>From 9c3e9a8d489796f2ec79391fb9cdb643c7514fa0 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Thu, 28 Apr 2016 23:53:25 +0200 Subject: [PATCH 2/2] Implement the new lean TrueType interpreter. --- src/truetype/ttinterp.c | 450 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 333 insertions(+), 117 deletions(-) diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index 78c35f2..3650158 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -45,10 +45,21 @@ #define FT_COMPONENT trace_ttinterp -#define SUBPIXEL_HINTING \ +#define NO_SUBPIXEL_HINTING \ + ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ + TT_INTERPRETER_VERSION_35 ) + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#define SUBPIXEL_HINTING_INFINALITY \ ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ TT_INTERPRETER_VERSION_38 ) +#endif +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN +#define SUBPIXEL_HINTING_LEAN \ + ( ((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 ) @@ -286,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; @@ -1642,6 +1653,10 @@ /* */ /* zone :: The affected glyph zone. */ /* */ + /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* `Touches' the point. */ + /* */ static void Direct_Move( TT_ExecContext exc, TT_GlyphZone zone, @@ -1656,10 +1671,23 @@ if ( v != 0 ) { #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( !SUBPIXEL_HINTING || - ( !exc->ignore_x_mode || - ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) + if ( SUBPIXEL_HINTING_INFINALITY && + ( !exc->ignore_x_mode || + ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) + zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + else #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* 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_LEAN && !exc->backwards_compatibility ) + zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + else +#endif + + if ( NO_SUBPIXEL_HINTING ) zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; @@ -1669,7 +1697,13 @@ if ( v != 0 ) { - zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + if ( !( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility && + exc->iupx_called && + exc->iupy_called ) ) +#endif + zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1720,6 +1754,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 backwards compatibility mode. */ /* */ /*************************************************************************/ @@ -1730,12 +1765,19 @@ FT_UShort point, FT_F26Dot6 distance ) { - FT_UNUSED( exc ); - #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( !SUBPIXEL_HINTING || - !exc->ignore_x_mode ) + if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode ) + zone->cur[point].x += distance; + else #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + if ( SUBPIXEL_HINTING_LEAN && !exc->backwards_compatibility ) + zone->cur[point].x += distance; + else +#endif + + if ( NO_SUBPIXEL_HINTING ) zone->cur[point].x += distance; zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; @@ -1750,8 +1792,14 @@ { FT_UNUSED( exc ); - zone->cur[point].y += distance; - zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + if ( !( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility && + exc->iupx_called && exc->iupy_called ) ) +#endif + zone->cur[point].y += distance; + + zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1853,16 +1901,17 @@ /* */ /* Rounded distance. */ /* */ + /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* */ static FT_F26Dot6 Round_To_Grid( TT_ExecContext exc, FT_F26Dot6 distance, FT_F26Dot6 compensation ) { FT_F26Dot6 val; - FT_UNUSED( exc ); - if ( distance >= 0 ) { val = FT_PIX_ROUND( distance + compensation ); @@ -1896,13 +1945,15 @@ /* */ /* Rounded distance. */ /* */ + /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* */ static FT_F26Dot6 Round_To_Half_Grid( TT_ExecContext exc, FT_F26Dot6 distance, FT_F26Dot6 compensation ) { FT_F26Dot6 val; - FT_UNUSED( exc ); @@ -1939,13 +1990,15 @@ /* */ /* Rounded distance. */ /* */ + /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* */ static FT_F26Dot6 Round_Down_To_Grid( TT_ExecContext exc, FT_F26Dot6 distance, FT_F26Dot6 compensation ) { FT_F26Dot6 val; - FT_UNUSED( exc ); @@ -1982,13 +2035,15 @@ /* */ /* Rounded distance. */ /* */ + /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* */ static FT_F26Dot6 Round_Up_To_Grid( TT_ExecContext exc, FT_F26Dot6 distance, FT_F26Dot6 compensation ) { FT_F26Dot6 val; - FT_UNUSED( exc ); @@ -2025,13 +2080,15 @@ /* */ /* Rounded distance. */ /* */ + /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* */ static FT_F26Dot6 Round_To_Double_Grid( TT_ExecContext exc, FT_F26Dot6 distance, FT_F26Dot6 compensation ) { - FT_F26Dot6 val; - + FT_F26Dot6 val; FT_UNUSED( exc ); @@ -2069,17 +2126,20 @@ /* Rounded distance. */ /* */ /* */ - /* 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. */ /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* */ static FT_F26Dot6 Round_Super( TT_ExecContext exc, FT_F26Dot6 distance, FT_F26Dot6 compensation ) { FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -2123,12 +2183,15 @@ /* There is a separate function for Round_Super_45() as we may need */ /* greater precision. */ /* */ + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* */ static FT_F26Dot6 Round_Super_45( TT_ExecContext exc, FT_F26Dot6 distance, FT_F26Dot6 compensation ) { FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -2878,8 +2941,6 @@ Ins_RS( TT_ExecContext exc, FT_Long* args ) { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_ULong I = (FT_ULong)args[0]; @@ -2892,10 +2953,11 @@ } else { +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* subpixel hinting - avoid Typeman Dstroke and */ /* IStroke and Vacuform rounds */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && ( ( I == 24 && ( exc->face->sph_found_func_flags & ( SPH_FDEF_SPACING_1 | @@ -2906,28 +2968,12 @@ ( I == 8 && ( exc->face->sph_found_func_flags & SPH_FDEF_VACUFORM_ROUND_1 ) && - exc->iup_called ) ) ) + exc->iup_called ) ) ) args[0] = 0; else +#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 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 */ } @@ -3409,6 +3455,7 @@ TT_DefRecord* rec; TT_DefRecord* limit; + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* arguments to opcodes are skipped by `SKIP_Code' */ FT_Byte opcode_pattern[9][12] = { @@ -3567,7 +3614,7 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { for ( i = 0; i < opcode_patterns; i++ ) { @@ -3792,11 +3839,11 @@ goto Fail; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - ( ( exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) || - ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + ( ( exc->iup_called && + ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) || + ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) ) goto Fail; else exc->sph_in_func_flags = def->sph_fdef_flags; @@ -3880,7 +3927,7 @@ goto Fail; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) goto Fail; @@ -4783,9 +4830,9 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* 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 */ @@ -5011,7 +5058,7 @@ Ins_INSTCTRL( TT_ExecContext exc, FT_Long* args ) { - FT_ULong K, L, Kf; + FT_ULong K, L, Kf; K = (FT_ULong)args[1]; @@ -5043,12 +5090,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_CONFIG_OPTION_SUBPIXEL_HINTING + /* 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_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* Native ClearType fonts sign a waiver that turns off all backwards */ + /* 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_LEAN ) + exc->backwards_compatibility = ! FT_BOOL( L == 4 ); +#endif + } } @@ -5133,6 +5191,15 @@ FT_UShort point; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* See `ttinterp.h' for details on backwards compatibility mode. */ + if ( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility && + exc->iupx_called && + exc->iupy_called ) + goto Fail; +#endif + if ( exc->top < exc->GS.loop ) { if ( exc->pedantic_hinting ) @@ -5179,6 +5246,15 @@ FT_UShort I, K, L; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* See `ttinterp.h' for details on backwards compatibility mode. */ + if ( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility && + exc->iupx_called && + exc->iupy_called ) + return; +#endif + K = (FT_UShort)args[1]; L = (FT_UShort)args[0]; @@ -5208,6 +5284,15 @@ FT_UShort I, K, L; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* See `ttinterp.h' for details on backwards compatibility mode. */ + if ( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility && + exc->iupx_called && + exc->iupy_called ) + return; +#endif + K = (FT_UShort)args[1]; L = (FT_UShort)args[0]; @@ -5267,6 +5352,7 @@ } + /* See `ttinterp.h' for details on backwards compatibility mode. */ static void Move_Zp2_Point( TT_ExecContext exc, FT_UShort point, @@ -5276,14 +5362,26 @@ { if ( exc->GS.freeVector.x != 0 ) { - exc->zp2.cur[point].x += dx; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + if ( !( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility ) ) +#endif + 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_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + if ( !( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility && + exc->iupx_called && + exc->iupy_called ) ) +#endif + exc->zp2.cur[point].y += dy; + if ( touch ) exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -5332,8 +5430,7 @@ else #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* 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 */ @@ -5495,6 +5592,7 @@ } else #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( SUBPIXEL_HINTING_INFINALITY ) { /* If not using ignore_x_mode rendering, allow ZP2 move. */ /* If inline deltas aren't allowed, skip ZP2 move. */ @@ -5504,8 +5602,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 ) @@ -5569,15 +5666,26 @@ else Move_Zp2_Point( exc, point, dx, dy, TRUE ); } + else +#endif +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + if ( SUBPIXEL_HINTING_LEAN && + exc->backwards_compatibility ) + { + /* XXX: breaks Rokkitt < v1.2 */ + /* (glyphs explode vertically on ALIGNRP). */ + if ( !( 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_CONFIG_OPTION_SUBPIXEL_HINTING 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--; } @@ -5597,14 +5705,15 @@ 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 */ +#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING + FT_F26Dot6 control_value_cutin = 0; +#endif - if ( SUBPIXEL_HINTING ) +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( SUBPIXEL_HINTING_INFINALITY ) { control_value_cutin = exc->GS.control_value_cutin; @@ -5613,7 +5722,7 @@ !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) control_value_cutin = 0; } - + else #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ point = (FT_UShort)args[0]; @@ -5639,7 +5748,7 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* subpixel hinting - make MSIRP respect CVT cut-in; */ - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.x != 0 && FT_ABS( distance - args[1] ) >= control_value_cutin ) @@ -5684,9 +5793,9 @@ { 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 ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 ) distance = Round_None( exc, cur_dist, @@ -5730,7 +5839,7 @@ point = (FT_UShort)args[0]; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.x != 0 && exc->GS.freeVector.y == 0 && @@ -5773,7 +5882,7 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */ /* Determined via experimentation and may be incorrect... */ - if ( !SUBPIXEL_HINTING || + if ( SUBPIXEL_HINTING_INFINALITY && ( !exc->ignore_x_mode || !exc->face->sph_compatibility_mode ) ) #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ @@ -5784,11 +5893,11 @@ exc->zp0.cur[point] = exc->zp0.org[point]; } #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && - distance > 0 && - exc->GS.freeVector.y != 0 ) + 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 */ @@ -5800,9 +5909,9 @@ distance = org_dist; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 ) distance = Round_None( exc, distance, exc->tt_metrics.compensations[0] ); @@ -5831,14 +5940,14 @@ 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 && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.x != 0 && !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) @@ -5908,9 +6017,9 @@ if ( ( exc->opcode & 4 ) != 0 ) { #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 ) distance = Round_None( exc, org_dist, @@ -5991,11 +6100,12 @@ cvtEntry = (FT_ULong)( args[1] + 1 ); #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && + 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; + else #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ @@ -6050,7 +6160,7 @@ } #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.y != 0 && ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) ) @@ -6097,9 +6207,9 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* do cvt cut-in always in MIRP for sph */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.gep0 == exc->GS.gep1 ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.gep0 == exc->GS.gep1 ) { if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) cvt_dist = org_dist; @@ -6129,7 +6239,7 @@ } #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { B1 = exc->zp1.cur[point].y; @@ -6151,7 +6261,7 @@ exc->func_move( exc, &exc->zp1, point, distance - cur_dist ); #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { B2 = exc->zp1.cur[point].y; @@ -6201,7 +6311,7 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->iup_called && ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) ) @@ -6324,6 +6434,7 @@ R.x = FT_MulDiv( val, dax, discriminant ); R.y = FT_MulDiv( val, day, discriminant ); + /* XXX: Block in backwards_compatibility and/or post-IUP? */ exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x; exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y; } @@ -6331,6 +6442,7 @@ { /* else, take the middle of the middles of A and B */ + /* XXX: Block in backwards_compatibility and/or post-IUP? */ exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x + exc->zp1.cur[a1].x + exc->zp0.cur[b0].x + @@ -6719,6 +6831,23 @@ FT_Short contour; /* current contour */ +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* Allow IUP until it has been called on both axes. Immediately */ + /* return on subsequent ones. */ + if ( SUBPIXEL_HINTING_LEAN && + exc->backwards_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; @@ -6743,8 +6872,8 @@ point = 0; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode ) { exc->iup_called = TRUE; if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) @@ -6826,7 +6955,7 @@ 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 ) ) @@ -6887,7 +7016,7 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { /* * Allow delta move if @@ -6946,7 +7075,23 @@ else #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - exc->func_move( exc, &exc->zp0, A, B ); + { + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* See `ttinterp.h' for details on backwards compatibility */ + /* mode. */ + if ( SUBPIXEL_HINTING_LEAN && + exc->backwards_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 @@ -7062,20 +7207,23 @@ Ins_GETINFO( TT_ExecContext exc, FT_Long* args ) { - FT_Long K; + FT_Long K; + TT_Driver driver; K = 0; + driver = (TT_Driver)FT_FACE_DRIVER( exc->face ); + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /********************************/ /* 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 ) { @@ -7091,7 +7239,7 @@ else #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ if ( ( args[0] & 1 ) != 0 ) - K = TT_INTERPRETER_VERSION_35; + K = driver->interpreter_version; /********************************/ /* GLYPH ROTATED */ @@ -7110,16 +7258,69 @@ K |= 1 << 8; /********************************/ - /* 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_LEAN + if ( SUBPIXEL_HINTING_LEAN ) + { + /********************************/ + /* HINTING FOR SUBPIXEL */ + /* Selector Bit: 6 */ + /* Return Bit(s): 13 */ + /* */ + /* v38 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 ) + 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 + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && + if ( SUBPIXEL_HINTING_INFINALITY && exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 ) { @@ -7292,6 +7493,21 @@ exc->iup_called = FALSE; #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN + /* Toggle backwards compatibility according to what font says, except */ + /* when it's a `tricky' font that heavily relies on the interpreter to */ + /* render glyphs correctly, e.g. DFKai-SB. Backwards compatibility */ + /* hacks may break it. */ + if ( SUBPIXEL_HINTING_LEAN && + !FT_IS_TRICKY( &exc->face->root ) ) + exc->backwards_compatibility = !( exc->GS.instruct_control & 4 ); + else + exc->backwards_compatibility = FALSE; + + exc->iupx_called = FALSE; + exc->iupy_called = FALSE; +#endif + /* set PPEM and CVT functions */ exc->tt_metrics.ratio = 0; if ( exc->metrics.x_ppem != exc->metrics.y_ppem ) @@ -7385,7 +7601,7 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) + if ( SUBPIXEL_HINTING_INFINALITY ) { for ( i = 0; i < opcode_patterns; i++ ) { -- 2.5.5