Upload tizen 2.0 beta source
[framework/graphics/freetype.git] / src / autofit / afhints.c
index c349709..f51066f 100644 (file)
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (body).                                 */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 by                  */
+/*  Copyright 2003-2007, 2009-2011 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,6 +21,8 @@
 #include FT_INTERNAL_CALC_H
 
 
+  /* Get new segment for given axis. */
+
   FT_LOCAL_DEF( FT_Error )
   af_axis_hints_new_segment( AF_AxisHints  axis,
                              FT_Memory     memory,
@@ -61,6 +63,8 @@
   }
 
 
+  /* Get new edge for given axis, direction, and position. */
+
   FT_LOCAL( FT_Error )
   af_axis_hints_new_edge( AF_AxisHints  axis,
                           FT_Int        fpos,
   }
 
 
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
 
 #include FT_CONFIG_STANDARD_LIBRARY_H
 
 #define AF_INDEX_NUM( ptr, base )  ( (ptr) ? ( (ptr) - (base) ) : -1 )
 
 
+#ifdef __cplusplus
+  extern "C" {
+#endif
   void
   af_glyph_hints_dump_points( AF_GlyphHints  hints )
   {
 
 
     printf( "Table of points:\n" );
-    printf(   "  [ index |  xorg |  yorg |  xscale |  yscale "
-              "|  xfit  |  yfit  |  flags ]\n" );
+    printf(   "  [ index |  xorg |  yorg | xscale | yscale"
+              " |  xfit |  yfit |  flags ]\n" );
 
     for ( point = points; point < limit; point++ )
     {
-      printf( "  [ %5d | %5d | %5d | %-5.2f | %-5.2f "
-              "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
+      printf( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
+              " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
               point - points,
               point->fx,
               point->fy,
-              point->ox/64.0,
-              point->oy/64.0,
-              point->x/64.0,
-              point->y/64.0,
+              point->ox / 64.0,
+              point->oy / 64.0,
+              point->x / 64.0,
+              point->y / 64.0,
               ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
               ( point->flags & AF_FLAG_INFLECTION )         ? 'i' : ' ',
               ( point->flags & AF_FLAG_EXTREMA_X )          ? '<' : ' ',
     }
     printf( "\n" );
   }
+#ifdef __cplusplus
+  }
+#endif
 
 
   static const char*
   }
 
 
-  /* A function to dump the array of linked segments. */
+  /* Dump the array of linked segments. */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
   void
   af_glyph_hints_dump_segments( AF_GlyphHints  hints )
   {
       printf ( "Table of %s segments:\n",
                dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
       printf ( "  [ index |  pos  |  dir  | link | serif |"
-               " height  | extra | flags    ]\n" );
+               " height | extra |    flags    ]\n" );
 
       for ( seg = segments; seg < limit; seg++ )
       {
-        printf ( "  [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
+        printf ( "  [ %5d | %5.2g | %5s | %4d | %5d | %6d | %5d | %11s ]\n",
                  seg - segments,
                  dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
                                                 : (int)seg->first->oy / 64.0,
                  AF_INDEX_NUM( seg->serif, segments ),
                  seg->height,
                  seg->height - ( seg->max_coord - seg->min_coord ),
-                 af_edge_flags_to_string( seg->flags ) );
+                 af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) );
       }
       printf( "\n" );
     }
   }
+#ifdef __cplusplus
+  }
+#endif
+
+
+  /* Fetch number of segments. */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+  FT_Error
+  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
+                                   FT_Int         dimension,
+                                   FT_Int*        num_segments )
+  {
+    AF_Dimension  dim;
+    AF_AxisHints  axis;
+
+
+    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+    axis          = &hints->axis[dim];
+    *num_segments = axis->num_segments;
+
+    return AF_Err_Ok;
+  }
+#ifdef __cplusplus
+  }
+#endif
+
+
+  /* Fetch offset of segments into user supplied offset array. */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+  FT_Error
+  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
+                                     FT_Int         dimension,
+                                     FT_Int         idx,
+                                     FT_Pos*        offset )
+  {
+    AF_Dimension  dim;
+    AF_AxisHints  axis;
+    AF_Segment    seg;
+
+
+    if ( !offset )
+      return AF_Err_Invalid_Argument;
+
+    dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+    axis = &hints->axis[dim];
+
+    if ( idx < 0 || idx >= axis->num_segments )
+      return AF_Err_Invalid_Argument;
+
+    seg     = &axis->segments[idx];
+    *offset = (dim == AF_DIMENSION_HORZ) ? seg->first->ox
+                                         : seg->first->oy;
+
+    return AF_Err_Ok;
+  }
+#ifdef __cplusplus
+  }
+#endif
+
 
+  /* Dump the array of linked edges. */
 
+#ifdef __cplusplus
+  extern "C" {
+#endif
   void
   af_glyph_hints_dump_edges( AF_GlyphHints  hints )
   {
 
       /*
        *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
-       *        since they have constant a X coordinate.
+       *        since they have a constant X coordinate.
        */
       printf ( "Table of %s edges:\n",
                dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
       printf ( "  [ index |  pos  |  dir  | link |"
-               " serif | blue | opos  |  pos  | flags   ]\n" );
+               " serif | blue | opos  |  pos  |    flags    ]\n" );
 
       for ( edge = edges; edge < limit; edge++ )
       {
         printf ( "  [ %5d | %5.2g | %5s | %4d |"
-                 " %5d |   %c  | %5.2f | %5.2f | %s ]\n",
+                 " %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
                  edge - edges,
                  (int)edge->opos / 64.0,
                  af_dir_str( (AF_Direction)edge->dir ),
                  edge->blue_edge ? 'y' : 'n',
                  edge->opos / 64.0,
                  edge->pos / 64.0,
-                 af_edge_flags_to_string( edge->flags ) );
+                 af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) );
       }
       printf( "\n" );
     }
   }
+#ifdef __cplusplus
+  }
+#endif
 
-#else /* !AF_DEBUG */
+#else /* !FT_DEBUG_AUTOFIT */
 
   /* these empty stubs are only used to link the `ftgrid' test program */
-  /* when debugging is disabled                                        */
+  /* if debugging is disabled                                          */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
 
   void
   af_glyph_hints_dump_points( AF_GlyphHints  hints )
   }
 
 
+  FT_Error
+  af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
+                                   FT_Int         dimension,
+                                   FT_Int*        num_segments )
+  {
+    FT_UNUSED( hints );
+    FT_UNUSED( dimension );
+    FT_UNUSED( num_segments );
+
+    return 0;
+  }
+
+
+  FT_Error
+  af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
+                                     FT_Int         dimension,
+                                     FT_Int         idx,
+                                     FT_Pos*        offset )
+  {
+    FT_UNUSED( hints );
+    FT_UNUSED( dimension );
+    FT_UNUSED( idx );
+    FT_UNUSED( offset );
+
+    return 0;
+  }
+
+
   void
   af_glyph_hints_dump_edges( AF_GlyphHints  hints )
   {
     FT_UNUSED( hints );
   }
 
-#endif /* !AF_DEBUG */
+#ifdef __cplusplus
+  }
+#endif
 
+#endif /* !FT_DEBUG_AUTOFIT */
+
+
+  /* Compute the direction value of a given vector. */
 
-  /* compute the direction value of a given vector */
   FT_LOCAL_DEF( AF_Direction )
   af_direction_compute( FT_Pos  dx,
                         FT_Pos  dy )
       }
     }
 
+    /* return no direction if arm lengths differ too much */
+    /* (value 14 is heuristic)                            */
     ss *= 14;
     if ( FT_ABS( ll ) <= FT_ABS( ss ) )
       dir = AF_DIR_NONE;
 
       /*
        *  note that we don't need to free the segment and edge
-       *  buffers, since they are really within the hints->points array
+       *  buffers since they are really within the hints->points array
        */
       for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
       {
         axis->max_segments = 0;
         FT_FREE( axis->segments );
 
-        axis->num_edges    = 0;
-        axis->max_edges    = 0;
+        axis->num_edges = 0;
+        axis->max_edges = 0;
         FT_FREE( axis->edges );
       }
 
   }
 
 
+  /* Reset metrics. */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_rescale( AF_GlyphHints     hints,
                           AF_ScriptMetrics  metrics )
   }
 
 
+  /* Recompute all AF_Point in AF_GlyphHints from the definitions */
+  /* in a source outline.                                         */
+
   FT_LOCAL_DEF( FT_Error )
   af_glyph_hints_reload( AF_GlyphHints  hints,
                          FT_Outline*    outline )
     hints->axis[1].num_segments = 0;
     hints->axis[1].num_edges    = 0;
 
-    /* first of all, reallocate the contours array when necessary */
+    /* first of all, reallocate the contours array if necessary */
     new_max = (FT_UInt)outline->n_contours;
     old_max = hints->max_contours;
     if ( new_max > old_max )
     {
-      new_max = ( new_max + 3 ) & ~3;
+      new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
 
       if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
         goto Exit;
     old_max = hints->max_points;
     if ( new_max > old_max )
     {
-      new_max = ( new_max + 2 + 7 ) & ~7;
+      new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
 
       if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
         goto Exit;
             point->flags = AF_FLAG_CUBIC;
             break;
           default:
-            point->flags = 0;
+            point->flags = AF_FLAG_NONE;
           }
 
           point->prev = prev;
         }
       }
 
-      /* set-up the contours array */
+      /* set up the contours array */
       {
         AF_Point*  contour       = hints->contours;
         AF_Point*  contour_limit = contour + hints->num_contours;
           in_dir         = af_direction_compute( out_x, out_y );
           point->out_dir = (FT_Char)in_dir;
 
+          /* check for weak points */
+
           if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
           {
           Is_Weak_Point:
   }
 
 
+  /* Store the hinted outline in an FT_Outline structure. */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_save( AF_GlyphHints  hints,
                        FT_Outline*    outline )
    ****************************************************************/
 
 
+  /* Align all points of an edge to the same coordinate value, */
+  /* either horizontally or vertically.                        */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
                                     AF_Dimension   dim )
             break;
 
           point = point->next;
-
         }
       }
     }
    ****************************************************************/
 
 
-  /* hint the strong points -- this is equivalent to the TrueType `IP' */
-  /* hinting instruction                                               */
+  /* Hint the strong points -- this is equivalent to the TrueType `IP' */
+  /* hinting instruction.                                              */
 
   FT_LOCAL_DEF( void )
   af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
           max = edge_limit - edges;
 
 #if 1
-          /* for small edge counts, a linear search is better */
+          /* for a small number of edges, a linear search is better */
           if ( max <= 8 )
           {
             FT_PtrDist  nn;
 
+
             for ( nn = 0; nn < max; nn++ )
               if ( edges[nn].fpos >= u )
                 break;
             }
           }
 
+          /* point is not on an edge */
           {
             AF_Edge  before = edges + min - 1;
             AF_Edge  after  = edges + min + 0;
    ****************************************************************/
 
 
+  /* Shift the original coordinates of all points between `p1' and */
+  /* `p2' to get hinted coordinates, using the same difference as  */
+  /* given by `ref'.                                               */
+
   static void
   af_iup_shift( AF_Point  p1,
                 AF_Point  p2,
     AF_Point  p;
     FT_Pos    delta = ref->u - ref->v;
 
+
     if ( delta == 0 )
       return;
 
   }
 
 
+  /* Interpolate the original coordinates of all points between `p1' and  */
+  /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the       */
+  /* reference points.  The `u' and `v' members are the current and       */
+  /* original coordinate values, respectively.                            */
+  /*                                                                      */
+  /* Details can be found in the TrueType bytecode specification.         */
+
   static void
   af_iup_interp( AF_Point  p1,
                  AF_Point  p2,
   }
 
 
+  /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
+  /* hinting instruction.                                             */
+
   FT_LOCAL_DEF( void )
   af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
                                     AF_Dimension   dim )
 
       for (;;)
       {
-        FT_ASSERT( point <= end_point &&
+        FT_ASSERT( point <= end_point                 &&
                    ( point->flags & touch_flag ) != 0 );
 
-        /* skip any touched neighbhours */
-        while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
+        /* skip any touched neighbours */
+        while ( point < end_point                    &&
+                ( point[1].flags & touch_flag ) != 0 )
           point++;
 
         last_touched = point;
 
         /* find the next touched point, if any */
-        point ++;
+        point++;
         for (;;)
         {
           if ( point > end_point )
     EndContour:
       /* special case: only one point was touched */
       if ( last_touched == first_touched )
-      {
         af_iup_shift( first_point, end_point, first_touched );
-      }
+
       else /* interpolate the last part */
       {
         if ( last_touched < end_point )
   }
 
 
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+  /* Apply (small) warp scale and warp delta for given dimension. */
 
   FT_LOCAL_DEF( void )
   af_glyph_hints_scale_dim( AF_GlyphHints  hints,
     }
   }
 
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
 
 /* END */