From 82b521aeb7cc73879b44ca4278d6fa8b4347527f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 19 Jun 2015 11:57:57 -0700 Subject: [PATCH] Rewrite hide_default_ignorables Separate the loops for the two cases of replacing with space and deleting. For deleting, use the out-buffer machinery. Needed for upcoming cluster merge fix. --- src/hb-buffer-private.hh | 18 +++++++++++ src/hb-ot-shape.cc | 65 ++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh index 069f92558..6a339628b 100644 --- a/src/hb-buffer-private.hh +++ b/src/hb-buffer-private.hh @@ -151,6 +151,24 @@ 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++; } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 5fb0e0537..568860469 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -647,45 +647,58 @@ hb_ot_position (hb_ot_shape_context_t *c) static void hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) { - if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) - return; + hb_buffer_t *buffer = c->buffer; - hb_codepoint_t space; - enum { - SPACE_DONT_KNOW, - SPACE_AVAILABLE, - SPACE_UNAVAILABLE - } space_status = SPACE_DONT_KNOW; + if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) + return; - unsigned int count = c->buffer->len; - hb_glyph_info_t *info = c->buffer->info; - hb_glyph_position_t *pos = c->buffer->pos; - unsigned int j = 0; - for (unsigned int i = 0; i < count; i++) + 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]))) - { - if (space_status == SPACE_DONT_KNOW) - space_status = c->font->get_glyph (' ', 0, &space) ? SPACE_AVAILABLE : SPACE_UNAVAILABLE; + break; + } + + /* No default-ignorables found; return. */ + if (i == count) + return; - if (space_status == SPACE_AVAILABLE) + 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 = 0; - pos[i].y_advance = 0; + pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0; } - else - continue; /* Delete it. XXX Merge clusters? */ } - if (j != i) + } + else + { + /* Merge clusters and delete default-ignorables. */ + buffer->clear_output (); + buffer->idx = 0; + buffer->next_glyphs (i); + while (buffer->idx < buffer->len) { - info[j] = info[i]; - pos[j] = pos[i]; + if (!_hb_glyph_info_ligated (&info[buffer->idx]) && + _hb_glyph_info_is_default_ignorable (&info[buffer->idx])) + { + buffer->skip_glyph (); + continue; + } + buffer->next_glyph (); } - j++; + buffer->swap_buffers (); } - c->buffer->len = j; }