X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fhb-buffer.cc;h=ea05307a224f81b36cdc3c9c166dc87da35c63f6;hb=45d6f29f15f1d2323bcaa2498aed23ff0c8a1567;hp=7cf5adcd66373df9c652305c363713e912ac53c9;hpb=d4bee9f813bb299b1c4aab7c33d588be2a7d354b;p=framework%2Fuifw%2Fharfbuzz.git diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 7cf5adc..ea05307 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -34,6 +34,11 @@ HB_BEGIN_DECLS +#ifndef HB_DEBUG_BUFFER +#define HB_DEBUG_BUFFER (HB_DEBUG+0) +#endif + + static hb_buffer_t _hb_buffer_nil = { HB_OBJECT_HEADER_STATIC, @@ -43,6 +48,10 @@ static hb_buffer_t _hb_buffer_nil = { HB_SCRIPT_INVALID, NULL, }, + + TRUE, /* in_error */ + TRUE, /* have_output */ + TRUE /* have_positions */ }; /* Here is how the buffer works internally: @@ -53,407 +62,554 @@ static hb_buffer_t _hb_buffer_nil = { * As an optimization, both info and out_info may point to the * same piece of memory, which is owned by info. This remains the * case as long as out_len doesn't exceed i at any time. - * In that case, swap() is no-op and the glyph operations operate + * In that case, swap_buffers() is no-op and the glyph operations operate * mostly in-place. * * As soon as out_info gets longer than info, out_info is moved over * to an alternate buffer (which we reuse the pos buffer for!), and its * current contents (out_len entries) are copied to the new place. - * This should all remain transparent to the user. swap() then + * This should all remain transparent to the user. swap_buffers() then * switches info and out_info. */ -static hb_bool_t -_hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size) + +/* Internal API */ + +bool +hb_buffer_t::enlarge (unsigned int size) { - if (unlikely (buffer->in_error)) + if (unlikely (in_error)) return FALSE; - unsigned int new_allocated = buffer->allocated; - hb_glyph_position_t *new_pos; - hb_glyph_info_t *new_info; - bool separate_out; + unsigned int new_allocated = allocated; + hb_glyph_position_t *new_pos = NULL; + hb_glyph_info_t *new_info = NULL; + bool separate_out = out_info != info; - separate_out = buffer->out_info != buffer->info; + if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0])))) + goto done; while (size > new_allocated) - new_allocated += (new_allocated >> 1) + 8; + new_allocated += (new_allocated >> 1) + 32; - ASSERT_STATIC (sizeof (buffer->info[0]) == sizeof (buffer->pos[0])); - bool overflows = new_allocated >= ((unsigned int) -1) / sizeof (buffer->info[0]); + ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0])); + if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0])))) + goto done; - if (unlikely (overflows)) { - new_pos = NULL; - new_info = NULL; - } else { - new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0])); - new_info = (hb_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof (buffer->info[0])); - } + new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0])); + new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0])); +done: if (unlikely (!new_pos || !new_info)) - buffer->in_error = TRUE; + in_error = TRUE; if (likely (new_pos)) - buffer->pos = new_pos; + pos = new_pos; if (likely (new_info)) - buffer->info = new_info; + info = new_info; - buffer->out_info = separate_out ? (hb_glyph_info_t *) buffer->pos : buffer->info; - if (likely (!buffer->in_error)) - buffer->allocated = new_allocated; + out_info = separate_out ? (hb_glyph_info_t *) pos : info; + if (likely (!in_error)) + allocated = new_allocated; - return likely (!buffer->in_error); -} - -static inline hb_bool_t -_hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size) -{ - return likely (size <= buffer->allocated) ? TRUE : _hb_buffer_enlarge (buffer, size); + return likely (!in_error); } -static inline hb_bool_t -_hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size) +bool +hb_buffer_t::make_room_for (unsigned int num_in, + unsigned int num_out) { - if (unlikely (!_hb_buffer_ensure (buffer, size))) return FALSE; + if (unlikely (!ensure (out_len + num_out))) return FALSE; - if (buffer->out_info == buffer->info) + if (out_info == info && + out_len + num_out > idx + num_in) { - assert (buffer->have_output); + assert (have_output); - buffer->out_info = (hb_glyph_info_t *) buffer->pos; - memcpy (buffer->out_info, buffer->info, buffer->out_len * sizeof (buffer->out_info[0])); + out_info = (hb_glyph_info_t *) pos; + memcpy (out_info, info, out_len * sizeof (out_info[0])); } return TRUE; } -/* Public API */ +/* HarfBuzz-Internal API */ -hb_buffer_t * -hb_buffer_create (unsigned int pre_alloc_size) +void +hb_buffer_t::reset (void) { - hb_buffer_t *buffer; + if (unlikely (hb_object_is_inert (this))) + return; - if (!HB_OBJECT_DO_CREATE (hb_buffer_t, buffer)) - return &_hb_buffer_nil; + hb_unicode_funcs_destroy (unicode); + unicode = _hb_buffer_nil.unicode; - if (pre_alloc_size) - _hb_buffer_ensure (buffer, pre_alloc_size); + props = _hb_buffer_nil.props; - hb_buffer_reset (buffer); + in_error = FALSE; + have_output = FALSE; + have_positions = FALSE; - return buffer; -} + idx = 0; + len = 0; + out_len = 0; -hb_buffer_t * -hb_buffer_reference (hb_buffer_t *buffer) -{ - HB_OBJECT_DO_REFERENCE (buffer); + serial = 0; + memset (allocated_var_bytes, 0, sizeof allocated_var_bytes); + memset (allocated_var_owner, 0, sizeof allocated_var_owner); + + out_info = info; } void -hb_buffer_destroy (hb_buffer_t *buffer) +hb_buffer_t::add (hb_codepoint_t codepoint, + hb_mask_t mask, + unsigned int cluster) { - HB_OBJECT_DO_DESTROY (buffer); + hb_glyph_info_t *glyph; - hb_unicode_funcs_destroy (buffer->unicode); + if (unlikely (!ensure (len + 1))) return; - free (buffer->info); - free (buffer->pos); + glyph = &info[len]; - free (buffer); -} + memset (glyph, 0, sizeof (*glyph)); + glyph->codepoint = codepoint; + glyph->mask = mask; + glyph->cluster = cluster; + len++; +} void -hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, - hb_unicode_funcs_t *unicode) +hb_buffer_t::clear_output (void) { - if (!unicode) - unicode = &_hb_unicode_funcs_default; + if (unlikely (hb_object_is_inert (this))) + return; - hb_unicode_funcs_reference (unicode); - hb_unicode_funcs_destroy (buffer->unicode); - buffer->unicode = unicode; + have_output = TRUE; + have_positions = FALSE; + + out_len = 0; + out_info = info; } -hb_unicode_funcs_t * -hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) +void +hb_buffer_t::clear_positions (void) { - return buffer->unicode; + if (unlikely (hb_object_is_inert (this))) + return; + + have_output = FALSE; + have_positions = TRUE; + + memset (pos, 0, sizeof (pos[0]) * len); } void -hb_buffer_set_direction (hb_buffer_t *buffer, - hb_direction_t direction) - +hb_buffer_t::swap_buffers (void) { - buffer->props.direction = direction; + if (unlikely (in_error)) return; + + assert (have_output); + + if (out_info != info) + { + hb_glyph_info_t *tmp_string; + tmp_string = info; + info = out_info; + out_info = tmp_string; + pos = (hb_glyph_position_t *) out_info; + } + + unsigned int tmp; + tmp = len; + len = out_len; + out_len = tmp; + + idx = 0; } -hb_direction_t -hb_buffer_get_direction (hb_buffer_t *buffer) +void +hb_buffer_t::replace_glyphs_be16 (unsigned int num_in, + unsigned int num_out, + const uint16_t *glyph_data_be) { - return buffer->props.direction; + if (!make_room_for (num_in, num_out)) return; + + hb_glyph_info_t orig_info = info[idx]; + for (unsigned int i = 1; i < num_in; i++) + { + hb_glyph_info_t *inf = &info[idx + i]; + orig_info.cluster = MIN (orig_info.cluster, inf->cluster); + } + + hb_glyph_info_t *pinfo = &out_info[out_len]; + for (unsigned int i = 0; i < num_out; i++) + { + *pinfo = orig_info; + pinfo->codepoint = hb_be_uint16 (glyph_data_be[i]); + pinfo++; + } + + idx += num_in; + out_len += num_out; } void -hb_buffer_set_script (hb_buffer_t *buffer, - hb_script_t script) +hb_buffer_t::output_glyph (hb_codepoint_t glyph_index) { - buffer->props.script = script; + if (!make_room_for (0, 1)) return; + + out_info[out_len] = info[idx]; + out_info[out_len].codepoint = glyph_index; + + out_len++; } -hb_script_t -hb_buffer_get_script (hb_buffer_t *buffer) +void +hb_buffer_t::copy_glyph (void) { - return buffer->props.script; + if (!make_room_for (0, 1)) return; + + out_info[out_len] = info[idx]; + + out_len++; } void -hb_buffer_set_language (hb_buffer_t *buffer, - hb_language_t language) +hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) { - buffer->props.language = language; + out_info[out_len] = info[idx]; + out_info[out_len].codepoint = glyph_index; + + idx++; + out_len++; } -hb_language_t -hb_buffer_get_language (hb_buffer_t *buffer) +void +hb_buffer_t::next_glyph (void) { - return buffer->props.language; + if (have_output) + { + if (out_info != info) + { + if (unlikely (!ensure (out_len + 1))) return; + out_info[out_len] = info[idx]; + } + else if (out_len != idx) + out_info[out_len] = info[idx]; + + out_len++; + } + + idx++; } +void +hb_buffer_t::set_masks (hb_mask_t value, + hb_mask_t mask, + unsigned int cluster_start, + unsigned int cluster_end) +{ + hb_mask_t not_mask = ~mask; + value &= mask; + + if (!mask) + return; + + if (cluster_start == 0 && cluster_end == (unsigned int)-1) { + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + info[i].mask = (info[i].mask & not_mask) | value; + return; + } + + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end) + info[i].mask = (info[i].mask & not_mask) | value; +} void -hb_buffer_reset (hb_buffer_t *buffer) +hb_buffer_t::reverse_range (unsigned int start, + unsigned int end) { - hb_unicode_funcs_destroy (buffer->unicode); - buffer->unicode = _hb_buffer_nil.unicode; + unsigned int i, j; - buffer->props = _hb_buffer_nil.props; + if (start == end - 1) + return; - buffer->have_output = FALSE; - buffer->have_positions = FALSE; - buffer->in_error = FALSE; + for (i = start, j = end - 1; i < j; i++, j--) { + hb_glyph_info_t t; - buffer->i = 0; - buffer->len = 0; - buffer->out_len = 0; + t = info[i]; + info[i] = info[j]; + info[j] = t; + } - buffer->serial = 0; + if (pos) { + for (i = start, j = end - 1; i < j; i++, j--) { + hb_glyph_position_t t; - buffer->out_info = buffer->info; + t = pos[i]; + pos[i] = pos[j]; + pos[j] = t; + } + } } -hb_bool_t -hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) +void +hb_buffer_t::reverse (void) { - return _hb_buffer_ensure (buffer, size); -} + if (unlikely (!len)) + return; -hb_bool_t -hb_buffer_allocation_successful (hb_buffer_t *buffer) -{ - return !buffer->in_error; + reverse_range (0, len); } void -hb_buffer_add (hb_buffer_t *buffer, - hb_codepoint_t codepoint, - hb_mask_t mask, - unsigned int cluster) +hb_buffer_t::reverse_clusters (void) { - hb_glyph_info_t *glyph; - - if (unlikely (!_hb_buffer_ensure (buffer, buffer->len + 1))) return; + unsigned int i, start, count, last_cluster; - glyph = &buffer->info[buffer->len]; + if (unlikely (!len)) + return; - memset (glyph, 0, sizeof (*glyph)); - glyph->codepoint = codepoint; - glyph->mask = mask; - glyph->cluster = cluster; + reverse (); - buffer->len++; + count = len; + start = 0; + last_cluster = info[0].cluster; + for (i = 1; i < count; i++) { + if (last_cluster != info[i].cluster) { + reverse_range (start, i); + start = i; + last_cluster = info[i].cluster; + } + } + reverse_range (start, i); } -/* HarfBuzz-Internal API */ +static inline void +dump_var_allocation (const hb_buffer_t *buffer) +{ + char buf[80]; + for (unsigned int i = 0; i < 8; i++) + buf[i] = '0' + buffer->allocated_var_bytes[7 - i]; + buf[8] = '\0'; + DEBUG_MSG (BUFFER, buffer, + "Current var allocation: %s", + buf); +} -void -_hb_buffer_clear_output (hb_buffer_t *buffer) +void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner) { - buffer->have_output = TRUE; - buffer->have_positions = FALSE; + assert (byte_i < 8 && byte_i + count <= 8); - buffer->out_len = 0; - buffer->out_info = buffer->info; + if (DEBUG (BUFFER)) + dump_var_allocation (this); + DEBUG_MSG (BUFFER, this, + "Allocating var bytes %d..%d for %s", + byte_i, byte_i + count - 1, owner); + + for (unsigned int i = byte_i; i < byte_i + count; i++) { + assert (!allocated_var_bytes[i]); + allocated_var_bytes[i]++; + allocated_var_owner[i] = owner; + } } -void -_hb_buffer_clear_positions (hb_buffer_t *buffer) +void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner) { - buffer->have_output = FALSE; - buffer->have_positions = TRUE; + if (DEBUG (BUFFER)) + dump_var_allocation (this); - memset (buffer->pos, 0, sizeof (buffer->pos[0]) * buffer->len); + DEBUG_MSG (BUFFER, this, + "Deallocating var bytes %d..%d for %s", + byte_i, byte_i + count - 1, owner); + + assert (byte_i < 8 && byte_i + count <= 8); + for (unsigned int i = byte_i; i < byte_i + count; i++) { + assert (allocated_var_bytes[i]); + assert (0 == strcmp (allocated_var_owner[i], owner)); + allocated_var_bytes[i]--; + } } -void -_hb_buffer_swap (hb_buffer_t *buffer) +void hb_buffer_t::deallocate_var_all (void) { - unsigned int tmp; + memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes)); + memset (allocated_var_owner, 0, sizeof (allocated_var_owner)); +} + +/* Public API */ - assert (buffer->have_output); +hb_buffer_t * +hb_buffer_create (unsigned int pre_alloc_size) +{ + hb_buffer_t *buffer; + + if (!(buffer = hb_object_create ())) + return &_hb_buffer_nil; - if (unlikely (buffer->in_error)) return; + buffer->reset (); - if (buffer->out_info != buffer->info) - { - hb_glyph_info_t *tmp_string; - tmp_string = buffer->info; - buffer->info = buffer->out_info; - buffer->out_info = tmp_string; - buffer->pos = (hb_glyph_position_t *) buffer->out_info; + if (pre_alloc_size && !buffer->ensure (pre_alloc_size)) { + hb_buffer_destroy (buffer); + return &_hb_buffer_nil; } - tmp = buffer->len; - buffer->len = buffer->out_len; - buffer->out_len = tmp; + return buffer; +} + +hb_buffer_t * +hb_buffer_get_empty (void) +{ + return &_hb_buffer_nil; +} - buffer->i = 0; +hb_buffer_t * +hb_buffer_reference (hb_buffer_t *buffer) +{ + return hb_object_reference (buffer); } void -_hb_buffer_replace_glyphs_be16 (hb_buffer_t *buffer, - unsigned int num_in, - unsigned int num_out, - const uint16_t *glyph_data_be) +hb_buffer_destroy (hb_buffer_t *buffer) { - if (buffer->out_info != buffer->info || - buffer->out_len + num_out > buffer->i + num_in) - { - if (unlikely (!_hb_buffer_ensure_separate (buffer, buffer->out_len + num_out))) - return; - } + if (!hb_object_destroy (buffer)) return; - hb_glyph_info_t orig_info = buffer->info[buffer->i]; + hb_unicode_funcs_destroy (buffer->unicode); - for (unsigned int i = 0; i < num_out; i++) - { - hb_glyph_info_t *info = &buffer->out_info[buffer->out_len + i]; - *info = orig_info; - info->codepoint = hb_be_uint16 (glyph_data_be[i]); - } + free (buffer->info); + free (buffer->pos); - buffer->i += num_in; - buffer->out_len += num_out; + free (buffer); } +hb_bool_t +hb_buffer_set_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy) +{ + return hb_object_set_user_data (buffer, key, data, destroy); +} + +void * +hb_buffer_get_user_data (hb_buffer_t *buffer, + hb_user_data_key_t *key) +{ + return hb_object_get_user_data (buffer, key); +} + + void -_hb_buffer_replace_glyph (hb_buffer_t *buffer, - hb_codepoint_t glyph_index) +hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, + hb_unicode_funcs_t *unicode) { - hb_glyph_info_t *info; + if (unlikely (hb_object_is_inert (buffer))) + return; - if (buffer->out_info != buffer->info) - { - if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return; - buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; - } - else if (buffer->out_len != buffer->i) - buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; + if (!unicode) + unicode = _hb_buffer_nil.unicode; - info = &buffer->out_info[buffer->out_len]; - info->codepoint = glyph_index; + hb_unicode_funcs_reference (unicode); + hb_unicode_funcs_destroy (buffer->unicode); + buffer->unicode = unicode; +} - buffer->i++; - buffer->out_len++; +hb_unicode_funcs_t * +hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) +{ + return buffer->unicode; } void -_hb_buffer_next_glyph (hb_buffer_t *buffer) +hb_buffer_set_direction (hb_buffer_t *buffer, + hb_direction_t direction) + { - if (buffer->have_output) - { - if (buffer->out_info != buffer->info) - { - if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return; - buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; - } - else if (buffer->out_len != buffer->i) - buffer->out_info[buffer->out_len] = buffer->info[buffer->i]; + if (unlikely (hb_object_is_inert (buffer))) + return; - buffer->out_len++; - } + buffer->props.direction = direction; +} - buffer->i++; +hb_direction_t +hb_buffer_get_direction (hb_buffer_t *buffer) +{ + return buffer->props.direction; } void -_hb_buffer_reset_masks (hb_buffer_t *buffer, - hb_mask_t mask) +hb_buffer_set_script (hb_buffer_t *buffer, + hb_script_t script) { - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - buffer->info[i].mask = mask; + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->props.script = script; } -void -_hb_buffer_add_masks (hb_buffer_t *buffer, - hb_mask_t mask) +hb_script_t +hb_buffer_get_script (hb_buffer_t *buffer) { - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - buffer->info[i].mask |= mask; + return buffer->props.script; } void -_hb_buffer_set_masks (hb_buffer_t *buffer, - hb_mask_t value, - hb_mask_t mask, - unsigned int cluster_start, - unsigned int cluster_end) +hb_buffer_set_language (hb_buffer_t *buffer, + hb_language_t language) { - hb_mask_t not_mask = ~mask; - value &= mask; - - if (!mask) + if (unlikely (hb_object_is_inert (buffer))) return; - if (cluster_start == 0 && cluster_end == (unsigned int)-1) { - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value; - return; - } + buffer->props.language = language; +} - /* XXX can't bsearch since .cluster may not be sorted. */ - /* Binary search to find the start position and go from there. */ - unsigned int min = 0, max = buffer->len; - while (min < max) - { - unsigned int mid = min + ((max - min) / 2); - if (buffer->info[mid].cluster < cluster_start) - min = mid + 1; - else - max = mid; - } - unsigned int count = buffer->len; - for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++) - buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value; +hb_language_t +hb_buffer_get_language (hb_buffer_t *buffer) +{ + return buffer->props.language; } -/* Public API again */ +void +hb_buffer_reset (hb_buffer_t *buffer) +{ + buffer->reset (); +} + +hb_bool_t +hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) +{ + return buffer->ensure (size); +} + +hb_bool_t +hb_buffer_allocation_successful (hb_buffer_t *buffer) +{ + return !buffer->in_error; +} + +void +hb_buffer_add (hb_buffer_t *buffer, + hb_codepoint_t codepoint, + hb_mask_t mask, + unsigned int cluster) +{ + buffer->add (codepoint, mask, cluster); +} hb_bool_t hb_buffer_set_length (hb_buffer_t *buffer, unsigned int length) { - if (!_hb_buffer_ensure (buffer, length)) + if (!buffer->ensure (length)) return FALSE; /* Wipe the new space */ @@ -490,7 +646,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, unsigned int *length) { if (!buffer->have_positions) - _hb_buffer_clear_positions (buffer); + buffer->clear_positions (); if (length) *length = buffer->len; @@ -498,66 +654,18 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, return (hb_glyph_position_t *) buffer->pos; } - -static void -reverse_range (hb_buffer_t *buffer, - unsigned int start, - unsigned int end) -{ - unsigned int i, j; - - for (i = start, j = end - 1; i < j; i++, j--) { - hb_glyph_info_t t; - - t = buffer->info[i]; - buffer->info[i] = buffer->info[j]; - buffer->info[j] = t; - } - - if (buffer->pos) { - for (i = 0, j = end - 1; i < j; i++, j--) { - hb_glyph_position_t t; - - t = buffer->pos[i]; - buffer->pos[i] = buffer->pos[j]; - buffer->pos[j] = t; - } - } -} - void hb_buffer_reverse (hb_buffer_t *buffer) { - if (unlikely (!buffer->len)) - return; - - reverse_range (buffer, 0, buffer->len); + buffer->reverse (); } void hb_buffer_reverse_clusters (hb_buffer_t *buffer) { - unsigned int i, start, count, last_cluster; - - if (unlikely (!buffer->len)) - return; - - hb_buffer_reverse (buffer); - - count = buffer->len; - start = 0; - last_cluster = buffer->info[0].cluster; - for (i = 1; i < count; i++) { - if (last_cluster != buffer->info[i].cluster) { - reverse_range (buffer, start, i); - start = i; - last_cluster = buffer->info[i].cluster; - } - } - reverse_range (buffer, start, i); + buffer->reverse_clusters (); } - #define ADD_UTF(T) \ HB_STMT_START { \ const T *next = (const T *) text + item_offset; \ @@ -586,7 +694,7 @@ hb_utf8_next (const uint8_t *text, uint8_t c = *text; unsigned int mask, len; - /* TODO check for overlong sequences? also: optimize? */ + /* TODO check for overlong sequences? */ UTF8_COMPUTE (c, mask, len); if (unlikely (!len || (unsigned int) (end - text) < len)) {