aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2024-05-13 15:19:58 -0700
committerGitHub <noreply@github.com>2024-05-13 15:19:58 -0700
commite2f1e3876826cd774152c11d3bd8c931dbbe8890 (patch)
treefe5d908bcdac0f9581a5428298b81573b757bad9
parent687c218fcb4ca094b4db7008b88b7c4ca432b1b5 (diff)
parent204778e8311b48404943bf0920aac5c7d1be0790 (diff)
downloadharfbuzz_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.hh10
-rw-r--r--src/hb-aat-layout-kerx-table.hh44
-rw-r--r--src/hb-aat-layout-morx-table.hh31
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;