diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 7d49710d1..7f3e32867 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -737,7 +737,8 @@ struct hb_ot_apply_context_t : hb_ot_apply_context_t (unsigned int table_index_, hb_font_t *font_, hb_buffer_t *buffer_, - hb_blob_t *table_blob_) : + hb_blob_t *table_blob_, + ItemVariationStore::cache_t *var_store_cache_ = nullptr) : table_index (table_index_), font (font_), face (font->face), buffer (buffer_), sanitizer (table_blob_), @@ -756,13 +757,7 @@ struct hb_ot_apply_context_t : #endif ), var_store (gdef.get_var_store ()), - var_store_cache ( -#ifndef HB_NO_VAR - table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr -#else - nullptr -#endif - ), + var_store_cache (var_store_cache_), direction (buffer_->props.direction), has_glyph_classes (gdef.has_glyph_classes ()) { @@ -770,13 +765,6 @@ struct hb_ot_apply_context_t : buffer->collect_codepoints (digest); } - ~hb_ot_apply_context_t () - { -#ifndef HB_NO_VAR - ItemVariationStore::destroy_cache (var_store_cache); -#endif - } - void init_iters () { iter_input.init (this, false); @@ -4946,9 +4934,54 @@ struct GSUBGPOS return accel; } + void check_serial (hb_font_t *font) const + { + int font_serial = font->serial_coords.get_acquire (); + if (likely (font_serial == coords_serial.get_acquire ())) + return; + + retry: + ItemVariationStore::cache_t *cache = var_store_cache.get_acquire (); + if (cache) + { + if (var_store_cache.cmpexch (cache, nullptr)) + ItemVariationStore::destroy_cache (cache); + else + goto retry; + } + + coords_serial.set_release (font_serial); + } + ItemVariationStore::cache_t *acquire_var_store_cache (hb_font_t *font) const + { + const OT::ItemVariationStore &var_store = font->face->table.GDEF->table->get_var_store (); + + check_serial (font); + + retry: + ItemVariationStore::cache_t *cache = var_store_cache.get_acquire (); + if (unlikely (!cache)) + return var_store.create_cache (); + + if (var_store_cache.cmpexch (cache, nullptr)) + return cache; + else + goto retry; + } + void release_var_store_cache (ItemVariationStore::cache_t *cache) const + { + if (!cache) return; + if (var_store_cache.cmpexch (nullptr, cache)) + return; + ItemVariationStore::destroy_cache (cache); + } + hb_blob_ptr_t table; unsigned int lookup_count; hb_atomic_t *accels; + + mutable hb_atomic_t coords_serial; + mutable hb_atomic_t var_store_cache; }; protected: diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 3aca40eb7..7f7cc14fe 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -2015,7 +2015,12 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, { const unsigned int table_index = proxy.table_index; unsigned int i = 0; - OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob ()); + + OT::ItemVariationStore::cache_t *var_store_cache = nullptr; + if (proxy.table_index == 1 && font->num_coords) + var_store_cache = proxy.accel.acquire_var_store_cache (font); + + OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob (), var_store_cache); c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func); for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) @@ -2067,6 +2072,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, } } } + + proxy.accel.release_var_store_cache (var_store_cache); } void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const