[cff2] Malloc-free draw of var blends
diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh
index 06fbb72..790aae3 100644
--- a/src/hb-cff2-interp-cs.hh
+++ b/src/hb-cff2-interp-cs.hh
@@ -71,7 +71,8 @@
template <typename ACC>
cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
const int *coords_=nullptr, unsigned int num_coords_=0)
- : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
+ : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs),
+ cached_scalars_vector (&acc.cached_scalars_vector)
{
coords = coords_;
num_coords = num_coords_;
@@ -80,9 +81,39 @@
set_ivs (acc.privateDicts[fd].ivs);
}
- void fini ()
+ ~cff2_cs_interp_env_t ()
{
- SUPER::fini ();
+ release_scalars_vector (scalars);
+ }
+
+ hb_vector_t<float> *acquire_scalars_vector () const
+ {
+ hb_vector_t<float> *scalars = cached_scalars_vector->get_acquire ();
+
+ if (!scalars || !cached_scalars_vector->cmpexch (scalars, nullptr))
+ {
+ scalars = (hb_vector_t<float> *) hb_calloc (1, sizeof (hb_vector_t<float>));
+ if (unlikely (!scalars))
+ return nullptr;
+ scalars->init ();
+ }
+
+ return scalars;
+ }
+
+ void release_scalars_vector (hb_vector_t<float> *scalars) const
+ {
+ if (!scalars)
+ return;
+
+ scalars->clear ();
+
+ if (!cached_scalars_vector->cmpexch (nullptr, scalars))
+ {
+ scalars->fini ();
+ hb_free (scalars);
+ }
+ scalars = nullptr;
}
op_code_t fetch_op ()
@@ -111,14 +142,20 @@
{
if (!seen_blend)
{
- region_count = varStore->varStore.get_region_index_count (get_ivs ());
- if (do_blend)
+ scalars = acquire_scalars_vector ();
+ if (unlikely (!scalars))
+ SUPER::set_error ();
+ else
{
- if (unlikely (!scalars.resize_exact (region_count)))
- SUPER::set_error ();
- else
- varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
- &scalars[0], region_count);
+ region_count = varStore->varStore.get_region_index_count (get_ivs ());
+ if (do_blend)
+ {
+ if (unlikely (!scalars->resize_exact (region_count)))
+ SUPER::set_error ();
+ else
+ varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
+ &(*scalars)[0], region_count);
+ }
}
seen_blend = true;
}
@@ -149,11 +186,11 @@
double v = 0;
if (do_blend)
{
- if (likely (scalars.length == deltas.length))
+ if (likely (scalars && scalars->length == deltas.length))
{
- unsigned count = scalars.length;
+ unsigned count = scalars->length;
for (unsigned i = 0; i < count; i++)
- v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
+ v += (double) scalars->arrayZ[i] * deltas.arrayZ[i].to_real ();
}
}
return v;
@@ -167,7 +204,8 @@
const CFF2ItemVariationStore *varStore;
unsigned int region_count;
unsigned int ivs;
- hb_vector_t<float> scalars;
+ hb_vector_t<float> *scalars = nullptr;
+ hb_atomic_t<hb_vector_t<float> *> *cached_scalars_vector = nullptr;
bool do_blend;
bool seen_vsindex_ = false;
bool seen_blend = false;
diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh
index f3b80a6..536c918 100644
--- a/src/hb-ot-cff2-table.hh
+++ b/src/hb-ot-cff2-table.hh
@@ -482,6 +482,13 @@
privateDicts.fini ();
hb_blob_destroy (blob);
blob = nullptr;
+
+ auto *scalars = cached_scalars_vector.get_acquire ();
+ if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr))
+ {
+ scalars->fini ();
+ hb_free (scalars);
+ }
}
hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
@@ -509,6 +516,8 @@
hb_vector_t<cff2_font_dict_values_t> fontDicts;
hb_vector_t<PRIVDICTVAL> privateDicts;
+ mutable hb_atomic_t<hb_vector_t<float> *> cached_scalars_vector;
+
unsigned int num_glyphs = 0;
};