[subset] Towards GSUB/GPOS subsetting

Add subset() call for GSUBGPOS struct and its dependencies.
Not hooked up anywhere.
This commit is contained in:
Behdad Esfahbod 2018-09-01 18:34:50 -07:00
parent 6803ed8674
commit bfa72a9a72
6 changed files with 145 additions and 33 deletions

View File

@ -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<Type> (size);
if (unlikely (!ret)) return nullptr;
memcpy (ret, obj, size);
memcpy (ret, &obj, size);
return ret;
}

View File

@ -247,6 +247,19 @@ struct OffsetTo : Offset<OffsetType>
return * (Type *) Offset<OffsetType>::serialize (c, base);
}
template <typename T>
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<Type> &items,
unsigned int items_len)
@ -506,6 +518,17 @@ struct OffsetListOf : OffsetArrayOf<Type>
return this+this->arrayZ[i];
}
inline bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
struct OffsetListOf<Type> *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);

View File

@ -97,15 +97,14 @@ struct Record
};
template <typename Type>
struct RecordArrayOf : SortedArrayOf<Record<Type> > {
struct RecordArrayOf : SortedArrayOf<Record<Type> >
{
inline const OffsetTo<Type>& get_offset (unsigned int i) const
{ return (*this)[i].offset; }
inline OffsetTo<Type>& 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 <typename Type>
struct RecordListOf : RecordArrayOf<Type>
{
inline const Type& operator [] (unsigned int i) const
{ return this+RecordArrayOf<Type>::operator [](i).offset; }
{ return this+this->get_offset (i); }
inline bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
struct RecordListOf<Type> *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<LangSys>::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<Script>::sanitize_closure_t * = nullptr) const
{
@ -278,7 +306,7 @@ struct Script
langSys; /* Array of LangSysRecords--listed
* alphabetically by LangSysTag */
public:
DEFINE_SIZE_ARRAY (4, langSys);
DEFINE_SIZE_ARRAY_SIZED (4, langSys);
};
typedef RecordListOf<Script> ScriptList;
@ -516,6 +544,15 @@ struct Feature
inline const FeatureParams &get_feature_params (void) const
{ return this+featureParams; }
inline bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
struct Feature *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
out->featureParams.set (0); /* TODO(subset) FeatureParams. */
return_trace (true);
}
inline bool sanitize (hb_sanitize_context_t *c,
const Record<Feature>::sanitize_closure_t *closure = nullptr) const
{
@ -567,7 +604,7 @@ struct Feature
* if not required */
IndexArray lookupIndex; /* Array of LookupList indices */
public:
DEFINE_SIZE_ARRAY (4, lookupIndex);
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
};
typedef RecordListOf<Feature> FeatureList;
@ -666,6 +703,17 @@ struct Lookup
return_trace (true);
}
inline bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
struct Lookup *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
unsigned int count = subTable.len;
for (unsigned int i = 0; i < count; i++)
out->subTable[i].set (0); /* To be filled out by SubstLookup/PosLookup. */
return_trace (true);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -1629,6 +1677,12 @@ struct FeatureVariations
return (this+record.substitutions).find_substitute (feature_index);
}
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
{
TRACE_SANITIZE (this);
@ -1642,7 +1696,7 @@ struct FeatureVariations
LArrayOf<FeatureVariationRecord>
varRecords;
public:
DEFINE_SIZE_ARRAY (8, varRecords);
DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
};

View File

@ -387,19 +387,6 @@ struct GDEF
inline const VariationStore &get_var_store (void) const
{ return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (version.sanitize (c) &&
likely (version.major == 1) &&
glyphClassDef.sanitize (c, this) &&
attachList.sanitize (c, this) &&
ligCaretList.sanitize (c, this) &&
markAttachClassDef.sanitize (c, this) &&
(version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
(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. */
@ -434,6 +421,26 @@ struct GDEF
const GDEF *table;
};
inline unsigned int get_size (void) const
{
return min_size +
(version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
(version.to_int () >= 0x00010003u ? varStore.static_size : 0);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (version.sanitize (c) &&
likely (version.major == 1) &&
glyphClassDef.sanitize (c, this) &&
attachList.sanitize (c, this) &&
ligCaretList.sanitize (c, this) &&
markAttachClassDef.sanitize (c, this) &&
(version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
(version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
}
protected:
FixedVersion<>version; /* Version of the GDEF table--currently
* 0x00010003u */

View File

@ -1308,15 +1308,20 @@ struct GSUB : GSUBGPOS
inline const SubstLookup& get_lookup (unsigned int i) const
{ return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
inline bool subset (hb_subset_context_t *c)
inline bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
struct GSUB *out = c->serializer->start_embed<GSUB> ();
//XXX if (unlikely (!GSUBGPOS::subset (c))) return_trace (false);
if (unlikely (!GSUBGPOS::subset (c))) return_trace (false);
/* TODO Replace following with c->iter_copy_and_subset()ish. */
unsigned int count = get_lookup_count ();
LookupList &outLookupList = out+out->lookupList;
for (unsigned int i = 0; i < count; i++)
//XXX if (unlikely (!outLookupList.arrayZ[i].subset (c, get_lookup (i), &outLookupList)))
return_trace (false);
return_trace (true);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -2370,6 +2370,25 @@ struct GSUBGPOS
return get_feature (feature_index);
}
inline bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
struct GSUBGPOS *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
out->scriptList.serialize_subset (c, this+scriptList, this);
out->featureList.serialize_subset (c, this+featureList, this);
out->lookupList.serialize_subset (c, this+lookupList, this);
if (version.to_int () >= 0x00010001u)
out->featureVars.serialize_subset (c, this+featureVars, this);
return_trace (true);
}
inline unsigned int get_size (void) const
{
return min_size +
(version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);