shithub: freetype+ttf2subf

Download patch

ref: b6370384aec60d4f1b3a7e4357b0537bcb7f6189
parent: b6420e84edeccc5c45078e92fd31aa9e5c8e8a1e
author: Werner Lemberg <[email protected]>
date: Wed May 19 05:22:26 EDT 2004

* src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases.
Reported by Mikey Anbary <[email protected]>.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2004-05-17  Werner Lemberg  <[email protected]>
+
+	* src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases. 
+	Reported by Mikey Anbary <[email protected]>.
+
 2004-05-15  Werner Lemberg  <[email protected]>
 
 	* src/sfnt/sfobjs.c (sfnt_done_face): Free face->postscript_name.
--- a/src/base/ftbbox.c
+++ b/src/base/ftbbox.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType bbox computation (body).                                    */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2001, 2002, 2004 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -48,7 +48,7 @@
   /*    This function is used as a `move_to' and `line_to' emitter during  */
   /*    FT_Outline_Decompose().  It simply records the destination point   */
   /*    in `user->last'; no further computations are necessary since we    */
-  /*    the cbox as the starting bbox which must be refined.               */
+  /*    use the cbox as the starting bbox which must be refined.           */
   /*                                                                       */
   /* <Input>                                                               */
   /*    to   :: A pointer to the destination vector.                       */
@@ -88,11 +88,14 @@
   /*                                                                       */
   /* <Input>                                                               */
   /*    y1  :: The start coordinate.                                       */
+  /*                                                                       */
   /*    y2  :: The coordinate of the control point.                        */
+  /*                                                                       */
   /*    y3  :: The end coordinate.                                         */
   /*                                                                       */
   /* <InOut>                                                               */
   /*    min :: The address of the current minimum.                         */
+  /*                                                                       */
   /*    max :: The address of the current maximum.                         */
   /*                                                                       */
   static void
@@ -102,19 +105,17 @@
                     FT_Pos*  min,
                     FT_Pos*  max )
   {
-    if ( y1 <= y3 )
+    if ( y1 <= y3 && y2 == y1 )     /* flat arc */
+      goto Suite;
+
+    if ( y1 < y3 )
     {
-      if ( y2 == y1 )               /* Flat arc */
+      if ( y2 >= y1 && y2 <= y3 )   /* ascending arc */
         goto Suite;
     }
-    else if ( y1 < y3 )
-    {
-      if ( y2 >= y1 && y2 <= y3 )   /* Ascending arc */
-        goto Suite;
-    }
     else
     {
-      if ( y2 >= y3 && y2 <= y1 )   /* Descending arc */
+      if ( y2 >= y3 && y2 <= y1 )   /* descending arc */
       {
         y2 = y1;
         y1 = y3;
@@ -144,6 +145,7 @@
   /*                                                                       */
   /* <Input>                                                               */
   /*    control :: A pointer to a control point.                           */
+  /*                                                                       */
   /*    to      :: A pointer to the destination vector.                    */
   /*                                                                       */
   /* <InOut>                                                               */
@@ -165,7 +167,6 @@
     /* within the bbox                                                    */
 
     if ( CHECK_X( control, user->bbox ) )
-
       BBox_Conic_Check( user->last.x,
                         control->x,
                         to->x,
@@ -173,7 +174,6 @@
                         &user->bbox.xMax );
 
     if ( CHECK_Y( control, user->bbox ) )
-
       BBox_Conic_Check( user->last.y,
                         control->y,
                         to->y,
@@ -194,19 +194,25 @@
   /* <Description>                                                         */
   /*    Finds the extrema of a 1-dimensional cubic Bezier curve and        */
   /*    updates a bounding range.  This version uses splitting because we  */
-  /*    don't want to use square roots and extra accuracies.               */
+  /*    don't want to use square roots and extra accuracy.                 */
   /*                                                                       */
   /* <Input>                                                               */
   /*    p1  :: The start coordinate.                                       */
+  /*                                                                       */
   /*    p2  :: The coordinate of the first control point.                  */
+  /*                                                                       */
   /*    p3  :: The coordinate of the second control point.                 */
+  /*                                                                       */
   /*    p4  :: The end coordinate.                                         */
   /*                                                                       */
   /* <InOut>                                                               */
   /*    min :: The address of the current minimum.                         */
+  /*                                                                       */
   /*    max :: The address of the current maximum.                         */
   /*                                                                       */
+
 #if 0
+
   static void
   BBox_Cubic_Check( FT_Pos   p1,
                     FT_Pos   p2,
@@ -235,17 +241,17 @@
 
       if ( y1 == y4 )
       {
-        if ( y1 == y2 && y1 == y3 )                         /* Flat */
+        if ( y1 == y2 && y1 == y3 )                         /* flat */
           goto Test;
       }
       else if ( y1 < y4 )
       {
-        if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* Ascending */
+        if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */
           goto Test;
       }
       else
       {
-        if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* Descending */
+        if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */
         {
           y2 = y1;
           y1 = y4;
@@ -254,7 +260,7 @@
         }
       }
 
-      /* Unknown direction -- split the arc in two */
+      /* unknown direction -- split the arc in two */
       arc[6] = y4;
       arc[1] = y1 = ( y1 + y2 ) / 2;
       arc[5] = y4 = ( y4 + y3 ) / 2;
@@ -275,6 +281,7 @@
       ;
     } while ( arc >= stack );
   }
+
 #else
 
   static void
@@ -296,17 +303,19 @@
     FT_UNUSED ( y4 );
 
 
-    /* The polynom is                       */
-    /*                                      */
-    /*   a*x^3 + 3b*x^2 + 3c*x + d      .   */
-    /*                                      */
-    /* However, we also have                */
-    /*                                      */
-    /*   dP/dx(u) = 0       ,               */
-    /*                                      */
-    /* which implies that                   */
-    /*                                      */
-    /*   P(u) = b*u^2 + 2c*u + d            */
+    /* The polynom is                         */
+    /*                                        */
+    /*    P(x) = a*x^3 + 3b*x^2 + 3c*x + d  , */
+    /*                                        */
+    /*   dP/dx = 3a*x^2 + 6b*x + 3c         . */
+    /*                                        */
+    /* However, we also have                  */
+    /*                                        */
+    /*   dP/dx(u) = 0                       , */
+    /*                                        */
+    /* which implies by subtraction that      */
+    /*                                        */
+    /*   P(u) = b*u^2 + 2c*u + d            . */
 
     if ( u > 0 && u < 0x10000L )
     {
@@ -357,72 +366,67 @@
       FT_Fixed  t;
 
 
-      /* We need to solve "ax^2+2bx+c" here, without floating points!      */
+      /* We need to solve `ax^2+2bx+c' here, without floating points!      */
       /* The trick is to normalize to a different representation in order  */
       /* to use our 16.16 fixed point routines.                            */
       /*                                                                   */
-      /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after the            */
-      /* the normalization.  These values must fit into a single 16.16     */
-      /* value.                                                            */
+      /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */
+      /* These values must fit into a single 16.16 value.                  */
       /*                                                                   */
-      /* We normalize a, b, and c to "8.16" fixed float values to ensure   */
-      /* that their product is held in a "16.16" value.                    */
-      /*                                                                   */
+      /* We normalize a, b, and c to `8.16' fixed float values to ensure   */
+      /* that its product is held in a `16.16' value.                      */
+
       {
         FT_ULong  t1, t2;
         int       shift = 0;
 
 
-        /* Technical explanation of what's happening there.            */
-        /*                                                             */
-        /*   The following computation is based on the fact that for   */
-        /*   any value "y", if "n" is the position of the most         */
-        /*   significant bit of "abs(y)" (starting from 0 for the      */
-        /*   least significant bit), then y is in the range            */
-        /*                                                             */
-        /*                  "-2^n..2^n-1"                              */
-        /*                                                             */
-        /*   We want to shift "a", "b" and "c" concurrently in order   */
-        /*   to ensure that they all fit in 8.16 values, which maps    */
-        /*   to the integer range "-2^23..2^23-1".                     */
-        /*                                                             */
-        /*   Necessarily, we need to shift "a", "b" and "c" so that    */
-        /*   the most significant bit of their absolute values is at   */
-        /*   _most_ at position 23.                                    */
-        /*                                                             */
-        /*   We begin by computing "t1" as the bitwise "or" of the     */
-        /*   absolute values of "a", "b", "c".                         */
-        /*                                                             */
-        t1  = (FT_ULong)((a >= 0) ? a : -a );
-        t2  = (FT_ULong)((b >= 0) ? b : -b );
+        /* The following computation is based on the fact that for   */
+        /* any value `y', if `n' is the position of the most         */
+        /* significant bit of `abs(y)' (starting from 0 for the      */
+        /* least significant bit), then `y' is in the range          */
+        /*                                                           */
+        /*   -2^n..2^n-1                                             */
+        /*                                                           */
+        /* We want to shift `a', `b', and `c' concurrently in order  */
+        /* to ensure that they all fit in 8.16 values, which maps    */
+        /* to the integer range `-2^23..2^23-1'.                     */
+        /*                                                           */
+        /* Necessarily, we need to shift `a', `b', and `c' so that   */
+        /* the most significant bit of its absolute values is at     */
+        /* _most_ at position 23.                                    */
+        /*                                                           */
+        /* We begin by computing `t1' as the bitwise `OR' of the     */
+        /* absolute values of `a', `b', `c'.                         */
+
+        t1  = (FT_ULong)( ( a >= 0 ) ? a : -a );
+        t2  = (FT_ULong)( ( b >= 0 ) ? b : -b );
         t1 |= t2;
-        t2  = (FT_ULong)((c >= 0) ? c : -c );
+        t2  = (FT_ULong)( ( c >= 0 ) ? c : -c );
         t1 |= t2;
 
-        /*   Now, the most significant bit of "t1" is sure to be the   */
-        /*   msb of one of "a", "b", "c", depending on which one is    */
-        /*   expressed in the greatest integer range.                  */
-        /*                                                             */
-        /*   We now compute the "shift", by shifting "t1" as many      */
-        /*   times as necessary to move its msb to position 23.        */
-        /*                                                             */
-        /*   This corresponds to a value of t1 that is in the range    */
-        /*   0x40_0000..0x7F_FFFF.                                     */
-        /*                                                             */
-        /*   Finally, we shift "a", "b" and "c" by the same amount.    */
-        /*   This ensures that all values are now in the range         */
-        /*   -2^23..2^23, i.e. that they are now expressed as 8.16     */
-        /*   fixed float numbers.                                      */
-        /*                                                             */
-        /*   This also means that we are using 24 bits of precision    */
-        /*   to compute the zeros, independently of the range of       */
-        /*   the original polynom coefficients.                        */
-        /*                                                             */
-        /*   This should ensure reasonably accurate values for the     */
-        /*   zeros.  Note that the latter are only expressed with      */
-        /*   16 bits when computing the extrema (the zeros need to     */
-        /*   be in 0..1 exclusive to be considered part of the arc).   */
-        /*                                                             */
+        /* Now we can be sure that the most significant bit of `t1'  */
+        /* is the most significant bit of either `a', `b', or `c',   */
+        /* depending on the greatest integer range of the particular */
+        /* variable.                                                 */
+        /*                                                           */
+        /* Next, we compute the `shift', by shifting `t1' as many    */
+        /* times as necessary to move its MSB to position 23.  This  */
+        /* corresponds to a value of `t1' that is in the range       */
+        /* 0x40_0000..0x7F_FFFF.                                     */
+        /*                                                           */
+        /* Finally, we shift `a', `b', and `c' by the same amount.   */
+        /* This ensures that all values are now in the range         */
+        /* -2^23..2^23, i.e., they are now expressed as 8.16         */
+        /* fixed-float numbers.  This also means that we are using   */
+        /* 24 bits of precision to compute the zeros, independently  */
+        /* of the range of the original polynomial coefficients.     */
+        /*                                                           */
+        /* This algorithm should ensure reasonably accurate values   */
+        /* for the zeros.  Note that they are only expressed with    */
+        /* 16 bits when computing the extrema (the zeros need to     */
+        /* be in 0..1 exclusive to be considered part of the arc).   */
+
         if ( t1 == 0 )  /* all coefficients are 0! */
           return;
 
@@ -432,10 +436,11 @@
           {
             shift++;
             t1 >>= 1;
+
           } while ( t1 > 0x7FFFFFUL );
 
-          /* losing some bits of precision, but we use 24 of them */
-          /* for the computation anyway.                          */
+          /* this loses some bits of precision, but we use 24 of them */
+          /* for the computation anyway                               */
           a >>= shift;
           b >>= shift;
           c >>= shift;
@@ -446,6 +451,7 @@
           {
             shift++;
             t1 <<= 1;
+
           } while ( t1 < 0x400000UL );
 
           a <<= shift;
@@ -478,7 +484,7 @@
         }
         else
         {
-          /* there are two solutions; we need to filter them though */
+          /* there are two solutions; we need to filter them */
           d = FT_SqrtFixed( (FT_Int32)d );
           t = - FT_DivFix( b - d, a );
           test_cubic_extrema( y1, y2, y3, y4, t, min, max );
@@ -506,7 +512,9 @@
   /*                                                                       */
   /* <Input>                                                               */
   /*    control1 :: A pointer to the first control point.                  */
+  /*                                                                       */
   /*    control2 :: A pointer to the second control point.                 */
+  /*                                                                       */
   /*    to       :: A pointer to the destination vector.                   */
   /*                                                                       */
   /* <InOut>                                                               */
@@ -517,7 +525,7 @@
   /*                                                                       */
   /* <Note>                                                                */
   /*    In the case of a non-monotonous arc, we don't compute directly     */
-  /*    extremum coordinates, we subdivise instead.                        */
+  /*    extremum coordinates, we subdivide instead.                        */
   /*                                                                       */
   static int
   BBox_Cubic_To( FT_Vector*  control1,
@@ -530,23 +538,21 @@
 
     if ( CHECK_X( control1, user->bbox ) ||
          CHECK_X( control2, user->bbox ) )
+      BBox_Cubic_Check( user->last.x,
+                        control1->x,
+                        control2->x,
+                        to->x,
+                        &user->bbox.xMin,
+                        &user->bbox.xMax );
 
-        BBox_Cubic_Check( user->last.x,
-                          control1->x,
-                          control2->x,
-                          to->x,
-                          &user->bbox.xMin,
-                          &user->bbox.xMax );
-
     if ( CHECK_Y( control1, user->bbox ) ||
          CHECK_Y( control2, user->bbox ) )
-
-        BBox_Cubic_Check( user->last.y,
-                          control1->y,
-                          control2->y,
-                          to->y,
-                          &user->bbox.yMin,
-                          &user->bbox.yMax );
+      BBox_Cubic_Check( user->last.y,
+                        control1->y,
+                        control2->y,
+                        to->y,
+                        &user->bbox.yMin,
+                        &user->bbox.yMax );
 
     user->last = *to;