[Indic] Reorder left matras to be closer to base
authorBehdad Esfahbod <behdad@behdad.org>
Thu, 10 May 2012 10:53:53 +0000 (12:53 +0200)
committerBehdad Esfahbod <behdad@behdad.org>
Thu, 10 May 2012 10:53:53 +0000 (12:53 +0200)
src/hb-ot-shape-complex-indic-private.hh
src/hb-ot-shape-complex-indic.cc

index 681391e..8f5144e 100644 (file)
@@ -67,10 +67,6 @@ enum indic_position_t {
   POS_LEFT_MATRA,
 
   POS_PRE_C,
-
-  POS_BEFORE_HALFS,
-  POS_HALFS,
-
   POS_BASE_C,
   POS_ABOVE_C,
   POS_BELOW_C,
index 67628ae..ad8b967 100644 (file)
@@ -462,14 +462,32 @@ static void
 final_reordering_syllable (hb_buffer_t *buffer,
                           unsigned int start, unsigned int end)
 {
+  hb_glyph_info_t *info = buffer->info;
+
   /* 4. Final reordering:
    *
    * After the localized forms and basic shaping forms GSUB features have been
    * applied (see below), the shaping engine performs some final glyph
    * reordering before applying all the remaining font features to the entire
    * cluster.
-   *
-   *   o Reorder matras:
+   */
+
+  /* Find base again */
+  unsigned int base = end;
+  for (unsigned int i = start; i < end; i++)
+    if (info[i].indic_position() == POS_BASE_C) {
+      base = i;
+      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;
+  }
+
+  /*   o Reorder matras:
    *
    *     If a pre-base matra character had been reordered before applying basic
    *     features, the glyph can be moved closer to the main consonant based on
@@ -477,8 +495,32 @@ final_reordering_syllable (hb_buffer_t *buffer,
    *     defined as “after last standalone halant glyph, after initial matra
    *     position and before the main consonant”. If ZWJ or ZWNJ follow this
    *     halant, position is moved after it.
-   *
-   *   o Reorder reph:
+   */
+
+  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--;
+  /* If we found no Halant we are done.  Otherwise... */
+  if (info[new_matra_pos].indic_category() == OT_H) {
+    /* -> 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_category () == OT_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;
+       new_matra_pos--;
+      }
+  }
+
+
+  /*   o Reorder reph:
    *
    *     Reph’s original position is always at the beginning of the syllable,
    *     (i.e. it is not reordered at the character reordering stage). However,