From 7d62f526fed7aebbe63421a54311792da0e62ff8 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Fri, 4 Jun 2004 22:30:10 +0000 Subject: [PATCH] * docs/CHANGES: Updated. Improve inter-letter spacing for autohinted glyphs. * include/freetype/freetype.h (FT_Glyph_Metrics): Add elements `lsb_delta' and `rsb_delta'. * src/autohint/ahhint.c (ah_hinter_load): Set `lsb_delta' and `rsb_delta' in slot->metrics. --- ChangeLog | 30 ++++++++++---- docs/CHANGES | 13 ++++++- include/freetype/freetype.h | 78 +++++++++++++++++++++++++++++-------- src/autohint/ahhint.c | 22 +++++++++-- 4 files changed, 115 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0890dc410..ec66ec9dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,15 +1,29 @@ +2004-06-04 Werner Lemberg + + * docs/CHANGES: Updated. + +2004-06-04 David Chester + + Improve inter-letter spacing for autohinted glyphs. + + * include/freetype/freetype.h (FT_Glyph_Metrics): Add elements + `lsb_delta' and `rsb_delta'. + + * src/autohint/ahhint.c (ah_hinter_load): Set `lsb_delta' and + `rsb_delta' in slot->metrics. + 2004-06-04 David Turner - * src/autofit/*: important fixes to the auto-fitter. The output - now seems to be 100% equivalent to the auto-hinter, while being - about 2% faster (which proves that script-specific algorithm - selection isn't a performance problem). + * src/autofit/*: Important fixes to the auto-fitter. The output + now seems to be 100% equivalent to the auto-hinter, while being + about 2% faster (which proves that script-specific algorithm + selection isn't a performance problem). - to test it, change "autohint" to "autofit" in - and recompile. + To test it, change `autohint' to `autofit' in + and recompile. - a few more testing is needed before making this the official - auto-hinting module + A few more testing is needed before making this the official + auto-hinting module. 2004-06-02 Werner Lemberg diff --git a/docs/CHANGES b/docs/CHANGES index 4ab413be1..550b722c3 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -8,13 +8,24 @@ LATEST CHANGES BETWEEN 2.1.9 and 2.1.8 `FT_Get_Charmap_Index'. (This function is needed to implement cmap caches.) + - `FT_Outline_Get_BBox' sometimes returned incorrect values for + conic outlines (e.g. for TrueType fonts). + + - Handling of `bhed' table has been fixed. II. IMPORTANT CHANGES - George Williams contributed code to handle Apple's font distortion technology found in GX fonts (`avar', `cvar', `fvar', and `gvar' tables; the Multiple Masters API has been slightly - extended to cope with the new functionality. + extended to cope with the new functionality). + + - The `FT_Glyph_Metrics' structure has been extended: The elements + `lsb_delta' and `rsb_delta' give the difference between hinted + and unhinted left and right side bearings if autohinting is + active. Using those values can improve the inter-letter spacing + considerably. See the documentation of `FT_Glyph_Metrics' and + the `ftstring' demo program how to use it. III. MISCELLANEOUS diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index 72870052b..453db7454 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -189,34 +189,80 @@ FT_BEGIN_HEADER /* instead. */ /* */ /* */ - /* width :: The glyph's width. */ + /* width :: */ + /* The glyph's width. */ /* */ - /* height :: The glyph's height. */ + /* height :: */ + /* The glyph's height. */ /* */ - /* horiBearingX :: Horizontal left side bearing. */ + /* horiBearingX :: */ + /* Left side bearing for horizontal layout. */ /* */ - /* horiBearingY :: Horizontal top side bearing. */ + /* horiBearingY :: */ + /* Top side bearing for horizontal layout. */ /* */ - /* horiAdvance :: Horizontal advance width. */ + /* horiAdvance :: */ + /* Advance width for horizontal layout. */ /* */ - /* vertBearingX :: Vertical left side bearing. */ + /* vertBearingX :: */ + /* Left side bearing for vertical layout. */ /* */ - /* vertBearingY :: Vertical top side bearing. */ + /* vertBearingY :: */ + /* Top side bearing for vertical layout. */ /* */ - /* vertAdvance :: Vertical advance height. */ + /* vertAdvance :: */ + /* Advance height for vertical layout. */ + /* */ + /* lsb_delta :: */ + /* The difference between hinted and unhinted left side bearing */ + /* while autohinting is active. Zero otherwise. */ + /* */ + /* rsb_delta :: */ + /* The difference between hinted and unhinted right side bearing */ + /* while autohinting is active. Zero otherwise. */ + /* */ + /* */ + /* Here a small pseudo code fragment which shows how to use */ + /* `lsb_delta' and `rsb_delta': */ + /* */ + /* FT_Pos origin_x = 0; */ + /* FT_Pos prev_rsb_delta = 0; */ + /* */ + /* */ + /* for all glyphs do */ + /* */ + /* */ + /* */ + /* */ + /* if ( prev_rsb_delta - face->glyph->metrics.lsb_delta >= 32 ) */ + /* origin_x -= 64; */ + /* else if */ + /* ( prev_rsb_delta - face->glyph->metrics.lsb_delta < -32 ) */ + /* origin_x += 64; */ + /* */ + /* prev_rsb_delta = face->glyph->metrics.rsb_delta; */ + /* */ + /* */ + /* */ + /* origin_x += face->glyph->advance.x; */ + /* endfor */ /* */ typedef struct FT_Glyph_Metrics_ { - FT_Pos width; /* glyph width */ - FT_Pos height; /* glyph height */ + FT_Pos width; + FT_Pos height; - FT_Pos horiBearingX; /* left side bearing in horizontal layouts */ - FT_Pos horiBearingY; /* top side bearing in horizontal layouts */ - FT_Pos horiAdvance; /* advance width for horizontal layout */ + FT_Pos horiBearingX; + FT_Pos horiBearingY; + FT_Pos horiAdvance; - FT_Pos vertBearingX; /* left side bearing in vertical layouts */ - FT_Pos vertBearingY; /* top side bearing in vertical layouts */ - FT_Pos vertAdvance; /* advance height for vertical layout */ + FT_Pos vertBearingX; + FT_Pos vertBearingY; + FT_Pos vertAdvance; + + FT_Pos lsb_delta; + FT_Pos rsb_delta; } FT_Glyph_Metrics; diff --git a/src/autohint/ahhint.c b/src/autohint/ahhint.c index 69ac95470..c9e4dbb35 100644 --- a/src/autohint/ahhint.c +++ b/src/autohint/ahhint.c @@ -1542,7 +1542,7 @@ /* width/positioning that occured during the hinting process */ if ( outline->num_vedges > 0 ) { - FT_Pos old_advance, old_rsb, old_lsb, new_lsb; + FT_Pos old_advance, old_rsb, old_lsb, new_lsb, pp1x_uh, pp2x_uh; AH_Edge edge1 = outline->vert_edges; /* leftmost edge */ AH_Edge edge2 = edge1 + outline->num_vedges - 1; /* rightmost edge */ @@ -1553,8 +1553,24 @@ old_lsb = edge1->opos; new_lsb = edge1->pos; - hinter->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb ); - hinter->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb ); + /* remember unhinted values to later account for rounding errors */ + + pp1x_uh = new_lsb - old_lsb; + pp2x_uh = edge2->pos + old_rsb; + + /* prefer too much space over too little space for very small sizes */ + + if ( old_lsb < 24 ) + pp1x_uh -= 5; + + if ( old_rsb < 24 ) + pp2x_uh += 5; + + hinter->pp1.x = FT_PIX_ROUND( pp1x_uh ); + hinter->pp2.x = FT_PIX_ROUND( pp2x_uh ); + + slot->metrics.lsb_delta = hinter->pp1.x - pp1x_uh; + slot->metrics.rsb_delta = hinter->pp2.x - pp2x_uh; #if 0 /* try to fix certain bad advance computations */