forked from minhngoc25a/freetype2
[autofit] Add a lot of comments and do some minor formatting.
This commit is contained in:
parent
dd6c38fac7
commit
c5bda503b9
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue