📄 pshalgo.c
字号:
/* first of all, compute all local extrema */
for ( n = 0; n < glyph->num_contours; n++ )
{
PSH_Point first = glyph->contours[n].start;
PSH_Point point, before, after;
if ( glyph->contours[n].count == 0 )
continue;
point = first;
before = point;
after = point;
do
{
before = before->prev;
if ( before == first )
goto Skip;
} while ( before->org_u == point->org_u );
first = point = before->next;
for (;;)
{
after = point;
do
{
after = after->next;
if ( after == first )
goto Next;
} while ( after->org_u == point->org_u );
if ( before->org_u < point->org_u )
{
if ( after->org_u < point->org_u )
{
/* local maximum */
goto Extremum;
}
}
else /* before->org_u > point->org_u */
{
if ( after->org_u > point->org_u )
{
/* local minimum */
Extremum:
do
{
psh_point_set_extremum( point );
point = point->next;
} while ( point != after );
}
}
before = after->prev;
point = after;
} /* for */
Next:
;
}
/* for each extremum, determine its direction along the */
/* orthogonal axis */
for ( n = 0; n < glyph->num_points; n++ )
{
PSH_Point point, before, after;
point = &glyph->points[n];
before = point;
after = point;
if ( psh_point_is_extremum( point ) )
{
do
{
before = before->prev;
if ( before == point )
goto Skip;
} while ( before->org_v == point->org_v );
do
{
after = after->next;
if ( after == point )
goto Skip;
} while ( after->org_v == point->org_v );
}
if ( before->org_v < point->org_v &&
after->org_v > point->org_v )
{
psh_point_set_positive( point );
}
else if ( before->org_v > point->org_v &&
after->org_v < point->org_v )
{
psh_point_set_negative( point );
}
Skip:
;
}
}
/* major_dir is the direction for points on the bottom/left of the stem; */
/* Points on the top/right of the stem will have a direction of */
/* -major_dir. */
static void
psh_hint_table_find_strong_points( PSH_Hint_Table table,
PSH_Point point,
FT_UInt count,
FT_Int threshold,
FT_Int major_dir )
{
PSH_Hint* sort = table->sort;
FT_UInt num_hints = table->num_hints;
for ( ; count > 0; count--, point++ )
{
FT_Int point_dir = 0;
FT_Pos org_u = point->org_u;
if ( psh_point_is_strong( point ) )
continue;
if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
point_dir = point->dir_in;
else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
point_dir = point->dir_out;
if ( point_dir )
{
if ( point_dir == major_dir )
{
FT_UInt nn;
for ( nn = 0; nn < num_hints; nn++ )
{
PSH_Hint hint = sort[nn];
FT_Pos d = org_u - hint->org_pos;
if ( d < threshold && -d < threshold )
{
psh_point_set_strong( point );
point->flags2 |= PSH_POINT_EDGE_MIN;
point->hint = hint;
break;
}
}
}
else if ( point_dir == -major_dir )
{
FT_UInt nn;
for ( nn = 0; nn < num_hints; nn++ )
{
PSH_Hint hint = sort[nn];
FT_Pos d = org_u - hint->org_pos - hint->org_len;
if ( d < threshold && -d < threshold )
{
psh_point_set_strong( point );
point->flags2 |= PSH_POINT_EDGE_MAX;
point->hint = hint;
break;
}
}
}
}
#if 1
else if ( psh_point_is_extremum( point ) )
{
/* treat extrema as special cases for stem edge alignment */
FT_UInt nn, min_flag, max_flag;
if ( major_dir == PSH_DIR_HORIZONTAL )
{
min_flag = PSH_POINT_POSITIVE;
max_flag = PSH_POINT_NEGATIVE;
}
else
{
min_flag = PSH_POINT_NEGATIVE;
max_flag = PSH_POINT_POSITIVE;
}
if ( point->flags2 & min_flag )
{
for ( nn = 0; nn < num_hints; nn++ )
{
PSH_Hint hint = sort[nn];
FT_Pos d = org_u - hint->org_pos;
if ( d < threshold && -d < threshold )
{
point->flags2 |= PSH_POINT_EDGE_MIN;
point->hint = hint;
psh_point_set_strong( point );
break;
}
}
}
else if ( point->flags2 & max_flag )
{
for ( nn = 0; nn < num_hints; nn++ )
{
PSH_Hint hint = sort[nn];
FT_Pos d = org_u - hint->org_pos - hint->org_len;
if ( d < threshold && -d < threshold )
{
point->flags2 |= PSH_POINT_EDGE_MAX;
point->hint = hint;
psh_point_set_strong( point );
break;
}
}
}
if ( point->hint == NULL )
{
for ( nn = 0; nn < num_hints; nn++ )
{
PSH_Hint hint = sort[nn];
if ( org_u >= hint->org_pos &&
org_u <= hint->org_pos + hint->org_len )
{
point->hint = hint;
break;
}
}
}
}
#endif /* 1 */
}
}
/* the accepted shift for strong points in fractional pixels */
#define PSH_STRONG_THRESHOLD 32
/* the maximum shift value in font units */
#define PSH_STRONG_THRESHOLD_MAXIMUM 30
/* find strong points in a glyph */
static void
psh_glyph_find_strong_points( PSH_Glyph glyph,
FT_Int dimension )
{
/* a point is `strong' if it is located on a stem edge and */
/* has an `in' or `out' tangent parallel to the hint's direction */
PSH_Hint_Table table = &glyph->hint_tables[dimension];
PS_Mask mask = table->hint_masks->masks;
FT_UInt num_masks = table->hint_masks->num_masks;
FT_UInt first = 0;
FT_Int major_dir = dimension == 0 ? PSH_DIR_VERTICAL
: PSH_DIR_HORIZONTAL;
PSH_Dimension dim = &glyph->globals->dimension[dimension];
FT_Fixed scale = dim->scale_mult;
FT_Int threshold;
threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale );
if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM )
threshold = PSH_STRONG_THRESHOLD_MAXIMUM;
/* process secondary hints to `selected' points */
if ( num_masks > 1 && glyph->num_points > 0 )
{
first = mask->end_point;
mask++;
for ( ; num_masks > 1; num_masks--, mask++ )
{
FT_UInt next;
FT_Int count;
next = mask->end_point;
count = next - first;
if ( count > 0 )
{
PSH_Point point = glyph->points + first;
psh_hint_table_activate_mask( table, mask );
psh_hint_table_find_strong_points( table, point, count,
threshold, major_dir );
}
first = next;
}
}
/* process primary hints for all points */
if ( num_masks == 1 )
{
FT_UInt count = glyph->num_points;
PSH_Point point = glyph->points;
psh_hint_table_activate_mask( table, table->hint_masks->masks );
psh_hint_table_find_strong_points( table, point, count,
threshold, major_dir );
}
/* now, certain points may have been attached to a hint and */
/* not marked as strong; update their flags then */
{
FT_UInt count = glyph->num_points;
PSH_Point point = glyph->points;
for ( ; count > 0; count--, point++ )
if ( point->hint && !psh_point_is_strong( point ) )
psh_point_set_strong( point );
}
}
/* find points in a glyph which are in a blue zone and have `in' or */
/* `out' tangents parallel to the horizontal axis */
static void
psh_glyph_find_blue_points( PSH_Blues blues,
PSH_Glyph glyph )
{
PSH_Blue_Table table;
PSH_Blue_Zone zone;
FT_UInt glyph_count = glyph->num_points;
FT_UInt blue_count;
PSH_Point point = glyph->points;
for ( ; glyph_count > 0; glyph_count--, point++ )
{
FT_Pos y;
/* check tangents */
if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) &&
!PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) )
continue;
/* skip strong points */
if ( psh_point_is_strong( point ) )
continue;
y = point->org_u;
/* look up top zones */
table = &blues->normal_top;
blue_count = table->count;
zone = table->zones;
for ( ; blue_count > 0; blue_count--, zone++ )
{
FT_Pos delta = y - zone->org_bottom;
if ( delta < -blues->blue_fuzz )
break;
if ( y <= zone->org_top + blues->blue_fuzz )
if ( blues->no_overshoots || delta <= blues->blue_threshold )
{
point->cur_u = zone->cur_bottom;
psh_point_set_strong( point );
psh_point_set_fitted( point );
}
}
/* look up bottom zones */
table = &blues->normal_bottom;
blue_count = table->count;
zone = table->zones + blue_count - 1;
for ( ; blue_count > 0; blue_count--, zone-- )
{
FT_Pos delta = zone->org_top - y;
if ( delta < -blues->blue_fuzz )
break;
if ( y >= zone->org_bottom - blues->blue_fuzz )
if ( blues->no_overshoots || delta < blues->blue_threshold )
{
point->cur_u = zone->cur_top;
psh_point_set_strong( point );
psh_point_set_fitted( point );
}
}
}
}
/* interpolate strong points with the help of hinted coordinates */
static void
psh_glyph_interpolate_strong_points( PSH_Glyph glyph,
FT_Int dimension )
{
PSH_Dimension dim = &glyph->globals->dimension[dimension];
FT_Fixed scale = dim->scale_mult;
FT_UInt count = glyph->num_points;
PSH_Point point = glyph->points;
for ( ; count > 0; count--, point++ )
{
PSH_Hint hint = point->hint;
if ( hint )
{
FT_Pos delta;
if ( psh_point_is_edge_min( point ) )
point->cur_u = hint->cur_pos;
else if ( psh_point_is_edge_max( point ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -