freetype-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Devel] FT_Outline_Get_Orientation is very broken


From: Anders Kaseorg
Subject: Re: [Devel] FT_Outline_Get_Orientation is very broken
Date: Tue, 23 Nov 2004 23:12:32 -0500
User-agent: Mozilla Thunderbird 0.9+ (X11/20041123)

Werner LEMBERG wrote:
The functions are coded very differently.  I don't know whether it is
worth the effort to unify them, but you are invited to contribute code
if it actually makes sense :-)

Okay. This patch replaces all of these functions with one that's much simpler, faster, and more likely to be correct. I tested that FT_Outline_Get_Orientation now works correctly on PostScript and Truetype fonts, including some with incorrect reversed glyphs, and that it does what was expected by the code that had used ah_get_orientation (and presumably ft_get_orientation, since that was almost identical).

Anders
Index: include/freetype/config/ftoption.h
===================================================================
RCS file: /cvs/freetype/freetype2/include/freetype/config/ftoption.h,v
retrieving revision 1.88
diff -u -r1.88 ftoption.h
--- ftoption.h  2004/11/17 08:19:26     1.88
+++ ftoption.h  2004/11/24 04:09:16
@@ -436,7 +436,7 @@
   /*   Do not #undef this macro here, since the build system might         */
   /*   define it for certain configurations only.                          */
   /*                                                                       */
-#define  TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+/* #define  TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
 
   /*************************************************************************/
Index: src/autohint/ahglyph.c
===================================================================
RCS file: /cvs/freetype/freetype2/src/autohint/ahglyph.c,v
retrieving revision 1.59
diff -u -r1.59 ahglyph.c
--- ahglyph.c   2004/03/27 08:43:17     1.59
+++ ahglyph.c   2004/11/24 04:09:16
@@ -21,6 +21,7 @@
 
 
 #include <ft2build.h>
+#include FT_OUTLINE_H
 #include "ahglyph.h"
 #include "ahangles.h"
 #include "ahglobal.h"
@@ -164,144 +165,6 @@
   }
 
 
-  /* this function is used by ah_get_orientation (see below) to test */
-  /* the fill direction of given bbox extremum                       */
-  static FT_Int
-  ah_test_extremum( FT_Outline*  outline,
-                    FT_Int       n )
-  {
-    FT_Vector  *prev, *cur, *next;
-    FT_Pos      product;
-    FT_Int      first, last, c;
-    FT_Int      retval;
-
-
-    /* we need to compute the `previous' and `next' point */
-    /* for this extremum; we check whether the extremum   */
-    /* is start or end of a contour and providing         */
-    /* appropriate values if so                           */
-    cur  = outline->points + n;
-    prev = cur - 1;
-    next = cur + 1;
-
-    first = 0;
-    for ( c = 0; c < outline->n_contours; c++ )
-    {
-      last = outline->contours[c];
-
-      if ( n == first )
-        prev = outline->points + last;
-
-      if ( n == last )
-        next = outline->points + first;
-
-      first = last + 1;
-    }
-
-    /* compute the vectorial product -- since we know that the angle */
-    /* is <= 180 degrees (otherwise it wouldn't be an extremum) we   */
-    /* can determine the filling orientation if the product is       */
-    /* either positive or negative                                   */
-    product = FT_MulDiv( cur->x  - prev->x,  /* in.x  */
-                         next->y - cur->y,   /* out.y */
-                         0x40 )
-              -
-              FT_MulDiv( cur->y  - prev->y,  /* in.y  */
-                         next->x - cur->x,   /* out.x */
-                         0x40 );
-
-    retval = 0;
-    if ( product )
-      retval = product > 0 ? 2 : 1;
-
-    return retval;
-  }
-
-
-  /* Compute the orientation of path filling.  It differs between TrueType */
-  /* and Type1 formats.  We could use the `FT_OUTLINE_REVERSE_FILL' flag,  */
-  /* but it is better to re-compute it directly (it seems that this flag   */
-  /* isn't correctly set for some weird composite glyphs currently).       */
-  /*                                                                       */
-  /* We do this by computing bounding box points, and computing their      */
-  /* curvature.                                                            */
-  /*                                                                       */
-  /* The function returns either 1 or 2.                                   */
-  /*                                                                       */
-  static FT_Int
-  ah_get_orientation( FT_Outline*  outline )
-  {
-    FT_BBox  box;
-    FT_Int   indices_xMin, indices_yMin, indices_xMax, indices_yMax;
-    FT_Int   n, last;
-
-
-    indices_xMin = -1;
-    indices_yMin = -1;
-    indices_xMax = -1;
-    indices_yMax = -1;
-
-    box.xMin = box.yMin =  32767L;
-    box.xMax = box.yMax = -32768L;
-
-    /* is it empty? */
-    if ( outline->n_contours < 1 )
-      return 1;
-
-    last = outline->contours[outline->n_contours - 1];
-
-    for ( n = 0; n <= last; n++ )
-    {
-      FT_Pos  x, y;
-
-
-      x = outline->points[n].x;
-      if ( x < box.xMin )
-      {
-        box.xMin     = x;
-        indices_xMin = n;
-      }
-      if ( x > box.xMax )
-      {
-        box.xMax     = x;
-        indices_xMax = n;
-      }
-
-      y = outline->points[n].y;
-      if ( y < box.yMin )
-      {
-        box.yMin     = y;
-        indices_yMin = n;
-      }
-      if ( y > box.yMax )
-      {
-        box.yMax     = y;
-        indices_yMax = n;
-      }
-    }
-
-    /* test orientation of the extrema */
-    n = ah_test_extremum( outline, indices_xMin );
-    if ( n )
-      goto Exit;
-
-    n = ah_test_extremum( outline, indices_yMin );
-    if ( n )
-      goto Exit;
-
-    n = ah_test_extremum( outline, indices_xMax );
-    if ( n )
-      goto Exit;
-
-    n = ah_test_extremum( outline, indices_yMax );
-    if ( !n )
-      n = 1;
-
-  Exit:
-    return n;
-  }
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -465,7 +328,7 @@
     outline->vert_major_dir = AH_DIR_UP;
     outline->horz_major_dir = AH_DIR_LEFT;
 
-    if ( ah_get_orientation( source ) > 1 )
+    if ( FT_Outline_Get_Orientation( source ) == FT_ORIENTATION_POSTSCRIPT )
     {
       outline->vert_major_dir = AH_DIR_DOWN;
       outline->horz_major_dir = AH_DIR_RIGHT;
Index: src/base/ftoutln.c
===================================================================
RCS file: /cvs/freetype/freetype2/src/base/ftoutln.c,v
retrieving revision 1.57
diff -u -r1.57 ftoutln.c
--- ftoutln.c   2004/01/22 09:07:10     1.57
+++ ftoutln.c   2004/11/24 04:09:16
@@ -653,142 +653,60 @@
   }
 
 
-  typedef struct  FT_OrientationExtremumRec_
-  {
-    FT_Int   index;
-    FT_Long  pos;
-    FT_Int   first;
-    FT_Int   last;
-
-  } FT_OrientationExtremumRec;
-
-
-  static FT_Orientation
-  ft_orientation_extremum_compute( FT_OrientationExtremumRec*  extremum,
-                                   FT_Outline*                 outline )
-  {
-    FT_Vector  *point, *first, *last, *prev, *next;
-    FT_Vector*  points = outline->points;
-    FT_Angle    angle_in, angle_out;
-
+  /* documentation is in ftoutln.h */
 
-    /* compute the previous and next points in the same contour */
-    point = points + extremum->index;
-    first = points + extremum->first;
-    last  = points + extremum->last;
-
-    prev = point;
-    next = point;
-
-    do
-    {
-      prev = ( prev == first ) ? last : prev - 1;
-      if ( prev == point )
-        return FT_ORIENTATION_TRUETYPE;  /* degenerate case */
-
-    } while ( prev->x != point->x || prev->y != point->y );
-
-    do
-    {
-      next = ( next == last ) ? first : next + 1;
-      if ( next == point )
-        return FT_ORIENTATION_TRUETYPE;  /* shouldn't happen */
-
-    } while ( next->x != point->x || next->y != point->y );
-
-    /* now compute the orientation of the `out' vector relative */
-    /* to the `in' vector.                                      */
-    angle_in  = FT_Atan2( point->x - prev->x,  point->y - prev->y );
-    angle_out = FT_Atan2( next->x  - point->x, next->y  - point->y );
-
-    return ( FT_Angle_Diff( angle_in, angle_out ) >= 0 )
-             ? FT_ORIENTATION_TRUETYPE
-             : FT_ORIENTATION_POSTSCRIPT;
-  }
-
-
   FT_EXPORT_DEF( FT_Orientation )
   FT_Outline_Get_Orientation( FT_Outline*  outline )
   {
-    FT_Orientation  result = FT_ORIENTATION_TRUETYPE;
-
-
-    if ( outline && outline->n_points > 0 )
+    FT_Pos     xmin = +32768L;
+    FT_Vector* xmin_point = NULL;
+    FT_Vector* xmin_first = NULL;
+    FT_Vector* xmin_last = NULL;
+    short*     contour;
+    FT_Vector* first;
+    FT_Vector* last;
+    FT_Vector* prev;
+    FT_Vector* next;
+
+    if ( !outline || outline->n_points <= 0 )
+      return FT_ORIENTATION_TRUETYPE;
+
+    first = outline->points;
+    for ( contour = outline->contours;
+         contour < outline->contours + outline->n_contours;
+         contour++, first = last + 1 )
     {
-      FT_OrientationExtremumRec  xmin, ymin, xmax, ymax;
-      FT_Int                     n;
-      FT_Int                     first, last;
-      FT_Vector*                 points = outline->points;
-
+      FT_Vector* point;
 
-      xmin.pos = ymin.pos = +32768L;
-      xmax.pos = ymax.pos = -32768L;
+      last = outline->points + *contour;
 
-      xmin.index = ymin.index = xmax.index = ymax.index = -1;
+      /* skip degenerate contours */
+      if ( last < first + 2 )
+       continue;
 
-      first = 0;
-      for ( n = 0; n < outline->n_contours; n++, first = last + 1 )
+      for ( point = first; point <= last; point++ )
       {
-        last = outline->contours[n];
-
-        /* skip single-point contours; these are degenerated cases */
-        if ( last > first + 1 )
-        {
-          FT_Int  i;
-
-
-          for ( i = first; i < last; i++ )
-          {
-            FT_Pos  x = points[i].x;
-            FT_Pos  y = points[i].y;
-
-
-            if ( x < xmin.pos )
-            {
-              xmin.pos   = x;
-              xmin.index = i;
-              xmin.first = first;
-              xmin.last  = last;
-            }
-            if ( x > xmax.pos )
-            {
-              xmax.pos   = x;
-              xmax.index = i;
-              xmax.first = first;
-              xmax.last  = last;
-            }
-            if ( y < ymin.pos )
-            {
-              ymin.pos   = y;
-              ymin.index = i;
-              ymin.first = first;
-              ymin.last  = last;
-            }
-            if ( y > ymax.pos )
-            {
-              ymax.pos   = y;
-              ymax.index = i;
-              ymax.first = first;
-              ymax.last  = last;
-            }
-          }
-        }
-
-        if ( xmin.index >= 0 )
-          result = ft_orientation_extremum_compute( &xmin, outline );
-
-        else if ( xmax.index >= 0 )
-          result = ft_orientation_extremum_compute( &xmax, outline );
-
-        else if ( ymin.index >= 0 )
-          result = ft_orientation_extremum_compute( &ymin, outline );
-
-        else if ( ymax.index >= 0 )
-          result = ft_orientation_extremum_compute( &ymax, outline );
+       if ( point->x < xmin )
+       {
+         xmin       = point->x;
+         xmin_point = point;
+         xmin_first = first;
+         xmin_last  = last;
+       }
       }
     }
+
+    if ( !xmin_point )
+      return FT_ORIENTATION_TRUETYPE;
+
+    prev = ( xmin_point == xmin_first ) ? xmin_last : xmin_point - 1;
+    next = ( xmin_point == xmin_last ) ? xmin_first : xmin_point + 1;
 
-    return result;
+    if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
+        FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
+      return FT_ORIENTATION_POSTSCRIPT;
+    else
+      return FT_ORIENTATION_TRUETYPE;
   }
 
 
Index: src/base/ftsynth.c
===================================================================
RCS file: /cvs/freetype/freetype2/src/base/ftsynth.c,v
retrieving revision 1.20
diff -u -r1.20 ftsynth.c
--- ftsynth.c   2003/12/24 13:37:58     1.20
+++ ftsynth.c   2004/11/24 04:09:16
@@ -71,134 +71,6 @@
 
 
 
-  static int
-  ft_test_extrema( FT_Outline*  outline,
-                   int          n )
-  {
-    FT_Vector  *prev, *cur, *next;
-    FT_Pos      product;
-    FT_Int      c, first, last;
-
-
-    /* we need to compute the `previous' and `next' point */
-    /* for these extrema.                                 */
-    cur  = outline->points + n;
-    prev = cur - 1;
-    next = cur + 1;
-
-    first = 0;
-    for ( c = 0; c < outline->n_contours; c++ )
-    {
-      last = outline->contours[c];
-
-      if ( n == first )
-        prev = outline->points + last;
-
-      if ( n == last )
-        next = outline->points + first;
-
-      first = last + 1;
-    }
-
-    product = FT_MulDiv( cur->x - prev->x,   /* in.x  */
-                         next->y - cur->y,   /* out.y */
-                         0x40 )
-              -
-              FT_MulDiv( cur->y - prev->y,   /* in.y  */
-                         next->x - cur->x,   /* out.x */
-                         0x40 );
-
-    if ( product )
-      product = product > 0 ? 1 : -1;
-
-    return product;
-  }
-
-
-  /* Compute the orientation of path filling.  It differs between TrueType */
-  /* and Type1 formats.  We could use the `FT_OUTLINE_REVERSE_FILL' flag,  */
-  /* but it is better to re-compute it directly (it seems that this flag   */
-  /* isn't correctly set for some weird composite glyphs currently).       */
-  /*                                                                       */
-  /* We do this by computing bounding box points, and computing their      */
-  /* curvature.                                                            */
-  /*                                                                       */
-  /* The function returns either 1 or -1.                                  */
-  /*                                                                       */
-  static int
-  ft_get_orientation( FT_Outline*  outline )
-  {
-    FT_BBox  box;
-    FT_BBox  indices;
-    int      n, last;
-
-
-    indices.xMin = -1;
-    indices.yMin = -1;
-    indices.xMax = -1;
-    indices.yMax = -1;
-
-    box.xMin = box.yMin =  32767;
-    box.xMax = box.yMax = -32768;
-
-    /* is it empty ? */
-    if ( outline->n_contours < 1 )
-      return 1;
-
-    last = outline->contours[outline->n_contours - 1];
-
-    for ( n = 0; n <= last; n++ )
-    {
-      FT_Pos  x, y;
-
-
-      x = outline->points[n].x;
-      if ( x < box.xMin )
-      {
-        box.xMin     = x;
-        indices.xMin = n;
-      }
-      if ( x > box.xMax )
-      {
-        box.xMax     = x;
-        indices.xMax = n;
-      }
-
-      y = outline->points[n].y;
-      if ( y < box.yMin )
-      {
-        box.yMin     = y;
-        indices.yMin = n;
-      }
-      if ( y > box.yMax )
-      {
-        box.yMax     = y;
-        indices.yMax = n;
-      }
-    }
-
-    /* test orientation of the xmin */
-    n = ft_test_extrema( outline, indices.xMin );
-    if ( n )
-      goto Exit;
-
-    n = ft_test_extrema( outline, indices.yMin );
-    if ( n )
-      goto Exit;
-
-    n = ft_test_extrema( outline, indices.xMax );
-    if ( n )
-      goto Exit;
-
-    n = ft_test_extrema( outline, indices.yMax );
-    if ( !n )
-      n = 1;
-
-  Exit:
-    return n;
-  }
-
-
   FT_EXPORT_DEF( void )
   FT_GlyphSlot_Embolden( FT_GlyphSlot  slot )
   {
@@ -208,7 +80,7 @@
     FT_Outline*  outline = &slot->outline;
     FT_Face      face = FT_SLOT_FACE( slot );
     FT_Angle     rotate, angle_in, angle_out;
-    FT_Int       c, n, first, orientation;
+    FT_Int       c, n, first;
 
 
     /* only embolden outline glyph images */
@@ -219,8 +91,10 @@
     distance = FT_MulFix( face->units_per_EM / 60,
                           face->size->metrics.y_scale );
 
-    orientation = ft_get_orientation( outline );
-    rotate      = FT_ANGLE_PI2*orientation;
+    if (FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_TRUETYPE)
+       rotate = -FT_ANGLE_PI2;
+    else
+       rotate = FT_ANGLE_PI2;
 
     points = outline->points;
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]