diff --git a/ChangeLog b/ChangeLog index b13701c96..ba9ca2fa1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2009-04-27 Werner Lemberg + + autohinter: Don't change digit widths if all widths are the same. + This fixes FreeDesktop bug #21197. + + * src/autofit/afglobal.c (AF_DIGIT): New macro. + (af_face_globals_compute_script_coverage): Mark ASCII digits in + `glyph_scripts' array. + (af_face_globals_get_metrics): Updated. + (af_face_globals_is_digit): New function. + * src/autofit/afglobal.h: Updated. + (AF_ScriptMetricsRec): Add `digits_have_same_width' flag. + + * src/autofit/aflatin.c: Include FT_ADVANCES_H. + (af_latin_metrics_check_digits): New function. + (af_latin_metrics_init): Use it. + * src/autofit/aflatin.h: Updated. + * src/autofit/afcjk.c (af_cjk_metrics_init): Updated. + + * src/autofit/aflatin2.c: Similar changes as with aflatin.c. + + * src/autofit/afloader.c (af_loader_load_g): Test digit width. + + * docs/CHANGES: Document it. + 2009-04-26 Werner Lemberg Make ftgrays compile with _STANDALONE_ and FT_STATIC_RASTER again. diff --git a/docs/CHANGES b/docs/CHANGES index e04067563..c46bd2338 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -1,6 +1,12 @@ CHANGES BETWEEN 2.3.10 and 2.3.9 - I. IMPORTANT CHANGES + I. IMPORTANT BUG FIXES + + - If all ASCII digits in a font have the same (unscaled) width, + the autohinter respects this and won't change it. + + + II. IMPORTANT CHANGES - Support for the SFNT cmap 13 table format (as defined by the new OpenType 1.6 specification) has been added. diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c index aead80035..9a473f4bf 100644 --- a/src/autofit/afcjk.c +++ b/src/autofit/afcjk.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for CJK script (body). */ /* */ -/* Copyright 2006, 2007, 2008 by */ +/* Copyright 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -58,9 +58,12 @@ if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) face->charmap = NULL; - - /* latin's version would suffice */ - af_latin_metrics_init_widths( metrics, face, 0x7530 ); + else + { + /* latin's version would suffice */ + af_latin_metrics_init_widths( metrics, face, 0x7530 ); + af_latin_metrics_check_digits( metrics, face ); + } FT_Set_Charmap( face, oldmap ); diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c index 53d18beba..452e70414 100644 --- a/src/autofit/afglobal.c +++ b/src/autofit/afglobal.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter routines to compute global hinting values (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2008 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -51,8 +51,10 @@ /* index of default script in `af_script_classes' */ #define AF_SCRIPT_LIST_DEFAULT 2 - /* indicates an uncovered glyph */ -#define AF_SCRIPT_LIST_NONE 255 + /* a bit mask indicating an uncovered glyph */ +#define AF_SCRIPT_LIST_NONE 0x7F + /* if this flag is set, we have an ASCII digit */ +#define AF_DIGIT 0x80 /* @@ -80,7 +82,7 @@ FT_Face face = globals->face; FT_CharMap old_charmap = face->charmap; FT_Byte* gscripts = globals->glyph_scripts; - FT_UInt ss; + FT_UInt ss, i; /* the value 255 means `uncovered glyph' */ @@ -144,6 +146,16 @@ } } + /* mark ASCII digits */ + for ( i = 0x30; i <= 0x39; i++ ) + { + FT_UInt gindex = FT_Get_Char_Index( face, i ); + + + if ( gindex != 0 && gindex < globals->glyph_count ) + gscripts[gindex] |= AF_DIGIT; + } + Exit: /* * By default, all uncovered glyphs are set to the latin script. @@ -253,7 +265,7 @@ gidx = script; if ( gidx == 0 || gidx + 1 >= script_max ) - gidx = globals->glyph_scripts[gindex]; + gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE; clazz = AF_SCRIPT_CLASSES_GET[gidx]; if ( script == 0 ) @@ -294,4 +306,15 @@ } + FT_LOCAL_DEF( FT_Bool ) + af_face_globals_is_digit( AF_FaceGlobals globals, + FT_UInt gindex ) + { + if ( gindex < globals->glyph_count ) + return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT ); + + return (FT_Bool)0; + } + + /* END */ diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h index cf52c0875..2a68e1960 100644 --- a/src/autofit/afglobal.h +++ b/src/autofit/afglobal.h @@ -5,7 +5,7 @@ /* Auto-fitter routines to compute global hinting values */ /* (specification). */ /* */ -/* Copyright 2003, 2004, 2005, 2007 by */ +/* Copyright 2003, 2004, 2005, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -56,7 +56,11 @@ FT_BEGIN_HEADER FT_LOCAL( void ) af_face_globals_free( AF_FaceGlobals globals ); - /* */ + FT_LOCAL_DEF( FT_Bool ) + af_face_globals_is_digit( AF_FaceGlobals globals, + FT_UInt gindex ); + + /* */ FT_END_HEADER diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 81770262b..148eb1e5b 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for latin script (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2008 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -16,6 +16,8 @@ /***************************************************************************/ +#include FT_ADVANCES_H + #include "aflatin.h" #include "aferrors.h" @@ -146,7 +148,8 @@ #define AF_LATIN_MAX_TEST_CHARACTERS 12 - static const char af_latin_blue_chars[AF_LATIN_MAX_BLUES][AF_LATIN_MAX_TEST_CHARACTERS+1] = + static const char af_latin_blue_chars[AF_LATIN_MAX_BLUES] + [AF_LATIN_MAX_TEST_CHARACTERS + 1] = { "THEZOCQS", "HEZLOCUS", @@ -379,7 +382,7 @@ blue->flags |= AF_LATIN_BLUE_TOP; /* - * The following flags is used later to adjust the y and x scales + * The following flag is used later to adjust the y and x scales * in order to optimize the pixel grid alignment of the top of small * letters. */ @@ -393,6 +396,52 @@ } + FT_LOCAL_DEF( void ) + af_latin_metrics_check_digits( AF_LatinMetrics metrics, + FT_Face face ) + { + FT_UInt i; + FT_Bool started = 0, same_width = 1; + + + /* check whether all ASCII digits have the same advance width; */ + /* digit `0' is 0x30 in all supported charmaps */ + for ( i = 0x30; i <= 0x39; i++ ) + { + FT_UInt glyph_index; + FT_Fixed advance, old_advance; + + + glyph_index = FT_Get_Char_Index( face, i ); + if ( glyph_index == 0 ) + continue; + + if ( FT_Get_Advance( face, glyph_index, + FT_LOAD_NO_SCALE | + FT_LOAD_NO_HINTING | + FT_LOAD_IGNORE_TRANSFORM, + &advance ) ) + continue; + + if ( started ) + { + if ( advance != old_advance ) + { + same_width = 0; + break; + } + } + else + { + old_advance = advance; + started = 1; + } + } + + metrics->root.digits_have_same_width = same_width; + } + + FT_LOCAL_DEF( FT_Error ) af_latin_metrics_init( AF_LatinMetrics metrics, FT_Face face ) @@ -426,6 +475,7 @@ /* For now, compute the standard width and height from the `o'. */ af_latin_metrics_init_widths( metrics, face, 'o' ); af_latin_metrics_init_blues( metrics, face ); + af_latin_metrics_check_digits( metrics, face ); } FT_Set_Charmap( face, oldmap ); diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h index bdd4b0927..660b10c83 100644 --- a/src/autofit/aflatin.h +++ b/src/autofit/aflatin.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for latin script (specification). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -137,6 +137,10 @@ FT_BEGIN_HEADER FT_Face face, FT_ULong charcode ); + FT_LOCAL( void ) + af_latin_metrics_check_digits( AF_LatinMetrics metrics, + FT_Face face ); + /*************************************************************************/ /*************************************************************************/ diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c index f85a685fc..58c07832e 100644 --- a/src/autofit/aflatin2.c +++ b/src/autofit/aflatin2.c @@ -16,6 +16,8 @@ /***************************************************************************/ +#include FT_ADVANCES_H + #include "aflatin.h" #include "aflatin2.h" #include "aferrors.h" @@ -401,6 +403,52 @@ } + FT_LOCAL_DEF( void ) + af_latin2_metrics_check_digits( AF_LatinMetrics metrics, + FT_Face face ) + { + FT_UInt i; + FT_Bool started = 0, same_width = 1; + + + /* check whether all ASCII digits have the same advance width; */ + /* digit `0' is 0x30 in all supported charmaps */ + for ( i = 0x30; i <= 0x39; i++ ) + { + FT_UInt glyph_index; + FT_Fixed advance, old_advance; + + + glyph_index = FT_Get_Char_Index( face, i ); + if ( glyph_index == 0 ) + continue; + + if ( FT_Get_Advance( face, glyph_index, + FT_LOAD_NO_SCALE | + FT_LOAD_NO_HINTING | + FT_LOAD_IGNORE_TRANSFORM, + &advance ) ) + continue; + + if ( started ) + { + if ( advance != old_advance ) + { + same_width = 0; + break; + } + } + else + { + old_advance = advance; + started = 1; + } + } + + metrics->root.digits_have_same_width = same_width; + } + + FT_LOCAL_DEF( FT_Error ) af_latin2_metrics_init( AF_LatinMetrics metrics, FT_Face face ) @@ -434,6 +482,7 @@ /* For now, compute the standard width and height from the `o'. */ af_latin2_metrics_init_widths( metrics, face, 'o' ); af_latin2_metrics_init_blues( metrics, face ); + af_latin2_metrics_check_digits( metrics, face ); } FT_Set_Charmap( face, oldmap ); diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c index 45f4a2538..6dd9f2a31 100644 --- a/src/autofit/afloader.c +++ b/src/autofit/afloader.c @@ -183,9 +183,9 @@ if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) ) { - old_rsb = loader->pp2.x - edge2->opos; - old_lsb = edge1->opos; - new_lsb = edge1->pos; + old_rsb = loader->pp2.x - edge2->opos; + old_lsb = edge1->opos; + new_lsb = edge1->pos; /* remember unhinted values to later account */ /* for rounding errors */ @@ -216,8 +216,9 @@ } else { - FT_Pos pp1x = loader->pp1.x; - FT_Pos pp2x = loader->pp2.x; + FT_Pos pp1x = loader->pp1.x; + FT_Pos pp2x = loader->pp2.x; + loader->pp1.x = FT_PIX_ROUND( pp1x ); loader->pp2.x = FT_PIX_ROUND( pp2x ); @@ -228,8 +229,9 @@ } else { - FT_Pos pp1x = loader->pp1.x; - FT_Pos pp2x = loader->pp2.x; + FT_Pos pp1x = loader->pp1.x; + FT_Pos pp2x = loader->pp2.x; + loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta ); loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta ); @@ -412,7 +414,8 @@ slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y ); /* for mono-width fonts (like Andale, Courier, etc.) we need */ - /* to keep the original rounded advance width */ + /* to keep the original rounded advance width; ditto for */ + /* digits if all have the same advance width */ #if 0 if ( !FT_IS_FIXED_WIDTH( slot->face ) ) slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; @@ -420,13 +423,9 @@ slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, x_scale ); #else - if ( !FT_IS_FIXED_WIDTH( slot->face ) ) - { - /* non-spacing glyphs must stay as-is */ - if ( slot->metrics.horiAdvance ) - slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; - } - else + if ( FT_IS_FIXED_WIDTH( slot->face ) || + ( af_face_globals_is_digit( loader->globals, glyph_index ) && + metrics->digits_have_same_width ) ) { slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, metrics->scaler.x_scale ); @@ -436,6 +435,12 @@ slot->lsb_delta = 0; slot->rsb_delta = 0; } + else + { + /* non-spacing glyphs must stay as-is */ + if ( slot->metrics.horiAdvance ) + slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; + } #endif slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance, diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h index b1d1b567c..5972f2e05 100644 --- a/src/autofit/aftypes.h +++ b/src/autofit/aftypes.h @@ -285,6 +285,7 @@ extern void* _af_debug_hints; { AF_ScriptClass clazz; AF_ScalerRec scaler; + FT_Bool digits_have_same_width; } AF_ScriptMetricsRec, *AF_ScriptMetrics;