src/hb-fallback-shape.cc | 36 +-- src/hb-ot-shape-complex-arabic.cc | 106 ++++++---- src/hb-ot-shape-complex-indic.cc | 15 - src/hb-ot-shape-complex-myanmar.cc | 7 src/hb-ot-shape-complex-sea.cc | 7 src/hb-ot-shape-fallback.cc | 30 +- src/hb-ot-shape.cc | 18 + src/hb-unicode-private.hh | 3 test/shaping/Makefile.am | 2 test/shaping/fonts/sha1sum/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf |binary test/shaping/fonts/sha1sum/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf |binary test/shaping/fonts/sha1sum/MANIFEST | 4 test/shaping/fonts/sha1sum/a919b33197965846f21074b24e30250d67277bce.ttf |binary test/shaping/fonts/sha1sum/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf |binary test/shaping/record-test.sh | 5 test/shaping/tests/MANIFEST | 1 test/shaping/tests/arabic-feature-order.tests | 3 test/shaping/tests/mongolian-variation-selector.tests | 1 18 files changed, 155 insertions(+), 83 deletions(-)
New commits: commit 82f4d9d53f348f41b14b877c1ac77c0372c49caa Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Jul 17 15:57:37 2014 -0400 [arabic] Add note re disabled 'cswh' diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 1b4ebc9..b90abfe 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -184,6 +184,15 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_gsub_pause (NULL); + /* The spec includes 'cswh'. Earlier versions of Windows + * used to enable this by default, but testing suggests + * that Windows 8 and later do not enable it by default, + * and spec now says 'Off by default'. + * We disabled this in ae23c24c32. + * Note that IranNastaliq uses this feature extensively + * to fixup broken glyph sequences. Oh well... + * Test case: U+0643,U+0640,U+0631. */ + map->add_global_bool_feature (HB_TAG('c','s','w','h')); map->add_global_bool_feature (HB_TAG('m','s','e','t')); } commit 615d00ea252739da57edbd980ff27e573f88ee7e Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Jul 17 13:36:09 2014 -0400 [arabic] Apply init/medi/isol/fini/... in separate stages Follows the order of the Arabic/Syriac specs. Also don't stop between rlig and calt in non-Arabic scripts. Micro-tests for Arabic and Mongolian added for the latter. diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 3c59743..1b4ebc9 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -68,31 +68,30 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ ) ? JOINING_TYPE_T : JOINING_TYPE_U; } +#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3') + static const hb_tag_t arabic_features[] = { - HB_TAG('i','n','i','t'), - HB_TAG('m','e','d','i'), - HB_TAG('f','i','n','a'), HB_TAG('i','s','o','l'), - /* Syriac */ - HB_TAG('m','e','d','2'), + HB_TAG('f','i','n','a'), HB_TAG('f','i','n','2'), HB_TAG('f','i','n','3'), + HB_TAG('m','e','d','i'), + HB_TAG('m','e','d','2'), + HB_TAG('i','n','i','t'), HB_TAG_NONE }; /* Same order as the feature array */ enum { - INIT, - MEDI, - FINA, ISOL, - - /* Syriac */ - MED2, + FINA, FIN2, FIN3, + MEDI, + MED2, + INIT, NONE, @@ -145,14 +144,23 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) { hb_ot_map_builder_t *map = &plan->map; - /* For Language forms (in ArabicOT speak), we do the iso/fina/medi/init together, - * then rlig and calt each in their own stage. This makes IranNastaliq's ALLAH - * ligature work correctly. It's unfortunate though... + /* We apply features according to the Arabic spec, with pauses + * in between most. * - * This also makes Arial Bold in Windows7 work. See: + * The pause between init/medi/... and rlig is required. See eg: * https://bugzilla.mozilla.org/show_bug.cgi?id=644184 * - * TODO: Add test cases for these two. + * The pauses between init/medi/... themselves are not necessarily + * needed as only one of those features is applied to any character. + * The only difference it makes is when fonts have contextual + * substitutions. We now follow the order of the spec, which makes + * for better experience if that's what Uniscribe is doing. + * + * At least for Arabic, looks like Uniscribe has a pause between + * rlig and calt. Otherwise the IranNastaliq's ALLAH ligature won't + * work. However, testing shows that rlig and calt are applied + * together for Mongolian in Uniscribe. As such, we only add a + * pause for Arabic, not other scripts. */ map->add_gsub_pause (nuke_joiners); @@ -163,12 +171,15 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_gsub_pause (NULL); for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) - map->add_feature (arabic_features[i], 1, i < 4 ? F_HAS_FALLBACK : F_NONE); /* The first four features have fallback. */ - - map->add_gsub_pause (NULL); + { + bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]); + map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE); + map->add_gsub_pause (NULL); + } map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK); - map->add_gsub_pause (arabic_fallback_shape); + if (plan->props.script == HB_SCRIPT_ARABIC) + map->add_gsub_pause (arabic_fallback_shape); map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_gsub_pause (NULL); @@ -202,8 +213,9 @@ data_create_arabic (const hb_ot_shape_plan_t *plan) arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC; for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) { arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]); - if (i < 4) - arabic_plan->do_fallback = arabic_plan->do_fallback && plan->map.needs_fallback (arabic_features[i]); + arabic_plan->do_fallback = arabic_plan->do_fallback && + !FEATURE_IS_SYRIAC (arabic_features[i]) && + plan->map.needs_fallback (arabic_features[i]); } return arabic_plan; diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index 33f75ab..3f43aec 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -36,8 +36,10 @@ CLEANFILES += \ $(NULL) TESTS = \ + tests/arabic-feature-order.tests \ tests/context-matching.tests \ tests/indic-pref-blocking.tests \ + tests/mongolian-variation-selector.tests \ $(NULL) TEST_EXTENSIONS = \ diff --git a/test/shaping/fonts/sha1sum/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf b/test/shaping/fonts/sha1sum/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf new file mode 100644 index 0000000..b728b27 Binary files /dev/null and b/test/shaping/fonts/sha1sum/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf differ diff --git a/test/shaping/fonts/sha1sum/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf b/test/shaping/fonts/sha1sum/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf new file mode 100644 index 0000000..875c699 Binary files /dev/null and b/test/shaping/fonts/sha1sum/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf differ diff --git a/test/shaping/fonts/sha1sum/MANIFEST b/test/shaping/fonts/sha1sum/MANIFEST index d1ff350..0e52060 100644 --- a/test/shaping/fonts/sha1sum/MANIFEST +++ b/test/shaping/fonts/sha1sum/MANIFEST @@ -1,6 +1,9 @@ 226bc2deab3846f1a682085f70c67d0421014144.ttf 37033cc5cf37bb223d7355153016b6ccece93b28.ttf 4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf +813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf +8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf +a919b33197965846f21074b24e30250d67277bce.ttf d629e7fedc0b350222d7987345fe61613fa3929a.ttf e207635780b42f898d58654b65098763e340f5c7.ttf ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf diff --git a/test/shaping/fonts/sha1sum/a919b33197965846f21074b24e30250d67277bce.ttf b/test/shaping/fonts/sha1sum/a919b33197965846f21074b24e30250d67277bce.ttf new file mode 100644 index 0000000..d2f116e Binary files /dev/null and b/test/shaping/fonts/sha1sum/a919b33197965846f21074b24e30250d67277bce.ttf differ diff --git a/test/shaping/tests/MANIFEST b/test/shaping/tests/MANIFEST index 024169d..1b577c7 100644 --- a/test/shaping/tests/MANIFEST +++ b/test/shaping/tests/MANIFEST @@ -1,3 +1,4 @@ +arabic-feature-order.tests context-matching.tests indic-pref-blocking.tests mongolian-variation-selector.tests diff --git a/test/shaping/tests/arabic-feature-order.tests b/test/shaping/tests/arabic-feature-order.tests new file mode 100644 index 0000000..3e3cf6a --- /dev/null +++ b/test/shaping/tests/arabic-feature-order.tests @@ -0,0 +1,3 @@ +fonts/sha1sum/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf:U+1820,U+180B:[uni2048.E81A=0+1550] +fonts/sha1sum/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf:U+1820,U+180B:[uni2048.E81A=0+1550] +fonts/sha1sum/a919b33197965846f21074b24e30250d67277bce.ttf:U+0644,U+0644,U+0647:[Lellah=0+1503] commit d21e997035b16e9807dfb29c3605abb93f92f1ee Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Jul 17 15:27:46 2014 -0400 [test] Make record_test understand cmdline args to hb-shape diff --git a/test/shaping/record-test.sh b/test/shaping/record-test.sh index 384d87f..81087f7 100755 --- a/test/shaping/record-test.sh +++ b/test/shaping/record-test.sh @@ -3,7 +3,10 @@ dir=`mktemp --directory` hb_shape=$1 -fontfile=$2 +shift +fontfile=$1 +shift +hb_shape="$hb_shape $@" unicodes=`./hb-unicode-decode` text=`./hb-unicode-encode "$unicodes"` glyphs=`echo "$text" | $hb_shape "$fontfile"` commit 7cd33f230441093dbfb1fec48f8c580ee8d9ef71 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Jul 17 14:22:11 2014 -0400 Micro optimization diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc index ea54bb8..9d061a9 100644 --- a/src/hb-fallback-shape.cc +++ b/src/hb-fallback-shape.cc @@ -105,34 +105,36 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, * shaper which many people unfortunately still request. */ - bool has_space; hb_codepoint_t space; - has_space = font->get_glyph (' ', 0, &space); + bool has_space = font->get_glyph (' ', 0, &space); buffer->clear_positions (); + hb_direction_t direction = buffer->props.direction; + hb_unicode_funcs_t *unicode = buffer->unicode; unsigned int count = buffer->len; - + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; for (unsigned int i = 0; i < count; i++) { - if (has_space && buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) { - buffer->info[i].codepoint = space; - buffer->pos[i].x_advance = 0; - buffer->pos[i].y_advance = 0; + if (has_space && unicode->is_default_ignorable (info[i].codepoint)) { + info[i].codepoint = space; + pos[i].x_advance = 0; + pos[i].y_advance = 0; continue; } - font->get_glyph (buffer->info[i].codepoint, 0, &buffer->info[i].codepoint); - font->get_glyph_advance_for_direction (buffer->info[i].codepoint, - buffer->props.direction, - &buffer->pos[i].x_advance, - &buffer->pos[i].y_advance); - font->subtract_glyph_origin_for_direction (buffer->info[i].codepoint, - buffer->props.direction, - &buffer->pos[i].x_offset, - &buffer->pos[i].y_offset); + font->get_glyph (info[i].codepoint, 0, &info[i].codepoint); + font->get_glyph_advance_for_direction (info[i].codepoint, + direction, + &pos[i].x_advance, + &pos[i].y_advance); + font->subtract_glyph_origin_for_direction (info[i].codepoint, + direction, + &pos[i].x_offset, + &pos[i].y_offset); } - if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) hb_buffer_reverse (buffer); return true; diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 5dd60a5..3c59743 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -223,6 +223,7 @@ static void arabic_joining (hb_buffer_t *buffer) { unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; unsigned int prev = (unsigned int) -1, state = 0; /* Check pre-context */ @@ -241,19 +242,19 @@ arabic_joining (hb_buffer_t *buffer) for (unsigned int i = 0; i < count; i++) { - unsigned int this_type = get_joining_type (buffer->info[i].codepoint, _hb_glyph_info_get_general_category (&buffer->info[i])); + unsigned int this_type = get_joining_type (info[i].codepoint, _hb_glyph_info_get_general_category (&info[i])); if (unlikely (this_type == JOINING_TYPE_T)) { - buffer->info[i].arabic_shaping_action() = NONE; + info[i].arabic_shaping_action() = NONE; continue; } const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; if (entry->prev_action != NONE && prev != (unsigned int) -1) - buffer->info[prev].arabic_shaping_action() = entry->prev_action; + info[prev].arabic_shaping_action() = entry->prev_action; - buffer->info[i].arabic_shaping_action() = entry->curr_action; + info[i].arabic_shaping_action() = entry->curr_action; prev = i; state = entry->next_state; @@ -269,7 +270,7 @@ arabic_joining (hb_buffer_t *buffer) const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; if (entry->prev_action != NONE && prev != (unsigned int) -1) - buffer->info[prev].arabic_shaping_action() = entry->prev_action; + info[prev].arabic_shaping_action() = entry->prev_action; break; } } @@ -299,8 +300,9 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, mongolian_variation_selectors (buffer); unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()]; + info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()]; HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } @@ -312,9 +314,10 @@ nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer) { unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if (_hb_glyph_info_is_zwj (&buffer->info[i])) - _hb_glyph_info_flip_joiners (&buffer->info[i]); + if (_hb_glyph_info_is_zwj (&info[i])) + _hb_glyph_info_flip_joiners (&info[i]); } static void diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 5bb1f33..33215a3 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -635,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 @@ -673,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); } } } @@ -1228,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; } diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index 8b2c00c..258ccc4 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -277,8 +277,9 @@ setup_masks_myanmar (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_myanmar_properties (buffer->info[i]); + set_myanmar_properties (info[i]); } static void @@ -451,8 +452,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; } diff --git a/src/hb-ot-shape-complex-sea.cc b/src/hb-ot-shape-complex-sea.cc index a4adb8f..f08b7cc 100644 --- a/src/hb-ot-shape-complex-sea.cc +++ b/src/hb-ot-shape-complex-sea.cc @@ -174,8 +174,9 @@ setup_masks_sea (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_sea_properties (buffer->info[i]); + set_sea_properties (info[i]); } static void @@ -278,8 +279,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; } diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc index 89eab28..a774f95 100644 --- a/src/hb-ot-shape-fallback.cc +++ b/src/hb-ot-shape-fallback.cc @@ -167,11 +167,12 @@ _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *pla hb_buffer_t *buffer) { unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { - unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]); - combining_class = recategorize_combining_class (buffer->info[i].codepoint, combining_class); - _hb_glyph_info_set_modified_combining_class (&buffer->info[i], combining_class); + if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]); + combining_class = recategorize_combining_class (info[i].codepoint, combining_class); + _hb_glyph_info_set_modified_combining_class (&info[i], combining_class); } } @@ -181,8 +182,9 @@ zero_mark_advances (hb_buffer_t *buffer, unsigned int start, unsigned int end) { + hb_glyph_info_t *info = buffer->info; for (unsigned int i = start; i < end; i++) - if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { buffer->pos[i].x_advance = 0; buffer->pos[i].y_advance = 0; @@ -327,12 +329,13 @@ position_around_base (const hb_ot_shape_plan_t *plan, unsigned int last_lig_component = (unsigned int) -1; unsigned int last_combining_class = 255; hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */ + hb_glyph_info_t *info = buffer->info; for (unsigned int i = base + 1; i < end; i++) - if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i])) + if (_hb_glyph_info_get_modified_combining_class (&info[i])) { if (num_lig_components > 1) { - unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[i]); - unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&buffer->info[i]) - 1; + unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]); + unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1; /* Conditions for attaching to the last component. */ if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components) this_lig_component = num_lig_components - 1; @@ -355,7 +358,7 @@ position_around_base (const hb_ot_shape_plan_t *plan, } } - unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]); + unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]); if (last_combining_class != this_combining_class) { last_combining_class = this_combining_class; @@ -391,13 +394,14 @@ position_cluster (const hb_ot_shape_plan_t *plan, return; /* Find the base glyph */ + hb_glyph_info_t *info = buffer->info; for (unsigned int i = start; i < end; i++) - if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i]))) + if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))) { /* Find mark glyphs */ unsigned int j; for (j = i + 1; j < end; j++) - if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[j]))) + if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j]))) break; position_around_base (plan, font, buffer, i, j); @@ -432,15 +436,13 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, { if (!plan->has_kern) return; - unsigned int count = buffer->len; - OT::hb_apply_context_t c (1, font, buffer); c.set_lookup_mask (plan->kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); + unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pos = buffer->pos; - for (unsigned int idx = 0; idx < count;) { OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1); diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 736eefd..1f99014 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -227,8 +227,9 @@ static void hb_set_unicode_props (hb_buffer_t *buffer) { unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - _hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode); + _hb_glyph_info_set_unicode_props (&info[i], buffer->unicode); } static void @@ -263,8 +264,9 @@ static void hb_form_clusters (hb_buffer_t *buffer) { unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) - if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i]))) + if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))) buffer->merge_clusters (i - 1, i + 1); } @@ -382,8 +384,9 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer) { /* Normalization process sets up glyph_index(), we just copy it. */ unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - buffer->info[i].codepoint = buffer->info[i].glyph_index(); + info[i].codepoint = info[i].glyph_index(); } static inline void @@ -483,8 +486,9 @@ static inline void zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets) { unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { if (adjust_offsets) adjust_mark_offsets (&buffer->pos[i]); @@ -496,8 +500,9 @@ static inline void zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets) { unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if (_hb_glyph_info_is_mark (&buffer->info[i])) + if (_hb_glyph_info_is_mark (&info[i])) { if (adjust_offsets) adjust_mark_offsets (&buffer->pos[i]); @@ -773,8 +778,9 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL; unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - add_char (font, buffer->unicode, mirror, buffer->info[i].codepoint, glyphs); + add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs); hb_set_t lookups; lookups.init (); commit 164c13d73f67fdddba28e6409d76b4903e8ffab3 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Jul 17 14:16:38 2014 -0400 Another try to fix Mongolian free variation selectors This reverts bf029281 and fixes it properly. That commit was not enough as it was only inheriting the shaping_action for prev_action, but not curr_action. Micro-test added. https://code.google.com/p/chromium/issues/detail?id=393896 diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index b7aa694..5dd60a5 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -225,8 +225,6 @@ arabic_joining (hb_buffer_t *buffer) unsigned int count = buffer->len; unsigned int prev = (unsigned int) -1, state = 0; - HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action); - /* Check pre-context */ if (!(buffer->flags & HB_BUFFER_FLAG_BOT)) for (unsigned int i = 0; i < buffer->context_len[0]; i++) @@ -253,8 +251,7 @@ arabic_joining (hb_buffer_t *buffer) const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; if (entry->prev_action != NONE && prev != (unsigned int) -1) - for (; prev < i; prev++) - buffer->info[prev].arabic_shaping_action() = entry->prev_action; + buffer->info[prev].arabic_shaping_action() = entry->prev_action; buffer->info[i].arabic_shaping_action() = entry->curr_action; @@ -275,9 +272,17 @@ arabic_joining (hb_buffer_t *buffer) buffer->info[prev].arabic_shaping_action() = entry->prev_action; break; } +} - - HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); +static void +mongolian_variation_selectors (hb_buffer_t *buffer) +{ + /* Copy arabic_shaping_action() from base to Mongolian variation selectors. */ + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 1; i < count; i++) + if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du))) + info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action(); } static void @@ -285,12 +290,19 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, hb_font_t *font HB_UNUSED) { + HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action); + const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; arabic_joining (buffer); + if (plan->props.script == HB_SCRIPT_MONGOLIAN) + mongolian_variation_selectors (buffer); + unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()]; + + HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh index 6652015..a2c59da 100644 --- a/src/hb-unicode-private.hh +++ b/src/hb-unicode-private.hh @@ -122,8 +122,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE static inline hb_bool_t is_variation_selector (hb_codepoint_t unicode) { + /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the + * Arabic shaper. No need to match them here. */ return unlikely (hb_in_ranges (unicode, - 0x180Bu, 0x180Du, /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */ 0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */ 0xE0100u, 0xE01EFu)); /* VARIATION SELECTOR-17..256 */ } diff --git a/test/shaping/fonts/sha1sum/MANIFEST b/test/shaping/fonts/sha1sum/MANIFEST index 427f433..d1ff350 100644 --- a/test/shaping/fonts/sha1sum/MANIFEST +++ b/test/shaping/fonts/sha1sum/MANIFEST @@ -3,4 +3,5 @@ 4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf d629e7fedc0b350222d7987345fe61613fa3929a.ttf e207635780b42f898d58654b65098763e340f5c7.ttf +ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf f499fbc23865022234775c43503bba2e63978fe1.ttf diff --git a/test/shaping/fonts/sha1sum/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf b/test/shaping/fonts/sha1sum/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf new file mode 100644 index 0000000..629c470 Binary files /dev/null and b/test/shaping/fonts/sha1sum/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf differ diff --git a/test/shaping/tests/mongolian-variation-selector.tests b/test/shaping/tests/mongolian-variation-selector.tests index 043fa18..86a2fd1 100644 --- a/test/shaping/tests/mongolian-variation-selector.tests +++ b/test/shaping/tests/mongolian-variation-selector.tests @@ -1 +1,2 @@ fonts/sha1sum/37033cc5cf37bb223d7355153016b6ccece93b28.ttf:U+1826,U+180B,U+1826:[uni1826.E85E_ue.init1=0+599|uni1826.E856_ue.fina=2+750] +fonts/sha1sum/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf:U+1820,U+180B:[uni1820.E821_a.isol1=0+1199] _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/harfbuzz