From f58caa09bc57f7f88333b9268b5ae0d12a1d70fe Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 26 Mar 2007 12:39:25 +0000 Subject: [PATCH] fix autofit's blue zone computations: it now ignores 1-point contours that correspond to mark attach coordinates, and not to the real glyph outline --- ChangeLog | 5 ++ src/autofit/aflatin.c | 114 +++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 429c6d766..91de82af1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ * src/truetype/ttinterp.c: last fix for the MD instruction bytecode and remove the FIX_BYTECODE macros from the sources. Woot, this looks good. + * src/autofit/aflatin.c (af_latin_metrics_init_blues): fix blues computations + in order to ignore 1-point contours. These are never rasterized and in certain + fonts correspond to mark-attach points that are very far from the glyph's + real outline, ruining the computation. + 2007-03-26 suzuki toshiya * builds/unix/ftconfig.in: disable Carbon framework dependency on diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 4fce36fa7..ce0ca8532 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -193,10 +193,8 @@ for ( ; p < limit && *p; p++ ) { FT_UInt glyph_index; - FT_Vector* extremum; + FT_Int best_point, best_y, best_first, best_last; FT_Vector* points; - FT_Vector* point_limit; - FT_Vector* point; FT_Bool round; @@ -213,85 +211,97 @@ /* now compute min or max point indices and coordinates */ points = glyph->outline.points; - point_limit = points + glyph->outline.n_points; - point = points; - extremum = point; - point++; + best_point = -1; + best_y = 0; /* make compiler happy */ + best_first = 0; /* ditto */ + best_last = 0; /* ditto */ - if ( AF_LATIN_IS_TOP_BLUE( bb ) ) { - for ( ; point < point_limit; point++ ) - if ( point->y > extremum->y ) - extremum = point; - } - else - { - for ( ; point < point_limit; point++ ) - if ( point->y < extremum->y ) - extremum = point; - } + FT_Int nn; + FT_Int first = 0; + FT_Int last = -1; - AF_LOG(( "%5d", (int)extremum->y )); + + for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ ) + { + FT_Int old_best_point = best_point; + FT_Int pp; + + last = glyph->outline.contours[nn]; + + /* avoid 1-point contours, they're never rasterized and + * in some fonts, they correspond to mark attachement + * points that are way outside the glyph's real outline. + */ + if (last <= first) + continue; + + if ( AF_LATIN_IS_TOP_BLUE( bb ) ) + { + for ( pp = first; pp <= last; pp++ ) + if ( best_point < 0 || points[pp].y > best_y ) + { + best_point = pp; + best_y = points[pp].y; + } + } + else + { + for ( pp = first; pp <= last; pp++ ) + if ( best_point < 0 || points[pp].y < best_y ) + { + best_point = pp; + best_y = points[pp].y; + } + } + + if (best_point != old_best_point) + { + best_first = first; + best_last = last; + } + } + AF_LOG(( "%5d", best_y )); + } /* now, check whether the point belongs to a straight or round */ /* segment; we first need to find in which contour the extremum */ /* lies, then see its previous and next points */ { - FT_Int idx = (FT_Int)( extremum - points ); - FT_Int n; - FT_Int first, last, prev, next, end; + FT_Int prev, next; FT_Pos dist; - last = -1; - first = 0; - - for ( n = 0; n < glyph->outline.n_contours; n++ ) - { - end = glyph->outline.contours[n]; - if ( end >= idx ) - { - last = end; - break; - } - first = end + 1; - } - - /* XXX: should never happen! */ - if ( last < 0 ) - continue; - /* now look for the previous and next points that are not on the */ /* same Y coordinate. Threshold the `closeness'... */ - - prev = idx; + prev = best_point; next = prev; do { - if ( prev > first ) + if ( prev > best_first ) prev--; else - prev = last; + prev = best_last; - dist = points[prev].y - extremum->y; + dist = points[prev].y - best_y; if ( dist < -5 || dist > 5 ) break; - } while ( prev != idx ); + } while ( prev != best_point ); do { - if ( next < last ) + if ( next < best_last ) next++; else - next = first; + next = best_first; - dist = points[next].y - extremum->y; + dist = points[next].y - best_y; if ( dist < -5 || dist > 5 ) break; - } while ( next != idx ); + } while ( next != best_point ); /* now, set the `round' flag depending on the segment's kind */ round = FT_BOOL( @@ -302,9 +312,9 @@ } if ( round ) - rounds[num_rounds++] = extremum->y; + rounds[num_rounds++] = best_y; else - flats[num_flats++] = extremum->y; + flats[num_flats++] = best_y; } AF_LOG(( "\n" ));