>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