diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 3f835f13d..fb99ec3e0 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -507,7 +507,7 @@ struct Feature { return this+featureParams; } inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t *closure) const + const Record::sanitize_closure_t *closure = NULL) const { TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c)))) @@ -1333,6 +1333,172 @@ struct VariationStore DEFINE_SIZE_ARRAY (8, dataSets); }; +/* + * Feature Variations + */ + +struct ConditionFormat1 +{ + friend struct Condition; + + private: + inline bool evaluate (int *coords, unsigned int coord_len) const + { + int coord = axisIndex < coord_len ? coords[axisIndex] : 0; + return filterRangeMinValue <= coord && coord <= filterRangeMaxValue; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + USHORT format; /* Format identifier--format = 1 */ + USHORT axisIndex; + F2DOT14 filterRangeMinValue; + F2DOT14 filterRangeMaxValue; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct Condition +{ + inline bool evaluate (int *coords, unsigned int coord_len) const + { + switch (u.format) { + case 1: return u.format1.evaluate (coords, coord_len); + default:return false; + } + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { + case 1: return_trace (u.format1.sanitize (c)); + default:return_trace (true); + } + } + + protected: + union { + USHORT format; /* Format identifier */ + ConditionFormat1 format1; + } u; + public: + DEFINE_SIZE_UNION (2, format); +}; + +struct ConditionSet +{ + inline bool evaluate (int *coords, unsigned int coord_len) const + { + unsigned int count = conditions.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+conditions.array[i]).evaluate (coords, coord_len)) + return false; + return true; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, this)); + } + + protected: + OffsetArrayOf conditions; + public: + DEFINE_SIZE_ARRAY (2, conditions); +}; + +struct FeatureTableSubstitutionRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && feature.sanitize (c, this)); + } + + protected: + USHORT featureIndex; + OffsetTo feature; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct FeatureTableSubstitution +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + substitutions.sanitize (c, this)); + } + + protected: + FixedVersion<> version; /* Version--0x00010000u */ + OffsetArrayOf + substitutions; + public: + DEFINE_SIZE_ARRAY (6, substitutions); +}; + +struct FeatureVariationRecord +{ + friend struct FeatureVariations; + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, base) && + substitutions.sanitize (c, base)); + } + + protected: + OffsetTo + conditions; + OffsetTo + substitutions; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct FeatureVariations +{ + inline const FeatureTableSubstitution & + get_substitutions (int *coords, unsigned int coord_len) const + { + unsigned int count = varRecords.len; + for (unsigned int i = 0; i < count; i++) + { + const FeatureVariationRecord &record = varRecords.array[i]; + if ((this+record.conditions).evaluate (coords, coord_len)) + return (this+record.substitutions); + } + return Null(FeatureTableSubstitution); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + varRecords.sanitize (c, this)); + } + + protected: + FixedVersion<> version; /* Version--0x00010000u */ + ArrayOf + varRecords; + public: + DEFINE_SIZE_ARRAY (8, varRecords); +}; + /* * Device Tables diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index d85140e27..b70cbb7a3 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -397,7 +397,6 @@ struct GDEF (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); } - /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing * glyph class and other bits, and high 8-bit gthe mark attachment type (if any). * Not to be confused with lookup_props which is very similar. */ diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 0ced5d03e..5c9fc29ca 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1518,8 +1518,6 @@ struct GPOS : GSUBGPOS const OffsetTo &list = CastR > (lookupList); return_trace (list.sanitize (c, this)); } - public: - DEFINE_SIZE_STATIC (10); }; diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 22031f43c..6658a2cd9 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -1273,8 +1273,6 @@ struct GSUB : GSUBGPOS const OffsetTo &list = CastR > (lookupList); return_trace (list.sanitize (c, this)); } - public: - DEFINE_SIZE_STATIC (10); }; diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 5cb6ba7c3..490b91e1b 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -2271,6 +2271,11 @@ struct GSUBGPOS inline const Lookup& get_lookup (unsigned int i) const { return (this+lookupList)[i]; } + inline const FeatureTableSubstitution & + get_feature_substitutions (int *coords, unsigned int coord_len) const + { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations)) + .get_substitutions (coords, coord_len); } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -2278,7 +2283,8 @@ struct GSUBGPOS likely (version.major == 1) && scriptList.sanitize (c, this) && featureList.sanitize (c, this) && - lookupList.sanitize (c, this)); + lookupList.sanitize (c, this) && + (version.to_int () < 0x00010001u || featureVars.sanitize (c, this))); } protected: @@ -2290,8 +2296,13 @@ struct GSUBGPOS featureList; /* FeatureList table */ OffsetTo lookupList; /* LookupList table */ + OffsetTo + featureVars; /* Offset to Feature Variations + table--from beginning of table + * (may be NULL). Introduced + * in version 0x00010001. */ public: - DEFINE_SIZE_STATIC (10); + DEFINE_SIZE_MIN (10); };