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