📄 pshalgo.c
字号:
point->cur_u = hint->cur_pos + hint->cur_len;
else
{
delta = point->org_u - hint->org_pos;
if ( delta <= 0 )
point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
else if ( delta >= hint->org_len )
point->cur_u = hint->cur_pos + hint->cur_len +
FT_MulFix( delta - hint->org_len, scale );
else if ( hint->org_len > 0 )
point->cur_u = hint->cur_pos +
FT_MulDiv( delta, hint->cur_len,
hint->org_len );
else
point->cur_u = hint->cur_pos;
}
psh_point_set_fitted( point );
}
}
}
#define PSH_MAX_STRONG_INTERNAL 16
static void
psh_glyph_interpolate_normal_points( PSH_Glyph glyph,
FT_Int dimension )
{
#if 1
/* first technique: a point is strong if it is a local extremum */
PSH_Dimension dim = &glyph->globals->dimension[dimension];
FT_Fixed scale = dim->scale_mult;
FT_Memory memory = glyph->memory;
PSH_Point* strongs = NULL;
PSH_Point strongs_0[PSH_MAX_STRONG_INTERNAL];
FT_UInt num_strongs = 0;
PSH_Point points = glyph->points;
PSH_Point points_end = points + glyph->num_points;
PSH_Point point;
/* first count the number of strong points */
for ( point = points; point < points_end; point++ )
{
if ( psh_point_is_strong( point ) )
num_strongs++;
}
if ( num_strongs == 0 ) /* nothing to do here */
return;
/* allocate an array to store a list of points, */
/* stored in increasing org_u order */
if ( num_strongs <= PSH_MAX_STRONG_INTERNAL )
strongs = strongs_0;
else
{
FT_Error error;
if ( FT_NEW_ARRAY( strongs, num_strongs ) )
return;
}
num_strongs = 0;
for ( point = points; point < points_end; point++ )
{
PSH_Point* insert;
if ( !psh_point_is_strong( point ) )
continue;
for ( insert = strongs + num_strongs; insert > strongs; insert-- )
{
if ( insert[-1]->org_u <= point->org_u )
break;
insert[0] = insert[-1];
}
insert[0] = point;
num_strongs++;
}
/* now try to interpolate all normal points */
for ( point = points; point < points_end; point++ )
{
if ( psh_point_is_strong( point ) )
continue;
/* sometimes, some local extrema are smooth points */
if ( psh_point_is_smooth( point ) )
{
if ( point->dir_in == PSH_DIR_NONE ||
point->dir_in != point->dir_out )
continue;
if ( !psh_point_is_extremum( point ) &&
!psh_point_is_inflex( point ) )
continue;
point->flags &= ~PSH_POINT_SMOOTH;
}
/* find best enclosing point coordinates then interpolate */
{
PSH_Point before, after;
FT_UInt nn;
for ( nn = 0; nn < num_strongs; nn++ )
if ( strongs[nn]->org_u > point->org_u )
break;
if ( nn == 0 ) /* point before the first strong point */
{
after = strongs[0];
point->cur_u = after->cur_u +
FT_MulFix( point->org_u - after->org_u,
scale );
}
else
{
before = strongs[nn - 1];
for ( nn = num_strongs; nn > 0; nn-- )
if ( strongs[nn - 1]->org_u < point->org_u )
break;
if ( nn == num_strongs ) /* point is after last strong point */
{
before = strongs[nn - 1];
point->cur_u = before->cur_u +
FT_MulFix( point->org_u - before->org_u,
scale );
}
else
{
FT_Pos u;
after = strongs[nn];
/* now interpolate point between before and after */
u = point->org_u;
if ( u == before->org_u )
point->cur_u = before->cur_u;
else if ( u == after->org_u )
point->cur_u = after->cur_u;
else
point->cur_u = before->cur_u +
FT_MulDiv( u - before->org_u,
after->cur_u - before->cur_u,
after->org_u - before->org_u );
}
}
psh_point_set_fitted( point );
}
}
if ( strongs != strongs_0 )
FT_FREE( strongs );
#endif /* 1 */
}
/* interpolate other points */
static void
psh_glyph_interpolate_other_points( PSH_Glyph glyph,
FT_Int dimension )
{
PSH_Dimension dim = &glyph->globals->dimension[dimension];
FT_Fixed scale = dim->scale_mult;
FT_Fixed delta = dim->scale_delta;
PSH_Contour contour = glyph->contours;
FT_UInt num_contours = glyph->num_contours;
for ( ; num_contours > 0; num_contours--, contour++ )
{
PSH_Point start = contour->start;
PSH_Point first, next, point;
FT_UInt fit_count;
/* count the number of strong points in this contour */
next = start + contour->count;
fit_count = 0;
first = 0;
for ( point = start; point < next; point++ )
if ( psh_point_is_fitted( point ) )
{
if ( !first )
first = point;
fit_count++;
}
/* if there are less than 2 fitted points in the contour, we */
/* simply scale and eventually translate the contour points */
if ( fit_count < 2 )
{
if ( fit_count == 1 )
delta = first->cur_u - FT_MulFix( first->org_u, scale );
for ( point = start; point < next; point++ )
if ( point != first )
point->cur_u = FT_MulFix( point->org_u, scale ) + delta;
goto Next_Contour;
}
/* there are more than 2 strong points in this contour; we */
/* need to interpolate weak points between them */
start = first;
do
{
point = first;
/* skip consecutive fitted points */
for (;;)
{
next = first->next;
if ( next == start )
goto Next_Contour;
if ( !psh_point_is_fitted( next ) )
break;
first = next;
}
/* find next fitted point after unfitted one */
for (;;)
{
next = next->next;
if ( psh_point_is_fitted( next ) )
break;
}
/* now interpolate between them */
{
FT_Pos org_a, org_ab, cur_a, cur_ab;
FT_Pos org_c, org_ac, cur_c;
FT_Fixed scale_ab;
if ( first->org_u <= next->org_u )
{
org_a = first->org_u;
cur_a = first->cur_u;
org_ab = next->org_u - org_a;
cur_ab = next->cur_u - cur_a;
}
else
{
org_a = next->org_u;
cur_a = next->cur_u;
org_ab = first->org_u - org_a;
cur_ab = first->cur_u - cur_a;
}
scale_ab = 0x10000L;
if ( org_ab > 0 )
scale_ab = FT_DivFix( cur_ab, org_ab );
point = first->next;
do
{
org_c = point->org_u;
org_ac = org_c - org_a;
if ( org_ac <= 0 )
{
/* on the left of the interpolation zone */
cur_c = cur_a + FT_MulFix( org_ac, scale );
}
else if ( org_ac >= org_ab )
{
/* on the right on the interpolation zone */
cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
}
else
{
/* within the interpolation zone */
cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
}
point->cur_u = cur_c;
point = point->next;
} while ( point != next );
}
/* keep going until all points in the contours have been processed */
first = next;
} while ( first != start );
Next_Contour:
;
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** HIGH-LEVEL INTERFACE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_Error
ps_hints_apply( PS_Hints ps_hints,
FT_Outline* outline,
PSH_Globals globals,
FT_Render_Mode hint_mode )
{
PSH_GlyphRec glyphrec;
PSH_Glyph glyph = &glyphrec;
FT_Error error;
#ifdef DEBUG_HINTER
FT_Memory memory;
#endif
FT_Int dimension;
/* something to do? */
if ( outline->n_points == 0 || outline->n_contours == 0 )
return PSH_Err_Ok;
#ifdef DEBUG_HINTER
memory = globals->memory;
if ( ps_debug_glyph )
{
psh_glyph_done( ps_debug_glyph );
FT_FREE( ps_debug_glyph );
}
if ( FT_NEW( glyph ) )
return error;
ps_debug_glyph = glyph;
#endif /* DEBUG_HINTER */
error = psh_glyph_init( glyph, outline, ps_hints, globals );
if ( error )
goto Exit;
/* try to optimize the y_scale so that the top of non-capital letters
* is aligned on a pixel boundary whenever possible
*/
{
PSH_Dimension dim_x = &glyph->globals->dimension[0];
PSH_Dimension dim_y = &glyph->globals->dimension[1];
FT_Fixed x_scale = dim_x->scale_mult;
FT_Fixed y_scale = dim_y->scale_mult;
FT_Fixed scaled;
FT_Fixed fitted;
scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
fitted = FT_PIX_ROUND( scaled );
if ( fitted != 0 && scaled != fitted )
{
y_scale = FT_MulDiv( y_scale, fitted, scaled );
if ( fitted < scaled )
x_scale -= x_scale / 50;
psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );
}
}
glyph->do_horz_hints = 1;
glyph->do_vert_hints = 1;
glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
hint_mode == FT_RENDER_MODE_LCD );
glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
hint_mode == FT_RENDER_MODE_LCD_V );
glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
for ( dimension = 0; dimension < 2; dimension++ )
{
/* load outline coordinates into glyph */
psh_glyph_load_points( glyph, dimension );
/* compute local extrema */
psh_glyph_compute_extrema( glyph );
/* compute aligned stem/hints positions */
psh_hint_table_align_hints( &glyph->hint_tables[dimension],
glyph->globals,
dimension,
glyph );
/* find strong points, align them, then interpolate others */
psh_glyph_find_strong_points( glyph, dimension );
if ( dimension == 1 )
psh_glyph_find_blue_points( &globals->blues, glyph );
psh_glyph_interpolate_strong_points( glyph, dimension );
psh_glyph_interpolate_normal_points( glyph, dimension );
psh_glyph_interpolate_other_points( glyph, dimension );
/* save hinted coordinates back to outline */
psh_glyph_save_points( glyph, dimension );
}
Exit:
#ifndef DEBUG_HINTER
psh_glyph_done( glyph );
#endif
return error;
}
/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -