[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.
This commit is contained in:
Werner Lemberg 2013-05-17 13:51:07 +02:00
parent 6650be7c43
commit f04951af8d
10 changed files with 755 additions and 405 deletions

View File

@ -1,3 +1,32 @@
2013-05-15 Werner Lemberg <wl@gnu.org>
[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 <wl@gnu.org>
[truetype] Avoid empty source file.

View File

@ -341,6 +341,19 @@
#define FT_CFF_DRIVER_H <freetype/ftcffdrv.h>
/*************************************************************************
*
* @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:

View File

@ -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 */
/* */
/***************************************************************************/

150
include/freetype/ftttdrv.h Normal file
View File

@ -0,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 */

View File

@ -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 );
}

View File

@ -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 /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
#endif
return FT_Err_Ok;
}
@ -848,14 +864,6 @@
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;
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
FT_Vector* vec = outline->points;
FT_Vector* limit = outline->points + n_points;
FT_Fixed x_scale;
FT_Fixed y_scale;
FT_Bool do_scale = FALSE;
/* 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 */
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
for ( ; vec < limit; vec++ )
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
#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;
}
}
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 ( 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,17 +1957,24 @@
{
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 )
{
@ -1937,114 +1993,115 @@
#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 )
{
/* 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 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->grayscale_hinting = grayscale_hinting;
reexecute = TRUE;
}
}
else
#endif /* 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 )
{
FT_TRACE4(( "tt_loader_init: grayscale change,"
" re-executing `prep' table\n" ));
exec->grayscale = grayscale;
reexecute = TRUE;
}
}
if ( reexecute )
{
FT_UInt i;
FT_TRACE4(( "tt_loader_init: subpixel 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 );
}
/* a change from mono to grayscale rendering (and vice versa) */
/* requires a re-execution of the CVT program */
if ( grayscale != exec->grayscale_hinting )
{
FT_UInt i;
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 );
}
#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 )
{
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 )
load_flags |= FT_LOAD_NO_HINTING;

View File

@ -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 )
{
/* 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 )
switch ( i )
{
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,14 +6089,18 @@
( 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 ( ( 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 ) );
}
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 */
/* 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;
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 );
}
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;

View File

@ -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;
}

View File

@ -347,11 +347,12 @@ FT_BEGIN_HEADER
/* */
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;

View File

@ -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
{