Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: core/src/fxge/fx_freetype/fxft2.5.01/src/truetype/ttinterp.c

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

Powered by Google App Engine
This is Rietveld 408576698