Update HarfBuzz to 12.2.0

This commit is contained in:
Pāvels Nadtočajevs 2025-11-05 08:44:06 +02:00
parent 019889d1da
commit 8749408de8
No known key found for this signature in database
GPG Key ID: 8413210218EF35D2
21 changed files with 80 additions and 176 deletions

View File

@ -436,7 +436,7 @@ Patches:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
- Version: 12.1.0 (a790c38b782f9d8e6f0299d2837229e5726fc669, 2025)
- Version: 12.2.0 (0426759f2b03e479495e987608f10e0866e70180, 2025)
- License: MIT
Files extracted from upstream source:
@ -444,7 +444,7 @@ Files extracted from upstream source:
- `AUTHORS`, `COPYING`, `THANKS`
- From the `src` folder, recursively:
- All the `.cc`, `.h`, `.hh` files
- Except `main.cc`, `harfbuzz*.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`, `hb-harfrust.cc`, `wasm/*`, `ms-use/*`, `rust/*`
- Except `main.cc`, `harfbuzz*.cc`, `harfrust.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`, `hb-harfrust.cc`, `wasm/*`, `ms-use/*`, `rust/*`
## hidapi

View File

@ -41,11 +41,11 @@ struct CoverageFormat1_3
{
friend struct Coverage;
protected:
public:
HBUINT16 coverageFormat; /* Format identifier--format = 1 */
SortedArray16Of<typename Types::HBGlyphID>
glyphArray; /* Array of GlyphIDs--in numerical order */
public:
DEFINE_SIZE_ARRAY (4, glyphArray);
private:

View File

@ -40,7 +40,7 @@ struct CoverageFormat2_4
{
friend struct Coverage;
protected:
public:
HBUINT16 coverageFormat; /* Format identifier--format = 2 */
SortedArray16Of<RangeRecord<Types>>
rangeRecord; /* Array of glyph ranges--ordered by

View File

@ -51,7 +51,8 @@ struct EntryExitRecord
};
static void
reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) {
reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
{
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
return;
@ -229,8 +230,13 @@ struct CursivePosFormat1
*/
reverse_cursive_minor_offset (pos, child, c->direction, parent);
pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
pos[child].attach_chain() = (int) parent - (int) child;
if (pos[child].attach_chain() != (int) parent - (int) child)
{
pos[child].attach_chain() = 0;
goto overflow;
}
pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
pos[child].y_offset = y_offset;
@ -256,6 +262,7 @@ struct CursivePosFormat1
i, j);
}
overflow:
buffer->idx++;
return_trace (true);
}

View File

@ -47,10 +47,15 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
}
hb_glyph_position_t &o = buffer->cur_pos();
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
if (o.attach_chain() != (int) glyph_pos - (int) buffer->idx)
{
o.attach_chain() = 0;
goto overflow;
}
o.attach_type() = ATTACH_TYPE_MARK;
o.x_offset = roundf (base_x - mark_x);
o.y_offset = roundf (base_y - mark_y);
o.attach_type() = ATTACH_TYPE_MARK;
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
@ -60,6 +65,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
c->buffer->idx, glyph_pos);
}
overflow:
buffer->idx++;
return_trace (true);
}

View File

@ -32,29 +32,27 @@
namespace graph {
struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3<SmallTypes>
{
bool sanitize (graph_t::vertex_t& vertex) const
{
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size;
if (vertex_len < min_size) return false;
hb_barrier ();
return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
}
};
static bool sanitize (
const OT::Layout::Common::CoverageFormat1_3<OT::Layout::SmallTypes>* thiz,
graph_t::vertex_t& vertex
) {
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<OT::Layout::SmallTypes>::min_size;
if (vertex_len < min_size) return false;
hb_barrier ();
return vertex_len >= min_size + thiz->glyphArray.get_size () - thiz->glyphArray.len.get_size ();
}
struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4<SmallTypes>
{
bool sanitize (graph_t::vertex_t& vertex) const
{
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size;
if (vertex_len < min_size) return false;
hb_barrier ();
return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
}
};
static bool sanitize (
const OT::Layout::Common::CoverageFormat2_4<OT::Layout::SmallTypes>* thiz,
graph_t::vertex_t& vertex
) {
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<OT::Layout::SmallTypes>::min_size;
if (vertex_len < min_size) return false;
hb_barrier ();
return vertex_len >= min_size + thiz->rangeRecord.get_size () - thiz->rangeRecord.len.get_size ();
}
struct Coverage : public OT::Layout::Common::Coverage
{
@ -165,8 +163,8 @@ struct Coverage : public OT::Layout::Common::Coverage
hb_barrier ();
switch (u.format)
{
case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
case 1: return graph::sanitize ((const OT::Layout::Common::CoverageFormat1_3<OT::Layout::SmallTypes>*) this, vertex);
case 2: return graph::sanitize ((const OT::Layout::Common::CoverageFormat2_4<OT::Layout::SmallTypes>*) this, vertex);
#ifndef HB_NO_BEYOND_64K
// Not currently supported
case 3:

View File

@ -1603,7 +1603,7 @@ struct graph_t
count++;
const uint32_t *v;
if (!id_map.has (link.objidx, &v)) continue;
if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
if (only_wide && (link.is_signed || (link.width != 4 && link.width != 3))) continue;
reassign_link (link, i, *v, count > num_real);
}

View File

@ -67,7 +67,7 @@ struct hb_alloc_pool_t
return ret;
}
unsigned pad = (unsigned)(-(uintptr_t) current_chunk.arrayZ) & (alignment - 1);
unsigned pad = (unsigned) ((alignment - ((uintptr_t) current_chunk.arrayZ & (alignment - 1))) & (alignment - 1));
// Small chunk, allocate from the last chunk.
if (current_chunk.length < pad + size)
@ -77,7 +77,7 @@ struct hb_alloc_pool_t
hb_vector_t<char> &chunk = chunks.arrayZ[chunks.length - 1];
if (unlikely (!chunk.resize (ChunkSize))) return nullptr;
current_chunk = chunk;
pad = (unsigned)(-(uintptr_t) current_chunk.arrayZ) & (alignment - 1);
pad = (unsigned) ((alignment - ((uintptr_t) current_chunk.arrayZ & (alignment - 1))) & (alignment - 1));
}
current_chunk += pad;

View File

@ -427,7 +427,7 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
* #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then,
* - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster.
* - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format:
* - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then,
* - If #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not both 0, `@x_offset,y_offset`. Then,
* - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then,
* - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the #hb_glyph_extents_t in the format `<x_bearing,y_bearing,width,height>`
*

View File

@ -90,7 +90,7 @@ struct hb_cache_t
{
unsigned int k = key & ((1u<<cache_bits)-1);
unsigned int v = values[k];
if ((key_bits + value_bits - cache_bits == 8 * sizeof (item_t) && v == (unsigned int) -1) ||
if ((key_bits + value_bits - cache_bits == 8 * sizeof (item_t) && (item_t) v == (item_t) -1) ||
(v >> value_bits) != (key >> cache_bits))
return false;
*value = v & ((1u<<value_bits)-1);

View File

@ -445,9 +445,7 @@ struct hb_font_t
if (synthetic && ret)
{
/* Slant */
if (slant_xy)
*x += roundf (*y * slant_xy);
/* Slant is ignored as it does not affect glyph origin */
/* Embolden */
if (!embolden_in_place)
@ -471,9 +469,7 @@ struct hb_font_t
if (synthetic && ret)
{
/* Slant */
if (slant_xy)
*x += roundf (*y * slant_xy);
/* Slant is ignored as it does not affect glyph origin */
/* Embolden */
if (!embolden_in_place)
@ -508,9 +504,7 @@ struct hb_font_t
hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
for (unsigned i = 0; i < count; i++)
{
/* Slant */
if (slant_xy)
*first_x += roundf (*first_y * slant_xy);
/* Slant is ignored as it does not affect glyph origin */
/* Embolden */
if (!embolden_in_place)
@ -518,9 +512,9 @@ struct hb_font_t
*first_x += x_shift;
*first_y += y_shift;
}
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
}
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
}
return ret;
@ -548,9 +542,7 @@ struct hb_font_t
hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
for (unsigned i = 0; i < count; i++)
{
/* Slant */
if (slant_xy)
*first_x += roundf (*first_y * slant_xy);
/* Slant is ignored as it does not affect glyph origin */
/* Embolden */
if (!embolden_in_place)
@ -558,9 +550,9 @@ struct hb_font_t
*first_x += x_shift;
*first_y += y_shift;
}
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
}
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
}
return ret;

View File

@ -772,8 +772,9 @@ struct hb_iota_iter_t :
template <typename S2 = S>
auto
inc (hb_type_identity<S2> s, hb_priority<1>)
-> hb_void_t<decltype (hb_invoke (std::forward<S2> (s), hb_declval<T&> ()))>
{ v = hb_invoke (std::forward<S2> (s), v); }
-> hb_void_t<decltype (hb_invoke (std::forward<hb_type_identity<S2>> (s),
hb_declval<T&> ()))>
{ v = hb_invoke (std::forward<hb_type_identity<S2>> (s), v); }
void
inc (S s, hb_priority<0>)

View File

@ -90,7 +90,6 @@ struct KernSubTableFormat3
template <typename set_t>
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
{
set_t set;
if (likely (glyphCount))
{
left_set.add_range (0, num_glyphs - 1);

View File

@ -523,9 +523,16 @@ struct skipping_iterator_t
#endif
void reset (unsigned int start_index_)
{
// For GSUB forward iterator
idx = start_index_;
end = c->buffer->len;
matcher.syllable = start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0;
matcher.syllable = c->buffer->cur().syllable();
}
void reset_back (unsigned int start_index_, bool from_out_buffer = false)
{
// For GSUB backward iterator
idx = start_index_;
matcher.syllable = c->buffer->cur().syllable();
}
#ifndef HB_OPTIMIZE_SIZE
@ -1554,7 +1561,7 @@ static bool match_backtrack (hb_ot_apply_context_t *c,
TRACE_APPLY (nullptr);
auto &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->backtrack_len ());
skippy_iter.reset_back (c->buffer->backtrack_len ());
skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (backtrack);

View File

@ -93,7 +93,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
shaper = hb_ot_shaper_categorize (props.script, props.direction, map.chosen_script[0]);
script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
script_fallback_mark_positioning = shaper->fallback_position;
script_fallback_position = shaper->fallback_position;
#ifndef HB_NO_AAT_SHAPE
/* https://github.com/harfbuzz/harfbuzz/issues/1528 */
@ -179,12 +179,12 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
#endif
#ifndef HB_NO_OT_KERN
else if (hb_ot_layout_has_kerning (face))
plan.apply_kern = true;
plan.apply_kern = script_fallback_position; // Not all shapers apply legacy `kern`
#endif
else {}
}
plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern);
plan.apply_fallback_kern = script_fallback_position && !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern);
plan.zero_marks = script_zero_marks &&
!plan.apply_kerx &&
@ -204,7 +204,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
);
plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
script_fallback_mark_positioning;
script_fallback_position;
#ifndef HB_NO_AAT_SHAPE
/* If we're using morx shaping, we cancel mark position adjustment because

View File

@ -150,7 +150,7 @@ struct hb_ot_shape_planner_t
static constexpr bool apply_morx = false;
#endif
bool script_zero_marks : 1;
bool script_fallback_mark_positioning : 1;
bool script_fallback_position : 1;
const struct hb_ot_shaper_t *shaper;
HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face,

View File

@ -427,7 +427,7 @@ const hb_ot_shaper_t _hb_ot_shaper_hangul =
HB_TAG_NONE, /* gpos_tag */
HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
true, /* fallback_position */
};

View File

@ -687,7 +687,7 @@ struct gvar_GVAR
bool apply_to_all = (indices.length == 0);
unsigned num_deltas = apply_to_all ? points.length : indices.length;
unsigned start_deltas = (phantom_only && num_deltas >= 4 ? num_deltas - 4 : 0);
unsigned start_deltas = (apply_to_all && phantom_only && num_deltas >= 4 ? num_deltas - 4 : 0);
if (unlikely (!x_deltas.resize_dirty (num_deltas))) return false;
if (unlikely (!GlyphVariationData::decompile_deltas (p, x_deltas, end, false, start_deltas))) return false;
if (unlikely (!y_deltas.resize_dirty (num_deltas))) return false;

View File

@ -1,107 +0,0 @@
/*
* Copyright © 2019 Facebook, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Facebook Author(s): Behdad Esfahbod
*/
#ifndef HB_POOL_HH
#define HB_POOL_HH
#include "hb.hh"
/* Memory pool for persistent allocation of small objects.
*
* Some AI musings on this, not necessarily true:
*
* This is a very simple implementation, but it's good enough for our
* purposes. It's not thread-safe. It's not very fast. It's not
* very memory efficient. It's not very cache efficient. It's not
* very anything efficient. But it's simple and it works. And it's
* good enough for our purposes. If you need something more
* sophisticated, use a real allocator. Or use a real language. */
template <typename T, unsigned ChunkLen = 32>
struct hb_pool_t
{
hb_pool_t () : next (nullptr) {}
~hb_pool_t ()
{
next = nullptr;
+ hb_iter (chunks)
| hb_apply (hb_free)
;
}
T* alloc ()
{
if (unlikely (!next))
{
if (unlikely (!chunks.alloc (chunks.length + 1))) return nullptr;
chunk_t *chunk = (chunk_t *) hb_malloc (sizeof (chunk_t));
if (unlikely (!chunk)) return nullptr;
chunks.push (chunk);
next = chunk->thread ();
}
T* obj = next;
next = * ((T**) next);
hb_memset (obj, 0, sizeof (T));
return obj;
}
void release (T* obj)
{
* (T**) obj = next;
next = obj;
}
private:
static_assert (ChunkLen > 1, "");
static_assert (sizeof (T) >= sizeof (void *), "");
static_assert (alignof (T) % alignof (void *) == 0, "");
struct chunk_t
{
T* thread ()
{
for (unsigned i = 0; i < ARRAY_LENGTH (arrayZ) - 1; i++)
* (T**) &arrayZ[i] = &arrayZ[i + 1];
* (T**) &arrayZ[ARRAY_LENGTH (arrayZ) - 1] = nullptr;
return arrayZ;
}
T arrayZ[ChunkLen];
};
T* next;
hb_vector_t<chunk_t *> chunks;
};
#endif /* HB_POOL_HH */

View File

@ -418,7 +418,8 @@ _nameid_closure (hb_subset_plan_t* plan,
hb_set_t* drop_tables)
{
#ifndef HB_NO_STYLE
plan->source->table.STAT->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
if (!drop_tables->has (HB_OT_TAG_STAT))
plan->source->table.STAT->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
#endif
#ifndef HB_NO_VAR
if (!plan->all_axes_pinned)

View File

@ -47,7 +47,7 @@ HB_BEGIN_DECLS
*
* The minor component of the library version available at compile-time.
*/
#define HB_VERSION_MINOR 1
#define HB_VERSION_MINOR 2
/**
* HB_VERSION_MICRO:
*
@ -60,7 +60,7 @@ HB_BEGIN_DECLS
*
* A string literal containing the library version available at compile-time.
*/
#define HB_VERSION_STRING "12.1.0"
#define HB_VERSION_STRING "12.2.0"
/**
* HB_VERSION_ATLEAST: