[cff2] Malloc-free draw of var blends

This commit is contained in:
Behdad Esfahbod 2025-03-20 19:58:37 -06:00
parent e2a24ce13a
commit cc0451c949
2 changed files with 61 additions and 14 deletions

View file

@ -71,7 +71,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
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 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
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 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
{
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 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
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 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
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;

View file

@ -482,6 +482,13 @@ struct cff2
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 @@ struct cff2
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;
};