Commit 699053ca759db89eff168713ca86163d76fd5b17

David Turner 2002-07-04T22:48:12

2002-07-03 David Turner <david@freetype.org> * src/autohint/ahglobal.c, src/autohint/ahtypes.h, src/autohint/ahhint.c: small improvements to the automatic hinter. un-even stem-widths have now disappeared and everything looks much better, even if there are still issues with serifed fonts.

diff --git a/ChangeLog b/ChangeLog
index 00fe943..f81ff22 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2002-07-03  David Turner  <david@freetype.org>
+
+    * src/autohint/ahglobal.c, src/autohint/ahtypes.h, src/autohint/ahhint.c:
+    small improvements to the automatic hinter. un-even stem-widths have now
+    disappeared and everything looks much better, even if there are still
+    issues with serifed fonts.
+
+2002-07-03  Owen Taylor  <owen@redhat.com>
+
+    * src/pshinter/pshalgo3.c, src/pshinter/pshalgo3.h, src/pshinter/pshalgo.h,
+    src/pshinter/pshinter.c: adding new algorithm based on Owen Taylor's recent
+    work
+
 2002-07-01  Owen Taylor  <owen@redhat.com>
 
     * src/pshinter/pshalgo2.c (psh2_glyph_find_strong_points): fix a bug
diff --git a/src/autohint/ahglobal.c b/src/autohint/ahglobal.c
index 93bb91a..3924ffb 100644
--- a/src/autohint/ahglobal.c
+++ b/src/autohint/ahglobal.c
@@ -368,7 +368,6 @@
       limit        = segments + outline->num_vsegments;
       widths       = globals->widths;
       p_num_widths = &globals->num_widths;
-
     }
 
     /* Now, compute the edge distance threshold as a fraction of the */
diff --git a/src/autohint/ahhint.c b/src/autohint/ahhint.c
index 169d983..945911c 100644
--- a/src/autohint/ahhint.c
+++ b/src/autohint/ahhint.c
@@ -30,7 +30,7 @@
 #define FACE_GLOBALS( face )  ((AH_Face_Globals*)(face)->autohint.data)
 
 #define AH_USE_IUP
-
+#define OPTIM_STEM_SNAP
 
   /*************************************************************************/
   /*************************************************************************/
@@ -51,6 +51,7 @@
     int     n;
     FT_Pos  best      = 64 + 32 + 2;
     FT_Pos  reference = width;
+    FT_Pos  scaled;
 
 
     for ( n = 0; n < count; n++ )
@@ -70,16 +71,16 @@
       }
     }
 
+    scaled = (reference+32) & -64;
+
     if ( width >= reference )
     {
-      width -= 0x21;
-      if ( width < reference )
+      if ( width < scaled + 48 )
         width = reference;
     }
     else
     {
-      width += 0x21;
-      if ( width > reference )
+      if ( width > scaled - 48 )
         width = reference;
     }
 
@@ -87,24 +88,62 @@
   }
 
 
-  /* align one stem edge relative to the previous stem edge */
-  static void
-  ah_align_linked_edge( AH_Hinter*  hinter,
-                        AH_Edge*    base_edge,
-                        AH_Edge*    stem_edge,
-                        int         vertical )
+  /* compute the snapped width of a given stem */
+  static FT_Pos
+  ah_compute_stem_width( AH_Hinter*  hinter,
+                         int         vertical,
+                         FT_Pos      width )
   {
-    FT_Pos       dist    = stem_edge->opos - base_edge->opos;
     AH_Globals*  globals = &hinter->globals->scaled;
-    FT_Pos       sign    = 1;
-
+    FT_Pos       dist    = width;
+    FT_Int       sign    = 0;
 
     if ( dist < 0 )
     {
-      dist = -dist;
-      sign = -1;
+      dist = -width;
+      sign = 1;
     }
 
+#if 1
+    if ( dist < 64 )
+      dist = 64;
+
+    {
+      FT_Pos  delta = dist - globals->stds[vertical];
+
+      if ( delta < 0 )
+        delta = -delta;
+
+      if ( delta < 40 )
+      {
+        dist = globals->stds[vertical];
+        if ( dist < 32 )
+          dist = 32;
+      }
+
+      {
+        if ( dist < 3*64 )
+        {
+          delta = (dist & 63);
+          dist &= -64;
+
+          if ( delta < 10 )
+            dist += delta;
+
+          else if ( delta < 32 )
+            dist += 10;
+
+          else if ( delta < 54 )
+            dist += 54;
+
+          else
+            dist += delta;
+        }
+        else
+          dist = (dist+32) & -64;
+      }
+    }
+#else
     if ( vertical )
     {
       dist = ah_snap_width( globals->heights, globals->num_heights, dist );
@@ -138,14 +177,32 @@
           dist = ( dist + 64 ) >> 1;
 
         else if ( dist < 128 )
-          dist = ( dist + 42 ) & -64;
+          dist = ( dist + 22 ) & -64;
         else
           /* XXX: round otherwise, prevent color fringes in LCD mode */
           dist = ( dist + 32 ) & -64;
       }
     }
+#endif
+
+    if ( sign )
+      dist = -dist;
+
+    return dist;
+  }
+
+
+  /* align one stem edge relative to the previous stem edge */
+  static void
+  ah_align_linked_edge( AH_Hinter*  hinter,
+                        AH_Edge*    base_edge,
+                        AH_Edge*    stem_edge,
+                        int         vertical )
+  {
+    FT_Pos       dist    = stem_edge->opos - base_edge->opos;
 
-    stem_edge->pos = base_edge->pos + sign * dist;
+    stem_edge->pos = base_edge->pos +
+                     ah_compute_stem_width( hinter, vertical, dist );
   }
 
 
@@ -168,6 +225,10 @@
       sign = -1;
     }
 
+#if 0
+    if ( dist < 32 )
+      dist = 32;
+#else
     /* do not strengthen serifs */
     if ( base->flags & ah_edge_done )
     {
@@ -179,6 +240,7 @@
       else
         dist = 0;
     }
+#endif
 
     serif->pos = base->pos + sign * dist;
   }
@@ -308,32 +370,57 @@
           {
             edge->pos = ( edge->opos + 32 ) & -64;
             anchor    = edge;
+
+            edge->flags |= ah_edge_done;
+
+            ah_align_linked_edge( hinter, edge, edge2, dimension );
           }
           else
-            edge->pos = anchor->pos +
-                        ( ( edge->opos - anchor->opos + 32 ) & -64 );
+          {
+            FT_Pos   org_pos, org_len, org_center, cur_len;
+            FT_Pos   cur_pos1, cur_pos2, delta1, delta2;
 
-          edge->flags |= ah_edge_done;
 
-          if ( edge > edges && edge->pos < edge[-1].pos )
-          {
-            edge->pos = edge[-1].pos;
-            min       = 1;
-          }
+            org_pos    = anchor->pos + (edge->opos - anchor->opos);
+            org_len    = edge2->opos - edge->opos;
+            org_center = org_pos + (org_len >> 1);
 
-          ah_align_linked_edge( hinter, edge, edge2, dimension );
-          delta = 0;
-          if ( edge2 + 1 < edge_limit        &&
-               edge2[1].flags & ah_edge_done )
-            delta = edge2[1].pos - edge2->pos;
+            cur_len    = ah_compute_stem_width( hinter, dimension, org_len );
 
-          if ( delta < 0 )
-          {
-            edge2->pos += delta;
-            if ( !min )
-              edge->pos += delta;
+            cur_pos1   = ( org_pos + 32 ) & -64;
+            delta1     = ( cur_pos1 + (cur_len >> 1) - org_center );
+            if ( delta1 < 0 )
+              delta1 = -delta1;
+
+            cur_pos2   = (( org_pos + org_len + 32 ) & -64) - cur_len;
+            delta2     = ( cur_pos2 + (cur_len >> 1) - org_center );
+            if ( delta2 < 0 )
+              delta2 = -delta2;
+
+            edge->pos  = ( delta1 <= delta2 ) ? cur_pos1 : cur_pos2;
+            edge2->pos = edge->pos + cur_len;
+
+            edge->flags  |= ah_edge_done;
+            edge2->flags |= ah_edge_done;
+
+            if ( edge > edges && edge->pos < edge[-1].pos )
+              edge->pos = edge[-1].pos;
+
+#if 0
+            delta = 0;
+            if ( edge2 + 1 < edge_limit        &&
+                 edge2[1].flags & ah_edge_done )
+              delta = edge2[1].pos - edge2->pos;
+
+            if ( delta < 0 )
+            {
+              edge2->pos += delta;
+              if ( !min )
+                edge->pos += delta;
+            }
+            edge2->flags |= ah_edge_done;
+#endif
           }
-          edge2->flags |= ah_edge_done;
         }
       }
 
@@ -855,6 +942,9 @@
     for ( n = 0; n < design->num_heights; n++ )
       scaled->heights[n] = FT_MulFix( design->heights[n], y_scale );
 
+    scaled->stds[0] = ( design->num_widths  > 0 ) ? scaled->widths[0]  : 32000;
+    scaled->stds[1] = ( design->num_heights > 0 ) ? scaled->heights[0] : 32000;
+
     /* scale the blue zones */
     for ( n = 0; n < ah_blue_max; n++ )
     {
diff --git a/src/autohint/ahtypes.h b/src/autohint/ahtypes.h
index 60f278d..cd62101 100644
--- a/src/autohint/ahtypes.h
+++ b/src/autohint/ahtypes.h
@@ -423,6 +423,8 @@ FT_BEGIN_HEADER
     FT_Int  num_widths;
     FT_Int  num_heights;
 
+    FT_Pos  stds[2];
+
     FT_Pos  widths [AH_MAX_WIDTHS];
     FT_Pos  heights[AH_MAX_HEIGHTS];