[HarfBuzz] harfbuzz: Branch 'master' - 5 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Jul 17 12:59:36 PDT 2014


 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 <behdad at 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 <behdad at 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 <behdad at 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 <behdad at 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 <behdad at 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]


More information about the HarfBuzz mailing list