diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 3c8bf2629..17624cbe2 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -66,6 +66,7 @@ struct hb_aat_apply_context_t : const ankr *ankr_table; const OT::GDEF *gdef_table; const hb_sorted_vector_t *range_flags = nullptr; + bool using_buffer_glyph_set = false; hb_bit_set_t buffer_glyph_set; const hb_bit_set_t *left_set = nullptr; const hb_bit_set_t *right_set = nullptr; @@ -86,6 +87,30 @@ struct hb_aat_apply_context_t : HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_); void set_lookup_index (unsigned int i) { lookup_index = i; } + +#define HB_MALLOC_COST 48 +#define HB_BIT_SET_HAS_COST 8 + void setup_buffer_glyph_set (unsigned subchain_count) + { + // Using buffer_glyph_set has at least two mallocs. Avoid it for small workloads. + unsigned malloced_cost = HB_MALLOC_COST * 2 + subchain_count * HB_BIT_SET_HAS_COST; + unsigned unmalloced_cost = subchain_count * buffer->len; + using_buffer_glyph_set = malloced_cost < unmalloced_cost; + + if (using_buffer_glyph_set) + buffer_glyph_set = buffer->bit_set (); + } + bool buffer_intersects_machine () const + { + if (using_buffer_glyph_set) + return buffer_glyph_set.intersects (*machine_glyph_set); + + // Faster for shorter buffers. + for (unsigned i = 0; i < buffer->len; i++) + if (machine_glyph_set->has (buffer->info[i].codepoint)) + return true; + return false; + } }; diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 9518f7690..a975b79d8 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -177,7 +177,7 @@ struct RearrangementSubtable StateTableDriver driver (machine, c->face); - if (!c->buffer_glyph_set.intersects (*c->machine_glyph_set)) + if (!c->buffer_intersects_machine ()) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -347,7 +347,7 @@ struct ContextualSubtable StateTableDriver driver (machine, c->face); - if (!c->buffer_glyph_set.intersects (*c->machine_glyph_set)) + if (!c->buffer_intersects_machine ()) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -623,7 +623,7 @@ struct LigatureSubtable StateTableDriver driver (machine, c->face); - if (!c->buffer_glyph_set.intersects (*c->machine_glyph_set)) + if (!c->buffer_intersects_machine ()) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -664,8 +664,11 @@ struct NoncontextualSubtable { TRACE_APPLY (this); - if (!c->buffer_glyph_set.intersects (*c->machine_glyph_set)) + if (!c->buffer_intersects_machine ()) + { + (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); + } const OT::GDEF &gdef (*c->gdef_table); bool has_glyph_classes = gdef.has_glyph_classes (); @@ -917,7 +920,7 @@ struct InsertionSubtable StateTableDriver driver (machine, c->face); - if (!c->buffer_glyph_set.intersects (*c->machine_glyph_set)) + if (!c->buffer_intersects_machine ()) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -1371,11 +1374,13 @@ struct mortmorx } this->chain_count = table->get_chain_count (); + this->subchain_count = table->get_subchain_count (); this->accels = (hb_atomic_ptr_t *) hb_calloc (this->chain_count, sizeof (*accels)); if (unlikely (!this->accels)) { this->chain_count = 0; + this->subchain_count = 0; this->table.destroy (); this->table = hb_blob_get_empty (); } @@ -1419,6 +1424,7 @@ struct mortmorx hb_blob_ptr_t table; unsigned int chain_count; + unsigned int subchain_count; hb_atomic_ptr_t *accels; }; @@ -1441,7 +1447,19 @@ struct mortmorx unsigned get_chain_count () const { - return chainCount; + return chainCount; + } + unsigned get_subchain_count () const + { + const Chain *chain = &firstChain; + unsigned int count = chainCount; + unsigned int subchain_count = 0; + for (unsigned int i = 0; i < count; i++) + { + subchain_count += chain->get_subtable_count (); + chain = &StructAfter> (*chain); + } + return subchain_count; } void apply (hb_aat_apply_context_t *c, @@ -1452,7 +1470,7 @@ struct mortmorx c->buffer->unsafe_to_concat (); - c->buffer_glyph_set = c->buffer->bit_set (); + c->setup_buffer_glyph_set (accel.subchain_count); c->set_lookup_index (0); const Chain *chain = &firstChain;