shithub: freetype+ttf2subf

Download patch

ref: 14018b4af9c4274e0b89cd31e94ef78109f0d912
parent: 57ce0bee449bfc6fa418f1492ef23cb4baeb7c95
author: David Turner <[email protected]>
date: Sun Jan 12 13:26:10 EST 2003

2003-01-11  David Chester  <[email protected]>

        * include/freetype/config/ftoption.h, src/autohint/ahglobal.h,
        src/autohint/ahglobal.c, src/autohint/ahglyph.c,
        src/autohint/ahtypes.h:

          included David Chester's patches to the auto-hinter in order to
          slightly improve the output. Note that everything is controlled
          through the new FT_CONFIG_OPTION_CHESTER_HINTS defined at the
          end of "ftoption.h", there are also individual FT_CONFIG_CHESTER_XXX
          macros to control individual "features".

          Note that all improvements are enabled by default, but can be
          tweaked for optimization and testing purpose. The configuration
          macros will most likely disappear in the short future.

2003-01-11  David Turner  <[email protected]>

        * include/freetype/internal/fnttypes.h: fixed a structure field
        definition to avoid memory overwrites

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2003-01-11  David Chester  <[email protected]>
+
+        * include/freetype/config/ftoption.h, src/autohint/ahglobal.h,
+        src/autohint/ahglobal.c, src/autohint/ahglyph.c,
+        src/autohint/ahtypes.h:
+
+          included David Chester's patches to the auto-hinter in order to
+          slightly improve the output. Note that everything is controlled
+          through the new FT_CONFIG_OPTION_CHESTER_HINTS defined at the
+          end of "ftoption.h", there are also individual FT_CONFIG_CHESTER_XXX
+          macros to control individual "features".
+
+          Note that all improvements are enabled by default, but can be
+          tweaked for optimization and testing purpose. The configuration
+          macros will most likely disappear in the short future.
+
+2003-01-11  David Turner  <[email protected]>
+
+        * include/freetype/internal/fnttypes.h: fixed a structure field
+        definition to avoid memory overwrites
+
 2003-01-08  Huw Dawies  <[email protected]>
 
         * src/winfonts/winfnt.c: read 16 bytes into "reserved2", not "reserved"
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -469,6 +469,17 @@
 
  /* */
 
+#undef   FT_CONFIG_OPTION_CHESTER_HINTS
+
+#ifdef   FT_CONFIG_OPTION_CHESTER_HINTS
+
+#  define  FT_CONFIG_CHESTER_SMALL_F
+#  define  FT_CONFIG_CHESTER_ASCENDER
+#  define  FT_CONFIG_CHESTER_SERIF
+#  define  FT_CONFIG_CHESTER_STEM
+
+#endif /* FT_CONFIG_OPTION_CHESTER_HINTS */
+
 FT_END_HEADER
 
 
--- a/include/freetype/internal/fnttypes.h
+++ b/include/freetype/internal/fnttypes.h
@@ -108,7 +108,7 @@
     FT_UShort  B_space;
     FT_UShort  C_space;
     FT_UShort  color_table_offset;
-    FT_Byte    reserved2[4];
+    FT_Byte    reserved2[16];
 
   } WinFNT_HeaderRec, *WinFNT_Header;
 
--- a/src/autohint/ahglobal.c
+++ b/src/autohint/ahglobal.c
@@ -32,6 +32,9 @@
   {
     "THEZOCQS",
     "HEZLOCUS",
+#ifdef FT_CONFIG_CHESTER_SMALL_F
+    "fijkdbh",
+#endif
     "xzroesc",
     "xzroesc",
     "pqgjy"
--- a/src/autohint/ahglobal.h
+++ b/src/autohint/ahglobal.h
@@ -32,8 +32,18 @@
 FT_BEGIN_HEADER
 
 
-#define AH_IS_TOP_BLUE( b )  ( (b) == AH_BLUE_CAPITAL_TOP || \
-                               (b) == AH_BLUE_SMALL_TOP   )
+#ifdef  FT_CONFIG_CHESTER_SMALL_F
+
+#  define AH_IS_TOP_BLUE( b )  ( (b) == AH_BLUE_CAPITAL_TOP || \
+                                 (b) == AH_BLUE_SMALL_F_TOP || \
+                                 (b) == AH_BLUE_SMALL_TOP   )
+
+#else /* !CHESTER_SMALL_F */
+
+#  define AH_IS_TOP_BLUE( b )  ( (b) == AH_BLUE_CAPITAL_TOP || \
+                                 (b) == AH_BLUE_SMALL_TOP   )
+
+#endif /* !CHESTER_SMALL_F */
 
 
   /* compute global metrics automatically */
--- a/src/autohint/ahglyph.c
+++ b/src/autohint/ahglyph.c
@@ -1350,10 +1350,20 @@
             else
               edge2 = seg2->edge;
 
+#ifdef FT_CONFIG_CHESTER_SERIF
             if ( is_serif )
+            {
+              edge->serif   = edge2;
+              edge2->flags |= AH_EDGE_SERIF;
+            }
+            else
+              edge->link  = edge2;
+#else /* !CHESTER_SERIF */
+            if ( is_serif )
               edge->serif = edge2;
             else
               edge->link  = edge2;
+#endif
           }
 
           seg = seg->edge_next;
@@ -1477,8 +1487,14 @@
 
       /* compute the initial threshold as a fraction of the EM size */
       best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale );
+
+#ifdef FT_CONFIG_CHESTER_SMALL_F
+      if ( best_dist > 64 / 2 )
+        best_dist = 64 / 2;
+#else
       if ( best_dist > 64 / 4 )
-        best_dist = 64 / 4;
+         best_dist = 64 / 4;
+#endif
 
       for ( blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++ )
       {
--- a/src/autohint/ahhint.c
+++ b/src/autohint/ahhint.c
@@ -88,7 +88,138 @@
 
 
   /* compute the snapped width of a given stem */
+#ifdef FT_CONFIG_CHESTER_SERIF
   static FT_Pos
+  ah_compute_stem_width( AH_Hinter      hinter,
+                         int            vertical,
+                         FT_Pos         width,
+                         AH_Edge_Flags  base_flags,
+                         AH_Edge_Flags  stem_flags )
+  {
+    AH_Globals  globals = &hinter->globals->scaled;
+    FT_Pos      dist    = width;
+    FT_Int      sign    = 0;
+
+
+    if ( dist < 0 )
+    {
+      dist = -width;
+      sign = 1;
+    }
+
+    if ( !hinter->do_stem_adjust )
+    {
+      /* leave stem widths unchanged */
+    }
+    else if ( (  vertical && !hinter->do_vert_snapping ) ||
+              ( !vertical && !hinter->do_horz_snapping ) )
+    {
+      /* smooth hinting process, very lightly quantize the stem width */
+      /*                                                              */
+
+      /* leave the widths of serifs alone */
+
+      if ( ( stem_flags & AH_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+        goto Done_Width;
+
+      else if ( ( base_flags & AH_EDGE_ROUND ) )
+      {
+        if ( dist < 96 )
+          dist = 64;
+      }
+      else if ( dist < 56 )
+        dist = 56;
+
+      {
+        FT_Pos  delta = dist - globals->stds[vertical];
+
+
+        if ( delta < 0 )
+          delta = -delta;
+
+        if ( delta < 40 )
+        {
+          dist = globals->stds[vertical];
+          if ( dist < 48 )
+            dist = 48;
+
+          goto Done_Width;
+        }
+
+        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
+    {
+      /* strong hinting process, snap the stem width to integer pixels */
+      /*                                                               */
+      if ( vertical )
+      {
+        dist = ah_snap_width( globals->heights, globals->num_heights, dist );
+
+        /* in the case of vertical hinting, always round */
+        /* the stem heights to integer pixels            */
+        if ( dist >= 64 )
+          dist = ( dist + 16 ) & -64;
+        else
+          dist = 64;
+      }
+      else
+      {
+        dist = ah_snap_width( globals->widths,  globals->num_widths, dist );
+
+        if ( hinter->flags & AH_HINTER_MONOCHROME )
+        {
+          /* monochrome horizontal hinting: snap widths to integer pixels */
+          /* with a different threshold                                   */
+          if ( dist < 64 )
+            dist = 64;
+          else
+            dist = ( dist + 32 ) & -64;
+        }
+        else
+        {
+          /* for horizontal anti-aliased hinting, we adopt a more subtle */
+          /* approach: we strengthen small stems, round stems whose size */
+          /* is between 1 and 2 pixels to an integer, otherwise nothing  */
+          if ( dist < 48 )
+            dist = ( dist + 64 ) >> 1;
+
+          else if ( dist < 128 )
+            dist = ( dist + 22 ) & -64;
+          else
+            /* XXX: round otherwise, prevent color fringes in LCD mode */
+            dist = ( dist + 32 ) & -64;
+        }
+      }
+    }
+
+  Done_Width:
+    if ( sign )
+      dist = -dist;
+
+    return dist;
+  }
+#else /* !CHESTER_SERIF */
+  static FT_Pos
   ah_compute_stem_width( AH_Hinter  hinter,
                          int        vertical,
                          FT_Pos     width )
@@ -201,6 +332,7 @@
 
     return dist;
   }
+#endif /* !CHESTER_SERIF */
 
 
   /* align one stem edge relative to the previous stem edge */
@@ -212,9 +344,18 @@
   {
     FT_Pos  dist = stem_edge->opos - base_edge->opos;
 
+#ifdef FT_CONFIG_CHESTER_SERIF
+    FT_Pos  fitted_width = ah_compute_stem_width( hinter,
+                                                  vertical,
+                                                  dist,
+                                                  base_edge->flags,
+                                                  stem_edge->flags );
 
+    stem_edge->pos = base_edge->pos + fitted_width;
+#else
     stem_edge->pos = base_edge->pos +
                      ah_compute_stem_width( hinter, vertical, dist );
+#endif
   }
 
 
@@ -368,6 +509,54 @@
 
         if ( !anchor )
         {
+#ifdef FT_CONFIG_CHESTER_STEM
+          FT_Pos   org_len, org_center, cur_len;
+          FT_Pos   cur_pos1, error1, error2, u_off, d_off;
+
+          org_len    = edge2->opos - edge->opos;
+          cur_len    = ah_compute_stem_width( hinter, dimension, org_len,
+                                              edge->flags, edge2->flags   );
+
+          if (cur_len <= 64 )
+            u_off = d_off = 32;
+          else
+          {
+            u_off = 38;
+            d_off = 26;
+          }
+
+          if ( cur_len < 96 )
+          {
+            org_center = edge->opos + ( org_len >> 1 );
+
+            cur_pos1   = ( org_center + 32 ) & -64;
+
+            error1 = org_center - ( cur_pos1 - u_off );
+            if ( error1 < 0 )
+              error1 = -error1;
+
+            error2 = org_center - ( cur_pos1 + d_off );
+            if ( error2 < 0 )
+              error2 = -error2;
+
+            if ( error1 < error2 )
+              cur_pos1 -= u_off;
+            else
+              cur_pos1 += d_off;
+
+            edge->pos  = cur_pos1 - cur_len / 2;
+            edge2->pos = cur_pos1 + cur_len / 2;
+
+          }
+          else
+            edge->pos = ( edge->opos + 32 ) & -64;
+
+          anchor    = edge;
+
+          edge->flags |= AH_EDGE_DONE;
+
+          ah_align_linked_edge( hinter, edge, edge2, dimension );
+#else /* !CHESTER_STEM */
           edge->pos = ( edge->opos + 32 ) & -64;
           anchor    = edge;
 
@@ -374,6 +563,7 @@
           edge->flags |= AH_EDGE_DONE;
 
           ah_align_linked_edge( hinter, edge, edge2, dimension );
+#endif /* !CHESTER_STEM */
         }
         else
         {
@@ -385,8 +575,71 @@
           org_len    = edge2->opos - edge->opos;
           org_center = org_pos + ( org_len >> 1 );
 
+#ifdef FT_CONFIG_CHESTER_SERIF
+          cur_len    = ah_compute_stem_width( hinter, dimension, org_len,
+                                              edge->flags, edge2->flags  );
+#else  /* !CHESTER_SERIF */
           cur_len    = ah_compute_stem_width( hinter, dimension, org_len );
+#endif /* !CHESTER_SERIF */
 
+#ifdef FT_CONFIG_CHESTER_STEM
+          if ( cur_len < 96 )
+          {
+            FT_Pos  u_off, d_off;
+
+
+            cur_pos1   = ( org_center + 32 ) & -64;
+
+            if (cur_len <= 64 )
+              u_off = d_off = 32;
+            else
+            {
+              u_off = 38;
+              d_off = 26;
+            }
+
+            delta1 = org_center - (cur_pos1 - u_off);
+            if ( delta1 < 0 )
+              delta1 = -delta1;
+
+            delta2 = org_center - (cur_pos1 + d_off);
+            if ( delta2 < 0 )
+              delta2 = -delta2;
+
+            if ( delta1 < delta2 )
+              cur_pos1 -= u_off;
+            else
+              cur_pos1 += d_off;
+
+            edge->pos  = cur_pos1 - cur_len / 2;
+            edge2->pos = cur_pos1 + cur_len / 2;
+          }
+          else
+          {
+
+            org_pos    = anchor->pos + (edge->opos - anchor->opos);
+            org_len    = edge2->opos - edge->opos;
+            org_center = org_pos + ( org_len >> 1 );
+
+            cur_len    = ah_compute_stem_width( hinter, dimension, org_len,
+                                                edge->flags, edge2->flags );
+
+            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;
+          }
+
+#else /* !CHESTER_STEM */
+
           cur_pos1   = ( org_pos + 32 ) & -64;
           delta1     = ( cur_pos1 + ( cur_len >> 1 ) - org_center );
           if ( delta1 < 0 )
@@ -399,6 +652,8 @@
 
           edge->pos  = ( delta1 <= delta2 ) ? cur_pos1 : cur_pos2;
           edge2->pos = edge->pos + cur_len;
+
+#endif /* !CHESTER_STEM */
 
           edge->flags  |= AH_EDGE_DONE;
           edge2->flags |= AH_EDGE_DONE;
--- a/src/autohint/ahtypes.h
+++ b/src/autohint/ahtypes.h
@@ -385,12 +385,26 @@
   } AH_OutlineRec, *AH_Outline;
 
 
-#define AH_BLUE_CAPITAL_TOP     0                              /* THEZOCQS */
-#define AH_BLUE_CAPITAL_BOTTOM  ( AH_BLUE_CAPITAL_TOP + 1 )    /* HEZLOCUS */
-#define AH_BLUE_SMALL_TOP       ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* xzroesc  */
-#define AH_BLUE_SMALL_BOTTOM    ( AH_BLUE_SMALL_TOP + 1 )      /* xzroesc  */
-#define AH_BLUE_SMALL_MINOR     ( AH_BLUE_SMALL_BOTTOM + 1 )   /* pqgjy    */
-#define AH_BLUE_MAX             ( AH_BLUE_SMALL_MINOR + 1 )
+#ifdef FT_CONFIG_CHESTER_SMALL_F
+
+#  define AH_BLUE_CAPITAL_TOP     0                              /* THEZOCQS */
+#  define AH_BLUE_CAPITAL_BOTTOM  ( AH_BLUE_CAPITAL_TOP + 1 )    /* HEZLOCUS */
+#  define AH_BLUE_SMALL_F_TOP     ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* fijkdbh  */
+#  define AH_BLUE_SMALL_TOP       ( AH_BLUE_SMALL_F_TOP + 1 )    /* xzroesc  */
+#  define AH_BLUE_SMALL_BOTTOM    ( AH_BLUE_SMALL_TOP + 1 )      /* xzroesc  */
+#  define AH_BLUE_SMALL_MINOR     ( AH_BLUE_SMALL_BOTTOM + 1 )   /* pqgjy    */
+#  define AH_BLUE_MAX             ( AH_BLUE_SMALL_MINOR + 1 )
+
+#else /* !CHESTER_SMALL_F */
+
+#  define AH_BLUE_CAPITAL_TOP     0                              /* THEZOCQS */
+#  define AH_BLUE_CAPITAL_BOTTOM  ( AH_BLUE_CAPITAL_TOP + 1 )    /* HEZLOCUS */
+#  define AH_BLUE_SMALL_TOP       ( AH_BLUE_CAPITAL_BOTTOM + 1)  /* xzroesc  */
+#  define AH_BLUE_SMALL_BOTTOM    ( AH_BLUE_SMALL_TOP + 1 )      /* xzroesc  */
+#  define AH_BLUE_SMALL_MINOR     ( AH_BLUE_SMALL_BOTTOM + 1 )   /* pqgjy    */
+#  define AH_BLUE_MAX             ( AH_BLUE_SMALL_MINOR + 1 )
+
+#endif /* !CHESTER_SMALL_F */
 
   typedef FT_Int  AH_Blue;
 
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -566,15 +566,26 @@
       size->ttmetrics.y_ratio = 0x10000L;
     }
 
+#ifdef FT_CONFIG_CHESTER_ASCENDER
+
     /* Compute root ascender, descender, test height, and max_advance */
     metrics->ascender    = ( FT_MulFix( face->root.ascender,
+                                        metrics->y_scale ) + 63 ) & -64;
+    metrics->descender   = ( FT_MulFix( face->root.descender,
+                                        metrics->y_scale ) + 0  ) & -64;
+#else /* !CHESTER_ASCENDER */
+    /* Compute root ascender, descender, test height, and max_advance */
+    metrics->ascender    = ( FT_MulFix( face->root.ascender,
                                         metrics->y_scale ) + 32 ) & -64;
     metrics->descender   = ( FT_MulFix( face->root.descender,
                                         metrics->y_scale ) + 32 ) & -64;
+#endif /* !CHESTER_ASCENDER */
+
     metrics->height      = ( FT_MulFix( face->root.height,
                                         metrics->y_scale ) + 32 ) & -64;
     metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
                                         metrics->x_scale ) + 32 ) & -64;
+
 
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
     /* set to `invalid' by default */