From 7afd3d6b6fa9b6fcd37a6efa11c5e1e1e6e3956c Mon Sep 17 00:00:00 2001 From: David Turner Date: Wed, 21 Aug 2002 21:34:59 +0000 Subject: [PATCH] * src/pshinter/pshalgo3.c, src/autohint/ahangles.c, src/autohint/ahangles.h, src/autohint/ahglyph.c, src/autohint/ahhint.c, src/autohint/ahtypes.h: the automatic and Postscript hinter now automatically detect inflection points in glyph outlines and treats them specially. This is very useful to prevent nasty effect like the disappearing diagonals of "S" and "s" in many, many fonts.. --- src/autohint/ahangles.c | 16 ++++++ src/autohint/ahangles.h | 5 ++ src/autohint/ahglyph.c | 115 ++++++++++++++++++++++++++++++++++++++++ src/autohint/ahhint.c | 3 +- src/autohint/ahtypes.h | 1 + src/pshinter/pshalgo3.c | 3 +- 6 files changed, 141 insertions(+), 2 deletions(-) diff --git a/src/autohint/ahangles.c b/src/autohint/ahangles.c index 1a13b2771..a4ef84299 100644 --- a/src/autohint/ahangles.c +++ b/src/autohint/ahangles.c @@ -127,4 +127,20 @@ } + FT_LOCAL_DEF( AH_Angle ) + ah_angle_diff( AH_Angle angle1, + AH_Angle angle2 ) + { + AH_Angle delta; + + delta = ( angle2 - angle1 ); + if ( delta < 0 ) + delta += AH_2PI; + + if ( delta > AH_PI ) + delta -= AH_2PI; + + return delta; + } + /* END */ diff --git a/src/autohint/ahangles.h b/src/autohint/ahangles.h index d509e0039..f46bfaad7 100644 --- a/src/autohint/ahangles.h +++ b/src/autohint/ahangles.h @@ -51,6 +51,11 @@ FT_BEGIN_HEADER ah_angle( FT_Vector* v ); + FT_LOCAL( AH_Angle ) + ah_angle_diff( AH_Angle angle1, + AH_Angle angle2 ); + + FT_END_HEADER #endif /* __AHANGLES_H__ */ diff --git a/src/autohint/ahglyph.c b/src/autohint/ahglyph.c index 2f0582e91..8939b7411 100644 --- a/src/autohint/ahglyph.c +++ b/src/autohint/ahglyph.c @@ -674,6 +674,120 @@ } } + /* compute all inflex points in a given glyph */ + static void + ah_outline_compute_inflections( AH_Outline* outline ) + { + AH_Point** contour = outline->contours; + AH_Point** contour_limit = contour + outline->num_contours; + + /* load original coordinates in (u,v) */ + ah_setup_uv( outline, ah_uv_fxy ); + + /* do each contour separately */ + for ( ; contour < contour_limit; contour++ ) + { + FT_Vector vec; + AH_Point* point = contour[0]; + AH_Point* first = point; + AH_Point* start = point; + AH_Point* end = point; + AH_Point* before; + AH_Point* after; + AH_Angle angle_in, angle_seg, angle_out; + AH_Angle diff_in, diff_out; + FT_Int finished = 0; + + /* compute first segment in contour */ + first = point; + + start = end = first; + do + { + end = end->next; + if ( end == first ) + goto Skip; + } + while ( end->u == first->u && end->v == first->v ); + + vec.x = end->u - start->u; + vec.y = end->v - start->v; + angle_seg = ah_angle( &vec ); + + /* extend the segment start whenever possible */ + before = start; + do + { + do + { + start = before; + before = before->prev; + if ( before == first ) + goto Skip; + } + while ( before->u == start->u && before->v == start->v ); + + vec.x = start->u - before->u; + vec.y = start->v - before->v; + angle_in = ah_angle( &vec ); + } + while ( angle_in == angle_seg ); + + first = start; + diff_in = ah_angle_diff( angle_in, angle_seg ); + + /* now, process all segments in the contour */ + do + { + /* first, extend current segment's end whenever possible */ + after = end; + do + { + do + { + end = after; + after = after->next; + if ( after == first ) + finished = 1; + } + while ( end->u == after->u && end->v == after->v ); + + vec.x = after->u - end->u; + vec.y = after->v - end->v; + angle_out = ah_angle( &vec ); + } + while ( angle_out == angle_seg ); + + diff_out = ah_angle_diff( angle_seg, angle_out ); + + if ( diff_in ^ diff_out < 0 ) + { + /* diff_in and diff_out have different signs, we have */ + /* inflection points here... */ + + do + { + start->flags |= ah_flag_inflection; + start = start->next; + } + while ( start != end ); + + start->flags |= ah_flag_inflection; + } + + start = end; + end = after; + angle_seg = angle_out; + diff_in = diff_out; + } + while ( !finished ); + + Skip: + ; + } + } + + FT_LOCAL_DEF( void ) ah_outline_compute_segments( AH_Outline* outline ) @@ -1290,6 +1404,7 @@ ah_outline_compute_segments( outline ); ah_outline_link_segments ( outline ); ah_outline_compute_edges ( outline ); + ah_outline_compute_inflections( outline ); } diff --git a/src/autohint/ahhint.c b/src/autohint/ahhint.c index 243b4d0ce..0aa5f2e86 100644 --- a/src/autohint/ahhint.c +++ b/src/autohint/ahhint.c @@ -612,7 +612,8 @@ #ifndef AH_OPTION_NO_WEAK_INTERPOLATION /* if this point is candidate to weak interpolation, we will */ /* interpolate it after all strong points have been processed */ - if ( point->flags & ah_flag_weak_interpolation ) + if ( (point->flags & ah_flag_weak_interpolation) && + !(point->flags & ah_flag_inflection) ) continue; #endif diff --git a/src/autohint/ahtypes.h b/src/autohint/ahtypes.h index cd621012d..4c9165571 100644 --- a/src/autohint/ahtypes.h +++ b/src/autohint/ahtypes.h @@ -147,6 +147,7 @@ FT_BEGIN_HEADER /* weak interpolation */ #define ah_flag_weak_interpolation 256 +#define ah_flag_inflection 512 typedef FT_Int AH_Flags; diff --git a/src/pshinter/pshalgo3.c b/src/pshinter/pshalgo3.c index ccf5bc2d0..18ea48d38 100644 --- a/src/pshinter/pshalgo3.c +++ b/src/pshinter/pshalgo3.c @@ -1422,7 +1422,8 @@ point->dir_in != point->dir_out ) continue; - if ( !psh3_point_is_extremum( point ) ) + if ( !psh3_point_is_extremum( point ) && + !psh3_point_is_inflection( point ) ) continue; point->flags &= ~PSH3_POINT_SMOOTH;