[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:
parent
ccfc4b4c4e
commit
63bef9a588
11
ChangeLog
11
ChangeLog
@ -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.
|
||||
|
@ -244,10 +244,11 @@ FT_BEGIN_HEADER
|
||||
/* edge hint flags */
|
||||
typedef enum AF_Edge_Flags_
|
||||
{
|
||||
AF_EDGE_NORMAL = 0,
|
||||
AF_EDGE_ROUND = 1 << 0,
|
||||
AF_EDGE_SERIF = 1 << 1,
|
||||
AF_EDGE_DONE = 1 << 2
|
||||
AF_EDGE_NORMAL = 0,
|
||||
AF_EDGE_ROUND = 1 << 0,
|
||||
AF_EDGE_SERIF = 1 << 1,
|
||||
AF_EDGE_DONE = 1 << 2,
|
||||
AF_EDGE_NEUTRAL = 1 << 3 /* set if edge aligns to a neutral blue zone */
|
||||
|
||||
} AF_Edge_Flags;
|
||||
|
||||
|
@ -1841,8 +1841,9 @@
|
||||
for ( ; edge < edge_limit; edge++ )
|
||||
{
|
||||
FT_UInt bb;
|
||||
AF_Width best_blue = NULL;
|
||||
FT_Pos best_dist; /* initial threshold */
|
||||
AF_Width best_blue = NULL;
|
||||
FT_Bool best_blue_is_neutral = 0;
|
||||
FT_Pos best_dist; /* initial threshold */
|
||||
|
||||
|
||||
/* compute the initial threshold as a fraction of the EM size */
|
||||
@ -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;
|
||||
|
||||
@ -1885,8 +1889,9 @@
|
||||
dist = FT_MulFix( dist, scale );
|
||||
if ( dist < best_dist )
|
||||
{
|
||||
best_dist = dist;
|
||||
best_blue = &blue->ref;
|
||||
best_dist = dist;
|
||||
best_blue = &blue->ref;
|
||||
best_blue_is_neutral = is_neutral_blue;
|
||||
}
|
||||
|
||||
/* now compare it to the overshoot position and check whether */
|
||||
@ -1894,9 +1899,9 @@
|
||||
/* reference position of a top zone, or under the reference */
|
||||
/* position of a bottom zone (provided we don't have a */
|
||||
/* neutral blue zone) */
|
||||
if ( edge->flags & AF_EDGE_ROUND &&
|
||||
dist != 0 &&
|
||||
!( blue->flags & AF_LATIN_BLUE_NEUTRAL ) )
|
||||
if ( edge->flags & AF_EDGE_ROUND &&
|
||||
dist != 0 &&
|
||||
!is_neutral_blue )
|
||||
{
|
||||
FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
|
||||
|
||||
@ -1910,8 +1915,9 @@
|
||||
dist = FT_MulFix( dist, scale );
|
||||
if ( dist < best_dist )
|
||||
{
|
||||
best_dist = dist;
|
||||
best_blue = &blue->shoot;
|
||||
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;
|
||||
@ -2378,7 +2415,7 @@
|
||||
/* this should not happen, but it's better to be safe */
|
||||
if ( edge2->blue_edge )
|
||||
{
|
||||
FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2-edges ));
|
||||
FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2 - edges ));
|
||||
|
||||
af_latin_align_linked_edge( hints, dim, edge2, edge );
|
||||
edge->flags |= AF_EDGE_DONE;
|
||||
|
Loading…
Reference in New Issue
Block a user