📄 aflatin.c
字号:
/* skip inactive blue zones (i.e., those that are too small) */
if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
continue;
/* if it is a top zone, check for right edges -- if it is a bottom */
/* zone, check for left edges */
/* */
/* of course, that's for TrueType */
is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
/* if it is a top zone, the edge must be against the major */
/* direction; if it is a bottom zone, it must be in the major */
/* direction */
if ( is_top_blue ^ is_major_dir )
{
FT_Pos dist;
/* first of all, compare it to the reference position */
dist = edge->fpos - blue->ref.org;
if ( dist < 0 )
dist = -dist;
dist = FT_MulFix( dist, scale );
if ( dist < best_dist )
{
best_dist = dist;
best_blue = & blue->ref;
}
/* now, compare it to the overshoot position if the edge is */
/* rounded, and if the edge is over the reference position of a */
/* top zone, or under the reference position of a bottom zone */
if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
{
FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
if ( is_top_blue ^ is_under_ref )
{
blue = latin->blues + bb;
dist = edge->fpos - blue->shoot.org;
if ( dist < 0 )
dist = -dist;
dist = FT_MulFix( dist, scale );
if ( dist < best_dist )
{
best_dist = dist;
best_blue = & blue->shoot;
}
}
}
}
}
if ( best_blue )
edge->blue_edge = best_blue;
}
}
static FT_Error
af_latin_hints_init( AF_GlyphHints hints,
AF_LatinMetrics metrics )
{
FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags;
FT_Face face = metrics->root.scaler.face;
af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
/*
* correct x_scale and y_scale when needed, since they may have
* been modified af_latin_scale_dim above
*/
hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
#ifdef AF_USE_WARPER
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
{
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
}
#endif
scaler_flags = hints->scaler_flags;
other_flags = 0;
/*
* We snap the width of vertical stems for the monochrome and
* horizontal LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
/*
* We snap the width of horizontal stems for the monochrome and
* vertical LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
other_flags |= AF_LATIN_HINTS_VERT_SNAP;
/*
* We adjust stems to full pixels only if we don't use the `light' mode.
*/
if ( mode != FT_RENDER_MODE_LIGHT )
other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
if ( mode == FT_RENDER_MODE_MONO )
other_flags |= AF_LATIN_HINTS_MONO;
/*
* In `light' hinting mode we disable horizontal hinting completely.
* We also do it if the face is italic.
*/
if ( mode == FT_RENDER_MODE_LIGHT ||
(face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
return 0;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N G L Y P H G R I D - F I T T I N G *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* snap a given width in scaled coordinates to one of the */
/* current standard widths */
static FT_Pos
af_latin_snap_width( AF_Width widths,
FT_Int count,
FT_Pos width )
{
int n;
FT_Pos best = 64 + 32 + 2;
FT_Pos reference = width;
FT_Pos scaled;
for ( n = 0; n < count; n++ )
{
FT_Pos w;
FT_Pos dist;
w = widths[n].cur;
dist = width - w;
if ( dist < 0 )
dist = -dist;
if ( dist < best )
{
best = dist;
reference = w;
}
}
scaled = FT_PIX_ROUND( reference );
if ( width >= reference )
{
if ( width < scaled + 48 )
width = reference;
}
else
{
if ( width > scaled - 48 )
width = reference;
}
return width;
}
/* compute the snapped width of a given stem */
static FT_Pos
af_latin_compute_stem_width( AF_GlyphHints hints,
AF_Dimension dim,
FT_Pos width,
AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags )
{
AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
AF_LatinAxis axis = & metrics->axis[dim];
FT_Pos dist = width;
FT_Int sign = 0;
FT_Int vertical = ( dim == AF_DIMENSION_VERT );
if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )
return width;
if ( dist < 0 )
{
dist = -width;
sign = 1;
}
if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
{
/* smooth hinting process: very lightly quantize the stem width */
/* leave the widths of serifs alone */
if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
goto Done_Width;
else if ( ( base_flags & AF_EDGE_ROUND ) )
{
if ( dist < 80 )
dist = 64;
}
else if ( dist < 56 )
dist = 56;
if ( axis->width_count > 0 )
{
FT_Pos delta;
/* compare to standard width */
if ( axis->width_count > 0 )
{
delta = dist - axis->widths[0].cur;
if ( delta < 0 )
delta = -delta;
if ( delta < 40 )
{
dist = axis->widths[0].cur;
if ( dist < 48 )
dist = 48;
goto Done_Width;
}
}
if ( dist < 3 * 64 )
{
delta = dist & 63;
dist &= -64;
if ( delta < 10 )
dist += delta;
else if ( delta < 32 )
dist += 10;
else if ( delta < 54 )
dist += 54;
else
dist += delta;
}
else
dist = ( dist + 32 ) & ~63;
}
}
else
{
/* strong hinting process: snap the stem width to integer pixels */
FT_Pos org_dist = dist;
dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
if ( vertical )
{
/* in the case of vertical hinting, always round */
/* the stem heights to integer pixels */
if ( dist >= 64 )
dist = ( dist + 16 ) & ~63;
else
dist = 64;
}
else
{
if ( AF_LATIN_HINTS_DO_MONO( hints ) )
{
/* monochrome horizontal hinting: snap widths to integer pixels */
/* with a different threshold */
if ( dist < 64 )
dist = 64;
else
dist = ( dist + 32 ) & ~63;
}
else
{
/* for horizontal anti-aliased hinting, we adopt a more subtle */
/* approach: we strengthen small stems, round stems whose size */
/* is between 1 and 2 pixels to an integer, otherwise nothing */
if ( dist < 48 )
dist = ( dist + 64 ) >> 1;
else if ( dist < 128 )
{
/* We only round to an integer width if the corresponding */
/* distortion is less than 1/4 pixel. Otherwise this */
/* makes everything worse since the diagonals, which are */
/* not hinted, appear a lot bolder or thinner than the */
/* vertical stems. */
FT_Int delta;
dist = ( dist + 22 ) & ~63;
delta = dist - org_dist;
if ( delta < 0 )
delta = -delta;
if (delta >= 16)
{
dist = org_dist;
if ( dist < 48 )
dist = ( dist + 64 ) >> 1;
}
}
else
/* round otherwise to prevent color fringes in LCD mode */
dist = ( dist + 32 ) & ~63;
}
}
}
Done_Width:
if ( sign )
dist = -dist;
return dist;
}
/* align one stem edge relative to the previous stem edge */
static void
af_latin_align_linked_edge( AF_GlyphHints hints,
AF_Dimension dim,
AF_Edge base_edge,
AF_Edge stem_edge )
{
FT_Pos dist = stem_edge->opos - base_edge->opos;
FT_Pos fitted_width = af_latin_compute_stem_width(
hints, dim, dist,
(AF_Edge_Flags)base_edge->flags,
(AF_Edge_Flags)stem_edge->flags );
stem_edge->pos = base_edge->pos + fitted_width;
AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
"dist was %.2f, now %.2f\n",
stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
}
static void
af_latin_align_serif_edge( AF_GlyphHints hints,
AF_Edge base,
AF_Edge serif )
{
FT_UNUSED( hints );
serif->pos = base->pos + (serif->opos - base->opos);
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** E D G E H I N T I N G ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( void )
af_latin_hint_edges( 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;
FT_Int n_edges;
AF_Edge edge;
AF_Edge anchor = 0;
FT_Int has_serifs = 0;
/* we begin by aligning all stems relative to the blue zone */
/* if needed -- that's only for horizontal edges */
if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
{
for ( edge = edges; edge < edge_limit; edge++ )
{
AF_Width blue;
AF_Edge edge1, edge2;
if ( edge->flags & AF_EDGE_DONE )
continue;
blue = edge->blue_edge;
edge1 = NULL;
edge2 = edge->link;
if ( blue )
{
edge1 = edge;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -