From f04951af8dd16495ebe5bd45a3e33ad30f511553 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Fri, 17 May 2013 13:51:07 +0200 Subject: [PATCH] [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. --- ChangeLog | 29 ++ include/freetype/config/ftheader.h | 13 + include/freetype/ftchapters.h | 18 +- include/freetype/ftttdrv.h | 150 +++++++++ src/truetype/ttdriver.c | 36 ++- src/truetype/ttgload.c | 389 ++++++++++++---------- src/truetype/ttinterp.c | 504 ++++++++++++++++------------- src/truetype/ttobjs.c | 9 +- src/truetype/ttobjs.h | 5 +- src/truetype/ttsubpix.c | 7 +- 10 files changed, 755 insertions(+), 405 deletions(-) create mode 100644 include/freetype/ftttdrv.h diff --git a/ChangeLog b/ChangeLog index 0fb0958e1..de49146e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2013-05-15 Werner Lemberg + + [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 [truetype] Avoid empty source file. diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h index 93969ef81..8371a3161 100644 --- a/include/freetype/config/ftheader.h +++ b/include/freetype/config/ftheader.h @@ -341,6 +341,19 @@ #define FT_CFF_DRIVER_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 + + /************************************************************************* * * @macro: diff --git a/include/freetype/ftchapters.h b/include/freetype/ftchapters.h index eccacaba6..c55670d1d 100644 --- a/include/freetype/ftchapters.h +++ b/include/freetype/ftchapters.h @@ -67,27 +67,15 @@ /***************************************************************************/ /* */ /* */ -/* auto_hinter */ +/* module_specific */ /* */ /* */ -/* The Auto-Hinter */ +/* Controlling FreeType Modules */ /* */ /* <Sections> */ /* auto_hinter */ -/* */ -/***************************************************************************/ - - -/***************************************************************************/ -/* */ -/* <Chapter> */ -/* cff_driver */ -/* */ -/* <Title> */ -/* The CFF Driver */ -/* */ -/* <Sections> */ /* cff_driver */ +/* tt_driver */ /* */ /***************************************************************************/ diff --git a/include/freetype/ftttdrv.h b/include/freetype/ftttdrv.h new file mode 100644 index 000000000..d5d3f1ccc --- /dev/null +++ b/include/freetype/ftttdrv.h @@ -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 */ diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index bc2e658d0..fb25706ab 100644 --- 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 ); } diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index b6bb7487c..64455e194 100644 --- 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 /* 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; diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index 872894d3b..2e9cf6452 100644 --- 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 ) - { - /* 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; diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index 85254aadc..7897efa77 100644 --- 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; } diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h index 030a552d2..a11dd3752 100644 --- a/src/truetype/ttobjs.h +++ b/src/truetype/ttobjs.h @@ -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; diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c index 27e9b150b..af57b9c21 100644 --- 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 {