diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc | 334 |
1 files changed, 195 insertions, 139 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc index 1e07d33177..33215a304f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc @@ -37,19 +37,19 @@ */ -#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base)) +#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base)) -#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900)) -#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980)) -#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00)) -#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80)) -#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00)) -#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80)) -#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00)) -#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80)) -#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00)) -#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80)) -#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780)) +#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u)) +#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u)) +#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u)) +#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u)) +#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u)) +#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u)) +#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u)) +#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u)) +#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u)) +#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u)) +#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780u)) #define MATRA_POS_LEFT(u) POS_PRE_M @@ -60,8 +60,8 @@ IS_GUJR(u) ? POS_AFTER_POST : \ IS_ORYA(u) ? POS_AFTER_POST : \ IS_TAML(u) ? POS_AFTER_POST : \ - IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ - IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ + IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ + IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \ IS_MLYM(u) ? POS_AFTER_POST : \ IS_SINH(u) ? POS_AFTER_SUB : \ IS_KHMR(u) ? POS_AFTER_POST : \ @@ -112,20 +112,20 @@ matra_position (hb_codepoint_t u, indic_position_t side) * Or completely remove it and just check in the tables. */ static const hb_codepoint_t ra_chars[] = { - 0x0930, /* Devanagari */ - 0x09B0, /* Bengali */ - 0x09F0, /* Bengali */ - 0x0A30, /* Gurmukhi */ /* No Reph */ - 0x0AB0, /* Gujarati */ - 0x0B30, /* Oriya */ - 0x0BB0, /* Tamil */ /* No Reph */ - 0x0C30, /* Telugu */ /* Reph formed only with ZWJ */ - 0x0CB0, /* Kannada */ - 0x0D30, /* Malayalam */ /* No Reph, Logical Repha */ - - 0x0DBB, /* Sinhala */ /* Reph formed only with ZWJ */ - - 0x179A, /* Khmer */ /* No Reph, Visual Repha */ + 0x0930u, /* Devanagari */ + 0x09B0u, /* Bengali */ + 0x09F0u, /* Bengali */ + 0x0A30u, /* Gurmukhi */ /* No Reph */ + 0x0AB0u, /* Gujarati */ + 0x0B30u, /* Oriya */ + 0x0BB0u, /* Tamil */ /* No Reph */ + 0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */ + 0x0CB0u, /* Kannada */ + 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */ + + 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */ + + 0x179Au, /* Khmer */ /* No Reph, Visual Repha */ }; static inline bool @@ -145,28 +145,18 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags) return !!(FLAG (info.indic_category()) & flags); } -#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ)) static inline bool is_joiner (const hb_glyph_info_t &info) { return is_one_of (info, JOINER_FLAGS); } -#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2)) - -/* Note: - * - * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels - * cannot happen in a consonant syllable. The plus side however is, we can call the - * consonant syllable logic from the vowel syllable function and get it all right! */ -#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE)) static inline bool is_consonant (const hb_glyph_info_t &info) { return is_one_of (info, CONSONANT_FLAGS); } -#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng)) static inline bool is_halant_or_coeng (const hb_glyph_info_t &info) { @@ -178,7 +168,7 @@ set_indic_properties (hb_glyph_info_t &info) { hb_codepoint_t u = info.codepoint; unsigned int type = hb_indic_get_categories (u); - indic_category_t cat = (indic_category_t) (type & 0x7F); + indic_category_t cat = (indic_category_t) (type & 0x7Fu); indic_position_t pos = (indic_position_t) (type >> 8); @@ -188,48 +178,59 @@ set_indic_properties (hb_glyph_info_t &info) /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe - * treats U+0951..U+0954 all behave similarly. - * TESTS: + * treats a whole bunch of characters similarly. + * TESTS: For example, for U+0951: * U+092E,U+0947,U+0952 * U+092E,U+0952,U+0947 * U+092E,U+0947,U+0951 * U+092E,U+0951,U+0947 + * U+092E,U+0951,U+0952 + * U+092E,U+0952,U+0951 */ - if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954))) + if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u, + 0x1CD0u, 0x1CD2u, + 0x1CD4u, 0x1CE1u) || + u == 0x1CF4u)) cat = OT_A; - - if (unlikely (u == 0x17D1)) - cat = OT_X; - if (cat == OT_X && - unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Various signs */ + /* The following act more like the Bindus. */ + else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) + cat = OT_SM; + /* The following act like consonants. */ + else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u, + 0x1CF5u, 0x1CF6u))) + cat = OT_C; + /* TODO: The following should only be allowed after a Visarga. + * For now, just treat them like regular tone marks. */ + else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u))) + cat = OT_A; + /* TODO: The following should only be allowed after some of + * the nasalization marks, maybe only for U+1CE9..U+1CF1. + * For now, just treat them like tone marks. */ + else if (unlikely (u == 0x1CEDu)) + cat = OT_A; + /* The following take marks in standalone clusters, similar to Avagraha. */ + else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u, + 0x1CE9u, 0x1CECu, + 0x1CEEu, 0x1CF1u))) + { + cat = OT_Symbol; + ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol); + } + else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) || + u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */ { /* These are like Top Matras. */ cat = OT_M; pos = POS_ABOVE_C; } - if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */ - cat = OT_N; - - if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */ - else if (unlikely (u == 0x200C)) cat = OT_ZWNJ; - else if (unlikely (u == 0x200D)) cat = OT_ZWJ; - else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE; - else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. Move it to the end. */ - else if (unlikely (u == 0xA982)) cat = OT_SM; /* Javanese repha. */ - else if (unlikely (u == 0xA9BE)) cat = OT_CM2; /* Javanese medial ya. */ - else if (unlikely (u == 0xA9BD)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */ - - if (cat == OT_Repha) { - /* There are two kinds of characters marked as Repha: - * - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer) - * - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam) - * - * We recategorize the first kind to look like a Nukta and attached to the base directly. - */ - if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) - cat = OT_N; - } - + else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ + else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */ + else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) + cat = OT_PLACEHOLDER; + else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE; + else if (unlikely (u == 0xA982u)) cat = OT_SM; /* Javanese repha. */ + else if (unlikely (u == 0xA9BEu)) cat = OT_CM2; /* Javanese medial ya. */ + else if (unlikely (u == 0xA9BDu)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */ /* @@ -246,12 +247,12 @@ set_indic_properties (hb_glyph_info_t &info) { pos = matra_position (u, pos); } - else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Avag)))) + else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol)))) { pos = POS_SMVD; } - if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */ + if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */ @@ -315,20 +316,20 @@ struct indic_config_t static const indic_config_t indic_configs[] = { /* Default. Should be first. */ - {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, - {HB_SCRIPT_DEVANAGARI,true, 0x094D,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_BENGALI, true, 0x09CD,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_GURMUKHI, true, 0x0A4D,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_GUJARATI, true, 0x0ACD,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_ORIYA, true, 0x0B4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_TAMIL, true, 0x0BCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, - {HB_SCRIPT_TELUGU, true, 0x0C4D,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, - {HB_SCRIPT_KANNADA, true, 0x0CCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, - {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, - {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_LAST_SINHALA, - REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, - {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, - {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, + {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, + {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, + {HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, + {HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, + {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, + {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA, + REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_KHMER, false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, + {HB_SCRIPT_JAVANESE, false,0xA9C0u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, }; @@ -552,12 +553,12 @@ data_create_indic (const hb_ot_shape_plan_t *plan) break; } - indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FF) != '2'); + indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2'); indic_plan->virama_glyph = (hb_codepoint_t) -1; /* Use zero-context would_substitute() matching for new-spec of the main - * Indic scripts, but not for old-spec or scripts with one spec only. */ - bool zero_context = indic_plan->config->has_old_spec || !indic_plan->is_old_spec; + * Indic scripts, and scripts with one spec only, but not for old-specs. */ + bool zero_context = !indic_plan->is_old_spec; indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context); indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context); indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context); @@ -614,7 +615,7 @@ enum syllable_type_t { consonant_syllable, vowel_syllable, standalone_cluster, - avagraha_cluster, + symbol_cluster, broken_cluster, non_indic_cluster, }; @@ -634,8 +635,9 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, * and setup masks later on in a pause-callback. */ unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - set_indic_properties (buffer->info[i]); + set_indic_properties (info[i]); } static void @@ -672,10 +674,12 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan, { hb_face_t *face = font->face; unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if (buffer->info[i].indic_position() == POS_BASE_C) { - hb_codepoint_t consonant = buffer->info[i].codepoint; - buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face); + if (info[i].indic_position() == POS_BASE_C) + { + hb_codepoint_t consonant = info[i].codepoint; + info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face); } } } @@ -725,8 +729,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, )) { /* See if it matches the 'rphf' feature. */ - hb_codepoint_t glyphs[2] = {info[start].codepoint, info[start + 1].codepoint}; - if (indic_plan->rphf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) + hb_codepoint_t glyphs[3] = {info[start].codepoint, + info[start + 1].codepoint, + indic_plan->config->reph_mode == REPH_MODE_EXPLICIT ? + info[start + 2].codepoint : 0}; + if (indic_plan->rphf.would_substitute (glyphs, 2, face) || + (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && + indic_plan->rphf.would_substitute (glyphs, 3, face))) { limit += 2; while (limit < end && is_joiner (info[limit])) @@ -801,7 +810,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, case BASE_POS_LAST_SINHALA: { /* Sinhala base positioning is slightly different from main Indic, in that: - * 1. It's ZWJ behavior is different, + * 1. Its ZWJ behavior is different, * 2. We don't need to look into the font for consonant positions. */ @@ -1151,8 +1160,8 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, unsigned int start, unsigned int end) { - /* We treat NBSP/dotted-circle as if they are consonants, so we should just chain. - * Only if not in compatibility mode that is... */ + /* We treat placeholder/dotted-circle as if they are consonants, so we + * should just chain. Only if not in compatibility mode that is... */ if (hb_options ().uniscribe_bug_compatible) { @@ -1177,10 +1186,10 @@ initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, } static void -initial_reordering_avagraha_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_face_t *face HB_UNUSED, - hb_buffer_t *buffer HB_UNUSED, - unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +initial_reordering_symbol_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer HB_UNUSED, + unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) { /* Nothing to do right now. If we ever switch to using the output * buffer in the reordering process, we'd need to next_glyph() here. */ @@ -1208,7 +1217,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; case vowel_syllable: initial_reordering_vowel_syllable (plan, face, buffer, start, end); return; case standalone_cluster: initial_reordering_standalone_cluster (plan, face, buffer, start, end); return; - case avagraha_cluster: initial_reordering_avagraha_cluster (plan, face, buffer, start, end); return; + case symbol_cluster: initial_reordering_symbol_cluster (plan, face, buffer, start, end); return; case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; case non_indic_cluster: initial_reordering_non_indic_cluster (plan, face, buffer, start, end); return; } @@ -1222,8 +1231,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, /* Note: This loop is extra overhead, but should not be measurable. */ bool has_broken_syllables = false; unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) { + if ((info[i].syllable() & 0x0F) == broken_cluster) + { has_broken_syllables = true; break; } @@ -1232,11 +1243,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_codepoint_t dottedcircle_glyph; - if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph)) + if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph)) return; hb_glyph_info_t dottedcircle = {0}; - dottedcircle.codepoint = 0x25CC; + dottedcircle.codepoint = 0x25CCu; set_indic_properties (dottedcircle); dottedcircle.codepoint = dottedcircle_glyph; @@ -1302,6 +1313,27 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; hb_glyph_info_t *info = buffer->info; + + /* This function relies heavily on halant glyphs. Lots of ligation + * and possibly multiplication substitutions happened prior to this + * phase, and that might have messed up our properties. Recover + * from a particular case of that where we're fairly sure that a + * class of OT_H is desired but has been lost. */ + if (indic_plan->virama_glyph) + { + unsigned int virama_glyph = indic_plan->virama_glyph; + for (unsigned int i = start; i < end; i++) + if (info[i].codepoint == virama_glyph && + _hb_glyph_info_ligated (&info[i]) && + _hb_glyph_info_multiplied (&info[i])) + { + /* This will make sure that this glyph passes is_halant_or_coeng() test. */ + info[i].indic_category() = OT_H; + _hb_glyph_info_clear_ligated_and_multiplied (&info[i]); + } + } + + /* 4. Final reordering: * * After the localized forms and basic shaping forms GSUB features have been @@ -1310,21 +1342,45 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * cluster. */ + bool try_pref = !!indic_plan->mask_array[PREF]; + /* Find base again */ unsigned int base; for (base = start; base < end; base++) - if (info[base].indic_position() >= POS_BASE_C) { + if (info[base].indic_position() >= POS_BASE_C) + { + if (try_pref && base + 1 < end && indic_plan->config->pref_len == 2) + { + for (unsigned int i = base + 1; i < end; i++) + if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) + { + if (!(_hb_glyph_info_substituted (&info[i]) && + _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) + { + /* Ok, this was a 'pref' candidate but didn't form any. + * Base is around here... */ + base = i; + while (base < end && is_halant_or_coeng (info[base])) + base++; + info[base].indic_position() = POS_BASE_C; + + try_pref = false; + } + break; + } + } + if (start < base && info[base].indic_position() > POS_BASE_C) base--; break; } if (base == end && start < base && - info[base - 1].indic_category() != OT_ZWJ) - base--; - while (start < base && - (info[base].indic_category() == OT_H || - info[base].indic_category() == OT_N)) + is_one_of (info[base - 1], FLAG (OT_ZWJ))) base--; + if (base < end) + while (start < base && + is_one_of (info[base], (FLAG (OT_N) | HALANT_OR_COENG_FLAGS))) + base--; /* o Reorder matras: @@ -1349,7 +1405,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL) { while (new_pos > start && - !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H) | FLAG (OT_Coeng))))) + !(is_one_of (info[new_pos], (FLAG (OT_M) | HALANT_OR_COENG_FLAGS)))) new_pos--; /* If we found no Halant we are done. @@ -1412,7 +1468,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (start + 1 < end && info[start].indic_position() == POS_RA_TO_BECOME_REPH && ((info[start].indic_category() == OT_Repha) ^ - _hb_glyph_info_ligated (&info[start]))) + _hb_glyph_info_ligated_and_didnt_multiply (&info[start]))) { unsigned int new_reph_pos; reph_position_t reph_pos = indic_plan->config->reph_pos; @@ -1549,7 +1605,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * the following rules: */ - if (indic_plan->mask_array[PREF] && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */ + if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */ { unsigned int pref_len = indic_plan->config->pref_len; for (unsigned int i = base + 1; i < end; i++) @@ -1565,7 +1621,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * If pref len is longer than one, then only reorder if it ligated. If * pref len is one, only reorder if it didn't ligate with other things. */ if (_hb_glyph_info_substituted (&info[i]) && - ((pref_len == 1) ^ _hb_glyph_info_ligated (&info[i]))) + ((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) { /* * 2. Try to find a target position the same way as for pre-base matra. @@ -1699,37 +1755,37 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, switch (ab) { /* Don't decompose these. */ - case 0x0931 : return false; - case 0x0B94 : return false; + case 0x0931u : return false; + case 0x0B94u : return false; /* * Decompose split matras that don't have Unicode decompositions. */ - case 0x0F77 : *a = 0x0FB2; *b= 0x0F81; return true; - case 0x0F79 : *a = 0x0FB3; *b= 0x0F81; return true; - case 0x17BE : *a = 0x17C1; *b= 0x17BE; return true; - case 0x17BF : *a = 0x17C1; *b= 0x17BF; return true; - case 0x17C0 : *a = 0x17C1; *b= 0x17C0; return true; - case 0x17C4 : *a = 0x17C1; *b= 0x17C4; return true; - case 0x17C5 : *a = 0x17C1; *b= 0x17C5; return true; - case 0x1925 : *a = 0x1920; *b= 0x1923; return true; - case 0x1926 : *a = 0x1920; *b= 0x1924; return true; - case 0x1B3C : *a = 0x1B42; *b= 0x1B3C; return true; - case 0x1112E : *a = 0x11127; *b= 0x11131; return true; - case 0x1112F : *a = 0x11127; *b= 0x11132; return true; + case 0x0F77u : *a = 0x0FB2u; *b= 0x0F81u; return true; + case 0x0F79u : *a = 0x0FB3u; *b= 0x0F81u; return true; + case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true; + case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true; + case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true; + case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true; + case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true; + case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true; + case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true; + case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; + case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; + case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; #if 0 /* This one has no decomposition in Unicode, but needs no decomposition either. */ - /* case 0x0AC9 : return false; */ - case 0x0B57 : *a = no decomp, -> RIGHT; return true; - case 0x1C29 : *a = no decomp, -> LEFT; return true; - case 0xA9C0 : *a = no decomp, -> RIGHT; return true; - case 0x111BF : *a = no decomp, -> ABOVE; return true; + /* case 0x0AC9u : return false; */ + case 0x0B57u : *a = no decomp, -> RIGHT; return true; + case 0x1C29u : *a = no decomp, -> LEFT; return true; + case 0xA9C0u : *a = no decomp, -> RIGHT; return true; + case 0x111BuF : *a = no decomp, -> ABOVE; return true; #endif } - if ((ab == 0x0DDA || hb_in_range<hb_codepoint_t> (ab, 0x0DDC, 0x0DDE))) + if ((ab == 0x0DDAu || hb_in_range (ab, 0x0DDCu, 0x0DDEu))) { /* * Sinhala split matras... Let the fun begin. @@ -1766,7 +1822,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, indic_plan->pstf.would_substitute (&glyph, 1, c->font->face))) { /* Ok, safe to use Uniscribe-style decomposition. */ - *a = 0x0DD9; + *a = 0x0DD9u; *b = ab; return true; } @@ -1786,7 +1842,7 @@ compose_indic (const hb_ot_shape_normalize_context_t *c, return false; /* Composition-exclusion exceptions that we want to recompose. */ - if (a == 0x09AF && b == 0x09BC) { *ab = 0x09DF; return true; } + if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; } return c->unicode->compose (a, b, ab); } |