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
This commit is contained in:
David Turner 2007-03-26 12:39:25 +00:00
parent 3b242d3619
commit f58caa09bc
2 changed files with 67 additions and 52 deletions

View File

@ -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 <mpsuzuki@hiroshima-u.ac.jp>
* builds/unix/ftconfig.in: disable Carbon framework dependency on

View File

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