|
|
|
@ -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 |
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < count; i++) |
|
|
|
|
hb_advance_cache_t *cache = nullptr; |
|
|
|
|
if (use_cache) |
|
|
|
|
{ |
|
|
|
|
*first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, cache)); |
|
|
|
|
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); |
|
|
|
|
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); |
|
|
|
|
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, 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 |
|
|
|
|