[autofit] Introduce neutral blue zones to the latin module.

Such blue zones match either the top or the bottom of a contour.  We
need them for scripts where accent-like elements directly touch the
base character (for example, some vowel signs in Devanagari, cf.
U+0913 or U+0914).

* src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_NEUTRAL): New
property.

* src/autofit/afblue.h: Regenerated.

* src/autofit/aflatin.h (AF_LATIN_IS_NEUTRAL_BLUE): New macro.
(AF_LATIN_BLUE_NEUTRAL): New enumeration value.

* src/autofit/aflatin.c (af_latin_metrics_init_blues,
af_latin_hints_compute_blue_edges): Handle neutral blue zones.
This commit is contained in:
Werner Lemberg 2014-04-28 21:13:14 +02:00
parent abb3fcac85
commit ccfc4b4c4e
6 changed files with 95 additions and 32 deletions

View File

@ -1,3 +1,23 @@
2014-04-28 Werner Lemberg <wl@gnu.org>
[autofit] Introduce neutral blue zones to the latin module.
Such blue zones match either the top or the bottom of a contour. We
need them for scripts where accent-like elements directly touch the
base character (for example, some vowel signs in Devanagari, cf.
U+0913 or U+0914).
* src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_NEUTRAL): New
property.
* src/autofit/afblue.h: Regenerated.
* src/autofit/aflatin.h (AF_LATIN_IS_NEUTRAL_BLUE): New macro.
(AF_LATIN_BLUE_NEUTRAL): New enumeration value.
* src/autofit/aflatin.c (af_latin_metrics_init_blues,
af_latin_hints_compute_blue_edges): Handle neutral blue zones.
2014-04-25 Werner Lemberg <wl@gnu.org> 2014-04-25 Werner Lemberg <wl@gnu.org>
* src/autofit/hbshim.c: Partially revert commit from 2014-04-17. * src/autofit/hbshim.c: Partially revert commit from 2014-04-17.
@ -47,7 +67,7 @@
* src/autofit/afblue.hin (AF_BLUE_PROPERTY_CJK_FILL): Removed, no * src/autofit/afblue.hin (AF_BLUE_PROPERTY_CJK_FILL): Removed, no
longer used. longer used.
(AF_BLUE_PROPERTY_CJK_TOP, AF_BLUE_PROPERTY_CJK_HORIZ): Fix values. (AF_BLUE_PROPERTY_CJK_TOP, AF_BLUE_PROPERTY_CJK_HORIZ): Fix values.
This is error #3. This is error #3.
* src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
@ -57,7 +77,7 @@
values. values.
Improve tracing messages, synchronizing them with the latin Improve tracing messages, synchronizing them with the latin
auto-hinter. auto-hinter.
(af_cjk_hints_compute_blue_edges): Fix value of `is_top_right_blue'. (af_cjk_hints_compute_blue_edges): Fix value of `is_top_right_blue'.
This is error #2. This is error #2.
(af_cjk_align_linked_edge): Add tracing message. (af_cjk_align_linked_edge): Add tracing message.

View File

@ -34,11 +34,11 @@
// using C syntax. There can be only one string per line, thus the // using C syntax. There can be only one string per line, thus the
// starting and ending double quote must be the first and last character // starting and ending double quote must be the first and last character
// in the line, respectively, ignoring whitespace before and after the // in the line, respectively, ignoring whitespace before and after the
// string. If there are multiple strings (in multiple lines), they are // string. Space characters within the string are ignored too. If there
// concatenated to a single string. In the output, a string gets // are multiple strings (in multiple lines), they are concatenated to a
// represented as a series of singles bytes, followed by a zero byte. The // single string. In the output, a string gets represented as a series of
// enumeration values simply hold byte offsets to the start of the // singles bytes, followed by a zero byte. The enumeration values simply
// corresponding strings. // hold byte offsets to the start of the corresponding strings.
// //
// - Data blocks enclosed in balanced braces, which get copied verbatim and // - Data blocks enclosed in balanced braces, which get copied verbatim and
// which can span multiple lines. The opening brace of a block must be // which can span multiple lines. The opening brace of a block must be
@ -163,6 +163,10 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
// wider than 0.75 pixels (otherwise the blue zone gets ignored). All // wider than 0.75 pixels (otherwise the blue zone gets ignored). All
// entries must have `AF_BLUE_STRING_MAX' as the final line. // entries must have `AF_BLUE_STRING_MAX' as the final line.
// //
// During the glyph analysis, edges are sorted from bottom to top, and then
// sequentially checked, edge by edge, against the blue zones in the order
// given below.
//
// //
// latin auto-hinter // latin auto-hinter
// ----------------- // -----------------
@ -178,7 +182,22 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
// //
// LATIN_TOP // LATIN_TOP
// Take the maximum flat and round coordinate values of the blue string // Take the maximum flat and round coordinate values of the blue string
// characters. If not set, take the minimum values. // characters for computing the blue zone's reference and overshoot
// values.
//
// If not set, take the minimum values.
//
// LATIN_NEUTRAL
// Ignore round extrema and define the blue zone with flat values only.
// Both top and bottom of contours can match. This is useful for
// scripts like Devanagari where vowel signs attach to the base
// character and are implemented as components of composite glyphs.
//
// If not set, both round and flat extrema are taken into account.
// Additionally, only the top or the bottom of a contour can match,
// depending on the LATIN_TOP flag.
//
// Neutral blue zones should always follow non-neutral blue zones.
// //
// LATIN_X_HEIGHT // LATIN_X_HEIGHT
// Scale all glyphs vertically from the corresponding script to make the // Scale all glyphs vertically from the corresponding script to make the

View File

@ -132,12 +132,13 @@ FT_BEGIN_HEADER
/* Properties are specific to a writing system. We assume that a given */ /* Properties are specific to a writing system. We assume that a given */
/* blue string can't be used in more than a single writing system, which */ /* blue string can't be used in more than a single writing system, which */
/* is a safe bet. */ /* is a safe bet. */
#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) #define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 ) #define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 )
#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 ) #define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 )
#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 )
#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) #define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) #define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */
#define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP

View File

@ -96,12 +96,13 @@ FT_BEGIN_HEADER
/* Properties are specific to a writing system. We assume that a given */ /* Properties are specific to a writing system. We assume that a given */
/* blue string can't be used in more than a single writing system, which */ /* blue string can't be used in more than a single writing system, which */
/* is a safe bet. */ /* is a safe bet. */
#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) #define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 ) #define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 )
#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 ) #define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 )
#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 )
#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) #define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) #define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */
#define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP

View File

@ -306,6 +306,14 @@
have_flag = 1; have_flag = 1;
} }
if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
{
if ( have_flag )
FT_TRACE5(( ", " ));
FT_TRACE5(( "neutral" ));
have_flag = 1;
}
if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) ) if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
{ {
if ( have_flag ) if ( have_flag )
@ -697,6 +705,13 @@
FT_CURVE_TAG( outline.tags[best_segment_last] ) != FT_CURVE_TAG( outline.tags[best_segment_last] ) !=
FT_CURVE_TAG_ON ); FT_CURVE_TAG_ON );
if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
{
/* only use flat segments for a neutral blue zone */
FT_TRACE5(( " (round, skipped)\n" ));
continue;
}
FT_TRACE5(( " (%s)\n", round ? "round" : "flat" )); FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
} }
@ -767,6 +782,8 @@
blue->flags = 0; blue->flags = 0;
if ( AF_LATIN_IS_TOP_BLUE( bs ) ) if ( AF_LATIN_IS_TOP_BLUE( bs ) )
blue->flags |= AF_LATIN_BLUE_TOP; blue->flags |= AF_LATIN_BLUE_TOP;
if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
blue->flags |= AF_LATIN_BLUE_NEUTRAL;
/* /*
* The following flag is used later to adjust the y and x scales * The following flag is used later to adjust the y and x scales
@ -1846,17 +1863,16 @@
if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) ) if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
continue; continue;
/* if it is a top zone, check for right edges -- if it is a bottom */ /* if it is a top zone, check for right edges (against the major */
/* zone, check for left edges */ /* direction); if it is a bottom zone, check for left edges (in */
/* */ /* the major direction) -- this assumes the TrueType convention */
/* of course, that's for TrueType */ /* for the orientation of contours */
is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 ); is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
/* if it is a top zone, the edge must be against the major */ /* neutral blue zones are handled for both directions */
/* direction; if it is a bottom zone, it must be in the major */ if ( is_top_blue ^ is_major_dir ||
/* direction */ blue->flags & AF_LATIN_BLUE_NEUTRAL )
if ( is_top_blue ^ is_major_dir )
{ {
FT_Pos dist; FT_Pos dist;
@ -1876,8 +1892,11 @@
/* now compare it to the overshoot position and check whether */ /* now compare it to the overshoot position and check whether */
/* the edge is rounded, and whether the edge is over the */ /* the edge is rounded, and whether the edge is over the */
/* reference position of a top zone, or under the reference */ /* reference position of a top zone, or under the reference */
/* position of a bottom zone */ /* position of a bottom zone (provided we don't have a */
if ( edge->flags & AF_EDGE_ROUND && dist != 0 ) /* neutral blue zone) */
if ( edge->flags & AF_EDGE_ROUND &&
dist != 0 &&
!( blue->flags & AF_LATIN_BLUE_NEUTRAL ) )
{ {
FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org ); FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );

View File

@ -53,6 +53,8 @@ FT_BEGIN_HEADER
#define AF_LATIN_IS_TOP_BLUE( b ) \ #define AF_LATIN_IS_TOP_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP ) ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
#define AF_LATIN_IS_NEUTRAL_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
#define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \ #define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT ) ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )
#define AF_LATIN_IS_LONG_BLUE( b ) \ #define AF_LATIN_IS_LONG_BLUE( b ) \
@ -63,10 +65,11 @@ FT_BEGIN_HEADER
enum enum
{ {
AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */ AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */
AF_LATIN_BLUE_TOP = 1 << 1, /* result of AF_LATIN_IS_TOP_BLUE */ AF_LATIN_BLUE_TOP = 1 << 1, /* set if we have a top blue zone */
AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */ AF_LATIN_BLUE_NEUTRAL = 1 << 2, /* set if we have neutral blue zone */
/* optimization */ AF_LATIN_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment */
/* optimization */
AF_LATIN_BLUE_FLAG_MAX AF_LATIN_BLUE_FLAG_MAX
}; };