diff options
Diffstat (limited to 'src/3rdparty/freetype/src/truetype/ttinterp.c')
-rw-r--r-- | src/3rdparty/freetype/src/truetype/ttinterp.c | 1462 |
1 files changed, 869 insertions, 593 deletions
diff --git a/src/3rdparty/freetype/src/truetype/ttinterp.c b/src/3rdparty/freetype/src/truetype/ttinterp.c index ae2a82adc5..da9b595aba 100644 --- a/src/3rdparty/freetype/src/truetype/ttinterp.c +++ b/src/3rdparty/freetype/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (body). */ /* */ -/* Copyright 1996-2015 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -25,11 +25,15 @@ #include FT_INTERNAL_CALC_H #include FT_TRIGONOMETRY_H #include FT_SYSTEM_H -#include FT_TRUETYPE_DRIVER_H +#include FT_DRIVER_H +#include FT_MULTIPLE_MASTERS_H #include "ttinterp.h" #include "tterrors.h" #include "ttsubpix.h" +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include "ttgxvar.h" +#endif #ifdef TT_USE_BYTECODE_INTERPRETER @@ -45,25 +49,31 @@ #define FT_COMPONENT trace_ttinterp - /*************************************************************************/ - /* */ - /* In order to detect infinite loops in the code, we set up a counter */ - /* within the run loop. A single stroke of interpretation is now */ - /* limited to a maximum number of opcodes defined below. */ - /* */ -#define MAX_RUNNABLE_OPCODES 1000000L - +#define NO_SUBPIXEL_HINTING \ + ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ + TT_INTERPRETER_VERSION_35 ) -#define SUBPIXEL_HINTING \ +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY +#define SUBPIXEL_HINTING_INFINALITY \ ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ TT_INTERPRETER_VERSION_38 ) +#endif +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL +#define SUBPIXEL_HINTING_MINIMAL \ + ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ + TT_INTERPRETER_VERSION_40 ) +#endif -#define PROJECT( v1, v2 ) \ - exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y ) +#define PROJECT( v1, v2 ) \ + exc->func_project( exc, \ + SUB_LONG( (v1)->x, (v2)->x ), \ + SUB_LONG( (v1)->y, (v2)->y ) ) -#define DUALPROJ( v1, v2 ) \ - exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y ) +#define DUALPROJ( v1, v2 ) \ + exc->func_dualproj( exc, \ + SUB_LONG( (v1)->x, (v2)->x ), \ + SUB_LONG( (v1)->y, (v2)->y ) ) #define FAST_PROJECT( v ) \ exc->func_project( exc, (v)->x, (v)->y ) @@ -74,14 +84,6 @@ /*************************************************************************/ /* */ - /* Instruction dispatch function, as used by the interpreter. */ - /* */ - typedef void (*TInstruction_Function)( TT_ExecContext exc, - FT_Long* args ); - - - /*************************************************************************/ - /* */ /* Two simple bounds-checking macros. */ /* */ #define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) @@ -94,20 +96,6 @@ #undef FAILURE #define FAILURE 1 -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING -#define GUESS_VECTOR( V ) \ - do \ - { \ - if ( exc->face->unpatented_hinting ) \ - { \ - exc->GS.V.x = (FT_F2Dot14)( exc->GS.both_x_axis ? 0x4000 : 0 ); \ - exc->GS.V.y = (FT_F2Dot14)( exc->GS.both_x_axis ? 0 : 0x4000 ); \ - } \ - } while (0) -#else -#define GUESS_VECTOR( V ) do { } while (0) -#endif - /*************************************************************************/ /* */ @@ -145,7 +133,7 @@ coderange = &exec->codeRangeTable[range - 1]; - FT_ASSERT( coderange->base != NULL ); + FT_ASSERT( coderange->base ); /* NOTE: Because the last instruction of a program may be a CALL */ /* which will return to the first byte *after* the code */ @@ -309,8 +297,8 @@ exec->stackSize = 0; exec->glyphSize = 0; - exec->stack = NULL; - exec->glyphIns = NULL; + exec->stack = NULL; + exec->glyphIns = NULL; exec->face = NULL; exec->size = NULL; @@ -416,8 +404,9 @@ exec->maxIDefs = size->max_instruction_defs; exec->FDefs = size->function_defs; exec->IDefs = size->instruction_defs; + exec->pointSize = size->point_size; exec->tt_metrics = size->ttmetrics; - exec->metrics = size->metrics; + exec->metrics = *size->metrics; exec->maxFunc = size->max_func; exec->maxIns = size->max_ins; @@ -438,7 +427,7 @@ /* In case of multi-threading it can happen that the old size object */ /* no longer exists, thus we must clear all glyph zone references. */ - ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) ); + FT_ZERO( &exec->zp0 ); exec->zp1 = exec->zp0; exec->zp2 = exec->zp0; } @@ -556,10 +545,6 @@ exec->GS.freeVector = exec->GS.projVector; exec->GS.dualVector = exec->GS.projVector; -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - exec->GS.both_x_axis = TRUE; -#endif - exec->GS.round_state = 1; exec->GS.loop = 1; @@ -586,10 +571,6 @@ { 0x4000, 0 }, { 0x4000, 0 }, -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - TRUE, -#endif - 1, 64, 1, TRUE, 68, 0, 0, 9, 3, 0, FALSE, 0, 1, 1, 1 @@ -709,17 +690,17 @@ /* IUP[0] */ PACK( 0, 0 ), /* IUP[1] */ PACK( 0, 0 ), - /* SHP[0] */ PACK( 0, 0 ), - /* SHP[1] */ PACK( 0, 0 ), + /* SHP[0] */ PACK( 0, 0 ), /* loops */ + /* SHP[1] */ PACK( 0, 0 ), /* loops */ /* SHC[0] */ PACK( 1, 0 ), /* SHC[1] */ PACK( 1, 0 ), /* SHZ[0] */ PACK( 1, 0 ), /* SHZ[1] */ PACK( 1, 0 ), - /* SHPIX */ PACK( 1, 0 ), - /* IP */ PACK( 0, 0 ), + /* SHPIX */ PACK( 1, 0 ), /* loops */ + /* IP */ PACK( 0, 0 ), /* loops */ /* MSIRP[0] */ PACK( 2, 0 ), /* MSIRP[1] */ PACK( 2, 0 ), - /* AlignRP */ PACK( 0, 0 ), + /* AlignRP */ PACK( 0, 0 ), /* loops */ /* RTDG */ PACK( 0, 0 ), /* MIAP[0] */ PACK( 2, 0 ), /* MIAP[1] */ PACK( 2, 0 ), @@ -792,7 +773,7 @@ /* SANGW */ PACK( 1, 0 ), /* AA */ PACK( 1, 0 ), - /* FlipPT */ PACK( 0, 0 ), + /* FlipPT */ PACK( 0, 0 ), /* loops */ /* FlipRgON */ PACK( 2, 0 ), /* FlipRgOFF */ PACK( 2, 0 ), /* INS_$83 */ PACK( 0, 0 ), @@ -810,8 +791,8 @@ /* INS_$8F */ PACK( 0, 0 ), /* INS_$90 */ PACK( 0, 0 ), - /* INS_$91 */ PACK( 0, 0 ), - /* INS_$92 */ PACK( 0, 0 ), + /* GETVAR */ PACK( 0, 0 ), /* will be handled specially */ + /* GETDATA */ PACK( 0, 1 ), /* INS_$93 */ PACK( 0, 0 ), /* INS_$94 */ PACK( 0, 0 ), /* INS_$95 */ PACK( 0, 0 ), @@ -1093,8 +1074,13 @@ "7 INS_$8F", "7 INS_$90", +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + "6 GETVAR", + "7 GETDATA", +#else "7 INS_$91", "7 INS_$92", +#endif "7 INS_$93", "7 INS_$94", "7 INS_$95", @@ -1479,34 +1465,22 @@ { if ( !exc->tt_metrics.ratio ) { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - if ( exc->GS.both_x_axis ) - exc->tt_metrics.ratio = exc->tt_metrics.x_ratio; - else - exc->tt_metrics.ratio = exc->tt_metrics.y_ratio; - } - else -#endif - { - if ( exc->GS.projVector.y == 0 ) - exc->tt_metrics.ratio = exc->tt_metrics.x_ratio; + if ( exc->GS.projVector.y == 0 ) + exc->tt_metrics.ratio = exc->tt_metrics.x_ratio; - else if ( exc->GS.projVector.x == 0 ) - exc->tt_metrics.ratio = exc->tt_metrics.y_ratio; + else if ( exc->GS.projVector.x == 0 ) + exc->tt_metrics.ratio = exc->tt_metrics.y_ratio; - else - { - FT_F26Dot6 x, y; + else + { + FT_F26Dot6 x, y; - x = TT_MulFix14( exc->tt_metrics.x_ratio, - exc->GS.projVector.x ); - y = TT_MulFix14( exc->tt_metrics.y_ratio, - exc->GS.projVector.y ); - exc->tt_metrics.ratio = FT_Hypot( x, y ); - } + x = TT_MulFix14( exc->tt_metrics.x_ratio, + exc->GS.projVector.x ); + y = TT_MulFix14( exc->tt_metrics.y_ratio, + exc->GS.projVector.y ); + exc->tt_metrics.ratio = FT_Hypot( x, y ); } } return exc->tt_metrics.ratio; @@ -1604,7 +1578,7 @@ static FT_Short GetShortIns( TT_ExecContext exc ) { - /* Reading a byte stream so there is no endianess (DaveP) */ + /* Reading a byte stream so there is no endianness (DaveP) */ exc->IP += 2; return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) + exc->code[exc->IP - 1] ); @@ -1643,7 +1617,7 @@ range = &exc->codeRangeTable[aRange - 1]; - if ( range->base == NULL ) /* invalid coderange */ + if ( !range->base ) /* invalid coderange */ { exc->error = FT_THROW( Invalid_CodeRange ); return FAILURE; @@ -1685,6 +1659,10 @@ /* <InOut> */ /* zone :: The affected glyph zone. */ /* */ + /* <Note> */ + /* See `ttinterp.h' for details on backward compatibility mode. */ + /* `Touches' the point. */ + /* */ static void Direct_Move( TT_ExecContext exc, TT_GlyphZone zone, @@ -1694,20 +1672,38 @@ FT_F26Dot6 v; -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_ASSERT( !exc->face->unpatented_hinting ); -#endif - v = exc->GS.freeVector.x; if ( v != 0 ) { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( !SUBPIXEL_HINTING || +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && ( !exc->ignore_x_mode || ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].x = ADD_LONG( zone->cur[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); + else +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* Exception to the post-IUP curfew: Allow the x component of */ + /* diagonal moves, but only post-IUP. DejaVu tries to adjust */ + /* diagonal stems like on `Z' and `z' post-IUP. */ + if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) + zone->cur[point].x = ADD_LONG( zone->cur[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); + else +#endif + + if ( NO_SUBPIXEL_HINTING ) + zone->cur[point].x = ADD_LONG( zone->cur[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1716,7 +1712,16 @@ if ( v != 0 ) { - zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) ) +#endif + zone->cur[point].y = ADD_LONG( zone->cur[point].y, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1749,19 +1754,21 @@ FT_F26Dot6 v; -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_ASSERT( !exc->face->unpatented_hinting ); -#endif - v = exc->GS.freeVector.x; if ( v != 0 ) - zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->org[point].x = ADD_LONG( zone->org[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); v = exc->GS.freeVector.y; if ( v != 0 ) - zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->org[point].y = ADD_LONG( zone->org[point].y, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); } @@ -1771,6 +1778,7 @@ /* */ /* The following versions are used whenever both vectors are both */ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ /* */ /*************************************************************************/ @@ -1781,13 +1789,20 @@ FT_UShort point, FT_F26Dot6 distance ) { - FT_UNUSED( exc ); +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode ) + zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); + else +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( !SUBPIXEL_HINTING || - !exc->ignore_x_mode ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - zone->cur[point].x += distance; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) + zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); + else +#endif + + if ( NO_SUBPIXEL_HINTING ) + zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1801,8 +1816,14 @@ { FT_UNUSED( exc ); - zone->cur[point].y += distance; - zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && exc->iupy_called ) ) +#endif + zone->cur[point].y = ADD_LONG( zone->cur[point].y, distance ); + + zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1824,7 +1845,7 @@ { FT_UNUSED( exc ); - zone->org[point].x += distance; + zone->org[point].x = ADD_LONG( zone->org[point].x, distance ); } @@ -1836,7 +1857,7 @@ { FT_UNUSED( exc ); - zone->org[point].y += distance; + zone->org[point].y = ADD_LONG( zone->org[point].y, distance ); } @@ -1874,13 +1895,13 @@ if ( distance >= 0 ) { - val = distance + compensation; + val = ADD_LONG( distance, compensation ); if ( val < 0 ) val = 0; } else { - val = distance - compensation; + val = SUB_LONG( distance, compensation ); if ( val > 0 ) val = 0; } @@ -1916,13 +1937,14 @@ if ( distance >= 0 ) { - val = FT_PIX_ROUND( distance + compensation ); + val = FT_PIX_ROUND_LONG( ADD_LONG( distance, compensation ) ); if ( val < 0 ) val = 0; } else { - val = -FT_PIX_ROUND( compensation - distance ); + val = NEG_LONG( FT_PIX_ROUND_LONG( SUB_LONG( compensation, + distance ) ) ); if ( val > 0 ) val = 0; } @@ -1959,13 +1981,16 @@ if ( distance >= 0 ) { - val = FT_PIX_FLOOR( distance + compensation ) + 32; + val = ADD_LONG( FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ), + 32 ); if ( val < 0 ) val = 32; } else { - val = -( FT_PIX_FLOOR( compensation - distance ) + 32 ); + val = NEG_LONG( ADD_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, + distance ) ), + 32 ) ); if ( val > 0 ) val = -32; } @@ -2002,13 +2027,13 @@ if ( distance >= 0 ) { - val = FT_PIX_FLOOR( distance + compensation ); + val = FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ); if ( val < 0 ) val = 0; } else { - val = -FT_PIX_FLOOR( compensation - distance ); + val = NEG_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, distance ) ) ); if ( val > 0 ) val = 0; } @@ -2045,13 +2070,14 @@ if ( distance >= 0 ) { - val = FT_PIX_CEIL( distance + compensation ); + val = FT_PIX_CEIL_LONG( ADD_LONG( distance, compensation ) ); if ( val < 0 ) val = 0; } else { - val = -FT_PIX_CEIL( compensation - distance ); + val = NEG_LONG( FT_PIX_CEIL_LONG( SUB_LONG( compensation, + distance ) ) ); if ( val > 0 ) val = 0; } @@ -2081,20 +2107,21 @@ FT_F26Dot6 distance, FT_F26Dot6 compensation ) { - FT_F26Dot6 val; + FT_F26Dot6 val; FT_UNUSED( exc ); if ( distance >= 0 ) { - val = FT_PAD_ROUND( distance + compensation, 32 ); + val = FT_PAD_ROUND_LONG( ADD_LONG( distance, compensation ), 32 ); if ( val < 0 ) val = 0; } else { - val = -FT_PAD_ROUND( compensation - distance, 32 ); + val = NEG_LONG( FT_PAD_ROUND_LONG( SUB_LONG( compensation, distance ), + 32 ) ); if ( val > 0 ) val = 0; } @@ -2120,7 +2147,7 @@ /* Rounded distance. */ /* */ /* <Note> */ - /* The TrueType specification says very few about the relationship */ + /* The TrueType specification says very little about the relationship */ /* between rounding and engine compensation. However, it seems from */ /* the description of super round that we should add the compensation */ /* before rounding. */ @@ -2135,17 +2162,19 @@ if ( distance >= 0 ) { - val = ( distance - exc->phase + exc->threshold + compensation ) & + val = ADD_LONG( distance, + exc->threshold - exc->phase + compensation ) & -exc->period; - val += exc->phase; + val = ADD_LONG( val, exc->phase ); if ( val < 0 ) val = exc->phase; } else { - val = -( ( exc->threshold - exc->phase - distance + compensation ) & - -exc->period ); - val -= exc->phase; + val = NEG_LONG( SUB_LONG( exc->threshold - exc->phase + compensation, + distance ) & + -exc->period ); + val = SUB_LONG( val, exc->phase ); if ( val > 0 ) val = -exc->phase; } @@ -2184,17 +2213,19 @@ if ( distance >= 0 ) { - val = ( ( distance - exc->phase + exc->threshold + compensation ) / + val = ( ADD_LONG( distance, + exc->threshold - exc->phase + compensation ) / exc->period ) * exc->period; - val += exc->phase; + val = ADD_LONG( val, exc->phase ); if ( val < 0 ) val = exc->phase; } else { - val = -( ( ( exc->threshold - exc->phase - distance + compensation ) / - exc->period ) * exc->period ); - val -= exc->phase; + val = NEG_LONG( ( SUB_LONG( exc->threshold - exc->phase + compensation, + distance ) / + exc->period ) * exc->period ); + val = SUB_LONG( val, exc->phase ); if ( val > 0 ) val = -exc->phase; } @@ -2345,10 +2376,6 @@ FT_Pos dx, FT_Pos dy ) { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_ASSERT( !exc->face->unpatented_hinting ); -#endif - return TT_DotFix14( dx, dy, exc->GS.projVector.x, exc->GS.projVector.y ); @@ -2450,51 +2477,6 @@ static void Compute_Funcs( TT_ExecContext exc ) { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - /* If both vectors point rightwards along the x axis, set */ - /* `both-x-axis' true, otherwise set it false. The x values only */ - /* need be tested because the vector has been normalised to a unit */ - /* vector of length 0x4000 = unity. */ - exc->GS.both_x_axis = (FT_Bool)( exc->GS.projVector.x == 0x4000 && - exc->GS.freeVector.x == 0x4000 ); - - /* Throw away projection and freedom vector information */ - /* because the patents don't allow them to be stored. */ - /* The relevant US Patents are 5155805 and 5325479. */ - exc->GS.projVector.x = 0; - exc->GS.projVector.y = 0; - exc->GS.freeVector.x = 0; - exc->GS.freeVector.y = 0; - - if ( exc->GS.both_x_axis ) - { - exc->func_project = Project_x; - exc->func_move = Direct_Move_X; - exc->func_move_orig = Direct_Move_Orig_X; - } - else - { - exc->func_project = Project_y; - exc->func_move = Direct_Move_Y; - exc->func_move_orig = Direct_Move_Orig_Y; - } - - if ( exc->GS.dualVector.x == 0x4000 ) - exc->func_dualproj = Project_x; - else if ( exc->GS.dualVector.y == 0x4000 ) - exc->func_dualproj = Project_y; - else - exc->func_dualproj = Dual_Project; - - /* Force recalculation of cached aspect ratio */ - exc->tt_metrics.ratio = 0; - - return; - } -#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ - if ( exc->GS.freeVector.x == 0x4000 ) exc->F_dot_P = exc->GS.projVector.x; else if ( exc->GS.freeVector.y == 0x4000 ) @@ -2634,13 +2616,20 @@ Ins_MPS( TT_ExecContext exc, FT_Long* args ) { - /* Note: The point size should be irrelevant in a given font program; */ - /* we thus decide to return only the PPEM value. */ -#if 0 - args[0] = exc->metrics.pointSize; -#else - args[0] = exc->func_cur_ppem( exc ); -#endif + if ( NO_SUBPIXEL_HINTING ) + { + /* Microsoft's GDI bytecode interpreter always returns value 12; */ + /* we return the current PPEM value instead. */ + args[0] = exc->func_cur_ppem( exc ); + } + else + { + /* A possible practical application of the MPS instruction is to */ + /* implement optical scaling and similar features, which should be */ + /* based on perceptual attributes, thus independent of the */ + /* resolution. */ + args[0] = exc->pointSize; + } } @@ -2869,7 +2858,7 @@ static void Ins_ADD( FT_Long* args ) { - args[0] += args[1]; + args[0] = ADD_LONG( args[0], args[1] ); } @@ -2882,7 +2871,7 @@ static void Ins_SUB( FT_Long* args ) { - args[0] -= args[1]; + args[0] = SUB_LONG( args[0], args[1] ); } @@ -2925,7 +2914,8 @@ static void Ins_ABS( FT_Long* args ) { - args[0] = FT_ABS( args[0] ); + if ( args[0] < 0 ) + args[0] = NEG_LONG( args[0] ); } @@ -2933,12 +2923,12 @@ /* */ /* NEG[]: NEGate */ /* Opcode range: 0x65 */ - /* Stack: f26.6 --> f26.6 */ + /* Stack: f26.6 --> f26.6 */ /* */ static void Ins_NEG( FT_Long* args ) { - args[0] = -args[0]; + args[0] = NEG_LONG( args[0] ); } @@ -2964,7 +2954,7 @@ static void Ins_CEILING( FT_Long* args ) { - args[0] = FT_PIX_CEIL( args[0] ); + args[0] = FT_PIX_CEIL_LONG( args[0] ); } @@ -2978,8 +2968,6 @@ Ins_RS( TT_ExecContext exc, FT_Long* args ) { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_ULong I = (FT_ULong)args[0]; @@ -2992,9 +2980,10 @@ } else { +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* subpixel hinting - avoid Typeman Dstroke and */ /* IStroke and Vacuform rounds */ - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && ( ( I == 24 && ( exc->face->sph_found_func_flags & @@ -3009,25 +2998,9 @@ exc->iup_called ) ) ) args[0] = 0; else +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ args[0] = exc->storage[I]; } - -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - FT_ULong I = (FT_ULong)args[0]; - - - if ( BOUNDSL( I, exc->storeSize ) ) - { - if ( exc->pedantic_hinting ) - ARRAY_BOUND_ERROR; - else - args[0] = 0; - } - else - args[0] = exc->storage[I]; - -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ } @@ -3190,7 +3163,7 @@ /*************************************************************************/ /* */ /* MAX[]: MAXimum */ - /* Opcode range: 0x68 */ + /* Opcode range: 0x8B */ /* Stack: int32? int32? --> int32 */ /* */ static void @@ -3204,7 +3177,7 @@ /*************************************************************************/ /* */ /* MIN[]: MINimum */ - /* Opcode range: 0x69 */ + /* Opcode range: 0x8C */ /* Stack: int32? int32? --> int32 */ /* */ static void @@ -3316,7 +3289,10 @@ if ( args[0] < 0 ) exc->error = FT_THROW( Bad_Argument ); else - exc->GS.loop = args[0]; + { + /* we heuristically limit the number of loops to 16 bits */ + exc->GS.loop = args[0] > 0xFFFFL ? 0xFFFFL : args[0]; + } } @@ -3448,13 +3424,27 @@ FT_Long* args ) { if ( args[0] == 0 && exc->args == 0 ) + { exc->error = FT_THROW( Bad_Argument ); + return; + } + exc->IP += args[0]; if ( exc->IP < 0 || ( exc->callTop > 0 && exc->IP > exc->callStack[exc->callTop - 1].Def->end ) ) + { exc->error = FT_THROW( Bad_Argument ); + return; + } + exc->step_ins = FALSE; + + if ( args[0] < 0 ) + { + if ( ++exc->neg_jump_counter > exc->neg_jump_counter_max ) + exc->error = FT_THROW( Execution_Too_Long ); + } } @@ -3509,7 +3499,7 @@ TT_DefRecord* rec; TT_DefRecord* limit; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* arguments to opcodes are skipped by `SKIP_Code' */ FT_Byte opcode_pattern[9][12] = { /* #0 inline delta function 1 */ @@ -3607,8 +3597,15 @@ FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 }; FT_UShort i; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + + /* FDEF is only allowed in `prep' or `fpgm' */ + if ( exc->curRange == tt_coderange_glyph ) + { + exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); + return; + } /* some font programs are broken enough to redefine functions! */ /* We will then parse the current table. */ @@ -3652,7 +3649,7 @@ if ( n > exc->maxFunc ) exc->maxFunc = (FT_UInt16)n; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* We don't know for sure these are typeman functions, */ /* however they are only active when RS 22 is called */ if ( n >= 64 && n <= 66 ) @@ -3665,9 +3662,9 @@ while ( SkipCode( exc ) == SUCCESS ) { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { for ( i = 0; i < opcode_patterns; i++ ) { @@ -3774,7 +3771,7 @@ ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ); } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ switch ( exc->opcode ) { @@ -3803,9 +3800,9 @@ TT_CallRec* pRec; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY exc->sph_in_func_flags = 0x0000; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ if ( exc->callTop <= 0 ) /* We encountered an ENDF without a call */ { @@ -3891,8 +3888,8 @@ if ( !def->active ) goto Fail; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && ( ( exc->iup_called && ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) || @@ -3900,7 +3897,7 @@ goto Fail; else exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ /* check the call stack */ if ( exc->callTop >= exc->callSize ) @@ -3979,14 +3976,14 @@ if ( !def->active ) goto Fail; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) goto Fail; else exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ /* check stack */ if ( exc->callTop >= exc->callSize ) @@ -4009,6 +4006,10 @@ Ins_Goto_CodeRange( exc, def->range, def->start ); exc->step_ins = FALSE; + + exc->loopcall_counter += (FT_ULong)args[0]; + if ( exc->loopcall_counter > exc->loopcall_counter_max ) + exc->error = FT_THROW( Execution_Too_Long ); } return; @@ -4032,6 +4033,13 @@ TT_DefRecord* limit; + /* we enable IDEF only in `prep' or `fpgm' */ + if ( exc->curRange == tt_coderange_glyph ) + { + exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); + return; + } + /* First of all, look for the same function in our table */ def = exc->IDefs; @@ -4079,6 +4087,7 @@ exc->error = FT_THROW( Nested_DEFS ); return; case 0x2D: /* ENDF */ + def->end = exc->IP; return; } } @@ -4238,8 +4247,8 @@ p1 = exc->zp1.cur + aIdx2; p2 = exc->zp2.cur + aIdx1; - A = p1->x - p2->x; - B = p1->y - p2->y; + A = SUB_LONG( p1->x, p2->x ); + B = SUB_LONG( p1->y, p2->y ); /* If p1 == p2, SPvTL and SFvTL behave the same as */ /* SPvTCA[X] and SFvTCA[X], respectively. */ @@ -4254,9 +4263,9 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; + C = B; /* counter clockwise rotation */ + B = A; + A = NEG_LONG( C ); } Normalize( A, B, Vec ); @@ -4298,16 +4307,12 @@ exc->GS.dualVector.x = AA; exc->GS.dualVector.y = BB; } - else - GUESS_VECTOR( projVector ); if ( ( opcode & 2 ) == 0 ) { exc->GS.freeVector.x = AA; exc->GS.freeVector.y = BB; } - else - GUESS_VECTOR( freeVector ); Compute_Funcs( exc ); } @@ -4329,7 +4334,6 @@ &exc->GS.projVector ) == SUCCESS ) { exc->GS.dualVector = exc->GS.projVector; - GUESS_VECTOR( freeVector ); Compute_Funcs( exc ); } } @@ -4350,7 +4354,6 @@ (FT_UShort)args[0], &exc->GS.freeVector ) == SUCCESS ) { - GUESS_VECTOR( projVector ); Compute_Funcs( exc ); } } @@ -4365,7 +4368,6 @@ static void Ins_SFVTPV( TT_ExecContext exc ) { - GUESS_VECTOR( projVector ); exc->GS.freeVector = exc->GS.projVector; Compute_Funcs( exc ); } @@ -4394,7 +4396,6 @@ Normalize( X, Y, &exc->GS.projVector ); exc->GS.dualVector = exc->GS.projVector; - GUESS_VECTOR( freeVector ); Compute_Funcs( exc ); } @@ -4420,7 +4421,6 @@ X = S; Normalize( X, Y, &exc->GS.freeVector ); - GUESS_VECTOR( projVector ); Compute_Funcs( exc ); } @@ -4435,21 +4435,8 @@ Ins_GPV( TT_ExecContext exc, FT_Long* args ) { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - args[0] = exc->GS.both_x_axis ? 0x4000 : 0; - args[1] = exc->GS.both_x_axis ? 0 : 0x4000; - } - else - { - args[0] = exc->GS.projVector.x; - args[1] = exc->GS.projVector.y; - } -#else args[0] = exc->GS.projVector.x; args[1] = exc->GS.projVector.y; -#endif } @@ -4463,21 +4450,8 @@ Ins_GFV( TT_ExecContext exc, FT_Long* args ) { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - args[0] = exc->GS.both_x_axis ? 0x4000 : 0; - args[1] = exc->GS.both_x_axis ? 0 : 0x4000; - } - else - { - args[0] = exc->GS.freeVector.x; - args[1] = exc->GS.freeVector.y; - } -#else args[0] = exc->GS.freeVector.x; args[1] = exc->GS.freeVector.y; -#endif } @@ -4597,7 +4571,7 @@ /* */ /* FLIPOFF[]: Set auto-FLIP to OFF */ /* Opcode range: 0x4E */ - /* Stack: --> */ + /* Stack: --> */ /* */ static void Ins_FLIPOFF( TT_ExecContext exc ) @@ -4832,7 +4806,7 @@ K = FAST_PROJECT( &exc->zp2.cur[L] ); - exc->func_move( exc, &exc->zp2, L, args[1] - K ); + exc->func_move( exc, &exc->zp2, L, SUB_LONG( args[1], K ) ); /* UNDOCUMENTED! The MS rasterizer does that with */ /* twilight points (confirmed by Greg Hitchcock) */ @@ -4916,13 +4890,13 @@ } } -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - FT_ABS( D ) == 64 ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + FT_ABS( D ) == 64 ) D += 1; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ args[0] = D; } @@ -4956,12 +4930,12 @@ } { - FT_Vector* v1 = exc->zp1.org + p2; - FT_Vector* v2 = exc->zp2.org + p1; + FT_Vector* v1 = exc->zp1.org + p2; + FT_Vector* v2 = exc->zp2.org + p1; - A = v1->x - v2->x; - B = v1->y - v2->y; + A = SUB_LONG( v1->x, v2->x ); + B = SUB_LONG( v1->y, v2->y ); /* If v1 == v2, SDPvTL behaves the same as */ /* SVTCA[X], respectively. */ @@ -4977,9 +4951,9 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; + C = B; /* counter clockwise rotation */ + B = A; + A = NEG_LONG( C ); } Normalize( A, B, &exc->GS.dualVector ); @@ -4989,8 +4963,8 @@ FT_Vector* v2 = exc->zp2.cur + p1; - A = v1->x - v2->x; - B = v1->y - v2->y; + A = SUB_LONG( v1->x, v2->x ); + B = SUB_LONG( v1->y, v2->y ); if ( A == 0 && B == 0 ) { @@ -5001,13 +4975,12 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; + C = B; /* counter clockwise rotation */ + B = A; + A = NEG_LONG( C ); } Normalize( A, B, &exc->GS.projVector ); - GUESS_VECTOR( freeVector ); Compute_Funcs( exc ); } @@ -5179,12 +5152,23 @@ exc->GS.instruct_control &= ~(FT_Byte)Kf; exc->GS.instruct_control |= (FT_Byte)L; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* INSTCTRL modifying flag 3 also has an effect */ - /* outside of the CVT program */ if ( K == 3 ) - exc->ignore_x_mode = FT_BOOL( L == 4 ); + { +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + /* INSTCTRL modifying flag 3 also has an effect */ + /* outside of the CVT program */ + if ( SUBPIXEL_HINTING_INFINALITY ) + exc->ignore_x_mode = FT_BOOL( L == 4 ); #endif + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* Native ClearType fonts sign a waiver that turns off all backward */ + /* compatibility hacks and lets them program points to the grid like */ + /* it's 1996. They might sign a waiver for just one glyph, though. */ + if ( SUBPIXEL_HINTING_MINIMAL ) + exc->backward_compatibility = !FT_BOOL( L == 4 ); +#endif + } } @@ -5239,14 +5223,14 @@ /* */ /* SCANTYPE[]: SCAN TYPE */ /* Opcode range: 0x8D */ - /* Stack: uint32? --> */ + /* Stack: uint16 --> */ /* */ static void Ins_SCANTYPE( TT_ExecContext exc, FT_Long* args ) { if ( args[0] >= 0 ) - exc->GS.scan_type = (FT_Int)args[0]; + exc->GS.scan_type = (FT_Int)args[0] & 0xFFFF; } @@ -5269,6 +5253,15 @@ FT_UShort point; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) + goto Fail; +#endif + if ( exc->top < exc->GS.loop ) { if ( exc->pedantic_hinting ) @@ -5315,6 +5308,15 @@ FT_UShort I, K, L; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) + return; +#endif + K = (FT_UShort)args[1]; L = (FT_UShort)args[0]; @@ -5344,6 +5346,15 @@ FT_UShort I, K, L; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) + return; +#endif + K = (FT_UShort)args[1]; L = (FT_UShort)args[0]; @@ -5396,31 +5407,14 @@ d = PROJECT( zp.cur + p, zp.org + p ); -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - if ( exc->GS.both_x_axis ) - { - *x = d; - *y = 0; - } - else - { - *x = 0; - *y = d; - } - } - else -#endif - { - *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P ); - *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P ); - } + *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P ); + *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P ); return SUCCESS; } + /* See `ttinterp.h' for details on backward compatibility mode. */ static void Move_Zp2_Point( TT_ExecContext exc, FT_UShort point, @@ -5428,35 +5422,28 @@ FT_F26Dot6 dy, FT_Bool touch ) { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) + if ( exc->GS.freeVector.x != 0 ) { - if ( exc->GS.both_x_axis ) - { - exc->zp2.cur[point].x += dx; - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; - } - else - { - exc->zp2.cur[point].y += dy; - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; - } - return; - } +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) ) #endif + exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx ); - if ( exc->GS.freeVector.x != 0 ) - { - exc->zp2.cur[point].x += dx; if ( touch ) exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; } if ( exc->GS.freeVector.y != 0 ) { - exc->zp2.cur[point].y += dy; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) ) +#endif + exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy ); + if ( touch ) exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -5503,13 +5490,12 @@ } } else -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* doesn't follow Cleartype spec but produces better result */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode ) + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode ) Move_Zp2_Point( exc, point, 0, dy, TRUE ); else -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ Move_Zp2_Point( exc, point, dx, dy, TRUE ); exc->GS.loop--; @@ -5637,9 +5623,15 @@ { FT_F26Dot6 dx, dy; FT_UShort point; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY FT_Int B1, B2; #endif +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + FT_Bool in_twilight = FT_BOOL( exc->GS.gep0 == 0 || + exc->GS.gep1 == 0 || + exc->GS.gep2 == 0 ); +#endif + if ( exc->top < exc->GS.loop + 1 ) @@ -5649,26 +5641,8 @@ goto Fail; } -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - if ( exc->GS.both_x_axis ) - { - dx = (FT_UInt32)args[0]; - dy = 0; - } - else - { - dx = 0; - dy = (FT_UInt32)args[0]; - } - } - else -#endif - { - dx = TT_MulFix14( args[0], exc->GS.freeVector.x ); - dy = TT_MulFix14( args[0], exc->GS.freeVector.y ); - } + dx = TT_MulFix14( args[0], exc->GS.freeVector.x ); + dy = TT_MulFix14( args[0], exc->GS.freeVector.y ); while ( exc->GS.loop > 0 ) { @@ -5685,7 +5659,8 @@ } } else -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY ) { /* If not using ignore_x_mode rendering, allow ZP2 move. */ /* If inline deltas aren't allowed, skip ZP2 move. */ @@ -5695,8 +5670,7 @@ /* - the glyph is specifically set to allow SHPIX moves */ /* - the move is on a previously Y-touched point */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode ) + if ( exc->ignore_x_mode ) { /* save point for later comparison */ if ( exc->GS.freeVector.y != 0 ) @@ -5719,7 +5693,11 @@ ( B1 & 63 ) != 0 && ( B2 & 63 ) != 0 && B1 != B2 ) - Move_Zp2_Point( exc, point, -dx, -dy, TRUE ); + Move_Zp2_Point( exc, + point, + NEG_LONG( dx ), + NEG_LONG( dy ), + TRUE ); } } else if ( exc->face->sph_compatibility_mode ) @@ -5751,7 +5729,7 @@ if ( ( B1 & 63 ) == 0 && ( B2 & 63 ) != 0 && B1 != B2 ) - Move_Zp2_Point( exc, point, 0, -dy, TRUE ); + Move_Zp2_Point( exc, point, 0, NEG_LONG( dy ), TRUE ); } } else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL ) @@ -5760,15 +5738,30 @@ else Move_Zp2_Point( exc, point, dx, dy, TRUE ); } + else +#endif +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) + { + /* Special case: allow SHPIX to move points in the twilight zone. */ + /* Otherwise, treat SHPIX the same as DELTAP. Unbreaks various */ + /* fonts such as older versions of Rokkitt and DTL Argo T Light */ + /* that would glitch severely after calling ALIGNRP after a */ + /* blocked SHPIX. */ + if ( in_twilight || + ( !( exc->iupx_called && exc->iupy_called ) && + ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || + ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ) ) ) + Move_Zp2_Point( exc, point, 0, dy, TRUE ); + } + else +#endif + Move_Zp2_Point( exc, point, dx, dy, TRUE ); +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY Skip: - -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - +#endif exc->GS.loop--; } @@ -5788,14 +5781,14 @@ Ins_MSIRP( TT_ExecContext exc, FT_Long* args ) { - FT_UShort point; + FT_UShort point = 0; FT_F26Dot6 distance; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_F26Dot6 control_value_cutin = 0; /* pacify compiler */ +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + FT_F26Dot6 control_value_cutin = 0; + FT_F26Dot6 delta; - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { control_value_cutin = exc->GS.control_value_cutin; @@ -5804,8 +5797,7 @@ !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) control_value_cutin = 0; } - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ point = (FT_UShort)args[0]; @@ -5828,16 +5820,23 @@ distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + delta = SUB_LONG( distance, args[1] ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + /* subpixel hinting - make MSIRP respect CVT cut-in; */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - FT_ABS( distance - args[1] ) >= control_value_cutin ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 && + delta >= control_value_cutin ) distance = args[1]; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->func_move( exc, &exc->zp1, point, args[1] - distance ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( args[1], distance ) ); exc->GS.rp1 = exc->GS.rp0; exc->GS.rp2 = point; @@ -5874,20 +5873,22 @@ if ( ( exc->opcode & 1 ) != 0 ) { cur_dist = FAST_PROJECT( &exc->zp0.cur[point] ); -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( - exc, - cur_dist, - exc->tt_metrics.compensations[0] ) - cur_dist; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 ) + distance = SUB_LONG( + Round_None( exc, + cur_dist, + exc->tt_metrics.compensations[0] ), + cur_dist ); else #endif - distance = exc->func_round( - exc, - cur_dist, - exc->tt_metrics.compensations[0] ) - cur_dist; + distance = SUB_LONG( + exc->func_round( exc, + cur_dist, + exc->tt_metrics.compensations[0] ), + cur_dist ); } else distance = 0; @@ -5920,14 +5921,14 @@ cvtEntry = (FT_ULong)args[1]; point = (FT_UShort)args[0]; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.x != 0 && exc->GS.freeVector.y == 0 && !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) control_value_cutin = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ if ( BOUNDS( point, exc->zp0.n_points ) || BOUNDSL( cvtEntry, exc->cvtSize ) ) @@ -5961,39 +5962,46 @@ if ( exc->GS.gep0 == 0 ) /* If in twilight zone */ { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */ /* Determined via experimentation and may be incorrect... */ - if ( !SUBPIXEL_HINTING || - ( !exc->ignore_x_mode || - !exc->face->sph_compatibility_mode ) ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + if ( !( SUBPIXEL_HINTING_INFINALITY && + ( exc->ignore_x_mode && + exc->face->sph_compatibility_mode ) ) ) +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ exc->zp0.org[point].x = TT_MulFix14( distance, exc->GS.freeVector.x ); exc->zp0.org[point].y = TT_MulFix14( distance, exc->GS.freeVector.y ), exc->zp0.cur[point] = exc->zp0.org[point]; } -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && distance > 0 && exc->GS.freeVector.y != 0 ) distance = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ org_dist = FAST_PROJECT( &exc->zp0.cur[point] ); if ( ( exc->opcode & 1 ) != 0 ) /* rounding and control cut-in flag */ { - if ( FT_ABS( distance - org_dist ) > control_value_cutin ) + FT_F26Dot6 delta; + + + delta = SUB_LONG( distance, org_dist ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + + if ( delta > control_value_cutin ) distance = org_dist; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 ) distance = Round_None( exc, distance, exc->tt_metrics.compensations[0] ); @@ -6004,7 +6012,7 @@ exc->tt_metrics.compensations[0] ); } - exc->func_move( exc, &exc->zp0, point, distance - org_dist ); + exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) ); Fail: exc->GS.rp0 = point; @@ -6022,19 +6030,19 @@ Ins_MDRP( TT_ExecContext exc, FT_Long* args ) { - FT_UShort point; + FT_UShort point = 0; FT_F26Dot6 org_dist, distance, minimum_distance; minimum_distance = exc->GS.minimum_distance; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.x != 0 && !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) minimum_distance = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ point = (FT_UShort)args[0]; @@ -6076,8 +6084,10 @@ FT_Vector vec; - vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale ); - vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale ); + vec.x = FT_MulFix( SUB_LONG( vec1->x, vec2->x ), + exc->metrics.x_scale ); + vec.y = FT_MulFix( SUB_LONG( vec1->y, vec2->y ), + exc->metrics.y_scale ); org_dist = FAST_DUALPROJ( &vec ); } @@ -6085,8 +6095,12 @@ /* single width cut-in test */ - if ( FT_ABS( org_dist - exc->GS.single_width_value ) < - exc->GS.single_width_cutin ) + /* |org_dist - single_width_value| < single_width_cutin */ + if ( exc->GS.single_width_cutin > 0 && + org_dist < exc->GS.single_width_value + + exc->GS.single_width_cutin && + org_dist > exc->GS.single_width_value - + exc->GS.single_width_cutin ) { if ( org_dist >= 0 ) org_dist = exc->GS.single_width_value; @@ -6098,10 +6112,10 @@ if ( ( exc->opcode & 4 ) != 0 ) { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 ) distance = Round_None( exc, org_dist, @@ -6130,8 +6144,8 @@ } else { - if ( distance > -minimum_distance ) - distance = -minimum_distance; + if ( distance > NEG_LONG( minimum_distance ) ) + distance = NEG_LONG( minimum_distance ); } } @@ -6139,7 +6153,7 @@ org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); - exc->func_move( exc, &exc->zp1, point, distance - org_dist ); + exc->func_move( exc, &exc->zp1, point, SUB_LONG( distance, org_dist ) ); Fail: exc->GS.rp1 = exc->GS.rp0; @@ -6169,25 +6183,25 @@ org_dist, control_value_cutin, minimum_distance; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY FT_Int B1 = 0; /* pacify compiler */ FT_Int B2 = 0; FT_Bool reverse_move = FALSE; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ minimum_distance = exc->GS.minimum_distance; control_value_cutin = exc->GS.control_value_cutin; point = (FT_UShort)args[0]; - cvtEntry = (FT_ULong)( args[1] + 1 ); + cvtEntry = (FT_ULong)( ADD_LONG( args[1], 1 ) ); -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.x != 0 && !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) control_value_cutin = minimum_distance = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ @@ -6240,8 +6254,8 @@ cvt_dist = -cvt_dist; } -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.y != 0 && ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) ) @@ -6251,7 +6265,7 @@ else if ( cur_dist > 64 && cur_dist < 84 ) cvt_dist += 32; } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ /* control value cut-in and round */ @@ -6262,6 +6276,9 @@ if ( exc->GS.gep0 == exc->GS.gep1 ) { + FT_F26Dot6 delta; + + /* XXX: According to Greg Hitchcock, the following wording is */ /* the right one: */ /* */ @@ -6274,7 +6291,11 @@ /* `ttinst2.doc', version 1.66, is thus incorrect since */ /* it implies `>=' instead of `>'. */ - if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) + delta = SUB_LONG( cvt_dist, org_dist ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + + if ( delta > control_value_cutin ) cvt_dist = org_dist; } @@ -6286,16 +6307,23 @@ else { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /* do cvt cut-in always in MIRP for sph */ - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.gep0 == exc->GS.gep1 ) { - if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) + FT_F26Dot6 delta; + + + delta = SUB_LONG( cvt_dist, org_dist ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + + if ( delta > control_value_cutin ) cvt_dist = org_dist; } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ distance = Round_None( exc, @@ -6314,13 +6342,13 @@ } else { - if ( distance > -minimum_distance ) - distance = -minimum_distance; + if ( distance > NEG_LONG( minimum_distance ) ) + distance = NEG_LONG( minimum_distance ); } } -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY ) { B1 = exc->zp1.cur[point].y; @@ -6337,12 +6365,15 @@ ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) ) distance += 64; } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->func_move( exc, &exc->zp1, point, distance - cur_dist ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( distance, cur_dist ) ); -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY ) { B2 = exc->zp1.cur[point].y; @@ -6363,10 +6394,13 @@ } if ( reverse_move ) - exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( cur_dist, distance ) ); } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ Fail: exc->GS.rp1 = exc->GS.rp0; @@ -6391,8 +6425,8 @@ FT_F26Dot6 distance; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->iup_called && ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) ) @@ -6400,7 +6434,7 @@ exc->error = FT_THROW( Invalid_Reference ); goto Fail; } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ if ( exc->top < exc->GS.loop || BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) @@ -6429,7 +6463,7 @@ distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); - exc->func_move( exc, &exc->zp1, point, -distance ); + exc->func_move( exc, &exc->zp1, point, NEG_LONG( distance ) ); } exc->GS.loop--; @@ -6486,19 +6520,19 @@ /* Cramer's rule */ - dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x; - dby = exc->zp0.cur[b1].y - exc->zp0.cur[b0].y; + dbx = SUB_LONG( exc->zp0.cur[b1].x, exc->zp0.cur[b0].x ); + dby = SUB_LONG( exc->zp0.cur[b1].y, exc->zp0.cur[b0].y ); - dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x; - day = exc->zp1.cur[a1].y - exc->zp1.cur[a0].y; + dax = SUB_LONG( exc->zp1.cur[a1].x, exc->zp1.cur[a0].x ); + day = SUB_LONG( exc->zp1.cur[a1].y, exc->zp1.cur[a0].y ); - dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x; - dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y; + dx = SUB_LONG( exc->zp0.cur[b0].x, exc->zp1.cur[a0].x ); + dy = SUB_LONG( exc->zp0.cur[b0].y, exc->zp1.cur[a0].y ); - discriminant = FT_MulDiv( dax, -dby, 0x40 ) + - FT_MulDiv( day, dbx, 0x40 ); - dotproduct = FT_MulDiv( dax, dbx, 0x40 ) + - FT_MulDiv( day, dby, 0x40 ); + discriminant = ADD_LONG( FT_MulDiv( dax, NEG_LONG( dby ), 0x40 ), + FT_MulDiv( day, dbx, 0x40 ) ); + dotproduct = ADD_LONG( FT_MulDiv( dax, dbx, 0x40 ), + FT_MulDiv( day, dby, 0x40 ) ); /* The discriminant above is actually a cross product of vectors */ /* da and db. Together with the dot product, they can be used as */ @@ -6508,28 +6542,29 @@ /* discriminant = |da||db|sin(angle) . */ /* We use these equations to reject grazing intersections by */ /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */ - if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) ) + if ( MUL_LONG( 19, FT_ABS( discriminant ) ) > FT_ABS( dotproduct ) ) { - val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 ); + val = ADD_LONG( FT_MulDiv( dx, NEG_LONG( dby ), 0x40 ), + FT_MulDiv( dy, dbx, 0x40 ) ); R.x = FT_MulDiv( val, dax, discriminant ); R.y = FT_MulDiv( val, day, discriminant ); - exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x; - exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y; + /* XXX: Block in backward_compatibility and/or post-IUP? */ + exc->zp2.cur[point].x = ADD_LONG( exc->zp1.cur[a0].x, R.x ); + exc->zp2.cur[point].y = ADD_LONG( exc->zp1.cur[a0].y, R.y ); } else { /* else, take the middle of the middles of A and B */ - exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x + - exc->zp1.cur[a1].x + - exc->zp0.cur[b0].x + - exc->zp0.cur[b1].x ) / 4; - exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y + - exc->zp1.cur[a1].y + - exc->zp0.cur[b0].y + - exc->zp0.cur[b1].y ) / 4; + /* XXX: Block in backward_compatibility and/or post-IUP? */ + exc->zp2.cur[point].x = + ADD_LONG( ADD_LONG( exc->zp1.cur[a0].x, exc->zp1.cur[a1].x ), + ADD_LONG( exc->zp0.cur[b0].x, exc->zp0.cur[b1].x ) ) / 4; + exc->zp2.cur[point].y = + ADD_LONG( ADD_LONG( exc->zp1.cur[a0].y, exc->zp1.cur[a1].y ), + ADD_LONG( exc->zp0.cur[b0].y, exc->zp0.cur[b1].y ) ) / 4; } exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH; @@ -6564,7 +6599,7 @@ distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2; exc->func_move( exc, &exc->zp1, p1, distance ); - exc->func_move( exc, &exc->zp0, p2, -distance ); + exc->func_move( exc, &exc->zp0, p2, NEG_LONG( distance ) ); } @@ -6598,7 +6633,9 @@ * Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0), * for every n. */ - twilight = exc->GS.gep0 == 0 || exc->GS.gep1 == 0 || exc->GS.gep2 == 0; + twilight = ( exc->GS.gep0 == 0 || + exc->GS.gep1 == 0 || + exc->GS.gep2 == 0 ); if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ) { @@ -6635,9 +6672,11 @@ FT_Vector vec; - vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x, + vec.x = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].x, + orus_base->x ), exc->metrics.x_scale ); - vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y, + vec.y = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].y, + orus_base->y ), exc->metrics.y_scale ); old_range = FAST_DUALPROJ( &vec ); @@ -6646,7 +6685,7 @@ cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base ); } - for ( ; exc->GS.loop > 0; --exc->GS.loop ) + for ( ; exc->GS.loop > 0; exc->GS.loop-- ) { FT_UInt point = (FT_UInt)exc->stack[--exc->args]; FT_F26Dot6 org_dist, cur_dist, new_dist; @@ -6672,9 +6711,11 @@ FT_Vector vec; - vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x, + vec.x = FT_MulFix( SUB_LONG( exc->zp2.orus[point].x, + orus_base->x ), exc->metrics.x_scale ); - vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y, + vec.y = FT_MulFix( SUB_LONG( exc->zp2.orus[point].y, + orus_base->y ), exc->metrics.y_scale ); org_dist = FAST_DUALPROJ( &vec ); @@ -6713,7 +6754,7 @@ exc->func_move( exc, &exc->zp2, (FT_UShort)point, - new_dist - cur_dist ); + SUB_LONG( new_dist, cur_dist ) ); } Fail: @@ -6778,14 +6819,14 @@ FT_F26Dot6 dx; - dx = worker->curs[p].x - worker->orgs[p].x; + dx = SUB_LONG( worker->curs[p].x, worker->orgs[p].x ); if ( dx != 0 ) { for ( i = p1; i < p; i++ ) - worker->curs[i].x += dx; + worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx ); for ( i = p + 1; i <= p2; i++ ) - worker->curs[i].x += dx; + worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx ); } } @@ -6830,8 +6871,8 @@ org2 = worker->orgs[ref2].x; cur1 = worker->curs[ref1].x; cur2 = worker->curs[ref2].x; - delta1 = cur1 - org1; - delta2 = cur2 - org2; + delta1 = SUB_LONG( cur1, org1 ); + delta2 = SUB_LONG( cur2, org2 ); if ( cur1 == cur2 || orus1 == orus2 ) { @@ -6843,10 +6884,10 @@ if ( x <= org1 ) - x += delta1; + x = ADD_LONG( x, delta1 ); else if ( x >= org2 ) - x += delta2; + x = ADD_LONG( x, delta2 ); else x = cur1; @@ -6867,20 +6908,23 @@ if ( x <= org1 ) - x += delta1; + x = ADD_LONG( x, delta1 ); else if ( x >= org2 ) - x += delta2; + x = ADD_LONG( x, delta2 ); else { if ( !scale_valid ) { scale_valid = 1; - scale = FT_DivFix( cur2 - cur1, orus2 - orus1 ); + scale = FT_DivFix( SUB_LONG( cur2, cur1 ), + SUB_LONG( orus2, orus1 ) ); } - x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale ); + x = ADD_LONG( cur1, + FT_MulFix( SUB_LONG( worker->orus[i].x, orus1 ), + scale ) ); } worker->curs[i].x = x; } @@ -6910,6 +6954,23 @@ FT_Short contour; /* current contour */ +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility mode. */ + /* Allow IUP until it has been called on both axes. Immediately */ + /* return on subsequent ones. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) + { + if ( exc->iupx_called && exc->iupy_called ) + return; + + if ( exc->opcode & 1 ) + exc->iupx_called = TRUE; + else + exc->iupy_called = TRUE; + } +#endif + /* ignore empty outlines */ if ( exc->pts.n_contours == 0 ) return; @@ -6933,15 +6994,15 @@ contour = 0; point = 0; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode ) +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode ) { exc->iup_called = TRUE; if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) return; } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ do { @@ -7013,37 +7074,16 @@ FT_UShort A; FT_ULong C, P; FT_Long B; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY FT_UShort B1, B2; - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->iup_called && ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) goto Fail; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - /* Delta hinting is covered by US Patent 5159668. */ - if ( exc->face->unpatented_hinting ) - { - FT_Long n = args[0] * 2; - - - if ( exc->args < n ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - n = exc->args; - } - - exc->args -= n; - exc->new_top = exc->args; - return; - } -#endif +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ P = (FT_ULong)exc->func_cur_ppem( exc ); nump = (FT_ULong)args[0]; /* some points theoretically may occur more @@ -7097,9 +7137,9 @@ B++; B *= 1L << ( 6 - exc->GS.delta_shift ); -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { /* * Allow delta move if @@ -7152,13 +7192,29 @@ SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) && ( B1 & 63 ) != 0 && ( B2 & 63 ) != 0 ) ) ) - exc->func_move( exc, &exc->zp0, A, -B ); + exc->func_move( exc, &exc->zp0, A, NEG_LONG( B ) ); } } else -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->func_move( exc, &exc->zp0, A, B ); + { + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility */ + /* mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) + { + if ( !( exc->iupx_called && exc->iupy_called ) && + ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || + ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) ) + exc->func_move( exc, &exc->zp0, A, B ); + } + else +#endif + exc->func_move( exc, &exc->zp0, A, B ); + } } } else @@ -7186,26 +7242,6 @@ FT_Long B; -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - /* Delta hinting is covered by US Patent 5159668. */ - if ( exc->face->unpatented_hinting ) - { - FT_Long n = args[0] * 2; - - - if ( exc->args < n ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - n = exc->args; - } - - exc->args -= n; - exc->new_top = exc->args; - return; - } -#endif - P = (FT_ULong)exc->func_cur_ppem( exc ); nump = (FT_ULong)args[0]; @@ -7294,24 +7330,25 @@ Ins_GETINFO( TT_ExecContext exc, FT_Long* args ) { - FT_Long K; + FT_Long K; + TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face ); K = 0; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY /********************************/ /* RASTERIZER VERSION */ /* Selector Bit: 0 */ /* Return Bit(s): 0-7 */ /* */ - if ( SUBPIXEL_HINTING && - ( args[0] & 1 ) != 0 && - exc->subpixel_hinting ) + if ( SUBPIXEL_HINTING_INFINALITY && + ( args[0] & 1 ) != 0 && + exc->subpixel_hinting ) { if ( exc->ignore_x_mode ) { - /* if in ClearType backwards compatibility mode, */ + /* if in ClearType backward compatibility mode, */ /* we sometimes change the TrueType version dynamically */ K = exc->rasterizer_version; FT_TRACE6(( "Setting rasterizer version %d\n", @@ -7321,9 +7358,9 @@ K = TT_INTERPRETER_VERSION_38; } else -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ if ( ( args[0] & 1 ) != 0 ) - K = TT_INTERPRETER_VERSION_35; + K = driver->interpreter_version; /********************************/ /* GLYPH ROTATED */ @@ -7331,7 +7368,7 @@ /* Return Bit(s): 8 */ /* */ if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated ) - K |= 0x80; + K |= 1 << 8; /********************************/ /* GLYPH STRETCHED */ @@ -7339,19 +7376,87 @@ /* Return Bit(s): 9 */ /* */ if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched ) - K |= 1 << 8; + K |= 1 << 9; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /********************************/ + /* VARIATION GLYPH */ + /* Selector Bit: 3 */ + /* Return Bit(s): 10 */ + /* */ + /* XXX: UNDOCUMENTED! */ + if ( (args[0] & 8 ) != 0 && exc->face->blend ) + K |= 1 << 10; +#endif /********************************/ - /* HINTING FOR GRAYSCALE */ + /* BI-LEVEL HINTING AND */ + /* GRAYSCALE RENDERING */ /* Selector Bit: 5 */ /* Return Bit(s): 12 */ /* */ if ( ( args[0] & 32 ) != 0 && exc->grayscale ) K |= 1 << 12; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* Toggle the following flags only outside of monochrome mode. */ + /* Otherwise, instructions may behave weirdly and rendering results */ + /* may differ between v35 and v40 mode, e.g., in `Times New Roman */ + /* Bold Italic'. */ + if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean ) + { + /********************************/ + /* HINTING FOR SUBPIXEL */ + /* Selector Bit: 6 */ + /* Return Bit(s): 13 */ + /* */ + /* v40 does subpixel hinting by default. */ + if ( ( args[0] & 64 ) != 0 ) + K |= 1 << 13; + + /********************************/ + /* VERTICAL LCD SUBPIXELS? */ + /* Selector Bit: 8 */ + /* Return Bit(s): 15 */ + /* */ + if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean ) + K |= 1 << 15; + + /********************************/ + /* SUBPIXEL POSITIONED? */ + /* Selector Bit: 10 */ + /* Return Bit(s): 17 */ + /* */ + /* XXX: FreeType supports it, dependent on what client does? */ + if ( ( args[0] & 1024 ) != 0 ) + K |= 1 << 17; + + /********************************/ + /* SYMMETRICAL SMOOTHING */ + /* Selector Bit: 11 */ + /* Return Bit(s): 18 */ + /* */ + /* The only smoothing method FreeType supports unless someone sets */ + /* FT_LOAD_TARGET_MONO. */ + if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean ) + K |= 1 << 18; + + /********************************/ + /* CLEARTYPE HINTING AND */ + /* GRAYSCALE RENDERING */ + /* Selector Bit: 12 */ + /* Return Bit(s): 19 */ + /* */ + /* Grayscale rendering is what FreeType does anyway unless someone */ + /* sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V) */ + if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype ) + K |= 1 << 19; + } +#endif - if ( SUBPIXEL_HINTING && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + + if ( SUBPIXEL_HINTING_INFINALITY && exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 ) { @@ -7424,12 +7529,71 @@ } } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ args[0] = K; } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + /*************************************************************************/ + /* */ + /* GETVARIATION[]: get normalized variation (blend) coordinates */ + /* Opcode range: 0x91 */ + /* Stack: --> f2.14... */ + /* */ + /* XXX: UNDOCUMENTED! There is no official documentation from Apple for */ + /* this bytecode instruction. Active only if a font has GX */ + /* variation axes. */ + /* */ + static void + Ins_GETVARIATION( TT_ExecContext exc, + FT_Long* args ) + { + FT_UInt num_axes = exc->face->blend->num_axis; + FT_Fixed* coords = exc->face->blend->normalizedcoords; + + FT_UInt i; + + + if ( BOUNDS( num_axes, exc->stackSize + 1 - exc->top ) ) + { + exc->error = FT_THROW( Stack_Overflow ); + return; + } + + if ( coords ) + { + for ( i = 0; i < num_axes; i++ ) + args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */ + } + else + { + for ( i = 0; i < num_axes; i++ ) + args[i] = 0; + } + } + + + /*************************************************************************/ + /* */ + /* GETDATA[]: no idea what this is good for */ + /* Opcode range: 0x92 */ + /* Stack: --> 17 */ + /* */ + /* XXX: UNDOCUMENTED! There is no documentation from Apple for this */ + /* very weird bytecode instruction. */ + /* */ + static void + Ins_GETDATA( FT_Long* args ) + { + args[0] = 17; + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + static void Ins_UNKNOWN( TT_ExecContext exc ) { @@ -7503,10 +7667,11 @@ FT_EXPORT_DEF( FT_Error ) TT_RunIns( TT_ExecContext exc ) { - FT_Long ins_counter = 0; /* executed instructions counter */ + FT_ULong ins_counter = 0; /* executed instructions counter */ + FT_ULong num_twilight_points; FT_UShort i; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY FT_Byte opcode_pattern[1][2] = { /* #8 TypeMan Talk Align */ { @@ -7517,12 +7682,88 @@ FT_UShort opcode_patterns = 1; FT_UShort opcode_pointer[1] = { 0 }; FT_UShort opcode_size[1] = { 1 }; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY exc->iup_called = FALSE; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* + * Toggle backward compatibility according to what font wants, except + * when + * + * 1) we have a `tricky' font that heavily relies on the interpreter to + * render glyphs correctly, for example DFKai-SB, or + * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. + * + * In those cases, backward compatibility needs to be turned off to get + * correct rendering. The rendering is then completely up to the + * font's programming. + * + */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->subpixel_hinting_lean && + !FT_IS_TRICKY( &exc->face->root ) ) + exc->backward_compatibility = !( exc->GS.instruct_control & 4 ); + else + exc->backward_compatibility = FALSE; + + exc->iupx_called = FALSE; + exc->iupy_called = FALSE; +#endif + + /* We restrict the number of twilight points to a reasonable, */ + /* heuristic value to avoid slow execution of malformed bytecode. */ + num_twilight_points = FT_MAX( 30, + 2 * ( exc->pts.n_points + exc->cvtSize ) ); + if ( exc->twilight.n_points > num_twilight_points ) + { + if ( num_twilight_points > 0xFFFFU ) + num_twilight_points = 0xFFFFU; + + FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n" + " from %d to the more reasonable value %d\n", + exc->twilight.n_points, + num_twilight_points )); + exc->twilight.n_points = (FT_UShort)num_twilight_points; + } + + /* Set up loop detectors. We restrict the number of LOOPCALL loops */ + /* and the number of JMPR, JROT, and JROF calls with a negative */ + /* argument to values that depend on various parameters like the */ + /* size of the CVT table or the number of points in the current */ + /* glyph (if applicable). */ + /* */ + /* The idea is that in real-world bytecode you either iterate over */ + /* all CVT entries (in the `prep' table), or over all points (or */ + /* contours, in the `glyf' table) of a glyph, and such iterations */ + /* don't happen very often. */ + exc->loopcall_counter = 0; + exc->neg_jump_counter = 0; + + /* The maximum values are heuristic. */ + if ( exc->pts.n_points ) + exc->loopcall_counter_max = FT_MAX( 50, + 10 * exc->pts.n_points ) + + FT_MAX( 50, + exc->cvtSize / 10 ); + else + exc->loopcall_counter_max = 300 + 8 * exc->cvtSize; + + /* as a protection against an unreasonable number of CVT entries */ + /* we assume at most 100 control values per glyph for the counter */ + if ( exc->loopcall_counter_max > + 100 * (FT_ULong)exc->face->root.num_glyphs ) + exc->loopcall_counter_max = 100 * (FT_ULong)exc->face->root.num_glyphs; + + FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL" + " to %d\n", exc->loopcall_counter_max )); + + exc->neg_jump_counter_max = exc->loopcall_counter_max; + FT_TRACE5(( "TT_RunIns: Limiting total number of backward jumps" + " to %d\n", exc->neg_jump_counter_max )); /* set PPEM and CVT functions */ exc->tt_metrics.ratio = 0; @@ -7565,7 +7806,7 @@ ? 2 : 12 - ( *opcode_name[exc->opcode] - '0' ), "#" )); - for ( n = 0; n < cnt; n++ ) + for ( n = 1; n <= cnt; n++ ) FT_TRACE7(( " %d", exc->stack[exc->top - n] )); FT_TRACE6(( "\n" )); } @@ -7601,7 +7842,21 @@ exc->args = 0; } - exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 ); +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( exc->opcode == 0x91 ) + { + /* this is very special: GETVARIATION returns */ + /* a variable number of arguments */ + + /* it is the job of the application to `activate' GX handling, */ + /* this is, calling any of the GX API functions on the current */ + /* font to select a variation instance */ + if ( exc->face->blend ) + exc->new_top = exc->args + exc->face->blend->num_axis; + } + else +#endif + exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 ); /* `new_top' is the new top of the stack, after the instruction's */ /* execution. `top' will be set to `new_top' after the `switch' */ @@ -7615,9 +7870,9 @@ exc->step_ins = TRUE; exc->error = FT_Err_Ok; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { for ( i = 0; i < opcode_patterns; i++ ) { @@ -7646,7 +7901,7 @@ } } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ { FT_Long* args = exc->stack + exc->args; @@ -7794,7 +8049,7 @@ Ins_ALIGNPTS( exc, args ); break; - case 0x28: /* ???? */ + case 0x28: /* RAW */ Ins_UNKNOWN( exc ); break; @@ -8146,10 +8401,33 @@ Ins_INSTCTRL( exc, args ); break; - case 0x8F: + case 0x8F: /* ADJUST */ + case 0x90: /* ADJUST */ Ins_UNKNOWN( exc ); break; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + case 0x91: + /* it is the job of the application to `activate' GX handling, */ + /* this is, calling any of the GX API functions on the current */ + /* font to select a variation instance */ + if ( exc->face->blend ) + Ins_GETVARIATION( exc, args ); + else + Ins_UNKNOWN( exc ); + break; + + case 0x92: + /* there is at least one MS font (LaoUI.ttf version 5.01) that */ + /* uses IDEFs for 0x91 and 0x92; for this reason we activate */ + /* GETDATA for GX fonts only, similar to GETVARIATION */ + if ( exc->face->blend ) + Ins_GETDATA( args ); + else + Ins_UNKNOWN( exc ); + break; +#endif + default: if ( opcode >= 0xE0 ) Ins_MIRP( exc, args ); @@ -8230,7 +8508,7 @@ /* increment instruction counter and check if we didn't */ /* run this program for too long (e.g. infinite loops). */ - if ( ++ins_counter > MAX_RUNNABLE_OPCODES ) + if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES ) return FT_THROW( Execution_Too_Long ); LSuiteLabel_: @@ -8247,29 +8525,27 @@ } while ( !exc->instruction_trap ); LNo_Error_: + FT_TRACE4(( " %d instruction%s executed\n", + ins_counter, + ins_counter == 1 ? "" : "s" )); return FT_Err_Ok; LErrorCodeOverflow_: exc->error = FT_THROW( Code_Overflow ); LErrorLabel_: - /* If any errors have occurred, function tables may be broken. */ - /* Force a re-execution of `prep' and `fpgm' tables if no */ - /* bytecode debugger is run. */ - if ( exc->error && - !exc->instruction_trap && - exc->curRange == tt_coderange_glyph ) - { + if ( exc->error && !exc->instruction_trap ) FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error )); - exc->size->bytecode_ready = -1; - exc->size->cvt_ready = -1; - } return exc->error; } +#else /* !TT_USE_BYTECODE_INTERPRETER */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_interp_dummy; -#endif /* TT_USE_BYTECODE_INTERPRETER */ +#endif /* !TT_USE_BYTECODE_INTERPRETER */ /* END */ |