zenilib: zenilib/jni/external/freetype2/src/truetype/ttinterp.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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 /* */
279 FT_LOCAL_DEF( FT_Error )
280 TT_Goto_CodeRange( TT_ExecContext exec,
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 /* */
329 FT_LOCAL_DEF( FT_Error )
330 TT_Set_CodeRange( TT_ExecContext exec,
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 /* */
364 FT_LOCAL_DEF( FT_Error )
365 TT_Clear_CodeRange( TT_ExecContext exec,
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 /* */
403 FT_LOCAL_DEF( FT_Error )
404 TT_Done_Context( TT_ExecContext exec )
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 /* */
515 FT_LOCAL_DEF( FT_Error )
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 /* */
559 FT_LOCAL_DEF( FT_Error )
560 TT_Load_Context( TT_ExecContext exec,
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 /* */
664 FT_LOCAL_DEF( FT_Error )
665 TT_Save_Context( TT_ExecContext exec,
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 /* */
711 FT_LOCAL_DEF( FT_Error )
712 TT_Run_Context( TT_ExecContext exec,
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
768 const TT_GraphicsState tt_default_graphics_state =
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
787 FT_EXPORT_DEF( TT_ExecContext )
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
1693 FT_CALLBACK_DEF( FT_F26Dot6 )
1694 Read_CVT( EXEC_OP_ FT_ULong idx )
1695 {
1696 return CUR.cvt[idx];
1697 }
1698
1699
1700 FT_CALLBACK_DEF( FT_F26Dot6 )
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 {
1784 TT_CodeRange* range;
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,
1840 FT_F26Dot6 distance )
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
2383 case TT_Round_To_Double_Grid:
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;
4593 TT_DefRecord* limit;
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 */
4737 TT_DefRecord* limit;
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 */
4814 TT_DefRecord* limit;
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;
4871 TT_DefRecord* limit;
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;
5946 FT_F26Dot6 distance;
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;
6031 FT_F26Dot6 distance,
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;
6355 FT_F26Dot6 distance;
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;
6491 FT_F26Dot6 distance;
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
7507 FT_EXPORT_DEF( FT_Error )
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 */
EXEC_ARG_
#define EXEC_ARG_
Definition: ttinterp.h:33
tt_default_graphics_state
const TT_GraphicsState tt_default_graphics_state
TT_GlyphZoneRec_::n_points
FT_UShort n_points
Definition: tttypes.h:1470
FT_PIX_CEIL
#define FT_PIX_CEIL(x)
Definition: ftobjs.h:82
FT_Error
int FT_Error
Definition: fttypes.h:296
FT_DivFix
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:536
FT_UnitVector_
Definition: fttypes.h:350
val
GLuint const GLfloat * val
Definition: glew.h:2715
FT_Long
signed long FT_Long
Definition: fttypes.h:238
TT_CodeRange_::size
FT_ULong size
Definition: ttobjs.h:163
s
GLdouble s
Definition: glew.h:1376
v1
GLfloat GLfloat v1
Definition: glew.h:1838
FT_ULong
unsigned long FT_ULong
Definition: fttypes.h:249
TT_ExecContextRec_::glyphSize
FT_UInt glyphSize
Definition: ttinterp.h:157
TT_GlyphZoneRec_::org
FT_Vector * org
Definition: tttypes.h:1473
FT_Pos
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:59
void
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
FT_UInt16
unsigned short FT_UInt16
Definition: ftconfig.h:176
TT_Round_Func
FT_F26Dot6(* TT_Round_Func)(EXEC_OP_ FT_F26Dot6 distance, FT_F26Dot6 compensation)
Definition: ttinterp.h:70
NULL
#define NULL
Definition: ftobjs.h:61
FT_Int
signed int FT_Int
Definition: fttypes.h:216
start
GLuint start
Definition: glew.h:1239
TT_Load_Context
TT_Load_Context(TT_ExecContext exec, TT_Face face, TT_Size size)
TT_Round_To_Half_Grid
#define TT_Round_To_Half_Grid
Definition: ttinterp.h:51
TT_CodeRange_
Definition: ttobjs.h:160
FT_ABS
#define FT_ABS(a)
Definition: ftobjs.h:73
TT_ExecContextRec_::memory
FT_Memory memory
Definition: ttinterp.h:119
FT_CURVE_TAG_TOUCH_BOTH
#define FT_CURVE_TAG_TOUCH_BOTH
Definition: ftimage.h:525
k
int32_t k
Definition: e_log.c:102
TT_Round_Up_To_Grid
#define TT_Round_Up_To_Grid
Definition: ttinterp.h:54
TT_CallRec_::Caller_Range
FT_Int Caller_Range
Definition: ttinterp.h:101
TT_DefRecord_::active
FT_Bool active
Definition: ttobjs.h:180
n
GLclampd n
Definition: glew.h:7287
TT_Round_Off
#define TT_Round_Off
Definition: ttinterp.h:50
cordic.hi
int hi
Definition: cordic.py:54
x
EGLSurface EGLint x
Definition: eglext.h:293
TT_DefRecord_::opc
FT_UInt opc
Definition: ttobjs.h:179
FT_Char
signed char FT_Char
Definition: fttypes.h:139
TT_ExecContextRec_::stack
FT_Long * stack
Definition: ttinterp.h:128
ft_memset
#define ft_memset
Definition: ftstdlib.h:83
FT_F2Dot14
signed short FT_F2Dot14
Definition: fttypes.h:260
cordic.lo
tuple lo
Definition: cordic.py:53
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
TT_CallRec_::Cur_Restart
FT_Long Cur_Restart
Definition: ttinterp.h:104
TT_Driver
typedefFT_BEGIN_HEADER struct TT_DriverRec_ * TT_Driver
Definition: ttobjs.h:39
d
return Display return Display Bool Bool int d
Definition: SDL_x11sym.h:30
S1
static double S1
Definition: k_sin.c:55
if
if(!yyg->yy_init)
Definition: glslang_lex.cpp:1037
SUCCESS
#define SUCCESS
Definition: ftraster.c:277
TT_New_Context
TT_New_Context(TT_Driver driver)
TT_ExecContextRec_::tt_metrics
TT_Size_Metrics tt_metrics
Definition: ttinterp.h:140
FT_Bool
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:104
FT_CURVE_TAG_TOUCH_X
#define FT_CURVE_TAG_TOUCH_X
Definition: ftimage.h:522
TT_Round_Super_45
#define TT_Round_Super_45
Definition: ttinterp.h:57
TT_Goto_CodeRange
TT_Goto_CodeRange(TT_ExecContext exec, FT_Int range, FT_Long IP)
FT_TRACE1
#define FT_TRACE1(varformat)
Definition: ftdebug.h:158
FT_UnitVector_::x
FT_F2Dot14 x
Definition: fttypes.h:352
FT_ERROR
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
TT_Clear_CodeRange
TT_Clear_CodeRange(TT_ExecContext exec, FT_Int range)
TT_Round_Down_To_Grid
#define TT_Round_Down_To_Grid
Definition: ttinterp.h:55
FT_Byte
unsigned char FT_Byte
Definition: fttypes.h:150
FT_ASSERT
#define FT_ASSERT(condition)
Definition: ftdebug.h:204
TT_ExecContextRec_
Definition: ttinterp.h:115
TT_GlyphZoneRec_::cur
FT_Vector * cur
Definition: tttypes.h:1474
range
GLenum GLint * range
Definition: glew.h:3391
TT_ExecContextRec_::maxContours
FT_Short maxContours
Definition: ttinterp.h:176
TT_CodeRange_::base
FT_Byte * base
Definition: ttobjs.h:162
TT_Run_Context
TT_Run_Context(TT_ExecContext exec, FT_Bool debug)
TT_CallRec_::Cur_End
FT_Long Cur_End
Definition: ttinterp.h:105
FT_PIX_FLOOR
#define FT_PIX_FLOOR(x)
Definition: ftobjs.h:80
TT_MaxProfile_
Definition: tttables.h:528
TT_Move_Func
void(* TT_Move_Func)(EXEC_OP_ TT_GlyphZone zone, FT_UShort point, FT_F26Dot6 distance)
Definition: ttinterp.h:75
TT_DefRecord_::start
FT_Long start
Definition: ttobjs.h:177
FT_FREE
#define FT_FREE(ptr)
Definition: ftmemory.h:286
TT_Size_Metrics_::ratio
FT_Long ratio
Definition: ttobjs.h:271
TT_Round_To_Grid
#define TT_Round_To_Grid
Definition: ttinterp.h:52
TT_CallRec_::Caller_IP
FT_Long Caller_IP
Definition: ttinterp.h:102
sign
int32_t sign
Definition: e_sqrt.c:107
FT_LOCAL_DEF
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:467
Update_Max
Update_Max(FT_Memory memory, FT_ULong *size, FT_Long multiplier, void *_pbuff, FT_ULong new_max)
v
const GLdouble * v
Definition: glew.h:1377
ttinterp.h
idx
FT_UInt idx
Definition: cffcmap.c:125
for
for(;;)
Definition: glslang_tab.cpp:4773
TT_DefRecord_::range
FT_Int range
Definition: ttobjs.h:176
length
GLsizei GLsizei * length
Definition: gl2ext.h:792
FT_PAD_ROUND
#define FT_PAD_ROUND(x, n)
Definition: ftobjs.h:77
FT_MulDiv
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:358
TT_GlyphZoneRec_
Definition: tttypes.h:1465
FAILURE
#define FAILURE
Definition: ftraster.c:281
error
FT_Error error
Definition: cffdrivr.c:407
FT_ARRAY_MOVE
#define FT_ARRAY_MOVE(dest, source, count)
Definition: ftmemory.h:219
TT_Round_To_Double_Grid
#define TT_Round_To_Double_Grid
Definition: ttinterp.h:53
FT_Vector_::x
FT_Pos x
Definition: ftimage.h:77
FT_CURVE_TAG_TOUCH_Y
#define FT_CURVE_TAG_TOUCH_Y
Definition: ftimage.h:523
TT_ExecContextRec_::error
FT_Error error
Definition: ttinterp.h:123
count
GLint GLsizei count
Definition: gl2ext.h:1011
face
GLenum face
Definition: gl2ext.h:1490
p
GLfloat GLfloat p
Definition: glew.h:14938
TT_CallRec_
Definition: ttinterp.h:99
TT_MaxProfile_::maxStackElements
FT_UShort maxStackElements
Definition: tttables.h:541
FT_Vector_::y
FT_Pos y
Definition: ftimage.h:78
distance
GLsizei GLsizei GLfloat distance
Definition: glew.h:12423
TT_CallRec_::Cur_Count
FT_Long Cur_Count
Definition: ttinterp.h:103
TT_GraphicsState_
Definition: ttobjs.h:76
by
GLbyte by
Definition: SDL_opengl.h:8286
tterrors.h
TT_MaxProfile_::maxSizeOfInstructions
FT_UShort maxSizeOfInstructions
Definition: tttables.h:542
limit
GLint limit
Definition: glew.h:11829
FT_TRACE7
#define FT_TRACE7(varformat)
Definition: ftdebug.h:164
TT_Project_Func
FT_F26Dot6(* TT_Project_Func)(EXEC_OP_ FT_Pos dx, FT_Pos dy)
Definition: ttinterp.h:81
FT_Vector_
Definition: ftimage.h:75
TT_Save_Context
TT_Save_Context(TT_ExecContext exec, TT_Size ins)
vec
FT_Vector * vec
Definition: ftbbox.c:579
FT_CALLBACK_DEF
#define FT_CALLBACK_DEF(x)
Definition: ftconfig.h:554
I
#define I(x, y, z)
Definition: SDL_test_md5.c:76
FALSE
#define FALSE
Definition: ftobjs.h:57
scale
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:12632
FT_Short
signed short FT_Short
Definition: fttypes.h:194
FT_Memory
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
FT_BOOL
#define FT_BOOL(x)
Definition: fttypes.h:581
TT_SizeRec_
Definition: ttobjs.h:288
sizeof
sizeof(FT_AutofitterRec)
FT_NEW_ARRAY
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:290
y
EGLSurface EGLint EGLint y
Definition: eglext.h:293
FT_F26Dot6
signed long FT_F26Dot6
Definition: fttypes.h:272
FT_UnitVector_::y
FT_F2Dot14 y
Definition: fttypes.h:353
l
GLdouble l
Definition: glew.h:8383
TT_Round_Super
#define TT_Round_Super
Definition: ttinterp.h:56
TT_ExecContextRec_::maxPoints
FT_UShort maxPoints
Definition: ttinterp.h:175
value
EGLSurface EGLint void ** value
Definition: eglext.h:301
ft2build.h
TT_ExecContextRec_::callSize
FT_Int callSize
Definition: ttinterp.h:171
FT_Fixed
signed long FT_Fixed
Definition: fttypes.h:284
FT_REALLOC
#define FT_REALLOC(ptr, cursz, newsz)
Definition: ftmemory.h:263
FT_EXPORT_DEF
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:511
FT_UInt
unsigned int FT_UInt
Definition: fttypes.h:227
TT_ExecContextRec_::size
TT_Size size
Definition: ttinterp.h:118
mask
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
Definition: gl2ext.h:961
EXEC_OP
#define EXEC_OP
Definition: ttinterp.h:32
TT_Done_Context
TT_Done_Context(TT_ExecContext exec)
b
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
tt_coderange_glyph
Definition: ttobjs.h:155
F
#define F(x, y, z)
Definition: SDL_test_md5.c:73
FT_Vector_Length
FT_Vector_Length(FT_Vector *vec)
Definition: fttrigon.c:455
FT_CURVE_TAG_ON
#define FT_CURVE_TAG_ON
Definition: ftimage.h:516
TT_DefRecord_
Definition: ttobjs.h:174
R
R
Definition: e_log.c:153
FT_NEW
#define FT_NEW(ptr)
Definition: ftmemory.h:288
i
int i
Definition: pngrutil.c:1377
TT_ExecContextRec_::glyphIns
FT_Byte * glyphIns
Definition: ttinterp.h:158
while
while(1)
Definition: glslang_lex.cpp:1063
S2
static double S2
Definition: k_sin.c:56
FT_UShort
unsigned short FT_UShort
Definition: fttypes.h:205
TT_FaceRec_
Definition: tttypes.h:1258
m
#define m(i, j)
FT_UNUSED
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
TRUE
#define TRUE
Definition: ftobjs.h:53
TT_ExecContextRec_::callStack
TT_CallStack callStack
Definition: ttinterp.h:173
TT_ExecContextRec_::face
TT_Face face
Definition: ttinterp.h:117
TT_Set_CodeRange
TT_Set_CodeRange(TT_ExecContext exec, FT_Int range, void *base, FT_Long length)
TT_ExecContextRec_::stackSize
FT_UInt stackSize
Definition: ttinterp.h:127
TT_DefRecord_::end
FT_Long end
Definition: ttobjs.h:178
FT_PIX_ROUND
#define FT_PIX_ROUND(x)
Definition: ftobjs.h:81
v2
GLfloat GLfloat GLfloat v2
Definition: glew.h:1842
EXEC_OP_
#define EXEC_OP_
Definition: ttinterp.h:31
TT_MAX_CODE_RANGES
#define TT_MAX_CODE_RANGES
Definition: ttobjs.h:140
size
GLsizei size
Definition: gl2ext.h:1467
TT_RunIns
TT_RunIns(TT_ExecContext exec)