ttinterp.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:250k
源码类别:

其他游戏

开发平台:

Visual C++

  1.   /*************************************************************************/
  2.   /*                                                                       */
  3.   /* CEILING[]:    CEILING                                                 */
  4.   /* Opcode range: 0x67                                                    */
  5.   /* Stack:        f26.6 --> f26.6                                         */
  6.   /*                                                                       */
  7.   static void
  8.   Ins_CEILING( INS_ARG )
  9.   {
  10.     DO_CEILING
  11.   }
  12.   /*************************************************************************/
  13.   /*                                                                       */
  14.   /* RS[]:         Read Store                                              */
  15.   /* Opcode range: 0x43                                                    */
  16.   /* Stack:        uint32 --> uint32                                       */
  17.   /*                                                                       */
  18.   static void
  19.   Ins_RS( INS_ARG )
  20.   {
  21.     DO_RS
  22.   }
  23.   /*************************************************************************/
  24.   /*                                                                       */
  25.   /* WS[]:         Write Store                                             */
  26.   /* Opcode range: 0x42                                                    */
  27.   /* Stack:        uint32 uint32 -->                                       */
  28.   /*                                                                       */
  29.   static void
  30.   Ins_WS( INS_ARG )
  31.   {
  32.     DO_WS
  33.   }
  34.   /*************************************************************************/
  35.   /*                                                                       */
  36.   /* WCVTP[]:      Write CVT in Pixel units                                */
  37.   /* Opcode range: 0x44                                                    */
  38.   /* Stack:        f26.6 uint32 -->                                        */
  39.   /*                                                                       */
  40.   static void
  41.   Ins_WCVTP( INS_ARG )
  42.   {
  43.     DO_WCVTP
  44.   }
  45.   /*************************************************************************/
  46.   /*                                                                       */
  47.   /* WCVTF[]:      Write CVT in Funits                                     */
  48.   /* Opcode range: 0x70                                                    */
  49.   /* Stack:        uint32 uint32 -->                                       */
  50.   /*                                                                       */
  51.   static void
  52.   Ins_WCVTF( INS_ARG )
  53.   {
  54.     DO_WCVTF
  55.   }
  56.   /*************************************************************************/
  57.   /*                                                                       */
  58.   /* RCVT[]:       Read CVT                                                */
  59.   /* Opcode range: 0x45                                                    */
  60.   /* Stack:        uint32 --> f26.6                                        */
  61.   /*                                                                       */
  62.   static void
  63.   Ins_RCVT( INS_ARG )
  64.   {
  65.     DO_RCVT
  66.   }
  67.   /*************************************************************************/
  68.   /*                                                                       */
  69.   /* AA[]:         Adjust Angle                                            */
  70.   /* Opcode range: 0x7F                                                    */
  71.   /* Stack:        uint32 -->                                              */
  72.   /*                                                                       */
  73.   static void
  74.   Ins_AA( INS_ARG )
  75.   {
  76.     /* intentionally no longer supported */
  77.   }
  78.   /*************************************************************************/
  79.   /*                                                                       */
  80.   /* DEBUG[]:      DEBUG.  Unsupported.                                    */
  81.   /* Opcode range: 0x4F                                                    */
  82.   /* Stack:        uint32 -->                                              */
  83.   /*                                                                       */
  84.   /* Note: The original instruction pops a value from the stack.           */
  85.   /*                                                                       */
  86.   static void
  87.   Ins_DEBUG( INS_ARG )
  88.   {
  89.     DO_DEBUG
  90.   }
  91.   /*************************************************************************/
  92.   /*                                                                       */
  93.   /* ROUND[ab]:    ROUND value                                             */
  94.   /* Opcode range: 0x68-0x6B                                               */
  95.   /* Stack:        f26.6 --> f26.6                                         */
  96.   /*                                                                       */
  97.   static void
  98.   Ins_ROUND( INS_ARG )
  99.   {
  100.     DO_ROUND
  101.   }
  102.   /*************************************************************************/
  103.   /*                                                                       */
  104.   /* NROUND[ab]:   No ROUNDing of value                                    */
  105.   /* Opcode range: 0x6C-0x6F                                               */
  106.   /* Stack:        f26.6 --> f26.6                                         */
  107.   /*                                                                       */
  108.   static void
  109.   Ins_NROUND( INS_ARG )
  110.   {
  111.     DO_NROUND
  112.   }
  113.   /*************************************************************************/
  114.   /*                                                                       */
  115.   /* MAX[]:        MAXimum                                                 */
  116.   /* Opcode range: 0x68                                                    */
  117.   /* Stack:        int32? int32? --> int32                                 */
  118.   /*                                                                       */
  119.   static void
  120.   Ins_MAX( INS_ARG )
  121.   {
  122.     DO_MAX
  123.   }
  124.   /*************************************************************************/
  125.   /*                                                                       */
  126.   /* MIN[]:        MINimum                                                 */
  127.   /* Opcode range: 0x69                                                    */
  128.   /* Stack:        int32? int32? --> int32                                 */
  129.   /*                                                                       */
  130.   static void
  131.   Ins_MIN( INS_ARG )
  132.   {
  133.     DO_MIN
  134.   }
  135. #endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
  136.   /*************************************************************************/
  137.   /*                                                                       */
  138.   /* The following functions are called as is within the switch statement. */
  139.   /*                                                                       */
  140.   /*************************************************************************/
  141.   /*************************************************************************/
  142.   /*                                                                       */
  143.   /* MINDEX[]:     Move INDEXed element                                    */
  144.   /* Opcode range: 0x26                                                    */
  145.   /* Stack:        int32? --> StkElt                                       */
  146.   /*                                                                       */
  147.   static void
  148.   Ins_MINDEX( INS_ARG )
  149.   {
  150.     FT_Long  L, K;
  151.     L = args[0];
  152.     if ( L <= 0 || L > CUR.args )
  153.     {
  154.       CUR.error = TT_Err_Invalid_Reference;
  155.       return;
  156.     }
  157.     K = CUR.stack[CUR.args - L];
  158.     FT_ARRAY_MOVE( &CUR.stack[CUR.args - L    ],
  159.                    &CUR.stack[CUR.args - L + 1],
  160.                    ( L - 1 ) );
  161.     CUR.stack[CUR.args - 1] = K;
  162.   }
  163.   /*************************************************************************/
  164.   /*                                                                       */
  165.   /* ROLL[]:       ROLL top three elements                                 */
  166.   /* Opcode range: 0x8A                                                    */
  167.   /* Stack:        3 * StkElt --> 3 * StkElt                               */
  168.   /*                                                                       */
  169.   static void
  170.   Ins_ROLL( INS_ARG )
  171.   {
  172.     FT_Long  A, B, C;
  173.     FT_UNUSED_EXEC;
  174.     A = args[2];
  175.     B = args[1];
  176.     C = args[0];
  177.     args[2] = C;
  178.     args[1] = A;
  179.     args[0] = B;
  180.   }
  181.   /*************************************************************************/
  182.   /*                                                                       */
  183.   /* MANAGING THE FLOW OF CONTROL                                          */
  184.   /*                                                                       */
  185.   /*   Instructions appear in the specification's order.                   */
  186.   /*                                                                       */
  187.   /*************************************************************************/
  188.   static FT_Bool
  189.   SkipCode( EXEC_OP )
  190.   {
  191.     CUR.IP += CUR.length;
  192.     if ( CUR.IP < CUR.codeSize )
  193.     {
  194.       CUR.opcode = CUR.code[CUR.IP];
  195.       CUR.length = opcode_length[CUR.opcode];
  196.       if ( CUR.length < 0 )
  197.       {
  198.         if ( CUR.IP + 1 > CUR.codeSize )
  199.           goto Fail_Overflow;
  200.         CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
  201.       }
  202.       if ( CUR.IP + CUR.length <= CUR.codeSize )
  203.         return SUCCESS;
  204.     }
  205.   Fail_Overflow:
  206.     CUR.error = TT_Err_Code_Overflow;
  207.     return FAILURE;
  208.   }
  209.   /*************************************************************************/
  210.   /*                                                                       */
  211.   /* IF[]:         IF test                                                 */
  212.   /* Opcode range: 0x58                                                    */
  213.   /* Stack:        StkElt -->                                              */
  214.   /*                                                                       */
  215.   static void
  216.   Ins_IF( INS_ARG )
  217.   {
  218.     FT_Int   nIfs;
  219.     FT_Bool  Out;
  220.     if ( args[0] != 0 )
  221.       return;
  222.     nIfs = 1;
  223.     Out = 0;
  224.     do
  225.     {
  226.       if ( SKIP_Code() == FAILURE )
  227.         return;
  228.       switch ( CUR.opcode )
  229.       {
  230.       case 0x58:      /* IF */
  231.         nIfs++;
  232.         break;
  233.       case 0x1B:      /* ELSE */
  234.         Out = FT_BOOL( nIfs == 1 );
  235.         break;
  236.       case 0x59:      /* EIF */
  237.         nIfs--;
  238.         Out = FT_BOOL( nIfs == 0 );
  239.         break;
  240.       }
  241.     } while ( Out == 0 );
  242.   }
  243.   /*************************************************************************/
  244.   /*                                                                       */
  245.   /* ELSE[]:       ELSE                                                    */
  246.   /* Opcode range: 0x1B                                                    */
  247.   /* Stack:        -->                                                     */
  248.   /*                                                                       */
  249.   static void
  250.   Ins_ELSE( INS_ARG )
  251.   {
  252.     FT_Int  nIfs;
  253.     FT_UNUSED_ARG;
  254.     nIfs = 1;
  255.     do
  256.     {
  257.       if ( SKIP_Code() == FAILURE )
  258.         return;
  259.       switch ( CUR.opcode )
  260.       {
  261.       case 0x58:    /* IF */
  262.         nIfs++;
  263.         break;
  264.       case 0x59:    /* EIF */
  265.         nIfs--;
  266.         break;
  267.       }
  268.     } while ( nIfs != 0 );
  269.   }
  270.   /*************************************************************************/
  271.   /*                                                                       */
  272.   /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
  273.   /*                                                                       */
  274.   /*   Instructions appear in the specification's order.                   */
  275.   /*                                                                       */
  276.   /*************************************************************************/
  277.   /*************************************************************************/
  278.   /*                                                                       */
  279.   /* FDEF[]:       Function DEFinition                                     */
  280.   /* Opcode range: 0x2C                                                    */
  281.   /* Stack:        uint32 -->                                              */
  282.   /*                                                                       */
  283.   static void
  284.   Ins_FDEF( INS_ARG )
  285.   {
  286.     FT_ULong       n;
  287.     TT_DefRecord*  rec;
  288.     TT_DefRecord*  limit;
  289.     /* some font programs are broken enough to redefine functions! */
  290.     /* We will then parse the current table.                       */
  291.     rec   = CUR.FDefs;
  292.     limit = rec + CUR.numFDefs;
  293.     n     = args[0];
  294.     for ( ; rec < limit; rec++ )
  295.     {
  296.       if ( rec->opc == n )
  297.         break;
  298.     }
  299.     if ( rec == limit )
  300.     {
  301.       /* check that there is enough room for new functions */
  302.       if ( CUR.numFDefs >= CUR.maxFDefs )
  303.       {
  304.         CUR.error = TT_Err_Too_Many_Function_Defs;
  305.         return;
  306.       }
  307.       CUR.numFDefs++;
  308.     }
  309.     rec->range  = CUR.curRange;
  310.     rec->opc    = n;
  311.     rec->start  = CUR.IP + 1;
  312.     rec->active = TRUE;
  313.     if ( n > CUR.maxFunc )
  314.       CUR.maxFunc = n;
  315.     /* Now skip the whole function definition. */
  316.     /* We don't allow nested IDEFS & FDEFs.    */
  317.     while ( SKIP_Code() == SUCCESS )
  318.     {
  319.       switch ( CUR.opcode )
  320.       {
  321.       case 0x89:    /* IDEF */
  322.       case 0x2C:    /* FDEF */
  323.         CUR.error = TT_Err_Nested_DEFS;
  324.         return;
  325.       case 0x2D:   /* ENDF */
  326.         return;
  327.       }
  328.     }
  329.   }
  330.   /*************************************************************************/
  331.   /*                                                                       */
  332.   /* ENDF[]:       END Function definition                                 */
  333.   /* Opcode range: 0x2D                                                    */
  334.   /* Stack:        -->                                                     */
  335.   /*                                                                       */
  336.   static void
  337.   Ins_ENDF( INS_ARG )
  338.   {
  339.     TT_CallRec*  pRec;
  340.     FT_UNUSED_ARG;
  341.     if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
  342.     {
  343.       CUR.error = TT_Err_ENDF_In_Exec_Stream;
  344.       return;
  345.     }
  346.     CUR.callTop--;
  347.     pRec = &CUR.callStack[CUR.callTop];
  348.     pRec->Cur_Count--;
  349.     CUR.step_ins = FALSE;
  350.     if ( pRec->Cur_Count > 0 )
  351.     {
  352.       CUR.callTop++;
  353.       CUR.IP = pRec->Cur_Restart;
  354.     }
  355.     else
  356.       /* Loop through the current function */
  357.       INS_Goto_CodeRange( pRec->Caller_Range,
  358.                           pRec->Caller_IP );
  359.     /* Exit the current call frame.                      */
  360.     /* NOTE: If the last instruction of a program is a   */
  361.     /*       CALL or LOOPCALL, the return address is     */
  362.     /*       always out of the code range.  This is a    */
  363.     /*       valid address, and it is why we do not test */
  364.     /*       the result of Ins_Goto_CodeRange() here!    */
  365.   }
  366.   /*************************************************************************/
  367.   /*                                                                       */
  368.   /* CALL[]:       CALL function                                           */
  369.   /* Opcode range: 0x2B                                                    */
  370.   /* Stack:        uint32? -->                                             */
  371.   /*                                                                       */
  372.   static void
  373.   Ins_CALL( INS_ARG )
  374.   {
  375.     FT_ULong       F;
  376.     TT_CallRec*    pCrec;
  377.     TT_DefRecord*  def;
  378.     /* first of all, check the index */
  379.     F = args[0];
  380.     if ( BOUNDS( F, CUR.maxFunc + 1 ) )
  381.       goto Fail;
  382.     /* Except for some old Apple fonts, all functions in a TrueType */
  383.     /* font are defined in increasing order, starting from 0.  This */
  384.     /* means that we normally have                                  */
  385.     /*                                                              */
  386.     /*    CUR.maxFunc+1 == CUR.numFDefs                             */
  387.     /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
  388.     /*                                                              */
  389.     /* If this isn't true, we need to look up the function table.   */
  390.     def = CUR.FDefs + F;
  391.     if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
  392.     {
  393.       /* look up the FDefs table */
  394.       TT_DefRecord*  limit;
  395.       def   = CUR.FDefs;
  396.       limit = def + CUR.numFDefs;
  397.       while ( def < limit && def->opc != F )
  398.         def++;
  399.       if ( def == limit )
  400.         goto Fail;
  401.     }
  402.     /* check that the function is active */
  403.     if ( !def->active )
  404.       goto Fail;
  405.     /* check the call stack */
  406.     if ( CUR.callTop >= CUR.callSize )
  407.     {
  408.       CUR.error = TT_Err_Stack_Overflow;
  409.       return;
  410.     }
  411.     pCrec = CUR.callStack + CUR.callTop;
  412.     pCrec->Caller_Range = CUR.curRange;
  413.     pCrec->Caller_IP    = CUR.IP + 1;
  414.     pCrec->Cur_Count    = 1;
  415.     pCrec->Cur_Restart  = def->start;
  416.     CUR.callTop++;
  417.     INS_Goto_CodeRange( def->range,
  418.                         def->start );
  419.     CUR.step_ins = FALSE;
  420.     return;
  421.   Fail:
  422.     CUR.error = TT_Err_Invalid_Reference;
  423.   }
  424.   /*************************************************************************/
  425.   /*                                                                       */
  426.   /* LOOPCALL[]:   LOOP and CALL function                                  */
  427.   /* Opcode range: 0x2A                                                    */
  428.   /* Stack:        uint32? Eint16? -->                                     */
  429.   /*                                                                       */
  430.   static void
  431.   Ins_LOOPCALL( INS_ARG )
  432.   {
  433.     FT_ULong       F;
  434.     TT_CallRec*    pCrec;
  435.     TT_DefRecord*  def;
  436.     /* first of all, check the index */
  437.     F = args[1];
  438.     if ( BOUNDS( F, CUR.maxFunc + 1 ) )
  439.       goto Fail;
  440.     /* Except for some old Apple fonts, all functions in a TrueType */
  441.     /* font are defined in increasing order, starting from 0.  This */
  442.     /* means that we normally have                                  */
  443.     /*                                                              */
  444.     /*    CUR.maxFunc+1 == CUR.numFDefs                             */
  445.     /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
  446.     /*                                                              */
  447.     /* If this isn't true, we need to look up the function table.   */
  448.     def = CUR.FDefs + F;
  449.     if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
  450.     {
  451.       /* look up the FDefs table */
  452.       TT_DefRecord*  limit;
  453.       def   = CUR.FDefs;
  454.       limit = def + CUR.numFDefs;
  455.       while ( def < limit && def->opc != F )
  456.         def++;
  457.       if ( def == limit )
  458.         goto Fail;
  459.     }
  460.     /* check that the function is active */
  461.     if ( !def->active )
  462.       goto Fail;
  463.     /* check stack */
  464.     if ( CUR.callTop >= CUR.callSize )
  465.     {
  466.       CUR.error = TT_Err_Stack_Overflow;
  467.       return;
  468.     }
  469.     if ( args[0] > 0 )
  470.     {
  471.       pCrec = CUR.callStack + CUR.callTop;
  472.       pCrec->Caller_Range = CUR.curRange;
  473.       pCrec->Caller_IP    = CUR.IP + 1;
  474.       pCrec->Cur_Count    = (FT_Int)args[0];
  475.       pCrec->Cur_Restart  = def->start;
  476.       CUR.callTop++;
  477.       INS_Goto_CodeRange( def->range, def->start );
  478.       CUR.step_ins = FALSE;
  479.     }
  480.     return;
  481.   Fail:
  482.     CUR.error = TT_Err_Invalid_Reference;
  483.   }
  484.   /*************************************************************************/
  485.   /*                                                                       */
  486.   /* IDEF[]:       Instruction DEFinition                                  */
  487.   /* Opcode range: 0x89                                                    */
  488.   /* Stack:        Eint8 -->                                               */
  489.   /*                                                                       */
  490.   static void
  491.   Ins_IDEF( INS_ARG )
  492.   {
  493.     TT_DefRecord*  def;
  494.     TT_DefRecord*  limit;
  495.     /*  First of all, look for the same function in our table */
  496.     def   = CUR.IDefs;
  497.     limit = def + CUR.numIDefs;
  498.     for ( ; def < limit; def++ )
  499.       if ( def->opc == (FT_ULong)args[0] )
  500.         break;
  501.     if ( def == limit )
  502.     {
  503.       /* check that there is enough room for a new instruction */
  504.       if ( CUR.numIDefs >= CUR.maxIDefs )
  505.       {
  506.         CUR.error = TT_Err_Too_Many_Instruction_Defs;
  507.         return;
  508.       }
  509.       CUR.numIDefs++;
  510.     }
  511.     def->opc    = args[0];
  512.     def->start  = CUR.IP+1;
  513.     def->range  = CUR.curRange;
  514.     def->active = TRUE;
  515.     if ( (FT_ULong)args[0] > CUR.maxIns )
  516.       CUR.maxIns = args[0];
  517.     /* Now skip the whole function definition. */
  518.     /* We don't allow nested IDEFs & FDEFs.    */
  519.     while ( SKIP_Code() == SUCCESS )
  520.     {
  521.       switch ( CUR.opcode )
  522.       {
  523.       case 0x89:   /* IDEF */
  524.       case 0x2C:   /* FDEF */
  525.         CUR.error = TT_Err_Nested_DEFS;
  526.         return;
  527.       case 0x2D:   /* ENDF */
  528.         return;
  529.       }
  530.     }
  531.   }
  532.   /*************************************************************************/
  533.   /*                                                                       */
  534.   /* PUSHING DATA ONTO THE INTERPRETER STACK                               */
  535.   /*                                                                       */
  536.   /*   Instructions appear in the specification's order.                   */
  537.   /*                                                                       */
  538.   /*************************************************************************/
  539.   /*************************************************************************/
  540.   /*                                                                       */
  541.   /* NPUSHB[]:     PUSH N Bytes                                            */
  542.   /* Opcode range: 0x40                                                    */
  543.   /* Stack:        --> uint32...                                           */
  544.   /*                                                                       */
  545.   static void
  546.   Ins_NPUSHB( INS_ARG )
  547.   {
  548.     FT_UShort  L, K;
  549.     L = (FT_UShort)CUR.code[CUR.IP + 1];
  550.     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
  551.     {
  552.       CUR.error = TT_Err_Stack_Overflow;
  553.       return;
  554.     }
  555.     for ( K = 1; K <= L; K++ )
  556.       args[K - 1] = CUR.code[CUR.IP + K + 1];
  557.     CUR.new_top += L;
  558.   }
  559.   /*************************************************************************/
  560.   /*                                                                       */
  561.   /* NPUSHW[]:     PUSH N Words                                            */
  562.   /* Opcode range: 0x41                                                    */
  563.   /* Stack:        --> int32...                                            */
  564.   /*                                                                       */
  565.   static void
  566.   Ins_NPUSHW( INS_ARG )
  567.   {
  568.     FT_UShort  L, K;
  569.     L = (FT_UShort)CUR.code[CUR.IP + 1];
  570.     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
  571.     {
  572.       CUR.error = TT_Err_Stack_Overflow;
  573.       return;
  574.     }
  575.     CUR.IP += 2;
  576.     for ( K = 0; K < L; K++ )
  577.       args[K] = GET_ShortIns();
  578.     CUR.step_ins = FALSE;
  579.     CUR.new_top += L;
  580.   }
  581.   /*************************************************************************/
  582.   /*                                                                       */
  583.   /* PUSHB[abc]:   PUSH Bytes                                              */
  584.   /* Opcode range: 0xB0-0xB7                                               */
  585.   /* Stack:        --> uint32...                                           */
  586.   /*                                                                       */
  587.   static void
  588.   Ins_PUSHB( INS_ARG )
  589.   {
  590.     FT_UShort  L, K;
  591.     L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
  592.     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
  593.     {
  594.       CUR.error = TT_Err_Stack_Overflow;
  595.       return;
  596.     }
  597.     for ( K = 1; K <= L; K++ )
  598.       args[K - 1] = CUR.code[CUR.IP + K];
  599.   }
  600.   /*************************************************************************/
  601.   /*                                                                       */
  602.   /* PUSHW[abc]:   PUSH Words                                              */
  603.   /* Opcode range: 0xB8-0xBF                                               */
  604.   /* Stack:        --> int32...                                            */
  605.   /*                                                                       */
  606.   static void
  607.   Ins_PUSHW( INS_ARG )
  608.   {
  609.     FT_UShort  L, K;
  610.     L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
  611.     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
  612.     {
  613.       CUR.error = TT_Err_Stack_Overflow;
  614.       return;
  615.     }
  616.     CUR.IP++;
  617.     for ( K = 0; K < L; K++ )
  618.       args[K] = GET_ShortIns();
  619.     CUR.step_ins = FALSE;
  620.   }
  621.   /*************************************************************************/
  622.   /*                                                                       */
  623.   /* MANAGING THE GRAPHICS STATE                                           */
  624.   /*                                                                       */
  625.   /*  Instructions appear in the specs' order.                             */
  626.   /*                                                                       */
  627.   /*************************************************************************/
  628.   /*************************************************************************/
  629.   /*                                                                       */
  630.   /* GC[a]:        Get Coordinate projected onto                           */
  631.   /* Opcode range: 0x46-0x47                                               */
  632.   /* Stack:        uint32 --> f26.6                                        */
  633.   /*                                                                       */
  634.   /* BULLSHIT: Measures from the original glyph must be taken along the    */
  635.   /*           dual projection vector!                                     */
  636.   /*                                                                       */
  637.   static void
  638.   Ins_GC( INS_ARG )
  639.   {
  640.     FT_ULong    L;
  641.     FT_F26Dot6  R;
  642.     L = (FT_ULong)args[0];
  643.     if ( BOUNDS( L, CUR.zp2.n_points ) )
  644.     {
  645.       if ( CUR.pedantic_hinting )
  646.       {
  647.         CUR.error = TT_Err_Invalid_Reference;
  648.         return;
  649.       }
  650.       else
  651.         R = 0;
  652.     }
  653.     else
  654.     {
  655.       if ( CUR.opcode & 1 )
  656.         R = CUR_fast_dualproj( &CUR.zp2.org[L] );
  657.       else
  658.         R = CUR_fast_project( &CUR.zp2.cur[L] );
  659.     }
  660.     args[0] = R;
  661.   }
  662.   /*************************************************************************/
  663.   /*                                                                       */
  664.   /* SCFS[]:       Set Coordinate From Stack                               */
  665.   /* Opcode range: 0x48                                                    */
  666.   /* Stack:        f26.6 uint32 -->                                        */
  667.   /*                                                                       */
  668.   /* Formula:                                                              */
  669.   /*                                                                       */
  670.   /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */
  671.   /*                                                                       */
  672.   static void
  673.   Ins_SCFS( INS_ARG )
  674.   {
  675.     FT_Long    K;
  676.     FT_UShort  L;
  677.     L = (FT_UShort)args[0];
  678.     if ( BOUNDS( L, CUR.zp2.n_points ) )
  679.     {
  680.       if ( CUR.pedantic_hinting )
  681.         CUR.error = TT_Err_Invalid_Reference;
  682.       return;
  683.     }
  684.     K = CUR_fast_project( &CUR.zp2.cur[L] );
  685.     CUR_Func_move( &CUR.zp2, L, args[1] - K );
  686.     /* not part of the specs, but here for safety */
  687.     if ( CUR.GS.gep2 == 0 )
  688.       CUR.zp2.org[L] = CUR.zp2.cur[L];
  689.   }
  690.   /*************************************************************************/
  691.   /*                                                                       */
  692.   /* MD[a]:        Measure Distance                                        */
  693.   /* Opcode range: 0x49-0x4A                                               */
  694.   /* Stack:        uint32 uint32 --> f26.6                                 */
  695.   /*                                                                       */
  696.   /* BULLSHIT: Measure taken in the original glyph must be along the dual  */
  697.   /*           projection vector.                                          */
  698.   /*                                                                       */
  699.   /* Second BULLSHIT: Flag attributes are inverted!                        */
  700.   /*                  0 => measure distance in original outline            */
  701.   /*                  1 => measure distance in grid-fitted outline         */
  702.   /*                                                                       */
  703.   /* Third one: `zp0 - zp1', and not `zp2 - zp1!                           */
  704.   /*                                                                       */
  705.   static void
  706.   Ins_MD( INS_ARG )
  707.   {
  708.     FT_UShort   K, L;
  709.     FT_F26Dot6  D;
  710.     K = (FT_UShort)args[1];
  711.     L = (FT_UShort)args[0];
  712.     if( BOUNDS( L, CUR.zp0.n_points ) ||
  713.         BOUNDS( K, CUR.zp1.n_points ) )
  714.     {
  715.       if ( CUR.pedantic_hinting )
  716.       {
  717.         CUR.error = TT_Err_Invalid_Reference;
  718.         return;
  719.       }
  720.       D = 0;
  721.     }
  722.     else
  723.     {
  724.       if ( CUR.opcode & 1 )
  725.         D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
  726.       else
  727.         D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
  728.     }
  729.     args[0] = D;
  730.   }
  731.   /*************************************************************************/
  732.   /*                                                                       */
  733.   /* SDPVTL[a]:    Set Dual PVector to Line                                */
  734.   /* Opcode range: 0x86-0x87                                               */
  735.   /* Stack:        uint32 uint32 -->                                       */
  736.   /*                                                                       */
  737.   static void
  738.   Ins_SDPVTL( INS_ARG )
  739.   {
  740.     FT_Long    A, B, C;
  741.     FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */
  742.     p1 = (FT_UShort)args[1];
  743.     p2 = (FT_UShort)args[0];
  744.     if ( BOUNDS( p2, CUR.zp1.n_points ) ||
  745.          BOUNDS( p1, CUR.zp2.n_points ) )
  746.     {
  747.       if ( CUR.pedantic_hinting )
  748.         CUR.error = TT_Err_Invalid_Reference;
  749.       return;
  750.     }
  751.     {
  752.       FT_Vector* v1 = CUR.zp1.org + p2;
  753.       FT_Vector* v2 = CUR.zp2.org + p1;
  754.       A = v1->x - v2->x;
  755.       B = v1->y - v2->y;
  756.     }
  757.     if ( ( CUR.opcode & 1 ) != 0 )
  758.     {
  759.       C =  B;   /* counter clockwise rotation */
  760.       B =  A;
  761.       A = -C;
  762.     }
  763.     NORMalize( A, B, &CUR.GS.dualVector );
  764.     {
  765.       FT_Vector*  v1 = CUR.zp1.cur + p2;
  766.       FT_Vector*  v2 = CUR.zp2.cur + p1;
  767.       A = v1->x - v2->x;
  768.       B = v1->y - v2->y;
  769.     }
  770.     if ( ( CUR.opcode & 1 ) != 0 )
  771.     {
  772.       C =  B;   /* counter clockwise rotation */
  773.       B =  A;
  774.       A = -C;
  775.     }
  776.     NORMalize( A, B, &CUR.GS.projVector );
  777.     GUESS_VECTOR( freeVector );
  778.     COMPUTE_Funcs();
  779.   }
  780.   /*************************************************************************/
  781.   /*                                                                       */
  782.   /* SZP0[]:       Set Zone Pointer 0                                      */
  783.   /* Opcode range: 0x13                                                    */
  784.   /* Stack:        uint32 -->                                              */
  785.   /*                                                                       */
  786.   static void
  787.   Ins_SZP0( INS_ARG )
  788.   {
  789.     switch ( (FT_Int)args[0] )
  790.     {
  791.     case 0:
  792.       CUR.zp0 = CUR.twilight;
  793.       break;
  794.     case 1:
  795.       CUR.zp0 = CUR.pts;
  796.       break;
  797.     default:
  798.       if ( CUR.pedantic_hinting )
  799.         CUR.error = TT_Err_Invalid_Reference;
  800.       return;
  801.     }
  802.     CUR.GS.gep0 = (FT_UShort)args[0];
  803.   }
  804.   /*************************************************************************/
  805.   /*                                                                       */
  806.   /* SZP1[]:       Set Zone Pointer 1                                      */
  807.   /* Opcode range: 0x14                                                    */
  808.   /* Stack:        uint32 -->                                              */
  809.   /*                                                                       */
  810.   static void
  811.   Ins_SZP1( INS_ARG )
  812.   {
  813.     switch ( (FT_Int)args[0] )
  814.     {
  815.     case 0:
  816.       CUR.zp1 = CUR.twilight;
  817.       break;
  818.     case 1:
  819.       CUR.zp1 = CUR.pts;
  820.       break;
  821.     default:
  822.       if ( CUR.pedantic_hinting )
  823.         CUR.error = TT_Err_Invalid_Reference;
  824.       return;
  825.     }
  826.     CUR.GS.gep1 = (FT_UShort)args[0];
  827.   }
  828.   /*************************************************************************/
  829.   /*                                                                       */
  830.   /* SZP2[]:       Set Zone Pointer 2                                      */
  831.   /* Opcode range: 0x15                                                    */
  832.   /* Stack:        uint32 -->                                              */
  833.   /*                                                                       */
  834.   static void
  835.   Ins_SZP2( INS_ARG )
  836.   {
  837.     switch ( (FT_Int)args[0] )
  838.     {
  839.     case 0:
  840.       CUR.zp2 = CUR.twilight;
  841.       break;
  842.     case 1:
  843.       CUR.zp2 = CUR.pts;
  844.       break;
  845.     default:
  846.       if ( CUR.pedantic_hinting )
  847.         CUR.error = TT_Err_Invalid_Reference;
  848.       return;
  849.     }
  850.     CUR.GS.gep2 = (FT_UShort)args[0];
  851.   }
  852.   /*************************************************************************/
  853.   /*                                                                       */
  854.   /* SZPS[]:       Set Zone PointerS                                       */
  855.   /* Opcode range: 0x16                                                    */
  856.   /* Stack:        uint32 -->                                              */
  857.   /*                                                                       */
  858.   static void
  859.   Ins_SZPS( INS_ARG )
  860.   {
  861.     switch ( (FT_Int)args[0] )
  862.     {
  863.     case 0:
  864.       CUR.zp0 = CUR.twilight;
  865.       break;
  866.     case 1:
  867.       CUR.zp0 = CUR.pts;
  868.       break;
  869.     default:
  870.       if ( CUR.pedantic_hinting )
  871.         CUR.error = TT_Err_Invalid_Reference;
  872.       return;
  873.     }
  874.     CUR.zp1 = CUR.zp0;
  875.     CUR.zp2 = CUR.zp0;
  876.     CUR.GS.gep0 = (FT_UShort)args[0];
  877.     CUR.GS.gep1 = (FT_UShort)args[0];
  878.     CUR.GS.gep2 = (FT_UShort)args[0];
  879.   }
  880.   /*************************************************************************/
  881.   /*                                                                       */
  882.   /* INSTCTRL[]:   INSTruction ConTRoL                                     */
  883.   /* Opcode range: 0x8e                                                    */
  884.   /* Stack:        int32 int32 -->                                         */
  885.   /*                                                                       */
  886.   static void
  887.   Ins_INSTCTRL( INS_ARG )
  888.   {
  889.     FT_Long  K, L;
  890.     K = args[1];
  891.     L = args[0];
  892.     if ( K < 1 || K > 2 )
  893.     {
  894.       if ( CUR.pedantic_hinting )
  895.         CUR.error = TT_Err_Invalid_Reference;
  896.       return;
  897.     }
  898.     if ( L != 0 )
  899.         L = K;
  900.     CUR.GS.instruct_control = FT_BOOL(
  901.       ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
  902.   }
  903.   /*************************************************************************/
  904.   /*                                                                       */
  905.   /* SCANCTRL[]:   SCAN ConTRoL                                            */
  906.   /* Opcode range: 0x85                                                    */
  907.   /* Stack:        uint32? -->                                             */
  908.   /*                                                                       */
  909.   static void
  910.   Ins_SCANCTRL( INS_ARG )
  911.   {
  912.     FT_Int  A;
  913.     /* Get Threshold */
  914.     A = (FT_Int)( args[0] & 0xFF );
  915.     if ( A == 0xFF )
  916.     {
  917.       CUR.GS.scan_control = TRUE;
  918.       return;
  919.     }
  920.     else if ( A == 0 )
  921.     {
  922.       CUR.GS.scan_control = FALSE;
  923.       return;
  924.     }
  925.     A *= 64;
  926. #if 0
  927.     if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )
  928.       CUR.GS.scan_control = TRUE;
  929. #endif
  930.     if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
  931.       CUR.GS.scan_control = TRUE;
  932.     if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
  933.       CUR.GS.scan_control = TRUE;
  934. #if 0
  935.     if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )
  936.       CUR.GS.scan_control = FALSE;
  937. #endif
  938.     if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
  939.       CUR.GS.scan_control = FALSE;
  940.     if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
  941.       CUR.GS.scan_control = FALSE;
  942.   }
  943.   /*************************************************************************/
  944.   /*                                                                       */
  945.   /* SCANTYPE[]:   SCAN TYPE                                               */
  946.   /* Opcode range: 0x8D                                                    */
  947.   /* Stack:        uint32? -->                                             */
  948.   /*                                                                       */
  949.   static void
  950.   Ins_SCANTYPE( INS_ARG )
  951.   {
  952.     /* for compatibility with future enhancements, */
  953.     /* we must ignore new modes                    */
  954.     if ( args[0] >= 0 && args[0] <= 5 )
  955.     {
  956.       if ( args[0] == 3 )
  957.         args[0] = 2;
  958.       CUR.GS.scan_type = (FT_Int)args[0];
  959.     }
  960.   }
  961.   /*************************************************************************/
  962.   /*                                                                       */
  963.   /* MANAGING OUTLINES                                                     */
  964.   /*                                                                       */
  965.   /*   Instructions appear in the specification's order.                   */
  966.   /*                                                                       */
  967.   /*************************************************************************/
  968.   /*************************************************************************/
  969.   /*                                                                       */
  970.   /* FLIPPT[]:     FLIP PoinT                                              */
  971.   /* Opcode range: 0x80                                                    */
  972.   /* Stack:        uint32... -->                                           */
  973.   /*                                                                       */
  974.   static void
  975.   Ins_FLIPPT( INS_ARG )
  976.   {
  977.     FT_UShort  point;
  978.     FT_UNUSED_ARG;
  979.     if ( CUR.top < CUR.GS.loop )
  980.     {
  981.       CUR.error = TT_Err_Too_Few_Arguments;
  982.       return;
  983.     }
  984.     while ( CUR.GS.loop > 0 )
  985.     {
  986.       CUR.args--;
  987.       point = (FT_UShort)CUR.stack[CUR.args];
  988.       if ( BOUNDS( point, CUR.pts.n_points ) )
  989.       {
  990.         if ( CUR.pedantic_hinting )
  991.         {
  992.           CUR.error = TT_Err_Invalid_Reference;
  993.           return;
  994.         }
  995.       }
  996.       else
  997.         CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
  998.       CUR.GS.loop--;
  999.     }
  1000.     CUR.GS.loop = 1;
  1001.     CUR.new_top = CUR.args;
  1002.   }
  1003.   /*************************************************************************/
  1004.   /*                                                                       */
  1005.   /* FLIPRGON[]:   FLIP RanGe ON                                           */
  1006.   /* Opcode range: 0x81                                                    */
  1007.   /* Stack:        uint32 uint32 -->                                       */
  1008.   /*                                                                       */
  1009.   static void
  1010.   Ins_FLIPRGON( INS_ARG )
  1011.   {
  1012.     FT_UShort  I, K, L;
  1013.     K = (FT_UShort)args[1];
  1014.     L = (FT_UShort)args[0];
  1015.     if ( BOUNDS( K, CUR.pts.n_points ) ||
  1016.          BOUNDS( L, CUR.pts.n_points ) )
  1017.     {
  1018.       if ( CUR.pedantic_hinting )
  1019.         CUR.error = TT_Err_Invalid_Reference;
  1020.       return;
  1021.     }
  1022.     for ( I = L; I <= K; I++ )
  1023.       CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
  1024.   }
  1025.   /*************************************************************************/
  1026.   /*                                                                       */
  1027.   /* FLIPRGOFF:    FLIP RanGe OFF                                          */
  1028.   /* Opcode range: 0x82                                                    */
  1029.   /* Stack:        uint32 uint32 -->                                       */
  1030.   /*                                                                       */
  1031.   static void
  1032.   Ins_FLIPRGOFF( INS_ARG )
  1033.   {
  1034.     FT_UShort  I, K, L;
  1035.     K = (FT_UShort)args[1];
  1036.     L = (FT_UShort)args[0];
  1037.     if ( BOUNDS( K, CUR.pts.n_points ) ||
  1038.          BOUNDS( L, CUR.pts.n_points ) )
  1039.     {
  1040.       if ( CUR.pedantic_hinting )
  1041.         CUR.error = TT_Err_Invalid_Reference;
  1042.       return;
  1043.     }
  1044.     for ( I = L; I <= K; I++ )
  1045.       CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
  1046.   }
  1047.   static FT_Bool
  1048.   Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*   x,
  1049.                                        FT_F26Dot6*   y,
  1050.                                        TT_GlyphZone  zone,
  1051.                                        FT_UShort*    refp )
  1052.   {
  1053.     TT_GlyphZoneRec  zp;
  1054.     FT_UShort        p;
  1055.     FT_F26Dot6       d;
  1056.     if ( CUR.opcode & 1 )
  1057.     {
  1058.       zp = CUR.zp0;
  1059.       p  = CUR.GS.rp1;
  1060.     }
  1061.     else
  1062.     {
  1063.       zp = CUR.zp1;
  1064.       p  = CUR.GS.rp2;
  1065.     }
  1066.     if ( BOUNDS( p, zp.n_points ) )
  1067.     {
  1068.       if ( CUR.pedantic_hinting )
  1069.         CUR.error = TT_Err_Invalid_Reference;
  1070.       *refp = 0;
  1071.       return FAILURE;
  1072.     }
  1073.     *zone = zp;
  1074.     *refp = p;
  1075.     d = CUR_Func_project( zp.cur + p, zp.org + p );
  1076. #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
  1077.     if ( CUR.face->unpatented_hinting )
  1078.     {
  1079.       if ( CUR.GS.both_x_axis )
  1080.       {
  1081.         *x = d;
  1082.         *y = 0;
  1083.       }
  1084.       else
  1085.       {
  1086.         *x = 0;
  1087.         *y = d;
  1088.       }
  1089.     }
  1090.     else
  1091. #endif
  1092.     {
  1093.       *x = TT_MULDIV( d,
  1094.                       (FT_Long)CUR.GS.freeVector.x * 0x10000L,
  1095.                       CUR.F_dot_P );
  1096.       *y = TT_MULDIV( d,
  1097.                       (FT_Long)CUR.GS.freeVector.y * 0x10000L,
  1098.                       CUR.F_dot_P );
  1099.     }
  1100.     return SUCCESS;
  1101.   }
  1102.   static void
  1103.   Move_Zp2_Point( EXEC_OP_ FT_UShort   point,
  1104.                            FT_F26Dot6  dx,
  1105.                            FT_F26Dot6  dy,
  1106.                            FT_Bool     touch )
  1107.   {
  1108. #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
  1109.     if ( CUR.face->unpatented_hinting )
  1110.     {
  1111.       if ( CUR.GS.both_x_axis )
  1112.       {
  1113.         CUR.zp2.cur[point].x += dx;
  1114.         if ( touch )
  1115.           CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
  1116.       }
  1117.       else
  1118.       {
  1119.         CUR.zp2.cur[point].y += dy;
  1120.         if ( touch )
  1121.           CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
  1122.       }
  1123.       return;
  1124.     }
  1125. #endif
  1126.     if ( CUR.GS.freeVector.x != 0 )
  1127.     {
  1128.       CUR.zp2.cur[point].x += dx;
  1129.       if ( touch )
  1130.         CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
  1131.     }
  1132.     if ( CUR.GS.freeVector.y != 0 )
  1133.     {
  1134.       CUR.zp2.cur[point].y += dy;
  1135.       if ( touch )
  1136.         CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
  1137.     }
  1138.   }
  1139.   /*************************************************************************/
  1140.   /*                                                                       */
  1141.   /* SHP[a]:       SHift Point by the last point                           */
  1142.   /* Opcode range: 0x32-0x33                                               */
  1143.   /* Stack:        uint32... -->                                           */
  1144.   /*                                                                       */
  1145.   static void
  1146.   Ins_SHP( INS_ARG )
  1147.   {
  1148.     TT_GlyphZoneRec  zp;
  1149.     FT_UShort        refp;
  1150.     FT_F26Dot6       dx,
  1151.                      dy;
  1152.     FT_UShort        point;
  1153.     FT_UNUSED_ARG;
  1154.     if ( CUR.top < CUR.GS.loop )
  1155.     {
  1156.       CUR.error = TT_Err_Invalid_Reference;
  1157.       return;
  1158.     }
  1159.     if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
  1160.       return;
  1161.     while ( CUR.GS.loop > 0 )
  1162.     {
  1163.       CUR.args--;
  1164.       point = (FT_UShort)CUR.stack[CUR.args];
  1165.       if ( BOUNDS( point, CUR.zp2.n_points ) )
  1166.       {
  1167.         if ( CUR.pedantic_hinting )
  1168.         {
  1169.           CUR.error = TT_Err_Invalid_Reference;
  1170.           return;
  1171.         }
  1172.       }
  1173.       else
  1174.         /* XXX: UNDOCUMENTED! SHP touches the points */
  1175.         MOVE_Zp2_Point( point, dx, dy, TRUE );
  1176.       CUR.GS.loop--;
  1177.     }
  1178.     CUR.GS.loop = 1;
  1179.     CUR.new_top = CUR.args;
  1180.   }
  1181.   /*************************************************************************/
  1182.   /*                                                                       */
  1183.   /* SHC[a]:       SHift Contour                                           */
  1184.   /* Opcode range: 0x34-35                                                 */
  1185.   /* Stack:        uint32 -->                                              */
  1186.   /*                                                                       */
  1187.   static void
  1188.   Ins_SHC( INS_ARG )
  1189.   {
  1190.     TT_GlyphZoneRec zp;
  1191.     FT_UShort       refp;
  1192.     FT_F26Dot6      dx,
  1193.                     dy;
  1194.     FT_Short        contour;
  1195.     FT_UShort       first_point, last_point, i;
  1196.     contour = (FT_UShort)args[0];
  1197.     if ( BOUNDS( contour, CUR.pts.n_contours ) )
  1198.     {
  1199.       if ( CUR.pedantic_hinting )
  1200.         CUR.error = TT_Err_Invalid_Reference;
  1201.       return;
  1202.     }
  1203.     if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
  1204.       return;
  1205.     if ( contour == 0 )
  1206.       first_point = 0;
  1207.     else
  1208.       first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
  1209.                                  CUR.pts.first_point );
  1210.     last_point = (FT_UShort)( CUR.pts.contours[contour] -
  1211.                               CUR.pts.first_point );
  1212.     /* XXX: this is probably wrong... at least it prevents memory */
  1213.     /*      corruption when zp2 is the twilight zone              */
  1214.     if ( last_point > CUR.zp2.n_points )
  1215.     {
  1216.       if ( CUR.zp2.n_points > 0 )
  1217.         last_point = (FT_UShort)(CUR.zp2.n_points - 1);
  1218.       else
  1219.         last_point = 0;
  1220.     }
  1221.     /* XXX: UNDOCUMENTED! SHC touches the points */
  1222.     for ( i = first_point; i <= last_point; i++ )
  1223.     {
  1224.       if ( zp.cur != CUR.zp2.cur || refp != i )
  1225.         MOVE_Zp2_Point( i, dx, dy, TRUE );
  1226.     }
  1227.   }
  1228.   /*************************************************************************/
  1229.   /*                                                                       */
  1230.   /* SHZ[a]:       SHift Zone                                              */
  1231.   /* Opcode range: 0x36-37                                                 */
  1232.   /* Stack:        uint32 -->                                              */
  1233.   /*                                                                       */
  1234.   static void
  1235.   Ins_SHZ( INS_ARG )
  1236.   {
  1237.     TT_GlyphZoneRec zp;
  1238.     FT_UShort       refp;
  1239.     FT_F26Dot6      dx,
  1240.                     dy;
  1241.     FT_UShort       last_point, i;
  1242.     if ( BOUNDS( args[0], 2 ) )
  1243.     {
  1244.       if ( CUR.pedantic_hinting )
  1245.         CUR.error = TT_Err_Invalid_Reference;
  1246.       return;
  1247.     }
  1248.     if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
  1249.       return;
  1250.     /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points.  */
  1251.     /*      Twilight zone has no contours, so use `n_points'.   */
  1252.     /*      Normal zone's `n_points' includes phantoms, so must */
  1253.     /*      use end of last contour.                            */
  1254.     if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
  1255.       last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
  1256.     else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
  1257.       last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
  1258.     else
  1259.       last_point = 0;
  1260.     /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
  1261.     for ( i = 0; i <= last_point; i++ )
  1262.     {
  1263.       if ( zp.cur != CUR.zp2.cur || refp != i )
  1264.         MOVE_Zp2_Point( i, dx, dy, FALSE );
  1265.     }
  1266.   }
  1267.   /*************************************************************************/
  1268.   /*                                                                       */
  1269.   /* SHPIX[]:      SHift points by a PIXel amount                          */
  1270.   /* Opcode range: 0x38                                                    */
  1271.   /* Stack:        f26.6 uint32... -->                                     */
  1272.   /*                                                                       */
  1273.   static void
  1274.   Ins_SHPIX( INS_ARG )
  1275.   {
  1276.     FT_F26Dot6  dx, dy;
  1277.     FT_UShort   point;
  1278.     if ( CUR.top < CUR.GS.loop + 1 )
  1279.     {
  1280.       CUR.error = TT_Err_Invalid_Reference;
  1281.       return;
  1282.     }
  1283. #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
  1284.     if ( CUR.face->unpatented_hinting )
  1285.     {
  1286.       if ( CUR.GS.both_x_axis )
  1287.       {
  1288.         dx = TT_MulFix14( args[0], 0x4000 );
  1289.         dy = 0;
  1290.       }
  1291.       else
  1292.       {
  1293.         dx = 0;
  1294.         dy = TT_MulFix14( args[0], 0x4000 );
  1295.       }
  1296.     }
  1297.     else
  1298. #endif
  1299.     {
  1300.       dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
  1301.       dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
  1302.     }
  1303.     while ( CUR.GS.loop > 0 )
  1304.     {
  1305.       CUR.args--;
  1306.       point = (FT_UShort)CUR.stack[CUR.args];
  1307.       if ( BOUNDS( point, CUR.zp2.n_points ) )
  1308.       {
  1309.         if ( CUR.pedantic_hinting )
  1310.         {
  1311.           CUR.error = TT_Err_Invalid_Reference;
  1312.           return;
  1313.         }
  1314.       }
  1315.       else
  1316.         MOVE_Zp2_Point( point, dx, dy, TRUE );
  1317.       CUR.GS.loop--;
  1318.     }
  1319.     CUR.GS.loop = 1;
  1320.     CUR.new_top = CUR.args;
  1321.   }
  1322.   /*************************************************************************/
  1323.   /*                                                                       */
  1324.   /* MSIRP[a]:     Move Stack Indirect Relative Position                   */
  1325.   /* Opcode range: 0x3A-0x3B                                               */
  1326.   /* Stack:        f26.6 uint32 -->                                        */
  1327.   /*                                                                       */
  1328.   static void
  1329.   Ins_MSIRP( INS_ARG )
  1330.   {
  1331.     FT_UShort   point;
  1332.     FT_F26Dot6  distance;
  1333.     point = (FT_UShort)args[0];
  1334.     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
  1335.          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
  1336.     {
  1337.       if ( CUR.pedantic_hinting )
  1338.         CUR.error = TT_Err_Invalid_Reference;
  1339.       return;
  1340.     }
  1341.     /* XXX: UNDOCUMENTED! behaviour */
  1342.     if ( CUR.GS.gep1 == 0 )   /* if the point that is to be moved */
  1343.                               /* is in twilight zone              */
  1344.     {
  1345.       CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
  1346.       CUR_Func_move_orig( &CUR.zp1, point, args[1] );
  1347.       CUR.zp1.cur[point] = CUR.zp1.org[point];
  1348.     }
  1349.     distance = CUR_Func_project( CUR.zp1.cur + point,
  1350.                                  CUR.zp0.cur + CUR.GS.rp0 );
  1351.     CUR_Func_move( &CUR.zp1, point, args[1] - distance );
  1352.     CUR.GS.rp1 = CUR.GS.rp0;
  1353.     CUR.GS.rp2 = point;
  1354.     if ( ( CUR.opcode & 1 ) != 0 )
  1355.       CUR.GS.rp0 = point;
  1356.   }
  1357.   /*************************************************************************/
  1358.   /*                                                                       */
  1359.   /* MDAP[a]:      Move Direct Absolute Point                              */
  1360.   /* Opcode range: 0x2E-0x2F                                               */
  1361.   /* Stack:        uint32 -->                                              */
  1362.   /*                                                                       */
  1363.   static void
  1364.   Ins_MDAP( INS_ARG )
  1365.   {
  1366.     FT_UShort   point;
  1367.     FT_F26Dot6  cur_dist,
  1368.                 distance;
  1369.     point = (FT_UShort)args[0];
  1370.     if ( BOUNDS( point, CUR.zp0.n_points ) )
  1371.     {
  1372.       if ( CUR.pedantic_hinting )
  1373.         CUR.error = TT_Err_Invalid_Reference;
  1374.       return;
  1375.     }
  1376.     /* XXX: Is there some undocumented feature while in the */
  1377.     /*      twilight zone? ?                                */
  1378.     if ( ( CUR.opcode & 1 ) != 0 )
  1379.     {
  1380.       cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
  1381.       distance = CUR_Func_round( cur_dist,
  1382.                                  CUR.tt_metrics.compensations[0] ) - cur_dist;
  1383.     }
  1384.     else
  1385.       distance = 0;
  1386.     CUR_Func_move( &CUR.zp0, point, distance );
  1387.     CUR.GS.rp0 = point;
  1388.     CUR.GS.rp1 = point;
  1389.   }
  1390.   /*************************************************************************/
  1391.   /*                                                                       */
  1392.   /* MIAP[a]:      Move Indirect Absolute Point                            */
  1393.   /* Opcode range: 0x3E-0x3F                                               */
  1394.   /* Stack:        uint32 uint32 -->                                       */
  1395.   /*                                                                       */
  1396.   static void
  1397.   Ins_MIAP( INS_ARG )
  1398.   {
  1399.     FT_ULong    cvtEntry;
  1400.     FT_UShort   point;
  1401.     FT_F26Dot6  distance,
  1402.                 org_dist;
  1403.     cvtEntry = (FT_ULong)args[1];
  1404.     point    = (FT_UShort)args[0];
  1405.     if ( BOUNDS( point,    CUR.zp0.n_points ) ||
  1406.          BOUNDS( cvtEntry, CUR.cvtSize )      )
  1407.     {
  1408.       if ( CUR.pedantic_hinting )
  1409.         CUR.error = TT_Err_Invalid_Reference;
  1410.       return;
  1411.     }
  1412.     /* XXX: UNDOCUMENTED!                                */
  1413.     /*                                                   */
  1414.     /* The behaviour of an MIAP instruction is quite     */
  1415.     /* different when used in the twilight zone.         */
  1416.     /*                                                   */
  1417.     /* First, no control value cut-in test is performed  */
  1418.     /* as it would fail anyway.  Second, the original    */
  1419.     /* point, i.e. (org_x,org_y) of zp0.point, is set    */
  1420.     /* to the absolute, unrounded distance found in      */
  1421.     /* the CVT.                                          */
  1422.     /*                                                   */
  1423.     /* This is used in the CVT programs of the Microsoft */
  1424.     /* fonts Arial, Times, etc., in order to re-adjust   */
  1425.     /* some key font heights.  It allows the use of the  */
  1426.     /* IP instruction in the twilight zone, which        */
  1427.     /* otherwise would be `illegal' according to the     */
  1428.     /* specification.                                    */
  1429.     /*                                                   */
  1430.     /* We implement it with a special sequence for the   */
  1431.     /* twilight zone.  This is a bad hack, but it seems  */
  1432.     /* to work.                                          */
  1433.     distance = CUR_Func_read_cvt( cvtEntry );
  1434.     if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
  1435.     {
  1436.       CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );
  1437.       CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ),
  1438.       CUR.zp0.cur[point]   = CUR.zp0.org[point];
  1439.     }
  1440.     org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
  1441.     if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */
  1442.     {
  1443.       if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
  1444.         distance = org_dist;
  1445.       distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
  1446.     }
  1447.     CUR_Func_move( &CUR.zp0, point, distance - org_dist );
  1448.     CUR.GS.rp0 = point;
  1449.     CUR.GS.rp1 = point;
  1450.   }
  1451.   /*************************************************************************/
  1452.   /*                                                                       */
  1453.   /* MDRP[abcde]:  Move Direct Relative Point                              */
  1454.   /* Opcode range: 0xC0-0xDF                                               */
  1455.   /* Stack:        uint32 -->                                              */
  1456.   /*                                                                       */
  1457.   static void
  1458.   Ins_MDRP( INS_ARG )
  1459.   {
  1460.     FT_UShort   point;
  1461.     FT_F26Dot6  org_dist, distance;
  1462.     point = (FT_UShort)args[0];
  1463.     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
  1464.          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
  1465.     {
  1466.       if ( CUR.pedantic_hinting )
  1467.         CUR.error = TT_Err_Invalid_Reference;
  1468.       return;
  1469.     }
  1470.     /* XXX: Is there some undocumented feature while in the */
  1471.     /*      twilight zone?                                  */
  1472.     /* XXX: UNDOCUMENTED: twilight zone special case */
  1473.     if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
  1474.     {
  1475.       FT_Vector*  vec1 = &CUR.zp1.org[point];
  1476.       FT_Vector*  vec2 = &CUR.zp0.org[CUR.GS.rp0];
  1477.       org_dist = CUR_Func_dualproj( vec1, vec2 );
  1478.     }
  1479.     else
  1480.     {
  1481.       FT_Vector*  vec1 = &CUR.zp1.orus[point];
  1482.       FT_Vector*  vec2 = &CUR.zp0.orus[CUR.GS.rp0];
  1483.       if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
  1484.       {
  1485.         /* this should be faster */
  1486.         org_dist = CUR_Func_dualproj( vec1, vec2 );
  1487.         org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
  1488.       }
  1489.       else
  1490.       {
  1491.         FT_Vector  vec;
  1492.         vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
  1493.         vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
  1494.         org_dist = CUR_fast_dualproj( &vec );
  1495.       }
  1496.     }
  1497.     /* single width cut-in test */
  1498.     if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
  1499.          CUR.GS.single_width_cutin )
  1500.     {
  1501.       if ( org_dist >= 0 )
  1502.         org_dist = CUR.GS.single_width_value;
  1503.       else
  1504.         org_dist = -CUR.GS.single_width_value;
  1505.     }
  1506.     /* round flag */
  1507.     if ( ( CUR.opcode & 4 ) != 0 )
  1508.       distance = CUR_Func_round(
  1509.                    org_dist,
  1510.                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
  1511.     else
  1512.       distance = ROUND_None(
  1513.                    org_dist,
  1514.                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
  1515.     /* minimum distance flag */
  1516.     if ( ( CUR.opcode & 8 ) != 0 )
  1517.     {
  1518.       if ( org_dist >= 0 )
  1519.       {
  1520.         if ( distance < CUR.GS.minimum_distance )
  1521.           distance = CUR.GS.minimum_distance;
  1522.       }
  1523.       else
  1524.       {
  1525.         if ( distance > -CUR.GS.minimum_distance )
  1526.           distance = -CUR.GS.minimum_distance;
  1527.       }
  1528.     }
  1529.     /* now move the point */
  1530.     org_dist = CUR_Func_project( CUR.zp1.cur + point,
  1531.                                  CUR.zp0.cur + CUR.GS.rp0 );
  1532.     CUR_Func_move( &CUR.zp1, point, distance - org_dist );
  1533.     CUR.GS.rp1 = CUR.GS.rp0;
  1534.     CUR.GS.rp2 = point;
  1535.     if ( ( CUR.opcode & 16 ) != 0 )
  1536.       CUR.GS.rp0 = point;
  1537.   }
  1538.   /*************************************************************************/
  1539.   /*                                                                       */
  1540.   /* MIRP[abcde]:  Move Indirect Relative Point                            */
  1541.   /* Opcode range: 0xE0-0xFF                                               */
  1542.   /* Stack:        int32? uint32 -->                                       */
  1543.   /*                                                                       */
  1544.   static void
  1545.   Ins_MIRP( INS_ARG )
  1546.   {
  1547.     FT_UShort   point;
  1548.     FT_ULong    cvtEntry;
  1549.     FT_F26Dot6  cvt_dist,
  1550.                 distance,
  1551.                 cur_dist,
  1552.                 org_dist;
  1553.     point    = (FT_UShort)args[0];
  1554.     cvtEntry = (FT_ULong)( args[1] + 1 );
  1555.     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
  1556.     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
  1557.          BOUNDS( cvtEntry,   CUR.cvtSize + 1 )  ||
  1558.          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
  1559.     {
  1560.       if ( CUR.pedantic_hinting )
  1561.         CUR.error = TT_Err_Invalid_Reference;
  1562.       return;
  1563.     }
  1564.     if ( !cvtEntry )
  1565.       cvt_dist = 0;
  1566.     else
  1567.       cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
  1568.     /* single width test */
  1569.     if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
  1570.          CUR.GS.single_width_cutin )
  1571.     {
  1572.       if ( cvt_dist >= 0 )
  1573.         cvt_dist =  CUR.GS.single_width_value;
  1574.       else
  1575.         cvt_dist = -CUR.GS.single_width_value;
  1576.     }
  1577.     /* XXX: UNDOCUMENTED! -- twilight zone */
  1578.     if ( CUR.GS.gep1 == 0 )
  1579.     {
  1580.       CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
  1581.                              TT_MulFix14( cvt_dist, CUR.GS.freeVector.x );
  1582.       CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
  1583.                              TT_MulFix14( cvt_dist, CUR.GS.freeVector.y );
  1584.       CUR.zp1.cur[point] = CUR.zp0.cur[point];
  1585.     }
  1586.     org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
  1587.                                   &CUR.zp0.org[CUR.GS.rp0] );
  1588.     cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
  1589.                                   &CUR.zp0.cur[CUR.GS.rp0] );
  1590.     /* auto-flip test */
  1591.     if ( CUR.GS.auto_flip )
  1592.     {
  1593.       if ( ( org_dist ^ cvt_dist ) < 0 )
  1594.         cvt_dist = -cvt_dist;
  1595.     }
  1596.     /* control value cutin and round */
  1597.     if ( ( CUR.opcode & 4 ) != 0 )
  1598.     {
  1599.       /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
  1600.       /*      refer to the same zone.                                  */
  1601.       if ( CUR.GS.gep0 == CUR.GS.gep1 )
  1602.         if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
  1603.           cvt_dist = org_dist;
  1604.       distance = CUR_Func_round(
  1605.                    cvt_dist,
  1606.                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
  1607.     }
  1608.     else
  1609.       distance = ROUND_None(
  1610.                    cvt_dist,
  1611.                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
  1612.     /* minimum distance test */
  1613.     if ( ( CUR.opcode & 8 ) != 0 )
  1614.     {
  1615.       if ( org_dist >= 0 )
  1616.       {
  1617.         if ( distance < CUR.GS.minimum_distance )
  1618.           distance = CUR.GS.minimum_distance;
  1619.       }
  1620.       else
  1621.       {
  1622.         if ( distance > -CUR.GS.minimum_distance )
  1623.           distance = -CUR.GS.minimum_distance;
  1624.       }
  1625.     }
  1626.     CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
  1627.     CUR.GS.rp1 = CUR.GS.rp0;
  1628.     if ( ( CUR.opcode & 16 ) != 0 )
  1629.       CUR.GS.rp0 = point;
  1630.     /* XXX: UNDOCUMENTED! */
  1631.     CUR.GS.rp2 = point;
  1632.   }
  1633.   /*************************************************************************/
  1634.   /*                                                                       */
  1635.   /* ALIGNRP[]:    ALIGN Relative Point                                    */
  1636.   /* Opcode range: 0x3C                                                    */
  1637.   /* Stack:        uint32 uint32... -->                                    */
  1638.   /*                                                                       */
  1639.   static void
  1640.   Ins_ALIGNRP( INS_ARG )
  1641.   {
  1642.     FT_UShort   point;
  1643.     FT_F26Dot6  distance;
  1644.     FT_UNUSED_ARG;
  1645.     if ( CUR.top < CUR.GS.loop ||
  1646.          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
  1647.     {
  1648.       if ( CUR.pedantic_hinting )
  1649.         CUR.error = TT_Err_Invalid_Reference;
  1650.       return;
  1651.     }
  1652.     while ( CUR.GS.loop > 0 )
  1653.     {
  1654.       CUR.args--;
  1655.       point = (FT_UShort)CUR.stack[CUR.args];
  1656.       if ( BOUNDS( point, CUR.zp1.n_points ) )
  1657.       {
  1658.         if ( CUR.pedantic_hinting )
  1659.         {
  1660.           CUR.error = TT_Err_Invalid_Reference;
  1661.           return;
  1662.         }
  1663.       }
  1664.       else
  1665.       {
  1666.         distance = CUR_Func_project( CUR.zp1.cur + point,
  1667.                                      CUR.zp0.cur + CUR.GS.rp0 );
  1668.         CUR_Func_move( &CUR.zp1, point, -distance );
  1669.       }
  1670.       CUR.GS.loop--;
  1671.     }
  1672.     CUR.GS.loop = 1;
  1673.     CUR.new_top = CUR.args;
  1674.   }
  1675.   /*************************************************************************/
  1676.   /*                                                                       */
  1677.   /* ISECT[]:      moves point to InterSECTion                             */
  1678.   /* Opcode range: 0x0F                                                    */
  1679.   /* Stack:        5 * uint32 -->                                          */
  1680.   /*                                                                       */
  1681.   static void
  1682.   Ins_ISECT( INS_ARG )
  1683.   {
  1684.     FT_UShort   point,
  1685.                 a0, a1,
  1686.                 b0, b1;
  1687.     FT_F26Dot6  discriminant;
  1688.     FT_F26Dot6  dx,  dy,
  1689.                 dax, day,
  1690.                 dbx, dby;
  1691.     FT_F26Dot6  val;
  1692.     FT_Vector   R;
  1693.     point = (FT_UShort)args[0];
  1694.     a0 = (FT_UShort)args[1];
  1695.     a1 = (FT_UShort)args[2];
  1696.     b0 = (FT_UShort)args[3];
  1697.     b1 = (FT_UShort)args[4];
  1698.     if ( BOUNDS( b0, CUR.zp0.n_points )  ||
  1699.          BOUNDS( b1, CUR.zp0.n_points )  ||
  1700.          BOUNDS( a0, CUR.zp1.n_points )  ||
  1701.          BOUNDS( a1, CUR.zp1.n_points )  ||
  1702.          BOUNDS( point, CUR.zp2.n_points ) )
  1703.     {
  1704.       if ( CUR.pedantic_hinting )
  1705.         CUR.error = TT_Err_Invalid_Reference;
  1706.       return;
  1707.     }
  1708.     dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
  1709.     dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
  1710.     dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
  1711.     day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
  1712.     dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
  1713.     dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
  1714.     CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
  1715.     discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
  1716.                    TT_MULDIV( day, dbx, 0x40 );
  1717.     if ( FT_ABS( discriminant ) >= 0x40 )
  1718.     {
  1719.       val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
  1720.       R.x = TT_MULDIV( val, dax, discriminant );
  1721.       R.y = TT_MULDIV( val, day, discriminant );
  1722.       CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
  1723.       CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
  1724.     }
  1725.     else
  1726.     {
  1727.       /* else, take the middle of the middles of A and B */
  1728.       CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
  1729.                                CUR.zp1.cur[a1].x +
  1730.                                CUR.zp0.cur[b0].x +
  1731.                                CUR.zp0.cur[b1].x ) / 4;
  1732.       CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
  1733.                                CUR.zp1.cur[a1].y +
  1734.                                CUR.zp0.cur[b0].y +
  1735.                                CUR.zp0.cur[b1].y ) / 4;
  1736.     }
  1737.   }
  1738.   /*************************************************************************/
  1739.   /*                                                                       */
  1740.   /* ALIGNPTS[]:   ALIGN PoinTS                                            */
  1741.   /* Opcode range: 0x27                                                    */
  1742.   /* Stack:        uint32 uint32 -->                                       */
  1743.   /*                                                                       */
  1744.   static void
  1745.   Ins_ALIGNPTS( INS_ARG )
  1746.   {
  1747.     FT_UShort   p1, p2;
  1748.     FT_F26Dot6  distance;
  1749.     p1 = (FT_UShort)args[0];
  1750.     p2 = (FT_UShort)args[1];
  1751.     if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
  1752.          BOUNDS( args[1], CUR.zp0.n_points ) )
  1753.     {
  1754.       if ( CUR.pedantic_hinting )
  1755.         CUR.error = TT_Err_Invalid_Reference;
  1756.       return;
  1757.     }
  1758.     distance = CUR_Func_project( CUR.zp0.cur + p2,
  1759.                                  CUR.zp1.cur + p1 ) / 2;
  1760.     CUR_Func_move( &CUR.zp1, p1, distance );
  1761.     CUR_Func_move( &CUR.zp0, p2, -distance );
  1762.   }
  1763.   /*************************************************************************/
  1764.   /*                                                                       */
  1765.   /* IP[]:         Interpolate Point                                       */
  1766.   /* Opcode range: 0x39                                                    */
  1767.   /* Stack:        uint32... -->                                           */
  1768.   /*                                                                       */
  1769.   /* SOMETIMES, DUMBER CODE IS BETTER CODE */
  1770.   static void
  1771.   Ins_IP( INS_ARG )
  1772.   {
  1773.     FT_F26Dot6  old_range, cur_range;
  1774.     FT_Vector*  orus_base;
  1775.     FT_Vector*  cur_base;
  1776.     FT_Int      twilight;
  1777.     FT_UNUSED_ARG;
  1778.     if ( CUR.top < CUR.GS.loop )
  1779.     {
  1780.       CUR.error = TT_Err_Invalid_Reference;
  1781.       return;
  1782.     }
  1783.     /*
  1784.      * We need to deal in a special way with the twilight zone.
  1785.      * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
  1786.      * for every n.
  1787.      */
  1788.     twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
  1789.     if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
  1790.     {
  1791.       if ( CUR.pedantic_hinting )
  1792.         CUR.error = TT_Err_Invalid_Reference;
  1793.       return;
  1794.     }
  1795.     if ( twilight )
  1796.       orus_base = &CUR.zp0.org[CUR.GS.rp1];
  1797.     else
  1798.       orus_base = &CUR.zp0.orus[CUR.GS.rp1];
  1799.     cur_base = &CUR.zp0.cur[CUR.GS.rp1];
  1800.     /* XXX: There are some glyphs in some braindead but popular */
  1801.     /*      fonts out there (e.g. [aeu]grave in monotype.ttf)   */
  1802.     /*      calling IP[] with bad values of rp[12].             */
  1803.     /*      Do something sane when this odd thing happens.      */
  1804.     if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
  1805.          BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
  1806.     {
  1807.       old_range = 0;
  1808.       cur_range = 0;
  1809.     }
  1810.     else
  1811.     {
  1812.       if ( twilight )
  1813.         old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
  1814.                                        orus_base );
  1815.       else
  1816.         old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
  1817.                                        orus_base );
  1818.       cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
  1819.     }
  1820.     for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
  1821.     {
  1822.       FT_UInt     point = (FT_UInt)CUR.stack[--CUR.args];
  1823.       FT_F26Dot6  org_dist, cur_dist, new_dist;
  1824.       /* check point bounds */
  1825.       if ( BOUNDS( point, CUR.zp2.n_points ) )
  1826.       {
  1827.         if ( CUR.pedantic_hinting )
  1828.         {
  1829.           CUR.error = TT_Err_Invalid_Reference;
  1830.           return;
  1831.         }
  1832.         continue;
  1833.       }
  1834.       if ( twilight )
  1835.         org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
  1836.       else
  1837.         org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
  1838.       cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
  1839.       new_dist = ( old_range != 0 )
  1840.                    ? TT_MULDIV( org_dist, cur_range, old_range )
  1841.                    : cur_dist;
  1842.       CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
  1843.     }
  1844.     CUR.GS.loop = 1;
  1845.     CUR.new_top = CUR.args;
  1846.   }
  1847.   /*************************************************************************/
  1848.   /*                                                                       */
  1849.   /* UTP[a]:       UnTouch Point                                           */
  1850.   /* Opcode range: 0x29                                                    */
  1851.   /* Stack:        uint32 -->                                              */
  1852.   /*                                                                       */
  1853.   static void
  1854.   Ins_UTP( INS_ARG )
  1855.   {
  1856.     FT_UShort  point;
  1857.     FT_Byte    mask;
  1858.     point = (FT_UShort)args[0];
  1859.     if ( BOUNDS( point, CUR.zp0.n_points ) )
  1860.     {
  1861.       if ( CUR.pedantic_hinting )
  1862.         CUR.error = TT_Err_Invalid_Reference;
  1863.       return;
  1864.     }
  1865.     mask = 0xFF;
  1866.     if ( CUR.GS.freeVector.x != 0 )
  1867.       mask &= ~FT_CURVE_TAG_TOUCH_X;
  1868.     if ( CUR.GS.freeVector.y != 0 )
  1869.       mask &= ~FT_CURVE_TAG_TOUCH_Y;
  1870.     CUR.zp0.tags[point] &= mask;
  1871.   }
  1872.   /* Local variables for Ins_IUP: */
  1873.   typedef struct
  1874.   {
  1875.     FT_Vector*  orgs;   /* original and current coordinate */
  1876.     FT_Vector*  curs;   /* arrays                          */
  1877.     FT_Vector*  orus;
  1878.     FT_UInt     max_points;
  1879.   } IUP_WorkerRec, *IUP_Worker;
  1880.   static void
  1881.   _iup_worker_shift( IUP_Worker  worker,
  1882.                      FT_UInt     p1,
  1883.                      FT_UInt     p2,
  1884.                      FT_UInt     p )
  1885.   {
  1886.     FT_UInt     i;
  1887.     FT_F26Dot6  dx;
  1888.     dx = worker->curs[p].x - worker->orgs[p].x;
  1889.     if ( dx != 0 )
  1890.     {
  1891.       for ( i = p1; i < p; i++ )
  1892.         worker->curs[i].x += dx;
  1893.       for ( i = p + 1; i <= p2; i++ )
  1894.         worker->curs[i].x += dx;
  1895.     }
  1896.   }
  1897.   static void
  1898.   _iup_worker_interpolate( IUP_Worker  worker,
  1899.                            FT_UInt     p1,
  1900.                            FT_UInt     p2,
  1901.                            FT_UInt     ref1,
  1902.                            FT_UInt     ref2 )
  1903.   {
  1904.     FT_UInt     i;
  1905.     FT_F26Dot6  orus1, orus2, org1, org2, delta1, delta2;
  1906.     if ( p1 > p2 )
  1907.       return;
  1908.     if ( BOUNDS( ref1, worker->max_points ) ||
  1909.          BOUNDS( ref2, worker->max_points ) )
  1910.       return;
  1911.     orus1 = worker->orus[ref1].x;
  1912.     orus2 = worker->orus[ref2].x;
  1913.     if ( orus1 > orus2 )
  1914.     {
  1915.       FT_F26Dot6  tmp_o;
  1916.       FT_UInt     tmp_r;
  1917.       tmp_o = orus1;
  1918.       orus1 = orus2;
  1919.       orus2 = tmp_o;
  1920.       tmp_r = ref1;
  1921.       ref1  = ref2;
  1922.       ref2  = tmp_r;
  1923.     }
  1924.     org1   = worker->orgs[ref1].x;
  1925.     org2   = worker->orgs[ref2].x;
  1926.     delta1 = worker->curs[ref1].x - org1;
  1927.     delta2 = worker->curs[ref2].x - org2;
  1928.     if ( orus1 == orus2 )
  1929.     {
  1930.       /* simple shift of untouched points */
  1931.       for ( i = p1; i <= p2; i++ )
  1932.       {
  1933.         FT_F26Dot6  x = worker->orgs[i].x;
  1934.         if ( x <= org1 )
  1935.           x += delta1;
  1936.         else
  1937.           x += delta2;
  1938.         worker->curs[i].x = x;
  1939.       }
  1940.     }
  1941.     else
  1942.     {
  1943.       FT_Fixed  scale       = 0;
  1944.       FT_Bool   scale_valid = 0;
  1945.       /* interpolation */
  1946.       for ( i = p1; i <= p2; i++ )
  1947.       {
  1948.         FT_F26Dot6  x = worker->orgs[i].x;
  1949.         if ( x <= org1 )
  1950.           x += delta1;
  1951.         else if ( x >= org2 )
  1952.           x += delta2;
  1953.         else
  1954.         {
  1955.           if ( !scale_valid )
  1956.           {
  1957.             scale_valid = 1;
  1958.             scale       = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
  1959.                                      0x10000, orus2 - orus1 );
  1960.           }
  1961.           x = ( org1 + delta1 ) +
  1962.               TT_MULFIX( worker->orus[i].x - orus1, scale );
  1963.         }
  1964.         worker->curs[i].x = x;
  1965.       }
  1966.     }
  1967.   }
  1968.   /*************************************************************************/
  1969.   /*                                                                       */
  1970.   /* IUP[a]:       Interpolate Untouched Points                            */
  1971.   /* Opcode range: 0x30-0x31                                               */
  1972.   /* Stack:        -->                                                     */
  1973.   /*                                                                       */
  1974.   static void
  1975.   Ins_IUP( INS_ARG )
  1976.   {
  1977.     IUP_WorkerRec  V;
  1978.     FT_Byte        mask;
  1979.     FT_UInt   first_point;   /* first point of contour        */
  1980.     FT_UInt   end_point;     /* end point (last+1) of contour */
  1981.     FT_UInt   first_touched; /* first touched point in contour   */
  1982.     FT_UInt   cur_touched;   /* current touched point in contour */
  1983.     FT_UInt   point;         /* current point   */
  1984.     FT_Short  contour;       /* current contour */
  1985.     FT_UNUSED_ARG;
  1986.     /* ignore empty outlines */
  1987.     if ( CUR.pts.n_contours == 0 )
  1988.       return;
  1989.     if ( CUR.opcode & 1 )
  1990.     {
  1991.       mask   = FT_CURVE_TAG_TOUCH_X;
  1992.       V.orgs = CUR.pts.org;
  1993.       V.curs = CUR.pts.cur;
  1994.       V.orus = CUR.pts.orus;
  1995.     }
  1996.     else
  1997.     {
  1998.       mask   = FT_CURVE_TAG_TOUCH_Y;
  1999.       V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
  2000.       V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
  2001.       V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
  2002.     }
  2003.     V.max_points = CUR.pts.n_points;
  2004.     contour = 0;
  2005.     point   = 0;
  2006.     do
  2007.     {
  2008.       end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;
  2009.       first_point = point;
  2010.       while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
  2011.         point++;
  2012.       if ( point <= end_point )
  2013.       {
  2014.         first_touched = point;
  2015.         cur_touched   = point;
  2016.         point++;
  2017.         while ( point <= end_point )
  2018.         {
  2019.           if ( ( CUR.pts.tags[point] & mask ) != 0 )
  2020.           {
  2021.             if ( point > 0 )
  2022.               _iup_worker_interpolate( &V,
  2023.                                        cur_touched + 1,
  2024.                                        point - 1,
  2025.                                        cur_touched,
  2026.                                        point );
  2027.             cur_touched = point;
  2028.           }
  2029.           point++;
  2030.         }
  2031.         if ( cur_touched == first_touched )
  2032.           _iup_worker_shift( &V, first_point, end_point, cur_touched );
  2033.         else
  2034.         {
  2035.           _iup_worker_interpolate( &V,
  2036.                                    (FT_UShort)( cur_touched + 1 ),
  2037.                                    end_point,
  2038.                                    cur_touched,
  2039.                                    first_touched );
  2040.           if ( first_touched > 0 )
  2041.             _iup_worker_interpolate( &V,
  2042.                                      first_point,
  2043.                                      first_touched - 1,
  2044.                                      cur_touched,
  2045.                                      first_touched );
  2046.         }
  2047.       }
  2048.       contour++;
  2049.     } while ( contour < CUR.pts.n_contours );
  2050.   }
  2051.   /*************************************************************************/
  2052.   /*                                                                       */
  2053.   /* DELTAPn[]:    DELTA exceptions P1, P2, P3                             */
  2054.   /* Opcode range: 0x5D,0x71,0x72                                          */
  2055.   /* Stack:        uint32 (2 * uint32)... -->                              */
  2056.   /*                                                                       */
  2057.   static void
  2058.   Ins_DELTAP( INS_ARG )
  2059.   {
  2060.     FT_ULong   k, nump;
  2061.     FT_UShort  A;
  2062.     FT_ULong   C;
  2063.     FT_Long    B;
  2064. #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
  2065.     /* Delta hinting is covered by US Patent 5159668. */
  2066.     if ( CUR.face->unpatented_hinting )
  2067.     {
  2068.       FT_Long  n = args[0] * 2;
  2069.       if ( CUR.args < n )
  2070.       {
  2071.         CUR.error = TT_Err_Too_Few_Arguments;
  2072.         return;
  2073.       }
  2074.       CUR.args -= n;
  2075.       CUR.new_top = CUR.args;
  2076.       return;
  2077.     }
  2078. #endif
  2079.     nump = (FT_ULong)args[0];   /* some points theoretically may occur more
  2080.                                    than once, thus UShort isn't enough */
  2081.     for ( k = 1; k <= nump; k++ )
  2082.     {
  2083.       if ( CUR.args < 2 )
  2084.       {
  2085.         CUR.error = TT_Err_Too_Few_Arguments;
  2086.         return;
  2087.       }
  2088.       CUR.args -= 2;
  2089.       A = (FT_UShort)CUR.stack[CUR.args + 1];
  2090.       B = CUR.stack[CUR.args];
  2091.       /* XXX: Because some popular fonts contain some invalid DeltaP */
  2092.       /*      instructions, we simply ignore them when the stacked   */
  2093.       /*      point reference is off limit, rather than returning an */
  2094.       /*      error.  As a delta instruction doesn't change a glyph  */
  2095.       /*      in great ways, this shouldn't be a problem.            */
  2096.       if ( !BOUNDS( A, CUR.zp0.n_points ) )
  2097.       {
  2098.         C = ( (FT_ULong)B & 0xF0 ) >> 4;
  2099.         switch ( CUR.opcode )
  2100.         {
  2101.         case 0x5D:
  2102.           break;
  2103.         case 0x71:
  2104.           C += 16;
  2105.           break;
  2106.         case 0x72:
  2107.           C += 32;
  2108.           break;
  2109.         }
  2110.         C += CUR.GS.delta_base;
  2111.         if ( CURRENT_Ppem() == (FT_Long)C )
  2112.         {
  2113.           B = ( (FT_ULong)B & 0xF ) - 8;
  2114.           if ( B >= 0 )
  2115.             B++;
  2116.           B = B * 64 / ( 1L << CUR.GS.delta_shift );
  2117.           CUR_Func_move( &CUR.zp0, A, B );
  2118.         }
  2119.       }
  2120.       else
  2121.         if ( CUR.pedantic_hinting )
  2122.           CUR.error = TT_Err_Invalid_Reference;
  2123.     }
  2124.     CUR.new_top = CUR.args;
  2125.   }
  2126.   /*************************************************************************/
  2127.   /*                                                                       */
  2128.   /* DELTACn[]:    DELTA exceptions C1, C2, C3                             */
  2129.   /* Opcode range: 0x73,0x74,0x75                                          */
  2130.   /* Stack:        uint32 (2 * uint32)... -->                              */
  2131.   /*                                                                       */
  2132.   static void
  2133.   Ins_DELTAC( INS_ARG )
  2134.   {
  2135.     FT_ULong  nump, k;
  2136.     FT_ULong  A, C;
  2137.     FT_Long   B;
  2138. #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
  2139.     /* Delta hinting is covered by US Patent 5159668. */
  2140.     if ( CUR.face->unpatented_hinting )
  2141.     {
  2142.       FT_Long  n = args[0] * 2;
  2143.       if ( CUR.args < n )
  2144.       {
  2145.         CUR.error = TT_Err_Too_Few_Arguments;
  2146.         return;
  2147.       }
  2148.       CUR.args -= n;
  2149.       CUR.new_top = CUR.args;
  2150.       return;
  2151.     }
  2152. #endif
  2153.     nump = (FT_ULong)args[0];
  2154.     for ( k = 1; k <= nump; k++ )
  2155.     {
  2156.       if ( CUR.args < 2 )
  2157.       {
  2158.         CUR.error = TT_Err_Too_Few_Arguments;
  2159.         return;
  2160.       }
  2161.       CUR.args -= 2;
  2162.       A = (FT_ULong)CUR.stack[CUR.args + 1];
  2163.       B = CUR.stack[CUR.args];
  2164.       if ( BOUNDS( A, CUR.cvtSize ) )
  2165.       {
  2166.         if ( CUR.pedantic_hinting )
  2167.         {
  2168.           CUR.error = TT_Err_Invalid_Reference;
  2169.           return;
  2170.         }
  2171.       }
  2172.       else
  2173.       {
  2174.         C = ( (FT_ULong)B & 0xF0 ) >> 4;
  2175.         switch ( CUR.opcode )
  2176.         {
  2177.         case 0x73:
  2178.           break;
  2179.         case 0x74:
  2180.           C += 16;
  2181.           break;
  2182.         case 0x75:
  2183.           C += 32;
  2184.           break;
  2185.         }
  2186.         C += CUR.GS.delta_base;
  2187.         if ( CURRENT_Ppem() == (FT_Long)C )
  2188.         {
  2189.           B = ( (FT_ULong)B & 0xF ) - 8;
  2190.           if ( B >= 0 )
  2191.             B++;
  2192.           B = B * 64 / ( 1L << CUR.GS.delta_shift );
  2193.           CUR_Func_move_cvt( A, B );
  2194.         }
  2195.       }
  2196.     }
  2197.     CUR.new_top = CUR.args;
  2198.   }
  2199.   /*************************************************************************/
  2200.   /*                                                                       */
  2201.   /* MISC. INSTRUCTIONS                                                    */
  2202.   /*                                                                       */
  2203.   /*************************************************************************/
  2204.   /*************************************************************************/
  2205.   /*                                                                       */
  2206.   /* GETINFO[]:    GET INFOrmation                                         */
  2207.   /* Opcode range: 0x88                                                    */
  2208.   /* Stack:        uint32 --> uint32                                       */
  2209.   /*                                                                       */
  2210.   static void
  2211.   Ins_GETINFO( INS_ARG )
  2212.   {
  2213.     FT_Long  K;
  2214.     K = 0;
  2215.     /* We return MS rasterizer version 1.7 for the font scaler. */
  2216.     if ( ( args[0] & 1 ) != 0 )
  2217.       K = 35;
  2218.     /* Has the glyph been rotated? */
  2219.     if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
  2220.       K |= 0x80;
  2221.     /* Has the glyph been stretched? */
  2222.     if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
  2223.       K |= 1 << 8;
  2224.     /* Are we hinting for grayscale? */
  2225.     if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
  2226.       K |= 1 << 12;
  2227.     args[0] = K;
  2228.   }
  2229.   static void
  2230.   Ins_UNKNOWN( INS_ARG )
  2231.   {
  2232.     TT_DefRecord*  def   = CUR.IDefs;
  2233.     TT_DefRecord*  limit = def + CUR.numIDefs;
  2234.     FT_UNUSED_ARG;
  2235.     for ( ; def < limit; def++ )
  2236.     {
  2237.       if ( (FT_Byte)def->opc == CUR.opcode && def->active )
  2238.       {
  2239.         TT_CallRec*  call;
  2240.         if ( CUR.callTop >= CUR.callSize )
  2241.         {
  2242.           CUR.error = TT_Err_Stack_Overflow;
  2243.           return;
  2244.         }
  2245.         call = CUR.callStack + CUR.callTop++;
  2246.         call->Caller_Range = CUR.curRange;
  2247.         call->Caller_IP    = CUR.IP+1;
  2248.         call->Cur_Count    = 1;
  2249.         call->Cur_Restart  = def->start;
  2250.         INS_Goto_CodeRange( def->range, def->start );
  2251.         CUR.step_ins = FALSE;
  2252.         return;
  2253.       }
  2254.     }
  2255.     CUR.error = TT_Err_Invalid_Opcode;
  2256.   }
  2257. #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
  2258.   static
  2259.   TInstruction_Function  Instruct_Dispatch[256] =
  2260.   {
  2261.     /* Opcodes are gathered in groups of 16. */
  2262.     /* Please keep the spaces as they are.   */
  2263.     /*  SVTCA  y  */  Ins_SVTCA,
  2264.     /*  SVTCA  x  */  Ins_SVTCA,
  2265.     /*  SPvTCA y  */  Ins_SPVTCA,
  2266.     /*  SPvTCA x  */  Ins_SPVTCA,
  2267.     /*  SFvTCA y  */  Ins_SFVTCA,
  2268.     /*  SFvTCA x  */  Ins_SFVTCA,
  2269.     /*  SPvTL //  */  Ins_SPVTL,
  2270.     /*  SPvTL +   */  Ins_SPVTL,
  2271.     /*  SFvTL //  */  Ins_SFVTL,
  2272.     /*  SFvTL +   */  Ins_SFVTL,
  2273.     /*  SPvFS     */  Ins_SPVFS,
  2274.     /*  SFvFS     */  Ins_SFVFS,
  2275.     /*  GPV       */  Ins_GPV,
  2276.     /*  GFV       */  Ins_GFV,
  2277.     /*  SFvTPv    */  Ins_SFVTPV,
  2278.     /*  ISECT     */  Ins_ISECT,
  2279.     /*  SRP0      */  Ins_SRP0,
  2280.     /*  SRP1      */  Ins_SRP1,
  2281.     /*  SRP2      */  Ins_SRP2,
  2282.     /*  SZP0      */  Ins_SZP0,
  2283.     /*  SZP1      */  Ins_SZP1,
  2284.     /*  SZP2      */  Ins_SZP2,
  2285.     /*  SZPS      */  Ins_SZPS,
  2286.     /*  SLOOP     */  Ins_SLOOP,
  2287.     /*  RTG       */  Ins_RTG,
  2288.     /*  RTHG      */  Ins_RTHG,
  2289.     /*  SMD       */  Ins_SMD,
  2290.     /*  ELSE      */  Ins_ELSE,
  2291.     /*  JMPR      */  Ins_JMPR,
  2292.     /*  SCvTCi    */  Ins_SCVTCI,
  2293.     /*  SSwCi     */  Ins_SSWCI,
  2294.     /*  SSW       */  Ins_SSW,
  2295.     /*  DUP       */  Ins_DUP,
  2296.     /*  POP       */  Ins_POP,
  2297.     /*  CLEAR     */  Ins_CLEAR,
  2298.     /*  SWAP      */  Ins_SWAP,
  2299.     /*  DEPTH     */  Ins_DEPTH,
  2300.     /*  CINDEX    */  Ins_CINDEX,
  2301.     /*  MINDEX    */  Ins_MINDEX,
  2302.     /*  AlignPTS  */  Ins_ALIGNPTS,
  2303.     /*  INS_0x28  */  Ins_UNKNOWN,
  2304.     /*  UTP       */  Ins_UTP,
  2305.     /*  LOOPCALL  */  Ins_LOOPCALL,
  2306.     /*  CALL      */  Ins_CALL,
  2307.     /*  FDEF      */  Ins_FDEF,
  2308.     /*  ENDF      */  Ins_ENDF,
  2309.     /*  MDAP[0]   */  Ins_MDAP,
  2310.     /*  MDAP[1]   */  Ins_MDAP,
  2311.     /*  IUP[0]    */  Ins_IUP,
  2312.     /*  IUP[1]    */  Ins_IUP,
  2313.     /*  SHP[0]    */  Ins_SHP,
  2314.     /*  SHP[1]    */  Ins_SHP,
  2315.     /*  SHC[0]    */  Ins_SHC,
  2316.     /*  SHC[1]    */  Ins_SHC,
  2317.     /*  SHZ[0]    */  Ins_SHZ,
  2318.     /*  SHZ[1]    */  Ins_SHZ,
  2319.     /*  SHPIX     */  Ins_SHPIX,
  2320.     /*  IP        */  Ins_IP,
  2321.     /*  MSIRP[0]  */  Ins_MSIRP,
  2322.     /*  MSIRP[1]  */  Ins_MSIRP,
  2323.     /*  AlignRP   */  Ins_ALIGNRP,
  2324.     /*  RTDG      */  Ins_RTDG,
  2325.     /*  MIAP[0]   */  Ins_MIAP,
  2326.     /*  MIAP[1]   */  Ins_MIAP,
  2327.     /*  NPushB    */  Ins_NPUSHB,
  2328.     /*  NPushW    */  Ins_NPUSHW,
  2329.     /*  WS        */  Ins_WS,
  2330.     /*  RS        */  Ins_RS,
  2331.     /*  WCvtP     */  Ins_WCVTP,
  2332.     /*  RCvt      */  Ins_RCVT,
  2333.     /*  GC[0]     */  Ins_GC,
  2334.     /*  GC[1]     */  Ins_GC,
  2335.     /*  SCFS      */  Ins_SCFS,
  2336.     /*  MD[0]     */  Ins_MD,
  2337.     /*  MD[1]     */  Ins_MD,
  2338.     /*  MPPEM     */  Ins_MPPEM,
  2339.     /*  MPS       */  Ins_MPS,
  2340.     /*  FlipON    */  Ins_FLIPON,
  2341.     /*  FlipOFF   */  Ins_FLIPOFF,
  2342.     /*  DEBUG     */  Ins_DEBUG,
  2343.     /*  LT        */  Ins_LT,
  2344.     /*  LTEQ      */  Ins_LTEQ,
  2345.     /*  GT        */  Ins_GT,
  2346.     /*  GTEQ      */  Ins_GTEQ,
  2347.     /*  EQ        */  Ins_EQ,
  2348.     /*  NEQ       */  Ins_NEQ,
  2349.     /*  ODD       */  Ins_ODD,
  2350.     /*  EVEN      */  Ins_EVEN,
  2351.     /*  IF        */  Ins_IF,
  2352.     /*  EIF       */  Ins_EIF,
  2353.     /*  AND       */  Ins_AND,
  2354.     /*  OR        */  Ins_OR,
  2355.     /*  NOT       */  Ins_NOT,
  2356.     /*  DeltaP1   */  Ins_DELTAP,
  2357.     /*  SDB       */  Ins_SDB,
  2358.     /*  SDS       */  Ins_SDS,
  2359.     /*  ADD       */  Ins_ADD,
  2360.     /*  SUB       */  Ins_SUB,
  2361.     /*  DIV       */  Ins_DIV,
  2362.     /*  MUL       */  Ins_MUL,
  2363.     /*  ABS       */  Ins_ABS,
  2364.     /*  NEG       */  Ins_NEG,
  2365.     /*  FLOOR     */  Ins_FLOOR,
  2366.     /*  CEILING   */  Ins_CEILING,
  2367.     /*  ROUND[0]  */  Ins_ROUND,
  2368.     /*  ROUND[1]  */  Ins_ROUND,
  2369.     /*  ROUND[2]  */  Ins_ROUND,
  2370.     /*  ROUND[3]  */  Ins_ROUND,
  2371.     /*  NROUND[0] */  Ins_NROUND,
  2372.     /*  NROUND[1] */  Ins_NROUND,
  2373.     /*  NROUND[2] */  Ins_NROUND,
  2374.     /*  NROUND[3] */  Ins_NROUND,
  2375.     /*  WCvtF     */  Ins_WCVTF,
  2376.     /*  DeltaP2   */  Ins_DELTAP,
  2377.     /*  DeltaP3   */  Ins_DELTAP,
  2378.     /*  DeltaCn[0] */ Ins_DELTAC,
  2379.     /*  DeltaCn[1] */ Ins_DELTAC,
  2380.     /*  DeltaCn[2] */ Ins_DELTAC,
  2381.     /*  SROUND    */  Ins_SROUND,
  2382.     /*  S45Round  */  Ins_S45ROUND,
  2383.     /*  JROT      */  Ins_JROT,
  2384.     /*  JROF      */  Ins_JROF,
  2385.     /*  ROFF      */  Ins_ROFF,
  2386.     /*  INS_0x7B  */  Ins_UNKNOWN,
  2387.     /*  RUTG      */  Ins_RUTG,
  2388.     /*  RDTG      */  Ins_RDTG,
  2389.     /*  SANGW     */  Ins_SANGW,
  2390.     /*  AA        */  Ins_AA,
  2391.     /*  FlipPT    */  Ins_FLIPPT,
  2392.     /*  FlipRgON  */  Ins_FLIPRGON,
  2393.     /*  FlipRgOFF */  Ins_FLIPRGOFF,
  2394.     /*  INS_0x83  */  Ins_UNKNOWN,
  2395.     /*  INS_0x84  */  Ins_UNKNOWN,
  2396.     /*  ScanCTRL  */  Ins_SCANCTRL,
  2397.     /*  SDPVTL[0] */  Ins_SDPVTL,
  2398.     /*  SDPVTL[1] */  Ins_SDPVTL,
  2399.     /*  GetINFO   */  Ins_GETINFO,
  2400.     /*  IDEF      */  Ins_IDEF,
  2401.     /*  ROLL      */  Ins_ROLL,
  2402.     /*  MAX       */  Ins_MAX,
  2403.     /*  MIN       */  Ins_MIN,
  2404.     /*  ScanTYPE  */  Ins_SCANTYPE,
  2405.     /*  InstCTRL  */  Ins_INSTCTRL,
  2406.     /*  INS_0x8F  */  Ins_UNKNOWN,
  2407.     /*  INS_0x90  */   Ins_UNKNOWN,
  2408.     /*  INS_0x91  */   Ins_UNKNOWN,
  2409.     /*  INS_0x92  */   Ins_UNKNOWN,
  2410.     /*  INS_0x93  */   Ins_UNKNOWN,
  2411.     /*  INS_0x94  */   Ins_UNKNOWN,
  2412.     /*  INS_0x95  */   Ins_UNKNOWN,
  2413.     /*  INS_0x96  */   Ins_UNKNOWN,
  2414.     /*  INS_0x97  */   Ins_UNKNOWN,
  2415.     /*  INS_0x98  */   Ins_UNKNOWN,
  2416.     /*  INS_0x99  */   Ins_UNKNOWN,
  2417.     /*  INS_0x9A  */   Ins_UNKNOWN,
  2418.     /*  INS_0x9B  */   Ins_UNKNOWN,
  2419.     /*  INS_0x9C  */   Ins_UNKNOWN,
  2420.     /*  INS_0x9D  */   Ins_UNKNOWN,
  2421.     /*  INS_0x9E  */   Ins_UNKNOWN,
  2422.     /*  INS_0x9F  */   Ins_UNKNOWN,
  2423.     /*  INS_0xA0  */   Ins_UNKNOWN,
  2424.     /*  INS_0xA1  */   Ins_UNKNOWN,
  2425.     /*  INS_0xA2  */   Ins_UNKNOWN,
  2426.     /*  INS_0xA3  */   Ins_UNKNOWN,
  2427.     /*  INS_0xA4  */   Ins_UNKNOWN,
  2428.     /*  INS_0xA5  */   Ins_UNKNOWN,
  2429.     /*  INS_0xA6  */   Ins_UNKNOWN,
  2430.     /*  INS_0xA7  */   Ins_UNKNOWN,
  2431.     /*  INS_0xA8  */   Ins_UNKNOWN,
  2432.     /*  INS_0xA9  */   Ins_UNKNOWN,
  2433.     /*  INS_0xAA  */   Ins_UNKNOWN,
  2434.     /*  INS_0xAB  */   Ins_UNKNOWN,
  2435.     /*  INS_0xAC  */   Ins_UNKNOWN,
  2436.     /*  INS_0xAD  */   Ins_UNKNOWN,
  2437.     /*  INS_0xAE  */   Ins_UNKNOWN,
  2438.     /*  INS_0xAF  */   Ins_UNKNOWN,
  2439.     /*  PushB[0]  */  Ins_PUSHB,
  2440.     /*  PushB[1]  */  Ins_PUSHB,
  2441.     /*  PushB[2]  */  Ins_PUSHB,
  2442.     /*  PushB[3]  */  Ins_PUSHB,
  2443.     /*  PushB[4]  */  Ins_PUSHB,
  2444.     /*  PushB[5]  */  Ins_PUSHB,
  2445.     /*  PushB[6]  */  Ins_PUSHB,
  2446.     /*  PushB[7]  */  Ins_PUSHB,
  2447.     /*  PushW[0]  */  Ins_PUSHW,
  2448.     /*  PushW[1]  */  Ins_PUSHW,
  2449.     /*  PushW[2]  */  Ins_PUSHW,
  2450.     /*  PushW[3]  */  Ins_PUSHW,
  2451.     /*  PushW[4]  */  Ins_PUSHW,
  2452.     /*  PushW[5]  */  Ins_PUSHW,
  2453.     /*  PushW[6]  */  Ins_PUSHW,
  2454.     /*  PushW[7]  */  Ins_PUSHW,
  2455.     /*  MDRP[00]  */  Ins_MDRP,
  2456.     /*  MDRP[01]  */  Ins_MDRP,
  2457.     /*  MDRP[02]  */  Ins_MDRP,
  2458.     /*  MDRP[03]  */  Ins_MDRP,
  2459.     /*  MDRP[04]  */  Ins_MDRP,
  2460.     /*  MDRP[05]  */  Ins_MDRP,
  2461.     /*  MDRP[06]  */  Ins_MDRP,
  2462.     /*  MDRP[07]  */  Ins_MDRP,
  2463.     /*  MDRP[08]  */  Ins_MDRP,
  2464.     /*  MDRP[09]  */  Ins_MDRP,
  2465.     /*  MDRP[10]  */  Ins_MDRP,
  2466.     /*  MDRP[11]  */  Ins_MDRP,
  2467.     /*  MDRP[12]  */  Ins_MDRP,
  2468.     /*  MDRP[13]  */  Ins_MDRP,
  2469.     /*  MDRP[14]  */  Ins_MDRP,
  2470.     /*  MDRP[15]  */  Ins_MDRP,
  2471.     /*  MDRP[16]  */  Ins_MDRP,
  2472.     /*  MDRP[17]  */  Ins_MDRP,
  2473.     /*  MDRP[18]  */  Ins_MDRP,
  2474.     /*  MDRP[19]  */  Ins_MDRP,
  2475.     /*  MDRP[20]  */  Ins_MDRP,
  2476.     /*  MDRP[21]  */  Ins_MDRP,
  2477.     /*  MDRP[22]  */  Ins_MDRP,
  2478.     /*  MDRP[23]  */  Ins_MDRP,
  2479.     /*  MDRP[24]  */  Ins_MDRP,
  2480.     /*  MDRP[25]  */  Ins_MDRP,
  2481.     /*  MDRP[26]  */  Ins_MDRP,
  2482.     /*  MDRP[27]  */  Ins_MDRP,
  2483.     /*  MDRP[28]  */  Ins_MDRP,
  2484.     /*  MDRP[29]  */  Ins_MDRP,
  2485.     /*  MDRP[30]  */  Ins_MDRP,
  2486.     /*  MDRP[31]  */  Ins_MDRP,
  2487.     /*  MIRP[00]  */  Ins_MIRP,
  2488.     /*  MIRP[01]  */  Ins_MIRP,
  2489.     /*  MIRP[02]  */  Ins_MIRP,
  2490.     /*  MIRP[03]  */  Ins_MIRP,
  2491.     /*  MIRP[04]  */  Ins_MIRP,
  2492.     /*  MIRP[05]  */  Ins_MIRP,
  2493.     /*  MIRP[06]  */  Ins_MIRP,
  2494.     /*  MIRP[07]  */  Ins_MIRP,
  2495.     /*  MIRP[08]  */  Ins_MIRP,
  2496.     /*  MIRP[09]  */  Ins_MIRP,
  2497.     /*  MIRP[10]  */  Ins_MIRP,
  2498.     /*  MIRP[11]  */  Ins_MIRP,
  2499.     /*  MIRP[12]  */  Ins_MIRP,
  2500.     /*  MIRP[13]  */  Ins_MIRP,
  2501.     /*  MIRP[14]  */  Ins_MIRP,
  2502.     /*  MIRP[15]  */  Ins_MIRP,
  2503.     /*  MIRP[16]  */  Ins_MIRP,
  2504.     /*  MIRP[17]  */  Ins_MIRP,
  2505.     /*  MIRP[18]  */  Ins_MIRP,
  2506.     /*  MIRP[19]  */  Ins_MIRP,
  2507.     /*  MIRP[20]  */  Ins_MIRP,
  2508.     /*  MIRP[21]  */  Ins_MIRP,
  2509.     /*  MIRP[22]  */  Ins_MIRP,
  2510.     /*  MIRP[23]  */  Ins_MIRP,
  2511.     /*  MIRP[24]  */  Ins_MIRP,
  2512.     /*  MIRP[25]  */  Ins_MIRP,
  2513.     /*  MIRP[26]  */  Ins_MIRP,
  2514.     /*  MIRP[27]  */  Ins_MIRP,
  2515.     /*  MIRP[28]  */  Ins_MIRP,
  2516.     /*  MIRP[29]  */  Ins_MIRP,
  2517.     /*  MIRP[30]  */  Ins_MIRP,
  2518.     /*  MIRP[31]  */  Ins_MIRP
  2519.   };
  2520. #endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
  2521.   /*************************************************************************/
  2522.   /*                                                                       */
  2523.   /* RUN                                                                   */
  2524.   /*                                                                       */
  2525.   /*  This function executes a run of opcodes.  It will exit in the        */
  2526.   /*  following cases:                                                     */
  2527.   /*                                                                       */
  2528.   /*  - Errors (in which case it returns FALSE).                           */
  2529.   /*                                                                       */
  2530.   /*  - Reaching the end of the main code range (returns TRUE).            */
  2531.   /*    Reaching the end of a code range within a function call is an      */
  2532.   /*    error.                                                             */
  2533.   /*                                                                       */
  2534.   /*  - After executing one single opcode, if the flag `Instruction_Trap'  */
  2535.   /*    is set to TRUE (returns TRUE).                                     */
  2536.   /*                                                                       */
  2537.   /*  On exit with TRUE, test IP < CodeSize to know whether it comes from  */
  2538.   /*  an instruction trap or a normal termination.                         */
  2539.   /*                                                                       */
  2540.   /*                                                                       */
  2541.   /*  Note: The documented DEBUG opcode pops a value from the stack.  This */
  2542.   /*        behaviour is unsupported; here a DEBUG opcode is always an     */
  2543.   /*        error.                                                         */
  2544.   /*                                                                       */
  2545.   /*                                                                       */
  2546.   /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */
  2547.   /*                                                                       */
  2548.   /*  Instructions appear in the specification's order.                    */
  2549.   /*                                                                       */
  2550.   /*************************************************************************/
  2551.   /* documentation is in ttinterp.h */
  2552.   FT_EXPORT_DEF( FT_Error )
  2553.   TT_RunIns( TT_ExecContext  exc )
  2554.   {
  2555.     FT_Long  ins_counter = 0;  /* executed instructions counter */
  2556. #ifdef TT_CONFIG_OPTION_STATIC_RASTER
  2557.     cur = *exc;
  2558. #endif
  2559.     /* set CVT functions */
  2560.     CUR.tt_metrics.ratio = 0;
  2561.     if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
  2562.     {
  2563.       /* non-square pixels, use the stretched routines */
  2564.       CUR.func_read_cvt  = Read_CVT_Stretched;
  2565.       CUR.func_write_cvt = Write_CVT_Stretched;
  2566.       CUR.func_move_cvt  = Move_CVT_Stretched;
  2567.     }
  2568.     else
  2569.     {
  2570.       /* square pixels, use normal routines */
  2571.       CUR.func_read_cvt  = Read_CVT;
  2572.       CUR.func_write_cvt = Write_CVT;
  2573.       CUR.func_move_cvt  = Move_CVT;
  2574.     }
  2575.     COMPUTE_Funcs();
  2576.     COMPUTE_Round( (FT_Byte)exc->GS.round_state );
  2577.     do
  2578.     {
  2579.       CUR.opcode = CUR.code[CUR.IP];
  2580.       if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
  2581.       {
  2582.         if ( CUR.IP + 1 > CUR.codeSize )
  2583.           goto LErrorCodeOverflow_;
  2584.         CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
  2585.       }
  2586.       if ( CUR.IP + CUR.length > CUR.codeSize )
  2587.         goto LErrorCodeOverflow_;
  2588.       /* First, let's check for empty stack and overflow */
  2589.       CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
  2590.       /* `args' is the top of the stack once arguments have been popped. */
  2591.       /* One can also interpret it as the index of the last argument.    */
  2592.       if ( CUR.args < 0 )
  2593.       {
  2594.         CUR.error = TT_Err_Too_Few_Arguments;
  2595.         goto LErrorLabel_;
  2596.       }
  2597.       CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
  2598.       /* `new_top' is the new top of the stack, after the instruction's */
  2599.       /* execution.  `top' will be set to `new_top' after the `switch'  */
  2600.       /* statement.                                                     */
  2601.       if ( CUR.new_top > CUR.stackSize )
  2602.       {
  2603.         CUR.error = TT_Err_Stack_Overflow;
  2604.         goto LErrorLabel_;
  2605.       }
  2606.       CUR.step_ins = TRUE;
  2607.       CUR.error    = TT_Err_Ok;
  2608. #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
  2609.       {
  2610.         FT_Long*  args   = CUR.stack + CUR.args;
  2611.         FT_Byte   opcode = CUR.opcode;
  2612. #undef  ARRAY_BOUND_ERROR
  2613. #define ARRAY_BOUND_ERROR  goto Set_Invalid_Ref
  2614.         switch ( opcode )
  2615.         {
  2616.         case 0x00:  /* SVTCA y  */
  2617.         case 0x01:  /* SVTCA x  */
  2618.         case 0x02:  /* SPvTCA y */
  2619.         case 0x03:  /* SPvTCA x */
  2620.         case 0x04:  /* SFvTCA y */
  2621.         case 0x05:  /* SFvTCA x */
  2622.           {
  2623.             FT_Short AA, BB;
  2624.             AA = (FT_Short)( ( opcode & 1 ) << 14 );
  2625.             BB = (FT_Short)( AA ^ 0x4000 );
  2626.             if ( opcode < 4 )
  2627.             {
  2628.               CUR.GS.projVector.x = AA;
  2629.               CUR.GS.projVector.y = BB;
  2630.               CUR.GS.dualVector.x = AA;
  2631.               CUR.GS.dualVector.y = BB;
  2632.             }
  2633.             else
  2634.             {
  2635.               GUESS_VECTOR( projVector );
  2636.             }
  2637.             if ( ( opcode & 2 ) == 0 )
  2638.             {
  2639.               CUR.GS.freeVector.x = AA;
  2640.               CUR.GS.freeVector.y = BB;
  2641.             }
  2642.             else
  2643.             {
  2644.               GUESS_VECTOR( freeVector );
  2645.             }
  2646.             COMPUTE_Funcs();
  2647.           }
  2648.           break;
  2649.         case 0x06:  /* SPvTL // */
  2650.         case 0x07:  /* SPvTL +  */
  2651.           DO_SPVTL
  2652.           break;
  2653.         case 0x08:  /* SFvTL // */
  2654.         case 0x09:  /* SFvTL +  */
  2655.           DO_SFVTL
  2656.           break;
  2657.         case 0x0A:  /* SPvFS */
  2658.           DO_SPVFS
  2659.           break;
  2660.         case 0x0B:  /* SFvFS */
  2661.           DO_SFVFS
  2662.           break;
  2663.         case 0x0C:  /* GPV */
  2664.           DO_GPV
  2665.           break;
  2666.         case 0x0D:  /* GFV */
  2667.           DO_GFV
  2668.           break;
  2669.         case 0x0E:  /* SFvTPv */
  2670.           DO_SFVTPV
  2671.           break;
  2672.         case 0x0F:  /* ISECT  */
  2673.           Ins_ISECT( EXEC_ARG_ args );
  2674.           break;
  2675.         case 0x10:  /* SRP0 */
  2676.           DO_SRP0
  2677.           break;
  2678.         case 0x11:  /* SRP1 */
  2679.           DO_SRP1
  2680.           break;
  2681.         case 0x12:  /* SRP2 */
  2682.           DO_SRP2
  2683.           break;
  2684.         case 0x13:  /* SZP0 */
  2685.           Ins_SZP0( EXEC_ARG_ args );
  2686.           break;
  2687.         case 0x14:  /* SZP1 */
  2688.           Ins_SZP1( EXEC_ARG_ args );
  2689.           break;
  2690.         case 0x15:  /* SZP2 */
  2691.           Ins_SZP2( EXEC_ARG_ args );
  2692.           break;
  2693.         case 0x16:  /* SZPS */
  2694.           Ins_SZPS( EXEC_ARG_ args );
  2695.           break;
  2696.         case 0x17:  /* SLOOP */
  2697.           DO_SLOOP
  2698.           break;
  2699.         case 0x18:  /* RTG */
  2700.           DO_RTG
  2701.           break;
  2702.         case 0x19:  /* RTHG */
  2703.           DO_RTHG
  2704.           break;
  2705.         case 0x1A:  /* SMD */
  2706.           DO_SMD
  2707.           break;
  2708.         case 0x1B:  /* ELSE */
  2709.           Ins_ELSE( EXEC_ARG_ args );
  2710.           break;
  2711.         case 0x1C:  /* JMPR */
  2712.           DO_JMPR
  2713.           break;
  2714.         case 0x1D:  /* SCVTCI */
  2715.           DO_SCVTCI
  2716.           break;
  2717.         case 0x1E:  /* SSWCI */
  2718.           DO_SSWCI
  2719.           break;
  2720.         case 0x1F:  /* SSW */
  2721.           DO_SSW
  2722.           break;
  2723.         case 0x20:  /* DUP */
  2724.           DO_DUP
  2725.           break;
  2726.         case 0x21:  /* POP */
  2727.           /* nothing :-) */
  2728.           break;
  2729.         case 0x22:  /* CLEAR */
  2730.           DO_CLEAR
  2731.           break;
  2732.         case 0x23:  /* SWAP */
  2733.           DO_SWAP
  2734.           break;
  2735.         case 0x24:  /* DEPTH */
  2736.           DO_DEPTH
  2737.           break;
  2738.         case 0x25:  /* CINDEX */
  2739.           DO_CINDEX
  2740.           break;
  2741.         case 0x26:  /* MINDEX */
  2742.           Ins_MINDEX( EXEC_ARG_ args );
  2743.           break;
  2744.         case 0x27:  /* ALIGNPTS */
  2745.           Ins_ALIGNPTS( EXEC_ARG_ args );
  2746.           break;
  2747.         case 0x28:  /* ???? */
  2748.           Ins_UNKNOWN( EXEC_ARG_ args );
  2749.           break;
  2750.         case 0x29:  /* UTP */
  2751.           Ins_UTP( EXEC_ARG_ args );
  2752.           break;
  2753.         case 0x2A:  /* LOOPCALL */
  2754.           Ins_LOOPCALL( EXEC_ARG_ args );
  2755.           break;
  2756.         case 0x2B:  /* CALL */
  2757.           Ins_CALL( EXEC_ARG_ args );
  2758.           break;
  2759.         case 0x2C:  /* FDEF */
  2760.           Ins_FDEF( EXEC_ARG_ args );
  2761.           break;
  2762.         case 0x2D:  /* ENDF */
  2763.           Ins_ENDF( EXEC_ARG_ args );
  2764.           break;
  2765.         case 0x2E:  /* MDAP */
  2766.         case 0x2F:  /* MDAP */
  2767.           Ins_MDAP( EXEC_ARG_ args );
  2768.           break;
  2769.         case 0x30:  /* IUP */
  2770.         case 0x31:  /* IUP */
  2771.           Ins_IUP( EXEC_ARG_ args );
  2772.           break;
  2773.         case 0x32:  /* SHP */
  2774.         case 0x33:  /* SHP */
  2775.           Ins_SHP( EXEC_ARG_ args );
  2776.           break;
  2777.         case 0x34:  /* SHC */
  2778.         case 0x35:  /* SHC */
  2779.           Ins_SHC( EXEC_ARG_ args );
  2780.           break;
  2781.         case 0x36:  /* SHZ */
  2782.         case 0x37:  /* SHZ */
  2783.           Ins_SHZ( EXEC_ARG_ args );
  2784.           break;
  2785.         case 0x38:  /* SHPIX */
  2786.           Ins_SHPIX( EXEC_ARG_ args );
  2787.           break;
  2788.         case 0x39:  /* IP    */
  2789.           Ins_IP( EXEC_ARG_ args );
  2790.           break;
  2791.         case 0x3A:  /* MSIRP */
  2792.         case 0x3B:  /* MSIRP */
  2793.           Ins_MSIRP( EXEC_ARG_ args );
  2794.           break;
  2795.         case 0x3C:  /* AlignRP */
  2796.           Ins_ALIGNRP( EXEC_ARG_ args );
  2797.           break;
  2798.         case 0x3D:  /* RTDG */
  2799.           DO_RTDG
  2800.           break;
  2801.         case 0x3E:  /* MIAP */
  2802.         case 0x3F:  /* MIAP */
  2803.           Ins_MIAP( EXEC_ARG_ args );
  2804.           break;
  2805.         case 0x40:  /* NPUSHB */
  2806.           Ins_NPUSHB( EXEC_ARG_ args );
  2807.           break;
  2808.         case 0x41:  /* NPUSHW */
  2809.           Ins_NPUSHW( EXEC_ARG_ args );
  2810.           break;
  2811.         case 0x42:  /* WS */
  2812.           DO_WS
  2813.           break;
  2814.       Set_Invalid_Ref:
  2815.             CUR.error = TT_Err_Invalid_Reference;
  2816.           break;
  2817.         case 0x43:  /* RS */
  2818.           DO_RS
  2819.           break;
  2820.         case 0x44:  /* WCVTP */
  2821.           DO_WCVTP
  2822.           break;
  2823.         case 0x45:  /* RCVT */
  2824.           DO_RCVT
  2825.           break;
  2826.         case 0x46:  /* GC */
  2827.         case 0x47:  /* GC */
  2828.           Ins_GC( EXEC_ARG_ args );
  2829.           break;
  2830.         case 0x48:  /* SCFS */
  2831.           Ins_SCFS( EXEC_ARG_ args );
  2832.           break;
  2833.         case 0x49:  /* MD */
  2834.         case 0x4A:  /* MD */
  2835.           Ins_MD( EXEC_ARG_ args );
  2836.           break;
  2837.         case 0x4B:  /* MPPEM */
  2838.           DO_MPPEM
  2839.           break;
  2840.         case 0x4C:  /* MPS */
  2841.           DO_MPS
  2842.           break;
  2843.         case 0x4D:  /* FLIPON */
  2844.           DO_FLIPON
  2845.           break;
  2846.         case 0x4E:  /* FLIPOFF */
  2847.           DO_FLIPOFF
  2848.           break;
  2849.         case 0x4F:  /* DEBUG */
  2850.           DO_DEBUG
  2851.           break;
  2852.         case 0x50:  /* LT */
  2853.           DO_LT
  2854.           break;
  2855.         case 0x51:  /* LTEQ */
  2856.           DO_LTEQ
  2857.           break;
  2858.         case 0x52:  /* GT */
  2859.           DO_GT
  2860.           break;
  2861.         case 0x53:  /* GTEQ */
  2862.           DO_GTEQ
  2863.           break;
  2864.         case 0x54:  /* EQ */
  2865.           DO_EQ
  2866.           break;
  2867.         case 0x55:  /* NEQ */
  2868.           DO_NEQ
  2869.           break;
  2870.         case 0x56:  /* ODD */
  2871.           DO_ODD
  2872.           break;
  2873.         case 0x57:  /* EVEN */
  2874.           DO_EVEN
  2875.           break;
  2876.         case 0x58:  /* IF */
  2877.           Ins_IF( EXEC_ARG_ args );
  2878.           break;
  2879.         case 0x59:  /* EIF */
  2880.           /* do nothing */
  2881.           break;
  2882.         case 0x5A:  /* AND */
  2883.           DO_AND
  2884.           break;
  2885.         case 0x5B:  /* OR */
  2886.           DO_OR
  2887.           break;
  2888.         case 0x5C:  /* NOT */
  2889.           DO_NOT
  2890.           break;
  2891.         case 0x5D:  /* DELTAP1 */
  2892.           Ins_DELTAP( EXEC_ARG_ args );
  2893.           break;
  2894.         case 0x5E:  /* SDB */
  2895.           DO_SDB
  2896.           break;
  2897.         case 0x5F:  /* SDS */
  2898.           DO_SDS
  2899.           break;
  2900.         case 0x60:  /* ADD */
  2901.           DO_ADD
  2902.           break;
  2903.         case 0x61:  /* SUB */
  2904.           DO_SUB
  2905.           break;
  2906.         case 0x62:  /* DIV */
  2907.           DO_DIV
  2908.           break;
  2909.         case 0x63:  /* MUL */
  2910.           DO_MUL
  2911.           break;
  2912.         case 0x64:  /* ABS */
  2913.           DO_ABS
  2914.           break;
  2915.         case 0x65:  /* NEG */
  2916.           DO_NEG
  2917.           break;
  2918.         case 0x66:  /* FLOOR */
  2919.           DO_FLOOR
  2920.           break;
  2921.         case 0x67:  /* CEILING */
  2922.           DO_CEILING
  2923.           break;
  2924.         case 0x68:  /* ROUND */
  2925.         case 0x69:  /* ROUND */
  2926.         case 0x6A:  /* ROUND */
  2927.         case 0x6B:  /* ROUND */
  2928.           DO_ROUND
  2929.           break;
  2930.         case 0x6C:  /* NROUND */
  2931.         case 0x6D:  /* NROUND */
  2932.         case 0x6E:  /* NRRUND */
  2933.         case 0x6F:  /* NROUND */
  2934.           DO_NROUND
  2935.           break;
  2936.         case 0x70:  /* WCVTF */
  2937.           DO_WCVTF
  2938.           break;
  2939.         case 0x71:  /* DELTAP2 */
  2940.         case 0x72:  /* DELTAP3 */
  2941.           Ins_DELTAP( EXEC_ARG_ args );
  2942.           break;
  2943.         case 0x73:  /* DELTAC0 */
  2944.         case 0x74:  /* DELTAC1 */
  2945.         case 0x75:  /* DELTAC2 */
  2946.           Ins_DELTAC( EXEC_ARG_ args );
  2947.           break;
  2948.         case 0x76:  /* SROUND */
  2949.           DO_SROUND
  2950.           break;
  2951.         case 0x77:  /* S45Round */
  2952.           DO_S45ROUND
  2953.           break;
  2954.         case 0x78:  /* JROT */
  2955.           DO_JROT
  2956.           break;
  2957.         case 0x79:  /* JROF */
  2958.           DO_JROF
  2959.           break;
  2960.         case 0x7A:  /* ROFF */
  2961.           DO_ROFF
  2962.           break;
  2963.         case 0x7B:  /* ???? */
  2964.           Ins_UNKNOWN( EXEC_ARG_ args );
  2965.           break;
  2966.         case 0x7C:  /* RUTG */
  2967.           DO_RUTG
  2968.           break;
  2969.         case 0x7D:  /* RDTG */
  2970.           DO_RDTG
  2971.           break;
  2972.         case 0x7E:  /* SANGW */
  2973.         case 0x7F:  /* AA    */
  2974.           /* nothing - obsolete */
  2975.           break;
  2976.         case 0x80:  /* FLIPPT */
  2977.           Ins_FLIPPT( EXEC_ARG_ args );
  2978.           break;
  2979.         case 0x81:  /* FLIPRGON */
  2980.           Ins_FLIPRGON( EXEC_ARG_ args );
  2981.           break;
  2982.         case 0x82:  /* FLIPRGOFF */
  2983.           Ins_FLIPRGOFF( EXEC_ARG_ args );
  2984.           break;
  2985.         case 0x83:  /* UNKNOWN */
  2986.         case 0x84:  /* UNKNOWN */
  2987.           Ins_UNKNOWN( EXEC_ARG_ args );
  2988.           break;
  2989.         case 0x85:  /* SCANCTRL */
  2990.           Ins_SCANCTRL( EXEC_ARG_ args );
  2991.           break;
  2992.         case 0x86:  /* SDPVTL */
  2993.         case 0x87:  /* SDPVTL */
  2994.           Ins_SDPVTL( EXEC_ARG_ args );
  2995.           break;
  2996.         case 0x88:  /* GETINFO */
  2997.           Ins_GETINFO( EXEC_ARG_ args );
  2998.           break;
  2999.         case 0x89:  /* IDEF */
  3000.           Ins_IDEF( EXEC_ARG_ args );
  3001.           break;
  3002.         case 0x8A:  /* ROLL */
  3003.           Ins_ROLL( EXEC_ARG_ args );
  3004.           break;
  3005.         case 0x8B:  /* MAX */
  3006.           DO_MAX
  3007.           break;
  3008.         case 0x8C:  /* MIN */
  3009.           DO_MIN
  3010.           break;
  3011.         case 0x8D:  /* SCANTYPE */
  3012.           Ins_SCANTYPE( EXEC_ARG_ args );
  3013.           break;
  3014.         case 0x8E:  /* INSTCTRL */
  3015.           Ins_INSTCTRL( EXEC_ARG_ args );
  3016.           break;
  3017.         case 0x8F:
  3018.           Ins_UNKNOWN( EXEC_ARG_ args );
  3019.           break;
  3020.         default:
  3021.           if ( opcode >= 0xE0 )
  3022.             Ins_MIRP( EXEC_ARG_ args );
  3023.           else if ( opcode >= 0xC0 )
  3024.             Ins_MDRP( EXEC_ARG_ args );
  3025.           else if ( opcode >= 0xB8 )
  3026.             Ins_PUSHW( EXEC_ARG_ args );
  3027.           else if ( opcode >= 0xB0 )
  3028.             Ins_PUSHB( EXEC_ARG_ args );
  3029.           else
  3030.             Ins_UNKNOWN( EXEC_ARG_ args );
  3031.         }
  3032.       }
  3033. #else
  3034.       Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
  3035. #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
  3036.       if ( CUR.error != TT_Err_Ok )
  3037.       {
  3038.         switch ( CUR.error )
  3039.         {
  3040.         case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
  3041.           {
  3042.             TT_DefRecord*  def   = CUR.IDefs;
  3043.             TT_DefRecord*  limit = def + CUR.numIDefs;
  3044.             for ( ; def < limit; def++ )
  3045.             {
  3046.               if ( def->active && CUR.opcode == (FT_Byte)def->opc )
  3047.               {
  3048.                 TT_CallRec*  callrec;
  3049.                 if ( CUR.callTop >= CUR.callSize )
  3050.                 {
  3051.                   CUR.error = TT_Err_Invalid_Reference;
  3052.                   goto LErrorLabel_;
  3053.                 }
  3054.                 callrec = &CUR.callStack[CUR.callTop];
  3055.                 callrec->Caller_Range = CUR.curRange;
  3056.                 callrec->Caller_IP    = CUR.IP + 1;
  3057.                 callrec->Cur_Count    = 1;
  3058.                 callrec->Cur_Restart  = def->start;
  3059.                 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
  3060.                   goto LErrorLabel_;
  3061.                 goto LSuiteLabel_;
  3062.               }
  3063.             }
  3064.           }
  3065.           CUR.error = TT_Err_Invalid_Opcode;
  3066.           goto LErrorLabel_;
  3067. #if 0
  3068.           break;   /* Unreachable code warning suppression.             */
  3069.                    /* Leave to remind in case a later change the editor */
  3070.                    /* to consider break;                                */
  3071. #endif
  3072.         default:
  3073.           goto LErrorLabel_;
  3074. #if 0
  3075.         break;
  3076. #endif
  3077.         }
  3078.       }
  3079.       CUR.top = CUR.new_top;
  3080.       if ( CUR.step_ins )
  3081.         CUR.IP += CUR.length;
  3082.       /* increment instruction counter and check if we didn't */
  3083.       /* run this program for too long (e.g. infinite loops). */
  3084.       if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
  3085.         return TT_Err_Execution_Too_Long;
  3086.     LSuiteLabel_:
  3087.       if ( CUR.IP >= CUR.codeSize )
  3088.       {
  3089.         if ( CUR.callTop > 0 )
  3090.         {
  3091.           CUR.error = TT_Err_Code_Overflow;
  3092.           goto LErrorLabel_;
  3093.         }
  3094.         else
  3095.           goto LNo_Error_;
  3096.       }
  3097.     } while ( !CUR.instruction_trap );
  3098.   LNo_Error_:
  3099. #ifdef TT_CONFIG_OPTION_STATIC_RASTER
  3100.     *exc = cur;
  3101. #endif
  3102.     return TT_Err_Ok;
  3103.   LErrorCodeOverflow_:
  3104.     CUR.error = TT_Err_Code_Overflow;
  3105.   LErrorLabel_:
  3106. #ifdef TT_CONFIG_OPTION_STATIC_RASTER
  3107.     *exc = cur;
  3108. #endif
  3109.     return CUR.error;
  3110.   }
  3111. #endif /* TT_USE_BYTECODE_INTERPRETER */
  3112. /* END */