diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-buffer.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-buffer.cc | 532 |
1 files changed, 389 insertions, 143 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index c6591ca230..d621a7cc55 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -40,6 +40,11 @@ * Buffers serve a dual role in HarfBuzz; before shaping, they hold * the input characters that are passed to hb_shape(), and after * shaping they hold the output glyphs. + * + * The input buffer is a sequence of Unicode codepoints, with + * associated attributes such as direction and script. The output + * buffer is a sequence of glyphs, with associated attributes such + * as position and cluster. **/ @@ -51,7 +56,7 @@ * Checks the equality of two #hb_segment_properties_t's. * * Return value: - * %true if all properties of @a equal those of @b, %false otherwise. + * `true` if all properties of @a equal those of @b, `false` otherwise. * * Since: 0.9.7 **/ @@ -81,12 +86,51 @@ hb_segment_properties_equal (const hb_segment_properties_t *a, unsigned int hb_segment_properties_hash (const hb_segment_properties_t *p) { - return (unsigned int) p->direction ^ - (unsigned int) p->script ^ + return ((unsigned int) p->direction * 31 + + (unsigned int) p->script) * 31 + (intptr_t) (p->language); } +/** + * hb_segment_properties_overlay: + * @p: #hb_segment_properties_t to fill in. + * @src: #hb_segment_properties_t to fill in from. + * + * Fills in missing fields of @p from @src in a considered manner. + * + * First, if @p does not have direction set, direction is copied from @src. + * + * Next, if @p and @src have the same direction (which can be unset), if @p + * does not have script set, script is copied from @src. + * + * Finally, if @p and @src have the same direction and script (which either + * can be unset), if @p does not have language set, language is copied from + * @src. + * + * Since: 3.3.0 + **/ +void +hb_segment_properties_overlay (hb_segment_properties_t *p, + const hb_segment_properties_t *src) +{ + if (unlikely (!p || !src)) + return; + + if (!p->direction) + p->direction = src->direction; + + if (p->direction != src->direction) + return; + + if (!p->script) + p->script = src->script; + if (p->script != src->script) + return; + + if (!p->language) + p->language = src->language; +} /* Here is how the buffer works internally: * @@ -96,14 +140,14 @@ hb_segment_properties_hash (const hb_segment_properties_t *p) * 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_buffers() is mostly no-op and the glyph operations + * In that case, sync() is mostly 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_buffers() then + * This should all remain transparent to the user. sync() then * switches info over to out_info and does housekeeping. */ @@ -133,12 +177,13 @@ hb_buffer_t::enlarge (unsigned int size) while (size >= new_allocated) new_allocated += (new_allocated >> 1) + 32; - static_assert ((sizeof (info[0]) == sizeof (pos[0])), ""); - if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0])))) + unsigned new_bytes; + if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]), &new_bytes))) goto done; - new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0])); - new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0])); + static_assert (sizeof (info[0]) == sizeof (pos[0]), ""); + new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_bytes); + new_info = (hb_glyph_info_t *) hb_realloc (info, new_bytes); done: if (unlikely (!new_pos || !new_info)) @@ -169,7 +214,7 @@ hb_buffer_t::make_room_for (unsigned int num_in, assert (have_output); out_info = (hb_glyph_info_t *) pos; - memcpy (out_info, info, out_len * sizeof (out_info[0])); + hb_memcpy (out_info, info, out_len * sizeof (out_info[0])); } return true; @@ -190,7 +235,7 @@ hb_buffer_t::shift_forward (unsigned int count) * Ideally, we should at least set Default_Ignorable bits on * these, as well as consistent cluster values. But the former * is layering violation... */ - memset (info + len, 0, (idx + count - len) * sizeof (info[0])); + hb_memset (info + len, 0, (idx + count - len) * sizeof (info[0])); } len += count; idx += count; @@ -217,13 +262,27 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size) /* HarfBuzz-Internal API */ void +hb_buffer_t::similar (const hb_buffer_t &src) +{ + hb_unicode_funcs_destroy (unicode); + unicode = hb_unicode_funcs_reference (src.unicode); + flags = src.flags; + cluster_level = src.cluster_level; + replacement = src.replacement; + invisible = src.invisible; + not_found = src.not_found; +} + +void hb_buffer_t::reset () { hb_unicode_funcs_destroy (unicode); unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ()); flags = HB_BUFFER_FLAG_DEFAULT; + cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; invisible = 0; + not_found = 0; clear (); } @@ -231,12 +290,12 @@ hb_buffer_t::reset () void hb_buffer_t::clear () { + content_type = HB_BUFFER_CONTENT_TYPE_INVALID; hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; props = default_props; - scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - content_type = HB_BUFFER_CONTENT_TYPE_INVALID; successful = true; + shaping_failed = false; have_output = false; have_positions = false; @@ -245,13 +304,42 @@ hb_buffer_t::clear () out_len = 0; out_info = info; - serial = 0; + hb_memset (context, 0, sizeof context); + hb_memset (context_len, 0, sizeof context_len); - memset (context, 0, sizeof context); - memset (context_len, 0, sizeof context_len); + deallocate_var_all (); + serial = 0; + random_state = 1; + scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; +} +void +hb_buffer_t::enter () +{ deallocate_var_all (); + serial = 0; + shaping_failed = false; + scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; + unsigned mul; + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul))) + { + max_len = hb_max (mul, (unsigned) HB_BUFFER_MAX_LEN_MIN); + } + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR, &mul))) + { + max_ops = hb_max (mul, (unsigned) HB_BUFFER_MAX_OPS_MIN); + } } +void +hb_buffer_t::leave () +{ + max_len = HB_BUFFER_MAX_LEN_DEFAULT; + max_ops = HB_BUFFER_MAX_OPS_DEFAULT; + deallocate_var_all (); + serial = 0; + // Intentionally not reseting shaping_failed, such that it can be inspected. +} + void hb_buffer_t::add (hb_codepoint_t codepoint, @@ -263,7 +351,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint, glyph = &info[len]; - memset (glyph, 0, sizeof (*glyph)); + hb_memset (glyph, 0, sizeof (*glyph)); glyph->codepoint = codepoint; glyph->mask = 0; glyph->cluster = cluster; @@ -305,9 +393,11 @@ hb_buffer_t::clear_positions () hb_memset (pos, 0, sizeof (pos[0]) * len); } -void -hb_buffer_t::swap_buffers () +bool +hb_buffer_t::sync () { + bool ret = false; + assert (have_output); assert (idx <= len); @@ -321,11 +411,39 @@ hb_buffer_t::swap_buffers () info = out_info; } len = out_len; + ret = true; reset: have_output = false; out_len = 0; + out_info = info; idx = 0; + + return ret; +} + +int +hb_buffer_t::sync_so_far () +{ + bool had_output = have_output; + unsigned out_i = out_len; + unsigned i = idx; + unsigned old_idx = idx; + + if (sync ()) + idx = out_i; + else + idx = i; + + if (had_output) + { + have_output = true; + out_len = idx; + } + + assert (idx <= len); + + return idx - old_idx; } bool @@ -382,12 +500,12 @@ hb_buffer_t::set_masks (hb_mask_t value, unsigned int cluster_start, unsigned int cluster_end) { - hb_mask_t not_mask = ~mask; - value &= mask; - if (!mask) return; + hb_mask_t not_mask = ~mask; + value &= mask; + unsigned int count = len; for (unsigned int i = 0; i < count; i++) if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end) @@ -395,52 +513,6 @@ hb_buffer_t::set_masks (hb_mask_t value, } void -hb_buffer_t::reverse_range (unsigned int start, - unsigned int end) -{ - if (end - start < 2) - return; - - hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end); - - if (have_positions) { - hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end); - } -} - -void -hb_buffer_t::reverse () -{ - if (unlikely (!len)) - return; - - reverse_range (0, len); -} - -void -hb_buffer_t::reverse_clusters () -{ - unsigned int i, start, count, last_cluster; - - if (unlikely (!len)) - return; - - reverse (); - - 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); -} - -void hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int end) { @@ -456,15 +528,17 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, cluster = hb_min (cluster, info[i].cluster); /* Extend end */ - while (end < len && info[end - 1].cluster == info[end].cluster) - end++; + if (cluster != info[end - 1].cluster) + while (end < len && info[end - 1].cluster == info[end].cluster) + end++; /* Extend start */ - while (idx < start && info[start - 1].cluster == info[start].cluster) - start--; + if (cluster != info[start].cluster) + while (idx < start && info[start - 1].cluster == info[start].cluster) + start--; /* If we hit the start of buffer, continue in out-buffer. */ - if (idx == start) + if (idx == start && info[start].cluster != cluster) for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) set_cluster (out_info[i - 1], cluster); @@ -508,7 +582,8 @@ hb_buffer_t::delete_glyph () /* The logic here is duplicated in hb_ot_hide_default_ignorables(). */ unsigned int cluster = info[idx].cluster; - if (idx + 1 < len && cluster == info[idx + 1].cluster) + if ((idx + 1 < len && cluster == info[idx + 1].cluster) || + (out_len && cluster == out_info[out_len - 1].cluster)) { /* Cluster survives; do nothing. */ goto done; @@ -539,29 +614,50 @@ done: } void -hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end) -{ - unsigned int cluster = UINT_MAX; - cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster); - _unsafe_to_break_set_mask (info, start, end, cluster); -} -void -hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end) +hb_buffer_t::delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info)) { - if (!have_output) + /* Merge clusters and delete filtered glyphs. + * NOTE! We can't use out-buffer as we have positioning data. */ + unsigned int j = 0; + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) { - unsafe_to_break_impl (start, end); - return; - } + if (filter (&info[i])) + { + /* Merge clusters. + * Same logic as 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. */ - assert (start <= out_len); - assert (idx <= end); + if (j) + { + /* Merge cluster backward. */ + if (cluster < info[j - 1].cluster) + { + unsigned int mask = info[i].mask; + unsigned int old_cluster = info[j - 1].cluster; + for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) + set_cluster (info[k - 1], cluster, mask); + } + continue; + } - unsigned int cluster = UINT_MAX; - cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster); - cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster); - _unsafe_to_break_set_mask (out_info, start, out_len, cluster); - _unsafe_to_break_set_mask (info, idx, end, cluster); + if (i + 1 < count) + merge_clusters (i, i + 2); /* Merge cluster forward. */ + + continue; + } + + if (j != i) + { + info[j] = info[i]; + pos[j] = pos[i]; + } + j++; + } + len = j; } void @@ -608,13 +704,14 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = HB_BUFFER_CLUSTER_LEVEL_DEFAULT, HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, 0, /* invisible */ - HB_BUFFER_SCRATCH_FLAG_DEFAULT, - HB_BUFFER_MAX_LEN_DEFAULT, - HB_BUFFER_MAX_OPS_DEFAULT, + 0, /* not_found */ + HB_BUFFER_CONTENT_TYPE_INVALID, HB_SEGMENT_PROPERTIES_DEFAULT, + false, /* successful */ + true, /* shaping_failed */ false, /* have_output */ true /* have_positions */ @@ -623,16 +720,16 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = /** - * hb_buffer_create: (Xconstructor) + * hb_buffer_create: * * Creates a new #hb_buffer_t with all properties to defaults. * * Return value: (transfer full): * A newly allocated #hb_buffer_t with a reference count of 1. The initial * reference count should be released with hb_buffer_destroy() when you are done - * using the #hb_buffer_t. This function never returns %NULL. If memory cannot + * using the #hb_buffer_t. This function never returns `NULL`. If memory cannot * be allocated, a special #hb_buffer_t object will be returned on which - * hb_buffer_allocation_successful() returns %false. + * hb_buffer_allocation_successful() returns `false`. * * Since: 0.9.2 **/ @@ -653,6 +750,46 @@ hb_buffer_create () } /** + * hb_buffer_create_similar: + * @src: An #hb_buffer_t + * + * Creates a new #hb_buffer_t, similar to hb_buffer_create(). The only + * difference is that the buffer is configured similarly to @src. + * + * Return value: (transfer full): + * A newly allocated #hb_buffer_t, similar to hb_buffer_create(). + * + * Since: 3.3.0 + **/ +hb_buffer_t * +hb_buffer_create_similar (const hb_buffer_t *src) +{ + hb_buffer_t *buffer = hb_buffer_create (); + + buffer->similar (*src); + + return buffer; +} + +/** + * hb_buffer_reset: + * @buffer: An #hb_buffer_t + * + * Resets the buffer to its initial status, as if it was just newly created + * with hb_buffer_create(). + * + * Since: 0.9.2 + **/ +void +hb_buffer_reset (hb_buffer_t *buffer) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->reset (); +} + +/** * hb_buffer_get_empty: * * Fetches an empty #hb_buffer_t. @@ -722,7 +859,7 @@ hb_buffer_destroy (hb_buffer_t *buffer) * * Attaches a user-data key/data pair to the specified buffer. * - * Return value: %true if success, %false otherwise + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -749,7 +886,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer, * Since: 0.9.2 **/ void * -hb_buffer_get_user_data (hb_buffer_t *buffer, +hb_buffer_get_user_data (const hb_buffer_t *buffer, hb_user_data_key_t *key) { return hb_object_get_user_data (buffer, key); @@ -764,6 +901,32 @@ hb_buffer_get_user_data (hb_buffer_t *buffer, * Sets the type of @buffer contents. Buffers are either empty, contain * characters (before shaping), or contain glyphs (the result of shaping). * + * You rarely need to call this function, since a number of other + * functions transition the content type for you. Namely: + * + * - A newly created buffer starts with content type + * %HB_BUFFER_CONTENT_TYPE_INVALID. Calling hb_buffer_reset(), + * hb_buffer_clear_contents(), as well as calling hb_buffer_set_length() + * with an argument of zero all set the buffer content type to invalid + * as well. + * + * - Calling hb_buffer_add_utf8(), hb_buffer_add_utf16(), + * hb_buffer_add_utf32(), hb_buffer_add_codepoints() and + * hb_buffer_add_latin1() expect that buffer is either empty and + * have a content type of invalid, or that buffer content type is + * %HB_BUFFER_CONTENT_TYPE_UNICODE, and they also set the content + * type to Unicode if they added anything to an empty buffer. + * + * - Finally hb_shape() and hb_shape_full() expect that the buffer + * is either empty and have content type of invalid, or that buffer + * content type is %HB_BUFFER_CONTENT_TYPE_UNICODE, and upon + * success they set the buffer content type to + * %HB_BUFFER_CONTENT_TYPE_GLYPHS. + * + * The above transitions are designed such that one can use a buffer + * in a loop of "reset : add-text : shape" without needing to ever + * modify the content type manually. + * * Since: 0.9.5 **/ void @@ -786,7 +949,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer, * Since: 0.9.5 **/ hb_buffer_content_type_t -hb_buffer_get_content_type (hb_buffer_t *buffer) +hb_buffer_get_content_type (const hb_buffer_t *buffer) { return buffer->content_type; } @@ -828,7 +991,7 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, * Since: 0.9.2 **/ hb_unicode_funcs_t * -hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) +hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer) { return buffer->unicode; } @@ -851,7 +1014,6 @@ hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) void hb_buffer_set_direction (hb_buffer_t *buffer, hb_direction_t direction) - { if (unlikely (hb_object_is_immutable (buffer))) return; @@ -871,7 +1033,7 @@ hb_buffer_set_direction (hb_buffer_t *buffer, * Since: 0.9.2 **/ hb_direction_t -hb_buffer_get_direction (hb_buffer_t *buffer) +hb_buffer_get_direction (const hb_buffer_t *buffer) { return buffer->props.direction; } @@ -915,7 +1077,7 @@ hb_buffer_set_script (hb_buffer_t *buffer, * Since: 0.9.2 **/ hb_script_t -hb_buffer_get_script (hb_buffer_t *buffer) +hb_buffer_get_script (const hb_buffer_t *buffer) { return buffer->props.script; } @@ -959,7 +1121,7 @@ hb_buffer_set_language (hb_buffer_t *buffer, * Since: 0.9.2 **/ hb_language_t -hb_buffer_get_language (hb_buffer_t *buffer) +hb_buffer_get_language (const hb_buffer_t *buffer) { return buffer->props.language; } @@ -995,7 +1157,7 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer, * Since: 0.9.7 **/ void -hb_buffer_get_segment_properties (hb_buffer_t *buffer, +hb_buffer_get_segment_properties (const hb_buffer_t *buffer, hb_segment_properties_t *props) { *props = buffer->props; @@ -1033,7 +1195,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer, * Since: 0.9.7 **/ hb_buffer_flags_t -hb_buffer_get_flags (hb_buffer_t *buffer) +hb_buffer_get_flags (const hb_buffer_t *buffer) { return buffer->flags; } @@ -1072,7 +1234,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer, * Since: 0.9.42 **/ hb_buffer_cluster_level_t -hb_buffer_get_cluster_level (hb_buffer_t *buffer) +hb_buffer_get_cluster_level (const hb_buffer_t *buffer) { return buffer->cluster_level; } @@ -1113,7 +1275,7 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, * Since: 0.9.31 **/ hb_codepoint_t -hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) +hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer) { return buffer->replacement; } @@ -1153,28 +1315,93 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, * Since: 2.0.0 **/ hb_codepoint_t -hb_buffer_get_invisible_glyph (hb_buffer_t *buffer) +hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer) { return buffer->invisible; } +/** + * hb_buffer_set_not_found_glyph: + * @buffer: An #hb_buffer_t + * @not_found: the not-found #hb_codepoint_t + * + * Sets the #hb_codepoint_t that replaces characters not found in + * the font during shaping. + * + * The not-found glyph defaults to zero, sometimes known as the + * ".notdef" glyph. This API allows for differentiating the two. + * + * Since: 3.1.0 + **/ +void +hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->not_found = not_found; +} /** - * hb_buffer_reset: + * hb_buffer_get_not_found_glyph: * @buffer: An #hb_buffer_t * - * Resets the buffer to its initial status, as if it was just newly created - * with hb_buffer_create(). + * See hb_buffer_set_not_found_glyph(). * - * Since: 0.9.2 + * Return value: + * The @buffer not-found #hb_codepoint_t + * + * Since: 3.1.0 + **/ +hb_codepoint_t +hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer) +{ + return buffer->not_found; +} + +/** + * hb_buffer_set_random_state: + * @buffer: An #hb_buffer_t + * @state: the new random state + * + * Sets the random state of the buffer. The state changes + * every time a glyph uses randomness (eg. the `rand` + * OpenType feature). This function together with + * hb_buffer_get_random_state() allow for transferring + * the current random state to a subsequent buffer, to + * get better randomness distribution. + * + * Defaults to 1 and when buffer contents are cleared. + * A value of 0 disables randomness during shaping. + * + * Since: 8.4.0 **/ void -hb_buffer_reset (hb_buffer_t *buffer) +hb_buffer_set_random_state (hb_buffer_t *buffer, + unsigned state) { if (unlikely (hb_object_is_immutable (buffer))) return; - buffer->reset (); + buffer->random_state = state; +} + +/** + * hb_buffer_get_random_state: + * @buffer: An #hb_buffer_t + * + * See hb_buffer_set_random_state(). + * + * Return value: + * The @buffer random state + * + * Since: 8.4.0 + **/ +unsigned +hb_buffer_get_random_state (const hb_buffer_t *buffer) +{ + return buffer->random_state; } /** @@ -1203,7 +1430,7 @@ hb_buffer_clear_contents (hb_buffer_t *buffer) * Pre allocates memory for @buffer to fit at least @size number of items. * * Return value: - * %true if @buffer memory allocation succeeded, %false otherwise + * `true` if @buffer memory allocation succeeded, `false` otherwise * * Since: 0.9.2 **/ @@ -1220,7 +1447,7 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) * Check if allocating memory for the buffer succeeded. * * Return value: - * %true if @buffer memory allocation succeeded, %false otherwise. + * `true` if @buffer memory allocation succeeded, `false` otherwise. * * Since: 0.9.2 **/ @@ -1265,7 +1492,7 @@ hb_buffer_add (hb_buffer_t *buffer, * end. * * Return value: - * %true if @buffer memory allocation succeeded, %false otherwise. + * `true` if @buffer memory allocation succeeded, `false` otherwise. * * Since: 0.9.2 **/ @@ -1281,9 +1508,9 @@ hb_buffer_set_length (hb_buffer_t *buffer, /* Wipe the new space */ if (length > buffer->len) { - memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len)); + hb_memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len)); if (buffer->have_positions) - memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len)); + hb_memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len)); } buffer->len = length; @@ -1311,7 +1538,7 @@ hb_buffer_set_length (hb_buffer_t *buffer, * Since: 0.9.2 **/ unsigned int -hb_buffer_get_length (hb_buffer_t *buffer) +hb_buffer_get_length (const hb_buffer_t *buffer) { return buffer->len; } @@ -1351,7 +1578,7 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer, * If buffer did not have positions before, the positions will be * initialized to zeros, unless this function is called from * within a buffer message callback (see hb_buffer_set_message_func()), - * in which case %NULL is returned. + * in which case `NULL` is returned. * * Return value: (transfer none) (array length=length): * The @buffer glyph position array. @@ -1386,7 +1613,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, * and cleared of position data when hb_buffer_clear_contents() is called. * * Return value: - * %true if the @buffer has position array, %false otherwise. + * `true` if the @buffer has position array, `false` otherwise. * * Since: 2.7.3 **/ @@ -1570,10 +1797,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer, * @buffer: An #hb_buffer_t * @text: (array length=text_length) (element-type uint8_t): An array of UTF-8 * characters to append. - * @text_length: The length of the @text, or -1 if it is %NULL terminated. + * @text_length: The length of the @text, or -1 if it is `NULL` terminated. * @item_offset: The offset of the first character to add to the @buffer. * @item_length: The number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated). + * end of @text (assuming it is `NULL` terminated). * * See hb_buffer_add_codepoints(). * @@ -1596,10 +1823,10 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer, * hb_buffer_add_utf16: * @buffer: An #hb_buffer_t * @text: (array length=text_length): An array of UTF-16 characters to append - * @text_length: The length of the @text, or -1 if it is %NULL terminated + * @text_length: The length of the @text, or -1 if it is `NULL` terminated * @item_offset: The offset of the first character to add to the @buffer * @item_length: The number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated) + * end of @text (assuming it is `NULL` terminated) * * See hb_buffer_add_codepoints(). * @@ -1622,10 +1849,10 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer, * hb_buffer_add_utf32: * @buffer: An #hb_buffer_t * @text: (array length=text_length): An array of UTF-32 characters to append - * @text_length: The length of the @text, or -1 if it is %NULL terminated + * @text_length: The length of the @text, or -1 if it is `NULL` terminated * @item_offset: The offset of the first character to add to the @buffer * @item_length: The number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated) + * end of @text (assuming it is `NULL` terminated) * * See hb_buffer_add_codepoints(). * @@ -1649,10 +1876,10 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer, * @buffer: An #hb_buffer_t * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 * characters to append - * @text_length: the length of the @text, or -1 if it is %NULL terminated + * @text_length: the length of the @text, or -1 if it is `NULL` terminated * @item_offset: the offset of the first character to add to the @buffer * @item_length: the number of characters to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated) + * end of @text (assuming it is `NULL` terminated) * * Similar to hb_buffer_add_codepoints(), but allows only access to first 256 * Unicode code points that can fit in 8-bit strings. @@ -1675,10 +1902,10 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer, * hb_buffer_add_codepoints: * @buffer: a #hb_buffer_t to append characters to. * @text: (array length=text_length): an array of Unicode code points to append. - * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @text_length: the length of the @text, or -1 if it is `NULL` terminated. * @item_offset: the offset of the first code point to add to the @buffer. * @item_length: the number of code points to add to the @buffer, or -1 for the - * end of @text (assuming it is %NULL terminated). + * end of @text (assuming it is `NULL` terminated). * * Appends characters from @text array to @buffer. The @item_offset is the * position of the first character from @text that will be appended, and @@ -1691,7 +1918,9 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer, * marks at stat of run. * * This function does not check the validity of @text, it is up to the caller - * to ensure it contains a valid Unicode code points. + * to ensure it contains a valid Unicode scalar values. In contrast, + * hb_buffer_add_utf32() can be used that takes similar input but performs + * sanity-check on the input. * * Since: 0.9.31 **/ @@ -1719,7 +1948,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer, **/ HB_EXTERN void hb_buffer_append (hb_buffer_t *buffer, - hb_buffer_t *source, + const hb_buffer_t *source, unsigned int start, unsigned int end) { @@ -1752,9 +1981,11 @@ hb_buffer_append (hb_buffer_t *buffer, if (!buffer->have_positions && source->have_positions) buffer->clear_positions (); - memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); + hb_segment_properties_overlay (&buffer->props, &source->props); + + hb_memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); if (buffer->have_positions) - memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); + hb_memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) { @@ -1889,7 +2120,7 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g * hb_buffer_diff: * @buffer: a buffer. * @reference: other buffer to compare to. - * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1. + * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepoint_t) -1. * @position_fuzz: allowed absolute difference in position values. * * If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT @@ -1942,7 +2173,7 @@ hb_buffer_diff (hb_buffer_t *buffer, result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH; if (buf_info->cluster != ref_info->cluster) result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH; - if ((buf_info->mask & ~ref_info->mask & HB_GLYPH_FLAG_DEFINED)) + if ((buf_info->mask ^ ref_info->mask) & HB_GLYPH_FLAG_DEFINED) result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH; if (contains && ref_info->codepoint == dottedcircle_glyph) result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; @@ -1997,6 +2228,13 @@ hb_buffer_set_message_func (hb_buffer_t *buffer, hb_buffer_message_func_t func, void *user_data, hb_destroy_func_t destroy) { + if (unlikely (hb_object_is_immutable (buffer))) + { + if (destroy) + destroy (user_data); + return; + } + if (buffer->message_destroy) buffer->message_destroy (buffer->message_data); @@ -2013,8 +2251,16 @@ hb_buffer_set_message_func (hb_buffer_t *buffer, bool hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) { + assert (!have_output || (out_info == info && out_len == idx)); + + message_depth++; + char buf[100]; vsnprintf (buf, sizeof (buf), fmt, ap); - return (bool) this->message_func (this, font, buf, this->message_data); + bool ret = (bool) this->message_func (this, font, buf, this->message_data); + + message_depth--; + + return ret; } #endif |