Commit 5b995a8dd849a309038103fc1c96c3040a04f81b

Werner Lemberg 2012-08-05T11:11:44

[autofit] Improve recognition of flat segments. Problem reported by Brad Dunzer <BDunzer@extensis.com>. * src/autofit/aflatin.c (af_latin_metrics_init_blues): We have a flat segment if the horizontal distance of best on-points is larger than a given threshold.

diff --git a/ChangeLog b/ChangeLog
index 1ee6c86..1d48e19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2012-08-05  Werner Lemberg  <wl@gnu.org>
 
+	[autofit] Improve recognition of flat segments.
+
+	Problem reported by Brad Dunzer <BDunzer@extensis.com>.
+
+	* src/autofit/aflatin.c (af_latin_metrics_init_blues): We have
+	a flat segment if the horizontal distance of best on-points is
+	larger than a given threshold.
+
+2012-08-05  Werner Lemberg  <wl@gnu.org>
+
 	[autofit] Variable renamings.
 
 	* src/autofit/aflatin.c (af_latin_metrics_init_blues): Replace
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index d7ea4a6..eb7bfed 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -302,11 +302,23 @@
         {
           FT_Pos  best_x = points[best_point].x;
           FT_Int  prev, next;
+          FT_Int best_on_point_first, best_on_point_last;
           FT_Pos  dist;
 
 
-          /* now look for the previous and next points that are not on the */
-          /* same Y coordinate.  Threshold the `closeness'...              */
+          if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON )
+          {
+            best_on_point_first = best_point;
+            best_on_point_last  = best_point;
+          }
+          else
+          {
+            best_on_point_first = -1;
+            best_on_point_last  = -1;
+          }
+
+          /* look for the previous and next points that are not on the */
+          /* same Y coordinate, then threshold the `closeness'...      */
           prev = best_point;
           next = prev;
 
@@ -324,6 +336,13 @@
               if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
                 break;
 
+            if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
+            {
+              best_on_point_first = prev;
+              if ( best_on_point_last < 0 )
+                best_on_point_last = prev;
+            }
+
           } while ( prev != best_point );
 
           do
@@ -338,12 +357,27 @@
               if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
                 break;
 
+            if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON )
+            {
+              best_on_point_last = next;
+              if ( best_on_point_first < 0 )
+                best_on_point_first = next;
+            }
+
           } while ( next != best_point );
 
           /* now set the `round' flag depending on the segment's kind */
-          round = FT_BOOL(
-            FT_CURVE_TAG( outline.tags[prev] ) != FT_CURVE_TAG_ON ||
-            FT_CURVE_TAG( outline.tags[next] ) != FT_CURVE_TAG_ON );
+          /* (value 8 is heuristic)                                   */
+          if ( best_on_point_first >= 0                               &&
+               best_on_point_last >= 0                                &&
+               (FT_UInt)( FT_ABS( points[best_on_point_last].x -
+                                  points[best_on_point_first].x ) ) >
+                 metrics->units_per_em / 8                            )
+            round = 0;
+          else
+            round = FT_BOOL(
+              FT_CURVE_TAG( outline.tags[prev] ) != FT_CURVE_TAG_ON ||
+              FT_CURVE_TAG( outline.tags[next] ) != FT_CURVE_TAG_ON );
 
           FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
         }