From aaf21968deb85b635cb6aa6544df233ea5981346 Mon Sep 17 00:00:00 2001 From: marha Date: Wed, 13 Feb 2013 09:48:21 +0100 Subject: Update to following packages: openssl-1.0.1e freetype-2.4.11 --- freetype/src/truetype/rules.mk | 5 +- freetype/src/truetype/truetype.c | 3 +- freetype/src/truetype/ttdriver.c | 39 +- freetype/src/truetype/ttgload.c | 163 ++++++- freetype/src/truetype/ttgxvar.c | 59 +-- freetype/src/truetype/ttinterp.c | 824 ++++++++++++++++++++++++++++------- freetype/src/truetype/ttinterp.h | 79 +++- freetype/src/truetype/ttobjs.c | 10 +- freetype/src/truetype/ttobjs.h | 18 +- freetype/src/truetype/ttpic.c | 11 +- freetype/src/truetype/ttpic.h | 31 +- freetype/src/truetype/ttsubpix.c | 265 ++++++++++++ freetype/src/truetype/ttsubpix.h | 908 +++++++++++++++++++++++++++++++++++++++ 13 files changed, 2177 insertions(+), 238 deletions(-) create mode 100644 freetype/src/truetype/ttsubpix.c create mode 100644 freetype/src/truetype/ttsubpix.h (limited to 'freetype/src/truetype') diff --git a/freetype/src/truetype/rules.mk b/freetype/src/truetype/rules.mk index 507ef16b0..d4b69f578 100644 --- a/freetype/src/truetype/rules.mk +++ b/freetype/src/truetype/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2000, 2001, 2003, 2004, 2011 by +# Copyright 1996-2001, 2003-2004, 2011-2012 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -31,7 +31,8 @@ TT_DRV_SRC := $(TT_DIR)/ttdriver.c \ $(TT_DIR)/ttinterp.c \ $(TT_DIR)/ttobjs.c \ $(TT_DIR)/ttpic.c \ - $(TT_DIR)/ttpload.c + $(TT_DIR)/ttpload.c \ + $(TT_DIR)/ttsubpix.c # TrueType driver headers # diff --git a/freetype/src/truetype/truetype.c b/freetype/src/truetype/truetype.c index 4bd120978..576912b21 100644 --- a/freetype/src/truetype/truetype.c +++ b/freetype/src/truetype/truetype.c @@ -4,7 +4,7 @@ /* */ /* FreeType TrueType driver component (body only). */ /* */ -/* Copyright 1996-2001, 2004, 2006 by */ +/* Copyright 1996-2001, 2004, 2006, 2012 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,6 +27,7 @@ #ifdef TT_USE_BYTECODE_INTERPRETER #include "ttinterp.c" +#include "ttsubpix.c" #endif #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT diff --git a/freetype/src/truetype/ttdriver.c b/freetype/src/truetype/ttdriver.c index 3669d4582..60c0f3e13 100644 --- a/freetype/src/truetype/ttdriver.c +++ b/freetype/src/truetype/ttdriver.c @@ -353,13 +353,13 @@ /*************************************************************************/ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICE_MULTIMASTERSREC(tt_service_gx_multi_masters, + FT_DEFINE_SERVICE_MULTIMASTERSREC( + tt_service_gx_multi_masters, (FT_Get_MM_Func) NULL, (FT_Set_MM_Design_Func) NULL, (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, (FT_Get_MM_Var_Func) TT_Get_MM_Var, - (FT_Set_Var_Design_Func)TT_Set_Var_Design - ) + (FT_Set_Var_Design_Func)TT_Set_Var_Design ) #endif static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine = @@ -379,25 +379,26 @@ #endif /* TT_USE_BYTECODE_INTERPRETER */ }; - FT_DEFINE_SERVICE_TTGLYFREC(tt_service_truetype_glyf, - (TT_Glyf_GetLocationFunc)tt_face_get_location - ) + FT_DEFINE_SERVICE_TTGLYFREC( + tt_service_truetype_glyf, + (TT_Glyf_GetLocationFunc)tt_face_get_location ) #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC4(tt_services, + FT_DEFINE_SERVICEDESCREC4( + tt_services, FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE, - FT_SERVICE_ID_MULTI_MASTERS, &FT_TT_SERVICE_GX_MULTI_MASTERS_GET, + FT_SERVICE_ID_MULTI_MASTERS, &TT_SERVICE_GX_MULTI_MASTERS_GET, FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, - FT_SERVICE_ID_TT_GLYF, &FT_TT_SERVICE_TRUETYPE_GLYF_GET - ) + FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET ) #else - FT_DEFINE_SERVICEDESCREC3(tt_services, + FT_DEFINE_SERVICEDESCREC3( + tt_services, FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE, FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, - FT_SERVICE_ID_TT_GLYF, &FT_TT_SERVICE_TRUETYPE_GLYF_GET - ) + FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET ) #endif + FT_CALLBACK_DEF( FT_Module_Interface ) tt_get_interface( FT_Module driver, /* TT_Driver */ const char* tt_interface ) @@ -408,7 +409,7 @@ SFNT_Service sfnt; - /* FT_TT_SERVICES_GET derefers `library' in PIC mode */ + /* TT_SERVICES_GET derefers `library' in PIC mode */ #ifdef FT_CONFIG_OPTION_PIC if ( !driver ) return NULL; @@ -417,7 +418,7 @@ return NULL; #endif - result = ft_service_list_lookup( FT_TT_SERVICES_GET, tt_interface ); + result = ft_service_list_lookup( TT_SERVICES_GET, tt_interface ); if ( result != NULL ) return result; @@ -445,15 +446,15 @@ /* The FT_DriverInterface structure is defined in ftdriver.h. */ #ifdef TT_USE_BYTECODE_INTERPRETER -#define TT_HINTER_FLAG FT_MODULE_DRIVER_HAS_HINTER +#define TT_HINTER_FLAG FT_MODULE_DRIVER_HAS_HINTER #else -#define TT_HINTER_FLAG 0 +#define TT_HINTER_FLAG 0 #endif #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#define TT_SIZE_SELECT tt_size_select +#define TT_SIZE_SELECT tt_size_select #else -#define TT_SIZE_SELECT 0 +#define TT_SIZE_SELECT 0 #endif FT_DEFINE_DRIVER( tt_driver_class, diff --git a/freetype/src/truetype/ttgload.c b/freetype/src/truetype/ttgload.c index 22cbc09e2..374f89dce 100644 --- a/freetype/src/truetype/ttgload.c +++ b/freetype/src/truetype/ttgload.c @@ -32,6 +32,7 @@ #endif #include "tterrors.h" +#include "ttsubpix.h" /*************************************************************************/ @@ -149,6 +150,15 @@ loader->top_bearing = top_bearing; loader->vadvance = advance_height; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + 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 ); +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + if ( !loader->linear_def ) { loader->linear_def = 1; @@ -252,10 +262,6 @@ } -#undef IS_HINTED -#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) - - /*************************************************************************/ /* */ /* The following functions are used by default with TrueType fonts. */ @@ -813,6 +819,13 @@ loader->pp4 = zone->cur[zone->n_points - 1]; } +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + 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 return TT_Err_Ok; } @@ -835,6 +848,14 @@ 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; @@ -889,6 +910,32 @@ 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 = scale_test_tweak( face, family, ppem, style, + loader->glyph_index, X_SCALING_Rules, + X_SCALING_RULES_SIZE ); + /* 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; + + + /* 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 ) { @@ -896,6 +943,7 @@ 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 */ for ( ; vec < limit; vec++ ) @@ -1648,12 +1696,26 @@ { 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 ) +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ glyph->metrics.horiAdvance = *widthp << 6; } @@ -1833,7 +1895,9 @@ { TT_Face face; FT_Stream stream; +#ifdef TT_USE_BYTECODE_INTERPRETER FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); +#endif face = (TT_Face)glyph->face; @@ -1848,6 +1912,16 @@ { TT_ExecContext exec; FT_Bool grayscale; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + FT_Bool subpixel_hinting; + FT_Bool grayscale_hinting; +#if 0 + FT_Bool compatible_widths; + FT_Bool symmetrical_smoothing; + FT_Bool bgr; + FT_Bool subpixel_positioned; +#endif +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ if ( !size->cvt_ready ) @@ -1865,11 +1939,90 @@ if ( !exec ) return TT_Err_Could_Not_Find_Context; +#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 ) + { + grayscale = grayscale_hinting = TRUE; + subpixel_hinting = FALSE; + } + + 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 = 35; + +#if 1 + 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 ); +#endif /* 0 */ + +#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO ); +#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + 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 ) + { + FT_UInt i; + + + 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; + + + 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 ) @@ -1887,6 +2040,8 @@ 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/freetype/src/truetype/ttgxvar.c b/freetype/src/truetype/ttgxvar.c index 69b702f62..4edcb07ab 100644 --- a/freetype/src/truetype/ttgxvar.c +++ b/freetype/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader */ /* */ -/* Copyright 2004-2011 by */ +/* Copyright 2004-2012 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -91,7 +91,7 @@ /* indicates that there is a delta for every point without needing to */ /* enumerate all of them. */ /* */ -#define ALL_POINTS (FT_UShort*)( -1 ) +#define ALL_POINTS (FT_UShort*)( ~0 ) #define GX_PT_POINTS_ARE_WORDS 0x80 @@ -501,11 +501,9 @@ FT_Fixed* im_end_coords ) { FT_UInt i; - FT_Fixed apply; - FT_Fixed temp; + FT_Fixed apply = 0x10000L; - apply = 0x10000L; for ( i = 0; i < blend->num_axis; ++i ) { if ( tuple_coords[i] == 0 ) @@ -525,11 +523,10 @@ else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) /* not an intermediate tuple */ - apply = FT_MulDiv( apply, + apply = FT_MulFix( apply, blend->normalizedcoords[i] > 0 ? blend->normalizedcoords[i] - : -blend->normalizedcoords[i], - 0x10000L ); + : -blend->normalizedcoords[i] ); else if ( blend->normalizedcoords[i] <= im_start_coords[i] || blend->normalizedcoords[i] >= im_end_coords[i] ) @@ -539,20 +536,14 @@ } else if ( blend->normalizedcoords[i] < tuple_coords[i] ) - { - temp = FT_MulDiv( blend->normalizedcoords[i] - im_start_coords[i], - 0x10000L, - tuple_coords[i] - im_start_coords[i]); - apply = FT_MulDiv( apply, temp, 0x10000L ); - } + apply = FT_MulDiv( apply, + blend->normalizedcoords[i] - im_start_coords[i], + tuple_coords[i] - im_start_coords[i] ); else - { - temp = FT_MulDiv( im_end_coords[i] - blend->normalizedcoords[i], - 0x10000L, - im_end_coords[i] - tuple_coords[i] ); - apply = FT_MulDiv( apply, temp, 0x10000L ); - } + apply = FT_MulDiv( apply, + im_end_coords[i] - blend->normalizedcoords[i], + im_end_coords[i] - tuple_coords[i] ); } return apply; @@ -712,7 +703,7 @@ mmvar->num_axis = fvar_head.axisCount; mmvar->num_designs = - (FT_UInt)-1; /* meaningless in this context; each glyph */ + ~0; /* meaningless in this context; each glyph */ /* may have a different number of designs */ /* (or tuples, as called by Apple) */ mmvar->num_namedstyles = @@ -1034,19 +1025,11 @@ } if ( coords[i] < a->def ) - { - normalized[i] = -FT_MulDiv( coords[i] - a->def, - 0x10000L, - a->minimum - a->def ); - } + normalized[i] = -FT_DivFix( coords[i] - a->def, a->minimum - a->def ); else if ( a->maximum == a->def ) normalized[i] = 0; else - { - normalized[i] = FT_MulDiv( coords[i] - a->def, - 0x10000L, - a->maximum - a->def ); - } + normalized[i] = FT_DivFix( coords[i] - a->def, a->maximum - a->def ); } if ( !blend->avar_checked ) @@ -1061,15 +1044,11 @@ if ( normalized[i] < av->correspondence[j].fromCoord ) { normalized[i] = - FT_MulDiv( - FT_MulDiv( - normalized[i] - av->correspondence[j - 1].fromCoord, - 0x10000L, - av->correspondence[j].fromCoord - - av->correspondence[j - 1].fromCoord ), - av->correspondence[j].toCoord - - av->correspondence[j - 1].toCoord, - 0x10000L ) + + FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, + av->correspondence[j].toCoord - + av->correspondence[j - 1].toCoord, + av->correspondence[j].fromCoord - + av->correspondence[j - 1].fromCoord ) + av->correspondence[j - 1].toCoord; break; } diff --git a/freetype/src/truetype/ttinterp.c b/freetype/src/truetype/ttinterp.c index 3a8680f83..19fb66c17 100644 --- a/freetype/src/truetype/ttinterp.c +++ b/freetype/src/truetype/ttinterp.c @@ -27,16 +27,15 @@ #include FT_SYSTEM_H #include "ttinterp.h" - #include "tterrors.h" +#include "ttsubpix.h" #ifdef TT_USE_BYTECODE_INTERPRETER -#define TT_MULFIX FT_MulFix -#define TT_MULDIV FT_MulDiv -#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round +#define xxxSPH_DEBUG +#define xxxSPH_DEBUG_MORE_VERBOSE /*************************************************************************/ @@ -232,6 +231,14 @@ #define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) #define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) ) + /*************************************************************************/ + /* */ + /* This macro computes (a*2^14)/b and complements TT_MulFix14. */ + /* */ +#define TT_DivFix14( a, b ) \ + FT_DivFix( a, (b) << 2 ) + + #undef SUCCESS #define SUCCESS 0 @@ -1661,13 +1668,13 @@ else { - FT_Long x, y; + FT_F26Dot6 x, y; - x = TT_MULDIV( CUR.GS.projVector.x, - CUR.tt_metrics.x_ratio, 0x4000 ); - y = TT_MULDIV( CUR.GS.projVector.y, - CUR.tt_metrics.y_ratio, 0x4000 ); + x = TT_MulFix14( CUR.tt_metrics.x_ratio, + CUR.GS.projVector.x ); + y = TT_MulFix14( CUR.tt_metrics.y_ratio, + CUR.GS.projVector.y ); CUR.tt_metrics.ratio = TT_VecLen( x, y ); } } @@ -1679,7 +1686,7 @@ static FT_Long Current_Ppem( EXEC_OP ) { - return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() ); + return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() ); } @@ -1700,7 +1707,7 @@ FT_CALLBACK_DEF( FT_F26Dot6 ) Read_CVT_Stretched( EXEC_OP_ FT_ULong idx ) { - return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() ); + return FT_MulFix( CUR.cvt[idx], CURRENT_Ratio() ); } @@ -1850,9 +1857,11 @@ if ( v != 0 ) { - zone->cur[point].x += TT_MULDIV( distance, - v * 0x10000L, - CUR.F_dot_P ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( !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->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1861,9 +1870,7 @@ if ( v != 0 ) { - zone->cur[point].y += TT_MULDIV( distance, - v * 0x10000L, - CUR.F_dot_P ); + zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1902,16 +1909,12 @@ v = CUR.GS.freeVector.x; if ( v != 0 ) - zone->org[point].x += TT_MULDIV( distance, - v * 0x10000L, - CUR.F_dot_P ); + zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P ); v = CUR.GS.freeVector.y; if ( v != 0 ) - zone->org[point].y += TT_MULDIV( distance, - v * 0x10000L, - CUR.F_dot_P ); + zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P ); } @@ -1932,6 +1935,10 @@ { FT_UNUSED_EXEC; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( !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->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -2193,7 +2200,7 @@ } else { - val = - FT_PIX_CEIL( compensation - distance ); + val = -FT_PIX_CEIL( compensation - distance ); if ( val > 0 ) val = 0; } @@ -2404,8 +2411,9 @@ /* Sets Super Round parameters. */ /* */ /* */ - /* GridPeriod :: Grid period */ - /* selector :: SROUND opcode */ + /* GridPeriod :: The grid period. */ + /* */ + /* selector :: The SROUND opcode. */ /* */ static void SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod, @@ -2617,13 +2625,10 @@ if ( CUR.GS.dualVector.x == 0x4000 ) CUR.func_dualproj = Project_x; + else if ( CUR.GS.dualVector.y == 0x4000 ) + CUR.func_dualproj = Project_y; else - { - if ( CUR.GS.dualVector.y == 0x4000 ) - CUR.func_dualproj = Project_y; - else - CUR.func_dualproj = Dual_Project; - } + CUR.func_dualproj = Dual_Project; /* Force recalculation of cached aspect ratio */ CUR.tt_metrics.ratio = 0; @@ -2633,61 +2638,50 @@ #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ if ( CUR.GS.freeVector.x == 0x4000 ) - CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L; + CUR.F_dot_P = CUR.GS.projVector.x; + else if ( CUR.GS.freeVector.y == 0x4000 ) + CUR.F_dot_P = CUR.GS.projVector.y; else - { - if ( CUR.GS.freeVector.y == 0x4000 ) - CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L; - else - CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 + - (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4; - } + CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x + + (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >> + 14; if ( CUR.GS.projVector.x == 0x4000 ) CUR.func_project = (TT_Project_Func)Project_x; + else if ( CUR.GS.projVector.y == 0x4000 ) + CUR.func_project = (TT_Project_Func)Project_y; else - { - if ( CUR.GS.projVector.y == 0x4000 ) - CUR.func_project = (TT_Project_Func)Project_y; - else - CUR.func_project = (TT_Project_Func)Project; - } + CUR.func_project = (TT_Project_Func)Project; if ( CUR.GS.dualVector.x == 0x4000 ) CUR.func_dualproj = (TT_Project_Func)Project_x; + else if ( CUR.GS.dualVector.y == 0x4000 ) + CUR.func_dualproj = (TT_Project_Func)Project_y; else - { - if ( CUR.GS.dualVector.y == 0x4000 ) - CUR.func_dualproj = (TT_Project_Func)Project_y; - else - CUR.func_dualproj = (TT_Project_Func)Dual_Project; - } + CUR.func_dualproj = (TT_Project_Func)Dual_Project; CUR.func_move = (TT_Move_Func)Direct_Move; CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig; - if ( CUR.F_dot_P == 0x40000000L ) + if ( CUR.F_dot_P == 0x4000L ) { if ( CUR.GS.freeVector.x == 0x4000 ) { CUR.func_move = (TT_Move_Func)Direct_Move_X; CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X; } - else + else if ( CUR.GS.freeVector.y == 0x4000 ) { - if ( CUR.GS.freeVector.y == 0x4000 ) - { - CUR.func_move = (TT_Move_Func)Direct_Move_Y; - CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y; - } + CUR.func_move = (TT_Move_Func)Direct_Move_Y; + CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y; } } /* at small sizes, F_dot_P can become too small, resulting */ /* in overflows and `spikes' in a number of glyphs like `w'. */ - if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L ) - CUR.F_dot_P = 0x40000000L; + if ( FT_ABS( CUR.F_dot_P ) < 0x400L ) + CUR.F_dot_P = 0x4000L; /* Disable cached aspect ratio */ CUR.tt_metrics.ratio = 0; @@ -2743,16 +2737,16 @@ return SUCCESS; } - R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W ); - R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W ); + R->x = (FT_F2Dot14)TT_DivFix14( Vx, W ); + R->y = (FT_F2Dot14)TT_DivFix14( Vy, W ); return SUCCESS; } W = TT_VecLen( Vx, Vy ); - Vx = FT_MulDiv( Vx, 0x4000L, W ); - Vy = FT_MulDiv( Vy, 0x4000L, W ); + Vx = TT_DivFix14( Vx, W ); + Vy = TT_DivFix14( Vy, W ); W = Vx * Vx + Vy * Vy; @@ -3111,7 +3105,7 @@ #define DO_SSW \ - CUR.GS.single_width_value = TT_MULFIX( args[0], \ + CUR.GS.single_width_value = FT_MulFix( args[0], \ CUR.tt_metrics.scale ); @@ -3289,11 +3283,11 @@ if ( args[1] == 0 ) \ CUR.error = TT_Err_Divide_By_Zero; \ else \ - args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] ); + args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] ); #define DO_MUL \ - args[0] = TT_MULDIV( args[0], args[1], 64L ); + args[0] = FT_MulDiv( args[0], args[1], 64L ); #define DO_ABS \ @@ -3311,6 +3305,34 @@ #define DO_CEILING \ args[0] = FT_PIX_CEIL( args[0] ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + +#define DO_RS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDSL( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + ARRAY_BOUND_ERROR; \ + else \ + args[0] = 0; \ + } \ + else \ + { \ + /* subpixel hinting - avoid Typeman Dstroke and */ \ + /* IStroke and Vacuform rounds */ \ + \ + if ( CUR.compatibility_mode && \ + ( I == 24 || I == 22 || I == 8 ) ) \ + args[0] = 0; \ + else \ + args[0] = CUR.storage[I]; \ + } \ + } + +#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ #define DO_RS \ { \ @@ -3330,6 +3352,8 @@ args[0] = CUR.storage[I]; \ } +#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + #define DO_WS \ { \ @@ -3397,7 +3421,7 @@ } \ } \ else \ - CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \ + CUR.cvt[I] = FT_MulFix( args[1], CUR.tt_metrics.scale ); \ } @@ -4587,6 +4611,27 @@ TT_DefRecord* rec; TT_DefRecord* limit; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* arguments to opcodes are skipped by `SKIP_Code' */ + FT_Byte opcode_pattern[1][12] = { + /* #0 TTFautohint bytecode (old) */ + { + 0x20, /* DUP */ + 0x64, /* ABS */ + 0xB0, /* PUSHB_1 */ + /* 32 */ + 0x60, /* ADD */ + 0x66, /* FLOOR */ + 0x23, /* SWAP */ + 0xB0 /* PUSHB_1 */ + }, + }; + FT_UShort opcode_patterns = 1; + FT_UShort opcode_pointer[1] = { 0, }; + FT_UShort opcode_size[1] = { 7, }; + FT_UShort i; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + /* some font programs are broken enough to redefine functions! */ /* We will then parse the current table. */ @@ -4620,10 +4665,11 @@ return; } - rec->range = CUR.curRange; - rec->opc = (FT_UInt16)n; - rec->start = CUR.IP + 1; - rec->active = TRUE; + rec->range = CUR.curRange; + rec->opc = (FT_UInt16)n; + rec->start = CUR.IP + 1; + rec->active = TRUE; + rec->inline_delta = FALSE; if ( n > CUR.maxFunc ) CUR.maxFunc = (FT_UInt16)n; @@ -4633,6 +4679,46 @@ while ( SKIP_Code() == SUCCESS ) { +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + +#ifdef SPH_DEBUG_MORE_VERBOSE + printf ( "Opcode: %d ", CUR.opcode ); +#endif + + for ( i = 0; i < opcode_patterns; i++ ) + { + if ( opcode_pointer[i] < opcode_size[i] && + CUR.opcode == opcode_pattern[i][opcode_pointer[i]] ) + { +#ifdef SPH_DEBUG_MORE_VERBOSE + printf( "function %d, opcode ptrn: %d" + " op# %d: %d FOUND \n", + n, i, opcode_pointer[i], CUR.opcode ); +#endif + opcode_pointer[i] += 1; + + if ( opcode_pointer[i] == opcode_size[i] ) + { +#ifdef SPH_DEBUG + printf( "Function signature %d detected in FDEF %d\n", i, n); +#endif + + switch ( i ) + { + case 0: + CUR.size->ttfautohinted = TRUE; + break; + } + opcode_pointer[i] = 0; + } + } + + else + opcode_pointer[i] = 0; + } + +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + switch ( CUR.opcode ) { case 0x89: /* IDEF */ @@ -4676,6 +4762,15 @@ CUR.step_ins = FALSE; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* + * CUR.ignore_x_mode may be turned off prior to function calls. This + * ensures it is turned back on. + */ + CUR.ignore_x_mode = ( CUR.subpixel_hinting || CUR.grayscale_hinting ) && + !( CUR.sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING ); +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + if ( pRec->Cur_Count > 0 ) { CUR.callTop++; @@ -4746,6 +4841,7 @@ if ( !def->active ) goto Fail; + /* check the call stack */ if ( CUR.callTop >= CUR.callSize ) { @@ -4846,6 +4942,7 @@ CUR.step_ins = FALSE; } + return; Fail: @@ -5179,15 +5276,15 @@ { /* this should be faster */ D = CUR_Func_dualproj( vec1, vec2 ); - D = TT_MULFIX( D, CUR.metrics.x_scale ); + D = FT_MulFix( D, CUR.metrics.x_scale ); } else { FT_Vector vec; - vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale ); - vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale ); + vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale ); + vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale ); D = CUR_fast_dualproj( &vec ); } @@ -5195,6 +5292,12 @@ } } +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */ + if ( CUR.ignore_x_mode && FT_ABS( D ) == 64 ) + D += 1; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + args[0] = D; } @@ -5652,12 +5755,8 @@ else #endif { - *x = TT_MULDIV( d, - (FT_Long)CUR.GS.freeVector.x * 0x10000L, - CUR.F_dot_P ); - *y = TT_MULDIV( d, - (FT_Long)CUR.GS.freeVector.y * 0x10000L, - CUR.F_dot_P ); + *x = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.x, CUR.F_dot_P ); + *y = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.y, CUR.F_dot_P ); } return SUCCESS; @@ -5691,7 +5790,12 @@ if ( CUR.GS.freeVector.x != 0 ) { - CUR.zp2.cur[point].x += dx; +#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 ) ) ) +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + CUR.zp2.cur[point].x += dx; if ( touch ) CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -5872,6 +5976,9 @@ { FT_F26Dot6 dx, dy; FT_UShort point; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + FT_Int B1, B2; +#endif if ( CUR.top < CUR.GS.loop + 1 ) @@ -5886,13 +5993,13 @@ { if ( CUR.GS.both_x_axis ) { - dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 ); + dx = (FT_UInt32)args[0]; dy = 0; } else { dx = 0; - dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 ); + dy = (FT_UInt32)args[0]; } } else @@ -5917,7 +6024,80 @@ } } else +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + /* If not using ignore_x_mode rendering, allow ZP2 move. */ + /* If inline deltas aren't allowed, skip ZP2 move. */ + /* If using ignore_x_mode rendering, allow ZP2 point move if: */ + /* - freedom vector is y and compatibility_mode is off */ + /* - the glyph is composite and the move is in the Y direction */ + /* - the glyph is specifically set to allow SHPIX moves */ + /* - the move is on a previously Y-touched point */ + + if ( CUR.ignore_x_mode ) + { + /* save point for later comparison */ + if ( CUR.GS.freeVector.y != 0 ) + B1 = CUR.zp2.cur[point].y; + else + B1 = CUR.zp2.cur[point].x; + + if ( CUR.GS.freeVector.y != 0 && + ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_INLINE_DELTAS ) ) + goto Skip; + + if ( CUR.ignore_x_mode && + !CUR.compatibility_mode && CUR.GS.freeVector.y != 0 ) + MOVE_Zp2_Point( point, dx, dy, TRUE ); + + else if ( CUR.ignore_x_mode && CUR.compatibility_mode ) + { + if ( CUR.ignore_x_mode && + ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) ) + { + dx = FT_PIX_ROUND( B1 + dx ) - B1; + dy = FT_PIX_ROUND( B1 + dy ) - B1; + } + + if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) && + ( ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) || + ( CUR.zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) || + ( CUR.sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) ) + MOVE_Zp2_Point( point, dx, dy, TRUE ); + } + + /* save new point */ + if ( CUR.GS.freeVector.y != 0 ) + B2 = CUR.zp2.cur[point].y; + else + B2 = CUR.zp2.cur[point].x; + + /* reverse any disallowed moves */ + if ( ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && + CUR.GS.freeVector.y != 0 && + B1 % 64 != 0 && + B2 % 64 != 0 && + B1 != B2 ) || + ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) && + CUR.GS.freeVector.y != 0 && + B1 % 64 == 0 && + B2 % 64 != 0 && + B1 != B2 && + !CUR.size->ttfautohinted ) ) + { +#ifdef SPH_DEBUG + printf( "Reversing ZP2 move\n" ); +#endif + MOVE_Zp2_Point( point, -dx, -dy, TRUE ); + } + } + else + MOVE_Zp2_Point( point, dx, dy, TRUE ); + } + Skip: +#else MOVE_Zp2_Point( point, dx, dy, TRUE ); +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ CUR.GS.loop--; } @@ -5939,7 +6119,17 @@ { 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 ( 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]; @@ -5963,6 +6153,14 @@ distance = CUR_Func_project( CUR.zp1.cur + point, CUR.zp0.cur + CUR.GS.rp0 ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* subpixel hinting - make MSIRP respect CVT cut-in; */ + if ( CUR.ignore_x_mode && + CUR.GS.freeVector.x != 0 && + FT_ABS( distance - args[1] ) >= control_value_cutin ) + distance = args[1]; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + CUR_Func_move( &CUR.zp1, point, args[1] - distance ); CUR.GS.rp1 = CUR.GS.rp0; @@ -5983,8 +6181,8 @@ Ins_MDAP( INS_ARG ) { FT_UShort point; - FT_F26Dot6 cur_dist, - distance; + FT_F26Dot6 cur_dist; + FT_F26Dot6 distance; point = (FT_UShort)args[0]; @@ -5999,8 +6197,17 @@ if ( ( CUR.opcode & 1 ) != 0 ) { cur_dist = CUR_fast_project( &CUR.zp0.cur[point] ); - distance = CUR_Func_round( cur_dist, - CUR.tt_metrics.compensations[0] ) - cur_dist; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode && + CUR.GS.freeVector.x != 0 ) + distance = ROUND_None( + cur_dist, + CUR.tt_metrics.compensations[0] ) - cur_dist; + else +#endif + distance = CUR_Func_round( + cur_dist, + CUR.tt_metrics.compensations[0] ) - cur_dist; } else distance = 0; @@ -6023,12 +6230,21 @@ { FT_ULong cvtEntry; FT_UShort point; - FT_F26Dot6 distance, - org_dist; + FT_F26Dot6 distance; + FT_F26Dot6 org_dist; + FT_F26Dot6 control_value_cutin; + + control_value_cutin = CUR.GS.control_value_cutin; + cvtEntry = (FT_ULong)args[1]; + point = (FT_UShort)args[0]; - cvtEntry = (FT_ULong)args[1]; - point = (FT_UShort)args[0]; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + 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 */ if ( BOUNDS( point, CUR.zp0.n_points ) || BOUNDSL( cvtEntry, CUR.cvtSize ) ) @@ -6062,21 +6278,39 @@ if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */ { - CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, - CUR.GS.freeVector.x ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* only adjust legacy fonts x otherwise breaks Calibri italic */ + if ( CUR.compatibility_mode ) +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, + CUR.GS.freeVector.x ); CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ), CUR.zp0.cur[point] = CUR.zp0.org[point]; } +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && + distance > 0 && + CUR.GS.freeVector.y != 0 ) + distance = 0; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ org_dist = CUR_fast_project( &CUR.zp0.cur[point] ); - if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */ + if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cut-in flag */ { - if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin ) + if ( FT_ABS( distance - org_dist ) > control_value_cutin ) distance = org_dist; - distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode && + CUR.GS.freeVector.x != 0 ) + distance = ROUND_None( distance, + CUR.tt_metrics.compensations[0] ); + else +#endif + distance = CUR_Func_round( distance, + CUR.tt_metrics.compensations[0] ); } CUR_Func_move( &CUR.zp0, point, distance - org_dist ); @@ -6097,7 +6331,17 @@ Ins_MDRP( INS_ARG ) { FT_UShort point; - FT_F26Dot6 org_dist, distance; + FT_F26Dot6 org_dist, distance, minimum_distance; + + + minimum_distance = CUR.GS.minimum_distance; + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( 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]; @@ -6133,15 +6377,15 @@ { /* this should be faster */ org_dist = CUR_Func_dualproj( vec1, vec2 ); - org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale ); + org_dist = FT_MulFix( org_dist, CUR.metrics.x_scale ); } else { FT_Vector vec; - vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale ); - vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale ); + vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale ); + vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale ); org_dist = CUR_fast_dualproj( &vec ); } @@ -6161,9 +6405,18 @@ /* round flag */ if ( ( CUR.opcode & 4 ) != 0 ) + { +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode && CUR.GS.freeVector.x != 0 ) + distance = ROUND_None( + org_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + else +#endif distance = CUR_Func_round( org_dist, CUR.tt_metrics.compensations[CUR.opcode & 3] ); + } else distance = ROUND_None( org_dist, @@ -6175,13 +6428,13 @@ { if ( org_dist >= 0 ) { - if ( distance < CUR.GS.minimum_distance ) - distance = CUR.GS.minimum_distance; + if ( distance < minimum_distance ) + distance = minimum_distance; } else { - if ( distance > -CUR.GS.minimum_distance ) - distance = -CUR.GS.minimum_distance; + if ( distance > -minimum_distance ) + distance = -minimum_distance; } } @@ -6216,11 +6469,27 @@ FT_F26Dot6 cvt_dist, distance, cur_dist, - org_dist; - - - point = (FT_UShort)args[0]; - cvtEntry = (FT_ULong)( args[1] + 1 ); + org_dist, + control_value_cutin, + minimum_distance; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + FT_Int B1; + FT_Int B2; + FT_Bool reverse_move = FALSE; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + + minimum_distance = CUR.GS.minimum_distance; + control_value_cutin = CUR.GS.control_value_cutin; + point = (FT_UShort)args[0]; + cvtEntry = (FT_ULong)( args[1] + 1 ); + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode && + CUR.GS.freeVector.x != 0 && + !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) + control_value_cutin = minimum_distance = 0; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ @@ -6237,6 +6506,10 @@ cvt_dist = 0; else cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.sph_tweak_flags & SPH_TWEAK_MIRP_CVT_ZERO ) + cvt_dist = 0; +#endif /* single width test */ @@ -6274,8 +6547,17 @@ if ( ( org_dist ^ cvt_dist ) < 0 ) cvt_dist = -cvt_dist; } - - /* control value cutin and round */ +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.GS.freeVector.y != 0 && + ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) ) + { + if ( cur_dist < -64 ) + cvt_dist -= 16; + else if ( cur_dist > 64 && cur_dist < 84 ) + cvt_dist += 32; + } +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + /* control value cut-in and round */ if ( ( CUR.opcode & 4 ) != 0 ) { @@ -6296,7 +6578,7 @@ /* `ttinst2.doc', version 1.66, is thus incorrect since */ /* it implies `>=' instead of `>'. */ - if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin ) + if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) cvt_dist = org_dist; } @@ -6315,18 +6597,65 @@ { if ( org_dist >= 0 ) { - if ( distance < CUR.GS.minimum_distance ) - distance = CUR.GS.minimum_distance; + if ( distance < minimum_distance ) + distance = minimum_distance; } else { - if ( distance > -CUR.GS.minimum_distance ) - distance = -CUR.GS.minimum_distance; + if ( distance > -minimum_distance ) + distance = -minimum_distance; } } +#ifdef TT_CONFIG_OPTION_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; + + if ( 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 ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) && + CUR.GS.freeVector.y != 0 && + B1 % 64 == 0 && + B2 % 64 != 0 && + !CUR.size->ttfautohinted ) + reverse_move = TRUE; + + if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && + CUR.GS.freeVector.y != 0 && + B2 % 64 != 0 && + B1 % 64 != 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 ) ); + +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + Fail: CUR.GS.rp1 = CUR.GS.rp0; @@ -6352,6 +6681,16 @@ FT_UNUSED_ARG; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode && + CUR.iup_called && + ( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) ) + { + CUR.error = TT_Err_Invalid_Reference; + goto Fail; + } +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + if ( CUR.top < CUR.GS.loop || BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) { @@ -6404,7 +6743,7 @@ a0, a1, b0, b1; - FT_F26Dot6 discriminant; + FT_F26Dot6 discriminant, dotproduct; FT_F26Dot6 dx, dy, dax, day, @@ -6433,6 +6772,8 @@ return; } + /* Cramer's rule */ + dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x; dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y; @@ -6444,15 +6785,25 @@ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH; - discriminant = TT_MULDIV( dax, -dby, 0x40 ) + - TT_MULDIV( day, dbx, 0x40 ); + discriminant = FT_MulDiv( dax, -dby, 0x40 ) + + FT_MulDiv( day, dbx, 0x40 ); + dotproduct = FT_MulDiv( dax, dbx, 0x40 ) + + FT_MulDiv( day, dby, 0x40 ); - if ( FT_ABS( discriminant ) >= 0x40 ) + /* The discriminant above is actually a cross product of vectors */ + /* da and db. Together with the dot product, they can be used as */ + /* surrogates for sine and cosine of the angle between the vectors. */ + /* Indeed, */ + /* dotproduct = |da||db|cos(angle) */ + /* discriminant = |da||db|sin(angle) . */ + /* We use these equations to reject grazing intersections by */ + /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */ + if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) ) { - val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 ); + val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 ); - R.x = TT_MULDIV( val, dax, discriminant ); - R.y = TT_MULDIV( val, day, discriminant ); + R.x = FT_MulDiv( val, dax, discriminant ); + R.y = FT_MulDiv( val, day, discriminant ); CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x; CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y; @@ -6576,9 +6927,9 @@ FT_Vector vec; - vec.x = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x, + vec.x = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x, CUR.metrics.x_scale ); - vec.y = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y, + vec.y = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y, CUR.metrics.y_scale ); old_range = CUR_fast_dualproj( &vec ); @@ -6613,9 +6964,9 @@ FT_Vector vec; - vec.x = TT_MULFIX( CUR.zp2.orus[point].x - orus_base->x, + vec.x = FT_MulFix( CUR.zp2.orus[point].x - orus_base->x, CUR.metrics.x_scale ); - vec.y = TT_MULFIX( CUR.zp2.orus[point].y - orus_base->y, + vec.y = FT_MulFix( CUR.zp2.orus[point].y - orus_base->y, CUR.metrics.y_scale ); org_dist = CUR_fast_dualproj( &vec ); @@ -6625,7 +6976,7 @@ if ( org_dist ) new_dist = ( old_range != 0 ) - ? TT_MULDIV( org_dist, cur_range, old_range ) + ? FT_MulDiv( org_dist, cur_range, old_range ) : cur_dist; else new_dist = 0; @@ -6786,12 +7137,12 @@ if ( !scale_valid ) { scale_valid = 1; - scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ), - 0x10000L, orus2 - orus1 ); + scale = FT_DivFix( org2 + delta2 - ( org1 + delta1 ), + orus2 - orus1 ); } x = ( org1 + delta1 ) + - TT_MULFIX( worker->orus[i].x - orus1, scale ); + FT_MulFix( worker->orus[i].x - orus1, scale ); } worker->curs[i].x = x; } @@ -6846,6 +7197,15 @@ contour = 0; point = 0; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode ) + { + CUR.iup_called = 1; + if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) + return; + } +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + do { end_point = CUR.pts.contours[contour] - CUR.pts.first_point; @@ -6915,6 +7275,9 @@ FT_UShort A; FT_ULong C; FT_Long B; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + FT_UShort B1, B2; +#endif #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING @@ -6988,7 +7351,69 @@ B++; 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 ( CUR.GS.freeVector.y != 0 ) + B1 = CUR.zp0.cur[A].y; + else + B1 = CUR.zp0.cur[A].x; + + /* Standard Subpixel Hinting: Allow y move */ + if ( !CUR.compatibility_mode && CUR.GS.freeVector.y != 0 ) + CUR_Func_move( &CUR.zp0, A, B ); + + /* Compatibility Mode: Allow x or y move if point touched in + Y direction */ + else if ( CUR.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 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.sph_tweak_flags & + SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES ) && + B1 % 64 == 0 && + B2 % 64 != 0 && + !CUR.size->ttfautohinted ) || + ( ( CUR.sph_tweak_flags & + SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && + B1 % 64 != 0 && + B2 % 64 != 0 ) ) ) + CUR_Func_move( &CUR.zp0, A, -B ); + } +#else CUR_Func_move( &CUR.zp0, A, B ); +#endif /* *TT_CONFIG_OPTION_SUBPIXEL_HINTING */ } } else @@ -7118,22 +7543,113 @@ K = 0; - /* We return MS rasterizer version 1.7 for the font scaler. */ - if ( ( args[0] & 1 ) != 0 ) - K = 35; - - /* Has the glyph been rotated? */ +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /********************************/ + /* RASTERIZER VERSION */ + /* Selector Bit: 0 */ + /* Return Bit(s): 0-7 */ + /* */ + if ( ( args[0] & 1 ) != 0 && CUR.ignore_x_mode ) + { + K = CUR.rasterizer_version; +#ifdef SPH_DEBUG_MORE_VERBOSE + printf(" SETTING AS %d\n", CUR.rasterizer_version ); +#endif + } + else +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + if ( ( args[0] & 1 ) != 0 ) + K = 35; + + /********************************/ + /* GLYPH ROTATED */ + /* Selector Bit: 1 */ + /* Return Bit(s): 8 */ + /* */ if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated ) K |= 0x80; - /* Has the glyph been stretched? */ + /********************************/ + /* GLYPH STRETCHED */ + /* Selector Bit: 2 */ + /* Return Bit(s): 9 */ + /* */ if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched ) K |= 1 << 8; - /* Are we hinting for grayscale? */ + /********************************/ + /* HINTING FOR GRAYSCALE */ + /* Selector Bit: 5 */ + /* Return Bit(s): 12 */ + /* */ if ( ( args[0] & 32 ) != 0 && CUR.grayscale ) K |= 1 << 12; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode && CUR.rasterizer_version >= 35 ) + { + /********************************/ + /* HINTING FOR GRAYSCALE */ + /* Selector Bit: 5 */ + /* Return Bit(s): 12 */ + /* */ + if ( ( args[0] & 32 ) != 0 && CUR.grayscale_hinting ) + K |= 1 << 12; + + /********************************/ + /* HINTING FOR SUBPIXEL */ + /* Selector Bit: 6 */ + /* Return Bit(s): 13 */ + /* */ + if ( ( args[0] & 64 ) != 0 && + CUR.subpixel_hinting && + CUR.rasterizer_version >= 37 ) + { + K |= 1 << 13; + + /* the stuff below is irrelevant if subpixel_hinting is not set */ + + /********************************/ + /* COMPATIBLE WIDTHS ENABLED */ + /* Selector Bit: 7 */ + /* Return Bit(s): 14 */ + /* */ + /* Functionality still needs to be added */ + if ( ( args[0] & 128 ) != 0 && CUR.compatible_widths ) + K |= 1 << 14; + + /********************************/ + /* SYMMETRICAL SMOOTHING */ + /* Selector Bit: 8 */ + /* Return Bit(s): 15 */ + /* */ + /* Functionality still needs to be added */ + if ( ( args[0] & 256 ) != 0 && CUR.symmetrical_smoothing ) + K |= 1 << 15; + + /********************************/ + /* HINTING FOR BGR? */ + /* Selector Bit: 9 */ + /* Return Bit(s): 16 */ + /* */ + /* Functionality still needs to be added */ + if ( ( args[0] & 512 ) != 0 && CUR.bgr ) + K |= 1 << 16; + + if ( CUR.rasterizer_version >= 38 ) + { + /********************************/ + /* SUBPIXEL POSITIONED? */ + /* Selector Bit: 10 */ + /* Return Bit(s): 17 */ + /* */ + /* Functionality still needs to be added */ + if ( ( args[0] & 1024 ) != 0 && CUR.subpixel_positioned ) + K |= 1 << 17; + } + } + } +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ args[0] = K; } @@ -7509,6 +8025,11 @@ cur = *exc; #endif +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode ) + CUR.iup_called = FALSE; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + /* set CVT functions */ CUR.tt_metrics.ratio = 0; if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem ) @@ -7780,7 +8301,13 @@ break; case 0x2B: /* CALL */ - Ins_CALL( EXEC_ARG_ args ); +#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 ) ) ) +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + Ins_CALL( EXEC_ARG_ args ); break; case 0x2C: /* FDEF */ @@ -7796,10 +8323,13 @@ Ins_MDAP( EXEC_ARG_ args ); break; - case 0x30: /* IUP */ case 0x31: /* IUP */ - Ins_IUP( EXEC_ARG_ args ); +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( CUR.ignore_x_mode ) + CUR.iup_called = TRUE; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + Ins_IUP( EXEC_ARG_ args ); break; case 0x32: /* SHP */ @@ -7958,7 +8488,13 @@ break; case 0x5D: /* DELTAP1 */ - Ins_DELTAP( EXEC_ARG_ args ); +#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 ) ) ) +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + Ins_DELTAP( EXEC_ARG_ args ); break; case 0x5E: /* SDB */ diff --git a/freetype/src/truetype/ttinterp.h b/freetype/src/truetype/ttinterp.h index 6d0fc03d6..f4336121b 100644 --- a/freetype/src/truetype/ttinterp.h +++ b/freetype/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010 by */ +/* Copyright 1996-2007, 2010, 2012 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -107,6 +107,48 @@ FT_BEGIN_HEADER } TT_CallRec, *TT_CallStack; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + + /*************************************************************************/ + /* */ + /* These structures define rules used to tweak subpixel hinting for */ + /* various fonts. "", 0, "", NULL value indicates to match any value. */ + /* */ + +#define MAX_NAME_SIZE 32 +#define MAX_CLASS_MEMBERS 100 + + typedef struct SPH_TweakRule_ + { + const char family[MAX_NAME_SIZE]; + const FT_UInt ppem; + const char style[MAX_NAME_SIZE]; + const FT_ULong glyph; + + } SPH_TweakRule; + + + typedef struct SPH_ScaleRule_ + { + const char family[MAX_NAME_SIZE]; + const FT_UInt ppem; + const char style[MAX_NAME_SIZE]; + const FT_ULong glyph; + const FT_ULong scale; + + } SPH_ScaleRule; + + + typedef struct Font_Class_ + { + const char name[MAX_NAME_SIZE]; + const char member[MAX_CLASS_MEMBERS][MAX_NAME_SIZE]; + + } Font_Class; + +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + /*************************************************************************/ /* */ /* The main structure for the interpreter which collects all necessary */ @@ -218,12 +260,43 @@ FT_BEGIN_HEADER FT_Bool grayscale; /* are we hinting for grayscale? */ +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + TT_Round_Func func_round_sphn; /* subpixel rounding function */ + + FT_Bool grayscale_hinting; /* Using grayscale hinting? */ + FT_Bool subpixel_hinting; /* Using subpixel hinting? */ + FT_Bool native_hinting; /* Using native hinting? */ + FT_Bool ignore_x_mode; /* Standard rendering mode for */ + /* subpixel hinting. On if gray */ + /* or subpixel hinting is on ) */ + FT_Bool compatibility_mode;/* Additional exceptions to */ + /* native TT rules for legacy */ + /* fonts. Implies */ + /* ignore_x_mode. */ + + /* The following 4 aren't fully implemented but here for MS rasterizer */ + /* compatibility. */ + FT_Bool compatible_widths; /* compatible widths? */ + FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */ + FT_Bool bgr; /* bgr instead of rgb? */ + FT_Bool subpixel_positioned; /* subpixel positioned */ + /* (DirectWrite ClearType)? */ + + FT_Int rasterizer_version; /* MS rasterizer version */ + + FT_Bool iup_called; /* IUP called for glyph? */ + + FT_ULong sph_tweak_flags; /* flags to control */ + /* hint tweaks */ +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + } TT_ExecContextRec; extern const TT_GraphicsState tt_default_graphics_state; +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER FT_LOCAL( FT_Error ) TT_Goto_CodeRange( TT_ExecContext exec, FT_Int range, @@ -246,6 +319,7 @@ FT_BEGIN_HEADER FT_Long multiplier, void* _pbuff, FT_ULong new_max ); +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ /*************************************************************************/ @@ -270,6 +344,8 @@ FT_BEGIN_HEADER FT_EXPORT( TT_ExecContext ) TT_New_Context( TT_Driver driver ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER FT_LOCAL( FT_Error ) TT_Done_Context( TT_ExecContext exec ); @@ -285,6 +361,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) TT_Run_Context( TT_ExecContext exec, FT_Bool debug ); +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ /*************************************************************************/ diff --git a/freetype/src/truetype/ttobjs.c b/freetype/src/truetype/ttobjs.c index 1f8a76891..c61b218c2 100644 --- a/freetype/src/truetype/ttobjs.c +++ b/freetype/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ /* */ /* Objects manager (body). */ /* */ -/* Copyright 1996-2011 */ +/* Copyright 1996-2012 */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -764,7 +764,7 @@ exec->threshold = 0; exec->instruction_trap = FALSE; - exec->F_dot_P = 0x10000L; + exec->F_dot_P = 0x4000L; exec->pedantic_hinting = pedantic; @@ -1190,16 +1190,14 @@ size->ttmetrics.scale = metrics->x_scale; size->ttmetrics.ppem = metrics->x_ppem; size->ttmetrics.x_ratio = 0x10000L; - size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem, - 0x10000L, + size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, metrics->x_ppem ); } else { size->ttmetrics.scale = metrics->y_scale; size->ttmetrics.ppem = metrics->y_ppem; - size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem, - 0x10000L, + size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, metrics->y_ppem ); size->ttmetrics.y_ratio = 0x10000L; } diff --git a/freetype/src/truetype/ttobjs.h b/freetype/src/truetype/ttobjs.h index 47e412910..5c3cb067e 100644 --- a/freetype/src/truetype/ttobjs.h +++ b/freetype/src/truetype/ttobjs.h @@ -173,11 +173,12 @@ FT_BEGIN_HEADER /* */ typedef struct TT_DefRecord_ { - FT_Int range; /* in which code range is it located? */ - FT_Long start; /* where does it start? */ - FT_Long end; /* where does it end? */ - FT_UInt opc; /* function #, or instruction code */ - FT_Bool active; /* is it active? */ + FT_Int range; /* in which code range is it located? */ + FT_Long start; /* where does it start? */ + FT_Long end; /* where does it end? */ + FT_UInt opc; /* function #, or instruction code */ + FT_Bool active; /* is it active? */ + FT_Bool inline_delta; /* is function that defines inline delta? */ } TT_DefRecord, *TT_DefArray; @@ -190,7 +191,7 @@ FT_BEGIN_HEADER { FT_Fixed xx, xy; /* transformation matrix coefficients */ FT_Fixed yx, yy; - FT_F26Dot6 ox, oy; /* offsets */ + FT_F26Dot6 ox, oy; /* offsets */ } TT_Transform; @@ -333,6 +334,7 @@ FT_BEGIN_HEADER FT_Bool bytecode_ready; FT_Bool cvt_ready; + FT_Bool ttfautohinted; #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -427,6 +429,10 @@ FT_BEGIN_HEADER tt_slot_init( FT_GlyphSlot slot ); + /* auxiliary */ +#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) + + FT_END_HEADER #endif /* __TTOBJS_H__ */ diff --git a/freetype/src/truetype/ttpic.c b/freetype/src/truetype/ttpic.c index 65ca845aa..faece4e81 100644 --- a/freetype/src/truetype/ttpic.c +++ b/freetype/src/truetype/ttpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for truetype module. */ /* */ -/* Copyright 2009, 2010 by */ +/* Copyright 2009, 2010, 2012 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -41,11 +41,12 @@ FT_Init_Class_tt_service_truetype_glyf( FT_Service_TTGlyfRec* sv_ttglyf ); + void tt_driver_class_pic_free( FT_Library library ) { FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; + FT_Memory memory = library->memory; if ( pic_container->truetype ) @@ -67,7 +68,7 @@ { FT_PIC_Container* pic_container = &library->pic_container; FT_Error error = TT_Err_Ok; - TTModulePIC* container; + TTModulePIC* container = NULL; FT_Memory memory = library->memory; @@ -77,7 +78,8 @@ FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->truetype = container; - /* initialize pointer table - this is how the module usually expects this data */ + /* initialize pointer table - this is how the module usually */ + /* expects this data */ error = FT_Create_Class_tt_services( library, &container->tt_services ); if ( error ) @@ -88,6 +90,7 @@ #endif FT_Init_Class_tt_service_truetype_glyf( &container->tt_service_truetype_glyf ); + Exit: if ( error ) tt_driver_class_pic_free( library ); diff --git a/freetype/src/truetype/ttpic.h b/freetype/src/truetype/ttpic.h index 48f43a5f9..625c9f169 100644 --- a/freetype/src/truetype/ttpic.h +++ b/freetype/src/truetype/ttpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for truetype module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2012 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,9 +23,10 @@ FT_BEGIN_HEADER #ifndef FT_CONFIG_OPTION_PIC -#define FT_TT_SERVICES_GET tt_services -#define FT_TT_SERVICE_GX_MULTI_MASTERS_GET tt_service_gx_multi_masters -#define FT_TT_SERVICE_TRUETYPE_GLYF_GET tt_service_truetype_glyf + +#define TT_SERVICES_GET tt_services +#define TT_SERVICE_GX_MULTI_MASTERS_GET tt_service_gx_multi_masters +#define TT_SERVICE_TRUETYPE_GLYF_GET tt_service_truetype_glyf #else /* FT_CONFIG_OPTION_PIC */ @@ -33,19 +34,27 @@ FT_BEGIN_HEADER #include FT_SERVICE_MULTIPLE_MASTERS_H #include FT_SERVICE_TRUETYPE_GLYF_H - typedef struct TTModulePIC_ + + typedef struct TTModulePIC_ { - FT_ServiceDescRec* tt_services; + FT_ServiceDescRec* tt_services; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Service_MultiMastersRec tt_service_gx_multi_masters; #endif - FT_Service_TTGlyfRec tt_service_truetype_glyf; + FT_Service_TTGlyfRec tt_service_truetype_glyf; + } TTModulePIC; -#define GET_PIC(lib) ((TTModulePIC*)((lib)->pic_container.truetype)) -#define FT_TT_SERVICES_GET (GET_PIC(library)->tt_services) -#define FT_TT_SERVICE_GX_MULTI_MASTERS_GET (GET_PIC(library)->tt_service_gx_multi_masters) -#define FT_TT_SERVICE_TRUETYPE_GLYF_GET (GET_PIC(library)->tt_service_truetype_glyf) + +#define GET_PIC( lib ) \ + ( (TTModulePIC*)((lib)->pic_container.truetype) ) +#define TT_SERVICES_GET \ + ( GET_PIC( library )->tt_services ) +#define TT_SERVICE_GX_MULTI_MASTERS_GET \ + ( GET_PIC( library )->tt_service_gx_multi_masters ) +#define TT_SERVICE_TRUETYPE_GLYF_GET \ + ( GET_PIC( library )->tt_service_truetype_glyf ) + /* see ttpic.c for the implementation */ void diff --git a/freetype/src/truetype/ttsubpix.c b/freetype/src/truetype/ttsubpix.c new file mode 100644 index 000000000..d09d3d89d --- /dev/null +++ b/freetype/src/truetype/ttsubpix.c @@ -0,0 +1,265 @@ +/***************************************************************************/ +/* */ +/* ttsubpix.c */ +/* */ +/* TrueType Subpixel Hinting. */ +/* */ +/* Copyright 2010-2012 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. */ +/* */ +/***************************************************************************/ + +#include +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_SFNT_H +#include FT_TRUETYPE_TAGS_H +#include FT_OUTLINE_H + +#include "ttsubpix.h" + + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + + FT_LOCAL_DEF( FT_Bool ) + is_member_of_family_class( const FT_String* detected_font_name, + const FT_String* rule_font_name ) + { + FT_UInt i, j; + + + /* Does font name match rule family? */ + if ( strcmp( detected_font_name, rule_font_name ) == 0 ) + return TRUE; + + /* Is font name a wildcard ""? */ + if ( strcmp( rule_font_name, "" ) == 0 ) + return TRUE; + + /* Is font name contained in a class list? */ + for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ ) + { + if ( strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) + { + for ( j = 0; j < MAX_CLASS_MEMBERS; j++ ) + { + if ( strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) + continue; + if ( strcmp( FAMILY_CLASS_Rules[i].member[j], + detected_font_name ) == 0 ) + return TRUE; + } + } + } + + return FALSE; + } + + + FT_LOCAL_DEF( FT_Bool ) + is_member_of_style_class( const FT_String* detected_font_style, + const FT_String* rule_font_style ) + { + FT_UInt i, j; + + + /* Does font style match rule style? */ + if ( strcmp( detected_font_style, rule_font_style ) == 0 ) + return TRUE; + + /* Is font style a wildcard ""? */ + if ( strcmp( rule_font_style, "" ) == 0 ) + return TRUE; + + /* Is font style contained in a class list? */ + for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ ) + { + if ( strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) + { + for ( j = 0; j < MAX_CLASS_MEMBERS; j++ ) + { + if ( strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) + continue; + if ( strcmp( STYLE_CLASS_Rules[i].member[j], + detected_font_style ) == 0 ) + return TRUE; + } + } + } + + return FALSE; + } + + + FT_LOCAL_DEF( FT_Bool ) + sph_test_tweak( TT_Face face, + FT_String* family, + FT_UInt ppem, + FT_String* style, + FT_UInt glyph_index, + SPH_TweakRule* rule, + FT_UInt num_rules ) + { + FT_UInt i; + + + /* rule checks may be able to be optimized further */ + for ( i = 0; i < num_rules; i++ ) + { + if ( family && + ( is_member_of_family_class ( family, rule[i].family ) ) ) + if ( rule[i].ppem == 0 || + rule[i].ppem == ppem ) + if ( style && + is_member_of_style_class ( style, rule[i].style ) ) + if ( rule[i].glyph == 0 || + FT_Get_Char_Index( (FT_Face)face, + rule[i].glyph ) == glyph_index ) + return TRUE; + } + + return FALSE; + } + + + FT_LOCAL_DEF( FT_UInt ) + scale_test_tweak( TT_Face face, + FT_String* family, + FT_UInt ppem, + FT_String* style, + FT_UInt glyph_index, + SPH_ScaleRule* rule, + FT_UInt num_rules ) + { + FT_UInt i; + + + /* rule checks may be able to be optimized further */ + for ( i = 0; i < num_rules; i++ ) + { + if ( family && + ( is_member_of_family_class ( family, rule[i].family ) ) ) + if ( rule[i].ppem == 0 || + rule[i].ppem == ppem ) + if ( style && + is_member_of_style_class( style, rule[i].style ) ) + if ( rule[i].glyph == 0 || + FT_Get_Char_Index( (FT_Face)face, + rule[i].glyph ) == glyph_index ) + return rule[i].scale; + } + + return 1000; + } + + +#define TWEAK_RULES( x ) \ + if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ + x##_Rules, x##_RULES_SIZE ) ) \ + loader->exec->sph_tweak_flags |= SPH_TWEAK_##x; + +#define TWEAK_RULES_EXCEPTIONS( x ) \ + if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ + x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \ + loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x; + + + FT_LOCAL_DEF( void ) + sph_set_tweaks( TT_Loader loader, + FT_UInt glyph_index ) + { + TT_Face face = (TT_Face)loader->face; + FT_String* family = face->root.family_name; + int ppem = loader->size->metrics.x_ppem; + FT_String* style = face->root.style_name; + + + /* don't apply rules if style isn't set */ + if ( !face->root.style_name ) + return; + +#ifdef SPH_DEBUG_MORE_VERBOSE + printf( "%s,%d,%s,%c=%d ", + family, ppem, style, glyph_index, glyph_index ); +#endif + + TWEAK_RULES( PIXEL_HINTING ); + + if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING ) + { + loader->exec->ignore_x_mode = FALSE; + return; + } + + TWEAK_RULES( ALLOW_X_DMOVE ); + TWEAK_RULES( ALLOW_X_DMOVEX ); + TWEAK_RULES( ALLOW_X_MOVE_ZP2 ); + TWEAK_RULES( ALWAYS_DO_DELTAP ); + TWEAK_RULES( ALWAYS_SKIP_DELTAP ); + TWEAK_RULES( DEEMBOLDEN ); + TWEAK_RULES( DELTAP_SKIP_EXAGGERATED_VALUES ); + TWEAK_RULES( DO_SHPIX ); + TWEAK_RULES( EMBOLDEN ); + TWEAK_RULES( MIAP_HACK ); + TWEAK_RULES( NORMAL_ROUND ); + TWEAK_RULES( NO_ALIGNRP_AFTER_IUP ); + TWEAK_RULES( NO_CALL_AFTER_IUP ); + TWEAK_RULES( NO_DELTAP_AFTER_IUP ); + TWEAK_RULES( RASTERIZER_35 ); + TWEAK_RULES( SKIP_INLINE_DELTAS ); + TWEAK_RULES( SKIP_IUP ); + TWEAK_RULES( MIRP_CVT_ZERO ); + + TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES ); + TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES ); + + TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES ); + TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES ); + + TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES ); + TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES ); + + if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) + loader->exec->rasterizer_version = 35; + else + loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; + + /* re-execute fpgm always to avoid problems */ + loader->exec->size->cvt_ready = FALSE; + tt_size_ready_bytecode( loader->exec->size, + FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); + + if ( IS_HINTED( loader->load_flags ) ) + { + TWEAK_RULES( TIMES_NEW_ROMAN_HACK ); + TWEAK_RULES( COURIER_NEW_2_HACK ); + } + + if ( sph_test_tweak( face, family, ppem, style, glyph_index, + COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) ) + { + loader->exec->compatibility_mode |= TRUE; + loader->exec->ignore_x_mode |= TRUE; + } + else + loader->exec->compatibility_mode &= FALSE; + + if ( IS_HINTED( loader->load_flags ) ) + { + if ( sph_test_tweak( face, family, ppem, style, glyph_index, + COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) ) + loader->exec->compatible_widths |= TRUE; + } + } + +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + +/* END */ diff --git a/freetype/src/truetype/ttsubpix.h b/freetype/src/truetype/ttsubpix.h new file mode 100644 index 000000000..2fbff2681 --- /dev/null +++ b/freetype/src/truetype/ttsubpix.h @@ -0,0 +1,908 @@ +/***************************************************************************/ +/* */ +/* ttsubpix.h */ +/* */ +/* TrueType Subpixel Hinting. */ +/* */ +/* Copyright 2010-2012 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 __TTSUBPIX_H__ +#define __TTSUBPIX_H__ + +#include +#include "ttobjs.h" +#include "ttinterp.h" + + +FT_BEGIN_HEADER + + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + + /*************************************************************************/ + /* */ + /* Tweak flags that are set for each glyph by the below rules. */ + /* */ + /* */ +#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001 +#define SPH_TWEAK_ALLOW_X_DMOVEX 0x0000002 +#define SPH_TWEAK_ALLOW_X_MOVE_ZP2 0x0000004 +#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000008 +#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000010 +#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000020 +#define SPH_TWEAK_DEEMBOLDEN 0x0000040 +#define SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES 0x0000080 +#define SPH_TWEAK_DO_SHPIX 0x0000100 +#define SPH_TWEAK_EMBOLDEN 0x0000200 +#define SPH_TWEAK_MIAP_HACK 0x0000400 +#define SPH_TWEAK_NORMAL_ROUND 0x0000800 +#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0001000 +#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0002000 +#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0004000 +#define SPH_TWEAK_PIXEL_HINTING 0x0008000 +#define SPH_TWEAK_RASTERIZER_35 0x0010000 +#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0020000 +#define SPH_TWEAK_SKIP_INLINE_DELTAS 0x0040000 +#define SPH_TWEAK_SKIP_IUP 0x0080000 +#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0100000 +#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0200000 +#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0400000 +#define SPH_TWEAK_MIRP_CVT_ZERO 0x0800000 + + + FT_LOCAL( FT_Bool ) + sph_test_tweak( TT_Face face, + FT_String* family, + FT_UInt ppem, + FT_String* style, + FT_UInt glyph_index, + SPH_TweakRule* rule, + FT_UInt num_rules ); + + FT_LOCAL_DEF( FT_UInt ) + scale_test_tweak( TT_Face face, + FT_String* family, + FT_UInt ppem, + FT_String* style, + FT_UInt glyph_index, + SPH_ScaleRule* rule, + FT_UInt num_rules ); + + FT_LOCAL( void ) + sph_set_tweaks( TT_Loader loader, + FT_UInt glyph_index ); + + + /*************************************************************************/ + /* */ + /* These rules affect how the TT Interpreter does hinting, with the */ + /* goal of doing subpixel hinting by (in general) ignoring x moves. */ + /* Some of these rules are fixes that go above and beyond the */ + /* stated techniques in the MS whitepaper on Cleartype, due to */ + /* artifacts in many glyphs. So, these rules make some glyphs render */ + /* better than they do in the MS rasterizer. */ + /* */ + /* "" string or 0 int/char indicates to apply to all glyphs. */ + /* "-" used as dummy placeholders, but any non-matching string works. */ + /* */ + /* Some of this could arguably be implemented in fontconfig, however: */ + /* */ + /* - Fontconfig can't set things on a glyph-by-glyph basis. */ + /* - The tweaks that happen here are very low-level, from an average */ + /* user's point of view and are best implemented in the hinter. */ + /* */ + /* The goal is to make the subpixel hinting techniques as generalized */ + /* as possible across all fonts to prevent the need for extra rules such */ + /* as these. */ + /* */ + /* The rule structure is designed so that entirely new rules can easily */ + /* be added when a new compatibility feature is discovered. */ + /* */ + /* The rule structures could also use some enhancement to handle ranges. */ + /* */ + /* ****************** WORK IN PROGRESS ******************* */ + /* */ + + /* These macros are defined absent a method for setting them */ +#define SPH_OPTION_BITMAP_WIDTHS FALSE +#define SPH_OPTION_SET_SUBPIXEL TRUE +#define SPH_OPTION_SET_GRAYSCALE FALSE +#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE +#define SPH_OPTION_SET_RASTERIZER_VERSION 38 + + + /* Define this to force natural (i.e. not bitmap-compatible) widths. */ + /* The default leans strongly towards natural widths except for a few */ + /* legacy fonts where a selective combination produces nicer results. */ +/* #define FORCE_NATURAL_WIDTHS */ + + + /* These are `classes' of fonts that can be grouped together and used in */ + /* rules below. A blank entry "" is required at the end of these! */ +#define FAMILY_CLASS_RULES_SIZE 7 + + Font_Class FAMILY_CLASS_Rules + [FAMILY_CLASS_RULES_SIZE] = + { + { "MS Legacy Fonts", + { "Aharoni", + "Andale Mono", + "Andalus", + "Angsana New", + "AngsanaUPC", + "Arabic Transparent", + "Arial Black", + "Arial Narrow", + "Arial Unicode MS", + "Arial", + "Batang", + "Browallia New", + "BrowalliaUPC", + "Comic Sans MS", + "Cordia New", + "CordiaUPC", + "Courier New", + "DFKai-SB", + "David Transparent", + "David", + "DilleniaUPC", + "Estrangelo Edessa", + "EucrosiaUPC", + "FangSong_GB2312", + "Fixed Miriam Transparent", + "FrankRuehl", + "Franklin Gothic Medium", + "FreesiaUPC", + "Garamond", + "Gautami", + "Georgia", + "Gulim", + "Impact", + "IrisUPC", + "JasmineUPC", + "KaiTi_GB2312", + "KodchiangUPC", + "Latha", + "Levenim MT", + "LilyUPC", + "Lucida Console", + "Lucida Sans Unicode", + "MS Gothic", + "MS Mincho", + "MV Boli", + "Mangal", + "Marlett", + "Microsoft Sans Serif", + "Mingliu", + "Miriam Fixed", + "Miriam Transparent", + "Miriam", + "Narkisim", + "Palatino Linotype", + "Raavi", + "Rod Transparent", + "Rod", + "Shruti", + "SimHei", + "Simplified Arabic Fixed", + "Simplified Arabic", + "Simsun", + "Sylfaen", + "Symbol", + "Tahoma", + "Times New Roman", + "Traditional Arabic", + "Trebuchet MS", + "Tunga", + "Verdana", + "Webdings", + "Wingdings", + "", + }, + }, + { "Core MS Legacy Fonts", + { "Arial Black", + "Arial Narrow", + "Arial Unicode MS", + "Arial", + "Comic Sans MS", + "Courier New", + "Garamond", + "Georgia", + "Impact", + "Lucida Console", + "Lucida Sans Unicode", + "Microsoft Sans Serif", + "Palatino Linotype", + "Tahoma", + "Times New Roman", + "Trebuchet MS", + "Verdana", + "", + }, + }, + { "Apple Legacy Fonts", + { "Geneva", + "Times", + "Monaco", + "Century", + "Chalkboard", + "Lobster", + "Century Gothic", + "Optima", + "Lucida Grande", + "Gill Sans", + "Baskerville", + "Helvetica", + "Helvetica Neue", + "", + }, + }, + { "Legacy Sans Fonts", + { "Andale Mono", + "Arial Unicode MS", + "Arial", + "Century Gothic", + "Comic Sans MS", + "Franklin Gothic Medium", + "Geneva", + "Lucida Console", + "Lucida Grande", + "Lucida Sans Unicode", + "Lucida Sans Typewriter", + "Microsoft Sans Serif", + "Monaco", + "Tahoma", + "Trebuchet MS", + "Verdana", + "", + }, + }, + + { "Misc Legacy Fonts", + { "Dark Courier", "", }, }, + { "Verdana Clones", + { "DejaVu Sans", + "Bitstream Vera Sans", "", }, }, + { "Verdana and Clones", + { "DejaVu Sans", + "Bitstream Vera Sans", + "Verdana", "", }, }, + }; + + + /* Define `classes' of styles that can be grouped together and used in */ + /* rules below. A blank entry "" is required at the end of these! */ +#define STYLE_CLASS_RULES_SIZE 5 + + Font_Class STYLE_CLASS_Rules + [STYLE_CLASS_RULES_SIZE] = + { + { "Regular Class", + { "Regular", + "Book", + "Medium", + "Roman", + "Normal", + "", + }, + }, + { "Regular/Italic Class", + { "Regular", + "Book", + "Medium", + "Italic", + "Oblique", + "Roman", + "Normal", + "", + }, + }, + { "Bold/BoldItalic Class", + { "Bold", + "Bold Italic", + "Black", + "", + }, + }, + { "Bold/Italic/BoldItalic Class", + { "Bold", + "Bold Italic", + "Black", + "Italic", + "Oblique", + "", + }, + }, + { "Regular/Bold Class", + { "Regular", + "Book", + "Medium", + "Normal", + "Roman", + "Bold", + "Black", + "", + }, + }, + }; + + + /* Special fixes for known legacy fonts; */ + /* this is the primary workhorse rule for legacy fonts */ +#define COMPATIBILITY_MODE_RULES_SIZE 4 + + SPH_TweakRule COMPATIBILITY_MODE_Rules + [COMPATIBILITY_MODE_RULES_SIZE] = + { + { "MS Legacy Fonts", 0, "", 0 }, + { "Apple Legacy Fonts", 0, "", 0 }, + { "Misc Legacy Fonts", 0, "", 0 }, + { "Verdana Clones", 0, "", 0 }, + }; + + + /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */ +#define PIXEL_HINTING_RULES_SIZE 4 + + SPH_TweakRule PIXEL_HINTING_Rules + [PIXEL_HINTING_RULES_SIZE] = + { + /* these characters are almost always safe */ + { "", 0, "", '<' }, + { "", 0, "", '>' }, + /* fixes the vanishing stem */ + { "Times New Roman", 0, "Bold", 'A' }, + { "Times New Roman", 0, "Bold", 'V' }, + }; + + + /* According to Greg Hitchcock and the MS whitepaper, this should work */ + /* on all legacy MS fonts, but creates artifacts with some. Only using */ + /* where absolutely necessary. */ +#define SKIP_INLINE_DELTAS_RULES_SIZE 1 + + SPH_TweakRule SKIP_INLINE_DELTAS_Rules + [SKIP_INLINE_DELTAS_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */ +#define DO_SHPIX_RULES_SIZE 1 + + SPH_TweakRule DO_SHPIX_Rules + [DO_SHPIX_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Skip Y moves that start with a point that is not on a Y pixel */ + /* boundary and don't move that point to a Y pixel boundary. */ +#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 10 + + SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules + [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] = + { + /* fix vwxyz thinness*/ + { "Consolas", 0, "Regular", 0 }, + /* fix tiny gap at top of m */ + { "Arial", 0, "Regular", 'm' }, + /* Fix thin middle stems */ + { "Core MS Legacy Fonts", 0, "Regular/Bold Class", 'N' }, + { "Lucida Grande", 0, "", 'N' }, + { "Lucida Grande", 0, "Bold", 'y' }, + /* Cyrillic small letter I */ + { "Legacy Sans Fonts", 0, "", 0x438 }, + { "Verdana Clones", 0, "",'N' }, + { "Ubuntu", 0, "Regular Class", 'N' }, + /* Fix misshapen x */ + { "Verdana", 0, "Bold", 'x' }, + /* Fix misshapen s */ + { "Tahoma", 0, "", 's' }, + }; + + +#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 6 + + SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions + [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = + { + { "Tahoma", 0, "", 'N' }, + { "Comic Sans MS", 0, "", 'N' }, + { "Verdana", 0, "Regular/Bold Class", 'N' }, + { "Verdana", 11, "Bold", 'x' }, + /* Cyrillic small letter I */ + { "Arial", 0, "", 0x438 }, + { "Trebuchet MS", 0, "Bold", 0 }, + }; + + + /* Skip Y moves that move a point off a Y pixel boundary. */ + /* This fixes Tahoma, Trebuchet oddities and some issues with `$'. */ +#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 5 + + SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules + [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] = + { + { "MS Legacy Fonts", 0, "", 0 }, + { "Apple Legacy Fonts", 0, "", 0 }, + { "Misc Legacy Fonts", 0, "", 0 }, + { "Ubuntu", 0, "Regular Class", 0 }, + { "Verdana Clones", 0, "", 0 }, + }; + + +#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 + + SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions + [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Round moves that don't move a point to a Y pixel boundary. */ +#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 3 + + SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules + [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] = + { + /* Droid font instructions don't snap Y to pixels */ + { "Droid Sans", 0, "Regular/Italic Class", 0 }, + { "Droid Sans Mono", 0, "", 0 }, + { "Ubuntu", 0, "", 0 }, + }; + + +#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 3 + + SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions + [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = + { + { "Droid Sans", 12, "Bold", 0 }, + { "Droid Sans", 13, "Bold", 0 }, + { "Droid Sans", 16, "Bold", 0 }, + }; + + + /* Allow a Direct_Move_X along X freedom vector if matched. */ +#define ALLOW_X_DMOVEX_RULES_SIZE 1 + + SPH_TweakRule ALLOW_X_DMOVEX_Rules + [ALLOW_X_DMOVEX_RULES_SIZE] = + { + { "-", 0, "Regular", 0 }, + }; + + + /* Allow a Direct_Move along X freedom vector if matched. */ +#define ALLOW_X_DMOVE_RULES_SIZE 1 + + SPH_TweakRule ALLOW_X_DMOVE_Rules + [ALLOW_X_DMOVE_RULES_SIZE] = + { + /* Fixes vanishing diagonal in 4 */ + { "Verdana", 0, "Regular", '4' }, + }; + + + /* Allow a ZP2 move along freedom vector if matched; */ + /* This is called from SHP, SHPIX, SHC, SHZ. */ +#define ALLOW_X_MOVE_ZP2_RULES_SIZE 1 + + SPH_TweakRule ALLOW_X_MOVE_ZP2_Rules + [ALLOW_X_MOVE_ZP2_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Return MS rasterizer version 35 if matched. */ +#define RASTERIZER_35_RULES_SIZE 8 + + SPH_TweakRule RASTERIZER_35_Rules + [RASTERIZER_35_RULES_SIZE] = + { + /* This seems to be the only way to make these look good */ + { "Times New Roman", 0, "Regular", 'i' }, + { "Times New Roman", 0, "Regular", 'j' }, + { "Times New Roman", 0, "Regular", 'm' }, + { "Times New Roman", 0, "Regular", 'r' }, + { "Times New Roman", 0, "Regular", 'a' }, + { "Times New Roman", 0, "Regular", 'n' }, + { "Times New Roman", 0, "Regular", 'p' }, + { "Times", 0, "", 0 }, + }; + + + /* Don't round to the subpixel grid. Round to pixel grid. */ +#define NORMAL_ROUND_RULES_SIZE 2 + + SPH_TweakRule NORMAL_ROUND_Rules + [NORMAL_ROUND_RULES_SIZE] = + { + /* Fix point "explosions" */ + { "Courier New", 0, "", 0 }, + { "Verdana", 10, "Regular", '4' }, + }; + + + /* Skip IUP instructions if matched. */ +#define SKIP_IUP_RULES_SIZE 1 + + SPH_TweakRule SKIP_IUP_Rules + [SKIP_IUP_RULES_SIZE] = + { + { "Arial", 13, "Regular", 'a' }, + }; + + + /* Skip MIAP Twilight hack if matched. */ +#define MIAP_HACK_RULES_SIZE 1 + + SPH_TweakRule MIAP_HACK_Rules + [MIAP_HACK_RULES_SIZE] = + { + { "Geneva", 12, "", 0 }, + }; + + + /* Skip DELTAP instructions if matched. */ +#define ALWAYS_SKIP_DELTAP_RULES_SIZE 16 + + SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules + [ALWAYS_SKIP_DELTAP_RULES_SIZE] = + { + { "Georgia", 0, "Regular", 'k' }, + /* fixes problems with W M w */ + { "Trebuchet MS", 0, "Italic", 0 }, + /* fix various problems with e in different versions */ + { "Trebuchet MS", 14, "Regular", 'e' }, + { "Trebuchet MS", 13, "Regular", 'e' }, + { "Trebuchet MS", 15, "Regular", 'e' }, + { "Arial", 11, "Regular", 's' }, + { "Verdana", 10, "Regular", 0 }, + { "Verdana", 9, "Regular", 0 }, + /* Cyrillic small letter short I */ + { "Legacy Sans Fonts", 0, "", 0x438 }, + { "Legacy Sans Fonts", 0, "", 0x439 }, + { "Arial", 10, "Regular", '6' }, + { "Arial", 0, "Bold/BoldItalic Class", 'a' }, + /* Make horizontal stems consistent with the rest */ + { "Arial", 24, "Bold", 's' }, + { "Arial", 25, "Bold", 's' }, + { "Arial", 24, "Bold", 'a' }, + { "Arial", 25, "Bold", 'a' }, + }; + + + /* Always do DELTAP instructions if matched. */ +#define ALWAYS_DO_DELTAP_RULES_SIZE 2 + + SPH_TweakRule ALWAYS_DO_DELTAP_Rules + [ALWAYS_DO_DELTAP_RULES_SIZE] = + { + { "Verdana Clones", 17, "Regular Class", 'K' }, + { "Verdana Clones", 17, "Regular Class", 'k' }, + }; + + + /* Do an extra RTG instruction in DELTAP if matched. */ +#define DELTAP_RTG_RULES_SIZE 1 + + SPH_TweakRule DELTAP_RTG_Rules + [DELTAP_RTG_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Force CVT distance to zero in MIRP. */ +#define MIRP_CVT_ZERO_RULES_SIZE 1 + + SPH_TweakRule MIRP_CVT_ZERO_Rules + [MIRP_CVT_ZERO_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Skip moves that meet or exceed 1 pixel. */ +#define DELTAP_SKIP_EXAGGERATED_VALUES_RULES_SIZE 1 + + SPH_TweakRule DELTAP_SKIP_EXAGGERATED_VALUES_Rules + [DELTAP_SKIP_EXAGGERATED_VALUES_RULES_SIZE] = + { + /* Fix vanishing stems */ + { "Ubuntu", 0, "Regular", 'M' }, + }; + + + /* Don't allow ALIGNRP after IUP. */ +#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 4 + + SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules + [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] = + { + /* Prevent creation of dents in outline */ + { "Courier New", 0, "Bold", 'C' }, + { "Courier New", 0, "Bold", 'D' }, + { "Courier New", 0, "Bold", 'Q' }, + { "Courier New", 0, "Bold", '0' }, + }; + + + /* Don't allow DELTAP after IUP. */ +#define NO_DELTAP_AFTER_IUP_RULES_SIZE 2 + + SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules + [NO_DELTAP_AFTER_IUP_RULES_SIZE] = + { + { "Arial", 0, "Bold", 'N' }, + { "Verdana", 0, "Regular", '4' }, + }; + + + /* Don't allow CALL after IUP. */ +#define NO_CALL_AFTER_IUP_RULES_SIZE 4 + + SPH_TweakRule NO_CALL_AFTER_IUP_Rules + [NO_CALL_AFTER_IUP_RULES_SIZE] = + { + /* Prevent creation of dents in outline */ + { "Courier New", 0, "Bold", 'O' }, + { "Courier New", 0, "Bold", 'Q' }, + { "Courier New", 0, "Bold", 'k' }, + { "Courier New", 0, "Bold Italic", 'M' }, + }; + + + /* De-embolden these glyphs slightly. */ +#define DEEMBOLDEN_RULES_SIZE 9 + + SPH_TweakRule DEEMBOLDEN_Rules + [DEEMBOLDEN_RULES_SIZE] = + { + { "Courier New", 0, "Bold", 'A' }, + { "Courier New", 0, "Bold", 'W' }, + { "Courier New", 0, "Bold", 'w' }, + { "Courier New", 0, "Bold", 'M' }, + { "Courier New", 0, "Bold", 'X' }, + { "Courier New", 0, "Bold", 'K' }, + { "Courier New", 0, "Bold", 'x' }, + { "Courier New", 0, "Bold", 'z' }, + { "Courier New", 0, "Bold", 'v' }, + }; + + + /* Embolden these glyphs slightly. */ +#define EMBOLDEN_RULES_SIZE 5 + + SPH_TweakRule EMBOLDEN_Rules + [EMBOLDEN_RULES_SIZE] = + { + { "Courier New", 12, "Italic", 'z' }, + { "Courier New", 11, "Italic", 'z' }, + { "Courier New", 10, "Italic", 'z' }, + { "Courier New", 0, "Regular", 0 }, + { "Courier New", 0, "Italic", 0 }, + }; + + + /* Do an extra RDTG instruction in DELTAP if matched. */ +#define DELTAP_RDTG_RULES_SIZE 1 + + SPH_TweakRule DELTAP_RDTG_Rules + [DELTAP_RDTG_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */ + /* similar to Windows XP. */ +#define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12 + + SPH_TweakRule TIMES_NEW_ROMAN_HACK_Rules + [TIMES_NEW_ROMAN_HACK_RULES_SIZE] = + { + { "Times New Roman", 16, "Italic", '2' }, + { "Times New Roman", 16, "Italic", '5' }, + { "Times New Roman", 16, "Italic", '7' }, + { "Times New Roman", 16, "Regular", '2' }, + { "Times New Roman", 16, "Regular", '5' }, + { "Times New Roman", 16, "Regular", '7' }, + { "Times New Roman", 17, "Italic", '2' }, + { "Times New Roman", 17, "Italic", '5' }, + { "Times New Roman", 17, "Italic", '7' }, + { "Times New Roman", 17, "Regular", '2' }, + { "Times New Roman", 17, "Regular", '5' }, + { "Times New Roman", 17, "Regular", '7' }, + }; + + + /* This fudges distance on 2 to get rid of the vanishing stem issue. */ + /* A real solution to this is certainly welcome. */ +#define COURIER_NEW_2_HACK_RULES_SIZE 15 + + SPH_TweakRule COURIER_NEW_2_HACK_Rules + [COURIER_NEW_2_HACK_RULES_SIZE] = + { + { "Courier New", 10, "Regular", '2' }, + { "Courier New", 11, "Regular", '2' }, + { "Courier New", 12, "Regular", '2' }, + { "Courier New", 13, "Regular", '2' }, + { "Courier New", 14, "Regular", '2' }, + { "Courier New", 15, "Regular", '2' }, + { "Courier New", 16, "Regular", '2' }, + { "Courier New", 17, "Regular", '2' }, + { "Courier New", 18, "Regular", '2' }, + { "Courier New", 19, "Regular", '2' }, + { "Courier New", 20, "Regular", '2' }, + { "Courier New", 21, "Regular", '2' }, + { "Courier New", 22, "Regular", '2' }, + { "Courier New", 23, "Regular", '2' }, + { "Courier New", 24, "Regular", '2' }, + }; + + +#ifndef FORCE_NATURAL_WIDTHS + + /* Use compatible widths with these glyphs. Compatible widths is always */ + /* on when doing B/W TrueType instructing, but is used selectively here, */ + /* typically on glyphs with 3 or more vertical stems. */ +#define COMPATIBLE_WIDTHS_RULES_SIZE 38 + + SPH_TweakRule COMPATIBLE_WIDTHS_Rules + [COMPATIBLE_WIDTHS_RULES_SIZE] = + { + { "Arial Unicode MS", 12, "Regular Class", 'm' }, + { "Arial Unicode MS", 14, "Regular Class", 'm' }, + /* Cyrillic small letter sha */ + { "Arial", 10, "Regular Class", 0x448 }, + { "Arial", 11, "Regular Class", 'm' }, + { "Arial", 12, "Regular Class", 'm' }, + /* Cyrillic small letter sha */ + { "Arial", 12, "Regular Class", 0x448 }, + { "Arial", 13, "Regular Class", 0x448 }, + { "Arial", 14, "Regular Class", 'm' }, + /* Cyrillic small letter sha */ + { "Arial", 14, "Regular Class", 0x448 }, + { "Arial", 15, "Regular Class", 0x448 }, + { "Arial", 17, "Regular Class", 'm' }, + { "DejaVu Sans", 15, "Regular Class", 0 }, + { "Microsoft Sans Serif", 11, "Regular Class", 0 }, + { "Microsoft Sans Serif", 12, "Regular Class", 0 }, + { "Segoe UI", 11, "Regular Class", 0 }, + { "Monaco", 0, "Regular Class", 0 }, + { "Segoe UI", 12, "Regular Class", 'm' }, + { "Segoe UI", 14, "Regular Class", 'm' }, + { "Tahoma", 11, "Regular Class", 0 }, + { "Times New Roman", 16, "Regular Class", 'c' }, + { "Times New Roman", 16, "Regular Class", 'm' }, + { "Times New Roman", 16, "Regular Class", 'o' }, + { "Times New Roman", 16, "Regular Class", 'w' }, + { "Trebuchet MS", 11, "Regular Class", 0 }, + { "Trebuchet MS", 12, "Regular Class", 0 }, + { "Trebuchet MS", 14, "Regular Class", 0 }, + { "Trebuchet MS", 15, "Regular Class", 0 }, + { "Ubuntu", 12, "Regular Class", 'm' }, + /* Cyrillic small letter sha */ + { "Verdana", 10, "Regular Class", 0x448 }, + { "Verdana", 11, "Regular Class", 0x448 }, + { "Verdana and Clones", 12, "Regular Class", 'i' }, + { "Verdana and Clones", 12, "Regular Class", 'j' }, + { "Verdana and Clones", 12, "Regular Class", 'l' }, + { "Verdana and Clones", 12, "Regular Class", 'm' }, + { "Verdana and Clones", 13, "Regular Class", 'i' }, + { "Verdana and Clones", 13, "Regular Class", 'j' }, + { "Verdana and Clones", 13, "Regular Class", 'l' }, + { "Verdana and Clones", 14, "Regular Class", 'm' }, + }; + + + /* Scaling slightly in the x-direction prior to hinting results in */ + /* more visually pleasing glyphs in certain cases. */ + /* This sometimes needs to be coordinated with compatible width rules. */ + /* A value of 1000 corresponds to a scaled value of 1.0. */ +#define X_SCALING_RULES_SIZE 50 + + SPH_ScaleRule X_SCALING_Rules + [X_SCALING_RULES_SIZE] = + { + { "DejaVu Sans", 12, "Regular Class", 'm', 950 }, + { "Verdana and Clones", 12, "Regular Class", 'a', 1100 }, + { "Verdana and Clones", 13, "Regular Class", 'a', 1050 }, + { "Arial", 11, "Regular Class", 'm', 975 }, + { "Arial", 12, "Regular Class", 'm', 1050 }, + /* Cyrillic small letter el */ + { "Arial", 13, "Regular Class", 0x43B, 950 }, + { "Arial", 13, "Regular Class", 'o', 950 }, + { "Arial", 13, "Regular Class", 'e', 950 }, + { "Arial", 14, "Regular Class", 'm', 950 }, + /* Cyrillic small letter el */ + { "Arial", 15, "Regular Class", 0x43B, 925 }, + { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 }, + { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 }, + { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 }, + { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 }, + { "DejaVu Sans", 12, "Regular Class", 'l', 975 }, + { "DejaVu Sans", 12, "Regular Class", 'i', 975 }, + { "DejaVu Sans", 12, "Regular Class", 'j', 975 }, + { "DejaVu Sans", 13, "Regular Class", 'l', 950 }, + { "DejaVu Sans", 13, "Regular Class", 'i', 950 }, + { "DejaVu Sans", 13, "Regular Class", 'j', 950 }, + { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 }, + { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 }, + { "Georgia", 10, "", 0, 1050 }, + { "Georgia", 11, "", 0, 1100 }, + { "Georgia", 12, "", 0, 1025 }, + { "Georgia", 13, "", 0, 1050 }, + { "Georgia", 16, "", 0, 1050 }, + { "Georgia", 17, "", 0, 1030 }, + { "Liberation Sans", 12, "Regular Class", 'm', 1100 }, + { "Lucida Grande", 11, "Regular Class", 'm', 1100 }, + { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 }, + { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 }, + { "Segoe UI", 12, "Regular Class", 'H', 1050 }, + { "Segoe UI", 12, "Regular Class", 'm', 1050 }, + { "Segoe UI", 14, "Regular Class", 'm', 1050 }, + { "Tahoma", 11, "Regular Class", 'i', 975 }, + { "Tahoma", 11, "Regular Class", 'l', 975 }, + { "Tahoma", 11, "Regular Class", 'j', 900 }, + { "Tahoma", 11, "Regular Class", 'm', 918 }, + { "Verdana", 10, "Regular/Italic Class", 0, 1100 }, + { "Verdana", 12, "Regular Class", 'm', 975 }, + { "Verdana", 12, "Regular/Italic Class", 0, 1050 }, + { "Verdana", 13, "Regular/Italic Class", 'i', 950 }, + { "Verdana", 13, "Regular/Italic Class", 'j', 950 }, + { "Verdana", 13, "Regular/Italic Class", 'l', 950 }, + { "Verdana", 16, "Regular Class", 0, 1050 }, + { "Verdana", 9, "Regular/Italic Class", 0, 1050 }, + { "Times New Roman", 16, "Regular Class", 'm', 918 }, + { "Trebuchet MS", 11, "Regular Class", 'm', 800 }, + { "Trebuchet MS", 12, "Regular Class", 'm', 800 }, + }; + +#else + +#define COMPATIBLE_WIDTHS_RULES_SIZE 1 + + SPH_TweakRule COMPATIBLE_WIDTHS_Rules + [COMPATIBLE_WIDTHS_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + +#define X_SCALING_RULES_SIZE 1 + + SPH_ScaleRule X_SCALING_Rules + [X_SCALING_RULES_SIZE] = + { + { "-", 0, "", 0, 1000 }, + }; + +#endif /* FORCE_NATURAL_WIDTHS */ + +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + +FT_END_HEADER + +#endif /* __TTSUBPIX_H__ */ + +/* END */ -- cgit v1.2.3