When removing default-ignorables, merge clusters
authorBehdad Esfahbod <behdad@behdad.org>
Fri, 19 Jun 2015 20:31:49 +0000 (13:31 -0700)
committerBehdad Esfahbod <behdad@behdad.org>
Fri, 19 Jun 2015 20:31:49 +0000 (13:31 -0700)
Fixes test-shape, and:
https://code.google.com/p/chromium/issues/detail?id=497578

src/hb-buffer-private.hh
src/hb-buffer.cc
src/hb-ot-shape.cc

index 6a33962..ced748f 100644 (file)
@@ -192,6 +192,8 @@ struct hb_buffer_t {
                                   unsigned int end);
   HB_INTERNAL void merge_out_clusters (unsigned int start,
                                       unsigned int end);
+  /* Merge clusters for deleting current glyph, and skip it. */
+  HB_INTERNAL void delete_glyph (void);
 
   /* Internal methods */
   HB_INTERNAL bool enlarge (unsigned int size);
index e13ee4a..4f953f0 100644 (file)
@@ -529,7 +529,7 @@ hb_buffer_t::merge_clusters (unsigned int start,
 
   /* If we hit the start of buffer, continue in out-buffer. */
   if (idx == start)
-    for (unsigned i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
+    for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
       out_info[i - 1].cluster = cluster;
 
   for (unsigned int i = start; i < end; i++)
@@ -561,12 +561,44 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
 
   /* If we hit the end of out-buffer, continue in buffer. */
   if (end == out_len)
-    for (unsigned i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
+    for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
       info[i].cluster = cluster;
 
   for (unsigned int i = start; i < end; i++)
     out_info[i].cluster = cluster;
 }
+void
+hb_buffer_t::delete_glyph ()
+{
+  unsigned int cluster = info[idx].cluster;
+  if (idx + 1 < len && cluster == info[idx + 1].cluster)
+  {
+    /* Cluster survives; do nothing. */
+    goto done;
+  }
+
+  if (out_len)
+  {
+    /* Merge cluster backward. */
+    if (cluster < out_info[out_len - 1].cluster)
+    {
+      unsigned int old_cluster = out_info[out_len - 1].cluster;
+      for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
+       out_info[i - 1].cluster = cluster;
+    }
+    goto done;
+  }
+
+  if (idx + 1 < len)
+  {
+    /* Merge cluster forward. */
+    merge_clusters (idx, idx + 2);
+    goto done;
+  }
+
+done:
+  skip_glyph ();
+}
 
 void
 hb_buffer_t::guess_segment_properties (void)
index 5688604..a531d77 100644 (file)
@@ -692,7 +692,7 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
       if (!_hb_glyph_info_ligated (&info[buffer->idx]) &&
           _hb_glyph_info_is_default_ignorable (&info[buffer->idx]))
       {
-        buffer->skip_glyph ();
+       buffer->delete_glyph ();
        continue;
       }
       buffer->next_glyph ();