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