mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-04 21:15:06 +00:00
Merge pull request #5239 from harfbuzz/alloc-free-var-shaping
Alloc free var shaping
This commit is contained in:
commit
c6c8dcdeca
3 changed files with 115 additions and 59 deletions
|
@ -192,7 +192,6 @@
|
||||||
#ifdef HB_MINIMIZE_MEMORY_USAGE
|
#ifdef HB_MINIMIZE_MEMORY_USAGE
|
||||||
#define HB_NO_GDEF_CACHE
|
#define HB_NO_GDEF_CACHE
|
||||||
#define HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
#define HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||||
#define HB_NO_OT_FONT_ADVANCE_CACHE
|
|
||||||
#define HB_NO_OT_FONT_CMAP_CACHE
|
#define HB_NO_OT_FONT_CMAP_CACHE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,102 @@ struct hb_ot_font_t
|
||||||
|
|
||||||
/* h_advance caching */
|
/* h_advance caching */
|
||||||
mutable hb_atomic_t<int> cached_coords_serial;
|
mutable hb_atomic_t<int> cached_coords_serial;
|
||||||
mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
|
struct advance_cache_t
|
||||||
|
{
|
||||||
|
mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
|
||||||
|
mutable hb_atomic_t<OT::ItemVariationStore::cache_t *> varStore_cache;
|
||||||
|
|
||||||
|
~advance_cache_t ()
|
||||||
|
{
|
||||||
|
clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_ot_font_advance_cache_t *acquire_advance_cache () const
|
||||||
|
{
|
||||||
|
retry:
|
||||||
|
auto *cache = advance_cache.get_acquire ();
|
||||||
|
if (!cache)
|
||||||
|
{
|
||||||
|
cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
|
||||||
|
if (!cache)
|
||||||
|
return nullptr;
|
||||||
|
new (cache) hb_ot_font_advance_cache_t;
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
if (advance_cache.cmpexch (cache, nullptr))
|
||||||
|
return cache;
|
||||||
|
else
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
void release_advance_cache (hb_ot_font_advance_cache_t *cache) const
|
||||||
|
{
|
||||||
|
if (!cache)
|
||||||
|
return;
|
||||||
|
if (!advance_cache.cmpexch (nullptr, cache))
|
||||||
|
hb_free (cache);
|
||||||
|
}
|
||||||
|
void clear_advance_cache () const
|
||||||
|
{
|
||||||
|
retry:
|
||||||
|
auto *cache = advance_cache.get_acquire ();
|
||||||
|
if (!cache)
|
||||||
|
return;
|
||||||
|
if (advance_cache.cmpexch (cache, nullptr))
|
||||||
|
hb_free (cache);
|
||||||
|
else
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
OT::ItemVariationStore::cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
|
||||||
|
{
|
||||||
|
retry:
|
||||||
|
auto *cache = varStore_cache.get_acquire ();
|
||||||
|
if (!cache)
|
||||||
|
return varStore.create_cache ();
|
||||||
|
if (varStore_cache.cmpexch (cache, nullptr))
|
||||||
|
return cache;
|
||||||
|
else
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
void release_varStore_cache (OT::ItemVariationStore::cache_t *cache) const
|
||||||
|
{
|
||||||
|
if (!cache)
|
||||||
|
return;
|
||||||
|
if (!varStore_cache.cmpexch (nullptr, cache))
|
||||||
|
OT::ItemVariationStore::destroy_cache (cache);
|
||||||
|
}
|
||||||
|
void clear_varStore_cache () const
|
||||||
|
{
|
||||||
|
retry:
|
||||||
|
auto *cache = varStore_cache.get_acquire ();
|
||||||
|
if (!cache)
|
||||||
|
return;
|
||||||
|
if (varStore_cache.cmpexch (cache, nullptr))
|
||||||
|
OT::ItemVariationStore::destroy_cache (cache);
|
||||||
|
else
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear () const
|
||||||
|
{
|
||||||
|
clear_advance_cache ();
|
||||||
|
clear_varStore_cache ();
|
||||||
|
}
|
||||||
|
|
||||||
|
} h, v;
|
||||||
|
|
||||||
|
void check_serial (hb_font_t *font) const
|
||||||
|
{
|
||||||
|
int font_serial = font->serial_coords.get_acquire ();
|
||||||
|
|
||||||
|
if (cached_coords_serial.get_acquire () == font_serial)
|
||||||
|
return;
|
||||||
|
|
||||||
|
h.clear ();
|
||||||
|
v.clear ();
|
||||||
|
|
||||||
|
cached_coords_serial.set_release (font_serial);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static hb_ot_font_t *
|
static hb_ot_font_t *
|
||||||
|
@ -90,8 +185,7 @@ _hb_ot_font_destroy (void *font_data)
|
||||||
{
|
{
|
||||||
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
|
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
|
||||||
|
|
||||||
auto *cache = ot_font->advance_cache.get_relaxed ();
|
ot_font->~hb_ot_font_t ();
|
||||||
hb_free (cache);
|
|
||||||
|
|
||||||
hb_free (ot_font);
|
hb_free (ot_font);
|
||||||
}
|
}
|
||||||
|
@ -153,41 +247,20 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||||
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
|
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
|
||||||
|
|
||||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
ot_font->check_serial (font);
|
||||||
const OT::HVAR &HVAR = *hmtx.var_table;
|
const OT::HVAR &HVAR = *hmtx.var_table;
|
||||||
const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
|
const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
|
||||||
OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
|
OT::ItemVariationStore::cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
|
||||||
|
|
||||||
|
hb_ot_font_advance_cache_t *advance_cache = nullptr;
|
||||||
|
|
||||||
bool use_cache = font->num_coords;
|
bool use_cache = font->num_coords;
|
||||||
#else
|
|
||||||
OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
|
|
||||||
bool use_cache = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hb_ot_font_advance_cache_t *cache = nullptr;
|
|
||||||
if (use_cache)
|
if (use_cache)
|
||||||
{
|
{
|
||||||
retry:
|
advance_cache = ot_font->h.acquire_advance_cache ();
|
||||||
cache = ot_font->advance_cache.get_acquire ();
|
if (!advance_cache)
|
||||||
if (unlikely (!cache))
|
use_cache = false;
|
||||||
{
|
|
||||||
cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
|
|
||||||
if (unlikely (!cache))
|
|
||||||
{
|
|
||||||
use_cache = false;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
new (cache) hb_ot_font_advance_cache_t;
|
|
||||||
|
|
||||||
if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
|
|
||||||
{
|
|
||||||
hb_free (cache);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
ot_font->cached_coords_serial.set_release (font->serial_coords);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
|
|
||||||
if (!use_cache)
|
if (!use_cache)
|
||||||
{
|
{
|
||||||
|
@ -200,38 +273,26 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* Use cache. */
|
{ /* Use cache. */
|
||||||
if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords)
|
|
||||||
{
|
|
||||||
// Retire advance cache and let it be recreated.
|
|
||||||
auto *old_cache = ot_font->advance_cache.get_acquire ();
|
|
||||||
if (ot_font->advance_cache.cmpexch (cache, nullptr))
|
|
||||||
{
|
|
||||||
ot_font->cached_coords_serial.set_release (font->serial_coords);
|
|
||||||
hb_free (old_cache);
|
|
||||||
}
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
hb_position_t v;
|
hb_position_t v;
|
||||||
unsigned cv;
|
unsigned cv;
|
||||||
if (ot_font->advance_cache->get (*first_glyph, &cv))
|
if (advance_cache->get (*first_glyph, &cv))
|
||||||
v = cv;
|
v = cv;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
|
v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
|
||||||
ot_font->advance_cache->set (*first_glyph, v);
|
advance_cache->set (*first_glyph, v);
|
||||||
}
|
}
|
||||||
*first_advance = font->em_scale_x (v);
|
*first_advance = font->em_scale_x (v);
|
||||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ot_font->h.release_advance_cache (advance_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
ot_font->h.release_varStore_cache (varStore_cache);
|
||||||
OT::ItemVariationStore::destroy_cache (varStore_cache);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_VERTICAL
|
#ifndef HB_NO_VERTICAL
|
||||||
|
@ -250,13 +311,11 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||||
|
|
||||||
if (vmtx.has_data ())
|
if (vmtx.has_data ())
|
||||||
{
|
{
|
||||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
ot_font->check_serial (font);
|
||||||
const OT::VVAR &VVAR = *vmtx.var_table;
|
const OT::VVAR &VVAR = *vmtx.var_table;
|
||||||
const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
|
const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
|
||||||
OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
|
OT::ItemVariationStore::cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
|
||||||
#else
|
// TODO Use advance_cache.
|
||||||
OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
@ -265,9 +324,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
ot_font->v.release_varStore_cache (varStore_cache);
|
||||||
OT::ItemVariationStore::destroy_cache (varStore_cache);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -3187,8 +3187,8 @@ struct ItemVariationStore
|
||||||
#ifdef HB_NO_VAR
|
#ifdef HB_NO_VAR
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
auto &r = this+regions;
|
unsigned count = (this+regions).regionCount;
|
||||||
unsigned count = r.regionCount;
|
if (!count) return nullptr;
|
||||||
|
|
||||||
float *cache = (float *) hb_malloc (sizeof (float) * count);
|
float *cache = (float *) hb_malloc (sizeof (float) * count);
|
||||||
if (unlikely (!cache)) return nullptr;
|
if (unlikely (!cache)) return nullptr;
|
||||||
|
|
Loading…
Add table
Reference in a new issue