diff --git a/ChangeLog b/ChangeLog index f525b2d66..592ffca97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,35 @@ -2013-07-18 Behdad Esfahbod +2013-07-19 Werner Lemberg + + [autofit] Fix segment classification for blue zones. + + The old code (essentially unchanged since the very beginning) + incorrectly handled this configuration + + x -o- x + / \ + / \ + / \ + o o + + as flat and this + + o o + / / + x| x| + | | + o---------------o + + as round. (`o' and `x' are on and off points, respectively). + + This is a major change which should improve the rendering results + enormously for many TrueType fonts, especially in the range approx. + 20-40ppem, fixing the appearance of many overshoots. + + * src/autofit/aflatin.c (af_latin_metrics_init_blues): Look at the + first and last points of the segment, not the points right before + and after. + +2013-07-19 Behdad Esfahbod [sfnt] `sbix' fix-ups. diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index a5d80c1ca..ec54b7095 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -328,10 +328,14 @@ { FT_Pos best_x = points[best_point].x; FT_Int prev, next; + FT_Int best_segment_first, best_segment_last; FT_Int best_on_point_first, best_on_point_last; FT_Pos dist; + best_segment_first = best_point; + best_segment_last = best_point; + if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON ) { best_on_point_first = best_point; @@ -343,8 +347,9 @@ best_on_point_last = -1; } - /* look for the previous and next points that are not on the */ - /* same Y coordinate, then threshold the `closeness'... */ + /* look for the previous and next points on the contour */ + /* that are not on the same Y coordinate, then threshold */ + /* the `closeness'... */ prev = best_point; next = prev; @@ -362,6 +367,8 @@ if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist ) break; + best_segment_first = prev; + if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON ) { best_on_point_first = prev; @@ -383,6 +390,8 @@ if ( FT_ABS( points[next].x - best_x ) <= 20 * dist ) break; + best_segment_last = next; + if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON ) { best_on_point_last = next; @@ -392,8 +401,14 @@ } while ( next != best_point ); - /* now set the `round' flag depending on the segment's kind */ - /* (value 8 is heuristic) */ + /* now set the `round' flag depending on the segment's kind: */ + /* */ + /* - if the horizontal distance between the first and last */ + /* `on' point is larger than upem/8 (value 8 is heuristic) */ + /* we have a flat segment */ + /* - if either the first or the last point of the segment is */ + /* an `off' point, the segment is round, otherwise it is */ + /* flat */ if ( best_on_point_first >= 0 && best_on_point_last >= 0 && (FT_UInt)( FT_ABS( points[best_on_point_last].x - @@ -402,8 +417,10 @@ round = 0; else round = FT_BOOL( - FT_CURVE_TAG( outline.tags[prev] ) != FT_CURVE_TAG_ON || - FT_CURVE_TAG( outline.tags[next] ) != FT_CURVE_TAG_ON ); + FT_CURVE_TAG( outline.tags[best_segment_first] ) != + FT_CURVE_TAG_ON || + FT_CURVE_TAG( outline.tags[best_segment_last] ) != + FT_CURVE_TAG_ON ); FT_TRACE5(( " (%s)\n", round ? "round" : "flat" )); }