summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh263
1 files changed, 205 insertions, 58 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
index 7d53c354da..c26f376aa6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
@@ -46,8 +46,9 @@ struct hb_aat_apply_context_t :
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
{
const char *get_name () { return "APPLY"; }
- template <typename T>
- return_t dispatch (const T &obj) { return obj.apply (this); }
+ template <typename T, typename ...Ts>
+ return_t dispatch (const T &obj, Ts&&... ds)
+ { return obj.apply (this, std::forward<Ts> (ds)...); }
static return_t default_return_value () { return false; }
bool stop_sublookup_iteration (return_t r) const { return r; }
@@ -59,6 +60,9 @@ struct hb_aat_apply_context_t :
const ankr *ankr_table;
const OT::GDEF *gdef_table;
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
+ hb_set_digest_t machine_glyph_set = hb_set_digest_t::full ();
+ hb_set_digest_t left_set = hb_set_digest_t::full ();
+ hb_set_digest_t right_set = hb_set_digest_t::full ();
hb_mask_t subtable_flags = 0;
/* Unused. For debug tracing only. */
@@ -81,6 +85,8 @@ struct hb_aat_apply_context_t :
* Lookup Table
*/
+enum { DELETED_GLYPH = 0xFFFF };
+
template <typename T> struct Lookup;
template <typename T>
@@ -95,6 +101,12 @@ struct LookupFormat0
return &arrayZ[glyph_id];
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
+ {
+ glyphs.add_range (0, num_glyphs - 1);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -123,6 +135,14 @@ struct LookupSegmentSingle
int cmp (hb_codepoint_t g) const
{ return g < first ? -1 : g <= last ? 0 : +1 ; }
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (first == DELETED_GLYPH)
+ return;
+ glyphs.add_range (first, last);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -153,6 +173,14 @@ struct LookupFormat2
return v ? &v->value : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ unsigned count = segments.get_length ();
+ for (unsigned int i = 0; i < count; i++)
+ segments[i].collect_glyphs (glyphs);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -184,6 +212,14 @@ struct LookupSegmentArray
return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (first == DELETED_GLYPH)
+ return;
+ glyphs.add_range (first, last);
+ }
+
int cmp (hb_codepoint_t g) const
{ return g < first ? -1 : g <= last ? 0 : +1; }
@@ -191,6 +227,7 @@ struct LookupSegmentArray
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
+ hb_barrier () &&
first <= last &&
valuesZ.sanitize (c, base, last - first + 1));
}
@@ -199,6 +236,7 @@ struct LookupSegmentArray
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
+ hb_barrier () &&
first <= last &&
valuesZ.sanitize (c, base, last - first + 1, std::forward<Ts> (ds)...));
}
@@ -224,6 +262,14 @@ struct LookupFormat4
return v ? v->get_value (glyph_id, this) : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ unsigned count = segments.get_length ();
+ for (unsigned i = 0; i < count; i++)
+ segments[i].collect_glyphs (glyphs);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -252,6 +298,14 @@ struct LookupSingle
int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (glyph == DELETED_GLYPH)
+ return;
+ glyphs.add (glyph);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -281,6 +335,14 @@ struct LookupFormat6
return v ? &v->value : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ unsigned count = entries.get_length ();
+ for (unsigned i = 0; i < count; i++)
+ entries[i].collect_glyphs (glyphs);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -312,6 +374,16 @@ struct LookupFormat8
&valueArrayZ[glyph_id - firstGlyph] : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (unlikely (!glyphCount))
+ return;
+ if (firstGlyph == DELETED_GLYPH)
+ return;
+ glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -356,10 +428,21 @@ struct LookupFormat10
return v;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (unlikely (!glyphCount))
+ return;
+ if (firstGlyph == DELETED_GLYPH)
+ return;
+ glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
+ hb_barrier () &&
valueSize <= 4 &&
valueArrayZ.sanitize (c, glyphCount * valueSize));
}
@@ -403,6 +486,20 @@ struct Lookup
}
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned int num_glyphs) const
+ {
+ switch (u.format) {
+ case 0: u.format0.collect_glyphs (glyphs, num_glyphs); return;
+ case 2: u.format2.collect_glyphs (glyphs); return;
+ case 4: u.format4.collect_glyphs (glyphs); return;
+ case 6: u.format6.collect_glyphs (glyphs); return;
+ case 8: u.format8.collect_glyphs (glyphs); return;
+ case 10: u.format10.collect_glyphs (glyphs); return;
+ default:return;
+ }
+ }
+
typename T::type get_class (hb_codepoint_t glyph_id,
unsigned int num_glyphs,
unsigned int outOfRange) const
@@ -415,6 +512,7 @@ struct Lookup
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return_trace (false);
+ hb_barrier ();
switch (u.format) {
case 0: return_trace (u.format0.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
@@ -429,6 +527,7 @@ struct Lookup
{
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return_trace (false);
+ hb_barrier ();
switch (u.format) {
case 0: return_trace (u.format0.sanitize (c, base));
case 2: return_trace (u.format2.sanitize (c, base));
@@ -455,8 +554,6 @@ struct Lookup
};
DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
-enum { DELETED_GLYPH = 0xFFFF };
-
/*
* (Extended) State Table
*/
@@ -507,6 +604,14 @@ struct Entry<void>
DEFINE_SIZE_STATIC (4);
};
+enum Class
+{
+ CLASS_END_OF_TEXT = 0,
+ CLASS_OUT_OF_BOUNDS = 1,
+ CLASS_DELETED_GLYPH = 2,
+ CLASS_END_OF_LINE = 3,
+};
+
template <typename Types, typename Extra>
struct StateTable
{
@@ -519,21 +624,24 @@ struct StateTable
STATE_START_OF_TEXT = 0,
STATE_START_OF_LINE = 1,
};
- enum Class
+
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
{
- CLASS_END_OF_TEXT = 0,
- CLASS_OUT_OF_BOUNDS = 1,
- CLASS_DELETED_GLYPH = 2,
- CLASS_END_OF_LINE = 3,
- };
+ (this+classTable).collect_glyphs (glyphs, num_glyphs);
+ }
int new_state (unsigned int newState) const
{ return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
- unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+ template <typename set_t>
+ unsigned int get_class (hb_codepoint_t glyph_id,
+ unsigned int num_glyphs,
+ const set_t &glyphs) const
{
if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
- return (this+classTable).get_class (glyph_id, num_glyphs, 1);
+ if (!glyphs[glyph_id]) return CLASS_OUT_OF_BOUNDS;
+ return (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
}
const Entry<Extra> *get_entries () const
@@ -542,7 +650,7 @@ struct StateTable
const Entry<Extra> &get_entry (int state, unsigned int klass) const
{
if (unlikely (klass >= nClasses))
- klass = StateTable::CLASS_OUT_OF_BOUNDS;
+ klass = CLASS_OUT_OF_BOUNDS;
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry<Extra> *entries = (this+entryTable).arrayZ;
@@ -558,6 +666,7 @@ struct StateTable
{
TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this) &&
+ hb_barrier () &&
nClasses >= 4 /* Ensure pre-defined classes fit. */ &&
classTable.sanitize (c, this)))) return_trace (false);
@@ -684,6 +793,15 @@ struct ClassTable
{
return get_class (glyph_id, outOfRange);
}
+
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
+ {
+ for (unsigned i = 0; i < classArray.len; i++)
+ if (classArray.arrayZ[i] != CLASS_OUT_OF_BOUNDS)
+ glyphs.add (firstGlyph + i);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -697,6 +815,38 @@ struct ClassTable
DEFINE_SIZE_ARRAY (4, classArray);
};
+struct SubtableGlyphCoverage
+{
+ bool sanitize (hb_sanitize_context_t *c, unsigned subtable_count) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (unlikely (!c->check_array (&subtableOffsets, subtable_count)))
+ return_trace (false);
+
+ unsigned bytes = (c->get_num_glyphs () + CHAR_BIT - 1) / CHAR_BIT;
+ for (unsigned i = 0; i < subtable_count; i++)
+ {
+ uint32_t offset = (uint32_t) subtableOffsets[i];
+ if (offset == 0 || offset == 0xFFFFFFFF)
+ continue;
+ if (unlikely (!subtableOffsets[i].sanitize (c, this, bytes)))
+ return_trace (false);
+ }
+
+ return_trace (true);
+ }
+ protected:
+ UnsizedArrayOf<NNOffset32To<UnsizedArrayOf<HBUINT8>>> subtableOffsets;
+ /* Array of offsets from the beginning of the
+ * subtable glyph coverage table to the glyph
+ * coverage bitfield for a given subtable; there
+ * is one offset for each subtable in the chain */
+ /* UnsizedArrayOf<HBUINT8> coverageBitfields; *//* The individual coverage bitfields. */
+ public:
+ DEFINE_SIZE_ARRAY (0, subtableOffsets);
+};
+
struct ObsoleteTypes
{
static constexpr bool extended = false;
@@ -773,15 +923,15 @@ struct StateTableDriver
using EntryT = Entry<EntryData>;
StateTableDriver (const StateTableT &machine_,
- hb_buffer_t *buffer_,
hb_face_t *face_) :
machine (machine_),
- buffer (buffer_),
num_glyphs (face_->get_num_glyphs ()) {}
- template <typename context_t>
+ template <typename context_t, typename set_t = hb_set_digest_t>
void drive (context_t *c, hb_aat_apply_context_t *ac)
{
+ hb_buffer_t *buffer = ac->buffer;
+
if (!c->in_place)
buffer->clear_output ();
@@ -816,9 +966,9 @@ struct StateTableDriver
}
}
- unsigned int klass = buffer->idx < buffer->len ?
- machine.get_class (buffer->cur().codepoint, num_glyphs) :
- (unsigned) StateTableT::CLASS_END_OF_TEXT;
+ unsigned int klass = likely (buffer->idx < buffer->len) ?
+ machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_glyph_set) :
+ (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);
@@ -851,46 +1001,44 @@ struct StateTableDriver
*
* https://github.com/harfbuzz/harfbuzz/issues/2860
*/
- const EntryT *wouldbe_entry;
- bool safe_to_break =
- /* 1. */
- !c->is_actionable (this, entry)
- &&
- /* 2. */
- (
- /* 2a. */
- state == StateTableT::STATE_START_OF_TEXT
- ||
- /* 2b. */
- (
- (entry.flags & context_t::DontAdvance) &&
- next_state == StateTableT::STATE_START_OF_TEXT
- )
- ||
- /* 2c. */
- (
- wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
- ,
- /* 2c'. */
- !c->is_actionable (this, *wouldbe_entry)
- &&
- /* 2c". */
- (
- next_state == machine.new_state (wouldbe_entry->newState)
- &&
- (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
- )
- )
- )
- &&
- /* 3. */
- !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
- ;
-
- if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
+
+ const auto is_safe_to_break_extra = [&]()
+ {
+ /* 2c. */
+ const auto wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass);
+
+ /* 2c'. */
+ if (c->is_actionable (buffer, this, wouldbe_entry))
+ return false;
+
+ /* 2c". */
+ return next_state == machine.new_state(wouldbe_entry.newState)
+ && (entry.flags & context_t::DontAdvance) == (wouldbe_entry.flags & context_t::DontAdvance);
+ };
+
+ const auto is_safe_to_break = [&]()
+ {
+ /* 1. */
+ if (c->is_actionable (buffer, this, entry))
+ return false;
+
+ /* 2. */
+ // This one is meh, I know...
+ const auto ok =
+ state == StateTableT::STATE_START_OF_TEXT
+ || ((entry.flags & context_t::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
+ || is_safe_to_break_extra();
+ if (!ok)
+ return false;
+
+ /* 3. */
+ return !c->is_actionable (buffer, this, machine.get_entry (state, CLASS_END_OF_TEXT));
+ };
+
+ if (!is_safe_to_break () && buffer->backtrack_len () && buffer->idx < buffer->len)
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
- c->transition (this, entry);
+ c->transition (buffer, this, entry);
state = next_state;
DEBUG_MSG (APPLY, nullptr, "s%d", state);
@@ -908,7 +1056,6 @@ struct StateTableDriver
public:
const StateTableT &machine;
- hb_buffer_t *buffer;
unsigned int num_glyphs;
};