2003-01-11 David Chester <davidchester@qmx.net>
* include/freetype/config/ftoption.h, src/autohint/ahglobal.h, src/autohint/ahglobal.c, src/autohint/ahglyph.c, src/autohint/ahtypes.h: included David Chester's patches to the auto-hinter in order to slightly improve the output. Note that everything is controlled through the new FT_CONFIG_OPTION_CHESTER_HINTS defined at the end of "ftoption.h", there are also individual FT_CONFIG_CHESTER_XXX macros to control individual "features". Note that all improvements are enabled by default, but can be tweaked for optimization and testing purpose. The configuration macros will most likely disappear in the short future. 2003-01-11 David Turner <david@freetype.org> * include/freetype/internal/fnttypes.h: fixed a structure field definition to avoid memory overwrites
This commit is contained in:
parent
0fb0820fee
commit
7f0c4e9cc2
21
ChangeLog
21
ChangeLog
@ -1,3 +1,24 @@
|
||||
2003-01-11 David Chester <davidchester@qmx.net>
|
||||
|
||||
* include/freetype/config/ftoption.h, src/autohint/ahglobal.h,
|
||||
src/autohint/ahglobal.c, src/autohint/ahglyph.c,
|
||||
src/autohint/ahtypes.h:
|
||||
|
||||
included David Chester's patches to the auto-hinter in order to
|
||||
slightly improve the output. Note that everything is controlled
|
||||
through the new FT_CONFIG_OPTION_CHESTER_HINTS defined at the
|
||||
end of "ftoption.h", there are also individual FT_CONFIG_CHESTER_XXX
|
||||
macros to control individual "features".
|
||||
|
||||
Note that all improvements are enabled by default, but can be
|
||||
tweaked for optimization and testing purpose. The configuration
|
||||
macros will most likely disappear in the short future.
|
||||
|
||||
2003-01-11 David Turner <david@freetype.org>
|
||||
|
||||
* include/freetype/internal/fnttypes.h: fixed a structure field
|
||||
definition to avoid memory overwrites
|
||||
|
||||
2003-01-08 Huw Dawies <huw@codeweavers.com>
|
||||
|
||||
* src/winfonts/winfnt.c: read 16 bytes into "reserved2", not "reserved"
|
||||
|
@ -469,6 +469,17 @@ FT_BEGIN_HEADER
|
||||
|
||||
/* */
|
||||
|
||||
#undef FT_CONFIG_OPTION_CHESTER_HINTS
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_CHESTER_HINTS
|
||||
|
||||
# define FT_CONFIG_CHESTER_SMALL_F
|
||||
# define FT_CONFIG_CHESTER_ASCENDER
|
||||
# define FT_CONFIG_CHESTER_SERIF
|
||||
# define FT_CONFIG_CHESTER_STEM
|
||||
|
||||
#endif /* FT_CONFIG_OPTION_CHESTER_HINTS */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
|
@ -108,7 +108,7 @@ FT_BEGIN_HEADER
|
||||
FT_UShort B_space;
|
||||
FT_UShort C_space;
|
||||
FT_UShort color_table_offset;
|
||||
FT_Byte reserved2[4];
|
||||
FT_Byte reserved2[16];
|
||||
|
||||
} WinFNT_HeaderRec, *WinFNT_Header;
|
||||
|
||||
|
@ -32,6 +32,9 @@
|
||||
{
|
||||
"THEZOCQS",
|
||||
"HEZLOCUS",
|
||||
#ifdef FT_CONFIG_CHESTER_SMALL_F
|
||||
"fijkdbh",
|
||||
#endif
|
||||
"xzroesc",
|
||||
"xzroesc",
|
||||
"pqgjy"
|
||||
|
@ -32,8 +32,18 @@
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
#define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || \
|
||||
(b) == AH_BLUE_SMALL_TOP )
|
||||
#ifdef FT_CONFIG_CHESTER_SMALL_F
|
||||
|
||||
# define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || \
|
||||
(b) == AH_BLUE_SMALL_F_TOP || \
|
||||
(b) == AH_BLUE_SMALL_TOP )
|
||||
|
||||
#else /* !CHESTER_SMALL_F */
|
||||
|
||||
# define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || \
|
||||
(b) == AH_BLUE_SMALL_TOP )
|
||||
|
||||
#endif /* !CHESTER_SMALL_F */
|
||||
|
||||
|
||||
/* compute global metrics automatically */
|
||||
|
@ -1350,10 +1350,20 @@
|
||||
else
|
||||
edge2 = seg2->edge;
|
||||
|
||||
#ifdef FT_CONFIG_CHESTER_SERIF
|
||||
if ( is_serif )
|
||||
{
|
||||
edge->serif = edge2;
|
||||
edge2->flags |= AH_EDGE_SERIF;
|
||||
}
|
||||
else
|
||||
edge->link = edge2;
|
||||
#else /* !CHESTER_SERIF */
|
||||
if ( is_serif )
|
||||
edge->serif = edge2;
|
||||
else
|
||||
edge->link = edge2;
|
||||
#endif
|
||||
}
|
||||
|
||||
seg = seg->edge_next;
|
||||
@ -1477,8 +1487,14 @@
|
||||
|
||||
/* compute the initial threshold as a fraction of the EM size */
|
||||
best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale );
|
||||
|
||||
#ifdef FT_CONFIG_CHESTER_SMALL_F
|
||||
if ( best_dist > 64 / 2 )
|
||||
best_dist = 64 / 2;
|
||||
#else
|
||||
if ( best_dist > 64 / 4 )
|
||||
best_dist = 64 / 4;
|
||||
best_dist = 64 / 4;
|
||||
#endif
|
||||
|
||||
for ( blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++ )
|
||||
{
|
||||
|
@ -88,6 +88,137 @@
|
||||
|
||||
|
||||
/* compute the snapped width of a given stem */
|
||||
#ifdef FT_CONFIG_CHESTER_SERIF
|
||||
static FT_Pos
|
||||
ah_compute_stem_width( AH_Hinter hinter,
|
||||
int vertical,
|
||||
FT_Pos width,
|
||||
AH_Edge_Flags base_flags,
|
||||
AH_Edge_Flags stem_flags )
|
||||
{
|
||||
AH_Globals globals = &hinter->globals->scaled;
|
||||
FT_Pos dist = width;
|
||||
FT_Int sign = 0;
|
||||
|
||||
|
||||
if ( dist < 0 )
|
||||
{
|
||||
dist = -width;
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
if ( !hinter->do_stem_adjust )
|
||||
{
|
||||
/* leave stem widths unchanged */
|
||||
}
|
||||
else if ( ( vertical && !hinter->do_vert_snapping ) ||
|
||||
( !vertical && !hinter->do_horz_snapping ) )
|
||||
{
|
||||
/* smooth hinting process, very lightly quantize the stem width */
|
||||
/* */
|
||||
|
||||
/* leave the widths of serifs alone */
|
||||
|
||||
if ( ( stem_flags & AH_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
|
||||
goto Done_Width;
|
||||
|
||||
else if ( ( base_flags & AH_EDGE_ROUND ) )
|
||||
{
|
||||
if ( dist < 96 )
|
||||
dist = 64;
|
||||
}
|
||||
else if ( dist < 56 )
|
||||
dist = 56;
|
||||
|
||||
{
|
||||
FT_Pos delta = dist - globals->stds[vertical];
|
||||
|
||||
|
||||
if ( delta < 0 )
|
||||
delta = -delta;
|
||||
|
||||
if ( delta < 40 )
|
||||
{
|
||||
dist = globals->stds[vertical];
|
||||
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 ) & -64;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* strong hinting process, snap the stem width to integer pixels */
|
||||
/* */
|
||||
if ( vertical )
|
||||
{
|
||||
dist = ah_snap_width( globals->heights, globals->num_heights, dist );
|
||||
|
||||
/* in the case of vertical hinting, always round */
|
||||
/* the stem heights to integer pixels */
|
||||
if ( dist >= 64 )
|
||||
dist = ( dist + 16 ) & -64;
|
||||
else
|
||||
dist = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist = ah_snap_width( globals->widths, globals->num_widths, dist );
|
||||
|
||||
if ( hinter->flags & AH_HINTER_MONOCHROME )
|
||||
{
|
||||
/* monochrome horizontal hinting: snap widths to integer pixels */
|
||||
/* with a different threshold */
|
||||
if ( dist < 64 )
|
||||
dist = 64;
|
||||
else
|
||||
dist = ( dist + 32 ) & -64;
|
||||
}
|
||||
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 )
|
||||
dist = ( dist + 22 ) & -64;
|
||||
else
|
||||
/* XXX: round otherwise, prevent color fringes in LCD mode */
|
||||
dist = ( dist + 32 ) & -64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Done_Width:
|
||||
if ( sign )
|
||||
dist = -dist;
|
||||
|
||||
return dist;
|
||||
}
|
||||
#else /* !CHESTER_SERIF */
|
||||
static FT_Pos
|
||||
ah_compute_stem_width( AH_Hinter hinter,
|
||||
int vertical,
|
||||
@ -201,6 +332,7 @@
|
||||
|
||||
return dist;
|
||||
}
|
||||
#endif /* !CHESTER_SERIF */
|
||||
|
||||
|
||||
/* align one stem edge relative to the previous stem edge */
|
||||
@ -212,9 +344,18 @@
|
||||
{
|
||||
FT_Pos dist = stem_edge->opos - base_edge->opos;
|
||||
|
||||
#ifdef FT_CONFIG_CHESTER_SERIF
|
||||
FT_Pos fitted_width = ah_compute_stem_width( hinter,
|
||||
vertical,
|
||||
dist,
|
||||
base_edge->flags,
|
||||
stem_edge->flags );
|
||||
|
||||
stem_edge->pos = base_edge->pos + fitted_width;
|
||||
#else
|
||||
stem_edge->pos = base_edge->pos +
|
||||
ah_compute_stem_width( hinter, vertical, dist );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -368,12 +509,61 @@
|
||||
|
||||
if ( !anchor )
|
||||
{
|
||||
#ifdef FT_CONFIG_CHESTER_STEM
|
||||
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 = ah_compute_stem_width( hinter, dimension, org_len,
|
||||
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 = ( org_center + 32 ) & -64;
|
||||
|
||||
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 = cur_pos1 + cur_len / 2;
|
||||
|
||||
}
|
||||
else
|
||||
edge->pos = ( edge->opos + 32 ) & -64;
|
||||
|
||||
anchor = edge;
|
||||
|
||||
edge->flags |= AH_EDGE_DONE;
|
||||
|
||||
ah_align_linked_edge( hinter, edge, edge2, dimension );
|
||||
#else /* !CHESTER_STEM */
|
||||
edge->pos = ( edge->opos + 32 ) & -64;
|
||||
anchor = edge;
|
||||
|
||||
edge->flags |= AH_EDGE_DONE;
|
||||
|
||||
ah_align_linked_edge( hinter, edge, edge2, dimension );
|
||||
#endif /* !CHESTER_STEM */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -385,7 +575,70 @@
|
||||
org_len = edge2->opos - edge->opos;
|
||||
org_center = org_pos + ( org_len >> 1 );
|
||||
|
||||
#ifdef FT_CONFIG_CHESTER_SERIF
|
||||
cur_len = ah_compute_stem_width( hinter, dimension, org_len,
|
||||
edge->flags, edge2->flags );
|
||||
#else /* !CHESTER_SERIF */
|
||||
cur_len = ah_compute_stem_width( hinter, dimension, org_len );
|
||||
#endif /* !CHESTER_SERIF */
|
||||
|
||||
#ifdef FT_CONFIG_CHESTER_STEM
|
||||
if ( cur_len < 96 )
|
||||
{
|
||||
FT_Pos u_off, d_off;
|
||||
|
||||
|
||||
cur_pos1 = ( org_center + 32 ) & -64;
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
org_pos = anchor->pos + (edge->opos - anchor->opos);
|
||||
org_len = edge2->opos - edge->opos;
|
||||
org_center = org_pos + ( org_len >> 1 );
|
||||
|
||||
cur_len = ah_compute_stem_width( hinter, dimension, org_len,
|
||||
edge->flags, edge2->flags );
|
||||
|
||||
cur_pos1 = ( org_pos + 32 ) & -64;
|
||||
delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center );
|
||||
if ( delta1 < 0 )
|
||||
delta1 = -delta1;
|
||||
|
||||
cur_pos2 = ( ( org_pos + org_len + 32 ) & -64 ) - 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;
|
||||
}
|
||||
|
||||
#else /* !CHESTER_STEM */
|
||||
|
||||
cur_pos1 = ( org_pos + 32 ) & -64;
|
||||
delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center );
|
||||
@ -400,6 +653,8 @@
|
||||
edge->pos = ( delta1 <= delta2 ) ? cur_pos1 : cur_pos2;
|
||||
edge2->pos = edge->pos + cur_len;
|
||||
|
||||
#endif /* !CHESTER_STEM */
|
||||
|
||||
edge->flags |= AH_EDGE_DONE;
|
||||
edge2->flags |= AH_EDGE_DONE;
|
||||
|
||||
|
@ -385,12 +385,26 @@ FT_BEGIN_HEADER
|
||||
} AH_OutlineRec, *AH_Outline;
|
||||
|
||||
|
||||
#define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
|
||||
#define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
|
||||
#define AH_BLUE_SMALL_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* xzroesc */
|
||||
#define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
|
||||
#define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
|
||||
#define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
|
||||
#ifdef FT_CONFIG_CHESTER_SMALL_F
|
||||
|
||||
# define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
|
||||
# define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
|
||||
# define AH_BLUE_SMALL_F_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* fijkdbh */
|
||||
# define AH_BLUE_SMALL_TOP ( AH_BLUE_SMALL_F_TOP + 1 ) /* xzroesc */
|
||||
# define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
|
||||
# define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
|
||||
# define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
|
||||
|
||||
#else /* !CHESTER_SMALL_F */
|
||||
|
||||
# define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
|
||||
# define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
|
||||
# define AH_BLUE_SMALL_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1) /* xzroesc */
|
||||
# define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
|
||||
# define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
|
||||
# define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
|
||||
|
||||
#endif /* !CHESTER_SMALL_F */
|
||||
|
||||
typedef FT_Int AH_Blue;
|
||||
|
||||
|
@ -566,16 +566,27 @@
|
||||
size->ttmetrics.y_ratio = 0x10000L;
|
||||
}
|
||||
|
||||
#ifdef FT_CONFIG_CHESTER_ASCENDER
|
||||
|
||||
/* Compute root ascender, descender, test height, and max_advance */
|
||||
metrics->ascender = ( FT_MulFix( face->root.ascender,
|
||||
metrics->y_scale ) + 63 ) & -64;
|
||||
metrics->descender = ( FT_MulFix( face->root.descender,
|
||||
metrics->y_scale ) + 0 ) & -64;
|
||||
#else /* !CHESTER_ASCENDER */
|
||||
/* Compute root ascender, descender, test height, and max_advance */
|
||||
metrics->ascender = ( FT_MulFix( face->root.ascender,
|
||||
metrics->y_scale ) + 32 ) & -64;
|
||||
metrics->descender = ( FT_MulFix( face->root.descender,
|
||||
metrics->y_scale ) + 32 ) & -64;
|
||||
#endif /* !CHESTER_ASCENDER */
|
||||
|
||||
metrics->height = ( FT_MulFix( face->root.height,
|
||||
metrics->y_scale ) + 32 ) & -64;
|
||||
metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
|
||||
metrics->x_scale ) + 32 ) & -64;
|
||||
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
|
||||
/* set to `invalid' by default */
|
||||
size->strike_index = 0xFFFFU;
|
||||
|
Loading…
Reference in New Issue
Block a user