[truetype] New implementation of v38 bytecode interpreter [1/3].

This patch prepares data structures and the like.

See added comments in `ttinterp.h' for more information on this and
the following commits in the series.

* devel/ftoption.h, include/freetype/config/ftoption.h
(TT_CONFIG_OPTION_SUBPIXEL_HINTING): Assign values to differentiate
between subpixel versions.
(TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY,
TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL): New macros.

* include/freetype/ftttdrv.h (TT_INTERPRETER_VERSION_40): New macro.

* include/freetype/internal/tttypes.h (TT_FaceRec): Updated.

* src/truetype/ttinterp.h (TT_ExecContextRec): Define new fields
`subpixel_hinting_lean', `vertical_lcd_lean',
`backwards_compatibility', `iupx_called', iupy_called', and
`grayscale_cleartype' for new hinting mode.

* src/truetype/ttdriver.c (tt_property_set): Handle v38 and v40
interpreters conditionally.

* src/truetype/ttgload.c (TT_Hint_Glyph): Save phantom points unless
in v38 backwards compatibility mode.
Updated.
(compute_glyph_metrics): Add v38 backwards compatibility mode
constraint for adjusting advance widths.
Updated.
(tt_loader_init): Handle new flags `subpixel_hinting_lean',
`grayscale_cleartype', and `vertical_lcd_lean'.
Updated.
(tt_get_metrics, TT_Process_Simple_Glyph, TT_LOADER_SET_PP):
Updated.

* src/truetype/ttobjs.c (tt_driver_init): Conditionally set
default interpreter version number.

* src/truetype/ttsubpix.c, src/truetype/ttsubpix.h: Updated.
This commit is contained in:
Nikolaus Waxweiler 2016-05-18 06:57:59 +02:00 committed by Werner Lemberg
parent 119e8e41ef
commit 596157365a
12 changed files with 453 additions and 106 deletions

View File

@ -1,3 +1,47 @@
2016-05-17 Nikolaus Waxweiler <madigens@gmail.com>
[truetype] New implementation of v38 bytecode interpreter [1/3].
This patch prepares data structures and the like.
See added comments in `ttinterp.h' for more information on this and
the following commits in the series.
* devel/ftoption.h, include/freetype/config/ftoption.h
(TT_CONFIG_OPTION_SUBPIXEL_HINTING): Assign values to differentiate
between subpixel versions.
(TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY,
TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL): New macros.
* include/freetype/ftttdrv.h (TT_INTERPRETER_VERSION_40): New macro.
* include/freetype/internal/tttypes.h (TT_FaceRec): Updated.
* src/truetype/ttinterp.h (TT_ExecContextRec): Define new fields
`subpixel_hinting_lean', `vertical_lcd_lean',
`backwards_compatibility', `iupx_called', iupy_called', and
`grayscale_cleartype' for new hinting mode.
* src/truetype/ttdriver.c (tt_property_set): Handle v38 and v40
interpreters conditionally.
* src/truetype/ttgload.c (TT_Hint_Glyph): Save phantom points unless
in v38 backwards compatibility mode.
Updated.
(compute_glyph_metrics): Add v38 backwards compatibility mode
constraint for adjusting advance widths.
Updated.
(tt_loader_init): Handle new flags `subpixel_hinting_lean',
`grayscale_cleartype', and `vertical_lcd_lean'.
Updated.
(tt_get_metrics, TT_Process_Simple_Glyph, TT_LOADER_SET_PP):
Updated.
* src/truetype/ttobjs.c (tt_driver_init): Conditionally set
default interpreter version number.
* src/truetype/ttsubpix.c, src/truetype/ttsubpix.h: Updated.
2016-05-17 Werner Lemberg <wl@gnu.org>
[cff] Fix matrix scaling (#47848).

View File

@ -586,23 +586,53 @@ 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. */
/* subpixel hinting support into the TrueType driver. This modifies the */
/* 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: */
/* In particular, 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 `ttinterp.h' */
/* for more details on the LEAN option. */
/* */
/* http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
/* There are three options. */
/* */
/* By undefining this, you only compile the code necessary to hint */
/* TrueType glyphs with native TT hinting. */
/* 1. This option is 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. */
/* */
/* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */
/* defined. */
/* 2. 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, or */
/* 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. */
/* */
#define TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* 3. Compile both. */
/* */
/* 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 subpixel hinting options, 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 1 */
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 */
#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 | 2
/*************************************************************************/
@ -811,6 +841,14 @@ FT_BEGIN_HEADER
*/
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
#define TT_USE_BYTECODE_INTERPRETER
#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1
#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
#endif
#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2
#define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
#endif
#endif

View File

@ -586,23 +586,53 @@ 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. */
/* subpixel hinting support into the TrueType driver. This modifies the */
/* 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: */
/* In particular, 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 `ttinterp.h' */
/* for more details on the LEAN option. */
/* */
/* http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
/* There are three options. */
/* */
/* By undefining this, you only compile the code necessary to hint */
/* TrueType glyphs with native TT hinting. */
/* 1. This option is 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. */
/* */
/* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */
/* defined. */
/* 2. 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, or */
/* 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. */
/* */
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
/* 3. Compile both. */
/* */
/* 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 subpixel hinting options, 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 1 */
#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 | 2 */
/*************************************************************************/
@ -811,6 +841,14 @@ FT_BEGIN_HEADER
*/
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
#define TT_USE_BYTECODE_INTERPRETER
#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1
#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
#endif
#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2
#define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
#endif
#endif

View File

@ -110,7 +110,7 @@ FT_BEGIN_HEADER
* to minimize distortion.
*
* @order:
* hinting-engine
* hinting-engine[cff]
* no-stem-darkening[cff]
* darkening-parameters[cff]
*
@ -120,7 +120,7 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @property:
* hinting-engine
* hinting-engine[cff]
*
* @description:
* Thanks to Adobe, which contributed a new hinting (and parsing)
@ -157,8 +157,8 @@ FT_BEGIN_HEADER
* FT_CFF_HINTING_XXX
*
* @description:
* A list of constants used for the @hinting-engine property to select
* the hinting engine for CFF fonts.
* A list of constants used for the @hinting-engine[cff] property to
* select the hinting engine for CFF fonts.
*
* @values:
* FT_CFF_HINTING_FREETYPE ::

View File

@ -138,31 +138,37 @@ FT_BEGIN_HEADER
* interpreter-version
*
* @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
* support otherwise (since it isn't available then).
* Currently, three versions are available, two representing the
* bytecode interpreter with subpixel hinting support (old `Infinality'
* code and new stripped-down and higher performance `minimal' code) and
* one without, respectively. The default is subpixel support if
* TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support
* otherwise (since it isn't available then).
*
* If subpixel hinting is on, many TrueType bytecode instructions behave
* differently compared to B/W or grayscale rendering (except if `native
* ClearType' is selected by the font). The main idea is to render at a
* 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.
* ClearType' is selected by the font). Microsoft's main idea is to
* render at a 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) tweaks in Microsoft's interpreter.
*
* Details on subpixel hinting and some of the necessary tweaks can be
* found in Greg Hitchcock's whitepaper at
* `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
* `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
* Note that FreeType currently doesn't really `subpixel hint' (6x1, 6x2,
* or 6x5 supersampling) like discussed in the paper. Depending on the
* chosen interpreter, it simply ignores instructions on vertical stems
* to arrive at very similar results.
*
* The following example code demonstrates how to activate subpixel
* The following example code demonstrates how to deactivate subpixel
* hinting (omitting the error handling).
*
* {
* FT_Library library;
* FT_Face face;
* FT_UInt interpreter_version = TT_INTERPRETER_VERSION_38;
* FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
*
*
* FT_Init_FreeType( &library );
@ -197,9 +203,19 @@ FT_BEGIN_HEADER
*
* TT_INTERPRETER_VERSION_38 ::
* Version~38 corresponds to MS rasterizer v.1.9; it is roughly
* equivalent to the hinting provided by DirectWrite ClearType (as
* can be found, for example, in the Internet Explorer~9 running on
* Windows~7).
* equivalent to the hinting provided by DirectWrite ClearType (as can
* be found, for example, in the Internet Explorer~9 running on
* Windows~7). It is used in FreeType to select the `Infinality'
* subpixel hinting code. The code may be removed in a future
* version.
*
* TT_INTERPRETER_VERSION_40 ::
* Version~40 corresponds to MS rasterizer v.2.1; it is roughly
* equivalent to the hinting provided by DirectWrite ClearType (as can
* be found, for example, in Microsoft's Edge Browser on Windows~10).
* It is used in FreeType to select the `minimal' subpixel hinting
* code, a stripped-down and higher performance version of the
* `Infinality' code.
*
* @note:
* This property controls the behaviour of the bytecode interpreter
@ -207,9 +223,9 @@ FT_BEGIN_HEADER
* get rasterized! In particular, it does not control subpixel color
* filtering.
*
* If FreeType has not been compiled with configuration option
* FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 causes an
* `FT_Err_Unimplemented_Feature' error.
* If FreeType has not been compiled with the configuration option
* FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes
* an `FT_Err_Unimplemented_Feature' error.
*
* Depending on the graphics framework, Microsoft uses different
* bytecode and rendering engines. As a consequence, the version
@ -290,13 +306,14 @@ FT_BEGIN_HEADER
* the version~1 gasp table exclusively (like Color ClearType), while
* v1.6 only respects the values of version~0 (bits 0 and~1).
*
* FreeType doesn't provide all capabilities of the most recent
* ClearType incarnation, thus we identify our subpixel support as
* version~38.
* Keep in mind that the features of the above interpreter versions
* might not map exactly to FreeType features or behavior because it is
* a fundamentally different library with different internals.
*
*/
#define TT_INTERPRETER_VERSION_35 35
#define TT_INTERPRETER_VERSION_38 38
#define TT_INTERPRETER_VERSION_40 40
/* */

View File

@ -1386,12 +1386,12 @@ FT_BEGIN_HEADER
FT_ULong horz_metrics_offset;
FT_ULong vert_metrics_offset;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/* since 2.4.12 */
FT_ULong sph_found_func_flags; /* special functions found */
/* for this face */
FT_Bool sph_compatibility_mode;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
} TT_FaceRec;

View File

@ -73,8 +73,11 @@
if ( *interpreter_version == TT_INTERPRETER_VERSION_35
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|| *interpreter_version == TT_INTERPRETER_VERSION_38
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|| *interpreter_version == TT_INTERPRETER_VERSION_40
#endif
)
driver->interpreter_version = *interpreter_version;

View File

@ -122,7 +122,7 @@
FT_UInt glyph_index )
{
TT_Face face = loader->face;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@ -153,7 +153,7 @@
loader->top_bearing = top_bearing;
loader->vadvance = advance_height;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
loader->exec )
{
@ -165,7 +165,7 @@
/* backwards compatibility mode on and off. */
sph_set_tweaks( loader, glyph_index );
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
if ( !loader->linear_def )
{
@ -733,7 +733,8 @@
TT_Hint_Glyph( TT_Loader loader,
FT_Bool is_composite )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@ -816,13 +817,23 @@
#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];
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
/* Save possibly modified glyph phantom points unless in v40 backwards */
/* compatibility mode, where no movement on the x axis means no reason */
/* to change bearings or advance widths. */
if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
!loader->exec->backwards_compatibility ) )
{
#endif
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_SUPPORT_SUBPIXEL_HINTING_MINIMAL
}
#endif
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
@ -831,7 +842,7 @@
else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
return FT_Err_Ok;
}
@ -897,7 +908,7 @@
}
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
@ -916,7 +927,7 @@
FT_Bool do_scale = FALSE;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@ -947,7 +958,7 @@
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
{
/* scale the glyph */
@ -1078,7 +1089,7 @@
: -subglyph->transform.yx;
int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
: -subglyph->transform.xy;
int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
: -subglyph->transform.yy;
int m = a > b ? a : b;
int n = c > d ? c : d;
@ -1324,7 +1335,8 @@
* (3) for everything else.
*
*/
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* XXX merge infinality + lean datafields? */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
#define TT_LOADER_SET_PP( loader ) \
do \
@ -1350,7 +1362,7 @@
(loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
} while ( 0 )
#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#define TT_LOADER_SET_PP( loader ) \
do \
@ -1366,7 +1378,7 @@
(loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
} while ( 0 )
#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
/* a utility function to retrieve i-th node from given FT_List */
@ -1978,7 +1990,8 @@
FT_UInt glyph_index )
{
TT_Face face = loader->face;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@ -2005,11 +2018,18 @@
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 ) &&
!( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
/* Adjust advance width to the value contained in the hdmx table */
/* unless FT_LOAD_COMPUTE_METRICS is set or backwards compatibility */
/* mode of the v40 interpreter is active. See `ttinterp.h' for */
/* details on backwards compatibility mode. */
if (
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
!( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
( loader->exec && loader->exec->backwards_compatibility ) ) &&
#endif
!face->postscript.isFixedPitch &&
IS_HINTED( loader->load_flags ) &&
!( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
{
FT_Byte* widthp;
@ -2018,7 +2038,7 @@
size->root.metrics.x_ppem,
glyph_index );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@ -2036,7 +2056,7 @@
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
{
if ( widthp )
@ -2225,6 +2245,10 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
#endif
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
#endif
face = (TT_Face)glyph->face;
@ -2238,11 +2262,13 @@
if ( IS_HINTED( load_flags ) && !glyf_table_only )
{
TT_ExecContext exec;
FT_Bool grayscale;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
FT_Bool grayscale = TRUE;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
FT_Bool subpixel_hinting_lean;
FT_Bool grayscale_cleartype;
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
FT_Bool subpixel_hinting = FALSE;
#if 0
@ -2254,7 +2280,7 @@
FT_Bool subpixel_positioned;
FT_Bool gray_cleartype;
#endif
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
FT_Bool reexecute = FALSE;
@ -2275,7 +2301,26 @@
if ( !exec )
return FT_THROW( Could_Not_Find_Context );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
{
subpixel_hinting_lean = TRUE;
grayscale_cleartype = !FT_BOOL( load_flags &
FT_LOAD_TARGET_LCD ||
load_flags &
FT_LOAD_TARGET_LCD_V );
exec->vertical_lcd_lean = FT_BOOL( load_flags &
FT_LOAD_TARGET_LCD_V );
}
else
{
subpixel_hinting_lean = FALSE;
grayscale_cleartype = FALSE;
exec->vertical_lcd_lean = FALSE;
}
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@ -2332,18 +2377,23 @@
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
grayscale = FT_BOOL( !subpixel_hinting_lean &&
FT_LOAD_TARGET_MODE( load_flags ) !=
FT_RENDER_MODE_MONO );
else
#endif
grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
FT_RENDER_MODE_MONO );
}
FT_RENDER_MODE_MONO );
error = TT_Load_Context( exec, face, size );
if ( error )
return error;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@ -2371,9 +2421,37 @@
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
{
/* 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_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" ));
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 )
@ -2406,10 +2484,11 @@
if ( exec->GS.instruct_control & 2 )
exec->GS = tt_default_graphics_state;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/* 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->interpreter_version == TT_INTERPRETER_VERSION_38 &&
exec->GS.instruct_control & 4 )
exec->ignore_x_mode = 0;
#endif

View File

@ -99,7 +99,7 @@ FT_BEGIN_HEADER
} TT_CallRec, *TT_CallStack;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/*************************************************************************/
/* */
@ -138,7 +138,7 @@ FT_BEGIN_HEADER
} SPH_Font_Class;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
/*************************************************************************/
@ -247,9 +247,135 @@ 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 */
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
/*
* 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).
*
* The minimal subpixel hinting code (interpreter version 40) employs a
* small list of font-agnostic hacks to bludgeon non-native-ClearType
* fonts (except tricky ones[1]) into submission. It 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 is 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 instructions
* on the x axis, which gives the same result in the majority of
* cases.
*
* - Points are not moved post-IUP (neither on the x nor on the y axis),
* 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 don't execute unless moving a composite on the
* y axis or moving a previously y touched point. SHPIX additionally
* denies movement on the x axis (cf. `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!), cf. `compute_glyph_metrics' and
* `TT_Hint_Glyph'. Letting non-native-ClearType fonts modify spacing
* might mess up spacing.
*
* Minor hacks
*
* - FLIPRGON, FLIPRGOFF, and FLIPPT don't execute post-IUP. This
* prevents dents in e.g. Arial-Regular's `D' and `G' glyphs at
* various sizes.
*
* (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-displays,
* the worse the results.
*
* Microsoft defines a way to turn off backwards compatibility and
* interpret instructions as before (called `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 v40
* interpreter assumes backwards compatibility by default, which can be
* turned off the same way by executing the following in the control
* program (cf. `Ins_INSTCTRL').
*
* #PUSH 4,3
* 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 (v40 with
* backwards compatibility turned off). Cf. `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.
*
*/
/* Using v40 implies subpixel hinting. Used to detect interpreter */
/* version switches. `_lean' to differentiate from the Infinality */
/* `subpixel_hinting', which 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', which */
/* is managed differently. */
FT_Bool vertical_lcd_lean;
/* Default to backwards compatibility mode in v40 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;
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
TT_Round_Func func_round_sphn; /* subpixel rounding function */
FT_Bool subpixel_hinting; /* Using subpixel hinting? */
@ -279,7 +405,7 @@ FT_BEGIN_HEADER
FT_ULong sph_in_func_flags; /* flags to indicate if in */
/* special functions */
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
} TT_ExecContextRec;

View File

@ -1287,10 +1287,12 @@
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;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
driver->interpreter_version = TT_INTERPRETER_VERSION_38;
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
driver->interpreter_version = TT_INTERPRETER_VERSION_40;
#endif
#else /* !TT_USE_BYTECODE_INTERPRETER */

View File

@ -27,7 +27,7 @@
#include "ttsubpix.h"
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/*************************************************************************/
/* */
@ -1000,12 +1000,12 @@
}
}
#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
/* ANSI C doesn't like empty source files */
typedef int _tt_subpix_dummy;
#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
/* END */

View File

@ -27,7 +27,7 @@
FT_BEGIN_HEADER
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/*************************************************************************/
/* */
@ -100,7 +100,7 @@ FT_BEGIN_HEADER
#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE
#define SPH_OPTION_SET_RASTERIZER_VERSION 38
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
FT_END_HEADER