Update HarfBuzz to 12.3.2
This commit is contained in:
parent
78c6632eb1
commit
7da2925a95
63 changed files with 1106 additions and 876 deletions
2
thirdparty/README.md
vendored
2
thirdparty/README.md
vendored
|
|
@ -451,7 +451,7 @@ Patches:
|
|||
## harfbuzz
|
||||
|
||||
- Upstream: https://github.com/harfbuzz/harfbuzz
|
||||
- Version: 12.2.0 (0426759f2b03e479495e987608f10e0866e70180, 2025)
|
||||
- Version: 12.3.2 (b42511e071162fe76102f613a6ccc009726c99af, 2026)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
|
|||
22
thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
vendored
22
thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
vendored
|
|
@ -1613,7 +1613,7 @@ struct ClipBox
|
|||
const ItemVarStoreInstancer &instancer) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.subset (c, instancer, VarIdx::NO_VARIATION));
|
||||
case 2: return_trace (u.format2.subset (c, instancer));
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
@ -1622,7 +1622,7 @@ struct ClipBox
|
|||
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 2: u.format2.closurev1 (c); return;
|
||||
default:return;
|
||||
}
|
||||
|
|
@ -1631,9 +1631,9 @@ struct ClipBox
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
@ -1644,7 +1644,7 @@ struct ClipBox
|
|||
const ItemVarStoreInstancer &instancer) const
|
||||
{
|
||||
ClipBoxData clip_box;
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
u.format1.get_clip_box (clip_box, instancer);
|
||||
break;
|
||||
|
|
@ -1664,7 +1664,7 @@ struct ClipBox
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT8 format; /* Format identifier */
|
||||
struct { HBUINT8 v; } format; /* Format identifier */
|
||||
ClipBoxFormat1 format1;
|
||||
ClipBoxFormat2 format2;
|
||||
} u;
|
||||
|
|
@ -1844,9 +1844,9 @@ struct Paint
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.paintformat1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.paintformat2, std::forward<Ts> (ds)...));
|
||||
case 3: return_trace (c->dispatch (u.paintformat3, std::forward<Ts> (ds)...));
|
||||
|
|
@ -1885,7 +1885,7 @@ struct Paint
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT8 format;
|
||||
struct { HBUINT8 v; } format;
|
||||
PaintColrLayers paintformat1;
|
||||
NoVariable<PaintSolid> paintformat2;
|
||||
Variable<PaintSolid> paintformat3;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ struct Coverage
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
CoverageFormat1_3<SmallTypes> format1;
|
||||
CoverageFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -55,7 +55,7 @@ struct Coverage
|
|||
#endif
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
HB_ALWAYS_INLINE
|
||||
|
|
@ -63,9 +63,9 @@ struct Coverage
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
|
|
@ -86,7 +86,7 @@ struct Coverage
|
|||
unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return u.format1.get_coverage (glyph_id);
|
||||
case 2: return u.format2.get_coverage (glyph_id);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -111,9 +111,24 @@ struct Coverage
|
|||
return coverage;
|
||||
}
|
||||
|
||||
unsigned int get_coverage_binary (hb_codepoint_t glyph_id,
|
||||
hb_ot_layout_binary_cache_t *cache) const
|
||||
{
|
||||
unsigned coverage;
|
||||
if (cache && cache->get (glyph_id, &coverage)) return coverage < cache->MAX_VALUE ? coverage : NOT_COVERED;
|
||||
coverage = get_coverage (glyph_id);
|
||||
if (cache) {
|
||||
if (coverage == NOT_COVERED)
|
||||
cache->set_unchecked (glyph_id, cache->MAX_VALUE);
|
||||
else
|
||||
cache->set_unchecked (glyph_id, 0);
|
||||
}
|
||||
return coverage;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return u.format1.get_population ();
|
||||
case 2: return u.format2.get_population ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -145,11 +160,11 @@ struct Coverage
|
|||
last = g;
|
||||
if (g > max) max = g;
|
||||
}
|
||||
u.format = !unsorted && count <= num_ranges * 3 ? 1 : 2;
|
||||
u.format.v = !unsorted && count <= num_ranges * 3 ? 1 : 2;
|
||||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (max > 0xFFFFu)
|
||||
u.format += 2;
|
||||
u.format.v += 2;
|
||||
if (unlikely (max > 0xFFFFFFu))
|
||||
#else
|
||||
if (unlikely (max > 0xFFFFu))
|
||||
|
|
@ -159,7 +174,7 @@ struct Coverage
|
|||
return_trace (false);
|
||||
}
|
||||
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return_trace (u.format1.serialize (c, glyphs));
|
||||
case 2: return_trace (u.format2.serialize (c, glyphs));
|
||||
|
|
@ -190,7 +205,7 @@ struct Coverage
|
|||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.intersects (glyphs);
|
||||
case 2: return u.format2.intersects (glyphs);
|
||||
|
|
@ -203,7 +218,7 @@ struct Coverage
|
|||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.intersects_coverage (glyphs, index);
|
||||
case 2: return u.format2.intersects_coverage (glyphs, index);
|
||||
|
|
@ -217,7 +232,7 @@ struct Coverage
|
|||
|
||||
unsigned cost () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.cost ();
|
||||
case 2: hb_barrier (); return u.format2.cost ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -233,7 +248,7 @@ struct Coverage
|
|||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.collect_coverage (glyphs);
|
||||
case 2: return u.format2.collect_coverage (glyphs);
|
||||
|
|
@ -249,7 +264,7 @@ struct Coverage
|
|||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
|
||||
case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
|
||||
|
|
@ -267,7 +282,7 @@ struct Coverage
|
|||
iter_t (const Coverage &c_ = Null (Coverage))
|
||||
{
|
||||
hb_memset (this, 0, sizeof (*this));
|
||||
format = c_.u.format;
|
||||
format = c_.u.format.v;
|
||||
switch (format)
|
||||
{
|
||||
case 1: u.format1.init (c_.u.format1); return;
|
||||
|
|
|
|||
56
thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
vendored
56
thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
vendored
|
|
@ -252,7 +252,7 @@ struct CaretValue
|
|||
hb_codepoint_t glyph_id,
|
||||
const ItemVariationStore &var_store) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return u.format1.get_caret_value (font, direction);
|
||||
case 2: return u.format2.get_caret_value (font, direction, glyph_id);
|
||||
case 3: return u.format3.get_caret_value (font, direction, var_store);
|
||||
|
|
@ -263,9 +263,9 @@ struct CaretValue
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
|
|
@ -275,7 +275,7 @@ struct CaretValue
|
|||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
case 2:
|
||||
return;
|
||||
|
|
@ -289,9 +289,9 @@ struct CaretValue
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
case 3: return_trace (u.format3.sanitize (c));
|
||||
|
|
@ -301,13 +301,13 @@ struct CaretValue
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
CaretValueFormat1 format1;
|
||||
CaretValueFormat2 format2;
|
||||
CaretValueFormat3 format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
|
||||
struct LigGlyph
|
||||
|
|
@ -519,7 +519,7 @@ struct MarkGlyphSets
|
|||
{
|
||||
bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return u.format1.covers (set_index, glyph_id);
|
||||
default:return false;
|
||||
}
|
||||
|
|
@ -528,7 +528,7 @@ struct MarkGlyphSets
|
|||
template <typename set_t>
|
||||
void collect_coverage (hb_vector_t<set_t> &sets) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: u.format1.collect_coverage (sets); return;
|
||||
default:return;
|
||||
}
|
||||
|
|
@ -537,7 +537,7 @@ struct MarkGlyphSets
|
|||
void collect_used_mark_sets (const hb_set_t& glyph_set,
|
||||
hb_set_t& used_mark_sets /* OUT */) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: u.format1.collect_used_mark_sets (glyph_set, used_mark_sets); return;
|
||||
default:return;
|
||||
}
|
||||
|
|
@ -546,7 +546,7 @@ struct MarkGlyphSets
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.subset (c));
|
||||
default:return_trace (false);
|
||||
}
|
||||
|
|
@ -555,9 +555,9 @@ struct MarkGlyphSets
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
default:return_trace (true);
|
||||
}
|
||||
|
|
@ -565,11 +565,11 @@ struct MarkGlyphSets
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MarkGlyphSetsFormat1 format1;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1002,20 +1002,34 @@ struct GDEF
|
|||
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
|
||||
{
|
||||
return
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
mark_glyph_sets[set_index].may_have (glyph_id)
|
||||
#else
|
||||
table->mark_set_covers (set_index, glyph_id)
|
||||
// We can access arrayZ directly because of sanitize_lookup_props() guarantee.
|
||||
mark_glyph_sets.arrayZ[set_index].may_have (glyph_id) &&
|
||||
#endif
|
||||
table->mark_set_covers (set_index, glyph_id)
|
||||
;
|
||||
}
|
||||
|
||||
unsigned sanitize_lookup_props (unsigned lookup_props) const
|
||||
{
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
if (lookup_props & LookupFlag::UseMarkFilteringSet &&
|
||||
(lookup_props >> 16) >= mark_glyph_sets.length)
|
||||
{
|
||||
// Invalid mark filtering set index; unset the flag.
|
||||
lookup_props &= ~LookupFlag::UseMarkFilteringSet;
|
||||
}
|
||||
#endif
|
||||
return lookup_props;
|
||||
}
|
||||
|
||||
hb_blob_ptr_t<GDEF> table;
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
hb_vector_t<hb_bit_set_t> mark_glyph_sets;
|
||||
hb_vector_t<hb_set_digest_t> mark_glyph_sets;
|
||||
mutable hb_cache_t<21, 3> glyph_props_cache;
|
||||
static_assert (sizeof (glyph_props_cache) == 512, "");
|
||||
#endif
|
||||
|
|
|
|||
14
thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh
vendored
14
thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh
vendored
|
|
@ -13,20 +13,20 @@ struct Anchor
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
AnchorFormat1 format1;
|
||||
AnchorFormat2 format2;
|
||||
AnchorFormat3 format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
case 3: return_trace (u.format3.sanitize (c));
|
||||
|
|
@ -38,7 +38,7 @@ struct Anchor
|
|||
float *x, float *y) const
|
||||
{
|
||||
*x = *y = 0;
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
|
||||
case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
|
||||
case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
|
||||
|
|
@ -49,7 +49,7 @@ struct Anchor
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
||||
case 2:
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
|
|
@ -66,7 +66,7 @@ struct Anchor
|
|||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: case 2:
|
||||
return;
|
||||
case 3:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct CursivePos
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
CursivePosFormat1 format1;
|
||||
} u;
|
||||
|
||||
|
|
@ -19,9 +19,9 @@ struct CursivePos
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct EntryExitRecord
|
|||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
static void
|
||||
static inline void
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct MarkBasePos
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MarkBasePosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkBasePosFormat1_2<MediumTypes> format2;
|
||||
|
|
@ -22,9 +22,9 @@ struct MarkBasePos
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct MarkLigPos
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MarkLigPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkLigPosFormat1_2<MediumTypes> format2;
|
||||
|
|
@ -22,9 +22,9 @@ struct MarkLigPos
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct MarkMarkPos
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MarkMarkPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkMarkPosFormat1_2<MediumTypes> format2;
|
||||
|
|
@ -22,9 +22,9 @@ struct MarkMarkPos
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct PairPos
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
PairPosFormat1_3<SmallTypes> format1;
|
||||
PairPosFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -25,9 +25,9 @@ struct PairPos
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct SinglePos
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
SinglePosFormat1 format1;
|
||||
SinglePosFormat2 format2;
|
||||
} u;
|
||||
|
|
@ -41,7 +41,7 @@ struct SinglePos
|
|||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
unsigned newFormat)
|
||||
{
|
||||
if (unlikely (!c->extend_min (u.format))) return;
|
||||
if (unlikely (!c->extend_min (u.format.v))) return;
|
||||
unsigned format = 2;
|
||||
ValueFormat new_format;
|
||||
new_format = newFormat;
|
||||
|
|
@ -49,8 +49,8 @@ struct SinglePos
|
|||
if (glyph_val_iter_pairs)
|
||||
format = get_format (glyph_val_iter_pairs);
|
||||
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
u.format.v = format;
|
||||
switch (u.format.v) {
|
||||
case 1: u.format1.serialize (c,
|
||||
src,
|
||||
glyph_val_iter_pairs,
|
||||
|
|
@ -70,9 +70,9 @@ struct SinglePos
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct AlternateSubst
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
AlternateSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
AlternateSubstFormat1_2<MediumTypes> format2;
|
||||
|
|
@ -23,9 +23,9 @@ struct AlternateSubst
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
|
|
@ -42,10 +42,10 @@ struct AlternateSubst
|
|||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (u.format.v))) return_trace (false);
|
||||
unsigned int format = 1;
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
u.format.v = format;
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
|
||||
default:return_trace (false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ struct LigatureSet
|
|||
*
|
||||
* This is replicated in ChainRuleSet and RuleSet. */
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
auto &skippy_iter = c->iter_context;
|
||||
skippy_iter.reset (c->buffer->idx);
|
||||
skippy_iter.set_match_func (match_always, nullptr);
|
||||
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct LigatureSubst
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
LigatureSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
LigatureSubstFormat1_2<MediumTypes> format2;
|
||||
|
|
@ -23,9 +23,9 @@ struct LigatureSubst
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
|
|
@ -45,10 +45,10 @@ struct LigatureSubst
|
|||
hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (u.format.v))) return_trace (false);
|
||||
unsigned int format = 1;
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
u.format.v = format;
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.serialize (c,
|
||||
first_glyphs,
|
||||
ligature_per_first_glyph_count_list,
|
||||
|
|
|
|||
|
|
@ -107,10 +107,10 @@ struct LigatureSubstFormat1_2
|
|||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
const hb_set_digest_t *seconds = cache ? &cache->seconds : nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
const hb_set_digest_t *seconds = nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct MultipleSubst
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MultipleSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MultipleSubstFormat1_2<MediumTypes> format2;
|
||||
|
|
@ -24,9 +24,9 @@ struct MultipleSubst
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
|
|
@ -41,10 +41,10 @@ struct MultipleSubst
|
|||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (u.format.v))) return_trace (false);
|
||||
unsigned int format = 1;
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
u.format.v = format;
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.serialize (c, it));
|
||||
default:return_trace (false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct ReverseChainSingleSubst
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
ReverseChainSingleSubstFormat1 format1;
|
||||
} u;
|
||||
|
||||
|
|
@ -20,9 +20,9 @@ struct ReverseChainSingleSubst
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ struct SingleSubst
|
|||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
SingleSubstFormat1_3<SmallTypes> format1;
|
||||
SingleSubstFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -27,9 +27,9 @@ struct SingleSubst
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -47,7 +47,7 @@ struct SingleSubst
|
|||
Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (u.format.v))) return_trace (false);
|
||||
unsigned format = 2;
|
||||
unsigned delta = 0;
|
||||
if (glyphs)
|
||||
|
|
@ -71,8 +71,8 @@ struct SingleSubst
|
|||
if (!hb_all (++(+glyphs), delta, get_delta)) format += 1;
|
||||
}
|
||||
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
u.format.v = format;
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.serialize (c,
|
||||
+ glyphs
|
||||
| hb_map_retains_sorting (hb_first),
|
||||
|
|
|
|||
7
thirdparty/harfbuzz/src/OT/Layout/types.hh
vendored
7
thirdparty/harfbuzz/src/OT/Layout/types.hh
vendored
|
|
@ -29,8 +29,11 @@
|
|||
#ifndef OT_LAYOUT_TYPES_HH
|
||||
#define OT_LAYOUT_TYPES_HH
|
||||
|
||||
using hb_ot_layout_mapping_cache_t = hb_cache_t<15, 8, 7>;
|
||||
static_assert (sizeof (hb_ot_layout_mapping_cache_t) == 256, "");
|
||||
using hb_ot_layout_mapping_cache_t = hb_cache_t<16, 8, 8>;
|
||||
static_assert (sizeof (hb_ot_layout_mapping_cache_t) == 512, "");
|
||||
|
||||
using hb_ot_layout_binary_cache_t = hb_cache_t<14, 1, 8>;
|
||||
static_assert (sizeof (hb_ot_layout_binary_cache_t) == 256, "");
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ struct ClassDef : public OT::ClassDef
|
|||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < OT::ClassDef::min_size) return false;
|
||||
hb_barrier ();
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
|
||||
case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ struct Coverage : public OT::Layout::Common::Coverage
|
|||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
|
||||
hb_barrier ();
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
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);
|
||||
|
|
|
|||
46
thirdparty/harfbuzz/src/graph/graph.hh
vendored
46
thirdparty/harfbuzz/src/graph/graph.hh
vendored
|
|
@ -1097,24 +1097,6 @@ struct graph_t
|
|||
return clone_idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a copy of child and re-assigns the link from
|
||||
* parent to the clone. The copy is a shallow copy, objects
|
||||
* linked from child are not duplicated.
|
||||
*
|
||||
* Returns the index of the newly created duplicate.
|
||||
*
|
||||
* If the child_idx only has incoming edges from parent_idx, this
|
||||
* will do nothing and return the original child_idx.
|
||||
*/
|
||||
unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
|
||||
{
|
||||
unsigned new_idx = duplicate (parent_idx, child_idx);
|
||||
if (new_idx == (unsigned) -1) return child_idx;
|
||||
return new_idx;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Creates a copy of child and re-assigns the link from
|
||||
* parent to the clone. The copy is a shallow copy, objects
|
||||
|
|
@ -1258,6 +1240,34 @@ struct graph_t
|
|||
return clone_idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new child node and remap the old child to it.
|
||||
*
|
||||
* Returns the index of the newly created child.
|
||||
*
|
||||
*/
|
||||
unsigned remap_child (unsigned parent_idx, unsigned old_child_idx)
|
||||
{
|
||||
unsigned new_child_idx = duplicate (old_child_idx);
|
||||
if (new_child_idx == (unsigned) -1) return -1;
|
||||
|
||||
auto& parent = vertices_[parent_idx];
|
||||
for (auto& l : parent.obj.real_links)
|
||||
{
|
||||
if (l.objidx != old_child_idx)
|
||||
continue;
|
||||
reassign_link (l, parent_idx, new_child_idx, false);
|
||||
}
|
||||
|
||||
for (auto& l : parent.obj.virtual_links)
|
||||
{
|
||||
if (l.objidx != old_child_idx)
|
||||
continue;
|
||||
reassign_link (l, parent_idx, new_child_idx, true);
|
||||
}
|
||||
return new_child_idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Raises the sorting priority of all children.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ struct gsubgpos_graph_context_t
|
|||
unsigned lookup_list_index;
|
||||
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
||||
hb_hashmap_t<unsigned, unsigned> subtable_to_extension;
|
||||
hb_hashmap_t<unsigned, hb_vector_t<unsigned>> split_subtables;
|
||||
|
||||
HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
||||
graph_t& graph_);
|
||||
|
|
|
|||
75
thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
vendored
75
thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
vendored
|
|
@ -138,10 +138,8 @@ struct Lookup : public OT::Lookup
|
|||
for (unsigned i = 0; i < subTable.len; i++)
|
||||
{
|
||||
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
||||
unsigned parent_index = this_index;
|
||||
if (is_ext) {
|
||||
unsigned ext_subtable_index = subtable_index;
|
||||
parent_index = ext_subtable_index;
|
||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
|
||||
c.graph.object (ext_subtable_index).head;
|
||||
|
|
@ -154,33 +152,43 @@ struct Lookup : public OT::Lookup
|
|||
continue;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> new_sub_tables;
|
||||
|
||||
if (c.table_tag == HB_OT_TAG_GPOS) {
|
||||
switch (type)
|
||||
{
|
||||
case 2:
|
||||
new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (c.table_tag == HB_OT_TAG_GSUB) {
|
||||
switch (type)
|
||||
{
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<graph::LigatureSubst> (c, parent_index, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hb_vector_t<unsigned>* split_result;
|
||||
if (c.split_subtables.has (subtable_index, &split_result))
|
||||
{
|
||||
if (split_result->length == 0)
|
||||
continue;
|
||||
all_new_subtables.push (hb_pair(i, *split_result));
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_vector_t<unsigned> new_sub_tables;
|
||||
|
||||
if (new_sub_tables.in_error ()) return false;
|
||||
if (!new_sub_tables) continue;
|
||||
hb_pair_t<unsigned, hb_vector_t<unsigned>>* entry = all_new_subtables.push ();
|
||||
entry->first = i;
|
||||
entry->second = std::move (new_sub_tables);
|
||||
if (c.table_tag == HB_OT_TAG_GPOS) {
|
||||
switch (type)
|
||||
{
|
||||
case 2:
|
||||
new_sub_tables = split_subtable<PairPos> (c, subtable_index); break;
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (c.table_tag == HB_OT_TAG_GSUB) {
|
||||
switch (type)
|
||||
{
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<graph::LigatureSubst> (c, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_sub_tables.in_error ()) return false;
|
||||
|
||||
c.split_subtables.set (subtable_index, new_sub_tables);
|
||||
if (new_sub_tables)
|
||||
all_new_subtables.push (hb_pair (i, std::move (new_sub_tables)));
|
||||
}
|
||||
}
|
||||
|
||||
if (all_new_subtables) {
|
||||
|
|
@ -192,20 +200,19 @@ struct Lookup : public OT::Lookup
|
|||
|
||||
template<typename T>
|
||||
hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_idx,
|
||||
unsigned objidx)
|
||||
{
|
||||
T* sub_table = (T*) c.graph.object (objidx).head;
|
||||
if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx]))
|
||||
return hb_vector_t<unsigned> ();
|
||||
|
||||
return sub_table->split_subtables (c, parent_idx, objidx);
|
||||
return sub_table->split_subtables (c, objidx);
|
||||
}
|
||||
|
||||
bool add_sub_tables (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
unsigned type,
|
||||
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
|
||||
const hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
|
||||
{
|
||||
bool is_ext = is_extension (c.table_tag);
|
||||
auto* v = &c.graph.vertices_[this_index];
|
||||
|
|
@ -272,17 +279,15 @@ struct Lookup : public OT::Lookup
|
|||
|
||||
void fix_existing_subtable_links (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
|
||||
const hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
|
||||
{
|
||||
auto& v = c.graph.vertices_[this_index];
|
||||
Lookup* lookup = (Lookup*) v.obj.head;
|
||||
|
||||
unsigned shift = 0;
|
||||
for (const auto& p : subtable_ids)
|
||||
{
|
||||
unsigned insert_index = p.first + shift;
|
||||
unsigned pos_offset = p.second.length * OT::Offset16::static_size;
|
||||
unsigned insert_offset = (char*) &lookup->subTable[insert_index] - (char*) lookup;
|
||||
unsigned insert_offset = Lookup::min_size + insert_index * OT::Offset16::static_size;
|
||||
shift += p.second.length;
|
||||
|
||||
for (auto& l : v.obj.all_links_writer ())
|
||||
|
|
@ -326,7 +331,7 @@ struct Lookup : public OT::Lookup
|
|||
unsigned* existing_ext_index = nullptr;
|
||||
if (c.subtable_to_extension.has(subtable_index, &existing_ext_index)) {
|
||||
ext_index = *existing_ext_index;
|
||||
} else {
|
||||
} else {
|
||||
ext_index = create_extension_subtable(c, subtable_index, type);
|
||||
c.subtable_to_extension.set(subtable_index, ext_index);
|
||||
}
|
||||
|
|
|
|||
39
thirdparty/harfbuzz/src/graph/ligature-graph.hh
vendored
39
thirdparty/harfbuzz/src/graph/ligature-graph.hh
vendored
|
|
@ -67,14 +67,13 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
auto split_points = compute_split_points(c, parent_index, this_index);
|
||||
auto split_points = compute_split_points(c, this_index);
|
||||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
this_index,
|
||||
total_number_ligas(c, this_index),
|
||||
liga_counts(c, this_index),
|
||||
};
|
||||
|
|
@ -123,7 +122,6 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
}
|
||||
|
||||
hb_vector_t<unsigned> compute_split_points(gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index) const
|
||||
{
|
||||
// For ligature subst coverage is always packed last, and as a result is where an overflow
|
||||
|
|
@ -441,26 +439,36 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
}
|
||||
|
||||
// Adjust liga set array
|
||||
c.graph.vertices_[this_index].obj.tail -= (ligatureSet.len - new_liga_set_count) * SmallTypes::size;
|
||||
auto& this_vertex = c.graph.vertices_[this_index];
|
||||
this_vertex.obj.tail -= (ligatureSet.len - new_liga_set_count) * SmallTypes::size;
|
||||
ligatureSet.len = new_liga_set_count;
|
||||
|
||||
// Coverage matches the number of liga sets so rebuild as needed
|
||||
auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage);
|
||||
if (!coverage) return false;
|
||||
unsigned coverage_idx = c.graph.index_for_offset (this_index, &this->coverage);
|
||||
if (coverage_idx == (unsigned) -1) return false;
|
||||
|
||||
auto& coverage_v = c.graph.vertices_[coverage_idx];
|
||||
unsigned coverage_size = coverage_v.table_size ();
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
|
||||
if (coverage_v.is_shared ())
|
||||
{
|
||||
coverage_idx = c.graph.remap_child (this_index, coverage_idx);
|
||||
if (coverage_idx == (unsigned) -1) return false;
|
||||
}
|
||||
|
||||
for (unsigned i : retained_indices.iter())
|
||||
add_virtual_link(c, i, coverage.index);
|
||||
add_virtual_link(c, i, coverage_idx);
|
||||
|
||||
unsigned coverage_size = coverage.vertex->table_size ();
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage.table->iter (), hb_range ())
|
||||
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second < new_liga_set_count;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size);
|
||||
return Coverage::make_coverage (c, new_coverage, coverage_idx, coverage_size);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -468,12 +476,11 @@ struct LigatureSubst : public OT::Layout::GSUB_impl::LigatureSubst
|
|||
{
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
return ((LigatureSubstFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
return ((LigatureSubstFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: HB_FALLTHROUGH;
|
||||
// Don't split 24bit Ligature Subs
|
||||
|
|
@ -486,10 +493,10 @@ struct LigatureSubst : public OT::Layout::GSUB_impl::LigatureSubst
|
|||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < u.format.get_size ()) return false;
|
||||
if (vertex_len < u.format.v.get_size ()) return false;
|
||||
hb_barrier ();
|
||||
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
return ((LigatureSubstFormat1*)(&u.format1))->sanitize (vertex);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
|
|||
|
|
@ -212,7 +212,6 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
hb_set_t visited;
|
||||
|
|
@ -265,7 +264,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
this_index,
|
||||
std::move (class_to_info),
|
||||
c.graph.vertices_[mark_array_id].position_to_index_map (),
|
||||
};
|
||||
|
|
@ -478,12 +477,11 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
||||
{
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: HB_FALLTHROUGH;
|
||||
// Don't split 24bit MarkBasePos's.
|
||||
|
|
@ -496,10 +494,10 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
|||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < u.format.get_size ()) return false;
|
||||
if (vertex_len < u.format.v.get_size ()) return false;
|
||||
hb_barrier ();
|
||||
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
|
|||
17
thirdparty/harfbuzz/src/graph/pairpos-graph.hh
vendored
17
thirdparty/harfbuzz/src/graph/pairpos-graph.hh
vendored
|
|
@ -49,7 +49,6 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
hb_set_t visited;
|
||||
|
|
@ -84,7 +83,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
this_index,
|
||||
};
|
||||
|
||||
return actuate_subtable_split<split_context_t> (split_context, split_points);
|
||||
|
|
@ -207,7 +206,6 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
|
||||
|
|
@ -291,7 +289,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
this_index,
|
||||
class1_record_size,
|
||||
total_value_len,
|
||||
value_1_len,
|
||||
|
|
@ -607,14 +605,13 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
||||
{
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
case 2:
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: HB_FALLTHROUGH;
|
||||
case 4: HB_FALLTHROUGH;
|
||||
|
|
@ -628,10 +625,10 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
|||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < u.format.get_size ()) return false;
|
||||
if (vertex_len < u.format.v.get_size ()) return false;
|
||||
hb_barrier ();
|
||||
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1:
|
||||
return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
|
||||
case 2:
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ hb_vector_t<unsigned> actuate_subtable_split (Context& split_context,
|
|||
if (id == (unsigned) -1)
|
||||
{
|
||||
new_objects.reset ();
|
||||
new_objects.allocated = -1; // mark error
|
||||
new_objects.ensure_error ();
|
||||
return new_objects;
|
||||
}
|
||||
new_objects.push (id);
|
||||
|
|
@ -58,7 +58,7 @@ hb_vector_t<unsigned> actuate_subtable_split (Context& split_context,
|
|||
if (!split_context.shrink (split_points[0]))
|
||||
{
|
||||
new_objects.reset ();
|
||||
new_objects.allocated = -1; // mark error
|
||||
new_objects.ensure_error ();
|
||||
}
|
||||
|
||||
return new_objects;
|
||||
|
|
|
|||
84
thirdparty/harfbuzz/src/hb-aat-layout-common.hh
vendored
84
thirdparty/harfbuzz/src/hb-aat-layout-common.hh
vendored
|
|
@ -692,7 +692,7 @@ struct Lookup
|
|||
{
|
||||
const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return u.format0.get_value (glyph_id, num_glyphs);
|
||||
case 2: hb_barrier (); return u.format2.get_value (glyph_id);
|
||||
case 4: hb_barrier (); return u.format4.get_value (glyph_id);
|
||||
|
|
@ -704,7 +704,7 @@ struct Lookup
|
|||
|
||||
const typename T::type get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
/* Format 10 cannot return a pointer. */
|
||||
case 10: hb_barrier (); return u.format10.get_value_or_null (glyph_id);
|
||||
default:
|
||||
|
|
@ -716,7 +716,7 @@ struct Lookup
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &glyphs, unsigned int num_glyphs) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); u.format0.collect_glyphs (glyphs, num_glyphs); return;
|
||||
case 2: hb_barrier (); u.format2.collect_glyphs (glyphs); return;
|
||||
case 4: hb_barrier (); u.format4.collect_glyphs (glyphs); return;
|
||||
|
|
@ -729,7 +729,7 @@ struct Lookup
|
|||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); u.format0.collect_glyphs_filtered (glyphs, num_glyphs, filter); return;
|
||||
case 2: hb_barrier (); u.format2.collect_glyphs_filtered (glyphs, filter); return;
|
||||
case 4: hb_barrier (); u.format4.collect_glyphs_filtered (glyphs, filter); return;
|
||||
|
|
@ -751,9 +751,9 @@ struct Lookup
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
|
||||
case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
|
||||
case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
|
||||
|
|
@ -766,9 +766,9 @@ struct Lookup
|
|||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return_trace (u.format0.sanitize (c, base));
|
||||
case 2: hb_barrier (); return_trace (u.format2.sanitize (c, base));
|
||||
case 4: hb_barrier (); return_trace (u.format4.sanitize (c, base));
|
||||
|
|
@ -781,7 +781,7 @@ struct Lookup
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
LookupFormat0<T> format0;
|
||||
LookupFormat2<T> format2;
|
||||
LookupFormat4<T> format4;
|
||||
|
|
@ -790,7 +790,7 @@ struct Lookup
|
|||
LookupFormat10<T> format10;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
|
||||
|
||||
|
|
@ -1216,11 +1216,24 @@ struct StateTableDriver
|
|||
int state = StateTableT::STATE_START_OF_TEXT;
|
||||
// If there's only one range, we already checked the flag.
|
||||
auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
|
||||
const bool start_state_safe_to_break_eot =
|
||||
!c->table->is_actionable (machine.get_entry (StateTableT::STATE_START_OF_TEXT, CLASS_END_OF_TEXT));
|
||||
for (buffer->idx = 0; buffer->successful;)
|
||||
{
|
||||
/* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
|
||||
if (last_range)
|
||||
unsigned int klass = likely (buffer->idx < buffer->len) ?
|
||||
machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_class_cache) :
|
||||
(unsigned) CLASS_END_OF_TEXT;
|
||||
resume:
|
||||
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
|
||||
const EntryT &entry = machine.get_entry (state, klass);
|
||||
const int next_state = machine.new_state (entry.newState);
|
||||
|
||||
bool is_not_epsilon_transition = !(entry.flags & Flags::DontAdvance);
|
||||
bool is_not_actionable = !c->table->is_actionable (entry);
|
||||
|
||||
if (unlikely (last_range))
|
||||
{
|
||||
/* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
|
||||
auto *range = last_range;
|
||||
if (buffer->idx < buffer->len)
|
||||
{
|
||||
|
|
@ -1235,7 +1248,7 @@ struct StateTableDriver
|
|||
}
|
||||
if (!(range->flags & ac->subtable_flags))
|
||||
{
|
||||
if (buffer->idx == buffer->len || unlikely (!buffer->successful))
|
||||
if (buffer->idx == buffer->len)
|
||||
break;
|
||||
|
||||
state = StateTableT::STATE_START_OF_TEXT;
|
||||
|
|
@ -1243,13 +1256,42 @@ struct StateTableDriver
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fast path for when transitioning from start-state to start-state with
|
||||
// no action and advancing. Do so as long as the class remains the same.
|
||||
// This is common with runs of non-actionable glyphs.
|
||||
|
||||
unsigned int klass = likely (buffer->idx < buffer->len) ?
|
||||
machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_class_cache) :
|
||||
(unsigned) CLASS_END_OF_TEXT;
|
||||
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
|
||||
const EntryT &entry = machine.get_entry (state, klass);
|
||||
const int next_state = machine.new_state (entry.newState);
|
||||
bool is_null_transition = state == StateTableT::STATE_START_OF_TEXT &&
|
||||
next_state == StateTableT::STATE_START_OF_TEXT &&
|
||||
start_state_safe_to_break_eot &&
|
||||
is_not_actionable &&
|
||||
is_not_epsilon_transition &&
|
||||
!last_range;
|
||||
|
||||
if (is_null_transition)
|
||||
{
|
||||
unsigned old_klass = klass;
|
||||
do
|
||||
{
|
||||
c->transition (buffer, this, entry);
|
||||
|
||||
if (buffer->idx == buffer->len || !buffer->successful)
|
||||
break;
|
||||
|
||||
(void) buffer->next_glyph ();
|
||||
|
||||
klass = likely (buffer->idx < buffer->len) ?
|
||||
machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_class_cache) :
|
||||
(unsigned) CLASS_END_OF_TEXT;
|
||||
} while (klass == old_klass);
|
||||
|
||||
if (buffer->idx == buffer->len || !buffer->successful)
|
||||
break;
|
||||
|
||||
goto resume;
|
||||
}
|
||||
}
|
||||
|
||||
/* Conditions under which it's guaranteed safe-to-break before current glyph:
|
||||
*
|
||||
|
|
@ -1316,10 +1358,10 @@ struct StateTableDriver
|
|||
state = next_state;
|
||||
DEBUG_MSG (APPLY, nullptr, "s%d", state);
|
||||
|
||||
if (buffer->idx == buffer->len || unlikely (!buffer->successful))
|
||||
if (buffer->idx == buffer->len)
|
||||
break;
|
||||
|
||||
if (!(entry.flags & Flags::DontAdvance) || buffer->max_ops-- <= 0)
|
||||
if (is_not_epsilon_transition || buffer->max_ops-- <= 0)
|
||||
(void) buffer->next_glyph ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ struct LigatureSubtable
|
|||
if (entry.flags & LigatureEntryT::SetComponent)
|
||||
{
|
||||
/* Never mark same index twice, in case DontAdvance was used... */
|
||||
if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len)
|
||||
if (unlikely (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len))
|
||||
match_length--;
|
||||
|
||||
match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len;
|
||||
|
|
@ -640,7 +640,7 @@ struct NoncontextualSubtable
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
/* This block copied from StateTableDriver::drive. Keep in sync. */
|
||||
if (last_range)
|
||||
if (unlikely (last_range))
|
||||
{
|
||||
auto *range = last_range;
|
||||
{
|
||||
|
|
|
|||
20
thirdparty/harfbuzz/src/hb-algs.hh
vendored
20
thirdparty/harfbuzz/src/hb-algs.hh
vendored
|
|
@ -98,7 +98,8 @@ struct __attribute__((packed)) hb_packed_t { Type v; };
|
|||
(__BYTE_ORDER == __BIG_ENDIAN || \
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN && \
|
||||
hb_has_builtin(__builtin_bswap16) && \
|
||||
hb_has_builtin(__builtin_bswap32)))
|
||||
hb_has_builtin(__builtin_bswap32) && \
|
||||
hb_has_builtin(__builtin_bswap64)))
|
||||
#define HB_FAST_NUM_ACCESS 1
|
||||
#else
|
||||
#define HB_FAST_NUM_ACCESS 0
|
||||
|
|
@ -222,6 +223,14 @@ struct HBInt<BE, Type, 8>
|
|||
HBInt () = default;
|
||||
|
||||
HBInt (Type V)
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
{
|
||||
if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
|
||||
((hb_packed_t<uint64_t> *) v)->v = V;
|
||||
else
|
||||
((hb_packed_t<uint64_t> *) v)->v = __builtin_bswap64 (V);
|
||||
}
|
||||
#else
|
||||
: v {BE ? uint8_t ((V >> 56) & 0xFF) : uint8_t ((V ) & 0xFF),
|
||||
BE ? uint8_t ((V >> 48) & 0xFF) : uint8_t ((V >> 8) & 0xFF),
|
||||
BE ? uint8_t ((V >> 40) & 0xFF) : uint8_t ((V >> 16) & 0xFF),
|
||||
|
|
@ -230,8 +239,16 @@ struct HBInt<BE, Type, 8>
|
|||
BE ? uint8_t ((V >> 16) & 0xFF) : uint8_t ((V >> 40) & 0xFF),
|
||||
BE ? uint8_t ((V >> 8) & 0xFF) : uint8_t ((V >> 48) & 0xFF),
|
||||
BE ? uint8_t ((V ) & 0xFF) : uint8_t ((V >> 56) & 0xFF)} {}
|
||||
#endif
|
||||
|
||||
constexpr operator Type () const {
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
return (BE == (__BYTE_ORDER == __BIG_ENDIAN)) ?
|
||||
((const hb_packed_t<uint64_t> *) v)->v
|
||||
:
|
||||
__builtin_bswap64 (((const hb_packed_t<uint64_t> *) v)->v)
|
||||
;
|
||||
#else
|
||||
return (BE ? (uint64_t (v[0]) << 56) : (uint64_t (v[0]) ))
|
||||
+ (BE ? (uint64_t (v[1]) << 48) : (uint64_t (v[1]) << 8))
|
||||
+ (BE ? (uint64_t (v[2]) << 40) : (uint64_t (v[2]) << 16))
|
||||
|
|
@ -240,6 +257,7 @@ struct HBInt<BE, Type, 8>
|
|||
+ (BE ? (uint64_t (v[5]) << 16) : (uint64_t (v[5]) << 40))
|
||||
+ (BE ? (uint64_t (v[6]) << 8) : (uint64_t (v[6]) << 48))
|
||||
+ (BE ? (uint64_t (v[7]) ) : (uint64_t (v[7]) << 56));
|
||||
#endif
|
||||
}
|
||||
private: uint8_t v[8];
|
||||
};
|
||||
|
|
|
|||
7
thirdparty/harfbuzz/src/hb-array.hh
vendored
7
thirdparty/harfbuzz/src/hb-array.hh
vendored
|
|
@ -291,6 +291,13 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
&& (unsigned int) (arrayZ + length - (const char *) p) >= size;
|
||||
}
|
||||
|
||||
template <unsigned P = sizeof (Type),
|
||||
hb_enable_if (P == 1)>
|
||||
bool check_end (const void *p) const
|
||||
{
|
||||
return (uintptr_t) (((const char *) p) - arrayZ) <= length;
|
||||
}
|
||||
|
||||
/* Only call if you allocated the underlying array using hb_malloc() or similar. */
|
||||
void fini ()
|
||||
{ hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
|
||||
|
|
|
|||
6
thirdparty/harfbuzz/src/hb-atomic.hh
vendored
6
thirdparty/harfbuzz/src/hb-atomic.hh
vendored
|
|
@ -169,11 +169,6 @@ struct hb_atomic_t
|
|||
|
||||
int operator++ (int) { return inc (); }
|
||||
int operator-- (int) { return dec (); }
|
||||
long operator|= (long v_)
|
||||
{
|
||||
set_relaxed (get_relaxed () | v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend void swap (hb_atomic_t &a, hb_atomic_t &b) noexcept
|
||||
{
|
||||
|
|
@ -236,7 +231,6 @@ struct hb_atomic_t
|
|||
|
||||
int operator ++ (int) { return inc (); }
|
||||
int operator -- (int) { return dec (); }
|
||||
long operator |= (long v_) { set_relaxed (get_relaxed () | v_); return *this; }
|
||||
|
||||
T v = 0;
|
||||
};
|
||||
|
|
|
|||
16
thirdparty/harfbuzz/src/hb-cache.hh
vendored
16
thirdparty/harfbuzz/src/hb-cache.hh
vendored
|
|
@ -64,12 +64,16 @@ template <unsigned int key_bits=16,
|
|||
struct hb_cache_t
|
||||
{
|
||||
using item_t = typename std::conditional<thread_safe,
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
|
||||
hb_atomic_t<unsigned short>,
|
||||
hb_atomic_t<unsigned int>>::type,
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
|
||||
unsigned short,
|
||||
unsigned int>::type
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 8,
|
||||
hb_atomic_t<unsigned char>,
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
|
||||
hb_atomic_t<unsigned short>,
|
||||
hb_atomic_t<unsigned int>>::type>::type,
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 8,
|
||||
unsigned char,
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
|
||||
unsigned short,
|
||||
unsigned int>::type>::type
|
||||
>::type;
|
||||
|
||||
static_assert ((key_bits >= cache_bits), "");
|
||||
|
|
|
|||
37
thirdparty/harfbuzz/src/hb-common.cc
vendored
37
thirdparty/harfbuzz/src/hb-common.cc
vendored
|
|
@ -40,43 +40,6 @@
|
|||
**/
|
||||
|
||||
|
||||
/* hb_options_t */
|
||||
|
||||
hb_atomic_t<unsigned> _hb_options;
|
||||
|
||||
void
|
||||
_hb_options_init ()
|
||||
{
|
||||
hb_options_union_t u;
|
||||
u.i = 0;
|
||||
u.opts.initialized = true;
|
||||
|
||||
const char *c = getenv ("HB_OPTIONS");
|
||||
if (c)
|
||||
{
|
||||
while (*c)
|
||||
{
|
||||
const char *p = strchr (c, ':');
|
||||
if (!p)
|
||||
p = c + strlen (c);
|
||||
|
||||
#define OPTION(name, symbol) \
|
||||
if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
|
||||
|
||||
OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
|
||||
|
||||
#undef OPTION
|
||||
|
||||
c = *p ? p + 1 : p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* This is idempotent and threadsafe. */
|
||||
_hb_options = u.i;
|
||||
}
|
||||
|
||||
|
||||
/* hb_tag_t */
|
||||
|
||||
/**
|
||||
|
|
|
|||
4
thirdparty/harfbuzz/src/hb-config.hh
vendored
4
thirdparty/harfbuzz/src/hb-config.hh
vendored
|
|
@ -145,10 +145,6 @@
|
|||
#define HB_NO_PAINT
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_GETENV
|
||||
#define HB_NO_UNISCRIBE_BUG_COMPATIBLE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_LEGACY
|
||||
#define HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
#define HB_NO_FALLBACK_SHAPE
|
||||
|
|
|
|||
42
thirdparty/harfbuzz/src/hb-debug.hh
vendored
42
thirdparty/harfbuzz/src/hb-debug.hh
vendored
|
|
@ -37,48 +37,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Global runtime options.
|
||||
*/
|
||||
|
||||
struct hb_options_t
|
||||
{
|
||||
bool unused : 1; /* In-case sign bit is here. */
|
||||
bool initialized : 1;
|
||||
bool uniscribe_bug_compatible : 1;
|
||||
};
|
||||
|
||||
union hb_options_union_t {
|
||||
unsigned i;
|
||||
hb_options_t opts;
|
||||
};
|
||||
static_assert ((sizeof (hb_atomic_t<unsigned>) >= sizeof (hb_options_union_t)), "");
|
||||
|
||||
HB_INTERNAL void
|
||||
_hb_options_init ();
|
||||
|
||||
extern HB_INTERNAL hb_atomic_t<unsigned> _hb_options;
|
||||
|
||||
static inline hb_options_t
|
||||
hb_options ()
|
||||
{
|
||||
#ifdef HB_NO_GETENV
|
||||
return hb_options_t ();
|
||||
#endif
|
||||
/* Make a local copy, so we can access bitfield threadsafely. */
|
||||
hb_options_union_t u;
|
||||
u.i = _hb_options;
|
||||
|
||||
if (unlikely (!u.i))
|
||||
{
|
||||
_hb_options_init ();
|
||||
u.i = _hb_options;
|
||||
}
|
||||
|
||||
return u.opts;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Debug output (needs enabling at compile time.)
|
||||
*/
|
||||
|
|
|
|||
6
thirdparty/harfbuzz/src/hb-font.hh
vendored
6
thirdparty/harfbuzz/src/hb-font.hh
vendored
|
|
@ -719,7 +719,13 @@ struct hb_font_t
|
|||
// Slant before embolden; produces nicer results.
|
||||
|
||||
if (slanted)
|
||||
{
|
||||
hb_position_t xo = 0, yo = 0;
|
||||
get_glyph_h_origin (glyph, &xo, &yo, false);
|
||||
outline.translate (-xo, -yo);
|
||||
outline.slant (slant_xy);
|
||||
outline.translate (xo, yo);
|
||||
}
|
||||
|
||||
if (embolden)
|
||||
{
|
||||
|
|
|
|||
304
thirdparty/harfbuzz/src/hb-kbts.cc
vendored
304
thirdparty/harfbuzz/src/hb-kbts.cc
vendored
|
|
@ -24,22 +24,140 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#if HAVE_KBTS
|
||||
#ifdef HAVE_KBTS
|
||||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#define KB_TEXT_SHAPE_IMPLEMENTATION
|
||||
#define KB_TEXT_SHAPE_STATIC
|
||||
#define KB_TEXT_SHAPE_NO_CRT
|
||||
#define KBTS_MALLOC(a, b) hb_malloc(b)
|
||||
#define KBTS_FREE(a, b) hb_free(b)
|
||||
#define KBTS_MEMCPY hb_memcpy
|
||||
#define KBTS_MEMSET hb_memset
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#pragma GCC diagnostic ignored "-Wextra-semi-stmt"
|
||||
#include "kb_text_shape.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
static hb_user_data_key_t hb_kbts_shape_plan_data_key = {0};
|
||||
|
||||
struct hb_kbts_shape_plan_data_t
|
||||
{
|
||||
kbts_shape_config *config = nullptr;
|
||||
mutable hb_atomic_t<kbts_shape_scratchpad *> scratchpad;
|
||||
};
|
||||
|
||||
static void
|
||||
hb_kbts_shape_plan_data_destroy (void *data)
|
||||
{
|
||||
auto *plan_data = (hb_kbts_shape_plan_data_t *) data;
|
||||
if (!plan_data)
|
||||
return;
|
||||
|
||||
auto *scratchpad = plan_data->scratchpad.get_acquire ();
|
||||
if (scratchpad && plan_data->scratchpad.cmpexch (scratchpad, nullptr))
|
||||
kbts_DestroyShapeScratchpad (scratchpad);
|
||||
|
||||
if (plan_data->config)
|
||||
kbts_DestroyShapeConfig (plan_data->config);
|
||||
|
||||
hb_free (plan_data);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_kbts_plan_props_to_script_language (const hb_segment_properties_t &props,
|
||||
kbts_script *kb_script,
|
||||
kbts_language *kb_language)
|
||||
{
|
||||
hb_tag_t scripts[HB_OT_MAX_TAGS_PER_SCRIPT];
|
||||
hb_tag_t language;
|
||||
unsigned int script_count = ARRAY_LENGTH (scripts);
|
||||
unsigned int language_count = 1;
|
||||
|
||||
*kb_script = KBTS_SCRIPT_DONT_KNOW;
|
||||
*kb_language = KBTS_LANGUAGE_DEFAULT;
|
||||
|
||||
hb_ot_tags_from_script_and_language (props.script, props.language,
|
||||
&script_count, scripts,
|
||||
&language_count, &language);
|
||||
|
||||
for (unsigned int i = 0; i < script_count && scripts[i] != HB_TAG_NONE; ++i)
|
||||
{
|
||||
*kb_script = kbts_ScriptTagToScript (hb_uint32_swap (scripts[i]));
|
||||
if (*kb_script != KBTS_SCRIPT_DONT_KNOW)
|
||||
break;
|
||||
}
|
||||
|
||||
if (language_count)
|
||||
*kb_language = (kbts_language) hb_uint32_swap (language);
|
||||
}
|
||||
|
||||
static hb_kbts_shape_plan_data_t *
|
||||
hb_kbts_get_shape_plan_data (hb_shape_plan_t *shape_plan,
|
||||
kbts_font *kb_font)
|
||||
{
|
||||
retry:
|
||||
auto *plan_data = (hb_kbts_shape_plan_data_t *)
|
||||
hb_shape_plan_get_user_data (shape_plan, &hb_kbts_shape_plan_data_key);
|
||||
if (plan_data)
|
||||
return plan_data;
|
||||
|
||||
kbts_script kb_script;
|
||||
kbts_language kb_language;
|
||||
hb_kbts_plan_props_to_script_language (shape_plan->key.props, &kb_script, &kb_language);
|
||||
|
||||
kbts_shape_config *config = kbts_CreateShapeConfig (kb_font, kb_script, kb_language, nullptr, nullptr);
|
||||
if (unlikely (!config))
|
||||
return nullptr;
|
||||
|
||||
plan_data = (hb_kbts_shape_plan_data_t *) hb_calloc (1, sizeof (*plan_data));
|
||||
if (unlikely (!plan_data))
|
||||
{
|
||||
kbts_DestroyShapeConfig (config);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
plan_data->config = config;
|
||||
plan_data->scratchpad.init (nullptr);
|
||||
|
||||
if (!hb_shape_plan_set_user_data (shape_plan,
|
||||
&hb_kbts_shape_plan_data_key,
|
||||
plan_data,
|
||||
hb_kbts_shape_plan_data_destroy,
|
||||
false))
|
||||
{
|
||||
hb_kbts_shape_plan_data_destroy (plan_data);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return plan_data;
|
||||
}
|
||||
|
||||
static kbts_shape_scratchpad *
|
||||
hb_kbts_acquire_shape_scratchpad (hb_kbts_shape_plan_data_t *plan_data)
|
||||
{
|
||||
auto *scratchpad = plan_data->scratchpad.get_acquire ();
|
||||
if (!scratchpad || unlikely (!plan_data->scratchpad.cmpexch (scratchpad, nullptr)))
|
||||
scratchpad = kbts_CreateShapeScratchpad (plan_data->config, nullptr, nullptr);
|
||||
|
||||
return scratchpad;
|
||||
}
|
||||
|
||||
static void
|
||||
hb_kbts_release_shape_scratchpad (hb_kbts_shape_plan_data_t *plan_data,
|
||||
kbts_shape_scratchpad *scratchpad)
|
||||
{
|
||||
if (!scratchpad)
|
||||
return;
|
||||
|
||||
if (!plan_data->scratchpad.cmpexch (nullptr, scratchpad))
|
||||
kbts_DestroyShapeScratchpad (scratchpad);
|
||||
}
|
||||
|
||||
|
||||
hb_kbts_face_data_t *
|
||||
_hb_kbts_shaper_face_data_create (hb_face_t *face)
|
||||
|
|
@ -55,40 +173,21 @@ _hb_kbts_shaper_face_data_create (hb_face_t *face)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void *data = hb_malloc (blob_length);
|
||||
if (likely (data))
|
||||
hb_memcpy (data, blob_data, blob_length);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
||||
if (unlikely (!data))
|
||||
{
|
||||
DEBUG_MSG (KBTS, face, "Failed to allocate memory for font data");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
kbts_font *kb_font = (kbts_font *) hb_calloc (1, sizeof (kbts_font));
|
||||
if (unlikely (!kb_font))
|
||||
{
|
||||
hb_free (data);
|
||||
hb_blob_destroy (blob);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t memory_size;
|
||||
{
|
||||
unsigned scratch_size = kbts_ReadFontHeader (kb_font, data, blob_length);
|
||||
void *scratch = hb_malloc (scratch_size);
|
||||
memory_size = kbts_ReadFontData (kb_font, scratch, scratch_size);
|
||||
hb_free (scratch);
|
||||
}
|
||||
*kb_font = kbts_FontFromMemory((void *)blob_data, blob_length, face->index, nullptr, nullptr);
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
||||
void *memory = hb_malloc (memory_size);
|
||||
if (unlikely (!kbts_PostReadFontInitialize (kb_font, memory, memory_size)))
|
||||
if (unlikely (!kbts_FontIsValid (kb_font)))
|
||||
{
|
||||
DEBUG_MSG (KBTS, face, "kbts_PostReadFontInitialize failed");
|
||||
hb_free (memory);
|
||||
hb_free (data);
|
||||
DEBUG_MSG (KBTS, face, "Failed create font from data");
|
||||
kbts_FreeFont (kb_font);
|
||||
hb_free (kb_font);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -103,8 +202,7 @@ _hb_kbts_shaper_face_data_destroy (hb_kbts_face_data_t *data)
|
|||
|
||||
assert (kbts_FontIsValid (font));
|
||||
|
||||
hb_free (font->FileBase);
|
||||
hb_free (font->GlyphLookupMatrix);
|
||||
kbts_FreeFont (font);
|
||||
hb_free (font);
|
||||
}
|
||||
|
||||
|
|
@ -144,116 +242,84 @@ _hb_kbts_shape (hb_shape_plan_t *shape_plan,
|
|||
return false;
|
||||
}
|
||||
|
||||
kbts_script kb_script = KBTS_SCRIPT_DONT_KNOW;
|
||||
kbts_language kb_language = KBTS_LANGUAGE_DEFAULT;
|
||||
{
|
||||
hb_tag_t scripts[HB_OT_MAX_TAGS_PER_SCRIPT];
|
||||
hb_tag_t language;
|
||||
unsigned int script_count = ARRAY_LENGTH (scripts);
|
||||
unsigned int language_count = 1;
|
||||
|
||||
hb_ot_tags_from_script_and_language (buffer->props.script, buffer->props.language,
|
||||
&script_count, scripts,
|
||||
&language_count, &language);
|
||||
|
||||
for (unsigned int i = 0; i < script_count && scripts[i] != HB_TAG_NONE; ++i)
|
||||
{
|
||||
kb_script = kbts_ScriptTagToScript (hb_uint32_swap (scripts[i]));
|
||||
if (kb_script != KBTS_SCRIPT_DONT_KNOW)
|
||||
break;
|
||||
}
|
||||
|
||||
if (language_count)
|
||||
kb_language = (kbts_language) hb_uint32_swap (language);
|
||||
}
|
||||
|
||||
hb_vector_t<kbts_glyph> kb_glyphs;
|
||||
if (unlikely (!kb_glyphs.resize_full (buffer->len, false, true)))
|
||||
kbts_glyph_storage kb_glyph_storage;
|
||||
if (unlikely (!kbts_InitializeGlyphStorage (&kb_glyph_storage, nullptr, nullptr)))
|
||||
return false;
|
||||
|
||||
hb_kbts_shape_plan_data_t *plan_data = hb_kbts_get_shape_plan_data (shape_plan, kb_font);
|
||||
if (unlikely (!plan_data))
|
||||
{
|
||||
kbts_FreeAllGlyphs (&kb_glyph_storage);
|
||||
return false;
|
||||
}
|
||||
|
||||
kbts_shape_config *kb_shape_config = nullptr;
|
||||
kbts_shape_scratchpad *kb_shape_scratchpad = nullptr;
|
||||
uint32_t glyph_count = 0;
|
||||
kbts_glyph *kb_glyph = nullptr;
|
||||
kbts_glyph_iterator kb_output;
|
||||
hb_glyph_info_t *info;
|
||||
hb_glyph_position_t *pos;
|
||||
hb_bool_t res = false;
|
||||
|
||||
kb_shape_config = plan_data->config;
|
||||
kb_shape_scratchpad = hb_kbts_acquire_shape_scratchpad (plan_data);
|
||||
if (unlikely (!kb_shape_scratchpad))
|
||||
goto done;
|
||||
|
||||
for (size_t i = 0; i < buffer->len; ++i)
|
||||
kb_glyphs.arrayZ[i] = kbts_CodepointToGlyph (kb_font, buffer->info[i].codepoint);
|
||||
|
||||
if (num_features)
|
||||
{
|
||||
for (unsigned int i = 0; i < num_features; ++i)
|
||||
kbts_glyph_config *kb_config = nullptr;
|
||||
if (num_features)
|
||||
{
|
||||
hb_feature_t feature = features[i];
|
||||
for (unsigned int j = 0; j < buffer->len; ++j)
|
||||
hb_vector_t<kbts_feature_override> kb_features;
|
||||
for (unsigned int j = 0; j < num_features; ++j)
|
||||
{
|
||||
kbts_glyph *kb_glyph = &kb_glyphs.arrayZ[j];
|
||||
if (hb_in_range (j, feature.start, feature.end))
|
||||
{
|
||||
if (!kb_glyph->Config)
|
||||
kb_glyph->Config = (kbts_glyph_config *) hb_calloc (1, sizeof (kbts_glyph_config));
|
||||
kbts_glyph_config *config = kb_glyph->Config;
|
||||
while (!kbts_GlyphConfigOverrideFeatureFromTag (config, hb_uint32_swap (feature.tag),
|
||||
feature.value > 1, feature.value))
|
||||
{
|
||||
config->FeatureOverrides = (kbts_feature_override *) hb_realloc (config->FeatureOverrides,
|
||||
config->RequiredFeatureOverrideCapacity);
|
||||
config->FeatureOverrideCapacity += 1;
|
||||
}
|
||||
}
|
||||
if (hb_in_range<size_t> (i, features[j].start, features[j].end))
|
||||
kb_features.push<kbts_feature_override>({ hb_uint32_swap (features[j].tag), (int)features[j].value });
|
||||
}
|
||||
if (kb_features)
|
||||
kb_config = kbts_CreateGlyphConfig (kb_shape_config, kb_features.arrayZ, kb_features.length, nullptr, nullptr);
|
||||
}
|
||||
kbts_PushGlyph (&kb_glyph_storage, kb_font, buffer->info[i].codepoint, kb_config, buffer->info[i].cluster);
|
||||
}
|
||||
|
||||
kbts_shape_state *kb_shape_state;
|
||||
{
|
||||
size_t kb_shape_state_size = kbts_SizeOfShapeState (kb_font);
|
||||
void *kb_shape_state_buffer = hb_malloc (kb_shape_state_size);
|
||||
if (unlikely (!kb_shape_state_buffer))
|
||||
{
|
||||
DEBUG_MSG (KBTS, face, "Failed to allocate memory for shape state");
|
||||
return false;
|
||||
}
|
||||
kb_shape_state = kbts_PlaceShapeState (kb_shape_state_buffer, kb_shape_state_size);
|
||||
}
|
||||
kbts_shape_config kb_shape_config = kbts_ShapeConfig (kb_font, kb_script, kb_language);
|
||||
uint32_t glyph_count = buffer->len;
|
||||
uint32_t glyph_capacity = kb_glyphs.length;
|
||||
while (kbts_Shape (kb_shape_state, &kb_shape_config, KBTS_DIRECTION_LTR, kb_direction,
|
||||
kb_glyphs.arrayZ, &glyph_count, glyph_capacity))
|
||||
{
|
||||
glyph_capacity = kb_shape_state->RequiredGlyphCapacity;
|
||||
/* kb increases capacity by a fixed number only. We increase it by 50% to
|
||||
* avoid O(n^2) behavior in case of expanding text.
|
||||
*
|
||||
* https://github.com/JimmyLefevre/kb/issues/32
|
||||
*/
|
||||
glyph_capacity += glyph_capacity / 2;
|
||||
if (unlikely (!kb_glyphs.resize_full (glyph_capacity, false, true)))
|
||||
return false;
|
||||
}
|
||||
res = kbts_ShapeDirect (kb_shape_scratchpad, &kb_glyph_storage, kb_direction, &kb_output) == KBTS_SHAPE_ERROR_NONE;
|
||||
if (unlikely (!res))
|
||||
goto done;
|
||||
|
||||
for (auto it = kb_output; kbts_GlyphIteratorNext (&it, &kb_glyph); )
|
||||
glyph_count += 1;
|
||||
|
||||
hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
|
||||
hb_buffer_set_length (buffer, glyph_count);
|
||||
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
|
||||
buffer->clear_positions ();
|
||||
for (size_t i = 0; i < glyph_count; ++i)
|
||||
{
|
||||
kbts_glyph kb_glyph = kb_glyphs.arrayZ[i];
|
||||
info[i].codepoint = kb_glyph.Id;
|
||||
info[i].cluster = 0; // FIXME
|
||||
pos[i].x_advance = font->em_scalef_x (kb_glyph.AdvanceX);
|
||||
pos[i].y_advance = font->em_scalef_y (kb_glyph.AdvanceY);
|
||||
pos[i].x_offset = font->em_scalef_x (kb_glyph.OffsetX);
|
||||
pos[i].y_offset = font->em_scalef_y (kb_glyph.OffsetY);
|
||||
|
||||
if (kb_glyph.Config)
|
||||
hb_free (kb_glyph.Config->FeatureOverrides);
|
||||
info = buffer->info;
|
||||
pos = buffer->pos;
|
||||
|
||||
for (auto it = kb_output; kbts_GlyphIteratorNext (&it, &kb_glyph); info++, pos++)
|
||||
{
|
||||
info->codepoint = kb_glyph->Id;
|
||||
info->cluster = kb_glyph->UserIdOrCodepointIndex;
|
||||
pos->x_advance = font->em_scalef_x (kb_glyph->AdvanceX);
|
||||
pos->y_advance = font->em_scalef_y (kb_glyph->AdvanceY);
|
||||
pos->x_offset = font->em_scalef_x (kb_glyph->OffsetX);
|
||||
pos->y_offset = font->em_scalef_y (kb_glyph->OffsetY);
|
||||
}
|
||||
|
||||
hb_free (kb_shape_state);
|
||||
done:
|
||||
if (likely (kb_shape_scratchpad))
|
||||
hb_kbts_release_shape_scratchpad (plan_data, kb_shape_scratchpad);
|
||||
while (kbts_GlyphIteratorNext (&kb_output, &kb_glyph))
|
||||
kbts_DestroyGlyphConfig (kb_glyph->Config);
|
||||
kbts_FreeAllGlyphs (&kb_glyph_storage);
|
||||
|
||||
buffer->clear_glyph_flags ();
|
||||
buffer->unsafe_to_break ();
|
||||
|
||||
return true;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
8
thirdparty/harfbuzz/src/hb-map.hh
vendored
8
thirdparty/harfbuzz/src/hb-map.hh
vendored
|
|
@ -492,16 +492,16 @@ struct hb_hashmap_t
|
|||
hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
|
||||
{ set (v.first, v.second); return *this; }
|
||||
template <typename V2 = V,
|
||||
hb_enable_if (!std::is_trivially_copyable<V2>::value)>
|
||||
hb_enable_if (!hb_is_trivially_copyable (V2))>
|
||||
hb_hashmap_t& operator << (const hb_pair_t<K, V&&>& v)
|
||||
{ set (v.first, std::move (v.second)); return *this; }
|
||||
template <typename K2 = K,
|
||||
hb_enable_if (!std::is_trivially_copyable<K2>::value)>
|
||||
hb_enable_if (!hb_is_trivially_copyable (K2))>
|
||||
hb_hashmap_t& operator << (const hb_pair_t<K&&, V>& v)
|
||||
{ set (std::move (v.first), v.second); return *this; }
|
||||
template <typename K2 = K, typename V2 = V,
|
||||
hb_enable_if (!std::is_trivially_copyable<K2>::value &&
|
||||
!std::is_trivially_copyable<V2>::value)>
|
||||
hb_enable_if (!hb_is_trivially_copyable (K2) &&
|
||||
!hb_is_trivially_copyable (V2))>
|
||||
hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
|
||||
{ set (std::move (v.first), std::move (v.second)); return *this; }
|
||||
|
||||
|
|
|
|||
14
thirdparty/harfbuzz/src/hb-open-file.hh
vendored
14
thirdparty/harfbuzz/src/hb-open-file.hh
vendored
|
|
@ -465,11 +465,11 @@ struct OpenTypeFontFile
|
|||
Typ1Tag = HB_TAG ('t','y','p','1') /* Obsolete Apple Type1 font in SFNT container */
|
||||
};
|
||||
|
||||
hb_tag_t get_tag () const { return u.tag; }
|
||||
hb_tag_t get_tag () const { return u.tag.v; }
|
||||
|
||||
unsigned int get_face_count () const
|
||||
{
|
||||
switch (u.tag) {
|
||||
switch (u.tag.v) {
|
||||
case CFFTag: /* All the non-collection tags */
|
||||
case TrueTag:
|
||||
case Typ1Tag:
|
||||
|
|
@ -483,7 +483,7 @@ struct OpenTypeFontFile
|
|||
{
|
||||
if (base_offset)
|
||||
*base_offset = 0;
|
||||
switch (u.tag) {
|
||||
switch (u.tag.v) {
|
||||
/* Note: for non-collection SFNT data we ignore index. This is because
|
||||
* Apple dfont container is a container of SFNT's. So each SFNT is a
|
||||
* non-TTC, but the index is more than zero. */
|
||||
|
|
@ -512,9 +512,9 @@ struct OpenTypeFontFile
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!u.tag.sanitize (c))) return_trace (false);
|
||||
if (unlikely (!u.tag.v.sanitize (c))) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.tag) {
|
||||
switch (u.tag.v) {
|
||||
case CFFTag: /* All the non-collection tags */
|
||||
case TrueTag:
|
||||
case Typ1Tag:
|
||||
|
|
@ -527,13 +527,13 @@ struct OpenTypeFontFile
|
|||
|
||||
protected:
|
||||
union {
|
||||
Tag tag; /* 4-byte identifier. */
|
||||
struct { Tag v; } tag; /* 4-byte identifier. */
|
||||
OpenTypeFontFace fontFace;
|
||||
TTCHeader ttcHeader;
|
||||
ResourceForkHeader rfHeader;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (4, tag);
|
||||
DEFINE_SIZE_UNION (4, tag.v);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
42
thirdparty/harfbuzz/src/hb-open-type.hh
vendored
42
thirdparty/harfbuzz/src/hb-open-type.hh
vendored
|
|
@ -62,7 +62,7 @@ struct NumType
|
|||
typedef Type type;
|
||||
/* For reason we define cast out operator for signed/unsigned, instead of Type, see:
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */
|
||||
typedef typename std::conditional<std::is_integral<Type>::value,
|
||||
typedef typename std::conditional<std::is_integral<Type>::value && sizeof (Type) <= sizeof(int),
|
||||
typename std::conditional<std::is_signed<Type>::value, signed, unsigned>::type,
|
||||
Type>::type WideType;
|
||||
|
||||
|
|
@ -118,6 +118,8 @@ typedef NumType<true, uint16_t> HBUINT16; /* 16-bit big-endian unsigned integer.
|
|||
typedef NumType<true, int16_t> HBINT16; /* 16-bit big-endian signed integer. */
|
||||
typedef NumType<true, uint32_t> HBUINT32; /* 32-bit big-endian unsigned integer. */
|
||||
typedef NumType<true, int32_t> HBINT32; /* 32-bit big-endian signed integer. */
|
||||
typedef NumType<true, uint64_t> HBUINT64; /* 64-bit big-endian unsigned integer. */
|
||||
typedef NumType<true, int64_t> HBINT64; /* 64-bit big-endian signed integer. */
|
||||
/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
|
||||
* Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
|
||||
typedef NumType<true, uint32_t, 3> HBUINT24; /* 24-bit big-endian unsigned integer. */
|
||||
|
|
@ -126,6 +128,8 @@ typedef NumType<false, uint16_t> HBUINT16LE; /* 16-bit little-endian unsigned in
|
|||
typedef NumType<false, int16_t> HBINT16LE; /* 16-bit little-endian signed integer. */
|
||||
typedef NumType<false, uint32_t> HBUINT32LE; /* 32-bit little-endian unsigned integer. */
|
||||
typedef NumType<false, int32_t> HBINT32LE; /* 32-bit little-endian signed integer. */
|
||||
typedef NumType<false, uint64_t> HBUINT64LE; /* 64-bit little-endian unsigned integer. */
|
||||
typedef NumType<false, int64_t> HBINT64LE; /* 64-bit little-endian signed integer. */
|
||||
|
||||
typedef NumType<true, float> HBFLOAT32BE; /* 32-bit little-endian floating point number. */
|
||||
typedef NumType<true, double> HBFLOAT64BE; /* 64-bit little-endian floating point number. */
|
||||
|
|
@ -522,16 +526,9 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
return_trace (sanitize_shallow (c, base) &&
|
||||
hb_barrier () &&
|
||||
(this->is_null () ||
|
||||
c->dispatch (StructAtOffset<Type> (base, *this), std::forward<Ts> (ds)...) ||
|
||||
neuter (c)));
|
||||
c->dispatch (StructAtOffset<Type> (base, *this), std::forward<Ts> (ds)...)));
|
||||
}
|
||||
|
||||
/* Set the offset to Null */
|
||||
bool neuter (hb_sanitize_context_t *c) const
|
||||
{
|
||||
if (!has_null) return false;
|
||||
return c->try_set (this, 0);
|
||||
}
|
||||
DEFINE_SIZE_STATIC (sizeof (OffsetType));
|
||||
};
|
||||
/* Partial specializations. */
|
||||
|
|
@ -1718,6 +1715,9 @@ struct TupleValues
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
HB_ALWAYS_INLINE
|
||||
#endif
|
||||
static bool decompile (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<T> &values /* IN/OUT */,
|
||||
const HBUINT8 *end,
|
||||
|
|
@ -1746,8 +1746,8 @@ struct TupleValues
|
|||
|
||||
if ((control & VALUES_SIZE_MASK) == VALUES_ARE_ZEROS)
|
||||
{
|
||||
for (; i < stop; i++)
|
||||
values.arrayZ[i] = 0;
|
||||
hb_memset (&values.arrayZ[i], 0, (stop - i) * sizeof (T));
|
||||
i = stop;
|
||||
}
|
||||
else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_WORDS)
|
||||
{
|
||||
|
|
@ -1806,7 +1806,7 @@ struct TupleValues
|
|||
{
|
||||
iter_t (const unsigned char *p_, unsigned len_)
|
||||
: p (p_), endp (p_ + len_)
|
||||
{ if (ensure_run ()) read_value (); }
|
||||
{ if (likely (ensure_run ())) read_value (); }
|
||||
|
||||
private:
|
||||
const unsigned char *p;
|
||||
|
|
@ -1815,10 +1815,14 @@ struct TupleValues
|
|||
signed run_count = 0;
|
||||
unsigned width = 0;
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
bool ensure_run ()
|
||||
{
|
||||
if (likely (run_count > 0)) return true;
|
||||
|
||||
return _ensure_run ();
|
||||
}
|
||||
bool _ensure_run ()
|
||||
{
|
||||
if (unlikely (p >= endp))
|
||||
{
|
||||
run_count = 0;
|
||||
|
|
@ -1908,10 +1912,15 @@ struct TupleValues
|
|||
signed run_count = 0;
|
||||
unsigned width = 0;
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
bool ensure_run ()
|
||||
{
|
||||
if (run_count > 0) return true;
|
||||
if (likely (run_count > 0)) return true;
|
||||
return _ensure_run ();
|
||||
}
|
||||
|
||||
bool _ensure_run ()
|
||||
{
|
||||
if (unlikely (p >= end))
|
||||
{
|
||||
run_count = 0;
|
||||
|
|
@ -2035,7 +2044,10 @@ struct TupleValues
|
|||
}
|
||||
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
if (scale == 1.0f)
|
||||
// The following branch is supposed to speed things up by avoiding
|
||||
// the multiplication in _add_to<> if scale is 1.0f.
|
||||
// But in practice it seems to bloat the code and slow things down.
|
||||
if (false && scale == 1.0f)
|
||||
_add_to<false> (out);
|
||||
else
|
||||
#endif
|
||||
|
|
|
|||
47
thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
vendored
47
thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
vendored
|
|
@ -697,16 +697,7 @@ struct CmapSubtableFormat4
|
|||
hb_barrier ();
|
||||
|
||||
if (unlikely (!c->check_range (this, length)))
|
||||
{
|
||||
/* Some broken fonts have too long of a "length" value.
|
||||
* If that is the case, just change the value to truncate
|
||||
* the subtable at the end of the blob. */
|
||||
uint16_t new_length = (uint16_t) hb_min ((uintptr_t) 65535,
|
||||
(uintptr_t) (c->end -
|
||||
(char *) this));
|
||||
if (!c->try_set (&length, new_length))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (false);
|
||||
|
||||
return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
|
||||
}
|
||||
|
|
@ -1496,7 +1487,7 @@ struct CmapSubtable
|
|||
bool get_glyph (hb_codepoint_t codepoint,
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return u.format0 .get_glyph (codepoint, glyph);
|
||||
case 4: hb_barrier (); return u.format4 .get_glyph (codepoint, glyph);
|
||||
case 6: hb_barrier (); return u.format6 .get_glyph (codepoint, glyph);
|
||||
|
|
@ -1509,7 +1500,7 @@ struct CmapSubtable
|
|||
}
|
||||
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs = UINT_MAX) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); u.format0 .collect_unicodes (out); return;
|
||||
case 4: hb_barrier (); u.format4 .collect_unicodes (out); return;
|
||||
case 6: hb_barrier (); u.format6 .collect_unicodes (out); return;
|
||||
|
|
@ -1525,7 +1516,7 @@ struct CmapSubtable
|
|||
hb_map_t *mapping, /* OUT */
|
||||
unsigned num_glyphs = UINT_MAX) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); u.format0 .collect_mapping (unicodes, mapping); return;
|
||||
case 4: hb_barrier (); u.format4 .collect_mapping (unicodes, mapping); return;
|
||||
case 6: hb_barrier (); u.format6 .collect_mapping (unicodes, mapping); return;
|
||||
|
|
@ -1539,7 +1530,7 @@ struct CmapSubtable
|
|||
|
||||
unsigned get_language () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return u.format0 .get_language ();
|
||||
case 4: hb_barrier (); return u.format4 .get_language ();
|
||||
case 6: hb_barrier (); return u.format6 .get_language ();
|
||||
|
|
@ -1570,9 +1561,9 @@ struct CmapSubtable
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return_trace (u.format0 .sanitize (c));
|
||||
case 4: hb_barrier (); return_trace (u.format4 .sanitize (c));
|
||||
case 6: hb_barrier (); return_trace (u.format6 .sanitize (c));
|
||||
|
|
@ -1586,7 +1577,7 @@ struct CmapSubtable
|
|||
|
||||
public:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
CmapSubtableFormat0 format0;
|
||||
CmapSubtableFormat4 format4;
|
||||
CmapSubtableFormat6 format6;
|
||||
|
|
@ -1596,7 +1587,7 @@ struct CmapSubtable
|
|||
CmapSubtableFormat14 format14;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1679,6 +1670,10 @@ struct SubtableUnicodesCache {
|
|||
{
|
||||
SubtableUnicodesCache* cache =
|
||||
(SubtableUnicodesCache*) hb_malloc (sizeof(SubtableUnicodesCache));
|
||||
|
||||
if (unlikely (!cache))
|
||||
return nullptr;
|
||||
|
||||
new (cache) SubtableUnicodesCache (source_table);
|
||||
return cache;
|
||||
}
|
||||
|
|
@ -1772,6 +1767,10 @@ struct cmap
|
|||
;
|
||||
|
||||
SubtableUnicodesCache* cache = SubtableUnicodesCache::create(source_table);
|
||||
|
||||
if (unlikely (!cache))
|
||||
return nullptr;
|
||||
|
||||
for (const EncodingRecord& _ : it)
|
||||
cache->set_for(&_); // populate the cache for this encoding record.
|
||||
|
||||
|
|
@ -1806,7 +1805,7 @@ struct cmap
|
|||
if (c->in_error ())
|
||||
return false;
|
||||
|
||||
unsigned format = (base+_.subtable).u.format;
|
||||
unsigned format = (base+_.subtable).u.format.v;
|
||||
if (format != 4 && format != 12 && format != 14) continue;
|
||||
|
||||
const hb_set_t* unicodes_set = unicodes_cache->set_for (&_, local_unicodes_cache);
|
||||
|
|
@ -1908,7 +1907,7 @@ struct cmap
|
|||
+ hb_iter (encodingRecord)
|
||||
| hb_map (&EncodingRecord::subtable)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_filter ([&] (const CmapSubtable& _) { return _.u.format == 14; })
|
||||
| hb_filter ([&] (const CmapSubtable& _) { return _.u.format.v == 14; })
|
||||
| hb_apply ([=] (const CmapSubtable& _) { _.u.format14.closure_glyphs (unicodes, glyphset); })
|
||||
;
|
||||
}
|
||||
|
|
@ -1933,7 +1932,7 @@ struct cmap
|
|||
|
||||
for (const EncodingRecord& _ : encodingrec_iter)
|
||||
{
|
||||
unsigned format = (this + _.subtable).u.format;
|
||||
unsigned format = (this + _.subtable).u.format.v;
|
||||
if (format == 12) has_format12 = true;
|
||||
|
||||
const EncodingRecord *table = std::addressof (_);
|
||||
|
|
@ -2021,7 +2020,7 @@ struct cmap
|
|||
this->subtable_uvs = &Null (CmapSubtableFormat14);
|
||||
{
|
||||
const CmapSubtable *st = table->find_subtable (0, 5);
|
||||
if (st && st->u.format == 14)
|
||||
if (st && st->u.format.v == 14)
|
||||
subtable_uvs = &st->u.format14;
|
||||
}
|
||||
|
||||
|
|
@ -2065,7 +2064,7 @@ struct cmap
|
|||
else
|
||||
#endif
|
||||
{
|
||||
switch (subtable->u.format) {
|
||||
switch (subtable->u.format.v) {
|
||||
/* Accelerate format 4 and format 12. */
|
||||
default:
|
||||
this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
|
||||
|
|
@ -2272,7 +2271,7 @@ struct cmap
|
|||
(_.platformID == 0 && _.encodingID == 4) ||
|
||||
(_.platformID == 3 && _.encodingID == 1) ||
|
||||
(_.platformID == 3 && _.encodingID == 10) ||
|
||||
(cmap + _.subtable).u.format == 14;
|
||||
(cmap + _.subtable).u.format.v == 14;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
|||
12
thirdparty/harfbuzz/src/hb-ot-kern-table.hh
vendored
12
thirdparty/harfbuzz/src/hb-ot-kern-table.hh
vendored
|
|
@ -306,8 +306,8 @@ struct kern
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
|
||||
|
||||
bool has_data () const { return u.version32; }
|
||||
unsigned get_type () const { return u.major; }
|
||||
bool has_data () const { return u.version32.v; }
|
||||
unsigned get_type () const { return u.major.v; }
|
||||
|
||||
bool has_state_machine () const
|
||||
{
|
||||
|
|
@ -363,7 +363,7 @@ struct kern
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.version32.sanitize (c)) return_trace (false);
|
||||
if (!u.version32.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
return_trace (dispatch (c));
|
||||
}
|
||||
|
|
@ -406,15 +406,15 @@ struct kern
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT32 version32;
|
||||
HBUINT16 major;
|
||||
struct { HBUINT32 v; } version32;
|
||||
struct { HBUINT16 v; } major;
|
||||
KernOT ot;
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
KernAAT aat;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (4, version32);
|
||||
DEFINE_SIZE_UNION (4, version32.v);
|
||||
};
|
||||
|
||||
struct kern_accelerator_t : kern::accelerator_t {
|
||||
|
|
|
|||
|
|
@ -165,13 +165,13 @@ struct BaseCoordFormat3
|
|||
|
||||
struct BaseCoord
|
||||
{
|
||||
bool has_data () const { return u.format; }
|
||||
bool has_data () const { return u.format.v; }
|
||||
|
||||
hb_position_t get_coord (hb_font_t *font,
|
||||
const ItemVariationStore &var_store,
|
||||
hb_direction_t direction) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.get_coord (font, direction);
|
||||
case 2: hb_barrier (); return u.format2.get_coord (font, direction);
|
||||
case 3: hb_barrier (); return u.format3.get_coord (font, var_store, direction);
|
||||
|
|
@ -181,7 +181,7 @@ struct BaseCoord
|
|||
|
||||
void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); return;
|
||||
default:return;
|
||||
}
|
||||
|
|
@ -190,9 +190,9 @@ struct BaseCoord
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
|
|
@ -203,9 +203,9 @@ struct BaseCoord
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!u.format.sanitize (c))) return_trace (false);
|
||||
if (unlikely (!u.format.v.sanitize (c))) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
|
||||
case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
|
||||
case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
|
||||
|
|
@ -215,13 +215,13 @@ struct BaseCoord
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format;
|
||||
struct { HBUINT16 v; } format;
|
||||
BaseCoordFormat1 format1;
|
||||
BaseCoordFormat2 format2;
|
||||
BaseCoordFormat3 format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
|
||||
struct FeatMinMaxRecord
|
||||
|
|
|
|||
147
thirdparty/harfbuzz/src/hb-ot-layout-common.hh
vendored
147
thirdparty/harfbuzz/src/hb-ot-layout-common.hh
vendored
|
|
@ -828,46 +828,9 @@ struct Feature
|
|||
const Record_sanitize_closure_t *closure = nullptr) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
|
||||
return_trace (false);
|
||||
hb_barrier ();
|
||||
|
||||
/* Some earlier versions of Adobe tools calculated the offset of the
|
||||
* FeatureParams subtable from the beginning of the FeatureList table!
|
||||
*
|
||||
* If sanitizing "failed" for the FeatureParams subtable, try it with the
|
||||
* alternative location. We would know sanitize "failed" if old value
|
||||
* of the offset was non-zero, but it's zeroed now.
|
||||
*
|
||||
* Only do this for the 'size' feature, since at the time of the faulty
|
||||
* Adobe tools, only the 'size' feature had FeatureParams defined.
|
||||
*/
|
||||
|
||||
if (likely (featureParams.is_null ()))
|
||||
return_trace (true);
|
||||
|
||||
unsigned int orig_offset = featureParams;
|
||||
if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
|
||||
return_trace (false);
|
||||
hb_barrier ();
|
||||
|
||||
if (featureParams == 0 && closure &&
|
||||
closure->tag == HB_TAG ('s','i','z','e') &&
|
||||
closure->list_base && closure->list_base < this)
|
||||
{
|
||||
unsigned int new_offset_int = orig_offset -
|
||||
(((char *) this) - ((char *) closure->list_base));
|
||||
|
||||
Offset16To<FeatureParams> new_offset;
|
||||
/* Check that it would not overflow. */
|
||||
new_offset = new_offset_int;
|
||||
if (new_offset == new_offset_int &&
|
||||
c->try_set (&featureParams, new_offset_int) &&
|
||||
!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
return_trace (c->check_struct (this) &&
|
||||
featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE) &&
|
||||
lookupIndex.sanitize (c));
|
||||
}
|
||||
|
||||
Offset16To<FeatureParams>
|
||||
|
|
@ -1433,7 +1396,7 @@ struct Lookup
|
|||
if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
|
||||
if (unlikely (get_type () == TSubTable::Extension))
|
||||
{
|
||||
hb_barrier ();
|
||||
|
||||
|
|
@ -1441,11 +1404,6 @@ struct Lookup
|
|||
* have the same type, which shall not be the Extension type
|
||||
* itself (but we already checked for that).
|
||||
* This is specially important if one has a reverse type!
|
||||
*
|
||||
* We only do this if sanitizer edit_count is zero. Otherwise,
|
||||
* some of the subtables might have become insane after they
|
||||
* were sanity-checked by the edits of subsequent subtables.
|
||||
* https://bugs.chromium.org/p/chromium/issues/detail?id=960331
|
||||
*/
|
||||
unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
|
||||
for (unsigned int i = 1; i < subtables; i++)
|
||||
|
|
@ -2075,7 +2033,7 @@ struct ClassDef
|
|||
unsigned int get (hb_codepoint_t k) const { return get_class (k); }
|
||||
unsigned int get_class (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.get_class (glyph_id);
|
||||
case 2: hb_barrier (); return u.format2.get_class (glyph_id);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2097,7 +2055,7 @@ struct ClassDef
|
|||
|
||||
unsigned get_population () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.get_population ();
|
||||
case 2: hb_barrier (); return u.format2.get_population ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2150,7 +2108,7 @@ struct ClassDef
|
|||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (glyph_max > 0xFFFFu)
|
||||
u.format += 2;
|
||||
u.format.v += 2;
|
||||
if (unlikely (glyph_max > 0xFFFFFFu))
|
||||
#else
|
||||
if (unlikely (glyph_max > 0xFFFFu))
|
||||
|
|
@ -2160,9 +2118,9 @@ struct ClassDef
|
|||
return_trace (false);
|
||||
}
|
||||
|
||||
u.format = format;
|
||||
u.format.v = format;
|
||||
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: hb_barrier (); return_trace (u.format1.serialize (c, it));
|
||||
case 2: hb_barrier (); return_trace (u.format2.serialize (c, it));
|
||||
|
|
@ -2181,7 +2139,7 @@ struct ClassDef
|
|||
const Coverage* glyph_filter = nullptr) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
|
||||
case 2: hb_barrier (); return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2195,9 +2153,9 @@ struct ClassDef
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
|
||||
case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2210,7 +2168,7 @@ struct ClassDef
|
|||
|
||||
unsigned cost () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.cost ();
|
||||
case 2: hb_barrier (); return u.format2.cost ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2226,7 +2184,7 @@ struct ClassDef
|
|||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.collect_coverage (glyphs);
|
||||
case 2: hb_barrier (); return u.format2.collect_coverage (glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2242,7 +2200,7 @@ struct ClassDef
|
|||
template <typename set_t>
|
||||
bool collect_class (set_t *glyphs, unsigned int klass) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass);
|
||||
case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2255,7 +2213,7 @@ struct ClassDef
|
|||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.intersects (glyphs);
|
||||
case 2: hb_barrier (); return u.format2.intersects (glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2267,7 +2225,7 @@ struct ClassDef
|
|||
}
|
||||
bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.intersects_class (glyphs, klass);
|
||||
case 2: hb_barrier (); return u.format2.intersects_class (glyphs, klass);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2280,7 +2238,7 @@ struct ClassDef
|
|||
|
||||
void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
|
||||
case 2: hb_barrier (); return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2293,7 +2251,7 @@ struct ClassDef
|
|||
|
||||
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.intersected_classes (glyphs, intersect_classes);
|
||||
case 2: hb_barrier (); return u.format2.intersected_classes (glyphs, intersect_classes);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2307,7 +2265,7 @@ struct ClassDef
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
ClassDefFormat1_3<SmallTypes> format1;
|
||||
ClassDefFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
|
@ -2316,7 +2274,7 @@ struct ClassDef
|
|||
#endif
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
|
|
@ -2628,7 +2586,17 @@ struct hb_scalar_cache_t
|
|||
void clear ()
|
||||
{
|
||||
auto *values = &static_values[0];
|
||||
for (unsigned i = 0; i < length; i++)
|
||||
unsigned i = 0;
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
for (; i + 3 < length; i += 4)
|
||||
{
|
||||
values[i + 0] = INVALID;
|
||||
values[i + 1] = INVALID;
|
||||
values[i + 2] = INVALID;
|
||||
values[i + 3] = INVALID;
|
||||
}
|
||||
#endif
|
||||
for (; i < length; i++)
|
||||
values[i] = INVALID;
|
||||
}
|
||||
|
||||
|
|
@ -2642,12 +2610,17 @@ struct hb_scalar_cache_t
|
|||
}
|
||||
auto *values = &static_values[0];
|
||||
auto *cached_value = &values[i];
|
||||
if (*cached_value != INVALID)
|
||||
// Super hot. Most common path is that we have a cached value of 0.
|
||||
int v = *cached_value;
|
||||
if (likely (!v))
|
||||
{
|
||||
*value = *cached_value ? *cached_value * DIVISOR : 0.f;
|
||||
*value = 0.f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (v == INVALID)
|
||||
return false;
|
||||
*value = v * DIVISOR;
|
||||
return true;
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
|
|
@ -3763,8 +3736,8 @@ struct DeltaSetIndexMap
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
unsigned length = plan.get_output_map ().length;
|
||||
u.format = length <= 0xFFFF ? 0 : 1;
|
||||
switch (u.format) {
|
||||
u.format.v = length <= 0xFFFF ? 0 : 1;
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return_trace (u.format0.serialize (c, plan));
|
||||
case 1: hb_barrier (); return_trace (u.format1.serialize (c, plan));
|
||||
default:return_trace (false);
|
||||
|
|
@ -3773,7 +3746,7 @@ struct DeltaSetIndexMap
|
|||
|
||||
uint32_t map (unsigned v) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return (u.format0.map (v));
|
||||
case 1: hb_barrier (); return (u.format1.map (v));
|
||||
default:return v;
|
||||
|
|
@ -3782,7 +3755,7 @@ struct DeltaSetIndexMap
|
|||
|
||||
unsigned get_map_count () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return u.format0.get_map_count ();
|
||||
case 1: hb_barrier (); return u.format1.get_map_count ();
|
||||
default:return 0;
|
||||
|
|
@ -3791,7 +3764,7 @@ struct DeltaSetIndexMap
|
|||
|
||||
unsigned get_width () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return u.format0.get_width ();
|
||||
case 1: hb_barrier (); return u.format1.get_width ();
|
||||
default:return 0;
|
||||
|
|
@ -3800,7 +3773,7 @@ struct DeltaSetIndexMap
|
|||
|
||||
unsigned get_inner_bit_count () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return u.format0.get_inner_bit_count ();
|
||||
case 1: hb_barrier (); return u.format1.get_inner_bit_count ();
|
||||
default:return 0;
|
||||
|
|
@ -3810,9 +3783,9 @@ struct DeltaSetIndexMap
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
|
||||
case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
|
||||
default:return_trace (true);
|
||||
|
|
@ -3822,7 +3795,7 @@ struct DeltaSetIndexMap
|
|||
DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 0: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
|
||||
case 1: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
|
||||
default:return_trace (nullptr);
|
||||
|
|
@ -3831,12 +3804,12 @@ struct DeltaSetIndexMap
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT8 format; /* Format identifier */
|
||||
struct { HBUINT8 v; } format; /* Format identifier */
|
||||
DeltaSetIndexMapFormat01<HBUINT16> format0;
|
||||
DeltaSetIndexMapFormat01<HBUINT32> format1;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (1, format);
|
||||
DEFINE_SIZE_UNION (1, format.v);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -4239,7 +4212,7 @@ struct Condition
|
|||
bool evaluate (const int *coords, unsigned int coord_len,
|
||||
Instancer *instancer) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.evaluate (coords, coord_len, instancer);
|
||||
case 2: hb_barrier (); return u.format2.evaluate (coords, coord_len, instancer);
|
||||
case 3: hb_barrier (); return u.format3.evaluate (coords, coord_len, instancer);
|
||||
|
|
@ -4252,7 +4225,7 @@ struct Condition
|
|||
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
|
||||
hb_map_t *condition_map /* OUT */) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.keep_with_variations (c, condition_map);
|
||||
// TODO(subset)
|
||||
default: c->apply = false; return KEEP_COND_WITH_VAR;
|
||||
|
|
@ -4262,9 +4235,9 @@ struct Condition
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
|
|
@ -4277,9 +4250,9 @@ struct Condition
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
|
||||
case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
|
||||
case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
|
||||
|
|
@ -4291,7 +4264,7 @@ struct Condition
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
ConditionAxisRange format1;
|
||||
ConditionValue format2;
|
||||
ConditionAnd format3;
|
||||
|
|
@ -4299,7 +4272,7 @@ struct Condition
|
|||
ConditionNegate format5;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
|
||||
template <typename Instancer>
|
||||
|
|
|
|||
225
thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
vendored
225
thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
vendored
|
|
@ -582,11 +582,12 @@ struct skipping_iterator_t
|
|||
#endif
|
||||
bool next (unsigned *unsafe_to = nullptr)
|
||||
{
|
||||
auto *info = c->buffer->info;
|
||||
const signed stop = (signed) end - 1;
|
||||
while ((signed) idx < stop)
|
||||
{
|
||||
idx++;
|
||||
switch (match (c->buffer->info[idx]))
|
||||
switch (match (info[idx]))
|
||||
{
|
||||
case MATCH:
|
||||
{
|
||||
|
|
@ -612,11 +613,12 @@ struct skipping_iterator_t
|
|||
#endif
|
||||
bool prev (unsigned *unsafe_from = nullptr)
|
||||
{
|
||||
auto *out_info = c->buffer->out_info;
|
||||
const unsigned stop = 0;
|
||||
while (idx > stop)
|
||||
{
|
||||
idx--;
|
||||
switch (match (c->buffer->out_info[idx]))
|
||||
switch (match (out_info[idx]))
|
||||
{
|
||||
case MATCH:
|
||||
{
|
||||
|
|
@ -786,7 +788,11 @@ struct hb_ot_apply_context_t :
|
|||
void set_random (bool random_) { random = random_; }
|
||||
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
|
||||
void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
|
||||
void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; init_iters (); }
|
||||
void set_lookup_props (unsigned int lookup_props_)
|
||||
{
|
||||
lookup_props = gdef_accel.sanitize_lookup_props (lookup_props_);
|
||||
init_iters ();
|
||||
}
|
||||
|
||||
uint32_t random_number ()
|
||||
{
|
||||
|
|
@ -831,7 +837,7 @@ struct hb_ot_apply_context_t :
|
|||
if (glyph_props & match_props & LookupFlag::IgnoreFlags)
|
||||
return false;
|
||||
|
||||
if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
|
||||
if (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)
|
||||
return match_properties_mark (info, glyph_props, match_props);
|
||||
|
||||
return true;
|
||||
|
|
@ -1312,10 +1318,19 @@ static bool match_input (hb_ot_apply_context_t *c,
|
|||
{
|
||||
TRACE_APPLY (nullptr);
|
||||
|
||||
if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
*end_position = buffer->idx + 1;
|
||||
c->match_positions[0] = buffer->idx;
|
||||
if (p_total_component_count)
|
||||
*p_total_component_count = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset (buffer->idx);
|
||||
skippy_iter.set_match_func (match_func, match_data);
|
||||
|
|
@ -1560,6 +1575,12 @@ static bool match_backtrack (hb_ot_apply_context_t *c,
|
|||
{
|
||||
TRACE_APPLY (nullptr);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
*match_start = c->buffer->backtrack_len ();
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
auto &skippy_iter = c->iter_context;
|
||||
skippy_iter.reset_back (c->buffer->backtrack_len ());
|
||||
skippy_iter.set_match_func (match_func, match_data);
|
||||
|
|
@ -1593,6 +1614,12 @@ static bool match_lookahead (hb_ot_apply_context_t *c,
|
|||
{
|
||||
TRACE_APPLY (nullptr);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
*end_index = start_index;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
auto &skippy_iter = c->iter_context;
|
||||
assert (start_index >= 1);
|
||||
skippy_iter.reset (start_index - 1);
|
||||
|
|
@ -1973,13 +2000,12 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
|
|||
}
|
||||
|
||||
template <typename HBUINT>
|
||||
HB_ALWAYS_INLINE
|
||||
static bool context_apply_lookup (hb_ot_apply_context_t *c,
|
||||
unsigned int inputCount, /* Including the first glyph (not matched) */
|
||||
const HBUINT input[], /* Array of input values--start with second glyph */
|
||||
unsigned int lookupCount,
|
||||
const LookupRecord lookupRecord[],
|
||||
const ContextApplyLookupContext &lookup_context)
|
||||
static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
|
||||
unsigned int inputCount, /* Including the first glyph (not matched) */
|
||||
const HBUINT input[], /* Array of input values--start with second glyph */
|
||||
unsigned int lookupCount,
|
||||
const LookupRecord lookupRecord[],
|
||||
const ContextApplyLookupContext &lookup_context)
|
||||
{
|
||||
if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
|
||||
|
||||
|
|
@ -2246,24 +2272,29 @@ struct RuleSet
|
|||
*
|
||||
* Replicated from LigatureSet::apply(). */
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
/* We use the iter_context instead of iter_input, to avoid skipping
|
||||
* default-ignorables and such.
|
||||
*
|
||||
* Related: https://github.com/harfbuzz/harfbuzz/issues/4813
|
||||
*/
|
||||
auto &skippy_iter = c->iter_context;
|
||||
skippy_iter.reset (c->buffer->idx);
|
||||
skippy_iter.set_match_func (match_always, nullptr);
|
||||
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
|
||||
unsigned unsafe_to = (unsigned) -1, unsafe_to1 = 0, unsafe_to2 = 0;
|
||||
unsigned unsafe_to = (unsigned) -1, unsafe_to1, unsafe_to2 = 0;
|
||||
hb_glyph_info_t *first = nullptr, *second = nullptr;
|
||||
bool matched = skippy_iter.next ();
|
||||
if (likely (matched))
|
||||
{
|
||||
first = &c->buffer->info[skippy_iter.idx];
|
||||
unsafe_to = skippy_iter.idx + 1;
|
||||
|
||||
if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
|
||||
{
|
||||
/* Can't use the fast path if eg. the next char is a default-ignorable
|
||||
* or other skippable. */
|
||||
goto slow;
|
||||
}
|
||||
|
||||
first = &c->buffer->info[skippy_iter.idx];
|
||||
unsafe_to1 = skippy_iter.idx + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2279,8 +2310,15 @@ struct RuleSet
|
|||
;
|
||||
}
|
||||
matched = skippy_iter.next ();
|
||||
if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
|
||||
if (likely (matched))
|
||||
{
|
||||
if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
|
||||
{
|
||||
/* Can't use the fast path if eg. the next char is a default-ignorable
|
||||
* or other skippable. */
|
||||
goto slow;
|
||||
}
|
||||
|
||||
second = &c->buffer->info[skippy_iter.idx];
|
||||
unsafe_to2 = skippy_iter.idx + 1;
|
||||
}
|
||||
|
|
@ -2317,6 +2355,15 @@ struct RuleSet
|
|||
{
|
||||
if (unsafe_to == (unsigned) -1)
|
||||
unsafe_to = unsafe_to1;
|
||||
|
||||
// Skip ahead to next possible first glyph match.
|
||||
for (; i + 1 < num_rules; i++)
|
||||
{
|
||||
const auto &r2 = this+rule.arrayZ[i + 1];
|
||||
const auto &input2 = r2.inputZ;
|
||||
if (r2.inputCount <= 1 || input2.arrayZ[0] != input.arrayZ[0])
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (likely (unsafe_to != (unsigned) -1))
|
||||
|
|
@ -2666,12 +2713,30 @@ struct ContextFormat2_5
|
|||
return context_cache_func (c, op);
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
struct external_cache_t
|
||||
{
|
||||
hb_ot_layout_binary_cache_t coverage;
|
||||
};
|
||||
void *external_cache_create () const
|
||||
{
|
||||
external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
cache->coverage.clear ();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
bool apply_cached (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, true, external_cache); }
|
||||
bool apply (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, false, external_cache); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached, void *external_cache) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
unsigned int index = (this+coverage).get_coverage_binary (c->buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
const ClassDef &class_def = this+classDef;
|
||||
|
|
@ -2926,9 +2991,9 @@ struct Context
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
|
|
@ -2942,7 +3007,7 @@ struct Context
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
ContextFormat1_4<SmallTypes> format1;
|
||||
ContextFormat2_5<SmallTypes> format2;
|
||||
ContextFormat3 format3;
|
||||
|
|
@ -3076,17 +3141,16 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c
|
|||
}
|
||||
|
||||
template <typename HBUINT>
|
||||
HB_ALWAYS_INLINE
|
||||
static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
|
||||
unsigned int backtrackCount,
|
||||
const HBUINT backtrack[],
|
||||
unsigned int inputCount, /* Including the first glyph (not matched) */
|
||||
const HBUINT input[], /* Array of input values--start with second glyph */
|
||||
unsigned int lookaheadCount,
|
||||
const HBUINT lookahead[],
|
||||
unsigned int lookupCount,
|
||||
const LookupRecord lookupRecord[],
|
||||
const ChainContextApplyLookupContext &lookup_context)
|
||||
static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
|
||||
unsigned int backtrackCount,
|
||||
const HBUINT backtrack[],
|
||||
unsigned int inputCount, /* Including the first glyph (not matched) */
|
||||
const HBUINT input[], /* Array of input values--start with second glyph */
|
||||
unsigned int lookaheadCount,
|
||||
const HBUINT lookahead[],
|
||||
unsigned int lookupCount,
|
||||
const LookupRecord lookupRecord[],
|
||||
const ChainContextApplyLookupContext &lookup_context)
|
||||
{
|
||||
if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
|
||||
|
||||
|
|
@ -3404,33 +3468,29 @@ struct ChainRuleSet
|
|||
*
|
||||
* Replicated from LigatureSet::apply(). */
|
||||
|
||||
/* If the input skippy has non-auto joiners behavior (as in Indic shapers),
|
||||
* skip this fast path, as we don't distinguish between input & lookahead
|
||||
* matching in the fast path.
|
||||
/* We use the iter_context instead of iter_input, to avoid skipping
|
||||
* default-ignorables and such.
|
||||
*
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/4813
|
||||
* Related: https://github.com/harfbuzz/harfbuzz/issues/4813
|
||||
*/
|
||||
if (!c->auto_zwnj || !c->auto_zwj)
|
||||
goto slow;
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
auto &skippy_iter = c->iter_context;
|
||||
skippy_iter.reset (c->buffer->idx);
|
||||
skippy_iter.set_match_func (match_always, nullptr);
|
||||
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
|
||||
unsigned unsafe_to = (unsigned) -1, unsafe_to1 = 0, unsafe_to2 = 0;
|
||||
unsigned unsafe_to = (unsigned) -1, unsafe_to1, unsafe_to2 = 0;
|
||||
hb_glyph_info_t *first = nullptr, *second = nullptr;
|
||||
bool matched = skippy_iter.next ();
|
||||
if (likely (matched))
|
||||
{
|
||||
first = &c->buffer->info[skippy_iter.idx];
|
||||
unsafe_to1 = skippy_iter.idx + 1;
|
||||
|
||||
if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
|
||||
{
|
||||
/* Can't use the fast path if eg. the next char is a default-ignorable
|
||||
* or other skippable. */
|
||||
goto slow;
|
||||
}
|
||||
|
||||
first = &c->buffer->info[skippy_iter.idx];
|
||||
unsafe_to1 = skippy_iter.idx + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3451,8 +3511,15 @@ struct ChainRuleSet
|
|||
;
|
||||
}
|
||||
matched = skippy_iter.next ();
|
||||
if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
|
||||
if (likely (matched))
|
||||
{
|
||||
if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
|
||||
{
|
||||
/* Can't use the fast path if eg. the next char is a default-ignorable
|
||||
* or other skippable. */
|
||||
goto slow;
|
||||
}
|
||||
|
||||
second = &c->buffer->info[skippy_iter.idx];
|
||||
unsafe_to2 = skippy_iter.idx + 1;
|
||||
}
|
||||
|
|
@ -3499,6 +3566,18 @@ struct ChainRuleSet
|
|||
{
|
||||
if (unsafe_to == (unsigned) -1)
|
||||
unsafe_to = unsafe_to1;
|
||||
|
||||
if (lenP1 > 1)
|
||||
{
|
||||
// Skip ahead to next possible first glyph match.
|
||||
for (; i + 1 < num_rules; i++)
|
||||
{
|
||||
const auto &r2 = this+rule.arrayZ[i + 1];
|
||||
const auto &input2 = StructAfter<decltype (r2.inputX)> (r2.backtrack);
|
||||
if (input2.lenP1 <= 1 || input2.arrayZ[0] != input.arrayZ[0])
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (likely (unsafe_to != (unsigned) -1))
|
||||
|
|
@ -3874,12 +3953,30 @@ struct ChainContextFormat2_5
|
|||
return context_cache_func (c, op);
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
struct external_cache_t
|
||||
{
|
||||
hb_ot_layout_binary_cache_t coverage;
|
||||
};
|
||||
void *external_cache_create () const
|
||||
{
|
||||
external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
cache->coverage.clear ();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
bool apply_cached (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, true, external_cache); }
|
||||
bool apply (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, false, external_cache); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached, void *external_cache) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
unsigned int index = (this+coverage).get_coverage_binary (c->buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
const ClassDef &backtrack_class_def = this+backtrackClassDef;
|
||||
|
|
@ -4227,9 +4324,9 @@ struct ChainContext
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
|
|
@ -4243,7 +4340,7 @@ struct ChainContext
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
ChainContextFormat1_4<SmallTypes> format1;
|
||||
ChainContextFormat2_5<SmallTypes> format2;
|
||||
ChainContextFormat3 format3;
|
||||
|
|
@ -4318,7 +4415,7 @@ struct Extension
|
|||
{
|
||||
unsigned int get_type () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.get_type ();
|
||||
default:return 0;
|
||||
}
|
||||
|
|
@ -4326,7 +4423,7 @@ struct Extension
|
|||
template <typename X>
|
||||
const X& get_subtable () const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.template get_subtable<typename T::SubTable> ();
|
||||
default:return Null (typename T::SubTable);
|
||||
}
|
||||
|
|
@ -4338,7 +4435,7 @@ struct Extension
|
|||
template <typename ...Ts>
|
||||
typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const
|
||||
{
|
||||
switch (u.format) {
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.subset (c);
|
||||
default: return c->default_return_value ();
|
||||
}
|
||||
|
|
@ -4347,9 +4444,9 @@ struct Extension
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
|
|
@ -4357,7 +4454,7 @@ struct Extension
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
ExtensionFormat1<T> format1;
|
||||
} u;
|
||||
};
|
||||
|
|
|
|||
48
thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
vendored
48
thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
vendored
|
|
@ -296,11 +296,6 @@ struct indic_shape_plan_t
|
|||
const indic_config_t *config;
|
||||
|
||||
bool is_old_spec;
|
||||
#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
|
||||
bool uniscribe_bug_compatible;
|
||||
#else
|
||||
static constexpr bool uniscribe_bug_compatible = false;
|
||||
#endif
|
||||
mutable hb_atomic_t<hb_codepoint_t> virama_glyph;
|
||||
|
||||
hb_indic_would_substitute_feature_t rphf;
|
||||
|
|
@ -327,9 +322,6 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
|
|||
}
|
||||
|
||||
indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
|
||||
#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
|
||||
indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
|
||||
#endif
|
||||
indic_plan->virama_glyph = -1;
|
||||
|
||||
/* Use zero-context would_substitute() matching for new-spec of the main
|
||||
|
|
@ -943,17 +935,7 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
|
|||
unsigned int start, unsigned int end)
|
||||
{
|
||||
/* We treat placeholder/dotted-circle as if they are consonants, so we
|
||||
* should just chain. Only if not in compatibility mode that is... */
|
||||
|
||||
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
|
||||
if (indic_plan->uniscribe_bug_compatible)
|
||||
{
|
||||
/* For dotted-circle, this is what Uniscribe does:
|
||||
* If dotted-circle is the last glyph, it just does nothing.
|
||||
* Ie. It doesn't form Reph. */
|
||||
if (buffer->info[end - 1].indic_category() == I_Cat(DOTTEDCIRCLE))
|
||||
return;
|
||||
}
|
||||
* should just chain... */
|
||||
|
||||
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
|
||||
}
|
||||
|
|
@ -1347,8 +1329,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
|
|||
* Uniscribe doesn't do this.
|
||||
* TEST: U+0930,U+094D,U+0915,U+094B,U+094D
|
||||
*/
|
||||
if (!indic_plan->uniscribe_bug_compatible &&
|
||||
unlikely (is_halant (info[new_reph_pos])))
|
||||
if (unlikely (is_halant (info[new_reph_pos])))
|
||||
{
|
||||
for (unsigned int i = base + 1; i < new_reph_pos; i++)
|
||||
if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
|
||||
|
|
@ -1451,27 +1432,6 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
|
|||
else
|
||||
buffer->unsafe_to_break (start - 1, start + 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish off the clusters and go home!
|
||||
*/
|
||||
if (indic_plan->uniscribe_bug_compatible)
|
||||
{
|
||||
switch ((hb_tag_t) plan->props.script)
|
||||
{
|
||||
case HB_SCRIPT_TAMIL:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Uniscribe merges the entire syllable into a single cluster... Except for Tamil.
|
||||
* This means, half forms are submerged into the main consonant's cluster.
|
||||
* This is unnecessary, and makes cursor positioning harder, but that's what
|
||||
* Uniscribe does. */
|
||||
buffer->merge_clusters (start, end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1501,9 +1461,7 @@ preprocess_text_indic (const hb_ot_shape_plan_t *plan,
|
|||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
|
||||
if (!indic_plan->uniscribe_bug_compatible)
|
||||
_hb_preprocess_text_vowel_constraints (plan, buffer, font);
|
||||
_hb_preprocess_text_vowel_constraints (plan, buffer, font);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
|||
|
|
@ -141,12 +141,6 @@ override_features_khmer (hb_ot_shape_planner_t *plan)
|
|||
* typographical correctness.", hence in overrides... */
|
||||
map->enable_feature (HB_TAG('c','l','i','g'));
|
||||
|
||||
/* Uniscribe does not apply 'kern' in Khmer. */
|
||||
if (hb_options ().uniscribe_bug_compatible)
|
||||
{
|
||||
map->disable_feature (HB_TAG('k','e','r','n'));
|
||||
}
|
||||
|
||||
map->disable_feature (HB_TAG('l','i','g','a'));
|
||||
}
|
||||
|
||||
|
|
|
|||
20
thirdparty/harfbuzz/src/hb-ot-stat-table.hh
vendored
20
thirdparty/harfbuzz/src/hb-ot-stat-table.hh
vendored
|
|
@ -352,7 +352,7 @@ struct AxisValue
|
|||
{
|
||||
float get_value (unsigned int axis_index) const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: hb_barrier (); return u.format1.get_value ();
|
||||
case 2: hb_barrier (); return u.format2.get_value ();
|
||||
|
|
@ -364,7 +364,7 @@ struct AxisValue
|
|||
|
||||
unsigned int get_axis_index () const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: hb_barrier (); return u.format1.get_axis_index ();
|
||||
case 2: hb_barrier (); return u.format2.get_axis_index ();
|
||||
|
|
@ -376,7 +376,7 @@ struct AxisValue
|
|||
|
||||
hb_ot_name_id_t get_value_name_id () const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: hb_barrier (); return u.format1.get_value_name_id ();
|
||||
case 2: hb_barrier (); return u.format2.get_value_name_id ();
|
||||
|
|
@ -389,9 +389,9 @@ struct AxisValue
|
|||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
|
|
@ -403,7 +403,7 @@ struct AxisValue
|
|||
bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
|
||||
hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
|
||||
{
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: hb_barrier (); return u.format1.keep_axis_value (axis_records, user_axes_location);
|
||||
case 2: hb_barrier (); return u.format2.keep_axis_value (axis_records, user_axes_location);
|
||||
|
|
@ -420,7 +420,7 @@ struct AxisValue
|
|||
return_trace (false);
|
||||
hb_barrier ();
|
||||
|
||||
switch (u.format)
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
|
||||
case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
|
||||
|
|
@ -433,14 +433,14 @@ struct AxisValue
|
|||
protected:
|
||||
union
|
||||
{
|
||||
HBUINT16 format;
|
||||
struct { HBUINT16 v; } format;
|
||||
AxisValueFormat1 format1;
|
||||
AxisValueFormat2 format2;
|
||||
AxisValueFormat3 format3;
|
||||
AxisValueFormat4 format4;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
};
|
||||
|
||||
struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>>
|
||||
|
|
|
|||
50
thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
vendored
50
thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
vendored
|
|
@ -411,6 +411,56 @@ struct avar
|
|||
#endif
|
||||
}
|
||||
|
||||
bool has_v2_data () const { return version.major > 1; }
|
||||
|
||||
// axis normalization is done in 2.14 here
|
||||
// TODO: deprecate this API once fonttools is updated to use 16.16 normalization
|
||||
bool map_coords_2_14 (float *coords, unsigned int coords_length) const
|
||||
{
|
||||
hb_vector_t<int> coords_2_14;
|
||||
if (!coords_2_14.resize (coords_length)) return false;
|
||||
unsigned int count = hb_min (coords_length, axisCount);
|
||||
|
||||
const SegmentMaps *map = &firstAxisSegmentMaps;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
int v = roundf (map->map_float (coords[i]) * 16384.f);
|
||||
coords_2_14[i] = v;
|
||||
coords[i] = v / 16384.f;
|
||||
map = &StructAfter<SegmentMaps> (*map);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_AVAR2
|
||||
if (version.major < 2)
|
||||
return true;
|
||||
hb_barrier ();
|
||||
|
||||
for (; count < axisCount; count++)
|
||||
map = &StructAfter<SegmentMaps> (*map);
|
||||
|
||||
const auto &v2 = * (const avarV2Tail *) map;
|
||||
|
||||
const auto &varidx_map = this+v2.varIdxMap;
|
||||
const auto &var_store = this+v2.varStore;
|
||||
auto *var_store_cache = var_store.create_cache ();
|
||||
|
||||
for (unsigned i = 0; i < coords_length; i++)
|
||||
{
|
||||
int v = coords_2_14[i];
|
||||
uint32_t varidx = varidx_map.map (i);
|
||||
float delta = var_store.get_delta (varidx, coords_2_14.arrayZ, coords_2_14.length, var_store_cache);
|
||||
v += roundf (delta);
|
||||
v = hb_clamp (v, -(1<<16), +(1<<16));
|
||||
coords[i] = v / 16384.f;
|
||||
}
|
||||
|
||||
OT::ItemVariationStore::destroy_cache (var_store_cache);
|
||||
return true;
|
||||
#else
|
||||
return version.major < 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
|
|
|||
101
thirdparty/harfbuzz/src/hb-ot-var-common.hh
vendored
101
thirdparty/harfbuzz/src/hb-ot-var-common.hh
vendored
|
|
@ -40,13 +40,22 @@ using rebase_tent_result_scratch_t = hb_pair_t<rebase_tent_result_t, rebase_tent
|
|||
struct TupleVariationHeader
|
||||
{
|
||||
friend struct tuple_delta_t;
|
||||
unsigned get_size (unsigned axis_count) const
|
||||
{ return min_size + get_all_tuples (axis_count).get_size (); }
|
||||
unsigned get_size (unsigned axis_count_times_2) const
|
||||
{
|
||||
// This function is super hot in mega-var-fonts with hundreds of masters.
|
||||
unsigned ti = tupleIndex;
|
||||
if (unlikely ((ti & (TupleIndex::EmbeddedPeakTuple | TupleIndex::IntermediateRegion))))
|
||||
{
|
||||
unsigned count = ((ti & TupleIndex::EmbeddedPeakTuple) != 0) + ((ti & TupleIndex::IntermediateRegion) != 0) * 2;
|
||||
return min_size + count * axis_count_times_2;
|
||||
}
|
||||
return min_size;
|
||||
}
|
||||
|
||||
unsigned get_data_size () const { return varDataSize; }
|
||||
|
||||
const TupleVariationHeader &get_next (unsigned axis_count) const
|
||||
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
|
||||
const TupleVariationHeader &get_next (unsigned axis_count_times_2) const
|
||||
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count_times_2)); }
|
||||
|
||||
bool unpack_axis_tuples (unsigned axis_count,
|
||||
const hb_array_t<const F2DOT14> shared_tuples,
|
||||
|
|
@ -109,23 +118,26 @@ struct TupleVariationHeader
|
|||
|
||||
const F2DOT14 *peak_tuple;
|
||||
|
||||
bool has_interm = tuple_index & TuppleIndex::IntermediateRegion; // Inlined for performance
|
||||
if (unlikely (has_interm))
|
||||
shared_tuple_scalar_cache = nullptr;
|
||||
bool has_interm = tuple_index & TupleIndex::IntermediateRegion; // Inlined for performance
|
||||
|
||||
if (unlikely (tuple_index & TuppleIndex::EmbeddedPeakTuple)) // Inlined for performance
|
||||
if (unlikely (tuple_index & TupleIndex::EmbeddedPeakTuple)) // Inlined for performance
|
||||
{
|
||||
peak_tuple = get_peak_tuple (coord_count);
|
||||
shared_tuple_scalar_cache = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int index = tuple_index & TuppleIndex::TupleIndexMask; // Inlined for performance
|
||||
unsigned int index = tuple_index & TupleIndex::TupleIndexMask; // Inlined for performance
|
||||
|
||||
float scalar;
|
||||
if (shared_tuple_scalar_cache &&
|
||||
shared_tuple_scalar_cache->get (index, &scalar))
|
||||
return (double) scalar;
|
||||
{
|
||||
if (has_interm && (scalar != 0 && scalar != 1.f))
|
||||
shared_tuple_scalar_cache = nullptr;
|
||||
else
|
||||
return (double) scalar;
|
||||
}
|
||||
|
||||
if (unlikely ((index + 1) * coord_count > shared_tuples.length))
|
||||
return 0.0;
|
||||
|
|
@ -143,8 +155,27 @@ struct TupleVariationHeader
|
|||
}
|
||||
|
||||
double scalar = 1.0;
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
bool skip = coord_count >= 16;
|
||||
#endif
|
||||
#endif
|
||||
for (unsigned int i = 0; i < coord_count; i++)
|
||||
{
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
if (skip)
|
||||
{
|
||||
while (i + 4 <= coord_count && * (HBUINT64LE *) &peak_tuple[i] == 0)
|
||||
i += 4;
|
||||
while (i < coord_count && peak_tuple[i].to_int () == 0)
|
||||
i += 1;
|
||||
if (i >= coord_count)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int peak = peak_tuple[i].to_int ();
|
||||
if (!peak) continue;
|
||||
|
||||
|
|
@ -154,6 +185,7 @@ struct TupleVariationHeader
|
|||
|
||||
if (has_interm)
|
||||
{
|
||||
shared_tuple_scalar_cache = nullptr;
|
||||
int start = start_tuple[i].to_int ();
|
||||
int end = end_tuple[i].to_int ();
|
||||
if (unlikely (start > peak || peak > end ||
|
||||
|
|
@ -173,13 +205,13 @@ struct TupleVariationHeader
|
|||
return scalar;
|
||||
}
|
||||
|
||||
bool has_peak () const { return tupleIndex & TuppleIndex::EmbeddedPeakTuple; }
|
||||
bool has_intermediate () const { return tupleIndex & TuppleIndex::IntermediateRegion; }
|
||||
bool has_private_points () const { return tupleIndex & TuppleIndex::PrivatePointNumbers; }
|
||||
unsigned get_index () const { return tupleIndex & TuppleIndex::TupleIndexMask; }
|
||||
bool has_peak () const { return tupleIndex & TupleIndex::EmbeddedPeakTuple; }
|
||||
bool has_intermediate () const { return tupleIndex & TupleIndex::IntermediateRegion; }
|
||||
bool has_private_points () const { return tupleIndex & TupleIndex::PrivatePointNumbers; }
|
||||
unsigned get_index () const { return tupleIndex & TupleIndex::TupleIndexMask; }
|
||||
|
||||
protected:
|
||||
struct TuppleIndex : HBUINT16
|
||||
struct TupleIndex : HBUINT16
|
||||
{
|
||||
enum Flags {
|
||||
EmbeddedPeakTuple = 0x8000u,
|
||||
|
|
@ -188,7 +220,7 @@ struct TupleVariationHeader
|
|||
TupleIndexMask = 0x0FFFu
|
||||
};
|
||||
|
||||
TuppleIndex& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
|
||||
TupleIndex& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
|
|
@ -205,7 +237,7 @@ struct TupleVariationHeader
|
|||
|
||||
HBUINT16 varDataSize; /* The size in bytes of the serialized
|
||||
* data for this tuple variation table. */
|
||||
TuppleIndex tupleIndex; /* A packed field. The high 4 bits are flags (see below).
|
||||
TupleIndex tupleIndex; /* A packed field. The high 4 bits are flags (see below).
|
||||
The low 12 bits are an index into a shared tuple
|
||||
records array. */
|
||||
/* UnsizedArrayOf<F2DOT14> peakTuple - optional */
|
||||
|
|
@ -288,13 +320,13 @@ struct tuple_delta_t
|
|||
void copy_from (const tuple_delta_t& o, hb_alloc_pool_t *pool = nullptr)
|
||||
{
|
||||
axis_tuples = o.axis_tuples;
|
||||
indices.allocate_from_pool (pool, o.indices);
|
||||
deltas_x.allocate_from_pool (pool, o.deltas_x);
|
||||
deltas_y.allocate_from_pool (pool, o.deltas_y);
|
||||
compiled_tuple_header.allocate_from_pool (pool, o.compiled_tuple_header);
|
||||
compiled_deltas.allocate_from_pool (pool, o.compiled_deltas);
|
||||
compiled_peak_coords.allocate_from_pool (pool, o.compiled_peak_coords);
|
||||
compiled_interm_coords.allocate_from_pool (pool, o.compiled_interm_coords);
|
||||
indices.duplicate_vector_from_pool (pool, o.indices);
|
||||
deltas_x.duplicate_vector_from_pool (pool, o.deltas_x);
|
||||
deltas_y.duplicate_vector_from_pool (pool, o.deltas_y);
|
||||
compiled_tuple_header.duplicate_vector_from_pool (pool, o.compiled_tuple_header);
|
||||
compiled_deltas.duplicate_vector_from_pool (pool, o.compiled_deltas);
|
||||
compiled_peak_coords.duplicate_vector_from_pool (pool, o.compiled_peak_coords);
|
||||
compiled_interm_coords.duplicate_vector_from_pool (pool, o.compiled_interm_coords);
|
||||
}
|
||||
|
||||
void remove_axis (hb_tag_t axis_tag)
|
||||
|
|
@ -515,7 +547,7 @@ struct tuple_delta_t
|
|||
|
||||
/* pointdata length = 0 implies "use shared points" */
|
||||
if (points_data_length)
|
||||
flag |= TupleVariationHeader::TuppleIndex::PrivatePointNumbers;
|
||||
flag |= TupleVariationHeader::TupleIndex::PrivatePointNumbers;
|
||||
|
||||
unsigned serialized_data_size = points_data_length + compiled_deltas.length;
|
||||
TupleVariationHeader *o = reinterpret_cast<TupleVariationHeader *> (compiled_tuple_header.begin ());
|
||||
|
|
@ -531,7 +563,7 @@ struct tuple_delta_t
|
|||
unsigned& flag) const
|
||||
{
|
||||
hb_memcpy (&peak_coords[0], &compiled_peak_coords[0], compiled_peak_coords.length * sizeof (compiled_peak_coords[0]));
|
||||
flag |= TupleVariationHeader::TuppleIndex::EmbeddedPeakTuple;
|
||||
flag |= TupleVariationHeader::TupleIndex::EmbeddedPeakTuple;
|
||||
return compiled_peak_coords.length;
|
||||
}
|
||||
|
||||
|
|
@ -542,7 +574,7 @@ struct tuple_delta_t
|
|||
if (compiled_interm_coords)
|
||||
{
|
||||
hb_memcpy (&coords[0], &compiled_interm_coords[0], compiled_interm_coords.length * sizeof (compiled_interm_coords[0]));
|
||||
flag |= TupleVariationHeader::TuppleIndex::IntermediateRegion;
|
||||
flag |= TupleVariationHeader::TupleIndex::IntermediateRegion;
|
||||
}
|
||||
return compiled_interm_coords.length;
|
||||
}
|
||||
|
|
@ -895,15 +927,15 @@ struct TupleVariationData
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
unsigned get_size (unsigned axis_count) const
|
||||
unsigned get_size (unsigned axis_count_times_2) const
|
||||
{
|
||||
unsigned total_size = min_size;
|
||||
unsigned count = tupleVarCount.get_count ();
|
||||
const TupleVariationHeader *tuple_var_header = &(get_tuple_var_header());
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
total_size += tuple_var_header->get_size (axis_count) + tuple_var_header->get_data_size ();
|
||||
tuple_var_header = &tuple_var_header->get_next (axis_count);
|
||||
total_size += tuple_var_header->get_size (axis_count_times_2) + tuple_var_header->get_data_size ();
|
||||
tuple_var_header = &tuple_var_header->get_next (axis_count_times_2);
|
||||
}
|
||||
|
||||
return total_size;
|
||||
|
|
@ -1398,6 +1430,7 @@ struct TupleVariationData
|
|||
var_data = var_data_bytes_.as<TupleVariationData> ();
|
||||
tuples_left = var_data->tupleVarCount.get_count ();
|
||||
axis_count = axis_count_;
|
||||
axis_count_times_2 = axis_count_ * 2;
|
||||
current_tuple = &var_data->get_tuple_var_header ();
|
||||
data_offset = 0;
|
||||
table_base = table_base_;
|
||||
|
|
@ -1421,11 +1454,11 @@ struct TupleVariationData
|
|||
return false;
|
||||
|
||||
current_tuple_size = TupleVariationHeader::min_size;
|
||||
if (unlikely (!var_data_bytes.check_range (current_tuple, current_tuple_size)))
|
||||
if (unlikely (!var_data_bytes.check_end ((const char *) current_tuple + current_tuple_size)))
|
||||
return false;
|
||||
|
||||
current_tuple_size = current_tuple->get_size (axis_count);
|
||||
if (unlikely (!var_data_bytes.check_range (current_tuple, current_tuple_size)))
|
||||
current_tuple_size = current_tuple->get_size (axis_count_times_2);
|
||||
if (unlikely (!var_data_bytes.check_end ((const char *) current_tuple + current_tuple_size)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -1448,6 +1481,7 @@ struct TupleVariationData
|
|||
signed tuples_left;
|
||||
const TupleVariationData *var_data;
|
||||
unsigned int axis_count;
|
||||
unsigned int axis_count_times_2;
|
||||
unsigned int data_offset;
|
||||
unsigned int current_tuple_size;
|
||||
const void *table_base;
|
||||
|
|
@ -1523,6 +1557,7 @@ struct TupleVariationData
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
HB_ALWAYS_INLINE
|
||||
static bool decompile_deltas (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<T> &deltas /* IN/OUT */,
|
||||
const HBUINT8 *end,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ struct cvar
|
|||
if (!coords) return true;
|
||||
hb_vector_t<unsigned> shared_indices;
|
||||
TupleVariationData<>::tuple_iterator_t iterator;
|
||||
unsigned var_data_length = tuple_var_data->get_size (axis_count);
|
||||
unsigned var_data_length = tuple_var_data->get_size (axis_count * 2);
|
||||
hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (tuple_var_data), var_data_length);
|
||||
if (!TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, base,
|
||||
shared_indices, &iterator))
|
||||
|
|
|
|||
24
thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
vendored
24
thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
vendored
|
|
@ -448,10 +448,18 @@ struct gvar_GVAR
|
|||
if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
it++;
|
||||
unsigned int subset_data_size = 0;
|
||||
unsigned padding_size = 0;
|
||||
for (auto &_ : it)
|
||||
{
|
||||
hb_codepoint_t old_gid = _.second;
|
||||
subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
|
||||
unsigned glyph_data_size = get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
|
||||
if (glyph_data_size % 2)
|
||||
{
|
||||
glyph_data_size++;
|
||||
padding_size++;
|
||||
}
|
||||
|
||||
subset_data_size += glyph_data_size;
|
||||
}
|
||||
|
||||
/* According to the spec: If the short format (Offset16) is used for offsets,
|
||||
|
|
@ -480,6 +488,8 @@ struct gvar_GVAR
|
|||
|
||||
/* This ordering relative to the shared tuples array, which puts the glyphVariationData
|
||||
last in the table, is required when HB_SUBSET_FLAGS_IFTB_REQUIREMENTS is set */
|
||||
if (long_offset)
|
||||
subset_data_size -= padding_size;
|
||||
char *subset_data = c->serializer->allocate_size<char> (subset_data_size, false);
|
||||
if (!subset_data) return_trace (false);
|
||||
out->dataZ = subset_data - (char *) out;
|
||||
|
|
@ -518,8 +528,16 @@ struct gvar_GVAR
|
|||
old_gid);
|
||||
|
||||
hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
|
||||
subset_data += var_data_bytes.length;
|
||||
glyph_offset += var_data_bytes.length;
|
||||
unsigned glyph_data_size = var_data_bytes.length;
|
||||
subset_data += glyph_data_size;
|
||||
glyph_offset += glyph_data_size;
|
||||
|
||||
if (!long_offset && (glyph_data_size % 2))
|
||||
{
|
||||
*subset_data = 0;
|
||||
subset_data++;
|
||||
glyph_offset++;
|
||||
}
|
||||
|
||||
if (long_offset)
|
||||
((HBUINT32 *) subset_offsets)[gid] = glyph_offset;
|
||||
|
|
|
|||
9
thirdparty/harfbuzz/src/hb-outline.cc
vendored
9
thirdparty/harfbuzz/src/hb-outline.cc
vendored
|
|
@ -84,6 +84,15 @@ void hb_outline_t::replay (hb_draw_funcs_t *pen, void *pen_data) const
|
|||
}
|
||||
}
|
||||
|
||||
void hb_outline_t::translate (float dx, float dy)
|
||||
{
|
||||
for (auto &p : points)
|
||||
{
|
||||
p.x += dx;
|
||||
p.y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
void hb_outline_t::slant (float slant_xy)
|
||||
{
|
||||
for (auto &p : points)
|
||||
|
|
|
|||
1
thirdparty/harfbuzz/src/hb-outline.hh
vendored
1
thirdparty/harfbuzz/src/hb-outline.hh
vendored
|
|
@ -69,6 +69,7 @@ struct hb_outline_t
|
|||
|
||||
HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const;
|
||||
HB_INTERNAL float control_area () const;
|
||||
HB_INTERNAL void translate (float dx, float dy);
|
||||
HB_INTERNAL void slant (float slant_xy);
|
||||
HB_INTERNAL void embolden (float x_strength, float y_strength,
|
||||
float x_shift, float y_shift);
|
||||
|
|
|
|||
82
thirdparty/harfbuzz/src/hb-sanitize.hh
vendored
82
thirdparty/harfbuzz/src/hb-sanitize.hh
vendored
|
|
@ -64,9 +64,6 @@
|
|||
*
|
||||
* - Cast blob content to T*, call sanitize() method of it,
|
||||
* - If sanitize succeeded, return blob.
|
||||
* - Otherwise, if blob is not writable, try making it writable,
|
||||
* or copy if cannot be made writable in-place,
|
||||
* - Call sanitize() again. Return blob if sanitize succeeded.
|
||||
* - Return empty blob otherwise.
|
||||
*
|
||||
*
|
||||
|
|
@ -98,6 +95,12 @@
|
|||
* structure is so complicated that by checking all offsets at sanitize() time,
|
||||
* we make the code much simpler in other methods, as offsets and referenced
|
||||
* objects do not need to be validated at each use site.
|
||||
*
|
||||
* Note:
|
||||
* Sanitize was named so because it used to try to recover from errors by
|
||||
* modifying the data to make it valid. This is no longer the case, as it
|
||||
* could make HarfBuzz hallucinate new rules if there was aliasing in the
|
||||
* data. However, the name stuck. See: https://behdad.github.io/harfbust/
|
||||
*/
|
||||
|
||||
/* This limits sanitizing time on really broken fonts. */
|
||||
|
|
@ -125,7 +128,7 @@ struct hb_sanitize_context_t :
|
|||
length (0),
|
||||
max_ops (0), max_subtables (0),
|
||||
recursion_depth (0),
|
||||
writable (false), edit_count (0),
|
||||
writable (false),
|
||||
blob (nullptr),
|
||||
num_glyphs (65536),
|
||||
num_glyphs_set (false),
|
||||
|
|
@ -236,7 +239,6 @@ struct hb_sanitize_context_t :
|
|||
this->max_ops = hb_clamp (m,
|
||||
(unsigned) HB_SANITIZE_MAX_OPS_MIN,
|
||||
(unsigned) HB_SANITIZE_MAX_OPS_MAX);
|
||||
this->edit_count = 0;
|
||||
this->debug_depth = 0;
|
||||
this->recursion_depth = 0;
|
||||
|
||||
|
|
@ -249,8 +251,8 @@ struct hb_sanitize_context_t :
|
|||
void end_processing ()
|
||||
{
|
||||
DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
|
||||
"end [%p..%p] %u edit requests",
|
||||
this->start, this->end, this->edit_count);
|
||||
"end [%p..%p]",
|
||||
this->start, this->end);
|
||||
|
||||
hb_blob_destroy (this->blob);
|
||||
this->blob = nullptr;
|
||||
|
|
@ -258,9 +260,6 @@ struct hb_sanitize_context_t :
|
|||
this->length = 0;
|
||||
}
|
||||
|
||||
unsigned get_edit_count () { return edit_count; }
|
||||
|
||||
|
||||
bool check_ops(unsigned count)
|
||||
{
|
||||
/* Avoid underflow */
|
||||
|
|
@ -404,35 +403,6 @@ struct hb_sanitize_context_t :
|
|||
return likely (this->check_point ((const char *) obj + obj->min_size));
|
||||
}
|
||||
|
||||
bool may_edit (const void *base, unsigned int len)
|
||||
{
|
||||
if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
|
||||
return false;
|
||||
|
||||
const char *p = (const char *) base;
|
||||
this->edit_count++;
|
||||
|
||||
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
|
||||
"may_edit(%u) [%p..%p] (%u bytes) in [%p..%p] -> %s",
|
||||
this->edit_count,
|
||||
p, p + len, len,
|
||||
this->start, this->end,
|
||||
this->writable ? "GRANTED" : "DENIED");
|
||||
|
||||
return this->writable;
|
||||
}
|
||||
|
||||
template <typename Type, typename ValueType>
|
||||
bool try_set (const Type *obj, const ValueType &v)
|
||||
{
|
||||
if (this->may_edit (obj, hb_static_size (Type)))
|
||||
{
|
||||
* const_cast<Type *> (obj) = v;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
hb_blob_t *sanitize_blob (hb_blob_t *blob)
|
||||
{
|
||||
|
|
@ -440,7 +410,6 @@ struct hb_sanitize_context_t :
|
|||
|
||||
init (blob);
|
||||
|
||||
retry:
|
||||
DEBUG_MSG_FUNC (SANITIZE, start, "start");
|
||||
|
||||
start_processing ();
|
||||
|
|
@ -454,38 +423,6 @@ struct hb_sanitize_context_t :
|
|||
Type *t = reinterpret_cast<Type *> (const_cast<char *> (start));
|
||||
|
||||
sane = t->sanitize (this);
|
||||
if (sane)
|
||||
{
|
||||
if (edit_count)
|
||||
{
|
||||
DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %u edits; going for second round", edit_count);
|
||||
|
||||
/* sanitize again to ensure no toe-stepping */
|
||||
edit_count = 0;
|
||||
sane = t->sanitize (this);
|
||||
if (edit_count) {
|
||||
DEBUG_MSG_FUNC (SANITIZE, start, "requested %u edits in second round; FAILING", edit_count);
|
||||
sane = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edit_count && !writable)
|
||||
{
|
||||
unsigned length;
|
||||
start = hb_blob_get_data_writable (blob, &length);
|
||||
end = start + length;
|
||||
|
||||
if (start)
|
||||
{
|
||||
writable = true;
|
||||
/* ok, we made it writable by relocating. try again */
|
||||
DEBUG_MSG_FUNC (SANITIZE, start, "retry");
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end_processing ();
|
||||
|
||||
|
|
@ -516,7 +453,6 @@ struct hb_sanitize_context_t :
|
|||
private:
|
||||
int recursion_depth;
|
||||
bool writable;
|
||||
unsigned int edit_count;
|
||||
hb_blob_t *blob;
|
||||
unsigned int num_glyphs;
|
||||
bool num_glyphs_set;
|
||||
|
|
|
|||
106
thirdparty/harfbuzz/src/hb-subset-plan-var.cc
vendored
106
thirdparty/harfbuzz/src/hb-subset-plan-var.cc
vendored
|
|
@ -160,36 +160,43 @@
|
|||
|
||||
#endif
|
||||
|
||||
void
|
||||
bool
|
||||
normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
||||
{
|
||||
if (plan->user_axes_location.is_empty ())
|
||||
return;
|
||||
return true;
|
||||
|
||||
hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes ();
|
||||
plan->normalized_coords.resize (axes.length);
|
||||
if (!plan->check_success (plan->normalized_coords.resize (axes.length)))
|
||||
return false;
|
||||
|
||||
bool has_avar = face->table.avar->has_data ();
|
||||
const OT::SegmentMaps *seg_maps = nullptr;
|
||||
unsigned avar_axis_count = 0;
|
||||
hb_vector_t<float> normalized_mins;
|
||||
hb_vector_t<float> normalized_defaults;
|
||||
hb_vector_t<float> normalized_maxs;
|
||||
if (has_avar)
|
||||
{
|
||||
seg_maps = face->table.avar->get_segment_maps ();
|
||||
avar_axis_count = face->table.avar->get_axis_count();
|
||||
if (!plan->check_success (normalized_mins.resize (axes.length)) ||
|
||||
!plan->check_success (normalized_defaults.resize (axes.length)) ||
|
||||
!plan->check_success (normalized_maxs.resize (axes.length)))
|
||||
return false;
|
||||
}
|
||||
|
||||
bool axis_not_pinned = false;
|
||||
unsigned old_axis_idx = 0, new_axis_idx = 0;
|
||||
for (const auto& axis : axes)
|
||||
unsigned new_axis_idx = 0;
|
||||
unsigned last_idx = 0;
|
||||
for (const auto& _ : + hb_enumerate (axes))
|
||||
{
|
||||
unsigned i = _.first;
|
||||
const OT::AxisRecord &axis = _.second;
|
||||
hb_tag_t axis_tag = axis.get_axis_tag ();
|
||||
plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag);
|
||||
plan->axes_old_index_tag_map.set (i, axis_tag);
|
||||
|
||||
if (!plan->user_axes_location.has (axis_tag) ||
|
||||
!plan->user_axes_location.get (axis_tag).is_point ())
|
||||
{
|
||||
axis_not_pinned = true;
|
||||
plan->axes_index_map.set (old_axis_idx, new_axis_idx);
|
||||
plan->axes_index_map.set (i, new_axis_idx);
|
||||
plan->axis_tags.push (axis_tag);
|
||||
new_axis_idx++;
|
||||
}
|
||||
|
|
@ -216,35 +223,66 @@ normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
normalized_default = roundf (normalized_default * 16384.f) / 16384.f;
|
||||
normalized_max = roundf (normalized_max * 16384.f) / 16384.f;
|
||||
|
||||
if (has_avar && old_axis_idx < avar_axis_count)
|
||||
if (has_avar)
|
||||
{
|
||||
normalized_min = seg_maps->map_float (normalized_min);
|
||||
normalized_default = seg_maps->map_float (normalized_default);
|
||||
normalized_max = seg_maps->map_float (normalized_max);
|
||||
|
||||
// Round to 2.14
|
||||
normalized_min = roundf (normalized_min * 16384.f) / 16384.f;
|
||||
normalized_default = roundf (normalized_default * 16384.f) / 16384.f;
|
||||
normalized_max = roundf (normalized_max * 16384.f) / 16384.f;
|
||||
normalized_mins[i] = normalized_min;
|
||||
normalized_defaults[i] = normalized_default;
|
||||
normalized_maxs[i] = normalized_max;
|
||||
last_idx = i;
|
||||
}
|
||||
plan->axes_location.set (axis_tag, Triple ((double) normalized_min,
|
||||
(double) normalized_default,
|
||||
(double) normalized_max));
|
||||
else
|
||||
{
|
||||
plan->axes_location.set (axis_tag, Triple ((double) normalized_min,
|
||||
(double) normalized_default,
|
||||
(double) normalized_max));
|
||||
if (normalized_default == -0.f)
|
||||
normalized_default = 0.f; // Normalize -0 to 0
|
||||
if (normalized_default != 0.f)
|
||||
plan->pinned_at_default = false;
|
||||
|
||||
if (normalized_default == -0.f)
|
||||
normalized_default = 0.f; // Normalize -0 to 0
|
||||
if (normalized_default != 0.f)
|
||||
plan->pinned_at_default = false;
|
||||
|
||||
plan->normalized_coords[old_axis_idx] = roundf (normalized_default * 16384.f);
|
||||
plan->normalized_coords[i] = roundf (normalized_default * 16384.f);
|
||||
}
|
||||
}
|
||||
|
||||
old_axis_idx++;
|
||||
|
||||
if (has_avar && old_axis_idx < avar_axis_count)
|
||||
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
|
||||
}
|
||||
plan->all_axes_pinned = !axis_not_pinned;
|
||||
|
||||
// TODO: use avar map_coords_16_16() when normalization is changed to 16.16
|
||||
// in fonttools
|
||||
if (has_avar)
|
||||
{
|
||||
const OT::avar* avar_table = face->table.avar;
|
||||
if (avar_table->has_v2_data () && !plan->all_axes_pinned)
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "Partial-instancing avar2 table is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned coords_len = last_idx + 1;
|
||||
if (!plan->check_success (avar_table->map_coords_2_14 (normalized_mins.arrayZ, coords_len)) ||
|
||||
!plan->check_success (avar_table->map_coords_2_14 (normalized_defaults.arrayZ, coords_len)) ||
|
||||
!plan->check_success (avar_table->map_coords_2_14 (normalized_maxs.arrayZ, coords_len)))
|
||||
return false;
|
||||
|
||||
for (const auto& _ : + hb_enumerate (axes))
|
||||
{
|
||||
unsigned i = _.first;
|
||||
hb_tag_t axis_tag = _.second.get_axis_tag ();
|
||||
if (plan->user_axes_location.has (axis_tag))
|
||||
{
|
||||
plan->axes_location.set (axis_tag, Triple ((double) normalized_mins[i],
|
||||
(double) normalized_defaults[i],
|
||||
(double) normalized_maxs[i]));
|
||||
float normalized_default = normalized_defaults[i];
|
||||
if (normalized_default == -0.f)
|
||||
normalized_default = 0.f; // Normalize -0 to 0
|
||||
if (normalized_default != 0.f)
|
||||
plan->pinned_at_default = false;
|
||||
|
||||
plan->normalized_coords[i] = roundf (normalized_default * 16384.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
3
thirdparty/harfbuzz/src/hb-subset-plan.cc
vendored
3
thirdparty/harfbuzz/src/hb-subset-plan.cc
vendored
|
|
@ -677,7 +677,8 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
|||
return;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
normalize_axes_location (face, this);
|
||||
if (!check_success (normalize_axes_location (face, this)))
|
||||
return;
|
||||
#endif
|
||||
|
||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
|
||||
|
|
|
|||
2
thirdparty/harfbuzz/src/hb-subset-plan.hh
vendored
2
thirdparty/harfbuzz/src/hb-subset-plan.hh
vendored
|
|
@ -333,7 +333,7 @@ generate_varstore_inner_maps (const hb_set_t& varidx_set,
|
|||
unsigned subtable_count,
|
||||
hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */);
|
||||
|
||||
HB_INTERNAL void
|
||||
HB_INTERNAL bool
|
||||
normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan);
|
||||
|
||||
HB_INTERNAL void
|
||||
|
|
|
|||
7
thirdparty/harfbuzz/src/hb-vector.hh
vendored
7
thirdparty/harfbuzz/src/hb-vector.hh
vendored
|
|
@ -313,6 +313,11 @@ struct hb_vector_t
|
|||
assert (allocated < 0);
|
||||
allocated = -(allocated + 1);
|
||||
}
|
||||
void ensure_error ()
|
||||
{
|
||||
if (!in_error ())
|
||||
set_error ();
|
||||
}
|
||||
|
||||
Type *
|
||||
_realloc (unsigned new_allocated)
|
||||
|
|
@ -565,7 +570,7 @@ struct hb_vector_t
|
|||
|
||||
template <typename allocator_t>
|
||||
HB_ALWAYS_INLINE_VECTOR_ALLOCS
|
||||
bool allocate_from_pool (allocator_t *allocator, const hb_vector_t &other)
|
||||
bool duplicate_vector_from_pool (allocator_t *allocator, const hb_vector_t &other)
|
||||
{
|
||||
if (unlikely (!allocate_from_pool (allocator, other.length, false)))
|
||||
return false;
|
||||
|
|
|
|||
6
thirdparty/harfbuzz/src/hb-version.h
vendored
6
thirdparty/harfbuzz/src/hb-version.h
vendored
|
|
@ -47,20 +47,20 @@ HB_BEGIN_DECLS
|
|||
*
|
||||
* The minor component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MINOR 2
|
||||
#define HB_VERSION_MINOR 3
|
||||
/**
|
||||
* HB_VERSION_MICRO:
|
||||
*
|
||||
* The micro component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MICRO 0
|
||||
#define HB_VERSION_MICRO 2
|
||||
|
||||
/**
|
||||
* HB_VERSION_STRING:
|
||||
*
|
||||
* A string literal containing the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_STRING "12.2.0"
|
||||
#define HB_VERSION_STRING "12.3.2"
|
||||
|
||||
/**
|
||||
* HB_VERSION_ATLEAST:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue