Commit 7d62f526fed7aebbe63421a54311792da0e62ff8

Werner Lemberg 2004-06-04T22:30:10

* 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.

diff --git a/ChangeLog b/ChangeLog
index 0890dc4..ec66ec9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,29 @@
+2004-06-04  Werner Lemberg  <wl@gnu.org>
+
+	* docs/CHANGES: Updated.
+
+2004-06-04  David Chester  <davidchester@gmx.net>
+
+	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  <david@freetype.org>
 
-        * 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  <wl@gnu.org>
 
diff --git a/docs/CHANGES b/docs/CHANGES
index 4ab413b..550b722 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 7287005..453db74 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -189,34 +189,80 @@ FT_BEGIN_HEADER
   /*    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;
+    FT_Pos  horiBearingY;
+    FT_Pos  horiAdvance;
 
-    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  vertBearingX;
+    FT_Pos  vertBearingY;
+    FT_Pos  vertAdvance;
 
-    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  lsb_delta;
+    FT_Pos  rsb_delta; 
 
   } FT_Glyph_Metrics;
 
diff --git a/src/autohint/ahhint.c b/src/autohint/ahhint.c
index 69ac954..c9e4dbb 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 */