Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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