xref: /inferno-os/libfreetype/ttinterp.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ttinterp.c                                                             */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    TrueType bytecode interpreter (body).                                */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
21*37da2899SCharles.Forsyth #include FT_INTERNAL_CALC_H
22*37da2899SCharles.Forsyth #include FT_TRIGONOMETRY_H
23*37da2899SCharles.Forsyth #include FT_SYSTEM_H
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth #include "ttinterp.h"
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth #include "tterrors.h"
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth 
33*37da2899SCharles.Forsyth #define TT_MULFIX  FT_MulFix
34*37da2899SCharles.Forsyth #define TT_MULDIV  FT_MulDiv
35*37da2899SCharles.Forsyth #define TT_INT64   FT_Int64
36*37da2899SCharles.Forsyth 
37*37da2899SCharles.Forsyth   /*************************************************************************/
38*37da2899SCharles.Forsyth   /*                                                                       */
39*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
40*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
41*37da2899SCharles.Forsyth   /* messages during execution.                                            */
42*37da2899SCharles.Forsyth   /*                                                                       */
43*37da2899SCharles.Forsyth #undef  FT_COMPONENT
44*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_ttinterp
45*37da2899SCharles.Forsyth 
46*37da2899SCharles.Forsyth #undef  NO_APPLE_PATENT
47*37da2899SCharles.Forsyth #define APPLE_THRESHOLD  0x4000000L
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth   /*************************************************************************/
50*37da2899SCharles.Forsyth   /*                                                                       */
51*37da2899SCharles.Forsyth   /* In order to detect infinite loops in the code, we set up a counter    */
52*37da2899SCharles.Forsyth   /* within the run loop.  A single stroke of interpretation is now        */
53*37da2899SCharles.Forsyth   /* limitet to a maximal number of opcodes defined below.                 */
54*37da2899SCharles.Forsyth   /*                                                                       */
55*37da2899SCharles.Forsyth #define MAX_RUNNABLE_OPCODES  1000000L
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth 
58*37da2899SCharles.Forsyth   /*************************************************************************/
59*37da2899SCharles.Forsyth   /*                                                                       */
60*37da2899SCharles.Forsyth   /* There are two kinds of implementations:                               */
61*37da2899SCharles.Forsyth   /*                                                                       */
62*37da2899SCharles.Forsyth   /* a. static implementation                                              */
63*37da2899SCharles.Forsyth   /*                                                                       */
64*37da2899SCharles.Forsyth   /*    The current execution context is a static variable, which fields   */
65*37da2899SCharles.Forsyth   /*    are accessed directly by the interpreter during execution.  The    */
66*37da2899SCharles.Forsyth   /*    context is named `cur'.                                            */
67*37da2899SCharles.Forsyth   /*                                                                       */
68*37da2899SCharles.Forsyth   /*    This version is non-reentrant, of course.                          */
69*37da2899SCharles.Forsyth   /*                                                                       */
70*37da2899SCharles.Forsyth   /* b. indirect implementation                                            */
71*37da2899SCharles.Forsyth   /*                                                                       */
72*37da2899SCharles.Forsyth   /*    The current execution context is passed to _each_ function as its  */
73*37da2899SCharles.Forsyth   /*    first argument, and each field is thus accessed indirectly.        */
74*37da2899SCharles.Forsyth   /*                                                                       */
75*37da2899SCharles.Forsyth   /*    This version is fully re-entrant.                                  */
76*37da2899SCharles.Forsyth   /*                                                                       */
77*37da2899SCharles.Forsyth   /* The idea is that an indirect implementation may be slower to execute  */
78*37da2899SCharles.Forsyth   /* on low-end processors that are used in some systems (like 386s or     */
79*37da2899SCharles.Forsyth   /* even 486s).                                                           */
80*37da2899SCharles.Forsyth   /*                                                                       */
81*37da2899SCharles.Forsyth   /* As a consequence, the indirect implementation is now the default, as  */
82*37da2899SCharles.Forsyth   /* its performance costs can be considered negligible in our context.    */
83*37da2899SCharles.Forsyth   /* Note, however, that we kept the same source with macros because:      */
84*37da2899SCharles.Forsyth   /*                                                                       */
85*37da2899SCharles.Forsyth   /* - The code is kept very close in design to the Pascal code used for   */
86*37da2899SCharles.Forsyth   /*   development.                                                        */
87*37da2899SCharles.Forsyth   /*                                                                       */
88*37da2899SCharles.Forsyth   /* - It's much more readable that way!                                   */
89*37da2899SCharles.Forsyth   /*                                                                       */
90*37da2899SCharles.Forsyth   /* - It's still open to experimentation and tuning.                      */
91*37da2899SCharles.Forsyth   /*                                                                       */
92*37da2899SCharles.Forsyth   /*************************************************************************/
93*37da2899SCharles.Forsyth 
94*37da2899SCharles.Forsyth 
95*37da2899SCharles.Forsyth #ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth #define CUR  (*exc)                             /* see ttobjs.h */
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth #else                                           /* static implementation */
100*37da2899SCharles.Forsyth 
101*37da2899SCharles.Forsyth #define CUR  cur
102*37da2899SCharles.Forsyth 
103*37da2899SCharles.Forsyth   static
104*37da2899SCharles.Forsyth   TT_ExecContextRec  cur;   /* static exec. context variable */
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth   /* apparently, we have a _lot_ of direct indexing when accessing  */
107*37da2899SCharles.Forsyth   /* the static `cur', which makes the code bigger (due to all the  */
108*37da2899SCharles.Forsyth   /* four bytes addresses).                                         */
109*37da2899SCharles.Forsyth 
110*37da2899SCharles.Forsyth #endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
111*37da2899SCharles.Forsyth 
112*37da2899SCharles.Forsyth 
113*37da2899SCharles.Forsyth   /*************************************************************************/
114*37da2899SCharles.Forsyth   /*                                                                       */
115*37da2899SCharles.Forsyth   /* The instruction argument stack.                                       */
116*37da2899SCharles.Forsyth   /*                                                                       */
117*37da2899SCharles.Forsyth #define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */
118*37da2899SCharles.Forsyth 
119*37da2899SCharles.Forsyth 
120*37da2899SCharles.Forsyth   /*************************************************************************/
121*37da2899SCharles.Forsyth   /*                                                                       */
122*37da2899SCharles.Forsyth   /* This macro is used whenever `exec' is unused in a function, to avoid  */
123*37da2899SCharles.Forsyth   /* stupid warnings from pedantic compilers.                              */
124*37da2899SCharles.Forsyth   /*                                                                       */
125*37da2899SCharles.Forsyth #define FT_UNUSED_EXEC  FT_UNUSED( CUR )
126*37da2899SCharles.Forsyth 
127*37da2899SCharles.Forsyth 
128*37da2899SCharles.Forsyth   /*************************************************************************/
129*37da2899SCharles.Forsyth   /*                                                                       */
130*37da2899SCharles.Forsyth   /* This macro is used whenever `args' is unused in a function, to avoid  */
131*37da2899SCharles.Forsyth   /* stupid warnings from pedantic compilers.                              */
132*37da2899SCharles.Forsyth   /*                                                                       */
133*37da2899SCharles.Forsyth #define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
134*37da2899SCharles.Forsyth 
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth   /*************************************************************************/
137*37da2899SCharles.Forsyth   /*                                                                       */
138*37da2899SCharles.Forsyth   /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
139*37da2899SCharles.Forsyth   /* increase readabilty of the code.                                      */
140*37da2899SCharles.Forsyth   /*                                                                       */
141*37da2899SCharles.Forsyth   /*************************************************************************/
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth #define SKIP_Code() \
145*37da2899SCharles.Forsyth           SkipCode( EXEC_ARG )
146*37da2899SCharles.Forsyth 
147*37da2899SCharles.Forsyth #define GET_ShortIns() \
148*37da2899SCharles.Forsyth           GetShortIns( EXEC_ARG )
149*37da2899SCharles.Forsyth 
150*37da2899SCharles.Forsyth #define NORMalize( x, y, v ) \
151*37da2899SCharles.Forsyth           Normalize( EXEC_ARG_ x, y, v )
152*37da2899SCharles.Forsyth 
153*37da2899SCharles.Forsyth #define SET_SuperRound( scale, flags ) \
154*37da2899SCharles.Forsyth           SetSuperRound( EXEC_ARG_ scale, flags )
155*37da2899SCharles.Forsyth 
156*37da2899SCharles.Forsyth #define ROUND_None( d, c ) \
157*37da2899SCharles.Forsyth           Round_None( EXEC_ARG_ d, c )
158*37da2899SCharles.Forsyth 
159*37da2899SCharles.Forsyth #define INS_Goto_CodeRange( range, ip ) \
160*37da2899SCharles.Forsyth           Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth #define CUR_Func_project( x, y ) \
163*37da2899SCharles.Forsyth           CUR.func_project( EXEC_ARG_ x, y )
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth #define CUR_Func_move( z, p, d ) \
166*37da2899SCharles.Forsyth           CUR.func_move( EXEC_ARG_ z, p, d )
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth #define CUR_Func_dualproj( x, y ) \
169*37da2899SCharles.Forsyth           CUR.func_dualproj( EXEC_ARG_ x, y )
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth #define CUR_Func_freeProj( x, y ) \
172*37da2899SCharles.Forsyth           CUR.func_freeProj( EXEC_ARG_ x, y )
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth #define CUR_Func_round( d, c ) \
175*37da2899SCharles.Forsyth           CUR.func_round( EXEC_ARG_ d, c )
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth #define CUR_Func_read_cvt( index ) \
178*37da2899SCharles.Forsyth           CUR.func_read_cvt( EXEC_ARG_ index )
179*37da2899SCharles.Forsyth 
180*37da2899SCharles.Forsyth #define CUR_Func_write_cvt( index, val ) \
181*37da2899SCharles.Forsyth           CUR.func_write_cvt( EXEC_ARG_ index, val )
182*37da2899SCharles.Forsyth 
183*37da2899SCharles.Forsyth #define CUR_Func_move_cvt( index, val ) \
184*37da2899SCharles.Forsyth           CUR.func_move_cvt( EXEC_ARG_ index, val )
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth #define CURRENT_Ratio() \
187*37da2899SCharles.Forsyth           Current_Ratio( EXEC_ARG )
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth #define CURRENT_Ppem() \
190*37da2899SCharles.Forsyth           Current_Ppem( EXEC_ARG )
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth #define CUR_Ppem() \
193*37da2899SCharles.Forsyth           Cur_PPEM( EXEC_ARG )
194*37da2899SCharles.Forsyth 
195*37da2899SCharles.Forsyth #define INS_SxVTL( a, b, c, d ) \
196*37da2899SCharles.Forsyth           Ins_SxVTL( EXEC_ARG_ a, b, c, d )
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth #define COMPUTE_Funcs() \
199*37da2899SCharles.Forsyth           Compute_Funcs( EXEC_ARG )
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth #define COMPUTE_Round( a ) \
202*37da2899SCharles.Forsyth           Compute_Round( EXEC_ARG_ a )
203*37da2899SCharles.Forsyth 
204*37da2899SCharles.Forsyth #define COMPUTE_Point_Displacement( a, b, c, d ) \
205*37da2899SCharles.Forsyth           Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth #define MOVE_Zp2_Point( a, b, c, t ) \
208*37da2899SCharles.Forsyth           Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
209*37da2899SCharles.Forsyth 
210*37da2899SCharles.Forsyth 
211*37da2899SCharles.Forsyth   /*************************************************************************/
212*37da2899SCharles.Forsyth   /*                                                                       */
213*37da2899SCharles.Forsyth   /* Instruction dispatch function, as used by the interpreter.            */
214*37da2899SCharles.Forsyth   /*                                                                       */
215*37da2899SCharles.Forsyth   typedef void  (*TInstruction_Function)( INS_ARG );
216*37da2899SCharles.Forsyth 
217*37da2899SCharles.Forsyth 
218*37da2899SCharles.Forsyth   /*************************************************************************/
219*37da2899SCharles.Forsyth   /*                                                                       */
220*37da2899SCharles.Forsyth   /* A simple bounds-checking macro.                                       */
221*37da2899SCharles.Forsyth   /*                                                                       */
222*37da2899SCharles.Forsyth #define BOUNDS( x, n )  ( (FT_UInt)(x) >= (FT_UInt)(n) )
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth #undef  SUCCESS
226*37da2899SCharles.Forsyth #define SUCCESS  0
227*37da2899SCharles.Forsyth 
228*37da2899SCharles.Forsyth #undef  FAILURE
229*37da2899SCharles.Forsyth #define FAILURE  1
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth   /*************************************************************************/
233*37da2899SCharles.Forsyth   /*                                                                       */
234*37da2899SCharles.Forsyth   /*                        CODERANGE FUNCTIONS                            */
235*37da2899SCharles.Forsyth   /*                                                                       */
236*37da2899SCharles.Forsyth   /*************************************************************************/
237*37da2899SCharles.Forsyth 
238*37da2899SCharles.Forsyth 
239*37da2899SCharles.Forsyth   /*************************************************************************/
240*37da2899SCharles.Forsyth   /*                                                                       */
241*37da2899SCharles.Forsyth   /* <Function>                                                            */
242*37da2899SCharles.Forsyth   /*    TT_Goto_CodeRange                                                  */
243*37da2899SCharles.Forsyth   /*                                                                       */
244*37da2899SCharles.Forsyth   /* <Description>                                                         */
245*37da2899SCharles.Forsyth   /*    Switches to a new code range (updates the code related elements in */
246*37da2899SCharles.Forsyth   /*    `exec', and `IP').                                                 */
247*37da2899SCharles.Forsyth   /*                                                                       */
248*37da2899SCharles.Forsyth   /* <Input>                                                               */
249*37da2899SCharles.Forsyth   /*    range :: The new execution code range.                             */
250*37da2899SCharles.Forsyth   /*                                                                       */
251*37da2899SCharles.Forsyth   /*    IP    :: The new IP in the new code range.                         */
252*37da2899SCharles.Forsyth   /*                                                                       */
253*37da2899SCharles.Forsyth   /* <InOut>                                                               */
254*37da2899SCharles.Forsyth   /*    exec  :: The target execution context.                             */
255*37da2899SCharles.Forsyth   /*                                                                       */
256*37da2899SCharles.Forsyth   /* <Return>                                                              */
257*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
258*37da2899SCharles.Forsyth   /*                                                                       */
259*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Goto_CodeRange(TT_ExecContext exec,FT_Int range,FT_Long IP)260*37da2899SCharles.Forsyth   TT_Goto_CodeRange( TT_ExecContext  exec,
261*37da2899SCharles.Forsyth                      FT_Int          range,
262*37da2899SCharles.Forsyth                      FT_Long         IP )
263*37da2899SCharles.Forsyth   {
264*37da2899SCharles.Forsyth     TT_CodeRange*  coderange;
265*37da2899SCharles.Forsyth 
266*37da2899SCharles.Forsyth 
267*37da2899SCharles.Forsyth     FT_ASSERT( range >= 1 && range <= 3 );
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth     coderange = &exec->codeRangeTable[range - 1];
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth     FT_ASSERT( coderange->base != NULL );
272*37da2899SCharles.Forsyth 
273*37da2899SCharles.Forsyth     /* NOTE: Because the last instruction of a program may be a CALL */
274*37da2899SCharles.Forsyth     /*       which will return to the first byte *after* the code    */
275*37da2899SCharles.Forsyth     /*       range, we test for IP <= Size instead of IP < Size.     */
276*37da2899SCharles.Forsyth     /*                                                               */
277*37da2899SCharles.Forsyth     FT_ASSERT( (FT_ULong)IP <= coderange->size );
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth     exec->code     = coderange->base;
280*37da2899SCharles.Forsyth     exec->codeSize = coderange->size;
281*37da2899SCharles.Forsyth     exec->IP       = IP;
282*37da2899SCharles.Forsyth     exec->curRange = range;
283*37da2899SCharles.Forsyth 
284*37da2899SCharles.Forsyth     return TT_Err_Ok;
285*37da2899SCharles.Forsyth   }
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth   /*************************************************************************/
289*37da2899SCharles.Forsyth   /*                                                                       */
290*37da2899SCharles.Forsyth   /* <Function>                                                            */
291*37da2899SCharles.Forsyth   /*    TT_Set_CodeRange                                                   */
292*37da2899SCharles.Forsyth   /*                                                                       */
293*37da2899SCharles.Forsyth   /* <Description>                                                         */
294*37da2899SCharles.Forsyth   /*    Sets a code range.                                                 */
295*37da2899SCharles.Forsyth   /*                                                                       */
296*37da2899SCharles.Forsyth   /* <Input>                                                               */
297*37da2899SCharles.Forsyth   /*    range  :: The code range index.                                    */
298*37da2899SCharles.Forsyth   /*                                                                       */
299*37da2899SCharles.Forsyth   /*    base   :: The new code base.                                       */
300*37da2899SCharles.Forsyth   /*                                                                       */
301*37da2899SCharles.Forsyth   /*    length :: The range size in bytes.                                 */
302*37da2899SCharles.Forsyth   /*                                                                       */
303*37da2899SCharles.Forsyth   /* <InOut>                                                               */
304*37da2899SCharles.Forsyth   /*    exec   :: The target execution context.                            */
305*37da2899SCharles.Forsyth   /*                                                                       */
306*37da2899SCharles.Forsyth   /* <Return>                                                              */
307*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
308*37da2899SCharles.Forsyth   /*                                                                       */
309*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Set_CodeRange(TT_ExecContext exec,FT_Int range,void * base,FT_Long length)310*37da2899SCharles.Forsyth   TT_Set_CodeRange( TT_ExecContext  exec,
311*37da2899SCharles.Forsyth                     FT_Int          range,
312*37da2899SCharles.Forsyth                     void*           base,
313*37da2899SCharles.Forsyth                     FT_Long         length )
314*37da2899SCharles.Forsyth   {
315*37da2899SCharles.Forsyth     FT_ASSERT( range >= 1 && range <= 3 );
316*37da2899SCharles.Forsyth 
317*37da2899SCharles.Forsyth     exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
318*37da2899SCharles.Forsyth     exec->codeRangeTable[range - 1].size = length;
319*37da2899SCharles.Forsyth 
320*37da2899SCharles.Forsyth     return TT_Err_Ok;
321*37da2899SCharles.Forsyth   }
322*37da2899SCharles.Forsyth 
323*37da2899SCharles.Forsyth 
324*37da2899SCharles.Forsyth   /*************************************************************************/
325*37da2899SCharles.Forsyth   /*                                                                       */
326*37da2899SCharles.Forsyth   /* <Function>                                                            */
327*37da2899SCharles.Forsyth   /*    TT_Clear_CodeRange                                                 */
328*37da2899SCharles.Forsyth   /*                                                                       */
329*37da2899SCharles.Forsyth   /* <Description>                                                         */
330*37da2899SCharles.Forsyth   /*    Clears a code range.                                               */
331*37da2899SCharles.Forsyth   /*                                                                       */
332*37da2899SCharles.Forsyth   /* <Input>                                                               */
333*37da2899SCharles.Forsyth   /*    range :: The code range index.                                     */
334*37da2899SCharles.Forsyth   /*                                                                       */
335*37da2899SCharles.Forsyth   /* <InOut>                                                               */
336*37da2899SCharles.Forsyth   /*    exec  :: The target execution context.                             */
337*37da2899SCharles.Forsyth   /*                                                                       */
338*37da2899SCharles.Forsyth   /* <Return>                                                              */
339*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
340*37da2899SCharles.Forsyth   /*                                                                       */
341*37da2899SCharles.Forsyth   /* <Note>                                                                */
342*37da2899SCharles.Forsyth   /*    Does not set the Error variable.                                   */
343*37da2899SCharles.Forsyth   /*                                                                       */
344*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Clear_CodeRange(TT_ExecContext exec,FT_Int range)345*37da2899SCharles.Forsyth   TT_Clear_CodeRange( TT_ExecContext  exec,
346*37da2899SCharles.Forsyth                       FT_Int          range )
347*37da2899SCharles.Forsyth   {
348*37da2899SCharles.Forsyth     FT_ASSERT( range >= 1 && range <= 3 );
349*37da2899SCharles.Forsyth 
350*37da2899SCharles.Forsyth     exec->codeRangeTable[range - 1].base = NULL;
351*37da2899SCharles.Forsyth     exec->codeRangeTable[range - 1].size = 0;
352*37da2899SCharles.Forsyth 
353*37da2899SCharles.Forsyth     return TT_Err_Ok;
354*37da2899SCharles.Forsyth   }
355*37da2899SCharles.Forsyth 
356*37da2899SCharles.Forsyth 
357*37da2899SCharles.Forsyth   /*************************************************************************/
358*37da2899SCharles.Forsyth   /*                                                                       */
359*37da2899SCharles.Forsyth   /*                   EXECUTION CONTEXT ROUTINES                          */
360*37da2899SCharles.Forsyth   /*                                                                       */
361*37da2899SCharles.Forsyth   /*************************************************************************/
362*37da2899SCharles.Forsyth 
363*37da2899SCharles.Forsyth 
364*37da2899SCharles.Forsyth   /*************************************************************************/
365*37da2899SCharles.Forsyth   /*                                                                       */
366*37da2899SCharles.Forsyth   /* <Function>                                                            */
367*37da2899SCharles.Forsyth   /*    TT_Destroy_Context                                                 */
368*37da2899SCharles.Forsyth   /*                                                                       */
369*37da2899SCharles.Forsyth   /* <Description>                                                         */
370*37da2899SCharles.Forsyth   /*    Destroys a given context.                                          */
371*37da2899SCharles.Forsyth   /*                                                                       */
372*37da2899SCharles.Forsyth   /* <Input>                                                               */
373*37da2899SCharles.Forsyth   /*    exec   :: A handle to the target execution context.                */
374*37da2899SCharles.Forsyth   /*                                                                       */
375*37da2899SCharles.Forsyth   /*    memory :: A handle to the parent memory object.                    */
376*37da2899SCharles.Forsyth   /*                                                                       */
377*37da2899SCharles.Forsyth   /* <Return>                                                              */
378*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
379*37da2899SCharles.Forsyth   /*                                                                       */
380*37da2899SCharles.Forsyth   /* <Note>                                                                */
381*37da2899SCharles.Forsyth   /*    Only the glyph loader and debugger should call this function.      */
382*37da2899SCharles.Forsyth   /*                                                                       */
383*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Destroy_Context(TT_ExecContext exec,FT_Memory memory)384*37da2899SCharles.Forsyth   TT_Destroy_Context( TT_ExecContext  exec,
385*37da2899SCharles.Forsyth                       FT_Memory       memory )
386*37da2899SCharles.Forsyth   {
387*37da2899SCharles.Forsyth     /* free composite load stack */
388*37da2899SCharles.Forsyth     FT_FREE( exec->loadStack );
389*37da2899SCharles.Forsyth     exec->loadSize = 0;
390*37da2899SCharles.Forsyth 
391*37da2899SCharles.Forsyth     /* points zone */
392*37da2899SCharles.Forsyth     exec->maxPoints   = 0;
393*37da2899SCharles.Forsyth     exec->maxContours = 0;
394*37da2899SCharles.Forsyth 
395*37da2899SCharles.Forsyth     /* free stack */
396*37da2899SCharles.Forsyth     FT_FREE( exec->stack );
397*37da2899SCharles.Forsyth     exec->stackSize = 0;
398*37da2899SCharles.Forsyth 
399*37da2899SCharles.Forsyth     /* free call stack */
400*37da2899SCharles.Forsyth     FT_FREE( exec->callStack );
401*37da2899SCharles.Forsyth     exec->callSize = 0;
402*37da2899SCharles.Forsyth     exec->callTop  = 0;
403*37da2899SCharles.Forsyth 
404*37da2899SCharles.Forsyth     /* free glyph code range */
405*37da2899SCharles.Forsyth     FT_FREE( exec->glyphIns );
406*37da2899SCharles.Forsyth     exec->glyphSize = 0;
407*37da2899SCharles.Forsyth 
408*37da2899SCharles.Forsyth     exec->size = NULL;
409*37da2899SCharles.Forsyth     exec->face = NULL;
410*37da2899SCharles.Forsyth 
411*37da2899SCharles.Forsyth     FT_FREE( exec );
412*37da2899SCharles.Forsyth     return TT_Err_Ok;
413*37da2899SCharles.Forsyth   }
414*37da2899SCharles.Forsyth 
415*37da2899SCharles.Forsyth 
416*37da2899SCharles.Forsyth   /*************************************************************************/
417*37da2899SCharles.Forsyth   /*                                                                       */
418*37da2899SCharles.Forsyth   /* <Function>                                                            */
419*37da2899SCharles.Forsyth   /*    Init_Context                                                       */
420*37da2899SCharles.Forsyth   /*                                                                       */
421*37da2899SCharles.Forsyth   /* <Description>                                                         */
422*37da2899SCharles.Forsyth   /*    Initializes a context object.                                      */
423*37da2899SCharles.Forsyth   /*                                                                       */
424*37da2899SCharles.Forsyth   /* <Input>                                                               */
425*37da2899SCharles.Forsyth   /*    memory :: A handle to the parent memory object.                    */
426*37da2899SCharles.Forsyth   /*                                                                       */
427*37da2899SCharles.Forsyth   /*    face   :: A handle to the source TrueType face object.             */
428*37da2899SCharles.Forsyth   /*                                                                       */
429*37da2899SCharles.Forsyth   /* <InOut>                                                               */
430*37da2899SCharles.Forsyth   /*    exec   :: A handle to the target execution context.                */
431*37da2899SCharles.Forsyth   /*                                                                       */
432*37da2899SCharles.Forsyth   /* <Return>                                                              */
433*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
434*37da2899SCharles.Forsyth   /*                                                                       */
435*37da2899SCharles.Forsyth   static FT_Error
Init_Context(TT_ExecContext exec,TT_Face face,FT_Memory memory)436*37da2899SCharles.Forsyth   Init_Context( TT_ExecContext  exec,
437*37da2899SCharles.Forsyth                 TT_Face         face,
438*37da2899SCharles.Forsyth                 FT_Memory       memory )
439*37da2899SCharles.Forsyth   {
440*37da2899SCharles.Forsyth     FT_Error  error;
441*37da2899SCharles.Forsyth 
442*37da2899SCharles.Forsyth 
443*37da2899SCharles.Forsyth     FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n",
444*37da2899SCharles.Forsyth                 exec, face ));
445*37da2899SCharles.Forsyth 
446*37da2899SCharles.Forsyth     exec->memory   = memory;
447*37da2899SCharles.Forsyth     exec->callSize = 32;
448*37da2899SCharles.Forsyth 
449*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
450*37da2899SCharles.Forsyth       goto Fail_Memory;
451*37da2899SCharles.Forsyth 
452*37da2899SCharles.Forsyth     /* all values in the context are set to 0 already, but this is */
453*37da2899SCharles.Forsyth     /* here as a remainder                                         */
454*37da2899SCharles.Forsyth     exec->maxPoints   = 0;
455*37da2899SCharles.Forsyth     exec->maxContours = 0;
456*37da2899SCharles.Forsyth 
457*37da2899SCharles.Forsyth     exec->stackSize = 0;
458*37da2899SCharles.Forsyth     exec->loadSize  = 0;
459*37da2899SCharles.Forsyth     exec->glyphSize = 0;
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth     exec->stack     = NULL;
462*37da2899SCharles.Forsyth     exec->loadStack = NULL;
463*37da2899SCharles.Forsyth     exec->glyphIns  = NULL;
464*37da2899SCharles.Forsyth 
465*37da2899SCharles.Forsyth     exec->face = face;
466*37da2899SCharles.Forsyth     exec->size = NULL;
467*37da2899SCharles.Forsyth 
468*37da2899SCharles.Forsyth     return TT_Err_Ok;
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth   Fail_Memory:
471*37da2899SCharles.Forsyth     FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
472*37da2899SCharles.Forsyth                (FT_Long)exec ));
473*37da2899SCharles.Forsyth     TT_Destroy_Context( exec, memory );
474*37da2899SCharles.Forsyth 
475*37da2899SCharles.Forsyth     return error;
476*37da2899SCharles.Forsyth  }
477*37da2899SCharles.Forsyth 
478*37da2899SCharles.Forsyth 
479*37da2899SCharles.Forsyth   /*************************************************************************/
480*37da2899SCharles.Forsyth   /*                                                                       */
481*37da2899SCharles.Forsyth   /* <Function>                                                            */
482*37da2899SCharles.Forsyth   /*    Update_Max                                                         */
483*37da2899SCharles.Forsyth   /*                                                                       */
484*37da2899SCharles.Forsyth   /* <Description>                                                         */
485*37da2899SCharles.Forsyth   /*    Checks the size of a buffer and reallocates it if necessary.       */
486*37da2899SCharles.Forsyth   /*                                                                       */
487*37da2899SCharles.Forsyth   /* <Input>                                                               */
488*37da2899SCharles.Forsyth   /*    memory     :: A handle to the parent memory object.                */
489*37da2899SCharles.Forsyth   /*                                                                       */
490*37da2899SCharles.Forsyth   /*    multiplier :: The size in bytes of each element in the buffer.     */
491*37da2899SCharles.Forsyth   /*                                                                       */
492*37da2899SCharles.Forsyth   /*    new_max    :: The new capacity (size) of the buffer.               */
493*37da2899SCharles.Forsyth   /*                                                                       */
494*37da2899SCharles.Forsyth   /* <InOut>                                                               */
495*37da2899SCharles.Forsyth   /*    size       :: The address of the buffer's current size expressed   */
496*37da2899SCharles.Forsyth   /*                  in elements.                                         */
497*37da2899SCharles.Forsyth   /*                                                                       */
498*37da2899SCharles.Forsyth   /*    buff       :: The address of the buffer base pointer.              */
499*37da2899SCharles.Forsyth   /*                                                                       */
500*37da2899SCharles.Forsyth   /* <Return>                                                              */
501*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
502*37da2899SCharles.Forsyth   /*                                                                       */
503*37da2899SCharles.Forsyth   static FT_Error
Update_Max(FT_Memory memory,FT_ULong * size,FT_Long multiplier,void ** buff,FT_ULong new_max)504*37da2899SCharles.Forsyth   Update_Max( FT_Memory  memory,
505*37da2899SCharles.Forsyth               FT_ULong*  size,
506*37da2899SCharles.Forsyth               FT_Long    multiplier,
507*37da2899SCharles.Forsyth               void**     buff,
508*37da2899SCharles.Forsyth               FT_ULong   new_max )
509*37da2899SCharles.Forsyth   {
510*37da2899SCharles.Forsyth     FT_Error  error;
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth 
513*37da2899SCharles.Forsyth     if ( *size < new_max )
514*37da2899SCharles.Forsyth     {
515*37da2899SCharles.Forsyth       FT_FREE( *buff );
516*37da2899SCharles.Forsyth       if ( FT_ALLOC( *buff, new_max * multiplier ) )
517*37da2899SCharles.Forsyth         return error;
518*37da2899SCharles.Forsyth       *size = new_max;
519*37da2899SCharles.Forsyth     }
520*37da2899SCharles.Forsyth 
521*37da2899SCharles.Forsyth     return TT_Err_Ok;
522*37da2899SCharles.Forsyth   }
523*37da2899SCharles.Forsyth 
524*37da2899SCharles.Forsyth 
525*37da2899SCharles.Forsyth   /*************************************************************************/
526*37da2899SCharles.Forsyth   /*                                                                       */
527*37da2899SCharles.Forsyth   /* <Function>                                                            */
528*37da2899SCharles.Forsyth   /*    TT_Load_Context                                                    */
529*37da2899SCharles.Forsyth   /*                                                                       */
530*37da2899SCharles.Forsyth   /* <Description>                                                         */
531*37da2899SCharles.Forsyth   /*    Prepare an execution context for glyph hinting.                    */
532*37da2899SCharles.Forsyth   /*                                                                       */
533*37da2899SCharles.Forsyth   /* <Input>                                                               */
534*37da2899SCharles.Forsyth   /*    face :: A handle to the source face object.                        */
535*37da2899SCharles.Forsyth   /*                                                                       */
536*37da2899SCharles.Forsyth   /*    size :: A handle to the source size object.                        */
537*37da2899SCharles.Forsyth   /*                                                                       */
538*37da2899SCharles.Forsyth   /* <InOut>                                                               */
539*37da2899SCharles.Forsyth   /*    exec :: A handle to the target execution context.                  */
540*37da2899SCharles.Forsyth   /*                                                                       */
541*37da2899SCharles.Forsyth   /* <Return>                                                              */
542*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
543*37da2899SCharles.Forsyth   /*                                                                       */
544*37da2899SCharles.Forsyth   /* <Note>                                                                */
545*37da2899SCharles.Forsyth   /*    Only the glyph loader and debugger should call this function.      */
546*37da2899SCharles.Forsyth   /*                                                                       */
547*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Load_Context(TT_ExecContext exec,TT_Face face,TT_Size size)548*37da2899SCharles.Forsyth   TT_Load_Context( TT_ExecContext  exec,
549*37da2899SCharles.Forsyth                    TT_Face         face,
550*37da2899SCharles.Forsyth                    TT_Size         size )
551*37da2899SCharles.Forsyth   {
552*37da2899SCharles.Forsyth     FT_Int          i;
553*37da2899SCharles.Forsyth     FT_ULong        tmp;
554*37da2899SCharles.Forsyth     TT_MaxProfile*  maxp;
555*37da2899SCharles.Forsyth     FT_Error        error;
556*37da2899SCharles.Forsyth 
557*37da2899SCharles.Forsyth 
558*37da2899SCharles.Forsyth     exec->face = face;
559*37da2899SCharles.Forsyth     maxp       = &face->max_profile;
560*37da2899SCharles.Forsyth     exec->size = size;
561*37da2899SCharles.Forsyth 
562*37da2899SCharles.Forsyth     if ( size )
563*37da2899SCharles.Forsyth     {
564*37da2899SCharles.Forsyth       exec->numFDefs   = size->num_function_defs;
565*37da2899SCharles.Forsyth       exec->maxFDefs   = size->max_function_defs;
566*37da2899SCharles.Forsyth       exec->numIDefs   = size->num_instruction_defs;
567*37da2899SCharles.Forsyth       exec->maxIDefs   = size->max_instruction_defs;
568*37da2899SCharles.Forsyth       exec->FDefs      = size->function_defs;
569*37da2899SCharles.Forsyth       exec->IDefs      = size->instruction_defs;
570*37da2899SCharles.Forsyth       exec->tt_metrics = size->ttmetrics;
571*37da2899SCharles.Forsyth       exec->metrics    = size->root.metrics;
572*37da2899SCharles.Forsyth 
573*37da2899SCharles.Forsyth       exec->maxFunc    = size->max_func;
574*37da2899SCharles.Forsyth       exec->maxIns     = size->max_ins;
575*37da2899SCharles.Forsyth 
576*37da2899SCharles.Forsyth       for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
577*37da2899SCharles.Forsyth         exec->codeRangeTable[i] = size->codeRangeTable[i];
578*37da2899SCharles.Forsyth 
579*37da2899SCharles.Forsyth       /* set graphics state */
580*37da2899SCharles.Forsyth       exec->GS = size->GS;
581*37da2899SCharles.Forsyth 
582*37da2899SCharles.Forsyth       exec->cvtSize = size->cvt_size;
583*37da2899SCharles.Forsyth       exec->cvt     = size->cvt;
584*37da2899SCharles.Forsyth 
585*37da2899SCharles.Forsyth       exec->storeSize = size->storage_size;
586*37da2899SCharles.Forsyth       exec->storage   = size->storage;
587*37da2899SCharles.Forsyth 
588*37da2899SCharles.Forsyth       exec->twilight  = size->twilight;
589*37da2899SCharles.Forsyth     }
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth     error = Update_Max( exec->memory,
592*37da2899SCharles.Forsyth                         &exec->loadSize,
593*37da2899SCharles.Forsyth                         sizeof ( TT_SubGlyphRec ),
594*37da2899SCharles.Forsyth                         (void**)&exec->loadStack,
595*37da2899SCharles.Forsyth                         exec->face->max_components + 1 );
596*37da2899SCharles.Forsyth     if ( error )
597*37da2899SCharles.Forsyth       return error;
598*37da2899SCharles.Forsyth 
599*37da2899SCharles.Forsyth     /* XXX: We reserve a little more elements on the stack to deal safely */
600*37da2899SCharles.Forsyth     /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
601*37da2899SCharles.Forsyth     tmp = exec->stackSize;
602*37da2899SCharles.Forsyth     error = Update_Max( exec->memory,
603*37da2899SCharles.Forsyth                         &tmp,
604*37da2899SCharles.Forsyth                         sizeof ( FT_F26Dot6 ),
605*37da2899SCharles.Forsyth                         (void**)&exec->stack,
606*37da2899SCharles.Forsyth                         maxp->maxStackElements + 32 );
607*37da2899SCharles.Forsyth     exec->stackSize = (FT_UInt)tmp;
608*37da2899SCharles.Forsyth     if ( error )
609*37da2899SCharles.Forsyth       return error;
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth     tmp = exec->glyphSize;
612*37da2899SCharles.Forsyth     error = Update_Max( exec->memory,
613*37da2899SCharles.Forsyth                         &tmp,
614*37da2899SCharles.Forsyth                         sizeof ( FT_Byte ),
615*37da2899SCharles.Forsyth                         (void**)&exec->glyphIns,
616*37da2899SCharles.Forsyth                         maxp->maxSizeOfInstructions );
617*37da2899SCharles.Forsyth     exec->glyphSize = (FT_UShort)tmp;
618*37da2899SCharles.Forsyth     if ( error )
619*37da2899SCharles.Forsyth       return error;
620*37da2899SCharles.Forsyth 
621*37da2899SCharles.Forsyth     exec->pts.n_points   = 0;
622*37da2899SCharles.Forsyth     exec->pts.n_contours = 0;
623*37da2899SCharles.Forsyth 
624*37da2899SCharles.Forsyth     exec->instruction_trap = FALSE;
625*37da2899SCharles.Forsyth 
626*37da2899SCharles.Forsyth     return TT_Err_Ok;
627*37da2899SCharles.Forsyth   }
628*37da2899SCharles.Forsyth 
629*37da2899SCharles.Forsyth 
630*37da2899SCharles.Forsyth   /*************************************************************************/
631*37da2899SCharles.Forsyth   /*                                                                       */
632*37da2899SCharles.Forsyth   /* <Function>                                                            */
633*37da2899SCharles.Forsyth   /*    TT_Save_Context                                                    */
634*37da2899SCharles.Forsyth   /*                                                                       */
635*37da2899SCharles.Forsyth   /* <Description>                                                         */
636*37da2899SCharles.Forsyth   /*    Saves the code ranges in a `size' object.                          */
637*37da2899SCharles.Forsyth   /*                                                                       */
638*37da2899SCharles.Forsyth   /* <Input>                                                               */
639*37da2899SCharles.Forsyth   /*    exec :: A handle to the source execution context.                  */
640*37da2899SCharles.Forsyth   /*                                                                       */
641*37da2899SCharles.Forsyth   /* <InOut>                                                               */
642*37da2899SCharles.Forsyth   /*    size :: A handle to the target size object.                        */
643*37da2899SCharles.Forsyth   /*                                                                       */
644*37da2899SCharles.Forsyth   /* <Return>                                                              */
645*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
646*37da2899SCharles.Forsyth   /*                                                                       */
647*37da2899SCharles.Forsyth   /* <Note>                                                                */
648*37da2899SCharles.Forsyth   /*    Only the glyph loader and debugger should call this function.      */
649*37da2899SCharles.Forsyth   /*                                                                       */
650*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Save_Context(TT_ExecContext exec,TT_Size size)651*37da2899SCharles.Forsyth   TT_Save_Context( TT_ExecContext  exec,
652*37da2899SCharles.Forsyth                    TT_Size         size )
653*37da2899SCharles.Forsyth   {
654*37da2899SCharles.Forsyth     FT_Int  i;
655*37da2899SCharles.Forsyth 
656*37da2899SCharles.Forsyth 
657*37da2899SCharles.Forsyth     /* XXXX: Will probably disappear soon with all the code range */
658*37da2899SCharles.Forsyth     /*       management, which is now rather obsolete.            */
659*37da2899SCharles.Forsyth     /*                                                            */
660*37da2899SCharles.Forsyth     size->num_function_defs    = exec->numFDefs;
661*37da2899SCharles.Forsyth     size->num_instruction_defs = exec->numIDefs;
662*37da2899SCharles.Forsyth 
663*37da2899SCharles.Forsyth     size->max_func = exec->maxFunc;
664*37da2899SCharles.Forsyth     size->max_ins  = exec->maxIns;
665*37da2899SCharles.Forsyth 
666*37da2899SCharles.Forsyth     for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
667*37da2899SCharles.Forsyth       size->codeRangeTable[i] = exec->codeRangeTable[i];
668*37da2899SCharles.Forsyth 
669*37da2899SCharles.Forsyth     return TT_Err_Ok;
670*37da2899SCharles.Forsyth   }
671*37da2899SCharles.Forsyth 
672*37da2899SCharles.Forsyth 
673*37da2899SCharles.Forsyth   /*************************************************************************/
674*37da2899SCharles.Forsyth   /*                                                                       */
675*37da2899SCharles.Forsyth   /* <Function>                                                            */
676*37da2899SCharles.Forsyth   /*    TT_Run_Context                                                     */
677*37da2899SCharles.Forsyth   /*                                                                       */
678*37da2899SCharles.Forsyth   /* <Description>                                                         */
679*37da2899SCharles.Forsyth   /*    Executes one or more instructions in the execution context.        */
680*37da2899SCharles.Forsyth   /*                                                                       */
681*37da2899SCharles.Forsyth   /* <Input>                                                               */
682*37da2899SCharles.Forsyth   /*    debug :: A Boolean flag.  If set, the function sets some internal  */
683*37da2899SCharles.Forsyth   /*             variables and returns immediately, otherwise TT_RunIns()  */
684*37da2899SCharles.Forsyth   /*             is called.                                                */
685*37da2899SCharles.Forsyth   /*                                                                       */
686*37da2899SCharles.Forsyth   /*             This is commented out currently.                          */
687*37da2899SCharles.Forsyth   /*                                                                       */
688*37da2899SCharles.Forsyth   /* <Input>                                                               */
689*37da2899SCharles.Forsyth   /*    exec  :: A handle to the target execution context.                 */
690*37da2899SCharles.Forsyth   /*                                                                       */
691*37da2899SCharles.Forsyth   /* <Return>                                                              */
692*37da2899SCharles.Forsyth   /*    TrueTyoe error code.  0 means success.                             */
693*37da2899SCharles.Forsyth   /*                                                                       */
694*37da2899SCharles.Forsyth   /* <Note>                                                                */
695*37da2899SCharles.Forsyth   /*    Only the glyph loader and debugger should call this function.      */
696*37da2899SCharles.Forsyth   /*                                                                       */
697*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Run_Context(TT_ExecContext exec,FT_Bool debug)698*37da2899SCharles.Forsyth   TT_Run_Context( TT_ExecContext  exec,
699*37da2899SCharles.Forsyth                   FT_Bool         debug )
700*37da2899SCharles.Forsyth   {
701*37da2899SCharles.Forsyth     FT_Error  error;
702*37da2899SCharles.Forsyth 
703*37da2899SCharles.Forsyth 
704*37da2899SCharles.Forsyth     if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0  ) )
705*37da2899SCharles.Forsyth            != TT_Err_Ok )
706*37da2899SCharles.Forsyth       return error;
707*37da2899SCharles.Forsyth 
708*37da2899SCharles.Forsyth     exec->zp0 = exec->pts;
709*37da2899SCharles.Forsyth     exec->zp1 = exec->pts;
710*37da2899SCharles.Forsyth     exec->zp2 = exec->pts;
711*37da2899SCharles.Forsyth 
712*37da2899SCharles.Forsyth     exec->GS.gep0 = 1;
713*37da2899SCharles.Forsyth     exec->GS.gep1 = 1;
714*37da2899SCharles.Forsyth     exec->GS.gep2 = 1;
715*37da2899SCharles.Forsyth 
716*37da2899SCharles.Forsyth     exec->GS.projVector.x = 0x4000;
717*37da2899SCharles.Forsyth     exec->GS.projVector.y = 0x0000;
718*37da2899SCharles.Forsyth 
719*37da2899SCharles.Forsyth     exec->GS.freeVector = exec->GS.projVector;
720*37da2899SCharles.Forsyth     exec->GS.dualVector = exec->GS.projVector;
721*37da2899SCharles.Forsyth 
722*37da2899SCharles.Forsyth     exec->GS.round_state = 1;
723*37da2899SCharles.Forsyth     exec->GS.loop        = 1;
724*37da2899SCharles.Forsyth 
725*37da2899SCharles.Forsyth     /* some glyphs leave something on the stack. so we clean it */
726*37da2899SCharles.Forsyth     /* before a new execution.                                  */
727*37da2899SCharles.Forsyth     exec->top     = 0;
728*37da2899SCharles.Forsyth     exec->callTop = 0;
729*37da2899SCharles.Forsyth 
730*37da2899SCharles.Forsyth #if 1
731*37da2899SCharles.Forsyth     FT_UNUSED( debug );
732*37da2899SCharles.Forsyth 
733*37da2899SCharles.Forsyth     return exec->face->interpreter( exec );
734*37da2899SCharles.Forsyth #else
735*37da2899SCharles.Forsyth     if ( !debug )
736*37da2899SCharles.Forsyth       return TT_RunIns( exec );
737*37da2899SCharles.Forsyth     else
738*37da2899SCharles.Forsyth       return TT_Err_Ok;
739*37da2899SCharles.Forsyth #endif
740*37da2899SCharles.Forsyth   }
741*37da2899SCharles.Forsyth 
742*37da2899SCharles.Forsyth 
743*37da2899SCharles.Forsyth   const TT_GraphicsState  tt_default_graphics_state =
744*37da2899SCharles.Forsyth   {
745*37da2899SCharles.Forsyth     0, 0, 0,
746*37da2899SCharles.Forsyth     { 0x4000, 0 },
747*37da2899SCharles.Forsyth     { 0x4000, 0 },
748*37da2899SCharles.Forsyth     { 0x4000, 0 },
749*37da2899SCharles.Forsyth     1, 64, 1,
750*37da2899SCharles.Forsyth     TRUE, 68, 0, 0, 9, 3,
751*37da2899SCharles.Forsyth     0, FALSE, 2, 1, 1, 1
752*37da2899SCharles.Forsyth   };
753*37da2899SCharles.Forsyth 
754*37da2899SCharles.Forsyth 
755*37da2899SCharles.Forsyth   /* documentation is in ttinterp.h */
756*37da2899SCharles.Forsyth 
757*37da2899SCharles.Forsyth   FT_EXPORT_DEF( TT_ExecContext )
TT_New_Context(TT_Face face)758*37da2899SCharles.Forsyth   TT_New_Context( TT_Face  face )
759*37da2899SCharles.Forsyth   {
760*37da2899SCharles.Forsyth     TT_Driver       driver;
761*37da2899SCharles.Forsyth     TT_ExecContext  exec;
762*37da2899SCharles.Forsyth     FT_Memory       memory;
763*37da2899SCharles.Forsyth 
764*37da2899SCharles.Forsyth 
765*37da2899SCharles.Forsyth     if ( !face )
766*37da2899SCharles.Forsyth       return 0;
767*37da2899SCharles.Forsyth 
768*37da2899SCharles.Forsyth     driver = (TT_Driver)face->root.driver;
769*37da2899SCharles.Forsyth 
770*37da2899SCharles.Forsyth     memory = driver->root.root.memory;
771*37da2899SCharles.Forsyth     exec   = driver->context;
772*37da2899SCharles.Forsyth 
773*37da2899SCharles.Forsyth     if ( !driver->context )
774*37da2899SCharles.Forsyth     {
775*37da2899SCharles.Forsyth       FT_Error  error;
776*37da2899SCharles.Forsyth 
777*37da2899SCharles.Forsyth 
778*37da2899SCharles.Forsyth       /* allocate object */
779*37da2899SCharles.Forsyth       if ( FT_NEW( exec ) )
780*37da2899SCharles.Forsyth         goto Exit;
781*37da2899SCharles.Forsyth 
782*37da2899SCharles.Forsyth       /* initialize it */
783*37da2899SCharles.Forsyth       error = Init_Context( exec, face, memory );
784*37da2899SCharles.Forsyth       if ( error )
785*37da2899SCharles.Forsyth         goto Fail;
786*37da2899SCharles.Forsyth 
787*37da2899SCharles.Forsyth       /* store it into the driver */
788*37da2899SCharles.Forsyth       driver->context = exec;
789*37da2899SCharles.Forsyth     }
790*37da2899SCharles.Forsyth 
791*37da2899SCharles.Forsyth   Exit:
792*37da2899SCharles.Forsyth     return driver->context;
793*37da2899SCharles.Forsyth 
794*37da2899SCharles.Forsyth   Fail:
795*37da2899SCharles.Forsyth     FT_FREE( exec );
796*37da2899SCharles.Forsyth 
797*37da2899SCharles.Forsyth     return 0;
798*37da2899SCharles.Forsyth   }
799*37da2899SCharles.Forsyth 
800*37da2899SCharles.Forsyth 
801*37da2899SCharles.Forsyth   /*************************************************************************/
802*37da2899SCharles.Forsyth   /*                                                                       */
803*37da2899SCharles.Forsyth   /* <Function>                                                            */
804*37da2899SCharles.Forsyth   /*    TT_Done_Context                                                    */
805*37da2899SCharles.Forsyth   /*                                                                       */
806*37da2899SCharles.Forsyth   /* <Description>                                                         */
807*37da2899SCharles.Forsyth   /*    Discards an execution context.                                     */
808*37da2899SCharles.Forsyth   /*                                                                       */
809*37da2899SCharles.Forsyth   /* <Input>                                                               */
810*37da2899SCharles.Forsyth   /*    exec :: A handle to the target execution context.                  */
811*37da2899SCharles.Forsyth   /*                                                                       */
812*37da2899SCharles.Forsyth   /* <Return>                                                              */
813*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
814*37da2899SCharles.Forsyth   /*                                                                       */
815*37da2899SCharles.Forsyth   /* <Note>                                                                */
816*37da2899SCharles.Forsyth   /*    Only the glyph loader and debugger should call this function.      */
817*37da2899SCharles.Forsyth   /*                                                                       */
818*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
TT_Done_Context(TT_ExecContext exec)819*37da2899SCharles.Forsyth   TT_Done_Context( TT_ExecContext  exec )
820*37da2899SCharles.Forsyth   {
821*37da2899SCharles.Forsyth     /* Nothing at all for now */
822*37da2899SCharles.Forsyth     FT_UNUSED( exec );
823*37da2899SCharles.Forsyth 
824*37da2899SCharles.Forsyth     return TT_Err_Ok;
825*37da2899SCharles.Forsyth   }
826*37da2899SCharles.Forsyth 
827*37da2899SCharles.Forsyth 
828*37da2899SCharles.Forsyth 
829*37da2899SCharles.Forsyth   /*************************************************************************/
830*37da2899SCharles.Forsyth   /*                                                                       */
831*37da2899SCharles.Forsyth   /* Before an opcode is executed, the interpreter verifies that there are */
832*37da2899SCharles.Forsyth   /* enough arguments on the stack, with the help of the Pop_Push_Count    */
833*37da2899SCharles.Forsyth   /* table.                                                                */
834*37da2899SCharles.Forsyth   /*                                                                       */
835*37da2899SCharles.Forsyth   /* For each opcode, the first column gives the number of arguments that  */
836*37da2899SCharles.Forsyth   /* are popped from the stack; the second one gives the number of those   */
837*37da2899SCharles.Forsyth   /* that are pushed in result.                                            */
838*37da2899SCharles.Forsyth   /*                                                                       */
839*37da2899SCharles.Forsyth   /* Note that for opcodes with a varying number of parameters, either 0   */
840*37da2899SCharles.Forsyth   /* or 1 arg is verified before execution, depending on the nature of the */
841*37da2899SCharles.Forsyth   /* instruction:                                                          */
842*37da2899SCharles.Forsyth   /*                                                                       */
843*37da2899SCharles.Forsyth   /* - if the number of arguments is given by the bytecode stream or the   */
844*37da2899SCharles.Forsyth   /*   loop variable, 0 is chosen.                                         */
845*37da2899SCharles.Forsyth   /*                                                                       */
846*37da2899SCharles.Forsyth   /* - if the first argument is a count n that is followed by arguments    */
847*37da2899SCharles.Forsyth   /*   a1 .. an, then 1 is chosen.                                         */
848*37da2899SCharles.Forsyth   /*                                                                       */
849*37da2899SCharles.Forsyth   /*************************************************************************/
850*37da2899SCharles.Forsyth 
851*37da2899SCharles.Forsyth 
852*37da2899SCharles.Forsyth #undef  PACK
853*37da2899SCharles.Forsyth #define PACK( x, y )  ( ( x << 4 ) | y )
854*37da2899SCharles.Forsyth 
855*37da2899SCharles.Forsyth 
856*37da2899SCharles.Forsyth   static
857*37da2899SCharles.Forsyth   const FT_Byte  Pop_Push_Count[256] =
858*37da2899SCharles.Forsyth   {
859*37da2899SCharles.Forsyth     /* opcodes are gathered in groups of 16 */
860*37da2899SCharles.Forsyth     /* please keep the spaces as they are   */
861*37da2899SCharles.Forsyth 
862*37da2899SCharles.Forsyth     /*  SVTCA  y  */  PACK( 0, 0 ),
863*37da2899SCharles.Forsyth     /*  SVTCA  x  */  PACK( 0, 0 ),
864*37da2899SCharles.Forsyth     /*  SPvTCA y  */  PACK( 0, 0 ),
865*37da2899SCharles.Forsyth     /*  SPvTCA x  */  PACK( 0, 0 ),
866*37da2899SCharles.Forsyth     /*  SFvTCA y  */  PACK( 0, 0 ),
867*37da2899SCharles.Forsyth     /*  SFvTCA x  */  PACK( 0, 0 ),
868*37da2899SCharles.Forsyth     /*  SPvTL //  */  PACK( 2, 0 ),
869*37da2899SCharles.Forsyth     /*  SPvTL +   */  PACK( 2, 0 ),
870*37da2899SCharles.Forsyth     /*  SFvTL //  */  PACK( 2, 0 ),
871*37da2899SCharles.Forsyth     /*  SFvTL +   */  PACK( 2, 0 ),
872*37da2899SCharles.Forsyth     /*  SPvFS     */  PACK( 2, 0 ),
873*37da2899SCharles.Forsyth     /*  SFvFS     */  PACK( 2, 0 ),
874*37da2899SCharles.Forsyth     /*  GPV       */  PACK( 0, 2 ),
875*37da2899SCharles.Forsyth     /*  GFV       */  PACK( 0, 2 ),
876*37da2899SCharles.Forsyth     /*  SFvTPv    */  PACK( 0, 0 ),
877*37da2899SCharles.Forsyth     /*  ISECT     */  PACK( 5, 0 ),
878*37da2899SCharles.Forsyth 
879*37da2899SCharles.Forsyth     /*  SRP0      */  PACK( 1, 0 ),
880*37da2899SCharles.Forsyth     /*  SRP1      */  PACK( 1, 0 ),
881*37da2899SCharles.Forsyth     /*  SRP2      */  PACK( 1, 0 ),
882*37da2899SCharles.Forsyth     /*  SZP0      */  PACK( 1, 0 ),
883*37da2899SCharles.Forsyth     /*  SZP1      */  PACK( 1, 0 ),
884*37da2899SCharles.Forsyth     /*  SZP2      */  PACK( 1, 0 ),
885*37da2899SCharles.Forsyth     /*  SZPS      */  PACK( 1, 0 ),
886*37da2899SCharles.Forsyth     /*  SLOOP     */  PACK( 1, 0 ),
887*37da2899SCharles.Forsyth     /*  RTG       */  PACK( 0, 0 ),
888*37da2899SCharles.Forsyth     /*  RTHG      */  PACK( 0, 0 ),
889*37da2899SCharles.Forsyth     /*  SMD       */  PACK( 1, 0 ),
890*37da2899SCharles.Forsyth     /*  ELSE      */  PACK( 0, 0 ),
891*37da2899SCharles.Forsyth     /*  JMPR      */  PACK( 1, 0 ),
892*37da2899SCharles.Forsyth     /*  SCvTCi    */  PACK( 1, 0 ),
893*37da2899SCharles.Forsyth     /*  SSwCi     */  PACK( 1, 0 ),
894*37da2899SCharles.Forsyth     /*  SSW       */  PACK( 1, 0 ),
895*37da2899SCharles.Forsyth 
896*37da2899SCharles.Forsyth     /*  DUP       */  PACK( 1, 2 ),
897*37da2899SCharles.Forsyth     /*  POP       */  PACK( 1, 0 ),
898*37da2899SCharles.Forsyth     /*  CLEAR     */  PACK( 0, 0 ),
899*37da2899SCharles.Forsyth     /*  SWAP      */  PACK( 2, 2 ),
900*37da2899SCharles.Forsyth     /*  DEPTH     */  PACK( 0, 1 ),
901*37da2899SCharles.Forsyth     /*  CINDEX    */  PACK( 1, 1 ),
902*37da2899SCharles.Forsyth     /*  MINDEX    */  PACK( 1, 0 ),
903*37da2899SCharles.Forsyth     /*  AlignPTS  */  PACK( 2, 0 ),
904*37da2899SCharles.Forsyth     /*  INS_$28   */  PACK( 0, 0 ),
905*37da2899SCharles.Forsyth     /*  UTP       */  PACK( 1, 0 ),
906*37da2899SCharles.Forsyth     /*  LOOPCALL  */  PACK( 2, 0 ),
907*37da2899SCharles.Forsyth     /*  CALL      */  PACK( 1, 0 ),
908*37da2899SCharles.Forsyth     /*  FDEF      */  PACK( 1, 0 ),
909*37da2899SCharles.Forsyth     /*  ENDF      */  PACK( 0, 0 ),
910*37da2899SCharles.Forsyth     /*  MDAP[0]   */  PACK( 1, 0 ),
911*37da2899SCharles.Forsyth     /*  MDAP[1]   */  PACK( 1, 0 ),
912*37da2899SCharles.Forsyth 
913*37da2899SCharles.Forsyth     /*  IUP[0]    */  PACK( 0, 0 ),
914*37da2899SCharles.Forsyth     /*  IUP[1]    */  PACK( 0, 0 ),
915*37da2899SCharles.Forsyth     /*  SHP[0]    */  PACK( 0, 0 ),
916*37da2899SCharles.Forsyth     /*  SHP[1]    */  PACK( 0, 0 ),
917*37da2899SCharles.Forsyth     /*  SHC[0]    */  PACK( 1, 0 ),
918*37da2899SCharles.Forsyth     /*  SHC[1]    */  PACK( 1, 0 ),
919*37da2899SCharles.Forsyth     /*  SHZ[0]    */  PACK( 1, 0 ),
920*37da2899SCharles.Forsyth     /*  SHZ[1]    */  PACK( 1, 0 ),
921*37da2899SCharles.Forsyth     /*  SHPIX     */  PACK( 1, 0 ),
922*37da2899SCharles.Forsyth     /*  IP        */  PACK( 0, 0 ),
923*37da2899SCharles.Forsyth     /*  MSIRP[0]  */  PACK( 2, 0 ),
924*37da2899SCharles.Forsyth     /*  MSIRP[1]  */  PACK( 2, 0 ),
925*37da2899SCharles.Forsyth     /*  AlignRP   */  PACK( 0, 0 ),
926*37da2899SCharles.Forsyth     /*  RTDG      */  PACK( 0, 0 ),
927*37da2899SCharles.Forsyth     /*  MIAP[0]   */  PACK( 2, 0 ),
928*37da2899SCharles.Forsyth     /*  MIAP[1]   */  PACK( 2, 0 ),
929*37da2899SCharles.Forsyth 
930*37da2899SCharles.Forsyth     /*  NPushB    */  PACK( 0, 0 ),
931*37da2899SCharles.Forsyth     /*  NPushW    */  PACK( 0, 0 ),
932*37da2899SCharles.Forsyth     /*  WS        */  PACK( 2, 0 ),
933*37da2899SCharles.Forsyth     /*  RS        */  PACK( 1, 1 ),
934*37da2899SCharles.Forsyth     /*  WCvtP     */  PACK( 2, 0 ),
935*37da2899SCharles.Forsyth     /*  RCvt      */  PACK( 1, 1 ),
936*37da2899SCharles.Forsyth     /*  GC[0]     */  PACK( 1, 1 ),
937*37da2899SCharles.Forsyth     /*  GC[1]     */  PACK( 1, 1 ),
938*37da2899SCharles.Forsyth     /*  SCFS      */  PACK( 2, 0 ),
939*37da2899SCharles.Forsyth     /*  MD[0]     */  PACK( 2, 1 ),
940*37da2899SCharles.Forsyth     /*  MD[1]     */  PACK( 2, 1 ),
941*37da2899SCharles.Forsyth     /*  MPPEM     */  PACK( 0, 1 ),
942*37da2899SCharles.Forsyth     /*  MPS       */  PACK( 0, 1 ),
943*37da2899SCharles.Forsyth     /*  FlipON    */  PACK( 0, 0 ),
944*37da2899SCharles.Forsyth     /*  FlipOFF   */  PACK( 0, 0 ),
945*37da2899SCharles.Forsyth     /*  DEBUG     */  PACK( 1, 0 ),
946*37da2899SCharles.Forsyth 
947*37da2899SCharles.Forsyth     /*  LT        */  PACK( 2, 1 ),
948*37da2899SCharles.Forsyth     /*  LTEQ      */  PACK( 2, 1 ),
949*37da2899SCharles.Forsyth     /*  GT        */  PACK( 2, 1 ),
950*37da2899SCharles.Forsyth     /*  GTEQ      */  PACK( 2, 1 ),
951*37da2899SCharles.Forsyth     /*  EQ        */  PACK( 2, 1 ),
952*37da2899SCharles.Forsyth     /*  NEQ       */  PACK( 2, 1 ),
953*37da2899SCharles.Forsyth     /*  ODD       */  PACK( 1, 1 ),
954*37da2899SCharles.Forsyth     /*  EVEN      */  PACK( 1, 1 ),
955*37da2899SCharles.Forsyth     /*  IF        */  PACK( 1, 0 ),
956*37da2899SCharles.Forsyth     /*  EIF       */  PACK( 0, 0 ),
957*37da2899SCharles.Forsyth     /*  AND       */  PACK( 2, 1 ),
958*37da2899SCharles.Forsyth     /*  OR        */  PACK( 2, 1 ),
959*37da2899SCharles.Forsyth     /*  NOT       */  PACK( 1, 1 ),
960*37da2899SCharles.Forsyth     /*  DeltaP1   */  PACK( 1, 0 ),
961*37da2899SCharles.Forsyth     /*  SDB       */  PACK( 1, 0 ),
962*37da2899SCharles.Forsyth     /*  SDS       */  PACK( 1, 0 ),
963*37da2899SCharles.Forsyth 
964*37da2899SCharles.Forsyth     /*  ADD       */  PACK( 2, 1 ),
965*37da2899SCharles.Forsyth     /*  SUB       */  PACK( 2, 1 ),
966*37da2899SCharles.Forsyth     /*  DIV       */  PACK( 2, 1 ),
967*37da2899SCharles.Forsyth     /*  MUL       */  PACK( 2, 1 ),
968*37da2899SCharles.Forsyth     /*  ABS       */  PACK( 1, 1 ),
969*37da2899SCharles.Forsyth     /*  NEG       */  PACK( 1, 1 ),
970*37da2899SCharles.Forsyth     /*  FLOOR     */  PACK( 1, 1 ),
971*37da2899SCharles.Forsyth     /*  CEILING   */  PACK( 1, 1 ),
972*37da2899SCharles.Forsyth     /*  ROUND[0]  */  PACK( 1, 1 ),
973*37da2899SCharles.Forsyth     /*  ROUND[1]  */  PACK( 1, 1 ),
974*37da2899SCharles.Forsyth     /*  ROUND[2]  */  PACK( 1, 1 ),
975*37da2899SCharles.Forsyth     /*  ROUND[3]  */  PACK( 1, 1 ),
976*37da2899SCharles.Forsyth     /*  NROUND[0] */  PACK( 1, 1 ),
977*37da2899SCharles.Forsyth     /*  NROUND[1] */  PACK( 1, 1 ),
978*37da2899SCharles.Forsyth     /*  NROUND[2] */  PACK( 1, 1 ),
979*37da2899SCharles.Forsyth     /*  NROUND[3] */  PACK( 1, 1 ),
980*37da2899SCharles.Forsyth 
981*37da2899SCharles.Forsyth     /*  WCvtF     */  PACK( 2, 0 ),
982*37da2899SCharles.Forsyth     /*  DeltaP2   */  PACK( 1, 0 ),
983*37da2899SCharles.Forsyth     /*  DeltaP3   */  PACK( 1, 0 ),
984*37da2899SCharles.Forsyth     /*  DeltaCn[0] */ PACK( 1, 0 ),
985*37da2899SCharles.Forsyth     /*  DeltaCn[1] */ PACK( 1, 0 ),
986*37da2899SCharles.Forsyth     /*  DeltaCn[2] */ PACK( 1, 0 ),
987*37da2899SCharles.Forsyth     /*  SROUND    */  PACK( 1, 0 ),
988*37da2899SCharles.Forsyth     /*  S45Round  */  PACK( 1, 0 ),
989*37da2899SCharles.Forsyth     /*  JROT      */  PACK( 2, 0 ),
990*37da2899SCharles.Forsyth     /*  JROF      */  PACK( 2, 0 ),
991*37da2899SCharles.Forsyth     /*  ROFF      */  PACK( 0, 0 ),
992*37da2899SCharles.Forsyth     /*  INS_$7B   */  PACK( 0, 0 ),
993*37da2899SCharles.Forsyth     /*  RUTG      */  PACK( 0, 0 ),
994*37da2899SCharles.Forsyth     /*  RDTG      */  PACK( 0, 0 ),
995*37da2899SCharles.Forsyth     /*  SANGW     */  PACK( 1, 0 ),
996*37da2899SCharles.Forsyth     /*  AA        */  PACK( 1, 0 ),
997*37da2899SCharles.Forsyth 
998*37da2899SCharles.Forsyth     /*  FlipPT    */  PACK( 0, 0 ),
999*37da2899SCharles.Forsyth     /*  FlipRgON  */  PACK( 2, 0 ),
1000*37da2899SCharles.Forsyth     /*  FlipRgOFF */  PACK( 2, 0 ),
1001*37da2899SCharles.Forsyth     /*  INS_$83   */  PACK( 0, 0 ),
1002*37da2899SCharles.Forsyth     /*  INS_$84   */  PACK( 0, 0 ),
1003*37da2899SCharles.Forsyth     /*  ScanCTRL  */  PACK( 1, 0 ),
1004*37da2899SCharles.Forsyth     /*  SDVPTL[0] */  PACK( 2, 0 ),
1005*37da2899SCharles.Forsyth     /*  SDVPTL[1] */  PACK( 2, 0 ),
1006*37da2899SCharles.Forsyth     /*  GetINFO   */  PACK( 1, 1 ),
1007*37da2899SCharles.Forsyth     /*  IDEF      */  PACK( 1, 0 ),
1008*37da2899SCharles.Forsyth     /*  ROLL      */  PACK( 3, 3 ),
1009*37da2899SCharles.Forsyth     /*  MAX       */  PACK( 2, 1 ),
1010*37da2899SCharles.Forsyth     /*  MIN       */  PACK( 2, 1 ),
1011*37da2899SCharles.Forsyth     /*  ScanTYPE  */  PACK( 1, 0 ),
1012*37da2899SCharles.Forsyth     /*  InstCTRL  */  PACK( 2, 0 ),
1013*37da2899SCharles.Forsyth     /*  INS_$8F   */  PACK( 0, 0 ),
1014*37da2899SCharles.Forsyth 
1015*37da2899SCharles.Forsyth     /*  INS_$90  */   PACK( 0, 0 ),
1016*37da2899SCharles.Forsyth     /*  INS_$91  */   PACK( 0, 0 ),
1017*37da2899SCharles.Forsyth     /*  INS_$92  */   PACK( 0, 0 ),
1018*37da2899SCharles.Forsyth     /*  INS_$93  */   PACK( 0, 0 ),
1019*37da2899SCharles.Forsyth     /*  INS_$94  */   PACK( 0, 0 ),
1020*37da2899SCharles.Forsyth     /*  INS_$95  */   PACK( 0, 0 ),
1021*37da2899SCharles.Forsyth     /*  INS_$96  */   PACK( 0, 0 ),
1022*37da2899SCharles.Forsyth     /*  INS_$97  */   PACK( 0, 0 ),
1023*37da2899SCharles.Forsyth     /*  INS_$98  */   PACK( 0, 0 ),
1024*37da2899SCharles.Forsyth     /*  INS_$99  */   PACK( 0, 0 ),
1025*37da2899SCharles.Forsyth     /*  INS_$9A  */   PACK( 0, 0 ),
1026*37da2899SCharles.Forsyth     /*  INS_$9B  */   PACK( 0, 0 ),
1027*37da2899SCharles.Forsyth     /*  INS_$9C  */   PACK( 0, 0 ),
1028*37da2899SCharles.Forsyth     /*  INS_$9D  */   PACK( 0, 0 ),
1029*37da2899SCharles.Forsyth     /*  INS_$9E  */   PACK( 0, 0 ),
1030*37da2899SCharles.Forsyth     /*  INS_$9F  */   PACK( 0, 0 ),
1031*37da2899SCharles.Forsyth 
1032*37da2899SCharles.Forsyth     /*  INS_$A0  */   PACK( 0, 0 ),
1033*37da2899SCharles.Forsyth     /*  INS_$A1  */   PACK( 0, 0 ),
1034*37da2899SCharles.Forsyth     /*  INS_$A2  */   PACK( 0, 0 ),
1035*37da2899SCharles.Forsyth     /*  INS_$A3  */   PACK( 0, 0 ),
1036*37da2899SCharles.Forsyth     /*  INS_$A4  */   PACK( 0, 0 ),
1037*37da2899SCharles.Forsyth     /*  INS_$A5  */   PACK( 0, 0 ),
1038*37da2899SCharles.Forsyth     /*  INS_$A6  */   PACK( 0, 0 ),
1039*37da2899SCharles.Forsyth     /*  INS_$A7  */   PACK( 0, 0 ),
1040*37da2899SCharles.Forsyth     /*  INS_$A8  */   PACK( 0, 0 ),
1041*37da2899SCharles.Forsyth     /*  INS_$A9  */   PACK( 0, 0 ),
1042*37da2899SCharles.Forsyth     /*  INS_$AA  */   PACK( 0, 0 ),
1043*37da2899SCharles.Forsyth     /*  INS_$AB  */   PACK( 0, 0 ),
1044*37da2899SCharles.Forsyth     /*  INS_$AC  */   PACK( 0, 0 ),
1045*37da2899SCharles.Forsyth     /*  INS_$AD  */   PACK( 0, 0 ),
1046*37da2899SCharles.Forsyth     /*  INS_$AE  */   PACK( 0, 0 ),
1047*37da2899SCharles.Forsyth     /*  INS_$AF  */   PACK( 0, 0 ),
1048*37da2899SCharles.Forsyth 
1049*37da2899SCharles.Forsyth     /*  PushB[0]  */  PACK( 0, 1 ),
1050*37da2899SCharles.Forsyth     /*  PushB[1]  */  PACK( 0, 2 ),
1051*37da2899SCharles.Forsyth     /*  PushB[2]  */  PACK( 0, 3 ),
1052*37da2899SCharles.Forsyth     /*  PushB[3]  */  PACK( 0, 4 ),
1053*37da2899SCharles.Forsyth     /*  PushB[4]  */  PACK( 0, 5 ),
1054*37da2899SCharles.Forsyth     /*  PushB[5]  */  PACK( 0, 6 ),
1055*37da2899SCharles.Forsyth     /*  PushB[6]  */  PACK( 0, 7 ),
1056*37da2899SCharles.Forsyth     /*  PushB[7]  */  PACK( 0, 8 ),
1057*37da2899SCharles.Forsyth     /*  PushW[0]  */  PACK( 0, 1 ),
1058*37da2899SCharles.Forsyth     /*  PushW[1]  */  PACK( 0, 2 ),
1059*37da2899SCharles.Forsyth     /*  PushW[2]  */  PACK( 0, 3 ),
1060*37da2899SCharles.Forsyth     /*  PushW[3]  */  PACK( 0, 4 ),
1061*37da2899SCharles.Forsyth     /*  PushW[4]  */  PACK( 0, 5 ),
1062*37da2899SCharles.Forsyth     /*  PushW[5]  */  PACK( 0, 6 ),
1063*37da2899SCharles.Forsyth     /*  PushW[6]  */  PACK( 0, 7 ),
1064*37da2899SCharles.Forsyth     /*  PushW[7]  */  PACK( 0, 8 ),
1065*37da2899SCharles.Forsyth 
1066*37da2899SCharles.Forsyth     /*  MDRP[00]  */  PACK( 1, 0 ),
1067*37da2899SCharles.Forsyth     /*  MDRP[01]  */  PACK( 1, 0 ),
1068*37da2899SCharles.Forsyth     /*  MDRP[02]  */  PACK( 1, 0 ),
1069*37da2899SCharles.Forsyth     /*  MDRP[03]  */  PACK( 1, 0 ),
1070*37da2899SCharles.Forsyth     /*  MDRP[04]  */  PACK( 1, 0 ),
1071*37da2899SCharles.Forsyth     /*  MDRP[05]  */  PACK( 1, 0 ),
1072*37da2899SCharles.Forsyth     /*  MDRP[06]  */  PACK( 1, 0 ),
1073*37da2899SCharles.Forsyth     /*  MDRP[07]  */  PACK( 1, 0 ),
1074*37da2899SCharles.Forsyth     /*  MDRP[08]  */  PACK( 1, 0 ),
1075*37da2899SCharles.Forsyth     /*  MDRP[09]  */  PACK( 1, 0 ),
1076*37da2899SCharles.Forsyth     /*  MDRP[10]  */  PACK( 1, 0 ),
1077*37da2899SCharles.Forsyth     /*  MDRP[11]  */  PACK( 1, 0 ),
1078*37da2899SCharles.Forsyth     /*  MDRP[12]  */  PACK( 1, 0 ),
1079*37da2899SCharles.Forsyth     /*  MDRP[13]  */  PACK( 1, 0 ),
1080*37da2899SCharles.Forsyth     /*  MDRP[14]  */  PACK( 1, 0 ),
1081*37da2899SCharles.Forsyth     /*  MDRP[15]  */  PACK( 1, 0 ),
1082*37da2899SCharles.Forsyth 
1083*37da2899SCharles.Forsyth     /*  MDRP[16]  */  PACK( 1, 0 ),
1084*37da2899SCharles.Forsyth     /*  MDRP[17]  */  PACK( 1, 0 ),
1085*37da2899SCharles.Forsyth     /*  MDRP[18]  */  PACK( 1, 0 ),
1086*37da2899SCharles.Forsyth     /*  MDRP[19]  */  PACK( 1, 0 ),
1087*37da2899SCharles.Forsyth     /*  MDRP[20]  */  PACK( 1, 0 ),
1088*37da2899SCharles.Forsyth     /*  MDRP[21]  */  PACK( 1, 0 ),
1089*37da2899SCharles.Forsyth     /*  MDRP[22]  */  PACK( 1, 0 ),
1090*37da2899SCharles.Forsyth     /*  MDRP[23]  */  PACK( 1, 0 ),
1091*37da2899SCharles.Forsyth     /*  MDRP[24]  */  PACK( 1, 0 ),
1092*37da2899SCharles.Forsyth     /*  MDRP[25]  */  PACK( 1, 0 ),
1093*37da2899SCharles.Forsyth     /*  MDRP[26]  */  PACK( 1, 0 ),
1094*37da2899SCharles.Forsyth     /*  MDRP[27]  */  PACK( 1, 0 ),
1095*37da2899SCharles.Forsyth     /*  MDRP[28]  */  PACK( 1, 0 ),
1096*37da2899SCharles.Forsyth     /*  MDRP[29]  */  PACK( 1, 0 ),
1097*37da2899SCharles.Forsyth     /*  MDRP[30]  */  PACK( 1, 0 ),
1098*37da2899SCharles.Forsyth     /*  MDRP[31]  */  PACK( 1, 0 ),
1099*37da2899SCharles.Forsyth 
1100*37da2899SCharles.Forsyth     /*  MIRP[00]  */  PACK( 2, 0 ),
1101*37da2899SCharles.Forsyth     /*  MIRP[01]  */  PACK( 2, 0 ),
1102*37da2899SCharles.Forsyth     /*  MIRP[02]  */  PACK( 2, 0 ),
1103*37da2899SCharles.Forsyth     /*  MIRP[03]  */  PACK( 2, 0 ),
1104*37da2899SCharles.Forsyth     /*  MIRP[04]  */  PACK( 2, 0 ),
1105*37da2899SCharles.Forsyth     /*  MIRP[05]  */  PACK( 2, 0 ),
1106*37da2899SCharles.Forsyth     /*  MIRP[06]  */  PACK( 2, 0 ),
1107*37da2899SCharles.Forsyth     /*  MIRP[07]  */  PACK( 2, 0 ),
1108*37da2899SCharles.Forsyth     /*  MIRP[08]  */  PACK( 2, 0 ),
1109*37da2899SCharles.Forsyth     /*  MIRP[09]  */  PACK( 2, 0 ),
1110*37da2899SCharles.Forsyth     /*  MIRP[10]  */  PACK( 2, 0 ),
1111*37da2899SCharles.Forsyth     /*  MIRP[11]  */  PACK( 2, 0 ),
1112*37da2899SCharles.Forsyth     /*  MIRP[12]  */  PACK( 2, 0 ),
1113*37da2899SCharles.Forsyth     /*  MIRP[13]  */  PACK( 2, 0 ),
1114*37da2899SCharles.Forsyth     /*  MIRP[14]  */  PACK( 2, 0 ),
1115*37da2899SCharles.Forsyth     /*  MIRP[15]  */  PACK( 2, 0 ),
1116*37da2899SCharles.Forsyth 
1117*37da2899SCharles.Forsyth     /*  MIRP[16]  */  PACK( 2, 0 ),
1118*37da2899SCharles.Forsyth     /*  MIRP[17]  */  PACK( 2, 0 ),
1119*37da2899SCharles.Forsyth     /*  MIRP[18]  */  PACK( 2, 0 ),
1120*37da2899SCharles.Forsyth     /*  MIRP[19]  */  PACK( 2, 0 ),
1121*37da2899SCharles.Forsyth     /*  MIRP[20]  */  PACK( 2, 0 ),
1122*37da2899SCharles.Forsyth     /*  MIRP[21]  */  PACK( 2, 0 ),
1123*37da2899SCharles.Forsyth     /*  MIRP[22]  */  PACK( 2, 0 ),
1124*37da2899SCharles.Forsyth     /*  MIRP[23]  */  PACK( 2, 0 ),
1125*37da2899SCharles.Forsyth     /*  MIRP[24]  */  PACK( 2, 0 ),
1126*37da2899SCharles.Forsyth     /*  MIRP[25]  */  PACK( 2, 0 ),
1127*37da2899SCharles.Forsyth     /*  MIRP[26]  */  PACK( 2, 0 ),
1128*37da2899SCharles.Forsyth     /*  MIRP[27]  */  PACK( 2, 0 ),
1129*37da2899SCharles.Forsyth     /*  MIRP[28]  */  PACK( 2, 0 ),
1130*37da2899SCharles.Forsyth     /*  MIRP[29]  */  PACK( 2, 0 ),
1131*37da2899SCharles.Forsyth     /*  MIRP[30]  */  PACK( 2, 0 ),
1132*37da2899SCharles.Forsyth     /*  MIRP[31]  */  PACK( 2, 0 )
1133*37da2899SCharles.Forsyth   };
1134*37da2899SCharles.Forsyth 
1135*37da2899SCharles.Forsyth 
1136*37da2899SCharles.Forsyth   static
1137*37da2899SCharles.Forsyth   const FT_Char  opcode_length[256] =
1138*37da2899SCharles.Forsyth   {
1139*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1140*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1141*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1142*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1143*37da2899SCharles.Forsyth 
1144*37da2899SCharles.Forsyth    -1,-1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1145*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1146*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1147*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1148*37da2899SCharles.Forsyth 
1149*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1150*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1151*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1152*37da2899SCharles.Forsyth     2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,
1153*37da2899SCharles.Forsyth 
1154*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1155*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1156*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1157*37da2899SCharles.Forsyth     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
1158*37da2899SCharles.Forsyth   };
1159*37da2899SCharles.Forsyth 
1160*37da2899SCharles.Forsyth   static
1161*37da2899SCharles.Forsyth   const FT_Vector  Null_Vector = {0,0};
1162*37da2899SCharles.Forsyth 
1163*37da2899SCharles.Forsyth 
1164*37da2899SCharles.Forsyth #undef PACK
1165*37da2899SCharles.Forsyth 
1166*37da2899SCharles.Forsyth 
1167*37da2899SCharles.Forsyth #undef  NULL_Vector
1168*37da2899SCharles.Forsyth #define NULL_Vector  (FT_Vector*)&Null_Vector
1169*37da2899SCharles.Forsyth 
1170*37da2899SCharles.Forsyth 
1171*37da2899SCharles.Forsyth   /* compute (a*b)/2^14 with maximal accuracy and rounding */
1172*37da2899SCharles.Forsyth   static FT_Int32
TT_MulFix14(FT_Int32 a,FT_Int b)1173*37da2899SCharles.Forsyth   TT_MulFix14( FT_Int32  a,
1174*37da2899SCharles.Forsyth                FT_Int    b )
1175*37da2899SCharles.Forsyth   {
1176*37da2899SCharles.Forsyth     FT_Int32   m, s, hi;
1177*37da2899SCharles.Forsyth     FT_UInt32  l, lo;
1178*37da2899SCharles.Forsyth 
1179*37da2899SCharles.Forsyth 
1180*37da2899SCharles.Forsyth     /* compute ax*bx as 64-bit value */
1181*37da2899SCharles.Forsyth     l  = (FT_UInt32)( ( a & 0xFFFFU ) * b );
1182*37da2899SCharles.Forsyth     m  = ( a >> 16 ) * b;
1183*37da2899SCharles.Forsyth 
1184*37da2899SCharles.Forsyth     lo = l + (FT_UInt32)( m << 16 );
1185*37da2899SCharles.Forsyth     hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
1186*37da2899SCharles.Forsyth 
1187*37da2899SCharles.Forsyth     /* divide the result by 2^14 with rounding */
1188*37da2899SCharles.Forsyth     s   = hi >> 31;
1189*37da2899SCharles.Forsyth     l   = lo + (FT_UInt32)s;
1190*37da2899SCharles.Forsyth     hi += s + ( l < lo );
1191*37da2899SCharles.Forsyth     lo  = l;
1192*37da2899SCharles.Forsyth 
1193*37da2899SCharles.Forsyth     l   = lo + 0x2000U;
1194*37da2899SCharles.Forsyth     hi += (l < lo);
1195*37da2899SCharles.Forsyth 
1196*37da2899SCharles.Forsyth     return ( hi << 18 ) | ( l >> 14 );
1197*37da2899SCharles.Forsyth   }
1198*37da2899SCharles.Forsyth 
1199*37da2899SCharles.Forsyth 
1200*37da2899SCharles.Forsyth   /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
1201*37da2899SCharles.Forsyth   static FT_Int32
TT_DotFix14(FT_Int32 ax,FT_Int32 ay,FT_Int bx,FT_Int by)1202*37da2899SCharles.Forsyth   TT_DotFix14( FT_Int32  ax,
1203*37da2899SCharles.Forsyth                FT_Int32  ay,
1204*37da2899SCharles.Forsyth                FT_Int    bx,
1205*37da2899SCharles.Forsyth                FT_Int    by )
1206*37da2899SCharles.Forsyth   {
1207*37da2899SCharles.Forsyth     FT_Int32   m, s, hi1, hi2, hi;
1208*37da2899SCharles.Forsyth     FT_UInt32  l, lo1, lo2, lo;
1209*37da2899SCharles.Forsyth 
1210*37da2899SCharles.Forsyth 
1211*37da2899SCharles.Forsyth     /* compute ax*bx as 64-bit value */
1212*37da2899SCharles.Forsyth     l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
1213*37da2899SCharles.Forsyth     m = ( ax >> 16 ) * bx;
1214*37da2899SCharles.Forsyth 
1215*37da2899SCharles.Forsyth     lo1 = l + (FT_UInt32)( m << 16 );
1216*37da2899SCharles.Forsyth     hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
1217*37da2899SCharles.Forsyth 
1218*37da2899SCharles.Forsyth     /* compute ay*by as 64-bit value */
1219*37da2899SCharles.Forsyth     l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
1220*37da2899SCharles.Forsyth     m = ( ay >> 16 ) * by;
1221*37da2899SCharles.Forsyth 
1222*37da2899SCharles.Forsyth     lo2 = l + (FT_UInt32)( m << 16 );
1223*37da2899SCharles.Forsyth     hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
1224*37da2899SCharles.Forsyth 
1225*37da2899SCharles.Forsyth     /* add them */
1226*37da2899SCharles.Forsyth     lo = lo1 + lo2;
1227*37da2899SCharles.Forsyth     hi = hi1 + hi2 + ( lo < lo1 );
1228*37da2899SCharles.Forsyth 
1229*37da2899SCharles.Forsyth     /* divide the result by 2^14 with rounding */
1230*37da2899SCharles.Forsyth     s   = hi >> 31;
1231*37da2899SCharles.Forsyth     l   = lo + (FT_UInt32)s;
1232*37da2899SCharles.Forsyth     hi += s + ( l < lo );
1233*37da2899SCharles.Forsyth     lo  = l;
1234*37da2899SCharles.Forsyth 
1235*37da2899SCharles.Forsyth     l   = lo + 0x2000U;
1236*37da2899SCharles.Forsyth     hi += ( l < lo );
1237*37da2899SCharles.Forsyth 
1238*37da2899SCharles.Forsyth     return ( hi << 18 ) | ( l >> 14 );
1239*37da2899SCharles.Forsyth   }
1240*37da2899SCharles.Forsyth 
1241*37da2899SCharles.Forsyth 
1242*37da2899SCharles.Forsyth   /* return length of given vector */
1243*37da2899SCharles.Forsyth 
1244*37da2899SCharles.Forsyth #if 0
1245*37da2899SCharles.Forsyth 
1246*37da2899SCharles.Forsyth   static FT_Int32
1247*37da2899SCharles.Forsyth   TT_VecLen( FT_Int32  x,
1248*37da2899SCharles.Forsyth              FT_Int32  y )
1249*37da2899SCharles.Forsyth   {
1250*37da2899SCharles.Forsyth     FT_Int32   m, hi1, hi2, hi;
1251*37da2899SCharles.Forsyth     FT_UInt32  l, lo1, lo2, lo;
1252*37da2899SCharles.Forsyth 
1253*37da2899SCharles.Forsyth 
1254*37da2899SCharles.Forsyth     /* compute x*x as 64-bit value */
1255*37da2899SCharles.Forsyth     lo = (FT_UInt32)( x & 0xFFFFU );
1256*37da2899SCharles.Forsyth     hi = x >> 16;
1257*37da2899SCharles.Forsyth 
1258*37da2899SCharles.Forsyth     l  = lo * lo;
1259*37da2899SCharles.Forsyth     m  = hi * lo;
1260*37da2899SCharles.Forsyth     hi = hi * hi;
1261*37da2899SCharles.Forsyth 
1262*37da2899SCharles.Forsyth     lo1 = l + (FT_UInt32)( m << 17 );
1263*37da2899SCharles.Forsyth     hi1 = hi + ( m >> 15 ) + ( lo1 < l );
1264*37da2899SCharles.Forsyth 
1265*37da2899SCharles.Forsyth     /* compute y*y as 64-bit value */
1266*37da2899SCharles.Forsyth     lo = (FT_UInt32)( y & 0xFFFFU );
1267*37da2899SCharles.Forsyth     hi = y >> 16;
1268*37da2899SCharles.Forsyth 
1269*37da2899SCharles.Forsyth     l  = lo * lo;
1270*37da2899SCharles.Forsyth     m  = hi * lo;
1271*37da2899SCharles.Forsyth     hi = hi * hi;
1272*37da2899SCharles.Forsyth 
1273*37da2899SCharles.Forsyth     lo2 = l + (FT_UInt32)( m << 17 );
1274*37da2899SCharles.Forsyth     hi2 = hi + ( m >> 15 ) + ( lo2 < l );
1275*37da2899SCharles.Forsyth 
1276*37da2899SCharles.Forsyth     /* add them to get 'x*x+y*y' as 64-bit value */
1277*37da2899SCharles.Forsyth     lo = lo1 + lo2;
1278*37da2899SCharles.Forsyth     hi = hi1 + hi2 + ( lo < lo1 );
1279*37da2899SCharles.Forsyth 
1280*37da2899SCharles.Forsyth     /* compute the square root of this value */
1281*37da2899SCharles.Forsyth     {
1282*37da2899SCharles.Forsyth       FT_UInt32  root, rem, test_div;
1283*37da2899SCharles.Forsyth       FT_Int     count;
1284*37da2899SCharles.Forsyth 
1285*37da2899SCharles.Forsyth 
1286*37da2899SCharles.Forsyth       root = 0;
1287*37da2899SCharles.Forsyth 
1288*37da2899SCharles.Forsyth       {
1289*37da2899SCharles.Forsyth         rem   = 0;
1290*37da2899SCharles.Forsyth         count = 32;
1291*37da2899SCharles.Forsyth         do
1292*37da2899SCharles.Forsyth         {
1293*37da2899SCharles.Forsyth           rem      = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
1294*37da2899SCharles.Forsyth           hi       = (  hi << 2 ) | (            lo >> 30 );
1295*37da2899SCharles.Forsyth           lo     <<= 2;
1296*37da2899SCharles.Forsyth           root   <<= 1;
1297*37da2899SCharles.Forsyth           test_div = ( root << 1 ) + 1;
1298*37da2899SCharles.Forsyth 
1299*37da2899SCharles.Forsyth           if ( rem >= test_div )
1300*37da2899SCharles.Forsyth           {
1301*37da2899SCharles.Forsyth             rem  -= test_div;
1302*37da2899SCharles.Forsyth             root += 1;
1303*37da2899SCharles.Forsyth           }
1304*37da2899SCharles.Forsyth         } while ( --count );
1305*37da2899SCharles.Forsyth       }
1306*37da2899SCharles.Forsyth 
1307*37da2899SCharles.Forsyth       return (FT_Int32)root;
1308*37da2899SCharles.Forsyth     }
1309*37da2899SCharles.Forsyth   }
1310*37da2899SCharles.Forsyth 
1311*37da2899SCharles.Forsyth #else
1312*37da2899SCharles.Forsyth 
1313*37da2899SCharles.Forsyth   /* this version uses FT_Vector_Length which computes the same value */
1314*37da2899SCharles.Forsyth   /* much, much faster..                                              */
1315*37da2899SCharles.Forsyth   /*                                                                  */
1316*37da2899SCharles.Forsyth   static FT_F26Dot6
TT_VecLen(FT_F26Dot6 X,FT_F26Dot6 Y)1317*37da2899SCharles.Forsyth   TT_VecLen( FT_F26Dot6  X,
1318*37da2899SCharles.Forsyth              FT_F26Dot6  Y )
1319*37da2899SCharles.Forsyth   {
1320*37da2899SCharles.Forsyth     FT_Vector  v;
1321*37da2899SCharles.Forsyth 
1322*37da2899SCharles.Forsyth 
1323*37da2899SCharles.Forsyth     v.x = X;
1324*37da2899SCharles.Forsyth     v.y = Y;
1325*37da2899SCharles.Forsyth 
1326*37da2899SCharles.Forsyth     return FT_Vector_Length( &v );
1327*37da2899SCharles.Forsyth   }
1328*37da2899SCharles.Forsyth 
1329*37da2899SCharles.Forsyth #endif
1330*37da2899SCharles.Forsyth 
1331*37da2899SCharles.Forsyth 
1332*37da2899SCharles.Forsyth   /*************************************************************************/
1333*37da2899SCharles.Forsyth   /*                                                                       */
1334*37da2899SCharles.Forsyth   /* <Function>                                                            */
1335*37da2899SCharles.Forsyth   /*    Current_Ratio                                                      */
1336*37da2899SCharles.Forsyth   /*                                                                       */
1337*37da2899SCharles.Forsyth   /* <Description>                                                         */
1338*37da2899SCharles.Forsyth   /*    Returns the current aspect ratio scaling factor depending on the   */
1339*37da2899SCharles.Forsyth   /*    projection vector's state and device resolutions.                  */
1340*37da2899SCharles.Forsyth   /*                                                                       */
1341*37da2899SCharles.Forsyth   /* <Return>                                                              */
1342*37da2899SCharles.Forsyth   /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */
1343*37da2899SCharles.Forsyth   /*                                                                       */
1344*37da2899SCharles.Forsyth   static FT_Long
Current_Ratio(EXEC_OP)1345*37da2899SCharles.Forsyth   Current_Ratio( EXEC_OP )
1346*37da2899SCharles.Forsyth   {
1347*37da2899SCharles.Forsyth     if ( CUR.tt_metrics.ratio )
1348*37da2899SCharles.Forsyth       return CUR.tt_metrics.ratio;
1349*37da2899SCharles.Forsyth 
1350*37da2899SCharles.Forsyth     if ( CUR.GS.projVector.y == 0 )
1351*37da2899SCharles.Forsyth       CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1352*37da2899SCharles.Forsyth 
1353*37da2899SCharles.Forsyth     else if ( CUR.GS.projVector.x == 0 )
1354*37da2899SCharles.Forsyth       CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1355*37da2899SCharles.Forsyth 
1356*37da2899SCharles.Forsyth     else
1357*37da2899SCharles.Forsyth     {
1358*37da2899SCharles.Forsyth       FT_Long  x, y;
1359*37da2899SCharles.Forsyth 
1360*37da2899SCharles.Forsyth       x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 );
1361*37da2899SCharles.Forsyth       y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 );
1362*37da2899SCharles.Forsyth       CUR.tt_metrics.ratio = TT_VecLen( x, y );
1363*37da2899SCharles.Forsyth     }
1364*37da2899SCharles.Forsyth 
1365*37da2899SCharles.Forsyth     return CUR.tt_metrics.ratio;
1366*37da2899SCharles.Forsyth   }
1367*37da2899SCharles.Forsyth 
1368*37da2899SCharles.Forsyth 
1369*37da2899SCharles.Forsyth   static FT_Long
Current_Ppem(EXEC_OP)1370*37da2899SCharles.Forsyth   Current_Ppem( EXEC_OP )
1371*37da2899SCharles.Forsyth   {
1372*37da2899SCharles.Forsyth     return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
1373*37da2899SCharles.Forsyth   }
1374*37da2899SCharles.Forsyth 
1375*37da2899SCharles.Forsyth 
1376*37da2899SCharles.Forsyth   /*************************************************************************/
1377*37da2899SCharles.Forsyth   /*                                                                       */
1378*37da2899SCharles.Forsyth   /* Functions related to the control value table (CVT).                   */
1379*37da2899SCharles.Forsyth   /*                                                                       */
1380*37da2899SCharles.Forsyth   /*************************************************************************/
1381*37da2899SCharles.Forsyth 
1382*37da2899SCharles.Forsyth 
1383*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_F26Dot6 )
Read_CVT(EXEC_OP_ FT_ULong idx)1384*37da2899SCharles.Forsyth   Read_CVT( EXEC_OP_ FT_ULong  idx )
1385*37da2899SCharles.Forsyth   {
1386*37da2899SCharles.Forsyth     return CUR.cvt[idx];
1387*37da2899SCharles.Forsyth   }
1388*37da2899SCharles.Forsyth 
1389*37da2899SCharles.Forsyth 
1390*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_F26Dot6 )
Read_CVT_Stretched(EXEC_OP_ FT_ULong idx)1391*37da2899SCharles.Forsyth   Read_CVT_Stretched( EXEC_OP_ FT_ULong  idx )
1392*37da2899SCharles.Forsyth   {
1393*37da2899SCharles.Forsyth     return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
1394*37da2899SCharles.Forsyth   }
1395*37da2899SCharles.Forsyth 
1396*37da2899SCharles.Forsyth 
1397*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
Write_CVT(EXEC_OP_ FT_ULong idx,FT_F26Dot6 value)1398*37da2899SCharles.Forsyth   Write_CVT( EXEC_OP_ FT_ULong    idx,
1399*37da2899SCharles.Forsyth                       FT_F26Dot6  value )
1400*37da2899SCharles.Forsyth   {
1401*37da2899SCharles.Forsyth     CUR.cvt[idx] = value;
1402*37da2899SCharles.Forsyth   }
1403*37da2899SCharles.Forsyth 
1404*37da2899SCharles.Forsyth 
1405*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
Write_CVT_Stretched(EXEC_OP_ FT_ULong idx,FT_F26Dot6 value)1406*37da2899SCharles.Forsyth   Write_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
1407*37da2899SCharles.Forsyth                                 FT_F26Dot6  value )
1408*37da2899SCharles.Forsyth   {
1409*37da2899SCharles.Forsyth     CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
1410*37da2899SCharles.Forsyth   }
1411*37da2899SCharles.Forsyth 
1412*37da2899SCharles.Forsyth 
1413*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
Move_CVT(EXEC_OP_ FT_ULong idx,FT_F26Dot6 value)1414*37da2899SCharles.Forsyth   Move_CVT( EXEC_OP_ FT_ULong    idx,
1415*37da2899SCharles.Forsyth                      FT_F26Dot6  value )
1416*37da2899SCharles.Forsyth   {
1417*37da2899SCharles.Forsyth     CUR.cvt[idx] += value;
1418*37da2899SCharles.Forsyth   }
1419*37da2899SCharles.Forsyth 
1420*37da2899SCharles.Forsyth 
1421*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
Move_CVT_Stretched(EXEC_OP_ FT_ULong idx,FT_F26Dot6 value)1422*37da2899SCharles.Forsyth   Move_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
1423*37da2899SCharles.Forsyth                                FT_F26Dot6  value )
1424*37da2899SCharles.Forsyth   {
1425*37da2899SCharles.Forsyth     CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
1426*37da2899SCharles.Forsyth   }
1427*37da2899SCharles.Forsyth 
1428*37da2899SCharles.Forsyth 
1429*37da2899SCharles.Forsyth   /*************************************************************************/
1430*37da2899SCharles.Forsyth   /*                                                                       */
1431*37da2899SCharles.Forsyth   /* <Function>                                                            */
1432*37da2899SCharles.Forsyth   /*    GetShortIns                                                        */
1433*37da2899SCharles.Forsyth   /*                                                                       */
1434*37da2899SCharles.Forsyth   /* <Description>                                                         */
1435*37da2899SCharles.Forsyth   /*    Returns a short integer taken from the instruction stream at       */
1436*37da2899SCharles.Forsyth   /*    address IP.                                                        */
1437*37da2899SCharles.Forsyth   /*                                                                       */
1438*37da2899SCharles.Forsyth   /* <Return>                                                              */
1439*37da2899SCharles.Forsyth   /*    Short read at code[IP].                                            */
1440*37da2899SCharles.Forsyth   /*                                                                       */
1441*37da2899SCharles.Forsyth   /* <Note>                                                                */
1442*37da2899SCharles.Forsyth   /*    This one could become a macro.                                     */
1443*37da2899SCharles.Forsyth   /*                                                                       */
1444*37da2899SCharles.Forsyth   static FT_Short
GetShortIns(EXEC_OP)1445*37da2899SCharles.Forsyth   GetShortIns( EXEC_OP )
1446*37da2899SCharles.Forsyth   {
1447*37da2899SCharles.Forsyth     /* Reading a byte stream so there is no endianess (DaveP) */
1448*37da2899SCharles.Forsyth     CUR.IP += 2;
1449*37da2899SCharles.Forsyth     return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
1450*37da2899SCharles.Forsyth                          CUR.code[CUR.IP - 1]      );
1451*37da2899SCharles.Forsyth   }
1452*37da2899SCharles.Forsyth 
1453*37da2899SCharles.Forsyth 
1454*37da2899SCharles.Forsyth   /*************************************************************************/
1455*37da2899SCharles.Forsyth   /*                                                                       */
1456*37da2899SCharles.Forsyth   /* <Function>                                                            */
1457*37da2899SCharles.Forsyth   /*    Ins_Goto_CodeRange                                                 */
1458*37da2899SCharles.Forsyth   /*                                                                       */
1459*37da2899SCharles.Forsyth   /* <Description>                                                         */
1460*37da2899SCharles.Forsyth   /*    Goes to a certain code range in the instruction stream.            */
1461*37da2899SCharles.Forsyth   /*                                                                       */
1462*37da2899SCharles.Forsyth   /* <Input>                                                               */
1463*37da2899SCharles.Forsyth   /*    aRange :: The index of the code range.                             */
1464*37da2899SCharles.Forsyth   /*                                                                       */
1465*37da2899SCharles.Forsyth   /*    aIP    :: The new IP address in the code range.                    */
1466*37da2899SCharles.Forsyth   /*                                                                       */
1467*37da2899SCharles.Forsyth   /* <Return>                                                              */
1468*37da2899SCharles.Forsyth   /*    SUCCESS or FAILURE.                                                */
1469*37da2899SCharles.Forsyth   /*                                                                       */
1470*37da2899SCharles.Forsyth   static FT_Bool
Ins_Goto_CodeRange(EXEC_OP_ FT_Int aRange,FT_ULong aIP)1471*37da2899SCharles.Forsyth   Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,
1472*37da2899SCharles.Forsyth                                FT_ULong  aIP )
1473*37da2899SCharles.Forsyth   {
1474*37da2899SCharles.Forsyth     TT_CodeRange*  range;
1475*37da2899SCharles.Forsyth 
1476*37da2899SCharles.Forsyth 
1477*37da2899SCharles.Forsyth     if ( aRange < 1 || aRange > 3 )
1478*37da2899SCharles.Forsyth     {
1479*37da2899SCharles.Forsyth       CUR.error = TT_Err_Bad_Argument;
1480*37da2899SCharles.Forsyth       return FAILURE;
1481*37da2899SCharles.Forsyth     }
1482*37da2899SCharles.Forsyth 
1483*37da2899SCharles.Forsyth     range = &CUR.codeRangeTable[aRange - 1];
1484*37da2899SCharles.Forsyth 
1485*37da2899SCharles.Forsyth     if ( range->base == NULL )     /* invalid coderange */
1486*37da2899SCharles.Forsyth     {
1487*37da2899SCharles.Forsyth       CUR.error = TT_Err_Invalid_CodeRange;
1488*37da2899SCharles.Forsyth       return FAILURE;
1489*37da2899SCharles.Forsyth     }
1490*37da2899SCharles.Forsyth 
1491*37da2899SCharles.Forsyth     /* NOTE: Because the last instruction of a program may be a CALL */
1492*37da2899SCharles.Forsyth     /*       which will return to the first byte *after* the code    */
1493*37da2899SCharles.Forsyth     /*       range, we test for AIP <= Size, instead of AIP < Size.  */
1494*37da2899SCharles.Forsyth 
1495*37da2899SCharles.Forsyth     if ( aIP > range->size )
1496*37da2899SCharles.Forsyth     {
1497*37da2899SCharles.Forsyth       CUR.error = TT_Err_Code_Overflow;
1498*37da2899SCharles.Forsyth       return FAILURE;
1499*37da2899SCharles.Forsyth     }
1500*37da2899SCharles.Forsyth 
1501*37da2899SCharles.Forsyth     CUR.code     = range->base;
1502*37da2899SCharles.Forsyth     CUR.codeSize = range->size;
1503*37da2899SCharles.Forsyth     CUR.IP       = aIP;
1504*37da2899SCharles.Forsyth     CUR.curRange = aRange;
1505*37da2899SCharles.Forsyth 
1506*37da2899SCharles.Forsyth     return SUCCESS;
1507*37da2899SCharles.Forsyth   }
1508*37da2899SCharles.Forsyth 
1509*37da2899SCharles.Forsyth 
1510*37da2899SCharles.Forsyth   /*************************************************************************/
1511*37da2899SCharles.Forsyth   /*                                                                       */
1512*37da2899SCharles.Forsyth   /* <Function>                                                            */
1513*37da2899SCharles.Forsyth   /*    Direct_Move                                                        */
1514*37da2899SCharles.Forsyth   /*                                                                       */
1515*37da2899SCharles.Forsyth   /* <Description>                                                         */
1516*37da2899SCharles.Forsyth   /*    Moves a point by a given distance along the freedom vector.  The   */
1517*37da2899SCharles.Forsyth   /*    point will be `touched'.                                           */
1518*37da2899SCharles.Forsyth   /*                                                                       */
1519*37da2899SCharles.Forsyth   /* <Input>                                                               */
1520*37da2899SCharles.Forsyth   /*    point    :: The index of the point to move.                        */
1521*37da2899SCharles.Forsyth   /*                                                                       */
1522*37da2899SCharles.Forsyth   /*    distance :: The distance to apply.                                 */
1523*37da2899SCharles.Forsyth   /*                                                                       */
1524*37da2899SCharles.Forsyth   /* <InOut>                                                               */
1525*37da2899SCharles.Forsyth   /*    zone     :: The affected glyph zone.                               */
1526*37da2899SCharles.Forsyth   /*                                                                       */
1527*37da2899SCharles.Forsyth   static void
Direct_Move(EXEC_OP_ TT_GlyphZone zone,FT_UShort point,FT_F26Dot6 distance)1528*37da2899SCharles.Forsyth   Direct_Move( EXEC_OP_ TT_GlyphZone  zone,
1529*37da2899SCharles.Forsyth                         FT_UShort     point,
1530*37da2899SCharles.Forsyth                         FT_F26Dot6    distance )
1531*37da2899SCharles.Forsyth   {
1532*37da2899SCharles.Forsyth     FT_F26Dot6  v;
1533*37da2899SCharles.Forsyth 
1534*37da2899SCharles.Forsyth 
1535*37da2899SCharles.Forsyth     v = CUR.GS.freeVector.x;
1536*37da2899SCharles.Forsyth 
1537*37da2899SCharles.Forsyth     if ( v != 0 )
1538*37da2899SCharles.Forsyth     {
1539*37da2899SCharles.Forsyth 
1540*37da2899SCharles.Forsyth #ifdef NO_APPLE_PATENT
1541*37da2899SCharles.Forsyth 
1542*37da2899SCharles.Forsyth       if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
1543*37da2899SCharles.Forsyth         zone->cur[point].x += distance;
1544*37da2899SCharles.Forsyth 
1545*37da2899SCharles.Forsyth #else
1546*37da2899SCharles.Forsyth 
1547*37da2899SCharles.Forsyth       zone->cur[point].x += TT_MULDIV( distance,
1548*37da2899SCharles.Forsyth                                        v * 0x10000L,
1549*37da2899SCharles.Forsyth                                        CUR.F_dot_P );
1550*37da2899SCharles.Forsyth 
1551*37da2899SCharles.Forsyth #endif
1552*37da2899SCharles.Forsyth 
1553*37da2899SCharles.Forsyth       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1554*37da2899SCharles.Forsyth     }
1555*37da2899SCharles.Forsyth 
1556*37da2899SCharles.Forsyth     v = CUR.GS.freeVector.y;
1557*37da2899SCharles.Forsyth 
1558*37da2899SCharles.Forsyth     if ( v != 0 )
1559*37da2899SCharles.Forsyth     {
1560*37da2899SCharles.Forsyth 
1561*37da2899SCharles.Forsyth #ifdef NO_APPLE_PATENT
1562*37da2899SCharles.Forsyth 
1563*37da2899SCharles.Forsyth       if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
1564*37da2899SCharles.Forsyth         zone->cur[point].y += distance;
1565*37da2899SCharles.Forsyth 
1566*37da2899SCharles.Forsyth #else
1567*37da2899SCharles.Forsyth 
1568*37da2899SCharles.Forsyth       zone->cur[point].y += TT_MULDIV( distance,
1569*37da2899SCharles.Forsyth                                        v * 0x10000L,
1570*37da2899SCharles.Forsyth                                        CUR.F_dot_P );
1571*37da2899SCharles.Forsyth 
1572*37da2899SCharles.Forsyth #endif
1573*37da2899SCharles.Forsyth 
1574*37da2899SCharles.Forsyth       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
1575*37da2899SCharles.Forsyth     }
1576*37da2899SCharles.Forsyth   }
1577*37da2899SCharles.Forsyth 
1578*37da2899SCharles.Forsyth 
1579*37da2899SCharles.Forsyth   /*************************************************************************/
1580*37da2899SCharles.Forsyth   /*                                                                       */
1581*37da2899SCharles.Forsyth   /* Special versions of Direct_Move()                                     */
1582*37da2899SCharles.Forsyth   /*                                                                       */
1583*37da2899SCharles.Forsyth   /*   The following versions are used whenever both vectors are both      */
1584*37da2899SCharles.Forsyth   /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1585*37da2899SCharles.Forsyth   /*                                                                       */
1586*37da2899SCharles.Forsyth   /*************************************************************************/
1587*37da2899SCharles.Forsyth 
1588*37da2899SCharles.Forsyth 
1589*37da2899SCharles.Forsyth   static void
Direct_Move_X(EXEC_OP_ TT_GlyphZone zone,FT_UShort point,FT_F26Dot6 distance)1590*37da2899SCharles.Forsyth   Direct_Move_X( EXEC_OP_ TT_GlyphZone  zone,
1591*37da2899SCharles.Forsyth                           FT_UShort     point,
1592*37da2899SCharles.Forsyth                           FT_F26Dot6    distance )
1593*37da2899SCharles.Forsyth   {
1594*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1595*37da2899SCharles.Forsyth 
1596*37da2899SCharles.Forsyth     zone->cur[point].x += distance;
1597*37da2899SCharles.Forsyth     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
1598*37da2899SCharles.Forsyth   }
1599*37da2899SCharles.Forsyth 
1600*37da2899SCharles.Forsyth 
1601*37da2899SCharles.Forsyth   static void
Direct_Move_Y(EXEC_OP_ TT_GlyphZone zone,FT_UShort point,FT_F26Dot6 distance)1602*37da2899SCharles.Forsyth   Direct_Move_Y( EXEC_OP_ TT_GlyphZone  zone,
1603*37da2899SCharles.Forsyth                           FT_UShort     point,
1604*37da2899SCharles.Forsyth                           FT_F26Dot6    distance )
1605*37da2899SCharles.Forsyth   {
1606*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1607*37da2899SCharles.Forsyth 
1608*37da2899SCharles.Forsyth     zone->cur[point].y += distance;
1609*37da2899SCharles.Forsyth     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;
1610*37da2899SCharles.Forsyth   }
1611*37da2899SCharles.Forsyth 
1612*37da2899SCharles.Forsyth 
1613*37da2899SCharles.Forsyth   /*************************************************************************/
1614*37da2899SCharles.Forsyth   /*                                                                       */
1615*37da2899SCharles.Forsyth   /* <Function>                                                            */
1616*37da2899SCharles.Forsyth   /*    Round_None                                                         */
1617*37da2899SCharles.Forsyth   /*                                                                       */
1618*37da2899SCharles.Forsyth   /* <Description>                                                         */
1619*37da2899SCharles.Forsyth   /*    Does not round, but adds engine compensation.                      */
1620*37da2899SCharles.Forsyth   /*                                                                       */
1621*37da2899SCharles.Forsyth   /* <Input>                                                               */
1622*37da2899SCharles.Forsyth   /*    distance     :: The distance (not) to round.                       */
1623*37da2899SCharles.Forsyth   /*                                                                       */
1624*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1625*37da2899SCharles.Forsyth   /*                                                                       */
1626*37da2899SCharles.Forsyth   /* <Return>                                                              */
1627*37da2899SCharles.Forsyth   /*    The compensated distance.                                          */
1628*37da2899SCharles.Forsyth   /*                                                                       */
1629*37da2899SCharles.Forsyth   /* <Note>                                                                */
1630*37da2899SCharles.Forsyth   /*    The TrueType specification says very few about the relationship    */
1631*37da2899SCharles.Forsyth   /*    between rounding and engine compensation.  However, it seems from  */
1632*37da2899SCharles.Forsyth   /*    the description of super round that we should add the compensation */
1633*37da2899SCharles.Forsyth   /*    before rounding.                                                   */
1634*37da2899SCharles.Forsyth   /*                                                                       */
1635*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_None(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1636*37da2899SCharles.Forsyth   Round_None( EXEC_OP_ FT_F26Dot6  distance,
1637*37da2899SCharles.Forsyth                        FT_F26Dot6  compensation )
1638*37da2899SCharles.Forsyth   {
1639*37da2899SCharles.Forsyth     FT_F26Dot6  val;
1640*37da2899SCharles.Forsyth 
1641*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1642*37da2899SCharles.Forsyth 
1643*37da2899SCharles.Forsyth 
1644*37da2899SCharles.Forsyth     if ( distance >= 0 )
1645*37da2899SCharles.Forsyth     {
1646*37da2899SCharles.Forsyth       val = distance + compensation;
1647*37da2899SCharles.Forsyth       if ( val < 0 )
1648*37da2899SCharles.Forsyth         val = 0;
1649*37da2899SCharles.Forsyth     }
1650*37da2899SCharles.Forsyth     else {
1651*37da2899SCharles.Forsyth       val = distance - compensation;
1652*37da2899SCharles.Forsyth       if ( val > 0 )
1653*37da2899SCharles.Forsyth         val = 0;
1654*37da2899SCharles.Forsyth     }
1655*37da2899SCharles.Forsyth     return val;
1656*37da2899SCharles.Forsyth   }
1657*37da2899SCharles.Forsyth 
1658*37da2899SCharles.Forsyth 
1659*37da2899SCharles.Forsyth   /*************************************************************************/
1660*37da2899SCharles.Forsyth   /*                                                                       */
1661*37da2899SCharles.Forsyth   /* <Function>                                                            */
1662*37da2899SCharles.Forsyth   /*    Round_To_Grid                                                      */
1663*37da2899SCharles.Forsyth   /*                                                                       */
1664*37da2899SCharles.Forsyth   /* <Description>                                                         */
1665*37da2899SCharles.Forsyth   /*    Rounds value to grid after adding engine compensation.             */
1666*37da2899SCharles.Forsyth   /*                                                                       */
1667*37da2899SCharles.Forsyth   /* <Input>                                                               */
1668*37da2899SCharles.Forsyth   /*    distance     :: The distance to round.                             */
1669*37da2899SCharles.Forsyth   /*                                                                       */
1670*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1671*37da2899SCharles.Forsyth   /*                                                                       */
1672*37da2899SCharles.Forsyth   /* <Return>                                                              */
1673*37da2899SCharles.Forsyth   /*    Rounded distance.                                                  */
1674*37da2899SCharles.Forsyth   /*                                                                       */
1675*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_To_Grid(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1676*37da2899SCharles.Forsyth   Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
1677*37da2899SCharles.Forsyth                           FT_F26Dot6  compensation )
1678*37da2899SCharles.Forsyth   {
1679*37da2899SCharles.Forsyth     FT_F26Dot6  val;
1680*37da2899SCharles.Forsyth 
1681*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1682*37da2899SCharles.Forsyth 
1683*37da2899SCharles.Forsyth 
1684*37da2899SCharles.Forsyth     if ( distance >= 0 )
1685*37da2899SCharles.Forsyth     {
1686*37da2899SCharles.Forsyth       val = distance + compensation + 32;
1687*37da2899SCharles.Forsyth       if ( val > 0 )
1688*37da2899SCharles.Forsyth         val &= ~63;
1689*37da2899SCharles.Forsyth       else
1690*37da2899SCharles.Forsyth         val = 0;
1691*37da2899SCharles.Forsyth     }
1692*37da2899SCharles.Forsyth     else
1693*37da2899SCharles.Forsyth     {
1694*37da2899SCharles.Forsyth       val = -( ( compensation - distance + 32 ) & -64 );
1695*37da2899SCharles.Forsyth       if ( val > 0 )
1696*37da2899SCharles.Forsyth         val = 0;
1697*37da2899SCharles.Forsyth     }
1698*37da2899SCharles.Forsyth 
1699*37da2899SCharles.Forsyth     return  val;
1700*37da2899SCharles.Forsyth   }
1701*37da2899SCharles.Forsyth 
1702*37da2899SCharles.Forsyth 
1703*37da2899SCharles.Forsyth   /*************************************************************************/
1704*37da2899SCharles.Forsyth   /*                                                                       */
1705*37da2899SCharles.Forsyth   /* <Function>                                                            */
1706*37da2899SCharles.Forsyth   /*    Round_To_Half_Grid                                                 */
1707*37da2899SCharles.Forsyth   /*                                                                       */
1708*37da2899SCharles.Forsyth   /* <Description>                                                         */
1709*37da2899SCharles.Forsyth   /*    Rounds value to half grid after adding engine compensation.        */
1710*37da2899SCharles.Forsyth   /*                                                                       */
1711*37da2899SCharles.Forsyth   /* <Input>                                                               */
1712*37da2899SCharles.Forsyth   /*    distance     :: The distance to round.                             */
1713*37da2899SCharles.Forsyth   /*                                                                       */
1714*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1715*37da2899SCharles.Forsyth   /*                                                                       */
1716*37da2899SCharles.Forsyth   /* <Return>                                                              */
1717*37da2899SCharles.Forsyth   /*    Rounded distance.                                                  */
1718*37da2899SCharles.Forsyth   /*                                                                       */
1719*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_To_Half_Grid(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1720*37da2899SCharles.Forsyth   Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,
1721*37da2899SCharles.Forsyth                                FT_F26Dot6  compensation )
1722*37da2899SCharles.Forsyth   {
1723*37da2899SCharles.Forsyth     FT_F26Dot6  val;
1724*37da2899SCharles.Forsyth 
1725*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1726*37da2899SCharles.Forsyth 
1727*37da2899SCharles.Forsyth 
1728*37da2899SCharles.Forsyth     if ( distance >= 0 )
1729*37da2899SCharles.Forsyth     {
1730*37da2899SCharles.Forsyth       val = ( ( distance + compensation ) & -64 ) + 32;
1731*37da2899SCharles.Forsyth       if ( val < 0 )
1732*37da2899SCharles.Forsyth         val = 0;
1733*37da2899SCharles.Forsyth     }
1734*37da2899SCharles.Forsyth     else
1735*37da2899SCharles.Forsyth     {
1736*37da2899SCharles.Forsyth       val = -( ( (compensation - distance) & -64 ) + 32 );
1737*37da2899SCharles.Forsyth       if ( val > 0 )
1738*37da2899SCharles.Forsyth         val = 0;
1739*37da2899SCharles.Forsyth     }
1740*37da2899SCharles.Forsyth 
1741*37da2899SCharles.Forsyth     return val;
1742*37da2899SCharles.Forsyth   }
1743*37da2899SCharles.Forsyth 
1744*37da2899SCharles.Forsyth 
1745*37da2899SCharles.Forsyth   /*************************************************************************/
1746*37da2899SCharles.Forsyth   /*                                                                       */
1747*37da2899SCharles.Forsyth   /* <Function>                                                            */
1748*37da2899SCharles.Forsyth   /*    Round_Down_To_Grid                                                 */
1749*37da2899SCharles.Forsyth   /*                                                                       */
1750*37da2899SCharles.Forsyth   /* <Description>                                                         */
1751*37da2899SCharles.Forsyth   /*    Rounds value down to grid after adding engine compensation.        */
1752*37da2899SCharles.Forsyth   /*                                                                       */
1753*37da2899SCharles.Forsyth   /* <Input>                                                               */
1754*37da2899SCharles.Forsyth   /*    distance     :: The distance to round.                             */
1755*37da2899SCharles.Forsyth   /*                                                                       */
1756*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1757*37da2899SCharles.Forsyth   /*                                                                       */
1758*37da2899SCharles.Forsyth   /* <Return>                                                              */
1759*37da2899SCharles.Forsyth   /*    Rounded distance.                                                  */
1760*37da2899SCharles.Forsyth   /*                                                                       */
1761*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_Down_To_Grid(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1762*37da2899SCharles.Forsyth   Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
1763*37da2899SCharles.Forsyth                                FT_F26Dot6  compensation )
1764*37da2899SCharles.Forsyth   {
1765*37da2899SCharles.Forsyth     FT_F26Dot6  val;
1766*37da2899SCharles.Forsyth 
1767*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1768*37da2899SCharles.Forsyth 
1769*37da2899SCharles.Forsyth 
1770*37da2899SCharles.Forsyth     if ( distance >= 0 )
1771*37da2899SCharles.Forsyth     {
1772*37da2899SCharles.Forsyth       val = distance + compensation;
1773*37da2899SCharles.Forsyth       if ( val > 0 )
1774*37da2899SCharles.Forsyth         val &= ~63;
1775*37da2899SCharles.Forsyth       else
1776*37da2899SCharles.Forsyth         val = 0;
1777*37da2899SCharles.Forsyth     }
1778*37da2899SCharles.Forsyth     else
1779*37da2899SCharles.Forsyth     {
1780*37da2899SCharles.Forsyth       val = -( ( compensation - distance ) & -64 );
1781*37da2899SCharles.Forsyth       if ( val > 0 )
1782*37da2899SCharles.Forsyth         val = 0;
1783*37da2899SCharles.Forsyth     }
1784*37da2899SCharles.Forsyth 
1785*37da2899SCharles.Forsyth     return val;
1786*37da2899SCharles.Forsyth   }
1787*37da2899SCharles.Forsyth 
1788*37da2899SCharles.Forsyth 
1789*37da2899SCharles.Forsyth   /*************************************************************************/
1790*37da2899SCharles.Forsyth   /*                                                                       */
1791*37da2899SCharles.Forsyth   /* <Function>                                                            */
1792*37da2899SCharles.Forsyth   /*    Round_Up_To_Grid                                                   */
1793*37da2899SCharles.Forsyth   /*                                                                       */
1794*37da2899SCharles.Forsyth   /* <Description>                                                         */
1795*37da2899SCharles.Forsyth   /*    Rounds value up to grid after adding engine compensation.          */
1796*37da2899SCharles.Forsyth   /*                                                                       */
1797*37da2899SCharles.Forsyth   /* <Input>                                                               */
1798*37da2899SCharles.Forsyth   /*    distance     :: The distance to round.                             */
1799*37da2899SCharles.Forsyth   /*                                                                       */
1800*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1801*37da2899SCharles.Forsyth   /*                                                                       */
1802*37da2899SCharles.Forsyth   /* <Return>                                                              */
1803*37da2899SCharles.Forsyth   /*    Rounded distance.                                                  */
1804*37da2899SCharles.Forsyth   /*                                                                       */
1805*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_Up_To_Grid(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1806*37da2899SCharles.Forsyth   Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
1807*37da2899SCharles.Forsyth                              FT_F26Dot6  compensation )
1808*37da2899SCharles.Forsyth   {
1809*37da2899SCharles.Forsyth     FT_F26Dot6  val;
1810*37da2899SCharles.Forsyth 
1811*37da2899SCharles.Forsyth 
1812*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1813*37da2899SCharles.Forsyth 
1814*37da2899SCharles.Forsyth     if ( distance >= 0 )
1815*37da2899SCharles.Forsyth     {
1816*37da2899SCharles.Forsyth       val = distance + compensation + 63;
1817*37da2899SCharles.Forsyth       if ( val > 0 )
1818*37da2899SCharles.Forsyth         val &= ~63;
1819*37da2899SCharles.Forsyth       else
1820*37da2899SCharles.Forsyth         val = 0;
1821*37da2899SCharles.Forsyth     }
1822*37da2899SCharles.Forsyth     else
1823*37da2899SCharles.Forsyth     {
1824*37da2899SCharles.Forsyth       val = -( ( compensation - distance + 63 ) & -64 );
1825*37da2899SCharles.Forsyth       if ( val > 0 )
1826*37da2899SCharles.Forsyth         val = 0;
1827*37da2899SCharles.Forsyth     }
1828*37da2899SCharles.Forsyth 
1829*37da2899SCharles.Forsyth     return val;
1830*37da2899SCharles.Forsyth   }
1831*37da2899SCharles.Forsyth 
1832*37da2899SCharles.Forsyth 
1833*37da2899SCharles.Forsyth   /*************************************************************************/
1834*37da2899SCharles.Forsyth   /*                                                                       */
1835*37da2899SCharles.Forsyth   /* <Function>                                                            */
1836*37da2899SCharles.Forsyth   /*    Round_To_Double_Grid                                               */
1837*37da2899SCharles.Forsyth   /*                                                                       */
1838*37da2899SCharles.Forsyth   /* <Description>                                                         */
1839*37da2899SCharles.Forsyth   /*    Rounds value to double grid after adding engine compensation.      */
1840*37da2899SCharles.Forsyth   /*                                                                       */
1841*37da2899SCharles.Forsyth   /* <Input>                                                               */
1842*37da2899SCharles.Forsyth   /*    distance     :: The distance to round.                             */
1843*37da2899SCharles.Forsyth   /*                                                                       */
1844*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1845*37da2899SCharles.Forsyth   /*                                                                       */
1846*37da2899SCharles.Forsyth   /* <Return>                                                              */
1847*37da2899SCharles.Forsyth   /*    Rounded distance.                                                  */
1848*37da2899SCharles.Forsyth   /*                                                                       */
1849*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_To_Double_Grid(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1850*37da2899SCharles.Forsyth   Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,
1851*37da2899SCharles.Forsyth                                  FT_F26Dot6  compensation )
1852*37da2899SCharles.Forsyth   {
1853*37da2899SCharles.Forsyth     FT_F26Dot6 val;
1854*37da2899SCharles.Forsyth 
1855*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
1856*37da2899SCharles.Forsyth 
1857*37da2899SCharles.Forsyth 
1858*37da2899SCharles.Forsyth     if ( distance >= 0 )
1859*37da2899SCharles.Forsyth     {
1860*37da2899SCharles.Forsyth       val = distance + compensation + 16;
1861*37da2899SCharles.Forsyth       if ( val > 0 )
1862*37da2899SCharles.Forsyth         val &= ~31;
1863*37da2899SCharles.Forsyth       else
1864*37da2899SCharles.Forsyth         val = 0;
1865*37da2899SCharles.Forsyth     }
1866*37da2899SCharles.Forsyth     else
1867*37da2899SCharles.Forsyth     {
1868*37da2899SCharles.Forsyth       val = -( ( compensation - distance + 16 ) & -32 );
1869*37da2899SCharles.Forsyth       if ( val > 0 )
1870*37da2899SCharles.Forsyth         val = 0;
1871*37da2899SCharles.Forsyth     }
1872*37da2899SCharles.Forsyth 
1873*37da2899SCharles.Forsyth     return val;
1874*37da2899SCharles.Forsyth   }
1875*37da2899SCharles.Forsyth 
1876*37da2899SCharles.Forsyth 
1877*37da2899SCharles.Forsyth   /*************************************************************************/
1878*37da2899SCharles.Forsyth   /*                                                                       */
1879*37da2899SCharles.Forsyth   /* <Function>                                                            */
1880*37da2899SCharles.Forsyth   /*    Round_Super                                                        */
1881*37da2899SCharles.Forsyth   /*                                                                       */
1882*37da2899SCharles.Forsyth   /* <Description>                                                         */
1883*37da2899SCharles.Forsyth   /*    Super-rounds value to grid after adding engine compensation.       */
1884*37da2899SCharles.Forsyth   /*                                                                       */
1885*37da2899SCharles.Forsyth   /* <Input>                                                               */
1886*37da2899SCharles.Forsyth   /*    distance     :: The distance to round.                             */
1887*37da2899SCharles.Forsyth   /*                                                                       */
1888*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1889*37da2899SCharles.Forsyth   /*                                                                       */
1890*37da2899SCharles.Forsyth   /* <Return>                                                              */
1891*37da2899SCharles.Forsyth   /*    Rounded distance.                                                  */
1892*37da2899SCharles.Forsyth   /*                                                                       */
1893*37da2899SCharles.Forsyth   /* <Note>                                                                */
1894*37da2899SCharles.Forsyth   /*    The TrueType specification says very few about the relationship    */
1895*37da2899SCharles.Forsyth   /*    between rounding and engine compensation.  However, it seems from  */
1896*37da2899SCharles.Forsyth   /*    the description of super round that we should add the compensation */
1897*37da2899SCharles.Forsyth   /*    before rounding.                                                   */
1898*37da2899SCharles.Forsyth   /*                                                                       */
1899*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_Super(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1900*37da2899SCharles.Forsyth   Round_Super( EXEC_OP_ FT_F26Dot6  distance,
1901*37da2899SCharles.Forsyth                         FT_F26Dot6  compensation )
1902*37da2899SCharles.Forsyth   {
1903*37da2899SCharles.Forsyth     FT_F26Dot6  val;
1904*37da2899SCharles.Forsyth 
1905*37da2899SCharles.Forsyth 
1906*37da2899SCharles.Forsyth     if ( distance >= 0 )
1907*37da2899SCharles.Forsyth     {
1908*37da2899SCharles.Forsyth       val = ( distance - CUR.phase + CUR.threshold + compensation ) &
1909*37da2899SCharles.Forsyth               -CUR.period;
1910*37da2899SCharles.Forsyth       if ( val < 0 )
1911*37da2899SCharles.Forsyth         val = 0;
1912*37da2899SCharles.Forsyth       val += CUR.phase;
1913*37da2899SCharles.Forsyth     }
1914*37da2899SCharles.Forsyth     else
1915*37da2899SCharles.Forsyth     {
1916*37da2899SCharles.Forsyth       val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
1917*37da2899SCharles.Forsyth                -CUR.period );
1918*37da2899SCharles.Forsyth       if ( val > 0 )
1919*37da2899SCharles.Forsyth         val = 0;
1920*37da2899SCharles.Forsyth       val -= CUR.phase;
1921*37da2899SCharles.Forsyth     }
1922*37da2899SCharles.Forsyth 
1923*37da2899SCharles.Forsyth     return val;
1924*37da2899SCharles.Forsyth   }
1925*37da2899SCharles.Forsyth 
1926*37da2899SCharles.Forsyth 
1927*37da2899SCharles.Forsyth   /*************************************************************************/
1928*37da2899SCharles.Forsyth   /*                                                                       */
1929*37da2899SCharles.Forsyth   /* <Function>                                                            */
1930*37da2899SCharles.Forsyth   /*    Round_Super_45                                                     */
1931*37da2899SCharles.Forsyth   /*                                                                       */
1932*37da2899SCharles.Forsyth   /* <Description>                                                         */
1933*37da2899SCharles.Forsyth   /*    Super-rounds value to grid after adding engine compensation.       */
1934*37da2899SCharles.Forsyth   /*                                                                       */
1935*37da2899SCharles.Forsyth   /* <Input>                                                               */
1936*37da2899SCharles.Forsyth   /*    distance     :: The distance to round.                             */
1937*37da2899SCharles.Forsyth   /*                                                                       */
1938*37da2899SCharles.Forsyth   /*    compensation :: The engine compensation.                           */
1939*37da2899SCharles.Forsyth   /*                                                                       */
1940*37da2899SCharles.Forsyth   /* <Return>                                                              */
1941*37da2899SCharles.Forsyth   /*    Rounded distance.                                                  */
1942*37da2899SCharles.Forsyth   /*                                                                       */
1943*37da2899SCharles.Forsyth   /* <Note>                                                                */
1944*37da2899SCharles.Forsyth   /*    There is a separate function for Round_Super_45() as we may need   */
1945*37da2899SCharles.Forsyth   /*    greater precision.                                                 */
1946*37da2899SCharles.Forsyth   /*                                                                       */
1947*37da2899SCharles.Forsyth   static FT_F26Dot6
Round_Super_45(EXEC_OP_ FT_F26Dot6 distance,FT_F26Dot6 compensation)1948*37da2899SCharles.Forsyth   Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,
1949*37da2899SCharles.Forsyth                            FT_F26Dot6  compensation )
1950*37da2899SCharles.Forsyth   {
1951*37da2899SCharles.Forsyth     FT_F26Dot6  val;
1952*37da2899SCharles.Forsyth 
1953*37da2899SCharles.Forsyth 
1954*37da2899SCharles.Forsyth     if ( distance >= 0 )
1955*37da2899SCharles.Forsyth     {
1956*37da2899SCharles.Forsyth       val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
1957*37da2899SCharles.Forsyth                 CUR.period ) * CUR.period;
1958*37da2899SCharles.Forsyth       if ( val < 0 )
1959*37da2899SCharles.Forsyth         val = 0;
1960*37da2899SCharles.Forsyth       val += CUR.phase;
1961*37da2899SCharles.Forsyth     }
1962*37da2899SCharles.Forsyth     else
1963*37da2899SCharles.Forsyth     {
1964*37da2899SCharles.Forsyth       val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
1965*37da2899SCharles.Forsyth                    CUR.period ) * CUR.period );
1966*37da2899SCharles.Forsyth       if ( val > 0 )
1967*37da2899SCharles.Forsyth         val = 0;
1968*37da2899SCharles.Forsyth       val -= CUR.phase;
1969*37da2899SCharles.Forsyth     }
1970*37da2899SCharles.Forsyth 
1971*37da2899SCharles.Forsyth     return val;
1972*37da2899SCharles.Forsyth   }
1973*37da2899SCharles.Forsyth 
1974*37da2899SCharles.Forsyth 
1975*37da2899SCharles.Forsyth   /*************************************************************************/
1976*37da2899SCharles.Forsyth   /*                                                                       */
1977*37da2899SCharles.Forsyth   /* <Function>                                                            */
1978*37da2899SCharles.Forsyth   /*    Compute_Round                                                      */
1979*37da2899SCharles.Forsyth   /*                                                                       */
1980*37da2899SCharles.Forsyth   /* <Description>                                                         */
1981*37da2899SCharles.Forsyth   /*    Sets the rounding mode.                                            */
1982*37da2899SCharles.Forsyth   /*                                                                       */
1983*37da2899SCharles.Forsyth   /* <Input>                                                               */
1984*37da2899SCharles.Forsyth   /*    round_mode :: The rounding mode to be used.                        */
1985*37da2899SCharles.Forsyth   /*                                                                       */
1986*37da2899SCharles.Forsyth   static void
Compute_Round(EXEC_OP_ FT_Byte round_mode)1987*37da2899SCharles.Forsyth   Compute_Round( EXEC_OP_ FT_Byte  round_mode )
1988*37da2899SCharles.Forsyth   {
1989*37da2899SCharles.Forsyth     switch ( round_mode )
1990*37da2899SCharles.Forsyth     {
1991*37da2899SCharles.Forsyth     case TT_Round_Off:
1992*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_None;
1993*37da2899SCharles.Forsyth       break;
1994*37da2899SCharles.Forsyth 
1995*37da2899SCharles.Forsyth     case TT_Round_To_Grid:
1996*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_To_Grid;
1997*37da2899SCharles.Forsyth       break;
1998*37da2899SCharles.Forsyth 
1999*37da2899SCharles.Forsyth     case TT_Round_Up_To_Grid:
2000*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
2001*37da2899SCharles.Forsyth       break;
2002*37da2899SCharles.Forsyth 
2003*37da2899SCharles.Forsyth     case TT_Round_Down_To_Grid:
2004*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
2005*37da2899SCharles.Forsyth       break;
2006*37da2899SCharles.Forsyth 
2007*37da2899SCharles.Forsyth     case TT_Round_To_Half_Grid:
2008*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
2009*37da2899SCharles.Forsyth       break;
2010*37da2899SCharles.Forsyth 
2011*37da2899SCharles.Forsyth     case TT_Round_To_Double_Grid:
2012*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
2013*37da2899SCharles.Forsyth       break;
2014*37da2899SCharles.Forsyth 
2015*37da2899SCharles.Forsyth     case TT_Round_Super:
2016*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_Super;
2017*37da2899SCharles.Forsyth       break;
2018*37da2899SCharles.Forsyth 
2019*37da2899SCharles.Forsyth     case TT_Round_Super_45:
2020*37da2899SCharles.Forsyth       CUR.func_round = (TT_Round_Func)Round_Super_45;
2021*37da2899SCharles.Forsyth       break;
2022*37da2899SCharles.Forsyth     }
2023*37da2899SCharles.Forsyth   }
2024*37da2899SCharles.Forsyth 
2025*37da2899SCharles.Forsyth 
2026*37da2899SCharles.Forsyth   /*************************************************************************/
2027*37da2899SCharles.Forsyth   /*                                                                       */
2028*37da2899SCharles.Forsyth   /* <Function>                                                            */
2029*37da2899SCharles.Forsyth   /*    SetSuperRound                                                      */
2030*37da2899SCharles.Forsyth   /*                                                                       */
2031*37da2899SCharles.Forsyth   /* <Description>                                                         */
2032*37da2899SCharles.Forsyth   /*    Sets Super Round parameters.                                       */
2033*37da2899SCharles.Forsyth   /*                                                                       */
2034*37da2899SCharles.Forsyth   /* <Input>                                                               */
2035*37da2899SCharles.Forsyth   /*    GridPeriod :: Grid period                                          */
2036*37da2899SCharles.Forsyth   /*    selector   :: SROUND opcode                                        */
2037*37da2899SCharles.Forsyth   /*                                                                       */
2038*37da2899SCharles.Forsyth   static void
SetSuperRound(EXEC_OP_ FT_F26Dot6 GridPeriod,FT_Long selector)2039*37da2899SCharles.Forsyth   SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
2040*37da2899SCharles.Forsyth                           FT_Long     selector )
2041*37da2899SCharles.Forsyth   {
2042*37da2899SCharles.Forsyth     switch ( (FT_Int)( selector & 0xC0 ) )
2043*37da2899SCharles.Forsyth     {
2044*37da2899SCharles.Forsyth       case 0:
2045*37da2899SCharles.Forsyth         CUR.period = GridPeriod / 2;
2046*37da2899SCharles.Forsyth         break;
2047*37da2899SCharles.Forsyth 
2048*37da2899SCharles.Forsyth       case 0x40:
2049*37da2899SCharles.Forsyth         CUR.period = GridPeriod;
2050*37da2899SCharles.Forsyth         break;
2051*37da2899SCharles.Forsyth 
2052*37da2899SCharles.Forsyth       case 0x80:
2053*37da2899SCharles.Forsyth         CUR.period = GridPeriod * 2;
2054*37da2899SCharles.Forsyth         break;
2055*37da2899SCharles.Forsyth 
2056*37da2899SCharles.Forsyth       /* This opcode is reserved, but... */
2057*37da2899SCharles.Forsyth 
2058*37da2899SCharles.Forsyth       case 0xC0:
2059*37da2899SCharles.Forsyth         CUR.period = GridPeriod;
2060*37da2899SCharles.Forsyth         break;
2061*37da2899SCharles.Forsyth     }
2062*37da2899SCharles.Forsyth 
2063*37da2899SCharles.Forsyth     switch ( (FT_Int)( selector & 0x30 ) )
2064*37da2899SCharles.Forsyth     {
2065*37da2899SCharles.Forsyth     case 0:
2066*37da2899SCharles.Forsyth       CUR.phase = 0;
2067*37da2899SCharles.Forsyth       break;
2068*37da2899SCharles.Forsyth 
2069*37da2899SCharles.Forsyth     case 0x10:
2070*37da2899SCharles.Forsyth       CUR.phase = CUR.period / 4;
2071*37da2899SCharles.Forsyth       break;
2072*37da2899SCharles.Forsyth 
2073*37da2899SCharles.Forsyth     case 0x20:
2074*37da2899SCharles.Forsyth       CUR.phase = CUR.period / 2;
2075*37da2899SCharles.Forsyth       break;
2076*37da2899SCharles.Forsyth 
2077*37da2899SCharles.Forsyth     case 0x30:
2078*37da2899SCharles.Forsyth       CUR.phase = GridPeriod * 3 / 4;
2079*37da2899SCharles.Forsyth       break;
2080*37da2899SCharles.Forsyth     }
2081*37da2899SCharles.Forsyth 
2082*37da2899SCharles.Forsyth     if ( (selector & 0x0F) == 0 )
2083*37da2899SCharles.Forsyth       CUR.threshold = CUR.period - 1;
2084*37da2899SCharles.Forsyth     else
2085*37da2899SCharles.Forsyth       CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
2086*37da2899SCharles.Forsyth 
2087*37da2899SCharles.Forsyth     CUR.period    /= 256;
2088*37da2899SCharles.Forsyth     CUR.phase     /= 256;
2089*37da2899SCharles.Forsyth     CUR.threshold /= 256;
2090*37da2899SCharles.Forsyth   }
2091*37da2899SCharles.Forsyth 
2092*37da2899SCharles.Forsyth 
2093*37da2899SCharles.Forsyth   /*************************************************************************/
2094*37da2899SCharles.Forsyth   /*                                                                       */
2095*37da2899SCharles.Forsyth   /* <Function>                                                            */
2096*37da2899SCharles.Forsyth   /*    Project                                                            */
2097*37da2899SCharles.Forsyth   /*                                                                       */
2098*37da2899SCharles.Forsyth   /* <Description>                                                         */
2099*37da2899SCharles.Forsyth   /*    Computes the projection of vector given by (v2-v1) along the       */
2100*37da2899SCharles.Forsyth   /*    current projection vector.                                         */
2101*37da2899SCharles.Forsyth   /*                                                                       */
2102*37da2899SCharles.Forsyth   /* <Input>                                                               */
2103*37da2899SCharles.Forsyth   /*    v1 :: First input vector.                                          */
2104*37da2899SCharles.Forsyth   /*    v2 :: Second input vector.                                         */
2105*37da2899SCharles.Forsyth   /*                                                                       */
2106*37da2899SCharles.Forsyth   /* <Return>                                                              */
2107*37da2899SCharles.Forsyth   /*    The distance in F26dot6 format.                                    */
2108*37da2899SCharles.Forsyth   /*                                                                       */
2109*37da2899SCharles.Forsyth   static FT_F26Dot6
Project(EXEC_OP_ FT_Vector * v1,FT_Vector * v2)2110*37da2899SCharles.Forsyth   Project( EXEC_OP_ FT_Vector*  v1,
2111*37da2899SCharles.Forsyth                     FT_Vector*  v2 )
2112*37da2899SCharles.Forsyth   {
2113*37da2899SCharles.Forsyth     return TT_DotFix14( v1->x - v2->x,
2114*37da2899SCharles.Forsyth                         v1->y - v2->y,
2115*37da2899SCharles.Forsyth                         CUR.GS.projVector.x,
2116*37da2899SCharles.Forsyth                         CUR.GS.projVector.y );
2117*37da2899SCharles.Forsyth   }
2118*37da2899SCharles.Forsyth 
2119*37da2899SCharles.Forsyth 
2120*37da2899SCharles.Forsyth   /*************************************************************************/
2121*37da2899SCharles.Forsyth   /*                                                                       */
2122*37da2899SCharles.Forsyth   /* <Function>                                                            */
2123*37da2899SCharles.Forsyth   /*    Dual_Project                                                       */
2124*37da2899SCharles.Forsyth   /*                                                                       */
2125*37da2899SCharles.Forsyth   /* <Description>                                                         */
2126*37da2899SCharles.Forsyth   /*    Computes the projection of the vector given by (v2-v1) along the   */
2127*37da2899SCharles.Forsyth   /*    current dual vector.                                               */
2128*37da2899SCharles.Forsyth   /*                                                                       */
2129*37da2899SCharles.Forsyth   /* <Input>                                                               */
2130*37da2899SCharles.Forsyth   /*    v1 :: First input vector.                                          */
2131*37da2899SCharles.Forsyth   /*    v2 :: Second input vector.                                         */
2132*37da2899SCharles.Forsyth   /*                                                                       */
2133*37da2899SCharles.Forsyth   /* <Return>                                                              */
2134*37da2899SCharles.Forsyth   /*    The distance in F26dot6 format.                                    */
2135*37da2899SCharles.Forsyth   /*                                                                       */
2136*37da2899SCharles.Forsyth   static FT_F26Dot6
Dual_Project(EXEC_OP_ FT_Vector * v1,FT_Vector * v2)2137*37da2899SCharles.Forsyth   Dual_Project( EXEC_OP_ FT_Vector*  v1,
2138*37da2899SCharles.Forsyth                          FT_Vector*  v2 )
2139*37da2899SCharles.Forsyth   {
2140*37da2899SCharles.Forsyth     return TT_DotFix14( v1->x - v2->x,
2141*37da2899SCharles.Forsyth                         v1->y - v2->y,
2142*37da2899SCharles.Forsyth                         CUR.GS.dualVector.x,
2143*37da2899SCharles.Forsyth                         CUR.GS.dualVector.y );
2144*37da2899SCharles.Forsyth   }
2145*37da2899SCharles.Forsyth 
2146*37da2899SCharles.Forsyth 
2147*37da2899SCharles.Forsyth   /*************************************************************************/
2148*37da2899SCharles.Forsyth   /*                                                                       */
2149*37da2899SCharles.Forsyth   /* <Function>                                                            */
2150*37da2899SCharles.Forsyth   /*    Free_Project                                                       */
2151*37da2899SCharles.Forsyth   /*                                                                       */
2152*37da2899SCharles.Forsyth   /* <Description>                                                         */
2153*37da2899SCharles.Forsyth   /*    Computes the projection of the vector given by (v2-v1) along the   */
2154*37da2899SCharles.Forsyth   /*    current freedom vector.                                            */
2155*37da2899SCharles.Forsyth   /*                                                                       */
2156*37da2899SCharles.Forsyth   /* <Input>                                                               */
2157*37da2899SCharles.Forsyth   /*    v1 :: First input vector.                                          */
2158*37da2899SCharles.Forsyth   /*    v2 :: Second input vector.                                         */
2159*37da2899SCharles.Forsyth   /*                                                                       */
2160*37da2899SCharles.Forsyth   /* <Return>                                                              */
2161*37da2899SCharles.Forsyth   /*    The distance in F26dot6 format.                                    */
2162*37da2899SCharles.Forsyth   /*                                                                       */
2163*37da2899SCharles.Forsyth   static FT_F26Dot6
Free_Project(EXEC_OP_ FT_Vector * v1,FT_Vector * v2)2164*37da2899SCharles.Forsyth   Free_Project( EXEC_OP_ FT_Vector*  v1,
2165*37da2899SCharles.Forsyth                          FT_Vector*  v2 )
2166*37da2899SCharles.Forsyth   {
2167*37da2899SCharles.Forsyth     return TT_DotFix14( v1->x - v2->x,
2168*37da2899SCharles.Forsyth                         v1->y - v2->y,
2169*37da2899SCharles.Forsyth                         CUR.GS.freeVector.x,
2170*37da2899SCharles.Forsyth                         CUR.GS.freeVector.y );
2171*37da2899SCharles.Forsyth   }
2172*37da2899SCharles.Forsyth 
2173*37da2899SCharles.Forsyth 
2174*37da2899SCharles.Forsyth   /*************************************************************************/
2175*37da2899SCharles.Forsyth   /*                                                                       */
2176*37da2899SCharles.Forsyth   /* <Function>                                                            */
2177*37da2899SCharles.Forsyth   /*    Project_x                                                          */
2178*37da2899SCharles.Forsyth   /*                                                                       */
2179*37da2899SCharles.Forsyth   /* <Description>                                                         */
2180*37da2899SCharles.Forsyth   /*    Computes the projection of the vector given by (v2-v1) along the   */
2181*37da2899SCharles.Forsyth   /*    horizontal axis.                                                   */
2182*37da2899SCharles.Forsyth   /*                                                                       */
2183*37da2899SCharles.Forsyth   /* <Input>                                                               */
2184*37da2899SCharles.Forsyth   /*    v1 :: First input vector.                                          */
2185*37da2899SCharles.Forsyth   /*    v2 :: Second input vector.                                         */
2186*37da2899SCharles.Forsyth   /*                                                                       */
2187*37da2899SCharles.Forsyth   /* <Return>                                                              */
2188*37da2899SCharles.Forsyth   /*    The distance in F26dot6 format.                                    */
2189*37da2899SCharles.Forsyth   /*                                                                       */
2190*37da2899SCharles.Forsyth   static FT_F26Dot6
Project_x(EXEC_OP_ FT_Vector * v1,FT_Vector * v2)2191*37da2899SCharles.Forsyth   Project_x( EXEC_OP_ FT_Vector*  v1,
2192*37da2899SCharles.Forsyth                       FT_Vector*  v2 )
2193*37da2899SCharles.Forsyth   {
2194*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
2195*37da2899SCharles.Forsyth 
2196*37da2899SCharles.Forsyth     return ( v1->x - v2->x );
2197*37da2899SCharles.Forsyth   }
2198*37da2899SCharles.Forsyth 
2199*37da2899SCharles.Forsyth 
2200*37da2899SCharles.Forsyth   /*************************************************************************/
2201*37da2899SCharles.Forsyth   /*                                                                       */
2202*37da2899SCharles.Forsyth   /* <Function>                                                            */
2203*37da2899SCharles.Forsyth   /*    Project_y                                                          */
2204*37da2899SCharles.Forsyth   /*                                                                       */
2205*37da2899SCharles.Forsyth   /* <Description>                                                         */
2206*37da2899SCharles.Forsyth   /*    Computes the projection of the vector given by (v2-v1) along the   */
2207*37da2899SCharles.Forsyth   /*    vertical axis.                                                     */
2208*37da2899SCharles.Forsyth   /*                                                                       */
2209*37da2899SCharles.Forsyth   /* <Input>                                                               */
2210*37da2899SCharles.Forsyth   /*    v1 :: First input vector.                                          */
2211*37da2899SCharles.Forsyth   /*    v2 :: Second input vector.                                         */
2212*37da2899SCharles.Forsyth   /*                                                                       */
2213*37da2899SCharles.Forsyth   /* <Return>                                                              */
2214*37da2899SCharles.Forsyth   /*    The distance in F26dot6 format.                                    */
2215*37da2899SCharles.Forsyth   /*                                                                       */
2216*37da2899SCharles.Forsyth   static FT_F26Dot6
Project_y(EXEC_OP_ FT_Vector * v1,FT_Vector * v2)2217*37da2899SCharles.Forsyth   Project_y( EXEC_OP_ FT_Vector*  v1,
2218*37da2899SCharles.Forsyth                       FT_Vector*  v2 )
2219*37da2899SCharles.Forsyth   {
2220*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
2221*37da2899SCharles.Forsyth 
2222*37da2899SCharles.Forsyth    return ( v1->y - v2->y );
2223*37da2899SCharles.Forsyth   }
2224*37da2899SCharles.Forsyth 
2225*37da2899SCharles.Forsyth 
2226*37da2899SCharles.Forsyth   /*************************************************************************/
2227*37da2899SCharles.Forsyth   /*                                                                       */
2228*37da2899SCharles.Forsyth   /* <Function>                                                            */
2229*37da2899SCharles.Forsyth   /*    Compute_Funcs                                                      */
2230*37da2899SCharles.Forsyth   /*                                                                       */
2231*37da2899SCharles.Forsyth   /* <Description>                                                         */
2232*37da2899SCharles.Forsyth   /*    Computes the projection and movement function pointers according   */
2233*37da2899SCharles.Forsyth   /*    to the current graphics state.                                     */
2234*37da2899SCharles.Forsyth   /*                                                                       */
2235*37da2899SCharles.Forsyth   static void
Compute_Funcs(EXEC_OP)2236*37da2899SCharles.Forsyth   Compute_Funcs( EXEC_OP )
2237*37da2899SCharles.Forsyth   {
2238*37da2899SCharles.Forsyth     if ( CUR.GS.freeVector.x == 0x4000 )
2239*37da2899SCharles.Forsyth     {
2240*37da2899SCharles.Forsyth       CUR.func_freeProj = (TT_Project_Func)Project_x;
2241*37da2899SCharles.Forsyth       CUR.F_dot_P       = CUR.GS.projVector.x * 0x10000L;
2242*37da2899SCharles.Forsyth     }
2243*37da2899SCharles.Forsyth     else
2244*37da2899SCharles.Forsyth     {
2245*37da2899SCharles.Forsyth       if ( CUR.GS.freeVector.y == 0x4000 )
2246*37da2899SCharles.Forsyth       {
2247*37da2899SCharles.Forsyth         CUR.func_freeProj = (TT_Project_Func)Project_y;
2248*37da2899SCharles.Forsyth         CUR.F_dot_P       = CUR.GS.projVector.y * 0x10000L;
2249*37da2899SCharles.Forsyth       }
2250*37da2899SCharles.Forsyth       else
2251*37da2899SCharles.Forsyth       {
2252*37da2899SCharles.Forsyth         CUR.func_freeProj = (TT_Project_Func)Free_Project;
2253*37da2899SCharles.Forsyth         CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
2254*37da2899SCharles.Forsyth                       (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
2255*37da2899SCharles.Forsyth       }
2256*37da2899SCharles.Forsyth     }
2257*37da2899SCharles.Forsyth 
2258*37da2899SCharles.Forsyth     if ( CUR.GS.projVector.x == 0x4000 )
2259*37da2899SCharles.Forsyth       CUR.func_project = (TT_Project_Func)Project_x;
2260*37da2899SCharles.Forsyth     else
2261*37da2899SCharles.Forsyth     {
2262*37da2899SCharles.Forsyth       if ( CUR.GS.projVector.y == 0x4000 )
2263*37da2899SCharles.Forsyth         CUR.func_project = (TT_Project_Func)Project_y;
2264*37da2899SCharles.Forsyth       else
2265*37da2899SCharles.Forsyth         CUR.func_project = (TT_Project_Func)Project;
2266*37da2899SCharles.Forsyth     }
2267*37da2899SCharles.Forsyth 
2268*37da2899SCharles.Forsyth     if ( CUR.GS.dualVector.x == 0x4000 )
2269*37da2899SCharles.Forsyth       CUR.func_dualproj = (TT_Project_Func)Project_x;
2270*37da2899SCharles.Forsyth     else
2271*37da2899SCharles.Forsyth     {
2272*37da2899SCharles.Forsyth       if ( CUR.GS.dualVector.y == 0x4000 )
2273*37da2899SCharles.Forsyth         CUR.func_dualproj = (TT_Project_Func)Project_y;
2274*37da2899SCharles.Forsyth       else
2275*37da2899SCharles.Forsyth         CUR.func_dualproj = (TT_Project_Func)Dual_Project;
2276*37da2899SCharles.Forsyth     }
2277*37da2899SCharles.Forsyth 
2278*37da2899SCharles.Forsyth     CUR.func_move = (TT_Move_Func)Direct_Move;
2279*37da2899SCharles.Forsyth 
2280*37da2899SCharles.Forsyth     if ( CUR.F_dot_P == 0x40000000L )
2281*37da2899SCharles.Forsyth     {
2282*37da2899SCharles.Forsyth       if ( CUR.GS.freeVector.x == 0x4000 )
2283*37da2899SCharles.Forsyth         CUR.func_move = (TT_Move_Func)Direct_Move_X;
2284*37da2899SCharles.Forsyth       else
2285*37da2899SCharles.Forsyth       {
2286*37da2899SCharles.Forsyth         if ( CUR.GS.freeVector.y == 0x4000 )
2287*37da2899SCharles.Forsyth           CUR.func_move = (TT_Move_Func)Direct_Move_Y;
2288*37da2899SCharles.Forsyth       }
2289*37da2899SCharles.Forsyth     }
2290*37da2899SCharles.Forsyth 
2291*37da2899SCharles.Forsyth     /* at small sizes, F_dot_P can become too small, resulting   */
2292*37da2899SCharles.Forsyth     /* in overflows and `spikes' in a number of glyphs like `w'. */
2293*37da2899SCharles.Forsyth 
2294*37da2899SCharles.Forsyth     if ( ABS( CUR.F_dot_P ) < 0x4000000L )
2295*37da2899SCharles.Forsyth       CUR.F_dot_P = 0x40000000L;
2296*37da2899SCharles.Forsyth 
2297*37da2899SCharles.Forsyth     /* Disable cached aspect ratio */
2298*37da2899SCharles.Forsyth     CUR.tt_metrics.ratio = 0;
2299*37da2899SCharles.Forsyth   }
2300*37da2899SCharles.Forsyth 
2301*37da2899SCharles.Forsyth 
2302*37da2899SCharles.Forsyth   /*************************************************************************/
2303*37da2899SCharles.Forsyth   /*                                                                       */
2304*37da2899SCharles.Forsyth   /* <Function>                                                            */
2305*37da2899SCharles.Forsyth   /*    Normalize                                                          */
2306*37da2899SCharles.Forsyth   /*                                                                       */
2307*37da2899SCharles.Forsyth   /* <Description>                                                         */
2308*37da2899SCharles.Forsyth   /*    Norms a vector.                                                    */
2309*37da2899SCharles.Forsyth   /*                                                                       */
2310*37da2899SCharles.Forsyth   /* <Input>                                                               */
2311*37da2899SCharles.Forsyth   /*    Vx :: The horizontal input vector coordinate.                      */
2312*37da2899SCharles.Forsyth   /*    Vy :: The vertical input vector coordinate.                        */
2313*37da2899SCharles.Forsyth   /*                                                                       */
2314*37da2899SCharles.Forsyth   /* <Output>                                                              */
2315*37da2899SCharles.Forsyth   /*    R  :: The normed unit vector.                                      */
2316*37da2899SCharles.Forsyth   /*                                                                       */
2317*37da2899SCharles.Forsyth   /* <Return>                                                              */
2318*37da2899SCharles.Forsyth   /*    Returns FAILURE if a vector parameter is zero.                     */
2319*37da2899SCharles.Forsyth   /*                                                                       */
2320*37da2899SCharles.Forsyth   /* <Note>                                                                */
2321*37da2899SCharles.Forsyth   /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
2322*37da2899SCharles.Forsyth   /*    R is undefined.                                                    */
2323*37da2899SCharles.Forsyth   /*                                                                       */
2324*37da2899SCharles.Forsyth 
2325*37da2899SCharles.Forsyth 
2326*37da2899SCharles.Forsyth   static FT_Bool
Normalize(EXEC_OP_ FT_F26Dot6 Vx,FT_F26Dot6 Vy,FT_UnitVector * R)2327*37da2899SCharles.Forsyth   Normalize( EXEC_OP_ FT_F26Dot6      Vx,
2328*37da2899SCharles.Forsyth                       FT_F26Dot6      Vy,
2329*37da2899SCharles.Forsyth                       FT_UnitVector*  R )
2330*37da2899SCharles.Forsyth   {
2331*37da2899SCharles.Forsyth     FT_F26Dot6  W;
2332*37da2899SCharles.Forsyth     FT_Bool     S1, S2;
2333*37da2899SCharles.Forsyth 
2334*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
2335*37da2899SCharles.Forsyth 
2336*37da2899SCharles.Forsyth 
2337*37da2899SCharles.Forsyth     if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L )
2338*37da2899SCharles.Forsyth     {
2339*37da2899SCharles.Forsyth       Vx *= 0x100;
2340*37da2899SCharles.Forsyth       Vy *= 0x100;
2341*37da2899SCharles.Forsyth 
2342*37da2899SCharles.Forsyth       W = TT_VecLen( Vx, Vy );
2343*37da2899SCharles.Forsyth 
2344*37da2899SCharles.Forsyth       if ( W == 0 )
2345*37da2899SCharles.Forsyth       {
2346*37da2899SCharles.Forsyth         /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
2347*37da2899SCharles.Forsyth         /*      to normalize the vector (0,0).  Return immediately. */
2348*37da2899SCharles.Forsyth         return SUCCESS;
2349*37da2899SCharles.Forsyth       }
2350*37da2899SCharles.Forsyth 
2351*37da2899SCharles.Forsyth       R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
2352*37da2899SCharles.Forsyth       R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
2353*37da2899SCharles.Forsyth 
2354*37da2899SCharles.Forsyth       return SUCCESS;
2355*37da2899SCharles.Forsyth     }
2356*37da2899SCharles.Forsyth 
2357*37da2899SCharles.Forsyth     W = TT_VecLen( Vx, Vy );
2358*37da2899SCharles.Forsyth 
2359*37da2899SCharles.Forsyth     Vx = FT_MulDiv( Vx, 0x4000L, W );
2360*37da2899SCharles.Forsyth     Vy = FT_MulDiv( Vy, 0x4000L, W );
2361*37da2899SCharles.Forsyth 
2362*37da2899SCharles.Forsyth     W = Vx * Vx + Vy * Vy;
2363*37da2899SCharles.Forsyth 
2364*37da2899SCharles.Forsyth     /* Now, we want that Sqrt( W ) = 0x4000 */
2365*37da2899SCharles.Forsyth     /* Or 0x1000000 <= W < 0x1004000        */
2366*37da2899SCharles.Forsyth 
2367*37da2899SCharles.Forsyth     if ( Vx < 0 )
2368*37da2899SCharles.Forsyth     {
2369*37da2899SCharles.Forsyth       Vx = -Vx;
2370*37da2899SCharles.Forsyth       S1 = TRUE;
2371*37da2899SCharles.Forsyth     }
2372*37da2899SCharles.Forsyth     else
2373*37da2899SCharles.Forsyth       S1 = FALSE;
2374*37da2899SCharles.Forsyth 
2375*37da2899SCharles.Forsyth     if ( Vy < 0 )
2376*37da2899SCharles.Forsyth     {
2377*37da2899SCharles.Forsyth       Vy = -Vy;
2378*37da2899SCharles.Forsyth       S2 = TRUE;
2379*37da2899SCharles.Forsyth     }
2380*37da2899SCharles.Forsyth     else
2381*37da2899SCharles.Forsyth       S2 = FALSE;
2382*37da2899SCharles.Forsyth 
2383*37da2899SCharles.Forsyth     while ( W < 0x1000000L )
2384*37da2899SCharles.Forsyth     {
2385*37da2899SCharles.Forsyth       /* We need to increase W by a minimal amount */
2386*37da2899SCharles.Forsyth       if ( Vx < Vy )
2387*37da2899SCharles.Forsyth         Vx++;
2388*37da2899SCharles.Forsyth       else
2389*37da2899SCharles.Forsyth         Vy++;
2390*37da2899SCharles.Forsyth 
2391*37da2899SCharles.Forsyth       W = Vx * Vx + Vy * Vy;
2392*37da2899SCharles.Forsyth     }
2393*37da2899SCharles.Forsyth 
2394*37da2899SCharles.Forsyth     while ( W >= 0x1004000L )
2395*37da2899SCharles.Forsyth     {
2396*37da2899SCharles.Forsyth       /* We need to decrease W by a minimal amount */
2397*37da2899SCharles.Forsyth       if ( Vx < Vy )
2398*37da2899SCharles.Forsyth         Vx--;
2399*37da2899SCharles.Forsyth       else
2400*37da2899SCharles.Forsyth         Vy--;
2401*37da2899SCharles.Forsyth 
2402*37da2899SCharles.Forsyth       W = Vx * Vx + Vy * Vy;
2403*37da2899SCharles.Forsyth     }
2404*37da2899SCharles.Forsyth 
2405*37da2899SCharles.Forsyth     /* Note that in various cases, we can only  */
2406*37da2899SCharles.Forsyth     /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
2407*37da2899SCharles.Forsyth 
2408*37da2899SCharles.Forsyth     if ( S1 )
2409*37da2899SCharles.Forsyth       Vx = -Vx;
2410*37da2899SCharles.Forsyth 
2411*37da2899SCharles.Forsyth     if ( S2 )
2412*37da2899SCharles.Forsyth       Vy = -Vy;
2413*37da2899SCharles.Forsyth 
2414*37da2899SCharles.Forsyth     R->x = (FT_F2Dot14)Vx;   /* Type conversion */
2415*37da2899SCharles.Forsyth     R->y = (FT_F2Dot14)Vy;   /* Type conversion */
2416*37da2899SCharles.Forsyth 
2417*37da2899SCharles.Forsyth     return SUCCESS;
2418*37da2899SCharles.Forsyth   }
2419*37da2899SCharles.Forsyth 
2420*37da2899SCharles.Forsyth 
2421*37da2899SCharles.Forsyth   /*************************************************************************/
2422*37da2899SCharles.Forsyth   /*                                                                       */
2423*37da2899SCharles.Forsyth   /* Here we start with the implementation of the various opcodes.         */
2424*37da2899SCharles.Forsyth   /*                                                                       */
2425*37da2899SCharles.Forsyth   /*************************************************************************/
2426*37da2899SCharles.Forsyth 
2427*37da2899SCharles.Forsyth 
2428*37da2899SCharles.Forsyth   static FT_Bool
Ins_SxVTL(EXEC_OP_ FT_UShort aIdx1,FT_UShort aIdx2,FT_Int aOpc,FT_UnitVector * Vec)2429*37da2899SCharles.Forsyth   Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,
2430*37da2899SCharles.Forsyth                       FT_UShort       aIdx2,
2431*37da2899SCharles.Forsyth                       FT_Int          aOpc,
2432*37da2899SCharles.Forsyth                       FT_UnitVector*  Vec )
2433*37da2899SCharles.Forsyth   {
2434*37da2899SCharles.Forsyth     FT_Long     A, B, C;
2435*37da2899SCharles.Forsyth     FT_Vector*  p1;
2436*37da2899SCharles.Forsyth     FT_Vector*  p2;
2437*37da2899SCharles.Forsyth 
2438*37da2899SCharles.Forsyth 
2439*37da2899SCharles.Forsyth     if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
2440*37da2899SCharles.Forsyth          BOUNDS( aIdx2, CUR.zp1.n_points ) )
2441*37da2899SCharles.Forsyth     {
2442*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
2443*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
2444*37da2899SCharles.Forsyth       return FAILURE;
2445*37da2899SCharles.Forsyth     }
2446*37da2899SCharles.Forsyth 
2447*37da2899SCharles.Forsyth     p1 = CUR.zp1.cur + aIdx2;
2448*37da2899SCharles.Forsyth     p2 = CUR.zp2.cur + aIdx1;
2449*37da2899SCharles.Forsyth 
2450*37da2899SCharles.Forsyth     A = p1->x - p2->x;
2451*37da2899SCharles.Forsyth     B = p1->y - p2->y;
2452*37da2899SCharles.Forsyth 
2453*37da2899SCharles.Forsyth     if ( ( aOpc & 1 ) != 0 )
2454*37da2899SCharles.Forsyth     {
2455*37da2899SCharles.Forsyth       C =  B;   /* counter clockwise rotation */
2456*37da2899SCharles.Forsyth       B =  A;
2457*37da2899SCharles.Forsyth       A = -C;
2458*37da2899SCharles.Forsyth     }
2459*37da2899SCharles.Forsyth 
2460*37da2899SCharles.Forsyth     NORMalize( A, B, Vec );
2461*37da2899SCharles.Forsyth 
2462*37da2899SCharles.Forsyth     return SUCCESS;
2463*37da2899SCharles.Forsyth   }
2464*37da2899SCharles.Forsyth 
2465*37da2899SCharles.Forsyth 
2466*37da2899SCharles.Forsyth   /* When not using the big switch statements, the interpreter uses a */
2467*37da2899SCharles.Forsyth   /* call table defined later below in this source.  Each opcode must */
2468*37da2899SCharles.Forsyth   /* thus have a corresponding function, even trivial ones.           */
2469*37da2899SCharles.Forsyth   /*                                                                  */
2470*37da2899SCharles.Forsyth   /* They are all defined there.                                      */
2471*37da2899SCharles.Forsyth 
2472*37da2899SCharles.Forsyth #define DO_SVTCA                            \
2473*37da2899SCharles.Forsyth   {                                         \
2474*37da2899SCharles.Forsyth     FT_Short  A, B;                         \
2475*37da2899SCharles.Forsyth                                             \
2476*37da2899SCharles.Forsyth                                             \
2477*37da2899SCharles.Forsyth     A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2478*37da2899SCharles.Forsyth     B = A ^ (FT_Short)0x4000;               \
2479*37da2899SCharles.Forsyth                                             \
2480*37da2899SCharles.Forsyth     CUR.GS.freeVector.x = A;                \
2481*37da2899SCharles.Forsyth     CUR.GS.projVector.x = A;                \
2482*37da2899SCharles.Forsyth     CUR.GS.dualVector.x = A;                \
2483*37da2899SCharles.Forsyth                                             \
2484*37da2899SCharles.Forsyth     CUR.GS.freeVector.y = B;                \
2485*37da2899SCharles.Forsyth     CUR.GS.projVector.y = B;                \
2486*37da2899SCharles.Forsyth     CUR.GS.dualVector.y = B;                \
2487*37da2899SCharles.Forsyth                                             \
2488*37da2899SCharles.Forsyth     COMPUTE_Funcs();                        \
2489*37da2899SCharles.Forsyth   }
2490*37da2899SCharles.Forsyth 
2491*37da2899SCharles.Forsyth 
2492*37da2899SCharles.Forsyth #define DO_SPVTCA                           \
2493*37da2899SCharles.Forsyth   {                                         \
2494*37da2899SCharles.Forsyth     FT_Short  A, B;                         \
2495*37da2899SCharles.Forsyth                                             \
2496*37da2899SCharles.Forsyth                                             \
2497*37da2899SCharles.Forsyth     A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2498*37da2899SCharles.Forsyth     B = A ^ (FT_Short)0x4000;               \
2499*37da2899SCharles.Forsyth                                             \
2500*37da2899SCharles.Forsyth     CUR.GS.projVector.x = A;                \
2501*37da2899SCharles.Forsyth     CUR.GS.dualVector.x = A;                \
2502*37da2899SCharles.Forsyth                                             \
2503*37da2899SCharles.Forsyth     CUR.GS.projVector.y = B;                \
2504*37da2899SCharles.Forsyth     CUR.GS.dualVector.y = B;                \
2505*37da2899SCharles.Forsyth                                             \
2506*37da2899SCharles.Forsyth     COMPUTE_Funcs();                        \
2507*37da2899SCharles.Forsyth   }
2508*37da2899SCharles.Forsyth 
2509*37da2899SCharles.Forsyth 
2510*37da2899SCharles.Forsyth #define DO_SFVTCA                           \
2511*37da2899SCharles.Forsyth   {                                         \
2512*37da2899SCharles.Forsyth     FT_Short  A, B;                         \
2513*37da2899SCharles.Forsyth                                             \
2514*37da2899SCharles.Forsyth                                             \
2515*37da2899SCharles.Forsyth     A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2516*37da2899SCharles.Forsyth     B = A ^ (FT_Short)0x4000;               \
2517*37da2899SCharles.Forsyth                                             \
2518*37da2899SCharles.Forsyth     CUR.GS.freeVector.x = A;                \
2519*37da2899SCharles.Forsyth     CUR.GS.freeVector.y = B;                \
2520*37da2899SCharles.Forsyth                                             \
2521*37da2899SCharles.Forsyth     COMPUTE_Funcs();                        \
2522*37da2899SCharles.Forsyth   }
2523*37da2899SCharles.Forsyth 
2524*37da2899SCharles.Forsyth 
2525*37da2899SCharles.Forsyth #define DO_SPVTL                                      \
2526*37da2899SCharles.Forsyth     if ( INS_SxVTL( (FT_UShort)args[1],               \
2527*37da2899SCharles.Forsyth                     (FT_UShort)args[0],               \
2528*37da2899SCharles.Forsyth                     CUR.opcode,                       \
2529*37da2899SCharles.Forsyth                     &CUR.GS.projVector ) == SUCCESS ) \
2530*37da2899SCharles.Forsyth     {                                                 \
2531*37da2899SCharles.Forsyth       CUR.GS.dualVector = CUR.GS.projVector;          \
2532*37da2899SCharles.Forsyth       COMPUTE_Funcs();                                \
2533*37da2899SCharles.Forsyth     }
2534*37da2899SCharles.Forsyth 
2535*37da2899SCharles.Forsyth 
2536*37da2899SCharles.Forsyth #define DO_SFVTL                                      \
2537*37da2899SCharles.Forsyth     if ( INS_SxVTL( (FT_UShort)args[1],               \
2538*37da2899SCharles.Forsyth                     (FT_UShort)args[0],               \
2539*37da2899SCharles.Forsyth                     CUR.opcode,                       \
2540*37da2899SCharles.Forsyth                     &CUR.GS.freeVector ) == SUCCESS ) \
2541*37da2899SCharles.Forsyth       COMPUTE_Funcs();
2542*37da2899SCharles.Forsyth 
2543*37da2899SCharles.Forsyth 
2544*37da2899SCharles.Forsyth #define DO_SFVTPV                          \
2545*37da2899SCharles.Forsyth     CUR.GS.freeVector = CUR.GS.projVector; \
2546*37da2899SCharles.Forsyth     COMPUTE_Funcs();
2547*37da2899SCharles.Forsyth 
2548*37da2899SCharles.Forsyth 
2549*37da2899SCharles.Forsyth #define DO_SPVFS                                \
2550*37da2899SCharles.Forsyth   {                                             \
2551*37da2899SCharles.Forsyth     FT_Short  S;                                \
2552*37da2899SCharles.Forsyth     FT_Long   X, Y;                             \
2553*37da2899SCharles.Forsyth                                                 \
2554*37da2899SCharles.Forsyth                                                 \
2555*37da2899SCharles.Forsyth     /* Only use low 16bits, then sign extend */ \
2556*37da2899SCharles.Forsyth     S = (FT_Short)args[1];                      \
2557*37da2899SCharles.Forsyth     Y = (FT_Long)S;                             \
2558*37da2899SCharles.Forsyth     S = (FT_Short)args[0];                      \
2559*37da2899SCharles.Forsyth     X = (FT_Long)S;                             \
2560*37da2899SCharles.Forsyth                                                 \
2561*37da2899SCharles.Forsyth     NORMalize( X, Y, &CUR.GS.projVector );      \
2562*37da2899SCharles.Forsyth                                                 \
2563*37da2899SCharles.Forsyth     CUR.GS.dualVector = CUR.GS.projVector;      \
2564*37da2899SCharles.Forsyth     COMPUTE_Funcs();                            \
2565*37da2899SCharles.Forsyth   }
2566*37da2899SCharles.Forsyth 
2567*37da2899SCharles.Forsyth 
2568*37da2899SCharles.Forsyth #define DO_SFVFS                                \
2569*37da2899SCharles.Forsyth   {                                             \
2570*37da2899SCharles.Forsyth     FT_Short  S;                                \
2571*37da2899SCharles.Forsyth     FT_Long   X, Y;                             \
2572*37da2899SCharles.Forsyth                                                 \
2573*37da2899SCharles.Forsyth                                                 \
2574*37da2899SCharles.Forsyth     /* Only use low 16bits, then sign extend */ \
2575*37da2899SCharles.Forsyth     S = (FT_Short)args[1];                      \
2576*37da2899SCharles.Forsyth     Y = (FT_Long)S;                             \
2577*37da2899SCharles.Forsyth     S = (FT_Short)args[0];                      \
2578*37da2899SCharles.Forsyth     X = S;                                      \
2579*37da2899SCharles.Forsyth                                                 \
2580*37da2899SCharles.Forsyth     NORMalize( X, Y, &CUR.GS.freeVector );      \
2581*37da2899SCharles.Forsyth     COMPUTE_Funcs();                            \
2582*37da2899SCharles.Forsyth   }
2583*37da2899SCharles.Forsyth 
2584*37da2899SCharles.Forsyth 
2585*37da2899SCharles.Forsyth #define DO_GPV                     \
2586*37da2899SCharles.Forsyth     args[0] = CUR.GS.projVector.x; \
2587*37da2899SCharles.Forsyth     args[1] = CUR.GS.projVector.y;
2588*37da2899SCharles.Forsyth 
2589*37da2899SCharles.Forsyth 
2590*37da2899SCharles.Forsyth #define DO_GFV                     \
2591*37da2899SCharles.Forsyth     args[0] = CUR.GS.freeVector.x; \
2592*37da2899SCharles.Forsyth     args[1] = CUR.GS.freeVector.y;
2593*37da2899SCharles.Forsyth 
2594*37da2899SCharles.Forsyth 
2595*37da2899SCharles.Forsyth #define DO_SRP0                      \
2596*37da2899SCharles.Forsyth     CUR.GS.rp0 = (FT_UShort)args[0];
2597*37da2899SCharles.Forsyth 
2598*37da2899SCharles.Forsyth 
2599*37da2899SCharles.Forsyth #define DO_SRP1                      \
2600*37da2899SCharles.Forsyth     CUR.GS.rp1 = (FT_UShort)args[0];
2601*37da2899SCharles.Forsyth 
2602*37da2899SCharles.Forsyth 
2603*37da2899SCharles.Forsyth #define DO_SRP2                      \
2604*37da2899SCharles.Forsyth     CUR.GS.rp2 = (FT_UShort)args[0];
2605*37da2899SCharles.Forsyth 
2606*37da2899SCharles.Forsyth 
2607*37da2899SCharles.Forsyth #define DO_RTHG                                         \
2608*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_To_Half_Grid;         \
2609*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
2610*37da2899SCharles.Forsyth 
2611*37da2899SCharles.Forsyth 
2612*37da2899SCharles.Forsyth #define DO_RTG                                     \
2613*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_To_Grid;         \
2614*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_To_Grid;
2615*37da2899SCharles.Forsyth 
2616*37da2899SCharles.Forsyth 
2617*37da2899SCharles.Forsyth #define DO_RTDG                                           \
2618*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_To_Double_Grid;         \
2619*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
2620*37da2899SCharles.Forsyth 
2621*37da2899SCharles.Forsyth 
2622*37da2899SCharles.Forsyth #define DO_RUTG                                       \
2623*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_Up_To_Grid;         \
2624*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
2625*37da2899SCharles.Forsyth 
2626*37da2899SCharles.Forsyth 
2627*37da2899SCharles.Forsyth #define DO_RDTG                                         \
2628*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_Down_To_Grid;         \
2629*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
2630*37da2899SCharles.Forsyth 
2631*37da2899SCharles.Forsyth 
2632*37da2899SCharles.Forsyth #define DO_ROFF                                 \
2633*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_Off;          \
2634*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_None;
2635*37da2899SCharles.Forsyth 
2636*37da2899SCharles.Forsyth 
2637*37da2899SCharles.Forsyth #define DO_SROUND                                \
2638*37da2899SCharles.Forsyth     SET_SuperRound( 0x4000, args[0] );           \
2639*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_Super;         \
2640*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_Super;
2641*37da2899SCharles.Forsyth 
2642*37da2899SCharles.Forsyth 
2643*37da2899SCharles.Forsyth #define DO_S45ROUND                                 \
2644*37da2899SCharles.Forsyth     SET_SuperRound( 0x2D41, args[0] );              \
2645*37da2899SCharles.Forsyth     CUR.GS.round_state = TT_Round_Super_45;         \
2646*37da2899SCharles.Forsyth     CUR.func_round = (TT_Round_Func)Round_Super_45;
2647*37da2899SCharles.Forsyth 
2648*37da2899SCharles.Forsyth 
2649*37da2899SCharles.Forsyth #define DO_SLOOP                       \
2650*37da2899SCharles.Forsyth     if ( args[0] < 0 )                 \
2651*37da2899SCharles.Forsyth       CUR.error = TT_Err_Bad_Argument; \
2652*37da2899SCharles.Forsyth     else                               \
2653*37da2899SCharles.Forsyth       CUR.GS.loop = args[0];
2654*37da2899SCharles.Forsyth 
2655*37da2899SCharles.Forsyth 
2656*37da2899SCharles.Forsyth #define DO_SMD                         \
2657*37da2899SCharles.Forsyth     CUR.GS.minimum_distance = args[0];
2658*37da2899SCharles.Forsyth 
2659*37da2899SCharles.Forsyth 
2660*37da2899SCharles.Forsyth #define DO_SCVTCI                                     \
2661*37da2899SCharles.Forsyth     CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
2662*37da2899SCharles.Forsyth 
2663*37da2899SCharles.Forsyth 
2664*37da2899SCharles.Forsyth #define DO_SSWCI                                     \
2665*37da2899SCharles.Forsyth     CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
2666*37da2899SCharles.Forsyth 
2667*37da2899SCharles.Forsyth 
2668*37da2899SCharles.Forsyth     /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
2669*37da2899SCharles.Forsyth     /*                                                  */
2670*37da2899SCharles.Forsyth     /* It seems that the value that is read here is     */
2671*37da2899SCharles.Forsyth     /* expressed in 16.16 format rather than in font    */
2672*37da2899SCharles.Forsyth     /* units.                                           */
2673*37da2899SCharles.Forsyth     /*                                                  */
2674*37da2899SCharles.Forsyth #define DO_SSW                                                 \
2675*37da2899SCharles.Forsyth     CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
2676*37da2899SCharles.Forsyth 
2677*37da2899SCharles.Forsyth 
2678*37da2899SCharles.Forsyth #define DO_FLIPON            \
2679*37da2899SCharles.Forsyth     CUR.GS.auto_flip = TRUE;
2680*37da2899SCharles.Forsyth 
2681*37da2899SCharles.Forsyth 
2682*37da2899SCharles.Forsyth #define DO_FLIPOFF            \
2683*37da2899SCharles.Forsyth     CUR.GS.auto_flip = FALSE;
2684*37da2899SCharles.Forsyth 
2685*37da2899SCharles.Forsyth 
2686*37da2899SCharles.Forsyth #define DO_SDB                             \
2687*37da2899SCharles.Forsyth     CUR.GS.delta_base = (FT_Short)args[0];
2688*37da2899SCharles.Forsyth 
2689*37da2899SCharles.Forsyth 
2690*37da2899SCharles.Forsyth #define DO_SDS                              \
2691*37da2899SCharles.Forsyth     CUR.GS.delta_shift = (FT_Short)args[0];
2692*37da2899SCharles.Forsyth 
2693*37da2899SCharles.Forsyth 
2694*37da2899SCharles.Forsyth #define DO_MD  /* nothing */
2695*37da2899SCharles.Forsyth 
2696*37da2899SCharles.Forsyth 
2697*37da2899SCharles.Forsyth #define DO_MPPEM              \
2698*37da2899SCharles.Forsyth     args[0] = CURRENT_Ppem();
2699*37da2899SCharles.Forsyth 
2700*37da2899SCharles.Forsyth 
2701*37da2899SCharles.Forsyth   /* Note: The pointSize should be irrelevant in a given font program; */
2702*37da2899SCharles.Forsyth   /*       we thus decide to return only the ppem.                     */
2703*37da2899SCharles.Forsyth #if 0
2704*37da2899SCharles.Forsyth 
2705*37da2899SCharles.Forsyth #define DO_MPS                       \
2706*37da2899SCharles.Forsyth     args[0] = CUR.metrics.pointSize;
2707*37da2899SCharles.Forsyth 
2708*37da2899SCharles.Forsyth #else
2709*37da2899SCharles.Forsyth 
2710*37da2899SCharles.Forsyth #define DO_MPS                \
2711*37da2899SCharles.Forsyth     args[0] = CURRENT_Ppem();
2712*37da2899SCharles.Forsyth 
2713*37da2899SCharles.Forsyth #endif /* 0 */
2714*37da2899SCharles.Forsyth 
2715*37da2899SCharles.Forsyth 
2716*37da2899SCharles.Forsyth #define DO_DUP         \
2717*37da2899SCharles.Forsyth     args[1] = args[0];
2718*37da2899SCharles.Forsyth 
2719*37da2899SCharles.Forsyth 
2720*37da2899SCharles.Forsyth #define DO_CLEAR     \
2721*37da2899SCharles.Forsyth     CUR.new_top = 0;
2722*37da2899SCharles.Forsyth 
2723*37da2899SCharles.Forsyth 
2724*37da2899SCharles.Forsyth #define DO_SWAP        \
2725*37da2899SCharles.Forsyth   {                    \
2726*37da2899SCharles.Forsyth     FT_Long  L;        \
2727*37da2899SCharles.Forsyth                        \
2728*37da2899SCharles.Forsyth                        \
2729*37da2899SCharles.Forsyth     L       = args[0]; \
2730*37da2899SCharles.Forsyth     args[0] = args[1]; \
2731*37da2899SCharles.Forsyth     args[1] = L;       \
2732*37da2899SCharles.Forsyth   }
2733*37da2899SCharles.Forsyth 
2734*37da2899SCharles.Forsyth 
2735*37da2899SCharles.Forsyth #define DO_DEPTH       \
2736*37da2899SCharles.Forsyth     args[0] = CUR.top;
2737*37da2899SCharles.Forsyth 
2738*37da2899SCharles.Forsyth 
2739*37da2899SCharles.Forsyth #define DO_CINDEX                           \
2740*37da2899SCharles.Forsyth   {                                         \
2741*37da2899SCharles.Forsyth     FT_Long  L;                             \
2742*37da2899SCharles.Forsyth                                             \
2743*37da2899SCharles.Forsyth                                             \
2744*37da2899SCharles.Forsyth     L = args[0];                            \
2745*37da2899SCharles.Forsyth                                             \
2746*37da2899SCharles.Forsyth     if ( L <= 0 || L > CUR.args )           \
2747*37da2899SCharles.Forsyth       CUR.error = TT_Err_Invalid_Reference; \
2748*37da2899SCharles.Forsyth     else                                    \
2749*37da2899SCharles.Forsyth       args[0] = CUR.stack[CUR.args - L];    \
2750*37da2899SCharles.Forsyth   }
2751*37da2899SCharles.Forsyth 
2752*37da2899SCharles.Forsyth 
2753*37da2899SCharles.Forsyth #define DO_JROT               \
2754*37da2899SCharles.Forsyth     if ( args[1] != 0 )       \
2755*37da2899SCharles.Forsyth     {                         \
2756*37da2899SCharles.Forsyth       CUR.IP      += args[0]; \
2757*37da2899SCharles.Forsyth       CUR.step_ins = FALSE;   \
2758*37da2899SCharles.Forsyth     }
2759*37da2899SCharles.Forsyth 
2760*37da2899SCharles.Forsyth 
2761*37da2899SCharles.Forsyth #define DO_JMPR             \
2762*37da2899SCharles.Forsyth     CUR.IP      += args[0]; \
2763*37da2899SCharles.Forsyth     CUR.step_ins = FALSE;
2764*37da2899SCharles.Forsyth 
2765*37da2899SCharles.Forsyth 
2766*37da2899SCharles.Forsyth #define DO_JROF               \
2767*37da2899SCharles.Forsyth     if ( args[1] == 0 )       \
2768*37da2899SCharles.Forsyth     {                         \
2769*37da2899SCharles.Forsyth       CUR.IP      += args[0]; \
2770*37da2899SCharles.Forsyth       CUR.step_ins = FALSE;   \
2771*37da2899SCharles.Forsyth     }
2772*37da2899SCharles.Forsyth 
2773*37da2899SCharles.Forsyth 
2774*37da2899SCharles.Forsyth #define DO_LT                        \
2775*37da2899SCharles.Forsyth     args[0] = ( args[0] < args[1] );
2776*37da2899SCharles.Forsyth 
2777*37da2899SCharles.Forsyth 
2778*37da2899SCharles.Forsyth #define DO_LTEQ                       \
2779*37da2899SCharles.Forsyth     args[0] = ( args[0] <= args[1] );
2780*37da2899SCharles.Forsyth 
2781*37da2899SCharles.Forsyth 
2782*37da2899SCharles.Forsyth #define DO_GT                        \
2783*37da2899SCharles.Forsyth     args[0] = ( args[0] > args[1] );
2784*37da2899SCharles.Forsyth 
2785*37da2899SCharles.Forsyth 
2786*37da2899SCharles.Forsyth #define DO_GTEQ                       \
2787*37da2899SCharles.Forsyth     args[0] = ( args[0] >= args[1] );
2788*37da2899SCharles.Forsyth 
2789*37da2899SCharles.Forsyth 
2790*37da2899SCharles.Forsyth #define DO_EQ                         \
2791*37da2899SCharles.Forsyth     args[0] = ( args[0] == args[1] );
2792*37da2899SCharles.Forsyth 
2793*37da2899SCharles.Forsyth 
2794*37da2899SCharles.Forsyth #define DO_NEQ                        \
2795*37da2899SCharles.Forsyth     args[0] = ( args[0] != args[1] );
2796*37da2899SCharles.Forsyth 
2797*37da2899SCharles.Forsyth 
2798*37da2899SCharles.Forsyth #define DO_ODD                                                  \
2799*37da2899SCharles.Forsyth     args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
2800*37da2899SCharles.Forsyth 
2801*37da2899SCharles.Forsyth 
2802*37da2899SCharles.Forsyth #define DO_EVEN                                                \
2803*37da2899SCharles.Forsyth     args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
2804*37da2899SCharles.Forsyth 
2805*37da2899SCharles.Forsyth 
2806*37da2899SCharles.Forsyth #define DO_AND                        \
2807*37da2899SCharles.Forsyth     args[0] = ( args[0] && args[1] );
2808*37da2899SCharles.Forsyth 
2809*37da2899SCharles.Forsyth 
2810*37da2899SCharles.Forsyth #define DO_OR                         \
2811*37da2899SCharles.Forsyth     args[0] = ( args[0] || args[1] );
2812*37da2899SCharles.Forsyth 
2813*37da2899SCharles.Forsyth 
2814*37da2899SCharles.Forsyth #define DO_NOT          \
2815*37da2899SCharles.Forsyth     args[0] = !args[0];
2816*37da2899SCharles.Forsyth 
2817*37da2899SCharles.Forsyth 
2818*37da2899SCharles.Forsyth #define DO_ADD          \
2819*37da2899SCharles.Forsyth     args[0] += args[1];
2820*37da2899SCharles.Forsyth 
2821*37da2899SCharles.Forsyth 
2822*37da2899SCharles.Forsyth #define DO_SUB          \
2823*37da2899SCharles.Forsyth     args[0] -= args[1];
2824*37da2899SCharles.Forsyth 
2825*37da2899SCharles.Forsyth 
2826*37da2899SCharles.Forsyth #define DO_DIV                                      \
2827*37da2899SCharles.Forsyth     if ( args[1] == 0 )                             \
2828*37da2899SCharles.Forsyth       CUR.error = TT_Err_Divide_By_Zero;            \
2829*37da2899SCharles.Forsyth     else                                            \
2830*37da2899SCharles.Forsyth       args[0] = TT_MULDIV( args[0], 64L, args[1] );
2831*37da2899SCharles.Forsyth 
2832*37da2899SCharles.Forsyth 
2833*37da2899SCharles.Forsyth #define DO_MUL                                    \
2834*37da2899SCharles.Forsyth     args[0] = TT_MULDIV( args[0], args[1], 64L );
2835*37da2899SCharles.Forsyth 
2836*37da2899SCharles.Forsyth 
2837*37da2899SCharles.Forsyth #define DO_ABS                \
2838*37da2899SCharles.Forsyth     args[0] = ABS( args[0] );
2839*37da2899SCharles.Forsyth 
2840*37da2899SCharles.Forsyth 
2841*37da2899SCharles.Forsyth #define DO_NEG          \
2842*37da2899SCharles.Forsyth     args[0] = -args[0];
2843*37da2899SCharles.Forsyth 
2844*37da2899SCharles.Forsyth 
2845*37da2899SCharles.Forsyth #define DO_FLOOR    \
2846*37da2899SCharles.Forsyth     args[0] &= -64;
2847*37da2899SCharles.Forsyth 
2848*37da2899SCharles.Forsyth 
2849*37da2899SCharles.Forsyth #define DO_CEILING                    \
2850*37da2899SCharles.Forsyth     args[0] = ( args[0] + 63 ) & -64;
2851*37da2899SCharles.Forsyth 
2852*37da2899SCharles.Forsyth 
2853*37da2899SCharles.Forsyth #define DO_RS                          \
2854*37da2899SCharles.Forsyth    {                                   \
2855*37da2899SCharles.Forsyth      FT_ULong  I = (FT_ULong)args[0];  \
2856*37da2899SCharles.Forsyth                                        \
2857*37da2899SCharles.Forsyth                                        \
2858*37da2899SCharles.Forsyth      if ( BOUNDS( I, CUR.storeSize ) ) \
2859*37da2899SCharles.Forsyth      {                                 \
2860*37da2899SCharles.Forsyth        if ( CUR.pedantic_hinting )     \
2861*37da2899SCharles.Forsyth        {                               \
2862*37da2899SCharles.Forsyth          ARRAY_BOUND_ERROR;            \
2863*37da2899SCharles.Forsyth        }                               \
2864*37da2899SCharles.Forsyth        else                            \
2865*37da2899SCharles.Forsyth          args[0] = 0;                  \
2866*37da2899SCharles.Forsyth      }                                 \
2867*37da2899SCharles.Forsyth      else                              \
2868*37da2899SCharles.Forsyth        args[0] = CUR.storage[I];       \
2869*37da2899SCharles.Forsyth    }
2870*37da2899SCharles.Forsyth 
2871*37da2899SCharles.Forsyth 
2872*37da2899SCharles.Forsyth #define DO_WS                          \
2873*37da2899SCharles.Forsyth    {                                   \
2874*37da2899SCharles.Forsyth      FT_ULong  I = (FT_ULong)args[0];  \
2875*37da2899SCharles.Forsyth                                        \
2876*37da2899SCharles.Forsyth                                        \
2877*37da2899SCharles.Forsyth      if ( BOUNDS( I, CUR.storeSize ) ) \
2878*37da2899SCharles.Forsyth      {                                 \
2879*37da2899SCharles.Forsyth        if ( CUR.pedantic_hinting )     \
2880*37da2899SCharles.Forsyth        {                               \
2881*37da2899SCharles.Forsyth          ARRAY_BOUND_ERROR;            \
2882*37da2899SCharles.Forsyth        }                               \
2883*37da2899SCharles.Forsyth      }                                 \
2884*37da2899SCharles.Forsyth      else                              \
2885*37da2899SCharles.Forsyth        CUR.storage[I] = args[1];       \
2886*37da2899SCharles.Forsyth    }
2887*37da2899SCharles.Forsyth 
2888*37da2899SCharles.Forsyth 
2889*37da2899SCharles.Forsyth #define DO_RCVT                          \
2890*37da2899SCharles.Forsyth    {                                     \
2891*37da2899SCharles.Forsyth      FT_ULong  I = (FT_ULong)args[0];    \
2892*37da2899SCharles.Forsyth                                          \
2893*37da2899SCharles.Forsyth                                          \
2894*37da2899SCharles.Forsyth      if ( BOUNDS( I, CUR.cvtSize ) )     \
2895*37da2899SCharles.Forsyth      {                                   \
2896*37da2899SCharles.Forsyth        if ( CUR.pedantic_hinting )       \
2897*37da2899SCharles.Forsyth        {                                 \
2898*37da2899SCharles.Forsyth          ARRAY_BOUND_ERROR;              \
2899*37da2899SCharles.Forsyth        }                                 \
2900*37da2899SCharles.Forsyth        else                              \
2901*37da2899SCharles.Forsyth          args[0] = 0;                    \
2902*37da2899SCharles.Forsyth      }                                   \
2903*37da2899SCharles.Forsyth      else                                \
2904*37da2899SCharles.Forsyth        args[0] = CUR_Func_read_cvt( I ); \
2905*37da2899SCharles.Forsyth    }
2906*37da2899SCharles.Forsyth 
2907*37da2899SCharles.Forsyth 
2908*37da2899SCharles.Forsyth #define DO_WCVTP                         \
2909*37da2899SCharles.Forsyth    {                                     \
2910*37da2899SCharles.Forsyth      FT_ULong  I = (FT_ULong)args[0];    \
2911*37da2899SCharles.Forsyth                                          \
2912*37da2899SCharles.Forsyth                                          \
2913*37da2899SCharles.Forsyth      if ( BOUNDS( I, CUR.cvtSize ) )     \
2914*37da2899SCharles.Forsyth      {                                   \
2915*37da2899SCharles.Forsyth        if ( CUR.pedantic_hinting )       \
2916*37da2899SCharles.Forsyth        {                                 \
2917*37da2899SCharles.Forsyth          ARRAY_BOUND_ERROR;              \
2918*37da2899SCharles.Forsyth        }                                 \
2919*37da2899SCharles.Forsyth      }                                   \
2920*37da2899SCharles.Forsyth      else                                \
2921*37da2899SCharles.Forsyth        CUR_Func_write_cvt( I, args[1] ); \
2922*37da2899SCharles.Forsyth    }
2923*37da2899SCharles.Forsyth 
2924*37da2899SCharles.Forsyth 
2925*37da2899SCharles.Forsyth #define DO_WCVTF                                                \
2926*37da2899SCharles.Forsyth    {                                                            \
2927*37da2899SCharles.Forsyth      FT_ULong  I = (FT_ULong)args[0];                           \
2928*37da2899SCharles.Forsyth                                                                 \
2929*37da2899SCharles.Forsyth                                                                 \
2930*37da2899SCharles.Forsyth      if ( BOUNDS( I, CUR.cvtSize ) )                            \
2931*37da2899SCharles.Forsyth      {                                                          \
2932*37da2899SCharles.Forsyth        if ( CUR.pedantic_hinting )                              \
2933*37da2899SCharles.Forsyth        {                                                        \
2934*37da2899SCharles.Forsyth          ARRAY_BOUND_ERROR;                                     \
2935*37da2899SCharles.Forsyth        }                                                        \
2936*37da2899SCharles.Forsyth      }                                                          \
2937*37da2899SCharles.Forsyth      else                                                       \
2938*37da2899SCharles.Forsyth        CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
2939*37da2899SCharles.Forsyth    }
2940*37da2899SCharles.Forsyth 
2941*37da2899SCharles.Forsyth 
2942*37da2899SCharles.Forsyth #define DO_DEBUG                     \
2943*37da2899SCharles.Forsyth     CUR.error = TT_Err_Debug_OpCode;
2944*37da2899SCharles.Forsyth 
2945*37da2899SCharles.Forsyth 
2946*37da2899SCharles.Forsyth #define DO_ROUND                                                   \
2947*37da2899SCharles.Forsyth     args[0] = CUR_Func_round(                                      \
2948*37da2899SCharles.Forsyth                 args[0],                                           \
2949*37da2899SCharles.Forsyth                 CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
2950*37da2899SCharles.Forsyth 
2951*37da2899SCharles.Forsyth 
2952*37da2899SCharles.Forsyth #define DO_NROUND                                                            \
2953*37da2899SCharles.Forsyth     args[0] = ROUND_None( args[0],                                           \
2954*37da2899SCharles.Forsyth                           CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
2955*37da2899SCharles.Forsyth 
2956*37da2899SCharles.Forsyth 
2957*37da2899SCharles.Forsyth #define DO_MAX               \
2958*37da2899SCharles.Forsyth     if ( args[1] > args[0] ) \
2959*37da2899SCharles.Forsyth       args[0] = args[1];
2960*37da2899SCharles.Forsyth 
2961*37da2899SCharles.Forsyth 
2962*37da2899SCharles.Forsyth #define DO_MIN               \
2963*37da2899SCharles.Forsyth     if ( args[1] < args[0] ) \
2964*37da2899SCharles.Forsyth       args[0] = args[1];
2965*37da2899SCharles.Forsyth 
2966*37da2899SCharles.Forsyth 
2967*37da2899SCharles.Forsyth #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
2968*37da2899SCharles.Forsyth 
2969*37da2899SCharles.Forsyth 
2970*37da2899SCharles.Forsyth #undef  ARRAY_BOUND_ERROR
2971*37da2899SCharles.Forsyth #define ARRAY_BOUND_ERROR                   \
2972*37da2899SCharles.Forsyth     {                                       \
2973*37da2899SCharles.Forsyth       CUR.error = TT_Err_Invalid_Reference; \
2974*37da2899SCharles.Forsyth       return;                               \
2975*37da2899SCharles.Forsyth     }
2976*37da2899SCharles.Forsyth 
2977*37da2899SCharles.Forsyth 
2978*37da2899SCharles.Forsyth   /*************************************************************************/
2979*37da2899SCharles.Forsyth   /*                                                                       */
2980*37da2899SCharles.Forsyth   /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */
2981*37da2899SCharles.Forsyth   /* Opcode range: 0x00-0x01                                               */
2982*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
2983*37da2899SCharles.Forsyth   /*                                                                       */
2984*37da2899SCharles.Forsyth   static void
Ins_SVTCA(INS_ARG)2985*37da2899SCharles.Forsyth   Ins_SVTCA( INS_ARG )
2986*37da2899SCharles.Forsyth   {
2987*37da2899SCharles.Forsyth     DO_SVTCA
2988*37da2899SCharles.Forsyth   }
2989*37da2899SCharles.Forsyth 
2990*37da2899SCharles.Forsyth 
2991*37da2899SCharles.Forsyth   /*************************************************************************/
2992*37da2899SCharles.Forsyth   /*                                                                       */
2993*37da2899SCharles.Forsyth   /* SPVTCA[a]:    Set PVector to Coordinate Axis                          */
2994*37da2899SCharles.Forsyth   /* Opcode range: 0x02-0x03                                               */
2995*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
2996*37da2899SCharles.Forsyth   /*                                                                       */
2997*37da2899SCharles.Forsyth   static void
Ins_SPVTCA(INS_ARG)2998*37da2899SCharles.Forsyth   Ins_SPVTCA( INS_ARG )
2999*37da2899SCharles.Forsyth   {
3000*37da2899SCharles.Forsyth     DO_SPVTCA
3001*37da2899SCharles.Forsyth   }
3002*37da2899SCharles.Forsyth 
3003*37da2899SCharles.Forsyth 
3004*37da2899SCharles.Forsyth   /*************************************************************************/
3005*37da2899SCharles.Forsyth   /*                                                                       */
3006*37da2899SCharles.Forsyth   /* SFVTCA[a]:    Set FVector to Coordinate Axis                          */
3007*37da2899SCharles.Forsyth   /* Opcode range: 0x04-0x05                                               */
3008*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3009*37da2899SCharles.Forsyth   /*                                                                       */
3010*37da2899SCharles.Forsyth   static void
Ins_SFVTCA(INS_ARG)3011*37da2899SCharles.Forsyth   Ins_SFVTCA( INS_ARG )
3012*37da2899SCharles.Forsyth   {
3013*37da2899SCharles.Forsyth     DO_SFVTCA
3014*37da2899SCharles.Forsyth   }
3015*37da2899SCharles.Forsyth 
3016*37da2899SCharles.Forsyth 
3017*37da2899SCharles.Forsyth   /*************************************************************************/
3018*37da2899SCharles.Forsyth   /*                                                                       */
3019*37da2899SCharles.Forsyth   /* SPVTL[a]:     Set PVector To Line                                     */
3020*37da2899SCharles.Forsyth   /* Opcode range: 0x06-0x07                                               */
3021*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
3022*37da2899SCharles.Forsyth   /*                                                                       */
3023*37da2899SCharles.Forsyth   static void
Ins_SPVTL(INS_ARG)3024*37da2899SCharles.Forsyth   Ins_SPVTL( INS_ARG )
3025*37da2899SCharles.Forsyth   {
3026*37da2899SCharles.Forsyth     DO_SPVTL
3027*37da2899SCharles.Forsyth   }
3028*37da2899SCharles.Forsyth 
3029*37da2899SCharles.Forsyth 
3030*37da2899SCharles.Forsyth   /*************************************************************************/
3031*37da2899SCharles.Forsyth   /*                                                                       */
3032*37da2899SCharles.Forsyth   /* SFVTL[a]:     Set FVector To Line                                     */
3033*37da2899SCharles.Forsyth   /* Opcode range: 0x08-0x09                                               */
3034*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
3035*37da2899SCharles.Forsyth   /*                                                                       */
3036*37da2899SCharles.Forsyth   static void
Ins_SFVTL(INS_ARG)3037*37da2899SCharles.Forsyth   Ins_SFVTL( INS_ARG )
3038*37da2899SCharles.Forsyth   {
3039*37da2899SCharles.Forsyth     DO_SFVTL
3040*37da2899SCharles.Forsyth   }
3041*37da2899SCharles.Forsyth 
3042*37da2899SCharles.Forsyth 
3043*37da2899SCharles.Forsyth   /*************************************************************************/
3044*37da2899SCharles.Forsyth   /*                                                                       */
3045*37da2899SCharles.Forsyth   /* SFVTPV[]:     Set FVector To PVector                                  */
3046*37da2899SCharles.Forsyth   /* Opcode range: 0x0E                                                    */
3047*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3048*37da2899SCharles.Forsyth   /*                                                                       */
3049*37da2899SCharles.Forsyth   static void
Ins_SFVTPV(INS_ARG)3050*37da2899SCharles.Forsyth   Ins_SFVTPV( INS_ARG )
3051*37da2899SCharles.Forsyth   {
3052*37da2899SCharles.Forsyth     DO_SFVTPV
3053*37da2899SCharles.Forsyth   }
3054*37da2899SCharles.Forsyth 
3055*37da2899SCharles.Forsyth 
3056*37da2899SCharles.Forsyth   /*************************************************************************/
3057*37da2899SCharles.Forsyth   /*                                                                       */
3058*37da2899SCharles.Forsyth   /* SPVFS[]:      Set PVector From Stack                                  */
3059*37da2899SCharles.Forsyth   /* Opcode range: 0x0A                                                    */
3060*37da2899SCharles.Forsyth   /* Stack:        f2.14 f2.14 -->                                         */
3061*37da2899SCharles.Forsyth   /*                                                                       */
3062*37da2899SCharles.Forsyth   static void
Ins_SPVFS(INS_ARG)3063*37da2899SCharles.Forsyth   Ins_SPVFS( INS_ARG )
3064*37da2899SCharles.Forsyth   {
3065*37da2899SCharles.Forsyth     DO_SPVFS
3066*37da2899SCharles.Forsyth   }
3067*37da2899SCharles.Forsyth 
3068*37da2899SCharles.Forsyth 
3069*37da2899SCharles.Forsyth   /*************************************************************************/
3070*37da2899SCharles.Forsyth   /*                                                                       */
3071*37da2899SCharles.Forsyth   /* SFVFS[]:      Set FVector From Stack                                  */
3072*37da2899SCharles.Forsyth   /* Opcode range: 0x0B                                                    */
3073*37da2899SCharles.Forsyth   /* Stack:        f2.14 f2.14 -->                                         */
3074*37da2899SCharles.Forsyth   /*                                                                       */
3075*37da2899SCharles.Forsyth   static void
Ins_SFVFS(INS_ARG)3076*37da2899SCharles.Forsyth   Ins_SFVFS( INS_ARG )
3077*37da2899SCharles.Forsyth   {
3078*37da2899SCharles.Forsyth     DO_SFVFS
3079*37da2899SCharles.Forsyth   }
3080*37da2899SCharles.Forsyth 
3081*37da2899SCharles.Forsyth 
3082*37da2899SCharles.Forsyth   /*************************************************************************/
3083*37da2899SCharles.Forsyth   /*                                                                       */
3084*37da2899SCharles.Forsyth   /* GPV[]:        Get Projection Vector                                   */
3085*37da2899SCharles.Forsyth   /* Opcode range: 0x0C                                                    */
3086*37da2899SCharles.Forsyth   /* Stack:        ef2.14 --> ef2.14                                       */
3087*37da2899SCharles.Forsyth   /*                                                                       */
3088*37da2899SCharles.Forsyth   static void
Ins_GPV(INS_ARG)3089*37da2899SCharles.Forsyth   Ins_GPV( INS_ARG )
3090*37da2899SCharles.Forsyth   {
3091*37da2899SCharles.Forsyth     DO_GPV
3092*37da2899SCharles.Forsyth   }
3093*37da2899SCharles.Forsyth 
3094*37da2899SCharles.Forsyth 
3095*37da2899SCharles.Forsyth   /*************************************************************************/
3096*37da2899SCharles.Forsyth   /* GFV[]:        Get Freedom Vector                                      */
3097*37da2899SCharles.Forsyth   /* Opcode range: 0x0D                                                    */
3098*37da2899SCharles.Forsyth   /* Stack:        ef2.14 --> ef2.14                                       */
3099*37da2899SCharles.Forsyth   /*                                                                       */
3100*37da2899SCharles.Forsyth   static void
Ins_GFV(INS_ARG)3101*37da2899SCharles.Forsyth   Ins_GFV( INS_ARG )
3102*37da2899SCharles.Forsyth   {
3103*37da2899SCharles.Forsyth     DO_GFV
3104*37da2899SCharles.Forsyth   }
3105*37da2899SCharles.Forsyth 
3106*37da2899SCharles.Forsyth 
3107*37da2899SCharles.Forsyth   /*************************************************************************/
3108*37da2899SCharles.Forsyth   /*                                                                       */
3109*37da2899SCharles.Forsyth   /* SRP0[]:       Set Reference Point 0                                   */
3110*37da2899SCharles.Forsyth   /* Opcode range: 0x10                                                    */
3111*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3112*37da2899SCharles.Forsyth   /*                                                                       */
3113*37da2899SCharles.Forsyth   static void
Ins_SRP0(INS_ARG)3114*37da2899SCharles.Forsyth   Ins_SRP0( INS_ARG )
3115*37da2899SCharles.Forsyth   {
3116*37da2899SCharles.Forsyth     DO_SRP0
3117*37da2899SCharles.Forsyth   }
3118*37da2899SCharles.Forsyth 
3119*37da2899SCharles.Forsyth 
3120*37da2899SCharles.Forsyth   /*************************************************************************/
3121*37da2899SCharles.Forsyth   /*                                                                       */
3122*37da2899SCharles.Forsyth   /* SRP1[]:       Set Reference Point 1                                   */
3123*37da2899SCharles.Forsyth   /* Opcode range: 0x11                                                    */
3124*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3125*37da2899SCharles.Forsyth   /*                                                                       */
3126*37da2899SCharles.Forsyth   static void
Ins_SRP1(INS_ARG)3127*37da2899SCharles.Forsyth   Ins_SRP1( INS_ARG )
3128*37da2899SCharles.Forsyth   {
3129*37da2899SCharles.Forsyth     DO_SRP1
3130*37da2899SCharles.Forsyth   }
3131*37da2899SCharles.Forsyth 
3132*37da2899SCharles.Forsyth 
3133*37da2899SCharles.Forsyth   /*************************************************************************/
3134*37da2899SCharles.Forsyth   /*                                                                       */
3135*37da2899SCharles.Forsyth   /* SRP2[]:       Set Reference Point 2                                   */
3136*37da2899SCharles.Forsyth   /* Opcode range: 0x12                                                    */
3137*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3138*37da2899SCharles.Forsyth   /*                                                                       */
3139*37da2899SCharles.Forsyth   static void
Ins_SRP2(INS_ARG)3140*37da2899SCharles.Forsyth   Ins_SRP2( INS_ARG )
3141*37da2899SCharles.Forsyth   {
3142*37da2899SCharles.Forsyth     DO_SRP2
3143*37da2899SCharles.Forsyth   }
3144*37da2899SCharles.Forsyth 
3145*37da2899SCharles.Forsyth 
3146*37da2899SCharles.Forsyth   /*************************************************************************/
3147*37da2899SCharles.Forsyth   /*                                                                       */
3148*37da2899SCharles.Forsyth   /* RTHG[]:       Round To Half Grid                                      */
3149*37da2899SCharles.Forsyth   /* Opcode range: 0x19                                                    */
3150*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3151*37da2899SCharles.Forsyth   /*                                                                       */
3152*37da2899SCharles.Forsyth   static void
Ins_RTHG(INS_ARG)3153*37da2899SCharles.Forsyth   Ins_RTHG( INS_ARG )
3154*37da2899SCharles.Forsyth   {
3155*37da2899SCharles.Forsyth     DO_RTHG
3156*37da2899SCharles.Forsyth   }
3157*37da2899SCharles.Forsyth 
3158*37da2899SCharles.Forsyth 
3159*37da2899SCharles.Forsyth   /*************************************************************************/
3160*37da2899SCharles.Forsyth   /*                                                                       */
3161*37da2899SCharles.Forsyth   /* RTG[]:        Round To Grid                                           */
3162*37da2899SCharles.Forsyth   /* Opcode range: 0x18                                                    */
3163*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3164*37da2899SCharles.Forsyth   /*                                                                       */
3165*37da2899SCharles.Forsyth   static void
Ins_RTG(INS_ARG)3166*37da2899SCharles.Forsyth   Ins_RTG( INS_ARG )
3167*37da2899SCharles.Forsyth   {
3168*37da2899SCharles.Forsyth     DO_RTG
3169*37da2899SCharles.Forsyth   }
3170*37da2899SCharles.Forsyth 
3171*37da2899SCharles.Forsyth 
3172*37da2899SCharles.Forsyth   /*************************************************************************/
3173*37da2899SCharles.Forsyth   /* RTDG[]:       Round To Double Grid                                    */
3174*37da2899SCharles.Forsyth   /* Opcode range: 0x3D                                                    */
3175*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3176*37da2899SCharles.Forsyth   /*                                                                       */
3177*37da2899SCharles.Forsyth   static void
Ins_RTDG(INS_ARG)3178*37da2899SCharles.Forsyth   Ins_RTDG( INS_ARG )
3179*37da2899SCharles.Forsyth   {
3180*37da2899SCharles.Forsyth     DO_RTDG
3181*37da2899SCharles.Forsyth   }
3182*37da2899SCharles.Forsyth 
3183*37da2899SCharles.Forsyth 
3184*37da2899SCharles.Forsyth   /*************************************************************************/
3185*37da2899SCharles.Forsyth   /* RUTG[]:       Round Up To Grid                                        */
3186*37da2899SCharles.Forsyth   /* Opcode range: 0x7C                                                    */
3187*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3188*37da2899SCharles.Forsyth   /*                                                                       */
3189*37da2899SCharles.Forsyth   static void
Ins_RUTG(INS_ARG)3190*37da2899SCharles.Forsyth   Ins_RUTG( INS_ARG )
3191*37da2899SCharles.Forsyth   {
3192*37da2899SCharles.Forsyth     DO_RUTG
3193*37da2899SCharles.Forsyth   }
3194*37da2899SCharles.Forsyth 
3195*37da2899SCharles.Forsyth 
3196*37da2899SCharles.Forsyth   /*************************************************************************/
3197*37da2899SCharles.Forsyth   /*                                                                       */
3198*37da2899SCharles.Forsyth   /* RDTG[]:       Round Down To Grid                                      */
3199*37da2899SCharles.Forsyth   /* Opcode range: 0x7D                                                    */
3200*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3201*37da2899SCharles.Forsyth   /*                                                                       */
3202*37da2899SCharles.Forsyth   static void
Ins_RDTG(INS_ARG)3203*37da2899SCharles.Forsyth   Ins_RDTG( INS_ARG )
3204*37da2899SCharles.Forsyth   {
3205*37da2899SCharles.Forsyth     DO_RDTG
3206*37da2899SCharles.Forsyth   }
3207*37da2899SCharles.Forsyth 
3208*37da2899SCharles.Forsyth 
3209*37da2899SCharles.Forsyth   /*************************************************************************/
3210*37da2899SCharles.Forsyth   /*                                                                       */
3211*37da2899SCharles.Forsyth   /* ROFF[]:       Round OFF                                               */
3212*37da2899SCharles.Forsyth   /* Opcode range: 0x7A                                                    */
3213*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3214*37da2899SCharles.Forsyth   /*                                                                       */
3215*37da2899SCharles.Forsyth   static void
Ins_ROFF(INS_ARG)3216*37da2899SCharles.Forsyth   Ins_ROFF( INS_ARG )
3217*37da2899SCharles.Forsyth   {
3218*37da2899SCharles.Forsyth     DO_ROFF
3219*37da2899SCharles.Forsyth   }
3220*37da2899SCharles.Forsyth 
3221*37da2899SCharles.Forsyth 
3222*37da2899SCharles.Forsyth   /*************************************************************************/
3223*37da2899SCharles.Forsyth   /*                                                                       */
3224*37da2899SCharles.Forsyth   /* SROUND[]:     Super ROUND                                             */
3225*37da2899SCharles.Forsyth   /* Opcode range: 0x76                                                    */
3226*37da2899SCharles.Forsyth   /* Stack:        Eint8 -->                                               */
3227*37da2899SCharles.Forsyth   /*                                                                       */
3228*37da2899SCharles.Forsyth   static void
Ins_SROUND(INS_ARG)3229*37da2899SCharles.Forsyth   Ins_SROUND( INS_ARG )
3230*37da2899SCharles.Forsyth   {
3231*37da2899SCharles.Forsyth     DO_SROUND
3232*37da2899SCharles.Forsyth   }
3233*37da2899SCharles.Forsyth 
3234*37da2899SCharles.Forsyth 
3235*37da2899SCharles.Forsyth   /*************************************************************************/
3236*37da2899SCharles.Forsyth   /*                                                                       */
3237*37da2899SCharles.Forsyth   /* S45ROUND[]:   Super ROUND 45 degrees                                  */
3238*37da2899SCharles.Forsyth   /* Opcode range: 0x77                                                    */
3239*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3240*37da2899SCharles.Forsyth   /*                                                                       */
3241*37da2899SCharles.Forsyth   static void
Ins_S45ROUND(INS_ARG)3242*37da2899SCharles.Forsyth   Ins_S45ROUND( INS_ARG )
3243*37da2899SCharles.Forsyth   {
3244*37da2899SCharles.Forsyth     DO_S45ROUND
3245*37da2899SCharles.Forsyth   }
3246*37da2899SCharles.Forsyth 
3247*37da2899SCharles.Forsyth 
3248*37da2899SCharles.Forsyth   /*************************************************************************/
3249*37da2899SCharles.Forsyth   /*                                                                       */
3250*37da2899SCharles.Forsyth   /* SLOOP[]:      Set LOOP variable                                       */
3251*37da2899SCharles.Forsyth   /* Opcode range: 0x17                                                    */
3252*37da2899SCharles.Forsyth   /* Stack:        int32? -->                                              */
3253*37da2899SCharles.Forsyth   /*                                                                       */
3254*37da2899SCharles.Forsyth   static void
Ins_SLOOP(INS_ARG)3255*37da2899SCharles.Forsyth   Ins_SLOOP( INS_ARG )
3256*37da2899SCharles.Forsyth   {
3257*37da2899SCharles.Forsyth     DO_SLOOP
3258*37da2899SCharles.Forsyth   }
3259*37da2899SCharles.Forsyth 
3260*37da2899SCharles.Forsyth 
3261*37da2899SCharles.Forsyth   /*************************************************************************/
3262*37da2899SCharles.Forsyth   /*                                                                       */
3263*37da2899SCharles.Forsyth   /* SMD[]:        Set Minimum Distance                                    */
3264*37da2899SCharles.Forsyth   /* Opcode range: 0x1A                                                    */
3265*37da2899SCharles.Forsyth   /* Stack:        f26.6 -->                                               */
3266*37da2899SCharles.Forsyth   /*                                                                       */
3267*37da2899SCharles.Forsyth   static void
Ins_SMD(INS_ARG)3268*37da2899SCharles.Forsyth   Ins_SMD( INS_ARG )
3269*37da2899SCharles.Forsyth   {
3270*37da2899SCharles.Forsyth     DO_SMD
3271*37da2899SCharles.Forsyth   }
3272*37da2899SCharles.Forsyth 
3273*37da2899SCharles.Forsyth 
3274*37da2899SCharles.Forsyth   /*************************************************************************/
3275*37da2899SCharles.Forsyth   /*                                                                       */
3276*37da2899SCharles.Forsyth   /* SCVTCI[]:     Set Control Value Table Cut In                          */
3277*37da2899SCharles.Forsyth   /* Opcode range: 0x1D                                                    */
3278*37da2899SCharles.Forsyth   /* Stack:        f26.6 -->                                               */
3279*37da2899SCharles.Forsyth   /*                                                                       */
3280*37da2899SCharles.Forsyth   static void
Ins_SCVTCI(INS_ARG)3281*37da2899SCharles.Forsyth   Ins_SCVTCI( INS_ARG )
3282*37da2899SCharles.Forsyth   {
3283*37da2899SCharles.Forsyth     DO_SCVTCI
3284*37da2899SCharles.Forsyth   }
3285*37da2899SCharles.Forsyth 
3286*37da2899SCharles.Forsyth 
3287*37da2899SCharles.Forsyth   /*************************************************************************/
3288*37da2899SCharles.Forsyth   /*                                                                       */
3289*37da2899SCharles.Forsyth   /* SSWCI[]:      Set Single Width Cut In                                 */
3290*37da2899SCharles.Forsyth   /* Opcode range: 0x1E                                                    */
3291*37da2899SCharles.Forsyth   /* Stack:        f26.6 -->                                               */
3292*37da2899SCharles.Forsyth   /*                                                                       */
3293*37da2899SCharles.Forsyth   static void
Ins_SSWCI(INS_ARG)3294*37da2899SCharles.Forsyth   Ins_SSWCI( INS_ARG )
3295*37da2899SCharles.Forsyth   {
3296*37da2899SCharles.Forsyth     DO_SSWCI
3297*37da2899SCharles.Forsyth   }
3298*37da2899SCharles.Forsyth 
3299*37da2899SCharles.Forsyth 
3300*37da2899SCharles.Forsyth   /*************************************************************************/
3301*37da2899SCharles.Forsyth   /*                                                                       */
3302*37da2899SCharles.Forsyth   /* SSW[]:        Set Single Width                                        */
3303*37da2899SCharles.Forsyth   /* Opcode range: 0x1F                                                    */
3304*37da2899SCharles.Forsyth   /* Stack:        int32? -->                                              */
3305*37da2899SCharles.Forsyth   /*                                                                       */
3306*37da2899SCharles.Forsyth   static void
Ins_SSW(INS_ARG)3307*37da2899SCharles.Forsyth   Ins_SSW( INS_ARG )
3308*37da2899SCharles.Forsyth   {
3309*37da2899SCharles.Forsyth     DO_SSW
3310*37da2899SCharles.Forsyth   }
3311*37da2899SCharles.Forsyth 
3312*37da2899SCharles.Forsyth 
3313*37da2899SCharles.Forsyth   /*************************************************************************/
3314*37da2899SCharles.Forsyth   /*                                                                       */
3315*37da2899SCharles.Forsyth   /* FLIPON[]:     Set auto-FLIP to ON                                     */
3316*37da2899SCharles.Forsyth   /* Opcode range: 0x4D                                                    */
3317*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3318*37da2899SCharles.Forsyth   /*                                                                       */
3319*37da2899SCharles.Forsyth   static void
Ins_FLIPON(INS_ARG)3320*37da2899SCharles.Forsyth   Ins_FLIPON( INS_ARG )
3321*37da2899SCharles.Forsyth   {
3322*37da2899SCharles.Forsyth     DO_FLIPON
3323*37da2899SCharles.Forsyth   }
3324*37da2899SCharles.Forsyth 
3325*37da2899SCharles.Forsyth 
3326*37da2899SCharles.Forsyth   /*************************************************************************/
3327*37da2899SCharles.Forsyth   /*                                                                       */
3328*37da2899SCharles.Forsyth   /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
3329*37da2899SCharles.Forsyth   /* Opcode range: 0x4E                                                    */
3330*37da2899SCharles.Forsyth   /* Stack: -->                                                            */
3331*37da2899SCharles.Forsyth   /*                                                                       */
3332*37da2899SCharles.Forsyth   static void
Ins_FLIPOFF(INS_ARG)3333*37da2899SCharles.Forsyth   Ins_FLIPOFF( INS_ARG )
3334*37da2899SCharles.Forsyth   {
3335*37da2899SCharles.Forsyth     DO_FLIPOFF
3336*37da2899SCharles.Forsyth   }
3337*37da2899SCharles.Forsyth 
3338*37da2899SCharles.Forsyth 
3339*37da2899SCharles.Forsyth   /*************************************************************************/
3340*37da2899SCharles.Forsyth   /*                                                                       */
3341*37da2899SCharles.Forsyth   /* SANGW[]:      Set ANGle Weight                                        */
3342*37da2899SCharles.Forsyth   /* Opcode range: 0x7E                                                    */
3343*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3344*37da2899SCharles.Forsyth   /*                                                                       */
3345*37da2899SCharles.Forsyth   static void
Ins_SANGW(INS_ARG)3346*37da2899SCharles.Forsyth   Ins_SANGW( INS_ARG )
3347*37da2899SCharles.Forsyth   {
3348*37da2899SCharles.Forsyth     /* instruction not supported anymore */
3349*37da2899SCharles.Forsyth   }
3350*37da2899SCharles.Forsyth 
3351*37da2899SCharles.Forsyth 
3352*37da2899SCharles.Forsyth   /*************************************************************************/
3353*37da2899SCharles.Forsyth   /*                                                                       */
3354*37da2899SCharles.Forsyth   /* SDB[]:        Set Delta Base                                          */
3355*37da2899SCharles.Forsyth   /* Opcode range: 0x5E                                                    */
3356*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3357*37da2899SCharles.Forsyth   /*                                                                       */
3358*37da2899SCharles.Forsyth   static void
Ins_SDB(INS_ARG)3359*37da2899SCharles.Forsyth   Ins_SDB( INS_ARG )
3360*37da2899SCharles.Forsyth   {
3361*37da2899SCharles.Forsyth     DO_SDB
3362*37da2899SCharles.Forsyth   }
3363*37da2899SCharles.Forsyth 
3364*37da2899SCharles.Forsyth 
3365*37da2899SCharles.Forsyth   /*************************************************************************/
3366*37da2899SCharles.Forsyth   /*                                                                       */
3367*37da2899SCharles.Forsyth   /* SDS[]:        Set Delta Shift                                         */
3368*37da2899SCharles.Forsyth   /* Opcode range: 0x5F                                                    */
3369*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3370*37da2899SCharles.Forsyth   /*                                                                       */
3371*37da2899SCharles.Forsyth   static void
Ins_SDS(INS_ARG)3372*37da2899SCharles.Forsyth   Ins_SDS( INS_ARG )
3373*37da2899SCharles.Forsyth   {
3374*37da2899SCharles.Forsyth     DO_SDS
3375*37da2899SCharles.Forsyth   }
3376*37da2899SCharles.Forsyth 
3377*37da2899SCharles.Forsyth 
3378*37da2899SCharles.Forsyth   /*************************************************************************/
3379*37da2899SCharles.Forsyth   /*                                                                       */
3380*37da2899SCharles.Forsyth   /* MPPEM[]:      Measure Pixel Per EM                                    */
3381*37da2899SCharles.Forsyth   /* Opcode range: 0x4B                                                    */
3382*37da2899SCharles.Forsyth   /* Stack:        --> Euint16                                             */
3383*37da2899SCharles.Forsyth   /*                                                                       */
3384*37da2899SCharles.Forsyth   static void
Ins_MPPEM(INS_ARG)3385*37da2899SCharles.Forsyth   Ins_MPPEM( INS_ARG )
3386*37da2899SCharles.Forsyth   {
3387*37da2899SCharles.Forsyth     DO_MPPEM
3388*37da2899SCharles.Forsyth   }
3389*37da2899SCharles.Forsyth 
3390*37da2899SCharles.Forsyth 
3391*37da2899SCharles.Forsyth   /*************************************************************************/
3392*37da2899SCharles.Forsyth   /*                                                                       */
3393*37da2899SCharles.Forsyth   /* MPS[]:        Measure Point Size                                      */
3394*37da2899SCharles.Forsyth   /* Opcode range: 0x4C                                                    */
3395*37da2899SCharles.Forsyth   /* Stack:        --> Euint16                                             */
3396*37da2899SCharles.Forsyth   /*                                                                       */
3397*37da2899SCharles.Forsyth   static void
Ins_MPS(INS_ARG)3398*37da2899SCharles.Forsyth   Ins_MPS( INS_ARG )
3399*37da2899SCharles.Forsyth   {
3400*37da2899SCharles.Forsyth     DO_MPS
3401*37da2899SCharles.Forsyth   }
3402*37da2899SCharles.Forsyth 
3403*37da2899SCharles.Forsyth 
3404*37da2899SCharles.Forsyth   /*************************************************************************/
3405*37da2899SCharles.Forsyth   /*                                                                       */
3406*37da2899SCharles.Forsyth   /* DUP[]:        DUPlicate the top stack's element                       */
3407*37da2899SCharles.Forsyth   /* Opcode range: 0x20                                                    */
3408*37da2899SCharles.Forsyth   /* Stack:        StkElt --> StkElt StkElt                                */
3409*37da2899SCharles.Forsyth   /*                                                                       */
3410*37da2899SCharles.Forsyth   static void
Ins_DUP(INS_ARG)3411*37da2899SCharles.Forsyth   Ins_DUP( INS_ARG )
3412*37da2899SCharles.Forsyth   {
3413*37da2899SCharles.Forsyth     DO_DUP
3414*37da2899SCharles.Forsyth   }
3415*37da2899SCharles.Forsyth 
3416*37da2899SCharles.Forsyth 
3417*37da2899SCharles.Forsyth   /*************************************************************************/
3418*37da2899SCharles.Forsyth   /*                                                                       */
3419*37da2899SCharles.Forsyth   /* POP[]:        POP the stack's top element                             */
3420*37da2899SCharles.Forsyth   /* Opcode range: 0x21                                                    */
3421*37da2899SCharles.Forsyth   /* Stack:        StkElt -->                                              */
3422*37da2899SCharles.Forsyth   /*                                                                       */
3423*37da2899SCharles.Forsyth   static void
Ins_POP(INS_ARG)3424*37da2899SCharles.Forsyth   Ins_POP( INS_ARG )
3425*37da2899SCharles.Forsyth   {
3426*37da2899SCharles.Forsyth     /* nothing to do */
3427*37da2899SCharles.Forsyth   }
3428*37da2899SCharles.Forsyth 
3429*37da2899SCharles.Forsyth 
3430*37da2899SCharles.Forsyth   /*************************************************************************/
3431*37da2899SCharles.Forsyth   /*                                                                       */
3432*37da2899SCharles.Forsyth   /* CLEAR[]:      CLEAR the entire stack                                  */
3433*37da2899SCharles.Forsyth   /* Opcode range: 0x22                                                    */
3434*37da2899SCharles.Forsyth   /* Stack:        StkElt... -->                                           */
3435*37da2899SCharles.Forsyth   /*                                                                       */
3436*37da2899SCharles.Forsyth   static void
Ins_CLEAR(INS_ARG)3437*37da2899SCharles.Forsyth   Ins_CLEAR( INS_ARG )
3438*37da2899SCharles.Forsyth   {
3439*37da2899SCharles.Forsyth     DO_CLEAR
3440*37da2899SCharles.Forsyth   }
3441*37da2899SCharles.Forsyth 
3442*37da2899SCharles.Forsyth 
3443*37da2899SCharles.Forsyth   /*************************************************************************/
3444*37da2899SCharles.Forsyth   /*                                                                       */
3445*37da2899SCharles.Forsyth   /* SWAP[]:       SWAP the stack's top two elements                       */
3446*37da2899SCharles.Forsyth   /* Opcode range: 0x23                                                    */
3447*37da2899SCharles.Forsyth   /* Stack:        2 * StkElt --> 2 * StkElt                               */
3448*37da2899SCharles.Forsyth   /*                                                                       */
3449*37da2899SCharles.Forsyth   static void
Ins_SWAP(INS_ARG)3450*37da2899SCharles.Forsyth   Ins_SWAP( INS_ARG )
3451*37da2899SCharles.Forsyth   {
3452*37da2899SCharles.Forsyth     DO_SWAP
3453*37da2899SCharles.Forsyth   }
3454*37da2899SCharles.Forsyth 
3455*37da2899SCharles.Forsyth 
3456*37da2899SCharles.Forsyth   /*************************************************************************/
3457*37da2899SCharles.Forsyth   /*                                                                       */
3458*37da2899SCharles.Forsyth   /* DEPTH[]:      return the stack DEPTH                                  */
3459*37da2899SCharles.Forsyth   /* Opcode range: 0x24                                                    */
3460*37da2899SCharles.Forsyth   /* Stack:        --> uint32                                              */
3461*37da2899SCharles.Forsyth   /*                                                                       */
3462*37da2899SCharles.Forsyth   static void
Ins_DEPTH(INS_ARG)3463*37da2899SCharles.Forsyth   Ins_DEPTH( INS_ARG )
3464*37da2899SCharles.Forsyth   {
3465*37da2899SCharles.Forsyth     DO_DEPTH
3466*37da2899SCharles.Forsyth   }
3467*37da2899SCharles.Forsyth 
3468*37da2899SCharles.Forsyth 
3469*37da2899SCharles.Forsyth   /*************************************************************************/
3470*37da2899SCharles.Forsyth   /*                                                                       */
3471*37da2899SCharles.Forsyth   /* CINDEX[]:     Copy INDEXed element                                    */
3472*37da2899SCharles.Forsyth   /* Opcode range: 0x25                                                    */
3473*37da2899SCharles.Forsyth   /* Stack:        int32 --> StkElt                                        */
3474*37da2899SCharles.Forsyth   /*                                                                       */
3475*37da2899SCharles.Forsyth   static void
Ins_CINDEX(INS_ARG)3476*37da2899SCharles.Forsyth   Ins_CINDEX( INS_ARG )
3477*37da2899SCharles.Forsyth   {
3478*37da2899SCharles.Forsyth     DO_CINDEX
3479*37da2899SCharles.Forsyth   }
3480*37da2899SCharles.Forsyth 
3481*37da2899SCharles.Forsyth 
3482*37da2899SCharles.Forsyth   /*************************************************************************/
3483*37da2899SCharles.Forsyth   /*                                                                       */
3484*37da2899SCharles.Forsyth   /* EIF[]:        End IF                                                  */
3485*37da2899SCharles.Forsyth   /* Opcode range: 0x59                                                    */
3486*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
3487*37da2899SCharles.Forsyth   /*                                                                       */
3488*37da2899SCharles.Forsyth   static void
Ins_EIF(INS_ARG)3489*37da2899SCharles.Forsyth   Ins_EIF( INS_ARG )
3490*37da2899SCharles.Forsyth   {
3491*37da2899SCharles.Forsyth     /* nothing to do */
3492*37da2899SCharles.Forsyth   }
3493*37da2899SCharles.Forsyth 
3494*37da2899SCharles.Forsyth 
3495*37da2899SCharles.Forsyth   /*************************************************************************/
3496*37da2899SCharles.Forsyth   /*                                                                       */
3497*37da2899SCharles.Forsyth   /* JROT[]:       Jump Relative On True                                   */
3498*37da2899SCharles.Forsyth   /* Opcode range: 0x78                                                    */
3499*37da2899SCharles.Forsyth   /* Stack:        StkElt int32 -->                                        */
3500*37da2899SCharles.Forsyth   /*                                                                       */
3501*37da2899SCharles.Forsyth   static void
Ins_JROT(INS_ARG)3502*37da2899SCharles.Forsyth   Ins_JROT( INS_ARG )
3503*37da2899SCharles.Forsyth   {
3504*37da2899SCharles.Forsyth     DO_JROT
3505*37da2899SCharles.Forsyth   }
3506*37da2899SCharles.Forsyth 
3507*37da2899SCharles.Forsyth 
3508*37da2899SCharles.Forsyth   /*************************************************************************/
3509*37da2899SCharles.Forsyth   /*                                                                       */
3510*37da2899SCharles.Forsyth   /* JMPR[]:       JuMP Relative                                           */
3511*37da2899SCharles.Forsyth   /* Opcode range: 0x1C                                                    */
3512*37da2899SCharles.Forsyth   /* Stack:        int32 -->                                               */
3513*37da2899SCharles.Forsyth   /*                                                                       */
3514*37da2899SCharles.Forsyth   static void
Ins_JMPR(INS_ARG)3515*37da2899SCharles.Forsyth   Ins_JMPR( INS_ARG )
3516*37da2899SCharles.Forsyth   {
3517*37da2899SCharles.Forsyth     DO_JMPR
3518*37da2899SCharles.Forsyth   }
3519*37da2899SCharles.Forsyth 
3520*37da2899SCharles.Forsyth 
3521*37da2899SCharles.Forsyth   /*************************************************************************/
3522*37da2899SCharles.Forsyth   /*                                                                       */
3523*37da2899SCharles.Forsyth   /* JROF[]:       Jump Relative On False                                  */
3524*37da2899SCharles.Forsyth   /* Opcode range: 0x79                                                    */
3525*37da2899SCharles.Forsyth   /* Stack:        StkElt int32 -->                                        */
3526*37da2899SCharles.Forsyth   /*                                                                       */
3527*37da2899SCharles.Forsyth   static void
Ins_JROF(INS_ARG)3528*37da2899SCharles.Forsyth   Ins_JROF( INS_ARG )
3529*37da2899SCharles.Forsyth   {
3530*37da2899SCharles.Forsyth     DO_JROF
3531*37da2899SCharles.Forsyth   }
3532*37da2899SCharles.Forsyth 
3533*37da2899SCharles.Forsyth 
3534*37da2899SCharles.Forsyth   /*************************************************************************/
3535*37da2899SCharles.Forsyth   /*                                                                       */
3536*37da2899SCharles.Forsyth   /* LT[]:         Less Than                                               */
3537*37da2899SCharles.Forsyth   /* Opcode range: 0x50                                                    */
3538*37da2899SCharles.Forsyth   /* Stack:        int32? int32? --> bool                                  */
3539*37da2899SCharles.Forsyth   /*                                                                       */
3540*37da2899SCharles.Forsyth   static void
Ins_LT(INS_ARG)3541*37da2899SCharles.Forsyth   Ins_LT( INS_ARG )
3542*37da2899SCharles.Forsyth   {
3543*37da2899SCharles.Forsyth     DO_LT
3544*37da2899SCharles.Forsyth   }
3545*37da2899SCharles.Forsyth 
3546*37da2899SCharles.Forsyth 
3547*37da2899SCharles.Forsyth   /*************************************************************************/
3548*37da2899SCharles.Forsyth   /*                                                                       */
3549*37da2899SCharles.Forsyth   /* LTEQ[]:       Less Than or EQual                                      */
3550*37da2899SCharles.Forsyth   /* Opcode range: 0x51                                                    */
3551*37da2899SCharles.Forsyth   /* Stack:        int32? int32? --> bool                                  */
3552*37da2899SCharles.Forsyth   /*                                                                       */
3553*37da2899SCharles.Forsyth   static void
Ins_LTEQ(INS_ARG)3554*37da2899SCharles.Forsyth   Ins_LTEQ( INS_ARG )
3555*37da2899SCharles.Forsyth   {
3556*37da2899SCharles.Forsyth     DO_LTEQ
3557*37da2899SCharles.Forsyth   }
3558*37da2899SCharles.Forsyth 
3559*37da2899SCharles.Forsyth 
3560*37da2899SCharles.Forsyth   /*************************************************************************/
3561*37da2899SCharles.Forsyth   /*                                                                       */
3562*37da2899SCharles.Forsyth   /* GT[]:         Greater Than                                            */
3563*37da2899SCharles.Forsyth   /* Opcode range: 0x52                                                    */
3564*37da2899SCharles.Forsyth   /* Stack:        int32? int32? --> bool                                  */
3565*37da2899SCharles.Forsyth   /*                                                                       */
3566*37da2899SCharles.Forsyth   static void
Ins_GT(INS_ARG)3567*37da2899SCharles.Forsyth   Ins_GT( INS_ARG )
3568*37da2899SCharles.Forsyth   {
3569*37da2899SCharles.Forsyth     DO_GT
3570*37da2899SCharles.Forsyth   }
3571*37da2899SCharles.Forsyth 
3572*37da2899SCharles.Forsyth 
3573*37da2899SCharles.Forsyth   /*************************************************************************/
3574*37da2899SCharles.Forsyth   /*                                                                       */
3575*37da2899SCharles.Forsyth   /* GTEQ[]:       Greater Than or EQual                                   */
3576*37da2899SCharles.Forsyth   /* Opcode range: 0x53                                                    */
3577*37da2899SCharles.Forsyth   /* Stack:        int32? int32? --> bool                                  */
3578*37da2899SCharles.Forsyth   /*                                                                       */
3579*37da2899SCharles.Forsyth   static void
Ins_GTEQ(INS_ARG)3580*37da2899SCharles.Forsyth   Ins_GTEQ( INS_ARG )
3581*37da2899SCharles.Forsyth   {
3582*37da2899SCharles.Forsyth     DO_GTEQ
3583*37da2899SCharles.Forsyth   }
3584*37da2899SCharles.Forsyth 
3585*37da2899SCharles.Forsyth 
3586*37da2899SCharles.Forsyth   /*************************************************************************/
3587*37da2899SCharles.Forsyth   /*                                                                       */
3588*37da2899SCharles.Forsyth   /* EQ[]:         EQual                                                   */
3589*37da2899SCharles.Forsyth   /* Opcode range: 0x54                                                    */
3590*37da2899SCharles.Forsyth   /* Stack:        StkElt StkElt --> bool                                  */
3591*37da2899SCharles.Forsyth   /*                                                                       */
3592*37da2899SCharles.Forsyth   static void
Ins_EQ(INS_ARG)3593*37da2899SCharles.Forsyth   Ins_EQ( INS_ARG )
3594*37da2899SCharles.Forsyth   {
3595*37da2899SCharles.Forsyth     DO_EQ
3596*37da2899SCharles.Forsyth   }
3597*37da2899SCharles.Forsyth 
3598*37da2899SCharles.Forsyth 
3599*37da2899SCharles.Forsyth   /*************************************************************************/
3600*37da2899SCharles.Forsyth   /*                                                                       */
3601*37da2899SCharles.Forsyth   /* NEQ[]:        Not EQual                                               */
3602*37da2899SCharles.Forsyth   /* Opcode range: 0x55                                                    */
3603*37da2899SCharles.Forsyth   /* Stack:        StkElt StkElt --> bool                                  */
3604*37da2899SCharles.Forsyth   /*                                                                       */
3605*37da2899SCharles.Forsyth   static void
Ins_NEQ(INS_ARG)3606*37da2899SCharles.Forsyth   Ins_NEQ( INS_ARG )
3607*37da2899SCharles.Forsyth   {
3608*37da2899SCharles.Forsyth     DO_NEQ
3609*37da2899SCharles.Forsyth   }
3610*37da2899SCharles.Forsyth 
3611*37da2899SCharles.Forsyth 
3612*37da2899SCharles.Forsyth   /*************************************************************************/
3613*37da2899SCharles.Forsyth   /*                                                                       */
3614*37da2899SCharles.Forsyth   /* ODD[]:        Is ODD                                                  */
3615*37da2899SCharles.Forsyth   /* Opcode range: 0x56                                                    */
3616*37da2899SCharles.Forsyth   /* Stack:        f26.6 --> bool                                          */
3617*37da2899SCharles.Forsyth   /*                                                                       */
3618*37da2899SCharles.Forsyth   static void
Ins_ODD(INS_ARG)3619*37da2899SCharles.Forsyth   Ins_ODD( INS_ARG )
3620*37da2899SCharles.Forsyth   {
3621*37da2899SCharles.Forsyth     DO_ODD
3622*37da2899SCharles.Forsyth   }
3623*37da2899SCharles.Forsyth 
3624*37da2899SCharles.Forsyth 
3625*37da2899SCharles.Forsyth   /*************************************************************************/
3626*37da2899SCharles.Forsyth   /*                                                                       */
3627*37da2899SCharles.Forsyth   /* EVEN[]:       Is EVEN                                                 */
3628*37da2899SCharles.Forsyth   /* Opcode range: 0x57                                                    */
3629*37da2899SCharles.Forsyth   /* Stack:        f26.6 --> bool                                          */
3630*37da2899SCharles.Forsyth   /*                                                                       */
3631*37da2899SCharles.Forsyth   static void
Ins_EVEN(INS_ARG)3632*37da2899SCharles.Forsyth   Ins_EVEN( INS_ARG )
3633*37da2899SCharles.Forsyth   {
3634*37da2899SCharles.Forsyth     DO_EVEN
3635*37da2899SCharles.Forsyth   }
3636*37da2899SCharles.Forsyth 
3637*37da2899SCharles.Forsyth 
3638*37da2899SCharles.Forsyth   /*************************************************************************/
3639*37da2899SCharles.Forsyth   /*                                                                       */
3640*37da2899SCharles.Forsyth   /* AND[]:        logical AND                                             */
3641*37da2899SCharles.Forsyth   /* Opcode range: 0x5A                                                    */
3642*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 --> uint32                                */
3643*37da2899SCharles.Forsyth   /*                                                                       */
3644*37da2899SCharles.Forsyth   static void
Ins_AND(INS_ARG)3645*37da2899SCharles.Forsyth   Ins_AND( INS_ARG )
3646*37da2899SCharles.Forsyth   {
3647*37da2899SCharles.Forsyth     DO_AND
3648*37da2899SCharles.Forsyth   }
3649*37da2899SCharles.Forsyth 
3650*37da2899SCharles.Forsyth 
3651*37da2899SCharles.Forsyth   /*************************************************************************/
3652*37da2899SCharles.Forsyth   /*                                                                       */
3653*37da2899SCharles.Forsyth   /* OR[]:         logical OR                                              */
3654*37da2899SCharles.Forsyth   /* Opcode range: 0x5B                                                    */
3655*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 --> uint32                                */
3656*37da2899SCharles.Forsyth   /*                                                                       */
3657*37da2899SCharles.Forsyth   static void
Ins_OR(INS_ARG)3658*37da2899SCharles.Forsyth   Ins_OR( INS_ARG )
3659*37da2899SCharles.Forsyth   {
3660*37da2899SCharles.Forsyth     DO_OR
3661*37da2899SCharles.Forsyth   }
3662*37da2899SCharles.Forsyth 
3663*37da2899SCharles.Forsyth 
3664*37da2899SCharles.Forsyth   /*************************************************************************/
3665*37da2899SCharles.Forsyth   /*                                                                       */
3666*37da2899SCharles.Forsyth   /* NOT[]:        logical NOT                                             */
3667*37da2899SCharles.Forsyth   /* Opcode range: 0x5C                                                    */
3668*37da2899SCharles.Forsyth   /* Stack:        StkElt --> uint32                                       */
3669*37da2899SCharles.Forsyth   /*                                                                       */
3670*37da2899SCharles.Forsyth   static void
Ins_NOT(INS_ARG)3671*37da2899SCharles.Forsyth   Ins_NOT( INS_ARG )
3672*37da2899SCharles.Forsyth   {
3673*37da2899SCharles.Forsyth     DO_NOT
3674*37da2899SCharles.Forsyth   }
3675*37da2899SCharles.Forsyth 
3676*37da2899SCharles.Forsyth 
3677*37da2899SCharles.Forsyth   /*************************************************************************/
3678*37da2899SCharles.Forsyth   /*                                                                       */
3679*37da2899SCharles.Forsyth   /* ADD[]:        ADD                                                     */
3680*37da2899SCharles.Forsyth   /* Opcode range: 0x60                                                    */
3681*37da2899SCharles.Forsyth   /* Stack:        f26.6 f26.6 --> f26.6                                   */
3682*37da2899SCharles.Forsyth   /*                                                                       */
3683*37da2899SCharles.Forsyth   static void
Ins_ADD(INS_ARG)3684*37da2899SCharles.Forsyth   Ins_ADD( INS_ARG )
3685*37da2899SCharles.Forsyth   {
3686*37da2899SCharles.Forsyth     DO_ADD
3687*37da2899SCharles.Forsyth   }
3688*37da2899SCharles.Forsyth 
3689*37da2899SCharles.Forsyth 
3690*37da2899SCharles.Forsyth   /*************************************************************************/
3691*37da2899SCharles.Forsyth   /*                                                                       */
3692*37da2899SCharles.Forsyth   /* SUB[]:        SUBtract                                                */
3693*37da2899SCharles.Forsyth   /* Opcode range: 0x61                                                    */
3694*37da2899SCharles.Forsyth   /* Stack:        f26.6 f26.6 --> f26.6                                   */
3695*37da2899SCharles.Forsyth   /*                                                                       */
3696*37da2899SCharles.Forsyth   static void
Ins_SUB(INS_ARG)3697*37da2899SCharles.Forsyth   Ins_SUB( INS_ARG )
3698*37da2899SCharles.Forsyth   {
3699*37da2899SCharles.Forsyth     DO_SUB
3700*37da2899SCharles.Forsyth   }
3701*37da2899SCharles.Forsyth 
3702*37da2899SCharles.Forsyth 
3703*37da2899SCharles.Forsyth   /*************************************************************************/
3704*37da2899SCharles.Forsyth   /*                                                                       */
3705*37da2899SCharles.Forsyth   /* DIV[]:        DIVide                                                  */
3706*37da2899SCharles.Forsyth   /* Opcode range: 0x62                                                    */
3707*37da2899SCharles.Forsyth   /* Stack:        f26.6 f26.6 --> f26.6                                   */
3708*37da2899SCharles.Forsyth   /*                                                                       */
3709*37da2899SCharles.Forsyth   static void
Ins_DIV(INS_ARG)3710*37da2899SCharles.Forsyth   Ins_DIV( INS_ARG )
3711*37da2899SCharles.Forsyth   {
3712*37da2899SCharles.Forsyth     DO_DIV
3713*37da2899SCharles.Forsyth   }
3714*37da2899SCharles.Forsyth 
3715*37da2899SCharles.Forsyth 
3716*37da2899SCharles.Forsyth   /*************************************************************************/
3717*37da2899SCharles.Forsyth   /*                                                                       */
3718*37da2899SCharles.Forsyth   /* MUL[]:        MULtiply                                                */
3719*37da2899SCharles.Forsyth   /* Opcode range: 0x63                                                    */
3720*37da2899SCharles.Forsyth   /* Stack:        f26.6 f26.6 --> f26.6                                   */
3721*37da2899SCharles.Forsyth   /*                                                                       */
3722*37da2899SCharles.Forsyth   static void
Ins_MUL(INS_ARG)3723*37da2899SCharles.Forsyth   Ins_MUL( INS_ARG )
3724*37da2899SCharles.Forsyth   {
3725*37da2899SCharles.Forsyth     DO_MUL
3726*37da2899SCharles.Forsyth   }
3727*37da2899SCharles.Forsyth 
3728*37da2899SCharles.Forsyth 
3729*37da2899SCharles.Forsyth   /*************************************************************************/
3730*37da2899SCharles.Forsyth   /*                                                                       */
3731*37da2899SCharles.Forsyth   /* ABS[]:        ABSolute value                                          */
3732*37da2899SCharles.Forsyth   /* Opcode range: 0x64                                                    */
3733*37da2899SCharles.Forsyth   /* Stack:        f26.6 --> f26.6                                         */
3734*37da2899SCharles.Forsyth   /*                                                                       */
3735*37da2899SCharles.Forsyth   static void
Ins_ABS(INS_ARG)3736*37da2899SCharles.Forsyth   Ins_ABS( INS_ARG )
3737*37da2899SCharles.Forsyth   {
3738*37da2899SCharles.Forsyth     DO_ABS
3739*37da2899SCharles.Forsyth   }
3740*37da2899SCharles.Forsyth 
3741*37da2899SCharles.Forsyth 
3742*37da2899SCharles.Forsyth   /*************************************************************************/
3743*37da2899SCharles.Forsyth   /*                                                                       */
3744*37da2899SCharles.Forsyth   /* NEG[]:        NEGate                                                  */
3745*37da2899SCharles.Forsyth   /* Opcode range: 0x65                                                    */
3746*37da2899SCharles.Forsyth   /* Stack: f26.6 --> f26.6                                                */
3747*37da2899SCharles.Forsyth   /*                                                                       */
3748*37da2899SCharles.Forsyth   static void
Ins_NEG(INS_ARG)3749*37da2899SCharles.Forsyth   Ins_NEG( INS_ARG )
3750*37da2899SCharles.Forsyth   {
3751*37da2899SCharles.Forsyth     DO_NEG
3752*37da2899SCharles.Forsyth   }
3753*37da2899SCharles.Forsyth 
3754*37da2899SCharles.Forsyth 
3755*37da2899SCharles.Forsyth   /*************************************************************************/
3756*37da2899SCharles.Forsyth   /*                                                                       */
3757*37da2899SCharles.Forsyth   /* FLOOR[]:      FLOOR                                                   */
3758*37da2899SCharles.Forsyth   /* Opcode range: 0x66                                                    */
3759*37da2899SCharles.Forsyth   /* Stack:        f26.6 --> f26.6                                         */
3760*37da2899SCharles.Forsyth   /*                                                                       */
3761*37da2899SCharles.Forsyth   static void
Ins_FLOOR(INS_ARG)3762*37da2899SCharles.Forsyth   Ins_FLOOR( INS_ARG )
3763*37da2899SCharles.Forsyth   {
3764*37da2899SCharles.Forsyth     DO_FLOOR
3765*37da2899SCharles.Forsyth   }
3766*37da2899SCharles.Forsyth 
3767*37da2899SCharles.Forsyth 
3768*37da2899SCharles.Forsyth   /*************************************************************************/
3769*37da2899SCharles.Forsyth   /*                                                                       */
3770*37da2899SCharles.Forsyth   /* CEILING[]:    CEILING                                                 */
3771*37da2899SCharles.Forsyth   /* Opcode range: 0x67                                                    */
3772*37da2899SCharles.Forsyth   /* Stack:        f26.6 --> f26.6                                         */
3773*37da2899SCharles.Forsyth   /*                                                                       */
3774*37da2899SCharles.Forsyth   static void
Ins_CEILING(INS_ARG)3775*37da2899SCharles.Forsyth   Ins_CEILING( INS_ARG )
3776*37da2899SCharles.Forsyth   {
3777*37da2899SCharles.Forsyth     DO_CEILING
3778*37da2899SCharles.Forsyth   }
3779*37da2899SCharles.Forsyth 
3780*37da2899SCharles.Forsyth 
3781*37da2899SCharles.Forsyth   /*************************************************************************/
3782*37da2899SCharles.Forsyth   /*                                                                       */
3783*37da2899SCharles.Forsyth   /* RS[]:         Read Store                                              */
3784*37da2899SCharles.Forsyth   /* Opcode range: 0x43                                                    */
3785*37da2899SCharles.Forsyth   /* Stack:        uint32 --> uint32                                       */
3786*37da2899SCharles.Forsyth   /*                                                                       */
3787*37da2899SCharles.Forsyth   static void
Ins_RS(INS_ARG)3788*37da2899SCharles.Forsyth   Ins_RS( INS_ARG )
3789*37da2899SCharles.Forsyth   {
3790*37da2899SCharles.Forsyth     DO_RS
3791*37da2899SCharles.Forsyth   }
3792*37da2899SCharles.Forsyth 
3793*37da2899SCharles.Forsyth 
3794*37da2899SCharles.Forsyth   /*************************************************************************/
3795*37da2899SCharles.Forsyth   /*                                                                       */
3796*37da2899SCharles.Forsyth   /* WS[]:         Write Store                                             */
3797*37da2899SCharles.Forsyth   /* Opcode range: 0x42                                                    */
3798*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
3799*37da2899SCharles.Forsyth   /*                                                                       */
3800*37da2899SCharles.Forsyth   static void
Ins_WS(INS_ARG)3801*37da2899SCharles.Forsyth   Ins_WS( INS_ARG )
3802*37da2899SCharles.Forsyth   {
3803*37da2899SCharles.Forsyth     DO_WS
3804*37da2899SCharles.Forsyth   }
3805*37da2899SCharles.Forsyth 
3806*37da2899SCharles.Forsyth 
3807*37da2899SCharles.Forsyth   /*************************************************************************/
3808*37da2899SCharles.Forsyth   /*                                                                       */
3809*37da2899SCharles.Forsyth   /* WCVTP[]:      Write CVT in Pixel units                                */
3810*37da2899SCharles.Forsyth   /* Opcode range: 0x44                                                    */
3811*37da2899SCharles.Forsyth   /* Stack:        f26.6 uint32 -->                                        */
3812*37da2899SCharles.Forsyth   /*                                                                       */
3813*37da2899SCharles.Forsyth   static void
Ins_WCVTP(INS_ARG)3814*37da2899SCharles.Forsyth   Ins_WCVTP( INS_ARG )
3815*37da2899SCharles.Forsyth   {
3816*37da2899SCharles.Forsyth     DO_WCVTP
3817*37da2899SCharles.Forsyth   }
3818*37da2899SCharles.Forsyth 
3819*37da2899SCharles.Forsyth 
3820*37da2899SCharles.Forsyth   /*************************************************************************/
3821*37da2899SCharles.Forsyth   /*                                                                       */
3822*37da2899SCharles.Forsyth   /* WCVTF[]:      Write CVT in Funits                                     */
3823*37da2899SCharles.Forsyth   /* Opcode range: 0x70                                                    */
3824*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
3825*37da2899SCharles.Forsyth   /*                                                                       */
3826*37da2899SCharles.Forsyth   static void
Ins_WCVTF(INS_ARG)3827*37da2899SCharles.Forsyth   Ins_WCVTF( INS_ARG )
3828*37da2899SCharles.Forsyth   {
3829*37da2899SCharles.Forsyth     DO_WCVTF
3830*37da2899SCharles.Forsyth   }
3831*37da2899SCharles.Forsyth 
3832*37da2899SCharles.Forsyth 
3833*37da2899SCharles.Forsyth   /*************************************************************************/
3834*37da2899SCharles.Forsyth   /*                                                                       */
3835*37da2899SCharles.Forsyth   /* RCVT[]:       Read CVT                                                */
3836*37da2899SCharles.Forsyth   /* Opcode range: 0x45                                                    */
3837*37da2899SCharles.Forsyth   /* Stack:        uint32 --> f26.6                                        */
3838*37da2899SCharles.Forsyth   /*                                                                       */
3839*37da2899SCharles.Forsyth   static void
Ins_RCVT(INS_ARG)3840*37da2899SCharles.Forsyth   Ins_RCVT( INS_ARG )
3841*37da2899SCharles.Forsyth   {
3842*37da2899SCharles.Forsyth     DO_RCVT
3843*37da2899SCharles.Forsyth   }
3844*37da2899SCharles.Forsyth 
3845*37da2899SCharles.Forsyth 
3846*37da2899SCharles.Forsyth   /*************************************************************************/
3847*37da2899SCharles.Forsyth   /*                                                                       */
3848*37da2899SCharles.Forsyth   /* AA[]:         Adjust Angle                                            */
3849*37da2899SCharles.Forsyth   /* Opcode range: 0x7F                                                    */
3850*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3851*37da2899SCharles.Forsyth   /*                                                                       */
3852*37da2899SCharles.Forsyth   static void
Ins_AA(INS_ARG)3853*37da2899SCharles.Forsyth   Ins_AA( INS_ARG )
3854*37da2899SCharles.Forsyth   {
3855*37da2899SCharles.Forsyth     /* intentionally no longer supported */
3856*37da2899SCharles.Forsyth   }
3857*37da2899SCharles.Forsyth 
3858*37da2899SCharles.Forsyth 
3859*37da2899SCharles.Forsyth   /*************************************************************************/
3860*37da2899SCharles.Forsyth   /*                                                                       */
3861*37da2899SCharles.Forsyth   /* DEBUG[]:      DEBUG.  Unsupported.                                    */
3862*37da2899SCharles.Forsyth   /* Opcode range: 0x4F                                                    */
3863*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
3864*37da2899SCharles.Forsyth   /*                                                                       */
3865*37da2899SCharles.Forsyth   /* Note: The original instruction pops a value from the stack.           */
3866*37da2899SCharles.Forsyth   /*                                                                       */
3867*37da2899SCharles.Forsyth   static void
Ins_DEBUG(INS_ARG)3868*37da2899SCharles.Forsyth   Ins_DEBUG( INS_ARG )
3869*37da2899SCharles.Forsyth   {
3870*37da2899SCharles.Forsyth     DO_DEBUG
3871*37da2899SCharles.Forsyth   }
3872*37da2899SCharles.Forsyth 
3873*37da2899SCharles.Forsyth 
3874*37da2899SCharles.Forsyth   /*************************************************************************/
3875*37da2899SCharles.Forsyth   /*                                                                       */
3876*37da2899SCharles.Forsyth   /* ROUND[ab]:    ROUND value                                             */
3877*37da2899SCharles.Forsyth   /* Opcode range: 0x68-0x6B                                               */
3878*37da2899SCharles.Forsyth   /* Stack:        f26.6 --> f26.6                                         */
3879*37da2899SCharles.Forsyth   /*                                                                       */
3880*37da2899SCharles.Forsyth   static void
Ins_ROUND(INS_ARG)3881*37da2899SCharles.Forsyth   Ins_ROUND( INS_ARG )
3882*37da2899SCharles.Forsyth   {
3883*37da2899SCharles.Forsyth     DO_ROUND
3884*37da2899SCharles.Forsyth   }
3885*37da2899SCharles.Forsyth 
3886*37da2899SCharles.Forsyth 
3887*37da2899SCharles.Forsyth   /*************************************************************************/
3888*37da2899SCharles.Forsyth   /*                                                                       */
3889*37da2899SCharles.Forsyth   /* NROUND[ab]:   No ROUNDing of value                                    */
3890*37da2899SCharles.Forsyth   /* Opcode range: 0x6C-0x6F                                               */
3891*37da2899SCharles.Forsyth   /* Stack:        f26.6 --> f26.6                                         */
3892*37da2899SCharles.Forsyth   /*                                                                       */
3893*37da2899SCharles.Forsyth   static void
Ins_NROUND(INS_ARG)3894*37da2899SCharles.Forsyth   Ins_NROUND( INS_ARG )
3895*37da2899SCharles.Forsyth   {
3896*37da2899SCharles.Forsyth     DO_NROUND
3897*37da2899SCharles.Forsyth   }
3898*37da2899SCharles.Forsyth 
3899*37da2899SCharles.Forsyth 
3900*37da2899SCharles.Forsyth   /*************************************************************************/
3901*37da2899SCharles.Forsyth   /*                                                                       */
3902*37da2899SCharles.Forsyth   /* MAX[]:        MAXimum                                                 */
3903*37da2899SCharles.Forsyth   /* Opcode range: 0x68                                                    */
3904*37da2899SCharles.Forsyth   /* Stack:        int32? int32? --> int32                                 */
3905*37da2899SCharles.Forsyth   /*                                                                       */
3906*37da2899SCharles.Forsyth   static void
Ins_MAX(INS_ARG)3907*37da2899SCharles.Forsyth   Ins_MAX( INS_ARG )
3908*37da2899SCharles.Forsyth   {
3909*37da2899SCharles.Forsyth     DO_MAX
3910*37da2899SCharles.Forsyth   }
3911*37da2899SCharles.Forsyth 
3912*37da2899SCharles.Forsyth 
3913*37da2899SCharles.Forsyth   /*************************************************************************/
3914*37da2899SCharles.Forsyth   /*                                                                       */
3915*37da2899SCharles.Forsyth   /* MIN[]:        MINimum                                                 */
3916*37da2899SCharles.Forsyth   /* Opcode range: 0x69                                                    */
3917*37da2899SCharles.Forsyth   /* Stack:        int32? int32? --> int32                                 */
3918*37da2899SCharles.Forsyth   /*                                                                       */
3919*37da2899SCharles.Forsyth   static void
Ins_MIN(INS_ARG)3920*37da2899SCharles.Forsyth   Ins_MIN( INS_ARG )
3921*37da2899SCharles.Forsyth   {
3922*37da2899SCharles.Forsyth     DO_MIN
3923*37da2899SCharles.Forsyth   }
3924*37da2899SCharles.Forsyth 
3925*37da2899SCharles.Forsyth 
3926*37da2899SCharles.Forsyth #endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
3927*37da2899SCharles.Forsyth 
3928*37da2899SCharles.Forsyth 
3929*37da2899SCharles.Forsyth   /*************************************************************************/
3930*37da2899SCharles.Forsyth   /*                                                                       */
3931*37da2899SCharles.Forsyth   /* The following functions are called as is within the switch statement. */
3932*37da2899SCharles.Forsyth   /*                                                                       */
3933*37da2899SCharles.Forsyth   /*************************************************************************/
3934*37da2899SCharles.Forsyth 
3935*37da2899SCharles.Forsyth 
3936*37da2899SCharles.Forsyth   /*************************************************************************/
3937*37da2899SCharles.Forsyth   /*                                                                       */
3938*37da2899SCharles.Forsyth   /* MINDEX[]:     Move INDEXed element                                    */
3939*37da2899SCharles.Forsyth   /* Opcode range: 0x26                                                    */
3940*37da2899SCharles.Forsyth   /* Stack:        int32? --> StkElt                                       */
3941*37da2899SCharles.Forsyth   /*                                                                       */
3942*37da2899SCharles.Forsyth   static void
Ins_MINDEX(INS_ARG)3943*37da2899SCharles.Forsyth   Ins_MINDEX( INS_ARG )
3944*37da2899SCharles.Forsyth   {
3945*37da2899SCharles.Forsyth     FT_Long  L, K;
3946*37da2899SCharles.Forsyth 
3947*37da2899SCharles.Forsyth 
3948*37da2899SCharles.Forsyth     L = args[0];
3949*37da2899SCharles.Forsyth 
3950*37da2899SCharles.Forsyth     if ( L <= 0 || L > CUR.args )
3951*37da2899SCharles.Forsyth     {
3952*37da2899SCharles.Forsyth       CUR.error = TT_Err_Invalid_Reference;
3953*37da2899SCharles.Forsyth       return;
3954*37da2899SCharles.Forsyth     }
3955*37da2899SCharles.Forsyth 
3956*37da2899SCharles.Forsyth     K = CUR.stack[CUR.args - L];
3957*37da2899SCharles.Forsyth 
3958*37da2899SCharles.Forsyth     FT_MEM_MOVE( &CUR.stack[CUR.args - L    ],
3959*37da2899SCharles.Forsyth                  &CUR.stack[CUR.args - L + 1],
3960*37da2899SCharles.Forsyth                  ( L - 1 ) * sizeof ( FT_Long ) );
3961*37da2899SCharles.Forsyth 
3962*37da2899SCharles.Forsyth     CUR.stack[CUR.args - 1] = K;
3963*37da2899SCharles.Forsyth   }
3964*37da2899SCharles.Forsyth 
3965*37da2899SCharles.Forsyth 
3966*37da2899SCharles.Forsyth   /*************************************************************************/
3967*37da2899SCharles.Forsyth   /*                                                                       */
3968*37da2899SCharles.Forsyth   /* ROLL[]:       ROLL top three elements                                 */
3969*37da2899SCharles.Forsyth   /* Opcode range: 0x8A                                                    */
3970*37da2899SCharles.Forsyth   /* Stack:        3 * StkElt --> 3 * StkElt                               */
3971*37da2899SCharles.Forsyth   /*                                                                       */
3972*37da2899SCharles.Forsyth   static void
Ins_ROLL(INS_ARG)3973*37da2899SCharles.Forsyth   Ins_ROLL( INS_ARG )
3974*37da2899SCharles.Forsyth   {
3975*37da2899SCharles.Forsyth     FT_Long  A, B, C;
3976*37da2899SCharles.Forsyth 
3977*37da2899SCharles.Forsyth     FT_UNUSED_EXEC;
3978*37da2899SCharles.Forsyth 
3979*37da2899SCharles.Forsyth 
3980*37da2899SCharles.Forsyth     A = args[2];
3981*37da2899SCharles.Forsyth     B = args[1];
3982*37da2899SCharles.Forsyth     C = args[0];
3983*37da2899SCharles.Forsyth 
3984*37da2899SCharles.Forsyth     args[2] = C;
3985*37da2899SCharles.Forsyth     args[1] = A;
3986*37da2899SCharles.Forsyth     args[0] = B;
3987*37da2899SCharles.Forsyth   }
3988*37da2899SCharles.Forsyth 
3989*37da2899SCharles.Forsyth 
3990*37da2899SCharles.Forsyth   /*************************************************************************/
3991*37da2899SCharles.Forsyth   /*                                                                       */
3992*37da2899SCharles.Forsyth   /* MANAGING THE FLOW OF CONTROL                                          */
3993*37da2899SCharles.Forsyth   /*                                                                       */
3994*37da2899SCharles.Forsyth   /*   Instructions appear in the specification's order.                   */
3995*37da2899SCharles.Forsyth   /*                                                                       */
3996*37da2899SCharles.Forsyth   /*************************************************************************/
3997*37da2899SCharles.Forsyth 
3998*37da2899SCharles.Forsyth 
3999*37da2899SCharles.Forsyth   static FT_Bool
SkipCode(EXEC_OP)4000*37da2899SCharles.Forsyth   SkipCode( EXEC_OP )
4001*37da2899SCharles.Forsyth   {
4002*37da2899SCharles.Forsyth     CUR.IP += CUR.length;
4003*37da2899SCharles.Forsyth 
4004*37da2899SCharles.Forsyth     if ( CUR.IP < CUR.codeSize )
4005*37da2899SCharles.Forsyth     {
4006*37da2899SCharles.Forsyth       CUR.opcode = CUR.code[CUR.IP];
4007*37da2899SCharles.Forsyth 
4008*37da2899SCharles.Forsyth       CUR.length = opcode_length[CUR.opcode];
4009*37da2899SCharles.Forsyth       if ( CUR.length < 0 )
4010*37da2899SCharles.Forsyth       {
4011*37da2899SCharles.Forsyth         if ( CUR.IP + 1 > CUR.codeSize )
4012*37da2899SCharles.Forsyth           goto Fail_Overflow;
4013*37da2899SCharles.Forsyth         CUR.length = CUR.code[CUR.IP + 1] + 2;
4014*37da2899SCharles.Forsyth       }
4015*37da2899SCharles.Forsyth 
4016*37da2899SCharles.Forsyth       if ( CUR.IP + CUR.length <= CUR.codeSize )
4017*37da2899SCharles.Forsyth         return SUCCESS;
4018*37da2899SCharles.Forsyth     }
4019*37da2899SCharles.Forsyth 
4020*37da2899SCharles.Forsyth   Fail_Overflow:
4021*37da2899SCharles.Forsyth     CUR.error = TT_Err_Code_Overflow;
4022*37da2899SCharles.Forsyth     return FAILURE;
4023*37da2899SCharles.Forsyth   }
4024*37da2899SCharles.Forsyth 
4025*37da2899SCharles.Forsyth 
4026*37da2899SCharles.Forsyth   /*************************************************************************/
4027*37da2899SCharles.Forsyth   /*                                                                       */
4028*37da2899SCharles.Forsyth   /* IF[]:         IF test                                                 */
4029*37da2899SCharles.Forsyth   /* Opcode range: 0x58                                                    */
4030*37da2899SCharles.Forsyth   /* Stack:        StkElt -->                                              */
4031*37da2899SCharles.Forsyth   /*                                                                       */
4032*37da2899SCharles.Forsyth   static void
Ins_IF(INS_ARG)4033*37da2899SCharles.Forsyth   Ins_IF( INS_ARG )
4034*37da2899SCharles.Forsyth   {
4035*37da2899SCharles.Forsyth     FT_Int   nIfs;
4036*37da2899SCharles.Forsyth     FT_Bool  Out;
4037*37da2899SCharles.Forsyth 
4038*37da2899SCharles.Forsyth 
4039*37da2899SCharles.Forsyth     if ( args[0] != 0 )
4040*37da2899SCharles.Forsyth       return;
4041*37da2899SCharles.Forsyth 
4042*37da2899SCharles.Forsyth     nIfs = 1;
4043*37da2899SCharles.Forsyth     Out = 0;
4044*37da2899SCharles.Forsyth 
4045*37da2899SCharles.Forsyth     do
4046*37da2899SCharles.Forsyth     {
4047*37da2899SCharles.Forsyth       if ( SKIP_Code() == FAILURE )
4048*37da2899SCharles.Forsyth         return;
4049*37da2899SCharles.Forsyth 
4050*37da2899SCharles.Forsyth       switch ( CUR.opcode )
4051*37da2899SCharles.Forsyth       {
4052*37da2899SCharles.Forsyth       case 0x58:      /* IF */
4053*37da2899SCharles.Forsyth         nIfs++;
4054*37da2899SCharles.Forsyth         break;
4055*37da2899SCharles.Forsyth 
4056*37da2899SCharles.Forsyth       case 0x1B:      /* ELSE */
4057*37da2899SCharles.Forsyth         Out = FT_BOOL( nIfs == 1 );
4058*37da2899SCharles.Forsyth         break;
4059*37da2899SCharles.Forsyth 
4060*37da2899SCharles.Forsyth       case 0x59:      /* EIF */
4061*37da2899SCharles.Forsyth         nIfs--;
4062*37da2899SCharles.Forsyth         Out = FT_BOOL( nIfs == 0 );
4063*37da2899SCharles.Forsyth         break;
4064*37da2899SCharles.Forsyth       }
4065*37da2899SCharles.Forsyth     } while ( Out == 0 );
4066*37da2899SCharles.Forsyth   }
4067*37da2899SCharles.Forsyth 
4068*37da2899SCharles.Forsyth 
4069*37da2899SCharles.Forsyth   /*************************************************************************/
4070*37da2899SCharles.Forsyth   /*                                                                       */
4071*37da2899SCharles.Forsyth   /* ELSE[]:       ELSE                                                    */
4072*37da2899SCharles.Forsyth   /* Opcode range: 0x1B                                                    */
4073*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
4074*37da2899SCharles.Forsyth   /*                                                                       */
4075*37da2899SCharles.Forsyth   static void
Ins_ELSE(INS_ARG)4076*37da2899SCharles.Forsyth   Ins_ELSE( INS_ARG )
4077*37da2899SCharles.Forsyth   {
4078*37da2899SCharles.Forsyth     FT_Int  nIfs;
4079*37da2899SCharles.Forsyth 
4080*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
4081*37da2899SCharles.Forsyth 
4082*37da2899SCharles.Forsyth 
4083*37da2899SCharles.Forsyth     nIfs = 1;
4084*37da2899SCharles.Forsyth 
4085*37da2899SCharles.Forsyth     do
4086*37da2899SCharles.Forsyth     {
4087*37da2899SCharles.Forsyth       if ( SKIP_Code() == FAILURE )
4088*37da2899SCharles.Forsyth         return;
4089*37da2899SCharles.Forsyth 
4090*37da2899SCharles.Forsyth       switch ( CUR.opcode )
4091*37da2899SCharles.Forsyth       {
4092*37da2899SCharles.Forsyth       case 0x58:    /* IF */
4093*37da2899SCharles.Forsyth         nIfs++;
4094*37da2899SCharles.Forsyth         break;
4095*37da2899SCharles.Forsyth 
4096*37da2899SCharles.Forsyth       case 0x59:    /* EIF */
4097*37da2899SCharles.Forsyth         nIfs--;
4098*37da2899SCharles.Forsyth         break;
4099*37da2899SCharles.Forsyth       }
4100*37da2899SCharles.Forsyth     } while ( nIfs != 0 );
4101*37da2899SCharles.Forsyth   }
4102*37da2899SCharles.Forsyth 
4103*37da2899SCharles.Forsyth 
4104*37da2899SCharles.Forsyth   /*************************************************************************/
4105*37da2899SCharles.Forsyth   /*                                                                       */
4106*37da2899SCharles.Forsyth   /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
4107*37da2899SCharles.Forsyth   /*                                                                       */
4108*37da2899SCharles.Forsyth   /*   Instructions appear in the specification's order.                   */
4109*37da2899SCharles.Forsyth   /*                                                                       */
4110*37da2899SCharles.Forsyth   /*************************************************************************/
4111*37da2899SCharles.Forsyth 
4112*37da2899SCharles.Forsyth 
4113*37da2899SCharles.Forsyth   /*************************************************************************/
4114*37da2899SCharles.Forsyth   /*                                                                       */
4115*37da2899SCharles.Forsyth   /* FDEF[]:       Function DEFinition                                     */
4116*37da2899SCharles.Forsyth   /* Opcode range: 0x2C                                                    */
4117*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
4118*37da2899SCharles.Forsyth   /*                                                                       */
4119*37da2899SCharles.Forsyth   static void
Ins_FDEF(INS_ARG)4120*37da2899SCharles.Forsyth   Ins_FDEF( INS_ARG )
4121*37da2899SCharles.Forsyth   {
4122*37da2899SCharles.Forsyth     FT_ULong       n;
4123*37da2899SCharles.Forsyth     TT_DefRecord*  rec;
4124*37da2899SCharles.Forsyth     TT_DefRecord*  limit;
4125*37da2899SCharles.Forsyth 
4126*37da2899SCharles.Forsyth 
4127*37da2899SCharles.Forsyth     /* some font programs are broken enough to redefine functions! */
4128*37da2899SCharles.Forsyth     /* We will then parse the current table.                       */
4129*37da2899SCharles.Forsyth 
4130*37da2899SCharles.Forsyth     rec   = CUR.FDefs;
4131*37da2899SCharles.Forsyth     limit = rec + CUR.numFDefs;
4132*37da2899SCharles.Forsyth     n     = args[0];
4133*37da2899SCharles.Forsyth 
4134*37da2899SCharles.Forsyth     for ( ; rec < limit; rec++ )
4135*37da2899SCharles.Forsyth     {
4136*37da2899SCharles.Forsyth       if ( rec->opc == n )
4137*37da2899SCharles.Forsyth         break;
4138*37da2899SCharles.Forsyth     }
4139*37da2899SCharles.Forsyth 
4140*37da2899SCharles.Forsyth     if ( rec == limit )
4141*37da2899SCharles.Forsyth     {
4142*37da2899SCharles.Forsyth       /* check that there is enough room for new functions */
4143*37da2899SCharles.Forsyth       if ( CUR.numFDefs >= CUR.maxFDefs )
4144*37da2899SCharles.Forsyth       {
4145*37da2899SCharles.Forsyth         CUR.error = TT_Err_Too_Many_Function_Defs;
4146*37da2899SCharles.Forsyth         return;
4147*37da2899SCharles.Forsyth       }
4148*37da2899SCharles.Forsyth       CUR.numFDefs++;
4149*37da2899SCharles.Forsyth     }
4150*37da2899SCharles.Forsyth 
4151*37da2899SCharles.Forsyth     rec->range  = CUR.curRange;
4152*37da2899SCharles.Forsyth     rec->opc    = n;
4153*37da2899SCharles.Forsyth     rec->start  = CUR.IP + 1;
4154*37da2899SCharles.Forsyth     rec->active = TRUE;
4155*37da2899SCharles.Forsyth 
4156*37da2899SCharles.Forsyth     if ( n > CUR.maxFunc )
4157*37da2899SCharles.Forsyth       CUR.maxFunc = n;
4158*37da2899SCharles.Forsyth 
4159*37da2899SCharles.Forsyth     /* Now skip the whole function definition. */
4160*37da2899SCharles.Forsyth     /* We don't allow nested IDEFS & FDEFs.    */
4161*37da2899SCharles.Forsyth 
4162*37da2899SCharles.Forsyth     while ( SKIP_Code() == SUCCESS )
4163*37da2899SCharles.Forsyth     {
4164*37da2899SCharles.Forsyth       switch ( CUR.opcode )
4165*37da2899SCharles.Forsyth       {
4166*37da2899SCharles.Forsyth       case 0x89:    /* IDEF */
4167*37da2899SCharles.Forsyth       case 0x2C:    /* FDEF */
4168*37da2899SCharles.Forsyth         CUR.error = TT_Err_Nested_DEFS;
4169*37da2899SCharles.Forsyth         return;
4170*37da2899SCharles.Forsyth 
4171*37da2899SCharles.Forsyth       case 0x2D:   /* ENDF */
4172*37da2899SCharles.Forsyth         return;
4173*37da2899SCharles.Forsyth       }
4174*37da2899SCharles.Forsyth     }
4175*37da2899SCharles.Forsyth   }
4176*37da2899SCharles.Forsyth 
4177*37da2899SCharles.Forsyth 
4178*37da2899SCharles.Forsyth   /*************************************************************************/
4179*37da2899SCharles.Forsyth   /*                                                                       */
4180*37da2899SCharles.Forsyth   /* ENDF[]:       END Function definition                                 */
4181*37da2899SCharles.Forsyth   /* Opcode range: 0x2D                                                    */
4182*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
4183*37da2899SCharles.Forsyth   /*                                                                       */
4184*37da2899SCharles.Forsyth   static void
Ins_ENDF(INS_ARG)4185*37da2899SCharles.Forsyth   Ins_ENDF( INS_ARG )
4186*37da2899SCharles.Forsyth   {
4187*37da2899SCharles.Forsyth     TT_CallRec*  pRec;
4188*37da2899SCharles.Forsyth 
4189*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
4190*37da2899SCharles.Forsyth 
4191*37da2899SCharles.Forsyth 
4192*37da2899SCharles.Forsyth     if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
4193*37da2899SCharles.Forsyth     {
4194*37da2899SCharles.Forsyth       CUR.error = TT_Err_ENDF_In_Exec_Stream;
4195*37da2899SCharles.Forsyth       return;
4196*37da2899SCharles.Forsyth     }
4197*37da2899SCharles.Forsyth 
4198*37da2899SCharles.Forsyth     CUR.callTop--;
4199*37da2899SCharles.Forsyth 
4200*37da2899SCharles.Forsyth     pRec = &CUR.callStack[CUR.callTop];
4201*37da2899SCharles.Forsyth 
4202*37da2899SCharles.Forsyth     pRec->Cur_Count--;
4203*37da2899SCharles.Forsyth 
4204*37da2899SCharles.Forsyth     CUR.step_ins = FALSE;
4205*37da2899SCharles.Forsyth 
4206*37da2899SCharles.Forsyth     if ( pRec->Cur_Count > 0 )
4207*37da2899SCharles.Forsyth     {
4208*37da2899SCharles.Forsyth       CUR.callTop++;
4209*37da2899SCharles.Forsyth       CUR.IP = pRec->Cur_Restart;
4210*37da2899SCharles.Forsyth     }
4211*37da2899SCharles.Forsyth     else
4212*37da2899SCharles.Forsyth       /* Loop through the current function */
4213*37da2899SCharles.Forsyth       INS_Goto_CodeRange( pRec->Caller_Range,
4214*37da2899SCharles.Forsyth                           pRec->Caller_IP );
4215*37da2899SCharles.Forsyth 
4216*37da2899SCharles.Forsyth     /* Exit the current call frame.                      */
4217*37da2899SCharles.Forsyth 
4218*37da2899SCharles.Forsyth     /* NOTE: If the last intruction of a program is a    */
4219*37da2899SCharles.Forsyth     /*       CALL or LOOPCALL, the return address is     */
4220*37da2899SCharles.Forsyth     /*       always out of the code range.  This is a    */
4221*37da2899SCharles.Forsyth     /*       valid address, and it is why we do not test */
4222*37da2899SCharles.Forsyth     /*       the result of Ins_Goto_CodeRange() here!    */
4223*37da2899SCharles.Forsyth   }
4224*37da2899SCharles.Forsyth 
4225*37da2899SCharles.Forsyth 
4226*37da2899SCharles.Forsyth   /*************************************************************************/
4227*37da2899SCharles.Forsyth   /*                                                                       */
4228*37da2899SCharles.Forsyth   /* CALL[]:       CALL function                                           */
4229*37da2899SCharles.Forsyth   /* Opcode range: 0x2B                                                    */
4230*37da2899SCharles.Forsyth   /* Stack:        uint32? -->                                             */
4231*37da2899SCharles.Forsyth   /*                                                                       */
4232*37da2899SCharles.Forsyth   static void
Ins_CALL(INS_ARG)4233*37da2899SCharles.Forsyth   Ins_CALL( INS_ARG )
4234*37da2899SCharles.Forsyth   {
4235*37da2899SCharles.Forsyth     FT_ULong       F;
4236*37da2899SCharles.Forsyth     TT_CallRec*    pCrec;
4237*37da2899SCharles.Forsyth     TT_DefRecord*  def;
4238*37da2899SCharles.Forsyth 
4239*37da2899SCharles.Forsyth 
4240*37da2899SCharles.Forsyth     /* first of all, check the index */
4241*37da2899SCharles.Forsyth 
4242*37da2899SCharles.Forsyth     F = args[0];
4243*37da2899SCharles.Forsyth     if ( BOUNDS( F, CUR.maxFunc + 1 ) )
4244*37da2899SCharles.Forsyth       goto Fail;
4245*37da2899SCharles.Forsyth 
4246*37da2899SCharles.Forsyth     /* Except for some old Apple fonts, all functions in a TrueType */
4247*37da2899SCharles.Forsyth     /* font are defined in increasing order, starting from 0.  This */
4248*37da2899SCharles.Forsyth     /* means that we normally have                                  */
4249*37da2899SCharles.Forsyth     /*                                                              */
4250*37da2899SCharles.Forsyth     /*    CUR.maxFunc+1 == CUR.numFDefs                             */
4251*37da2899SCharles.Forsyth     /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
4252*37da2899SCharles.Forsyth     /*                                                              */
4253*37da2899SCharles.Forsyth     /* If this isn't true, we need to look up the function table.   */
4254*37da2899SCharles.Forsyth 
4255*37da2899SCharles.Forsyth     def = CUR.FDefs + F;
4256*37da2899SCharles.Forsyth     if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
4257*37da2899SCharles.Forsyth     {
4258*37da2899SCharles.Forsyth       /* look up the FDefs table */
4259*37da2899SCharles.Forsyth       TT_DefRecord*  limit;
4260*37da2899SCharles.Forsyth 
4261*37da2899SCharles.Forsyth 
4262*37da2899SCharles.Forsyth       def   = CUR.FDefs;
4263*37da2899SCharles.Forsyth       limit = def + CUR.numFDefs;
4264*37da2899SCharles.Forsyth 
4265*37da2899SCharles.Forsyth       while ( def < limit && def->opc != F )
4266*37da2899SCharles.Forsyth         def++;
4267*37da2899SCharles.Forsyth 
4268*37da2899SCharles.Forsyth       if ( def == limit )
4269*37da2899SCharles.Forsyth         goto Fail;
4270*37da2899SCharles.Forsyth     }
4271*37da2899SCharles.Forsyth 
4272*37da2899SCharles.Forsyth     /* check that the function is active */
4273*37da2899SCharles.Forsyth     if ( !def->active )
4274*37da2899SCharles.Forsyth       goto Fail;
4275*37da2899SCharles.Forsyth 
4276*37da2899SCharles.Forsyth     /* check the call stack */
4277*37da2899SCharles.Forsyth     if ( CUR.callTop >= CUR.callSize )
4278*37da2899SCharles.Forsyth     {
4279*37da2899SCharles.Forsyth       CUR.error = TT_Err_Stack_Overflow;
4280*37da2899SCharles.Forsyth       return;
4281*37da2899SCharles.Forsyth     }
4282*37da2899SCharles.Forsyth 
4283*37da2899SCharles.Forsyth     pCrec = CUR.callStack + CUR.callTop;
4284*37da2899SCharles.Forsyth 
4285*37da2899SCharles.Forsyth     pCrec->Caller_Range = CUR.curRange;
4286*37da2899SCharles.Forsyth     pCrec->Caller_IP    = CUR.IP + 1;
4287*37da2899SCharles.Forsyth     pCrec->Cur_Count    = 1;
4288*37da2899SCharles.Forsyth     pCrec->Cur_Restart  = def->start;
4289*37da2899SCharles.Forsyth 
4290*37da2899SCharles.Forsyth     CUR.callTop++;
4291*37da2899SCharles.Forsyth 
4292*37da2899SCharles.Forsyth     INS_Goto_CodeRange( def->range,
4293*37da2899SCharles.Forsyth                         def->start );
4294*37da2899SCharles.Forsyth 
4295*37da2899SCharles.Forsyth     CUR.step_ins = FALSE;
4296*37da2899SCharles.Forsyth     return;
4297*37da2899SCharles.Forsyth 
4298*37da2899SCharles.Forsyth   Fail:
4299*37da2899SCharles.Forsyth     CUR.error = TT_Err_Invalid_Reference;
4300*37da2899SCharles.Forsyth   }
4301*37da2899SCharles.Forsyth 
4302*37da2899SCharles.Forsyth 
4303*37da2899SCharles.Forsyth   /*************************************************************************/
4304*37da2899SCharles.Forsyth   /*                                                                       */
4305*37da2899SCharles.Forsyth   /* LOOPCALL[]:   LOOP and CALL function                                  */
4306*37da2899SCharles.Forsyth   /* Opcode range: 0x2A                                                    */
4307*37da2899SCharles.Forsyth   /* Stack:        uint32? Eint16? -->                                     */
4308*37da2899SCharles.Forsyth   /*                                                                       */
4309*37da2899SCharles.Forsyth   static void
Ins_LOOPCALL(INS_ARG)4310*37da2899SCharles.Forsyth   Ins_LOOPCALL( INS_ARG )
4311*37da2899SCharles.Forsyth   {
4312*37da2899SCharles.Forsyth     FT_ULong       F;
4313*37da2899SCharles.Forsyth     TT_CallRec*    pCrec;
4314*37da2899SCharles.Forsyth     TT_DefRecord*  def;
4315*37da2899SCharles.Forsyth 
4316*37da2899SCharles.Forsyth 
4317*37da2899SCharles.Forsyth     /* first of all, check the index */
4318*37da2899SCharles.Forsyth     F = args[1];
4319*37da2899SCharles.Forsyth     if ( BOUNDS( F, CUR.maxFunc + 1 ) )
4320*37da2899SCharles.Forsyth       goto Fail;
4321*37da2899SCharles.Forsyth 
4322*37da2899SCharles.Forsyth     /* Except for some old Apple fonts, all functions in a TrueType */
4323*37da2899SCharles.Forsyth     /* font are defined in increasing order, starting from 0.  This */
4324*37da2899SCharles.Forsyth     /* means that we normally have                                  */
4325*37da2899SCharles.Forsyth     /*                                                              */
4326*37da2899SCharles.Forsyth     /*    CUR.maxFunc+1 == CUR.numFDefs                             */
4327*37da2899SCharles.Forsyth     /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
4328*37da2899SCharles.Forsyth     /*                                                              */
4329*37da2899SCharles.Forsyth     /* If this isn't true, we need to look up the function table.   */
4330*37da2899SCharles.Forsyth 
4331*37da2899SCharles.Forsyth     def = CUR.FDefs + F;
4332*37da2899SCharles.Forsyth     if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
4333*37da2899SCharles.Forsyth     {
4334*37da2899SCharles.Forsyth       /* look up the FDefs table */
4335*37da2899SCharles.Forsyth       TT_DefRecord*  limit;
4336*37da2899SCharles.Forsyth 
4337*37da2899SCharles.Forsyth 
4338*37da2899SCharles.Forsyth       def   = CUR.FDefs;
4339*37da2899SCharles.Forsyth       limit = def + CUR.numFDefs;
4340*37da2899SCharles.Forsyth 
4341*37da2899SCharles.Forsyth       while ( def < limit && def->opc != F )
4342*37da2899SCharles.Forsyth         def++;
4343*37da2899SCharles.Forsyth 
4344*37da2899SCharles.Forsyth       if ( def == limit )
4345*37da2899SCharles.Forsyth         goto Fail;
4346*37da2899SCharles.Forsyth     }
4347*37da2899SCharles.Forsyth 
4348*37da2899SCharles.Forsyth     /* check that the function is active */
4349*37da2899SCharles.Forsyth     if ( !def->active )
4350*37da2899SCharles.Forsyth       goto Fail;
4351*37da2899SCharles.Forsyth 
4352*37da2899SCharles.Forsyth     /* check stack */
4353*37da2899SCharles.Forsyth     if ( CUR.callTop >= CUR.callSize )
4354*37da2899SCharles.Forsyth     {
4355*37da2899SCharles.Forsyth       CUR.error = TT_Err_Stack_Overflow;
4356*37da2899SCharles.Forsyth       return;
4357*37da2899SCharles.Forsyth     }
4358*37da2899SCharles.Forsyth 
4359*37da2899SCharles.Forsyth     if ( args[0] > 0 )
4360*37da2899SCharles.Forsyth     {
4361*37da2899SCharles.Forsyth       pCrec = CUR.callStack + CUR.callTop;
4362*37da2899SCharles.Forsyth 
4363*37da2899SCharles.Forsyth       pCrec->Caller_Range = CUR.curRange;
4364*37da2899SCharles.Forsyth       pCrec->Caller_IP    = CUR.IP + 1;
4365*37da2899SCharles.Forsyth       pCrec->Cur_Count    = (FT_Int)args[0];
4366*37da2899SCharles.Forsyth       pCrec->Cur_Restart  = def->start;
4367*37da2899SCharles.Forsyth 
4368*37da2899SCharles.Forsyth       CUR.callTop++;
4369*37da2899SCharles.Forsyth 
4370*37da2899SCharles.Forsyth       INS_Goto_CodeRange( def->range, def->start );
4371*37da2899SCharles.Forsyth 
4372*37da2899SCharles.Forsyth       CUR.step_ins = FALSE;
4373*37da2899SCharles.Forsyth     }
4374*37da2899SCharles.Forsyth     return;
4375*37da2899SCharles.Forsyth 
4376*37da2899SCharles.Forsyth   Fail:
4377*37da2899SCharles.Forsyth     CUR.error = TT_Err_Invalid_Reference;
4378*37da2899SCharles.Forsyth   }
4379*37da2899SCharles.Forsyth 
4380*37da2899SCharles.Forsyth 
4381*37da2899SCharles.Forsyth   /*************************************************************************/
4382*37da2899SCharles.Forsyth   /*                                                                       */
4383*37da2899SCharles.Forsyth   /* IDEF[]:       Instruction DEFinition                                  */
4384*37da2899SCharles.Forsyth   /* Opcode range: 0x89                                                    */
4385*37da2899SCharles.Forsyth   /* Stack:        Eint8 -->                                               */
4386*37da2899SCharles.Forsyth   /*                                                                       */
4387*37da2899SCharles.Forsyth   static void
Ins_IDEF(INS_ARG)4388*37da2899SCharles.Forsyth   Ins_IDEF( INS_ARG )
4389*37da2899SCharles.Forsyth   {
4390*37da2899SCharles.Forsyth     TT_DefRecord*  def;
4391*37da2899SCharles.Forsyth     TT_DefRecord*  limit;
4392*37da2899SCharles.Forsyth 
4393*37da2899SCharles.Forsyth 
4394*37da2899SCharles.Forsyth     /*  First of all, look for the same function in our table */
4395*37da2899SCharles.Forsyth 
4396*37da2899SCharles.Forsyth     def   = CUR.IDefs;
4397*37da2899SCharles.Forsyth     limit = def + CUR.numIDefs;
4398*37da2899SCharles.Forsyth 
4399*37da2899SCharles.Forsyth     for ( ; def < limit; def++ )
4400*37da2899SCharles.Forsyth       if ( def->opc == (FT_ULong)args[0] )
4401*37da2899SCharles.Forsyth         break;
4402*37da2899SCharles.Forsyth 
4403*37da2899SCharles.Forsyth     if ( def == limit )
4404*37da2899SCharles.Forsyth     {
4405*37da2899SCharles.Forsyth       /* check that there is enough room for a new instruction */
4406*37da2899SCharles.Forsyth       if ( CUR.numIDefs >= CUR.maxIDefs )
4407*37da2899SCharles.Forsyth       {
4408*37da2899SCharles.Forsyth         CUR.error = TT_Err_Too_Many_Instruction_Defs;
4409*37da2899SCharles.Forsyth         return;
4410*37da2899SCharles.Forsyth       }
4411*37da2899SCharles.Forsyth       CUR.numIDefs++;
4412*37da2899SCharles.Forsyth     }
4413*37da2899SCharles.Forsyth 
4414*37da2899SCharles.Forsyth     def->opc    = args[0];
4415*37da2899SCharles.Forsyth     def->start  = CUR.IP+1;
4416*37da2899SCharles.Forsyth     def->range  = CUR.curRange;
4417*37da2899SCharles.Forsyth     def->active = TRUE;
4418*37da2899SCharles.Forsyth 
4419*37da2899SCharles.Forsyth     if ( (FT_ULong)args[0] > CUR.maxIns )
4420*37da2899SCharles.Forsyth       CUR.maxIns = args[0];
4421*37da2899SCharles.Forsyth 
4422*37da2899SCharles.Forsyth     /* Now skip the whole function definition. */
4423*37da2899SCharles.Forsyth     /* We don't allow nested IDEFs & FDEFs.    */
4424*37da2899SCharles.Forsyth 
4425*37da2899SCharles.Forsyth     while ( SKIP_Code() == SUCCESS )
4426*37da2899SCharles.Forsyth     {
4427*37da2899SCharles.Forsyth       switch ( CUR.opcode )
4428*37da2899SCharles.Forsyth       {
4429*37da2899SCharles.Forsyth       case 0x89:   /* IDEF */
4430*37da2899SCharles.Forsyth       case 0x2C:   /* FDEF */
4431*37da2899SCharles.Forsyth         CUR.error = TT_Err_Nested_DEFS;
4432*37da2899SCharles.Forsyth         return;
4433*37da2899SCharles.Forsyth       case 0x2D:   /* ENDF */
4434*37da2899SCharles.Forsyth         return;
4435*37da2899SCharles.Forsyth       }
4436*37da2899SCharles.Forsyth     }
4437*37da2899SCharles.Forsyth   }
4438*37da2899SCharles.Forsyth 
4439*37da2899SCharles.Forsyth 
4440*37da2899SCharles.Forsyth   /*************************************************************************/
4441*37da2899SCharles.Forsyth   /*                                                                       */
4442*37da2899SCharles.Forsyth   /* PUSHING DATA ONTO THE INTERPRETER STACK                               */
4443*37da2899SCharles.Forsyth   /*                                                                       */
4444*37da2899SCharles.Forsyth   /*   Instructions appear in the specification's order.                   */
4445*37da2899SCharles.Forsyth   /*                                                                       */
4446*37da2899SCharles.Forsyth   /*************************************************************************/
4447*37da2899SCharles.Forsyth 
4448*37da2899SCharles.Forsyth 
4449*37da2899SCharles.Forsyth   /*************************************************************************/
4450*37da2899SCharles.Forsyth   /*                                                                       */
4451*37da2899SCharles.Forsyth   /* NPUSHB[]:     PUSH N Bytes                                            */
4452*37da2899SCharles.Forsyth   /* Opcode range: 0x40                                                    */
4453*37da2899SCharles.Forsyth   /* Stack:        --> uint32...                                           */
4454*37da2899SCharles.Forsyth   /*                                                                       */
4455*37da2899SCharles.Forsyth   static void
Ins_NPUSHB(INS_ARG)4456*37da2899SCharles.Forsyth   Ins_NPUSHB( INS_ARG )
4457*37da2899SCharles.Forsyth   {
4458*37da2899SCharles.Forsyth     FT_UShort  L, K;
4459*37da2899SCharles.Forsyth 
4460*37da2899SCharles.Forsyth 
4461*37da2899SCharles.Forsyth     L = (FT_UShort)CUR.code[CUR.IP + 1];
4462*37da2899SCharles.Forsyth 
4463*37da2899SCharles.Forsyth     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4464*37da2899SCharles.Forsyth     {
4465*37da2899SCharles.Forsyth       CUR.error = TT_Err_Stack_Overflow;
4466*37da2899SCharles.Forsyth       return;
4467*37da2899SCharles.Forsyth     }
4468*37da2899SCharles.Forsyth 
4469*37da2899SCharles.Forsyth     for ( K = 1; K <= L; K++ )
4470*37da2899SCharles.Forsyth       args[K - 1] = CUR.code[CUR.IP + K + 1];
4471*37da2899SCharles.Forsyth 
4472*37da2899SCharles.Forsyth     CUR.new_top += L;
4473*37da2899SCharles.Forsyth   }
4474*37da2899SCharles.Forsyth 
4475*37da2899SCharles.Forsyth 
4476*37da2899SCharles.Forsyth   /*************************************************************************/
4477*37da2899SCharles.Forsyth   /*                                                                       */
4478*37da2899SCharles.Forsyth   /* NPUSHW[]:     PUSH N Words                                            */
4479*37da2899SCharles.Forsyth   /* Opcode range: 0x41                                                    */
4480*37da2899SCharles.Forsyth   /* Stack:        --> int32...                                            */
4481*37da2899SCharles.Forsyth   /*                                                                       */
4482*37da2899SCharles.Forsyth   static void
Ins_NPUSHW(INS_ARG)4483*37da2899SCharles.Forsyth   Ins_NPUSHW( INS_ARG )
4484*37da2899SCharles.Forsyth   {
4485*37da2899SCharles.Forsyth     FT_UShort  L, K;
4486*37da2899SCharles.Forsyth 
4487*37da2899SCharles.Forsyth 
4488*37da2899SCharles.Forsyth     L = (FT_UShort)CUR.code[CUR.IP + 1];
4489*37da2899SCharles.Forsyth 
4490*37da2899SCharles.Forsyth     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4491*37da2899SCharles.Forsyth     {
4492*37da2899SCharles.Forsyth       CUR.error = TT_Err_Stack_Overflow;
4493*37da2899SCharles.Forsyth       return;
4494*37da2899SCharles.Forsyth     }
4495*37da2899SCharles.Forsyth 
4496*37da2899SCharles.Forsyth     CUR.IP += 2;
4497*37da2899SCharles.Forsyth 
4498*37da2899SCharles.Forsyth     for ( K = 0; K < L; K++ )
4499*37da2899SCharles.Forsyth       args[K] = GET_ShortIns();
4500*37da2899SCharles.Forsyth 
4501*37da2899SCharles.Forsyth     CUR.step_ins = FALSE;
4502*37da2899SCharles.Forsyth     CUR.new_top += L;
4503*37da2899SCharles.Forsyth   }
4504*37da2899SCharles.Forsyth 
4505*37da2899SCharles.Forsyth 
4506*37da2899SCharles.Forsyth   /*************************************************************************/
4507*37da2899SCharles.Forsyth   /*                                                                       */
4508*37da2899SCharles.Forsyth   /* PUSHB[abc]:   PUSH Bytes                                              */
4509*37da2899SCharles.Forsyth   /* Opcode range: 0xB0-0xB7                                               */
4510*37da2899SCharles.Forsyth   /* Stack:        --> uint32...                                           */
4511*37da2899SCharles.Forsyth   /*                                                                       */
4512*37da2899SCharles.Forsyth   static void
Ins_PUSHB(INS_ARG)4513*37da2899SCharles.Forsyth   Ins_PUSHB( INS_ARG )
4514*37da2899SCharles.Forsyth   {
4515*37da2899SCharles.Forsyth     FT_UShort  L, K;
4516*37da2899SCharles.Forsyth 
4517*37da2899SCharles.Forsyth 
4518*37da2899SCharles.Forsyth     L = (FT_UShort)(CUR.opcode - 0xB0 + 1);
4519*37da2899SCharles.Forsyth 
4520*37da2899SCharles.Forsyth     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4521*37da2899SCharles.Forsyth     {
4522*37da2899SCharles.Forsyth       CUR.error = TT_Err_Stack_Overflow;
4523*37da2899SCharles.Forsyth       return;
4524*37da2899SCharles.Forsyth     }
4525*37da2899SCharles.Forsyth 
4526*37da2899SCharles.Forsyth     for ( K = 1; K <= L; K++ )
4527*37da2899SCharles.Forsyth       args[K - 1] = CUR.code[CUR.IP + K];
4528*37da2899SCharles.Forsyth   }
4529*37da2899SCharles.Forsyth 
4530*37da2899SCharles.Forsyth 
4531*37da2899SCharles.Forsyth   /*************************************************************************/
4532*37da2899SCharles.Forsyth   /*                                                                       */
4533*37da2899SCharles.Forsyth   /* PUSHW[abc]:   PUSH Words                                              */
4534*37da2899SCharles.Forsyth   /* Opcode range: 0xB8-0xBF                                               */
4535*37da2899SCharles.Forsyth   /* Stack:        --> int32...                                            */
4536*37da2899SCharles.Forsyth   /*                                                                       */
4537*37da2899SCharles.Forsyth   static void
Ins_PUSHW(INS_ARG)4538*37da2899SCharles.Forsyth   Ins_PUSHW( INS_ARG )
4539*37da2899SCharles.Forsyth   {
4540*37da2899SCharles.Forsyth     FT_UShort  L, K;
4541*37da2899SCharles.Forsyth 
4542*37da2899SCharles.Forsyth 
4543*37da2899SCharles.Forsyth     L = (FT_UShort)(CUR.opcode - 0xB8 + 1);
4544*37da2899SCharles.Forsyth 
4545*37da2899SCharles.Forsyth     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4546*37da2899SCharles.Forsyth     {
4547*37da2899SCharles.Forsyth       CUR.error = TT_Err_Stack_Overflow;
4548*37da2899SCharles.Forsyth       return;
4549*37da2899SCharles.Forsyth     }
4550*37da2899SCharles.Forsyth 
4551*37da2899SCharles.Forsyth     CUR.IP++;
4552*37da2899SCharles.Forsyth 
4553*37da2899SCharles.Forsyth     for ( K = 0; K < L; K++ )
4554*37da2899SCharles.Forsyth       args[K] = GET_ShortIns();
4555*37da2899SCharles.Forsyth 
4556*37da2899SCharles.Forsyth     CUR.step_ins = FALSE;
4557*37da2899SCharles.Forsyth   }
4558*37da2899SCharles.Forsyth 
4559*37da2899SCharles.Forsyth 
4560*37da2899SCharles.Forsyth   /*************************************************************************/
4561*37da2899SCharles.Forsyth   /*                                                                       */
4562*37da2899SCharles.Forsyth   /* MANAGING THE GRAPHICS STATE                                           */
4563*37da2899SCharles.Forsyth   /*                                                                       */
4564*37da2899SCharles.Forsyth   /*  Instructions appear in the specs' order.                             */
4565*37da2899SCharles.Forsyth   /*                                                                       */
4566*37da2899SCharles.Forsyth   /*************************************************************************/
4567*37da2899SCharles.Forsyth 
4568*37da2899SCharles.Forsyth 
4569*37da2899SCharles.Forsyth   /*************************************************************************/
4570*37da2899SCharles.Forsyth   /*                                                                       */
4571*37da2899SCharles.Forsyth   /* GC[a]:        Get Coordinate projected onto                           */
4572*37da2899SCharles.Forsyth   /* Opcode range: 0x46-0x47                                               */
4573*37da2899SCharles.Forsyth   /* Stack:        uint32 --> f26.6                                        */
4574*37da2899SCharles.Forsyth   /*                                                                       */
4575*37da2899SCharles.Forsyth   /* BULLSHIT: Measures from the original glyph must be taken along the    */
4576*37da2899SCharles.Forsyth   /*           dual projection vector!                                     */
4577*37da2899SCharles.Forsyth   /*                                                                       */
4578*37da2899SCharles.Forsyth   static void
Ins_GC(INS_ARG)4579*37da2899SCharles.Forsyth   Ins_GC( INS_ARG )
4580*37da2899SCharles.Forsyth   {
4581*37da2899SCharles.Forsyth     FT_ULong    L;
4582*37da2899SCharles.Forsyth     FT_F26Dot6  R;
4583*37da2899SCharles.Forsyth 
4584*37da2899SCharles.Forsyth 
4585*37da2899SCharles.Forsyth     L = (FT_ULong)args[0];
4586*37da2899SCharles.Forsyth 
4587*37da2899SCharles.Forsyth     if ( BOUNDS( L, CUR.zp2.n_points ) )
4588*37da2899SCharles.Forsyth     {
4589*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4590*37da2899SCharles.Forsyth       {
4591*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4592*37da2899SCharles.Forsyth         return;
4593*37da2899SCharles.Forsyth       }
4594*37da2899SCharles.Forsyth       else
4595*37da2899SCharles.Forsyth         R = 0;
4596*37da2899SCharles.Forsyth     }
4597*37da2899SCharles.Forsyth     else
4598*37da2899SCharles.Forsyth     {
4599*37da2899SCharles.Forsyth       if ( CUR.opcode & 1 )
4600*37da2899SCharles.Forsyth         R = CUR_Func_dualproj( CUR.zp2.org + L, NULL_Vector );
4601*37da2899SCharles.Forsyth       else
4602*37da2899SCharles.Forsyth         R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
4603*37da2899SCharles.Forsyth     }
4604*37da2899SCharles.Forsyth 
4605*37da2899SCharles.Forsyth     args[0] = R;
4606*37da2899SCharles.Forsyth   }
4607*37da2899SCharles.Forsyth 
4608*37da2899SCharles.Forsyth 
4609*37da2899SCharles.Forsyth   /*************************************************************************/
4610*37da2899SCharles.Forsyth   /*                                                                       */
4611*37da2899SCharles.Forsyth   /* SCFS[]:       Set Coordinate From Stack                               */
4612*37da2899SCharles.Forsyth   /* Opcode range: 0x48                                                    */
4613*37da2899SCharles.Forsyth   /* Stack:        f26.6 uint32 -->                                        */
4614*37da2899SCharles.Forsyth   /*                                                                       */
4615*37da2899SCharles.Forsyth   /* Formula:                                                              */
4616*37da2899SCharles.Forsyth   /*                                                                       */
4617*37da2899SCharles.Forsyth   /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */
4618*37da2899SCharles.Forsyth   /*                                                                       */
4619*37da2899SCharles.Forsyth   static void
Ins_SCFS(INS_ARG)4620*37da2899SCharles.Forsyth   Ins_SCFS( INS_ARG )
4621*37da2899SCharles.Forsyth   {
4622*37da2899SCharles.Forsyth     FT_Long    K;
4623*37da2899SCharles.Forsyth     FT_UShort  L;
4624*37da2899SCharles.Forsyth 
4625*37da2899SCharles.Forsyth 
4626*37da2899SCharles.Forsyth     L = (FT_UShort)args[0];
4627*37da2899SCharles.Forsyth 
4628*37da2899SCharles.Forsyth     if ( BOUNDS( L, CUR.zp2.n_points ) )
4629*37da2899SCharles.Forsyth     {
4630*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4631*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4632*37da2899SCharles.Forsyth       return;
4633*37da2899SCharles.Forsyth     }
4634*37da2899SCharles.Forsyth 
4635*37da2899SCharles.Forsyth     K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
4636*37da2899SCharles.Forsyth 
4637*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp2, L, args[1] - K );
4638*37da2899SCharles.Forsyth 
4639*37da2899SCharles.Forsyth     /* not part of the specs, but here for safety */
4640*37da2899SCharles.Forsyth 
4641*37da2899SCharles.Forsyth     if ( CUR.GS.gep2 == 0 )
4642*37da2899SCharles.Forsyth       CUR.zp2.org[L] = CUR.zp2.cur[L];
4643*37da2899SCharles.Forsyth   }
4644*37da2899SCharles.Forsyth 
4645*37da2899SCharles.Forsyth 
4646*37da2899SCharles.Forsyth   /*************************************************************************/
4647*37da2899SCharles.Forsyth   /*                                                                       */
4648*37da2899SCharles.Forsyth   /* MD[a]:        Measure Distance                                        */
4649*37da2899SCharles.Forsyth   /* Opcode range: 0x49-0x4A                                               */
4650*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 --> f26.6                                 */
4651*37da2899SCharles.Forsyth   /*                                                                       */
4652*37da2899SCharles.Forsyth   /* BULLSHIT: Measure taken in the original glyph must be along the dual  */
4653*37da2899SCharles.Forsyth   /*           projection vector.                                          */
4654*37da2899SCharles.Forsyth   /*                                                                       */
4655*37da2899SCharles.Forsyth   /* Second BULLSHIT: Flag attributes are inverted!                        */
4656*37da2899SCharles.Forsyth   /*                  0 => measure distance in original outline            */
4657*37da2899SCharles.Forsyth   /*                  1 => measure distance in grid-fitted outline         */
4658*37da2899SCharles.Forsyth   /*                                                                       */
4659*37da2899SCharles.Forsyth   /* Third one: `zp0 - zp1', and not `zp2 - zp1!                           */
4660*37da2899SCharles.Forsyth   /*                                                                       */
4661*37da2899SCharles.Forsyth   static void
Ins_MD(INS_ARG)4662*37da2899SCharles.Forsyth   Ins_MD( INS_ARG )
4663*37da2899SCharles.Forsyth   {
4664*37da2899SCharles.Forsyth     FT_UShort   K, L;
4665*37da2899SCharles.Forsyth     FT_F26Dot6  D;
4666*37da2899SCharles.Forsyth 
4667*37da2899SCharles.Forsyth 
4668*37da2899SCharles.Forsyth     K = (FT_UShort)args[1];
4669*37da2899SCharles.Forsyth     L = (FT_UShort)args[0];
4670*37da2899SCharles.Forsyth 
4671*37da2899SCharles.Forsyth     if( BOUNDS( L, CUR.zp0.n_points ) ||
4672*37da2899SCharles.Forsyth         BOUNDS( K, CUR.zp1.n_points ) )
4673*37da2899SCharles.Forsyth     {
4674*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4675*37da2899SCharles.Forsyth       {
4676*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4677*37da2899SCharles.Forsyth         return;
4678*37da2899SCharles.Forsyth       }
4679*37da2899SCharles.Forsyth       D = 0;
4680*37da2899SCharles.Forsyth     }
4681*37da2899SCharles.Forsyth     else
4682*37da2899SCharles.Forsyth     {
4683*37da2899SCharles.Forsyth       if ( CUR.opcode & 1 )
4684*37da2899SCharles.Forsyth         D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
4685*37da2899SCharles.Forsyth       else
4686*37da2899SCharles.Forsyth         D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
4687*37da2899SCharles.Forsyth     }
4688*37da2899SCharles.Forsyth 
4689*37da2899SCharles.Forsyth     args[0] = D;
4690*37da2899SCharles.Forsyth   }
4691*37da2899SCharles.Forsyth 
4692*37da2899SCharles.Forsyth 
4693*37da2899SCharles.Forsyth   /*************************************************************************/
4694*37da2899SCharles.Forsyth   /*                                                                       */
4695*37da2899SCharles.Forsyth   /* SDPVTL[a]:    Set Dual PVector to Line                                */
4696*37da2899SCharles.Forsyth   /* Opcode range: 0x86-0x87                                               */
4697*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
4698*37da2899SCharles.Forsyth   /*                                                                       */
4699*37da2899SCharles.Forsyth   static void
Ins_SDPVTL(INS_ARG)4700*37da2899SCharles.Forsyth   Ins_SDPVTL( INS_ARG )
4701*37da2899SCharles.Forsyth   {
4702*37da2899SCharles.Forsyth     FT_Long    A, B, C;
4703*37da2899SCharles.Forsyth     FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */
4704*37da2899SCharles.Forsyth 
4705*37da2899SCharles.Forsyth 
4706*37da2899SCharles.Forsyth     p1 = (FT_UShort)args[1];
4707*37da2899SCharles.Forsyth     p2 = (FT_UShort)args[0];
4708*37da2899SCharles.Forsyth 
4709*37da2899SCharles.Forsyth     if ( BOUNDS( p2, CUR.zp1.n_points ) ||
4710*37da2899SCharles.Forsyth          BOUNDS( p1, CUR.zp2.n_points ) )
4711*37da2899SCharles.Forsyth     {
4712*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4713*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4714*37da2899SCharles.Forsyth       return;
4715*37da2899SCharles.Forsyth     }
4716*37da2899SCharles.Forsyth 
4717*37da2899SCharles.Forsyth     {
4718*37da2899SCharles.Forsyth       FT_Vector* v1 = CUR.zp1.org + p2;
4719*37da2899SCharles.Forsyth       FT_Vector* v2 = CUR.zp2.org + p1;
4720*37da2899SCharles.Forsyth 
4721*37da2899SCharles.Forsyth 
4722*37da2899SCharles.Forsyth       A = v1->x - v2->x;
4723*37da2899SCharles.Forsyth       B = v1->y - v2->y;
4724*37da2899SCharles.Forsyth     }
4725*37da2899SCharles.Forsyth 
4726*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 1 ) != 0 )
4727*37da2899SCharles.Forsyth     {
4728*37da2899SCharles.Forsyth       C =  B;   /* counter clockwise rotation */
4729*37da2899SCharles.Forsyth       B =  A;
4730*37da2899SCharles.Forsyth       A = -C;
4731*37da2899SCharles.Forsyth     }
4732*37da2899SCharles.Forsyth 
4733*37da2899SCharles.Forsyth     NORMalize( A, B, &CUR.GS.dualVector );
4734*37da2899SCharles.Forsyth 
4735*37da2899SCharles.Forsyth     {
4736*37da2899SCharles.Forsyth       FT_Vector*  v1 = CUR.zp1.cur + p2;
4737*37da2899SCharles.Forsyth       FT_Vector*  v2 = CUR.zp2.cur + p1;
4738*37da2899SCharles.Forsyth 
4739*37da2899SCharles.Forsyth 
4740*37da2899SCharles.Forsyth       A = v1->x - v2->x;
4741*37da2899SCharles.Forsyth       B = v1->y - v2->y;
4742*37da2899SCharles.Forsyth     }
4743*37da2899SCharles.Forsyth 
4744*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 1 ) != 0 )
4745*37da2899SCharles.Forsyth     {
4746*37da2899SCharles.Forsyth       C =  B;   /* counter clockwise rotation */
4747*37da2899SCharles.Forsyth       B =  A;
4748*37da2899SCharles.Forsyth       A = -C;
4749*37da2899SCharles.Forsyth     }
4750*37da2899SCharles.Forsyth 
4751*37da2899SCharles.Forsyth     NORMalize( A, B, &CUR.GS.projVector );
4752*37da2899SCharles.Forsyth 
4753*37da2899SCharles.Forsyth     COMPUTE_Funcs();
4754*37da2899SCharles.Forsyth   }
4755*37da2899SCharles.Forsyth 
4756*37da2899SCharles.Forsyth 
4757*37da2899SCharles.Forsyth   /*************************************************************************/
4758*37da2899SCharles.Forsyth   /*                                                                       */
4759*37da2899SCharles.Forsyth   /* SZP0[]:       Set Zone Pointer 0                                      */
4760*37da2899SCharles.Forsyth   /* Opcode range: 0x13                                                    */
4761*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
4762*37da2899SCharles.Forsyth   /*                                                                       */
4763*37da2899SCharles.Forsyth   static void
Ins_SZP0(INS_ARG)4764*37da2899SCharles.Forsyth   Ins_SZP0( INS_ARG )
4765*37da2899SCharles.Forsyth   {
4766*37da2899SCharles.Forsyth     switch ( (FT_Int)args[0] )
4767*37da2899SCharles.Forsyth     {
4768*37da2899SCharles.Forsyth     case 0:
4769*37da2899SCharles.Forsyth       CUR.zp0 = CUR.twilight;
4770*37da2899SCharles.Forsyth       break;
4771*37da2899SCharles.Forsyth 
4772*37da2899SCharles.Forsyth     case 1:
4773*37da2899SCharles.Forsyth       CUR.zp0 = CUR.pts;
4774*37da2899SCharles.Forsyth       break;
4775*37da2899SCharles.Forsyth 
4776*37da2899SCharles.Forsyth     default:
4777*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4778*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4779*37da2899SCharles.Forsyth       return;
4780*37da2899SCharles.Forsyth     }
4781*37da2899SCharles.Forsyth 
4782*37da2899SCharles.Forsyth     CUR.GS.gep0 = (FT_UShort)args[0];
4783*37da2899SCharles.Forsyth   }
4784*37da2899SCharles.Forsyth 
4785*37da2899SCharles.Forsyth 
4786*37da2899SCharles.Forsyth   /*************************************************************************/
4787*37da2899SCharles.Forsyth   /*                                                                       */
4788*37da2899SCharles.Forsyth   /* SZP1[]:       Set Zone Pointer 1                                      */
4789*37da2899SCharles.Forsyth   /* Opcode range: 0x14                                                    */
4790*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
4791*37da2899SCharles.Forsyth   /*                                                                       */
4792*37da2899SCharles.Forsyth   static void
Ins_SZP1(INS_ARG)4793*37da2899SCharles.Forsyth   Ins_SZP1( INS_ARG )
4794*37da2899SCharles.Forsyth   {
4795*37da2899SCharles.Forsyth     switch ( (FT_Int)args[0] )
4796*37da2899SCharles.Forsyth     {
4797*37da2899SCharles.Forsyth     case 0:
4798*37da2899SCharles.Forsyth       CUR.zp1 = CUR.twilight;
4799*37da2899SCharles.Forsyth       break;
4800*37da2899SCharles.Forsyth 
4801*37da2899SCharles.Forsyth     case 1:
4802*37da2899SCharles.Forsyth       CUR.zp1 = CUR.pts;
4803*37da2899SCharles.Forsyth       break;
4804*37da2899SCharles.Forsyth 
4805*37da2899SCharles.Forsyth     default:
4806*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4807*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4808*37da2899SCharles.Forsyth       return;
4809*37da2899SCharles.Forsyth     }
4810*37da2899SCharles.Forsyth 
4811*37da2899SCharles.Forsyth     CUR.GS.gep1 = (FT_UShort)args[0];
4812*37da2899SCharles.Forsyth   }
4813*37da2899SCharles.Forsyth 
4814*37da2899SCharles.Forsyth 
4815*37da2899SCharles.Forsyth   /*************************************************************************/
4816*37da2899SCharles.Forsyth   /*                                                                       */
4817*37da2899SCharles.Forsyth   /* SZP2[]:       Set Zone Pointer 2                                      */
4818*37da2899SCharles.Forsyth   /* Opcode range: 0x15                                                    */
4819*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
4820*37da2899SCharles.Forsyth   /*                                                                       */
4821*37da2899SCharles.Forsyth   static void
Ins_SZP2(INS_ARG)4822*37da2899SCharles.Forsyth   Ins_SZP2( INS_ARG )
4823*37da2899SCharles.Forsyth   {
4824*37da2899SCharles.Forsyth     switch ( (FT_Int)args[0] )
4825*37da2899SCharles.Forsyth     {
4826*37da2899SCharles.Forsyth     case 0:
4827*37da2899SCharles.Forsyth       CUR.zp2 = CUR.twilight;
4828*37da2899SCharles.Forsyth       break;
4829*37da2899SCharles.Forsyth 
4830*37da2899SCharles.Forsyth     case 1:
4831*37da2899SCharles.Forsyth       CUR.zp2 = CUR.pts;
4832*37da2899SCharles.Forsyth       break;
4833*37da2899SCharles.Forsyth 
4834*37da2899SCharles.Forsyth     default:
4835*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4836*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4837*37da2899SCharles.Forsyth       return;
4838*37da2899SCharles.Forsyth     }
4839*37da2899SCharles.Forsyth 
4840*37da2899SCharles.Forsyth     CUR.GS.gep2 = (FT_UShort)args[0];
4841*37da2899SCharles.Forsyth   }
4842*37da2899SCharles.Forsyth 
4843*37da2899SCharles.Forsyth 
4844*37da2899SCharles.Forsyth   /*************************************************************************/
4845*37da2899SCharles.Forsyth   /*                                                                       */
4846*37da2899SCharles.Forsyth   /* SZPS[]:       Set Zone PointerS                                       */
4847*37da2899SCharles.Forsyth   /* Opcode range: 0x16                                                    */
4848*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
4849*37da2899SCharles.Forsyth   /*                                                                       */
4850*37da2899SCharles.Forsyth   static void
Ins_SZPS(INS_ARG)4851*37da2899SCharles.Forsyth   Ins_SZPS( INS_ARG )
4852*37da2899SCharles.Forsyth   {
4853*37da2899SCharles.Forsyth     switch ( (FT_Int)args[0] )
4854*37da2899SCharles.Forsyth     {
4855*37da2899SCharles.Forsyth     case 0:
4856*37da2899SCharles.Forsyth       CUR.zp0 = CUR.twilight;
4857*37da2899SCharles.Forsyth       break;
4858*37da2899SCharles.Forsyth 
4859*37da2899SCharles.Forsyth     case 1:
4860*37da2899SCharles.Forsyth       CUR.zp0 = CUR.pts;
4861*37da2899SCharles.Forsyth       break;
4862*37da2899SCharles.Forsyth 
4863*37da2899SCharles.Forsyth     default:
4864*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4865*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4866*37da2899SCharles.Forsyth       return;
4867*37da2899SCharles.Forsyth     }
4868*37da2899SCharles.Forsyth 
4869*37da2899SCharles.Forsyth     CUR.zp1 = CUR.zp0;
4870*37da2899SCharles.Forsyth     CUR.zp2 = CUR.zp0;
4871*37da2899SCharles.Forsyth 
4872*37da2899SCharles.Forsyth     CUR.GS.gep0 = (FT_UShort)args[0];
4873*37da2899SCharles.Forsyth     CUR.GS.gep1 = (FT_UShort)args[0];
4874*37da2899SCharles.Forsyth     CUR.GS.gep2 = (FT_UShort)args[0];
4875*37da2899SCharles.Forsyth   }
4876*37da2899SCharles.Forsyth 
4877*37da2899SCharles.Forsyth 
4878*37da2899SCharles.Forsyth   /*************************************************************************/
4879*37da2899SCharles.Forsyth   /*                                                                       */
4880*37da2899SCharles.Forsyth   /* INSTCTRL[]:   INSTruction ConTRoL                                     */
4881*37da2899SCharles.Forsyth   /* Opcode range: 0x8e                                                    */
4882*37da2899SCharles.Forsyth   /* Stack:        int32 int32 -->                                         */
4883*37da2899SCharles.Forsyth   /*                                                                       */
4884*37da2899SCharles.Forsyth   static void
Ins_INSTCTRL(INS_ARG)4885*37da2899SCharles.Forsyth   Ins_INSTCTRL( INS_ARG )
4886*37da2899SCharles.Forsyth   {
4887*37da2899SCharles.Forsyth     FT_Long  K, L;
4888*37da2899SCharles.Forsyth 
4889*37da2899SCharles.Forsyth 
4890*37da2899SCharles.Forsyth     K = args[1];
4891*37da2899SCharles.Forsyth     L = args[0];
4892*37da2899SCharles.Forsyth 
4893*37da2899SCharles.Forsyth     if ( K < 1 || K > 2 )
4894*37da2899SCharles.Forsyth     {
4895*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
4896*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
4897*37da2899SCharles.Forsyth       return;
4898*37da2899SCharles.Forsyth     }
4899*37da2899SCharles.Forsyth 
4900*37da2899SCharles.Forsyth     if ( L != 0 )
4901*37da2899SCharles.Forsyth         L = K;
4902*37da2899SCharles.Forsyth 
4903*37da2899SCharles.Forsyth     CUR.GS.instruct_control = FT_BOOL(
4904*37da2899SCharles.Forsyth       ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
4905*37da2899SCharles.Forsyth   }
4906*37da2899SCharles.Forsyth 
4907*37da2899SCharles.Forsyth 
4908*37da2899SCharles.Forsyth   /*************************************************************************/
4909*37da2899SCharles.Forsyth   /*                                                                       */
4910*37da2899SCharles.Forsyth   /* SCANCTRL[]:   SCAN ConTRoL                                            */
4911*37da2899SCharles.Forsyth   /* Opcode range: 0x85                                                    */
4912*37da2899SCharles.Forsyth   /* Stack:        uint32? -->                                             */
4913*37da2899SCharles.Forsyth   /*                                                                       */
4914*37da2899SCharles.Forsyth   static void
Ins_SCANCTRL(INS_ARG)4915*37da2899SCharles.Forsyth   Ins_SCANCTRL( INS_ARG )
4916*37da2899SCharles.Forsyth   {
4917*37da2899SCharles.Forsyth     FT_Int  A;
4918*37da2899SCharles.Forsyth 
4919*37da2899SCharles.Forsyth 
4920*37da2899SCharles.Forsyth     /* Get Threshold */
4921*37da2899SCharles.Forsyth     A = (FT_Int)( args[0] & 0xFF );
4922*37da2899SCharles.Forsyth 
4923*37da2899SCharles.Forsyth     if ( A == 0xFF )
4924*37da2899SCharles.Forsyth     {
4925*37da2899SCharles.Forsyth       CUR.GS.scan_control = TRUE;
4926*37da2899SCharles.Forsyth       return;
4927*37da2899SCharles.Forsyth     }
4928*37da2899SCharles.Forsyth     else if ( A == 0 )
4929*37da2899SCharles.Forsyth     {
4930*37da2899SCharles.Forsyth       CUR.GS.scan_control = FALSE;
4931*37da2899SCharles.Forsyth       return;
4932*37da2899SCharles.Forsyth     }
4933*37da2899SCharles.Forsyth 
4934*37da2899SCharles.Forsyth     A *= 64;
4935*37da2899SCharles.Forsyth 
4936*37da2899SCharles.Forsyth #if 0
4937*37da2899SCharles.Forsyth     if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A )
4938*37da2899SCharles.Forsyth       CUR.GS.scan_control = TRUE;
4939*37da2899SCharles.Forsyth #endif
4940*37da2899SCharles.Forsyth 
4941*37da2899SCharles.Forsyth     if ( (args[0] & 0x200) != 0 && CUR.tt_metrics.rotated )
4942*37da2899SCharles.Forsyth       CUR.GS.scan_control = TRUE;
4943*37da2899SCharles.Forsyth 
4944*37da2899SCharles.Forsyth     if ( (args[0] & 0x400) != 0 && CUR.tt_metrics.stretched )
4945*37da2899SCharles.Forsyth       CUR.GS.scan_control = TRUE;
4946*37da2899SCharles.Forsyth 
4947*37da2899SCharles.Forsyth #if 0
4948*37da2899SCharles.Forsyth     if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A )
4949*37da2899SCharles.Forsyth       CUR.GS.scan_control = FALSE;
4950*37da2899SCharles.Forsyth #endif
4951*37da2899SCharles.Forsyth 
4952*37da2899SCharles.Forsyth     if ( (args[0] & 0x1000) != 0 && CUR.tt_metrics.rotated )
4953*37da2899SCharles.Forsyth       CUR.GS.scan_control = FALSE;
4954*37da2899SCharles.Forsyth 
4955*37da2899SCharles.Forsyth     if ( (args[0] & 0x2000) != 0 && CUR.tt_metrics.stretched )
4956*37da2899SCharles.Forsyth       CUR.GS.scan_control = FALSE;
4957*37da2899SCharles.Forsyth   }
4958*37da2899SCharles.Forsyth 
4959*37da2899SCharles.Forsyth 
4960*37da2899SCharles.Forsyth   /*************************************************************************/
4961*37da2899SCharles.Forsyth   /*                                                                       */
4962*37da2899SCharles.Forsyth   /* SCANTYPE[]:   SCAN TYPE                                               */
4963*37da2899SCharles.Forsyth   /* Opcode range: 0x8D                                                    */
4964*37da2899SCharles.Forsyth   /* Stack:        uint32? -->                                             */
4965*37da2899SCharles.Forsyth   /*                                                                       */
4966*37da2899SCharles.Forsyth   static void
Ins_SCANTYPE(INS_ARG)4967*37da2899SCharles.Forsyth   Ins_SCANTYPE( INS_ARG )
4968*37da2899SCharles.Forsyth   {
4969*37da2899SCharles.Forsyth     /* for compatibility with future enhancements, */
4970*37da2899SCharles.Forsyth     /* we must ignore new modes                    */
4971*37da2899SCharles.Forsyth 
4972*37da2899SCharles.Forsyth     if ( args[0] >= 0 && args[0] <= 5 )
4973*37da2899SCharles.Forsyth     {
4974*37da2899SCharles.Forsyth       if ( args[0] == 3 )
4975*37da2899SCharles.Forsyth         args[0] = 2;
4976*37da2899SCharles.Forsyth 
4977*37da2899SCharles.Forsyth       CUR.GS.scan_type = (FT_Int)args[0];
4978*37da2899SCharles.Forsyth     }
4979*37da2899SCharles.Forsyth   }
4980*37da2899SCharles.Forsyth 
4981*37da2899SCharles.Forsyth 
4982*37da2899SCharles.Forsyth   /*************************************************************************/
4983*37da2899SCharles.Forsyth   /*                                                                       */
4984*37da2899SCharles.Forsyth   /* MANAGING OUTLINES                                                     */
4985*37da2899SCharles.Forsyth   /*                                                                       */
4986*37da2899SCharles.Forsyth   /*   Instructions appear in the specification's order.                   */
4987*37da2899SCharles.Forsyth   /*                                                                       */
4988*37da2899SCharles.Forsyth   /*************************************************************************/
4989*37da2899SCharles.Forsyth 
4990*37da2899SCharles.Forsyth 
4991*37da2899SCharles.Forsyth   /*************************************************************************/
4992*37da2899SCharles.Forsyth   /*                                                                       */
4993*37da2899SCharles.Forsyth   /* FLIPPT[]:     FLIP PoinT                                              */
4994*37da2899SCharles.Forsyth   /* Opcode range: 0x80                                                    */
4995*37da2899SCharles.Forsyth   /* Stack:        uint32... -->                                           */
4996*37da2899SCharles.Forsyth   /*                                                                       */
4997*37da2899SCharles.Forsyth   static void
Ins_FLIPPT(INS_ARG)4998*37da2899SCharles.Forsyth   Ins_FLIPPT( INS_ARG )
4999*37da2899SCharles.Forsyth   {
5000*37da2899SCharles.Forsyth     FT_UShort  point;
5001*37da2899SCharles.Forsyth 
5002*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
5003*37da2899SCharles.Forsyth 
5004*37da2899SCharles.Forsyth 
5005*37da2899SCharles.Forsyth     if ( CUR.top < CUR.GS.loop )
5006*37da2899SCharles.Forsyth     {
5007*37da2899SCharles.Forsyth       CUR.error = TT_Err_Too_Few_Arguments;
5008*37da2899SCharles.Forsyth       return;
5009*37da2899SCharles.Forsyth     }
5010*37da2899SCharles.Forsyth 
5011*37da2899SCharles.Forsyth     while ( CUR.GS.loop > 0 )
5012*37da2899SCharles.Forsyth     {
5013*37da2899SCharles.Forsyth       CUR.args--;
5014*37da2899SCharles.Forsyth 
5015*37da2899SCharles.Forsyth       point = (FT_UShort)CUR.stack[CUR.args];
5016*37da2899SCharles.Forsyth 
5017*37da2899SCharles.Forsyth       if ( BOUNDS( point, CUR.pts.n_points ) )
5018*37da2899SCharles.Forsyth       {
5019*37da2899SCharles.Forsyth         if ( CUR.pedantic_hinting )
5020*37da2899SCharles.Forsyth         {
5021*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Reference;
5022*37da2899SCharles.Forsyth           return;
5023*37da2899SCharles.Forsyth         }
5024*37da2899SCharles.Forsyth       }
5025*37da2899SCharles.Forsyth       else
5026*37da2899SCharles.Forsyth         CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
5027*37da2899SCharles.Forsyth 
5028*37da2899SCharles.Forsyth       CUR.GS.loop--;
5029*37da2899SCharles.Forsyth     }
5030*37da2899SCharles.Forsyth 
5031*37da2899SCharles.Forsyth     CUR.GS.loop = 1;
5032*37da2899SCharles.Forsyth     CUR.new_top = CUR.args;
5033*37da2899SCharles.Forsyth   }
5034*37da2899SCharles.Forsyth 
5035*37da2899SCharles.Forsyth 
5036*37da2899SCharles.Forsyth   /*************************************************************************/
5037*37da2899SCharles.Forsyth   /*                                                                       */
5038*37da2899SCharles.Forsyth   /* FLIPRGON[]:   FLIP RanGe ON                                           */
5039*37da2899SCharles.Forsyth   /* Opcode range: 0x81                                                    */
5040*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
5041*37da2899SCharles.Forsyth   /*                                                                       */
5042*37da2899SCharles.Forsyth   static void
Ins_FLIPRGON(INS_ARG)5043*37da2899SCharles.Forsyth   Ins_FLIPRGON( INS_ARG )
5044*37da2899SCharles.Forsyth   {
5045*37da2899SCharles.Forsyth     FT_UShort  I, K, L;
5046*37da2899SCharles.Forsyth 
5047*37da2899SCharles.Forsyth 
5048*37da2899SCharles.Forsyth     K = (FT_UShort)args[1];
5049*37da2899SCharles.Forsyth     L = (FT_UShort)args[0];
5050*37da2899SCharles.Forsyth 
5051*37da2899SCharles.Forsyth     if ( BOUNDS( K, CUR.pts.n_points ) ||
5052*37da2899SCharles.Forsyth          BOUNDS( L, CUR.pts.n_points ) )
5053*37da2899SCharles.Forsyth     {
5054*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5055*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5056*37da2899SCharles.Forsyth       return;
5057*37da2899SCharles.Forsyth     }
5058*37da2899SCharles.Forsyth 
5059*37da2899SCharles.Forsyth     for ( I = L; I <= K; I++ )
5060*37da2899SCharles.Forsyth       CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
5061*37da2899SCharles.Forsyth   }
5062*37da2899SCharles.Forsyth 
5063*37da2899SCharles.Forsyth 
5064*37da2899SCharles.Forsyth   /*************************************************************************/
5065*37da2899SCharles.Forsyth   /*                                                                       */
5066*37da2899SCharles.Forsyth   /* FLIPRGOFF:    FLIP RanGe OFF                                          */
5067*37da2899SCharles.Forsyth   /* Opcode range: 0x82                                                    */
5068*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
5069*37da2899SCharles.Forsyth   /*                                                                       */
5070*37da2899SCharles.Forsyth   static void
Ins_FLIPRGOFF(INS_ARG)5071*37da2899SCharles.Forsyth   Ins_FLIPRGOFF( INS_ARG )
5072*37da2899SCharles.Forsyth   {
5073*37da2899SCharles.Forsyth     FT_UShort  I, K, L;
5074*37da2899SCharles.Forsyth 
5075*37da2899SCharles.Forsyth 
5076*37da2899SCharles.Forsyth     K = (FT_UShort)args[1];
5077*37da2899SCharles.Forsyth     L = (FT_UShort)args[0];
5078*37da2899SCharles.Forsyth 
5079*37da2899SCharles.Forsyth     if ( BOUNDS( K, CUR.pts.n_points ) ||
5080*37da2899SCharles.Forsyth          BOUNDS( L, CUR.pts.n_points ) )
5081*37da2899SCharles.Forsyth     {
5082*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5083*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5084*37da2899SCharles.Forsyth       return;
5085*37da2899SCharles.Forsyth     }
5086*37da2899SCharles.Forsyth 
5087*37da2899SCharles.Forsyth     for ( I = L; I <= K; I++ )
5088*37da2899SCharles.Forsyth       CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
5089*37da2899SCharles.Forsyth   }
5090*37da2899SCharles.Forsyth 
5091*37da2899SCharles.Forsyth 
5092*37da2899SCharles.Forsyth   static FT_Bool
Compute_Point_Displacement(EXEC_OP_ FT_F26Dot6 * x,FT_F26Dot6 * y,TT_GlyphZone zone,FT_UShort * refp)5093*37da2899SCharles.Forsyth   Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*   x,
5094*37da2899SCharles.Forsyth                                        FT_F26Dot6*   y,
5095*37da2899SCharles.Forsyth                                        TT_GlyphZone  zone,
5096*37da2899SCharles.Forsyth                                        FT_UShort*    refp )
5097*37da2899SCharles.Forsyth   {
5098*37da2899SCharles.Forsyth     TT_GlyphZoneRec  zp;
5099*37da2899SCharles.Forsyth     FT_UShort        p;
5100*37da2899SCharles.Forsyth     FT_F26Dot6       d;
5101*37da2899SCharles.Forsyth 
5102*37da2899SCharles.Forsyth 
5103*37da2899SCharles.Forsyth     if ( CUR.opcode & 1 )
5104*37da2899SCharles.Forsyth     {
5105*37da2899SCharles.Forsyth       zp = CUR.zp0;
5106*37da2899SCharles.Forsyth       p  = CUR.GS.rp1;
5107*37da2899SCharles.Forsyth     }
5108*37da2899SCharles.Forsyth     else
5109*37da2899SCharles.Forsyth     {
5110*37da2899SCharles.Forsyth       zp = CUR.zp1;
5111*37da2899SCharles.Forsyth       p  = CUR.GS.rp2;
5112*37da2899SCharles.Forsyth     }
5113*37da2899SCharles.Forsyth 
5114*37da2899SCharles.Forsyth     if ( BOUNDS( p, zp.n_points ) )
5115*37da2899SCharles.Forsyth     {
5116*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5117*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5118*37da2899SCharles.Forsyth       return FAILURE;
5119*37da2899SCharles.Forsyth     }
5120*37da2899SCharles.Forsyth 
5121*37da2899SCharles.Forsyth     *zone = zp;
5122*37da2899SCharles.Forsyth     *refp = p;
5123*37da2899SCharles.Forsyth 
5124*37da2899SCharles.Forsyth     d = CUR_Func_project( zp.cur + p, zp.org + p );
5125*37da2899SCharles.Forsyth 
5126*37da2899SCharles.Forsyth #ifdef NO_APPLE_PATENT
5127*37da2899SCharles.Forsyth 
5128*37da2899SCharles.Forsyth     *x = TT_MulFix14( d, CUR.GS.freeVector.x );
5129*37da2899SCharles.Forsyth     *y = TT_MulFix14( d, CUR.GS.freeVector.y );
5130*37da2899SCharles.Forsyth 
5131*37da2899SCharles.Forsyth #else
5132*37da2899SCharles.Forsyth 
5133*37da2899SCharles.Forsyth     *x = TT_MULDIV( d,
5134*37da2899SCharles.Forsyth                     (FT_Long)CUR.GS.freeVector.x * 0x10000L,
5135*37da2899SCharles.Forsyth                     CUR.F_dot_P );
5136*37da2899SCharles.Forsyth     *y = TT_MULDIV( d,
5137*37da2899SCharles.Forsyth                     (FT_Long)CUR.GS.freeVector.y * 0x10000L,
5138*37da2899SCharles.Forsyth                     CUR.F_dot_P );
5139*37da2899SCharles.Forsyth 
5140*37da2899SCharles.Forsyth #endif /* NO_APPLE_PATENT */
5141*37da2899SCharles.Forsyth 
5142*37da2899SCharles.Forsyth     return SUCCESS;
5143*37da2899SCharles.Forsyth   }
5144*37da2899SCharles.Forsyth 
5145*37da2899SCharles.Forsyth 
5146*37da2899SCharles.Forsyth   static void
Move_Zp2_Point(EXEC_OP_ FT_UShort point,FT_F26Dot6 dx,FT_F26Dot6 dy,FT_Bool touch)5147*37da2899SCharles.Forsyth   Move_Zp2_Point( EXEC_OP_ FT_UShort   point,
5148*37da2899SCharles.Forsyth                            FT_F26Dot6  dx,
5149*37da2899SCharles.Forsyth                            FT_F26Dot6  dy,
5150*37da2899SCharles.Forsyth                            FT_Bool     touch )
5151*37da2899SCharles.Forsyth   {
5152*37da2899SCharles.Forsyth     if ( CUR.GS.freeVector.x != 0 )
5153*37da2899SCharles.Forsyth     {
5154*37da2899SCharles.Forsyth       CUR.zp2.cur[point].x += dx;
5155*37da2899SCharles.Forsyth       if ( touch )
5156*37da2899SCharles.Forsyth         CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
5157*37da2899SCharles.Forsyth     }
5158*37da2899SCharles.Forsyth 
5159*37da2899SCharles.Forsyth     if ( CUR.GS.freeVector.y != 0 )
5160*37da2899SCharles.Forsyth     {
5161*37da2899SCharles.Forsyth       CUR.zp2.cur[point].y += dy;
5162*37da2899SCharles.Forsyth       if ( touch )
5163*37da2899SCharles.Forsyth         CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
5164*37da2899SCharles.Forsyth     }
5165*37da2899SCharles.Forsyth   }
5166*37da2899SCharles.Forsyth 
5167*37da2899SCharles.Forsyth 
5168*37da2899SCharles.Forsyth   /*************************************************************************/
5169*37da2899SCharles.Forsyth   /*                                                                       */
5170*37da2899SCharles.Forsyth   /* SHP[a]:       SHift Point by the last point                           */
5171*37da2899SCharles.Forsyth   /* Opcode range: 0x32-0x33                                               */
5172*37da2899SCharles.Forsyth   /* Stack:        uint32... -->                                           */
5173*37da2899SCharles.Forsyth   /*                                                                       */
5174*37da2899SCharles.Forsyth   static void
Ins_SHP(INS_ARG)5175*37da2899SCharles.Forsyth   Ins_SHP( INS_ARG )
5176*37da2899SCharles.Forsyth   {
5177*37da2899SCharles.Forsyth     TT_GlyphZoneRec  zp;
5178*37da2899SCharles.Forsyth     FT_UShort        refp;
5179*37da2899SCharles.Forsyth 
5180*37da2899SCharles.Forsyth     FT_F26Dot6       dx,
5181*37da2899SCharles.Forsyth                      dy;
5182*37da2899SCharles.Forsyth     FT_UShort        point;
5183*37da2899SCharles.Forsyth 
5184*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
5185*37da2899SCharles.Forsyth 
5186*37da2899SCharles.Forsyth 
5187*37da2899SCharles.Forsyth     if ( CUR.top < CUR.GS.loop )
5188*37da2899SCharles.Forsyth     {
5189*37da2899SCharles.Forsyth       CUR.error = TT_Err_Invalid_Reference;
5190*37da2899SCharles.Forsyth       return;
5191*37da2899SCharles.Forsyth     }
5192*37da2899SCharles.Forsyth 
5193*37da2899SCharles.Forsyth     if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5194*37da2899SCharles.Forsyth       return;
5195*37da2899SCharles.Forsyth 
5196*37da2899SCharles.Forsyth     while ( CUR.GS.loop > 0 )
5197*37da2899SCharles.Forsyth     {
5198*37da2899SCharles.Forsyth       CUR.args--;
5199*37da2899SCharles.Forsyth       point = (FT_UShort)CUR.stack[CUR.args];
5200*37da2899SCharles.Forsyth 
5201*37da2899SCharles.Forsyth       if ( BOUNDS( point, CUR.zp2.n_points ) )
5202*37da2899SCharles.Forsyth       {
5203*37da2899SCharles.Forsyth         if ( CUR.pedantic_hinting )
5204*37da2899SCharles.Forsyth         {
5205*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Reference;
5206*37da2899SCharles.Forsyth           return;
5207*37da2899SCharles.Forsyth         }
5208*37da2899SCharles.Forsyth       }
5209*37da2899SCharles.Forsyth       else
5210*37da2899SCharles.Forsyth         /* XXX: UNDOCUMENTED! SHP touches the points */
5211*37da2899SCharles.Forsyth         MOVE_Zp2_Point( point, dx, dy, TRUE );
5212*37da2899SCharles.Forsyth 
5213*37da2899SCharles.Forsyth       CUR.GS.loop--;
5214*37da2899SCharles.Forsyth     }
5215*37da2899SCharles.Forsyth 
5216*37da2899SCharles.Forsyth     CUR.GS.loop = 1;
5217*37da2899SCharles.Forsyth     CUR.new_top = CUR.args;
5218*37da2899SCharles.Forsyth   }
5219*37da2899SCharles.Forsyth 
5220*37da2899SCharles.Forsyth 
5221*37da2899SCharles.Forsyth   /*************************************************************************/
5222*37da2899SCharles.Forsyth   /*                                                                       */
5223*37da2899SCharles.Forsyth   /* SHC[a]:       SHift Contour                                           */
5224*37da2899SCharles.Forsyth   /* Opcode range: 0x34-35                                                 */
5225*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
5226*37da2899SCharles.Forsyth   /*                                                                       */
5227*37da2899SCharles.Forsyth   static void
Ins_SHC(INS_ARG)5228*37da2899SCharles.Forsyth   Ins_SHC( INS_ARG )
5229*37da2899SCharles.Forsyth   {
5230*37da2899SCharles.Forsyth     TT_GlyphZoneRec zp;
5231*37da2899SCharles.Forsyth     FT_UShort       refp;
5232*37da2899SCharles.Forsyth     FT_F26Dot6      dx,
5233*37da2899SCharles.Forsyth                     dy;
5234*37da2899SCharles.Forsyth 
5235*37da2899SCharles.Forsyth     FT_Short        contour;
5236*37da2899SCharles.Forsyth     FT_UShort       first_point, last_point, i;
5237*37da2899SCharles.Forsyth 
5238*37da2899SCharles.Forsyth 
5239*37da2899SCharles.Forsyth     contour = (FT_UShort)args[0];
5240*37da2899SCharles.Forsyth 
5241*37da2899SCharles.Forsyth     if ( BOUNDS( contour, CUR.pts.n_contours ) )
5242*37da2899SCharles.Forsyth     {
5243*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5244*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5245*37da2899SCharles.Forsyth       return;
5246*37da2899SCharles.Forsyth     }
5247*37da2899SCharles.Forsyth 
5248*37da2899SCharles.Forsyth     if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5249*37da2899SCharles.Forsyth       return;
5250*37da2899SCharles.Forsyth 
5251*37da2899SCharles.Forsyth     if ( contour == 0 )
5252*37da2899SCharles.Forsyth       first_point = 0;
5253*37da2899SCharles.Forsyth     else
5254*37da2899SCharles.Forsyth       first_point = (FT_UShort)(CUR.pts.contours[contour - 1] + 1);
5255*37da2899SCharles.Forsyth 
5256*37da2899SCharles.Forsyth     last_point = CUR.pts.contours[contour];
5257*37da2899SCharles.Forsyth 
5258*37da2899SCharles.Forsyth     /* XXX: this is probably wrong... at least it prevents memory */
5259*37da2899SCharles.Forsyth     /*      corruption when zp2 is the twilight zone              */
5260*37da2899SCharles.Forsyth     if ( last_point > CUR.zp2.n_points )
5261*37da2899SCharles.Forsyth     {
5262*37da2899SCharles.Forsyth       if ( CUR.zp2.n_points > 0 )
5263*37da2899SCharles.Forsyth         last_point = (FT_UShort)(CUR.zp2.n_points - 1);
5264*37da2899SCharles.Forsyth       else
5265*37da2899SCharles.Forsyth         last_point = 0;
5266*37da2899SCharles.Forsyth     }
5267*37da2899SCharles.Forsyth 
5268*37da2899SCharles.Forsyth     /* XXX: UNDOCUMENTED! SHC doesn't touch the points */
5269*37da2899SCharles.Forsyth     for ( i = first_point; i <= last_point; i++ )
5270*37da2899SCharles.Forsyth     {
5271*37da2899SCharles.Forsyth       if ( zp.cur != CUR.zp2.cur || refp != i )
5272*37da2899SCharles.Forsyth         MOVE_Zp2_Point( i, dx, dy, FALSE );
5273*37da2899SCharles.Forsyth     }
5274*37da2899SCharles.Forsyth   }
5275*37da2899SCharles.Forsyth 
5276*37da2899SCharles.Forsyth 
5277*37da2899SCharles.Forsyth   /*************************************************************************/
5278*37da2899SCharles.Forsyth   /*                                                                       */
5279*37da2899SCharles.Forsyth   /* SHZ[a]:       SHift Zone                                              */
5280*37da2899SCharles.Forsyth   /* Opcode range: 0x36-37                                                 */
5281*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
5282*37da2899SCharles.Forsyth   /*                                                                       */
5283*37da2899SCharles.Forsyth   static void
Ins_SHZ(INS_ARG)5284*37da2899SCharles.Forsyth   Ins_SHZ( INS_ARG )
5285*37da2899SCharles.Forsyth   {
5286*37da2899SCharles.Forsyth     TT_GlyphZoneRec zp;
5287*37da2899SCharles.Forsyth     FT_UShort       refp;
5288*37da2899SCharles.Forsyth     FT_F26Dot6      dx,
5289*37da2899SCharles.Forsyth                     dy;
5290*37da2899SCharles.Forsyth 
5291*37da2899SCharles.Forsyth     FT_UShort       last_point, i;
5292*37da2899SCharles.Forsyth 
5293*37da2899SCharles.Forsyth 
5294*37da2899SCharles.Forsyth     if ( BOUNDS( args[0], 2 ) )
5295*37da2899SCharles.Forsyth     {
5296*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5297*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5298*37da2899SCharles.Forsyth       return;
5299*37da2899SCharles.Forsyth     }
5300*37da2899SCharles.Forsyth 
5301*37da2899SCharles.Forsyth     if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5302*37da2899SCharles.Forsyth       return;
5303*37da2899SCharles.Forsyth 
5304*37da2899SCharles.Forsyth     if ( CUR.zp2.n_points > 0 )
5305*37da2899SCharles.Forsyth       last_point = (FT_UShort)(CUR.zp2.n_points - 1);
5306*37da2899SCharles.Forsyth     else
5307*37da2899SCharles.Forsyth       last_point = 0;
5308*37da2899SCharles.Forsyth 
5309*37da2899SCharles.Forsyth     /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
5310*37da2899SCharles.Forsyth     for ( i = 0; i <= last_point; i++ )
5311*37da2899SCharles.Forsyth     {
5312*37da2899SCharles.Forsyth       if ( zp.cur != CUR.zp2.cur || refp != i )
5313*37da2899SCharles.Forsyth         MOVE_Zp2_Point( i, dx, dy, FALSE );
5314*37da2899SCharles.Forsyth     }
5315*37da2899SCharles.Forsyth   }
5316*37da2899SCharles.Forsyth 
5317*37da2899SCharles.Forsyth 
5318*37da2899SCharles.Forsyth   /*************************************************************************/
5319*37da2899SCharles.Forsyth   /*                                                                       */
5320*37da2899SCharles.Forsyth   /* SHPIX[]:      SHift points by a PIXel amount                          */
5321*37da2899SCharles.Forsyth   /* Opcode range: 0x38                                                    */
5322*37da2899SCharles.Forsyth   /* Stack:        f26.6 uint32... -->                                     */
5323*37da2899SCharles.Forsyth   /*                                                                       */
5324*37da2899SCharles.Forsyth   static void
Ins_SHPIX(INS_ARG)5325*37da2899SCharles.Forsyth   Ins_SHPIX( INS_ARG )
5326*37da2899SCharles.Forsyth   {
5327*37da2899SCharles.Forsyth     FT_F26Dot6  dx, dy;
5328*37da2899SCharles.Forsyth     FT_UShort   point;
5329*37da2899SCharles.Forsyth 
5330*37da2899SCharles.Forsyth 
5331*37da2899SCharles.Forsyth     if ( CUR.top < CUR.GS.loop + 1 )
5332*37da2899SCharles.Forsyth     {
5333*37da2899SCharles.Forsyth       CUR.error = TT_Err_Invalid_Reference;
5334*37da2899SCharles.Forsyth       return;
5335*37da2899SCharles.Forsyth     }
5336*37da2899SCharles.Forsyth 
5337*37da2899SCharles.Forsyth     dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
5338*37da2899SCharles.Forsyth     dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
5339*37da2899SCharles.Forsyth 
5340*37da2899SCharles.Forsyth     while ( CUR.GS.loop > 0 )
5341*37da2899SCharles.Forsyth     {
5342*37da2899SCharles.Forsyth       CUR.args--;
5343*37da2899SCharles.Forsyth 
5344*37da2899SCharles.Forsyth       point = (FT_UShort)CUR.stack[CUR.args];
5345*37da2899SCharles.Forsyth 
5346*37da2899SCharles.Forsyth       if ( BOUNDS( point, CUR.zp2.n_points ) )
5347*37da2899SCharles.Forsyth       {
5348*37da2899SCharles.Forsyth         if ( CUR.pedantic_hinting )
5349*37da2899SCharles.Forsyth         {
5350*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Reference;
5351*37da2899SCharles.Forsyth           return;
5352*37da2899SCharles.Forsyth         }
5353*37da2899SCharles.Forsyth       }
5354*37da2899SCharles.Forsyth       else
5355*37da2899SCharles.Forsyth         MOVE_Zp2_Point( point, dx, dy, TRUE );
5356*37da2899SCharles.Forsyth 
5357*37da2899SCharles.Forsyth       CUR.GS.loop--;
5358*37da2899SCharles.Forsyth     }
5359*37da2899SCharles.Forsyth 
5360*37da2899SCharles.Forsyth     CUR.GS.loop = 1;
5361*37da2899SCharles.Forsyth     CUR.new_top = CUR.args;
5362*37da2899SCharles.Forsyth   }
5363*37da2899SCharles.Forsyth 
5364*37da2899SCharles.Forsyth 
5365*37da2899SCharles.Forsyth   /*************************************************************************/
5366*37da2899SCharles.Forsyth   /*                                                                       */
5367*37da2899SCharles.Forsyth   /* MSIRP[a]:     Move Stack Indirect Relative Position                   */
5368*37da2899SCharles.Forsyth   /* Opcode range: 0x3A-0x3B                                               */
5369*37da2899SCharles.Forsyth   /* Stack:        f26.6 uint32 -->                                        */
5370*37da2899SCharles.Forsyth   /*                                                                       */
5371*37da2899SCharles.Forsyth   static void
Ins_MSIRP(INS_ARG)5372*37da2899SCharles.Forsyth   Ins_MSIRP( INS_ARG )
5373*37da2899SCharles.Forsyth   {
5374*37da2899SCharles.Forsyth     FT_UShort   point;
5375*37da2899SCharles.Forsyth     FT_F26Dot6  distance;
5376*37da2899SCharles.Forsyth 
5377*37da2899SCharles.Forsyth 
5378*37da2899SCharles.Forsyth     point = (FT_UShort)args[0];
5379*37da2899SCharles.Forsyth 
5380*37da2899SCharles.Forsyth     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
5381*37da2899SCharles.Forsyth          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5382*37da2899SCharles.Forsyth     {
5383*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5384*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5385*37da2899SCharles.Forsyth       return;
5386*37da2899SCharles.Forsyth     }
5387*37da2899SCharles.Forsyth 
5388*37da2899SCharles.Forsyth     /* XXX: UNDOCUMENTED! behaviour */
5389*37da2899SCharles.Forsyth     if ( CUR.GS.gep0 == 0 )   /* if in twilight zone */
5390*37da2899SCharles.Forsyth     {
5391*37da2899SCharles.Forsyth       CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
5392*37da2899SCharles.Forsyth       CUR.zp1.cur[point] = CUR.zp1.org[point];
5393*37da2899SCharles.Forsyth     }
5394*37da2899SCharles.Forsyth 
5395*37da2899SCharles.Forsyth     distance = CUR_Func_project( CUR.zp1.cur + point,
5396*37da2899SCharles.Forsyth                                  CUR.zp0.cur + CUR.GS.rp0 );
5397*37da2899SCharles.Forsyth 
5398*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp1, point, args[1] - distance );
5399*37da2899SCharles.Forsyth 
5400*37da2899SCharles.Forsyth     CUR.GS.rp1 = CUR.GS.rp0;
5401*37da2899SCharles.Forsyth     CUR.GS.rp2 = point;
5402*37da2899SCharles.Forsyth 
5403*37da2899SCharles.Forsyth     if ( (CUR.opcode & 1) != 0 )
5404*37da2899SCharles.Forsyth       CUR.GS.rp0 = point;
5405*37da2899SCharles.Forsyth   }
5406*37da2899SCharles.Forsyth 
5407*37da2899SCharles.Forsyth 
5408*37da2899SCharles.Forsyth   /*************************************************************************/
5409*37da2899SCharles.Forsyth   /*                                                                       */
5410*37da2899SCharles.Forsyth   /* MDAP[a]:      Move Direct Absolute Point                              */
5411*37da2899SCharles.Forsyth   /* Opcode range: 0x2E-0x2F                                               */
5412*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
5413*37da2899SCharles.Forsyth   /*                                                                       */
5414*37da2899SCharles.Forsyth   static void
Ins_MDAP(INS_ARG)5415*37da2899SCharles.Forsyth   Ins_MDAP( INS_ARG )
5416*37da2899SCharles.Forsyth   {
5417*37da2899SCharles.Forsyth     FT_UShort   point;
5418*37da2899SCharles.Forsyth     FT_F26Dot6  cur_dist,
5419*37da2899SCharles.Forsyth                 distance;
5420*37da2899SCharles.Forsyth 
5421*37da2899SCharles.Forsyth 
5422*37da2899SCharles.Forsyth     point = (FT_UShort)args[0];
5423*37da2899SCharles.Forsyth 
5424*37da2899SCharles.Forsyth     if ( BOUNDS( point, CUR.zp0.n_points ) )
5425*37da2899SCharles.Forsyth     {
5426*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5427*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5428*37da2899SCharles.Forsyth       return;
5429*37da2899SCharles.Forsyth     }
5430*37da2899SCharles.Forsyth 
5431*37da2899SCharles.Forsyth     /* XXX: Is there some undocumented feature while in the */
5432*37da2899SCharles.Forsyth     /*      twilight zone? ?                                */
5433*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 1 ) != 0 )
5434*37da2899SCharles.Forsyth     {
5435*37da2899SCharles.Forsyth       cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
5436*37da2899SCharles.Forsyth       distance = CUR_Func_round( cur_dist,
5437*37da2899SCharles.Forsyth                                  CUR.tt_metrics.compensations[0] ) - cur_dist;
5438*37da2899SCharles.Forsyth     }
5439*37da2899SCharles.Forsyth     else
5440*37da2899SCharles.Forsyth       distance = 0;
5441*37da2899SCharles.Forsyth 
5442*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp0, point, distance );
5443*37da2899SCharles.Forsyth 
5444*37da2899SCharles.Forsyth     CUR.GS.rp0 = point;
5445*37da2899SCharles.Forsyth     CUR.GS.rp1 = point;
5446*37da2899SCharles.Forsyth   }
5447*37da2899SCharles.Forsyth 
5448*37da2899SCharles.Forsyth 
5449*37da2899SCharles.Forsyth   /*************************************************************************/
5450*37da2899SCharles.Forsyth   /*                                                                       */
5451*37da2899SCharles.Forsyth   /* MIAP[a]:      Move Indirect Absolute Point                            */
5452*37da2899SCharles.Forsyth   /* Opcode range: 0x3E-0x3F                                               */
5453*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
5454*37da2899SCharles.Forsyth   /*                                                                       */
5455*37da2899SCharles.Forsyth   static void
Ins_MIAP(INS_ARG)5456*37da2899SCharles.Forsyth   Ins_MIAP( INS_ARG )
5457*37da2899SCharles.Forsyth   {
5458*37da2899SCharles.Forsyth     FT_ULong    cvtEntry;
5459*37da2899SCharles.Forsyth     FT_UShort   point;
5460*37da2899SCharles.Forsyth     FT_F26Dot6  distance,
5461*37da2899SCharles.Forsyth                 org_dist;
5462*37da2899SCharles.Forsyth 
5463*37da2899SCharles.Forsyth 
5464*37da2899SCharles.Forsyth     cvtEntry = (FT_ULong)args[1];
5465*37da2899SCharles.Forsyth     point    = (FT_UShort)args[0];
5466*37da2899SCharles.Forsyth 
5467*37da2899SCharles.Forsyth     if ( BOUNDS( point,    CUR.zp0.n_points ) ||
5468*37da2899SCharles.Forsyth          BOUNDS( cvtEntry, CUR.cvtSize )      )
5469*37da2899SCharles.Forsyth     {
5470*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5471*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5472*37da2899SCharles.Forsyth       return;
5473*37da2899SCharles.Forsyth     }
5474*37da2899SCharles.Forsyth 
5475*37da2899SCharles.Forsyth     /* UNDOCUMENTED!                                     */
5476*37da2899SCharles.Forsyth     /*                                                   */
5477*37da2899SCharles.Forsyth     /* The behaviour of an MIAP instruction is quite     */
5478*37da2899SCharles.Forsyth     /* different when used in the twilight zone.         */
5479*37da2899SCharles.Forsyth     /*                                                   */
5480*37da2899SCharles.Forsyth     /* First, no control value cutin test is performed   */
5481*37da2899SCharles.Forsyth     /* as it would fail anyway.  Second, the original    */
5482*37da2899SCharles.Forsyth     /* point, i.e. (org_x,org_y) of zp0.point, is set    */
5483*37da2899SCharles.Forsyth     /* to the absolute, unrounded distance found in      */
5484*37da2899SCharles.Forsyth     /* the CVT.                                          */
5485*37da2899SCharles.Forsyth     /*                                                   */
5486*37da2899SCharles.Forsyth     /* This is used in the CVT programs of the Microsoft */
5487*37da2899SCharles.Forsyth     /* fonts Arial, Times, etc., in order to re-adjust   */
5488*37da2899SCharles.Forsyth     /* some key font heights.  It allows the use of the  */
5489*37da2899SCharles.Forsyth     /* IP instruction in the twilight zone, which        */
5490*37da2899SCharles.Forsyth     /* otherwise would be `illegal' according to the     */
5491*37da2899SCharles.Forsyth     /* specification.                                    */
5492*37da2899SCharles.Forsyth     /*                                                   */
5493*37da2899SCharles.Forsyth     /* We implement it with a special sequence for the   */
5494*37da2899SCharles.Forsyth     /* twilight zone.  This is a bad hack, but it seems  */
5495*37da2899SCharles.Forsyth     /* to work.                                          */
5496*37da2899SCharles.Forsyth 
5497*37da2899SCharles.Forsyth     distance = CUR_Func_read_cvt( cvtEntry );
5498*37da2899SCharles.Forsyth 
5499*37da2899SCharles.Forsyth     if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
5500*37da2899SCharles.Forsyth     {
5501*37da2899SCharles.Forsyth       CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );
5502*37da2899SCharles.Forsyth       CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ),
5503*37da2899SCharles.Forsyth       CUR.zp0.cur[point]   = CUR.zp0.org[point];
5504*37da2899SCharles.Forsyth     }
5505*37da2899SCharles.Forsyth 
5506*37da2899SCharles.Forsyth     org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
5507*37da2899SCharles.Forsyth 
5508*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */
5509*37da2899SCharles.Forsyth     {
5510*37da2899SCharles.Forsyth       if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
5511*37da2899SCharles.Forsyth         distance = org_dist;
5512*37da2899SCharles.Forsyth 
5513*37da2899SCharles.Forsyth       distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
5514*37da2899SCharles.Forsyth     }
5515*37da2899SCharles.Forsyth 
5516*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp0, point, distance - org_dist );
5517*37da2899SCharles.Forsyth 
5518*37da2899SCharles.Forsyth     CUR.GS.rp0 = point;
5519*37da2899SCharles.Forsyth     CUR.GS.rp1 = point;
5520*37da2899SCharles.Forsyth   }
5521*37da2899SCharles.Forsyth 
5522*37da2899SCharles.Forsyth 
5523*37da2899SCharles.Forsyth   /*************************************************************************/
5524*37da2899SCharles.Forsyth   /*                                                                       */
5525*37da2899SCharles.Forsyth   /* MDRP[abcde]:  Move Direct Relative Point                              */
5526*37da2899SCharles.Forsyth   /* Opcode range: 0xC0-0xDF                                               */
5527*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
5528*37da2899SCharles.Forsyth   /*                                                                       */
5529*37da2899SCharles.Forsyth   static void
Ins_MDRP(INS_ARG)5530*37da2899SCharles.Forsyth   Ins_MDRP( INS_ARG )
5531*37da2899SCharles.Forsyth   {
5532*37da2899SCharles.Forsyth     FT_UShort   point;
5533*37da2899SCharles.Forsyth     FT_F26Dot6  org_dist, distance;
5534*37da2899SCharles.Forsyth 
5535*37da2899SCharles.Forsyth 
5536*37da2899SCharles.Forsyth     point = (FT_UShort)args[0];
5537*37da2899SCharles.Forsyth 
5538*37da2899SCharles.Forsyth     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
5539*37da2899SCharles.Forsyth          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5540*37da2899SCharles.Forsyth     {
5541*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5542*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5543*37da2899SCharles.Forsyth       return;
5544*37da2899SCharles.Forsyth     }
5545*37da2899SCharles.Forsyth 
5546*37da2899SCharles.Forsyth     /* XXX: Is there some undocumented feature while in the */
5547*37da2899SCharles.Forsyth     /*      twilight zone?                                  */
5548*37da2899SCharles.Forsyth 
5549*37da2899SCharles.Forsyth     org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
5550*37da2899SCharles.Forsyth                                   CUR.zp0.org + CUR.GS.rp0 );
5551*37da2899SCharles.Forsyth 
5552*37da2899SCharles.Forsyth     /* single width cutin test */
5553*37da2899SCharles.Forsyth 
5554*37da2899SCharles.Forsyth     if ( ABS( org_dist ) < CUR.GS.single_width_cutin )
5555*37da2899SCharles.Forsyth     {
5556*37da2899SCharles.Forsyth       if ( org_dist >= 0 )
5557*37da2899SCharles.Forsyth         org_dist = CUR.GS.single_width_value;
5558*37da2899SCharles.Forsyth       else
5559*37da2899SCharles.Forsyth         org_dist = -CUR.GS.single_width_value;
5560*37da2899SCharles.Forsyth     }
5561*37da2899SCharles.Forsyth 
5562*37da2899SCharles.Forsyth     /* round flag */
5563*37da2899SCharles.Forsyth 
5564*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 4 ) != 0 )
5565*37da2899SCharles.Forsyth       distance = CUR_Func_round(
5566*37da2899SCharles.Forsyth                    org_dist,
5567*37da2899SCharles.Forsyth                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
5568*37da2899SCharles.Forsyth     else
5569*37da2899SCharles.Forsyth       distance = ROUND_None(
5570*37da2899SCharles.Forsyth                    org_dist,
5571*37da2899SCharles.Forsyth                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
5572*37da2899SCharles.Forsyth 
5573*37da2899SCharles.Forsyth     /* minimum distance flag */
5574*37da2899SCharles.Forsyth 
5575*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 8 ) != 0 )
5576*37da2899SCharles.Forsyth     {
5577*37da2899SCharles.Forsyth       if ( org_dist >= 0 )
5578*37da2899SCharles.Forsyth       {
5579*37da2899SCharles.Forsyth         if ( distance < CUR.GS.minimum_distance )
5580*37da2899SCharles.Forsyth           distance = CUR.GS.minimum_distance;
5581*37da2899SCharles.Forsyth       }
5582*37da2899SCharles.Forsyth       else
5583*37da2899SCharles.Forsyth       {
5584*37da2899SCharles.Forsyth         if ( distance > -CUR.GS.minimum_distance )
5585*37da2899SCharles.Forsyth           distance = -CUR.GS.minimum_distance;
5586*37da2899SCharles.Forsyth       }
5587*37da2899SCharles.Forsyth     }
5588*37da2899SCharles.Forsyth 
5589*37da2899SCharles.Forsyth     /* now move the point */
5590*37da2899SCharles.Forsyth 
5591*37da2899SCharles.Forsyth     org_dist = CUR_Func_project( CUR.zp1.cur + point,
5592*37da2899SCharles.Forsyth                                  CUR.zp0.cur + CUR.GS.rp0 );
5593*37da2899SCharles.Forsyth 
5594*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp1, point, distance - org_dist );
5595*37da2899SCharles.Forsyth 
5596*37da2899SCharles.Forsyth     CUR.GS.rp1 = CUR.GS.rp0;
5597*37da2899SCharles.Forsyth     CUR.GS.rp2 = point;
5598*37da2899SCharles.Forsyth 
5599*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 16 ) != 0 )
5600*37da2899SCharles.Forsyth       CUR.GS.rp0 = point;
5601*37da2899SCharles.Forsyth   }
5602*37da2899SCharles.Forsyth 
5603*37da2899SCharles.Forsyth 
5604*37da2899SCharles.Forsyth   /*************************************************************************/
5605*37da2899SCharles.Forsyth   /*                                                                       */
5606*37da2899SCharles.Forsyth   /* MIRP[abcde]:  Move Indirect Relative Point                            */
5607*37da2899SCharles.Forsyth   /* Opcode range: 0xE0-0xFF                                               */
5608*37da2899SCharles.Forsyth   /* Stack:        int32? uint32 -->                                       */
5609*37da2899SCharles.Forsyth   /*                                                                       */
5610*37da2899SCharles.Forsyth   static void
Ins_MIRP(INS_ARG)5611*37da2899SCharles.Forsyth   Ins_MIRP( INS_ARG )
5612*37da2899SCharles.Forsyth   {
5613*37da2899SCharles.Forsyth     FT_UShort   point;
5614*37da2899SCharles.Forsyth     FT_ULong    cvtEntry;
5615*37da2899SCharles.Forsyth 
5616*37da2899SCharles.Forsyth     FT_F26Dot6  cvt_dist,
5617*37da2899SCharles.Forsyth                 distance,
5618*37da2899SCharles.Forsyth                 cur_dist,
5619*37da2899SCharles.Forsyth                 org_dist;
5620*37da2899SCharles.Forsyth 
5621*37da2899SCharles.Forsyth 
5622*37da2899SCharles.Forsyth     point    = (FT_UShort)args[0];
5623*37da2899SCharles.Forsyth     cvtEntry = (FT_ULong)( args[1] + 1 );
5624*37da2899SCharles.Forsyth 
5625*37da2899SCharles.Forsyth     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
5626*37da2899SCharles.Forsyth 
5627*37da2899SCharles.Forsyth     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
5628*37da2899SCharles.Forsyth          BOUNDS( cvtEntry,   CUR.cvtSize + 1 )  ||
5629*37da2899SCharles.Forsyth          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5630*37da2899SCharles.Forsyth     {
5631*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5632*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5633*37da2899SCharles.Forsyth       return;
5634*37da2899SCharles.Forsyth     }
5635*37da2899SCharles.Forsyth 
5636*37da2899SCharles.Forsyth     if ( !cvtEntry )
5637*37da2899SCharles.Forsyth       cvt_dist = 0;
5638*37da2899SCharles.Forsyth     else
5639*37da2899SCharles.Forsyth       cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
5640*37da2899SCharles.Forsyth 
5641*37da2899SCharles.Forsyth     /* single width test */
5642*37da2899SCharles.Forsyth 
5643*37da2899SCharles.Forsyth     if ( ABS( cvt_dist ) < CUR.GS.single_width_cutin )
5644*37da2899SCharles.Forsyth     {
5645*37da2899SCharles.Forsyth       if ( cvt_dist >= 0 )
5646*37da2899SCharles.Forsyth         cvt_dist =  CUR.GS.single_width_value;
5647*37da2899SCharles.Forsyth       else
5648*37da2899SCharles.Forsyth         cvt_dist = -CUR.GS.single_width_value;
5649*37da2899SCharles.Forsyth     }
5650*37da2899SCharles.Forsyth 
5651*37da2899SCharles.Forsyth     /* XXX: UNDOCUMENTED! -- twilight zone */
5652*37da2899SCharles.Forsyth 
5653*37da2899SCharles.Forsyth     if ( CUR.GS.gep1 == 0 )
5654*37da2899SCharles.Forsyth     {
5655*37da2899SCharles.Forsyth       CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
5656*37da2899SCharles.Forsyth                              TT_MulFix14( cvt_dist, CUR.GS.freeVector.x );
5657*37da2899SCharles.Forsyth 
5658*37da2899SCharles.Forsyth       CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
5659*37da2899SCharles.Forsyth                              TT_MulFix14( cvt_dist, CUR.GS.freeVector.y );
5660*37da2899SCharles.Forsyth 
5661*37da2899SCharles.Forsyth       CUR.zp1.cur[point] = CUR.zp1.org[point];
5662*37da2899SCharles.Forsyth     }
5663*37da2899SCharles.Forsyth 
5664*37da2899SCharles.Forsyth     org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
5665*37da2899SCharles.Forsyth                                   CUR.zp0.org + CUR.GS.rp0 );
5666*37da2899SCharles.Forsyth 
5667*37da2899SCharles.Forsyth     cur_dist = CUR_Func_project( CUR.zp1.cur + point,
5668*37da2899SCharles.Forsyth                                  CUR.zp0.cur + CUR.GS.rp0 );
5669*37da2899SCharles.Forsyth 
5670*37da2899SCharles.Forsyth     /* auto-flip test */
5671*37da2899SCharles.Forsyth 
5672*37da2899SCharles.Forsyth     if ( CUR.GS.auto_flip )
5673*37da2899SCharles.Forsyth     {
5674*37da2899SCharles.Forsyth       if ( ( org_dist ^ cvt_dist ) < 0 )
5675*37da2899SCharles.Forsyth         cvt_dist = -cvt_dist;
5676*37da2899SCharles.Forsyth     }
5677*37da2899SCharles.Forsyth 
5678*37da2899SCharles.Forsyth     /* control value cutin and round */
5679*37da2899SCharles.Forsyth 
5680*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 4 ) != 0 )
5681*37da2899SCharles.Forsyth     {
5682*37da2899SCharles.Forsyth       /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
5683*37da2899SCharles.Forsyth       /*      refer to the same zone.                                  */
5684*37da2899SCharles.Forsyth 
5685*37da2899SCharles.Forsyth       if ( CUR.GS.gep0 == CUR.GS.gep1 )
5686*37da2899SCharles.Forsyth         if ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
5687*37da2899SCharles.Forsyth           cvt_dist = org_dist;
5688*37da2899SCharles.Forsyth 
5689*37da2899SCharles.Forsyth       distance = CUR_Func_round(
5690*37da2899SCharles.Forsyth                    cvt_dist,
5691*37da2899SCharles.Forsyth                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
5692*37da2899SCharles.Forsyth     }
5693*37da2899SCharles.Forsyth     else
5694*37da2899SCharles.Forsyth       distance = ROUND_None(
5695*37da2899SCharles.Forsyth                    cvt_dist,
5696*37da2899SCharles.Forsyth                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
5697*37da2899SCharles.Forsyth 
5698*37da2899SCharles.Forsyth     /* minimum distance test */
5699*37da2899SCharles.Forsyth 
5700*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 8 ) != 0 )
5701*37da2899SCharles.Forsyth     {
5702*37da2899SCharles.Forsyth       if ( org_dist >= 0 )
5703*37da2899SCharles.Forsyth       {
5704*37da2899SCharles.Forsyth         if ( distance < CUR.GS.minimum_distance )
5705*37da2899SCharles.Forsyth           distance = CUR.GS.minimum_distance;
5706*37da2899SCharles.Forsyth       }
5707*37da2899SCharles.Forsyth       else
5708*37da2899SCharles.Forsyth       {
5709*37da2899SCharles.Forsyth         if ( distance > -CUR.GS.minimum_distance )
5710*37da2899SCharles.Forsyth           distance = -CUR.GS.minimum_distance;
5711*37da2899SCharles.Forsyth       }
5712*37da2899SCharles.Forsyth     }
5713*37da2899SCharles.Forsyth 
5714*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
5715*37da2899SCharles.Forsyth 
5716*37da2899SCharles.Forsyth     CUR.GS.rp1 = CUR.GS.rp0;
5717*37da2899SCharles.Forsyth 
5718*37da2899SCharles.Forsyth     if ( ( CUR.opcode & 16 ) != 0 )
5719*37da2899SCharles.Forsyth       CUR.GS.rp0 = point;
5720*37da2899SCharles.Forsyth 
5721*37da2899SCharles.Forsyth     /* XXX: UNDOCUMENTED! */
5722*37da2899SCharles.Forsyth 
5723*37da2899SCharles.Forsyth     CUR.GS.rp2 = point;
5724*37da2899SCharles.Forsyth   }
5725*37da2899SCharles.Forsyth 
5726*37da2899SCharles.Forsyth 
5727*37da2899SCharles.Forsyth   /*************************************************************************/
5728*37da2899SCharles.Forsyth   /*                                                                       */
5729*37da2899SCharles.Forsyth   /* ALIGNRP[]:    ALIGN Relative Point                                    */
5730*37da2899SCharles.Forsyth   /* Opcode range: 0x3C                                                    */
5731*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32... -->                                    */
5732*37da2899SCharles.Forsyth   /*                                                                       */
5733*37da2899SCharles.Forsyth   static void
Ins_ALIGNRP(INS_ARG)5734*37da2899SCharles.Forsyth   Ins_ALIGNRP( INS_ARG )
5735*37da2899SCharles.Forsyth   {
5736*37da2899SCharles.Forsyth     FT_UShort   point;
5737*37da2899SCharles.Forsyth     FT_F26Dot6  distance;
5738*37da2899SCharles.Forsyth 
5739*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
5740*37da2899SCharles.Forsyth 
5741*37da2899SCharles.Forsyth 
5742*37da2899SCharles.Forsyth     if ( CUR.top < CUR.GS.loop ||
5743*37da2899SCharles.Forsyth          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5744*37da2899SCharles.Forsyth     {
5745*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5746*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5747*37da2899SCharles.Forsyth       return;
5748*37da2899SCharles.Forsyth     }
5749*37da2899SCharles.Forsyth 
5750*37da2899SCharles.Forsyth     while ( CUR.GS.loop > 0 )
5751*37da2899SCharles.Forsyth     {
5752*37da2899SCharles.Forsyth       CUR.args--;
5753*37da2899SCharles.Forsyth 
5754*37da2899SCharles.Forsyth       point = (FT_UShort)CUR.stack[CUR.args];
5755*37da2899SCharles.Forsyth 
5756*37da2899SCharles.Forsyth       if ( BOUNDS( point, CUR.zp1.n_points ) )
5757*37da2899SCharles.Forsyth       {
5758*37da2899SCharles.Forsyth         if ( CUR.pedantic_hinting )
5759*37da2899SCharles.Forsyth         {
5760*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Reference;
5761*37da2899SCharles.Forsyth           return;
5762*37da2899SCharles.Forsyth         }
5763*37da2899SCharles.Forsyth       }
5764*37da2899SCharles.Forsyth       else
5765*37da2899SCharles.Forsyth       {
5766*37da2899SCharles.Forsyth         distance = CUR_Func_project( CUR.zp1.cur + point,
5767*37da2899SCharles.Forsyth                                      CUR.zp0.cur + CUR.GS.rp0 );
5768*37da2899SCharles.Forsyth 
5769*37da2899SCharles.Forsyth         CUR_Func_move( &CUR.zp1, point, -distance );
5770*37da2899SCharles.Forsyth       }
5771*37da2899SCharles.Forsyth 
5772*37da2899SCharles.Forsyth       CUR.GS.loop--;
5773*37da2899SCharles.Forsyth     }
5774*37da2899SCharles.Forsyth 
5775*37da2899SCharles.Forsyth     CUR.GS.loop = 1;
5776*37da2899SCharles.Forsyth     CUR.new_top = CUR.args;
5777*37da2899SCharles.Forsyth   }
5778*37da2899SCharles.Forsyth 
5779*37da2899SCharles.Forsyth 
5780*37da2899SCharles.Forsyth   /*************************************************************************/
5781*37da2899SCharles.Forsyth   /*                                                                       */
5782*37da2899SCharles.Forsyth   /* ISECT[]:      moves point to InterSECTion                             */
5783*37da2899SCharles.Forsyth   /* Opcode range: 0x0F                                                    */
5784*37da2899SCharles.Forsyth   /* Stack:        5 * uint32 -->                                          */
5785*37da2899SCharles.Forsyth   /*                                                                       */
5786*37da2899SCharles.Forsyth   static void
Ins_ISECT(INS_ARG)5787*37da2899SCharles.Forsyth   Ins_ISECT( INS_ARG )
5788*37da2899SCharles.Forsyth   {
5789*37da2899SCharles.Forsyth     FT_UShort   point,
5790*37da2899SCharles.Forsyth                 a0, a1,
5791*37da2899SCharles.Forsyth                 b0, b1;
5792*37da2899SCharles.Forsyth 
5793*37da2899SCharles.Forsyth     FT_F26Dot6  discriminant;
5794*37da2899SCharles.Forsyth 
5795*37da2899SCharles.Forsyth     FT_F26Dot6  dx,  dy,
5796*37da2899SCharles.Forsyth                 dax, day,
5797*37da2899SCharles.Forsyth                 dbx, dby;
5798*37da2899SCharles.Forsyth 
5799*37da2899SCharles.Forsyth     FT_F26Dot6  val;
5800*37da2899SCharles.Forsyth 
5801*37da2899SCharles.Forsyth     FT_Vector   R;
5802*37da2899SCharles.Forsyth 
5803*37da2899SCharles.Forsyth 
5804*37da2899SCharles.Forsyth     point = (FT_UShort)args[0];
5805*37da2899SCharles.Forsyth 
5806*37da2899SCharles.Forsyth     a0 = (FT_UShort)args[1];
5807*37da2899SCharles.Forsyth     a1 = (FT_UShort)args[2];
5808*37da2899SCharles.Forsyth     b0 = (FT_UShort)args[3];
5809*37da2899SCharles.Forsyth     b1 = (FT_UShort)args[4];
5810*37da2899SCharles.Forsyth 
5811*37da2899SCharles.Forsyth     if ( BOUNDS( b0, CUR.zp0.n_points )  ||
5812*37da2899SCharles.Forsyth          BOUNDS( b1, CUR.zp0.n_points )  ||
5813*37da2899SCharles.Forsyth          BOUNDS( a0, CUR.zp1.n_points )  ||
5814*37da2899SCharles.Forsyth          BOUNDS( a1, CUR.zp1.n_points )  ||
5815*37da2899SCharles.Forsyth          BOUNDS( point, CUR.zp2.n_points ) )
5816*37da2899SCharles.Forsyth     {
5817*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5818*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5819*37da2899SCharles.Forsyth       return;
5820*37da2899SCharles.Forsyth     }
5821*37da2899SCharles.Forsyth 
5822*37da2899SCharles.Forsyth     dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
5823*37da2899SCharles.Forsyth     dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
5824*37da2899SCharles.Forsyth 
5825*37da2899SCharles.Forsyth     dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
5826*37da2899SCharles.Forsyth     day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
5827*37da2899SCharles.Forsyth 
5828*37da2899SCharles.Forsyth     dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
5829*37da2899SCharles.Forsyth     dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
5830*37da2899SCharles.Forsyth 
5831*37da2899SCharles.Forsyth     CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
5832*37da2899SCharles.Forsyth 
5833*37da2899SCharles.Forsyth     discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
5834*37da2899SCharles.Forsyth                    TT_MULDIV( day, dbx, 0x40 );
5835*37da2899SCharles.Forsyth 
5836*37da2899SCharles.Forsyth     if ( ABS( discriminant ) >= 0x40 )
5837*37da2899SCharles.Forsyth     {
5838*37da2899SCharles.Forsyth       val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
5839*37da2899SCharles.Forsyth 
5840*37da2899SCharles.Forsyth       R.x = TT_MULDIV( val, dax, discriminant );
5841*37da2899SCharles.Forsyth       R.y = TT_MULDIV( val, day, discriminant );
5842*37da2899SCharles.Forsyth 
5843*37da2899SCharles.Forsyth       CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
5844*37da2899SCharles.Forsyth       CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
5845*37da2899SCharles.Forsyth     }
5846*37da2899SCharles.Forsyth     else
5847*37da2899SCharles.Forsyth     {
5848*37da2899SCharles.Forsyth       /* else, take the middle of the middles of A and B */
5849*37da2899SCharles.Forsyth 
5850*37da2899SCharles.Forsyth       CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
5851*37da2899SCharles.Forsyth                                CUR.zp1.cur[a1].x +
5852*37da2899SCharles.Forsyth                                CUR.zp0.cur[b0].x +
5853*37da2899SCharles.Forsyth                                CUR.zp0.cur[b1].x ) / 4;
5854*37da2899SCharles.Forsyth       CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
5855*37da2899SCharles.Forsyth                                CUR.zp1.cur[a1].y +
5856*37da2899SCharles.Forsyth                                CUR.zp0.cur[b0].y +
5857*37da2899SCharles.Forsyth                                CUR.zp0.cur[b1].y ) / 4;
5858*37da2899SCharles.Forsyth     }
5859*37da2899SCharles.Forsyth   }
5860*37da2899SCharles.Forsyth 
5861*37da2899SCharles.Forsyth 
5862*37da2899SCharles.Forsyth   /*************************************************************************/
5863*37da2899SCharles.Forsyth   /*                                                                       */
5864*37da2899SCharles.Forsyth   /* ALIGNPTS[]:   ALIGN PoinTS                                            */
5865*37da2899SCharles.Forsyth   /* Opcode range: 0x27                                                    */
5866*37da2899SCharles.Forsyth   /* Stack:        uint32 uint32 -->                                       */
5867*37da2899SCharles.Forsyth   /*                                                                       */
5868*37da2899SCharles.Forsyth   static void
Ins_ALIGNPTS(INS_ARG)5869*37da2899SCharles.Forsyth   Ins_ALIGNPTS( INS_ARG )
5870*37da2899SCharles.Forsyth   {
5871*37da2899SCharles.Forsyth     FT_UShort   p1, p2;
5872*37da2899SCharles.Forsyth     FT_F26Dot6  distance;
5873*37da2899SCharles.Forsyth 
5874*37da2899SCharles.Forsyth 
5875*37da2899SCharles.Forsyth     p1 = (FT_UShort)args[0];
5876*37da2899SCharles.Forsyth     p2 = (FT_UShort)args[1];
5877*37da2899SCharles.Forsyth 
5878*37da2899SCharles.Forsyth     if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
5879*37da2899SCharles.Forsyth          BOUNDS( args[1], CUR.zp0.n_points ) )
5880*37da2899SCharles.Forsyth     {
5881*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
5882*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
5883*37da2899SCharles.Forsyth       return;
5884*37da2899SCharles.Forsyth     }
5885*37da2899SCharles.Forsyth 
5886*37da2899SCharles.Forsyth     distance = CUR_Func_project( CUR.zp0.cur + p2,
5887*37da2899SCharles.Forsyth                                  CUR.zp1.cur + p1 ) / 2;
5888*37da2899SCharles.Forsyth 
5889*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp1, p1, distance );
5890*37da2899SCharles.Forsyth     CUR_Func_move( &CUR.zp0, p2, -distance );
5891*37da2899SCharles.Forsyth   }
5892*37da2899SCharles.Forsyth 
5893*37da2899SCharles.Forsyth 
5894*37da2899SCharles.Forsyth   /*************************************************************************/
5895*37da2899SCharles.Forsyth   /*                                                                       */
5896*37da2899SCharles.Forsyth   /* IP[]:         Interpolate Point                                       */
5897*37da2899SCharles.Forsyth   /* Opcode range: 0x39                                                    */
5898*37da2899SCharles.Forsyth   /* Stack:        uint32... -->                                           */
5899*37da2899SCharles.Forsyth   /*                                                                       */
5900*37da2899SCharles.Forsyth   static void
Ins_IP(INS_ARG)5901*37da2899SCharles.Forsyth   Ins_IP( INS_ARG )
5902*37da2899SCharles.Forsyth   {
5903*37da2899SCharles.Forsyth     FT_F26Dot6  org_a, org_b, org_x,
5904*37da2899SCharles.Forsyth                 cur_a, cur_b, cur_x,
5905*37da2899SCharles.Forsyth                 distance;
5906*37da2899SCharles.Forsyth     FT_UShort   point;
5907*37da2899SCharles.Forsyth 
5908*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
5909*37da2899SCharles.Forsyth 
5910*37da2899SCharles.Forsyth 
5911*37da2899SCharles.Forsyth     if ( CUR.top < CUR.GS.loop )
5912*37da2899SCharles.Forsyth     {
5913*37da2899SCharles.Forsyth       CUR.error = TT_Err_Invalid_Reference;
5914*37da2899SCharles.Forsyth       return;
5915*37da2899SCharles.Forsyth     }
5916*37da2899SCharles.Forsyth 
5917*37da2899SCharles.Forsyth     /* XXX: There are some glyphs in some braindead but popular  */
5918*37da2899SCharles.Forsyth     /*      fonts out there (e.g. [aeu]grave in monotype.ttf)    */
5919*37da2899SCharles.Forsyth     /*      calling IP[] with bad values of rp[12].              */
5920*37da2899SCharles.Forsyth     /*      Do something sane when this odd thing happens.       */
5921*37da2899SCharles.Forsyth 
5922*37da2899SCharles.Forsyth     if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
5923*37da2899SCharles.Forsyth          BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
5924*37da2899SCharles.Forsyth     {
5925*37da2899SCharles.Forsyth       org_a = cur_a = 0;
5926*37da2899SCharles.Forsyth       org_b = cur_b = 0;
5927*37da2899SCharles.Forsyth     }
5928*37da2899SCharles.Forsyth     else
5929*37da2899SCharles.Forsyth     {
5930*37da2899SCharles.Forsyth       org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector );
5931*37da2899SCharles.Forsyth       org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector );
5932*37da2899SCharles.Forsyth 
5933*37da2899SCharles.Forsyth       cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector );
5934*37da2899SCharles.Forsyth       cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector );
5935*37da2899SCharles.Forsyth     }
5936*37da2899SCharles.Forsyth 
5937*37da2899SCharles.Forsyth     while ( CUR.GS.loop > 0 )
5938*37da2899SCharles.Forsyth     {
5939*37da2899SCharles.Forsyth       CUR.args--;
5940*37da2899SCharles.Forsyth 
5941*37da2899SCharles.Forsyth       point = (FT_UShort)CUR.stack[CUR.args];
5942*37da2899SCharles.Forsyth       if ( BOUNDS( point, CUR.zp2.n_points ) )
5943*37da2899SCharles.Forsyth       {
5944*37da2899SCharles.Forsyth         if ( CUR.pedantic_hinting )
5945*37da2899SCharles.Forsyth         {
5946*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Reference;
5947*37da2899SCharles.Forsyth           return;
5948*37da2899SCharles.Forsyth         }
5949*37da2899SCharles.Forsyth       }
5950*37da2899SCharles.Forsyth       else
5951*37da2899SCharles.Forsyth       {
5952*37da2899SCharles.Forsyth         org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector );
5953*37da2899SCharles.Forsyth         cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector );
5954*37da2899SCharles.Forsyth 
5955*37da2899SCharles.Forsyth         if ( ( org_a <= org_b && org_x <= org_a ) ||
5956*37da2899SCharles.Forsyth              ( org_a >  org_b && org_x >= org_a ) )
5957*37da2899SCharles.Forsyth 
5958*37da2899SCharles.Forsyth           distance = ( cur_a - org_a ) + ( org_x - cur_x );
5959*37da2899SCharles.Forsyth 
5960*37da2899SCharles.Forsyth         else if ( ( org_a <= org_b  &&  org_x >= org_b ) ||
5961*37da2899SCharles.Forsyth                   ( org_a >  org_b  &&  org_x <  org_b ) )
5962*37da2899SCharles.Forsyth 
5963*37da2899SCharles.Forsyth           distance = ( cur_b - org_b ) + ( org_x - cur_x );
5964*37da2899SCharles.Forsyth 
5965*37da2899SCharles.Forsyth         else
5966*37da2899SCharles.Forsyth            /* note: it seems that rounding this value isn't a good */
5967*37da2899SCharles.Forsyth            /*       idea (cf. width of capital `S' in Times)       */
5968*37da2899SCharles.Forsyth 
5969*37da2899SCharles.Forsyth            distance = TT_MULDIV( cur_b - cur_a,
5970*37da2899SCharles.Forsyth                                  org_x - org_a,
5971*37da2899SCharles.Forsyth                                  org_b - org_a ) + ( cur_a - cur_x );
5972*37da2899SCharles.Forsyth 
5973*37da2899SCharles.Forsyth         CUR_Func_move( &CUR.zp2, point, distance );
5974*37da2899SCharles.Forsyth       }
5975*37da2899SCharles.Forsyth 
5976*37da2899SCharles.Forsyth       CUR.GS.loop--;
5977*37da2899SCharles.Forsyth     }
5978*37da2899SCharles.Forsyth 
5979*37da2899SCharles.Forsyth     CUR.GS.loop = 1;
5980*37da2899SCharles.Forsyth     CUR.new_top = CUR.args;
5981*37da2899SCharles.Forsyth   }
5982*37da2899SCharles.Forsyth 
5983*37da2899SCharles.Forsyth 
5984*37da2899SCharles.Forsyth   /*************************************************************************/
5985*37da2899SCharles.Forsyth   /*                                                                       */
5986*37da2899SCharles.Forsyth   /* UTP[a]:       UnTouch Point                                           */
5987*37da2899SCharles.Forsyth   /* Opcode range: 0x29                                                    */
5988*37da2899SCharles.Forsyth   /* Stack:        uint32 -->                                              */
5989*37da2899SCharles.Forsyth   /*                                                                       */
5990*37da2899SCharles.Forsyth   static void
Ins_UTP(INS_ARG)5991*37da2899SCharles.Forsyth   Ins_UTP( INS_ARG )
5992*37da2899SCharles.Forsyth   {
5993*37da2899SCharles.Forsyth     FT_UShort  point;
5994*37da2899SCharles.Forsyth     FT_Byte    mask;
5995*37da2899SCharles.Forsyth 
5996*37da2899SCharles.Forsyth 
5997*37da2899SCharles.Forsyth     point = (FT_UShort)args[0];
5998*37da2899SCharles.Forsyth 
5999*37da2899SCharles.Forsyth     if ( BOUNDS( point, CUR.zp0.n_points ) )
6000*37da2899SCharles.Forsyth     {
6001*37da2899SCharles.Forsyth       if ( CUR.pedantic_hinting )
6002*37da2899SCharles.Forsyth         CUR.error = TT_Err_Invalid_Reference;
6003*37da2899SCharles.Forsyth       return;
6004*37da2899SCharles.Forsyth     }
6005*37da2899SCharles.Forsyth 
6006*37da2899SCharles.Forsyth     mask = 0xFF;
6007*37da2899SCharles.Forsyth 
6008*37da2899SCharles.Forsyth     if ( CUR.GS.freeVector.x != 0 )
6009*37da2899SCharles.Forsyth       mask &= ~FT_CURVE_TAG_TOUCH_X;
6010*37da2899SCharles.Forsyth 
6011*37da2899SCharles.Forsyth     if ( CUR.GS.freeVector.y != 0 )
6012*37da2899SCharles.Forsyth       mask &= ~FT_CURVE_TAG_TOUCH_Y;
6013*37da2899SCharles.Forsyth 
6014*37da2899SCharles.Forsyth     CUR.zp0.tags[point] &= mask;
6015*37da2899SCharles.Forsyth   }
6016*37da2899SCharles.Forsyth 
6017*37da2899SCharles.Forsyth 
6018*37da2899SCharles.Forsyth   /* Local variables for Ins_IUP: */
6019*37da2899SCharles.Forsyth   struct  LOC_Ins_IUP
6020*37da2899SCharles.Forsyth   {
6021*37da2899SCharles.Forsyth     FT_Vector*  orgs;   /* original and current coordinate */
6022*37da2899SCharles.Forsyth     FT_Vector*  curs;   /* arrays                          */
6023*37da2899SCharles.Forsyth   };
6024*37da2899SCharles.Forsyth 
6025*37da2899SCharles.Forsyth 
6026*37da2899SCharles.Forsyth   static void
Shift(FT_UInt p1,FT_UInt p2,FT_UInt p,struct LOC_Ins_IUP * LINK)6027*37da2899SCharles.Forsyth   Shift( FT_UInt              p1,
6028*37da2899SCharles.Forsyth          FT_UInt              p2,
6029*37da2899SCharles.Forsyth          FT_UInt              p,
6030*37da2899SCharles.Forsyth          struct LOC_Ins_IUP*  LINK )
6031*37da2899SCharles.Forsyth   {
6032*37da2899SCharles.Forsyth     FT_UInt     i;
6033*37da2899SCharles.Forsyth     FT_F26Dot6  x;
6034*37da2899SCharles.Forsyth 
6035*37da2899SCharles.Forsyth 
6036*37da2899SCharles.Forsyth     x = LINK->curs[p].x - LINK->orgs[p].x;
6037*37da2899SCharles.Forsyth 
6038*37da2899SCharles.Forsyth     for ( i = p1; i < p; i++ )
6039*37da2899SCharles.Forsyth       LINK->curs[i].x += x;
6040*37da2899SCharles.Forsyth 
6041*37da2899SCharles.Forsyth     for ( i = p + 1; i <= p2; i++ )
6042*37da2899SCharles.Forsyth       LINK->curs[i].x += x;
6043*37da2899SCharles.Forsyth   }
6044*37da2899SCharles.Forsyth 
6045*37da2899SCharles.Forsyth 
6046*37da2899SCharles.Forsyth   static void
Interp(FT_UInt p1,FT_UInt p2,FT_UInt ref1,FT_UInt ref2,struct LOC_Ins_IUP * LINK)6047*37da2899SCharles.Forsyth   Interp( FT_UInt              p1,
6048*37da2899SCharles.Forsyth           FT_UInt              p2,
6049*37da2899SCharles.Forsyth           FT_UInt              ref1,
6050*37da2899SCharles.Forsyth           FT_UInt              ref2,
6051*37da2899SCharles.Forsyth           struct LOC_Ins_IUP*  LINK )
6052*37da2899SCharles.Forsyth   {
6053*37da2899SCharles.Forsyth     FT_UInt     i;
6054*37da2899SCharles.Forsyth     FT_F26Dot6  x, x1, x2, d1, d2;
6055*37da2899SCharles.Forsyth 
6056*37da2899SCharles.Forsyth 
6057*37da2899SCharles.Forsyth     if ( p1 > p2 )
6058*37da2899SCharles.Forsyth       return;
6059*37da2899SCharles.Forsyth 
6060*37da2899SCharles.Forsyth     x1 = LINK->orgs[ref1].x;
6061*37da2899SCharles.Forsyth     d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x;
6062*37da2899SCharles.Forsyth     x2 = LINK->orgs[ref2].x;
6063*37da2899SCharles.Forsyth     d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x;
6064*37da2899SCharles.Forsyth 
6065*37da2899SCharles.Forsyth     if ( x1 == x2 )
6066*37da2899SCharles.Forsyth     {
6067*37da2899SCharles.Forsyth       for ( i = p1; i <= p2; i++ )
6068*37da2899SCharles.Forsyth       {
6069*37da2899SCharles.Forsyth         x = LINK->orgs[i].x;
6070*37da2899SCharles.Forsyth 
6071*37da2899SCharles.Forsyth         if ( x <= x1 )
6072*37da2899SCharles.Forsyth           x += d1;
6073*37da2899SCharles.Forsyth         else
6074*37da2899SCharles.Forsyth           x += d2;
6075*37da2899SCharles.Forsyth 
6076*37da2899SCharles.Forsyth         LINK->curs[i].x = x;
6077*37da2899SCharles.Forsyth       }
6078*37da2899SCharles.Forsyth       return;
6079*37da2899SCharles.Forsyth     }
6080*37da2899SCharles.Forsyth 
6081*37da2899SCharles.Forsyth     if ( x1 < x2 )
6082*37da2899SCharles.Forsyth     {
6083*37da2899SCharles.Forsyth       for ( i = p1; i <= p2; i++ )
6084*37da2899SCharles.Forsyth       {
6085*37da2899SCharles.Forsyth         x = LINK->orgs[i].x;
6086*37da2899SCharles.Forsyth 
6087*37da2899SCharles.Forsyth         if ( x <= x1 )
6088*37da2899SCharles.Forsyth           x += d1;
6089*37da2899SCharles.Forsyth         else
6090*37da2899SCharles.Forsyth         {
6091*37da2899SCharles.Forsyth           if ( x >= x2 )
6092*37da2899SCharles.Forsyth             x += d2;
6093*37da2899SCharles.Forsyth           else
6094*37da2899SCharles.Forsyth             x = LINK->curs[ref1].x +
6095*37da2899SCharles.Forsyth                   TT_MULDIV( x - x1,
6096*37da2899SCharles.Forsyth                              LINK->curs[ref2].x - LINK->curs[ref1].x,
6097*37da2899SCharles.Forsyth                              x2 - x1 );
6098*37da2899SCharles.Forsyth         }
6099*37da2899SCharles.Forsyth         LINK->curs[i].x = x;
6100*37da2899SCharles.Forsyth       }
6101*37da2899SCharles.Forsyth       return;
6102*37da2899SCharles.Forsyth     }
6103*37da2899SCharles.Forsyth 
6104*37da2899SCharles.Forsyth     /* x2 < x1 */
6105*37da2899SCharles.Forsyth 
6106*37da2899SCharles.Forsyth     for ( i = p1; i <= p2; i++ )
6107*37da2899SCharles.Forsyth     {
6108*37da2899SCharles.Forsyth       x = LINK->orgs[i].x;
6109*37da2899SCharles.Forsyth       if ( x <= x2 )
6110*37da2899SCharles.Forsyth         x += d2;
6111*37da2899SCharles.Forsyth       else
6112*37da2899SCharles.Forsyth       {
6113*37da2899SCharles.Forsyth         if ( x >= x1 )
6114*37da2899SCharles.Forsyth           x += d1;
6115*37da2899SCharles.Forsyth         else
6116*37da2899SCharles.Forsyth           x = LINK->curs[ref1].x +
6117*37da2899SCharles.Forsyth               TT_MULDIV( x - x1,
6118*37da2899SCharles.Forsyth                          LINK->curs[ref2].x - LINK->curs[ref1].x,
6119*37da2899SCharles.Forsyth                          x2 - x1 );
6120*37da2899SCharles.Forsyth       }
6121*37da2899SCharles.Forsyth       LINK->curs[i].x = x;
6122*37da2899SCharles.Forsyth     }
6123*37da2899SCharles.Forsyth   }
6124*37da2899SCharles.Forsyth 
6125*37da2899SCharles.Forsyth 
6126*37da2899SCharles.Forsyth   /*************************************************************************/
6127*37da2899SCharles.Forsyth   /*                                                                       */
6128*37da2899SCharles.Forsyth   /* IUP[a]:       Interpolate Untouched Points                            */
6129*37da2899SCharles.Forsyth   /* Opcode range: 0x30-0x31                                               */
6130*37da2899SCharles.Forsyth   /* Stack:        -->                                                     */
6131*37da2899SCharles.Forsyth   /*                                                                       */
6132*37da2899SCharles.Forsyth   static void
Ins_IUP(INS_ARG)6133*37da2899SCharles.Forsyth   Ins_IUP( INS_ARG )
6134*37da2899SCharles.Forsyth   {
6135*37da2899SCharles.Forsyth     struct LOC_Ins_IUP  V;
6136*37da2899SCharles.Forsyth     FT_Byte             mask;
6137*37da2899SCharles.Forsyth 
6138*37da2899SCharles.Forsyth     FT_UInt   first_point;   /* first point of contour        */
6139*37da2899SCharles.Forsyth     FT_UInt   end_point;     /* end point (last+1) of contour */
6140*37da2899SCharles.Forsyth 
6141*37da2899SCharles.Forsyth     FT_UInt   first_touched; /* first touched point in contour   */
6142*37da2899SCharles.Forsyth     FT_UInt   cur_touched;   /* current touched point in contour */
6143*37da2899SCharles.Forsyth 
6144*37da2899SCharles.Forsyth     FT_UInt   point;         /* current point   */
6145*37da2899SCharles.Forsyth     FT_Short  contour;       /* current contour */
6146*37da2899SCharles.Forsyth 
6147*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
6148*37da2899SCharles.Forsyth 
6149*37da2899SCharles.Forsyth 
6150*37da2899SCharles.Forsyth     if ( CUR.opcode & 1 )
6151*37da2899SCharles.Forsyth     {
6152*37da2899SCharles.Forsyth       mask   = FT_CURVE_TAG_TOUCH_X;
6153*37da2899SCharles.Forsyth       V.orgs = CUR.pts.org;
6154*37da2899SCharles.Forsyth       V.curs = CUR.pts.cur;
6155*37da2899SCharles.Forsyth     }
6156*37da2899SCharles.Forsyth     else
6157*37da2899SCharles.Forsyth     {
6158*37da2899SCharles.Forsyth       mask   = FT_CURVE_TAG_TOUCH_Y;
6159*37da2899SCharles.Forsyth       V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
6160*37da2899SCharles.Forsyth       V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
6161*37da2899SCharles.Forsyth     }
6162*37da2899SCharles.Forsyth 
6163*37da2899SCharles.Forsyth     contour = 0;
6164*37da2899SCharles.Forsyth     point   = 0;
6165*37da2899SCharles.Forsyth 
6166*37da2899SCharles.Forsyth     do
6167*37da2899SCharles.Forsyth     {
6168*37da2899SCharles.Forsyth       end_point   = CUR.pts.contours[contour];
6169*37da2899SCharles.Forsyth       first_point = point;
6170*37da2899SCharles.Forsyth 
6171*37da2899SCharles.Forsyth       while ( point <= end_point && (CUR.pts.tags[point] & mask) == 0 )
6172*37da2899SCharles.Forsyth         point++;
6173*37da2899SCharles.Forsyth 
6174*37da2899SCharles.Forsyth       if ( point <= end_point )
6175*37da2899SCharles.Forsyth       {
6176*37da2899SCharles.Forsyth         first_touched = point;
6177*37da2899SCharles.Forsyth         cur_touched   = point;
6178*37da2899SCharles.Forsyth 
6179*37da2899SCharles.Forsyth         point++;
6180*37da2899SCharles.Forsyth 
6181*37da2899SCharles.Forsyth         while ( point <= end_point )
6182*37da2899SCharles.Forsyth         {
6183*37da2899SCharles.Forsyth           if ( ( CUR.pts.tags[point] & mask ) != 0 )
6184*37da2899SCharles.Forsyth           {
6185*37da2899SCharles.Forsyth             if ( point > 0 )
6186*37da2899SCharles.Forsyth               Interp( cur_touched + 1,
6187*37da2899SCharles.Forsyth                       point - 1,
6188*37da2899SCharles.Forsyth                       cur_touched,
6189*37da2899SCharles.Forsyth                       point,
6190*37da2899SCharles.Forsyth                       &V );
6191*37da2899SCharles.Forsyth             cur_touched = point;
6192*37da2899SCharles.Forsyth           }
6193*37da2899SCharles.Forsyth 
6194*37da2899SCharles.Forsyth           point++;
6195*37da2899SCharles.Forsyth         }
6196*37da2899SCharles.Forsyth 
6197*37da2899SCharles.Forsyth         if ( cur_touched == first_touched )
6198*37da2899SCharles.Forsyth           Shift( first_point, end_point, cur_touched, &V );
6199*37da2899SCharles.Forsyth         else
6200*37da2899SCharles.Forsyth         {
6201*37da2899SCharles.Forsyth           Interp( (FT_UShort)( cur_touched + 1 ),
6202*37da2899SCharles.Forsyth                   end_point,
6203*37da2899SCharles.Forsyth                   cur_touched,
6204*37da2899SCharles.Forsyth                   first_touched,
6205*37da2899SCharles.Forsyth                   &V );
6206*37da2899SCharles.Forsyth 
6207*37da2899SCharles.Forsyth           if ( first_touched > 0 )
6208*37da2899SCharles.Forsyth             Interp( first_point,
6209*37da2899SCharles.Forsyth                     first_touched - 1,
6210*37da2899SCharles.Forsyth                     cur_touched,
6211*37da2899SCharles.Forsyth                     first_touched,
6212*37da2899SCharles.Forsyth                     &V );
6213*37da2899SCharles.Forsyth         }
6214*37da2899SCharles.Forsyth       }
6215*37da2899SCharles.Forsyth       contour++;
6216*37da2899SCharles.Forsyth     } while ( contour < CUR.pts.n_contours );
6217*37da2899SCharles.Forsyth   }
6218*37da2899SCharles.Forsyth 
6219*37da2899SCharles.Forsyth 
6220*37da2899SCharles.Forsyth   /*************************************************************************/
6221*37da2899SCharles.Forsyth   /*                                                                       */
6222*37da2899SCharles.Forsyth   /* DELTAPn[]:    DELTA exceptions P1, P2, P3                             */
6223*37da2899SCharles.Forsyth   /* Opcode range: 0x5D,0x71,0x72                                          */
6224*37da2899SCharles.Forsyth   /* Stack:        uint32 (2 * uint32)... -->                              */
6225*37da2899SCharles.Forsyth   /*                                                                       */
6226*37da2899SCharles.Forsyth   static void
Ins_DELTAP(INS_ARG)6227*37da2899SCharles.Forsyth   Ins_DELTAP( INS_ARG )
6228*37da2899SCharles.Forsyth   {
6229*37da2899SCharles.Forsyth     FT_ULong   k, nump;
6230*37da2899SCharles.Forsyth     FT_UShort  A;
6231*37da2899SCharles.Forsyth     FT_ULong   C;
6232*37da2899SCharles.Forsyth     FT_Long    B;
6233*37da2899SCharles.Forsyth 
6234*37da2899SCharles.Forsyth 
6235*37da2899SCharles.Forsyth     nump = (FT_ULong)args[0];   /* some points theoretically may occur more
6236*37da2899SCharles.Forsyth                                    than once, thus UShort isn't enough */
6237*37da2899SCharles.Forsyth 
6238*37da2899SCharles.Forsyth     for ( k = 1; k <= nump; k++ )
6239*37da2899SCharles.Forsyth     {
6240*37da2899SCharles.Forsyth       if ( CUR.args < 2 )
6241*37da2899SCharles.Forsyth       {
6242*37da2899SCharles.Forsyth         CUR.error = TT_Err_Too_Few_Arguments;
6243*37da2899SCharles.Forsyth         return;
6244*37da2899SCharles.Forsyth       }
6245*37da2899SCharles.Forsyth 
6246*37da2899SCharles.Forsyth       CUR.args -= 2;
6247*37da2899SCharles.Forsyth 
6248*37da2899SCharles.Forsyth       A = (FT_UShort)CUR.stack[CUR.args + 1];
6249*37da2899SCharles.Forsyth       B = CUR.stack[CUR.args];
6250*37da2899SCharles.Forsyth 
6251*37da2899SCharles.Forsyth       /* XXX: Because some popular fonts contain some invalid DeltaP */
6252*37da2899SCharles.Forsyth       /*      instructions, we simply ignore them when the stacked   */
6253*37da2899SCharles.Forsyth       /*      point reference is off limit, rather than returning an */
6254*37da2899SCharles.Forsyth       /*      error.  As a delta instruction doesn't change a glyph  */
6255*37da2899SCharles.Forsyth       /*      in great ways, this shouldn't be a problem.            */
6256*37da2899SCharles.Forsyth 
6257*37da2899SCharles.Forsyth       if ( !BOUNDS( A, CUR.zp0.n_points ) )
6258*37da2899SCharles.Forsyth       {
6259*37da2899SCharles.Forsyth         C = ( (FT_ULong)B & 0xF0 ) >> 4;
6260*37da2899SCharles.Forsyth 
6261*37da2899SCharles.Forsyth         switch ( CUR.opcode )
6262*37da2899SCharles.Forsyth         {
6263*37da2899SCharles.Forsyth         case 0x5D:
6264*37da2899SCharles.Forsyth           break;
6265*37da2899SCharles.Forsyth 
6266*37da2899SCharles.Forsyth         case 0x71:
6267*37da2899SCharles.Forsyth           C += 16;
6268*37da2899SCharles.Forsyth           break;
6269*37da2899SCharles.Forsyth 
6270*37da2899SCharles.Forsyth         case 0x72:
6271*37da2899SCharles.Forsyth           C += 32;
6272*37da2899SCharles.Forsyth           break;
6273*37da2899SCharles.Forsyth         }
6274*37da2899SCharles.Forsyth 
6275*37da2899SCharles.Forsyth         C += CUR.GS.delta_base;
6276*37da2899SCharles.Forsyth 
6277*37da2899SCharles.Forsyth         if ( CURRENT_Ppem() == (FT_Long)C )
6278*37da2899SCharles.Forsyth         {
6279*37da2899SCharles.Forsyth           B = ( (FT_ULong)B & 0xF ) - 8;
6280*37da2899SCharles.Forsyth           if ( B >= 0 )
6281*37da2899SCharles.Forsyth             B++;
6282*37da2899SCharles.Forsyth           B = B * 64 / ( 1L << CUR.GS.delta_shift );
6283*37da2899SCharles.Forsyth 
6284*37da2899SCharles.Forsyth           CUR_Func_move( &CUR.zp0, A, B );
6285*37da2899SCharles.Forsyth         }
6286*37da2899SCharles.Forsyth       }
6287*37da2899SCharles.Forsyth       else
6288*37da2899SCharles.Forsyth         if ( CUR.pedantic_hinting )
6289*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Reference;
6290*37da2899SCharles.Forsyth     }
6291*37da2899SCharles.Forsyth 
6292*37da2899SCharles.Forsyth     CUR.new_top = CUR.args;
6293*37da2899SCharles.Forsyth   }
6294*37da2899SCharles.Forsyth 
6295*37da2899SCharles.Forsyth 
6296*37da2899SCharles.Forsyth   /*************************************************************************/
6297*37da2899SCharles.Forsyth   /*                                                                       */
6298*37da2899SCharles.Forsyth   /* DELTACn[]:    DELTA exceptions C1, C2, C3                             */
6299*37da2899SCharles.Forsyth   /* Opcode range: 0x73,0x74,0x75                                          */
6300*37da2899SCharles.Forsyth   /* Stack:        uint32 (2 * uint32)... -->                              */
6301*37da2899SCharles.Forsyth   /*                                                                       */
6302*37da2899SCharles.Forsyth   static void
Ins_DELTAC(INS_ARG)6303*37da2899SCharles.Forsyth   Ins_DELTAC( INS_ARG )
6304*37da2899SCharles.Forsyth   {
6305*37da2899SCharles.Forsyth     FT_ULong  nump, k;
6306*37da2899SCharles.Forsyth     FT_ULong  A, C;
6307*37da2899SCharles.Forsyth     FT_Long   B;
6308*37da2899SCharles.Forsyth 
6309*37da2899SCharles.Forsyth 
6310*37da2899SCharles.Forsyth     nump = (FT_ULong)args[0];
6311*37da2899SCharles.Forsyth 
6312*37da2899SCharles.Forsyth     for ( k = 1; k <= nump; k++ )
6313*37da2899SCharles.Forsyth     {
6314*37da2899SCharles.Forsyth       if ( CUR.args < 2 )
6315*37da2899SCharles.Forsyth       {
6316*37da2899SCharles.Forsyth         CUR.error = TT_Err_Too_Few_Arguments;
6317*37da2899SCharles.Forsyth         return;
6318*37da2899SCharles.Forsyth       }
6319*37da2899SCharles.Forsyth 
6320*37da2899SCharles.Forsyth       CUR.args -= 2;
6321*37da2899SCharles.Forsyth 
6322*37da2899SCharles.Forsyth       A = (FT_ULong)CUR.stack[CUR.args + 1];
6323*37da2899SCharles.Forsyth       B = CUR.stack[CUR.args];
6324*37da2899SCharles.Forsyth 
6325*37da2899SCharles.Forsyth       if ( BOUNDS( A, CUR.cvtSize ) )
6326*37da2899SCharles.Forsyth       {
6327*37da2899SCharles.Forsyth         if ( CUR.pedantic_hinting )
6328*37da2899SCharles.Forsyth         {
6329*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Reference;
6330*37da2899SCharles.Forsyth           return;
6331*37da2899SCharles.Forsyth         }
6332*37da2899SCharles.Forsyth       }
6333*37da2899SCharles.Forsyth       else
6334*37da2899SCharles.Forsyth       {
6335*37da2899SCharles.Forsyth         C = ( (FT_ULong)B & 0xF0 ) >> 4;
6336*37da2899SCharles.Forsyth 
6337*37da2899SCharles.Forsyth         switch ( CUR.opcode )
6338*37da2899SCharles.Forsyth         {
6339*37da2899SCharles.Forsyth         case 0x73:
6340*37da2899SCharles.Forsyth           break;
6341*37da2899SCharles.Forsyth 
6342*37da2899SCharles.Forsyth         case 0x74:
6343*37da2899SCharles.Forsyth           C += 16;
6344*37da2899SCharles.Forsyth           break;
6345*37da2899SCharles.Forsyth 
6346*37da2899SCharles.Forsyth         case 0x75:
6347*37da2899SCharles.Forsyth           C += 32;
6348*37da2899SCharles.Forsyth           break;
6349*37da2899SCharles.Forsyth         }
6350*37da2899SCharles.Forsyth 
6351*37da2899SCharles.Forsyth         C += CUR.GS.delta_base;
6352*37da2899SCharles.Forsyth 
6353*37da2899SCharles.Forsyth         if ( CURRENT_Ppem() == (FT_Long)C )
6354*37da2899SCharles.Forsyth         {
6355*37da2899SCharles.Forsyth           B = ( (FT_ULong)B & 0xF ) - 8;
6356*37da2899SCharles.Forsyth           if ( B >= 0 )
6357*37da2899SCharles.Forsyth             B++;
6358*37da2899SCharles.Forsyth           B = B * 64 / ( 1L << CUR.GS.delta_shift );
6359*37da2899SCharles.Forsyth 
6360*37da2899SCharles.Forsyth           CUR_Func_move_cvt( A, B );
6361*37da2899SCharles.Forsyth         }
6362*37da2899SCharles.Forsyth       }
6363*37da2899SCharles.Forsyth     }
6364*37da2899SCharles.Forsyth 
6365*37da2899SCharles.Forsyth     CUR.new_top = CUR.args;
6366*37da2899SCharles.Forsyth   }
6367*37da2899SCharles.Forsyth 
6368*37da2899SCharles.Forsyth 
6369*37da2899SCharles.Forsyth   /*************************************************************************/
6370*37da2899SCharles.Forsyth   /*                                                                       */
6371*37da2899SCharles.Forsyth   /* MISC. INSTRUCTIONS                                                    */
6372*37da2899SCharles.Forsyth   /*                                                                       */
6373*37da2899SCharles.Forsyth   /*************************************************************************/
6374*37da2899SCharles.Forsyth 
6375*37da2899SCharles.Forsyth 
6376*37da2899SCharles.Forsyth   /*************************************************************************/
6377*37da2899SCharles.Forsyth   /*                                                                       */
6378*37da2899SCharles.Forsyth   /* GETINFO[]:    GET INFOrmation                                         */
6379*37da2899SCharles.Forsyth   /* Opcode range: 0x88                                                    */
6380*37da2899SCharles.Forsyth   /* Stack:        uint32 --> uint32                                       */
6381*37da2899SCharles.Forsyth   /*                                                                       */
6382*37da2899SCharles.Forsyth   /* XXX: According to Apple specs, bits 1 & 2 of the argument ought to be */
6383*37da2899SCharles.Forsyth   /*      consulted before rotated/stretched info is returned.             */
6384*37da2899SCharles.Forsyth   static void
Ins_GETINFO(INS_ARG)6385*37da2899SCharles.Forsyth   Ins_GETINFO( INS_ARG )
6386*37da2899SCharles.Forsyth   {
6387*37da2899SCharles.Forsyth     FT_Long  K;
6388*37da2899SCharles.Forsyth 
6389*37da2899SCharles.Forsyth 
6390*37da2899SCharles.Forsyth     K = 0;
6391*37da2899SCharles.Forsyth 
6392*37da2899SCharles.Forsyth     /* We return then Windows 3.1 version number */
6393*37da2899SCharles.Forsyth     /* for the font scaler                       */
6394*37da2899SCharles.Forsyth     if ( ( args[0] & 1 ) != 0 )
6395*37da2899SCharles.Forsyth       K = 3;
6396*37da2899SCharles.Forsyth 
6397*37da2899SCharles.Forsyth     /* Has the glyph been rotated ? */
6398*37da2899SCharles.Forsyth     if ( CUR.tt_metrics.rotated )
6399*37da2899SCharles.Forsyth       K |= 0x80;
6400*37da2899SCharles.Forsyth 
6401*37da2899SCharles.Forsyth     /* Has the glyph been stretched ? */
6402*37da2899SCharles.Forsyth     if ( CUR.tt_metrics.stretched )
6403*37da2899SCharles.Forsyth       K |= 0x100;
6404*37da2899SCharles.Forsyth 
6405*37da2899SCharles.Forsyth     args[0] = K;
6406*37da2899SCharles.Forsyth   }
6407*37da2899SCharles.Forsyth 
6408*37da2899SCharles.Forsyth 
6409*37da2899SCharles.Forsyth   static void
Ins_UNKNOWN(INS_ARG)6410*37da2899SCharles.Forsyth   Ins_UNKNOWN( INS_ARG )
6411*37da2899SCharles.Forsyth   {
6412*37da2899SCharles.Forsyth     TT_DefRecord*  def   = CUR.IDefs;
6413*37da2899SCharles.Forsyth     TT_DefRecord*  limit = def + CUR.numIDefs;
6414*37da2899SCharles.Forsyth 
6415*37da2899SCharles.Forsyth     FT_UNUSED_ARG;
6416*37da2899SCharles.Forsyth 
6417*37da2899SCharles.Forsyth 
6418*37da2899SCharles.Forsyth     for ( ; def < limit; def++ )
6419*37da2899SCharles.Forsyth     {
6420*37da2899SCharles.Forsyth       if ( (FT_Byte)def->opc == CUR.opcode && def->active )
6421*37da2899SCharles.Forsyth       {
6422*37da2899SCharles.Forsyth         TT_CallRec*  call;
6423*37da2899SCharles.Forsyth 
6424*37da2899SCharles.Forsyth 
6425*37da2899SCharles.Forsyth         if ( CUR.callTop >= CUR.callSize )
6426*37da2899SCharles.Forsyth         {
6427*37da2899SCharles.Forsyth           CUR.error = TT_Err_Stack_Overflow;
6428*37da2899SCharles.Forsyth           return;
6429*37da2899SCharles.Forsyth         }
6430*37da2899SCharles.Forsyth 
6431*37da2899SCharles.Forsyth         call = CUR.callStack + CUR.callTop++;
6432*37da2899SCharles.Forsyth 
6433*37da2899SCharles.Forsyth         call->Caller_Range = CUR.curRange;
6434*37da2899SCharles.Forsyth         call->Caller_IP    = CUR.IP+1;
6435*37da2899SCharles.Forsyth         call->Cur_Count    = 1;
6436*37da2899SCharles.Forsyth         call->Cur_Restart  = def->start;
6437*37da2899SCharles.Forsyth 
6438*37da2899SCharles.Forsyth         INS_Goto_CodeRange( def->range, def->start );
6439*37da2899SCharles.Forsyth 
6440*37da2899SCharles.Forsyth         CUR.step_ins = FALSE;
6441*37da2899SCharles.Forsyth         return;
6442*37da2899SCharles.Forsyth       }
6443*37da2899SCharles.Forsyth     }
6444*37da2899SCharles.Forsyth 
6445*37da2899SCharles.Forsyth     CUR.error = TT_Err_Invalid_Opcode;
6446*37da2899SCharles.Forsyth   }
6447*37da2899SCharles.Forsyth 
6448*37da2899SCharles.Forsyth 
6449*37da2899SCharles.Forsyth #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
6450*37da2899SCharles.Forsyth 
6451*37da2899SCharles.Forsyth 
6452*37da2899SCharles.Forsyth   static
6453*37da2899SCharles.Forsyth   TInstruction_Function  Instruct_Dispatch[256] =
6454*37da2899SCharles.Forsyth   {
6455*37da2899SCharles.Forsyth     /* Opcodes are gathered in groups of 16. */
6456*37da2899SCharles.Forsyth     /* Please keep the spaces as they are.   */
6457*37da2899SCharles.Forsyth 
6458*37da2899SCharles.Forsyth     /*  SVTCA  y  */  Ins_SVTCA,
6459*37da2899SCharles.Forsyth     /*  SVTCA  x  */  Ins_SVTCA,
6460*37da2899SCharles.Forsyth     /*  SPvTCA y  */  Ins_SPVTCA,
6461*37da2899SCharles.Forsyth     /*  SPvTCA x  */  Ins_SPVTCA,
6462*37da2899SCharles.Forsyth     /*  SFvTCA y  */  Ins_SFVTCA,
6463*37da2899SCharles.Forsyth     /*  SFvTCA x  */  Ins_SFVTCA,
6464*37da2899SCharles.Forsyth     /*  SPvTL //  */  Ins_SPVTL,
6465*37da2899SCharles.Forsyth     /*  SPvTL +   */  Ins_SPVTL,
6466*37da2899SCharles.Forsyth     /*  SFvTL //  */  Ins_SFVTL,
6467*37da2899SCharles.Forsyth     /*  SFvTL +   */  Ins_SFVTL,
6468*37da2899SCharles.Forsyth     /*  SPvFS     */  Ins_SPVFS,
6469*37da2899SCharles.Forsyth     /*  SFvFS     */  Ins_SFVFS,
6470*37da2899SCharles.Forsyth     /*  GPV       */  Ins_GPV,
6471*37da2899SCharles.Forsyth     /*  GFV       */  Ins_GFV,
6472*37da2899SCharles.Forsyth     /*  SFvTPv    */  Ins_SFVTPV,
6473*37da2899SCharles.Forsyth     /*  ISECT     */  Ins_ISECT,
6474*37da2899SCharles.Forsyth 
6475*37da2899SCharles.Forsyth     /*  SRP0      */  Ins_SRP0,
6476*37da2899SCharles.Forsyth     /*  SRP1      */  Ins_SRP1,
6477*37da2899SCharles.Forsyth     /*  SRP2      */  Ins_SRP2,
6478*37da2899SCharles.Forsyth     /*  SZP0      */  Ins_SZP0,
6479*37da2899SCharles.Forsyth     /*  SZP1      */  Ins_SZP1,
6480*37da2899SCharles.Forsyth     /*  SZP2      */  Ins_SZP2,
6481*37da2899SCharles.Forsyth     /*  SZPS      */  Ins_SZPS,
6482*37da2899SCharles.Forsyth     /*  SLOOP     */  Ins_SLOOP,
6483*37da2899SCharles.Forsyth     /*  RTG       */  Ins_RTG,
6484*37da2899SCharles.Forsyth     /*  RTHG      */  Ins_RTHG,
6485*37da2899SCharles.Forsyth     /*  SMD       */  Ins_SMD,
6486*37da2899SCharles.Forsyth     /*  ELSE      */  Ins_ELSE,
6487*37da2899SCharles.Forsyth     /*  JMPR      */  Ins_JMPR,
6488*37da2899SCharles.Forsyth     /*  SCvTCi    */  Ins_SCVTCI,
6489*37da2899SCharles.Forsyth     /*  SSwCi     */  Ins_SSWCI,
6490*37da2899SCharles.Forsyth     /*  SSW       */  Ins_SSW,
6491*37da2899SCharles.Forsyth 
6492*37da2899SCharles.Forsyth     /*  DUP       */  Ins_DUP,
6493*37da2899SCharles.Forsyth     /*  POP       */  Ins_POP,
6494*37da2899SCharles.Forsyth     /*  CLEAR     */  Ins_CLEAR,
6495*37da2899SCharles.Forsyth     /*  SWAP      */  Ins_SWAP,
6496*37da2899SCharles.Forsyth     /*  DEPTH     */  Ins_DEPTH,
6497*37da2899SCharles.Forsyth     /*  CINDEX    */  Ins_CINDEX,
6498*37da2899SCharles.Forsyth     /*  MINDEX    */  Ins_MINDEX,
6499*37da2899SCharles.Forsyth     /*  AlignPTS  */  Ins_ALIGNPTS,
6500*37da2899SCharles.Forsyth     /*  INS_0x28  */  Ins_UNKNOWN,
6501*37da2899SCharles.Forsyth     /*  UTP       */  Ins_UTP,
6502*37da2899SCharles.Forsyth     /*  LOOPCALL  */  Ins_LOOPCALL,
6503*37da2899SCharles.Forsyth     /*  CALL      */  Ins_CALL,
6504*37da2899SCharles.Forsyth     /*  FDEF      */  Ins_FDEF,
6505*37da2899SCharles.Forsyth     /*  ENDF      */  Ins_ENDF,
6506*37da2899SCharles.Forsyth     /*  MDAP[0]   */  Ins_MDAP,
6507*37da2899SCharles.Forsyth     /*  MDAP[1]   */  Ins_MDAP,
6508*37da2899SCharles.Forsyth 
6509*37da2899SCharles.Forsyth     /*  IUP[0]    */  Ins_IUP,
6510*37da2899SCharles.Forsyth     /*  IUP[1]    */  Ins_IUP,
6511*37da2899SCharles.Forsyth     /*  SHP[0]    */  Ins_SHP,
6512*37da2899SCharles.Forsyth     /*  SHP[1]    */  Ins_SHP,
6513*37da2899SCharles.Forsyth     /*  SHC[0]    */  Ins_SHC,
6514*37da2899SCharles.Forsyth     /*  SHC[1]    */  Ins_SHC,
6515*37da2899SCharles.Forsyth     /*  SHZ[0]    */  Ins_SHZ,
6516*37da2899SCharles.Forsyth     /*  SHZ[1]    */  Ins_SHZ,
6517*37da2899SCharles.Forsyth     /*  SHPIX     */  Ins_SHPIX,
6518*37da2899SCharles.Forsyth     /*  IP        */  Ins_IP,
6519*37da2899SCharles.Forsyth     /*  MSIRP[0]  */  Ins_MSIRP,
6520*37da2899SCharles.Forsyth     /*  MSIRP[1]  */  Ins_MSIRP,
6521*37da2899SCharles.Forsyth     /*  AlignRP   */  Ins_ALIGNRP,
6522*37da2899SCharles.Forsyth     /*  RTDG      */  Ins_RTDG,
6523*37da2899SCharles.Forsyth     /*  MIAP[0]   */  Ins_MIAP,
6524*37da2899SCharles.Forsyth     /*  MIAP[1]   */  Ins_MIAP,
6525*37da2899SCharles.Forsyth 
6526*37da2899SCharles.Forsyth     /*  NPushB    */  Ins_NPUSHB,
6527*37da2899SCharles.Forsyth     /*  NPushW    */  Ins_NPUSHW,
6528*37da2899SCharles.Forsyth     /*  WS        */  Ins_WS,
6529*37da2899SCharles.Forsyth     /*  RS        */  Ins_RS,
6530*37da2899SCharles.Forsyth     /*  WCvtP     */  Ins_WCVTP,
6531*37da2899SCharles.Forsyth     /*  RCvt      */  Ins_RCVT,
6532*37da2899SCharles.Forsyth     /*  GC[0]     */  Ins_GC,
6533*37da2899SCharles.Forsyth     /*  GC[1]     */  Ins_GC,
6534*37da2899SCharles.Forsyth     /*  SCFS      */  Ins_SCFS,
6535*37da2899SCharles.Forsyth     /*  MD[0]     */  Ins_MD,
6536*37da2899SCharles.Forsyth     /*  MD[1]     */  Ins_MD,
6537*37da2899SCharles.Forsyth     /*  MPPEM     */  Ins_MPPEM,
6538*37da2899SCharles.Forsyth     /*  MPS       */  Ins_MPS,
6539*37da2899SCharles.Forsyth     /*  FlipON    */  Ins_FLIPON,
6540*37da2899SCharles.Forsyth     /*  FlipOFF   */  Ins_FLIPOFF,
6541*37da2899SCharles.Forsyth     /*  DEBUG     */  Ins_DEBUG,
6542*37da2899SCharles.Forsyth 
6543*37da2899SCharles.Forsyth     /*  LT        */  Ins_LT,
6544*37da2899SCharles.Forsyth     /*  LTEQ      */  Ins_LTEQ,
6545*37da2899SCharles.Forsyth     /*  GT        */  Ins_GT,
6546*37da2899SCharles.Forsyth     /*  GTEQ      */  Ins_GTEQ,
6547*37da2899SCharles.Forsyth     /*  EQ        */  Ins_EQ,
6548*37da2899SCharles.Forsyth     /*  NEQ       */  Ins_NEQ,
6549*37da2899SCharles.Forsyth     /*  ODD       */  Ins_ODD,
6550*37da2899SCharles.Forsyth     /*  EVEN      */  Ins_EVEN,
6551*37da2899SCharles.Forsyth     /*  IF        */  Ins_IF,
6552*37da2899SCharles.Forsyth     /*  EIF       */  Ins_EIF,
6553*37da2899SCharles.Forsyth     /*  AND       */  Ins_AND,
6554*37da2899SCharles.Forsyth     /*  OR        */  Ins_OR,
6555*37da2899SCharles.Forsyth     /*  NOT       */  Ins_NOT,
6556*37da2899SCharles.Forsyth     /*  DeltaP1   */  Ins_DELTAP,
6557*37da2899SCharles.Forsyth     /*  SDB       */  Ins_SDB,
6558*37da2899SCharles.Forsyth     /*  SDS       */  Ins_SDS,
6559*37da2899SCharles.Forsyth 
6560*37da2899SCharles.Forsyth     /*  ADD       */  Ins_ADD,
6561*37da2899SCharles.Forsyth     /*  SUB       */  Ins_SUB,
6562*37da2899SCharles.Forsyth     /*  DIV       */  Ins_DIV,
6563*37da2899SCharles.Forsyth     /*  MUL       */  Ins_MUL,
6564*37da2899SCharles.Forsyth     /*  ABS       */  Ins_ABS,
6565*37da2899SCharles.Forsyth     /*  NEG       */  Ins_NEG,
6566*37da2899SCharles.Forsyth     /*  FLOOR     */  Ins_FLOOR,
6567*37da2899SCharles.Forsyth     /*  CEILING   */  Ins_CEILING,
6568*37da2899SCharles.Forsyth     /*  ROUND[0]  */  Ins_ROUND,
6569*37da2899SCharles.Forsyth     /*  ROUND[1]  */  Ins_ROUND,
6570*37da2899SCharles.Forsyth     /*  ROUND[2]  */  Ins_ROUND,
6571*37da2899SCharles.Forsyth     /*  ROUND[3]  */  Ins_ROUND,
6572*37da2899SCharles.Forsyth     /*  NROUND[0] */  Ins_NROUND,
6573*37da2899SCharles.Forsyth     /*  NROUND[1] */  Ins_NROUND,
6574*37da2899SCharles.Forsyth     /*  NROUND[2] */  Ins_NROUND,
6575*37da2899SCharles.Forsyth     /*  NROUND[3] */  Ins_NROUND,
6576*37da2899SCharles.Forsyth 
6577*37da2899SCharles.Forsyth     /*  WCvtF     */  Ins_WCVTF,
6578*37da2899SCharles.Forsyth     /*  DeltaP2   */  Ins_DELTAP,
6579*37da2899SCharles.Forsyth     /*  DeltaP3   */  Ins_DELTAP,
6580*37da2899SCharles.Forsyth     /*  DeltaCn[0] */ Ins_DELTAC,
6581*37da2899SCharles.Forsyth     /*  DeltaCn[1] */ Ins_DELTAC,
6582*37da2899SCharles.Forsyth     /*  DeltaCn[2] */ Ins_DELTAC,
6583*37da2899SCharles.Forsyth     /*  SROUND    */  Ins_SROUND,
6584*37da2899SCharles.Forsyth     /*  S45Round  */  Ins_S45ROUND,
6585*37da2899SCharles.Forsyth     /*  JROT      */  Ins_JROT,
6586*37da2899SCharles.Forsyth     /*  JROF      */  Ins_JROF,
6587*37da2899SCharles.Forsyth     /*  ROFF      */  Ins_ROFF,
6588*37da2899SCharles.Forsyth     /*  INS_0x7B  */  Ins_UNKNOWN,
6589*37da2899SCharles.Forsyth     /*  RUTG      */  Ins_RUTG,
6590*37da2899SCharles.Forsyth     /*  RDTG      */  Ins_RDTG,
6591*37da2899SCharles.Forsyth     /*  SANGW     */  Ins_SANGW,
6592*37da2899SCharles.Forsyth     /*  AA        */  Ins_AA,
6593*37da2899SCharles.Forsyth 
6594*37da2899SCharles.Forsyth     /*  FlipPT    */  Ins_FLIPPT,
6595*37da2899SCharles.Forsyth     /*  FlipRgON  */  Ins_FLIPRGON,
6596*37da2899SCharles.Forsyth     /*  FlipRgOFF */  Ins_FLIPRGOFF,
6597*37da2899SCharles.Forsyth     /*  INS_0x83  */  Ins_UNKNOWN,
6598*37da2899SCharles.Forsyth     /*  INS_0x84  */  Ins_UNKNOWN,
6599*37da2899SCharles.Forsyth     /*  ScanCTRL  */  Ins_SCANCTRL,
6600*37da2899SCharles.Forsyth     /*  SDPVTL[0] */  Ins_SDPVTL,
6601*37da2899SCharles.Forsyth     /*  SDPVTL[1] */  Ins_SDPVTL,
6602*37da2899SCharles.Forsyth     /*  GetINFO   */  Ins_GETINFO,
6603*37da2899SCharles.Forsyth     /*  IDEF      */  Ins_IDEF,
6604*37da2899SCharles.Forsyth     /*  ROLL      */  Ins_ROLL,
6605*37da2899SCharles.Forsyth     /*  MAX       */  Ins_MAX,
6606*37da2899SCharles.Forsyth     /*  MIN       */  Ins_MIN,
6607*37da2899SCharles.Forsyth     /*  ScanTYPE  */  Ins_SCANTYPE,
6608*37da2899SCharles.Forsyth     /*  InstCTRL  */  Ins_INSTCTRL,
6609*37da2899SCharles.Forsyth     /*  INS_0x8F  */  Ins_UNKNOWN,
6610*37da2899SCharles.Forsyth 
6611*37da2899SCharles.Forsyth     /*  INS_0x90  */   Ins_UNKNOWN,
6612*37da2899SCharles.Forsyth     /*  INS_0x91  */   Ins_UNKNOWN,
6613*37da2899SCharles.Forsyth     /*  INS_0x92  */   Ins_UNKNOWN,
6614*37da2899SCharles.Forsyth     /*  INS_0x93  */   Ins_UNKNOWN,
6615*37da2899SCharles.Forsyth     /*  INS_0x94  */   Ins_UNKNOWN,
6616*37da2899SCharles.Forsyth     /*  INS_0x95  */   Ins_UNKNOWN,
6617*37da2899SCharles.Forsyth     /*  INS_0x96  */   Ins_UNKNOWN,
6618*37da2899SCharles.Forsyth     /*  INS_0x97  */   Ins_UNKNOWN,
6619*37da2899SCharles.Forsyth     /*  INS_0x98  */   Ins_UNKNOWN,
6620*37da2899SCharles.Forsyth     /*  INS_0x99  */   Ins_UNKNOWN,
6621*37da2899SCharles.Forsyth     /*  INS_0x9A  */   Ins_UNKNOWN,
6622*37da2899SCharles.Forsyth     /*  INS_0x9B  */   Ins_UNKNOWN,
6623*37da2899SCharles.Forsyth     /*  INS_0x9C  */   Ins_UNKNOWN,
6624*37da2899SCharles.Forsyth     /*  INS_0x9D  */   Ins_UNKNOWN,
6625*37da2899SCharles.Forsyth     /*  INS_0x9E  */   Ins_UNKNOWN,
6626*37da2899SCharles.Forsyth     /*  INS_0x9F  */   Ins_UNKNOWN,
6627*37da2899SCharles.Forsyth 
6628*37da2899SCharles.Forsyth     /*  INS_0xA0  */   Ins_UNKNOWN,
6629*37da2899SCharles.Forsyth     /*  INS_0xA1  */   Ins_UNKNOWN,
6630*37da2899SCharles.Forsyth     /*  INS_0xA2  */   Ins_UNKNOWN,
6631*37da2899SCharles.Forsyth     /*  INS_0xA3  */   Ins_UNKNOWN,
6632*37da2899SCharles.Forsyth     /*  INS_0xA4  */   Ins_UNKNOWN,
6633*37da2899SCharles.Forsyth     /*  INS_0xA5  */   Ins_UNKNOWN,
6634*37da2899SCharles.Forsyth     /*  INS_0xA6  */   Ins_UNKNOWN,
6635*37da2899SCharles.Forsyth     /*  INS_0xA7  */   Ins_UNKNOWN,
6636*37da2899SCharles.Forsyth     /*  INS_0xA8  */   Ins_UNKNOWN,
6637*37da2899SCharles.Forsyth     /*  INS_0xA9  */   Ins_UNKNOWN,
6638*37da2899SCharles.Forsyth     /*  INS_0xAA  */   Ins_UNKNOWN,
6639*37da2899SCharles.Forsyth     /*  INS_0xAB  */   Ins_UNKNOWN,
6640*37da2899SCharles.Forsyth     /*  INS_0xAC  */   Ins_UNKNOWN,
6641*37da2899SCharles.Forsyth     /*  INS_0xAD  */   Ins_UNKNOWN,
6642*37da2899SCharles.Forsyth     /*  INS_0xAE  */   Ins_UNKNOWN,
6643*37da2899SCharles.Forsyth     /*  INS_0xAF  */   Ins_UNKNOWN,
6644*37da2899SCharles.Forsyth 
6645*37da2899SCharles.Forsyth     /*  PushB[0]  */  Ins_PUSHB,
6646*37da2899SCharles.Forsyth     /*  PushB[1]  */  Ins_PUSHB,
6647*37da2899SCharles.Forsyth     /*  PushB[2]  */  Ins_PUSHB,
6648*37da2899SCharles.Forsyth     /*  PushB[3]  */  Ins_PUSHB,
6649*37da2899SCharles.Forsyth     /*  PushB[4]  */  Ins_PUSHB,
6650*37da2899SCharles.Forsyth     /*  PushB[5]  */  Ins_PUSHB,
6651*37da2899SCharles.Forsyth     /*  PushB[6]  */  Ins_PUSHB,
6652*37da2899SCharles.Forsyth     /*  PushB[7]  */  Ins_PUSHB,
6653*37da2899SCharles.Forsyth     /*  PushW[0]  */  Ins_PUSHW,
6654*37da2899SCharles.Forsyth     /*  PushW[1]  */  Ins_PUSHW,
6655*37da2899SCharles.Forsyth     /*  PushW[2]  */  Ins_PUSHW,
6656*37da2899SCharles.Forsyth     /*  PushW[3]  */  Ins_PUSHW,
6657*37da2899SCharles.Forsyth     /*  PushW[4]  */  Ins_PUSHW,
6658*37da2899SCharles.Forsyth     /*  PushW[5]  */  Ins_PUSHW,
6659*37da2899SCharles.Forsyth     /*  PushW[6]  */  Ins_PUSHW,
6660*37da2899SCharles.Forsyth     /*  PushW[7]  */  Ins_PUSHW,
6661*37da2899SCharles.Forsyth 
6662*37da2899SCharles.Forsyth     /*  MDRP[00]  */  Ins_MDRP,
6663*37da2899SCharles.Forsyth     /*  MDRP[01]  */  Ins_MDRP,
6664*37da2899SCharles.Forsyth     /*  MDRP[02]  */  Ins_MDRP,
6665*37da2899SCharles.Forsyth     /*  MDRP[03]  */  Ins_MDRP,
6666*37da2899SCharles.Forsyth     /*  MDRP[04]  */  Ins_MDRP,
6667*37da2899SCharles.Forsyth     /*  MDRP[05]  */  Ins_MDRP,
6668*37da2899SCharles.Forsyth     /*  MDRP[06]  */  Ins_MDRP,
6669*37da2899SCharles.Forsyth     /*  MDRP[07]  */  Ins_MDRP,
6670*37da2899SCharles.Forsyth     /*  MDRP[08]  */  Ins_MDRP,
6671*37da2899SCharles.Forsyth     /*  MDRP[09]  */  Ins_MDRP,
6672*37da2899SCharles.Forsyth     /*  MDRP[10]  */  Ins_MDRP,
6673*37da2899SCharles.Forsyth     /*  MDRP[11]  */  Ins_MDRP,
6674*37da2899SCharles.Forsyth     /*  MDRP[12]  */  Ins_MDRP,
6675*37da2899SCharles.Forsyth     /*  MDRP[13]  */  Ins_MDRP,
6676*37da2899SCharles.Forsyth     /*  MDRP[14]  */  Ins_MDRP,
6677*37da2899SCharles.Forsyth     /*  MDRP[15]  */  Ins_MDRP,
6678*37da2899SCharles.Forsyth 
6679*37da2899SCharles.Forsyth     /*  MDRP[16]  */  Ins_MDRP,
6680*37da2899SCharles.Forsyth     /*  MDRP[17]  */  Ins_MDRP,
6681*37da2899SCharles.Forsyth     /*  MDRP[18]  */  Ins_MDRP,
6682*37da2899SCharles.Forsyth     /*  MDRP[19]  */  Ins_MDRP,
6683*37da2899SCharles.Forsyth     /*  MDRP[20]  */  Ins_MDRP,
6684*37da2899SCharles.Forsyth     /*  MDRP[21]  */  Ins_MDRP,
6685*37da2899SCharles.Forsyth     /*  MDRP[22]  */  Ins_MDRP,
6686*37da2899SCharles.Forsyth     /*  MDRP[23]  */  Ins_MDRP,
6687*37da2899SCharles.Forsyth     /*  MDRP[24]  */  Ins_MDRP,
6688*37da2899SCharles.Forsyth     /*  MDRP[25]  */  Ins_MDRP,
6689*37da2899SCharles.Forsyth     /*  MDRP[26]  */  Ins_MDRP,
6690*37da2899SCharles.Forsyth     /*  MDRP[27]  */  Ins_MDRP,
6691*37da2899SCharles.Forsyth     /*  MDRP[28]  */  Ins_MDRP,
6692*37da2899SCharles.Forsyth     /*  MDRP[29]  */  Ins_MDRP,
6693*37da2899SCharles.Forsyth     /*  MDRP[30]  */  Ins_MDRP,
6694*37da2899SCharles.Forsyth     /*  MDRP[31]  */  Ins_MDRP,
6695*37da2899SCharles.Forsyth 
6696*37da2899SCharles.Forsyth     /*  MIRP[00]  */  Ins_MIRP,
6697*37da2899SCharles.Forsyth     /*  MIRP[01]  */  Ins_MIRP,
6698*37da2899SCharles.Forsyth     /*  MIRP[02]  */  Ins_MIRP,
6699*37da2899SCharles.Forsyth     /*  MIRP[03]  */  Ins_MIRP,
6700*37da2899SCharles.Forsyth     /*  MIRP[04]  */  Ins_MIRP,
6701*37da2899SCharles.Forsyth     /*  MIRP[05]  */  Ins_MIRP,
6702*37da2899SCharles.Forsyth     /*  MIRP[06]  */  Ins_MIRP,
6703*37da2899SCharles.Forsyth     /*  MIRP[07]  */  Ins_MIRP,
6704*37da2899SCharles.Forsyth     /*  MIRP[08]  */  Ins_MIRP,
6705*37da2899SCharles.Forsyth     /*  MIRP[09]  */  Ins_MIRP,
6706*37da2899SCharles.Forsyth     /*  MIRP[10]  */  Ins_MIRP,
6707*37da2899SCharles.Forsyth     /*  MIRP[11]  */  Ins_MIRP,
6708*37da2899SCharles.Forsyth     /*  MIRP[12]  */  Ins_MIRP,
6709*37da2899SCharles.Forsyth     /*  MIRP[13]  */  Ins_MIRP,
6710*37da2899SCharles.Forsyth     /*  MIRP[14]  */  Ins_MIRP,
6711*37da2899SCharles.Forsyth     /*  MIRP[15]  */  Ins_MIRP,
6712*37da2899SCharles.Forsyth 
6713*37da2899SCharles.Forsyth     /*  MIRP[16]  */  Ins_MIRP,
6714*37da2899SCharles.Forsyth     /*  MIRP[17]  */  Ins_MIRP,
6715*37da2899SCharles.Forsyth     /*  MIRP[18]  */  Ins_MIRP,
6716*37da2899SCharles.Forsyth     /*  MIRP[19]  */  Ins_MIRP,
6717*37da2899SCharles.Forsyth     /*  MIRP[20]  */  Ins_MIRP,
6718*37da2899SCharles.Forsyth     /*  MIRP[21]  */  Ins_MIRP,
6719*37da2899SCharles.Forsyth     /*  MIRP[22]  */  Ins_MIRP,
6720*37da2899SCharles.Forsyth     /*  MIRP[23]  */  Ins_MIRP,
6721*37da2899SCharles.Forsyth     /*  MIRP[24]  */  Ins_MIRP,
6722*37da2899SCharles.Forsyth     /*  MIRP[25]  */  Ins_MIRP,
6723*37da2899SCharles.Forsyth     /*  MIRP[26]  */  Ins_MIRP,
6724*37da2899SCharles.Forsyth     /*  MIRP[27]  */  Ins_MIRP,
6725*37da2899SCharles.Forsyth     /*  MIRP[28]  */  Ins_MIRP,
6726*37da2899SCharles.Forsyth     /*  MIRP[29]  */  Ins_MIRP,
6727*37da2899SCharles.Forsyth     /*  MIRP[30]  */  Ins_MIRP,
6728*37da2899SCharles.Forsyth     /*  MIRP[31]  */  Ins_MIRP
6729*37da2899SCharles.Forsyth   };
6730*37da2899SCharles.Forsyth 
6731*37da2899SCharles.Forsyth 
6732*37da2899SCharles.Forsyth #endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
6733*37da2899SCharles.Forsyth 
6734*37da2899SCharles.Forsyth 
6735*37da2899SCharles.Forsyth   /*************************************************************************/
6736*37da2899SCharles.Forsyth   /*                                                                       */
6737*37da2899SCharles.Forsyth   /* RUN                                                                   */
6738*37da2899SCharles.Forsyth   /*                                                                       */
6739*37da2899SCharles.Forsyth   /*  This function executes a run of opcodes.  It will exit in the        */
6740*37da2899SCharles.Forsyth   /*  following cases:                                                     */
6741*37da2899SCharles.Forsyth   /*                                                                       */
6742*37da2899SCharles.Forsyth   /*  - Errors (in which case it returns FALSE).                           */
6743*37da2899SCharles.Forsyth   /*                                                                       */
6744*37da2899SCharles.Forsyth   /*  - Reaching the end of the main code range (returns TRUE).            */
6745*37da2899SCharles.Forsyth   /*    Reaching the end of a code range within a function call is an      */
6746*37da2899SCharles.Forsyth   /*    error.                                                             */
6747*37da2899SCharles.Forsyth   /*                                                                       */
6748*37da2899SCharles.Forsyth   /*  - After executing one single opcode, if the flag `Instruction_Trap'  */
6749*37da2899SCharles.Forsyth   /*    is set to TRUE (returns TRUE).                                     */
6750*37da2899SCharles.Forsyth   /*                                                                       */
6751*37da2899SCharles.Forsyth   /*  On exit whith TRUE, test IP < CodeSize to know wether it comes from  */
6752*37da2899SCharles.Forsyth   /*  an instruction trap or a normal termination.                         */
6753*37da2899SCharles.Forsyth   /*                                                                       */
6754*37da2899SCharles.Forsyth   /*                                                                       */
6755*37da2899SCharles.Forsyth   /*  Note: The documented DEBUG opcode pops a value from the stack.  This */
6756*37da2899SCharles.Forsyth   /*        behaviour is unsupported; here a DEBUG opcode is always an     */
6757*37da2899SCharles.Forsyth   /*        error.                                                         */
6758*37da2899SCharles.Forsyth   /*                                                                       */
6759*37da2899SCharles.Forsyth   /*                                                                       */
6760*37da2899SCharles.Forsyth   /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */
6761*37da2899SCharles.Forsyth   /*                                                                       */
6762*37da2899SCharles.Forsyth   /*  Instructions appear in the specification's order.                    */
6763*37da2899SCharles.Forsyth   /*                                                                       */
6764*37da2899SCharles.Forsyth   /*************************************************************************/
6765*37da2899SCharles.Forsyth 
6766*37da2899SCharles.Forsyth 
6767*37da2899SCharles.Forsyth   /* documentation is in ttinterp.h */
6768*37da2899SCharles.Forsyth 
6769*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
TT_RunIns(TT_ExecContext exc)6770*37da2899SCharles.Forsyth   TT_RunIns( TT_ExecContext  exc )
6771*37da2899SCharles.Forsyth   {
6772*37da2899SCharles.Forsyth     FT_Long  ins_counter = 0;  /* executed instructions counter */
6773*37da2899SCharles.Forsyth 
6774*37da2899SCharles.Forsyth 
6775*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_STATIC_RASTER
6776*37da2899SCharles.Forsyth     cur = *exc;
6777*37da2899SCharles.Forsyth #endif
6778*37da2899SCharles.Forsyth 
6779*37da2899SCharles.Forsyth     /* set CVT functions */
6780*37da2899SCharles.Forsyth     CUR.tt_metrics.ratio = 0;
6781*37da2899SCharles.Forsyth     if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
6782*37da2899SCharles.Forsyth     {
6783*37da2899SCharles.Forsyth       /* non-square pixels, use the stretched routines */
6784*37da2899SCharles.Forsyth       CUR.func_read_cvt  = Read_CVT_Stretched;
6785*37da2899SCharles.Forsyth       CUR.func_write_cvt = Write_CVT_Stretched;
6786*37da2899SCharles.Forsyth       CUR.func_move_cvt  = Move_CVT_Stretched;
6787*37da2899SCharles.Forsyth     }
6788*37da2899SCharles.Forsyth     else
6789*37da2899SCharles.Forsyth     {
6790*37da2899SCharles.Forsyth       /* square pixels, use normal routines */
6791*37da2899SCharles.Forsyth       CUR.func_read_cvt  = Read_CVT;
6792*37da2899SCharles.Forsyth       CUR.func_write_cvt = Write_CVT;
6793*37da2899SCharles.Forsyth       CUR.func_move_cvt  = Move_CVT;
6794*37da2899SCharles.Forsyth     }
6795*37da2899SCharles.Forsyth 
6796*37da2899SCharles.Forsyth     COMPUTE_Funcs();
6797*37da2899SCharles.Forsyth     COMPUTE_Round( (FT_Byte)exc->GS.round_state );
6798*37da2899SCharles.Forsyth 
6799*37da2899SCharles.Forsyth     do
6800*37da2899SCharles.Forsyth     {
6801*37da2899SCharles.Forsyth       CUR.opcode = CUR.code[CUR.IP];
6802*37da2899SCharles.Forsyth 
6803*37da2899SCharles.Forsyth       if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
6804*37da2899SCharles.Forsyth       {
6805*37da2899SCharles.Forsyth         if ( CUR.IP + 1 > CUR.codeSize )
6806*37da2899SCharles.Forsyth           goto LErrorCodeOverflow_;
6807*37da2899SCharles.Forsyth 
6808*37da2899SCharles.Forsyth         CUR.length = CUR.code[CUR.IP + 1] + 2;
6809*37da2899SCharles.Forsyth       }
6810*37da2899SCharles.Forsyth 
6811*37da2899SCharles.Forsyth       if ( CUR.IP + CUR.length > CUR.codeSize )
6812*37da2899SCharles.Forsyth         goto LErrorCodeOverflow_;
6813*37da2899SCharles.Forsyth 
6814*37da2899SCharles.Forsyth       /* First, let's check for empty stack and overflow */
6815*37da2899SCharles.Forsyth       CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
6816*37da2899SCharles.Forsyth 
6817*37da2899SCharles.Forsyth       /* `args' is the top of the stack once arguments have been popped. */
6818*37da2899SCharles.Forsyth       /* One can also interpret it as the index of the last argument.    */
6819*37da2899SCharles.Forsyth       if ( CUR.args < 0 )
6820*37da2899SCharles.Forsyth       {
6821*37da2899SCharles.Forsyth         CUR.error = TT_Err_Too_Few_Arguments;
6822*37da2899SCharles.Forsyth         goto LErrorLabel_;
6823*37da2899SCharles.Forsyth       }
6824*37da2899SCharles.Forsyth 
6825*37da2899SCharles.Forsyth       CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
6826*37da2899SCharles.Forsyth 
6827*37da2899SCharles.Forsyth       /* `new_top' is the new top of the stack, after the instruction's */
6828*37da2899SCharles.Forsyth       /* execution.  `top' will be set to `new_top' after the `switch'  */
6829*37da2899SCharles.Forsyth       /* statement.                                                     */
6830*37da2899SCharles.Forsyth       if ( CUR.new_top > CUR.stackSize )
6831*37da2899SCharles.Forsyth       {
6832*37da2899SCharles.Forsyth         CUR.error = TT_Err_Stack_Overflow;
6833*37da2899SCharles.Forsyth         goto LErrorLabel_;
6834*37da2899SCharles.Forsyth       }
6835*37da2899SCharles.Forsyth 
6836*37da2899SCharles.Forsyth       CUR.step_ins = TRUE;
6837*37da2899SCharles.Forsyth       CUR.error    = TT_Err_Ok;
6838*37da2899SCharles.Forsyth 
6839*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
6840*37da2899SCharles.Forsyth 
6841*37da2899SCharles.Forsyth       {
6842*37da2899SCharles.Forsyth         FT_Long*  args   = CUR.stack + CUR.args;
6843*37da2899SCharles.Forsyth         FT_Byte   opcode = CUR.opcode;
6844*37da2899SCharles.Forsyth 
6845*37da2899SCharles.Forsyth 
6846*37da2899SCharles.Forsyth #undef  ARRAY_BOUND_ERROR
6847*37da2899SCharles.Forsyth #define ARRAY_BOUND_ERROR  goto Set_Invalid_Ref
6848*37da2899SCharles.Forsyth 
6849*37da2899SCharles.Forsyth 
6850*37da2899SCharles.Forsyth         switch ( opcode )
6851*37da2899SCharles.Forsyth         {
6852*37da2899SCharles.Forsyth         case 0x00:  /* SVTCA y  */
6853*37da2899SCharles.Forsyth         case 0x01:  /* SVTCA x  */
6854*37da2899SCharles.Forsyth         case 0x02:  /* SPvTCA y */
6855*37da2899SCharles.Forsyth         case 0x03:  /* SPvTCA x */
6856*37da2899SCharles.Forsyth         case 0x04:  /* SFvTCA y */
6857*37da2899SCharles.Forsyth         case 0x05:  /* SFvTCA x */
6858*37da2899SCharles.Forsyth           {
6859*37da2899SCharles.Forsyth             FT_Short AA, BB;
6860*37da2899SCharles.Forsyth 
6861*37da2899SCharles.Forsyth 
6862*37da2899SCharles.Forsyth             AA = (FT_Short)( ( opcode & 1 ) << 14 );
6863*37da2899SCharles.Forsyth             BB = (FT_Short)( AA ^ 0x4000 );
6864*37da2899SCharles.Forsyth 
6865*37da2899SCharles.Forsyth             if ( opcode < 4 )
6866*37da2899SCharles.Forsyth             {
6867*37da2899SCharles.Forsyth               CUR.GS.projVector.x = AA;
6868*37da2899SCharles.Forsyth               CUR.GS.projVector.y = BB;
6869*37da2899SCharles.Forsyth 
6870*37da2899SCharles.Forsyth               CUR.GS.dualVector.x = AA;
6871*37da2899SCharles.Forsyth               CUR.GS.dualVector.y = BB;
6872*37da2899SCharles.Forsyth             }
6873*37da2899SCharles.Forsyth 
6874*37da2899SCharles.Forsyth             if ( ( opcode & 2 ) == 0 )
6875*37da2899SCharles.Forsyth             {
6876*37da2899SCharles.Forsyth               CUR.GS.freeVector.x = AA;
6877*37da2899SCharles.Forsyth               CUR.GS.freeVector.y = BB;
6878*37da2899SCharles.Forsyth             }
6879*37da2899SCharles.Forsyth 
6880*37da2899SCharles.Forsyth             COMPUTE_Funcs();
6881*37da2899SCharles.Forsyth           }
6882*37da2899SCharles.Forsyth           break;
6883*37da2899SCharles.Forsyth 
6884*37da2899SCharles.Forsyth         case 0x06:  /* SPvTL // */
6885*37da2899SCharles.Forsyth         case 0x07:  /* SPvTL +  */
6886*37da2899SCharles.Forsyth           DO_SPVTL
6887*37da2899SCharles.Forsyth           break;
6888*37da2899SCharles.Forsyth 
6889*37da2899SCharles.Forsyth         case 0x08:  /* SFvTL // */
6890*37da2899SCharles.Forsyth         case 0x09:  /* SFvTL +  */
6891*37da2899SCharles.Forsyth           DO_SFVTL
6892*37da2899SCharles.Forsyth           break;
6893*37da2899SCharles.Forsyth 
6894*37da2899SCharles.Forsyth         case 0x0A:  /* SPvFS */
6895*37da2899SCharles.Forsyth           DO_SPVFS
6896*37da2899SCharles.Forsyth           break;
6897*37da2899SCharles.Forsyth 
6898*37da2899SCharles.Forsyth         case 0x0B:  /* SFvFS */
6899*37da2899SCharles.Forsyth           DO_SFVFS
6900*37da2899SCharles.Forsyth           break;
6901*37da2899SCharles.Forsyth 
6902*37da2899SCharles.Forsyth         case 0x0C:  /* GPV */
6903*37da2899SCharles.Forsyth           DO_GPV
6904*37da2899SCharles.Forsyth           break;
6905*37da2899SCharles.Forsyth 
6906*37da2899SCharles.Forsyth         case 0x0D:  /* GFV */
6907*37da2899SCharles.Forsyth           DO_GFV
6908*37da2899SCharles.Forsyth           break;
6909*37da2899SCharles.Forsyth 
6910*37da2899SCharles.Forsyth         case 0x0E:  /* SFvTPv */
6911*37da2899SCharles.Forsyth           DO_SFVTPV
6912*37da2899SCharles.Forsyth           break;
6913*37da2899SCharles.Forsyth 
6914*37da2899SCharles.Forsyth         case 0x0F:  /* ISECT  */
6915*37da2899SCharles.Forsyth           Ins_ISECT( EXEC_ARG_ args );
6916*37da2899SCharles.Forsyth           break;
6917*37da2899SCharles.Forsyth 
6918*37da2899SCharles.Forsyth         case 0x10:  /* SRP0 */
6919*37da2899SCharles.Forsyth           DO_SRP0
6920*37da2899SCharles.Forsyth           break;
6921*37da2899SCharles.Forsyth 
6922*37da2899SCharles.Forsyth         case 0x11:  /* SRP1 */
6923*37da2899SCharles.Forsyth           DO_SRP1
6924*37da2899SCharles.Forsyth           break;
6925*37da2899SCharles.Forsyth 
6926*37da2899SCharles.Forsyth         case 0x12:  /* SRP2 */
6927*37da2899SCharles.Forsyth           DO_SRP2
6928*37da2899SCharles.Forsyth           break;
6929*37da2899SCharles.Forsyth 
6930*37da2899SCharles.Forsyth         case 0x13:  /* SZP0 */
6931*37da2899SCharles.Forsyth           Ins_SZP0( EXEC_ARG_ args );
6932*37da2899SCharles.Forsyth           break;
6933*37da2899SCharles.Forsyth 
6934*37da2899SCharles.Forsyth         case 0x14:  /* SZP1 */
6935*37da2899SCharles.Forsyth           Ins_SZP1( EXEC_ARG_ args );
6936*37da2899SCharles.Forsyth           break;
6937*37da2899SCharles.Forsyth 
6938*37da2899SCharles.Forsyth         case 0x15:  /* SZP2 */
6939*37da2899SCharles.Forsyth           Ins_SZP2( EXEC_ARG_ args );
6940*37da2899SCharles.Forsyth           break;
6941*37da2899SCharles.Forsyth 
6942*37da2899SCharles.Forsyth         case 0x16:  /* SZPS */
6943*37da2899SCharles.Forsyth           Ins_SZPS( EXEC_ARG_ args );
6944*37da2899SCharles.Forsyth           break;
6945*37da2899SCharles.Forsyth 
6946*37da2899SCharles.Forsyth         case 0x17:  /* SLOOP */
6947*37da2899SCharles.Forsyth           DO_SLOOP
6948*37da2899SCharles.Forsyth           break;
6949*37da2899SCharles.Forsyth 
6950*37da2899SCharles.Forsyth         case 0x18:  /* RTG */
6951*37da2899SCharles.Forsyth           DO_RTG
6952*37da2899SCharles.Forsyth           break;
6953*37da2899SCharles.Forsyth 
6954*37da2899SCharles.Forsyth         case 0x19:  /* RTHG */
6955*37da2899SCharles.Forsyth           DO_RTHG
6956*37da2899SCharles.Forsyth           break;
6957*37da2899SCharles.Forsyth 
6958*37da2899SCharles.Forsyth         case 0x1A:  /* SMD */
6959*37da2899SCharles.Forsyth           DO_SMD
6960*37da2899SCharles.Forsyth           break;
6961*37da2899SCharles.Forsyth 
6962*37da2899SCharles.Forsyth         case 0x1B:  /* ELSE */
6963*37da2899SCharles.Forsyth           Ins_ELSE( EXEC_ARG_ args );
6964*37da2899SCharles.Forsyth           break;
6965*37da2899SCharles.Forsyth 
6966*37da2899SCharles.Forsyth         case 0x1C:  /* JMPR */
6967*37da2899SCharles.Forsyth           DO_JMPR
6968*37da2899SCharles.Forsyth           break;
6969*37da2899SCharles.Forsyth 
6970*37da2899SCharles.Forsyth         case 0x1D:  /* SCVTCI */
6971*37da2899SCharles.Forsyth           DO_SCVTCI
6972*37da2899SCharles.Forsyth           break;
6973*37da2899SCharles.Forsyth 
6974*37da2899SCharles.Forsyth         case 0x1E:  /* SSWCI */
6975*37da2899SCharles.Forsyth           DO_SSWCI
6976*37da2899SCharles.Forsyth           break;
6977*37da2899SCharles.Forsyth 
6978*37da2899SCharles.Forsyth         case 0x1F:  /* SSW */
6979*37da2899SCharles.Forsyth           DO_SSW
6980*37da2899SCharles.Forsyth           break;
6981*37da2899SCharles.Forsyth 
6982*37da2899SCharles.Forsyth         case 0x20:  /* DUP */
6983*37da2899SCharles.Forsyth           DO_DUP
6984*37da2899SCharles.Forsyth           break;
6985*37da2899SCharles.Forsyth 
6986*37da2899SCharles.Forsyth         case 0x21:  /* POP */
6987*37da2899SCharles.Forsyth           /* nothing :-) */
6988*37da2899SCharles.Forsyth           break;
6989*37da2899SCharles.Forsyth 
6990*37da2899SCharles.Forsyth         case 0x22:  /* CLEAR */
6991*37da2899SCharles.Forsyth           DO_CLEAR
6992*37da2899SCharles.Forsyth           break;
6993*37da2899SCharles.Forsyth 
6994*37da2899SCharles.Forsyth         case 0x23:  /* SWAP */
6995*37da2899SCharles.Forsyth           DO_SWAP
6996*37da2899SCharles.Forsyth           break;
6997*37da2899SCharles.Forsyth 
6998*37da2899SCharles.Forsyth         case 0x24:  /* DEPTH */
6999*37da2899SCharles.Forsyth           DO_DEPTH
7000*37da2899SCharles.Forsyth           break;
7001*37da2899SCharles.Forsyth 
7002*37da2899SCharles.Forsyth         case 0x25:  /* CINDEX */
7003*37da2899SCharles.Forsyth           DO_CINDEX
7004*37da2899SCharles.Forsyth           break;
7005*37da2899SCharles.Forsyth 
7006*37da2899SCharles.Forsyth         case 0x26:  /* MINDEX */
7007*37da2899SCharles.Forsyth           Ins_MINDEX( EXEC_ARG_ args );
7008*37da2899SCharles.Forsyth           break;
7009*37da2899SCharles.Forsyth 
7010*37da2899SCharles.Forsyth         case 0x27:  /* ALIGNPTS */
7011*37da2899SCharles.Forsyth           Ins_ALIGNPTS( EXEC_ARG_ args );
7012*37da2899SCharles.Forsyth           break;
7013*37da2899SCharles.Forsyth 
7014*37da2899SCharles.Forsyth         case 0x28:  /* ???? */
7015*37da2899SCharles.Forsyth           Ins_UNKNOWN( EXEC_ARG_ args );
7016*37da2899SCharles.Forsyth           break;
7017*37da2899SCharles.Forsyth 
7018*37da2899SCharles.Forsyth         case 0x29:  /* UTP */
7019*37da2899SCharles.Forsyth           Ins_UTP( EXEC_ARG_ args );
7020*37da2899SCharles.Forsyth           break;
7021*37da2899SCharles.Forsyth 
7022*37da2899SCharles.Forsyth         case 0x2A:  /* LOOPCALL */
7023*37da2899SCharles.Forsyth           Ins_LOOPCALL( EXEC_ARG_ args );
7024*37da2899SCharles.Forsyth           break;
7025*37da2899SCharles.Forsyth 
7026*37da2899SCharles.Forsyth         case 0x2B:  /* CALL */
7027*37da2899SCharles.Forsyth           Ins_CALL( EXEC_ARG_ args );
7028*37da2899SCharles.Forsyth           break;
7029*37da2899SCharles.Forsyth 
7030*37da2899SCharles.Forsyth         case 0x2C:  /* FDEF */
7031*37da2899SCharles.Forsyth           Ins_FDEF( EXEC_ARG_ args );
7032*37da2899SCharles.Forsyth           break;
7033*37da2899SCharles.Forsyth 
7034*37da2899SCharles.Forsyth         case 0x2D:  /* ENDF */
7035*37da2899SCharles.Forsyth           Ins_ENDF( EXEC_ARG_ args );
7036*37da2899SCharles.Forsyth           break;
7037*37da2899SCharles.Forsyth 
7038*37da2899SCharles.Forsyth         case 0x2E:  /* MDAP */
7039*37da2899SCharles.Forsyth         case 0x2F:  /* MDAP */
7040*37da2899SCharles.Forsyth           Ins_MDAP( EXEC_ARG_ args );
7041*37da2899SCharles.Forsyth           break;
7042*37da2899SCharles.Forsyth 
7043*37da2899SCharles.Forsyth 
7044*37da2899SCharles.Forsyth         case 0x30:  /* IUP */
7045*37da2899SCharles.Forsyth         case 0x31:  /* IUP */
7046*37da2899SCharles.Forsyth           Ins_IUP( EXEC_ARG_ args );
7047*37da2899SCharles.Forsyth           break;
7048*37da2899SCharles.Forsyth 
7049*37da2899SCharles.Forsyth         case 0x32:  /* SHP */
7050*37da2899SCharles.Forsyth         case 0x33:  /* SHP */
7051*37da2899SCharles.Forsyth           Ins_SHP( EXEC_ARG_ args );
7052*37da2899SCharles.Forsyth           break;
7053*37da2899SCharles.Forsyth 
7054*37da2899SCharles.Forsyth         case 0x34:  /* SHC */
7055*37da2899SCharles.Forsyth         case 0x35:  /* SHC */
7056*37da2899SCharles.Forsyth           Ins_SHC( EXEC_ARG_ args );
7057*37da2899SCharles.Forsyth           break;
7058*37da2899SCharles.Forsyth 
7059*37da2899SCharles.Forsyth         case 0x36:  /* SHZ */
7060*37da2899SCharles.Forsyth         case 0x37:  /* SHZ */
7061*37da2899SCharles.Forsyth           Ins_SHZ( EXEC_ARG_ args );
7062*37da2899SCharles.Forsyth           break;
7063*37da2899SCharles.Forsyth 
7064*37da2899SCharles.Forsyth         case 0x38:  /* SHPIX */
7065*37da2899SCharles.Forsyth           Ins_SHPIX( EXEC_ARG_ args );
7066*37da2899SCharles.Forsyth           break;
7067*37da2899SCharles.Forsyth 
7068*37da2899SCharles.Forsyth         case 0x39:  /* IP    */
7069*37da2899SCharles.Forsyth           Ins_IP( EXEC_ARG_ args );
7070*37da2899SCharles.Forsyth           break;
7071*37da2899SCharles.Forsyth 
7072*37da2899SCharles.Forsyth         case 0x3A:  /* MSIRP */
7073*37da2899SCharles.Forsyth         case 0x3B:  /* MSIRP */
7074*37da2899SCharles.Forsyth           Ins_MSIRP( EXEC_ARG_ args );
7075*37da2899SCharles.Forsyth           break;
7076*37da2899SCharles.Forsyth 
7077*37da2899SCharles.Forsyth         case 0x3C:  /* AlignRP */
7078*37da2899SCharles.Forsyth           Ins_ALIGNRP( EXEC_ARG_ args );
7079*37da2899SCharles.Forsyth           break;
7080*37da2899SCharles.Forsyth 
7081*37da2899SCharles.Forsyth         case 0x3D:  /* RTDG */
7082*37da2899SCharles.Forsyth           DO_RTDG
7083*37da2899SCharles.Forsyth           break;
7084*37da2899SCharles.Forsyth 
7085*37da2899SCharles.Forsyth         case 0x3E:  /* MIAP */
7086*37da2899SCharles.Forsyth         case 0x3F:  /* MIAP */
7087*37da2899SCharles.Forsyth           Ins_MIAP( EXEC_ARG_ args );
7088*37da2899SCharles.Forsyth           break;
7089*37da2899SCharles.Forsyth 
7090*37da2899SCharles.Forsyth         case 0x40:  /* NPUSHB */
7091*37da2899SCharles.Forsyth           Ins_NPUSHB( EXEC_ARG_ args );
7092*37da2899SCharles.Forsyth           break;
7093*37da2899SCharles.Forsyth 
7094*37da2899SCharles.Forsyth         case 0x41:  /* NPUSHW */
7095*37da2899SCharles.Forsyth           Ins_NPUSHW( EXEC_ARG_ args );
7096*37da2899SCharles.Forsyth           break;
7097*37da2899SCharles.Forsyth 
7098*37da2899SCharles.Forsyth         case 0x42:  /* WS */
7099*37da2899SCharles.Forsyth           DO_WS
7100*37da2899SCharles.Forsyth           break;
7101*37da2899SCharles.Forsyth 
7102*37da2899SCharles.Forsyth       Set_Invalid_Ref:
7103*37da2899SCharles.Forsyth             CUR.error = TT_Err_Invalid_Reference;
7104*37da2899SCharles.Forsyth           break;
7105*37da2899SCharles.Forsyth 
7106*37da2899SCharles.Forsyth         case 0x43:  /* RS */
7107*37da2899SCharles.Forsyth           DO_RS
7108*37da2899SCharles.Forsyth           break;
7109*37da2899SCharles.Forsyth 
7110*37da2899SCharles.Forsyth         case 0x44:  /* WCVTP */
7111*37da2899SCharles.Forsyth           DO_WCVTP
7112*37da2899SCharles.Forsyth           break;
7113*37da2899SCharles.Forsyth 
7114*37da2899SCharles.Forsyth         case 0x45:  /* RCVT */
7115*37da2899SCharles.Forsyth           DO_RCVT
7116*37da2899SCharles.Forsyth           break;
7117*37da2899SCharles.Forsyth 
7118*37da2899SCharles.Forsyth         case 0x46:  /* GC */
7119*37da2899SCharles.Forsyth         case 0x47:  /* GC */
7120*37da2899SCharles.Forsyth           Ins_GC( EXEC_ARG_ args );
7121*37da2899SCharles.Forsyth           break;
7122*37da2899SCharles.Forsyth 
7123*37da2899SCharles.Forsyth         case 0x48:  /* SCFS */
7124*37da2899SCharles.Forsyth           Ins_SCFS( EXEC_ARG_ args );
7125*37da2899SCharles.Forsyth           break;
7126*37da2899SCharles.Forsyth 
7127*37da2899SCharles.Forsyth         case 0x49:  /* MD */
7128*37da2899SCharles.Forsyth         case 0x4A:  /* MD */
7129*37da2899SCharles.Forsyth           Ins_MD( EXEC_ARG_ args );
7130*37da2899SCharles.Forsyth           break;
7131*37da2899SCharles.Forsyth 
7132*37da2899SCharles.Forsyth         case 0x4B:  /* MPPEM */
7133*37da2899SCharles.Forsyth           DO_MPPEM
7134*37da2899SCharles.Forsyth           break;
7135*37da2899SCharles.Forsyth 
7136*37da2899SCharles.Forsyth         case 0x4C:  /* MPS */
7137*37da2899SCharles.Forsyth           DO_MPS
7138*37da2899SCharles.Forsyth           break;
7139*37da2899SCharles.Forsyth 
7140*37da2899SCharles.Forsyth         case 0x4D:  /* FLIPON */
7141*37da2899SCharles.Forsyth           DO_FLIPON
7142*37da2899SCharles.Forsyth           break;
7143*37da2899SCharles.Forsyth 
7144*37da2899SCharles.Forsyth         case 0x4E:  /* FLIPOFF */
7145*37da2899SCharles.Forsyth           DO_FLIPOFF
7146*37da2899SCharles.Forsyth           break;
7147*37da2899SCharles.Forsyth 
7148*37da2899SCharles.Forsyth         case 0x4F:  /* DEBUG */
7149*37da2899SCharles.Forsyth           DO_DEBUG
7150*37da2899SCharles.Forsyth           break;
7151*37da2899SCharles.Forsyth 
7152*37da2899SCharles.Forsyth         case 0x50:  /* LT */
7153*37da2899SCharles.Forsyth           DO_LT
7154*37da2899SCharles.Forsyth           break;
7155*37da2899SCharles.Forsyth 
7156*37da2899SCharles.Forsyth         case 0x51:  /* LTEQ */
7157*37da2899SCharles.Forsyth           DO_LTEQ
7158*37da2899SCharles.Forsyth           break;
7159*37da2899SCharles.Forsyth 
7160*37da2899SCharles.Forsyth         case 0x52:  /* GT */
7161*37da2899SCharles.Forsyth           DO_GT
7162*37da2899SCharles.Forsyth           break;
7163*37da2899SCharles.Forsyth 
7164*37da2899SCharles.Forsyth         case 0x53:  /* GTEQ */
7165*37da2899SCharles.Forsyth           DO_GTEQ
7166*37da2899SCharles.Forsyth           break;
7167*37da2899SCharles.Forsyth 
7168*37da2899SCharles.Forsyth         case 0x54:  /* EQ */
7169*37da2899SCharles.Forsyth           DO_EQ
7170*37da2899SCharles.Forsyth           break;
7171*37da2899SCharles.Forsyth 
7172*37da2899SCharles.Forsyth         case 0x55:  /* NEQ */
7173*37da2899SCharles.Forsyth           DO_NEQ
7174*37da2899SCharles.Forsyth           break;
7175*37da2899SCharles.Forsyth 
7176*37da2899SCharles.Forsyth         case 0x56:  /* ODD */
7177*37da2899SCharles.Forsyth           DO_ODD
7178*37da2899SCharles.Forsyth           break;
7179*37da2899SCharles.Forsyth 
7180*37da2899SCharles.Forsyth         case 0x57:  /* EVEN */
7181*37da2899SCharles.Forsyth           DO_EVEN
7182*37da2899SCharles.Forsyth           break;
7183*37da2899SCharles.Forsyth 
7184*37da2899SCharles.Forsyth         case 0x58:  /* IF */
7185*37da2899SCharles.Forsyth           Ins_IF( EXEC_ARG_ args );
7186*37da2899SCharles.Forsyth           break;
7187*37da2899SCharles.Forsyth 
7188*37da2899SCharles.Forsyth         case 0x59:  /* EIF */
7189*37da2899SCharles.Forsyth           /* do nothing */
7190*37da2899SCharles.Forsyth           break;
7191*37da2899SCharles.Forsyth 
7192*37da2899SCharles.Forsyth         case 0x5A:  /* AND */
7193*37da2899SCharles.Forsyth           DO_AND
7194*37da2899SCharles.Forsyth           break;
7195*37da2899SCharles.Forsyth 
7196*37da2899SCharles.Forsyth         case 0x5B:  /* OR */
7197*37da2899SCharles.Forsyth           DO_OR
7198*37da2899SCharles.Forsyth           break;
7199*37da2899SCharles.Forsyth 
7200*37da2899SCharles.Forsyth         case 0x5C:  /* NOT */
7201*37da2899SCharles.Forsyth           DO_NOT
7202*37da2899SCharles.Forsyth           break;
7203*37da2899SCharles.Forsyth 
7204*37da2899SCharles.Forsyth         case 0x5D:  /* DELTAP1 */
7205*37da2899SCharles.Forsyth           Ins_DELTAP( EXEC_ARG_ args );
7206*37da2899SCharles.Forsyth           break;
7207*37da2899SCharles.Forsyth 
7208*37da2899SCharles.Forsyth         case 0x5E:  /* SDB */
7209*37da2899SCharles.Forsyth           DO_SDB
7210*37da2899SCharles.Forsyth           break;
7211*37da2899SCharles.Forsyth 
7212*37da2899SCharles.Forsyth         case 0x5F:  /* SDS */
7213*37da2899SCharles.Forsyth           DO_SDS
7214*37da2899SCharles.Forsyth           break;
7215*37da2899SCharles.Forsyth 
7216*37da2899SCharles.Forsyth         case 0x60:  /* ADD */
7217*37da2899SCharles.Forsyth           DO_ADD
7218*37da2899SCharles.Forsyth           break;
7219*37da2899SCharles.Forsyth 
7220*37da2899SCharles.Forsyth         case 0x61:  /* SUB */
7221*37da2899SCharles.Forsyth           DO_SUB
7222*37da2899SCharles.Forsyth           break;
7223*37da2899SCharles.Forsyth 
7224*37da2899SCharles.Forsyth         case 0x62:  /* DIV */
7225*37da2899SCharles.Forsyth           DO_DIV
7226*37da2899SCharles.Forsyth           break;
7227*37da2899SCharles.Forsyth 
7228*37da2899SCharles.Forsyth         case 0x63:  /* MUL */
7229*37da2899SCharles.Forsyth           DO_MUL
7230*37da2899SCharles.Forsyth           break;
7231*37da2899SCharles.Forsyth 
7232*37da2899SCharles.Forsyth         case 0x64:  /* ABS */
7233*37da2899SCharles.Forsyth           DO_ABS
7234*37da2899SCharles.Forsyth           break;
7235*37da2899SCharles.Forsyth 
7236*37da2899SCharles.Forsyth         case 0x65:  /* NEG */
7237*37da2899SCharles.Forsyth           DO_NEG
7238*37da2899SCharles.Forsyth           break;
7239*37da2899SCharles.Forsyth 
7240*37da2899SCharles.Forsyth         case 0x66:  /* FLOOR */
7241*37da2899SCharles.Forsyth           DO_FLOOR
7242*37da2899SCharles.Forsyth           break;
7243*37da2899SCharles.Forsyth 
7244*37da2899SCharles.Forsyth         case 0x67:  /* CEILING */
7245*37da2899SCharles.Forsyth           DO_CEILING
7246*37da2899SCharles.Forsyth           break;
7247*37da2899SCharles.Forsyth 
7248*37da2899SCharles.Forsyth         case 0x68:  /* ROUND */
7249*37da2899SCharles.Forsyth         case 0x69:  /* ROUND */
7250*37da2899SCharles.Forsyth         case 0x6A:  /* ROUND */
7251*37da2899SCharles.Forsyth         case 0x6B:  /* ROUND */
7252*37da2899SCharles.Forsyth           DO_ROUND
7253*37da2899SCharles.Forsyth           break;
7254*37da2899SCharles.Forsyth 
7255*37da2899SCharles.Forsyth         case 0x6C:  /* NROUND */
7256*37da2899SCharles.Forsyth         case 0x6D:  /* NROUND */
7257*37da2899SCharles.Forsyth         case 0x6E:  /* NRRUND */
7258*37da2899SCharles.Forsyth         case 0x6F:  /* NROUND */
7259*37da2899SCharles.Forsyth           DO_NROUND
7260*37da2899SCharles.Forsyth           break;
7261*37da2899SCharles.Forsyth 
7262*37da2899SCharles.Forsyth         case 0x70:  /* WCVTF */
7263*37da2899SCharles.Forsyth           DO_WCVTF
7264*37da2899SCharles.Forsyth           break;
7265*37da2899SCharles.Forsyth 
7266*37da2899SCharles.Forsyth         case 0x71:  /* DELTAP2 */
7267*37da2899SCharles.Forsyth         case 0x72:  /* DELTAP3 */
7268*37da2899SCharles.Forsyth           Ins_DELTAP( EXEC_ARG_ args );
7269*37da2899SCharles.Forsyth           break;
7270*37da2899SCharles.Forsyth 
7271*37da2899SCharles.Forsyth         case 0x73:  /* DELTAC0 */
7272*37da2899SCharles.Forsyth         case 0x74:  /* DELTAC1 */
7273*37da2899SCharles.Forsyth         case 0x75:  /* DELTAC2 */
7274*37da2899SCharles.Forsyth           Ins_DELTAC( EXEC_ARG_ args );
7275*37da2899SCharles.Forsyth           break;
7276*37da2899SCharles.Forsyth 
7277*37da2899SCharles.Forsyth         case 0x76:  /* SROUND */
7278*37da2899SCharles.Forsyth           DO_SROUND
7279*37da2899SCharles.Forsyth           break;
7280*37da2899SCharles.Forsyth 
7281*37da2899SCharles.Forsyth         case 0x77:  /* S45Round */
7282*37da2899SCharles.Forsyth           DO_S45ROUND
7283*37da2899SCharles.Forsyth           break;
7284*37da2899SCharles.Forsyth 
7285*37da2899SCharles.Forsyth         case 0x78:  /* JROT */
7286*37da2899SCharles.Forsyth           DO_JROT
7287*37da2899SCharles.Forsyth           break;
7288*37da2899SCharles.Forsyth 
7289*37da2899SCharles.Forsyth         case 0x79:  /* JROF */
7290*37da2899SCharles.Forsyth           DO_JROF
7291*37da2899SCharles.Forsyth           break;
7292*37da2899SCharles.Forsyth 
7293*37da2899SCharles.Forsyth         case 0x7A:  /* ROFF */
7294*37da2899SCharles.Forsyth           DO_ROFF
7295*37da2899SCharles.Forsyth           break;
7296*37da2899SCharles.Forsyth 
7297*37da2899SCharles.Forsyth         case 0x7B:  /* ???? */
7298*37da2899SCharles.Forsyth           Ins_UNKNOWN( EXEC_ARG_ args );
7299*37da2899SCharles.Forsyth           break;
7300*37da2899SCharles.Forsyth 
7301*37da2899SCharles.Forsyth         case 0x7C:  /* RUTG */
7302*37da2899SCharles.Forsyth           DO_RUTG
7303*37da2899SCharles.Forsyth           break;
7304*37da2899SCharles.Forsyth 
7305*37da2899SCharles.Forsyth         case 0x7D:  /* RDTG */
7306*37da2899SCharles.Forsyth           DO_RDTG
7307*37da2899SCharles.Forsyth           break;
7308*37da2899SCharles.Forsyth 
7309*37da2899SCharles.Forsyth         case 0x7E:  /* SANGW */
7310*37da2899SCharles.Forsyth         case 0x7F:  /* AA    */
7311*37da2899SCharles.Forsyth           /* nothing - obsolete */
7312*37da2899SCharles.Forsyth           break;
7313*37da2899SCharles.Forsyth 
7314*37da2899SCharles.Forsyth         case 0x80:  /* FLIPPT */
7315*37da2899SCharles.Forsyth           Ins_FLIPPT( EXEC_ARG_ args );
7316*37da2899SCharles.Forsyth           break;
7317*37da2899SCharles.Forsyth 
7318*37da2899SCharles.Forsyth         case 0x81:  /* FLIPRGON */
7319*37da2899SCharles.Forsyth           Ins_FLIPRGON( EXEC_ARG_ args );
7320*37da2899SCharles.Forsyth           break;
7321*37da2899SCharles.Forsyth 
7322*37da2899SCharles.Forsyth         case 0x82:  /* FLIPRGOFF */
7323*37da2899SCharles.Forsyth           Ins_FLIPRGOFF( EXEC_ARG_ args );
7324*37da2899SCharles.Forsyth           break;
7325*37da2899SCharles.Forsyth 
7326*37da2899SCharles.Forsyth         case 0x83:  /* UNKNOWN */
7327*37da2899SCharles.Forsyth         case 0x84:  /* UNKNOWN */
7328*37da2899SCharles.Forsyth           Ins_UNKNOWN( EXEC_ARG_ args );
7329*37da2899SCharles.Forsyth           break;
7330*37da2899SCharles.Forsyth 
7331*37da2899SCharles.Forsyth         case 0x85:  /* SCANCTRL */
7332*37da2899SCharles.Forsyth           Ins_SCANCTRL( EXEC_ARG_ args );
7333*37da2899SCharles.Forsyth           break;
7334*37da2899SCharles.Forsyth 
7335*37da2899SCharles.Forsyth         case 0x86:  /* SDPVTL */
7336*37da2899SCharles.Forsyth         case 0x87:  /* SDPVTL */
7337*37da2899SCharles.Forsyth           Ins_SDPVTL( EXEC_ARG_ args );
7338*37da2899SCharles.Forsyth           break;
7339*37da2899SCharles.Forsyth 
7340*37da2899SCharles.Forsyth         case 0x88:  /* GETINFO */
7341*37da2899SCharles.Forsyth           Ins_GETINFO( EXEC_ARG_ args );
7342*37da2899SCharles.Forsyth           break;
7343*37da2899SCharles.Forsyth 
7344*37da2899SCharles.Forsyth         case 0x89:  /* IDEF */
7345*37da2899SCharles.Forsyth           Ins_IDEF( EXEC_ARG_ args );
7346*37da2899SCharles.Forsyth           break;
7347*37da2899SCharles.Forsyth 
7348*37da2899SCharles.Forsyth         case 0x8A:  /* ROLL */
7349*37da2899SCharles.Forsyth           Ins_ROLL( EXEC_ARG_ args );
7350*37da2899SCharles.Forsyth           break;
7351*37da2899SCharles.Forsyth 
7352*37da2899SCharles.Forsyth         case 0x8B:  /* MAX */
7353*37da2899SCharles.Forsyth           DO_MAX
7354*37da2899SCharles.Forsyth           break;
7355*37da2899SCharles.Forsyth 
7356*37da2899SCharles.Forsyth         case 0x8C:  /* MIN */
7357*37da2899SCharles.Forsyth           DO_MIN
7358*37da2899SCharles.Forsyth           break;
7359*37da2899SCharles.Forsyth 
7360*37da2899SCharles.Forsyth         case 0x8D:  /* SCANTYPE */
7361*37da2899SCharles.Forsyth           Ins_SCANTYPE( EXEC_ARG_ args );
7362*37da2899SCharles.Forsyth           break;
7363*37da2899SCharles.Forsyth 
7364*37da2899SCharles.Forsyth         case 0x8E:  /* INSTCTRL */
7365*37da2899SCharles.Forsyth           Ins_INSTCTRL( EXEC_ARG_ args );
7366*37da2899SCharles.Forsyth           break;
7367*37da2899SCharles.Forsyth 
7368*37da2899SCharles.Forsyth         case 0x8F:
7369*37da2899SCharles.Forsyth           Ins_UNKNOWN( EXEC_ARG_ args );
7370*37da2899SCharles.Forsyth           break;
7371*37da2899SCharles.Forsyth 
7372*37da2899SCharles.Forsyth         default:
7373*37da2899SCharles.Forsyth           if ( opcode >= 0xE0 )
7374*37da2899SCharles.Forsyth             Ins_MIRP( EXEC_ARG_ args );
7375*37da2899SCharles.Forsyth           else if ( opcode >= 0xC0 )
7376*37da2899SCharles.Forsyth             Ins_MDRP( EXEC_ARG_ args );
7377*37da2899SCharles.Forsyth           else if ( opcode >= 0xB8 )
7378*37da2899SCharles.Forsyth             Ins_PUSHW( EXEC_ARG_ args );
7379*37da2899SCharles.Forsyth           else if ( opcode >= 0xB0 )
7380*37da2899SCharles.Forsyth             Ins_PUSHB( EXEC_ARG_ args );
7381*37da2899SCharles.Forsyth           else
7382*37da2899SCharles.Forsyth             Ins_UNKNOWN( EXEC_ARG_ args );
7383*37da2899SCharles.Forsyth         }
7384*37da2899SCharles.Forsyth 
7385*37da2899SCharles.Forsyth       }
7386*37da2899SCharles.Forsyth 
7387*37da2899SCharles.Forsyth #else
7388*37da2899SCharles.Forsyth 
7389*37da2899SCharles.Forsyth       Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
7390*37da2899SCharles.Forsyth 
7391*37da2899SCharles.Forsyth #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
7392*37da2899SCharles.Forsyth 
7393*37da2899SCharles.Forsyth       if ( CUR.error != TT_Err_Ok )
7394*37da2899SCharles.Forsyth       {
7395*37da2899SCharles.Forsyth         switch ( CUR.error )
7396*37da2899SCharles.Forsyth         {
7397*37da2899SCharles.Forsyth         case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
7398*37da2899SCharles.Forsyth           {
7399*37da2899SCharles.Forsyth             TT_DefRecord*  def   = CUR.IDefs;
7400*37da2899SCharles.Forsyth             TT_DefRecord*  limit = def + CUR.numIDefs;
7401*37da2899SCharles.Forsyth 
7402*37da2899SCharles.Forsyth 
7403*37da2899SCharles.Forsyth             for ( ; def < limit; def++ )
7404*37da2899SCharles.Forsyth             {
7405*37da2899SCharles.Forsyth               if ( def->active && CUR.opcode == (FT_Byte)def->opc )
7406*37da2899SCharles.Forsyth               {
7407*37da2899SCharles.Forsyth                 TT_CallRec*  callrec;
7408*37da2899SCharles.Forsyth 
7409*37da2899SCharles.Forsyth 
7410*37da2899SCharles.Forsyth                 if ( CUR.callTop >= CUR.callSize )
7411*37da2899SCharles.Forsyth                 {
7412*37da2899SCharles.Forsyth                   CUR.error = TT_Err_Invalid_Reference;
7413*37da2899SCharles.Forsyth                   goto LErrorLabel_;
7414*37da2899SCharles.Forsyth                 }
7415*37da2899SCharles.Forsyth 
7416*37da2899SCharles.Forsyth                 callrec = &CUR.callStack[CUR.callTop];
7417*37da2899SCharles.Forsyth 
7418*37da2899SCharles.Forsyth                 callrec->Caller_Range = CUR.curRange;
7419*37da2899SCharles.Forsyth                 callrec->Caller_IP    = CUR.IP + 1;
7420*37da2899SCharles.Forsyth                 callrec->Cur_Count    = 1;
7421*37da2899SCharles.Forsyth                 callrec->Cur_Restart  = def->start;
7422*37da2899SCharles.Forsyth 
7423*37da2899SCharles.Forsyth                 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
7424*37da2899SCharles.Forsyth                   goto LErrorLabel_;
7425*37da2899SCharles.Forsyth 
7426*37da2899SCharles.Forsyth                 goto LSuiteLabel_;
7427*37da2899SCharles.Forsyth               }
7428*37da2899SCharles.Forsyth             }
7429*37da2899SCharles.Forsyth           }
7430*37da2899SCharles.Forsyth 
7431*37da2899SCharles.Forsyth           CUR.error = TT_Err_Invalid_Opcode;
7432*37da2899SCharles.Forsyth           goto LErrorLabel_;
7433*37da2899SCharles.Forsyth 
7434*37da2899SCharles.Forsyth #if 0
7435*37da2899SCharles.Forsyth           break;   /* Unreachable code warning suppression.             */
7436*37da2899SCharles.Forsyth                    /* Leave to remind in case a later change the editor */
7437*37da2899SCharles.Forsyth                    /* to consider break;                                */
7438*37da2899SCharles.Forsyth #endif
7439*37da2899SCharles.Forsyth 
7440*37da2899SCharles.Forsyth         default:
7441*37da2899SCharles.Forsyth           goto LErrorLabel_;
7442*37da2899SCharles.Forsyth 
7443*37da2899SCharles.Forsyth #if 0
7444*37da2899SCharles.Forsyth         break;
7445*37da2899SCharles.Forsyth #endif
7446*37da2899SCharles.Forsyth         }
7447*37da2899SCharles.Forsyth       }
7448*37da2899SCharles.Forsyth 
7449*37da2899SCharles.Forsyth       CUR.top = CUR.new_top;
7450*37da2899SCharles.Forsyth 
7451*37da2899SCharles.Forsyth       if ( CUR.step_ins )
7452*37da2899SCharles.Forsyth         CUR.IP += CUR.length;
7453*37da2899SCharles.Forsyth 
7454*37da2899SCharles.Forsyth       /* increment instruction counter and check if we didn't */
7455*37da2899SCharles.Forsyth       /* run this program for too long (e.g. infinite loops). */
7456*37da2899SCharles.Forsyth       if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
7457*37da2899SCharles.Forsyth         return TT_Err_Execution_Too_Long;
7458*37da2899SCharles.Forsyth 
7459*37da2899SCharles.Forsyth     LSuiteLabel_:
7460*37da2899SCharles.Forsyth       if ( CUR.IP >= CUR.codeSize )
7461*37da2899SCharles.Forsyth       {
7462*37da2899SCharles.Forsyth         if ( CUR.callTop > 0 )
7463*37da2899SCharles.Forsyth         {
7464*37da2899SCharles.Forsyth           CUR.error = TT_Err_Code_Overflow;
7465*37da2899SCharles.Forsyth           goto LErrorLabel_;
7466*37da2899SCharles.Forsyth         }
7467*37da2899SCharles.Forsyth         else
7468*37da2899SCharles.Forsyth           goto LNo_Error_;
7469*37da2899SCharles.Forsyth       }
7470*37da2899SCharles.Forsyth     } while ( !CUR.instruction_trap );
7471*37da2899SCharles.Forsyth 
7472*37da2899SCharles.Forsyth   LNo_Error_:
7473*37da2899SCharles.Forsyth 
7474*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_STATIC_RASTER
7475*37da2899SCharles.Forsyth     *exc = cur;
7476*37da2899SCharles.Forsyth #endif
7477*37da2899SCharles.Forsyth 
7478*37da2899SCharles.Forsyth     return TT_Err_Ok;
7479*37da2899SCharles.Forsyth 
7480*37da2899SCharles.Forsyth   LErrorCodeOverflow_:
7481*37da2899SCharles.Forsyth     CUR.error = TT_Err_Code_Overflow;
7482*37da2899SCharles.Forsyth 
7483*37da2899SCharles.Forsyth   LErrorLabel_:
7484*37da2899SCharles.Forsyth 
7485*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_STATIC_RASTER
7486*37da2899SCharles.Forsyth     *exc = cur;
7487*37da2899SCharles.Forsyth #endif
7488*37da2899SCharles.Forsyth 
7489*37da2899SCharles.Forsyth     return CUR.error;
7490*37da2899SCharles.Forsyth   }
7491*37da2899SCharles.Forsyth 
7492*37da2899SCharles.Forsyth 
7493*37da2899SCharles.Forsyth #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
7494*37da2899SCharles.Forsyth 
7495*37da2899SCharles.Forsyth 
7496*37da2899SCharles.Forsyth /* END */
7497