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