|
|
|
@ -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 ) |
|
|
|
|