< prev index next >

src/java.desktop/share/native/libfreetype/src/cff/cffparse.c

Print this page


   1 /***************************************************************************/
   2 /*                                                                         */
   3 /*  cffparse.c                                                             */
   4 /*                                                                         */
   5 /*    CFF token stream parser (body)                                       */
   6 /*                                                                         */
   7 /*  Copyright 1996-2018 by                                                 */
   8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
   9 /*                                                                         */
  10 /*  This file is part of the FreeType project, and may only be used,       */
  11 /*  modified, and distributed under the terms of the FreeType project      */
  12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13 /*  this file you indicate that you have read the license and              */
  14 /*  understand and accept it fully.                                        */
  15 /*                                                                         */
  16 /***************************************************************************/
  17 
  18 
  19 #include <ft2build.h>
  20 #include "cffparse.h"
  21 #include FT_INTERNAL_STREAM_H
  22 #include FT_INTERNAL_DEBUG_H
  23 #include FT_INTERNAL_CALC_H
  24 #include FT_INTERNAL_POSTSCRIPT_AUX_H

  25 
  26 #include "cfferrs.h"
  27 #include "cffpic.h"
  28 #include "cffload.h"
  29 
  30 
  31   /*************************************************************************/
  32   /*                                                                       */
  33   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  34   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  35   /* messages during execution.                                            */
  36   /*                                                                       */
  37 #undef  FT_COMPONENT
  38 #define FT_COMPONENT  trace_cffparse
  39 
  40 
  41   FT_LOCAL_DEF( FT_Error )
  42   cff_parser_init( CFF_Parser  parser,
  43                    FT_UInt     code,
  44                    void*       object,
  45                    FT_Library  library,
  46                    FT_UInt     stackSize,
  47                    FT_UShort   num_designs,
  48                    FT_UShort   num_axes )
  49   {
  50     FT_Memory  memory = library->memory;    /* for FT_NEW_ARRAY */
  51     FT_Error   error;                       /* for FT_NEW_ARRAY */
  52 
  53 
  54     FT_ZERO( parser );
  55 
  56 #if 0
  57     parser->top         = parser->stack;
  58 #endif


 588           return FT_DivFix( number, power_tens[integer_length - 5] );
 589         }
 590       }
 591       else
 592       {
 593         *scaling = 0;
 594         return (FT_Long)( (FT_ULong)number << 16 );
 595       }
 596     }
 597   }
 598 
 599 
 600   static FT_Error
 601   cff_parse_font_matrix( CFF_Parser  parser )
 602   {
 603     CFF_FontRecDict  dict   = (CFF_FontRecDict)parser->object;
 604     FT_Matrix*       matrix = &dict->font_matrix;
 605     FT_Vector*       offset = &dict->font_offset;
 606     FT_ULong*        upm    = &dict->units_per_em;
 607     FT_Byte**        data   = parser->stack;
 608     FT_Error         error  = FT_ERR( Stack_Underflow );
 609 
 610 
 611     if ( parser->top >= parser->stack + 6 )
 612     {
 613       FT_Fixed  values[6];
 614       FT_Long   scalings[6];
 615 
 616       FT_Long  min_scaling, max_scaling;
 617       int      i;
 618 
 619 
 620       error = FT_Err_Ok;
 621 
 622       dict->has_font_matrix = TRUE;
 623 
 624       /* We expect a well-formed font matrix, this is, the matrix elements */
 625       /* `xx' and `yy' are of approximately the same magnitude.  To avoid  */
 626       /* loss of precision, we use the magnitude of the largest matrix     */
 627       /* element to scale all other elements.  The scaling factor is then  */
 628       /* contained in the `units_per_em' value.                            */
 629 
 630       max_scaling = FT_LONG_MIN;
 631       min_scaling = FT_LONG_MAX;
 632 
 633       for ( i = 0; i < 6; i++ )
 634       {
 635         values[i] = cff_parse_fixed_dynamic( parser, data++, &scalings[i] );
 636         if ( values[i] )
 637         {
 638           if ( scalings[i] > max_scaling )
 639             max_scaling = scalings[i];
 640           if ( scalings[i] < min_scaling )
 641             min_scaling = scalings[i];
 642         }
 643       }
 644 
 645       if ( max_scaling < -9                  ||
 646            max_scaling > 0                   ||
 647            ( max_scaling - min_scaling ) < 0 ||
 648            ( max_scaling - min_scaling ) > 9 )
 649       {
 650         /* Return default matrix in case of unlikely values. */
 651 
 652         FT_TRACE1(( "cff_parse_font_matrix:"
 653                     " strange scaling values (minimum %d, maximum %d),\n"
 654                     "                      "
 655                     " using default matrix\n", min_scaling, max_scaling ));
 656 
 657         matrix->xx = 0x10000L;
 658         matrix->yx = 0;
 659         matrix->xy = 0;
 660         matrix->yy = 0x10000L;
 661         offset->x  = 0;
 662         offset->y  = 0;
 663         *upm       = 1;
 664 
 665         goto Exit;
 666       }
 667 
 668       for ( i = 0; i < 6; i++ )
 669       {
 670         FT_Fixed  value = values[i];
 671         FT_Long   divisor, half_divisor;
 672 
 673 
 674         if ( !value )
 675           continue;
 676 
 677         divisor      = power_tens[max_scaling - scalings[i]];
 678         half_divisor = divisor >> 1;
 679 
 680         if ( value < 0 )
 681         {
 682           if ( FT_LONG_MIN + half_divisor < value )
 683             values[i] = ( value - half_divisor ) / divisor;
 684           else
 685             values[i] = FT_LONG_MIN / divisor;


 692             values[i] = FT_LONG_MAX / divisor;
 693         }
 694       }
 695 
 696       matrix->xx = values[0];
 697       matrix->yx = values[1];
 698       matrix->xy = values[2];
 699       matrix->yy = values[3];
 700       offset->x  = values[4];
 701       offset->y  = values[5];
 702 
 703       *upm = (FT_ULong)power_tens[-max_scaling];
 704 
 705       FT_TRACE4(( " [%f %f %f %f %f %f]\n",
 706                   (double)matrix->xx / *upm / 65536,
 707                   (double)matrix->xy / *upm / 65536,
 708                   (double)matrix->yx / *upm / 65536,
 709                   (double)matrix->yy / *upm / 65536,
 710                   (double)offset->x  / *upm / 65536,
 711                   (double)offset->y  / *upm / 65536 ));






 712     }
 713 
 714   Exit:
 715     return error;















 716   }
 717 
 718 
 719   static FT_Error
 720   cff_parse_font_bbox( CFF_Parser  parser )
 721   {
 722     CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
 723     FT_BBox*         bbox = &dict->font_bbox;
 724     FT_Byte**        data = parser->stack;
 725     FT_Error         error;
 726 
 727 
 728     error = FT_ERR( Stack_Underflow );
 729 
 730     if ( parser->top >= parser->stack + 4 )
 731     {
 732       bbox->xMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
 733       bbox->yMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
 734       bbox->xMax = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
 735       bbox->yMax = FT_RoundFix( cff_parse_fixed( parser, data   ) );


 785       error = FT_Err_Ok;
 786     }
 787 
 788   Fail:
 789     return error;
 790   }
 791 
 792 
 793   /* The `MultipleMaster' operator comes before any  */
 794   /* top DICT operators that contain T2 charstrings. */
 795 
 796   static FT_Error
 797   cff_parse_multiple_master( CFF_Parser  parser )
 798   {
 799     CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
 800     FT_Error         error;
 801 
 802 
 803 #ifdef FT_DEBUG_LEVEL_TRACE
 804     /* beautify tracing message */
 805     if ( ft_trace_levels[FT_COMPONENT] < 4 )
 806       FT_TRACE1(( "Multiple Master CFFs not supported yet,"
 807                   " handling first master design only\n" ));
 808     else
 809       FT_TRACE1(( " (not supported yet,"
 810                   " handling first master design only)\n" ));
 811 #endif
 812 
 813     error = FT_ERR( Stack_Underflow );
 814 
 815     /* currently, we handle only the first argument */
 816     if ( parser->top >= parser->stack + 5 )
 817     {
 818       FT_Long  num_designs = cff_parse_num( parser, parser->stack );
 819 
 820 
 821       if ( num_designs > 16 || num_designs < 2 )
 822       {
 823         FT_ERROR(( "cff_parse_multiple_master:"
 824                    " Invalid number of designs\n" ));
 825         error = FT_THROW( Invalid_File_Format );


 986 
 987     FT_TRACE4(( " %d\n", dict->maxstack ));
 988 
 989   Exit:
 990     return error;
 991   }
 992 
 993 
 994 #define CFF_FIELD_NUM( code, name, id )             \
 995           CFF_FIELD( code, name, id, cff_kind_num )
 996 #define CFF_FIELD_FIXED( code, name, id )             \
 997           CFF_FIELD( code, name, id, cff_kind_fixed )
 998 #define CFF_FIELD_FIXED_1000( code, name, id )                 \
 999           CFF_FIELD( code, name, id, cff_kind_fixed_thousand )
1000 #define CFF_FIELD_STRING( code, name, id )             \
1001           CFF_FIELD( code, name, id, cff_kind_string )
1002 #define CFF_FIELD_BOOL( code, name, id )             \
1003           CFF_FIELD( code, name, id, cff_kind_bool )
1004 
1005 
1006 #ifndef FT_CONFIG_OPTION_PIC
1007 
1008 
1009 #undef  CFF_FIELD
1010 #undef  CFF_FIELD_DELTA
1011 
1012 
1013 #ifndef FT_DEBUG_LEVEL_TRACE
1014 
1015 
1016 #define CFF_FIELD_CALLBACK( code, name, id ) \
1017           {                                  \
1018             cff_kind_callback,               \
1019             code | CFFCODE,                  \
1020             0, 0,                            \
1021             cff_parse_ ## name,              \
1022             0, 0                             \
1023           },
1024 
1025 #define CFF_FIELD_BLEND( code, id ) \
1026           {                         \
1027             cff_kind_blend,         \
1028             code | CFFCODE,         \


1101             FT_FIELD_OFFSET( name ),           \
1102             FT_FIELD_SIZE_DELTA( name ),       \
1103             0,                                 \
1104             max,                               \
1105             FT_FIELD_OFFSET( num_ ## name ),   \
1106             id                                 \
1107           },
1108 
1109   static const CFF_Field_Handler  cff_field_handlers[] =
1110   {
1111 
1112 #include "cfftoken.h"
1113 
1114     { 0, 0, 0, 0, 0, 0, 0, 0 }
1115   };
1116 
1117 
1118 #endif /* FT_DEBUG_LEVEL_TRACE */
1119 
1120 
1121 #else /* FT_CONFIG_OPTION_PIC */
1122 
1123 
1124   void
1125   FT_Destroy_Class_cff_field_handlers( FT_Library          library,
1126                                        CFF_Field_Handler*  clazz )
1127   {
1128     FT_Memory  memory = library->memory;
1129 
1130 
1131     if ( clazz )
1132       FT_FREE( clazz );
1133   }
1134 
1135 
1136   FT_Error
1137   FT_Create_Class_cff_field_handlers( FT_Library           library,
1138                                       CFF_Field_Handler**  output_class )
1139   {
1140     CFF_Field_Handler*  clazz  = NULL;
1141     FT_Error            error;
1142     FT_Memory           memory = library->memory;
1143 
1144     int  i = 0;
1145 
1146 
1147 #undef CFF_FIELD
1148 #define CFF_FIELD( code, name, id, kind ) i++;
1149 #undef CFF_FIELD_DELTA
1150 #define CFF_FIELD_DELTA( code, name, max, id ) i++;
1151 #undef CFF_FIELD_CALLBACK
1152 #define CFF_FIELD_CALLBACK( code, name, id ) i++;
1153 #undef CFF_FIELD_BLEND
1154 #define CFF_FIELD_BLEND( code, id ) i++;
1155 
1156 #include "cfftoken.h"
1157 
1158     i++; /* { 0, 0, 0, 0, 0, 0, 0 } */
1159 
1160     if ( FT_ALLOC( clazz, sizeof ( CFF_Field_Handler ) * i ) )
1161       return error;
1162 
1163     i = 0;
1164 
1165 
1166 #ifndef FT_DEBUG_LEVEL_TRACE
1167 
1168 
1169 #undef CFF_FIELD_CALLBACK
1170 #define CFF_FIELD_CALLBACK( code_, name_, id_ )        \
1171           clazz[i].kind         = cff_kind_callback;   \
1172           clazz[i].code         = code_ | CFFCODE;     \
1173           clazz[i].offset       = 0;                   \
1174           clazz[i].size         = 0;                   \
1175           clazz[i].reader       = cff_parse_ ## name_; \
1176           clazz[i].array_max    = 0;                   \
1177           clazz[i].count_offset = 0;                   \
1178           i++;
1179 
1180 #undef  CFF_FIELD
1181 #define CFF_FIELD( code_, name_, id_, kind_ )               \
1182           clazz[i].kind         = kind_;                    \
1183           clazz[i].code         = code_ | CFFCODE;          \
1184           clazz[i].offset       = FT_FIELD_OFFSET( name_ ); \
1185           clazz[i].size         = FT_FIELD_SIZE( name_ );   \
1186           clazz[i].reader       = 0;                        \
1187           clazz[i].array_max    = 0;                        \
1188           clazz[i].count_offset = 0;                        \
1189           i++;                                              \
1190 
1191 #undef  CFF_FIELD_DELTA
1192 #define CFF_FIELD_DELTA( code_, name_, max_, id_ )                  \
1193           clazz[i].kind         = cff_kind_delta;                   \
1194           clazz[i].code         = code_ | CFFCODE;                  \
1195           clazz[i].offset       = FT_FIELD_OFFSET( name_ );         \
1196           clazz[i].size         = FT_FIELD_SIZE_DELTA( name_ );     \
1197           clazz[i].reader       = 0;                                \
1198           clazz[i].array_max    = max_;                             \
1199           clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
1200           i++;
1201 
1202 #undef  CFF_FIELD_BLEND
1203 #define CFF_FIELD_BLEND( code_, id_ )              \
1204           clazz[i].kind         = cff_kind_blend;  \
1205           clazz[i].code         = code_ | CFFCODE; \
1206           clazz[i].offset       = 0;               \
1207           clazz[i].size         = 0;               \
1208           clazz[i].reader       = cff_parse_blend; \
1209           clazz[i].array_max    = 0;               \
1210           clazz[i].count_offset = 0;               \
1211           i++;
1212 
1213 #include "cfftoken.h"
1214 
1215     clazz[i].kind         = 0;
1216     clazz[i].code         = 0;
1217     clazz[i].offset       = 0;
1218     clazz[i].size         = 0;
1219     clazz[i].reader       = 0;
1220     clazz[i].array_max    = 0;
1221     clazz[i].count_offset = 0;
1222 
1223 
1224 #else /* FT_DEBUG_LEVEL_TRACE */
1225 
1226 
1227 #undef CFF_FIELD_CALLBACK
1228 #define CFF_FIELD_CALLBACK( code_, name_, id_ )        \
1229           clazz[i].kind         = cff_kind_callback;   \
1230           clazz[i].code         = code_ | CFFCODE;     \
1231           clazz[i].offset       = 0;                   \
1232           clazz[i].size         = 0;                   \
1233           clazz[i].reader       = cff_parse_ ## name_; \
1234           clazz[i].array_max    = 0;                   \
1235           clazz[i].count_offset = 0;                   \
1236           clazz[i].id           = id_;                 \
1237           i++;
1238 
1239 #undef  CFF_FIELD
1240 #define CFF_FIELD( code_, name_, id_, kind_ )               \
1241           clazz[i].kind         = kind_;                    \
1242           clazz[i].code         = code_ | CFFCODE;          \
1243           clazz[i].offset       = FT_FIELD_OFFSET( name_ ); \
1244           clazz[i].size         = FT_FIELD_SIZE( name_ );   \
1245           clazz[i].reader       = 0;                        \
1246           clazz[i].array_max    = 0;                        \
1247           clazz[i].count_offset = 0;                        \
1248           clazz[i].id           = id_;                      \
1249           i++;                                              \
1250 
1251 #undef  CFF_FIELD_DELTA
1252 #define CFF_FIELD_DELTA( code_, name_, max_, id_ )                  \
1253           clazz[i].kind         = cff_kind_delta;                   \
1254           clazz[i].code         = code_ | CFFCODE;                  \
1255           clazz[i].offset       = FT_FIELD_OFFSET( name_ );         \
1256           clazz[i].size         = FT_FIELD_SIZE_DELTA( name_ );     \
1257           clazz[i].reader       = 0;                                \
1258           clazz[i].array_max    = max_;                             \
1259           clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
1260           clazz[i].id           = id_;                              \
1261           i++;
1262 
1263 #undef  CFF_FIELD_BLEND
1264 #define CFF_FIELD_BLEND( code_, id_ )              \
1265           clazz[i].kind         = cff_kind_blend;  \
1266           clazz[i].code         = code_ | CFFCODE; \
1267           clazz[i].offset       = 0;               \
1268           clazz[i].size         = 0;               \
1269           clazz[i].reader       = cff_parse_blend; \
1270           clazz[i].array_max    = 0;               \
1271           clazz[i].count_offset = 0;               \
1272           clazz[i].id           = id_;             \
1273           i++;
1274 
1275 #include "cfftoken.h"
1276 
1277     clazz[i].kind         = 0;
1278     clazz[i].code         = 0;
1279     clazz[i].offset       = 0;
1280     clazz[i].size         = 0;
1281     clazz[i].reader       = 0;
1282     clazz[i].array_max    = 0;
1283     clazz[i].count_offset = 0;
1284     clazz[i].id           = 0;
1285 
1286 
1287 #endif /* FT_DEBUG_LEVEL_TRACE */
1288 
1289 
1290     *output_class = clazz;
1291 
1292     return FT_Err_Ok;
1293   }
1294 
1295 
1296 #endif /* FT_CONFIG_OPTION_PIC */
1297 
1298 
1299   FT_LOCAL_DEF( FT_Error )
1300   cff_parser_run( CFF_Parser  parser,
1301                   FT_Byte*    start,
1302                   FT_Byte*    limit )
1303   {



1304 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1305     PSAux_Service  psaux;
1306 #endif
1307 
1308     FT_Byte*    p       = start;
1309     FT_Error    error   = FT_Err_Ok;
1310     FT_Library  library = parser->library;



1311 
1312     FT_UNUSED( library );
1313 


1314 
1315     parser->top    = parser->stack;
1316     parser->start  = start;
1317     parser->limit  = limit;
1318     parser->cursor = start;
1319 
1320     while ( p < limit )
1321     {
1322       FT_UInt  v = *p;
1323 

1324       /* Opcode 31 is legacy MM T2 operator, not a number.      */
1325       /* Opcode 255 is reserved and should not appear in fonts; */
1326       /* it is used internally for CFF2 blends.                 */
1327       if ( v >= 27 && v != 31 && v != 255 )
1328       {
1329         /* it's a number; we will push its position on the stack */
1330         if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
1331           goto Stack_Overflow;
1332 
1333         *parser->top++ = p;
1334 
1335         /* now, skip it */
1336         if ( v == 30 )
1337         {
1338           /* skip real number */
1339           p++;
1340           for (;;)
1341           {
1342             /* An unterminated floating point number at the */
1343             /* end of a dictionary is invalid but harmless. */


1353           }
1354         }
1355         else if ( v == 28 )
1356           p += 2;
1357         else if ( v == 29 )
1358           p += 4;
1359         else if ( v > 246 )
1360           p += 1;
1361       }
1362 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1363       else if ( v == 31 )
1364       {
1365         /* a Type 2 charstring */
1366 
1367         CFF_Decoder  decoder;
1368         CFF_FontRec  cff_rec;
1369         FT_Byte*     charstring_base;
1370         FT_ULong     charstring_len;
1371 
1372         FT_Fixed*  stack;

1373         FT_Byte*   q;
1374 
1375 
1376         charstring_base = ++p;
1377 
1378         /* search `endchar' operator */
1379         for (;;)
1380         {
1381           if ( p >= limit )
1382             goto Exit;
1383           if ( *p == 14 )
1384             break;
1385           p++;
1386         }
1387 
1388         charstring_len = (FT_ULong)( p - charstring_base ) + 1;
1389 
1390         /* construct CFF_Decoder object */
1391         FT_ZERO( &decoder );
1392         FT_ZERO( &cff_rec );
1393 
1394         cff_rec.top_font.font_dict.num_designs = parser->num_designs;
1395         cff_rec.top_font.font_dict.num_axes    = parser->num_axes;
1396         decoder.cff                            = &cff_rec;
1397 
1398         psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" );
1399         if ( !psaux )
1400         {
1401           FT_ERROR(( "cff_parser_run: cannot access `psaux' module\n" ));
1402           error = FT_THROW( Missing_Module );
1403           goto Exit;
1404         }
1405 
1406         error = psaux->cff_decoder_funcs->parse_charstrings_old(
1407                   &decoder, charstring_base, charstring_len, 1 );


1408 
1409         /* Now copy the stack data in the temporary decoder object,    */
1410         /* converting it back to charstring number representations     */
1411         /* (this is ugly, I know).                                     */
1412         /*                                                             */
1413         /* We overwrite the original top DICT charstring under the     */
1414         /* assumption that the charstring representation of the result */
1415         /* of `cff_decoder_parse_charstrings' is shorter, which should */
1416         /* be always true.                                             */
1417 
1418         q     = charstring_base - 1;















1419         stack = decoder.stack;
1420 
1421         while ( stack < decoder.top )
1422         {
1423           FT_ULong  num;
1424           FT_Bool   neg;
1425 
1426 
1427           if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
1428             goto Stack_Overflow;
1429 
1430           *parser->top++ = q;
1431 
1432           if ( *stack < 0 )
1433           {
1434             num = (FT_ULong)-*stack;
1435             neg = 1;
1436           }
1437           else
1438           {
1439             num = (FT_ULong)*stack;
1440             neg = 0;
1441           }
1442 
1443           if ( num & 0xFFFFU )
1444           {
1445             if ( neg )
1446               num = (FT_ULong)-num;
1447 
1448             *q++ = 255;
1449             *q++ = ( num & 0xFF000000U ) >> 24;
1450             *q++ = ( num & 0x00FF0000U ) >> 16;
1451             *q++ = ( num & 0x0000FF00U ) >>  8;
1452             *q++ =   num & 0x000000FFU;
1453           }
1454           else


1506 
1507 
1508         if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
1509           goto Stack_Overflow;
1510 
1511         num_args     = (FT_UInt)( parser->top - parser->stack );
1512         *parser->top = p;
1513         code         = v;
1514 
1515         if ( v == 12 )
1516         {
1517           /* two byte operator */
1518           p++;
1519           if ( p >= limit )
1520             goto Syntax_Error;
1521 
1522           code = 0x100 | p[0];
1523         }
1524         code = code | parser->object_code;
1525 
1526         for ( field = CFF_FIELD_HANDLERS_GET; field->kind; field++ )
1527         {
1528           if ( field->code == (FT_Int)code )
1529           {
1530             /* we found our field's handler; read it */
1531             FT_Long   val;
1532             FT_Byte*  q = (FT_Byte*)parser->object + field->offset;
1533 
1534 
1535 #ifdef FT_DEBUG_LEVEL_TRACE
1536             FT_TRACE4(( "  %s", field->id ));
1537 #endif
1538 
1539             /* check that we have enough arguments -- except for */
1540             /* delta encoded arrays, which can be empty          */
1541             if ( field->kind != cff_kind_delta && num_args < 1 )
1542               goto Stack_Underflow;
1543 
1544             switch ( field->kind )
1545             {
1546             case cff_kind_bool:


1655             default:  /* callback or blend */
1656               error = field->reader( parser );
1657               if ( error )
1658                 goto Exit;
1659             }
1660             goto Found;
1661           }
1662         }
1663 
1664         /* this is an unknown operator, or it is unsupported; */
1665         /* we will ignore it for now.                         */
1666 
1667       Found:
1668         /* clear stack */
1669         /* TODO: could clear blend stack here,       */
1670         /*       but we don't have access to subFont */
1671         if ( field->kind != cff_kind_blend )
1672           parser->top = parser->stack;
1673       }
1674       p++;
1675     }
1676 
1677   Exit:



1678     return error;






1679 
1680   Stack_Overflow:
1681     error = FT_THROW( Invalid_Argument );
1682     goto Exit;
1683 
1684   Stack_Underflow:
1685     error = FT_THROW( Invalid_Argument );
1686     goto Exit;
1687 
1688   Syntax_Error:
1689     error = FT_THROW( Invalid_Argument );
1690     goto Exit;
1691   }
1692 
1693 
1694 /* END */
   1 /****************************************************************************
   2  *
   3  * cffparse.c
   4  *
   5  *   CFF token stream parser (body)
   6  *
   7  * Copyright (C) 1996-2019 by
   8  * David Turner, Robert Wilhelm, and Werner Lemberg.
   9  *
  10  * This file is part of the FreeType project, and may only be used,
  11  * modified, and distributed under the terms of the FreeType project
  12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
  13  * this file you indicate that you have read the license and
  14  * understand and accept it fully.
  15  *
  16  */
  17 
  18 
  19 #include <ft2build.h>
  20 #include "cffparse.h"
  21 #include FT_INTERNAL_STREAM_H
  22 #include FT_INTERNAL_DEBUG_H
  23 #include FT_INTERNAL_CALC_H
  24 #include FT_INTERNAL_POSTSCRIPT_AUX_H
  25 #include FT_LIST_H
  26 
  27 #include "cfferrs.h"

  28 #include "cffload.h"
  29 
  30 
  31   /**************************************************************************
  32    *
  33    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
  34    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  35    * messages during execution.
  36    */
  37 #undef  FT_COMPONENT
  38 #define FT_COMPONENT  cffparse
  39 
  40 
  41   FT_LOCAL_DEF( FT_Error )
  42   cff_parser_init( CFF_Parser  parser,
  43                    FT_UInt     code,
  44                    void*       object,
  45                    FT_Library  library,
  46                    FT_UInt     stackSize,
  47                    FT_UShort   num_designs,
  48                    FT_UShort   num_axes )
  49   {
  50     FT_Memory  memory = library->memory;    /* for FT_NEW_ARRAY */
  51     FT_Error   error;                       /* for FT_NEW_ARRAY */
  52 
  53 
  54     FT_ZERO( parser );
  55 
  56 #if 0
  57     parser->top         = parser->stack;
  58 #endif


 588           return FT_DivFix( number, power_tens[integer_length - 5] );
 589         }
 590       }
 591       else
 592       {
 593         *scaling = 0;
 594         return (FT_Long)( (FT_ULong)number << 16 );
 595       }
 596     }
 597   }
 598 
 599 
 600   static FT_Error
 601   cff_parse_font_matrix( CFF_Parser  parser )
 602   {
 603     CFF_FontRecDict  dict   = (CFF_FontRecDict)parser->object;
 604     FT_Matrix*       matrix = &dict->font_matrix;
 605     FT_Vector*       offset = &dict->font_offset;
 606     FT_ULong*        upm    = &dict->units_per_em;
 607     FT_Byte**        data   = parser->stack;

 608 
 609 
 610     if ( parser->top >= parser->stack + 6 )
 611     {
 612       FT_Fixed  values[6];
 613       FT_Long   scalings[6];
 614 
 615       FT_Long  min_scaling, max_scaling;
 616       int      i;
 617 
 618 


 619       dict->has_font_matrix = TRUE;
 620 
 621       /* We expect a well-formed font matrix, this is, the matrix elements */
 622       /* `xx' and `yy' are of approximately the same magnitude.  To avoid  */
 623       /* loss of precision, we use the magnitude of the largest matrix     */
 624       /* element to scale all other elements.  The scaling factor is then  */
 625       /* contained in the `units_per_em' value.                            */
 626 
 627       max_scaling = FT_LONG_MIN;
 628       min_scaling = FT_LONG_MAX;
 629 
 630       for ( i = 0; i < 6; i++ )
 631       {
 632         values[i] = cff_parse_fixed_dynamic( parser, data++, &scalings[i] );
 633         if ( values[i] )
 634         {
 635           if ( scalings[i] > max_scaling )
 636             max_scaling = scalings[i];
 637           if ( scalings[i] < min_scaling )
 638             min_scaling = scalings[i];
 639         }
 640       }
 641 
 642       if ( max_scaling < -9                  ||
 643            max_scaling > 0                   ||
 644            ( max_scaling - min_scaling ) < 0 ||
 645            ( max_scaling - min_scaling ) > 9 )
 646       {


 647         FT_TRACE1(( "cff_parse_font_matrix:"
 648                     " strange scaling values (minimum %d, maximum %d),\n"
 649                     "                      "
 650                     " using default matrix\n", min_scaling, max_scaling ));
 651         goto Unlikely;









 652       }
 653 
 654       for ( i = 0; i < 6; i++ )
 655       {
 656         FT_Fixed  value = values[i];
 657         FT_Long   divisor, half_divisor;
 658 
 659 
 660         if ( !value )
 661           continue;
 662 
 663         divisor      = power_tens[max_scaling - scalings[i]];
 664         half_divisor = divisor >> 1;
 665 
 666         if ( value < 0 )
 667         {
 668           if ( FT_LONG_MIN + half_divisor < value )
 669             values[i] = ( value - half_divisor ) / divisor;
 670           else
 671             values[i] = FT_LONG_MIN / divisor;


 678             values[i] = FT_LONG_MAX / divisor;
 679         }
 680       }
 681 
 682       matrix->xx = values[0];
 683       matrix->yx = values[1];
 684       matrix->xy = values[2];
 685       matrix->yy = values[3];
 686       offset->x  = values[4];
 687       offset->y  = values[5];
 688 
 689       *upm = (FT_ULong)power_tens[-max_scaling];
 690 
 691       FT_TRACE4(( " [%f %f %f %f %f %f]\n",
 692                   (double)matrix->xx / *upm / 65536,
 693                   (double)matrix->xy / *upm / 65536,
 694                   (double)matrix->yx / *upm / 65536,
 695                   (double)matrix->yy / *upm / 65536,
 696                   (double)offset->x  / *upm / 65536,
 697                   (double)offset->y  / *upm / 65536 ));
 698 
 699       if ( !FT_Matrix_Check( matrix ) )
 700       {
 701         FT_TRACE1(( "cff_parse_font_matrix:"
 702                     " degenerate values, using default matrix\n" ));
 703         goto Unlikely;
 704       }
 705 
 706       return FT_Err_Ok;
 707     }
 708     else
 709       return FT_THROW( Stack_Underflow );
 710 
 711   Unlikely:
 712     /* Return default matrix in case of unlikely values. */
 713 
 714     matrix->xx = 0x10000L;
 715     matrix->yx = 0;
 716     matrix->xy = 0;
 717     matrix->yy = 0x10000L;
 718     offset->x  = 0;
 719     offset->y  = 0;
 720     *upm       = 1;
 721 
 722     return FT_Err_Ok;
 723   }
 724 
 725 
 726   static FT_Error
 727   cff_parse_font_bbox( CFF_Parser  parser )
 728   {
 729     CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
 730     FT_BBox*         bbox = &dict->font_bbox;
 731     FT_Byte**        data = parser->stack;
 732     FT_Error         error;
 733 
 734 
 735     error = FT_ERR( Stack_Underflow );
 736 
 737     if ( parser->top >= parser->stack + 4 )
 738     {
 739       bbox->xMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
 740       bbox->yMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
 741       bbox->xMax = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
 742       bbox->yMax = FT_RoundFix( cff_parse_fixed( parser, data   ) );


 792       error = FT_Err_Ok;
 793     }
 794 
 795   Fail:
 796     return error;
 797   }
 798 
 799 
 800   /* The `MultipleMaster' operator comes before any  */
 801   /* top DICT operators that contain T2 charstrings. */
 802 
 803   static FT_Error
 804   cff_parse_multiple_master( CFF_Parser  parser )
 805   {
 806     CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
 807     FT_Error         error;
 808 
 809 
 810 #ifdef FT_DEBUG_LEVEL_TRACE
 811     /* beautify tracing message */
 812     if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] < 4 )
 813       FT_TRACE1(( "Multiple Master CFFs not supported yet,"
 814                   " handling first master design only\n" ));
 815     else
 816       FT_TRACE1(( " (not supported yet,"
 817                   " handling first master design only)\n" ));
 818 #endif
 819 
 820     error = FT_ERR( Stack_Underflow );
 821 
 822     /* currently, we handle only the first argument */
 823     if ( parser->top >= parser->stack + 5 )
 824     {
 825       FT_Long  num_designs = cff_parse_num( parser, parser->stack );
 826 
 827 
 828       if ( num_designs > 16 || num_designs < 2 )
 829       {
 830         FT_ERROR(( "cff_parse_multiple_master:"
 831                    " Invalid number of designs\n" ));
 832         error = FT_THROW( Invalid_File_Format );


 993 
 994     FT_TRACE4(( " %d\n", dict->maxstack ));
 995 
 996   Exit:
 997     return error;
 998   }
 999 
1000 
1001 #define CFF_FIELD_NUM( code, name, id )             \
1002           CFF_FIELD( code, name, id, cff_kind_num )
1003 #define CFF_FIELD_FIXED( code, name, id )             \
1004           CFF_FIELD( code, name, id, cff_kind_fixed )
1005 #define CFF_FIELD_FIXED_1000( code, name, id )                 \
1006           CFF_FIELD( code, name, id, cff_kind_fixed_thousand )
1007 #define CFF_FIELD_STRING( code, name, id )             \
1008           CFF_FIELD( code, name, id, cff_kind_string )
1009 #define CFF_FIELD_BOOL( code, name, id )             \
1010           CFF_FIELD( code, name, id, cff_kind_bool )
1011 
1012 



1013 #undef  CFF_FIELD
1014 #undef  CFF_FIELD_DELTA
1015 
1016 
1017 #ifndef FT_DEBUG_LEVEL_TRACE
1018 
1019 
1020 #define CFF_FIELD_CALLBACK( code, name, id ) \
1021           {                                  \
1022             cff_kind_callback,               \
1023             code | CFFCODE,                  \
1024             0, 0,                            \
1025             cff_parse_ ## name,              \
1026             0, 0                             \
1027           },
1028 
1029 #define CFF_FIELD_BLEND( code, id ) \
1030           {                         \
1031             cff_kind_blend,         \
1032             code | CFFCODE,         \


1105             FT_FIELD_OFFSET( name ),           \
1106             FT_FIELD_SIZE_DELTA( name ),       \
1107             0,                                 \
1108             max,                               \
1109             FT_FIELD_OFFSET( num_ ## name ),   \
1110             id                                 \
1111           },
1112 
1113   static const CFF_Field_Handler  cff_field_handlers[] =
1114   {
1115 
1116 #include "cfftoken.h"
1117 
1118     { 0, 0, 0, 0, 0, 0, 0, 0 }
1119   };
1120 
1121 
1122 #endif /* FT_DEBUG_LEVEL_TRACE */
1123 
1124 
1125 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1126   static void
1127   destruct_t2s_item( FT_Memory  memory,
1128                      void*      data,
1129                      void*      user )

1130   {
1131     FT_UNUSED( user );
1132     memory->free( memory, data );



1133   }
1134 #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */


































































































































































1135 
1136 
1137   FT_LOCAL_DEF( FT_Error )
1138   cff_parser_run( CFF_Parser  parser,
1139                   FT_Byte*    start,
1140                   FT_Byte*    limit )
1141   {
1142     FT_Byte*  p     = start;
1143     FT_Error  error = FT_Err_Ok;
1144 
1145 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1146     PSAux_Service  psaux;

1147 


1148     FT_Library  library = parser->library;
1149     FT_Memory   memory  = library->memory;
1150 
1151     FT_ListRec  t2s;
1152 

1153 
1154     FT_ZERO( &t2s );
1155 #endif
1156 
1157     parser->top    = parser->stack;
1158     parser->start  = start;
1159     parser->limit  = limit;
1160     parser->cursor = start;
1161 
1162     while ( p < limit )
1163     {
1164       FT_UInt  v = *p;
1165 
1166 
1167       /* Opcode 31 is legacy MM T2 operator, not a number.      */
1168       /* Opcode 255 is reserved and should not appear in fonts; */
1169       /* it is used internally for CFF2 blends.                 */
1170       if ( v >= 27 && v != 31 && v != 255 )
1171       {
1172         /* it's a number; we will push its position on the stack */
1173         if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
1174           goto Stack_Overflow;
1175 
1176         *parser->top++ = p;
1177 
1178         /* now, skip it */
1179         if ( v == 30 )
1180         {
1181           /* skip real number */
1182           p++;
1183           for (;;)
1184           {
1185             /* An unterminated floating point number at the */
1186             /* end of a dictionary is invalid but harmless. */


1196           }
1197         }
1198         else if ( v == 28 )
1199           p += 2;
1200         else if ( v == 29 )
1201           p += 4;
1202         else if ( v > 246 )
1203           p += 1;
1204       }
1205 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1206       else if ( v == 31 )
1207       {
1208         /* a Type 2 charstring */
1209 
1210         CFF_Decoder  decoder;
1211         CFF_FontRec  cff_rec;
1212         FT_Byte*     charstring_base;
1213         FT_ULong     charstring_len;
1214 
1215         FT_Fixed*    stack;
1216         FT_ListNode  node;
1217         FT_Byte*     q;
1218 
1219 
1220         charstring_base = ++p;
1221 
1222         /* search `endchar' operator */
1223         for (;;)
1224         {
1225           if ( p >= limit )
1226             goto Exit;
1227           if ( *p == 14 )
1228             break;
1229           p++;
1230         }
1231 
1232         charstring_len = (FT_ULong)( p - charstring_base ) + 1;
1233 
1234         /* construct CFF_Decoder object */
1235         FT_ZERO( &decoder );
1236         FT_ZERO( &cff_rec );
1237 
1238         cff_rec.top_font.font_dict.num_designs = parser->num_designs;
1239         cff_rec.top_font.font_dict.num_axes    = parser->num_axes;
1240         decoder.cff                            = &cff_rec;
1241 
1242         psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" );
1243         if ( !psaux )
1244         {
1245           FT_ERROR(( "cff_parser_run: cannot access `psaux' module\n" ));
1246           error = FT_THROW( Missing_Module );
1247           goto Exit;
1248         }
1249 
1250         error = psaux->cff_decoder_funcs->parse_charstrings_old(
1251                   &decoder, charstring_base, charstring_len, 1 );
1252         if ( error )
1253           goto Exit;
1254 
1255         /* Now copy the stack data in the temporary decoder object,    */
1256         /* converting it back to charstring number representations     */
1257         /* (this is ugly, I know).                                     */





1258 
1259         node = (FT_ListNode)memory->alloc( memory,
1260                                            sizeof ( FT_ListNodeRec ) );
1261         if ( !node )
1262           goto Out_Of_Memory_Error;
1263 
1264         /* `5' is the conservative upper bound of required bytes per stack */
1265         /* element.                                                        */
1266         q = (FT_Byte*)memory->alloc( memory,
1267                                      5 * ( decoder.top - decoder.stack ) );
1268         if ( !q )
1269           goto Out_Of_Memory_Error;
1270 
1271         node->data = q;
1272 
1273         FT_List_Add( &t2s, node );
1274 
1275         stack = decoder.stack;
1276 
1277         while ( stack < decoder.top )
1278         {
1279           FT_ULong  num;
1280           FT_Bool   neg;
1281 
1282 
1283           if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
1284             goto Stack_Overflow;
1285 
1286           *parser->top++ = q;
1287 
1288           if ( *stack < 0 )
1289           {
1290             num = (FT_ULong)NEG_LONG( *stack );
1291             neg = 1;
1292           }
1293           else
1294           {
1295             num = (FT_ULong)*stack;
1296             neg = 0;
1297           }
1298 
1299           if ( num & 0xFFFFU )
1300           {
1301             if ( neg )
1302               num = (FT_ULong)-num;
1303 
1304             *q++ = 255;
1305             *q++ = ( num & 0xFF000000U ) >> 24;
1306             *q++ = ( num & 0x00FF0000U ) >> 16;
1307             *q++ = ( num & 0x0000FF00U ) >>  8;
1308             *q++ =   num & 0x000000FFU;
1309           }
1310           else


1362 
1363 
1364         if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
1365           goto Stack_Overflow;
1366 
1367         num_args     = (FT_UInt)( parser->top - parser->stack );
1368         *parser->top = p;
1369         code         = v;
1370 
1371         if ( v == 12 )
1372         {
1373           /* two byte operator */
1374           p++;
1375           if ( p >= limit )
1376             goto Syntax_Error;
1377 
1378           code = 0x100 | p[0];
1379         }
1380         code = code | parser->object_code;
1381 
1382         for ( field = cff_field_handlers; field->kind; field++ )
1383         {
1384           if ( field->code == (FT_Int)code )
1385           {
1386             /* we found our field's handler; read it */
1387             FT_Long   val;
1388             FT_Byte*  q = (FT_Byte*)parser->object + field->offset;
1389 
1390 
1391 #ifdef FT_DEBUG_LEVEL_TRACE
1392             FT_TRACE4(( "  %s", field->id ));
1393 #endif
1394 
1395             /* check that we have enough arguments -- except for */
1396             /* delta encoded arrays, which can be empty          */
1397             if ( field->kind != cff_kind_delta && num_args < 1 )
1398               goto Stack_Underflow;
1399 
1400             switch ( field->kind )
1401             {
1402             case cff_kind_bool:


1511             default:  /* callback or blend */
1512               error = field->reader( parser );
1513               if ( error )
1514                 goto Exit;
1515             }
1516             goto Found;
1517           }
1518         }
1519 
1520         /* this is an unknown operator, or it is unsupported; */
1521         /* we will ignore it for now.                         */
1522 
1523       Found:
1524         /* clear stack */
1525         /* TODO: could clear blend stack here,       */
1526         /*       but we don't have access to subFont */
1527         if ( field->kind != cff_kind_blend )
1528           parser->top = parser->stack;
1529       }
1530       p++;
1531     } /* while ( p < limit ) */
1532 
1533   Exit:
1534 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1535     FT_List_Finalize( &t2s, destruct_t2s_item, memory, NULL );
1536 #endif
1537     return error;
1538 
1539 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1540   Out_Of_Memory_Error:
1541     error = FT_THROW( Out_Of_Memory );
1542     goto Exit;
1543 #endif
1544 
1545   Stack_Overflow:
1546     error = FT_THROW( Invalid_Argument );
1547     goto Exit;
1548 
1549   Stack_Underflow:
1550     error = FT_THROW( Invalid_Argument );
1551     goto Exit;
1552 
1553   Syntax_Error:
1554     error = FT_THROW( Invalid_Argument );
1555     goto Exit;
1556   }
1557 
1558 
1559 /* END */
< prev index next >