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