Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / freetype2 / src / src / autofit / aflatin.c
index 394fb97..54fcf7f 100644 (file)
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (body).                */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by                  */
+/*  Copyright 2003-2011 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 
 #include <ft2build.h>
 #include FT_ADVANCES_H
+#include FT_INTERNAL_DEBUG_H
 
 #include "aflatin.h"
 #include "aferrors.h"
 
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
 #include "afwarp.h"
 #endif
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_aflatin
+
+
+  /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
   /*****            L A T I N   G L O B A L   M E T R I C S            *****/
   /*************************************************************************/
   /*************************************************************************/
 
+
+  /* Find segments and links, compute all stem widths, and initialize */
+  /* standard width and height for the glyph with given charcode.     */
+
   FT_LOCAL_DEF( void )
   af_latin_metrics_init_widths( AF_LatinMetrics  metrics,
                                 FT_Face          face,
       FT_ZERO( dummy );
 
       dummy->units_per_em = metrics->units_per_em;
-      scaler->x_scale     = scaler->y_scale = 0x10000L;
-      scaler->x_delta     = scaler->y_delta = 0;
+
+      scaler->x_scale = 0x10000L;
+      scaler->y_scale = 0x10000L;
+      scaler->x_delta = 0;
+      scaler->y_delta = 0;
+
       scaler->face        = face;
       scaler->render_mode = FT_RENDER_MODE_NORMAL;
       scaler->flags       = 0;
 
       af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
 
-      error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 );
+      error = af_glyph_hints_reload( hints, &face->glyph->outline );
       if ( error )
         goto Exit;
 
               dist = -dist;
 
             if ( num_widths < AF_LATIN_MAX_WIDTHS )
-              axis->widths[ num_widths++ ].org = dist;
+              axis->widths[num_widths++].org = dist;
           }
         }
 
   };
 
 
+  /* Find all blue zones.  Flat segments give the reference points, */
+  /* round segments the overshoot positions.                        */
+
   static void
   af_latin_metrics_init_blues( AF_LatinMetrics  metrics,
                                FT_Face          face )
 
 
     /* we compute the blues simply by loading each character from the    */
-    /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */
+    /* `af_latin_blue_chars[blues]' string, then finding its top-most or */
     /* bottom-most points (depending on `AF_IS_TOP_BLUE')                */
 
-    AF_LOG(( "blue zones computation\n" ));
-    AF_LOG(( "------------------------------------------------\n" ));
+    FT_TRACE5(( "blue zones computation\n" ));
+    FT_TRACE5(( "------------------------------------------------\n" ));
 
     for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
     {
       FT_Pos*      blue_shoot;
 
 
-      AF_LOG(( "blue %3d: ", bb ));
+      FT_TRACE5(( "blue %3d: ", bb ));
 
       num_flats  = 0;
       num_rounds = 0;
       for ( ; p < limit && *p; p++ )
       {
         FT_UInt     glyph_index;
-        FT_Pos      best_y; /* same as points.y */
+        FT_Pos      best_y;                            /* same as points.y */
         FT_Int      best_point, best_first, best_last;
         FT_Vector*  points;
         FT_Bool     round = 0;
 
 
-        AF_LOG(( "'%c'", *p ));
+        FT_TRACE5(( "'%c'", *p ));
 
         /* load the character in the face -- skip unknown or empty ones */
         glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
           FT_Int  last  = -1;
 
 
-          for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
+          for ( nn = 0;
+                nn < glyph->outline.n_contours;
+                first = last + 1, nn++ )
           {
             FT_Int  old_best_point = best_point;
             FT_Int  pp;
             /* In some fonts, they correspond to mark attachment points     */
             /* which are way outside of the glyph's real outline.           */
             if ( last <= first )
-                continue;
+              continue;
 
             if ( AF_LATIN_IS_TOP_BLUE( bb ) )
             {
               best_last  = last;
             }
           }
-          AF_LOG(( "%5d", best_y ));
+          FT_TRACE5(( "%5d", best_y ));
         }
 
         /* now check whether the point belongs to a straight or round   */
 
           } while ( next != best_point );
 
-          /* now, set the `round' flag depending on the segment's kind */
+          /* now set the `round' flag depending on the segment's kind */
           round = FT_BOOL(
             FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
             FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
 
-          AF_LOG(( "%c ", round ? 'r' : 'f' ));
+          FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
         }
 
         if ( round )
           flats[num_flats++]   = best_y;
       }
 
-      AF_LOG(( "\n" ));
+      FT_TRACE5(( "\n" ));
 
       if ( num_flats == 0 && num_rounds == 0 )
       {
          *  we couldn't find a single glyph to compute this blue zone,
          *  we will simply ignore it then
          */
-        AF_LOG(( "empty\n" ));
+        FT_TRACE5(( "empty\n" ));
         continue;
       }
 
       af_sort_pos( num_rounds, rounds );
       af_sort_pos( num_flats,  flats );
 
-      blue       = & axis->blues[axis->blue_count];
-      blue_ref   = & blue->ref.org;
-      blue_shoot = & blue->shoot.org;
+      blue       = &axis->blues[axis->blue_count];
+      blue_ref   = &blue->ref.org;
+      blue_shoot = &blue->shoot.org;
 
       axis->blue_count++;
 
 
 
         if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
-          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+          *blue_ref   =
+          *blue_shoot = ( shoot + ref ) / 2;
       }
 
       blue->flags = 0;
       if ( bb == AF_LATIN_BLUE_SMALL_TOP )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
-      AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
     }
 
+    FT_TRACE5(( "\n" ));
+
     return;
   }
 
 
+  /* Check whether all ASCII digits have the same advance width. */
+
   FT_LOCAL_DEF( void )
   af_latin_metrics_check_digits( AF_LatinMetrics  metrics,
                                  FT_Face          face )
   {
-    FT_UInt  i;
-    FT_Bool  started = 0, same_width = 1;
+    FT_UInt   i;
+    FT_Bool   started = 0, same_width = 1;
+    FT_Fixed  advance, old_advance = 0;
 
 
-    /* check whether all ASCII digits have the same advance width; */
-    /* digit `0' is 0x30 in all supported charmaps                 */
+    /* digit `0' is 0x30 in all supported charmaps */
     for ( i = 0x30; i <= 0x39; i++ )
     {
-      FT_UInt   glyph_index;
-      FT_Fixed  advance, old_advance = 0;
+      FT_UInt  glyph_index;
 
 
       glyph_index = FT_Get_Char_Index( face, i );
   }
 
 
+  /* Initialize global metrics. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_metrics_init( AF_LatinMetrics  metrics,
                          FT_Face          face )
       FT_ENCODING_APPLE_ROMAN,
       FT_ENCODING_ADOBE_STANDARD,
       FT_ENCODING_ADOBE_LATIN_1,
+
       FT_ENCODING_NONE  /* end of list */
     };
 
   }
 
 
+  /* Adjust scaling value, then scale and shift widths   */
+  /* and blue zones (if applicable) for given dimension. */
+
   static void
   af_latin_metrics_scale_dim( AF_LatinMetrics  metrics,
                               AF_Scaler        scaler,
           else
 #endif
           if ( dim == AF_DIMENSION_VERT )
-          {
             scale = FT_MulDiv( scale, fitted, scaled );
-          }
         }
       }
     }
       metrics->root.scaler.y_delta = delta;
     }
 
-    /* scale the standard widths */
+    /* scale the widths */
     for ( nn = 0; nn < axis->width_count; nn++ )
     {
       AF_Width  width = axis->widths + nn;
     }
 
     /* an extra-light axis corresponds to a standard width that is */
-    /* smaller than 0.75 pixels                                    */
+    /* smaller than 5/8 pixels                                     */
     axis->extra_light =
       (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
 
         dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
         if ( dist <= 48 && dist >= -48 )
         {
-          FT_Pos  delta1, delta2;
+#if 0
+          FT_Pos  delta1;
+#endif
+          FT_Pos  delta2;
+
 
+          /* use discrete values for blue zone widths */
 
+#if 0
+
+          /* generic, original code */
           delta1 = blue->shoot.org - blue->ref.org;
           delta2 = delta1;
           if ( delta1 < 0 )
           blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
           blue->shoot.fit = blue->ref.fit + delta2;
 
+#else
+
+          /* simplified version due to abs(dist) <= 48 */
+          delta2 = dist;
+          if ( dist < 0 )
+            delta2 = -delta2;
+
+          if ( delta2 < 32 )
+            delta2 = 0;
+          else if ( delta < 48 )
+            delta2 = 32;
+          else
+            delta2 = 64;
+
+          if ( dist < 0 )
+            delta2 = -delta2;
+
+          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
+          blue->shoot.fit = blue->ref.fit - delta2;
+
+#endif
+
           blue->flags |= AF_LATIN_BLUE_ACTIVE;
         }
       }
   }
 
 
+  /* Scale global values in both directions. */
+
   FT_LOCAL_DEF( void )
   af_latin_metrics_scale( AF_LatinMetrics  metrics,
                           AF_Scaler        scaler )
   /*************************************************************************/
   /*************************************************************************/
 
+
+  /* Walk over all contours and compute its segments. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_hints_compute_segments( AF_GlyphHints  hints,
                                    AF_Dimension   dim )
   {
-    AF_AxisHints  axis          = &hints->axis[dim];
-    FT_Memory     memory        = hints->memory;
-    FT_Error      error         = AF_Err_Ok;
-    AF_Segment    segment       = NULL;
-    AF_SegmentRec seg0;
-    AF_Point*     contour       = hints->contours;
-    AF_Point*     contour_limit = contour + hints->num_contours;
-    AF_Direction  major_dir, segment_dir;
+    AF_AxisHints   axis          = &hints->axis[dim];
+    FT_Memory      memory        = hints->memory;
+    FT_Error       error         = AF_Err_Ok;
+    AF_Segment     segment       = NULL;
+    AF_SegmentRec  seg0;
+    AF_Point*      contour       = hints->contours;
+    AF_Point*      contour_limit = contour + hints->num_contours;
+    AF_Direction   major_dir, segment_dir;
 
 
     FT_ZERO( &seg0 );
             /* a segment is round if either its first or last point */
             /* is a control point                                   */
             if ( ( segment->first->flags | point->flags ) &
-                   AF_FLAG_CONTROL                        )
+                 AF_FLAG_CONTROL                          )
               segment->flags |= AF_EDGE_ROUND;
 
             /* compute segment size */
           min_pos = max_pos = point->u;
           segment->first    = point;
           segment->last     = point;
-          segment->contour  = contour;
           on_edge           = 1;
         }
 
   }
 
 
+  /* Link segments to form stems and serifs. */
+
   FT_LOCAL_DEF( void )
   af_latin_hints_link_segments( AF_GlyphHints  hints,
                                 AF_Dimension   dim )
       if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
         continue;
 
+      /* search for stems having opposite directions, */
+      /* with seg1 to the `left' of seg2              */
       for ( seg2 = segments; seg2 < segment_limit; seg2++ )
-        if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
-        {
-          FT_Pos  pos1 = seg1->pos;
-          FT_Pos  pos2 = seg2->pos;
-          FT_Pos  dist = pos2 - pos1;
+      {
+        FT_Pos  pos1 = seg1->pos;
+        FT_Pos  pos2 = seg2->pos;
 
 
-          if ( dist < 0 )
-            dist = -dist;
+        if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 )
+        {
+          /* compute distance between the two segments */
+          FT_Pos  dist = pos2 - pos1;
+          FT_Pos  min  = seg1->min_coord;
+          FT_Pos  max  = seg1->max_coord;
+          FT_Pos  len, score;
 
-          {
-            FT_Pos  min = seg1->min_coord;
-            FT_Pos  max = seg1->max_coord;
-            FT_Pos  len, score;
 
+          if ( min < seg2->min_coord )
+            min = seg2->min_coord;
 
-            if ( min < seg2->min_coord )
-              min = seg2->min_coord;
+          if ( max > seg2->max_coord )
+            max = seg2->max_coord;
 
-            if ( max > seg2->max_coord )
-              max = seg2->max_coord;
+          /* compute maximum coordinate difference of the two segments */
+          len = max - min;
+          if ( len >= len_threshold )
+          {
+            /* small coordinate differences cause a higher score, and     */
+            /* segments with a greater distance cause a higher score also */
+            score = dist + len_score / len;
 
-            len = max - min;
-            if ( len >= len_threshold )
+            /* and we search for the smallest score */
+            /* of the sum of the two values         */
+            if ( score < seg1->score )
             {
-              score = dist + len_score / len;
-
-              if ( score < seg1->score )
-              {
-                seg1->score = score;
-                seg1->link  = seg2;
-              }
+              seg1->score = score;
+              seg1->link  = seg2;
+            }
 
-              if ( score < seg2->score )
-              {
-                seg2->score = score;
-                seg2->link  = seg1;
-              }
+            if ( score < seg2->score )
+            {
+              seg2->score = score;
+              seg2->link  = seg1;
             }
           }
         }
+      }
     }
 
-    /* now, compute the `serif' segments */
+    /* now compute the `serif' segments, cf. explanations in `afhints.h' */
     for ( seg1 = segments; seg1 < segment_limit; seg1++ )
     {
       seg2 = seg1->link;
   }
 
 
+  /* Link segments to edges, using feature analysis for selection. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_hints_compute_edges( AF_GlyphHints  hints,
                                 AF_Dimension   dim )
     AF_Segment    segment_limit = segments + axis->num_segments;
     AF_Segment    seg;
 
+#if 0
     AF_Direction  up_dir;
+#endif
     FT_Fixed      scale;
     FT_Pos        edge_distance_threshold;
     FT_Pos        segment_length_threshold;
     scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
                                          : hints->y_scale;
 
+#if 0
     up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
                                           : AF_DIR_RIGHT;
+#endif
 
     /*
-     *  We ignore all segments that are less than 1 pixels in length,
+     *  We ignore all segments that are less than 1 pixel in length
      *  to avoid many problems with serif fonts.  We compute the
      *  corresponding threshold in font units.
      */
 
     /*********************************************************************/
     /*                                                                   */
-    /* We will begin by generating a sorted table of edges for the       */
-    /* current direction.  To do so, we simply scan each segment and try */
-    /* to find an edge in our table that corresponds to its position.    */
+    /* We begin by generating a sorted table of edges for the current    */
+    /* direction.  To do so, we simply scan each segment and try to find */
+    /* an edge in our table that corresponds to its position.            */
     /*                                                                   */
     /* If no edge is found, we create and insert a new edge in the       */
     /* sorted table.  Otherwise, we simply add the segment to the edge's */
-    /* list which will be processed in the second step to compute the    */
+    /* list which gets processed in the second step to compute the       */
     /* edge's properties.                                                */
     /*                                                                   */
-    /* Note that the edges table is sorted along the segment/edge        */
+    /* Note that the table of edges is sorted along the segment/edge     */
     /* position.                                                         */
     /*                                                                   */
     /*********************************************************************/
 
+    /* assure that edge distance threshold is at most 0.25px */
     edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
                                          scale );
     if ( edge_distance_threshold > 64 / 4 )
 
     for ( seg = segments; seg < segment_limit; seg++ )
     {
-      AF_Edge  found = 0;
+      AF_Edge  found = NULL;
       FT_Int   ee;
 
 
 
         edge->first    = seg;
         edge->last     = seg;
-        edge->fpos     = seg->pos;
         edge->dir      = seg->dir;
-        edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
+        edge->fpos     = seg->pos;
+        edge->opos     = FT_MulFix( seg->pos, scale );
+        edge->pos      = edge->opos;
         seg->edge_next = seg;
       }
       else
     /*********************************************************************/
     /*                                                                   */
     /* Good, we will now compute each edge's properties according to     */
-    /* segments found on its position.  Basically, these are:            */
+    /* the segments found on its position.  Basically, these are         */
     /*                                                                   */
-    /*  - edge's main direction                                          */
+    /*  - the edge's main direction                                      */
     /*  - stem edge, serif edge or both (which defaults to stem then)    */
     /*  - rounded edge, straight or both (which defaults to straight)    */
     /*  - link for edge                                                  */
           } while ( seg != edge->first );
       }
 
-      /* now, compute each edge properties */
+      /* now compute each edge properties */
       for ( edge = edges; edge < edge_limit; edge++ )
       {
         FT_Int  is_round    = 0;  /* does it contain round segments?    */
         FT_Int  is_straight = 0;  /* does it contain straight segments? */
+#if 0
         FT_Pos  ups         = 0;  /* number of upwards segments         */
         FT_Pos  downs       = 0;  /* number of downwards segments       */
+#endif
 
 
         seg = edge->first;
           else
             is_straight++;
 
+#if 0
           /* check for segment direction */
           if ( seg->dir == up_dir )
-            ups   += seg->max_coord-seg->min_coord;
+            ups   += seg->max_coord - seg->min_coord;
           else
-            downs += seg->max_coord-seg->min_coord;
+            downs += seg->max_coord - seg->min_coord;
+#endif
 
           /* check for links -- if seg->serif is set, then seg->link must */
           /* be ignored                                                   */
           edge->dir = 0;  /* both up and down! */
 #endif
 
-        /* gets rid of serifs if link is set                */
+        /* get rid of serifs if link is set                 */
         /* XXX: This gets rid of many unpleasant artefacts! */
         /*      Example: the `c' in cour.pfa at size 13     */
 
   }
 
 
+  /* Detect segments and edges for given dimension. */
+
   FT_LOCAL_DEF( FT_Error )
   af_latin_hints_detect_features( AF_GlyphHints  hints,
                                   AF_Dimension   dim )
 
       error = af_latin_hints_compute_edges( hints, dim );
     }
+
     return error;
   }
 
 
+  /* Compute all edges which lie within blue zones. */
+
   FT_LOCAL_DEF( void )
   af_latin_hints_compute_blue_edges( AF_GlyphHints    hints,
                                      AF_LatinMetrics  metrics )
   {
-    AF_AxisHints  axis       = &hints->axis[ AF_DIMENSION_VERT ];
+    AF_AxisHints  axis       = &hints->axis[AF_DIMENSION_VERT];
     AF_Edge       edge       = axis->edges;
     AF_Edge       edge_limit = edge + axis->num_edges;
-    AF_LatinAxis  latin      = &metrics->axis[ AF_DIMENSION_VERT ];
+    AF_LatinAxis  latin      = &metrics->axis[AF_DIMENSION_VERT];
     FT_Fixed      scale      = latin->scale;
 
 
 
 
       /* compute the initial threshold as a fraction of the EM size */
+      /* (the value 40 is heuristic)                                */
       best_dist = FT_MulFix( metrics->units_per_em / 40, scale );
 
+      /* assure a minimum distance of 0.5px */
       if ( best_dist > 64 / 2 )
         best_dist = 64 / 2;
 
         FT_Bool       is_top_blue, is_major_dir;
 
 
-        /* skip inactive blue zones (i.e., those that are too small) */
+        /* skip inactive blue zones (i.e., those that are too large) */
         if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
           continue;
 
           if ( dist < best_dist )
           {
             best_dist = dist;
-            best_blue = & blue->ref;
+            best_blue = &blue->ref;
           }
 
-          /* now, compare it to the overshoot position if the edge is     */
-          /* rounded, and if the edge is over the reference position of a */
-          /* top zone, or under the reference position of a bottom zone   */
+          /* now compare it to the overshoot position and check whether */
+          /* the edge is rounded, and whether the edge is over the      */
+          /* reference position of a top zone, or under the reference   */
+          /* position of a bottom zone                                  */
           if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
           {
             FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
 
             if ( is_top_blue ^ is_under_ref )
             {
-              blue = latin->blues + bb;
               dist = edge->fpos - blue->shoot.org;
               if ( dist < 0 )
                 dist = -dist;
               if ( dist < best_dist )
               {
                 best_dist = dist;
-                best_blue = & blue->shoot;
+                best_blue = &blue->shoot;
               }
             }
           }
   }
 
 
+  /* Initalize hinting engine. */
+
   static FT_Error
   af_latin_hints_init( AF_GlyphHints    hints,
                        AF_LatinMetrics  metrics )
 
     /*
      *  correct x_scale and y_scale if needed, since they may have
-     *  been modified `af_latin_metrics_scale_dim' above
+     *  been modified by `af_latin_metrics_scale_dim' above
      */
     hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
     hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
     /* compute flags depending on render mode, etc. */
     mode = metrics->root.scaler.render_mode;
 
-#if 0 /* #ifdef AF_USE_WARPER */
+#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
     if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
     {
       metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
      *  In `light' hinting mode we disable horizontal hinting completely.
      *  We also do it if the face is italic.
      */
-    if ( mode == FT_RENDER_MODE_LIGHT                    ||
-         (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
+    if ( mode == FT_RENDER_MODE_LIGHT                      ||
+         ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
       scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
 
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
-    return 0;
+    return AF_Err_Ok;
   }
 
 
   /*************************************************************************/
   /*************************************************************************/
 
-  /* snap a given width in scaled coordinates to one of the */
-  /* current standard widths                                */
+  /* Snap a given width in scaled coordinates to one of the */
+  /* current standard widths.                               */
 
   static FT_Pos
   af_latin_snap_width( AF_Width  widths,
   }
 
 
-  /* compute the snapped width of a given stem */
+  /* Compute the snapped width of a given stem, ignoring very thin ones. */
+  /* There is a lot of voodoo in this function; changing the hard-coded  */
+  /* parameters influence the whole hinting process.                     */
 
   static FT_Pos
   af_latin_compute_stem_width( AF_GlyphHints  hints,
 
 
     if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
-          axis->extra_light                      )
+         axis->extra_light                       )
       return width;
 
     if ( dist < 0 )
       /* smooth hinting process: very lightly quantize the stem width */
 
       /* leave the widths of serifs alone */
-
-      if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+      if ( ( stem_flags & AF_EDGE_SERIF ) &&
+           vertical                       &&
+           ( dist < 3 * 64 )              )
         goto Done_Width;
 
-      else if ( ( base_flags & AF_EDGE_ROUND ) )
+      else if ( base_flags & AF_EDGE_ROUND )
       {
         if ( dist < 80 )
           dist = 64;
 
 
         /* compare to standard width */
-        if ( axis->width_count > 0 )
-        {
-          delta = dist - axis->widths[0].cur;
+        delta = dist - axis->widths[0].cur;
 
-          if ( delta < 0 )
-            delta = -delta;
+        if ( delta < 0 )
+          delta = -delta;
 
-          if ( delta < 40 )
-          {
-            dist = axis->widths[0].cur;
-            if ( dist < 48 )
-              dist = 48;
+        if ( delta < 40 )
+        {
+          dist = axis->widths[0].cur;
+          if ( dist < 48 )
+            dist = 48;
 
-            goto Done_Width;
-          }
+          goto Done_Width;
         }
 
         if ( dist < 3 * 64 )
     else
     {
       /* strong hinting process: snap the stem width to integer pixels */
+
       FT_Pos  org_dist = dist;
 
 
   }
 
 
-  /* align one stem edge relative to the previous stem edge */
+  /* Align one stem edge relative to the previous stem edge. */
 
   static void
   af_latin_align_linked_edge( AF_GlyphHints  hints,
 
     stem_edge->pos = base_edge->pos + fitted_width;
 
-    AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
-             "dist was %.2f, now %.2f\n",
-             stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
-             stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+    FT_TRACE5(( "  LINK: edge %d (opos=%.2f) linked to (%.2f),"
+                " dist was %.2f, now %.2f\n",
+                stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
+                stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
   }
 
 
+  /* Shift the coordinates of the `serif' edge by the same amount */
+  /* as the corresponding `base' edge has been moved already.     */
+
   static void
   af_latin_align_serif_edge( AF_GlyphHints  hints,
                              AF_Edge        base,
   {
     FT_UNUSED( hints );
 
-    serif->pos = base->pos + (serif->opos - base->opos);
+    serif->pos = base->pos + ( serif->opos - base->opos );
   }
 
 
   /*************************************************************************/
 
 
+  /* The main grid-fitting routine. */
+
   FT_LOCAL_DEF( void )
   af_latin_hint_edges( AF_GlyphHints  hints,
                        AF_Dimension   dim )
     AF_Edge       edge_limit = edges + axis->num_edges;
     FT_PtrDist    n_edges;
     AF_Edge       edge;
-    AF_Edge       anchor     = 0;
+    AF_Edge       anchor     = NULL;
     FT_Int        has_serifs = 0;
 
 
+    FT_TRACE5(("%s edge hinting\n", dim == AF_DIMENSION_VERT ? "horizontal"
+                                                             : "vertical"));
+
     /* we begin by aligning all stems relative to the blue zone */
     /* if needed -- that's only for horizontal edges            */
 
       for ( edge = edges; edge < edge_limit; edge++ )
       {
         AF_Width  blue;
-        AF_Edge   edge1, edge2;
+        AF_Edge   edge1, edge2; /* these edges form the stem to check */
 
 
         if ( edge->flags & AF_EDGE_DONE )
         edge2 = edge->link;
 
         if ( blue )
-        {
           edge1 = edge;
-        }
+
+        /* flip edges if the other stem is aligned to a blue zone */
         else if ( edge2 && edge2->blue_edge )
         {
           blue  = edge2->blue_edge;
         if ( !edge1 )
           continue;
 
-        AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
-                 "was (%.2f)\n",
-                 edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
-                 edge1->pos / 64.0 ));
+        FT_TRACE5(( "  BLUE: edge %d (opos=%.2f) snapped to (%.2f),"
+                    " was (%.2f)\n",
+                    edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
+                    edge1->pos / 64.0 ));
 
         edge1->pos    = blue->fit;
         edge1->flags |= AF_EDGE_DONE;
       }
     }
 
-    /* now we will align all stem edges, trying to maintain the */
-    /* relative order of stems in the glyph                     */
+    /* now we align all other stem edges, trying to maintain the */
+    /* relative order of stems in the glyph                      */
     for ( edge = edges; edge < edge_limit; edge++ )
     {
       AF_Edge  edge2;
       /* this should not happen, but it's better to be safe */
       if ( edge2->blue_edge )
       {
-        AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+        FT_TRACE5(( "  ASSERTION FAILED for edge %d\n", edge2-edges ));
 
         af_latin_align_linked_edge( hints, dim, edge2, edge );
         edge->flags |= AF_EDGE_DONE;
 
       if ( !anchor )
       {
+        /* if we reach this if clause, no stem has been aligned yet */
+
         FT_Pos  org_len, org_center, cur_len;
         FT_Pos  cur_pos1, error1, error2, u_off, d_off;
 
                     hints, dim, org_len,
                     (AF_Edge_Flags)edge->flags,
                     (AF_Edge_Flags)edge2->flags );
+
+        /* some voodoo to specially round edges for small stem widths; */
+        /* the idea is to align the center of a stem, then shifting    */
+        /* the stem edges to suitable positions                        */
         if ( cur_len <= 64 )
-          u_off = d_off = 32;
+        {
+          /* width <= 1px */
+          u_off = 32;
+          d_off = 32;
+        }
         else
         {
+          /* 1px < width < 1.5px */
           u_off = 38;
           d_off = 26;
         }
         if ( cur_len < 96 )
         {
           org_center = edge->opos + ( org_len >> 1 );
-
           cur_pos1   = FT_PIX_ROUND( org_center );
 
           error1 = org_center - ( cur_pos1 - u_off );
         else
           edge->pos = FT_PIX_ROUND( edge->opos );
 
-        AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
-                 "snapped to (%.2f) (%.2f)\n",
-                 edge-edges, edge->opos / 64.0,
-                 edge2-edges, edge2->opos / 64.0,
-                 edge->pos / 64.0, edge2->pos / 64.0 ));
+        FT_TRACE5(( "  ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
+                    " snapped to (%.2f) (%.2f)\n",
+                    edge - edges, edge->opos / 64.0,
+                    edge2 - edges, edge2->opos / 64.0,
+                    edge->pos / 64.0, edge2->pos / 64.0 ));
         anchor = edge;
 
         edge->flags |= AF_EDGE_DONE;
         org_center = org_pos + ( org_len >> 1 );
 
         cur_len = af_latin_compute_stem_width(
-                   hints, dim, org_len,
-                   (AF_Edge_Flags)edge->flags,
-                   (AF_Edge_Flags)edge2->flags );
+                    hints, dim, org_len,
+                    (AF_Edge_Flags)edge->flags,
+                    (AF_Edge_Flags)edge2->flags );
 
         if ( edge2->flags & AF_EDGE_DONE )
+        {
+          FT_TRACE5(( "  ADJUST: edge %d (pos=%.2f) moved to %.2f\n",
+                      edge - edges, edge->pos / 64.0,
+                      ( edge2->pos - cur_len ) / 64.0 ));
+
           edge->pos = edge2->pos - cur_len;
+        }
 
         else if ( cur_len < 96 )
         {
           cur_pos1 = FT_PIX_ROUND( org_center );
 
           if (cur_len <= 64 )
-            u_off = d_off = 32;
+          {
+            u_off = 32;
+            d_off = 32;
+          }
           else
           {
             u_off = 38;
           edge->pos  = cur_pos1 - cur_len / 2;
           edge2->pos = cur_pos1 + cur_len / 2;
 
-          AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
-                   "snapped to (%.2f) and (%.2f)\n",
-                   edge-edges, edge->opos / 64.0,
-                   edge2-edges, edge2->opos / 64.0,
-                   edge->pos / 64.0, edge2->pos / 64.0 ));
+          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
+                      " snapped to (%.2f) and (%.2f)\n",
+                      edge - edges, edge->opos / 64.0,
+                      edge2 - edges, edge2->opos / 64.0,
+                      edge->pos / 64.0, edge2->pos / 64.0 ));
         }
         else
         {
                          (AF_Edge_Flags)edge->flags,
                          (AF_Edge_Flags)edge2->flags );
 
-          cur_pos1   = FT_PIX_ROUND( org_pos );
-          delta1     = cur_pos1 + ( cur_len >> 1 ) - org_center;
+          cur_pos1 = FT_PIX_ROUND( org_pos );
+          delta1   = cur_pos1 + ( cur_len >> 1 ) - org_center;
           if ( delta1 < 0 )
             delta1 = -delta1;
 
-          cur_pos2   = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
-          delta2     = cur_pos2 + ( cur_len >> 1 ) - org_center;
+          cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - 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;
 
-          AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
-                   "snapped to (%.2f) and (%.2f)\n",
-                   edge-edges, edge->opos / 64.0,
-                   edge2-edges, edge2->opos / 64.0,
-                   edge->pos / 64.0, edge2->pos / 64.0 ));
+          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
+                      " snapped to (%.2f) and (%.2f)\n",
+                      edge - edges, edge->opos / 64.0,
+                      edge2 - edges, edge2->opos / 64.0,
+                      edge->pos / 64.0, edge2->pos / 64.0 ));
         }
 
         edge->flags  |= AF_EDGE_DONE;
 
         if ( edge > edges && edge->pos < edge[-1].pos )
         {
-          AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
-                   edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+          FT_TRACE5(( "  BOUND: %d (pos=%.2f) to (%.2f)\n",
+                      edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
           edge->pos = edge[-1].pos;
         }
       }
         if ( delta < 64 + 16 )
         {
           af_latin_align_serif_edge( hints, edge->serif, edge );
-          AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
-                   "aligned to (%.2f)\n",
-                   edge-edges, edge->opos / 64.0,
-                   edge->serif - edges, edge->serif->opos / 64.0,
-                   edge->pos / 64.0 ));
+          FT_TRACE5(( "  SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
+                      " aligned to (%.2f)\n",
+                      edge - edges, edge->opos / 64.0,
+                      edge->serif - edges, edge->serif->opos / 64.0,
+                      edge->pos / 64.0 ));
         }
         else if ( !anchor )
         {
-          AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
-                   edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
           edge->pos = FT_PIX_ROUND( edge->opos );
           anchor    = edge;
+          FT_TRACE5(( "  SERIF_ANCHOR: edge %d (opos=%.2f)"
+                      " snapped to (%.2f)\n",
+                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
         }
         else
         {
                           FT_MulDiv( edge->opos - before->opos,
                                      after->pos - before->pos,
                                      after->opos - before->opos );
-            AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) "
-                     "from %d (opos=%.2f)\n",
-                     edge-edges, edge->opos / 64.0,
-                     edge->pos / 64.0, before - edges,
-                     before->opos / 64.0 ));
+
+            FT_TRACE5(( "  SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+                        " from %d (opos=%.2f)\n",
+                        edge - edges, edge->opos / 64.0,
+                        edge->pos / 64.0,
+                        before - edges, before->opos / 64.0 ));
           }
           else
           {
             edge->pos = anchor->pos +
                         ( ( edge->opos - anchor->opos + 16 ) & ~31 );
-            AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
-                     edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+
+            FT_TRACE5(( "  SERIF_LINK2: edge %d (opos=%.2f)"
+                        " snapped to (%.2f)\n",
+                        edge - edges, edge->opos / 64.0, edge->pos / 64.0 ));
           }
         }
 
           edge->pos = edge[1].pos;
       }
     }
+
+    FT_TRACE5(( "\n" ));
   }
 
 
+  /* Apply the complete hinting algorithm to a latin glyph. */
+
   static FT_Error
   af_latin_hints_apply( AF_GlyphHints    hints,
                         FT_Outline*      outline,
     int       dim;
 
 
-    error = af_glyph_hints_reload( hints, outline, 1 );
+    error = af_glyph_hints_reload( hints, outline );
     if ( error )
       goto Exit;
 
     /* analyze glyph outline */
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
     if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
-         AF_HINTS_DO_HORIZONTAL( hints ) )
+         AF_HINTS_DO_HORIZONTAL( hints )                          )
 #else
     if ( AF_HINTS_DO_HORIZONTAL( hints ) )
 #endif
     /* grid-fit the outline */
     for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
     {
-#ifdef AF_USE_WARPER
-      if ( ( dim == AF_DIMENSION_HORZ &&
-             metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+      if ( dim == AF_DIMENSION_HORZ                                 &&
+           metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT )
       {
         AF_WarperRec  warper;
         FT_Fixed      scale;
         FT_Pos        delta;
 
 
-        af_warper_compute( &warper, hints, dim, &scale, &delta );
-        af_glyph_hints_scale_dim( hints, dim, scale, delta );
+        af_warper_compute( &warper, hints, (AF_Dimension)dim,
+                           &scale, &delta );
+        af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+                                  scale, delta );
         continue;
       }
 #endif
   };
 
 
-  AF_DEFINE_SCRIPT_CLASS(af_latin_script_class,  
+  AF_DEFINE_SCRIPT_CLASS(af_latin_script_class,
     AF_SCRIPT_LATIN,
     af_latin_uniranges,