diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index cda97a68c..3a1e31f06 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -108,6 +108,10 @@ struct hb_font_t { unsigned int x_ppem; unsigned int y_ppem; + /* Font variation coordinates. */ + int *coords; + unsigned int coord_count; + hb_font_funcs_t *klass; void *user_data; hb_destroy_func_t destroy; @@ -120,6 +124,8 @@ struct hb_font_t { { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } + inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); } + inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); } inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) { return em_scale (v, dir_scale (direction)); } @@ -531,6 +537,10 @@ struct hb_font_t { scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */ return (hb_position_t) (scaled / upem); } + inline hb_position_t em_scalef (float v, int scale) + { + return (hb_position_t) (v * scale / face->get_upem ()); + } }; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS diff --git a/src/hb-font.cc b/src/hb-font.cc index 08fcd6475..b4b4d0a52 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1194,6 +1194,9 @@ hb_font_get_empty (void) 0, /* x_ppem */ 0, /* y_ppem */ + NULL, /* coords */ + 0, /* coord_count */ + const_cast (&_hb_font_funcs_nil), /* klass */ NULL, /* user_data */ NULL, /* destroy */ diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 34fa1b773..a18ce74dc 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1236,6 +1236,119 @@ struct Device }; +struct VariationAxis +{ + inline float evaluate (int *coords, unsigned int coord_len) const + { + unsigned int i = axisIndex; + int coord = i < coord_len ? coords[i] : 0; + + int start = startCoord, peak = peakCoord, end = endCoord; + if (coord < start || coord > end) return 0.; + if (coord == peak) return 1.; + /* Interpolate */ + if (coord < peak) + return float (coord - start) / (peak - start); + else + return float (end - coord) / (end - peak); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + Index axisIndex; + F2DOT14 startCoord; + F2DOT14 peakCoord; + F2DOT14 endCoord; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct VariationTuple +{ + inline float evaluate (int *coords, unsigned int coord_len) const + { + float v = 1.; + unsigned int count = axes.len; + for (unsigned int i = 0; i < count; i++) + v *= (this+axes[i]).evaluate (coords, coord_len); + return v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (axes.sanitize (c, this)); + } + + OffsetArrayOf + axes; + public: + DEFINE_SIZE_ARRAY (2, axes); +}; + +struct VariationMap +{ + inline const VariationTuple& operator [] (unsigned int i) const + { return this+tuples[i]; } + + inline unsigned int get_len (void) const + { return tuples.len; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (tuples.sanitize (c, this)); + } + + OffsetArrayOf + tuples; + public: + DEFINE_SIZE_ARRAY (2, tuples); +}; + +struct VariationDevice +{ + + inline hb_position_t get_x_delta (hb_font_t *font) const + { return font->em_scalef_x (get_delta (font->coords, font->coord_count)); } + + inline hb_position_t get_y_delta (hb_font_t *font) const + { return font->em_scalef_y (get_delta (font->coords, font->coord_count)); } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && c->check_range (&deltaValue, numDeltas * SHORT::static_size)); + } + + private: + + inline float get_delta (int *coords, unsigned int coord_count) const + { + float v = 0; + const VariationMap &map = this+variationMap; + unsigned int count = MIN ((unsigned int) numDeltas, map.get_len ()); + for (unsigned int i = 0; i < count; i++) + v += deltaValue[i] * map[i].evaluate (coords, coord_count); + return v; + } + + protected: + OffsetTo + variationMap; /* Offset to variation mapping for this table. */ + USHORT numDeltas; /* Number of deltas for in this table. */ + USHORT deltaFormat; /* Format identifier for this table: 0x10 */ + SHORT deltaValue[VAR]; /* Deltas as signed values in design space. */ + public: + DEFINE_SIZE_ARRAY (6, deltaValue); +}; + + } /* namespace OT */