From 630b874ae6f54d7c1705ec1c16599d476b8c1c69 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 3 Dec 2022 12:13:15 -0700 Subject: [PATCH] [gsubgpos] Add a cache to intersected_class_glyphs 30% gain on subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/1400. --- src/hb-ot-layout-gsubgpos.hh | 72 +++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 0246d80e4..04ccefd10 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -1003,7 +1003,7 @@ struct hb_accelerate_subtables_context_t : typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data, void *cache); -typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs); +typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache); typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data); typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data); @@ -1052,17 +1052,36 @@ static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, } -static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs) +static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache) { 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) + +using intersected_class_cache_t = hb_hashmap_t; + +static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache) { const ClassDef &class_def = *reinterpret_cast(data); - class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs); + + intersected_class_cache_t *map = (intersected_class_cache_t *) cache; + + hb_set_t *cached_v; + if (map->has (value, &cached_v)) + { + intersected_glyphs->union_ (*cached_v); + return; + } + + hb_set_t v; + class_def.intersected_class_glyphs (glyphs, value, &v); + + intersected_glyphs->union_ (v); + + map->set (value, std::move (v)); } -static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs) + +static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache) { Offset16To coverage; coverage = value; @@ -1516,7 +1535,8 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, unsigned value, ContextFormat context_format, const void *data, - intersected_glyphs_func_t intersected_glyphs_func) + intersected_glyphs_func_t intersected_glyphs_func, + void *cache) { hb_set_t *covered_seq_indicies = hb_set_create (); for (unsigned int i = 0; i < lookupCount; i++) @@ -1537,7 +1557,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, pos_glyphs.add (value); break; case ContextFormat::ClassBasedContext: - intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs); + intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache); break; case ContextFormat::CoverageBasedContext: pos_glyphs.set (c->parent_active_glyphs ()); @@ -1554,7 +1574,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, input_value = input[seqIndex - 1]; } - intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs); + intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache); } } @@ -1734,7 +1754,8 @@ struct ContextClosureLookupContext ContextClosureFuncs funcs; ContextFormat context_format; const void *intersects_data; - void *cache; + void *intersects_cache; + void *intersected_glyphs_cache; }; struct ContextCollectGlyphsLookupContext @@ -1757,7 +1778,9 @@ static inline bool context_intersects (const hb_set_t *glyphs, { return array_is_subset_of (glyphs, inputCount ? inputCount - 1 : 0, input, - lookup_context.funcs.intersects, lookup_context.intersects_data, lookup_context.cache); + lookup_context.funcs.intersects, + lookup_context.intersects_data, + lookup_context.intersects_cache); } template @@ -1778,7 +1801,8 @@ static inline void context_closure_lookup (hb_closure_context_t *c, value, lookup_context.context_format, lookup_context.intersects_data, - lookup_context.funcs.intersected_glyphs); + lookup_context.funcs.intersected_glyphs, + lookup_context.intersected_glyphs_cache); } template @@ -2287,11 +2311,13 @@ struct ContextFormat2_5 const ClassDef &class_def = this+classDef; hb_map_t cache; + intersected_class_cache_t intersected_cache; struct ContextClosureLookupContext lookup_context = { {intersects_class, intersected_class_glyphs}, ContextFormat::ClassBasedContext, &class_def, - &cache + &cache, + &intersected_cache }; + hb_enumerate (ruleSet) @@ -2690,7 +2716,8 @@ struct ChainContextClosureLookupContext ContextClosureFuncs funcs; ContextFormat context_format; const void *intersects_data[3]; - void *cache[3]; + void *intersects_cache[3]; + void *intersected_glyphs_cache; }; struct ChainContextCollectGlyphsLookupContext @@ -2717,13 +2744,19 @@ static inline bool chain_context_intersects (const hb_set_t *glyphs, { return array_is_subset_of (glyphs, backtrackCount, backtrack, - lookup_context.funcs.intersects, lookup_context.intersects_data[0], lookup_context.cache[0]) + lookup_context.funcs.intersects, + lookup_context.intersects_data[0], + lookup_context.intersects_cache[0]) && array_is_subset_of (glyphs, inputCount ? inputCount - 1 : 0, input, - lookup_context.funcs.intersects, lookup_context.intersects_data[1], lookup_context.cache[1]) + lookup_context.funcs.intersects, + lookup_context.intersects_data[1], + lookup_context.intersects_cache[1]) && array_is_subset_of (glyphs, lookaheadCount, lookahead, - lookup_context.funcs.intersects, lookup_context.intersects_data[2], lookup_context.cache[2]); + lookup_context.funcs.intersects, + lookup_context.intersects_data[2], + lookup_context.intersects_cache[2]); } template @@ -2750,7 +2783,8 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, value, lookup_context.context_format, lookup_context.intersects_data[1], - lookup_context.funcs.intersected_glyphs); + lookup_context.funcs.intersected_glyphs, + lookup_context.intersected_glyphs_cache); } template @@ -3363,13 +3397,15 @@ struct ChainContextFormat2_5 const ClassDef &lookahead_class_def = this+lookaheadClassDef; hb_map_t caches[3] = {}; + intersected_class_cache_t intersected_cache; struct ChainContextClosureLookupContext lookup_context = { {intersects_class, intersected_class_glyphs}, ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, &lookahead_class_def}, - {&caches[0], &caches[1], &caches[2]} + {&caches[0], &caches[1], &caches[2]}, + &intersected_cache }; + hb_enumerate (ruleSet)