src/hb-ot-layout-common-private.hh | 2 src/hb-ot-layout-gsub-table.hh | 20 +-- src/hb-ot-layout-gsubgpos-private.hh | 85 +++++++-------- src/hb-ot-layout.cc | 4 src/hb-ot-shape-complex-indic.cc | 191 +++++++++++++++++++++-------------- src/hb-ot-shape-complex-private.hh | 4 src/hb-ot-shape-complex-sea.cc | 2 7 files changed, 176 insertions(+), 132 deletions(-)
New commits: commit 8f9ec92dfce5c469fb85ad301296b5dde1b2ab0a Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 19:52:47 2013 +0200 [indic] Adjust Javanese base algorithm diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 587977b..bc79025 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -323,7 +323,7 @@ static const indic_config_t indic_configs[] = {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_LAST, REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, + {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, }; commit 49901862e36e1c153835877a9f1183729333bbbe Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 19:48:51 2013 +0200 [otlayout] Guard against use of ReverseChain through Context diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index a595a4b..28ba3b9 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -1037,7 +1037,9 @@ struct ReverseChainSingleSubstFormat1 1)) { c->replace_glyph_inplace (substitute[index]); - c->buffer->idx--; /* Reverse! */ + /* Note: We DON'T decrease buffer->idx. The main loop does it + * for us. This is useful for preventing surprises if someone + * calls us through a Context lookup. */ return TRACE_RETURN (true); } diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 5f3eb57..06c98d2 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -867,8 +867,8 @@ apply_string (OT::hb_apply_context_t *c, (c->buffer->cur().mask & c->lookup_mask) && apply_once (c, lookup)) ret = true; - else - c->buffer->idx--; + /* The reverse lookup doesn't "advance" cursor (for good reason). */ + c->buffer->idx--; } while ((int) c->buffer->idx >= 0); commit 74f4bbf0560a5fd2d295e100e96f0c6c7033e852 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 19:07:53 2013 +0200 [indic] Towards supporting atomicly-encoded prebase-reorderings diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index e1f64d1..587977b 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -273,12 +273,12 @@ enum base_position_t { BASE_POS_LAST }; enum reph_position_t { - REPH_POS_DONT_CARE = POS_RA_TO_BECOME_REPH, REPH_POS_AFTER_MAIN = POS_AFTER_MAIN, REPH_POS_BEFORE_SUB = POS_BEFORE_SUB, REPH_POS_AFTER_SUB = POS_AFTER_SUB, REPH_POS_BEFORE_POST = POS_BEFORE_POST, - REPH_POS_AFTER_POST = POS_AFTER_POST + REPH_POS_AFTER_POST = POS_AFTER_POST, + REPH_POS_DONT_CARE = POS_RA_TO_BECOME_REPH }; enum reph_mode_t { REPH_MODE_IMPLICIT, /* Reph formed out of initial Ra,H sequence. */ @@ -290,6 +290,11 @@ enum blwf_mode_t { BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-base. */ BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */ }; +enum pref_len_t { + PREF_LEN_1 = 1, + PREF_LEN_2 = 2, + PREF_LEN_DONT_CARE = PREF_LEN_2 +}; struct indic_config_t { hb_script_t script; @@ -299,25 +304,26 @@ struct indic_config_t reph_position_t reph_pos; reph_mode_t reph_mode; blwf_mode_t blwf_mode; + pref_len_t pref_len; }; 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}, - {HB_SCRIPT_DEVANAGARI,true, 0x094D,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_BENGALI, true, 0x09CD,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_GURMUKHI, true, 0x0A4D,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_GUJARATI, true, 0x0ACD,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_ORIYA, true, 0x0B4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_TAMIL, true, 0x0BCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_TELUGU, true, 0x0C4D,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY}, - {HB_SCRIPT_KANNADA, true, 0x0CCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY}, - {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST}, + {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}, - {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_LAST, REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, + 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_LAST, REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, }; @@ -588,8 +594,12 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, if (indic_plan->pstf.would_substitute (glyphs , 2, face) || indic_plan->pstf.would_substitute (glyphs+1, 2, face)) return POS_POST_C; - if (indic_plan->pref.would_substitute (glyphs , 2, face) || - indic_plan->pref.would_substitute (glyphs+1, 2, face)) + unsigned int pref_len = indic_plan->config->pref_len; + if ((pref_len == PREF_LEN_2 && + (indic_plan->pref.would_substitute (glyphs , 2, face) || + indic_plan->pref.would_substitute (glyphs+1, 2, face))) + || (pref_len == PREF_LEN_1 && + indic_plan->pref.would_substitute (glyphs+1, 1, face))) return POS_POST_C; return POS_BASE_C; } @@ -1068,15 +1078,19 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, } } - if (indic_plan->mask_array[PREF] && base + 2 < end) + unsigned int pref_len = indic_plan->config->pref_len; + if (indic_plan->mask_array[PREF] && base + pref_len < end) { + assert (1 <= pref_len && pref_len <= 2); /* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */ - for (unsigned int i = base + 1; i + 1 < end; i++) { - hb_codepoint_t glyphs[2] = {info[i].codepoint, info[i + 1].codepoint}; - if (indic_plan->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) + for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { + hb_codepoint_t glyphs[2]; + for (unsigned int j = 0; j < pref_len; j++) + glyphs[j] = info[i + j].codepoint; + if (indic_plan->pref.would_substitute (glyphs, pref_len, face)) { - info[i++].mask |= indic_plan->mask_array[PREF]; - info[i++].mask |= indic_plan->mask_array[PREF]; + for (unsigned int j = 0; j < pref_len; j++) + info[i++].mask |= indic_plan->mask_array[PREF]; /* Mark the subsequent stuff with 'cfar'. Used in Khmer. * Read the feature spec. @@ -1084,8 +1098,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * U+1784,U+17D2,U+179A,U+17D2,U+1782 * U+1784,U+17D2,U+1782,U+17D2,U+179A */ - for (; i < end; i++) - info[i].mask |= indic_plan->mask_array[CFAR]; + if (indic_plan->mask_array[CFAR]) + for (; i < end; i++) + info[i].mask |= indic_plan->mask_array[CFAR]; break; } commit efed40b975110d78c9c505441e7e17a8c13e85c8 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 18:50:11 2013 +0200 [indic] Minor refactoring of reph handling diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 8c3e1e0..e1f64d1 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -273,8 +273,7 @@ enum base_position_t { BASE_POS_LAST }; enum reph_position_t { - REPH_POS_DEFAULT = POS_BEFORE_POST, - + REPH_POS_DONT_CARE = POS_RA_TO_BECOME_REPH, REPH_POS_AFTER_MAIN = POS_AFTER_MAIN, REPH_POS_BEFORE_SUB = POS_BEFORE_SUB, REPH_POS_AFTER_SUB = POS_AFTER_SUB, @@ -305,7 +304,7 @@ 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_DEFAULT, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, {HB_SCRIPT_DEVANAGARI,true, 0x094D,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, {HB_SCRIPT_BENGALI, true, 0x09CD,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, {HB_SCRIPT_GURMUKHI, true, 0x0A4D,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, @@ -317,8 +316,8 @@ static const indic_config_t indic_configs[] = {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST}, {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_LAST_SINHALA, REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DEFAULT, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_LAST, REPH_POS_DEFAULT, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_LAST, REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, }; @@ -702,7 +701,8 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * and has more than one consonant, Ra is excluded from candidates for * base consonants. */ unsigned int limit = start; - if (indic_plan->mask_array[RPHF] && + if (indic_plan->config->reph_pos != POS_RA_TO_BECOME_REPH && + indic_plan->mask_array[RPHF] && start + 3 <= end && ( (indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) || @@ -816,6 +816,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* The first consonant is always the base. */ assert (indic_plan->config->reph_mode == REPH_MODE_VIS_REPHA); + assert (!has_reph); base = start; @@ -1394,6 +1395,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, unsigned int new_reph_pos; reph_position_t reph_pos = indic_plan->config->reph_pos; + assert (reph_pos != POS_RA_TO_BECOME_REPH); /* 1. If reph should be positioned after post-base consonant forms, * proceed to step 5. diff --git a/src/hb-ot-shape-complex-sea.cc b/src/hb-ot-shape-complex-sea.cc index 9c0c303..da687ed 100644 --- a/src/hb-ot-shape-complex-sea.cc +++ b/src/hb-ot-shape-complex-sea.cc @@ -266,7 +266,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, switch (syllable_type) { case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; - case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return; + case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return; } } commit 684fe59ff858a0ecba71b3ed80378afb0b8bbb48 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 18:30:06 2013 +0200 [indic] Minor refactoring of would_substitute() diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 81079bc..8c3e1e0 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -568,7 +568,8 @@ data_destroy_indic (void *data) static indic_position_t consonant_position_from_face (const indic_shape_plan_t *indic_plan, - const hb_codepoint_t glyphs[2], + const hb_codepoint_t consonant, + const hb_codepoint_t virama, hb_face_t *face) { /* For old-spec, the order of glyphs is Consonant,Virama, @@ -581,15 +582,15 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, * 930,94D in 'blwf', not the expected 94D,930 (with new-spec * table). As such, we simply match both sequences. Seems * to work. */ - hb_codepoint_t glyphs_r[2] = {glyphs[1], glyphs[0]}; + hb_codepoint_t glyphs[3] = {virama, consonant, virama}; if (indic_plan->blwf.would_substitute (glyphs , 2, face) || - indic_plan->blwf.would_substitute (glyphs_r, 2, face)) + indic_plan->blwf.would_substitute (glyphs+1, 2, face)) return POS_BELOW_C; if (indic_plan->pstf.would_substitute (glyphs , 2, face) || - indic_plan->pstf.would_substitute (glyphs_r, 2, face)) + indic_plan->pstf.would_substitute (glyphs+1, 2, face)) return POS_POST_C; if (indic_plan->pref.would_substitute (glyphs , 2, face) || - indic_plan->pref.would_substitute (glyphs_r, 2, face)) + indic_plan->pref.would_substitute (glyphs+1, 2, face)) return POS_POST_C; return POS_BASE_C; } @@ -652,15 +653,15 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan, if (indic_plan->config->base_pos != BASE_POS_LAST) return; - hb_codepoint_t glyphs[2]; - if (indic_plan->get_virama_glyph (font, &glyphs[0])) + hb_codepoint_t virama; + if (indic_plan->get_virama_glyph (font, &virama)) { hb_face_t *face = font->face; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) if (buffer->info[i].indic_position() == POS_BASE_C) { - glyphs[1] = buffer->info[i].codepoint; - buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, glyphs, face); + hb_codepoint_t consonant = buffer->info[i].codepoint; + buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face); } } } commit 321df83fb4f0b8a5310888129cb70bfda8ae0c96 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 18:16:14 2013 +0200 Route Buginese through the SEA shaper Both Indic and SEA seem to do it just fine, but SEA is much simpler. diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index a099e05..ac0072b 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -279,9 +279,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-3.0 additions */ case HB_SCRIPT_SINHALA: - /* Unicode-4.1 additions */ - case HB_SCRIPT_BUGINESE: - /* Unicode-5.0 additions */ case HB_SCRIPT_BALINESE: @@ -336,6 +333,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) return &_hb_ot_complex_shaper_default; /* Unicode-4.1 additions */ + case HB_SCRIPT_BUGINESE: case HB_SCRIPT_NEW_TAI_LUE: /* Unicode-5.1 additions */ commit b5a0f69e47ace468b06e21cf069a18ddcfcf6064 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 18:04:23 2013 +0200 [indic] Pass zero-context=false to would_substitute for newer scripts For scripts without an old/new spec distinction, use zero-context=false. This changes behavior in Sinhala / Khmer, but doesn't seem to regress. This will be useful and used in Javanese. diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 42549ed..81079bc 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -468,8 +468,9 @@ override_features_indic (hb_ot_shape_planner_t *plan) struct would_substitute_feature_t { - inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag) + inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) { + zero_context = zero_context_; map->get_stage_lookups (0/*GSUB*/, map->get_feature_stage (0/*GSUB*/, feature_tag), &lookups, &count); @@ -477,7 +478,6 @@ struct would_substitute_feature_t inline bool would_substitute (const hb_codepoint_t *glyphs, unsigned int glyphs_count, - bool zero_context, hb_face_t *face) const { for (unsigned int i = 0; i < count; i++) @@ -489,6 +489,7 @@ struct would_substitute_feature_t private: const hb_ot_map_t::lookup_map_t *lookups; unsigned int count; + bool zero_context; }; struct indic_shape_plan_t @@ -544,10 +545,13 @@ data_create_indic (const hb_ot_shape_plan_t *plan) indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FF) != '2'); indic_plan->virama_glyph = (hb_codepoint_t) -1; - indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f')); - indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f')); - indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f')); - indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f')); + /* 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_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); + indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context); for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++) indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ? @@ -577,16 +581,15 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, * 930,94D in 'blwf', not the expected 94D,930 (with new-spec * table). As such, we simply match both sequences. Seems * to work. */ - bool zero_context = indic_plan->is_old_spec ? false : true; hb_codepoint_t glyphs_r[2] = {glyphs[1], glyphs[0]}; - if (indic_plan->blwf.would_substitute (glyphs , 2, zero_context, face) || - indic_plan->blwf.would_substitute (glyphs_r, 2, zero_context, face)) + if (indic_plan->blwf.would_substitute (glyphs , 2, face) || + indic_plan->blwf.would_substitute (glyphs_r, 2, face)) return POS_BELOW_C; - if (indic_plan->pstf.would_substitute (glyphs , 2, zero_context, face) || - indic_plan->pstf.would_substitute (glyphs_r, 2, zero_context, face)) + if (indic_plan->pstf.would_substitute (glyphs , 2, face) || + indic_plan->pstf.would_substitute (glyphs_r, 2, face)) return POS_POST_C; - if (indic_plan->pref.would_substitute (glyphs , 2, zero_context, face) || - indic_plan->pref.would_substitute (glyphs_r, 2, zero_context, face)) + if (indic_plan->pref.would_substitute (glyphs , 2, face) || + indic_plan->pref.would_substitute (glyphs_r, 2, face)) return POS_POST_C; return POS_BASE_C; } @@ -707,7 +710,7 @@ 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), true, face)) + if (indic_plan->rphf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) { limit += 2; while (limit < end && is_joiner (info[limit])) @@ -1068,7 +1071,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */ for (unsigned int i = base + 1; i + 1 < end; i++) { hb_codepoint_t glyphs[2] = {info[i].codepoint, info[i + 1].codepoint}; - if (indic_plan->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), true, face)) + if (indic_plan->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) { info[i++].mask |= indic_plan->mask_array[PREF]; info[i++].mask |= indic_plan->mask_array[PREF]; @@ -1734,7 +1737,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, if (hb_options ().uniscribe_bug_compatible || (c->font->get_glyph (ab, 0, &glyph) && - indic_plan->pstf.would_substitute (&glyph, 1, true, c->font->face))) + indic_plan->pstf.would_substitute (&glyph, 1, c->font->face))) { /* Ok, safe to use Uniscribe-style decomposition. */ *a = 0x0DD9; commit c4e71ff36d1f86a6ea56539728a964d97217e2b6 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 17:04:47 2013 +0200 [indic] Clean up Khmer and Sinhala base finding algorithm diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index b120a61..42549ed 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -128,14 +128,6 @@ static const hb_codepoint_t ra_chars[] = { 0x179A, /* Khmer */ /* No Reph, Visual Repha */ }; -static inline indic_position_t -consonant_position (hb_codepoint_t u) -{ - if ((u & ~0x007F) == 0x1780) - return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */ - return POS_BASE_C; /* Will recategorize later based on font lookups. */ -} - static inline bool is_ra (hb_codepoint_t u) { @@ -241,7 +233,7 @@ set_indic_properties (hb_glyph_info_t &info) if ((FLAG (cat) & CONSONANT_FLAGS)) { - pos = consonant_position (u); + pos = POS_BASE_C; if (is_ra (u)) cat = OT_Ra; } @@ -654,6 +646,9 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan, { const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; + if (indic_plan->config->base_pos != BASE_POS_LAST) + return; + hb_codepoint_t glyphs[2]; if (indic_plan->get_virama_glyph (font, &glyphs[0])) { @@ -786,7 +781,10 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, case BASE_POS_LAST_SINHALA: { - /* In scripts without half forms (eg. Khmer), the first consonant is always the base. */ + /* Sinhala base positioning is slightly different from main Indic, in that: + * 1. It's ZWJ behavior is different, + * 2. We don't need to look into the font for consonant positions. + */ if (!has_reph) base = limit; @@ -794,7 +792,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Find the last base consonant that is not blocked by ZWJ. If there is * a ZWJ right before a base consonant, that would request a subjoined form. */ for (unsigned int i = limit; i < end; i++) - if (is_consonant (info[i]) && info[i].indic_position() == POS_BASE_C) + if (is_consonant (info[i])) { if (limit < i && info[i - 1].indic_category() == OT_ZWJ) break; @@ -804,7 +802,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Mark all subsequent consonants as below. */ for (unsigned int i = base + 1; i < end; i++) - if (is_consonant (info[i]) && info[i].indic_position() == POS_BASE_C) + if (is_consonant (info[i])) info[i].indic_position() = POS_BELOW_C; } break; @@ -819,7 +817,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Mark all subsequent consonants as below. */ for (unsigned int i = base + 1; i < end; i++) - if (is_consonant (info[i]) && info[i].indic_position() == POS_BASE_C) + if (is_consonant (info[i])) info[i].indic_position() = POS_BELOW_C; } break; commit e10453e6fb2544724ccd7ddfdbb9de90ef9274ce Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 16:49:06 2013 +0200 [indic] Add BASE_POS_LAST_SINHALA Previously we planted this into the mode used for Khmer. There's not really much in common between the two, so separate again. diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index a0ebfef..b120a61 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -277,6 +277,7 @@ set_indic_properties (hb_glyph_info_t &info) enum base_position_t { BASE_POS_FIRST, + BASE_POS_LAST_SINHALA, BASE_POS_LAST }; enum reph_position_t { @@ -322,7 +323,8 @@ static const indic_config_t indic_configs[] = {HB_SCRIPT_TELUGU, true, 0x0C4D,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY}, {HB_SCRIPT_KANNADA, true, 0x0CCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY}, {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST}, - {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_FIRST,REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST}, + {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_LAST_SINHALA, + REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST}, {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DEFAULT, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_LAST, REPH_POS_DEFAULT, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, }; @@ -782,7 +784,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, } break; - case BASE_POS_FIRST: + case BASE_POS_LAST_SINHALA: { /* In scripts without half forms (eg. Khmer), the first consonant is always the base. */ @@ -806,6 +808,21 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, info[i].indic_position() = POS_BELOW_C; } break; + + case BASE_POS_FIRST: + { + /* The first consonant is always the base. */ + + assert (indic_plan->config->reph_mode == REPH_MODE_VIS_REPHA); + + base = start; + + /* Mark all subsequent consonants as below. */ + for (unsigned int i = base + 1; i < end; i++) + if (is_consonant (info[i]) && info[i].indic_position() == POS_BASE_C) + info[i].indic_position() = POS_BELOW_C; + } + break; } /* -> If the syllable starts with Ra + Halant (in a script that has Reph) commit 9ac6b01e0cd8e2d66dfc727157f45b615bc77109 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 16:27:38 2013 +0200 [indic] Adjust Sinhala cluster merging under uniscribe Similar to 190c8f2b60af0851bf692f653c1604cfbf0561a5 but for Sinhala. diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 3471aa6..a0ebfef 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -463,7 +463,7 @@ override_features_indic (hb_ot_shape_planner_t *plan) switch ((hb_tag_t) plan->props.script) { case HB_SCRIPT_KHMER: - plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL); + plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL); break; } } @@ -1584,13 +1584,22 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* * Finish off the clusters and go home! */ - if (hb_options ().uniscribe_bug_compatible && buffer->props.script != HB_SCRIPT_TAMIL) + if (hb_options ().uniscribe_bug_compatible) { - /* Uniscribe merges the entire cluster... Except for Tamil. - * This means, half forms are submerged into the main consonants cluster. - * This is unnecessary, and makes cursor positioning harder, but that's what - * Uniscribe does. */ - buffer->merge_clusters (start, end); + switch ((hb_tag_t) plan->props.script) + { + case HB_SCRIPT_TAMIL: + case HB_SCRIPT_SINHALA: + break; + + default: + /* Uniscribe merges the entire cluster... Except for Tamil & Sinhala. + * This means, half forms are submerged into the main consonants cluster. + * This is unnecessary, and makes cursor positioning harder, but that's what + * Uniscribe does. */ + buffer->merge_clusters (start, end); + break; + } } } commit 3c3df9cba13fec2c35e0e7ae587d9699ac0c37f5 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 13:58:31 2013 +0200 [otlayout] Minor diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 2ba9978..f156b98 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -761,7 +761,9 @@ static inline bool match_input (hb_apply_context_t *c, if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false); - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + hb_buffer_t *buffer = c->buffer; + + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1); skippy_iter.set_match_func (match_func, match_data, input); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); @@ -783,23 +785,23 @@ static inline bool match_input (hb_apply_context_t *c, * ligate with a conjunct...) */ - bool is_mark_ligature = !!(c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); + bool is_mark_ligature = !!(buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); unsigned int total_component_count = 0; - total_component_count += get_lig_num_comps (c->buffer->cur()); + total_component_count += get_lig_num_comps (buffer->cur()); - unsigned int first_lig_id = get_lig_id (c->buffer->cur()); - unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); + unsigned int first_lig_id = get_lig_id (buffer->cur()); + unsigned int first_lig_comp = get_lig_comp (buffer->cur()); - match_positions[0] = c->buffer->idx; + match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { if (!skippy_iter.next ()) return TRACE_RETURN (false); match_positions[i] = skippy_iter.idx; - unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); - unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]); + unsigned int this_lig_id = get_lig_id (buffer->info[skippy_iter.idx]); + unsigned int this_lig_comp = get_lig_comp (buffer->info[skippy_iter.idx]); if (first_lig_id && first_lig_comp) { /* If first component was attached to a previous ligature component, @@ -815,11 +817,11 @@ static inline bool match_input (hb_apply_context_t *c, return TRACE_RETURN (false); } - is_mark_ligature = is_mark_ligature && (c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); - total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]); + is_mark_ligature = is_mark_ligature && (buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); + total_component_count += get_lig_num_comps (buffer->info[skippy_iter.idx]); } - *end_offset = skippy_iter.idx - c->buffer->idx + 1; + *end_offset = skippy_iter.idx - buffer->idx + 1; if (p_is_mark_ligature) *p_is_mark_ligature = is_mark_ligature; @@ -839,7 +841,9 @@ static inline void ligate_input (hb_apply_context_t *c, { TRACE_APPLY (NULL); - c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + match_length); + hb_buffer_t *buffer = c->buffer; + + buffer->merge_clusters (buffer->idx, buffer->idx + match_length); /* * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave @@ -870,46 +874,46 @@ static inline void ligate_input (hb_apply_context_t *c, */ unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; - unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer); - unsigned int last_lig_id = get_lig_id (c->buffer->cur()); - unsigned int last_num_components = get_lig_num_comps (c->buffer->cur()); + unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (buffer); + unsigned int last_lig_id = get_lig_id (buffer->cur()); + unsigned int last_num_components = get_lig_num_comps (buffer->cur()); unsigned int components_so_far = last_num_components; if (!is_mark_ligature) { - set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count); - if (_hb_glyph_info_get_general_category (&c->buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) - _hb_glyph_info_set_general_category (&c->buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER); + set_lig_props_for_ligature (buffer->cur(), lig_id, total_component_count); + if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER); } c->replace_glyph (lig_glyph, klass); for (unsigned int i = 1; i < count; i++) { - while (c->buffer->idx < match_positions[i]) + while (buffer->idx < match_positions[i]) { if (!is_mark_ligature) { unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components); - set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp); + MIN (MAX (get_lig_comp (buffer->cur()), 1u), last_num_components); + set_lig_props_for_mark (buffer->cur(), lig_id, new_lig_comp); } - c->buffer->next_glyph (); + buffer->next_glyph (); } - last_lig_id = get_lig_id (c->buffer->cur()); - last_num_components = get_lig_num_comps (c->buffer->cur()); + last_lig_id = get_lig_id (buffer->cur()); + last_num_components = get_lig_num_comps (buffer->cur()); components_so_far += last_num_components; /* Skip the base glyph */ - c->buffer->idx++; + buffer->idx++; } if (!is_mark_ligature && last_lig_id) { /* Re-adjust components for any marks following. */ - for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) { - if (last_lig_id == get_lig_id (c->buffer->info[i])) { + for (unsigned int i = buffer->idx; i < buffer->len; i++) { + if (last_lig_id == get_lig_id (buffer->info[i])) { unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components); - set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp); + MIN (MAX (get_lig_comp (buffer->info[i]), 1u), last_num_components); + set_lig_props_for_mark (buffer->info[i], lig_id, new_lig_comp); } else break; } commit 6cc136f7531a45e71ea08a7dc8a2187172cb813d Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 13:55:48 2013 +0200 [otlayout] Minor diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index bc7616b..2ba9978 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -752,8 +752,8 @@ static inline bool match_input (hb_apply_context_t *c, const USHORT input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, - unsigned int *end_offset = NULL, - unsigned int match_positions[MAX_CONTEXT_LENGTH] = NULL, + unsigned int *end_offset, + unsigned int match_positions[MAX_CONTEXT_LENGTH], bool *p_is_mark_ligature = NULL, unsigned int *p_total_component_count = NULL) { @@ -791,13 +791,12 @@ static inline bool match_input (hb_apply_context_t *c, unsigned int first_lig_id = get_lig_id (c->buffer->cur()); unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); - if (match_positions) - match_positions[0] = c->buffer->idx; + match_positions[0] = c->buffer->idx; for (unsigned int i = 1; i < count; i++) { if (!skippy_iter.next ()) return TRACE_RETURN (false); - if (match_positions) - match_positions[i] = skippy_iter.idx; + + match_positions[i] = skippy_iter.idx; unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]); @@ -820,8 +819,7 @@ static inline bool match_input (hb_apply_context_t *c, total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]); } - if (end_offset) - *end_offset = skippy_iter.idx - c->buffer->idx + 1; + *end_offset = skippy_iter.idx - c->buffer->idx + 1; if (p_is_mark_ligature) *p_is_mark_ligature = is_mark_ligature; commit ba6ddc421e5e440231c2ece2db1363f8e6d2ecbf Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 13:52:51 2013 +0200 [otlayout] Increase MAX_CONTEXT_LENGTH It's cheap. diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 8ef8424..1e75930 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -39,7 +39,7 @@ namespace OT { #define NOT_COVERED ((unsigned int) -1) #define MAX_NESTING_LEVEL 8 -#define MAX_CONTEXT_LENGTH 32 +#define MAX_CONTEXT_LENGTH 64 commit e714fe6d6a2633494cb1fa7170a32ca2638cbb51 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 13:49:51 2013 +0200 [otlayout] Simplify ligate_input() Shouldn't change behavior at all, but is faster / more robust. diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 1588580..a595a4b 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -663,28 +663,26 @@ struct Ligature unsigned int count = component.len; if (unlikely (count < 1)) return TRACE_RETURN (false); - unsigned int end_offset = 0; bool is_mark_ligature = false; unsigned int total_component_count = 0; + unsigned int match_length = 0; + unsigned int match_positions[MAX_CONTEXT_LENGTH]; + if (likely (!match_input (c, count, &component[1], match_glyph, NULL, - &end_offset, - NULL, + &match_length, + match_positions, &is_mark_ligature, &total_component_count))) return TRACE_RETURN (false); - /* Deal, we are forming the ligature. */ - c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + end_offset); - ligate_input (c, count, - &component[1], - match_glyph, - NULL, + match_positions, + match_length, ligGlyph, is_mark_ligature, total_component_count); diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index fde6eae..bc7616b 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -832,17 +832,16 @@ static inline bool match_input (hb_apply_context_t *c, return TRACE_RETURN (true); } static inline void ligate_input (hb_apply_context_t *c, - unsigned int count, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ - match_func_t match_func, - const void *match_data, + unsigned int count, /* Including the first glyph */ + unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */ + unsigned int match_length, hb_codepoint_t lig_glyph, bool is_mark_ligature, unsigned int total_component_count) { - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); - skippy_iter.set_match_func (match_func, match_data, input); - if (skippy_iter.has_no_chance ()) return; + TRACE_APPLY (NULL); + + c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + match_length); /* * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave @@ -888,9 +887,7 @@ static inline void ligate_input (hb_apply_context_t *c, for (unsigned int i = 1; i < count; i++) { - if (!skippy_iter.next ()) return; - - while (c->buffer->idx < skippy_iter.idx) + while (c->buffer->idx < match_positions[i]) { if (!is_mark_ligature) { unsigned int new_lig_comp = components_so_far - last_num_components + commit 6b2abdcd203204131f3017ca85c91de9d43959cd Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 13:15:43 2013 +0200 [indic] Improve clusters in presence of reph diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 943d1f6..3471aa6 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1375,7 +1375,6 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, unsigned int new_reph_pos; reph_position_t reph_pos = indic_plan->config->reph_pos; - /* XXX Figure out old behavior too */ /* 1. If reph should be positioned after post-base consonant forms, * proceed to step 5. @@ -1417,7 +1416,6 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (reph_pos == REPH_POS_AFTER_MAIN) { new_reph_pos = base; - /* XXX Skip potential pre-base reordering Ra. */ while (new_reph_pos + 1 < end && info[new_reph_pos + 1].indic_position() <= POS_AFTER_MAIN) new_reph_pos++; if (new_reph_pos < end) @@ -1490,8 +1488,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, reph_move: { - /* Yay, one big cluster! Merge before moving. */ - buffer->merge_clusters (start, end); + buffer->merge_clusters (start, new_reph_pos + 1); /* Move */ hb_glyph_info_t reph = info[start]; commit 42d0f55cbc68285e22d713df7062e520af708c82 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 13:05:05 2013 +0200 [indic] Apply calt,clig in the same stage as presentation features Whic means these twp are applied per-syllable now. Apparently in some Khmer fonts the clig interacts with presentation features. Test case: U+1781,U+17D2,U+1789,U+17BB,U+17C6 with Mondulkiri-R.ttf should produce one big ligature. diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 75d4cad..943d1f6 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -447,6 +447,10 @@ collect_features_indic (hb_ot_shape_planner_t *plan) for (; i < INDIC_NUM_FEATURES; i++) { map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); } + + map->add_global_bool_feature (HB_TAG('c','a','l','t')); + map->add_global_bool_feature (HB_TAG('c','l','i','g')); + map->add_gsub_pause (clear_syllables); } commit ae9a5834df477006686421d494b55a1569789327 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 12:24:55 2013 +0200 [indic] Fix pref vs blwf interaction If a glyph can be both blwf and pref, we were wrongly sorting it in the post position instead of below position. diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 07f231b..75d4cad 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -581,15 +581,15 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, * to work. */ bool zero_context = indic_plan->is_old_spec ? false : true; hb_codepoint_t glyphs_r[2] = {glyphs[1], glyphs[0]}; - if (indic_plan->pref.would_substitute (glyphs , 2, zero_context, face) || - indic_plan->pref.would_substitute (glyphs_r, 2, zero_context, face)) - return POS_POST_C; if (indic_plan->blwf.would_substitute (glyphs , 2, zero_context, face) || indic_plan->blwf.would_substitute (glyphs_r, 2, zero_context, face)) return POS_BELOW_C; if (indic_plan->pstf.would_substitute (glyphs , 2, zero_context, face) || indic_plan->pstf.would_substitute (glyphs_r, 2, zero_context, face)) return POS_POST_C; + if (indic_plan->pref.would_substitute (glyphs , 2, zero_context, face) || + indic_plan->pref.would_substitute (glyphs_r, 2, zero_context, face)) + return POS_POST_C; return POS_BASE_C; } commit c7dacac02cfe8526eaf131ce6c5e7b6df7ca2ccd Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 17 12:20:24 2013 +0200 [indic] Don't apply blwf before base under old-spec mode Test case: U+09AC,U+09CD,U+09A6 with Lohit-Bengali 2.5.3. diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index a98c540..07f231b 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -997,7 +997,8 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Pre-base */ mask = indic_plan->mask_array[HALF]; - if (indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST) + if (!indic_plan->is_old_spec && + indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST) mask |= indic_plan->mask_array[BLWF]; for (unsigned int i = start; i < base; i++) info[i].mask |= mask; _______________________________________________ HarfBuzz mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/harfbuzz
