From b8a58a0c0b7d62c33b106ad119a567b6d86d1d36 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Sun, 10 Jan 2021 15:50:04 -0800 Subject: [PATCH] [subset] optimize glyph closure method: step 4 optimize recurse_lookups in Context/ChainContext glyph closure, only the glyphs that the parent lookup can apply the recursion to can participate in recursing the lookup. --- src/hb-ot-layout-gsub-table.hh | 84 +++---------- src/hb-ot-layout-gsubgpos.hh | 219 +++++++++++++++++++++++++-------- 2 files changed, 186 insertions(+), 117 deletions(-) diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 178ba6546..0ea305d6a 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -52,18 +52,9 @@ struct SingleSubstFormat1 void closure (hb_closure_context_t *c) const { unsigned d = deltaGlyphID; - hb_set_t *active_parent_glyphs; - - if (c->active_glyphs_stack.length >= 1) - { - active_parent_glyphs = c->parent_active_glyphs (); - } else - { - active_parent_glyphs = c->glyphs; - } + hb_iter (this+coverage) - | hb_filter (active_parent_glyphs) + | hb_filter (c->parent_active_glyphs ()) | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) | hb_sink (c->output) ; @@ -166,18 +157,8 @@ struct SingleSubstFormat2 void closure (hb_closure_context_t *c) const { - hb_set_t *active_parent_glyphs; - - if (c->active_glyphs_stack.length >= 1) - { - active_parent_glyphs = c->parent_active_glyphs (); - } else - { - active_parent_glyphs = c->glyphs; - } - + hb_zip (this+coverage, substitute) - | hb_filter (active_parent_glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_sink (c->output) ; @@ -421,18 +402,8 @@ struct MultipleSubstFormat1 void closure (hb_closure_context_t *c) const { - hb_set_t *active_parent_glyphs; - - if (c->active_glyphs_stack.length >= 1) - { - active_parent_glyphs = c->parent_active_glyphs (); - } else - { - active_parent_glyphs = c->glyphs; - } - + hb_zip (this+coverage, sequence) - | hb_filter (active_parent_glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const Sequence &_) { _.closure (c); }) @@ -662,18 +633,8 @@ struct AlternateSubstFormat1 void closure (hb_closure_context_t *c) const { - hb_set_t *active_parent_glyphs; - - if (c->active_glyphs_stack.length >= 1) - { - active_parent_glyphs = c->parent_active_glyphs (); - } else - { - active_parent_glyphs = c->glyphs; - } - + hb_zip (this+coverage, alternateSet) - | hb_filter (active_parent_glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) @@ -1047,18 +1008,8 @@ struct LigatureSubstFormat1 void closure (hb_closure_context_t *c) const { - hb_set_t *active_parent_glyphs; - - if (c->active_glyphs_stack.length >= 1) - { - active_parent_glyphs = c->parent_active_glyphs (); - } else - { - active_parent_glyphs = c->glyphs; - } - + hb_zip (this+coverage, ligatureSet) - | hb_filter (active_parent_glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) @@ -1251,20 +1202,11 @@ struct ReverseChainSingleSubstFormat1 { if (!intersects (c->glyphs)) return; - hb_set_t *active_parent_glyphs; - if (c->active_glyphs_stack.length >= 1) - { - active_parent_glyphs = c->parent_active_glyphs (); - } else - { - active_parent_glyphs = c->glyphs; - } - const OffsetArrayOf &lookahead = StructAfter> (backtrack); const ArrayOf &substitute = StructAfter> (lookahead); + hb_zip (this+coverage, substitute) - | hb_filter (active_parent_glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_sink (c->output) ; @@ -1609,13 +1551,15 @@ struct SubstLookup : Lookup template static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); + + static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *chaos, unsigned seq_index, unsigned end_index); - static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) + static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *chaos, unsigned seq_index, unsigned end_index) { if (!c->should_visit_lookup (lookup_index)) return hb_empty_t (); - hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index); + hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, chaos, seq_index, end_index); /* While in theory we should flush here, it will cause timeouts because a recursive * lookup can keep growing the glyph set. Skip, and outer loop will retry up to @@ -1688,6 +1632,14 @@ template return l.dispatch (c); } +/*static*/ typename hb_closure_context_t::return_t SubstLookup::closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *chaos, unsigned seq_index, unsigned end_index) +{ + const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); + if (l.may_have_non_1to1 ()) + hb_set_add_range (chaos, seq_index, end_index); + return l.dispatch (c); +} + /*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index) { const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index); diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index c8f0ff107..9a1ed084b 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -67,17 +67,17 @@ struct hb_have_non_1to1_context_t : struct hb_closure_context_t : hb_dispatch_context_t { - typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); + typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *chaos, unsigned seq_index, unsigned end_index); template return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); } static return_t default_return_value () { return hb_empty_t (); } - void recurse (unsigned int lookup_index) + void recurse (unsigned lookup_index, hb_set_t *chaos, unsigned seq_index, unsigned end_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) return; nesting_level_left--; - recurse_func (this, lookup_index); + recurse_func (this, lookup_index, chaos, seq_index, end_index); nesting_level_left++; } @@ -107,6 +107,9 @@ struct hb_closure_context_t : hb_set_t* parent_active_glyphs () { + if (active_glyphs_stack.length < 1) + return glyphs; + return active_glyphs_stack.tail (); } @@ -770,12 +773,14 @@ struct hb_get_subtables_context_t : typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data); +typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs); typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data); typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data); struct ContextClosureFuncs { intersects_func_t intersects; + intersected_glyphs_func_t intersected_glyphs; }; struct ContextCollectGlyphsFuncs { @@ -802,6 +807,25 @@ static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 & return (data+coverage).intersects (glyphs); } + +static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs) +{ + unsigned g = reinterpret_cast(data)[value]; + intersected_glyphs->add (g); +} +static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs) +{ + const ClassDef &class_def = *reinterpret_cast(data); + class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs); +} +static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs) +{ + OffsetTo coverage; + coverage = value; + (data+coverage).intersected_coverage_glyphs (glyphs, intersected_glyphs); +} + + static inline bool array_is_subset_of (const hb_set_t *glyphs, unsigned int count, const HBUINT16 values[], @@ -1179,18 +1203,82 @@ struct LookupRecord DEFINE_SIZE_STATIC (4); }; -template -static inline void recurse_lookups (context_t *c, - unsigned int lookupCount, - const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) +enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 }; + +static void context_closure_recurse_lookups (hb_closure_context_t *c, + unsigned inputCount, const HBUINT16 input[], + unsigned lookupCount, + const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */, + unsigned value, + ContextFormat context_format, + const void *data, + intersected_glyphs_func_t intersected_glyphs_func) { + printf ("qxliu_1\n"); hb_set_t *chaos = hb_set_create (); + for (unsigned int i = 0; i < lookupCount; i++) - c->recurse (lookupRecord[i].lookupListIndex); + { + unsigned seqIndex = lookupRecord[i].sequenceIndex; + if (seqIndex > inputCount) continue; + + hb_set_t *pos_glyphs = hb_set_create (); + + if (hb_set_is_empty (chaos) || !hb_set_has (chaos, seqIndex)) + { + if (seqIndex == 0) + { + switch (context_format) { + case ContextFormat::SimpleContext: + pos_glyphs->add (value); + break; + case ContextFormat::ClassBasedContext: + intersected_glyphs_func (c->parent_active_glyphs (), data, value, pos_glyphs); + break; + case ContextFormat::CoverageBasedContext: + hb_set_set (pos_glyphs, c->parent_active_glyphs ()); + break; + } + } + else + { + const void *input_data = input; + unsigned input_value = seqIndex - 1; + if (context_format == ContextFormat::ClassBasedContext) + { + input_data = data; + input_value = input[seqIndex - 1]; + } + + intersected_glyphs_func (c->parent_active_glyphs (), input_data, input_value, pos_glyphs); + } + } + + hb_set_add (chaos, seqIndex); + c->push_cur_active_glyphs (pos_glyphs); + + unsigned endIndex = inputCount; + if (context_format == ContextFormat::CoverageBasedContext) + endIndex += 1; + + c->recurse (lookupRecord[i].lookupListIndex, chaos, seqIndex, endIndex); + + c->pop_cur_done_glyphs (); + hb_set_destroy (pos_glyphs); + } hb_set_destroy (chaos); } +template +static inline void recurse_lookups (context_t *c, + unsigned int lookupCount, + const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) +{ + for (unsigned int i = 0; i < lookupCount; i++) + c->recurse (lookupRecord[i].lookupListIndex); +} + static inline bool apply_lookup (hb_ot_apply_context_t *c, unsigned int count, /* Including the first glyph */ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */ @@ -1320,6 +1408,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, struct ContextClosureLookupContext { ContextClosureFuncs funcs; + ContextFormat context_format; const void *intersects_data; }; @@ -1350,13 +1439,19 @@ static inline void context_closure_lookup (hb_closure_context_t *c, const HBUINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], + unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */ ContextClosureLookupContext &lookup_context) { if (context_intersects (c->glyphs, inputCount, input, lookup_context)) - recurse_lookups (c, - lookupCount, lookupRecord); + context_closure_recurse_lookups (c, + inputCount, input, + lookupCount, lookupRecord, + value, + lookup_context.context_format, + lookup_context.intersects_data, + lookup_context.funcs.intersected_glyphs); } static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, @@ -1413,7 +1508,7 @@ struct Rule lookup_context); } - void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const + void closure (hb_closure_context_t *c, unsigned value, ContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; @@ -1422,7 +1517,7 @@ struct Rule context_closure_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, - lookup_context); + value, lookup_context); } void closure_lookups (hb_closure_lookups_context_t *c, @@ -1547,7 +1642,7 @@ struct RuleSet ; } - void closure (hb_closure_context_t *c, + void closure (hb_closure_context_t *c, unsigned value, ContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; @@ -1555,7 +1650,7 @@ struct RuleSet return + hb_iter (rule) | hb_map (hb_add (this)) - | hb_apply ([&] (const Rule &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const Rule &_) { _.closure (c, value, lookup_context); }) ; } @@ -1653,7 +1748,8 @@ struct ContextFormat1 bool intersects (const hb_set_t *glyphs) const { struct ContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, nullptr }; @@ -1673,15 +1769,15 @@ struct ContextFormat1 void closure (hb_closure_context_t *c) const { struct ContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, nullptr }; - + hb_zip (this+coverage, ruleSet) - | hb_filter (*c->glyphs, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); }) + + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) + | hb_filter (c->parent_active_glyphs (), hb_first) + | hb_map ([&](const hb_pair_t _) { return hb_pair_t (_.first, this+ruleSet[_.second]); }) + | hb_apply ([&] (const hb_pair_t& _) { _.second.closure (c, _.first, lookup_context); }) ; } @@ -1798,7 +1894,8 @@ struct ContextFormat2 const ClassDef &class_def = this+classDef; struct ContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, &class_def }; @@ -1824,18 +1921,21 @@ struct ContextFormat2 const ClassDef &class_def = this+classDef; struct ContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, &class_def }; return + hb_enumerate (ruleSet) | hb_filter ([&] (unsigned _) - { return class_def.intersects_class (c->glyphs, _); }, + { return class_def.intersects_class (c->parent_active_glyphs (), _); }, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const hb_pair_t&> _) + { + const RuleSet& rule_set = this+_.second; + rule_set.closure (c, _.first, lookup_context); + }) ; } @@ -1983,7 +2083,8 @@ struct ContextFormat3 return false; struct ContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, this }; return context_intersects (glyphs, @@ -2001,13 +2102,14 @@ struct ContextFormat3 const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount)); struct ContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, this }; context_closure_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, - lookup_context); + 0, lookup_context); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -2151,6 +2253,7 @@ struct Context struct ChainContextClosureLookupContext { ContextClosureFuncs funcs; + ContextFormat context_format; const void *intersects_data[3]; }; @@ -2195,6 +2298,7 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, const HBUINT16 lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], + unsigned value, ChainContextClosureLookupContext &lookup_context) { if (chain_context_intersects (c->glyphs, @@ -2202,8 +2306,13 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, inputCount, input, lookaheadCount, lookahead, lookup_context)) - recurse_lookups (c, - lookupCount, lookupRecord); + context_closure_recurse_lookups (c, + inputCount, input, + lookupCount, lookupRecord, + value, + lookup_context.context_format, + lookup_context.intersects_data[1], + lookup_context.funcs.intersected_glyphs); } static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, @@ -2292,7 +2401,7 @@ struct ChainRule lookup_context); } - void closure (hb_closure_context_t *c, + void closure (hb_closure_context_t *c, unsigned value, ChainContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; @@ -2305,6 +2414,7 @@ struct ChainRule input.lenP1, input.arrayZ, lookahead.len, lookahead.arrayZ, lookup.len, lookup.arrayZ, + value, lookup_context); } @@ -2488,14 +2598,14 @@ struct ChainRuleSet | hb_any ; } - void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const + void closure (hb_closure_context_t *c, unsigned value, ChainContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; return + hb_iter (rule) | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRule &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const ChainRule &_) { _.closure (c, value, lookup_context); }) ; } @@ -2596,7 +2706,8 @@ struct ChainContextFormat1 bool intersects (const hb_set_t *glyphs) const { struct ChainContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, {nullptr, nullptr, nullptr} }; @@ -2616,15 +2727,15 @@ struct ChainContextFormat1 void closure (hb_closure_context_t *c) const { struct ChainContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, {nullptr, nullptr, nullptr} }; - + hb_zip (this+coverage, ruleSet) - | hb_filter (*c->glyphs, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); }) + + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) + | hb_filter (c->parent_active_glyphs (), hb_first) + | hb_map ([&](const hb_pair_t _) { return hb_pair_t (_.first, this+ruleSet[_.second]); }) + | hb_apply ([&] (const hb_pair_t& _) { _.second.closure (c, _.first, lookup_context); }) ; } @@ -2741,7 +2852,8 @@ struct ChainContextFormat2 const ClassDef &lookahead_class_def = this+lookaheadClassDef; struct ChainContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, &lookahead_class_def} @@ -2771,7 +2883,8 @@ struct ChainContextFormat2 const ClassDef &lookahead_class_def = this+lookaheadClassDef; struct ChainContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, &lookahead_class_def} @@ -2780,11 +2893,13 @@ struct ChainContextFormat2 return + hb_enumerate (ruleSet) | hb_filter ([&] (unsigned _) - { return input_class_def.intersects_class (c->glyphs, _); }, + { return input_class_def.intersects_class (c->parent_active_glyphs (), _); }, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const hb_pair_t&> _) + { + const ChainRuleSet& chainrule_set = this+_.second; + chainrule_set.closure (c, _.first, lookup_context); + }) ; } @@ -2983,7 +3098,8 @@ struct ChainContextFormat3 const OffsetArrayOf &lookahead = StructAfter> (input); struct ChainContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, {this, this, this} }; return chain_context_intersects (glyphs, @@ -3006,7 +3122,8 @@ struct ChainContextFormat3 const OffsetArrayOf &lookahead = StructAfter> (input); const ArrayOf &lookup = StructAfter> (lookahead); struct ChainContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, {this, this, this} }; chain_context_closure_lookup (c, @@ -3014,7 +3131,7 @@ struct ChainContextFormat3 input.len, (const HBUINT16 *) input.arrayZ + 1, lookahead.len, (const HBUINT16 *) lookahead.arrayZ, lookup.len, lookup.arrayZ, - lookup_context); + 0, lookup_context); } void closure_lookups (hb_closure_lookups_context_t *c) const