ref: f04951af8dd16495ebe5bd45a3e33ad30f511553
parent: 6650be7c43c9f7299a0bfbd5d81b481efbe9d95b
author: Werner Lemberg <[email protected]>
date: Fri May 17 09:51:07 EDT 2013
[truetype] Add `interpreter-version' property. This makes the option TT_CONFIG_OPTION_SUBPIXEL_HINTING controllable at runtime. * src/truetype/ttdriver.c: Include FT_TRUETYPE_DRIVER_H. (tt_property_set, tt_property_get): Fill templates. * src/truetype/ttobjs.h (TT_DriverRec): Add `interpreter_version' member. Remove unused `extension_component' member. * src/truetype/ttgload.c: Include FT_TRUETYPE_DRIVER_H. (tt_get_metrics, TT_Hint_Glyph, TT_Process_Simple_Glyph, compute_glyph_metrics, tt_loader_init): Use `interpreter_version'. * src/truetype/ttinterp.c: Include FT_TRUETYPE_DRIVER_H. (SUBPIXEL_HINTING): New macro to check `interpreter_version' flag. Update all affected functions to use it. Use TT_INTERPRETER_VERSION_XXX where appropriate. * src/truetype/ttobjs.c: Include FT_TRUETYPE_DRIVER_H. (tt_driver_init): Initialize `interpreter_version'. * src/truetype/ttsubpix.c: Include FT_TRUETYPE_DRIVER_H. Use TT_INTERPRETER_VERSION_XXX where appropriate.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2013-05-15 Werner Lemberg <[email protected]>
+
+ [truetype] Add `interpreter-version' property.
+
+ This makes the option TT_CONFIG_OPTION_SUBPIXEL_HINTING controllable
+ at runtime.
+
+ * src/truetype/ttdriver.c: Include FT_TRUETYPE_DRIVER_H.
+ (tt_property_set, tt_property_get): Fill templates.
+
+ * src/truetype/ttobjs.h (TT_DriverRec): Add `interpreter_version'
+ member.
+ Remove unused `extension_component' member.
+
+ * src/truetype/ttgload.c: Include FT_TRUETYPE_DRIVER_H.
+ (tt_get_metrics, TT_Hint_Glyph, TT_Process_Simple_Glyph,
+ compute_glyph_metrics, tt_loader_init): Use `interpreter_version'.
+
+ * src/truetype/ttinterp.c: Include FT_TRUETYPE_DRIVER_H.
+ (SUBPIXEL_HINTING): New macro to check `interpreter_version' flag.
+ Update all affected functions to use it.
+ Use TT_INTERPRETER_VERSION_XXX where appropriate.
+
+ * src/truetype/ttobjs.c: Include FT_TRUETYPE_DRIVER_H.
+ (tt_driver_init): Initialize `interpreter_version'.
+
+ * src/truetype/ttsubpix.c: Include FT_TRUETYPE_DRIVER_H.
+ Use TT_INTERPRETER_VERSION_XXX where appropriate.
+
2013-05-13 Werner Lemberg <[email protected]>
[truetype] Avoid empty source file.
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -344,6 +344,19 @@
/*************************************************************************
*
* @macro:
+ * FT_TRUETYPE_DRIVER_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing
+ * structures and macros related to the TrueType driver module.
+ *
+ */
+#define FT_TRUETYPE_DRIVER_H <freetype/ftttdrv.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
* FT_TYPE1_TABLES_H
*
* @description:
--- a/include/freetype/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -67,27 +67,15 @@
/***************************************************************************/
/* */
/* <Chapter> */
-/* auto_hinter */
+/* module_specific */
/* */
/* <Title> */
-/* The Auto-Hinter */
+/* Controlling FreeType Modules */
/* */
/* <Sections> */
/* auto_hinter */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
/* cff_driver */
-/* */
-/* <Title> */
-/* The CFF Driver */
-/* */
-/* <Sections> */
-/* cff_driver */
+/* tt_driver */
/* */
/***************************************************************************/
--- /dev/null
+++ b/include/freetype/ftttdrv.h
@@ -1,0 +1,150 @@
+/***************************************************************************/
+/* */
+/* ftttdrv.h */
+/* */
+/* FreeType API for controlling the TrueType driver */
+/* (specification only). */
+/* */
+/* Copyright 2013 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTTTDRV_H__
+#define __FTTTDRV_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * tt_driver
+ *
+ * @title:
+ * The TrueType driver
+ *
+ * @abstract:
+ * Controlling the TrueType driver module.
+ *
+ * @description:
+ * While FreeType's TrueType driver doesn't expose API functions by
+ * itself, it is possible to control its behaviour with @FT_Property_Set
+ * and @FT_Property_Get. The following lists the available properties
+ * together with the necessary macros and structures.
+ *
+ * The TrueType driver's module name is `truetype'.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * interpreter-version
+ *
+ * @description:
+ * Currently, two versions are available which represent 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).
+ *
+ * If subpixel hinting is on, many TrueType bytecode instructions
+ * behave differently compared to B/W or grayscale rendering. 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.
+ *
+ * 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'.
+ *
+ * The following example code demonstrates how to activate subpixel
+ * hinting (omitting the error handling).
+ *
+ * {
+ * FT_Library library;
+ * FT_Face face;
+ * FT_UInt interpreter_version = TT_INTERPRETER_VERSION_38;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "truetype",
+ * "interpreter-version",
+ * &interpreter_version );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_INTERPRETER_VERSION_XXX
+ *
+ * @description:
+ * A list of constants used for the @interpreter-version property to
+ * select the hinting engine for Truetype fonts.
+ *
+ * The numeric value in the constant names represents the version
+ * number as returned by the `GETINFO' bytecode instruction.
+ *
+ * @values:
+ * TT_INTERPRETER_VERSION_35 ::
+ * Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in
+ * Windows~98; only grayscale and B/W rasterizing is supported.
+ *
+ * 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).
+ *
+ * @note:
+ * This property controls the behaviour of the bytecode interpreter
+ * and thus how outlines get hinted. It does *not* control how glyph
+ * 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.
+ *
+ */
+#define TT_INTERPRETER_VERSION_35 35
+#define TT_INTERPRETER_VERSION_38 38
+
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTTTDRV_H__ */
+
+
+/* END */
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -30,6 +30,7 @@
#include FT_SERVICE_TRUETYPE_ENGINE_H
#include FT_SERVICE_TRUETYPE_GLYF_H
#include FT_SERVICE_PROPERTIES_H
+#include FT_TRUETYPE_DRIVER_H
#include "ttdriver.h"
#include "ttgload.h"
@@ -66,7 +67,24 @@
TT_Driver driver = (TT_Driver)module;
- return error;
+ if ( !ft_strcmp( property_name, "interpreter-version" ) )
+ {
+ FT_UInt* interpreter_version = (FT_UInt*)value;
+
+
+#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ if ( *interpreter_version != TT_INTERPRETER_VERSION_35 )
+ error = FT_ERR( Unimplemented_Feature );
+ else
+#endif
+ driver->interpreter_version = *interpreter_version;
+
+ return error;
+ }
+
+ FT_TRACE0(( "tt_property_set: missing property `%s'\n",
+ property_name ));
+ return FT_THROW( Missing_Property );
}
@@ -78,8 +96,22 @@
FT_Error error = FT_Err_Ok;
TT_Driver driver = (TT_Driver)module;
+ FT_UInt interpreter_version = driver->interpreter_version;
- return error;
+
+ if ( !ft_strcmp( property_name, "interpreter-version" ) )
+ {
+ FT_UInt* val = (FT_UInt*)value;
+
+
+ *val = interpreter_version;
+
+ return error;
+ }
+
+ FT_TRACE0(( "tt_property_get: missing property `%s'\n",
+ property_name ));
+ return FT_THROW( Missing_Property );
}
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -23,6 +23,7 @@
#include FT_INTERNAL_SFNT_H
#include FT_TRUETYPE_TAGS_H
#include FT_OUTLINE_H
+#include FT_TRUETYPE_DRIVER_H
#include "ttgload.h"
#include "ttpload.h"
@@ -132,7 +133,10 @@
tt_get_metrics( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = (TT_Face)loader->face;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+#endif
FT_Short left_bearing = 0, top_bearing = 0;
FT_UShort advance_width = 0, advance_height = 0;
@@ -151,12 +155,15 @@
loader->vadvance = advance_height;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( loader->exec )
- loader->exec->sph_tweak_flags = 0;
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ {
+ if ( loader->exec )
+ loader->exec->sph_tweak_flags = 0;
- /* this may not be the right place for this, but it works */
- if ( loader->exec && loader->exec->ignore_x_mode )
- sph_set_tweaks( loader, glyph_index );
+ /* this may not be the right place for this, but it works */
+ if ( loader->exec && loader->exec->ignore_x_mode )
+ sph_set_tweaks( loader, glyph_index );
+ }
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
if ( !loader->linear_def )
@@ -720,6 +727,11 @@
TT_Hint_Glyph( TT_Loader loader,
FT_Bool is_composite )
{
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Face face = (TT_Face)loader->face;
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+#endif
+
TT_GlyphZone zone = &loader->zone;
FT_Pos origin;
@@ -820,12 +832,16 @@
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
- FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
+ if ( 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 );
- else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
- FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
-#endif
+ 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 */
+
return FT_Err_Ok;
}
@@ -848,15 +864,7 @@
FT_Outline* outline;
FT_Int n_points;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Face face = (TT_Face)loader->face;
- FT_String* family = face->root.family_name;
- FT_Int ppem = loader->size->metrics.x_ppem;
- FT_String* style = face->root.style_name;
- FT_Int x_scale_factor = 1000;
-#endif
-
outline = &gloader->current.outline;
n_points = outline->n_points;
@@ -910,54 +918,83 @@
loader->zone.n_points + 4 );
}
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- /* scale, but only if enabled and only if TT hinting is being used */
- if ( IS_HINTED( loader->load_flags ) )
- x_scale_factor = sph_test_tweak_x_scaling( face,
- family,
- ppem,
- style,
- loader->glyph_index );
- /* scale the glyph */
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
- x_scale_factor != 1000 )
{
- FT_Vector* vec = outline->points;
- FT_Vector* limit = outline->points + n_points;
- FT_Fixed x_scale = FT_MulDiv(
- ((TT_Size)loader->size)->metrics.x_scale,
- x_scale_factor, 1000 );
- FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Face face = (TT_Face)loader->face;
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+ FT_String* family = face->root.family_name;
+ FT_Int ppem = loader->size->metrics.x_ppem;
+ FT_String* style = face->root.style_name;
+ FT_Int x_scale_factor = 1000;
+#endif
- /* compensate for any scaling by de/emboldening; */
- /* the amount was determined via experimentation */
- if ( x_scale_factor != 1000 && ppem > 11 )
- FT_Outline_EmboldenXY( outline,
- FT_MulFix( 1280 * ppem,
- 1000 - x_scale_factor ),
- 0 );
-#else
- /* scale the glyph */
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- {
- FT_Vector* vec = outline->points;
- FT_Vector* limit = outline->points + n_points;
- FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = outline->points + n_points;
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
- for ( ; vec < limit; vec++ )
+ FT_Bool do_scale = FALSE;
+
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
- vec->x = FT_MulFix( vec->x, x_scale );
- vec->y = FT_MulFix( vec->y, y_scale );
+ /* scale, but only if enabled and only if TT hinting is being used */
+ if ( IS_HINTED( loader->load_flags ) )
+ x_scale_factor = sph_test_tweak_x_scaling( face,
+ family,
+ ppem,
+ style,
+ loader->glyph_index );
+ /* scale the glyph */
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
+ x_scale_factor != 1000 )
+ {
+ x_scale = FT_MulDiv( ((TT_Size)loader->size)->metrics.x_scale,
+ x_scale_factor, 1000 );
+ y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+
+ /* compensate for any scaling by de/emboldening; */
+ /* the amount was determined via experimentation */
+ if ( x_scale_factor != 1000 && ppem > 11 )
+ FT_Outline_EmboldenXY( outline,
+ FT_MulFix( 1280 * ppem,
+ 1000 - x_scale_factor ),
+ 0 );
+ do_scale = TRUE;
+ }
}
+ else
- loader->pp1 = outline->points[n_points - 4];
- loader->pp2 = outline->points[n_points - 3];
- loader->pp3 = outline->points[n_points - 2];
- loader->pp4 = outline->points[n_points - 1];
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+ {
+ /* scale the glyph */
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ x_scale = ((TT_Size)loader->size)->metrics.x_scale;
+ y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+
+ do_scale = TRUE;
+ }
+ }
+
+ if ( do_scale )
+ {
+ for ( ; vec < limit; vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ loader->pp1 = outline->points[n_points - 4];
+ loader->pp2 = outline->points[n_points - 3];
+ loader->pp3 = outline->points[n_points - 2];
+ loader->pp4 = outline->points[n_points - 1];
+ }
}
if ( IS_HINTED( loader->load_flags ) )
@@ -1662,11 +1699,15 @@
compute_glyph_metrics( TT_Loader loader,
FT_UInt glyph_index )
{
+ TT_Face face = (TT_Face)loader->face;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+#endif
+
FT_BBox bbox;
- TT_Face face = (TT_Face)loader->face;
FT_Fixed y_scale;
TT_GlyphSlot glyph = loader->glyph;
- TT_Size size = (TT_Size)loader->size;
+ TT_Size size = (TT_Size)loader->size;
y_scale = 0x10000L;
@@ -1692,27 +1733,35 @@
{
FT_Byte* widthp;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- FT_Bool ignore_x_mode;
-
- ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
- FT_RENDER_MODE_MONO );
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
widthp = tt_face_get_device_metrics( face,
size->root.metrics.x_ppem,
glyph_index );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( widthp &&
- ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
- !ignore_x_mode ||
- SPH_OPTION_BITMAP_WIDTHS ) )
-#else
- if ( widthp )
+
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ {
+ FT_Bool ignore_x_mode;
+
+
+ ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
+ FT_RENDER_MODE_MONO );
+
+ if ( widthp &&
+ ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
+ !ignore_x_mode ||
+ SPH_OPTION_BITMAP_WIDTHS ) )
+ glyph->metrics.horiAdvance = *widthp << 6;
+ }
+ else
+
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- glyph->metrics.horiAdvance = *widthp << 6;
+
+ {
+ if ( widthp )
+ glyph->metrics.horiAdvance = *widthp << 6;
+ }
}
/* set glyph dimensions */
@@ -1908,18 +1957,25 @@
{
TT_ExecContext exec;
FT_Bool grayscale;
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- FT_Bool subpixel_hinting;
- FT_Bool grayscale_hinting;
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+
+ FT_Bool subpixel_hinting = FALSE;
+ FT_Bool grayscale_hinting = TRUE;
+
#if 0
- FT_Bool compatible_widths;
- FT_Bool symmetrical_smoothing;
- FT_Bool bgr;
- FT_Bool subpixel_positioned;
+ /* not used yet */
+ FT_Bool compatible_widths;
+ FT_Bool symmetrical_smoothing;
+ FT_Bool bgr;
+ FT_Bool subpixel_positioned;
#endif
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ FT_Bool reexecute = FALSE;
+
if ( !size->cvt_ready )
{
FT_Error error = tt_size_ready_bytecode( size, pedantic );
@@ -1937,113 +1993,114 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags )
- != FT_RENDER_MODE_MONO ) &&
- SPH_OPTION_SET_SUBPIXEL );
-
- if ( subpixel_hinting )
- grayscale = grayscale_hinting = FALSE;
- else if ( SPH_OPTION_SET_GRAYSCALE )
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
- grayscale = grayscale_hinting = TRUE;
- subpixel_hinting = FALSE;
- }
- else
- grayscale = grayscale_hinting = FALSE;
+ subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags )
+ != FT_RENDER_MODE_MONO ) &&
+ SPH_OPTION_SET_SUBPIXEL );
- if ( FT_IS_TRICKY( glyph->face ) )
- subpixel_hinting = grayscale_hinting = FALSE;
+ if ( subpixel_hinting )
+ grayscale = grayscale_hinting = FALSE;
+ else if ( SPH_OPTION_SET_GRAYSCALE )
+ {
+ grayscale = grayscale_hinting = TRUE;
+ subpixel_hinting = FALSE;
+ }
+ else
+ grayscale = grayscale_hinting = FALSE;
- exec->ignore_x_mode = subpixel_hinting || grayscale_hinting;
- exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
- if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
- exec->rasterizer_version = 35;
+ if ( FT_IS_TRICKY( glyph->face ) )
+ subpixel_hinting = grayscale_hinting = FALSE;
+ exec->ignore_x_mode = subpixel_hinting || grayscale_hinting;
+ exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
+ if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
+ exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
+
#if 1
- exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
- exec->symmetrical_smoothing = FALSE;
- exec->bgr = FALSE;
- exec->subpixel_positioned = TRUE;
+ exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
+ exec->symmetrical_smoothing = FALSE;
+ exec->bgr = FALSE;
+ exec->subpixel_positioned = TRUE;
#else /* 0 */
- exec->compatible_widths =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_COMPATIBLE_WIDTHS );
- exec->symmetrical_smoothing =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_SYMMETRICAL_SMOOTHING );
- exec->bgr =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_BGR );
- exec->subpixel_positioned =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_SUBPIXEL_POSITIONED );
+ exec->compatible_widths =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ TT_LOAD_COMPATIBLE_WIDTHS );
+ exec->symmetrical_smoothing =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ TT_LOAD_SYMMETRICAL_SMOOTHING );
+ exec->bgr =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ TT_LOAD_BGR );
+ exec->subpixel_positioned =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ TT_LOAD_SUBPIXEL_POSITIONED );
#endif /* 0 */
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ }
+ else
- grayscale =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ {
+ grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ FT_RENDER_MODE_MONO );
+ }
TT_Load_Context( exec, face, size );
#ifdef 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 )
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
- FT_UInt i;
+ /* 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;
+ }
- FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
- " re-executing `prep' table\n" ));
+ /* a change from mono to grayscale rendering (and vice versa) */
+ /* requires a re-execution of the CVT program */
+ if ( grayscale != exec->grayscale_hinting )
+ {
+ FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
+ " re-executing `prep' table\n" ));
- exec->subpixel_hinting = subpixel_hinting;
-
- for ( i = 0; i < size->cvt_size; i++ )
- size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
- tt_size_run_prep( size, pedantic );
+ exec->grayscale_hinting = grayscale_hinting;
+ reexecute = TRUE;
+ }
}
+ else
- /* a change from mono to grayscale rendering (and vice versa) */
- /* requires a re-execution of the CVT program */
- if ( grayscale != exec->grayscale_hinting )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
{
- FT_UInt i;
+ /* a change from mono to grayscale rendering (and vice versa) */
+ /* requires a re-execution of the CVT program */
+ if ( grayscale != exec->grayscale )
+ {
+ FT_TRACE4(( "tt_loader_init: grayscale change,"
+ " re-executing `prep' table\n" ));
-
- FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
- " re-executing `prep' table\n" ));
-
- exec->grayscale_hinting = grayscale_hinting;
-
- for ( i = 0; i < size->cvt_size; i++ )
- size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
- tt_size_run_prep( size, pedantic );
+ exec->grayscale = grayscale;
+ reexecute = TRUE;
+ }
}
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
- /* a change from mono to grayscale rendering (and vice versa) */
- /* requires a re-execution of the CVT program */
- if ( grayscale != exec->grayscale )
+ if ( reexecute )
{
FT_UInt i;
- FT_TRACE4(( "tt_loader_init: grayscale change,"
- " re-executing `prep' table\n" ));
-
- exec->grayscale = grayscale;
-
for ( i = 0; i < size->cvt_size; i++ )
size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
tt_size_run_prep( size, pedantic );
}
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
/* see whether the cvt program has disabled hinting */
if ( exec->GS.instruct_control & 1 )
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -25,6 +25,7 @@
#include FT_INTERNAL_CALC_H
#include FT_TRIGONOMETRY_H
#include FT_SYSTEM_H
+#include FT_TRUETYPE_DRIVER_H
#include "ttinterp.h"
#include "tterrors.h"
@@ -131,6 +132,11 @@
#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
+#define SUBPIXEL_HINTING \
+ ( ((TT_Driver)FT_FACE_DRIVER( CUR.face ))->interpreter_version == \
+ TT_INTERPRETER_VERSION_38 )
+
+
/*************************************************************************/
/* */
/* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
@@ -1764,10 +1770,11 @@
if ( v != 0 )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !CUR.ignore_x_mode ||
- ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) )
+ if ( !SUBPIXEL_HINTING ||
+ ( !CUR.ignore_x_mode ||
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
+ zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1842,10 +1849,12 @@
FT_UNUSED_EXEC;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !CUR.ignore_x_mode ||
- ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVEX ) )
+ if ( !SUBPIXEL_HINTING ||
+ ( !CUR.ignore_x_mode ||
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVEX ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- zone->cur[point].x += distance;
+ zone->cur[point].x += distance;
+
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -3165,7 +3174,8 @@
/* subpixel hinting - avoid Typeman Dstroke and */ \
/* IStroke and Vacuform rounds */ \
\
- if ( CUR.ignore_x_mode && \
+ if ( SUBPIXEL_HINTING && \
+ CUR.ignore_x_mode && \
( ( I == 24 && \
( CUR.face->sph_found_func_flags & \
( SPH_FDEF_SPACING_1 | \
@@ -4604,100 +4614,104 @@
while ( SKIP_Code() == SUCCESS )
{
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- for ( i = 0; i < opcode_patterns; i++ )
+ if ( SUBPIXEL_HINTING )
{
- if ( opcode_pointer[i] < opcode_size[i] &&
- CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+ for ( i = 0; i < opcode_patterns; i++ )
{
- opcode_pointer[i] += 1;
-
- if ( opcode_pointer[i] == opcode_size[i] )
+ if ( opcode_pointer[i] < opcode_size[i] &&
+ CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
{
- FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
- i, n,
- CUR.face->root.family_name,
- CUR.face->root.style_name ));
+ opcode_pointer[i] += 1;
- switch ( i )
+ if ( opcode_pointer[i] == opcode_size[i] )
{
- case 0:
- rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
- break;
+ FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
+ i, n,
+ CUR.face->root.family_name,
+ CUR.face->root.style_name ));
- case 1:
- rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2;
- CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
- break;
-
- case 2:
- switch ( n )
+ switch ( i )
{
- /* needs to be implemented still */
- case 58:
- rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE;
- CUR.face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
- }
- break;
-
- case 3:
- switch ( n )
- {
case 0:
- rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
- }
- break;
+ rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1;
+ CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
+ break;
- case 4:
- /* probably not necessary to detect anymore */
- rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
- break;
-
- case 5:
- switch ( n )
- {
- case 0:
case 1:
- case 2:
- case 4:
- case 7:
- case 8:
- rec->sph_fdef_flags |= SPH_FDEF_SPACING_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
- }
- break;
+ rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2;
+ CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
+ break;
- case 6:
- switch ( n )
- {
- case 0:
- case 1:
case 2:
+ switch ( n )
+ {
+ /* needs to be implemented still */
+ case 58:
+ rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE;
+ CUR.face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
+ }
+ break;
+
+ case 3:
+ switch ( n )
+ {
+ case 0:
+ rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1;
+ CUR.face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
+ }
+ break;
+
case 4:
- case 7:
- case 8:
- rec->sph_fdef_flags |= SPH_FDEF_SPACING_2;
- CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
+ /* probably not necessary to detect anymore */
+ rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1;
+ CUR.face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
+ break;
+
+ case 5:
+ switch ( n )
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 7:
+ case 8:
+ rec->sph_fdef_flags |= SPH_FDEF_SPACING_1;
+ CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
+ }
+ break;
+
+ case 6:
+ switch ( n )
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 7:
+ case 8:
+ rec->sph_fdef_flags |= SPH_FDEF_SPACING_2;
+ CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
+ }
+ break;
}
- break;
+ opcode_pointer[i] = 0;
}
- opcode_pointer[i] = 0;
}
+
+ else
+ opcode_pointer[i] = 0;
}
- else
- opcode_pointer[i] = 0;
+ /* Set sph_compatibility_mode only when deltas are detected */
+ CUR.face->sph_compatibility_mode =
+ ( ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
+ ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
}
- /* Set sph_compatibility_mode only when deltas are detected */
- CUR.face->sph_compatibility_mode =
- ( ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
- ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
-
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
switch ( CUR.opcode )
@@ -5282,7 +5296,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
- if ( CUR.ignore_x_mode && FT_ABS( D ) == 64 )
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode && FT_ABS( D ) == 64 )
D += 1;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
@@ -5779,11 +5794,13 @@
if ( CUR.GS.freeVector.x != 0 )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !CUR.ignore_x_mode ||
- ( CUR.ignore_x_mode &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_MOVE_ZP2 ) ) )
+ if ( !SUBPIXEL_HINTING ||
+ ( !CUR.ignore_x_mode ||
+ ( CUR.ignore_x_mode &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_MOVE_ZP2 ) ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
CUR.zp2.cur[point].x += dx;
+
if ( touch )
CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -6022,7 +6039,8 @@
/* - the glyph is specifically set to allow SHPIX moves */
/* - the move is on a previously Y-touched point */
- if ( CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode )
{
/* save point for later comparison */
if ( CUR.GS.freeVector.y != 0 )
@@ -6071,15 +6089,19 @@
( B2 & 63 ) != 0 &&
B1 != B2 ) )
MOVE_Zp2_Point( point, -dx, -dy, TRUE );
- }
+ }
else
MOVE_Zp2_Point( point, dx, dy, TRUE );
}
- Skip:
-#else
+
+ Skip:
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
MOVE_Zp2_Point( point, dx, dy, TRUE );
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
CUR.GS.loop--;
}
@@ -6100,16 +6122,21 @@
{
FT_UShort point;
FT_F26Dot6 distance;
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
FT_F26Dot6 control_value_cutin;
- control_value_cutin = CUR.GS.control_value_cutin;
+ if ( SUBPIXEL_HINTING )
+ {
+ control_value_cutin = CUR.GS.control_value_cutin;
- if ( CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
- control_value_cutin = 0;
+ if ( CUR.ignore_x_mode &&
+ CUR.GS.freeVector.x != 0 &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ control_value_cutin = 0;
+ }
+
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
point = (FT_UShort)args[0];
@@ -6136,7 +6163,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* subpixel hinting - make MSIRP respect CVT cut-in; */
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.x != 0 &&
FT_ABS( distance - args[1] ) >= control_value_cutin )
distance = args[1];
@@ -6179,7 +6207,8 @@
{
cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.x != 0 )
distance = ROUND_None(
cur_dist,
@@ -6221,7 +6250,8 @@
point = (FT_UShort)args[0];
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.x != 0 &&
!( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
control_value_cutin = 0;
@@ -6262,7 +6292,9 @@
#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 ( !CUR.ignore_x_mode || !CUR.face->sph_compatibility_mode )
+ if ( !SUBPIXEL_HINTING ||
+ ( !CUR.ignore_x_mode ||
+ !CUR.face->sph_compatibility_mode ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
CUR.GS.freeVector.x );
@@ -6271,7 +6303,8 @@
CUR.zp0.cur[point] = CUR.zp0.org[point];
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
distance > 0 &&
CUR.GS.freeVector.y != 0 )
@@ -6286,7 +6319,8 @@
distance = org_dist;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.x != 0 )
distance = ROUND_None( distance,
CUR.tt_metrics.compensations[0] );
@@ -6320,13 +6354,13 @@
minimum_distance = CUR.GS.minimum_distance;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.x != 0 &&
!( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
minimum_distance = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
point = (FT_UShort)args[0];
if ( BOUNDS( point, CUR.zp1.n_points ) ||
@@ -6390,7 +6424,9 @@
if ( ( CUR.opcode & 4 ) != 0 )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode && CUR.GS.freeVector.x != 0 )
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
+ CUR.GS.freeVector.x != 0 )
distance = ROUND_None(
org_dist,
CUR.tt_metrics.compensations[CUR.opcode & 3] );
@@ -6468,7 +6504,8 @@
cvtEntry = (FT_ULong)( args[1] + 1 );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.x != 0 &&
!( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
control_value_cutin = minimum_distance = 0;
@@ -6489,10 +6526,12 @@
cvt_dist = 0;
else
cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_MIRP_CVT_ZERO ) )
- cvt_dist = 0;
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_MIRP_CVT_ZERO ) )
+ cvt_dist = 0;
#endif
/* single width test */
@@ -6531,8 +6570,10 @@
if ( ( org_dist ^ cvt_dist ) < 0 )
cvt_dist = -cvt_dist;
}
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.GS.freeVector.y != 0 &&
( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
{
@@ -6542,6 +6583,7 @@
cvt_dist += 32;
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/* control value cut-in and round */
if ( ( CUR.opcode & 4 ) != 0 )
@@ -6572,23 +6614,23 @@
CUR.tt_metrics.compensations[CUR.opcode & 3] );
}
else
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
{
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* do cvt cut-in always in MIRP for sph */
- if ( CUR.ignore_x_mode && CUR.GS.gep0 == CUR.GS.gep1 )
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
+ CUR.GS.gep0 == CUR.GS.gep1 )
{
if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
cvt_dist = org_dist;
}
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
distance = ROUND_None(
cvt_dist,
CUR.tt_metrics.compensations[CUR.opcode & 3] );
}
-#else
- distance = ROUND_None(
- cvt_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
/* minimum distance test */
@@ -6607,52 +6649,58 @@
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- B1 = CUR.zp1.cur[point].y;
+ if ( SUBPIXEL_HINTING )
+ {
+ B1 = CUR.zp1.cur[point].y;
- /* Round moves if necessary */
- if ( CUR.ignore_x_mode &&
- CUR.GS.freeVector.y != 0 &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
- distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
+ /* Round moves if necessary */
+ if ( CUR.ignore_x_mode &&
+ CUR.GS.freeVector.y != 0 &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
+ distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
- if ( CUR.ignore_x_mode &&
- CUR.GS.freeVector.y != 0 &&
- ( CUR.opcode & 16 ) == 0 &&
- ( CUR.opcode & 8 ) == 0 &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
- distance += 64;
+ if ( CUR.ignore_x_mode &&
+ CUR.GS.freeVector.y != 0 &&
+ ( CUR.opcode & 16 ) == 0 &&
+ ( CUR.opcode & 8 ) == 0 &&
+ ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
+ distance += 64;
+ }
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- B2 = CUR.zp1.cur[point].y;
-
- /* Reverse move if necessary */
- if ( CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING )
{
- if ( CUR.face->sph_compatibility_mode &&
- CUR.GS.freeVector.y != 0 &&
- ( B1 & 63 ) == 0 &&
- ( B2 & 63 ) != 0 )
- reverse_move = TRUE;
+ B2 = CUR.zp1.cur[point].y;
- if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
- CUR.GS.freeVector.y != 0 &&
- ( B2 & 63 ) != 0 &&
- ( B1 & 63 ) != 0 )
- reverse_move = TRUE;
+ /* Reverse move if necessary */
+ if ( CUR.ignore_x_mode )
+ {
+ if ( CUR.face->sph_compatibility_mode &&
+ CUR.GS.freeVector.y != 0 &&
+ ( B1 & 63 ) == 0 &&
+ ( B2 & 63 ) != 0 )
+ reverse_move = TRUE;
- if ( ( CUR.sph_tweak_flags &
- SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES ) &&
- !reverse_move &&
- FT_ABS( B1 - B2 ) >= 64 )
- reverse_move = TRUE;
- }
+ if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+ CUR.GS.freeVector.y != 0 &&
+ ( B2 & 63 ) != 0 &&
+ ( B1 & 63 ) != 0 )
+ reverse_move = TRUE;
- if ( reverse_move )
- CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
+ if ( ( CUR.sph_tweak_flags &
+ SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES ) &&
+ !reverse_move &&
+ FT_ABS( B1 - B2 ) >= 64 )
+ reverse_move = TRUE;
+ }
+ if ( reverse_move )
+ CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
+ }
+
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
Fail:
@@ -6681,7 +6729,8 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode &&
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
CUR.iup_called &&
( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
{
@@ -7212,7 +7261,8 @@
point = 0;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode )
{
CUR.iup_called = 1;
if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
@@ -7366,67 +7416,76 @@
B = B * 64 / ( 1L << CUR.GS.delta_shift );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- /*
- * Allow delta move if
- *
- * - not using ignore_x_mode rendering
- * - glyph is specifically set to allow it
- * - glyph is composite and freedom vector is not subpixel vector
- */
- if ( !CUR.ignore_x_mode ||
- ( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
- ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) )
- CUR_Func_move( &CUR.zp0, A, B );
- /* Otherwise apply subpixel hinting and compatibility mode rules */
- else if ( CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING )
{
- if ( CUR.GS.freeVector.y != 0 )
- B1 = CUR.zp0.cur[A].y;
- else
- B1 = CUR.zp0.cur[A].x;
-#if 0
- /* Standard Subpixel Hinting: Allow y move. */
- /* This messes up dejavu and may not be needed... */
- if ( !CUR.face->sph_compatibility_mode &&
- CUR.GS.freeVector.y != 0 )
+ /*
+ * Allow delta move if
+ *
+ * - not using ignore_x_mode rendering
+ * - glyph is specifically set to allow it
+ * - glyph is composite and freedom vector is not subpixel
+ * vector
+ */
+ if ( !CUR.ignore_x_mode ||
+ ( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
+ ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) )
CUR_Func_move( &CUR.zp0, A, B );
- else
-#endif
- /* Compatibility Mode: Allow x or y move if point touched in */
- /* Y direction. */
- if ( CUR.face->sph_compatibility_mode &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
+
+ /* Otherwise apply subpixel hinting and */
+ /* compatibility mode rules */
+ else if ( CUR.ignore_x_mode )
{
- /* save the y value of the point now; compare after move */
- B1 = CUR.zp0.cur[A].y;
+ if ( CUR.GS.freeVector.y != 0 )
+ B1 = CUR.zp0.cur[A].y;
+ else
+ B1 = CUR.zp0.cur[A].x;
- if ( ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
- B = FT_PIX_ROUND( B1 + B ) - B1;
-
- /* Allow delta move if using sph_compatibility_mode, */
- /* IUP has not been called, and point is touched on Y. */
- if ( !CUR.iup_called &&
- ( CUR.zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
+#if 0
+ /* Standard Subpixel Hinting: Allow y move. */
+ /* This messes up dejavu and may not be needed... */
+ if ( !CUR.face->sph_compatibility_mode &&
+ CUR.GS.freeVector.y != 0 )
CUR_Func_move( &CUR.zp0, A, B );
- }
+ else
+#endif /* 0 */
- B2 = CUR.zp0.cur[A].y;
+ /* Compatibility Mode: Allow x or y move if point touched in */
+ /* Y direction. */
+ if ( CUR.face->sph_compatibility_mode &&
+ !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
+ {
+ /* save the y value of the point now; compare after move */
+ B1 = CUR.zp0.cur[A].y;
- /* Reverse this move if it results in a disallowed move */
- if ( CUR.GS.freeVector.y != 0 &&
- ( ( CUR.face->sph_compatibility_mode &&
- ( B1 & 63 ) == 0 &&
- ( B2 & 63 ) != 0 ) ||
- ( ( CUR.sph_tweak_flags &
- SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
- ( B1 & 63 ) != 0 &&
- ( B2 & 63 ) != 0 ) ) )
- CUR_Func_move( &CUR.zp0, A, -B );
+ if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+ B = FT_PIX_ROUND( B1 + B ) - B1;
+
+ /* Allow delta move if using sph_compatibility_mode, */
+ /* IUP has not been called, and point is touched on Y. */
+ if ( !CUR.iup_called &&
+ ( CUR.zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
+ CUR_Func_move( &CUR.zp0, A, B );
+ }
+
+ B2 = CUR.zp0.cur[A].y;
+
+ /* Reverse this move if it results in a disallowed move */
+ if ( CUR.GS.freeVector.y != 0 &&
+ ( ( CUR.face->sph_compatibility_mode &&
+ ( B1 & 63 ) == 0 &&
+ ( B2 & 63 ) != 0 ) ||
+ ( ( CUR.sph_tweak_flags &
+ SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+ ( B1 & 63 ) != 0 &&
+ ( B2 & 63 ) != 0 ) ) )
+ CUR_Func_move( &CUR.zp0, A, -B );
+ }
}
-#else
- CUR_Func_move( &CUR.zp0, A, B );
-#endif /* *TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ else
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+ CUR_Func_move( &CUR.zp0, A, B );
}
}
else
@@ -7562,7 +7621,9 @@
/* Selector Bit: 0 */
/* Return Bit(s): 0-7 */
/* */
- if ( ( args[0] & 1 ) != 0 && CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING &&
+ ( args[0] & 1 ) != 0 &&
+ CUR.ignore_x_mode )
{
K = CUR.rasterizer_version;
FT_TRACE7(( "Setting rasterizer version %d\n",
@@ -7571,7 +7632,7 @@
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
if ( ( args[0] & 1 ) != 0 )
- K = 35;
+ K = TT_INTERPRETER_VERSION_35;
/********************************/
/* GLYPH ROTATED */
@@ -7598,7 +7659,10 @@
K |= 1 << 12;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode && CUR.rasterizer_version >= 35 )
+
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode &&
+ CUR.rasterizer_version >= TT_INTERPRETER_VERSION_35 )
{
/********************************/
/* HINTING FOR GRAYSCALE */
@@ -7661,7 +7725,9 @@
}
}
}
+
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
args[0] = K;
}
@@ -8313,10 +8379,12 @@
case 0x2B: /* CALL */
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !CUR.ignore_x_mode ||
- !CUR.iup_called ||
- ( CUR.iup_called &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) )
+ if ( !SUBPIXEL_HINTING ||
+ ( !CUR.ignore_x_mode ||
+ !CUR.iup_called ||
+ ( CUR.iup_called &&
+ !( CUR.sph_tweak_flags &
+ SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
Ins_CALL( EXEC_ARG_ args );
break;
@@ -8337,10 +8405,12 @@
case 0x30: /* IUP */
case 0x31: /* IUP */
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING &&
+ CUR.ignore_x_mode )
CUR.iup_called = TRUE;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- Ins_IUP( EXEC_ARG_ args );
+
+ Ins_IUP( EXEC_ARG_ args );
break;
case 0x32: /* SHP */
@@ -8500,10 +8570,12 @@
case 0x5D: /* DELTAP1 */
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !CUR.ignore_x_mode ||
- !CUR.iup_called ||
- ( CUR.iup_called &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) )
+ if ( !SUBPIXEL_HINTING ||
+ ( !CUR.ignore_x_mode ||
+ !CUR.iup_called ||
+ ( CUR.iup_called &&
+ !( CUR.sph_tweak_flags &
+ SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
Ins_DELTAP( EXEC_ARG_ args );
break;
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -21,6 +21,7 @@
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_DRIVER_H
#include "ttgload.h"
#include "ttpload.h"
@@ -1259,11 +1260,17 @@
if ( !TT_New_Context( driver ) )
return FT_THROW( Could_Not_Find_Context );
+#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 */
+
FT_UNUSED( ttdriver );
-#endif
+#endif /* !TT_USE_BYTECODE_INTERPRETER */
return FT_Err_Ok;
}
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -347,11 +347,12 @@
/* */
typedef struct TT_DriverRec_
{
- FT_DriverRec root;
+ FT_DriverRec root;
+
TT_ExecContext context; /* execution context */
TT_GlyphZoneRec zone; /* glyph loader points zone */
- void* extension_component;
+ FT_UInt interpreter_version;
} TT_DriverRec;
--- a/src/truetype/ttsubpix.c
+++ b/src/truetype/ttsubpix.c
@@ -22,6 +22,7 @@
#include FT_INTERNAL_SFNT_H
#include FT_TRUETYPE_TAGS_H
#include FT_OUTLINE_H
+#include FT_TRUETYPE_DRIVER_H
#include "ttsubpix.h"
@@ -1027,9 +1028,9 @@
if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
{
- if ( loader->exec->rasterizer_version != 35 )
+ if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 )
{
- loader->exec->rasterizer_version = 35;
+ loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
loader->exec->size->cvt_ready = FALSE;
tt_size_ready_bytecode(
@@ -1037,7 +1038,7 @@
FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
}
else
- loader->exec->rasterizer_version = 35;
+ loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
}
else
{