Fix hide-ignorables if font doesn't have space glyph
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 22 Jul 2015 17:28:39 +0000 (18:28 +0100)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 22 Jul 2015 17:29:47 +0000 (18:29 +0100)
Was broken by 82b521aeb7cc73879b44ca4278d6fa8b4347527f, as we have
positioning data by then and can't use the output buffer.  Ouch!

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

index 3a2db48..9aa5e7d 100644 (file)
@@ -152,24 +152,6 @@ struct hb_buffer_t {
 
     idx++;
   }
-  inline void
-  next_glyphs (unsigned int count)
-  {
-    if (have_output)
-    {
-      if (unlikely (out_info != info || out_len != idx)) {
-       if (unlikely (!make_room_for (count, count))) return;
-       {
-         while (count--)
-           out_info[out_len++] = info[idx++];
-         return;
-       }
-      }
-      out_len += count;
-    }
-
-    idx += count;
-  }
 
   /* Advance idx without copying to output. */
   inline void skip_glyph (void) { idx++; }
index 33b13b5..cf5ae87 100644 (file)
@@ -449,20 +449,46 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
   }
   else
   {
-    /* Merge clusters and delete default-ignorables. */
-    buffer->clear_output ();
-    buffer->idx = 0;
-    buffer->next_glyphs (i);
-    while (buffer->idx < buffer->len)
+    /* Merge clusters and delete default-ignorables.
+     * NOTE! We can't use out-buffer as we have positioning data. */
+    unsigned int j = i;
+    for (; i < count; i++)
     {
-      if (_hb_glyph_info_is_default_ignorable (&info[buffer->idx]))
+      if (_hb_glyph_info_is_default_ignorable (&info[i]))
       {
-       buffer->delete_glyph ();
+       /* Merge clusters.
+        * Same logic as buffer->delete_glyph(), but for in-place removal. */
+
+       unsigned int cluster = info[i].cluster;
+       if (i + 1 < count && cluster == info[i + 1].cluster)
+         continue; /* Cluster survives; do nothing. */
+
+       if (j)
+       {
+         /* Merge cluster backward. */
+         if (cluster < info[j - 1].cluster)
+         {
+           unsigned int old_cluster = info[j - 1].cluster;
+           for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
+             info[k - 1].cluster = cluster;
+         }
+         continue;
+       }
+
+       if (i + 1 < count)
+         buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
+
        continue;
       }
-      buffer->next_glyph ();
+
+      if (j != i)
+      {
+       info[j] = info[i];
+       pos[j] = pos[i];
+      }
+      j++;
     }
-    buffer->swap_buffers ();
+    buffer->len = j;
   }
 }