experimental changes for the Latin auto-hinter.

note that the new code is disabled by default.
This commit is contained in:
David Turner 2007-06-11 05:37:35 +00:00
parent cf7b764285
commit b792017faf
14 changed files with 2597 additions and 398 deletions

View File

@ -1,3 +1,9 @@
2007-06-11 David Turner <david@freetype.org>
* src/autofit/*: some very experimental changes to improve the Latin
auto-hinter. note that the new code is disabled by default since this
is not stablizied yet.
2007-06-11 Werner Lemberg <wl@gnu.org>
* docs/CHANGES: Document FT_Face_CheckTrueTypePatents.

View File

@ -14,9 +14,19 @@ SubDir FT2_TOP src autofit ;
{
local _sources ;
# define FT2_AUTOFIT2 do enable to experimental latin hinter replacement
if $(FT2_AUTOFIT2)
{
DEFINES += FT_OPTION_AUTOFIT2 ;
}
if $(FT2_MULTI)
{
_sources = afangles afglobal afhints aflatin afloader afmodule afdummy afwarp ;
if $(FT2_AUTOFIT2)
{
_sources += aflatin2 ;
}
}
else
{

View File

@ -427,7 +427,7 @@
/* insert a new edge in the list and */
/* sort according to the position */
error = af_axis_hints_new_edge( axis, seg->pos, memory, &edge );
error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
if ( error )
goto Exit;
@ -1361,7 +1361,7 @@
FT_UNUSED( metrics );
error = af_glyph_hints_reload( hints, outline );
error = af_glyph_hints_reload( hints, outline, 0 );
if ( error )
goto Exit;

View File

@ -22,11 +22,17 @@
#include "afcjk.h"
#include "aferrors.h"
#ifdef FT_OPTION_AUTOFIT2
#include "aflatin2.h"
#endif
/* populate this list when you add new scripts */
static AF_ScriptClass const af_script_classes[] =
{
&af_dummy_script_class,
#ifdef FT_OPTION_AUTOFIT2
&af_latin2_script_class,
#endif
&af_latin_script_class,
&af_cjk_script_class,
@ -217,11 +223,15 @@
FT_LOCAL_DEF( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
FT_UInt options,
AF_ScriptMetrics *ametrics )
{
AF_ScriptMetrics metrics = NULL;
FT_UInt gidx;
AF_ScriptClass clazz;
FT_UInt script = (options & 15);
const FT_UInt script_max = sizeof(af_script_classes)/
sizeof(af_script_classes[0]);
FT_Error error = AF_Err_Ok;
@ -231,8 +241,14 @@
goto Exit;
}
gidx = globals->glyph_scripts[gindex];
gidx = script;
if (gidx == 0 || gidx+1 >= script_max)
gidx = globals->glyph_scripts[gindex];
clazz = af_script_classes[gidx];
if (script == 0)
script = clazz->script;
metrics = globals->metrics[clazz->script];
if ( metrics == NULL )
{

View File

@ -50,6 +50,7 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
FT_UInt options,
AF_ScriptMetrics *ametrics );
FT_LOCAL( void )

View File

@ -54,9 +54,6 @@
}
segment = axis->segments + axis->num_segments++;
#if 0
FT_ZERO( segment );
#endif
Exit:
*asegment = segment;
@ -67,6 +64,7 @@
FT_LOCAL( FT_Error )
af_axis_hints_new_edge( AF_AxisHints axis,
FT_Int fpos,
AF_Direction dir,
FT_Memory memory,
AF_Edge *aedge )
{
@ -101,8 +99,17 @@
edges = axis->edges;
edge = edges + axis->num_edges;
while ( edge > edges && edge[-1].fpos > fpos )
while ( edge > edges )
{
if (edge[-1].fpos < fpos)
break;
/* we want the edge with same position and minor direction
* to appear before those in the major one in the list
*/
if (edge[-1].fpos == fpos && dir == axis->major_dir)
break;
edge[0] = edge[-1];
edge--;
}
@ -111,6 +118,7 @@
FT_ZERO( edge );
edge->fpos = (FT_Short)fpos;
edge->dir = (FT_Char)dir;
Exit:
*aedge = edge;
@ -187,6 +195,31 @@
}
static const char*
af_edge_flags_to_string( AF_Edge_Flags flags )
{
static char temp[32];
int pos = 0;
if ( flags & AF_EDGE_ROUND )
{
memcpy( temp+pos, "round", 5 );
pos += 5;
}
if ( flags & AF_EDGE_SERIF )
{
if (pos > 0)
temp[pos++] = ' ';
memcpy( temp+pos, "serif", 5 );
pos += 5;
}
if (pos == 0)
return "normal";
temp[pos] = 0;
return temp;
}
/* A function to dump the array of linked segments. */
void
af_glyph_hints_dump_segments( AF_GlyphHints hints )
@ -204,19 +237,20 @@
printf ( "Table of %s segments:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link | serif |"
" height | extra ]\n" );
printf ( " [ index | pos | dir | link | serif |"
" height | extra | flags ]\n" );
for ( seg = segments; seg < limit; seg++ )
{
printf ( " [ %5d | %4d | %5s | %4d | %5d | %5d | %5d ]\n",
printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
seg - segments,
(int)seg->pos,
dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox/64.0 : (int)seg->first->oy/64.0,
af_dir_str( (AF_Direction)seg->dir ),
AF_INDEX_NUM( seg->link, segments ),
AF_INDEX_NUM( seg->serif, segments ),
seg->height,
seg->height - ( seg->max_coord - seg->min_coord ) );
seg->height - ( seg->max_coord - seg->min_coord ),
af_edge_flags_to_string(seg->flags));
}
printf( "\n" );
}
@ -243,21 +277,22 @@
*/
printf ( "Table of %s edges:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link |"
" serif | blue | opos | pos ]\n" );
printf ( " [ index | pos | dir | link |"
" serif | blue | opos | pos | flags ]\n" );
for ( edge = edges; edge < limit; edge++ )
{
printf ( " [ %5d | %4d | %5s | %4d |"
" %5d | %c | %5.2f | %5.2f ]\n",
printf ( " [ %5d | %5.2g | %5s | %4d |"
" %5d | %c | %5.2f | %5.2f | %s ]\n",
edge - edges,
(int)edge->fpos,
(int)edge->opos/64.0,
af_dir_str( (AF_Direction)edge->dir ),
AF_INDEX_NUM( edge->link, edges ),
AF_INDEX_NUM( edge->serif, edges ),
edge->blue_edge ? 'y' : 'n',
edge->opos / 64.0,
edge->pos / 64.0 );
edge->pos / 64.0,
af_edge_flags_to_string(edge->flags) );
}
printf( "\n" );
}
@ -296,9 +331,6 @@
af_direction_compute( FT_Pos dx,
FT_Pos dy )
{
#if 1
FT_Pos ll, ss; /* long and short arm lengths */
AF_Direction dir; /* candidate direction */
@ -334,45 +366,16 @@
}
}
ss *= 12;
ss *= 14;
if ( FT_ABS(ll) <= FT_ABS(ss) )
dir = AF_DIR_NONE;
return dir;
#else /* 0 */
AF_Direction dir;
FT_Pos ax = FT_ABS( dx );
FT_Pos ay = FT_ABS( dy );
dir = AF_DIR_NONE;
/* atan(1/12) == 4.7 degrees */
/* test for vertical direction */
if ( ax * 12 < ay )
{
dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
}
/* test for horizontal direction */
else if ( ay * 12 < ax )
{
dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
}
return dir;
#endif /* 0 */
}
/* compute all inflex points in a given glyph */
#if 1
static void
af_glyph_hints_compute_inflections( AF_GlyphHints hints )
{
@ -484,117 +487,6 @@
}
}
#else /* old code */
static void
af_glyph_hints_compute_inflections( AF_GlyphHints hints )
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
/* do each contour separately */
for ( ; contour < contour_limit; contour++ )
{
AF_Point point = contour[0];
AF_Point first = point;
AF_Point start = point;
AF_Point end = point;
AF_Point before;
AF_Point after;
AF_Angle angle_in, angle_seg, angle_out;
AF_Angle diff_in, diff_out;
FT_Int finished = 0;
/* compute first segment in contour */
first = point;
start = end = first;
do
{
end = end->next;
if ( end == first )
goto Skip;
} while ( end->fx == first->fx && end->fy == first->fy );
angle_seg = af_angle_atan( end->fx - start->fx,
end->fy - start->fy );
/* extend the segment start whenever possible */
before = start;
do
{
do
{
start = before;
before = before->prev;
if ( before == first )
goto Skip;
} while ( before->fx == start->fx && before->fy == start->fy );
angle_in = af_angle_atan( start->fx - before->fx,
start->fy - before->fy );
} while ( angle_in == angle_seg );
first = start;
AF_ANGLE_DIFF( diff_in, angle_in, angle_seg );
/* now, process all segments in the contour */
do
{
/* first, extend current segment's end whenever possible */
after = end;
do
{
do
{
end = after;
after = after->next;
if ( after == first )
finished = 1;
} while ( end->fx == after->fx && end->fy == after->fy );
angle_out = af_angle_atan( after->fx - end->fx,
after->fy - end->fy );
} while ( angle_out == angle_seg );
AF_ANGLE_DIFF( diff_out, angle_seg, angle_out );
if ( ( diff_in ^ diff_out ) < 0 )
{
/* diff_in and diff_out have different signs, we have */
/* inflection points here... */
do
{
start->flags |= AF_FLAG_INFLECTION;
start = start->next;
} while ( start != end );
start->flags |= AF_FLAG_INFLECTION;
}
start = end;
end = after;
angle_seg = angle_out;
diff_in = diff_out;
} while ( !finished );
Skip:
;
}
}
#endif /* old code */
FT_LOCAL_DEF( void )
af_glyph_hints_init( AF_GlyphHints hints,
@ -656,7 +548,8 @@
FT_LOCAL_DEF( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline )
FT_Outline* outline,
FT_Bool get_inflections )
{
FT_Error error = AF_Err_Ok;
AF_Point points;
@ -739,11 +632,14 @@
AF_Point point_limit = points + hints->num_points;
/* compute coordinates & Bezier flags */
/* compute coordinates & Bezier flags, next and prev */
{
FT_Vector* vec = outline->points;
char* tag = outline->tags;
AF_Point first = points;
AF_Point end = points + outline->contours[0];
AF_Point prev = end;
FT_Int contour_index = 0;
for ( point = points; point < point_limit; point++, vec++, tag++ )
{
@ -763,39 +659,17 @@
default:
point->flags = 0;
}
}
}
/* compute `next' and `prev' */
{
FT_Int contour_index;
AF_Point prev;
AF_Point first;
AF_Point end;
contour_index = 0;
first = points;
end = points + outline->contours[0];
prev = end;
for ( point = points; point < point_limit; point++ )
{
point->prev = prev;
if ( point < end )
prev->next = point;
prev = point;
if (point == end)
{
point->next = point + 1;
prev = point;
}
else
{
point->next = first;
contour_index++;
if ( point + 1 < point_limit )
if ( ++contour_index < outline->n_contours )
{
end = points + outline->contours[contour_index];
first = point + 1;
end = points + outline->contours[contour_index];
prev = end;
}
}
@ -819,24 +693,34 @@
/* compute directions of in & out vectors */
{
AF_Point first = points;
AF_Point prev = NULL;
FT_Pos in_x = 0;
FT_Pos in_y = 0;
AF_Direction in_dir = AF_DIR_NONE;
for ( point = points; point < point_limit; point++ )
{
AF_Point prev;
AF_Point next;
FT_Pos in_x, in_y, out_x, out_y;
FT_Pos out_x, out_y;
if ( point == first )
{
prev = first->prev;
in_x = first->fx - prev->fx;
in_y = first->fy - prev->fy;
in_dir = af_direction_compute( in_x, in_y );
first = prev + 1;
}
prev = point->prev;
in_x = point->fx - prev->fx;
in_y = point->fy - prev->fy;
point->in_dir = (FT_Char)af_direction_compute( in_x, in_y );
point->in_dir = (FT_Char) in_dir;
next = point->next;
out_x = next->fx - point->fx;
out_y = next->fy - point->fy;
point->out_dir = (FT_Char)af_direction_compute( out_x, out_y );
in_dir = af_direction_compute( out_x, out_y );
point->out_dir = (FT_Char) in_dir;
if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
{
@ -845,42 +729,25 @@
}
else if ( point->out_dir == point->in_dir )
{
#if 1
if ( point->out_dir != AF_DIR_NONE )
goto Is_Weak_Point;
if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
goto Is_Weak_Point;
#else /* old code */
AF_Angle angle_in, angle_out, delta;
if ( point->out_dir != AF_DIR_NONE )
goto Is_Weak_Point;
angle_in = af_angle_atan( in_x, in_y );
angle_out = af_angle_atan( out_x, out_y );
AF_ANGLE_DIFF( delta, angle_in, angle_out );
if ( delta < 2 && delta > -2 )
goto Is_Weak_Point;
#endif /* old code */
}
else if ( point->in_dir == -point->out_dir )
goto Is_Weak_Point;
in_x = out_x;
in_y = out_y;
prev = point;
}
}
}
/* compute inflection points */
af_glyph_hints_compute_inflections( hints );
/* compute inflection points -- disable due to no longer perceived benefits */
if (0 && get_inflections)
af_glyph_hints_compute_inflections( hints );
Exit:
return error;
@ -923,46 +790,64 @@
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_AxisHints axis = & hints->axis[dim];
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
AF_Edge edge;
AF_AxisHints axis = & hints->axis[dim];
AF_Segment segments = axis->segments;
AF_Segment segment_limit = segments + axis->num_segments;
AF_Segment seg;
for ( edge = edges; edge < edge_limit; edge++ )
if ( dim == AF_DIMENSION_HORZ )
{
/* move the points of each segment */
/* in each edge to the edge's position */
AF_Segment seg = edge->first;
do
for ( seg = segments; seg < segment_limit; seg++ )
{
AF_Point point = seg->first;
AF_Edge edge = seg->edge;
AF_Point point, first, last;
if ( edge == NULL )
continue;
first = seg->first;
last = seg->last;
point = first;
for (;;)
{
if ( dim == AF_DIMENSION_HORZ )
{
point->x = edge->pos;
point->flags |= AF_FLAG_TOUCH_X;
}
else
{
point->y = edge->pos;
point->flags |= AF_FLAG_TOUCH_Y;
}
point->x = edge->pos;
point->flags |= AF_FLAG_TOUCH_X;
if ( point == seg->last )
if ( point == last )
break;
point = point->next;
}
}
}
else
{
for ( seg = segments; seg < segment_limit; seg++ )
{
AF_Edge edge = seg->edge;
AF_Point point, first, last;
if ( edge == NULL )
continue;
first = seg->first;
last = seg->last;
point = first;
for (;;)
{
point->y = edge->pos;
point->flags |= AF_FLAG_TOUCH_Y;
if ( point == last )
break;
point = point->next;
}
seg = seg->edge_next;
} while ( seg != edge->first );
}
}
}
@ -1056,6 +941,25 @@
min = 0;
max = edge_limit - edges;
#if 1
/* for small edge counts, a linear search is better */
if ( max <= 8 )
{
FT_UInt nn;
for ( nn = 0; nn < max; nn++ )
if ( edges[nn].fpos >= u )
break;
if ( edges[nn].fpos == u )
{
u = edges[nn].pos;
goto Store_Point;
}
min = nn;
}
else
#endif
while ( min < max )
{
mid = ( max + min ) >> 1;
@ -1117,6 +1021,8 @@
AF_Point p;
FT_Pos delta = ref->u - ref->v;
if (delta == 0)
return;
for ( p = p1; p < ref; p++ )
p->u = p->v + delta;
@ -1235,53 +1141,74 @@
for ( ; contour < contour_limit; contour++ )
{
AF_Point first_touched, last_touched;
point = *contour;
end_point = point->prev;
first_point = point;
while ( point <= end_point && !( point->flags & touch_flag ) )
point++;
if ( point <= end_point )
/* find first touched point */
for (;;)
{
AF_Point first_touched = point;
AF_Point cur_touched = point;
if ( point > end_point ) /* no touched point in contour */
goto NextContour;
if ( point->flags & touch_flag )
break;
point++;
while ( point <= end_point )
}
first_touched = point;
last_touched = point;
for (;;)
{
FT_ASSERT( point <= end_point && (point->flags & touch_flag) != 0 );
/* skip any touched neighbhours */
while ( point < end_point && (point[1].flags & touch_flag) != 0 )
point++;
last_touched = point;
/* find the next touched point, if any */
point ++;
for (;;)
{
if ( point->flags & touch_flag )
{
/* we found two successive touched points; we interpolate */
/* all contour points between them */
af_iup_interp( cur_touched + 1, point - 1,
cur_touched, point );
cur_touched = point;
}
if ( point > end_point )
goto EndContour;
if ( (point->flags & touch_flag) != 0 )
break;
point++;
}
if ( cur_touched == first_touched )
{
/* this is a special case: only one point was touched in the */
/* contour; we thus simply shift the whole contour */
af_iup_shift( first_point, end_point, cur_touched );
}
else
{
/* now interpolate after the last touched point to the end */
/* of the contour */
af_iup_interp( cur_touched + 1, end_point,
cur_touched, first_touched );
/* if the first contour point isn't touched, interpolate */
/* from the contour start to the first touched point */
if ( first_touched > points )
af_iup_interp( first_point, first_touched - 1,
cur_touched, first_touched );
}
/* interpolate between last_touched and point */
af_iup_interp( last_touched + 1, point - 1,
last_touched, 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 )
af_iup_interp( last_touched + 1, end_point,
last_touched, first_touched );
if ( first_touched > points )
af_iup_interp( first_point, first_touched - 1,
last_touched, first_touched );
}
NextContour:
;
}
/* now save the interpolated values back to x/y */

View File

@ -21,6 +21,7 @@
#include "aftypes.h"
#define xxAF_SORT_SEGMENTS
FT_BEGIN_HEADER
@ -171,6 +172,9 @@ FT_BEGIN_HEADER
FT_Int num_segments;
FT_Int max_segments;
AF_Segment segments;
#ifdef AF_SORT_SEGMENTS
FT_Int mid_segments;
#endif
FT_Int num_edges;
FT_Int max_edges;
@ -262,6 +266,7 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error)
af_axis_hints_new_edge( AF_AxisHints axis,
FT_Int fpos,
AF_Direction dir,
FT_Memory memory,
AF_Edge *edge );
@ -281,7 +286,8 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline );
FT_Outline* outline,
FT_Bool get_inflections );
FT_LOCAL( void )
af_glyph_hints_save( AF_GlyphHints hints,

View File

@ -74,7 +74,7 @@
af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
error = af_glyph_hints_reload( hints, &face->glyph->outline );
error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 );
if ( error )
goto Exit;
@ -488,12 +488,15 @@
if ( scaled != fitted )
{
#if 0
if ( dim == AF_DIMENSION_HORZ )
{
if ( fitted < scaled )
scale -= scale / 50; /* scale *= 0.98 */
}
else
#endif
if ( dim == AF_DIMENSION_VERT )
{
scale = FT_MulDiv( scale, fitted, scaled );
}
@ -612,13 +615,6 @@
AF_Point* contour_limit = contour + hints->num_contours;
AF_Direction major_dir, segment_dir;
#ifdef AF_HINT_METRICS
AF_Point min_point = 0;
AF_Point max_point = 0;
FT_Pos min_coord = 32000;
FT_Pos max_coord = -32000;
#endif
FT_ZERO( &seg0 );
seg0.score = 32000;
@ -666,19 +662,6 @@
FT_Bool passed;
#ifdef AF_HINT_METRICS
if ( point->u < min_coord )
{
min_coord = point->u;
min_point = point;
}
if ( point->u > max_coord )
{
max_coord = point->u;
max_point = point;
}
#endif
if ( point == last ) /* skip singletons -- just in case */
continue;
@ -774,14 +757,6 @@
segment->last = point;
segment->contour = contour;
on_edge = 1;
#ifdef AF_HINT_METRICS
if ( point == max_point )
max_point = 0;
if ( point == min_point )
min_point = 0;
#endif
}
point = point->next;
@ -841,77 +816,6 @@
}
}
#ifdef AF_HINT_METRICS
/* we need to ensure that there are edges on the left-most and */
/* right-most points of the glyph in order to hint the metrics; */
/* we do this by inserting fake segments when needed */
if ( dim == AF_DIMENSION_HORZ )
{
AF_Point point = hints->points;
AF_Point point_limit = point + hints->num_points;
FT_Pos min_pos = 32000;
FT_Pos max_pos = -32000;
min_point = 0;
max_point = 0;
/* compute minimum and maximum points */
for ( ; point < point_limit; point++ )
{
FT_Pos x = point->fx;
if ( x < min_pos )
{
min_pos = x;
min_point = point;
}
if ( x > max_pos )
{
max_pos = x;
max_point = point;
}
}
/* insert minimum segment */
if ( min_point )
{
/* clear all segment fields */
error = af_axis_hints_new_segment( axis, memory, &segment );
if ( error )
goto Exit;
segment[0] = seg0;
segment->dir = segment_dir;
segment->first = min_point;
segment->last = min_point;
segment->pos = min_pos;
segment = NULL;
}
/* insert maximum segment */
if ( max_point )
{
/* clear all segment fields */
error = af_axis_hints_new_segment( axis, memory, &segment );
if ( error )
goto Exit;
segment[0] = seg0;
segment->dir = segment_dir;
segment->first = max_point;
segment->last = max_point;
segment->pos = max_pos;
segment = NULL;
}
}
#endif /* AF_HINT_METRICS */
Exit:
return error;
}
@ -1090,7 +994,7 @@
if ( dist < 0 )
dist = -dist;
if ( dist < edge_distance_threshold )
if ( dist < edge_distance_threshold && edge->dir == seg->dir )
{
found = edge;
break;
@ -1104,7 +1008,7 @@
/* insert a new edge in the list and */
/* sort according to the position */
error = af_axis_hints_new_edge( axis, seg->pos, memory, &edge );
error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
if ( error )
goto Exit;
@ -1114,6 +1018,7 @@
edge->first = seg;
edge->last = seg;
edge->fpos = seg->pos;
edge->dir = seg->dir;
edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
seg->edge_next = seg;
}
@ -1254,6 +1159,7 @@
if ( is_round > 0 && is_round >= is_straight )
edge->flags |= AF_EDGE_ROUND;
#if 0
/* set the edge's main direction */
edge->dir = AF_DIR_NONE;
@ -1265,6 +1171,7 @@
else if ( ups == downs )
edge->dir = 0; /* both up and down! */
#endif
/* gets rid of serifs if link is set */
/* XXX: This gets rid of many unpleasant artefacts! */
@ -2097,16 +2004,21 @@
if ( before >= edges && before < edge &&
after < edge_limit && after > edge )
{
edge->pos = before->pos +
FT_MulDiv( edge->opos - before->opos,
after->pos - before->pos,
after->opos - before->opos );
AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) from %d (opos=%.2f)\n",
edge-edges, edge->opos / 64.0, edge->pos / 64.0, before - edges, before->opos / 64.0 ));
}
else
edge->pos = anchor->pos +
FT_PIX_ROUND( edge->opos - anchor->opos );
{
edge->pos = anchor->pos + (( edge->opos - anchor->opos + 16) & ~31);
AF_LOG(( "SERIF_LINK: edge %d (opos=%.2f) snapped to (%.2f)\n",
edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
}
edge->flags |= AF_EDGE_DONE;
@ -2132,7 +2044,7 @@
int dim;
error = af_glyph_hints_reload( hints, outline );
error = af_glyph_hints_reload( hints, outline, 1 );
if ( error )
goto Exit;

2270
src/autofit/aflatin2.c Normal file

File diff suppressed because it is too large Load Diff

40
src/autofit/aflatin2.h Normal file
View File

@ -0,0 +1,40 @@
/***************************************************************************/
/* */
/* aflatin2.h */
/* */
/* Auto-fitter hinting routines for latin script (specification). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef __AFLATIN2_H__
#define __AFLATIN2_H__
#include "afhints.h"
FT_BEGIN_HEADER
/* the latin-specific script class */
FT_CALLBACK_TABLE const AF_ScriptClassRec
af_latin2_script_class;
/* */
FT_END_HEADER
#endif /* __AFLATIN_H__ */
/* END */

View File

@ -390,12 +390,12 @@
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
FT_Vector_Transform( &vvector, &loader->trans_matrix );
}
#if 1
/* we must translate our final outline by -pp1.x and compute */
/* the new metrics */
if ( loader->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
#endif
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
@ -492,10 +492,16 @@
if ( !error )
{
AF_ScriptMetrics metrics;
FT_UInt options = 0;
#ifdef FT_OPTION_AUTOFIT2
/* XXX: undocumented hook to activate the latin2 hinter */
if (load_flags & (1UL << 20))
options = 2;
#endif
error = af_face_globals_get_metrics( loader->globals, gindex,
&metrics );
options, &metrics );
if ( !error )
{
loader->metrics = metrics;

View File

@ -265,6 +265,9 @@ extern void* _af_debug_hints;
AF_SCRIPT_NONE = 0,
AF_SCRIPT_LATIN = 1,
AF_SCRIPT_CJK = 2,
#ifdef FT_OPTION_AUTOFIT2
AF_SCRIPT_LATIN2,
#endif
/* add new scripts here. Don't forget to update the list in */
/* `afglobal.c'. */

View File

@ -23,6 +23,9 @@
#include "afhints.c"
#include "afdummy.c"
#include "aflatin.c"
#ifdef FT_OPTION_AUTOFIT2
#include "aflatin2.c"
#endif
#include "afcjk.c"
#include "afloader.c"
#include "afmodule.c"

View File

@ -743,7 +743,6 @@
}
else /* general case */
{
#ifdef FT_LONG64
FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;