diff --git a/ChangeLog b/ChangeLog index ef42ba7af..73239bd5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2015-12-09 Werner Lemberg + + [autofit] Introduce subscript top blue zones. + + This feature is mainly for Khmer: The idea is to avoid a clash + between the top of subscript glyphs and the bottom of normal + baseline glyphs. + + This only works for character clusters mapped to multiple glyphs. + + * src/autofit/afblue.dat: Add subscript top blue zone for Khmer. + + * src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_SUB_TOP): New + macro. + + * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. + + * src/autofit/aflatin.h (AF_LATIN_IS_SUB_TOP_BLUE, + AF_LATIN_BLUE_SUB_TOP): New macros. + + * src/autofit/aflatin.c (af_latin_metrics_init_blues): Handle new + blue zone property. + Update tracing messages. + (af_latin_metrics_scale_dim): Handle new blue zone property. + (af_latin_hints_compute_blue_edges): Updated. + 2015-12-09 Werner Lemberg [autofit] Fix tracing message. diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c index 2196d9d75..ce932a3a1 100644 --- a/src/autofit/afblue.c +++ b/src/autofit/afblue.c @@ -66,6 +66,8 @@ '\0', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6', /* ខ ទ ន ឧ ឩ ា */ '\0', + '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90', /* ក្ក ក្ខ ក្គ ក្ថ */ + '\0', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x83', ' ', '\xE1', '\x9E', '\x85', ' ', '\xE1', '\x9E', '\x8B', ' ', '\xE1', '\x9E', '\x94', ' ', '\xE1', '\x9E', '\x98', ' ', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xB2', /* ខ ឃ ច ឋ ប ម យ ឲ */ '\0', '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', ' ', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\xB2', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xA2', '\xE1', '\x9E', '\xBF', /* ត្រ រៀ ឲ្យ អឿ */ @@ -217,6 +219,7 @@ { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP }, { AF_BLUE_STRING_KHMER_BOTTOM, 0 }, { AF_BLUE_STRING_KHMER_DESCENDER, 0 }, { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 }, diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat index 9c29c7827..970812b4a 100644 --- a/src/autofit/afblue.dat +++ b/src/autofit/afblue.dat @@ -127,6 +127,8 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_KHMER_TOP "ខ ទ ន ឧ ឩ ា" + AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP + "ក្ក ក្ខ ក្គ ក្ថ" AF_BLUE_STRING_KHMER_BOTTOM "ខ ឃ ច ឋ ប ម យ ឲ" AF_BLUE_STRING_KHMER_DESCENDER @@ -297,6 +299,21 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: // // If not set, take the minimum values. // +// Mutually exclusive with `LATIN_SUB_TOP'. +// +// LATIN_SUB_TOP +// For all glyphs of a character cluster, compute the maximum flat +// and round coordinate values of each component, then take the +// smallest of the maximum values. The idea is to get the top of +// subscript glyphs, as used in Khmer, for example. Note that +// this mechanism doesn't work for ordinary ligatures. +// +// This flags indicates a secondary blue zone: It gets removed if +// there is a non-LATIN_SUB_TOP blue zone at the same coordinate +// value (after scaling). +// +// Mutually exclusive with `LATIN_TOP'. +// // 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 @@ -401,6 +418,7 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: AF_BLUE_STRINGSET_KHMR { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP } { AF_BLUE_STRING_KHMER_BOTTOM, 0 } { AF_BLUE_STRING_KHMER_DESCENDER, 0 } { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 } diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h index 5a20613d4..96cfe4310 100644 --- a/src/autofit/afblue.h +++ b/src/autofit/afblue.h @@ -97,41 +97,42 @@ FT_BEGIN_HEADER AF_BLUE_STRING_HEBREW_BOTTOM = 350, AF_BLUE_STRING_HEBREW_DESCENDER = 368, AF_BLUE_STRING_KHMER_TOP = 383, - AF_BLUE_STRING_KHMER_BOTTOM = 407, - AF_BLUE_STRING_KHMER_DESCENDER = 439, - AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 473, - AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 560, - AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 568, - AF_BLUE_STRING_LAO_TOP = 576, - AF_BLUE_STRING_LAO_BOTTOM = 608, - AF_BLUE_STRING_LAO_ASCENDER = 640, - AF_BLUE_STRING_LAO_LARGE_ASCENDER = 656, - AF_BLUE_STRING_LAO_DESCENDER = 668, - AF_BLUE_STRING_LATIN_CAPITAL_TOP = 692, - AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 708, - AF_BLUE_STRING_LATIN_SMALL_F_TOP = 724, - AF_BLUE_STRING_LATIN_SMALL = 738, - AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 752, - AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 762, - AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 782, - AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 802, - AF_BLUE_STRING_LATIN_SUBS_SMALL = 822, - AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 858, - AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 878, - AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 909, - AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 938, - AF_BLUE_STRING_LATIN_SUPS_SMALL = 964, - AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 989, - AF_BLUE_STRING_TELUGU_TOP = 1000, - AF_BLUE_STRING_TELUGU_BOTTOM = 1028, - AF_BLUE_STRING_THAI_TOP = 1056, - AF_BLUE_STRING_THAI_BOTTOM = 1080, - AF_BLUE_STRING_THAI_ASCENDER = 1108, - AF_BLUE_STRING_THAI_LARGE_ASCENDER = 1120, - AF_BLUE_STRING_THAI_DESCENDER = 1132, - AF_BLUE_STRING_THAI_LARGE_DESCENDER = 1148, - AF_BLUE_STRING_THAI_DIGIT_TOP = 1156, - af_blue_1_1 = 1167, + AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 407, + AF_BLUE_STRING_KHMER_BOTTOM = 447, + AF_BLUE_STRING_KHMER_DESCENDER = 479, + AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 513, + AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 600, + AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 608, + AF_BLUE_STRING_LAO_TOP = 616, + AF_BLUE_STRING_LAO_BOTTOM = 648, + AF_BLUE_STRING_LAO_ASCENDER = 680, + AF_BLUE_STRING_LAO_LARGE_ASCENDER = 696, + AF_BLUE_STRING_LAO_DESCENDER = 708, + AF_BLUE_STRING_LATIN_CAPITAL_TOP = 732, + AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 748, + AF_BLUE_STRING_LATIN_SMALL_F_TOP = 764, + AF_BLUE_STRING_LATIN_SMALL = 778, + AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 792, + AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 802, + AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 822, + AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 842, + AF_BLUE_STRING_LATIN_SUBS_SMALL = 862, + AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 898, + AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 918, + AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 949, + AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 978, + AF_BLUE_STRING_LATIN_SUPS_SMALL = 1004, + AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 1029, + AF_BLUE_STRING_TELUGU_TOP = 1040, + AF_BLUE_STRING_TELUGU_BOTTOM = 1068, + AF_BLUE_STRING_THAI_TOP = 1096, + AF_BLUE_STRING_THAI_BOTTOM = 1120, + AF_BLUE_STRING_THAI_ASCENDER = 1148, + AF_BLUE_STRING_THAI_LARGE_ASCENDER = 1160, + AF_BLUE_STRING_THAI_DESCENDER = 1172, + AF_BLUE_STRING_THAI_LARGE_DESCENDER = 1188, + AF_BLUE_STRING_THAI_DIGIT_TOP = 1196, + af_blue_1_1 = 1207, #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1, AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203, @@ -173,9 +174,10 @@ FT_BEGIN_HEADER /* blue string can't be used in more than a single writing system, which */ /* is a safe bet. */ #define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */ -#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 1 ) -#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 2 ) -#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 3 ) +#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 ) +#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 ) +#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 ) +#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 ) #define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */ #define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */ @@ -195,14 +197,14 @@ FT_BEGIN_HEADER AF_BLUE_STRINGSET_GREK = 16, AF_BLUE_STRINGSET_HEBR = 23, AF_BLUE_STRINGSET_KHMR = 27, - AF_BLUE_STRINGSET_KHMS = 32, - AF_BLUE_STRINGSET_LAO = 35, - AF_BLUE_STRINGSET_LATN = 41, - AF_BLUE_STRINGSET_LATB = 48, - AF_BLUE_STRINGSET_LATP = 55, - AF_BLUE_STRINGSET_TELU = 62, - AF_BLUE_STRINGSET_THAI = 65, - af_blue_2_1 = 73, + AF_BLUE_STRINGSET_KHMS = 33, + AF_BLUE_STRINGSET_LAO = 36, + AF_BLUE_STRINGSET_LATN = 42, + AF_BLUE_STRINGSET_LATB = 49, + AF_BLUE_STRINGSET_LATP = 56, + AF_BLUE_STRINGSET_TELU = 63, + AF_BLUE_STRINGSET_THAI = 66, + af_blue_2_1 = 74, #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0, af_blue_2_1_1 = af_blue_2_1 + 2, diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin index 3f85ee707..1eb917218 100644 --- a/src/autofit/afblue.hin +++ b/src/autofit/afblue.hin @@ -100,9 +100,10 @@ FT_BEGIN_HEADER /* blue string can't be used in more than a single writing system, which */ /* is a safe bet. */ #define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */ -#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 1 ) -#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 2 ) -#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 3 ) +#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 ) +#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 ) +#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 ) +#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 ) #define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */ #define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */ diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 0ad634e58..aeaffb88e 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -330,6 +330,11 @@ FT_TRACE5(( "top" )); have_flag = 1; } + else if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) ) + { + FT_TRACE5(( "sub top" )); + have_flag = 1; + } if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) { @@ -462,7 +467,8 @@ if ( last <= first ) continue; - if ( AF_LATIN_IS_TOP_BLUE( bs ) ) + if ( AF_LATIN_IS_TOP_BLUE( bs ) || + AF_LATIN_IS_SUB_TOP_BLUE( bs ) ) { for ( pp = first; pp <= last; pp++ ) { @@ -871,7 +877,8 @@ FT_Bool over_ref = FT_BOOL( shoot > ref ); - if ( AF_LATIN_IS_TOP_BLUE( bs ) ^ over_ref ) + if ( ( AF_LATIN_IS_TOP_BLUE( bs ) || + AF_LATIN_IS_SUB_TOP_BLUE( bs) ) ^ over_ref ) { *blue_ref = *blue_shoot = ( shoot + ref ) / 2; @@ -887,6 +894,8 @@ blue->flags = 0; if ( AF_LATIN_IS_TOP_BLUE( bs ) ) blue->flags |= AF_LATIN_BLUE_TOP; + if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) ) + blue->flags |= AF_LATIN_BLUE_SUB_TOP; if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) blue->flags |= AF_LATIN_BLUE_NEUTRAL; @@ -1259,6 +1268,40 @@ } } + /* use sub-top blue zone only if it doesn't overlap with */ + /* another (non-sup-top) blue zone; otherwise, the */ + /* effect would be similar to a neutral blue zone, which */ + /* is not desired here */ + for ( nn = 0; nn < axis->blue_count; nn++ ) + { + AF_LatinBlue blue = &axis->blues[nn]; + FT_UInt i; + + + if ( !( blue->flags & AF_LATIN_BLUE_SUB_TOP ) ) + continue; + if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) ) + continue; + + for ( i = 0; i < axis->blue_count; i++ ) + { + AF_LatinBlue b = &axis->blues[i]; + + + if ( b->flags & AF_LATIN_BLUE_SUB_TOP ) + continue; + if ( !( b->flags & AF_LATIN_BLUE_ACTIVE ) ) + continue; + + if ( b->ref.fit <= blue->shoot.fit && + b->shoot.fit >= blue->ref.fit ) + { + blue->flags &= ~AF_LATIN_BLUE_ACTIVE; + break; + } + } + } + #ifdef FT_DEBUG_LEVEL_TRACE for ( nn = 0; nn < axis->blue_count; nn++ ) { @@ -2071,7 +2114,8 @@ /* 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 ); + (FT_Byte)( ( blue->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) != 0 ); is_neutral_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0); is_major_dir = diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h index dd75ef341..414060f4f 100644 --- a/src/autofit/aflatin.h +++ b/src/autofit/aflatin.h @@ -53,6 +53,8 @@ FT_BEGIN_HEADER #define AF_LATIN_IS_TOP_BLUE( b ) \ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP ) +#define AF_LATIN_IS_SUB_TOP_BLUE( b ) \ + ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP ) #define AF_LATIN_IS_NEUTRAL_BLUE( b ) \ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL ) #define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \ @@ -65,8 +67,10 @@ FT_BEGIN_HEADER #define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */ #define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */ -#define AF_LATIN_BLUE_NEUTRAL ( 1U << 2 ) /* we have neutral blue zone */ -#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 3 ) /* used for scale adjustment */ +#define AF_LATIN_BLUE_SUB_TOP ( 1U << 2 ) /* we have a subscript top */ + /* blue zone */ +#define AF_LATIN_BLUE_NEUTRAL ( 1U << 3 ) /* we have neutral blue zone */ +#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 4 ) /* used for scale adjustment */ /* optimization */