ref: 7d62f526fed7aebbe63421a54311792da0e62ff8
parent: e664efadddc49bee32b337571e329f150006a84b
author: Werner Lemberg <[email protected]>
date: Fri Jun 4 18:30:10 EDT 2004
* 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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,29 @@
+2004-06-04 Werner Lemberg <[email protected]>
+
+ * docs/CHANGES: Updated.
+
+2004-06-04 David Chester <[email protected]>
+
+ 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 <[email protected]>
- * 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
- <freetype/config/ftmodule.h> and recompile.
+ To test it, change `autohint' to `autofit' in
+ <freetype/config/ftmodule.h> 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 <[email protected]>
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -8,13 +8,24 @@
`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
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -189,34 +189,80 @@
/* instead. */
/* */
/* <Fields> */
- /* 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. */
+ /* */
+ /* <Note> */
+ /* 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 */
+ /* <compute kern between current and previous glyph and add it to */
+ /* `origin_x'> */
+ /* */
+ /* <load glyph with `FT_Load_Glyph'> */
+ /* */
+ /* 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; */
+ /* */
+ /* <save glyph image, or render glyph, or ...> */
+ /* */
+ /* 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;
--- 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 */