summaryrefslogtreecommitdiffstats
path: root/src/autofit/afhints.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/autofit/afhints.c')
-rw-r--r--src/autofit/afhints.c241
1 files changed, 199 insertions, 42 deletions
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index c349709..f51066f 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -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,
@@ -125,7 +129,7 @@
}
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
@@ -160,6 +164,9 @@
#define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_points( AF_GlyphHints hints )
{
@@ -169,20 +176,20 @@
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 ) ? '<' : ' ',
@@ -192,6 +199,9 @@
}
printf( "\n" );
}
+#ifdef __cplusplus
+ }
+#endif
static const char*
@@ -222,7 +232,11 @@
}
- /* 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 )
{
@@ -240,11 +254,11 @@
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,
@@ -253,13 +267,84 @@
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 )
{
@@ -276,17 +361,17 @@
/*
* 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 ),
@@ -295,16 +380,23 @@
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 )
@@ -320,16 +412,49 @@
}
+ 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 )
@@ -369,6 +494,8 @@
}
}
+ /* 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;
@@ -397,7 +524,7 @@
/*
* 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++ )
{
@@ -408,8 +535,8 @@
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 );
}
@@ -426,6 +553,8 @@
}
+ /* Reset metrics. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics )
@@ -435,6 +564,9 @@
}
+ /* 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 )
@@ -457,12 +589,12 @@
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;
@@ -479,7 +611,7 @@
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;
@@ -545,7 +677,7 @@
point->flags = AF_FLAG_CUBIC;
break;
default:
- point->flags = 0;
+ point->flags = AF_FLAG_NONE;
}
point->prev = prev;
@@ -563,7 +695,7 @@
}
}
- /* set-up the contours array */
+ /* set up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
@@ -611,6 +743,8 @@
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:
@@ -639,6 +773,8 @@
}
+ /* Store the hinted outline in an FT_Outline structure. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline )
@@ -671,6 +807,9 @@
****************************************************************/
+ /* 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 )
@@ -704,7 +843,6 @@
break;
point = point->next;
-
}
}
}
@@ -744,8 +882,8 @@
****************************************************************/
- /* 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,
@@ -827,11 +965,12 @@
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;
@@ -863,6 +1002,7 @@
}
}
+ /* point is not on an edge */
{
AF_Edge before = edges + min - 1;
AF_Edge after = edges + min + 0;
@@ -898,6 +1038,10 @@
****************************************************************/
+ /* 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,
@@ -906,6 +1050,7 @@
AF_Point p;
FT_Pos delta = ref->u - ref->v;
+
if ( delta == 0 )
return;
@@ -917,6 +1062,13 @@
}
+ /* 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,
@@ -985,6 +1137,9 @@
}
+ /* 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 )
@@ -1050,17 +1205,18 @@
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 )
@@ -1080,9 +1236,8 @@
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 )
@@ -1112,7 +1267,9 @@
}
-#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,
@@ -1137,6 +1294,6 @@
}
}
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
/* END */