From 6a091df9b403b147ef78f3974610dedf4ce1e08a Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad@behdad.org>
Date: Fri, 11 May 2012 21:42:27 +0200
Subject: [PATCH] [Indic] Disambiguate sub vs post vs above matras

Bengali is at *just* above 5% now.
---
 src/hb-ot-shape-complex-indic-private.hh | 31 ++++++++++++------------
 src/hb-ot-shape-complex-indic.cc         | 12 ++++-----
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh
index eaf1de8f3..f06ebd07d 100644
--- a/src/hb-ot-shape-complex-indic-private.hh
+++ b/src/hb-ot-shape-complex-indic-private.hh
@@ -64,16 +64,15 @@ enum indic_category_t {
 /* Visual positions in a syllable from left to right. */
 enum indic_position_t {
   POS_RA_TO_BECOME_REPH,
-  POS_LEFT_MATRA,
-
+  POS_PRE_M,
   POS_PRE_C,
   POS_BASE_C,
   POS_ABOVE_C,
+  POS_ABOVE_M,
   POS_BELOW_C,
+  POS_BELOW_M,
   POS_POST_C,
-
-  POS_MATRAS,
-
+  POS_POST_M,
   POS_SMVD
 };
 
@@ -107,10 +106,10 @@ enum indic_syllabic_category_t {
 enum indic_matra_category_t {
   INDIC_MATRA_CATEGORY_NOT_APPLICABLE		= POS_BASE_C,
 
-  INDIC_MATRA_CATEGORY_LEFT			= POS_LEFT_MATRA,
-  INDIC_MATRA_CATEGORY_TOP			= POS_MATRAS,
-  INDIC_MATRA_CATEGORY_BOTTOM			= POS_MATRAS,
-  INDIC_MATRA_CATEGORY_RIGHT			= POS_MATRAS,
+  INDIC_MATRA_CATEGORY_LEFT			= POS_PRE_M,
+  INDIC_MATRA_CATEGORY_TOP			= POS_ABOVE_M,
+  INDIC_MATRA_CATEGORY_BOTTOM			= POS_BELOW_M,
+  INDIC_MATRA_CATEGORY_RIGHT			= POS_POST_M,
 
   /* We don't really care much about these since we decompose them
    * in the generic pre-shaping layer.  They will only be used if
@@ -121,13 +120,13 @@ enum indic_matra_category_t {
    * TODO: There are some split matras without Unicode decompositions.
    * We have to figure out what to do with them.
    */
-  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT		= POS_MATRAS,
-  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		= POS_LEFT_MATRA,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM		= POS_MATRAS,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT	= POS_MATRAS,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT		= POS_LEFT_MATRA,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT	= POS_LEFT_MATRA,
-  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT		= POS_MATRAS,
+  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT		= POS_POST_M,
+  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		= POS_PRE_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_RIGHT		= POS_POST_M,
 
   INDIC_MATRA_CATEGORY_INVISIBLE		= INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
   INDIC_MATRA_CATEGORY_OVERSTRUCK		= INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 89108bf00..93b490e91 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -410,9 +410,9 @@ initial_reordering_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mas
     for (unsigned int i = start + 1; i < end; i++)
       if ((FLAG (info[i].indic_category()) & (FLAG (OT_ZWNJ) | FLAG (OT_ZWJ) | FLAG (OT_N) | FLAG (OT_H)))) {
 	info[i].indic_position() = info[i - 1].indic_position();
-	if (info[i].indic_category() == OT_H && info[i].indic_position() == POS_LEFT_MATRA)
+	if (info[i].indic_category() == OT_H && info[i].indic_position() == POS_PRE_M)
 	  for (unsigned int j = i; j > start; j--)
-	    if (info[j - 1].indic_position() != POS_LEFT_MATRA) {
+	    if (info[j - 1].indic_position() != POS_PRE_M) {
 	      info[i].indic_position() = info[j - 1].indic_position();
 	      break;
 	    }
@@ -573,14 +573,14 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *mask_array,
     /* 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_LEFT_MATRA) {
+	info[new_matra_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++;
 
       /* Now go see if there's actually any matras... */
       for (unsigned int i = new_matra_pos; i > start; i--)
-	if (info[i - 1].indic_position () == POS_LEFT_MATRA)
+	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];
@@ -703,7 +703,7 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *mask_array,
     {
       new_reph_pos = base;
       while (new_reph_pos < end &&
-	     !( FLAG (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_MATRAS) | FLAG (POS_SMVD))))
+	     !( FLAG (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_POST_M) | FLAG (POS_SMVD))))
 	new_reph_pos++;
       if (new_reph_pos < end)
         goto reph_move;
@@ -779,7 +779,7 @@ final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *mask_array,
 
 
   /* Apply 'init' to the Left Matra if it's a word start. */
-  if (info[start].indic_position () == POS_LEFT_MATRA &&
+  if (info[start].indic_position () == POS_PRE_M &&
       (!start ||
        !(FLAG (_hb_glyph_info_get_general_category (&buffer->info[start - 1])) &
 	 (FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |