diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2024-05-13 15:19:58 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-13 15:19:58 -0700 |
commit | e2f1e3876826cd774152c11d3bd8c931dbbe8890 (patch) | |
tree | fe5d908bcdac0f9581a5428298b81573b757bad9 | |
parent | 687c218fcb4ca094b4db7008b88b7c4ca432b1b5 (diff) | |
parent | 204778e8311b48404943bf0920aac5c7d1be0790 (diff) | |
download | harfbuzz_ng-e2f1e3876826cd774152c11d3bd8c931dbbe8890.tar.gz |
Merge pull request #4719 from harfbuzz/aat-buffer-digest
[aat] For short words, use buffer digest to skip morx / kerx subtables
-rw-r--r-- | src/hb-aat-layout-common.hh | 10 | ||||
-rw-r--r-- | src/hb-aat-layout-kerx-table.hh | 44 | ||||
-rw-r--r-- | src/hb-aat-layout-morx-table.hh | 31 |
3 files changed, 79 insertions, 6 deletions
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index dbee48717..e0cfb078e 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -39,6 +39,7 @@ namespace AAT { using namespace OT; +#define HB_AAT_BUFFER_DIGEST_THRESHOLD 32 struct ankr; @@ -60,6 +61,7 @@ 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 buffer_digest = hb_set_digest_t::full (); 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 (); @@ -927,6 +929,14 @@ struct StateTableDriver machine (machine_), num_glyphs (face_->get_num_glyphs ()) {} + template <typename context_t> + bool is_idempotent_on_all_out_of_bounds (context_t *c, hb_aat_apply_context_t *ac) + { + const auto entry = machine.get_entry (StateTableT::STATE_START_OF_TEXT, CLASS_OUT_OF_BOUNDS); + return !c->is_actionable (ac->buffer, this, entry) && + machine.new_state (entry.newState) == StateTableT::STATE_START_OF_TEXT; + } + template <typename context_t, typename set_t = hb_set_digest_t> void drive (context_t *c, hb_aat_apply_context_t *ac) { diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 8d0d87af0..c01c31d73 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -107,10 +107,14 @@ struct KerxSubTableFormat0 TRACE_APPLY (this); if (!c->plan->requested_kerning) - return false; + return_trace (false); if (header.coverage & header.Backwards) - return false; + return_trace (false); + + if (!(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); accelerator_t accel (*this, c); hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream); @@ -367,6 +371,12 @@ struct KerxSubTableFormat1 driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->font->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); + driver.drive (&dc, c); return_trace (true); @@ -425,10 +435,14 @@ struct KerxSubTableFormat2 TRACE_APPLY (this); if (!c->plan->requested_kerning) - return false; + return_trace (false); if (header.coverage & header.Backwards) - return false; + return_trace (false); + + if (!(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); accelerator_t accel (*this, c); hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream); @@ -635,6 +649,12 @@ struct KerxSubTableFormat4 driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->font->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); + driver.drive (&dc, c); return_trace (true); @@ -710,10 +730,14 @@ struct KerxSubTableFormat6 TRACE_APPLY (this); if (!c->plan->requested_kerning) - return false; + return_trace (false); if (header.coverage & header.Backwards) - return false; + return_trace (false); + + if (!(c->buffer_digest.may_have (c->left_set) && + c->buffer_digest.may_have (c->right_set))) + return_trace (false); accelerator_t accel (*this, c); hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream); @@ -919,6 +943,9 @@ struct KerxTable { if (st->get_type () == 1) return true; + + // TODO: What about format 4? What's this API used for anyway? + st = &StructAfter<SubTable> (*st); } return false; @@ -962,6 +989,11 @@ struct KerxTable { c->buffer->unsafe_to_concat (); + if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD) + c->buffer_digest = c->buffer->digest (); + else + c->buffer_digest = hb_set_digest_t::full (); + typedef typename T::SubTable SubTable; bool ret = false; diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 4a94e6a8f..4a0f6da16 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -170,6 +170,11 @@ struct RearrangementSubtable driver_context_t dc (this); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -267,6 +272,7 @@ struct ContextualSubtable { buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); buffer->info[mark].codepoint = *replacement; + c->buffer_digest.add (*replacement); if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&buffer->info[mark], gdef.get_glyph_props (*replacement)); @@ -296,6 +302,7 @@ struct ContextualSubtable if (replacement) { buffer->info[idx].codepoint = *replacement; + c->buffer_digest.add (*replacement); if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&buffer->info[idx], gdef.get_glyph_props (*replacement)); @@ -328,6 +335,11 @@ struct ContextualSubtable driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -586,6 +598,11 @@ struct LigatureSubtable driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -654,6 +671,7 @@ struct NoncontextualSubtable if (replacement) { info[i].codepoint = *replacement; + c->buffer_digest.add (*replacement); if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&info[i], gdef.get_glyph_props (*replacement)); @@ -788,6 +806,9 @@ struct InsertionSubtable if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; + for (unsigned int i = 0; i < count; i++) + c->buffer_digest.add (glyphs[i]); + ret = true; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); @@ -853,6 +874,11 @@ struct InsertionSubtable driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->face); + + if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && + !c->buffer_digest.may_have (c->machine_glyph_set)) + return_trace (false); + driver.drive (&dc, c); return_trace (dc.ret); @@ -1348,6 +1374,11 @@ struct mortmorx c->buffer->unsafe_to_concat (); + if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD) + c->buffer_digest = c->buffer->digest (); + else + c->buffer_digest = hb_set_digest_t::full (); + c->set_lookup_index (0); const Chain<Types> *chain = &firstChain; unsigned int count = chainCount; |