Home | History | Annotate | Download | only in truetype
      1 /****************************************************************************
      2  *
      3  * ttinterp.c
      4  *
      5  *   TrueType bytecode interpreter (body).
      6  *
      7  * Copyright 1996-2018 by
      8  * David Turner, Robert Wilhelm, and Werner Lemberg.
      9  *
     10  * This file is part of the FreeType project, and may only be used,
     11  * modified, and distributed under the terms of the FreeType project
     12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
     13  * this file you indicate that you have read the license and
     14  * understand and accept it fully.
     15  *
     16  */
     17 
     18 
     19 /* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */
     20 /* issues; many thanks!                                                */
     21 
     22 
     23 #include <ft2build.h>
     24 #include FT_INTERNAL_DEBUG_H
     25 #include FT_INTERNAL_CALC_H
     26 #include FT_TRIGONOMETRY_H
     27 #include FT_SYSTEM_H
     28 #include FT_DRIVER_H
     29 #include FT_MULTIPLE_MASTERS_H
     30 
     31 #include "ttinterp.h"
     32 #include "tterrors.h"
     33 #include "ttsubpix.h"
     34 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     35 #include "ttgxvar.h"
     36 #endif
     37 
     38 
     39 #ifdef TT_USE_BYTECODE_INTERPRETER
     40 
     41 
     42   /**************************************************************************
     43    *
     44    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     45    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     46    * messages during execution.
     47    */
     48 #undef  FT_COMPONENT
     49 #define FT_COMPONENT  trace_ttinterp
     50 
     51 
     52 #define NO_SUBPIXEL_HINTING                                                  \
     53           ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
     54             TT_INTERPRETER_VERSION_35 )
     55 
     56 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     57 #define SUBPIXEL_HINTING_INFINALITY                                          \
     58           ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
     59             TT_INTERPRETER_VERSION_38 )
     60 #endif
     61 
     62 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
     63 #define SUBPIXEL_HINTING_MINIMAL                                             \
     64           ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
     65             TT_INTERPRETER_VERSION_40 )
     66 #endif
     67 
     68 #define PROJECT( v1, v2 )                                   \
     69           exc->func_project( exc,                           \
     70                              SUB_LONG( (v1)->x, (v2)->x ),  \
     71                              SUB_LONG( (v1)->y, (v2)->y ) )
     72 
     73 #define DUALPROJ( v1, v2 )                                   \
     74           exc->func_dualproj( exc,                           \
     75                               SUB_LONG( (v1)->x, (v2)->x ),  \
     76                               SUB_LONG( (v1)->y, (v2)->y ) )
     77 
     78 #define FAST_PROJECT( v )                          \
     79           exc->func_project( exc, (v)->x, (v)->y )
     80 
     81 #define FAST_DUALPROJ( v )                          \
     82           exc->func_dualproj( exc, (v)->x, (v)->y )
     83 
     84 
     85   /**************************************************************************
     86    *
     87    * Two simple bounds-checking macros.
     88    */
     89 #define BOUNDS( x, n )   ( (FT_UInt)(x)  >= (FT_UInt)(n)  )
     90 #define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
     91 
     92 
     93 #undef  SUCCESS
     94 #define SUCCESS  0
     95 
     96 #undef  FAILURE
     97 #define FAILURE  1
     98 
     99 
    100   /**************************************************************************
    101    *
    102    *                       CODERANGE FUNCTIONS
    103    *
    104    */
    105 
    106 
    107   /**************************************************************************
    108    *
    109    * @Function:
    110    *   TT_Goto_CodeRange
    111    *
    112    * @Description:
    113    *   Switches to a new code range (updates the code related elements in
    114    *   `exec', and `IP').
    115    *
    116    * @Input:
    117    *   range ::
    118    *     The new execution code range.
    119    *
    120    *   IP ::
    121    *     The new IP in the new code range.
    122    *
    123    * @InOut:
    124    *   exec ::
    125    *     The target execution context.
    126    */
    127   FT_LOCAL_DEF( void )
    128   TT_Goto_CodeRange( TT_ExecContext  exec,
    129                      FT_Int          range,
    130                      FT_Long         IP )
    131   {
    132     TT_CodeRange*  coderange;
    133 
    134 
    135     FT_ASSERT( range >= 1 && range <= 3 );
    136 
    137     coderange = &exec->codeRangeTable[range - 1];
    138 
    139     FT_ASSERT( coderange->base );
    140 
    141     /* NOTE: Because the last instruction of a program may be a CALL */
    142     /*       which will return to the first byte *after* the code    */
    143     /*       range, we test for IP <= Size instead of IP < Size.     */
    144     /*                                                               */
    145     FT_ASSERT( IP <= coderange->size );
    146 
    147     exec->code     = coderange->base;
    148     exec->codeSize = coderange->size;
    149     exec->IP       = IP;
    150     exec->curRange = range;
    151   }
    152 
    153 
    154   /**************************************************************************
    155    *
    156    * @Function:
    157    *   TT_Set_CodeRange
    158    *
    159    * @Description:
    160    *   Sets a code range.
    161    *
    162    * @Input:
    163    *   range ::
    164    *     The code range index.
    165    *
    166    *   base ::
    167    *     The new code base.
    168    *
    169    *   length ::
    170    *     The range size in bytes.
    171    *
    172    * @InOut:
    173    *   exec ::
    174    *     The target execution context.
    175    */
    176   FT_LOCAL_DEF( void )
    177   TT_Set_CodeRange( TT_ExecContext  exec,
    178                     FT_Int          range,
    179                     void*           base,
    180                     FT_Long         length )
    181   {
    182     FT_ASSERT( range >= 1 && range <= 3 );
    183 
    184     exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
    185     exec->codeRangeTable[range - 1].size = length;
    186   }
    187 
    188 
    189   /**************************************************************************
    190    *
    191    * @Function:
    192    *   TT_Clear_CodeRange
    193    *
    194    * @Description:
    195    *   Clears a code range.
    196    *
    197    * @Input:
    198    *   range ::
    199    *     The code range index.
    200    *
    201    * @InOut:
    202    *   exec ::
    203    *     The target execution context.
    204    */
    205   FT_LOCAL_DEF( void )
    206   TT_Clear_CodeRange( TT_ExecContext  exec,
    207                       FT_Int          range )
    208   {
    209     FT_ASSERT( range >= 1 && range <= 3 );
    210 
    211     exec->codeRangeTable[range - 1].base = NULL;
    212     exec->codeRangeTable[range - 1].size = 0;
    213   }
    214 
    215 
    216   /**************************************************************************
    217    *
    218    *                  EXECUTION CONTEXT ROUTINES
    219    *
    220    */
    221 
    222 
    223   /**************************************************************************
    224    *
    225    * @Function:
    226    *   TT_Done_Context
    227    *
    228    * @Description:
    229    *   Destroys a given context.
    230    *
    231    * @Input:
    232    *   exec ::
    233    *     A handle to the target execution context.
    234    *
    235    *   memory ::
    236    *     A handle to the parent memory object.
    237    *
    238    * @Note:
    239    *   Only the glyph loader and debugger should call this function.
    240    */
    241   FT_LOCAL_DEF( void )
    242   TT_Done_Context( TT_ExecContext  exec )
    243   {
    244     FT_Memory  memory = exec->memory;
    245 
    246 
    247     /* points zone */
    248     exec->maxPoints   = 0;
    249     exec->maxContours = 0;
    250 
    251     /* free stack */
    252     FT_FREE( exec->stack );
    253     exec->stackSize = 0;
    254 
    255     /* free call stack */
    256     FT_FREE( exec->callStack );
    257     exec->callSize = 0;
    258     exec->callTop  = 0;
    259 
    260     /* free glyph code range */
    261     FT_FREE( exec->glyphIns );
    262     exec->glyphSize = 0;
    263 
    264     exec->size = NULL;
    265     exec->face = NULL;
    266 
    267     FT_FREE( exec );
    268   }
    269 
    270 
    271   /**************************************************************************
    272    *
    273    * @Function:
    274    *   Init_Context
    275    *
    276    * @Description:
    277    *   Initializes a context object.
    278    *
    279    * @Input:
    280    *   memory ::
    281    *     A handle to the parent memory object.
    282    *
    283    * @InOut:
    284    *   exec ::
    285    *     A handle to the target execution context.
    286    *
    287    * @Return:
    288    *   FreeType error code.  0 means success.
    289    */
    290   static FT_Error
    291   Init_Context( TT_ExecContext  exec,
    292                 FT_Memory       memory )
    293   {
    294     FT_Error  error;
    295 
    296 
    297     FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
    298 
    299     exec->memory   = memory;
    300     exec->callSize = 32;
    301 
    302     if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
    303       goto Fail_Memory;
    304 
    305     /* all values in the context are set to 0 already, but this is */
    306     /* here as a remainder                                         */
    307     exec->maxPoints   = 0;
    308     exec->maxContours = 0;
    309 
    310     exec->stackSize = 0;
    311     exec->glyphSize = 0;
    312 
    313     exec->stack    = NULL;
    314     exec->glyphIns = NULL;
    315 
    316     exec->face = NULL;
    317     exec->size = NULL;
    318 
    319     return FT_Err_Ok;
    320 
    321   Fail_Memory:
    322     FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
    323     TT_Done_Context( exec );
    324 
    325     return error;
    326  }
    327 
    328 
    329   /**************************************************************************
    330    *
    331    * @Function:
    332    *   Update_Max
    333    *
    334    * @Description:
    335    *   Checks the size of a buffer and reallocates it if necessary.
    336    *
    337    * @Input:
    338    *   memory ::
    339    *     A handle to the parent memory object.
    340    *
    341    *   multiplier ::
    342    *     The size in bytes of each element in the buffer.
    343    *
    344    *   new_max ::
    345    *     The new capacity (size) of the buffer.
    346    *
    347    * @InOut:
    348    *   size ::
    349    *     The address of the buffer's current size expressed
    350    *     in elements.
    351    *
    352    *   buff ::
    353    *     The address of the buffer base pointer.
    354    *
    355    * @Return:
    356    *   FreeType error code.  0 means success.
    357    */
    358   FT_LOCAL_DEF( FT_Error )
    359   Update_Max( FT_Memory  memory,
    360               FT_ULong*  size,
    361               FT_ULong   multiplier,
    362               void*      _pbuff,
    363               FT_ULong   new_max )
    364   {
    365     FT_Error  error;
    366     void**    pbuff = (void**)_pbuff;
    367 
    368 
    369     if ( *size < new_max )
    370     {
    371       if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
    372         return error;
    373       *size = new_max;
    374     }
    375 
    376     return FT_Err_Ok;
    377   }
    378 
    379 
    380   /**************************************************************************
    381    *
    382    * @Function:
    383    *   TT_Load_Context
    384    *
    385    * @Description:
    386    *   Prepare an execution context for glyph hinting.
    387    *
    388    * @Input:
    389    *   face ::
    390    *     A handle to the source face object.
    391    *
    392    *   size ::
    393    *     A handle to the source size object.
    394    *
    395    * @InOut:
    396    *   exec ::
    397    *     A handle to the target execution context.
    398    *
    399    * @Return:
    400    *   FreeType error code.  0 means success.
    401    *
    402    * @Note:
    403    *   Only the glyph loader and debugger should call this function.
    404    */
    405   FT_LOCAL_DEF( FT_Error )
    406   TT_Load_Context( TT_ExecContext  exec,
    407                    TT_Face         face,
    408                    TT_Size         size )
    409   {
    410     FT_Int          i;
    411     FT_ULong        tmp;
    412     TT_MaxProfile*  maxp;
    413     FT_Error        error;
    414 
    415 
    416     exec->face = face;
    417     maxp       = &face->max_profile;
    418     exec->size = size;
    419 
    420     if ( size )
    421     {
    422       exec->numFDefs   = size->num_function_defs;
    423       exec->maxFDefs   = size->max_function_defs;
    424       exec->numIDefs   = size->num_instruction_defs;
    425       exec->maxIDefs   = size->max_instruction_defs;
    426       exec->FDefs      = size->function_defs;
    427       exec->IDefs      = size->instruction_defs;
    428       exec->pointSize  = size->point_size;
    429       exec->tt_metrics = size->ttmetrics;
    430       exec->metrics    = *size->metrics;
    431 
    432       exec->maxFunc    = size->max_func;
    433       exec->maxIns     = size->max_ins;
    434 
    435       for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
    436         exec->codeRangeTable[i] = size->codeRangeTable[i];
    437 
    438       /* set graphics state */
    439       exec->GS = size->GS;
    440 
    441       exec->cvtSize = size->cvt_size;
    442       exec->cvt     = size->cvt;
    443 
    444       exec->storeSize = size->storage_size;
    445       exec->storage   = size->storage;
    446 
    447       exec->twilight  = size->twilight;
    448 
    449       /* In case of multi-threading it can happen that the old size object */
    450       /* no longer exists, thus we must clear all glyph zone references.   */
    451       FT_ZERO( &exec->zp0 );
    452       exec->zp1 = exec->zp0;
    453       exec->zp2 = exec->zp0;
    454     }
    455 
    456     /* XXX: We reserve a little more elements on the stack to deal safely */
    457     /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
    458     tmp = (FT_ULong)exec->stackSize;
    459     error = Update_Max( exec->memory,
    460                         &tmp,
    461                         sizeof ( FT_F26Dot6 ),
    462                         (void*)&exec->stack,
    463                         maxp->maxStackElements + 32 );
    464     exec->stackSize = (FT_Long)tmp;
    465     if ( error )
    466       return error;
    467 
    468     tmp = exec->glyphSize;
    469     error = Update_Max( exec->memory,
    470                         &tmp,
    471                         sizeof ( FT_Byte ),
    472                         (void*)&exec->glyphIns,
    473                         maxp->maxSizeOfInstructions );
    474     exec->glyphSize = (FT_UShort)tmp;
    475     if ( error )
    476       return error;
    477 
    478     exec->pts.n_points   = 0;
    479     exec->pts.n_contours = 0;
    480 
    481     exec->zp1 = exec->pts;
    482     exec->zp2 = exec->pts;
    483     exec->zp0 = exec->pts;
    484 
    485     exec->instruction_trap = FALSE;
    486 
    487     return FT_Err_Ok;
    488   }
    489 
    490 
    491   /**************************************************************************
    492    *
    493    * @Function:
    494    *   TT_Save_Context
    495    *
    496    * @Description:
    497    *   Saves the code ranges in a `size' object.
    498    *
    499    * @Input:
    500    *   exec ::
    501    *     A handle to the source execution context.
    502    *
    503    * @InOut:
    504    *   size ::
    505    *     A handle to the target size object.
    506    *
    507    * @Note:
    508    *   Only the glyph loader and debugger should call this function.
    509    */
    510   FT_LOCAL_DEF( void )
    511   TT_Save_Context( TT_ExecContext  exec,
    512                    TT_Size         size )
    513   {
    514     FT_Int  i;
    515 
    516 
    517     /* XXX: Will probably disappear soon with all the code range */
    518     /*      management, which is now rather obsolete.            */
    519     /*                                                           */
    520     size->num_function_defs    = exec->numFDefs;
    521     size->num_instruction_defs = exec->numIDefs;
    522 
    523     size->max_func = exec->maxFunc;
    524     size->max_ins  = exec->maxIns;
    525 
    526     for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
    527       size->codeRangeTable[i] = exec->codeRangeTable[i];
    528   }
    529 
    530 
    531   /**************************************************************************
    532    *
    533    * @Function:
    534    *   TT_Run_Context
    535    *
    536    * @Description:
    537    *   Executes one or more instructions in the execution context.
    538    *
    539    * @Input:
    540    *   debug ::
    541    *     A Boolean flag.  If set, the function sets some internal
    542    *     variables and returns immediately, otherwise TT_RunIns()
    543    *     is called.
    544    *
    545    *     This is commented out currently.
    546    *
    547    * @Input:
    548    *   exec ::
    549    *     A handle to the target execution context.
    550    *
    551    * @Return:
    552    *   TrueType error code.  0 means success.
    553    */
    554   FT_LOCAL_DEF( FT_Error )
    555   TT_Run_Context( TT_ExecContext  exec )
    556   {
    557     TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 );
    558 
    559     exec->zp0 = exec->pts;
    560     exec->zp1 = exec->pts;
    561     exec->zp2 = exec->pts;
    562 
    563     exec->GS.gep0 = 1;
    564     exec->GS.gep1 = 1;
    565     exec->GS.gep2 = 1;
    566 
    567     exec->GS.projVector.x = 0x4000;
    568     exec->GS.projVector.y = 0x0000;
    569 
    570     exec->GS.freeVector = exec->GS.projVector;
    571     exec->GS.dualVector = exec->GS.projVector;
    572 
    573     exec->GS.round_state = 1;
    574     exec->GS.loop        = 1;
    575 
    576     /* some glyphs leave something on the stack. so we clean it */
    577     /* before a new execution.                                  */
    578     exec->top     = 0;
    579     exec->callTop = 0;
    580 
    581     return exec->face->interpreter( exec );
    582   }
    583 
    584 
    585   /* The default value for `scan_control' is documented as FALSE in the */
    586   /* TrueType specification.  This is confusing since it implies a      */
    587   /* Boolean value.  However, this is not the case, thus both the       */
    588   /* default values of our `scan_type' and `scan_control' fields (which */
    589   /* the documentation's `scan_control' variable is split into) are     */
    590   /* zero.                                                              */
    591 
    592   const TT_GraphicsState  tt_default_graphics_state =
    593   {
    594     0, 0, 0,
    595     { 0x4000, 0 },
    596     { 0x4000, 0 },
    597     { 0x4000, 0 },
    598 
    599     1, 64, 1,
    600     TRUE, 68, 0, 0, 9, 3,
    601     0, FALSE, 0, 1, 1, 1
    602   };
    603 
    604 
    605   /* documentation is in ttinterp.h */
    606 
    607   FT_EXPORT_DEF( TT_ExecContext )
    608   TT_New_Context( TT_Driver  driver )
    609   {
    610     FT_Memory  memory;
    611     FT_Error   error;
    612 
    613     TT_ExecContext  exec = NULL;
    614 
    615 
    616     if ( !driver )
    617       goto Fail;
    618 
    619     memory = driver->root.root.memory;
    620 
    621     /* allocate object */
    622     if ( FT_NEW( exec ) )
    623       goto Fail;
    624 
    625     /* initialize it; in case of error this deallocates `exec' too */
    626     error = Init_Context( exec, memory );
    627     if ( error )
    628       goto Fail;
    629 
    630     return exec;
    631 
    632   Fail:
    633     return NULL;
    634   }
    635 
    636 
    637   /**************************************************************************
    638    *
    639    * Before an opcode is executed, the interpreter verifies that there are
    640    * enough arguments on the stack, with the help of the `Pop_Push_Count'
    641    * table.
    642    *
    643    * For each opcode, the first column gives the number of arguments that
    644    * are popped from the stack; the second one gives the number of those
    645    * that are pushed in result.
    646    *
    647    * Opcodes which have a varying number of parameters in the data stream
    648    * (NPUSHB, NPUSHW) are handled specially; they have a negative value in
    649    * the `opcode_length' table, and the value in `Pop_Push_Count' is set
    650    * to zero.
    651    *
    652    */
    653 
    654 
    655 #undef  PACK
    656 #define PACK( x, y )  ( ( x << 4 ) | y )
    657 
    658 
    659   static
    660   const FT_Byte  Pop_Push_Count[256] =
    661   {
    662     /* opcodes are gathered in groups of 16 */
    663     /* please keep the spaces as they are   */
    664 
    665     /*  SVTCA  y  */  PACK( 0, 0 ),
    666     /*  SVTCA  x  */  PACK( 0, 0 ),
    667     /*  SPvTCA y  */  PACK( 0, 0 ),
    668     /*  SPvTCA x  */  PACK( 0, 0 ),
    669     /*  SFvTCA y  */  PACK( 0, 0 ),
    670     /*  SFvTCA x  */  PACK( 0, 0 ),
    671     /*  SPvTL //  */  PACK( 2, 0 ),
    672     /*  SPvTL +   */  PACK( 2, 0 ),
    673     /*  SFvTL //  */  PACK( 2, 0 ),
    674     /*  SFvTL +   */  PACK( 2, 0 ),
    675     /*  SPvFS     */  PACK( 2, 0 ),
    676     /*  SFvFS     */  PACK( 2, 0 ),
    677     /*  GPv       */  PACK( 0, 2 ),
    678     /*  GFv       */  PACK( 0, 2 ),
    679     /*  SFvTPv    */  PACK( 0, 0 ),
    680     /*  ISECT     */  PACK( 5, 0 ),
    681 
    682     /*  SRP0      */  PACK( 1, 0 ),
    683     /*  SRP1      */  PACK( 1, 0 ),
    684     /*  SRP2      */  PACK( 1, 0 ),
    685     /*  SZP0      */  PACK( 1, 0 ),
    686     /*  SZP1      */  PACK( 1, 0 ),
    687     /*  SZP2      */  PACK( 1, 0 ),
    688     /*  SZPS      */  PACK( 1, 0 ),
    689     /*  SLOOP     */  PACK( 1, 0 ),
    690     /*  RTG       */  PACK( 0, 0 ),
    691     /*  RTHG      */  PACK( 0, 0 ),
    692     /*  SMD       */  PACK( 1, 0 ),
    693     /*  ELSE      */  PACK( 0, 0 ),
    694     /*  JMPR      */  PACK( 1, 0 ),
    695     /*  SCvTCi    */  PACK( 1, 0 ),
    696     /*  SSwCi     */  PACK( 1, 0 ),
    697     /*  SSW       */  PACK( 1, 0 ),
    698 
    699     /*  DUP       */  PACK( 1, 2 ),
    700     /*  POP       */  PACK( 1, 0 ),
    701     /*  CLEAR     */  PACK( 0, 0 ),
    702     /*  SWAP      */  PACK( 2, 2 ),
    703     /*  DEPTH     */  PACK( 0, 1 ),
    704     /*  CINDEX    */  PACK( 1, 1 ),
    705     /*  MINDEX    */  PACK( 1, 0 ),
    706     /*  AlignPTS  */  PACK( 2, 0 ),
    707     /*  INS_$28   */  PACK( 0, 0 ),
    708     /*  UTP       */  PACK( 1, 0 ),
    709     /*  LOOPCALL  */  PACK( 2, 0 ),
    710     /*  CALL      */  PACK( 1, 0 ),
    711     /*  FDEF      */  PACK( 1, 0 ),
    712     /*  ENDF      */  PACK( 0, 0 ),
    713     /*  MDAP[0]   */  PACK( 1, 0 ),
    714     /*  MDAP[1]   */  PACK( 1, 0 ),
    715 
    716     /*  IUP[0]    */  PACK( 0, 0 ),
    717     /*  IUP[1]    */  PACK( 0, 0 ),
    718     /*  SHP[0]    */  PACK( 0, 0 ), /* loops */
    719     /*  SHP[1]    */  PACK( 0, 0 ), /* loops */
    720     /*  SHC[0]    */  PACK( 1, 0 ),
    721     /*  SHC[1]    */  PACK( 1, 0 ),
    722     /*  SHZ[0]    */  PACK( 1, 0 ),
    723     /*  SHZ[1]    */  PACK( 1, 0 ),
    724     /*  SHPIX     */  PACK( 1, 0 ), /* loops */
    725     /*  IP        */  PACK( 0, 0 ), /* loops */
    726     /*  MSIRP[0]  */  PACK( 2, 0 ),
    727     /*  MSIRP[1]  */  PACK( 2, 0 ),
    728     /*  AlignRP   */  PACK( 0, 0 ), /* loops */
    729     /*  RTDG      */  PACK( 0, 0 ),
    730     /*  MIAP[0]   */  PACK( 2, 0 ),
    731     /*  MIAP[1]   */  PACK( 2, 0 ),
    732 
    733     /*  NPushB    */  PACK( 0, 0 ),
    734     /*  NPushW    */  PACK( 0, 0 ),
    735     /*  WS        */  PACK( 2, 0 ),
    736     /*  RS        */  PACK( 1, 1 ),
    737     /*  WCvtP     */  PACK( 2, 0 ),
    738     /*  RCvt      */  PACK( 1, 1 ),
    739     /*  GC[0]     */  PACK( 1, 1 ),
    740     /*  GC[1]     */  PACK( 1, 1 ),
    741     /*  SCFS      */  PACK( 2, 0 ),
    742     /*  MD[0]     */  PACK( 2, 1 ),
    743     /*  MD[1]     */  PACK( 2, 1 ),
    744     /*  MPPEM     */  PACK( 0, 1 ),
    745     /*  MPS       */  PACK( 0, 1 ),
    746     /*  FlipON    */  PACK( 0, 0 ),
    747     /*  FlipOFF   */  PACK( 0, 0 ),
    748     /*  DEBUG     */  PACK( 1, 0 ),
    749 
    750     /*  LT        */  PACK( 2, 1 ),
    751     /*  LTEQ      */  PACK( 2, 1 ),
    752     /*  GT        */  PACK( 2, 1 ),
    753     /*  GTEQ      */  PACK( 2, 1 ),
    754     /*  EQ        */  PACK( 2, 1 ),
    755     /*  NEQ       */  PACK( 2, 1 ),
    756     /*  ODD       */  PACK( 1, 1 ),
    757     /*  EVEN      */  PACK( 1, 1 ),
    758     /*  IF        */  PACK( 1, 0 ),
    759     /*  EIF       */  PACK( 0, 0 ),
    760     /*  AND       */  PACK( 2, 1 ),
    761     /*  OR        */  PACK( 2, 1 ),
    762     /*  NOT       */  PACK( 1, 1 ),
    763     /*  DeltaP1   */  PACK( 1, 0 ),
    764     /*  SDB       */  PACK( 1, 0 ),
    765     /*  SDS       */  PACK( 1, 0 ),
    766 
    767     /*  ADD       */  PACK( 2, 1 ),
    768     /*  SUB       */  PACK( 2, 1 ),
    769     /*  DIV       */  PACK( 2, 1 ),
    770     /*  MUL       */  PACK( 2, 1 ),
    771     /*  ABS       */  PACK( 1, 1 ),
    772     /*  NEG       */  PACK( 1, 1 ),
    773     /*  FLOOR     */  PACK( 1, 1 ),
    774     /*  CEILING   */  PACK( 1, 1 ),
    775     /*  ROUND[0]  */  PACK( 1, 1 ),
    776     /*  ROUND[1]  */  PACK( 1, 1 ),
    777     /*  ROUND[2]  */  PACK( 1, 1 ),
    778     /*  ROUND[3]  */  PACK( 1, 1 ),
    779     /*  NROUND[0] */  PACK( 1, 1 ),
    780     /*  NROUND[1] */  PACK( 1, 1 ),
    781     /*  NROUND[2] */  PACK( 1, 1 ),
    782     /*  NROUND[3] */  PACK( 1, 1 ),
    783 
    784     /*  WCvtF     */  PACK( 2, 0 ),
    785     /*  DeltaP2   */  PACK( 1, 0 ),
    786     /*  DeltaP3   */  PACK( 1, 0 ),
    787     /*  DeltaCn[0] */ PACK( 1, 0 ),
    788     /*  DeltaCn[1] */ PACK( 1, 0 ),
    789     /*  DeltaCn[2] */ PACK( 1, 0 ),
    790     /*  SROUND    */  PACK( 1, 0 ),
    791     /*  S45Round  */  PACK( 1, 0 ),
    792     /*  JROT      */  PACK( 2, 0 ),
    793     /*  JROF      */  PACK( 2, 0 ),
    794     /*  ROFF      */  PACK( 0, 0 ),
    795     /*  INS_$7B   */  PACK( 0, 0 ),
    796     /*  RUTG      */  PACK( 0, 0 ),
    797     /*  RDTG      */  PACK( 0, 0 ),
    798     /*  SANGW     */  PACK( 1, 0 ),
    799     /*  AA        */  PACK( 1, 0 ),
    800 
    801     /*  FlipPT    */  PACK( 0, 0 ), /* loops */
    802     /*  FlipRgON  */  PACK( 2, 0 ),
    803     /*  FlipRgOFF */  PACK( 2, 0 ),
    804     /*  INS_$83   */  PACK( 0, 0 ),
    805     /*  INS_$84   */  PACK( 0, 0 ),
    806     /*  ScanCTRL  */  PACK( 1, 0 ),
    807     /*  SDPvTL[0] */  PACK( 2, 0 ),
    808     /*  SDPvTL[1] */  PACK( 2, 0 ),
    809     /*  GetINFO   */  PACK( 1, 1 ),
    810     /*  IDEF      */  PACK( 1, 0 ),
    811     /*  ROLL      */  PACK( 3, 3 ),
    812     /*  MAX       */  PACK( 2, 1 ),
    813     /*  MIN       */  PACK( 2, 1 ),
    814     /*  ScanTYPE  */  PACK( 1, 0 ),
    815     /*  InstCTRL  */  PACK( 2, 0 ),
    816     /*  INS_$8F   */  PACK( 0, 0 ),
    817 
    818     /*  INS_$90  */   PACK( 0, 0 ),
    819     /*  GETVAR   */   PACK( 0, 0 ), /* will be handled specially */
    820     /*  GETDATA  */   PACK( 0, 1 ),
    821     /*  INS_$93  */   PACK( 0, 0 ),
    822     /*  INS_$94  */   PACK( 0, 0 ),
    823     /*  INS_$95  */   PACK( 0, 0 ),
    824     /*  INS_$96  */   PACK( 0, 0 ),
    825     /*  INS_$97  */   PACK( 0, 0 ),
    826     /*  INS_$98  */   PACK( 0, 0 ),
    827     /*  INS_$99  */   PACK( 0, 0 ),
    828     /*  INS_$9A  */   PACK( 0, 0 ),
    829     /*  INS_$9B  */   PACK( 0, 0 ),
    830     /*  INS_$9C  */   PACK( 0, 0 ),
    831     /*  INS_$9D  */   PACK( 0, 0 ),
    832     /*  INS_$9E  */   PACK( 0, 0 ),
    833     /*  INS_$9F  */   PACK( 0, 0 ),
    834 
    835     /*  INS_$A0  */   PACK( 0, 0 ),
    836     /*  INS_$A1  */   PACK( 0, 0 ),
    837     /*  INS_$A2  */   PACK( 0, 0 ),
    838     /*  INS_$A3  */   PACK( 0, 0 ),
    839     /*  INS_$A4  */   PACK( 0, 0 ),
    840     /*  INS_$A5  */   PACK( 0, 0 ),
    841     /*  INS_$A6  */   PACK( 0, 0 ),
    842     /*  INS_$A7  */   PACK( 0, 0 ),
    843     /*  INS_$A8  */   PACK( 0, 0 ),
    844     /*  INS_$A9  */   PACK( 0, 0 ),
    845     /*  INS_$AA  */   PACK( 0, 0 ),
    846     /*  INS_$AB  */   PACK( 0, 0 ),
    847     /*  INS_$AC  */   PACK( 0, 0 ),
    848     /*  INS_$AD  */   PACK( 0, 0 ),
    849     /*  INS_$AE  */   PACK( 0, 0 ),
    850     /*  INS_$AF  */   PACK( 0, 0 ),
    851 
    852     /*  PushB[0]  */  PACK( 0, 1 ),
    853     /*  PushB[1]  */  PACK( 0, 2 ),
    854     /*  PushB[2]  */  PACK( 0, 3 ),
    855     /*  PushB[3]  */  PACK( 0, 4 ),
    856     /*  PushB[4]  */  PACK( 0, 5 ),
    857     /*  PushB[5]  */  PACK( 0, 6 ),
    858     /*  PushB[6]  */  PACK( 0, 7 ),
    859     /*  PushB[7]  */  PACK( 0, 8 ),
    860     /*  PushW[0]  */  PACK( 0, 1 ),
    861     /*  PushW[1]  */  PACK( 0, 2 ),
    862     /*  PushW[2]  */  PACK( 0, 3 ),
    863     /*  PushW[3]  */  PACK( 0, 4 ),
    864     /*  PushW[4]  */  PACK( 0, 5 ),
    865     /*  PushW[5]  */  PACK( 0, 6 ),
    866     /*  PushW[6]  */  PACK( 0, 7 ),
    867     /*  PushW[7]  */  PACK( 0, 8 ),
    868 
    869     /*  MDRP[00]  */  PACK( 1, 0 ),
    870     /*  MDRP[01]  */  PACK( 1, 0 ),
    871     /*  MDRP[02]  */  PACK( 1, 0 ),
    872     /*  MDRP[03]  */  PACK( 1, 0 ),
    873     /*  MDRP[04]  */  PACK( 1, 0 ),
    874     /*  MDRP[05]  */  PACK( 1, 0 ),
    875     /*  MDRP[06]  */  PACK( 1, 0 ),
    876     /*  MDRP[07]  */  PACK( 1, 0 ),
    877     /*  MDRP[08]  */  PACK( 1, 0 ),
    878     /*  MDRP[09]  */  PACK( 1, 0 ),
    879     /*  MDRP[10]  */  PACK( 1, 0 ),
    880     /*  MDRP[11]  */  PACK( 1, 0 ),
    881     /*  MDRP[12]  */  PACK( 1, 0 ),
    882     /*  MDRP[13]  */  PACK( 1, 0 ),
    883     /*  MDRP[14]  */  PACK( 1, 0 ),
    884     /*  MDRP[15]  */  PACK( 1, 0 ),
    885 
    886     /*  MDRP[16]  */  PACK( 1, 0 ),
    887     /*  MDRP[17]  */  PACK( 1, 0 ),
    888     /*  MDRP[18]  */  PACK( 1, 0 ),
    889     /*  MDRP[19]  */  PACK( 1, 0 ),
    890     /*  MDRP[20]  */  PACK( 1, 0 ),
    891     /*  MDRP[21]  */  PACK( 1, 0 ),
    892     /*  MDRP[22]  */  PACK( 1, 0 ),
    893     /*  MDRP[23]  */  PACK( 1, 0 ),
    894     /*  MDRP[24]  */  PACK( 1, 0 ),
    895     /*  MDRP[25]  */  PACK( 1, 0 ),
    896     /*  MDRP[26]  */  PACK( 1, 0 ),
    897     /*  MDRP[27]  */  PACK( 1, 0 ),
    898     /*  MDRP[28]  */  PACK( 1, 0 ),
    899     /*  MDRP[29]  */  PACK( 1, 0 ),
    900     /*  MDRP[30]  */  PACK( 1, 0 ),
    901     /*  MDRP[31]  */  PACK( 1, 0 ),
    902 
    903     /*  MIRP[00]  */  PACK( 2, 0 ),
    904     /*  MIRP[01]  */  PACK( 2, 0 ),
    905     /*  MIRP[02]  */  PACK( 2, 0 ),
    906     /*  MIRP[03]  */  PACK( 2, 0 ),
    907     /*  MIRP[04]  */  PACK( 2, 0 ),
    908     /*  MIRP[05]  */  PACK( 2, 0 ),
    909     /*  MIRP[06]  */  PACK( 2, 0 ),
    910     /*  MIRP[07]  */  PACK( 2, 0 ),
    911     /*  MIRP[08]  */  PACK( 2, 0 ),
    912     /*  MIRP[09]  */  PACK( 2, 0 ),
    913     /*  MIRP[10]  */  PACK( 2, 0 ),
    914     /*  MIRP[11]  */  PACK( 2, 0 ),
    915     /*  MIRP[12]  */  PACK( 2, 0 ),
    916     /*  MIRP[13]  */  PACK( 2, 0 ),
    917     /*  MIRP[14]  */  PACK( 2, 0 ),
    918     /*  MIRP[15]  */  PACK( 2, 0 ),
    919 
    920     /*  MIRP[16]  */  PACK( 2, 0 ),
    921     /*  MIRP[17]  */  PACK( 2, 0 ),
    922     /*  MIRP[18]  */  PACK( 2, 0 ),
    923     /*  MIRP[19]  */  PACK( 2, 0 ),
    924     /*  MIRP[20]  */  PACK( 2, 0 ),
    925     /*  MIRP[21]  */  PACK( 2, 0 ),
    926     /*  MIRP[22]  */  PACK( 2, 0 ),
    927     /*  MIRP[23]  */  PACK( 2, 0 ),
    928     /*  MIRP[24]  */  PACK( 2, 0 ),
    929     /*  MIRP[25]  */  PACK( 2, 0 ),
    930     /*  MIRP[26]  */  PACK( 2, 0 ),
    931     /*  MIRP[27]  */  PACK( 2, 0 ),
    932     /*  MIRP[28]  */  PACK( 2, 0 ),
    933     /*  MIRP[29]  */  PACK( 2, 0 ),
    934     /*  MIRP[30]  */  PACK( 2, 0 ),
    935     /*  MIRP[31]  */  PACK( 2, 0 )
    936   };
    937 
    938 
    939 #ifdef FT_DEBUG_LEVEL_TRACE
    940 
    941   /* the first hex digit gives the length of the opcode name; the space */
    942   /* after the digit is here just to increase readability of the source */
    943   /* code                                                               */
    944 
    945   static
    946   const char*  const opcode_name[256] =
    947   {
    948     "7 SVTCA y",
    949     "7 SVTCA x",
    950     "8 SPvTCA y",
    951     "8 SPvTCA x",
    952     "8 SFvTCA y",
    953     "8 SFvTCA x",
    954     "8 SPvTL ||",
    955     "7 SPvTL +",
    956     "8 SFvTL ||",
    957     "7 SFvTL +",
    958     "5 SPvFS",
    959     "5 SFvFS",
    960     "3 GPv",
    961     "3 GFv",
    962     "6 SFvTPv",
    963     "5 ISECT",
    964 
    965     "4 SRP0",
    966     "4 SRP1",
    967     "4 SRP2",
    968     "4 SZP0",
    969     "4 SZP1",
    970     "4 SZP2",
    971     "4 SZPS",
    972     "5 SLOOP",
    973     "3 RTG",
    974     "4 RTHG",
    975     "3 SMD",
    976     "4 ELSE",
    977     "4 JMPR",
    978     "6 SCvTCi",
    979     "5 SSwCi",
    980     "3 SSW",
    981 
    982     "3 DUP",
    983     "3 POP",
    984     "5 CLEAR",
    985     "4 SWAP",
    986     "5 DEPTH",
    987     "6 CINDEX",
    988     "6 MINDEX",
    989     "8 AlignPTS",
    990     "7 INS_$28",
    991     "3 UTP",
    992     "8 LOOPCALL",
    993     "4 CALL",
    994     "4 FDEF",
    995     "4 ENDF",
    996     "7 MDAP[0]",
    997     "7 MDAP[1]",
    998 
    999     "6 IUP[0]",
   1000     "6 IUP[1]",
   1001     "6 SHP[0]",
   1002     "6 SHP[1]",
   1003     "6 SHC[0]",
   1004     "6 SHC[1]",
   1005     "6 SHZ[0]",
   1006     "6 SHZ[1]",
   1007     "5 SHPIX",
   1008     "2 IP",
   1009     "8 MSIRP[0]",
   1010     "8 MSIRP[1]",
   1011     "7 AlignRP",
   1012     "4 RTDG",
   1013     "7 MIAP[0]",
   1014     "7 MIAP[1]",
   1015 
   1016     "6 NPushB",
   1017     "6 NPushW",
   1018     "2 WS",
   1019     "2 RS",
   1020     "5 WCvtP",
   1021     "4 RCvt",
   1022     "5 GC[0]",
   1023     "5 GC[1]",
   1024     "4 SCFS",
   1025     "5 MD[0]",
   1026     "5 MD[1]",
   1027     "5 MPPEM",
   1028     "3 MPS",
   1029     "6 FlipON",
   1030     "7 FlipOFF",
   1031     "5 DEBUG",
   1032 
   1033     "2 LT",
   1034     "4 LTEQ",
   1035     "2 GT",
   1036     "4 GTEQ",
   1037     "2 EQ",
   1038     "3 NEQ",
   1039     "3 ODD",
   1040     "4 EVEN",
   1041     "2 IF",
   1042     "3 EIF",
   1043     "3 AND",
   1044     "2 OR",
   1045     "3 NOT",
   1046     "7 DeltaP1",
   1047     "3 SDB",
   1048     "3 SDS",
   1049 
   1050     "3 ADD",
   1051     "3 SUB",
   1052     "3 DIV",
   1053     "3 MUL",
   1054     "3 ABS",
   1055     "3 NEG",
   1056     "5 FLOOR",
   1057     "7 CEILING",
   1058     "8 ROUND[0]",
   1059     "8 ROUND[1]",
   1060     "8 ROUND[2]",
   1061     "8 ROUND[3]",
   1062     "9 NROUND[0]",
   1063     "9 NROUND[1]",
   1064     "9 NROUND[2]",
   1065     "9 NROUND[3]",
   1066 
   1067     "5 WCvtF",
   1068     "7 DeltaP2",
   1069     "7 DeltaP3",
   1070     "A DeltaCn[0]",
   1071     "A DeltaCn[1]",
   1072     "A DeltaCn[2]",
   1073     "6 SROUND",
   1074     "8 S45Round",
   1075     "4 JROT",
   1076     "4 JROF",
   1077     "4 ROFF",
   1078     "7 INS_$7B",
   1079     "4 RUTG",
   1080     "4 RDTG",
   1081     "5 SANGW",
   1082     "2 AA",
   1083 
   1084     "6 FlipPT",
   1085     "8 FlipRgON",
   1086     "9 FlipRgOFF",
   1087     "7 INS_$83",
   1088     "7 INS_$84",
   1089     "8 ScanCTRL",
   1090     "9 SDPvTL[0]",
   1091     "9 SDPvTL[1]",
   1092     "7 GetINFO",
   1093     "4 IDEF",
   1094     "4 ROLL",
   1095     "3 MAX",
   1096     "3 MIN",
   1097     "8 ScanTYPE",
   1098     "8 InstCTRL",
   1099     "7 INS_$8F",
   1100 
   1101     "7 INS_$90",
   1102 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   1103     "6 GETVAR",
   1104     "7 GETDATA",
   1105 #else
   1106     "7 INS_$91",
   1107     "7 INS_$92",
   1108 #endif
   1109     "7 INS_$93",
   1110     "7 INS_$94",
   1111     "7 INS_$95",
   1112     "7 INS_$96",
   1113     "7 INS_$97",
   1114     "7 INS_$98",
   1115     "7 INS_$99",
   1116     "7 INS_$9A",
   1117     "7 INS_$9B",
   1118     "7 INS_$9C",
   1119     "7 INS_$9D",
   1120     "7 INS_$9E",
   1121     "7 INS_$9F",
   1122 
   1123     "7 INS_$A0",
   1124     "7 INS_$A1",
   1125     "7 INS_$A2",
   1126     "7 INS_$A3",
   1127     "7 INS_$A4",
   1128     "7 INS_$A5",
   1129     "7 INS_$A6",
   1130     "7 INS_$A7",
   1131     "7 INS_$A8",
   1132     "7 INS_$A9",
   1133     "7 INS_$AA",
   1134     "7 INS_$AB",
   1135     "7 INS_$AC",
   1136     "7 INS_$AD",
   1137     "7 INS_$AE",
   1138     "7 INS_$AF",
   1139 
   1140     "8 PushB[0]",
   1141     "8 PushB[1]",
   1142     "8 PushB[2]",
   1143     "8 PushB[3]",
   1144     "8 PushB[4]",
   1145     "8 PushB[5]",
   1146     "8 PushB[6]",
   1147     "8 PushB[7]",
   1148     "8 PushW[0]",
   1149     "8 PushW[1]",
   1150     "8 PushW[2]",
   1151     "8 PushW[3]",
   1152     "8 PushW[4]",
   1153     "8 PushW[5]",
   1154     "8 PushW[6]",
   1155     "8 PushW[7]",
   1156 
   1157     "7 MDRP[G]",
   1158     "7 MDRP[B]",
   1159     "7 MDRP[W]",
   1160     "7 MDRP[?]",
   1161     "8 MDRP[rG]",
   1162     "8 MDRP[rB]",
   1163     "8 MDRP[rW]",
   1164     "8 MDRP[r?]",
   1165     "8 MDRP[mG]",
   1166     "8 MDRP[mB]",
   1167     "8 MDRP[mW]",
   1168     "8 MDRP[m?]",
   1169     "9 MDRP[mrG]",
   1170     "9 MDRP[mrB]",
   1171     "9 MDRP[mrW]",
   1172     "9 MDRP[mr?]",
   1173 
   1174     "8 MDRP[pG]",
   1175     "8 MDRP[pB]",
   1176     "8 MDRP[pW]",
   1177     "8 MDRP[p?]",
   1178     "9 MDRP[prG]",
   1179     "9 MDRP[prB]",
   1180     "9 MDRP[prW]",
   1181     "9 MDRP[pr?]",
   1182     "9 MDRP[pmG]",
   1183     "9 MDRP[pmB]",
   1184     "9 MDRP[pmW]",
   1185     "9 MDRP[pm?]",
   1186     "A MDRP[pmrG]",
   1187     "A MDRP[pmrB]",
   1188     "A MDRP[pmrW]",
   1189     "A MDRP[pmr?]",
   1190 
   1191     "7 MIRP[G]",
   1192     "7 MIRP[B]",
   1193     "7 MIRP[W]",
   1194     "7 MIRP[?]",
   1195     "8 MIRP[rG]",
   1196     "8 MIRP[rB]",
   1197     "8 MIRP[rW]",
   1198     "8 MIRP[r?]",
   1199     "8 MIRP[mG]",
   1200     "8 MIRP[mB]",
   1201     "8 MIRP[mW]",
   1202     "8 MIRP[m?]",
   1203     "9 MIRP[mrG]",
   1204     "9 MIRP[mrB]",
   1205     "9 MIRP[mrW]",
   1206     "9 MIRP[mr?]",
   1207 
   1208     "8 MIRP[pG]",
   1209     "8 MIRP[pB]",
   1210     "8 MIRP[pW]",
   1211     "8 MIRP[p?]",
   1212     "9 MIRP[prG]",
   1213     "9 MIRP[prB]",
   1214     "9 MIRP[prW]",
   1215     "9 MIRP[pr?]",
   1216     "9 MIRP[pmG]",
   1217     "9 MIRP[pmB]",
   1218     "9 MIRP[pmW]",
   1219     "9 MIRP[pm?]",
   1220     "A MIRP[pmrG]",
   1221     "A MIRP[pmrB]",
   1222     "A MIRP[pmrW]",
   1223     "A MIRP[pmr?]"
   1224   };
   1225 
   1226 #endif /* FT_DEBUG_LEVEL_TRACE */
   1227 
   1228 
   1229   static
   1230   const FT_Char  opcode_length[256] =
   1231   {
   1232     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1233     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1234     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1235     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1236 
   1237    -1,-2, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1238     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1239     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1240     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1241 
   1242     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1243     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1244     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1245     2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,
   1246 
   1247     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1248     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1249     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
   1250     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
   1251   };
   1252 
   1253 #undef PACK
   1254 
   1255 
   1256 #ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
   1257 
   1258 #if defined( __arm__ )                                 && \
   1259     ( defined( __thumb2__ ) || !defined( __thumb__ ) )
   1260 
   1261 #define TT_MulFix14  TT_MulFix14_arm
   1262 
   1263   static FT_Int32
   1264   TT_MulFix14_arm( FT_Int32  a,
   1265                    FT_Int    b )
   1266   {
   1267     FT_Int32  t, t2;
   1268 
   1269 
   1270 #if defined( __CC_ARM ) || defined( __ARMCC__ )
   1271 
   1272     __asm
   1273     {
   1274       smull t2, t,  b,  a           /* (lo=t2,hi=t) = a*b */
   1275       mov   a,  t,  asr #31         /* a   = (hi >> 31) */
   1276       add   a,  a,  #0x2000         /* a  += 0x2000 */
   1277       adds  t2, t2, a               /* t2 += a */
   1278       adc   t,  t,  #0              /* t  += carry */
   1279       mov   a,  t2, lsr #14         /* a   = t2 >> 14 */
   1280       orr   a,  a,  t,  lsl #18     /* a  |= t << 18 */
   1281     }
   1282 
   1283 #elif defined( __GNUC__ )
   1284 
   1285     __asm__ __volatile__ (
   1286       "smull  %1, %2, %4, %3\n\t"       /* (lo=%1,hi=%2) = a*b */
   1287       "mov    %0, %2, asr #31\n\t"      /* %0  = (hi >> 31) */
   1288 #if defined( __clang__ ) && defined( __thumb2__ )
   1289       "add.w  %0, %0, #0x2000\n\t"      /* %0 += 0x2000 */
   1290 #else
   1291       "add    %0, %0, #0x2000\n\t"      /* %0 += 0x2000 */
   1292 #endif
   1293       "adds   %1, %1, %0\n\t"           /* %1 += %0 */
   1294       "adc    %2, %2, #0\n\t"           /* %2 += carry */
   1295       "mov    %0, %1, lsr #14\n\t"      /* %0  = %1 >> 16 */
   1296       "orr    %0, %0, %2, lsl #18\n\t"  /* %0 |= %2 << 16 */
   1297       : "=r"(a), "=&r"(t2), "=&r"(t)
   1298       : "r"(a), "r"(b)
   1299       : "cc" );
   1300 
   1301 #endif
   1302 
   1303     return a;
   1304   }
   1305 
   1306 #endif /* __arm__ && ( __thumb2__ || !__thumb__ ) */
   1307 
   1308 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
   1309 
   1310 
   1311 #if defined( __GNUC__ )                              && \
   1312     ( defined( __i386__ ) || defined( __x86_64__ ) )
   1313 
   1314 #define TT_MulFix14  TT_MulFix14_long_long
   1315 
   1316   /* Temporarily disable the warning that C90 doesn't support `long long'. */
   1317 #if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
   1318 #pragma GCC diagnostic push
   1319 #endif
   1320 #pragma GCC diagnostic ignored "-Wlong-long"
   1321 
   1322   /* This is declared `noinline' because inlining the function results */
   1323   /* in slower code.  The `pure' attribute indicates that the result   */
   1324   /* only depends on the parameters.                                   */
   1325   static __attribute__(( noinline ))
   1326          __attribute__(( pure )) FT_Int32
   1327   TT_MulFix14_long_long( FT_Int32  a,
   1328                          FT_Int    b )
   1329   {
   1330 
   1331     long long  ret = (long long)a * b;
   1332 
   1333     /* The following line assumes that right shifting of signed values */
   1334     /* will actually preserve the sign bit.  The exact behaviour is    */
   1335     /* undefined, but this is true on x86 and x86_64.                  */
   1336     long long  tmp = ret >> 63;
   1337 
   1338 
   1339     ret += 0x2000 + tmp;
   1340 
   1341     return (FT_Int32)( ret >> 14 );
   1342   }
   1343 
   1344 #if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
   1345 #pragma GCC diagnostic pop
   1346 #endif
   1347 
   1348 #endif /* __GNUC__ && ( __i386__ || __x86_64__ ) */
   1349 
   1350 
   1351 #ifndef TT_MulFix14
   1352 
   1353   /* Compute (a*b)/2^14 with maximum accuracy and rounding.  */
   1354   /* This is optimized to be faster than calling FT_MulFix() */
   1355   /* for platforms where sizeof(int) == 2.                   */
   1356   static FT_Int32
   1357   TT_MulFix14( FT_Int32  a,
   1358                FT_Int    b )
   1359   {
   1360     FT_Int32   sign;
   1361     FT_UInt32  ah, al, mid, lo, hi;
   1362 
   1363 
   1364     sign = a ^ b;
   1365 
   1366     if ( a < 0 )
   1367       a = -a;
   1368     if ( b < 0 )
   1369       b = -b;
   1370 
   1371     ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
   1372     al = (FT_UInt32)( a & 0xFFFFU );
   1373 
   1374     lo    = al * b;
   1375     mid   = ah * b;
   1376     hi    = mid >> 16;
   1377     mid   = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
   1378     lo   += mid;
   1379     if ( lo < mid )
   1380       hi += 1;
   1381 
   1382     mid = ( lo >> 14 ) | ( hi << 18 );
   1383 
   1384     return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
   1385   }
   1386 
   1387 #endif  /* !TT_MulFix14 */
   1388 
   1389 
   1390 #if defined( __GNUC__ )        && \
   1391     ( defined( __i386__ )   ||    \
   1392       defined( __x86_64__ ) ||    \
   1393       defined( __arm__ )    )
   1394 
   1395 #define TT_DotFix14  TT_DotFix14_long_long
   1396 
   1397 #if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
   1398 #pragma GCC diagnostic push
   1399 #endif
   1400 #pragma GCC diagnostic ignored "-Wlong-long"
   1401 
   1402   static __attribute__(( pure )) FT_Int32
   1403   TT_DotFix14_long_long( FT_Int32  ax,
   1404                          FT_Int32  ay,
   1405                          FT_Int    bx,
   1406                          FT_Int    by )
   1407   {
   1408     /* Temporarily disable the warning that C90 doesn't support */
   1409     /* `long long'.                                             */
   1410 
   1411     long long  temp1 = (long long)ax * bx;
   1412     long long  temp2 = (long long)ay * by;
   1413 
   1414 
   1415     temp1 += temp2;
   1416     temp2  = temp1 >> 63;
   1417     temp1 += 0x2000 + temp2;
   1418 
   1419     return (FT_Int32)( temp1 >> 14 );
   1420 
   1421   }
   1422 
   1423 #if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
   1424 #pragma GCC diagnostic pop
   1425 #endif
   1426 
   1427 #endif /* __GNUC__ && (__arm__ || __i386__ || __x86_64__) */
   1428 
   1429 
   1430 #ifndef TT_DotFix14
   1431 
   1432   /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
   1433   static FT_Int32
   1434   TT_DotFix14( FT_Int32  ax,
   1435                FT_Int32  ay,
   1436                FT_Int    bx,
   1437                FT_Int    by )
   1438   {
   1439     FT_Int32   m, s, hi1, hi2, hi;
   1440     FT_UInt32  l, lo1, lo2, lo;
   1441 
   1442 
   1443     /* compute ax*bx as 64-bit value */
   1444     l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
   1445     m = ( ax >> 16 ) * bx;
   1446 
   1447     lo1 = l + ( (FT_UInt32)m << 16 );
   1448     hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
   1449 
   1450     /* compute ay*by as 64-bit value */
   1451     l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
   1452     m = ( ay >> 16 ) * by;
   1453 
   1454     lo2 = l + ( (FT_UInt32)m << 16 );
   1455     hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
   1456 
   1457     /* add them */
   1458     lo = lo1 + lo2;
   1459     hi = hi1 + hi2 + ( lo < lo1 );
   1460 
   1461     /* divide the result by 2^14 with rounding */
   1462     s   = hi >> 31;
   1463     l   = lo + (FT_UInt32)s;
   1464     hi += s + ( l < lo );
   1465     lo  = l;
   1466 
   1467     l   = lo + 0x2000U;
   1468     hi += ( l < lo );
   1469 
   1470     return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
   1471   }
   1472 
   1473 #endif /* TT_DotFix14 */
   1474 
   1475 
   1476   /**************************************************************************
   1477    *
   1478    * @Function:
   1479    *   Current_Ratio
   1480    *
   1481    * @Description:
   1482    *   Returns the current aspect ratio scaling factor depending on the
   1483    *   projection vector's state and device resolutions.
   1484    *
   1485    * @Return:
   1486    *   The aspect ratio in 16.16 format, always <= 1.0 .
   1487    */
   1488   static FT_Long
   1489   Current_Ratio( TT_ExecContext  exc )
   1490   {
   1491     if ( !exc->tt_metrics.ratio )
   1492     {
   1493       if ( exc->GS.projVector.y == 0 )
   1494         exc->tt_metrics.ratio = exc->tt_metrics.x_ratio;
   1495 
   1496       else if ( exc->GS.projVector.x == 0 )
   1497         exc->tt_metrics.ratio = exc->tt_metrics.y_ratio;
   1498 
   1499       else
   1500       {
   1501         FT_F26Dot6  x, y;
   1502 
   1503 
   1504         x = TT_MulFix14( exc->tt_metrics.x_ratio,
   1505                          exc->GS.projVector.x );
   1506         y = TT_MulFix14( exc->tt_metrics.y_ratio,
   1507                          exc->GS.projVector.y );
   1508         exc->tt_metrics.ratio = FT_Hypot( x, y );
   1509       }
   1510     }
   1511     return exc->tt_metrics.ratio;
   1512   }
   1513 
   1514 
   1515   FT_CALLBACK_DEF( FT_Long )
   1516   Current_Ppem( TT_ExecContext  exc )
   1517   {
   1518     return exc->tt_metrics.ppem;
   1519   }
   1520 
   1521 
   1522   FT_CALLBACK_DEF( FT_Long )
   1523   Current_Ppem_Stretched( TT_ExecContext  exc )
   1524   {
   1525     return FT_MulFix( exc->tt_metrics.ppem, Current_Ratio( exc ) );
   1526   }
   1527 
   1528 
   1529   /**************************************************************************
   1530    *
   1531    * Functions related to the control value table (CVT).
   1532    *
   1533    */
   1534 
   1535 
   1536   FT_CALLBACK_DEF( FT_F26Dot6 )
   1537   Read_CVT( TT_ExecContext  exc,
   1538             FT_ULong        idx )
   1539   {
   1540     return exc->cvt[idx];
   1541   }
   1542 
   1543 
   1544   FT_CALLBACK_DEF( FT_F26Dot6 )
   1545   Read_CVT_Stretched( TT_ExecContext  exc,
   1546                       FT_ULong        idx )
   1547   {
   1548     return FT_MulFix( exc->cvt[idx], Current_Ratio( exc ) );
   1549   }
   1550 
   1551 
   1552   FT_CALLBACK_DEF( void )
   1553   Write_CVT( TT_ExecContext  exc,
   1554              FT_ULong        idx,
   1555              FT_F26Dot6      value )
   1556   {
   1557     exc->cvt[idx] = value;
   1558   }
   1559 
   1560 
   1561   FT_CALLBACK_DEF( void )
   1562   Write_CVT_Stretched( TT_ExecContext  exc,
   1563                        FT_ULong        idx,
   1564                        FT_F26Dot6      value )
   1565   {
   1566     exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) );
   1567   }
   1568 
   1569 
   1570   FT_CALLBACK_DEF( void )
   1571   Move_CVT( TT_ExecContext  exc,
   1572             FT_ULong        idx,
   1573             FT_F26Dot6      value )
   1574   {
   1575     exc->cvt[idx] += value;
   1576   }
   1577 
   1578 
   1579   FT_CALLBACK_DEF( void )
   1580   Move_CVT_Stretched( TT_ExecContext  exc,
   1581                       FT_ULong        idx,
   1582                       FT_F26Dot6      value )
   1583   {
   1584     exc->cvt[idx] += FT_DivFix( value, Current_Ratio( exc ) );
   1585   }
   1586 
   1587 
   1588   /**************************************************************************
   1589    *
   1590    * @Function:
   1591    *   GetShortIns
   1592    *
   1593    * @Description:
   1594    *   Returns a short integer taken from the instruction stream at
   1595    *   address IP.
   1596    *
   1597    * @Return:
   1598    *   Short read at code[IP].
   1599    *
   1600    * @Note:
   1601    *   This one could become a macro.
   1602    */
   1603   static FT_Short
   1604   GetShortIns( TT_ExecContext  exc )
   1605   {
   1606     /* Reading a byte stream so there is no endianness (DaveP) */
   1607     exc->IP += 2;
   1608     return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) +
   1609                          exc->code[exc->IP - 1]      );
   1610   }
   1611 
   1612 
   1613   /**************************************************************************
   1614    *
   1615    * @Function:
   1616    *   Ins_Goto_CodeRange
   1617    *
   1618    * @Description:
   1619    *   Goes to a certain code range in the instruction stream.
   1620    *
   1621    * @Input:
   1622    *   aRange ::
   1623    *     The index of the code range.
   1624    *
   1625    *   aIP ::
   1626    *     The new IP address in the code range.
   1627    *
   1628    * @Return:
   1629    *   SUCCESS or FAILURE.
   1630    */
   1631   static FT_Bool
   1632   Ins_Goto_CodeRange( TT_ExecContext  exc,
   1633                       FT_Int          aRange,
   1634                       FT_Long         aIP )
   1635   {
   1636     TT_CodeRange*  range;
   1637 
   1638 
   1639     if ( aRange < 1 || aRange > 3 )
   1640     {
   1641       exc->error = FT_THROW( Bad_Argument );
   1642       return FAILURE;
   1643     }
   1644 
   1645     range = &exc->codeRangeTable[aRange - 1];
   1646 
   1647     if ( !range->base )     /* invalid coderange */
   1648     {
   1649       exc->error = FT_THROW( Invalid_CodeRange );
   1650       return FAILURE;
   1651     }
   1652 
   1653     /* NOTE: Because the last instruction of a program may be a CALL */
   1654     /*       which will return to the first byte *after* the code    */
   1655     /*       range, we test for aIP <= Size, instead of aIP < Size.  */
   1656 
   1657     if ( aIP > range->size )
   1658     {
   1659       exc->error = FT_THROW( Code_Overflow );
   1660       return FAILURE;
   1661     }
   1662 
   1663     exc->code     = range->base;
   1664     exc->codeSize = range->size;
   1665     exc->IP       = aIP;
   1666     exc->curRange = aRange;
   1667 
   1668     return SUCCESS;
   1669   }
   1670 
   1671 
   1672   /**************************************************************************
   1673    *
   1674    * @Function:
   1675    *   Direct_Move
   1676    *
   1677    * @Description:
   1678    *   Moves a point by a given distance along the freedom vector.  The
   1679    *   point will be `touched'.
   1680    *
   1681    * @Input:
   1682    *   point ::
   1683    *     The index of the point to move.
   1684    *
   1685    *   distance ::
   1686    *     The distance to apply.
   1687    *
   1688    * @InOut:
   1689    *   zone ::
   1690    *     The affected glyph zone.
   1691    *
   1692    * @Note:
   1693    *   See `ttinterp.h' for details on backward compatibility mode.
   1694    *   `Touches' the point.
   1695    */
   1696   static void
   1697   Direct_Move( TT_ExecContext  exc,
   1698                TT_GlyphZone    zone,
   1699                FT_UShort       point,
   1700                FT_F26Dot6      distance )
   1701   {
   1702     FT_F26Dot6  v;
   1703 
   1704 
   1705     v = exc->GS.freeVector.x;
   1706 
   1707     if ( v != 0 )
   1708     {
   1709 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   1710       if ( SUBPIXEL_HINTING_INFINALITY                            &&
   1711            ( !exc->ignore_x_mode                                ||
   1712              ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
   1713         zone->cur[point].x = ADD_LONG( zone->cur[point].x,
   1714                                        FT_MulDiv( distance,
   1715                                                   v,
   1716                                                   exc->F_dot_P ) );
   1717       else
   1718 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   1719 
   1720 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   1721       /* Exception to the post-IUP curfew: Allow the x component of */
   1722       /* diagonal moves, but only post-IUP.  DejaVu tries to adjust */
   1723       /* diagonal stems like on `Z' and `z' post-IUP.               */
   1724       if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
   1725         zone->cur[point].x = ADD_LONG( zone->cur[point].x,
   1726                                        FT_MulDiv( distance,
   1727                                                   v,
   1728                                                   exc->F_dot_P ) );
   1729       else
   1730 #endif
   1731 
   1732       if ( NO_SUBPIXEL_HINTING )
   1733         zone->cur[point].x = ADD_LONG( zone->cur[point].x,
   1734                                        FT_MulDiv( distance,
   1735                                                   v,
   1736                                                   exc->F_dot_P ) );
   1737 
   1738       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
   1739     }
   1740 
   1741     v = exc->GS.freeVector.y;
   1742 
   1743     if ( v != 0 )
   1744     {
   1745 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   1746       if ( !( SUBPIXEL_HINTING_MINIMAL    &&
   1747               exc->backward_compatibility &&
   1748               exc->iupx_called            &&
   1749               exc->iupy_called            ) )
   1750 #endif
   1751         zone->cur[point].y = ADD_LONG( zone->cur[point].y,
   1752                                        FT_MulDiv( distance,
   1753                                                   v,
   1754                                                   exc->F_dot_P ) );
   1755 
   1756       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
   1757     }
   1758   }
   1759 
   1760 
   1761   /**************************************************************************
   1762    *
   1763    * @Function:
   1764    *   Direct_Move_Orig
   1765    *
   1766    * @Description:
   1767    *   Moves the *original* position of a point by a given distance along
   1768    *   the freedom vector.  Obviously, the point will not be `touched'.
   1769    *
   1770    * @Input:
   1771    *   point ::
   1772    *     The index of the point to move.
   1773    *
   1774    *   distance ::
   1775    *     The distance to apply.
   1776    *
   1777    * @InOut:
   1778    *   zone ::
   1779    *     The affected glyph zone.
   1780    */
   1781   static void
   1782   Direct_Move_Orig( TT_ExecContext  exc,
   1783                     TT_GlyphZone    zone,
   1784                     FT_UShort       point,
   1785                     FT_F26Dot6      distance )
   1786   {
   1787     FT_F26Dot6  v;
   1788 
   1789 
   1790     v = exc->GS.freeVector.x;
   1791 
   1792     if ( v != 0 )
   1793       zone->org[point].x = ADD_LONG( zone->org[point].x,
   1794                                      FT_MulDiv( distance,
   1795                                                 v,
   1796                                                 exc->F_dot_P ) );
   1797 
   1798     v = exc->GS.freeVector.y;
   1799 
   1800     if ( v != 0 )
   1801       zone->org[point].y = ADD_LONG( zone->org[point].y,
   1802                                      FT_MulDiv( distance,
   1803                                                 v,
   1804                                                 exc->F_dot_P ) );
   1805   }
   1806 
   1807 
   1808   /**************************************************************************
   1809    *
   1810    * Special versions of Direct_Move()
   1811    *
   1812    *   The following versions are used whenever both vectors are both
   1813    *   along one of the coordinate unit vectors, i.e. in 90% of the cases.
   1814    *   See `ttinterp.h' for details on backward compatibility mode.
   1815    *
   1816    */
   1817 
   1818 
   1819   static void
   1820   Direct_Move_X( TT_ExecContext  exc,
   1821                  TT_GlyphZone    zone,
   1822                  FT_UShort       point,
   1823                  FT_F26Dot6      distance )
   1824   {
   1825 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   1826     if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode )
   1827       zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
   1828     else
   1829 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   1830 
   1831 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   1832     if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
   1833       zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
   1834     else
   1835 #endif
   1836 
   1837     if ( NO_SUBPIXEL_HINTING )
   1838       zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
   1839 
   1840     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
   1841   }
   1842 
   1843 
   1844   static void
   1845   Direct_Move_Y( TT_ExecContext  exc,
   1846                  TT_GlyphZone    zone,
   1847                  FT_UShort       point,
   1848                  FT_F26Dot6      distance )
   1849   {
   1850     FT_UNUSED( exc );
   1851 
   1852 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   1853     if ( !( SUBPIXEL_HINTING_MINIMAL             &&
   1854             exc->backward_compatibility          &&
   1855             exc->iupx_called && exc->iupy_called ) )
   1856 #endif
   1857       zone->cur[point].y = ADD_LONG( zone->cur[point].y, distance );
   1858 
   1859     zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
   1860   }
   1861 
   1862 
   1863   /**************************************************************************
   1864    *
   1865    * Special versions of Direct_Move_Orig()
   1866    *
   1867    *   The following versions are used whenever both vectors are both
   1868    *   along one of the coordinate unit vectors, i.e. in 90% of the cases.
   1869    *
   1870    */
   1871 
   1872 
   1873   static void
   1874   Direct_Move_Orig_X( TT_ExecContext  exc,
   1875                       TT_GlyphZone    zone,
   1876                       FT_UShort       point,
   1877                       FT_F26Dot6      distance )
   1878   {
   1879     FT_UNUSED( exc );
   1880 
   1881     zone->org[point].x = ADD_LONG( zone->org[point].x, distance );
   1882   }
   1883 
   1884 
   1885   static void
   1886   Direct_Move_Orig_Y( TT_ExecContext  exc,
   1887                       TT_GlyphZone    zone,
   1888                       FT_UShort       point,
   1889                       FT_F26Dot6      distance )
   1890   {
   1891     FT_UNUSED( exc );
   1892 
   1893     zone->org[point].y = ADD_LONG( zone->org[point].y, distance );
   1894   }
   1895 
   1896 
   1897   /**************************************************************************
   1898    *
   1899    * @Function:
   1900    *   Round_None
   1901    *
   1902    * @Description:
   1903    *   Does not round, but adds engine compensation.
   1904    *
   1905    * @Input:
   1906    *   distance ::
   1907    *     The distance (not) to round.
   1908    *
   1909    *   compensation ::
   1910    *     The engine compensation.
   1911    *
   1912    * @Return:
   1913    *   The compensated distance.
   1914    *
   1915    * @Note:
   1916    *   The TrueType specification says very few about the relationship
   1917    *   between rounding and engine compensation.  However, it seems from
   1918    *   the description of super round that we should add the compensation
   1919    *   before rounding.
   1920    */
   1921   static FT_F26Dot6
   1922   Round_None( TT_ExecContext  exc,
   1923               FT_F26Dot6      distance,
   1924               FT_F26Dot6      compensation )
   1925   {
   1926     FT_F26Dot6  val;
   1927 
   1928     FT_UNUSED( exc );
   1929 
   1930 
   1931     if ( distance >= 0 )
   1932     {
   1933       val = ADD_LONG( distance, compensation );
   1934       if ( val < 0 )
   1935         val = 0;
   1936     }
   1937     else
   1938     {
   1939       val = SUB_LONG( distance, compensation );
   1940       if ( val > 0 )
   1941         val = 0;
   1942     }
   1943     return val;
   1944   }
   1945 
   1946 
   1947   /**************************************************************************
   1948    *
   1949    * @Function:
   1950    *   Round_To_Grid
   1951    *
   1952    * @Description:
   1953    *   Rounds value to grid after adding engine compensation.
   1954    *
   1955    * @Input:
   1956    *   distance ::
   1957    *     The distance to round.
   1958    *
   1959    *   compensation ::
   1960    *     The engine compensation.
   1961    *
   1962    * @Return:
   1963    *   Rounded distance.
   1964    */
   1965   static FT_F26Dot6
   1966   Round_To_Grid( TT_ExecContext  exc,
   1967                  FT_F26Dot6      distance,
   1968                  FT_F26Dot6      compensation )
   1969   {
   1970     FT_F26Dot6  val;
   1971 
   1972     FT_UNUSED( exc );
   1973 
   1974 
   1975     if ( distance >= 0 )
   1976     {
   1977       val = FT_PIX_ROUND_LONG( ADD_LONG( distance, compensation ) );
   1978       if ( val < 0 )
   1979         val = 0;
   1980     }
   1981     else
   1982     {
   1983       val = NEG_LONG( FT_PIX_ROUND_LONG( SUB_LONG( compensation,
   1984                                                    distance ) ) );
   1985       if ( val > 0 )
   1986         val = 0;
   1987     }
   1988 
   1989     return val;
   1990   }
   1991 
   1992 
   1993   /**************************************************************************
   1994    *
   1995    * @Function:
   1996    *   Round_To_Half_Grid
   1997    *
   1998    * @Description:
   1999    *   Rounds value to half grid after adding engine compensation.
   2000    *
   2001    * @Input:
   2002    *   distance ::
   2003    *     The distance to round.
   2004    *
   2005    *   compensation ::
   2006    *     The engine compensation.
   2007    *
   2008    * @Return:
   2009    *   Rounded distance.
   2010    */
   2011   static FT_F26Dot6
   2012   Round_To_Half_Grid( TT_ExecContext  exc,
   2013                       FT_F26Dot6      distance,
   2014                       FT_F26Dot6      compensation )
   2015   {
   2016     FT_F26Dot6  val;
   2017 
   2018     FT_UNUSED( exc );
   2019 
   2020 
   2021     if ( distance >= 0 )
   2022     {
   2023       val = ADD_LONG( FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ),
   2024                       32 );
   2025       if ( val < 0 )
   2026         val = 32;
   2027     }
   2028     else
   2029     {
   2030       val = NEG_LONG( ADD_LONG( FT_PIX_FLOOR( SUB_LONG( compensation,
   2031                                                         distance ) ),
   2032                                 32 ) );
   2033       if ( val > 0 )
   2034         val = -32;
   2035     }
   2036 
   2037     return val;
   2038   }
   2039 
   2040 
   2041   /**************************************************************************
   2042    *
   2043    * @Function:
   2044    *   Round_Down_To_Grid
   2045    *
   2046    * @Description:
   2047    *   Rounds value down to grid after adding engine compensation.
   2048    *
   2049    * @Input:
   2050    *   distance ::
   2051    *     The distance to round.
   2052    *
   2053    *   compensation ::
   2054    *     The engine compensation.
   2055    *
   2056    * @Return:
   2057    *   Rounded distance.
   2058    */
   2059   static FT_F26Dot6
   2060   Round_Down_To_Grid( TT_ExecContext  exc,
   2061                       FT_F26Dot6      distance,
   2062                       FT_F26Dot6      compensation )
   2063   {
   2064     FT_F26Dot6  val;
   2065 
   2066     FT_UNUSED( exc );
   2067 
   2068 
   2069     if ( distance >= 0 )
   2070     {
   2071       val = FT_PIX_FLOOR( ADD_LONG( distance, compensation ) );
   2072       if ( val < 0 )
   2073         val = 0;
   2074     }
   2075     else
   2076     {
   2077       val = NEG_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, distance ) ) );
   2078       if ( val > 0 )
   2079         val = 0;
   2080     }
   2081 
   2082     return val;
   2083   }
   2084 
   2085 
   2086   /**************************************************************************
   2087    *
   2088    * @Function:
   2089    *   Round_Up_To_Grid
   2090    *
   2091    * @Description:
   2092    *   Rounds value up to grid after adding engine compensation.
   2093    *
   2094    * @Input:
   2095    *   distance ::
   2096    *     The distance to round.
   2097    *
   2098    *   compensation ::
   2099    *     The engine compensation.
   2100    *
   2101    * @Return:
   2102    *   Rounded distance.
   2103    */
   2104   static FT_F26Dot6
   2105   Round_Up_To_Grid( TT_ExecContext  exc,
   2106                     FT_F26Dot6      distance,
   2107                     FT_F26Dot6      compensation )
   2108   {
   2109     FT_F26Dot6  val;
   2110 
   2111     FT_UNUSED( exc );
   2112 
   2113 
   2114     if ( distance >= 0 )
   2115     {
   2116       val = FT_PIX_CEIL_LONG( ADD_LONG( distance, compensation ) );
   2117       if ( val < 0 )
   2118         val = 0;
   2119     }
   2120     else
   2121     {
   2122       val = NEG_LONG( FT_PIX_CEIL_LONG( SUB_LONG( compensation,
   2123                                                   distance ) ) );
   2124       if ( val > 0 )
   2125         val = 0;
   2126     }
   2127 
   2128     return val;
   2129   }
   2130 
   2131 
   2132   /**************************************************************************
   2133    *
   2134    * @Function:
   2135    *   Round_To_Double_Grid
   2136    *
   2137    * @Description:
   2138    *   Rounds value to double grid after adding engine compensation.
   2139    *
   2140    * @Input:
   2141    *   distance ::
   2142    *     The distance to round.
   2143    *
   2144    *   compensation ::
   2145    *     The engine compensation.
   2146    *
   2147    * @Return:
   2148    *   Rounded distance.
   2149    */
   2150   static FT_F26Dot6
   2151   Round_To_Double_Grid( TT_ExecContext  exc,
   2152                         FT_F26Dot6      distance,
   2153                         FT_F26Dot6      compensation )
   2154   {
   2155     FT_F26Dot6  val;
   2156 
   2157     FT_UNUSED( exc );
   2158 
   2159 
   2160     if ( distance >= 0 )
   2161     {
   2162       val = FT_PAD_ROUND_LONG( ADD_LONG( distance, compensation ), 32 );
   2163       if ( val < 0 )
   2164         val = 0;
   2165     }
   2166     else
   2167     {
   2168       val = NEG_LONG( FT_PAD_ROUND_LONG( SUB_LONG( compensation, distance ),
   2169                                          32 ) );
   2170       if ( val > 0 )
   2171         val = 0;
   2172     }
   2173 
   2174     return val;
   2175   }
   2176 
   2177 
   2178   /**************************************************************************
   2179    *
   2180    * @Function:
   2181    *   Round_Super
   2182    *
   2183    * @Description:
   2184    *   Super-rounds value to grid after adding engine compensation.
   2185    *
   2186    * @Input:
   2187    *   distance ::
   2188    *     The distance to round.
   2189    *
   2190    *   compensation ::
   2191    *     The engine compensation.
   2192    *
   2193    * @Return:
   2194    *   Rounded distance.
   2195    *
   2196    * @Note:
   2197    *   The TrueType specification says very little about the relationship
   2198    *   between rounding and engine compensation.  However, it seems from
   2199    *   the description of super round that we should add the compensation
   2200    *   before rounding.
   2201    */
   2202   static FT_F26Dot6
   2203   Round_Super( TT_ExecContext  exc,
   2204                FT_F26Dot6      distance,
   2205                FT_F26Dot6      compensation )
   2206   {
   2207     FT_F26Dot6  val;
   2208 
   2209 
   2210     if ( distance >= 0 )
   2211     {
   2212       val = ADD_LONG( distance,
   2213                       exc->threshold - exc->phase + compensation ) &
   2214               -exc->period;
   2215       val = ADD_LONG( val, exc->phase );
   2216       if ( val < 0 )
   2217         val = exc->phase;
   2218     }
   2219     else
   2220     {
   2221       val = NEG_LONG( SUB_LONG( exc->threshold - exc->phase + compensation,
   2222                                 distance ) &
   2223                         -exc->period );
   2224       val = SUB_LONG( val, exc->phase );
   2225       if ( val > 0 )
   2226         val = -exc->phase;
   2227     }
   2228 
   2229     return val;
   2230   }
   2231 
   2232 
   2233   /**************************************************************************
   2234    *
   2235    * @Function:
   2236    *   Round_Super_45
   2237    *
   2238    * @Description:
   2239    *   Super-rounds value to grid after adding engine compensation.
   2240    *
   2241    * @Input:
   2242    *   distance ::
   2243    *     The distance to round.
   2244    *
   2245    *   compensation ::
   2246    *     The engine compensation.
   2247    *
   2248    * @Return:
   2249    *   Rounded distance.
   2250    *
   2251    * @Note:
   2252    *   There is a separate function for Round_Super_45() as we may need
   2253    *   greater precision.
   2254    */
   2255   static FT_F26Dot6
   2256   Round_Super_45( TT_ExecContext  exc,
   2257                   FT_F26Dot6      distance,
   2258                   FT_F26Dot6      compensation )
   2259   {
   2260     FT_F26Dot6  val;
   2261 
   2262 
   2263     if ( distance >= 0 )
   2264     {
   2265       val = ( ADD_LONG( distance,
   2266                         exc->threshold - exc->phase + compensation ) /
   2267                 exc->period ) * exc->period;
   2268       val = ADD_LONG( val, exc->phase );
   2269       if ( val < 0 )
   2270         val = exc->phase;
   2271     }
   2272     else
   2273     {
   2274       val = NEG_LONG( ( SUB_LONG( exc->threshold - exc->phase + compensation,
   2275                                   distance ) /
   2276                           exc->period ) * exc->period );
   2277       val = SUB_LONG( val, exc->phase );
   2278       if ( val > 0 )
   2279         val = -exc->phase;
   2280     }
   2281 
   2282     return val;
   2283   }
   2284 
   2285 
   2286   /**************************************************************************
   2287    *
   2288    * @Function:
   2289    *   Compute_Round
   2290    *
   2291    * @Description:
   2292    *   Sets the rounding mode.
   2293    *
   2294    * @Input:
   2295    *   round_mode ::
   2296    *     The rounding mode to be used.
   2297    */
   2298   static void
   2299   Compute_Round( TT_ExecContext  exc,
   2300                  FT_Byte         round_mode )
   2301   {
   2302     switch ( round_mode )
   2303     {
   2304     case TT_Round_Off:
   2305       exc->func_round = (TT_Round_Func)Round_None;
   2306       break;
   2307 
   2308     case TT_Round_To_Grid:
   2309       exc->func_round = (TT_Round_Func)Round_To_Grid;
   2310       break;
   2311 
   2312     case TT_Round_Up_To_Grid:
   2313       exc->func_round = (TT_Round_Func)Round_Up_To_Grid;
   2314       break;
   2315 
   2316     case TT_Round_Down_To_Grid:
   2317       exc->func_round = (TT_Round_Func)Round_Down_To_Grid;
   2318       break;
   2319 
   2320     case TT_Round_To_Half_Grid:
   2321       exc->func_round = (TT_Round_Func)Round_To_Half_Grid;
   2322       break;
   2323 
   2324     case TT_Round_To_Double_Grid:
   2325       exc->func_round = (TT_Round_Func)Round_To_Double_Grid;
   2326       break;
   2327 
   2328     case TT_Round_Super:
   2329       exc->func_round = (TT_Round_Func)Round_Super;
   2330       break;
   2331 
   2332     case TT_Round_Super_45:
   2333       exc->func_round = (TT_Round_Func)Round_Super_45;
   2334       break;
   2335     }
   2336   }
   2337 
   2338 
   2339   /**************************************************************************
   2340    *
   2341    * @Function:
   2342    *   SetSuperRound
   2343    *
   2344    * @Description:
   2345    *   Sets Super Round parameters.
   2346    *
   2347    * @Input:
   2348    *   GridPeriod ::
   2349    *     The grid period.
   2350    *
   2351    *   selector ::
   2352    *     The SROUND opcode.
   2353    */
   2354   static void
   2355   SetSuperRound( TT_ExecContext  exc,
   2356                  FT_F2Dot14      GridPeriod,
   2357                  FT_Long         selector )
   2358   {
   2359     switch ( (FT_Int)( selector & 0xC0 ) )
   2360     {
   2361       case 0:
   2362         exc->period = GridPeriod / 2;
   2363         break;
   2364 
   2365       case 0x40:
   2366         exc->period = GridPeriod;
   2367         break;
   2368 
   2369       case 0x80:
   2370         exc->period = GridPeriod * 2;
   2371         break;
   2372 
   2373       /* This opcode is reserved, but... */
   2374       case 0xC0:
   2375         exc->period = GridPeriod;
   2376         break;
   2377     }
   2378 
   2379     switch ( (FT_Int)( selector & 0x30 ) )
   2380     {
   2381     case 0:
   2382       exc->phase = 0;
   2383       break;
   2384 
   2385     case 0x10:
   2386       exc->phase = exc->period / 4;
   2387       break;
   2388 
   2389     case 0x20:
   2390       exc->phase = exc->period / 2;
   2391       break;
   2392 
   2393     case 0x30:
   2394       exc->phase = exc->period * 3 / 4;
   2395       break;
   2396     }
   2397 
   2398     if ( ( selector & 0x0F ) == 0 )
   2399       exc->threshold = exc->period - 1;
   2400     else
   2401       exc->threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * exc->period / 8;
   2402 
   2403     /* convert to F26Dot6 format */
   2404     exc->period    >>= 8;
   2405     exc->phase     >>= 8;
   2406     exc->threshold >>= 8;
   2407   }
   2408 
   2409 
   2410   /**************************************************************************
   2411    *
   2412    * @Function:
   2413    *   Project
   2414    *
   2415    * @Description:
   2416    *   Computes the projection of vector given by (v2-v1) along the
   2417    *   current projection vector.
   2418    *
   2419    * @Input:
   2420    *   v1 ::
   2421    *     First input vector.
   2422    *   v2 ::
   2423    *     Second input vector.
   2424    *
   2425    * @Return:
   2426    *   The distance in F26dot6 format.
   2427    */
   2428   static FT_F26Dot6
   2429   Project( TT_ExecContext  exc,
   2430            FT_Pos          dx,
   2431            FT_Pos          dy )
   2432   {
   2433     return TT_DotFix14( dx, dy,
   2434                         exc->GS.projVector.x,
   2435                         exc->GS.projVector.y );
   2436   }
   2437 
   2438 
   2439   /**************************************************************************
   2440    *
   2441    * @Function:
   2442    *   Dual_Project
   2443    *
   2444    * @Description:
   2445    *   Computes the projection of the vector given by (v2-v1) along the
   2446    *   current dual vector.
   2447    *
   2448    * @Input:
   2449    *   v1 ::
   2450    *     First input vector.
   2451    *   v2 ::
   2452    *     Second input vector.
   2453    *
   2454    * @Return:
   2455    *   The distance in F26dot6 format.
   2456    */
   2457   static FT_F26Dot6
   2458   Dual_Project( TT_ExecContext  exc,
   2459                 FT_Pos          dx,
   2460                 FT_Pos          dy )
   2461   {
   2462     return TT_DotFix14( dx, dy,
   2463                         exc->GS.dualVector.x,
   2464                         exc->GS.dualVector.y );
   2465   }
   2466 
   2467 
   2468   /**************************************************************************
   2469    *
   2470    * @Function:
   2471    *   Project_x
   2472    *
   2473    * @Description:
   2474    *   Computes the projection of the vector given by (v2-v1) along the
   2475    *   horizontal axis.
   2476    *
   2477    * @Input:
   2478    *   v1 ::
   2479    *     First input vector.
   2480    *   v2 ::
   2481    *     Second input vector.
   2482    *
   2483    * @Return:
   2484    *   The distance in F26dot6 format.
   2485    */
   2486   static FT_F26Dot6
   2487   Project_x( TT_ExecContext  exc,
   2488              FT_Pos          dx,
   2489              FT_Pos          dy )
   2490   {
   2491     FT_UNUSED( exc );
   2492     FT_UNUSED( dy );
   2493 
   2494     return dx;
   2495   }
   2496 
   2497 
   2498   /**************************************************************************
   2499    *
   2500    * @Function:
   2501    *   Project_y
   2502    *
   2503    * @Description:
   2504    *   Computes the projection of the vector given by (v2-v1) along the
   2505    *   vertical axis.
   2506    *
   2507    * @Input:
   2508    *   v1 ::
   2509    *     First input vector.
   2510    *   v2 ::
   2511    *     Second input vector.
   2512    *
   2513    * @Return:
   2514    *   The distance in F26dot6 format.
   2515    */
   2516   static FT_F26Dot6
   2517   Project_y( TT_ExecContext  exc,
   2518              FT_Pos          dx,
   2519              FT_Pos          dy )
   2520   {
   2521     FT_UNUSED( exc );
   2522     FT_UNUSED( dx );
   2523 
   2524     return dy;
   2525   }
   2526 
   2527 
   2528   /**************************************************************************
   2529    *
   2530    * @Function:
   2531    *   Compute_Funcs
   2532    *
   2533    * @Description:
   2534    *   Computes the projection and movement function pointers according
   2535    *   to the current graphics state.
   2536    */
   2537   static void
   2538   Compute_Funcs( TT_ExecContext  exc )
   2539   {
   2540     if ( exc->GS.freeVector.x == 0x4000 )
   2541       exc->F_dot_P = exc->GS.projVector.x;
   2542     else if ( exc->GS.freeVector.y == 0x4000 )
   2543       exc->F_dot_P = exc->GS.projVector.y;
   2544     else
   2545       exc->F_dot_P =
   2546         ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x +
   2547           (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14;
   2548 
   2549     if ( exc->GS.projVector.x == 0x4000 )
   2550       exc->func_project = (TT_Project_Func)Project_x;
   2551     else if ( exc->GS.projVector.y == 0x4000 )
   2552       exc->func_project = (TT_Project_Func)Project_y;
   2553     else
   2554       exc->func_project = (TT_Project_Func)Project;
   2555 
   2556     if ( exc->GS.dualVector.x == 0x4000 )
   2557       exc->func_dualproj = (TT_Project_Func)Project_x;
   2558     else if ( exc->GS.dualVector.y == 0x4000 )
   2559       exc->func_dualproj = (TT_Project_Func)Project_y;
   2560     else
   2561       exc->func_dualproj = (TT_Project_Func)Dual_Project;
   2562 
   2563     exc->func_move      = (TT_Move_Func)Direct_Move;
   2564     exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig;
   2565 
   2566     if ( exc->F_dot_P == 0x4000L )
   2567     {
   2568       if ( exc->GS.freeVector.x == 0x4000 )
   2569       {
   2570         exc->func_move      = (TT_Move_Func)Direct_Move_X;
   2571         exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
   2572       }
   2573       else if ( exc->GS.freeVector.y == 0x4000 )
   2574       {
   2575         exc->func_move      = (TT_Move_Func)Direct_Move_Y;
   2576         exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
   2577       }
   2578     }
   2579 
   2580     /* at small sizes, F_dot_P can become too small, resulting   */
   2581     /* in overflows and `spikes' in a number of glyphs like `w'. */
   2582 
   2583     if ( FT_ABS( exc->F_dot_P ) < 0x400L )
   2584       exc->F_dot_P = 0x4000L;
   2585 
   2586     /* Disable cached aspect ratio */
   2587     exc->tt_metrics.ratio = 0;
   2588   }
   2589 
   2590 
   2591   /**************************************************************************
   2592    *
   2593    * @Function:
   2594    *   Normalize
   2595    *
   2596    * @Description:
   2597    *   Norms a vector.
   2598    *
   2599    * @Input:
   2600    *   Vx ::
   2601    *     The horizontal input vector coordinate.
   2602    *   Vy ::
   2603    *     The vertical input vector coordinate.
   2604    *
   2605    * @Output:
   2606    *   R ::
   2607    *     The normed unit vector.
   2608    *
   2609    * @Return:
   2610    *   Returns FAILURE if a vector parameter is zero.
   2611    *
   2612    * @Note:
   2613    *   In case Vx and Vy are both zero, `Normalize' returns SUCCESS, and
   2614    *   R is undefined.
   2615    */
   2616   static FT_Bool
   2617   Normalize( FT_F26Dot6      Vx,
   2618              FT_F26Dot6      Vy,
   2619              FT_UnitVector*  R )
   2620   {
   2621     FT_Vector V;
   2622 
   2623 
   2624     if ( Vx == 0 && Vy == 0 )
   2625     {
   2626       /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
   2627       /*      to normalize the vector (0,0).  Return immediately. */
   2628       return SUCCESS;
   2629     }
   2630 
   2631     V.x = Vx;
   2632     V.y = Vy;
   2633 
   2634     FT_Vector_NormLen( &V );
   2635 
   2636     R->x = (FT_F2Dot14)( V.x / 4 );
   2637     R->y = (FT_F2Dot14)( V.y / 4 );
   2638 
   2639     return SUCCESS;
   2640   }
   2641 
   2642 
   2643   /**************************************************************************
   2644    *
   2645    * Here we start with the implementation of the various opcodes.
   2646    *
   2647    */
   2648 
   2649 
   2650 #define ARRAY_BOUND_ERROR                         \
   2651     do                                            \
   2652     {                                             \
   2653       exc->error = FT_THROW( Invalid_Reference ); \
   2654       return;                                     \
   2655     } while (0)
   2656 
   2657 
   2658   /**************************************************************************
   2659    *
   2660    * MPPEM[]:      Measure Pixel Per EM
   2661    * Opcode range: 0x4B
   2662    * Stack:        --> Euint16
   2663    */
   2664   static void
   2665   Ins_MPPEM( TT_ExecContext  exc,
   2666              FT_Long*        args )
   2667   {
   2668     args[0] = exc->func_cur_ppem( exc );
   2669   }
   2670 
   2671 
   2672   /**************************************************************************
   2673    *
   2674    * MPS[]:        Measure Point Size
   2675    * Opcode range: 0x4C
   2676    * Stack:        --> Euint16
   2677    */
   2678   static void
   2679   Ins_MPS( TT_ExecContext  exc,
   2680            FT_Long*        args )
   2681   {
   2682     if ( NO_SUBPIXEL_HINTING )
   2683     {
   2684       /* Microsoft's GDI bytecode interpreter always returns value 12; */
   2685       /* we return the current PPEM value instead.                     */
   2686       args[0] = exc->func_cur_ppem( exc );
   2687     }
   2688     else
   2689     {
   2690       /* A possible practical application of the MPS instruction is to   */
   2691       /* implement optical scaling and similar features, which should be */
   2692       /* based on perceptual attributes, thus independent of the         */
   2693       /* resolution.                                                     */
   2694       args[0] = exc->pointSize;
   2695     }
   2696   }
   2697 
   2698 
   2699   /**************************************************************************
   2700    *
   2701    * DUP[]:        DUPlicate the stack's top element
   2702    * Opcode range: 0x20
   2703    * Stack:        StkElt --> StkElt StkElt
   2704    */
   2705   static void
   2706   Ins_DUP( FT_Long*  args )
   2707   {
   2708     args[1] = args[0];
   2709   }
   2710 
   2711 
   2712   /**************************************************************************
   2713    *
   2714    * POP[]:        POP the stack's top element
   2715    * Opcode range: 0x21
   2716    * Stack:        StkElt -->
   2717    */
   2718   static void
   2719   Ins_POP( void )
   2720   {
   2721     /* nothing to do */
   2722   }
   2723 
   2724 
   2725   /**************************************************************************
   2726    *
   2727    * CLEAR[]:      CLEAR the entire stack
   2728    * Opcode range: 0x22
   2729    * Stack:        StkElt... -->
   2730    */
   2731   static void
   2732   Ins_CLEAR( TT_ExecContext  exc )
   2733   {
   2734     exc->new_top = 0;
   2735   }
   2736 
   2737 
   2738   /**************************************************************************
   2739    *
   2740    * SWAP[]:       SWAP the stack's top two elements
   2741    * Opcode range: 0x23
   2742    * Stack:        2 * StkElt --> 2 * StkElt
   2743    */
   2744   static void
   2745   Ins_SWAP( FT_Long*  args )
   2746   {
   2747     FT_Long  L;
   2748 
   2749 
   2750     L       = args[0];
   2751     args[0] = args[1];
   2752     args[1] = L;
   2753   }
   2754 
   2755 
   2756   /**************************************************************************
   2757    *
   2758    * DEPTH[]:      return the stack DEPTH
   2759    * Opcode range: 0x24
   2760    * Stack:        --> uint32
   2761    */
   2762   static void
   2763   Ins_DEPTH( TT_ExecContext  exc,
   2764              FT_Long*        args )
   2765   {
   2766     args[0] = exc->top;
   2767   }
   2768 
   2769 
   2770   /**************************************************************************
   2771    *
   2772    * LT[]:         Less Than
   2773    * Opcode range: 0x50
   2774    * Stack:        int32? int32? --> bool
   2775    */
   2776   static void
   2777   Ins_LT( FT_Long*  args )
   2778   {
   2779     args[0] = ( args[0] < args[1] );
   2780   }
   2781 
   2782 
   2783   /**************************************************************************
   2784    *
   2785    * LTEQ[]:       Less Than or EQual
   2786    * Opcode range: 0x51
   2787    * Stack:        int32? int32? --> bool
   2788    */
   2789   static void
   2790   Ins_LTEQ( FT_Long*  args )
   2791   {
   2792     args[0] = ( args[0] <= args[1] );
   2793   }
   2794 
   2795 
   2796   /**************************************************************************
   2797    *
   2798    * GT[]:         Greater Than
   2799    * Opcode range: 0x52
   2800    * Stack:        int32? int32? --> bool
   2801    */
   2802   static void
   2803   Ins_GT( FT_Long*  args )
   2804   {
   2805     args[0] = ( args[0] > args[1] );
   2806   }
   2807 
   2808 
   2809   /**************************************************************************
   2810    *
   2811    * GTEQ[]:       Greater Than or EQual
   2812    * Opcode range: 0x53
   2813    * Stack:        int32? int32? --> bool
   2814    */
   2815   static void
   2816   Ins_GTEQ( FT_Long*  args )
   2817   {
   2818     args[0] = ( args[0] >= args[1] );
   2819   }
   2820 
   2821 
   2822   /**************************************************************************
   2823    *
   2824    * EQ[]:         EQual
   2825    * Opcode range: 0x54
   2826    * Stack:        StkElt StkElt --> bool
   2827    */
   2828   static void
   2829   Ins_EQ( FT_Long*  args )
   2830   {
   2831     args[0] = ( args[0] == args[1] );
   2832   }
   2833 
   2834 
   2835   /**************************************************************************
   2836    *
   2837    * NEQ[]:        Not EQual
   2838    * Opcode range: 0x55
   2839    * Stack:        StkElt StkElt --> bool
   2840    */
   2841   static void
   2842   Ins_NEQ( FT_Long*  args )
   2843   {
   2844     args[0] = ( args[0] != args[1] );
   2845   }
   2846 
   2847 
   2848   /**************************************************************************
   2849    *
   2850    * ODD[]:        Is ODD
   2851    * Opcode range: 0x56
   2852    * Stack:        f26.6 --> bool
   2853    */
   2854   static void
   2855   Ins_ODD( TT_ExecContext  exc,
   2856            FT_Long*        args )
   2857   {
   2858     args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 64 );
   2859   }
   2860 
   2861 
   2862   /**************************************************************************
   2863    *
   2864    * EVEN[]:       Is EVEN
   2865    * Opcode range: 0x57
   2866    * Stack:        f26.6 --> bool
   2867    */
   2868   static void
   2869   Ins_EVEN( TT_ExecContext  exc,
   2870             FT_Long*        args )
   2871   {
   2872     args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 0 );
   2873   }
   2874 
   2875 
   2876   /**************************************************************************
   2877    *
   2878    * AND[]:        logical AND
   2879    * Opcode range: 0x5A
   2880    * Stack:        uint32 uint32 --> uint32
   2881    */
   2882   static void
   2883   Ins_AND( FT_Long*  args )
   2884   {
   2885     args[0] = ( args[0] && args[1] );
   2886   }
   2887 
   2888 
   2889   /**************************************************************************
   2890    *
   2891    * OR[]:         logical OR
   2892    * Opcode range: 0x5B
   2893    * Stack:        uint32 uint32 --> uint32
   2894    */
   2895   static void
   2896   Ins_OR( FT_Long*  args )
   2897   {
   2898     args[0] = ( args[0] || args[1] );
   2899   }
   2900 
   2901 
   2902   /**************************************************************************
   2903    *
   2904    * NOT[]:        logical NOT
   2905    * Opcode range: 0x5C
   2906    * Stack:        StkElt --> uint32
   2907    */
   2908   static void
   2909   Ins_NOT( FT_Long*  args )
   2910   {
   2911     args[0] = !args[0];
   2912   }
   2913 
   2914 
   2915   /**************************************************************************
   2916    *
   2917    * ADD[]:        ADD
   2918    * Opcode range: 0x60
   2919    * Stack:        f26.6 f26.6 --> f26.6
   2920    */
   2921   static void
   2922   Ins_ADD( FT_Long*  args )
   2923   {
   2924     args[0] = ADD_LONG( args[0], args[1] );
   2925   }
   2926 
   2927 
   2928   /**************************************************************************
   2929    *
   2930    * SUB[]:        SUBtract
   2931    * Opcode range: 0x61
   2932    * Stack:        f26.6 f26.6 --> f26.6
   2933    */
   2934   static void
   2935   Ins_SUB( FT_Long*  args )
   2936   {
   2937     args[0] = SUB_LONG( args[0], args[1] );
   2938   }
   2939 
   2940 
   2941   /**************************************************************************
   2942    *
   2943    * DIV[]:        DIVide
   2944    * Opcode range: 0x62
   2945    * Stack:        f26.6 f26.6 --> f26.6
   2946    */
   2947   static void
   2948   Ins_DIV( TT_ExecContext  exc,
   2949            FT_Long*        args )
   2950   {
   2951     if ( args[1] == 0 )
   2952       exc->error = FT_THROW( Divide_By_Zero );
   2953     else
   2954       args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
   2955   }
   2956 
   2957 
   2958   /**************************************************************************
   2959    *
   2960    * MUL[]:        MULtiply
   2961    * Opcode range: 0x63
   2962    * Stack:        f26.6 f26.6 --> f26.6
   2963    */
   2964   static void
   2965   Ins_MUL( FT_Long*  args )
   2966   {
   2967     args[0] = FT_MulDiv( args[0], args[1], 64L );
   2968   }
   2969 
   2970 
   2971   /**************************************************************************
   2972    *
   2973    * ABS[]:        ABSolute value
   2974    * Opcode range: 0x64
   2975    * Stack:        f26.6 --> f26.6
   2976    */
   2977   static void
   2978   Ins_ABS( FT_Long*  args )
   2979   {
   2980     if ( args[0] < 0 )
   2981       args[0] = NEG_LONG( args[0] );
   2982   }
   2983 
   2984 
   2985   /**************************************************************************
   2986    *
   2987    * NEG[]:        NEGate
   2988    * Opcode range: 0x65
   2989    * Stack:        f26.6 --> f26.6
   2990    */
   2991   static void
   2992   Ins_NEG( FT_Long*  args )
   2993   {
   2994     args[0] = NEG_LONG( args[0] );
   2995   }
   2996 
   2997 
   2998   /**************************************************************************
   2999    *
   3000    * FLOOR[]:      FLOOR
   3001    * Opcode range: 0x66
   3002    * Stack:        f26.6 --> f26.6
   3003    */
   3004   static void
   3005   Ins_FLOOR( FT_Long*  args )
   3006   {
   3007     args[0] = FT_PIX_FLOOR( args[0] );
   3008   }
   3009 
   3010 
   3011   /**************************************************************************
   3012    *
   3013    * CEILING[]:    CEILING
   3014    * Opcode range: 0x67
   3015    * Stack:        f26.6 --> f26.6
   3016    */
   3017   static void
   3018   Ins_CEILING( FT_Long*  args )
   3019   {
   3020     args[0] = FT_PIX_CEIL_LONG( args[0] );
   3021   }
   3022 
   3023 
   3024   /**************************************************************************
   3025    *
   3026    * RS[]:         Read Store
   3027    * Opcode range: 0x43
   3028    * Stack:        uint32 --> uint32
   3029    */
   3030   static void
   3031   Ins_RS( TT_ExecContext  exc,
   3032           FT_Long*        args )
   3033   {
   3034     FT_ULong  I = (FT_ULong)args[0];
   3035 
   3036 
   3037     if ( BOUNDSL( I, exc->storeSize ) )
   3038     {
   3039       if ( exc->pedantic_hinting )
   3040         ARRAY_BOUND_ERROR;
   3041       else
   3042         args[0] = 0;
   3043     }
   3044     else
   3045     {
   3046 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   3047       /* subpixel hinting - avoid Typeman Dstroke and */
   3048       /* IStroke and Vacuform rounds                  */
   3049       if ( SUBPIXEL_HINTING_INFINALITY                 &&
   3050            exc->ignore_x_mode                          &&
   3051            ( ( I == 24                             &&
   3052                ( exc->face->sph_found_func_flags &
   3053                  ( SPH_FDEF_SPACING_1 |
   3054                    SPH_FDEF_SPACING_2 )          ) ) ||
   3055              ( I == 22                      &&
   3056                ( exc->sph_in_func_flags   &
   3057                  SPH_FDEF_TYPEMAN_STROKES ) )        ||
   3058              ( I == 8                              &&
   3059                ( exc->face->sph_found_func_flags &
   3060                  SPH_FDEF_VACUFORM_ROUND_1       ) &&
   3061                exc->iup_called                     ) ) )
   3062         args[0] = 0;
   3063       else
   3064 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   3065         args[0] = exc->storage[I];
   3066     }
   3067   }
   3068 
   3069 
   3070   /**************************************************************************
   3071    *
   3072    * WS[]:         Write Store
   3073    * Opcode range: 0x42
   3074    * Stack:        uint32 uint32 -->
   3075    */
   3076   static void
   3077   Ins_WS( TT_ExecContext  exc,
   3078           FT_Long*        args )
   3079   {
   3080     FT_ULong  I = (FT_ULong)args[0];
   3081 
   3082 
   3083     if ( BOUNDSL( I, exc->storeSize ) )
   3084     {
   3085       if ( exc->pedantic_hinting )
   3086         ARRAY_BOUND_ERROR;
   3087     }
   3088     else
   3089       exc->storage[I] = args[1];
   3090   }
   3091 
   3092 
   3093   /**************************************************************************
   3094    *
   3095    * WCVTP[]:      Write CVT in Pixel units
   3096    * Opcode range: 0x44
   3097    * Stack:        f26.6 uint32 -->
   3098    */
   3099   static void
   3100   Ins_WCVTP( TT_ExecContext  exc,
   3101              FT_Long*        args )
   3102   {
   3103     FT_ULong  I = (FT_ULong)args[0];
   3104 
   3105 
   3106     if ( BOUNDSL( I, exc->cvtSize ) )
   3107     {
   3108       if ( exc->pedantic_hinting )
   3109         ARRAY_BOUND_ERROR;
   3110     }
   3111     else
   3112       exc->func_write_cvt( exc, I, args[1] );
   3113   }
   3114 
   3115 
   3116   /**************************************************************************
   3117    *
   3118    * WCVTF[]:      Write CVT in Funits
   3119    * Opcode range: 0x70
   3120    * Stack:        uint32 uint32 -->
   3121    */
   3122   static void
   3123   Ins_WCVTF( TT_ExecContext  exc,
   3124              FT_Long*        args )
   3125   {
   3126     FT_ULong  I = (FT_ULong)args[0];
   3127 
   3128 
   3129     if ( BOUNDSL( I, exc->cvtSize ) )
   3130     {
   3131       if ( exc->pedantic_hinting )
   3132         ARRAY_BOUND_ERROR;
   3133     }
   3134     else
   3135       exc->cvt[I] = FT_MulFix( args[1], exc->tt_metrics.scale );
   3136   }
   3137 
   3138 
   3139   /**************************************************************************
   3140    *
   3141    * RCVT[]:       Read CVT
   3142    * Opcode range: 0x45
   3143    * Stack:        uint32 --> f26.6
   3144    */
   3145   static void
   3146   Ins_RCVT( TT_ExecContext  exc,
   3147             FT_Long*        args )
   3148   {
   3149     FT_ULong  I = (FT_ULong)args[0];
   3150 
   3151 
   3152     if ( BOUNDSL( I, exc->cvtSize ) )
   3153     {
   3154       if ( exc->pedantic_hinting )
   3155         ARRAY_BOUND_ERROR;
   3156       else
   3157         args[0] = 0;
   3158     }
   3159     else
   3160       args[0] = exc->func_read_cvt( exc, I );
   3161   }
   3162 
   3163 
   3164   /**************************************************************************
   3165    *
   3166    * AA[]:         Adjust Angle
   3167    * Opcode range: 0x7F
   3168    * Stack:        uint32 -->
   3169    */
   3170   static void
   3171   Ins_AA( void )
   3172   {
   3173     /* intentionally no longer supported */
   3174   }
   3175 
   3176 
   3177   /**************************************************************************
   3178    *
   3179    * DEBUG[]:      DEBUG.  Unsupported.
   3180    * Opcode range: 0x4F
   3181    * Stack:        uint32 -->
   3182    *
   3183    * Note: The original instruction pops a value from the stack.
   3184    */
   3185   static void
   3186   Ins_DEBUG( TT_ExecContext  exc )
   3187   {
   3188     exc->error = FT_THROW( Debug_OpCode );
   3189   }
   3190 
   3191 
   3192   /**************************************************************************
   3193    *
   3194    * ROUND[ab]:    ROUND value
   3195    * Opcode range: 0x68-0x6B
   3196    * Stack:        f26.6 --> f26.6
   3197    */
   3198   static void
   3199   Ins_ROUND( TT_ExecContext  exc,
   3200              FT_Long*        args )
   3201   {
   3202     args[0] = exc->func_round(
   3203                 exc,
   3204                 args[0],
   3205                 exc->tt_metrics.compensations[exc->opcode - 0x68] );
   3206   }
   3207 
   3208 
   3209   /**************************************************************************
   3210    *
   3211    * NROUND[ab]:   No ROUNDing of value
   3212    * Opcode range: 0x6C-0x6F
   3213    * Stack:        f26.6 --> f26.6
   3214    */
   3215   static void
   3216   Ins_NROUND( TT_ExecContext  exc,
   3217               FT_Long*        args )
   3218   {
   3219     args[0] = Round_None(
   3220                 exc,
   3221                 args[0],
   3222                 exc->tt_metrics.compensations[exc->opcode - 0x6C] );
   3223   }
   3224 
   3225 
   3226   /**************************************************************************
   3227    *
   3228    * MAX[]:        MAXimum
   3229    * Opcode range: 0x8B
   3230    * Stack:        int32? int32? --> int32
   3231    */
   3232   static void
   3233   Ins_MAX( FT_Long*  args )
   3234   {
   3235     if ( args[1] > args[0] )
   3236       args[0] = args[1];
   3237   }
   3238 
   3239 
   3240   /**************************************************************************
   3241    *
   3242    * MIN[]:        MINimum
   3243    * Opcode range: 0x8C
   3244    * Stack:        int32? int32? --> int32
   3245    */
   3246   static void
   3247   Ins_MIN( FT_Long*  args )
   3248   {
   3249     if ( args[1] < args[0] )
   3250       args[0] = args[1];
   3251   }
   3252 
   3253 
   3254   /**************************************************************************
   3255    *
   3256    * MINDEX[]:     Move INDEXed element
   3257    * Opcode range: 0x26
   3258    * Stack:        int32? --> StkElt
   3259    */
   3260   static void
   3261   Ins_MINDEX( TT_ExecContext  exc,
   3262               FT_Long*        args )
   3263   {
   3264     FT_Long  L, K;
   3265 
   3266 
   3267     L = args[0];
   3268 
   3269     if ( L <= 0 || L > exc->args )
   3270     {
   3271       if ( exc->pedantic_hinting )
   3272         exc->error = FT_THROW( Invalid_Reference );
   3273     }
   3274     else
   3275     {
   3276       K = exc->stack[exc->args - L];
   3277 
   3278       FT_ARRAY_MOVE( &exc->stack[exc->args - L    ],
   3279                      &exc->stack[exc->args - L + 1],
   3280                      ( L - 1 ) );
   3281 
   3282       exc->stack[exc->args - 1] = K;
   3283     }
   3284   }
   3285 
   3286 
   3287   /**************************************************************************
   3288    *
   3289    * CINDEX[]:     Copy INDEXed element
   3290    * Opcode range: 0x25
   3291    * Stack:        int32 --> StkElt
   3292    */
   3293   static void
   3294   Ins_CINDEX( TT_ExecContext  exc,
   3295               FT_Long*        args )
   3296   {
   3297     FT_Long  L;
   3298 
   3299 
   3300     L = args[0];
   3301 
   3302     if ( L <= 0 || L > exc->args )
   3303     {
   3304       if ( exc->pedantic_hinting )
   3305         exc->error = FT_THROW( Invalid_Reference );
   3306       args[0] = 0;
   3307     }
   3308     else
   3309       args[0] = exc->stack[exc->args - L];
   3310   }
   3311 
   3312 
   3313   /**************************************************************************
   3314    *
   3315    * ROLL[]:       ROLL top three elements
   3316    * Opcode range: 0x8A
   3317    * Stack:        3 * StkElt --> 3 * StkElt
   3318    */
   3319   static void
   3320   Ins_ROLL( FT_Long*  args )
   3321   {
   3322     FT_Long  A, B, C;
   3323 
   3324 
   3325     A = args[2];
   3326     B = args[1];
   3327     C = args[0];
   3328 
   3329     args[2] = C;
   3330     args[1] = A;
   3331     args[0] = B;
   3332   }
   3333 
   3334 
   3335   /**************************************************************************
   3336    *
   3337    * MANAGING THE FLOW OF CONTROL
   3338    *
   3339    */
   3340 
   3341 
   3342   /**************************************************************************
   3343    *
   3344    * SLOOP[]:      Set LOOP variable
   3345    * Opcode range: 0x17
   3346    * Stack:        int32? -->
   3347    */
   3348   static void
   3349   Ins_SLOOP( TT_ExecContext  exc,
   3350              FT_Long*        args )
   3351   {
   3352     if ( args[0] < 0 )
   3353       exc->error = FT_THROW( Bad_Argument );
   3354     else
   3355     {
   3356       /* we heuristically limit the number of loops to 16 bits */
   3357       exc->GS.loop = args[0] > 0xFFFFL ? 0xFFFFL : args[0];
   3358     }
   3359   }
   3360 
   3361 
   3362   static FT_Bool
   3363   SkipCode( TT_ExecContext  exc )
   3364   {
   3365     exc->IP += exc->length;
   3366 
   3367     if ( exc->IP < exc->codeSize )
   3368     {
   3369       exc->opcode = exc->code[exc->IP];
   3370 
   3371       exc->length = opcode_length[exc->opcode];
   3372       if ( exc->length < 0 )
   3373       {
   3374         if ( exc->IP + 1 >= exc->codeSize )
   3375           goto Fail_Overflow;
   3376         exc->length = 2 - exc->length * exc->code[exc->IP + 1];
   3377       }
   3378 
   3379       if ( exc->IP + exc->length <= exc->codeSize )
   3380         return SUCCESS;
   3381     }
   3382 
   3383   Fail_Overflow:
   3384     exc->error = FT_THROW( Code_Overflow );
   3385     return FAILURE;
   3386   }
   3387 
   3388 
   3389   /**************************************************************************
   3390    *
   3391    * IF[]:         IF test
   3392    * Opcode range: 0x58
   3393    * Stack:        StkElt -->
   3394    */
   3395   static void
   3396   Ins_IF( TT_ExecContext  exc,
   3397           FT_Long*        args )
   3398   {
   3399     FT_Int   nIfs;
   3400     FT_Bool  Out;
   3401 
   3402 
   3403     if ( args[0] != 0 )
   3404       return;
   3405 
   3406     nIfs = 1;
   3407     Out = 0;
   3408 
   3409     do
   3410     {
   3411       if ( SkipCode( exc ) == FAILURE )
   3412         return;
   3413 
   3414       switch ( exc->opcode )
   3415       {
   3416       case 0x58:      /* IF */
   3417         nIfs++;
   3418         break;
   3419 
   3420       case 0x1B:      /* ELSE */
   3421         Out = FT_BOOL( nIfs == 1 );
   3422         break;
   3423 
   3424       case 0x59:      /* EIF */
   3425         nIfs--;
   3426         Out = FT_BOOL( nIfs == 0 );
   3427         break;
   3428       }
   3429     } while ( Out == 0 );
   3430   }
   3431 
   3432 
   3433   /**************************************************************************
   3434    *
   3435    * ELSE[]:       ELSE
   3436    * Opcode range: 0x1B
   3437    * Stack:        -->
   3438    */
   3439   static void
   3440   Ins_ELSE( TT_ExecContext  exc )
   3441   {
   3442     FT_Int  nIfs;
   3443 
   3444 
   3445     nIfs = 1;
   3446 
   3447     do
   3448     {
   3449       if ( SkipCode( exc ) == FAILURE )
   3450         return;
   3451 
   3452       switch ( exc->opcode )
   3453       {
   3454       case 0x58:    /* IF */
   3455         nIfs++;
   3456         break;
   3457 
   3458       case 0x59:    /* EIF */
   3459         nIfs--;
   3460         break;
   3461       }
   3462     } while ( nIfs != 0 );
   3463   }
   3464 
   3465 
   3466   /**************************************************************************
   3467    *
   3468    * EIF[]:        End IF
   3469    * Opcode range: 0x59
   3470    * Stack:        -->
   3471    */
   3472   static void
   3473   Ins_EIF( void )
   3474   {
   3475     /* nothing to do */
   3476   }
   3477 
   3478 
   3479   /**************************************************************************
   3480    *
   3481    * JMPR[]:       JuMP Relative
   3482    * Opcode range: 0x1C
   3483    * Stack:        int32 -->
   3484    */
   3485   static void
   3486   Ins_JMPR( TT_ExecContext  exc,
   3487             FT_Long*        args )
   3488   {
   3489     if ( args[0] == 0 && exc->args == 0 )
   3490     {
   3491       exc->error = FT_THROW( Bad_Argument );
   3492       return;
   3493     }
   3494 
   3495     exc->IP += args[0];
   3496     if ( exc->IP < 0                                             ||
   3497          ( exc->callTop > 0                                    &&
   3498            exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
   3499     {
   3500       exc->error = FT_THROW( Bad_Argument );
   3501       return;
   3502     }
   3503 
   3504     exc->step_ins = FALSE;
   3505 
   3506     if ( args[0] < 0 )
   3507     {
   3508       if ( ++exc->neg_jump_counter > exc->neg_jump_counter_max )
   3509         exc->error = FT_THROW( Execution_Too_Long );
   3510     }
   3511   }
   3512 
   3513 
   3514   /**************************************************************************
   3515    *
   3516    * JROT[]:       Jump Relative On True
   3517    * Opcode range: 0x78
   3518    * Stack:        StkElt int32 -->
   3519    */
   3520   static void
   3521   Ins_JROT( TT_ExecContext  exc,
   3522             FT_Long*        args )
   3523   {
   3524     if ( args[1] != 0 )
   3525       Ins_JMPR( exc, args );
   3526   }
   3527 
   3528 
   3529   /**************************************************************************
   3530    *
   3531    * JROF[]:       Jump Relative On False
   3532    * Opcode range: 0x79
   3533    * Stack:        StkElt int32 -->
   3534    */
   3535   static void
   3536   Ins_JROF( TT_ExecContext  exc,
   3537             FT_Long*        args )
   3538   {
   3539     if ( args[1] == 0 )
   3540       Ins_JMPR( exc, args );
   3541   }
   3542 
   3543 
   3544   /**************************************************************************
   3545    *
   3546    * DEFINING AND USING FUNCTIONS AND INSTRUCTIONS
   3547    *
   3548    */
   3549 
   3550 
   3551   /**************************************************************************
   3552    *
   3553    * FDEF[]:       Function DEFinition
   3554    * Opcode range: 0x2C
   3555    * Stack:        uint32 -->
   3556    */
   3557   static void
   3558   Ins_FDEF( TT_ExecContext  exc,
   3559             FT_Long*        args )
   3560   {
   3561     FT_ULong       n;
   3562     TT_DefRecord*  rec;
   3563     TT_DefRecord*  limit;
   3564 
   3565 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   3566     /* arguments to opcodes are skipped by `SKIP_Code' */
   3567     FT_Byte    opcode_pattern[9][12] = {
   3568                  /* #0 inline delta function 1 */
   3569                  {
   3570                    0x4B, /* PPEM    */
   3571                    0x53, /* GTEQ    */
   3572                    0x23, /* SWAP    */
   3573                    0x4B, /* PPEM    */
   3574                    0x51, /* LTEQ    */
   3575                    0x5A, /* AND     */
   3576                    0x58, /* IF      */
   3577                    0x38, /*   SHPIX */
   3578                    0x1B, /* ELSE    */
   3579                    0x21, /*   POP   */
   3580                    0x21, /*   POP   */
   3581                    0x59  /* EIF     */
   3582                  },
   3583                  /* #1 inline delta function 2 */
   3584                  {
   3585                    0x4B, /* PPEM    */
   3586                    0x54, /* EQ      */
   3587                    0x58, /* IF      */
   3588                    0x38, /*   SHPIX */
   3589                    0x1B, /* ELSE    */
   3590                    0x21, /*   POP   */
   3591                    0x21, /*   POP   */
   3592                    0x59  /* EIF     */
   3593                  },
   3594                  /* #2 diagonal stroke function */
   3595                  {
   3596                    0x20, /* DUP     */
   3597                    0x20, /* DUP     */
   3598                    0xB0, /* PUSHB_1 */
   3599                          /*   1     */
   3600                    0x60, /* ADD     */
   3601                    0x46, /* GC_cur  */
   3602                    0xB0, /* PUSHB_1 */
   3603                          /*   64    */
   3604                    0x23, /* SWAP    */
   3605                    0x42  /* WS      */
   3606                  },
   3607                  /* #3 VacuFormRound function */
   3608                  {
   3609                    0x45, /* RCVT    */
   3610                    0x23, /* SWAP    */
   3611                    0x46, /* GC_cur  */
   3612                    0x60, /* ADD     */
   3613                    0x20, /* DUP     */
   3614                    0xB0  /* PUSHB_1 */
   3615                          /*   38    */
   3616                  },
   3617                  /* #4 TTFautohint bytecode (old) */
   3618                  {
   3619                    0x20, /* DUP     */
   3620                    0x64, /* ABS     */
   3621                    0xB0, /* PUSHB_1 */
   3622                          /*   32    */
   3623                    0x60, /* ADD     */
   3624                    0x66, /* FLOOR   */
   3625                    0x23, /* SWAP    */
   3626                    0xB0  /* PUSHB_1 */
   3627                  },
   3628                  /* #5 spacing function 1 */
   3629                  {
   3630                    0x01, /* SVTCA_x */
   3631                    0xB0, /* PUSHB_1 */
   3632                          /*   24    */
   3633                    0x43, /* RS      */
   3634                    0x58  /* IF      */
   3635                  },
   3636                  /* #6 spacing function 2 */
   3637                  {
   3638                    0x01, /* SVTCA_x */
   3639                    0x18, /* RTG     */
   3640                    0xB0, /* PUSHB_1 */
   3641                          /*   24    */
   3642                    0x43, /* RS      */
   3643                    0x58  /* IF      */
   3644                  },
   3645                  /* #7 TypeMan Talk DiagEndCtrl function */
   3646                  {
   3647                    0x01, /* SVTCA_x */
   3648                    0x20, /* DUP     */
   3649                    0xB0, /* PUSHB_1 */
   3650                          /*   3     */
   3651                    0x25, /* CINDEX  */
   3652                  },
   3653                  /* #8 TypeMan Talk Align */
   3654                  {
   3655                    0x06, /* SPVTL   */
   3656                    0x7D, /* RDTG    */
   3657                  },
   3658                };
   3659     FT_UShort  opcode_patterns   = 9;
   3660     FT_UShort  opcode_pointer[9] = {  0, 0, 0, 0, 0, 0, 0, 0, 0 };
   3661     FT_UShort  opcode_size[9]    = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
   3662     FT_UShort  i;
   3663 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   3664 
   3665 
   3666     /* FDEF is only allowed in `prep' or `fpgm' */
   3667     if ( exc->curRange == tt_coderange_glyph )
   3668     {
   3669       exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
   3670       return;
   3671     }
   3672 
   3673     /* some font programs are broken enough to redefine functions! */
   3674     /* We will then parse the current table.                       */
   3675 
   3676     rec   = exc->FDefs;
   3677     limit = rec + exc->numFDefs;
   3678     n     = (FT_ULong)args[0];
   3679 
   3680     for ( ; rec < limit; rec++ )
   3681     {
   3682       if ( rec->opc == n )
   3683         break;
   3684     }
   3685 
   3686     if ( rec == limit )
   3687     {
   3688       /* check that there is enough room for new functions */
   3689       if ( exc->numFDefs >= exc->maxFDefs )
   3690       {
   3691         exc->error = FT_THROW( Too_Many_Function_Defs );
   3692         return;
   3693       }
   3694       exc->numFDefs++;
   3695     }
   3696 
   3697     /* Although FDEF takes unsigned 32-bit integer,  */
   3698     /* func # must be within unsigned 16-bit integer */
   3699     if ( n > 0xFFFFU )
   3700     {
   3701       exc->error = FT_THROW( Too_Many_Function_Defs );
   3702       return;
   3703     }
   3704 
   3705     rec->range          = exc->curRange;
   3706     rec->opc            = (FT_UInt16)n;
   3707     rec->start          = exc->IP + 1;
   3708     rec->active         = TRUE;
   3709     rec->inline_delta   = FALSE;
   3710     rec->sph_fdef_flags = 0x0000;
   3711 
   3712     if ( n > exc->maxFunc )
   3713       exc->maxFunc = (FT_UInt16)n;
   3714 
   3715 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   3716     /* We don't know for sure these are typeman functions, */
   3717     /* however they are only active when RS 22 is called   */
   3718     if ( n >= 64 && n <= 66 )
   3719       rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES;
   3720 #endif
   3721 
   3722     /* Now skip the whole function definition. */
   3723     /* We don't allow nested IDEFS & FDEFs.    */
   3724 
   3725     while ( SkipCode( exc ) == SUCCESS )
   3726     {
   3727 
   3728 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   3729 
   3730       if ( SUBPIXEL_HINTING_INFINALITY )
   3731       {
   3732         for ( i = 0; i < opcode_patterns; i++ )
   3733         {
   3734           if ( opcode_pointer[i] < opcode_size[i]                  &&
   3735                exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
   3736           {
   3737             opcode_pointer[i] += 1;
   3738 
   3739             if ( opcode_pointer[i] == opcode_size[i] )
   3740             {
   3741               FT_TRACE6(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
   3742                           i, n,
   3743                           exc->face->root.family_name,
   3744                           exc->face->root.style_name ));
   3745 
   3746               switch ( i )
   3747               {
   3748               case 0:
   3749                 rec->sph_fdef_flags             |= SPH_FDEF_INLINE_DELTA_1;
   3750                 exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
   3751                 break;
   3752 
   3753               case 1:
   3754                 rec->sph_fdef_flags             |= SPH_FDEF_INLINE_DELTA_2;
   3755                 exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
   3756                 break;
   3757 
   3758               case 2:
   3759                 switch ( n )
   3760                 {
   3761                   /* needs to be implemented still */
   3762                 case 58:
   3763                   rec->sph_fdef_flags             |= SPH_FDEF_DIAGONAL_STROKE;
   3764                   exc->face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
   3765                 }
   3766                 break;
   3767 
   3768               case 3:
   3769                 switch ( n )
   3770                 {
   3771                 case 0:
   3772                   rec->sph_fdef_flags             |= SPH_FDEF_VACUFORM_ROUND_1;
   3773                   exc->face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
   3774                 }
   3775                 break;
   3776 
   3777               case 4:
   3778                 /* probably not necessary to detect anymore */
   3779                 rec->sph_fdef_flags             |= SPH_FDEF_TTFAUTOHINT_1;
   3780                 exc->face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
   3781                 break;
   3782 
   3783               case 5:
   3784                 switch ( n )
   3785                 {
   3786                 case 0:
   3787                 case 1:
   3788                 case 2:
   3789                 case 4:
   3790                 case 7:
   3791                 case 8:
   3792                   rec->sph_fdef_flags             |= SPH_FDEF_SPACING_1;
   3793                   exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
   3794                 }
   3795                 break;
   3796 
   3797               case 6:
   3798                 switch ( n )
   3799                 {
   3800                 case 0:
   3801                 case 1:
   3802                 case 2:
   3803                 case 4:
   3804                 case 7:
   3805                 case 8:
   3806                   rec->sph_fdef_flags             |= SPH_FDEF_SPACING_2;
   3807                   exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
   3808                 }
   3809                 break;
   3810 
   3811                case 7:
   3812                  rec->sph_fdef_flags             |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
   3813                  exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
   3814                  break;
   3815 
   3816                case 8:
   3817 #if 0
   3818                  rec->sph_fdef_flags             |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
   3819                  exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
   3820 #endif
   3821                  break;
   3822               }
   3823               opcode_pointer[i] = 0;
   3824             }
   3825           }
   3826 
   3827           else
   3828             opcode_pointer[i] = 0;
   3829         }
   3830 
   3831         /* Set sph_compatibility_mode only when deltas are detected */
   3832         exc->face->sph_compatibility_mode =
   3833           ( ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
   3834             ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
   3835       }
   3836 
   3837 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   3838 
   3839       switch ( exc->opcode )
   3840       {
   3841       case 0x89:    /* IDEF */
   3842       case 0x2C:    /* FDEF */
   3843         exc->error = FT_THROW( Nested_DEFS );
   3844         return;
   3845 
   3846       case 0x2D:   /* ENDF */
   3847         rec->end = exc->IP;
   3848         return;
   3849       }
   3850     }
   3851   }
   3852 
   3853 
   3854   /**************************************************************************
   3855    *
   3856    * ENDF[]:       END Function definition
   3857    * Opcode range: 0x2D
   3858    * Stack:        -->
   3859    */
   3860   static void
   3861   Ins_ENDF( TT_ExecContext  exc )
   3862   {
   3863     TT_CallRec*  pRec;
   3864 
   3865 
   3866 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   3867     exc->sph_in_func_flags = 0x0000;
   3868 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   3869 
   3870     if ( exc->callTop <= 0 )     /* We encountered an ENDF without a call */
   3871     {
   3872       exc->error = FT_THROW( ENDF_In_Exec_Stream );
   3873       return;
   3874     }
   3875 
   3876     exc->callTop--;
   3877 
   3878     pRec = &exc->callStack[exc->callTop];
   3879 
   3880     pRec->Cur_Count--;
   3881 
   3882     exc->step_ins = FALSE;
   3883 
   3884     if ( pRec->Cur_Count > 0 )
   3885     {
   3886       exc->callTop++;
   3887       exc->IP = pRec->Def->start;
   3888     }
   3889     else
   3890       /* Loop through the current function */
   3891       Ins_Goto_CodeRange( exc, pRec->Caller_Range, pRec->Caller_IP );
   3892 
   3893     /* Exit the current call frame.                      */
   3894 
   3895     /* NOTE: If the last instruction of a program is a   */
   3896     /*       CALL or LOOPCALL, the return address is     */
   3897     /*       always out of the code range.  This is a    */
   3898     /*       valid address, and it is why we do not test */
   3899     /*       the result of Ins_Goto_CodeRange() here!    */
   3900   }
   3901 
   3902 
   3903   /**************************************************************************
   3904    *
   3905    * CALL[]:       CALL function
   3906    * Opcode range: 0x2B
   3907    * Stack:        uint32? -->
   3908    */
   3909   static void
   3910   Ins_CALL( TT_ExecContext  exc,
   3911             FT_Long*        args )
   3912   {
   3913     FT_ULong       F;
   3914     TT_CallRec*    pCrec;
   3915     TT_DefRecord*  def;
   3916 
   3917 
   3918     /* first of all, check the index */
   3919 
   3920     F = (FT_ULong)args[0];
   3921     if ( BOUNDSL( F, exc->maxFunc + 1 ) )
   3922       goto Fail;
   3923 
   3924     /* Except for some old Apple fonts, all functions in a TrueType */
   3925     /* font are defined in increasing order, starting from 0.  This */
   3926     /* means that we normally have                                  */
   3927     /*                                                              */
   3928     /*    exc->maxFunc+1 == exc->numFDefs                           */
   3929     /*    exc->FDefs[n].opc == n for n in 0..exc->maxFunc           */
   3930     /*                                                              */
   3931     /* If this isn't true, we need to look up the function table.   */
   3932 
   3933     def = exc->FDefs + F;
   3934     if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
   3935     {
   3936       /* look up the FDefs table */
   3937       TT_DefRecord*  limit;
   3938 
   3939 
   3940       def   = exc->FDefs;
   3941       limit = def + exc->numFDefs;
   3942 
   3943       while ( def < limit && def->opc != F )
   3944         def++;
   3945 
   3946       if ( def == limit )
   3947         goto Fail;
   3948     }
   3949 
   3950     /* check that the function is active */
   3951     if ( !def->active )
   3952       goto Fail;
   3953 
   3954 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   3955     if ( SUBPIXEL_HINTING_INFINALITY                                    &&
   3956          exc->ignore_x_mode                                             &&
   3957          ( ( exc->iup_called                                        &&
   3958              ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
   3959            ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 )        ) )
   3960       goto Fail;
   3961     else
   3962       exc->sph_in_func_flags = def->sph_fdef_flags;
   3963 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   3964 
   3965     /* check the call stack */
   3966     if ( exc->callTop >= exc->callSize )
   3967     {
   3968       exc->error = FT_THROW( Stack_Overflow );
   3969       return;
   3970     }
   3971 
   3972     pCrec = exc->callStack + exc->callTop;
   3973 
   3974     pCrec->Caller_Range = exc->curRange;
   3975     pCrec->Caller_IP    = exc->IP + 1;
   3976     pCrec->Cur_Count    = 1;
   3977     pCrec->Def          = def;
   3978 
   3979     exc->callTop++;
   3980 
   3981     Ins_Goto_CodeRange( exc, def->range, def->start );
   3982 
   3983     exc->step_ins = FALSE;
   3984 
   3985     return;
   3986 
   3987   Fail:
   3988     exc->error = FT_THROW( Invalid_Reference );
   3989   }
   3990 
   3991 
   3992   /**************************************************************************
   3993    *
   3994    * LOOPCALL[]:   LOOP and CALL function
   3995    * Opcode range: 0x2A
   3996    * Stack:        uint32? Eint16? -->
   3997    */
   3998   static void
   3999   Ins_LOOPCALL( TT_ExecContext  exc,
   4000                 FT_Long*        args )
   4001   {
   4002     FT_ULong       F;
   4003     TT_CallRec*    pCrec;
   4004     TT_DefRecord*  def;
   4005 
   4006 
   4007     /* first of all, check the index */
   4008     F = (FT_ULong)args[1];
   4009     if ( BOUNDSL( F, exc->maxFunc + 1 ) )
   4010       goto Fail;
   4011 
   4012     /* Except for some old Apple fonts, all functions in a TrueType */
   4013     /* font are defined in increasing order, starting from 0.  This */
   4014     /* means that we normally have                                  */
   4015     /*                                                              */
   4016     /*    exc->maxFunc+1 == exc->numFDefs                           */
   4017     /*    exc->FDefs[n].opc == n for n in 0..exc->maxFunc           */
   4018     /*                                                              */
   4019     /* If this isn't true, we need to look up the function table.   */
   4020 
   4021     def = exc->FDefs + F;
   4022     if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
   4023     {
   4024       /* look up the FDefs table */
   4025       TT_DefRecord*  limit;
   4026 
   4027 
   4028       def   = exc->FDefs;
   4029       limit = def + exc->numFDefs;
   4030 
   4031       while ( def < limit && def->opc != F )
   4032         def++;
   4033 
   4034       if ( def == limit )
   4035         goto Fail;
   4036     }
   4037 
   4038     /* check that the function is active */
   4039     if ( !def->active )
   4040       goto Fail;
   4041 
   4042 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   4043     if ( SUBPIXEL_HINTING_INFINALITY                         &&
   4044          exc->ignore_x_mode                                  &&
   4045          ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
   4046       goto Fail;
   4047     else
   4048       exc->sph_in_func_flags = def->sph_fdef_flags;
   4049 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   4050 
   4051     /* check stack */
   4052     if ( exc->callTop >= exc->callSize )
   4053     {
   4054       exc->error = FT_THROW( Stack_Overflow );
   4055       return;
   4056     }
   4057 
   4058     if ( args[0] > 0 )
   4059     {
   4060       pCrec = exc->callStack + exc->callTop;
   4061 
   4062       pCrec->Caller_Range = exc->curRange;
   4063       pCrec->Caller_IP    = exc->IP + 1;
   4064       pCrec->Cur_Count    = (FT_Int)args[0];
   4065       pCrec->Def          = def;
   4066 
   4067       exc->callTop++;
   4068 
   4069       Ins_Goto_CodeRange( exc, def->range, def->start );
   4070 
   4071       exc->step_ins = FALSE;
   4072 
   4073       exc->loopcall_counter += (FT_ULong)args[0];
   4074       if ( exc->loopcall_counter > exc->loopcall_counter_max )
   4075         exc->error = FT_THROW( Execution_Too_Long );
   4076     }
   4077 
   4078     return;
   4079 
   4080   Fail:
   4081     exc->error = FT_THROW( Invalid_Reference );
   4082   }
   4083 
   4084 
   4085   /**************************************************************************
   4086    *
   4087    * IDEF[]:       Instruction DEFinition
   4088    * Opcode range: 0x89
   4089    * Stack:        Eint8 -->
   4090    */
   4091   static void
   4092   Ins_IDEF( TT_ExecContext  exc,
   4093             FT_Long*        args )
   4094   {
   4095     TT_DefRecord*  def;
   4096     TT_DefRecord*  limit;
   4097 
   4098 
   4099     /* we enable IDEF only in `prep' or `fpgm' */
   4100     if ( exc->curRange == tt_coderange_glyph )
   4101     {
   4102       exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
   4103       return;
   4104     }
   4105 
   4106     /*  First of all, look for the same function in our table */
   4107 
   4108     def   = exc->IDefs;
   4109     limit = def + exc->numIDefs;
   4110 
   4111     for ( ; def < limit; def++ )
   4112       if ( def->opc == (FT_ULong)args[0] )
   4113         break;
   4114 
   4115     if ( def == limit )
   4116     {
   4117       /* check that there is enough room for a new instruction */
   4118       if ( exc->numIDefs >= exc->maxIDefs )
   4119       {
   4120         exc->error = FT_THROW( Too_Many_Instruction_Defs );
   4121         return;
   4122       }
   4123       exc->numIDefs++;
   4124     }
   4125 
   4126     /* opcode must be unsigned 8-bit integer */
   4127     if ( 0 > args[0] || args[0] > 0x00FF )
   4128     {
   4129       exc->error = FT_THROW( Too_Many_Instruction_Defs );
   4130       return;
   4131     }
   4132 
   4133     def->opc    = (FT_Byte)args[0];
   4134     def->start  = exc->IP + 1;
   4135     def->range  = exc->curRange;
   4136     def->active = TRUE;
   4137 
   4138     if ( (FT_ULong)args[0] > exc->maxIns )
   4139       exc->maxIns = (FT_Byte)args[0];
   4140 
   4141     /* Now skip the whole function definition. */
   4142     /* We don't allow nested IDEFs & FDEFs.    */
   4143 
   4144     while ( SkipCode( exc ) == SUCCESS )
   4145     {
   4146       switch ( exc->opcode )
   4147       {
   4148       case 0x89:   /* IDEF */
   4149       case 0x2C:   /* FDEF */
   4150         exc->error = FT_THROW( Nested_DEFS );
   4151         return;
   4152       case 0x2D:   /* ENDF */
   4153         def->end = exc->IP;
   4154         return;
   4155       }
   4156     }
   4157   }
   4158 
   4159 
   4160   /**************************************************************************
   4161    *
   4162    * PUSHING DATA ONTO THE INTERPRETER STACK
   4163    *
   4164    */
   4165 
   4166 
   4167   /**************************************************************************
   4168    *
   4169    * NPUSHB[]:     PUSH N Bytes
   4170    * Opcode range: 0x40
   4171    * Stack:        --> uint32...
   4172    */
   4173   static void
   4174   Ins_NPUSHB( TT_ExecContext  exc,
   4175               FT_Long*        args )
   4176   {
   4177     FT_UShort  L, K;
   4178 
   4179 
   4180     L = (FT_UShort)exc->code[exc->IP + 1];
   4181 
   4182     if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
   4183     {
   4184       exc->error = FT_THROW( Stack_Overflow );
   4185       return;
   4186     }
   4187 
   4188     for ( K = 1; K <= L; K++ )
   4189       args[K - 1] = exc->code[exc->IP + K + 1];
   4190 
   4191     exc->new_top += L;
   4192   }
   4193 
   4194 
   4195   /**************************************************************************
   4196    *
   4197    * NPUSHW[]:     PUSH N Words
   4198    * Opcode range: 0x41
   4199    * Stack:        --> int32...
   4200    */
   4201   static void
   4202   Ins_NPUSHW( TT_ExecContext  exc,
   4203               FT_Long*        args )
   4204   {
   4205     FT_UShort  L, K;
   4206 
   4207 
   4208     L = (FT_UShort)exc->code[exc->IP + 1];
   4209 
   4210     if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
   4211     {
   4212       exc->error = FT_THROW( Stack_Overflow );
   4213       return;
   4214     }
   4215 
   4216     exc->IP += 2;
   4217 
   4218     for ( K = 0; K < L; K++ )
   4219       args[K] = GetShortIns( exc );
   4220 
   4221     exc->step_ins = FALSE;
   4222     exc->new_top += L;
   4223   }
   4224 
   4225 
   4226   /**************************************************************************
   4227    *
   4228    * PUSHB[abc]:   PUSH Bytes
   4229    * Opcode range: 0xB0-0xB7
   4230    * Stack:        --> uint32...
   4231    */
   4232   static void
   4233   Ins_PUSHB( TT_ExecContext  exc,
   4234              FT_Long*        args )
   4235   {
   4236     FT_UShort  L, K;
   4237 
   4238 
   4239     L = (FT_UShort)( exc->opcode - 0xB0 + 1 );
   4240 
   4241     if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
   4242     {
   4243       exc->error = FT_THROW( Stack_Overflow );
   4244       return;
   4245     }
   4246 
   4247     for ( K = 1; K <= L; K++ )
   4248       args[K - 1] = exc->code[exc->IP + K];
   4249   }
   4250 
   4251 
   4252   /**************************************************************************
   4253    *
   4254    * PUSHW[abc]:   PUSH Words
   4255    * Opcode range: 0xB8-0xBF
   4256    * Stack:        --> int32...
   4257    */
   4258   static void
   4259   Ins_PUSHW( TT_ExecContext  exc,
   4260              FT_Long*        args )
   4261   {
   4262     FT_UShort  L, K;
   4263 
   4264 
   4265     L = (FT_UShort)( exc->opcode - 0xB8 + 1 );
   4266 
   4267     if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
   4268     {
   4269       exc->error = FT_THROW( Stack_Overflow );
   4270       return;
   4271     }
   4272 
   4273     exc->IP++;
   4274 
   4275     for ( K = 0; K < L; K++ )
   4276       args[K] = GetShortIns( exc );
   4277 
   4278     exc->step_ins = FALSE;
   4279   }
   4280 
   4281 
   4282   /**************************************************************************
   4283    *
   4284    * MANAGING THE GRAPHICS STATE
   4285    *
   4286    */
   4287 
   4288 
   4289   static FT_Bool
   4290   Ins_SxVTL( TT_ExecContext  exc,
   4291              FT_UShort       aIdx1,
   4292              FT_UShort       aIdx2,
   4293              FT_UnitVector*  Vec )
   4294   {
   4295     FT_Long     A, B, C;
   4296     FT_Vector*  p1;
   4297     FT_Vector*  p2;
   4298 
   4299     FT_Byte  opcode = exc->opcode;
   4300 
   4301 
   4302     if ( BOUNDS( aIdx1, exc->zp2.n_points ) ||
   4303          BOUNDS( aIdx2, exc->zp1.n_points ) )
   4304     {
   4305       if ( exc->pedantic_hinting )
   4306         exc->error = FT_THROW( Invalid_Reference );
   4307       return FAILURE;
   4308     }
   4309 
   4310     p1 = exc->zp1.cur + aIdx2;
   4311     p2 = exc->zp2.cur + aIdx1;
   4312 
   4313     A = SUB_LONG( p1->x, p2->x );
   4314     B = SUB_LONG( p1->y, p2->y );
   4315 
   4316     /* If p1 == p2, SPvTL and SFvTL behave the same as */
   4317     /* SPvTCA[X] and SFvTCA[X], respectively.          */
   4318     /*                                                 */
   4319     /* Confirmed by Greg Hitchcock.                    */
   4320 
   4321     if ( A == 0 && B == 0 )
   4322     {
   4323       A      = 0x4000;
   4324       opcode = 0;
   4325     }
   4326 
   4327     if ( ( opcode & 1 ) != 0 )
   4328     {
   4329       C = B;   /* counter clockwise rotation */
   4330       B = A;
   4331       A = NEG_LONG( C );
   4332     }
   4333 
   4334     Normalize( A, B, Vec );
   4335 
   4336     return SUCCESS;
   4337   }
   4338 
   4339 
   4340   /**************************************************************************
   4341    *
   4342    * SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis
   4343    * Opcode range: 0x00-0x01
   4344    * Stack:        -->
   4345    *
   4346    * SPvTCA[a]:    Set PVector to Coordinate Axis
   4347    * Opcode range: 0x02-0x03
   4348    * Stack:        -->
   4349    *
   4350    * SFvTCA[a]:    Set FVector to Coordinate Axis
   4351    * Opcode range: 0x04-0x05
   4352    * Stack:        -->
   4353    */
   4354   static void
   4355   Ins_SxyTCA( TT_ExecContext  exc )
   4356   {
   4357     FT_Short  AA, BB;
   4358 
   4359     FT_Byte  opcode = exc->opcode;
   4360 
   4361 
   4362     AA = (FT_Short)( ( opcode & 1 ) << 14 );
   4363     BB = (FT_Short)( AA ^ 0x4000 );
   4364 
   4365     if ( opcode < 4 )
   4366     {
   4367       exc->GS.projVector.x = AA;
   4368       exc->GS.projVector.y = BB;
   4369 
   4370       exc->GS.dualVector.x = AA;
   4371       exc->GS.dualVector.y = BB;
   4372     }
   4373 
   4374     if ( ( opcode & 2 ) == 0 )
   4375     {
   4376       exc->GS.freeVector.x = AA;
   4377       exc->GS.freeVector.y = BB;
   4378     }
   4379 
   4380     Compute_Funcs( exc );
   4381   }
   4382 
   4383 
   4384   /**************************************************************************
   4385    *
   4386    * SPvTL[a]:     Set PVector To Line
   4387    * Opcode range: 0x06-0x07
   4388    * Stack:        uint32 uint32 -->
   4389    */
   4390   static void
   4391   Ins_SPVTL( TT_ExecContext  exc,
   4392              FT_Long*        args )
   4393   {
   4394     if ( Ins_SxVTL( exc,
   4395                     (FT_UShort)args[1],
   4396                     (FT_UShort)args[0],
   4397                     &exc->GS.projVector ) == SUCCESS )
   4398     {
   4399       exc->GS.dualVector = exc->GS.projVector;
   4400       Compute_Funcs( exc );
   4401     }
   4402   }
   4403 
   4404 
   4405   /**************************************************************************
   4406    *
   4407    * SFvTL[a]:     Set FVector To Line
   4408    * Opcode range: 0x08-0x09
   4409    * Stack:        uint32 uint32 -->
   4410    */
   4411   static void
   4412   Ins_SFVTL( TT_ExecContext  exc,
   4413              FT_Long*        args )
   4414   {
   4415     if ( Ins_SxVTL( exc,
   4416                     (FT_UShort)args[1],
   4417                     (FT_UShort)args[0],
   4418                     &exc->GS.freeVector ) == SUCCESS )
   4419     {
   4420       Compute_Funcs( exc );
   4421     }
   4422   }
   4423 
   4424 
   4425   /**************************************************************************
   4426    *
   4427    * SFvTPv[]:     Set FVector To PVector
   4428    * Opcode range: 0x0E
   4429    * Stack:        -->
   4430    */
   4431   static void
   4432   Ins_SFVTPV( TT_ExecContext  exc )
   4433   {
   4434     exc->GS.freeVector = exc->GS.projVector;
   4435     Compute_Funcs( exc );
   4436   }
   4437 
   4438 
   4439   /**************************************************************************
   4440    *
   4441    * SPvFS[]:      Set PVector From Stack
   4442    * Opcode range: 0x0A
   4443    * Stack:        f2.14 f2.14 -->
   4444    */
   4445   static void
   4446   Ins_SPVFS( TT_ExecContext  exc,
   4447              FT_Long*        args )
   4448   {
   4449     FT_Short  S;
   4450     FT_Long   X, Y;
   4451 
   4452 
   4453     /* Only use low 16bits, then sign extend */
   4454     S = (FT_Short)args[1];
   4455     Y = (FT_Long)S;
   4456     S = (FT_Short)args[0];
   4457     X = (FT_Long)S;
   4458 
   4459     Normalize( X, Y, &exc->GS.projVector );
   4460 
   4461     exc->GS.dualVector = exc->GS.projVector;
   4462     Compute_Funcs( exc );
   4463   }
   4464 
   4465 
   4466   /**************************************************************************
   4467    *
   4468    * SFvFS[]:      Set FVector From Stack
   4469    * Opcode range: 0x0B
   4470    * Stack:        f2.14 f2.14 -->
   4471    */
   4472   static void
   4473   Ins_SFVFS( TT_ExecContext  exc,
   4474              FT_Long*        args )
   4475   {
   4476     FT_Short  S;
   4477     FT_Long   X, Y;
   4478 
   4479 
   4480     /* Only use low 16bits, then sign extend */
   4481     S = (FT_Short)args[1];
   4482     Y = (FT_Long)S;
   4483     S = (FT_Short)args[0];
   4484     X = S;
   4485 
   4486     Normalize( X, Y, &exc->GS.freeVector );
   4487     Compute_Funcs( exc );
   4488   }
   4489 
   4490 
   4491   /**************************************************************************
   4492    *
   4493    * GPv[]:        Get Projection Vector
   4494    * Opcode range: 0x0C
   4495    * Stack:        ef2.14 --> ef2.14
   4496    */
   4497   static void
   4498   Ins_GPV( TT_ExecContext  exc,
   4499            FT_Long*        args )
   4500   {
   4501     args[0] = exc->GS.projVector.x;
   4502     args[1] = exc->GS.projVector.y;
   4503   }
   4504 
   4505 
   4506   /**************************************************************************
   4507    *
   4508    * GFv[]:        Get Freedom Vector
   4509    * Opcode range: 0x0D
   4510    * Stack:        ef2.14 --> ef2.14
   4511    */
   4512   static void
   4513   Ins_GFV( TT_ExecContext  exc,
   4514            FT_Long*        args )
   4515   {
   4516     args[0] = exc->GS.freeVector.x;
   4517     args[1] = exc->GS.freeVector.y;
   4518   }
   4519 
   4520 
   4521   /**************************************************************************
   4522    *
   4523    * SRP0[]:       Set Reference Point 0
   4524    * Opcode range: 0x10
   4525    * Stack:        uint32 -->
   4526    */
   4527   static void
   4528   Ins_SRP0( TT_ExecContext  exc,
   4529             FT_Long*        args )
   4530   {
   4531     exc->GS.rp0 = (FT_UShort)args[0];
   4532   }
   4533 
   4534 
   4535   /**************************************************************************
   4536    *
   4537    * SRP1[]:       Set Reference Point 1
   4538    * Opcode range: 0x11
   4539    * Stack:        uint32 -->
   4540    */
   4541   static void
   4542   Ins_SRP1( TT_ExecContext  exc,
   4543             FT_Long*        args )
   4544   {
   4545     exc->GS.rp1 = (FT_UShort)args[0];
   4546   }
   4547 
   4548 
   4549   /**************************************************************************
   4550    *
   4551    * SRP2[]:       Set Reference Point 2
   4552    * Opcode range: 0x12
   4553    * Stack:        uint32 -->
   4554    */
   4555   static void
   4556   Ins_SRP2( TT_ExecContext  exc,
   4557             FT_Long*        args )
   4558   {
   4559     exc->GS.rp2 = (FT_UShort)args[0];
   4560   }
   4561 
   4562 
   4563   /**************************************************************************
   4564    *
   4565    * SMD[]:        Set Minimum Distance
   4566    * Opcode range: 0x1A
   4567    * Stack:        f26.6 -->
   4568    */
   4569   static void
   4570   Ins_SMD( TT_ExecContext  exc,
   4571            FT_Long*        args )
   4572   {
   4573     exc->GS.minimum_distance = args[0];
   4574   }
   4575 
   4576 
   4577   /**************************************************************************
   4578    *
   4579    * SCVTCI[]:     Set Control Value Table Cut In
   4580    * Opcode range: 0x1D
   4581    * Stack:        f26.6 -->
   4582    */
   4583   static void
   4584   Ins_SCVTCI( TT_ExecContext  exc,
   4585               FT_Long*        args )
   4586   {
   4587     exc->GS.control_value_cutin = (FT_F26Dot6)args[0];
   4588   }
   4589 
   4590 
   4591   /**************************************************************************
   4592    *
   4593    * SSWCI[]:      Set Single Width Cut In
   4594    * Opcode range: 0x1E
   4595    * Stack:        f26.6 -->
   4596    */
   4597   static void
   4598   Ins_SSWCI( TT_ExecContext  exc,
   4599              FT_Long*        args )
   4600   {
   4601     exc->GS.single_width_cutin = (FT_F26Dot6)args[0];
   4602   }
   4603 
   4604 
   4605   /**************************************************************************
   4606    *
   4607    * SSW[]:        Set Single Width
   4608    * Opcode range: 0x1F
   4609    * Stack:        int32? -->
   4610    */
   4611   static void
   4612   Ins_SSW( TT_ExecContext  exc,
   4613            FT_Long*        args )
   4614   {
   4615     exc->GS.single_width_value = FT_MulFix( args[0],
   4616                                             exc->tt_metrics.scale );
   4617   }
   4618 
   4619 
   4620   /**************************************************************************
   4621    *
   4622    * FLIPON[]:     Set auto-FLIP to ON
   4623    * Opcode range: 0x4D
   4624    * Stack:        -->
   4625    */
   4626   static void
   4627   Ins_FLIPON( TT_ExecContext  exc )
   4628   {
   4629     exc->GS.auto_flip = TRUE;
   4630   }
   4631 
   4632 
   4633   /**************************************************************************
   4634    *
   4635    * FLIPOFF[]:    Set auto-FLIP to OFF
   4636    * Opcode range: 0x4E
   4637    * Stack:        -->
   4638    */
   4639   static void
   4640   Ins_FLIPOFF( TT_ExecContext  exc )
   4641   {
   4642     exc->GS.auto_flip = FALSE;
   4643   }
   4644 
   4645 
   4646   /**************************************************************************
   4647    *
   4648    * SANGW[]:      Set ANGle Weight
   4649    * Opcode range: 0x7E
   4650    * Stack:        uint32 -->
   4651    */
   4652   static void
   4653   Ins_SANGW( void )
   4654   {
   4655     /* instruction not supported anymore */
   4656   }
   4657 
   4658 
   4659   /**************************************************************************
   4660    *
   4661    * SDB[]:        Set Delta Base
   4662    * Opcode range: 0x5E
   4663    * Stack:        uint32 -->
   4664    */
   4665   static void
   4666   Ins_SDB( TT_ExecContext  exc,
   4667            FT_Long*        args )
   4668   {
   4669     exc->GS.delta_base = (FT_UShort)args[0];
   4670   }
   4671 
   4672 
   4673   /**************************************************************************
   4674    *
   4675    * SDS[]:        Set Delta Shift
   4676    * Opcode range: 0x5F
   4677    * Stack:        uint32 -->
   4678    */
   4679   static void
   4680   Ins_SDS( TT_ExecContext  exc,
   4681            FT_Long*        args )
   4682   {
   4683     if ( (FT_ULong)args[0] > 6UL )
   4684       exc->error = FT_THROW( Bad_Argument );
   4685     else
   4686       exc->GS.delta_shift = (FT_UShort)args[0];
   4687   }
   4688 
   4689 
   4690   /**************************************************************************
   4691    *
   4692    * RTHG[]:       Round To Half Grid
   4693    * Opcode range: 0x19
   4694    * Stack:        -->
   4695    */
   4696   static void
   4697   Ins_RTHG( TT_ExecContext  exc )
   4698   {
   4699     exc->GS.round_state = TT_Round_To_Half_Grid;
   4700     exc->func_round     = (TT_Round_Func)Round_To_Half_Grid;
   4701   }
   4702 
   4703 
   4704   /**************************************************************************
   4705    *
   4706    * RTG[]:        Round To Grid
   4707    * Opcode range: 0x18
   4708    * Stack:        -->
   4709    */
   4710   static void
   4711   Ins_RTG( TT_ExecContext  exc )
   4712   {
   4713     exc->GS.round_state = TT_Round_To_Grid;
   4714     exc->func_round     = (TT_Round_Func)Round_To_Grid;
   4715   }
   4716 
   4717 
   4718   /**************************************************************************
   4719    * RTDG[]:       Round To Double Grid
   4720    * Opcode range: 0x3D
   4721    * Stack:        -->
   4722    */
   4723   static void
   4724   Ins_RTDG( TT_ExecContext  exc )
   4725   {
   4726     exc->GS.round_state = TT_Round_To_Double_Grid;
   4727     exc->func_round     = (TT_Round_Func)Round_To_Double_Grid;
   4728   }
   4729 
   4730 
   4731   /**************************************************************************
   4732    * RUTG[]:       Round Up To Grid
   4733    * Opcode range: 0x7C
   4734    * Stack:        -->
   4735    */
   4736   static void
   4737   Ins_RUTG( TT_ExecContext  exc )
   4738   {
   4739     exc->GS.round_state = TT_Round_Up_To_Grid;
   4740     exc->func_round     = (TT_Round_Func)Round_Up_To_Grid;
   4741   }
   4742 
   4743 
   4744   /**************************************************************************
   4745    *
   4746    * RDTG[]:       Round Down To Grid
   4747    * Opcode range: 0x7D
   4748    * Stack:        -->
   4749    */
   4750   static void
   4751   Ins_RDTG( TT_ExecContext  exc )
   4752   {
   4753     exc->GS.round_state = TT_Round_Down_To_Grid;
   4754     exc->func_round     = (TT_Round_Func)Round_Down_To_Grid;
   4755   }
   4756 
   4757 
   4758   /**************************************************************************
   4759    *
   4760    * ROFF[]:       Round OFF
   4761    * Opcode range: 0x7A
   4762    * Stack:        -->
   4763    */
   4764   static void
   4765   Ins_ROFF( TT_ExecContext  exc )
   4766   {
   4767     exc->GS.round_state = TT_Round_Off;
   4768     exc->func_round     = (TT_Round_Func)Round_None;
   4769   }
   4770 
   4771 
   4772   /**************************************************************************
   4773    *
   4774    * SROUND[]:     Super ROUND
   4775    * Opcode range: 0x76
   4776    * Stack:        Eint8 -->
   4777    */
   4778   static void
   4779   Ins_SROUND( TT_ExecContext  exc,
   4780               FT_Long*        args )
   4781   {
   4782     SetSuperRound( exc, 0x4000, args[0] );
   4783 
   4784     exc->GS.round_state = TT_Round_Super;
   4785     exc->func_round     = (TT_Round_Func)Round_Super;
   4786   }
   4787 
   4788 
   4789   /**************************************************************************
   4790    *
   4791    * S45ROUND[]:   Super ROUND 45 degrees
   4792    * Opcode range: 0x77
   4793    * Stack:        uint32 -->
   4794    */
   4795   static void
   4796   Ins_S45ROUND( TT_ExecContext  exc,
   4797                 FT_Long*        args )
   4798   {
   4799     SetSuperRound( exc, 0x2D41, args[0] );
   4800 
   4801     exc->GS.round_state = TT_Round_Super_45;
   4802     exc->func_round     = (TT_Round_Func)Round_Super_45;
   4803   }
   4804 
   4805 
   4806   /**************************************************************************
   4807    *
   4808    * GC[a]:        Get Coordinate projected onto
   4809    * Opcode range: 0x46-0x47
   4810    * Stack:        uint32 --> f26.6
   4811    *
   4812    * XXX: UNDOCUMENTED: Measures from the original glyph must be taken
   4813    *      along the dual projection vector!
   4814    */
   4815   static void
   4816   Ins_GC( TT_ExecContext  exc,
   4817           FT_Long*        args )
   4818   {
   4819     FT_ULong    L;
   4820     FT_F26Dot6  R;
   4821 
   4822 
   4823     L = (FT_ULong)args[0];
   4824 
   4825     if ( BOUNDSL( L, exc->zp2.n_points ) )
   4826     {
   4827       if ( exc->pedantic_hinting )
   4828         exc->error = FT_THROW( Invalid_Reference );
   4829       R = 0;
   4830     }
   4831     else
   4832     {
   4833       if ( exc->opcode & 1 )
   4834         R = FAST_DUALPROJ( &exc->zp2.org[L] );
   4835       else
   4836         R = FAST_PROJECT( &exc->zp2.cur[L] );
   4837     }
   4838 
   4839     args[0] = R;
   4840   }
   4841 
   4842 
   4843   /**************************************************************************
   4844    *
   4845    * SCFS[]:       Set Coordinate From Stack
   4846    * Opcode range: 0x48
   4847    * Stack:        f26.6 uint32 -->
   4848    *
   4849    * Formula:
   4850    *
   4851    *   OA := OA + ( value - OA.p )/( f.p ) * f
   4852    */
   4853   static void
   4854   Ins_SCFS( TT_ExecContext  exc,
   4855             FT_Long*        args )
   4856   {
   4857     FT_Long    K;
   4858     FT_UShort  L;
   4859 
   4860 
   4861     L = (FT_UShort)args[0];
   4862 
   4863     if ( BOUNDS( L, exc->zp2.n_points ) )
   4864     {
   4865       if ( exc->pedantic_hinting )
   4866         exc->error = FT_THROW( Invalid_Reference );
   4867       return;
   4868     }
   4869 
   4870     K = FAST_PROJECT( &exc->zp2.cur[L] );
   4871 
   4872     exc->func_move( exc, &exc->zp2, L, SUB_LONG( args[1], K ) );
   4873 
   4874     /* UNDOCUMENTED!  The MS rasterizer does that with */
   4875     /* twilight points (confirmed by Greg Hitchcock)   */
   4876     if ( exc->GS.gep2 == 0 )
   4877       exc->zp2.org[L] = exc->zp2.cur[L];
   4878   }
   4879 
   4880 
   4881   /**************************************************************************
   4882    *
   4883    * MD[a]:        Measure Distance
   4884    * Opcode range: 0x49-0x4A
   4885    * Stack:        uint32 uint32 --> f26.6
   4886    *
   4887    * XXX: UNDOCUMENTED: Measure taken in the original glyph must be along
   4888    *                    the dual projection vector.
   4889    *
   4890    * XXX: UNDOCUMENTED: Flag attributes are inverted!
   4891    *                      0 => measure distance in original outline
   4892    *                      1 => measure distance in grid-fitted outline
   4893    *
   4894    * XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1!
   4895    */
   4896   static void
   4897   Ins_MD( TT_ExecContext  exc,
   4898           FT_Long*        args )
   4899   {
   4900     FT_UShort   K, L;
   4901     FT_F26Dot6  D;
   4902 
   4903 
   4904     K = (FT_UShort)args[1];
   4905     L = (FT_UShort)args[0];
   4906 
   4907     if ( BOUNDS( L, exc->zp0.n_points ) ||
   4908          BOUNDS( K, exc->zp1.n_points ) )
   4909     {
   4910       if ( exc->pedantic_hinting )
   4911         exc->error = FT_THROW( Invalid_Reference );
   4912       D = 0;
   4913     }
   4914     else
   4915     {
   4916       if ( exc->opcode & 1 )
   4917         D = PROJECT( exc->zp0.cur + L, exc->zp1.cur + K );
   4918       else
   4919       {
   4920         /* XXX: UNDOCUMENTED: twilight zone special case */
   4921 
   4922         if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
   4923         {
   4924           FT_Vector*  vec1 = exc->zp0.org + L;
   4925           FT_Vector*  vec2 = exc->zp1.org + K;
   4926 
   4927 
   4928           D = DUALPROJ( vec1, vec2 );
   4929         }
   4930         else
   4931         {
   4932           FT_Vector*  vec1 = exc->zp0.orus + L;
   4933           FT_Vector*  vec2 = exc->zp1.orus + K;
   4934 
   4935 
   4936           if ( exc->metrics.x_scale == exc->metrics.y_scale )
   4937           {
   4938             /* this should be faster */
   4939             D = DUALPROJ( vec1, vec2 );
   4940             D = FT_MulFix( D, exc->metrics.x_scale );
   4941           }
   4942           else
   4943           {
   4944             FT_Vector  vec;
   4945 
   4946 
   4947             vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
   4948             vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
   4949 
   4950             D = FAST_DUALPROJ( &vec );
   4951           }
   4952         }
   4953       }
   4954     }
   4955 
   4956 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   4957     /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
   4958     if ( SUBPIXEL_HINTING_INFINALITY &&
   4959          exc->ignore_x_mode          &&
   4960          FT_ABS( D ) == 64           )
   4961       D += 1;
   4962 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   4963 
   4964     args[0] = D;
   4965   }
   4966 
   4967 
   4968   /**************************************************************************
   4969    *
   4970    * SDPvTL[a]:    Set Dual PVector to Line
   4971    * Opcode range: 0x86-0x87
   4972    * Stack:        uint32 uint32 -->
   4973    */
   4974   static void
   4975   Ins_SDPVTL( TT_ExecContext  exc,
   4976               FT_Long*        args )
   4977   {
   4978     FT_Long    A, B, C;
   4979     FT_UShort  p1, p2;            /* was FT_Int in pas type ERROR */
   4980 
   4981     FT_Byte  opcode = exc->opcode;
   4982 
   4983 
   4984     p1 = (FT_UShort)args[1];
   4985     p2 = (FT_UShort)args[0];
   4986 
   4987     if ( BOUNDS( p2, exc->zp1.n_points ) ||
   4988          BOUNDS( p1, exc->zp2.n_points ) )
   4989     {
   4990       if ( exc->pedantic_hinting )
   4991         exc->error = FT_THROW( Invalid_Reference );
   4992       return;
   4993     }
   4994 
   4995     {
   4996       FT_Vector*  v1 = exc->zp1.org + p2;
   4997       FT_Vector*  v2 = exc->zp2.org + p1;
   4998 
   4999 
   5000       A = SUB_LONG( v1->x, v2->x );
   5001       B = SUB_LONG( v1->y, v2->y );
   5002 
   5003       /* If v1 == v2, SDPvTL behaves the same as */
   5004       /* SVTCA[X], respectively.                 */
   5005       /*                                         */
   5006       /* Confirmed by Greg Hitchcock.            */
   5007 
   5008       if ( A == 0 && B == 0 )
   5009       {
   5010         A      = 0x4000;
   5011         opcode = 0;
   5012       }
   5013     }
   5014 
   5015     if ( ( opcode & 1 ) != 0 )
   5016     {
   5017       C = B;   /* counter clockwise rotation */
   5018       B = A;
   5019       A = NEG_LONG( C );
   5020     }
   5021 
   5022     Normalize( A, B, &exc->GS.dualVector );
   5023 
   5024     {
   5025       FT_Vector*  v1 = exc->zp1.cur + p2;
   5026       FT_Vector*  v2 = exc->zp2.cur + p1;
   5027 
   5028 
   5029       A = SUB_LONG( v1->x, v2->x );
   5030       B = SUB_LONG( v1->y, v2->y );
   5031 
   5032       if ( A == 0 && B == 0 )
   5033       {
   5034         A      = 0x4000;
   5035         opcode = 0;
   5036       }
   5037     }
   5038 
   5039     if ( ( opcode & 1 ) != 0 )
   5040     {
   5041       C = B;   /* counter clockwise rotation */
   5042       B = A;
   5043       A = NEG_LONG( C );
   5044     }
   5045 
   5046     Normalize( A, B, &exc->GS.projVector );
   5047     Compute_Funcs( exc );
   5048   }
   5049 
   5050 
   5051   /**************************************************************************
   5052    *
   5053    * SZP0[]:       Set Zone Pointer 0
   5054    * Opcode range: 0x13
   5055    * Stack:        uint32 -->
   5056    */
   5057   static void
   5058   Ins_SZP0( TT_ExecContext  exc,
   5059             FT_Long*        args )
   5060   {
   5061     switch ( (FT_Int)args[0] )
   5062     {
   5063     case 0:
   5064       exc->zp0 = exc->twilight;
   5065       break;
   5066 
   5067     case 1:
   5068       exc->zp0 = exc->pts;
   5069       break;
   5070 
   5071     default:
   5072       if ( exc->pedantic_hinting )
   5073         exc->error = FT_THROW( Invalid_Reference );
   5074       return;
   5075     }
   5076 
   5077     exc->GS.gep0 = (FT_UShort)args[0];
   5078   }
   5079 
   5080 
   5081   /**************************************************************************
   5082    *
   5083    * SZP1[]:       Set Zone Pointer 1
   5084    * Opcode range: 0x14
   5085    * Stack:        uint32 -->
   5086    */
   5087   static void
   5088   Ins_SZP1( TT_ExecContext  exc,
   5089             FT_Long*        args )
   5090   {
   5091     switch ( (FT_Int)args[0] )
   5092     {
   5093     case 0:
   5094       exc->zp1 = exc->twilight;
   5095       break;
   5096 
   5097     case 1:
   5098       exc->zp1 = exc->pts;
   5099       break;
   5100 
   5101     default:
   5102       if ( exc->pedantic_hinting )
   5103         exc->error = FT_THROW( Invalid_Reference );
   5104       return;
   5105     }
   5106 
   5107     exc->GS.gep1 = (FT_UShort)args[0];
   5108   }
   5109 
   5110 
   5111   /**************************************************************************
   5112    *
   5113    * SZP2[]:       Set Zone Pointer 2
   5114    * Opcode range: 0x15
   5115    * Stack:        uint32 -->
   5116    */
   5117   static void
   5118   Ins_SZP2( TT_ExecContext  exc,
   5119             FT_Long*        args )
   5120   {
   5121     switch ( (FT_Int)args[0] )
   5122     {
   5123     case 0:
   5124       exc->zp2 = exc->twilight;
   5125       break;
   5126 
   5127     case 1:
   5128       exc->zp2 = exc->pts;
   5129       break;
   5130 
   5131     default:
   5132       if ( exc->pedantic_hinting )
   5133         exc->error = FT_THROW( Invalid_Reference );
   5134       return;
   5135     }
   5136 
   5137     exc->GS.gep2 = (FT_UShort)args[0];
   5138   }
   5139 
   5140 
   5141   /**************************************************************************
   5142    *
   5143    * SZPS[]:       Set Zone PointerS
   5144    * Opcode range: 0x16
   5145    * Stack:        uint32 -->
   5146    */
   5147   static void
   5148   Ins_SZPS( TT_ExecContext  exc,
   5149             FT_Long*        args )
   5150   {
   5151     switch ( (FT_Int)args[0] )
   5152     {
   5153     case 0:
   5154       exc->zp0 = exc->twilight;
   5155       break;
   5156 
   5157     case 1:
   5158       exc->zp0 = exc->pts;
   5159       break;
   5160 
   5161     default:
   5162       if ( exc->pedantic_hinting )
   5163         exc->error = FT_THROW( Invalid_Reference );
   5164       return;
   5165     }
   5166 
   5167     exc->zp1 = exc->zp0;
   5168     exc->zp2 = exc->zp0;
   5169 
   5170     exc->GS.gep0 = (FT_UShort)args[0];
   5171     exc->GS.gep1 = (FT_UShort)args[0];
   5172     exc->GS.gep2 = (FT_UShort)args[0];
   5173   }
   5174 
   5175 
   5176   /**************************************************************************
   5177    *
   5178    * INSTCTRL[]:   INSTruction ConTRoL
   5179    * Opcode range: 0x8E
   5180    * Stack:        int32 int32 -->
   5181    */
   5182   static void
   5183   Ins_INSTCTRL( TT_ExecContext  exc,
   5184                 FT_Long*        args )
   5185   {
   5186     FT_ULong  K, L, Kf;
   5187 
   5188 
   5189     K = (FT_ULong)args[1];
   5190     L = (FT_ULong)args[0];
   5191 
   5192     /* selector values cannot be `OR'ed;                 */
   5193     /* they are indices starting with index 1, not flags */
   5194     if ( K < 1 || K > 3 )
   5195     {
   5196       if ( exc->pedantic_hinting )
   5197         exc->error = FT_THROW( Invalid_Reference );
   5198       return;
   5199     }
   5200 
   5201     /* convert index to flag value */
   5202     Kf = 1 << ( K - 1 );
   5203 
   5204     if ( L != 0 )
   5205     {
   5206       /* arguments to selectors look like flag values */
   5207       if ( L != Kf )
   5208       {
   5209         if ( exc->pedantic_hinting )
   5210           exc->error = FT_THROW( Invalid_Reference );
   5211         return;
   5212       }
   5213     }
   5214 
   5215     exc->GS.instruct_control &= ~(FT_Byte)Kf;
   5216     exc->GS.instruct_control |= (FT_Byte)L;
   5217 
   5218     if ( K == 3 )
   5219     {
   5220 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5221       /* INSTCTRL modifying flag 3 also has an effect */
   5222       /* outside of the CVT program                   */
   5223       if ( SUBPIXEL_HINTING_INFINALITY )
   5224         exc->ignore_x_mode = FT_BOOL( L == 4 );
   5225 #endif
   5226 
   5227 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5228       /* Native ClearType fonts sign a waiver that turns off all backward  */
   5229       /* compatibility hacks and lets them program points to the grid like */
   5230       /* it's 1996.  They might sign a waiver for just one glyph, though.  */
   5231       if ( SUBPIXEL_HINTING_MINIMAL )
   5232         exc->backward_compatibility = !FT_BOOL( L == 4 );
   5233 #endif
   5234     }
   5235   }
   5236 
   5237 
   5238   /**************************************************************************
   5239    *
   5240    * SCANCTRL[]:   SCAN ConTRoL
   5241    * Opcode range: 0x85
   5242    * Stack:        uint32? -->
   5243    */
   5244   static void
   5245   Ins_SCANCTRL( TT_ExecContext  exc,
   5246                 FT_Long*        args )
   5247   {
   5248     FT_Int  A;
   5249 
   5250 
   5251     /* Get Threshold */
   5252     A = (FT_Int)( args[0] & 0xFF );
   5253 
   5254     if ( A == 0xFF )
   5255     {
   5256       exc->GS.scan_control = TRUE;
   5257       return;
   5258     }
   5259     else if ( A == 0 )
   5260     {
   5261       exc->GS.scan_control = FALSE;
   5262       return;
   5263     }
   5264 
   5265     if ( ( args[0] & 0x100 ) != 0 && exc->tt_metrics.ppem <= A )
   5266       exc->GS.scan_control = TRUE;
   5267 
   5268     if ( ( args[0] & 0x200 ) != 0 && exc->tt_metrics.rotated )
   5269       exc->GS.scan_control = TRUE;
   5270 
   5271     if ( ( args[0] & 0x400 ) != 0 && exc->tt_metrics.stretched )
   5272       exc->GS.scan_control = TRUE;
   5273 
   5274     if ( ( args[0] & 0x800 ) != 0 && exc->tt_metrics.ppem > A )
   5275       exc->GS.scan_control = FALSE;
   5276 
   5277     if ( ( args[0] & 0x1000 ) != 0 && exc->tt_metrics.rotated )
   5278       exc->GS.scan_control = FALSE;
   5279 
   5280     if ( ( args[0] & 0x2000 ) != 0 && exc->tt_metrics.stretched )
   5281       exc->GS.scan_control = FALSE;
   5282   }
   5283 
   5284 
   5285   /**************************************************************************
   5286    *
   5287    * SCANTYPE[]:   SCAN TYPE
   5288    * Opcode range: 0x8D
   5289    * Stack:        uint16 -->
   5290    */
   5291   static void
   5292   Ins_SCANTYPE( TT_ExecContext  exc,
   5293                 FT_Long*        args )
   5294   {
   5295     if ( args[0] >= 0 )
   5296       exc->GS.scan_type = (FT_Int)args[0] & 0xFFFF;
   5297   }
   5298 
   5299 
   5300   /**************************************************************************
   5301    *
   5302    * MANAGING OUTLINES
   5303    *
   5304    */
   5305 
   5306 
   5307   /**************************************************************************
   5308    *
   5309    * FLIPPT[]:     FLIP PoinT
   5310    * Opcode range: 0x80
   5311    * Stack:        uint32... -->
   5312    */
   5313   static void
   5314   Ins_FLIPPT( TT_ExecContext  exc )
   5315   {
   5316     FT_UShort  point;
   5317 
   5318 
   5319 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5320     /* See `ttinterp.h' for details on backward compatibility mode. */
   5321     if ( SUBPIXEL_HINTING_MINIMAL    &&
   5322          exc->backward_compatibility &&
   5323          exc->iupx_called            &&
   5324          exc->iupy_called            )
   5325       goto Fail;
   5326 #endif
   5327 
   5328     if ( exc->top < exc->GS.loop )
   5329     {
   5330       if ( exc->pedantic_hinting )
   5331         exc->error = FT_THROW( Too_Few_Arguments );
   5332       goto Fail;
   5333     }
   5334 
   5335     while ( exc->GS.loop > 0 )
   5336     {
   5337       exc->args--;
   5338 
   5339       point = (FT_UShort)exc->stack[exc->args];
   5340 
   5341       if ( BOUNDS( point, exc->pts.n_points ) )
   5342       {
   5343         if ( exc->pedantic_hinting )
   5344         {
   5345           exc->error = FT_THROW( Invalid_Reference );
   5346           return;
   5347         }
   5348       }
   5349       else
   5350         exc->pts.tags[point] ^= FT_CURVE_TAG_ON;
   5351 
   5352       exc->GS.loop--;
   5353     }
   5354 
   5355   Fail:
   5356     exc->GS.loop = 1;
   5357     exc->new_top = exc->args;
   5358   }
   5359 
   5360 
   5361   /**************************************************************************
   5362    *
   5363    * FLIPRGON[]:   FLIP RanGe ON
   5364    * Opcode range: 0x81
   5365    * Stack:        uint32 uint32 -->
   5366    */
   5367   static void
   5368   Ins_FLIPRGON( TT_ExecContext  exc,
   5369                 FT_Long*        args )
   5370   {
   5371     FT_UShort  I, K, L;
   5372 
   5373 
   5374 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5375     /* See `ttinterp.h' for details on backward compatibility mode. */
   5376     if ( SUBPIXEL_HINTING_MINIMAL    &&
   5377          exc->backward_compatibility &&
   5378          exc->iupx_called            &&
   5379          exc->iupy_called            )
   5380       return;
   5381 #endif
   5382 
   5383     K = (FT_UShort)args[1];
   5384     L = (FT_UShort)args[0];
   5385 
   5386     if ( BOUNDS( K, exc->pts.n_points ) ||
   5387          BOUNDS( L, exc->pts.n_points ) )
   5388     {
   5389       if ( exc->pedantic_hinting )
   5390         exc->error = FT_THROW( Invalid_Reference );
   5391       return;
   5392     }
   5393 
   5394     for ( I = L; I <= K; I++ )
   5395       exc->pts.tags[I] |= FT_CURVE_TAG_ON;
   5396   }
   5397 
   5398 
   5399   /**************************************************************************
   5400    *
   5401    * FLIPRGOFF:    FLIP RanGe OFF
   5402    * Opcode range: 0x82
   5403    * Stack:        uint32 uint32 -->
   5404    */
   5405   static void
   5406   Ins_FLIPRGOFF( TT_ExecContext  exc,
   5407                  FT_Long*        args )
   5408   {
   5409     FT_UShort  I, K, L;
   5410 
   5411 
   5412 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5413     /* See `ttinterp.h' for details on backward compatibility mode. */
   5414     if ( SUBPIXEL_HINTING_MINIMAL    &&
   5415          exc->backward_compatibility &&
   5416          exc->iupx_called            &&
   5417          exc->iupy_called            )
   5418       return;
   5419 #endif
   5420 
   5421     K = (FT_UShort)args[1];
   5422     L = (FT_UShort)args[0];
   5423 
   5424     if ( BOUNDS( K, exc->pts.n_points ) ||
   5425          BOUNDS( L, exc->pts.n_points ) )
   5426     {
   5427       if ( exc->pedantic_hinting )
   5428         exc->error = FT_THROW( Invalid_Reference );
   5429       return;
   5430     }
   5431 
   5432     for ( I = L; I <= K; I++ )
   5433       exc->pts.tags[I] &= ~FT_CURVE_TAG_ON;
   5434   }
   5435 
   5436 
   5437   static FT_Bool
   5438   Compute_Point_Displacement( TT_ExecContext  exc,
   5439                               FT_F26Dot6*     x,
   5440                               FT_F26Dot6*     y,
   5441                               TT_GlyphZone    zone,
   5442                               FT_UShort*      refp )
   5443   {
   5444     TT_GlyphZoneRec  zp;
   5445     FT_UShort        p;
   5446     FT_F26Dot6       d;
   5447 
   5448 
   5449     if ( exc->opcode & 1 )
   5450     {
   5451       zp = exc->zp0;
   5452       p  = exc->GS.rp1;
   5453     }
   5454     else
   5455     {
   5456       zp = exc->zp1;
   5457       p  = exc->GS.rp2;
   5458     }
   5459 
   5460     if ( BOUNDS( p, zp.n_points ) )
   5461     {
   5462       if ( exc->pedantic_hinting )
   5463         exc->error = FT_THROW( Invalid_Reference );
   5464       *refp = 0;
   5465       return FAILURE;
   5466     }
   5467 
   5468     *zone = zp;
   5469     *refp = p;
   5470 
   5471     d = PROJECT( zp.cur + p, zp.org + p );
   5472 
   5473     *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P );
   5474     *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P );
   5475 
   5476     return SUCCESS;
   5477   }
   5478 
   5479 
   5480   /* See `ttinterp.h' for details on backward compatibility mode. */
   5481   static void
   5482   Move_Zp2_Point( TT_ExecContext  exc,
   5483                   FT_UShort       point,
   5484                   FT_F26Dot6      dx,
   5485                   FT_F26Dot6      dy,
   5486                   FT_Bool         touch )
   5487   {
   5488     if ( exc->GS.freeVector.x != 0 )
   5489     {
   5490 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5491       if ( !( SUBPIXEL_HINTING_MINIMAL    &&
   5492               exc->backward_compatibility ) )
   5493 #endif
   5494         exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx );
   5495 
   5496       if ( touch )
   5497         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
   5498     }
   5499 
   5500     if ( exc->GS.freeVector.y != 0 )
   5501     {
   5502 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5503       if ( !( SUBPIXEL_HINTING_MINIMAL    &&
   5504               exc->backward_compatibility &&
   5505               exc->iupx_called            &&
   5506               exc->iupy_called            ) )
   5507 #endif
   5508         exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy );
   5509 
   5510       if ( touch )
   5511         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
   5512     }
   5513   }
   5514 
   5515 
   5516   /**************************************************************************
   5517    *
   5518    * SHP[a]:       SHift Point by the last point
   5519    * Opcode range: 0x32-0x33
   5520    * Stack:        uint32... -->
   5521    */
   5522   static void
   5523   Ins_SHP( TT_ExecContext  exc )
   5524   {
   5525     TT_GlyphZoneRec  zp;
   5526     FT_UShort        refp;
   5527 
   5528     FT_F26Dot6       dx, dy;
   5529     FT_UShort        point;
   5530 
   5531 
   5532     if ( exc->top < exc->GS.loop )
   5533     {
   5534       if ( exc->pedantic_hinting )
   5535         exc->error = FT_THROW( Invalid_Reference );
   5536       goto Fail;
   5537     }
   5538 
   5539     if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
   5540       return;
   5541 
   5542     while ( exc->GS.loop > 0 )
   5543     {
   5544       exc->args--;
   5545       point = (FT_UShort)exc->stack[exc->args];
   5546 
   5547       if ( BOUNDS( point, exc->zp2.n_points ) )
   5548       {
   5549         if ( exc->pedantic_hinting )
   5550         {
   5551           exc->error = FT_THROW( Invalid_Reference );
   5552           return;
   5553         }
   5554       }
   5555       else
   5556 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5557       /* doesn't follow Cleartype spec but produces better result */
   5558       if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode )
   5559         Move_Zp2_Point( exc, point, 0, dy, TRUE );
   5560       else
   5561 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   5562         Move_Zp2_Point( exc, point, dx, dy, TRUE );
   5563 
   5564       exc->GS.loop--;
   5565     }
   5566 
   5567   Fail:
   5568     exc->GS.loop = 1;
   5569     exc->new_top = exc->args;
   5570   }
   5571 
   5572 
   5573   /**************************************************************************
   5574    *
   5575    * SHC[a]:       SHift Contour
   5576    * Opcode range: 0x34-35
   5577    * Stack:        uint32 -->
   5578    *
   5579    * UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual)
   5580    *               contour in the twilight zone, namely contour number
   5581    *               zero which includes all points of it.
   5582    */
   5583   static void
   5584   Ins_SHC( TT_ExecContext  exc,
   5585            FT_Long*        args )
   5586   {
   5587     TT_GlyphZoneRec  zp;
   5588     FT_UShort        refp;
   5589     FT_F26Dot6       dx, dy;
   5590 
   5591     FT_Short         contour, bounds;
   5592     FT_UShort        start, limit, i;
   5593 
   5594 
   5595     contour = (FT_Short)args[0];
   5596     bounds  = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
   5597 
   5598     if ( BOUNDS( contour, bounds ) )
   5599     {
   5600       if ( exc->pedantic_hinting )
   5601         exc->error = FT_THROW( Invalid_Reference );
   5602       return;
   5603     }
   5604 
   5605     if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
   5606       return;
   5607 
   5608     if ( contour == 0 )
   5609       start = 0;
   5610     else
   5611       start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
   5612                            exc->zp2.first_point );
   5613 
   5614     /* we use the number of points if in the twilight zone */
   5615     if ( exc->GS.gep2 == 0 )
   5616       limit = exc->zp2.n_points;
   5617     else
   5618       limit = (FT_UShort)( exc->zp2.contours[contour] -
   5619                            exc->zp2.first_point + 1 );
   5620 
   5621     for ( i = start; i < limit; i++ )
   5622     {
   5623       if ( zp.cur != exc->zp2.cur || refp != i )
   5624         Move_Zp2_Point( exc, i, dx, dy, TRUE );
   5625     }
   5626   }
   5627 
   5628 
   5629   /**************************************************************************
   5630    *
   5631    * SHZ[a]:       SHift Zone
   5632    * Opcode range: 0x36-37
   5633    * Stack:        uint32 -->
   5634    */
   5635   static void
   5636   Ins_SHZ( TT_ExecContext  exc,
   5637            FT_Long*        args )
   5638   {
   5639     TT_GlyphZoneRec  zp;
   5640     FT_UShort        refp;
   5641     FT_F26Dot6       dx,
   5642                      dy;
   5643 
   5644     FT_UShort        limit, i;
   5645 
   5646 
   5647     if ( BOUNDS( args[0], 2 ) )
   5648     {
   5649       if ( exc->pedantic_hinting )
   5650         exc->error = FT_THROW( Invalid_Reference );
   5651       return;
   5652     }
   5653 
   5654     if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
   5655       return;
   5656 
   5657     /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points.     */
   5658     /*      Twilight zone has no real contours, so use `n_points'. */
   5659     /*      Normal zone's `n_points' includes phantoms, so must    */
   5660     /*      use end of last contour.                               */
   5661     if ( exc->GS.gep2 == 0 )
   5662       limit = (FT_UShort)exc->zp2.n_points;
   5663     else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
   5664       limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
   5665     else
   5666       limit = 0;
   5667 
   5668     /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
   5669     for ( i = 0; i < limit; i++ )
   5670     {
   5671       if ( zp.cur != exc->zp2.cur || refp != i )
   5672         Move_Zp2_Point( exc, i, dx, dy, FALSE );
   5673     }
   5674   }
   5675 
   5676 
   5677   /**************************************************************************
   5678    *
   5679    * SHPIX[]:      SHift points by a PIXel amount
   5680    * Opcode range: 0x38
   5681    * Stack:        f26.6 uint32... -->
   5682    */
   5683   static void
   5684   Ins_SHPIX( TT_ExecContext  exc,
   5685              FT_Long*        args )
   5686   {
   5687     FT_F26Dot6  dx, dy;
   5688     FT_UShort   point;
   5689 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5690     FT_Int      B1, B2;
   5691 #endif
   5692 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5693     FT_Bool     in_twilight = FT_BOOL( exc->GS.gep0 == 0 ||
   5694                                        exc->GS.gep1 == 0 ||
   5695                                        exc->GS.gep2 == 0 );
   5696 #endif
   5697 
   5698 
   5699 
   5700     if ( exc->top < exc->GS.loop + 1 )
   5701     {
   5702       if ( exc->pedantic_hinting )
   5703         exc->error = FT_THROW( Invalid_Reference );
   5704       goto Fail;
   5705     }
   5706 
   5707     dx = TT_MulFix14( args[0], exc->GS.freeVector.x );
   5708     dy = TT_MulFix14( args[0], exc->GS.freeVector.y );
   5709 
   5710     while ( exc->GS.loop > 0 )
   5711     {
   5712       exc->args--;
   5713 
   5714       point = (FT_UShort)exc->stack[exc->args];
   5715 
   5716       if ( BOUNDS( point, exc->zp2.n_points ) )
   5717       {
   5718         if ( exc->pedantic_hinting )
   5719         {
   5720           exc->error = FT_THROW( Invalid_Reference );
   5721           return;
   5722         }
   5723       }
   5724       else
   5725 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5726       if ( SUBPIXEL_HINTING_INFINALITY )
   5727       {
   5728         /*  If not using ignore_x_mode rendering, allow ZP2 move.        */
   5729         /*  If inline deltas aren't allowed, skip ZP2 move.              */
   5730         /*  If using ignore_x_mode rendering, allow ZP2 point move if:   */
   5731         /*   - freedom vector is y and sph_compatibility_mode is off     */
   5732         /*   - the glyph is composite and the move is in the Y direction */
   5733         /*   - the glyph is specifically set to allow SHPIX moves        */
   5734         /*   - the move is on a previously Y-touched point               */
   5735 
   5736         if ( exc->ignore_x_mode )
   5737         {
   5738           /* save point for later comparison */
   5739           if ( exc->GS.freeVector.y != 0 )
   5740             B1 = exc->zp2.cur[point].y;
   5741           else
   5742             B1 = exc->zp2.cur[point].x;
   5743 
   5744           if ( !exc->face->sph_compatibility_mode &&
   5745                exc->GS.freeVector.y != 0          )
   5746           {
   5747             Move_Zp2_Point( exc, point, dx, dy, TRUE );
   5748 
   5749             /* save new point */
   5750             if ( exc->GS.freeVector.y != 0 )
   5751             {
   5752               B2 = exc->zp2.cur[point].y;
   5753 
   5754               /* reverse any disallowed moves */
   5755               if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
   5756                    ( B1 & 63 ) != 0                                           &&
   5757                    ( B2 & 63 ) != 0                                           &&
   5758                    B1 != B2                                                   )
   5759                 Move_Zp2_Point( exc,
   5760                                 point,
   5761                                 NEG_LONG( dx ),
   5762                                 NEG_LONG( dy ),
   5763                                 TRUE );
   5764             }
   5765           }
   5766           else if ( exc->face->sph_compatibility_mode )
   5767           {
   5768             if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
   5769             {
   5770               dx = FT_PIX_ROUND( B1 + dx ) - B1;
   5771               dy = FT_PIX_ROUND( B1 + dy ) - B1;
   5772             }
   5773 
   5774             /* skip post-iup deltas */
   5775             if ( exc->iup_called                                          &&
   5776                  ( ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
   5777                    ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
   5778               goto Skip;
   5779 
   5780             if ( !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
   5781                   ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
   5782                     ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y )    ||
   5783                     ( exc->sph_tweak_flags & SPH_TWEAK_DO_SHPIX )      )  )
   5784               Move_Zp2_Point( exc, point, 0, dy, TRUE );
   5785 
   5786             /* save new point */
   5787             if ( exc->GS.freeVector.y != 0 )
   5788             {
   5789               B2 = exc->zp2.cur[point].y;
   5790 
   5791               /* reverse any disallowed moves */
   5792               if ( ( B1 & 63 ) == 0 &&
   5793                    ( B2 & 63 ) != 0 &&
   5794                    B1 != B2         )
   5795                 Move_Zp2_Point( exc, point, 0, NEG_LONG( dy ), TRUE );
   5796             }
   5797           }
   5798           else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
   5799             Move_Zp2_Point( exc, point, dx, dy, TRUE );
   5800         }
   5801         else
   5802           Move_Zp2_Point( exc, point, dx, dy, TRUE );
   5803       }
   5804       else
   5805 #endif
   5806 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   5807       if ( SUBPIXEL_HINTING_MINIMAL    &&
   5808            exc->backward_compatibility )
   5809       {
   5810         /* Special case: allow SHPIX to move points in the twilight zone.  */
   5811         /* Otherwise, treat SHPIX the same as DELTAP.  Unbreaks various    */
   5812         /* fonts such as older versions of Rokkitt and DTL Argo T Light    */
   5813         /* that would glitch severely after calling ALIGNRP after a        */
   5814         /* blocked SHPIX.                                                  */
   5815         if ( in_twilight                                                ||
   5816              ( !( exc->iupx_called && exc->iupy_called )              &&
   5817                ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
   5818                  ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y )    ) ) )
   5819           Move_Zp2_Point( exc, point, 0, dy, TRUE );
   5820       }
   5821       else
   5822 #endif
   5823         Move_Zp2_Point( exc, point, dx, dy, TRUE );
   5824 
   5825 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5826     Skip:
   5827 #endif
   5828       exc->GS.loop--;
   5829     }
   5830 
   5831   Fail:
   5832     exc->GS.loop = 1;
   5833     exc->new_top = exc->args;
   5834   }
   5835 
   5836 
   5837   /**************************************************************************
   5838    *
   5839    * MSIRP[a]:     Move Stack Indirect Relative Position
   5840    * Opcode range: 0x3A-0x3B
   5841    * Stack:        f26.6 uint32 -->
   5842    */
   5843   static void
   5844   Ins_MSIRP( TT_ExecContext  exc,
   5845              FT_Long*        args )
   5846   {
   5847     FT_UShort   point = 0;
   5848     FT_F26Dot6  distance;
   5849 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5850     FT_F26Dot6  control_value_cutin = 0;
   5851     FT_F26Dot6  delta;
   5852 
   5853 
   5854     if ( SUBPIXEL_HINTING_INFINALITY )
   5855     {
   5856       control_value_cutin = exc->GS.control_value_cutin;
   5857 
   5858       if ( exc->ignore_x_mode                                 &&
   5859            exc->GS.freeVector.x != 0                          &&
   5860            !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
   5861         control_value_cutin = 0;
   5862     }
   5863 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   5864 
   5865     point = (FT_UShort)args[0];
   5866 
   5867     if ( BOUNDS( point,       exc->zp1.n_points ) ||
   5868          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
   5869     {
   5870       if ( exc->pedantic_hinting )
   5871         exc->error = FT_THROW( Invalid_Reference );
   5872       return;
   5873     }
   5874 
   5875     /* UNDOCUMENTED!  The MS rasterizer does that with */
   5876     /* twilight points (confirmed by Greg Hitchcock)   */
   5877     if ( exc->GS.gep1 == 0 )
   5878     {
   5879       exc->zp1.org[point] = exc->zp0.org[exc->GS.rp0];
   5880       exc->func_move_orig( exc, &exc->zp1, point, args[1] );
   5881       exc->zp1.cur[point] = exc->zp1.org[point];
   5882     }
   5883 
   5884     distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
   5885 
   5886 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5887     delta = SUB_LONG( distance, args[1] );
   5888     if ( delta < 0 )
   5889       delta = NEG_LONG( delta );
   5890 
   5891     /* subpixel hinting - make MSIRP respect CVT cut-in; */
   5892     if ( SUBPIXEL_HINTING_INFINALITY  &&
   5893          exc->ignore_x_mode           &&
   5894          exc->GS.freeVector.x != 0    &&
   5895          delta >= control_value_cutin )
   5896       distance = args[1];
   5897 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   5898 
   5899     exc->func_move( exc,
   5900                     &exc->zp1,
   5901                     point,
   5902                     SUB_LONG( args[1], distance ) );
   5903 
   5904     exc->GS.rp1 = exc->GS.rp0;
   5905     exc->GS.rp2 = point;
   5906 
   5907     if ( ( exc->opcode & 1 ) != 0 )
   5908       exc->GS.rp0 = point;
   5909   }
   5910 
   5911 
   5912   /**************************************************************************
   5913    *
   5914    * MDAP[a]:      Move Direct Absolute Point
   5915    * Opcode range: 0x2E-0x2F
   5916    * Stack:        uint32 -->
   5917    */
   5918   static void
   5919   Ins_MDAP( TT_ExecContext  exc,
   5920             FT_Long*        args )
   5921   {
   5922     FT_UShort   point;
   5923     FT_F26Dot6  cur_dist;
   5924     FT_F26Dot6  distance;
   5925 
   5926 
   5927     point = (FT_UShort)args[0];
   5928 
   5929     if ( BOUNDS( point, exc->zp0.n_points ) )
   5930     {
   5931       if ( exc->pedantic_hinting )
   5932         exc->error = FT_THROW( Invalid_Reference );
   5933       return;
   5934     }
   5935 
   5936     if ( ( exc->opcode & 1 ) != 0 )
   5937     {
   5938       cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
   5939 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5940       if ( SUBPIXEL_HINTING_INFINALITY &&
   5941            exc->ignore_x_mode          &&
   5942            exc->GS.freeVector.x != 0   )
   5943         distance = SUB_LONG(
   5944                      Round_None( exc,
   5945                                  cur_dist,
   5946                                  exc->tt_metrics.compensations[0] ),
   5947                      cur_dist );
   5948       else
   5949 #endif
   5950         distance = SUB_LONG(
   5951                      exc->func_round( exc,
   5952                                       cur_dist,
   5953                                       exc->tt_metrics.compensations[0] ),
   5954                      cur_dist );
   5955     }
   5956     else
   5957       distance = 0;
   5958 
   5959     exc->func_move( exc, &exc->zp0, point, distance );
   5960 
   5961     exc->GS.rp0 = point;
   5962     exc->GS.rp1 = point;
   5963   }
   5964 
   5965 
   5966   /**************************************************************************
   5967    *
   5968    * MIAP[a]:      Move Indirect Absolute Point
   5969    * Opcode range: 0x3E-0x3F
   5970    * Stack:        uint32 uint32 -->
   5971    */
   5972   static void
   5973   Ins_MIAP( TT_ExecContext  exc,
   5974             FT_Long*        args )
   5975   {
   5976     FT_ULong    cvtEntry;
   5977     FT_UShort   point;
   5978     FT_F26Dot6  distance;
   5979     FT_F26Dot6  org_dist;
   5980     FT_F26Dot6  control_value_cutin;
   5981 
   5982 
   5983     control_value_cutin = exc->GS.control_value_cutin;
   5984     cvtEntry            = (FT_ULong)args[1];
   5985     point               = (FT_UShort)args[0];
   5986 
   5987 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   5988     if ( SUBPIXEL_HINTING_INFINALITY                        &&
   5989          exc->ignore_x_mode                                 &&
   5990          exc->GS.freeVector.x != 0                          &&
   5991          exc->GS.freeVector.y == 0                          &&
   5992          !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
   5993       control_value_cutin = 0;
   5994 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   5995 
   5996     if ( BOUNDS( point,     exc->zp0.n_points ) ||
   5997          BOUNDSL( cvtEntry, exc->cvtSize )      )
   5998     {
   5999       if ( exc->pedantic_hinting )
   6000         exc->error = FT_THROW( Invalid_Reference );
   6001       goto Fail;
   6002     }
   6003 
   6004     /* UNDOCUMENTED!                                                      */
   6005     /*                                                                    */
   6006     /* The behaviour of an MIAP instruction is quite different when used  */
   6007     /* in the twilight zone.                                              */
   6008     /*                                                                    */
   6009     /* First, no control value cut-in test is performed as it would fail  */
   6010     /* anyway.  Second, the original point, i.e. (org_x,org_y) of         */
   6011     /* zp0.point, is set to the absolute, unrounded distance found in the */
   6012     /* CVT.                                                               */
   6013     /*                                                                    */
   6014     /* This is used in the CVT programs of the Microsoft fonts Arial,     */
   6015     /* Times, etc., in order to re-adjust some key font heights.  It      */
   6016     /* allows the use of the IP instruction in the twilight zone, which   */
   6017     /* otherwise would be invalid according to the specification.         */
   6018     /*                                                                    */
   6019     /* We implement it with a special sequence for the twilight zone.     */
   6020     /* This is a bad hack, but it seems to work.                          */
   6021     /*                                                                    */
   6022     /* Confirmed by Greg Hitchcock.                                       */
   6023 
   6024     distance = exc->func_read_cvt( exc, cvtEntry );
   6025 
   6026     if ( exc->GS.gep0 == 0 )   /* If in twilight zone */
   6027     {
   6028 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6029       /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
   6030       /* Determined via experimentation and may be incorrect...         */
   6031       if ( !( SUBPIXEL_HINTING_INFINALITY           &&
   6032               ( exc->ignore_x_mode                &&
   6033                 exc->face->sph_compatibility_mode ) ) )
   6034 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6035         exc->zp0.org[point].x = TT_MulFix14( distance,
   6036                                              exc->GS.freeVector.x );
   6037       exc->zp0.org[point].y = TT_MulFix14( distance,
   6038                                            exc->GS.freeVector.y ),
   6039       exc->zp0.cur[point]   = exc->zp0.org[point];
   6040     }
   6041 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6042     if ( SUBPIXEL_HINTING_INFINALITY                    &&
   6043          exc->ignore_x_mode                             &&
   6044          ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
   6045          distance > 0                                   &&
   6046          exc->GS.freeVector.y != 0                      )
   6047       distance = 0;
   6048 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6049 
   6050     org_dist = FAST_PROJECT( &exc->zp0.cur[point] );
   6051 
   6052     if ( ( exc->opcode & 1 ) != 0 )   /* rounding and control cut-in flag */
   6053     {
   6054       FT_F26Dot6  delta;
   6055 
   6056 
   6057       delta = SUB_LONG( distance, org_dist );
   6058       if ( delta < 0 )
   6059         delta = NEG_LONG( delta );
   6060 
   6061       if ( delta > control_value_cutin )
   6062         distance = org_dist;
   6063 
   6064 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6065       if ( SUBPIXEL_HINTING_INFINALITY &&
   6066            exc->ignore_x_mode          &&
   6067            exc->GS.freeVector.x != 0   )
   6068         distance = Round_None( exc,
   6069                                distance,
   6070                                exc->tt_metrics.compensations[0] );
   6071       else
   6072 #endif
   6073         distance = exc->func_round( exc,
   6074                                     distance,
   6075                                     exc->tt_metrics.compensations[0] );
   6076     }
   6077 
   6078     exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) );
   6079 
   6080   Fail:
   6081     exc->GS.rp0 = point;
   6082     exc->GS.rp1 = point;
   6083   }
   6084 
   6085 
   6086   /**************************************************************************
   6087    *
   6088    * MDRP[abcde]:  Move Direct Relative Point
   6089    * Opcode range: 0xC0-0xDF
   6090    * Stack:        uint32 -->
   6091    */
   6092   static void
   6093   Ins_MDRP( TT_ExecContext  exc,
   6094             FT_Long*        args )
   6095   {
   6096     FT_UShort   point = 0;
   6097     FT_F26Dot6  org_dist, distance, minimum_distance;
   6098 
   6099 
   6100     minimum_distance = exc->GS.minimum_distance;
   6101 
   6102 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6103     if ( SUBPIXEL_HINTING_INFINALITY                        &&
   6104          exc->ignore_x_mode                                 &&
   6105          exc->GS.freeVector.x != 0                          &&
   6106          !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
   6107       minimum_distance = 0;
   6108 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6109 
   6110     point = (FT_UShort)args[0];
   6111 
   6112     if ( BOUNDS( point,       exc->zp1.n_points ) ||
   6113          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
   6114     {
   6115       if ( exc->pedantic_hinting )
   6116         exc->error = FT_THROW( Invalid_Reference );
   6117       goto Fail;
   6118     }
   6119 
   6120     /* XXX: Is there some undocumented feature while in the */
   6121     /*      twilight zone?                                  */
   6122 
   6123     /* XXX: UNDOCUMENTED: twilight zone special case */
   6124 
   6125     if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
   6126     {
   6127       FT_Vector*  vec1 = &exc->zp1.org[point];
   6128       FT_Vector*  vec2 = &exc->zp0.org[exc->GS.rp0];
   6129 
   6130 
   6131       org_dist = DUALPROJ( vec1, vec2 );
   6132     }
   6133     else
   6134     {
   6135       FT_Vector*  vec1 = &exc->zp1.orus[point];
   6136       FT_Vector*  vec2 = &exc->zp0.orus[exc->GS.rp0];
   6137 
   6138 
   6139       if ( exc->metrics.x_scale == exc->metrics.y_scale )
   6140       {
   6141         /* this should be faster */
   6142         org_dist = DUALPROJ( vec1, vec2 );
   6143         org_dist = FT_MulFix( org_dist, exc->metrics.x_scale );
   6144       }
   6145       else
   6146       {
   6147         FT_Vector  vec;
   6148 
   6149 
   6150         vec.x = FT_MulFix( SUB_LONG( vec1->x, vec2->x ),
   6151                            exc->metrics.x_scale );
   6152         vec.y = FT_MulFix( SUB_LONG( vec1->y, vec2->y ),
   6153                            exc->metrics.y_scale );
   6154 
   6155         org_dist = FAST_DUALPROJ( &vec );
   6156       }
   6157     }
   6158 
   6159     /* single width cut-in test */
   6160 
   6161     /* |org_dist - single_width_value| < single_width_cutin */
   6162     if ( exc->GS.single_width_cutin > 0          &&
   6163          org_dist < exc->GS.single_width_value +
   6164                       exc->GS.single_width_cutin &&
   6165          org_dist > exc->GS.single_width_value -
   6166                       exc->GS.single_width_cutin )
   6167     {
   6168       if ( org_dist >= 0 )
   6169         org_dist = exc->GS.single_width_value;
   6170       else
   6171         org_dist = -exc->GS.single_width_value;
   6172     }
   6173 
   6174     /* round flag */
   6175 
   6176     if ( ( exc->opcode & 4 ) != 0 )
   6177     {
   6178 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6179       if ( SUBPIXEL_HINTING_INFINALITY &&
   6180            exc->ignore_x_mode          &&
   6181            exc->GS.freeVector.x != 0   )
   6182         distance = Round_None(
   6183                      exc,
   6184                      org_dist,
   6185                      exc->tt_metrics.compensations[exc->opcode & 3] );
   6186       else
   6187 #endif
   6188         distance = exc->func_round(
   6189                      exc,
   6190                      org_dist,
   6191                      exc->tt_metrics.compensations[exc->opcode & 3] );
   6192     }
   6193     else
   6194       distance = Round_None(
   6195                    exc,
   6196                    org_dist,
   6197                    exc->tt_metrics.compensations[exc->opcode & 3] );
   6198 
   6199     /* minimum distance flag */
   6200 
   6201     if ( ( exc->opcode & 8 ) != 0 )
   6202     {
   6203       if ( org_dist >= 0 )
   6204       {
   6205         if ( distance < minimum_distance )
   6206           distance = minimum_distance;
   6207       }
   6208       else
   6209       {
   6210         if ( distance > NEG_LONG( minimum_distance ) )
   6211           distance = NEG_LONG( minimum_distance );
   6212       }
   6213     }
   6214 
   6215     /* now move the point */
   6216 
   6217     org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
   6218 
   6219     exc->func_move( exc, &exc->zp1, point, SUB_LONG( distance, org_dist ) );
   6220 
   6221   Fail:
   6222     exc->GS.rp1 = exc->GS.rp0;
   6223     exc->GS.rp2 = point;
   6224 
   6225     if ( ( exc->opcode & 16 ) != 0 )
   6226       exc->GS.rp0 = point;
   6227   }
   6228 
   6229 
   6230   /**************************************************************************
   6231    *
   6232    * MIRP[abcde]:  Move Indirect Relative Point
   6233    * Opcode range: 0xE0-0xFF
   6234    * Stack:        int32? uint32 -->
   6235    */
   6236   static void
   6237   Ins_MIRP( TT_ExecContext  exc,
   6238             FT_Long*        args )
   6239   {
   6240     FT_UShort   point;
   6241     FT_ULong    cvtEntry;
   6242 
   6243     FT_F26Dot6  cvt_dist,
   6244                 distance,
   6245                 cur_dist,
   6246                 org_dist,
   6247                 control_value_cutin,
   6248                 minimum_distance;
   6249 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6250     FT_Int      B1           = 0; /* pacify compiler */
   6251     FT_Int      B2           = 0;
   6252     FT_Bool     reverse_move = FALSE;
   6253 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6254 
   6255     FT_F26Dot6  delta;
   6256 
   6257 
   6258     minimum_distance    = exc->GS.minimum_distance;
   6259     control_value_cutin = exc->GS.control_value_cutin;
   6260     point               = (FT_UShort)args[0];
   6261     cvtEntry            = (FT_ULong)( ADD_LONG( args[1], 1 ) );
   6262 
   6263 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6264     if ( SUBPIXEL_HINTING_INFINALITY                        &&
   6265          exc->ignore_x_mode                                 &&
   6266          exc->GS.freeVector.x != 0                          &&
   6267          !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
   6268       control_value_cutin = minimum_distance = 0;
   6269 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6270 
   6271     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
   6272 
   6273     if ( BOUNDS( point,       exc->zp1.n_points ) ||
   6274          BOUNDSL( cvtEntry,   exc->cvtSize + 1 )  ||
   6275          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
   6276     {
   6277       if ( exc->pedantic_hinting )
   6278         exc->error = FT_THROW( Invalid_Reference );
   6279       goto Fail;
   6280     }
   6281 
   6282     if ( !cvtEntry )
   6283       cvt_dist = 0;
   6284     else
   6285       cvt_dist = exc->func_read_cvt( exc, cvtEntry - 1 );
   6286 
   6287     /* single width test */
   6288 
   6289     delta = SUB_LONG( cvt_dist, exc->GS.single_width_value );
   6290     if ( delta < 0 )
   6291       delta = NEG_LONG( delta );
   6292 
   6293     if ( delta < exc->GS.single_width_cutin )
   6294     {
   6295       if ( cvt_dist >= 0 )
   6296         cvt_dist =  exc->GS.single_width_value;
   6297       else
   6298         cvt_dist = -exc->GS.single_width_value;
   6299     }
   6300 
   6301     /* UNDOCUMENTED!  The MS rasterizer does that with */
   6302     /* twilight points (confirmed by Greg Hitchcock)   */
   6303     if ( exc->GS.gep1 == 0 )
   6304     {
   6305       exc->zp1.org[point].x = exc->zp0.org[exc->GS.rp0].x +
   6306                               TT_MulFix14( cvt_dist,
   6307                                            exc->GS.freeVector.x );
   6308       exc->zp1.org[point].y = exc->zp0.org[exc->GS.rp0].y +
   6309                               TT_MulFix14( cvt_dist,
   6310                                            exc->GS.freeVector.y );
   6311       exc->zp1.cur[point]   = exc->zp1.org[point];
   6312     }
   6313 
   6314     org_dist = DUALPROJ( &exc->zp1.org[point], &exc->zp0.org[exc->GS.rp0] );
   6315     cur_dist = PROJECT ( &exc->zp1.cur[point], &exc->zp0.cur[exc->GS.rp0] );
   6316 
   6317     /* auto-flip test */
   6318 
   6319     if ( exc->GS.auto_flip )
   6320     {
   6321       if ( ( org_dist ^ cvt_dist ) < 0 )
   6322         cvt_dist = -cvt_dist;
   6323     }
   6324 
   6325 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6326     if ( SUBPIXEL_HINTING_INFINALITY                               &&
   6327          exc->ignore_x_mode                                        &&
   6328          exc->GS.freeVector.y != 0                                 &&
   6329          ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
   6330     {
   6331       if ( cur_dist < -64 )
   6332         cvt_dist -= 16;
   6333       else if ( cur_dist > 64 && cur_dist < 84 )
   6334         cvt_dist += 32;
   6335     }
   6336 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6337 
   6338     /* control value cut-in and round */
   6339 
   6340     if ( ( exc->opcode & 4 ) != 0 )
   6341     {
   6342       /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
   6343       /*      refer to the same zone.                                  */
   6344 
   6345       if ( exc->GS.gep0 == exc->GS.gep1 )
   6346       {
   6347         /* XXX: According to Greg Hitchcock, the following wording is */
   6348         /*      the right one:                                        */
   6349         /*                                                            */
   6350         /*        When the absolute difference between the value in   */
   6351         /*        the table [CVT] and the measurement directly from   */
   6352         /*        the outline is _greater_ than the cut_in value, the */
   6353         /*        outline measurement is used.                        */
   6354         /*                                                            */
   6355         /*      This is from `instgly.doc'.  The description in       */
   6356         /*      `ttinst2.doc', version 1.66, is thus incorrect since  */
   6357         /*      it implies `>=' instead of `>'.                       */
   6358 
   6359         delta = SUB_LONG( cvt_dist, org_dist );
   6360         if ( delta < 0 )
   6361           delta = NEG_LONG( delta );
   6362 
   6363         if ( delta > control_value_cutin )
   6364           cvt_dist = org_dist;
   6365       }
   6366 
   6367       distance = exc->func_round(
   6368                    exc,
   6369                    cvt_dist,
   6370                    exc->tt_metrics.compensations[exc->opcode & 3] );
   6371     }
   6372     else
   6373     {
   6374 
   6375 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6376       /* do cvt cut-in always in MIRP for sph */
   6377       if ( SUBPIXEL_HINTING_INFINALITY  &&
   6378            exc->ignore_x_mode           &&
   6379            exc->GS.gep0 == exc->GS.gep1 )
   6380       {
   6381         delta = SUB_LONG( cvt_dist, org_dist );
   6382         if ( delta < 0 )
   6383           delta = NEG_LONG( delta );
   6384 
   6385         if ( delta > control_value_cutin )
   6386           cvt_dist = org_dist;
   6387       }
   6388 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6389 
   6390       distance = Round_None(
   6391                    exc,
   6392                    cvt_dist,
   6393                    exc->tt_metrics.compensations[exc->opcode & 3] );
   6394     }
   6395 
   6396     /* minimum distance test */
   6397 
   6398     if ( ( exc->opcode & 8 ) != 0 )
   6399     {
   6400       if ( org_dist >= 0 )
   6401       {
   6402         if ( distance < minimum_distance )
   6403           distance = minimum_distance;
   6404       }
   6405       else
   6406       {
   6407         if ( distance > NEG_LONG( minimum_distance ) )
   6408           distance = NEG_LONG( minimum_distance );
   6409       }
   6410     }
   6411 
   6412 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6413     if ( SUBPIXEL_HINTING_INFINALITY )
   6414     {
   6415       B1 = exc->zp1.cur[point].y;
   6416 
   6417       /* Round moves if necessary */
   6418       if ( exc->ignore_x_mode                                          &&
   6419            exc->GS.freeVector.y != 0                                   &&
   6420            ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
   6421         distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
   6422 
   6423       if ( exc->ignore_x_mode                                      &&
   6424            exc->GS.freeVector.y != 0                               &&
   6425            ( exc->opcode & 16 ) == 0                               &&
   6426            ( exc->opcode & 8 ) == 0                                &&
   6427            ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
   6428         distance += 64;
   6429     }
   6430 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6431 
   6432     exc->func_move( exc,
   6433                     &exc->zp1,
   6434                     point,
   6435                     SUB_LONG( distance, cur_dist ) );
   6436 
   6437 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6438     if ( SUBPIXEL_HINTING_INFINALITY )
   6439     {
   6440       B2 = exc->zp1.cur[point].y;
   6441 
   6442       /* Reverse move if necessary */
   6443       if ( exc->ignore_x_mode )
   6444       {
   6445         if ( exc->face->sph_compatibility_mode &&
   6446              exc->GS.freeVector.y != 0         &&
   6447              ( B1 & 63 ) == 0                  &&
   6448              ( B2 & 63 ) != 0                  )
   6449           reverse_move = TRUE;
   6450 
   6451         if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
   6452              exc->GS.freeVector.y != 0                                  &&
   6453              ( B2 & 63 ) != 0                                           &&
   6454              ( B1 & 63 ) != 0                                           )
   6455           reverse_move = TRUE;
   6456       }
   6457 
   6458       if ( reverse_move )
   6459         exc->func_move( exc,
   6460                         &exc->zp1,
   6461                         point,
   6462                         SUB_LONG( cur_dist, distance ) );
   6463     }
   6464 
   6465 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6466 
   6467   Fail:
   6468     exc->GS.rp1 = exc->GS.rp0;
   6469 
   6470     if ( ( exc->opcode & 16 ) != 0 )
   6471       exc->GS.rp0 = point;
   6472 
   6473     exc->GS.rp2 = point;
   6474   }
   6475 
   6476 
   6477   /**************************************************************************
   6478    *
   6479    * ALIGNRP[]:    ALIGN Relative Point
   6480    * Opcode range: 0x3C
   6481    * Stack:        uint32 uint32... -->
   6482    */
   6483   static void
   6484   Ins_ALIGNRP( TT_ExecContext  exc )
   6485   {
   6486     FT_UShort   point;
   6487     FT_F26Dot6  distance;
   6488 
   6489 
   6490 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   6491     if ( SUBPIXEL_HINTING_INFINALITY                               &&
   6492          exc->ignore_x_mode                                        &&
   6493          exc->iup_called                                           &&
   6494          ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
   6495     {
   6496       exc->error = FT_THROW( Invalid_Reference );
   6497       goto Fail;
   6498     }
   6499 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   6500 
   6501     if ( exc->top < exc->GS.loop                  ||
   6502          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
   6503     {
   6504       if ( exc->pedantic_hinting )
   6505         exc->error = FT_THROW( Invalid_Reference );
   6506       goto Fail;
   6507     }
   6508 
   6509     while ( exc->GS.loop > 0 )
   6510     {
   6511       exc->args--;
   6512 
   6513       point = (FT_UShort)exc->stack[exc->args];
   6514 
   6515       if ( BOUNDS( point, exc->zp1.n_points ) )
   6516       {
   6517         if ( exc->pedantic_hinting )
   6518         {
   6519           exc->error = FT_THROW( Invalid_Reference );
   6520           return;
   6521         }
   6522       }
   6523       else
   6524       {
   6525         distance = PROJECT( exc->zp1.cur + point,
   6526                             exc->zp0.cur + exc->GS.rp0 );
   6527 
   6528         exc->func_move( exc, &exc->zp1, point, NEG_LONG( distance ) );
   6529       }
   6530 
   6531       exc->GS.loop--;
   6532     }
   6533 
   6534   Fail:
   6535     exc->GS.loop = 1;
   6536     exc->new_top = exc->args;
   6537   }
   6538 
   6539 
   6540   /**************************************************************************
   6541    *
   6542    * ISECT[]:      moves point to InterSECTion
   6543    * Opcode range: 0x0F
   6544    * Stack:        5 * uint32 -->
   6545    */
   6546   static void
   6547   Ins_ISECT( TT_ExecContext  exc,
   6548              FT_Long*        args )
   6549   {
   6550     FT_UShort   point,
   6551                 a0, a1,
   6552                 b0, b1;
   6553 
   6554     FT_F26Dot6  discriminant, dotproduct;
   6555 
   6556     FT_F26Dot6  dx,  dy,
   6557                 dax, day,
   6558                 dbx, dby;
   6559 
   6560     FT_F26Dot6  val;
   6561 
   6562     FT_Vector   R;
   6563 
   6564 
   6565     point = (FT_UShort)args[0];
   6566 
   6567     a0 = (FT_UShort)args[1];
   6568     a1 = (FT_UShort)args[2];
   6569     b0 = (FT_UShort)args[3];
   6570     b1 = (FT_UShort)args[4];
   6571 
   6572     if ( BOUNDS( b0,    exc->zp0.n_points ) ||
   6573          BOUNDS( b1,    exc->zp0.n_points ) ||
   6574          BOUNDS( a0,    exc->zp1.n_points ) ||
   6575          BOUNDS( a1,    exc->zp1.n_points ) ||
   6576          BOUNDS( point, exc->zp2.n_points ) )
   6577     {
   6578       if ( exc->pedantic_hinting )
   6579         exc->error = FT_THROW( Invalid_Reference );
   6580       return;
   6581     }
   6582 
   6583     /* Cramer's rule */
   6584 
   6585     dbx = SUB_LONG( exc->zp0.cur[b1].x, exc->zp0.cur[b0].x );
   6586     dby = SUB_LONG( exc->zp0.cur[b1].y, exc->zp0.cur[b0].y );
   6587 
   6588     dax = SUB_LONG( exc->zp1.cur[a1].x, exc->zp1.cur[a0].x );
   6589     day = SUB_LONG( exc->zp1.cur[a1].y, exc->zp1.cur[a0].y );
   6590 
   6591     dx = SUB_LONG( exc->zp0.cur[b0].x, exc->zp1.cur[a0].x );
   6592     dy = SUB_LONG( exc->zp0.cur[b0].y, exc->zp1.cur[a0].y );
   6593 
   6594     discriminant = ADD_LONG( FT_MulDiv( dax, NEG_LONG( dby ), 0x40 ),
   6595                              FT_MulDiv( day, dbx, 0x40 ) );
   6596     dotproduct   = ADD_LONG( FT_MulDiv( dax, dbx, 0x40 ),
   6597                              FT_MulDiv( day, dby, 0x40 ) );
   6598 
   6599     /* The discriminant above is actually a cross product of vectors     */
   6600     /* da and db. Together with the dot product, they can be used as     */
   6601     /* surrogates for sine and cosine of the angle between the vectors.  */
   6602     /* Indeed,                                                           */
   6603     /*       dotproduct   = |da||db|cos(angle)                           */
   6604     /*       discriminant = |da||db|sin(angle)     .                     */
   6605     /* We use these equations to reject grazing intersections by         */
   6606     /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
   6607     if ( MUL_LONG( 19, FT_ABS( discriminant ) ) > FT_ABS( dotproduct ) )
   6608     {
   6609       val = ADD_LONG( FT_MulDiv( dx, NEG_LONG( dby ), 0x40 ),
   6610                       FT_MulDiv( dy, dbx, 0x40 ) );
   6611 
   6612       R.x = FT_MulDiv( val, dax, discriminant );
   6613       R.y = FT_MulDiv( val, day, discriminant );
   6614 
   6615       /* XXX: Block in backward_compatibility and/or post-IUP? */
   6616       exc->zp2.cur[point].x = ADD_LONG( exc->zp1.cur[a0].x, R.x );
   6617       exc->zp2.cur[point].y = ADD_LONG( exc->zp1.cur[a0].y, R.y );
   6618     }
   6619     else
   6620     {
   6621       /* else, take the middle of the middles of A and B */
   6622 
   6623       /* XXX: Block in backward_compatibility and/or post-IUP? */
   6624       exc->zp2.cur[point].x =
   6625         ADD_LONG( ADD_LONG( exc->zp1.cur[a0].x, exc->zp1.cur[a1].x ),
   6626                   ADD_LONG( exc->zp0.cur[b0].x, exc->zp0.cur[b1].x ) ) / 4;
   6627       exc->zp2.cur[point].y =
   6628         ADD_LONG( ADD_LONG( exc->zp1.cur[a0].y, exc->zp1.cur[a1].y ),
   6629                   ADD_LONG( exc->zp0.cur[b0].y, exc->zp0.cur[b1].y ) ) / 4;
   6630     }
   6631 
   6632     exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
   6633   }
   6634 
   6635 
   6636   /**************************************************************************
   6637    *
   6638    * ALIGNPTS[]:   ALIGN PoinTS
   6639    * Opcode range: 0x27
   6640    * Stack:        uint32 uint32 -->
   6641    */
   6642   static void
   6643   Ins_ALIGNPTS( TT_ExecContext  exc,
   6644                 FT_Long*        args )
   6645   {
   6646     FT_UShort   p1, p2;
   6647     FT_F26Dot6  distance;
   6648 
   6649 
   6650     p1 = (FT_UShort)args[0];
   6651     p2 = (FT_UShort)args[1];
   6652 
   6653     if ( BOUNDS( p1, exc->zp1.n_points ) ||
   6654          BOUNDS( p2, exc->zp0.n_points ) )
   6655     {
   6656       if ( exc->pedantic_hinting )
   6657         exc->error = FT_THROW( Invalid_Reference );
   6658       return;
   6659     }
   6660 
   6661     distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2;
   6662 
   6663     exc->func_move( exc, &exc->zp1, p1, distance );
   6664     exc->func_move( exc, &exc->zp0, p2, NEG_LONG( distance ) );
   6665   }
   6666 
   6667 
   6668   /**************************************************************************
   6669    *
   6670    * IP[]:         Interpolate Point
   6671    * Opcode range: 0x39
   6672    * Stack:        uint32... -->
   6673    */
   6674 
   6675   /* SOMETIMES, DUMBER CODE IS BETTER CODE */
   6676 
   6677   static void
   6678   Ins_IP( TT_ExecContext  exc )
   6679   {
   6680     FT_F26Dot6  old_range, cur_range;
   6681     FT_Vector*  orus_base;
   6682     FT_Vector*  cur_base;
   6683     FT_Int      twilight;
   6684 
   6685 
   6686     if ( exc->top < exc->GS.loop )
   6687     {
   6688       if ( exc->pedantic_hinting )
   6689         exc->error = FT_THROW( Invalid_Reference );
   6690       goto Fail;
   6691     }
   6692 
   6693     /*
   6694      * We need to deal in a special way with the twilight zone.
   6695      * Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0),
   6696      * for every n.
   6697      */
   6698     twilight = ( exc->GS.gep0 == 0 ||
   6699                  exc->GS.gep1 == 0 ||
   6700                  exc->GS.gep2 == 0 );
   6701 
   6702     if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
   6703     {
   6704       if ( exc->pedantic_hinting )
   6705         exc->error = FT_THROW( Invalid_Reference );
   6706       goto Fail;
   6707     }
   6708 
   6709     if ( twilight )
   6710       orus_base = &exc->zp0.org[exc->GS.rp1];
   6711     else
   6712       orus_base = &exc->zp0.orus[exc->GS.rp1];
   6713 
   6714     cur_base = &exc->zp0.cur[exc->GS.rp1];
   6715 
   6716     /* XXX: There are some glyphs in some braindead but popular */
   6717     /*      fonts out there (e.g. [aeu]grave in monotype.ttf)   */
   6718     /*      calling IP[] with bad values of rp[12].             */
   6719     /*      Do something sane when this odd thing happens.      */
   6720     if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ||
   6721          BOUNDS( exc->GS.rp2, exc->zp1.n_points ) )
   6722     {
   6723       old_range = 0;
   6724       cur_range = 0;
   6725     }
   6726     else
   6727     {
   6728       if ( twilight )
   6729         old_range = DUALPROJ( &exc->zp1.org[exc->GS.rp2], orus_base );
   6730       else if ( exc->metrics.x_scale == exc->metrics.y_scale )
   6731         old_range = DUALPROJ( &exc->zp1.orus[exc->GS.rp2], orus_base );
   6732       else
   6733       {
   6734         FT_Vector  vec;
   6735 
   6736 
   6737         vec.x = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].x,
   6738                                      orus_base->x ),
   6739                            exc->metrics.x_scale );
   6740         vec.y = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].y,
   6741                                      orus_base->y ),
   6742                            exc->metrics.y_scale );
   6743 
   6744         old_range = FAST_DUALPROJ( &vec );
   6745       }
   6746 
   6747       cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base );
   6748     }
   6749 
   6750     for ( ; exc->GS.loop > 0; exc->GS.loop-- )
   6751     {
   6752       FT_UInt     point = (FT_UInt)exc->stack[--exc->args];
   6753       FT_F26Dot6  org_dist, cur_dist, new_dist;
   6754 
   6755 
   6756       /* check point bounds */
   6757       if ( BOUNDS( point, exc->zp2.n_points ) )
   6758       {
   6759         if ( exc->pedantic_hinting )
   6760         {
   6761           exc->error = FT_THROW( Invalid_Reference );
   6762           return;
   6763         }
   6764         continue;
   6765       }
   6766 
   6767       if ( twilight )
   6768         org_dist = DUALPROJ( &exc->zp2.org[point], orus_base );
   6769       else if ( exc->metrics.x_scale == exc->metrics.y_scale )
   6770         org_dist = DUALPROJ( &exc->zp2.orus[point], orus_base );
   6771       else
   6772       {
   6773         FT_Vector  vec;
   6774 
   6775 
   6776         vec.x = FT_MulFix( SUB_LONG( exc->zp2.orus[point].x,
   6777                                      orus_base->x ),
   6778                            exc->metrics.x_scale );
   6779         vec.y = FT_MulFix( SUB_LONG( exc->zp2.orus[point].y,
   6780                                      orus_base->y ),
   6781                            exc->metrics.y_scale );
   6782 
   6783         org_dist = FAST_DUALPROJ( &vec );
   6784       }
   6785 
   6786       cur_dist = PROJECT( &exc->zp2.cur[point], cur_base );
   6787 
   6788       if ( org_dist )
   6789       {
   6790         if ( old_range )
   6791           new_dist = FT_MulDiv( org_dist, cur_range, old_range );
   6792         else
   6793         {
   6794           /* This is the same as what MS does for the invalid case:  */
   6795           /*                                                         */
   6796           /*   delta = (Original_Pt - Original_RP1) -                */
   6797           /*           (Current_Pt - Current_RP1)         ;          */
   6798           /*                                                         */
   6799           /* In FreeType speak:                                      */
   6800           /*                                                         */
   6801           /*   delta = org_dist - cur_dist          .                */
   6802           /*                                                         */
   6803           /* We move `point' by `new_dist - cur_dist' after leaving  */
   6804           /* this block, thus we have                                */
   6805           /*                                                         */
   6806           /*   new_dist - cur_dist = delta                   ,       */
   6807           /*   new_dist - cur_dist = org_dist - cur_dist     ,       */
   6808           /*              new_dist = org_dist                .       */
   6809 
   6810           new_dist = org_dist;
   6811         }
   6812       }
   6813       else
   6814         new_dist = 0;
   6815 
   6816       exc->func_move( exc,
   6817                       &exc->zp2,
   6818                       (FT_UShort)point,
   6819                       SUB_LONG( new_dist, cur_dist ) );
   6820     }
   6821 
   6822   Fail:
   6823     exc->GS.loop = 1;
   6824     exc->new_top = exc->args;
   6825   }
   6826 
   6827 
   6828   /**************************************************************************
   6829    *
   6830    * UTP[a]:       UnTouch Point
   6831    * Opcode range: 0x29
   6832    * Stack:        uint32 -->
   6833    */
   6834   static void
   6835   Ins_UTP( TT_ExecContext  exc,
   6836            FT_Long*        args )
   6837   {
   6838     FT_UShort  point;
   6839     FT_Byte    mask;
   6840 
   6841 
   6842     point = (FT_UShort)args[0];
   6843 
   6844     if ( BOUNDS( point, exc->zp0.n_points ) )
   6845     {
   6846       if ( exc->pedantic_hinting )
   6847         exc->error = FT_THROW( Invalid_Reference );
   6848       return;
   6849     }
   6850 
   6851     mask = 0xFF;
   6852 
   6853     if ( exc->GS.freeVector.x != 0 )
   6854       mask &= ~FT_CURVE_TAG_TOUCH_X;
   6855 
   6856     if ( exc->GS.freeVector.y != 0 )
   6857       mask &= ~FT_CURVE_TAG_TOUCH_Y;
   6858 
   6859     exc->zp0.tags[point] &= mask;
   6860   }
   6861 
   6862 
   6863   /* Local variables for Ins_IUP: */
   6864   typedef struct  IUP_WorkerRec_
   6865   {
   6866     FT_Vector*  orgs;   /* original and current coordinate */
   6867     FT_Vector*  curs;   /* arrays                          */
   6868     FT_Vector*  orus;
   6869     FT_UInt     max_points;
   6870 
   6871   } IUP_WorkerRec, *IUP_Worker;
   6872 
   6873 
   6874   static void
   6875   _iup_worker_shift( IUP_Worker  worker,
   6876                      FT_UInt     p1,
   6877                      FT_UInt     p2,
   6878                      FT_UInt     p )
   6879   {
   6880     FT_UInt     i;
   6881     FT_F26Dot6  dx;
   6882 
   6883 
   6884     dx = SUB_LONG( worker->curs[p].x, worker->orgs[p].x );
   6885     if ( dx != 0 )
   6886     {
   6887       for ( i = p1; i < p; i++ )
   6888         worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
   6889 
   6890       for ( i = p + 1; i <= p2; i++ )
   6891         worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
   6892     }
   6893   }
   6894 
   6895 
   6896   static void
   6897   _iup_worker_interpolate( IUP_Worker  worker,
   6898                            FT_UInt     p1,
   6899                            FT_UInt     p2,
   6900                            FT_UInt     ref1,
   6901                            FT_UInt     ref2 )
   6902   {
   6903     FT_UInt     i;
   6904     FT_F26Dot6  orus1, orus2, org1, org2, cur1, cur2, delta1, delta2;
   6905 
   6906 
   6907     if ( p1 > p2 )
   6908       return;
   6909 
   6910     if ( BOUNDS( ref1, worker->max_points ) ||
   6911          BOUNDS( ref2, worker->max_points ) )
   6912       return;
   6913 
   6914     orus1 = worker->orus[ref1].x;
   6915     orus2 = worker->orus[ref2].x;
   6916 
   6917     if ( orus1 > orus2 )
   6918     {
   6919       FT_F26Dot6  tmp_o;
   6920       FT_UInt     tmp_r;
   6921 
   6922 
   6923       tmp_o = orus1;
   6924       orus1 = orus2;
   6925       orus2 = tmp_o;
   6926 
   6927       tmp_r = ref1;
   6928       ref1  = ref2;
   6929       ref2  = tmp_r;
   6930     }
   6931 
   6932     org1   = worker->orgs[ref1].x;
   6933     org2   = worker->orgs[ref2].x;
   6934     cur1   = worker->curs[ref1].x;
   6935     cur2   = worker->curs[ref2].x;
   6936     delta1 = SUB_LONG( cur1, org1 );
   6937     delta2 = SUB_LONG( cur2, org2 );
   6938 
   6939     if ( cur1 == cur2 || orus1 == orus2 )
   6940     {
   6941 
   6942       /* trivial snap or shift of untouched points */
   6943       for ( i = p1; i <= p2; i++ )
   6944       {
   6945         FT_F26Dot6  x = worker->orgs[i].x;
   6946 
   6947 
   6948         if ( x <= org1 )
   6949           x = ADD_LONG( x, delta1 );
   6950 
   6951         else if ( x >= org2 )
   6952           x = ADD_LONG( x, delta2 );
   6953 
   6954         else
   6955           x = cur1;
   6956 
   6957         worker->curs[i].x = x;
   6958       }
   6959     }
   6960     else
   6961     {
   6962       FT_Fixed  scale       = 0;
   6963       FT_Bool   scale_valid = 0;
   6964 
   6965 
   6966       /* interpolation */
   6967       for ( i = p1; i <= p2; i++ )
   6968       {
   6969         FT_F26Dot6  x = worker->orgs[i].x;
   6970 
   6971 
   6972         if ( x <= org1 )
   6973           x = ADD_LONG( x, delta1 );
   6974 
   6975         else if ( x >= org2 )
   6976           x = ADD_LONG( x, delta2 );
   6977 
   6978         else
   6979         {
   6980           if ( !scale_valid )
   6981           {
   6982             scale_valid = 1;
   6983             scale       = FT_DivFix( SUB_LONG( cur2, cur1 ),
   6984                                      SUB_LONG( orus2, orus1 ) );
   6985           }
   6986 
   6987           x = ADD_LONG( cur1,
   6988                         FT_MulFix( SUB_LONG( worker->orus[i].x, orus1 ),
   6989                                    scale ) );
   6990         }
   6991         worker->curs[i].x = x;
   6992       }
   6993     }
   6994   }
   6995 
   6996 
   6997   /**************************************************************************
   6998    *
   6999    * IUP[a]:       Interpolate Untouched Points
   7000    * Opcode range: 0x30-0x31
   7001    * Stack:        -->
   7002    */
   7003   static void
   7004   Ins_IUP( TT_ExecContext  exc )
   7005   {
   7006     IUP_WorkerRec  V;
   7007     FT_Byte        mask;
   7008 
   7009     FT_UInt   first_point;   /* first point of contour        */
   7010     FT_UInt   end_point;     /* end point (last+1) of contour */
   7011 
   7012     FT_UInt   first_touched; /* first touched point in contour   */
   7013     FT_UInt   cur_touched;   /* current touched point in contour */
   7014 
   7015     FT_UInt   point;         /* current point   */
   7016     FT_Short  contour;       /* current contour */
   7017 
   7018 
   7019 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   7020     /* See `ttinterp.h' for details on backward compatibility mode.  */
   7021     /* Allow IUP until it has been called on both axes.  Immediately */
   7022     /* return on subsequent ones.                                    */
   7023     if ( SUBPIXEL_HINTING_MINIMAL    &&
   7024          exc->backward_compatibility )
   7025     {
   7026       if ( exc->iupx_called && exc->iupy_called )
   7027         return;
   7028 
   7029       if ( exc->opcode & 1 )
   7030         exc->iupx_called = TRUE;
   7031       else
   7032         exc->iupy_called = TRUE;
   7033     }
   7034 #endif
   7035 
   7036     /* ignore empty outlines */
   7037     if ( exc->pts.n_contours == 0 )
   7038       return;
   7039 
   7040     if ( exc->opcode & 1 )
   7041     {
   7042       mask   = FT_CURVE_TAG_TOUCH_X;
   7043       V.orgs = exc->pts.org;
   7044       V.curs = exc->pts.cur;
   7045       V.orus = exc->pts.orus;
   7046     }
   7047     else
   7048     {
   7049       mask   = FT_CURVE_TAG_TOUCH_Y;
   7050       V.orgs = (FT_Vector*)( (FT_Pos*)exc->pts.org + 1 );
   7051       V.curs = (FT_Vector*)( (FT_Pos*)exc->pts.cur + 1 );
   7052       V.orus = (FT_Vector*)( (FT_Pos*)exc->pts.orus + 1 );
   7053     }
   7054     V.max_points = exc->pts.n_points;
   7055 
   7056     contour = 0;
   7057     point   = 0;
   7058 
   7059 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7060     if ( SUBPIXEL_HINTING_INFINALITY &&
   7061          exc->ignore_x_mode          )
   7062     {
   7063       exc->iup_called = TRUE;
   7064       if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
   7065         return;
   7066     }
   7067 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7068 
   7069     do
   7070     {
   7071       end_point   = exc->pts.contours[contour] - exc->pts.first_point;
   7072       first_point = point;
   7073 
   7074       if ( BOUNDS( end_point, exc->pts.n_points ) )
   7075         end_point = exc->pts.n_points - 1;
   7076 
   7077       while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 )
   7078         point++;
   7079 
   7080       if ( point <= end_point )
   7081       {
   7082         first_touched = point;
   7083         cur_touched   = point;
   7084 
   7085         point++;
   7086 
   7087         while ( point <= end_point )
   7088         {
   7089           if ( ( exc->pts.tags[point] & mask ) != 0 )
   7090           {
   7091             _iup_worker_interpolate( &V,
   7092                                      cur_touched + 1,
   7093                                      point - 1,
   7094                                      cur_touched,
   7095                                      point );
   7096             cur_touched = point;
   7097           }
   7098 
   7099           point++;
   7100         }
   7101 
   7102         if ( cur_touched == first_touched )
   7103           _iup_worker_shift( &V, first_point, end_point, cur_touched );
   7104         else
   7105         {
   7106           _iup_worker_interpolate( &V,
   7107                                    (FT_UShort)( cur_touched + 1 ),
   7108                                    end_point,
   7109                                    cur_touched,
   7110                                    first_touched );
   7111 
   7112           if ( first_touched > 0 )
   7113             _iup_worker_interpolate( &V,
   7114                                      first_point,
   7115                                      first_touched - 1,
   7116                                      cur_touched,
   7117                                      first_touched );
   7118         }
   7119       }
   7120       contour++;
   7121     } while ( contour < exc->pts.n_contours );
   7122   }
   7123 
   7124 
   7125   /**************************************************************************
   7126    *
   7127    * DELTAPn[]:    DELTA exceptions P1, P2, P3
   7128    * Opcode range: 0x5D,0x71,0x72
   7129    * Stack:        uint32 (2 * uint32)... -->
   7130    */
   7131   static void
   7132   Ins_DELTAP( TT_ExecContext  exc,
   7133               FT_Long*        args )
   7134   {
   7135     FT_ULong   nump, k;
   7136     FT_UShort  A;
   7137     FT_ULong   C, P;
   7138     FT_Long    B;
   7139 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7140     FT_UShort  B1, B2;
   7141 
   7142 
   7143     if ( SUBPIXEL_HINTING_INFINALITY                              &&
   7144          exc->ignore_x_mode                                       &&
   7145          exc->iup_called                                          &&
   7146          ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
   7147       goto Fail;
   7148 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7149 
   7150     P    = (FT_ULong)exc->func_cur_ppem( exc );
   7151     nump = (FT_ULong)args[0];   /* some points theoretically may occur more
   7152                                    than once, thus UShort isn't enough */
   7153 
   7154     for ( k = 1; k <= nump; k++ )
   7155     {
   7156       if ( exc->args < 2 )
   7157       {
   7158         if ( exc->pedantic_hinting )
   7159           exc->error = FT_THROW( Too_Few_Arguments );
   7160         exc->args = 0;
   7161         goto Fail;
   7162       }
   7163 
   7164       exc->args -= 2;
   7165 
   7166       A = (FT_UShort)exc->stack[exc->args + 1];
   7167       B = exc->stack[exc->args];
   7168 
   7169       /* XXX: Because some popular fonts contain some invalid DeltaP */
   7170       /*      instructions, we simply ignore them when the stacked   */
   7171       /*      point reference is off limit, rather than returning an */
   7172       /*      error.  As a delta instruction doesn't change a glyph  */
   7173       /*      in great ways, this shouldn't be a problem.            */
   7174 
   7175       if ( !BOUNDS( A, exc->zp0.n_points ) )
   7176       {
   7177         C = ( (FT_ULong)B & 0xF0 ) >> 4;
   7178 
   7179         switch ( exc->opcode )
   7180         {
   7181         case 0x5D:
   7182           break;
   7183 
   7184         case 0x71:
   7185           C += 16;
   7186           break;
   7187 
   7188         case 0x72:
   7189           C += 32;
   7190           break;
   7191         }
   7192 
   7193         C += exc->GS.delta_base;
   7194 
   7195         if ( P == C )
   7196         {
   7197           B = ( (FT_ULong)B & 0xF ) - 8;
   7198           if ( B >= 0 )
   7199             B++;
   7200           B *= 1L << ( 6 - exc->GS.delta_shift );
   7201 
   7202 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7203 
   7204           if ( SUBPIXEL_HINTING_INFINALITY )
   7205           {
   7206             /*
   7207              * Allow delta move if
   7208              *
   7209              * - not using ignore_x_mode rendering,
   7210              * - glyph is specifically set to allow it, or
   7211              * - glyph is composite and freedom vector is not in subpixel
   7212              *   direction.
   7213              */
   7214             if ( !exc->ignore_x_mode                                   ||
   7215                  ( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
   7216                  ( exc->is_composite && exc->GS.freeVector.y != 0 )    )
   7217               exc->func_move( exc, &exc->zp0, A, B );
   7218 
   7219             /* Otherwise, apply subpixel hinting and compatibility mode */
   7220             /* rules, always skipping deltas in subpixel direction.     */
   7221             else if ( exc->ignore_x_mode && exc->GS.freeVector.y != 0 )
   7222             {
   7223               /* save the y value of the point now; compare after move */
   7224               B1 = (FT_UShort)exc->zp0.cur[A].y;
   7225 
   7226               /* Standard subpixel hinting: Allow y move for y-touched */
   7227               /* points.  This messes up DejaVu ...                    */
   7228               if ( !exc->face->sph_compatibility_mode          &&
   7229                    ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
   7230                 exc->func_move( exc, &exc->zp0, A, B );
   7231 
   7232               /* compatibility mode */
   7233               else if ( exc->face->sph_compatibility_mode                        &&
   7234                         !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
   7235               {
   7236                 if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
   7237                   B = FT_PIX_ROUND( B1 + B ) - B1;
   7238 
   7239                 /* Allow delta move if using sph_compatibility_mode,   */
   7240                 /* IUP has not been called, and point is touched on Y. */
   7241                 if ( !exc->iup_called                            &&
   7242                      ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
   7243                   exc->func_move( exc, &exc->zp0, A, B );
   7244               }
   7245 
   7246               B2 = (FT_UShort)exc->zp0.cur[A].y;
   7247 
   7248               /* Reverse this move if it results in a disallowed move */
   7249               if ( exc->GS.freeVector.y != 0                          &&
   7250                    ( ( exc->face->sph_compatibility_mode          &&
   7251                        ( B1 & 63 ) == 0                           &&
   7252                        ( B2 & 63 ) != 0                           ) ||
   7253                      ( ( exc->sph_tweak_flags                   &
   7254                          SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
   7255                        ( B1 & 63 ) != 0                           &&
   7256                        ( B2 & 63 ) != 0                           ) ) )
   7257                 exc->func_move( exc, &exc->zp0, A, NEG_LONG( B ) );
   7258             }
   7259           }
   7260           else
   7261 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7262 
   7263           {
   7264 
   7265 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   7266             /* See `ttinterp.h' for details on backward compatibility */
   7267             /* mode.                                                  */
   7268             if ( SUBPIXEL_HINTING_MINIMAL    &&
   7269                  exc->backward_compatibility )
   7270             {
   7271               if ( !( exc->iupx_called && exc->iupy_called )              &&
   7272                    ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
   7273                      ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y )        ) )
   7274                 exc->func_move( exc, &exc->zp0, A, B );
   7275             }
   7276             else
   7277 #endif
   7278               exc->func_move( exc, &exc->zp0, A, B );
   7279           }
   7280         }
   7281       }
   7282       else
   7283         if ( exc->pedantic_hinting )
   7284           exc->error = FT_THROW( Invalid_Reference );
   7285     }
   7286 
   7287   Fail:
   7288     exc->new_top = exc->args;
   7289   }
   7290 
   7291 
   7292   /**************************************************************************
   7293    *
   7294    * DELTACn[]:    DELTA exceptions C1, C2, C3
   7295    * Opcode range: 0x73,0x74,0x75
   7296    * Stack:        uint32 (2 * uint32)... -->
   7297    */
   7298   static void
   7299   Ins_DELTAC( TT_ExecContext  exc,
   7300               FT_Long*        args )
   7301   {
   7302     FT_ULong  nump, k;
   7303     FT_ULong  A, C, P;
   7304     FT_Long   B;
   7305 
   7306 
   7307     P    = (FT_ULong)exc->func_cur_ppem( exc );
   7308     nump = (FT_ULong)args[0];
   7309 
   7310     for ( k = 1; k <= nump; k++ )
   7311     {
   7312       if ( exc->args < 2 )
   7313       {
   7314         if ( exc->pedantic_hinting )
   7315           exc->error = FT_THROW( Too_Few_Arguments );
   7316         exc->args = 0;
   7317         goto Fail;
   7318       }
   7319 
   7320       exc->args -= 2;
   7321 
   7322       A = (FT_ULong)exc->stack[exc->args + 1];
   7323       B = exc->stack[exc->args];
   7324 
   7325       if ( BOUNDSL( A, exc->cvtSize ) )
   7326       {
   7327         if ( exc->pedantic_hinting )
   7328         {
   7329           exc->error = FT_THROW( Invalid_Reference );
   7330           return;
   7331         }
   7332       }
   7333       else
   7334       {
   7335         C = ( (FT_ULong)B & 0xF0 ) >> 4;
   7336 
   7337         switch ( exc->opcode )
   7338         {
   7339         case 0x73:
   7340           break;
   7341 
   7342         case 0x74:
   7343           C += 16;
   7344           break;
   7345 
   7346         case 0x75:
   7347           C += 32;
   7348           break;
   7349         }
   7350 
   7351         C += exc->GS.delta_base;
   7352 
   7353         if ( P == C )
   7354         {
   7355           B = ( (FT_ULong)B & 0xF ) - 8;
   7356           if ( B >= 0 )
   7357             B++;
   7358           B *= 1L << ( 6 - exc->GS.delta_shift );
   7359 
   7360           exc->func_move_cvt( exc, A, B );
   7361         }
   7362       }
   7363     }
   7364 
   7365   Fail:
   7366     exc->new_top = exc->args;
   7367   }
   7368 
   7369 
   7370   /**************************************************************************
   7371    *
   7372    * MISC. INSTRUCTIONS
   7373    *
   7374    */
   7375 
   7376 
   7377   /**************************************************************************
   7378    *
   7379    * GETINFO[]:    GET INFOrmation
   7380    * Opcode range: 0x88
   7381    * Stack:        uint32 --> uint32
   7382    *
   7383    * XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May
   7384    *      2015) not documented in the OpenType specification.
   7385    *
   7386    *      Selector bit 11 is incorrectly described as bit 8, while the
   7387    *      real meaning of bit 8 (vertical LCD subpixels) stays
   7388    *      undocumented.  The same mistake can be found in Greg Hitchcock's
   7389    *      whitepaper.
   7390    */
   7391   static void
   7392   Ins_GETINFO( TT_ExecContext  exc,
   7393                FT_Long*        args )
   7394   {
   7395     FT_Long    K;
   7396     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
   7397 
   7398 
   7399     K = 0;
   7400 
   7401 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7402     /*********************************
   7403      * RASTERIZER VERSION
   7404      * Selector Bit:  0
   7405      * Return Bit(s): 0-7
   7406      */
   7407     if ( SUBPIXEL_HINTING_INFINALITY &&
   7408          ( args[0] & 1 ) != 0        &&
   7409          exc->subpixel_hinting       )
   7410     {
   7411       if ( exc->ignore_x_mode )
   7412       {
   7413         /* if in ClearType backward compatibility mode,         */
   7414         /* we sometimes change the TrueType version dynamically */
   7415         K = exc->rasterizer_version;
   7416         FT_TRACE6(( "Setting rasterizer version %d\n",
   7417                     exc->rasterizer_version ));
   7418       }
   7419       else
   7420         K = TT_INTERPRETER_VERSION_38;
   7421     }
   7422     else
   7423 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7424       if ( ( args[0] & 1 ) != 0 )
   7425         K = driver->interpreter_version;
   7426 
   7427     /*********************************
   7428      * GLYPH ROTATED
   7429      * Selector Bit:  1
   7430      * Return Bit(s): 8
   7431      */
   7432     if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated )
   7433       K |= 1 << 8;
   7434 
   7435     /*********************************
   7436      * GLYPH STRETCHED
   7437      * Selector Bit:  2
   7438      * Return Bit(s): 9
   7439      */
   7440     if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched )
   7441       K |= 1 << 9;
   7442 
   7443 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   7444     /*********************************
   7445      * VARIATION GLYPH
   7446      * Selector Bit:  3
   7447      * Return Bit(s): 10
   7448      *
   7449      * XXX: UNDOCUMENTED!
   7450      */
   7451     if ( (args[0] & 8 ) != 0 && exc->face->blend )
   7452       K |= 1 << 10;
   7453 #endif
   7454 
   7455     /*********************************
   7456      * BI-LEVEL HINTING AND
   7457      * GRAYSCALE RENDERING
   7458      * Selector Bit:  5
   7459      * Return Bit(s): 12
   7460      */
   7461     if ( ( args[0] & 32 ) != 0 && exc->grayscale )
   7462       K |= 1 << 12;
   7463 
   7464 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   7465     /* Toggle the following flags only outside of monochrome mode.      */
   7466     /* Otherwise, instructions may behave weirdly and rendering results */
   7467     /* may differ between v35 and v40 mode, e.g., in `Times New Roman   */
   7468     /* Bold Italic'. */
   7469     if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean )
   7470     {
   7471       /*********************************
   7472        * HINTING FOR SUBPIXEL
   7473        * Selector Bit:  6
   7474        * Return Bit(s): 13
   7475        *
   7476        * v40 does subpixel hinting by default.
   7477        */
   7478       if ( ( args[0] & 64 ) != 0 )
   7479         K |= 1 << 13;
   7480 
   7481       /*********************************
   7482        * VERTICAL LCD SUBPIXELS?
   7483        * Selector Bit:  8
   7484        * Return Bit(s): 15
   7485        */
   7486       if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
   7487         K |= 1 << 15;
   7488 
   7489       /*********************************
   7490        * SUBPIXEL POSITIONED?
   7491        * Selector Bit:  10
   7492        * Return Bit(s): 17
   7493        *
   7494        * XXX: FreeType supports it, dependent on what client does?
   7495        */
   7496       if ( ( args[0] & 1024 ) != 0 )
   7497         K |= 1 << 17;
   7498 
   7499       /*********************************
   7500        * SYMMETRICAL SMOOTHING
   7501        * Selector Bit:  11
   7502        * Return Bit(s): 18
   7503        *
   7504        * The only smoothing method FreeType supports unless someone sets
   7505        * FT_LOAD_TARGET_MONO.
   7506        */
   7507       if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean )
   7508         K |= 1 << 18;
   7509 
   7510       /*********************************
   7511        * CLEARTYPE HINTING AND
   7512        * GRAYSCALE RENDERING
   7513        * Selector Bit:  12
   7514        * Return Bit(s): 19
   7515        *
   7516        * Grayscale rendering is what FreeType does anyway unless someone
   7517        * sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V)
   7518        */
   7519       if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
   7520         K |= 1 << 19;
   7521     }
   7522 #endif
   7523 
   7524 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7525 
   7526     if ( SUBPIXEL_HINTING_INFINALITY                          &&
   7527          exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
   7528     {
   7529 
   7530       if ( exc->rasterizer_version >= 37 )
   7531       {
   7532         /*********************************
   7533          * HINTING FOR SUBPIXEL
   7534          * Selector Bit:  6
   7535          * Return Bit(s): 13
   7536          */
   7537         if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting )
   7538           K |= 1 << 13;
   7539 
   7540         /*********************************
   7541          * COMPATIBLE WIDTHS ENABLED
   7542          * Selector Bit:  7
   7543          * Return Bit(s): 14
   7544          *
   7545          * Functionality still needs to be added
   7546          */
   7547         if ( ( args[0] & 128 ) != 0 && exc->compatible_widths )
   7548           K |= 1 << 14;
   7549 
   7550         /*********************************
   7551          * VERTICAL LCD SUBPIXELS?
   7552          * Selector Bit:  8
   7553          * Return Bit(s): 15
   7554          *
   7555          * Functionality still needs to be added
   7556          */
   7557         if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd )
   7558           K |= 1 << 15;
   7559 
   7560         /*********************************
   7561          * HINTING FOR BGR?
   7562          * Selector Bit:  9
   7563          * Return Bit(s): 16
   7564          *
   7565          * Functionality still needs to be added
   7566          */
   7567         if ( ( args[0] & 512 ) != 0 && exc->bgr )
   7568           K |= 1 << 16;
   7569 
   7570         if ( exc->rasterizer_version >= 38 )
   7571         {
   7572           /*********************************
   7573            * SUBPIXEL POSITIONED?
   7574            * Selector Bit:  10
   7575            * Return Bit(s): 17
   7576            *
   7577            * Functionality still needs to be added
   7578            */
   7579           if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned )
   7580             K |= 1 << 17;
   7581 
   7582           /*********************************
   7583            * SYMMETRICAL SMOOTHING
   7584            * Selector Bit:  11
   7585            * Return Bit(s): 18
   7586            *
   7587            * Functionality still needs to be added
   7588            */
   7589           if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing )
   7590             K |= 1 << 18;
   7591 
   7592           /*********************************
   7593            * GRAY CLEARTYPE
   7594            * Selector Bit:  12
   7595            * Return Bit(s): 19
   7596            *
   7597            * Functionality still needs to be added
   7598            */
   7599           if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype )
   7600             K |= 1 << 19;
   7601         }
   7602       }
   7603     }
   7604 
   7605 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7606 
   7607     args[0] = K;
   7608   }
   7609 
   7610 
   7611 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   7612 
   7613   /**************************************************************************
   7614    *
   7615    * GETVARIATION[]: get normalized variation (blend) coordinates
   7616    * Opcode range: 0x91
   7617    * Stack:        --> f2.14...
   7618    *
   7619    * XXX: UNDOCUMENTED!  There is no official documentation from Apple for
   7620    *      this bytecode instruction.  Active only if a font has GX
   7621    *      variation axes.
   7622    */
   7623   static void
   7624   Ins_GETVARIATION( TT_ExecContext  exc,
   7625                     FT_Long*        args )
   7626   {
   7627     FT_UInt    num_axes = exc->face->blend->num_axis;
   7628     FT_Fixed*  coords   = exc->face->blend->normalizedcoords;
   7629 
   7630     FT_UInt  i;
   7631 
   7632 
   7633     if ( BOUNDS( num_axes, exc->stackSize + 1 - exc->top ) )
   7634     {
   7635       exc->error = FT_THROW( Stack_Overflow );
   7636       return;
   7637     }
   7638 
   7639     if ( coords )
   7640     {
   7641       for ( i = 0; i < num_axes; i++ )
   7642         args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */
   7643     }
   7644     else
   7645     {
   7646       for ( i = 0; i < num_axes; i++ )
   7647         args[i] = 0;
   7648     }
   7649   }
   7650 
   7651 
   7652   /**************************************************************************
   7653    *
   7654    * GETDATA[]:    no idea what this is good for
   7655    * Opcode range: 0x92
   7656    * Stack:        --> 17
   7657    *
   7658    * XXX: UNDOCUMENTED!  There is no documentation from Apple for this
   7659    *      very weird bytecode instruction.
   7660    */
   7661   static void
   7662   Ins_GETDATA( FT_Long*  args )
   7663   {
   7664     args[0] = 17;
   7665   }
   7666 
   7667 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
   7668 
   7669 
   7670   static void
   7671   Ins_UNKNOWN( TT_ExecContext  exc )
   7672   {
   7673     TT_DefRecord*  def   = exc->IDefs;
   7674     TT_DefRecord*  limit = def + exc->numIDefs;
   7675 
   7676 
   7677     for ( ; def < limit; def++ )
   7678     {
   7679       if ( (FT_Byte)def->opc == exc->opcode && def->active )
   7680       {
   7681         TT_CallRec*  call;
   7682 
   7683 
   7684         if ( exc->callTop >= exc->callSize )
   7685         {
   7686           exc->error = FT_THROW( Stack_Overflow );
   7687           return;
   7688         }
   7689 
   7690         call = exc->callStack + exc->callTop++;
   7691 
   7692         call->Caller_Range = exc->curRange;
   7693         call->Caller_IP    = exc->IP + 1;
   7694         call->Cur_Count    = 1;
   7695         call->Def          = def;
   7696 
   7697         Ins_Goto_CodeRange( exc, def->range, def->start );
   7698 
   7699         exc->step_ins = FALSE;
   7700         return;
   7701       }
   7702     }
   7703 
   7704     exc->error = FT_THROW( Invalid_Opcode );
   7705   }
   7706 
   7707 
   7708   /**************************************************************************
   7709    *
   7710    * RUN
   7711    *
   7712    * This function executes a run of opcodes.  It will exit in the
   7713    * following cases:
   7714    *
   7715    * - Errors (in which case it returns FALSE).
   7716    *
   7717    * - Reaching the end of the main code range (returns TRUE).
   7718    *   Reaching the end of a code range within a function call is an
   7719    *   error.
   7720    *
   7721    * - After executing one single opcode, if the flag `Instruction_Trap'
   7722    *   is set to TRUE (returns TRUE).
   7723    *
   7724    * On exit with TRUE, test IP < CodeSize to know whether it comes from
   7725    * an instruction trap or a normal termination.
   7726    *
   7727    *
   7728    * Note: The documented DEBUG opcode pops a value from the stack.  This
   7729    *       behaviour is unsupported; here a DEBUG opcode is always an
   7730    *       error.
   7731    *
   7732    *
   7733    * THIS IS THE INTERPRETER'S MAIN LOOP.
   7734    *
   7735    */
   7736 
   7737 
   7738   /* documentation is in ttinterp.h */
   7739 
   7740   FT_EXPORT_DEF( FT_Error )
   7741   TT_RunIns( TT_ExecContext  exc )
   7742   {
   7743     FT_ULong   ins_counter = 0;  /* executed instructions counter */
   7744     FT_ULong   num_twilight_points;
   7745     FT_UShort  i;
   7746 
   7747 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7748     FT_Byte    opcode_pattern[1][2] = {
   7749                   /* #8 TypeMan Talk Align */
   7750                   {
   7751                     0x06, /* SPVTL   */
   7752                     0x7D, /* RDTG    */
   7753                   },
   7754                 };
   7755     FT_UShort  opcode_patterns   = 1;
   7756     FT_UShort  opcode_pointer[1] = { 0 };
   7757     FT_UShort  opcode_size[1]    = { 1 };
   7758 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7759 
   7760 
   7761 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7762     exc->iup_called = FALSE;
   7763 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7764 
   7765 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   7766     /*
   7767      * Toggle backward compatibility according to what font wants, except
   7768      * when
   7769      *
   7770      * 1) we have a `tricky' font that heavily relies on the interpreter to
   7771      *    render glyphs correctly, for example DFKai-SB, or
   7772      * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
   7773      *
   7774      * In those cases, backward compatibility needs to be turned off to get
   7775      * correct rendering.  The rendering is then completely up to the
   7776      * font's programming.
   7777      *
   7778      */
   7779     if ( SUBPIXEL_HINTING_MINIMAL          &&
   7780          exc->subpixel_hinting_lean        &&
   7781          !FT_IS_TRICKY( &exc->face->root ) )
   7782       exc->backward_compatibility = !( exc->GS.instruct_control & 4 );
   7783     else
   7784       exc->backward_compatibility = FALSE;
   7785 
   7786     exc->iupx_called = FALSE;
   7787     exc->iupy_called = FALSE;
   7788 #endif
   7789 
   7790     /* We restrict the number of twilight points to a reasonable,     */
   7791     /* heuristic value to avoid slow execution of malformed bytecode. */
   7792     num_twilight_points = FT_MAX( 30,
   7793                                   2 * ( exc->pts.n_points + exc->cvtSize ) );
   7794     if ( exc->twilight.n_points > num_twilight_points )
   7795     {
   7796       if ( num_twilight_points > 0xFFFFU )
   7797         num_twilight_points = 0xFFFFU;
   7798 
   7799       FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n"
   7800                   "           from %d to the more reasonable value %d\n",
   7801                   exc->twilight.n_points,
   7802                   num_twilight_points ));
   7803       exc->twilight.n_points = (FT_UShort)num_twilight_points;
   7804     }
   7805 
   7806     /* Set up loop detectors.  We restrict the number of LOOPCALL loops */
   7807     /* and the number of JMPR, JROT, and JROF calls with a negative     */
   7808     /* argument to values that depend on various parameters like the    */
   7809     /* size of the CVT table or the number of points in the current     */
   7810     /* glyph (if applicable).                                           */
   7811     /*                                                                  */
   7812     /* The idea is that in real-world bytecode you either iterate over  */
   7813     /* all CVT entries (in the `prep' table), or over all points (or    */
   7814     /* contours, in the `glyf' table) of a glyph, and such iterations   */
   7815     /* don't happen very often.                                         */
   7816     exc->loopcall_counter = 0;
   7817     exc->neg_jump_counter = 0;
   7818 
   7819     /* The maximum values are heuristic. */
   7820     if ( exc->pts.n_points )
   7821       exc->loopcall_counter_max = FT_MAX( 50,
   7822                                           10 * exc->pts.n_points ) +
   7823                                   FT_MAX( 50,
   7824                                           exc->cvtSize / 10 );
   7825     else
   7826       exc->loopcall_counter_max = 300 + 8 * exc->cvtSize;
   7827 
   7828     /* as a protection against an unreasonable number of CVT entries  */
   7829     /* we assume at most 100 control values per glyph for the counter */
   7830     if ( exc->loopcall_counter_max >
   7831          100 * (FT_ULong)exc->face->root.num_glyphs )
   7832       exc->loopcall_counter_max = 100 * (FT_ULong)exc->face->root.num_glyphs;
   7833 
   7834     FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL"
   7835                 " to %d\n", exc->loopcall_counter_max ));
   7836 
   7837     exc->neg_jump_counter_max = exc->loopcall_counter_max;
   7838     FT_TRACE5(( "TT_RunIns: Limiting total number of backward jumps"
   7839                 " to %d\n", exc->neg_jump_counter_max ));
   7840 
   7841     /* set PPEM and CVT functions */
   7842     exc->tt_metrics.ratio = 0;
   7843     if ( exc->metrics.x_ppem != exc->metrics.y_ppem )
   7844     {
   7845       /* non-square pixels, use the stretched routines */
   7846       exc->func_cur_ppem  = Current_Ppem_Stretched;
   7847       exc->func_read_cvt  = Read_CVT_Stretched;
   7848       exc->func_write_cvt = Write_CVT_Stretched;
   7849       exc->func_move_cvt  = Move_CVT_Stretched;
   7850     }
   7851     else
   7852     {
   7853       /* square pixels, use normal routines */
   7854       exc->func_cur_ppem  = Current_Ppem;
   7855       exc->func_read_cvt  = Read_CVT;
   7856       exc->func_write_cvt = Write_CVT;
   7857       exc->func_move_cvt  = Move_CVT;
   7858     }
   7859 
   7860     Compute_Funcs( exc );
   7861     Compute_Round( exc, (FT_Byte)exc->GS.round_state );
   7862 
   7863     do
   7864     {
   7865       exc->opcode = exc->code[exc->IP];
   7866 
   7867 #ifdef FT_DEBUG_LEVEL_TRACE
   7868       {
   7869         FT_Long  cnt = FT_MIN( 8, exc->top );
   7870         FT_Long  n;
   7871 
   7872 
   7873         /* if tracing level is 7, show current code position */
   7874         /* and the first few stack elements also             */
   7875         FT_TRACE6(( "  " ));
   7876         FT_TRACE7(( "%06d ", exc->IP ));
   7877         FT_TRACE6(( opcode_name[exc->opcode] + 2 ));
   7878         FT_TRACE7(( "%*s", *opcode_name[exc->opcode] == 'A'
   7879                               ? 2
   7880                               : 12 - ( *opcode_name[exc->opcode] - '0' ),
   7881                               "#" ));
   7882         for ( n = 1; n <= cnt; n++ )
   7883           FT_TRACE7(( " %d", exc->stack[exc->top - n] ));
   7884         FT_TRACE6(( "\n" ));
   7885       }
   7886 #endif /* FT_DEBUG_LEVEL_TRACE */
   7887 
   7888       if ( ( exc->length = opcode_length[exc->opcode] ) < 0 )
   7889       {
   7890         if ( exc->IP + 1 >= exc->codeSize )
   7891           goto LErrorCodeOverflow_;
   7892 
   7893         exc->length = 2 - exc->length * exc->code[exc->IP + 1];
   7894       }
   7895 
   7896       if ( exc->IP + exc->length > exc->codeSize )
   7897         goto LErrorCodeOverflow_;
   7898 
   7899       /* First, let's check for empty stack and overflow */
   7900       exc->args = exc->top - ( Pop_Push_Count[exc->opcode] >> 4 );
   7901 
   7902       /* `args' is the top of the stack once arguments have been popped. */
   7903       /* One can also interpret it as the index of the last argument.    */
   7904       if ( exc->args < 0 )
   7905       {
   7906         if ( exc->pedantic_hinting )
   7907         {
   7908           exc->error = FT_THROW( Too_Few_Arguments );
   7909           goto LErrorLabel_;
   7910         }
   7911 
   7912         /* push zeroes onto the stack */
   7913         for ( i = 0; i < Pop_Push_Count[exc->opcode] >> 4; i++ )
   7914           exc->stack[i] = 0;
   7915         exc->args = 0;
   7916       }
   7917 
   7918 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   7919       if ( exc->opcode == 0x91 )
   7920       {
   7921         /* this is very special: GETVARIATION returns */
   7922         /* a variable number of arguments             */
   7923 
   7924         /* it is the job of the application to `activate' GX handling, */
   7925         /* this is, calling any of the GX API functions on the current */
   7926         /* font to select a variation instance                         */
   7927         if ( exc->face->blend )
   7928           exc->new_top = exc->args + exc->face->blend->num_axis;
   7929       }
   7930       else
   7931 #endif
   7932         exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 );
   7933 
   7934       /* `new_top' is the new top of the stack, after the instruction's */
   7935       /* execution.  `top' will be set to `new_top' after the `switch'  */
   7936       /* statement.                                                     */
   7937       if ( exc->new_top > exc->stackSize )
   7938       {
   7939         exc->error = FT_THROW( Stack_Overflow );
   7940         goto LErrorLabel_;
   7941       }
   7942 
   7943       exc->step_ins = TRUE;
   7944       exc->error    = FT_Err_Ok;
   7945 
   7946 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   7947 
   7948       if ( SUBPIXEL_HINTING_INFINALITY )
   7949       {
   7950         for ( i = 0; i < opcode_patterns; i++ )
   7951         {
   7952           if ( opcode_pointer[i] < opcode_size[i]                  &&
   7953                exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
   7954           {
   7955             opcode_pointer[i] += 1;
   7956 
   7957             if ( opcode_pointer[i] == opcode_size[i] )
   7958             {
   7959               FT_TRACE6(( "sph: opcode ptrn: %d, %s %s\n",
   7960                           i,
   7961                           exc->face->root.family_name,
   7962                           exc->face->root.style_name ));
   7963 
   7964               switch ( i )
   7965               {
   7966               case 0:
   7967                 break;
   7968               }
   7969               opcode_pointer[i] = 0;
   7970             }
   7971           }
   7972           else
   7973             opcode_pointer[i] = 0;
   7974         }
   7975       }
   7976 
   7977 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
   7978 
   7979       {
   7980         FT_Long*  args   = exc->stack + exc->args;
   7981         FT_Byte   opcode = exc->opcode;
   7982 
   7983 
   7984         switch ( opcode )
   7985         {
   7986         case 0x00:  /* SVTCA y  */
   7987         case 0x01:  /* SVTCA x  */
   7988         case 0x02:  /* SPvTCA y */
   7989         case 0x03:  /* SPvTCA x */
   7990         case 0x04:  /* SFvTCA y */
   7991         case 0x05:  /* SFvTCA x */
   7992           Ins_SxyTCA( exc );
   7993           break;
   7994 
   7995         case 0x06:  /* SPvTL // */
   7996         case 0x07:  /* SPvTL +  */
   7997           Ins_SPVTL( exc, args );
   7998           break;
   7999 
   8000         case 0x08:  /* SFvTL // */
   8001         case 0x09:  /* SFvTL +  */
   8002           Ins_SFVTL( exc, args );
   8003           break;
   8004 
   8005         case 0x0A:  /* SPvFS */
   8006           Ins_SPVFS( exc, args );
   8007           break;
   8008 
   8009         case 0x0B:  /* SFvFS */
   8010           Ins_SFVFS( exc, args );
   8011           break;
   8012 
   8013         case 0x0C:  /* GPv */
   8014           Ins_GPV( exc, args );
   8015           break;
   8016 
   8017         case 0x0D:  /* GFv */
   8018           Ins_GFV( exc, args );
   8019           break;
   8020 
   8021         case 0x0E:  /* SFvTPv */
   8022           Ins_SFVTPV( exc );
   8023           break;
   8024 
   8025         case 0x0F:  /* ISECT  */
   8026           Ins_ISECT( exc, args );
   8027           break;
   8028 
   8029         case 0x10:  /* SRP0 */
   8030           Ins_SRP0( exc, args );
   8031           break;
   8032 
   8033         case 0x11:  /* SRP1 */
   8034           Ins_SRP1( exc, args );
   8035           break;
   8036 
   8037         case 0x12:  /* SRP2 */
   8038           Ins_SRP2( exc, args );
   8039           break;
   8040 
   8041         case 0x13:  /* SZP0 */
   8042           Ins_SZP0( exc, args );
   8043           break;
   8044 
   8045         case 0x14:  /* SZP1 */
   8046           Ins_SZP1( exc, args );
   8047           break;
   8048 
   8049         case 0x15:  /* SZP2 */
   8050           Ins_SZP2( exc, args );
   8051           break;
   8052 
   8053         case 0x16:  /* SZPS */
   8054           Ins_SZPS( exc, args );
   8055           break;
   8056 
   8057         case 0x17:  /* SLOOP */
   8058           Ins_SLOOP( exc, args );
   8059           break;
   8060 
   8061         case 0x18:  /* RTG */
   8062           Ins_RTG( exc );
   8063           break;
   8064 
   8065         case 0x19:  /* RTHG */
   8066           Ins_RTHG( exc );
   8067           break;
   8068 
   8069         case 0x1A:  /* SMD */
   8070           Ins_SMD( exc, args );
   8071           break;
   8072 
   8073         case 0x1B:  /* ELSE */
   8074           Ins_ELSE( exc );
   8075           break;
   8076 
   8077         case 0x1C:  /* JMPR */
   8078           Ins_JMPR( exc, args );
   8079           break;
   8080 
   8081         case 0x1D:  /* SCVTCI */
   8082           Ins_SCVTCI( exc, args );
   8083           break;
   8084 
   8085         case 0x1E:  /* SSWCI */
   8086           Ins_SSWCI( exc, args );
   8087           break;
   8088 
   8089         case 0x1F:  /* SSW */
   8090           Ins_SSW( exc, args );
   8091           break;
   8092 
   8093         case 0x20:  /* DUP */
   8094           Ins_DUP( args );
   8095           break;
   8096 
   8097         case 0x21:  /* POP */
   8098           Ins_POP();
   8099           break;
   8100 
   8101         case 0x22:  /* CLEAR */
   8102           Ins_CLEAR( exc );
   8103           break;
   8104 
   8105         case 0x23:  /* SWAP */
   8106           Ins_SWAP( args );
   8107           break;
   8108 
   8109         case 0x24:  /* DEPTH */
   8110           Ins_DEPTH( exc, args );
   8111           break;
   8112 
   8113         case 0x25:  /* CINDEX */
   8114           Ins_CINDEX( exc, args );
   8115           break;
   8116 
   8117         case 0x26:  /* MINDEX */
   8118           Ins_MINDEX( exc, args );
   8119           break;
   8120 
   8121         case 0x27:  /* ALIGNPTS */
   8122           Ins_ALIGNPTS( exc, args );
   8123           break;
   8124 
   8125         case 0x28:  /* RAW */
   8126           Ins_UNKNOWN( exc );
   8127           break;
   8128 
   8129         case 0x29:  /* UTP */
   8130           Ins_UTP( exc, args );
   8131           break;
   8132 
   8133         case 0x2A:  /* LOOPCALL */
   8134           Ins_LOOPCALL( exc, args );
   8135           break;
   8136 
   8137         case 0x2B:  /* CALL */
   8138           Ins_CALL( exc, args );
   8139           break;
   8140 
   8141         case 0x2C:  /* FDEF */
   8142           Ins_FDEF( exc, args );
   8143           break;
   8144 
   8145         case 0x2D:  /* ENDF */
   8146           Ins_ENDF( exc );
   8147           break;
   8148 
   8149         case 0x2E:  /* MDAP */
   8150         case 0x2F:  /* MDAP */
   8151           Ins_MDAP( exc, args );
   8152           break;
   8153 
   8154         case 0x30:  /* IUP */
   8155         case 0x31:  /* IUP */
   8156           Ins_IUP( exc );
   8157           break;
   8158 
   8159         case 0x32:  /* SHP */
   8160         case 0x33:  /* SHP */
   8161           Ins_SHP( exc );
   8162           break;
   8163 
   8164         case 0x34:  /* SHC */
   8165         case 0x35:  /* SHC */
   8166           Ins_SHC( exc, args );
   8167           break;
   8168 
   8169         case 0x36:  /* SHZ */
   8170         case 0x37:  /* SHZ */
   8171           Ins_SHZ( exc, args );
   8172           break;
   8173 
   8174         case 0x38:  /* SHPIX */
   8175           Ins_SHPIX( exc, args );
   8176           break;
   8177 
   8178         case 0x39:  /* IP    */
   8179           Ins_IP( exc );
   8180           break;
   8181 
   8182         case 0x3A:  /* MSIRP */
   8183         case 0x3B:  /* MSIRP */
   8184           Ins_MSIRP( exc, args );
   8185           break;
   8186 
   8187         case 0x3C:  /* AlignRP */
   8188           Ins_ALIGNRP( exc );
   8189           break;
   8190 
   8191         case 0x3D:  /* RTDG */
   8192           Ins_RTDG( exc );
   8193           break;
   8194 
   8195         case 0x3E:  /* MIAP */
   8196         case 0x3F:  /* MIAP */
   8197           Ins_MIAP( exc, args );
   8198           break;
   8199 
   8200         case 0x40:  /* NPUSHB */
   8201           Ins_NPUSHB( exc, args );
   8202           break;
   8203 
   8204         case 0x41:  /* NPUSHW */
   8205           Ins_NPUSHW( exc, args );
   8206           break;
   8207 
   8208         case 0x42:  /* WS */
   8209           Ins_WS( exc, args );
   8210           break;
   8211 
   8212         case 0x43:  /* RS */
   8213           Ins_RS( exc, args );
   8214           break;
   8215 
   8216         case 0x44:  /* WCVTP */
   8217           Ins_WCVTP( exc, args );
   8218           break;
   8219 
   8220         case 0x45:  /* RCVT */
   8221           Ins_RCVT( exc, args );
   8222           break;
   8223 
   8224         case 0x46:  /* GC */
   8225         case 0x47:  /* GC */
   8226           Ins_GC( exc, args );
   8227           break;
   8228 
   8229         case 0x48:  /* SCFS */
   8230           Ins_SCFS( exc, args );
   8231           break;
   8232 
   8233         case 0x49:  /* MD */
   8234         case 0x4A:  /* MD */
   8235           Ins_MD( exc, args );
   8236           break;
   8237 
   8238         case 0x4B:  /* MPPEM */
   8239           Ins_MPPEM( exc, args );
   8240           break;
   8241 
   8242         case 0x4C:  /* MPS */
   8243           Ins_MPS( exc, args );
   8244           break;
   8245 
   8246         case 0x4D:  /* FLIPON */
   8247           Ins_FLIPON( exc );
   8248           break;
   8249 
   8250         case 0x4E:  /* FLIPOFF */
   8251           Ins_FLIPOFF( exc );
   8252           break;
   8253 
   8254         case 0x4F:  /* DEBUG */
   8255           Ins_DEBUG( exc );
   8256           break;
   8257 
   8258         case 0x50:  /* LT */
   8259           Ins_LT( args );
   8260           break;
   8261 
   8262         case 0x51:  /* LTEQ */
   8263           Ins_LTEQ( args );
   8264           break;
   8265 
   8266         case 0x52:  /* GT */
   8267           Ins_GT( args );
   8268           break;
   8269 
   8270         case 0x53:  /* GTEQ */
   8271           Ins_GTEQ( args );
   8272           break;
   8273 
   8274         case 0x54:  /* EQ */
   8275           Ins_EQ( args );
   8276           break;
   8277 
   8278         case 0x55:  /* NEQ */
   8279           Ins_NEQ( args );
   8280           break;
   8281 
   8282         case 0x56:  /* ODD */
   8283           Ins_ODD( exc, args );
   8284           break;
   8285 
   8286         case 0x57:  /* EVEN */
   8287           Ins_EVEN( exc, args );
   8288           break;
   8289 
   8290         case 0x58:  /* IF */
   8291           Ins_IF( exc, args );
   8292           break;
   8293 
   8294         case 0x59:  /* EIF */
   8295           Ins_EIF();
   8296           break;
   8297 
   8298         case 0x5A:  /* AND */
   8299           Ins_AND( args );
   8300           break;
   8301 
   8302         case 0x5B:  /* OR */
   8303           Ins_OR( args );
   8304           break;
   8305 
   8306         case 0x5C:  /* NOT */
   8307           Ins_NOT( args );
   8308           break;
   8309 
   8310         case 0x5D:  /* DELTAP1 */
   8311           Ins_DELTAP( exc, args );
   8312           break;
   8313 
   8314         case 0x5E:  /* SDB */
   8315           Ins_SDB( exc, args );
   8316           break;
   8317 
   8318         case 0x5F:  /* SDS */
   8319           Ins_SDS( exc, args );
   8320           break;
   8321 
   8322         case 0x60:  /* ADD */
   8323           Ins_ADD( args );
   8324           break;
   8325 
   8326         case 0x61:  /* SUB */
   8327           Ins_SUB( args );
   8328           break;
   8329 
   8330         case 0x62:  /* DIV */
   8331           Ins_DIV( exc, args );
   8332           break;
   8333 
   8334         case 0x63:  /* MUL */
   8335           Ins_MUL( args );
   8336           break;
   8337 
   8338         case 0x64:  /* ABS */
   8339           Ins_ABS( args );
   8340           break;
   8341 
   8342         case 0x65:  /* NEG */
   8343           Ins_NEG( args );
   8344           break;
   8345 
   8346         case 0x66:  /* FLOOR */
   8347           Ins_FLOOR( args );
   8348           break;
   8349 
   8350         case 0x67:  /* CEILING */
   8351           Ins_CEILING( args );
   8352           break;
   8353 
   8354         case 0x68:  /* ROUND */
   8355         case 0x69:  /* ROUND */
   8356         case 0x6A:  /* ROUND */
   8357         case 0x6B:  /* ROUND */
   8358           Ins_ROUND( exc, args );
   8359           break;
   8360 
   8361         case 0x6C:  /* NROUND */
   8362         case 0x6D:  /* NROUND */
   8363         case 0x6E:  /* NRRUND */
   8364         case 0x6F:  /* NROUND */
   8365           Ins_NROUND( exc, args );
   8366           break;
   8367 
   8368         case 0x70:  /* WCVTF */
   8369           Ins_WCVTF( exc, args );
   8370           break;
   8371 
   8372         case 0x71:  /* DELTAP2 */
   8373         case 0x72:  /* DELTAP3 */
   8374           Ins_DELTAP( exc, args );
   8375           break;
   8376 
   8377         case 0x73:  /* DELTAC0 */
   8378         case 0x74:  /* DELTAC1 */
   8379         case 0x75:  /* DELTAC2 */
   8380           Ins_DELTAC( exc, args );
   8381           break;
   8382 
   8383         case 0x76:  /* SROUND */
   8384           Ins_SROUND( exc, args );
   8385           break;
   8386 
   8387         case 0x77:  /* S45Round */
   8388           Ins_S45ROUND( exc, args );
   8389           break;
   8390 
   8391         case 0x78:  /* JROT */
   8392           Ins_JROT( exc, args );
   8393           break;
   8394 
   8395         case 0x79:  /* JROF */
   8396           Ins_JROF( exc, args );
   8397           break;
   8398 
   8399         case 0x7A:  /* ROFF */
   8400           Ins_ROFF( exc );
   8401           break;
   8402 
   8403         case 0x7B:  /* ???? */
   8404           Ins_UNKNOWN( exc );
   8405           break;
   8406 
   8407         case 0x7C:  /* RUTG */
   8408           Ins_RUTG( exc );
   8409           break;
   8410 
   8411         case 0x7D:  /* RDTG */
   8412           Ins_RDTG( exc );
   8413           break;
   8414 
   8415         case 0x7E:  /* SANGW */
   8416           Ins_SANGW();
   8417           break;
   8418 
   8419         case 0x7F:  /* AA */
   8420           Ins_AA();
   8421           break;
   8422 
   8423         case 0x80:  /* FLIPPT */
   8424           Ins_FLIPPT( exc );
   8425           break;
   8426 
   8427         case 0x81:  /* FLIPRGON */
   8428           Ins_FLIPRGON( exc, args );
   8429           break;
   8430 
   8431         case 0x82:  /* FLIPRGOFF */
   8432           Ins_FLIPRGOFF( exc, args );
   8433           break;
   8434 
   8435         case 0x83:  /* UNKNOWN */
   8436         case 0x84:  /* UNKNOWN */
   8437           Ins_UNKNOWN( exc );
   8438           break;
   8439 
   8440         case 0x85:  /* SCANCTRL */
   8441           Ins_SCANCTRL( exc, args );
   8442           break;
   8443 
   8444         case 0x86:  /* SDPvTL */
   8445         case 0x87:  /* SDPvTL */
   8446           Ins_SDPVTL( exc, args );
   8447           break;
   8448 
   8449         case 0x88:  /* GETINFO */
   8450           Ins_GETINFO( exc, args );
   8451           break;
   8452 
   8453         case 0x89:  /* IDEF */
   8454           Ins_IDEF( exc, args );
   8455           break;
   8456 
   8457         case 0x8A:  /* ROLL */
   8458           Ins_ROLL( args );
   8459           break;
   8460 
   8461         case 0x8B:  /* MAX */
   8462           Ins_MAX( args );
   8463           break;
   8464 
   8465         case 0x8C:  /* MIN */
   8466           Ins_MIN( args );
   8467           break;
   8468 
   8469         case 0x8D:  /* SCANTYPE */
   8470           Ins_SCANTYPE( exc, args );
   8471           break;
   8472 
   8473         case 0x8E:  /* INSTCTRL */
   8474           Ins_INSTCTRL( exc, args );
   8475           break;
   8476 
   8477         case 0x8F:  /* ADJUST */
   8478         case 0x90:  /* ADJUST */
   8479           Ins_UNKNOWN( exc );
   8480           break;
   8481 
   8482 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   8483         case 0x91:
   8484           /* it is the job of the application to `activate' GX handling, */
   8485           /* this is, calling any of the GX API functions on the current */
   8486           /* font to select a variation instance                         */
   8487           if ( exc->face->blend )
   8488             Ins_GETVARIATION( exc, args );
   8489           else
   8490             Ins_UNKNOWN( exc );
   8491           break;
   8492 
   8493         case 0x92:
   8494           /* there is at least one MS font (LaoUI.ttf version 5.01) that */
   8495           /* uses IDEFs for 0x91 and 0x92; for this reason we activate   */
   8496           /* GETDATA for GX fonts only, similar to GETVARIATION          */
   8497           if ( exc->face->blend )
   8498             Ins_GETDATA( args );
   8499           else
   8500             Ins_UNKNOWN( exc );
   8501           break;
   8502 #endif
   8503 
   8504         default:
   8505           if ( opcode >= 0xE0 )
   8506             Ins_MIRP( exc, args );
   8507           else if ( opcode >= 0xC0 )
   8508             Ins_MDRP( exc, args );
   8509           else if ( opcode >= 0xB8 )
   8510             Ins_PUSHW( exc, args );
   8511           else if ( opcode >= 0xB0 )
   8512             Ins_PUSHB( exc, args );
   8513           else
   8514             Ins_UNKNOWN( exc );
   8515         }
   8516       }
   8517 
   8518       if ( exc->error )
   8519       {
   8520         switch ( exc->error )
   8521         {
   8522           /* looking for redefined instructions */
   8523         case FT_ERR( Invalid_Opcode ):
   8524           {
   8525             TT_DefRecord*  def   = exc->IDefs;
   8526             TT_DefRecord*  limit = def + exc->numIDefs;
   8527 
   8528 
   8529             for ( ; def < limit; def++ )
   8530             {
   8531               if ( def->active && exc->opcode == (FT_Byte)def->opc )
   8532               {
   8533                 TT_CallRec*  callrec;
   8534 
   8535 
   8536                 if ( exc->callTop >= exc->callSize )
   8537                 {
   8538                   exc->error = FT_THROW( Invalid_Reference );
   8539                   goto LErrorLabel_;
   8540                 }
   8541 
   8542                 callrec = &exc->callStack[exc->callTop];
   8543 
   8544                 callrec->Caller_Range = exc->curRange;
   8545                 callrec->Caller_IP    = exc->IP + 1;
   8546                 callrec->Cur_Count    = 1;
   8547                 callrec->Def          = def;
   8548 
   8549                 if ( Ins_Goto_CodeRange( exc,
   8550                                          def->range,
   8551                                          def->start ) == FAILURE )
   8552                   goto LErrorLabel_;
   8553 
   8554                 goto LSuiteLabel_;
   8555               }
   8556             }
   8557           }
   8558 
   8559           exc->error = FT_THROW( Invalid_Opcode );
   8560           goto LErrorLabel_;
   8561 
   8562 #if 0
   8563           break;   /* Unreachable code warning suppression.             */
   8564                    /* Leave to remind in case a later change the editor */
   8565                    /* to consider break;                                */
   8566 #endif
   8567 
   8568         default:
   8569           goto LErrorLabel_;
   8570 
   8571 #if 0
   8572         break;
   8573 #endif
   8574         }
   8575       }
   8576 
   8577       exc->top = exc->new_top;
   8578 
   8579       if ( exc->step_ins )
   8580         exc->IP += exc->length;
   8581 
   8582       /* increment instruction counter and check if we didn't */
   8583       /* run this program for too long (e.g. infinite loops). */
   8584       if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
   8585         return FT_THROW( Execution_Too_Long );
   8586 
   8587     LSuiteLabel_:
   8588       if ( exc->IP >= exc->codeSize )
   8589       {
   8590         if ( exc->callTop > 0 )
   8591         {
   8592           exc->error = FT_THROW( Code_Overflow );
   8593           goto LErrorLabel_;
   8594         }
   8595         else
   8596           goto LNo_Error_;
   8597       }
   8598     } while ( !exc->instruction_trap );
   8599 
   8600   LNo_Error_:
   8601     FT_TRACE4(( "  %d instruction%s executed\n",
   8602                 ins_counter,
   8603                 ins_counter == 1 ? "" : "s" ));
   8604     return FT_Err_Ok;
   8605 
   8606   LErrorCodeOverflow_:
   8607     exc->error = FT_THROW( Code_Overflow );
   8608 
   8609   LErrorLabel_:
   8610     if ( exc->error && !exc->instruction_trap )
   8611       FT_TRACE1(( "  The interpreter returned error 0x%x\n", exc->error ));
   8612 
   8613     return exc->error;
   8614   }
   8615 
   8616 #else /* !TT_USE_BYTECODE_INTERPRETER */
   8617 
   8618   /* ANSI C doesn't like empty source files */
   8619   typedef int  _tt_interp_dummy;
   8620 
   8621 #endif /* !TT_USE_BYTECODE_INTERPRETER */
   8622 
   8623 
   8624 /* END */
   8625