diff options
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-ot-stat-table.hh')
-rw-r--r-- | thirdparty/harfbuzz/src/hb-ot-stat-table.hh | 262 |
1 files changed, 238 insertions, 24 deletions
diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh index 41d1734b39..d83bf14219 100644 --- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh @@ -57,6 +57,31 @@ enum // Reserved = 0xFFFC /* Reserved for future use — set to zero. */ }; +struct StatAxisRecord +{ + int cmp (hb_tag_t key) const { return tag.cmp (key); } + + hb_ot_name_id_t get_name_id () const { return nameID; } + + hb_tag_t get_axis_tag () const { return tag; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + Tag tag; /* A tag identifying the axis of design variation. */ + NameID nameID; /* The name ID for entries in the 'name' table that + * provide a display string for this axis. */ + HBUINT16 ordering; /* A value that applications can use to determine + * primary sorting of face names, or for ordering + * of descriptors when composing family or face names. */ + public: + DEFINE_SIZE_STATIC (8); +}; + struct AxisValueFormat1 { unsigned int get_axis_index () const { return axisIndex; } @@ -64,10 +89,41 @@ struct AxisValueFormat1 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const + { + unsigned axis_idx = get_axis_index (); + return axis_records[axis_idx].get_axis_tag (); + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_tag_t axis_tag = get_axis_tag (axis_records); + float axis_value = get_value (); + + if (!user_axes_location->has (axis_tag) || + fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) + return true; + + return false; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; + + if (keep_axis_value (axis_records, user_axes_location)) + return_trace (c->serializer->embed (this)); + + return_trace (false); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -92,10 +148,41 @@ struct AxisValueFormat2 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const + { + unsigned axis_idx = get_axis_index (); + return axis_records[axis_idx].get_axis_tag (); + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_tag_t axis_tag = get_axis_tag (axis_records); + float axis_value = get_value (); + + if (!user_axes_location->has (axis_tag) || + fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) + return true; + + return false; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; + + if (keep_axis_value (axis_records, user_axes_location)) + return_trace (c->serializer->embed (this)); + + return_trace (false); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -124,10 +211,41 @@ struct AxisValueFormat3 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const + { + unsigned axis_idx = get_axis_index (); + return axis_records[axis_idx].get_axis_tag (); + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_tag_t axis_tag = get_axis_tag (axis_records); + float axis_value = get_value (); + + if (!user_axes_location->has (axis_tag) || + fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) + return true; + + return false; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; + + if (keep_axis_value (axis_records, user_axes_location)) + return_trace (c->serializer->embed (this)); + + return_trace (false); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -155,7 +273,7 @@ struct AxisValueRecord bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this)); } protected: @@ -172,12 +290,47 @@ struct AxisValueFormat4 const AxisValueRecord &get_axis_record (unsigned int axis_index) const { return axisValues.as_array (axisCount)[axis_index]; } + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount); + + for (const auto& rec : axis_value_records) + { + unsigned axis_idx = rec.get_axis_index (); + float axis_value = rec.get_value (); + hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag (); + + if (user_axes_location->has (axis_tag) && + fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f) + return false; + } + + return true; + } + + bool subset (hb_subset_context_t *c, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + const hb_hashmap_t<hb_tag_t, float> *user_axes_location = c->plan->user_axes_location; + if (!keep_axis_value (axis_records, user_axes_location)) + return_trace (false); + + unsigned total_size = min_size + axisCount * AxisValueRecord::static_size; + auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size); + if (unlikely (!out)) return_trace (false); + memcpy (out, this, total_size); + return_trace (true); + } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (likely (c->check_struct (this) && + axisValues.sanitize (c, axisCount))); } protected: @@ -234,6 +387,33 @@ struct AxisValue } } + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, + hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + { + switch (u.format) + { + case 1: return u.format1.keep_axis_value (axis_records, user_axes_location); + case 2: return u.format2.keep_axis_value (axis_records, user_axes_location); + case 3: return u.format3.keep_axis_value (axis_records, user_axes_location); + case 4: return u.format4.keep_axis_value (axis_records, user_axes_location); + default:return false; + } + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -263,27 +443,35 @@ struct AxisValue DEFINE_SIZE_UNION (2, format); }; -struct StatAxisRecord +struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>> { - int cmp (hb_tag_t key) const { return tag.cmp (key); } + bool subset (hb_subset_context_t *c, + unsigned axisValueCount, + unsigned& count, + const hb_array_t<const StatAxisRecord> axis_records) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!out)) return_trace (false); - hb_ot_name_id_t get_name_id () const { return nameID; } + auto axisValueOffsets = as_array (axisValueCount); + count = 0; + for (const auto& offset : axisValueOffsets) + { + if (!offset) continue; + auto o_snap = c->serializer->snapshot (); + auto *o = c->serializer->embed (offset); + if (!o) return_trace (false); + if (!o->serialize_subset (c, offset, this, axis_records)) + { + c->serializer->revert (o_snap); + continue; + } + count++; + } - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (count); } - - protected: - Tag tag; /* A tag identifying the axis of design variation. */ - NameID nameID; /* The name ID for entries in the 'name' table that - * provide a display string for this axis. */ - HBUINT16 ordering; /* A value that applications can use to determine - * primary sorting of face names, or for ordering - * of descriptors when composing family or face names. */ - public: - DEFINE_SIZE_STATIC (8); }; struct STAT @@ -329,7 +517,8 @@ struct STAT return axis_value.get_value_name_id (); } - void collect_name_ids (hb_set_t *nameids_to_retain) const + void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location, + hb_set_t *nameids_to_retain /* OUT */) const { if (!has_data ()) return; @@ -338,13 +527,38 @@ struct STAT | hb_sink (nameids_to_retain) ; + auto designAxes = get_design_axes (); + + get_axis_value_offsets () | hb_map (hb_add (&(this + offsetToAxisValueOffsets))) + | hb_filter ([&] (const AxisValue& _) + { return _.keep_axis_value (designAxes, user_axes_location); }) | hb_map (&AxisValue::get_value_name_id) | hb_sink (nameids_to_retain) ; } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + STAT *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + auto designAxes = get_design_axes (); + for (unsigned i = 0; i < (unsigned)designAxisCount; i++) + if (unlikely (!c->serializer->embed (designAxes[i]))) + return_trace (false); + + if (designAxisCount) + c->serializer->check_assign (out->designAxesOffset, this->get_size (), + HB_SERIALIZE_ERROR_INT_OVERFLOW); + + unsigned count = 0; + out->offsetToAxisValueOffsets.serialize_subset (c, offsetToAxisValueOffsets, this, + axisValueCount, count, designAxes); + return_trace (c->serializer->check_assign (out->axisValueCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -381,7 +595,7 @@ struct STAT * set to zero; if designAxisCount is greater * than zero, must be greater than zero. */ HBUINT16 axisValueCount; /* The number of axis value tables. */ - NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>> + NNOffset32To<AxisValueOffsetArray> offsetToAxisValueOffsets; /* Offset in bytes from the beginning of * the STAT table to the start of the design |