[ot-font] Cache h-advances for variable fonts

This commit is contained in:
Behdad Esfahbod 2022-05-23 19:39:52 -06:00
parent 39a07bf3eb
commit 3548b6025f
1 changed files with 89 additions and 8 deletions

View File

@ -30,6 +30,7 @@
#include "hb-ot.h"
#include "hb-cache.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-ot-face.hh"
@ -61,8 +62,42 @@
struct hb_ot_font_t
{
const hb_ot_face_t *ot_face;
/* h_advance caching */
mutable hb_mutex_t lock;
mutable unsigned cached_coords_serial;
mutable hb_advance_cache_t *advance_cache;
};
static hb_ot_font_t *
_hb_ot_font_create (hb_font_t *font)
{
hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
if (unlikely (!ot_font))
return nullptr;
ot_font->ot_face = &font->face->table;
ot_font->lock.init ();
return ot_font;
}
static void
_hb_ot_font_destroy (void *font_data)
{
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
ot_font->lock.fini ();
if (ot_font->advance_cache)
{
ot_font->advance_cache->fini ();
hb_free (ot_font->advance_cache);
}
hb_free (ot_font);
}
static hb_bool_t
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
void *font_data,
@ -122,15 +157,63 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
const OT::HVARVVAR &HVAR = *hmtx.var_table;
const OT::VariationStore &varStore = &HVAR + HVAR.varStore;
OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
bool use_cache = font->num_coords;
#else
OT::VariationStore::cache_t *varStore_cache = nullptr;
bool use_cache = false;
#endif
for (unsigned int i = 0; i < count; i++)
if (use_cache && !ot_font->advance_cache)
{
*first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, varStore_cache));
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
ot_font->lock.lock ();
ot_font->advance_cache = (hb_advance_cache_t *) hb_malloc (sizeof (*ot_font->advance_cache));
if (unlikely (!ot_font->advance_cache))
{
ot_font->lock.unlock ();
use_cache = false;
}
else
{
ot_font->advance_cache->init ();
ot_font->cached_coords_serial = font->serial_coords;
}
}
if (!use_cache)
{
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, varStore_cache));
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
}
else
{ /* Use cache; lock already held and cache initialized. */
if (ot_font->cached_coords_serial != font->serial_coords)
{
ot_font->advance_cache->init ();
ot_font->cached_coords_serial = font->serial_coords;
}
for (unsigned int i = 0; i < count; i++)
{
hb_position_t v;
unsigned cv;
if (ot_font->advance_cache->get (*first_glyph, &cv))
v = cv;
else
{
v = hmtx.get_advance (*first_glyph, font, varStore_cache);
ot_font->advance_cache->set (*first_glyph, v);
}
*first_advance = font->em_scale_x (v);
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
ot_font->lock.unlock ();
}
#ifndef HB_NO_VAR
@ -405,16 +488,14 @@ _hb_ot_get_font_funcs ()
void
hb_ot_font_set_funcs (hb_font_t *font)
{
hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
hb_ot_font_t *ot_font = _hb_ot_font_create (font);
if (unlikely (!ot_font))
return;
ot_font->ot_face = &font->face->table;
hb_font_set_funcs (font,
_hb_ot_get_font_funcs (),
ot_font,
hb_free);
_hb_ot_font_destroy);
}
#ifndef HB_NO_VAR