tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

psintrp.c (105457B)


      1 /****************************************************************************
      2 *
      3 * psintrp.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 "psft.h"
     40 #include <freetype/internal/ftcalc.h>
     41 #include <freetype/internal/ftdebug.h>
     42 #include <freetype/internal/services/svcfftl.h>
     43 
     44 #include "psglue.h"
     45 #include "psfont.h"
     46 #include "psstack.h"
     47 #include "pshints.h"
     48 #include "psintrp.h"
     49 
     50 #include "pserror.h"
     51 
     52 #include "psobjs.h"   /* for cff_random */
     53 #include "t1decode.h" /* for t1 seac    */
     54 
     55 
     56  /**************************************************************************
     57   *
     58   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     59   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     60   * messages during execution.
     61   */
     62 #undef  FT_COMPONENT
     63 #define FT_COMPONENT  cf2interp
     64 
     65 
     66  FT_LOCAL_DEF( void )
     67  cf2_hintmask_init( CF2_HintMask  hintmask,
     68                     FT_Error*     error )
     69  {
     70    FT_ZERO( hintmask );
     71 
     72    hintmask->error = error;
     73  }
     74 
     75 
     76  FT_LOCAL_DEF( FT_Bool )
     77  cf2_hintmask_isValid( const CF2_HintMask  hintmask )
     78  {
     79    return hintmask->isValid;
     80  }
     81 
     82 
     83  FT_LOCAL_DEF( FT_Bool )
     84  cf2_hintmask_isNew( const CF2_HintMask  hintmask )
     85  {
     86    return hintmask->isNew;
     87  }
     88 
     89 
     90  FT_LOCAL_DEF( void )
     91  cf2_hintmask_setNew( CF2_HintMask  hintmask,
     92                       FT_Bool       val )
     93  {
     94    hintmask->isNew = val;
     95  }
     96 
     97 
     98  /* clients call `getMaskPtr' in order to iterate */
     99  /* through hint mask                             */
    100 
    101  FT_LOCAL_DEF( FT_Byte* )
    102  cf2_hintmask_getMaskPtr( CF2_HintMask  hintmask )
    103  {
    104    return hintmask->mask;
    105  }
    106 
    107 
    108  static size_t
    109  cf2_hintmask_setCounts( CF2_HintMask  hintmask,
    110                          size_t        bitCount )
    111  {
    112    if ( bitCount > CF2_MAX_HINTS )
    113    {
    114      /* total of h and v stems must be <= 96 */
    115      CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
    116      return 0;
    117    }
    118 
    119    hintmask->bitCount  = bitCount;
    120    hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
    121 
    122    hintmask->isValid = TRUE;
    123    hintmask->isNew   = TRUE;
    124 
    125    return bitCount;
    126  }
    127 
    128 
    129  /* consume the hintmask bytes from the charstring, advancing the src */
    130  /* pointer                                                           */
    131  static void
    132  cf2_hintmask_read( CF2_HintMask  hintmask,
    133                     CF2_Buffer    charstring,
    134                     size_t        bitCount )
    135  {
    136    size_t  i;
    137 
    138 #ifndef CF2_NDEBUG
    139    /* these are the bits in the final mask byte that should be zero  */
    140    /* Note: this variable is only used in an assert expression below */
    141    /* and then only if CF2_NDEBUG is not defined                     */
    142    CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
    143 #endif
    144 
    145 
    146    /* initialize counts and isValid */
    147    if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
    148      return;
    149 
    150    FT_ASSERT( hintmask->byteCount > 0 );
    151 
    152    FT_TRACE4(( " (maskbytes:" ));
    153 
    154    /* set mask and advance interpreter's charstring pointer */
    155    for ( i = 0; i < hintmask->byteCount; i++ )
    156    {
    157      hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
    158      FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
    159    }
    160 
    161    FT_TRACE4(( ")\n" ));
    162 
    163    /* assert any unused bits in last byte are zero unless there's a prior */
    164    /* error                                                               */
    165    /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1      */
    166 #ifndef CF2_NDEBUG
    167    FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
    168               *hintmask->error                                        );
    169 #endif
    170  }
    171 
    172 
    173  FT_LOCAL_DEF( void )
    174  cf2_hintmask_setAll( CF2_HintMask  hintmask,
    175                       size_t        bitCount )
    176  {
    177    size_t    i;
    178    CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
    179 
    180 
    181    /* initialize counts and isValid */
    182    if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
    183      return;
    184 
    185    FT_ASSERT( hintmask->byteCount > 0 );
    186    FT_ASSERT( hintmask->byteCount <=
    187                 sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
    188 
    189    /* set mask to all ones */
    190    for ( i = 0; i < hintmask->byteCount; i++ )
    191      hintmask->mask[i] = 0xFF;
    192 
    193    /* clear unused bits                                              */
    194    /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
    195    hintmask->mask[hintmask->byteCount - 1] &= ~mask;
    196  }
    197 
    198 
    199  /* Type2 charstring opcodes */
    200  enum
    201  {
    202    cf2_cmdRESERVED_0,   /* 0 */
    203    cf2_cmdHSTEM,        /* 1 */
    204    cf2_cmdRESERVED_2,   /* 2 */
    205    cf2_cmdVSTEM,        /* 3 */
    206    cf2_cmdVMOVETO,      /* 4 */
    207    cf2_cmdRLINETO,      /* 5 */
    208    cf2_cmdHLINETO,      /* 6 */
    209    cf2_cmdVLINETO,      /* 7 */
    210    cf2_cmdRRCURVETO,    /* 8 */
    211    cf2_cmdCLOSEPATH,    /* 9      T1 only */
    212    cf2_cmdCALLSUBR,     /* 10 */
    213    cf2_cmdRETURN,       /* 11 */
    214    cf2_cmdESC,          /* 12 */
    215    cf2_cmdHSBW,         /* 13     T1 only */
    216    cf2_cmdENDCHAR,      /* 14 */
    217    cf2_cmdVSINDEX,      /* 15 */
    218    cf2_cmdBLEND,        /* 16 */
    219    cf2_cmdRESERVED_17,  /* 17 */
    220    cf2_cmdHSTEMHM,      /* 18 */
    221    cf2_cmdHINTMASK,     /* 19 */
    222    cf2_cmdCNTRMASK,     /* 20 */
    223    cf2_cmdRMOVETO,      /* 21 */
    224    cf2_cmdHMOVETO,      /* 22 */
    225    cf2_cmdVSTEMHM,      /* 23 */
    226    cf2_cmdRCURVELINE,   /* 24 */
    227    cf2_cmdRLINECURVE,   /* 25 */
    228    cf2_cmdVVCURVETO,    /* 26 */
    229    cf2_cmdHHCURVETO,    /* 27 */
    230    cf2_cmdEXTENDEDNMBR, /* 28 */
    231    cf2_cmdCALLGSUBR,    /* 29 */
    232    cf2_cmdVHCURVETO,    /* 30 */
    233    cf2_cmdHVCURVETO     /* 31 */
    234  };
    235 
    236  enum
    237  {
    238    cf2_escDOTSECTION,   /* 0 */
    239    cf2_escVSTEM3,       /* 1      T1 only */
    240    cf2_escHSTEM3,       /* 2      T1 only */
    241    cf2_escAND,          /* 3 */
    242    cf2_escOR,           /* 4 */
    243    cf2_escNOT,          /* 5 */
    244    cf2_escSEAC,         /* 6      T1 only */
    245    cf2_escSBW,          /* 7      T1 only */
    246    cf2_escRESERVED_8,   /* 8 */
    247    cf2_escABS,          /* 9 */
    248    cf2_escADD,          /* 10     like otherADD */
    249    cf2_escSUB,          /* 11     like otherSUB */
    250    cf2_escDIV,          /* 12 */
    251    cf2_escRESERVED_13,  /* 13 */
    252    cf2_escNEG,          /* 14 */
    253    cf2_escEQ,           /* 15 */
    254    cf2_escCALLOTHERSUBR,/* 16     T1 only */
    255    cf2_escPOP,          /* 17     T1 only */
    256    cf2_escDROP,         /* 18 */
    257    cf2_escRESERVED_19,  /* 19 */
    258    cf2_escPUT,          /* 20     like otherPUT    */
    259    cf2_escGET,          /* 21     like otherGET    */
    260    cf2_escIFELSE,       /* 22     like otherIFELSE */
    261    cf2_escRANDOM,       /* 23     like otherRANDOM */
    262    cf2_escMUL,          /* 24     like otherMUL    */
    263    cf2_escRESERVED_25,  /* 25 */
    264    cf2_escSQRT,         /* 26 */
    265    cf2_escDUP,          /* 27     like otherDUP    */
    266    cf2_escEXCH,         /* 28     like otherEXCH   */
    267    cf2_escINDEX,        /* 29 */
    268    cf2_escROLL,         /* 30 */
    269    cf2_escRESERVED_31,  /* 31 */
    270    cf2_escRESERVED_32,  /* 32 */
    271    cf2_escSETCURRENTPT, /* 33     T1 only */
    272    cf2_escHFLEX,        /* 34 */
    273    cf2_escFLEX,         /* 35 */
    274    cf2_escHFLEX1,       /* 36 */
    275    cf2_escFLEX1,        /* 37 */
    276    cf2_escRESERVED_38   /* 38     & all higher     */
    277  };
    278 
    279 
    280  /* `stemHintArray' does not change once we start drawing the outline. */
    281  static void
    282  cf2_doStems( const CF2_Font  font,
    283               CF2_Stack       opStack,
    284               CF2_ArrStack    stemHintArray,
    285               CF2_Fixed*      width,
    286               FT_Bool*        haveWidth,
    287               CF2_Fixed       hintOffset )
    288  {
    289    CF2_UInt  i;
    290    CF2_UInt  count       = cf2_stack_count( opStack );
    291    FT_Bool   hasWidthArg = FT_BOOL( count & 1 );
    292 
    293    /* variable accumulates delta values from operand stack */
    294    CF2_Fixed  position = hintOffset;
    295 
    296    if ( font->isT1 && !font->decoder->flex_state && !*haveWidth )
    297      FT_ERROR(( "cf2_doStems (Type 1 mode):"
    298                 " No width. Use hsbw/sbw as first op\n" ));
    299 
    300    if ( !font->isT1 && hasWidthArg && !*haveWidth )
    301      *width = ADD_INT32( 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     = ADD_INT32( position,
    315                                cf2_stack_getReal( opStack, i ) );
    316      stemhint.max =
    317      position     = ADD_INT32( position,
    318                                cf2_stack_getReal( opStack, i + 1 ) );
    319 
    320      stemhint.used  = FALSE;
    321      stemhint.maxDS =
    322      stemhint.minDS = 0;
    323 
    324      cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
    325    }
    326 
    327    cf2_stack_clear( opStack );
    328 
    329  exit:
    330    /* cf2_doStems must define a width (may be default) */
    331    *haveWidth = TRUE;
    332  }
    333 
    334 
    335  static void
    336  cf2_doFlex( CF2_Stack       opStack,
    337              CF2_Fixed*      curX,
    338              CF2_Fixed*      curY,
    339              CF2_GlyphPath   glyphPath,
    340              const FT_Bool*  readFromStack,
    341              FT_Bool         doConditionalLastRead )
    342  {
    343    CF2_Fixed  vals[14];
    344    CF2_UInt   idx;
    345    FT_Bool    isHFlex;
    346    CF2_Int    top, i, j;
    347 
    348 
    349    vals[0] = *curX;
    350    vals[1] = *curY;
    351    idx     = 0;
    352    isHFlex = FT_BOOL( readFromStack[9] == FALSE );
    353    top     = isHFlex ? 9 : 10;
    354 
    355    for ( i = 0; i < top; i++ )
    356    {
    357      vals[i + 2] = vals[i];
    358      if ( readFromStack[i] )
    359        vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack,
    360                                                                 idx++ ) );
    361    }
    362 
    363    if ( isHFlex )
    364      vals[9 + 2] = *curY;
    365 
    366    if ( doConditionalLastRead )
    367    {
    368      FT_Bool    lastIsX = FT_BOOL(
    369                             cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) >
    370                             cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) );
    371      CF2_Fixed  lastVal = cf2_stack_getReal( opStack, idx );
    372 
    373 
    374      if ( lastIsX )
    375      {
    376        vals[12] = ADD_INT32( vals[10], lastVal );
    377        vals[13] = *curY;
    378      }
    379      else
    380      {
    381        vals[12] = *curX;
    382        vals[13] = ADD_INT32( vals[11], lastVal );
    383      }
    384    }
    385    else
    386    {
    387      if ( readFromStack[10] )
    388        vals[12] = ADD_INT32( vals[10],
    389                              cf2_stack_getReal( opStack, idx++ ) );
    390      else
    391        vals[12] = *curX;
    392 
    393      if ( readFromStack[11] )
    394        vals[13] = ADD_INT32( vals[11],
    395                              cf2_stack_getReal( opStack, idx ) );
    396      else
    397        vals[13] = *curY;
    398    }
    399 
    400    for ( j = 0; j < 2; j++ )
    401      cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
    402                                        vals[j * 6 + 3],
    403                                        vals[j * 6 + 4],
    404                                        vals[j * 6 + 5],
    405                                        vals[j * 6 + 6],
    406                                        vals[j * 6 + 7] );
    407 
    408    cf2_stack_clear( opStack );
    409 
    410    *curX = vals[12];
    411    *curY = vals[13];
    412  }
    413 
    414 
    415  /* Blend numOperands on the stack,                */
    416  /* store results into the first numBlends values, */
    417  /* then pop remaining arguments.                  */
    418  static void
    419  cf2_doBlend( const CFF_Blend  blend,
    420               CF2_Stack        opStack,
    421               CF2_UInt         numBlends )
    422  {
    423    CF2_UInt  delta;
    424    CF2_UInt  base;
    425    CF2_UInt  i, j;
    426    CF2_UInt  numOperands = (CF2_UInt)( numBlends * blend->lenBV );
    427 
    428 
    429    base  = cf2_stack_count( opStack ) - numOperands;
    430    delta = base + numBlends;
    431 
    432    FT_TRACE6(( " (" ));
    433 
    434    for ( i = 0; i < numBlends; i++ )
    435    {
    436      const CF2_Fixed*  weight = &blend->BV[1];
    437 
    438      /* start with first term */
    439      CF2_Fixed  sum = cf2_stack_getReal( opStack, i + base );
    440 
    441 
    442      for ( j = 1; j < blend->lenBV; j++ )
    443        sum = ADD_INT32( sum,
    444                         FT_MulFix( *weight++,
    445                                    cf2_stack_getReal( opStack,
    446                                                       delta++ ) ) );
    447 
    448      FT_TRACE6(( "%f ", (double)sum / 65536 ));
    449 
    450      /* store blended result  */
    451      cf2_stack_setReal( opStack, i + base, sum );
    452    }
    453 
    454    FT_TRACE6(( "blended)\n" ));
    455 
    456    /* leave only `numBlends' results on stack */
    457    cf2_stack_pop( opStack, numOperands - numBlends );
    458  }
    459 
    460 
    461  /*
    462   * `error' is a shared error code used by many objects in this
    463   * routine.  Before the code continues from an error, it must check and
    464   * record the error in `*error'.  The idea is that this shared
    465   * error code will record the first error encountered.  If testing
    466   * for an error anyway, the cost of `goto exit' is small, so we do it,
    467   * even if continuing would be safe.  In this case, `lastError' is
    468   * set, so the testing and storing can be done in one place, at `exit'.
    469   *
    470   * Continuing after an error is intended for objects which do their own
    471   * testing of `*error', e.g., array stack functions.  This allows us to
    472   * avoid an extra test after the call.
    473   *
    474   * Unimplemented opcodes are ignored.
    475   *
    476   */
    477  FT_LOCAL_DEF( void )
    478  cf2_interpT2CharString( CF2_Font              font,
    479                          const CF2_Buffer      buf,
    480                          CF2_OutlineCallbacks  callbacks,
    481                          const FT_Vector*      translation,
    482                          FT_Bool               doingSeac,
    483                          CF2_Fixed             curX,
    484                          CF2_Fixed             curY,
    485                          CF2_Fixed*            width )
    486  {
    487    /* lastError is used for errors that are immediately tested */
    488    FT_Error  lastError = FT_Err_Ok;
    489 
    490    /* pointer to parsed font object */
    491    PS_Decoder*  decoder = font->decoder;
    492 
    493    FT_Error*  error  = &font->error;
    494    FT_Memory  memory = font->memory;
    495 
    496    CF2_Fixed  scaleY        = font->innerTransform.d;
    497    CF2_Fixed  nominalWidthX = cf2_getNominalWidthX( decoder );
    498 
    499    /* stuff for Type 1 */
    500    FT_Int   known_othersubr_result_cnt = 0;
    501    FT_Bool  large_int                  = FALSE;
    502    FT_Bool  initial_map_ready          = FALSE;
    503 
    504 #define PS_STORAGE_SIZE 3
    505    CF2_F16Dot16  results[PS_STORAGE_SIZE];   /* for othersubr results */
    506    FT_Int        result_cnt = 0;
    507 
    508    /* save this for hinting seac accents */
    509    CF2_Fixed  hintOriginY = curY;
    510 
    511    CF2_Stack  opStack = NULL;
    512    FT_UInt    stackSize;
    513    FT_Byte    op1;                       /* first opcode byte */
    514 
    515    CF2_F16Dot16  storage[CF2_STORAGE_SIZE];    /* for `put' and `get' */
    516    CF2_F16Dot16  flexStore[6];                 /* for Type 1 flex     */
    517 
    518    /* instruction limit; 20,000,000 matches Avalon */
    519    FT_UInt32  instructionLimit = 20000000UL;
    520 
    521    CF2_ArrStackRec  subrStack;
    522 
    523    FT_Bool     haveWidth;
    524    CF2_Buffer  charstring = NULL;
    525 
    526    CF2_Int  charstringIndex = -1;       /* initialize to empty */
    527 
    528    /* TODO: placeholders for hint structures */
    529 
    530    /* objects used for hinting */
    531    CF2_ArrStackRec  hStemHintArray;
    532    CF2_ArrStackRec  vStemHintArray;
    533 
    534    CF2_HintMaskRec   hintMask;
    535    CF2_GlyphPathRec  glyphPath;
    536 
    537 
    538    FT_ZERO( &storage );
    539    FT_ZERO( &results );
    540    FT_ZERO( &flexStore );
    541 
    542    /* initialize the remaining objects */
    543    cf2_arrstack_init( &subrStack,
    544                       memory,
    545                       error,
    546                       sizeof ( CF2_BufferRec ) );
    547    cf2_arrstack_init( &hStemHintArray,
    548                       memory,
    549                       error,
    550                       sizeof ( CF2_StemHintRec ) );
    551    cf2_arrstack_init( &vStemHintArray,
    552                       memory,
    553                       error,
    554                       sizeof ( CF2_StemHintRec ) );
    555 
    556    /* initialize CF2_StemHint arrays */
    557    cf2_hintmask_init( &hintMask, error );
    558 
    559    /* initialize path map to manage drawing operations */
    560 
    561    /* Note: last 4 params are used to handle `MoveToPermissive', which */
    562    /*       may need to call `hintMap.Build'                           */
    563    /* TODO: MoveToPermissive is gone; are these still needed?          */
    564    cf2_glyphpath_init( &glyphPath,
    565                        font,
    566                        callbacks,
    567                        scaleY,
    568                        /* hShift, */
    569                        &hStemHintArray,
    570                        &vStemHintArray,
    571                        &hintMask,
    572                        hintOriginY,
    573                        &font->blues,
    574                        translation );
    575 
    576    /*
    577     * Initialize state for width parsing.  From the CFF Spec:
    578     *
    579     *   The first stack-clearing operator, which must be one of hstem,
    580     *   hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
    581     *   rmoveto, or endchar, takes an additional argument - the width (as
    582     *   described earlier), which may be expressed as zero or one numeric
    583     *   argument.
    584     *
    585     * What we implement here uses the first validly specified width, but
    586     * does not detect errors for specifying more than one width.
    587     *
    588     * If one of the above operators occurs without explicitly specifying
    589     * a width, we assume the default width.
    590     *
    591     * CFF2 charstrings always return the default width (0).
    592     *
    593     */
    594    haveWidth = font->isCFF2 ? TRUE : FALSE;
    595    *width    = cf2_getDefaultWidthX( decoder );
    596 
    597    /*
    598     * Note: At this point, all pointers to resources must be NULL
    599     *       and all local objects must be initialized.
    600     *       There must be no branches to `exit:' above this point.
    601     *
    602     */
    603 
    604    /* allocate an operand stack */
    605    stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
    606                             : CF2_OPERAND_STACK_SIZE;
    607    opStack   = cf2_stack_init( memory, error, stackSize );
    608 
    609    if ( !opStack )
    610    {
    611      lastError = FT_THROW( Out_Of_Memory );
    612      goto exit;
    613    }
    614 
    615    /* initialize subroutine stack by placing top level charstring as */
    616    /* first element (max depth plus one for the charstring)          */
    617    /* Note: Caller owns and must finalize the first charstring.      */
    618    /*       Our copy of it does not change that requirement.         */
    619    cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
    620 
    621    charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
    622 
    623    /* catch errors so far */
    624    if ( *error )
    625      goto exit;
    626 
    627    *charstring     = *buf;    /* structure copy     */
    628    charstringIndex = 0;       /* entry is valid now */
    629 
    630    /* main interpreter loop */
    631    while ( 1 )
    632    {
    633      if ( font->isT1 )
    634        FT_ASSERT( known_othersubr_result_cnt == 0 ||
    635                   result_cnt == 0                 );
    636 
    637      if ( cf2_buf_isEnd( charstring ) )
    638      {
    639        /* If we've reached the end of the charstring, simulate a */
    640        /* cf2_cmdRETURN or cf2_cmdENDCHAR.                       */
    641        /* We do this for both CFF and CFF2.                      */
    642        if ( charstringIndex )
    643          op1 = cf2_cmdRETURN;  /* end of buffer for subroutine */
    644        else
    645          op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
    646      }
    647      else
    648      {
    649        op1 = (FT_Byte)cf2_buf_readByte( charstring );
    650 
    651        /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
    652        /* Note: Trace message will report 0 instead of 11 or 14. */
    653        if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) &&
    654             font->isCFF2                                      )
    655          op1 = cf2_cmdRESERVED_0;
    656      }
    657 
    658      if ( font->isT1 )
    659      {
    660        if ( !initial_map_ready           &&
    661             !( op1 == cf2_cmdHSTEM     ||
    662                op1 == cf2_cmdVSTEM     ||
    663                op1 == cf2_cmdHSBW      ||
    664                op1 == cf2_cmdCALLSUBR  ||
    665                op1 == cf2_cmdRETURN    ||
    666                op1 == cf2_cmdESC       ||
    667                op1 == cf2_cmdENDCHAR   ||
    668                op1 >= 32 /* Numbers */ ) )
    669        {
    670          /* Skip outline commands first time round.       */
    671          /* `endchar' will trigger initial hintmap build  */
    672          /* and rewind the charstring.                    */
    673          FT_TRACE4(( " <outline command skipped>\n" ));
    674          cf2_stack_clear( opStack );
    675          continue;
    676        }
    677 
    678        if ( result_cnt > 0               &&
    679             !( op1 == cf2_cmdCALLSUBR  ||
    680                op1 == cf2_cmdRETURN    ||
    681                op1 == cf2_cmdESC       ||
    682                op1 >= 32 /* Numbers */ ) )
    683        {
    684          /* all operands have been transferred by previous pops */
    685          result_cnt = 0;
    686        }
    687 
    688        if ( large_int && !( op1 >= 32 || op1 == cf2_escDIV ) )
    689        {
    690          FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
    691                     " no `div' after large integer\n" ));
    692 
    693          large_int = FALSE;
    694        }
    695      }
    696 
    697      /* check for errors once per loop */
    698      if ( *error )
    699        goto exit;
    700 
    701      instructionLimit--;
    702      if ( instructionLimit == 0 )
    703      {
    704        lastError = FT_THROW( Invalid_Glyph_Format );
    705        goto exit;
    706      }
    707 
    708      switch( op1 )
    709      {
    710      case cf2_cmdRESERVED_0:
    711      case cf2_cmdRESERVED_2:
    712      case cf2_cmdRESERVED_17:
    713        /* we may get here if we have a prior error */
    714        FT_TRACE4(( " unknown op (%d)\n", op1 ));
    715        break;
    716 
    717      case cf2_cmdVSINDEX:
    718        FT_TRACE4(( " vsindex\n" ));
    719 
    720        if ( !font->isCFF2 )
    721          break;    /* clear stack & ignore */
    722 
    723        if ( font->blend.usedBV )
    724        {
    725          /* vsindex not allowed after blend */
    726          lastError = FT_THROW( Invalid_Glyph_Format );
    727          goto exit;
    728        }
    729 
    730        {
    731          FT_Int  temp = cf2_stack_popInt( opStack );
    732 
    733 
    734          if ( temp >= 0 )
    735            font->vsindex = (FT_UInt)temp;
    736        }
    737        break;
    738 
    739      case cf2_cmdBLEND:
    740        {
    741          FT_UInt  numBlends;
    742 
    743 
    744          FT_TRACE4(( " blend" ));
    745 
    746          if ( !font->isCFF2 )
    747            break;    /* clear stack & ignore */
    748 
    749          /* do we have a `blend' op in a non-variant font? */
    750          if ( !font->blend.font )
    751          {
    752            lastError = FT_THROW( Invalid_Glyph_Format );
    753            goto exit;
    754          }
    755 
    756          /* check cached blend vector */
    757          if ( font->cffload->blend_check_vector( &font->blend,
    758                                                  font->vsindex,
    759                                                  font->lenNDV,
    760                                                  font->NDV ) )
    761          {
    762            lastError = font->cffload->blend_build_vector( &font->blend,
    763                                                           font->vsindex,
    764                                                           font->lenNDV,
    765                                                           font->NDV );
    766            if ( lastError )
    767              goto exit;
    768          }
    769 
    770          /* do the blend */
    771          numBlends = (FT_UInt)cf2_stack_popInt( opStack );
    772          if ( numBlends > stackSize )
    773          {
    774            lastError = FT_THROW( Invalid_Glyph_Format );
    775            goto exit;
    776          }
    777 
    778          cf2_doBlend( &font->blend, opStack, numBlends );
    779 
    780          font->blend.usedBV = TRUE;
    781        }
    782        continue;     /* do not clear the stack */
    783 
    784      case cf2_cmdHSTEMHM:
    785      case cf2_cmdHSTEM:
    786        FT_TRACE4(( "%s\n", op1 == cf2_cmdHSTEMHM ? " hstemhm"
    787                                                  : " hstem" ));
    788 
    789        if ( !font->isT1 )
    790        {
    791          /* never add hints after the mask is computed */
    792          /* except if in Type 1 mode (no hintmask op)  */
    793          if ( cf2_hintmask_isValid( &hintMask ) )
    794          {
    795            FT_TRACE4(( "cf2_interpT2CharString:"
    796                        " invalid horizontal hint mask\n" ));
    797            break;
    798          }
    799        }
    800 
    801        /* add left-sidebearing correction in Type 1 mode */
    802        cf2_doStems( font,
    803                     opStack,
    804                     &hStemHintArray,
    805                     width,
    806                     &haveWidth,
    807                     font->isT1 ? decoder->builder.left_bearing->y
    808                                : 0 );
    809 
    810        if ( decoder->width_only )
    811          goto exit;
    812 
    813        break;
    814 
    815      case cf2_cmdVSTEMHM:
    816      case cf2_cmdVSTEM:
    817        FT_TRACE4(( "%s\n", op1 == cf2_cmdVSTEMHM ? " vstemhm"
    818                                                  : " vstem" ));
    819 
    820        if ( !font->isT1 )
    821        {
    822          /* never add hints after the mask is computed */
    823          /* except if in Type 1 mode (no hintmask op)  */
    824          if ( cf2_hintmask_isValid( &hintMask ) )
    825          {
    826            FT_TRACE4(( "cf2_interpT2CharString:"
    827                        " invalid vertical hint mask\n" ));
    828            break;
    829          }
    830        }
    831 
    832        /* add left-sidebearing correction in Type 1 mode */
    833        cf2_doStems( font,
    834                     opStack,
    835                     &vStemHintArray,
    836                     width,
    837                     &haveWidth,
    838                     font->isT1 ? decoder->builder.left_bearing->x
    839                                : 0 );
    840 
    841        if ( decoder->width_only )
    842          goto exit;
    843 
    844        break;
    845 
    846      case cf2_cmdVMOVETO:
    847        FT_TRACE4(( " vmoveto\n" ));
    848 
    849        if ( font->isT1 && !decoder->flex_state && !haveWidth )
    850          FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
    851                     " No width. Use hsbw/sbw as first op\n" ));
    852 
    853        if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
    854          *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
    855                              nominalWidthX );
    856 
    857        /* width is defined or default after this */
    858        haveWidth = TRUE;
    859 
    860        if ( decoder->width_only )
    861          goto exit;
    862 
    863        curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
    864 
    865        if ( !decoder->flex_state )
    866          cf2_glyphpath_moveTo( &glyphPath, curX, curY );
    867 
    868        break;
    869 
    870      case cf2_cmdRLINETO:
    871        {
    872          CF2_UInt  idx;
    873          CF2_UInt  count = cf2_stack_count( opStack );
    874 
    875 
    876          FT_TRACE4(( " rlineto\n" ));
    877 
    878          for ( idx = 0; idx < count; idx += 2 )
    879          {
    880            curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
    881                                                       idx + 0 ) );
    882            curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
    883                                                       idx + 1 ) );
    884 
    885            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
    886          }
    887 
    888          cf2_stack_clear( opStack );
    889        }
    890        continue; /* no need to clear stack again */
    891 
    892      case cf2_cmdHLINETO:
    893      case cf2_cmdVLINETO:
    894        {
    895          CF2_UInt  idx;
    896          CF2_UInt  count = cf2_stack_count( opStack );
    897 
    898          FT_Bool  isX = FT_BOOL( op1 == cf2_cmdHLINETO );
    899 
    900 
    901          FT_TRACE4(( "%s\n", isX ? " hlineto" : " vlineto" ));
    902 
    903          for ( idx = 0; idx < count; idx++ )
    904          {
    905            CF2_Fixed  v = cf2_stack_getReal( opStack, idx );
    906 
    907 
    908            if ( isX )
    909              curX = ADD_INT32( curX, v );
    910            else
    911              curY = ADD_INT32( curY, v );
    912 
    913            isX = !isX;
    914 
    915            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
    916          }
    917 
    918          cf2_stack_clear( opStack );
    919        }
    920        continue;
    921 
    922      case cf2_cmdRCURVELINE:
    923      case cf2_cmdRRCURVETO:
    924        {
    925          CF2_UInt  count = cf2_stack_count( opStack );
    926          CF2_UInt  idx   = 0;
    927 
    928 
    929          FT_TRACE4(( "%s\n", op1 == cf2_cmdRCURVELINE ? " rcurveline"
    930                                                       : " rrcurveto" ));
    931 
    932          while ( idx + 6 <= count )
    933          {
    934            CF2_Fixed  x1, y1, x2, y2, x3, y3;
    935 
    936 
    937            x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
    938            y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
    939            x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
    940            y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
    941            x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
    942            y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
    943 
    944            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
    945 
    946            curX  = x3;
    947            curY  = y3;
    948            idx  += 6;
    949          }
    950 
    951          if ( op1 == cf2_cmdRCURVELINE )
    952          {
    953            curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
    954                                                       idx + 0 ) );
    955            curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
    956                                                       idx + 1 ) );
    957 
    958            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
    959          }
    960 
    961          cf2_stack_clear( opStack );
    962        }
    963        continue; /* no need to clear stack again */
    964 
    965      case cf2_cmdCLOSEPATH:
    966        if ( !font->isT1 )
    967          FT_TRACE4(( " unknown op (%d)\n", op1 ));
    968        else
    969        {
    970          FT_TRACE4(( " closepath\n" ));
    971 
    972          /* if there is no path, `closepath' is a no-op */
    973          cf2_glyphpath_closeOpenPath( &glyphPath );
    974 
    975          haveWidth = TRUE;
    976        }
    977        break;
    978 
    979      case cf2_cmdCALLGSUBR:
    980      case cf2_cmdCALLSUBR:
    981        {
    982          CF2_Int  subrNum;
    983 
    984 
    985          FT_TRACE4(( "%s", op1 == cf2_cmdCALLGSUBR ? " callgsubr"
    986                                                    : " callsubr" ));
    987 
    988          if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR )       ||
    989               (  font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) )
    990          {
    991            /* max subr plus one for charstring */
    992            lastError = FT_THROW( Invalid_Glyph_Format );
    993            goto exit;                      /* overflow of stack */
    994          }
    995 
    996          /* push our current CFF charstring region on subrStack */
    997          charstring = (CF2_Buffer)
    998                         cf2_arrstack_getPointer(
    999                           &subrStack,
   1000                           (size_t)charstringIndex + 1 );
   1001 
   1002          /* set up the new CFF region and pointer */
   1003          subrNum = cf2_stack_popInt( opStack );
   1004 
   1005          if ( font->isT1 && decoder->locals_hash )
   1006          {
   1007            size_t*  val = ft_hash_num_lookup( subrNum,
   1008                                               decoder->locals_hash );
   1009 
   1010 
   1011            if ( val )
   1012              subrNum = *val;
   1013            else
   1014              subrNum = -1;
   1015          }
   1016 
   1017          switch ( op1 )
   1018          {
   1019          case cf2_cmdCALLGSUBR:
   1020            FT_TRACE4(( " (idx %d, entering level %d)\n",
   1021                        subrNum + decoder->globals_bias,
   1022                        charstringIndex + 1 ));
   1023 
   1024            if ( cf2_initGlobalRegionBuffer( decoder,
   1025                                             subrNum,
   1026                                             charstring ) )
   1027            {
   1028              lastError = FT_THROW( Invalid_Glyph_Format );
   1029              goto exit;  /* subroutine lookup or stream error */
   1030            }
   1031            break;
   1032 
   1033          default:
   1034            /* cf2_cmdCALLSUBR */
   1035            FT_TRACE4(( " (idx %d, entering level %d)\n",
   1036                        subrNum + decoder->locals_bias,
   1037                        charstringIndex + 1 ));
   1038 
   1039            if ( cf2_initLocalRegionBuffer( decoder,
   1040                                            subrNum,
   1041                                            charstring ) )
   1042            {
   1043              lastError = FT_THROW( Invalid_Glyph_Format );
   1044              goto exit;  /* subroutine lookup or stream error */
   1045            }
   1046          }
   1047 
   1048          charstringIndex += 1;       /* entry is valid now */
   1049        }
   1050        continue; /* do not clear the stack */
   1051 
   1052      case cf2_cmdRETURN:
   1053        FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
   1054 
   1055        if ( charstringIndex < 1 )
   1056        {
   1057          /* Note: cannot return from top charstring */
   1058          lastError = FT_THROW( Invalid_Glyph_Format );
   1059          goto exit;                      /* underflow of stack */
   1060        }
   1061 
   1062        /* restore position in previous charstring */
   1063        charstring = (CF2_Buffer)
   1064                       cf2_arrstack_getPointer(
   1065                         &subrStack,
   1066                         (CF2_UInt)--charstringIndex );
   1067        continue;     /* do not clear the stack */
   1068 
   1069      case cf2_cmdESC:
   1070        {
   1071          FT_Byte  op2 = (FT_Byte)cf2_buf_readByte( charstring );
   1072 
   1073 
   1074          /* first switch for 2-byte operators handles CFF2      */
   1075          /* and opcodes that are reserved for both CFF and CFF2 */
   1076          switch ( op2 )
   1077          {
   1078          case cf2_escHFLEX:
   1079            {
   1080              static const FT_Bool  readFromStack[12] =
   1081              {
   1082                TRUE /* dx1 */, FALSE /* dy1 */,
   1083                TRUE /* dx2 */, TRUE  /* dy2 */,
   1084                TRUE /* dx3 */, FALSE /* dy3 */,
   1085                TRUE /* dx4 */, FALSE /* dy4 */,
   1086                TRUE /* dx5 */, FALSE /* dy5 */,
   1087                TRUE /* dx6 */, FALSE /* dy6 */
   1088              };
   1089 
   1090 
   1091              FT_TRACE4(( " hflex\n" ));
   1092 
   1093              cf2_doFlex( opStack,
   1094                          &curX,
   1095                          &curY,
   1096                          &glyphPath,
   1097                          readFromStack,
   1098                          FALSE /* doConditionalLastRead */ );
   1099            }
   1100            continue;
   1101 
   1102          case cf2_escFLEX:
   1103            {
   1104              static const FT_Bool  readFromStack[12] =
   1105              {
   1106                TRUE /* dx1 */, TRUE /* dy1 */,
   1107                TRUE /* dx2 */, TRUE /* dy2 */,
   1108                TRUE /* dx3 */, TRUE /* dy3 */,
   1109                TRUE /* dx4 */, TRUE /* dy4 */,
   1110                TRUE /* dx5 */, TRUE /* dy5 */,
   1111                TRUE /* dx6 */, TRUE /* dy6 */
   1112              };
   1113 
   1114 
   1115              FT_TRACE4(( " flex\n" ));
   1116 
   1117              cf2_doFlex( opStack,
   1118                          &curX,
   1119                          &curY,
   1120                          &glyphPath,
   1121                          readFromStack,
   1122                          FALSE /* doConditionalLastRead */ );
   1123            }
   1124            break;      /* TODO: why is this not a continue? */
   1125 
   1126          case cf2_escHFLEX1:
   1127            {
   1128              static const FT_Bool  readFromStack[12] =
   1129              {
   1130                TRUE /* dx1 */, TRUE  /* dy1 */,
   1131                TRUE /* dx2 */, TRUE  /* dy2 */,
   1132                TRUE /* dx3 */, FALSE /* dy3 */,
   1133                TRUE /* dx4 */, FALSE /* dy4 */,
   1134                TRUE /* dx5 */, TRUE  /* dy5 */,
   1135                TRUE /* dx6 */, FALSE /* dy6 */
   1136              };
   1137 
   1138 
   1139              FT_TRACE4(( " hflex1\n" ));
   1140 
   1141              cf2_doFlex( opStack,
   1142                          &curX,
   1143                          &curY,
   1144                          &glyphPath,
   1145                          readFromStack,
   1146                          FALSE /* doConditionalLastRead */ );
   1147            }
   1148            continue;
   1149 
   1150          case cf2_escFLEX1:
   1151            {
   1152              static const FT_Bool  readFromStack[12] =
   1153              {
   1154                TRUE  /* dx1 */, TRUE  /* dy1 */,
   1155                TRUE  /* dx2 */, TRUE  /* dy2 */,
   1156                TRUE  /* dx3 */, TRUE  /* dy3 */,
   1157                TRUE  /* dx4 */, TRUE  /* dy4 */,
   1158                TRUE  /* dx5 */, TRUE  /* dy5 */,
   1159                FALSE /* dx6 */, FALSE /* dy6 */
   1160              };
   1161 
   1162 
   1163              FT_TRACE4(( " flex1\n" ));
   1164 
   1165              cf2_doFlex( opStack,
   1166                          &curX,
   1167                          &curY,
   1168                          &glyphPath,
   1169                          readFromStack,
   1170                          TRUE /* doConditionalLastRead */ );
   1171            }
   1172            continue;
   1173 
   1174          /* these opcodes are always reserved */
   1175          case cf2_escRESERVED_8:
   1176          case cf2_escRESERVED_13:
   1177          case cf2_escRESERVED_19:
   1178          case cf2_escRESERVED_25:
   1179          case cf2_escRESERVED_31:
   1180          case cf2_escRESERVED_32:
   1181            FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1182            break;
   1183 
   1184          default:
   1185            {
   1186              if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
   1187                FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1188              else if ( font->isT1 && result_cnt > 0 && op2 != cf2_escPOP )
   1189              {
   1190                /* all operands have been transferred by previous pops */
   1191                result_cnt = 0;
   1192              }
   1193              else
   1194              {
   1195                /* second switch for 2-byte operators handles */
   1196                /* CFF and Type 1                             */
   1197                switch ( op2 )
   1198                {
   1199 
   1200                case cf2_escDOTSECTION:
   1201                  /* something about `flip type of locking' -- ignore it */
   1202                  FT_TRACE4(( " dotsection\n" ));
   1203 
   1204                  break;
   1205 
   1206                case cf2_escVSTEM3:
   1207                case cf2_escHSTEM3:
   1208                  /*
   1209                   * Type 1:                          Type 2:
   1210                   *   x0 dx0 x1 dx1 x2 dx2 vstem3      x dx {dxa dxb}* vstem
   1211                   *   y0 dy0 y1 dy1 y2 dy2 hstem3      y dy {dya dyb}* hstem
   1212                   *   relative to lsb point            relative to zero
   1213                   *
   1214                   */
   1215                  {
   1216                    if ( !font->isT1 )
   1217                      FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1218                    else
   1219                    {
   1220                      CF2_F16Dot16  v0, v1, v2;
   1221 
   1222                      FT_Bool  isV = FT_BOOL( op2 == cf2_escVSTEM3 );
   1223 
   1224 
   1225                      FT_TRACE4(( "%s\n", isV ? " vstem3"
   1226                                              : " hstem3" ));
   1227 
   1228                      FT_ASSERT( cf2_stack_count( opStack ) == 6 );
   1229 
   1230                      v0 = cf2_stack_getReal( opStack, 0 );
   1231                      v1 = cf2_stack_getReal( opStack, 2 );
   1232                      v2 = cf2_stack_getReal( opStack, 4 );
   1233 
   1234                      cf2_stack_setReal(
   1235                        opStack, 2,
   1236                        SUB_INT32( SUB_INT32( v1, v0 ),
   1237                                   cf2_stack_getReal( opStack, 1 ) ) );
   1238                      cf2_stack_setReal(
   1239                        opStack, 4,
   1240                        SUB_INT32( SUB_INT32( v2, v1 ),
   1241                                   cf2_stack_getReal( opStack, 3 ) ) );
   1242 
   1243                      /* add left-sidebearing correction */
   1244                      cf2_doStems( font,
   1245                                   opStack,
   1246                                   isV ? &vStemHintArray : &hStemHintArray,
   1247                                   width,
   1248                                   &haveWidth,
   1249                                   isV ? decoder->builder.left_bearing->x
   1250                                       : decoder->builder.left_bearing->y );
   1251 
   1252                      if ( decoder->width_only )
   1253                        goto exit;
   1254                    }
   1255                  }
   1256                  break;
   1257 
   1258                case cf2_escAND:
   1259                  {
   1260                    CF2_F16Dot16  arg1;
   1261                    CF2_F16Dot16  arg2;
   1262 
   1263 
   1264                    FT_TRACE4(( " and\n" ));
   1265 
   1266                    arg2 = cf2_stack_popFixed( opStack );
   1267                    arg1 = cf2_stack_popFixed( opStack );
   1268 
   1269                    cf2_stack_pushInt( opStack, arg1 && arg2 );
   1270                  }
   1271                  continue; /* do not clear the stack */
   1272 
   1273                case cf2_escOR:
   1274                  {
   1275                    CF2_F16Dot16  arg1;
   1276                    CF2_F16Dot16  arg2;
   1277 
   1278 
   1279                    FT_TRACE4(( " or\n" ));
   1280 
   1281                    arg2 = cf2_stack_popFixed( opStack );
   1282                    arg1 = cf2_stack_popFixed( opStack );
   1283 
   1284                    cf2_stack_pushInt( opStack, arg1 || arg2 );
   1285                  }
   1286                  continue; /* do not clear the stack */
   1287 
   1288                case cf2_escNOT:
   1289                  {
   1290                    CF2_F16Dot16  arg;
   1291 
   1292 
   1293                    FT_TRACE4(( " not\n" ));
   1294 
   1295                    arg = cf2_stack_popFixed( opStack );
   1296 
   1297                    cf2_stack_pushInt( opStack, !arg );
   1298                  }
   1299                  continue; /* do not clear the stack */
   1300 
   1301                case cf2_escSEAC:
   1302                  if ( !font->isT1 )
   1303                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1304                  else
   1305                  {
   1306                    FT_Error   error2;
   1307                    CF2_Int    bchar_index, achar_index;
   1308                    FT_Vector  left_bearing, advance;
   1309 
   1310 #ifdef FT_CONFIG_OPTION_INCREMENTAL
   1311                    T1_Face  face = (T1_Face)decoder->builder.face;
   1312 #endif
   1313                    CF2_BufferRec  component;
   1314                    CF2_Fixed      dummyWidth;
   1315 
   1316                    CF2_Int  achar = cf2_stack_popInt( opStack );
   1317                    CF2_Int  bchar = cf2_stack_popInt( opStack );
   1318 
   1319                    FT_Pos  ady = cf2_stack_popFixed ( opStack );
   1320                    FT_Pos  adx = cf2_stack_popFixed ( opStack );
   1321                    FT_Pos  asb = cf2_stack_popFixed ( opStack );
   1322 
   1323 
   1324                    FT_TRACE4(( " seac\n" ));
   1325 
   1326                    if ( doingSeac )
   1327                    {
   1328                      FT_ERROR(( " nested seac\n" ));
   1329                      lastError = FT_THROW( Invalid_Glyph_Format );
   1330                      goto exit;      /* nested seac */
   1331                    }
   1332 
   1333                    if ( decoder->builder.metrics_only )
   1334                    {
   1335                      FT_ERROR(( " unexpected seac\n" ));
   1336                      lastError = FT_THROW( Invalid_Glyph_Format );
   1337                      goto exit;      /* unexpected seac */
   1338                    }
   1339 
   1340                    /* `glyph_names' is set to 0 for CID fonts which do */
   1341                    /* not include an encoding.  How can we deal with   */
   1342                    /* these?                                           */
   1343 #ifdef FT_CONFIG_OPTION_INCREMENTAL
   1344                    if ( decoder->glyph_names == 0                   &&
   1345                         !face->root.internal->incremental_interface )
   1346 #else
   1347                      if ( decoder->glyph_names == 0 )
   1348 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
   1349                      {
   1350                        FT_ERROR(( "cf2_interpT2CharString:\n" ));
   1351                        FT_ERROR(( "  (Type 1 seac) glyph names table"
   1352                                   " not available in this font\n" ));
   1353                        lastError = FT_THROW( Invalid_Glyph_Format );
   1354                        goto exit;
   1355                      }
   1356 
   1357                    /* seac weirdness */
   1358                    adx += decoder->builder.left_bearing->x;
   1359 
   1360 #ifdef FT_CONFIG_OPTION_INCREMENTAL
   1361                    if ( face->root.internal->incremental_interface )
   1362                    {
   1363                      /* the caller must handle the font encoding also */
   1364                      bchar_index = bchar;
   1365                      achar_index = achar;
   1366                    }
   1367                    else
   1368 #endif
   1369                    {
   1370                      bchar_index = t1_lookup_glyph_by_stdcharcode_ps(
   1371                                      decoder, bchar );
   1372                      achar_index = t1_lookup_glyph_by_stdcharcode_ps(
   1373                                      decoder, achar );
   1374                    }
   1375 
   1376                    if ( bchar_index < 0 || achar_index < 0 )
   1377                    {
   1378                      FT_ERROR(( "cf2_interpT2CharString:\n" ));
   1379                      FT_ERROR(( "  (Type 1 seac) invalid"
   1380                                 " seac character code arguments\n" ));
   1381                      lastError = FT_THROW( Invalid_Glyph_Format );
   1382                      goto exit;
   1383                    }
   1384 
   1385                    /* if we are trying to load a composite glyph, */
   1386                    /* do not load the accent character and return */
   1387                    /* the array of subglyphs.                     */
   1388                    if ( decoder->builder.no_recurse )
   1389                    {
   1390                      FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
   1391                      FT_GlyphLoader  loader = glyph->internal->loader;
   1392                      FT_SubGlyph     subg;
   1393 
   1394 
   1395                      /* reallocate subglyph array if necessary */
   1396                      error2 = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
   1397                      if ( error2 )
   1398                      {
   1399                        lastError = error2; /* pass FreeType error through */
   1400                        goto exit;
   1401                      }
   1402 
   1403                      subg = loader->current.subglyphs;
   1404 
   1405                      /* subglyph 0 = base character */
   1406                      subg->index = bchar_index;
   1407                      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
   1408                                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
   1409                      subg->arg1  = 0;
   1410                      subg->arg2  = 0;
   1411                      subg++;
   1412 
   1413                      /* subglyph 1 = accent character */
   1414                      subg->index = achar_index;
   1415                      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
   1416                      subg->arg1  = (FT_Int)FIXED_TO_INT( adx - asb );
   1417                      subg->arg2  = (FT_Int)FIXED_TO_INT( ady );
   1418 
   1419                      /* set up remaining glyph fields */
   1420                      glyph->num_subglyphs = 2;
   1421                      glyph->subglyphs     = loader->base.subglyphs;
   1422                      glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
   1423 
   1424                      loader->current.num_subglyphs = 2;
   1425 
   1426                      goto exit;
   1427                    }
   1428 
   1429                    /* First load `bchar' in builder */
   1430                    /* now load the unscaled outline */
   1431 
   1432                    /* prepare loader */
   1433                    FT_GlyphLoader_Prepare( decoder->builder.loader );
   1434 
   1435                    error2 = cf2_getT1SeacComponent( decoder,
   1436                                                     (FT_UInt)bchar_index,
   1437                                                     &component );
   1438                    if ( error2 )
   1439                    {
   1440                      lastError = error2; /* pass FreeType error through */
   1441                      goto exit;
   1442                    }
   1443 
   1444                    /* save the left bearing and width of the SEAC   */
   1445                    /* glyph as they will be erased by the next load */
   1446 
   1447                    left_bearing = *decoder->builder.left_bearing;
   1448                    advance      = *decoder->builder.advance;
   1449 
   1450                    cf2_interpT2CharString( font,
   1451                                            &component,
   1452                                            callbacks,
   1453                                            translation,
   1454                                            TRUE,
   1455                                            0,
   1456                                            0,
   1457                                            &dummyWidth );
   1458                    cf2_freeT1SeacComponent( decoder, &component );
   1459 
   1460                    /* If the SEAC glyph doesn't have a (H)SBW of its */
   1461                    /* own use the values from the base glyph.        */
   1462 
   1463                    if ( !haveWidth )
   1464                    {
   1465                      left_bearing = *decoder->builder.left_bearing;
   1466                      advance      = *decoder->builder.advance;
   1467                    }
   1468 
   1469                    decoder->builder.left_bearing->x = 0;
   1470                    decoder->builder.left_bearing->y = 0;
   1471 
   1472                    /* Now load `achar' on top of */
   1473                    /* the base outline           */
   1474 
   1475                    error2 = cf2_getT1SeacComponent( decoder,
   1476                                                     (FT_UInt)achar_index,
   1477                                                     &component );
   1478                    if ( error2 )
   1479                    {
   1480                      lastError = error2; /* pass FreeType error through */
   1481                      goto exit;
   1482                    }
   1483                    cf2_interpT2CharString( font,
   1484                                            &component,
   1485                                            callbacks,
   1486                                            translation,
   1487                                            TRUE,
   1488                                            adx - asb,
   1489                                            ady,
   1490                                            &dummyWidth );
   1491                    cf2_freeT1SeacComponent( decoder, &component );
   1492 
   1493                    /* restore the left side bearing and advance width   */
   1494                    /* of the SEAC glyph or base character (saved above) */
   1495 
   1496                    *decoder->builder.left_bearing = left_bearing;
   1497                    *decoder->builder.advance      = advance;
   1498 
   1499                    goto exit;
   1500                  }
   1501                  break;
   1502 
   1503                case cf2_escSBW:
   1504                  if ( !font->isT1 )
   1505                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1506                  else
   1507                  {
   1508                    CF2_Fixed    lsb_x, lsb_y;
   1509                    PS_Builder*  builder;
   1510 
   1511 
   1512                    FT_TRACE4(( " sbw" ));
   1513 
   1514                    builder = &decoder->builder;
   1515 
   1516                    builder->advance->y = cf2_stack_popFixed( opStack );
   1517                    builder->advance->x = cf2_stack_popFixed( opStack );
   1518 
   1519                    lsb_y = cf2_stack_popFixed( opStack );
   1520                    lsb_x = cf2_stack_popFixed( opStack );
   1521 
   1522                    builder->left_bearing->x =
   1523                      ADD_INT32( builder->left_bearing->x, lsb_x );
   1524                    builder->left_bearing->y =
   1525                      ADD_INT32( builder->left_bearing->y, lsb_y );
   1526 
   1527                    haveWidth = TRUE;
   1528 
   1529                    /* the `metrics_only' indicates that we only want */
   1530                    /* to compute the glyph's metrics (lsb + advance  */
   1531                    /* width), not load the  rest of it; so exit      */
   1532                    /* immediately                                    */
   1533                    if ( builder->metrics_only )
   1534                      goto exit;
   1535 
   1536                    if ( initial_map_ready )
   1537                    {
   1538                      curX = ADD_INT32( curX, lsb_x );
   1539                      curY = ADD_INT32( curY, lsb_y );
   1540                    }
   1541                  }
   1542                  break;
   1543 
   1544                case cf2_escABS:
   1545                  {
   1546                    CF2_F16Dot16  arg;
   1547 
   1548 
   1549                    FT_TRACE4(( " abs\n" ));
   1550 
   1551                    arg = cf2_stack_popFixed( opStack );
   1552 
   1553                    if ( arg < -CF2_FIXED_MAX )
   1554                      cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
   1555                    else
   1556                      cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
   1557                  }
   1558                  continue; /* do not clear the stack */
   1559 
   1560                case cf2_escADD:
   1561                  {
   1562                    CF2_F16Dot16  summand1;
   1563                    CF2_F16Dot16  summand2;
   1564 
   1565 
   1566                    FT_TRACE4(( " add\n" ));
   1567 
   1568                    summand2 = cf2_stack_popFixed( opStack );
   1569                    summand1 = cf2_stack_popFixed( opStack );
   1570 
   1571                    cf2_stack_pushFixed( opStack,
   1572                                         ADD_INT32( summand1,
   1573                                                    summand2 ) );
   1574                  }
   1575                  continue; /* do not clear the stack */
   1576 
   1577                case cf2_escSUB:
   1578                  {
   1579                    CF2_F16Dot16  minuend;
   1580                    CF2_F16Dot16  subtrahend;
   1581 
   1582 
   1583                    FT_TRACE4(( " sub\n" ));
   1584 
   1585                    subtrahend = cf2_stack_popFixed( opStack );
   1586                    minuend    = cf2_stack_popFixed( opStack );
   1587 
   1588                    cf2_stack_pushFixed( opStack,
   1589                                         SUB_INT32( minuend, subtrahend ) );
   1590                  }
   1591                  continue; /* do not clear the stack */
   1592 
   1593                case cf2_escDIV:
   1594                  {
   1595                    CF2_F16Dot16  dividend;
   1596                    CF2_F16Dot16  divisor;
   1597 
   1598 
   1599                    FT_TRACE4(( " div\n" ));
   1600 
   1601                    if ( font->isT1 && large_int )
   1602                    {
   1603                      divisor  = (CF2_F16Dot16)cf2_stack_popInt( opStack );
   1604                      dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack );
   1605 
   1606                      large_int = FALSE;
   1607                    }
   1608                    else
   1609                    {
   1610                      divisor  = cf2_stack_popFixed( opStack );
   1611                      dividend = cf2_stack_popFixed( opStack );
   1612                    }
   1613 
   1614                    cf2_stack_pushFixed( opStack,
   1615                                         FT_DivFix( dividend, divisor ) );
   1616 
   1617                  }
   1618                  continue; /* do not clear the stack */
   1619 
   1620                case cf2_escNEG:
   1621                  {
   1622                    CF2_F16Dot16  arg;
   1623 
   1624 
   1625                    FT_TRACE4(( " neg\n" ));
   1626 
   1627                    arg = cf2_stack_popFixed( opStack );
   1628 
   1629                    if ( arg < -CF2_FIXED_MAX )
   1630                      cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
   1631                    else
   1632                      cf2_stack_pushFixed( opStack, -arg );
   1633                  }
   1634                  continue; /* do not clear the stack */
   1635 
   1636                case cf2_escEQ:
   1637                  {
   1638                    CF2_F16Dot16  arg1;
   1639                    CF2_F16Dot16  arg2;
   1640 
   1641 
   1642                    FT_TRACE4(( " eq\n" ));
   1643 
   1644                    arg2 = cf2_stack_popFixed( opStack );
   1645                    arg1 = cf2_stack_popFixed( opStack );
   1646 
   1647                    cf2_stack_pushInt( opStack, arg1 == arg2 );
   1648                  }
   1649                  continue; /* do not clear the stack */
   1650 
   1651                case cf2_escCALLOTHERSUBR:
   1652                  if ( !font->isT1 )
   1653                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   1654                  else
   1655                  {
   1656                    CF2_Int   subr_no;
   1657                    CF2_Int   arg_cnt;
   1658                    CF2_UInt  count;
   1659                    CF2_UInt  opIdx = 0;
   1660 
   1661 
   1662                    FT_TRACE4(( " callothersubr\n" ));
   1663 
   1664                    subr_no = cf2_stack_popInt( opStack );
   1665                    arg_cnt = cf2_stack_popInt( opStack );
   1666 
   1667                    /********************************************************
   1668                     *
   1669                     * remove all operands to callothersubr from the stack
   1670                     *
   1671                     * for handled othersubrs, where we know the number of
   1672                     * arguments, we increase the stack by the value of
   1673                     * known_othersubr_result_cnt
   1674                     *
   1675                     * for unhandled othersubrs the following pops adjust
   1676                     * the stack pointer as necessary
   1677                     */
   1678 
   1679                    count = cf2_stack_count( opStack );
   1680                    if ( (CF2_UInt)arg_cnt > count )
   1681                    {
   1682                      FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   1683                                 " stack underflow\n" ));
   1684                      lastError = FT_THROW( Invalid_Glyph_Format );
   1685                      goto exit;
   1686                    }
   1687 
   1688                    opIdx += count - (CF2_UInt)arg_cnt;
   1689 
   1690                    known_othersubr_result_cnt = 0;
   1691                    result_cnt                 = 0;
   1692 
   1693                    /* XXX TODO: The checks to `arg_count == <whatever>'   */
   1694                    /* might not be correct; an othersubr expects a        */
   1695                    /* certain number of operands on the PostScript stack  */
   1696                    /* (as opposed to the T1 stack) but it doesn't have to */
   1697                    /* put them there by itself; previous othersubrs might */
   1698                    /* have left the operands there if they were not       */
   1699                    /* followed by an appropriate number of pops           */
   1700                    /*                                                     */
   1701                    /* On the other hand, Adobe Reader 7.0.8 for Linux     */
   1702                    /* doesn't accept a font that contains charstrings     */
   1703                    /* like                                                */
   1704                    /*                                                     */
   1705                    /*     100 200 2 20 callothersubr                      */
   1706                    /*     300 1 20 callothersubr pop                      */
   1707                    /*                                                     */
   1708                    /* Perhaps this is the reason why BuildCharArray       */
   1709                    /* exists.                                             */
   1710 
   1711                    switch ( subr_no )
   1712                    {
   1713                    case 0:                     /* end flex feature */
   1714                      if ( arg_cnt != 3 )
   1715                        goto Unexpected_OtherSubr;
   1716 
   1717                      if ( initial_map_ready &&
   1718                           ( !decoder->flex_state           ||
   1719                             decoder->num_flex_vectors != 7 ) )
   1720                      {
   1721                        FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   1722                                   " unexpected flex end\n" ));
   1723                        lastError = FT_THROW( Invalid_Glyph_Format );
   1724                        goto exit;
   1725                      }
   1726 
   1727                      /* the two `results' are popped     */
   1728                      /* by the following setcurrentpoint */
   1729                      cf2_stack_pushFixed( opStack, curX );
   1730                      cf2_stack_pushFixed( opStack, curY );
   1731                      known_othersubr_result_cnt = 2;
   1732                      break;
   1733 
   1734                    case 1:                     /* start flex feature */
   1735                      if ( arg_cnt != 0 )
   1736                        goto Unexpected_OtherSubr;
   1737 
   1738                      if ( !initial_map_ready )
   1739                        break;
   1740 
   1741                      if ( ps_builder_check_points( &decoder->builder, 6 ) )
   1742                        goto exit;
   1743 
   1744                      decoder->flex_state        = 1;
   1745                      decoder->num_flex_vectors  = 0;
   1746                      break;
   1747 
   1748                    case 2:                     /* add flex vectors */
   1749                      {
   1750                        FT_Int  idx;
   1751                        FT_Int  idx2;
   1752 
   1753 
   1754                        if ( arg_cnt != 0 )
   1755                          goto Unexpected_OtherSubr;
   1756 
   1757                        if ( !initial_map_ready )
   1758                          break;
   1759 
   1760                        if ( !decoder->flex_state )
   1761                        {
   1762                          FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   1763                                     " missing flex start\n" ));
   1764                          lastError = FT_THROW( Invalid_Glyph_Format );
   1765                          goto exit;
   1766                        }
   1767 
   1768                        /* note that we should not add a point for      */
   1769                        /* index 0; this will move our current position */
   1770                        /* to the flex point without adding any point   */
   1771                        /* to the outline                               */
   1772                        idx = decoder->num_flex_vectors++;
   1773                        if ( idx > 0 && idx < 7 )
   1774                        {
   1775                          /* in malformed fonts it is possible to have    */
   1776                          /* other opcodes in the middle of a flex (which */
   1777                          /* don't increase `num_flex_vectors'); we thus  */
   1778                          /* have to check whether we can add a point     */
   1779 
   1780                          if ( ps_builder_check_points( &decoder->builder,
   1781                                                        1 ) )
   1782                          {
   1783                            lastError = FT_THROW( Invalid_Glyph_Format );
   1784                            goto exit;
   1785                          }
   1786 
   1787                          /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */
   1788                          idx2 = ( idx > 3 ? idx - 3 : idx ) * 2;
   1789 
   1790                          flexStore[idx2 - 2] = curX;
   1791                          flexStore[idx2 - 1] = curY;
   1792 
   1793                          if ( idx == 3 || idx == 6 )
   1794                            cf2_glyphpath_curveTo( &glyphPath,
   1795                                                   flexStore[0],
   1796                                                   flexStore[1],
   1797                                                   flexStore[2],
   1798                                                   flexStore[3],
   1799                                                   flexStore[4],
   1800                                                   flexStore[5] );
   1801                        }
   1802                      }
   1803                      break;
   1804 
   1805                    case 3:                     /* change hints */
   1806                      if ( arg_cnt != 1 )
   1807                        goto Unexpected_OtherSubr;
   1808 
   1809                      if ( initial_map_ready )
   1810                      {
   1811                        /* do not clear hints if initial hintmap */
   1812                        /* is not ready - we need to collate all */
   1813                        cf2_arrstack_clear( &vStemHintArray );
   1814                        cf2_arrstack_clear( &hStemHintArray );
   1815 
   1816                        cf2_hintmask_init( &hintMask, error );
   1817                        hintMask.isValid = FALSE;
   1818                        hintMask.isNew   = TRUE;
   1819                      }
   1820 
   1821                      known_othersubr_result_cnt = 1;
   1822                      break;
   1823 
   1824                    case 12:
   1825                    case 13:
   1826                      /* counter control hints, clear stack */
   1827                      cf2_stack_clear( opStack );
   1828                      break;
   1829 
   1830                    case 14:
   1831                    case 15:
   1832                    case 16:
   1833                    case 17:
   1834                    case 18:                    /* multiple masters */
   1835                      {
   1836                        PS_Blend  blend = decoder->blend;
   1837                        FT_UInt   num_points, nn, mm;
   1838                        CF2_UInt  delta;
   1839                        CF2_UInt  values;
   1840 
   1841 
   1842                        if ( !blend )
   1843                        {
   1844                          FT_ERROR((
   1845                            "cf2_interpT2CharString:"
   1846                            " unexpected multiple masters operator\n" ));
   1847                          lastError = FT_THROW( Invalid_Glyph_Format );
   1848                          goto exit;
   1849                        }
   1850 
   1851                        num_points = (FT_UInt)subr_no - 13 +
   1852                                       ( subr_no == 18 );
   1853                        if ( arg_cnt != (FT_Int)( num_points *
   1854                                                  blend->num_designs ) )
   1855                        {
   1856                          FT_ERROR((
   1857                            "cf2_interpT2CharString:"
   1858                            " incorrect number of multiple masters arguments\n" ));
   1859                          lastError = FT_THROW( Invalid_Glyph_Format );
   1860                          goto exit;
   1861                        }
   1862 
   1863                        /* We want to compute                                */
   1864                        /*                                                   */
   1865                        /*   a0*w0 + a1*w1 + ... + ak*wk                     */
   1866                        /*                                                   */
   1867                        /* but we only have a0, a1-a0, a2-a0, ..., ak-a0.    */
   1868                        /*                                                   */
   1869                        /* However, given that w0 + w1 + ... + wk == 1, we   */
   1870                        /* can rewrite it easily as                          */
   1871                        /*                                                   */
   1872                        /*   a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
   1873                        /*                                                   */
   1874                        /* where k == num_designs-1.                         */
   1875                        /*                                                   */
   1876                        /* I guess that's why it's written in this `compact' */
   1877                        /* form.                                             */
   1878                        /*                                                   */
   1879                        delta  = opIdx + num_points;
   1880                        values = opIdx;
   1881                        for ( nn = 0; nn < num_points; nn++ )
   1882                        {
   1883                          CF2_Fixed  tmp = cf2_stack_getReal( opStack,
   1884                                                              values );
   1885 
   1886 
   1887                          for ( mm = 1; mm < blend->num_designs; mm++ )
   1888                            tmp = ADD_INT32( tmp,
   1889                                             FT_MulFix(
   1890                                               cf2_stack_getReal( opStack,
   1891                                                                  delta++ ),
   1892                                               blend->weight_vector[mm] ) );
   1893 
   1894                          cf2_stack_setReal( opStack, values++, tmp );
   1895                        }
   1896                        cf2_stack_pop( opStack,
   1897                                       (CF2_UInt)arg_cnt - num_points );
   1898 
   1899                        known_othersubr_result_cnt = (FT_Int)num_points;
   1900                        break;
   1901                      }
   1902 
   1903                    case 19:
   1904                      /* <idx> 1 19 callothersubr                 */
   1905                      /* ==> replace elements starting from index */
   1906                      /*     cvi( <idx> ) of BuildCharArray with  */
   1907                      /*     WeightVector                         */
   1908                      {
   1909                        FT_UInt   idx;
   1910                        PS_Blend  blend         = decoder->blend;
   1911                        FT_UInt   len_buildchar = decoder->len_buildchar;
   1912 
   1913 
   1914                        if ( arg_cnt != 1 || !blend )
   1915                          goto Unexpected_OtherSubr;
   1916 
   1917                        idx = (FT_UInt)cf2_stack_popInt( opStack );
   1918 
   1919                        if ( len_buildchar < blend->num_designs       ||
   1920                             len_buildchar - blend->num_designs < idx )
   1921                          goto Unexpected_OtherSubr;
   1922 
   1923                        if ( decoder->buildchar && blend->weight_vector )
   1924                          ft_memcpy( &decoder->buildchar[idx],
   1925                                     blend->weight_vector,
   1926                                     blend->num_designs *
   1927                                       sizeof ( blend->weight_vector[0] ) );
   1928                      }
   1929                      break;
   1930 
   1931                    case 20:
   1932                      /* <arg1> <arg2> 2 20 callothersubr pop   */
   1933                      /* ==> push <arg1> + <arg2> onto T1 stack */
   1934                      {
   1935                        CF2_F16Dot16  summand1;
   1936                        CF2_F16Dot16  summand2;
   1937 
   1938 
   1939                        if ( arg_cnt != 2 )
   1940                          goto Unexpected_OtherSubr;
   1941 
   1942                        summand2 = cf2_stack_popFixed( opStack );
   1943                        summand1 = cf2_stack_popFixed( opStack );
   1944 
   1945                        cf2_stack_pushFixed( opStack,
   1946                                             ADD_INT32( summand1,
   1947                                                        summand2 ) );
   1948                        known_othersubr_result_cnt = 1;
   1949                      }
   1950                      break;
   1951 
   1952                    case 21:
   1953                      /* <arg1> <arg2> 2 21 callothersubr pop   */
   1954                      /* ==> push <arg1> - <arg2> onto T1 stack */
   1955                      {
   1956                        CF2_F16Dot16  minuend;
   1957                        CF2_F16Dot16  subtrahend;
   1958 
   1959 
   1960                        if ( arg_cnt != 2 )
   1961                          goto Unexpected_OtherSubr;
   1962 
   1963                        subtrahend = cf2_stack_popFixed( opStack );
   1964                        minuend    = cf2_stack_popFixed( opStack );
   1965 
   1966                        cf2_stack_pushFixed( opStack,
   1967                                             SUB_INT32( minuend,
   1968                                                        subtrahend ) );
   1969                        known_othersubr_result_cnt = 1;
   1970                      }
   1971                      break;
   1972 
   1973                    case 22:
   1974                      /* <arg1> <arg2> 2 22 callothersubr pop   */
   1975                      /* ==> push <arg1> * <arg2> onto T1 stack */
   1976                      {
   1977                        CF2_F16Dot16  factor1;
   1978                        CF2_F16Dot16  factor2;
   1979 
   1980 
   1981                        if ( arg_cnt != 2 )
   1982                          goto Unexpected_OtherSubr;
   1983 
   1984                        factor2 = cf2_stack_popFixed( opStack );
   1985                        factor1 = cf2_stack_popFixed( opStack );
   1986 
   1987                        cf2_stack_pushFixed( opStack,
   1988                                             FT_MulFix( factor1, factor2 ) );
   1989                        known_othersubr_result_cnt = 1;
   1990                      }
   1991                      break;
   1992 
   1993                    case 23:
   1994                      /* <arg1> <arg2> 2 23 callothersubr pop   */
   1995                      /* ==> push <arg1> / <arg2> onto T1 stack */
   1996                      {
   1997                        CF2_F16Dot16  dividend;
   1998                        CF2_F16Dot16  divisor;
   1999 
   2000 
   2001                        if ( arg_cnt != 2 )
   2002                          goto Unexpected_OtherSubr;
   2003 
   2004                        divisor  = cf2_stack_popFixed( opStack );
   2005                        dividend = cf2_stack_popFixed( opStack );
   2006 
   2007                        if ( divisor == 0 )
   2008                          goto Unexpected_OtherSubr;
   2009 
   2010                        cf2_stack_pushFixed( opStack,
   2011                                             FT_DivFix( dividend,
   2012                                                        divisor ) );
   2013                        known_othersubr_result_cnt = 1;
   2014                      }
   2015                      break;
   2016 
   2017                    case 24:
   2018                      /* <val> <idx> 2 24 callothersubr               */
   2019                      /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
   2020                      {
   2021                        CF2_UInt  idx;
   2022                        PS_Blend  blend = decoder->blend;
   2023 
   2024 
   2025                        if ( arg_cnt != 2 || !blend )
   2026                          goto Unexpected_OtherSubr;
   2027 
   2028                        idx = (CF2_UInt)cf2_stack_popInt( opStack );
   2029 
   2030                        if ( idx >= decoder->len_buildchar )
   2031                          goto Unexpected_OtherSubr;
   2032 
   2033                        decoder->buildchar[idx] =
   2034                          cf2_stack_popFixed( opStack );
   2035                      }
   2036                      break;
   2037 
   2038                    case 25:
   2039                      /* <idx> 1 25 callothersubr pop        */
   2040                      /* ==> push BuildCharArray[cvi( idx )] */
   2041                      /*     onto T1 stack                   */
   2042                      {
   2043                        CF2_UInt  idx;
   2044                        PS_Blend  blend = decoder->blend;
   2045 
   2046 
   2047                        if ( arg_cnt != 1 || !blend )
   2048                          goto Unexpected_OtherSubr;
   2049 
   2050                        idx = (CF2_UInt)cf2_stack_popInt( opStack );
   2051 
   2052                        if ( idx >= decoder->len_buildchar )
   2053                          goto Unexpected_OtherSubr;
   2054 
   2055                        cf2_stack_pushFixed( opStack,
   2056                                             decoder->buildchar[idx] );
   2057                        known_othersubr_result_cnt = 1;
   2058                      }
   2059                      break;
   2060 
   2061 #if 0
   2062                    case 26:
   2063                      /* <val> mark <idx>                              */
   2064                      /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */
   2065                      /*     leave mark on T1 stack                    */
   2066                      /* <val> <idx>                                   */
   2067                      /* ==> set BuildCharArray[cvi( <idx> )] = <val>  */
   2068                      XXX which routine has left its mark on the
   2069                      XXX (PostScript) stack?;
   2070                      break;
   2071 #endif
   2072 
   2073                    case 27:
   2074                      /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
   2075                      /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
   2076                      /*     otherwise push <res2>                          */
   2077                      {
   2078                        CF2_F16Dot16  arg1;
   2079                        CF2_F16Dot16  arg2;
   2080                        CF2_F16Dot16  cond1;
   2081                        CF2_F16Dot16  cond2;
   2082 
   2083 
   2084                        if ( arg_cnt != 4 )
   2085                          goto Unexpected_OtherSubr;
   2086 
   2087                        cond2 = cf2_stack_popFixed( opStack );
   2088                        cond1 = cf2_stack_popFixed( opStack );
   2089                        arg2  = cf2_stack_popFixed( opStack );
   2090                        arg1  = cf2_stack_popFixed( opStack );
   2091 
   2092                        cf2_stack_pushFixed( opStack,
   2093                                             cond1 <= cond2 ? arg1 : arg2 );
   2094                        known_othersubr_result_cnt = 1;
   2095                      }
   2096                      break;
   2097 
   2098                    case 28:
   2099                      /* 0 28 callothersubr pop                     */
   2100                      /* ==> push random value from interval [0, 1) */
   2101                      /*     onto stack                             */
   2102                      {
   2103                        CF2_F16Dot16  r;
   2104 
   2105 
   2106                        if ( arg_cnt != 0 )
   2107                          goto Unexpected_OtherSubr;
   2108 
   2109                        /* only use the lower 16 bits of `random'  */
   2110                        /* to generate a number in the range (0;1] */
   2111                        r = (CF2_F16Dot16)
   2112                              ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
   2113 
   2114                        decoder->current_subfont->random =
   2115                          cff_random( decoder->current_subfont->random );
   2116 
   2117                        cf2_stack_pushFixed( opStack, r );
   2118                        known_othersubr_result_cnt = 1;
   2119                      }
   2120                      break;
   2121 
   2122                    default:
   2123                      if ( arg_cnt >= 0 && subr_no >= 0 )
   2124                      {
   2125                        FT_Int  i;
   2126 
   2127 
   2128                        FT_ERROR((
   2129                          "cf2_interpT2CharString (Type 1 mode):"
   2130                          " unknown othersubr [%d %d], wish me luck\n",
   2131                          arg_cnt, subr_no ));
   2132 
   2133                        /* store the unused args        */
   2134                        /* for this unhandled OtherSubr */
   2135 
   2136                        if ( arg_cnt > PS_STORAGE_SIZE )
   2137                          arg_cnt = PS_STORAGE_SIZE;
   2138                        result_cnt = arg_cnt;
   2139 
   2140                        for ( i = 1; i <= arg_cnt; i++ )
   2141                          results[result_cnt - i] =
   2142                            cf2_stack_popFixed( opStack );
   2143 
   2144                        break;
   2145                      }
   2146                      /* fall through */
   2147 
   2148                    Unexpected_OtherSubr:
   2149                      FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   2150                                 " invalid othersubr [%d %d]\n",
   2151                                 arg_cnt, subr_no ));
   2152                      lastError = FT_THROW( Invalid_Glyph_Format );
   2153                      goto exit;
   2154                    }
   2155                  }
   2156                  continue; /* do not clear the stack */
   2157 
   2158                case cf2_escPOP:
   2159                  if ( !font->isT1 )
   2160                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   2161                  else
   2162                  {
   2163                    FT_TRACE4(( " pop" ));
   2164 
   2165                    if ( known_othersubr_result_cnt > 0 )
   2166                    {
   2167                      known_othersubr_result_cnt--;
   2168                      /* ignore, we pushed the operands ourselves */
   2169                      continue;
   2170                    }
   2171 
   2172                    if ( result_cnt == 0 )
   2173                    {
   2174                      FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   2175                                 " no more operands for othersubr\n" ));
   2176                      lastError = FT_THROW( Invalid_Glyph_Format );
   2177                      goto exit;
   2178                    }
   2179 
   2180                    result_cnt--;
   2181                    cf2_stack_pushFixed( opStack, results[result_cnt] );
   2182                  }
   2183                  continue; /* do not clear the stack */
   2184 
   2185                case cf2_escDROP:
   2186                  FT_TRACE4(( " drop\n" ));
   2187 
   2188                  (void)cf2_stack_popFixed( opStack );
   2189                  continue; /* do not clear the stack */
   2190 
   2191                case cf2_escPUT:
   2192                  {
   2193                    CF2_F16Dot16  val;
   2194                    CF2_UInt      idx;
   2195 
   2196 
   2197                    FT_TRACE4(( " put\n" ));
   2198 
   2199                    idx = (CF2_UInt)cf2_stack_popInt( opStack );
   2200                    val = cf2_stack_popFixed( opStack );
   2201 
   2202                    if ( idx < CF2_STORAGE_SIZE )
   2203                      storage[idx] = val;
   2204                  }
   2205                  continue; /* do not clear the stack */
   2206 
   2207                case cf2_escGET:
   2208                  {
   2209                    CF2_UInt  idx;
   2210 
   2211 
   2212                    FT_TRACE4(( " get\n" ));
   2213 
   2214                    idx = (CF2_UInt)cf2_stack_popInt( opStack );
   2215 
   2216                    if ( idx < CF2_STORAGE_SIZE )
   2217                      cf2_stack_pushFixed( opStack, storage[idx] );
   2218                  }
   2219                  continue; /* do not clear the stack */
   2220 
   2221                case cf2_escIFELSE:
   2222                  {
   2223                    CF2_F16Dot16  arg1;
   2224                    CF2_F16Dot16  arg2;
   2225                    CF2_F16Dot16  cond1;
   2226                    CF2_F16Dot16  cond2;
   2227 
   2228 
   2229                    FT_TRACE4(( " ifelse\n" ));
   2230 
   2231                    cond2 = cf2_stack_popFixed( opStack );
   2232                    cond1 = cf2_stack_popFixed( opStack );
   2233                    arg2  = cf2_stack_popFixed( opStack );
   2234                    arg1  = cf2_stack_popFixed( opStack );
   2235 
   2236                    cf2_stack_pushFixed( opStack,
   2237                                         cond1 <= cond2 ? arg1 : arg2 );
   2238                  }
   2239                  continue; /* do not clear the stack */
   2240 
   2241                case cf2_escRANDOM: /* in spec */
   2242                  {
   2243                    CF2_F16Dot16  r;
   2244 
   2245 
   2246                    FT_TRACE4(( " random\n" ));
   2247 
   2248                    /* only use the lower 16 bits of `random'  */
   2249                    /* to generate a number in the range (0;1] */
   2250                    r = (CF2_F16Dot16)
   2251                          ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
   2252 
   2253                    decoder->current_subfont->random =
   2254                      cff_random( decoder->current_subfont->random );
   2255 
   2256                    cf2_stack_pushFixed( opStack, r );
   2257                  }
   2258                  continue; /* do not clear the stack */
   2259 
   2260                case cf2_escMUL:
   2261                  {
   2262                    CF2_F16Dot16  factor1;
   2263                    CF2_F16Dot16  factor2;
   2264 
   2265 
   2266                    FT_TRACE4(( " mul\n" ));
   2267 
   2268                    factor2 = cf2_stack_popFixed( opStack );
   2269                    factor1 = cf2_stack_popFixed( opStack );
   2270 
   2271                    cf2_stack_pushFixed( opStack,
   2272                                         FT_MulFix( factor1, factor2 ) );
   2273                  }
   2274                  continue; /* do not clear the stack */
   2275 
   2276                case cf2_escSQRT:
   2277                  {
   2278                    CF2_F16Dot16  arg;
   2279 
   2280 
   2281                    FT_TRACE4(( " sqrt\n" ));
   2282 
   2283                    arg = cf2_stack_popFixed( opStack );
   2284                    if ( arg > 0 )
   2285                      arg = (CF2_F16Dot16)FT_SqrtFixed( (FT_UInt32)arg );
   2286                    else
   2287                      arg = 0;
   2288 
   2289                    cf2_stack_pushFixed( opStack, arg );
   2290                  }
   2291                  continue; /* do not clear the stack */
   2292 
   2293                case cf2_escDUP:
   2294                  {
   2295                    CF2_F16Dot16  arg;
   2296 
   2297 
   2298                    FT_TRACE4(( " dup\n" ));
   2299 
   2300                    arg = cf2_stack_popFixed( opStack );
   2301 
   2302                    cf2_stack_pushFixed( opStack, arg );
   2303                    cf2_stack_pushFixed( opStack, arg );
   2304                  }
   2305                  continue; /* do not clear the stack */
   2306 
   2307                case cf2_escEXCH:
   2308                  {
   2309                    CF2_F16Dot16  arg1;
   2310                    CF2_F16Dot16  arg2;
   2311 
   2312 
   2313                    FT_TRACE4(( " exch\n" ));
   2314 
   2315                    arg2 = cf2_stack_popFixed( opStack );
   2316                    arg1 = cf2_stack_popFixed( opStack );
   2317 
   2318                    cf2_stack_pushFixed( opStack, arg2 );
   2319                    cf2_stack_pushFixed( opStack, arg1 );
   2320                  }
   2321                  continue; /* do not clear the stack */
   2322 
   2323                case cf2_escINDEX:
   2324                  {
   2325                    CF2_Int   idx;
   2326                    CF2_UInt  size;
   2327 
   2328 
   2329                    FT_TRACE4(( " index\n" ));
   2330 
   2331                    idx  = cf2_stack_popInt( opStack );
   2332                    size = cf2_stack_count( opStack );
   2333 
   2334                    if ( size > 0 )
   2335                    {
   2336                      /* for `cf2_stack_getReal',   */
   2337                      /* index 0 is bottom of stack */
   2338                      CF2_UInt  gr_idx;
   2339 
   2340 
   2341                      if ( idx < 0 )
   2342                        gr_idx = size - 1;
   2343                      else if ( (CF2_UInt)idx >= size )
   2344                        gr_idx = 0;
   2345                      else
   2346                        gr_idx = size - 1 - (CF2_UInt)idx;
   2347 
   2348                      cf2_stack_pushFixed( opStack,
   2349                                           cf2_stack_getReal( opStack,
   2350                                                              gr_idx ) );
   2351                    }
   2352                  }
   2353                  continue; /* do not clear the stack */
   2354 
   2355                case cf2_escROLL:
   2356                  {
   2357                    CF2_Int  idx;
   2358                    CF2_Int  count;
   2359 
   2360 
   2361                    FT_TRACE4(( " roll\n" ));
   2362 
   2363                    idx   = cf2_stack_popInt( opStack );
   2364                    count = cf2_stack_popInt( opStack );
   2365 
   2366                    cf2_stack_roll( opStack, count, idx );
   2367                  }
   2368                  continue; /* do not clear the stack */
   2369 
   2370                case cf2_escSETCURRENTPT:
   2371                  if ( !font->isT1 )
   2372                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
   2373                  else
   2374                  {
   2375                    FT_TRACE4(( " setcurrentpoint" ));
   2376 
   2377                    if ( !initial_map_ready )
   2378                      break;
   2379 
   2380                    /* From the T1 specification, section 6.4:            */
   2381                    /*                                                    */
   2382                    /*   The setcurrentpoint command is used only in      */
   2383                    /*   conjunction with results from OtherSubrs         */
   2384                    /*   procedures.                                      */
   2385 
   2386                    /* known_othersubr_result_cnt != 0 is already handled */
   2387                    /* above.                                             */
   2388 
   2389                    /* Note, however, that both Ghostscript and Adobe     */
   2390                    /* Distiller handle this situation by silently        */
   2391                    /* ignoring the inappropriate `setcurrentpoint'       */
   2392                    /* instruction.  So we do the same.                   */
   2393 #if 0
   2394 
   2395                    if ( decoder->flex_state != 1 )
   2396                    {
   2397                      FT_ERROR(( "cf2_interpT2CharString:"
   2398                                 " unexpected `setcurrentpoint'\n" ));
   2399                      goto Syntax_Error;
   2400                    }
   2401                    else
   2402                      ...
   2403 #endif
   2404 
   2405                    curY = cf2_stack_popFixed( opStack );
   2406                    curX = cf2_stack_popFixed( opStack );
   2407 
   2408                    decoder->flex_state = 0;
   2409                  }
   2410                  break;
   2411 
   2412                } /* end of 2nd switch checking op2 */
   2413              }
   2414            }
   2415          } /* end of 1st switch checking op2 */
   2416        } /* case cf2_cmdESC */
   2417 
   2418        break;
   2419 
   2420      case cf2_cmdHSBW:
   2421        if ( !font->isT1 )
   2422          FT_TRACE4(( " unknown op (%d)\n", op1 ));
   2423        else
   2424        {
   2425          CF2_Fixed    lsb_x;
   2426          PS_Builder*  builder;
   2427 
   2428 
   2429          FT_TRACE4(( " hsbw\n" ));
   2430 
   2431          builder = &decoder->builder;
   2432 
   2433          builder->advance->x = cf2_stack_popFixed( opStack );
   2434          builder->advance->y = 0;
   2435 
   2436          lsb_x = cf2_stack_popFixed( opStack );
   2437 
   2438          builder->left_bearing->x = ADD_INT32( builder->left_bearing->x,
   2439                                                lsb_x );
   2440 
   2441          haveWidth = TRUE;
   2442 
   2443          /* the `metrics_only' indicates that we only want to compute */
   2444          /* the glyph's metrics (lsb + advance width), not load the   */
   2445          /* rest of it; so exit immediately                           */
   2446          if ( builder->metrics_only )
   2447            goto exit;
   2448 
   2449          if ( initial_map_ready )
   2450            curX = ADD_INT32( curX, lsb_x );
   2451        }
   2452        break;
   2453 
   2454      case cf2_cmdENDCHAR:
   2455        FT_TRACE4(( " endchar\n" ));
   2456 
   2457        if ( font->isT1 && !initial_map_ready )
   2458        {
   2459          FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
   2460                      "Build initial hintmap, rewinding...\n" ));
   2461 
   2462          /* trigger initial hintmap build */
   2463          cf2_glyphpath_moveTo( &glyphPath, curX, curY );
   2464 
   2465          initial_map_ready = TRUE;
   2466 
   2467          /* change hints routine - clear for rewind */
   2468          cf2_arrstack_clear( &vStemHintArray );
   2469          cf2_arrstack_clear( &hStemHintArray );
   2470 
   2471          cf2_hintmask_init( &hintMask, error );
   2472          hintMask.isValid = FALSE;
   2473          hintMask.isNew   = TRUE;
   2474 
   2475          /* rewind charstring */
   2476          /* some charstrings use endchar from a final subroutine call */
   2477          /* without returning, detect these and exit to the top level */
   2478          /* charstring                                                */
   2479          while ( charstringIndex > 0 )
   2480          {
   2481            FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
   2482 
   2483            /* restore position in previous charstring */
   2484            charstring = (CF2_Buffer)
   2485                           cf2_arrstack_getPointer(
   2486                             &subrStack,
   2487                             (CF2_UInt)--charstringIndex );
   2488          }
   2489          charstring->ptr = charstring->start;
   2490 
   2491          break;
   2492        }
   2493 
   2494        if ( cf2_stack_count( opStack ) == 1 ||
   2495             cf2_stack_count( opStack ) == 5 )
   2496        {
   2497          if ( !haveWidth )
   2498            *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
   2499                                nominalWidthX );
   2500        }
   2501 
   2502        /* width is defined or default after this */
   2503        haveWidth = TRUE;
   2504 
   2505        if ( decoder->width_only )
   2506          goto exit;
   2507 
   2508        /* close path if still open */
   2509        cf2_glyphpath_closeOpenPath( &glyphPath );
   2510 
   2511        /* disable seac for CFF2 and Type1        */
   2512        /* (charstring ending with args on stack) */
   2513        if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 )
   2514        {
   2515          /* must be either 4 or 5 --                       */
   2516          /* this is a (deprecated) implied `seac' operator */
   2517 
   2518          CF2_Int        achar;
   2519          CF2_Int        bchar;
   2520          CF2_BufferRec  component;
   2521          CF2_Fixed      dummyWidth;   /* ignore component width */
   2522          FT_Error       error2;
   2523 
   2524 
   2525          if ( doingSeac )
   2526          {
   2527            lastError = FT_THROW( Invalid_Glyph_Format );
   2528            goto exit;      /* nested seac */
   2529          }
   2530 
   2531          achar = cf2_stack_popInt( opStack );
   2532          bchar = cf2_stack_popInt( opStack );
   2533 
   2534          curY = cf2_stack_popFixed( opStack );
   2535          curX = cf2_stack_popFixed( opStack );
   2536 
   2537          error2 = cf2_getSeacComponent( decoder, achar, &component );
   2538          if ( error2 )
   2539          {
   2540            lastError = error2;      /* pass FreeType error through */
   2541            goto exit;
   2542          }
   2543          cf2_interpT2CharString( font,
   2544                                  &component,
   2545                                  callbacks,
   2546                                  translation,
   2547                                  TRUE,
   2548                                  curX,
   2549                                  curY,
   2550                                  &dummyWidth );
   2551          cf2_freeSeacComponent( decoder, &component );
   2552 
   2553          error2 = cf2_getSeacComponent( decoder, bchar, &component );
   2554          if ( error2 )
   2555          {
   2556            lastError = error2;      /* pass FreeType error through */
   2557            goto exit;
   2558          }
   2559          cf2_interpT2CharString( font,
   2560                                  &component,
   2561                                  callbacks,
   2562                                  translation,
   2563                                  TRUE,
   2564                                  0,
   2565                                  0,
   2566                                  &dummyWidth );
   2567          cf2_freeSeacComponent( decoder, &component );
   2568        }
   2569        goto exit;
   2570 
   2571      case cf2_cmdCNTRMASK:
   2572      case cf2_cmdHINTMASK:
   2573        /* the final \n in the tracing message gets added in      */
   2574        /* `cf2_hintmask_read' (which also traces the mask bytes) */
   2575        FT_TRACE4(( "%s", op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
   2576 
   2577        /* never add hints after the mask is computed */
   2578        if ( cf2_stack_count( opStack ) > 1    &&
   2579             cf2_hintmask_isValid( &hintMask ) )
   2580        {
   2581          FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
   2582          break;
   2583        }
   2584 
   2585        /* if there are arguments on the stack, there this is an */
   2586        /* implied cf2_cmdVSTEMHM                                */
   2587        cf2_doStems( font,
   2588                     opStack,
   2589                     &vStemHintArray,
   2590                     width,
   2591                     &haveWidth,
   2592                     0 );
   2593 
   2594        if ( decoder->width_only )
   2595          goto exit;
   2596 
   2597        if ( op1 == cf2_cmdHINTMASK )
   2598        {
   2599          /* consume the hint mask bytes which follow the operator */
   2600          cf2_hintmask_read( &hintMask,
   2601                             charstring,
   2602                             cf2_arrstack_size( &hStemHintArray ) +
   2603                               cf2_arrstack_size( &vStemHintArray ) );
   2604        }
   2605        else
   2606        {
   2607          /*
   2608           * Consume the counter mask bytes which follow the operator:
   2609           * Build a temporary hint map, just to place and lock those
   2610           * stems participating in the counter mask.  These are most
   2611           * likely the dominant hstems, and are grouped together in a
   2612           * few counter groups, not necessarily in correspondence
   2613           * with the hint groups.  This reduces the chances of
   2614           * conflicts between hstems that are initially placed in
   2615           * separate hint groups and then brought together.  The
   2616           * positions are copied back to `hStemHintArray', so we can
   2617           * discard `counterMask' and `counterHintMap'.
   2618           *
   2619           */
   2620          CF2_HintMapRec   counterHintMap;
   2621          CF2_HintMaskRec  counterMask;
   2622 
   2623 
   2624          cf2_hintmap_init( &counterHintMap,
   2625                            font,
   2626                            &glyphPath.initialHintMap,
   2627                            &glyphPath.hintMoves,
   2628                            scaleY );
   2629          cf2_hintmask_init( &counterMask, error );
   2630 
   2631          cf2_hintmask_read( &counterMask,
   2632                             charstring,
   2633                             cf2_arrstack_size( &hStemHintArray ) +
   2634                               cf2_arrstack_size( &vStemHintArray ) );
   2635          cf2_hintmap_build( &counterHintMap,
   2636                             &hStemHintArray,
   2637                             &vStemHintArray,
   2638                             &counterMask,
   2639                             0,
   2640                             FALSE );
   2641        }
   2642        break;
   2643 
   2644      case cf2_cmdRMOVETO:
   2645        FT_TRACE4(( " rmoveto\n" ));
   2646 
   2647        if ( font->isT1 && !decoder->flex_state && !haveWidth )
   2648          FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   2649                     " No width. Use hsbw/sbw as first op\n" ));
   2650 
   2651        if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
   2652          *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
   2653                              nominalWidthX );
   2654 
   2655        /* width is defined or default after this */
   2656        haveWidth = TRUE;
   2657 
   2658        if ( decoder->width_only )
   2659          goto exit;
   2660 
   2661        curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
   2662        curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
   2663 
   2664        if ( !decoder->flex_state )
   2665          cf2_glyphpath_moveTo( &glyphPath, curX, curY );
   2666 
   2667        break;
   2668 
   2669      case cf2_cmdHMOVETO:
   2670        FT_TRACE4(( " hmoveto\n" ));
   2671 
   2672        if ( font->isT1 && !decoder->flex_state && !haveWidth )
   2673          FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   2674                     " No width. Use hsbw/sbw as first op\n" ));
   2675 
   2676        if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
   2677          *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
   2678                              nominalWidthX );
   2679 
   2680        /* width is defined or default after this */
   2681        haveWidth = TRUE;
   2682 
   2683        if ( decoder->width_only )
   2684          goto exit;
   2685 
   2686        curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
   2687 
   2688        if ( !decoder->flex_state )
   2689          cf2_glyphpath_moveTo( &glyphPath, curX, curY );
   2690 
   2691        break;
   2692 
   2693      case cf2_cmdRLINECURVE:
   2694        {
   2695          CF2_UInt  count = cf2_stack_count( opStack );
   2696          CF2_UInt  idx   = 0;
   2697 
   2698 
   2699          FT_TRACE4(( " rlinecurve\n" ));
   2700 
   2701          while ( idx + 6 < count )
   2702          {
   2703            curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
   2704                                                       idx + 0 ) );
   2705            curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
   2706                                                       idx + 1 ) );
   2707 
   2708            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
   2709            idx += 2;
   2710          }
   2711 
   2712          while ( idx < count )
   2713          {
   2714            CF2_Fixed  x1, y1, x2, y2, x3, y3;
   2715 
   2716 
   2717            x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
   2718            y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
   2719            x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
   2720            y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
   2721            x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
   2722            y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
   2723 
   2724            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   2725 
   2726            curX  = x3;
   2727            curY  = y3;
   2728            idx  += 6;
   2729          }
   2730 
   2731          cf2_stack_clear( opStack );
   2732        }
   2733        continue; /* no need to clear stack again */
   2734 
   2735      case cf2_cmdVVCURVETO:
   2736        {
   2737          CF2_UInt  count, count1 = cf2_stack_count( opStack );
   2738          CF2_UInt  idx = 0;
   2739 
   2740 
   2741          /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
   2742          /* we enforce it by clearing the second bit           */
   2743          /* (and sorting the stack indexing to suit)           */
   2744          count = count1 & ~2U;
   2745          idx  += count1 - count;
   2746 
   2747          FT_TRACE4(( " vvcurveto\n" ));
   2748 
   2749          while ( idx < count )
   2750          {
   2751            CF2_Fixed  x1, y1, x2, y2, x3, y3;
   2752 
   2753 
   2754            if ( ( count - idx ) & 1 )
   2755            {
   2756              x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX );
   2757 
   2758              idx++;
   2759            }
   2760            else
   2761              x1 = curX;
   2762 
   2763            y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
   2764            x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
   2765            y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
   2766            x3 = x2;
   2767            y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
   2768 
   2769            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   2770 
   2771            curX  = x3;
   2772            curY  = y3;
   2773            idx  += 4;
   2774          }
   2775 
   2776          cf2_stack_clear( opStack );
   2777        }
   2778        continue; /* no need to clear stack again */
   2779 
   2780      case cf2_cmdHHCURVETO:
   2781        {
   2782          CF2_UInt  count, count1 = cf2_stack_count( opStack );
   2783          CF2_UInt  idx = 0;
   2784 
   2785 
   2786          /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
   2787          /* we enforce it by clearing the second bit           */
   2788          /* (and sorting the stack indexing to suit)           */
   2789          count = count1 & ~2U;
   2790          idx  += count1 - count;
   2791 
   2792          FT_TRACE4(( " hhcurveto\n" ));
   2793 
   2794          while ( idx < count )
   2795          {
   2796            CF2_Fixed  x1, y1, x2, y2, x3, y3;
   2797 
   2798 
   2799            if ( ( count - idx ) & 1 )
   2800            {
   2801              y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY );
   2802 
   2803              idx++;
   2804            }
   2805            else
   2806              y1 = curY;
   2807 
   2808            x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
   2809            x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
   2810            y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
   2811            x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
   2812            y3 = y2;
   2813 
   2814            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   2815 
   2816            curX  = x3;
   2817            curY  = y3;
   2818            idx  += 4;
   2819          }
   2820 
   2821          cf2_stack_clear( opStack );
   2822        }
   2823        continue; /* no need to clear stack again */
   2824 
   2825      case cf2_cmdVHCURVETO:
   2826      case cf2_cmdHVCURVETO:
   2827        {
   2828          CF2_UInt  count, count1 = cf2_stack_count( opStack );
   2829          CF2_UInt  idx = 0;
   2830 
   2831          FT_Bool  alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
   2832 
   2833 
   2834          /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
   2835          /* 8n+4, or 8n+5, we enforce it by clearing the     */
   2836          /* second bit                                       */
   2837          /* (and sorting the stack indexing to suit)         */
   2838          count = count1 & ~2U;
   2839          idx  += count1 - count;
   2840 
   2841          FT_TRACE4(( "%s\n", alternate ? " hvcurveto" : " vhcurveto" ));
   2842 
   2843          while ( idx < count )
   2844          {
   2845            CF2_Fixed x1, x2, x3, y1, y2, y3;
   2846 
   2847 
   2848            if ( alternate )
   2849            {
   2850              x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
   2851              y1 = curY;
   2852              x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
   2853              y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
   2854              y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
   2855 
   2856              if ( count - idx == 5 )
   2857              {
   2858                x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
   2859 
   2860                idx++;
   2861              }
   2862              else
   2863                x3 = x2;
   2864 
   2865              alternate = FALSE;
   2866            }
   2867            else
   2868            {
   2869              x1 = curX;
   2870              y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
   2871              x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
   2872              y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
   2873              x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
   2874 
   2875              if ( count - idx == 5 )
   2876              {
   2877                y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 );
   2878 
   2879                idx++;
   2880              }
   2881              else
   2882                y3 = y2;
   2883 
   2884              alternate = TRUE;
   2885            }
   2886 
   2887            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
   2888 
   2889            curX  = x3;
   2890            curY  = y3;
   2891            idx  += 4;
   2892          }
   2893 
   2894          cf2_stack_clear( opStack );
   2895        }
   2896        continue;     /* no need to clear stack again */
   2897 
   2898      case cf2_cmdEXTENDEDNMBR:
   2899        {
   2900          CF2_Int  v;
   2901 
   2902          CF2_Int  byte1 = cf2_buf_readByte( charstring );
   2903          CF2_Int  byte2 = cf2_buf_readByte( charstring );
   2904 
   2905 
   2906          v = (FT_Short)( ( byte1 << 8 ) |
   2907                            byte2        );
   2908 
   2909          FT_TRACE4(( " %d", v ));
   2910 
   2911          cf2_stack_pushInt( opStack, v );
   2912        }
   2913        continue;
   2914 
   2915      default:
   2916        /* numbers */
   2917        {
   2918          if ( /* op1 >= 32 && */ op1 <= 246 )
   2919          {
   2920            CF2_Int  v;
   2921 
   2922 
   2923            v = op1 - 139;
   2924 
   2925            FT_TRACE4(( " %d", v ));
   2926 
   2927            /* -107 .. 107 */
   2928            cf2_stack_pushInt( opStack, v );
   2929          }
   2930 
   2931          else if ( /* op1 >= 247 && */ op1 <= 250 )
   2932          {
   2933            CF2_Int  v;
   2934 
   2935 
   2936            v  = op1;
   2937            v -= 247;
   2938            v *= 256;
   2939            v += cf2_buf_readByte( charstring );
   2940            v += 108;
   2941 
   2942            FT_TRACE4(( " %d", v ));
   2943 
   2944            /* 108 .. 1131 */
   2945            cf2_stack_pushInt( opStack, v );
   2946          }
   2947 
   2948          else if ( /* op1 >= 251 && */ op1 <= 254 )
   2949          {
   2950            CF2_Int  v;
   2951 
   2952 
   2953            v  = op1;
   2954            v -= 251;
   2955            v *= 256;
   2956            v += cf2_buf_readByte( charstring );
   2957            v  = -v - 108;
   2958 
   2959            FT_TRACE4(( " %d", v ));
   2960 
   2961            /* -1131 .. -108 */
   2962            cf2_stack_pushInt( opStack, v );
   2963          }
   2964 
   2965          else /* op1 == 255 */
   2966          {
   2967            CF2_Fixed  v;
   2968 
   2969            FT_UInt32  byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
   2970            FT_UInt32  byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
   2971            FT_UInt32  byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
   2972            FT_UInt32  byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
   2973 
   2974 
   2975            v = (CF2_Fixed)( ( byte1 << 24 ) |
   2976                             ( byte2 << 16 ) |
   2977                             ( byte3 <<  8 ) |
   2978                               byte4         );
   2979 
   2980            /*
   2981             * For Type 1:
   2982             *
   2983             * According to the specification, values > 32000 or < -32000
   2984             * must be followed by a `div' operator to make the result be
   2985             * in the range [-32000;32000].  We expect that the second
   2986             * argument of `div' is not a large number.  Additionally, we
   2987             * don't handle stuff like `<large1> <large2> <num> div <num>
   2988             * div' or <large1> <large2> <num> div div'.  This is probably
   2989             * not allowed anyway.
   2990             *
   2991             * <large> <num> <num>+ div is not checked but should not be
   2992             * allowed as the large value remains untouched.
   2993             *
   2994             */
   2995            if ( font->isT1 )
   2996            {
   2997              if ( v > 32000 || v < -32000 )
   2998              {
   2999                if ( large_int )
   3000                  FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
   3001                             " no `div' after large integer\n" ));
   3002                else
   3003                  large_int = TRUE;
   3004              }
   3005 
   3006              FT_TRACE4(( " %d", v ));
   3007 
   3008              cf2_stack_pushInt( opStack, (CF2_Int)v );
   3009            }
   3010            else
   3011            {
   3012              FT_TRACE4(( " %.5fF", v / 65536.0 ));
   3013 
   3014              cf2_stack_pushFixed( opStack, v );
   3015            }
   3016          }
   3017        }
   3018        continue;   /* don't clear stack */
   3019 
   3020      } /* end of switch statement checking `op1' */
   3021 
   3022      cf2_stack_clear( opStack );
   3023 
   3024    } /* end of main interpreter loop */
   3025 
   3026    /* we get here if the charstring ends without cf2_cmdENDCHAR */
   3027    FT_TRACE4(( "cf2_interpT2CharString:"
   3028                "  charstring ends without ENDCHAR\n" ));
   3029 
   3030  exit:
   3031    /* check whether last error seen is also the first one */
   3032    cf2_setError( error, lastError );
   3033 
   3034    if ( *error )
   3035      FT_TRACE4(( "charstring error %d\n", *error ));
   3036 
   3037    /* free resources from objects we've used */
   3038    cf2_glyphpath_finalize( &glyphPath );
   3039    cf2_arrstack_finalize( &vStemHintArray );
   3040    cf2_arrstack_finalize( &hStemHintArray );
   3041    cf2_arrstack_finalize( &subrStack );
   3042    cf2_stack_free( opStack );
   3043 
   3044    FT_TRACE4(( "\n" ));
   3045 
   3046    return;
   3047  }
   3048 
   3049 
   3050 /* END */