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