improvements to the Postscript hinter
This commit is contained in:
parent
fa12012a5d
commit
06fa55c892
|
@ -456,7 +456,9 @@
|
|||
return;
|
||||
}
|
||||
|
||||
/* perform stem snapping when requested */
|
||||
/* perform stem snapping when requested - this is necessary
|
||||
* for monochrome and LCD hinting modes only
|
||||
*/
|
||||
do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||
|
||||
( dimension == 1 && glyph->do_vert_snapping );
|
||||
|
||||
|
@ -516,14 +518,24 @@
|
|||
hint->cur_pos = pos;
|
||||
hint->cur_len = fit_len;
|
||||
|
||||
#if 0
|
||||
/* stem adjustment tries to snap stem widths to standard
|
||||
* ones. this is important to prevent unpleasant rounding
|
||||
* artefacts...
|
||||
*/
|
||||
if ( glyph->do_stem_adjust )
|
||||
{
|
||||
if ( len <= 64 )
|
||||
{
|
||||
/* the stem is less than one pixel, we will center it */
|
||||
/* around the nearest pixel center */
|
||||
/* */
|
||||
/* the stem is less than one pixel, we will center it
|
||||
* around the nearest pixel center
|
||||
*/
|
||||
#if 1
|
||||
pos = ( pos + (len >> 1) ) & -64;
|
||||
#else
|
||||
/* this seems to be a bug !! */
|
||||
pos = ( pos + ( (len >> 1) & -64 ) );
|
||||
#endif
|
||||
len = 64;
|
||||
}
|
||||
else
|
||||
|
@ -531,6 +543,7 @@
|
|||
len = psh3_dimension_quantize_len( dim, len, 0 );
|
||||
}
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/* now that we have a good hinted stem width, try to position */
|
||||
/* the stem along a pixel grid integer coordinate */
|
||||
|
@ -541,7 +554,7 @@
|
|||
|
||||
if ( do_snapping )
|
||||
{
|
||||
pos = hint->cur_pos;
|
||||
pos = hint->cur_pos;
|
||||
len = hint->cur_len;
|
||||
|
||||
if ( len < 64 )
|
||||
|
@ -587,6 +600,186 @@
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
|
||||
* of stems
|
||||
*/
|
||||
static void
|
||||
psh3_hint_align_light( PSH3_Hint hint,
|
||||
PSH_Globals globals,
|
||||
FT_Int dimension,
|
||||
PSH3_Glyph glyph )
|
||||
{
|
||||
PSH_Dimension dim = &globals->dimension[dimension];
|
||||
FT_Fixed scale = dim->scale_mult;
|
||||
FT_Fixed delta = dim->scale_delta;
|
||||
|
||||
|
||||
if ( !psh3_hint_is_fitted(hint) )
|
||||
{
|
||||
FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;
|
||||
FT_Pos len = FT_MulFix( hint->org_len, scale );
|
||||
|
||||
FT_Pos fit_center;
|
||||
FT_Pos fit_len;
|
||||
|
||||
PSH_AlignmentRec align;
|
||||
|
||||
/* ignore stem alignments when requested through the hint flags */
|
||||
if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
|
||||
( dimension == 1 && !glyph->do_vert_hints ) )
|
||||
{
|
||||
hint->cur_pos = pos;
|
||||
hint->cur_len = len;
|
||||
|
||||
psh3_hint_set_fitted( hint );
|
||||
return;
|
||||
}
|
||||
|
||||
fit_len = len;
|
||||
|
||||
hint->cur_len = fit_len;
|
||||
|
||||
/* check blue zones for horizontal stems */
|
||||
align.align = PSH_BLUE_ALIGN_NONE;
|
||||
align.align_bot = align.align_top = 0;
|
||||
|
||||
if ( dimension == 1 )
|
||||
psh_blues_snap_stem( &globals->blues,
|
||||
hint->org_pos + hint->org_len,
|
||||
hint->org_pos,
|
||||
&align );
|
||||
|
||||
switch ( align.align )
|
||||
{
|
||||
case PSH_BLUE_ALIGN_TOP:
|
||||
/* the top of the stem is aligned against a blue zone */
|
||||
hint->cur_pos = align.align_top - fit_len;
|
||||
break;
|
||||
|
||||
case PSH_BLUE_ALIGN_BOT:
|
||||
/* the bottom of the stem is aligned against a blue zone */
|
||||
hint->cur_pos = align.align_bot;
|
||||
break;
|
||||
|
||||
case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
|
||||
/* both edges of the stem are aligned against blue zones */
|
||||
hint->cur_pos = align.align_bot;
|
||||
hint->cur_len = align.align_top - align.align_bot;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
PSH3_Hint parent = hint->parent;
|
||||
|
||||
|
||||
if ( parent )
|
||||
{
|
||||
FT_Pos par_org_center, par_cur_center;
|
||||
FT_Pos cur_org_center, cur_delta;
|
||||
|
||||
|
||||
/* ensure that parent is already fitted */
|
||||
if ( !psh3_hint_is_fitted( parent ) )
|
||||
psh3_hint_align_light( parent, globals, dimension, glyph );
|
||||
|
||||
par_org_center = parent->org_pos + ( parent->org_len / 2);
|
||||
par_cur_center = parent->cur_pos + ( parent->cur_len / 2);
|
||||
cur_org_center = hint->org_pos + ( hint->org_len / 2);
|
||||
|
||||
cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
|
||||
pos = par_cur_center + cur_delta - ( len >> 1 );
|
||||
}
|
||||
|
||||
/* Stems less than one pixel wide are easy - we want to
|
||||
* make them as dark as possible, so they must fall within
|
||||
* one pixel. If the stem is split between two pixels
|
||||
* then snap the edge that is nearer to the pixel boundary
|
||||
* to the pixel boundary
|
||||
*/
|
||||
if (len <= 64)
|
||||
{
|
||||
if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 )
|
||||
pos += psh3_hint_snap_stem_side_delta ( pos, len );
|
||||
}
|
||||
/* Position stems other to minimize the amount of mid-grays.
|
||||
* There are, in general, two positions that do this,
|
||||
* illustrated as A) and B) below.
|
||||
*
|
||||
* + + + +
|
||||
*
|
||||
* A) |--------------------------------|
|
||||
* B) |--------------------------------|
|
||||
* C) |--------------------------------|
|
||||
*
|
||||
* Position A) (split the excess stem equally) should be better
|
||||
* for stems of width N + f where f < 0.5
|
||||
*
|
||||
* Position B) (split the deficiency equally) should be better
|
||||
* for stems of width N + f where f > 0.5
|
||||
*
|
||||
* It turns out though that minimizing the total number of lit
|
||||
* pixels is also important, so position C), with one edge
|
||||
* aligned with a pixel boundary is actually preferable
|
||||
* to A). There are also more possibile positions for C) than
|
||||
* for A) or B), so it involves less distortion of the overall
|
||||
* character shape.
|
||||
*/
|
||||
else /* len > 64 */
|
||||
{
|
||||
FT_Fixed frac_len = len & 63;
|
||||
FT_Fixed center = pos + ( len >> 1 );
|
||||
FT_Fixed delta_a, delta_b;
|
||||
|
||||
if ( ( len / 64 ) & 1 )
|
||||
{
|
||||
delta_a = ( center & -64 ) + 32 - center;
|
||||
delta_b = ( ( center + 32 ) & - 64 ) - center;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta_a = ( ( center + 32 ) & - 64 ) - center;
|
||||
delta_b = ( center & -64 ) + 32 - center;
|
||||
}
|
||||
|
||||
/* We choose between B) and C) above based on the amount
|
||||
* of fractinal stem width; for small amounts, choose
|
||||
* C) always, for large amounts, B) always, and inbetween,
|
||||
* pick whichever one involves less stem movement.
|
||||
*/
|
||||
if (frac_len < 32)
|
||||
{
|
||||
pos += psh3_hint_snap_stem_side_delta ( pos, len );
|
||||
}
|
||||
else if (frac_len < 48)
|
||||
{
|
||||
FT_Fixed side_delta = psh3_hint_snap_stem_side_delta ( pos, len );
|
||||
|
||||
if ( ABS( side_delta ) < ABS( delta_b ) )
|
||||
pos += side_delta;
|
||||
else
|
||||
pos += delta_b;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos += delta_b;
|
||||
}
|
||||
}
|
||||
|
||||
hint->cur_pos = pos;
|
||||
}
|
||||
} /* switch */
|
||||
|
||||
psh3_hint_set_fitted( hint );
|
||||
|
||||
#ifdef DEBUG_HINTER
|
||||
if ( ps3_debug_hint_func )
|
||||
ps3_debug_hint_func( hint, dimension );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
psh3_hint_table_align_hints( PSH3_Hint_Table table,
|
||||
PSH_Globals globals,
|
||||
|
|
Loading…
Reference in New Issue