XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / truetype / ttinterp.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ttinterp.c                                                             */
4 /*                                                                         */
5 /*    TrueType bytecode interpreter (body).                                */
6 /*                                                                         */
7 /*  Copyright 1996-2013                                                    */
8 /*  by David Turner, Robert Wilhelm, and Werner Lemberg.                   */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17
18
19 /* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */
20 /* issues; many thanks!                                                */
21
22
23 #include "../../include/ft2build.h"
24 #include "../../include/freetype/internal/ftdebug.h"
25 #include "../../include/freetype/internal/ftcalc.h"
26 #include "../../include/freetype/fttrigon.h"
27 #include "../../include/freetype/ftsystem.h"
28 #include "../../include/freetype/ftttdrv.h"
29
30 #include "ttinterp.h"
31 #include "tterrors.h"
32 #include "ttsubpix.h"
33
34
35 #ifdef TT_USE_BYTECODE_INTERPRETER
36
37
38   /*************************************************************************/
39   /*                                                                       */
40   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
41   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
42   /* messages during execution.                                            */
43   /*                                                                       */
44 #undef  FT_COMPONENT
45 #define FT_COMPONENT  trace_ttinterp
46
47   /*************************************************************************/
48   /*                                                                       */
49   /* In order to detect infinite loops in the code, we set up a counter    */
50   /* within the run loop.  A single stroke of interpretation is now        */
51   /* limited to a maximum number of opcodes defined below.                 */
52   /*                                                                       */
53 #define MAX_RUNNABLE_OPCODES  1000000L
54
55
56   /*************************************************************************/
57   /*                                                                       */
58   /* There are two kinds of implementations:                               */
59   /*                                                                       */
60   /* a. static implementation                                              */
61   /*                                                                       */
62   /*    The current execution context is a static variable, which fields   */
63   /*    are accessed directly by the interpreter during execution.  The    */
64   /*    context is named `cur'.                                            */
65   /*                                                                       */
66   /*    This version is non-reentrant, of course.                          */
67   /*                                                                       */
68   /* b. indirect implementation                                            */
69   /*                                                                       */
70   /*    The current execution context is passed to _each_ function as its  */
71   /*    first argument, and each field is thus accessed indirectly.        */
72   /*                                                                       */
73   /*    This version is fully re-entrant.                                  */
74   /*                                                                       */
75   /* The idea is that an indirect implementation may be slower to execute  */
76   /* on low-end processors that are used in some systems (like 386s or     */
77   /* even 486s).                                                           */
78   /*                                                                       */
79   /* As a consequence, the indirect implementation is now the default, as  */
80   /* its performance costs can be considered negligible in our context.    */
81   /* Note, however, that we kept the same source with macros because:      */
82   /*                                                                       */
83   /* - The code is kept very close in design to the Pascal code used for   */
84   /*   development.                                                        */
85   /*                                                                       */
86   /* - It's much more readable that way!                                   */
87   /*                                                                       */
88   /* - It's still open to experimentation and tuning.                      */
89   /*                                                                       */
90   /*************************************************************************/
91
92
93 #ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */
94
95 #define CUR  (*exc)                             /* see ttobjs.h */
96
97   /*************************************************************************/
98   /*                                                                       */
99   /* This macro is used whenever `exec' is unused in a function, to avoid  */
100   /* stupid warnings from pedantic compilers.                              */
101   /*                                                                       */
102 #define FT_UNUSED_EXEC  FT_UNUSED( exc )
103
104 #else                                           /* static implementation */
105
106 #define CUR  cur
107
108 #define FT_UNUSED_EXEC  int  __dummy = __dummy
109
110   static
111   TT_ExecContextRec  cur;   /* static exec. context variable */
112
113   /* apparently, we have a _lot_ of direct indexing when accessing  */
114   /* the static `cur', which makes the code bigger (due to all the  */
115   /* four bytes addresses).                                         */
116
117 #endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
118
119
120   /*************************************************************************/
121   /*                                                                       */
122   /* The instruction argument stack.                                       */
123   /*                                                                       */
124 #define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */
125
126
127   /*************************************************************************/
128   /*                                                                       */
129   /* This macro is used whenever `args' is unused in a function, to avoid  */
130   /* stupid warnings from pedantic compilers.                              */
131   /*                                                                       */
132 #define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
133
134
135 #define SUBPIXEL_HINTING                                                    \
136           ( ((TT_Driver)FT_FACE_DRIVER( CUR.face ))->interpreter_version == \
137             TT_INTERPRETER_VERSION_38 )
138
139
140   /*************************************************************************/
141   /*                                                                       */
142   /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
143   /* increase readability of the code.                                     */
144   /*                                                                       */
145   /*************************************************************************/
146
147
148 #define SKIP_Code() \
149           SkipCode( EXEC_ARG )
150
151 #define GET_ShortIns() \
152           GetShortIns( EXEC_ARG )
153
154 #define NORMalize( x, y, v ) \
155           Normalize( EXEC_ARG_ x, y, v )
156
157 #define SET_SuperRound( scale, flags ) \
158           SetSuperRound( EXEC_ARG_ scale, flags )
159
160 #define ROUND_None( d, c ) \
161           Round_None( EXEC_ARG_ d, c )
162
163 #define INS_Goto_CodeRange( range, ip ) \
164           Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
165
166 #define CUR_Func_move( z, p, d ) \
167           CUR.func_move( EXEC_ARG_ z, p, d )
168
169 #define CUR_Func_move_orig( z, p, d ) \
170           CUR.func_move_orig( EXEC_ARG_ z, p, d )
171
172 #define CUR_Func_round( d, c ) \
173           CUR.func_round( EXEC_ARG_ d, c )
174
175 #define CUR_Func_read_cvt( index ) \
176           CUR.func_read_cvt( EXEC_ARG_ index )
177
178 #define CUR_Func_write_cvt( index, val ) \
179           CUR.func_write_cvt( EXEC_ARG_ index, val )
180
181 #define CUR_Func_move_cvt( index, val ) \
182           CUR.func_move_cvt( EXEC_ARG_ index, val )
183
184 #define CURRENT_Ratio() \
185           Current_Ratio( EXEC_ARG )
186
187 #define CURRENT_Ppem() \
188           Current_Ppem( EXEC_ARG )
189
190 #define CUR_Ppem() \
191           Cur_PPEM( EXEC_ARG )
192
193 #define INS_SxVTL( a, b, c, d ) \
194           Ins_SxVTL( EXEC_ARG_ a, b, c, d )
195
196 #define COMPUTE_Funcs() \
197           Compute_Funcs( EXEC_ARG )
198
199 #define COMPUTE_Round( a ) \
200           Compute_Round( EXEC_ARG_ a )
201
202 #define COMPUTE_Point_Displacement( a, b, c, d ) \
203           Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
204
205 #define MOVE_Zp2_Point( a, b, c, t ) \
206           Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
207
208
209 #define CUR_Func_project( v1, v2 )  \
210           CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
211
212 #define CUR_Func_dualproj( v1, v2 )  \
213           CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
214
215 #define CUR_fast_project( v ) \
216           CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
217
218 #define CUR_fast_dualproj( v ) \
219           CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
220
221
222   /*************************************************************************/
223   /*                                                                       */
224   /* Instruction dispatch function, as used by the interpreter.            */
225   /*                                                                       */
226   typedef void  (*TInstruction_Function)( INS_ARG );
227
228
229   /*************************************************************************/
230   /*                                                                       */
231   /* Two simple bounds-checking macros.                                    */
232   /*                                                                       */
233 #define BOUNDS( x, n )   ( (FT_UInt)(x)  >= (FT_UInt)(n)  )
234 #define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
235
236   /*************************************************************************/
237   /*                                                                       */
238   /* This macro computes (a*2^14)/b and complements TT_MulFix14.           */
239   /*                                                                       */
240 #define TT_DivFix14( a, b ) \
241           FT_DivFix( a, (b) << 2 )
242
243
244 #undef  SUCCESS
245 #define SUCCESS  0
246
247 #undef  FAILURE
248 #define FAILURE  1
249
250 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
251 #define GUESS_VECTOR( V )                                         \
252   if ( CUR.face->unpatented_hinting )                             \
253   {                                                               \
254     CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
255     CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
256   }
257 #else
258 #define GUESS_VECTOR( V )
259 #endif
260
261   /*************************************************************************/
262   /*                                                                       */
263   /*                        CODERANGE FUNCTIONS                            */
264   /*                                                                       */
265   /*************************************************************************/
266
267
268   /*************************************************************************/
269   /*                                                                       */
270   /* <Function>                                                            */
271   /*    TT_Goto_CodeRange                                                  */
272   /*                                                                       */
273   /* <Description>                                                         */
274   /*    Switches to a new code range (updates the code related elements in */
275   /*    `exec', and `IP').                                                 */
276   /*                                                                       */
277   /* <Input>                                                               */
278   /*    range :: The new execution code range.                             */
279   /*                                                                       */
280   /*    IP    :: The new IP in the new code range.                         */
281   /*                                                                       */
282   /* <InOut>                                                               */
283   /*    exec  :: The target execution context.                             */
284   /*                                                                       */
285   /* <Return>                                                              */
286   /*    FreeType error code.  0 means success.                             */
287   /*                                                                       */
288   FT_LOCAL_DEF( FT_Error )
289   TT_Goto_CodeRange( TT_ExecContext  exec,
290                      FT_Int          range,
291                      FT_Long         IP )
292   {
293     TT_CodeRange*  coderange;
294
295
296     FT_ASSERT( range >= 1 && range <= 3 );
297
298     coderange = &exec->codeRangeTable[range - 1];
299
300     FT_ASSERT( coderange->base != NULL );
301
302     /* NOTE: Because the last instruction of a program may be a CALL */
303     /*       which will return to the first byte *after* the code    */
304     /*       range, we test for IP <= Size instead of IP < Size.     */
305     /*                                                               */
306     FT_ASSERT( (FT_ULong)IP <= coderange->size );
307
308     exec->code     = coderange->base;
309     exec->codeSize = coderange->size;
310     exec->IP       = IP;
311     exec->curRange = range;
312
313     return FT_Err_Ok;
314   }
315
316
317   /*************************************************************************/
318   /*                                                                       */
319   /* <Function>                                                            */
320   /*    TT_Set_CodeRange                                                   */
321   /*                                                                       */
322   /* <Description>                                                         */
323   /*    Sets a code range.                                                 */
324   /*                                                                       */
325   /* <Input>                                                               */
326   /*    range  :: The code range index.                                    */
327   /*                                                                       */
328   /*    base   :: The new code base.                                       */
329   /*                                                                       */
330   /*    length :: The range size in bytes.                                 */
331   /*                                                                       */
332   /* <InOut>                                                               */
333   /*    exec   :: The target execution context.                            */
334   /*                                                                       */
335   /* <Return>                                                              */
336   /*    FreeType error code.  0 means success.                             */
337   /*                                                                       */
338   FT_LOCAL_DEF( FT_Error )
339   TT_Set_CodeRange( TT_ExecContext  exec,
340                     FT_Int          range,
341                     void*           base,
342                     FT_Long         length )
343   {
344     FT_ASSERT( range >= 1 && range <= 3 );
345
346     exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
347     exec->codeRangeTable[range - 1].size = length;
348
349     return FT_Err_Ok;
350   }
351
352
353   /*************************************************************************/
354   /*                                                                       */
355   /* <Function>                                                            */
356   /*    TT_Clear_CodeRange                                                 */
357   /*                                                                       */
358   /* <Description>                                                         */
359   /*    Clears a code range.                                               */
360   /*                                                                       */
361   /* <Input>                                                               */
362   /*    range :: The code range index.                                     */
363   /*                                                                       */
364   /* <InOut>                                                               */
365   /*    exec  :: The target execution context.                             */
366   /*                                                                       */
367   /* <Return>                                                              */
368   /*    FreeType error code.  0 means success.                             */
369   /*                                                                       */
370   /* <Note>                                                                */
371   /*    Does not set the Error variable.                                   */
372   /*                                                                       */
373   FT_LOCAL_DEF( FT_Error )
374   TT_Clear_CodeRange( TT_ExecContext  exec,
375                       FT_Int          range )
376   {
377     FT_ASSERT( range >= 1 && range <= 3 );
378
379     exec->codeRangeTable[range - 1].base = NULL;
380     exec->codeRangeTable[range - 1].size = 0;
381
382     return FT_Err_Ok;
383   }
384
385
386   /*************************************************************************/
387   /*                                                                       */
388   /*                   EXECUTION CONTEXT ROUTINES                          */
389   /*                                                                       */
390   /*************************************************************************/
391
392
393   /*************************************************************************/
394   /*                                                                       */
395   /* <Function>                                                            */
396   /*    TT_Done_Context                                                    */
397   /*                                                                       */
398   /* <Description>                                                         */
399   /*    Destroys a given context.                                          */
400   /*                                                                       */
401   /* <Input>                                                               */
402   /*    exec   :: A handle to the target execution context.                */
403   /*                                                                       */
404   /*    memory :: A handle to the parent memory object.                    */
405   /*                                                                       */
406   /* <Return>                                                              */
407   /*    FreeType error code.  0 means success.                             */
408   /*                                                                       */
409   /* <Note>                                                                */
410   /*    Only the glyph loader and debugger should call this function.      */
411   /*                                                                       */
412   FT_LOCAL_DEF( FT_Error )
413   TT_Done_Context( TT_ExecContext  exec )
414   {
415     FT_Memory  memory = exec->memory;
416
417
418     /* points zone */
419     exec->maxPoints   = 0;
420     exec->maxContours = 0;
421
422     /* free stack */
423     FT_FREE( exec->stack );
424     exec->stackSize = 0;
425
426     /* free call stack */
427     FT_FREE( exec->callStack );
428     exec->callSize = 0;
429     exec->callTop  = 0;
430
431     /* free glyph code range */
432     FT_FREE( exec->glyphIns );
433     exec->glyphSize = 0;
434
435     exec->size = NULL;
436     exec->face = NULL;
437
438     FT_FREE( exec );
439
440     return FT_Err_Ok;
441   }
442
443
444   /*************************************************************************/
445   /*                                                                       */
446   /* <Function>                                                            */
447   /*    Init_Context                                                       */
448   /*                                                                       */
449   /* <Description>                                                         */
450   /*    Initializes a context object.                                      */
451   /*                                                                       */
452   /* <Input>                                                               */
453   /*    memory :: A handle to the parent memory object.                    */
454   /*                                                                       */
455   /* <InOut>                                                               */
456   /*    exec   :: A handle to the target execution context.                */
457   /*                                                                       */
458   /* <Return>                                                              */
459   /*    FreeType error code.  0 means success.                             */
460   /*                                                                       */
461   static FT_Error
462   Init_Context( TT_ExecContext  exec,
463                 FT_Memory       memory )
464   {
465     FT_Error  error;
466
467
468     FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
469
470     exec->memory   = memory;
471     exec->callSize = 32;
472
473     if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
474       goto Fail_Memory;
475
476     /* all values in the context are set to 0 already, but this is */
477     /* here as a remainder                                         */
478     exec->maxPoints   = 0;
479     exec->maxContours = 0;
480
481     exec->stackSize = 0;
482     exec->glyphSize = 0;
483
484     exec->stack     = NULL;
485     exec->glyphIns  = NULL;
486
487     exec->face = NULL;
488     exec->size = NULL;
489
490     return FT_Err_Ok;
491
492   Fail_Memory:
493     FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
494     TT_Done_Context( exec );
495
496     return error;
497  }
498
499
500   /*************************************************************************/
501   /*                                                                       */
502   /* <Function>                                                            */
503   /*    Update_Max                                                         */
504   /*                                                                       */
505   /* <Description>                                                         */
506   /*    Checks the size of a buffer and reallocates it if necessary.       */
507   /*                                                                       */
508   /* <Input>                                                               */
509   /*    memory     :: A handle to the parent memory object.                */
510   /*                                                                       */
511   /*    multiplier :: The size in bytes of each element in the buffer.     */
512   /*                                                                       */
513   /*    new_max    :: The new capacity (size) of the buffer.               */
514   /*                                                                       */
515   /* <InOut>                                                               */
516   /*    size       :: The address of the buffer's current size expressed   */
517   /*                  in elements.                                         */
518   /*                                                                       */
519   /*    buff       :: The address of the buffer base pointer.              */
520   /*                                                                       */
521   /* <Return>                                                              */
522   /*    FreeType error code.  0 means success.                             */
523   /*                                                                       */
524   FT_LOCAL_DEF( FT_Error )
525   Update_Max( FT_Memory  memory,
526               FT_ULong*  size,
527               FT_Long    multiplier,
528               void*      _pbuff,
529               FT_ULong   new_max )
530   {
531     FT_Error  error;
532     void**    pbuff = (void**)_pbuff;
533
534
535     if ( *size < new_max )
536     {
537       if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
538         return error;
539       *size = new_max;
540     }
541
542     return FT_Err_Ok;
543   }
544
545
546   /*************************************************************************/
547   /*                                                                       */
548   /* <Function>                                                            */
549   /*    TT_Load_Context                                                    */
550   /*                                                                       */
551   /* <Description>                                                         */
552   /*    Prepare an execution context for glyph hinting.                    */
553   /*                                                                       */
554   /* <Input>                                                               */
555   /*    face :: A handle to the source face object.                        */
556   /*                                                                       */
557   /*    size :: A handle to the source size object.                        */
558   /*                                                                       */
559   /* <InOut>                                                               */
560   /*    exec :: A handle to the target execution context.                  */
561   /*                                                                       */
562   /* <Return>                                                              */
563   /*    FreeType error code.  0 means success.                             */
564   /*                                                                       */
565   /* <Note>                                                                */
566   /*    Only the glyph loader and debugger should call this function.      */
567   /*                                                                       */
568   FT_LOCAL_DEF( FT_Error )
569   TT_Load_Context( TT_ExecContext  exec,
570                    TT_Face         face,
571                    TT_Size         size )
572   {
573     FT_Int          i;
574     FT_ULong        tmp;
575     TT_MaxProfile*  maxp;
576     FT_Error        error;
577
578
579     exec->face = face;
580     maxp       = &face->max_profile;
581     exec->size = size;
582
583     if ( size )
584     {
585       exec->numFDefs   = size->num_function_defs;
586       exec->maxFDefs   = size->max_function_defs;
587       exec->numIDefs   = size->num_instruction_defs;
588       exec->maxIDefs   = size->max_instruction_defs;
589       exec->FDefs      = size->function_defs;
590       exec->IDefs      = size->instruction_defs;
591       exec->tt_metrics = size->ttmetrics;
592       exec->metrics    = size->metrics;
593
594       exec->maxFunc    = size->max_func;
595       exec->maxIns     = size->max_ins;
596
597       for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
598         exec->codeRangeTable[i] = size->codeRangeTable[i];
599
600       /* set graphics state */
601       exec->GS = size->GS;
602
603       exec->cvtSize = size->cvt_size;
604       exec->cvt     = size->cvt;
605
606       exec->storeSize = size->storage_size;
607       exec->storage   = size->storage;
608
609       exec->twilight  = size->twilight;
610
611       /* In case of multi-threading it can happen that the old size object */
612       /* no longer exists, thus we must clear all glyph zone references.   */
613       ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
614       exec->zp1 = exec->zp0;
615       exec->zp2 = exec->zp0;
616     }
617
618     /* XXX: We reserve a little more elements on the stack to deal safely */
619     /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
620     tmp = exec->stackSize;
621     error = Update_Max( exec->memory,
622                         &tmp,
623                         sizeof ( FT_F26Dot6 ),
624                         (void*)&exec->stack,
625                         maxp->maxStackElements + 32 );
626     exec->stackSize = (FT_UInt)tmp;
627     if ( error )
628       return error;
629
630     tmp = exec->glyphSize;
631     error = Update_Max( exec->memory,
632                         &tmp,
633                         sizeof ( FT_Byte ),
634                         (void*)&exec->glyphIns,
635                         maxp->maxSizeOfInstructions );
636     exec->glyphSize = (FT_UShort)tmp;
637     if ( error )
638       return error;
639
640     exec->pts.n_points   = 0;
641     exec->pts.n_contours = 0;
642
643     exec->zp1 = exec->pts;
644     exec->zp2 = exec->pts;
645     exec->zp0 = exec->pts;
646
647     exec->instruction_trap = FALSE;
648
649     return FT_Err_Ok;
650   }
651
652
653   /*************************************************************************/
654   /*                                                                       */
655   /* <Function>                                                            */
656   /*    TT_Save_Context                                                    */
657   /*                                                                       */
658   /* <Description>                                                         */
659   /*    Saves the code ranges in a `size' object.                          */
660   /*                                                                       */
661   /* <Input>                                                               */
662   /*    exec :: A handle to the source execution context.                  */
663   /*                                                                       */
664   /* <InOut>                                                               */
665   /*    size :: A handle to the target size object.                        */
666   /*                                                                       */
667   /* <Return>                                                              */
668   /*    FreeType error code.  0 means success.                             */
669   /*                                                                       */
670   /* <Note>                                                                */
671   /*    Only the glyph loader and debugger should call this function.      */
672   /*                                                                       */
673   FT_LOCAL_DEF( FT_Error )
674   TT_Save_Context( TT_ExecContext  exec,
675                    TT_Size         size )
676   {
677     FT_Int  i;
678
679
680     /* XXX: Will probably disappear soon with all the code range */
681     /*      management, which is now rather obsolete.            */
682     /*                                                           */
683     size->num_function_defs    = exec->numFDefs;
684     size->num_instruction_defs = exec->numIDefs;
685
686     size->max_func = exec->maxFunc;
687     size->max_ins  = exec->maxIns;
688
689     for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
690       size->codeRangeTable[i] = exec->codeRangeTable[i];
691
692     return FT_Err_Ok;
693   }
694
695
696   /*************************************************************************/
697   /*                                                                       */
698   /* <Function>                                                            */
699   /*    TT_Run_Context                                                     */
700   /*                                                                       */
701   /* <Description>                                                         */
702   /*    Executes one or more instructions in the execution context.        */
703   /*                                                                       */
704   /* <Input>                                                               */
705   /*    debug :: A Boolean flag.  If set, the function sets some internal  */
706   /*             variables and returns immediately, otherwise TT_RunIns()  */
707   /*             is called.                                                */
708   /*                                                                       */
709   /*             This is commented out currently.                          */
710   /*                                                                       */
711   /* <Input>                                                               */
712   /*    exec  :: A handle to the target execution context.                 */
713   /*                                                                       */
714   /* <Return>                                                              */
715   /*    TrueType error code.  0 means success.                             */
716   /*                                                                       */
717   /* <Note>                                                                */
718   /*    Only the glyph loader and debugger should call this function.      */
719   /*                                                                       */
720   FT_LOCAL_DEF( FT_Error )
721   TT_Run_Context( TT_ExecContext  exec,
722                   FT_Bool         debug )
723   {
724     FT_Error  error;
725
726
727     if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
728            != FT_Err_Ok )
729       return error;
730
731     exec->zp0 = exec->pts;
732     exec->zp1 = exec->pts;
733     exec->zp2 = exec->pts;
734
735     exec->GS.gep0 = 1;
736     exec->GS.gep1 = 1;
737     exec->GS.gep2 = 1;
738
739     exec->GS.projVector.x = 0x4000;
740     exec->GS.projVector.y = 0x0000;
741
742     exec->GS.freeVector = exec->GS.projVector;
743     exec->GS.dualVector = exec->GS.projVector;
744
745 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
746     exec->GS.both_x_axis = TRUE;
747 #endif
748
749     exec->GS.round_state = 1;
750     exec->GS.loop        = 1;
751
752     /* some glyphs leave something on the stack. so we clean it */
753     /* before a new execution.                                  */
754     exec->top     = 0;
755     exec->callTop = 0;
756
757 #if 1
758     FT_UNUSED( debug );
759
760     return exec->face->interpreter( exec );
761 #else
762     if ( !debug )
763       return TT_RunIns( exec );
764     else
765       return FT_Err_Ok;
766 #endif
767   }
768
769
770   /* The default value for `scan_control' is documented as FALSE in the */
771   /* TrueType specification.  This is confusing since it implies a      */
772   /* Boolean value.  However, this is not the case, thus both the       */
773   /* default values of our `scan_type' and `scan_control' fields (which */
774   /* the documentation's `scan_control' variable is split into) are     */
775   /* zero.                                                              */
776
777   const TT_GraphicsState  tt_default_graphics_state =
778   {
779     0, 0, 0,
780     { 0x4000, 0 },
781     { 0x4000, 0 },
782     { 0x4000, 0 },
783
784 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
785     TRUE,
786 #endif
787
788     1, 64, 1,
789     TRUE, 68, 0, 0, 9, 3,
790     0, FALSE, 0, 1, 1, 1
791   };
792
793
794   /* documentation is in ttinterp.h */
795
796   FT_EXPORT_DEF( TT_ExecContext )
797   TT_New_Context( TT_Driver  driver )
798   {
799     TT_ExecContext  exec;
800     FT_Memory       memory;
801
802
803     memory = driver->root.root.memory;
804     exec   = driver->context;
805
806     if ( !driver->context )
807     {
808       FT_Error  error;
809
810
811       /* allocate object */
812       if ( FT_NEW( exec ) )
813         goto Fail;
814
815       /* initialize it; in case of error this deallocates `exec' too */
816       error = Init_Context( exec, memory );
817       if ( error )
818         goto Fail;
819
820       /* store it into the driver */
821       driver->context = exec;
822     }
823
824     return driver->context;
825
826   Fail:
827     return NULL;
828   }
829
830
831   /*************************************************************************/
832   /*                                                                       */
833   /* Before an opcode is executed, the interpreter verifies that there are */
834   /* enough arguments on the stack, with the help of the `Pop_Push_Count'  */
835   /* table.                                                                */
836   /*                                                                       */
837   /* For each opcode, the first column gives the number of arguments that  */
838   /* are popped from the stack; the second one gives the number of those   */
839   /* that are pushed in result.                                            */
840   /*                                                                       */
841   /* Opcodes which have a varying number of parameters in the data stream  */
842   /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
843   /* the `opcode_length' table, and the value in `Pop_Push_Count' is set   */
844   /* to zero.                                                              */
845   /*                                                                       */
846   /*************************************************************************/
847
848
849 #undef  PACK
850 #define PACK( x, y )  ( ( x << 4 ) | y )
851
852
853   static
854   const FT_Byte  Pop_Push_Count[256] =
855   {
856     /* opcodes are gathered in groups of 16 */
857     /* please keep the spaces as they are   */
858
859     /*  SVTCA  y  */  PACK( 0, 0 ),
860     /*  SVTCA  x  */  PACK( 0, 0 ),
861     /*  SPvTCA y  */  PACK( 0, 0 ),
862     /*  SPvTCA x  */  PACK( 0, 0 ),
863     /*  SFvTCA y  */  PACK( 0, 0 ),
864     /*  SFvTCA x  */  PACK( 0, 0 ),
865     /*  SPvTL //  */  PACK( 2, 0 ),
866     /*  SPvTL +   */  PACK( 2, 0 ),
867     /*  SFvTL //  */  PACK( 2, 0 ),
868     /*  SFvTL +   */  PACK( 2, 0 ),
869     /*  SPvFS     */  PACK( 2, 0 ),
870     /*  SFvFS     */  PACK( 2, 0 ),
871     /*  GPV       */  PACK( 0, 2 ),
872     /*  GFV       */  PACK( 0, 2 ),
873     /*  SFvTPv    */  PACK( 0, 0 ),
874     /*  ISECT     */  PACK( 5, 0 ),
875
876     /*  SRP0      */  PACK( 1, 0 ),
877     /*  SRP1      */  PACK( 1, 0 ),
878     /*  SRP2      */  PACK( 1, 0 ),
879     /*  SZP0      */  PACK( 1, 0 ),
880     /*  SZP1      */  PACK( 1, 0 ),
881     /*  SZP2      */  PACK( 1, 0 ),
882     /*  SZPS      */  PACK( 1, 0 ),
883     /*  SLOOP     */  PACK( 1, 0 ),
884     /*  RTG       */  PACK( 0, 0 ),
885     /*  RTHG      */  PACK( 0, 0 ),
886     /*  SMD       */  PACK( 1, 0 ),
887     /*  ELSE      */  PACK( 0, 0 ),
888     /*  JMPR      */  PACK( 1, 0 ),
889     /*  SCvTCi    */  PACK( 1, 0 ),
890     /*  SSwCi     */  PACK( 1, 0 ),
891     /*  SSW       */  PACK( 1, 0 ),
892
893     /*  DUP       */  PACK( 1, 2 ),
894     /*  POP       */  PACK( 1, 0 ),
895     /*  CLEAR     */  PACK( 0, 0 ),
896     /*  SWAP      */  PACK( 2, 2 ),
897     /*  DEPTH     */  PACK( 0, 1 ),
898     /*  CINDEX    */  PACK( 1, 1 ),
899     /*  MINDEX    */  PACK( 1, 0 ),
900     /*  AlignPTS  */  PACK( 2, 0 ),
901     /*  INS_$28   */  PACK( 0, 0 ),
902     /*  UTP       */  PACK( 1, 0 ),
903     /*  LOOPCALL  */  PACK( 2, 0 ),
904     /*  CALL      */  PACK( 1, 0 ),
905     /*  FDEF      */  PACK( 1, 0 ),
906     /*  ENDF      */  PACK( 0, 0 ),
907     /*  MDAP[0]   */  PACK( 1, 0 ),
908     /*  MDAP[1]   */  PACK( 1, 0 ),
909
910     /*  IUP[0]    */  PACK( 0, 0 ),
911     /*  IUP[1]    */  PACK( 0, 0 ),
912     /*  SHP[0]    */  PACK( 0, 0 ),
913     /*  SHP[1]    */  PACK( 0, 0 ),
914     /*  SHC[0]    */  PACK( 1, 0 ),
915     /*  SHC[1]    */  PACK( 1, 0 ),
916     /*  SHZ[0]    */  PACK( 1, 0 ),
917     /*  SHZ[1]    */  PACK( 1, 0 ),
918     /*  SHPIX     */  PACK( 1, 0 ),
919     /*  IP        */  PACK( 0, 0 ),
920     /*  MSIRP[0]  */  PACK( 2, 0 ),
921     /*  MSIRP[1]  */  PACK( 2, 0 ),
922     /*  AlignRP   */  PACK( 0, 0 ),
923     /*  RTDG      */  PACK( 0, 0 ),
924     /*  MIAP[0]   */  PACK( 2, 0 ),
925     /*  MIAP[1]   */  PACK( 2, 0 ),
926
927     /*  NPushB    */  PACK( 0, 0 ),
928     /*  NPushW    */  PACK( 0, 0 ),
929     /*  WS        */  PACK( 2, 0 ),
930     /*  RS        */  PACK( 1, 1 ),
931     /*  WCvtP     */  PACK( 2, 0 ),
932     /*  RCvt      */  PACK( 1, 1 ),
933     /*  GC[0]     */  PACK( 1, 1 ),
934     /*  GC[1]     */  PACK( 1, 1 ),
935     /*  SCFS      */  PACK( 2, 0 ),
936     /*  MD[0]     */  PACK( 2, 1 ),
937     /*  MD[1]     */  PACK( 2, 1 ),
938     /*  MPPEM     */  PACK( 0, 1 ),
939     /*  MPS       */  PACK( 0, 1 ),
940     /*  FlipON    */  PACK( 0, 0 ),
941     /*  FlipOFF   */  PACK( 0, 0 ),
942     /*  DEBUG     */  PACK( 1, 0 ),
943
944     /*  LT        */  PACK( 2, 1 ),
945     /*  LTEQ      */  PACK( 2, 1 ),
946     /*  GT        */  PACK( 2, 1 ),
947     /*  GTEQ      */  PACK( 2, 1 ),
948     /*  EQ        */  PACK( 2, 1 ),
949     /*  NEQ       */  PACK( 2, 1 ),
950     /*  ODD       */  PACK( 1, 1 ),
951     /*  EVEN      */  PACK( 1, 1 ),
952     /*  IF        */  PACK( 1, 0 ),
953     /*  EIF       */  PACK( 0, 0 ),
954     /*  AND       */  PACK( 2, 1 ),
955     /*  OR        */  PACK( 2, 1 ),
956     /*  NOT       */  PACK( 1, 1 ),
957     /*  DeltaP1   */  PACK( 1, 0 ),
958     /*  SDB       */  PACK( 1, 0 ),
959     /*  SDS       */  PACK( 1, 0 ),
960
961     /*  ADD       */  PACK( 2, 1 ),
962     /*  SUB       */  PACK( 2, 1 ),
963     /*  DIV       */  PACK( 2, 1 ),
964     /*  MUL       */  PACK( 2, 1 ),
965     /*  ABS       */  PACK( 1, 1 ),
966     /*  NEG       */  PACK( 1, 1 ),
967     /*  FLOOR     */  PACK( 1, 1 ),
968     /*  CEILING   */  PACK( 1, 1 ),
969     /*  ROUND[0]  */  PACK( 1, 1 ),
970     /*  ROUND[1]  */  PACK( 1, 1 ),
971     /*  ROUND[2]  */  PACK( 1, 1 ),
972     /*  ROUND[3]  */  PACK( 1, 1 ),
973     /*  NROUND[0] */  PACK( 1, 1 ),
974     /*  NROUND[1] */  PACK( 1, 1 ),
975     /*  NROUND[2] */  PACK( 1, 1 ),
976     /*  NROUND[3] */  PACK( 1, 1 ),
977
978     /*  WCvtF     */  PACK( 2, 0 ),
979     /*  DeltaP2   */  PACK( 1, 0 ),
980     /*  DeltaP3   */  PACK( 1, 0 ),
981     /*  DeltaCn[0] */ PACK( 1, 0 ),
982     /*  DeltaCn[1] */ PACK( 1, 0 ),
983     /*  DeltaCn[2] */ PACK( 1, 0 ),
984     /*  SROUND    */  PACK( 1, 0 ),
985     /*  S45Round  */  PACK( 1, 0 ),
986     /*  JROT      */  PACK( 2, 0 ),
987     /*  JROF      */  PACK( 2, 0 ),
988     /*  ROFF      */  PACK( 0, 0 ),
989     /*  INS_$7B   */  PACK( 0, 0 ),
990     /*  RUTG      */  PACK( 0, 0 ),
991     /*  RDTG      */  PACK( 0, 0 ),
992     /*  SANGW     */  PACK( 1, 0 ),
993     /*  AA        */  PACK( 1, 0 ),
994
995     /*  FlipPT    */  PACK( 0, 0 ),
996     /*  FlipRgON  */  PACK( 2, 0 ),
997     /*  FlipRgOFF */  PACK( 2, 0 ),
998     /*  INS_$83   */  PACK( 0, 0 ),
999     /*  INS_$84   */  PACK( 0, 0 ),
1000     /*  ScanCTRL  */  PACK( 1, 0 ),
1001     /*  SDPVTL[0] */  PACK( 2, 0 ),
1002     /*  SDPVTL[1] */  PACK( 2, 0 ),
1003     /*  GetINFO   */  PACK( 1, 1 ),
1004     /*  IDEF      */  PACK( 1, 0 ),
1005     /*  ROLL      */  PACK( 3, 3 ),
1006     /*  MAX       */  PACK( 2, 1 ),
1007     /*  MIN       */  PACK( 2, 1 ),
1008     /*  ScanTYPE  */  PACK( 1, 0 ),
1009     /*  InstCTRL  */  PACK( 2, 0 ),
1010     /*  INS_$8F   */  PACK( 0, 0 ),
1011
1012     /*  INS_$90  */   PACK( 0, 0 ),
1013     /*  INS_$91  */   PACK( 0, 0 ),
1014     /*  INS_$92  */   PACK( 0, 0 ),
1015     /*  INS_$93  */   PACK( 0, 0 ),
1016     /*  INS_$94  */   PACK( 0, 0 ),
1017     /*  INS_$95  */   PACK( 0, 0 ),
1018     /*  INS_$96  */   PACK( 0, 0 ),
1019     /*  INS_$97  */   PACK( 0, 0 ),
1020     /*  INS_$98  */   PACK( 0, 0 ),
1021     /*  INS_$99  */   PACK( 0, 0 ),
1022     /*  INS_$9A  */   PACK( 0, 0 ),
1023     /*  INS_$9B  */   PACK( 0, 0 ),
1024     /*  INS_$9C  */   PACK( 0, 0 ),
1025     /*  INS_$9D  */   PACK( 0, 0 ),
1026     /*  INS_$9E  */   PACK( 0, 0 ),
1027     /*  INS_$9F  */   PACK( 0, 0 ),
1028
1029     /*  INS_$A0  */   PACK( 0, 0 ),
1030     /*  INS_$A1  */   PACK( 0, 0 ),
1031     /*  INS_$A2  */   PACK( 0, 0 ),
1032     /*  INS_$A3  */   PACK( 0, 0 ),
1033     /*  INS_$A4  */   PACK( 0, 0 ),
1034     /*  INS_$A5  */   PACK( 0, 0 ),
1035     /*  INS_$A6  */   PACK( 0, 0 ),
1036     /*  INS_$A7  */   PACK( 0, 0 ),
1037     /*  INS_$A8  */   PACK( 0, 0 ),
1038     /*  INS_$A9  */   PACK( 0, 0 ),
1039     /*  INS_$AA  */   PACK( 0, 0 ),
1040     /*  INS_$AB  */   PACK( 0, 0 ),
1041     /*  INS_$AC  */   PACK( 0, 0 ),
1042     /*  INS_$AD  */   PACK( 0, 0 ),
1043     /*  INS_$AE  */   PACK( 0, 0 ),
1044     /*  INS_$AF  */   PACK( 0, 0 ),
1045
1046     /*  PushB[0]  */  PACK( 0, 1 ),
1047     /*  PushB[1]  */  PACK( 0, 2 ),
1048     /*  PushB[2]  */  PACK( 0, 3 ),
1049     /*  PushB[3]  */  PACK( 0, 4 ),
1050     /*  PushB[4]  */  PACK( 0, 5 ),
1051     /*  PushB[5]  */  PACK( 0, 6 ),
1052     /*  PushB[6]  */  PACK( 0, 7 ),
1053     /*  PushB[7]  */  PACK( 0, 8 ),
1054     /*  PushW[0]  */  PACK( 0, 1 ),
1055     /*  PushW[1]  */  PACK( 0, 2 ),
1056     /*  PushW[2]  */  PACK( 0, 3 ),
1057     /*  PushW[3]  */  PACK( 0, 4 ),
1058     /*  PushW[4]  */  PACK( 0, 5 ),
1059     /*  PushW[5]  */  PACK( 0, 6 ),
1060     /*  PushW[6]  */  PACK( 0, 7 ),
1061     /*  PushW[7]  */  PACK( 0, 8 ),
1062
1063     /*  MDRP[00]  */  PACK( 1, 0 ),
1064     /*  MDRP[01]  */  PACK( 1, 0 ),
1065     /*  MDRP[02]  */  PACK( 1, 0 ),
1066     /*  MDRP[03]  */  PACK( 1, 0 ),
1067     /*  MDRP[04]  */  PACK( 1, 0 ),
1068     /*  MDRP[05]  */  PACK( 1, 0 ),
1069     /*  MDRP[06]  */  PACK( 1, 0 ),
1070     /*  MDRP[07]  */  PACK( 1, 0 ),
1071     /*  MDRP[08]  */  PACK( 1, 0 ),
1072     /*  MDRP[09]  */  PACK( 1, 0 ),
1073     /*  MDRP[10]  */  PACK( 1, 0 ),
1074     /*  MDRP[11]  */  PACK( 1, 0 ),
1075     /*  MDRP[12]  */  PACK( 1, 0 ),
1076     /*  MDRP[13]  */  PACK( 1, 0 ),
1077     /*  MDRP[14]  */  PACK( 1, 0 ),
1078     /*  MDRP[15]  */  PACK( 1, 0 ),
1079
1080     /*  MDRP[16]  */  PACK( 1, 0 ),
1081     /*  MDRP[17]  */  PACK( 1, 0 ),
1082     /*  MDRP[18]  */  PACK( 1, 0 ),
1083     /*  MDRP[19]  */  PACK( 1, 0 ),
1084     /*  MDRP[20]  */  PACK( 1, 0 ),
1085     /*  MDRP[21]  */  PACK( 1, 0 ),
1086     /*  MDRP[22]  */  PACK( 1, 0 ),
1087     /*  MDRP[23]  */  PACK( 1, 0 ),
1088     /*  MDRP[24]  */  PACK( 1, 0 ),
1089     /*  MDRP[25]  */  PACK( 1, 0 ),
1090     /*  MDRP[26]  */  PACK( 1, 0 ),
1091     /*  MDRP[27]  */  PACK( 1, 0 ),
1092     /*  MDRP[28]  */  PACK( 1, 0 ),
1093     /*  MDRP[29]  */  PACK( 1, 0 ),
1094     /*  MDRP[30]  */  PACK( 1, 0 ),
1095     /*  MDRP[31]  */  PACK( 1, 0 ),
1096
1097     /*  MIRP[00]  */  PACK( 2, 0 ),
1098     /*  MIRP[01]  */  PACK( 2, 0 ),
1099     /*  MIRP[02]  */  PACK( 2, 0 ),
1100     /*  MIRP[03]  */  PACK( 2, 0 ),
1101     /*  MIRP[04]  */  PACK( 2, 0 ),
1102     /*  MIRP[05]  */  PACK( 2, 0 ),
1103     /*  MIRP[06]  */  PACK( 2, 0 ),
1104     /*  MIRP[07]  */  PACK( 2, 0 ),
1105     /*  MIRP[08]  */  PACK( 2, 0 ),
1106     /*  MIRP[09]  */  PACK( 2, 0 ),
1107     /*  MIRP[10]  */  PACK( 2, 0 ),
1108     /*  MIRP[11]  */  PACK( 2, 0 ),
1109     /*  MIRP[12]  */  PACK( 2, 0 ),
1110     /*  MIRP[13]  */  PACK( 2, 0 ),
1111     /*  MIRP[14]  */  PACK( 2, 0 ),
1112     /*  MIRP[15]  */  PACK( 2, 0 ),
1113
1114     /*  MIRP[16]  */  PACK( 2, 0 ),
1115     /*  MIRP[17]  */  PACK( 2, 0 ),
1116     /*  MIRP[18]  */  PACK( 2, 0 ),
1117     /*  MIRP[19]  */  PACK( 2, 0 ),
1118     /*  MIRP[20]  */  PACK( 2, 0 ),
1119     /*  MIRP[21]  */  PACK( 2, 0 ),
1120     /*  MIRP[22]  */  PACK( 2, 0 ),
1121     /*  MIRP[23]  */  PACK( 2, 0 ),
1122     /*  MIRP[24]  */  PACK( 2, 0 ),
1123     /*  MIRP[25]  */  PACK( 2, 0 ),
1124     /*  MIRP[26]  */  PACK( 2, 0 ),
1125     /*  MIRP[27]  */  PACK( 2, 0 ),
1126     /*  MIRP[28]  */  PACK( 2, 0 ),
1127     /*  MIRP[29]  */  PACK( 2, 0 ),
1128     /*  MIRP[30]  */  PACK( 2, 0 ),
1129     /*  MIRP[31]  */  PACK( 2, 0 )
1130   };
1131
1132
1133 #ifdef FT_DEBUG_LEVEL_TRACE
1134
1135   static
1136   const char*  const opcode_name[256] =
1137   {
1138     "SVTCA y",
1139     "SVTCA x",
1140     "SPvTCA y",
1141     "SPvTCA x",
1142     "SFvTCA y",
1143     "SFvTCA x",
1144     "SPvTL ||",
1145     "SPvTL +",
1146     "SFvTL ||",
1147     "SFvTL +",
1148     "SPvFS",
1149     "SFvFS",
1150     "GPV",
1151     "GFV",
1152     "SFvTPv",
1153     "ISECT",
1154
1155     "SRP0",
1156     "SRP1",
1157     "SRP2",
1158     "SZP0",
1159     "SZP1",
1160     "SZP2",
1161     "SZPS",
1162     "SLOOP",
1163     "RTG",
1164     "RTHG",
1165     "SMD",
1166     "ELSE",
1167     "JMPR",
1168     "SCvTCi",
1169     "SSwCi",
1170     "SSW",
1171
1172     "DUP",
1173     "POP",
1174     "CLEAR",
1175     "SWAP",
1176     "DEPTH",
1177     "CINDEX",
1178     "MINDEX",
1179     "AlignPTS",
1180     "INS_$28",
1181     "UTP",
1182     "LOOPCALL",
1183     "CALL",
1184     "FDEF",
1185     "ENDF",
1186     "MDAP[0]",
1187     "MDAP[1]",
1188
1189     "IUP[0]",
1190     "IUP[1]",
1191     "SHP[0]",
1192     "SHP[1]",
1193     "SHC[0]",
1194     "SHC[1]",
1195     "SHZ[0]",
1196     "SHZ[1]",
1197     "SHPIX",
1198     "IP",
1199     "MSIRP[0]",
1200     "MSIRP[1]",
1201     "AlignRP",
1202     "RTDG",
1203     "MIAP[0]",
1204     "MIAP[1]",
1205
1206     "NPushB",
1207     "NPushW",
1208     "WS",
1209     "RS",
1210     "WCvtP",
1211     "RCvt",
1212     "GC[0]",
1213     "GC[1]",
1214     "SCFS",
1215     "MD[0]",
1216     "MD[1]",
1217     "MPPEM",
1218     "MPS",
1219     "FlipON",
1220     "FlipOFF",
1221     "DEBUG",
1222
1223     "LT",
1224     "LTEQ",
1225     "GT",
1226     "GTEQ",
1227     "EQ",
1228     "NEQ",
1229     "ODD",
1230     "EVEN",
1231     "IF",
1232     "EIF",
1233     "AND",
1234     "OR",
1235     "NOT",
1236     "DeltaP1",
1237     "SDB",
1238     "SDS",
1239
1240     "ADD",
1241     "SUB",
1242     "DIV",
1243     "MUL",
1244     "ABS",
1245     "NEG",
1246     "FLOOR",
1247     "CEILING",
1248     "ROUND[0]",
1249     "ROUND[1]",
1250     "ROUND[2]",
1251     "ROUND[3]",
1252     "NROUND[0]",
1253     "NROUND[1]",
1254     "NROUND[2]",
1255     "NROUND[3]",
1256
1257     "WCvtF",
1258     "DeltaP2",
1259     "DeltaP3",
1260     "DeltaCn[0]",
1261     "DeltaCn[1]",
1262     "DeltaCn[2]",
1263     "SROUND",
1264     "S45Round",
1265     "JROT",
1266     "JROF",
1267     "ROFF",
1268     "INS_$7B",
1269     "RUTG",
1270     "RDTG",
1271     "SANGW",
1272     "AA",
1273
1274     "FlipPT",
1275     "FlipRgON",
1276     "FlipRgOFF",
1277     "INS_$83",
1278     "INS_$84",
1279     "ScanCTRL",
1280     "SDVPTL[0]",
1281     "SDVPTL[1]",
1282     "GetINFO",
1283     "IDEF",
1284     "ROLL",
1285     "MAX",
1286     "MIN",
1287     "ScanTYPE",
1288     "InstCTRL",
1289     "INS_$8F",
1290
1291     "INS_$90",
1292     "INS_$91",
1293     "INS_$92",
1294     "INS_$93",
1295     "INS_$94",
1296     "INS_$95",
1297     "INS_$96",
1298     "INS_$97",
1299     "INS_$98",
1300     "INS_$99",
1301     "INS_$9A",
1302     "INS_$9B",
1303     "INS_$9C",
1304     "INS_$9D",
1305     "INS_$9E",
1306     "INS_$9F",
1307
1308     "INS_$A0",
1309     "INS_$A1",
1310     "INS_$A2",
1311     "INS_$A3",
1312     "INS_$A4",
1313     "INS_$A5",
1314     "INS_$A6",
1315     "INS_$A7",
1316     "INS_$A8",
1317     "INS_$A9",
1318     "INS_$AA",
1319     "INS_$AB",
1320     "INS_$AC",
1321     "INS_$AD",
1322     "INS_$AE",
1323     "INS_$AF",
1324
1325     "PushB[0]",
1326     "PushB[1]",
1327     "PushB[2]",
1328     "PushB[3]",
1329     "PushB[4]",
1330     "PushB[5]",
1331     "PushB[6]",
1332     "PushB[7]",
1333     "PushW[0]",
1334     "PushW[1]",
1335     "PushW[2]",
1336     "PushW[3]",
1337     "PushW[4]",
1338     "PushW[5]",
1339     "PushW[6]",
1340     "PushW[7]",
1341
1342     "MDRP[00]",
1343     "MDRP[01]",
1344     "MDRP[02]",
1345     "MDRP[03]",
1346     "MDRP[04]",
1347     "MDRP[05]",
1348     "MDRP[06]",
1349     "MDRP[07]",
1350     "MDRP[08]",
1351     "MDRP[09]",
1352     "MDRP[10]",
1353     "MDRP[11]",
1354     "MDRP[12]",
1355     "MDRP[13]",
1356     "MDRP[14]",
1357     "MDRP[15]",
1358
1359     "MDRP[16]",
1360     "MDRP[17]",
1361     "MDRP[18]",
1362     "MDRP[19]",
1363     "MDRP[20]",
1364     "MDRP[21]",
1365     "MDRP[22]",
1366     "MDRP[23]",
1367     "MDRP[24]",
1368     "MDRP[25]",
1369     "MDRP[26]",
1370     "MDRP[27]",
1371     "MDRP[28]",
1372     "MDRP[29]",
1373     "MDRP[30]",
1374     "MDRP[31]",
1375
1376     "MIRP[00]",
1377     "MIRP[01]",
1378     "MIRP[02]",
1379     "MIRP[03]",
1380     "MIRP[04]",
1381     "MIRP[05]",
1382     "MIRP[06]",
1383     "MIRP[07]",
1384     "MIRP[08]",
1385     "MIRP[09]",
1386     "MIRP[10]",
1387     "MIRP[11]",
1388     "MIRP[12]",
1389     "MIRP[13]",
1390     "MIRP[14]",
1391     "MIRP[15]",
1392
1393     "MIRP[16]",
1394     "MIRP[17]",
1395     "MIRP[18]",
1396     "MIRP[19]",
1397     "MIRP[20]",
1398     "MIRP[21]",
1399     "MIRP[22]",
1400     "MIRP[23]",
1401     "MIRP[24]",
1402     "MIRP[25]",
1403     "MIRP[26]",
1404     "MIRP[27]",
1405     "MIRP[28]",
1406     "MIRP[29]",
1407     "MIRP[30]",
1408     "MIRP[31]"
1409   };
1410
1411 #endif /* FT_DEBUG_LEVEL_TRACE */
1412
1413
1414   static
1415   const FT_Char  opcode_length[256] =
1416   {
1417     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1418     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1419     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1420     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1421
1422    -1,-2, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1423     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1424     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1425     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1426
1427     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1428     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1429     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1430     2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,
1431
1432     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1433     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1434     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
1435     1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
1436   };
1437
1438 #undef PACK
1439
1440 #if 1
1441
1442   static FT_Int32
1443   TT_MulFix14( FT_Int32  a,
1444                FT_Int    b )
1445   {
1446     FT_Int32   sign;
1447     FT_UInt32  ah, al, mid, lo, hi;
1448
1449
1450     sign = a ^ b;
1451
1452     if ( a < 0 )
1453       a = -a;
1454     if ( b < 0 )
1455       b = -b;
1456
1457     ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
1458     al = (FT_UInt32)( a & 0xFFFFU );
1459
1460     lo    = al * b;
1461     mid   = ah * b;
1462     hi    = mid >> 16;
1463     mid   = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
1464     lo   += mid;
1465     if ( lo < mid )
1466       hi += 1;
1467
1468     mid = ( lo >> 14 ) | ( hi << 18 );
1469
1470     return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
1471   }
1472
1473 #else
1474
1475   /* compute (a*b)/2^14 with maximum accuracy and rounding */
1476   static FT_Int32
1477   TT_MulFix14( FT_Int32  a,
1478                FT_Int    b )
1479   {
1480     FT_Int32   m, s, hi;
1481     FT_UInt32  l, lo;
1482
1483
1484     /* compute ax*bx as 64-bit value */
1485     l  = (FT_UInt32)( ( a & 0xFFFFU ) * b );
1486     m  = ( a >> 16 ) * b;
1487
1488     lo = l + ( (FT_UInt32)m << 16 );
1489     hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
1490
1491     /* divide the result by 2^14 with rounding */
1492     s   = hi >> 31;
1493     l   = lo + (FT_UInt32)s;
1494     hi += s + ( l < lo );
1495     lo  = l;
1496
1497     l   = lo + 0x2000U;
1498     hi += l < lo;
1499
1500     return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
1501   }
1502 #endif
1503
1504
1505   /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
1506   static FT_Int32
1507   TT_DotFix14( FT_Int32  ax,
1508                FT_Int32  ay,
1509                FT_Int    bx,
1510                FT_Int    by )
1511   {
1512     FT_Int32   m, s, hi1, hi2, hi;
1513     FT_UInt32  l, lo1, lo2, lo;
1514
1515
1516     /* compute ax*bx as 64-bit value */
1517     l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
1518     m = ( ax >> 16 ) * bx;
1519
1520     lo1 = l + ( (FT_UInt32)m << 16 );
1521     hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
1522
1523     /* compute ay*by as 64-bit value */
1524     l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
1525     m = ( ay >> 16 ) * by;
1526
1527     lo2 = l + ( (FT_UInt32)m << 16 );
1528     hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
1529
1530     /* add them */
1531     lo = lo1 + lo2;
1532     hi = hi1 + hi2 + ( lo < lo1 );
1533
1534     /* divide the result by 2^14 with rounding */
1535     s   = hi >> 31;
1536     l   = lo + (FT_UInt32)s;
1537     hi += s + ( l < lo );
1538     lo  = l;
1539
1540     l   = lo + 0x2000U;
1541     hi += ( l < lo );
1542
1543     return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
1544   }
1545
1546
1547   /*************************************************************************/
1548   /*                                                                       */
1549   /* <Function>                                                            */
1550   /*    Current_Ratio                                                      */
1551   /*                                                                       */
1552   /* <Description>                                                         */
1553   /*    Returns the current aspect ratio scaling factor depending on the   */
1554   /*    projection vector's state and device resolutions.                  */
1555   /*                                                                       */
1556   /* <Return>                                                              */
1557   /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */
1558   /*                                                                       */
1559   static FT_Long
1560   Current_Ratio( EXEC_OP )
1561   {
1562     if ( !CUR.tt_metrics.ratio )
1563     {
1564 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1565       if ( CUR.face->unpatented_hinting )
1566       {
1567         if ( CUR.GS.both_x_axis )
1568           CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1569         else
1570           CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1571       }
1572       else
1573 #endif
1574       {
1575         if ( CUR.GS.projVector.y == 0 )
1576           CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1577
1578         else if ( CUR.GS.projVector.x == 0 )
1579           CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1580
1581         else
1582         {
1583           FT_F26Dot6  x, y;
1584
1585
1586           x = TT_MulFix14( CUR.tt_metrics.x_ratio,
1587                            CUR.GS.projVector.x );
1588           y = TT_MulFix14( CUR.tt_metrics.y_ratio,
1589                            CUR.GS.projVector.y );
1590           CUR.tt_metrics.ratio = FT_Hypot( x, y );
1591         }
1592       }
1593     }
1594     return CUR.tt_metrics.ratio;
1595   }
1596
1597
1598   static FT_Long
1599   Current_Ppem( EXEC_OP )
1600   {
1601     return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() );
1602   }
1603
1604
1605   /*************************************************************************/
1606   /*                                                                       */
1607   /* Functions related to the control value table (CVT).                   */
1608   /*                                                                       */
1609   /*************************************************************************/
1610
1611
1612   FT_CALLBACK_DEF( FT_F26Dot6 )
1613   Read_CVT( EXEC_OP_ FT_ULong  idx )
1614   {
1615     return CUR.cvt[idx];
1616   }
1617
1618
1619   FT_CALLBACK_DEF( FT_F26Dot6 )
1620   Read_CVT_Stretched( EXEC_OP_ FT_ULong  idx )
1621   {
1622     return FT_MulFix( CUR.cvt[idx], CURRENT_Ratio() );
1623   }
1624
1625
1626   FT_CALLBACK_DEF( void )
1627   Write_CVT( EXEC_OP_ FT_ULong    idx,
1628                       FT_F26Dot6  value )
1629   {
1630     CUR.cvt[idx] = value;
1631   }
1632
1633
1634   FT_CALLBACK_DEF( void )
1635   Write_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
1636                                 FT_F26Dot6  value )
1637   {
1638     CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
1639   }
1640
1641
1642   FT_CALLBACK_DEF( void )
1643   Move_CVT( EXEC_OP_ FT_ULong    idx,
1644                      FT_F26Dot6  value )
1645   {
1646     CUR.cvt[idx] += value;
1647   }
1648
1649
1650   FT_CALLBACK_DEF( void )
1651   Move_CVT_Stretched( EXEC_OP_ FT_ULong    idx,
1652                                FT_F26Dot6  value )
1653   {
1654     CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
1655   }
1656
1657
1658   /*************************************************************************/
1659   /*                                                                       */
1660   /* <Function>                                                            */
1661   /*    GetShortIns                                                        */
1662   /*                                                                       */
1663   /* <Description>                                                         */
1664   /*    Returns a short integer taken from the instruction stream at       */
1665   /*    address IP.                                                        */
1666   /*                                                                       */
1667   /* <Return>                                                              */
1668   /*    Short read at code[IP].                                            */
1669   /*                                                                       */
1670   /* <Note>                                                                */
1671   /*    This one could become a macro.                                     */
1672   /*                                                                       */
1673   static FT_Short
1674   GetShortIns( EXEC_OP )
1675   {
1676     /* Reading a byte stream so there is no endianess (DaveP) */
1677     CUR.IP += 2;
1678     return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
1679                          CUR.code[CUR.IP - 1]      );
1680   }
1681
1682
1683   /*************************************************************************/
1684   /*                                                                       */
1685   /* <Function>                                                            */
1686   /*    Ins_Goto_CodeRange                                                 */
1687   /*                                                                       */
1688   /* <Description>                                                         */
1689   /*    Goes to a certain code range in the instruction stream.            */
1690   /*                                                                       */
1691   /* <Input>                                                               */
1692   /*    aRange :: The index of the code range.                             */
1693   /*                                                                       */
1694   /*    aIP    :: The new IP address in the code range.                    */
1695   /*                                                                       */
1696   /* <Return>                                                              */
1697   /*    SUCCESS or FAILURE.                                                */
1698   /*                                                                       */
1699   static FT_Bool
1700   Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,
1701                                FT_ULong  aIP )
1702   {
1703     TT_CodeRange*  range;
1704
1705
1706     if ( aRange < 1 || aRange > 3 )
1707     {
1708       CUR.error = FT_THROW( Bad_Argument );
1709       return FAILURE;
1710     }
1711
1712     range = &CUR.codeRangeTable[aRange - 1];
1713
1714     if ( range->base == NULL )     /* invalid coderange */
1715     {
1716       CUR.error = FT_THROW( Invalid_CodeRange );
1717       return FAILURE;
1718     }
1719
1720     /* NOTE: Because the last instruction of a program may be a CALL */
1721     /*       which will return to the first byte *after* the code    */
1722     /*       range, we test for aIP <= Size, instead of aIP < Size.  */
1723
1724     if ( aIP > range->size )
1725     {
1726       CUR.error = FT_THROW( Code_Overflow );
1727       return FAILURE;
1728     }
1729
1730     CUR.code     = range->base;
1731     CUR.codeSize = range->size;
1732     CUR.IP       = aIP;
1733     CUR.curRange = aRange;
1734
1735     return SUCCESS;
1736   }
1737
1738
1739   /*************************************************************************/
1740   /*                                                                       */
1741   /* <Function>                                                            */
1742   /*    Direct_Move                                                        */
1743   /*                                                                       */
1744   /* <Description>                                                         */
1745   /*    Moves a point by a given distance along the freedom vector.  The   */
1746   /*    point will be `touched'.                                           */
1747   /*                                                                       */
1748   /* <Input>                                                               */
1749   /*    point    :: The index of the point to move.                        */
1750   /*                                                                       */
1751   /*    distance :: The distance to apply.                                 */
1752   /*                                                                       */
1753   /* <InOut>                                                               */
1754   /*    zone     :: The affected glyph zone.                               */
1755   /*                                                                       */
1756   static void
1757   Direct_Move( EXEC_OP_ TT_GlyphZone  zone,
1758                         FT_UShort     point,
1759                         FT_F26Dot6    distance )
1760   {
1761     FT_F26Dot6  v;
1762
1763
1764 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1765     FT_ASSERT( !CUR.face->unpatented_hinting );
1766 #endif
1767
1768     v = CUR.GS.freeVector.x;
1769
1770     if ( v != 0 )
1771     {
1772 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1773       if ( !SUBPIXEL_HINTING                                     ||
1774            ( !CUR.ignore_x_mode                                ||
1775              ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
1776 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
1777         zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
1778
1779       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1780     }
1781
1782     v = CUR.GS.freeVector.y;
1783
1784     if ( v != 0 )
1785     {
1786       zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
1787
1788       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
1789     }
1790   }
1791
1792
1793   /*************************************************************************/
1794   /*                                                                       */
1795   /* <Function>                                                            */
1796   /*    Direct_Move_Orig                                                   */
1797   /*                                                                       */
1798   /* <Description>                                                         */
1799   /*    Moves the *original* position of a point by a given distance along */
1800   /*    the freedom vector.  Obviously, the point will not be `touched'.   */
1801   /*                                                                       */
1802   /* <Input>                                                               */
1803   /*    point    :: The index of the point to move.                        */
1804   /*                                                                       */
1805   /*    distance :: The distance to apply.                                 */
1806   /*                                                                       */
1807   /* <InOut>                                                               */
1808   /*    zone     :: The affected glyph zone.                               */
1809   /*                                                                       */
1810   static void
1811   Direct_Move_Orig( EXEC_OP_ TT_GlyphZone  zone,
1812                              FT_UShort     point,
1813                              FT_F26Dot6    distance )
1814   {
1815     FT_F26Dot6  v;
1816
1817
1818 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1819     FT_ASSERT( !CUR.face->unpatented_hinting );
1820 #endif
1821
1822     v = CUR.GS.freeVector.x;
1823
1824     if ( v != 0 )
1825       zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
1826
1827     v = CUR.GS.freeVector.y;
1828
1829     if ( v != 0 )
1830       zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
1831   }
1832
1833
1834   /*************************************************************************/
1835   /*                                                                       */
1836   /* Special versions of Direct_Move()                                     */
1837   /*                                                                       */
1838   /*   The following versions are used whenever both vectors are both      */
1839   /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1840   /*                                                                       */
1841   /*************************************************************************/
1842
1843
1844   static void
1845   Direct_Move_X( EXEC_OP_ TT_GlyphZone  zone,
1846                           FT_UShort     point,
1847                           FT_F26Dot6    distance )
1848   {
1849     FT_UNUSED_EXEC;
1850
1851 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1852     if ( !SUBPIXEL_HINTING  ||
1853          !CUR.ignore_x_mode )
1854 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
1855       zone->cur[point].x += distance;
1856
1857     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
1858   }
1859
1860
1861   static void
1862   Direct_Move_Y( EXEC_OP_ TT_GlyphZone  zone,
1863                           FT_UShort     point,
1864                           FT_F26Dot6    distance )
1865   {
1866     FT_UNUSED_EXEC;
1867
1868     zone->cur[point].y += distance;
1869     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;
1870   }
1871
1872
1873   /*************************************************************************/
1874   /*                                                                       */
1875   /* Special versions of Direct_Move_Orig()                                */
1876   /*                                                                       */
1877   /*   The following versions are used whenever both vectors are both      */
1878   /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1879   /*                                                                       */
1880   /*************************************************************************/
1881
1882
1883   static void
1884   Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone  zone,
1885                                FT_UShort     point,
1886                                FT_F26Dot6    distance )
1887   {
1888     FT_UNUSED_EXEC;
1889
1890     zone->org[point].x += distance;
1891   }
1892
1893
1894   static void
1895   Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone  zone,
1896                                FT_UShort     point,
1897                                FT_F26Dot6    distance )
1898   {
1899     FT_UNUSED_EXEC;
1900
1901     zone->org[point].y += distance;
1902   }
1903
1904
1905   /*************************************************************************/
1906   /*                                                                       */
1907   /* <Function>                                                            */
1908   /*    Round_None                                                         */
1909   /*                                                                       */
1910   /* <Description>                                                         */
1911   /*    Does not round, but adds engine compensation.                      */
1912   /*                                                                       */
1913   /* <Input>                                                               */
1914   /*    distance     :: The distance (not) to round.                       */
1915   /*                                                                       */
1916   /*    compensation :: The engine compensation.                           */
1917   /*                                                                       */
1918   /* <Return>                                                              */
1919   /*    The compensated distance.                                          */
1920   /*                                                                       */
1921   /* <Note>                                                                */
1922   /*    The TrueType specification says very few about the relationship    */
1923   /*    between rounding and engine compensation.  However, it seems from  */
1924   /*    the description of super round that we should add the compensation */
1925   /*    before rounding.                                                   */
1926   /*                                                                       */
1927   static FT_F26Dot6
1928   Round_None( EXEC_OP_ FT_F26Dot6  distance,
1929                        FT_F26Dot6  compensation )
1930   {
1931     FT_F26Dot6  val;
1932
1933     FT_UNUSED_EXEC;
1934
1935
1936     if ( distance >= 0 )
1937     {
1938       val = distance + compensation;
1939       if ( distance && val < 0 )
1940         val = 0;
1941     }
1942     else
1943     {
1944       val = distance - compensation;
1945       if ( val > 0 )
1946         val = 0;
1947     }
1948     return val;
1949   }
1950
1951
1952   /*************************************************************************/
1953   /*                                                                       */
1954   /* <Function>                                                            */
1955   /*    Round_To_Grid                                                      */
1956   /*                                                                       */
1957   /* <Description>                                                         */
1958   /*    Rounds value to grid after adding engine compensation.             */
1959   /*                                                                       */
1960   /* <Input>                                                               */
1961   /*    distance     :: The distance to round.                             */
1962   /*                                                                       */
1963   /*    compensation :: The engine compensation.                           */
1964   /*                                                                       */
1965   /* <Return>                                                              */
1966   /*    Rounded distance.                                                  */
1967   /*                                                                       */
1968   static FT_F26Dot6
1969   Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
1970                           FT_F26Dot6  compensation )
1971   {
1972     FT_F26Dot6  val;
1973
1974     FT_UNUSED_EXEC;
1975
1976
1977     if ( distance >= 0 )
1978     {
1979       val = distance + compensation + 32;
1980       if ( distance && val > 0 )
1981         val &= ~63;
1982       else
1983         val = 0;
1984     }
1985     else
1986     {
1987       val = -FT_PIX_ROUND( compensation - distance );
1988       if ( val > 0 )
1989         val = 0;
1990     }
1991
1992     return  val;
1993   }
1994
1995
1996   /*************************************************************************/
1997   /*                                                                       */
1998   /* <Function>                                                            */
1999   /*    Round_To_Half_Grid                                                 */
2000   /*                                                                       */
2001   /* <Description>                                                         */
2002   /*    Rounds value to half grid after adding engine compensation.        */
2003   /*                                                                       */
2004   /* <Input>                                                               */
2005   /*    distance     :: The distance to round.                             */
2006   /*                                                                       */
2007   /*    compensation :: The engine compensation.                           */
2008   /*                                                                       */
2009   /* <Return>                                                              */
2010   /*    Rounded distance.                                                  */
2011   /*                                                                       */
2012   static FT_F26Dot6
2013   Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,
2014                                FT_F26Dot6  compensation )
2015   {
2016     FT_F26Dot6  val;
2017
2018     FT_UNUSED_EXEC;
2019
2020
2021     if ( distance >= 0 )
2022     {
2023       val = FT_PIX_FLOOR( distance + compensation ) + 32;
2024       if ( distance && val < 0 )
2025         val = 0;
2026     }
2027     else
2028     {
2029       val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
2030       if ( val > 0 )
2031         val = 0;
2032     }
2033
2034     return val;
2035   }
2036
2037
2038   /*************************************************************************/
2039   /*                                                                       */
2040   /* <Function>                                                            */
2041   /*    Round_Down_To_Grid                                                 */
2042   /*                                                                       */
2043   /* <Description>                                                         */
2044   /*    Rounds value down to grid after adding engine compensation.        */
2045   /*                                                                       */
2046   /* <Input>                                                               */
2047   /*    distance     :: The distance to round.                             */
2048   /*                                                                       */
2049   /*    compensation :: The engine compensation.                           */
2050   /*                                                                       */
2051   /* <Return>                                                              */
2052   /*    Rounded distance.                                                  */
2053   /*                                                                       */
2054   static FT_F26Dot6
2055   Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
2056                                FT_F26Dot6  compensation )
2057   {
2058     FT_F26Dot6  val;
2059
2060     FT_UNUSED_EXEC;
2061
2062
2063     if ( distance >= 0 )
2064     {
2065       val = distance + compensation;
2066       if ( distance && val > 0 )
2067         val &= ~63;
2068       else
2069         val = 0;
2070     }
2071     else
2072     {
2073       val = -( ( compensation - distance ) & -64 );
2074       if ( val > 0 )
2075         val = 0;
2076     }
2077
2078     return val;
2079   }
2080
2081
2082   /*************************************************************************/
2083   /*                                                                       */
2084   /* <Function>                                                            */
2085   /*    Round_Up_To_Grid                                                   */
2086   /*                                                                       */
2087   /* <Description>                                                         */
2088   /*    Rounds value up to grid after adding engine compensation.          */
2089   /*                                                                       */
2090   /* <Input>                                                               */
2091   /*    distance     :: The distance to round.                             */
2092   /*                                                                       */
2093   /*    compensation :: The engine compensation.                           */
2094   /*                                                                       */
2095   /* <Return>                                                              */
2096   /*    Rounded distance.                                                  */
2097   /*                                                                       */
2098   static FT_F26Dot6
2099   Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
2100                              FT_F26Dot6  compensation )
2101   {
2102     FT_F26Dot6  val;
2103
2104     FT_UNUSED_EXEC;
2105
2106
2107     if ( distance >= 0 )
2108     {
2109       val = distance + compensation + 63;
2110       if ( distance && val > 0 )
2111         val &= ~63;
2112       else
2113         val = 0;
2114     }
2115     else
2116     {
2117       val = -FT_PIX_CEIL( compensation - distance );
2118       if ( val > 0 )
2119         val = 0;
2120     }
2121
2122     return val;
2123   }
2124
2125
2126   /*************************************************************************/
2127   /*                                                                       */
2128   /* <Function>                                                            */
2129   /*    Round_To_Double_Grid                                               */
2130   /*                                                                       */
2131   /* <Description>                                                         */
2132   /*    Rounds value to double grid after adding engine compensation.      */
2133   /*                                                                       */
2134   /* <Input>                                                               */
2135   /*    distance     :: The distance to round.                             */
2136   /*                                                                       */
2137   /*    compensation :: The engine compensation.                           */
2138   /*                                                                       */
2139   /* <Return>                                                              */
2140   /*    Rounded distance.                                                  */
2141   /*                                                                       */
2142   static FT_F26Dot6
2143   Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,
2144                                  FT_F26Dot6  compensation )
2145   {
2146     FT_F26Dot6 val;
2147
2148     FT_UNUSED_EXEC;
2149
2150
2151     if ( distance >= 0 )
2152     {
2153       val = distance + compensation + 16;
2154       if ( distance && val > 0 )
2155         val &= ~31;
2156       else
2157         val = 0;
2158     }
2159     else
2160     {
2161       val = -FT_PAD_ROUND( compensation - distance, 32 );
2162       if ( val > 0 )
2163         val = 0;
2164     }
2165
2166     return val;
2167   }
2168
2169
2170   /*************************************************************************/
2171   /*                                                                       */
2172   /* <Function>                                                            */
2173   /*    Round_Super                                                        */
2174   /*                                                                       */
2175   /* <Description>                                                         */
2176   /*    Super-rounds value to grid after adding engine compensation.       */
2177   /*                                                                       */
2178   /* <Input>                                                               */
2179   /*    distance     :: The distance to round.                             */
2180   /*                                                                       */
2181   /*    compensation :: The engine compensation.                           */
2182   /*                                                                       */
2183   /* <Return>                                                              */
2184   /*    Rounded distance.                                                  */
2185   /*                                                                       */
2186   /* <Note>                                                                */
2187   /*    The TrueType specification says very few about the relationship    */
2188   /*    between rounding and engine compensation.  However, it seems from  */
2189   /*    the description of super round that we should add the compensation */
2190   /*    before rounding.                                                   */
2191   /*                                                                       */
2192   static FT_F26Dot6
2193   Round_Super( EXEC_OP_ FT_F26Dot6  distance,
2194                         FT_F26Dot6  compensation )
2195   {
2196     FT_F26Dot6  val;
2197
2198
2199     if ( distance >= 0 )
2200     {
2201       val = ( distance - CUR.phase + CUR.threshold + compensation ) &
2202               -CUR.period;
2203       if ( distance && val < 0 )
2204         val = 0;
2205       val += CUR.phase;
2206     }
2207     else
2208     {
2209       val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
2210                -CUR.period );
2211       if ( val > 0 )
2212         val = 0;
2213       val -= CUR.phase;
2214     }
2215
2216     return val;
2217   }
2218
2219
2220   /*************************************************************************/
2221   /*                                                                       */
2222   /* <Function>                                                            */
2223   /*    Round_Super_45                                                     */
2224   /*                                                                       */
2225   /* <Description>                                                         */
2226   /*    Super-rounds value to grid after adding engine compensation.       */
2227   /*                                                                       */
2228   /* <Input>                                                               */
2229   /*    distance     :: The distance to round.                             */
2230   /*                                                                       */
2231   /*    compensation :: The engine compensation.                           */
2232   /*                                                                       */
2233   /* <Return>                                                              */
2234   /*    Rounded distance.                                                  */
2235   /*                                                                       */
2236   /* <Note>                                                                */
2237   /*    There is a separate function for Round_Super_45() as we may need   */
2238   /*    greater precision.                                                 */
2239   /*                                                                       */
2240   static FT_F26Dot6
2241   Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,
2242                            FT_F26Dot6  compensation )
2243   {
2244     FT_F26Dot6  val;
2245
2246
2247     if ( distance >= 0 )
2248     {
2249       val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
2250                 CUR.period ) * CUR.period;
2251       if ( distance && val < 0 )
2252         val = 0;
2253       val += CUR.phase;
2254     }
2255     else
2256     {
2257       val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
2258                    CUR.period ) * CUR.period );
2259       if ( val > 0 )
2260         val = 0;
2261       val -= CUR.phase;
2262     }
2263
2264     return val;
2265   }
2266
2267
2268   /*************************************************************************/
2269   /*                                                                       */
2270   /* <Function>                                                            */
2271   /*    Compute_Round                                                      */
2272   /*                                                                       */
2273   /* <Description>                                                         */
2274   /*    Sets the rounding mode.                                            */
2275   /*                                                                       */
2276   /* <Input>                                                               */
2277   /*    round_mode :: The rounding mode to be used.                        */
2278   /*                                                                       */
2279   static void
2280   Compute_Round( EXEC_OP_ FT_Byte  round_mode )
2281   {
2282     switch ( round_mode )
2283     {
2284     case TT_Round_Off:
2285       CUR.func_round = (TT_Round_Func)Round_None;
2286       break;
2287
2288     case TT_Round_To_Grid:
2289       CUR.func_round = (TT_Round_Func)Round_To_Grid;
2290       break;
2291
2292     case TT_Round_Up_To_Grid:
2293       CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
2294       break;
2295
2296     case TT_Round_Down_To_Grid:
2297       CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
2298       break;
2299
2300     case TT_Round_To_Half_Grid:
2301       CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
2302       break;
2303
2304     case TT_Round_To_Double_Grid:
2305       CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
2306       break;
2307
2308     case TT_Round_Super:
2309       CUR.func_round = (TT_Round_Func)Round_Super;
2310       break;
2311
2312     case TT_Round_Super_45:
2313       CUR.func_round = (TT_Round_Func)Round_Super_45;
2314       break;
2315     }
2316   }
2317
2318
2319   /*************************************************************************/
2320   /*                                                                       */
2321   /* <Function>                                                            */
2322   /*    SetSuperRound                                                      */
2323   /*                                                                       */
2324   /* <Description>                                                         */
2325   /*    Sets Super Round parameters.                                       */
2326   /*                                                                       */
2327   /* <Input>                                                               */
2328   /*    GridPeriod :: The grid period.                                     */
2329   /*                                                                       */
2330   /*    selector   :: The SROUND opcode.                                   */
2331   /*                                                                       */
2332   static void
2333   SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
2334                           FT_Long     selector )
2335   {
2336     switch ( (FT_Int)( selector & 0xC0 ) )
2337     {
2338       case 0:
2339         CUR.period = GridPeriod / 2;
2340         break;
2341
2342       case 0x40:
2343         CUR.period = GridPeriod;
2344         break;
2345
2346       case 0x80:
2347         CUR.period = GridPeriod * 2;
2348         break;
2349
2350       /* This opcode is reserved, but... */
2351
2352       case 0xC0:
2353         CUR.period = GridPeriod;
2354         break;
2355     }
2356
2357     switch ( (FT_Int)( selector & 0x30 ) )
2358     {
2359     case 0:
2360       CUR.phase = 0;
2361       break;
2362
2363     case 0x10:
2364       CUR.phase = CUR.period / 4;
2365       break;
2366
2367     case 0x20:
2368       CUR.phase = CUR.period / 2;
2369       break;
2370
2371     case 0x30:
2372       CUR.phase = CUR.period * 3 / 4;
2373       break;
2374     }
2375
2376     if ( ( selector & 0x0F ) == 0 )
2377       CUR.threshold = CUR.period - 1;
2378     else
2379       CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
2380
2381     CUR.period    /= 256;
2382     CUR.phase     /= 256;
2383     CUR.threshold /= 256;
2384   }
2385
2386
2387   /*************************************************************************/
2388   /*                                                                       */
2389   /* <Function>                                                            */
2390   /*    Project                                                            */
2391   /*                                                                       */
2392   /* <Description>                                                         */
2393   /*    Computes the projection of vector given by (v2-v1) along the       */
2394   /*    current projection vector.                                         */
2395   /*                                                                       */
2396   /* <Input>                                                               */
2397   /*    v1 :: First input vector.                                          */
2398   /*    v2 :: Second input vector.                                         */
2399   /*                                                                       */
2400   /* <Return>                                                              */
2401   /*    The distance in F26dot6 format.                                    */
2402   /*                                                                       */
2403   static FT_F26Dot6
2404   Project( EXEC_OP_ FT_Pos  dx,
2405                     FT_Pos  dy )
2406   {
2407 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
2408     FT_ASSERT( !CUR.face->unpatented_hinting );
2409 #endif
2410
2411     return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
2412                         CUR.GS.projVector.x,
2413                         CUR.GS.projVector.y );
2414   }
2415
2416
2417   /*************************************************************************/
2418   /*                                                                       */
2419   /* <Function>                                                            */
2420   /*    Dual_Project                                                       */
2421   /*                                                                       */
2422   /* <Description>                                                         */
2423   /*    Computes the projection of the vector given by (v2-v1) along the   */
2424   /*    current dual vector.                                               */
2425   /*                                                                       */
2426   /* <Input>                                                               */
2427   /*    v1 :: First input vector.                                          */
2428   /*    v2 :: Second input vector.                                         */
2429   /*                                                                       */
2430   /* <Return>                                                              */
2431   /*    The distance in F26dot6 format.                                    */
2432   /*                                                                       */
2433   static FT_F26Dot6
2434   Dual_Project( EXEC_OP_ FT_Pos  dx,
2435                          FT_Pos  dy )
2436   {
2437     return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
2438                         CUR.GS.dualVector.x,
2439                         CUR.GS.dualVector.y );
2440   }
2441
2442
2443   /*************************************************************************/
2444   /*                                                                       */
2445   /* <Function>                                                            */
2446   /*    Project_x                                                          */
2447   /*                                                                       */
2448   /* <Description>                                                         */
2449   /*    Computes the projection of the vector given by (v2-v1) along the   */
2450   /*    horizontal axis.                                                   */
2451   /*                                                                       */
2452   /* <Input>                                                               */
2453   /*    v1 :: First input vector.                                          */
2454   /*    v2 :: Second input vector.                                         */
2455   /*                                                                       */
2456   /* <Return>                                                              */
2457   /*    The distance in F26dot6 format.                                    */
2458   /*                                                                       */
2459   static FT_F26Dot6
2460   Project_x( EXEC_OP_ FT_Pos  dx,
2461                       FT_Pos  dy )
2462   {
2463     FT_UNUSED_EXEC;
2464     FT_UNUSED( dy );
2465
2466     return dx;
2467   }
2468
2469
2470   /*************************************************************************/
2471   /*                                                                       */
2472   /* <Function>                                                            */
2473   /*    Project_y                                                          */
2474   /*                                                                       */
2475   /* <Description>                                                         */
2476   /*    Computes the projection of the vector given by (v2-v1) along the   */
2477   /*    vertical axis.                                                     */
2478   /*                                                                       */
2479   /* <Input>                                                               */
2480   /*    v1 :: First input vector.                                          */
2481   /*    v2 :: Second input vector.                                         */
2482   /*                                                                       */
2483   /* <Return>                                                              */
2484   /*    The distance in F26dot6 format.                                    */
2485   /*                                                                       */
2486   static FT_F26Dot6
2487   Project_y( EXEC_OP_ FT_Pos  dx,
2488                       FT_Pos  dy )
2489   {
2490     FT_UNUSED_EXEC;
2491     FT_UNUSED( dx );
2492
2493     return dy;
2494   }
2495
2496
2497   /*************************************************************************/
2498   /*                                                                       */
2499   /* <Function>                                                            */
2500   /*    Compute_Funcs                                                      */
2501   /*                                                                       */
2502   /* <Description>                                                         */
2503   /*    Computes the projection and movement function pointers according   */
2504   /*    to the current graphics state.                                     */
2505   /*                                                                       */
2506   static void
2507   Compute_Funcs( EXEC_OP )
2508   {
2509 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
2510     if ( CUR.face->unpatented_hinting )
2511     {
2512       /* If both vectors point rightwards along the x axis, set             */
2513       /* `both-x-axis' true, otherwise set it false.  The x values only     */
2514       /* need be tested because the vector has been normalised to a unit    */
2515       /* vector of length 0x4000 = unity.                                   */
2516       CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
2517                                       CUR.GS.freeVector.x == 0x4000 );
2518
2519       /* Throw away projection and freedom vector information */
2520       /* because the patents don't allow them to be stored.   */
2521       /* The relevant US Patents are 5155805 and 5325479.     */
2522       CUR.GS.projVector.x = 0;
2523       CUR.GS.projVector.y = 0;
2524       CUR.GS.freeVector.x = 0;
2525       CUR.GS.freeVector.y = 0;
2526
2527       if ( CUR.GS.both_x_axis )
2528       {
2529         CUR.func_project   = Project_x;
2530         CUR.func_move      = Direct_Move_X;
2531         CUR.func_move_orig = Direct_Move_Orig_X;
2532       }
2533       else
2534       {
2535         CUR.func_project   = Project_y;
2536         CUR.func_move      = Direct_Move_Y;
2537         CUR.func_move_orig = Direct_Move_Orig_Y;
2538       }
2539
2540       if ( CUR.GS.dualVector.x == 0x4000 )
2541         CUR.func_dualproj = Project_x;
2542       else if ( CUR.GS.dualVector.y == 0x4000 )
2543         CUR.func_dualproj = Project_y;
2544       else
2545         CUR.func_dualproj = Dual_Project;
2546
2547       /* Force recalculation of cached aspect ratio */
2548       CUR.tt_metrics.ratio = 0;
2549
2550       return;
2551     }
2552 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
2553
2554     if ( CUR.GS.freeVector.x == 0x4000 )
2555       CUR.F_dot_P = CUR.GS.projVector.x;
2556     else if ( CUR.GS.freeVector.y == 0x4000 )
2557       CUR.F_dot_P = CUR.GS.projVector.y;
2558     else
2559       CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x +
2560                       (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >>
2561                     14;
2562
2563     if ( CUR.GS.projVector.x == 0x4000 )
2564       CUR.func_project = (TT_Project_Func)Project_x;
2565     else if ( CUR.GS.projVector.y == 0x4000 )
2566       CUR.func_project = (TT_Project_Func)Project_y;
2567     else
2568       CUR.func_project = (TT_Project_Func)Project;
2569
2570     if ( CUR.GS.dualVector.x == 0x4000 )
2571       CUR.func_dualproj = (TT_Project_Func)Project_x;
2572     else if ( CUR.GS.dualVector.y == 0x4000 )
2573       CUR.func_dualproj = (TT_Project_Func)Project_y;
2574     else
2575       CUR.func_dualproj = (TT_Project_Func)Dual_Project;
2576
2577     CUR.func_move      = (TT_Move_Func)Direct_Move;
2578     CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
2579
2580     if ( CUR.F_dot_P == 0x4000L )
2581     {
2582       if ( CUR.GS.freeVector.x == 0x4000 )
2583       {
2584         CUR.func_move      = (TT_Move_Func)Direct_Move_X;
2585         CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
2586       }
2587       else if ( CUR.GS.freeVector.y == 0x4000 )
2588       {
2589         CUR.func_move      = (TT_Move_Func)Direct_Move_Y;
2590         CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
2591       }
2592     }
2593
2594     /* at small sizes, F_dot_P can become too small, resulting   */
2595     /* in overflows and `spikes' in a number of glyphs like `w'. */
2596
2597     if ( FT_ABS( CUR.F_dot_P ) < 0x400L )
2598       CUR.F_dot_P = 0x4000L;
2599
2600     /* Disable cached aspect ratio */
2601     CUR.tt_metrics.ratio = 0;
2602   }
2603
2604
2605   /*************************************************************************/
2606   /*                                                                       */
2607   /* <Function>                                                            */
2608   /*    Normalize                                                          */
2609   /*                                                                       */
2610   /* <Description>                                                         */
2611   /*    Norms a vector.                                                    */
2612   /*                                                                       */
2613   /* <Input>                                                               */
2614   /*    Vx :: The horizontal input vector coordinate.                      */
2615   /*    Vy :: The vertical input vector coordinate.                        */
2616   /*                                                                       */
2617   /* <Output>                                                              */
2618   /*    R  :: The normed unit vector.                                      */
2619   /*                                                                       */
2620   /* <Return>                                                              */
2621   /*    Returns FAILURE if a vector parameter is zero.                     */
2622   /*                                                                       */
2623   /* <Note>                                                                */
2624   /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
2625   /*    R is undefined.                                                    */
2626   /*                                                                       */
2627   static FT_Bool
2628   Normalize( EXEC_OP_ FT_F26Dot6      Vx,
2629                       FT_F26Dot6      Vy,
2630                       FT_UnitVector*  R )
2631   {
2632     FT_F26Dot6  W;
2633
2634     FT_UNUSED_EXEC;
2635
2636
2637     if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
2638     {
2639       if ( Vx == 0 && Vy == 0 )
2640       {
2641         /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
2642         /*      to normalize the vector (0,0).  Return immediately. */
2643         return SUCCESS;
2644       }
2645
2646       Vx *= 0x4000;
2647       Vy *= 0x4000;
2648     }
2649
2650     W = FT_Hypot( Vx, Vy );
2651
2652     R->x = (FT_F2Dot14)TT_DivFix14( Vx, W );
2653     R->y = (FT_F2Dot14)TT_DivFix14( Vy, W );
2654
2655     return SUCCESS;
2656   }
2657
2658
2659   /*************************************************************************/
2660   /*                                                                       */
2661   /* Here we start with the implementation of the various opcodes.         */
2662   /*                                                                       */
2663   /*************************************************************************/
2664
2665
2666   static FT_Bool
2667   Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,
2668                       FT_UShort       aIdx2,
2669                       FT_Int          aOpc,
2670                       FT_UnitVector*  Vec )
2671   {
2672     FT_Long     A, B, C;
2673     FT_Vector*  p1;
2674     FT_Vector*  p2;
2675
2676
2677     if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
2678          BOUNDS( aIdx2, CUR.zp1.n_points ) )
2679     {
2680       if ( CUR.pedantic_hinting )
2681         CUR.error = FT_THROW( Invalid_Reference );
2682       return FAILURE;
2683     }
2684
2685     p1 = CUR.zp1.cur + aIdx2;
2686     p2 = CUR.zp2.cur + aIdx1;
2687
2688     A = p1->x - p2->x;
2689     B = p1->y - p2->y;
2690
2691     /* If p1 == p2, SPVTL and SFVTL behave the same as */
2692     /* SPVTCA[X] and SFVTCA[X], respectively.          */
2693     /*                                                 */
2694     /* Confirmed by Greg Hitchcock.                    */
2695
2696     if ( A == 0 && B == 0 )
2697     {
2698       A    = 0x4000;
2699       aOpc = 0;
2700     }
2701
2702     if ( ( aOpc & 1 ) != 0 )
2703     {
2704       C =  B;   /* counter clockwise rotation */
2705       B =  A;
2706       A = -C;
2707     }
2708
2709     NORMalize( A, B, Vec );
2710
2711     return SUCCESS;
2712   }
2713
2714
2715   /* When not using the big switch statements, the interpreter uses a */
2716   /* call table defined later below in this source.  Each opcode must */
2717   /* thus have a corresponding function, even trivial ones.           */
2718   /*                                                                  */
2719   /* They are all defined there.                                      */
2720
2721 #define DO_SVTCA                            \
2722   {                                         \
2723     FT_Short  A, B;                         \
2724                                             \
2725                                             \
2726     A = (FT_Short)( CUR.opcode & 1 ) << 14; \
2727     B = A ^ (FT_Short)0x4000;               \
2728                                             \
2729     CUR.GS.freeVector.x = A;                \
2730     CUR.GS.projVector.x = A;                \</