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

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Jun 5 17:43:14 PDT 2014


 src/hb-ot-layout-gsub-table.hh                                          |   46 +++++++---
 src/hb-ot-layout-gsubgpos-private.hh                                    |   24 ++++-
 src/hb-ot-layout-private.hh                                             |   16 +++
 src/hb-ot-shape-complex-indic.cc                                        |    4 
 test/shaping/Makefile.am                                                |    5 -
 test/shaping/fonts/sha1sum/226bc2deab3846f1a682085f70c67d0421014144.ttf |binary
 test/shaping/tests/MANIFEST                                             |    1 
 7 files changed, 74 insertions(+), 22 deletions(-)

New commits:
commit 832a6f99b34f334b1e82b8e3a7ad137e823d203c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Jun 4 16:57:42 2014 -0400

    [indic] Don't reorder reph/pref if ligature was expanded
    
    Normally if you want to, say, conditionally prevent a 'pref', you
    would use blocking contextual matching.  Some designers instead
    form the 'pref' form, then undo it in context.  To detect that
    we now also remember glyphs that went through MultipleSubst.
    
    In the only place that this is used, Uniscribe seems to only care
    about the "last" transformation between Ligature and Multiple
    substitions.  Ie. if you ligate, expand, and ligate again, it
    moves the pref, but if you ligate and expand it doesn't.  That's
    why we clear the MULTIPLIED bit when setting LIGATED.
    
    Micro-test added.  Test: U+0D2F,0D4D,0D30 with font from:
    
    [1]
    https://code.google.com/a/google.com/p/noto-alpha/issues/detail?id=186#c29

diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index d73ddc1..2e867e3 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -295,7 +295,7 @@ struct Sequence
 
     for (unsigned int i = 0; i < count; i++) {
       _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
-      c->output_glyph (substitute.array[i], klass);
+      c->output_glyph_for_component (substitute.array[i], klass);
     }
     c->buffer->skip_glyph ();
 
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index c8926c0..4521eec 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -567,13 +567,25 @@ struct hb_apply_context_t
 
   inline void _set_glyph_props (hb_codepoint_t glyph_index,
 			  unsigned int class_guess = 0,
-			  bool ligature = false) const
+			  bool ligature = false,
+			  bool component = false) const
   {
     unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
 			  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
     add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
     if (ligature)
+    {
       add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+      /* In the only place that the MULTIPLIED bit is used, Uniscribe
+       * seems to only care about the "last" transformation between
+       * Ligature and Multiple substitions.  Ie. if you ligate, expand,
+       * and ligate again, it forgives the multiplication and acts as
+       * if only ligation happened.  As such, clear MULTIPLIED bit.
+       */
+      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    }
+    if (component)
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
     if (likely (has_glyph_classes))
       _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
     else if (class_guess)
@@ -596,10 +608,10 @@ struct hb_apply_context_t
     _set_glyph_props (glyph_index, class_guess, true);
     buffer->replace_glyph (glyph_index);
   }
-  inline void output_glyph (hb_codepoint_t glyph_index,
-			    unsigned int class_guess) const
+  inline void output_glyph_for_component (hb_codepoint_t glyph_index,
+					  unsigned int class_guess) const
   {
-    _set_glyph_props (glyph_index, class_guess);
+    _set_glyph_props (glyph_index, class_guess, false, true);
     buffer->output_glyph (glyph_index);
   }
 };
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 4f03e1b..3ded92f 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -50,9 +50,11 @@ typedef enum
   /* The following are used internally; not derived from GDEF. */
   HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED	= 0x10u,
   HB_OT_LAYOUT_GLYPH_PROPS_LIGATED	= 0x20u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED	= 0x40u,
 
   HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
-					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED
+					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+					  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
 } hb_ot_layout_glyph_class_mask_t;
 
 
@@ -381,6 +383,18 @@ _hb_glyph_info_ligated (const hb_glyph_info_t *info)
   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
 }
 
+static inline bool
+_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline bool
+_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
+}
+
 /* Allocation / deallocation. */
 
 static inline void
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 77a79a5..4b12220 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -1446,7 +1446,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
   if (start + 1 < end &&
       info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
       ((info[start].indic_category() == OT_Repha) ^
-       _hb_glyph_info_ligated (&info[start])))
+       _hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
   {
     unsigned int new_reph_pos;
     reph_position_t reph_pos = indic_plan->config->reph_pos;
@@ -1599,7 +1599,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
 	 * If pref len is longer than one, then only reorder if it ligated.  If
 	 * pref len is one, only reorder if it didn't ligate with other things. */
 	if (_hb_glyph_info_substituted (&info[i]) &&
-	    ((pref_len == 1) ^ _hb_glyph_info_ligated (&info[i])))
+	    ((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
 	{
 	  /*
 	   *       2. Try to find a target position the same way as for pre-base matra.
diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am
index db3ebbc..cefd480 100644
--- a/test/shaping/Makefile.am
+++ b/test/shaping/Makefile.am
@@ -34,7 +34,10 @@ CLEANFILES += \
 	hb_test_tools.py[co] \
 	$(NULL)
 
-TESTS = tests/context-matching.tests
+TESTS = \
+	tests/context-matching.tests \
+	tests/indic-pref-blocking.tests \
+	$(NULL)
 
 TEST_EXTENSIONS = \
 	.tests \
diff --git a/test/shaping/fonts/sha1sum/226bc2deab3846f1a682085f70c67d0421014144.ttf b/test/shaping/fonts/sha1sum/226bc2deab3846f1a682085f70c67d0421014144.ttf
new file mode 100644
index 0000000..70c0c0a
Binary files /dev/null and b/test/shaping/fonts/sha1sum/226bc2deab3846f1a682085f70c67d0421014144.ttf differ
diff --git a/test/shaping/tests/MANIFEST b/test/shaping/tests/MANIFEST
index 8a6157a..ac10e07 100644
--- a/test/shaping/tests/MANIFEST
+++ b/test/shaping/tests/MANIFEST
@@ -1 +1,2 @@
 context-matching.tests
+indic-pref-blocking.tests
commit b5be2317201774c84470167767ad83c8637cad5b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Jun 5 19:00:22 2014 -0400

    [gsub] Adjust single-length ligature subst to act like single subst

diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 60e292e..d73ddc1 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -638,6 +638,14 @@ struct Ligature
 
     if (unlikely (!count)) return TRACE_RETURN (false);
 
+    /* Special-case to make it in-place and not consider this
+     * as a "ligated" substitution. */
+    if (unlikely (count == 1))
+    {
+      c->replace_glyph (ligGlyph);
+      return TRACE_RETURN (true);
+    }
+
     bool is_mark_ligature = false;
     unsigned int total_component_count = 0;
 
commit aae69451dfbf2e3671c555c234f788c194302818
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Jun 5 18:54:44 2014 -0400

    [gsub] Minor shuffling

diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index ea761e4..60e292e 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -270,6 +270,7 @@ struct Sequence
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
+    unsigned int count = substitute.len;
 
     /* TODO:
      * Testing shows that Uniscribe actually allows zero-len susbstitute,
@@ -279,23 +280,24 @@ struct Sequence
      * buffer->move_to() makes assumptions about this too.  Perhaps fix
      * in the future after figuring out what to do with the clusters.
      */
-    if (unlikely (!substitute.len)) return TRACE_RETURN (false);
+    if (unlikely (!count)) return TRACE_RETURN (false);
 
-    unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
-			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
-    unsigned int count = substitute.len;
-    if (count == 1) /* Special-case to make it in-place. */
+    /* Special-case to make it in-place and not consider this
+     * as a "multiplied" substitution. */
+    if (unlikely (count == 1))
     {
       c->replace_glyph (substitute.array[0]);
+      return TRACE_RETURN (true);
     }
-    else
-    {
-      for (unsigned int i = 0; i < count; i++) {
-	_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
-	c->output_glyph (substitute.array[i], klass);
-      }
-      c->buffer->skip_glyph ();
+
+    unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
+			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
+
+    for (unsigned int i = 0; i < count; i++) {
+      _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
+      c->output_glyph (substitute.array[i], klass);
     }
+    c->buffer->skip_glyph ();
 
     return TRACE_RETURN (true);
   }
@@ -633,7 +635,8 @@ struct Ligature
   {
     TRACE_APPLY (this);
     unsigned int count = component.len;
-    if (unlikely (count < 1)) return TRACE_RETURN (false);
+
+    if (unlikely (!count)) return TRACE_RETURN (false);
 
     bool is_mark_ligature = false;
     unsigned int total_component_count = 0;
commit b6b304f12be917b7449b3ac9409069fcd4a27d95
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Jun 5 17:12:54 2014 -0400

    [ot] Add TODO re zero-len MultipleSubst sequences

diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 3a1a0ef..ea761e4 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -270,6 +270,15 @@ struct Sequence
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
+
+    /* TODO:
+     * Testing shows that Uniscribe actually allows zero-len susbstitute,
+     * which essentially deletes a glyph.  We don't allow for now.  It
+     * can be confusing to the client since the cluster from the deleted
+     * glyph won't be merged with any output cluster...  Also, currently
+     * buffer->move_to() makes assumptions about this too.  Perhaps fix
+     * in the future after figuring out what to do with the clusters.
+     */
     if (unlikely (!substitute.len)) return TRACE_RETURN (false);
 
     unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index cd27c05..c8926c0 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -995,7 +995,9 @@ static inline bool apply_lookup (hb_apply_context_t *c,
 
     /* Recursed lookup changed buffer len.  Adjust. */
 
-    /* end can't go back past the current match position. */
+    /* end can't go back past the current match position.
+     * Note: this is only true because we do NOT allow MultipleSubst
+     * with zero sequence len. */
     end = MAX ((int) match_positions[idx] + 1, int (end) + delta);
 
     unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */


More information about the HarfBuzz mailing list