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