|
|
|
@ -2601,14 +2601,27 @@ struct VarRegionAxis |
|
|
|
|
DEFINE_SIZE_STATIC (6); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#define REGION_CACHE_ITEM_CACHE_INVALID 2.f |
|
|
|
|
|
|
|
|
|
struct VarRegionList |
|
|
|
|
{ |
|
|
|
|
using cache_t = float; |
|
|
|
|
|
|
|
|
|
float evaluate (unsigned int region_index, |
|
|
|
|
const int *coords, unsigned int coord_len) const |
|
|
|
|
const int *coords, unsigned int coord_len, |
|
|
|
|
cache_t *cache = nullptr) const |
|
|
|
|
{ |
|
|
|
|
if (unlikely (region_index >= regionCount)) |
|
|
|
|
return 0.; |
|
|
|
|
|
|
|
|
|
float *cached = nullptr; |
|
|
|
|
if (cache) |
|
|
|
|
{ |
|
|
|
|
cached = &(cache[region_index]); |
|
|
|
|
if (likely (*cached != REGION_CACHE_ITEM_CACHE_INVALID)) |
|
|
|
|
return *cached; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount); |
|
|
|
|
|
|
|
|
|
float v = 1.; |
|
|
|
@ -2618,9 +2631,16 @@ struct VarRegionList |
|
|
|
|
int coord = i < coord_len ? coords[i] : 0; |
|
|
|
|
float factor = axes[i].evaluate (coord); |
|
|
|
|
if (factor == 0.f) |
|
|
|
|
{ |
|
|
|
|
if (cache) |
|
|
|
|
*cached = 0.; |
|
|
|
|
return 0.; |
|
|
|
|
} |
|
|
|
|
v *= factor; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (cache) |
|
|
|
|
*cached = v; |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2678,7 +2698,8 @@ struct VarData |
|
|
|
|
|
|
|
|
|
float get_delta (unsigned int inner, |
|
|
|
|
const int *coords, unsigned int coord_count, |
|
|
|
|
const VarRegionList ®ions) const |
|
|
|
|
const VarRegionList ®ions, |
|
|
|
|
VarRegionList::cache_t *cache = nullptr) const |
|
|
|
|
{ |
|
|
|
|
if (unlikely (inner >= itemCount)) |
|
|
|
|
return 0.; |
|
|
|
@ -2695,13 +2716,13 @@ struct VarData |
|
|
|
|
const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row); |
|
|
|
|
for (; i < scount; i++) |
|
|
|
|
{ |
|
|
|
|
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count); |
|
|
|
|
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache); |
|
|
|
|
delta += scalar * *scursor++; |
|
|
|
|
} |
|
|
|
|
const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor); |
|
|
|
|
for (; i < count; i++) |
|
|
|
|
{ |
|
|
|
|
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count); |
|
|
|
|
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache); |
|
|
|
|
delta += scalar * *bcursor++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2846,9 +2867,28 @@ struct VarData |
|
|
|
|
|
|
|
|
|
struct VariationStore |
|
|
|
|
{ |
|
|
|
|
using cache_t = VarRegionList::cache_t; |
|
|
|
|
|
|
|
|
|
cache_t *create_cache () const |
|
|
|
|
{ |
|
|
|
|
auto &r = this+regions; |
|
|
|
|
unsigned count = r.regionCount; |
|
|
|
|
|
|
|
|
|
float *cache = (float *) hb_malloc (sizeof (float) * count); |
|
|
|
|
if (unlikely (!cache)) return nullptr; |
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; i++) |
|
|
|
|
cache[i] = REGION_CACHE_ITEM_CACHE_INVALID; |
|
|
|
|
|
|
|
|
|
return cache; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void destroy_cache (cache_t *cache) { hb_free (cache); } |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
float get_delta (unsigned int outer, unsigned int inner, |
|
|
|
|
const int *coords, unsigned int coord_count) const |
|
|
|
|
const int *coords, unsigned int coord_count, |
|
|
|
|
VarRegionList::cache_t *cache = nullptr) const |
|
|
|
|
{ |
|
|
|
|
#ifdef HB_NO_VAR |
|
|
|
|
return 0.f; |
|
|
|
@ -2859,16 +2899,18 @@ struct VariationStore |
|
|
|
|
|
|
|
|
|
return (this+dataSets[outer]).get_delta (inner, |
|
|
|
|
coords, coord_count, |
|
|
|
|
this+regions); |
|
|
|
|
this+regions, |
|
|
|
|
cache); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
float get_delta (unsigned int index, |
|
|
|
|
const int *coords, unsigned int coord_count) const |
|
|
|
|
const int *coords, unsigned int coord_count, |
|
|
|
|
VarRegionList::cache_t *cache = nullptr) const |
|
|
|
|
{ |
|
|
|
|
unsigned int outer = index >> 16; |
|
|
|
|
unsigned int inner = index & 0xFFFF; |
|
|
|
|
return get_delta (outer, inner, coords, coord_count); |
|
|
|
|
return get_delta (outer, inner, coords, coord_count, cache); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool sanitize (hb_sanitize_context_t *c) const |
|
|
|
@ -2995,6 +3037,8 @@ struct VariationStore |
|
|
|
|
DEFINE_SIZE_ARRAY_SIZED (8, dataSets); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#undef REGION_CACHE_ITEM_CACHE_INVALID |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Feature Variations |
|
|
|
|
*/ |
|
|
|
@ -3462,11 +3506,15 @@ struct VariationDevice |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const |
|
|
|
|
{ return font->em_scalef_x (get_delta (font, store)); } |
|
|
|
|
hb_position_t get_x_delta (hb_font_t *font, |
|
|
|
|
const VariationStore &store, |
|
|
|
|
VariationStore::cache_t *store_cache = nullptr) const |
|
|
|
|
{ return font->em_scalef_x (get_delta (font, store, store_cache)); } |
|
|
|
|
|
|
|
|
|
hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const |
|
|
|
|
{ return font->em_scalef_y (get_delta (font, store)); } |
|
|
|
|
hb_position_t get_y_delta (hb_font_t *font, |
|
|
|
|
const VariationStore &store, |
|
|
|
|
VariationStore::cache_t *store_cache = nullptr) const |
|
|
|
|
{ return font->em_scalef_y (get_delta (font, store, store_cache)); } |
|
|
|
|
|
|
|
|
|
VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const |
|
|
|
|
{ |
|
|
|
@ -3500,9 +3548,11 @@ struct VariationDevice |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
float get_delta (hb_font_t *font, const VariationStore &store) const |
|
|
|
|
float get_delta (hb_font_t *font, |
|
|
|
|
const VariationStore &store, |
|
|
|
|
VariationStore::cache_t *store_cache = nullptr) const |
|
|
|
|
{ |
|
|
|
|
return store.get_delta (varIdx, font->coords, font->num_coords); |
|
|
|
|
return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
@ -3525,7 +3575,9 @@ struct DeviceHeader |
|
|
|
|
|
|
|
|
|
struct Device |
|
|
|
|
{ |
|
|
|
|
hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const |
|
|
|
|
hb_position_t get_x_delta (hb_font_t *font, |
|
|
|
|
const VariationStore &store=Null (VariationStore), |
|
|
|
|
VariationStore::cache_t *store_cache = nullptr) const |
|
|
|
|
{ |
|
|
|
|
switch (u.b.format) |
|
|
|
|
{ |
|
|
|
@ -3535,13 +3587,15 @@ struct Device |
|
|
|
|
#endif |
|
|
|
|
#ifndef HB_NO_VAR |
|
|
|
|
case 0x8000: |
|
|
|
|
return u.variation.get_x_delta (font, store); |
|
|
|
|
return u.variation.get_x_delta (font, store, store_cache); |
|
|
|
|
#endif |
|
|
|
|
default: |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const |
|
|
|
|
hb_position_t get_y_delta (hb_font_t *font, |
|
|
|
|
const VariationStore &store=Null (VariationStore), |
|
|
|
|
VariationStore::cache_t *store_cache = nullptr) const |
|
|
|
|
{ |
|
|
|
|
switch (u.b.format) |
|
|
|
|
{ |
|
|
|
@ -3551,7 +3605,7 @@ struct Device |
|
|
|
|
#endif |
|
|
|
|
#ifndef HB_NO_VAR |
|
|
|
|
case 0x8000: |
|
|
|
|
return u.variation.get_y_delta (font, store); |
|
|
|
|
return u.variation.get_y_delta (font, store, store_cache); |
|
|
|
|
#endif |
|
|
|
|
default: |
|
|
|
|
return 0; |
|
|
|
|