update harfbuzz to 10.1.0

This commit is contained in:
Sasha Szpakowski
2024-11-08 20:45:28 -04:00
parent 7ca40027e0
commit aecb572558
3449 changed files with 101770 additions and 22266 deletions
+208 -33
View File
@@ -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.
**/
@@ -172,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))
@@ -208,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;
@@ -229,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;
@@ -262,9 +268,10 @@ hb_buffer_t::similar (const hb_buffer_t &src)
unicode = hb_unicode_funcs_reference (src.unicode);
flags = src.flags;
cluster_level = src.cluster_level;
replacement = src.invisible;
replacement = src.replacement;
invisible = src.invisible;
not_found = src.not_found;
not_found_variation_selector = src.not_found_variation_selector;
}
void
@@ -277,6 +284,7 @@ hb_buffer_t::reset ()
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
invisible = 0;
not_found = 0;
not_found_variation_selector = HB_CODEPOINT_INVALID;
clear ();
}
@@ -298,11 +306,12 @@ hb_buffer_t::clear ()
out_len = 0;
out_info = info;
memset (context, 0, sizeof context);
memset (context_len, 0, sizeof context_len);
hb_memset (context, 0, sizeof context);
hb_memset (context_len, 0, sizeof context_len);
deallocate_var_all ();
serial = 0;
random_state = 1;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
}
@@ -313,15 +322,14 @@ hb_buffer_t::enter ()
serial = 0;
shaping_failed = false;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
unsigned mul;
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul)))
{
max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR,
(unsigned) HB_BUFFER_MAX_LEN_MIN);
max_len = hb_max (mul, (unsigned) HB_BUFFER_MAX_LEN_MIN);
}
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR)))
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR, &mul)))
{
max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR,
(unsigned) HB_BUFFER_MAX_OPS_MIN);
max_ops = hb_max (mul, (unsigned) HB_BUFFER_MAX_OPS_MIN);
}
}
void
@@ -345,7 +353,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;
@@ -494,12 +502,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)
@@ -522,15 +530,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);
@@ -605,6 +615,53 @@ done:
skip_glyph ();
}
void
hb_buffer_t::delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info))
{
/* 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++)
{
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. */
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;
}
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
hb_buffer_t::guess_segment_properties ()
{
@@ -650,6 +707,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
0, /* invisible */
0, /* not_found */
HB_CODEPOINT_INVALID, /* not_found_variation_selector */
HB_BUFFER_CONTENT_TYPE_INVALID,
@@ -846,6 +904,32 @@ hb_buffer_get_user_data (const 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
@@ -933,7 +1017,6 @@ hb_buffer_get_unicode_funcs (const 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;
@@ -1248,7 +1331,7 @@ hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer)
* Sets the #hb_codepoint_t that replaces characters not found in
* the font during shaping.
*
* The not-found glyph defaults to zero, sometimes knows as the
* The not-found glyph defaults to zero, sometimes known as the
* ".notdef" glyph. This API allows for differentiating the two.
*
* Since: 3.1.0
@@ -1280,6 +1363,89 @@ hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer)
return buffer->not_found;
}
/**
* hb_buffer_set_not_found_variation_selector_glyph:
* @buffer: An #hb_buffer_t
* @not_found_variation_selector: the not-found-variation-selector #hb_codepoint_t
*
* Sets the #hb_codepoint_t that replaces variation-selector characters not resolved
* in the font during shaping.
*
* The not-found-variation-selector glyph defaults to #HB_CODEPOINT_INVALID,
* in which case an unresolved variation-selector will be removed from the glyph
* string during shaping. This API allows for changing that and retaining a glyph,
* such that the situation can be detected by the client and handled accordingly
* (e.g. by using a different font).
*
* Since: 10.0.0
**/
void
hb_buffer_set_not_found_variation_selector_glyph (hb_buffer_t *buffer,
hb_codepoint_t not_found_variation_selector)
{
buffer->not_found_variation_selector = not_found_variation_selector;
}
/**
* hb_buffer_get_not_found_variation_selector_glyph:
* @buffer: An #hb_buffer_t
*
* See hb_buffer_set_not_found_variation_selector_glyph().
*
* Return value:
* The @buffer not-found-variation-selector #hb_codepoint_t
*
* Since: 10.0.0
**/
hb_codepoint_t
hb_buffer_get_not_found_variation_selector_glyph (const hb_buffer_t *buffer)
{
return buffer->not_found_variation_selector;
}
/**
* 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_set_random_state (hb_buffer_t *buffer,
unsigned state)
{
if (unlikely (hb_object_is_immutable (buffer)))
return;
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;
}
/**
* hb_buffer_clear_contents:
@@ -1385,9 +1551,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;
@@ -1795,7 +1961,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
**/
@@ -1858,9 +2026,9 @@ hb_buffer_append (hb_buffer_t *buffer,
hb_segment_properties_overlay (&buffer->props, &source->props);
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
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)
{
@@ -1995,7 +2163,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
@@ -2048,7 +2216,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;
@@ -2103,6 +2271,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);