[HarfBuzz] harfbuzz-ng: Branch 'master' - 22 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Mon Jul 16 19:20:46 PDT 2012


 src/hb-ot-layout-gsub-table.hh           |    2 
 src/hb-ot-layout-gsubgpos-private.hh     |   20 ++-
 src/hb-ot-shape-complex-arabic.cc        |    6 
 src/hb-ot-shape-complex-indic-machine.rl |    3 
 src/hb-ot-shape-complex-indic-private.hh |   13 +-
 src/hb-ot-shape-complex-indic.cc         |  199 ++++++++++++++++++++-----------
 src/hb-ot-shape-complex-misc.cc          |   18 ++
 src/hb-ot-shape-complex-private.hh       |   30 ++++
 src/hb-ot-shape.cc                       |    2 
 src/hb-unicode.cc                        |   22 +++
 10 files changed, 236 insertions(+), 79 deletions(-)

New commits:
commit af92b4cc90e4184d5bdd8037c551ed482700114f
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 20:31:24 2012 -0400

    [Indic] Disable 'kern' in Uniscribe bug compatibility mode
    
    Uniscribe does not apply 'kern' in the Indic module.  Some of the Khmer
    fonts they ship have small adjustments in the 'kern' table.  Disable
    'kern' in the Indic module under Uniscribe bug compatibility mode.
    
    Fixes some 10% of the Khmer failures.  Remains under 3% (excluding
    dotted-circle ones).

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index f8be98e..19bb75c 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -221,6 +221,9 @@ void
 _hb_ot_shape_complex_override_features_indic (hb_ot_map_builder_t *map,
 					      const hb_segment_properties_t *props HB_UNUSED)
 {
+  /* Uniscribe does not apply 'kern'. */
+  if (indic_options ().uniscribe_bug_compatible)
+    map->add_feature (HB_TAG('k','e','r','n'), 0, true);
 }
 
 
commit d96838ef951ce6170eb2dc576ebcba2262cf7008
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 20:26:57 2012 -0400

    Allow complex shapers overriding common features
    
    In a new callback...  Currently unused by all complex shapers.

diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index 54460f0..75f5fe9 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -199,6 +199,12 @@ _hb_ot_shape_complex_collect_features_arabic (hb_ot_map_builder_t *map,
   map->add_bool_feature (HB_TAG('c','s','w','h'));
 }
 
+void
+_hb_ot_shape_complex_override_features_arabic (hb_ot_map_builder_t *map,
+					       const hb_segment_properties_t *props)
+{
+}
+
 hb_ot_shape_normalization_mode_t
 _hb_ot_shape_complex_normalization_preference_arabic (void)
 {
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index d9087d6..f8be98e 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -217,6 +217,12 @@ _hb_ot_shape_complex_collect_features_indic (hb_ot_map_builder_t *map,
   }
 }
 
+void
+_hb_ot_shape_complex_override_features_indic (hb_ot_map_builder_t *map,
+					      const hb_segment_properties_t *props HB_UNUSED)
+{
+}
+
 
 hb_ot_shape_normalization_mode_t
 _hb_ot_shape_complex_normalization_preference_indic (void)
diff --git a/src/hb-ot-shape-complex-misc.cc b/src/hb-ot-shape-complex-misc.cc
index 52fbd6d..3cea734 100644
--- a/src/hb-ot-shape-complex-misc.cc
+++ b/src/hb-ot-shape-complex-misc.cc
@@ -42,6 +42,12 @@ _hb_ot_shape_complex_collect_features_default (hb_ot_map_builder_t *map HB_UNUSE
 {
 }
 
+void
+_hb_ot_shape_complex_override_features_default (hb_ot_map_builder_t *map HB_UNUSED,
+					        const hb_segment_properties_t *props HB_UNUSED)
+{
+}
+
 hb_ot_shape_normalization_mode_t
 _hb_ot_shape_complex_normalization_preference_default (void)
 {
@@ -74,6 +80,12 @@ _hb_ot_shape_complex_collect_features_hangul (hb_ot_map_builder_t *map,
     map->add_bool_feature (hangul_features[i]);
 }
 
+void
+_hb_ot_shape_complex_override_features_hangul (hb_ot_map_builder_t *map,
+					       const hb_segment_properties_t *props HB_UNUSED)
+{
+}
+
 hb_ot_shape_normalization_mode_t
 _hb_ot_shape_complex_normalization_preference_hangul (void)
 {
@@ -97,6 +109,12 @@ _hb_ot_shape_complex_collect_features_thai (hb_ot_map_builder_t *map HB_UNUSED,
 {
 }
 
+void
+_hb_ot_shape_complex_override_features_thai (hb_ot_map_builder_t *map HB_UNUSED,
+					     const hb_segment_properties_t *props HB_UNUSED)
+{
+}
+
 hb_ot_shape_normalization_mode_t
 _hb_ot_shape_complex_normalization_preference_thai (void)
 {
diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh
index d2f7959..7f74e34 100644
--- a/src/hb-ot-shape-complex-private.hh
+++ b/src/hb-ot-shape-complex-private.hh
@@ -249,6 +249,36 @@ hb_ot_shape_complex_collect_features (hb_ot_complex_shaper_t shaper,
 
 
 /*
+ * override_features()
+ *
+ * Called during shape_plan().
+ *
+ * Shapers should use map to override features and add callbacks after
+ * common features are added.
+ */
+
+typedef void hb_ot_shape_complex_override_features_func_t (hb_ot_map_builder_t *map, const hb_segment_properties_t  *props);
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+  HB_INTERNAL hb_ot_shape_complex_override_features_func_t _hb_ot_shape_complex_override_features_##name;
+  HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+
+static inline void
+hb_ot_shape_complex_override_features (hb_ot_complex_shaper_t shaper,
+				       hb_ot_map_builder_t *map,
+				       const hb_segment_properties_t  *props)
+{
+  switch (shaper) {
+    default:
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+    case hb_ot_complex_shaper_##name:	_hb_ot_shape_complex_override_features_##name (map, props); return;
+    HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+  }
+}
+
+
+/*
  * normalization_preference()
  *
  * Called during shape_execute().
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 60b028d..b5485bd 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -123,6 +123,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
   else
     ADD_FEATURES (vertical_features);
 
+  hb_ot_shape_complex_override_features (planner->shaper, &planner->map, props);
+
 #undef ADD_FEATURES
 
   for (unsigned int i = 0; i < num_user_features; i++) {
commit df50b8474094f0563ccfdae12c4425a51b72add6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 19:56:29 2012 -0400

    [Indic] Categorize other Khmer marks
    
    Mark them the same as the Register Shifters for now.  Need to rename
    that category to something more sensible after all is settled.
    
    Fixes another percent of Khmer failures.  Down to under 3%!

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index feb5136..d9087d6 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -257,6 +257,10 @@ _hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map HB_UNUSED,
     if (unlikely (hb_in_range<hb_codepoint_t> (info.codepoint, 0x0951, 0x0954)))
       info.indic_category() = OT_VD;
 
+    if (info.indic_category() == OT_X &&
+	unlikely (hb_in_range<hb_codepoint_t> (info.codepoint, 0x17CB, 0x17D0)))
+      info.indic_category() = OT_RS;
+
     if (info.indic_category() == OT_C) {
       info.indic_position() = consonant_position (info.codepoint);
       if (is_ra (info.codepoint))
commit 8e7b5882fb4c1921c9d030d354a9b998115cdb8c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 17:04:46 2012 -0400

    [Indic] Recognize pre-base reordering Ra anywhere in the syllable
    
    We were doing that only immediately after base.
    
    Fixes another percent in the Khmer failures.  About three more to go...

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 10ec5c5..feb5136 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -493,13 +493,17 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
   }
 
   /* XXX This will not match for old-Indic spec since the Halant-Ra order is reversed already. */
-  if (basic_mask_array[PREF] &&
-      base + 3 <= end &&
-      info[base + 1].indic_category() == OT_H &&
-      info[base + 2].indic_category() == OT_Ra)
+  if (basic_mask_array[PREF] && base + 3 <= end)
   {
-    info[base + 1].mask |= basic_mask_array[PREF];
-    info[base + 2].mask |= basic_mask_array[PREF];
+    /* Find a Halant,Ra sequence and mark it fore pre-base reordering processing. */
+    for (unsigned int i = base + 1; i + 1 < end; i++)
+      if (info[i].indic_category() == OT_H &&
+	  info[i + 1].indic_category() == OT_Ra)
+      {
+	info[i].mask |= basic_mask_array[PREF];
+	info[i + 1].mask |= basic_mask_array[PREF];
+	break;
+      }
   }
 
   /* Apply ZWJ/ZWNJ effects */
@@ -815,40 +819,44 @@ final_reordering_syllable (hb_buffer_t *buffer,
 
   if (pref_mask && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
   {
-    /*       1. Only reorder a glyph produced by substitution during application
-     *          of the <pref> feature. (Note that a font may shape a Ra consonant with
-     *          the feature generally but block it in certain contexts.)
-     */
-    if ((info[base + 1].mask & pref_mask) != 0 &&
-	(base + 2 == end ||
-	 (info[base + 2].mask & pref_mask) == 0))
-    {
-      /*
-       *       2. Try to find a target position the same way as for pre-base matra.
-       *          If it is found, reorder pre-base consonant glyph.
-       *
-       *       3. If position is not found, reorder immediately before main
-       *          consonant.
-       */
-
-      unsigned int new_pos = base;
-      while (new_pos > start + 1 &&
-	     !(FLAG (info[new_pos - 1].indic_category()) & (FLAG (OT_M) | FLAG (OT_H))))
-	new_pos--;
-
-      if (new_pos > start && info[new_pos - 1].indic_category() == OT_H)
-	/* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-	if (new_pos < end && is_joiner (info[new_pos]))
-	  new_pos++;
-
+    for (unsigned int i = base + 1; i < end; i++)
+      if ((info[i].mask & pref_mask) != 0)
       {
-	unsigned int old_pos = base + 1;
-	hb_glyph_info_t tmp = info[old_pos];
-	memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
-	info[new_pos] = tmp;
-	start_of_last_cluster = MIN (new_pos, start_of_last_cluster);
+	/*       1. Only reorder a glyph produced by substitution during application
+	 *          of the <pref> feature. (Note that a font may shape a Ra consonant with
+	 *          the feature generally but block it in certain contexts.)
+	 */
+	if (i + 1 == end || (info[i + 1].mask & pref_mask) == 0)
+	{
+	  /*
+	   *       2. Try to find a target position the same way as for pre-base matra.
+	   *          If it is found, reorder pre-base consonant glyph.
+	   *
+	   *       3. If position is not found, reorder immediately before main
+	   *          consonant.
+	   */
+
+	  unsigned int new_pos = base;
+	  while (new_pos > start + 1 &&
+		 !(FLAG (info[new_pos - 1].indic_category()) & (FLAG (OT_M) | FLAG (OT_H))))
+	    new_pos--;
+
+	  if (new_pos > start && info[new_pos - 1].indic_category() == OT_H)
+	    /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
+	    if (new_pos < end && is_joiner (info[new_pos]))
+	      new_pos++;
+
+	  {
+	    unsigned int old_pos = i;
+	    hb_glyph_info_t tmp = info[old_pos];
+	    memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
+	    info[new_pos] = tmp;
+	    start_of_last_cluster = MIN (new_pos, start_of_last_cluster);
+	  }
+	}
+
+        break;
       }
-    }
   }
 
 
commit 7d09c98a1fff97127e48eae48d380dc9fcff288e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 16:45:22 2012 -0400

    [Indic] Recognizer Register Shifter marks
    
    Fixes another 6% of the Khmer failures.

diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl
index 7dcbb06..77606d1 100644
--- a/src/hb-ot-shape-complex-indic-machine.rl
+++ b/src/hb-ot-shape-complex-indic-machine.rl
@@ -52,11 +52,12 @@ VD   = 10;
 A    = 11;
 NBSP = 12;
 DOTTEDCIRCLE = 13;
+RS   = 14;
 
 c = C | Ra;
 n = N N?;
 z = ZWJ|ZWNJ;
-matra_group = M N? H?;
+matra_group = (M | RS) N? H?;
 syllable_tail = SM? (VD VD?)?;
 place_holder = NBSP | DOTTEDCIRCLE;
 
diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh
index faf5616..ab44777 100644
--- a/src/hb-ot-shape-complex-indic-private.hh
+++ b/src/hb-ot-shape-complex-indic-private.hh
@@ -58,7 +58,8 @@ enum indic_category_t {
   OT_VD,
   OT_A,
   OT_NBSP,
-  OT_DOTTEDCIRCLE /* Not in the spec, but special in Uniscribe. /Very very/ special! */
+  OT_DOTTEDCIRCLE, /* Not in the spec, but special in Uniscribe. /Very very/ special! */
+  OT_RS /* Register Shifter, used in Khmer OT spec */
 };
 
 /* Visual positions in a syllable from left to right. */
@@ -92,7 +93,7 @@ enum indic_syllabic_category_t {
   INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA	= OT_C,
   INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER	= OT_X,
   INDIC_SYLLABIC_CATEGORY_NUKTA			= OT_N,
-  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER	= OT_X,
+  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER	= OT_RS,
   INDIC_SYLLABIC_CATEGORY_TONE_LETTER		= OT_X,
   INDIC_SYLLABIC_CATEGORY_TONE_MARK		= OT_X,
   INDIC_SYLLABIC_CATEGORY_VIRAMA		= OT_H,
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index fd0fe34..10ec5c5 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -261,6 +261,8 @@ _hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map HB_UNUSED,
       info.indic_position() = consonant_position (info.codepoint);
       if (is_ra (info.codepoint))
 	info.indic_category() = OT_Ra;
+    } else if (info.indic_category() == OT_RS) {
+      info.indic_position() = POS_ABOVE_M;
     } else if (info.indic_category() == OT_SM ||
 	       info.indic_category() == OT_VD) {
       info.indic_position() = POS_SMVD;
commit 60da763dfac96a7931d6e6bdef8b9973bd5209ab
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 16:13:32 2012 -0400

    [GSUB/GDEF] Guess glyph classes after substitution only if no GDEF
    
    Brings down Khmer failures with Daun Penh font from 36% to 20%.

diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 98d4e0a..06049ec 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -110,6 +110,7 @@ struct hb_apply_context_t
   unsigned int lookup_props;
   unsigned int property; /* propety of first glyph */
   unsigned int debug_depth;
+  bool has_glyph_classes;
 
 
   hb_apply_context_t (hb_font_t *font_,
@@ -120,7 +121,8 @@ struct hb_apply_context_t
 			direction (buffer_->props.direction),
 			lookup_mask (lookup_mask_),
 			nesting_level_left (MAX_NESTING_LEVEL),
-			lookup_props (0), property (0), debug_depth (0) {}
+			lookup_props (0), property (0), debug_depth (0),
+			has_glyph_classes (hb_ot_layout_has_glyph_classes (face_)) {}
 
   void set_lookup (const Lookup &l) {
     lookup_props = l.get_props ();
@@ -229,25 +231,29 @@ struct hb_apply_context_t
     return _hb_ot_layout_skip_mark (face, &buffer->cur(), lookup_props, &property);
   }
 
+  inline void set_klass_guess (unsigned int klass_guess) const
+  {
+    buffer->cur().props_cache() = has_glyph_classes ? 0 : klass_guess;
+  }
 
   inline void output_glyph (hb_codepoint_t glyph_index,
-			    unsigned int klass = 0) const
+			    unsigned int klass_guess = 0) const
   {
-    buffer->cur().props_cache() = klass; /*XXX if has gdef? */
+    set_klass_guess (klass_guess);
     buffer->output_glyph (glyph_index);
   }
   inline void replace_glyph (hb_codepoint_t glyph_index,
-			     unsigned int klass = 0) const
+			     unsigned int klass_guess = 0) const
   {
-    buffer->cur().props_cache() = klass; /*XXX if has gdef? */
+    set_klass_guess (klass_guess);
     buffer->replace_glyph (glyph_index);
   }
   inline void replace_glyphs (unsigned int num_in,
 			      unsigned int num_out,
 			      hb_codepoint_t *glyph_data,
-			      unsigned int klass = 0) const
+			      unsigned int klass_guess = 0) const
   {
-    buffer->cur().props_cache() = klass; /* XXX if has gdef? */
+    set_klass_guess (klass_guess);
     buffer->replace_glyphs (num_in, num_out, glyph_data);
   }
 };
commit fcdc5f1c8849a7f38d9f34f64d60c6d95d7501f7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:52:54 2012 -0400

    [Indic] Categorize Khmer Ro
    
    Khmer failures down from 58% to 36%.

diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh
index 85ec81a..faf5616 100644
--- a/src/hb-ot-shape-complex-indic-private.hh
+++ b/src/hb-ot-shape-complex-indic-private.hh
@@ -264,6 +264,8 @@ static const hb_codepoint_t ra_chars[] = {
   0x0C30, /* Telugu */		/* No Reph */
   0x0CB0, /* Kannada */
   0x0D30, /* Malayalam */	/* No Reph */
+
+  0x179A, /* Khmer */		/* No Reph */
 };
 
 
commit 78818124b17691ec2c647142fdb9ae743aa03dee
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:49:08 2012 -0400

    [Indic] Reoder pre-base reordering Ra
    
    Brings down Malayalam failures from 14% down to 3%.

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 394dbf7..fd0fe34 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -809,27 +809,43 @@ final_reordering_syllable (hb_buffer_t *buffer,
    *
    *     If a pre-base reordering consonant is found, reorder it according to
    *     the following rules:
-   *
-   *       1. Only reorder a glyph produced by substitution during application
-   *          of the <pref> feature. (Note that a font may shape a Ra consonant with
-   *          the feature generally but block it in certain contexts.)
-   *
-   *       2. Try to find a target position the same way as for pre-base matra.
-   *          If it is found, reorder pre-base consonant glyph.
-   *
-   *       3. If position is not found, reorder immediately before main
-   *          consonant.
    */
 
-  /* XXX */
   if (pref_mask && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
   {
+    /*       1. Only reorder a glyph produced by substitution during application
+     *          of the <pref> feature. (Note that a font may shape a Ra consonant with
+     *          the feature generally but block it in certain contexts.)
+     */
     if ((info[base + 1].mask & pref_mask) != 0 &&
 	(base + 2 == end ||
 	 (info[base + 2].mask & pref_mask) == 0))
     {
-      /* Found a pre-base reordering Ra produced by substitution during application of the
-       * <pref> feature. */
+      /*
+       *       2. Try to find a target position the same way as for pre-base matra.
+       *          If it is found, reorder pre-base consonant glyph.
+       *
+       *       3. If position is not found, reorder immediately before main
+       *          consonant.
+       */
+
+      unsigned int new_pos = base;
+      while (new_pos > start + 1 &&
+	     !(FLAG (info[new_pos - 1].indic_category()) & (FLAG (OT_M) | FLAG (OT_H))))
+	new_pos--;
+
+      if (new_pos > start && info[new_pos - 1].indic_category() == OT_H)
+	/* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
+	if (new_pos < end && is_joiner (info[new_pos]))
+	  new_pos++;
+
+      {
+	unsigned int old_pos = base + 1;
+	hb_glyph_info_t tmp = info[old_pos];
+	memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
+	info[new_pos] = tmp;
+	start_of_last_cluster = MIN (new_pos, start_of_last_cluster);
+      }
     }
   }
 
commit 1a1dbe9a2787f226f3e43063da8eb6633438b0a0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:40:33 2012 -0400

    [Indic] Rename

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index feb8b80..394dbf7 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -628,10 +628,10 @@ final_reordering_syllable (hb_buffer_t *buffer,
       for (unsigned int i = new_pos; i > start; i--)
 	if (info[i - 1].indic_position () == POS_PRE_M)
 	{
-	  unsigned int old_matra_pos = i - 1;
-	  hb_glyph_info_t matra = info[old_matra_pos];
-	  memmove (&info[old_matra_pos], &info[old_matra_pos + 1], (new_pos - old_matra_pos) * sizeof (info[0]));
-	  info[new_pos] = matra;
+	  unsigned int old_pos = i - 1;
+	  hb_glyph_info_t tmp = info[old_pos];
+	  memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
+	  info[new_pos] = tmp;
 	  start_of_last_cluster = MIN (new_pos, start_of_last_cluster);
 	  new_pos--;
 	}
commit 46e645ec4b59f0a278347be11f40c7df700d5bb6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:30:05 2012 -0400

    [Indic] Start implementing pre-base reordering

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 9c4b3e4..feb8b80 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -181,11 +181,6 @@ indic_other_features[] =
   {HB_TAG('b','l','w','m'), true},
 };
 
-/* Same order as the indic_other_features array */
-enum {
-  INIT
-};
-
 
 static void
 initial_reordering (const hb_ot_map_t *map,
@@ -581,7 +576,8 @@ initial_reordering (const hb_ot_map_t *map,
 }
 
 static void
-final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
+final_reordering_syllable (hb_buffer_t *buffer,
+			   hb_mask_t init_mask, hb_mask_t pref_mask,
 			   unsigned int start, unsigned int end)
 {
   hb_glyph_info_t *info = buffer->info;
@@ -825,8 +821,17 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
    *          consonant.
    */
 
-  /* TODO */
-
+  /* XXX */
+  if (pref_mask && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
+  {
+    if ((info[base + 1].mask & pref_mask) != 0 &&
+	(base + 2 == end ||
+	 (info[base + 2].mask & pref_mask) == 0))
+    {
+      /* Found a pre-base reordering Ra produced by substitution during application of the
+       * <pref> feature. */
+    }
+  }
 
 
   /* Apply 'init' to the Left Matra if it's a word start. */
@@ -841,7 +846,7 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))))
-    info[start].mask |= other_mask_array[INIT];
+    info[start].mask |= init_mask;
 
 
 
@@ -876,21 +881,19 @@ final_reordering (const hb_ot_map_t *map,
   unsigned int count = buffer->len;
   if (!count) return;
 
-  hb_mask_t other_mask_array[ARRAY_LENGTH (indic_other_features)] = {0};
-  unsigned int num_masks = ARRAY_LENGTH (indic_other_features);
-  for (unsigned int i = 0; i < num_masks; i++)
-    other_mask_array[i] = map->get_1_mask (indic_other_features[i].tag);
+  hb_mask_t init_mask = map->get_1_mask (HB_TAG('i','n','i','t'));
+  hb_mask_t pref_mask = map->get_1_mask (HB_TAG('p','r','e','f'));
 
   hb_glyph_info_t *info = buffer->info;
   unsigned int last = 0;
   unsigned int last_syllable = info[0].syllable();
   for (unsigned int i = 1; i < count; i++)
     if (last_syllable != info[i].syllable()) {
-      final_reordering_syllable (buffer, other_mask_array, last, i);
+      final_reordering_syllable (buffer, init_mask, pref_mask, last, i);
       last = i;
       last_syllable = info[last].syllable();
     }
-  final_reordering_syllable (buffer, other_mask_array, last, count);
+  final_reordering_syllable (buffer, init_mask, pref_mask, last, count);
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
   HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
commit 921ce5b17daf06af8e17989a3e335b9f5df20483
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:26:56 2012 -0400

    [Indic] Rename
    
    No semantic change.

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index b3d8def..9c4b3e4 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -616,28 +616,28 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
 
   if (start < base) /* Otherwise there can't be any pre-base matra characters. */
   {
-    unsigned int new_matra_pos = base - 1;
-    while (new_matra_pos > start &&
-	   !(FLAG (info[new_matra_pos].indic_category()) & (FLAG (OT_M) | FLAG (OT_H))))
-      new_matra_pos--;
+    unsigned int new_pos = base - 1;
+    while (new_pos > start &&
+	   !(FLAG (info[new_pos].indic_category()) & (FLAG (OT_M) | FLAG (OT_H))))
+      new_pos--;
     /* If we found no Halant we are done.  Otherwise only proceed if the Halant does
      * not belong to the Matra itself! */
-    if (info[new_matra_pos].indic_category() == OT_H &&
-	info[new_matra_pos].indic_position() != POS_PRE_M) {
+    if (info[new_pos].indic_category() == OT_H &&
+	info[new_pos].indic_position() != POS_PRE_M) {
       /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-      if (new_matra_pos + 1 < end && is_joiner (info[new_matra_pos + 1]))
-	new_matra_pos++;
+      if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
+	new_pos++;
 
       /* Now go see if there's actually any matras... */
-      for (unsigned int i = new_matra_pos; i > start; i--)
+      for (unsigned int i = new_pos; i > start; i--)
 	if (info[i - 1].indic_position () == POS_PRE_M)
 	{
 	  unsigned int old_matra_pos = i - 1;
 	  hb_glyph_info_t matra = info[old_matra_pos];
-	  memmove (&info[old_matra_pos], &info[old_matra_pos + 1], (new_matra_pos - old_matra_pos) * sizeof (info[0]));
-	  info[new_matra_pos] = matra;
-	  start_of_last_cluster = MIN (new_matra_pos, start_of_last_cluster);
-	  new_matra_pos--;
+	  memmove (&info[old_matra_pos], &info[old_matra_pos + 1], (new_pos - old_matra_pos) * sizeof (info[0]));
+	  info[new_pos] = matra;
+	  start_of_last_cluster = MIN (new_pos, start_of_last_cluster);
+	  new_pos--;
 	}
     }
   }
commit b504e060f008e95b1ba36c06600c9fea4f5d4808
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:21:12 2012 -0400

    [Indic] Implement After-Main Reph positioning
    
    Almost...

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 7725eda..b3d8def 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -736,7 +736,13 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
      */
     if (reph_pos == REPH_AFTER_MAIN)
     {
-      /* XXX */
+      new_reph_pos = base;
+      /* XXX Skip potential pre-base reordering Ra. */
+      while (new_reph_pos < end &&
+	     !( FLAG (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_BELOW_C) | FLAG (POS_POST_C) | FLAG (POS_POST_M) | FLAG (POS_SMVD))))
+	new_reph_pos++;
+      if (new_reph_pos < end)
+        goto reph_move;
     }
 
     /*       4. If reph should be positioned before post-base consonant, find
commit 17d7de91d76406d3e92db37d9eef2fc615f06e68
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:20:15 2012 -0400

    [Indic] Apply 'pref' to pre-base reodering Ra
    
    No reordering yet.

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 682f5cd..7725eda 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -495,6 +495,16 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
       info[i].mask  |= mask;
   }
 
+  /* XXX This will not match for old-Indic spec since the Halant-Ra order is reversed already. */
+  if (basic_mask_array[PREF] &&
+      base + 3 <= end &&
+      info[base + 1].indic_category() == OT_H &&
+      info[base + 2].indic_category() == OT_Ra)
+  {
+    info[base + 1].mask |= basic_mask_array[PREF];
+    info[base + 2].mask |= basic_mask_array[PREF];
+  }
+
   /* Apply ZWJ/ZWNJ effects */
   for (unsigned int i = start + 1; i < end; i++)
     if (is_joiner (info[i])) {
commit 362d3db8d3527d0fef260a17d2466e92a4a25425
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 15:15:28 2012 -0400

    [Indic] Minor
    
    Should not be any semantic change.  In preparation for implementing
    pre-base reordering Ra.

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index b820aea..682f5cd 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -592,13 +592,6 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
       break;
     }
 
-  if (base == start) {
-    /* There's no Reph, and no left Matra to reposition.  Just merge the cluster
-     * and go home. */
-    buffer->merge_clusters (start, end);
-    return;
-  }
-
   unsigned int start_of_last_cluster = base;
 
   /*   o Reorder matras:
@@ -611,6 +604,7 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
    *     halant, position is moved after it.
    */
 
+  if (start < base) /* Otherwise there can't be any pre-base matra characters. */
   {
     unsigned int new_matra_pos = base - 1;
     while (new_matra_pos > start &&
commit 70fe77bb9a25922bd34f206826d8731d901fb451
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 14:52:18 2012 -0400

    Minor

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 564b980..b820aea 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -291,7 +291,7 @@ compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
  * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
 
 static void
-initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
+initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *basic_mask_array,
 				       unsigned int start, unsigned int end)
 {
   hb_glyph_info_t *info = buffer->info;
@@ -319,7 +319,7 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
      *    and has more than one consonant, Ra is excluded from candidates for
      *    base consonants. */
     unsigned int limit = start;
-    if (mask_array[RPHF] &&
+    if (basic_mask_array[RPHF] &&
 	start + 3 <= end &&
 	info[start].indic_category() == OT_Ra &&
 	info[start + 1].indic_category() == OT_H &&
@@ -480,17 +480,17 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
 
     /* Reph */
     for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
-      info[i].mask |= mask_array[RPHF];
+      info[i].mask |= basic_mask_array[RPHF];
 
     /* Pre-base */
-    mask = mask_array[HALF] | mask_array[AKHN] | mask_array[CJCT];
+    mask = basic_mask_array[HALF] | basic_mask_array[AKHN] | basic_mask_array[CJCT];
     for (unsigned int i = start; i < base; i++)
       info[i].mask  |= mask;
     /* Base */
-    mask = mask_array[AKHN] | mask_array[CJCT];
+    mask = basic_mask_array[AKHN] | basic_mask_array[CJCT];
     info[base].mask |= mask;
     /* Post-base */
-    mask = mask_array[BLWF] | mask_array[ABVF] | mask_array[PSTF] | mask_array[CJCT];
+    mask = basic_mask_array[BLWF] | basic_mask_array[ABVF] | basic_mask_array[PSTF] | basic_mask_array[CJCT];
     for (unsigned int i = base + 1; i < end; i++)
       info[i].mask  |= mask;
   }
@@ -504,9 +504,9 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
       do {
 	j--;
 
-	info[j].mask &= ~mask_array[CJCT];
+	info[j].mask &= ~basic_mask_array[CJCT];
 	if (non_joiner)
-	  info[j].mask &= ~mask_array[HALF];
+	  info[j].mask &= ~basic_mask_array[HALF];
 
       } while (j > start && !is_consonant (info[j]));
     }
@@ -516,17 +516,17 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
 static void
 initial_reordering_vowel_syllable (const hb_ot_map_t *map,
 				   hb_buffer_t *buffer,
-				   hb_mask_t *mask_array,
+				   hb_mask_t *basic_mask_array,
 				   unsigned int start, unsigned int end)
 {
   /* We made the vowels look like consonants.  So let's call the consonant logic! */
-  initial_reordering_consonant_syllable (map, buffer, mask_array, start, end);
+  initial_reordering_consonant_syllable (map, buffer, basic_mask_array, start, end);
 }
 
 static void
 initial_reordering_standalone_cluster (const hb_ot_map_t *map,
 				       hb_buffer_t *buffer,
-				       hb_mask_t *mask_array,
+				       hb_mask_t *basic_mask_array,
 				       unsigned int start, unsigned int end)
 {
   /* We treat NBSP/dotted-circle as if they are consonants, so we should just chain.
@@ -541,13 +541,13 @@ initial_reordering_standalone_cluster (const hb_ot_map_t *map,
       return;
   }
 
-  initial_reordering_consonant_syllable (map, buffer, mask_array, start, end);
+  initial_reordering_consonant_syllable (map, buffer, basic_mask_array, start, end);
 }
 
 static void
 initial_reordering_non_indic (const hb_ot_map_t *map HB_UNUSED,
 			      hb_buffer_t *buffer HB_UNUSED,
-			      hb_mask_t *mask_array HB_UNUSED,
+			      hb_mask_t *basic_mask_array HB_UNUSED,
 			      unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
 {
   /* Nothing to do right now.  If we ever switch to using the output
@@ -562,16 +562,16 @@ initial_reordering (const hb_ot_map_t *map,
 		    hb_buffer_t *buffer,
 		    void *user_data HB_UNUSED)
 {
-  hb_mask_t mask_array[ARRAY_LENGTH (indic_basic_features)] = {0};
+  hb_mask_t basic_mask_array[ARRAY_LENGTH (indic_basic_features)] = {0};
   unsigned int num_masks = ARRAY_LENGTH (indic_basic_features);
   for (unsigned int i = 0; i < num_masks; i++)
-    mask_array[i] = map->get_1_mask (indic_basic_features[i].tag);
+    basic_mask_array[i] = map->get_1_mask (indic_basic_features[i].tag);
 
-  find_syllables (map, buffer, mask_array);
+  find_syllables (map, buffer, basic_mask_array);
 }
 
 static void
-final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *mask_array,
+final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *other_mask_array,
 			   unsigned int start, unsigned int end)
 {
   hb_glyph_info_t *info = buffer->info;
@@ -831,7 +831,7 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *mask_array,
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))))
-    info[start].mask |= mask_array[INIT];
+    info[start].mask |= other_mask_array[INIT];
 
 
 
@@ -866,21 +866,21 @@ final_reordering (const hb_ot_map_t *map,
   unsigned int count = buffer->len;
   if (!count) return;
 
-  hb_mask_t mask_array[ARRAY_LENGTH (indic_other_features)] = {0};
+  hb_mask_t other_mask_array[ARRAY_LENGTH (indic_other_features)] = {0};
   unsigned int num_masks = ARRAY_LENGTH (indic_other_features);
   for (unsigned int i = 0; i < num_masks; i++)
-    mask_array[i] = map->get_1_mask (indic_other_features[i].tag);
+    other_mask_array[i] = map->get_1_mask (indic_other_features[i].tag);
 
   hb_glyph_info_t *info = buffer->info;
   unsigned int last = 0;
   unsigned int last_syllable = info[0].syllable();
   for (unsigned int i = 1; i < count; i++)
     if (last_syllable != info[i].syllable()) {
-      final_reordering_syllable (buffer, mask_array, last, i);
+      final_reordering_syllable (buffer, other_mask_array, last, i);
       last = i;
       last_syllable = info[last].syllable();
     }
-  final_reordering_syllable (buffer, mask_array, last, count);
+  final_reordering_syllable (buffer, other_mask_array, last, count);
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
   HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
commit 2f903215c5da2330a37abe489a3f45f7c3fd5a09
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 13:54:43 2012 -0400

    Minor

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 1bc3d4b..564b980 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -805,7 +805,7 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *mask_array,
    *     the following rules:
    *
    *       1. Only reorder a glyph produced by substitution during application
-   *          of the feature. (Note that a font may shape a Ra consonant with
+   *          of the <pref> feature. (Note that a font may shape a Ra consonant with
    *          the feature generally but block it in certain contexts.)
    *
    *       2. Try to find a target position the same way as for pre-base matra.
commit a3e04bee2c2fa648759a87e460db6b4f1b685586
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 13:47:19 2012 -0400

    [Indic] Reorder virama only for old Indic spec

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 3ebd23a..1bc3d4b 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -27,6 +27,18 @@
 #include "hb-ot-shape-complex-indic-private.hh"
 #include "hb-ot-shape-private.hh"
 
+#define OLD_INDIC_TAG(script) (((hb_tag_t) script) | 0x20000000)
+#define IS_OLD_INDIC_TAG(tag) ( \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_BENGALI) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_DEVANAGARI) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_GUJARATI) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_GURMUKHI) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_KANNADA) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_MALAYALAM) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_ORIYA) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_TAMIL) || \
+				(tag) == OLD_INDIC_TAG (HB_SCRIPT_TELUGU) \
+			      )
 struct indic_options_t
 {
   int initialized : 1;
@@ -405,8 +417,7 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
 
   /* For old-style Indic script tags, move the first post-base Halant after
    * last consonant. */
-  if ((map->get_chosen_script (0) & 0x000000FF) != '2') {
-    /* We should only do this for Indic scripts which have a version two I guess. */
+  if (IS_OLD_INDIC_TAG (map->get_chosen_script (0))) {
     for (unsigned int i = base + 1; i < end; i++)
       if (info[i].indic_category() == OT_H) {
         unsigned int j;
commit 0de771b72da6b342b015e3556190821547a4011d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 13:39:36 2012 -0400

    [Indic] Categorize Khmer consonants

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index d838f16..3ebd23a 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -80,6 +80,10 @@ consonant_position (hb_codepoint_t u)
 {
   consonant_position_t *record;
 
+  /* Khmer does not have pre-base half forms. */
+  if (0x1780 <= u && u <= 0x17FF)
+    return POS_BELOW_C;
+
   record = (consonant_position_t *) bsearch (&u, consonant_positions,
 					     ARRAY_LENGTH (consonant_positions),
 					     sizeof (consonant_positions[0]),
commit d487fff266258eb1af056e9704cfb09d04251ddc
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 13:25:17 2012 -0400

    Split matras without a Unicode decomposition
    
    This is a hack for now, to get us going with Khmer.  This will be
    refactored properly later to move the complex logic into complex
    shapers.

diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index 1d6eacb..7a5aa6c 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -267,6 +267,28 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
 		      hb_codepoint_t     *a,
 		      hb_codepoint_t     *b)
 {
+  /* XXX FIXME, move these to complex shapers and propagage to normalizer.*/
+  switch (ab) {
+    case 0x0AC9  : *a = 0x0AC5; *b= 0x0ABE; return true;
+    case 0x0F77  : *a = 0x0FB2; *b= 0x0F81; return true;
+    case 0x0F79  : *a = 0x0FB3; *b= 0x0F81; return true;
+    case 0x17BE  : *a = 0x17C1; *b= 0x17BE; return true;
+    case 0x17BF  : *a = 0x17C1; *b= 0x17BF; return true;
+    case 0x17C0  : *a = 0x17C1; *b= 0x17C0; return true;
+    case 0x17C4  : *a = 0x17C1; *b= 0x17C4; return true;
+    case 0x17C5  : *a = 0x17C1; *b= 0x17C5; return true;
+    case 0x1925  : *a = 0x1920; *b= 0x1923; return true;
+    case 0x1926  : *a = 0x1920; *b= 0x1924; return true;
+    case 0x1B3C  : *a = 0x1B42; *b= 0x1B3C; return true;
+    case 0x1112E  : *a = 0x11127; *b= 0x11131; return true;
+    case 0x1112F  : *a = 0x11127; *b= 0x11132; return true;
+#if 0
+    case 0x0B57  : *a = 0xno decomp, -> RIGHT; return true;
+    case 0x1C29  : *a = 0xno decomp, -> LEFT; return true;
+    case 0xA9C0  : *a = 0xno decomp, -> RIGHT; return true;
+    case 0x111BF  : *a = 0xno decomp, -> ABOVE; return true;
+#endif
+  }
   *a = ab; *b = 0;
   return ufuncs->func.decompose (ufuncs, ab, a, b, ufuncs->user_data.decompose);
 }
commit 8aa801a6fd1a737fa20b851edf7528bdd6635b8b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 13:24:26 2012 -0400

    [Indic] Adjust position for split matras
    
    We are going to split matras without a Unicode decompositions in a way
    that the second half takes the codepoint of the whole matra.  So,
    position them where the second half is supposed to end up.

diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh
index 64af0da..85ec81a 100644
--- a/src/hb-ot-shape-complex-indic-private.hh
+++ b/src/hb-ot-shape-complex-indic-private.hh
@@ -121,11 +121,11 @@ enum indic_matra_category_t {
    * We have to figure out what to do with them.
    */
   INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT		= POS_POST_M,
-  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		= POS_PRE_M,
+  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		= POS_POST_M,
   INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM		= POS_BELOW_M,
   INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT	= POS_POST_M,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT		= POS_PRE_M,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT	= POS_PRE_M,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT		= POS_ABOVE_M,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT	= POS_POST_M,
   INDIC_MATRA_CATEGORY_TOP_AND_RIGHT		= POS_POST_M,
 
   INDIC_MATRA_CATEGORY_INVISIBLE		= INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
commit 1feb8345a5fd92297eb6796e6dce633bafa0c76e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 13:23:40 2012 -0400

    [GSUB] Allow 1-to-1 ligature substitutions!
    
    Apparently Uniscribe allows these, and they are used in some Khmer fonts
    shipped with Windows, namely, Daun Penh.

diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index f5f38cc..8a0bc3c 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -480,7 +480,7 @@ struct Ligature
   {
     TRACE_APPLY ();
     unsigned int count = component.len;
-    if (unlikely (count < 2)) return TRACE_RETURN (false);
+    if (unlikely (count < 1)) return TRACE_RETURN (false);
 
     hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
     if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
commit 29f106d7fba25e1464debd3a4831a7380d75c4c9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Jul 16 12:05:35 2012 -0400

    [Indic] Apply Above Forms

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index f168fe1..d838f16 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -129,6 +129,7 @@ indic_basic_features[] =
   {HB_TAG('p','r','e','f'), false},
   {HB_TAG('b','l','w','f'), false},
   {HB_TAG('h','a','l','f'), false},
+  {HB_TAG('a','b','v','f'), false},
   {HB_TAG('p','s','t','f'), false},
   {HB_TAG('c','j','c','t'), false},
   {HB_TAG('v','a','t','u'), true},
@@ -143,6 +144,7 @@ enum {
   PREF,
   BLWF,
   HALF,
+  ABVF,
   PSTF,
   CJCT,
   VATU
@@ -473,7 +475,7 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
     mask = mask_array[AKHN] | mask_array[CJCT];
     info[base].mask |= mask;
     /* Post-base */
-    mask = mask_array[BLWF] | mask_array[PSTF] | mask_array[CJCT];
+    mask = mask_array[BLWF] | mask_array[ABVF] | mask_array[PSTF] | mask_array[CJCT];
     for (unsigned int i = base + 1; i < end; i++)
       info[i].mask  |= mask;
   }



More information about the HarfBuzz mailing list