shithub: freetype+ttf2subf

Download patch

ref: e664efadddc49bee32b337571e329f150006a84b
parent: 56a4d87cb2935339e970d0743c250389fc4706c8
author: David Turner <[email protected]>
date: Fri Jun 4 13:41:59 EDT 2004

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

        a few more testing is needed before making this the official
        auto-hinting module

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+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).
+
+        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
+
 2004-06-02  Werner Lemberg  <[email protected]>
 
 	* src/truetype/ttgload.c (compute_glyph_metrics): Fix compiler
@@ -24,7 +37,7 @@
 
 2004-05-17  Werner Lemberg  <[email protected]>
 
-	* src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases. 
+	* src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases.
 	Reported by Mikey Anbary <[email protected]>.
 
 2004-05-15  Werner Lemberg  <[email protected]>
@@ -173,7 +186,7 @@
 	consistency.
 	(pcf_cmap_init, pcf_cmap_done, pcf_cmap_char_index,
 	pcf_cmap_char_next): Don't use PCF_XXX but FT_XXX arguments which
-	are typecast to the proper PCF_XXX types within the function. 
+	are typecast to the proper PCF_XXX types within the function.
 	Update code accordingly.
 	(pcf_cmap_class): Remove casts.
 	(PCF_Face_Done, PCF_Face_Init, PCF_Set_Pixel_Size): Don't use
--- a/src/autofit/afangles.c
+++ b/src/autofit/afangles.c
@@ -1,8 +1,57 @@
 #include "aftypes.h"
 
+/*
+ * a python script used to generate the following table
+ *
+
+import sys, math
+
+units  = 256
+scale  = units/math.pi
+comma  = ""
+
+print ""
+print "table of arctan( 1/2^n ) for PI = " + repr(units/65536.0) + " units"
+
+r = [-1] + range(32)
+
+for n in r:
+
+    if n >= 0:
+        x = 1.0/(2.0**n)    # tangent value
+    else:
+        x = 2.0**(-n)
+
+    angle  = math.atan(x)    # arctangent
+    angle2 = angle*scale     # arctangent in FT_Angle units
+
+    # determine which integer value for angle gives the best tangent
+    lo  = int(angle2)
+    hi  = lo + 1
+    tlo = math.tan(lo/scale)
+    thi = math.tan(hi/scale)
+
+    errlo = abs( tlo - x )
+    errhi = abs( thi - x )
+
+    angle2 = hi
+    if errlo < errhi:
+        angle2 = lo
+
+    if angle2 <= 0:
+        break
+
+    sys.stdout.write( comma + repr( int(angle2) ) )
+    comma = ", "
+
+*
+* end of python script
+*/
+
+
   /* this table was generated for AF_ANGLE_PI = 256 */
 #define AF_ANGLE_MAX_ITERS  8
-#define AF_TRIG_MAX_ITERS   9
+#define AF_TRIG_MAX_ITERS   8
 
   static const FT_Fixed
   af_angle_arctan_table[9] =
@@ -69,7 +118,7 @@
     {
       x = -x;
       y = -y;
-      theta = 2 * AF_ANGLE_PI2;
+      theta = AF_ANGLE_PI;
     }
 
     if ( y > 0 )
@@ -115,11 +164,13 @@
       }
     } while ( ++i < AF_TRIG_MAX_ITERS );
 
+#if 0
     /* round theta */
     if ( theta >= 0 )
-      theta = FT_PAD_ROUND( theta, 4 );
+      theta =   FT_PAD_ROUND( theta, 2 );
     else
-      theta = - FT_PAD_ROUND( theta, 4 );
+      theta = - FT_PAD_ROUND( -theta, 2 );
+#endif
 
     vec->x = x;
     vec->y = theta;
@@ -212,3 +263,40 @@
       }
     }
   }
+
+
+#ifdef TEST
+#include <stdio.h>
+#include <math.h>
+
+int main( void )
+{
+  int  angle;
+  int  dist;
+
+  for ( dist = 100; dist < 1000; dist++ )
+  {
+    for ( angle = AF_ANGLE_PI; angle < AF_ANGLE_2PI*4; angle++ )
+    {
+      double a = (angle*3.1415926535)/(1.0*AF_ANGLE_PI);
+      int    dx, dy, angle1, angle2, delta;
+
+      dx = dist * cos(a);
+      dy = dist * sin(a);
+
+      angle1  = ((atan2(dy,dx)*AF_ANGLE_PI)/3.1415926535);
+      angle2  = af_angle_atan( dx, dy );
+      delta   = (angle2 - angle1) % AF_ANGLE_2PI;
+      if ( delta < 0 )
+        delta = -delta;
+
+      if ( delta >= 2 )
+      {
+        printf( "dist:%4d angle:%4d => (%4d,%4d) angle1:%4d angle2:%4d\n",
+                dist, angle, dx, dy, angle1, angle2 );
+      }
+    }
+  }
+  return 0;
+}
+#endif
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -3,13 +3,11 @@
 
   static FT_Error
   af_dummy_hints_init( AF_GlyphHints     hints,
-                       FT_Outline*       outline,
                        AF_ScriptMetrics  metrics )
   {
-    return af_glyph_hints_reset( hints,
-                                 &metrics->scaler,
-                                 metrics,
-                                 outline );
+    af_glyph_hints_rescale( hints,
+                            metrics );
+    return 0;
   }
 
   static FT_Error
@@ -16,7 +14,10 @@
   af_dummy_hints_apply( AF_GlyphHints  hints,
                         FT_Outline*    outline )
   {
-    af_glyph_hints_save( hints, outline );
+    FT_UNUSED( hints );
+    FT_UNUSED( outline );
+
+    return 0;
   }
 
 
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -12,7 +12,7 @@
     NULL  /* do not remove */
   };
 
-#define AF_SCRIPT_LIST_DEFAULT   0    /* index of default script in 'af_script_classes' */
+#define AF_SCRIPT_LIST_DEFAULT   1    /* index of default script in 'af_script_classes' */
 #define AF_SCRIPT_LIST_NONE      255  /* indicates an uncovered glyph                      */
 
  /*
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -10,11 +10,11 @@
 
     switch (dir)
     {
-     case AF_DIR_UP: result = "up"; break;
-     case AF_DIR_DOWN: result = "down"; break;
-     case AF_DIR_LEFT: result = "left"; break;
+     case AF_DIR_UP:    result = "up";    break;
+     case AF_DIR_DOWN:  result = "down";  break;
+     case AF_DIR_LEFT:  result = "left";  break;
      case AF_DIR_RIGHT: result = "right"; break;
-     default: result = "none";
+     default:           result = "none";
     }
     return result;
   }
@@ -111,7 +111,7 @@
 
       for ( edge = edges; edge < limit; edge++ )
       {
-        printf ( "  [ %5d | %4d | %5s | %4d | %5d |  %c  | %5.2f | %5.2f ]\n",
+        printf ( "  [ %5d | %4d | %5s | %4d | %5d |   %c  | %5.2f | %5.2f ]\n",
                  edge - edges,
                  (int)edge->fpos,
                  af_dir_str( edge->dir ),
@@ -314,26 +314,29 @@
 
 
 
+  FT_LOCAL_DEF( void )
+  af_glyph_hints_rescale( AF_GlyphHints     hints,
+                          AF_ScriptMetrics  metrics )
+  {
+    hints->metrics = metrics;
+  }
+
+
   FT_LOCAL_DEF( FT_Error )
-  af_glyph_hints_reset( AF_GlyphHints     hints,
-                        AF_Scaler         scaler,
-                        AF_ScriptMetrics  metrics,
-                        FT_Outline*       outline )
+  af_glyph_hints_reload( AF_GlyphHints     hints,
+                         FT_Outline*       outline )
   {
     FT_Error     error        = FT_Err_Ok;
     AF_Point     points;
     FT_UInt      old_max, new_max;
-    FT_Fixed     x_scale = scaler->x_scale;
-    FT_Fixed     y_scale = scaler->y_scale;
-    FT_Pos       x_delta = scaler->x_delta;
-    FT_Pos       y_delta = scaler->y_delta;
+    AF_Scaler    scaler  = &hints->metrics->scaler;
+    FT_Fixed     x_scale = hints->x_scale;
+    FT_Fixed     y_scale = hints->y_scale;
+    FT_Pos       x_delta = hints->x_delta;
+    FT_Pos       y_delta = hints->y_delta;
     FT_Memory    memory  = hints->memory;
 
-    hints->metrics = metrics;
-
-    hints->scaler_flags = scaler->flags;
-    hints->other_flags  = 0;
-
+    hints->scaler_flags  = scaler->flags;
     hints->num_points    = 0;
     hints->num_contours  = 0;
 
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -214,11 +214,13 @@
  /*  recomputes all AF_Point in a AF_GlyphHints from the definitions
   *  in a source outline
   */
+  FT_LOCAL( void )
+  af_glyph_hints_rescale( AF_GlyphHints     hints,
+                          AF_ScriptMetrics  metrics );
+
   FT_LOCAL( FT_Error )
-  af_glyph_hints_reset( AF_GlyphHints     hints,
-                        AF_Scaler         scaler,
-                        AF_ScriptMetrics  metrics,
-                        FT_Outline*       outline );
+  af_glyph_hints_reload( AF_GlyphHints     hints,
+                         FT_Outline*       outline );
 
   FT_LOCAL( void )
   af_glyph_hints_save( AF_GlyphHints   hints,
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -25,9 +25,9 @@
       FT_Error      error;
       FT_UInt       glyph_index;
       AF_Dimension  dim;
-      AF_ScalerRec  scaler[1];
+      AF_ScriptMetricsRec  dummy[1];
+      AF_Scaler            scaler = &dummy->scaler;
 
-
       glyph_index = FT_Get_Char_Index( face, 'o' );
       if ( glyph_index == 0 )
         goto Exit;
@@ -36,6 +36,8 @@
       if ( error || face->glyph->outline.n_points <= 0 )
         goto Exit;
 
+      FT_ZERO( dummy );
+
       scaler->x_scale     = scaler->y_scale = 0x10000L;
       scaler->x_delta     = scaler->y_delta = 0;
       scaler->face        = face;
@@ -42,9 +44,9 @@
       scaler->render_mode = 0;
       scaler->flags       = 0;
 
-      error = af_glyph_hints_reset( hints, scaler,
-                                    (AF_ScriptMetrics) metrics,
-                                    &face->glyph->outline );
+      af_glyph_hints_rescale( hints, dummy );
+
+      error = af_glyph_hints_reload( hints, &face->glyph->outline );
       if ( error )
         goto Exit;
 
@@ -324,6 +326,13 @@
       if ( AF_LATIN_IS_TOP_BLUE(bb) )
         blue->flags |= AF_LATIN_BLUE_TOP;
 
+     /* the following flags is used later to adjust the y and x scales
+      * in order to optimize the pixel grid alignment of the top of small
+      * letters.
+      */
+      if ( bb == AF_LATIN_BLUE_SMALL_TOP )
+        blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
+
       AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
     }
 
@@ -382,8 +391,44 @@
     axis->org_scale = scale;
     axis->org_delta = delta;
 
-   /* XXX: TODO: Correct Y and X scale according to Chester rules
+   /* correct X and Y scale to optimize the alignment of the top of small
+    * letters to the pixel grid
     */
+    {
+      AF_LatinAxis  axis  = &metrics->axis[ AF_DIMENSION_VERT ];
+      AF_LatinBlue  blue  = NULL;
+      FT_UInt       nn;
+
+      for ( nn = 0; nn < axis->blue_count; nn++ )
+      {
+        if ( axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
+        {
+          blue = &axis->blues[nn];
+          break;
+        }
+      }
+
+      if ( blue )
+      {
+        FT_Pos  scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
+        FT_Pos  fitted = FT_PIX_ROUND( scaled );
+
+
+        if ( scaled != fitted )
+        {
+          if ( dim == AF_DIMENSION_HORZ )
+          {
+            if ( fitted < scaled )
+              scale -= scale/50;  /* x_scale = x_scale*0.98 */
+          }
+          else
+          {
+            scale = FT_MulDiv( scale, fitted, scaled );
+          }
+        }
+      }
+    }
+
     axis->scale = scale;
     axis->delta = delta;
 
@@ -417,17 +462,41 @@
         AF_LatinBlue  blue  = & axis->blues[nn];
         FT_Pos        dist;
 
-        blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
-        blue->ref.fit = blue->ref.cur;
-
+        blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
+        blue->ref.fit   = blue->ref.cur;
         blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
         blue->shoot.fit = blue->shoot.cur;
+        blue->flags    &= ~AF_LATIN_BLUE_ACTIVE;
 
        /* a blue zone is only active when it is less than 3/4 pixels tall
         */
         dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
-        if ( dist >= 48 || dist <= -48 )
-          blue->flags |= ~AF_LATIN_BLUE_ACTIVE;
+        if ( dist <= 48 && dist >= -48 )
+        {
+          FT_Pos  delta, delta2;
+
+          delta  = blue->shoot.org - blue->ref.org;
+          delta2 = delta;
+          if ( delta < 0 )
+            delta2 = -delta2;
+
+          delta2 = FT_MulFix( delta2, scale );
+
+          if ( delta2 < 32 )
+            delta2 = 0;
+          else if ( delta2 < 64 )
+            delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
+          else
+            delta2 = FT_PIX_ROUND( delta2 );
+
+          if ( delta < 0 )
+            delta2 = -delta2;
+
+          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
+          blue->shoot.fit = blue->ref.fit + delta2;
+
+          blue->flags |= AF_LATIN_BLUE_ACTIVE;
+        }
       }
     }
   }
@@ -437,6 +506,9 @@
   af_latin_metrics_scale( AF_LatinMetrics  metrics,
                           AF_Scaler        scaler )
   {
+    if ( AF_SCALER_EQUAL_SCALES( scaler, &metrics->root.scaler ) )
+      return;
+
     af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
     af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
   }
@@ -791,6 +863,7 @@
                                 AF_Dimension   dim )
   {
     AF_AxisHints  axis = &hints->axis[dim];
+    AF_LatinAxis  laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
     AF_Edge       edges = axis->edges;
     AF_Edge       edge, edge_limit;
 
@@ -825,7 +898,7 @@
     /*                                                                   */
     /*********************************************************************/
 
-    edge_distance_threshold = FT_MulFix( hints->edge_distance_threshold,
+    edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
                                          scale );
     if ( edge_distance_threshold > 64 / 4 )
       edge_distance_threshold = 64 / 4;
@@ -1138,18 +1211,19 @@
 
   static FT_Error
   af_latin_hints_init( AF_GlyphHints    hints,
-                       FT_Outline*      outline,
                        AF_LatinMetrics  metrics )
   {
-    FT_Error        error;
     FT_Render_Mode  mode;
 
-    error = af_glyph_hints_reset( hints, &metrics->root.scaler,
-                                  (AF_ScriptMetrics) metrics,
-                                  outline );
-    if (error)
-      goto Exit;
+    af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
 
+   /* correct x_scale and y_scale when needed, since they may have
+    * been modified af_latin_scale_dim above
+    */
+    hints->x_scale = metrics->axis[ AF_DIMENSION_HORZ ].scale;
+    hints->x_delta = metrics->axis[ AF_DIMENSION_HORZ ].delta;
+    hints->y_scale = metrics->axis[ AF_DIMENSION_VERT ].scale;
+    hints->y_delta = metrics->axis[ AF_DIMENSION_VERT ].delta;
 
    /* compute flags depending on render mode, etc...
     */
@@ -1176,20 +1250,10 @@
     if ( mode == FT_RENDER_MODE_MONO )
       hints->other_flags |= AF_LATIN_HINTS_MONO;
 
-   /* analyze glyph outline
-    */
-    if ( AF_HINTS_DO_HORIZONTAL(hints) )
-      af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
+    return 0;
+  }
 
-    if ( AF_HINTS_DO_VERTICAL(hints) )
-    {
-      af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
-      af_latin_hints_compute_blue_edges( hints, metrics );
-    }
 
- Exit:
-   return error;
-  }
 
  /***************************************************************************/
  /***************************************************************************/
@@ -1738,10 +1802,26 @@
                         FT_Outline*      outline,
                         AF_LatinMetrics  metrics )
   {
+    FT_Error      error;
     AF_Dimension  dim;
 
-    FT_UNUSED( metrics );
+    error = af_glyph_hints_reload( hints, outline );
+    if ( error )
+      goto Exit;
 
+   /* analyze glyph outline
+    */
+    if ( AF_HINTS_DO_HORIZONTAL(hints) )
+      af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
+
+    if ( AF_HINTS_DO_VERTICAL(hints) )
+    {
+      af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
+      af_latin_hints_compute_blue_edges( hints, metrics );
+    }
+
+   /* grid-fit the outline
+    */
     for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
     {
       if ( (dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL(hints)) ||
@@ -1755,7 +1835,8 @@
     }
     af_glyph_hints_save( hints, outline );
 
-    return 0;
+  Exit:
+    return error;
   }
 
  /***************************************************************************/
@@ -1768,10 +1849,11 @@
 
   static const AF_Script_UniRangeRec  af_latin_uniranges[] =
   {
-    { 32, 127 },    /* XXX: TODO: Add new Unicode ranges here !! */
+    { 32,  127 },    /* XXX: TODO: Add new Unicode ranges here !! */
     { 160, 255 },
-    { 0, 0 }
+    { 0,   0 }
   };
+
 
   FT_LOCAL_DEF( const AF_ScriptClassRec )  af_latin_script_class =
   {
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -51,9 +51,10 @@
 
   enum
   {
-    AF_LATIN_BLUE_ACTIVE = (1 << 0),
-    AF_LATIN_BLUE_TOP    = (1 << 1),
-
+    AF_LATIN_BLUE_ACTIVE     = (1 << 0),
+    AF_LATIN_BLUE_TOP        = (1 << 1),
+    AF_LATIN_BLUE_ADJUSTMENT = (1 << 2),  /* used for scale adjustment */
+                                          /* optimization              */
     AF_LATIN_BLUE_FLAG_MAX
   };
 
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -105,17 +105,10 @@
         * is needed
         */
         if ( loader->transformed )
-        {
-          FT_Vector*  point = slot->outline.points;
-          FT_Vector*  limit = point + slot->outline.n_points;
+          FT_Outline_Translate( &slot->outline,
+                                loader->trans_delta.x,
+                                loader->trans_delta.y );
 
-          for ( ; point < limit; point++ )
-          {
-            point->x += loader->trans_delta.x;
-            point->y += loader->trans_delta.y;
-          }
-        }
-
         /* copy the outline points in the loader's current               */
         /* extra points which is used to keep original glyph coordinates */
         error = FT_GlyphLoader_CheckPoints( gloader,
@@ -157,16 +150,10 @@
 
         /* now load the slot image into the auto-outline and run the */
         /* automatic hinting process                                 */
-        error = metrics->clazz->script_hints_init( hints,
-                                                   &gloader->current.outline,
-                                                   metrics );
-        if ( error )
-          goto Exit;
-
-        /* apply the hints */
         metrics->clazz->script_hints_apply( hints,
                                             &gloader->current.outline,
                                             metrics );
+
         /* we now need to hint the metrics according to the change in */
         /* width/positioning that occured during the hinting process  */
         {
@@ -175,20 +162,27 @@
           AF_Edge       edge1 = axis->edges;    /* leftmost edge  */
           AF_Edge       edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */
 
+          if ( edge2 > edge1 )
+          {
+            old_advance = loader->pp2.x;
+            old_rsb     = old_advance - edge2->opos;
+            old_lsb     = edge1->opos;
+            new_lsb     = edge1->pos;
 
-          old_advance = loader->pp2.x;
-          old_rsb     = old_advance - edge2->opos;
-          old_lsb     = edge1->opos;
-          new_lsb     = edge1->pos;
+            loader->pp1.x = FT_PIX_ROUND( new_lsb    - old_lsb );
+            loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
 
-          loader->pp1.x = FT_PIX_ROUND( new_lsb    - old_lsb );
-          loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
-
 #if 0
-          /* try to fix certain bad advance computations */
-          if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
-            loader->pp2.x += 64;
+            /* try to fix certain bad advance computations */
+            if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
+              loader->pp2.x += 64;
 #endif
+          }
+          else
+          {
+            loader->pp1.x = FT_PIX_ROUND( loader->pp1.x );
+            loader->pp2.x = FT_PIX_ROUND( loader->pp2.x );
+          }
         }
 
         /* good, we simply add the glyph to our loader's base */
@@ -366,7 +360,13 @@
         slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
                                                x_scale );
 #else
-      slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+      /* for mono-width fonts (like Andale, Courier, etc.) we need */
+      /* to keep the original rounded advance width                */
+      if ( !FT_IS_FIXED_WIDTH( slot->face ) )
+        slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+      else
+        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
+                                               metrics->scaler.x_scale );
 #endif
 
       slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
@@ -434,8 +434,13 @@
         load_flags |=  FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
         load_flags &= ~FT_LOAD_RENDER;
 
+        error = metrics->clazz->script_hints_init( &loader->hints, metrics );
+        if ( error )
+          goto Exit;
+
         error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
       }
     }
+  Exit:
     return error;
   }
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -1,3 +1,20 @@
+/***************************************************************************
+ *
+ *  FreeType auto-fitter
+ *
+ *  (c) 2004 David Turner
+ *
+ *  The auto-fitter is a complete rewrite of the old auto-hinter.
+ *  its main feature is the ability to differentiate between different
+ *  scripts in order to apply language-specific rules.
+ *
+ *  the code has also been compartimentized into several entities that
+ *  should make algorithmic experimentation easier than with the old
+ *  code.
+ *
+ *  finally, we get rid of the Catharon license, since this code is
+ *  released under the FreeType one.
+ */
 #ifndef __AFTYPES_H__
 #define __AFTYPES_H__
 
@@ -73,7 +90,7 @@
 
   typedef FT_Int    AF_Angle;
 
-#define  AF_ANGLE_PI     128
+#define  AF_ANGLE_PI     256
 #define  AF_ANGLE_2PI    (AF_ANGLE_PI*2)
 #define  AF_ANGLE_PI2    (AF_ANGLE_PI/2)
 #define  AF_ANGLE_PI4    (AF_ANGLE_PI/4)
@@ -164,7 +181,13 @@
   } AF_ScalerRec, *AF_Scaler;
 
 
+#define  AF_SCALER_EQUAL_SCALES(a,b)    \
+   ( (a)->x_scale == (b)->x_scale &&    \
+     (a)->y_scale == (b)->y_scale &&    \
+     (a)->x_delta == (b)->x_delta &&    \
+     (a)->y_delta == (b)->y_delta )
 
+
  /**************************************************************************/
  /**************************************************************************/
  /*****                                                                *****/
@@ -228,7 +251,6 @@
 
 
   typedef FT_Error  (*AF_Script_InitHintsFunc)( AF_GlyphHints     hints,
-                                                FT_Outline*       outline,
                                                 AF_ScriptMetrics  metrics );
 
   typedef void      (*AF_Script_ApplyHintsFunc)( AF_GlyphHints     hints,
--- a/src/tools/cordic.py
+++ b/src/tools/cordic.py
@@ -1,7 +1,8 @@
 # compute arctangent table for CORDIC computations in fttrigon.c
 import sys, math
 
-units  = 64*65536.0   # don't change !!
+#units  = 64*65536.0   # don't change !!
+units  = 256
 scale  = units/math.pi
 shrink = 1.0
 comma  = ""
@@ -23,7 +24,7 @@
 
     errlo = abs( alo - ax )
     errhi = abs( ahi - ax )
-    
+
     if ( errlo < errhi ):
       hi = lo
 
@@ -44,8 +45,8 @@
         x = 1.0/(2.0**n)    # tangent value
     else:
         x = 2.0**(-n)
-      
-    angle  = math.atan(x)    # arctangent 
+
+    angle  = math.atan(x)    # arctangent
     angle2 = angle*scale     # arctangent in FT_Angle units
 
     # determine which integer value for angle gives the best tangent
@@ -63,12 +64,12 @@
 
     if angle2 <= 0:
         break
-    
+
     sys.stdout.write( comma + repr( int(angle2) ) )
     comma = ", "
-    
+
     shrink = shrink * math.cos( angle2/scale)
-      
+
 
 print
 print "shrink factor    = " + repr( shrink )