[instance] update FeatureList with variations
This commit is contained in:
parent
8f3a7017c3
commit
b706c6f77e
|
@ -353,6 +353,31 @@ struct subset_record_array_t
|
||||||
const void *base;
|
const void *base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename OutputArray, typename Arg>
|
||||||
|
struct subset_record_array_arg_t
|
||||||
|
{
|
||||||
|
subset_record_array_arg_t (hb_subset_layout_context_t *c_, OutputArray* out_,
|
||||||
|
const void *base_,
|
||||||
|
Arg &&arg_) : subset_layout_context (c_),
|
||||||
|
out (out_), base (base_), arg (arg_) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void
|
||||||
|
operator () (T&& record)
|
||||||
|
{
|
||||||
|
auto snap = subset_layout_context->subset_context->serializer->snapshot ();
|
||||||
|
bool ret = record.subset (subset_layout_context, base, arg);
|
||||||
|
if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
|
||||||
|
else out->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
hb_subset_layout_context_t *subset_layout_context;
|
||||||
|
OutputArray *out;
|
||||||
|
const void *base;
|
||||||
|
Arg &&arg;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper to subset a RecordList/record array. Subsets each Record in the array and
|
* Helper to subset a RecordList/record array. Subsets each Record in the array and
|
||||||
* discards the record if the subset operation returns false.
|
* discards the record if the subset operation returns false.
|
||||||
|
@ -364,6 +389,13 @@ struct
|
||||||
operator () (hb_subset_layout_context_t *c, OutputArray* out,
|
operator () (hb_subset_layout_context_t *c, OutputArray* out,
|
||||||
const void *base) const
|
const void *base) const
|
||||||
{ return subset_record_array_t<OutputArray> (c, out, base); }
|
{ return subset_record_array_t<OutputArray> (c, out, base); }
|
||||||
|
|
||||||
|
/* Variant with one extra argument passed to subset */
|
||||||
|
template<typename OutputArray, typename Arg>
|
||||||
|
subset_record_array_arg_t<OutputArray, Arg>
|
||||||
|
operator () (hb_subset_layout_context_t *c, OutputArray* out,
|
||||||
|
const void *base, Arg &&arg) const
|
||||||
|
{ return subset_record_array_arg_t<OutputArray, Arg> (c, out, base, arg); }
|
||||||
}
|
}
|
||||||
HB_FUNCOBJ (subset_record_array);
|
HB_FUNCOBJ (subset_record_array);
|
||||||
|
|
||||||
|
@ -460,94 +492,6 @@ struct IndexArray : Array16Of<Index>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Record_sanitize_closure_t {
|
|
||||||
hb_tag_t tag;
|
|
||||||
const void *list_base;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
struct Record
|
|
||||||
{
|
|
||||||
int cmp (hb_tag_t a) const { return tag.cmp (a); }
|
|
||||||
|
|
||||||
bool subset (hb_subset_layout_context_t *c, const void *base) const
|
|
||||||
{
|
|
||||||
TRACE_SUBSET (this);
|
|
||||||
auto *out = c->subset_context->serializer->embed (this);
|
|
||||||
if (unlikely (!out)) return_trace (false);
|
|
||||||
bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag);
|
|
||||||
return_trace (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
|
||||||
{
|
|
||||||
TRACE_SANITIZE (this);
|
|
||||||
const Record_sanitize_closure_t closure = {tag, base};
|
|
||||||
return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
|
|
||||||
}
|
|
||||||
|
|
||||||
Tag tag; /* 4-byte Tag identifier */
|
|
||||||
Offset16To<Type>
|
|
||||||
offset; /* Offset from beginning of object holding
|
|
||||||
* the Record */
|
|
||||||
public:
|
|
||||||
DEFINE_SIZE_STATIC (6);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
struct RecordArrayOf : SortedArray16Of<Record<Type>>
|
|
||||||
{
|
|
||||||
const Offset16To<Type>& get_offset (unsigned int i) const
|
|
||||||
{ return (*this)[i].offset; }
|
|
||||||
Offset16To<Type>& get_offset (unsigned int i)
|
|
||||||
{ return (*this)[i].offset; }
|
|
||||||
const Tag& get_tag (unsigned int i) const
|
|
||||||
{ return (*this)[i].tag; }
|
|
||||||
unsigned int get_tags (unsigned int start_offset,
|
|
||||||
unsigned int *record_count /* IN/OUT */,
|
|
||||||
hb_tag_t *record_tags /* OUT */) const
|
|
||||||
{
|
|
||||||
if (record_count)
|
|
||||||
{
|
|
||||||
+ this->sub_array (start_offset, record_count)
|
|
||||||
| hb_map (&Record<Type>::tag)
|
|
||||||
| hb_sink (hb_array (record_tags, *record_count))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return this->len;
|
|
||||||
}
|
|
||||||
bool find_index (hb_tag_t tag, unsigned int *index) const
|
|
||||||
{
|
|
||||||
return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
struct RecordListOf : RecordArrayOf<Type>
|
|
||||||
{
|
|
||||||
const Type& operator [] (unsigned int i) const
|
|
||||||
{ return this+this->get_offset (i); }
|
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c,
|
|
||||||
hb_subset_layout_context_t *l) const
|
|
||||||
{
|
|
||||||
TRACE_SUBSET (this);
|
|
||||||
auto *out = c->serializer->start_embed (*this);
|
|
||||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
|
||||||
|
|
||||||
+ this->iter ()
|
|
||||||
| hb_apply (subset_record_array (l, out, this))
|
|
||||||
;
|
|
||||||
return_trace (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
|
||||||
{
|
|
||||||
TRACE_SANITIZE (this);
|
|
||||||
return_trace (RecordArrayOf<Type>::sanitize (c, this));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
|
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
|
||||||
struct FeatureParamsSize
|
struct FeatureParamsSize
|
||||||
{
|
{
|
||||||
|
@ -830,6 +774,10 @@ struct FeatureParams
|
||||||
DEFINE_SIZE_MIN (0);
|
DEFINE_SIZE_MIN (0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Record_sanitize_closure_t {
|
||||||
|
hb_tag_t tag;
|
||||||
|
const void *list_base;
|
||||||
|
};
|
||||||
|
|
||||||
struct Feature
|
struct Feature
|
||||||
{
|
{
|
||||||
|
@ -926,6 +874,103 @@ struct Feature
|
||||||
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
|
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct Record
|
||||||
|
{
|
||||||
|
int cmp (hb_tag_t a) const { return tag.cmp (a); }
|
||||||
|
|
||||||
|
bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->subset_context->serializer->embed (this);
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
if (!f_sub)
|
||||||
|
return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag));
|
||||||
|
|
||||||
|
const Feature& f = *reinterpret_cast<const Feature *> (f_sub);
|
||||||
|
auto *s = c->subset_context->serializer;
|
||||||
|
s->push ();
|
||||||
|
|
||||||
|
out->offset = 0;
|
||||||
|
bool ret = f.subset (c->subset_context, c, &tag);
|
||||||
|
if (ret)
|
||||||
|
s->add_link (out->offset, s->pop_pack ());
|
||||||
|
else
|
||||||
|
s->pop_discard ();
|
||||||
|
|
||||||
|
return_trace (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
const Record_sanitize_closure_t closure = {tag, base};
|
||||||
|
return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag tag; /* 4-byte Tag identifier */
|
||||||
|
Offset16To<Type>
|
||||||
|
offset; /* Offset from beginning of object holding
|
||||||
|
* the Record */
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_STATIC (6);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct RecordArrayOf : SortedArray16Of<Record<Type>>
|
||||||
|
{
|
||||||
|
const Offset16To<Type>& get_offset (unsigned int i) const
|
||||||
|
{ return (*this)[i].offset; }
|
||||||
|
Offset16To<Type>& get_offset (unsigned int i)
|
||||||
|
{ return (*this)[i].offset; }
|
||||||
|
const Tag& get_tag (unsigned int i) const
|
||||||
|
{ return (*this)[i].tag; }
|
||||||
|
unsigned int get_tags (unsigned int start_offset,
|
||||||
|
unsigned int *record_count /* IN/OUT */,
|
||||||
|
hb_tag_t *record_tags /* OUT */) const
|
||||||
|
{
|
||||||
|
if (record_count)
|
||||||
|
{
|
||||||
|
+ this->sub_array (start_offset, record_count)
|
||||||
|
| hb_map (&Record<Type>::tag)
|
||||||
|
| hb_sink (hb_array (record_tags, *record_count))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return this->len;
|
||||||
|
}
|
||||||
|
bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||||
|
{
|
||||||
|
return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct RecordListOf : RecordArrayOf<Type>
|
||||||
|
{
|
||||||
|
const Type& operator [] (unsigned int i) const
|
||||||
|
{ return this+this->get_offset (i); }
|
||||||
|
|
||||||
|
bool subset (hb_subset_context_t *c,
|
||||||
|
hb_subset_layout_context_t *l) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
|
+ this->iter ()
|
||||||
|
| hb_apply (subset_record_array (l, out, this))
|
||||||
|
;
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SANITIZE (this);
|
||||||
|
return_trace (RecordArrayOf<Type>::sanitize (c, this));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct RecordListOfFeature : RecordListOf<Feature>
|
struct RecordListOfFeature : RecordListOf<Feature>
|
||||||
{
|
{
|
||||||
bool subset (hb_subset_context_t *c,
|
bool subset (hb_subset_context_t *c,
|
||||||
|
@ -936,11 +981,20 @@ struct RecordListOfFeature : RecordListOf<Feature>
|
||||||
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
unsigned count = this->len;
|
unsigned count = this->len;
|
||||||
|
|
||||||
+ hb_zip (*this, hb_range (count))
|
+ hb_zip (*this, hb_range (count))
|
||||||
| hb_filter (l->feature_index_map, hb_second)
|
| hb_filter (l->feature_index_map, hb_second)
|
||||||
| hb_map (hb_first)
|
| hb_apply ([l, out, this] (const hb_pair_t<const Record<Feature>&, unsigned>& _)
|
||||||
| hb_apply (subset_record_array (l, out, this))
|
{
|
||||||
|
const Feature *f_sub = nullptr;
|
||||||
|
const Feature **f = nullptr;
|
||||||
|
if (l->feature_substitutes_map->has (_.second, &f))
|
||||||
|
f_sub = *f;
|
||||||
|
|
||||||
|
subset_record_array (l, out, this, f_sub) (_.first);
|
||||||
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue