📄 aflatin.c
字号:
else if ( edge2 && edge2->blue_edge )
{
blue = edge2->blue_edge;
edge1 = edge2;
edge2 = edge;
}
if ( !edge1 )
continue;
AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
"was (%.2f)\n",
edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
edge1->pos / 64.0 ));
edge1->pos = blue->fit;
edge1->flags |= AF_EDGE_DONE;
if ( edge2 && !edge2->blue_edge )
{
af_latin_align_linked_edge( hints, dim, edge1, edge2 );
edge2->flags |= AF_EDGE_DONE;
}
if ( !anchor )
anchor = edge;
}
}
/* now we will align all stem edges, trying to maintain the */
/* relative order of stems in the glyph */
for ( edge = edges; edge < edge_limit; edge++ )
{
AF_Edge edge2;
if ( edge->flags & AF_EDGE_DONE )
continue;
/* skip all non-stem edges */
edge2 = edge->link;
if ( !edge2 )
{
has_serifs++;
continue;
}
/* now align the stem */
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge )
{
AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
af_latin_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
continue;
}
if ( !anchor )
{
FT_Pos org_len, org_center, cur_len;
FT_Pos cur_pos1, error1, error2, u_off, d_off;
org_len = edge2->opos - edge->opos;
cur_len = af_latin_compute_stem_width(
hints, dim, org_len,
(AF_Edge_Flags)edge->flags,
(AF_Edge_Flags)edge2->flags );
if ( cur_len <= 64 )
u_off = d_off = 32;
else
{
u_off = 38;
d_off = 26;
}
if ( cur_len < 96 )
{
org_center = edge->opos + ( org_len >> 1 );
cur_pos1 = FT_PIX_ROUND( org_center );
error1 = org_center - ( cur_pos1 - u_off );
if ( error1 < 0 )
error1 = -error1;
error2 = org_center - ( cur_pos1 + d_off );
if ( error2 < 0 )
error2 = -error2;
if ( error1 < error2 )
cur_pos1 -= u_off;
else
cur_pos1 += d_off;
edge->pos = cur_pos1 - cur_len / 2;
edge2->pos = edge->pos + cur_len;
}
else
edge->pos = FT_PIX_ROUND( edge->opos );
AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
"snapped to (%.2f) (%.2f)\n",
edge-edges, edge->opos / 64.0,
edge2-edges, edge2->opos / 64.0,
edge->pos / 64.0, edge2->pos / 64.0 ));
anchor = edge;
edge->flags |= AF_EDGE_DONE;
af_latin_align_linked_edge( hints, dim, edge, edge2 );
}
else
{
FT_Pos org_pos, org_len, org_center, cur_len;
FT_Pos cur_pos1, cur_pos2, delta1, delta2;
org_pos = anchor->pos + ( edge->opos - anchor->opos );
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
cur_len = af_latin_compute_stem_width(
hints, dim, org_len,
(AF_Edge_Flags)edge->flags,
(AF_Edge_Flags)edge2->flags );
if ( edge2->flags & AF_EDGE_DONE )
edge->pos = edge2->pos - cur_len;
else if ( cur_len < 96 )
{
FT_Pos u_off, d_off;
cur_pos1 = FT_PIX_ROUND( org_center );
if (cur_len <= 64 )
u_off = d_off = 32;
else
{
u_off = 38;
d_off = 26;
}
delta1 = org_center - ( cur_pos1 - u_off );
if ( delta1 < 0 )
delta1 = -delta1;
delta2 = org_center - ( cur_pos1 + d_off );
if ( delta2 < 0 )
delta2 = -delta2;
if ( delta1 < delta2 )
cur_pos1 -= u_off;
else
cur_pos1 += d_off;
edge->pos = cur_pos1 - cur_len / 2;
edge2->pos = cur_pos1 + cur_len / 2;
AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
"snapped to (%.2f) and (%.2f)\n",
edge-edges, edge->opos / 64.0,
edge2-edges, edge2->opos / 64.0,
edge->pos / 64.0, edge2->pos / 64.0 ));
}
else
{
org_pos = anchor->pos + ( edge->opos - anchor->opos );
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
cur_len = af_latin_compute_stem_width(
hints, dim, org_len,
(AF_Edge_Flags)edge->flags,
(AF_Edge_Flags)edge2->flags );
cur_pos1 = FT_PIX_ROUND( org_pos );
delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;
if ( delta1 < 0 )
delta1 = -delta1;
cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center;
if ( delta2 < 0 )
delta2 = -delta2;
edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
edge2->pos = edge->pos + cur_len;
AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
"snapped to (%.2f) and (%.2f)\n",
edge-edges, edge->opos / 64.0,
edge2-edges, edge2->opos / 64.0,
edge->pos / 64.0, edge2->pos / 64.0 ));
}
edge->flags |= AF_EDGE_DONE;
edge2->flags |= AF_EDGE_DONE;
if ( edge > edges && edge->pos < edge[-1].pos )
{
AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
edge->pos = edge[-1].pos;
}
}
}
/* make sure that lowercase m's maintain their symmetry */
/* In general, lowercase m's have six vertical edges if they are sans */
/* serif, or twelve if they are with serifs. This implementation is */
/* based on that assumption, and seems to work very well with most */
/* faces. However, if for a certain face this assumption is not */
/* true, the m is just rendered like before. In addition, any stem */
/* correction will only be applied to symmetrical glyphs (even if the */
/* glyph is not an m), so the potential for unwanted distortion is */
/* relatively low. */
/* We don't handle horizontal edges since we can't easily assure that */
/* the third (lowest) stem aligns with the base line; it might end up */
/* one pixel higher or lower. */
n_edges = edge_limit - edges;
if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
{
AF_Edge edge1, edge2, edge3;
FT_Pos dist1, dist2, span, delta;
if ( n_edges == 6 )
{
edge1 = edges;
edge2 = edges + 2;
edge3 = edges + 4;
}
else
{
edge1 = edges + 1;
edge2 = edges + 5;
edge3 = edges + 9;
}
dist1 = edge2->opos - edge1->opos;
dist2 = edge3->opos - edge2->opos;
span = dist1 - dist2;
if ( span < 0 )
span = -span;
if ( span < 8 )
{
delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
edge3->pos -= delta;
if ( edge3->link )
edge3->link->pos -= delta;
/* move the serifs along with the stem */
if ( n_edges == 12 )
{
( edges + 8 )->pos -= delta;
( edges + 11 )->pos -= delta;
}
edge3->flags |= AF_EDGE_DONE;
if ( edge3->link )
edge3->link->flags |= AF_EDGE_DONE;
}
}
if ( has_serifs || !anchor )
{
/*
* now hint the remaining edges (serifs and single) in order
* to complete our processing
*/
for ( edge = edges; edge < edge_limit; edge++ )
{
FT_Pos delta;
if ( edge->flags & AF_EDGE_DONE )
continue;
delta = 1000;
if ( edge->serif )
{
delta = edge->serif->opos - edge->opos;
if ( delta < 0 )
delta = -delta;
}
if ( delta < 64 + 16 )
{
af_latin_align_serif_edge( hints, edge->serif, edge );
AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
"aligned to (%.2f)\n",
edge-edges, edge->opos / 64.0,
edge->serif - edges, edge->serif->opos / 64.0,
edge->pos / 64.0 ));
}
else if ( !anchor )
{
AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
}
else
{
AF_Edge before, after;
for ( before = edge - 1; before >= edges; before-- )
if ( before->flags & AF_EDGE_DONE )
break;
for ( after = edge + 1; after < edge_limit; after++ )
if ( after->flags & AF_EDGE_DONE )
break;
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 );
else
edge->pos = anchor->pos +
FT_PIX_ROUND( edge->opos - anchor->opos );
AF_LOG(( "SERIF_LINK: edge %d (opos=%.2f) snapped to (%.2f)\n",
edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
edge->flags |= AF_EDGE_DONE;
if ( edge > edges && edge->pos < edge[-1].pos )
edge->pos = edge[-1].pos;
if ( edge + 1 < edge_limit &&
edge[1].flags & AF_EDGE_DONE &&
edge->pos > edge[1].pos )
edge->pos = edge[1].pos;
}
}
}
static FT_Error
af_latin_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_LatinMetrics metrics )
{
FT_Error error;
int dim;
error = af_glyph_hints_reload( hints, outline );
if ( error )
goto Exit;
/* analyze glyph outline */
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
{
error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
if ( error )
goto Exit;
}
if ( AF_HINTS_DO_VERTICAL( hints ) )
{
error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
if ( error )
goto Exit;
af_latin_hints_compute_blue_edges( hints, metrics );
}
/* grid-fit the outline */
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
{
#ifdef AF_USE_WARPER
if ( dim == AF_DIMENSION_HORZ &&
metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )
{
AF_WarperRec warper;
FT_Fixed scale;
FT_Pos delta;
af_warper_compute( &warper, hints, dim, &scale, &delta );
af_glyph_hints_scale_dim( hints, dim, scale, delta );
continue;
}
#endif
af_latin_hint_edges( hints, (AF_Dimension)dim );
af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
}
}
af_glyph_hints_save( hints, outline );
Exit:
return error;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N S C R I P T C L A S S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static const AF_Script_UniRangeRec af_latin_uniranges[] =
{
{ 32, 127 }, /* XXX: TODO: Add new Unicode ranges here! */
{ 160, 255 },
{ 0, 0 }
};
FT_CALLBACK_TABLE_DEF const AF_Scr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -