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.
This commit is contained in:
Werner Lemberg 2009-04-27 19:40:35 +02:00
parent b5a460597a
commit 8b84c9d19f
10 changed files with 201 additions and 31 deletions

View File

@ -1,3 +1,28 @@
2009-04-27 Werner Lemberg <wl@gnu.org>
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 <wl@gnu.org> 2009-04-26 Werner Lemberg <wl@gnu.org>
Make ftgrays compile with _STANDALONE_ and FT_STATIC_RASTER again. Make ftgrays compile with _STANDALONE_ and FT_STATIC_RASTER again.

View File

@ -1,6 +1,12 @@
CHANGES BETWEEN 2.3.10 and 2.3.9 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 - Support for the SFNT cmap 13 table format (as defined by the new
OpenType 1.6 specification) has been added. OpenType 1.6 specification) has been added.

View File

@ -4,7 +4,7 @@
/* */ /* */
/* Auto-fitter hinting routines for CJK script (body). */ /* 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. */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */ /* */
/* This file is part of the FreeType project, and may only be used, */ /* 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 ) ) if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
face->charmap = NULL; face->charmap = NULL;
else
/* latin's version would suffice */ {
af_latin_metrics_init_widths( metrics, face, 0x7530 ); /* 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 ); FT_Set_Charmap( face, oldmap );

View File

@ -4,7 +4,7 @@
/* */ /* */
/* Auto-fitter routines to compute global hinting values (body). */ /* 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. */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */ /* */
/* This file is part of the FreeType project, and may only be used, */ /* 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' */ /* index of default script in `af_script_classes' */
#define AF_SCRIPT_LIST_DEFAULT 2 #define AF_SCRIPT_LIST_DEFAULT 2
/* indicates an uncovered glyph */ /* a bit mask indicating an uncovered glyph */
#define AF_SCRIPT_LIST_NONE 255 #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_Face face = globals->face;
FT_CharMap old_charmap = face->charmap; FT_CharMap old_charmap = face->charmap;
FT_Byte* gscripts = globals->glyph_scripts; FT_Byte* gscripts = globals->glyph_scripts;
FT_UInt ss; FT_UInt ss, i;
/* the value 255 means `uncovered glyph' */ /* 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: Exit:
/* /*
* By default, all uncovered glyphs are set to the latin script. * By default, all uncovered glyphs are set to the latin script.
@ -253,7 +265,7 @@
gidx = script; gidx = script;
if ( gidx == 0 || gidx + 1 >= script_max ) 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]; clazz = AF_SCRIPT_CLASSES_GET[gidx];
if ( script == 0 ) 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 */ /* END */

View File

@ -5,7 +5,7 @@
/* Auto-fitter routines to compute global hinting values */ /* Auto-fitter routines to compute global hinting values */
/* (specification). */ /* (specification). */
/* */ /* */
/* Copyright 2003, 2004, 2005, 2007 by */ /* Copyright 2003, 2004, 2005, 2007, 2009 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */ /* */
/* This file is part of the FreeType project, and may only be used, */ /* This file is part of the FreeType project, and may only be used, */
@ -56,7 +56,11 @@ FT_BEGIN_HEADER
FT_LOCAL( void ) FT_LOCAL( void )
af_face_globals_free( AF_FaceGlobals globals ); 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 FT_END_HEADER

View File

@ -4,7 +4,7 @@
/* */ /* */
/* Auto-fitter hinting routines for latin script (body). */ /* 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. */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */ /* */
/* This file is part of the FreeType project, and may only be used, */ /* 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 "aflatin.h"
#include "aferrors.h" #include "aferrors.h"
@ -146,7 +148,8 @@
#define AF_LATIN_MAX_TEST_CHARACTERS 12 #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", "THEZOCQS",
"HEZLOCUS", "HEZLOCUS",
@ -379,7 +382,7 @@
blue->flags |= AF_LATIN_BLUE_TOP; 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 * in order to optimize the pixel grid alignment of the top of small
* letters. * 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 ) FT_LOCAL_DEF( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics, af_latin_metrics_init( AF_LatinMetrics metrics,
FT_Face face ) FT_Face face )
@ -426,6 +475,7 @@
/* For now, compute the standard width and height from the `o'. */ /* For now, compute the standard width and height from the `o'. */
af_latin_metrics_init_widths( metrics, face, 'o' ); af_latin_metrics_init_widths( metrics, face, 'o' );
af_latin_metrics_init_blues( metrics, face ); af_latin_metrics_init_blues( metrics, face );
af_latin_metrics_check_digits( metrics, face );
} }
FT_Set_Charmap( face, oldmap ); FT_Set_Charmap( face, oldmap );

View File

@ -4,7 +4,7 @@
/* */ /* */
/* Auto-fitter hinting routines for latin script (specification). */ /* 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. */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */ /* */
/* This file is part of the FreeType project, and may only be used, */ /* This file is part of the FreeType project, and may only be used, */
@ -137,6 +137,10 @@ FT_BEGIN_HEADER
FT_Face face, FT_Face face,
FT_ULong charcode ); FT_ULong charcode );
FT_LOCAL( void )
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face );
/*************************************************************************/ /*************************************************************************/
/*************************************************************************/ /*************************************************************************/

View File

@ -16,6 +16,8 @@
/***************************************************************************/ /***************************************************************************/
#include FT_ADVANCES_H
#include "aflatin.h" #include "aflatin.h"
#include "aflatin2.h" #include "aflatin2.h"
#include "aferrors.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 ) FT_LOCAL_DEF( FT_Error )
af_latin2_metrics_init( AF_LatinMetrics metrics, af_latin2_metrics_init( AF_LatinMetrics metrics,
FT_Face face ) FT_Face face )
@ -434,6 +482,7 @@
/* For now, compute the standard width and height from the `o'. */ /* For now, compute the standard width and height from the `o'. */
af_latin2_metrics_init_widths( metrics, face, 'o' ); af_latin2_metrics_init_widths( metrics, face, 'o' );
af_latin2_metrics_init_blues( metrics, face ); af_latin2_metrics_init_blues( metrics, face );
af_latin2_metrics_check_digits( metrics, face );
} }
FT_Set_Charmap( face, oldmap ); FT_Set_Charmap( face, oldmap );

View File

@ -183,9 +183,9 @@
if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) ) if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
{ {
old_rsb = loader->pp2.x - edge2->opos; old_rsb = loader->pp2.x - edge2->opos;
old_lsb = edge1->opos; old_lsb = edge1->opos;
new_lsb = edge1->pos; new_lsb = edge1->pos;
/* remember unhinted values to later account */ /* remember unhinted values to later account */
/* for rounding errors */ /* for rounding errors */
@ -216,8 +216,9 @@
} }
else else
{ {
FT_Pos pp1x = loader->pp1.x; FT_Pos pp1x = loader->pp1.x;
FT_Pos pp2x = loader->pp2.x; FT_Pos pp2x = loader->pp2.x;
loader->pp1.x = FT_PIX_ROUND( pp1x ); loader->pp1.x = FT_PIX_ROUND( pp1x );
loader->pp2.x = FT_PIX_ROUND( pp2x ); loader->pp2.x = FT_PIX_ROUND( pp2x );
@ -228,8 +229,9 @@
} }
else else
{ {
FT_Pos pp1x = loader->pp1.x; FT_Pos pp1x = loader->pp1.x;
FT_Pos pp2x = loader->pp2.x; FT_Pos pp2x = loader->pp2.x;
loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta ); loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_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 ); slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );
/* for mono-width fonts (like Andale, Courier, etc.) we need */ /* 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 0
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) if ( !FT_IS_FIXED_WIDTH( slot->face ) )
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
@ -420,13 +423,9 @@
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
x_scale ); x_scale );
#else #else
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) if ( FT_IS_FIXED_WIDTH( slot->face ) ||
{ ( af_face_globals_is_digit( loader->globals, glyph_index ) &&
/* non-spacing glyphs must stay as-is */ metrics->digits_have_same_width ) )
if ( slot->metrics.horiAdvance )
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
}
else
{ {
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
metrics->scaler.x_scale ); metrics->scaler.x_scale );
@ -436,6 +435,12 @@
slot->lsb_delta = 0; slot->lsb_delta = 0;
slot->rsb_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 #endif
slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance, slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,

View File

@ -285,6 +285,7 @@ extern void* _af_debug_hints;
{ {
AF_ScriptClass clazz; AF_ScriptClass clazz;
AF_ScalerRec scaler; AF_ScalerRec scaler;
FT_Bool digits_have_same_width;
} AF_ScriptMetricsRec, *AF_ScriptMetrics; } AF_ScriptMetricsRec, *AF_ScriptMetrics;