Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: src/truetype/ttinterp.c

Issue 89753003: Update freetype to latest version of ASOP. (Closed) Base URL: https://chromium.googlesource.com/chromium/src/third_party/freetype.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/truetype/ttinterp.h ('k') | src/truetype/ttobjs.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /***************************************************************************/ 1 /***************************************************************************/
2 /* */ 2 /* */
3 /* ttinterp.c */ 3 /* ttinterp.c */
4 /* */ 4 /* */
5 /* TrueType bytecode interpreter (body). */ 5 /* TrueType bytecode interpreter (body). */
6 /* */ 6 /* */
7 /* Copyright 1996-2012 */ 7 /* Copyright 1996-2013 */
8 /* by David Turner, Robert Wilhelm, and Werner Lemberg. */ 8 /* by David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */ 9 /* */
10 /* This file is part of the FreeType project, and may only be used, */ 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 */ 11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */ 13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */ 14 /* understand and accept it fully. */
15 /* */ 15 /* */
16 /***************************************************************************/ 16 /***************************************************************************/
17 17
18 18
19 /* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */ 19 /* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */
20 /* issues; many thanks! */ 20 /* issues; many thanks! */
21 21
22 22
23 #include <ft2build.h> 23 #include <ft2build.h>
24 #include FT_INTERNAL_DEBUG_H 24 #include FT_INTERNAL_DEBUG_H
25 #include FT_INTERNAL_CALC_H 25 #include FT_INTERNAL_CALC_H
26 #include FT_TRIGONOMETRY_H 26 #include FT_TRIGONOMETRY_H
27 #include FT_SYSTEM_H 27 #include FT_SYSTEM_H
28 #include FT_TRUETYPE_DRIVER_H
28 29
29 #include "ttinterp.h" 30 #include "ttinterp.h"
30
31 #include "tterrors.h" 31 #include "tterrors.h"
32 #include "ttsubpix.h"
32 33
33 34
34 #ifdef TT_USE_BYTECODE_INTERPRETER 35 #ifdef TT_USE_BYTECODE_INTERPRETER
35 36
36 37
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 /*************************************************************************/ 38 /*************************************************************************/
43 /* */ 39 /* */
44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 40 /* 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 */ 41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
46 /* messages during execution. */ 42 /* messages during execution. */
47 /* */ 43 /* */
48 #undef FT_COMPONENT 44 #undef FT_COMPONENT
49 #define FT_COMPONENT trace_ttinterp 45 #define FT_COMPONENT trace_ttinterp
50 46
51 /*************************************************************************/ 47 /*************************************************************************/
52 /* */ 48 /* */
53 /* In order to detect infinite loops in the code, we set up a counter */ 49 /* 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 */ 50 /* within the run loop. A single stroke of interpretation is now */
55 /* limited to a maximal number of opcodes defined below. */ 51 /* limited to a maximum number of opcodes defined below. */
56 /* */ 52 /* */
57 #define MAX_RUNNABLE_OPCODES 1000000L 53 #define MAX_RUNNABLE_OPCODES 1000000L
58 54
59 55
60 /*************************************************************************/ 56 /*************************************************************************/
61 /* */ 57 /* */
62 /* There are two kinds of implementations: */ 58 /* There are two kinds of implementations: */
63 /* */ 59 /* */
64 /* a. static implementation */ 60 /* a. static implementation */
65 /* */ 61 /* */
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 125
130 126
131 /*************************************************************************/ 127 /*************************************************************************/
132 /* */ 128 /* */
133 /* This macro is used whenever `args' is unused in a function, to avoid */ 129 /* This macro is used whenever `args' is unused in a function, to avoid */
134 /* stupid warnings from pedantic compilers. */ 130 /* stupid warnings from pedantic compilers. */
135 /* */ 131 /* */
136 #define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args ) 132 #define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
137 133
138 134
135 #define SUBPIXEL_HINTING \
136 ( ((TT_Driver)FT_FACE_DRIVER( CUR.face ))->interpreter_version == \
137 TT_INTERPRETER_VERSION_38 )
138
139
139 /*************************************************************************/ 140 /*************************************************************************/
140 /* */ 141 /* */
141 /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */ 142 /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
142 /* increase readability of the code. */ 143 /* increase readability of the code. */
143 /* */ 144 /* */
144 /*************************************************************************/ 145 /*************************************************************************/
145 146
146 147
147 #define SKIP_Code() \ 148 #define SKIP_Code() \
148 SkipCode( EXEC_ARG ) 149 SkipCode( EXEC_ARG )
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 typedef void (*TInstruction_Function)( INS_ARG ); 226 typedef void (*TInstruction_Function)( INS_ARG );
226 227
227 228
228 /*************************************************************************/ 229 /*************************************************************************/
229 /* */ 230 /* */
230 /* Two simple bounds-checking macros. */ 231 /* Two simple bounds-checking macros. */
231 /* */ 232 /* */
232 #define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) 233 #define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
233 #define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) ) 234 #define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
234 235
236 /*************************************************************************/
237 /* */
238 /* This macro computes (a*2^14)/b and complements TT_MulFix14. */
239 /* */
240 #define TT_DivFix14( a, b ) \
241 FT_DivFix( a, (b) << 2 )
242
243
235 #undef SUCCESS 244 #undef SUCCESS
236 #define SUCCESS 0 245 #define SUCCESS 0
237 246
238 #undef FAILURE 247 #undef FAILURE
239 #define FAILURE 1 248 #define FAILURE 1
240 249
241 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 250 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
242 #define GUESS_VECTOR( V ) \ 251 #define GUESS_VECTOR( V ) \
243 if ( CUR.face->unpatented_hinting ) \ 252 if ( CUR.face->unpatented_hinting ) \
244 { \ 253 { \
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 /* which will return to the first byte *after* the code */ 303 /* which will return to the first byte *after* the code */
295 /* range, we test for IP <= Size instead of IP < Size. */ 304 /* range, we test for IP <= Size instead of IP < Size. */
296 /* */ 305 /* */
297 FT_ASSERT( (FT_ULong)IP <= coderange->size ); 306 FT_ASSERT( (FT_ULong)IP <= coderange->size );
298 307
299 exec->code = coderange->base; 308 exec->code = coderange->base;
300 exec->codeSize = coderange->size; 309 exec->codeSize = coderange->size;
301 exec->IP = IP; 310 exec->IP = IP;
302 exec->curRange = range; 311 exec->curRange = range;
303 312
304 return TT_Err_Ok; 313 return FT_Err_Ok;
305 } 314 }
306 315
307 316
308 /*************************************************************************/ 317 /*************************************************************************/
309 /* */ 318 /* */
310 /* <Function> */ 319 /* <Function> */
311 /* TT_Set_CodeRange */ 320 /* TT_Set_CodeRange */
312 /* */ 321 /* */
313 /* <Description> */ 322 /* <Description> */
314 /* Sets a code range. */ 323 /* Sets a code range. */
(...skipping 15 matching lines...) Expand all
330 TT_Set_CodeRange( TT_ExecContext exec, 339 TT_Set_CodeRange( TT_ExecContext exec,
331 FT_Int range, 340 FT_Int range,
332 void* base, 341 void* base,
333 FT_Long length ) 342 FT_Long length )
334 { 343 {
335 FT_ASSERT( range >= 1 && range <= 3 ); 344 FT_ASSERT( range >= 1 && range <= 3 );
336 345
337 exec->codeRangeTable[range - 1].base = (FT_Byte*)base; 346 exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
338 exec->codeRangeTable[range - 1].size = length; 347 exec->codeRangeTable[range - 1].size = length;
339 348
340 return TT_Err_Ok; 349 return FT_Err_Ok;
341 } 350 }
342 351
343 352
344 /*************************************************************************/ 353 /*************************************************************************/
345 /* */ 354 /* */
346 /* <Function> */ 355 /* <Function> */
347 /* TT_Clear_CodeRange */ 356 /* TT_Clear_CodeRange */
348 /* */ 357 /* */
349 /* <Description> */ 358 /* <Description> */
350 /* Clears a code range. */ 359 /* Clears a code range. */
(...skipping 12 matching lines...) Expand all
363 /* */ 372 /* */
364 FT_LOCAL_DEF( FT_Error ) 373 FT_LOCAL_DEF( FT_Error )
365 TT_Clear_CodeRange( TT_ExecContext exec, 374 TT_Clear_CodeRange( TT_ExecContext exec,
366 FT_Int range ) 375 FT_Int range )
367 { 376 {
368 FT_ASSERT( range >= 1 && range <= 3 ); 377 FT_ASSERT( range >= 1 && range <= 3 );
369 378
370 exec->codeRangeTable[range - 1].base = NULL; 379 exec->codeRangeTable[range - 1].base = NULL;
371 exec->codeRangeTable[range - 1].size = 0; 380 exec->codeRangeTable[range - 1].size = 0;
372 381
373 return TT_Err_Ok; 382 return FT_Err_Ok;
374 } 383 }
375 384
376 385
377 /*************************************************************************/ 386 /*************************************************************************/
378 /* */ 387 /* */
379 /* EXECUTION CONTEXT ROUTINES */ 388 /* EXECUTION CONTEXT ROUTINES */
380 /* */ 389 /* */
381 /*************************************************************************/ 390 /*************************************************************************/
382 391
383 392
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 430
422 /* free glyph code range */ 431 /* free glyph code range */
423 FT_FREE( exec->glyphIns ); 432 FT_FREE( exec->glyphIns );
424 exec->glyphSize = 0; 433 exec->glyphSize = 0;
425 434
426 exec->size = NULL; 435 exec->size = NULL;
427 exec->face = NULL; 436 exec->face = NULL;
428 437
429 FT_FREE( exec ); 438 FT_FREE( exec );
430 439
431 return TT_Err_Ok; 440 return FT_Err_Ok;
432 } 441 }
433 442
434 443
435 /*************************************************************************/ 444 /*************************************************************************/
436 /* */ 445 /* */
437 /* <Function> */ 446 /* <Function> */
438 /* Init_Context */ 447 /* Init_Context */
439 /* */ 448 /* */
440 /* <Description> */ 449 /* <Description> */
441 /* Initializes a context object. */ 450 /* Initializes a context object. */
(...skipping 29 matching lines...) Expand all
471 480
472 exec->stackSize = 0; 481 exec->stackSize = 0;
473 exec->glyphSize = 0; 482 exec->glyphSize = 0;
474 483
475 exec->stack = NULL; 484 exec->stack = NULL;
476 exec->glyphIns = NULL; 485 exec->glyphIns = NULL;
477 486
478 exec->face = NULL; 487 exec->face = NULL;
479 exec->size = NULL; 488 exec->size = NULL;
480 489
481 return TT_Err_Ok; 490 return FT_Err_Ok;
482 491
483 Fail_Memory: 492 Fail_Memory:
484 FT_ERROR(( "Init_Context: not enough memory for %p\n", exec )); 493 FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
485 TT_Done_Context( exec ); 494 TT_Done_Context( exec );
486 495
487 return error; 496 return error;
488 } 497 }
489 498
490 499
491 /*************************************************************************/ 500 /*************************************************************************/
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 void** pbuff = (void**)_pbuff; 532 void** pbuff = (void**)_pbuff;
524 533
525 534
526 if ( *size < new_max ) 535 if ( *size < new_max )
527 { 536 {
528 if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) ) 537 if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
529 return error; 538 return error;
530 *size = new_max; 539 *size = new_max;
531 } 540 }
532 541
533 return TT_Err_Ok; 542 return FT_Err_Ok;
534 } 543 }
535 544
536 545
537 /*************************************************************************/ 546 /*************************************************************************/
538 /* */ 547 /* */
539 /* <Function> */ 548 /* <Function> */
540 /* TT_Load_Context */ 549 /* TT_Load_Context */
541 /* */ 550 /* */
542 /* <Description> */ 551 /* <Description> */
543 /* Prepare an execution context for glyph hinting. */ 552 /* Prepare an execution context for glyph hinting. */
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 639
631 exec->pts.n_points = 0; 640 exec->pts.n_points = 0;
632 exec->pts.n_contours = 0; 641 exec->pts.n_contours = 0;
633 642
634 exec->zp1 = exec->pts; 643 exec->zp1 = exec->pts;
635 exec->zp2 = exec->pts; 644 exec->zp2 = exec->pts;
636 exec->zp0 = exec->pts; 645 exec->zp0 = exec->pts;
637 646
638 exec->instruction_trap = FALSE; 647 exec->instruction_trap = FALSE;
639 648
640 return TT_Err_Ok; 649 return FT_Err_Ok;
641 } 650 }
642 651
643 652
644 /*************************************************************************/ 653 /*************************************************************************/
645 /* */ 654 /* */
646 /* <Function> */ 655 /* <Function> */
647 /* TT_Save_Context */ 656 /* TT_Save_Context */
648 /* */ 657 /* */
649 /* <Description> */ 658 /* <Description> */
650 /* Saves the code ranges in a `size' object. */ 659 /* Saves the code ranges in a `size' object. */
(...skipping 22 matching lines...) Expand all
673 /* */ 682 /* */
674 size->num_function_defs = exec->numFDefs; 683 size->num_function_defs = exec->numFDefs;
675 size->num_instruction_defs = exec->numIDefs; 684 size->num_instruction_defs = exec->numIDefs;
676 685
677 size->max_func = exec->maxFunc; 686 size->max_func = exec->maxFunc;
678 size->max_ins = exec->maxIns; 687 size->max_ins = exec->maxIns;
679 688
680 for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) 689 for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
681 size->codeRangeTable[i] = exec->codeRangeTable[i]; 690 size->codeRangeTable[i] = exec->codeRangeTable[i];
682 691
683 return TT_Err_Ok; 692 return FT_Err_Ok;
684 } 693 }
685 694
686 695
687 /*************************************************************************/ 696 /*************************************************************************/
688 /* */ 697 /* */
689 /* <Function> */ 698 /* <Function> */
690 /* TT_Run_Context */ 699 /* TT_Run_Context */
691 /* */ 700 /* */
692 /* <Description> */ 701 /* <Description> */
693 /* Executes one or more instructions in the execution context. */ 702 /* Executes one or more instructions in the execution context. */
(...skipping 15 matching lines...) Expand all
709 /* Only the glyph loader and debugger should call this function. */ 718 /* Only the glyph loader and debugger should call this function. */
710 /* */ 719 /* */
711 FT_LOCAL_DEF( FT_Error ) 720 FT_LOCAL_DEF( FT_Error )
712 TT_Run_Context( TT_ExecContext exec, 721 TT_Run_Context( TT_ExecContext exec,
713 FT_Bool debug ) 722 FT_Bool debug )
714 { 723 {
715 FT_Error error; 724 FT_Error error;
716 725
717 726
718 if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) ) 727 if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
719 != TT_Err_Ok ) 728 != FT_Err_Ok )
720 return error; 729 return error;
721 730
722 exec->zp0 = exec->pts; 731 exec->zp0 = exec->pts;
723 exec->zp1 = exec->pts; 732 exec->zp1 = exec->pts;
724 exec->zp2 = exec->pts; 733 exec->zp2 = exec->pts;
725 734
726 exec->GS.gep0 = 1; 735 exec->GS.gep0 = 1;
727 exec->GS.gep1 = 1; 736 exec->GS.gep1 = 1;
728 exec->GS.gep2 = 1; 737 exec->GS.gep2 = 1;
729 738
(...skipping 16 matching lines...) Expand all
746 exec->callTop = 0; 755 exec->callTop = 0;
747 756
748 #if 1 757 #if 1
749 FT_UNUSED( debug ); 758 FT_UNUSED( debug );
750 759
751 return exec->face->interpreter( exec ); 760 return exec->face->interpreter( exec );
752 #else 761 #else
753 if ( !debug ) 762 if ( !debug )
754 return TT_RunIns( exec ); 763 return TT_RunIns( exec );
755 else 764 else
756 return TT_Err_Ok; 765 return FT_Err_Ok;
757 #endif 766 #endif
758 } 767 }
759 768
760 769
761 /* The default value for `scan_control' is documented as FALSE in the */ 770 /* The default value for `scan_control' is documented as FALSE in the */
762 /* TrueType specification. This is confusing since it implies a */ 771 /* TrueType specification. This is confusing since it implies a */
763 /* Boolean value. However, this is not the case, thus both the */ 772 /* Boolean value. However, this is not the case, thus both the */
764 /* default values of our `scan_type' and `scan_control' fields (which */ 773 /* default values of our `scan_type' and `scan_control' fields (which */
765 /* the documentation's `scan_control' variable is split into) are */ 774 /* the documentation's `scan_control' variable is split into) are */
766 /* zero. */ 775 /* zero. */
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 if ( lo < mid ) 1465 if ( lo < mid )
1457 hi += 1; 1466 hi += 1;
1458 1467
1459 mid = ( lo >> 14 ) | ( hi << 18 ); 1468 mid = ( lo >> 14 ) | ( hi << 18 );
1460 1469
1461 return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid; 1470 return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
1462 } 1471 }
1463 1472
1464 #else 1473 #else
1465 1474
1466 /* compute (a*b)/2^14 with maximal accuracy and rounding */ 1475 /* compute (a*b)/2^14 with maximum accuracy and rounding */
1467 static FT_Int32 1476 static FT_Int32
1468 TT_MulFix14( FT_Int32 a, 1477 TT_MulFix14( FT_Int32 a,
1469 FT_Int b ) 1478 FT_Int b )
1470 { 1479 {
1471 FT_Int32 m, s, hi; 1480 FT_Int32 m, s, hi;
1472 FT_UInt32 l, lo; 1481 FT_UInt32 l, lo;
1473 1482
1474 1483
1475 /* compute ax*bx as 64-bit value */ 1484 /* compute ax*bx as 64-bit value */
1476 l = (FT_UInt32)( ( a & 0xFFFFU ) * b ); 1485 l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
1477 m = ( a >> 16 ) * b; 1486 m = ( a >> 16 ) * b;
1478 1487
1479 lo = l + (FT_UInt32)( m << 16 ); 1488 lo = l + ( (FT_UInt32)m << 16 );
1480 hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l ); 1489 hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
1481 1490
1482 /* divide the result by 2^14 with rounding */ 1491 /* divide the result by 2^14 with rounding */
1483 s = hi >> 31; 1492 s = hi >> 31;
1484 l = lo + (FT_UInt32)s; 1493 l = lo + (FT_UInt32)s;
1485 hi += s + ( l < lo ); 1494 hi += s + ( l < lo );
1486 lo = l; 1495 lo = l;
1487 1496
1488 l = lo + 0x2000U; 1497 l = lo + 0x2000U;
1489 hi += l < lo; 1498 hi += l < lo;
1490 1499
1491 return ( hi << 18 ) | ( l >> 14 ); 1500 return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
1492 } 1501 }
1493 #endif 1502 #endif
1494 1503
1495 1504
1496 /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */ 1505 /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
1497 static FT_Int32 1506 static FT_Int32
1498 TT_DotFix14( FT_Int32 ax, 1507 TT_DotFix14( FT_Int32 ax,
1499 FT_Int32 ay, 1508 FT_Int32 ay,
1500 FT_Int bx, 1509 FT_Int bx,
1501 FT_Int by ) 1510 FT_Int by )
1502 { 1511 {
1503 FT_Int32 m, s, hi1, hi2, hi; 1512 FT_Int32 m, s, hi1, hi2, hi;
1504 FT_UInt32 l, lo1, lo2, lo; 1513 FT_UInt32 l, lo1, lo2, lo;
1505 1514
1506 1515
1507 /* compute ax*bx as 64-bit value */ 1516 /* compute ax*bx as 64-bit value */
1508 l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx ); 1517 l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
1509 m = ( ax >> 16 ) * bx; 1518 m = ( ax >> 16 ) * bx;
1510 1519
1511 lo1 = l + (FT_UInt32)( m << 16 ); 1520 lo1 = l + ( (FT_UInt32)m << 16 );
1512 hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l ); 1521 hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
1513 1522
1514 /* compute ay*by as 64-bit value */ 1523 /* compute ay*by as 64-bit value */
1515 l = (FT_UInt32)( ( ay & 0xFFFFU ) * by ); 1524 l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
1516 m = ( ay >> 16 ) * by; 1525 m = ( ay >> 16 ) * by;
1517 1526
1518 lo2 = l + (FT_UInt32)( m << 16 ); 1527 lo2 = l + ( (FT_UInt32)m << 16 );
1519 hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l ); 1528 hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
1520 1529
1521 /* add them */ 1530 /* add them */
1522 lo = lo1 + lo2; 1531 lo = lo1 + lo2;
1523 hi = hi1 + hi2 + ( lo < lo1 ); 1532 hi = hi1 + hi2 + ( lo < lo1 );
1524 1533
1525 /* divide the result by 2^14 with rounding */ 1534 /* divide the result by 2^14 with rounding */
1526 s = hi >> 31; 1535 s = hi >> 31;
1527 l = lo + (FT_UInt32)s; 1536 l = lo + (FT_UInt32)s;
1528 hi += s + ( l < lo ); 1537 hi += s + ( l < lo );
1529 lo = l; 1538 lo = l;
1530 1539
1531 l = lo + 0x2000U; 1540 l = lo + 0x2000U;
1532 hi += ( l < lo ); 1541 hi += ( l < lo );
1533 1542
1534 return ( hi << 18 ) | ( l >> 14 ); 1543 return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
1535 } 1544 }
1536 1545
1537 1546
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 /*************************************************************************/ 1547 /*************************************************************************/
1629 /* */ 1548 /* */
1630 /* <Function> */ 1549 /* <Function> */
1631 /* Current_Ratio */ 1550 /* Current_Ratio */
1632 /* */ 1551 /* */
1633 /* <Description> */ 1552 /* <Description> */
1634 /* Returns the current aspect ratio scaling factor depending on the */ 1553 /* Returns the current aspect ratio scaling factor depending on the */
1635 /* projection vector's state and device resolutions. */ 1554 /* projection vector's state and device resolutions. */
1636 /* */ 1555 /* */
1637 /* <Return> */ 1556 /* <Return> */
(...skipping 16 matching lines...) Expand all
1654 #endif 1573 #endif
1655 { 1574 {
1656 if ( CUR.GS.projVector.y == 0 ) 1575 if ( CUR.GS.projVector.y == 0 )
1657 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio; 1576 CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
1658 1577
1659 else if ( CUR.GS.projVector.x == 0 ) 1578 else if ( CUR.GS.projVector.x == 0 )
1660 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio; 1579 CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
1661 1580
1662 else 1581 else
1663 { 1582 {
1664 FT_Long x, y; 1583 FT_F26Dot6 x, y;
1665 1584
1666 1585
1667 x = TT_MULDIV( CUR.GS.projVector.x, 1586 x = TT_MulFix14( CUR.tt_metrics.x_ratio,
1668 CUR.tt_metrics.x_ratio, 0x4000 ); 1587 CUR.GS.projVector.x );
1669 y = TT_MULDIV( CUR.GS.projVector.y, 1588 y = TT_MulFix14( CUR.tt_metrics.y_ratio,
1670 CUR.tt_metrics.y_ratio, 0x4000 ); 1589 CUR.GS.projVector.y );
1671 CUR.tt_metrics.ratio = TT_VecLen( x, y ); 1590 CUR.tt_metrics.ratio = FT_Hypot( x, y );
1672 } 1591 }
1673 } 1592 }
1674 } 1593 }
1675 return CUR.tt_metrics.ratio; 1594 return CUR.tt_metrics.ratio;
1676 } 1595 }
1677 1596
1678 1597
1679 static FT_Long 1598 static FT_Long
1680 Current_Ppem( EXEC_OP ) 1599 Current_Ppem( EXEC_OP )
1681 { 1600 {
1682 return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() ); 1601 return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() );
1683 } 1602 }
1684 1603
1685 1604
1686 /*************************************************************************/ 1605 /*************************************************************************/
1687 /* */ 1606 /* */
1688 /* Functions related to the control value table (CVT). */ 1607 /* Functions related to the control value table (CVT). */
1689 /* */ 1608 /* */
1690 /*************************************************************************/ 1609 /*************************************************************************/
1691 1610
1692 1611
1693 FT_CALLBACK_DEF( FT_F26Dot6 ) 1612 FT_CALLBACK_DEF( FT_F26Dot6 )
1694 Read_CVT( EXEC_OP_ FT_ULong idx ) 1613 Read_CVT( EXEC_OP_ FT_ULong idx )
1695 { 1614 {
1696 return CUR.cvt[idx]; 1615 return CUR.cvt[idx];
1697 } 1616 }
1698 1617
1699 1618
1700 FT_CALLBACK_DEF( FT_F26Dot6 ) 1619 FT_CALLBACK_DEF( FT_F26Dot6 )
1701 Read_CVT_Stretched( EXEC_OP_ FT_ULong idx ) 1620 Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
1702 { 1621 {
1703 return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() ); 1622 return FT_MulFix( CUR.cvt[idx], CURRENT_Ratio() );
1704 } 1623 }
1705 1624
1706 1625
1707 FT_CALLBACK_DEF( void ) 1626 FT_CALLBACK_DEF( void )
1708 Write_CVT( EXEC_OP_ FT_ULong idx, 1627 Write_CVT( EXEC_OP_ FT_ULong idx,
1709 FT_F26Dot6 value ) 1628 FT_F26Dot6 value )
1710 { 1629 {
1711 CUR.cvt[idx] = value; 1630 CUR.cvt[idx] = value;
1712 } 1631 }
1713 1632
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 /* */ 1698 /* */
1780 static FT_Bool 1699 static FT_Bool
1781 Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange, 1700 Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
1782 FT_ULong aIP ) 1701 FT_ULong aIP )
1783 { 1702 {
1784 TT_CodeRange* range; 1703 TT_CodeRange* range;
1785 1704
1786 1705
1787 if ( aRange < 1 || aRange > 3 ) 1706 if ( aRange < 1 || aRange > 3 )
1788 { 1707 {
1789 CUR.error = TT_Err_Bad_Argument; 1708 CUR.error = FT_THROW( Bad_Argument );
1790 return FAILURE; 1709 return FAILURE;
1791 } 1710 }
1792 1711
1793 range = &CUR.codeRangeTable[aRange - 1]; 1712 range = &CUR.codeRangeTable[aRange - 1];
1794 1713
1795 if ( range->base == NULL ) /* invalid coderange */ 1714 if ( range->base == NULL ) /* invalid coderange */
1796 { 1715 {
1797 CUR.error = TT_Err_Invalid_CodeRange; 1716 CUR.error = FT_THROW( Invalid_CodeRange );
1798 return FAILURE; 1717 return FAILURE;
1799 } 1718 }
1800 1719
1801 /* NOTE: Because the last instruction of a program may be a CALL */ 1720 /* NOTE: Because the last instruction of a program may be a CALL */
1802 /* which will return to the first byte *after* the code */ 1721 /* which will return to the first byte *after* the code */
1803 /* range, we test for aIP <= Size, instead of aIP < Size. */ 1722 /* range, we test for aIP <= Size, instead of aIP < Size. */
1804 1723
1805 if ( aIP > range->size ) 1724 if ( aIP > range->size )
1806 { 1725 {
1807 CUR.error = TT_Err_Code_Overflow; 1726 CUR.error = FT_THROW( Code_Overflow );
1808 return FAILURE; 1727 return FAILURE;
1809 } 1728 }
1810 1729
1811 CUR.code = range->base; 1730 CUR.code = range->base;
1812 CUR.codeSize = range->size; 1731 CUR.codeSize = range->size;
1813 CUR.IP = aIP; 1732 CUR.IP = aIP;
1814 CUR.curRange = aRange; 1733 CUR.curRange = aRange;
1815 1734
1816 return SUCCESS; 1735 return SUCCESS;
1817 } 1736 }
(...skipping 25 matching lines...) Expand all
1843 1762
1844 1763
1845 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 1764 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1846 FT_ASSERT( !CUR.face->unpatented_hinting ); 1765 FT_ASSERT( !CUR.face->unpatented_hinting );
1847 #endif 1766 #endif
1848 1767
1849 v = CUR.GS.freeVector.x; 1768 v = CUR.GS.freeVector.x;
1850 1769
1851 if ( v != 0 ) 1770 if ( v != 0 )
1852 { 1771 {
1853 zone->cur[point].x += TT_MULDIV( distance, 1772 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1854 v * 0x10000L, 1773 if ( !SUBPIXEL_HINTING ||
1855 CUR.F_dot_P ); 1774 ( !CUR.ignore_x_mode ||
1775 ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
1776 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
1777 zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
1856 1778
1857 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; 1779 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1858 } 1780 }
1859 1781
1860 v = CUR.GS.freeVector.y; 1782 v = CUR.GS.freeVector.y;
1861 1783
1862 if ( v != 0 ) 1784 if ( v != 0 )
1863 { 1785 {
1864 zone->cur[point].y += TT_MULDIV( distance, 1786 zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
1865 v * 0x10000L,
1866 CUR.F_dot_P );
1867 1787
1868 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; 1788 zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
1869 } 1789 }
1870 } 1790 }
1871 1791
1872 1792
1873 /*************************************************************************/ 1793 /*************************************************************************/
1874 /* */ 1794 /* */
1875 /* <Function> */ 1795 /* <Function> */
1876 /* Direct_Move_Orig */ 1796 /* Direct_Move_Orig */
(...skipping 18 matching lines...) Expand all
1895 FT_F26Dot6 v; 1815 FT_F26Dot6 v;
1896 1816
1897 1817
1898 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 1818 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
1899 FT_ASSERT( !CUR.face->unpatented_hinting ); 1819 FT_ASSERT( !CUR.face->unpatented_hinting );
1900 #endif 1820 #endif
1901 1821
1902 v = CUR.GS.freeVector.x; 1822 v = CUR.GS.freeVector.x;
1903 1823
1904 if ( v != 0 ) 1824 if ( v != 0 )
1905 zone->org[point].x += TT_MULDIV( distance, 1825 zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
1906 v * 0x10000L,
1907 CUR.F_dot_P );
1908 1826
1909 v = CUR.GS.freeVector.y; 1827 v = CUR.GS.freeVector.y;
1910 1828
1911 if ( v != 0 ) 1829 if ( v != 0 )
1912 zone->org[point].y += TT_MULDIV( distance, 1830 zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
1913 v * 0x10000L,
1914 CUR.F_dot_P );
1915 } 1831 }
1916 1832
1917 1833
1918 /*************************************************************************/ 1834 /*************************************************************************/
1919 /* */ 1835 /* */
1920 /* Special versions of Direct_Move() */ 1836 /* Special versions of Direct_Move() */
1921 /* */ 1837 /* */
1922 /* The following versions are used whenever both vectors are both */ 1838 /* 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. */ 1839 /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
1924 /* */ 1840 /* */
1925 /*************************************************************************/ 1841 /*************************************************************************/
1926 1842
1927 1843
1928 static void 1844 static void
1929 Direct_Move_X( EXEC_OP_ TT_GlyphZone zone, 1845 Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
1930 FT_UShort point, 1846 FT_UShort point,
1931 FT_F26Dot6 distance ) 1847 FT_F26Dot6 distance )
1932 { 1848 {
1933 FT_UNUSED_EXEC; 1849 FT_UNUSED_EXEC;
1934 1850
1935 zone->cur[point].x += distance; 1851 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1852 if ( !SUBPIXEL_HINTING ||
1853 !CUR.ignore_x_mode )
1854 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
1855 zone->cur[point].x += distance;
1856
1936 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; 1857 zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
1937 } 1858 }
1938 1859
1939 1860
1940 static void 1861 static void
1941 Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone, 1862 Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
1942 FT_UShort point, 1863 FT_UShort point,
1943 FT_F26Dot6 distance ) 1864 FT_F26Dot6 distance )
1944 { 1865 {
1945 FT_UNUSED_EXEC; 1866 FT_UNUSED_EXEC;
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
2186 if ( distance >= 0 ) 2107 if ( distance >= 0 )
2187 { 2108 {
2188 val = distance + compensation + 63; 2109 val = distance + compensation + 63;
2189 if ( distance && val > 0 ) 2110 if ( distance && val > 0 )
2190 val &= ~63; 2111 val &= ~63;
2191 else 2112 else
2192 val = 0; 2113 val = 0;
2193 } 2114 }
2194 else 2115 else
2195 { 2116 {
2196 val = - FT_PIX_CEIL( compensation - distance ); 2117 val = -FT_PIX_CEIL( compensation - distance );
2197 if ( val > 0 ) 2118 if ( val > 0 )
2198 val = 0; 2119 val = 0;
2199 } 2120 }
2200 2121
2201 return val; 2122 return val;
2202 } 2123 }
2203 2124
2204 2125
2205 /*************************************************************************/ 2126 /*************************************************************************/
2206 /* */ 2127 /* */
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2397 2318
2398 /*************************************************************************/ 2319 /*************************************************************************/
2399 /* */ 2320 /* */
2400 /* <Function> */ 2321 /* <Function> */
2401 /* SetSuperRound */ 2322 /* SetSuperRound */
2402 /* */ 2323 /* */
2403 /* <Description> */ 2324 /* <Description> */
2404 /* Sets Super Round parameters. */ 2325 /* Sets Super Round parameters. */
2405 /* */ 2326 /* */
2406 /* <Input> */ 2327 /* <Input> */
2407 /* GridPeriod :: Grid period */ 2328 /* GridPeriod :: The grid period. */
2408 /* selector :: SROUND opcode */ 2329 /* */
2330 /* selector :: The SROUND opcode. */
2409 /* */ 2331 /* */
2410 static void 2332 static void
2411 SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod, 2333 SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
2412 FT_Long selector ) 2334 FT_Long selector )
2413 { 2335 {
2414 switch ( (FT_Int)( selector & 0xC0 ) ) 2336 switch ( (FT_Int)( selector & 0xC0 ) )
2415 { 2337 {
2416 case 0: 2338 case 0:
2417 CUR.period = GridPeriod / 2; 2339 CUR.period = GridPeriod / 2;
2418 break; 2340 break;
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 } 2532 }
2611 else 2533 else
2612 { 2534 {
2613 CUR.func_project = Project_y; 2535 CUR.func_project = Project_y;
2614 CUR.func_move = Direct_Move_Y; 2536 CUR.func_move = Direct_Move_Y;
2615 CUR.func_move_orig = Direct_Move_Orig_Y; 2537 CUR.func_move_orig = Direct_Move_Orig_Y;
2616 } 2538 }
2617 2539
2618 if ( CUR.GS.dualVector.x == 0x4000 ) 2540 if ( CUR.GS.dualVector.x == 0x4000 )
2619 CUR.func_dualproj = Project_x; 2541 CUR.func_dualproj = Project_x;
2542 else if ( CUR.GS.dualVector.y == 0x4000 )
2543 CUR.func_dualproj = Project_y;
2620 else 2544 else
2621 { 2545 CUR.func_dualproj = Dual_Project;
2622 if ( CUR.GS.dualVector.y == 0x4000 )
2623 CUR.func_dualproj = Project_y;
2624 else
2625 CUR.func_dualproj = Dual_Project;
2626 }
2627 2546
2628 /* Force recalculation of cached aspect ratio */ 2547 /* Force recalculation of cached aspect ratio */
2629 CUR.tt_metrics.ratio = 0; 2548 CUR.tt_metrics.ratio = 0;
2630 2549
2631 return; 2550 return;
2632 } 2551 }
2633 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ 2552 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
2634 2553
2635 if ( CUR.GS.freeVector.x == 0x4000 ) 2554 if ( CUR.GS.freeVector.x == 0x4000 )
2636 CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L; 2555 CUR.F_dot_P = CUR.GS.projVector.x;
2556 else if ( CUR.GS.freeVector.y == 0x4000 )
2557 CUR.F_dot_P = CUR.GS.projVector.y;
2637 else 2558 else
2638 { 2559 CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x +
2639 if ( CUR.GS.freeVector.y == 0x4000 ) 2560 (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >>
2640 CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L; 2561 14;
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 2562
2646 if ( CUR.GS.projVector.x == 0x4000 ) 2563 if ( CUR.GS.projVector.x == 0x4000 )
2647 CUR.func_project = (TT_Project_Func)Project_x; 2564 CUR.func_project = (TT_Project_Func)Project_x;
2565 else if ( CUR.GS.projVector.y == 0x4000 )
2566 CUR.func_project = (TT_Project_Func)Project_y;
2648 else 2567 else
2649 { 2568 CUR.func_project = (TT_Project_Func)Project;
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 2569
2656 if ( CUR.GS.dualVector.x == 0x4000 ) 2570 if ( CUR.GS.dualVector.x == 0x4000 )
2657 CUR.func_dualproj = (TT_Project_Func)Project_x; 2571 CUR.func_dualproj = (TT_Project_Func)Project_x;
2572 else if ( CUR.GS.dualVector.y == 0x4000 )
2573 CUR.func_dualproj = (TT_Project_Func)Project_y;
2658 else 2574 else
2659 { 2575 CUR.func_dualproj = (TT_Project_Func)Dual_Project;
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 2576
2666 CUR.func_move = (TT_Move_Func)Direct_Move; 2577 CUR.func_move = (TT_Move_Func)Direct_Move;
2667 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig; 2578 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
2668 2579
2669 if ( CUR.F_dot_P == 0x40000000L ) 2580 if ( CUR.F_dot_P == 0x4000L )
2670 { 2581 {
2671 if ( CUR.GS.freeVector.x == 0x4000 ) 2582 if ( CUR.GS.freeVector.x == 0x4000 )
2672 { 2583 {
2673 CUR.func_move = (TT_Move_Func)Direct_Move_X; 2584 CUR.func_move = (TT_Move_Func)Direct_Move_X;
2674 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X; 2585 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
2675 } 2586 }
2676 else 2587 else if ( CUR.GS.freeVector.y == 0x4000 )
2677 { 2588 {
2678 if ( CUR.GS.freeVector.y == 0x4000 ) 2589 CUR.func_move = (TT_Move_Func)Direct_Move_Y;
2679 { 2590 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
2680 CUR.func_move = (TT_Move_Func)Direct_Move_Y;
2681 CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
2682 }
2683 } 2591 }
2684 } 2592 }
2685 2593
2686 /* at small sizes, F_dot_P can become too small, resulting */ 2594 /* at small sizes, F_dot_P can become too small, resulting */
2687 /* in overflows and `spikes' in a number of glyphs like `w'. */ 2595 /* in overflows and `spikes' in a number of glyphs like `w'. */
2688 2596
2689 if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L ) 2597 if ( FT_ABS( CUR.F_dot_P ) < 0x400L )
2690 CUR.F_dot_P = 0x40000000L; 2598 CUR.F_dot_P = 0x4000L;
2691 2599
2692 /* Disable cached aspect ratio */ 2600 /* Disable cached aspect ratio */
2693 CUR.tt_metrics.ratio = 0; 2601 CUR.tt_metrics.ratio = 0;
2694 } 2602 }
2695 2603
2696 2604
2697 /*************************************************************************/ 2605 /*************************************************************************/
2698 /* */ 2606 /* */
2699 /* <Function> */ 2607 /* <Function> */
2700 /* Normalize */ 2608 /* Normalize */
2701 /* */ 2609 /* */
2702 /* <Description> */ 2610 /* <Description> */
2703 /* Norms a vector. */ 2611 /* Norms a vector. */
2704 /* */ 2612 /* */
2705 /* <Input> */ 2613 /* <Input> */
2706 /* Vx :: The horizontal input vector coordinate. */ 2614 /* Vx :: The horizontal input vector coordinate. */
2707 /* Vy :: The vertical input vector coordinate. */ 2615 /* Vy :: The vertical input vector coordinate. */
2708 /* */ 2616 /* */
2709 /* <Output> */ 2617 /* <Output> */
2710 /* R :: The normed unit vector. */ 2618 /* R :: The normed unit vector. */
2711 /* */ 2619 /* */
2712 /* <Return> */ 2620 /* <Return> */
2713 /* Returns FAILURE if a vector parameter is zero. */ 2621 /* Returns FAILURE if a vector parameter is zero. */
2714 /* */ 2622 /* */
2715 /* <Note> */ 2623 /* <Note> */
2716 /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */ 2624 /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
2717 /* R is undefined. */ 2625 /* R is undefined. */
2718 /* */ 2626 /* */
2719
2720
2721 static FT_Bool 2627 static FT_Bool
2722 Normalize( EXEC_OP_ FT_F26Dot6 Vx, 2628 Normalize( EXEC_OP_ FT_F26Dot6 Vx,
2723 FT_F26Dot6 Vy, 2629 FT_F26Dot6 Vy,
2724 FT_UnitVector* R ) 2630 FT_UnitVector* R )
2725 { 2631 {
2726 FT_F26Dot6 W; 2632 FT_F26Dot6 W;
2727 FT_Bool S1, S2;
2728 2633
2729 FT_UNUSED_EXEC; 2634 FT_UNUSED_EXEC;
2730 2635
2731 2636
2732 if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L ) 2637 if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
2733 { 2638 {
2734 Vx *= 0x100; 2639 if ( Vx == 0 && Vy == 0 )
2735 Vy *= 0x100;
2736
2737 W = TT_VecLen( Vx, Vy );
2738
2739 if ( W == 0 )
2740 { 2640 {
2741 /* XXX: UNDOCUMENTED! It seems that it is possible to try */ 2641 /* XXX: UNDOCUMENTED! It seems that it is possible to try */
2742 /* to normalize the vector (0,0). Return immediately. */ 2642 /* to normalize the vector (0,0). Return immediately. */
2743 return SUCCESS; 2643 return SUCCESS;
2744 } 2644 }
2745 2645
2746 R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W ); 2646 Vx *= 0x4000;
2747 R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W ); 2647 Vy *= 0x4000;
2748
2749 return SUCCESS;
2750 } 2648 }
2751 2649
2752 W = TT_VecLen( Vx, Vy ); 2650 W = FT_Hypot( Vx, Vy );
2753 2651
2754 Vx = FT_MulDiv( Vx, 0x4000L, W ); 2652 R->x = (FT_F2Dot14)TT_DivFix14( Vx, W );
2755 Vy = FT_MulDiv( Vy, 0x4000L, W ); 2653 R->y = (FT_F2Dot14)TT_DivFix14( Vy, 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 2654
2812 return SUCCESS; 2655 return SUCCESS;
2813 } 2656 }
2814 2657
2815 2658
2816 /*************************************************************************/ 2659 /*************************************************************************/
2817 /* */ 2660 /* */
2818 /* Here we start with the implementation of the various opcodes. */ 2661 /* Here we start with the implementation of the various opcodes. */
2819 /* */ 2662 /* */
2820 /*************************************************************************/ 2663 /*************************************************************************/
2821 2664
2822 2665
2823 static FT_Bool 2666 static FT_Bool
2824 Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1, 2667 Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
2825 FT_UShort aIdx2, 2668 FT_UShort aIdx2,
2826 FT_Int aOpc, 2669 FT_Int aOpc,
2827 FT_UnitVector* Vec ) 2670 FT_UnitVector* Vec )
2828 { 2671 {
2829 FT_Long A, B, C; 2672 FT_Long A, B, C;
2830 FT_Vector* p1; 2673 FT_Vector* p1;
2831 FT_Vector* p2; 2674 FT_Vector* p2;
2832 2675
2833 2676
2834 if ( BOUNDS( aIdx1, CUR.zp2.n_points ) || 2677 if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
2835 BOUNDS( aIdx2, CUR.zp1.n_points ) ) 2678 BOUNDS( aIdx2, CUR.zp1.n_points ) )
2836 { 2679 {
2837 if ( CUR.pedantic_hinting ) 2680 if ( CUR.pedantic_hinting )
2838 CUR.error = TT_Err_Invalid_Reference; 2681 CUR.error = FT_THROW( Invalid_Reference );
2839 return FAILURE; 2682 return FAILURE;
2840 } 2683 }
2841 2684
2842 p1 = CUR.zp1.cur + aIdx2; 2685 p1 = CUR.zp1.cur + aIdx2;
2843 p2 = CUR.zp2.cur + aIdx1; 2686 p2 = CUR.zp2.cur + aIdx1;
2844 2687
2845 A = p1->x - p2->x; 2688 A = p1->x - p2->x;
2846 B = p1->y - p2->y; 2689 B = p1->y - p2->y;
2847 2690
2848 /* If p1 == p2, SPVTL and SFVTL behave the same as */ 2691 /* If p1 == p2, SPVTL and SFVTL behave the same as */
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
3084 CUR.GS.round_state = TT_Round_Super; \ 2927 CUR.GS.round_state = TT_Round_Super; \
3085 CUR.func_round = (TT_Round_Func)Round_Super; 2928 CUR.func_round = (TT_Round_Func)Round_Super;
3086 2929
3087 2930
3088 #define DO_S45ROUND \ 2931 #define DO_S45ROUND \
3089 SET_SuperRound( 0x2D41, args[0] ); \ 2932 SET_SuperRound( 0x2D41, args[0] ); \
3090 CUR.GS.round_state = TT_Round_Super_45; \ 2933 CUR.GS.round_state = TT_Round_Super_45; \
3091 CUR.func_round = (TT_Round_Func)Round_Super_45; 2934 CUR.func_round = (TT_Round_Func)Round_Super_45;
3092 2935
3093 2936
3094 #define DO_SLOOP \ 2937 #define DO_SLOOP \
3095 if ( args[0] < 0 ) \ 2938 if ( args[0] < 0 ) \
3096 CUR.error = TT_Err_Bad_Argument; \ 2939 CUR.error = FT_THROW( Bad_Argument ); \
3097 else \ 2940 else \
3098 CUR.GS.loop = args[0]; 2941 CUR.GS.loop = args[0];
3099 2942
3100 2943
3101 #define DO_SMD \ 2944 #define DO_SMD \
3102 CUR.GS.minimum_distance = args[0]; 2945 CUR.GS.minimum_distance = args[0];
3103 2946
3104 2947
3105 #define DO_SCVTCI \ 2948 #define DO_SCVTCI \
3106 CUR.GS.control_value_cutin = (FT_F26Dot6)args[0]; 2949 CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
3107 2950
3108 2951
3109 #define DO_SSWCI \ 2952 #define DO_SSWCI \
3110 CUR.GS.single_width_cutin = (FT_F26Dot6)args[0]; 2953 CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
3111 2954
3112 2955
3113 /* XXX: UNDOCUMENTED! or bug in the Windows engine? */ 2956 #define DO_SSW \
3114 /* */ 2957 CUR.GS.single_width_value = FT_MulFix( args[0], \
3115 /* It seems that the value that is read here is */ 2958 CUR.tt_metrics.scale );
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 2959
3122 2960
3123 #define DO_FLIPON \ 2961 #define DO_FLIPON \
3124 CUR.GS.auto_flip = TRUE; 2962 CUR.GS.auto_flip = TRUE;
3125 2963
3126 2964
3127 #define DO_FLIPOFF \ 2965 #define DO_FLIPOFF \
3128 CUR.GS.auto_flip = FALSE; 2966 CUR.GS.auto_flip = FALSE;
3129 2967
3130 2968
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3174 L = args[0]; \ 3012 L = args[0]; \
3175 args[0] = args[1]; \ 3013 args[0] = args[1]; \
3176 args[1] = L; \ 3014 args[1] = L; \
3177 } 3015 }
3178 3016
3179 3017
3180 #define DO_DEPTH \ 3018 #define DO_DEPTH \
3181 args[0] = CUR.top; 3019 args[0] = CUR.top;
3182 3020
3183 3021
3184 #define DO_CINDEX \ 3022 #define DO_CINDEX \
3185 { \ 3023 { \
3186 FT_Long L; \ 3024 FT_Long L; \
3187 \ 3025 \
3188 \ 3026 \
3189 L = args[0]; \ 3027 L = args[0]; \
3190 \ 3028 \
3191 if ( L <= 0 || L > CUR.args ) \ 3029 if ( L <= 0 || L > CUR.args ) \
3192 { \ 3030 { \
3193 if ( CUR.pedantic_hinting ) \ 3031 if ( CUR.pedantic_hinting ) \
3194 CUR.error = TT_Err_Invalid_Reference; \ 3032 CUR.error = FT_THROW( Invalid_Reference ); \
3195 args[0] = 0; \ 3033 args[0] = 0; \
3196 } \ 3034 } \
3197 else \ 3035 else \
3198 args[0] = CUR.stack[CUR.args - L]; \ 3036 args[0] = CUR.stack[CUR.args - L]; \
3199 } 3037 }
3200 3038
3201 3039
3202 #define DO_JROT \ 3040 #define DO_JROT \
3203 if ( args[1] != 0 ) \ 3041 if ( args[1] != 0 ) \
3204 { \ 3042 { \
3205 if ( args[0] == 0 && CUR.args == 0 ) \ 3043 if ( args[0] == 0 && CUR.args == 0 ) \
3206 CUR.error = TT_Err_Bad_Argument; \ 3044 CUR.error = FT_THROW( Bad_Argument ); \
3207 CUR.IP += args[0]; \ 3045 CUR.IP += args[0]; \
3208 if ( CUR.IP < 0 || \ 3046 if ( CUR.IP < 0 || \
3209 ( CUR.callTop > 0 && \ 3047 ( CUR.callTop > 0 && \
3210 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ 3048 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
3211 CUR.error = TT_Err_Bad_Argument; \ 3049 CUR.error = FT_THROW( Bad_Argument ); \
3212 CUR.step_ins = FALSE; \ 3050 CUR.step_ins = FALSE; \
3213 } 3051 }
3214 3052
3215 3053
3216 #define DO_JMPR \ 3054 #define DO_JMPR \
3217 if ( args[0] == 0 && CUR.args == 0 ) \ 3055 if ( args[0] == 0 && CUR.args == 0 ) \
3218 CUR.error = TT_Err_Bad_Argument; \ 3056 CUR.error = FT_THROW( Bad_Argument ); \
3219 CUR.IP += args[0]; \ 3057 CUR.IP += args[0]; \
3220 if ( CUR.IP < 0 || \ 3058 if ( CUR.IP < 0 || \
3221 ( CUR.callTop > 0 && \ 3059 ( CUR.callTop > 0 && \
3222 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ 3060 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
3223 CUR.error = TT_Err_Bad_Argument; \ 3061 CUR.error = FT_THROW( Bad_Argument ); \
3224 CUR.step_ins = FALSE; 3062 CUR.step_ins = FALSE;
3225 3063
3226 3064
3227 #define DO_JROF \ 3065 #define DO_JROF \
3228 if ( args[1] == 0 ) \ 3066 if ( args[1] == 0 ) \
3229 { \ 3067 { \
3230 if ( args[0] == 0 && CUR.args == 0 ) \ 3068 if ( args[0] == 0 && CUR.args == 0 ) \
3231 CUR.error = TT_Err_Bad_Argument; \ 3069 CUR.error = FT_THROW( Bad_Argument ); \
3232 CUR.IP += args[0]; \ 3070 CUR.IP += args[0]; \
3233 if ( CUR.IP < 0 || \ 3071 if ( CUR.IP < 0 || \
3234 ( CUR.callTop > 0 && \ 3072 ( CUR.callTop > 0 && \
3235 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ 3073 CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
3236 CUR.error = TT_Err_Bad_Argument; \ 3074 CUR.error = FT_THROW( Bad_Argument ); \
3237 CUR.step_ins = FALSE; \ 3075 CUR.step_ins = FALSE; \
3238 } 3076 }
3239 3077
3240 3078
3241 #define DO_LT \ 3079 #define DO_LT \
3242 args[0] = ( args[0] < args[1] ); 3080 args[0] = ( args[0] < args[1] );
3243 3081
3244 3082
3245 #define DO_LTEQ \ 3083 #define DO_LTEQ \
3246 args[0] = ( args[0] <= args[1] ); 3084 args[0] = ( args[0] <= args[1] );
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3285 #define DO_ADD \ 3123 #define DO_ADD \
3286 args[0] += args[1]; 3124 args[0] += args[1];
3287 3125
3288 3126
3289 #define DO_SUB \ 3127 #define DO_SUB \
3290 args[0] -= args[1]; 3128 args[0] -= args[1];
3291 3129
3292 3130
3293 #define DO_DIV \ 3131 #define DO_DIV \
3294 if ( args[1] == 0 ) \ 3132 if ( args[1] == 0 ) \
3295 CUR.error = TT_Err_Divide_By_Zero; \ 3133 CUR.error = FT_THROW( Divide_By_Zero ); \
3296 else \ 3134 else \
3297 args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] ); 3135 args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
3298 3136
3299 3137
3300 #define DO_MUL \ 3138 #define DO_MUL \
3301 args[0] = TT_MULDIV( args[0], args[1], 64L ); 3139 args[0] = FT_MulDiv( args[0], args[1], 64L );
3302 3140
3303 3141
3304 #define DO_ABS \ 3142 #define DO_ABS \
3305 args[0] = FT_ABS( args[0] ); 3143 args[0] = FT_ABS( args[0] );
3306 3144
3307 3145
3308 #define DO_NEG \ 3146 #define DO_NEG \
3309 args[0] = -args[0]; 3147 args[0] = -args[0];
3310 3148
3311 3149
3312 #define DO_FLOOR \ 3150 #define DO_FLOOR \
3313 args[0] = FT_PIX_FLOOR( args[0] ); 3151 args[0] = FT_PIX_FLOOR( args[0] );
3314 3152
3315 3153
3316 #define DO_CEILING \ 3154 #define DO_CEILING \
3317 args[0] = FT_PIX_CEIL( args[0] ); 3155 args[0] = FT_PIX_CEIL( args[0] );
3318 3156
3157 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
3158
3159 #define DO_RS \
3160 { \
3161 FT_ULong I = (FT_ULong)args[0]; \
3162 \
3163 \
3164 if ( BOUNDSL( I, CUR.storeSize ) ) \
3165 { \
3166 if ( CUR.pedantic_hinting ) \
3167 ARRAY_BOUND_ERROR; \
3168 else \
3169 args[0] = 0; \
3170 } \
3171 else \
3172 { \
3173 /* subpixel hinting - avoid Typeman Dstroke and */ \
3174 /* IStroke and Vacuform rounds */ \
3175 \
3176 if ( SUBPIXEL_HINTING && \
3177 CUR.ignore_x_mode && \
3178 ( ( I == 24 && \
3179 ( CUR.face->sph_found_func_flags & \
3180 ( SPH_FDEF_SPACING_1 | \
3181 SPH_FDEF_SPACING_2 ) ) ) || \
3182 ( I == 22 && \
3183 ( CUR.sph_in_func_flags & \
3184 SPH_FDEF_TYPEMAN_STROKES ) ) || \
3185 ( I == 8 && \
3186 ( CUR.face->sph_found_func_flags & \
3187 SPH_FDEF_VACUFORM_ROUND_1 ) && \
3188 CUR.iup_called ) ) ) \
3189 args[0] = 0; \
3190 else \
3191 args[0] = CUR.storage[I]; \
3192 } \
3193 }
3194
3195 #else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
3319 3196
3320 #define DO_RS \ 3197 #define DO_RS \
3321 { \ 3198 { \
3322 FT_ULong I = (FT_ULong)args[0]; \ 3199 FT_ULong I = (FT_ULong)args[0]; \
3323 \ 3200 \
3324 \ 3201 \
3325 if ( BOUNDSL( I, CUR.storeSize ) ) \ 3202 if ( BOUNDSL( I, CUR.storeSize ) ) \
3326 { \ 3203 { \
3327 if ( CUR.pedantic_hinting ) \ 3204 if ( CUR.pedantic_hinting ) \
3328 { \ 3205 { \
3329 ARRAY_BOUND_ERROR; \ 3206 ARRAY_BOUND_ERROR; \
3330 } \ 3207 } \
3331 else \ 3208 else \
3332 args[0] = 0; \ 3209 args[0] = 0; \
3333 } \ 3210 } \
3334 else \ 3211 else \
3335 args[0] = CUR.storage[I]; \ 3212 args[0] = CUR.storage[I]; \
3336 } 3213 }
3337 3214
3215 #endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
3216
3338 3217
3339 #define DO_WS \ 3218 #define DO_WS \
3340 { \ 3219 { \
3341 FT_ULong I = (FT_ULong)args[0]; \ 3220 FT_ULong I = (FT_ULong)args[0]; \
3342 \ 3221 \
3343 \ 3222 \
3344 if ( BOUNDSL( I, CUR.storeSize ) ) \ 3223 if ( BOUNDSL( I, CUR.storeSize ) ) \
3345 { \ 3224 { \
3346 if ( CUR.pedantic_hinting ) \ 3225 if ( CUR.pedantic_hinting ) \
3347 { \ 3226 { \
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3395 \ 3274 \
3396 \ 3275 \
3397 if ( BOUNDSL( I, CUR.cvtSize ) ) \ 3276 if ( BOUNDSL( I, CUR.cvtSize ) ) \
3398 { \ 3277 { \
3399 if ( CUR.pedantic_hinting ) \ 3278 if ( CUR.pedantic_hinting ) \
3400 { \ 3279 { \
3401 ARRAY_BOUND_ERROR; \ 3280 ARRAY_BOUND_ERROR; \
3402 } \ 3281 } \
3403 } \ 3282 } \
3404 else \ 3283 else \
3405 CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \ 3284 CUR.cvt[I] = FT_MulFix( args[1], CUR.tt_metrics.scale ); \
3406 } 3285 }
3407 3286
3408 3287
3409 #define DO_DEBUG \ 3288 #define DO_DEBUG \
3410 CUR.error = TT_Err_Debug_OpCode; 3289 CUR.error = FT_THROW( Debug_OpCode );
3411 3290
3412 3291
3413 #define DO_ROUND \ 3292 #define DO_ROUND \
3414 args[0] = CUR_Func_round( \ 3293 args[0] = CUR_Func_round( \
3415 args[0], \ 3294 args[0], \
3416 CUR.tt_metrics.compensations[CUR.opcode - 0x68] ); 3295 CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
3417 3296
3418 3297
3419 #define DO_NROUND \ 3298 #define DO_NROUND \
3420 args[0] = ROUND_None( args[0], \ 3299 args[0] = ROUND_None( args[0], \
3421 CUR.tt_metrics.compensations[CUR.opcode - 0x6C] ); 3300 CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
3422 3301
3423 3302
3424 #define DO_MAX \ 3303 #define DO_MAX \
3425 if ( args[1] > args[0] ) \ 3304 if ( args[1] > args[0] ) \
3426 args[0] = args[1]; 3305 args[0] = args[1];
3427 3306
3428 3307
3429 #define DO_MIN \ 3308 #define DO_MIN \
3430 if ( args[1] < args[0] ) \ 3309 if ( args[1] < args[0] ) \
3431 args[0] = args[1]; 3310 args[0] = args[1];
3432 3311
3433 3312
3434 #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH 3313 #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
3435 3314
3436 3315
3437 #undef ARRAY_BOUND_ERROR 3316 #undef ARRAY_BOUND_ERROR
3438 #define ARRAY_BOUND_ERROR \ 3317 #define ARRAY_BOUND_ERROR \
3439 { \ 3318 { \
3440 CUR.error = TT_Err_Invalid_Reference; \ 3319 CUR.error = FT_THROW( Invalid_Reference ); \
3441 return; \ 3320 return; \
3442 } 3321 }
3443 3322
3444 3323
3445 /*************************************************************************/ 3324 /*************************************************************************/
3446 /* */ 3325 /* */
3447 /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */ 3326 /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
3448 /* Opcode range: 0x00-0x01 */ 3327 /* Opcode range: 0x00-0x01 */
3449 /* Stack: --> */ 3328 /* Stack: --> */
3450 /* */ 3329 /* */
3451 static void 3330 static void
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after
4410 Ins_MINDEX( INS_ARG ) 4289 Ins_MINDEX( INS_ARG )
4411 { 4290 {
4412 FT_Long L, K; 4291 FT_Long L, K;
4413 4292
4414 4293
4415 L = args[0]; 4294 L = args[0];
4416 4295
4417 if ( L <= 0 || L > CUR.args ) 4296 if ( L <= 0 || L > CUR.args )
4418 { 4297 {
4419 if ( CUR.pedantic_hinting ) 4298 if ( CUR.pedantic_hinting )
4420 CUR.error = TT_Err_Invalid_Reference; 4299 CUR.error = FT_THROW( Invalid_Reference );
4421 } 4300 }
4422 else 4301 else
4423 { 4302 {
4424 K = CUR.stack[CUR.args - L]; 4303 K = CUR.stack[CUR.args - L];
4425 4304
4426 FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ], 4305 FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
4427 &CUR.stack[CUR.args - L + 1], 4306 &CUR.stack[CUR.args - L + 1],
4428 ( L - 1 ) ); 4307 ( L - 1 ) );
4429 4308
4430 CUR.stack[CUR.args - 1] = K; 4309 CUR.stack[CUR.args - 1] = K;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
4480 if ( CUR.IP + 1 >= CUR.codeSize ) 4359 if ( CUR.IP + 1 >= CUR.codeSize )
4481 goto Fail_Overflow; 4360 goto Fail_Overflow;
4482 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1]; 4361 CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
4483 } 4362 }
4484 4363
4485 if ( CUR.IP + CUR.length <= CUR.codeSize ) 4364 if ( CUR.IP + CUR.length <= CUR.codeSize )
4486 return SUCCESS; 4365 return SUCCESS;
4487 } 4366 }
4488 4367
4489 Fail_Overflow: 4368 Fail_Overflow:
4490 CUR.error = TT_Err_Code_Overflow; 4369 CUR.error = FT_THROW( Code_Overflow );
4491 return FAILURE; 4370 return FAILURE;
4492 } 4371 }
4493 4372
4494 4373
4495 /*************************************************************************/ 4374 /*************************************************************************/
4496 /* */ 4375 /* */
4497 /* IF[]: IF test */ 4376 /* IF[]: IF test */
4498 /* Opcode range: 0x58 */ 4377 /* Opcode range: 0x58 */
4499 /* Stack: StkElt --> */ 4378 /* Stack: StkElt --> */
4500 /* */ 4379 /* */
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
4585 /* Opcode range: 0x2C */ 4464 /* Opcode range: 0x2C */
4586 /* Stack: uint32 --> */ 4465 /* Stack: uint32 --> */
4587 /* */ 4466 /* */
4588 static void 4467 static void
4589 Ins_FDEF( INS_ARG ) 4468 Ins_FDEF( INS_ARG )
4590 { 4469 {
4591 FT_ULong n; 4470 FT_ULong n;
4592 TT_DefRecord* rec; 4471 TT_DefRecord* rec;
4593 TT_DefRecord* limit; 4472 TT_DefRecord* limit;
4594 4473
4474 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
4475 /* arguments to opcodes are skipped by `SKIP_Code' */
4476 FT_Byte opcode_pattern[9][12] = {
4477 /* #0 inline delta function 1 */
4478 {
4479 0x4B, /* PPEM */
4480 0x53, /* GTEQ */
4481 0x23, /* SWAP */
4482 0x4B, /* PPEM */
4483 0x51, /* LTEQ */
4484 0x5A, /* AND */
4485 0x58, /* IF */
4486 0x38, /* SHPIX */
4487 0x1B, /* ELSE */
4488 0x21, /* POP */
4489 0x21, /* POP */
4490 0x59 /* EIF */
4491 },
4492 /* #1 inline delta function 2 */
4493 {
4494 0x4B, /* PPEM */
4495 0x54, /* EQ */
4496 0x58, /* IF */
4497 0x38, /* SHPIX */
4498 0x1B, /* ELSE */
4499 0x21, /* POP */
4500 0x21, /* POP */
4501 0x59 /* EIF */
4502 },
4503 /* #2 diagonal stroke function */
4504 {
4505 0x20, /* DUP */
4506 0x20, /* DUP */
4507 0xB0, /* PUSHB_1 */
4508 /* 1 */
4509 0x60, /* ADD */
4510 0x46, /* GC_cur */
4511 0xB0, /* PUSHB_1 */
4512 /* 64 */
4513 0x23, /* SWAP */
4514 0x42 /* WS */
4515 },
4516 /* #3 VacuFormRound function */
4517 {
4518 0x45, /* RCVT */
4519 0x23, /* SWAP */
4520 0x46, /* GC_cur */
4521 0x60, /* ADD */
4522 0x20, /* DUP */
4523 0xB0 /* PUSHB_1 */
4524 /* 38 */
4525 },
4526 /* #4 TTFautohint bytecode (old) */
4527 {
4528 0x20, /* DUP */
4529 0x64, /* ABS */
4530 0xB0, /* PUSHB_1 */
4531 /* 32 */
4532 0x60, /* ADD */
4533 0x66, /* FLOOR */
4534 0x23, /* SWAP */
4535 0xB0 /* PUSHB_1 */
4536 },
4537 /* #5 spacing function 1 */
4538 {
4539 0x01, /* SVTCA_x */
4540 0xB0, /* PUSHB_1 */
4541 /* 24 */
4542 0x43, /* RS */
4543 0x58 /* IF */
4544 },
4545 /* #6 spacing function 2 */
4546 {
4547 0x01, /* SVTCA_x */
4548 0x18, /* RTG */
4549 0xB0, /* PUSHB_1 */
4550 /* 24 */
4551 0x43, /* RS */
4552 0x58 /* IF */
4553 },
4554 /* #7 TypeMan Talk DiagEndCtrl function */
4555 {
4556 0x01, /* SVTCA_x */
4557 0x20, /* DUP */
4558 0xB0, /* PUSHB_1 */
4559 /* 3 */
4560 0x25, /* CINDEX */
4561 },
4562 /* #8 TypeMan Talk Align */
4563 {
4564 0x06, /* SPVTL */
4565 0x7D, /* RDTG */
4566 },
4567 };
4568 FT_UShort opcode_patterns = 9;
4569 FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
4570 FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
4571 FT_UShort i;
4572 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
4573
4595 4574
4596 /* some font programs are broken enough to redefine functions! */ 4575 /* some font programs are broken enough to redefine functions! */
4597 /* We will then parse the current table. */ 4576 /* We will then parse the current table. */
4598 4577
4599 rec = CUR.FDefs; 4578 rec = CUR.FDefs;
4600 limit = rec + CUR.numFDefs; 4579 limit = rec + CUR.numFDefs;
4601 n = args[0]; 4580 n = args[0];
4602 4581
4603 for ( ; rec < limit; rec++ ) 4582 for ( ; rec < limit; rec++ )
4604 { 4583 {
4605 if ( rec->opc == n ) 4584 if ( rec->opc == n )
4606 break; 4585 break;
4607 } 4586 }
4608 4587
4609 if ( rec == limit ) 4588 if ( rec == limit )
4610 { 4589 {
4611 /* check that there is enough room for new functions */ 4590 /* check that there is enough room for new functions */
4612 if ( CUR.numFDefs >= CUR.maxFDefs ) 4591 if ( CUR.numFDefs >= CUR.maxFDefs )
4613 { 4592 {
4614 CUR.error = TT_Err_Too_Many_Function_Defs; 4593 CUR.error = FT_THROW( Too_Many_Function_Defs );
4615 return; 4594 return;
4616 } 4595 }
4617 CUR.numFDefs++; 4596 CUR.numFDefs++;
4618 } 4597 }
4619 4598
4620 /* Although FDEF takes unsigned 32-bit integer, */ 4599 /* Although FDEF takes unsigned 32-bit integer, */
4621 /* func # must be within unsigned 16-bit integer */ 4600 /* func # must be within unsigned 16-bit integer */
4622 if ( n > 0xFFFFU ) 4601 if ( n > 0xFFFFU )
4623 { 4602 {
4624 CUR.error = TT_Err_Too_Many_Function_Defs; 4603 CUR.error = FT_THROW( Too_Many_Function_Defs );
4625 return; 4604 return;
4626 } 4605 }
4627 4606
4628 rec->range = CUR.curRange; 4607 rec->range = CUR.curRange;
4629 rec->opc = (FT_UInt16)n; 4608 rec->opc = (FT_UInt16)n;
4630 rec->start = CUR.IP + 1; 4609 rec->start = CUR.IP + 1;
4631 rec->active = TRUE; 4610 rec->active = TRUE;
4611 rec->inline_delta = FALSE;
4612 rec->sph_fdef_flags = 0x0000;
4632 4613
4633 if ( n > CUR.maxFunc ) 4614 if ( n > CUR.maxFunc )
4634 CUR.maxFunc = (FT_UInt16)n; 4615 CUR.maxFunc = (FT_UInt16)n;
4635 4616
4617 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
4618 /* We don't know for sure these are typeman functions, */
4619 /* however they are only active when RS 22 is called */
4620 if ( n >= 64 && n <= 66 )
4621 rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES;
4622 #endif
4623
4636 /* Now skip the whole function definition. */ 4624 /* Now skip the whole function definition. */
4637 /* We don't allow nested IDEFS & FDEFs. */ 4625 /* We don't allow nested IDEFS & FDEFs. */
4638 4626
4639 while ( SKIP_Code() == SUCCESS ) 4627 while ( SKIP_Code() == SUCCESS )
4640 { 4628 {
4629
4630 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
4631
4632 if ( SUBPIXEL_HINTING )
4633 {
4634 for ( i = 0; i < opcode_patterns; i++ )
4635 {
4636 if ( opcode_pointer[i] < opcode_size[i] &&
4637 CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
4638 {
4639 opcode_pointer[i] += 1;
4640
4641 if ( opcode_pointer[i] == opcode_size[i] )
4642 {
4643 FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
4644 i, n,
4645 CUR.face->root.family_name,
4646 CUR.face->root.style_name ));
4647
4648 switch ( i )
4649 {
4650 case 0:
4651 rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1;
4652 CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
4653 break;
4654
4655 case 1:
4656 rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2;
4657 CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
4658 break;
4659
4660 case 2:
4661 switch ( n )
4662 {
4663 /* needs to be implemented still */
4664 case 58:
4665 rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE;
4666 CUR.face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
4667 }
4668 break;
4669
4670 case 3:
4671 switch ( n )
4672 {
4673 case 0:
4674 rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1;
4675 CUR.face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
4676 }
4677 break;
4678
4679 case 4:
4680 /* probably not necessary to detect anymore */
4681 rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1;
4682 CUR.face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
4683 break;
4684
4685 case 5:
4686 switch ( n )
4687 {
4688 case 0:
4689 case 1:
4690 case 2:
4691 case 4:
4692 case 7:
4693 case 8:
4694 rec->sph_fdef_flags |= SPH_FDEF_SPACING_1;
4695 CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
4696 }
4697 break;
4698
4699 case 6:
4700 switch ( n )
4701 {
4702 case 0:
4703 case 1:
4704 case 2:
4705 case 4:
4706 case 7:
4707 case 8:
4708 rec->sph_fdef_flags |= SPH_FDEF_SPACING_2;
4709 CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
4710 }
4711 break;
4712
4713 case 7:
4714 rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
4715 CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
4716 break;
4717
4718 case 8:
4719 #if 0
4720 rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
4721 CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
4722 #endif
4723 break;
4724 }
4725 opcode_pointer[i] = 0;
4726 }
4727 }
4728
4729 else
4730 opcode_pointer[i] = 0;
4731 }
4732
4733 /* Set sph_compatibility_mode only when deltas are detected */
4734 CUR.face->sph_compatibility_mode =
4735 ( ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
4736 ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
4737 }
4738
4739 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
4740
4641 switch ( CUR.opcode ) 4741 switch ( CUR.opcode )
4642 { 4742 {
4643 case 0x89: /* IDEF */ 4743 case 0x89: /* IDEF */
4644 case 0x2C: /* FDEF */ 4744 case 0x2C: /* FDEF */
4645 CUR.error = TT_Err_Nested_DEFS; 4745 CUR.error = FT_THROW( Nested_DEFS );
4646 return; 4746 return;
4647 4747
4648 case 0x2D: /* ENDF */ 4748 case 0x2D: /* ENDF */
4649 rec->end = CUR.IP; 4749 rec->end = CUR.IP;
4650 return; 4750 return;
4651 } 4751 }
4652 } 4752 }
4653 } 4753 }
4654 4754
4655 4755
4656 /*************************************************************************/ 4756 /*************************************************************************/
4657 /* */ 4757 /* */
4658 /* ENDF[]: END Function definition */ 4758 /* ENDF[]: END Function definition */
4659 /* Opcode range: 0x2D */ 4759 /* Opcode range: 0x2D */
4660 /* Stack: --> */ 4760 /* Stack: --> */
4661 /* */ 4761 /* */
4662 static void 4762 static void
4663 Ins_ENDF( INS_ARG ) 4763 Ins_ENDF( INS_ARG )
4664 { 4764 {
4665 TT_CallRec* pRec; 4765 TT_CallRec* pRec;
4666 4766
4667 FT_UNUSED_ARG; 4767 FT_UNUSED_ARG;
4668 4768
4669 4769
4770 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
4771 CUR.sph_in_func_flags = 0x0000;
4772 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
4773
4670 if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */ 4774 if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
4671 { 4775 {
4672 CUR.error = TT_Err_ENDF_In_Exec_Stream; 4776 CUR.error = FT_THROW( ENDF_In_Exec_Stream );
4673 return; 4777 return;
4674 } 4778 }
4675 4779
4676 CUR.callTop--; 4780 CUR.callTop--;
4677 4781
4678 pRec = &CUR.callStack[CUR.callTop]; 4782 pRec = &CUR.callStack[CUR.callTop];
4679 4783
4680 pRec->Cur_Count--; 4784 pRec->Cur_Count--;
4681 4785
4682 CUR.step_ins = FALSE; 4786 CUR.step_ins = FALSE;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4744 def++; 4848 def++;
4745 4849
4746 if ( def == limit ) 4850 if ( def == limit )
4747 goto Fail; 4851 goto Fail;
4748 } 4852 }
4749 4853
4750 /* check that the function is active */ 4854 /* check that the function is active */
4751 if ( !def->active ) 4855 if ( !def->active )
4752 goto Fail; 4856 goto Fail;
4753 4857
4858 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
4859 if ( SUBPIXEL_HINTING &&
4860 CUR.ignore_x_mode &&
4861 ( ( CUR.iup_called &&
4862 ( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
4863 ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) )
4864 goto Fail;
4865 else
4866 CUR.sph_in_func_flags = def->sph_fdef_flags;
4867 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
4868
4754 /* check the call stack */ 4869 /* check the call stack */
4755 if ( CUR.callTop >= CUR.callSize ) 4870 if ( CUR.callTop >= CUR.callSize )
4756 { 4871 {
4757 CUR.error = TT_Err_Stack_Overflow; 4872 CUR.error = FT_THROW( Stack_Overflow );
4758 return; 4873 return;
4759 } 4874 }
4760 4875
4761 pCrec = CUR.callStack + CUR.callTop; 4876 pCrec = CUR.callStack + CUR.callTop;
4762 4877
4763 pCrec->Caller_Range = CUR.curRange; 4878 pCrec->Caller_Range = CUR.curRange;
4764 pCrec->Caller_IP = CUR.IP + 1; 4879 pCrec->Caller_IP = CUR.IP + 1;
4765 pCrec->Cur_Count = 1; 4880 pCrec->Cur_Count = 1;
4766 pCrec->Cur_Restart = def->start; 4881 pCrec->Cur_Restart = def->start;
4767 pCrec->Cur_End = def->end; 4882 pCrec->Cur_End = def->end;
4768 4883
4769 CUR.callTop++; 4884 CUR.callTop++;
4770 4885
4771 INS_Goto_CodeRange( def->range, 4886 INS_Goto_CodeRange( def->range,
4772 def->start ); 4887 def->start );
4773 4888
4774 CUR.step_ins = FALSE; 4889 CUR.step_ins = FALSE;
4890
4775 return; 4891 return;
4776 4892
4777 Fail: 4893 Fail:
4778 CUR.error = TT_Err_Invalid_Reference; 4894 CUR.error = FT_THROW( Invalid_Reference );
4779 } 4895 }
4780 4896
4781 4897
4782 /*************************************************************************/ 4898 /*************************************************************************/
4783 /* */ 4899 /* */
4784 /* LOOPCALL[]: LOOP and CALL function */ 4900 /* LOOPCALL[]: LOOP and CALL function */
4785 /* Opcode range: 0x2A */ 4901 /* Opcode range: 0x2A */
4786 /* Stack: uint32? Eint16? --> */ 4902 /* Stack: uint32? Eint16? --> */
4787 /* */ 4903 /* */
4788 static void 4904 static void
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
4821 def++; 4937 def++;
4822 4938
4823 if ( def == limit ) 4939 if ( def == limit )
4824 goto Fail; 4940 goto Fail;
4825 } 4941 }
4826 4942
4827 /* check that the function is active */ 4943 /* check that the function is active */
4828 if ( !def->active ) 4944 if ( !def->active )
4829 goto Fail; 4945 goto Fail;
4830 4946
4947 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
4948 if ( SUBPIXEL_HINTING &&
4949 CUR.ignore_x_mode &&
4950 ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
4951 goto Fail;
4952 else
4953 CUR.sph_in_func_flags = def->sph_fdef_flags;
4954 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
4955
4831 /* check stack */ 4956 /* check stack */
4832 if ( CUR.callTop >= CUR.callSize ) 4957 if ( CUR.callTop >= CUR.callSize )
4833 { 4958 {
4834 CUR.error = TT_Err_Stack_Overflow; 4959 CUR.error = FT_THROW( Stack_Overflow );
4835 return; 4960 return;
4836 } 4961 }
4837 4962
4838 if ( args[0] > 0 ) 4963 if ( args[0] > 0 )
4839 { 4964 {
4840 pCrec = CUR.callStack + CUR.callTop; 4965 pCrec = CUR.callStack + CUR.callTop;
4841 4966
4842 pCrec->Caller_Range = CUR.curRange; 4967 pCrec->Caller_Range = CUR.curRange;
4843 pCrec->Caller_IP = CUR.IP + 1; 4968 pCrec->Caller_IP = CUR.IP + 1;
4844 pCrec->Cur_Count = (FT_Int)args[0]; 4969 pCrec->Cur_Count = (FT_Int)args[0];
4845 pCrec->Cur_Restart = def->start; 4970 pCrec->Cur_Restart = def->start;
4846 pCrec->Cur_End = def->end; 4971 pCrec->Cur_End = def->end;
4847 4972
4848 CUR.callTop++; 4973 CUR.callTop++;
4849 4974
4850 INS_Goto_CodeRange( def->range, def->start ); 4975 INS_Goto_CodeRange( def->range, def->start );
4851 4976
4852 CUR.step_ins = FALSE; 4977 CUR.step_ins = FALSE;
4853 } 4978 }
4979
4854 return; 4980 return;
4855 4981
4856 Fail: 4982 Fail:
4857 CUR.error = TT_Err_Invalid_Reference; 4983 CUR.error = FT_THROW( Invalid_Reference );
4858 } 4984 }
4859 4985
4860 4986
4861 /*************************************************************************/ 4987 /*************************************************************************/
4862 /* */ 4988 /* */
4863 /* IDEF[]: Instruction DEFinition */ 4989 /* IDEF[]: Instruction DEFinition */
4864 /* Opcode range: 0x89 */ 4990 /* Opcode range: 0x89 */
4865 /* Stack: Eint8 --> */ 4991 /* Stack: Eint8 --> */
4866 /* */ 4992 /* */
4867 static void 4993 static void
(...skipping 10 matching lines...) Expand all
4878 5004
4879 for ( ; def < limit; def++ ) 5005 for ( ; def < limit; def++ )
4880 if ( def->opc == (FT_ULong)args[0] ) 5006 if ( def->opc == (FT_ULong)args[0] )
4881 break; 5007 break;
4882 5008
4883 if ( def == limit ) 5009 if ( def == limit )
4884 { 5010 {
4885 /* check that there is enough room for a new instruction */ 5011 /* check that there is enough room for a new instruction */
4886 if ( CUR.numIDefs >= CUR.maxIDefs ) 5012 if ( CUR.numIDefs >= CUR.maxIDefs )
4887 { 5013 {
4888 CUR.error = TT_Err_Too_Many_Instruction_Defs; 5014 CUR.error = FT_THROW( Too_Many_Instruction_Defs );
4889 return; 5015 return;
4890 } 5016 }
4891 CUR.numIDefs++; 5017 CUR.numIDefs++;
4892 } 5018 }
4893 5019
4894 /* opcode must be unsigned 8-bit integer */ 5020 /* opcode must be unsigned 8-bit integer */
4895 if ( 0 > args[0] || args[0] > 0x00FF ) 5021 if ( 0 > args[0] || args[0] > 0x00FF )
4896 { 5022 {
4897 CUR.error = TT_Err_Too_Many_Instruction_Defs; 5023 CUR.error = FT_THROW( Too_Many_Instruction_Defs );
4898 return; 5024 return;
4899 } 5025 }
4900 5026
4901 def->opc = (FT_Byte)args[0]; 5027 def->opc = (FT_Byte)args[0];
4902 def->start = CUR.IP + 1; 5028 def->start = CUR.IP + 1;
4903 def->range = CUR.curRange; 5029 def->range = CUR.curRange;
4904 def->active = TRUE; 5030 def->active = TRUE;
4905 5031
4906 if ( (FT_ULong)args[0] > CUR.maxIns ) 5032 if ( (FT_ULong)args[0] > CUR.maxIns )
4907 CUR.maxIns = (FT_Byte)args[0]; 5033 CUR.maxIns = (FT_Byte)args[0];
4908 5034
4909 /* Now skip the whole function definition. */ 5035 /* Now skip the whole function definition. */
4910 /* We don't allow nested IDEFs & FDEFs. */ 5036 /* We don't allow nested IDEFs & FDEFs. */
4911 5037
4912 while ( SKIP_Code() == SUCCESS ) 5038 while ( SKIP_Code() == SUCCESS )
4913 { 5039 {
4914 switch ( CUR.opcode ) 5040 switch ( CUR.opcode )
4915 { 5041 {
4916 case 0x89: /* IDEF */ 5042 case 0x89: /* IDEF */
4917 case 0x2C: /* FDEF */ 5043 case 0x2C: /* FDEF */
4918 CUR.error = TT_Err_Nested_DEFS; 5044 CUR.error = FT_THROW( Nested_DEFS );
4919 return; 5045 return;
4920 case 0x2D: /* ENDF */ 5046 case 0x2D: /* ENDF */
4921 return; 5047 return;
4922 } 5048 }
4923 } 5049 }
4924 } 5050 }
4925 5051
4926 5052
4927 /*************************************************************************/ 5053 /*************************************************************************/
4928 /* */ 5054 /* */
(...skipping 13 matching lines...) Expand all
4942 static void 5068 static void
4943 Ins_NPUSHB( INS_ARG ) 5069 Ins_NPUSHB( INS_ARG )
4944 { 5070 {
4945 FT_UShort L, K; 5071 FT_UShort L, K;
4946 5072
4947 5073
4948 L = (FT_UShort)CUR.code[CUR.IP + 1]; 5074 L = (FT_UShort)CUR.code[CUR.IP + 1];
4949 5075
4950 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) 5076 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4951 { 5077 {
4952 CUR.error = TT_Err_Stack_Overflow; 5078 CUR.error = FT_THROW( Stack_Overflow );
4953 return; 5079 return;
4954 } 5080 }
4955 5081
4956 for ( K = 1; K <= L; K++ ) 5082 for ( K = 1; K <= L; K++ )
4957 args[K - 1] = CUR.code[CUR.IP + K + 1]; 5083 args[K - 1] = CUR.code[CUR.IP + K + 1];
4958 5084
4959 CUR.new_top += L; 5085 CUR.new_top += L;
4960 } 5086 }
4961 5087
4962 5088
4963 /*************************************************************************/ 5089 /*************************************************************************/
4964 /* */ 5090 /* */
4965 /* NPUSHW[]: PUSH N Words */ 5091 /* NPUSHW[]: PUSH N Words */
4966 /* Opcode range: 0x41 */ 5092 /* Opcode range: 0x41 */
4967 /* Stack: --> int32... */ 5093 /* Stack: --> int32... */
4968 /* */ 5094 /* */
4969 static void 5095 static void
4970 Ins_NPUSHW( INS_ARG ) 5096 Ins_NPUSHW( INS_ARG )
4971 { 5097 {
4972 FT_UShort L, K; 5098 FT_UShort L, K;
4973 5099
4974 5100
4975 L = (FT_UShort)CUR.code[CUR.IP + 1]; 5101 L = (FT_UShort)CUR.code[CUR.IP + 1];
4976 5102
4977 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) 5103 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
4978 { 5104 {
4979 CUR.error = TT_Err_Stack_Overflow; 5105 CUR.error = FT_THROW( Stack_Overflow );
4980 return; 5106 return;
4981 } 5107 }
4982 5108
4983 CUR.IP += 2; 5109 CUR.IP += 2;
4984 5110
4985 for ( K = 0; K < L; K++ ) 5111 for ( K = 0; K < L; K++ )
4986 args[K] = GET_ShortIns(); 5112 args[K] = GET_ShortIns();
4987 5113
4988 CUR.step_ins = FALSE; 5114 CUR.step_ins = FALSE;
4989 CUR.new_top += L; 5115 CUR.new_top += L;
4990 } 5116 }
4991 5117
4992 5118
4993 /*************************************************************************/ 5119 /*************************************************************************/
4994 /* */ 5120 /* */
4995 /* PUSHB[abc]: PUSH Bytes */ 5121 /* PUSHB[abc]: PUSH Bytes */
4996 /* Opcode range: 0xB0-0xB7 */ 5122 /* Opcode range: 0xB0-0xB7 */
4997 /* Stack: --> uint32... */ 5123 /* Stack: --> uint32... */
4998 /* */ 5124 /* */
4999 static void 5125 static void
5000 Ins_PUSHB( INS_ARG ) 5126 Ins_PUSHB( INS_ARG )
5001 { 5127 {
5002 FT_UShort L, K; 5128 FT_UShort L, K;
5003 5129
5004 5130
5005 L = (FT_UShort)( CUR.opcode - 0xB0 + 1 ); 5131 L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
5006 5132
5007 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) 5133 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
5008 { 5134 {
5009 CUR.error = TT_Err_Stack_Overflow; 5135 CUR.error = FT_THROW( Stack_Overflow );
5010 return; 5136 return;
5011 } 5137 }
5012 5138
5013 for ( K = 1; K <= L; K++ ) 5139 for ( K = 1; K <= L; K++ )
5014 args[K - 1] = CUR.code[CUR.IP + K]; 5140 args[K - 1] = CUR.code[CUR.IP + K];
5015 } 5141 }
5016 5142
5017 5143
5018 /*************************************************************************/ 5144 /*************************************************************************/
5019 /* */ 5145 /* */
5020 /* PUSHW[abc]: PUSH Words */ 5146 /* PUSHW[abc]: PUSH Words */
5021 /* Opcode range: 0xB8-0xBF */ 5147 /* Opcode range: 0xB8-0xBF */
5022 /* Stack: --> int32... */ 5148 /* Stack: --> int32... */
5023 /* */ 5149 /* */
5024 static void 5150 static void
5025 Ins_PUSHW( INS_ARG ) 5151 Ins_PUSHW( INS_ARG )
5026 { 5152 {
5027 FT_UShort L, K; 5153 FT_UShort L, K;
5028 5154
5029 5155
5030 L = (FT_UShort)( CUR.opcode - 0xB8 + 1 ); 5156 L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
5031 5157
5032 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) 5158 if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
5033 { 5159 {
5034 CUR.error = TT_Err_Stack_Overflow; 5160 CUR.error = FT_THROW( Stack_Overflow );
5035 return; 5161 return;
5036 } 5162 }
5037 5163
5038 CUR.IP++; 5164 CUR.IP++;
5039 5165
5040 for ( K = 0; K < L; K++ ) 5166 for ( K = 0; K < L; K++ )
5041 args[K] = GET_ShortIns(); 5167 args[K] = GET_ShortIns();
5042 5168
5043 CUR.step_ins = FALSE; 5169 CUR.step_ins = FALSE;
5044 } 5170 }
(...skipping 22 matching lines...) Expand all
5067 { 5193 {
5068 FT_ULong L; 5194 FT_ULong L;
5069 FT_F26Dot6 R; 5195 FT_F26Dot6 R;
5070 5196
5071 5197
5072 L = (FT_ULong)args[0]; 5198 L = (FT_ULong)args[0];
5073 5199
5074 if ( BOUNDSL( L, CUR.zp2.n_points ) ) 5200 if ( BOUNDSL( L, CUR.zp2.n_points ) )
5075 { 5201 {
5076 if ( CUR.pedantic_hinting ) 5202 if ( CUR.pedantic_hinting )
5077 CUR.error = TT_Err_Invalid_Reference; 5203 CUR.error = FT_THROW( Invalid_Reference );
5078 R = 0; 5204 R = 0;
5079 } 5205 }
5080 else 5206 else
5081 { 5207 {
5082 if ( CUR.opcode & 1 ) 5208 if ( CUR.opcode & 1 )
5083 R = CUR_fast_dualproj( &CUR.zp2.org[L] ); 5209 R = CUR_fast_dualproj( &CUR.zp2.org[L] );
5084 else 5210 else
5085 R = CUR_fast_project( &CUR.zp2.cur[L] ); 5211 R = CUR_fast_project( &CUR.zp2.cur[L] );
5086 } 5212 }
5087 5213
(...skipping 16 matching lines...) Expand all
5104 { 5230 {
5105 FT_Long K; 5231 FT_Long K;
5106 FT_UShort L; 5232 FT_UShort L;
5107 5233
5108 5234
5109 L = (FT_UShort)args[0]; 5235 L = (FT_UShort)args[0];
5110 5236
5111 if ( BOUNDS( L, CUR.zp2.n_points ) ) 5237 if ( BOUNDS( L, CUR.zp2.n_points ) )
5112 { 5238 {
5113 if ( CUR.pedantic_hinting ) 5239 if ( CUR.pedantic_hinting )
5114 CUR.error = TT_Err_Invalid_Reference; 5240 CUR.error = FT_THROW( Invalid_Reference );
5115 return; 5241 return;
5116 } 5242 }
5117 5243
5118 K = CUR_fast_project( &CUR.zp2.cur[L] ); 5244 K = CUR_fast_project( &CUR.zp2.cur[L] );
5119 5245
5120 CUR_Func_move( &CUR.zp2, L, args[1] - K ); 5246 CUR_Func_move( &CUR.zp2, L, args[1] - K );
5121 5247
5122 /* UNDOCUMENTED! The MS rasterizer does that with */ 5248 /* UNDOCUMENTED! The MS rasterizer does that with */
5123 /* twilight points (confirmed by Greg Hitchcock) */ 5249 /* twilight points (confirmed by Greg Hitchcock) */
5124 if ( CUR.GS.gep2 == 0 ) 5250 if ( CUR.GS.gep2 == 0 )
(...skipping 23 matching lines...) Expand all
5148 FT_F26Dot6 D; 5274 FT_F26Dot6 D;
5149 5275
5150 5276
5151 K = (FT_UShort)args[1]; 5277 K = (FT_UShort)args[1];
5152 L = (FT_UShort)args[0]; 5278 L = (FT_UShort)args[0];
5153 5279
5154 if ( BOUNDS( L, CUR.zp0.n_points ) || 5280 if ( BOUNDS( L, CUR.zp0.n_points ) ||
5155 BOUNDS( K, CUR.zp1.n_points ) ) 5281 BOUNDS( K, CUR.zp1.n_points ) )
5156 { 5282 {
5157 if ( CUR.pedantic_hinting ) 5283 if ( CUR.pedantic_hinting )
5158 CUR.error = TT_Err_Invalid_Reference; 5284 CUR.error = FT_THROW( Invalid_Reference );
5159 D = 0; 5285 D = 0;
5160 } 5286 }
5161 else 5287 else
5162 { 5288 {
5163 if ( CUR.opcode & 1 ) 5289 if ( CUR.opcode & 1 )
5164 D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K ); 5290 D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
5165 else 5291 else
5166 { 5292 {
5167 /* XXX: UNDOCUMENTED: twilight zone special case */ 5293 /* XXX: UNDOCUMENTED: twilight zone special case */
5168 5294
5169 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 ) 5295 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
5170 { 5296 {
5171 FT_Vector* vec1 = CUR.zp0.org + L; 5297 FT_Vector* vec1 = CUR.zp0.org + L;
5172 FT_Vector* vec2 = CUR.zp1.org + K; 5298 FT_Vector* vec2 = CUR.zp1.org + K;
5173 5299
5174 5300
5175 D = CUR_Func_dualproj( vec1, vec2 ); 5301 D = CUR_Func_dualproj( vec1, vec2 );
5176 } 5302 }
5177 else 5303 else
5178 { 5304 {
5179 FT_Vector* vec1 = CUR.zp0.orus + L; 5305 FT_Vector* vec1 = CUR.zp0.orus + L;
5180 FT_Vector* vec2 = CUR.zp1.orus + K; 5306 FT_Vector* vec2 = CUR.zp1.orus + K;
5181 5307
5182 5308
5183 if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) 5309 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
5184 { 5310 {
5185 /* this should be faster */ 5311 /* this should be faster */
5186 D = CUR_Func_dualproj( vec1, vec2 ); 5312 D = CUR_Func_dualproj( vec1, vec2 );
5187 D = TT_MULFIX( D, CUR.metrics.x_scale ); 5313 D = FT_MulFix( D, CUR.metrics.x_scale );
5188 } 5314 }
5189 else 5315 else
5190 { 5316 {
5191 FT_Vector vec; 5317 FT_Vector vec;
5192 5318
5193 5319
5194 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale ); 5320 vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
5195 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale ); 5321 vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
5196 5322
5197 D = CUR_fast_dualproj( &vec ); 5323 D = CUR_fast_dualproj( &vec );
5198 } 5324 }
5199 } 5325 }
5200 } 5326 }
5201 } 5327 }
5202 5328
5329 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
5330 /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
5331 if ( SUBPIXEL_HINTING &&
5332 CUR.ignore_x_mode && FT_ABS( D ) == 64 )
5333 D += 1;
5334 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
5335
5203 args[0] = D; 5336 args[0] = D;
5204 } 5337 }
5205 5338
5206 5339
5207 /*************************************************************************/ 5340 /*************************************************************************/
5208 /* */ 5341 /* */
5209 /* SDPVTL[a]: Set Dual PVector to Line */ 5342 /* SDPVTL[a]: Set Dual PVector to Line */
5210 /* Opcode range: 0x86-0x87 */ 5343 /* Opcode range: 0x86-0x87 */
5211 /* Stack: uint32 uint32 --> */ 5344 /* Stack: uint32 uint32 --> */
5212 /* */ 5345 /* */
5213 static void 5346 static void
5214 Ins_SDPVTL( INS_ARG ) 5347 Ins_SDPVTL( INS_ARG )
5215 { 5348 {
5216 FT_Long A, B, C; 5349 FT_Long A, B, C;
5217 FT_UShort p1, p2; /* was FT_Int in pas type ERROR */ 5350 FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
5218 FT_Int aOpc = CUR.opcode; 5351 FT_Int aOpc = CUR.opcode;
5219 5352
5220 5353
5221 p1 = (FT_UShort)args[1]; 5354 p1 = (FT_UShort)args[1];
5222 p2 = (FT_UShort)args[0]; 5355 p2 = (FT_UShort)args[0];
5223 5356
5224 if ( BOUNDS( p2, CUR.zp1.n_points ) || 5357 if ( BOUNDS( p2, CUR.zp1.n_points ) ||
5225 BOUNDS( p1, CUR.zp2.n_points ) ) 5358 BOUNDS( p1, CUR.zp2.n_points ) )
5226 { 5359 {
5227 if ( CUR.pedantic_hinting ) 5360 if ( CUR.pedantic_hinting )
5228 CUR.error = TT_Err_Invalid_Reference; 5361 CUR.error = FT_THROW( Invalid_Reference );
5229 return; 5362 return;
5230 } 5363 }
5231 5364
5232 { 5365 {
5233 FT_Vector* v1 = CUR.zp1.org + p2; 5366 FT_Vector* v1 = CUR.zp1.org + p2;
5234 FT_Vector* v2 = CUR.zp2.org + p1; 5367 FT_Vector* v2 = CUR.zp2.org + p1;
5235 5368
5236 5369
5237 A = v1->x - v2->x; 5370 A = v1->x - v2->x;
5238 B = v1->y - v2->y; 5371 B = v1->y - v2->y;
(...skipping 19 matching lines...) Expand all
5258 5391
5259 NORMalize( A, B, &CUR.GS.dualVector ); 5392 NORMalize( A, B, &CUR.GS.dualVector );
5260 5393
5261 { 5394 {
5262 FT_Vector* v1 = CUR.zp1.cur + p2; 5395 FT_Vector* v1 = CUR.zp1.cur + p2;
5263 FT_Vector* v2 = CUR.zp2.cur + p1; 5396 FT_Vector* v2 = CUR.zp2.cur + p1;
5264 5397
5265 5398
5266 A = v1->x - v2->x; 5399 A = v1->x - v2->x;
5267 B = v1->y - v2->y; 5400 B = v1->y - v2->y;
5401
5402 if ( A == 0 && B == 0 )
5403 {
5404 A = 0x4000;
5405 aOpc = 0;
5406 }
5268 } 5407 }
5269 5408
5270 if ( ( aOpc & 1 ) != 0 ) 5409 if ( ( aOpc & 1 ) != 0 )
5271 { 5410 {
5272 C = B; /* counter clockwise rotation */ 5411 C = B; /* counter clockwise rotation */
5273 B = A; 5412 B = A;
5274 A = -C; 5413 A = -C;
5275 } 5414 }
5276 5415
5277 NORMalize( A, B, &CUR.GS.projVector ); 5416 NORMalize( A, B, &CUR.GS.projVector );
(...skipping 18 matching lines...) Expand all
5296 case 0: 5435 case 0:
5297 CUR.zp0 = CUR.twilight; 5436 CUR.zp0 = CUR.twilight;
5298 break; 5437 break;
5299 5438
5300 case 1: 5439 case 1:
5301 CUR.zp0 = CUR.pts; 5440 CUR.zp0 = CUR.pts;
5302 break; 5441 break;
5303 5442
5304 default: 5443 default:
5305 if ( CUR.pedantic_hinting ) 5444 if ( CUR.pedantic_hinting )
5306 CUR.error = TT_Err_Invalid_Reference; 5445 CUR.error = FT_THROW( Invalid_Reference );
5307 return; 5446 return;
5308 } 5447 }
5309 5448
5310 CUR.GS.gep0 = (FT_UShort)args[0]; 5449 CUR.GS.gep0 = (FT_UShort)args[0];
5311 } 5450 }
5312 5451
5313 5452
5314 /*************************************************************************/ 5453 /*************************************************************************/
5315 /* */ 5454 /* */
5316 /* SZP1[]: Set Zone Pointer 1 */ 5455 /* SZP1[]: Set Zone Pointer 1 */
5317 /* Opcode range: 0x14 */ 5456 /* Opcode range: 0x14 */
5318 /* Stack: uint32 --> */ 5457 /* Stack: uint32 --> */
5319 /* */ 5458 /* */
5320 static void 5459 static void
5321 Ins_SZP1( INS_ARG ) 5460 Ins_SZP1( INS_ARG )
5322 { 5461 {
5323 switch ( (FT_Int)args[0] ) 5462 switch ( (FT_Int)args[0] )
5324 { 5463 {
5325 case 0: 5464 case 0:
5326 CUR.zp1 = CUR.twilight; 5465 CUR.zp1 = CUR.twilight;
5327 break; 5466 break;
5328 5467
5329 case 1: 5468 case 1:
5330 CUR.zp1 = CUR.pts; 5469 CUR.zp1 = CUR.pts;
5331 break; 5470 break;
5332 5471
5333 default: 5472 default:
5334 if ( CUR.pedantic_hinting ) 5473 if ( CUR.pedantic_hinting )
5335 CUR.error = TT_Err_Invalid_Reference; 5474 CUR.error = FT_THROW( Invalid_Reference );
5336 return; 5475 return;
5337 } 5476 }
5338 5477
5339 CUR.GS.gep1 = (FT_UShort)args[0]; 5478 CUR.GS.gep1 = (FT_UShort)args[0];
5340 } 5479 }
5341 5480
5342 5481
5343 /*************************************************************************/ 5482 /*************************************************************************/
5344 /* */ 5483 /* */
5345 /* SZP2[]: Set Zone Pointer 2 */ 5484 /* SZP2[]: Set Zone Pointer 2 */
5346 /* Opcode range: 0x15 */ 5485 /* Opcode range: 0x15 */
5347 /* Stack: uint32 --> */ 5486 /* Stack: uint32 --> */
5348 /* */ 5487 /* */
5349 static void 5488 static void
5350 Ins_SZP2( INS_ARG ) 5489 Ins_SZP2( INS_ARG )
5351 { 5490 {
5352 switch ( (FT_Int)args[0] ) 5491 switch ( (FT_Int)args[0] )
5353 { 5492 {
5354 case 0: 5493 case 0:
5355 CUR.zp2 = CUR.twilight; 5494 CUR.zp2 = CUR.twilight;
5356 break; 5495 break;
5357 5496
5358 case 1: 5497 case 1:
5359 CUR.zp2 = CUR.pts; 5498 CUR.zp2 = CUR.pts;
5360 break; 5499 break;
5361 5500
5362 default: 5501 default:
5363 if ( CUR.pedantic_hinting ) 5502 if ( CUR.pedantic_hinting )
5364 CUR.error = TT_Err_Invalid_Reference; 5503 CUR.error = FT_THROW( Invalid_Reference );
5365 return; 5504 return;
5366 } 5505 }
5367 5506
5368 CUR.GS.gep2 = (FT_UShort)args[0]; 5507 CUR.GS.gep2 = (FT_UShort)args[0];
5369 } 5508 }
5370 5509
5371 5510
5372 /*************************************************************************/ 5511 /*************************************************************************/
5373 /* */ 5512 /* */
5374 /* SZPS[]: Set Zone PointerS */ 5513 /* SZPS[]: Set Zone PointerS */
5375 /* Opcode range: 0x16 */ 5514 /* Opcode range: 0x16 */
5376 /* Stack: uint32 --> */ 5515 /* Stack: uint32 --> */
5377 /* */ 5516 /* */
5378 static void 5517 static void
5379 Ins_SZPS( INS_ARG ) 5518 Ins_SZPS( INS_ARG )
5380 { 5519 {
5381 switch ( (FT_Int)args[0] ) 5520 switch ( (FT_Int)args[0] )
5382 { 5521 {
5383 case 0: 5522 case 0:
5384 CUR.zp0 = CUR.twilight; 5523 CUR.zp0 = CUR.twilight;
5385 break; 5524 break;
5386 5525
5387 case 1: 5526 case 1:
5388 CUR.zp0 = CUR.pts; 5527 CUR.zp0 = CUR.pts;
5389 break; 5528 break;
5390 5529
5391 default: 5530 default:
5392 if ( CUR.pedantic_hinting ) 5531 if ( CUR.pedantic_hinting )
5393 CUR.error = TT_Err_Invalid_Reference; 5532 CUR.error = FT_THROW( Invalid_Reference );
5394 return; 5533 return;
5395 } 5534 }
5396 5535
5397 CUR.zp1 = CUR.zp0; 5536 CUR.zp1 = CUR.zp0;
5398 CUR.zp2 = CUR.zp0; 5537 CUR.zp2 = CUR.zp0;
5399 5538
5400 CUR.GS.gep0 = (FT_UShort)args[0]; 5539 CUR.GS.gep0 = (FT_UShort)args[0];
5401 CUR.GS.gep1 = (FT_UShort)args[0]; 5540 CUR.GS.gep1 = (FT_UShort)args[0];
5402 CUR.GS.gep2 = (FT_UShort)args[0]; 5541 CUR.GS.gep2 = (FT_UShort)args[0];
5403 } 5542 }
(...skipping 10 matching lines...) Expand all
5414 { 5553 {
5415 FT_Long K, L; 5554 FT_Long K, L;
5416 5555
5417 5556
5418 K = args[1]; 5557 K = args[1];
5419 L = args[0]; 5558 L = args[0];
5420 5559
5421 if ( K < 1 || K > 2 ) 5560 if ( K < 1 || K > 2 )
5422 { 5561 {
5423 if ( CUR.pedantic_hinting ) 5562 if ( CUR.pedantic_hinting )
5424 CUR.error = TT_Err_Invalid_Reference; 5563 CUR.error = FT_THROW( Invalid_Reference );
5425 return; 5564 return;
5426 } 5565 }
5427 5566
5428 if ( L != 0 ) 5567 if ( L != 0 )
5429 L = K; 5568 L = K;
5430 5569
5431 CUR.GS.instruct_control = FT_BOOL( 5570 CUR.GS.instruct_control = FT_BOOL(
5432 ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L ); 5571 ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
5433 } 5572 }
5434 5573
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
5512 Ins_FLIPPT( INS_ARG ) 5651 Ins_FLIPPT( INS_ARG )
5513 { 5652 {
5514 FT_UShort point; 5653 FT_UShort point;
5515 5654
5516 FT_UNUSED_ARG; 5655 FT_UNUSED_ARG;
5517 5656
5518 5657
5519 if ( CUR.top < CUR.GS.loop ) 5658 if ( CUR.top < CUR.GS.loop )
5520 { 5659 {
5521 if ( CUR.pedantic_hinting ) 5660 if ( CUR.pedantic_hinting )
5522 CUR.error = TT_Err_Too_Few_Arguments; 5661 CUR.error = FT_THROW( Too_Few_Arguments );
5523 goto Fail; 5662 goto Fail;
5524 } 5663 }
5525 5664
5526 while ( CUR.GS.loop > 0 ) 5665 while ( CUR.GS.loop > 0 )
5527 { 5666 {
5528 CUR.args--; 5667 CUR.args--;
5529 5668
5530 point = (FT_UShort)CUR.stack[CUR.args]; 5669 point = (FT_UShort)CUR.stack[CUR.args];
5531 5670
5532 if ( BOUNDS( point, CUR.pts.n_points ) ) 5671 if ( BOUNDS( point, CUR.pts.n_points ) )
5533 { 5672 {
5534 if ( CUR.pedantic_hinting ) 5673 if ( CUR.pedantic_hinting )
5535 { 5674 {
5536 CUR.error = TT_Err_Invalid_Reference; 5675 CUR.error = FT_THROW( Invalid_Reference );
5537 return; 5676 return;
5538 } 5677 }
5539 } 5678 }
5540 else 5679 else
5541 CUR.pts.tags[point] ^= FT_CURVE_TAG_ON; 5680 CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
5542 5681
5543 CUR.GS.loop--; 5682 CUR.GS.loop--;
5544 } 5683 }
5545 5684
5546 Fail: 5685 Fail:
(...skipping 14 matching lines...) Expand all
5561 FT_UShort I, K, L; 5700 FT_UShort I, K, L;
5562 5701
5563 5702
5564 K = (FT_UShort)args[1]; 5703 K = (FT_UShort)args[1];
5565 L = (FT_UShort)args[0]; 5704 L = (FT_UShort)args[0];
5566 5705
5567 if ( BOUNDS( K, CUR.pts.n_points ) || 5706 if ( BOUNDS( K, CUR.pts.n_points ) ||
5568 BOUNDS( L, CUR.pts.n_points ) ) 5707 BOUNDS( L, CUR.pts.n_points ) )
5569 { 5708 {
5570 if ( CUR.pedantic_hinting ) 5709 if ( CUR.pedantic_hinting )
5571 CUR.error = TT_Err_Invalid_Reference; 5710 CUR.error = FT_THROW( Invalid_Reference );
5572 return; 5711 return;
5573 } 5712 }
5574 5713
5575 for ( I = L; I <= K; I++ ) 5714 for ( I = L; I <= K; I++ )
5576 CUR.pts.tags[I] |= FT_CURVE_TAG_ON; 5715 CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
5577 } 5716 }
5578 5717
5579 5718
5580 /*************************************************************************/ 5719 /*************************************************************************/
5581 /* */ 5720 /* */
5582 /* FLIPRGOFF: FLIP RanGe OFF */ 5721 /* FLIPRGOFF: FLIP RanGe OFF */
5583 /* Opcode range: 0x82 */ 5722 /* Opcode range: 0x82 */
5584 /* Stack: uint32 uint32 --> */ 5723 /* Stack: uint32 uint32 --> */
5585 /* */ 5724 /* */
5586 static void 5725 static void
5587 Ins_FLIPRGOFF( INS_ARG ) 5726 Ins_FLIPRGOFF( INS_ARG )
5588 { 5727 {
5589 FT_UShort I, K, L; 5728 FT_UShort I, K, L;
5590 5729
5591 5730
5592 K = (FT_UShort)args[1]; 5731 K = (FT_UShort)args[1];
5593 L = (FT_UShort)args[0]; 5732 L = (FT_UShort)args[0];
5594 5733
5595 if ( BOUNDS( K, CUR.pts.n_points ) || 5734 if ( BOUNDS( K, CUR.pts.n_points ) ||
5596 BOUNDS( L, CUR.pts.n_points ) ) 5735 BOUNDS( L, CUR.pts.n_points ) )
5597 { 5736 {
5598 if ( CUR.pedantic_hinting ) 5737 if ( CUR.pedantic_hinting )
5599 CUR.error = TT_Err_Invalid_Reference; 5738 CUR.error = FT_THROW( Invalid_Reference );
5600 return; 5739 return;
5601 } 5740 }
5602 5741
5603 for ( I = L; I <= K; I++ ) 5742 for ( I = L; I <= K; I++ )
5604 CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON; 5743 CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
5605 } 5744 }
5606 5745
5607 5746
5608 static FT_Bool 5747 static FT_Bool
5609 Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x, 5748 Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
(...skipping 13 matching lines...) Expand all
5623 } 5762 }
5624 else 5763 else
5625 { 5764 {
5626 zp = CUR.zp1; 5765 zp = CUR.zp1;
5627 p = CUR.GS.rp2; 5766 p = CUR.GS.rp2;
5628 } 5767 }
5629 5768
5630 if ( BOUNDS( p, zp.n_points ) ) 5769 if ( BOUNDS( p, zp.n_points ) )
5631 { 5770 {
5632 if ( CUR.pedantic_hinting ) 5771 if ( CUR.pedantic_hinting )
5633 CUR.error = TT_Err_Invalid_Reference; 5772 CUR.error = FT_THROW( Invalid_Reference );
5634 *refp = 0; 5773 *refp = 0;
5635 return FAILURE; 5774 return FAILURE;
5636 } 5775 }
5637 5776
5638 *zone = zp; 5777 *zone = zp;
5639 *refp = p; 5778 *refp = p;
5640 5779
5641 d = CUR_Func_project( zp.cur + p, zp.org + p ); 5780 d = CUR_Func_project( zp.cur + p, zp.org + p );
5642 5781
5643 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 5782 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
5644 if ( CUR.face->unpatented_hinting ) 5783 if ( CUR.face->unpatented_hinting )
5645 { 5784 {
5646 if ( CUR.GS.both_x_axis ) 5785 if ( CUR.GS.both_x_axis )
5647 { 5786 {
5648 *x = d; 5787 *x = d;
5649 *y = 0; 5788 *y = 0;
5650 } 5789 }
5651 else 5790 else
5652 { 5791 {
5653 *x = 0; 5792 *x = 0;
5654 *y = d; 5793 *y = d;
5655 } 5794 }
5656 } 5795 }
5657 else 5796 else
5658 #endif 5797 #endif
5659 { 5798 {
5660 *x = TT_MULDIV( d, 5799 *x = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.x, CUR.F_dot_P );
5661 (FT_Long)CUR.GS.freeVector.x * 0x10000L, 5800 *y = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.y, CUR.F_dot_P );
5662 CUR.F_dot_P );
5663 *y = TT_MULDIV( d,
5664 (FT_Long)CUR.GS.freeVector.y * 0x10000L,
5665 CUR.F_dot_P );
5666 } 5801 }
5667 5802
5668 return SUCCESS; 5803 return SUCCESS;
5669 } 5804 }
5670 5805
5671 5806
5672 static void 5807 static void
5673 Move_Zp2_Point( EXEC_OP_ FT_UShort point, 5808 Move_Zp2_Point( EXEC_OP_ FT_UShort point,
5674 FT_F26Dot6 dx, 5809 FT_F26Dot6 dx,
5675 FT_F26Dot6 dy, 5810 FT_F26Dot6 dy,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
5725 FT_F26Dot6 dx, 5860 FT_F26Dot6 dx,
5726 dy; 5861 dy;
5727 FT_UShort point; 5862 FT_UShort point;
5728 5863
5729 FT_UNUSED_ARG; 5864 FT_UNUSED_ARG;
5730 5865
5731 5866
5732 if ( CUR.top < CUR.GS.loop ) 5867 if ( CUR.top < CUR.GS.loop )
5733 { 5868 {
5734 if ( CUR.pedantic_hinting ) 5869 if ( CUR.pedantic_hinting )
5735 CUR.error = TT_Err_Invalid_Reference; 5870 CUR.error = FT_THROW( Invalid_Reference );
5736 goto Fail; 5871 goto Fail;
5737 } 5872 }
5738 5873
5739 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) 5874 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5740 return; 5875 return;
5741 5876
5742 while ( CUR.GS.loop > 0 ) 5877 while ( CUR.GS.loop > 0 )
5743 { 5878 {
5744 CUR.args--; 5879 CUR.args--;
5745 point = (FT_UShort)CUR.stack[CUR.args]; 5880 point = (FT_UShort)CUR.stack[CUR.args];
5746 5881
5747 if ( BOUNDS( point, CUR.zp2.n_points ) ) 5882 if ( BOUNDS( point, CUR.zp2.n_points ) )
5748 { 5883 {
5749 if ( CUR.pedantic_hinting ) 5884 if ( CUR.pedantic_hinting )
5750 { 5885 {
5751 CUR.error = TT_Err_Invalid_Reference; 5886 CUR.error = FT_THROW( Invalid_Reference );
5752 return; 5887 return;
5753 } 5888 }
5754 } 5889 }
5755 else 5890 else
5891 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
5892 /* doesn't follow Cleartype spec but produces better result */
5893 if ( SUBPIXEL_HINTING &&
5894 CUR.ignore_x_mode )
5895 MOVE_Zp2_Point( point, 0, dy, TRUE );
5896 else
5897 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
5756 MOVE_Zp2_Point( point, dx, dy, TRUE ); 5898 MOVE_Zp2_Point( point, dx, dy, TRUE );
5757 5899
5758 CUR.GS.loop--; 5900 CUR.GS.loop--;
5759 } 5901 }
5760 5902
5761 Fail: 5903 Fail:
5762 CUR.GS.loop = 1; 5904 CUR.GS.loop = 1;
5763 CUR.new_top = CUR.args; 5905 CUR.new_top = CUR.args;
5764 } 5906 }
5765 5907
5766 5908
5767 /*************************************************************************/ 5909 /*************************************************************************/
5768 /* */ 5910 /* */
5769 /* SHC[a]: SHift Contour */ 5911 /* SHC[a]: SHift Contour */
5770 /* Opcode range: 0x34-35 */ 5912 /* Opcode range: 0x34-35 */
5771 /* Stack: uint32 --> */ 5913 /* Stack: uint32 --> */
5772 /* */ 5914 /* */
5773 /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */ 5915 /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */
5774 /* contour in the twilight zone, namely contour number */ 5916 /* contour in the twilight zone, namely contour number */
5775 /* zero. */ 5917 /* zero which includes all points of it. */
5776 /* */ 5918 /* */
5777 static void 5919 static void
5778 Ins_SHC( INS_ARG ) 5920 Ins_SHC( INS_ARG )
5779 { 5921 {
5780 TT_GlyphZoneRec zp; 5922 TT_GlyphZoneRec zp;
5781 FT_UShort refp; 5923 FT_UShort refp;
5782 FT_F26Dot6 dx, dy; 5924 FT_F26Dot6 dx, dy;
5783 5925
5784 FT_Short contour, bounds; 5926 FT_Short contour, bounds;
5785 FT_UShort start, limit, i; 5927 FT_UShort start, limit, i;
5786 5928
5787 5929
5788 contour = (FT_UShort)args[0]; 5930 contour = (FT_UShort)args[0];
5789 bounds = ( CUR.GS.gep2 == 0 ) ? 1 : CUR.zp2.n_contours; 5931 bounds = ( CUR.GS.gep2 == 0 ) ? 1 : CUR.zp2.n_contours;
5790 5932
5791 if ( BOUNDS( contour, bounds ) ) 5933 if ( BOUNDS( contour, bounds ) )
5792 { 5934 {
5793 if ( CUR.pedantic_hinting ) 5935 if ( CUR.pedantic_hinting )
5794 CUR.error = TT_Err_Invalid_Reference; 5936 CUR.error = FT_THROW( Invalid_Reference );
5795 return; 5937 return;
5796 } 5938 }
5797 5939
5798 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) 5940 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5799 return; 5941 return;
5800 5942
5801 if ( contour == 0 ) 5943 if ( contour == 0 )
5802 start = 0; 5944 start = 0;
5803 else 5945 else
5804 start = (FT_UShort)( CUR.zp2.contours[contour - 1] + 1 - 5946 start = (FT_UShort)( CUR.zp2.contours[contour - 1] + 1 -
(...skipping 27 matching lines...) Expand all
5832 FT_UShort refp; 5974 FT_UShort refp;
5833 FT_F26Dot6 dx, 5975 FT_F26Dot6 dx,
5834 dy; 5976 dy;
5835 5977
5836 FT_UShort limit, i; 5978 FT_UShort limit, i;
5837 5979
5838 5980
5839 if ( BOUNDS( args[0], 2 ) ) 5981 if ( BOUNDS( args[0], 2 ) )
5840 { 5982 {
5841 if ( CUR.pedantic_hinting ) 5983 if ( CUR.pedantic_hinting )
5842 CUR.error = TT_Err_Invalid_Reference; 5984 CUR.error = FT_THROW( Invalid_Reference );
5843 return; 5985 return;
5844 } 5986 }
5845 5987
5846 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) 5988 if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
5847 return; 5989 return;
5848 5990
5849 /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */ 5991 /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
5850 /* Twilight zone has no real contours, so use `n_points'. */ 5992 /* Twilight zone has no real contours, so use `n_points'. */
5851 /* Normal zone's `n_points' includes phantoms, so must */ 5993 /* Normal zone's `n_points' includes phantoms, so must */
5852 /* use end of last contour. */ 5994 /* use end of last contour. */
(...skipping 17 matching lines...) Expand all
5870 /* */ 6012 /* */
5871 /* SHPIX[]: SHift points by a PIXel amount */ 6013 /* SHPIX[]: SHift points by a PIXel amount */
5872 /* Opcode range: 0x38 */ 6014 /* Opcode range: 0x38 */
5873 /* Stack: f26.6 uint32... --> */ 6015 /* Stack: f26.6 uint32... --> */
5874 /* */ 6016 /* */
5875 static void 6017 static void
5876 Ins_SHPIX( INS_ARG ) 6018 Ins_SHPIX( INS_ARG )
5877 { 6019 {
5878 FT_F26Dot6 dx, dy; 6020 FT_F26Dot6 dx, dy;
5879 FT_UShort point; 6021 FT_UShort point;
6022 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6023 FT_Int B1, B2;
6024 #endif
5880 6025
5881 6026
5882 if ( CUR.top < CUR.GS.loop + 1 ) 6027 if ( CUR.top < CUR.GS.loop + 1 )
5883 { 6028 {
5884 if ( CUR.pedantic_hinting ) 6029 if ( CUR.pedantic_hinting )
5885 CUR.error = TT_Err_Invalid_Reference; 6030 CUR.error = FT_THROW( Invalid_Reference );
5886 goto Fail; 6031 goto Fail;
5887 } 6032 }
5888 6033
5889 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 6034 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
5890 if ( CUR.face->unpatented_hinting ) 6035 if ( CUR.face->unpatented_hinting )
5891 { 6036 {
5892 if ( CUR.GS.both_x_axis ) 6037 if ( CUR.GS.both_x_axis )
5893 { 6038 {
5894 dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 ); 6039 dx = (FT_UInt32)args[0];
5895 dy = 0; 6040 dy = 0;
5896 } 6041 }
5897 else 6042 else
5898 { 6043 {
5899 dx = 0; 6044 dx = 0;
5900 dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 ); 6045 dy = (FT_UInt32)args[0];
5901 } 6046 }
5902 } 6047 }
5903 else 6048 else
5904 #endif 6049 #endif
5905 { 6050 {
5906 dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x ); 6051 dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
5907 dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y ); 6052 dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
5908 } 6053 }
5909 6054
5910 while ( CUR.GS.loop > 0 ) 6055 while ( CUR.GS.loop > 0 )
5911 { 6056 {
5912 CUR.args--; 6057 CUR.args--;
5913 6058
5914 point = (FT_UShort)CUR.stack[CUR.args]; 6059 point = (FT_UShort)CUR.stack[CUR.args];
5915 6060
5916 if ( BOUNDS( point, CUR.zp2.n_points ) ) 6061 if ( BOUNDS( point, CUR.zp2.n_points ) )
5917 { 6062 {
5918 if ( CUR.pedantic_hinting ) 6063 if ( CUR.pedantic_hinting )
5919 { 6064 {
5920 CUR.error = TT_Err_Invalid_Reference; 6065 CUR.error = FT_THROW( Invalid_Reference );
5921 return; 6066 return;
5922 } 6067 }
5923 } 6068 }
5924 else 6069 else
6070 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6071 {
6072 /* If not using ignore_x_mode rendering, allow ZP2 move. */
6073 /* If inline deltas aren't allowed, skip ZP2 move. */
6074 /* If using ignore_x_mode rendering, allow ZP2 point move if: */
6075 /* - freedom vector is y and sph_compatibility_mode is off */
6076 /* - the glyph is composite and the move is in the Y direction */
6077 /* - the glyph is specifically set to allow SHPIX moves */
6078 /* - the move is on a previously Y-touched point */
6079
6080 if ( SUBPIXEL_HINTING &&
6081 CUR.ignore_x_mode )
6082 {
6083 /* save point for later comparison */
6084 if ( CUR.GS.freeVector.y != 0 )
6085 B1 = CUR.zp2.cur[point].y;
6086 else
6087 B1 = CUR.zp2.cur[point].x;
6088
6089 if ( !CUR.face->sph_compatibility_mode &&
6090 CUR.GS.freeVector.y != 0 )
6091 {
6092 MOVE_Zp2_Point( point, dx, dy, TRUE );
6093
6094 /* save new point */
6095 if ( CUR.GS.freeVector.y != 0 )
6096 {
6097 B2 = CUR.zp2.cur[point].y;
6098
6099 /* reverse any disallowed moves */
6100 if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
6101 ( B1 & 63 ) != 0 &&
6102 ( B2 & 63 ) != 0 &&
6103 B1 != B2 )
6104 MOVE_Zp2_Point( point, -dx, -dy, TRUE );
6105 }
6106 }
6107 else if ( CUR.face->sph_compatibility_mode )
6108 {
6109 if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
6110 {
6111 dx = FT_PIX_ROUND( B1 + dx ) - B1;
6112 dy = FT_PIX_ROUND( B1 + dy ) - B1;
6113 }
6114
6115 /* skip post-iup deltas */
6116 if ( CUR.iup_called &&
6117 ( ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
6118 ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
6119 goto Skip;
6120
6121 if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
6122 ( ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) ||
6123 ( CUR.zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ||
6124 ( CUR.sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) )
6125 MOVE_Zp2_Point( point, 0, dy, TRUE );
6126
6127 /* save new point */
6128 if ( CUR.GS.freeVector.y != 0 )
6129 {
6130 B2 = CUR.zp2.cur[point].y;
6131
6132 /* reverse any disallowed moves */
6133 if ( ( B1 & 63 ) == 0 &&
6134 ( B2 & 63 ) != 0 &&
6135 B1 != B2 )
6136 MOVE_Zp2_Point( point, 0, -dy, TRUE );
6137 }
6138 }
6139 else if ( CUR.sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
6140 MOVE_Zp2_Point( point, dx, dy, TRUE );
6141 }
6142 else
6143 MOVE_Zp2_Point( point, dx, dy, TRUE );
6144 }
6145
6146 Skip:
6147
6148 #else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6149
5925 MOVE_Zp2_Point( point, dx, dy, TRUE ); 6150 MOVE_Zp2_Point( point, dx, dy, TRUE );
5926 6151
6152 #endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6153
5927 CUR.GS.loop--; 6154 CUR.GS.loop--;
5928 } 6155 }
5929 6156
5930 Fail: 6157 Fail:
5931 CUR.GS.loop = 1; 6158 CUR.GS.loop = 1;
5932 CUR.new_top = CUR.args; 6159 CUR.new_top = CUR.args;
5933 } 6160 }
5934 6161
5935 6162
5936 /*************************************************************************/ 6163 /*************************************************************************/
5937 /* */ 6164 /* */
5938 /* MSIRP[a]: Move Stack Indirect Relative Position */ 6165 /* MSIRP[a]: Move Stack Indirect Relative Position */
5939 /* Opcode range: 0x3A-0x3B */ 6166 /* Opcode range: 0x3A-0x3B */
5940 /* Stack: f26.6 uint32 --> */ 6167 /* Stack: f26.6 uint32 --> */
5941 /* */ 6168 /* */
5942 static void 6169 static void
5943 Ins_MSIRP( INS_ARG ) 6170 Ins_MSIRP( INS_ARG )
5944 { 6171 {
5945 FT_UShort point; 6172 FT_UShort point;
5946 FT_F26Dot6 distance; 6173 FT_F26Dot6 distance;
5947 6174
6175 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6176 FT_F26Dot6 control_value_cutin;
6177
6178
6179 if ( SUBPIXEL_HINTING )
6180 {
6181 control_value_cutin = CUR.GS.control_value_cutin;
6182
6183 if ( CUR.ignore_x_mode &&
6184 CUR.GS.freeVector.x != 0 &&
6185 !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
6186 control_value_cutin = 0;
6187 }
6188
6189 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
5948 6190
5949 point = (FT_UShort)args[0]; 6191 point = (FT_UShort)args[0];
5950 6192
5951 if ( BOUNDS( point, CUR.zp1.n_points ) || 6193 if ( BOUNDS( point, CUR.zp1.n_points ) ||
5952 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) 6194 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
5953 { 6195 {
5954 if ( CUR.pedantic_hinting ) 6196 if ( CUR.pedantic_hinting )
5955 CUR.error = TT_Err_Invalid_Reference; 6197 CUR.error = FT_THROW( Invalid_Reference );
5956 return; 6198 return;
5957 } 6199 }
5958 6200
5959 /* UNDOCUMENTED! The MS rasterizer does that with */ 6201 /* UNDOCUMENTED! The MS rasterizer does that with */
5960 /* twilight points (confirmed by Greg Hitchcock) */ 6202 /* twilight points (confirmed by Greg Hitchcock) */
5961 if ( CUR.GS.gep1 == 0 ) 6203 if ( CUR.GS.gep1 == 0 )
5962 { 6204 {
5963 CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0]; 6205 CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
5964 CUR_Func_move_orig( &CUR.zp1, point, args[1] ); 6206 CUR_Func_move_orig( &CUR.zp1, point, args[1] );
5965 CUR.zp1.cur[point] = CUR.zp1.org[point]; 6207 CUR.zp1.cur[point] = CUR.zp1.org[point];
5966 } 6208 }
5967 6209
5968 distance = CUR_Func_project( CUR.zp1.cur + point, 6210 distance = CUR_Func_project( CUR.zp1.cur + point,
5969 CUR.zp0.cur + CUR.GS.rp0 ); 6211 CUR.zp0.cur + CUR.GS.rp0 );
5970 6212
6213 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6214 /* subpixel hinting - make MSIRP respect CVT cut-in; */
6215 if ( SUBPIXEL_HINTING &&
6216 CUR.ignore_x_mode &&
6217 CUR.GS.freeVector.x != 0 &&
6218 FT_ABS( distance - args[1] ) >= control_value_cutin )
6219 distance = args[1];
6220 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6221
5971 CUR_Func_move( &CUR.zp1, point, args[1] - distance ); 6222 CUR_Func_move( &CUR.zp1, point, args[1] - distance );
5972 6223
5973 CUR.GS.rp1 = CUR.GS.rp0; 6224 CUR.GS.rp1 = CUR.GS.rp0;
5974 CUR.GS.rp2 = point; 6225 CUR.GS.rp2 = point;
5975 6226
5976 if ( ( CUR.opcode & 1 ) != 0 ) 6227 if ( ( CUR.opcode & 1 ) != 0 )
5977 CUR.GS.rp0 = point; 6228 CUR.GS.rp0 = point;
5978 } 6229 }
5979 6230
5980 6231
5981 /*************************************************************************/ 6232 /*************************************************************************/
5982 /* */ 6233 /* */
5983 /* MDAP[a]: Move Direct Absolute Point */ 6234 /* MDAP[a]: Move Direct Absolute Point */
5984 /* Opcode range: 0x2E-0x2F */ 6235 /* Opcode range: 0x2E-0x2F */
5985 /* Stack: uint32 --> */ 6236 /* Stack: uint32 --> */
5986 /* */ 6237 /* */
5987 static void 6238 static void
5988 Ins_MDAP( INS_ARG ) 6239 Ins_MDAP( INS_ARG )
5989 { 6240 {
5990 FT_UShort point; 6241 FT_UShort point;
5991 FT_F26Dot6 cur_dist, 6242 FT_F26Dot6 cur_dist;
5992 distance; 6243 FT_F26Dot6 distance;
5993 6244
5994 6245
5995 point = (FT_UShort)args[0]; 6246 point = (FT_UShort)args[0];
5996 6247
5997 if ( BOUNDS( point, CUR.zp0.n_points ) ) 6248 if ( BOUNDS( point, CUR.zp0.n_points ) )
5998 { 6249 {
5999 if ( CUR.pedantic_hinting ) 6250 if ( CUR.pedantic_hinting )
6000 CUR.error = TT_Err_Invalid_Reference; 6251 CUR.error = FT_THROW( Invalid_Reference );
6001 return; 6252 return;
6002 } 6253 }
6003 6254
6004 if ( ( CUR.opcode & 1 ) != 0 ) 6255 if ( ( CUR.opcode & 1 ) != 0 )
6005 { 6256 {
6006 cur_dist = CUR_fast_project( &CUR.zp0.cur[point] ); 6257 cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
6007 distance = CUR_Func_round( cur_dist, 6258 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6008 CUR.tt_metrics.compensations[0] ) - cur_dist; 6259 if ( SUBPIXEL_HINTING &&
6260 CUR.ignore_x_mode &&
6261 CUR.GS.freeVector.x != 0 )
6262 distance = ROUND_None(
6263 cur_dist,
6264 CUR.tt_metrics.compensations[0] ) - cur_dist;
6265 else
6266 #endif
6267 distance = CUR_Func_round(
6268 cur_dist,
6269 CUR.tt_metrics.compensations[0] ) - cur_dist;
6009 } 6270 }
6010 else 6271 else
6011 distance = 0; 6272 distance = 0;
6012 6273
6013 CUR_Func_move( &CUR.zp0, point, distance ); 6274 CUR_Func_move( &CUR.zp0, point, distance );
6014 6275
6015 CUR.GS.rp0 = point; 6276 CUR.GS.rp0 = point;
6016 CUR.GS.rp1 = point; 6277 CUR.GS.rp1 = point;
6017 } 6278 }
6018 6279
6019 6280
6020 /*************************************************************************/ 6281 /*************************************************************************/
6021 /* */ 6282 /* */
6022 /* MIAP[a]: Move Indirect Absolute Point */ 6283 /* MIAP[a]: Move Indirect Absolute Point */
6023 /* Opcode range: 0x3E-0x3F */ 6284 /* Opcode range: 0x3E-0x3F */
6024 /* Stack: uint32 uint32 --> */ 6285 /* Stack: uint32 uint32 --> */
6025 /* */ 6286 /* */
6026 static void 6287 static void
6027 Ins_MIAP( INS_ARG ) 6288 Ins_MIAP( INS_ARG )
6028 { 6289 {
6029 FT_ULong cvtEntry; 6290 FT_ULong cvtEntry;
6030 FT_UShort point; 6291 FT_UShort point;
6031 FT_F26Dot6 distance, 6292 FT_F26Dot6 distance;
6032 org_dist; 6293 FT_F26Dot6 org_dist;
6294 FT_F26Dot6 control_value_cutin;
6033 6295
6034 6296
6035 cvtEntry = (FT_ULong)args[1]; 6297 control_value_cutin = CUR.GS.control_value_cutin;
6036 point = (FT_UShort)args[0]; 6298 cvtEntry = (FT_ULong)args[1];
6299 point = (FT_UShort)args[0];
6300
6301 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6302 if ( SUBPIXEL_HINTING &&
6303 CUR.ignore_x_mode &&
6304 CUR.GS.freeVector.x != 0 &&
6305 CUR.GS.freeVector.y == 0 &&
6306 !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
6307 control_value_cutin = 0;
6308 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6037 6309
6038 if ( BOUNDS( point, CUR.zp0.n_points ) || 6310 if ( BOUNDS( point, CUR.zp0.n_points ) ||
6039 BOUNDSL( cvtEntry, CUR.cvtSize ) ) 6311 BOUNDSL( cvtEntry, CUR.cvtSize ) )
6040 { 6312 {
6041 if ( CUR.pedantic_hinting ) 6313 if ( CUR.pedantic_hinting )
6042 CUR.error = TT_Err_Invalid_Reference; 6314 CUR.error = FT_THROW( Invalid_Reference );
6043 goto Fail; 6315 goto Fail;
6044 } 6316 }
6045 6317
6046 /* UNDOCUMENTED! */ 6318 /* UNDOCUMENTED! */
6047 /* */ 6319 /* */
6048 /* The behaviour of an MIAP instruction is quite different when used */ 6320 /* The behaviour of an MIAP instruction is quite different when used */
6049 /* in the twilight zone. */ 6321 /* in the twilight zone. */
6050 /* */ 6322 /* */
6051 /* First, no control value cut-in test is performed as it would fail */ 6323 /* 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 */ 6324 /* 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 */ 6325 /* zp0.point, is set to the absolute, unrounded distance found in the */
6054 /* CVT. */ 6326 /* CVT. */
6055 /* */ 6327 /* */
6056 /* This is used in the CVT programs of the Microsoft fonts Arial, */ 6328 /* 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 */ 6329 /* 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 */ 6330 /* allows the use of the IP instruction in the twilight zone, which */
6059 /* otherwise would be invalid according to the specification. */ 6331 /* otherwise would be invalid according to the specification. */
6060 /* */ 6332 /* */
6061 /* We implement it with a special sequence for the twilight zone. */ 6333 /* We implement it with a special sequence for the twilight zone. */
6062 /* This is a bad hack, but it seems to work. */ 6334 /* This is a bad hack, but it seems to work. */
6063 /* */ 6335 /* */
6064 /* Confirmed by Greg Hitchcock. */ 6336 /* Confirmed by Greg Hitchcock. */
6065 6337
6066 distance = CUR_Func_read_cvt( cvtEntry ); 6338 distance = CUR_Func_read_cvt( cvtEntry );
6067 6339
6068 if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */ 6340 if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
6069 { 6341 {
6070 CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, 6342 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6071 CUR.GS.freeVector.x ); 6343 /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
6344 /* Determined via experimentation and may be incorrect... */
6345 if ( !SUBPIXEL_HINTING ||
6346 ( !CUR.ignore_x_mode ||
6347 !CUR.face->sph_compatibility_mode ) )
6348 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6349 CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
6350 CUR.GS.freeVector.x );
6072 CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, 6351 CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance,
6073 CUR.GS.freeVector.y ), 6352 CUR.GS.freeVector.y ),
6074 CUR.zp0.cur[point] = CUR.zp0.org[point]; 6353 CUR.zp0.cur[point] = CUR.zp0.org[point];
6075 } 6354 }
6355 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6356 if ( SUBPIXEL_HINTING &&
6357 CUR.ignore_x_mode &&
6358 ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
6359 distance > 0 &&
6360 CUR.GS.freeVector.y != 0 )
6361 distance = 0;
6362 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6076 6363
6077 org_dist = CUR_fast_project( &CUR.zp0.cur[point] ); 6364 org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
6078 6365
6079 if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */ 6366 if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cut-in flag */
6080 { 6367 {
6081 if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin ) 6368 if ( FT_ABS( distance - org_dist ) > control_value_cutin )
6082 distance = org_dist; 6369 distance = org_dist;
6083 6370
6084 distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] ); 6371 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6372 if ( SUBPIXEL_HINTING &&
6373 CUR.ignore_x_mode &&
6374 CUR.GS.freeVector.x != 0 )
6375 distance = ROUND_None( distance,
6376 CUR.tt_metrics.compensations[0] );
6377 else
6378 #endif
6379 distance = CUR_Func_round( distance,
6380 CUR.tt_metrics.compensations[0] );
6085 } 6381 }
6086 6382
6087 CUR_Func_move( &CUR.zp0, point, distance - org_dist ); 6383 CUR_Func_move( &CUR.zp0, point, distance - org_dist );
6088 6384
6089 Fail: 6385 Fail:
6090 CUR.GS.rp0 = point; 6386 CUR.GS.rp0 = point;
6091 CUR.GS.rp1 = point; 6387 CUR.GS.rp1 = point;
6092 } 6388 }
6093 6389
6094 6390
6095 /*************************************************************************/ 6391 /*************************************************************************/
6096 /* */ 6392 /* */
6097 /* MDRP[abcde]: Move Direct Relative Point */ 6393 /* MDRP[abcde]: Move Direct Relative Point */
6098 /* Opcode range: 0xC0-0xDF */ 6394 /* Opcode range: 0xC0-0xDF */
6099 /* Stack: uint32 --> */ 6395 /* Stack: uint32 --> */
6100 /* */ 6396 /* */
6101 static void 6397 static void
6102 Ins_MDRP( INS_ARG ) 6398 Ins_MDRP( INS_ARG )
6103 { 6399 {
6104 FT_UShort point; 6400 FT_UShort point;
6105 FT_F26Dot6 org_dist, distance; 6401 FT_F26Dot6 org_dist, distance, minimum_distance;
6106 6402
6107 6403
6404 minimum_distance = CUR.GS.minimum_distance;
6405
6406 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6407 if ( SUBPIXEL_HINTING &&
6408 CUR.ignore_x_mode &&
6409 CUR.GS.freeVector.x != 0 &&
6410 !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
6411 minimum_distance = 0;
6412 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6413
6108 point = (FT_UShort)args[0]; 6414 point = (FT_UShort)args[0];
6109 6415
6110 if ( BOUNDS( point, CUR.zp1.n_points ) || 6416 if ( BOUNDS( point, CUR.zp1.n_points ) ||
6111 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) 6417 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6112 { 6418 {
6113 if ( CUR.pedantic_hinting ) 6419 if ( CUR.pedantic_hinting )
6114 CUR.error = TT_Err_Invalid_Reference; 6420 CUR.error = FT_THROW( Invalid_Reference );
6115 goto Fail; 6421 goto Fail;
6116 } 6422 }
6117 6423
6118 /* XXX: Is there some undocumented feature while in the */ 6424 /* XXX: Is there some undocumented feature while in the */
6119 /* twilight zone? */ 6425 /* twilight zone? */
6120 6426
6121 /* XXX: UNDOCUMENTED: twilight zone special case */ 6427 /* XXX: UNDOCUMENTED: twilight zone special case */
6122 6428
6123 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 ) 6429 if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
6124 { 6430 {
6125 FT_Vector* vec1 = &CUR.zp1.org[point]; 6431 FT_Vector* vec1 = &CUR.zp1.org[point];
6126 FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0]; 6432 FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
6127 6433
6128 6434
6129 org_dist = CUR_Func_dualproj( vec1, vec2 ); 6435 org_dist = CUR_Func_dualproj( vec1, vec2 );
6130 } 6436 }
6131 else 6437 else
6132 { 6438 {
6133 FT_Vector* vec1 = &CUR.zp1.orus[point]; 6439 FT_Vector* vec1 = &CUR.zp1.orus[point];
6134 FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0]; 6440 FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
6135 6441
6136 6442
6137 if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) 6443 if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
6138 { 6444 {
6139 /* this should be faster */ 6445 /* this should be faster */
6140 org_dist = CUR_Func_dualproj( vec1, vec2 ); 6446 org_dist = CUR_Func_dualproj( vec1, vec2 );
6141 org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale ); 6447 org_dist = FT_MulFix( org_dist, CUR.metrics.x_scale );
6142 } 6448 }
6143 else 6449 else
6144 { 6450 {
6145 FT_Vector vec; 6451 FT_Vector vec;
6146 6452
6147 6453
6148 vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale ); 6454 vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
6149 vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale ); 6455 vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
6150 6456
6151 org_dist = CUR_fast_dualproj( &vec ); 6457 org_dist = CUR_fast_dualproj( &vec );
6152 } 6458 }
6153 } 6459 }
6154 6460
6155 /* single width cut-in test */ 6461 /* single width cut-in test */
6156 6462
6157 if ( FT_ABS( org_dist - CUR.GS.single_width_value ) < 6463 if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
6158 CUR.GS.single_width_cutin ) 6464 CUR.GS.single_width_cutin )
6159 { 6465 {
6160 if ( org_dist >= 0 ) 6466 if ( org_dist >= 0 )
6161 org_dist = CUR.GS.single_width_value; 6467 org_dist = CUR.GS.single_width_value;
6162 else 6468 else
6163 org_dist = -CUR.GS.single_width_value; 6469 org_dist = -CUR.GS.single_width_value;
6164 } 6470 }
6165 6471
6166 /* round flag */ 6472 /* round flag */
6167 6473
6168 if ( ( CUR.opcode & 4 ) != 0 ) 6474 if ( ( CUR.opcode & 4 ) != 0 )
6475 {
6476 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6477 if ( SUBPIXEL_HINTING &&
6478 CUR.ignore_x_mode &&
6479 CUR.GS.freeVector.x != 0 )
6480 distance = ROUND_None(
6481 org_dist,
6482 CUR.tt_metrics.compensations[CUR.opcode & 3] );
6483 else
6484 #endif
6169 distance = CUR_Func_round( 6485 distance = CUR_Func_round(
6170 org_dist, 6486 org_dist,
6171 CUR.tt_metrics.compensations[CUR.opcode & 3] ); 6487 CUR.tt_metrics.compensations[CUR.opcode & 3] );
6488 }
6172 else 6489 else
6173 distance = ROUND_None( 6490 distance = ROUND_None(
6174 org_dist, 6491 org_dist,
6175 CUR.tt_metrics.compensations[CUR.opcode & 3] ); 6492 CUR.tt_metrics.compensations[CUR.opcode & 3] );
6176 6493
6177 /* minimum distance flag */ 6494 /* minimum distance flag */
6178 6495
6179 if ( ( CUR.opcode & 8 ) != 0 ) 6496 if ( ( CUR.opcode & 8 ) != 0 )
6180 { 6497 {
6181 if ( org_dist >= 0 ) 6498 if ( org_dist >= 0 )
6182 { 6499 {
6183 if ( distance < CUR.GS.minimum_distance ) 6500 if ( distance < minimum_distance )
6184 distance = CUR.GS.minimum_distance; 6501 distance = minimum_distance;
6185 } 6502 }
6186 else 6503 else
6187 { 6504 {
6188 if ( distance > -CUR.GS.minimum_distance ) 6505 if ( distance > -minimum_distance )
6189 distance = -CUR.GS.minimum_distance; 6506 distance = -minimum_distance;
6190 } 6507 }
6191 } 6508 }
6192 6509
6193 /* now move the point */ 6510 /* now move the point */
6194 6511
6195 org_dist = CUR_Func_project( CUR.zp1.cur + point, 6512 org_dist = CUR_Func_project( CUR.zp1.cur + point,
6196 CUR.zp0.cur + CUR.GS.rp0 ); 6513 CUR.zp0.cur + CUR.GS.rp0 );
6197 6514
6198 CUR_Func_move( &CUR.zp1, point, distance - org_dist ); 6515 CUR_Func_move( &CUR.zp1, point, distance - org_dist );
6199 6516
(...skipping 14 matching lines...) Expand all
6214 /* */ 6531 /* */
6215 static void 6532 static void
6216 Ins_MIRP( INS_ARG ) 6533 Ins_MIRP( INS_ARG )
6217 { 6534 {
6218 FT_UShort point; 6535 FT_UShort point;
6219 FT_ULong cvtEntry; 6536 FT_ULong cvtEntry;
6220 6537
6221 FT_F26Dot6 cvt_dist, 6538 FT_F26Dot6 cvt_dist,
6222 distance, 6539 distance,
6223 cur_dist, 6540 cur_dist,
6224 org_dist; 6541 org_dist,
6542 control_value_cutin,
6543 minimum_distance;
6544 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6545 FT_Int B1;
6546 FT_Int B2;
6547 FT_Bool reverse_move = FALSE;
6548 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6225 6549
6226 6550
6227 point = (FT_UShort)args[0]; 6551 minimum_distance = CUR.GS.minimum_distance;
6228 cvtEntry = (FT_ULong)( args[1] + 1 ); 6552 control_value_cutin = CUR.GS.control_value_cutin;
6553 point = (FT_UShort)args[0];
6554 cvtEntry = (FT_ULong)( args[1] + 1 );
6555
6556 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6557 if ( SUBPIXEL_HINTING &&
6558 CUR.ignore_x_mode &&
6559 CUR.GS.freeVector.x != 0 &&
6560 !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
6561 control_value_cutin = minimum_distance = 0;
6562 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6229 6563
6230 /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ 6564 /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
6231 6565
6232 if ( BOUNDS( point, CUR.zp1.n_points ) || 6566 if ( BOUNDS( point, CUR.zp1.n_points ) ||
6233 BOUNDSL( cvtEntry, CUR.cvtSize + 1 ) || 6567 BOUNDSL( cvtEntry, CUR.cvtSize + 1 ) ||
6234 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) 6568 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6235 { 6569 {
6236 if ( CUR.pedantic_hinting ) 6570 if ( CUR.pedantic_hinting )
6237 CUR.error = TT_Err_Invalid_Reference; 6571 CUR.error = FT_THROW( Invalid_Reference );
6238 goto Fail; 6572 goto Fail;
6239 } 6573 }
6240 6574
6241 if ( !cvtEntry ) 6575 if ( !cvtEntry )
6242 cvt_dist = 0; 6576 cvt_dist = 0;
6243 else 6577 else
6244 cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 ); 6578 cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
6245 6579
6246 /* single width test */ 6580 /* single width test */
6247 6581
(...skipping 25 matching lines...) Expand all
6273 &CUR.zp0.cur[CUR.GS.rp0] ); 6607 &CUR.zp0.cur[CUR.GS.rp0] );
6274 6608
6275 /* auto-flip test */ 6609 /* auto-flip test */
6276 6610
6277 if ( CUR.GS.auto_flip ) 6611 if ( CUR.GS.auto_flip )
6278 { 6612 {
6279 if ( ( org_dist ^ cvt_dist ) < 0 ) 6613 if ( ( org_dist ^ cvt_dist ) < 0 )
6280 cvt_dist = -cvt_dist; 6614 cvt_dist = -cvt_dist;
6281 } 6615 }
6282 6616
6283 /* control value cutin and round */ 6617 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6618 if ( SUBPIXEL_HINTING &&
6619 CUR.ignore_x_mode &&
6620 CUR.GS.freeVector.y != 0 &&
6621 ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
6622 {
6623 if ( cur_dist < -64 )
6624 cvt_dist -= 16;
6625 else if ( cur_dist > 64 && cur_dist < 84 )
6626 cvt_dist += 32;
6627 }
6628 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6629
6630 /* control value cut-in and round */
6284 6631
6285 if ( ( CUR.opcode & 4 ) != 0 ) 6632 if ( ( CUR.opcode & 4 ) != 0 )
6286 { 6633 {
6287 /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */ 6634 /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
6288 /* refer to the same zone. */ 6635 /* refer to the same zone. */
6289 6636
6290 if ( CUR.GS.gep0 == CUR.GS.gep1 ) 6637 if ( CUR.GS.gep0 == CUR.GS.gep1 )
6291 { 6638 {
6292 /* XXX: According to Greg Hitchcock, the following wording is */ 6639 /* XXX: According to Greg Hitchcock, the following wording is */
6293 /* the right one: */ 6640 /* the right one: */
6294 /* */ 6641 /* */
6295 /* When the absolute difference between the value in */ 6642 /* When the absolute difference between the value in */
6296 /* the table [CVT] and the measurement directly from */ 6643 /* the table [CVT] and the measurement directly from */
6297 /* the outline is _greater_ than the cut_in value, the */ 6644 /* the outline is _greater_ than the cut_in value, the */
6298 /* outline measurement is used. */ 6645 /* outline measurement is used. */
6299 /* */ 6646 /* */
6300 /* This is from `instgly.doc'. The description in */ 6647 /* This is from `instgly.doc'. The description in */
6301 /* `ttinst2.doc', version 1.66, is thus incorrect since */ 6648 /* `ttinst2.doc', version 1.66, is thus incorrect since */
6302 /* it implies `>=' instead of `>'. */ 6649 /* it implies `>=' instead of `>'. */
6303 6650
6304 if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin ) 6651 if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
6305 cvt_dist = org_dist; 6652 cvt_dist = org_dist;
6306 } 6653 }
6307 6654
6308 distance = CUR_Func_round( 6655 distance = CUR_Func_round(
6309 cvt_dist, 6656 cvt_dist,
6310 CUR.tt_metrics.compensations[CUR.opcode & 3] ); 6657 CUR.tt_metrics.compensations[CUR.opcode & 3] );
6311 } 6658 }
6312 else 6659 else
6660 {
6661
6662 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6663 /* do cvt cut-in always in MIRP for sph */
6664 if ( SUBPIXEL_HINTING &&
6665 CUR.ignore_x_mode &&
6666 CUR.GS.gep0 == CUR.GS.gep1 )
6667 {
6668 if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
6669 cvt_dist = org_dist;
6670 }
6671 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6672
6313 distance = ROUND_None( 6673 distance = ROUND_None(
6314 cvt_dist, 6674 cvt_dist,
6315 CUR.tt_metrics.compensations[CUR.opcode & 3] ); 6675 CUR.tt_metrics.compensations[CUR.opcode & 3] );
6676 }
6316 6677
6317 /* minimum distance test */ 6678 /* minimum distance test */
6318 6679
6319 if ( ( CUR.opcode & 8 ) != 0 ) 6680 if ( ( CUR.opcode & 8 ) != 0 )
6320 { 6681 {
6321 if ( org_dist >= 0 ) 6682 if ( org_dist >= 0 )
6322 { 6683 {
6323 if ( distance < CUR.GS.minimum_distance ) 6684 if ( distance < minimum_distance )
6324 distance = CUR.GS.minimum_distance; 6685 distance = minimum_distance;
6325 } 6686 }
6326 else 6687 else
6327 { 6688 {
6328 if ( distance > -CUR.GS.minimum_distance ) 6689 if ( distance > -minimum_distance )
6329 distance = -CUR.GS.minimum_distance; 6690 distance = -minimum_distance;
6330 } 6691 }
6331 } 6692 }
6332 6693
6694 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6695 if ( SUBPIXEL_HINTING )
6696 {
6697 B1 = CUR.zp1.cur[point].y;
6698
6699 /* Round moves if necessary */
6700 if ( CUR.ignore_x_mode &&
6701 CUR.GS.freeVector.y != 0 &&
6702 ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
6703 distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
6704
6705 if ( CUR.ignore_x_mode &&
6706 CUR.GS.freeVector.y != 0 &&
6707 ( CUR.opcode & 16 ) == 0 &&
6708 ( CUR.opcode & 8 ) == 0 &&
6709 ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
6710 distance += 64;
6711 }
6712 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6713
6333 CUR_Func_move( &CUR.zp1, point, distance - cur_dist ); 6714 CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
6334 6715
6716 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6717 if ( SUBPIXEL_HINTING )
6718 {
6719 B2 = CUR.zp1.cur[point].y;
6720
6721 /* Reverse move if necessary */
6722 if ( CUR.ignore_x_mode )
6723 {
6724 if ( CUR.face->sph_compatibility_mode &&
6725 CUR.GS.freeVector.y != 0 &&
6726 ( B1 & 63 ) == 0 &&
6727 ( B2 & 63 ) != 0 )
6728 reverse_move = TRUE;
6729
6730 if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
6731 CUR.GS.freeVector.y != 0 &&
6732 ( B2 & 63 ) != 0 &&
6733 ( B1 & 63 ) != 0 )
6734 reverse_move = TRUE;
6735 }
6736
6737 if ( reverse_move )
6738 CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
6739 }
6740
6741 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6742
6335 Fail: 6743 Fail:
6336 CUR.GS.rp1 = CUR.GS.rp0; 6744 CUR.GS.rp1 = CUR.GS.rp0;
6337 6745
6338 if ( ( CUR.opcode & 16 ) != 0 ) 6746 if ( ( CUR.opcode & 16 ) != 0 )
6339 CUR.GS.rp0 = point; 6747 CUR.GS.rp0 = point;
6340 6748
6341 CUR.GS.rp2 = point; 6749 CUR.GS.rp2 = point;
6342 } 6750 }
6343 6751
6344 6752
6345 /*************************************************************************/ 6753 /*************************************************************************/
6346 /* */ 6754 /* */
6347 /* ALIGNRP[]: ALIGN Relative Point */ 6755 /* ALIGNRP[]: ALIGN Relative Point */
6348 /* Opcode range: 0x3C */ 6756 /* Opcode range: 0x3C */
6349 /* Stack: uint32 uint32... --> */ 6757 /* Stack: uint32 uint32... --> */
6350 /* */ 6758 /* */
6351 static void 6759 static void
6352 Ins_ALIGNRP( INS_ARG ) 6760 Ins_ALIGNRP( INS_ARG )
6353 { 6761 {
6354 FT_UShort point; 6762 FT_UShort point;
6355 FT_F26Dot6 distance; 6763 FT_F26Dot6 distance;
6356 6764
6357 FT_UNUSED_ARG; 6765 FT_UNUSED_ARG;
6358 6766
6359 6767
6768 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
6769 if ( SUBPIXEL_HINTING &&
6770 CUR.ignore_x_mode &&
6771 CUR.iup_called &&
6772 ( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
6773 {
6774 CUR.error = FT_THROW( Invalid_Reference );
6775 goto Fail;
6776 }
6777 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6778
6360 if ( CUR.top < CUR.GS.loop || 6779 if ( CUR.top < CUR.GS.loop ||
6361 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) 6780 BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
6362 { 6781 {
6363 if ( CUR.pedantic_hinting ) 6782 if ( CUR.pedantic_hinting )
6364 CUR.error = TT_Err_Invalid_Reference; 6783 CUR.error = FT_THROW( Invalid_Reference );
6365 goto Fail; 6784 goto Fail;
6366 } 6785 }
6367 6786
6368 while ( CUR.GS.loop > 0 ) 6787 while ( CUR.GS.loop > 0 )
6369 { 6788 {
6370 CUR.args--; 6789 CUR.args--;
6371 6790
6372 point = (FT_UShort)CUR.stack[CUR.args]; 6791 point = (FT_UShort)CUR.stack[CUR.args];
6373 6792
6374 if ( BOUNDS( point, CUR.zp1.n_points ) ) 6793 if ( BOUNDS( point, CUR.zp1.n_points ) )
6375 { 6794 {
6376 if ( CUR.pedantic_hinting ) 6795 if ( CUR.pedantic_hinting )
6377 { 6796 {
6378 CUR.error = TT_Err_Invalid_Reference; 6797 CUR.error = FT_THROW( Invalid_Reference );
6379 return; 6798 return;
6380 } 6799 }
6381 } 6800 }
6382 else 6801 else
6383 { 6802 {
6384 distance = CUR_Func_project( CUR.zp1.cur + point, 6803 distance = CUR_Func_project( CUR.zp1.cur + point,
6385 CUR.zp0.cur + CUR.GS.rp0 ); 6804 CUR.zp0.cur + CUR.GS.rp0 );
6386 6805
6387 CUR_Func_move( &CUR.zp1, point, -distance ); 6806 CUR_Func_move( &CUR.zp1, point, -distance );
6388 } 6807 }
(...skipping 13 matching lines...) Expand all
6402 /* Opcode range: 0x0F */ 6821 /* Opcode range: 0x0F */
6403 /* Stack: 5 * uint32 --> */ 6822 /* Stack: 5 * uint32 --> */
6404 /* */ 6823 /* */
6405 static void 6824 static void
6406 Ins_ISECT( INS_ARG ) 6825 Ins_ISECT( INS_ARG )
6407 { 6826 {
6408 FT_UShort point, 6827 FT_UShort point,
6409 a0, a1, 6828 a0, a1,
6410 b0, b1; 6829 b0, b1;
6411 6830
6412 FT_F26Dot6 discriminant; 6831 FT_F26Dot6 discriminant, dotproduct;
6413 6832
6414 FT_F26Dot6 dx, dy, 6833 FT_F26Dot6 dx, dy,
6415 dax, day, 6834 dax, day,
6416 dbx, dby; 6835 dbx, dby;
6417 6836
6418 FT_F26Dot6 val; 6837 FT_F26Dot6 val;
6419 6838
6420 FT_Vector R; 6839 FT_Vector R;
6421 6840
6422 6841
6423 point = (FT_UShort)args[0]; 6842 point = (FT_UShort)args[0];
6424 6843
6425 a0 = (FT_UShort)args[1]; 6844 a0 = (FT_UShort)args[1];
6426 a1 = (FT_UShort)args[2]; 6845 a1 = (FT_UShort)args[2];
6427 b0 = (FT_UShort)args[3]; 6846 b0 = (FT_UShort)args[3];
6428 b1 = (FT_UShort)args[4]; 6847 b1 = (FT_UShort)args[4];
6429 6848
6430 if ( BOUNDS( b0, CUR.zp0.n_points ) || 6849 if ( BOUNDS( b0, CUR.zp0.n_points ) ||
6431 BOUNDS( b1, CUR.zp0.n_points ) || 6850 BOUNDS( b1, CUR.zp0.n_points ) ||
6432 BOUNDS( a0, CUR.zp1.n_points ) || 6851 BOUNDS( a0, CUR.zp1.n_points ) ||
6433 BOUNDS( a1, CUR.zp1.n_points ) || 6852 BOUNDS( a1, CUR.zp1.n_points ) ||
6434 BOUNDS( point, CUR.zp2.n_points ) ) 6853 BOUNDS( point, CUR.zp2.n_points ) )
6435 { 6854 {
6436 if ( CUR.pedantic_hinting ) 6855 if ( CUR.pedantic_hinting )
6437 CUR.error = TT_Err_Invalid_Reference; 6856 CUR.error = FT_THROW( Invalid_Reference );
6438 return; 6857 return;
6439 } 6858 }
6440 6859
6860 /* Cramer's rule */
6861
6441 dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x; 6862 dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
6442 dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y; 6863 dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
6443 6864
6444 dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x; 6865 dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
6445 day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y; 6866 day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
6446 6867
6447 dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x; 6868 dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
6448 dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y; 6869 dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
6449 6870
6450 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH; 6871 CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
6451 6872
6452 discriminant = TT_MULDIV( dax, -dby, 0x40 ) + 6873 discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
6453 TT_MULDIV( day, dbx, 0x40 ); 6874 FT_MulDiv( day, dbx, 0x40 );
6875 dotproduct = FT_MulDiv( dax, dbx, 0x40 ) +
6876 FT_MulDiv( day, dby, 0x40 );
6454 6877
6455 if ( FT_ABS( discriminant ) >= 0x40 ) 6878 /* The discriminant above is actually a cross product of vectors */
6879 /* da and db. Together with the dot product, they can be used as */
6880 /* surrogates for sine and cosine of the angle between the vectors. */
6881 /* Indeed, */
6882 /* dotproduct = |da||db|cos(angle) */
6883 /* discriminant = |da||db|sin(angle) . */
6884 /* We use these equations to reject grazing intersections by */
6885 /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
6886 if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) )
6456 { 6887 {
6457 val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 ); 6888 val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 );
6458 6889
6459 R.x = TT_MULDIV( val, dax, discriminant ); 6890 R.x = FT_MulDiv( val, dax, discriminant );
6460 R.y = TT_MULDIV( val, day, discriminant ); 6891 R.y = FT_MulDiv( val, day, discriminant );
6461 6892
6462 CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x; 6893 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; 6894 CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
6464 } 6895 }
6465 else 6896 else
6466 { 6897 {
6467 /* else, take the middle of the middles of A and B */ 6898 /* else, take the middle of the middles of A and B */
6468 6899
6469 CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x + 6900 CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
6470 CUR.zp1.cur[a1].x + 6901 CUR.zp1.cur[a1].x +
(...skipping 20 matching lines...) Expand all
6491 FT_F26Dot6 distance; 6922 FT_F26Dot6 distance;
6492 6923
6493 6924
6494 p1 = (FT_UShort)args[0]; 6925 p1 = (FT_UShort)args[0];
6495 p2 = (FT_UShort)args[1]; 6926 p2 = (FT_UShort)args[1];
6496 6927
6497 if ( BOUNDS( p1, CUR.zp1.n_points ) || 6928 if ( BOUNDS( p1, CUR.zp1.n_points ) ||
6498 BOUNDS( p2, CUR.zp0.n_points ) ) 6929 BOUNDS( p2, CUR.zp0.n_points ) )
6499 { 6930 {
6500 if ( CUR.pedantic_hinting ) 6931 if ( CUR.pedantic_hinting )
6501 CUR.error = TT_Err_Invalid_Reference; 6932 CUR.error = FT_THROW( Invalid_Reference );
6502 return; 6933 return;
6503 } 6934 }
6504 6935
6505 distance = CUR_Func_project( CUR.zp0.cur + p2, 6936 distance = CUR_Func_project( CUR.zp0.cur + p2,
6506 CUR.zp1.cur + p1 ) / 2; 6937 CUR.zp1.cur + p1 ) / 2;
6507 6938
6508 CUR_Func_move( &CUR.zp1, p1, distance ); 6939 CUR_Func_move( &CUR.zp1, p1, distance );
6509 CUR_Func_move( &CUR.zp0, p2, -distance ); 6940 CUR_Func_move( &CUR.zp0, p2, -distance );
6510 } 6941 }
6511 6942
(...skipping 14 matching lines...) Expand all
6526 FT_Vector* orus_base; 6957 FT_Vector* orus_base;
6527 FT_Vector* cur_base; 6958 FT_Vector* cur_base;
6528 FT_Int twilight; 6959 FT_Int twilight;
6529 6960
6530 FT_UNUSED_ARG; 6961 FT_UNUSED_ARG;
6531 6962
6532 6963
6533 if ( CUR.top < CUR.GS.loop ) 6964 if ( CUR.top < CUR.GS.loop )
6534 { 6965 {
6535 if ( CUR.pedantic_hinting ) 6966 if ( CUR.pedantic_hinting )
6536 CUR.error = TT_Err_Invalid_Reference; 6967 CUR.error = FT_THROW( Invalid_Reference );
6537 goto Fail; 6968 goto Fail;
6538 } 6969 }
6539 6970
6540 /* 6971 /*
6541 * We need to deal in a special way with the twilight zone. 6972 * 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), 6973 * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
6543 * for every n. 6974 * for every n.
6544 */ 6975 */
6545 twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0; 6976 twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
6546 6977
6547 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ) 6978 if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
6548 { 6979 {
6549 if ( CUR.pedantic_hinting ) 6980 if ( CUR.pedantic_hinting )
6550 CUR.error = TT_Err_Invalid_Reference; 6981 CUR.error = FT_THROW( Invalid_Reference );
6551 goto Fail; 6982 goto Fail;
6552 } 6983 }
6553 6984
6554 if ( twilight ) 6985 if ( twilight )
6555 orus_base = &CUR.zp0.org[CUR.GS.rp1]; 6986 orus_base = &CUR.zp0.org[CUR.GS.rp1];
6556 else 6987 else
6557 orus_base = &CUR.zp0.orus[CUR.GS.rp1]; 6988 orus_base = &CUR.zp0.orus[CUR.GS.rp1];
6558 6989
6559 cur_base = &CUR.zp0.cur[CUR.GS.rp1]; 6990 cur_base = &CUR.zp0.cur[CUR.GS.rp1];
6560 6991
(...skipping 13 matching lines...) Expand all
6574 old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2], 7005 old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
6575 orus_base ); 7006 orus_base );
6576 else if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) 7007 else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
6577 old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2], 7008 old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
6578 orus_base ); 7009 orus_base );
6579 else 7010 else
6580 { 7011 {
6581 FT_Vector vec; 7012 FT_Vector vec;
6582 7013
6583 7014
6584 vec.x = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x, 7015 vec.x = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
6585 CUR.metrics.x_scale ); 7016 CUR.metrics.x_scale );
6586 vec.y = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y, 7017 vec.y = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
6587 CUR.metrics.y_scale ); 7018 CUR.metrics.y_scale );
6588 7019
6589 old_range = CUR_fast_dualproj( &vec ); 7020 old_range = CUR_fast_dualproj( &vec );
6590 } 7021 }
6591 7022
6592 cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base ); 7023 cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
6593 } 7024 }
6594 7025
6595 for ( ; CUR.GS.loop > 0; --CUR.GS.loop ) 7026 for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
6596 { 7027 {
6597 FT_UInt point = (FT_UInt)CUR.stack[--CUR.args]; 7028 FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
6598 FT_F26Dot6 org_dist, cur_dist, new_dist; 7029 FT_F26Dot6 org_dist, cur_dist, new_dist;
6599 7030
6600 7031
6601 /* check point bounds */ 7032 /* check point bounds */
6602 if ( BOUNDS( point, CUR.zp2.n_points ) ) 7033 if ( BOUNDS( point, CUR.zp2.n_points ) )
6603 { 7034 {
6604 if ( CUR.pedantic_hinting ) 7035 if ( CUR.pedantic_hinting )
6605 { 7036 {
6606 CUR.error = TT_Err_Invalid_Reference; 7037 CUR.error = FT_THROW( Invalid_Reference );
6607 return; 7038 return;
6608 } 7039 }
6609 continue; 7040 continue;
6610 } 7041 }
6611 7042
6612 if ( twilight ) 7043 if ( twilight )
6613 org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base ); 7044 org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
6614 else if ( CUR.metrics.x_scale == CUR.metrics.y_scale ) 7045 else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
6615 org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base ); 7046 org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
6616 else 7047 else
6617 { 7048 {
6618 FT_Vector vec; 7049 FT_Vector vec;
6619 7050
6620 7051
6621 vec.x = TT_MULFIX( CUR.zp2.orus[point].x - orus_base->x, 7052 vec.x = FT_MulFix( CUR.zp2.orus[point].x - orus_base->x,
6622 CUR.metrics.x_scale ); 7053 CUR.metrics.x_scale );
6623 vec.y = TT_MULFIX( CUR.zp2.orus[point].y - orus_base->y, 7054 vec.y = FT_MulFix( CUR.zp2.orus[point].y - orus_base->y,
6624 CUR.metrics.y_scale ); 7055 CUR.metrics.y_scale );
6625 7056
6626 org_dist = CUR_fast_dualproj( &vec ); 7057 org_dist = CUR_fast_dualproj( &vec );
6627 } 7058 }
6628 7059
6629 cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base ); 7060 cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
6630 7061
6631 if ( org_dist ) 7062 if ( org_dist )
6632 new_dist = ( old_range != 0 ) 7063 {
6633 ? TT_MULDIV( org_dist, cur_range, old_range ) 7064 if ( old_range )
6634 : cur_dist; 7065 new_dist = FT_MulDiv( org_dist, cur_range, old_range );
7066 else
7067 {
7068 /* This is the same as what MS does for the invalid case: */
7069 /* */
7070 /* delta = (Original_Pt - Original_RP1) - */
7071 /* (Current_Pt - Current_RP1) */
7072 /* */
7073 /* In FreeType speak: */
7074 /* */
7075 /* new_dist = cur_dist - */
7076 /* org_dist - cur_dist; */
7077
7078 new_dist = -org_dist;
7079 }
7080 }
6635 else 7081 else
6636 new_dist = 0; 7082 new_dist = 0;
6637 7083
6638 CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist ); 7084 CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
6639 } 7085 }
6640 7086
6641 Fail: 7087 Fail:
6642 CUR.GS.loop = 1; 7088 CUR.GS.loop = 1;
6643 CUR.new_top = CUR.args; 7089 CUR.new_top = CUR.args;
6644 } 7090 }
(...skipping 10 matching lines...) Expand all
6655 { 7101 {
6656 FT_UShort point; 7102 FT_UShort point;
6657 FT_Byte mask; 7103 FT_Byte mask;
6658 7104
6659 7105
6660 point = (FT_UShort)args[0]; 7106 point = (FT_UShort)args[0];
6661 7107
6662 if ( BOUNDS( point, CUR.zp0.n_points ) ) 7108 if ( BOUNDS( point, CUR.zp0.n_points ) )
6663 { 7109 {
6664 if ( CUR.pedantic_hinting ) 7110 if ( CUR.pedantic_hinting )
6665 CUR.error = TT_Err_Invalid_Reference; 7111 CUR.error = FT_THROW( Invalid_Reference );
6666 return; 7112 return;
6667 } 7113 }
6668 7114
6669 mask = 0xFF; 7115 mask = 0xFF;
6670 7116
6671 if ( CUR.GS.freeVector.x != 0 ) 7117 if ( CUR.GS.freeVector.x != 0 )
6672 mask &= ~FT_CURVE_TAG_TOUCH_X; 7118 mask &= ~FT_CURVE_TAG_TOUCH_X;
6673 7119
6674 if ( CUR.GS.freeVector.y != 0 ) 7120 if ( CUR.GS.freeVector.y != 0 )
6675 mask &= ~FT_CURVE_TAG_TOUCH_Y; 7121 mask &= ~FT_CURVE_TAG_TOUCH_Y;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
6784 x += delta1; 7230 x += delta1;
6785 7231
6786 else if ( x >= org2 ) 7232 else if ( x >= org2 )
6787 x += delta2; 7233 x += delta2;
6788 7234
6789 else 7235 else
6790 { 7236 {
6791 if ( !scale_valid ) 7237 if ( !scale_valid )
6792 { 7238 {
6793 scale_valid = 1; 7239 scale_valid = 1;
6794 scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ), 7240 scale = FT_DivFix( org2 + delta2 - ( org1 + delta1 ),
6795 0x10000L, orus2 - orus1 ); 7241 orus2 - orus1 );
6796 } 7242 }
6797 7243
6798 x = ( org1 + delta1 ) + 7244 x = ( org1 + delta1 ) +
6799 TT_MULFIX( worker->orus[i].x - orus1, scale ); 7245 FT_MulFix( worker->orus[i].x - orus1, scale );
6800 } 7246 }
6801 worker->curs[i].x = x; 7247 worker->curs[i].x = x;
6802 } 7248 }
6803 } 7249 }
6804 } 7250 }
6805 7251
6806 7252
6807 /*************************************************************************/ 7253 /*************************************************************************/
6808 /* */ 7254 /* */
6809 /* IUP[a]: Interpolate Untouched Points */ 7255 /* IUP[a]: Interpolate Untouched Points */
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
6844 mask = FT_CURVE_TAG_TOUCH_Y; 7290 mask = FT_CURVE_TAG_TOUCH_Y;
6845 V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 ); 7291 V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
6846 V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 ); 7292 V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
6847 V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 ); 7293 V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
6848 } 7294 }
6849 V.max_points = CUR.pts.n_points; 7295 V.max_points = CUR.pts.n_points;
6850 7296
6851 contour = 0; 7297 contour = 0;
6852 point = 0; 7298 point = 0;
6853 7299
7300 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
7301 if ( SUBPIXEL_HINTING &&
7302 CUR.ignore_x_mode )
7303 {
7304 CUR.iup_called = TRUE;
7305 if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
7306 return;
7307 }
7308 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
7309
6854 do 7310 do
6855 { 7311 {
6856 end_point = CUR.pts.contours[contour] - CUR.pts.first_point; 7312 end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
6857 first_point = point; 7313 first_point = point;
6858 7314
6859 if ( BOUNDS ( end_point, CUR.pts.n_points ) ) 7315 if ( BOUNDS ( end_point, CUR.pts.n_points ) )
6860 end_point = CUR.pts.n_points - 1; 7316 end_point = CUR.pts.n_points - 1;
6861 7317
6862 while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 ) 7318 while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
6863 point++; 7319 point++;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6913 /* Opcode range: 0x5D,0x71,0x72 */ 7369 /* Opcode range: 0x5D,0x71,0x72 */
6914 /* Stack: uint32 (2 * uint32)... --> */ 7370 /* Stack: uint32 (2 * uint32)... --> */
6915 /* */ 7371 /* */
6916 static void 7372 static void
6917 Ins_DELTAP( INS_ARG ) 7373 Ins_DELTAP( INS_ARG )
6918 { 7374 {
6919 FT_ULong k, nump; 7375 FT_ULong k, nump;
6920 FT_UShort A; 7376 FT_UShort A;
6921 FT_ULong C; 7377 FT_ULong C;
6922 FT_Long B; 7378 FT_Long B;
7379 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
7380 FT_UShort B1, B2;
7381
7382
7383 if ( SUBPIXEL_HINTING &&
7384 CUR.ignore_x_mode &&
7385 CUR.iup_called &&
7386 ( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
7387 goto Fail;
7388 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
6923 7389
6924 7390
6925 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 7391 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
6926 /* Delta hinting is covered by US Patent 5159668. */ 7392 /* Delta hinting is covered by US Patent 5159668. */
6927 if ( CUR.face->unpatented_hinting ) 7393 if ( CUR.face->unpatented_hinting )
6928 { 7394 {
6929 FT_Long n = args[0] * 2; 7395 FT_Long n = args[0] * 2;
6930 7396
6931 7397
6932 if ( CUR.args < n ) 7398 if ( CUR.args < n )
6933 { 7399 {
6934 if ( CUR.pedantic_hinting ) 7400 if ( CUR.pedantic_hinting )
6935 CUR.error = TT_Err_Too_Few_Arguments; 7401 CUR.error = FT_THROW( Too_Few_Arguments );
6936 n = CUR.args; 7402 n = CUR.args;
6937 } 7403 }
6938 7404
6939 CUR.args -= n; 7405 CUR.args -= n;
6940 CUR.new_top = CUR.args; 7406 CUR.new_top = CUR.args;
6941 return; 7407 return;
6942 } 7408 }
6943 #endif 7409 #endif
6944 7410
6945 nump = (FT_ULong)args[0]; /* some points theoretically may occur more 7411 nump = (FT_ULong)args[0]; /* some points theoretically may occur more
6946 than once, thus UShort isn't enough */ 7412 than once, thus UShort isn't enough */
6947 7413
6948 for ( k = 1; k <= nump; k++ ) 7414 for ( k = 1; k <= nump; k++ )
6949 { 7415 {
6950 if ( CUR.args < 2 ) 7416 if ( CUR.args < 2 )
6951 { 7417 {
6952 if ( CUR.pedantic_hinting ) 7418 if ( CUR.pedantic_hinting )
6953 CUR.error = TT_Err_Too_Few_Arguments; 7419 CUR.error = FT_THROW( Too_Few_Arguments );
6954 CUR.args = 0; 7420 CUR.args = 0;
6955 goto Fail; 7421 goto Fail;
6956 } 7422 }
6957 7423
6958 CUR.args -= 2; 7424 CUR.args -= 2;
6959 7425
6960 A = (FT_UShort)CUR.stack[CUR.args + 1]; 7426 A = (FT_UShort)CUR.stack[CUR.args + 1];
6961 B = CUR.stack[CUR.args]; 7427 B = CUR.stack[CUR.args];
6962 7428
6963 /* XXX: Because some popular fonts contain some invalid DeltaP */ 7429 /* XXX: Because some popular fonts contain some invalid DeltaP */
(...skipping 22 matching lines...) Expand all
6986 7452
6987 C += CUR.GS.delta_base; 7453 C += CUR.GS.delta_base;
6988 7454
6989 if ( CURRENT_Ppem() == (FT_Long)C ) 7455 if ( CURRENT_Ppem() == (FT_Long)C )
6990 { 7456 {
6991 B = ( (FT_ULong)B & 0xF ) - 8; 7457 B = ( (FT_ULong)B & 0xF ) - 8;
6992 if ( B >= 0 ) 7458 if ( B >= 0 )
6993 B++; 7459 B++;
6994 B = B * 64 / ( 1L << CUR.GS.delta_shift ); 7460 B = B * 64 / ( 1L << CUR.GS.delta_shift );
6995 7461
6996 CUR_Func_move( &CUR.zp0, A, B ); 7462 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
7463
7464 if ( SUBPIXEL_HINTING )
7465 {
7466 /*
7467 * Allow delta move if
7468 *
7469 * - not using ignore_x_mode rendering
7470 * - glyph is specifically set to allow it
7471 * - glyph is composite and freedom vector is not subpixel
7472 * vector
7473 */
7474 if ( !CUR.ignore_x_mode ||
7475 ( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
7476 ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) )
7477 CUR_Func_move( &CUR.zp0, A, B );
7478
7479 /* Otherwise apply subpixel hinting and */
7480 /* compatibility mode rules */
7481 else if ( CUR.ignore_x_mode )
7482 {
7483 if ( CUR.GS.freeVector.y != 0 )
7484 B1 = CUR.zp0.cur[A].y;
7485 else
7486 B1 = CUR.zp0.cur[A].x;
7487
7488 #if 0
7489 /* Standard Subpixel Hinting: Allow y move. */
7490 /* This messes up dejavu and may not be needed... */
7491 if ( !CUR.face->sph_compatibility_mode &&
7492 CUR.GS.freeVector.y != 0 )
7493 CUR_Func_move( &CUR.zp0, A, B );
7494 else
7495 #endif /* 0 */
7496
7497 /* Compatibility Mode: Allow x or y move if point touched in */
7498 /* Y direction. */
7499 if ( CUR.face->sph_compatibility_mode &&
7500 !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
7501 {
7502 /* save the y value of the point now; compare after move */
7503 B1 = CUR.zp0.cur[A].y;
7504
7505 if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
7506 B = FT_PIX_ROUND( B1 + B ) - B1;
7507
7508 /* Allow delta move if using sph_compatibility_mode, */
7509 /* IUP has not been called, and point is touched on Y. */
7510 if ( !CUR.iup_called &&
7511 ( CUR.zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
7512 CUR_Func_move( &CUR.zp0, A, B );
7513 }
7514
7515 B2 = CUR.zp0.cur[A].y;
7516
7517 /* Reverse this move if it results in a disallowed move */
7518 if ( CUR.GS.freeVector.y != 0 &&
7519 ( ( CUR.face->sph_compatibility_mode &&
7520 ( B1 & 63 ) == 0 &&
7521 ( B2 & 63 ) != 0 ) ||
7522 ( ( CUR.sph_tweak_flags &
7523 SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
7524 ( B1 & 63 ) != 0 &&
7525 ( B2 & 63 ) != 0 ) ) )
7526 CUR_Func_move( &CUR.zp0, A, -B );
7527 }
7528 }
7529 else
7530 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
7531
7532 CUR_Func_move( &CUR.zp0, A, B );
6997 } 7533 }
6998 } 7534 }
6999 else 7535 else
7000 if ( CUR.pedantic_hinting ) 7536 if ( CUR.pedantic_hinting )
7001 CUR.error = TT_Err_Invalid_Reference; 7537 CUR.error = FT_THROW( Invalid_Reference );
7002 } 7538 }
7003 7539
7004 Fail: 7540 Fail:
7005 CUR.new_top = CUR.args; 7541 CUR.new_top = CUR.args;
7006 } 7542 }
7007 7543
7008 7544
7009 /*************************************************************************/ 7545 /*************************************************************************/
7010 /* */ 7546 /* */
7011 /* DELTACn[]: DELTA exceptions C1, C2, C3 */ 7547 /* DELTACn[]: DELTA exceptions C1, C2, C3 */
(...skipping 11 matching lines...) Expand all
7023 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 7559 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
7024 /* Delta hinting is covered by US Patent 5159668. */ 7560 /* Delta hinting is covered by US Patent 5159668. */
7025 if ( CUR.face->unpatented_hinting ) 7561 if ( CUR.face->unpatented_hinting )
7026 { 7562 {
7027 FT_Long n = args[0] * 2; 7563 FT_Long n = args[0] * 2;
7028 7564
7029 7565
7030 if ( CUR.args < n ) 7566 if ( CUR.args < n )
7031 { 7567 {
7032 if ( CUR.pedantic_hinting ) 7568 if ( CUR.pedantic_hinting )
7033 CUR.error = TT_Err_Too_Few_Arguments; 7569 CUR.error = FT_THROW( Too_Few_Arguments );
7034 n = CUR.args; 7570 n = CUR.args;
7035 } 7571 }
7036 7572
7037 CUR.args -= n; 7573 CUR.args -= n;
7038 CUR.new_top = CUR.args; 7574 CUR.new_top = CUR.args;
7039 return; 7575 return;
7040 } 7576 }
7041 #endif 7577 #endif
7042 7578
7043 nump = (FT_ULong)args[0]; 7579 nump = (FT_ULong)args[0];
7044 7580
7045 for ( k = 1; k <= nump; k++ ) 7581 for ( k = 1; k <= nump; k++ )
7046 { 7582 {
7047 if ( CUR.args < 2 ) 7583 if ( CUR.args < 2 )
7048 { 7584 {
7049 if ( CUR.pedantic_hinting ) 7585 if ( CUR.pedantic_hinting )
7050 CUR.error = TT_Err_Too_Few_Arguments; 7586 CUR.error = FT_THROW( Too_Few_Arguments );
7051 CUR.args = 0; 7587 CUR.args = 0;
7052 goto Fail; 7588 goto Fail;
7053 } 7589 }
7054 7590
7055 CUR.args -= 2; 7591 CUR.args -= 2;
7056 7592
7057 A = (FT_ULong)CUR.stack[CUR.args + 1]; 7593 A = (FT_ULong)CUR.stack[CUR.args + 1];
7058 B = CUR.stack[CUR.args]; 7594 B = CUR.stack[CUR.args];
7059 7595
7060 if ( BOUNDSL( A, CUR.cvtSize ) ) 7596 if ( BOUNDSL( A, CUR.cvtSize ) )
7061 { 7597 {
7062 if ( CUR.pedantic_hinting ) 7598 if ( CUR.pedantic_hinting )
7063 { 7599 {
7064 CUR.error = TT_Err_Invalid_Reference; 7600 CUR.error = FT_THROW( Invalid_Reference );
7065 return; 7601 return;
7066 } 7602 }
7067 } 7603 }
7068 else 7604 else
7069 { 7605 {
7070 C = ( (FT_ULong)B & 0xF0 ) >> 4; 7606 C = ( (FT_ULong)B & 0xF0 ) >> 4;
7071 7607
7072 switch ( CUR.opcode ) 7608 switch ( CUR.opcode )
7073 { 7609 {
7074 case 0x73: 7610 case 0x73:
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
7116 /* Stack: uint32 --> uint32 */ 7652 /* Stack: uint32 --> uint32 */
7117 /* */ 7653 /* */
7118 static void 7654 static void
7119 Ins_GETINFO( INS_ARG ) 7655 Ins_GETINFO( INS_ARG )
7120 { 7656 {
7121 FT_Long K; 7657 FT_Long K;
7122 7658
7123 7659
7124 K = 0; 7660 K = 0;
7125 7661
7126 /* We return MS rasterizer version 1.7 for the font scaler. */ 7662 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
7127 if ( ( args[0] & 1 ) != 0 ) 7663 /********************************/
7128 K = 35; 7664 /* RASTERIZER VERSION */
7665 /* Selector Bit: 0 */
7666 /* Return Bit(s): 0-7 */
7667 /* */
7668 if ( SUBPIXEL_HINTING &&
7669 ( args[0] & 1 ) != 0 &&
7670 CUR.ignore_x_mode )
7671 {
7672 K = CUR.rasterizer_version;
7673 FT_TRACE7(( "Setting rasterizer version %d\n",
7674 CUR.rasterizer_version ));
7675 }
7676 else
7677 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
7678 if ( ( args[0] & 1 ) != 0 )
7679 K = TT_INTERPRETER_VERSION_35;
7129 7680
7130 /* Has the glyph been rotated? */ 7681 /********************************/
7682 /* GLYPH ROTATED */
7683 /* Selector Bit: 1 */
7684 /* Return Bit(s): 8 */
7685 /* */
7131 if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated ) 7686 if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
7132 K |= 0x80; 7687 K |= 0x80;
7133 7688
7134 /* Has the glyph been stretched? */ 7689 /********************************/
7690 /* GLYPH STRETCHED */
7691 /* Selector Bit: 2 */
7692 /* Return Bit(s): 9 */
7693 /* */
7135 if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched ) 7694 if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
7136 K |= 1 << 8; 7695 K |= 1 << 8;
7137 7696
7138 /* Are we hinting for grayscale? */ 7697 /********************************/
7698 /* HINTING FOR GRAYSCALE */
7699 /* Selector Bit: 5 */
7700 /* Return Bit(s): 12 */
7701 /* */
7139 if ( ( args[0] & 32 ) != 0 && CUR.grayscale ) 7702 if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
7140 K |= 1 << 12; 7703 K |= 1 << 12;
7141 7704
7705 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
7706
7707 if ( SUBPIXEL_HINTING &&
7708 CUR.ignore_x_mode &&
7709 CUR.rasterizer_version >= TT_INTERPRETER_VERSION_35 )
7710 {
7711 /********************************/
7712 /* HINTING FOR GRAYSCALE */
7713 /* Selector Bit: 5 */
7714 /* Return Bit(s): 12 */
7715 /* */
7716 if ( ( args[0] & 32 ) != 0 && CUR.grayscale_hinting )
7717 K |= 1 << 12;
7718
7719 /********************************/
7720 /* HINTING FOR SUBPIXEL */
7721 /* Selector Bit: 6 */
7722 /* Return Bit(s): 13 */
7723 /* */
7724 if ( ( args[0] & 64 ) != 0 &&
7725 CUR.subpixel_hinting &&
7726 CUR.rasterizer_version >= 37 )
7727 {
7728 K |= 1 << 13;
7729
7730 /* the stuff below is irrelevant if subpixel_hinting is not set */
7731
7732 /********************************/
7733 /* COMPATIBLE WIDTHS ENABLED */
7734 /* Selector Bit: 7 */
7735 /* Return Bit(s): 14 */
7736 /* */
7737 /* Functionality still needs to be added */
7738 if ( ( args[0] & 128 ) != 0 && CUR.compatible_widths )
7739 K |= 1 << 14;
7740
7741 /********************************/
7742 /* SYMMETRICAL SMOOTHING */
7743 /* Selector Bit: 8 */
7744 /* Return Bit(s): 15 */
7745 /* */
7746 /* Functionality still needs to be added */
7747 if ( ( args[0] & 256 ) != 0 && CUR.symmetrical_smoothing )
7748 K |= 1 << 15;
7749
7750 /********************************/
7751 /* HINTING FOR BGR? */
7752 /* Selector Bit: 9 */
7753 /* Return Bit(s): 16 */
7754 /* */
7755 /* Functionality still needs to be added */
7756 if ( ( args[0] & 512 ) != 0 && CUR.bgr )
7757 K |= 1 << 16;
7758
7759 if ( CUR.rasterizer_version >= 38 )
7760 {
7761 /********************************/
7762 /* SUBPIXEL POSITIONED? */
7763 /* Selector Bit: 10 */
7764 /* Return Bit(s): 17 */
7765 /* */
7766 /* Functionality still needs to be added */
7767 if ( ( args[0] & 1024 ) != 0 && CUR.subpixel_positioned )
7768 K |= 1 << 17;
7769 }
7770 }
7771 }
7772
7773 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
7774
7142 args[0] = K; 7775 args[0] = K;
7143 } 7776 }
7144 7777
7145 7778
7146 static void 7779 static void
7147 Ins_UNKNOWN( INS_ARG ) 7780 Ins_UNKNOWN( INS_ARG )
7148 { 7781 {
7149 TT_DefRecord* def = CUR.IDefs; 7782 TT_DefRecord* def = CUR.IDefs;
7150 TT_DefRecord* limit = def + CUR.numIDefs; 7783 TT_DefRecord* limit = def + CUR.numIDefs;
7151 7784
7152 FT_UNUSED_ARG; 7785 FT_UNUSED_ARG;
7153 7786
7154 7787
7155 for ( ; def < limit; def++ ) 7788 for ( ; def < limit; def++ )
7156 { 7789 {
7157 if ( (FT_Byte)def->opc == CUR.opcode && def->active ) 7790 if ( (FT_Byte)def->opc == CUR.opcode && def->active )
7158 { 7791 {
7159 TT_CallRec* call; 7792 TT_CallRec* call;
7160 7793
7161 7794
7162 if ( CUR.callTop >= CUR.callSize ) 7795 if ( CUR.callTop >= CUR.callSize )
7163 { 7796 {
7164 CUR.error = TT_Err_Stack_Overflow; 7797 CUR.error = FT_THROW( Stack_Overflow );
7165 return; 7798 return;
7166 } 7799 }
7167 7800
7168 call = CUR.callStack + CUR.callTop++; 7801 call = CUR.callStack + CUR.callTop++;
7169 7802
7170 call->Caller_Range = CUR.curRange; 7803 call->Caller_Range = CUR.curRange;
7171 call->Caller_IP = CUR.IP + 1; 7804 call->Caller_IP = CUR.IP + 1;
7172 call->Cur_Count = 1; 7805 call->Cur_Count = 1;
7173 call->Cur_Restart = def->start; 7806 call->Cur_Restart = def->start;
7174 call->Cur_End = def->end; 7807 call->Cur_End = def->end;
7175 7808
7176 INS_Goto_CodeRange( def->range, def->start ); 7809 INS_Goto_CodeRange( def->range, def->start );
7177 7810
7178 CUR.step_ins = FALSE; 7811 CUR.step_ins = FALSE;
7179 return; 7812 return;
7180 } 7813 }
7181 } 7814 }
7182 7815
7183 CUR.error = TT_Err_Invalid_Opcode; 7816 CUR.error = FT_THROW( Invalid_Opcode );
7184 } 7817 }
7185 7818
7186 7819
7187 #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH 7820 #ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
7188 7821
7189 7822
7190 static 7823 static
7191 TInstruction_Function Instruct_Dispatch[256] = 7824 TInstruction_Function Instruct_Dispatch[256] =
7192 { 7825 {
7193 /* Opcodes are gathered in groups of 16. */ 7826 /* Opcodes are gathered in groups of 16. */
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
7500 /* Instructions appear in the specification's order. */ 8133 /* Instructions appear in the specification's order. */
7501 /* */ 8134 /* */
7502 /*************************************************************************/ 8135 /*************************************************************************/
7503 8136
7504 8137
7505 /* documentation is in ttinterp.h */ 8138 /* documentation is in ttinterp.h */
7506 8139
7507 FT_EXPORT_DEF( FT_Error ) 8140 FT_EXPORT_DEF( FT_Error )
7508 TT_RunIns( TT_ExecContext exc ) 8141 TT_RunIns( TT_ExecContext exc )
7509 { 8142 {
7510 FT_Long ins_counter = 0; /* executed instructions counter */ 8143 FT_Long ins_counter = 0; /* executed instructions counter */
8144 FT_UShort i;
8145
8146 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
8147 FT_Byte opcode_pattern[1][2] = {
8148 /* #8 TypeMan Talk Align */
8149 {
8150 0x06, /* SPVTL */
8151 0x7D, /* RDTG */
8152 },
8153 };
8154 FT_UShort opcode_patterns = 1;
8155 FT_UShort opcode_pointer[1] = { 0 };
8156 FT_UShort opcode_size[1] = { 1 };
8157 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
7511 8158
7512 8159
7513 #ifdef TT_CONFIG_OPTION_STATIC_RASTER 8160 #ifdef TT_CONFIG_OPTION_STATIC_RASTER
7514 cur = *exc; 8161 cur = *exc;
7515 #endif 8162 #endif
7516 8163
8164 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
8165 CUR.iup_called = FALSE;
8166 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
8167
7517 /* set CVT functions */ 8168 /* set CVT functions */
7518 CUR.tt_metrics.ratio = 0; 8169 CUR.tt_metrics.ratio = 0;
7519 if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem ) 8170 if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
7520 { 8171 {
7521 /* non-square pixels, use the stretched routines */ 8172 /* non-square pixels, use the stretched routines */
7522 CUR.func_read_cvt = Read_CVT_Stretched; 8173 CUR.func_read_cvt = Read_CVT_Stretched;
7523 CUR.func_write_cvt = Write_CVT_Stretched; 8174 CUR.func_write_cvt = Write_CVT_Stretched;
7524 CUR.func_move_cvt = Move_CVT_Stretched; 8175 CUR.func_move_cvt = Move_CVT_Stretched;
7525 } 8176 }
7526 else 8177 else
(...skipping 26 matching lines...) Expand all
7553 if ( CUR.IP + CUR.length > CUR.codeSize ) 8204 if ( CUR.IP + CUR.length > CUR.codeSize )
7554 goto LErrorCodeOverflow_; 8205 goto LErrorCodeOverflow_;
7555 8206
7556 /* First, let's check for empty stack and overflow */ 8207 /* First, let's check for empty stack and overflow */
7557 CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 ); 8208 CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
7558 8209
7559 /* `args' is the top of the stack once arguments have been popped. */ 8210 /* `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. */ 8211 /* One can also interpret it as the index of the last argument. */
7561 if ( CUR.args < 0 ) 8212 if ( CUR.args < 0 )
7562 { 8213 {
7563 FT_UShort i;
7564
7565
7566 if ( CUR.pedantic_hinting ) 8214 if ( CUR.pedantic_hinting )
7567 { 8215 {
7568 CUR.error = TT_Err_Too_Few_Arguments; 8216 CUR.error = FT_THROW( Too_Few_Arguments );
7569 goto LErrorLabel_; 8217 goto LErrorLabel_;
7570 } 8218 }
7571 8219
7572 /* push zeroes onto the stack */ 8220 /* push zeroes onto the stack */
7573 for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ ) 8221 for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ )
7574 CUR.stack[i] = 0; 8222 CUR.stack[i] = 0;
7575 CUR.args = 0; 8223 CUR.args = 0;
7576 } 8224 }
7577 8225
7578 CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 ); 8226 CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
7579 8227
7580 /* `new_top' is the new top of the stack, after the instruction's */ 8228 /* `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' */ 8229 /* execution. `top' will be set to `new_top' after the `switch' */
7582 /* statement. */ 8230 /* statement. */
7583 if ( CUR.new_top > CUR.stackSize ) 8231 if ( CUR.new_top > CUR.stackSize )
7584 { 8232 {
7585 CUR.error = TT_Err_Stack_Overflow; 8233 CUR.error = FT_THROW( Stack_Overflow );
7586 goto LErrorLabel_; 8234 goto LErrorLabel_;
7587 } 8235 }
7588 8236
7589 CUR.step_ins = TRUE; 8237 CUR.step_ins = TRUE;
7590 CUR.error = TT_Err_Ok; 8238 CUR.error = FT_Err_Ok;
8239
8240 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
8241
8242 if ( SUBPIXEL_HINTING )
8243 {
8244 for ( i = 0; i < opcode_patterns; i++ )
8245 {
8246 if ( opcode_pointer[i] < opcode_size[i] &&
8247 CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
8248 {
8249 opcode_pointer[i] += 1;
8250
8251 if ( opcode_pointer[i] == opcode_size[i] )
8252 {
8253 FT_TRACE7(( "sph: opcode ptrn: %d, %s %s\n",
8254 i,
8255 CUR.face->root.family_name,
8256 CUR.face->root.style_name ));
8257
8258 switch ( i )
8259 {
8260 case 0:
8261 break;
8262 }
8263 opcode_pointer[i] = 0;
8264 }
8265 }
8266 else
8267 opcode_pointer[i] = 0;
8268 }
8269 }
8270
8271 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
7591 8272
7592 #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH 8273 #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
7593 8274
7594 { 8275 {
7595 FT_Long* args = CUR.stack + CUR.args; 8276 FT_Long* args = CUR.stack + CUR.args;
7596 FT_Byte opcode = CUR.opcode; 8277 FT_Byte opcode = CUR.opcode;
7597 8278
7598 8279
7599 #undef ARRAY_BOUND_ERROR 8280 #undef ARRAY_BOUND_ERROR
7600 #define ARRAY_BOUND_ERROR goto Set_Invalid_Ref 8281 #define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
7794 8475
7795 case 0x2D: /* ENDF */ 8476 case 0x2D: /* ENDF */
7796 Ins_ENDF( EXEC_ARG_ args ); 8477 Ins_ENDF( EXEC_ARG_ args );
7797 break; 8478 break;
7798 8479
7799 case 0x2E: /* MDAP */ 8480 case 0x2E: /* MDAP */
7800 case 0x2F: /* MDAP */ 8481 case 0x2F: /* MDAP */
7801 Ins_MDAP( EXEC_ARG_ args ); 8482 Ins_MDAP( EXEC_ARG_ args );
7802 break; 8483 break;
7803 8484
7804
7805 case 0x30: /* IUP */ 8485 case 0x30: /* IUP */
7806 case 0x31: /* IUP */ 8486 case 0x31: /* IUP */
7807 Ins_IUP( EXEC_ARG_ args ); 8487 Ins_IUP( EXEC_ARG_ args );
7808 break; 8488 break;
7809 8489
7810 case 0x32: /* SHP */ 8490 case 0x32: /* SHP */
7811 case 0x33: /* SHP */ 8491 case 0x33: /* SHP */
7812 Ins_SHP( EXEC_ARG_ args ); 8492 Ins_SHP( EXEC_ARG_ args );
7813 break; 8493 break;
7814 8494
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
7854 8534
7855 case 0x41: /* NPUSHW */ 8535 case 0x41: /* NPUSHW */
7856 Ins_NPUSHW( EXEC_ARG_ args ); 8536 Ins_NPUSHW( EXEC_ARG_ args );
7857 break; 8537 break;
7858 8538
7859 case 0x42: /* WS */ 8539 case 0x42: /* WS */
7860 DO_WS 8540 DO_WS
7861 break; 8541 break;
7862 8542
7863 Set_Invalid_Ref: 8543 Set_Invalid_Ref:
7864 CUR.error = TT_Err_Invalid_Reference; 8544 CUR.error = FT_THROW( Invalid_Reference );
7865 break; 8545 break;
7866 8546
7867 case 0x43: /* RS */ 8547 case 0x43: /* RS */
7868 DO_RS 8548 DO_RS
7869 break; 8549 break;
7870 8550
7871 case 0x44: /* WCVTP */ 8551 case 0x44: /* WCVTP */
7872 DO_WCVTP 8552 DO_WCVTP
7873 break; 8553 break;
7874 8554
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
8144 } 8824 }
8145 8825
8146 } 8826 }
8147 8827
8148 #else 8828 #else
8149 8829
8150 Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] ); 8830 Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
8151 8831
8152 #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */ 8832 #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
8153 8833
8154 if ( CUR.error != TT_Err_Ok ) 8834 if ( CUR.error )
8155 { 8835 {
8156 switch ( CUR.error ) 8836 switch ( CUR.error )
8157 { 8837 {
8158 case TT_Err_Invalid_Opcode: /* looking for redefined instructions */ 8838 /* looking for redefined instructions */
8839 case FT_ERR( Invalid_Opcode ):
8159 { 8840 {
8160 TT_DefRecord* def = CUR.IDefs; 8841 TT_DefRecord* def = CUR.IDefs;
8161 TT_DefRecord* limit = def + CUR.numIDefs; 8842 TT_DefRecord* limit = def + CUR.numIDefs;
8162 8843
8163 8844
8164 for ( ; def < limit; def++ ) 8845 for ( ; def < limit; def++ )
8165 { 8846 {
8166 if ( def->active && CUR.opcode == (FT_Byte)def->opc ) 8847 if ( def->active && CUR.opcode == (FT_Byte)def->opc )
8167 { 8848 {
8168 TT_CallRec* callrec; 8849 TT_CallRec* callrec;
8169 8850
8170 8851
8171 if ( CUR.callTop >= CUR.callSize ) 8852 if ( CUR.callTop >= CUR.callSize )
8172 { 8853 {
8173 CUR.error = TT_Err_Invalid_Reference; 8854 CUR.error = FT_THROW( Invalid_Reference );
8174 goto LErrorLabel_; 8855 goto LErrorLabel_;
8175 } 8856 }
8176 8857
8177 callrec = &CUR.callStack[CUR.callTop]; 8858 callrec = &CUR.callStack[CUR.callTop];
8178 8859
8179 callrec->Caller_Range = CUR.curRange; 8860 callrec->Caller_Range = CUR.curRange;
8180 callrec->Caller_IP = CUR.IP + 1; 8861 callrec->Caller_IP = CUR.IP + 1;
8181 callrec->Cur_Count = 1; 8862 callrec->Cur_Count = 1;
8182 callrec->Cur_Restart = def->start; 8863 callrec->Cur_Restart = def->start;
8183 callrec->Cur_End = def->end; 8864 callrec->Cur_End = def->end;
8184 8865
8185 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE ) 8866 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
8186 goto LErrorLabel_; 8867 goto LErrorLabel_;
8187 8868
8188 goto LSuiteLabel_; 8869 goto LSuiteLabel_;
8189 } 8870 }
8190 } 8871 }
8191 } 8872 }
8192 8873
8193 CUR.error = TT_Err_Invalid_Opcode; 8874 CUR.error = FT_THROW( Invalid_Opcode );
8194 goto LErrorLabel_; 8875 goto LErrorLabel_;
8195 8876
8196 #if 0 8877 #if 0
8197 break; /* Unreachable code warning suppression. */ 8878 break; /* Unreachable code warning suppression. */
8198 /* Leave to remind in case a later change the editor */ 8879 /* Leave to remind in case a later change the editor */
8199 /* to consider break; */ 8880 /* to consider break; */
8200 #endif 8881 #endif
8201 8882
8202 default: 8883 default:
8203 goto LErrorLabel_; 8884 goto LErrorLabel_;
8204 8885
8205 #if 0 8886 #if 0
8206 break; 8887 break;
8207 #endif 8888 #endif
8208 } 8889 }
8209 } 8890 }
8210 8891
8211 CUR.top = CUR.new_top; 8892 CUR.top = CUR.new_top;
8212 8893
8213 if ( CUR.step_ins ) 8894 if ( CUR.step_ins )
8214 CUR.IP += CUR.length; 8895 CUR.IP += CUR.length;
8215 8896
8216 /* increment instruction counter and check if we didn't */ 8897 /* increment instruction counter and check if we didn't */
8217 /* run this program for too long (e.g. infinite loops). */ 8898 /* run this program for too long (e.g. infinite loops). */
8218 if ( ++ins_counter > MAX_RUNNABLE_OPCODES ) 8899 if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
8219 return TT_Err_Execution_Too_Long; 8900 return FT_THROW( Execution_Too_Long );
8220 8901
8221 LSuiteLabel_: 8902 LSuiteLabel_:
8222 if ( CUR.IP >= CUR.codeSize ) 8903 if ( CUR.IP >= CUR.codeSize )
8223 { 8904 {
8224 if ( CUR.callTop > 0 ) 8905 if ( CUR.callTop > 0 )
8225 { 8906 {
8226 CUR.error = TT_Err_Code_Overflow; 8907 CUR.error = FT_THROW( Code_Overflow );
8227 goto LErrorLabel_; 8908 goto LErrorLabel_;
8228 } 8909 }
8229 else 8910 else
8230 goto LNo_Error_; 8911 goto LNo_Error_;
8231 } 8912 }
8232 } while ( !CUR.instruction_trap ); 8913 } while ( !CUR.instruction_trap );
8233 8914
8234 LNo_Error_: 8915 LNo_Error_:
8235 8916
8236 #ifdef TT_CONFIG_OPTION_STATIC_RASTER 8917 #ifdef TT_CONFIG_OPTION_STATIC_RASTER
8237 *exc = cur; 8918 *exc = cur;
8238 #endif 8919 #endif
8239 8920
8240 return TT_Err_Ok; 8921 return FT_Err_Ok;
8241 8922
8242 LErrorCodeOverflow_: 8923 LErrorCodeOverflow_:
8243 CUR.error = TT_Err_Code_Overflow; 8924 CUR.error = FT_THROW( Code_Overflow );
8244 8925
8245 LErrorLabel_: 8926 LErrorLabel_:
8246 8927
8247 #ifdef TT_CONFIG_OPTION_STATIC_RASTER 8928 #ifdef TT_CONFIG_OPTION_STATIC_RASTER
8248 *exc = cur; 8929 *exc = cur;
8249 #endif 8930 #endif
8250 8931
8251 /* If any errors have occurred, function tables may be broken. */ 8932 /* If any errors have occurred, function tables may be broken. */
8252 /* Force a re-execution of `prep' and `fpgm' tables if no */ 8933 /* Force a re-execution of `prep' and `fpgm' tables if no */
8253 /* bytecode debugger is run. */ 8934 /* bytecode debugger is run. */
8254 if ( CUR.error && !CUR.instruction_trap ) 8935 if ( CUR.error && !CUR.instruction_trap )
8255 { 8936 {
8256 FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error )); 8937 FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
8257 exc->size->cvt_ready = FALSE; 8938 exc->size->cvt_ready = FALSE;
8258 } 8939 }
8259 8940
8260 return CUR.error; 8941 return CUR.error;
8261 } 8942 }
8262 8943
8263 8944
8264 #endif /* TT_USE_BYTECODE_INTERPRETER */ 8945 #endif /* TT_USE_BYTECODE_INTERPRETER */
8265 8946
8266 8947
8267 /* END */ 8948 /* END */
OLDNEW
« no previous file with comments | « src/truetype/ttinterp.h ('k') | src/truetype/ttobjs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698