Patch is almost ready for for mainlining.
The new lean interpreter can now coexist with the Infinality code. Both
are gated by macros: TT_CONFIG_OPTION_SUBPIXEL_HINTING for the
Infinality code, TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN for the new
code. You can define none, one of them or both. The new code is on by
default.
@Werner: I just now remembered that you sent me proofed patches but
forgot to base these patches on them... Aside, I defined a new public
property "hinting-engine" for the TT driver, akin to the CFF driver. I
don't really feel comfortable doing that as the Infinality code may be
removed in the future and I'm bound to have overlooked a combinatorial
corner case with "interpreter-version". A patch for ftview etc. may
follow at a later point. And yes, it turned into an ifdef orgy.
>From cbc1d782ba514b8eb1707306cb0bd944f84398de Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <madig...@gmail.com>
Date: Thu, 17 Mar 2016 21:53:29 +0100
Subject: [PATCH 1/3] Prepare landing of v38 bytecode interpreter
Modern TrueType fonts are usually rendered through Microsoft's
collection of rendering techniques called ClearType (e.g. subpixel
rendering and subpixel hinting). When ClearType was introduced, most
fonts were not ready. Microsoft decided to implement a backwards
compatibility mode that employed several simple to complicated
assumptions and tricks that modified the interpretation of the bytecode
contained in these fonts to make them look ClearType-y somehow. Most
(web)fonts that were released since then have come to rely on these
hacks to render correctly, even some of Microsoft's flagship ClearType
fonts (Calibri, Cambria, Segoe UI).
FreeType employs a small list of font-agnostic hacks to bludgeon
non-native-ClearType fonts (except tricky ones[1]) into submission.
FreeType will not try to toggle hacks for specific fonts for performance
and complexity reasons. The focus is on modern (web)fonts rather than
legacy fonts that were made for black-and-white rendering.
Major hacks:
- Any point movement on the X-axis will be ignored (cf. Direct_Move()
and Direct_Move_X()). This has the smallest code footprint and single
biggest effect. The ClearType way to increase resolution is
supersampling the x-axis, the FreeType way is ignoring instuctions on
the x-axis, which gives the same result in the majority of cases.
- Points will not be moved post-IUP, except the x-component of diagonal
moves post-IUP (cf. Direct_Move(), Direct_Move_Y(), Move_Zp2_Point()).
Post-IUP changes are commonly used to "fix" pixel patterns which has
little use outside monochrome rendering.
- SHPIX and DELTAP will not execute unless moving a composite on the
Y-axis or moving a previously Y-touched point. SHPIX will additionally
deny movement on the X-axis (c.f. Ins_SHPIX() and Ins_DELTAP()). Both
instructions are commonly used to "fix" pixel patterns for monochrome
or Windows's GDI rendering but make little sense for FreeType
rendering. Both can distort the outline. See [2] for details.
- The hdmx table and modifications to phantom points are ignored.
Bearings and advance widths remain unchanged (except rounding them
outside the interpreter!). C.f. compute_glyph_metrics() and
TT_Hint_Glyph(). Letting non-native-ClearType fonts modify spacing
might mess up spacing.
Minor hacks:
- All rounding instructions are turned into Round_None if the freedom
vector is parallel to the X-axis (c.f. Round_*()). Given ClearType's
virtual increase of resolution on the X-axis, rounding to the physical
pixel grid there doesn't make much sense. Native ClearType fonts know
this, the rest (where backwards compatibility applies) may or may not.
- SHP will deny movement on the X-axis (c.f. Ins_SHP()). Prevents dents.
- FLIPRGON, FLIPRGOFF and FLIPPT will not execute post-IUP. This
prevents dents in e.g. Arial-Regular's 'D' and 'G' at various sizes.
- MSIRP, MIAP, MDRP and MIRP will see a control value cut-in and minimum
distance of 0 if the freedom vector is parallel to the X-axis (c.f.
Ins_MSIRP(), Ins_MIAP(), Ins_MDRP() and Ins_MIRP()). See [2] for
details.
Post-IUP is the state after both IUP[x] and IUP[y] have been executed.
The best results are achieved for fonts that were from the outset
designed with ClearType in mind, meaning they leave the X-axis mostly
alone and don't mess with the "final" outline to produce more pleasing
pixel patterns. The harder the designer tried to produce very specific
patterns ("superhinting") for pre-ClearType-display, the worse the
results.
Microsoft defines a way to turn off backwards compatibility and
interpret instructions as before ("native ClearType")[2][3]. The font
designer then regains full control and is responsible for making the
font work correctly with ClearType without any hand-holding by the
interpreter or rasterizer[4]. The v38 interpreter assumes backwards
compatibility by default, which can be turned off the same way by
executing the following in the control program:
#PUSH 4,3
INSTCTRL[]
(cf. Ins_INSTCTRL()).
[1]: Tricky fonts as FreeType defines them rely on the bytecode
interpreter to display correctly. Hacks can interfere with them, so
they get treated like native ClearType fonts (v38 with
backwards compatibility turned off). C.f. TT_RunIns().
[2]: Proposed by Microsoft's Greg Hitchcock in
https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
[3]: Beat Stamm describes it in more detail:
http://www.beatstamm.com/typography/RTRCh4.htm#Sec12
[4]: The list of "native ClearType" fonts is small at the time of this
writing, I found the following on a Windows 10 Update 1511
installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft
JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
SimSun, NSimSun and Yu Gothic.
---
src/truetype/ttdriver.c | 5 +--
src/truetype/ttgload.c | 68 ++++++++++++++++++++++++-----
src/truetype/ttinterp.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++-
src/truetype/ttobjs.c | 5 ---
4 files changed, 171 insertions(+), 20 deletions(-)
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index bbebabd..a856fed 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -72,11 +72,10 @@
FT_UInt* interpreter_version = (FT_UInt*)value;
-#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( *interpreter_version != TT_INTERPRETER_VERSION_35 )
+ if ( *interpreter_version != TT_INTERPRETER_VERSION_35 &&
+ *interpreter_version != TT_INTERPRETER_VERSION_38 )
error = FT_ERR( Unimplemented_Feature );
else
-#endif
driver->interpreter_version = *interpreter_version;
return error;
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index d1cb357..8ea887c 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -816,11 +816,16 @@
#endif
- /* save glyph phantom points */
- loader->pp1 = zone->cur[zone->n_points - 4];
- loader->pp2 = zone->cur[zone->n_points - 3];
- loader->pp3 = zone->cur[zone->n_points - 2];
- loader->pp4 = zone->cur[zone->n_points - 1];
+ /* Save possibly modified glyph phantom points unless in v38 backwards
+ * compatibility mode, where no movement on the X-axis means no reason to
+ * change bearings or advance widths. */
+ if ( !loader->exec->backwards_compatibility )
+ {
+ loader->pp1 = zone->cur[zone->n_points - 4];
+ loader->pp2 = zone->cur[zone->n_points - 3];
+ loader->pp3 = zone->cur[zone->n_points - 2];
+ loader->pp4 = zone->cur[zone->n_points - 1];
+ }
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
@@ -1970,10 +1975,13 @@
glyph->metrics.horiBearingY = bbox.yMax;
glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
- /* adjust advance width to the value contained in the hdmx table */
- /* unless FT_LOAD_COMPUTE_METRICS is set */
- if ( !face->postscript.isFixedPitch &&
- IS_HINTED( loader->load_flags ) &&
+ /* Adjust advance width to the value contained in the hdmx table unless
+ * FT_LOAD_COMPUTE_METRICS is set or backwards compatibility mode of the
+ * v38 interpreter is active. See ttinterp.h for details on backwards
+ * compatibility mode. */
+ if ( !( loader->exec && loader->exec->backwards_compatibility ) &&
+ !face->postscript.isFixedPitch &&
+ IS_HINTED( loader->load_flags ) &&
!( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
{
FT_Byte* widthp;
@@ -2187,6 +2195,7 @@
TT_Face face;
FT_Stream stream;
+ TT_Driver driver;
#ifdef TT_USE_BYTECODE_INTERPRETER
FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
#endif
@@ -2194,6 +2203,7 @@
face = (TT_Face)glyph->face;
stream = face->root.stream;
+ driver = (TT_Driver)FT_FACE_DRIVER( face );
FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
@@ -2204,6 +2214,8 @@
{
TT_ExecContext exec;
FT_Bool grayscale;
+ FT_Bool subpixel_hinting;
+ FT_Bool grayscale_cleartype;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
@@ -2240,6 +2252,18 @@
if ( !exec )
return FT_THROW( Could_Not_Find_Context );
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ {
+ subpixel_hinting = TRUE;
+ grayscale_cleartype = ! FT_BOOL( load_flags & FT_LOAD_TARGET_LCD ||
+ load_flags & FT_LOAD_TARGET_LCD_V );
+ exec->vertical_lcd = FT_BOOL( load_flags & FT_LOAD_TARGET_LCD_V );
+ } else {
+ subpixel_hinting = FALSE;
+ grayscale_cleartype = FALSE;
+ exec->vertical_lcd = FALSE;
+ }
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
@@ -2300,8 +2324,8 @@
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
{
- grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- FT_RENDER_MODE_MONO );
+ grayscale = FT_BOOL( ! subpixel_hinting &&
+ FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
}
error = TT_Load_Context( exec, face, size );
@@ -2339,6 +2363,28 @@
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
{
+ /* a change from mono to subpixel rendering (and vice versa) */
+ /* requires a re-execution of the CVT program */
+ if ( subpixel_hinting != exec->subpixel_hinting )
+ {
+ FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
+ " re-executing `prep' table\n" ));
+
+ exec->subpixel_hinting = subpixel_hinting;
+ reexecute = TRUE;
+ }
+
+ /* a change from colored to grayscale subpixel rendering (and vice
+ * versa) requires a re-execution of the CVT program */
+ if ( grayscale_cleartype != exec->grayscale_cleartype )
+ {
+ FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
+ " re-executing `prep' table\n" ));
+
+ exec->grayscale_cleartype = grayscale_cleartype;
+ reexecute = TRUE;
+ }
+
/* a change from mono to grayscale rendering (and vice versa) */
/* requires a re-execution of the CVT program */
if ( grayscale != exec->grayscale )
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index e5a02b9..d88e34f 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -247,7 +247,118 @@ FT_BEGIN_HEADER
TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */
TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */
- FT_Bool grayscale; /* are we hinting for grayscale? */
+ FT_Bool grayscale; /* Bi-level hinting and grayscale
+ rendering */
+
+ /* Modern TrueType fonts are usually rendered through Microsoft's
+ * collection of rendering techniques called ClearType (e.g. subpixel
+ * rendering and subpixel hinting). When ClearType was introduced, most
+ * fonts were not ready. Microsoft decided to implement a backwards
+ * compatibility mode that employed several simple to complicated
+ * assumptions and tricks that modified the interpretation of the bytecode
+ * contained in these fonts to make them look ClearType-y somehow. Most
+ * (web)fonts that were released since then have come to rely on these
+ * hacks to render correctly, even some of Microsoft's flagship ClearType
+ * fonts (Calibri, Cambria, Segoe UI).
+ *
+ * FreeType employs a small list of font-agnostic hacks to bludgeon
+ * non-native-ClearType fonts (except tricky ones[1]) into submission.
+ * FreeType will not try to toggle hacks for specific fonts for performance
+ * and complexity reasons. The focus is on modern (web)fonts rather than
+ * legacy fonts that were made for black-and-white rendering.
+ *
+ * Major hacks:
+ * - Any point movement on the X-axis will be ignored (cf. Direct_Move()
+ * and Direct_Move_X()). This has the smallest code footprint and single
+ * biggest effect. The ClearType way to increase resolution is
+ * supersampling the x-axis, the FreeType way is ignoring instuctions on
+ * the x-axis, which gives the same result in the majority of cases.
+ * - Points will not be moved post-IUP, except the x-component of diagonal
+ * moves post-IUP (cf. Direct_Move(), Direct_Move_Y(), Move_Zp2_Point()).
+ * Post-IUP changes are commonly used to "fix" pixel patterns which has
+ * little use outside monochrome rendering.
+ * - SHPIX and DELTAP will not execute unless moving a composite on the
+ * Y-axis or moving a previously Y-touched point. SHPIX will additionally
+ * deny movement on the X-axis (c.f. Ins_SHPIX() and Ins_DELTAP()). Both
+ * instructions are commonly used to "fix" pixel patterns for monochrome
+ * or Windows's GDI rendering but make little sense for FreeType
+ * rendering. Both can distort the outline. See [2] for details.
+ * - The hdmx table and modifications to phantom points are ignored.
+ * Bearings and advance widths remain unchanged (except rounding them
+ * outside the interpreter!). C.f. compute_glyph_metrics() and
+ * TT_Hint_Glyph(). Letting non-native-ClearType fonts modify spacing
+ * might mess up spacing.
+ *
+ * Minor hacks:
+ * - All rounding instructions are turned into Round_None if the freedom
+ * vector is parallel to the X-axis (c.f. Round_*()). Given ClearType's
+ * virtual increase of resolution on the X-axis, rounding to the physical
+ * pixel grid there doesn't make much sense. Native ClearType fonts know
+ * this, the rest (where backwards compatibility applies) may or may not.
+ * - SHP will deny movement on the X-axis (c.f. Ins_SHP()). Prevents dents.
+ * - FLIPRGON, FLIPRGOFF and FLIPPT will not execute post-IUP. This
+ * prevents dents in e.g. Arial-Regular's 'D' and 'G' at various sizes.
+ * - MSIRP, MIAP, MDRP and MIRP will see a control value cut-in and minimum
+ * distance of 0 if the freedom vector is parallel to the X-axis (c.f.
+ * Ins_MSIRP(), Ins_MIAP(), Ins_MDRP() and Ins_MIRP()). See [2] for
+ * details.
+ *
+ * Post-IUP is the state after both IUP[x] and IUP[y] have been executed.
+ *
+ * The best results are achieved for fonts that were from the outset
+ * designed with ClearType in mind, meaning they leave the X-axis mostly
+ * alone and don't mess with the "final" outline to produce more pleasing
+ * pixel patterns. The harder the designer tried to produce very specific
+ * patterns ("superhinting") for pre-ClearType-display, the worse the
+ * results.
+ *
+ * Microsoft defines a way to turn off backwards compatibility and
+ * interpret instructions as before ("native ClearType")[2][3]. The font
+ * designer then regains full control and is responsible for making the
+ * font work correctly with ClearType without any hand-holding by the
+ * interpreter or rasterizer[4]. The v38 interpreter assumes backwards
+ * compatibility by default, which can be turned off the same way by
+ * executing the following in the control program:
+ *
+ * #PUSH 4,3
+ * INSTCTRL[]
+ *
+ * (cf. Ins_INSTCTRL()).
+ *
+ * [1]: Tricky fonts as FreeType defines them rely on the bytecode
+ * interpreter to display correctly. Hacks can interfere with them, so
+ * they get treated like native ClearType fonts (v38 with
+ * backwards compatibility turned off). C.f. TT_RunIns().
+ * [2]: Proposed by Microsoft's Greg Hitchcock in
+ * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
+ * [3]: Beat Stamm describes it in more detail:
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec12
+ * [4]: The list of "native ClearType" fonts is small at the time of this
+ * writing, I found the following on a Windows 10 Update 1511
+ * installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft
+ * JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
+ * SimSun, NSimSun and Yu Gothic.
+ */
+ FT_Bool subpixel_hinting; /* Using v38 implies this. */
+ FT_Bool vertical_lcd; /* long side of LCD subpixel */
+ /* rectangles is horizontal */
+
+ /* Defaults to true with v38 interpreter. If this is false, it implies the
+ * interpreter is in v35 or in native ClearType mode. */
+ FT_Bool backwards_compatibility;
+
+ /* Useful for detecting and denying post-iup trickery that is usually used
+ * to fix pixel patterns ("superhinting"). */
+ FT_Bool iupx_called;
+ FT_Bool iupy_called;
+
+ /* ClearType hinting and grayscale rendering, as used by Universal Windows
+ * Platform apps (Windows 8 and above). Like the standard colorful
+ * ClearType mode, it utilizes a vastly increased virtual resolution on the
+ * X-axis. Different from bi-level hinting and grayscale rendering, the
+ * old mode from Win9x days that roughly adheres to the physical pixel grid
+ * on both axes. */
+ FT_Bool grayscale_cleartype;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Round_Func func_round_sphn; /* subpixel rounding function */
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index a05f216..953931f 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -1286,12 +1286,7 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
TT_Driver driver = (TT_Driver)ttdriver;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
driver->interpreter_version = TT_INTERPRETER_VERSION_38;
-#else
- driver->interpreter_version = TT_INTERPRETER_VERSION_35;
-#endif
#else /* !TT_USE_BYTECODE_INTERPRETER */
--
2.5.5
>From 70e8dafd9ecf547d7ebdad0fa1d5d6b19bdf0041 Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <madig...@gmail.com>
Date: Thu, 17 Mar 2016 21:54:50 +0100
Subject: [PATCH 2/3] Implement v38 bytecode interpreter.
---
src/truetype/ttinterp.c | 230 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 214 insertions(+), 16 deletions(-)
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 78c35f2..8e597de 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -1642,6 +1642,10 @@
/* <InOut> */
/* zone :: The affected glyph zone. */
/* */
+ /* <Note> */
+ /* See ttinterp.h for details on backwards compatibility mode. Will */
+ /* `touch' the point. */
+ /* */
static void
Direct_Move( TT_ExecContext exc,
TT_GlyphZone zone,
@@ -1660,6 +1664,10 @@
( !exc->ignore_x_mode ||
( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ /* 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 ( !exc->backwards_compatibility )
zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
@@ -1669,7 +1677,9 @@
if ( v != 0 )
{
- zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+ if ( !( exc->backwards_compatibility &&
+ exc->iupx_called && exc->iupy_called ) )
+ zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1720,6 +1730,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. */
/* */
/*************************************************************************/
@@ -1736,6 +1747,7 @@
if ( !SUBPIXEL_HINTING ||
!exc->ignore_x_mode )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ if ( ! exc->backwards_compatibility )
zone->cur[point].x += distance;
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
@@ -1750,7 +1762,9 @@
{
FT_UNUSED( exc );
- zone->cur[point].y += distance;
+ if ( !( exc->backwards_compatibility &&
+ exc->iupx_called && exc->iupy_called ) )
+ zone->cur[point].y += distance;
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1853,6 +1867,9 @@
/* <Return> */
/* Rounded distance. */
/* */
+ /* <Note> */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ /* */
static FT_F26Dot6
Round_To_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -1860,8 +1877,9 @@
{
FT_F26Dot6 val;
- FT_UNUSED( exc );
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ return Round_None( exc, distance, compensation );
if ( distance >= 0 )
{
@@ -1896,6 +1914,9 @@
/* <Return> */
/* Rounded distance. */
/* */
+ /* <Note> */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ /* */
static FT_F26Dot6
Round_To_Half_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -1903,8 +1924,9 @@
{
FT_F26Dot6 val;
- FT_UNUSED( exc );
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ return Round_None( exc, distance, compensation );
if ( distance >= 0 )
{
@@ -1939,6 +1961,9 @@
/* <Return> */
/* Rounded distance. */
/* */
+ /* <Note> */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ /* */
static FT_F26Dot6
Round_Down_To_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -1946,8 +1971,9 @@
{
FT_F26Dot6 val;
- FT_UNUSED( exc );
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ return Round_None( exc, distance, compensation );
if ( distance >= 0 )
{
@@ -1982,6 +2008,9 @@
/* <Return> */
/* Rounded distance. */
/* */
+ /* <Note> */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ /* */
static FT_F26Dot6
Round_Up_To_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -1989,8 +2018,9 @@
{
FT_F26Dot6 val;
- FT_UNUSED( exc );
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ return Round_None( exc, distance, compensation );
if ( distance >= 0 )
{
@@ -2025,6 +2055,9 @@
/* <Return> */
/* Rounded distance. */
/* */
+ /* <Note> */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ /* */
static FT_F26Dot6
Round_To_Double_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -2032,8 +2065,9 @@
{
FT_F26Dot6 val;
- FT_UNUSED( exc );
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ return Round_None( exc, distance, compensation );
if ( distance >= 0 )
{
@@ -2074,6 +2108,8 @@
/* 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,
@@ -2082,6 +2118,9 @@
FT_F26Dot6 val;
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ return Round_None( exc, distance, compensation );
+
if ( distance >= 0 )
{
val = ( distance - exc->phase + exc->threshold + compensation ) &
@@ -2123,6 +2162,8 @@
/* 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,
@@ -2131,6 +2172,9 @@
FT_F26Dot6 val;
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ return Round_None( exc, distance, compensation );
+
if ( distance >= 0 )
{
val = ( ( distance - exc->phase + exc->threshold + compensation ) /
@@ -5049,6 +5093,11 @@
if ( K == 3 )
exc->ignore_x_mode = FT_BOOL( L == 4 );
#endif
+ /* 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 ( K == 3 )
+ exc->backwards_compatibility = ! FT_BOOL( L == 4 );
}
@@ -5133,6 +5182,10 @@
FT_UShort point;
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( exc->backwards_compatibility && exc->iupx_called && exc->iupy_called )
+ goto Fail;
+
if ( exc->top < exc->GS.loop )
{
if ( exc->pedantic_hinting )
@@ -5179,6 +5232,10 @@
FT_UShort I, K, L;
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( exc->backwards_compatibility && exc->iupx_called && exc->iupy_called )
+ return;
+
K = (FT_UShort)args[1];
L = (FT_UShort)args[0];
@@ -5208,6 +5265,10 @@
FT_UShort I, K, L;
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( exc->backwards_compatibility && exc->iupx_called && exc->iupy_called )
+ return;
+
K = (FT_UShort)args[1];
L = (FT_UShort)args[0];
@@ -5267,6 +5328,7 @@
}
+ /* See ttinterp.h for details on backwards compatibility mode. */
static void
Move_Zp2_Point( TT_ExecContext exc,
FT_UShort point,
@@ -5276,14 +5338,18 @@
{
if ( exc->GS.freeVector.x != 0 )
{
- exc->zp2.cur[point].x += dx;
+ if ( !( exc->backwards_compatibility &&
+ exc->iupx_called && exc->iupy_called ) )
+ 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;
+ if ( !( exc->backwards_compatibility &&
+ exc->iupx_called && exc->iupy_called ) )
+ exc->zp2.cur[point].y += dy;
if ( touch )
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -5337,7 +5403,10 @@
Move_Zp2_Point( exc, point, 0, dy, TRUE );
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
+ if ( exc->backwards_compatibility )
+ Move_Zp2_Point( exc, point, 0, dy, TRUE );
+ else
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
exc->GS.loop--;
}
@@ -5468,7 +5537,6 @@
FT_Int B1, B2;
#endif
-
if ( exc->top < exc->GS.loop + 1 )
{
if ( exc->pedantic_hinting )
@@ -5574,7 +5642,17 @@
#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
+ if ( 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
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
@@ -5616,6 +5694,12 @@
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin;
+
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ control_value_cutin = 0;
+
point = (FT_UShort)args[0];
if ( BOUNDS( point, exc->zp1.n_points ) ||
@@ -5646,6 +5730,10 @@
distance = args[1];
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ if ( exc->backwards_compatibility &&
+ FT_ABS( distance - args[1] ) >= control_value_cutin )
+ distance = args[1];
+
exc->func_move( exc, &exc->zp1, point, args[1] - distance );
exc->GS.rp1 = exc->GS.rp0;
@@ -5738,6 +5826,10 @@
control_value_cutin = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ control_value_cutin = 0;
+
if ( BOUNDS( point, exc->zp0.n_points ) ||
BOUNDSL( cvtEntry, exc->cvtSize ) )
{
@@ -5845,6 +5937,10 @@
minimum_distance = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+ minimum_distance = 0;
+
point = (FT_UShort)args[0];
if ( BOUNDS( point, exc->zp1.n_points ) ||
@@ -5998,6 +6094,10 @@
control_value_cutin = minimum_distance = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+ control_value_cutin = minimum_distance = 0;
+
/* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
if ( BOUNDS( point, exc->zp1.n_points ) ||
@@ -6106,6 +6206,13 @@
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ if ( exc->backwards_compatibility &&
+ exc->GS.gep0 == exc->GS.gep1 )
+ {
+ if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
+ cvt_dist = org_dist;
+ }
+
distance = Round_None(
exc,
cvt_dist,
@@ -6324,6 +6431,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 +6439,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 +6828,20 @@
FT_Short contour; /* current contour */
+ /* 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 ( exc->backwards_compatibility )
+ {
+ if ( exc->iupx_called && exc->iupy_called )
+ return;
+
+ if ( exc->opcode & 1 )
+ exc->iupx_called = TRUE;
+ else
+ exc->iupy_called = TRUE;
+ }
+
/* ignore empty outlines */
if ( exc->pts.n_contours == 0 )
return;
@@ -6945,8 +7068,15 @@
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
- exc->func_move( exc, &exc->zp0, A, B );
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( 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
+ exc->func_move( exc, &exc->zp0, A, B );
}
}
else
@@ -7063,9 +7193,11 @@
FT_Long* args )
{
FT_Long K;
+ TT_Driver driver;
K = 0;
+ driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/********************************/
@@ -7091,7 +7223,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,13 +7242,65 @@
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;
+
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ {
+ /********************************/
+ /* HINTING FOR SUBPIXEL */
+ /* Selector Bit: 6 */
+ /* Return Bit(s): 13 */
+ /* */
+ /* v38 will do 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 )
+ K |= 1 << 15;
+
+ /********************************/
+ /* SUBPIXEL POSITIONED? */
+ /* Selector Bit: 10 */
+ /* Return Bit(s): 17 */
+ /* */
+ /* XXX: FreeType supports it, dependant 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 set
+ * 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 set
+ * FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V) */
+ if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
+ K |= 1 << 19;
+ }
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
if ( SUBPIXEL_HINTING &&
@@ -7274,6 +7458,8 @@
FT_Long ins_counter = 0; /* executed instructions counter */
FT_UShort i;
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
FT_Byte opcode_pattern[1][2] = {
/* #8 TypeMan Talk Align */
@@ -7291,6 +7477,18 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
exc->iup_called = FALSE;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ /* 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 ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+ !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;
/* set PPEM and CVT functions */
exc->tt_metrics.ratio = 0;
--
2.5.5
>From 6a0fe5d09291070a83552c41bdcce47ba7339192 Mon Sep 17 00:00:00 2001
From: Nikolaus Waxweiler <madig...@gmail.com>
Date: Sun, 17 Apr 2016 20:06:42 +0200
Subject: [PATCH 3/3] Coexist with Infinality code. Engine can be switched at
runtime.
---
devel/ftoption.h | 3 +-
include/freetype/config/ftoption.h | 56 +++--
include/freetype/ftttdrv.h | 63 ++++-
src/truetype/ttdriver.c | 33 ++-
src/truetype/ttgload.c | 122 ++++++----
src/truetype/ttinterp.c | 487 ++++++++++++++++++++++++++-----------
src/truetype/ttinterp.h | 20 +-
src/truetype/ttobjs.c | 13 +
src/truetype/ttobjs.h | 1 +
9 files changed, 580 insertions(+), 218 deletions(-)
diff --git a/devel/ftoption.h b/devel/ftoption.h
index b354efd..09e0c53 100644
--- a/devel/ftoption.h
+++ b/devel/ftoption.h
@@ -602,7 +602,8 @@ FT_BEGIN_HEADER
/* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */
/* defined. */
/* */
-#define TT_CONFIG_OPTION_SUBPIXEL_HINTING
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/*************************************************************************/
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index a8097fe..ec6cee1 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -585,24 +585,46 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
- /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile */
- /* EXPERIMENTAL subpixel hinting support into the TrueType driver. This */
- /* replaces the native TrueType hinting mechanism when anything but */
- /* FT_RENDER_MODE_MONO is requested. */
- /* */
- /* Enabling this causes the TrueType driver to ignore instructions under */
- /* certain conditions. This is done in accordance with the guide here, */
- /* with some minor differences: */
- /* */
- /* http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
- /* */
- /* By undefining this, you only compile the code necessary to hint */
- /* TrueType glyphs with native TT hinting. */
- /* */
- /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */
- /* defined. */
- /* */
+ /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING or
+ * TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN if you want to compile subpixel
+ * hinting support into the TrueType driver. This modifies the TrueType
+ * hinting mechanism when anything but FT_RENDER_MODE_MONO is requested.
+ *
+ * What actually happens is, it modifies the bytecode interpreter to
+ * interpret (or not) instructions in a certain way so that all TrueType
+ * fonts look like they do in a Windows ClearType (DirectWrite) environment.
+ * See [1] for a technical overview on what this means. See ttinter.h for
+ * more details on the LEAN option.
+ *
+ * There are two options:
+ * - TT_CONFIG_OPTION_SUBPIXEL_HINTING: Associated with the "Infinality"
+ * moniker. Contributed by an individual nicknamed Infinality with the goal
+ * of making TrueType fonts render better than on Windows. A high amount of
+ * configurability and flexibility, down to rules for single glyphs in
+ * fonts, but also very slow. Its' experimental and slow nature and the
+ * original developer losing interest meant that this option was never
+ * enabled in default builds.
+ * - TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN: The new default mode for the
+ * TrueType driver. The Infinality code base was stripped to the bare
+ * minimum and all configurability removed in the name of speed and
+ * simplicity. The configurability was mainly aimed at legacy fonts like
+ * Arial, Times New Roman and Courier. Legacy fonts are fonts that modify
+ * vertical stems to achieve clean black-and-white bitmaps. The new mode
+ * focuses on applying a minimal set of rules to all fonts indiscriminately
+ * so that modern and web fonts render well while legacy fonts render okay.
+ *
+ * By undefining these, you get rendering behavior like on Windows without
+ * ClearType, i.e. Windows XP without ClearType enabled and Win9x
+ * (interpreter version v35). Or not, depending on how much hinting blood and
+ * testing tears the font designer put into a given font. If you define one
+ * or both, you can switch between between v35 and the ones you define.
+ *
+ * This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be defined.
+ *
+ * [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
+ */
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/*************************************************************************/
diff --git a/include/freetype/ftttdrv.h b/include/freetype/ftttdrv.h
index 6c02e65..710406e 100644
--- a/include/freetype/ftttdrv.h
+++ b/include/freetype/ftttdrv.h
@@ -139,9 +139,9 @@ FT_BEGIN_HEADER
*
* @description:
* Currently, two versions are available, representing the bytecode
- * interpreter with and without subpixel hinting support,
- * respectively. The default is subpixel support if
- * TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel
+ * interpreter with and without subpixel hinting support, respectively.
+ * The default is subpixel support if TT_CONFIG_OPTION_SUBPIXEL_HINTING or
+ * TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN is defined, and no subpixel
* support otherwise (since it isn't available then).
*
* If subpixel hinting is on, many TrueType bytecode instructions behave
@@ -150,7 +150,7 @@ FT_BEGIN_HEADER
* much increased horizontal resolution, then sampling down the created
* output to subpixel precision. However, many older fonts are not
* suited to this and must be specially taken care of by applying
- * (hardcoded) font-specific tweaks.
+ * (hardcoded) tweaks.
*
* Details on subpixel hinting and some of the necessary tweaks can be
* found in Greg Hitchcock's whitepaper at
@@ -180,6 +180,58 @@ FT_BEGIN_HEADER
/**************************************************************************
*
+ * @property:
+ * hinting-engine
+ *
+ * @description:
+ * This property allows switching between the older Infinality interpreter
+ * for subpixel hinting if TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined and
+ * the stripped-down lean version of it if
+ * TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN is defined. Lean is the default.
+ *
+ * The following example code demonstrates how to select Infinality's hinting
+ * engine (omitting the error handling).
+ *
+ * {
+ * FT_Library library;
+ * FT_UInt hinting_engine = FT_TT_HINTING_INFINALITY;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "truetype",
+ * "hinting-engine", &hinting_engine );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_TT_HINTING_XXX
+ *
+ * @description:
+ * A list of constants used for the @hinting-engine property to select
+ * the hinting engine for CFF fonts.
+ *
+ * @values:
+ * FT_TT_HINTING_INFINALITY ::
+ * Use the old FreeType hinting engine.
+ *
+ * FT_TT_HINTING_LEAN ::
+ * Use the hinting engine contributed by Adobe.
+ *
+ */
+#define FT_TT_HINTING_INFINALITY 0
+#define FT_TT_HINTING_LEAN 1
+
+
+ /**************************************************************************
+ *
* @enum:
* TT_INTERPRETER_VERSION_XXX
*
@@ -296,7 +348,10 @@ FT_BEGIN_HEADER
*
*/
#define TT_INTERPRETER_VERSION_35 35
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
#define TT_INTERPRETER_VERSION_38 38
+#endif
/* */
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index a856fed..530eede 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -72,14 +72,32 @@
FT_UInt* interpreter_version = (FT_UInt*)value;
- if ( *interpreter_version != TT_INTERPRETER_VERSION_35 &&
- *interpreter_version != TT_INTERPRETER_VERSION_38 )
+ if ( *interpreter_version != TT_INTERPRETER_VERSION_35
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ && *interpreter_version != TT_INTERPRETER_VERSION_38
+#endif
+ )
error = FT_ERR( Unimplemented_Feature );
else
driver->interpreter_version = *interpreter_version;
return error;
}
+ else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+ {
+ FT_UInt* hinting_engine = (FT_UInt*)value;
+
+
+#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( *hinting_engine != FT_TT_HINTING_LEAN )
+ error = FT_ERR( Unimplemented_Feature );
+ else
+#endif
+ driver->hinting_engine = *hinting_engine;
+
+ return error;
+ }
FT_TRACE0(( "tt_property_set: missing property `%s'\n",
property_name ));
@@ -107,6 +125,17 @@
return error;
}
+ else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+ {
+ FT_UInt hinting_engine = driver->hinting_engine;
+ FT_UInt* val = (FT_UInt*)value;
+
+
+ *val = hinting_engine;
+
+ return error;
+ }
+
FT_TRACE0(( "tt_property_get: missing property `%s'\n",
property_name ));
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 8ea887c..39a1afc 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -154,7 +154,8 @@
loader->vadvance = advance_height;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
loader->exec )
{
loader->exec->sph_tweak_flags = 0;
@@ -733,7 +734,8 @@
TT_Hint_Glyph( TT_Loader loader,
FT_Bool is_composite )
{
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -816,19 +818,28 @@
#endif
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* Save possibly modified glyph phantom points unless in v38 backwards
* compatibility mode, where no movement on the X-axis means no reason to
* change bearings or advance widths. */
- if ( !loader->exec->backwards_compatibility )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ !loader->exec->backwards_compatibility )
{
loader->pp1 = zone->cur[zone->n_points - 4];
loader->pp2 = zone->cur[zone->n_points - 3];
loader->pp3 = zone->cur[zone->n_points - 2];
loader->pp4 = zone->cur[zone->n_points - 1];
}
+#else
+ loader->pp1 = zone->cur[zone->n_points - 4];
+ loader->pp2 = zone->cur[zone->n_points - 3];
+ loader->pp3 = zone->cur[zone->n_points - 2];
+ loader->pp4 = zone->cur[zone->n_points - 1];
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
@@ -923,7 +934,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
/* scale, but only if enabled and only if TT hinting is being used */
if ( IS_HINTED( loader->load_flags ) )
@@ -1329,6 +1341,7 @@
* (3) for everything else.
*
*/
+ /* XXX merge infinality + lean datafields? */
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#define TT_LOADER_SET_PP( loader ) \
@@ -1948,8 +1961,9 @@
FT_UInt glyph_index )
{
TT_Face face = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
FT_BBox bbox;
@@ -1979,7 +1993,11 @@
* FT_LOAD_COMPUTE_METRICS is set or backwards compatibility mode of the
* v38 interpreter is active. See ttinterp.h for details on backwards
* compatibility mode. */
- if ( !( loader->exec && loader->exec->backwards_compatibility ) &&
+ if (
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ ! ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ ( loader->exec && loader->exec->backwards_compatibility ) ) &&
+#endif
!face->postscript.isFixedPitch &&
IS_HINTED( loader->load_flags ) &&
!( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
@@ -1993,7 +2011,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
FT_Bool ignore_x_mode;
@@ -2195,15 +2214,17 @@
TT_Face face;
FT_Stream stream;
- TT_Driver driver;
#ifdef TT_USE_BYTECODE_INTERPRETER
FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
#endif
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
+#endif
face = (TT_Face)glyph->face;
stream = face->root.stream;
- driver = (TT_Driver)FT_FACE_DRIVER( face );
FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
@@ -2213,13 +2234,13 @@
if ( IS_HINTED( load_flags ) && !glyf_table_only )
{
TT_ExecContext exec;
- FT_Bool grayscale;
- FT_Bool subpixel_hinting;
+ FT_Bool grayscale = TRUE;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ FT_Bool subpixel_hinting_lean;
FT_Bool grayscale_cleartype;
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
-
FT_Bool subpixel_hinting = FALSE;
#if 0
@@ -2252,21 +2273,25 @@
if ( !exec )
return FT_THROW( Could_Not_Find_Context );
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
- subpixel_hinting = TRUE;
+ subpixel_hinting_lean = TRUE;
grayscale_cleartype = ! FT_BOOL( load_flags & FT_LOAD_TARGET_LCD ||
load_flags & FT_LOAD_TARGET_LCD_V );
- exec->vertical_lcd = FT_BOOL( load_flags & FT_LOAD_TARGET_LCD_V );
+ exec->vertical_lcd_lean = FT_BOOL( load_flags & FT_LOAD_TARGET_LCD_V );
} else {
- subpixel_hinting = FALSE;
+ subpixel_hinting_lean = FALSE;
grayscale_cleartype = FALSE;
- exec->vertical_lcd = FALSE;
+ exec->vertical_lcd_lean = FALSE;
}
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
FT_RENDER_MODE_MONO ) &&
@@ -2323,10 +2348,17 @@
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- {
- grayscale = FT_BOOL( ! subpixel_hinting &&
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN ) {
+ grayscale = FT_BOOL( ! subpixel_hinting_lean &&
FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
+ } else
+#else
+ {
+ grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ FT_RENDER_MODE_MONO );
}
+#endif
error = TT_Load_Context( exec, face, size );
if ( error )
@@ -2334,7 +2366,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
/* a change from mono to subpixel rendering (and vice versa) */
/* requires a re-execution of the CVT program */
@@ -2363,28 +2396,32 @@
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
{
- /* a change from mono to subpixel rendering (and vice versa) */
- /* requires a re-execution of the CVT program */
- if ( subpixel_hinting != exec->subpixel_hinting )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN )
{
- FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
- " re-executing `prep' table\n" ));
+ /* a change from mono to subpixel rendering (and vice versa) */
+ /* requires a re-execution of the CVT program */
+ if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
+ {
+ FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
+ " re-executing `prep' table\n" ));
- exec->subpixel_hinting = subpixel_hinting;
- reexecute = TRUE;
- }
+ exec->subpixel_hinting_lean = subpixel_hinting_lean;
+ reexecute = TRUE;
+ }
- /* a change from colored to grayscale subpixel rendering (and vice
- * versa) requires a re-execution of the CVT program */
- if ( grayscale_cleartype != exec->grayscale_cleartype )
- {
- FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
- " re-executing `prep' table\n" ));
+ /* a change from colored to grayscale subpixel rendering (and vice
+ * versa) requires a re-execution of the CVT program */
+ if ( grayscale_cleartype != exec->grayscale_cleartype )
+ {
+ FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
+ " re-executing `prep' table\n" ));
- exec->grayscale_cleartype = grayscale_cleartype;
- reexecute = TRUE;
+ exec->grayscale_cleartype = grayscale_cleartype;
+ reexecute = TRUE;
+ }
}
-
+#endif
/* a change from mono to grayscale rendering (and vice versa) */
/* requires a re-execution of the CVT program */
if ( grayscale != exec->grayscale )
@@ -2420,7 +2457,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* check whether we have a font hinted for ClearType -- */
/* note that this flag can also be modified in a glyph's bytecode */
- if ( exec->GS.instruct_control & 4 )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ exec->GS.instruct_control & 4 )
exec->ignore_x_mode = 0;
#endif
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 8e597de..caa3b37 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -1653,22 +1653,35 @@
FT_F26Dot6 distance )
{
FT_F26Dot6 v;
-
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
v = exc->GS.freeVector.x;
if ( v != 0 )
{
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !SUBPIXEL_HINTING ||
- ( !exc->ignore_x_mode ||
- ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ ( !SUBPIXEL_HINTING ||
+ ( !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 );
#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 ( !exc->backwards_compatibility )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ !exc->backwards_compatibility )
zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+#endif
+#else
+ zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+#endif
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1677,8 +1690,11 @@
if ( v != 0 )
{
- if ( !( exc->backwards_compatibility &&
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( !( driver->hinting_engine == FT_TT_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;
@@ -1741,14 +1757,30 @@
FT_UShort point,
FT_F26Dot6 distance )
{
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#else
FT_UNUSED( exc );
+#endif
+
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !SUBPIXEL_HINTING ||
- !exc->ignore_x_mode )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ ( !SUBPIXEL_HINTING ||
+ !exc->ignore_x_mode ) )
+ zone->cur[point].x += distance;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- if ( ! exc->backwards_compatibility )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ ! exc->backwards_compatibility )
zone->cur[point].x += distance;
+#endif
+#else
+ zone->cur[point].x += distance;
+#endif
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1762,8 +1794,10 @@
{
FT_UNUSED( exc );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
if ( !( exc->backwards_compatibility &&
exc->iupx_called && exc->iupy_called ) )
+#endif
zone->cur[point].y += distance;
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1876,10 +1910,15 @@
FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
return Round_None( exc, distance, compensation );
+#else
+ FT_UNUSED( exc );
+#endif
if ( distance >= 0 )
{
@@ -1923,10 +1962,16 @@
FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
return Round_None( exc, distance, compensation );
+#else
+ FT_UNUSED( exc );
+#endif
+
if ( distance >= 0 )
{
@@ -1970,10 +2015,16 @@
FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
return Round_None( exc, distance, compensation );
+#else
+ FT_UNUSED( exc );
+#endif
+
if ( distance >= 0 )
{
@@ -2017,10 +2068,16 @@
FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
return Round_None( exc, distance, compensation );
+#else
+ FT_UNUSED( exc );
+#endif
+
if ( distance >= 0 )
{
@@ -2064,10 +2121,16 @@
FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
return Round_None( exc, distance, compensation );
+#else
+ FT_UNUSED( exc );
+#endif
+
if ( distance >= 0 )
{
@@ -2116,10 +2179,16 @@
FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
return Round_None( exc, distance, compensation );
+#else
+ FT_UNUSED( exc );
+#endif
+
if ( distance >= 0 )
{
@@ -2170,10 +2239,16 @@
FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
return Round_None( exc, distance, compensation );
+#else
+ FT_UNUSED( exc );
+#endif
+
if ( distance >= 0 )
{
@@ -2922,7 +2997,9 @@
Ins_RS( TT_ExecContext exc,
FT_Long* args )
{
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
FT_ULong I = (FT_ULong)args[0];
@@ -2936,42 +3013,28 @@
}
else
{
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* subpixel hinting - avoid Typeman Dstroke and */
/* IStroke and Vacuform rounds */
- if ( SUBPIXEL_HINTING &&
- exc->ignore_x_mode &&
- ( ( I == 24 &&
- ( exc->face->sph_found_func_flags &
- ( SPH_FDEF_SPACING_1 |
- SPH_FDEF_SPACING_2 ) ) ) ||
- ( I == 22 &&
- ( exc->sph_in_func_flags &
- SPH_FDEF_TYPEMAN_STROKES ) ) ||
- ( I == 8 &&
- ( exc->face->sph_found_func_flags &
- SPH_FDEF_VACUFORM_ROUND_1 ) &&
- exc->iup_called ) ) )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ ( ( I == 24 &&
+ ( exc->face->sph_found_func_flags &
+ ( SPH_FDEF_SPACING_1 |
+ SPH_FDEF_SPACING_2 ) ) ) ||
+ ( I == 22 &&
+ ( exc->sph_in_func_flags &
+ SPH_FDEF_TYPEMAN_STROKES ) ) ||
+ ( I == 8 &&
+ ( exc->face->sph_found_func_flags &
+ SPH_FDEF_VACUFORM_ROUND_1 ) &&
+ 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 */
}
@@ -3452,6 +3515,10 @@
FT_ULong n;
TT_DefRecord* rec;
TT_DefRecord* limit;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* arguments to opcodes are skipped by `SKIP_Code' */
@@ -3611,7 +3678,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING )
{
for ( i = 0; i < opcode_patterns; i++ )
{
@@ -3797,6 +3865,9 @@
FT_ULong F;
TT_CallRec* pCrec;
TT_DefRecord* def;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
/* first of all, check the index */
@@ -3836,14 +3907,17 @@
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 ) ) )
- goto Fail;
- else
- exc->sph_in_func_flags = def->sph_fdef_flags;
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
+ {
+ 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 ) ) )
+ goto Fail;
+ else
+ exc->sph_in_func_flags = def->sph_fdef_flags;
+ }
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
/* check the call stack */
@@ -3886,6 +3960,9 @@
FT_ULong F;
TT_CallRec* pCrec;
TT_DefRecord* def;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
/* first of all, check the index */
@@ -3924,12 +4001,15 @@
goto Fail;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- 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;
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
+ {
+ if ( SUBPIXEL_HINTING &&
+ 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 */
/* check stack */
@@ -4771,6 +4851,9 @@
{
FT_UShort K, L;
FT_F26Dot6 D;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
K = (FT_UShort)args[1];
@@ -4827,7 +4910,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
FT_ABS( D ) == 64 )
D += 1;
@@ -5056,6 +5140,10 @@
FT_Long* args )
{
FT_ULong K, L, Kf;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
K = (FT_ULong)args[1];
@@ -5087,17 +5175,22 @@
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 ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
+ exc->ignore_x_mode = FT_BOOL( L == 4 );
#endif
- /* 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 ( K == 3 )
- exc->backwards_compatibility = ! FT_BOOL( L == 4 );
+#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 ( driver->hinting_engine == FT_TT_HINTING_LEAN )
+ exc->backwards_compatibility = ! FT_BOOL( L == 4 );
+#endif
+ }
}
@@ -5182,9 +5275,11 @@
FT_UShort point;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* See ttinterp.h for details on backwards compatibility mode. */
if ( exc->backwards_compatibility && exc->iupx_called && exc->iupy_called )
goto Fail;
+#endif
if ( exc->top < exc->GS.loop )
{
@@ -5232,9 +5327,11 @@
FT_UShort I, K, L;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* See ttinterp.h for details on backwards compatibility mode. */
if ( exc->backwards_compatibility && exc->iupx_called && exc->iupy_called )
return;
+#endif
K = (FT_UShort)args[1];
L = (FT_UShort)args[0];
@@ -5265,9 +5362,11 @@
FT_UShort I, K, L;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* See ttinterp.h for details on backwards compatibility mode. */
if ( exc->backwards_compatibility && exc->iupx_called && exc->iupy_called )
return;
+#endif
K = (FT_UShort)args[1];
L = (FT_UShort)args[0];
@@ -5338,8 +5437,10 @@
{
if ( exc->GS.freeVector.x != 0 )
{
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
if ( !( exc->backwards_compatibility &&
exc->iupx_called && exc->iupy_called ) )
+#endif
exc->zp2.cur[point].x += dx;
if ( touch )
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
@@ -5347,8 +5448,10 @@
if ( exc->GS.freeVector.y != 0 )
{
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
if ( !( 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;
@@ -5370,6 +5473,10 @@
FT_F26Dot6 dx, dy;
FT_UShort point;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
if ( exc->top < exc->GS.loop )
@@ -5398,14 +5505,18 @@
else
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* doesn't follow Cleartype spec but produces better result */
- if ( SUBPIXEL_HINTING &&
- exc->ignore_x_mode )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode ) )
Move_Zp2_Point( exc, point, 0, dy, TRUE );
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- if ( exc->backwards_compatibility )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility )
Move_Zp2_Point( exc, point, 0, dy, TRUE );
else
+#endif
Move_Zp2_Point( exc, point, dx, dy, TRUE );
exc->GS.loop--;
@@ -5536,6 +5647,10 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
FT_Int B1, B2;
#endif
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
if ( exc->top < exc->GS.loop + 1 )
{
@@ -5563,6 +5678,7 @@
}
else
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY )
{
/* If not using ignore_x_mode rendering, allow ZP2 move. */
/* If inline deltas aren't allowed, skip ZP2 move. */
@@ -5636,13 +5752,11 @@
}
else
Move_Zp2_Point( exc, point, dx, dy, TRUE );
- }
-
- Skip:
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
- if ( exc->backwards_compatibility )
+ } else
+#endif
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility )
{
/* XXX: breaks Rokkitt < v1.2 (glyphs explode vertically on ALIGNRP).
*/
@@ -5652,10 +5766,12 @@
Move_Zp2_Point( exc, point, 0, dy, TRUE );
}
else
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
-
#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ Skip:
+#endif
exc->GS.loop--;
}
@@ -5677,12 +5793,18 @@
{
FT_UShort point;
FT_F26Dot6 distance;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- FT_F26Dot6 control_value_cutin = 0; /* pacify compiler */
+ FT_F26Dot6 control_value_cutin = 0;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#else
+ FT_UNUSED( control_value_cutin );
+#endif
- if ( SUBPIXEL_HINTING )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING )
{
control_value_cutin = exc->GS.control_value_cutin;
@@ -5691,14 +5813,16 @@
!( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
control_value_cutin = 0;
}
-
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
- FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin;
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* See ttinterp.h for details on backwards compatibility mode. */
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
control_value_cutin = 0;
+ else
+#endif
+ control_value_cutin = exc->GS.control_value_cutin;
+
point = (FT_UShort)args[0];
@@ -5723,16 +5847,19 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* subpixel hinting - make MSIRP respect CVT cut-in; */
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
exc->GS.freeVector.x != 0 &&
FT_ABS( distance - args[1] ) >= control_value_cutin )
distance = args[1];
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
- if ( exc->backwards_compatibility &&
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility &&
FT_ABS( distance - args[1] ) >= control_value_cutin )
distance = args[1];
+#endif
exc->func_move( exc, &exc->zp1, point, args[1] - distance );
@@ -5757,6 +5884,9 @@
FT_UShort point;
FT_F26Dot6 cur_dist;
FT_F26Dot6 distance;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
point = (FT_UShort)args[0];
@@ -5772,8 +5902,9 @@
{
cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- exc->ignore_x_mode &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
exc->GS.freeVector.x != 0 )
distance = Round_None(
exc,
@@ -5811,6 +5942,10 @@
FT_F26Dot6 distance;
FT_F26Dot6 org_dist;
FT_F26Dot6 control_value_cutin;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
control_value_cutin = exc->GS.control_value_cutin;
@@ -5818,17 +5953,20 @@
point = (FT_UShort)args[0];
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
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 */
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* See ttinterp.h for details on backwards compatibility mode. */
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
control_value_cutin = 0;
+#endif
if ( BOUNDS( point, exc->zp0.n_points ) ||
BOUNDSL( cvtEntry, exc->cvtSize ) )
@@ -5865,9 +6003,10 @@
#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 ||
- ( !exc->ignore_x_mode ||
- !exc->face->sph_compatibility_mode ) )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ ( !SUBPIXEL_HINTING ||
+ ( !exc->ignore_x_mode ||
+ !exc->face->sph_compatibility_mode ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
exc->zp0.org[point].x = TT_MulFix14( distance,
exc->GS.freeVector.x );
@@ -5876,7 +6015,8 @@
exc->zp0.cur[point] = exc->zp0.org[point];
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
distance > 0 &&
@@ -5892,7 +6032,8 @@
distance = org_dist;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
exc->GS.freeVector.x != 0 )
distance = Round_None( exc,
@@ -5923,23 +6064,30 @@
Ins_MDRP( TT_ExecContext exc,
FT_Long* args )
{
- FT_UShort point;
+ FT_UShort point = 0;
FT_F26Dot6 org_dist, distance, minimum_distance;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
minimum_distance = exc->GS.minimum_distance;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
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 */
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* See ttinterp.h for details on backwards compatibility mode. */
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
minimum_distance = 0;
+#endif
point = (FT_UShort)args[0];
@@ -6004,7 +6152,8 @@
if ( ( exc->opcode & 4 ) != 0 )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
exc->GS.freeVector.x != 0 )
distance = Round_None(
@@ -6079,6 +6228,10 @@
FT_Int B2 = 0;
FT_Bool reverse_move = FALSE;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
minimum_distance = exc->GS.minimum_distance;
@@ -6087,16 +6240,20 @@
cvtEntry = (FT_ULong)( args[1] + 1 );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
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 */
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* See ttinterp.h for details on backwards compatibility mode. */
- if ( exc->backwards_compatibility && exc->GS.freeVector.y == 0x0 )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility && exc->GS.freeVector.y == 0 )
control_value_cutin = minimum_distance = 0;
+#endif
/* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
@@ -6150,7 +6307,8 @@
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
exc->GS.freeVector.y != 0 &&
( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
@@ -6197,7 +6355,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* do cvt cut-in always in MIRP for sph */
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
exc->GS.gep0 == exc->GS.gep1 )
{
@@ -6205,13 +6364,14 @@
cvt_dist = org_dist;
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
if ( exc->backwards_compatibility &&
exc->GS.gep0 == exc->GS.gep1 )
{
if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
cvt_dist = org_dist;
}
+#endif
distance = Round_None(
exc,
@@ -6236,7 +6396,8 @@
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING )
{
B1 = exc->zp1.cur[point].y;
@@ -6258,7 +6419,8 @@
exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING )
{
B2 = exc->zp1.cur[point].y;
@@ -6305,10 +6467,13 @@
{
FT_UShort point;
FT_F26Dot6 distance;
-
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
exc->iup_called &&
( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
@@ -6826,12 +6991,18 @@
FT_UInt point; /* current point */
FT_Short contour; /* current contour */
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
+#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 ( exc->backwards_compatibility )
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ exc->backwards_compatibility )
{
if ( exc->iupx_called && exc->iupy_called )
return;
@@ -6841,6 +7012,7 @@
else
exc->iupy_called = TRUE;
}
+#endif
/* ignore empty outlines */
if ( exc->pts.n_contours == 0 )
@@ -6866,7 +7038,8 @@
point = 0;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode )
{
exc->iup_called = TRUE;
@@ -6945,11 +7118,16 @@
FT_UShort A;
FT_ULong C, P;
FT_Long B;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
FT_UShort B1, B2;
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->ignore_x_mode &&
exc->iup_called &&
( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
@@ -7010,7 +7188,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING )
{
/*
* Allow delta move if
@@ -7068,14 +7247,17 @@
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- /* See ttinterp.h for details on backwards compatibility mode. */
- if ( 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
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ /* See ttinterp.h for details on backwards compatibility mode. */
+ if ( driver->hinting_engine == FT_TT_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 );
}
}
@@ -7205,7 +7387,8 @@
/* Selector Bit: 0 */
/* Return Bit(s): 0-7 */
/* */
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
( args[0] & 1 ) != 0 &&
exc->subpixel_hinting )
{
@@ -7250,8 +7433,9 @@
if ( ( args[0] & 32 ) != 0 && exc->grayscale )
K |= 1 << 12;
-
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
/********************************/
/* HINTING FOR SUBPIXEL */
@@ -7267,7 +7451,7 @@
/* Selector Bit: 8 */
/* Return Bit(s): 15 */
/* */
- if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd )
+ if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
K |= 1 << 15;
/********************************/
@@ -7300,10 +7484,12 @@
if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
K |= 1 << 19;
}
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING &&
exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
{
@@ -7458,7 +7644,10 @@
FT_Long ins_counter = 0; /* executed instructions counter */
FT_UShort i;
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
FT_Byte opcode_pattern[1][2] = {
@@ -7477,11 +7666,13 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
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 ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+ if ( driver->hinting_engine == FT_TT_HINTING_LEAN &&
+ driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
!FT_IS_TRICKY( (&exc->face->root) ) )
exc->backwards_compatibility = ! (exc->GS.instruct_control & 4);
else
@@ -7489,6 +7680,7 @@
exc->iupx_called = FALSE;
exc->iupy_called = FALSE;
+#endif
/* set PPEM and CVT functions */
exc->tt_metrics.ratio = 0;
@@ -7583,7 +7775,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING )
+ if ( driver->hinting_engine == FT_TT_HINTING_INFINALITY &&
+ SUBPIXEL_HINTING )
{
for ( i = 0; i < opcode_patterns; i++ )
{
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index d88e34f..34acc89 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -250,6 +250,7 @@ FT_BEGIN_HEADER
FT_Bool grayscale; /* Bi-level hinting and grayscale
rendering */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
/* Modern TrueType fonts are usually rendered through Microsoft's
* collection of rendering techniques called ClearType (e.g. subpixel
* rendering and subpixel hinting). When ClearType was introduced, most
@@ -339,12 +340,20 @@ FT_BEGIN_HEADER
* JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
* SimSun, NSimSun and Yu Gothic.
*/
- FT_Bool subpixel_hinting; /* Using v38 implies this. */
- FT_Bool vertical_lcd; /* long side of LCD subpixel */
- /* rectangles is horizontal */
- /* Defaults to true with v38 interpreter. If this is false, it implies the
- * interpreter is in v35 or in native ClearType mode. */
+ /* Using v38 implies subpixel hinting. Used to detect interpreter version
+ * switches. "_lean" to differentiate from the Infinality
+ * "subpixel_hinting" that is managed differently. */
+ FT_Bool subpixel_hinting_lean;
+
+ /* Long side of a LCD subpixel is vertical (e.g. screen is rotated).
+ * "_lean" to differentiate from the Infinality "vertical_lcd" that is
+ * managed differently. */
+ FT_Bool vertical_lcd_lean;
+
+ /* Default to backwards compatibility mode in v38 interpreter. If this is
+ * false, it implies the interpreter is in v35 or in native ClearType mode.
+ */
FT_Bool backwards_compatibility;
/* Useful for detecting and denying post-iup trickery that is usually used
@@ -359,6 +368,7 @@ FT_BEGIN_HEADER
* old mode from Win9x days that roughly adheres to the physical pixel grid
* on both axes. */
FT_Bool grayscale_cleartype;
+#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Round_Func func_round_sphn; /* subpixel rounding function */
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 953931f..f9a4914 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -1286,7 +1286,20 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
TT_Driver driver = (TT_Driver)ttdriver;
+
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING || \
+ defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
driver->interpreter_version = TT_INTERPRETER_VERSION_38;
+#else
+ driver->interpreter_version = TT_INTERPRETER_VERSION_35;
+#endif
+
+#if defined TT_CONFIG_OPTION_SUBPIXEL_HINTING && \
+ !defined TT_CONFIG_OPTION_SUBPIXEL_HINTING_LEAN
+ driver->hinting_engine = FT_TT_HINTING_INFINALITY;
+#else
+ driver->hinting_engine = FT_TT_HINTING_LEAN;
+#endif
#else /* !TT_USE_BYTECODE_INTERPRETER */
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index ed61a7d..384a5c0 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -332,6 +332,7 @@ FT_BEGIN_HEADER
TT_GlyphZoneRec zone; /* glyph loader points zone */
FT_UInt interpreter_version;
+ FT_UInt hinting_engine;
} TT_DriverRec;
--
2.5.5
_______________________________________________
Freetype-devel mailing list
Freetype-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/freetype-devel