afhints.c.svn-base
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 1,265 行 · 第 1/3 页
SVN-BASE
1,265 行
{
start = before;
before = before->prev;
if ( before == first )
goto Skip;
out_x = start->fx - before->fx;
out_y = start->fy - before->fy;
} while ( out_x == 0 && out_y == 0 );
orient_prev = ft_corner_orientation( in_x, in_y, out_x, out_y );
} while ( orient_prev == 0 );
first = start;
in_x = out_x;
in_y = out_y;
/* 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;
out_x = after->fx - end->fx;
out_y = after->fy - end->fy;
} while ( out_x == 0 && out_y == 0 );
orient_cur = ft_corner_orientation( in_x, in_y, out_x, out_y );
} while ( orient_cur == 0 );
if ( ( orient_prev + orient_cur ) == 0 )
{
/* we have an inflection point here */
do
{
start->flags |= AF_FLAG_INFLECTION;
start = start->next;
} while ( start != end );
start->flags |= AF_FLAG_INFLECTION;
}
start = end;
end = after;
orient_prev = orient_cur;
in_x = out_x;
in_y = out_y;
} while ( !finished );
Skip:
;
}
}
FT_LOCAL_DEF( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory )
{
FT_ZERO( hints );
hints->memory = memory;
}
FT_LOCAL_DEF( void )
af_glyph_hints_done( AF_GlyphHints hints )
{
if ( hints && hints->memory )
{
FT_Memory memory = hints->memory;
int dim;
/*
* note that we don't need to free the segment and edge
* buffers, since they are really within the hints->points array
*/
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
AF_AxisHints axis = &hints->axis[dim];
axis->num_segments = 0;
axis->max_segments = 0;
FT_FREE( axis->segments );
axis->num_edges = 0;
axis->max_edges = 0;
FT_FREE( axis->edges );
}
FT_FREE( hints->contours );
hints->max_contours = 0;
hints->num_contours = 0;
FT_FREE( hints->points );
hints->num_points = 0;
hints->max_points = 0;
hints->memory = NULL;
}
}
FT_LOCAL_DEF( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics )
{
hints->metrics = metrics;
hints->scaler_flags = metrics->scaler.flags;
}
FT_LOCAL_DEF( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline,
FT_Bool get_inflections )
{
FT_Error error = AF_Err_Ok;
AF_Point points;
FT_UInt old_max, new_max;
FT_Fixed x_scale = hints->x_scale;
FT_Fixed y_scale = hints->y_scale;
FT_Pos x_delta = hints->x_delta;
FT_Pos y_delta = hints->y_delta;
FT_Memory memory = hints->memory;
hints->num_points = 0;
hints->num_contours = 0;
hints->axis[0].num_segments = 0;
hints->axis[0].num_edges = 0;
hints->axis[1].num_segments = 0;
hints->axis[1].num_edges = 0;
/* first of all, reallocate the contours array when necessary */
new_max = (FT_UInt)outline->n_contours;
old_max = hints->max_contours;
if ( new_max > old_max )
{
new_max = ( new_max + 3 ) & ~3;
if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
goto Exit;
hints->max_contours = new_max;
}
/*
* then reallocate the points arrays if necessary --
* note that we reserve two additional point positions, used to
* hint metrics appropriately
*/
new_max = (FT_UInt)( outline->n_points + 2 );
old_max = hints->max_points;
if ( new_max > old_max )
{
new_max = ( new_max + 2 + 7 ) & ~7;
if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
goto Exit;
hints->max_points = new_max;
}
hints->num_points = outline->n_points;
hints->num_contours = outline->n_contours;
/* We can't rely on the value of `FT_Outline.flags' to know the fill */
/* direction used for a glyph, given that some fonts are broken (e.g., */
/* the Arphic ones). We thus recompute it each time we need to. */
/* */
hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
{
hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
}
hints->x_scale = x_scale;
hints->y_scale = y_scale;
hints->x_delta = x_delta;
hints->y_delta = y_delta;
hints->xmin_delta = 0;
hints->xmax_delta = 0;
points = hints->points;
if ( hints->num_points == 0 )
goto Exit;
{
AF_Point point;
AF_Point point_limit = points + hints->num_points;
/* 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++ )
{
point->fx = (FT_Short)vec->x;
point->fy = (FT_Short)vec->y;
point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
switch ( FT_CURVE_TAG( *tag ) )
{
case FT_CURVE_TAG_CONIC:
point->flags = AF_FLAG_CONIC;
break;
case FT_CURVE_TAG_CUBIC:
point->flags = AF_FLAG_CUBIC;
break;
default:
point->flags = 0;
}
point->prev = prev;
prev->next = point;
prev = point;
if ( point == end )
{
if ( ++contour_index < outline->n_contours )
{
first = point + 1;
end = points + outline->contours[contour_index];
prev = end;
}
}
}
}
/* set-up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
short* end = outline->contours;
short idx = 0;
for ( ; contour < contour_limit; contour++, end++ )
{
contour[0] = points + idx;
idx = (short)( end[0] + 1 );
}
}
/* 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 next;
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;
}
point->in_dir = (FT_Char)in_dir;
next = point->next;
out_x = next->fx - point->fx;
out_y = next->fy - point->fy;
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 ) )
{
Is_Weak_Point:
point->flags |= AF_FLAG_WEAK_INTERPOLATION;
}
else if ( point->out_dir == point->in_dir )
{
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 if ( point->in_dir == -point->out_dir )
goto Is_Weak_Point;
in_x = out_x;
in_y = out_y;
prev = point;
}
}
}
/* compute inflection points -- */
/* disabled due to no longer perceived benefits */
if ( 0 && get_inflections )
af_glyph_hints_compute_inflections( hints );
Exit:
return error;
}
FT_LOCAL_DEF( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline )
{
AF_Point point = hints->points;
AF_Point limit = point + hints->num_points;
FT_Vector* vec = outline->points;
char* tag = outline->tags;
for ( ; point < limit; point++, vec++, tag++ )
{
vec->x = point->x;
vec->y = point->y;
if ( point->flags & AF_FLAG_CONIC )
tag[0] = FT_CURVE_TAG_CONIC;
else if ( point->flags & AF_FLAG_CUBIC )
tag[0] = FT_CURVE_TAG_CUBIC;
else
tag[0] = FT_CURVE_TAG_ON;
}
}
/****************************************************************
*
* EDGE POINT GRID-FITTING
*
****************************************************************/
FT_LOCAL_DEF( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_AxisHints axis = & hints->axis[dim];
AF_Segment segments = axis->segments;
AF_Segment segment_limit = segments + axis->num_segments;
AF_Segment seg;
if ( dim == AF_DIMENSION_HORZ )
{
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->x = edge->pos;
point->flags |= AF_FLAG_TOUCH_X;
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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?