diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh index 3f8675434..6e3e70c75 100644 --- a/src/hb-machinery.hh +++ b/src/hb-machinery.hh @@ -111,9 +111,13 @@ static inline Type& StructAfter(TObject &X) static const unsigned int min_size = (size) #define DEFINE_SIZE_ARRAY(size, array) \ - DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof (array[0])); \ DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ - static const unsigned int min_size = (size) + static const unsigned int min_size = (size); \ + +#define DEFINE_SIZE_ARRAY_SIZED(size, array) \ + DEFINE_SIZE_ARRAY(size, array); \ + inline unsigned int get_size (void) const { return (size - array[0].min_size + array.get_size ()); } #define DEFINE_SIZE_ARRAY2(size, array1, array2) \ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ @@ -508,7 +512,7 @@ struct hb_serialize_context_t unsigned int size = obj.get_size (); Type *ret = this->allocate_size (size); if (unlikely (!ret)) return nullptr; - memcpy (ret, obj, size); + memcpy (ret, &obj, size); return ret; } diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index d43dcac7e..24fafd9e9 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -247,6 +247,19 @@ struct OffsetTo : Offset return * (Type *) Offset::serialize (c, base); } + template + inline void serialize_subset (hb_subset_context_t *c, const T &src, const void *base) + { + if (&src == &Null(T)) + { + this->set (0); + return; + } + serialize (c->serializer, base); + if (!src.subset (c)) + this->set (0); + } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -405,7 +418,6 @@ struct ArrayOf if (unlikely (!c->extend (*this))) return_trace (false); return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, Supplier &items, unsigned int items_len) @@ -506,6 +518,17 @@ struct OffsetListOf : OffsetArrayOf return this+this->arrayZ[i]; } + inline bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + struct OffsetListOf *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + unsigned int count = this->len; + for (unsigned int i = 0; i < count; i++) + out->arrayZ[i].serialize_subset (c, (*this)[i], this); + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 887f27e9e..a51a6c7e9 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -97,15 +97,14 @@ struct Record }; template -struct RecordArrayOf : SortedArrayOf > { +struct RecordArrayOf : SortedArrayOf > +{ + inline const OffsetTo& get_offset (unsigned int i) const + { return (*this)[i].offset; } + inline OffsetTo& get_offset (unsigned int i) + { return (*this)[i].offset; } inline const Tag& get_tag (unsigned int i) const - { - /* We cheat slightly and don't define separate Null objects - * for Record types. Instead, we return the correct Null(Tag) - * here. */ - if (unlikely (i >= this->len)) return Null(Tag); - return (*this)[i].tag; - } + { return (*this)[i].tag; } inline unsigned int get_tags (unsigned int start_offset, unsigned int *record_count /* IN/OUT */, hb_tag_t *record_tags /* OUT */) const @@ -136,7 +135,18 @@ template struct RecordListOf : RecordArrayOf { inline const Type& operator [] (unsigned int i) const - { return this+RecordArrayOf::operator [](i).offset; } + { return this+this->get_offset (i); } + + inline bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + struct RecordListOf *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + unsigned int count = this->len; + for (unsigned int i = 0; i < count; i++) + out->get_offset (i).serialize_subset (c, (*this)[i], this); + return_trace (true); + } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -224,6 +234,12 @@ struct LangSys return reqFeatureIndex;; } + inline bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + return_trace (c->serializer->embed (*this)); + } + inline bool sanitize (hb_sanitize_context_t *c, const Record::sanitize_closure_t * = nullptr) const { @@ -238,7 +254,7 @@ struct LangSys * = 0xFFFFu */ IndexArray featureIndex; /* Array of indices into the FeatureList */ public: - DEFINE_SIZE_ARRAY (6, featureIndex); + DEFINE_SIZE_ARRAY_SIZED (6, featureIndex); }; DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys); @@ -263,6 +279,18 @@ struct Script inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; } inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } + inline bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + struct Script *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + out->defaultLangSys.serialize_subset (c, this+defaultLangSys, this); + unsigned int count = langSys.len; + for (unsigned int i = 0; i < count; i++) + out->langSys.arrayZ[i].offset.serialize_subset (c, this+langSys[i].offset, this); + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c, const Record