[autofit] Fix handling of neutral blue zones in stems.

* src/autofit/afhints.h (AF_Edge_Flags): New value
`AF_EDGE_NEUTRAL'.

* src/autofit/aflatin.c (af_latin_hints_compute_blue_edges): Trace
neutral blue zones with AF_EDGE_NEUTRAL.
(af_latin_hint_edges): Skip neutral blue zones if necessary.
This commit is contained in:
Werner Lemberg 2014-05-01 07:16:05 +02:00
parent ccfc4b4c4e
commit 63bef9a588
3 changed files with 70 additions and 21 deletions

View File

@ -1,3 +1,14 @@
2014-05-01 Werner Lemberg <wl@gnu.org>
[autofit] Fix handling of neutral blue zones in stems.
* src/autofit/afhints.h (AF_Edge_Flags): New value
`AF_EDGE_NEUTRAL'.
* src/autofit/aflatin.c (af_latin_hints_compute_blue_edges): Trace
neutral blue zones with AF_EDGE_NEUTRAL.
(af_latin_hint_edges): Skip neutral blue zones if necessary.
2014-04-28 Werner Lemberg <wl@gnu.org>
[autofit] Introduce neutral blue zones to the latin module.

View File

@ -247,7 +247,8 @@ FT_BEGIN_HEADER
AF_EDGE_NORMAL = 0,
AF_EDGE_ROUND = 1 << 0,
AF_EDGE_SERIF = 1 << 1,
AF_EDGE_DONE = 1 << 2
AF_EDGE_DONE = 1 << 2,
AF_EDGE_NEUTRAL = 1 << 3 /* set if edge aligns to a neutral blue zone */
} AF_Edge_Flags;

View File

@ -1842,6 +1842,7 @@
{
FT_UInt bb;
AF_Width best_blue = NULL;
FT_Bool best_blue_is_neutral = 0;
FT_Pos best_dist; /* initial threshold */
@ -1856,7 +1857,7 @@
for ( bb = 0; bb < latin->blue_count; bb++ )
{
AF_LatinBlue blue = latin->blues + bb;
FT_Bool is_top_blue, is_major_dir;
FT_Bool is_top_blue, is_neutral_blue, is_major_dir;
/* skip inactive blue zones (i.e., those that are too large) */
@ -1867,12 +1868,15 @@
/* direction); if it is a bottom zone, check for left edges (in */
/* the major direction) -- this assumes the TrueType convention */
/* for the orientation of contours */
is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
is_top_blue =
(FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
is_neutral_blue =
(FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0);
is_major_dir =
FT_BOOL( edge->dir == axis->major_dir );
/* neutral blue zones are handled for both directions */
if ( is_top_blue ^ is_major_dir ||
blue->flags & AF_LATIN_BLUE_NEUTRAL )
if ( is_top_blue ^ is_major_dir || is_neutral_blue )
{
FT_Pos dist;
@ -1887,6 +1891,7 @@
{
best_dist = dist;
best_blue = &blue->ref;
best_blue_is_neutral = is_neutral_blue;
}
/* now compare it to the overshoot position and check whether */
@ -1896,7 +1901,7 @@
/* neutral blue zone) */
if ( edge->flags & AF_EDGE_ROUND &&
dist != 0 &&
!( blue->flags & AF_LATIN_BLUE_NEUTRAL ) )
!is_neutral_blue )
{
FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
@ -1912,6 +1917,7 @@
{
best_dist = dist;
best_blue = &blue->shoot;
best_blue_is_neutral = is_neutral_blue;
}
}
}
@ -1919,7 +1925,11 @@
}
if ( best_blue )
{
edge->blue_edge = best_blue;
if ( best_blue_is_neutral )
edge->flags |= AF_EDGE_NEUTRAL;
}
}
}
@ -2304,14 +2314,41 @@
if ( edge->flags & AF_EDGE_DONE )
continue;
blue = edge->blue_edge;
edge1 = NULL;
edge2 = edge->link;
/*
* If a stem contains both a neutral and a non-neutral blue zone,
* skip the neutral one. Otherwise, outlines with different
* directions might be incorrectly aligned at the same vertical
* position.
*
* If we have two neutral blue zones, skip one of them.
*
*/
if ( edge->blue_edge && edge2 && edge2->blue_edge )
{
FT_Byte neutral = edge->flags & AF_EDGE_NEUTRAL;
FT_Byte neutral2 = edge2->flags & AF_EDGE_NEUTRAL;
if ( ( neutral && neutral2 ) || neutral2 )
{
edge2->blue_edge = NULL;
edge2->flags &= ~AF_EDGE_NEUTRAL;
}
else if ( neutral )
{
edge->blue_edge = NULL;
edge->flags &= ~AF_EDGE_NEUTRAL;
}
}
blue = edge->blue_edge;
if ( blue )
edge1 = edge;
/* flip edges if the other stem is aligned to a blue zone */
/* flip edges if the other edge is aligned to a blue zone */
else if ( edge2 && edge2->blue_edge )
{
blue = edge2->blue_edge;