From fa791414601df61d20d860299dba80fdb62565df Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 21 Jun 2013 10:45:51 +0200 Subject: Upgraded freetype to 2.5.0.1 --- freetype/src/truetype/ttdriver.c | 101 +++- freetype/src/truetype/ttgload.c | 439 ++++++++------ freetype/src/truetype/ttgxvar.c | 52 +- freetype/src/truetype/ttinterp.c | 1232 +++++++++++++++++++++----------------- freetype/src/truetype/ttinterp.h | 46 +- freetype/src/truetype/ttobjs.c | 57 +- freetype/src/truetype/ttobjs.h | 21 +- freetype/src/truetype/ttpic.c | 12 +- freetype/src/truetype/ttpic.h | 14 +- freetype/src/truetype/ttpload.c | 26 +- freetype/src/truetype/ttsubpix.c | 818 +++++++++++++++++++++++-- freetype/src/truetype/ttsubpix.h | 898 ++------------------------- 12 files changed, 1992 insertions(+), 1724 deletions(-) (limited to 'freetype/src/truetype') diff --git a/freetype/src/truetype/ttdriver.c b/freetype/src/truetype/ttdriver.c index 60c0f3e13..fb25706ab 100644 --- a/freetype/src/truetype/ttdriver.c +++ b/freetype/src/truetype/ttdriver.c @@ -4,7 +4,7 @@ /* */ /* TrueType font driver implementation (body). */ /* */ -/* Copyright 1996-2012 by */ +/* Copyright 1996-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,6 +29,8 @@ #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" @@ -52,6 +54,73 @@ #define FT_COMPONENT trace_ttdriver + /* + * PROPERTY SERVICE + * + */ + static FT_Error + tt_property_set( FT_Module module, /* TT_Driver */ + const char* property_name, + const void* value ) + { + FT_Error error = FT_Err_Ok; + TT_Driver driver = (TT_Driver)module; + + + 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 ); + } + + + static FT_Error + tt_property_get( FT_Module module, /* TT_Driver */ + const char* property_name, + const void* value ) + { + FT_Error error = FT_Err_Ok; + TT_Driver driver = (TT_Driver)module; + + FT_UInt interpreter_version = driver->interpreter_version; + + + 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 ); + } + + + FT_DEFINE_SERVICE_PROPERTIESREC( + tt_service_properties, + (FT_Properties_SetFunc)tt_property_set, + (FT_Properties_GetFunc)tt_property_get ) + + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ @@ -163,7 +232,7 @@ } } - return TT_Err_Ok; + return FT_Err_Ok; } /*************************************************************************/ @@ -187,7 +256,7 @@ { TT_Face ttface = (TT_Face)size->face; TT_Size ttsize = (TT_Size)size; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; ttsize->strike_index = strike_index; @@ -221,7 +290,7 @@ FT_Size_Request req ) { TT_Size ttsize = (TT_Size)size; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS @@ -294,13 +363,13 @@ if ( !slot ) - return TT_Err_Invalid_Slot_Handle; + return FT_THROW( Invalid_Slot_Handle ); if ( !size ) - return TT_Err_Invalid_Size_Handle; + return FT_THROW( Invalid_Size_Handle ); if ( !face ) - return TT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( glyph_index >= (FT_UInt)face->num_glyphs && @@ -308,7 +377,7 @@ #else if ( glyph_index >= (FT_UInt)face->num_glyphs ) #endif - return TT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); if ( load_flags & FT_LOAD_NO_HINTING ) { @@ -384,18 +453,20 @@ (TT_Glyf_GetLocationFunc)tt_face_get_location ) #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC4( + FT_DEFINE_SERVICEDESCREC5( tt_services, FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE, 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, &TT_SERVICE_TRUETYPE_GLYF_GET ) + FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET, + FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET ) #else - FT_DEFINE_SERVICEDESCREC3( + FT_DEFINE_SERVICEDESCREC4( 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, &TT_SERVICE_TRUETYPE_GLYF_GET ) + FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET, + FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET ) #endif @@ -457,7 +528,8 @@ #define TT_SIZE_SELECT 0 #endif - FT_DEFINE_DRIVER( tt_driver_class, + FT_DEFINE_DRIVER( + tt_driver_class, FT_MODULE_FONT_DRIVER | FT_MODULE_DRIVER_SCALABLE | @@ -486,9 +558,6 @@ tt_slot_init, 0, /* FT_Slot_DoneFunc */ - ft_stub_set_char_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */ - ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */ - tt_glyph_load, tt_get_kerning, diff --git a/freetype/src/truetype/ttgload.c b/freetype/src/truetype/ttgload.c index 374f89dce..f640a6c78 100644 --- a/freetype/src/truetype/ttgload.c +++ b/freetype/src/truetype/ttgload.c @@ -4,7 +4,7 @@ /* */ /* TrueType Glyph Loader (body). */ /* */ -/* Copyright 1996-2012 */ +/* Copyright 1996-2013 */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -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 ) @@ -292,7 +299,7 @@ loader->cursor = stream->cursor; loader->limit = stream->limit; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -314,7 +321,7 @@ if ( p + 10 > limit ) - return TT_Err_Invalid_Outline; + return FT_THROW( Invalid_Outline ); loader->n_contours = FT_NEXT_SHORT( p ); @@ -330,7 +337,7 @@ loader->bbox.yMax )); loader->cursor = p; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -415,14 +422,14 @@ { FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n", n_ins )); - error = TT_Err_Too_Many_Hints; + error = FT_THROW( Too_Many_Hints ); goto Fail; } if ( ( limit - p ) < n_ins ) { FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); - error = TT_Err_Too_Many_Hints; + error = FT_THROW( Too_Many_Hints ); goto Fail; } @@ -552,7 +559,7 @@ return error; Invalid_Outline: - error = TT_Err_Invalid_Outline; + error = FT_THROW( Invalid_Outline ); goto Fail; } @@ -673,7 +680,7 @@ return error; Invalid_Composite: - error = TT_Err_Invalid_Composite; + error = FT_THROW( Invalid_Composite ); goto Fail; } @@ -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,13 +832,17 @@ } #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 - return TT_Err_Ok; + else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) + FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 ); + } +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + return FT_Err_Ok; } @@ -844,18 +860,10 @@ TT_Process_Simple_Glyph( TT_Loader loader ) { FT_GlyphLoader gloader = loader->gloader; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; 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,52 +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 = 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 ) - { - 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 + 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 = 0; /* pacify compiler */ + FT_Fixed y_scale = 0; + FT_Bool do_scale = FALSE; - for ( ; vec < limit; vec++ ) + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) { - vec->x = FT_MulFix( vec->x, x_scale ); - vec->y = FT_MulFix( vec->y, y_scale ); + /* scale, but only if enabled and only if TT hinting is being used */ + if ( IS_HINTED( loader->load_flags ) ) + x_scale_factor = sph_test_tweak_x_scaling( face, + family, + ppem, + style, + loader->glyph_index ); + /* scale the glyph */ + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || + x_scale_factor != 1000 ) + { + x_scale = FT_MulDiv( ((TT_Size)loader->size)->metrics.x_scale, + x_scale_factor, 1000 ); + y_scale = ((TT_Size)loader->size)->metrics.y_scale; + + /* compensate for any scaling by de/emboldening; */ + /* the amount was determined via experimentation */ + if ( x_scale_factor != 1000 && ppem > 11 ) + FT_Outline_EmboldenXY( outline, + FT_MulFix( 1280 * ppem, + 1000 - x_scale_factor ), + 0 ); + do_scale = TRUE; + } + } + else + +#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 ) ) @@ -1022,7 +1061,7 @@ l += num_base_points; if ( k >= num_base_points || l >= num_points ) - return TT_Err_Invalid_Composite; + return FT_THROW( Invalid_Composite ); p1 = gloader->base.outline.points + k; p2 = gloader->base.outline.points + l; @@ -1036,7 +1075,7 @@ y = subglyph->arg2; if ( !x && !y ) - return TT_Err_Ok; + return FT_Err_Ok; /* Use a default value dependent on */ /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */ @@ -1081,16 +1120,10 @@ /* */ /* This algorithm is a guess and works much better than the above. */ /* */ - FT_Fixed mac_xscale = FT_SqrtFixed( - (FT_Int32)FT_MulFix( subglyph->transform.xx, - subglyph->transform.xx ) + - (FT_Int32)FT_MulFix( subglyph->transform.xy, - subglyph->transform.xy ) ); - FT_Fixed mac_yscale = FT_SqrtFixed( - (FT_Int32)FT_MulFix( subglyph->transform.yy, - subglyph->transform.yy ) + - (FT_Int32)FT_MulFix( subglyph->transform.yx, - subglyph->transform.yx ) ); + FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx, + subglyph->transform.xy ); + FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy, + subglyph->transform.yx ); x = FT_MulFix( x, mac_xscale ); @@ -1122,7 +1155,7 @@ base_vec + num_base_points, x, y ); - return TT_Err_Ok; + return FT_Err_Ok; } @@ -1191,7 +1224,7 @@ FT_TRACE1(( "TT_Process_Composite_Glyph: " "too many instructions (%d) for glyph with length %d\n", n_ins, loader->byte_len )); - return TT_Err_Too_Many_Hints; + return FT_THROW( Too_Many_Hints ); } tmp = loader->exec->glyphSize; @@ -1205,7 +1238,7 @@ return error; } else if ( n_ins == 0 ) - return TT_Err_Ok; + return FT_Err_Ok; if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) return error; @@ -1261,7 +1294,7 @@ FT_UInt recurse_count, FT_Bool header_only ) { - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; FT_Fixed x_scale, y_scale; FT_ULong offset; TT_Face face = (TT_Face)loader->face; @@ -1284,14 +1317,14 @@ if ( recurse_count > 1 && recurse_count > face->max_profile.maxComponentDepth ) { - error = TT_Err_Invalid_Composite; + error = FT_THROW( Invalid_Composite ); goto Exit; } /* check glyph index */ if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) { - error = TT_Err_Invalid_Glyph_Index; + error = FT_THROW( Invalid_Glyph_Index ); goto Exit; } @@ -1355,7 +1388,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" )); - error = TT_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Exit; } @@ -1422,7 +1455,7 @@ loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); } - error = TT_Err_Ok; + error = FT_Err_Ok; goto Exit; } @@ -1636,7 +1669,7 @@ else { /* invalid composite count (negative but not -1) */ - error = TT_Err_Invalid_Outline; + error = FT_THROW( Invalid_Outline ); goto Exit; } @@ -1666,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; @@ -1696,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 */ @@ -1912,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,111 +1989,119 @@ exec = size->debug ? size->context : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; if ( !exec ) - return TT_Err_Could_Not_Find_Context; + return FT_THROW( 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 ) + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) { - grayscale = grayscale_hinting = TRUE; - subpixel_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; + + 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; + exec->ignore_x_mode = subpixel_hinting || grayscale_hinting; + exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; + if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) + exec->rasterizer_version = TT_INTERPRETER_VERSION_35; #if 1 - exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; - exec->symmetrical_smoothing = FALSE; - exec->bgr = FALSE; - exec->subpixel_positioned = TRUE; + exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; + exec->symmetrical_smoothing = FALSE; + exec->bgr = FALSE; + exec->subpixel_positioned = TRUE; #else /* 0 */ - exec->compatible_widths = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_COMPATIBLE_WIDTHS ); - exec->symmetrical_smoothing = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SYMMETRICAL_SMOOTHING ); - exec->bgr = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_BGR ); - exec->subpixel_positioned = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SUBPIXEL_POSITIONED ); + exec->compatible_widths = + FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + TT_LOAD_COMPATIBLE_WIDTHS ); + exec->symmetrical_smoothing = + FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + TT_LOAD_SYMMETRICAL_SMOOTHING ); + exec->bgr = + FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + TT_LOAD_BGR ); + exec->subpixel_positioned = + FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + TT_LOAD_SUBPIXEL_POSITIONED ); #endif /* 0 */ -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + } + else - grayscale = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO ); +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + { + grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + FT_RENDER_MODE_MONO ); + } TT_Load_Context( exec, face, size ); #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* a change from mono to subpixel rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( subpixel_hinting != exec->subpixel_hinting ) + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) { - FT_UInt i; + /* a change from mono to subpixel rendering (and vice versa) */ + /* requires a re-execution of the CVT program */ + if ( subpixel_hinting != exec->subpixel_hinting ) + { + FT_TRACE4(( "tt_loader_init: subpixel hinting change," + " re-executing `prep' table\n" )); + exec->subpixel_hinting = subpixel_hinting; + reexecute = TRUE; + } - exec->subpixel_hinting = subpixel_hinting; + /* 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" )); - for ( i = 0; i < size->cvt_size; i++ ) - size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); - tt_size_run_prep( size, pedantic ); + exec->grayscale_hinting = grayscale_hinting; + reexecute = TRUE; + } } + else - /* a change from mono to grayscale rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( grayscale != exec->grayscale_hinting ) - { - FT_UInt i; - +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - exec->grayscale_hinting = grayscale_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" )); - for ( i = 0; i < size->cvt_size; i++ ) - size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); - tt_size_run_prep( size, pedantic ); + exec->grayscale = grayscale; + reexecute = TRUE; + } } -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - /* a change from mono to grayscale rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( grayscale != exec->grayscale ) + if ( reexecute ) { FT_UInt i; - FT_TRACE4(( "tt_loader_init: grayscale change," - " re-executing `prep' table\n" )); - - exec->grayscale = grayscale; - for ( i = 0; i < size->cvt_size; i++ ) size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); tt_size_run_prep( size, pedantic ); } -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - /* see whether the cvt program has disabled hinting */ if ( exec->GS.instruct_control & 1 ) load_flags |= FT_LOAD_NO_HINTING; @@ -2073,7 +2133,7 @@ FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 ); - if ( error == TT_Err_Table_Missing ) + if ( FT_ERR_EQ( error, Table_Missing ) ) loader->glyf_offset = 0; else if ( error ) { @@ -2101,7 +2161,7 @@ loader->glyph = (FT_GlyphSlot)glyph; loader->stream = stream; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -2142,7 +2202,7 @@ TT_LoaderRec loader; - error = TT_Err_Ok; + error = FT_Err_Ok; #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS @@ -2164,9 +2224,16 @@ glyph->linearHoriAdvance = loader.linear; glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax - loader.vadvance; + + /* sanity check: if `horiAdvance' in the sbit metric */ + /* structure isn't set, use `linearHoriAdvance' */ + if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) + glyph->metrics.horiAdvance = + FT_MulFix( glyph->linearHoriAdvance, + size->root.metrics.x_scale ); } - return TT_Err_Ok; + return FT_Err_Ok; } } @@ -2174,10 +2241,10 @@ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) - return TT_Err_Invalid_Size_Handle; + return FT_THROW( Invalid_Size_Handle ); if ( load_flags & FT_LOAD_SBITS_ONLY ) - return TT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); if ( error ) diff --git a/freetype/src/truetype/ttgxvar.c b/freetype/src/truetype/ttgxvar.c index 4edcb07ab..7899d3671 100644 --- a/freetype/src/truetype/ttgxvar.c +++ b/freetype/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader */ /* */ -/* Copyright 2004-2012 by */ +/* Copyright 2004-2013 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -61,9 +61,9 @@ #define FT_Stream_FTell( stream ) \ - ( (stream)->cursor - (stream)->base ) + (FT_ULong)( (stream)->cursor - (stream)->base ) #define FT_Stream_SeekSet( stream, off ) \ - ( (stream)->cursor = (stream)->base+(off) ) + ( (stream)->cursor = (stream)->base + (off) ) /*************************************************************************/ @@ -91,7 +91,9 @@ /* indicates that there is a delta for every point without needing to */ /* enumerate all of them. */ /* */ -#define ALL_POINTS (FT_UShort*)( ~0 ) + + /* ensure that value `0' has the same width as a pointer */ +#define ALL_POINTS (FT_UShort*)~(FT_PtrDist)0 #define GX_PT_POINTS_ARE_WORDS 0x80 @@ -130,7 +132,7 @@ FT_Int j; FT_Int first; FT_Memory memory = stream->memory; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; FT_UNUSED( error ); @@ -215,7 +217,7 @@ FT_Offset i; FT_UInt j; FT_Memory memory = stream->memory; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; FT_UNUSED( error ); @@ -283,7 +285,7 @@ FT_Memory memory = stream->memory; GX_Blend blend = face->blend; GX_AVarSegment segment; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; FT_ULong version; FT_Long axisCount; FT_Int i, j; @@ -412,7 +414,7 @@ if ( gvar_head.version != (FT_Long)0x00010000L || gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis ) { - error = TT_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Exit; } @@ -610,7 +612,7 @@ FT_Stream stream = face->root.stream; FT_Memory memory = face->root.memory; FT_ULong table_len; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; FT_ULong fvar_start; FT_Int i, j; FT_MM_Var* mmvar = NULL; @@ -681,7 +683,7 @@ fvar_head.offsetToData + fvar_head.axisCount * 20U + fvar_head.instanceCount * fvar_head.instanceSize > table_len ) { - error = TT_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Exit; } @@ -703,7 +705,7 @@ mmvar->num_axis = fvar_head.axisCount; mmvar->num_designs = - ~0; /* meaningless in this context; each glyph */ + ~0U; /* meaningless in this context; each glyph */ /* may have a different number of designs */ /* (or tuples, as called by Apple) */ mmvar->num_namedstyles = @@ -847,7 +849,7 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; GX_Blend blend; FT_MM_Var* mmvar; FT_UInt i; @@ -875,14 +877,14 @@ if ( num_coords != mmvar->num_axis ) { - error = TT_Err_Invalid_Argument; + error = FT_THROW( Invalid_Argument ); goto Exit; } for ( i = 0; i < num_coords; ++i ) if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) { - error = TT_Err_Invalid_Argument; + error = FT_THROW( Invalid_Argument ); goto Exit; } @@ -983,7 +985,7 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; FT_Fixed* normalized = NULL; GX_Blend blend; FT_MM_Var* mmvar; @@ -1004,7 +1006,7 @@ if ( num_coords != mmvar->num_axis ) { - error = TT_Err_Invalid_Argument; + error = FT_THROW( Invalid_Argument ); goto Exit; } @@ -1020,7 +1022,7 @@ { if ( coords[i] > a->maximum || coords[i] < a->minimum ) { - error = TT_Err_Invalid_Argument; + error = FT_THROW( Invalid_Argument ); goto Exit; } @@ -1120,7 +1122,7 @@ { FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" )); - error = TT_Err_Ok; + error = FT_Err_Ok; goto Exit; } @@ -1128,7 +1130,7 @@ { FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" )); - error = TT_Err_Ok; + error = FT_Err_Ok; goto Exit; } @@ -1137,13 +1139,13 @@ { FT_TRACE2(( "is missing\n" )); - error = TT_Err_Ok; + error = FT_Err_Ok; goto Exit; } if ( FT_FRAME_ENTER( table_len ) ) { - error = TT_Err_Ok; + error = FT_Err_Ok; goto Exit; } @@ -1152,7 +1154,7 @@ { FT_TRACE2(( "bad table version\n" )); - error = TT_Err_Ok; + error = FT_Err_Ok; goto FExit; } @@ -1323,7 +1325,7 @@ if ( !face->doblend || blend == NULL ) - return TT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); /* to be freed by the caller */ if ( FT_NEW_ARRAY( delta_xy, n_points ) ) @@ -1333,7 +1335,7 @@ if ( glyph_index >= blend->gv_glyphcnt || blend->glyphoffsets[glyph_index] == blend->glyphoffsets[glyph_index + 1] ) - return TT_Err_Ok; /* no variation data for this glyph */ + return FT_Err_Ok; /* no variation data for this glyph */ if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] - @@ -1383,7 +1385,7 @@ } else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) { - error = TT_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Fail3; } else diff --git a/freetype/src/truetype/ttinterp.c b/freetype/src/truetype/ttinterp.c index 19fb66c17..e7ffb987c 100644 --- a/freetype/src/truetype/ttinterp.c +++ b/freetype/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (body). */ /* */ -/* Copyright 1996-2012 */ +/* Copyright 1996-2013 */ /* by David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -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" @@ -34,10 +35,6 @@ #ifdef TT_USE_BYTECODE_INTERPRETER -#define xxxSPH_DEBUG -#define xxxSPH_DEBUG_MORE_VERBOSE - - /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ @@ -135,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 */ @@ -308,7 +310,7 @@ exec->IP = IP; exec->curRange = range; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -344,7 +346,7 @@ exec->codeRangeTable[range - 1].base = (FT_Byte*)base; exec->codeRangeTable[range - 1].size = length; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -377,7 +379,7 @@ exec->codeRangeTable[range - 1].base = NULL; exec->codeRangeTable[range - 1].size = 0; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -435,7 +437,7 @@ FT_FREE( exec ); - return TT_Err_Ok; + return FT_Err_Ok; } @@ -485,7 +487,7 @@ exec->face = NULL; exec->size = NULL; - return TT_Err_Ok; + return FT_Err_Ok; Fail_Memory: FT_ERROR(( "Init_Context: not enough memory for %p\n", exec )); @@ -537,7 +539,7 @@ *size = new_max; } - return TT_Err_Ok; + return FT_Err_Ok; } @@ -644,7 +646,7 @@ exec->instruction_trap = FALSE; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -687,7 +689,7 @@ for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) size->codeRangeTable[i] = exec->codeRangeTable[i]; - return TT_Err_Ok; + return FT_Err_Ok; } @@ -723,7 +725,7 @@ if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) ) - != TT_Err_Ok ) + != FT_Err_Ok ) return error; exec->zp0 = exec->pts; @@ -760,7 +762,7 @@ if ( !debug ) return TT_RunIns( exec ); else - return TT_Err_Ok; + return FT_Err_Ok; #endif } @@ -1483,7 +1485,7 @@ l = (FT_UInt32)( ( a & 0xFFFFU ) * b ); m = ( a >> 16 ) * b; - lo = l + (FT_UInt32)( m << 16 ); + lo = l + ( (FT_UInt32)m << 16 ); hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l ); /* divide the result by 2^14 with rounding */ @@ -1495,7 +1497,7 @@ l = lo + 0x2000U; hi += l < lo; - return ( hi << 18 ) | ( l >> 14 ); + return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) ); } #endif @@ -1515,14 +1517,14 @@ l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx ); m = ( ax >> 16 ) * bx; - lo1 = l + (FT_UInt32)( m << 16 ); + lo1 = l + ( (FT_UInt32)m << 16 ); hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l ); /* compute ay*by as 64-bit value */ l = (FT_UInt32)( ( ay & 0xFFFFU ) * by ); m = ( ay >> 16 ) * by; - lo2 = l + (FT_UInt32)( m << 16 ); + lo2 = l + ( (FT_UInt32)m << 16 ); hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l ); /* add them */ @@ -1538,99 +1540,9 @@ l = lo + 0x2000U; hi += ( l < lo ); - return ( hi << 18 ) | ( l >> 14 ); - } - - - /* return length of given vector */ - -#if 0 - - static FT_Int32 - TT_VecLen( FT_Int32 x, - FT_Int32 y ) - { - FT_Int32 m, hi1, hi2, hi; - FT_UInt32 l, lo1, lo2, lo; - - - /* compute x*x as 64-bit value */ - lo = (FT_UInt32)( x & 0xFFFFU ); - hi = x >> 16; - - l = lo * lo; - m = hi * lo; - hi = hi * hi; - - lo1 = l + (FT_UInt32)( m << 17 ); - hi1 = hi + ( m >> 15 ) + ( lo1 < l ); - - /* compute y*y as 64-bit value */ - lo = (FT_UInt32)( y & 0xFFFFU ); - hi = y >> 16; - - l = lo * lo; - m = hi * lo; - hi = hi * hi; - - lo2 = l + (FT_UInt32)( m << 17 ); - hi2 = hi + ( m >> 15 ) + ( lo2 < l ); - - /* add them to get 'x*x+y*y' as 64-bit value */ - lo = lo1 + lo2; - hi = hi1 + hi2 + ( lo < lo1 ); - - /* compute the square root of this value */ - { - FT_UInt32 root, rem, test_div; - FT_Int count; - - - root = 0; - - { - rem = 0; - count = 32; - do - { - rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 ); - hi = ( hi << 2 ) | ( lo >> 30 ); - lo <<= 2; - root <<= 1; - test_div = ( root << 1 ) + 1; - - if ( rem >= test_div ) - { - rem -= test_div; - root += 1; - } - } while ( --count ); - } - - return (FT_Int32)root; - } + return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) ); } -#else - - /* this version uses FT_Vector_Length which computes the same value */ - /* much, much faster.. */ - /* */ - static FT_F26Dot6 - TT_VecLen( FT_F26Dot6 X, - FT_F26Dot6 Y ) - { - FT_Vector v; - - - v.x = X; - v.y = Y; - - return FT_Vector_Length( &v ); - } - -#endif - /*************************************************************************/ /* */ @@ -1675,7 +1587,7 @@ CUR.GS.projVector.x ); y = TT_MulFix14( CUR.tt_metrics.y_ratio, CUR.GS.projVector.y ); - CUR.tt_metrics.ratio = TT_VecLen( x, y ); + CUR.tt_metrics.ratio = FT_Hypot( x, y ); } } } @@ -1793,7 +1705,7 @@ if ( aRange < 1 || aRange > 3 ) { - CUR.error = TT_Err_Bad_Argument; + CUR.error = FT_THROW( Bad_Argument ); return FAILURE; } @@ -1801,7 +1713,7 @@ if ( range->base == NULL ) /* invalid coderange */ { - CUR.error = TT_Err_Invalid_CodeRange; + CUR.error = FT_THROW( Invalid_CodeRange ); return FAILURE; } @@ -1811,7 +1723,7 @@ if ( aIP > range->size ) { - CUR.error = TT_Err_Code_Overflow; + CUR.error = FT_THROW( Code_Overflow ); return FAILURE; } @@ -1858,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; } @@ -1936,10 +1849,11 @@ 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 ) #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - zone->cur[point].x += distance; + zone->cur[point].x += distance; + zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -2710,98 +2624,33 @@ /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */ /* R is undefined. */ /* */ - - static FT_Bool Normalize( EXEC_OP_ FT_F26Dot6 Vx, FT_F26Dot6 Vy, FT_UnitVector* R ) { FT_F26Dot6 W; - FT_Bool S1, S2; FT_UNUSED_EXEC; - if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L ) + if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L ) { - Vx *= 0x100; - Vy *= 0x100; - - W = TT_VecLen( Vx, Vy ); - - if ( W == 0 ) + if ( Vx == 0 && Vy == 0 ) { /* XXX: UNDOCUMENTED! It seems that it is possible to try */ /* to normalize the vector (0,0). Return immediately. */ return SUCCESS; } - R->x = (FT_F2Dot14)TT_DivFix14( Vx, W ); - R->y = (FT_F2Dot14)TT_DivFix14( Vy, W ); - - return SUCCESS; - } - - W = TT_VecLen( Vx, Vy ); - - Vx = TT_DivFix14( Vx, W ); - Vy = TT_DivFix14( Vy, W ); - - W = Vx * Vx + Vy * Vy; - - /* Now, we want that Sqrt( W ) = 0x4000 */ - /* Or 0x10000000 <= W < 0x10004000 */ - - if ( Vx < 0 ) - { - Vx = -Vx; - S1 = TRUE; - } - else - S1 = FALSE; - - if ( Vy < 0 ) - { - Vy = -Vy; - S2 = TRUE; - } - else - S2 = FALSE; - - while ( W < 0x10000000L ) - { - /* We need to increase W by a minimal amount */ - if ( Vx < Vy ) - Vx++; - else - Vy++; - - W = Vx * Vx + Vy * Vy; - } - - while ( W >= 0x10004000L ) - { - /* We need to decrease W by a minimal amount */ - if ( Vx < Vy ) - Vx--; - else - Vy--; - - W = Vx * Vx + Vy * Vy; + Vx *= 0x4000; + Vy *= 0x4000; } - /* Note that in various cases, we can only */ - /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */ - - if ( S1 ) - Vx = -Vx; - - if ( S2 ) - Vy = -Vy; + W = FT_Hypot( Vx, Vy ); - R->x = (FT_F2Dot14)Vx; /* Type conversion */ - R->y = (FT_F2Dot14)Vy; /* Type conversion */ + R->x = (FT_F2Dot14)TT_DivFix14( Vx, W ); + R->y = (FT_F2Dot14)TT_DivFix14( Vy, W ); return SUCCESS; } @@ -2829,7 +2678,7 @@ BOUNDS( aIdx2, CUR.zp1.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return FAILURE; } @@ -3085,10 +2934,10 @@ CUR.func_round = (TT_Round_Func)Round_Super_45; -#define DO_SLOOP \ - if ( args[0] < 0 ) \ - CUR.error = TT_Err_Bad_Argument; \ - else \ +#define DO_SLOOP \ + if ( args[0] < 0 ) \ + CUR.error = FT_THROW( Bad_Argument ); \ + else \ CUR.GS.loop = args[0]; @@ -3170,21 +3019,21 @@ args[0] = CUR.top; -#define DO_CINDEX \ - { \ - FT_Long L; \ - \ - \ - L = args[0]; \ - \ - if ( L <= 0 || L > CUR.args ) \ - { \ - if ( CUR.pedantic_hinting ) \ - CUR.error = TT_Err_Invalid_Reference; \ - args[0] = 0; \ - } \ - else \ - args[0] = CUR.stack[CUR.args - L]; \ +#define DO_CINDEX \ + { \ + FT_Long L; \ + \ + \ + L = args[0]; \ + \ + if ( L <= 0 || L > CUR.args ) \ + { \ + if ( CUR.pedantic_hinting ) \ + CUR.error = FT_THROW( Invalid_Reference ); \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR.stack[CUR.args - L]; \ } @@ -3192,24 +3041,24 @@ if ( args[1] != 0 ) \ { \ if ( args[0] == 0 && CUR.args == 0 ) \ - CUR.error = TT_Err_Bad_Argument; \ + CUR.error = FT_THROW( Bad_Argument ); \ CUR.IP += args[0]; \ if ( CUR.IP < 0 || \ ( CUR.callTop > 0 && \ CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ - CUR.error = TT_Err_Bad_Argument; \ + CUR.error = FT_THROW( Bad_Argument ); \ CUR.step_ins = FALSE; \ } #define DO_JMPR \ if ( args[0] == 0 && CUR.args == 0 ) \ - CUR.error = TT_Err_Bad_Argument; \ + CUR.error = FT_THROW( Bad_Argument ); \ CUR.IP += args[0]; \ if ( CUR.IP < 0 || \ ( CUR.callTop > 0 && \ CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ - CUR.error = TT_Err_Bad_Argument; \ + CUR.error = FT_THROW( Bad_Argument ); \ CUR.step_ins = FALSE; @@ -3217,12 +3066,12 @@ if ( args[1] == 0 ) \ { \ if ( args[0] == 0 && CUR.args == 0 ) \ - CUR.error = TT_Err_Bad_Argument; \ + CUR.error = FT_THROW( Bad_Argument ); \ CUR.IP += args[0]; \ if ( CUR.IP < 0 || \ ( CUR.callTop > 0 && \ CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \ - CUR.error = TT_Err_Bad_Argument; \ + CUR.error = FT_THROW( Bad_Argument ); \ CUR.step_ins = FALSE; \ } @@ -3281,7 +3130,7 @@ #define DO_DIV \ if ( args[1] == 0 ) \ - CUR.error = TT_Err_Divide_By_Zero; \ + CUR.error = FT_THROW( Divide_By_Zero ); \ else \ args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] ); @@ -3324,8 +3173,19 @@ /* subpixel hinting - avoid Typeman Dstroke and */ \ /* IStroke and Vacuform rounds */ \ \ - if ( CUR.compatibility_mode && \ - ( I == 24 || I == 22 || I == 8 ) ) \ + if ( SUBPIXEL_HINTING && \ + CUR.ignore_x_mode && \ + ( ( I == 24 && \ + ( CUR.face->sph_found_func_flags & \ + ( SPH_FDEF_SPACING_1 | \ + SPH_FDEF_SPACING_2 ) ) ) || \ + ( I == 22 && \ + ( CUR.sph_in_func_flags & \ + SPH_FDEF_TYPEMAN_STROKES ) ) || \ + ( I == 8 && \ + ( CUR.face->sph_found_func_flags & \ + SPH_FDEF_VACUFORM_ROUND_1 ) && \ + CUR.iup_called ) ) ) \ args[0] = 0; \ else \ args[0] = CUR.storage[I]; \ @@ -3425,8 +3285,8 @@ } -#define DO_DEBUG \ - CUR.error = TT_Err_Debug_OpCode; +#define DO_DEBUG \ + CUR.error = FT_THROW( Debug_OpCode ); #define DO_ROUND \ @@ -3454,10 +3314,10 @@ #undef ARRAY_BOUND_ERROR -#define ARRAY_BOUND_ERROR \ - { \ - CUR.error = TT_Err_Invalid_Reference; \ - return; \ +#define ARRAY_BOUND_ERROR \ + { \ + CUR.error = FT_THROW( Invalid_Reference ); \ + return; \ } @@ -4436,7 +4296,7 @@ if ( L <= 0 || L > CUR.args ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); } else { @@ -4506,7 +4366,7 @@ } Fail_Overflow: - CUR.error = TT_Err_Code_Overflow; + CUR.error = FT_THROW( Code_Overflow ); return FAILURE; } @@ -4613,8 +4473,57 @@ #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* arguments to opcodes are skipped by `SKIP_Code' */ - FT_Byte opcode_pattern[1][12] = { - /* #0 TTFautohint bytecode (old) */ + FT_Byte opcode_pattern[9][12] = { + /* #0 inline delta function 1 */ + { + 0x4B, /* PPEM */ + 0x53, /* GTEQ */ + 0x23, /* SWAP */ + 0x4B, /* PPEM */ + 0x51, /* LTEQ */ + 0x5A, /* AND */ + 0x58, /* IF */ + 0x38, /* SHPIX */ + 0x1B, /* ELSE */ + 0x21, /* POP */ + 0x21, /* POP */ + 0x59 /* EIF */ + }, + /* #1 inline delta function 2 */ + { + 0x4B, /* PPEM */ + 0x54, /* EQ */ + 0x58, /* IF */ + 0x38, /* SHPIX */ + 0x1B, /* ELSE */ + 0x21, /* POP */ + 0x21, /* POP */ + 0x59 /* EIF */ + }, + /* #2 diagonal stroke function */ + { + 0x20, /* DUP */ + 0x20, /* DUP */ + 0xB0, /* PUSHB_1 */ + /* 1 */ + 0x60, /* ADD */ + 0x46, /* GC_cur */ + 0xB0, /* PUSHB_1 */ + /* 64 */ + 0x23, /* SWAP */ + 0x42 /* WS */ + }, + /* #3 VacuFormRound function */ + { + 0x45, /* RCVT */ + 0x23, /* SWAP */ + 0x46, /* GC_cur */ + 0x60, /* ADD */ + 0x20, /* DUP */ + 0xB0 /* PUSHB_1 */ + /* 38 */ + }, + /* #4 TTFautohint bytecode (old) */ { 0x20, /* DUP */ 0x64, /* ABS */ @@ -4625,10 +4534,40 @@ 0x23, /* SWAP */ 0xB0 /* PUSHB_1 */ }, + /* #5 spacing function 1 */ + { + 0x01, /* SVTCA_x */ + 0xB0, /* PUSHB_1 */ + /* 24 */ + 0x43, /* RS */ + 0x58 /* IF */ + }, + /* #6 spacing function 2 */ + { + 0x01, /* SVTCA_x */ + 0x18, /* RTG */ + 0xB0, /* PUSHB_1 */ + /* 24 */ + 0x43, /* RS */ + 0x58 /* IF */ + }, + /* #7 TypeMan Talk DiagEndCtrl function */ + { + 0x01, /* SVTCA_x */ + 0x20, /* DUP */ + 0xB0, /* PUSHB_1 */ + /* 3 */ + 0x25, /* CINDEX */ + }, + /* #8 TypeMan Talk Align */ + { + 0x06, /* SPVTL */ + 0x7D, /* RDTG */ + }, }; - FT_UShort opcode_patterns = 1; - FT_UShort opcode_pointer[1] = { 0, }; - FT_UShort opcode_size[1] = { 7, }; + FT_UShort opcode_patterns = 9; + FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 }; FT_UShort i; #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ @@ -4651,7 +4590,7 @@ /* check that there is enough room for new functions */ if ( CUR.numFDefs >= CUR.maxFDefs ) { - CUR.error = TT_Err_Too_Many_Function_Defs; + CUR.error = FT_THROW( Too_Many_Function_Defs ); return; } CUR.numFDefs++; @@ -4661,60 +4600,140 @@ /* func # must be within unsigned 16-bit integer */ if ( n > 0xFFFFU ) { - CUR.error = TT_Err_Too_Many_Function_Defs; + CUR.error = FT_THROW( Too_Many_Function_Defs ); return; } - rec->range = CUR.curRange; - rec->opc = (FT_UInt16)n; - rec->start = CUR.IP + 1; - rec->active = TRUE; - rec->inline_delta = FALSE; + rec->range = CUR.curRange; + rec->opc = (FT_UInt16)n; + rec->start = CUR.IP + 1; + rec->active = TRUE; + rec->inline_delta = FALSE; + rec->sph_fdef_flags = 0x0000; if ( n > CUR.maxFunc ) CUR.maxFunc = (FT_UInt16)n; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* We don't know for sure these are typeman functions, */ + /* however they are only active when RS 22 is called */ + if ( n >= 64 && n <= 66 ) + rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES; +#endif + /* Now skip the whole function definition. */ /* We don't allow nested IDEFS & FDEFs. */ while ( SKIP_Code() == SUCCESS ) { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING -#ifdef SPH_DEBUG_MORE_VERBOSE - printf ( "Opcode: %d ", CUR.opcode ); -#endif +#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++ ) { -#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] ) + if ( opcode_pointer[i] < opcode_size[i] && + CUR.opcode == opcode_pattern[i][opcode_pointer[i]] ) { -#ifdef SPH_DEBUG - printf( "Function signature %d detected in FDEF %d\n", i, n); -#endif + opcode_pointer[i] += 1; - switch ( i ) + if ( opcode_pointer[i] == opcode_size[i] ) { - case 0: - CUR.size->ttfautohinted = TRUE; - break; + FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n", + i, n, + CUR.face->root.family_name, + CUR.face->root.style_name )); + + switch ( i ) + { + case 0: + rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1; + CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1; + break; + + 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 ) + { + 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: + /* 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; + + case 7: + rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; + CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; + break; + + case 8: +#if 0 + rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; + CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; +#endif + 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 ) ); } #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ @@ -4723,7 +4742,7 @@ { case 0x89: /* IDEF */ case 0x2C: /* FDEF */ - CUR.error = TT_Err_Nested_DEFS; + CUR.error = FT_THROW( Nested_DEFS ); return; case 0x2D: /* ENDF */ @@ -4748,9 +4767,13 @@ FT_UNUSED_ARG; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + CUR.sph_in_func_flags = 0x0000; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */ { - CUR.error = TT_Err_ENDF_In_Exec_Stream; + CUR.error = FT_THROW( ENDF_In_Exec_Stream ); return; } @@ -4762,15 +4785,6 @@ 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++; @@ -4841,11 +4855,21 @@ if ( !def->active ) goto Fail; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode && + ( ( CUR.iup_called && + ( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) || + ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) ) + goto Fail; + else + CUR.sph_in_func_flags = def->sph_fdef_flags; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ /* check the call stack */ if ( CUR.callTop >= CUR.callSize ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); return; } @@ -4863,10 +4887,11 @@ def->start ); CUR.step_ins = FALSE; + return; Fail: - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); } @@ -4919,10 +4944,19 @@ if ( !def->active ) goto Fail; +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode && + ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) + goto Fail; + else + CUR.sph_in_func_flags = def->sph_fdef_flags; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + /* check stack */ if ( CUR.callTop >= CUR.callSize ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); return; } @@ -4946,7 +4980,7 @@ return; Fail: - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); } @@ -4977,7 +5011,7 @@ /* check that there is enough room for a new instruction */ if ( CUR.numIDefs >= CUR.maxIDefs ) { - CUR.error = TT_Err_Too_Many_Instruction_Defs; + CUR.error = FT_THROW( Too_Many_Instruction_Defs ); return; } CUR.numIDefs++; @@ -4986,7 +5020,7 @@ /* opcode must be unsigned 8-bit integer */ if ( 0 > args[0] || args[0] > 0x00FF ) { - CUR.error = TT_Err_Too_Many_Instruction_Defs; + CUR.error = FT_THROW( Too_Many_Instruction_Defs ); return; } @@ -5007,7 +5041,7 @@ { case 0x89: /* IDEF */ case 0x2C: /* FDEF */ - CUR.error = TT_Err_Nested_DEFS; + CUR.error = FT_THROW( Nested_DEFS ); return; case 0x2D: /* ENDF */ return; @@ -5041,7 +5075,7 @@ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); return; } @@ -5068,7 +5102,7 @@ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); return; } @@ -5098,7 +5132,7 @@ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); return; } @@ -5123,7 +5157,7 @@ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); return; } @@ -5166,7 +5200,7 @@ if ( BOUNDSL( L, CUR.zp2.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); R = 0; } else @@ -5203,7 +5237,7 @@ if ( BOUNDS( L, CUR.zp2.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5247,7 +5281,7 @@ BOUNDS( K, CUR.zp1.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); D = 0; } else @@ -5294,7 +5328,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 */ @@ -5323,7 +5358,7 @@ BOUNDS( p1, CUR.zp2.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5363,6 +5398,12 @@ A = v1->x - v2->x; B = v1->y - v2->y; + + if ( A == 0 && B == 0 ) + { + A = 0x4000; + aOpc = 0; + } } if ( ( aOpc & 1 ) != 0 ) @@ -5401,7 +5442,7 @@ default: if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5430,7 +5471,7 @@ default: if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5459,7 +5500,7 @@ default: if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5488,7 +5529,7 @@ default: if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5519,7 +5560,7 @@ if ( K < 1 || K > 2 ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5617,7 +5658,7 @@ if ( CUR.top < CUR.GS.loop ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Too_Few_Arguments; + CUR.error = FT_THROW( Too_Few_Arguments ); goto Fail; } @@ -5631,7 +5672,7 @@ { if ( CUR.pedantic_hinting ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } } @@ -5666,7 +5707,7 @@ BOUNDS( L, CUR.pts.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5694,7 +5735,7 @@ BOUNDS( L, CUR.pts.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5728,7 +5769,7 @@ if ( BOUNDS( p, zp.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); *refp = 0; return FAILURE; } @@ -5790,12 +5831,7 @@ 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 ) ) ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - CUR.zp2.cur[point].x += dx; + CUR.zp2.cur[point].x += dx; if ( touch ) CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -5831,7 +5867,7 @@ if ( CUR.top < CUR.GS.loop ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -5847,11 +5883,18 @@ { if ( CUR.pedantic_hinting ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } } else +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* doesn't follow Cleartype spec but produces better result */ + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode ) + MOVE_Zp2_Point( point, 0, dy, TRUE ); + else +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ MOVE_Zp2_Point( point, dx, dy, TRUE ); CUR.GS.loop--; @@ -5890,7 +5933,7 @@ if ( BOUNDS( contour, bounds ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5938,7 +5981,7 @@ if ( BOUNDS( args[0], 2 ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -5984,7 +6027,7 @@ if ( CUR.top < CUR.GS.loop + 1 ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -6019,7 +6062,7 @@ { if ( CUR.pedantic_hinting ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } } @@ -6029,12 +6072,13 @@ /* 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 */ + /* - freedom vector is y and sph_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 ) + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode ) { /* save point for later comparison */ if ( CUR.GS.freeVector.y != 0 ) @@ -6042,62 +6086,70 @@ 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 ) + if ( !CUR.face->sph_compatibility_mode && + CUR.GS.freeVector.y != 0 ) + { MOVE_Zp2_Point( point, dx, dy, TRUE ); - else if ( CUR.ignore_x_mode && CUR.compatibility_mode ) + /* save new point */ + if ( CUR.GS.freeVector.y != 0 ) + { + B2 = CUR.zp2.cur[point].y; + + /* reverse any disallowed moves */ + if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && + ( B1 & 63 ) != 0 && + ( B2 & 63 ) != 0 && + B1 != B2 ) + MOVE_Zp2_Point( point, -dx, -dy, TRUE ); + } + } + else if ( CUR.face->sph_compatibility_mode ) { - if ( CUR.ignore_x_mode && - ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) ) + if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) { dx = FT_PIX_ROUND( B1 + dx ) - B1; dy = FT_PIX_ROUND( B1 + dy ) - B1; } + /* skip post-iup deltas */ + if ( CUR.iup_called && + ( ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) || + ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) ) + goto Skip; + 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 ); - } + MOVE_Zp2_Point( point, 0, 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 ); + /* save new point */ + if ( CUR.GS.freeVector.y != 0 ) + { + B2 = CUR.zp2.cur[point].y; + + /* reverse any disallowed moves */ + if ( ( B1 & 63 ) == 0 && + ( B2 & 63 ) != 0 && + B1 != B2 ) + MOVE_Zp2_Point( point, 0, -dy, TRUE ); + } } - } + else if ( CUR.sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL ) + 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--; } @@ -6119,16 +6171,21 @@ { FT_UShort point; FT_F26Dot6 distance; + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_F26Dot6 control_value_cutin; + FT_F26Dot6 control_value_cutin = 0; /* pacify compiler */ - 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]; @@ -6137,7 +6194,7 @@ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -6155,7 +6212,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]; @@ -6190,7 +6248,7 @@ if ( BOUNDS( point, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -6198,7 +6256,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, @@ -6240,8 +6299,10 @@ 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.GS.freeVector.y == 0 && !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) control_value_cutin = 0; #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ @@ -6250,7 +6311,7 @@ BOUNDSL( cvtEntry, CUR.cvtSize ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -6279,8 +6340,11 @@ if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */ { #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* only adjust legacy fonts x otherwise breaks Calibri italic */ - if ( CUR.compatibility_mode ) + /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */ + /* Determined via experimentation and may be incorrect... */ + 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 ); @@ -6289,7 +6353,9 @@ CUR.zp0.cur[point] = CUR.zp0.org[point]; } #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode && + ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && distance > 0 && CUR.GS.freeVector.y != 0 ) distance = 0; @@ -6303,7 +6369,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] ); @@ -6337,20 +6404,20 @@ 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 ) || BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -6407,7 +6474,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] ); @@ -6473,8 +6542,8 @@ control_value_cutin, minimum_distance; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_Int B1; - FT_Int B2; + FT_Int B1 = 0; /* pacify compiler */ + FT_Int B2 = 0; FT_Bool reverse_move = FALSE; #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ @@ -6485,7 +6554,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; @@ -6498,7 +6568,7 @@ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -6506,10 +6576,6 @@ 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 */ @@ -6547,8 +6613,11 @@ if ( ( org_dist ^ cvt_dist ) < 0 ) cvt_dist = -cvt_dist; } + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( CUR.GS.freeVector.y != 0 && + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode && + CUR.GS.freeVector.y != 0 && ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) ) { if ( cur_dist < -64 ) @@ -6557,6 +6626,7 @@ cvt_dist += 32; } #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + /* control value cut-in and round */ if ( ( CUR.opcode & 4 ) != 0 ) @@ -6587,9 +6657,23 @@ CUR.tt_metrics.compensations[CUR.opcode & 3] ); } else + { + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /* do cvt cut-in always in MIRP for sph */ + 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] ); + } /* minimum distance test */ @@ -6608,52 +6692,52 @@ } #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; + 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; + + 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.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; + B2 = CUR.zp1.cur[point].y; - 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; + /* 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_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: @@ -6682,11 +6766,12 @@ #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 ) ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ @@ -6695,7 +6780,7 @@ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -6709,7 +6794,7 @@ { if ( CUR.pedantic_hinting ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } } @@ -6768,7 +6853,7 @@ BOUNDS( point, CUR.zp2.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -6844,7 +6929,7 @@ BOUNDS( p2, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -6879,7 +6964,7 @@ if ( CUR.top < CUR.GS.loop ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -6893,7 +6978,7 @@ if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto Fail; } @@ -6949,7 +7034,7 @@ { if ( CUR.pedantic_hinting ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } continue; @@ -6975,9 +7060,24 @@ cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base ); if ( org_dist ) - new_dist = ( old_range != 0 ) - ? FT_MulDiv( org_dist, cur_range, old_range ) - : cur_dist; + { + if ( old_range ) + new_dist = FT_MulDiv( org_dist, cur_range, old_range ); + else + { + /* This is the same as what MS does for the invalid case: */ + /* */ + /* delta = (Original_Pt - Original_RP1) - */ + /* (Current_Pt - Current_RP1) */ + /* */ + /* In FreeType speak: */ + /* */ + /* new_dist = cur_dist - */ + /* org_dist - cur_dist; */ + + new_dist = -org_dist; + } + } else new_dist = 0; @@ -7008,7 +7108,7 @@ if ( BOUNDS( point, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } @@ -7198,9 +7298,10 @@ point = 0; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( CUR.ignore_x_mode ) + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode ) { - CUR.iup_called = 1; + CUR.iup_called = TRUE; if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) return; } @@ -7277,7 +7378,14 @@ FT_Long B; #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING FT_UShort B1, B2; -#endif + + + if ( SUBPIXEL_HINTING && + CUR.ignore_x_mode && + CUR.iup_called && + ( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) + goto Fail; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING @@ -7290,7 +7398,7 @@ if ( CUR.args < n ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Too_Few_Arguments; + CUR.error = FT_THROW( Too_Few_Arguments ); n = CUR.args; } @@ -7308,7 +7416,7 @@ if ( CUR.args < 2 ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Too_Few_Arguments; + CUR.error = FT_THROW( Too_Few_Arguments ); CUR.args = 0; goto Fail; } @@ -7352,73 +7460,81 @@ 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; - - /* Standard Subpixel Hinting: Allow y move */ - if ( !CUR.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 ); - /* 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 ) ) + /* 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.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 ) ) + 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 ) 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; - 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 ); + 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_DELTAP ) && + ( 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 if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); } Fail: @@ -7450,7 +7566,7 @@ if ( CUR.args < n ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Too_Few_Arguments; + CUR.error = FT_THROW( Too_Few_Arguments ); n = CUR.args; } @@ -7467,7 +7583,7 @@ if ( CUR.args < 2 ) { if ( CUR.pedantic_hinting ) - CUR.error = TT_Err_Too_Few_Arguments; + CUR.error = FT_THROW( Too_Few_Arguments ); CUR.args = 0; goto Fail; } @@ -7481,7 +7597,7 @@ { if ( CUR.pedantic_hinting ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); return; } } @@ -7549,17 +7665,18 @@ /* 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; -#ifdef SPH_DEBUG_MORE_VERBOSE - printf(" SETTING AS %d\n", CUR.rasterizer_version ); -#endif + FT_TRACE7(( "Setting rasterizer version %d\n", + CUR.rasterizer_version )); } else #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ if ( ( args[0] & 1 ) != 0 ) - K = 35; + K = TT_INTERPRETER_VERSION_35; /********************************/ /* GLYPH ROTATED */ @@ -7586,7 +7703,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 */ @@ -7649,7 +7769,9 @@ } } } + #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + args[0] = K; } @@ -7672,7 +7794,7 @@ if ( CUR.callTop >= CUR.callSize ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); return; } @@ -7691,7 +7813,7 @@ } } - CUR.error = TT_Err_Invalid_Opcode; + CUR.error = FT_THROW( Invalid_Opcode ); } @@ -8018,7 +8140,21 @@ FT_EXPORT_DEF( FT_Error ) TT_RunIns( TT_ExecContext exc ) { - FT_Long ins_counter = 0; /* executed instructions counter */ + FT_Long ins_counter = 0; /* executed instructions counter */ + FT_UShort i; + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + FT_Byte opcode_pattern[1][2] = { + /* #8 TypeMan Talk Align */ + { + 0x06, /* SPVTL */ + 0x7D, /* RDTG */ + }, + }; + FT_UShort opcode_patterns = 1; + FT_UShort opcode_pointer[1] = { 0 }; + FT_UShort opcode_size[1] = { 1 }; +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ #ifdef TT_CONFIG_OPTION_STATIC_RASTER @@ -8026,8 +8162,7 @@ #endif #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( CUR.ignore_x_mode ) - CUR.iup_called = FALSE; + CUR.iup_called = FALSE; #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ /* set CVT functions */ @@ -8076,12 +8211,9 @@ /* One can also interpret it as the index of the last argument. */ if ( CUR.args < 0 ) { - FT_UShort i; - - if ( CUR.pedantic_hinting ) { - CUR.error = TT_Err_Too_Few_Arguments; + CUR.error = FT_THROW( Too_Few_Arguments ); goto LErrorLabel_; } @@ -8098,12 +8230,45 @@ /* statement. */ if ( CUR.new_top > CUR.stackSize ) { - CUR.error = TT_Err_Stack_Overflow; + CUR.error = FT_THROW( Stack_Overflow ); goto LErrorLabel_; } CUR.step_ins = TRUE; - CUR.error = TT_Err_Ok; + CUR.error = FT_Err_Ok; + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + + if ( SUBPIXEL_HINTING ) + { + for ( i = 0; i < opcode_patterns; i++ ) + { + if ( opcode_pointer[i] < opcode_size[i] && + CUR.opcode == opcode_pattern[i][opcode_pointer[i]] ) + { + opcode_pointer[i] += 1; + + if ( opcode_pointer[i] == opcode_size[i] ) + { + FT_TRACE7(( "sph: opcode ptrn: %d, %s %s\n", + i, + CUR.face->root.family_name, + CUR.face->root.style_name )); + + switch ( i ) + { + case 0: + break; + } + opcode_pointer[i] = 0; + } + } + else + opcode_pointer[i] = 0; + } + } + +#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH @@ -8301,13 +8466,7 @@ break; 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 ) ) ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - Ins_CALL( EXEC_ARG_ args ); + Ins_CALL( EXEC_ARG_ args ); break; case 0x2C: /* FDEF */ @@ -8325,11 +8484,7 @@ case 0x30: /* IUP */ case 0x31: /* IUP */ -#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 ); + Ins_IUP( EXEC_ARG_ args ); break; case 0x32: /* SHP */ @@ -8386,7 +8541,7 @@ break; Set_Invalid_Ref: - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); break; case 0x43: /* RS */ @@ -8488,13 +8643,7 @@ break; 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 ) ) ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - Ins_DELTAP( EXEC_ARG_ args ); + Ins_DELTAP( EXEC_ARG_ args ); break; case 0x5E: /* SDB */ @@ -8682,11 +8831,12 @@ #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */ - if ( CUR.error != TT_Err_Ok ) + if ( CUR.error ) { switch ( CUR.error ) { - case TT_Err_Invalid_Opcode: /* looking for redefined instructions */ + /* looking for redefined instructions */ + case FT_ERR( Invalid_Opcode ): { TT_DefRecord* def = CUR.IDefs; TT_DefRecord* limit = def + CUR.numIDefs; @@ -8701,7 +8851,7 @@ if ( CUR.callTop >= CUR.callSize ) { - CUR.error = TT_Err_Invalid_Reference; + CUR.error = FT_THROW( Invalid_Reference ); goto LErrorLabel_; } @@ -8721,7 +8871,7 @@ } } - CUR.error = TT_Err_Invalid_Opcode; + CUR.error = FT_THROW( Invalid_Opcode ); goto LErrorLabel_; #if 0 @@ -8747,14 +8897,14 @@ /* increment instruction counter and check if we didn't */ /* run this program for too long (e.g. infinite loops). */ if ( ++ins_counter > MAX_RUNNABLE_OPCODES ) - return TT_Err_Execution_Too_Long; + return FT_THROW( Execution_Too_Long ); LSuiteLabel_: if ( CUR.IP >= CUR.codeSize ) { if ( CUR.callTop > 0 ) { - CUR.error = TT_Err_Code_Overflow; + CUR.error = FT_THROW( Code_Overflow ); goto LErrorLabel_; } else @@ -8768,10 +8918,10 @@ *exc = cur; #endif - return TT_Err_Ok; + return FT_Err_Ok; LErrorCodeOverflow_: - CUR.error = TT_Err_Code_Overflow; + CUR.error = FT_THROW( Code_Overflow ); LErrorLabel_: diff --git a/freetype/src/truetype/ttinterp.h b/freetype/src/truetype/ttinterp.h index f4336121b..69f5011ed 100644 --- a/freetype/src/truetype/ttinterp.h +++ b/freetype/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (specification). */ /* */ -/* Copyright 1996-2007, 2010, 2012 by */ +/* Copyright 1996-2007, 2010, 2012-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -115,14 +115,14 @@ FT_BEGIN_HEADER /* various fonts. "", 0, "", NULL value indicates to match any value. */ /* */ -#define MAX_NAME_SIZE 32 -#define MAX_CLASS_MEMBERS 100 +#define SPH_MAX_NAME_SIZE 32 +#define SPH_MAX_CLASS_MEMBERS 100 typedef struct SPH_TweakRule_ { - const char family[MAX_NAME_SIZE]; + const char family[SPH_MAX_NAME_SIZE]; const FT_UInt ppem; - const char style[MAX_NAME_SIZE]; + const char style[SPH_MAX_NAME_SIZE]; const FT_ULong glyph; } SPH_TweakRule; @@ -130,21 +130,21 @@ FT_BEGIN_HEADER typedef struct SPH_ScaleRule_ { - const char family[MAX_NAME_SIZE]; + const char family[SPH_MAX_NAME_SIZE]; const FT_UInt ppem; - const char style[MAX_NAME_SIZE]; + const char style[SPH_MAX_NAME_SIZE]; const FT_ULong glyph; const FT_ULong scale; } SPH_ScaleRule; - typedef struct Font_Class_ + typedef struct SPH_Font_Class_ { - const char name[MAX_NAME_SIZE]; - const char member[MAX_CLASS_MEMBERS][MAX_NAME_SIZE]; + const char name[SPH_MAX_NAME_SIZE]; + const char member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE]; - } Font_Class; + } SPH_Font_Class; #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ @@ -269,10 +269,6 @@ FT_BEGIN_HEADER 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. */ @@ -282,12 +278,16 @@ FT_BEGIN_HEADER FT_Bool subpixel_positioned; /* subpixel positioned */ /* (DirectWrite ClearType)? */ - FT_Int rasterizer_version; /* MS rasterizer version */ + FT_Int rasterizer_version; /* MS rasterizer version */ - FT_Bool iup_called; /* IUP called for glyph? */ + FT_Bool iup_called; /* IUP called for glyph? */ + + FT_ULong sph_tweak_flags; /* flags to control */ + /* hint tweaks */ + + FT_ULong sph_in_func_flags; /* flags to indicate if in */ + /* special functions */ - FT_ULong sph_tweak_flags; /* flags to control */ - /* hint tweaks */ #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ } TT_ExecContextRec; @@ -296,7 +296,7 @@ FT_BEGIN_HEADER extern const TT_GraphicsState tt_default_graphics_state; -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#ifdef TT_USE_BYTECODE_INTERPRETER FT_LOCAL( FT_Error ) TT_Goto_CodeRange( TT_ExecContext exec, FT_Int range, @@ -319,7 +319,7 @@ FT_BEGIN_HEADER FT_Long multiplier, void* _pbuff, FT_ULong new_max ); -#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ +#endif /* TT_USE_BYTECODE_INTERPRETER */ /*************************************************************************/ @@ -345,7 +345,7 @@ FT_BEGIN_HEADER TT_New_Context( TT_Driver driver ); -#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#ifdef TT_USE_BYTECODE_INTERPRETER FT_LOCAL( FT_Error ) TT_Done_Context( TT_ExecContext exec ); @@ -361,7 +361,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) TT_Run_Context( TT_ExecContext exec, FT_Bool debug ); -#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ +#endif /* TT_USE_BYTECODE_INTERPRETER */ /*************************************************************************/ diff --git a/freetype/src/truetype/ttobjs.c b/freetype/src/truetype/ttobjs.c index c61b218c2..7897efa77 100644 --- a/freetype/src/truetype/ttobjs.c +++ b/freetype/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ /* */ /* Objects manager (body). */ /* */ -/* Copyright 1996-2012 */ +/* Copyright 1996-2013 */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -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" @@ -521,7 +522,7 @@ if ( !sfnt ) { FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" )); - error = TT_Err_Missing_Module; + error = FT_THROW( Missing_Module ); goto Exit; } @@ -551,7 +552,7 @@ /* If we are performing a simple font format check, exit immediately. */ if ( face_index < 0 ) - return TT_Err_Ok; + return FT_Err_Ok; /* Load font directory */ error = sfnt->load_face( stream, face, face_index, num_params, params ); @@ -651,7 +652,7 @@ return error; Bad_Format: - error = TT_Err_Unknown_File_Format; + error = FT_THROW( Unknown_File_Format ); goto Exit; } @@ -752,7 +753,7 @@ exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; if ( !exec ) - return TT_Err_Could_Not_Find_Context; + return FT_THROW( Could_Not_Find_Context ); TT_Load_Context( exec, face, size ); @@ -805,7 +806,7 @@ } } else - error = TT_Err_Ok; + error = FT_Err_Ok; if ( !error ) TT_Save_Context( exec, size ); @@ -846,7 +847,7 @@ exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; if ( !exec ) - return TT_Err_Could_Not_Find_Context; + return FT_THROW( Could_Not_Find_Context ); TT_Load_Context( exec, face, size ); @@ -876,7 +877,27 @@ } } else - error = TT_Err_Ok; + error = FT_Err_Ok; + + /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ + /* graphics state variables to be modified by the CVT program. */ + + exec->GS.dualVector.x = 0x4000; + exec->GS.dualVector.y = 0; + exec->GS.projVector.x = 0x4000; + exec->GS.projVector.y = 0x0; + exec->GS.freeVector.x = 0x4000; + exec->GS.freeVector.y = 0x0; + + exec->GS.rp0 = 0; + exec->GS.rp1 = 0; + exec->GS.rp2 = 0; + + exec->GS.gep0 = 1; + exec->GS.gep1 = 1; + exec->GS.gep2 = 1; + + exec->GS.loop = 1; /* save as default graphics state */ size->GS = exec->GS; @@ -1023,7 +1044,7 @@ tt_size_ready_bytecode( TT_Size size, FT_Bool pedantic ) { - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; if ( !size->bytecode_ready ) @@ -1090,7 +1111,7 @@ tt_size_init( FT_Size ttsize ) /* TT_Size */ { TT_Size size = (TT_Size)ttsize; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; #ifdef TT_USE_BYTECODE_INTERPRETER size->bytecode_ready = 0; @@ -1146,7 +1167,7 @@ tt_size_reset( TT_Size size ) { TT_Face face; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; FT_Size_Metrics* metrics; @@ -1160,7 +1181,7 @@ *metrics = size->root.metrics; if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) - return TT_Err_Invalid_PPem; + return FT_THROW( Invalid_PPem ); /* This bit flag, if set, indicates that the ppems must be */ /* rounded to integers. Nearly all TrueType fonts have this bit */ @@ -1237,15 +1258,21 @@ if ( !TT_New_Context( driver ) ) - return TT_Err_Could_Not_Find_Context; + 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 TT_Err_Ok; + return FT_Err_Ok; } diff --git a/freetype/src/truetype/ttobjs.h b/freetype/src/truetype/ttobjs.h index 5c3cb067e..a11dd3752 100644 --- a/freetype/src/truetype/ttobjs.h +++ b/freetype/src/truetype/ttobjs.h @@ -4,7 +4,7 @@ /* */ /* Objects manager (specification). */ /* */ -/* Copyright 1996-2009, 2011-2012 by */ +/* Copyright 1996-2009, 2011-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -173,12 +173,13 @@ 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_Bool inline_delta; /* is function that defines inline delta? */ + 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? */ + FT_ULong sph_fdef_flags; /* flags to identify special functions */ } TT_DefRecord, *TT_DefArray; @@ -334,7 +335,6 @@ FT_BEGIN_HEADER FT_Bool bytecode_ready; FT_Bool cvt_ready; - FT_Bool ttfautohinted; #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -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/freetype/src/truetype/ttpic.c b/freetype/src/truetype/ttpic.c index faece4e81..edefae72c 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, 2012 by */ +/* Copyright 2009, 2010, 2012, 2013 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,21 +22,19 @@ #include "ttpic.h" #include "tterrors.h" + #ifdef FT_CONFIG_OPTION_PIC /* forward declaration of PIC init functions from ttdriver.c */ FT_Error FT_Create_Class_tt_services( FT_Library library, FT_ServiceDescRec** output_class ); - void FT_Destroy_Class_tt_services( FT_Library library, FT_ServiceDescRec* clazz ); - void FT_Init_Class_tt_service_gx_multi_masters( FT_Service_MultiMastersRec* sv_mm ); - void FT_Init_Class_tt_service_truetype_glyf( FT_Service_TTGlyfRec* sv_ttglyf ); @@ -67,13 +65,13 @@ tt_driver_class_pic_init( FT_Library library ) { FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = TT_Err_Ok; + FT_Error error = FT_Err_Ok; TTModulePIC* container = NULL; FT_Memory memory = library->memory; /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC ( container, sizeof ( *container ) ) ) + if ( FT_ALLOC( container, sizeof ( *container ) ) ) return error; FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->truetype = container; @@ -91,7 +89,7 @@ FT_Init_Class_tt_service_truetype_glyf( &container->tt_service_truetype_glyf ); -Exit: + Exit: if ( error ) tt_driver_class_pic_free( library ); return error; diff --git a/freetype/src/truetype/ttpic.h b/freetype/src/truetype/ttpic.h index 625c9f169..cfb4ee628 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, 2012 by */ +/* Copyright 2009, 2012, 2013 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,21 +27,24 @@ FT_BEGIN_HEADER #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 +#define TT_SERVICE_PROPERTIES_GET tt_service_properties #else /* FT_CONFIG_OPTION_PIC */ #include FT_MULTIPLE_MASTERS_H #include FT_SERVICE_MULTIPLE_MASTERS_H #include FT_SERVICE_TRUETYPE_GLYF_H +#include FT_SERVICE_PROPERTIES_H 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; + FT_Service_MultiMastersRec tt_service_gx_multi_masters; #endif - FT_Service_TTGlyfRec tt_service_truetype_glyf; + FT_Service_TTGlyfRec tt_service_truetype_glyf; + FT_Service_PropertiesRec tt_service_properties; } TTModulePIC; @@ -54,6 +57,8 @@ FT_BEGIN_HEADER ( GET_PIC( library )->tt_service_gx_multi_masters ) #define TT_SERVICE_TRUETYPE_GLYF_GET \ ( GET_PIC( library )->tt_service_truetype_glyf ) +#define TT_SERVICE_PROPERTIES_GET \ + ( GET_PIC( library )->tt_service_properties ) /* see ttpic.c for the implementation */ @@ -67,6 +72,7 @@ FT_BEGIN_HEADER /* */ + FT_END_HEADER #endif /* __TTPIC_H__ */ diff --git a/freetype/src/truetype/ttpload.c b/freetype/src/truetype/ttpload.c index bb6005d45..9723a515b 100644 --- a/freetype/src/truetype/ttpload.c +++ b/freetype/src/truetype/ttpload.c @@ -4,7 +4,7 @@ /* */ /* TrueType-specific tables loader (body). */ /* */ -/* Copyright 1996-2002, 2004-2012 by */ +/* Copyright 1996-2002, 2004-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -72,7 +72,7 @@ /* it is possible that a font doesn't have a glyf table at all */ /* or its size is zero */ - if ( error == TT_Err_Table_Missing ) + if ( FT_ERR_EQ( error, Table_Missing ) ) face->glyf_len = 0; else if ( error ) goto Exit; @@ -81,7 +81,7 @@ error = face->goto_table( face, TTAG_loca, stream, &table_len ); if ( error ) { - error = TT_Err_Locations_Missing; + error = FT_THROW( Locations_Missing ); goto Exit; } @@ -92,7 +92,7 @@ if ( table_len >= 0x40000L ) { FT_TRACE2(( "table too large\n" )); - error = TT_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Exit; } face->num_locations = table_len >> shift; @@ -104,7 +104,7 @@ if ( table_len >= 0x20000L ) { FT_TRACE2(( "table too large\n" )); - error = TT_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Exit; } face->num_locations = table_len >> shift; @@ -296,7 +296,7 @@ face->cvt_size = 0; face->cvt = NULL; - error = TT_Err_Ok; + error = FT_Err_Ok; goto Exit; } @@ -334,7 +334,7 @@ FT_UNUSED( face ); FT_UNUSED( stream ); - return TT_Err_Ok; + return FT_Err_Ok; #endif } @@ -375,7 +375,7 @@ { face->font_program = NULL; face->font_program_size = 0; - error = TT_Err_Ok; + error = FT_Err_Ok; FT_TRACE2(( "is missing\n" )); } @@ -396,7 +396,7 @@ FT_UNUSED( face ); FT_UNUSED( stream ); - return TT_Err_Ok; + return FT_Err_Ok; #endif } @@ -436,7 +436,7 @@ { face->cvt_program = NULL; face->cvt_program_size = 0; - error = TT_Err_Ok; + error = FT_Err_Ok; FT_TRACE2(( "is missing\n" )); } @@ -457,7 +457,7 @@ FT_UNUSED( face ); FT_UNUSED( stream ); - return TT_Err_Ok; + return FT_Err_Ok; #endif } @@ -495,7 +495,7 @@ /* this table is optional */ error = face->goto_table( face, TTAG_hdmx, stream, &table_size ); if ( error || table_size < 8 ) - return TT_Err_Ok; + return FT_Err_Ok; if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) ) goto Exit; @@ -525,7 +525,7 @@ if ( version != 0 || num_records > 255 || record_size > 0x10001L ) { - error = TT_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Fail; } diff --git a/freetype/src/truetype/ttsubpix.c b/freetype/src/truetype/ttsubpix.c index d09d3d89d..28470ad65 100644 --- a/freetype/src/truetype/ttsubpix.c +++ b/freetype/src/truetype/ttsubpix.c @@ -4,7 +4,7 @@ /* */ /* TrueType Subpixel Hinting. */ /* */ -/* Copyright 2010-2012 by */ +/* Copyright 2010-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,12 +22,728 @@ #include FT_INTERNAL_SFNT_H #include FT_TRUETYPE_TAGS_H #include FT_OUTLINE_H +#include FT_TRUETYPE_DRIVER_H #include "ttsubpix.h" #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /*************************************************************************/ + /* */ + /* 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 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 + + static const SPH_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 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 */ + + + /* 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 + + const SPH_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", + "", + }, + }, + }; + + + /* Force special legacy fixes for fonts. */ +#define COMPATIBILITY_MODE_RULES_SIZE 1 + + const SPH_TweakRule COMPATIBILITY_MODE_Rules + [COMPATIBILITY_MODE_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */ +#define PIXEL_HINTING_RULES_SIZE 2 + + const SPH_TweakRule PIXEL_HINTING_Rules + [PIXEL_HINTING_RULES_SIZE] = + { + /* these characters are almost always safe */ + { "Courier New", 12, "Italic", 'z' }, + { "Courier New", 11, "Italic", 'z' }, + }; + + + /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */ +#define DO_SHPIX_RULES_SIZE 1 + + const 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 4 + + const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules + [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] = + { + /* fix vwxyz thinness*/ + { "Consolas", 0, "", 0 }, + /* Fix thin middle stems */ + { "Core MS Legacy Fonts", 0, "Regular", 0 }, + /* Cyrillic small letter I */ + { "Legacy Sans Fonts", 0, "", 0 }, + /* Fix artifacts with some Regular & Bold */ + { "Verdana Clones", 0, "", 0 }, + }; + + +#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 + + const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions + [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = + { + /* Fixes < and > */ + { "Courier New", 0, "Regular", 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_DELTAP_RULES_SIZE 2 + + const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules + [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] = + { + /* Maintain thickness of diagonal in 'N' */ + { "Times New Roman", 0, "Regular/Bold Class", 'N' }, + { "Georgia", 0, "Regular/Bold Class", 'N' }, + }; + + + /* Skip Y moves that move a point off a Y pixel boundary. */ +#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1 + + const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules + [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + +#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 + + const 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 2 + + const 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 }, + }; + + +#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 + + const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions + [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Allow a Direct_Move along X freedom vector if matched. */ +#define ALLOW_X_DMOVE_RULES_SIZE 1 + + const SPH_TweakRule ALLOW_X_DMOVE_Rules + [ALLOW_X_DMOVE_RULES_SIZE] = + { + /* Fixes vanishing diagonal in 4 */ + { "Verdana", 0, "Regular", '4' }, + }; + + + /* Return MS rasterizer version 35 if matched. */ +#define RASTERIZER_35_RULES_SIZE 8 + + const 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 1 + + const SPH_TweakRule NORMAL_ROUND_Rules + [NORMAL_ROUND_RULES_SIZE] = + { + /* Fix serif thickness for certain ppems */ + /* Can probably be generalized somehow */ + { "Courier New", 0, "", 0 }, + }; + + + /* Skip IUP instructions if matched. */ +#define SKIP_IUP_RULES_SIZE 1 + + const 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 + + const SPH_TweakRule MIAP_HACK_Rules + [MIAP_HACK_RULES_SIZE] = + { + { "Geneva", 12, "", 0 }, + }; + + + /* Skip DELTAP instructions if matched. */ +#define ALWAYS_SKIP_DELTAP_RULES_SIZE 23 + + const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules + [ALWAYS_SKIP_DELTAP_RULES_SIZE] = + { + { "Georgia", 0, "Regular", 'k' }, + /* fix various problems with e in different versions */ + { "Trebuchet MS", 14, "Regular", 'e' }, + { "Trebuchet MS", 13, "Regular", 'e' }, + { "Trebuchet MS", 15, "Regular", 'e' }, + { "Trebuchet MS", 0, "Italic", 'v' }, + { "Trebuchet MS", 0, "Italic", 'w' }, + { "Trebuchet MS", 0, "Regular", 'Y' }, + { "Arial", 11, "Regular", 's' }, + /* prevent problems with '3' and others */ + { "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", 'a' }, + { "Arial", 25, "Bold", 'a' }, + { "Arial", 24, "Bold", 's' }, + { "Arial", 25, "Bold", 's' }, + { "Arial", 34, "Bold", 's' }, + { "Arial", 35, "Bold", 's' }, + { "Arial", 36, "Bold", 's' }, + { "Arial", 25, "Regular", 's' }, + { "Arial", 26, "Regular", 's' }, + }; + + + /* Always do DELTAP instructions if matched. */ +#define ALWAYS_DO_DELTAP_RULES_SIZE 1 + + const SPH_TweakRule ALWAYS_DO_DELTAP_Rules + [ALWAYS_DO_DELTAP_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Don't allow ALIGNRP after IUP. */ +#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 1 + + static const SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules + [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] = + { + /* Prevent creation of dents in outline */ + { "-", 0, "", 0 }, + }; + + + /* Don't allow DELTAP after IUP. */ +#define NO_DELTAP_AFTER_IUP_RULES_SIZE 1 + + static const SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules + [NO_DELTAP_AFTER_IUP_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + + /* Don't allow CALL after IUP. */ +#define NO_CALL_AFTER_IUP_RULES_SIZE 1 + + static const SPH_TweakRule NO_CALL_AFTER_IUP_Rules + [NO_CALL_AFTER_IUP_RULES_SIZE] = + { + /* Prevent creation of dents in outline */ + { "-", 0, "", 0 }, + }; + + + /* De-embolden these glyphs slightly. */ +#define DEEMBOLDEN_RULES_SIZE 9 + + static const 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 2 + + static const SPH_TweakRule EMBOLDEN_Rules + [EMBOLDEN_RULES_SIZE] = + { + { "Courier New", 0, "Regular", 0 }, + { "Courier New", 0, "Italic", 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 + + static const 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 + + static const 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 + + static const 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 + + static const 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 + + static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules + [COMPATIBLE_WIDTHS_RULES_SIZE] = + { + { "-", 0, "", 0 }, + }; + + +#define X_SCALING_RULES_SIZE 1 + + static const SPH_ScaleRule X_SCALING_Rules + [X_SCALING_RULES_SIZE] = + { + { "-", 0, "", 0, 1000 }, + }; + +#endif /* FORCE_NATURAL_WIDTHS */ + + FT_LOCAL_DEF( FT_Bool ) is_member_of_family_class( const FT_String* detected_font_name, const FT_String* rule_font_name ) @@ -48,7 +764,7 @@ { if ( strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) { - for ( j = 0; j < MAX_CLASS_MEMBERS; j++ ) + for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) { if ( strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) continue; @@ -83,7 +799,7 @@ { if ( strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) { - for ( j = 0; j < MAX_CLASS_MEMBERS; j++ ) + for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) { if ( strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) continue; @@ -99,13 +815,13 @@ 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 ) + sph_test_tweak( TT_Face face, + const FT_String* family, + FT_UInt ppem, + const FT_String* style, + FT_UInt glyph_index, + const SPH_TweakRule* rule, + FT_UInt num_rules ) { FT_UInt i; @@ -129,14 +845,14 @@ } - 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 ) + static FT_UInt + scale_test_tweak( TT_Face face, + const FT_String* family, + FT_UInt ppem, + const FT_String* style, + FT_UInt glyph_index, + const SPH_ScaleRule* rule, + FT_UInt num_rules ) { FT_UInt i; @@ -160,6 +876,18 @@ } + FT_LOCAL_DEF( FT_UInt ) + sph_test_tweak_x_scaling( TT_Face face, + const FT_String* family, + FT_UInt ppem, + const FT_String* style, + FT_UInt glyph_index ) + { + return scale_test_tweak( face, family, ppem, style, glyph_index, + X_SCALING_Rules, X_SCALING_RULES_SIZE ); + } + + #define TWEAK_RULES( x ) \ if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ x##_Rules, x##_RULES_SIZE ) ) \ @@ -199,12 +927,9 @@ } 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 ); @@ -213,13 +938,13 @@ 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_DELTAP ); + TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES ); TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES ); @@ -227,14 +952,34 @@ TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES ); if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - loader->exec->rasterizer_version = 35; + { + if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 ) + { + loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; + loader->exec->size->cvt_ready = FALSE; + + tt_size_ready_bytecode( + loader->exec->size, + FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); + } + else + loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; + } else - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; + { + if ( loader->exec->rasterizer_version != + SPH_OPTION_SET_RASTERIZER_VERSION ) + { + loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; + loader->exec->size->cvt_ready = FALSE; - /* 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 ) ); + tt_size_ready_bytecode( + loader->exec->size, + FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); + } + else + loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; + } if ( IS_HINTED( loader->load_flags ) ) { @@ -244,12 +989,8 @@ 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; + loader->exec->face->sph_compatibility_mode = TRUE; + if ( IS_HINTED( loader->load_flags ) ) { @@ -259,7 +1000,12 @@ } } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_subpix_dummy; + +#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ /* END */ diff --git a/freetype/src/truetype/ttsubpix.h b/freetype/src/truetype/ttsubpix.h index 2fbff2681..8a54fc7cc 100644 --- a/freetype/src/truetype/ttsubpix.h +++ b/freetype/src/truetype/ttsubpix.h @@ -4,7 +4,7 @@ /* */ /* TrueType Subpixel Hinting. */ /* */ -/* Copyright 2010-2012 by */ +/* Copyright 2010-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,90 +29,70 @@ FT_BEGIN_HEADER #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + /*************************************************************************/ + /* */ + /* ID flags to identify special functions at FDEF and runtime. */ + /* */ + /* */ +#define SPH_FDEF_INLINE_DELTA_1 0x0000001 +#define SPH_FDEF_INLINE_DELTA_2 0x0000002 +#define SPH_FDEF_DIAGONAL_STROKE 0x0000004 +#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008 +#define SPH_FDEF_TTFAUTOHINT_1 0x0000010 +#define SPH_FDEF_SPACING_1 0x0000020 +#define SPH_FDEF_SPACING_2 0x0000040 +#define SPH_FDEF_TYPEMAN_STROKES 0x0000080 +#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100 + + /*************************************************************************/ /* */ /* 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 +#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002 +#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004 +#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008 +#define SPH_TWEAK_DEEMBOLDEN 0x0000010 +#define SPH_TWEAK_DO_SHPIX 0x0000020 +#define SPH_TWEAK_EMBOLDEN 0x0000040 +#define SPH_TWEAK_MIAP_HACK 0x0000080 +#define SPH_TWEAK_NORMAL_ROUND 0x0000100 +#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200 +#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400 +#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800 +#define SPH_TWEAK_PIXEL_HINTING 0x0001000 +#define SPH_TWEAK_RASTERIZER_35 0x0002000 +#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000 +#define SPH_TWEAK_SKIP_IUP 0x0008000 +#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000 +#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000 +#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000 +#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000 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 ); + sph_test_tweak( TT_Face face, + const FT_String* family, + FT_UInt ppem, + const FT_String* style, + FT_UInt glyph_index, + const SPH_TweakRule* rule, + FT_UInt num_rules ); + + FT_LOCAL( FT_UInt ) + sph_test_tweak_x_scaling( TT_Face face, + const FT_String* family, + FT_UInt ppem, + const FT_String* style, + FT_UInt glyph_index ); 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 @@ -120,784 +100,6 @@ FT_BEGIN_HEADER #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 */ -- cgit v1.2.3