OLD | NEW |
| (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 */ | |
OLD | NEW |