From 5fbc70c59b2d867e2142dba821802e2f26237c81 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 May 2022 14:07:27 -0600 Subject: [PATCH 1/9] [VarStore] Add cache API --- src/hb-ot-layout-common.hh | 67 ++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index b644df708..577cf634d 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2604,11 +2604,22 @@ struct VarRegionAxis struct VarRegionList { float evaluate (unsigned int region_index, - const int *coords, unsigned int coord_len) const + const int *coords, unsigned int coord_len, + hb_vector_t *cache = nullptr) const { if (unlikely (region_index >= regionCount)) return 0.; + float *cached = nullptr; + if (cache) + { + cached = &((*cache)[region_index]); + if (!std::isnan (*cached)) + { + return *cached; + } + } + const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount); float v = 1.; @@ -2618,9 +2629,15 @@ struct VarRegionList int coord = i < coord_len ? coords[i] : 0; float factor = axes[i].evaluate (coord); if (factor == 0.f) + { + if (cached) + *cached = 0.; return 0.; + } v *= factor; } + if (cached) + *cached = v; return v; } @@ -2678,7 +2695,8 @@ struct VarData float get_delta (unsigned int inner, const int *coords, unsigned int coord_count, - const VarRegionList ®ions) const + const VarRegionList ®ions, + hb_vector_t *regions_cache = nullptr) const { if (unlikely (inner >= itemCount)) return 0.; @@ -2695,13 +2713,13 @@ struct VarData const HBINT16 *scursor = reinterpret_cast (row); for (; i < scount; i++) { - float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count); + float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, regions_cache); delta += scalar * *scursor++; } const HBINT8 *bcursor = reinterpret_cast (scursor); for (; i < count; i++) { - float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count); + float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, regions_cache); delta += scalar * *bcursor++; } @@ -2848,7 +2866,8 @@ struct VariationStore { private: float get_delta (unsigned int outer, unsigned int inner, - const int *coords, unsigned int coord_count) const + const int *coords, unsigned int coord_count, + hb_vector_t *regions_cache = nullptr) const { #ifdef HB_NO_VAR return 0.f; @@ -2859,16 +2878,18 @@ struct VariationStore return (this+dataSets[outer]).get_delta (inner, coords, coord_count, - this+regions); + this+regions, + regions_cache); } public: float get_delta (unsigned int index, - const int *coords, unsigned int coord_count) const + const int *coords, unsigned int coord_count, + hb_vector_t *regions_cache = nullptr) const { unsigned int outer = index >> 16; unsigned int inner = index & 0xFFFF; - return get_delta (outer, inner, coords, coord_count); + return get_delta (outer, inner, coords, coord_count, regions_cache); } bool sanitize (hb_sanitize_context_t *c) const @@ -3462,11 +3483,15 @@ struct VariationDevice private: - hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const - { return font->em_scalef_x (get_delta (font, store)); } + hb_position_t get_x_delta (hb_font_t *font, + const VariationStore &store, + hb_vector_t *regions_cache = nullptr) const + { return font->em_scalef_x (get_delta (font, store, regions_cache)); } - hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const - { return font->em_scalef_y (get_delta (font, store)); } + hb_position_t get_y_delta (hb_font_t *font, + const VariationStore &store, + hb_vector_t *regions_cache = nullptr) const + { return font->em_scalef_y (get_delta (font, store, regions_cache)); } VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const { @@ -3500,9 +3525,11 @@ struct VariationDevice private: - float get_delta (hb_font_t *font, const VariationStore &store) const + float get_delta (hb_font_t *font, + const VariationStore &store, + hb_vector_t *regions_cache = nullptr) const { - return store.get_delta (varIdx, font->coords, font->num_coords); + return store.get_delta (varIdx, font->coords, font->num_coords, regions_cache); } protected: @@ -3525,7 +3552,9 @@ struct DeviceHeader struct Device { - hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const + hb_position_t get_x_delta (hb_font_t *font, + const VariationStore &store=Null (VariationStore), + hb_vector_t *regions_cache = nullptr) const { switch (u.b.format) { @@ -3535,13 +3564,15 @@ struct Device #endif #ifndef HB_NO_VAR case 0x8000: - return u.variation.get_x_delta (font, store); + return u.variation.get_x_delta (font, store, regions_cache); #endif default: return 0; } } - hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const + hb_position_t get_y_delta (hb_font_t *font, + const VariationStore &store=Null (VariationStore), + hb_vector_t *regions_cache = nullptr) const { switch (u.b.format) { @@ -3551,7 +3582,7 @@ struct Device #endif #ifndef HB_NO_VAR case 0x8000: - return u.variation.get_y_delta (font, store); + return u.variation.get_y_delta (font, store, regions_cache); #endif default: return 0; From f2a2fb91a34cde23448eadd11a0fbc294153fcf5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 May 2022 16:06:05 -0600 Subject: [PATCH 2/9] [GPOS] Cache VarStore region scalars --- src/hb-ot-layout-common.hh | 2 ++ src/hb-ot-layout-gpos-table.hh | 13 +++++++------ src/hb-ot-layout-gsubgpos.hh | 12 +++++++++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 577cf634d..cdcffd424 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -3010,7 +3010,9 @@ struct VariationStore protected: HBUINT16 format; + public: Offset32To regions; + protected: Array16OfOffset32To dataSets; public: DEFINE_SIZE_ARRAY_SIZED (8, dataSets); diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 2f9186a2a..4d1872493 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -146,23 +146,24 @@ struct ValueFormat : HBUINT16 if (!use_x_device && !use_y_device) return ret; const VariationStore &store = c->var_store; + auto *cache = &c->regions_cache; /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store); + if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache); values++; } if (format & yPlaDevice) { - if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store); + if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache); values++; } if (format & xAdvDevice) { - if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store); + if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache); values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store); + if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache); values++; } return ret; @@ -465,9 +466,9 @@ struct AnchorFormat3 *y = font->em_fscale_y (yCoordinate); if (font->x_ppem || font->num_coords) - *x += (this+xDeviceTable).get_x_delta (font, c->var_store); + *x += (this+xDeviceTable).get_x_delta (font, c->var_store, &c->regions_cache); if (font->y_ppem || font->num_coords) - *y += (this+yDeviceTable).get_y_delta (font, c->var_store); + *y += (this+yDeviceTable).get_y_delta (font, c->var_store, &c->regions_cache); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index c9750ff63..74922b3da 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -627,6 +627,7 @@ struct hb_ot_apply_context_t : recurse_func_t recurse_func; const GDEF &gdef; const VariationStore &var_store; + hb_vector_t regions_cache; hb_direction_t direction; hb_mask_t lookup_mask; @@ -669,7 +670,16 @@ struct hb_ot_apply_context_t : auto_zwj (true), per_syllable (false), random (false), - random_state (1) { init_iters (); } + random_state (1) + { + init_iters (); + if (table_index == 1 && font->num_coords) /* GPOS */ + { + regions_cache.resize ((&var_store+var_store.regions).regionCount); + for (auto &f : regions_cache.writer ()) + f = NAN; + } + } void init_iters () { From 880f50f7e423858209c490acab13328ca475a89c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 May 2022 16:50:00 -0600 Subject: [PATCH 3/9] Refactor varstore cache --- src/hb-ot-layout-common.hh | 63 +++++++++++++++++++++------------- src/hb-ot-layout-gpos-table.hh | 6 ++-- src/hb-ot-layout-gsubgpos.hh | 19 ++++------ 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index cdcffd424..e4f3e06f7 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2603,9 +2603,11 @@ struct VarRegionAxis struct VarRegionList { + using cache_t = float; + float evaluate (unsigned int region_index, const int *coords, unsigned int coord_len, - hb_vector_t *cache = nullptr) const + cache_t *cache = nullptr) const { if (unlikely (region_index >= regionCount)) return 0.; @@ -2613,11 +2615,9 @@ struct VarRegionList float *cached = nullptr; if (cache) { - cached = &((*cache)[region_index]); + cached = &(cache[region_index]); if (!std::isnan (*cached)) - { return *cached; - } } const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount); @@ -2636,6 +2636,7 @@ struct VarRegionList } v *= factor; } + if (cached) *cached = v; return v; @@ -2696,7 +2697,7 @@ struct VarData float get_delta (unsigned int inner, const int *coords, unsigned int coord_count, const VarRegionList ®ions, - hb_vector_t *regions_cache = nullptr) const + VarRegionList::cache_t *cache = nullptr) const { if (unlikely (inner >= itemCount)) return 0.; @@ -2713,13 +2714,13 @@ struct VarData const HBINT16 *scursor = reinterpret_cast (row); for (; i < scount; i++) { - float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, regions_cache); + float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache); delta += scalar * *scursor++; } const HBINT8 *bcursor = reinterpret_cast (scursor); for (; i < count; i++) { - float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, regions_cache); + float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache); delta += scalar * *bcursor++; } @@ -2864,10 +2865,28 @@ struct VarData struct VariationStore { + using cache_t = VarRegionList::cache_t; + + cache_t *create_cache () const + { + auto &r = this+regions; + unsigned count = r.regionCount; + + float *cache = (float *) hb_malloc (sizeof (float) * count); + if (unlikely (!cache)) return nullptr; + + for (unsigned i = 0; i < count; i++) + cache[i] = NAN; + + return cache; + } + + static void destroy_cache (cache_t *cache) { hb_free (cache); } + private: float get_delta (unsigned int outer, unsigned int inner, const int *coords, unsigned int coord_count, - hb_vector_t *regions_cache = nullptr) const + VarRegionList::cache_t *cache = nullptr) const { #ifdef HB_NO_VAR return 0.f; @@ -2879,17 +2898,17 @@ struct VariationStore return (this+dataSets[outer]).get_delta (inner, coords, coord_count, this+regions, - regions_cache); + cache); } public: float get_delta (unsigned int index, const int *coords, unsigned int coord_count, - hb_vector_t *regions_cache = nullptr) const + VarRegionList::cache_t *cache = nullptr) const { unsigned int outer = index >> 16; unsigned int inner = index & 0xFFFF; - return get_delta (outer, inner, coords, coord_count, regions_cache); + return get_delta (outer, inner, coords, coord_count, cache); } bool sanitize (hb_sanitize_context_t *c) const @@ -3010,9 +3029,7 @@ struct VariationStore protected: HBUINT16 format; - public: Offset32To regions; - protected: Array16OfOffset32To dataSets; public: DEFINE_SIZE_ARRAY_SIZED (8, dataSets); @@ -3487,13 +3504,13 @@ struct VariationDevice hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store, - hb_vector_t *regions_cache = nullptr) const - { return font->em_scalef_x (get_delta (font, store, regions_cache)); } + void *store_cache = nullptr) const + { return font->em_scalef_x (get_delta (font, store, store_cache)); } hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store, - hb_vector_t *regions_cache = nullptr) const - { return font->em_scalef_y (get_delta (font, store, regions_cache)); } + void *store_cache = nullptr) const + { return font->em_scalef_y (get_delta (font, store, store_cache)); } VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const { @@ -3529,9 +3546,9 @@ struct VariationDevice float get_delta (hb_font_t *font, const VariationStore &store, - hb_vector_t *regions_cache = nullptr) const + void *store_cache = nullptr) const { - return store.get_delta (varIdx, font->coords, font->num_coords, regions_cache); + return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache); } protected: @@ -3556,7 +3573,7 @@ struct Device { hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore), - hb_vector_t *regions_cache = nullptr) const + void *store_cache = nullptr) const { switch (u.b.format) { @@ -3566,7 +3583,7 @@ struct Device #endif #ifndef HB_NO_VAR case 0x8000: - return u.variation.get_x_delta (font, store, regions_cache); + return u.variation.get_x_delta (font, store, store_cache); #endif default: return 0; @@ -3574,7 +3591,7 @@ struct Device } hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore), - hb_vector_t *regions_cache = nullptr) const + void *store_cache = nullptr) const { switch (u.b.format) { @@ -3584,7 +3601,7 @@ struct Device #endif #ifndef HB_NO_VAR case 0x8000: - return u.variation.get_y_delta (font, store, regions_cache); + return u.variation.get_y_delta (font, store, store_cache); #endif default: return 0; diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 4d1872493..0dbfa016a 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -146,7 +146,7 @@ struct ValueFormat : HBUINT16 if (!use_x_device && !use_y_device) return ret; const VariationStore &store = c->var_store; - auto *cache = &c->regions_cache; + auto *cache = c->var_store_cache; /* pixel -> fractional pixel */ if (format & xPlaDevice) { @@ -466,9 +466,9 @@ struct AnchorFormat3 *y = font->em_fscale_y (yCoordinate); if (font->x_ppem || font->num_coords) - *x += (this+xDeviceTable).get_x_delta (font, c->var_store, &c->regions_cache); + *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache); if (font->y_ppem || font->num_coords) - *y += (this+yDeviceTable).get_y_delta (font, c->var_store, &c->regions_cache); + *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 74922b3da..c2e043a60 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -621,17 +621,17 @@ struct hb_ot_apply_context_t : skipping_iterator_t iter_input, iter_context; + unsigned int table_index; /* GSUB/GPOS */ hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; recurse_func_t recurse_func; const GDEF &gdef; const VariationStore &var_store; - hb_vector_t regions_cache; + VariationStore::cache_t *var_store_cache; hb_direction_t direction; hb_mask_t lookup_mask; - unsigned int table_index; /* GSUB/GPOS */ unsigned int lookup_index; unsigned int lookup_props; unsigned int nesting_level_left; @@ -649,6 +649,7 @@ struct hb_ot_apply_context_t : hb_font_t *font_, hb_buffer_t *buffer_) : iter_input (), iter_context (), + table_index (table_index_), font (font_), face (font->face), buffer (buffer_), recurse_func (nullptr), gdef ( @@ -659,9 +660,9 @@ struct hb_ot_apply_context_t : #endif ), var_store (gdef.get_var_store ()), + var_store_cache (table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr), direction (buffer_->props.direction), lookup_mask (1), - table_index (table_index_), lookup_index ((unsigned int) -1), lookup_props (0), nesting_level_left (HB_MAX_NESTING_LEVEL), @@ -671,15 +672,9 @@ struct hb_ot_apply_context_t : per_syllable (false), random (false), random_state (1) - { - init_iters (); - if (table_index == 1 && font->num_coords) /* GPOS */ - { - regions_cache.resize ((&var_store+var_store.regions).regionCount); - for (auto &f : regions_cache.writer ()) - f = NAN; - } - } + { init_iters (); } + + ~hb_ot_apply_context_t () { VariationStore::destroy_cache (var_store_cache); } void init_iters () { From 5336ba70f6fc995858881c2e4339e035b16c70a0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 May 2022 17:03:18 -0600 Subject: [PATCH 4/9] [HVAR] Cache VarStore region scalars --- src/hb-ot-font.cc | 8 +++++++- src/hb-ot-hmtx-table.hh | 9 +++++---- src/hb-ot-var-hvar-table.hh | 11 ++++++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 0f44ee4d5..ef4115a8d 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -110,12 +110,18 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; + const OT::HVARVVAR &HVAR = *hmtx.var_table; + const OT::VariationStore &varStore = &HVAR + HVAR.varStore; + OT::VariationStore::cache_t *cache = font->num_coords ? varStore.create_cache () : nullptr; + for (unsigned int i = 0; i < count; i++) { - *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font)); + *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, cache)); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } + + OT::VariationStore::destroy_cache (cache); } #ifndef HB_NO_VERTICAL diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index d5e1fc91d..d0e46e0b0 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -242,7 +242,7 @@ struct hmtxvmtx return side_bearing; if (var_table.get_length ()) - return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?! + return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); #else @@ -284,7 +284,8 @@ struct hmtxvmtx } unsigned int get_advance (hb_codepoint_t glyph, - hb_font_t *font) const + hb_font_t *font, + VariationStore::cache_t *store_cache = nullptr) const { unsigned int advance = get_advance (glyph); @@ -293,7 +294,7 @@ struct hmtxvmtx return advance; if (var_table.get_length ()) - return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?! + return advance + roundf (var_table->get_advance_var (glyph, font, store_cache)); // TODO Optimize?! return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); #else @@ -310,7 +311,7 @@ struct hmtxvmtx unsigned int default_advance; - private: + public: hb_blob_ptr_t table; hb_blob_ptr_t var_table; }; diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh index e9d90352f..56efcdbee 100644 --- a/src/hb-ot-var-hvar-table.hh +++ b/src/hb-ot-var-hvar-table.hh @@ -319,10 +319,15 @@ struct HVARVVAR hvar_plan.index_map_plans.as_array ())); } - float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const + float get_advance_var (hb_codepoint_t glyph, + hb_font_t *font, + VariationStore::cache_t *store_cache = nullptr) const { uint32_t varidx = (this+advMap).map (glyph); - return (this+varStore).get_delta (varidx, font->coords, font->num_coords); + return (this+varStore).get_delta (varidx, + font->coords, + font->num_coords, + store_cache); } float get_side_bearing_var (hb_codepoint_t glyph, @@ -335,7 +340,7 @@ struct HVARVVAR bool has_side_bearing_deltas () const { return lsbMap && rsbMap; } - protected: + public: FixedVersion<>version; /* Version of the metrics variation table * initially set to 0x00010000u */ Offset32To From cf8f00e3548c4e4eb8dca7da598bfe9990b53dd3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 May 2022 17:14:10 -0600 Subject: [PATCH 5/9] [VarStore] Don't use NAN Is faster. With this, I'm seeing 25 to 28% speedup in glyph_h_advances benchmark of benchmark-font for var/hb tests. --- src/hb-ot-layout-common.hh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index e4f3e06f7..61d0cf14f 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2601,6 +2601,8 @@ struct VarRegionAxis DEFINE_SIZE_STATIC (6); }; +#define REGION_CACHE_ITEM_CACHE_INVALID 2.f + struct VarRegionList { using cache_t = float; @@ -2616,7 +2618,7 @@ struct VarRegionList if (cache) { cached = &(cache[region_index]); - if (!std::isnan (*cached)) + if (*cached != REGION_CACHE_ITEM_CACHE_INVALID) return *cached; } @@ -2875,8 +2877,10 @@ struct VariationStore float *cache = (float *) hb_malloc (sizeof (float) * count); if (unlikely (!cache)) return nullptr; + for (unsigned i = 0; i < count; i++) - cache[i] = NAN; + cache[i] = REGION_CACHE_ITEM_CACHE_INVALID; + return cache; } @@ -3035,6 +3039,8 @@ struct VariationStore DEFINE_SIZE_ARRAY_SIZED (8, dataSets); }; +#undef REGION_CACHE_ITEM_CACHE_INVALID + /* * Feature Variations */ From da38312e4201185621b440faf8faf57084a38e7f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 May 2022 17:32:56 -0600 Subject: [PATCH 6/9] [VarStore] Pepper cache with likely() --- src/hb-ot-layout-common.hh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 61d0cf14f..203822d7c 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2618,7 +2618,7 @@ struct VarRegionList if (cache) { cached = &(cache[region_index]); - if (*cached != REGION_CACHE_ITEM_CACHE_INVALID) + if (likely (*cached != REGION_CACHE_ITEM_CACHE_INVALID)) return *cached; } @@ -2632,14 +2632,14 @@ struct VarRegionList float factor = axes[i].evaluate (coord); if (factor == 0.f) { - if (cached) + if (cache) *cached = 0.; return 0.; } v *= factor; } - if (cached) + if (cache) *cached = v; return v; } @@ -2877,11 +2877,9 @@ struct VariationStore float *cache = (float *) hb_malloc (sizeof (float) * count); if (unlikely (!cache)) return nullptr; - for (unsigned i = 0; i < count; i++) cache[i] = REGION_CACHE_ITEM_CACHE_INVALID; - return cache; } From d9acc045f1651db5ffb42fe38ff2e2895199be87 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 May 2022 14:16:21 -0600 Subject: [PATCH 7/9] [VarStore] Sprinkle cache_t type around It's available so no need to use void*. --- src/hb-ot-layout-common.hh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 203822d7c..3e061b7c6 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -3508,12 +3508,12 @@ struct VariationDevice hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store, - void *store_cache = nullptr) const + VariationStore::cache_t *store_cache = nullptr) const { return font->em_scalef_x (get_delta (font, store, store_cache)); } hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store, - void *store_cache = nullptr) const + VariationStore::cache_t *store_cache = nullptr) const { return font->em_scalef_y (get_delta (font, store, store_cache)); } VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const @@ -3550,7 +3550,7 @@ struct VariationDevice float get_delta (hb_font_t *font, const VariationStore &store, - void *store_cache = nullptr) const + VariationStore::cache_t *store_cache = nullptr) const { return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache); } @@ -3577,7 +3577,7 @@ struct Device { hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore), - void *store_cache = nullptr) const + VariationStore::cache_t *store_cache = nullptr) const { switch (u.b.format) { @@ -3595,7 +3595,7 @@ struct Device } hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore), - void *store_cache = nullptr) const + VariationStore::cache_t *store_cache = nullptr) const { switch (u.b.format) { From 099482a37ad51d3dec5e762ab9f1d7dd3d3bb6a3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 May 2022 15:20:23 -0600 Subject: [PATCH 8/9] [ot-font] Cache v_advance varstore as well --- src/hb-ot-font.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index ef4115a8d..f1e7479f2 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -138,12 +138,20 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; if (vmtx.has_data ()) + { + const OT::HVARVVAR &VVAR = *vmtx.var_table; + const OT::VariationStore &varStore = &VVAR + VVAR.varStore; + OT::VariationStore::cache_t *cache = font->num_coords ? varStore.create_cache () : nullptr; + for (unsigned int i = 0; i < count; i++) { - *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font)); + *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font, cache)); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } + + OT::VariationStore::destroy_cache (cache); + } else { hb_font_extents_t font_extents; From 3eb7eff487f5aa3abaf5f7e1e40f96cb1de1c364 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 May 2022 15:25:53 -0600 Subject: [PATCH 9/9] Remove varstore cache use if HB_NO_VAR --- src/hb-ot-font.cc | 12 ++++++++++++ src/hb-ot-layout-gsubgpos.hh | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index f1e7479f2..521b3ee92 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -110,9 +110,13 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; +#ifndef HB_NO_VAR const OT::HVARVVAR &HVAR = *hmtx.var_table; const OT::VariationStore &varStore = &HVAR + HVAR.varStore; OT::VariationStore::cache_t *cache = font->num_coords ? varStore.create_cache () : nullptr; +#else + OT::VariationStore::cache_t *cache = nullptr; +#endif for (unsigned int i = 0; i < count; i++) { @@ -121,7 +125,9 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } +#ifndef HB_NO_VAR OT::VariationStore::destroy_cache (cache); +#endif } #ifndef HB_NO_VERTICAL @@ -139,9 +145,13 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, if (vmtx.has_data ()) { +#ifndef HB_NO_VAR const OT::HVARVVAR &VVAR = *vmtx.var_table; const OT::VariationStore &varStore = &VVAR + VVAR.varStore; OT::VariationStore::cache_t *cache = font->num_coords ? varStore.create_cache () : nullptr; +#else + OT::VariationStore::cache_t *cache = nullptr; +#endif for (unsigned int i = 0; i < count; i++) { @@ -150,7 +160,9 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } +#ifndef HB_NO_VAR OT::VariationStore::destroy_cache (cache); +#endif } else { diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index c2e043a60..d45499fd4 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -660,7 +660,13 @@ struct hb_ot_apply_context_t : #endif ), var_store (gdef.get_var_store ()), - var_store_cache (table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr), + var_store_cache ( +#ifndef HB_NO_VAR + table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr +#else + nullptr +#endif + ), direction (buffer_->props.direction), lookup_mask (1), lookup_index ((unsigned int) -1), @@ -674,7 +680,12 @@ struct hb_ot_apply_context_t : random_state (1) { init_iters (); } - ~hb_ot_apply_context_t () { VariationStore::destroy_cache (var_store_cache); } + ~hb_ot_apply_context_t () + { +#ifndef HB_NO_VAR + VariationStore::destroy_cache (var_store_cache); +#endif + } void init_iters () {