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;