summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/hb-buffer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-buffer.cc')
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc99
1 files changed, 58 insertions, 41 deletions
diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc
index 8cad6ab8e6..c6591ca230 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -96,14 +96,15 @@ 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 no-op and the glyph operations operate
- * mostly in-place.
+ * In that case, swap_buffers() 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
+ * 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
- * switches info and out_info.
+ * switches info over to out_info and does housekeeping.
*/
@@ -136,8 +137,8 @@ hb_buffer_t::enlarge (unsigned int size)
if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
goto done;
- 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]));
+ 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]));
done:
if (unlikely (!new_pos || !new_info))
@@ -282,21 +283,12 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
void
-hb_buffer_t::remove_output ()
-{
- have_output = false;
- have_positions = false;
-
- out_len = 0;
- out_info = info;
-}
-
-void
hb_buffer_t::clear_output ()
{
have_output = true;
have_positions = false;
+ idx = 0;
out_len = 0;
out_info = info;
}
@@ -316,29 +308,23 @@ hb_buffer_t::clear_positions ()
void
hb_buffer_t::swap_buffers ()
{
- if (unlikely (!successful)) return;
+ assert (have_output);
assert (idx <= len);
- if (unlikely (!next_glyphs (len - idx))) return;
- assert (have_output);
- have_output = false;
+ if (unlikely (!successful || !next_glyphs (len - idx)))
+ goto reset;
if (out_info != info)
{
- hb_glyph_info_t *tmp;
- tmp = info;
+ pos = (hb_glyph_position_t *) info;
info = out_info;
- out_info = tmp;
-
- pos = (hb_glyph_position_t *) out_info;
}
-
- unsigned int tmp;
- tmp = len;
len = out_len;
- out_len = tmp;
+reset:
+ have_output = false;
+ out_len = 0;
idx = 0;
}
@@ -373,12 +359,11 @@ hb_buffer_t::move_to (unsigned int i)
/* This will blow in our face if memory allocation fails later
* in this same lookup...
*
- * We used to shift with extra 32 items, instead of the 0 below.
+ * We used to shift with extra 32 items.
* But that would leave empty slots in the buffer in case of allocation
- * failures. Setting to zero for now to avoid other problems (see
- * comments in shift_forward(). This can cause O(N^2) behavior more
- * severely than adding 32 empty slots can... */
- if (unlikely (idx < count && !shift_forward (count + 0))) return false;
+ * failures. See comments in shift_forward(). This can cause O(N^2)
+ * behavior more severely than adding 32 empty slots can... */
+ if (unlikely (idx < count && !shift_forward (count - idx))) return false;
assert (idx >= count);
@@ -630,7 +615,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_BUFFER_CONTENT_TYPE_INVALID,
HB_SEGMENT_PROPERTIES_DEFAULT,
false, /* successful */
- true, /* have_output */
+ false, /* have_output */
true /* have_positions */
/* Zero is good enough for everything else. */
@@ -717,14 +702,14 @@ hb_buffer_destroy (hb_buffer_t *buffer)
hb_unicode_funcs_destroy (buffer->unicode);
- free (buffer->info);
- free (buffer->pos);
+ hb_free (buffer->info);
+ hb_free (buffer->pos);
#ifndef HB_NO_BUFFER_MESSAGE
if (buffer->message_destroy)
buffer->message_destroy (buffer->message_data);
#endif
- free (buffer);
+ hb_free (buffer);
}
/**
@@ -1363,6 +1348,11 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
* Returns @buffer glyph position array. Returned pointer
* is valid as long as @buffer contents are not modified.
*
+ * 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.
+ *
* Return value: (transfer none) (array length=length):
* The @buffer glyph position array.
* The value valid as long as buffer has not been modified.
@@ -1373,12 +1363,17 @@ hb_glyph_position_t *
hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
unsigned int *length)
{
- if (!buffer->have_positions)
- buffer->clear_positions ();
-
if (length)
*length = buffer->len;
+ if (!buffer->have_positions)
+ {
+ if (unlikely (buffer->message_depth))
+ return nullptr;
+
+ buffer->clear_positions ();
+ }
+
return (hb_glyph_position_t *) buffer->pos;
}
@@ -1760,6 +1755,28 @@ hb_buffer_append (hb_buffer_t *buffer,
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]));
+
+ if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
+ {
+ /* See similar logic in add_utf. */
+
+ /* pre-context */
+ if (!orig_len && start + source->context_len[0] > 0)
+ {
+ buffer->clear_context (0);
+ while (start > 0 && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
+ buffer->context[0][buffer->context_len[0]++] = source->info[--start].codepoint;
+ for (auto i = 0u; i < source->context_len[0] && buffer->context_len[0] < buffer->CONTEXT_LENGTH; i++)
+ buffer->context[0][buffer->context_len[0]++] = source->context[0][i];
+ }
+
+ /* post-context */
+ buffer->clear_context (1);
+ while (end < source->len && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
+ buffer->context[1][buffer->context_len[1]++] = source->info[end++].codepoint;
+ for (auto i = 0u; i < source->context_len[1] && buffer->context_len[1] < buffer->CONTEXT_LENGTH; i++)
+ buffer->context[1][buffer->context_len[1]++] = source->context[1][i];
+ }
}