ref: 14018b4af9c4274e0b89cd31e94ef78109f0d912
parent: 57ce0bee449bfc6fa418f1492ef23cb4baeb7c95
author: David Turner <[email protected]>
date: Sun Jan 12 13:26:10 EST 2003
2003-01-11 David Chester <[email protected]> * 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 <[email protected]> * include/freetype/internal/fnttypes.h: fixed a structure field definition to avoid memory overwrites
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2003-01-11 David Chester <[email protected]>
+
+ * 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 <[email protected]>
+
+ * include/freetype/internal/fnttypes.h: fixed a structure field
+ definition to avoid memory overwrites
+
2003-01-08 Huw Dawies <[email protected]>
* src/winfonts/winfnt.c: read 16 bytes into "reserved2", not "reserved"
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -469,6 +469,17 @@
/* */
+#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
--- a/include/freetype/internal/fnttypes.h
+++ b/include/freetype/internal/fnttypes.h
@@ -108,7 +108,7 @@
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;
--- a/src/autohint/ahglobal.c
+++ b/src/autohint/ahglobal.c
@@ -32,6 +32,9 @@
{
"THEZOCQS",
"HEZLOCUS",
+#ifdef FT_CONFIG_CHESTER_SMALL_F
+ "fijkdbh",
+#endif
"xzroesc",
"xzroesc",
"pqgjy"
--- a/src/autohint/ahglobal.h
+++ b/src/autohint/ahglobal.h
@@ -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 */
--- a/src/autohint/ahglyph.c
+++ b/src/autohint/ahglyph.c
@@ -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++ )
{
--- a/src/autohint/ahhint.c
+++ b/src/autohint/ahhint.c
@@ -88,7 +88,138 @@
/* 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,
FT_Pos width )
@@ -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,6 +509,54 @@
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;
@@ -374,6 +563,7 @@
edge->flags |= AH_EDGE_DONE;
ah_align_linked_edge( hinter, edge, edge2, dimension );
+#endif /* !CHESTER_STEM */
}
else
{
@@ -385,8 +575,71 @@
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 );
if ( delta1 < 0 )
@@ -399,6 +652,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;
--- a/src/autohint/ahtypes.h
+++ b/src/autohint/ahtypes.h
@@ -385,12 +385,26 @@
} 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;
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -566,15 +566,26 @@
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 */