Home | History | Annotate | Download | only in cff
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  cf2intrp.c                                                             */
      4 /*                                                                         */
      5 /*    Adobe's CFF Interpreter (body).                                      */
      6 /*                                                                         */
      7 /*  Copyright 2007-2014 Adobe Systems Incorporated.                        */
      8 /*                                                                         */
      9 /*  This software, and all works of authorship, whether in source or       */
     10 /*  object code form as indicated by the copyright notice(s) included      */
     11 /*  herein (collectively, the "Work") is made available, and may only be   */
     12 /*  used, modified, and distributed under the FreeType Project License,    */
     13 /*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
     14 /*  FreeType Project License, each contributor to the Work hereby grants   */
     15 /*  to any individual or legal entity exercising permissions granted by    */
     16 /*  the FreeType Project License and this section (hereafter, "You" or     */
     17 /*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
     18 /*  royalty-free, irrevocable (except as stated in this section) patent    */
     19 /*  license to make, have made, use, offer to sell, sell, import, and      */
     20 /*  otherwise transfer the Work, where such license applies only to those  */
     21 /*  patent claims licensable by such contributor that are necessarily      */
     22 /*  infringed by their contribution(s) alone or by combination of their    */
     23 /*  contribution(s) with the Work to which such contribution(s) was        */
     24 /*  submitted.  If You institute patent litigation against any entity      */
     25 /*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
     26 /*  the Work or a contribution incorporated within the Work constitutes    */
     27 /*  direct or contributory patent infringement, then any patent licenses   */
     28 /*  granted to You under this License for that Work shall terminate as of  */
     29 /*  the date such litigation is filed.                                     */
     30 /*                                                                         */
     31 /*  By using, modifying, or distributing the Work you indicate that you    */
     32 /*  have read and understood the terms and conditions of the               */
     33 /*  FreeType Project License as well as those provided in this section,    */
     34 /*  and you accept them fully.                                             */
     35 /*                                                                         */
     36 /***************************************************************************/
     37 
     38 
     39 #include "cf2ft.h"
     40 #include FT_INTERNAL_DEBUG_H
     41 
     42 #include "cf2glue.h"
     43 #include "cf2font.h"
     44 #include "cf2stack.h"
     45 #include "cf2hints.h"
     46 #include "cf2intrp.h"
     47 
     48 #include "cf2error.h"
     49 
     50 #include "cffload.h"
     51 
     52 
     53   /*************************************************************************/
     54   /*                                                                       */
     55   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     56   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     57   /* messages during execution.                                            */
     58   /*                                                                       */
     59 #undef  FT_COMPONENT
     60 #define FT_COMPONENT  trace_cf2interp
     61 
     62 
     63   /* some operators are not implemented yet */
     64 #define CF2_FIXME  FT_TRACE4(( "cf2_interpT2CharString:"            \
     65                                " operator not implemented yet\n" ))
     66 
     67 
     68 
     69   FT_LOCAL_DEF( void )
     70   cf2_hintmask_init( CF2_HintMask  hintmask,
     71                      FT_Error*     error )
     72   {
     73     FT_ZERO( hintmask );
     74 
     75     hintmask->error = error;
     76   }
     77 
     78 
     79   FT_LOCAL_DEF( FT_Bool )
     80   cf2_hintmask_isValid( const CF2_HintMask  hintmask )
     81   {
     82     return hintmask->isValid;
     83   }
     84 
     85 
     86   FT_LOCAL_DEF( FT_Bool )
     87   cf2_hintmask_isNew( const CF2_HintMask  hintmask )
     88   {
     89     return hintmask->isNew;
     90   }
     91 
     92 
     93   FT_LOCAL_DEF( void )
     94   cf2_hintmask_setNew( CF2_HintMask  hintmask,
     95                        FT_Bool       val )
     96   {
     97     hintmask->isNew = val;
     98   }
     99 
    100 
    101   /* clients call `getMaskPtr' in order to iterate */
    102   /* through hint mask                             */
    103 
    104   FT_LOCAL_DEF( FT_Byte* )
    105   cf2_hintmask_getMaskPtr( CF2_HintMask  hintmask )
    106   {
    107     return hintmask->mask;
    108   }
    109 
    110 
    111   static size_t
    112   cf2_hintmask_setCounts( CF2_HintMask  hintmask,
    113                           size_t        bitCount )
    114   {
    115     if ( bitCount > CF2_MAX_HINTS )
    116     {
    117       /* total of h and v stems must be <= 96 */
    118       CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
    119       return 0;
    120     }
    121 
    122     hintmask->bitCount  = bitCount;
    123     hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
    124 
    125     hintmask->isValid = TRUE;
    126     hintmask->isNew   = TRUE;
    127 
    128     return bitCount;
    129   }
    130 
    131 
    132   /* consume the hintmask bytes from the charstring, advancing the src */
    133   /* pointer                                                           */
    134   static void
    135   cf2_hintmask_read( CF2_HintMask  hintmask,
    136                      CF2_Buffer    charstring,
    137                      size_t        bitCount )
    138   {
    139     size_t  i;
    140 
    141 #ifndef CF2_NDEBUG
    142     /* these are the bits in the final mask byte that should be zero  */
    143     /* Note: this variable is only used in an assert expression below */
    144     /* and then only if CF2_NDEBUG is not defined                     */
    145     CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
    146 #endif
    147 
    148 
    149     /* initialize counts and isValid */
    150     if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
    151       return;
    152 
    153     FT_ASSERT( hintmask->byteCount > 0 );
    154 
    155     FT_TRACE4(( " (maskbytes:" ));
    156 
    157     /* set mask and advance interpreter's charstring pointer */
    158     for ( i = 0; i < hintmask->byteCount; i++ )
    159     {
    160       hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
    161       FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
    162     }
    163 
    164     FT_TRACE4(( ")\n" ));
    165 
    166     /* assert any unused bits in last byte are zero unless there's a prior */
    167     /* error                                                               */
    168     /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1      */
    169 #ifndef CF2_NDEBUG
    170     FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
    171                *hintmask->error                                        );
    172 #endif
    173   }
    174 
    175 
    176   FT_LOCAL_DEF( void )
    177   cf2_hintmask_setAll( CF2_HintMask  hintmask,
    178                        size_t        bitCount )
    179   {
    180     size_t    i;
    181     CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
    182 
    183 
    184     /* initialize counts and isValid */
    185     if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
    186       return;
    187 
    188     FT_ASSERT( hintmask->byteCount > 0 );
    189     FT_ASSERT( hintmask->byteCount <=
    190                  sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
    191 
    192     /* set mask to all ones */
    193     for ( i = 0; i < hintmask->byteCount; i++ )
    194       hintmask->mask[i] = 0xFF;
    195 
    196     /* clear unused bits                                              */
    197     /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
    198     hintmask->mask[hintmask->byteCount - 1] &= ~mask;
    199   }
    200 
    201 
    202   /* Type2 charstring opcodes */
    203   enum
    204   {
    205     cf2_cmdRESERVED_0,   /* 0 */
    206     cf2_cmdHSTEM,        /* 1 */
    207     cf2_cmdRESERVED_2,   /* 2 */
    208     cf2_cmdVSTEM,        /* 3 */
    209     cf2_cmdVMOVETO,      /* 4 */
    210     cf2_cmdRLINETO,      /* 5 */
    211     cf2_cmdHLINETO,      /* 6 */
    212     cf2_cmdVLINETO,      /* 7 */
    213     cf2_cmdRRCURVETO,    /* 8 */
    214     cf2_cmdRESERVED_9,   /* 9 */
    215     cf2_cmdCALLSUBR,     /* 10 */
    216     cf2_cmdRETURN,       /* 11 */
    217     cf2_cmdESC,          /* 12 */
    218     cf2_cmdRESERVED_13,  /* 13 */
    219     cf2_cmdENDCHAR,      /* 14 */
    220     cf2_cmdVSINDEX,      /* 15 */
    221     cf2_cmdBLEND,        /* 16 */
    222     cf2_cmdRESERVED_17,  /* 17 */
    223     cf2_cmdHSTEMHM,      /* 18 */
    224     cf2_cmdHINTMASK,     /* 19 */
    225     cf2_cmdCNTRMASK,     /* 20 */
    226     cf2_cmdRMOVETO,      /* 21 */
    227     cf2_cmdHMOVETO,      /* 22 */
    228     cf2_cmdVSTEMHM,      /* 23 */
    229     cf2_cmdRCURVELINE,   /* 24 */
    230     cf2_cmdRLINECURVE,   /* 25 */
    231     cf2_cmdVVCURVETO,    /* 26 */
    232     cf2_cmdHHCURVETO,    /* 27 */
    233     cf2_cmdEXTENDEDNMBR, /* 28 */
    234     cf2_cmdCALLGSUBR,    /* 29 */
    235     cf2_cmdVHCURVETO,    /* 30 */
    236     cf2_cmdHVCURVETO     /* 31 */
    237   };
    238 
    239   enum
    240   {
    241     cf2_escDOTSECTION,   /* 0 */
    242     cf2_escRESERVED_1,   /* 1 */
    243     cf2_escRESERVED_2,   /* 2 */
    244     cf2_escAND,          /* 3 */
    245     cf2_escOR,           /* 4 */
    246     cf2_escNOT,          /* 5 */
    247     cf2_escRESERVED_6,   /* 6 */
    248     cf2_escRESERVED_7,   /* 7 */
    249     cf2_escRESERVED_8,   /* 8 */
    250     cf2_escABS,          /* 9 */
    251     cf2_escADD,          /* 10     like otherADD */
    252     cf2_escSUB,          /* 11     like otherSUB */
    253     cf2_escDIV,          /* 12 */
    254     cf2_escRESERVED_13,  /* 13 */
    255     cf2_escNEG,          /* 14 */
    256     cf2_escEQ,           /* 15 */
    257     cf2_escRESERVED_16,  /* 16 */
    258     cf2_escRESERVED_17,  /* 17 */
    259     cf2_escDROP,         /* 18 */
    260     cf2_escRESERVED_19,  /* 19 */
    261     cf2_escPUT,          /* 20     like otherPUT    */
    262     cf2_escGET,          /* 21     like otherGET    */
    263     cf2_escIFELSE,       /* 22     like otherIFELSE */
    264     cf2_escRANDOM,       /* 23     like otherRANDOM */
    265     cf2_escMUL,          /* 24     like otherMUL    */
    266     cf2_escRESERVED_25,  /* 25 */
    267     cf2_escSQRT,         /* 26 */
    268     cf2_escDUP,          /* 27     like otherDUP    */
    269     cf2_escEXCH,         /* 28     like otherEXCH   */
    270     cf2_escINDEX,        /* 29 */
    271     cf2_escROLL,         /* 30 */
    272     cf2_escRESERVED_31,  /* 31 */
    273     cf2_escRESERVED_32,  /* 32 */
    274     cf2_escRESERVED_33,  /* 33 */
    275     cf2_escHFLEX,        /* 34 */
    276     cf2_escFLEX,         /* 35 */
    277     cf2_escHFLEX1,       /* 36 */
    278     cf2_escFLEX1,        /* 37 */
    279     cf2_escRESERVED_38   /* 38     & all higher     */
    280   };
    281 
    282 
    283   /* `stemHintArray' does not change once we start drawing the outline. */
    284   static void
    285   cf2_doStems( const CF2_Font  font,
    286                CF2_Stack       opStack,
    287                CF2_ArrStack    stemHintArray,
    288                CF2_Fixed*      width,
    289                FT_Bool*        haveWidth,
    290                CF2_Fixed       hintOffset )
    291   {
    292     CF2_UInt  i;
    293     CF2_UInt  count       = cf2_stack_count( opStack );
    294     FT_Bool   hasWidthArg = (FT_Bool)( count & 1 );
    295 
    296     /* variable accumulates delta values from operand stack */
    297     CF2_Fixed  position = hintOffset;
    298 
    299 
    300     if ( hasWidthArg && !*haveWidth )
    301       *width = cf2_stack_getReal( opStack, 0 ) +
    302                  cf2_getNominalWidthX( font->decoder );
    303 
    304     if ( font->decoder->width_only )
    305       goto exit;
    306 
    307     for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
    308     {
    309       /* construct a CF2_StemHint and push it onto the list */
    310       CF2_StemHintRec  stemhint;
    311 
    312 
    313       stemhint.min  =
    314         position   += cf2_stack_getReal( opStack, i );
    315       stemhint.max  =
    316         position   += cf2_stack_getReal( opStack, i + 1 );
    317 
    318       stemhint.used  = FALSE;
    319       stemhint.maxDS =
    320       stemhint.minDS = 0;
    321 
    322       cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
    323     }
    324 
    325     cf2_stack_clear( opStack );
    326 
    327   exit:
    328     /* cf2_doStems must define a width (may be default) */
    329     *haveWidth = TRUE;
    330   }
    331 
    332 
    333   static void
    334   cf2_doFlex( CF2_Stack       opStack,
    335               CF2_Fixed*      curX,
    336               CF2_Fixed*      curY,
    337               CF2_GlyphPath   glyphPath,
    338               const FT_Bool*  readFromStack,
    339               FT_Bool         doConditionalLastRead )
    340   {
    341     CF2_Fixed  vals[14];
    342     CF2_UInt   index;
    343     FT_Bool    isHFlex;
    344     CF2_Int    top, i, j;
    345 
    346 
    347     vals[0] = *curX;
    348     vals[1] = *curY;
    349     index   = 0;
    350     isHFlex = FT_BOOL( readFromStack[9] == FALSE );
    351     top     = isHFlex ? 9 : 10;
    352 
    353     for ( i = 0; i < top; i++ )
    354     {
    355       vals[i + 2] = vals[i];
    356       if ( readFromStack[i] )
    357         vals[i + 2] += cf2_stack_getReal( opStack, index++ );
    358     }
    359 
    360     if ( isHFlex )
    361       vals[9 + 2] = *curY;
    362 
    363     if ( doConditionalLastRead )
    364     {
    365       FT_Bool    lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) >
    366                                         cf2_fixedAbs( vals[11] - *curY ) );
    367       CF2_Fixed  lastVal = cf2_stack_getReal( opStack, index );
    368 
    369 
    370       if ( lastIsX )
    371       {
    372         vals[12] = vals[10] + lastVal;
    373         vals[13] = *curY;
    374       }
    375       else
    376       {
    377         vals[12] = *curX;
    378         vals[13] = vals[11] + lastVal;
    379       }
    380     }
    381     else
    382     {
    383       if ( readFromStack[10] )
    384         vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ );
    385       else
    386         vals[12] = *curX;
    387 
    388       if ( readFromStack[11] )
    389         vals[13] = vals[11] + cf2_stack_getReal( opStack, index );
    390       else
    391         vals[13] = *curY;
    392     }
    393 
    394     for ( j = 0; j < 2; j++ )
    395       cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
    396                                         vals[j * 6 + 3],
    397                                         vals[j * 6 + 4],
    398                                         vals[j * 6 + 5],
    399                                         vals[j * 6 + 6],
    400                                         vals[j * 6 + 7] );
    401 
    402     cf2_stack_clear( opStack );
    403 
    404     *curX = vals[12];
    405     *curY = vals[13];
    406   }
    407 
    408 
    409   /* Blend numOperands on the stack,                */
    410   /* store results into the first numBlends values, */
    411   /* then pop remaining arguments.                  */
    412   static void
    413   cf2_doBlend( const CFF_Blend  blend,
    414                CF2_Stack        opStack,
    415                CF2_UInt         numBlends )
    416   {
    417     CF2_UInt  delta;
    418     CF2_UInt  base;
    419     CF2_UInt  i, j;
    420     CF2_UInt  numOperands = (CF2_UInt)( numBlends * blend->lenBV );
    421 
    422 
    423     base  = cf2_stack_count( opStack ) - numOperands;
    424     delta = base + numBlends;
    425 
    426     for ( i = 0; i < numBlends; i++ )
    427     {
    428       const CF2_Fixed*  weight = &blend->BV[1];
    429 
    430       /* start with first term */
    431       CF2_Fixed  sum = cf2_stack_getReal( opStack, i + base );
    432 
    433 
    434       for ( j = 1; j < blend->lenBV; j++ )
    435         sum += FT_MulFix( *weight++, cf2_stack_getReal( opStack, delta++ ) );
    436 
    437       /* store blended result  */
    438       cf2_stack_setReal( opStack, i + base, sum );
    439     }
    440 
    441     /* leave only `numBlends' results on stack */
    442     cf2_stack_pop( opStack, numOperands - numBlends );
    443   }
    444 
    445 
    446   /*
    447    * `error' is a shared error code used by many objects in this
    448    * routine.  Before the code continues from an error, it must check and
    449    * record the error in `*error'.  The idea is that this shared
    450    * error code will record the first error encountered.  If testing
    451    * for an error anyway, the cost of `goto exit' is small, so we do it,
    452    * even if continuing would be safe.  In this case, `lastError' is
    453    * set, so the testing and storing can be done in one place, at `exit'.
    454    *
    455    * Continuing after an error is intended for objects which do their own
    456    * testing of `*error', e.g., array stack functions.  This allows us to
    457    * avoid an extra test after the call.
    458    *
    459    * Unimplemented opcodes are ignored.
    460    *
    461    */
    462   FT_LOCAL_DEF( void )
    463   cf2_interpT2CharString( CF2_Font              font,
    464                           CF2_Buffer            buf,
    465                           CF2_OutlineCallbacks  callbacks,
    466                           const FT_Vector*      translation,
    467                           FT_Bool               doingSeac,
    468                           CF2_Fixed             curX,
    469                           CF2_Fixed             curY,
    470                           CF2_Fixed*            width )
    471   {
    472     /* lastError is used for errors that are immediately tested */
    473     FT_Error  lastError = FT_Err_Ok;
    474 
    475     /* pointer to parsed font object */
    476     CFF_Decoder*  decoder = font->decoder;
    477 
    478     FT_Error*  error  = &font->error;
    479     FT_Memory  memory = font->memory;
    480 
    481     CF2_Fixed  scaleY        = font->innerTransform.d;
    482     CF2_Fixed  nominalWidthX = cf2_getNominalWidthX( decoder );
    483 
    484     /* save this for hinting seac accents */
    485     CF2_Fixed  hintOriginY = curY;
    486 
    487     CF2_Stack  opStack = NULL;
    488     FT_UInt    stackSize;
    489     FT_Byte    op1;                       /* first opcode byte */
    490 
    491     CF2_F16Dot16  storage[CF2_STORAGE_SIZE];    /* for `put' and `get' */
    492 
    493     /* instruction limit; 20,000,000 matches Avalon */
    494     FT_UInt32  instructionLimit = 20000000UL;
    495 
    496     CF2_ArrStackRec  subrStack;
    497 
    498     FT_Bool     haveWidth;
    499     CF2_Buffer  charstring = NULL;
    500 
    501     CF2_Int  charstringIndex = -1;       /* initialize to empty */
    502 
    503     /* TODO: placeholders for hint structures */
    504 
    505     /* objects used for hinting */
    506     CF2_ArrStackRec  hStemHintArray;
    507     CF2_ArrStackRec  vStemHintArray;
    508 
    509     CF2_HintMaskRec   hintMask;
    510     CF2_GlyphPathRec  glyphPath;
    511 
    512 
    513     FT_ZERO( &storage );
    514 
    515     /* initialize the remaining objects */
    516     cf2_arrstack_init( &subrStack,
    517                        memory,
    518                        error,
    519                        sizeof ( CF2_BufferRec ) );
    520     cf2_arrstack_init( &hStemHintArray,
    521                        memory,
    522                        error,
    523                        sizeof ( CF2_StemHintRec ) );
    524     cf2_arrstack_init( &vStemHintArray,
    525                        memory,
    526                        error,
    527                        sizeof ( CF2_StemHintRec ) );
    528 
    529     /* initialize CF2_StemHint arrays */
    530     cf2_hintmask_init( &hintMask, error );
    531 
    532     /* initialize path map to manage drawing operations */
    533 
    534     /* Note: last 4 params are used to handle `MoveToPermissive', which */
    535     /*       may need to call `hintMap.Build'                           */
    536     /* TODO: MoveToPermissive is gone; are these still needed?          */
    537     cf2_glyphpath_init( &glyphPath,
    538                         font,
    539                         callbacks,
    540                         scaleY,
    541                         /* hShift, */
    542                         &hStemHintArray,
    543                         &vStemHintArray,
    544                         &hintMask,
    545                         hintOriginY,
    546                         &font->blues,
    547                         translation );
    548 
    549     /*
    550      * Initialize state for width parsing.  From the CFF Spec:
    551      *
    552      *   The first stack-clearing operator, which must be one of hstem,
    553      *   hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
    554      *   rmoveto, or endchar, takes an additional argument - the width (as
    555      *   described earlier), which may be expressed as zero or one numeric
    556      *   argument.
    557      *
    558      * What we implement here uses the first validly specified width, but
    559      * does not detect errors for specifying more than one width.
    560      *
    561      * If one of the above operators occurs without explicitly specifying
    562      * a width, we assume the default width.
    563      *
    564      * CFF2 charstrings always return the default width (0).
    565      *
    566      */
    567     haveWidth = font->isCFF2 ? TRUE : FALSE;
    568     *width    = cf2_getDefaultWidthX( decoder );
    569 
    570     /*
    571      * Note: At this point, all pointers to resources must be NULL
    572      *       and all local objects must be initialized.
    573      *       There must be no branches to `exit:' above this point.
    574      *
    575      */
    576 
    577     /* allocate an operand stack */
    578     stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
    579                              : CF2_OPERAND_STACK_SIZE;
    580     opStack   = cf2_stack_init( memory, error, stackSize );
    581 
    582     if ( !opStack )
    583     {
    584       lastError = FT_THROW( Out_Of_Memory );
    585       goto exit;
    586     }
    587 
    588     /* initialize subroutine stack by placing top level charstring as */
    589     /* first element (max depth plus one for the charstring)          */
    590     /* Note: Caller owns and must finalize the first charstring.      */
    591     /*       Our copy of it does not change that requirement.         */
    592     cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
    593 
    594     charstring  = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
    595     *charstring = *buf;    /* structure copy */
    596 
    597     charstringIndex = 0;       /* entry is valid now */
    598 
    599     /* catch errors so far */
    600     if ( *error )
    601       goto exit;
    602 
    603     /* main interpreter loop */
    604     while ( 1 )
    605     {
    606       if ( cf2_buf_isEnd( charstring ) )
    607       {
    608         /* If we've reached the end of the charstring, simulate a */
    609         /* cf2_cmdRETURN or cf2_cmdENDCHAR.                       */
    610         /* We do this for both CFF and CFF2.                      */
    611         if ( charstringIndex )
    612           op1 = cf2_cmdRETURN;  /* end of buffer for subroutine */
    613         else
    614           op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
    615       }
    616       else
    617       {
    618         op1 = (FT_Byte)cf2_buf_readByte( charstring );
    619 
    620         /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
    621         /* Note: Trace message will report 0 instead of 11 or 14. */
    622         if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) &&
    623              font->isCFF2                                      )
    624           op1 = cf2_cmdRESERVED_0;
    625       }
    626 
    627       /* check for errors once per loop */
    628       if ( *error )
    629         goto exit;
    630 
    631       instructionLimit--;
    632       if ( instructionLimit == 0 )
    633       {
    634         lastError = FT_THROW( Invalid_Glyph_Format );
    635         goto exit;
    636       }
    637 
    638       switch( op1 )
    639       {
    640       case cf2_cmdRESERVED_0:
    641       case cf2_cmdRESERVED_2:
    642       case cf2_cmdRESERVED_9:
    643       case cf2_cmdRESERVED_13:
    644       case cf2_cmdRESERVED_17:
    645         /* we may get here if we have a prior error */
    646         FT_TRACE4(( " unknown op (%d)\n", op1 ));
    647         break;
    648 
    649       case cf2_cmdVSINDEX:
    650         FT_TRACE4(( " vsindex\n" ));
    651 
    652         if ( !font->isCFF2 )
    653           break;    /* clear stack & ignore */
    654 
    655         if ( font->blend.usedBV )
    656         {
    657           /* vsindex not allowed after blend */
    658           lastError = FT_THROW( Invalid_Glyph_Format );
    659           goto exit;
    660         }
    661 
    662         {
    663           FT_Int  temp = cf2_stack_popInt( opStack );
    664 
    665 
    666           if ( temp >= 0 )
    667             font->vsindex = (FT_UInt)temp;
    668         }
    669         break;
    670 
    671       case cf2_cmdBLEND:
    672         {
    673           FT_UInt  numBlends;
    674 
    675 
    676           FT_TRACE4(( " blend\n" ));
    677 
    678           if ( !font->isCFF2 )
    679             break;    /* clear stack & ignore */
    680 
    681           /* do we have a `blend' op in a non-variant font? */
    682           if ( !font->blend.font )
    683           {
    684             lastError = FT_THROW( Invalid_Glyph_Format );
    685             goto exit;
    686           }
    687 
    688           /* check cached blend vector */
    689           if ( cff_blend_check_vector( &font->blend,
    690                                        font->vsindex,
    691                                        font->lenNDV,
    692                                        font->NDV ) )
    693           {
    694             lastError = cff_blend_build_vector( &font->blend,
    695                                                 font->vsindex,
    696                                                 font->lenNDV,
    697                                                 font->NDV );
    698             if ( lastError )
    699               goto exit;
    700           }
    701 
    702           /* do the blend */
    703           numBlends = (FT_UInt)cf2_stack_popInt( opStack );
    704           if ( numBlends > stackSize )
    705           {
    706             lastError = FT_THROW( Invalid_Glyph_Format );
    707             goto exit;
    708           }
    709 
    710           cf2_doBlend( &font->blend, opStack, numBlends );
    711 
    712           font->blend.usedBV = TRUE;
    713         }
    714         continue;     /* do not clear the stack */
    715 
    716       case cf2_cmdHSTEMHM:
    717       case cf2_cmdHSTEM:
    718         FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
    719 
    720         /* never add hints after the mask is computed */
    721         if ( cf2_hintmask_isValid( &hintMask ) )
    722         {
    723           FT_TRACE4(( "cf2_interpT2CharString:"
    724                       " invalid horizontal hint mask\n" ));
    725           break;
    726         }
    727 
    728         cf2_doStems( font,
    729                      opStack,
    730                      &hStemHintArray,
    731                      width,
    732                      &haveWidth,
    733                      0 );
    734 
    735         if ( font->decoder->width_only )
    736           goto exit;
    737 
    738         break;
    739 
    740       case cf2_cmdVSTEMHM:
    741       case cf2_cmdVSTEM:
    742         FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
    743 
    744         /* never add hints after the mask is computed */
    745         if ( cf2_hintmask_isValid( &hintMask ) )
    746         {
    747           FT_TRACE4(( "cf2_interpT2CharString:"
    748                       " invalid vertical hint mask\n" ));
    749           break;
    750         }
    751 
    752         cf2_doStems( font,
    753                      opStack,
    754                      &vStemHintArray,
    755                      width,
    756                      &haveWidth,
    757                      0 );
    758 
    759         if ( font->decoder->width_only )
    760           goto exit;
    761 
    762         break;
    763 
    764       case cf2_cmdVMOVETO:
    765         FT_TRACE4(( " vmoveto\n" ));
    766 
    767         if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
    768           *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
    769 
    770         /* width is defined or default after this */
    771         haveWidth = TRUE;
    772 
    773         if ( font->decoder->width_only )
    774           goto exit;
    775 
    776         curY += cf2_stack_popFixed( opStack );
    777 
    778         cf2_glyphpath_moveTo( &glyphPath, curX, curY );
    779 
    780         break;
    781 
    782       case cf2_cmdRLINETO:
    783         {
    784           CF2_UInt  index;
    785           CF2_UInt  count = cf2_stack_count( opStack );
    786 
    787 
    788           FT_TRACE4(( " rlineto\n" ));
    789 
    790           for ( index = 0; index < count; index += 2 )
    791           {
    792             curX += cf2_stack_getReal( opStack, index + 0 );
    793             curY += cf2_stack_getReal( opStack, index + 1 );
    794 
    795             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
    796           }
    797 
    798           cf2_stack_clear( opStack );
    799         }
    800         continue; /* no need to clear stack again */
    801 
    802       case cf2_cmdHLINETO:
    803       case cf2_cmdVLINETO:
    804         {
    805           CF2_UInt  index;
    806           CF2_UInt  count = cf2_stack_count( opStack );
    807 
    808           FT_Bool  isX = FT_BOOL( op1 == cf2_cmdHLINETO );
    809 
    810 
    811           FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
    812 
    813           for ( index = 0; index < count; index++ )
    814           {
    815             CF2_Fixed  v = cf2_stack_getReal( opStack, index );
    816 
    817 
    818             if ( isX )
    819               curX += v;
    820             else
    821               curY += v;
    822 
    823             isX = !isX;
    824 
    825             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
    826           }
    827 
    828           cf2_stack_clear( opStack );
    829         }
    830         continue;
    831 
    832       case cf2_cmdRCURVELINE:
    833       case cf2_cmdRRCURVETO:
    834         {
    835           CF2_UInt  count = cf2_stack_count( opStack );
    836           CF2_UInt  index = 0;
    837 
    838 
    839           FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
    840                                                : " rrcurveto\n" ));
    841 
    842           while ( index + 6 <= count )
    843           {
    844             CF2_Fixed  x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
    845             CF2_Fixed  y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
    846             CF2_Fixed  x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
    847             CF2_Fixed  y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
    848             CF2_Fixed  x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
    849             CF2_Fixed  y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
    850 
    851 
    852             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
    853 
    854             curX   = x3;
    855             curY   = y3;
    856             index += 6;
    857           }
    858 
    859           if ( op1 == cf2_cmdRCURVELINE )
    860           {
    861             curX += cf2_stack_getReal( opStack, index + 0 );
    862             curY += cf2_stack_getReal( opStack, index + 1 );
    863 
    864             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
    865           }
    866 
    867           cf2_stack_clear( opStack );
    868         }
    869         continue; /* no need to clear stack again */
    870 
    871       case cf2_cmdCALLGSUBR:
    872       case cf2_cmdCALLSUBR:
    873         {
    874           CF2_Int  subrNum;
    875 
    876 
    877           FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
    878                                               : " callsubr" ));
    879 
    880           if ( charstringIndex > CF2_MAX_SUBR )
    881           {
    882             /* max subr plus one for charstring */
    883             lastError = FT_THROW( Invalid_Glyph_Format );
    884             goto exit;                      /* overflow of stack */
    885           }
    886 
    887           /* push our current CFF charstring region on subrStack */
    888           charstring = (CF2_Buffer)
    889                          cf2_arrstack_getPointer(
    890                            &subrStack,
    891                            (size_t)charstringIndex + 1 );
    892 
    893           /* set up the new CFF region and pointer */
    894           subrNum = cf2_stack_popInt( opStack );
    895 
    896           switch ( op1 )
    897           {
    898           case cf2_cmdCALLGSUBR:
    899             FT_TRACE4(( " (idx %d, entering level %d)\n",
    900                         subrNum + decoder->globals_bias,
    901                         charstringIndex + 1 ));
    902 
    903             if ( cf2_initGlobalRegionBuffer( decoder,
    904                                              subrNum,
    905                                              charstring ) )
    906             {
    907               lastError = FT_THROW( Invalid_Glyph_Format );
    908               goto exit;  /* subroutine lookup or stream error */
    909             }
    910             break;
    911 
    912           default:
    913             /* cf2_cmdCALLSUBR */
    914             FT_TRACE4(( " (idx %d, entering level %d)\n",
    915                         subrNum + decoder->locals_bias,
    916                         charstringIndex + 1 ));
    917 
    918             if ( cf2_initLocalRegionBuffer( decoder,
    919                                             subrNum,
    920                                             charstring ) )
    921             {
    922               lastError = FT_THROW( Invalid_Glyph_Format );
    923               goto exit;  /* subroutine lookup or stream error */
    924             }
    925           }
    926 
    927           charstringIndex += 1;       /* entry is valid now */
    928         }
    929         continue; /* do not clear the stack */
    930 
    931       case cf2_cmdRETURN:
    932         FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
    933 
    934         if ( charstringIndex < 1 )
    935         {
    936           /* Note: cannot return from top charstring */
    937           lastError = FT_THROW( Invalid_Glyph_Format );
    938           goto exit;                      /* underflow of stack */
    939         }
    940 
    941         /* restore position in previous charstring */
    942         charstring = (CF2_Buffer)
    943                        cf2_arrstack_getPointer(
    944                          &subrStack,
    945                          (CF2_UInt)--charstringIndex );
    946         continue;     /* do not clear the stack */
    947 
    948       case cf2_cmdESC:
    949         {
    950           FT_Byte  op2 = (FT_Byte)cf2_buf_readByte( charstring );
    951 
    952 
    953           /* first switch for 2-byte operators handles CFF2      */
    954           /* and opcodes that are reserved for both CFF and CFF2 */
    955           switch ( op2 )
    956           {
    957           case cf2_escHFLEX:
    958             {
    959               static const FT_Bool  readFromStack[12] =
    960               {
    961                 TRUE /* dx1 */, FALSE /* dy1 */,
    962                 TRUE /* dx2 */, TRUE  /* dy2 */,
    963                 TRUE /* dx3 */, FALSE /* dy3 */,
    964                 TRUE /* dx4 */, FALSE /* dy4 */,
    965                 TRUE /* dx5 */, FALSE /* dy5 */,
    966                 TRUE /* dx6 */, FALSE /* dy6 */
    967               };
    968 
    969 
    970               FT_TRACE4(( " hflex\n" ));
    971 
    972               cf2_doFlex( opStack,
    973                           &curX,
    974                           &curY,
    975                           &glyphPath,
    976                           readFromStack,
    977                           FALSE /* doConditionalLastRead */ );
    978             }
    979             continue;
    980 
    981           case cf2_escFLEX:
    982             {
    983               static const FT_Bool  readFromStack[12] =
    984               {
    985                 TRUE /* dx1 */, TRUE /* dy1 */,
    986                 TRUE /* dx2 */, TRUE /* dy2 */,
    987                 TRUE /* dx3 */, TRUE /* dy3 */,
    988                 TRUE /* dx4 */, TRUE /* dy4 */,
    989                 TRUE /* dx5 */, TRUE /* dy5 */,
    990                 TRUE /* dx6 */, TRUE /* dy6 */
    991               };
    992 
    993 
    994               FT_TRACE4(( " flex\n" ));
    995 
    996               cf2_doFlex( opStack,
    997                           &curX,
    998                           &curY,
    999                           &glyphPath,
   1000                           readFromStack,
   1001                           FALSE /* doConditionalLastRead */ );
   1002             }
   1003             break;      /* TODO: why is this not a continue? */
   1004 
   1005           case cf2_escHFLEX1:
   1006             {
   1007               static const FT_Bool  readFromStack[12] =
   1008               {
   1009                 TRUE /* dx1 */, TRUE  /* dy1 */,
   1010                 TRUE /* dx2 */, TRUE  /* dy2 */,
   1011                 TRUE /* dx3 */, FALSE /* dy3 */,
   1012                 TRUE /* dx4 */, FALSE /* dy4 */,
   1013                 TRUE /* dx5 */, TRUE  /* dy5 */,
   1014                 TRUE /* dx6 */, FALSE /* dy6 */
   1015               };
   1016 
   1017 
   1018               FT_TRACE4(( " hflex1\n" ));
   1019 
   1020               cf2_doFlex( opStack,
   1021                           &curX,
   1022                           &curY,
   1023                           &glyphPath,
   1024                           readFromStack,
   1025                           FALSE /* doConditionalLastRead */ );
   1026             }
   1027             continue;
   1028 
   1029           case cf2_escFLEX1:
   1030             {
   1031               static const FT_Bool  readFromStack[12] =
   1032               {
   1033                 TRUE  /* dx1 */, TRUE  /* dy1 */,
   1034                 TRUE  /* dx2 */, TRUE  /* dy2 */,
   1035                 TRUE  /* dx3 */, TRUE  /* dy3 */,
   1036                 TRUE  /* dx4 */, TRUE  /* dy4 */,
   1037                 TRUE  /* dx5 */, TRUE  /* dy5 */,
   1038                 FALSE /* dx6 */, FALSE /* dy6 */
   1039               };
   1040 
   1041 
   1042               FT_TRACE4(( " flex1\n" ));
   1043 
   1044               cf2_doFlex( opStack,
   1045                           &curX,
   1046                           &curY,
   1047                           &glyphPath,
   1048                           readFromStack,
   1049                           TRUE /* doConditionalLastRead */ );
   1050             }
   1051             continue;
   1052 
   1053           /* these opcodes are reserved in both CFF & CFF2 */
   1054           case cf2_escRESERVED_1:
   1055           case cf2_escRESERVED_2:
   1056           case cf2_escRESERVED_6:
   1057           case cf2_escRESERVED_7:
   1058           case cf2_escRESERVED_8:
   1059           case cf2_escRESERVED_13:
   1060           case cf2_escRESERVED_16:
   1061           case cf2_escRESERVED_17:
   1062           case cf2_escRESERVED_19:
   1063           case cf2_escRESERVED_25:
   1064           case cf2_escRESERVED_31:
   1065           case cf2_escRESERVED_32:
   1066           case cf2_escRESERVED_33:
   1067             FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1068             break;
   1069 
   1070           default:
   1071             {
   1072               if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
   1073                 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1074               else
   1075               {
   1076                 /* second switch for 2-byte operators handles just CFF */
   1077                 switch ( op2 )
   1078                 {
   1079 
   1080                 case cf2_escDOTSECTION:
   1081                   /* something about `flip type of locking' -- ignore it */
   1082                   FT_TRACE4(( " dotsection\n" ));
   1083 
   1084                   break;
   1085 
   1086                 case cf2_escAND:
   1087                   {
   1088                     CF2_F16Dot16  arg1;
   1089                     CF2_F16Dot16  arg2;
   1090 
   1091 
   1092                     FT_TRACE4(( " and\n" ));
   1093 
   1094                     arg2 = cf2_stack_popFixed( opStack );
   1095                     arg1 = cf2_stack_popFixed( opStack );
   1096 
   1097                     cf2_stack_pushInt( opStack, arg1 && arg2 );
   1098                   }
   1099                   continue; /* do not clear the stack */
   1100 
   1101                 case cf2_escOR:
   1102                   {
   1103                     CF2_F16Dot16  arg1;
   1104                     CF2_F16Dot16  arg2;
   1105 
   1106 
   1107                     FT_TRACE4(( " or\n" ));
   1108 
   1109                     arg2 = cf2_stack_popFixed( opStack );
   1110                     arg1 = cf2_stack_popFixed( opStack );
   1111 
   1112                     cf2_stack_pushInt( opStack, arg1 || arg2 );
   1113                   }
   1114                   continue; /* do not clear the stack */
   1115 
   1116                 case cf2_escNOT:
   1117                   {
   1118                     CF2_F16Dot16  arg;
   1119 
   1120 
   1121                     FT_TRACE4(( " not\n" ));
   1122 
   1123                     arg = cf2_stack_popFixed( opStack );
   1124 
   1125                     cf2_stack_pushInt( opStack, !arg );
   1126                   }
   1127                   continue; /* do not clear the stack */
   1128 
   1129                 case cf2_escABS:
   1130                   {
   1131                     CF2_F16Dot16  arg;
   1132 
   1133 
   1134                     FT_TRACE4(( " abs\n" ));
   1135 
   1136                     arg = cf2_stack_popFixed( opStack );
   1137 
   1138                     cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
   1139                   }
   1140                   continue; /* do not clear the stack */
   1141 
   1142                 case cf2_escADD:
   1143                   {
   1144                     CF2_F16Dot16  summand1;
   1145                     CF2_F16Dot16  summand2;
   1146 
   1147 
   1148                     FT_TRACE4(( " add\n" ));
   1149 
   1150                     summand2 = cf2_stack_popFixed( opStack );
   1151                     summand1 = cf2_stack_popFixed( opStack );
   1152 
   1153                     cf2_stack_pushFixed( opStack, summand1 + summand2 );
   1154                   }
   1155                   continue; /* do not clear the stack */
   1156 
   1157                 case cf2_escSUB:
   1158                   {
   1159                     CF2_F16Dot16  minuend;
   1160                     CF2_F16Dot16  subtrahend;
   1161 
   1162 
   1163                     FT_TRACE4(( " sub\n" ));
   1164 
   1165                     subtrahend = cf2_stack_popFixed( opStack );
   1166                     minuend    = cf2_stack_popFixed( opStack );
   1167 
   1168                     cf2_stack_pushFixed( opStack, minuend - subtrahend );
   1169                   }
   1170                   continue; /* do not clear the stack */
   1171 
   1172                 case cf2_escDIV:
   1173                   {
   1174                     CF2_F16Dot16  dividend;
   1175                     CF2_F16Dot16  divisor;
   1176 
   1177 
   1178                     FT_TRACE4(( " div\n" ));
   1179 
   1180                     divisor  = cf2_stack_popFixed( opStack );
   1181                     dividend = cf2_stack_popFixed( opStack );
   1182 
   1183                     cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) );
   1184                   }
   1185                   continue; /* do not clear the stack */
   1186 
   1187                 case cf2_escNEG:
   1188                   {
   1189                     CF2_F16Dot16  arg;
   1190 
   1191 
   1192                     FT_TRACE4(( " neg\n" ));
   1193 
   1194                     arg = cf2_stack_popFixed( opStack );
   1195 
   1196                     cf2_stack_pushFixed( opStack, -arg );
   1197                   }
   1198                   continue; /* do not clear the stack */
   1199 
   1200                 case cf2_escEQ:
   1201                   {
   1202                     CF2_F16Dot16  arg1;
   1203                     CF2_F16Dot16  arg2;
   1204 
   1205 
   1206                     FT_TRACE4(( " eq\n" ));
   1207 
   1208                     arg2 = cf2_stack_popFixed( opStack );
   1209                     arg1 = cf2_stack_popFixed( opStack );
   1210 
   1211                     cf2_stack_pushInt( opStack, arg1 == arg2 );
   1212                   }
   1213                   continue; /* do not clear the stack */
   1214 
   1215                 case cf2_escDROP:
   1216                   FT_TRACE4(( " drop\n" ));
   1217 
   1218                   (void)cf2_stack_popFixed( opStack );
   1219                   continue; /* do not clear the stack */
   1220 
   1221                 case cf2_escPUT:
   1222                   {
   1223                     CF2_F16Dot16  val;
   1224                     CF2_Int       idx;
   1225 
   1226 
   1227                     FT_TRACE4(( " put\n" ));
   1228 
   1229                     idx = cf2_stack_popInt( opStack );
   1230                     val = cf2_stack_popFixed( opStack );
   1231 
   1232                     if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
   1233                       storage[idx] = val;
   1234                   }
   1235                   continue; /* do not clear the stack */
   1236 
   1237                 case cf2_escGET:
   1238                   {
   1239                     CF2_Int  idx;
   1240 
   1241 
   1242                     FT_TRACE4(( " get\n" ));
   1243 
   1244                     idx = cf2_stack_popInt( opStack );
   1245 
   1246                     if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
   1247                       cf2_stack_pushFixed( opStack, storage[idx] );
   1248                   }
   1249                   continue; /* do not clear the stack */
   1250 
   1251                 case cf2_escIFELSE:
   1252                   {
   1253                     CF2_F16Dot16  arg1;
   1254                     CF2_F16Dot16  arg2;
   1255                     CF2_F16Dot16  cond1;
   1256                     CF2_F16Dot16  cond2;
   1257 
   1258 
   1259                     FT_TRACE4(( " ifelse\n" ));
   1260 
   1261                     cond2 = cf2_stack_popFixed( opStack );
   1262                     cond1 = cf2_stack_popFixed( opStack );
   1263                     arg2  = cf2_stack_popFixed( opStack );
   1264                     arg1  = cf2_stack_popFixed( opStack );
   1265 
   1266                     cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 );
   1267                   }
   1268                   continue; /* do not clear the stack */
   1269 
   1270                 case cf2_escRANDOM: /* in spec */
   1271                   FT_TRACE4(( " random\n" ));
   1272 
   1273                   CF2_FIXME;
   1274                   break;
   1275 
   1276                 case cf2_escMUL:
   1277                   {
   1278                     CF2_F16Dot16  factor1;
   1279                     CF2_F16Dot16  factor2;
   1280 
   1281 
   1282                     FT_TRACE4(( " mul\n" ));
   1283 
   1284                     factor2 = cf2_stack_popFixed( opStack );
   1285                     factor1 = cf2_stack_popFixed( opStack );
   1286 
   1287                     cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) );
   1288                   }
   1289                   continue; /* do not clear the stack */
   1290 
   1291                 case cf2_escSQRT:
   1292                   {
   1293                     CF2_F16Dot16  arg;
   1294 
   1295 
   1296                     FT_TRACE4(( " sqrt\n" ));
   1297 
   1298                     arg = cf2_stack_popFixed( opStack );
   1299                     if ( arg > 0 )
   1300                     {
   1301                       FT_Fixed  root = arg;
   1302                       FT_Fixed  new_root;
   1303 
   1304 
   1305                       /* Babylonian method */
   1306                       for (;;)
   1307                       {
   1308                         new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
   1309                         if ( new_root == root )
   1310                           break;
   1311                         root = new_root;
   1312                       }
   1313                       arg = new_root;
   1314                     }
   1315                     else
   1316                       arg = 0;
   1317 
   1318                     cf2_stack_pushFixed( opStack, arg );
   1319                   }
   1320                   continue; /* do not clear the stack */
   1321 
   1322                 case cf2_escDUP:
   1323                   {
   1324                     CF2_F16Dot16  arg;
   1325 
   1326 
   1327                     FT_TRACE4(( " dup\n" ));
   1328 
   1329                     arg = cf2_stack_popFixed( opStack );
   1330 
   1331                     cf2_stack_pushFixed( opStack, arg );
   1332                     cf2_stack_pushFixed( opStack, arg );
   1333                   }
   1334                   continue; /* do not clear the stack */
   1335 
   1336                 case cf2_escEXCH:
   1337                   {
   1338                     CF2_F16Dot16  arg1;
   1339                     CF2_F16Dot16  arg2;
   1340 
   1341 
   1342                     FT_TRACE4(( " exch\n" ));
   1343 
   1344                     arg2 = cf2_stack_popFixed( opStack );
   1345                     arg1 = cf2_stack_popFixed( opStack );
   1346 
   1347                     cf2_stack_pushFixed( opStack, arg2 );
   1348                     cf2_stack_pushFixed( opStack, arg1 );
   1349                   }
   1350                   continue; /* do not clear the stack */
   1351 
   1352                 case cf2_escINDEX:
   1353                   {
   1354                     CF2_Int   idx;
   1355                     CF2_UInt  size;
   1356 
   1357 
   1358                     FT_TRACE4(( " index\n" ));
   1359 
   1360                     idx  = cf2_stack_popInt( opStack );
   1361                     size = cf2_stack_count( opStack );
   1362 
   1363                     if ( size > 0 )
   1364                     {
   1365                       /* for `cf2_stack_getReal', index 0 is bottom of stack */
   1366                       CF2_UInt  gr_idx;
   1367 
   1368 
   1369                       if ( idx < 0 )
   1370                         gr_idx = size - 1;
   1371                       else if ( (CF2_UInt)idx >= size )
   1372                         gr_idx = 0;
   1373                       else
   1374                         gr_idx = size - 1 - (CF2_UInt)idx;
   1375 
   1376                       cf2_stack_pushFixed( opStack,
   1377                                            cf2_stack_getReal( opStack, gr_idx ) );
   1378                     }
   1379                   }
   1380                   continue; /* do not clear the stack */
   1381 
   1382                 case cf2_escROLL:
   1383                   {
   1384                     CF2_Int  idx;
   1385                     CF2_Int  count;
   1386 
   1387 
   1388                     FT_TRACE4(( " roll\n" ));
   1389 
   1390                     idx   = cf2_stack_popInt( opStack );
   1391                     count = cf2_stack_popInt( opStack );
   1392 
   1393                     cf2_stack_roll( opStack, count, idx );
   1394                   }
   1395                   continue; /* do not clear the stack */
   1396 
   1397                 } /* end of 2nd switch checking op2 */
   1398               }
   1399             }
   1400           } /* end of 1st switch checking op2 */
   1401         } /* case cf2_cmdESC */
   1402 
   1403         break;
   1404 
   1405       case cf2_cmdENDCHAR:
   1406         FT_TRACE4(( " endchar\n" ));
   1407 
   1408         if ( cf2_stack_count( opStack ) == 1 ||
   1409              cf2_stack_count( opStack ) == 5 )
   1410         {
   1411           if ( !haveWidth )
   1412             *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
   1413         }
   1414 
   1415         /* width is defined or default after this */
   1416         haveWidth = TRUE;
   1417 
   1418         if ( font->decoder->width_only )
   1419           goto exit;
   1420 
   1421         /* close path if still open */
   1422         cf2_glyphpath_closeOpenPath( &glyphPath );
   1423 
   1424         /* disable seac for CFF2 (charstring ending with args on stack) */
   1425         if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 )
   1426         {
   1427           /* must be either 4 or 5 --                       */
   1428           /* this is a (deprecated) implied `seac' operator */
   1429 
   1430           CF2_Int        achar;
   1431           CF2_Int        bchar;
   1432           CF2_BufferRec  component;
   1433           CF2_Fixed      dummyWidth;   /* ignore component width */
   1434           FT_Error       error2;
   1435 
   1436 
   1437           if ( doingSeac )
   1438           {
   1439             lastError = FT_THROW( Invalid_Glyph_Format );
   1440             goto exit;      /* nested seac */
   1441           }
   1442 
   1443           achar = cf2_stack_popInt( opStack );
   1444           bchar = cf2_stack_popInt( opStack );
   1445 
   1446           curY = cf2_stack_popFixed( opStack );
   1447           curX = cf2_stack_popFixed( opStack );
   1448 
   1449           error2 = cf2_getSeacComponent( decoder, achar, &component );
   1450           if ( error2 )
   1451           {
   1452             lastError = error2;      /* pass FreeType error through */
   1453             goto exit;
   1454           }
   1455           cf2_interpT2CharString( font,
   1456                                   &component,
   1457                                   callbacks,
   1458                                   translation,
   1459                                   TRUE,
   1460                                   curX,
   1461                                   curY,
   1462                                   &dummyWidth );
   1463           cf2_freeSeacComponent( decoder, &component );
   1464 
   1465           error2 = cf2_getSeacComponent( decoder, bchar, &component );
   1466           if ( error2 )
   1467           {
   1468             lastError = error2;      /* pass FreeType error through */
   1469             goto exit;
   1470           }
   1471           cf2_interpT2CharString( font,
   1472                                   &component,
   1473                                   callbacks,
   1474                                   translation,
   1475                                   TRUE,
   1476                                   0,
   1477                                   0,
   1478                                   &dummyWidth );
   1479           cf2_freeSeacComponent( decoder, &component );
   1480         }
   1481         goto exit;
   1482 
   1483       case cf2_cmdCNTRMASK:
   1484       case cf2_cmdHINTMASK:
   1485         /* the final \n in the tracing message gets added in      */
   1486         /* `cf2_hintmask_read' (which also traces the mask bytes) */
   1487         FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
   1488 
   1489         /* never add hints after the mask is computed */
   1490         if ( cf2_stack_count( opStack ) > 1    &&
   1491              cf2_hintmask_isValid( &hintMask ) )
   1492         {
   1493           FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
   1494           break;
   1495         }
   1496 
   1497         /* if there are arguments on the stack, there this is an */
   1498         /* implied cf2_cmdVSTEMHM                                */
   1499         cf2_doStems( font,
   1500                      opStack,
   1501                      &vStemHintArray,
   1502                      width,
   1503                      &haveWidth,
   1504                      0 );
   1505 
   1506         if ( font->decoder->width_only )
   1507           goto exit;
   1508 
   1509         if ( op1 == cf2_cmdHINTMASK )
   1510         {
   1511           /* consume the hint mask bytes which follow the operator */
   1512           cf2_hintmask_read( &hintMask,
   1513                              charstring,
   1514                              cf2_arrstack_size( &hStemHintArray ) +
   1515                                cf2_arrstack_size( &vStemHintArray ) );
   1516         }
   1517         else
   1518         {
   1519           /*
   1520            * Consume the counter mask bytes which follow the operator:
   1521            * Build a temporary hint map, just to place and lock those
   1522            * stems participating in the counter mask.  These are most
   1523            * likely the dominant hstems, and are grouped together in a
   1524            * few counter groups, not necessarily in correspondence
   1525            * with the hint groups.  This reduces the chances of
   1526            * conflicts between hstems that are initially placed in
   1527            * separate hint groups and then brought together.  The
   1528            * positions are copied back to `hStemHintArray', so we can
   1529            * discard `counterMask' and `counterHintMap'.
   1530            *
   1531            */
   1532           CF2_HintMapRec   counterHintMap;
   1533           CF2_HintMaskRec  counterMask;
   1534 
   1535 
   1536           cf2_hintmap_init( &counterHintMap,
   1537                             font,
   1538                             &glyphPath.initialHintMap,
   1539                             &glyphPath.hintMoves,
   1540                             scaleY );
   1541           cf2_hintmask_init( &counterMask, error );
   1542 
   1543           cf2_hintmask_read( &counterMask,
   1544                              charstring,
   1545                              cf2_arrstack_size( &hStemHintArray ) +
   1546                                cf2_arrstack_size( &vStemHintArray ) );
   1547           cf2_hintmap_build( &counterHintMap,
   1548                              &hStemHintArray,
   1549                              &vStemHintArray,
   1550                              &counterMask,
   1551                              0,
   1552                              FALSE );
   1553         }
   1554         break;
   1555 
   1556       case cf2_cmdRMOVETO:
   1557         FT_TRACE4(( " rmoveto\n" ));
   1558 
   1559         if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
   1560           *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
   1561 
   1562         /* width is defined or default after this */
   1563         haveWidth = TRUE;
   1564 
   1565         if ( font->decoder->width_only )
   1566           goto exit;
   1567 
   1568         curY += cf2_stack_popFixed( opStack );
   1569         curX += cf2_stack_popFixed( opStack );
   1570 
   1571         cf2_glyphpath_moveTo( &glyphPath, curX, curY );
   1572 
   1573         break;
   1574 
   1575       case cf2_cmdHMOVETO:
   1576         FT_TRACE4(( " hmoveto\n" ));
   1577 
   1578         if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
   1579           *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
   1580 
   1581         /* width is defined or default after this */
   1582         haveWidth = TRUE;
   1583 
   1584         if ( font->decoder->width_only )
   1585           goto exit;
   1586 
   1587         curX += cf2_stack_popFixed( opStack );
   1588 
   1589         cf2_glyphpath_moveTo( &glyphPath, curX, curY );
   1590 
   1591         break;
   1592 
   1593       case cf2_cmdRLINECURVE:
   1594         {
   1595           CF2_UInt  count = cf2_stack_count( opStack );
   1596           CF2_UInt  index = 0;
   1597 
   1598 
   1599           FT_TRACE4(( " rlinecurve\n" ));
   1600 
   1601           while ( index + 6 < count )
   1602           {
   1603             curX += cf2_stack_getReal( opStack, index + 0 );
   1604             curY += cf2_stack_getReal( opStack, index + 1 );
   1605 
   1606             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
   1607             index += 2;
   1608           }
   1609 
   1610           while ( index < count )
   1611           {
   1612             CF2_Fixed  x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
   1613             CF2_Fixed  y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
   1614             CF2_Fixed  x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
   1615             CF2_Fixed  y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
   1616             CF2_Fixed  x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
   1617             CF2_Fixed  y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
   1618 
   1619 
   1620             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   1621 
   1622             curX   = x3;
   1623             curY   = y3;
   1624             index += 6;
   1625           }
   1626 
   1627           cf2_stack_clear( opStack );
   1628         }
   1629         continue; /* no need to clear stack again */
   1630 
   1631       case cf2_cmdVVCURVETO:
   1632         {
   1633           CF2_UInt  count, count1 = cf2_stack_count( opStack );
   1634           CF2_UInt  index = 0;
   1635 
   1636 
   1637           /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
   1638           /* we enforce it by clearing the second bit           */
   1639           /* (and sorting the stack indexing to suit)           */
   1640           count  = count1 & ~2U;
   1641           index += count1 - count;
   1642 
   1643           FT_TRACE4(( " vvcurveto\n" ));
   1644 
   1645           while ( index < count )
   1646           {
   1647             CF2_Fixed  x1, y1, x2, y2, x3, y3;
   1648 
   1649 
   1650             if ( ( count - index ) & 1 )
   1651             {
   1652               x1 = cf2_stack_getReal( opStack, index ) + curX;
   1653 
   1654               index++;
   1655             }
   1656             else
   1657               x1 = curX;
   1658 
   1659             y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
   1660             x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
   1661             y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
   1662             x3 = x2;
   1663             y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
   1664 
   1665             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   1666 
   1667             curX   = x3;
   1668             curY   = y3;
   1669             index += 4;
   1670           }
   1671 
   1672           cf2_stack_clear( opStack );
   1673         }
   1674         continue; /* no need to clear stack again */
   1675 
   1676       case cf2_cmdHHCURVETO:
   1677         {
   1678           CF2_UInt  count, count1 = cf2_stack_count( opStack );
   1679           CF2_UInt  index = 0;
   1680 
   1681 
   1682           /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
   1683           /* we enforce it by clearing the second bit           */
   1684           /* (and sorting the stack indexing to suit)           */
   1685           count  = count1 & ~2U;
   1686           index += count1 - count;
   1687 
   1688           FT_TRACE4(( " hhcurveto\n" ));
   1689 
   1690           while ( index < count )
   1691           {
   1692             CF2_Fixed  x1, y1, x2, y2, x3, y3;
   1693 
   1694 
   1695             if ( ( count - index ) & 1 )
   1696             {
   1697               y1 = cf2_stack_getReal( opStack, index ) + curY;
   1698 
   1699               index++;
   1700             }
   1701             else
   1702               y1 = curY;
   1703 
   1704             x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
   1705             x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
   1706             y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
   1707             x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
   1708             y3 = y2;
   1709 
   1710             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   1711 
   1712             curX   = x3;
   1713             curY   = y3;
   1714             index += 4;
   1715           }
   1716 
   1717           cf2_stack_clear( opStack );
   1718         }
   1719         continue; /* no need to clear stack again */
   1720 
   1721       case cf2_cmdVHCURVETO:
   1722       case cf2_cmdHVCURVETO:
   1723         {
   1724           CF2_UInt  count, count1 = cf2_stack_count( opStack );
   1725           CF2_UInt  index = 0;
   1726 
   1727           FT_Bool  alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
   1728 
   1729 
   1730           /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
   1731           /* 8n+4, or 8n+5, we enforce it by clearing the     */
   1732           /* second bit                                       */
   1733           /* (and sorting the stack indexing to suit)         */
   1734           count  = count1 & ~2U;
   1735           index += count1 - count;
   1736 
   1737           FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
   1738 
   1739           while ( index < count )
   1740           {
   1741             CF2_Fixed x1, x2, x3, y1, y2, y3;
   1742 
   1743 
   1744             if ( alternate )
   1745             {
   1746               x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
   1747               y1 = curY;
   1748               x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
   1749               y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
   1750               y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
   1751 
   1752               if ( count - index == 5 )
   1753               {
   1754                 x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
   1755 
   1756                 index++;
   1757               }
   1758               else
   1759                 x3 = x2;
   1760 
   1761               alternate = FALSE;
   1762             }
   1763             else
   1764             {
   1765               x1 = curX;
   1766               y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
   1767               x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
   1768               y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
   1769               x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
   1770 
   1771               if ( count - index == 5 )
   1772               {
   1773                 y3 = cf2_stack_getReal( opStack, index + 4 ) + y2;
   1774 
   1775                 index++;
   1776               }
   1777               else
   1778                 y3 = y2;
   1779 
   1780               alternate = TRUE;
   1781             }
   1782 
   1783             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   1784 
   1785             curX   = x3;
   1786             curY   = y3;
   1787             index += 4;
   1788           }
   1789 
   1790           cf2_stack_clear( opStack );
   1791         }
   1792         continue;     /* no need to clear stack again */
   1793 
   1794       case cf2_cmdEXTENDEDNMBR:
   1795         {
   1796           CF2_Int  v;
   1797 
   1798           CF2_Int  byte1 = cf2_buf_readByte( charstring );
   1799           CF2_Int  byte2 = cf2_buf_readByte( charstring );
   1800 
   1801 
   1802           v = (FT_Short)( ( byte1 << 8 ) |
   1803                             byte2        );
   1804 
   1805           FT_TRACE4(( " %d", v ));
   1806 
   1807           cf2_stack_pushInt( opStack, v );
   1808         }
   1809         continue;
   1810 
   1811       default:
   1812         /* numbers */
   1813         {
   1814           if ( /* op1 >= 32 && */ op1 <= 246 )
   1815           {
   1816             CF2_Int  v;
   1817 
   1818 
   1819             v = op1 - 139;
   1820 
   1821             FT_TRACE4(( " %d", v ));
   1822 
   1823             /* -107 .. 107 */
   1824             cf2_stack_pushInt( opStack, v );
   1825           }
   1826 
   1827           else if ( /* op1 >= 247 && */ op1 <= 250 )
   1828           {
   1829             CF2_Int  v;
   1830 
   1831 
   1832             v  = op1;
   1833             v -= 247;
   1834             v *= 256;
   1835             v += cf2_buf_readByte( charstring );
   1836             v += 108;
   1837 
   1838             FT_TRACE4(( " %d", v ));
   1839 
   1840             /* 108 .. 1131 */
   1841             cf2_stack_pushInt( opStack, v );
   1842           }
   1843 
   1844           else if ( /* op1 >= 251 && */ op1 <= 254 )
   1845           {
   1846             CF2_Int  v;
   1847 
   1848 
   1849             v  = op1;
   1850             v -= 251;
   1851             v *= 256;
   1852             v += cf2_buf_readByte( charstring );
   1853             v  = -v - 108;
   1854 
   1855             FT_TRACE4(( " %d", v ));
   1856 
   1857             /* -1131 .. -108 */
   1858             cf2_stack_pushInt( opStack, v );
   1859           }
   1860 
   1861           else /* op1 == 255 */
   1862           {
   1863             CF2_Fixed  v;
   1864 
   1865             FT_UInt32  byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
   1866             FT_UInt32  byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
   1867             FT_UInt32  byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
   1868             FT_UInt32  byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
   1869 
   1870 
   1871             v = (CF2_Fixed)( ( byte1 << 24 ) |
   1872                              ( byte2 << 16 ) |
   1873                              ( byte3 <<  8 ) |
   1874                                byte4         );
   1875 
   1876             FT_TRACE4(( " %.5f", v / 65536.0 ));
   1877 
   1878             cf2_stack_pushFixed( opStack, v );
   1879           }
   1880         }
   1881         continue;   /* don't clear stack */
   1882 
   1883       } /* end of switch statement checking `op1' */
   1884 
   1885       cf2_stack_clear( opStack );
   1886 
   1887     } /* end of main interpreter loop */
   1888 
   1889     /* we get here if the charstring ends without cf2_cmdENDCHAR */
   1890     FT_TRACE4(( "cf2_interpT2CharString:"
   1891                 "  charstring ends without ENDCHAR\n" ));
   1892 
   1893   exit:
   1894     /* check whether last error seen is also the first one */
   1895     cf2_setError( error, lastError );
   1896 
   1897     if ( *error )
   1898       FT_TRACE4(( "charstring error %d\n", *error ));
   1899 
   1900     /* free resources from objects we've used */
   1901     cf2_glyphpath_finalize( &glyphPath );
   1902     cf2_arrstack_finalize( &vStemHintArray );
   1903     cf2_arrstack_finalize( &hStemHintArray );
   1904     cf2_arrstack_finalize( &subrStack );
   1905     cf2_stack_free( opStack );
   1906 
   1907     FT_TRACE4(( "\n" ));
   1908 
   1909     return;
   1910   }
   1911 
   1912 
   1913 /* END */
   1914