[ot] Hide default-ignorables before finishing off positioning
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 22 Jul 2015 16:36:23 +0000 (17:36 +0100)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 22 Jul 2015 16:36:23 +0000 (17:36 +0100)
For example, fixes the following sequence with Arial XP:
628 25cc 651 25cc 64e 3a 20 628 651 34f 64e
628 25cc 64e 25cc 651 3a 20 628 64e 34f 651

Discovered as part of:
https://bugs.freedesktop.org/show_bug.cgi?id=85873

src/hb-ot-shape.cc

index d290cad..59c58fd 100644 (file)
@@ -411,6 +411,65 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
   }
 }
 
+
+static void
+hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
+{
+  hb_buffer_t *buffer = c->buffer;
+
+  if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
+    return;
+
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+  unsigned int i = 0;
+  for (i = 0; i < count; i++)
+  {
+    if (unlikely (!_hb_glyph_info_ligated (&info[i]) &&
+                 _hb_glyph_info_is_default_ignorable (&info[i])))
+      break;
+  }
+
+  /* No default-ignorables found; return. */
+  if (i == count)
+    return;
+
+  hb_codepoint_t space;
+  if (c->font->get_glyph (' ', 0, &space))
+  {
+    /* Replace default-ignorables with a zero-advance space glyph. */
+    for (/*continue*/; i < count; i++)
+    {
+      if (!_hb_glyph_info_ligated (&info[i]) &&
+          _hb_glyph_info_is_default_ignorable (&info[i]))
+      {
+       info[i].codepoint = space;
+       pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
+      }
+    }
+  }
+  else
+  {
+    /* Merge clusters and delete default-ignorables. */
+    buffer->clear_output ();
+    buffer->idx = 0;
+    buffer->next_glyphs (i);
+    while (buffer->idx < buffer->len)
+    {
+      if (!_hb_glyph_info_ligated (&info[buffer->idx]) &&
+          _hb_glyph_info_is_default_ignorable (&info[buffer->idx]))
+      {
+       buffer->delete_glyph ();
+       continue;
+      }
+      buffer->next_glyph ();
+    }
+    buffer->swap_buffers ();
+  }
+}
+
+
 static inline void
 hb_ot_map_glyphs_fast (hb_buffer_t  *buffer)
 {
@@ -656,6 +715,10 @@ hb_ot_position (hb_ot_shape_context_t *c)
 
   hb_bool_t fallback = !hb_ot_position_complex (c);
 
+  /* Need to do this here, since position_finish and fallback positioning
+   * might be affected by width of default_ignorables. */
+  hb_ot_hide_default_ignorables (c);
+
   hb_ot_layout_position_finish (c->font, c->buffer);
 
   if (fallback && c->plan->shaper->fallback_position)
@@ -673,66 +736,6 @@ hb_ot_position (hb_ot_shape_context_t *c)
 }
 
 
-/* Post-process */
-
-static void
-hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
-{
-  hb_buffer_t *buffer = c->buffer;
-
-  if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
-    return;
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  unsigned int i = 0;
-  for (i = 0; i < count; i++)
-  {
-    if (unlikely (!_hb_glyph_info_ligated (&info[i]) &&
-                 _hb_glyph_info_is_default_ignorable (&info[i])))
-      break;
-  }
-
-  /* No default-ignorables found; return. */
-  if (i == count)
-    return;
-
-  hb_codepoint_t space;
-  if (c->font->get_glyph (' ', 0, &space))
-  {
-    /* Replace default-ignorables with a zero-advance space glyph. */
-    for (/*continue*/; i < count; i++)
-    {
-      if (!_hb_glyph_info_ligated (&info[i]) &&
-          _hb_glyph_info_is_default_ignorable (&info[i]))
-      {
-       info[i].codepoint = space;
-       pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
-      }
-    }
-  }
-  else
-  {
-    /* Merge clusters and delete default-ignorables. */
-    buffer->clear_output ();
-    buffer->idx = 0;
-    buffer->next_glyphs (i);
-    while (buffer->idx < buffer->len)
-    {
-      if (!_hb_glyph_info_ligated (&info[buffer->idx]) &&
-          _hb_glyph_info_is_default_ignorable (&info[buffer->idx]))
-      {
-       buffer->delete_glyph ();
-       continue;
-      }
-      buffer->next_glyph ();
-    }
-    buffer->swap_buffers ();
-  }
-}
-
-
 /* Pull it all together! */
 
 static void
@@ -756,8 +759,6 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
   hb_ot_substitute (c);
   hb_ot_position (c);
 
-  hb_ot_hide_default_ignorables (c);
-
   _hb_buffer_deallocate_unicode_vars (c->buffer);
 
   c->buffer->props.direction = c->target_direction;