Merge pull request #3603 from harfbuzz/font-serial

Add font serial API
This commit is contained in:
Behdad Esfahbod 2022-05-27 08:25:22 -06:00 committed by GitHub
commit 63bc6be0cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 297 additions and 60 deletions

View File

@ -373,6 +373,8 @@ hb_font_glyph_from_string
hb_font_glyph_to_string
hb_font_is_immutable
hb_font_make_immutable
hb_font_get_serial
hb_font_changed
hb_font_reference
hb_font_set_face
hb_font_set_funcs

View File

@ -1623,6 +1623,9 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
{
HB_OBJECT_HEADER_STATIC,
0, /* serial */
0, /* serial_coords */
nullptr, /* parent */
const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
@ -1852,6 +1855,9 @@ hb_font_set_user_data (hb_font_t *font,
hb_destroy_func_t destroy /* May be NULL. */,
hb_bool_t replace)
{
if (!hb_object_is_immutable (font))
font->serial++;
return hb_object_set_user_data (font, key, data, destroy, replace);
}
@ -1910,6 +1916,45 @@ hb_font_is_immutable (hb_font_t *font)
return hb_object_is_immutable (font);
}
/**
* hb_font_get_serial:
* @font: #hb_font_t to work upon
*
* Returns the internal serial number of the font. The serial
* number is increased every time a setting on the font is
* changed, using a setter function.
*
* Return value: serial number
*
* Since: REPLACEME.
**/
unsigned int
hb_font_get_serial (hb_font_t *font)
{
return font->serial;
}
/**
* hb_font_changed:
* @font: #hb_font_t to work upon
*
* Notifies the @font that underlying font data has changed.
* This has the effect of increasing the serial as returned
* by hb_font_get_serial(), which invalidates internal caches.
*
* Since: REPLACEME.
**/
void
hb_font_changed (hb_font_t *font)
{
if (hb_object_is_immutable (font))
return;
font->serial++;
font->mults_changed ();
}
/**
* hb_font_set_parent:
* @font: #hb_font_t to work upon
@ -1926,6 +1971,11 @@ hb_font_set_parent (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
if (parent == font->parent)
return;
font->serial++;
if (!parent)
parent = hb_font_get_empty ();
@ -1968,6 +2018,11 @@ hb_font_set_face (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
if (face == font->face)
return;
font->serial++;
if (unlikely (!face))
face = hb_face_get_empty ();
@ -2022,6 +2077,8 @@ hb_font_set_funcs (hb_font_t *font,
return;
}
font->serial++;
if (font->destroy)
font->destroy (font->user_data);
@ -2059,6 +2116,8 @@ hb_font_set_funcs_data (hb_font_t *font,
return;
}
font->serial++;
if (font->destroy)
font->destroy (font->user_data);
@ -2085,6 +2144,11 @@ hb_font_set_scale (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
if (font->x_scale == x_scale && font->y_scale == y_scale)
return;
font->serial++;
font->x_scale = x_scale;
font->y_scale = y_scale;
font->mults_changed ();
@ -2127,6 +2191,11 @@ hb_font_set_ppem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
return;
font->serial++;
font->x_ppem = x_ppem;
font->y_ppem = y_ppem;
}
@ -2169,6 +2238,11 @@ hb_font_set_ptem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
if (font->ptem == ptem)
return;
font->serial++;
font->ptem = ptem;
}
@ -2216,6 +2290,11 @@ hb_font_set_synthetic_slant (hb_font_t *font, float slant)
if (hb_object_is_immutable (font))
return;
if (font->slant == slant)
return;
font->serial++;
font->slant = slant;
font->mults_changed ();
}
@ -2263,6 +2342,8 @@ hb_font_set_variations (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
font->serial_coords = ++font->serial;
if (!variations_length)
{
hb_font_set_var_coords_normalized (font, nullptr, 0);
@ -2322,6 +2403,8 @@ hb_font_set_var_coords_design (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
font->serial_coords = ++font->serial;
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@ -2355,6 +2438,8 @@ hb_font_set_var_named_instance (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
font->serial_coords = ++font->serial;
unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@ -2391,6 +2476,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
font->serial_coords = ++font->serial;
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;

View File

@ -1002,6 +1002,12 @@ hb_font_make_immutable (hb_font_t *font);
HB_EXTERN hb_bool_t
hb_font_is_immutable (hb_font_t *font);
HB_EXTERN unsigned int
hb_font_get_serial (hb_font_t *font);
HB_EXTERN void
hb_font_changed (hb_font_t *font);
HB_EXTERN void
hb_font_set_parent (hb_font_t *font,
hb_font_t *parent);

View File

@ -104,6 +104,8 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
struct hb_font_t
{
hb_object_header_t header;
unsigned int serial;
unsigned int serial_coords;
hb_font_t *parent;
hb_face_t *face;

View File

@ -86,7 +86,7 @@ struct hb_ft_font_t
mutable hb_mutex_t lock;
FT_Face ft_face;
mutable int cached_x_scale;
mutable unsigned cached_serial;
mutable hb_advance_cache_t advance_cache;
};
@ -103,7 +103,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
ft_font->cached_x_scale = 0;
ft_font->cached_serial = (unsigned) -1;
ft_font->advance_cache.init ();
return ft_font;
@ -130,6 +130,56 @@ _hb_ft_font_destroy (void *data)
hb_free (ft_font);
}
/* hb_font changed, update FT_Face. */
static void _hb_ft_changed (hb_font_t *font, FT_Face ft_face)
{
FT_Set_Char_Size (ft_face,
abs (font->x_scale), abs (font->y_scale),
0, 0);
#if 0
font->x_ppem * 72 * 64 / font->x_scale,
font->y_ppem * 72 * 64 / font->y_scale);
#endif
if (font->x_scale < 0 || font->y_scale < 0)
{
FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
0, font->y_scale < 0 ? -1 : +1};
FT_Set_Transform (ft_face, &matrix, nullptr);
}
#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
unsigned int num_coords;
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
if (num_coords)
{
FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
if (ft_coords)
{
for (unsigned int i = 0; i < num_coords; i++)
ft_coords[i] = coords[i] * 4;
FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
hb_free (ft_coords);
}
}
#endif
}
/* Check if hb_font changed, update FT_Face. */
static inline bool
_hb_ft_check_changed (hb_font_t *font,
const hb_ft_font_t *ft_font)
{
if (font->serial != ft_font->cached_serial)
{
_hb_ft_changed (font, ft_font->ft_face);
ft_font->cached_serial = font->serial;
return true;
}
return false;
}
/**
* hb_ft_font_set_load_flags:
* @font: #hb_font_t to work upon
@ -337,11 +387,8 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
int load_flags = ft_font->load_flags;
int mult = font->x_scale < 0 ? -1 : +1;
if (font->x_scale != ft_font->cached_x_scale)
{
if (_hb_ft_check_changed (font, ft_font))
ft_font->advance_cache.clear ();
ft_font->cached_x_scale = font->x_scale;
}
for (unsigned int i = 0; i < count; i++)
{
@ -374,6 +421,8 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
hb_lock_t lock (ft_font->lock);
FT_Fixed v;
_hb_ft_check_changed (font, ft_font);
if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
return 0;
@ -400,6 +449,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
_hb_ft_check_changed (font, ft_font);
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
@ -429,6 +480,8 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
hb_lock_t lock (ft_font->lock);
FT_Vector kerningv;
_hb_ft_check_changed (font, ft_font);
FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
return 0;
@ -448,6 +501,8 @@ hb_ft_get_glyph_extents (hb_font_t *font,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
_hb_ft_check_changed (font, ft_font);
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
@ -481,6 +536,8 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
_hb_ft_check_changed (font, ft_font);
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
@ -557,6 +614,9 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
_hb_ft_check_changed (font, ft_font);
metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
@ -620,6 +680,8 @@ hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
_hb_ft_check_changed (font, ft_font);
if (unlikely (FT_Load_Glyph (ft_face, glyph,
FT_LOAD_NO_BITMAP | ft_font->load_flags)))
return;
@ -1082,35 +1144,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL))
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
FT_Set_Char_Size (ft_face,
abs (font->x_scale), abs (font->y_scale),
0, 0);
#if 0
font->x_ppem * 72 * 64 / font->x_scale,
font->y_ppem * 72 * 64 / font->y_scale);
#endif
if (font->x_scale < 0 || font->y_scale < 0)
{
FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
0, font->y_scale < 0 ? -1 : +1};
FT_Set_Transform (ft_face, &matrix, nullptr);
}
#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
unsigned int num_coords;
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
if (num_coords)
{
FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
if (ft_coords)
{
for (unsigned int i = 0; i < num_coords; i++)
ft_coords[i] = coords[i] * 4;
FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
hb_free (ft_coords);
}
}
#endif
_hb_ft_changed (font, ft_face);
ft_face->generic.data = blob;
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;

View File

@ -1333,7 +1333,7 @@ struct cff1
if (names)
{
names->fini ();
free (names);
hb_free (names);
}
SUPER::fini ();
@ -1379,7 +1379,7 @@ struct cff1
hb_sorted_vector_t<gname_t> *names = glyph_names.get ();
if (unlikely (!names))
{
names = (hb_sorted_vector_t<gname_t> *) calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
if (likely (names))
{
names->init ();
@ -1409,7 +1409,7 @@ struct cff1
if (names)
{
names->fini ();
free (names);
hb_free (names);
}
goto retry;
}

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"
@ -58,6 +59,41 @@
* never need to call these functions directly.
**/
struct hb_ot_font_t
{
const hb_ot_face_t *ot_face;
/* h_advance caching */
mutable hb_atomic_int_t cached_coords_serial;
mutable hb_atomic_ptr_t<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;
return ot_font;
}
static void
_hb_ot_font_destroy (void *font_data)
{
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
auto *cache = ot_font->advance_cache.get_relaxed ();
if (cache)
{
cache->fini ();
hb_free (cache);
}
hb_free (ot_font);
}
static hb_bool_t
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
@ -66,7 +102,8 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_nominal_glyph (unicode, glyph);
}
@ -80,7 +117,8 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
unsigned int glyph_stride,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_nominal_glyphs (count,
first_unicode, unicode_stride,
first_glyph, glyph_stride);
@ -94,7 +132,8 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
}
@ -107,26 +146,82 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
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;
OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
bool use_cache = font->num_coords;
#else
OT::VariationStore::cache_t *cache = nullptr;
OT::VariationStore::cache_t *varStore_cache = nullptr;
bool use_cache = false;
#endif
hb_advance_cache_t *cache = nullptr;
if (use_cache)
{
retry:
cache = ot_font->advance_cache.get ();
if (unlikely (!cache))
{
cache = (hb_advance_cache_t *) hb_malloc (sizeof (hb_advance_cache_t));
if (unlikely (!cache))
{
use_cache = false;
goto out;
}
cache->init ();
if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
{
hb_free (cache);
goto retry;
}
ot_font->cached_coords_serial.set (font->serial_coords);
}
}
out:
if (!use_cache)
{
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, 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);
}
}
else
{ /* Use cache. */
if (ot_font->cached_coords_serial.get () != (int) font->serial_coords)
{
ot_font->advance_cache->init ();
ot_font->cached_coords_serial.set (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);
}
}
#ifndef HB_NO_VAR
OT::VariationStore::destroy_cache (cache);
OT::VariationStore::destroy_cache (varStore_cache);
#endif
}
@ -140,7 +235,8 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
if (vmtx.has_data ())
@ -148,20 +244,20 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_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;
OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
#else
OT::VariationStore::cache_t *cache = nullptr;
OT::VariationStore::cache_t *varStore_cache = nullptr;
#endif
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font, cache));
*first_advance = font->em_scale_y (-(int) vmtx.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);
}
#ifndef HB_NO_VAR
OT::VariationStore::destroy_cache (cache);
OT::VariationStore::destroy_cache (varStore_cache);
#endif
}
else
@ -189,7 +285,8 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
hb_position_t *y,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
*x = font->get_glyph_h_advance (glyph) / 2;
@ -234,7 +331,8 @@ hb_ot_get_glyph_extents (hb_font_t *font,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
@ -260,7 +358,9 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
char *name, unsigned int size,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
@ -274,7 +374,9 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
@ -390,10 +492,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_create (font);
if (unlikely (!ot_font))
return;
hb_font_set_funcs (font,
_hb_ot_get_font_funcs (),
&font->face->table,
nullptr);
ot_font,
_hb_ot_font_destroy);
}
#ifndef HB_NO_VAR