Delete all Trailing spaces in code.
[reactos.git] / reactos / dll / 3rdparty / freetype / src / truetype / ttinterp.c
index 85c8529..78488f2 100644 (file)
-/***************************************************************************/
-/*                                                                         */
-/*  ttinterp.c                                                             */
-/*                                                                         */
-/*    TrueType bytecode interpreter (body).                                */
-/*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by             */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  modified, and distributed under the terms of the FreeType project      */
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
-/*  this file you indicate that you have read the license and              */
-/*  understand and accept it fully.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_CALC_H
-#include FT_TRIGONOMETRY_H
-#include FT_SYSTEM_H
-
-#include "ttinterp.h"
-
-#include "tterrors.h"
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
-
-#define TT_MULFIX           FT_MulFix
-#define TT_MULDIV           FT_MulDiv
-#define TT_MULDIV_NO_ROUND  FT_MulDiv_No_Round
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_ttinterp
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* In order to detect infinite loops in the code, we set up a counter    */
-  /* within the run loop.  A single stroke of interpretation is now        */
-  /* limited to a maximal number of opcodes defined below.                 */
-  /*                                                                       */
-#define MAX_RUNNABLE_OPCODES  1000000L
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* There are two kinds of implementations:                               */
-  /*                                                                       */
-  /* a. static implementation                                              */
-  /*                                                                       */
-  /*    The current execution context is a static variable, which fields   */
-  /*    are accessed directly by the interpreter during execution.  The    */
-  /*    context is named `cur'.                                            */
-  /*                                                                       */
-  /*    This version is non-reentrant, of course.                          */
-  /*                                                                       */
-  /* b. indirect implementation                                            */
-  /*                                                                       */
-  /*    The current execution context is passed to _each_ function as its  */
-  /*    first argument, and each field is thus accessed indirectly.        */
-  /*                                                                       */
-  /*    This version is fully re-entrant.                                  */
-  /*                                                                       */
-  /* The idea is that an indirect implementation may be slower to execute  */
-  /* on low-end processors that are used in some systems (like 386s or     */
-  /* even 486s).                                                           */
-  /*                                                                       */
-  /* As a consequence, the indirect implementation is now the default, as  */
-  /* its performance costs can be considered negligible in our context.    */
-  /* Note, however, that we kept the same source with macros because:      */
-  /*                                                                       */
-  /* - The code is kept very close in design to the Pascal code used for   */
-  /*   development.                                                        */
-  /*                                                                       */
-  /* - It's much more readable that way!                                   */
-  /*                                                                       */
-  /* - It's still open to experimentation and tuning.                      */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */
-
-#define CUR  (*exc)                             /* see ttobjs.h */
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* This macro is used whenever `exec' is unused in a function, to avoid  */
-  /* stupid warnings from pedantic compilers.                              */
-  /*                                                                       */
-#define FT_UNUSED_EXEC  FT_UNUSED( exc )
-
-#else                                           /* static implementation */
-
-#define CUR  cur
-
-#define FT_UNUSED_EXEC  int  __dummy = __dummy
-
-  static
-  TT_ExecContextRec  cur;   /* static exec. context variable */
-
-  /* apparently, we have a _lot_ of direct indexing when accessing  */
-  /* the static `cur', which makes the code bigger (due to all the  */
-  /* four bytes addresses).                                         */
-
-#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The instruction argument stack.                                       */
-  /*                                                                       */
-#define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* This macro is used whenever `args' is unused in a function, to avoid  */
-  /* stupid warnings from pedantic compilers.                              */
-  /*                                                                       */
-#define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
-  /* increase readability of the code.                                     */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#define SKIP_Code() \
-          SkipCode( EXEC_ARG )
-
-#define GET_ShortIns() \
-          GetShortIns( EXEC_ARG )
-
-#define NORMalize( x, y, v ) \
-          Normalize( EXEC_ARG_ x, y, v )
-
-#define SET_SuperRound( scale, flags ) \
-          SetSuperRound( EXEC_ARG_ scale, flags )
-
-#define ROUND_None( d, c ) \
-          Round_None( EXEC_ARG_ d, c )
-
-#define INS_Goto_CodeRange( range, ip ) \
-          Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
-
-#define CUR_Func_move( z, p, d ) \
-          CUR.func_move( EXEC_ARG_ z, p, d )
-
-#define CUR_Func_move_orig( z, p, d ) \
-          CUR.func_move_orig( EXEC_ARG_ z, p, d )
-
-#define CUR_Func_round( d, c ) \
-          CUR.func_round( EXEC_ARG_ d, c )
-
-#define CUR_Func_read_cvt( index ) \
-          CUR.func_read_cvt( EXEC_ARG_ index )
-
-#define CUR_Func_write_cvt( index, val ) \
-          CUR.func_write_cvt( EXEC_ARG_ index, val )
-
-#define CUR_Func_move_cvt( index, val ) \
-          CUR.func_move_cvt( EXEC_ARG_ index, val )
-
-#define CURRENT_Ratio() \
-          Current_Ratio( EXEC_ARG )
-
-#define CURRENT_Ppem() \
-          Current_Ppem( EXEC_ARG )
-
-#define CUR_Ppem() \
-          Cur_PPEM( EXEC_ARG )
-
-#define INS_SxVTL( a, b, c, d ) \
-          Ins_SxVTL( EXEC_ARG_ a, b, c, d )
-
-#define COMPUTE_Funcs() \
-          Compute_Funcs( EXEC_ARG )
-
-#define COMPUTE_Round( a ) \
-          Compute_Round( EXEC_ARG_ a )
-
-#define COMPUTE_Point_Displacement( a, b, c, d ) \
-          Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
-
-#define MOVE_Zp2_Point( a, b, c, t ) \
-          Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
-
-
-#define CUR_Func_project( v1, v2 )  \
-          CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define CUR_Func_dualproj( v1, v2 )  \
-          CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define CUR_fast_project( v ) \
-          CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
-
-#define CUR_fast_dualproj( v ) \
-          CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Instruction dispatch function, as used by the interpreter.            */
-  /*                                                                       */
-  typedef void  (*TInstruction_Function)( INS_ARG );
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* A simple bounds-checking macro.                                       */
-  /*                                                                       */
-#define BOUNDS( x, n )  ( (FT_UInt)(x) >= (FT_UInt)(n) )
-
-#undef  SUCCESS
-#define SUCCESS  0
-
-#undef  FAILURE
-#define FAILURE  1
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define GUESS_VECTOR( V )                                         \
-  if ( CUR.face->unpatented_hinting )                             \
-  {                                                               \
-    CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
-    CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
-  }
-#else
-#define GUESS_VECTOR( V )
-#endif
-
-  /*************************************************************************/
-  /*                                                                       */
-  /*                        CODERANGE FUNCTIONS                            */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Goto_CodeRange                                                  */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Switches to a new code range (updates the code related elements in */
-  /*    `exec', and `IP').                                                 */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    range :: The new execution code range.                             */
-  /*                                                                       */
-  /*    IP    :: The new IP in the new code range.                         */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    exec  :: The target execution context.                             */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Goto_CodeRange( TT_ExecContext  exec,
-                     FT_Int          range,
-                     FT_Long         IP )
-  {
-    TT_CodeRange*  coderange;
-
-
-    FT_ASSERT( range >= 1 && range <= 3 );
-
-    coderange = &exec->codeRangeTable[range - 1];
-
-    FT_ASSERT( coderange->base != NULL );
-
-    /* NOTE: Because the last instruction of a program may be a CALL */
-    /*       which will return to the first byte *after* the code    */
-    /*       range, we test for IP <= Size instead of IP < Size.     */
-    /*                                                               */
-    FT_ASSERT( (FT_ULong)IP <= coderange->size );
-
-    exec->code     = coderange->base;
-    exec->codeSize = coderange->size;
-    exec->IP       = IP;
-    exec->curRange = range;
-
-    return TT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Set_CodeRange                                                   */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Sets a code range.                                                 */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    range  :: The code range index.                                    */
-  /*                                                                       */
-  /*    base   :: The new code base.                                       */
-  /*                                                                       */
-  /*    length :: The range size in bytes.                                 */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    exec   :: The target execution context.                            */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Set_CodeRange( TT_ExecContext  exec,
-                    FT_Int          range,
-                    void*           base,
-                    FT_Long         length )
-  {
-    FT_ASSERT( range >= 1 && range <= 3 );
-
-    exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
-    exec->codeRangeTable[range - 1].size = length;
-
-    return TT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Clear_CodeRange                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Clears a code range.                                               */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    range :: The code range index.                                     */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    exec  :: The target execution context.                             */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    Does not set the Error variable.                                   */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Clear_CodeRange( TT_ExecContext  exec,
-                      FT_Int          range )
-  {
-    FT_ASSERT( range >= 1 && range <= 3 );
-
-    exec->codeRangeTable[range - 1].base = NULL;
-    exec->codeRangeTable[range - 1].size = 0;
-
-    return TT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /*                   EXECUTION CONTEXT ROUTINES                          */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Done_Context                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Destroys a given context.                                          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    exec   :: A handle to the target execution context.                */
-  /*                                                                       */
-  /*    memory :: A handle to the parent memory object.                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    Only the glyph loader and debugger should call this function.      */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Done_Context( TT_ExecContext  exec )
-  {
-    FT_Memory  memory = exec->memory;
-
-
-    /* points zone */
-    exec->maxPoints   = 0;
-    exec->maxContours = 0;
-
-    /* free stack */
-    FT_FREE( exec->stack );
-    exec->stackSize = 0;
-
-    /* free call stack */
-    FT_FREE( exec->callStack );
-    exec->callSize = 0;
-    exec->callTop  = 0;
-
-    /* free glyph code range */
-    FT_FREE( exec->glyphIns );
-    exec->glyphSize = 0;
-
-    exec->size = NULL;
-    exec->face = NULL;
-
-    FT_FREE( exec );
-
-    return TT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Init_Context                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Initializes a context object.                                      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    memory :: A handle to the parent memory object.                    */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    exec   :: A handle to the target execution context.                */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
-  Init_Context( TT_ExecContext  exec,
-                FT_Memory       memory )
-  {
-    FT_Error  error;
-
-
-    FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
-
-    exec->memory   = memory;
-    exec->callSize = 32;
-
-    if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
-      goto Fail_Memory;
-
-    /* all values in the context are set to 0 already, but this is */
-    /* here as a remainder                                         */
-    exec->maxPoints   = 0;
-    exec->maxContours = 0;
-
-    exec->stackSize = 0;
-    exec->glyphSize = 0;
-
-    exec->stack     = NULL;
-    exec->glyphIns  = NULL;
-
-    exec->face = NULL;
-    exec->size = NULL;
-
-    return TT_Err_Ok;
-
-  Fail_Memory:
-    FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
-               (FT_Long)exec ));
-    TT_Done_Context( exec );
-
-    return error;
- }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Update_Max                                                         */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Checks the size of a buffer and reallocates it if necessary.       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    memory     :: A handle to the parent memory object.                */
-  /*                                                                       */
-  /*    multiplier :: The size in bytes of each element in the buffer.     */
-  /*                                                                       */
-  /*    new_max    :: The new capacity (size) of the buffer.               */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    size       :: The address of the buffer's current size expressed   */
-  /*                  in elements.                                         */
-  /*                                                                       */
-  /*    buff       :: The address of the buffer base pointer.              */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
-  Update_Max( FT_Memory  memory,
-              FT_ULong*  size,
-              FT_Long    multiplier,
-              void*      _pbuff,
-              FT_ULong   new_max )
-  {
-    FT_Error  error;
-    void**    pbuff = (void**)_pbuff;
-
-
-    if ( *size < new_max )
-    {
-      if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
-        return error;
-      *size = new_max;
-    }
-
-    return TT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Load_Context                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Prepare an execution context for glyph hinting.                    */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face :: A handle to the source face object.                        */
-  /*                                                                       */
-  /*    size :: A handle to the source size object.                        */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    exec :: A handle to the target execution context.                  */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    Only the glyph loader and debugger should call this function.      */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Load_Context( TT_ExecContext  exec,
-                   TT_Face         face,
-                   TT_Size         size )
-  {
-    FT_Int          i;
-    FT_ULong        tmp;
-    TT_MaxProfile*  maxp;
-    FT_Error        error;
-
-
-    exec->face = face;
-    maxp       = &face->max_profile;
-    exec->size = size;
-
-    if ( size )
-    {
-      exec->numFDefs   = size->num_function_defs;
-      exec->maxFDefs   = size->max_function_defs;
-      exec->numIDefs   = size->num_instruction_defs;
-      exec->maxIDefs   = size->max_instruction_defs;
-      exec->FDefs      = size->function_defs;
-      exec->IDefs      = size->instruction_defs;
-      exec->tt_metrics = size->ttmetrics;
-      exec->metrics    = size->metrics;
-
-      exec->maxFunc    = size->max_func;
-      exec->maxIns     = size->max_ins;
-
-      for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
-        exec->codeRangeTable[i] = size->codeRangeTable[i];
-
-      /* set graphics state */
-      exec->GS = size->GS;
-
-      exec->cvtSize = size->cvt_size;
-      exec->cvt     = size->cvt;
-
-      exec->storeSize = size->storage_size;
-      exec->storage   = size->storage;
-
-      exec->twilight  = size->twilight;
-    }
-
-    /* XXX: We reserve a little more elements on the stack to deal safely */
-    /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
-    tmp = exec->stackSize;
-    error = Update_Max( exec->memory,
-                        &tmp,
-                        sizeof ( FT_F26Dot6 ),
-                        (void*)&exec->stack,
-                        maxp->maxStackElements + 32 );
-    exec->stackSize = (FT_UInt)tmp;
-    if ( error )
-      return error;
-
-    tmp = exec->glyphSize;
-    error = Update_Max( exec->memory,
-                        &tmp,
-                        sizeof ( FT_Byte ),
-                        (void*)&exec->glyphIns,
-                        maxp->maxSizeOfInstructions );
-    exec->glyphSize = (FT_UShort)tmp;
-    if ( error )
-      return error;
-
-    exec->pts.n_points   = 0;
-    exec->pts.n_contours = 0;
-
-    exec->zp1 = exec->pts;
-    exec->zp2 = exec->pts;
-    exec->zp0 = exec->pts;
-
-    exec->instruction_trap = FALSE;
-
-    return TT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Save_Context                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Saves the code ranges in a `size' object.                          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    exec :: A handle to the source execution context.                  */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    size :: A handle to the target size object.                        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    Only the glyph loader and debugger should call this function.      */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Save_Context( TT_ExecContext  exec,
-                   TT_Size         size )
-  {
-    FT_Int  i;
-
-
-    /* XXXX: Will probably disappear soon with all the code range */
-    /*       management, which is now rather obsolete.            */
-    /*                                                            */
-    size->num_function_defs    = exec->numFDefs;
-    size->num_instruction_defs = exec->numIDefs;
-
-    size->max_func = exec->maxFunc;
-    size->max_ins  = exec->maxIns;
-
-    for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
-      size->codeRangeTable[i] = exec->codeRangeTable[i];
-
-    return TT_Err_Ok;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Run_Context                                                     */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Executes one or more instructions in the execution context.        */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    debug :: A Boolean flag.  If set, the function sets some internal  */
-  /*             variables and returns immediately, otherwise TT_RunIns()  */
-  /*             is called.                                                */
-  /*                                                                       */
-  /*             This is commented out currently.                          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    exec  :: A handle to the target execution context.                 */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    TrueTyoe error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    Only the glyph loader and debugger should call this function.      */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Run_Context( TT_ExecContext  exec,
-                  FT_Bool         debug )
-  {
-    FT_Error  error;
-
-
-    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0  ) )
-           != TT_Err_Ok )
-      return error;
-
-    exec->zp0 = exec->pts;
-    exec->zp1 = exec->pts;
-    exec->zp2 = exec->pts;
-
-    exec->GS.gep0 = 1;
-    exec->GS.gep1 = 1;
-    exec->GS.gep2 = 1;
-
-    exec->GS.projVector.x = 0x4000;
-    exec->GS.projVector.y = 0x0000;
-
-    exec->GS.freeVector = exec->GS.projVector;
-    exec->GS.dualVector = exec->GS.projVector;
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    exec->GS.both_x_axis = TRUE;
-#endif
-
-    exec->GS.round_state = 1;
-    exec->GS.loop        = 1;
-
-    /* some glyphs leave something on the stack. so we clean it */
-    /* before a new execution.                                  */
-    exec->top     = 0;
-    exec->callTop = 0;
-
-#if 1
-    FT_UNUSED( debug );
-
-    return exec->face->interpreter( exec );
-#else
-    if ( !debug )
-      return TT_RunIns( exec );
-    else
-      return TT_Err_Ok;
-#endif
-  }
-
-
-  const TT_GraphicsState  tt_default_graphics_state =
-  {
-    0, 0, 0,
-    { 0x4000, 0 },
-    { 0x4000, 0 },
-    { 0x4000, 0 },
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    TRUE,
-#endif
-
-    1, 64, 1,
-    TRUE, 68, 0, 0, 9, 3,
-    0, FALSE, 2, 1, 1, 1
-  };
-
-
-  /* documentation is in ttinterp.h */
-
-  FT_EXPORT_DEF( TT_ExecContext )
-  TT_New_Context( TT_Driver  driver )
-  {
-    TT_ExecContext  exec;
-    FT_Memory       memory;
-
-
-    memory = driver->root.root.memory;
-    exec   = driver->context;
-
-    if ( !driver->context )
-    {
-      FT_Error  error;
-
-
-      /* allocate object */
-      if ( FT_NEW( exec ) )
-        goto Exit;
-
-      /* initialize it */
-      error = Init_Context( exec, memory );
-      if ( error )
-        goto Fail;
-
-      /* store it into the driver */
-      driver->context = exec;
-    }
-
-  Exit:
-    return driver->context;
-
-  Fail:
-    FT_FREE( exec );
-
-    return 0;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Before an opcode is executed, the interpreter verifies that there are */
-  /* enough arguments on the stack, with the help of the `Pop_Push_Count'  */
-  /* table.                                                                */
-  /*                                                                       */
-  /* For each opcode, the first column gives the number of arguments that  */
-  /* are popped from the stack; the second one gives the number of those   */
-  /* that are pushed in result.                                            */
-  /*                                                                       */
-  /* Opcodes which have a varying number of parameters in the data stream  */
-  /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
-  /* the `opcode_length' table, and the value in `Pop_Push_Count' is set   */
-  /* to zero.                                                              */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#undef  PACK
-#define PACK( x, y )  ( ( x << 4 ) | y )
-
-
-  static
-  const FT_Byte  Pop_Push_Count[256] =
-  {
-    /* opcodes are gathered in groups of 16 */
-    /* please keep the spaces as they are   */
-
-    /*  SVTCA  y  */  PACK( 0, 0 ),
-    /*  SVTCA  x  */  PACK( 0, 0 ),
-    /*  SPvTCA y  */  PACK( 0, 0 ),
-    /*  SPvTCA x  */  PACK( 0, 0 ),
-    /*  SFvTCA y  */  PACK( 0, 0 ),
-    /*  SFvTCA x  */  PACK( 0, 0 ),
-    /*  SPvTL //  */  PACK( 2, 0 ),
-    /*  SPvTL +   */  PACK( 2, 0 ),
-    /*  SFvTL //  */  PACK( 2, 0 ),
-    /*  SFvTL +   */  PACK( 2, 0 ),
-    /*  SPvFS     */  PACK( 2, 0 ),
-    /*  SFvFS     */  PACK( 2, 0 ),
-    /*  GPV       */  PACK( 0, 2 ),
-    /*  GFV       */  PACK( 0, 2 ),
-    /*  SFvTPv    */  PACK( 0, 0 ),
-    /*  ISECT     */  PACK( 5, 0 ),
-
-    /*  SRP0      */  PACK( 1, 0 ),
-    /*  SRP1      */  PACK( 1, 0 ),
-    /*  SRP2      */  PACK( 1, 0 ),
-    /*  SZP0      */  PACK( 1, 0 ),
-    /*  SZP1      */  PACK( 1, 0 ),
-    /*  SZP2      */  PACK( 1, 0 ),
-    /*  SZPS      */  PACK( 1, 0 ),
-    /*  SLOOP     */  PACK( 1, 0 ),
-    /*  RTG       */  PACK( 0, 0 ),
-    /*  RTHG      */  PACK( 0, 0 ),
-    /*  SMD       */  PACK( 1, 0 ),
-    /*  ELSE      */  PACK( 0, 0 ),
-    /*  JMPR      */  PACK( 1, 0 ),
-    /*  SCvTCi    */  PACK( 1, 0 ),
-    /*  SSwCi     */  PACK( 1, 0 ),
-    /*  SSW       */  PACK( 1, 0 ),
-
-    /*  DUP       */  PACK( 1, 2 ),
-    /*  POP       */  PACK( 1, 0 ),
-    /*  CLEAR     */  PACK( 0, 0 ),
-    /*  SWAP      */  PACK( 2, 2 ),
-    /*  DEPTH     */  PACK( 0, 1 ),
-    /*  CINDEX    */  PACK( 1, 1 ),
-    /*  MINDEX    */  PACK( 1, 0 ),
-    /*  AlignPTS  */  PACK( 2, 0 ),
-    /*  INS_$28   */  PACK( 0, 0 ),
-    /*  UTP       */  PACK( 1, 0 ),
-    /*  LOOPCALL  */  PACK( 2, 0 ),
-    /*  CALL      */  PACK( 1, 0 ),
-    /*  FDEF      */  PACK( 1, 0 ),
-    /*  ENDF      */  PACK( 0, 0 ),
-    /*  MDAP[0]   */  PACK( 1, 0 ),
-    /*  MDAP[1]   */  PACK( 1, 0 ),
-
-    /*  IUP[0]    */  PACK( 0, 0 ),
-    /*  IUP[1]    */  PACK( 0, 0 ),
-    /*  SHP[0]    */  PACK( 0, 0 ),
-    /*  SHP[1]    */  PACK( 0, 0 ),
-    /*  SHC[0]    */  PACK( 1, 0 ),
-    /*  SHC[1]    */  PACK( 1, 0 ),
-    /*  SHZ[0]    */  PACK( 1, 0 ),
-    /*  SHZ[1]    */  PACK( 1, 0 ),
-    /*  SHPIX     */  PACK( 1, 0 ),
-    /*  IP        */  PACK( 0, 0 ),
-    /*  MSIRP[0]  */  PACK( 2, 0 ),
-    /*  MSIRP[1]  */  PACK( 2, 0 ),
-    /*  AlignRP   */  PACK( 0, 0 ),
-    /*  RTDG      */  PACK( 0, 0 ),
-    /*  MIAP[0]   */  PACK( 2, 0 ),
-    /*  MIAP[1]   */  PACK( 2, 0 ),
-
-    /*  NPushB    */  PACK( 0, 0 ),
-    /*  NPushW    */  PACK( 0, 0 ),
-    /*  WS        */  PACK( 2, 0 ),
-    /*  RS        */  PACK( 1, 1 ),
-    /*  WCvtP     */  PACK( 2, 0 ),
-    /*  RCvt      */  PACK( 1, 1 ),
-    /*  GC[0]     */  PACK( 1, 1 ),
-    /*  GC[1]     */  PACK( 1, 1 ),
-    /*  SCFS      */  PACK( 2, 0 ),
-    /*  MD[0]     */  PACK( 2, 1 ),
-    /*  MD[1]     */  PACK( 2, 1 ),
-    /*  MPPEM     */  PACK( 0, 1 ),
-    /*  MPS       */  PACK( 0, 1 ),
-    /*  FlipON    */  PACK( 0, 0 ),
-    /*  FlipOFF   */  PACK( 0, 0 ),
-    /*  DEBUG     */  PACK( 1, 0 ),
-
-    /*  LT        */  PACK( 2, 1 ),
-    /*  LTEQ      */  PACK( 2, 1 ),
-    /*  GT        */  PACK( 2, 1 ),
-    /*  GTEQ      */  PACK( 2, 1 ),
-    /*  EQ        */  PACK( 2, 1 ),
-    /*  NEQ       */  PACK( 2, 1 ),
-    /*  ODD       */  PACK( 1, 1 ),
-    /*  EVEN      */  PACK( 1, 1 ),
-    /*  IF        */  PACK( 1, 0 ),
-    /*  EIF       */  PACK( 0, 0 ),
-    /*  AND       */  PACK( 2, 1 ),
-    /*  OR        */  PACK( 2, 1 ),
-    /*  NOT       */  PACK( 1, 1 ),
-    /*  DeltaP1   */  PACK( 1, 0 ),
-    /*  SDB       */  PACK( 1, 0 ),
-    /*  SDS       */  PACK( 1, 0 ),
-
-    /*  ADD       */  PACK( 2, 1 ),
-    /*  SUB       */  PACK( 2, 1 ),
-    /*  DIV       */  PACK( 2, 1 ),
-    /*  MUL       */  PACK( 2, 1 ),
-    /*  ABS       */  PACK( 1, 1 ),
-    /*  NEG       */  PACK( 1, 1 ),
-    /*  FLOOR     */  PACK( 1, 1 ),
-    /*  CEILING   */  PACK( 1, 1 ),
-    /*  ROUND[0]  */  PACK( 1, 1 ),
-    /*  ROUND[1]  */  PACK( 1, 1 ),
-    /*  ROUND[2]  */  PACK( 1, 1 ),
-    /*  ROUND[3]  */  PACK( 1, 1 ),
-    /*  NROUND[0] */  PACK( 1, 1 ),
-    /*  NROUND[1] */  PACK( 1, 1 ),
-    /*  NROUND[2] */  PACK( 1, 1 ),
-    /*  NROUND[3] */  PACK( 1, 1 ),
-
-    /*  WCvtF     */  PACK( 2, 0 ),
-    /*  DeltaP2   */  PACK( 1, 0 ),
-    /*  DeltaP3   */  PACK( 1, 0 ),
-    /*  DeltaCn[0] */ PACK( 1, 0 ),
-    /*  DeltaCn[1] */ PACK( 1, 0 ),
-    /*  DeltaCn[2] */ PACK( 1, 0 ),
-    /*  SROUND    */  PACK( 1, 0 ),
-    /*  S45Round  */  PACK( 1, 0 ),
-    /*  JROT      */  PACK( 2, 0 ),
-    /*  JROF      */  PACK( 2, 0 ),
-    /*  ROFF      */  PACK( 0, 0 ),
-    /*  INS_$7B   */  PACK( 0, 0 ),
-    /*  RUTG      */  PACK( 0, 0 ),
-    /*  RDTG      */  PACK( 0, 0 ),
-    /*  SANGW     */  PACK( 1, 0 ),
-    /*  AA        */  PACK( 1, 0 ),
-
-    /*  FlipPT    */  PACK( 0, 0 ),
-    /*  FlipRgON  */  PACK( 2, 0 ),
-    /*  FlipRgOFF */  PACK( 2, 0 ),
-    /*  INS_$83   */  PACK( 0, 0 ),
-    /*  INS_$84   */  PACK( 0, 0 ),
-    /*  ScanCTRL  */  PACK( 1, 0 ),
-    /*  SDVPTL[0] */  PACK( 2, 0 ),
-    /*  SDVPTL[1] */  PACK( 2, 0 ),
-    /*  GetINFO   */  PACK( 1, 1 ),
-    /*  IDEF      */  PACK( 1, 0 ),
-    /*  ROLL      */  PACK( 3, 3 ),
-    /*  MAX       */  PACK( 2, 1 ),
-    /*  MIN       */  PACK( 2, 1 ),
-    /*  ScanTYPE  */  PACK( 1, 0 ),
-    /*  InstCTRL  */  PACK( 2, 0 ),
-    /*  INS_$8F   */  PACK( 0, 0 ),
-
-    /*  INS_$90  */   PACK( 0, 0 ),
-    /*  INS_$91  */   PACK( 0, 0 ),
-    /*  INS_$92  */   PACK( 0, 0 ),
-    /*  INS_$93  */   PACK( 0, 0 ),
-    /*  INS_$94  */   PACK( 0, 0 ),
-    /*  INS_$95  */   PACK( 0, 0 ),
-    /*  INS_$96  */   PACK( 0, 0 ),
-    /*  INS_$97  */   PACK( 0, 0 ),
-    /*  INS_$98  */   PACK( 0, 0 ),
-    /*  INS_$99  */   PACK( 0, 0 ),
-    /*  INS_$9A  */   PACK( 0, 0 ),
-    /*  INS_$9B  */   PACK( 0, 0 ),
-    /*  INS_$9C  */   PACK( 0, 0 ),
-    /*  INS_$9D  */   PACK( 0, 0 ),
-    /*  INS_$9E  */   PACK( 0, 0 ),
-    /*  INS_$9F  */   PACK( 0, 0 ),
-
-    /*  INS_$A0  */   PACK( 0, 0 ),
-    /*  INS_$A1  */   PACK( 0, 0 ),
-    /*  INS_$A2  */   PACK( 0, 0 ),
-    /*  INS_$A3  */   PACK( 0, 0 ),
-    /*  INS_$A4  */   PACK( 0, 0 ),
-    /*  INS_$A5  */   PACK( 0, 0 ),
-    /*  INS_$A6  */   PACK( 0, 0 ),
-    /*  INS_$A7  */   PACK( 0, 0 ),
-    /*  INS_$A8  */   PACK( 0, 0 ),
-    /*  INS_$A9  */   PACK( 0, 0 ),
-    /*  INS_$AA  */   PACK( 0, 0 ),
-    /*  INS_$AB  */   PACK( 0, 0 ),
-    /*  INS_$AC  */   PACK( 0, 0 ),
-    /*  INS_$AD  */   PACK( 0, 0 ),
-    /*  INS_$AE  */   PACK( 0, 0 ),
-    /*  INS_$AF  */   PACK( 0, 0 ),
-
-    /*  PushB[0]  */  PACK( 0, 1 ),
-    /*  PushB[1]  */  PACK( 0, 2 ),
-    /*  PushB[2]  */  PACK( 0, 3 ),
-    /*  PushB[3]  */  PACK( 0, 4 ),
-    /*  PushB[4]  */  PACK( 0, 5 ),
-    /*  PushB[5]  */  PACK( 0, 6 ),
-    /*  PushB[6]  */  PACK( 0, 7 ),
-    /*  PushB[7]  */  PACK( 0, 8 ),
-    /*  PushW[0]  */  PACK( 0, 1 ),
-    /*  PushW[1]  */  PACK( 0, 2 ),
-    /*  PushW[2]  */  PACK( 0, 3 ),
-    /*  PushW[3]  */  PACK( 0, 4 ),
-    /*  PushW[4]  */  PACK( 0, 5 ),
-    /*  PushW[5]  */  PACK( 0, 6 ),
-    /*  PushW[6]  */  PACK( 0, 7 ),
-    /*  PushW[7]  */  PACK( 0, 8 ),
-
-    /*  MDRP[00]  */  PACK( 1, 0 ),
-    /*  MDRP[01]  */  PACK( 1, 0 ),
-    /*  MDRP[02]  */  PACK( 1, 0 ),
-    /*  MDRP[03]  */  PACK( 1, 0 ),
-    /*  MDRP[04]  */  PACK( 1, 0 ),
-    /*  MDRP[05]  */  PACK( 1, 0 ),
-    /*  MDRP[06]  */  PACK( 1, 0 ),
-    /*  MDRP[07]  */  PACK( 1, 0 ),
-    /*  MDRP[08]  */  PACK( 1, 0 ),
-    /*  MDRP[09]  */  PACK( 1, 0 ),
-    /*  MDRP[10]  */  PACK( 1, 0 ),
-    /*  MDRP[11]  */  PACK( 1, 0 ),
-    /*  MDRP[12]  */  PACK( 1, 0 ),
-    /*  MDRP[13]  */  PACK( 1, 0 ),
-    /*  MDRP[14]  */  PACK( 1, 0 ),
-    /*  MDRP[15]  */  PACK( 1, 0 ),
-
-    /*  MDRP[16]  */  PACK( 1, 0 ),
-    /*  MDRP[17]  */  PACK( 1, 0 ),
-    /*  MDRP[18]  */  PACK( 1, 0 ),
-    /*  MDRP[19]  */  PACK( 1, 0 ),
-    /*  MDRP[20]  */  PACK( 1, 0 ),
-    /*  MDRP[21]  */  PACK( 1, 0 ),
-    /*  MDRP[22]  */  PACK( 1, 0 ),
-    /*  MDRP[23]  */  PACK( 1, 0 ),
-    /*  MDRP[24]  */  PACK( 1, 0 ),
-    /*  MDRP[25]  */  PACK( 1, 0 ),
-    /*  MDRP[26]  */  PACK( 1, 0 ),
-    /*  MDRP[27]  */  PACK( 1, 0 ),
-    /*  MDRP[28]  */  PACK( 1, 0 ),
-    /*  MDRP[29]  */  PACK( 1, 0 ),
-    /*  MDRP[30]  */  PACK( 1, 0 ),
-    /*  MDRP[31]  */  PACK( 1, 0 ),
-
-    /*  MIRP[00]  */  PACK( 2, 0 ),
-    /*  MIRP[01]  */  PACK( 2, 0 ),
-    /*  MIRP[02]  */  PACK( 2, 0 ),
-    /*  MIRP[03]  */  PACK( 2, 0 ),
-    /*  MIRP[04]  */  PACK( 2, 0 ),
-    /*  MIRP[05]  */  PACK( 2, 0 ),
-    /*  MIRP[06]  */  PACK( 2, 0 ),
-    /*  MIRP[07]  */  PACK( 2, 0 ),
-    /*  MIRP[08]  */  PACK( 2, 0 ),
-    /*  MIRP[09]  */  PACK( 2, 0 ),
-    /*  MIRP[10]  */  PACK( 2, 0 ),
-    /*  MIRP[11]  */  PACK( 2, 0 ),
-    /*  MIRP[12]  */  PACK( 2, 0 ),
-    /*  MIRP[13]  */  PACK( 2, 0 ),
-    /*  MIRP[14]  */  PACK( 2, 0 ),
-    /*  MIRP[15]  */  PACK( 2, 0 ),
-
-    /*  MIRP[16]  */  PACK( 2, 0 ),
-    /*  MIRP[17]  */  PACK( 2, 0 ),
-    /*  MIRP[18]  */  PACK( 2, 0 ),
-    /*  MIRP[19]  */  PACK( 2, 0 ),
-    /*  MIRP[20]  */  PACK( 2, 0 ),
-    /*  MIRP[21]  */  PACK( 2, 0 ),
-    /*  MIRP[22]  */  PACK( 2, 0 ),
-    /*  MIRP[23]  */  PACK( 2, 0 ),
-    /*  MIRP[24]  */  PACK( 2, 0 ),
-    /*  MIRP[25]  */  PACK( 2, 0 ),
-    /*  MIRP[26]  */  PACK( 2, 0 ),
-    /*  MIRP[27]  */  PACK( 2, 0 ),
-    /*  MIRP[28]  */  PACK( 2, 0 ),
-    /*  MIRP[29]  */  PACK( 2, 0 ),
-    /*  MIRP[30]  */  PACK( 2, 0 ),
-    /*  MIRP[31]  */  PACK( 2, 0 )
-  };
-
-
-  static
-  const FT_Char  opcode_length[256] =
-  {
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-
-   -1,-2, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,
-
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
-  };
-
-#undef PACK
-
-#if 1
-
-  static FT_Int32
-  TT_MulFix14( FT_Int32  a,
-               FT_Int    b )
-  {
-    FT_Int32   sign;
-    FT_UInt32  ah, al, mid, lo, hi;
-
-
-    sign = a ^ b;
-
-    if ( a < 0 )
-      a = -a;
-    if ( b < 0 )
-      b = -b;
-
-    ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
-    al = (FT_UInt32)( a & 0xFFFFU );
-
-    lo    = al * b;
-    mid   = ah * b;
-    hi    = mid >> 16;
-    mid   = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
-    lo   += mid;
-    if ( lo < mid )
-      hi += 1;
-
-    mid = ( lo >> 14 ) | ( hi << 18 );
-
-    return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
-  }
-
-#else
-
-  /* compute (a*b)/2^14 with maximal accuracy and rounding */
-  static FT_Int32
-  TT_MulFix14( FT_Int32  a,
-               FT_Int    b )
-  {
-    FT_Int32   m, s, hi;
-    FT_UInt32  l, lo;
-
-
-    /* compute ax*bx as 64-bit value */
-    l  = (FT_UInt32)( ( a & 0xFFFFU ) * b );
-    m  = ( a >> 16 ) * b;
-
-    lo = l + (FT_UInt32)( m << 16 );
-    hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
-
-    /* divide the result by 2^14 with rounding */
-    s   = hi >> 31;
-    l   = lo + (FT_UInt32)s;
-    hi += s + ( l < lo );
-    lo  = l;
-
-    l   = lo + 0x2000U;
-    hi += l < lo;
-
-    return ( hi << 18 ) | ( l >> 14 );
-  }
-#endif
-
-
-  /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
-  static FT_Int32
-  TT_DotFix14( FT_Int32  ax,
-               FT_Int32  ay,
-               FT_Int    bx,
-               FT_Int    by )
-  {
-    FT_Int32   m, s, hi1, hi2, hi;
-    FT_UInt32  l, lo1, lo2, lo;
-
-
-    /* compute ax*bx as 64-bit value */
-    l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
-    m = ( ax >> 16 ) * bx;
-
-    lo1 = l + (FT_UInt32)( m << 16 );
-    hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
-
-    /* compute ay*by as 64-bit value */
-    l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
-    m = ( ay >> 16 ) * by;
-
-    lo2 = l + (FT_UInt32)( m << 16 );
-    hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
-
-    /* add them */
-    lo = lo1 + lo2;
-    hi = hi1 + hi2 + ( lo < lo1 );
-
-    /* divide the result by 2^14 with rounding */
-    s   = hi >> 31;
-    l   = lo + (FT_UInt32)s;
-    hi += s + ( l < lo );
-    lo  = l;
-
-    l   = lo + 0x2000U;
-    hi += ( l < lo );
-
-    return ( hi << 18 ) | ( l >> 14 );
-  }
-
-
-  /* return length of given vector */
-
-#if 0
-
-  static FT_Int32
-  TT_VecLen( FT_Int32  x,
-             FT_Int32  y )
-  {
-    FT_Int32   m, hi1, hi2, hi;
-    FT_UInt32  l, lo1, lo2, lo;
-
-
-    /* compute x*x as 64-bit value */
-    lo = (FT_UInt32)( x & 0xFFFFU );
-    hi = x >> 16;
-
-    l  = lo * lo;
-    m  = hi * lo;
-    hi = hi * hi;
-
-    lo1 = l + (FT_UInt32)( m << 17 );
-    hi1 = hi + ( m >> 15 ) + ( lo1 < l );
-
-    /* compute y*y as 64-bit value */
-    lo = (FT_UInt32)( y & 0xFFFFU );
-    hi = y >> 16;
-
-    l  = lo * lo;
-    m  = hi * lo;
-    hi = hi * hi;
-
-    lo2 = l + (FT_UInt32)( m << 17 );
-    hi2 = hi + ( m >> 15 ) + ( lo2 < l );
-
-    /* add them to get 'x*x+y*y' as 64-bit value */
-    lo = lo1 + lo2;
-    hi = hi1 + hi2 + ( lo < lo1 );
-
-    /* compute the square root of this value */
-    {
-      FT_UInt32  root, rem, test_div;
-      FT_Int     count;
-
-
-      root = 0;
-
-      {
-        rem   = 0;
-        count = 32;
-        do
-        {
-          rem      = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
-          hi       = (  hi << 2 ) | (            lo >> 30 );
-          lo     <<= 2;
-          root   <<= 1;
-          test_div = ( root << 1 ) + 1;
-
-          if ( rem >= test_div )
-          {
-            rem  -= test_div;
-            root += 1;
-          }
-        } while ( --count );
-      }
-
-      return (FT_Int32)root;
-    }
-  }
-
-#else
-
-  /* this version uses FT_Vector_Length which computes the same value */
-  /* much, much faster..                                              */
-  /*                                                                  */
-  static FT_F26Dot6
-  TT_VecLen( FT_F26Dot6  X,
-             FT_F26Dot6  Y )
-  {
-    FT_Vector  v;
-
-
-    v.x = X;
-    v.y = Y;
-
-    return FT_Vector_Length( &v );
-  }
-
-#endif
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Current_Ratio                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Returns the current aspect ratio scaling factor depending on the   */
-  /*    projection vector's state and device resolutions.                  */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */
-  /*                                                                       */
-  static FT_Long
-  Current_Ratio( EXEC_OP )
-  {
-    if ( !CUR.tt_metrics.ratio )
-    {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-      if ( CUR.face->unpatented_hinting )
-      {
-        if ( CUR.GS.both_x_axis )
-          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
-        else
-          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
-      }
-      else
-#endif
-      {
-        if ( CUR.GS.projVector.y == 0 )
-          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
-
-        else if ( CUR.GS.projVector.x == 0 )
-          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
-
-        else
-        {
-          FT_Long  x, y;
-
-
-          x = TT_MULDIV( CUR.GS.projVector.x,
-                         CUR.tt_metrics.x_ratio, 0x4000 );
-          y = TT_MULDIV( CUR.GS.projVector.y,
-                         CUR.tt_metrics.y_ratio, 0x4000 );
-          CUR.tt_metrics.ratio = TT_VecLen( x, y );
-        }
-      }
-    }
-    return CUR.tt_metrics.ratio;
-  }
-
-
-  static FT_Long
-  Current_Ppem( EXEC_OP )
-  {
-    return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Functions related to the control value table (CVT).                   */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  FT_CALLBACK_DEF( FT_F26Dot6 )
-  Read_CVT( EXEC_OP_ FT_ULong  idx )
-  {
-    return CUR.cvt[idx];
-  }
-
-
-  FT_CALLBACK_DEF( FT_F26Dot6 )
-  Read_CVT_Stretched( EXEC_OP_ FT_ULong  idx )
-  {
-    return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
-  }
-
-
-  FT_CALLBACK_DEF( void )
-  Write_CVT( EXEC_OP_ FT_ULong    idx,
-                      FT_F26Dot6  value )
-  {
-    CUR.cvt[idx] = value;
-  }
-
-
-  FT_CALLBACK_DEF( void )
-  Write_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
-                                FT_F26Dot6  value )
-  {
-    CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
-  }
-
-
-  FT_CALLBACK_DEF( void )
-  Move_CVT( EXEC_OP_ FT_ULong    idx,
-                     FT_F26Dot6  value )
-  {
-    CUR.cvt[idx] += value;
-  }
-
-
-  FT_CALLBACK_DEF( void )
-  Move_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
-                               FT_F26Dot6  value )
-  {
-    CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    GetShortIns                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Returns a short integer taken from the instruction stream at       */
-  /*    address IP.                                                        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Short read at code[IP].                                            */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    This one could become a macro.                                     */
-  /*                                                                       */
-  static FT_Short
-  GetShortIns( EXEC_OP )
-  {
-    /* Reading a byte stream so there is no endianess (DaveP) */
-    CUR.IP += 2;
-    return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
-                         CUR.code[CUR.IP - 1]      );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Ins_Goto_CodeRange                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Goes to a certain code range in the instruction stream.            */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    aRange :: The index of the code range.                             */
-  /*                                                                       */
-  /*    aIP    :: The new IP address in the code range.                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS or FAILURE.                                                */
-  /*                                                                       */
-  static FT_Bool
-  Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,
-                               FT_ULong  aIP )
-  {
-    TT_CodeRange*  range;
-
-
-    if ( aRange < 1 || aRange > 3 )
-    {
-      CUR.error = TT_Err_Bad_Argument;
-      return FAILURE;
-    }
-
-    range = &CUR.codeRangeTable[aRange - 1];
-
-    if ( range->base == NULL )     /* invalid coderange */
-    {
-      CUR.error = TT_Err_Invalid_CodeRange;
-      return FAILURE;
-    }
-
-    /* NOTE: Because the last instruction of a program may be a CALL */
-    /*       which will return to the first byte *after* the code    */
-    /*       range, we test for AIP <= Size, instead of AIP < Size.  */
-
-    if ( aIP > range->size )
-    {
-      CUR.error = TT_Err_Code_Overflow;
-      return FAILURE;
-    }
-
-    CUR.code     = range->base;
-    CUR.codeSize = range->size;
-    CUR.IP       = aIP;
-    CUR.curRange = aRange;
-
-    return SUCCESS;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Direct_Move                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Moves a point by a given distance along the freedom vector.  The   */
-  /*    point will be `touched'.                                           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    point    :: The index of the point to move.                        */
-  /*                                                                       */
-  /*    distance :: The distance to apply.                                 */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    zone     :: The affected glyph zone.                               */
-  /*                                                                       */
-  static void
-  Direct_Move( EXEC_OP_ TT_GlyphZone  zone,
-                        FT_UShort     point,
-                        FT_F26Dot6    distance )
-  {
-    FT_F26Dot6  v;
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !CUR.face->unpatented_hinting );
-#endif
-
-    v = CUR.GS.freeVector.x;
-
-    if ( v != 0 )
-    {
-      zone->cur[point].x += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
-
-      zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
-    }
-
-    v = CUR.GS.freeVector.y;
-
-    if ( v != 0 )
-    {
-      zone->cur[point].y += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
-
-      zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Direct_Move_Orig                                                   */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Moves the *original* position of a point by a given distance along */
-  /*    the freedom vector.  Obviously, the point will not be `touched'.   */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    point    :: The index of the point to move.                        */
-  /*                                                                       */
-  /*    distance :: The distance to apply.                                 */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    zone     :: The affected glyph zone.                               */
-  /*                                                                       */
-  static void
-  Direct_Move_Orig( EXEC_OP_ TT_GlyphZone  zone,
-                             FT_UShort     point,
-                             FT_F26Dot6    distance )
-  {
-    FT_F26Dot6  v;
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !CUR.face->unpatented_hinting );
-#endif
-
-    v = CUR.GS.freeVector.x;
-
-    if ( v != 0 )
-      zone->org[point].x += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
-
-    v = CUR.GS.freeVector.y;
-
-    if ( v != 0 )
-      zone->org[point].y += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Special versions of Direct_Move()                                     */
-  /*                                                                       */
-  /*   The following versions are used whenever both vectors are both      */
-  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  static void
-  Direct_Move_X( EXEC_OP_ TT_GlyphZone  zone,
-                          FT_UShort     point,
-                          FT_F26Dot6    distance )
-  {
-    FT_UNUSED_EXEC;
-
-    zone->cur[point].x += distance;
-    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
-  }
-
-
-  static void
-  Direct_Move_Y( EXEC_OP_ TT_GlyphZone  zone,
-                          FT_UShort     point,
-                          FT_F26Dot6    distance )
-  {
-    FT_UNUSED_EXEC;
-
-    zone->cur[point].y += distance;
-    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Special versions of Direct_Move_Orig()                                */
-  /*                                                                       */
-  /*   The following versions are used whenever both vectors are both      */
-  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  static void
-  Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone  zone,
-                               FT_UShort     point,
-                               FT_F26Dot6    distance )
-  {
-    FT_UNUSED_EXEC;
-
-    zone->org[point].x += distance;
-  }
-
-
-  static void
-  Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone  zone,
-                               FT_UShort     point,
-                               FT_F26Dot6    distance )
-  {
-    FT_UNUSED_EXEC;
-
-    zone->org[point].y += distance;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_None                                                         */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Does not round, but adds engine compensation.                      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance (not) to round.                       */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The compensated distance.                                          */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    The TrueType specification says very few about the relationship    */
-  /*    between rounding and engine compensation.  However, it seems from  */
-  /*    the description of super round that we should add the compensation */
-  /*    before rounding.                                                   */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_None( EXEC_OP_ FT_F26Dot6  distance,
-                       FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6  val;
-
-    FT_UNUSED_EXEC;
-
-
-    if ( distance >= 0 )
-    {
-      val = distance + compensation;
-      if ( distance && val < 0 )
-        val = 0;
-    }
-    else {
-      val = distance - compensation;
-      if ( val > 0 )
-        val = 0;
-    }
-    return val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_To_Grid                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Rounds value to grid after adding engine compensation.             */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance to round.                             */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Rounded distance.                                                  */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                          FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6  val;
-
-    FT_UNUSED_EXEC;
-
-
-    if ( distance >= 0 )
-    {
-      val = distance + compensation + 32;
-      if ( distance && val > 0 )
-        val &= ~63;
-      else
-        val = 0;
-    }
-    else
-    {
-      val = -FT_PIX_ROUND( compensation - distance );
-      if ( val > 0 )
-        val = 0;
-    }
-
-    return  val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_To_Half_Grid                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Rounds value to half grid after adding engine compensation.        */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance to round.                             */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Rounded distance.                                                  */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                               FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6  val;
-
-    FT_UNUSED_EXEC;
-
-
-    if ( distance >= 0 )
-    {
-      val = FT_PIX_FLOOR( distance + compensation ) + 32;
-      if ( distance && val < 0 )
-        val = 0;
-    }
-    else
-    {
-      val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
-      if ( val > 0 )
-        val = 0;
-    }
-
-    return val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_Down_To_Grid                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Rounds value down to grid after adding engine compensation.        */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance to round.                             */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Rounded distance.                                                  */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                               FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6  val;
-
-    FT_UNUSED_EXEC;
-
-
-    if ( distance >= 0 )
-    {
-      val = distance + compensation;
-      if ( distance && val > 0 )
-        val &= ~63;
-      else
-        val = 0;
-    }
-    else
-    {
-      val = -( ( compensation - distance ) & -64 );
-      if ( val > 0 )
-        val = 0;
-    }
-
-    return val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_Up_To_Grid                                                   */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Rounds value up to grid after adding engine compensation.          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance to round.                             */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Rounded distance.                                                  */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                             FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6  val;
-
-    FT_UNUSED_EXEC;
-
-
-    if ( distance >= 0 )
-    {
-      val = distance + compensation + 63;
-      if ( distance && val > 0 )
-        val &= ~63;
-      else
-        val = 0;
-    }
-    else
-    {
-      val = - FT_PIX_CEIL( compensation - distance );
-      if ( val > 0 )
-        val = 0;
-    }
-
-    return val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_To_Double_Grid                                               */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Rounds value to double grid after adding engine compensation.      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance to round.                             */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Rounded distance.                                                  */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,
-                                 FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6 val;
-
-    FT_UNUSED_EXEC;
-
-
-    if ( distance >= 0 )
-    {
-      val = distance + compensation + 16;
-      if ( distance && val > 0 )
-        val &= ~31;
-      else
-        val = 0;
-    }
-    else
-    {
-      val = -FT_PAD_ROUND( compensation - distance, 32 );
-      if ( val > 0 )
-        val = 0;
-    }
-
-    return val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_Super                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Super-rounds value to grid after adding engine compensation.       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance to round.                             */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Rounded distance.                                                  */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    The TrueType specification says very few about the relationship    */
-  /*    between rounding and engine compensation.  However, it seems from  */
-  /*    the description of super round that we should add the compensation */
-  /*    before rounding.                                                   */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_Super( EXEC_OP_ FT_F26Dot6  distance,
-                        FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6  val;
-
-
-    if ( distance >= 0 )
-    {
-      val = ( distance - CUR.phase + CUR.threshold + compensation ) &
-              -CUR.period;
-      if ( distance && val < 0 )
-        val = 0;
-      val += CUR.phase;
-    }
-    else
-    {
-      val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
-               -CUR.period );
-      if ( val > 0 )
-        val = 0;
-      val -= CUR.phase;
-    }
-
-    return val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Round_Super_45                                                     */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Super-rounds value to grid after adding engine compensation.       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    distance     :: The distance to round.                             */
-  /*                                                                       */
-  /*    compensation :: The engine compensation.                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Rounded distance.                                                  */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    There is a separate function for Round_Super_45() as we may need   */
-  /*    greater precision.                                                 */
-  /*                                                                       */
-  static FT_F26Dot6
-  Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,
-                           FT_F26Dot6  compensation )
-  {
-    FT_F26Dot6  val;
-
-
-    if ( distance >= 0 )
-    {
-      val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
-                CUR.period ) * CUR.period;
-      if ( distance && val < 0 )
-        val = 0;
-      val += CUR.phase;
-    }
-    else
-    {
-      val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
-                   CUR.period ) * CUR.period );
-      if ( val > 0 )
-        val = 0;
-      val -= CUR.phase;
-    }
-
-    return val;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Compute_Round                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Sets the rounding mode.                                            */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    round_mode :: The rounding mode to be used.                        */
-  /*                                                                       */
-  static void
-  Compute_Round( EXEC_OP_ FT_Byte  round_mode )
-  {
-    switch ( round_mode )
-    {
-    case TT_Round_Off:
-      CUR.func_round = (TT_Round_Func)Round_None;
-      break;
-
-    case TT_Round_To_Grid:
-      CUR.func_round = (TT_Round_Func)Round_To_Grid;
-      break;
-
-    case TT_Round_Up_To_Grid:
-      CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
-      break;
-
-    case TT_Round_Down_To_Grid:
-      CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
-      break;
-
-    case TT_Round_To_Half_Grid:
-      CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
-      break;
-
-    case TT_Round_To_Double_Grid:
-      CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
-      break;
-
-    case TT_Round_Super:
-      CUR.func_round = (TT_Round_Func)Round_Super;
-      break;
-
-    case TT_Round_Super_45:
-      CUR.func_round = (TT_Round_Func)Round_Super_45;
-      break;
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    SetSuperRound                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Sets Super Round parameters.                                       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    GridPeriod :: Grid period                                          */
-  /*    selector   :: SROUND opcode                                        */
-  /*                                                                       */
-  static void
-  SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
-                          FT_Long     selector )
-  {
-    switch ( (FT_Int)( selector & 0xC0 ) )
-    {
-      case 0:
-        CUR.period = GridPeriod / 2;
-        break;
-
-      case 0x40:
-        CUR.period = GridPeriod;
-        break;
-
-      case 0x80:
-        CUR.period = GridPeriod * 2;
-        break;
-
-      /* This opcode is reserved, but... */
-
-      case 0xC0:
-        CUR.period = GridPeriod;
-        break;
-    }
-
-    switch ( (FT_Int)( selector & 0x30 ) )
-    {
-    case 0:
-      CUR.phase = 0;
-      break;
-
-    case 0x10:
-      CUR.phase = CUR.period / 4;
-      break;
-
-    case 0x20:
-      CUR.phase = CUR.period / 2;
-      break;
-
-    case 0x30:
-      CUR.phase = CUR.period * 3 / 4;
-      break;
-    }
-
-    if ( ( selector & 0x0F ) == 0 )
-      CUR.threshold = CUR.period - 1;
-    else
-      CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
-
-    CUR.period    /= 256;
-    CUR.phase     /= 256;
-    CUR.threshold /= 256;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Project                                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the projection of vector given by (v2-v1) along the       */
-  /*    current projection vector.                                         */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    v1 :: First input vector.                                          */
-  /*    v2 :: Second input vector.                                         */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The distance in F26dot6 format.                                    */
-  /*                                                                       */
-  static FT_F26Dot6
-  Project( EXEC_OP_ FT_Pos  dx,
-                    FT_Pos  dy )
-  {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    FT_ASSERT( !CUR.face->unpatented_hinting );
-#endif
-
-    return TT_DotFix14( dx, dy,
-                        CUR.GS.projVector.x,
-                        CUR.GS.projVector.y );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Dual_Project                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the projection of the vector given by (v2-v1) along the   */
-  /*    current dual vector.                                               */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    v1 :: First input vector.                                          */
-  /*    v2 :: Second input vector.                                         */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The distance in F26dot6 format.                                    */
-  /*                                                                       */
-  static FT_F26Dot6
-  Dual_Project( EXEC_OP_ FT_Pos  dx,
-                         FT_Pos  dy )
-  {
-    return TT_DotFix14( dx, dy,
-                        CUR.GS.dualVector.x,
-                        CUR.GS.dualVector.y );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Project_x                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the projection of the vector given by (v2-v1) along the   */
-  /*    horizontal axis.                                                   */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    v1 :: First input vector.                                          */
-  /*    v2 :: Second input vector.                                         */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The distance in F26dot6 format.                                    */
-  /*                                                                       */
-  static FT_F26Dot6
-  Project_x( EXEC_OP_ FT_Pos  dx,
-                      FT_Pos  dy )
-  {
-    FT_UNUSED_EXEC;
-    FT_UNUSED( dy );
-
-    return dx;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Project_y                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the projection of the vector given by (v2-v1) along the   */
-  /*    vertical axis.                                                     */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    v1 :: First input vector.                                          */
-  /*    v2 :: Second input vector.                                         */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The distance in F26dot6 format.                                    */
-  /*                                                                       */
-  static FT_F26Dot6
-  Project_y( EXEC_OP_ FT_Pos  dx,
-                      FT_Pos  dy )
-  {
-    FT_UNUSED_EXEC;
-    FT_UNUSED( dx );
-
-    return dy;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Compute_Funcs                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the projection and movement function pointers according   */
-  /*    to the current graphics state.                                     */
-  /*                                                                       */
-  static void
-  Compute_Funcs( EXEC_OP )
-  {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
-    {
-      /* If both vectors point rightwards along the x axis, set             */
-      /* `both-x-axis' true, otherwise set it false.  The x values only     */
-      /* need be tested because the vector has been normalised to a unit    */
-      /* vector of length 0x4000 = unity.                                   */
-      CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
-                                      CUR.GS.freeVector.x == 0x4000 );
-
-      /* Throw away projection and freedom vector information */
-      /* because the patents don't allow them to be stored.   */
-      /* The relevant US Patents are 5155805 and 5325479.     */
-      CUR.GS.projVector.x = 0;
-      CUR.GS.projVector.y = 0;
-      CUR.GS.freeVector.x = 0;
-      CUR.GS.freeVector.y = 0;
-
-      if ( CUR.GS.both_x_axis )
-      {
-        CUR.func_project   = Project_x;
-        CUR.func_move      = Direct_Move_X;
-        CUR.func_move_orig = Direct_Move_Orig_X;
-      }
-      else
-      {
-        CUR.func_project   = Project_y;
-        CUR.func_move      = Direct_Move_Y;
-        CUR.func_move_orig = Direct_Move_Orig_Y;
-      }
-
-      if ( CUR.GS.dualVector.x == 0x4000 )
-        CUR.func_dualproj = Project_x;
-      else
-      {
-        if ( CUR.GS.dualVector.y == 0x4000 )
-          CUR.func_dualproj = Project_y;
-        else
-          CUR.func_dualproj = Dual_Project;
-      }
-
-      /* Force recalculation of cached aspect ratio */
-      CUR.tt_metrics.ratio = 0;
-
-      return;
-    }
-#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
-
-    if ( CUR.GS.freeVector.x == 0x4000 )
-      CUR.F_dot_P       = CUR.GS.projVector.x * 0x10000L;
-    else
-    {
-      if ( CUR.GS.freeVector.y == 0x4000 )
-        CUR.F_dot_P       = CUR.GS.projVector.y * 0x10000L;
-      else
-        CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
-                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
-    }
-
-    if ( CUR.GS.projVector.x == 0x4000 )
-      CUR.func_project = (TT_Project_Func)Project_x;
-    else
-    {
-      if ( CUR.GS.projVector.y == 0x4000 )
-        CUR.func_project = (TT_Project_Func)Project_y;
-      else
-        CUR.func_project = (TT_Project_Func)Project;
-    }
-
-    if ( CUR.GS.dualVector.x == 0x4000 )
-      CUR.func_dualproj = (TT_Project_Func)Project_x;
-    else
-    {
-      if ( CUR.GS.dualVector.y == 0x4000 )
-        CUR.func_dualproj = (TT_Project_Func)Project_y;
-      else
-        CUR.func_dualproj = (TT_Project_Func)Dual_Project;
-    }
-
-    CUR.func_move      = (TT_Move_Func)Direct_Move;
-    CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
-
-    if ( CUR.F_dot_P == 0x40000000L )
-    {
-      if ( CUR.GS.freeVector.x == 0x4000 )
-      {
-        CUR.func_move      = (TT_Move_Func)Direct_Move_X;
-        CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
-      }
-      else
-      {
-        if ( CUR.GS.freeVector.y == 0x4000 )
-        {
-          CUR.func_move      = (TT_Move_Func)Direct_Move_Y;
-          CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
-        }
-      }
-    }
-
-    /* at small sizes, F_dot_P can become too small, resulting   */
-    /* in overflows and `spikes' in a number of glyphs like `w'. */
-
-    if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
-      CUR.F_dot_P = 0x40000000L;
-
-    /* Disable cached aspect ratio */
-    CUR.tt_metrics.ratio = 0;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Normalize                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Norms a vector.                                                    */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    Vx :: The horizontal input vector coordinate.                      */
-  /*    Vy :: The vertical input vector coordinate.                        */
-  /*                                                                       */
-  /* <Output>                                                              */
-  /*    R  :: The normed unit vector.                                      */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Returns FAILURE if a vector parameter is zero.                     */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
-  /*    R is undefined.                                                    */
-  /*                                                                       */
-
-
-  static FT_Bool
-  Normalize( EXEC_OP_ FT_F26Dot6      Vx,
-                      FT_F26Dot6      Vy,
-                      FT_UnitVector*  R )
-  {
-    FT_F26Dot6  W;
-    FT_Bool     S1, S2;
-
-    FT_UNUSED_EXEC;
-
-
-    if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
-    {
-      Vx *= 0x100;
-      Vy *= 0x100;
-
-      W = TT_VecLen( Vx, Vy );
-
-      if ( W == 0 )
-      {
-        /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
-        /*      to normalize the vector (0,0).  Return immediately. */
-        return SUCCESS;
-      }
-
-      R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
-      R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
-
-      return SUCCESS;
-    }
-
-    W = TT_VecLen( Vx, Vy );
-
-    Vx = FT_MulDiv( Vx, 0x4000L, W );
-    Vy = FT_MulDiv( Vy, 0x4000L, W );
-
-    W = Vx * Vx + Vy * Vy;
-
-    /* Now, we want that Sqrt( W ) = 0x4000 */
-    /* Or 0x10000000 <= W < 0x10004000        */
-
-    if ( Vx < 0 )
-    {
-      Vx = -Vx;
-      S1 = TRUE;
-    }
-    else
-      S1 = FALSE;
-
-    if ( Vy < 0 )
-    {
-      Vy = -Vy;
-      S2 = TRUE;
-    }
-    else
-      S2 = FALSE;
-
-    while ( W < 0x10000000L )
-    {
-      /* We need to increase W by a minimal amount */
-      if ( Vx < Vy )
-        Vx++;
-      else
-        Vy++;
-
-      W = Vx * Vx + Vy * Vy;
-    }
-
-    while ( W >= 0x10004000L )
-    {
-      /* We need to decrease W by a minimal amount */
-      if ( Vx < Vy )
-        Vx--;
-      else
-        Vy--;
-
-      W = Vx * Vx + Vy * Vy;
-    }
-
-    /* Note that in various cases, we can only  */
-    /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
-
-    if ( S1 )
-      Vx = -Vx;
-
-    if ( S2 )
-      Vy = -Vy;
-
-    R->x = (FT_F2Dot14)Vx;   /* Type conversion */
-    R->y = (FT_F2Dot14)Vy;   /* Type conversion */
-
-    return SUCCESS;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Here we start with the implementation of the various opcodes.         */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  static FT_Bool
-  Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,
-                      FT_UShort       aIdx2,
-                      FT_Int          aOpc,
-                      FT_UnitVector*  Vec )
-  {
-    FT_Long     A, B, C;
-    FT_Vector*  p1;
-    FT_Vector*  p2;
-
-
-    if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
-         BOUNDS( aIdx2, CUR.zp1.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return FAILURE;
-    }
-
-    p1 = CUR.zp1.cur + aIdx2;
-    p2 = CUR.zp2.cur + aIdx1;
-
-    A = p1->x - p2->x;
-    B = p1->y - p2->y;
-
-    if ( ( aOpc & 1 ) != 0 )
-    {
-      C =  B;   /* counter clockwise rotation */
-      B =  A;
-      A = -C;
-    }
-
-    NORMalize( A, B, Vec );
-
-    return SUCCESS;
-  }
-
-
-  /* When not using the big switch statements, the interpreter uses a */
-  /* call table defined later below in this source.  Each opcode must */
-  /* thus have a corresponding function, even trivial ones.           */
-  /*                                                                  */
-  /* They are all defined there.                                      */
-
-#define DO_SVTCA                            \
-  {                                         \
-    FT_Short  A, B;                         \
-                                            \
-                                            \
-    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
-    B = A ^ (FT_Short)0x4000;               \
-                                            \
-    CUR.GS.freeVector.x = A;                \
-    CUR.GS.projVector.x = A;                \
-    CUR.GS.dualVector.x = A;                \
-                                            \
-    CUR.GS.freeVector.y = B;                \
-    CUR.GS.projVector.y = B;                \
-    CUR.GS.dualVector.y = B;                \
-                                            \
-    COMPUTE_Funcs();                        \
-  }
-
-
-#define DO_SPVTCA                           \
-  {                                         \
-    FT_Short  A, B;                         \
-                                            \
-                                            \
-    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
-    B = A ^ (FT_Short)0x4000;               \
-                                            \
-    CUR.GS.projVector.x = A;                \
-    CUR.GS.dualVector.x = A;                \
-                                            \
-    CUR.GS.projVector.y = B;                \
-    CUR.GS.dualVector.y = B;                \
-                                            \
-    GUESS_VECTOR( freeVector );             \
-                                            \
-    COMPUTE_Funcs();                        \
-  }
-
-
-#define DO_SFVTCA                           \
-  {                                         \
-    FT_Short  A, B;                         \
-                                            \
-                                            \
-    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
-    B = A ^ (FT_Short)0x4000;               \
-                                            \
-    CUR.GS.freeVector.x = A;                \
-    CUR.GS.freeVector.y = B;                \
-                                            \
-    GUESS_VECTOR( projVector );             \
-                                            \
-    COMPUTE_Funcs();                        \
-  }
-
-
-#define DO_SPVTL                                      \
-    if ( INS_SxVTL( (FT_UShort)args[1],               \
-                    (FT_UShort)args[0],               \
-                    CUR.opcode,                       \
-                    &CUR.GS.projVector ) == SUCCESS ) \
-    {                                                 \
-      CUR.GS.dualVector = CUR.GS.projVector;          \
-      GUESS_VECTOR( freeVector );                     \
-      COMPUTE_Funcs();                                \
-    }
-
-
-#define DO_SFVTL                                      \
-    if ( INS_SxVTL( (FT_UShort)args[1],               \
-                    (FT_UShort)args[0],               \
-                    CUR.opcode,                       \
-                    &CUR.GS.freeVector ) == SUCCESS ) \
-    {                                                 \
-      GUESS_VECTOR( projVector );                     \
-      COMPUTE_Funcs();                                \
-    }
-
-
-#define DO_SFVTPV                          \
-    GUESS_VECTOR( projVector );            \
-    CUR.GS.freeVector = CUR.GS.projVector; \
-    COMPUTE_Funcs();
-
-
-#define DO_SPVFS                                \
-  {                                             \
-    FT_Short  S;                                \
-    FT_Long   X, Y;                             \
-                                                \
-                                                \
-    /* Only use low 16bits, then sign extend */ \
-    S = (FT_Short)args[1];                      \
-    Y = (FT_Long)S;                             \
-    S = (FT_Short)args[0];                      \
-    X = (FT_Long)S;                             \
-                                                \
-    NORMalize( X, Y, &CUR.GS.projVector );      \
-                                                \
-    CUR.GS.dualVector = CUR.GS.projVector;      \
-    GUESS_VECTOR( freeVector );                 \
-    COMPUTE_Funcs();                            \
-  }
-
-
-#define DO_SFVFS                                \
-  {                                             \
-    FT_Short  S;                                \
-    FT_Long   X, Y;                             \
-                                                \
-                                                \
-    /* Only use low 16bits, then sign extend */ \
-    S = (FT_Short)args[1];                      \
-    Y = (FT_Long)S;                             \
-    S = (FT_Short)args[0];                      \
-    X = S;                                      \
-                                                \
-    NORMalize( X, Y, &CUR.GS.freeVector );      \
-    GUESS_VECTOR( projVector );                 \
-    COMPUTE_Funcs();                            \
-  }
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define DO_GPV                                   \
-    if ( CUR.face->unpatented_hinting )          \
-    {                                            \
-      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
-      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
-    }                                            \
-    else                                         \
-    {                                            \
-      args[0] = CUR.GS.projVector.x;             \
-      args[1] = CUR.GS.projVector.y;             \
-    }
-#else
-#define DO_GPV                                   \
-    args[0] = CUR.GS.projVector.x;               \
-    args[1] = CUR.GS.projVector.y;
-#endif
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define DO_GFV                                   \
-    if ( CUR.face->unpatented_hinting )          \
-    {                                            \
-      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
-      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
-    }                                            \
-    else                                         \
-    {                                            \
-      args[0] = CUR.GS.freeVector.x;             \
-      args[1] = CUR.GS.freeVector.y;             \
-    }
-#else
-#define DO_GFV                                   \
-    args[0] = CUR.GS.freeVector.x;               \
-    args[1] = CUR.GS.freeVector.y;
-#endif
-
-
-#define DO_SRP0                      \
-    CUR.GS.rp0 = (FT_UShort)args[0];
-
-
-#define DO_SRP1                      \
-    CUR.GS.rp1 = (FT_UShort)args[0];
-
-
-#define DO_SRP2                      \
-    CUR.GS.rp2 = (FT_UShort)args[0];
-
-
-#define DO_RTHG                                         \
-    CUR.GS.round_state = TT_Round_To_Half_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
-
-
-#define DO_RTG                                     \
-    CUR.GS.round_state = TT_Round_To_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_To_Grid;
-
-
-#define DO_RTDG                                           \
-    CUR.GS.round_state = TT_Round_To_Double_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
-
-
-#define DO_RUTG                                       \
-    CUR.GS.round_state = TT_Round_Up_To_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
-
-
-#define DO_RDTG                                         \
-    CUR.GS.round_state = TT_Round_Down_To_Grid;         \
-    CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
-
-
-#define DO_ROFF                                 \
-    CUR.GS.round_state = TT_Round_Off;          \
-    CUR.func_round = (TT_Round_Func)Round_None;
-
-
-#define DO_SROUND                                \
-    SET_SuperRound( 0x4000, args[0] );           \
-    CUR.GS.round_state = TT_Round_Super;         \
-    CUR.func_round = (TT_Round_Func)Round_Super;
-
-
-#define DO_S45ROUND                                 \
-    SET_SuperRound( 0x2D41, args[0] );              \
-    CUR.GS.round_state = TT_Round_Super_45;         \
-    CUR.func_round = (TT_Round_Func)Round_Super_45;
-
-
-#define DO_SLOOP                       \
-    if ( args[0] < 0 )                 \
-      CUR.error = TT_Err_Bad_Argument; \
-    else                               \
-      CUR.GS.loop = args[0];
-
-
-#define DO_SMD                         \
-    CUR.GS.minimum_distance = args[0];
-
-
-#define DO_SCVTCI                                     \
-    CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
-
-
-#define DO_SSWCI                                     \
-    CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
-
-
-    /* XXX: UNDOCUMENTED! or bug in the Windows engine?   */
-    /*                                                    */
-    /*      It seems that the value that is read here is  */
-    /*      expressed in 16.16 format rather than in font */
-    /*      units.                                        */
-    /*                                                    */
-#define DO_SSW                                                 \
-    CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
-
-
-#define DO_FLIPON            \
-    CUR.GS.auto_flip = TRUE;
-
-
-#define DO_FLIPOFF            \
-    CUR.GS.auto_flip = FALSE;
-
-
-#define DO_SDB                             \
-    CUR.GS.delta_base = (FT_Short)args[0];
-
-
-#define DO_SDS                              \
-    CUR.GS.delta_shift = (FT_Short)args[0];
-
-
-#define DO_MD  /* nothing */
-
-
-#define DO_MPPEM              \
-    args[0] = CURRENT_Ppem();
-
-
-  /* Note: The pointSize should be irrelevant in a given font program; */
-  /*       we thus decide to return only the ppem.                     */
-#if 0
-
-#define DO_MPS                       \
-    args[0] = CUR.metrics.pointSize;
-
-#else
-
-#define DO_MPS                \
-    args[0] = CURRENT_Ppem();
-
-#endif /* 0 */
-
-
-#define DO_DUP         \
-    args[1] = args[0];
-
-
-#define DO_CLEAR     \
-    CUR.new_top = 0;
-
-
-#define DO_SWAP        \
-  {                    \
-    FT_Long  L;        \
-                       \
-                       \
-    L       = args[0]; \
-    args[0] = args[1]; \
-    args[1] = L;       \
-  }
-
-
-#define DO_DEPTH       \
-    args[0] = CUR.top;
-
-
-#define DO_CINDEX                           \
-  {                                         \
-    FT_Long  L;                             \
-                                            \
-                                            \
-    L = args[0];                            \
-                                            \
-    if ( L <= 0 || L > CUR.args )           \
-      CUR.error = TT_Err_Invalid_Reference; \
-    else                                    \
-      args[0] = CUR.stack[CUR.args - L];    \
-  }
-
-
-#define DO_JROT               \
-    if ( args[1] != 0 )       \
-    {                         \
-      CUR.IP      += args[0]; \
-      CUR.step_ins = FALSE;   \
-    }
-
-
-#define DO_JMPR             \
-    CUR.IP      += args[0]; \
-    CUR.step_ins = FALSE;
-
-
-#define DO_JROF               \
-    if ( args[1] == 0 )       \
-    {                         \
-      CUR.IP      += args[0]; \
-      CUR.step_ins = FALSE;   \
-    }
-
-
-#define DO_LT                        \
-    args[0] = ( args[0] < args[1] );
-
-
-#define DO_LTEQ                       \
-    args[0] = ( args[0] <= args[1] );
-
-
-#define DO_GT                        \
-    args[0] = ( args[0] > args[1] );
-
-
-#define DO_GTEQ                       \
-    args[0] = ( args[0] >= args[1] );
-
-
-#define DO_EQ                         \
-    args[0] = ( args[0] == args[1] );
-
-
-#define DO_NEQ                        \
-    args[0] = ( args[0] != args[1] );
-
-
-#define DO_ODD                                                  \
-    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
-
-
-#define DO_EVEN                                                \
-    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
-
-
-#define DO_AND                        \
-    args[0] = ( args[0] && args[1] );
-
-
-#define DO_OR                         \
-    args[0] = ( args[0] || args[1] );
-
-
-#define DO_NOT          \
-    args[0] = !args[0];
-
-
-#define DO_ADD          \
-    args[0] += args[1];
-
-
-#define DO_SUB          \
-    args[0] -= args[1];
-
-
-#define DO_DIV                                               \
-    if ( args[1] == 0 )                                      \
-      CUR.error = TT_Err_Divide_By_Zero;                     \
-    else                                                     \
-      args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
-
-
-#define DO_MUL                                    \
-    args[0] = TT_MULDIV( args[0], args[1], 64L );
-
-
-#define DO_ABS                   \
-    args[0] = FT_ABS( args[0] );
-
-
-#define DO_NEG          \
-    args[0] = -args[0];
-
-
-#define DO_FLOOR    \
-    args[0] = FT_PIX_FLOOR( args[0] );
-
-
-#define DO_CEILING                    \
-    args[0] = FT_PIX_CEIL( args[0] );
-
-
-#define DO_RS                          \
-   {                                   \
-     FT_ULong  I = (FT_ULong)args[0];  \
-                                       \
-                                       \
-     if ( BOUNDS( I, CUR.storeSize ) ) \
-     {                                 \
-       if ( CUR.pedantic_hinting )     \
-       {                               \
-         ARRAY_BOUND_ERROR;            \
-       }                               \
-       else                            \
-         args[0] = 0;                  \
-     }                                 \
-     else                              \
-       args[0] = CUR.storage[I];       \
-   }
-
-
-#define DO_WS                          \
-   {                                   \
-     FT_ULong  I = (FT_ULong)args[0];  \
-                                       \
-                                       \
-     if ( BOUNDS( I, CUR.storeSize ) ) \
-     {                                 \
-       if ( CUR.pedantic_hinting )     \
-       {                               \
-         ARRAY_BOUND_ERROR;            \
-       }                               \
-     }                                 \
-     else                              \
-       CUR.storage[I] = args[1];       \
-   }
-
-
-#define DO_RCVT                          \
-   {                                     \
-     FT_ULong  I = (FT_ULong)args[0];    \
-                                         \
-                                         \
-     if ( BOUNDS( I, CUR.cvtSize ) )     \
-     {                                   \
-       if ( CUR.pedantic_hinting )       \
-       {                                 \
-         ARRAY_BOUND_ERROR;              \
-       }                                 \
-       else                              \
-         args[0] = 0;                    \
-     }                                   \
-     else                                \
-       args[0] = CUR_Func_read_cvt( I ); \
-   }
-
-
-#define DO_WCVTP                         \
-   {                                     \
-     FT_ULong  I = (FT_ULong)args[0];    \
-                                         \
-                                         \
-     if ( BOUNDS( I, CUR.cvtSize ) )     \
-     {                                   \
-       if ( CUR.pedantic_hinting )       \
-       {                                 \
-         ARRAY_BOUND_ERROR;              \
-       }                                 \
-     }                                   \
-     else                                \
-       CUR_Func_write_cvt( I, args[1] ); \
-   }
-
-
-#define DO_WCVTF                                                \
-   {                                                            \
-     FT_ULong  I = (FT_ULong)args[0];                           \
-                                                                \
-                                                                \
-     if ( BOUNDS( I, CUR.cvtSize ) )                            \
-     {                                                          \
-       if ( CUR.pedantic_hinting )                              \
-       {                                                        \
-         ARRAY_BOUND_ERROR;                                     \
-       }                                                        \
-     }                                                          \
-     else                                                       \
-       CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
-   }
-
-
-#define DO_DEBUG                     \
-    CUR.error = TT_Err_Debug_OpCode;
-
-
-#define DO_ROUND                                                   \
-    args[0] = CUR_Func_round(                                      \
-                args[0],                                           \
-                CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
-
-
-#define DO_NROUND                                                            \
-    args[0] = ROUND_None( args[0],                                           \
-                          CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
-
-
-#define DO_MAX               \
-    if ( args[1] > args[0] ) \
-      args[0] = args[1];
-
-
-#define DO_MIN               \
-    if ( args[1] < args[0] ) \
-      args[0] = args[1];
-
-
-#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
-
-
-#undef  ARRAY_BOUND_ERROR
-#define ARRAY_BOUND_ERROR                   \
-    {                                       \
-      CUR.error = TT_Err_Invalid_Reference; \
-      return;                               \
-    }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */
-  /* Opcode range: 0x00-0x01                                               */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SVTCA( INS_ARG )
-  {
-    DO_SVTCA
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SPVTCA[a]:    Set PVector to Coordinate Axis                          */
-  /* Opcode range: 0x02-0x03                                               */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SPVTCA( INS_ARG )
-  {
-    DO_SPVTCA
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVTCA[a]:    Set FVector to Coordinate Axis                          */
-  /* Opcode range: 0x04-0x05                                               */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SFVTCA( INS_ARG )
-  {
-    DO_SFVTCA
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SPVTL[a]:     Set PVector To Line                                     */
-  /* Opcode range: 0x06-0x07                                               */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_SPVTL( INS_ARG )
-  {
-    DO_SPVTL
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVTL[a]:     Set FVector To Line                                     */
-  /* Opcode range: 0x08-0x09                                               */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_SFVTL( INS_ARG )
-  {
-    DO_SFVTL
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVTPV[]:     Set FVector To PVector                                  */
-  /* Opcode range: 0x0E                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_SFVTPV( INS_ARG )
-  {
-    DO_SFVTPV
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SPVFS[]:      Set PVector From Stack                                  */
-  /* Opcode range: 0x0A                                                    */
-  /* Stack:        f2.14 f2.14 -->                                         */
-  /*                                                                       */
-  static void
-  Ins_SPVFS( INS_ARG )
-  {
-    DO_SPVFS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SFVFS[]:      Set FVector From Stack                                  */
-  /* Opcode range: 0x0B                                                    */
-  /* Stack:        f2.14 f2.14 -->                                         */
-  /*                                                                       */
-  static void
-  Ins_SFVFS( INS_ARG )
-  {
-    DO_SFVFS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* GPV[]:        Get Projection Vector                                   */
-  /* Opcode range: 0x0C                                                    */
-  /* Stack:        ef2.14 --> ef2.14                                       */
-  /*                                                                       */
-  static void
-  Ins_GPV( INS_ARG )
-  {
-    DO_GPV
-  }
-
-
-  /*************************************************************************/
-  /* GFV[]:        Get Freedom Vector                                      */
-  /* Opcode range: 0x0D                                                    */
-  /* Stack:        ef2.14 --> ef2.14                                       */
-  /*                                                                       */
-  static void
-  Ins_GFV( INS_ARG )
-  {
-    DO_GFV
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SRP0[]:       Set Reference Point 0                                   */
-  /* Opcode range: 0x10                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SRP0( INS_ARG )
-  {
-    DO_SRP0
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SRP1[]:       Set Reference Point 1                                   */
-  /* Opcode range: 0x11                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SRP1( INS_ARG )
-  {
-    DO_SRP1
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SRP2[]:       Set Reference Point 2                                   */
-  /* Opcode range: 0x12                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SRP2( INS_ARG )
-  {
-    DO_SRP2
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RTHG[]:       Round To Half Grid                                      */
-  /* Opcode range: 0x19                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RTHG( INS_ARG )
-  {
-    DO_RTHG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RTG[]:        Round To Grid                                           */
-  /* Opcode range: 0x18                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RTG( INS_ARG )
-  {
-    DO_RTG
-  }
-
-
-  /*************************************************************************/
-  /* RTDG[]:       Round To Double Grid                                    */
-  /* Opcode range: 0x3D                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RTDG( INS_ARG )
-  {
-    DO_RTDG
-  }
-
-
-  /*************************************************************************/
-  /* RUTG[]:       Round Up To Grid                                        */
-  /* Opcode range: 0x7C                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RUTG( INS_ARG )
-  {
-    DO_RUTG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RDTG[]:       Round Down To Grid                                      */
-  /* Opcode range: 0x7D                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_RDTG( INS_ARG )
-  {
-    DO_RDTG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ROFF[]:       Round OFF                                               */
-  /* Opcode range: 0x7A                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_ROFF( INS_ARG )
-  {
-    DO_ROFF
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SROUND[]:     Super ROUND                                             */
-  /* Opcode range: 0x76                                                    */
-  /* Stack:        Eint8 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SROUND( INS_ARG )
-  {
-    DO_SROUND
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* S45ROUND[]:   Super ROUND 45 degrees                                  */
-  /* Opcode range: 0x77                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_S45ROUND( INS_ARG )
-  {
-    DO_S45ROUND
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SLOOP[]:      Set LOOP variable                                       */
-  /* Opcode range: 0x17                                                    */
-  /* Stack:        int32? -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SLOOP( INS_ARG )
-  {
-    DO_SLOOP
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SMD[]:        Set Minimum Distance                                    */
-  /* Opcode range: 0x1A                                                    */
-  /* Stack:        f26.6 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SMD( INS_ARG )
-  {
-    DO_SMD
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SCVTCI[]:     Set Control Value Table Cut In                          */
-  /* Opcode range: 0x1D                                                    */
-  /* Stack:        f26.6 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SCVTCI( INS_ARG )
-  {
-    DO_SCVTCI
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SSWCI[]:      Set Single Width Cut In                                 */
-  /* Opcode range: 0x1E                                                    */
-  /* Stack:        f26.6 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_SSWCI( INS_ARG )
-  {
-    DO_SSWCI
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SSW[]:        Set Single Width                                        */
-  /* Opcode range: 0x1F                                                    */
-  /* Stack:        int32? -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SSW( INS_ARG )
-  {
-    DO_SSW
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLIPON[]:     Set auto-FLIP to ON                                     */
-  /* Opcode range: 0x4D                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_FLIPON( INS_ARG )
-  {
-    DO_FLIPON
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
-  /* Opcode range: 0x4E                                                    */
-  /* Stack: -->                                                            */
-  /*                                                                       */
-  static void
-  Ins_FLIPOFF( INS_ARG )
-  {
-    DO_FLIPOFF
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SANGW[]:      Set ANGle Weight                                        */
-  /* Opcode range: 0x7E                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SANGW( INS_ARG )
-  {
-    /* instruction not supported anymore */
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SDB[]:        Set Delta Base                                          */
-  /* Opcode range: 0x5E                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SDB( INS_ARG )
-  {
-    DO_SDB
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SDS[]:        Set Delta Shift                                         */
-  /* Opcode range: 0x5F                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SDS( INS_ARG )
-  {
-    DO_SDS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MPPEM[]:      Measure Pixel Per EM                                    */
-  /* Opcode range: 0x4B                                                    */
-  /* Stack:        --> Euint16                                             */
-  /*                                                                       */
-  static void
-  Ins_MPPEM( INS_ARG )
-  {
-    DO_MPPEM
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MPS[]:        Measure Point Size                                      */
-  /* Opcode range: 0x4C                                                    */
-  /* Stack:        --> Euint16                                             */
-  /*                                                                       */
-  static void
-  Ins_MPS( INS_ARG )
-  {
-    DO_MPS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* DUP[]:        DUPlicate the top stack's element                       */
-  /* Opcode range: 0x20                                                    */
-  /* Stack:        StkElt --> StkElt StkElt                                */
-  /*                                                                       */
-  static void
-  Ins_DUP( INS_ARG )
-  {
-    DO_DUP
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* POP[]:        POP the stack's top element                             */
-  /* Opcode range: 0x21                                                    */
-  /* Stack:        StkElt -->                                              */
-  /*                                                                       */
-  static void
-  Ins_POP( INS_ARG )
-  {
-    /* nothing to do */
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* CLEAR[]:      CLEAR the entire stack                                  */
-  /* Opcode range: 0x22                                                    */
-  /* Stack:        StkElt... -->                                           */
-  /*                                                                       */
-  static void
-  Ins_CLEAR( INS_ARG )
-  {
-    DO_CLEAR
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SWAP[]:       SWAP the stack's top two elements                       */
-  /* Opcode range: 0x23                                                    */
-  /* Stack:        2 * StkElt --> 2 * StkElt                               */
-  /*                                                                       */
-  static void
-  Ins_SWAP( INS_ARG )
-  {
-    DO_SWAP
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* DEPTH[]:      return the stack DEPTH                                  */
-  /* Opcode range: 0x24                                                    */
-  /* Stack:        --> uint32                                              */
-  /*                                                                       */
-  static void
-  Ins_DEPTH( INS_ARG )
-  {
-    DO_DEPTH
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* CINDEX[]:     Copy INDEXed element                                    */
-  /* Opcode range: 0x25                                                    */
-  /* Stack:        int32 --> StkElt                                        */
-  /*                                                                       */
-  static void
-  Ins_CINDEX( INS_ARG )
-  {
-    DO_CINDEX
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* EIF[]:        End IF                                                  */
-  /* Opcode range: 0x59                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_EIF( INS_ARG )
-  {
-    /* nothing to do */
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* JROT[]:       Jump Relative On True                                   */
-  /* Opcode range: 0x78                                                    */
-  /* Stack:        StkElt int32 -->                                        */
-  /*                                                                       */
-  static void
-  Ins_JROT( INS_ARG )
-  {
-    DO_JROT
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* JMPR[]:       JuMP Relative                                           */
-  /* Opcode range: 0x1C                                                    */
-  /* Stack:        int32 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_JMPR( INS_ARG )
-  {
-    DO_JMPR
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* JROF[]:       Jump Relative On False                                  */
-  /* Opcode range: 0x79                                                    */
-  /* Stack:        StkElt int32 -->                                        */
-  /*                                                                       */
-  static void
-  Ins_JROF( INS_ARG )
-  {
-    DO_JROF
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* LT[]:         Less Than                                               */
-  /* Opcode range: 0x50                                                    */
-  /* Stack:        int32? int32? --> bool                                  */
-  /*                                                                       */
-  static void
-  Ins_LT( INS_ARG )
-  {
-    DO_LT
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* LTEQ[]:       Less Than or EQual                                      */
-  /* Opcode range: 0x51                                                    */
-  /* Stack:        int32? int32? --> bool                                  */
-  /*                                                                       */
-  static void
-  Ins_LTEQ( INS_ARG )
-  {
-    DO_LTEQ
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* GT[]:         Greater Than                                            */
-  /* Opcode range: 0x52                                                    */
-  /* Stack:        int32? int32? --> bool                                  */
-  /*                                                                       */
-  static void
-  Ins_GT( INS_ARG )
-  {
-    DO_GT
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* GTEQ[]:       Greater Than or EQual                                   */
-  /* Opcode range: 0x53                                                    */
-  /* Stack:        int32? int32? --> bool                                  */
-  /*                                                                       */
-  static void
-  Ins_GTEQ( INS_ARG )
-  {
-    DO_GTEQ
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* EQ[]:         EQual                                                   */
-  /* Opcode range: 0x54                                                    */
-  /* Stack:        StkElt StkElt --> bool                                  */
-  /*                                                                       */
-  static void
-  Ins_EQ( INS_ARG )
-  {
-    DO_EQ
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* NEQ[]:        Not EQual                                               */
-  /* Opcode range: 0x55                                                    */
-  /* Stack:        StkElt StkElt --> bool                                  */
-  /*                                                                       */
-  static void
-  Ins_NEQ( INS_ARG )
-  {
-    DO_NEQ
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ODD[]:        Is ODD                                                  */
-  /* Opcode range: 0x56                                                    */
-  /* Stack:        f26.6 --> bool                                          */
-  /*                                                                       */
-  static void
-  Ins_ODD( INS_ARG )
-  {
-    DO_ODD
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* EVEN[]:       Is EVEN                                                 */
-  /* Opcode range: 0x57                                                    */
-  /* Stack:        f26.6 --> bool                                          */
-  /*                                                                       */
-  static void
-  Ins_EVEN( INS_ARG )
-  {
-    DO_EVEN
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* AND[]:        logical AND                                             */
-  /* Opcode range: 0x5A                                                    */
-  /* Stack:        uint32 uint32 --> uint32                                */
-  /*                                                                       */
-  static void
-  Ins_AND( INS_ARG )
-  {
-    DO_AND
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* OR[]:         logical OR                                              */
-  /* Opcode range: 0x5B                                                    */
-  /* Stack:        uint32 uint32 --> uint32                                */
-  /*                                                                       */
-  static void
-  Ins_OR( INS_ARG )
-  {
-    DO_OR
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* NOT[]:        logical NOT                                             */
-  /* Opcode range: 0x5C                                                    */
-  /* Stack:        StkElt --> uint32                                       */
-  /*                                                                       */
-  static void
-  Ins_NOT( INS_ARG )
-  {
-    DO_NOT
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ADD[]:        ADD                                                     */
-  /* Opcode range: 0x60                                                    */
-  /* Stack:        f26.6 f26.6 --> f26.6                                   */
-  /*                                                                       */
-  static void
-  Ins_ADD( INS_ARG )
-  {
-    DO_ADD
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SUB[]:        SUBtract                                                */
-  /* Opcode range: 0x61                                                    */
-  /* Stack:        f26.6 f26.6 --> f26.6                                   */
-  /*                                                                       */
-  static void
-  Ins_SUB( INS_ARG )
-  {
-    DO_SUB
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* DIV[]:        DIVide                                                  */
-  /* Opcode range: 0x62                                                    */
-  /* Stack:        f26.6 f26.6 --> f26.6                                   */
-  /*                                                                       */
-  static void
-  Ins_DIV( INS_ARG )
-  {
-    DO_DIV
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MUL[]:        MULtiply                                                */
-  /* Opcode range: 0x63                                                    */
-  /* Stack:        f26.6 f26.6 --> f26.6                                   */
-  /*                                                                       */
-  static void
-  Ins_MUL( INS_ARG )
-  {
-    DO_MUL
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ABS[]:        ABSolute value                                          */
-  /* Opcode range: 0x64                                                    */
-  /* Stack:        f26.6 --> f26.6                                         */
-  /*                                                                       */
-  static void
-  Ins_ABS( INS_ARG )
-  {
-    DO_ABS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* NEG[]:        NEGate                                                  */
-  /* Opcode range: 0x65                                                    */
-  /* Stack: f26.6 --> f26.6                                                */
-  /*                                                                       */
-  static void
-  Ins_NEG( INS_ARG )
-  {
-    DO_NEG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLOOR[]:      FLOOR                                                   */
-  /* Opcode range: 0x66                                                    */
-  /* Stack:        f26.6 --> f26.6                                         */
-  /*                                                                       */
-  static void
-  Ins_FLOOR( INS_ARG )
-  {
-    DO_FLOOR
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* CEILING[]:    CEILING                                                 */
-  /* Opcode range: 0x67                                                    */
-  /* Stack:        f26.6 --> f26.6                                         */
-  /*                                                                       */
-  static void
-  Ins_CEILING( INS_ARG )
-  {
-    DO_CEILING
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RS[]:         Read Store                                              */
-  /* Opcode range: 0x43                                                    */
-  /* Stack:        uint32 --> uint32                                       */
-  /*                                                                       */
-  static void
-  Ins_RS( INS_ARG )
-  {
-    DO_RS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* WS[]:         Write Store                                             */
-  /* Opcode range: 0x42                                                    */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_WS( INS_ARG )
-  {
-    DO_WS
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* WCVTP[]:      Write CVT in Pixel units                                */
-  /* Opcode range: 0x44                                                    */
-  /* Stack:        f26.6 uint32 -->                                        */
-  /*                                                                       */
-  static void
-  Ins_WCVTP( INS_ARG )
-  {
-    DO_WCVTP
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* WCVTF[]:      Write CVT in Funits                                     */
-  /* Opcode range: 0x70                                                    */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_WCVTF( INS_ARG )
-  {
-    DO_WCVTF
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RCVT[]:       Read CVT                                                */
-  /* Opcode range: 0x45                                                    */
-  /* Stack:        uint32 --> f26.6                                        */
-  /*                                                                       */
-  static void
-  Ins_RCVT( INS_ARG )
-  {
-    DO_RCVT
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* AA[]:         Adjust Angle                                            */
-  /* Opcode range: 0x7F                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_AA( INS_ARG )
-  {
-    /* intentionally no longer supported */
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* DEBUG[]:      DEBUG.  Unsupported.                                    */
-  /* Opcode range: 0x4F                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  /* Note: The original instruction pops a value from the stack.           */
-  /*                                                                       */
-  static void
-  Ins_DEBUG( INS_ARG )
-  {
-    DO_DEBUG
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ROUND[ab]:    ROUND value                                             */
-  /* Opcode range: 0x68-0x6B                                               */
-  /* Stack:        f26.6 --> f26.6                                         */
-  /*                                                                       */
-  static void
-  Ins_ROUND( INS_ARG )
-  {
-    DO_ROUND
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* NROUND[ab]:   No ROUNDing of value                                    */
-  /* Opcode range: 0x6C-0x6F                                               */
-  /* Stack:        f26.6 --> f26.6                                         */
-  /*                                                                       */
-  static void
-  Ins_NROUND( INS_ARG )
-  {
-    DO_NROUND
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MAX[]:        MAXimum                                                 */
-  /* Opcode range: 0x68                                                    */
-  /* Stack:        int32? int32? --> int32                                 */
-  /*                                                                       */
-  static void
-  Ins_MAX( INS_ARG )
-  {
-    DO_MAX
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MIN[]:        MINimum                                                 */
-  /* Opcode range: 0x69                                                    */
-  /* Stack:        int32? int32? --> int32                                 */
-  /*                                                                       */
-  static void
-  Ins_MIN( INS_ARG )
-  {
-    DO_MIN
-  }
-
-
-#endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The following functions are called as is within the switch statement. */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MINDEX[]:     Move INDEXed element                                    */
-  /* Opcode range: 0x26                                                    */
-  /* Stack:        int32? --> StkElt                                       */
-  /*                                                                       */
-  static void
-  Ins_MINDEX( INS_ARG )
-  {
-    FT_Long  L, K;
-
-
-    L = args[0];
-
-    if ( L <= 0 || L > CUR.args )
-    {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    K = CUR.stack[CUR.args - L];
-
-    FT_ARRAY_MOVE( &CUR.stack[CUR.args - L    ],
-                   &CUR.stack[CUR.args - L + 1],
-                   ( L - 1 ) );
-
-    CUR.stack[CUR.args - 1] = K;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ROLL[]:       ROLL top three elements                                 */
-  /* Opcode range: 0x8A                                                    */
-  /* Stack:        3 * StkElt --> 3 * StkElt                               */
-  /*                                                                       */
-  static void
-  Ins_ROLL( INS_ARG )
-  {
-    FT_Long  A, B, C;
-
-    FT_UNUSED_EXEC;
-
-
-    A = args[2];
-    B = args[1];
-    C = args[0];
-
-    args[2] = C;
-    args[1] = A;
-    args[0] = B;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MANAGING THE FLOW OF CONTROL                                          */
-  /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  static FT_Bool
-  SkipCode( EXEC_OP )
-  {
-    CUR.IP += CUR.length;
-
-    if ( CUR.IP < CUR.codeSize )
-    {
-      CUR.opcode = CUR.code[CUR.IP];
-
-      CUR.length = opcode_length[CUR.opcode];
-      if ( CUR.length < 0 )
-      {
-        if ( CUR.IP + 1 > CUR.codeSize )
-          goto Fail_Overflow;
-        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
-      }
-
-      if ( CUR.IP + CUR.length <= CUR.codeSize )
-        return SUCCESS;
-    }
-
-  Fail_Overflow:
-    CUR.error = TT_Err_Code_Overflow;
-    return FAILURE;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* IF[]:         IF test                                                 */
-  /* Opcode range: 0x58                                                    */
-  /* Stack:        StkElt -->                                              */
-  /*                                                                       */
-  static void
-  Ins_IF( INS_ARG )
-  {
-    FT_Int   nIfs;
-    FT_Bool  Out;
-
-
-    if ( args[0] != 0 )
-      return;
-
-    nIfs = 1;
-    Out = 0;
-
-    do
-    {
-      if ( SKIP_Code() == FAILURE )
-        return;
-
-      switch ( CUR.opcode )
-      {
-      case 0x58:      /* IF */
-        nIfs++;
-        break;
-
-      case 0x1B:      /* ELSE */
-        Out = FT_BOOL( nIfs == 1 );
-        break;
-
-      case 0x59:      /* EIF */
-        nIfs--;
-        Out = FT_BOOL( nIfs == 0 );
-        break;
-      }
-    } while ( Out == 0 );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ELSE[]:       ELSE                                                    */
-  /* Opcode range: 0x1B                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_ELSE( INS_ARG )
-  {
-    FT_Int  nIfs;
-
-    FT_UNUSED_ARG;
-
-
-    nIfs = 1;
-
-    do
-    {
-      if ( SKIP_Code() == FAILURE )
-        return;
-
-      switch ( CUR.opcode )
-      {
-      case 0x58:    /* IF */
-        nIfs++;
-        break;
-
-      case 0x59:    /* EIF */
-        nIfs--;
-        break;
-      }
-    } while ( nIfs != 0 );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
-  /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FDEF[]:       Function DEFinition                                     */
-  /* Opcode range: 0x2C                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_FDEF( INS_ARG )
-  {
-    FT_ULong       n;
-    TT_DefRecord*  rec;
-    TT_DefRecord*  limit;
-
-
-    /* some font programs are broken enough to redefine functions! */
-    /* We will then parse the current table.                       */
-
-    rec   = CUR.FDefs;
-    limit = rec + CUR.numFDefs;
-    n     = args[0];
-
-    for ( ; rec < limit; rec++ )
-    {
-      if ( rec->opc == n )
-        break;
-    }
-
-    if ( rec == limit )
-    {
-      /* check that there is enough room for new functions */
-      if ( CUR.numFDefs >= CUR.maxFDefs )
-      {
-        CUR.error = TT_Err_Too_Many_Function_Defs;
-        return;
-      }
-      CUR.numFDefs++;
-    }
-
-    rec->range  = CUR.curRange;
-    rec->opc    = n;
-    rec->start  = CUR.IP + 1;
-    rec->active = TRUE;
-
-    if ( n > CUR.maxFunc )
-      CUR.maxFunc = n;
-
-    /* Now skip the whole function definition. */
-    /* We don't allow nested IDEFS & FDEFs.    */
-
-    while ( SKIP_Code() == SUCCESS )
-    {
-      switch ( CUR.opcode )
-      {
-      case 0x89:    /* IDEF */
-      case 0x2C:    /* FDEF */
-        CUR.error = TT_Err_Nested_DEFS;
-        return;
-
-      case 0x2D:   /* ENDF */
-        return;
-      }
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ENDF[]:       END Function definition                                 */
-  /* Opcode range: 0x2D                                                    */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_ENDF( INS_ARG )
-  {
-    TT_CallRec*  pRec;
-
-    FT_UNUSED_ARG;
-
-
-    if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
-    {
-      CUR.error = TT_Err_ENDF_In_Exec_Stream;
-      return;
-    }
-
-    CUR.callTop--;
-
-    pRec = &CUR.callStack[CUR.callTop];
-
-    pRec->Cur_Count--;
-
-    CUR.step_ins = FALSE;
-
-    if ( pRec->Cur_Count > 0 )
-    {
-      CUR.callTop++;
-      CUR.IP = pRec->Cur_Restart;
-    }
-    else
-      /* Loop through the current function */
-      INS_Goto_CodeRange( pRec->Caller_Range,
-                          pRec->Caller_IP );
-
-    /* Exit the current call frame.                      */
-
-    /* NOTE: If the last instruction of a program is a   */
-    /*       CALL or LOOPCALL, the return address is     */
-    /*       always out of the code range.  This is a    */
-    /*       valid address, and it is why we do not test */
-    /*       the result of Ins_Goto_CodeRange() here!    */
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* CALL[]:       CALL function                                           */
-  /* Opcode range: 0x2B                                                    */
-  /* Stack:        uint32? -->                                             */
-  /*                                                                       */
-  static void
-  Ins_CALL( INS_ARG )
-  {
-    FT_ULong       F;
-    TT_CallRec*    pCrec;
-    TT_DefRecord*  def;
-
-
-    /* first of all, check the index */
-
-    F = args[0];
-    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
-      goto Fail;
-
-    /* Except for some old Apple fonts, all functions in a TrueType */
-    /* font are defined in increasing order, starting from 0.  This */
-    /* means that we normally have                                  */
-    /*                                                              */
-    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
-    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
-    /*                                                              */
-    /* If this isn't true, we need to look up the function table.   */
-
-    def = CUR.FDefs + F;
-    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
-    {
-      /* look up the FDefs table */
-      TT_DefRecord*  limit;
-
-
-      def   = CUR.FDefs;
-      limit = def + CUR.numFDefs;
-
-      while ( def < limit && def->opc != F )
-        def++;
-
-      if ( def == limit )
-        goto Fail;
-    }
-
-    /* check that the function is active */
-    if ( !def->active )
-      goto Fail;
-
-    /* check the call stack */
-    if ( CUR.callTop >= CUR.callSize )
-    {
-      CUR.error = TT_Err_Stack_Overflow;
-      return;
-    }
-
-    pCrec = CUR.callStack + CUR.callTop;
-
-    pCrec->Caller_Range = CUR.curRange;
-    pCrec->Caller_IP    = CUR.IP + 1;
-    pCrec->Cur_Count    = 1;
-    pCrec->Cur_Restart  = def->start;
-
-    CUR.callTop++;
-
-    INS_Goto_CodeRange( def->range,
-                        def->start );
-
-    CUR.step_ins = FALSE;
-    return;
-
-  Fail:
-    CUR.error = TT_Err_Invalid_Reference;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* LOOPCALL[]:   LOOP and CALL function                                  */
-  /* Opcode range: 0x2A                                                    */
-  /* Stack:        uint32? Eint16? -->                                     */
-  /*                                                                       */
-  static void
-  Ins_LOOPCALL( INS_ARG )
-  {
-    FT_ULong       F;
-    TT_CallRec*    pCrec;
-    TT_DefRecord*  def;
-
-
-    /* first of all, check the index */
-    F = args[1];
-    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
-      goto Fail;
-
-    /* Except for some old Apple fonts, all functions in a TrueType */
-    /* font are defined in increasing order, starting from 0.  This */
-    /* means that we normally have                                  */
-    /*                                                              */
-    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
-    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
-    /*                                                              */
-    /* If this isn't true, we need to look up the function table.   */
-
-    def = CUR.FDefs + F;
-    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
-    {
-      /* look up the FDefs table */
-      TT_DefRecord*  limit;
-
-
-      def   = CUR.FDefs;
-      limit = def + CUR.numFDefs;
-
-      while ( def < limit && def->opc != F )
-        def++;
-
-      if ( def == limit )
-        goto Fail;
-    }
-
-    /* check that the function is active */
-    if ( !def->active )
-      goto Fail;
-
-    /* check stack */
-    if ( CUR.callTop >= CUR.callSize )
-    {
-      CUR.error = TT_Err_Stack_Overflow;
-      return;
-    }
-
-    if ( args[0] > 0 )
-    {
-      pCrec = CUR.callStack + CUR.callTop;
-
-      pCrec->Caller_Range = CUR.curRange;
-      pCrec->Caller_IP    = CUR.IP + 1;
-      pCrec->Cur_Count    = (FT_Int)args[0];
-      pCrec->Cur_Restart  = def->start;
-
-      CUR.callTop++;
-
-      INS_Goto_CodeRange( def->range, def->start );
-
-      CUR.step_ins = FALSE;
-    }
-    return;
-
-  Fail:
-    CUR.error = TT_Err_Invalid_Reference;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* IDEF[]:       Instruction DEFinition                                  */
-  /* Opcode range: 0x89                                                    */
-  /* Stack:        Eint8 -->                                               */
-  /*                                                                       */
-  static void
-  Ins_IDEF( INS_ARG )
-  {
-    TT_DefRecord*  def;
-    TT_DefRecord*  limit;
-
-
-    /*  First of all, look for the same function in our table */
-
-    def   = CUR.IDefs;
-    limit = def + CUR.numIDefs;
-
-    for ( ; def < limit; def++ )
-      if ( def->opc == (FT_ULong)args[0] )
-        break;
-
-    if ( def == limit )
-    {
-      /* check that there is enough room for a new instruction */
-      if ( CUR.numIDefs >= CUR.maxIDefs )
-      {
-        CUR.error = TT_Err_Too_Many_Instruction_Defs;
-        return;
-      }
-      CUR.numIDefs++;
-    }
-
-    def->opc    = args[0];
-    def->start  = CUR.IP+1;
-    def->range  = CUR.curRange;
-    def->active = TRUE;
-
-    if ( (FT_ULong)args[0] > CUR.maxIns )
-      CUR.maxIns = args[0];
-
-    /* Now skip the whole function definition. */
-    /* We don't allow nested IDEFs & FDEFs.    */
-
-    while ( SKIP_Code() == SUCCESS )
-    {
-      switch ( CUR.opcode )
-      {
-      case 0x89:   /* IDEF */
-      case 0x2C:   /* FDEF */
-        CUR.error = TT_Err_Nested_DEFS;
-        return;
-      case 0x2D:   /* ENDF */
-        return;
-      }
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* PUSHING DATA ONTO THE INTERPRETER STACK                               */
-  /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* NPUSHB[]:     PUSH N Bytes                                            */
-  /* Opcode range: 0x40                                                    */
-  /* Stack:        --> uint32...                                           */
-  /*                                                                       */
-  static void
-  Ins_NPUSHB( INS_ARG )
-  {
-    FT_UShort  L, K;
-
-
-    L = (FT_UShort)CUR.code[CUR.IP + 1];
-
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
-    {
-      CUR.error = TT_Err_Stack_Overflow;
-      return;
-    }
-
-    for ( K = 1; K <= L; K++ )
-      args[K - 1] = CUR.code[CUR.IP + K + 1];
-
-    CUR.new_top += L;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* NPUSHW[]:     PUSH N Words                                            */
-  /* Opcode range: 0x41                                                    */
-  /* Stack:        --> int32...                                            */
-  /*                                                                       */
-  static void
-  Ins_NPUSHW( INS_ARG )
-  {
-    FT_UShort  L, K;
-
-
-    L = (FT_UShort)CUR.code[CUR.IP + 1];
-
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
-    {
-      CUR.error = TT_Err_Stack_Overflow;
-      return;
-    }
-
-    CUR.IP += 2;
-
-    for ( K = 0; K < L; K++ )
-      args[K] = GET_ShortIns();
-
-    CUR.step_ins = FALSE;
-    CUR.new_top += L;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* PUSHB[abc]:   PUSH Bytes                                              */
-  /* Opcode range: 0xB0-0xB7                                               */
-  /* Stack:        --> uint32...                                           */
-  /*                                                                       */
-  static void
-  Ins_PUSHB( INS_ARG )
-  {
-    FT_UShort  L, K;
-
-
-    L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
-
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
-    {
-      CUR.error = TT_Err_Stack_Overflow;
-      return;
-    }
-
-    for ( K = 1; K <= L; K++ )
-      args[K - 1] = CUR.code[CUR.IP + K];
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* PUSHW[abc]:   PUSH Words                                              */
-  /* Opcode range: 0xB8-0xBF                                               */
-  /* Stack:        --> int32...                                            */
-  /*                                                                       */
-  static void
-  Ins_PUSHW( INS_ARG )
-  {
-    FT_UShort  L, K;
-
-
-    L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
-
-    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
-    {
-      CUR.error = TT_Err_Stack_Overflow;
-      return;
-    }
-
-    CUR.IP++;
-
-    for ( K = 0; K < L; K++ )
-      args[K] = GET_ShortIns();
-
-    CUR.step_ins = FALSE;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MANAGING THE GRAPHICS STATE                                           */
-  /*                                                                       */
-  /*  Instructions appear in the specs' order.                             */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* GC[a]:        Get Coordinate projected onto                           */
-  /* Opcode range: 0x46-0x47                                               */
-  /* Stack:        uint32 --> f26.6                                        */
-  /*                                                                       */
-  /* BULLSHIT: Measures from the original glyph must be taken along the    */
-  /*           dual projection vector!                                     */
-  /*                                                                       */
-  static void
-  Ins_GC( INS_ARG )
-  {
-    FT_ULong    L;
-    FT_F26Dot6  R;
-
-
-    L = (FT_ULong)args[0];
-
-    if ( BOUNDS( L, CUR.zp2.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-      {
-        CUR.error = TT_Err_Invalid_Reference;
-        return;
-      }
-      else
-        R = 0;
-    }
-    else
-    {
-      if ( CUR.opcode & 1 )
-        R = CUR_fast_dualproj( &CUR.zp2.org[L] );
-      else
-        R = CUR_fast_project( &CUR.zp2.cur[L] );
-    }
-
-    args[0] = R;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SCFS[]:       Set Coordinate From Stack                               */
-  /* Opcode range: 0x48                                                    */
-  /* Stack:        f26.6 uint32 -->                                        */
-  /*                                                                       */
-  /* Formula:                                                              */
-  /*                                                                       */
-  /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */
-  /*                                                                       */
-  static void
-  Ins_SCFS( INS_ARG )
-  {
-    FT_Long    K;
-    FT_UShort  L;
-
-
-    L = (FT_UShort)args[0];
-
-    if ( BOUNDS( L, CUR.zp2.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    K = CUR_fast_project( &CUR.zp2.cur[L] );
-
-    CUR_Func_move( &CUR.zp2, L, args[1] - K );
-
-    /* not part of the specs, but here for safety */
-
-    if ( CUR.GS.gep2 == 0 )
-      CUR.zp2.org[L] = CUR.zp2.cur[L];
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MD[a]:        Measure Distance                                        */
-  /* Opcode range: 0x49-0x4A                                               */
-  /* Stack:        uint32 uint32 --> f26.6                                 */
-  /*                                                                       */
-  /* BULLSHIT: Measure taken in the original glyph must be along the dual  */
-  /*           projection vector.                                          */
-  /*                                                                       */
-  /* Second BULLSHIT: Flag attributes are inverted!                        */
-  /*                  0 => measure distance in original outline            */
-  /*                  1 => measure distance in grid-fitted outline         */
-  /*                                                                       */
-  /* Third one: `zp0 - zp1', and not `zp2 - zp1!                           */
-  /*                                                                       */
-  static void
-  Ins_MD( INS_ARG )
-  {
-    FT_UShort   K, L;
-    FT_F26Dot6  D;
-
-
-    K = (FT_UShort)args[1];
-    L = (FT_UShort)args[0];
-
-    if( BOUNDS( L, CUR.zp0.n_points ) ||
-        BOUNDS( K, CUR.zp1.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-      {
-        CUR.error = TT_Err_Invalid_Reference;
-        return;
-      }
-      D = 0;
-    }
-    else
-    {
-      if ( CUR.opcode & 1 )
-        D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
-      else
-        D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
-    }
-
-    args[0] = D;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SDPVTL[a]:    Set Dual PVector to Line                                */
-  /* Opcode range: 0x86-0x87                                               */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_SDPVTL( INS_ARG )
-  {
-    FT_Long    A, B, C;
-    FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */
-
-
-    p1 = (FT_UShort)args[1];
-    p2 = (FT_UShort)args[0];
-
-    if ( BOUNDS( p2, CUR.zp1.n_points ) ||
-         BOUNDS( p1, CUR.zp2.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    {
-      FT_Vector* v1 = CUR.zp1.org + p2;
-      FT_Vector* v2 = CUR.zp2.org + p1;
-
-
-      A = v1->x - v2->x;
-      B = v1->y - v2->y;
-    }
-
-    if ( ( CUR.opcode & 1 ) != 0 )
-    {
-      C =  B;   /* counter clockwise rotation */
-      B =  A;
-      A = -C;
-    }
-
-    NORMalize( A, B, &CUR.GS.dualVector );
-
-    {
-      FT_Vector*  v1 = CUR.zp1.cur + p2;
-      FT_Vector*  v2 = CUR.zp2.cur + p1;
-
-
-      A = v1->x - v2->x;
-      B = v1->y - v2->y;
-    }
-
-    if ( ( CUR.opcode & 1 ) != 0 )
-    {
-      C =  B;   /* counter clockwise rotation */
-      B =  A;
-      A = -C;
-    }
-
-    NORMalize( A, B, &CUR.GS.projVector );
-
-    GUESS_VECTOR( freeVector );
-
-    COMPUTE_Funcs();
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SZP0[]:       Set Zone Pointer 0                                      */
-  /* Opcode range: 0x13                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SZP0( INS_ARG )
-  {
-    switch ( (FT_Int)args[0] )
-    {
-    case 0:
-      CUR.zp0 = CUR.twilight;
-      break;
-
-    case 1:
-      CUR.zp0 = CUR.pts;
-      break;
-
-    default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    CUR.GS.gep0 = (FT_UShort)args[0];
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SZP1[]:       Set Zone Pointer 1                                      */
-  /* Opcode range: 0x14                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SZP1( INS_ARG )
-  {
-    switch ( (FT_Int)args[0] )
-    {
-    case 0:
-      CUR.zp1 = CUR.twilight;
-      break;
-
-    case 1:
-      CUR.zp1 = CUR.pts;
-      break;
-
-    default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    CUR.GS.gep1 = (FT_UShort)args[0];
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SZP2[]:       Set Zone Pointer 2                                      */
-  /* Opcode range: 0x15                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SZP2( INS_ARG )
-  {
-    switch ( (FT_Int)args[0] )
-    {
-    case 0:
-      CUR.zp2 = CUR.twilight;
-      break;
-
-    case 1:
-      CUR.zp2 = CUR.pts;
-      break;
-
-    default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    CUR.GS.gep2 = (FT_UShort)args[0];
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SZPS[]:       Set Zone PointerS                                       */
-  /* Opcode range: 0x16                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SZPS( INS_ARG )
-  {
-    switch ( (FT_Int)args[0] )
-    {
-    case 0:
-      CUR.zp0 = CUR.twilight;
-      break;
-
-    case 1:
-      CUR.zp0 = CUR.pts;
-      break;
-
-    default:
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    CUR.zp1 = CUR.zp0;
-    CUR.zp2 = CUR.zp0;
-
-    CUR.GS.gep0 = (FT_UShort)args[0];
-    CUR.GS.gep1 = (FT_UShort)args[0];
-    CUR.GS.gep2 = (FT_UShort)args[0];
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* INSTCTRL[]:   INSTruction ConTRoL                                     */
-  /* Opcode range: 0x8e                                                    */
-  /* Stack:        int32 int32 -->                                         */
-  /*                                                                       */
-  static void
-  Ins_INSTCTRL( INS_ARG )
-  {
-    FT_Long  K, L;
-
-
-    K = args[1];
-    L = args[0];
-
-    if ( K < 1 || K > 2 )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    if ( L != 0 )
-        L = K;
-
-    CUR.GS.instruct_control = FT_BOOL(
-      ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SCANCTRL[]:   SCAN ConTRoL                                            */
-  /* Opcode range: 0x85                                                    */
-  /* Stack:        uint32? -->                                             */
-  /*                                                                       */
-  static void
-  Ins_SCANCTRL( INS_ARG )
-  {
-    FT_Int  A;
-
-
-    /* Get Threshold */
-    A = (FT_Int)( args[0] & 0xFF );
-
-    if ( A == 0xFF )
-    {
-      CUR.GS.scan_control = TRUE;
-      return;
-    }
-    else if ( A == 0 )
-    {
-      CUR.GS.scan_control = FALSE;
-      return;
-    }
-
-    A *= 64;
-
-#if 0
-    if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )
-      CUR.GS.scan_control = TRUE;
-#endif
-
-    if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
-      CUR.GS.scan_control = TRUE;
-
-    if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
-      CUR.GS.scan_control = TRUE;
-
-#if 0
-    if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )
-      CUR.GS.scan_control = FALSE;
-#endif
-
-    if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
-      CUR.GS.scan_control = FALSE;
-
-    if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
-      CUR.GS.scan_control = FALSE;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SCANTYPE[]:   SCAN TYPE                                               */
-  /* Opcode range: 0x8D                                                    */
-  /* Stack:        uint32? -->                                             */
-  /*                                                                       */
-  static void
-  Ins_SCANTYPE( INS_ARG )
-  {
-    /* for compatibility with future enhancements, */
-    /* we must ignore new modes                    */
-
-    if ( args[0] >= 0 && args[0] <= 5 )
-    {
-      if ( args[0] == 3 )
-        args[0] = 2;
-
-      CUR.GS.scan_type = (FT_Int)args[0];
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MANAGING OUTLINES                                                     */
-  /*                                                                       */
-  /*   Instructions appear in the specification's order.                   */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLIPPT[]:     FLIP PoinT                                              */
-  /* Opcode range: 0x80                                                    */
-  /* Stack:        uint32... -->                                           */
-  /*                                                                       */
-  static void
-  Ins_FLIPPT( INS_ARG )
-  {
-    FT_UShort  point;
-
-    FT_UNUSED_ARG;
-
-
-    if ( CUR.top < CUR.GS.loop )
-    {
-      CUR.error = TT_Err_Too_Few_Arguments;
-      return;
-    }
-
-    while ( CUR.GS.loop > 0 )
-    {
-      CUR.args--;
-
-      point = (FT_UShort)CUR.stack[CUR.args];
-
-      if ( BOUNDS( point, CUR.pts.n_points ) )
-      {
-        if ( CUR.pedantic_hinting )
-        {
-          CUR.error = TT_Err_Invalid_Reference;
-          return;
-        }
-      }
-      else
-        CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
-
-      CUR.GS.loop--;
-    }
-
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLIPRGON[]:   FLIP RanGe ON                                           */
-  /* Opcode range: 0x81                                                    */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_FLIPRGON( INS_ARG )
-  {
-    FT_UShort  I, K, L;
-
-
-    K = (FT_UShort)args[1];
-    L = (FT_UShort)args[0];
-
-    if ( BOUNDS( K, CUR.pts.n_points ) ||
-         BOUNDS( L, CUR.pts.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    for ( I = L; I <= K; I++ )
-      CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* FLIPRGOFF:    FLIP RanGe OFF                                          */
-  /* Opcode range: 0x82                                                    */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_FLIPRGOFF( INS_ARG )
-  {
-    FT_UShort  I, K, L;
-
-
-    K = (FT_UShort)args[1];
-    L = (FT_UShort)args[0];
-
-    if ( BOUNDS( K, CUR.pts.n_points ) ||
-         BOUNDS( L, CUR.pts.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    for ( I = L; I <= K; I++ )
-      CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
-  }
-
-
-  static FT_Bool
-  Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*   x,
-                                       FT_F26Dot6*   y,
-                                       TT_GlyphZone  zone,
-                                       FT_UShort*    refp )
-  {
-    TT_GlyphZoneRec  zp;
-    FT_UShort        p;
-    FT_F26Dot6       d;
-
-
-    if ( CUR.opcode & 1 )
-    {
-      zp = CUR.zp0;
-      p  = CUR.GS.rp1;
-    }
-    else
-    {
-      zp = CUR.zp1;
-      p  = CUR.GS.rp2;
-    }
-
-    if ( BOUNDS( p, zp.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      *refp = 0;
-      return FAILURE;
-    }
-
-    *zone = zp;
-    *refp = p;
-
-    d = CUR_Func_project( zp.cur + p, zp.org + p );
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
-    {
-      if ( CUR.GS.both_x_axis )
-      {
-        *x = d;
-        *y = 0;
-      }
-      else
-      {
-        *x = 0;
-        *y = d;
-      }
-    }
-    else
-#endif
-    {
-      *x = TT_MULDIV( d,
-                      (FT_Long)CUR.GS.freeVector.x * 0x10000L,
-                      CUR.F_dot_P );
-      *y = TT_MULDIV( d,
-                      (FT_Long)CUR.GS.freeVector.y * 0x10000L,
-                      CUR.F_dot_P );
-    }
-
-    return SUCCESS;
-  }
-
-
-  static void
-  Move_Zp2_Point( EXEC_OP_ FT_UShort   point,
-                           FT_F26Dot6  dx,
-                           FT_F26Dot6  dy,
-                           FT_Bool     touch )
-  {
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
-    {
-      if ( CUR.GS.both_x_axis )
-      {
-        CUR.zp2.cur[point].x += dx;
-        if ( touch )
-          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
-      }
-      else
-      {
-        CUR.zp2.cur[point].y += dy;
-        if ( touch )
-          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
-      }
-      return;
-    }
-#endif
-
-    if ( CUR.GS.freeVector.x != 0 )
-    {
-      CUR.zp2.cur[point].x += dx;
-      if ( touch )
-        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
-    }
-
-    if ( CUR.GS.freeVector.y != 0 )
-    {
-      CUR.zp2.cur[point].y += dy;
-      if ( touch )
-        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SHP[a]:       SHift Point by the last point                           */
-  /* Opcode range: 0x32-0x33                                               */
-  /* Stack:        uint32... -->                                           */
-  /*                                                                       */
-  static void
-  Ins_SHP( INS_ARG )
-  {
-    TT_GlyphZoneRec  zp;
-    FT_UShort        refp;
-
-    FT_F26Dot6       dx,
-                     dy;
-    FT_UShort        point;
-
-    FT_UNUSED_ARG;
-
-
-    if ( CUR.top < CUR.GS.loop )
-    {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
-      return;
-
-    while ( CUR.GS.loop > 0 )
-    {
-      CUR.args--;
-      point = (FT_UShort)CUR.stack[CUR.args];
-
-      if ( BOUNDS( point, CUR.zp2.n_points ) )
-      {
-        if ( CUR.pedantic_hinting )
-        {
-          CUR.error = TT_Err_Invalid_Reference;
-          return;
-        }
-      }
-      else
-        /* XXX: UNDOCUMENTED! SHP touches the points */
-        MOVE_Zp2_Point( point, dx, dy, TRUE );
-
-      CUR.GS.loop--;
-    }
-
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SHC[a]:       SHift Contour                                           */
-  /* Opcode range: 0x34-35                                                 */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SHC( INS_ARG )
-  {
-    TT_GlyphZoneRec zp;
-    FT_UShort       refp;
-    FT_F26Dot6      dx,
-                    dy;
-
-    FT_Short        contour;
-    FT_UShort       first_point, last_point, i;
-
-
-    contour = (FT_UShort)args[0];
-
-    if ( BOUNDS( contour, CUR.pts.n_contours ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
-      return;
-
-    if ( contour == 0 )
-      first_point = 0;
-    else
-      first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
-                                 CUR.pts.first_point );
-
-    last_point = (FT_UShort)( CUR.pts.contours[contour] -
-                              CUR.pts.first_point );
-
-    /* XXX: this is probably wrong... at least it prevents memory */
-    /*      corruption when zp2 is the twilight zone              */
-    if ( last_point > CUR.zp2.n_points )
-    {
-      if ( CUR.zp2.n_points > 0 )
-        last_point = (FT_UShort)(CUR.zp2.n_points - 1);
-      else
-        last_point = 0;
-    }
-
-    /* XXX: UNDOCUMENTED! SHC touches the points */
-    for ( i = first_point; i <= last_point; i++ )
-    {
-      if ( zp.cur != CUR.zp2.cur || refp != i )
-        MOVE_Zp2_Point( i, dx, dy, TRUE );
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SHZ[a]:       SHift Zone                                              */
-  /* Opcode range: 0x36-37                                                 */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_SHZ( INS_ARG )
-  {
-    TT_GlyphZoneRec zp;
-    FT_UShort       refp;
-    FT_F26Dot6      dx,
-                    dy;
-
-    FT_UShort       last_point, i;
-
-
-    if ( BOUNDS( args[0], 2 ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
-      return;
-
-    /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points.  */
-    /*      Twilight zone has no contours, so use `n_points'.   */
-    /*      Normal zone's `n_points' includes phantoms, so must */
-    /*      use end of last contour.                            */
-    if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
-      last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
-    else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
-      last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
-    else
-      last_point = 0;
-
-    /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
-    for ( i = 0; i <= last_point; i++ )
-    {
-      if ( zp.cur != CUR.zp2.cur || refp != i )
-        MOVE_Zp2_Point( i, dx, dy, FALSE );
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* SHPIX[]:      SHift points by a PIXel amount                          */
-  /* Opcode range: 0x38                                                    */
-  /* Stack:        f26.6 uint32... -->                                     */
-  /*                                                                       */
-  static void
-  Ins_SHPIX( INS_ARG )
-  {
-    FT_F26Dot6  dx, dy;
-    FT_UShort   point;
-
-
-    if ( CUR.top < CUR.GS.loop + 1 )
-    {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    if ( CUR.face->unpatented_hinting )
-    {
-      if ( CUR.GS.both_x_axis )
-      {
-        dx = TT_MulFix14( args[0], 0x4000 );
-        dy = 0;
-      }
-      else
-      {
-        dx = 0;
-        dy = TT_MulFix14( args[0], 0x4000 );
-      }
-    }
-    else
-#endif
-    {
-      dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
-      dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
-    }
-
-    while ( CUR.GS.loop > 0 )
-    {
-      CUR.args--;
-
-      point = (FT_UShort)CUR.stack[CUR.args];
-
-      if ( BOUNDS( point, CUR.zp2.n_points ) )
-      {
-        if ( CUR.pedantic_hinting )
-        {
-          CUR.error = TT_Err_Invalid_Reference;
-          return;
-        }
-      }
-      else
-        MOVE_Zp2_Point( point, dx, dy, TRUE );
-
-      CUR.GS.loop--;
-    }
-
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MSIRP[a]:     Move Stack Indirect Relative Position                   */
-  /* Opcode range: 0x3A-0x3B                                               */
-  /* Stack:        f26.6 uint32 -->                                        */
-  /*                                                                       */
-  static void
-  Ins_MSIRP( INS_ARG )
-  {
-    FT_UShort   point;
-    FT_F26Dot6  distance;
-
-
-    point = (FT_UShort)args[0];
-
-    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    /* XXX: UNDOCUMENTED! behaviour */
-    if ( CUR.GS.gep1 == 0 )   /* if the point that is to be moved */
-                              /* is in twilight zone              */
-    {
-      CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
-      CUR_Func_move_orig( &CUR.zp1, point, args[1] );
-      CUR.zp1.cur[point] = CUR.zp1.org[point];
-    }
-
-    distance = CUR_Func_project( CUR.zp1.cur + point,
-                                 CUR.zp0.cur + CUR.GS.rp0 );
-
-    CUR_Func_move( &CUR.zp1, point, args[1] - distance );
-
-    CUR.GS.rp1 = CUR.GS.rp0;
-    CUR.GS.rp2 = point;
-
-    if ( ( CUR.opcode & 1 ) != 0 )
-      CUR.GS.rp0 = point;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MDAP[a]:      Move Direct Absolute Point                              */
-  /* Opcode range: 0x2E-0x2F                                               */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_MDAP( INS_ARG )
-  {
-    FT_UShort   point;
-    FT_F26Dot6  cur_dist,
-                distance;
-
-
-    point = (FT_UShort)args[0];
-
-    if ( BOUNDS( point, CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    /* XXX: Is there some undocumented feature while in the */
-    /*      twilight zone? ?                                */
-    if ( ( CUR.opcode & 1 ) != 0 )
-    {
-      cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
-      distance = CUR_Func_round( cur_dist,
-                                 CUR.tt_metrics.compensations[0] ) - cur_dist;
-    }
-    else
-      distance = 0;
-
-    CUR_Func_move( &CUR.zp0, point, distance );
-
-    CUR.GS.rp0 = point;
-    CUR.GS.rp1 = point;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MIAP[a]:      Move Indirect Absolute Point                            */
-  /* Opcode range: 0x3E-0x3F                                               */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_MIAP( INS_ARG )
-  {
-    FT_ULong    cvtEntry;
-    FT_UShort   point;
-    FT_F26Dot6  distance,
-                org_dist;
-
-
-    cvtEntry = (FT_ULong)args[1];
-    point    = (FT_UShort)args[0];
-
-    if ( BOUNDS( point,    CUR.zp0.n_points ) ||
-         BOUNDS( cvtEntry, CUR.cvtSize )      )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    /* XXX: UNDOCUMENTED!                                */
-    /*                                                   */
-    /* The behaviour of an MIAP instruction is quite     */
-    /* different when used in the twilight zone.         */
-    /*                                                   */
-    /* First, no control value cut-in test is performed  */
-    /* as it would fail anyway.  Second, the original    */
-    /* point, i.e. (org_x,org_y) of zp0.point, is set    */
-    /* to the absolute, unrounded distance found in      */
-    /* the CVT.                                          */
-    /*                                                   */
-    /* This is used in the CVT programs of the Microsoft */
-    /* fonts Arial, Times, etc., in order to re-adjust   */
-    /* some key font heights.  It allows the use of the  */
-    /* IP instruction in the twilight zone, which        */
-    /* otherwise would be `illegal' according to the     */
-    /* specification.                                    */
-    /*                                                   */
-    /* We implement it with a special sequence for the   */
-    /* twilight zone.  This is a bad hack, but it seems  */
-    /* to work.                                          */
-
-    distance = CUR_Func_read_cvt( cvtEntry );
-
-    if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
-    {
-      CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );
-      CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ),
-      CUR.zp0.cur[point]   = CUR.zp0.org[point];
-    }
-
-    org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
-
-    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */
-    {
-      if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
-        distance = org_dist;
-
-      distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
-    }
-
-    CUR_Func_move( &CUR.zp0, point, distance - org_dist );
-
-    CUR.GS.rp0 = point;
-    CUR.GS.rp1 = point;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MDRP[abcde]:  Move Direct Relative Point                              */
-  /* Opcode range: 0xC0-0xDF                                               */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_MDRP( INS_ARG )
-  {
-    FT_UShort   point;
-    FT_F26Dot6  org_dist, distance;
-
-
-    point = (FT_UShort)args[0];
-
-    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    /* XXX: Is there some undocumented feature while in the */
-    /*      twilight zone?                                  */
-
-    /* XXX: UNDOCUMENTED: twilight zone special case */
-
-    if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
-    {
-      FT_Vector*  vec1 = &CUR.zp1.org[point];
-      FT_Vector*  vec2 = &CUR.zp0.org[CUR.GS.rp0];
-
-
-      org_dist = CUR_Func_dualproj( vec1, vec2 );
-    }
-    else
-    {
-      FT_Vector*  vec1 = &CUR.zp1.orus[point];
-      FT_Vector*  vec2 = &CUR.zp0.orus[CUR.GS.rp0];
-
-
-      if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
-      {
-        /* this should be faster */
-        org_dist = CUR_Func_dualproj( vec1, vec2 );
-        org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
-      }
-      else
-      {
-        FT_Vector  vec;
-
-
-        vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
-        vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
-
-        org_dist = CUR_fast_dualproj( &vec );
-      }
-    }
-
-    /* single width cut-in test */
-
-    if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
-         CUR.GS.single_width_cutin )
-    {
-      if ( org_dist >= 0 )
-        org_dist = CUR.GS.single_width_value;
-      else
-        org_dist = -CUR.GS.single_width_value;
-    }
-
-    /* round flag */
-
-    if ( ( CUR.opcode & 4 ) != 0 )
-      distance = CUR_Func_round(
-                   org_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
-    else
-      distance = ROUND_None(
-                   org_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
-
-    /* minimum distance flag */
-
-    if ( ( CUR.opcode & 8 ) != 0 )
-    {
-      if ( org_dist >= 0 )
-      {
-        if ( distance < CUR.GS.minimum_distance )
-          distance = CUR.GS.minimum_distance;
-      }
-      else
-      {
-        if ( distance > -CUR.GS.minimum_distance )
-          distance = -CUR.GS.minimum_distance;
-      }
-    }
-
-    /* now move the point */
-
-    org_dist = CUR_Func_project( CUR.zp1.cur + point,
-                                 CUR.zp0.cur + CUR.GS.rp0 );
-
-    CUR_Func_move( &CUR.zp1, point, distance - org_dist );
-
-    CUR.GS.rp1 = CUR.GS.rp0;
-    CUR.GS.rp2 = point;
-
-    if ( ( CUR.opcode & 16 ) != 0 )
-      CUR.GS.rp0 = point;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MIRP[abcde]:  Move Indirect Relative Point                            */
-  /* Opcode range: 0xE0-0xFF                                               */
-  /* Stack:        int32? uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_MIRP( INS_ARG )
-  {
-    FT_UShort   point;
-    FT_ULong    cvtEntry;
-
-    FT_F26Dot6  cvt_dist,
-                distance,
-                cur_dist,
-                org_dist;
-
-
-    point    = (FT_UShort)args[0];
-    cvtEntry = (FT_ULong)( args[1] + 1 );
-
-    /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
-
-    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
-         BOUNDS( cvtEntry,   CUR.cvtSize + 1 )  ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    if ( !cvtEntry )
-      cvt_dist = 0;
-    else
-      cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
-
-    /* single width test */
-
-    if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
-         CUR.GS.single_width_cutin )
-    {
-      if ( cvt_dist >= 0 )
-        cvt_dist =  CUR.GS.single_width_value;
-      else
-        cvt_dist = -CUR.GS.single_width_value;
-    }
-
-    /* XXX: UNDOCUMENTED! -- twilight zone */
-
-    if ( CUR.GS.gep1 == 0 )
-    {
-      CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
-                             TT_MulFix14( cvt_dist, CUR.GS.freeVector.x );
-
-      CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
-                             TT_MulFix14( cvt_dist, CUR.GS.freeVector.y );
-
-      CUR.zp1.cur[point] = CUR.zp0.cur[point];
-    }
-
-    org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
-                                  &CUR.zp0.org[CUR.GS.rp0] );
-    cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
-                                  &CUR.zp0.cur[CUR.GS.rp0] );
-
-    /* auto-flip test */
-
-    if ( CUR.GS.auto_flip )
-    {
-      if ( ( org_dist ^ cvt_dist ) < 0 )
-        cvt_dist = -cvt_dist;
-    }
-
-    /* control value cutin and round */
-
-    if ( ( CUR.opcode & 4 ) != 0 )
-    {
-      /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
-      /*      refer to the same zone.                                  */
-
-      if ( CUR.GS.gep0 == CUR.GS.gep1 )
-        if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
-          cvt_dist = org_dist;
-
-      distance = CUR_Func_round(
-                   cvt_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
-    }
-    else
-      distance = ROUND_None(
-                   cvt_dist,
-                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
-
-    /* minimum distance test */
-
-    if ( ( CUR.opcode & 8 ) != 0 )
-    {
-      if ( org_dist >= 0 )
-      {
-        if ( distance < CUR.GS.minimum_distance )
-          distance = CUR.GS.minimum_distance;
-      }
-      else
-      {
-        if ( distance > -CUR.GS.minimum_distance )
-          distance = -CUR.GS.minimum_distance;
-      }
-    }
-
-    CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
-
-    CUR.GS.rp1 = CUR.GS.rp0;
-
-    if ( ( CUR.opcode & 16 ) != 0 )
-      CUR.GS.rp0 = point;
-
-    /* XXX: UNDOCUMENTED! */
-    CUR.GS.rp2 = point;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ALIGNRP[]:    ALIGN Relative Point                                    */
-  /* Opcode range: 0x3C                                                    */
-  /* Stack:        uint32 uint32... -->                                    */
-  /*                                                                       */
-  static void
-  Ins_ALIGNRP( INS_ARG )
-  {
-    FT_UShort   point;
-    FT_F26Dot6  distance;
-
-    FT_UNUSED_ARG;
-
-
-    if ( CUR.top < CUR.GS.loop ||
-         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    while ( CUR.GS.loop > 0 )
-    {
-      CUR.args--;
-
-      point = (FT_UShort)CUR.stack[CUR.args];
-
-      if ( BOUNDS( point, CUR.zp1.n_points ) )
-      {
-        if ( CUR.pedantic_hinting )
-        {
-          CUR.error = TT_Err_Invalid_Reference;
-          return;
-        }
-      }
-      else
-      {
-        distance = CUR_Func_project( CUR.zp1.cur + point,
-                                     CUR.zp0.cur + CUR.GS.rp0 );
-
-        CUR_Func_move( &CUR.zp1, point, -distance );
-      }
-
-      CUR.GS.loop--;
-    }
-
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ISECT[]:      moves point to InterSECTion                             */
-  /* Opcode range: 0x0F                                                    */
-  /* Stack:        5 * uint32 -->                                          */
-  /*                                                                       */
-  static void
-  Ins_ISECT( INS_ARG )
-  {
-    FT_UShort   point,
-                a0, a1,
-                b0, b1;
-
-    FT_F26Dot6  discriminant;
-
-    FT_F26Dot6  dx,  dy,
-                dax, day,
-                dbx, dby;
-
-    FT_F26Dot6  val;
-
-    FT_Vector   R;
-
-
-    point = (FT_UShort)args[0];
-
-    a0 = (FT_UShort)args[1];
-    a1 = (FT_UShort)args[2];
-    b0 = (FT_UShort)args[3];
-    b1 = (FT_UShort)args[4];
-
-    if ( BOUNDS( b0, CUR.zp0.n_points )  ||
-         BOUNDS( b1, CUR.zp0.n_points )  ||
-         BOUNDS( a0, CUR.zp1.n_points )  ||
-         BOUNDS( a1, CUR.zp1.n_points )  ||
-         BOUNDS( point, CUR.zp2.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
-    dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
-
-    dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
-    day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
-
-    dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
-    dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
-
-    CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
-
-    discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
-                   TT_MULDIV( day, dbx, 0x40 );
-
-    if ( FT_ABS( discriminant ) >= 0x40 )
-    {
-      val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
-
-      R.x = TT_MULDIV( val, dax, discriminant );
-      R.y = TT_MULDIV( val, day, discriminant );
-
-      CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
-      CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
-    }
-    else
-    {
-      /* else, take the middle of the middles of A and B */
-
-      CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
-                               CUR.zp1.cur[a1].x +
-                               CUR.zp0.cur[b0].x +
-                               CUR.zp0.cur[b1].x ) / 4;
-      CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
-                               CUR.zp1.cur[a1].y +
-                               CUR.zp0.cur[b0].y +
-                               CUR.zp0.cur[b1].y ) / 4;
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* ALIGNPTS[]:   ALIGN PoinTS                                            */
-  /* Opcode range: 0x27                                                    */
-  /* Stack:        uint32 uint32 -->                                       */
-  /*                                                                       */
-  static void
-  Ins_ALIGNPTS( INS_ARG )
-  {
-    FT_UShort   p1, p2;
-    FT_F26Dot6  distance;
-
-
-    p1 = (FT_UShort)args[0];
-    p2 = (FT_UShort)args[1];
-
-    if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
-         BOUNDS( args[1], CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    distance = CUR_Func_project( CUR.zp0.cur + p2,
-                                 CUR.zp1.cur + p1 ) / 2;
-
-    CUR_Func_move( &CUR.zp1, p1, distance );
-    CUR_Func_move( &CUR.zp0, p2, -distance );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* IP[]:         Interpolate Point                                       */
-  /* Opcode range: 0x39                                                    */
-  /* Stack:        uint32... -->                                           */
-  /*                                                                       */
-
-  /* SOMETIMES, DUMBER CODE IS BETTER CODE */
-
-  static void
-  Ins_IP( INS_ARG )
-  {
-    FT_F26Dot6  old_range, cur_range;
-    FT_Vector*  orus_base;
-    FT_Vector*  cur_base;
-    FT_Int      twilight;
-
-    FT_UNUSED_ARG;
-
-
-    if ( CUR.top < CUR.GS.loop )
-    {
-      CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    /*
-     * We need to deal in a special way with the twilight zone.
-     * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
-     * for every n.
-     */
-    twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
-
-    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    if ( twilight )
-      orus_base = &CUR.zp0.org[CUR.GS.rp1];
-    else
-      orus_base = &CUR.zp0.orus[CUR.GS.rp1];
-
-    cur_base = &CUR.zp0.cur[CUR.GS.rp1];
-
-    /* XXX: There are some glyphs in some braindead but popular */
-    /*      fonts out there (e.g. [aeu]grave in monotype.ttf)   */
-    /*      calling IP[] with bad values of rp[12].             */
-    /*      Do something sane when this odd thing happens.      */
-    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
-         BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
-    {
-      old_range = 0;
-      cur_range = 0;
-    }
-    else
-    {
-      if ( twilight )
-        old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
-                                       orus_base );
-      else
-        old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
-                                       orus_base );
-
-      cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
-    }
-
-    for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
-    {
-      FT_UInt     point = (FT_UInt)CUR.stack[--CUR.args];
-      FT_F26Dot6  org_dist, cur_dist, new_dist;
-
-
-      /* check point bounds */
-      if ( BOUNDS( point, CUR.zp2.n_points ) )
-      {
-        if ( CUR.pedantic_hinting )
-        {
-          CUR.error = TT_Err_Invalid_Reference;
-          return;
-        }
-        continue;
-      }
-
-      if ( twilight )
-        org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
-      else
-        org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
-
-      cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
-      new_dist = ( old_range != 0 )
-                   ? TT_MULDIV( org_dist, cur_range, old_range )
-                   : cur_dist;
-
-      CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
-    }
-    CUR.GS.loop = 1;
-    CUR.new_top = CUR.args;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* UTP[a]:       UnTouch Point                                           */
-  /* Opcode range: 0x29                                                    */
-  /* Stack:        uint32 -->                                              */
-  /*                                                                       */
-  static void
-  Ins_UTP( INS_ARG )
-  {
-    FT_UShort  point;
-    FT_Byte    mask;
-
-
-    point = (FT_UShort)args[0];
-
-    if ( BOUNDS( point, CUR.zp0.n_points ) )
-    {
-      if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
-      return;
-    }
-
-    mask = 0xFF;
-
-    if ( CUR.GS.freeVector.x != 0 )
-      mask &= ~FT_CURVE_TAG_TOUCH_X;
-
-    if ( CUR.GS.freeVector.y != 0 )
-      mask &= ~FT_CURVE_TAG_TOUCH_Y;
-
-    CUR.zp0.tags[point] &= mask;
-  }
-
-
-  /* Local variables for Ins_IUP: */
-  typedef struct
-  {
-    FT_Vector*  orgs;   /* original and current coordinate */
-    FT_Vector*  curs;   /* arrays                          */
-    FT_Vector*  orus;
-    FT_UInt     max_points;
-
-  } IUP_WorkerRec, *IUP_Worker;
-
-
-  static void
-  _iup_worker_shift( IUP_Worker  worker,
-                     FT_UInt     p1,
-                     FT_UInt     p2,
-                     FT_UInt     p )
-  {
-    FT_UInt     i;
-    FT_F26Dot6  dx;
-
-
-    dx = worker->curs[p].x - worker->orgs[p].x;
-    if ( dx != 0 )
-    {
-      for ( i = p1; i < p; i++ )
-        worker->curs[i].x += dx;
-
-      for ( i = p + 1; i <= p2; i++ )
-        worker->curs[i].x += dx;
-    }
-  }
-
-
-  static void
-  _iup_worker_interpolate( IUP_Worker  worker,
-                           FT_UInt     p1,
-                           FT_UInt     p2,
-                           FT_UInt     ref1,
-                           FT_UInt     ref2 )
-  {
-    FT_UInt     i;
-    FT_F26Dot6  orus1, orus2, org1, org2, delta1, delta2;
-
-
-    if ( p1 > p2 )
-      return;
-
-    if ( BOUNDS( ref1, worker->max_points ) ||
-         BOUNDS( ref2, worker->max_points ) )
-      return;
-
-    orus1 = worker->orus[ref1].x;
-    orus2 = worker->orus[ref2].x;
-
-    if ( orus1 > orus2 )
-    {
-      FT_F26Dot6  tmp_o;
-      FT_UInt     tmp_r;
-
-
-      tmp_o = orus1;
-      orus1 = orus2;
-      orus2 = tmp_o;
-
-      tmp_r = ref1;
-      ref1  = ref2;
-      ref2  = tmp_r;
-    }
-
-    org1   = worker->orgs[ref1].x;
-    org2   = worker->orgs[ref2].x;
-    delta1 = worker->curs[ref1].x - org1;
-    delta2 = worker->curs[ref2].x - org2;
-
-    if ( orus1 == orus2 )
-    {
-      /* simple shift of untouched points */
-      for ( i = p1; i <= p2; i++ )
-      {
-        FT_F26Dot6  x = worker->orgs[i].x;
-
-
-        if ( x <= org1 )
-          x += delta1;
-        else
-          x += delta2;
-
-        worker->curs[i].x = x;
-      }
-    }
-    else
-    {
-      FT_Fixed  scale       = 0;
-      FT_Bool   scale_valid = 0;
-
-
-      /* interpolation */
-      for ( i = p1; i <= p2; i++ )
-      {
-        FT_F26Dot6  x = worker->orgs[i].x;
-
-
-        if ( x <= org1 )
-          x += delta1;
-
-        else if ( x >= org2 )
-          x += delta2;
-
-        else
-        {
-          if ( !scale_valid )
-          {
-            scale_valid = 1;
-            scale       = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
-                                     0x10000, orus2 - orus1 );
-          }
-
-          x = ( org1 + delta1 ) +
-              TT_MULFIX( worker->orus[i].x - orus1, scale );
-        }
-        worker->curs[i].x = x;
-      }
-    }
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* IUP[a]:       Interpolate Untouched Points                            */
-  /* Opcode range: 0x30-0x31                                               */
-  /* Stack:        -->                                                     */
-  /*                                                                       */
-  static void
-  Ins_IUP( INS_ARG )
-  {
-    IUP_WorkerRec  V;
-    FT_Byte        mask;
-
-    FT_UInt   first_point;   /* first point of contour        */
-    FT_UInt   end_point;     /* end point (last+1) of contour */
-
-    FT_UInt   first_touched; /* first touched point in contour   */
-    FT_UInt   cur_touched;   /* current touched point in contour */
-
-    FT_UInt   point;         /* current point   */
-    FT_Short  contour;       /* current contour */
-
-    FT_UNUSED_ARG;
-
-
-    /* ignore empty outlines */
-    if ( CUR.pts.n_contours == 0 )
-      return;
-
-    if ( CUR.opcode & 1 )
-    {
-      mask   = FT_CURVE_TAG_TOUCH_X;
-      V.orgs = CUR.pts.org;
-      V.curs = CUR.pts.cur;
-      V.orus = CUR.pts.orus;
-    }
-    else
-    {
-      mask   = FT_CURVE_TAG_TOUCH_Y;
-      V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
-      V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
-      V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
-    }
-    V.max_points = CUR.pts.n_points;
-
-    contour = 0;
-    point   = 0;
-
-    do
-    {
-      end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;
-      first_point = point;
-
-      while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
-        point++;
-
-      if ( point <= end_point )
-      {
-        first_touched = point;
-        cur_touched   = point;
-
-        point++;
-
-        while ( point <= end_point )
-        {
-          if ( ( CUR.pts.tags[point] & mask ) != 0 )
-          {
-            if ( point > 0 )
-              _iup_worker_interpolate( &V,
-                                       cur_touched + 1,
-                                       point - 1,
-                                       cur_touched,
-                                       point );
-            cur_touched = point;
-          }
-
-          point++;
-        }
-
-        if ( cur_touched == first_touched )
-          _iup_worker_shift( &V, first_point, end_point, cur_touched );
-        else
-        {
-          _iup_worker_interpolate( &V,
-                                   (FT_UShort)( cur_touched + 1 ),
-                                   end_point,
-                                   cur_touched,
-                                   first_touched );
-
-          if ( first_touched > 0 )
-            _iup_worker_interpolate( &V,
-                                     first_point,
-                                     first_touched - 1,
-                                     cur_touched,
-                                     first_touched );
-        }
-      }
-      contour++;
-    } while ( contour < CUR.pts.n_contours );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* DELTAPn[]:    DELTA exceptions P1, P2, P3                             */
-  /* Opcode range: 0x5D,0x71,0x72                                          */
-  /* Stack:        uint32 (2 * uint32)... -->                              */
-  /*                                                                       */
-  static void
-  Ins_DELTAP( INS_ARG )
-  {
-    FT_ULong   k, nump;
-    FT_UShort  A;
-    FT_ULong   C;
-    FT_Long    B;
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    /* Delta hinting is covered by US Patent 5159668. */
-    if ( CUR.face->unpatented_hinting )
-    {
-      FT_Long  n = args[0] * 2;
-
-
-      if ( CUR.args < n )
-      {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
-      }
-
-      CUR.args -= n;
-      CUR.new_top = CUR.args;
-      return;
-    }
-#endif
-
-    nump = (FT_ULong)args[0];   /* some points theoretically may occur more
-                                   than once, thus UShort isn't enough */
-
-    for ( k = 1; k <= nump; k++ )
-    {
-      if ( CUR.args < 2 )
-      {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
-      }
-
-      CUR.args -= 2;
-
-      A = (FT_UShort)CUR.stack[CUR.args + 1];
-      B = CUR.stack[CUR.args];
-
-      /* XXX: Because some popular fonts contain some invalid DeltaP */
-      /*      instructions, we simply ignore them when the stacked   */
-      /*      point reference is off limit, rather than returning an */
-      /*      error.  As a delta instruction doesn't change a glyph  */
-      /*      in great ways, this shouldn't be a problem.            */
-
-      if ( !BOUNDS( A, CUR.zp0.n_points ) )
-      {
-        C = ( (FT_ULong)B & 0xF0 ) >> 4;
-
-        switch ( CUR.opcode )
-        {
-        case 0x5D:
-          break;
-
-        case 0x71:
-          C += 16;
-          break;
-
-        case 0x72:
-          C += 32;
-          break;
-        }
-
-        C += CUR.GS.delta_base;
-
-        if ( CURRENT_Ppem() == (FT_Long)C )
-        {
-          B = ( (FT_ULong)B & 0xF ) - 8;
-          if ( B >= 0 )
-            B++;
-          B = B * 64 / ( 1L << CUR.GS.delta_shift );
-
-          CUR_Func_move( &CUR.zp0, A, B );
-        }
-      }
-      else
-        if ( CUR.pedantic_hinting )
-          CUR.error = TT_Err_Invalid_Reference;
-    }
-
-    CUR.new_top = CUR.args;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* DELTACn[]:    DELTA exceptions C1, C2, C3                             */
-  /* Opcode range: 0x73,0x74,0x75                                          */
-  /* Stack:        uint32 (2 * uint32)... -->                              */
-  /*                                                                       */
-  static void
-  Ins_DELTAC( INS_ARG )
-  {
-    FT_ULong  nump, k;
-    FT_ULong  A, C;
-    FT_Long   B;
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-    /* Delta hinting is covered by US Patent 5159668. */
-    if ( CUR.face->unpatented_hinting )
-    {
-      FT_Long  n = args[0] * 2;
-
-
-      if ( CUR.args < n )
-      {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
-      }
-
-      CUR.args -= n;
-      CUR.new_top = CUR.args;
-      return;
-    }
-#endif
-
-    nump = (FT_ULong)args[0];
-
-    for ( k = 1; k <= nump; k++ )
-    {
-      if ( CUR.args < 2 )
-      {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        return;
-      }
-
-      CUR.args -= 2;
-
-      A = (FT_ULong)CUR.stack[CUR.args + 1];
-      B = CUR.stack[CUR.args];
-
-      if ( BOUNDS( A, CUR.cvtSize ) )
-      {
-        if ( CUR.pedantic_hinting )
-        {
-          CUR.error = TT_Err_Invalid_Reference;
-          return;
-        }
-      }
-      else
-      {
-        C = ( (FT_ULong)B & 0xF0 ) >> 4;
-
-        switch ( CUR.opcode )
-        {
-        case 0x73:
-          break;
-
-        case 0x74:
-          C += 16;
-          break;
-
-        case 0x75:
-          C += 32;
-          break;
-        }
-
-        C += CUR.GS.delta_base;
-
-        if ( CURRENT_Ppem() == (FT_Long)C )
-        {
-          B = ( (FT_ULong)B & 0xF ) - 8;
-          if ( B >= 0 )
-            B++;
-          B = B * 64 / ( 1L << CUR.GS.delta_shift );
-
-          CUR_Func_move_cvt( A, B );
-        }
-      }
-    }
-
-    CUR.new_top = CUR.args;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* MISC. INSTRUCTIONS                                                    */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* GETINFO[]:    GET INFOrmation                                         */
-  /* Opcode range: 0x88                                                    */
-  /* Stack:        uint32 --> uint32                                       */
-  /*                                                                       */
-  static void
-  Ins_GETINFO( INS_ARG )
-  {
-    FT_Long  K;
-
-
-    K = 0;
-
-    /* We return MS rasterizer version 1.7 for the font scaler. */
-    if ( ( args[0] & 1 ) != 0 )
-      K = 35;
-
-    /* Has the glyph been rotated? */
-    if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
-      K |= 0x80;
-
-    /* Has the glyph been stretched? */
-    if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
-      K |= 1 << 8;
-
-    /* Are we hinting for grayscale? */
-    if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
-      K |= 1 << 12;
-
-    args[0] = K;
-  }
-
-
-  static void
-  Ins_UNKNOWN( INS_ARG )
-  {
-    TT_DefRecord*  def   = CUR.IDefs;
-    TT_DefRecord*  limit = def + CUR.numIDefs;
-
-    FT_UNUSED_ARG;
-
-
-    for ( ; def < limit; def++ )
-    {
-      if ( (FT_Byte)def->opc == CUR.opcode && def->active )
-      {
-        TT_CallRec*  call;
-
-
-        if ( CUR.callTop >= CUR.callSize )
-        {
-          CUR.error = TT_Err_Stack_Overflow;
-          return;
-        }
-
-        call = CUR.callStack + CUR.callTop++;
-
-        call->Caller_Range = CUR.curRange;
-        call->Caller_IP    = CUR.IP+1;
-        call->Cur_Count    = 1;
-        call->Cur_Restart  = def->start;
-
-        INS_Goto_CodeRange( def->range, def->start );
-
-        CUR.step_ins = FALSE;
-        return;
-      }
-    }
-
-    CUR.error = TT_Err_Invalid_Opcode;
-  }
-
-
-#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
-
-
-  static
-  TInstruction_Function  Instruct_Dispatch[256] =
-  {
-    /* Opcodes are gathered in groups of 16. */
-    /* Please keep the spaces as they are.   */
-
-    /*  SVTCA  y  */  Ins_SVTCA,
-    /*  SVTCA  x  */  Ins_SVTCA,
-    /*  SPvTCA y  */  Ins_SPVTCA,
-    /*  SPvTCA x  */  Ins_SPVTCA,
-    /*  SFvTCA y  */  Ins_SFVTCA,
-    /*  SFvTCA x  */  Ins_SFVTCA,
-    /*  SPvTL //  */  Ins_SPVTL,
-    /*  SPvTL +   */  Ins_SPVTL,
-    /*  SFvTL //  */  Ins_SFVTL,
-    /*  SFvTL +   */  Ins_SFVTL,
-    /*  SPvFS     */  Ins_SPVFS,
-    /*  SFvFS     */  Ins_SFVFS,
-    /*  GPV       */  Ins_GPV,
-    /*  GFV       */  Ins_GFV,
-    /*  SFvTPv    */  Ins_SFVTPV,
-    /*  ISECT     */  Ins_ISECT,
-
-    /*  SRP0      */  Ins_SRP0,
-    /*  SRP1      */  Ins_SRP1,
-    /*  SRP2      */  Ins_SRP2,
-    /*  SZP0      */  Ins_SZP0,
-    /*  SZP1      */  Ins_SZP1,
-    /*  SZP2      */  Ins_SZP2,
-    /*  SZPS      */  Ins_SZPS,
-    /*  SLOOP     */  Ins_SLOOP,
-    /*  RTG       */  Ins_RTG,
-    /*  RTHG      */  Ins_RTHG,
-    /*  SMD       */  Ins_SMD,
-    /*  ELSE      */  Ins_ELSE,
-    /*  JMPR      */  Ins_JMPR,
-    /*  SCvTCi    */  Ins_SCVTCI,
-    /*  SSwCi     */  Ins_SSWCI,
-    /*  SSW       */  Ins_SSW,
-
-    /*  DUP       */  Ins_DUP,
-    /*  POP       */  Ins_POP,
-    /*  CLEAR     */  Ins_CLEAR,
-    /*  SWAP      */  Ins_SWAP,
-    /*  DEPTH     */  Ins_DEPTH,
-    /*  CINDEX    */  Ins_CINDEX,
-    /*  MINDEX    */  Ins_MINDEX,
-    /*  AlignPTS  */  Ins_ALIGNPTS,
-    /*  INS_0x28  */  Ins_UNKNOWN,
-    /*  UTP       */  Ins_UTP,
-    /*  LOOPCALL  */  Ins_LOOPCALL,
-    /*  CALL      */  Ins_CALL,
-    /*  FDEF      */  Ins_FDEF,
-    /*  ENDF      */  Ins_ENDF,
-    /*  MDAP[0]   */  Ins_MDAP,
-    /*  MDAP[1]   */  Ins_MDAP,
-
-    /*  IUP[0]    */  Ins_IUP,
-    /*  IUP[1]    */  Ins_IUP,
-    /*  SHP[0]    */  Ins_SHP,
-    /*  SHP[1]    */  Ins_SHP,
-    /*  SHC[0]    */  Ins_SHC,
-    /*  SHC[1]    */  Ins_SHC,
-    /*  SHZ[0]    */  Ins_SHZ,
-    /*  SHZ[1]    */  Ins_SHZ,
-    /*  SHPIX     */  Ins_SHPIX,
-    /*  IP        */  Ins_IP,
-    /*  MSIRP[0]  */  Ins_MSIRP,
-    /*  MSIRP[1]  */  Ins_MSIRP,
-    /*  AlignRP   */  Ins_ALIGNRP,
-    /*  RTDG      */  Ins_RTDG,
-    /*  MIAP[0]   */  Ins_MIAP,
-    /*  MIAP[1]   */  Ins_MIAP,
-
-    /*  NPushB    */  Ins_NPUSHB,
-    /*  NPushW    */  Ins_NPUSHW,
-    /*  WS        */  Ins_WS,
-    /*  RS        */  Ins_RS,
-    /*  WCvtP     */  Ins_WCVTP,
-    /*  RCvt      */  Ins_RCVT,
-    /*  GC[0]     */  Ins_GC,
-    /*  GC[1]     */  Ins_GC,
-    /*  SCFS      */  Ins_SCFS,
-    /*  MD[0]     */  Ins_MD,
-    /*  MD[1]     */  Ins_MD,
-    /*  MPPEM     */  Ins_MPPEM,
-    /*  MPS       */  Ins_MPS,
-    /*  FlipON    */  Ins_FLIPON,
-    /*  FlipOFF   */  Ins_FLIPOFF,
-    /*  DEBUG     */  Ins_DEBUG,
-
-    /*  LT        */  Ins_LT,
-    /*  LTEQ      */  Ins_LTEQ,
-    /*  GT        */  Ins_GT,
-    /*  GTEQ      */  Ins_GTEQ,
-    /*  EQ        */  Ins_EQ,
-    /*  NEQ       */  Ins_NEQ,
-    /*  ODD       */  Ins_ODD,
-    /*  EVEN      */  Ins_EVEN,
-    /*  IF        */  Ins_IF,
-    /*  EIF       */  Ins_EIF,
-    /*  AND       */  Ins_AND,
-    /*  OR        */  Ins_OR,
-    /*  NOT       */  Ins_NOT,
-    /*  DeltaP1   */  Ins_DELTAP,
-    /*  SDB       */  Ins_SDB,
-    /*  SDS       */  Ins_SDS,
-
-    /*  ADD       */  Ins_ADD,
-    /*  SUB       */  Ins_SUB,
-    /*  DIV       */  Ins_DIV,
-    /*  MUL       */  Ins_MUL,
-    /*  ABS       */  Ins_ABS,
-    /*  NEG       */  Ins_NEG,
-    /*  FLOOR     */  Ins_FLOOR,
-    /*  CEILING   */  Ins_CEILING,
-    /*  ROUND[0]  */  Ins_ROUND,
-    /*  ROUND[1]  */  Ins_ROUND,
-    /*  ROUND[2]  */  Ins_ROUND,
-    /*  ROUND[3]  */  Ins_ROUND,
-    /*  NROUND[0] */  Ins_NROUND,
-    /*  NROUND[1] */  Ins_NROUND,
-    /*  NROUND[2] */  Ins_NROUND,
-    /*  NROUND[3] */  Ins_NROUND,
-
-    /*  WCvtF     */  Ins_WCVTF,
-    /*  DeltaP2   */  Ins_DELTAP,
-    /*  DeltaP3   */  Ins_DELTAP,
-    /*  DeltaCn[0] */ Ins_DELTAC,
-    /*  DeltaCn[1] */ Ins_DELTAC,
-    /*  DeltaCn[2] */ Ins_DELTAC,
-    /*  SROUND    */  Ins_SROUND,
-    /*  S45Round  */  Ins_S45ROUND,
-    /*  JROT      */  Ins_JROT,
-    /*  JROF      */  Ins_JROF,
-    /*  ROFF      */  Ins_ROFF,
-    /*  INS_0x7B  */  Ins_UNKNOWN,
-    /*  RUTG      */  Ins_RUTG,
-    /*  RDTG      */  Ins_RDTG,
-    /*  SANGW     */  Ins_SANGW,
-    /*  AA        */  Ins_AA,
-
-    /*  FlipPT    */  Ins_FLIPPT,
-    /*  FlipRgON  */  Ins_FLIPRGON,
-    /*  FlipRgOFF */  Ins_FLIPRGOFF,
-    /*  INS_0x83  */  Ins_UNKNOWN,
-    /*  INS_0x84  */  Ins_UNKNOWN,
-    /*  ScanCTRL  */  Ins_SCANCTRL,
-    /*  SDPVTL[0] */  Ins_SDPVTL,
-    /*  SDPVTL[1] */  Ins_SDPVTL,
-    /*  GetINFO   */  Ins_GETINFO,
-    /*  IDEF      */  Ins_IDEF,
-    /*  ROLL      */  Ins_ROLL,
-    /*  MAX       */  Ins_MAX,
-    /*  MIN       */  Ins_MIN,
-    /*  ScanTYPE  */  Ins_SCANTYPE,
-    /*  InstCTRL  */  Ins_INSTCTRL,
-    /*  INS_0x8F  */  Ins_UNKNOWN,
-
-    /*  INS_0x90  */   Ins_UNKNOWN,
-    /*  INS_0x91  */   Ins_UNKNOWN,
-    /*  INS_0x92  */   Ins_UNKNOWN,
-    /*  INS_0x93  */   Ins_UNKNOWN,
-    /*  INS_0x94  */   Ins_UNKNOWN,
-    /*  INS_0x95  */   Ins_UNKNOWN,
-    /*  INS_0x96  */   Ins_UNKNOWN,
-    /*  INS_0x97  */   Ins_UNKNOWN,
-    /*  INS_0x98  */   Ins_UNKNOWN,
-    /*  INS_0x99  */   Ins_UNKNOWN,
-    /*  INS_0x9A  */   Ins_UNKNOWN,
-    /*  INS_0x9B  */   Ins_UNKNOWN,
-    /*  INS_0x9C  */   Ins_UNKNOWN,
-    /*  INS_0x9D  */   Ins_UNKNOWN,
-    /*  INS_0x9E  */   Ins_UNKNOWN,
-    /*  INS_0x9F  */   Ins_UNKNOWN,
-
-    /*  INS_0xA0  */   Ins_UNKNOWN,
-    /*  INS_0xA1  */   Ins_UNKNOWN,
-    /*  INS_0xA2  */   Ins_UNKNOWN,
-    /*  INS_0xA3  */   Ins_UNKNOWN,
-    /*  INS_0xA4  */   Ins_UNKNOWN,
-    /*  INS_0xA5  */   Ins_UNKNOWN,
-    /*  INS_0xA6  */   Ins_UNKNOWN,
-    /*  INS_0xA7  */   Ins_UNKNOWN,
-    /*  INS_0xA8  */   Ins_UNKNOWN,
-    /*  INS_0xA9  */   Ins_UNKNOWN,
-    /*  INS_0xAA  */   Ins_UNKNOWN,
-    /*  INS_0xAB  */   Ins_UNKNOWN,
-    /*  INS_0xAC  */   Ins_UNKNOWN,
-    /*  INS_0xAD  */   Ins_UNKNOWN,
-    /*  INS_0xAE  */   Ins_UNKNOWN,
-    /*  INS_0xAF  */   Ins_UNKNOWN,
-
-    /*  PushB[0]  */  Ins_PUSHB,
-    /*  PushB[1]  */  Ins_PUSHB,
-    /*  PushB[2]  */  Ins_PUSHB,
-    /*  PushB[3]  */  Ins_PUSHB,
-    /*  PushB[4]  */  Ins_PUSHB,
-    /*  PushB[5]  */  Ins_PUSHB,
-    /*  PushB[6]  */  Ins_PUSHB,
-    /*  PushB[7]  */  Ins_PUSHB,
-    /*  PushW[0]  */  Ins_PUSHW,
-    /*  PushW[1]  */  Ins_PUSHW,
-    /*  PushW[2]  */  Ins_PUSHW,
-    /*  PushW[3]  */  Ins_PUSHW,
-    /*  PushW[4]  */  Ins_PUSHW,
-    /*  PushW[5]  */  Ins_PUSHW,
-    /*  PushW[6]  */  Ins_PUSHW,
-    /*  PushW[7]  */  Ins_PUSHW,
-
-    /*  MDRP[00]  */  Ins_MDRP,
-    /*  MDRP[01]  */  Ins_MDRP,
-    /*  MDRP[02]  */  Ins_MDRP,
-    /*  MDRP[03]  */  Ins_MDRP,
-    /*  MDRP[04]  */  Ins_MDRP,
-    /*  MDRP[05]  */  Ins_MDRP,
-    /*  MDRP[06]  */  Ins_MDRP,
-    /*  MDRP[07]  */  Ins_MDRP,
-    /*  MDRP[08]  */  Ins_MDRP,
-    /*  MDRP[09]  */  Ins_MDRP,
-    /*  MDRP[10]  */  Ins_MDRP,
-    /*  MDRP[11]  */  Ins_MDRP,
-    /*  MDRP[12]  */  Ins_MDRP,
-    /*  MDRP[13]  */  Ins_MDRP,
-    /*  MDRP[14]  */  Ins_MDRP,
-    /*  MDRP[15]  */  Ins_MDRP,
-
-    /*  MDRP[16]  */  Ins_MDRP,
-    /*  MDRP[17]  */  Ins_MDRP,
-    /*  MDRP[18]  */  Ins_MDRP,
-    /*  MDRP[19]  */  Ins_MDRP,
-    /*  MDRP[20]  */  Ins_MDRP,
-    /*  MDRP[21]  */  Ins_MDRP,
-    /*  MDRP[22]  */  Ins_MDRP,
-    /*  MDRP[23]  */  Ins_MDRP,
-    /*  MDRP[24]  */  Ins_MDRP,
-    /*  MDRP[25]  */  Ins_MDRP,
-    /*  MDRP[26]  */  Ins_MDRP,
-    /*  MDRP[27]  */  Ins_MDRP,
-    /*  MDRP[28]  */  Ins_MDRP,
-    /*  MDRP[29]  */  Ins_MDRP,
-    /*  MDRP[30]  */  Ins_MDRP,
-    /*  MDRP[31]  */  Ins_MDRP,
-
-    /*  MIRP[00]  */  Ins_MIRP,
-    /*  MIRP[01]  */  Ins_MIRP,
-    /*  MIRP[02]  */  Ins_MIRP,
-    /*  MIRP[03]  */  Ins_MIRP,
-    /*  MIRP[04]  */  Ins_MIRP,
-    /*  MIRP[05]  */  Ins_MIRP,
-    /*  MIRP[06]  */  Ins_MIRP,
-    /*  MIRP[07]  */  Ins_MIRP,
-    /*  MIRP[08]  */  Ins_MIRP,
-    /*  MIRP[09]  */  Ins_MIRP,
-    /*  MIRP[10]  */  Ins_MIRP,
-    /*  MIRP[11]  */  Ins_MIRP,
-    /*  MIRP[12]  */  Ins_MIRP,
-    /*  MIRP[13]  */  Ins_MIRP,
-    /*  MIRP[14]  */  Ins_MIRP,
-    /*  MIRP[15]  */  Ins_MIRP,
-
-    /*  MIRP[16]  */  Ins_MIRP,
-    /*  MIRP[17]  */  Ins_MIRP,
-    /*  MIRP[18]  */  Ins_MIRP,
-    /*  MIRP[19]  */  Ins_MIRP,
-    /*  MIRP[20]  */  Ins_MIRP,
-    /*  MIRP[21]  */  Ins_MIRP,
-    /*  MIRP[22]  */  Ins_MIRP,
-    /*  MIRP[23]  */  Ins_MIRP,
-    /*  MIRP[24]  */  Ins_MIRP,
-    /*  MIRP[25]  */  Ins_MIRP,
-    /*  MIRP[26]  */  Ins_MIRP,
-    /*  MIRP[27]  */  Ins_MIRP,
-    /*  MIRP[28]  */  Ins_MIRP,
-    /*  MIRP[29]  */  Ins_MIRP,
-    /*  MIRP[30]  */  Ins_MIRP,
-    /*  MIRP[31]  */  Ins_MIRP
-  };
-
-
-#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* RUN                                                                   */
-  /*                                                                       */
-  /*  This function executes a run of opcodes.  It will exit in the        */
-  /*  following cases:                                                     */
-  /*                                                                       */
-  /*  - Errors (in which case it returns FALSE).                           */
-  /*                                                                       */
-  /*  - Reaching the end of the main code range (returns TRUE).            */
-  /*    Reaching the end of a code range within a function call is an      */
-  /*    error.                                                             */
-  /*                                                                       */
-  /*  - After executing one single opcode, if the flag `Instruction_Trap'  */
-  /*    is set to TRUE (returns TRUE).                                     */
-  /*                                                                       */
-  /*  On exit with TRUE, test IP < CodeSize to know whether it comes from  */
-  /*  an instruction trap or a normal termination.                         */
-  /*                                                                       */
-  /*                                                                       */
-  /*  Note: The documented DEBUG opcode pops a value from the stack.  This */
-  /*        behaviour is unsupported; here a DEBUG opcode is always an     */
-  /*        error.                                                         */
-  /*                                                                       */
-  /*                                                                       */
-  /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */
-  /*                                                                       */
-  /*  Instructions appear in the specification's order.                    */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /* documentation is in ttinterp.h */
-
-  FT_EXPORT_DEF( FT_Error )
-  TT_RunIns( TT_ExecContext  exc )
-  {
-    FT_Long  ins_counter = 0;  /* executed instructions counter */
-
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
-    cur = *exc;
-#endif
-
-    /* set CVT functions */
-    CUR.tt_metrics.ratio = 0;
-    if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
-    {
-      /* non-square pixels, use the stretched routines */
-      CUR.func_read_cvt  = Read_CVT_Stretched;
-      CUR.func_write_cvt = Write_CVT_Stretched;
-      CUR.func_move_cvt  = Move_CVT_Stretched;
-    }
-    else
-    {
-      /* square pixels, use normal routines */
-      CUR.func_read_cvt  = Read_CVT;
-      CUR.func_write_cvt = Write_CVT;
-      CUR.func_move_cvt  = Move_CVT;
-    }
-
-    COMPUTE_Funcs();
-    COMPUTE_Round( (FT_Byte)exc->GS.round_state );
-
-    do
-    {
-      CUR.opcode = CUR.code[CUR.IP];
-
-      if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
-      {
-        if ( CUR.IP + 1 > CUR.codeSize )
-          goto LErrorCodeOverflow_;
-
-        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
-      }
-
-      if ( CUR.IP + CUR.length > CUR.codeSize )
-        goto LErrorCodeOverflow_;
-
-      /* First, let's check for empty stack and overflow */
-      CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
-
-      /* `args' is the top of the stack once arguments have been popped. */
-      /* One can also interpret it as the index of the last argument.    */
-      if ( CUR.args < 0 )
-      {
-        CUR.error = TT_Err_Too_Few_Arguments;
-        goto LErrorLabel_;
-      }
-
-      CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
-
-      /* `new_top' is the new top of the stack, after the instruction's */
-      /* execution.  `top' will be set to `new_top' after the `switch'  */
-      /* statement.                                                     */
-      if ( CUR.new_top > CUR.stackSize )
-      {
-        CUR.error = TT_Err_Stack_Overflow;
-        goto LErrorLabel_;
-      }
-
-      CUR.step_ins = TRUE;
-      CUR.error    = TT_Err_Ok;
-
-#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
-
-      {
-        FT_Long*  args   = CUR.stack + CUR.args;
-        FT_Byte   opcode = CUR.opcode;
-
-
-#undef  ARRAY_BOUND_ERROR
-#define ARRAY_BOUND_ERROR  goto Set_Invalid_Ref
-
-
-        switch ( opcode )
-        {
-        case 0x00:  /* SVTCA y  */
-        case 0x01:  /* SVTCA x  */
-        case 0x02:  /* SPvTCA y */
-        case 0x03:  /* SPvTCA x */
-        case 0x04:  /* SFvTCA y */
-        case 0x05:  /* SFvTCA x */
-          {
-            FT_Short AA, BB;
-
-
-            AA = (FT_Short)( ( opcode & 1 ) << 14 );
-            BB = (FT_Short)( AA ^ 0x4000 );
-
-            if ( opcode < 4 )
-            {
-              CUR.GS.projVector.x = AA;
-              CUR.GS.projVector.y = BB;
-
-              CUR.GS.dualVector.x = AA;
-              CUR.GS.dualVector.y = BB;
-            }
-            else
-            {
-              GUESS_VECTOR( projVector );
-            }
-
-            if ( ( opcode & 2 ) == 0 )
-            {
-              CUR.GS.freeVector.x = AA;
-              CUR.GS.freeVector.y = BB;
-            }
-            else
-            {
-              GUESS_VECTOR( freeVector );
-            }
-
-            COMPUTE_Funcs();
-          }
-          break;
-
-        case 0x06:  /* SPvTL // */
-        case 0x07:  /* SPvTL +  */
-          DO_SPVTL
-          break;
-
-        case 0x08:  /* SFvTL // */
-        case 0x09:  /* SFvTL +  */
-          DO_SFVTL
-          break;
-
-        case 0x0A:  /* SPvFS */
-          DO_SPVFS
-          break;
-
-        case 0x0B:  /* SFvFS */
-          DO_SFVFS
-          break;
-
-        case 0x0C:  /* GPV */
-          DO_GPV
-          break;
-
-        case 0x0D:  /* GFV */
-          DO_GFV
-          break;
-
-        case 0x0E:  /* SFvTPv */
-          DO_SFVTPV
-          break;
-
-        case 0x0F:  /* ISECT  */
-          Ins_ISECT( EXEC_ARG_ args );
-          break;
-
-        case 0x10:  /* SRP0 */
-          DO_SRP0
-          break;
-
-        case 0x11:  /* SRP1 */
-          DO_SRP1
-          break;
-
-        case 0x12:  /* SRP2 */
-          DO_SRP2
-          break;
-
-        case 0x13:  /* SZP0 */
-          Ins_SZP0( EXEC_ARG_ args );
-          break;
-
-        case 0x14:  /* SZP1 */
-          Ins_SZP1( EXEC_ARG_ args );
-          break;
-
-        case 0x15:  /* SZP2 */
-          Ins_SZP2( EXEC_ARG_ args );
-          break;
-
-        case 0x16:  /* SZPS */
-          Ins_SZPS( EXEC_ARG_ args );
-          break;
-
-        case 0x17:  /* SLOOP */
-          DO_SLOOP
-          break;
-
-        case 0x18:  /* RTG */
-          DO_RTG
-          break;
-
-        case 0x19:  /* RTHG */
-          DO_RTHG
-          break;
-
-        case 0x1A:  /* SMD */
-          DO_SMD
-          break;
-
-        case 0x1B:  /* ELSE */
-          Ins_ELSE( EXEC_ARG_ args );
-          break;
-
-        case 0x1C:  /* JMPR */
-          DO_JMPR
-          break;
-
-        case 0x1D:  /* SCVTCI */
-          DO_SCVTCI
-          break;
-
-        case 0x1E:  /* SSWCI */
-          DO_SSWCI
-          break;
-
-        case 0x1F:  /* SSW */
-          DO_SSW
-          break;
-
-        case 0x20:  /* DUP */
-          DO_DUP
-          break;
-
-        case 0x21:  /* POP */
-          /* nothing :-) */
-          break;
-
-        case 0x22:  /* CLEAR */
-          DO_CLEAR
-          break;
-
-        case 0x23:  /* SWAP */
-          DO_SWAP
-          break;
-
-        case 0x24:  /* DEPTH */
-          DO_DEPTH
-          break;
-
-        case 0x25:  /* CINDEX */
-          DO_CINDEX
-          break;
-
-        case 0x26:  /* MINDEX */
-          Ins_MINDEX( EXEC_ARG_ args );
-          break;
-
-        case 0x27:  /* ALIGNPTS */
-          Ins_ALIGNPTS( EXEC_ARG_ args );
-          break;
-
-        case 0x28:  /* ???? */
-          Ins_UNKNOWN( EXEC_ARG_ args );
-          break;
-
-        case 0x29:  /* UTP */
-          Ins_UTP( EXEC_ARG_ args );
-          break;
-
-        case 0x2A:  /* LOOPCALL */
-          Ins_LOOPCALL( EXEC_ARG_ args );
-          break;
-
-        case 0x2B:  /* CALL */
-          Ins_CALL( EXEC_ARG_ args );
-          break;
-
-        case 0x2C:  /* FDEF */
-          Ins_FDEF( EXEC_ARG_ args );
-          break;
-
-        case 0x2D:  /* ENDF */
-          Ins_ENDF( EXEC_ARG_ args );
-          break;
-
-        case 0x2E:  /* MDAP */
-        case 0x2F:  /* MDAP */
-          Ins_MDAP( EXEC_ARG_ args );
-          break;
-
-
-        case 0x30:  /* IUP */
-        case 0x31:  /* IUP */
-          Ins_IUP( EXEC_ARG_ args );
-          break;
-
-        case 0x32:  /* SHP */
-        case 0x33:  /* SHP */
-          Ins_SHP( EXEC_ARG_ args );
-          break;
-
-        case 0x34:  /* SHC */
-        case 0x35:  /* SHC */
-          Ins_SHC( EXEC_ARG_ args );
-          break;
-
-        case 0x36:  /* SHZ */
-        case 0x37:  /* SHZ */
-          Ins_SHZ( EXEC_ARG_ args );
-          break;
-
-        case 0x38:  /* SHPIX */
-          Ins_SHPIX( EXEC_ARG_ args );
-          break;
-
-        case 0x39:  /* IP    */
-          Ins_IP( EXEC_ARG_ args );
-          break;
-
-        case 0x3A:  /* MSIRP */
-        case 0x3B:  /* MSIRP */
-          Ins_MSIRP( EXEC_ARG_ args );
-          break;
-
-        case 0x3C:  /* AlignRP */
-          Ins_ALIGNRP( EXEC_ARG_ args );
-          break;
-
-        case 0x3D:  /* RTDG */
-          DO_RTDG
-          break;
-
-        case 0x3E:  /* MIAP */
-        case 0x3F:  /* MIAP */
-          Ins_MIAP( EXEC_ARG_ args );
-          break;
-
-        case 0x40:  /* NPUSHB */
-          Ins_NPUSHB( EXEC_ARG_ args );
-          break;
-
-        case 0x41:  /* NPUSHW */
-          Ins_NPUSHW( EXEC_ARG_ args );
-          break;
-
-        case 0x42:  /* WS */
-          DO_WS
-          break;
-
-      Set_Invalid_Ref:
-            CUR.error = TT_Err_Invalid_Reference;
-          break;
-
-        case 0x43:  /* RS */
-          DO_RS
-          break;
-
-        case 0x44:  /* WCVTP */
-          DO_WCVTP
-          break;
-
-        case 0x45:  /* RCVT */
-          DO_RCVT
-          break;
-
-        case 0x46:  /* GC */
-        case 0x47:  /* GC */
-          Ins_GC( EXEC_ARG_ args );
-          break;
-
-        case 0x48:  /* SCFS */
-          Ins_SCFS( EXEC_ARG_ args );
-          break;
-
-        case 0x49:  /* MD */
-        case 0x4A:  /* MD */
-          Ins_MD( EXEC_ARG_ args );
-          break;
-
-        case 0x4B:  /* MPPEM */
-          DO_MPPEM
-          break;
-
-        case 0x4C:  /* MPS */
-          DO_MPS
-          break;
-
-        case 0x4D:  /* FLIPON */
-          DO_FLIPON
-          break;
-
-        case 0x4E:  /* FLIPOFF */
-          DO_FLIPOFF
-          break;
-
-        case 0x4F:  /* DEBUG */
-          DO_DEBUG
-          break;
-
-        case 0x50:  /* LT */
-          DO_LT
-          break;
-
-        case 0x51:  /* LTEQ */
-          DO_LTEQ
-          break;
-
-        case 0x52:  /* GT */
-          DO_GT
-          break;
-
-        case 0x53:  /* GTEQ */
-          DO_GTEQ
-          break;
-
-        case 0x54:  /* EQ */
-          DO_EQ
-          break;
-
-        case 0x55:  /* NEQ */
-          DO_NEQ
-          break;
-
-        case 0x56:  /* ODD */
-          DO_ODD
-          break;
-
-        case 0x57:  /* EVEN */
-          DO_EVEN
-          break;
-
-        case 0x58:  /* IF */
-          Ins_IF( EXEC_ARG_ args );
-          break;
-
-        case 0x59:  /* EIF */
-          /* do nothing */
-          break;
-
-        case 0x5A:  /* AND */
-          DO_AND
-          break;
-
-        case 0x5B:  /* OR */
-          DO_OR
-          break;
-
-        case 0x5C:  /* NOT */
-          DO_NOT
-          break;
-
-        case 0x5D:  /* DELTAP1 */
-          Ins_DELTAP( EXEC_ARG_ args );
-          break;
-
-        case 0x5E:  /* SDB */
-          DO_SDB
-          break;
-
-        case 0x5F:  /* SDS */
-          DO_SDS
-          break;
-
-        case 0x60:  /* ADD */
-          DO_ADD
-          break;
-
-        case 0x61:  /* SUB */
-          DO_SUB
-          break;
-
-        case 0x62:  /* DIV */
-          DO_DIV
-          break;
-
-        case 0x63:  /* MUL */
-          DO_MUL
-          break;
-
-        case 0x64:  /* ABS */
-          DO_ABS
-          break;
-
-        case 0x65:  /* NEG */
-          DO_NEG
-          break;
-
-        case 0x66:  /* FLOOR */
-          DO_FLOOR
-          break;
-
-        case 0x67:  /* CEILING */
-          DO_CEILING
-          break;
-
-        case 0x68:  /* ROUND */
-        case 0x69:  /* ROUND */
-        case 0x6A:  /* ROUND */
-        case 0x6B:  /* ROUND */
-          DO_ROUND
-          break;
-
-        case 0x6C:  /* NROUND */
-        case 0x6D:  /* NROUND */
-        case 0x6E:  /* NRRUND */
-        case 0x6F:  /* NROUND */
-          DO_NROUND
-          break;
-
-        case 0x70:  /* WCVTF */
-          DO_WCVTF
-          break;
-
-        case 0x71:  /* DELTAP2 */
-        case 0x72:  /* DELTAP3 */
-          Ins_DELTAP( EXEC_ARG_ args );
-          break;
-
-        case 0x73:  /* DELTAC0 */
-        case 0x74:  /* DELTAC1 */
-        case 0x75:  /* DELTAC2 */
-          Ins_DELTAC( EXEC_ARG_ args );
-          break;
-
-        case 0x76:  /* SROUND */
-          DO_SROUND
-          break;
-
-        case 0x77:  /* S45Round */
-          DO_S45ROUND
-          break;
-
-        case 0x78:  /* JROT */
-          DO_JROT
-          break;
-
-        case 0x79:  /* JROF */
-          DO_JROF
-          break;
-
-        case 0x7A:  /* ROFF */
-          DO_ROFF
-          break;
-
-        case 0x7B:  /* ???? */
-          Ins_UNKNOWN( EXEC_ARG_ args );
-          break;
-
-        case 0x7C:  /* RUTG */
-          DO_RUTG
-          break;
-
-        case 0x7D:  /* RDTG */
-          DO_RDTG
-          break;
-
-        case 0x7E:  /* SANGW */
-        case 0x7F:  /* AA    */
-          /* nothing - obsolete */
-          break;
-
-        case 0x80:  /* FLIPPT */
-          Ins_FLIPPT( EXEC_ARG_ args );
-          break;
-
-        case 0x81:  /* FLIPRGON */
-          Ins_FLIPRGON( EXEC_ARG_ args );
-          break;
-
-        case 0x82:  /* FLIPRGOFF */
-          Ins_FLIPRGOFF( EXEC_ARG_ args );
-          break;
-
-        case 0x83:  /* UNKNOWN */
-        case 0x84:  /* UNKNOWN */
-          Ins_UNKNOWN( EXEC_ARG_ args );
-          break;
-
-        case 0x85:  /* SCANCTRL */
-          Ins_SCANCTRL( EXEC_ARG_ args );
-          break;
-
-        case 0x86:  /* SDPVTL */
-        case 0x87:  /* SDPVTL */
-          Ins_SDPVTL( EXEC_ARG_ args );
-          break;
-
-        case 0x88:  /* GETINFO */
-          Ins_GETINFO( EXEC_ARG_ args );
-          break;
-
-        case 0x89:  /* IDEF */
-          Ins_IDEF( EXEC_ARG_ args );
-          break;
-
-        case 0x8A:  /* ROLL */
-          Ins_ROLL( EXEC_ARG_ args );
-          break;
-
-        case 0x8B:  /* MAX */
-          DO_MAX
-          break;
-
-        case 0x8C:  /* MIN */
-          DO_MIN
-          break;
-
-        case 0x8D:  /* SCANTYPE */
-          Ins_SCANTYPE( EXEC_ARG_ args );
-          break;
-
-        case 0x8E:  /* INSTCTRL */
-          Ins_INSTCTRL( EXEC_ARG_ args );
-          break;
-
-        case 0x8F:
-          Ins_UNKNOWN( EXEC_ARG_ args );
-          break;
-
-        default:
-          if ( opcode >= 0xE0 )
-            Ins_MIRP( EXEC_ARG_ args );
-          else if ( opcode >= 0xC0 )
-            Ins_MDRP( EXEC_ARG_ args );
-          else if ( opcode >= 0xB8 )
-            Ins_PUSHW( EXEC_ARG_ args );
-          else if ( opcode >= 0xB0 )
-            Ins_PUSHB( EXEC_ARG_ args );
-          else
-            Ins_UNKNOWN( EXEC_ARG_ args );
-        }
-
-      }
-
-#else
-
-      Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
-
-#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-      if ( CUR.error != TT_Err_Ok )
-      {
-        switch ( CUR.error )
-        {
-        case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
-          {
-            TT_DefRecord*  def   = CUR.IDefs;
-            TT_DefRecord*  limit = def + CUR.numIDefs;
-
-
-            for ( ; def < limit; def++ )
-            {
-              if ( def->active && CUR.opcode == (FT_Byte)def->opc )
-              {
-                TT_CallRec*  callrec;
-
-
-                if ( CUR.callTop >= CUR.callSize )
-                {
-                  CUR.error = TT_Err_Invalid_Reference;
-                  goto LErrorLabel_;
-                }
-
-                callrec = &CUR.callStack[CUR.callTop];
-
-                callrec->Caller_Range = CUR.curRange;
-                callrec->Caller_IP    = CUR.IP + 1;
-                callrec->Cur_Count    = 1;
-                callrec->Cur_Restart  = def->start;
-
-                if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
-                  goto LErrorLabel_;
-
-                goto LSuiteLabel_;
-              }
-            }
-          }
-
-          CUR.error = TT_Err_Invalid_Opcode;
-          goto LErrorLabel_;
-
-#if 0
-          break;   /* Unreachable code warning suppression.             */
-                   /* Leave to remind in case a later change the editor */
-                   /* to consider break;                                */
-#endif
-
-        default:
-          goto LErrorLabel_;
-
-#if 0
-        break;
-#endif
-        }
-      }
-
-      CUR.top = CUR.new_top;
-
-      if ( CUR.step_ins )
-        CUR.IP += CUR.length;
-
-      /* increment instruction counter and check if we didn't */
-      /* run this program for too long (e.g. infinite loops). */
-      if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
-        return TT_Err_Execution_Too_Long;
-
-    LSuiteLabel_:
-      if ( CUR.IP >= CUR.codeSize )
-      {
-        if ( CUR.callTop > 0 )
-        {
-          CUR.error = TT_Err_Code_Overflow;
-          goto LErrorLabel_;
-        }
-        else
-          goto LNo_Error_;
-      }
-    } while ( !CUR.instruction_trap );
-
-  LNo_Error_:
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
-    *exc = cur;
-#endif
-
-    return TT_Err_Ok;
-
-  LErrorCodeOverflow_:
-    CUR.error = TT_Err_Code_Overflow;
-
-  LErrorLabel_:
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
-    *exc = cur;
-#endif
-
-    return CUR.error;
-  }
-
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
-/* END */
+/***************************************************************************/\r
+/*                                                                         */\r
+/*  ttinterp.c                                                             */\r
+/*                                                                         */\r
+/*    TrueType bytecode interpreter (body).                                */\r
+/*                                                                         */\r
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by             */\r
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */\r
+/*                                                                         */\r
+/*  This file is part of the FreeType project, and may only be used,       */\r
+/*  modified, and distributed under the terms of the FreeType project      */\r
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */\r
+/*  this file you indicate that you have read the license and              */\r
+/*  understand and accept it fully.                                        */\r
+/*                                                                         */\r
+/***************************************************************************/\r
+\r
+\r
+#include <ft2build.h>\r
+#include FT_INTERNAL_DEBUG_H\r
+#include FT_INTERNAL_CALC_H\r
+#include FT_TRIGONOMETRY_H\r
+#include FT_SYSTEM_H\r
+\r
+#include "ttinterp.h"\r
+\r
+#include "tterrors.h"\r
+\r
+\r
+#ifdef TT_USE_BYTECODE_INTERPRETER\r
+\r
+\r
+#define TT_MULFIX           FT_MulFix\r
+#define TT_MULDIV           FT_MulDiv\r
+#define TT_MULDIV_NO_ROUND  FT_MulDiv_No_Round\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */\r
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */\r
+  /* messages during execution.                                            */\r
+  /*                                                                       */\r
+#undef  FT_COMPONENT\r
+#define FT_COMPONENT  trace_ttinterp\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* In order to detect infinite loops in the code, we set up a counter    */\r
+  /* within the run loop.  A single stroke of interpretation is now        */\r
+  /* limited to a maximal number of opcodes defined below.                 */\r
+  /*                                                                       */\r
+#define MAX_RUNNABLE_OPCODES  1000000L\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* There are two kinds of implementations:                               */\r
+  /*                                                                       */\r
+  /* a. static implementation                                              */\r
+  /*                                                                       */\r
+  /*    The current execution context is a static variable, which fields   */\r
+  /*    are accessed directly by the interpreter during execution.  The    */\r
+  /*    context is named `cur'.                                            */\r
+  /*                                                                       */\r
+  /*    This version is non-reentrant, of course.                          */\r
+  /*                                                                       */\r
+  /* b. indirect implementation                                            */\r
+  /*                                                                       */\r
+  /*    The current execution context is passed to _each_ function as its  */\r
+  /*    first argument, and each field is thus accessed indirectly.        */\r
+  /*                                                                       */\r
+  /*    This version is fully re-entrant.                                  */\r
+  /*                                                                       */\r
+  /* The idea is that an indirect implementation may be slower to execute  */\r
+  /* on low-end processors that are used in some systems (like 386s or     */\r
+  /* even 486s).                                                           */\r
+  /*                                                                       */\r
+  /* As a consequence, the indirect implementation is now the default, as  */\r
+  /* its performance costs can be considered negligible in our context.    */\r
+  /* Note, however, that we kept the same source with macros because:      */\r
+  /*                                                                       */\r
+  /* - The code is kept very close in design to the Pascal code used for   */\r
+  /*   development.                                                        */\r
+  /*                                                                       */\r
+  /* - It's much more readable that way!                                   */\r
+  /*                                                                       */\r
+  /* - It's still open to experimentation and tuning.                      */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */\r
+\r
+#define CUR  (*exc)                             /* see ttobjs.h */\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* This macro is used whenever `exec' is unused in a function, to avoid  */\r
+  /* stupid warnings from pedantic compilers.                              */\r
+  /*                                                                       */\r
+#define FT_UNUSED_EXEC  FT_UNUSED( exc )\r
+\r
+#else                                           /* static implementation */\r
+\r
+#define CUR  cur\r
+\r
+#define FT_UNUSED_EXEC  int  __dummy = __dummy\r
+\r
+  static\r
+  TT_ExecContextRec  cur;   /* static exec. context variable */\r
+\r
+  /* apparently, we have a _lot_ of direct indexing when accessing  */\r
+  /* the static `cur', which makes the code bigger (due to all the  */\r
+  /* four bytes addresses).                                         */\r
+\r
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* The instruction argument stack.                                       */\r
+  /*                                                                       */\r
+#define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* This macro is used whenever `args' is unused in a function, to avoid  */\r
+  /* stupid warnings from pedantic compilers.                              */\r
+  /*                                                                       */\r
+#define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */\r
+  /* increase readability of the code.                                     */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+#define SKIP_Code() \\r
+          SkipCode( EXEC_ARG )\r
+\r
+#define GET_ShortIns() \\r
+          GetShortIns( EXEC_ARG )\r
+\r
+#define NORMalize( x, y, v ) \\r
+          Normalize( EXEC_ARG_ x, y, v )\r
+\r
+#define SET_SuperRound( scale, flags ) \\r
+          SetSuperRound( EXEC_ARG_ scale, flags )\r
+\r
+#define ROUND_None( d, c ) \\r
+          Round_None( EXEC_ARG_ d, c )\r
+\r
+#define INS_Goto_CodeRange( range, ip ) \\r
+          Ins_Goto_CodeRange( EXEC_ARG_ range, ip )\r
+\r
+#define CUR_Func_move( z, p, d ) \\r
+          CUR.func_move( EXEC_ARG_ z, p, d )\r
+\r
+#define CUR_Func_move_orig( z, p, d ) \\r
+          CUR.func_move_orig( EXEC_ARG_ z, p, d )\r
+\r
+#define CUR_Func_round( d, c ) \\r
+          CUR.func_round( EXEC_ARG_ d, c )\r
+\r
+#define CUR_Func_read_cvt( index ) \\r
+          CUR.func_read_cvt( EXEC_ARG_ index )\r
+\r
+#define CUR_Func_write_cvt( index, val ) \\r
+          CUR.func_write_cvt( EXEC_ARG_ index, val )\r
+\r
+#define CUR_Func_move_cvt( index, val ) \\r
+          CUR.func_move_cvt( EXEC_ARG_ index, val )\r
+\r
+#define CURRENT_Ratio() \\r
+          Current_Ratio( EXEC_ARG )\r
+\r
+#define CURRENT_Ppem() \\r
+          Current_Ppem( EXEC_ARG )\r
+\r
+#define CUR_Ppem() \\r
+          Cur_PPEM( EXEC_ARG )\r
+\r
+#define INS_SxVTL( a, b, c, d ) \\r
+          Ins_SxVTL( EXEC_ARG_ a, b, c, d )\r
+\r
+#define COMPUTE_Funcs() \\r
+          Compute_Funcs( EXEC_ARG )\r
+\r
+#define COMPUTE_Round( a ) \\r
+          Compute_Round( EXEC_ARG_ a )\r
+\r
+#define COMPUTE_Point_Displacement( a, b, c, d ) \\r
+          Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )\r
+\r
+#define MOVE_Zp2_Point( a, b, c, t ) \\r
+          Move_Zp2_Point( EXEC_ARG_ a, b, c, t )\r
+\r
+\r
+#define CUR_Func_project( v1, v2 )  \\r
+          CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )\r
+\r
+#define CUR_Func_dualproj( v1, v2 )  \\r
+          CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )\r
+\r
+#define CUR_fast_project( v ) \\r
+          CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )\r
+\r
+#define CUR_fast_dualproj( v ) \\r
+          CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* Instruction dispatch function, as used by the interpreter.            */\r
+  /*                                                                       */\r
+  typedef void  (*TInstruction_Function)( INS_ARG );\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* A simple bounds-checking macro.                                       */\r
+  /*                                                                       */\r
+#define BOUNDS( x, n )  ( (FT_UInt)(x) >= (FT_UInt)(n) )\r
+\r
+#undef  SUCCESS\r
+#define SUCCESS  0\r
+\r
+#undef  FAILURE\r
+#define FAILURE  1\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+#define GUESS_VECTOR( V )                                         \\r
+  if ( CUR.face->unpatented_hinting )                             \\r
+  {                                                               \\r
+    CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \\r
+    CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \\r
+  }\r
+#else\r
+#define GUESS_VECTOR( V )\r
+#endif\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /*                        CODERANGE FUNCTIONS                            */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    TT_Goto_CodeRange                                                  */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Switches to a new code range (updates the code related elements in */\r
+  /*    `exec', and `IP').                                                 */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    range :: The new execution code range.                             */\r
+  /*                                                                       */\r
+  /*    IP    :: The new IP in the new code range.                         */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    exec  :: The target execution context.                             */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  FT_LOCAL_DEF( FT_Error )\r
+  TT_Goto_CodeRange( TT_ExecContext  exec,\r
+                     FT_Int          range,\r
+                     FT_Long         IP )\r
+  {\r
+    TT_CodeRange*  coderange;\r
+\r
+\r
+    FT_ASSERT( range >= 1 && range <= 3 );\r
+\r
+    coderange = &exec->codeRangeTable[range - 1];\r
+\r
+    FT_ASSERT( coderange->base != NULL );\r
+\r
+    /* NOTE: Because the last instruction of a program may be a CALL */\r
+    /*       which will return to the first byte *after* the code    */\r
+    /*       range, we test for IP <= Size instead of IP < Size.     */\r
+    /*                                                               */\r
+    FT_ASSERT( (FT_ULong)IP <= coderange->size );\r
+\r
+    exec->code     = coderange->base;\r
+    exec->codeSize = coderange->size;\r
+    exec->IP       = IP;\r
+    exec->curRange = range;\r
+\r
+    return TT_Err_Ok;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    TT_Set_CodeRange                                                   */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Sets a code range.                                                 */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    range  :: The code range index.                                    */\r
+  /*                                                                       */\r
+  /*    base   :: The new code base.                                       */\r
+  /*                                                                       */\r
+  /*    length :: The range size in bytes.                                 */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    exec   :: The target execution context.                            */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  FT_LOCAL_DEF( FT_Error )\r
+  TT_Set_CodeRange( TT_ExecContext  exec,\r
+                    FT_Int          range,\r
+                    void*           base,\r
+                    FT_Long         length )\r
+  {\r
+    FT_ASSERT( range >= 1 && range <= 3 );\r
+\r
+    exec->codeRangeTable[range - 1].base = (FT_Byte*)base;\r
+    exec->codeRangeTable[range - 1].size = length;\r
+\r
+    return TT_Err_Ok;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    TT_Clear_CodeRange                                                 */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Clears a code range.                                               */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    range :: The code range index.                                     */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    exec  :: The target execution context.                             */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    Does not set the Error variable.                                   */\r
+  /*                                                                       */\r
+  FT_LOCAL_DEF( FT_Error )\r
+  TT_Clear_CodeRange( TT_ExecContext  exec,\r
+                      FT_Int          range )\r
+  {\r
+    FT_ASSERT( range >= 1 && range <= 3 );\r
+\r
+    exec->codeRangeTable[range - 1].base = NULL;\r
+    exec->codeRangeTable[range - 1].size = 0;\r
+\r
+    return TT_Err_Ok;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /*                   EXECUTION CONTEXT ROUTINES                          */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    TT_Done_Context                                                    */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Destroys a given context.                                          */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    exec   :: A handle to the target execution context.                */\r
+  /*                                                                       */\r
+  /*    memory :: A handle to the parent memory object.                    */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    Only the glyph loader and debugger should call this function.      */\r
+  /*                                                                       */\r
+  FT_LOCAL_DEF( FT_Error )\r
+  TT_Done_Context( TT_ExecContext  exec )\r
+  {\r
+    FT_Memory  memory = exec->memory;\r
+\r
+\r
+    /* points zone */\r
+    exec->maxPoints   = 0;\r
+    exec->maxContours = 0;\r
+\r
+    /* free stack */\r
+    FT_FREE( exec->stack );\r
+    exec->stackSize = 0;\r
+\r
+    /* free call stack */\r
+    FT_FREE( exec->callStack );\r
+    exec->callSize = 0;\r
+    exec->callTop  = 0;\r
+\r
+    /* free glyph code range */\r
+    FT_FREE( exec->glyphIns );\r
+    exec->glyphSize = 0;\r
+\r
+    exec->size = NULL;\r
+    exec->face = NULL;\r
+\r
+    FT_FREE( exec );\r
+\r
+    return TT_Err_Ok;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Init_Context                                                       */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Initializes a context object.                                      */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    memory :: A handle to the parent memory object.                    */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    exec   :: A handle to the target execution context.                */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  static FT_Error\r
+  Init_Context( TT_ExecContext  exec,\r
+                FT_Memory       memory )\r
+  {\r
+    FT_Error  error;\r
+\r
+\r
+    FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));\r
+\r
+    exec->memory   = memory;\r
+    exec->callSize = 32;\r
+\r
+    if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )\r
+      goto Fail_Memory;\r
+\r
+    /* all values in the context are set to 0 already, but this is */\r
+    /* here as a remainder                                         */\r
+    exec->maxPoints   = 0;\r
+    exec->maxContours = 0;\r
+\r
+    exec->stackSize = 0;\r
+    exec->glyphSize = 0;\r
+\r
+    exec->stack     = NULL;\r
+    exec->glyphIns  = NULL;\r
+\r
+    exec->face = NULL;\r
+    exec->size = NULL;\r
+\r
+    return TT_Err_Ok;\r
+\r
+  Fail_Memory:\r
+    FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",\r
+               (FT_Long)exec ));\r
+    TT_Done_Context( exec );\r
+\r
+    return error;\r
+ }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Update_Max                                                         */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Checks the size of a buffer and reallocates it if necessary.       */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    memory     :: A handle to the parent memory object.                */\r
+  /*                                                                       */\r
+  /*    multiplier :: The size in bytes of each element in the buffer.     */\r
+  /*                                                                       */\r
+  /*    new_max    :: The new capacity (size) of the buffer.               */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    size       :: The address of the buffer's current size expressed   */\r
+  /*                  in elements.                                         */\r
+  /*                                                                       */\r
+  /*    buff       :: The address of the buffer base pointer.              */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  static FT_Error\r
+  Update_Max( FT_Memory  memory,\r
+              FT_ULong*  size,\r
+              FT_Long    multiplier,\r
+              void*      _pbuff,\r
+              FT_ULong   new_max )\r
+  {\r
+    FT_Error  error;\r
+    void**    pbuff = (void**)_pbuff;\r
+\r
+\r
+    if ( *size < new_max )\r
+    {\r
+      if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )\r
+        return error;\r
+      *size = new_max;\r
+    }\r
+\r
+    return TT_Err_Ok;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    TT_Load_Context                                                    */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Prepare an execution context for glyph hinting.                    */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    face :: A handle to the source face object.                        */\r
+  /*                                                                       */\r
+  /*    size :: A handle to the source size object.                        */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    exec :: A handle to the target execution context.                  */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    Only the glyph loader and debugger should call this function.      */\r
+  /*                                                                       */\r
+  FT_LOCAL_DEF( FT_Error )\r
+  TT_Load_Context( TT_ExecContext  exec,\r
+                   TT_Face         face,\r
+                   TT_Size         size )\r
+  {\r
+    FT_Int          i;\r
+    FT_ULong        tmp;\r
+    TT_MaxProfile*  maxp;\r
+    FT_Error        error;\r
+\r
+\r
+    exec->face = face;\r
+    maxp       = &face->max_profile;\r
+    exec->size = size;\r
+\r
+    if ( size )\r
+    {\r
+      exec->numFDefs   = size->num_function_defs;\r
+      exec->maxFDefs   = size->max_function_defs;\r
+      exec->numIDefs   = size->num_instruction_defs;\r
+      exec->maxIDefs   = size->max_instruction_defs;\r
+      exec->FDefs      = size->function_defs;\r
+      exec->IDefs      = size->instruction_defs;\r
+      exec->tt_metrics = size->ttmetrics;\r
+      exec->metrics    = size->metrics;\r
+\r
+      exec->maxFunc    = size->max_func;\r
+      exec->maxIns     = size->max_ins;\r
+\r
+      for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )\r
+        exec->codeRangeTable[i] = size->codeRangeTable[i];\r
+\r
+      /* set graphics state */\r
+      exec->GS = size->GS;\r
+\r
+      exec->cvtSize = size->cvt_size;\r
+      exec->cvt     = size->cvt;\r
+\r
+      exec->storeSize = size->storage_size;\r
+      exec->storage   = size->storage;\r
+\r
+      exec->twilight  = size->twilight;\r
+    }\r
+\r
+    /* XXX: We reserve a little more elements on the stack to deal safely */\r
+    /*      with broken fonts like arialbs, courbs, timesbs, etc.         */\r
+    tmp = exec->stackSize;\r
+    error = Update_Max( exec->memory,\r
+                        &tmp,\r
+                        sizeof ( FT_F26Dot6 ),\r
+                        (void*)&exec->stack,\r
+                        maxp->maxStackElements + 32 );\r
+    exec->stackSize = (FT_UInt)tmp;\r
+    if ( error )\r
+      return error;\r
+\r
+    tmp = exec->glyphSize;\r
+    error = Update_Max( exec->memory,\r
+                        &tmp,\r
+                        sizeof ( FT_Byte ),\r
+                        (void*)&exec->glyphIns,\r
+                        maxp->maxSizeOfInstructions );\r
+    exec->glyphSize = (FT_UShort)tmp;\r
+    if ( error )\r
+      return error;\r
+\r
+    exec->pts.n_points   = 0;\r
+    exec->pts.n_contours = 0;\r
+\r
+    exec->zp1 = exec->pts;\r
+    exec->zp2 = exec->pts;\r
+    exec->zp0 = exec->pts;\r
+\r
+    exec->instruction_trap = FALSE;\r
+\r
+    return TT_Err_Ok;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    TT_Save_Context                                                    */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Saves the code ranges in a `size' object.                          */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    exec :: A handle to the source execution context.                  */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    size :: A handle to the target size object.                        */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    FreeType error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    Only the glyph loader and debugger should call this function.      */\r
+  /*                                                                       */\r
+  FT_LOCAL_DEF( FT_Error )\r
+  TT_Save_Context( TT_ExecContext  exec,\r
+                   TT_Size         size )\r
+  {\r
+    FT_Int  i;\r
+\r
+\r
+    /* XXXX: Will probably disappear soon with all the code range */\r
+    /*       management, which is now rather obsolete.            */\r
+    /*                                                            */\r
+    size->num_function_defs    = exec->numFDefs;\r
+    size->num_instruction_defs = exec->numIDefs;\r
+\r
+    size->max_func = exec->maxFunc;\r
+    size->max_ins  = exec->maxIns;\r
+\r
+    for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )\r
+      size->codeRangeTable[i] = exec->codeRangeTable[i];\r
+\r
+    return TT_Err_Ok;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    TT_Run_Context                                                     */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Executes one or more instructions in the execution context.        */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    debug :: A Boolean flag.  If set, the function sets some internal  */\r
+  /*             variables and returns immediately, otherwise TT_RunIns()  */\r
+  /*             is called.                                                */\r
+  /*                                                                       */\r
+  /*             This is commented out currently.                          */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    exec  :: A handle to the target execution context.                 */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    TrueTyoe error code.  0 means success.                             */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    Only the glyph loader and debugger should call this function.      */\r
+  /*                                                                       */\r
+  FT_LOCAL_DEF( FT_Error )\r
+  TT_Run_Context( TT_ExecContext  exec,\r
+                  FT_Bool         debug )\r
+  {\r
+    FT_Error  error;\r
+\r
+\r
+    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0  ) )\r
+           != TT_Err_Ok )\r
+      return error;\r
+\r
+    exec->zp0 = exec->pts;\r
+    exec->zp1 = exec->pts;\r
+    exec->zp2 = exec->pts;\r
+\r
+    exec->GS.gep0 = 1;\r
+    exec->GS.gep1 = 1;\r
+    exec->GS.gep2 = 1;\r
+\r
+    exec->GS.projVector.x = 0x4000;\r
+    exec->GS.projVector.y = 0x0000;\r
+\r
+    exec->GS.freeVector = exec->GS.projVector;\r
+    exec->GS.dualVector = exec->GS.projVector;\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    exec->GS.both_x_axis = TRUE;\r
+#endif\r
+\r
+    exec->GS.round_state = 1;\r
+    exec->GS.loop        = 1;\r
+\r
+    /* some glyphs leave something on the stack. so we clean it */\r
+    /* before a new execution.                                  */\r
+    exec->top     = 0;\r
+    exec->callTop = 0;\r
+\r
+#if 1\r
+    FT_UNUSED( debug );\r
+\r
+    return exec->face->interpreter( exec );\r
+#else\r
+    if ( !debug )\r
+      return TT_RunIns( exec );\r
+    else\r
+      return TT_Err_Ok;\r
+#endif\r
+  }\r
+\r
+\r
+  const TT_GraphicsState  tt_default_graphics_state =\r
+  {\r
+    0, 0, 0,\r
+    { 0x4000, 0 },\r
+    { 0x4000, 0 },\r
+    { 0x4000, 0 },\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    TRUE,\r
+#endif\r
+\r
+    1, 64, 1,\r
+    TRUE, 68, 0, 0, 9, 3,\r
+    0, FALSE, 2, 1, 1, 1\r
+  };\r
+\r
+\r
+  /* documentation is in ttinterp.h */\r
+\r
+  FT_EXPORT_DEF( TT_ExecContext )\r
+  TT_New_Context( TT_Driver  driver )\r
+  {\r
+    TT_ExecContext  exec;\r
+    FT_Memory       memory;\r
+\r
+\r
+    memory = driver->root.root.memory;\r
+    exec   = driver->context;\r
+\r
+    if ( !driver->context )\r
+    {\r
+      FT_Error  error;\r
+\r
+\r
+      /* allocate object */\r
+      if ( FT_NEW( exec ) )\r
+        goto Exit;\r
+\r
+      /* initialize it */\r
+      error = Init_Context( exec, memory );\r
+      if ( error )\r
+        goto Fail;\r
+\r
+      /* store it into the driver */\r
+      driver->context = exec;\r
+    }\r
+\r
+  Exit:\r
+    return driver->context;\r
+\r
+  Fail:\r
+    FT_FREE( exec );\r
+\r
+    return 0;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* Before an opcode is executed, the interpreter verifies that there are */\r
+  /* enough arguments on the stack, with the help of the `Pop_Push_Count'  */\r
+  /* table.                                                                */\r
+  /*                                                                       */\r
+  /* For each opcode, the first column gives the number of arguments that  */\r
+  /* are popped from the stack; the second one gives the number of those   */\r
+  /* that are pushed in result.                                            */\r
+  /*                                                                       */\r
+  /* Opcodes which have a varying number of parameters in the data stream  */\r
+  /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */\r
+  /* the `opcode_length' table, and the value in `Pop_Push_Count' is set   */\r
+  /* to zero.                                                              */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+#undef  PACK\r
+#define PACK( x, y )  ( ( x << 4 ) | y )\r
+\r
+\r
+  static\r
+  const FT_Byte  Pop_Push_Count[256] =\r
+  {\r
+    /* opcodes are gathered in groups of 16 */\r
+    /* please keep the spaces as they are   */\r
+\r
+    /*  SVTCA  y  */  PACK( 0, 0 ),\r
+    /*  SVTCA  x  */  PACK( 0, 0 ),\r
+    /*  SPvTCA y  */  PACK( 0, 0 ),\r
+    /*  SPvTCA x  */  PACK( 0, 0 ),\r
+    /*  SFvTCA y  */  PACK( 0, 0 ),\r
+    /*  SFvTCA x  */  PACK( 0, 0 ),\r
+    /*  SPvTL //  */  PACK( 2, 0 ),\r
+    /*  SPvTL +   */  PACK( 2, 0 ),\r
+    /*  SFvTL //  */  PACK( 2, 0 ),\r
+    /*  SFvTL +   */  PACK( 2, 0 ),\r
+    /*  SPvFS     */  PACK( 2, 0 ),\r
+    /*  SFvFS     */  PACK( 2, 0 ),\r
+    /*  GPV       */  PACK( 0, 2 ),\r
+    /*  GFV       */  PACK( 0, 2 ),\r
+    /*  SFvTPv    */  PACK( 0, 0 ),\r
+    /*  ISECT     */  PACK( 5, 0 ),\r
+\r
+    /*  SRP0      */  PACK( 1, 0 ),\r
+    /*  SRP1      */  PACK( 1, 0 ),\r
+    /*  SRP2      */  PACK( 1, 0 ),\r
+    /*  SZP0      */  PACK( 1, 0 ),\r
+    /*  SZP1      */  PACK( 1, 0 ),\r
+    /*  SZP2      */  PACK( 1, 0 ),\r
+    /*  SZPS      */  PACK( 1, 0 ),\r
+    /*  SLOOP     */  PACK( 1, 0 ),\r
+    /*  RTG       */  PACK( 0, 0 ),\r
+    /*  RTHG      */  PACK( 0, 0 ),\r
+    /*  SMD       */  PACK( 1, 0 ),\r
+    /*  ELSE      */  PACK( 0, 0 ),\r
+    /*  JMPR      */  PACK( 1, 0 ),\r
+    /*  SCvTCi    */  PACK( 1, 0 ),\r
+    /*  SSwCi     */  PACK( 1, 0 ),\r
+    /*  SSW       */  PACK( 1, 0 ),\r
+\r
+    /*  DUP       */  PACK( 1, 2 ),\r
+    /*  POP       */  PACK( 1, 0 ),\r
+    /*  CLEAR     */  PACK( 0, 0 ),\r
+    /*  SWAP      */  PACK( 2, 2 ),\r
+    /*  DEPTH     */  PACK( 0, 1 ),\r
+    /*  CINDEX    */  PACK( 1, 1 ),\r
+    /*  MINDEX    */  PACK( 1, 0 ),\r
+    /*  AlignPTS  */  PACK( 2, 0 ),\r
+    /*  INS_$28   */  PACK( 0, 0 ),\r
+    /*  UTP       */  PACK( 1, 0 ),\r
+    /*  LOOPCALL  */  PACK( 2, 0 ),\r
+    /*  CALL      */  PACK( 1, 0 ),\r
+    /*  FDEF      */  PACK( 1, 0 ),\r
+    /*  ENDF      */  PACK( 0, 0 ),\r
+    /*  MDAP[0]   */  PACK( 1, 0 ),\r
+    /*  MDAP[1]   */  PACK( 1, 0 ),\r
+\r
+    /*  IUP[0]    */  PACK( 0, 0 ),\r
+    /*  IUP[1]    */  PACK( 0, 0 ),\r
+    /*  SHP[0]    */  PACK( 0, 0 ),\r
+    /*  SHP[1]    */  PACK( 0, 0 ),\r
+    /*  SHC[0]    */  PACK( 1, 0 ),\r
+    /*  SHC[1]    */  PACK( 1, 0 ),\r
+    /*  SHZ[0]    */  PACK( 1, 0 ),\r
+    /*  SHZ[1]    */  PACK( 1, 0 ),\r
+    /*  SHPIX     */  PACK( 1, 0 ),\r
+    /*  IP        */  PACK( 0, 0 ),\r
+    /*  MSIRP[0]  */  PACK( 2, 0 ),\r
+    /*  MSIRP[1]  */  PACK( 2, 0 ),\r
+    /*  AlignRP   */  PACK( 0, 0 ),\r
+    /*  RTDG      */  PACK( 0, 0 ),\r
+    /*  MIAP[0]   */  PACK( 2, 0 ),\r
+    /*  MIAP[1]   */  PACK( 2, 0 ),\r
+\r
+    /*  NPushB    */  PACK( 0, 0 ),\r
+    /*  NPushW    */  PACK( 0, 0 ),\r
+    /*  WS        */  PACK( 2, 0 ),\r
+    /*  RS        */  PACK( 1, 1 ),\r
+    /*  WCvtP     */  PACK( 2, 0 ),\r
+    /*  RCvt      */  PACK( 1, 1 ),\r
+    /*  GC[0]     */  PACK( 1, 1 ),\r
+    /*  GC[1]     */  PACK( 1, 1 ),\r
+    /*  SCFS      */  PACK( 2, 0 ),\r
+    /*  MD[0]     */  PACK( 2, 1 ),\r
+    /*  MD[1]     */  PACK( 2, 1 ),\r
+    /*  MPPEM     */  PACK( 0, 1 ),\r
+    /*  MPS       */  PACK( 0, 1 ),\r
+    /*  FlipON    */  PACK( 0, 0 ),\r
+    /*  FlipOFF   */  PACK( 0, 0 ),\r
+    /*  DEBUG     */  PACK( 1, 0 ),\r
+\r
+    /*  LT        */  PACK( 2, 1 ),\r
+    /*  LTEQ      */  PACK( 2, 1 ),\r
+    /*  GT        */  PACK( 2, 1 ),\r
+    /*  GTEQ      */  PACK( 2, 1 ),\r
+    /*  EQ        */  PACK( 2, 1 ),\r
+    /*  NEQ       */  PACK( 2, 1 ),\r
+    /*  ODD       */  PACK( 1, 1 ),\r
+    /*  EVEN      */  PACK( 1, 1 ),\r
+    /*  IF        */  PACK( 1, 0 ),\r
+    /*  EIF       */  PACK( 0, 0 ),\r
+    /*  AND       */  PACK( 2, 1 ),\r
+    /*  OR        */  PACK( 2, 1 ),\r
+    /*  NOT       */  PACK( 1, 1 ),\r
+    /*  DeltaP1   */  PACK( 1, 0 ),\r
+    /*  SDB       */  PACK( 1, 0 ),\r
+    /*  SDS       */  PACK( 1, 0 ),\r
+\r
+    /*  ADD       */  PACK( 2, 1 ),\r
+    /*  SUB       */  PACK( 2, 1 ),\r
+    /*  DIV       */  PACK( 2, 1 ),\r
+    /*  MUL       */  PACK( 2, 1 ),\r
+    /*  ABS       */  PACK( 1, 1 ),\r
+    /*  NEG       */  PACK( 1, 1 ),\r
+    /*  FLOOR     */  PACK( 1, 1 ),\r
+    /*  CEILING   */  PACK( 1, 1 ),\r
+    /*  ROUND[0]  */  PACK( 1, 1 ),\r
+    /*  ROUND[1]  */  PACK( 1, 1 ),\r
+    /*  ROUND[2]  */  PACK( 1, 1 ),\r
+    /*  ROUND[3]  */  PACK( 1, 1 ),\r
+    /*  NROUND[0] */  PACK( 1, 1 ),\r
+    /*  NROUND[1] */  PACK( 1, 1 ),\r
+    /*  NROUND[2] */  PACK( 1, 1 ),\r
+    /*  NROUND[3] */  PACK( 1, 1 ),\r
+\r
+    /*  WCvtF     */  PACK( 2, 0 ),\r
+    /*  DeltaP2   */  PACK( 1, 0 ),\r
+    /*  DeltaP3   */  PACK( 1, 0 ),\r
+    /*  DeltaCn[0] */ PACK( 1, 0 ),\r
+    /*  DeltaCn[1] */ PACK( 1, 0 ),\r
+    /*  DeltaCn[2] */ PACK( 1, 0 ),\r
+    /*  SROUND    */  PACK( 1, 0 ),\r
+    /*  S45Round  */  PACK( 1, 0 ),\r
+    /*  JROT      */  PACK( 2, 0 ),\r
+    /*  JROF      */  PACK( 2, 0 ),\r
+    /*  ROFF      */  PACK( 0, 0 ),\r
+    /*  INS_$7B   */  PACK( 0, 0 ),\r
+    /*  RUTG      */  PACK( 0, 0 ),\r
+    /*  RDTG      */  PACK( 0, 0 ),\r
+    /*  SANGW     */  PACK( 1, 0 ),\r
+    /*  AA        */  PACK( 1, 0 ),\r
+\r
+    /*  FlipPT    */  PACK( 0, 0 ),\r
+    /*  FlipRgON  */  PACK( 2, 0 ),\r
+    /*  FlipRgOFF */  PACK( 2, 0 ),\r
+    /*  INS_$83   */  PACK( 0, 0 ),\r
+    /*  INS_$84   */  PACK( 0, 0 ),\r
+    /*  ScanCTRL  */  PACK( 1, 0 ),\r
+    /*  SDVPTL[0] */  PACK( 2, 0 ),\r
+    /*  SDVPTL[1] */  PACK( 2, 0 ),\r
+    /*  GetINFO   */  PACK( 1, 1 ),\r
+    /*  IDEF      */  PACK( 1, 0 ),\r
+    /*  ROLL      */  PACK( 3, 3 ),\r
+    /*  MAX       */  PACK( 2, 1 ),\r
+    /*  MIN       */  PACK( 2, 1 ),\r
+    /*  ScanTYPE  */  PACK( 1, 0 ),\r
+    /*  InstCTRL  */  PACK( 2, 0 ),\r
+    /*  INS_$8F   */  PACK( 0, 0 ),\r
+\r
+    /*  INS_$90  */   PACK( 0, 0 ),\r
+    /*  INS_$91  */   PACK( 0, 0 ),\r
+    /*  INS_$92  */   PACK( 0, 0 ),\r
+    /*  INS_$93  */   PACK( 0, 0 ),\r
+    /*  INS_$94  */   PACK( 0, 0 ),\r
+    /*  INS_$95  */   PACK( 0, 0 ),\r
+    /*  INS_$96  */   PACK( 0, 0 ),\r
+    /*  INS_$97  */   PACK( 0, 0 ),\r
+    /*  INS_$98  */   PACK( 0, 0 ),\r
+    /*  INS_$99  */   PACK( 0, 0 ),\r
+    /*  INS_$9A  */   PACK( 0, 0 ),\r
+    /*  INS_$9B  */   PACK( 0, 0 ),\r
+    /*  INS_$9C  */   PACK( 0, 0 ),\r
+    /*  INS_$9D  */   PACK( 0, 0 ),\r
+    /*  INS_$9E  */   PACK( 0, 0 ),\r
+    /*  INS_$9F  */   PACK( 0, 0 ),\r
+\r
+    /*  INS_$A0  */   PACK( 0, 0 ),\r
+    /*  INS_$A1  */   PACK( 0, 0 ),\r
+    /*  INS_$A2  */   PACK( 0, 0 ),\r
+    /*  INS_$A3  */   PACK( 0, 0 ),\r
+    /*  INS_$A4  */   PACK( 0, 0 ),\r
+    /*  INS_$A5  */   PACK( 0, 0 ),\r
+    /*  INS_$A6  */   PACK( 0, 0 ),\r
+    /*  INS_$A7  */   PACK( 0, 0 ),\r
+    /*  INS_$A8  */   PACK( 0, 0 ),\r
+    /*  INS_$A9  */   PACK( 0, 0 ),\r
+    /*  INS_$AA  */   PACK( 0, 0 ),\r
+    /*  INS_$AB  */   PACK( 0, 0 ),\r
+    /*  INS_$AC  */   PACK( 0, 0 ),\r
+    /*  INS_$AD  */   PACK( 0, 0 ),\r
+    /*  INS_$AE  */   PACK( 0, 0 ),\r
+    /*  INS_$AF  */   PACK( 0, 0 ),\r
+\r
+    /*  PushB[0]  */  PACK( 0, 1 ),\r
+    /*  PushB[1]  */  PACK( 0, 2 ),\r
+    /*  PushB[2]  */  PACK( 0, 3 ),\r
+    /*  PushB[3]  */  PACK( 0, 4 ),\r
+    /*  PushB[4]  */  PACK( 0, 5 ),\r
+    /*  PushB[5]  */  PACK( 0, 6 ),\r
+    /*  PushB[6]  */  PACK( 0, 7 ),\r
+    /*  PushB[7]  */  PACK( 0, 8 ),\r
+    /*  PushW[0]  */  PACK( 0, 1 ),\r
+    /*  PushW[1]  */  PACK( 0, 2 ),\r
+    /*  PushW[2]  */  PACK( 0, 3 ),\r
+    /*  PushW[3]  */  PACK( 0, 4 ),\r
+    /*  PushW[4]  */  PACK( 0, 5 ),\r
+    /*  PushW[5]  */  PACK( 0, 6 ),\r
+    /*  PushW[6]  */  PACK( 0, 7 ),\r
+    /*  PushW[7]  */  PACK( 0, 8 ),\r
+\r
+    /*  MDRP[00]  */  PACK( 1, 0 ),\r
+    /*  MDRP[01]  */  PACK( 1, 0 ),\r
+    /*  MDRP[02]  */  PACK( 1, 0 ),\r
+    /*  MDRP[03]  */  PACK( 1, 0 ),\r
+    /*  MDRP[04]  */  PACK( 1, 0 ),\r
+    /*  MDRP[05]  */  PACK( 1, 0 ),\r
+    /*  MDRP[06]  */  PACK( 1, 0 ),\r
+    /*  MDRP[07]  */  PACK( 1, 0 ),\r
+    /*  MDRP[08]  */  PACK( 1, 0 ),\r
+    /*  MDRP[09]  */  PACK( 1, 0 ),\r
+    /*  MDRP[10]  */  PACK( 1, 0 ),\r
+    /*  MDRP[11]  */  PACK( 1, 0 ),\r
+    /*  MDRP[12]  */  PACK( 1, 0 ),\r
+    /*  MDRP[13]  */  PACK( 1, 0 ),\r
+    /*  MDRP[14]  */  PACK( 1, 0 ),\r
+    /*  MDRP[15]  */  PACK( 1, 0 ),\r
+\r
+    /*  MDRP[16]  */  PACK( 1, 0 ),\r
+    /*  MDRP[17]  */  PACK( 1, 0 ),\r
+    /*  MDRP[18]  */  PACK( 1, 0 ),\r
+    /*  MDRP[19]  */  PACK( 1, 0 ),\r
+    /*  MDRP[20]  */  PACK( 1, 0 ),\r
+    /*  MDRP[21]  */  PACK( 1, 0 ),\r
+    /*  MDRP[22]  */  PACK( 1, 0 ),\r
+    /*  MDRP[23]  */  PACK( 1, 0 ),\r
+    /*  MDRP[24]  */  PACK( 1, 0 ),\r
+    /*  MDRP[25]  */  PACK( 1, 0 ),\r
+    /*  MDRP[26]  */  PACK( 1, 0 ),\r
+    /*  MDRP[27]  */  PACK( 1, 0 ),\r
+    /*  MDRP[28]  */  PACK( 1, 0 ),\r
+    /*  MDRP[29]  */  PACK( 1, 0 ),\r
+    /*  MDRP[30]  */  PACK( 1, 0 ),\r
+    /*  MDRP[31]  */  PACK( 1, 0 ),\r
+\r
+    /*  MIRP[00]  */  PACK( 2, 0 ),\r
+    /*  MIRP[01]  */  PACK( 2, 0 ),\r
+    /*  MIRP[02]  */  PACK( 2, 0 ),\r
+    /*  MIRP[03]  */  PACK( 2, 0 ),\r
+    /*  MIRP[04]  */  PACK( 2, 0 ),\r
+    /*  MIRP[05]  */  PACK( 2, 0 ),\r
+    /*  MIRP[06]  */  PACK( 2, 0 ),\r
+    /*  MIRP[07]  */  PACK( 2, 0 ),\r
+    /*  MIRP[08]  */  PACK( 2, 0 ),\r
+    /*  MIRP[09]  */  PACK( 2, 0 ),\r
+    /*  MIRP[10]  */  PACK( 2, 0 ),\r
+    /*  MIRP[11]  */  PACK( 2, 0 ),\r
+    /*  MIRP[12]  */  PACK( 2, 0 ),\r
+    /*  MIRP[13]  */  PACK( 2, 0 ),\r
+    /*  MIRP[14]  */  PACK( 2, 0 ),\r
+    /*  MIRP[15]  */  PACK( 2, 0 ),\r
+\r
+    /*  MIRP[16]  */  PACK( 2, 0 ),\r
+    /*  MIRP[17]  */  PACK( 2, 0 ),\r
+    /*  MIRP[18]  */  PACK( 2, 0 ),\r
+    /*  MIRP[19]  */  PACK( 2, 0 ),\r
+    /*  MIRP[20]  */  PACK( 2, 0 ),\r
+    /*  MIRP[21]  */  PACK( 2, 0 ),\r
+    /*  MIRP[22]  */  PACK( 2, 0 ),\r
+    /*  MIRP[23]  */  PACK( 2, 0 ),\r
+    /*  MIRP[24]  */  PACK( 2, 0 ),\r
+    /*  MIRP[25]  */  PACK( 2, 0 ),\r
+    /*  MIRP[26]  */  PACK( 2, 0 ),\r
+    /*  MIRP[27]  */  PACK( 2, 0 ),\r
+    /*  MIRP[28]  */  PACK( 2, 0 ),\r
+    /*  MIRP[29]  */  PACK( 2, 0 ),\r
+    /*  MIRP[30]  */  PACK( 2, 0 ),\r
+    /*  MIRP[31]  */  PACK( 2, 0 )\r
+  };\r
+\r
+\r
+  static\r
+  const FT_Char  opcode_length[256] =\r
+  {\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+\r
+   -1,-2, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,\r
+\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,\r
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1\r
+  };\r
+\r
+#undef PACK\r
+\r
+#if 1\r
+\r
+  static FT_Int32\r
+  TT_MulFix14( FT_Int32  a,\r
+               FT_Int    b )\r
+  {\r
+    FT_Int32   sign;\r
+    FT_UInt32  ah, al, mid, lo, hi;\r
+\r
+\r
+    sign = a ^ b;\r
+\r
+    if ( a < 0 )\r
+      a = -a;\r
+    if ( b < 0 )\r
+      b = -b;\r
+\r
+    ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );\r
+    al = (FT_UInt32)( a & 0xFFFFU );\r
+\r
+    lo    = al * b;\r
+    mid   = ah * b;\r
+    hi    = mid >> 16;\r
+    mid   = ( mid << 16 ) + ( 1 << 13 ); /* rounding */\r
+    lo   += mid;\r
+    if ( lo < mid )\r
+      hi += 1;\r
+\r
+    mid = ( lo >> 14 ) | ( hi << 18 );\r
+\r
+    return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;\r
+  }\r
+\r
+#else\r
+\r
+  /* compute (a*b)/2^14 with maximal accuracy and rounding */\r
+  static FT_Int32\r
+  TT_MulFix14( FT_Int32  a,\r
+               FT_Int    b )\r
+  {\r
+    FT_Int32   m, s, hi;\r
+    FT_UInt32  l, lo;\r
+\r
+\r
+    /* compute ax*bx as 64-bit value */\r
+    l  = (FT_UInt32)( ( a & 0xFFFFU ) * b );\r
+    m  = ( a >> 16 ) * b;\r
+\r
+    lo = l + (FT_UInt32)( m << 16 );\r
+    hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );\r
+\r
+    /* divide the result by 2^14 with rounding */\r
+    s   = hi >> 31;\r
+    l   = lo + (FT_UInt32)s;\r
+    hi += s + ( l < lo );\r
+    lo  = l;\r
+\r
+    l   = lo + 0x2000U;\r
+    hi += l < lo;\r
+\r
+    return ( hi << 18 ) | ( l >> 14 );\r
+  }\r
+#endif\r
+\r
+\r
+  /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */\r
+  static FT_Int32\r
+  TT_DotFix14( FT_Int32  ax,\r
+               FT_Int32  ay,\r
+               FT_Int    bx,\r
+               FT_Int    by )\r
+  {\r
+    FT_Int32   m, s, hi1, hi2, hi;\r
+    FT_UInt32  l, lo1, lo2, lo;\r
+\r
+\r
+    /* compute ax*bx as 64-bit value */\r
+    l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );\r
+    m = ( ax >> 16 ) * bx;\r
+\r
+    lo1 = l + (FT_UInt32)( m << 16 );\r
+    hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );\r
+\r
+    /* compute ay*by as 64-bit value */\r
+    l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );\r
+    m = ( ay >> 16 ) * by;\r
+\r
+    lo2 = l + (FT_UInt32)( m << 16 );\r
+    hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );\r
+\r
+    /* add them */\r
+    lo = lo1 + lo2;\r
+    hi = hi1 + hi2 + ( lo < lo1 );\r
+\r
+    /* divide the result by 2^14 with rounding */\r
+    s   = hi >> 31;\r
+    l   = lo + (FT_UInt32)s;\r
+    hi += s + ( l < lo );\r
+    lo  = l;\r
+\r
+    l   = lo + 0x2000U;\r
+    hi += ( l < lo );\r
+\r
+    return ( hi << 18 ) | ( l >> 14 );\r
+  }\r
+\r
+\r
+  /* return length of given vector */\r
+\r
+#if 0\r
+\r
+  static FT_Int32\r
+  TT_VecLen( FT_Int32  x,\r
+             FT_Int32  y )\r
+  {\r
+    FT_Int32   m, hi1, hi2, hi;\r
+    FT_UInt32  l, lo1, lo2, lo;\r
+\r
+\r
+    /* compute x*x as 64-bit value */\r
+    lo = (FT_UInt32)( x & 0xFFFFU );\r
+    hi = x >> 16;\r
+\r
+    l  = lo * lo;\r
+    m  = hi * lo;\r
+    hi = hi * hi;\r
+\r
+    lo1 = l + (FT_UInt32)( m << 17 );\r
+    hi1 = hi + ( m >> 15 ) + ( lo1 < l );\r
+\r
+    /* compute y*y as 64-bit value */\r
+    lo = (FT_UInt32)( y & 0xFFFFU );\r
+    hi = y >> 16;\r
+\r
+    l  = lo * lo;\r
+    m  = hi * lo;\r
+    hi = hi * hi;\r
+\r
+    lo2 = l + (FT_UInt32)( m << 17 );\r
+    hi2 = hi + ( m >> 15 ) + ( lo2 < l );\r
+\r
+    /* add them to get 'x*x+y*y' as 64-bit value */\r
+    lo = lo1 + lo2;\r
+    hi = hi1 + hi2 + ( lo < lo1 );\r
+\r
+    /* compute the square root of this value */\r
+    {\r
+      FT_UInt32  root, rem, test_div;\r
+      FT_Int     count;\r
+\r
+\r
+      root = 0;\r
+\r
+      {\r
+        rem   = 0;\r
+        count = 32;\r
+        do\r
+        {\r
+          rem      = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );\r
+          hi       = (  hi << 2 ) | (            lo >> 30 );\r
+          lo     <<= 2;\r
+          root   <<= 1;\r
+          test_div = ( root << 1 ) + 1;\r
+\r
+          if ( rem >= test_div )\r
+          {\r
+            rem  -= test_div;\r
+            root += 1;\r
+          }\r
+        } while ( --count );\r
+      }\r
+\r
+      return (FT_Int32)root;\r
+    }\r
+  }\r
+\r
+#else\r
+\r
+  /* this version uses FT_Vector_Length which computes the same value */\r
+  /* much, much faster..                                              */\r
+  /*                                                                  */\r
+  static FT_F26Dot6\r
+  TT_VecLen( FT_F26Dot6  X,\r
+             FT_F26Dot6  Y )\r
+  {\r
+    FT_Vector  v;\r
+\r
+\r
+    v.x = X;\r
+    v.y = Y;\r
+\r
+    return FT_Vector_Length( &v );\r
+  }\r
+\r
+#endif\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Current_Ratio                                                      */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Returns the current aspect ratio scaling factor depending on the   */\r
+  /*    projection vector's state and device resolutions.                  */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */\r
+  /*                                                                       */\r
+  static FT_Long\r
+  Current_Ratio( EXEC_OP )\r
+  {\r
+    if ( !CUR.tt_metrics.ratio )\r
+    {\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+      if ( CUR.face->unpatented_hinting )\r
+      {\r
+        if ( CUR.GS.both_x_axis )\r
+          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;\r
+        else\r
+          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;\r
+      }\r
+      else\r
+#endif\r
+      {\r
+        if ( CUR.GS.projVector.y == 0 )\r
+          CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;\r
+\r
+        else if ( CUR.GS.projVector.x == 0 )\r
+          CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;\r
+\r
+        else\r
+        {\r
+          FT_Long  x, y;\r
+\r
+\r
+          x = TT_MULDIV( CUR.GS.projVector.x,\r
+                         CUR.tt_metrics.x_ratio, 0x4000 );\r
+          y = TT_MULDIV( CUR.GS.projVector.y,\r
+                         CUR.tt_metrics.y_ratio, 0x4000 );\r
+          CUR.tt_metrics.ratio = TT_VecLen( x, y );\r
+        }\r
+      }\r
+    }\r
+    return CUR.tt_metrics.ratio;\r
+  }\r
+\r
+\r
+  static FT_Long\r
+  Current_Ppem( EXEC_OP )\r
+  {\r
+    return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* Functions related to the control value table (CVT).                   */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  FT_CALLBACK_DEF( FT_F26Dot6 )\r
+  Read_CVT( EXEC_OP_ FT_ULong  idx )\r
+  {\r
+    return CUR.cvt[idx];\r
+  }\r
+\r
+\r
+  FT_CALLBACK_DEF( FT_F26Dot6 )\r
+  Read_CVT_Stretched( EXEC_OP_ FT_ULong  idx )\r
+  {\r
+    return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );\r
+  }\r
+\r
+\r
+  FT_CALLBACK_DEF( void )\r
+  Write_CVT( EXEC_OP_ FT_ULong    idx,\r
+                      FT_F26Dot6  value )\r
+  {\r
+    CUR.cvt[idx] = value;\r
+  }\r
+\r
+\r
+  FT_CALLBACK_DEF( void )\r
+  Write_CVT_Stretched( EXEC_OP_ FT_ULong    idx,\r
+                                FT_F26Dot6  value )\r
+  {\r
+    CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );\r
+  }\r
+\r
+\r
+  FT_CALLBACK_DEF( void )\r
+  Move_CVT( EXEC_OP_ FT_ULong    idx,\r
+                     FT_F26Dot6  value )\r
+  {\r
+    CUR.cvt[idx] += value;\r
+  }\r
+\r
+\r
+  FT_CALLBACK_DEF( void )\r
+  Move_CVT_Stretched( EXEC_OP_ FT_ULong    idx,\r
+                               FT_F26Dot6  value )\r
+  {\r
+    CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    GetShortIns                                                        */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Returns a short integer taken from the instruction stream at       */\r
+  /*    address IP.                                                        */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Short read at code[IP].                                            */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    This one could become a macro.                                     */\r
+  /*                                                                       */\r
+  static FT_Short\r
+  GetShortIns( EXEC_OP )\r
+  {\r
+    /* Reading a byte stream so there is no endianess (DaveP) */\r
+    CUR.IP += 2;\r
+    return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +\r
+                         CUR.code[CUR.IP - 1]      );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Ins_Goto_CodeRange                                                 */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Goes to a certain code range in the instruction stream.            */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    aRange :: The index of the code range.                             */\r
+  /*                                                                       */\r
+  /*    aIP    :: The new IP address in the code range.                    */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    SUCCESS or FAILURE.                                                */\r
+  /*                                                                       */\r
+  static FT_Bool\r
+  Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,\r
+                               FT_ULong  aIP )\r
+  {\r
+    TT_CodeRange*  range;\r
+\r
+\r
+    if ( aRange < 1 || aRange > 3 )\r
+    {\r
+      CUR.error = TT_Err_Bad_Argument;\r
+      return FAILURE;\r
+    }\r
+\r
+    range = &CUR.codeRangeTable[aRange - 1];\r
+\r
+    if ( range->base == NULL )     /* invalid coderange */\r
+    {\r
+      CUR.error = TT_Err_Invalid_CodeRange;\r
+      return FAILURE;\r
+    }\r
+\r
+    /* NOTE: Because the last instruction of a program may be a CALL */\r
+    /*       which will return to the first byte *after* the code    */\r
+    /*       range, we test for AIP <= Size, instead of AIP < Size.  */\r
+\r
+    if ( aIP > range->size )\r
+    {\r
+      CUR.error = TT_Err_Code_Overflow;\r
+      return FAILURE;\r
+    }\r
+\r
+    CUR.code     = range->base;\r
+    CUR.codeSize = range->size;\r
+    CUR.IP       = aIP;\r
+    CUR.curRange = aRange;\r
+\r
+    return SUCCESS;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Direct_Move                                                        */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Moves a point by a given distance along the freedom vector.  The   */\r
+  /*    point will be `touched'.                                           */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    point    :: The index of the point to move.                        */\r
+  /*                                                                       */\r
+  /*    distance :: The distance to apply.                                 */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    zone     :: The affected glyph zone.                               */\r
+  /*                                                                       */\r
+  static void\r
+  Direct_Move( EXEC_OP_ TT_GlyphZone  zone,\r
+                        FT_UShort     point,\r
+                        FT_F26Dot6    distance )\r
+  {\r
+    FT_F26Dot6  v;\r
+\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    FT_ASSERT( !CUR.face->unpatented_hinting );\r
+#endif\r
+\r
+    v = CUR.GS.freeVector.x;\r
+\r
+    if ( v != 0 )\r
+    {\r
+      zone->cur[point].x += TT_MULDIV( distance,\r
+                                       v * 0x10000L,\r
+                                       CUR.F_dot_P );\r
+\r
+      zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;\r
+    }\r
+\r
+    v = CUR.GS.freeVector.y;\r
+\r
+    if ( v != 0 )\r
+    {\r
+      zone->cur[point].y += TT_MULDIV( distance,\r
+                                       v * 0x10000L,\r
+                                       CUR.F_dot_P );\r
+\r
+      zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Direct_Move_Orig                                                   */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Moves the *original* position of a point by a given distance along */\r
+  /*    the freedom vector.  Obviously, the point will not be `touched'.   */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    point    :: The index of the point to move.                        */\r
+  /*                                                                       */\r
+  /*    distance :: The distance to apply.                                 */\r
+  /*                                                                       */\r
+  /* <InOut>                                                               */\r
+  /*    zone     :: The affected glyph zone.                               */\r
+  /*                                                                       */\r
+  static void\r
+  Direct_Move_Orig( EXEC_OP_ TT_GlyphZone  zone,\r
+                             FT_UShort     point,\r
+                             FT_F26Dot6    distance )\r
+  {\r
+    FT_F26Dot6  v;\r
+\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    FT_ASSERT( !CUR.face->unpatented_hinting );\r
+#endif\r
+\r
+    v = CUR.GS.freeVector.x;\r
+\r
+    if ( v != 0 )\r
+      zone->org[point].x += TT_MULDIV( distance,\r
+                                       v * 0x10000L,\r
+                                       CUR.F_dot_P );\r
+\r
+    v = CUR.GS.freeVector.y;\r
+\r
+    if ( v != 0 )\r
+      zone->org[point].y += TT_MULDIV( distance,\r
+                                       v * 0x10000L,\r
+                                       CUR.F_dot_P );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* Special versions of Direct_Move()                                     */\r
+  /*                                                                       */\r
+  /*   The following versions are used whenever both vectors are both      */\r
+  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  static void\r
+  Direct_Move_X( EXEC_OP_ TT_GlyphZone  zone,\r
+                          FT_UShort     point,\r
+                          FT_F26Dot6    distance )\r
+  {\r
+    FT_UNUSED_EXEC;\r
+\r
+    zone->cur[point].x += distance;\r
+    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;\r
+  }\r
+\r
+\r
+  static void\r
+  Direct_Move_Y( EXEC_OP_ TT_GlyphZone  zone,\r
+                          FT_UShort     point,\r
+                          FT_F26Dot6    distance )\r
+  {\r
+    FT_UNUSED_EXEC;\r
+\r
+    zone->cur[point].y += distance;\r
+    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* Special versions of Direct_Move_Orig()                                */\r
+  /*                                                                       */\r
+  /*   The following versions are used whenever both vectors are both      */\r
+  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  static void\r
+  Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone  zone,\r
+                               FT_UShort     point,\r
+                               FT_F26Dot6    distance )\r
+  {\r
+    FT_UNUSED_EXEC;\r
+\r
+    zone->org[point].x += distance;\r
+  }\r
+\r
+\r
+  static void\r
+  Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone  zone,\r
+                               FT_UShort     point,\r
+                               FT_F26Dot6    distance )\r
+  {\r
+    FT_UNUSED_EXEC;\r
+\r
+    zone->org[point].y += distance;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_None                                                         */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Does not round, but adds engine compensation.                      */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance (not) to round.                       */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    The compensated distance.                                          */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    The TrueType specification says very few about the relationship    */\r
+  /*    between rounding and engine compensation.  However, it seems from  */\r
+  /*    the description of super round that we should add the compensation */\r
+  /*    before rounding.                                                   */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_None( EXEC_OP_ FT_F26Dot6  distance,\r
+                       FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6  val;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = distance + compensation;\r
+      if ( distance && val < 0 )\r
+        val = 0;\r
+    }\r
+    else {\r
+      val = distance - compensation;\r
+      if ( val > 0 )\r
+        val = 0;\r
+    }\r
+    return val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_To_Grid                                                      */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Rounds value to grid after adding engine compensation.             */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance to round.                             */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Rounded distance.                                                  */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,\r
+                          FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6  val;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = distance + compensation + 32;\r
+      if ( distance && val > 0 )\r
+        val &= ~63;\r
+      else\r
+        val = 0;\r
+    }\r
+    else\r
+    {\r
+      val = -FT_PIX_ROUND( compensation - distance );\r
+      if ( val > 0 )\r
+        val = 0;\r
+    }\r
+\r
+    return  val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_To_Half_Grid                                                 */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Rounds value to half grid after adding engine compensation.        */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance to round.                             */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Rounded distance.                                                  */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,\r
+                               FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6  val;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = FT_PIX_FLOOR( distance + compensation ) + 32;\r
+      if ( distance && val < 0 )\r
+        val = 0;\r
+    }\r
+    else\r
+    {\r
+      val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );\r
+      if ( val > 0 )\r
+        val = 0;\r
+    }\r
+\r
+    return val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_Down_To_Grid                                                 */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Rounds value down to grid after adding engine compensation.        */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance to round.                             */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Rounded distance.                                                  */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,\r
+                               FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6  val;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = distance + compensation;\r
+      if ( distance && val > 0 )\r
+        val &= ~63;\r
+      else\r
+        val = 0;\r
+    }\r
+    else\r
+    {\r
+      val = -( ( compensation - distance ) & -64 );\r
+      if ( val > 0 )\r
+        val = 0;\r
+    }\r
+\r
+    return val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_Up_To_Grid                                                   */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Rounds value up to grid after adding engine compensation.          */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance to round.                             */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Rounded distance.                                                  */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,\r
+                             FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6  val;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = distance + compensation + 63;\r
+      if ( distance && val > 0 )\r
+        val &= ~63;\r
+      else\r
+        val = 0;\r
+    }\r
+    else\r
+    {\r
+      val = - FT_PIX_CEIL( compensation - distance );\r
+      if ( val > 0 )\r
+        val = 0;\r
+    }\r
+\r
+    return val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_To_Double_Grid                                               */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Rounds value to double grid after adding engine compensation.      */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance to round.                             */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Rounded distance.                                                  */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,\r
+                                 FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6 val;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = distance + compensation + 16;\r
+      if ( distance && val > 0 )\r
+        val &= ~31;\r
+      else\r
+        val = 0;\r
+    }\r
+    else\r
+    {\r
+      val = -FT_PAD_ROUND( compensation - distance, 32 );\r
+      if ( val > 0 )\r
+        val = 0;\r
+    }\r
+\r
+    return val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_Super                                                        */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Super-rounds value to grid after adding engine compensation.       */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance to round.                             */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Rounded distance.                                                  */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    The TrueType specification says very few about the relationship    */\r
+  /*    between rounding and engine compensation.  However, it seems from  */\r
+  /*    the description of super round that we should add the compensation */\r
+  /*    before rounding.                                                   */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_Super( EXEC_OP_ FT_F26Dot6  distance,\r
+                        FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6  val;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = ( distance - CUR.phase + CUR.threshold + compensation ) &\r
+              -CUR.period;\r
+      if ( distance && val < 0 )\r
+        val = 0;\r
+      val += CUR.phase;\r
+    }\r
+    else\r
+    {\r
+      val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &\r
+               -CUR.period );\r
+      if ( val > 0 )\r
+        val = 0;\r
+      val -= CUR.phase;\r
+    }\r
+\r
+    return val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Round_Super_45                                                     */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Super-rounds value to grid after adding engine compensation.       */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    distance     :: The distance to round.                             */\r
+  /*                                                                       */\r
+  /*    compensation :: The engine compensation.                           */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Rounded distance.                                                  */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    There is a separate function for Round_Super_45() as we may need   */\r
+  /*    greater precision.                                                 */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,\r
+                           FT_F26Dot6  compensation )\r
+  {\r
+    FT_F26Dot6  val;\r
+\r
+\r
+    if ( distance >= 0 )\r
+    {\r
+      val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /\r
+                CUR.period ) * CUR.period;\r
+      if ( distance && val < 0 )\r
+        val = 0;\r
+      val += CUR.phase;\r
+    }\r
+    else\r
+    {\r
+      val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /\r
+                   CUR.period ) * CUR.period );\r
+      if ( val > 0 )\r
+        val = 0;\r
+      val -= CUR.phase;\r
+    }\r
+\r
+    return val;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Compute_Round                                                      */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Sets the rounding mode.                                            */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    round_mode :: The rounding mode to be used.                        */\r
+  /*                                                                       */\r
+  static void\r
+  Compute_Round( EXEC_OP_ FT_Byte  round_mode )\r
+  {\r
+    switch ( round_mode )\r
+    {\r
+    case TT_Round_Off:\r
+      CUR.func_round = (TT_Round_Func)Round_None;\r
+      break;\r
+\r
+    case TT_Round_To_Grid:\r
+      CUR.func_round = (TT_Round_Func)Round_To_Grid;\r
+      break;\r
+\r
+    case TT_Round_Up_To_Grid:\r
+      CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;\r
+      break;\r
+\r
+    case TT_Round_Down_To_Grid:\r
+      CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;\r
+      break;\r
+\r
+    case TT_Round_To_Half_Grid:\r
+      CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;\r
+      break;\r
+\r
+    case TT_Round_To_Double_Grid:\r
+      CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;\r
+      break;\r
+\r
+    case TT_Round_Super:\r
+      CUR.func_round = (TT_Round_Func)Round_Super;\r
+      break;\r
+\r
+    case TT_Round_Super_45:\r
+      CUR.func_round = (TT_Round_Func)Round_Super_45;\r
+      break;\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    SetSuperRound                                                      */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Sets Super Round parameters.                                       */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    GridPeriod :: Grid period                                          */\r
+  /*    selector   :: SROUND opcode                                        */\r
+  /*                                                                       */\r
+  static void\r
+  SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,\r
+                          FT_Long     selector )\r
+  {\r
+    switch ( (FT_Int)( selector & 0xC0 ) )\r
+    {\r
+      case 0:\r
+        CUR.period = GridPeriod / 2;\r
+        break;\r
+\r
+      case 0x40:\r
+        CUR.period = GridPeriod;\r
+        break;\r
+\r
+      case 0x80:\r
+        CUR.period = GridPeriod * 2;\r
+        break;\r
+\r
+      /* This opcode is reserved, but... */\r
+\r
+      case 0xC0:\r
+        CUR.period = GridPeriod;\r
+        break;\r
+    }\r
+\r
+    switch ( (FT_Int)( selector & 0x30 ) )\r
+    {\r
+    case 0:\r
+      CUR.phase = 0;\r
+      break;\r
+\r
+    case 0x10:\r
+      CUR.phase = CUR.period / 4;\r
+      break;\r
+\r
+    case 0x20:\r
+      CUR.phase = CUR.period / 2;\r
+      break;\r
+\r
+    case 0x30:\r
+      CUR.phase = CUR.period * 3 / 4;\r
+      break;\r
+    }\r
+\r
+    if ( ( selector & 0x0F ) == 0 )\r
+      CUR.threshold = CUR.period - 1;\r
+    else\r
+      CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;\r
+\r
+    CUR.period    /= 256;\r
+    CUR.phase     /= 256;\r
+    CUR.threshold /= 256;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Project                                                            */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Computes the projection of vector given by (v2-v1) along the       */\r
+  /*    current projection vector.                                         */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    v1 :: First input vector.                                          */\r
+  /*    v2 :: Second input vector.                                         */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    The distance in F26dot6 format.                                    */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Project( EXEC_OP_ FT_Pos  dx,\r
+                    FT_Pos  dy )\r
+  {\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    FT_ASSERT( !CUR.face->unpatented_hinting );\r
+#endif\r
+\r
+    return TT_DotFix14( dx, dy,\r
+                        CUR.GS.projVector.x,\r
+                        CUR.GS.projVector.y );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Dual_Project                                                       */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Computes the projection of the vector given by (v2-v1) along the   */\r
+  /*    current dual vector.                                               */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    v1 :: First input vector.                                          */\r
+  /*    v2 :: Second input vector.                                         */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    The distance in F26dot6 format.                                    */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Dual_Project( EXEC_OP_ FT_Pos  dx,\r
+                         FT_Pos  dy )\r
+  {\r
+    return TT_DotFix14( dx, dy,\r
+                        CUR.GS.dualVector.x,\r
+                        CUR.GS.dualVector.y );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Project_x                                                          */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Computes the projection of the vector given by (v2-v1) along the   */\r
+  /*    horizontal axis.                                                   */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    v1 :: First input vector.                                          */\r
+  /*    v2 :: Second input vector.                                         */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    The distance in F26dot6 format.                                    */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Project_x( EXEC_OP_ FT_Pos  dx,\r
+                      FT_Pos  dy )\r
+  {\r
+    FT_UNUSED_EXEC;\r
+    FT_UNUSED( dy );\r
+\r
+    return dx;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Project_y                                                          */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Computes the projection of the vector given by (v2-v1) along the   */\r
+  /*    vertical axis.                                                     */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    v1 :: First input vector.                                          */\r
+  /*    v2 :: Second input vector.                                         */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    The distance in F26dot6 format.                                    */\r
+  /*                                                                       */\r
+  static FT_F26Dot6\r
+  Project_y( EXEC_OP_ FT_Pos  dx,\r
+                      FT_Pos  dy )\r
+  {\r
+    FT_UNUSED_EXEC;\r
+    FT_UNUSED( dx );\r
+\r
+    return dy;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Compute_Funcs                                                      */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Computes the projection and movement function pointers according   */\r
+  /*    to the current graphics state.                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Compute_Funcs( EXEC_OP )\r
+  {\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    if ( CUR.face->unpatented_hinting )\r
+    {\r
+      /* If both vectors point rightwards along the x axis, set             */\r
+      /* `both-x-axis' true, otherwise set it false.  The x values only     */\r
+      /* need be tested because the vector has been normalised to a unit    */\r
+      /* vector of length 0x4000 = unity.                                   */\r
+      CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&\r
+                                      CUR.GS.freeVector.x == 0x4000 );\r
+\r
+      /* Throw away projection and freedom vector information */\r
+      /* because the patents don't allow them to be stored.   */\r
+      /* The relevant US Patents are 5155805 and 5325479.     */\r
+      CUR.GS.projVector.x = 0;\r
+      CUR.GS.projVector.y = 0;\r
+      CUR.GS.freeVector.x = 0;\r
+      CUR.GS.freeVector.y = 0;\r
+\r
+      if ( CUR.GS.both_x_axis )\r
+      {\r
+        CUR.func_project   = Project_x;\r
+        CUR.func_move      = Direct_Move_X;\r
+        CUR.func_move_orig = Direct_Move_Orig_X;\r
+      }\r
+      else\r
+      {\r
+        CUR.func_project   = Project_y;\r
+        CUR.func_move      = Direct_Move_Y;\r
+        CUR.func_move_orig = Direct_Move_Orig_Y;\r
+      }\r
+\r
+      if ( CUR.GS.dualVector.x == 0x4000 )\r
+        CUR.func_dualproj = Project_x;\r
+      else\r
+      {\r
+        if ( CUR.GS.dualVector.y == 0x4000 )\r
+          CUR.func_dualproj = Project_y;\r
+        else\r
+          CUR.func_dualproj = Dual_Project;\r
+      }\r
+\r
+      /* Force recalculation of cached aspect ratio */\r
+      CUR.tt_metrics.ratio = 0;\r
+\r
+      return;\r
+    }\r
+#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */\r
+\r
+    if ( CUR.GS.freeVector.x == 0x4000 )\r
+      CUR.F_dot_P       = CUR.GS.projVector.x * 0x10000L;\r
+    else\r
+    {\r
+      if ( CUR.GS.freeVector.y == 0x4000 )\r
+        CUR.F_dot_P       = CUR.GS.projVector.y * 0x10000L;\r
+      else\r
+        CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +\r
+                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;\r
+    }\r
+\r
+    if ( CUR.GS.projVector.x == 0x4000 )\r
+      CUR.func_project = (TT_Project_Func)Project_x;\r
+    else\r
+    {\r
+      if ( CUR.GS.projVector.y == 0x4000 )\r
+        CUR.func_project = (TT_Project_Func)Project_y;\r
+      else\r
+        CUR.func_project = (TT_Project_Func)Project;\r
+    }\r
+\r
+    if ( CUR.GS.dualVector.x == 0x4000 )\r
+      CUR.func_dualproj = (TT_Project_Func)Project_x;\r
+    else\r
+    {\r
+      if ( CUR.GS.dualVector.y == 0x4000 )\r
+        CUR.func_dualproj = (TT_Project_Func)Project_y;\r
+      else\r
+        CUR.func_dualproj = (TT_Project_Func)Dual_Project;\r
+    }\r
+\r
+    CUR.func_move      = (TT_Move_Func)Direct_Move;\r
+    CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;\r
+\r
+    if ( CUR.F_dot_P == 0x40000000L )\r
+    {\r
+      if ( CUR.GS.freeVector.x == 0x4000 )\r
+      {\r
+        CUR.func_move      = (TT_Move_Func)Direct_Move_X;\r
+        CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;\r
+      }\r
+      else\r
+      {\r
+        if ( CUR.GS.freeVector.y == 0x4000 )\r
+        {\r
+          CUR.func_move      = (TT_Move_Func)Direct_Move_Y;\r
+          CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;\r
+        }\r
+      }\r
+    }\r
+\r
+    /* at small sizes, F_dot_P can become too small, resulting   */\r
+    /* in overflows and `spikes' in a number of glyphs like `w'. */\r
+\r
+    if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )\r
+      CUR.F_dot_P = 0x40000000L;\r
+\r
+    /* Disable cached aspect ratio */\r
+    CUR.tt_metrics.ratio = 0;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* <Function>                                                            */\r
+  /*    Normalize                                                          */\r
+  /*                                                                       */\r
+  /* <Description>                                                         */\r
+  /*    Norms a vector.                                                    */\r
+  /*                                                                       */\r
+  /* <Input>                                                               */\r
+  /*    Vx :: The horizontal input vector coordinate.                      */\r
+  /*    Vy :: The vertical input vector coordinate.                        */\r
+  /*                                                                       */\r
+  /* <Output>                                                              */\r
+  /*    R  :: The normed unit vector.                                      */\r
+  /*                                                                       */\r
+  /* <Return>                                                              */\r
+  /*    Returns FAILURE if a vector parameter is zero.                     */\r
+  /*                                                                       */\r
+  /* <Note>                                                                */\r
+  /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */\r
+  /*    R is undefined.                                                    */\r
+  /*                                                                       */\r
+\r
+\r
+  static FT_Bool\r
+  Normalize( EXEC_OP_ FT_F26Dot6      Vx,\r
+                      FT_F26Dot6      Vy,\r
+                      FT_UnitVector*  R )\r
+  {\r
+    FT_F26Dot6  W;\r
+    FT_Bool     S1, S2;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )\r
+    {\r
+      Vx *= 0x100;\r
+      Vy *= 0x100;\r
+\r
+      W = TT_VecLen( Vx, Vy );\r
+\r
+      if ( W == 0 )\r
+      {\r
+        /* XXX: UNDOCUMENTED! It seems that it is possible to try   */\r
+        /*      to normalize the vector (0,0).  Return immediately. */\r
+        return SUCCESS;\r
+      }\r
+\r
+      R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );\r
+      R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );\r
+\r
+      return SUCCESS;\r
+    }\r
+\r
+    W = TT_VecLen( Vx, Vy );\r
+\r
+    Vx = FT_MulDiv( Vx, 0x4000L, W );\r
+    Vy = FT_MulDiv( Vy, 0x4000L, W );\r
+\r
+    W = Vx * Vx + Vy * Vy;\r
+\r
+    /* Now, we want that Sqrt( W ) = 0x4000 */\r
+    /* Or 0x10000000 <= W < 0x10004000        */\r
+\r
+    if ( Vx < 0 )\r
+    {\r
+      Vx = -Vx;\r
+      S1 = TRUE;\r
+    }\r
+    else\r
+      S1 = FALSE;\r
+\r
+    if ( Vy < 0 )\r
+    {\r
+      Vy = -Vy;\r
+      S2 = TRUE;\r
+    }\r
+    else\r
+      S2 = FALSE;\r
+\r
+    while ( W < 0x10000000L )\r
+    {\r
+      /* We need to increase W by a minimal amount */\r
+      if ( Vx < Vy )\r
+        Vx++;\r
+      else\r
+        Vy++;\r
+\r
+      W = Vx * Vx + Vy * Vy;\r
+    }\r
+\r
+    while ( W >= 0x10004000L )\r
+    {\r
+      /* We need to decrease W by a minimal amount */\r
+      if ( Vx < Vy )\r
+        Vx--;\r
+      else\r
+        Vy--;\r
+\r
+      W = Vx * Vx + Vy * Vy;\r
+    }\r
+\r
+    /* Note that in various cases, we can only  */\r
+    /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */\r
+\r
+    if ( S1 )\r
+      Vx = -Vx;\r
+\r
+    if ( S2 )\r
+      Vy = -Vy;\r
+\r
+    R->x = (FT_F2Dot14)Vx;   /* Type conversion */\r
+    R->y = (FT_F2Dot14)Vy;   /* Type conversion */\r
+\r
+    return SUCCESS;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* Here we start with the implementation of the various opcodes.         */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  static FT_Bool\r
+  Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,\r
+                      FT_UShort       aIdx2,\r
+                      FT_Int          aOpc,\r
+                      FT_UnitVector*  Vec )\r
+  {\r
+    FT_Long     A, B, C;\r
+    FT_Vector*  p1;\r
+    FT_Vector*  p2;\r
+\r
+\r
+    if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||\r
+         BOUNDS( aIdx2, CUR.zp1.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return FAILURE;\r
+    }\r
+\r
+    p1 = CUR.zp1.cur + aIdx2;\r
+    p2 = CUR.zp2.cur + aIdx1;\r
+\r
+    A = p1->x - p2->x;\r
+    B = p1->y - p2->y;\r
+\r
+    if ( ( aOpc & 1 ) != 0 )\r
+    {\r
+      C =  B;   /* counter clockwise rotation */\r
+      B =  A;\r
+      A = -C;\r
+    }\r
+\r
+    NORMalize( A, B, Vec );\r
+\r
+    return SUCCESS;\r
+  }\r
+\r
+\r
+  /* When not using the big switch statements, the interpreter uses a */\r
+  /* call table defined later below in this source.  Each opcode must */\r
+  /* thus have a corresponding function, even trivial ones.           */\r
+  /*                                                                  */\r
+  /* They are all defined there.                                      */\r
+\r
+#define DO_SVTCA                            \\r
+  {                                         \\r
+    FT_Short  A, B;                         \\r
+                                            \\r
+                                            \\r
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \\r
+    B = A ^ (FT_Short)0x4000;               \\r
+                                            \\r
+    CUR.GS.freeVector.x = A;                \\r
+    CUR.GS.projVector.x = A;                \\r
+    CUR.GS.dualVector.x = A;                \\r
+                                            \\r
+    CUR.GS.freeVector.y = B;                \\r
+    CUR.GS.projVector.y = B;                \\r
+    CUR.GS.dualVector.y = B;                \\r
+                                            \\r
+    COMPUTE_Funcs();                        \\r
+  }\r
+\r
+\r
+#define DO_SPVTCA                           \\r
+  {                                         \\r
+    FT_Short  A, B;                         \\r
+                                            \\r
+                                            \\r
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \\r
+    B = A ^ (FT_Short)0x4000;               \\r
+                                            \\r
+    CUR.GS.projVector.x = A;                \\r
+    CUR.GS.dualVector.x = A;                \\r
+                                            \\r
+    CUR.GS.projVector.y = B;                \\r
+    CUR.GS.dualVector.y = B;                \\r
+                                            \\r
+    GUESS_VECTOR( freeVector );             \\r
+                                            \\r
+    COMPUTE_Funcs();                        \\r
+  }\r
+\r
+\r
+#define DO_SFVTCA                           \\r
+  {                                         \\r
+    FT_Short  A, B;                         \\r
+                                            \\r
+                                            \\r
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \\r
+    B = A ^ (FT_Short)0x4000;               \\r
+                                            \\r
+    CUR.GS.freeVector.x = A;                \\r
+    CUR.GS.freeVector.y = B;                \\r
+                                            \\r
+    GUESS_VECTOR( projVector );             \\r
+                                            \\r
+    COMPUTE_Funcs();                        \\r
+  }\r
+\r
+\r
+#define DO_SPVTL                                      \\r
+    if ( INS_SxVTL( (FT_UShort)args[1],               \\r
+                    (FT_UShort)args[0],               \\r
+                    CUR.opcode,                       \\r
+                    &CUR.GS.projVector ) == SUCCESS ) \\r
+    {                                                 \\r
+      CUR.GS.dualVector = CUR.GS.projVector;          \\r
+      GUESS_VECTOR( freeVector );                     \\r
+      COMPUTE_Funcs();                                \\r
+    }\r
+\r
+\r
+#define DO_SFVTL                                      \\r
+    if ( INS_SxVTL( (FT_UShort)args[1],               \\r
+                    (FT_UShort)args[0],               \\r
+                    CUR.opcode,                       \\r
+                    &CUR.GS.freeVector ) == SUCCESS ) \\r
+    {                                                 \\r
+      GUESS_VECTOR( projVector );                     \\r
+      COMPUTE_Funcs();                                \\r
+    }\r
+\r
+\r
+#define DO_SFVTPV                          \\r
+    GUESS_VECTOR( projVector );            \\r
+    CUR.GS.freeVector = CUR.GS.projVector; \\r
+    COMPUTE_Funcs();\r
+\r
+\r
+#define DO_SPVFS                                \\r
+  {                                             \\r
+    FT_Short  S;                                \\r
+    FT_Long   X, Y;                             \\r
+                                                \\r
+                                                \\r
+    /* Only use low 16bits, then sign extend */ \\r
+    S = (FT_Short)args[1];                      \\r
+    Y = (FT_Long)S;                             \\r
+    S = (FT_Short)args[0];                      \\r
+    X = (FT_Long)S;                             \\r
+                                                \\r
+    NORMalize( X, Y, &CUR.GS.projVector );      \\r
+                                                \\r
+    CUR.GS.dualVector = CUR.GS.projVector;      \\r
+    GUESS_VECTOR( freeVector );                 \\r
+    COMPUTE_Funcs();                            \\r
+  }\r
+\r
+\r
+#define DO_SFVFS                                \\r
+  {                                             \\r
+    FT_Short  S;                                \\r
+    FT_Long   X, Y;                             \\r
+                                                \\r
+                                                \\r
+    /* Only use low 16bits, then sign extend */ \\r
+    S = (FT_Short)args[1];                      \\r
+    Y = (FT_Long)S;                             \\r
+    S = (FT_Short)args[0];                      \\r
+    X = S;                                      \\r
+                                                \\r
+    NORMalize( X, Y, &CUR.GS.freeVector );      \\r
+    GUESS_VECTOR( projVector );                 \\r
+    COMPUTE_Funcs();                            \\r
+  }\r
+\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+#define DO_GPV                                   \\r
+    if ( CUR.face->unpatented_hinting )          \\r
+    {                                            \\r
+      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \\r
+      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \\r
+    }                                            \\r
+    else                                         \\r
+    {                                            \\r
+      args[0] = CUR.GS.projVector.x;             \\r
+      args[1] = CUR.GS.projVector.y;             \\r
+    }\r
+#else\r
+#define DO_GPV                                   \\r
+    args[0] = CUR.GS.projVector.x;               \\r
+    args[1] = CUR.GS.projVector.y;\r
+#endif\r
+\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+#define DO_GFV                                   \\r
+    if ( CUR.face->unpatented_hinting )          \\r
+    {                                            \\r
+      args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \\r
+      args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \\r
+    }                                            \\r
+    else                                         \\r
+    {                                            \\r
+      args[0] = CUR.GS.freeVector.x;             \\r
+      args[1] = CUR.GS.freeVector.y;             \\r
+    }\r
+#else\r
+#define DO_GFV                                   \\r
+    args[0] = CUR.GS.freeVector.x;               \\r
+    args[1] = CUR.GS.freeVector.y;\r
+#endif\r
+\r
+\r
+#define DO_SRP0                      \\r
+    CUR.GS.rp0 = (FT_UShort)args[0];\r
+\r
+\r
+#define DO_SRP1                      \\r
+    CUR.GS.rp1 = (FT_UShort)args[0];\r
+\r
+\r
+#define DO_SRP2                      \\r
+    CUR.GS.rp2 = (FT_UShort)args[0];\r
+\r
+\r
+#define DO_RTHG                                         \\r
+    CUR.GS.round_state = TT_Round_To_Half_Grid;         \\r
+    CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;\r
+\r
+\r
+#define DO_RTG                                     \\r
+    CUR.GS.round_state = TT_Round_To_Grid;         \\r
+    CUR.func_round = (TT_Round_Func)Round_To_Grid;\r
+\r
+\r
+#define DO_RTDG                                           \\r
+    CUR.GS.round_state = TT_Round_To_Double_Grid;         \\r
+    CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;\r
+\r
+\r
+#define DO_RUTG                                       \\r
+    CUR.GS.round_state = TT_Round_Up_To_Grid;         \\r
+    CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;\r
+\r
+\r
+#define DO_RDTG                                         \\r
+    CUR.GS.round_state = TT_Round_Down_To_Grid;         \\r
+    CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;\r
+\r
+\r
+#define DO_ROFF                                 \\r
+    CUR.GS.round_state = TT_Round_Off;          \\r
+    CUR.func_round = (TT_Round_Func)Round_None;\r
+\r
+\r
+#define DO_SROUND                                \\r
+    SET_SuperRound( 0x4000, args[0] );           \\r
+    CUR.GS.round_state = TT_Round_Super;         \\r
+    CUR.func_round = (TT_Round_Func)Round_Super;\r
+\r
+\r
+#define DO_S45ROUND                                 \\r
+    SET_SuperRound( 0x2D41, args[0] );              \\r
+    CUR.GS.round_state = TT_Round_Super_45;         \\r
+    CUR.func_round = (TT_Round_Func)Round_Super_45;\r
+\r
+\r
+#define DO_SLOOP                       \\r
+    if ( args[0] < 0 )                 \\r
+      CUR.error = TT_Err_Bad_Argument; \\r
+    else                               \\r
+      CUR.GS.loop = args[0];\r
+\r
+\r
+#define DO_SMD                         \\r
+    CUR.GS.minimum_distance = args[0];\r
+\r
+\r
+#define DO_SCVTCI                                     \\r
+    CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];\r
+\r
+\r
+#define DO_SSWCI                                     \\r
+    CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];\r
+\r
+\r
+    /* XXX: UNDOCUMENTED! or bug in the Windows engine?   */\r
+    /*                                                    */\r
+    /*      It seems that the value that is read here is  */\r
+    /*      expressed in 16.16 format rather than in font */\r
+    /*      units.                                        */\r
+    /*                                                    */\r
+#define DO_SSW                                                 \\r
+    CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );\r
+\r
+\r
+#define DO_FLIPON            \\r
+    CUR.GS.auto_flip = TRUE;\r
+\r
+\r
+#define DO_FLIPOFF            \\r
+    CUR.GS.auto_flip = FALSE;\r
+\r
+\r
+#define DO_SDB                             \\r
+    CUR.GS.delta_base = (FT_Short)args[0];\r
+\r
+\r
+#define DO_SDS                              \\r
+    CUR.GS.delta_shift = (FT_Short)args[0];\r
+\r
+\r
+#define DO_MD  /* nothing */\r
+\r
+\r
+#define DO_MPPEM              \\r
+    args[0] = CURRENT_Ppem();\r
+\r
+\r
+  /* Note: The pointSize should be irrelevant in a given font program; */\r
+  /*       we thus decide to return only the ppem.                     */\r
+#if 0\r
+\r
+#define DO_MPS                       \\r
+    args[0] = CUR.metrics.pointSize;\r
+\r
+#else\r
+\r
+#define DO_MPS                \\r
+    args[0] = CURRENT_Ppem();\r
+\r
+#endif /* 0 */\r
+\r
+\r
+#define DO_DUP         \\r
+    args[1] = args[0];\r
+\r
+\r
+#define DO_CLEAR     \\r
+    CUR.new_top = 0;\r
+\r
+\r
+#define DO_SWAP        \\r
+  {                    \\r
+    FT_Long  L;        \\r
+                       \\r
+                       \\r
+    L       = args[0]; \\r
+    args[0] = args[1]; \\r
+    args[1] = L;       \\r
+  }\r
+\r
+\r
+#define DO_DEPTH       \\r
+    args[0] = CUR.top;\r
+\r
+\r
+#define DO_CINDEX                           \\r
+  {                                         \\r
+    FT_Long  L;                             \\r
+                                            \\r
+                                            \\r
+    L = args[0];                            \\r
+                                            \\r
+    if ( L <= 0 || L > CUR.args )           \\r
+      CUR.error = TT_Err_Invalid_Reference; \\r
+    else                                    \\r
+      args[0] = CUR.stack[CUR.args - L];    \\r
+  }\r
+\r
+\r
+#define DO_JROT               \\r
+    if ( args[1] != 0 )       \\r
+    {                         \\r
+      CUR.IP      += args[0]; \\r
+      CUR.step_ins = FALSE;   \\r
+    }\r
+\r
+\r
+#define DO_JMPR             \\r
+    CUR.IP      += args[0]; \\r
+    CUR.step_ins = FALSE;\r
+\r
+\r
+#define DO_JROF               \\r
+    if ( args[1] == 0 )       \\r
+    {                         \\r
+      CUR.IP      += args[0]; \\r
+      CUR.step_ins = FALSE;   \\r
+    }\r
+\r
+\r
+#define DO_LT                        \\r
+    args[0] = ( args[0] < args[1] );\r
+\r
+\r
+#define DO_LTEQ                       \\r
+    args[0] = ( args[0] <= args[1] );\r
+\r
+\r
+#define DO_GT                        \\r
+    args[0] = ( args[0] > args[1] );\r
+\r
+\r
+#define DO_GTEQ                       \\r
+    args[0] = ( args[0] >= args[1] );\r
+\r
+\r
+#define DO_EQ                         \\r
+    args[0] = ( args[0] == args[1] );\r
+\r
+\r
+#define DO_NEQ                        \\r
+    args[0] = ( args[0] != args[1] );\r
+\r
+\r
+#define DO_ODD                                                  \\r
+    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );\r
+\r
+\r
+#define DO_EVEN                                                \\r
+    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );\r
+\r
+\r
+#define DO_AND                        \\r
+    args[0] = ( args[0] && args[1] );\r
+\r
+\r
+#define DO_OR                         \\r
+    args[0] = ( args[0] || args[1] );\r
+\r
+\r
+#define DO_NOT          \\r
+    args[0] = !args[0];\r
+\r
+\r
+#define DO_ADD          \\r
+    args[0] += args[1];\r
+\r
+\r
+#define DO_SUB          \\r
+    args[0] -= args[1];\r
+\r
+\r
+#define DO_DIV                                               \\r
+    if ( args[1] == 0 )                                      \\r
+      CUR.error = TT_Err_Divide_By_Zero;                     \\r
+    else                                                     \\r
+      args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );\r
+\r
+\r
+#define DO_MUL                                    \\r
+    args[0] = TT_MULDIV( args[0], args[1], 64L );\r
+\r
+\r
+#define DO_ABS                   \\r
+    args[0] = FT_ABS( args[0] );\r
+\r
+\r
+#define DO_NEG          \\r
+    args[0] = -args[0];\r
+\r
+\r
+#define DO_FLOOR    \\r
+    args[0] = FT_PIX_FLOOR( args[0] );\r
+\r
+\r
+#define DO_CEILING                    \\r
+    args[0] = FT_PIX_CEIL( args[0] );\r
+\r
+\r
+#define DO_RS                          \\r
+   {                                   \\r
+     FT_ULong  I = (FT_ULong)args[0];  \\r
+                                       \\r
+                                       \\r
+     if ( BOUNDS( I, CUR.storeSize ) ) \\r
+     {                                 \\r
+       if ( CUR.pedantic_hinting )     \\r
+       {                               \\r
+         ARRAY_BOUND_ERROR;            \\r
+       }                               \\r
+       else                            \\r
+         args[0] = 0;                  \\r
+     }                                 \\r
+     else                              \\r
+       args[0] = CUR.storage[I];       \\r
+   }\r
+\r
+\r
+#define DO_WS                          \\r
+   {                                   \\r
+     FT_ULong  I = (FT_ULong)args[0];  \\r
+                                       \\r
+                                       \\r
+     if ( BOUNDS( I, CUR.storeSize ) ) \\r
+     {                                 \\r
+       if ( CUR.pedantic_hinting )     \\r
+       {                               \\r
+         ARRAY_BOUND_ERROR;            \\r
+       }                               \\r
+     }                                 \\r
+     else                              \\r
+       CUR.storage[I] = args[1];       \\r
+   }\r
+\r
+\r
+#define DO_RCVT                          \\r
+   {                                     \\r
+     FT_ULong  I = (FT_ULong)args[0];    \\r
+                                         \\r
+                                         \\r
+     if ( BOUNDS( I, CUR.cvtSize ) )     \\r
+     {                                   \\r
+       if ( CUR.pedantic_hinting )       \\r
+       {                                 \\r
+         ARRAY_BOUND_ERROR;              \\r
+       }                                 \\r
+       else                              \\r
+         args[0] = 0;                    \\r
+     }                                   \\r
+     else                                \\r
+       args[0] = CUR_Func_read_cvt( I ); \\r
+   }\r
+\r
+\r
+#define DO_WCVTP                         \\r
+   {                                     \\r
+     FT_ULong  I = (FT_ULong)args[0];    \\r
+                                         \\r
+                                         \\r
+     if ( BOUNDS( I, CUR.cvtSize ) )     \\r
+     {                                   \\r
+       if ( CUR.pedantic_hinting )       \\r
+       {                                 \\r
+         ARRAY_BOUND_ERROR;              \\r
+       }                                 \\r
+     }                                   \\r
+     else                                \\r
+       CUR_Func_write_cvt( I, args[1] ); \\r
+   }\r
+\r
+\r
+#define DO_WCVTF                                                \\r
+   {                                                            \\r
+     FT_ULong  I = (FT_ULong)args[0];                           \\r
+                                                                \\r
+                                                                \\r
+     if ( BOUNDS( I, CUR.cvtSize ) )                            \\r
+     {                                                          \\r
+       if ( CUR.pedantic_hinting )                              \\r
+       {                                                        \\r
+         ARRAY_BOUND_ERROR;                                     \\r
+       }                                                        \\r
+     }                                                          \\r
+     else                                                       \\r
+       CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \\r
+   }\r
+\r
+\r
+#define DO_DEBUG                     \\r
+    CUR.error = TT_Err_Debug_OpCode;\r
+\r
+\r
+#define DO_ROUND                                                   \\r
+    args[0] = CUR_Func_round(                                      \\r
+                args[0],                                           \\r
+                CUR.tt_metrics.compensations[CUR.opcode - 0x68] );\r
+\r
+\r
+#define DO_NROUND                                                            \\r
+    args[0] = ROUND_None( args[0],                                           \\r
+                          CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );\r
+\r
+\r
+#define DO_MAX               \\r
+    if ( args[1] > args[0] ) \\r
+      args[0] = args[1];\r
+\r
+\r
+#define DO_MIN               \\r
+    if ( args[1] < args[0] ) \\r
+      args[0] = args[1];\r
+\r
+\r
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH\r
+\r
+\r
+#undef  ARRAY_BOUND_ERROR\r
+#define ARRAY_BOUND_ERROR                   \\r
+    {                                       \\r
+      CUR.error = TT_Err_Invalid_Reference; \\r
+      return;                               \\r
+    }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */\r
+  /* Opcode range: 0x00-0x01                                               */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SVTCA( INS_ARG )\r
+  {\r
+    DO_SVTCA\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SPVTCA[a]:    Set PVector to Coordinate Axis                          */\r
+  /* Opcode range: 0x02-0x03                                               */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SPVTCA( INS_ARG )\r
+  {\r
+    DO_SPVTCA\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SFVTCA[a]:    Set FVector to Coordinate Axis                          */\r
+  /* Opcode range: 0x04-0x05                                               */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SFVTCA( INS_ARG )\r
+  {\r
+    DO_SFVTCA\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SPVTL[a]:     Set PVector To Line                                     */\r
+  /* Opcode range: 0x06-0x07                                               */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SPVTL( INS_ARG )\r
+  {\r
+    DO_SPVTL\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SFVTL[a]:     Set FVector To Line                                     */\r
+  /* Opcode range: 0x08-0x09                                               */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SFVTL( INS_ARG )\r
+  {\r
+    DO_SFVTL\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SFVTPV[]:     Set FVector To PVector                                  */\r
+  /* Opcode range: 0x0E                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SFVTPV( INS_ARG )\r
+  {\r
+    DO_SFVTPV\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SPVFS[]:      Set PVector From Stack                                  */\r
+  /* Opcode range: 0x0A                                                    */\r
+  /* Stack:        f2.14 f2.14 -->                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SPVFS( INS_ARG )\r
+  {\r
+    DO_SPVFS\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SFVFS[]:      Set FVector From Stack                                  */\r
+  /* Opcode range: 0x0B                                                    */\r
+  /* Stack:        f2.14 f2.14 -->                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SFVFS( INS_ARG )\r
+  {\r
+    DO_SFVFS\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* GPV[]:        Get Projection Vector                                   */\r
+  /* Opcode range: 0x0C                                                    */\r
+  /* Stack:        ef2.14 --> ef2.14                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_GPV( INS_ARG )\r
+  {\r
+    DO_GPV\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /* GFV[]:        Get Freedom Vector                                      */\r
+  /* Opcode range: 0x0D                                                    */\r
+  /* Stack:        ef2.14 --> ef2.14                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_GFV( INS_ARG )\r
+  {\r
+    DO_GFV\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SRP0[]:       Set Reference Point 0                                   */\r
+  /* Opcode range: 0x10                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SRP0( INS_ARG )\r
+  {\r
+    DO_SRP0\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SRP1[]:       Set Reference Point 1                                   */\r
+  /* Opcode range: 0x11                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SRP1( INS_ARG )\r
+  {\r
+    DO_SRP1\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SRP2[]:       Set Reference Point 2                                   */\r
+  /* Opcode range: 0x12                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SRP2( INS_ARG )\r
+  {\r
+    DO_SRP2\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* RTHG[]:       Round To Half Grid                                      */\r
+  /* Opcode range: 0x19                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_RTHG( INS_ARG )\r
+  {\r
+    DO_RTHG\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* RTG[]:        Round To Grid                                           */\r
+  /* Opcode range: 0x18                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_RTG( INS_ARG )\r
+  {\r
+    DO_RTG\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /* RTDG[]:       Round To Double Grid                                    */\r
+  /* Opcode range: 0x3D                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_RTDG( INS_ARG )\r
+  {\r
+    DO_RTDG\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /* RUTG[]:       Round Up To Grid                                        */\r
+  /* Opcode range: 0x7C                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_RUTG( INS_ARG )\r
+  {\r
+    DO_RUTG\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* RDTG[]:       Round Down To Grid                                      */\r
+  /* Opcode range: 0x7D                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_RDTG( INS_ARG )\r
+  {\r
+    DO_RDTG\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ROFF[]:       Round OFF                                               */\r
+  /* Opcode range: 0x7A                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ROFF( INS_ARG )\r
+  {\r
+    DO_ROFF\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SROUND[]:     Super ROUND                                             */\r
+  /* Opcode range: 0x76                                                    */\r
+  /* Stack:        Eint8 -->                                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SROUND( INS_ARG )\r
+  {\r
+    DO_SROUND\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* S45ROUND[]:   Super ROUND 45 degrees                                  */\r
+  /* Opcode range: 0x77                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_S45ROUND( INS_ARG )\r
+  {\r
+    DO_S45ROUND\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SLOOP[]:      Set LOOP variable                                       */\r
+  /* Opcode range: 0x17                                                    */\r
+  /* Stack:        int32? -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SLOOP( INS_ARG )\r
+  {\r
+    DO_SLOOP\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SMD[]:        Set Minimum Distance                                    */\r
+  /* Opcode range: 0x1A                                                    */\r
+  /* Stack:        f26.6 -->                                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SMD( INS_ARG )\r
+  {\r
+    DO_SMD\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SCVTCI[]:     Set Control Value Table Cut In                          */\r
+  /* Opcode range: 0x1D                                                    */\r
+  /* Stack:        f26.6 -->                                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SCVTCI( INS_ARG )\r
+  {\r
+    DO_SCVTCI\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SSWCI[]:      Set Single Width Cut In                                 */\r
+  /* Opcode range: 0x1E                                                    */\r
+  /* Stack:        f26.6 -->                                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SSWCI( INS_ARG )\r
+  {\r
+    DO_SSWCI\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SSW[]:        Set Single Width                                        */\r
+  /* Opcode range: 0x1F                                                    */\r
+  /* Stack:        int32? -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SSW( INS_ARG )\r
+  {\r
+    DO_SSW\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* FLIPON[]:     Set auto-FLIP to ON                                     */\r
+  /* Opcode range: 0x4D                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_FLIPON( INS_ARG )\r
+  {\r
+    DO_FLIPON\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */\r
+  /* Opcode range: 0x4E                                                    */\r
+  /* Stack: -->                                                            */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_FLIPOFF( INS_ARG )\r
+  {\r
+    DO_FLIPOFF\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SANGW[]:      Set ANGle Weight                                        */\r
+  /* Opcode range: 0x7E                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SANGW( INS_ARG )\r
+  {\r
+    /* instruction not supported anymore */\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SDB[]:        Set Delta Base                                          */\r
+  /* Opcode range: 0x5E                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SDB( INS_ARG )\r
+  {\r
+    DO_SDB\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SDS[]:        Set Delta Shift                                         */\r
+  /* Opcode range: 0x5F                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SDS( INS_ARG )\r
+  {\r
+    DO_SDS\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MPPEM[]:      Measure Pixel Per EM                                    */\r
+  /* Opcode range: 0x4B                                                    */\r
+  /* Stack:        --> Euint16                                             */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MPPEM( INS_ARG )\r
+  {\r
+    DO_MPPEM\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MPS[]:        Measure Point Size                                      */\r
+  /* Opcode range: 0x4C                                                    */\r
+  /* Stack:        --> Euint16                                             */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MPS( INS_ARG )\r
+  {\r
+    DO_MPS\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* DUP[]:        DUPlicate the top stack's element                       */\r
+  /* Opcode range: 0x20                                                    */\r
+  /* Stack:        StkElt --> StkElt StkElt                                */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_DUP( INS_ARG )\r
+  {\r
+    DO_DUP\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* POP[]:        POP the stack's top element                             */\r
+  /* Opcode range: 0x21                                                    */\r
+  /* Stack:        StkElt -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_POP( INS_ARG )\r
+  {\r
+    /* nothing to do */\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* CLEAR[]:      CLEAR the entire stack                                  */\r
+  /* Opcode range: 0x22                                                    */\r
+  /* Stack:        StkElt... -->                                           */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_CLEAR( INS_ARG )\r
+  {\r
+    DO_CLEAR\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SWAP[]:       SWAP the stack's top two elements                       */\r
+  /* Opcode range: 0x23                                                    */\r
+  /* Stack:        2 * StkElt --> 2 * StkElt                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SWAP( INS_ARG )\r
+  {\r
+    DO_SWAP\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* DEPTH[]:      return the stack DEPTH                                  */\r
+  /* Opcode range: 0x24                                                    */\r
+  /* Stack:        --> uint32                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_DEPTH( INS_ARG )\r
+  {\r
+    DO_DEPTH\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* CINDEX[]:     Copy INDEXed element                                    */\r
+  /* Opcode range: 0x25                                                    */\r
+  /* Stack:        int32 --> StkElt                                        */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_CINDEX( INS_ARG )\r
+  {\r
+    DO_CINDEX\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* EIF[]:        End IF                                                  */\r
+  /* Opcode range: 0x59                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_EIF( INS_ARG )\r
+  {\r
+    /* nothing to do */\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* JROT[]:       Jump Relative On True                                   */\r
+  /* Opcode range: 0x78                                                    */\r
+  /* Stack:        StkElt int32 -->                                        */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_JROT( INS_ARG )\r
+  {\r
+    DO_JROT\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* JMPR[]:       JuMP Relative                                           */\r
+  /* Opcode range: 0x1C                                                    */\r
+  /* Stack:        int32 -->                                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_JMPR( INS_ARG )\r
+  {\r
+    DO_JMPR\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* JROF[]:       Jump Relative On False                                  */\r
+  /* Opcode range: 0x79                                                    */\r
+  /* Stack:        StkElt int32 -->                                        */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_JROF( INS_ARG )\r
+  {\r
+    DO_JROF\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* LT[]:         Less Than                                               */\r
+  /* Opcode range: 0x50                                                    */\r
+  /* Stack:        int32? int32? --> bool                                  */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_LT( INS_ARG )\r
+  {\r
+    DO_LT\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* LTEQ[]:       Less Than or EQual                                      */\r
+  /* Opcode range: 0x51                                                    */\r
+  /* Stack:        int32? int32? --> bool                                  */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_LTEQ( INS_ARG )\r
+  {\r
+    DO_LTEQ\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* GT[]:         Greater Than                                            */\r
+  /* Opcode range: 0x52                                                    */\r
+  /* Stack:        int32? int32? --> bool                                  */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_GT( INS_ARG )\r
+  {\r
+    DO_GT\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* GTEQ[]:       Greater Than or EQual                                   */\r
+  /* Opcode range: 0x53                                                    */\r
+  /* Stack:        int32? int32? --> bool                                  */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_GTEQ( INS_ARG )\r
+  {\r
+    DO_GTEQ\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* EQ[]:         EQual                                                   */\r
+  /* Opcode range: 0x54                                                    */\r
+  /* Stack:        StkElt StkElt --> bool                                  */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_EQ( INS_ARG )\r
+  {\r
+    DO_EQ\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* NEQ[]:        Not EQual                                               */\r
+  /* Opcode range: 0x55                                                    */\r
+  /* Stack:        StkElt StkElt --> bool                                  */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_NEQ( INS_ARG )\r
+  {\r
+    DO_NEQ\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ODD[]:        Is ODD                                                  */\r
+  /* Opcode range: 0x56                                                    */\r
+  /* Stack:        f26.6 --> bool                                          */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ODD( INS_ARG )\r
+  {\r
+    DO_ODD\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* EVEN[]:       Is EVEN                                                 */\r
+  /* Opcode range: 0x57                                                    */\r
+  /* Stack:        f26.6 --> bool                                          */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_EVEN( INS_ARG )\r
+  {\r
+    DO_EVEN\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* AND[]:        logical AND                                             */\r
+  /* Opcode range: 0x5A                                                    */\r
+  /* Stack:        uint32 uint32 --> uint32                                */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_AND( INS_ARG )\r
+  {\r
+    DO_AND\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* OR[]:         logical OR                                              */\r
+  /* Opcode range: 0x5B                                                    */\r
+  /* Stack:        uint32 uint32 --> uint32                                */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_OR( INS_ARG )\r
+  {\r
+    DO_OR\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* NOT[]:        logical NOT                                             */\r
+  /* Opcode range: 0x5C                                                    */\r
+  /* Stack:        StkElt --> uint32                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_NOT( INS_ARG )\r
+  {\r
+    DO_NOT\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ADD[]:        ADD                                                     */\r
+  /* Opcode range: 0x60                                                    */\r
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ADD( INS_ARG )\r
+  {\r
+    DO_ADD\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SUB[]:        SUBtract                                                */\r
+  /* Opcode range: 0x61                                                    */\r
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SUB( INS_ARG )\r
+  {\r
+    DO_SUB\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* DIV[]:        DIVide                                                  */\r
+  /* Opcode range: 0x62                                                    */\r
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_DIV( INS_ARG )\r
+  {\r
+    DO_DIV\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MUL[]:        MULtiply                                                */\r
+  /* Opcode range: 0x63                                                    */\r
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MUL( INS_ARG )\r
+  {\r
+    DO_MUL\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ABS[]:        ABSolute value                                          */\r
+  /* Opcode range: 0x64                                                    */\r
+  /* Stack:        f26.6 --> f26.6                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ABS( INS_ARG )\r
+  {\r
+    DO_ABS\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* NEG[]:        NEGate                                                  */\r
+  /* Opcode range: 0x65                                                    */\r
+  /* Stack: f26.6 --> f26.6                                                */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_NEG( INS_ARG )\r
+  {\r
+    DO_NEG\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* FLOOR[]:      FLOOR                                                   */\r
+  /* Opcode range: 0x66                                                    */\r
+  /* Stack:        f26.6 --> f26.6                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_FLOOR( INS_ARG )\r
+  {\r
+    DO_FLOOR\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* CEILING[]:    CEILING                                                 */\r
+  /* Opcode range: 0x67                                                    */\r
+  /* Stack:        f26.6 --> f26.6                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_CEILING( INS_ARG )\r
+  {\r
+    DO_CEILING\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* RS[]:         Read Store                                              */\r
+  /* Opcode range: 0x43                                                    */\r
+  /* Stack:        uint32 --> uint32                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_RS( INS_ARG )\r
+  {\r
+    DO_RS\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* WS[]:         Write Store                                             */\r
+  /* Opcode range: 0x42                                                    */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_WS( INS_ARG )\r
+  {\r
+    DO_WS\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* WCVTP[]:      Write CVT in Pixel units                                */\r
+  /* Opcode range: 0x44                                                    */\r
+  /* Stack:        f26.6 uint32 -->                                        */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_WCVTP( INS_ARG )\r
+  {\r
+    DO_WCVTP\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* WCVTF[]:      Write CVT in Funits                                     */\r
+  /* Opcode range: 0x70                                                    */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_WCVTF( INS_ARG )\r
+  {\r
+    DO_WCVTF\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* RCVT[]:       Read CVT                                                */\r
+  /* Opcode range: 0x45                                                    */\r
+  /* Stack:        uint32 --> f26.6                                        */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_RCVT( INS_ARG )\r
+  {\r
+    DO_RCVT\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* AA[]:         Adjust Angle                                            */\r
+  /* Opcode range: 0x7F                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_AA( INS_ARG )\r
+  {\r
+    /* intentionally no longer supported */\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* DEBUG[]:      DEBUG.  Unsupported.                                    */\r
+  /* Opcode range: 0x4F                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  /* Note: The original instruction pops a value from the stack.           */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_DEBUG( INS_ARG )\r
+  {\r
+    DO_DEBUG\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ROUND[ab]:    ROUND value                                             */\r
+  /* Opcode range: 0x68-0x6B                                               */\r
+  /* Stack:        f26.6 --> f26.6                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ROUND( INS_ARG )\r
+  {\r
+    DO_ROUND\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* NROUND[ab]:   No ROUNDing of value                                    */\r
+  /* Opcode range: 0x6C-0x6F                                               */\r
+  /* Stack:        f26.6 --> f26.6                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_NROUND( INS_ARG )\r
+  {\r
+    DO_NROUND\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MAX[]:        MAXimum                                                 */\r
+  /* Opcode range: 0x68                                                    */\r
+  /* Stack:        int32? int32? --> int32                                 */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MAX( INS_ARG )\r
+  {\r
+    DO_MAX\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MIN[]:        MINimum                                                 */\r
+  /* Opcode range: 0x69                                                    */\r
+  /* Stack:        int32? int32? --> int32                                 */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MIN( INS_ARG )\r
+  {\r
+    DO_MIN\r
+  }\r
+\r
+\r
+#endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* The following functions are called as is within the switch statement. */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MINDEX[]:     Move INDEXed element                                    */\r
+  /* Opcode range: 0x26                                                    */\r
+  /* Stack:        int32? --> StkElt                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MINDEX( INS_ARG )\r
+  {\r
+    FT_Long  L, K;\r
+\r
+\r
+    L = args[0];\r
+\r
+    if ( L <= 0 || L > CUR.args )\r
+    {\r
+      CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    K = CUR.stack[CUR.args - L];\r
+\r
+    FT_ARRAY_MOVE( &CUR.stack[CUR.args - L    ],\r
+                   &CUR.stack[CUR.args - L + 1],\r
+                   ( L - 1 ) );\r
+\r
+    CUR.stack[CUR.args - 1] = K;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ROLL[]:       ROLL top three elements                                 */\r
+  /* Opcode range: 0x8A                                                    */\r
+  /* Stack:        3 * StkElt --> 3 * StkElt                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ROLL( INS_ARG )\r
+  {\r
+    FT_Long  A, B, C;\r
+\r
+    FT_UNUSED_EXEC;\r
+\r
+\r
+    A = args[2];\r
+    B = args[1];\r
+    C = args[0];\r
+\r
+    args[2] = C;\r
+    args[1] = A;\r
+    args[0] = B;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MANAGING THE FLOW OF CONTROL                                          */\r
+  /*                                                                       */\r
+  /*   Instructions appear in the specification's order.                   */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  static FT_Bool\r
+  SkipCode( EXEC_OP )\r
+  {\r
+    CUR.IP += CUR.length;\r
+\r
+    if ( CUR.IP < CUR.codeSize )\r
+    {\r
+      CUR.opcode = CUR.code[CUR.IP];\r
+\r
+      CUR.length = opcode_length[CUR.opcode];\r
+      if ( CUR.length < 0 )\r
+      {\r
+        if ( CUR.IP + 1 > CUR.codeSize )\r
+          goto Fail_Overflow;\r
+        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];\r
+      }\r
+\r
+      if ( CUR.IP + CUR.length <= CUR.codeSize )\r
+        return SUCCESS;\r
+    }\r
+\r
+  Fail_Overflow:\r
+    CUR.error = TT_Err_Code_Overflow;\r
+    return FAILURE;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* IF[]:         IF test                                                 */\r
+  /* Opcode range: 0x58                                                    */\r
+  /* Stack:        StkElt -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_IF( INS_ARG )\r
+  {\r
+    FT_Int   nIfs;\r
+    FT_Bool  Out;\r
+\r
+\r
+    if ( args[0] != 0 )\r
+      return;\r
+\r
+    nIfs = 1;\r
+    Out = 0;\r
+\r
+    do\r
+    {\r
+      if ( SKIP_Code() == FAILURE )\r
+        return;\r
+\r
+      switch ( CUR.opcode )\r
+      {\r
+      case 0x58:      /* IF */\r
+        nIfs++;\r
+        break;\r
+\r
+      case 0x1B:      /* ELSE */\r
+        Out = FT_BOOL( nIfs == 1 );\r
+        break;\r
+\r
+      case 0x59:      /* EIF */\r
+        nIfs--;\r
+        Out = FT_BOOL( nIfs == 0 );\r
+        break;\r
+      }\r
+    } while ( Out == 0 );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ELSE[]:       ELSE                                                    */\r
+  /* Opcode range: 0x1B                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ELSE( INS_ARG )\r
+  {\r
+    FT_Int  nIfs;\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    nIfs = 1;\r
+\r
+    do\r
+    {\r
+      if ( SKIP_Code() == FAILURE )\r
+        return;\r
+\r
+      switch ( CUR.opcode )\r
+      {\r
+      case 0x58:    /* IF */\r
+        nIfs++;\r
+        break;\r
+\r
+      case 0x59:    /* EIF */\r
+        nIfs--;\r
+        break;\r
+      }\r
+    } while ( nIfs != 0 );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */\r
+  /*                                                                       */\r
+  /*   Instructions appear in the specification's order.                   */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* FDEF[]:       Function DEFinition                                     */\r
+  /* Opcode range: 0x2C                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_FDEF( INS_ARG )\r
+  {\r
+    FT_ULong       n;\r
+    TT_DefRecord*  rec;\r
+    TT_DefRecord*  limit;\r
+\r
+\r
+    /* some font programs are broken enough to redefine functions! */\r
+    /* We will then parse the current table.                       */\r
+\r
+    rec   = CUR.FDefs;\r
+    limit = rec + CUR.numFDefs;\r
+    n     = args[0];\r
+\r
+    for ( ; rec < limit; rec++ )\r
+    {\r
+      if ( rec->opc == n )\r
+        break;\r
+    }\r
+\r
+    if ( rec == limit )\r
+    {\r
+      /* check that there is enough room for new functions */\r
+      if ( CUR.numFDefs >= CUR.maxFDefs )\r
+      {\r
+        CUR.error = TT_Err_Too_Many_Function_Defs;\r
+        return;\r
+      }\r
+      CUR.numFDefs++;\r
+    }\r
+\r
+    rec->range  = CUR.curRange;\r
+    rec->opc    = n;\r
+    rec->start  = CUR.IP + 1;\r
+    rec->active = TRUE;\r
+\r
+    if ( n > CUR.maxFunc )\r
+      CUR.maxFunc = n;\r
+\r
+    /* Now skip the whole function definition. */\r
+    /* We don't allow nested IDEFS & FDEFs.    */\r
+\r
+    while ( SKIP_Code() == SUCCESS )\r
+    {\r
+      switch ( CUR.opcode )\r
+      {\r
+      case 0x89:    /* IDEF */\r
+      case 0x2C:    /* FDEF */\r
+        CUR.error = TT_Err_Nested_DEFS;\r
+        return;\r
+\r
+      case 0x2D:   /* ENDF */\r
+        return;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ENDF[]:       END Function definition                                 */\r
+  /* Opcode range: 0x2D                                                    */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ENDF( INS_ARG )\r
+  {\r
+    TT_CallRec*  pRec;\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */\r
+    {\r
+      CUR.error = TT_Err_ENDF_In_Exec_Stream;\r
+      return;\r
+    }\r
+\r
+    CUR.callTop--;\r
+\r
+    pRec = &CUR.callStack[CUR.callTop];\r
+\r
+    pRec->Cur_Count--;\r
+\r
+    CUR.step_ins = FALSE;\r
+\r
+    if ( pRec->Cur_Count > 0 )\r
+    {\r
+      CUR.callTop++;\r
+      CUR.IP = pRec->Cur_Restart;\r
+    }\r
+    else\r
+      /* Loop through the current function */\r
+      INS_Goto_CodeRange( pRec->Caller_Range,\r
+                          pRec->Caller_IP );\r
+\r
+    /* Exit the current call frame.                      */\r
+\r
+    /* NOTE: If the last instruction of a program is a   */\r
+    /*       CALL or LOOPCALL, the return address is     */\r
+    /*       always out of the code range.  This is a    */\r
+    /*       valid address, and it is why we do not test */\r
+    /*       the result of Ins_Goto_CodeRange() here!    */\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* CALL[]:       CALL function                                           */\r
+  /* Opcode range: 0x2B                                                    */\r
+  /* Stack:        uint32? -->                                             */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_CALL( INS_ARG )\r
+  {\r
+    FT_ULong       F;\r
+    TT_CallRec*    pCrec;\r
+    TT_DefRecord*  def;\r
+\r
+\r
+    /* first of all, check the index */\r
+\r
+    F = args[0];\r
+    if ( BOUNDS( F, CUR.maxFunc + 1 ) )\r
+      goto Fail;\r
+\r
+    /* Except for some old Apple fonts, all functions in a TrueType */\r
+    /* font are defined in increasing order, starting from 0.  This */\r
+    /* means that we normally have                                  */\r
+    /*                                                              */\r
+    /*    CUR.maxFunc+1 == CUR.numFDefs                             */\r
+    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */\r
+    /*                                                              */\r
+    /* If this isn't true, we need to look up the function table.   */\r
+\r
+    def = CUR.FDefs + F;\r
+    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )\r
+    {\r
+      /* look up the FDefs table */\r
+      TT_DefRecord*  limit;\r
+\r
+\r
+      def   = CUR.FDefs;\r
+      limit = def + CUR.numFDefs;\r
+\r
+      while ( def < limit && def->opc != F )\r
+        def++;\r
+\r
+      if ( def == limit )\r
+        goto Fail;\r
+    }\r
+\r
+    /* check that the function is active */\r
+    if ( !def->active )\r
+      goto Fail;\r
+\r
+    /* check the call stack */\r
+    if ( CUR.callTop >= CUR.callSize )\r
+    {\r
+      CUR.error = TT_Err_Stack_Overflow;\r
+      return;\r
+    }\r
+\r
+    pCrec = CUR.callStack + CUR.callTop;\r
+\r
+    pCrec->Caller_Range = CUR.curRange;\r
+    pCrec->Caller_IP    = CUR.IP + 1;\r
+    pCrec->Cur_Count    = 1;\r
+    pCrec->Cur_Restart  = def->start;\r
+\r
+    CUR.callTop++;\r
+\r
+    INS_Goto_CodeRange( def->range,\r
+                        def->start );\r
+\r
+    CUR.step_ins = FALSE;\r
+    return;\r
+\r
+  Fail:\r
+    CUR.error = TT_Err_Invalid_Reference;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* LOOPCALL[]:   LOOP and CALL function                                  */\r
+  /* Opcode range: 0x2A                                                    */\r
+  /* Stack:        uint32? Eint16? -->                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_LOOPCALL( INS_ARG )\r
+  {\r
+    FT_ULong       F;\r
+    TT_CallRec*    pCrec;\r
+    TT_DefRecord*  def;\r
+\r
+\r
+    /* first of all, check the index */\r
+    F = args[1];\r
+    if ( BOUNDS( F, CUR.maxFunc + 1 ) )\r
+      goto Fail;\r
+\r
+    /* Except for some old Apple fonts, all functions in a TrueType */\r
+    /* font are defined in increasing order, starting from 0.  This */\r
+    /* means that we normally have                                  */\r
+    /*                                                              */\r
+    /*    CUR.maxFunc+1 == CUR.numFDefs                             */\r
+    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */\r
+    /*                                                              */\r
+    /* If this isn't true, we need to look up the function table.   */\r
+\r
+    def = CUR.FDefs + F;\r
+    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )\r
+    {\r
+      /* look up the FDefs table */\r
+      TT_DefRecord*  limit;\r
+\r
+\r
+      def   = CUR.FDefs;\r
+      limit = def + CUR.numFDefs;\r
+\r
+      while ( def < limit && def->opc != F )\r
+        def++;\r
+\r
+      if ( def == limit )\r
+        goto Fail;\r
+    }\r
+\r
+    /* check that the function is active */\r
+    if ( !def->active )\r
+      goto Fail;\r
+\r
+    /* check stack */\r
+    if ( CUR.callTop >= CUR.callSize )\r
+    {\r
+      CUR.error = TT_Err_Stack_Overflow;\r
+      return;\r
+    }\r
+\r
+    if ( args[0] > 0 )\r
+    {\r
+      pCrec = CUR.callStack + CUR.callTop;\r
+\r
+      pCrec->Caller_Range = CUR.curRange;\r
+      pCrec->Caller_IP    = CUR.IP + 1;\r
+      pCrec->Cur_Count    = (FT_Int)args[0];\r
+      pCrec->Cur_Restart  = def->start;\r
+\r
+      CUR.callTop++;\r
+\r
+      INS_Goto_CodeRange( def->range, def->start );\r
+\r
+      CUR.step_ins = FALSE;\r
+    }\r
+    return;\r
+\r
+  Fail:\r
+    CUR.error = TT_Err_Invalid_Reference;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* IDEF[]:       Instruction DEFinition                                  */\r
+  /* Opcode range: 0x89                                                    */\r
+  /* Stack:        Eint8 -->                                               */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_IDEF( INS_ARG )\r
+  {\r
+    TT_DefRecord*  def;\r
+    TT_DefRecord*  limit;\r
+\r
+\r
+    /*  First of all, look for the same function in our table */\r
+\r
+    def   = CUR.IDefs;\r
+    limit = def + CUR.numIDefs;\r
+\r
+    for ( ; def < limit; def++ )\r
+      if ( def->opc == (FT_ULong)args[0] )\r
+        break;\r
+\r
+    if ( def == limit )\r
+    {\r
+      /* check that there is enough room for a new instruction */\r
+      if ( CUR.numIDefs >= CUR.maxIDefs )\r
+      {\r
+        CUR.error = TT_Err_Too_Many_Instruction_Defs;\r
+        return;\r
+      }\r
+      CUR.numIDefs++;\r
+    }\r
+\r
+    def->opc    = args[0];\r
+    def->start  = CUR.IP+1;\r
+    def->range  = CUR.curRange;\r
+    def->active = TRUE;\r
+\r
+    if ( (FT_ULong)args[0] > CUR.maxIns )\r
+      CUR.maxIns = args[0];\r
+\r
+    /* Now skip the whole function definition. */\r
+    /* We don't allow nested IDEFs & FDEFs.    */\r
+\r
+    while ( SKIP_Code() == SUCCESS )\r
+    {\r
+      switch ( CUR.opcode )\r
+      {\r
+      case 0x89:   /* IDEF */\r
+      case 0x2C:   /* FDEF */\r
+        CUR.error = TT_Err_Nested_DEFS;\r
+        return;\r
+      case 0x2D:   /* ENDF */\r
+        return;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* PUSHING DATA ONTO THE INTERPRETER STACK                               */\r
+  /*                                                                       */\r
+  /*   Instructions appear in the specification's order.                   */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* NPUSHB[]:     PUSH N Bytes                                            */\r
+  /* Opcode range: 0x40                                                    */\r
+  /* Stack:        --> uint32...                                           */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_NPUSHB( INS_ARG )\r
+  {\r
+    FT_UShort  L, K;\r
+\r
+\r
+    L = (FT_UShort)CUR.code[CUR.IP + 1];\r
+\r
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )\r
+    {\r
+      CUR.error = TT_Err_Stack_Overflow;\r
+      return;\r
+    }\r
+\r
+    for ( K = 1; K <= L; K++ )\r
+      args[K - 1] = CUR.code[CUR.IP + K + 1];\r
+\r
+    CUR.new_top += L;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* NPUSHW[]:     PUSH N Words                                            */\r
+  /* Opcode range: 0x41                                                    */\r
+  /* Stack:        --> int32...                                            */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_NPUSHW( INS_ARG )\r
+  {\r
+    FT_UShort  L, K;\r
+\r
+\r
+    L = (FT_UShort)CUR.code[CUR.IP + 1];\r
+\r
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )\r
+    {\r
+      CUR.error = TT_Err_Stack_Overflow;\r
+      return;\r
+    }\r
+\r
+    CUR.IP += 2;\r
+\r
+    for ( K = 0; K < L; K++ )\r
+      args[K] = GET_ShortIns();\r
+\r
+    CUR.step_ins = FALSE;\r
+    CUR.new_top += L;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* PUSHB[abc]:   PUSH Bytes                                              */\r
+  /* Opcode range: 0xB0-0xB7                                               */\r
+  /* Stack:        --> uint32...                                           */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_PUSHB( INS_ARG )\r
+  {\r
+    FT_UShort  L, K;\r
+\r
+\r
+    L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );\r
+\r
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )\r
+    {\r
+      CUR.error = TT_Err_Stack_Overflow;\r
+      return;\r
+    }\r
+\r
+    for ( K = 1; K <= L; K++ )\r
+      args[K - 1] = CUR.code[CUR.IP + K];\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* PUSHW[abc]:   PUSH Words                                              */\r
+  /* Opcode range: 0xB8-0xBF                                               */\r
+  /* Stack:        --> int32...                                            */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_PUSHW( INS_ARG )\r
+  {\r
+    FT_UShort  L, K;\r
+\r
+\r
+    L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );\r
+\r
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )\r
+    {\r
+      CUR.error = TT_Err_Stack_Overflow;\r
+      return;\r
+    }\r
+\r
+    CUR.IP++;\r
+\r
+    for ( K = 0; K < L; K++ )\r
+      args[K] = GET_ShortIns();\r
+\r
+    CUR.step_ins = FALSE;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MANAGING THE GRAPHICS STATE                                           */\r
+  /*                                                                       */\r
+  /*  Instructions appear in the specs' order.                             */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* GC[a]:        Get Coordinate projected onto                           */\r
+  /* Opcode range: 0x46-0x47                                               */\r
+  /* Stack:        uint32 --> f26.6                                        */\r
+  /*                                                                       */\r
+  /* BULLSHIT: Measures from the original glyph must be taken along the    */\r
+  /*           dual projection vector!                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_GC( INS_ARG )\r
+  {\r
+    FT_ULong    L;\r
+    FT_F26Dot6  R;\r
+\r
+\r
+    L = (FT_ULong)args[0];\r
+\r
+    if ( BOUNDS( L, CUR.zp2.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+      {\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+        return;\r
+      }\r
+      else\r
+        R = 0;\r
+    }\r
+    else\r
+    {\r
+      if ( CUR.opcode & 1 )\r
+        R = CUR_fast_dualproj( &CUR.zp2.org[L] );\r
+      else\r
+        R = CUR_fast_project( &CUR.zp2.cur[L] );\r
+    }\r
+\r
+    args[0] = R;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SCFS[]:       Set Coordinate From Stack                               */\r
+  /* Opcode range: 0x48                                                    */\r
+  /* Stack:        f26.6 uint32 -->                                        */\r
+  /*                                                                       */\r
+  /* Formula:                                                              */\r
+  /*                                                                       */\r
+  /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SCFS( INS_ARG )\r
+  {\r
+    FT_Long    K;\r
+    FT_UShort  L;\r
+\r
+\r
+    L = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( L, CUR.zp2.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    K = CUR_fast_project( &CUR.zp2.cur[L] );\r
+\r
+    CUR_Func_move( &CUR.zp2, L, args[1] - K );\r
+\r
+    /* not part of the specs, but here for safety */\r
+\r
+    if ( CUR.GS.gep2 == 0 )\r
+      CUR.zp2.org[L] = CUR.zp2.cur[L];\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MD[a]:        Measure Distance                                        */\r
+  /* Opcode range: 0x49-0x4A                                               */\r
+  /* Stack:        uint32 uint32 --> f26.6                                 */\r
+  /*                                                                       */\r
+  /* BULLSHIT: Measure taken in the original glyph must be along the dual  */\r
+  /*           projection vector.                                          */\r
+  /*                                                                       */\r
+  /* Second BULLSHIT: Flag attributes are inverted!                        */\r
+  /*                  0 => measure distance in original outline            */\r
+  /*                  1 => measure distance in grid-fitted outline         */\r
+  /*                                                                       */\r
+  /* Third one: `zp0 - zp1', and not `zp2 - zp1!                           */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MD( INS_ARG )\r
+  {\r
+    FT_UShort   K, L;\r
+    FT_F26Dot6  D;\r
+\r
+\r
+    K = (FT_UShort)args[1];\r
+    L = (FT_UShort)args[0];\r
+\r
+    if( BOUNDS( L, CUR.zp0.n_points ) ||\r
+        BOUNDS( K, CUR.zp1.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+      {\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+        return;\r
+      }\r
+      D = 0;\r
+    }\r
+    else\r
+    {\r
+      if ( CUR.opcode & 1 )\r
+        D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );\r
+      else\r
+        D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );\r
+    }\r
+\r
+    args[0] = D;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SDPVTL[a]:    Set Dual PVector to Line                                */\r
+  /* Opcode range: 0x86-0x87                                               */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SDPVTL( INS_ARG )\r
+  {\r
+    FT_Long    A, B, C;\r
+    FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */\r
+\r
+\r
+    p1 = (FT_UShort)args[1];\r
+    p2 = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( p2, CUR.zp1.n_points ) ||\r
+         BOUNDS( p1, CUR.zp2.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    {\r
+      FT_Vector* v1 = CUR.zp1.org + p2;\r
+      FT_Vector* v2 = CUR.zp2.org + p1;\r
+\r
+\r
+      A = v1->x - v2->x;\r
+      B = v1->y - v2->y;\r
+    }\r
+\r
+    if ( ( CUR.opcode & 1 ) != 0 )\r
+    {\r
+      C =  B;   /* counter clockwise rotation */\r
+      B =  A;\r
+      A = -C;\r
+    }\r
+\r
+    NORMalize( A, B, &CUR.GS.dualVector );\r
+\r
+    {\r
+      FT_Vector*  v1 = CUR.zp1.cur + p2;\r
+      FT_Vector*  v2 = CUR.zp2.cur + p1;\r
+\r
+\r
+      A = v1->x - v2->x;\r
+      B = v1->y - v2->y;\r
+    }\r
+\r
+    if ( ( CUR.opcode & 1 ) != 0 )\r
+    {\r
+      C =  B;   /* counter clockwise rotation */\r
+      B =  A;\r
+      A = -C;\r
+    }\r
+\r
+    NORMalize( A, B, &CUR.GS.projVector );\r
+\r
+    GUESS_VECTOR( freeVector );\r
+\r
+    COMPUTE_Funcs();\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SZP0[]:       Set Zone Pointer 0                                      */\r
+  /* Opcode range: 0x13                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SZP0( INS_ARG )\r
+  {\r
+    switch ( (FT_Int)args[0] )\r
+    {\r
+    case 0:\r
+      CUR.zp0 = CUR.twilight;\r
+      break;\r
+\r
+    case 1:\r
+      CUR.zp0 = CUR.pts;\r
+      break;\r
+\r
+    default:\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    CUR.GS.gep0 = (FT_UShort)args[0];\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SZP1[]:       Set Zone Pointer 1                                      */\r
+  /* Opcode range: 0x14                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SZP1( INS_ARG )\r
+  {\r
+    switch ( (FT_Int)args[0] )\r
+    {\r
+    case 0:\r
+      CUR.zp1 = CUR.twilight;\r
+      break;\r
+\r
+    case 1:\r
+      CUR.zp1 = CUR.pts;\r
+      break;\r
+\r
+    default:\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    CUR.GS.gep1 = (FT_UShort)args[0];\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SZP2[]:       Set Zone Pointer 2                                      */\r
+  /* Opcode range: 0x15                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SZP2( INS_ARG )\r
+  {\r
+    switch ( (FT_Int)args[0] )\r
+    {\r
+    case 0:\r
+      CUR.zp2 = CUR.twilight;\r
+      break;\r
+\r
+    case 1:\r
+      CUR.zp2 = CUR.pts;\r
+      break;\r
+\r
+    default:\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    CUR.GS.gep2 = (FT_UShort)args[0];\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SZPS[]:       Set Zone PointerS                                       */\r
+  /* Opcode range: 0x16                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SZPS( INS_ARG )\r
+  {\r
+    switch ( (FT_Int)args[0] )\r
+    {\r
+    case 0:\r
+      CUR.zp0 = CUR.twilight;\r
+      break;\r
+\r
+    case 1:\r
+      CUR.zp0 = CUR.pts;\r
+      break;\r
+\r
+    default:\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    CUR.zp1 = CUR.zp0;\r
+    CUR.zp2 = CUR.zp0;\r
+\r
+    CUR.GS.gep0 = (FT_UShort)args[0];\r
+    CUR.GS.gep1 = (FT_UShort)args[0];\r
+    CUR.GS.gep2 = (FT_UShort)args[0];\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* INSTCTRL[]:   INSTruction ConTRoL                                     */\r
+  /* Opcode range: 0x8e                                                    */\r
+  /* Stack:        int32 int32 -->                                         */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_INSTCTRL( INS_ARG )\r
+  {\r
+    FT_Long  K, L;\r
+\r
+\r
+    K = args[1];\r
+    L = args[0];\r
+\r
+    if ( K < 1 || K > 2 )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    if ( L != 0 )\r
+        L = K;\r
+\r
+    CUR.GS.instruct_control = FT_BOOL(\r
+      ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SCANCTRL[]:   SCAN ConTRoL                                            */\r
+  /* Opcode range: 0x85                                                    */\r
+  /* Stack:        uint32? -->                                             */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SCANCTRL( INS_ARG )\r
+  {\r
+    FT_Int  A;\r
+\r
+\r
+    /* Get Threshold */\r
+    A = (FT_Int)( args[0] & 0xFF );\r
+\r
+    if ( A == 0xFF )\r
+    {\r
+      CUR.GS.scan_control = TRUE;\r
+      return;\r
+    }\r
+    else if ( A == 0 )\r
+    {\r
+      CUR.GS.scan_control = FALSE;\r
+      return;\r
+    }\r
+\r
+    A *= 64;\r
+\r
+#if 0\r
+    if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )\r
+      CUR.GS.scan_control = TRUE;\r
+#endif\r
+\r
+    if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )\r
+      CUR.GS.scan_control = TRUE;\r
+\r
+    if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )\r
+      CUR.GS.scan_control = TRUE;\r
+\r
+#if 0\r
+    if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )\r
+      CUR.GS.scan_control = FALSE;\r
+#endif\r
+\r
+    if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )\r
+      CUR.GS.scan_control = FALSE;\r
+\r
+    if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )\r
+      CUR.GS.scan_control = FALSE;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SCANTYPE[]:   SCAN TYPE                                               */\r
+  /* Opcode range: 0x8D                                                    */\r
+  /* Stack:        uint32? -->                                             */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SCANTYPE( INS_ARG )\r
+  {\r
+    /* for compatibility with future enhancements, */\r
+    /* we must ignore new modes                    */\r
+\r
+    if ( args[0] >= 0 && args[0] <= 5 )\r
+    {\r
+      if ( args[0] == 3 )\r
+        args[0] = 2;\r
+\r
+      CUR.GS.scan_type = (FT_Int)args[0];\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MANAGING OUTLINES                                                     */\r
+  /*                                                                       */\r
+  /*   Instructions appear in the specification's order.                   */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* FLIPPT[]:     FLIP PoinT                                              */\r
+  /* Opcode range: 0x80                                                    */\r
+  /* Stack:        uint32... -->                                           */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_FLIPPT( INS_ARG )\r
+  {\r
+    FT_UShort  point;\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    if ( CUR.top < CUR.GS.loop )\r
+    {\r
+      CUR.error = TT_Err_Too_Few_Arguments;\r
+      return;\r
+    }\r
+\r
+    while ( CUR.GS.loop > 0 )\r
+    {\r
+      CUR.args--;\r
+\r
+      point = (FT_UShort)CUR.stack[CUR.args];\r
+\r
+      if ( BOUNDS( point, CUR.pts.n_points ) )\r
+      {\r
+        if ( CUR.pedantic_hinting )\r
+        {\r
+          CUR.error = TT_Err_Invalid_Reference;\r
+          return;\r
+        }\r
+      }\r
+      else\r
+        CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;\r
+\r
+      CUR.GS.loop--;\r
+    }\r
+\r
+    CUR.GS.loop = 1;\r
+    CUR.new_top = CUR.args;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* FLIPRGON[]:   FLIP RanGe ON                                           */\r
+  /* Opcode range: 0x81                                                    */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_FLIPRGON( INS_ARG )\r
+  {\r
+    FT_UShort  I, K, L;\r
+\r
+\r
+    K = (FT_UShort)args[1];\r
+    L = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( K, CUR.pts.n_points ) ||\r
+         BOUNDS( L, CUR.pts.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    for ( I = L; I <= K; I++ )\r
+      CUR.pts.tags[I] |= FT_CURVE_TAG_ON;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* FLIPRGOFF:    FLIP RanGe OFF                                          */\r
+  /* Opcode range: 0x82                                                    */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_FLIPRGOFF( INS_ARG )\r
+  {\r
+    FT_UShort  I, K, L;\r
+\r
+\r
+    K = (FT_UShort)args[1];\r
+    L = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( K, CUR.pts.n_points ) ||\r
+         BOUNDS( L, CUR.pts.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    for ( I = L; I <= K; I++ )\r
+      CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;\r
+  }\r
+\r
+\r
+  static FT_Bool\r
+  Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*   x,\r
+                                       FT_F26Dot6*   y,\r
+                                       TT_GlyphZone  zone,\r
+                                       FT_UShort*    refp )\r
+  {\r
+    TT_GlyphZoneRec  zp;\r
+    FT_UShort        p;\r
+    FT_F26Dot6       d;\r
+\r
+\r
+    if ( CUR.opcode & 1 )\r
+    {\r
+      zp = CUR.zp0;\r
+      p  = CUR.GS.rp1;\r
+    }\r
+    else\r
+    {\r
+      zp = CUR.zp1;\r
+      p  = CUR.GS.rp2;\r
+    }\r
+\r
+    if ( BOUNDS( p, zp.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      *refp = 0;\r
+      return FAILURE;\r
+    }\r
+\r
+    *zone = zp;\r
+    *refp = p;\r
+\r
+    d = CUR_Func_project( zp.cur + p, zp.org + p );\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    if ( CUR.face->unpatented_hinting )\r
+    {\r
+      if ( CUR.GS.both_x_axis )\r
+      {\r
+        *x = d;\r
+        *y = 0;\r
+      }\r
+      else\r
+      {\r
+        *x = 0;\r
+        *y = d;\r
+      }\r
+    }\r
+    else\r
+#endif\r
+    {\r
+      *x = TT_MULDIV( d,\r
+                      (FT_Long)CUR.GS.freeVector.x * 0x10000L,\r
+                      CUR.F_dot_P );\r
+      *y = TT_MULDIV( d,\r
+                      (FT_Long)CUR.GS.freeVector.y * 0x10000L,\r
+                      CUR.F_dot_P );\r
+    }\r
+\r
+    return SUCCESS;\r
+  }\r
+\r
+\r
+  static void\r
+  Move_Zp2_Point( EXEC_OP_ FT_UShort   point,\r
+                           FT_F26Dot6  dx,\r
+                           FT_F26Dot6  dy,\r
+                           FT_Bool     touch )\r
+  {\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    if ( CUR.face->unpatented_hinting )\r
+    {\r
+      if ( CUR.GS.both_x_axis )\r
+      {\r
+        CUR.zp2.cur[point].x += dx;\r
+        if ( touch )\r
+          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;\r
+      }\r
+      else\r
+      {\r
+        CUR.zp2.cur[point].y += dy;\r
+        if ( touch )\r
+          CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;\r
+      }\r
+      return;\r
+    }\r
+#endif\r
+\r
+    if ( CUR.GS.freeVector.x != 0 )\r
+    {\r
+      CUR.zp2.cur[point].x += dx;\r
+      if ( touch )\r
+        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;\r
+    }\r
+\r
+    if ( CUR.GS.freeVector.y != 0 )\r
+    {\r
+      CUR.zp2.cur[point].y += dy;\r
+      if ( touch )\r
+        CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SHP[a]:       SHift Point by the last point                           */\r
+  /* Opcode range: 0x32-0x33                                               */\r
+  /* Stack:        uint32... -->                                           */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SHP( INS_ARG )\r
+  {\r
+    TT_GlyphZoneRec  zp;\r
+    FT_UShort        refp;\r
+\r
+    FT_F26Dot6       dx,\r
+                     dy;\r
+    FT_UShort        point;\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    if ( CUR.top < CUR.GS.loop )\r
+    {\r
+      CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )\r
+      return;\r
+\r
+    while ( CUR.GS.loop > 0 )\r
+    {\r
+      CUR.args--;\r
+      point = (FT_UShort)CUR.stack[CUR.args];\r
+\r
+      if ( BOUNDS( point, CUR.zp2.n_points ) )\r
+      {\r
+        if ( CUR.pedantic_hinting )\r
+        {\r
+          CUR.error = TT_Err_Invalid_Reference;\r
+          return;\r
+        }\r
+      }\r
+      else\r
+        /* XXX: UNDOCUMENTED! SHP touches the points */\r
+        MOVE_Zp2_Point( point, dx, dy, TRUE );\r
+\r
+      CUR.GS.loop--;\r
+    }\r
+\r
+    CUR.GS.loop = 1;\r
+    CUR.new_top = CUR.args;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SHC[a]:       SHift Contour                                           */\r
+  /* Opcode range: 0x34-35                                                 */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SHC( INS_ARG )\r
+  {\r
+    TT_GlyphZoneRec zp;\r
+    FT_UShort       refp;\r
+    FT_F26Dot6      dx,\r
+                    dy;\r
+\r
+    FT_Short        contour;\r
+    FT_UShort       first_point, last_point, i;\r
+\r
+\r
+    contour = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( contour, CUR.pts.n_contours ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )\r
+      return;\r
+\r
+    if ( contour == 0 )\r
+      first_point = 0;\r
+    else\r
+      first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -\r
+                                 CUR.pts.first_point );\r
+\r
+    last_point = (FT_UShort)( CUR.pts.contours[contour] -\r
+                              CUR.pts.first_point );\r
+\r
+    /* XXX: this is probably wrong... at least it prevents memory */\r
+    /*      corruption when zp2 is the twilight zone              */\r
+    if ( last_point > CUR.zp2.n_points )\r
+    {\r
+      if ( CUR.zp2.n_points > 0 )\r
+        last_point = (FT_UShort)(CUR.zp2.n_points - 1);\r
+      else\r
+        last_point = 0;\r
+    }\r
+\r
+    /* XXX: UNDOCUMENTED! SHC touches the points */\r
+    for ( i = first_point; i <= last_point; i++ )\r
+    {\r
+      if ( zp.cur != CUR.zp2.cur || refp != i )\r
+        MOVE_Zp2_Point( i, dx, dy, TRUE );\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SHZ[a]:       SHift Zone                                              */\r
+  /* Opcode range: 0x36-37                                                 */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SHZ( INS_ARG )\r
+  {\r
+    TT_GlyphZoneRec zp;\r
+    FT_UShort       refp;\r
+    FT_F26Dot6      dx,\r
+                    dy;\r
+\r
+    FT_UShort       last_point, i;\r
+\r
+\r
+    if ( BOUNDS( args[0], 2 ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )\r
+      return;\r
+\r
+    /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points.  */\r
+    /*      Twilight zone has no contours, so use `n_points'.   */\r
+    /*      Normal zone's `n_points' includes phantoms, so must */\r
+    /*      use end of last contour.                            */\r
+    if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )\r
+      last_point = (FT_UShort)( CUR.zp2.n_points - 1 );\r
+    else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )\r
+      last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );\r
+    else\r
+      last_point = 0;\r
+\r
+    /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */\r
+    for ( i = 0; i <= last_point; i++ )\r
+    {\r
+      if ( zp.cur != CUR.zp2.cur || refp != i )\r
+        MOVE_Zp2_Point( i, dx, dy, FALSE );\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* SHPIX[]:      SHift points by a PIXel amount                          */\r
+  /* Opcode range: 0x38                                                    */\r
+  /* Stack:        f26.6 uint32... -->                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_SHPIX( INS_ARG )\r
+  {\r
+    FT_F26Dot6  dx, dy;\r
+    FT_UShort   point;\r
+\r
+\r
+    if ( CUR.top < CUR.GS.loop + 1 )\r
+    {\r
+      CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    if ( CUR.face->unpatented_hinting )\r
+    {\r
+      if ( CUR.GS.both_x_axis )\r
+      {\r
+        dx = TT_MulFix14( args[0], 0x4000 );\r
+        dy = 0;\r
+      }\r
+      else\r
+      {\r
+        dx = 0;\r
+        dy = TT_MulFix14( args[0], 0x4000 );\r
+      }\r
+    }\r
+    else\r
+#endif\r
+    {\r
+      dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );\r
+      dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );\r
+    }\r
+\r
+    while ( CUR.GS.loop > 0 )\r
+    {\r
+      CUR.args--;\r
+\r
+      point = (FT_UShort)CUR.stack[CUR.args];\r
+\r
+      if ( BOUNDS( point, CUR.zp2.n_points ) )\r
+      {\r
+        if ( CUR.pedantic_hinting )\r
+        {\r
+          CUR.error = TT_Err_Invalid_Reference;\r
+          return;\r
+        }\r
+      }\r
+      else\r
+        MOVE_Zp2_Point( point, dx, dy, TRUE );\r
+\r
+      CUR.GS.loop--;\r
+    }\r
+\r
+    CUR.GS.loop = 1;\r
+    CUR.new_top = CUR.args;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MSIRP[a]:     Move Stack Indirect Relative Position                   */\r
+  /* Opcode range: 0x3A-0x3B                                               */\r
+  /* Stack:        f26.6 uint32 -->                                        */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MSIRP( INS_ARG )\r
+  {\r
+    FT_UShort   point;\r
+    FT_F26Dot6  distance;\r
+\r
+\r
+    point = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||\r
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    /* XXX: UNDOCUMENTED! behaviour */\r
+    if ( CUR.GS.gep1 == 0 )   /* if the point that is to be moved */\r
+                              /* is in twilight zone              */\r
+    {\r
+      CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];\r
+      CUR_Func_move_orig( &CUR.zp1, point, args[1] );\r
+      CUR.zp1.cur[point] = CUR.zp1.org[point];\r
+    }\r
+\r
+    distance = CUR_Func_project( CUR.zp1.cur + point,\r
+                                 CUR.zp0.cur + CUR.GS.rp0 );\r
+\r
+    CUR_Func_move( &CUR.zp1, point, args[1] - distance );\r
+\r
+    CUR.GS.rp1 = CUR.GS.rp0;\r
+    CUR.GS.rp2 = point;\r
+\r
+    if ( ( CUR.opcode & 1 ) != 0 )\r
+      CUR.GS.rp0 = point;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MDAP[a]:      Move Direct Absolute Point                              */\r
+  /* Opcode range: 0x2E-0x2F                                               */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MDAP( INS_ARG )\r
+  {\r
+    FT_UShort   point;\r
+    FT_F26Dot6  cur_dist,\r
+                distance;\r
+\r
+\r
+    point = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( point, CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    /* XXX: Is there some undocumented feature while in the */\r
+    /*      twilight zone? ?                                */\r
+    if ( ( CUR.opcode & 1 ) != 0 )\r
+    {\r
+      cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );\r
+      distance = CUR_Func_round( cur_dist,\r
+                                 CUR.tt_metrics.compensations[0] ) - cur_dist;\r
+    }\r
+    else\r
+      distance = 0;\r
+\r
+    CUR_Func_move( &CUR.zp0, point, distance );\r
+\r
+    CUR.GS.rp0 = point;\r
+    CUR.GS.rp1 = point;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MIAP[a]:      Move Indirect Absolute Point                            */\r
+  /* Opcode range: 0x3E-0x3F                                               */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MIAP( INS_ARG )\r
+  {\r
+    FT_ULong    cvtEntry;\r
+    FT_UShort   point;\r
+    FT_F26Dot6  distance,\r
+                org_dist;\r
+\r
+\r
+    cvtEntry = (FT_ULong)args[1];\r
+    point    = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( point,    CUR.zp0.n_points ) ||\r
+         BOUNDS( cvtEntry, CUR.cvtSize )      )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    /* XXX: UNDOCUMENTED!                                */\r
+    /*                                                   */\r
+    /* The behaviour of an MIAP instruction is quite     */\r
+    /* different when used in the twilight zone.         */\r
+    /*                                                   */\r
+    /* First, no control value cut-in test is performed  */\r
+    /* as it would fail anyway.  Second, the original    */\r
+    /* point, i.e. (org_x,org_y) of zp0.point, is set    */\r
+    /* to the absolute, unrounded distance found in      */\r
+    /* the CVT.                                          */\r
+    /*                                                   */\r
+    /* This is used in the CVT programs of the Microsoft */\r
+    /* fonts Arial, Times, etc., in order to re-adjust   */\r
+    /* some key font heights.  It allows the use of the  */\r
+    /* IP instruction in the twilight zone, which        */\r
+    /* otherwise would be `illegal' according to the     */\r
+    /* specification.                                    */\r
+    /*                                                   */\r
+    /* We implement it with a special sequence for the   */\r
+    /* twilight zone.  This is a bad hack, but it seems  */\r
+    /* to work.                                          */\r
+\r
+    distance = CUR_Func_read_cvt( cvtEntry );\r
+\r
+    if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */\r
+    {\r
+      CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );\r
+      CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ),\r
+      CUR.zp0.cur[point]   = CUR.zp0.org[point];\r
+    }\r
+\r
+    org_dist = CUR_fast_project( &CUR.zp0.cur[point] );\r
+\r
+    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */\r
+    {\r
+      if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )\r
+        distance = org_dist;\r
+\r
+      distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );\r
+    }\r
+\r
+    CUR_Func_move( &CUR.zp0, point, distance - org_dist );\r
+\r
+    CUR.GS.rp0 = point;\r
+    CUR.GS.rp1 = point;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MDRP[abcde]:  Move Direct Relative Point                              */\r
+  /* Opcode range: 0xC0-0xDF                                               */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MDRP( INS_ARG )\r
+  {\r
+    FT_UShort   point;\r
+    FT_F26Dot6  org_dist, distance;\r
+\r
+\r
+    point = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||\r
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    /* XXX: Is there some undocumented feature while in the */\r
+    /*      twilight zone?                                  */\r
+\r
+    /* XXX: UNDOCUMENTED: twilight zone special case */\r
+\r
+    if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )\r
+    {\r
+      FT_Vector*  vec1 = &CUR.zp1.org[point];\r
+      FT_Vector*  vec2 = &CUR.zp0.org[CUR.GS.rp0];\r
+\r
+\r
+      org_dist = CUR_Func_dualproj( vec1, vec2 );\r
+    }\r
+    else\r
+    {\r
+      FT_Vector*  vec1 = &CUR.zp1.orus[point];\r
+      FT_Vector*  vec2 = &CUR.zp0.orus[CUR.GS.rp0];\r
+\r
+\r
+      if ( CUR.metrics.x_scale == CUR.metrics.y_scale )\r
+      {\r
+        /* this should be faster */\r
+        org_dist = CUR_Func_dualproj( vec1, vec2 );\r
+        org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );\r
+      }\r
+      else\r
+      {\r
+        FT_Vector  vec;\r
+\r
+\r
+        vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );\r
+        vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );\r
+\r
+        org_dist = CUR_fast_dualproj( &vec );\r
+      }\r
+    }\r
+\r
+    /* single width cut-in test */\r
+\r
+    if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <\r
+         CUR.GS.single_width_cutin )\r
+    {\r
+      if ( org_dist >= 0 )\r
+        org_dist = CUR.GS.single_width_value;\r
+      else\r
+        org_dist = -CUR.GS.single_width_value;\r
+    }\r
+\r
+    /* round flag */\r
+\r
+    if ( ( CUR.opcode & 4 ) != 0 )\r
+      distance = CUR_Func_round(\r
+                   org_dist,\r
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );\r
+    else\r
+      distance = ROUND_None(\r
+                   org_dist,\r
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );\r
+\r
+    /* minimum distance flag */\r
+\r
+    if ( ( CUR.opcode & 8 ) != 0 )\r
+    {\r
+      if ( org_dist >= 0 )\r
+      {\r
+        if ( distance < CUR.GS.minimum_distance )\r
+          distance = CUR.GS.minimum_distance;\r
+      }\r
+      else\r
+      {\r
+        if ( distance > -CUR.GS.minimum_distance )\r
+          distance = -CUR.GS.minimum_distance;\r
+      }\r
+    }\r
+\r
+    /* now move the point */\r
+\r
+    org_dist = CUR_Func_project( CUR.zp1.cur + point,\r
+                                 CUR.zp0.cur + CUR.GS.rp0 );\r
+\r
+    CUR_Func_move( &CUR.zp1, point, distance - org_dist );\r
+\r
+    CUR.GS.rp1 = CUR.GS.rp0;\r
+    CUR.GS.rp2 = point;\r
+\r
+    if ( ( CUR.opcode & 16 ) != 0 )\r
+      CUR.GS.rp0 = point;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MIRP[abcde]:  Move Indirect Relative Point                            */\r
+  /* Opcode range: 0xE0-0xFF                                               */\r
+  /* Stack:        int32? uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_MIRP( INS_ARG )\r
+  {\r
+    FT_UShort   point;\r
+    FT_ULong    cvtEntry;\r
+\r
+    FT_F26Dot6  cvt_dist,\r
+                distance,\r
+                cur_dist,\r
+                org_dist;\r
+\r
+\r
+    point    = (FT_UShort)args[0];\r
+    cvtEntry = (FT_ULong)( args[1] + 1 );\r
+\r
+    /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */\r
+\r
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||\r
+         BOUNDS( cvtEntry,   CUR.cvtSize + 1 )  ||\r
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    if ( !cvtEntry )\r
+      cvt_dist = 0;\r
+    else\r
+      cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );\r
+\r
+    /* single width test */\r
+\r
+    if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <\r
+         CUR.GS.single_width_cutin )\r
+    {\r
+      if ( cvt_dist >= 0 )\r
+        cvt_dist =  CUR.GS.single_width_value;\r
+      else\r
+        cvt_dist = -CUR.GS.single_width_value;\r
+    }\r
+\r
+    /* XXX: UNDOCUMENTED! -- twilight zone */\r
+\r
+    if ( CUR.GS.gep1 == 0 )\r
+    {\r
+      CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +\r
+                             TT_MulFix14( cvt_dist, CUR.GS.freeVector.x );\r
+\r
+      CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +\r
+                             TT_MulFix14( cvt_dist, CUR.GS.freeVector.y );\r
+\r
+      CUR.zp1.cur[point] = CUR.zp0.cur[point];\r
+    }\r
+\r
+    org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],\r
+                                  &CUR.zp0.org[CUR.GS.rp0] );\r
+    cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],\r
+                                  &CUR.zp0.cur[CUR.GS.rp0] );\r
+\r
+    /* auto-flip test */\r
+\r
+    if ( CUR.GS.auto_flip )\r
+    {\r
+      if ( ( org_dist ^ cvt_dist ) < 0 )\r
+        cvt_dist = -cvt_dist;\r
+    }\r
+\r
+    /* control value cutin and round */\r
+\r
+    if ( ( CUR.opcode & 4 ) != 0 )\r
+    {\r
+      /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */\r
+      /*      refer to the same zone.                                  */\r
+\r
+      if ( CUR.GS.gep0 == CUR.GS.gep1 )\r
+        if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )\r
+          cvt_dist = org_dist;\r
+\r
+      distance = CUR_Func_round(\r
+                   cvt_dist,\r
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );\r
+    }\r
+    else\r
+      distance = ROUND_None(\r
+                   cvt_dist,\r
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );\r
+\r
+    /* minimum distance test */\r
+\r
+    if ( ( CUR.opcode & 8 ) != 0 )\r
+    {\r
+      if ( org_dist >= 0 )\r
+      {\r
+        if ( distance < CUR.GS.minimum_distance )\r
+          distance = CUR.GS.minimum_distance;\r
+      }\r
+      else\r
+      {\r
+        if ( distance > -CUR.GS.minimum_distance )\r
+          distance = -CUR.GS.minimum_distance;\r
+      }\r
+    }\r
+\r
+    CUR_Func_move( &CUR.zp1, point, distance - cur_dist );\r
+\r
+    CUR.GS.rp1 = CUR.GS.rp0;\r
+\r
+    if ( ( CUR.opcode & 16 ) != 0 )\r
+      CUR.GS.rp0 = point;\r
+\r
+    /* XXX: UNDOCUMENTED! */\r
+    CUR.GS.rp2 = point;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ALIGNRP[]:    ALIGN Relative Point                                    */\r
+  /* Opcode range: 0x3C                                                    */\r
+  /* Stack:        uint32 uint32... -->                                    */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ALIGNRP( INS_ARG )\r
+  {\r
+    FT_UShort   point;\r
+    FT_F26Dot6  distance;\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    if ( CUR.top < CUR.GS.loop ||\r
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    while ( CUR.GS.loop > 0 )\r
+    {\r
+      CUR.args--;\r
+\r
+      point = (FT_UShort)CUR.stack[CUR.args];\r
+\r
+      if ( BOUNDS( point, CUR.zp1.n_points ) )\r
+      {\r
+        if ( CUR.pedantic_hinting )\r
+        {\r
+          CUR.error = TT_Err_Invalid_Reference;\r
+          return;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        distance = CUR_Func_project( CUR.zp1.cur + point,\r
+                                     CUR.zp0.cur + CUR.GS.rp0 );\r
+\r
+        CUR_Func_move( &CUR.zp1, point, -distance );\r
+      }\r
+\r
+      CUR.GS.loop--;\r
+    }\r
+\r
+    CUR.GS.loop = 1;\r
+    CUR.new_top = CUR.args;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ISECT[]:      moves point to InterSECTion                             */\r
+  /* Opcode range: 0x0F                                                    */\r
+  /* Stack:        5 * uint32 -->                                          */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ISECT( INS_ARG )\r
+  {\r
+    FT_UShort   point,\r
+                a0, a1,\r
+                b0, b1;\r
+\r
+    FT_F26Dot6  discriminant;\r
+\r
+    FT_F26Dot6  dx,  dy,\r
+                dax, day,\r
+                dbx, dby;\r
+\r
+    FT_F26Dot6  val;\r
+\r
+    FT_Vector   R;\r
+\r
+\r
+    point = (FT_UShort)args[0];\r
+\r
+    a0 = (FT_UShort)args[1];\r
+    a1 = (FT_UShort)args[2];\r
+    b0 = (FT_UShort)args[3];\r
+    b1 = (FT_UShort)args[4];\r
+\r
+    if ( BOUNDS( b0, CUR.zp0.n_points )  ||\r
+         BOUNDS( b1, CUR.zp0.n_points )  ||\r
+         BOUNDS( a0, CUR.zp1.n_points )  ||\r
+         BOUNDS( a1, CUR.zp1.n_points )  ||\r
+         BOUNDS( point, CUR.zp2.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;\r
+    dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;\r
+\r
+    dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;\r
+    day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;\r
+\r
+    dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;\r
+    dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;\r
+\r
+    CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;\r
+\r
+    discriminant = TT_MULDIV( dax, -dby, 0x40 ) +\r
+                   TT_MULDIV( day, dbx, 0x40 );\r
+\r
+    if ( FT_ABS( discriminant ) >= 0x40 )\r
+    {\r
+      val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );\r
+\r
+      R.x = TT_MULDIV( val, dax, discriminant );\r
+      R.y = TT_MULDIV( val, day, discriminant );\r
+\r
+      CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;\r
+      CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;\r
+    }\r
+    else\r
+    {\r
+      /* else, take the middle of the middles of A and B */\r
+\r
+      CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +\r
+                               CUR.zp1.cur[a1].x +\r
+                               CUR.zp0.cur[b0].x +\r
+                               CUR.zp0.cur[b1].x ) / 4;\r
+      CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +\r
+                               CUR.zp1.cur[a1].y +\r
+                               CUR.zp0.cur[b0].y +\r
+                               CUR.zp0.cur[b1].y ) / 4;\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* ALIGNPTS[]:   ALIGN PoinTS                                            */\r
+  /* Opcode range: 0x27                                                    */\r
+  /* Stack:        uint32 uint32 -->                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_ALIGNPTS( INS_ARG )\r
+  {\r
+    FT_UShort   p1, p2;\r
+    FT_F26Dot6  distance;\r
+\r
+\r
+    p1 = (FT_UShort)args[0];\r
+    p2 = (FT_UShort)args[1];\r
+\r
+    if ( BOUNDS( args[0], CUR.zp1.n_points ) ||\r
+         BOUNDS( args[1], CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    distance = CUR_Func_project( CUR.zp0.cur + p2,\r
+                                 CUR.zp1.cur + p1 ) / 2;\r
+\r
+    CUR_Func_move( &CUR.zp1, p1, distance );\r
+    CUR_Func_move( &CUR.zp0, p2, -distance );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* IP[]:         Interpolate Point                                       */\r
+  /* Opcode range: 0x39                                                    */\r
+  /* Stack:        uint32... -->                                           */\r
+  /*                                                                       */\r
+\r
+  /* SOMETIMES, DUMBER CODE IS BETTER CODE */\r
+\r
+  static void\r
+  Ins_IP( INS_ARG )\r
+  {\r
+    FT_F26Dot6  old_range, cur_range;\r
+    FT_Vector*  orus_base;\r
+    FT_Vector*  cur_base;\r
+    FT_Int      twilight;\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    if ( CUR.top < CUR.GS.loop )\r
+    {\r
+      CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    /*\r
+     * We need to deal in a special way with the twilight zone.\r
+     * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),\r
+     * for every n.\r
+     */\r
+    twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;\r
+\r
+    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    if ( twilight )\r
+      orus_base = &CUR.zp0.org[CUR.GS.rp1];\r
+    else\r
+      orus_base = &CUR.zp0.orus[CUR.GS.rp1];\r
+\r
+    cur_base = &CUR.zp0.cur[CUR.GS.rp1];\r
+\r
+    /* XXX: There are some glyphs in some braindead but popular */\r
+    /*      fonts out there (e.g. [aeu]grave in monotype.ttf)   */\r
+    /*      calling IP[] with bad values of rp[12].             */\r
+    /*      Do something sane when this odd thing happens.      */\r
+    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||\r
+         BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )\r
+    {\r
+      old_range = 0;\r
+      cur_range = 0;\r
+    }\r
+    else\r
+    {\r
+      if ( twilight )\r
+        old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],\r
+                                       orus_base );\r
+      else\r
+        old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],\r
+                                       orus_base );\r
+\r
+      cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );\r
+    }\r
+\r
+    for ( ; CUR.GS.loop > 0; --CUR.GS.loop )\r
+    {\r
+      FT_UInt     point = (FT_UInt)CUR.stack[--CUR.args];\r
+      FT_F26Dot6  org_dist, cur_dist, new_dist;\r
+\r
+\r
+      /* check point bounds */\r
+      if ( BOUNDS( point, CUR.zp2.n_points ) )\r
+      {\r
+        if ( CUR.pedantic_hinting )\r
+        {\r
+          CUR.error = TT_Err_Invalid_Reference;\r
+          return;\r
+        }\r
+        continue;\r
+      }\r
+\r
+      if ( twilight )\r
+        org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );\r
+      else\r
+        org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );\r
+\r
+      cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );\r
+      new_dist = ( old_range != 0 )\r
+                   ? TT_MULDIV( org_dist, cur_range, old_range )\r
+                   : cur_dist;\r
+\r
+      CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );\r
+    }\r
+    CUR.GS.loop = 1;\r
+    CUR.new_top = CUR.args;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* UTP[a]:       UnTouch Point                                           */\r
+  /* Opcode range: 0x29                                                    */\r
+  /* Stack:        uint32 -->                                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_UTP( INS_ARG )\r
+  {\r
+    FT_UShort  point;\r
+    FT_Byte    mask;\r
+\r
+\r
+    point = (FT_UShort)args[0];\r
+\r
+    if ( BOUNDS( point, CUR.zp0.n_points ) )\r
+    {\r
+      if ( CUR.pedantic_hinting )\r
+        CUR.error = TT_Err_Invalid_Reference;\r
+      return;\r
+    }\r
+\r
+    mask = 0xFF;\r
+\r
+    if ( CUR.GS.freeVector.x != 0 )\r
+      mask &= ~FT_CURVE_TAG_TOUCH_X;\r
+\r
+    if ( CUR.GS.freeVector.y != 0 )\r
+      mask &= ~FT_CURVE_TAG_TOUCH_Y;\r
+\r
+    CUR.zp0.tags[point] &= mask;\r
+  }\r
+\r
+\r
+  /* Local variables for Ins_IUP: */\r
+  typedef struct\r
+  {\r
+    FT_Vector*  orgs;   /* original and current coordinate */\r
+    FT_Vector*  curs;   /* arrays                          */\r
+    FT_Vector*  orus;\r
+    FT_UInt     max_points;\r
+\r
+  } IUP_WorkerRec, *IUP_Worker;\r
+\r
+\r
+  static void\r
+  _iup_worker_shift( IUP_Worker  worker,\r
+                     FT_UInt     p1,\r
+                     FT_UInt     p2,\r
+                     FT_UInt     p )\r
+  {\r
+    FT_UInt     i;\r
+    FT_F26Dot6  dx;\r
+\r
+\r
+    dx = worker->curs[p].x - worker->orgs[p].x;\r
+    if ( dx != 0 )\r
+    {\r
+      for ( i = p1; i < p; i++ )\r
+        worker->curs[i].x += dx;\r
+\r
+      for ( i = p + 1; i <= p2; i++ )\r
+        worker->curs[i].x += dx;\r
+    }\r
+  }\r
+\r
+\r
+  static void\r
+  _iup_worker_interpolate( IUP_Worker  worker,\r
+                           FT_UInt     p1,\r
+                           FT_UInt     p2,\r
+                           FT_UInt     ref1,\r
+                           FT_UInt     ref2 )\r
+  {\r
+    FT_UInt     i;\r
+    FT_F26Dot6  orus1, orus2, org1, org2, delta1, delta2;\r
+\r
+\r
+    if ( p1 > p2 )\r
+      return;\r
+\r
+    if ( BOUNDS( ref1, worker->max_points ) ||\r
+         BOUNDS( ref2, worker->max_points ) )\r
+      return;\r
+\r
+    orus1 = worker->orus[ref1].x;\r
+    orus2 = worker->orus[ref2].x;\r
+\r
+    if ( orus1 > orus2 )\r
+    {\r
+      FT_F26Dot6  tmp_o;\r
+      FT_UInt     tmp_r;\r
+\r
+\r
+      tmp_o = orus1;\r
+      orus1 = orus2;\r
+      orus2 = tmp_o;\r
+\r
+      tmp_r = ref1;\r
+      ref1  = ref2;\r
+      ref2  = tmp_r;\r
+    }\r
+\r
+    org1   = worker->orgs[ref1].x;\r
+    org2   = worker->orgs[ref2].x;\r
+    delta1 = worker->curs[ref1].x - org1;\r
+    delta2 = worker->curs[ref2].x - org2;\r
+\r
+    if ( orus1 == orus2 )\r
+    {\r
+      /* simple shift of untouched points */\r
+      for ( i = p1; i <= p2; i++ )\r
+      {\r
+        FT_F26Dot6  x = worker->orgs[i].x;\r
+\r
+\r
+        if ( x <= org1 )\r
+          x += delta1;\r
+        else\r
+          x += delta2;\r
+\r
+        worker->curs[i].x = x;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      FT_Fixed  scale       = 0;\r
+      FT_Bool   scale_valid = 0;\r
+\r
+\r
+      /* interpolation */\r
+      for ( i = p1; i <= p2; i++ )\r
+      {\r
+        FT_F26Dot6  x = worker->orgs[i].x;\r
+\r
+\r
+        if ( x <= org1 )\r
+          x += delta1;\r
+\r
+        else if ( x >= org2 )\r
+          x += delta2;\r
+\r
+        else\r
+        {\r
+          if ( !scale_valid )\r
+          {\r
+            scale_valid = 1;\r
+            scale       = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),\r
+                                     0x10000, orus2 - orus1 );\r
+          }\r
+\r
+          x = ( org1 + delta1 ) +\r
+              TT_MULFIX( worker->orus[i].x - orus1, scale );\r
+        }\r
+        worker->curs[i].x = x;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* IUP[a]:       Interpolate Untouched Points                            */\r
+  /* Opcode range: 0x30-0x31                                               */\r
+  /* Stack:        -->                                                     */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_IUP( INS_ARG )\r
+  {\r
+    IUP_WorkerRec  V;\r
+    FT_Byte        mask;\r
+\r
+    FT_UInt   first_point;   /* first point of contour        */\r
+    FT_UInt   end_point;     /* end point (last+1) of contour */\r
+\r
+    FT_UInt   first_touched; /* first touched point in contour   */\r
+    FT_UInt   cur_touched;   /* current touched point in contour */\r
+\r
+    FT_UInt   point;         /* current point   */\r
+    FT_Short  contour;       /* current contour */\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    /* ignore empty outlines */\r
+    if ( CUR.pts.n_contours == 0 )\r
+      return;\r
+\r
+    if ( CUR.opcode & 1 )\r
+    {\r
+      mask   = FT_CURVE_TAG_TOUCH_X;\r
+      V.orgs = CUR.pts.org;\r
+      V.curs = CUR.pts.cur;\r
+      V.orus = CUR.pts.orus;\r
+    }\r
+    else\r
+    {\r
+      mask   = FT_CURVE_TAG_TOUCH_Y;\r
+      V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );\r
+      V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );\r
+      V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );\r
+    }\r
+    V.max_points = CUR.pts.n_points;\r
+\r
+    contour = 0;\r
+    point   = 0;\r
+\r
+    do\r
+    {\r
+      end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;\r
+      first_point = point;\r
+\r
+      while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )\r
+        point++;\r
+\r
+      if ( point <= end_point )\r
+      {\r
+        first_touched = point;\r
+        cur_touched   = point;\r
+\r
+        point++;\r
+\r
+        while ( point <= end_point )\r
+        {\r
+          if ( ( CUR.pts.tags[point] & mask ) != 0 )\r
+          {\r
+            if ( point > 0 )\r
+              _iup_worker_interpolate( &V,\r
+                                       cur_touched + 1,\r
+                                       point - 1,\r
+                                       cur_touched,\r
+                                       point );\r
+            cur_touched = point;\r
+          }\r
+\r
+          point++;\r
+        }\r
+\r
+        if ( cur_touched == first_touched )\r
+          _iup_worker_shift( &V, first_point, end_point, cur_touched );\r
+        else\r
+        {\r
+          _iup_worker_interpolate( &V,\r
+                                   (FT_UShort)( cur_touched + 1 ),\r
+                                   end_point,\r
+                                   cur_touched,\r
+                                   first_touched );\r
+\r
+          if ( first_touched > 0 )\r
+            _iup_worker_interpolate( &V,\r
+                                     first_point,\r
+                                     first_touched - 1,\r
+                                     cur_touched,\r
+                                     first_touched );\r
+        }\r
+      }\r
+      contour++;\r
+    } while ( contour < CUR.pts.n_contours );\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* DELTAPn[]:    DELTA exceptions P1, P2, P3                             */\r
+  /* Opcode range: 0x5D,0x71,0x72                                          */\r
+  /* Stack:        uint32 (2 * uint32)... -->                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_DELTAP( INS_ARG )\r
+  {\r
+    FT_ULong   k, nump;\r
+    FT_UShort  A;\r
+    FT_ULong   C;\r
+    FT_Long    B;\r
+\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    /* Delta hinting is covered by US Patent 5159668. */\r
+    if ( CUR.face->unpatented_hinting )\r
+    {\r
+      FT_Long  n = args[0] * 2;\r
+\r
+\r
+      if ( CUR.args < n )\r
+      {\r
+        CUR.error = TT_Err_Too_Few_Arguments;\r
+        return;\r
+      }\r
+\r
+      CUR.args -= n;\r
+      CUR.new_top = CUR.args;\r
+      return;\r
+    }\r
+#endif\r
+\r
+    nump = (FT_ULong)args[0];   /* some points theoretically may occur more\r
+                                   than once, thus UShort isn't enough */\r
+\r
+    for ( k = 1; k <= nump; k++ )\r
+    {\r
+      if ( CUR.args < 2 )\r
+      {\r
+        CUR.error = TT_Err_Too_Few_Arguments;\r
+        return;\r
+      }\r
+\r
+      CUR.args -= 2;\r
+\r
+      A = (FT_UShort)CUR.stack[CUR.args + 1];\r
+      B = CUR.stack[CUR.args];\r
+\r
+      /* XXX: Because some popular fonts contain some invalid DeltaP */\r
+      /*      instructions, we simply ignore them when the stacked   */\r
+      /*      point reference is off limit, rather than returning an */\r
+      /*      error.  As a delta instruction doesn't change a glyph  */\r
+      /*      in great ways, this shouldn't be a problem.            */\r
+\r
+      if ( !BOUNDS( A, CUR.zp0.n_points ) )\r
+      {\r
+        C = ( (FT_ULong)B & 0xF0 ) >> 4;\r
+\r
+        switch ( CUR.opcode )\r
+        {\r
+        case 0x5D:\r
+          break;\r
+\r
+        case 0x71:\r
+          C += 16;\r
+          break;\r
+\r
+        case 0x72:\r
+          C += 32;\r
+          break;\r
+        }\r
+\r
+        C += CUR.GS.delta_base;\r
+\r
+        if ( CURRENT_Ppem() == (FT_Long)C )\r
+        {\r
+          B = ( (FT_ULong)B & 0xF ) - 8;\r
+          if ( B >= 0 )\r
+            B++;\r
+          B = B * 64 / ( 1L << CUR.GS.delta_shift );\r
+\r
+          CUR_Func_move( &CUR.zp0, A, B );\r
+        }\r
+      }\r
+      else\r
+        if ( CUR.pedantic_hinting )\r
+          CUR.error = TT_Err_Invalid_Reference;\r
+    }\r
+\r
+    CUR.new_top = CUR.args;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* DELTACn[]:    DELTA exceptions C1, C2, C3                             */\r
+  /* Opcode range: 0x73,0x74,0x75                                          */\r
+  /* Stack:        uint32 (2 * uint32)... -->                              */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_DELTAC( INS_ARG )\r
+  {\r
+    FT_ULong  nump, k;\r
+    FT_ULong  A, C;\r
+    FT_Long   B;\r
+\r
+\r
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING\r
+    /* Delta hinting is covered by US Patent 5159668. */\r
+    if ( CUR.face->unpatented_hinting )\r
+    {\r
+      FT_Long  n = args[0] * 2;\r
+\r
+\r
+      if ( CUR.args < n )\r
+      {\r
+        CUR.error = TT_Err_Too_Few_Arguments;\r
+        return;\r
+      }\r
+\r
+      CUR.args -= n;\r
+      CUR.new_top = CUR.args;\r
+      return;\r
+    }\r
+#endif\r
+\r
+    nump = (FT_ULong)args[0];\r
+\r
+    for ( k = 1; k <= nump; k++ )\r
+    {\r
+      if ( CUR.args < 2 )\r
+      {\r
+        CUR.error = TT_Err_Too_Few_Arguments;\r
+        return;\r
+      }\r
+\r
+      CUR.args -= 2;\r
+\r
+      A = (FT_ULong)CUR.stack[CUR.args + 1];\r
+      B = CUR.stack[CUR.args];\r
+\r
+      if ( BOUNDS( A, CUR.cvtSize ) )\r
+      {\r
+        if ( CUR.pedantic_hinting )\r
+        {\r
+          CUR.error = TT_Err_Invalid_Reference;\r
+          return;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        C = ( (FT_ULong)B & 0xF0 ) >> 4;\r
+\r
+        switch ( CUR.opcode )\r
+        {\r
+        case 0x73:\r
+          break;\r
+\r
+        case 0x74:\r
+          C += 16;\r
+          break;\r
+\r
+        case 0x75:\r
+          C += 32;\r
+          break;\r
+        }\r
+\r
+        C += CUR.GS.delta_base;\r
+\r
+        if ( CURRENT_Ppem() == (FT_Long)C )\r
+        {\r
+          B = ( (FT_ULong)B & 0xF ) - 8;\r
+          if ( B >= 0 )\r
+            B++;\r
+          B = B * 64 / ( 1L << CUR.GS.delta_shift );\r
+\r
+          CUR_Func_move_cvt( A, B );\r
+        }\r
+      }\r
+    }\r
+\r
+    CUR.new_top = CUR.args;\r
+  }\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* MISC. INSTRUCTIONS                                                    */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* GETINFO[]:    GET INFOrmation                                         */\r
+  /* Opcode range: 0x88                                                    */\r
+  /* Stack:        uint32 --> uint32                                       */\r
+  /*                                                                       */\r
+  static void\r
+  Ins_GETINFO( INS_ARG )\r
+  {\r
+    FT_Long  K;\r
+\r
+\r
+    K = 0;\r
+\r
+    /* We return MS rasterizer version 1.7 for the font scaler. */\r
+    if ( ( args[0] & 1 ) != 0 )\r
+      K = 35;\r
+\r
+    /* Has the glyph been rotated? */\r
+    if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )\r
+      K |= 0x80;\r
+\r
+    /* Has the glyph been stretched? */\r
+    if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )\r
+      K |= 1 << 8;\r
+\r
+    /* Are we hinting for grayscale? */\r
+    if ( ( args[0] & 32 ) != 0 && CUR.grayscale )\r
+      K |= 1 << 12;\r
+\r
+    args[0] = K;\r
+  }\r
+\r
+\r
+  static void\r
+  Ins_UNKNOWN( INS_ARG )\r
+  {\r
+    TT_DefRecord*  def   = CUR.IDefs;\r
+    TT_DefRecord*  limit = def + CUR.numIDefs;\r
+\r
+    FT_UNUSED_ARG;\r
+\r
+\r
+    for ( ; def < limit; def++ )\r
+    {\r
+      if ( (FT_Byte)def->opc == CUR.opcode && def->active )\r
+      {\r
+        TT_CallRec*  call;\r
+\r
+\r
+        if ( CUR.callTop >= CUR.callSize )\r
+        {\r
+          CUR.error = TT_Err_Stack_Overflow;\r
+          return;\r
+        }\r
+\r
+        call = CUR.callStack + CUR.callTop++;\r
+\r
+        call->Caller_Range = CUR.curRange;\r
+        call->Caller_IP    = CUR.IP+1;\r
+        call->Cur_Count    = 1;\r
+        call->Cur_Restart  = def->start;\r
+\r
+        INS_Goto_CodeRange( def->range, def->start );\r
+\r
+        CUR.step_ins = FALSE;\r
+        return;\r
+      }\r
+    }\r
+\r
+    CUR.error = TT_Err_Invalid_Opcode;\r
+  }\r
+\r
+\r
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH\r
+\r
+\r
+  static\r
+  TInstruction_Function  Instruct_Dispatch[256] =\r
+  {\r
+    /* Opcodes are gathered in groups of 16. */\r
+    /* Please keep the spaces as they are.   */\r
+\r
+    /*  SVTCA  y  */  Ins_SVTCA,\r
+    /*  SVTCA  x  */  Ins_SVTCA,\r
+    /*  SPvTCA y  */  Ins_SPVTCA,\r
+    /*  SPvTCA x  */  Ins_SPVTCA,\r
+    /*  SFvTCA y  */  Ins_SFVTCA,\r
+    /*  SFvTCA x  */  Ins_SFVTCA,\r
+    /*  SPvTL //  */  Ins_SPVTL,\r
+    /*  SPvTL +   */  Ins_SPVTL,\r
+    /*  SFvTL //  */  Ins_SFVTL,\r
+    /*  SFvTL +   */  Ins_SFVTL,\r
+    /*  SPvFS     */  Ins_SPVFS,\r
+    /*  SFvFS     */  Ins_SFVFS,\r
+    /*  GPV       */  Ins_GPV,\r
+    /*  GFV       */  Ins_GFV,\r
+    /*  SFvTPv    */  Ins_SFVTPV,\r
+    /*  ISECT     */  Ins_ISECT,\r
+\r
+    /*  SRP0      */  Ins_SRP0,\r
+    /*  SRP1      */  Ins_SRP1,\r
+    /*  SRP2      */  Ins_SRP2,\r
+    /*  SZP0      */  Ins_SZP0,\r
+    /*  SZP1      */  Ins_SZP1,\r
+    /*  SZP2      */  Ins_SZP2,\r
+    /*  SZPS      */  Ins_SZPS,\r
+    /*  SLOOP     */  Ins_SLOOP,\r
+    /*  RTG       */  Ins_RTG,\r
+    /*  RTHG      */  Ins_RTHG,\r
+    /*  SMD       */  Ins_SMD,\r
+    /*  ELSE      */  Ins_ELSE,\r
+    /*  JMPR      */  Ins_JMPR,\r
+    /*  SCvTCi    */  Ins_SCVTCI,\r
+    /*  SSwCi     */  Ins_SSWCI,\r
+    /*  SSW       */  Ins_SSW,\r
+\r
+    /*  DUP       */  Ins_DUP,\r
+    /*  POP       */  Ins_POP,\r
+    /*  CLEAR     */  Ins_CLEAR,\r
+    /*  SWAP      */  Ins_SWAP,\r
+    /*  DEPTH     */  Ins_DEPTH,\r
+    /*  CINDEX    */  Ins_CINDEX,\r
+    /*  MINDEX    */  Ins_MINDEX,\r
+    /*  AlignPTS  */  Ins_ALIGNPTS,\r
+    /*  INS_0x28  */  Ins_UNKNOWN,\r
+    /*  UTP       */  Ins_UTP,\r
+    /*  LOOPCALL  */  Ins_LOOPCALL,\r
+    /*  CALL      */  Ins_CALL,\r
+    /*  FDEF      */  Ins_FDEF,\r
+    /*  ENDF      */  Ins_ENDF,\r
+    /*  MDAP[0]   */  Ins_MDAP,\r
+    /*  MDAP[1]   */  Ins_MDAP,\r
+\r
+    /*  IUP[0]    */  Ins_IUP,\r
+    /*  IUP[1]    */  Ins_IUP,\r
+    /*  SHP[0]    */  Ins_SHP,\r
+    /*  SHP[1]    */  Ins_SHP,\r
+    /*  SHC[0]    */  Ins_SHC,\r
+    /*  SHC[1]    */  Ins_SHC,\r
+    /*  SHZ[0]    */  Ins_SHZ,\r
+    /*  SHZ[1]    */  Ins_SHZ,\r
+    /*  SHPIX     */  Ins_SHPIX,\r
+    /*  IP        */  Ins_IP,\r
+    /*  MSIRP[0]  */  Ins_MSIRP,\r
+    /*  MSIRP[1]  */  Ins_MSIRP,\r
+    /*  AlignRP   */  Ins_ALIGNRP,\r
+    /*  RTDG      */  Ins_RTDG,\r
+    /*  MIAP[0]   */  Ins_MIAP,\r
+    /*  MIAP[1]   */  Ins_MIAP,\r
+\r
+    /*  NPushB    */  Ins_NPUSHB,\r
+    /*  NPushW    */  Ins_NPUSHW,\r
+    /*  WS        */  Ins_WS,\r
+    /*  RS        */  Ins_RS,\r
+    /*  WCvtP     */  Ins_WCVTP,\r
+    /*  RCvt      */  Ins_RCVT,\r
+    /*  GC[0]     */  Ins_GC,\r
+    /*  GC[1]     */  Ins_GC,\r
+    /*  SCFS      */  Ins_SCFS,\r
+    /*  MD[0]     */  Ins_MD,\r
+    /*  MD[1]     */  Ins_MD,\r
+    /*  MPPEM     */  Ins_MPPEM,\r
+    /*  MPS       */  Ins_MPS,\r
+    /*  FlipON    */  Ins_FLIPON,\r
+    /*  FlipOFF   */  Ins_FLIPOFF,\r
+    /*  DEBUG     */  Ins_DEBUG,\r
+\r
+    /*  LT        */  Ins_LT,\r
+    /*  LTEQ      */  Ins_LTEQ,\r
+    /*  GT        */  Ins_GT,\r
+    /*  GTEQ      */  Ins_GTEQ,\r
+    /*  EQ        */  Ins_EQ,\r
+    /*  NEQ       */  Ins_NEQ,\r
+    /*  ODD       */  Ins_ODD,\r
+    /*  EVEN      */  Ins_EVEN,\r
+    /*  IF        */  Ins_IF,\r
+    /*  EIF       */  Ins_EIF,\r
+    /*  AND       */  Ins_AND,\r
+    /*  OR        */  Ins_OR,\r
+    /*  NOT       */  Ins_NOT,\r
+    /*  DeltaP1   */  Ins_DELTAP,\r
+    /*  SDB       */  Ins_SDB,\r
+    /*  SDS       */  Ins_SDS,\r
+\r
+    /*  ADD       */  Ins_ADD,\r
+    /*  SUB       */  Ins_SUB,\r
+    /*  DIV       */  Ins_DIV,\r
+    /*  MUL       */  Ins_MUL,\r
+    /*  ABS       */  Ins_ABS,\r
+    /*  NEG       */  Ins_NEG,\r
+    /*  FLOOR     */  Ins_FLOOR,\r
+    /*  CEILING   */  Ins_CEILING,\r
+    /*  ROUND[0]  */  Ins_ROUND,\r
+    /*  ROUND[1]  */  Ins_ROUND,\r
+    /*  ROUND[2]  */  Ins_ROUND,\r
+    /*  ROUND[3]  */  Ins_ROUND,\r
+    /*  NROUND[0] */  Ins_NROUND,\r
+    /*  NROUND[1] */  Ins_NROUND,\r
+    /*  NROUND[2] */  Ins_NROUND,\r
+    /*  NROUND[3] */  Ins_NROUND,\r
+\r
+    /*  WCvtF     */  Ins_WCVTF,\r
+    /*  DeltaP2   */  Ins_DELTAP,\r
+    /*  DeltaP3   */  Ins_DELTAP,\r
+    /*  DeltaCn[0] */ Ins_DELTAC,\r
+    /*  DeltaCn[1] */ Ins_DELTAC,\r
+    /*  DeltaCn[2] */ Ins_DELTAC,\r
+    /*  SROUND    */  Ins_SROUND,\r
+    /*  S45Round  */  Ins_S45ROUND,\r
+    /*  JROT      */  Ins_JROT,\r
+    /*  JROF      */  Ins_JROF,\r
+    /*  ROFF      */  Ins_ROFF,\r
+    /*  INS_0x7B  */  Ins_UNKNOWN,\r
+    /*  RUTG      */  Ins_RUTG,\r
+    /*  RDTG      */  Ins_RDTG,\r
+    /*  SANGW     */  Ins_SANGW,\r
+    /*  AA        */  Ins_AA,\r
+\r
+    /*  FlipPT    */  Ins_FLIPPT,\r
+    /*  FlipRgON  */  Ins_FLIPRGON,\r
+    /*  FlipRgOFF */  Ins_FLIPRGOFF,\r
+    /*  INS_0x83  */  Ins_UNKNOWN,\r
+    /*  INS_0x84  */  Ins_UNKNOWN,\r
+    /*  ScanCTRL  */  Ins_SCANCTRL,\r
+    /*  SDPVTL[0] */  Ins_SDPVTL,\r
+    /*  SDPVTL[1] */  Ins_SDPVTL,\r
+    /*  GetINFO   */  Ins_GETINFO,\r
+    /*  IDEF      */  Ins_IDEF,\r
+    /*  ROLL      */  Ins_ROLL,\r
+    /*  MAX       */  Ins_MAX,\r
+    /*  MIN       */  Ins_MIN,\r
+    /*  ScanTYPE  */  Ins_SCANTYPE,\r
+    /*  InstCTRL  */  Ins_INSTCTRL,\r
+    /*  INS_0x8F  */  Ins_UNKNOWN,\r
+\r
+    /*  INS_0x90  */   Ins_UNKNOWN,\r
+    /*  INS_0x91  */   Ins_UNKNOWN,\r
+    /*  INS_0x92  */   Ins_UNKNOWN,\r
+    /*  INS_0x93  */   Ins_UNKNOWN,\r
+    /*  INS_0x94  */   Ins_UNKNOWN,\r
+    /*  INS_0x95  */   Ins_UNKNOWN,\r
+    /*  INS_0x96  */   Ins_UNKNOWN,\r
+    /*  INS_0x97  */   Ins_UNKNOWN,\r
+    /*  INS_0x98  */   Ins_UNKNOWN,\r
+    /*  INS_0x99  */   Ins_UNKNOWN,\r
+    /*  INS_0x9A  */   Ins_UNKNOWN,\r
+    /*  INS_0x9B  */   Ins_UNKNOWN,\r
+    /*  INS_0x9C  */   Ins_UNKNOWN,\r
+    /*  INS_0x9D  */   Ins_UNKNOWN,\r
+    /*  INS_0x9E  */   Ins_UNKNOWN,\r
+    /*  INS_0x9F  */   Ins_UNKNOWN,\r
+\r
+    /*  INS_0xA0  */   Ins_UNKNOWN,\r
+    /*  INS_0xA1  */   Ins_UNKNOWN,\r
+    /*  INS_0xA2  */   Ins_UNKNOWN,\r
+    /*  INS_0xA3  */   Ins_UNKNOWN,\r
+    /*  INS_0xA4  */   Ins_UNKNOWN,\r
+    /*  INS_0xA5  */   Ins_UNKNOWN,\r
+    /*  INS_0xA6  */   Ins_UNKNOWN,\r
+    /*  INS_0xA7  */   Ins_UNKNOWN,\r
+    /*  INS_0xA8  */   Ins_UNKNOWN,\r
+    /*  INS_0xA9  */   Ins_UNKNOWN,\r
+    /*  INS_0xAA  */   Ins_UNKNOWN,\r
+    /*  INS_0xAB  */   Ins_UNKNOWN,\r
+    /*  INS_0xAC  */   Ins_UNKNOWN,\r
+    /*  INS_0xAD  */   Ins_UNKNOWN,\r
+    /*  INS_0xAE  */   Ins_UNKNOWN,\r
+    /*  INS_0xAF  */   Ins_UNKNOWN,\r
+\r
+    /*  PushB[0]  */  Ins_PUSHB,\r
+    /*  PushB[1]  */  Ins_PUSHB,\r
+    /*  PushB[2]  */  Ins_PUSHB,\r
+    /*  PushB[3]  */  Ins_PUSHB,\r
+    /*  PushB[4]  */  Ins_PUSHB,\r
+    /*  PushB[5]  */  Ins_PUSHB,\r
+    /*  PushB[6]  */  Ins_PUSHB,\r
+    /*  PushB[7]  */  Ins_PUSHB,\r
+    /*  PushW[0]  */  Ins_PUSHW,\r
+    /*  PushW[1]  */  Ins_PUSHW,\r
+    /*  PushW[2]  */  Ins_PUSHW,\r
+    /*  PushW[3]  */  Ins_PUSHW,\r
+    /*  PushW[4]  */  Ins_PUSHW,\r
+    /*  PushW[5]  */  Ins_PUSHW,\r
+    /*  PushW[6]  */  Ins_PUSHW,\r
+    /*  PushW[7]  */  Ins_PUSHW,\r
+\r
+    /*  MDRP[00]  */  Ins_MDRP,\r
+    /*  MDRP[01]  */  Ins_MDRP,\r
+    /*  MDRP[02]  */  Ins_MDRP,\r
+    /*  MDRP[03]  */  Ins_MDRP,\r
+    /*  MDRP[04]  */  Ins_MDRP,\r
+    /*  MDRP[05]  */  Ins_MDRP,\r
+    /*  MDRP[06]  */  Ins_MDRP,\r
+    /*  MDRP[07]  */  Ins_MDRP,\r
+    /*  MDRP[08]  */  Ins_MDRP,\r
+    /*  MDRP[09]  */  Ins_MDRP,\r
+    /*  MDRP[10]  */  Ins_MDRP,\r
+    /*  MDRP[11]  */  Ins_MDRP,\r
+    /*  MDRP[12]  */  Ins_MDRP,\r
+    /*  MDRP[13]  */  Ins_MDRP,\r
+    /*  MDRP[14]  */  Ins_MDRP,\r
+    /*  MDRP[15]  */  Ins_MDRP,\r
+\r
+    /*  MDRP[16]  */  Ins_MDRP,\r
+    /*  MDRP[17]  */  Ins_MDRP,\r
+    /*  MDRP[18]  */  Ins_MDRP,\r
+    /*  MDRP[19]  */  Ins_MDRP,\r
+    /*  MDRP[20]  */  Ins_MDRP,\r
+    /*  MDRP[21]  */  Ins_MDRP,\r
+    /*  MDRP[22]  */  Ins_MDRP,\r
+    /*  MDRP[23]  */  Ins_MDRP,\r
+    /*  MDRP[24]  */  Ins_MDRP,\r
+    /*  MDRP[25]  */  Ins_MDRP,\r
+    /*  MDRP[26]  */  Ins_MDRP,\r
+    /*  MDRP[27]  */  Ins_MDRP,\r
+    /*  MDRP[28]  */  Ins_MDRP,\r
+    /*  MDRP[29]  */  Ins_MDRP,\r
+    /*  MDRP[30]  */  Ins_MDRP,\r
+    /*  MDRP[31]  */  Ins_MDRP,\r
+\r
+    /*  MIRP[00]  */  Ins_MIRP,\r
+    /*  MIRP[01]  */  Ins_MIRP,\r
+    /*  MIRP[02]  */  Ins_MIRP,\r
+    /*  MIRP[03]  */  Ins_MIRP,\r
+    /*  MIRP[04]  */  Ins_MIRP,\r
+    /*  MIRP[05]  */  Ins_MIRP,\r
+    /*  MIRP[06]  */  Ins_MIRP,\r
+    /*  MIRP[07]  */  Ins_MIRP,\r
+    /*  MIRP[08]  */  Ins_MIRP,\r
+    /*  MIRP[09]  */  Ins_MIRP,\r
+    /*  MIRP[10]  */  Ins_MIRP,\r
+    /*  MIRP[11]  */  Ins_MIRP,\r
+    /*  MIRP[12]  */  Ins_MIRP,\r
+    /*  MIRP[13]  */  Ins_MIRP,\r
+    /*  MIRP[14]  */  Ins_MIRP,\r
+    /*  MIRP[15]  */  Ins_MIRP,\r
+\r
+    /*  MIRP[16]  */  Ins_MIRP,\r
+    /*  MIRP[17]  */  Ins_MIRP,\r
+    /*  MIRP[18]  */  Ins_MIRP,\r
+    /*  MIRP[19]  */  Ins_MIRP,\r
+    /*  MIRP[20]  */  Ins_MIRP,\r
+    /*  MIRP[21]  */  Ins_MIRP,\r
+    /*  MIRP[22]  */  Ins_MIRP,\r
+    /*  MIRP[23]  */  Ins_MIRP,\r
+    /*  MIRP[24]  */  Ins_MIRP,\r
+    /*  MIRP[25]  */  Ins_MIRP,\r
+    /*  MIRP[26]  */  Ins_MIRP,\r
+    /*  MIRP[27]  */  Ins_MIRP,\r
+    /*  MIRP[28]  */  Ins_MIRP,\r
+    /*  MIRP[29]  */  Ins_MIRP,\r
+    /*  MIRP[30]  */  Ins_MIRP,\r
+    /*  MIRP[31]  */  Ins_MIRP\r
+  };\r
+\r
+\r
+#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */\r
+\r
+\r
+  /*************************************************************************/\r
+  /*                                                                       */\r
+  /* RUN                                                                   */\r
+  /*                                                                       */\r
+  /*  This function executes a run of opcodes.  It will exit in the        */\r
+  /*  following cases:                                                     */\r
+  /*                                                                       */\r
+  /*  - Errors (in which case it returns FALSE).                           */\r
+  /*                                                                       */\r
+  /*  - Reaching the end of the main code range (returns TRUE).            */\r
+  /*    Reaching the end of a code range within a function call is an      */\r
+  /*    error.                                                             */\r
+  /*                                                                       */\r
+  /*  - After executing one single opcode, if the flag `Instruction_Trap'  */\r
+  /*    is set to TRUE (returns TRUE).                                     */\r
+  /*                                                                       */\r
+  /*  On exit with TRUE, test IP < CodeSize to know whether it comes from  */\r
+  /*  an instruction trap or a normal termination.                         */\r
+  /*                                                                       */\r
+  /*                                                                       */\r
+  /*  Note: The documented DEBUG opcode pops a value from the stack.  This */\r
+  /*        behaviour is unsupported; here a DEBUG opcode is always an     */\r
+  /*        error.                                                         */\r
+  /*                                                                       */\r
+  /*                                                                       */\r
+  /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */\r
+  /*                                                                       */\r
+  /*  Instructions appear in the specification's order.                    */\r
+  /*                                                                       */\r
+  /*************************************************************************/\r
+\r
+\r
+  /* documentation is in ttinterp.h */\r
+\r
+  FT_EXPORT_DEF( FT_Error )\r
+  TT_RunIns( TT_ExecContext  exc )\r
+  {\r
+    FT_Long  ins_counter = 0;  /* executed instructions counter */\r
+\r
+\r
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER\r
+    cur = *exc;\r
+#endif\r
+\r
+    /* set CVT functions */\r
+    CUR.tt_metrics.ratio = 0;\r
+    if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )\r
+    {\r
+      /* non-square pixels, use the stretched routines */\r
+      CUR.func_read_cvt  = Read_CVT_Stretched;\r
+      CUR.func_write_cvt = Write_CVT_Stretched;\r
+      CUR.func_move_cvt  = Move_CVT_Stretched;\r
+    }\r
+    else\r
+    {\r
+      /* square pixels, use normal routines */\r
+      CUR.func_read_cvt  = Read_CVT;\r
+      CUR.func_write_cvt = Write_CVT;\r
+      CUR.func_move_cvt  = Move_CVT;\r
+    }\r
+\r
+    COMPUTE_Funcs();\r
+    COMPUTE_Round( (FT_Byte)exc->GS.round_state );\r
+\r
+    do\r
+    {\r
+      CUR.opcode = CUR.code[CUR.IP];\r
+\r
+      if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )\r
+      {\r
+        if ( CUR.IP + 1 > CUR.codeSize )\r
+          goto LErrorCodeOverflow_;\r
+\r
+        CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];\r
+      }\r
+\r
+      if ( CUR.IP + CUR.length > CUR.codeSize )\r
+        goto LErrorCodeOverflow_;\r
+\r
+      /* First, let's check for empty stack and overflow */\r
+      CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );\r
+\r
+      /* `args' is the top of the stack once arguments have been popped. */\r
+      /* One can also interpret it as the index of the last argument.    */\r
+      if ( CUR.args < 0 )\r
+      {\r
+        CUR.error = TT_Err_Too_Few_Arguments;\r
+        goto LErrorLabel_;\r
+      }\r
+\r
+      CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );\r
+\r
+      /* `new_top' is the new top of the stack, after the instruction's */\r
+      /* execution.  `top' will be set to `new_top' after the `switch'  */\r
+      /* statement.                                                     */\r
+      if ( CUR.new_top > CUR.stackSize )\r
+      {\r
+        CUR.error = TT_Err_Stack_Overflow;\r
+        goto LErrorLabel_;\r
+      }\r
+\r
+      CUR.step_ins = TRUE;\r
+      CUR.error    = TT_Err_Ok;\r
+\r
+#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH\r
+\r
+      {\r
+        FT_Long*  args   = CUR.stack + CUR.args;\r
+        FT_Byte   opcode = CUR.opcode;\r
+\r
+\r
+#undef  ARRAY_BOUND_ERROR\r
+#define ARRAY_BOUND_ERROR  goto Set_Invalid_Ref\r
+\r
+\r
+        switch ( opcode )\r
+        {\r
+        case 0x00:  /* SVTCA y  */\r
+        case 0x01:  /* SVTCA x  */\r
+        case 0x02:  /* SPvTCA y */\r
+        case 0x03:  /* SPvTCA x */\r
+        case 0x04:  /* SFvTCA y */\r
+        case 0x05:  /* SFvTCA x */\r
+          {\r
+            FT_Short AA, BB;\r
+\r
+\r
+            AA = (FT_Short)( ( opcode & 1 ) << 14 );\r
+            BB = (FT_Short)( AA ^ 0x4000 );\r
+\r
+            if ( opcode < 4 )\r
+            {\r
+              CUR.GS.projVector.x = AA;\r
+              CUR.GS.projVector.y = BB;\r
+\r
+              CUR.GS.dualVector.x = AA;\r
+              CUR.GS.dualVector.y = BB;\r
+            }\r
+            else\r
+            {\r
+              GUESS_VECTOR( projVector );\r
+            }\r
+\r
+            if ( ( opcode & 2 ) == 0 )\r
+            {\r
+              CUR.GS.freeVector.x = AA;\r
+              CUR.GS.freeVector.y = BB;\r
+            }\r
+            else\r
+            {\r
+              GUESS_VECTOR( freeVector );\r
+            }\r
+\r
+            COMPUTE_Funcs();\r
+          }\r
+          break;\r
+\r
+        case 0x06:  /* SPvTL // */\r
+        case 0x07:  /* SPvTL +  */\r
+          DO_SPVTL\r
+          break;\r
+\r
+        case 0x08:  /* SFvTL // */\r
+        case 0x09:  /* SFvTL +  */\r
+          DO_SFVTL\r
+          break;\r
+\r
+        case 0x0A:  /* SPvFS */\r
+          DO_SPVFS\r
+          break;\r
+\r
+        case 0x0B:  /* SFvFS */\r
+          DO_SFVFS\r
+          break;\r
+\r
+        case 0x0C:  /* GPV */\r
+          DO_GPV\r
+          break;\r
+\r
+        case 0x0D:  /* GFV */\r
+          DO_GFV\r
+          break;\r
+\r
+        case 0x0E:  /* SFvTPv */\r
+          DO_SFVTPV\r
+          break;\r
+\r
+        case 0x0F:  /* ISECT  */\r
+          Ins_ISECT( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x10:  /* SRP0 */\r
+          DO_SRP0\r
+          break;\r
+\r
+        case 0x11:  /* SRP1 */\r
+          DO_SRP1\r
+          break;\r
+\r
+        case 0x12:  /* SRP2 */\r
+          DO_SRP2\r
+          break;\r
+\r
+        case 0x13:  /* SZP0 */\r
+          Ins_SZP0( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x14:  /* SZP1 */\r
+          Ins_SZP1( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x15:  /* SZP2 */\r
+          Ins_SZP2( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x16:  /* SZPS */\r
+          Ins_SZPS( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x17:  /* SLOOP */\r
+          DO_SLOOP\r
+          break;\r
+\r
+        case 0x18:  /* RTG */\r
+          DO_RTG\r
+          break;\r
+\r
+        case 0x19:  /* RTHG */\r
+          DO_RTHG\r
+          break;\r
+\r
+        case 0x1A:  /* SMD */\r
+          DO_SMD\r
+          break;\r
+\r
+        case 0x1B:  /* ELSE */\r
+          Ins_ELSE( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x1C:  /* JMPR */\r
+          DO_JMPR\r
+          break;\r
+\r
+        case 0x1D:  /* SCVTCI */\r
+          DO_SCVTCI\r
+          break;\r
+\r
+        case 0x1E:  /* SSWCI */\r
+          DO_SSWCI\r
+          break;\r
+\r
+        case 0x1F:  /* SSW */\r
+          DO_SSW\r
+          break;\r
+\r
+        case 0x20:  /* DUP */\r
+          DO_DUP\r
+          break;\r
+\r
+        case 0x21:  /* POP */\r
+          /* nothing :-) */\r
+          break;\r
+\r
+        case 0x22:  /* CLEAR */\r
+          DO_CLEAR\r
+          break;\r
+\r
+        case 0x23:  /* SWAP */\r
+          DO_SWAP\r
+          break;\r
+\r
+        case 0x24:  /* DEPTH */\r
+          DO_DEPTH\r
+          break;\r
+\r
+        case 0x25:  /* CINDEX */\r
+          DO_CINDEX\r
+          break;\r
+\r
+        case 0x26:  /* MINDEX */\r
+          Ins_MINDEX( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x27:  /* ALIGNPTS */\r
+          Ins_ALIGNPTS( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x28:  /* ???? */\r
+          Ins_UNKNOWN( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x29:  /* UTP */\r
+          Ins_UTP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x2A:  /* LOOPCALL */\r
+          Ins_LOOPCALL( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x2B:  /* CALL */\r
+          Ins_CALL( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x2C:  /* FDEF */\r
+          Ins_FDEF( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x2D:  /* ENDF */\r
+          Ins_ENDF( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x2E:  /* MDAP */\r
+        case 0x2F:  /* MDAP */\r
+          Ins_MDAP( EXEC_ARG_ args );\r
+          break;\r
+\r
+\r
+        case 0x30:  /* IUP */\r
+        case 0x31:  /* IUP */\r
+          Ins_IUP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x32:  /* SHP */\r
+        case 0x33:  /* SHP */\r
+          Ins_SHP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x34:  /* SHC */\r
+        case 0x35:  /* SHC */\r
+          Ins_SHC( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x36:  /* SHZ */\r
+        case 0x37:  /* SHZ */\r
+          Ins_SHZ( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x38:  /* SHPIX */\r
+          Ins_SHPIX( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x39:  /* IP    */\r
+          Ins_IP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x3A:  /* MSIRP */\r
+        case 0x3B:  /* MSIRP */\r
+          Ins_MSIRP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x3C:  /* AlignRP */\r
+          Ins_ALIGNRP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x3D:  /* RTDG */\r
+          DO_RTDG\r
+          break;\r
+\r
+        case 0x3E:  /* MIAP */\r
+        case 0x3F:  /* MIAP */\r
+          Ins_MIAP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x40:  /* NPUSHB */\r
+          Ins_NPUSHB( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x41:  /* NPUSHW */\r
+          Ins_NPUSHW( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x42:  /* WS */\r
+          DO_WS\r
+          break;\r
+\r
+      Set_Invalid_Ref:\r
+            CUR.error = TT_Err_Invalid_Reference;\r
+          break;\r
+\r
+        case 0x43:  /* RS */\r
+          DO_RS\r
+          break;\r
+\r
+        case 0x44:  /* WCVTP */\r
+          DO_WCVTP\r
+          break;\r
+\r
+        case 0x45:  /* RCVT */\r
+          DO_RCVT\r
+          break;\r
+\r
+        case 0x46:  /* GC */\r
+        case 0x47:  /* GC */\r
+          Ins_GC( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x48:  /* SCFS */\r
+          Ins_SCFS( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x49:  /* MD */\r
+        case 0x4A:  /* MD */\r
+          Ins_MD( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x4B:  /* MPPEM */\r
+          DO_MPPEM\r
+          break;\r
+\r
+        case 0x4C:  /* MPS */\r
+          DO_MPS\r
+          break;\r
+\r
+        case 0x4D:  /* FLIPON */\r
+          DO_FLIPON\r
+          break;\r
+\r
+        case 0x4E:  /* FLIPOFF */\r
+          DO_FLIPOFF\r
+          break;\r
+\r
+        case 0x4F:  /* DEBUG */\r
+          DO_DEBUG\r
+          break;\r
+\r
+        case 0x50:  /* LT */\r
+          DO_LT\r
+          break;\r
+\r
+        case 0x51:  /* LTEQ */\r
+          DO_LTEQ\r
+          break;\r
+\r
+        case 0x52:  /* GT */\r
+          DO_GT\r
+          break;\r
+\r
+        case 0x53:  /* GTEQ */\r
+          DO_GTEQ\r
+          break;\r
+\r
+        case 0x54:  /* EQ */\r
+          DO_EQ\r
+          break;\r
+\r
+        case 0x55:  /* NEQ */\r
+          DO_NEQ\r
+          break;\r
+\r
+        case 0x56:  /* ODD */\r
+          DO_ODD\r
+          break;\r
+\r
+        case 0x57:  /* EVEN */\r
+          DO_EVEN\r
+          break;\r
+\r
+        case 0x58:  /* IF */\r
+          Ins_IF( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x59:  /* EIF */\r
+          /* do nothing */\r
+          break;\r
+\r
+        case 0x5A:  /* AND */\r
+          DO_AND\r
+          break;\r
+\r
+        case 0x5B:  /* OR */\r
+          DO_OR\r
+          break;\r
+\r
+        case 0x5C:  /* NOT */\r
+          DO_NOT\r
+          break;\r
+\r
+        case 0x5D:  /* DELTAP1 */\r
+          Ins_DELTAP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x5E:  /* SDB */\r
+          DO_SDB\r
+          break;\r
+\r
+        case 0x5F:  /* SDS */\r
+          DO_SDS\r
+          break;\r
+\r
+        case 0x60:  /* ADD */\r
+          DO_ADD\r
+          break;\r
+\r
+        case 0x61:  /* SUB */\r
+          DO_SUB\r
+          break;\r
+\r
+        case 0x62:  /* DIV */\r
+          DO_DIV\r
+          break;\r
+\r
+        case 0x63:  /* MUL */\r
+          DO_MUL\r
+          break;\r
+\r
+        case 0x64:  /* ABS */\r
+          DO_ABS\r
+          break;\r
+\r
+        case 0x65:  /* NEG */\r
+          DO_NEG\r
+          break;\r
+\r
+        case 0x66:  /* FLOOR */\r
+          DO_FLOOR\r
+          break;\r
+\r
+        case 0x67:  /* CEILING */\r
+          DO_CEILING\r
+          break;\r
+\r
+        case 0x68:  /* ROUND */\r
+        case 0x69:  /* ROUND */\r
+        case 0x6A:  /* ROUND */\r
+        case 0x6B:  /* ROUND */\r
+          DO_ROUND\r
+          break;\r
+\r
+        case 0x6C:  /* NROUND */\r
+        case 0x6D:  /* NROUND */\r
+        case 0x6E:  /* NRRUND */\r
+        case 0x6F:  /* NROUND */\r
+          DO_NROUND\r
+          break;\r
+\r
+        case 0x70:  /* WCVTF */\r
+          DO_WCVTF\r
+          break;\r
+\r
+        case 0x71:  /* DELTAP2 */\r
+        case 0x72:  /* DELTAP3 */\r
+          Ins_DELTAP( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x73:  /* DELTAC0 */\r
+        case 0x74:  /* DELTAC1 */\r
+        case 0x75:  /* DELTAC2 */\r
+          Ins_DELTAC( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x76:  /* SROUND */\r
+          DO_SROUND\r
+          break;\r
+\r
+        case 0x77:  /* S45Round */\r
+          DO_S45ROUND\r
+          break;\r
+\r
+        case 0x78:  /* JROT */\r
+          DO_JROT\r
+          break;\r
+\r
+        case 0x79:  /* JROF */\r
+          DO_JROF\r
+          break;\r
+\r
+        case 0x7A:  /* ROFF */\r
+          DO_ROFF\r
+          break;\r
+\r
+        case 0x7B:  /* ???? */\r
+          Ins_UNKNOWN( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x7C:  /* RUTG */\r
+          DO_RUTG\r
+          break;\r
+\r
+        case 0x7D:  /* RDTG */\r
+          DO_RDTG\r
+          break;\r
+\r
+        case 0x7E:  /* SANGW */\r
+        case 0x7F:  /* AA    */\r
+          /* nothing - obsolete */\r
+          break;\r
+\r
+        case 0x80:  /* FLIPPT */\r
+          Ins_FLIPPT( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x81:  /* FLIPRGON */\r
+          Ins_FLIPRGON( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x82:  /* FLIPRGOFF */\r
+          Ins_FLIPRGOFF( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x83:  /* UNKNOWN */\r
+        case 0x84:  /* UNKNOWN */\r
+          Ins_UNKNOWN( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x85:  /* SCANCTRL */\r
+          Ins_SCANCTRL( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x86:  /* SDPVTL */\r
+        case 0x87:  /* SDPVTL */\r
+          Ins_SDPVTL( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x88:  /* GETINFO */\r
+          Ins_GETINFO( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x89:  /* IDEF */\r
+          Ins_IDEF( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x8A:  /* ROLL */\r
+          Ins_ROLL( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x8B:  /* MAX */\r
+          DO_MAX\r
+          break;\r
+\r
+        case 0x8C:  /* MIN */\r
+          DO_MIN\r
+          break;\r
+\r
+        case 0x8D:  /* SCANTYPE */\r
+          Ins_SCANTYPE( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x8E:  /* INSTCTRL */\r
+          Ins_INSTCTRL( EXEC_ARG_ args );\r
+          break;\r
+\r
+        case 0x8F:\r
+          Ins_UNKNOWN( EXEC_ARG_ args );\r
+          break;\r
+\r
+        default:\r
+          if ( opcode >= 0xE0 )\r
+            Ins_MIRP( EXEC_ARG_ args );\r
+          else if ( opcode >= 0xC0 )\r
+            Ins_MDRP( EXEC_ARG_ args );\r
+          else if ( opcode >= 0xB8 )\r
+            Ins_PUSHW( EXEC_ARG_ args );\r
+          else if ( opcode >= 0xB0 )\r
+            Ins_PUSHB( EXEC_ARG_ args );\r
+          else\r
+            Ins_UNKNOWN( EXEC_ARG_ args );\r
+        }\r
+\r
+      }\r
+\r
+#else\r
+\r
+      Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );\r
+\r
+#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */\r
+\r
+      if ( CUR.error != TT_Err_Ok )\r
+      {\r
+        switch ( CUR.error )\r
+        {\r
+        case TT_Err_Invalid_Opcode: /* looking for redefined instructions */\r
+          {\r
+            TT_DefRecord*  def   = CUR.IDefs;\r
+            TT_DefRecord*  limit = def + CUR.numIDefs;\r
+\r
+\r
+            for ( ; def < limit; def++ )\r
+            {\r
+              if ( def->active && CUR.opcode == (FT_Byte)def->opc )\r
+              {\r
+                TT_CallRec*  callrec;\r
+\r
+\r
+                if ( CUR.callTop >= CUR.callSize )\r
+                {\r
+                  CUR.error = TT_Err_Invalid_Reference;\r
+                  goto LErrorLabel_;\r
+                }\r
+\r
+                callrec = &CUR.callStack[CUR.callTop];\r
+\r
+                callrec->Caller_Range = CUR.curRange;\r
+                callrec->Caller_IP    = CUR.IP + 1;\r
+                callrec->Cur_Count    = 1;\r
+                callrec->Cur_Restart  = def->start;\r
+\r
+                if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )\r
+                  goto LErrorLabel_;\r
+\r
+                goto LSuiteLabel_;\r
+              }\r
+            }\r
+          }\r
+\r
+          CUR.error = TT_Err_Invalid_Opcode;\r
+          goto LErrorLabel_;\r
+\r
+#if 0\r
+          break;   /* Unreachable code warning suppression.             */\r
+                   /* Leave to remind in case a later change the editor */\r
+                   /* to consider break;                                */\r
+#endif\r
+\r
+        default:\r
+          goto LErrorLabel_;\r
+\r
+#if 0\r
+        break;\r
+#endif\r
+        }\r
+      }\r
+\r
+      CUR.top = CUR.new_top;\r
+\r
+      if ( CUR.step_ins )\r
+        CUR.IP += CUR.length;\r
+\r
+      /* increment instruction counter and check if we didn't */\r
+      /* run this program for too long (e.g. infinite loops). */\r
+      if ( ++ins_counter > MAX_RUNNABLE_OPCODES )\r
+        return TT_Err_Execution_Too_Long;\r
+\r
+    LSuiteLabel_:\r
+      if ( CUR.IP >= CUR.codeSize )\r
+      {\r
+        if ( CUR.callTop > 0 )\r
+        {\r
+          CUR.error = TT_Err_Code_Overflow;\r
+          goto LErrorLabel_;\r
+        }\r
+        else\r
+          goto LNo_Error_;\r
+      }\r
+    } while ( !CUR.instruction_trap );\r
+\r
+  LNo_Error_:\r
+\r
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER\r
+    *exc = cur;\r
+#endif\r
+\r
+    return TT_Err_Ok;\r
+\r
+  LErrorCodeOverflow_:\r
+    CUR.error = TT_Err_Code_Overflow;\r
+\r
+  LErrorLabel_:\r
+\r
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER\r
+    *exc = cur;\r
+#endif\r
+\r
+    return CUR.error;\r
+  }\r
+\r
+\r
+#endif /* TT_USE_BYTECODE_INTERPRETER */\r
+\r
+\r
+/* END */\r