diff --git a/src/autohint/ahglyph.c b/src/autohint/ahglyph.c index 348ee8e32..873dc2d1b 100644 --- a/src/autohint/ahglyph.c +++ b/src/autohint/ahglyph.c @@ -68,6 +68,134 @@ } + /* this function is used by ah_get_orientation (see below) to test */ + /* the fill direction of a given bbox extrema.. */ + static + int ah_test_extrema( FT_Outline* outline, + int n ) + { + FT_Vector *prev, *cur, *next; + FT_Pos product; + FT_Int first, last, c; + + + /* we need to compute the `previous' and `next' point */ + /* for these extrema. */ + cur = outline->points + n; + prev = cur - 1; + next = cur + 1; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + last = outline->contours[c]; + + if ( n == first ) + prev = outline->points + last; + + if ( n == last ) + next = outline->points + first; + + first = last + 1; + } + + product = FT_MulDiv( cur->x - prev->x, /* in.x */ + next->y - cur->y, /* out.y */ + 0x40 ) + - + FT_MulDiv( cur->y - prev->y, /* in.y */ + next->x - cur->x, /* out.x */ + 0x40 ); + + if ( product ) + product = product > 0 ? 2 : 1; + + return product; + } + + + /* Compute the orientation of path filling. It differs between TrueType */ + /* and Type1 formats. We could use the `ft_outline_reverse_fill' flag, */ + /* but it is better to re-compute it directly (it seems that this flag */ + /* isn't correctly set for some weird composite glyphs currently). */ + /* */ + /* We do this by computing bounding box points, and computing their */ + /* curvature. */ + /* */ + /* The function returns either 1 or -1. */ + /* */ + static + int ah_get_orientation( FT_Outline* outline ) + { + FT_BBox box; + FT_BBox indices; + int n, last; + + + indices.xMin = -1; + indices.yMin = -1; + indices.xMax = -1; + indices.yMax = -1; + + box.xMin = box.yMin = 32767; + box.xMax = box.yMax = -32768; + + /* is it empty ? */ + if ( outline->n_contours < 1 ) + return 1; + + last = outline->contours[outline->n_contours - 1]; + + for ( n = 0; n <= last; n++ ) + { + FT_Pos x, y; + + + x = outline->points[n].x; + if ( x < box.xMin ) + { + box.xMin = x; + indices.xMin = n; + } + if ( x > box.xMax ) + { + box.xMax = x; + indices.xMax = n; + } + + y = outline->points[n].y; + if ( y < box.yMin ) + { + box.yMin = y; + indices.yMin = n; + } + if ( y > box.yMax ) + { + box.yMax = y; + indices.yMax = n; + } + } + + /* test orientation of the xmin */ + n = ah_test_extrema( outline, indices.xMin ); + if (n) goto Exit; + + n = ah_test_extrema( outline, indices.yMin ); + if (n) goto Exit; + + n = ah_test_extrema( outline, indices.xMax ); + if (n) goto Exit; + + n = ah_test_extrema( outline, indices.yMax ); + if (!n) + n = 1; + + Exit: + return n; + } + + + /*************************************************************************/ /* */ /* */ @@ -218,6 +346,20 @@ outline->num_hsegments = 0; outline->num_vsegments = 0; +#if 1 + /* we can't rely on the value of FT_Outline.flags to know the */ + /* fill direction used for a glyph, given that some fonts are */ + /* broken (e.g. the Arphic ones..). We thus recompute it each */ + /* time we need to.. */ + outline->vert_major_dir = ah_dir_up; + outline->horz_major_dir = ah_dir_left; + + if ( ah_get_orientation( source ) > 1 ) + { + outline->vert_major_dir = ah_dir_down; + outline->horz_major_dir = ah_dir_right; + } +#else /* Compute the vertical and horizontal major directions; this is */ /* currently done by inspecting the `ft_outline_reverse_fill' flag. */ /* However, some fonts have improper glyphs, and it'd be a good idea */ @@ -230,11 +372,13 @@ outline->vert_major_dir = ah_dir_down; outline->horz_major_dir = ah_dir_right; } - +#endif outline->x_scale = face->size->metrics.x_scale; outline->y_scale = face->size->metrics.y_scale; points = outline->points; + if (outline->num_points == 0) + goto Exit; { /* do one thing at a time -- it is easier to understand, and */