diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh | 263 |
1 files changed, 223 insertions, 40 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh index 06c9334b37..4a94e6a8ff 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh @@ -74,15 +74,16 @@ struct RearrangementSubtable ret (false), start (0), end (0) {} - bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, - const Entry<EntryData> &entry) + bool is_actionable (hb_buffer_t *buffer HB_UNUSED, + StateTableDriver<Types, EntryData> *driver HB_UNUSED, + const Entry<EntryData> &entry) const { return (entry.flags & Verb) && start < end; } - void transition (StateTableDriver<Types, EntryData> *driver, + void transition (hb_buffer_t *buffer, + StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> &entry) { - hb_buffer_t *buffer = driver->buffer; unsigned int flags = entry.flags; if (flags & MarkFirst) @@ -168,7 +169,7 @@ struct RearrangementSubtable driver_context_t dc (this); - StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->face); driver.drive (&dc, c); return_trace (dc.ret); @@ -180,10 +181,10 @@ struct RearrangementSubtable return_trace (machine.sanitize (c)); } - protected: + public: StateTable<Types, EntryData> machine; public: - DEFINE_SIZE_STATIC (16); + DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size)); }; template <typename Types> @@ -223,21 +224,19 @@ struct ContextualSubtable table (table_), subs (table+table->substitutionTables) {} - bool is_actionable (StateTableDriver<Types, EntryData> *driver, - const Entry<EntryData> &entry) + bool is_actionable (hb_buffer_t *buffer, + StateTableDriver<Types, EntryData> *driver, + const Entry<EntryData> &entry) const { - hb_buffer_t *buffer = driver->buffer; - if (buffer->idx == buffer->len && !mark_set) return false; return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF; } - void transition (StateTableDriver<Types, EntryData> *driver, + void transition (hb_buffer_t *buffer, + StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> &entry) { - hb_buffer_t *buffer = driver->buffer; - /* Looks like CoreText applies neither mark nor current substitution for * end-of-text if mark was not explicitly set. */ if (buffer->idx == buffer->len && !mark_set) @@ -328,7 +327,7 @@ struct ContextualSubtable driver_context_t dc (this, c); - StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->face); driver.drive (&dc, c); return_trace (dc.ret); @@ -361,13 +360,14 @@ struct ContextualSubtable return_trace (substitutionTables.sanitize (c, this, num_lookups)); } - protected: + public: StateTable<Types, EntryData> machine; + protected: NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false>, HBUINT> substitutionTables; public: - DEFINE_SIZE_STATIC (20); + DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + HBUINT::static_size)); }; @@ -464,16 +464,16 @@ struct LigatureSubtable ligature (table+table->ligature), match_length (0) {} - bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, - const Entry<EntryData> &entry) + bool is_actionable (hb_buffer_t *buffer HB_UNUSED, + StateTableDriver<Types, EntryData> *driver HB_UNUSED, + const Entry<EntryData> &entry) const { return LigatureEntryT::performAction (entry); } - void transition (StateTableDriver<Types, EntryData> *driver, + void transition (hb_buffer_t *buffer, + StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> &entry) { - hb_buffer_t *buffer = driver->buffer; - DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx); if (entry.flags & LigatureEntryT::SetComponent) { @@ -552,6 +552,7 @@ struct LigatureSubtable { DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; + buffer->cur().unicode_props() |= UPROPS_MASK_IGNORABLE; if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; } @@ -584,7 +585,7 @@ struct LigatureSubtable driver_context_t dc (this, c); - StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->face); driver.drive (&dc, c); return_trace (dc.ret); @@ -599,9 +600,10 @@ struct LigatureSubtable ligAction && component && ligature); } - protected: + public: StateTable<Types, EntryData> machine; + protected: NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT> ligAction; /* Offset to the ligature action table. */ NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT> @@ -609,7 +611,7 @@ struct LigatureSubtable NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT> ligature; /* Offset to the actual ligature lists. */ public: - DEFINE_SIZE_STATIC (28); + DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + 3 * HBUINT::static_size)); }; template <typename Types> @@ -753,16 +755,17 @@ struct InsertionSubtable mark (0), insertionAction (table+table->insertionAction) {} - bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, - const Entry<EntryData> &entry) + bool is_actionable (hb_buffer_t *buffer HB_UNUSED, + StateTableDriver<Types, EntryData> *driver HB_UNUSED, + const Entry<EntryData> &entry) const { return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) && (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF); } - void transition (StateTableDriver<Types, EntryData> *driver, + void transition (hb_buffer_t *buffer, + StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> &entry) { - hb_buffer_t *buffer = driver->buffer; unsigned int flags = entry.flags; unsigned mark_loc = buffer->out_len; @@ -849,7 +852,7 @@ struct InsertionSubtable driver_context_t dc (this, c); - StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->face); driver.drive (&dc, c); return_trace (dc.ret); @@ -864,14 +867,15 @@ struct InsertionSubtable insertionAction); } - protected: + public: StateTable<Types, EntryData> machine; + protected: NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT> insertionAction; /* Byte offset from stateHeader to the start of * the insertion glyph table. */ public: - DEFINE_SIZE_STATIC (20); + DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + HBUINT::static_size)); }; @@ -895,6 +899,89 @@ struct Feature DEFINE_SIZE_STATIC (12); }; + +struct hb_accelerate_subtables_context_t : + hb_dispatch_context_t<hb_accelerate_subtables_context_t> +{ + struct hb_applicable_t + { + friend struct hb_accelerate_subtables_context_t; + friend struct hb_aat_layout_lookup_accelerator_t; + + public: + hb_set_digest_t digest; + + template <typename T> + auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN + ( + obj_.machine.collect_glyphs (this->digest, num_glyphs) + ) + + template <typename T> + void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>) + { + digest = digest.full (); + } + + template <typename T> + void init (const T &obj_, unsigned num_glyphs) + { + init_ (obj_, num_glyphs, hb_prioritize); + } + }; + + /* Dispatch interface. */ + template <typename T> + return_t dispatch (const T &obj) + { + hb_applicable_t *entry = &array[i++]; + + entry->init (obj, num_glyphs); + + return hb_empty_t (); + } + static return_t default_return_value () { return hb_empty_t (); } + + bool stop_sublookup_iteration (return_t r) const { return false; } + + hb_accelerate_subtables_context_t (hb_applicable_t *array_, unsigned num_glyphs_) : + hb_dispatch_context_t<hb_accelerate_subtables_context_t> (), + array (array_), num_glyphs (num_glyphs_) {} + + hb_applicable_t *array; + unsigned num_glyphs; + unsigned i = 0; +}; + +struct hb_aat_layout_chain_accelerator_t +{ + template <typename TChain> + static hb_aat_layout_chain_accelerator_t *create (const TChain &chain, unsigned num_glyphs) + { + unsigned count = chain.get_subtable_count (); + + unsigned size = sizeof (hb_aat_layout_chain_accelerator_t) - + HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) + + count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t); + + /* The following is a calloc because when we are collecting subtables, + * some of them might be invalid and hence not collect; as a result, + * we might not fill in all the count entries of the subtables array. + * Zeroing it allows the set digest to gatekeep it without having to + * initialize it further. */ + auto *thiz = (hb_aat_layout_chain_accelerator_t *) hb_calloc (1, size); + if (unlikely (!thiz)) + return nullptr; + + hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables, num_glyphs); + chain.dispatch (&c_accelerate_subtables); + + return thiz; + } + + hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY]; +}; + template <typename Types> struct ChainSubtable { @@ -986,6 +1073,8 @@ struct Chain { typedef typename Types::HBUINT HBUINT; + unsigned get_subtable_count () const { return subtableCount; } + hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const { hb_mask_t flags = defaultFlags; @@ -1026,7 +1115,8 @@ struct Chain return flags; } - void apply (hb_aat_apply_context_t *c) const + void apply (hb_aat_apply_context_t *c, + const hb_aat_layout_chain_accelerator_t *accel) const { const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); unsigned int count = subtableCount; @@ -1038,6 +1128,7 @@ struct Chain hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); }))) goto skip; c->subtable_flags = subtable->subFeatureFlags; + c->machine_glyph_set = accel ? accel->subtables[i].digest : hb_set_digest_t::full (); if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) && HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != @@ -1099,7 +1190,22 @@ struct Chain unsigned int get_size () const { return length; } - bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); + unsigned int count = subtableCount; + for (unsigned int i = 0; i < count; i++) + { + typename context_t::return_t ret = subtable->dispatch (c, std::forward<Ts> (ds)...); + if (c->stop_sublookup_iteration (ret)) + return ret; + subtable = &StructAfter<ChainSubtable<Types>> (*subtable); + } + return c->default_return_value (); + } + + bool sanitize (hb_sanitize_context_t *c, unsigned int version) const { TRACE_SANITIZE (this); if (!(length.sanitize (c) && @@ -1121,6 +1227,13 @@ struct Chain subtable = &StructAfter<ChainSubtable<Types>> (*subtable); } + if (version >= 3) + { + const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) subtable; + if (!coverage->sanitize (c, count)) + return_trace (false); + } + return_trace (true); } @@ -1132,7 +1245,7 @@ struct Chain UnsizedArrayOf<Feature> featureZ; /* Features. */ /*ChainSubtable firstSubtable;*//* Subtables. */ -/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */ +/*SubtableGlyphCoverage coverages*//* Only if version >= 3. */ public: DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT)); @@ -1143,13 +1256,69 @@ struct Chain * The 'mort'/'morx' Table */ -template <typename Types, hb_tag_t TAG> +template <typename T, typename Types, hb_tag_t TAG> struct mortmorx { static constexpr hb_tag_t tableTag = TAG; bool has_data () const { return version != 0; } + struct accelerator_t + { + accelerator_t (hb_face_t *face) + { + hb_sanitize_context_t sc; + this->table = sc.reference_table<T> (face); + + this->chain_count = table->get_chain_count (); + + this->accels = (hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *) hb_calloc (this->chain_count, sizeof (*accels)); + if (unlikely (!this->accels)) + { + this->chain_count = 0; + this->table.destroy (); + this->table = hb_blob_get_empty (); + } + } + ~accelerator_t () + { + for (unsigned int i = 0; i < this->chain_count; i++) + hb_free (this->accels[i]); + hb_free (this->accels); + this->table.destroy (); + } + + hb_blob_t *get_blob () const { return table.get_blob (); } + + template <typename Chain> + hb_aat_layout_chain_accelerator_t *get_accel (unsigned chain_index, const Chain &chain, unsigned num_glyphs) const + { + if (unlikely (chain_index >= chain_count)) return nullptr; + + retry: + auto *accel = accels[chain_index].get_acquire (); + if (unlikely (!accel)) + { + accel = hb_aat_layout_chain_accelerator_t::create (chain, num_glyphs); + if (unlikely (!accel)) + return nullptr; + + if (unlikely (!accels[chain_index].cmpexch (nullptr, accel))) + { + hb_free (accel); + goto retry; + } + } + + return accel; + } + + hb_blob_ptr_t<T> table; + unsigned int chain_count; + hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *accels; + }; + + void compile_flags (const hb_aat_map_builder_t *mapper, hb_aat_map_t *map) const { @@ -1166,8 +1335,14 @@ struct mortmorx } } + unsigned get_chain_count () const + { + return chainCount; + } + void apply (hb_aat_apply_context_t *c, - const hb_aat_map_t &map) const + const hb_aat_map_t &map, + const accelerator_t &accel) const { if (unlikely (!c->buffer->successful)) return; @@ -1178,8 +1353,9 @@ struct mortmorx unsigned int count = chainCount; for (unsigned int i = 0; i < count; i++) { + auto *chain_accel = accel.get_accel (i, *chain, c->face->get_num_glyphs ()); c->range_flags = &map.chain_flags[i]; - chain->apply (c); + chain->apply (c, chain_accel); if (unlikely (!c->buffer->successful)) return; chain = &StructAfter<Chain<Types>> (*chain); } @@ -1219,8 +1395,15 @@ struct mortmorx DEFINE_SIZE_MIN (8); }; -struct morx : mortmorx<ExtendedTypes, HB_AAT_TAG_morx> {}; -struct mort : mortmorx<ObsoleteTypes, HB_AAT_TAG_mort> {}; +struct morx : mortmorx<morx, ExtendedTypes, HB_AAT_TAG_morx> {}; +struct mort : mortmorx<mort, ObsoleteTypes, HB_AAT_TAG_mort> {}; + +struct morx_accelerator_t : morx::accelerator_t { + morx_accelerator_t (hb_face_t *face) : morx::accelerator_t (face) {} +}; +struct mort_accelerator_t : mort::accelerator_t { + mort_accelerator_t (hb_face_t *face) : mort::accelerator_t (face) {} +}; } /* namespace AAT */ |