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