ref: caa48b0db1a4a79f08670d45027988799b2e4c3c
parent: 1fd2bc8c37a053b5de531ba1380c18b014a94d9b
author: Werner Lemberg <[email protected]>
date: Sat Mar 5 14:47:07 EST 2016
[autofit] Avoid excessive stem length rounding (#25392). * src/autofit/aflatin.c (af_latin_compute_stem_width): Add argument to pass difference between hinted and unhinted position of base point; use this to adjust the stem width depending on the PPEM so that it doesn't become too large under certain circumstances. Update all callers using value 0 for this argument except... (af_latin_align_linked_edge): Pass position delta of base point to `af_latin_compute_stem_width'.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2016-03-05 Werner Lemberg <[email protected]>
+
+ [autofit] Avoid excessive stem length rounding (#25392).
+
+ * src/autofit/aflatin.c (af_latin_compute_stem_width): Add argument
+ to pass difference between hinted and unhinted position of base
+ point; use this to adjust the stem width depending on the PPEM so
+ that it doesn't become too large under certain circumstances.
+ Update all callers using value 0 for this argument except...
+ (af_latin_align_linked_edge): Pass position delta of base point to
+ `af_latin_compute_stem_width'.
+
2016-03-05 J Raynor <[email protected]>
Make FreeType compile on AIX out of the box.
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -2504,6 +2504,7 @@
af_latin_compute_stem_width( AF_GlyphHints hints,
AF_Dimension dim,
FT_Pos width,
+ FT_Pos base_delta,
FT_UInt base_flags,
FT_UInt stem_flags )
{
@@ -2510,6 +2511,7 @@
AF_LatinMetrics metrics = (AF_LatinMetrics)hints->metrics;
AF_LatinAxis axis = &metrics->axis[dim];
FT_Pos dist = width;
+ FT_Pos bdelta = 0;
FT_Int sign = 0;
FT_Int vertical = ( dim == AF_DIMENSION_VERT );
@@ -2524,6 +2526,32 @@
sign = 1;
}
+ /* A stem's end position depends on two values: the start position */
+ /* and the stem length. The former gets usually rounded to the grid, */
+ /* while the latter gets rounded also if it exceeds a certain length */
+ /* (see below in this function). This `double rounding' can lead to */
+ /* a great difference to the original, unhinted position; this */
+ /* normally doesn't matter for large PPEM values, but for small sizes */
+ /* it can easily make outlines collide. For this reason, we adjust */
+ /* the stem length by a small amount depending on the PPEM value in */
+ /* case the former and latter rounding both point into the same */
+ /* direction. */
+
+ if ( ( ( width > 0 ) && ( base_delta > 0 ) ) ||
+ ( ( width < 0 ) && ( base_delta < 0 ) ) )
+ {
+ FT_UInt ppem = metrics->root.scaler.face->size->metrics.x_ppem;
+
+
+ if ( ppem < 10 )
+ bdelta = base_delta;
+ else if ( ppem < 30 )
+ bdelta = ( base_delta * (FT_Pos)( 30 - ppem ) ) / 20;
+
+ if ( bdelta < 0 )
+ bdelta = -bdelta;
+ }
+
if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
{
@@ -2581,7 +2609,7 @@
dist += delta;
}
else
- dist = ( dist + 32 ) & ~63;
+ dist = ( dist - bdelta + 32 ) & ~63;
}
}
else
@@ -2670,13 +2698,19 @@
AF_Edge base_edge,
AF_Edge stem_edge )
{
- FT_Pos dist = stem_edge->opos - base_edge->opos;
+ FT_Pos dist, base_delta;
+ FT_Pos fitted_width;
- FT_Pos fitted_width = af_latin_compute_stem_width( hints, dim, dist,
- base_edge->flags,
- stem_edge->flags );
+ dist = stem_edge->opos - base_edge->opos;
+ base_delta = base_edge->pos - base_edge->opos;
+ fitted_width = af_latin_compute_stem_width( hints, dim,
+ dist, base_delta,
+ base_edge->flags,
+ stem_edge->flags );
+
+
stem_edge->pos = base_edge->pos + fitted_width;
FT_TRACE5(( " LINK: edge %d (opos=%.2f) linked to %.2f,"
@@ -2878,7 +2912,8 @@
org_len = edge2->opos - edge->opos;
- cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+ cur_len = af_latin_compute_stem_width( hints, dim,
+ org_len, 0,
edge->flags,
edge2->flags );
@@ -2947,7 +2982,8 @@
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
- cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+ cur_len = af_latin_compute_stem_width( hints, dim,
+ org_len, 0,
edge->flags,
edge2->flags );
@@ -3007,7 +3043,8 @@
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
- cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+ cur_len = af_latin_compute_stem_width( hints, dim,
+ org_len, 0,
edge->flags,
edge2->flags );