[autofit] Add a lot of comments and do some minor formatting.

This commit is contained in:
Werner Lemberg 2011-02-16 21:59:44 +01:00
parent dd6c38fac7
commit c5bda503b9
2 changed files with 215 additions and 62 deletions

View 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,
@ -169,20 +173,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 | %-5.2f | %-5.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 ) ? '<' : ' ',
@ -222,7 +226,8 @@
}
/* A function to dump the array of linked segments. */
/* Dump the array of linked segments. */
void
af_glyph_hints_dump_segments( AF_GlyphHints hints )
{
@ -260,6 +265,8 @@
}
/* Dump the array of linked edges. */
void
af_glyph_hints_dump_edges( AF_GlyphHints hints )
{
@ -276,7 +283,7 @@
/*
* 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" );
@ -329,7 +336,8 @@
#endif /* !AF_DEBUG */
/* 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 +377,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 +407,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 +418,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 +436,8 @@
}
/* Reset metrics. */
FT_LOCAL_DEF( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics )
@ -435,6 +447,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 +472,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 +494,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 +560,7 @@
point->flags = AF_FLAG_CUBIC;
break;
default:
point->flags = 0;
point->flags = AF_FLAG_NONE;
}
point->prev = prev;
@ -563,7 +578,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 +626,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 +656,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 +690,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 +726,6 @@
break;
point = point->next;
}
}
}
@ -744,8 +765,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 +848,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 +885,7 @@
}
}
/* point is not on an edge */
{
AF_Edge before = edges + min - 1;
AF_Edge after = edges + min + 0;
@ -898,6 +921,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 +933,7 @@
AF_Point p;
FT_Pos delta = ref->u - ref->v;
if ( delta == 0 )
return;
@ -917,6 +945,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 +1020,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 +1088,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 +1119,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 )

View File

@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (specification). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
/* Copyright 2003-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -25,10 +25,10 @@
FT_BEGIN_HEADER
/*
* The definition of outline glyph hints. These are shared by all
* script analysis routines (until now).
*/
/*
* The definition of outline glyph hints. These are shared by all
* script analysis routines (until now).
*/
typedef enum AF_Dimension_
{
@ -55,6 +55,128 @@ FT_BEGIN_HEADER
} AF_Direction;
/*
* The following explanations are mostly taken from the article
*
* Real-Time Grid Fitting of Typographic Outlines
*
* by David Turner and Werner Lemberg
*
* http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
*
*
* Segments
*
* `af_{cjk,latin,...}_hints_compute_segments' are the functions to
* find segments in an outline. A segment is a series of consecutive
* points that are approximately aligned along a coordinate axis. The
* analysis to do so is specific to a script.
*
* A segment must have at least two points, except in the case of
* `fake' segments that are generated to hint metrics appropriately,
* and which consist of a single point.
*
*
* Edges
*
* As soon as segments are defined, the auto-hinter groups them into
* edges. An edge corresponds to a single position on the main
* dimension that collects one or more segments (allowing for a small
* threshold).
*
* The auto-hinter first tries to grid fit edges, then to align
* segments on the edges unless it detects that they form a serif.
*
* `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
* edges; they are specific to a script.
*
*
* Stems
*
* Segments need to be `linked' to other ones in order to detect stems.
* A stem is made of two segments that face each other in opposite
* directions and that are sufficiently close to each other. Using
* vocabulary from the TrueType specification, stem segments form a
* `black distance'.
*
* Each segment has at most one `best' candidate to form a black
* distance, or no candidate at all. Notice that two distinct segments
* can have the same candidate, which frequently means a serif.
*
* A stem is recognized by the following condition:
*
* best segment_1 = segment_2 && best segment_2 = segment_1
*
* The best candidate is stored in field `link' in structure
* `AF_Segment'.
*
* Stems are detected by `af_{cjk,latin,...}_hint_edges'.
*
*
* Serifs
*
* On the opposite, a serif has
*
* best segment_1 = segment_2 && best segment_2 != segment_1
*
* where segment_1 corresponds to the serif segment.
*
* The best candidate is stored in field `serif' in structure
* `AF_Segment' (and `link' is set to NULL).
*
* Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
*
*
* Touched points
*
* A point is called `touched' if it has been processed somehow by the
* auto-hinter. It basically means that it shouldn't be moved again
* (or moved only under certain constraints to preserve the already
* applied processing).
*
*
* Flat and round segments
*
* Segments are `round' or `flat', depending on the series of points
* that define them. A segment is round if the next and previous point
* of an extremum (which can be either a single point or sequence of
* points) are both conic or cubic control points. Otherwise, a
* segment with an extremum is flat.
*
*
* Strong Points
*
* Experience has shown that points which are not part of an edge need
* to be interpolated linearly between their two closest edges, even if
* these are not part of the contour of those particular points.
* Typical candidates for this are
*
* - angle points (i.e., points where the `in' and `out' direction
* differ greatly)
*
* - inflection points (i.e., where the `in' and `out' angles are the
* same, but the curvature changes sign)
*
* `af_glyph_hints_align_strong_points' is the function which takes
* care of such situations; it is equivalent to the TrueType `IP'
* hinting instruction.
*
*
* Weak Points
*
* Other points in the outline must be interpolated using the
* coordinates of their previous and next unfitted contour neighbours.
* These are called `weak points' and are touched by the function
* `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
* hinting instruction. Typical candidates are control points and
* points on the contour without a major direction.
*
* The major effect is to reduce possible distortion caused by
* alignment of edges and strong points, thus weak points are processed
* after strong points.
*/
/* point hint flags */
typedef enum AF_Flags_
{
@ -155,32 +277,31 @@ FT_BEGIN_HEADER
FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */
AF_Edge link;
AF_Edge serif;
FT_Short num_linked;
AF_Edge link; /* link edge */
AF_Edge serif; /* primary edge for serifs */
FT_Short num_linked; /* number of linked edges */
FT_Int score; /* used during stem matching */
FT_Int score;
AF_Segment first;
AF_Segment last;
AF_Segment first; /* first segment in edge */
AF_Segment last; /* last segment in edge */
} AF_EdgeRec;
typedef struct AF_AxisHintsRec_
{
FT_Int num_segments;
FT_Int max_segments;
AF_Segment segments;
FT_Int num_segments; /* number of used segments */
FT_Int max_segments; /* number of allocated segments */
AF_Segment segments; /* segments array */
#ifdef AF_SORT_SEGMENTS
FT_Int mid_segments;
#endif
FT_Int num_edges;
FT_Int max_edges;
AF_Edge edges;
FT_Int num_edges; /* number of used edges */
FT_Int max_edges; /* number of allocated edges */
AF_Edge edges; /* edges array */
AF_Direction major_dir;
AF_Direction major_dir; /* either vertical or horizontal */
} AF_AxisHintsRec, *AF_AxisHints;
@ -197,13 +318,13 @@ FT_BEGIN_HEADER
FT_Pos edge_distance_threshold;
FT_Int max_points;
FT_Int num_points;
AF_Point points;
FT_Int max_points; /* number of allocated points */
FT_Int num_points; /* number of used points */
AF_Point points; /* points array */
FT_Int max_contours;
FT_Int num_contours;
AF_Point* contours;
FT_Int max_contours; /* number of allocated contours */
FT_Int num_contours; /* number of used contours */
AF_Point* contours; /* contours array */
AF_AxisHintsRec axis[AF_DIMENSION_MAX];
@ -214,7 +335,7 @@ FT_BEGIN_HEADER
FT_Pos xmin_delta; /* used for warping */
FT_Pos xmax_delta;
} AF_GlyphHintsRec;
@ -274,12 +395,6 @@ FT_BEGIN_HEADER
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory );
/*
* recompute all AF_Point in a AF_GlyphHints from the definitions
* in a source outline
*/
FT_LOCAL( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics );