[GSUB] Don't ligate glyphs attached to different components of ligatures
authorBehdad Esfahbod <behdad@behdad.org>
Mon, 30 Jul 2012 04:51:47 +0000 (00:51 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Mon, 30 Jul 2012 04:51:47 +0000 (00:51 -0400)
This concludes the mark-attachment vs ligating interaction fixes (for now).

src/hb-ot-layout-gsub-table.hh

index 0a3e9da..b5520ed 100644 (file)
@@ -518,6 +518,11 @@ struct Ligature
      *
      *   This in fact happened to a font...  See:
      *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
+     *
+     * - Ligatures cannot be formed across glyphs attached to different components
+     *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
+     *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
+     *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
      */
 
     bool is_mark_ligature = !!(c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
@@ -525,6 +530,9 @@ struct Ligature
     unsigned int total_component_count = 0;
     total_component_count += get_lig_num_comps (c->buffer->cur());
 
+    unsigned int first_lig_id = get_lig_id (c->buffer->cur());
+    unsigned int first_lig_comp = get_lig_comp (c->buffer->cur());
+
     for (unsigned int i = 1; i < count; i++)
     {
       unsigned int property;
@@ -533,6 +541,22 @@ struct Ligature
 
       if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) return TRACE_RETURN (false);
 
+      unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]);
+      unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]);
+      if (first_lig_id && first_lig_comp) {
+        /* If first component was attached to a previous ligature component,
+        * all subsequent components should be attached to the same ligature
+        * component, otherwise we shouldn't ligate them. */
+        if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
+         return TRACE_RETURN (false);
+      } else {
+        /* If first component was NOT attached to a previous ligature component,
+        * all subsequent components should also NOT be attached to any ligature
+        * component, otherwise we shouldn't ligate them. */
+        if (this_lig_id && this_lig_comp)
+         return TRACE_RETURN (false);
+      }
+
       is_mark_ligature = is_mark_ligature && (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
       total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]);
     }