Commit 07e7b8affeef35383fdef09ebe817b568f71249a

Werner Lemberg 2014-05-11T08:00:25

[autofit] Fix crash with font `CabinSketch-Bold.ttf'. Problem reported by Ralf S. Engelschall <rse@engelschall.com>. * src/autofit/afhints.c (af_glyph_hints_reload): Fix threshold for finding first non-near point. Properly initialize non-near point deltas.

diff --git a/ChangeLog b/ChangeLog
index 6584062..eb6e161 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-05-11  Werner Lemberg  <wl@gnu.org>
+
+	[autofit] Fix crash with font `CabinSketch-Bold.ttf'.
+
+	Problem reported by Ralf S. Engelschall <rse@engelschall.com>.
+
+	* src/autofit/afhints.c (af_glyph_hints_reload): Fix threshold for
+	finding first non-near point.
+	Properly initialize non-near point deltas.
+
 2014-05-01  Werner Lemberg  <wl@gnu.org>
 
 	[autofit] Add blue-zone support for Devanagari.
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index 905662b..75a3452 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -713,6 +713,7 @@
         /* value 20 in `near_limit' is heuristic */
         FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
         FT_Int   near_limit   = 20 * units_per_em / 2048;
+        FT_Int   near_limit2  = 2 * near_limit - 1;
 
         AF_Point*  contour;
         AF_Point*  contour_limit = hints->contours + hints->num_contours;
@@ -740,8 +741,15 @@
             out_x = point->fx - prev->fx;
             out_y = point->fy - prev->fy;
 
-            /* we use Taxicab metrics to measure the vector length */
-            if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit )
+            /*
+             *  We use Taxicab metrics to measure the vector length.
+             *
+             *  Note that the accumulated distances so far could have the
+             *  opposite direction of the distance measured here.  For this
+             *  reason we use `near_limit2' for the comparison to get a
+             *  non-near point even in the worst case.
+             */
+            if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 )
               break;
 
             point = prev;
@@ -755,6 +763,18 @@
           /* `in' and `out' vector directions               */
 
           curr  = first;
+
+          /*
+           *  We abuse the `u' and `v' fields to store index deltas to the
+           *  next and previous non-near point, respectively.
+           *
+           *  To avoid problems with not having non-near points, we point to
+           *  `first' by default as the next non-near point.
+           *
+           */
+          curr->u  = (FT_Pos)( first - curr );
+          first->v = -curr->u;
+
           out_x = 0;
           out_y = 0;
 
@@ -780,8 +800,6 @@
               continue;
             }
 
-            /* we abuse the `u' and `v' fields to store index deltas */
-            /* to the next and previous non-near point, respectively */
             curr->u = (FT_Pos)( next - curr );
             next->v = -curr->u;
 
@@ -797,6 +815,9 @@
             }
             next->in_dir = (FT_Char)out_dir;
 
+            curr->u  = (FT_Pos)( first - curr );
+            first->v = -curr->u;
+
             out_x = 0;
             out_y = 0;
           }