experimental changes for the Latin auto-hinter.
note that the new code is disabled by default.
This commit is contained in:
parent
cf7b764285
commit
b792017faf
@ -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.
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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 )
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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
2270
src/autofit/aflatin2.c
Normal file
File diff suppressed because it is too large
Load Diff
40
src/autofit/aflatin2.h
Normal file
40
src/autofit/aflatin2.h
Normal 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 */
|
@ -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;
|
||||
|
@ -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'. */
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user