[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.
This commit is contained in:
Werner Lemberg 2013-07-19 23:11:23 +02:00
parent 778a7e6a36
commit 05c1421f8d
2 changed files with 55 additions and 7 deletions

View File

@ -1,4 +1,35 @@
2013-07-18 Behdad Esfahbod <behdad@google.com>
2013-07-19 Werner Lemberg <wl@gnu.org>
[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 <behdad@google.com>
[sfnt] `sbix' fix-ups.

View File

@ -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" ));
}