[subset] fixed GPOS device table sanitize & serialize (#2087)
This commit is contained in:
parent
e565d1f9bc
commit
c828d7bf76
|
@ -155,6 +155,22 @@ struct ValueFormat : HBUINT16
|
|||
return ret;
|
||||
}
|
||||
|
||||
void serialize_copy (hb_serialize_context_t *c, const void *src_base, const void *dst_base, const Value *values) const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
if (!format) return;
|
||||
|
||||
if (format & xPlacement) c->copy (*values++);
|
||||
if (format & yPlacement) c->copy (*values++);
|
||||
if (format & xAdvance) c->copy (*values++);
|
||||
if (format & yAdvance) c->copy (*values++);
|
||||
|
||||
if (format & xPlaDevice) copy_device (c, src_base, dst_base, values++);
|
||||
if (format & yPlaDevice) copy_device (c, src_base, dst_base, values++);
|
||||
if (format & xAdvDevice) copy_device (c, src_base, dst_base, values++);
|
||||
if (format & yAdvDevice) copy_device (c, src_base, dst_base, values++);
|
||||
}
|
||||
|
||||
private:
|
||||
bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
|
||||
{
|
||||
|
@ -173,6 +189,27 @@ struct ValueFormat : HBUINT16
|
|||
return true;
|
||||
}
|
||||
|
||||
bool copy_device (hb_serialize_context_t *c, const void *src_base, const void *dst_base, const Value *src_value) const
|
||||
{
|
||||
Value *dst_value = c->copy (*src_value);
|
||||
|
||||
if (!dst_value) return false;
|
||||
if (*dst_value == 0) return true;
|
||||
|
||||
*dst_value = 0;
|
||||
c->push ();
|
||||
if ((src_base + get_device (src_value)).copy (c))
|
||||
{
|
||||
c->add_link (*dst_value, c->pop_pack (), dst_base);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->pop_discard ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline OffsetTo<Device>& get_device (Value* value)
|
||||
{
|
||||
return *static_cast<OffsetTo<Device> *> (value);
|
||||
|
@ -240,6 +277,7 @@ struct ValueFormat : HBUINT16
|
|||
|
||||
template<typename Iterator>
|
||||
static void SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const void *src,
|
||||
Iterator it,
|
||||
ValueFormat valFormat);
|
||||
|
||||
|
@ -542,13 +580,19 @@ struct SinglePosFormat1
|
|||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const void *src,
|
||||
Iterator it,
|
||||
ValueFormat valFormat)
|
||||
{
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
auto out = c->extend_min (*this);
|
||||
if (unlikely (!out)) return;
|
||||
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
|
||||
|
||||
c->copy_all (hb_second (*it));
|
||||
+ it
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (hb_array_t<const Value> _)
|
||||
{ valFormat.serialize_copy (c, src, out, &_); })
|
||||
;
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
|
@ -572,7 +616,7 @@ struct SinglePosFormat1
|
|||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, it, valueFormat);
|
||||
SinglePos_serialize (c->serializer, this, it, valueFormat);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
|
@ -630,14 +674,20 @@ struct SinglePosFormat2
|
|||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const void *src,
|
||||
Iterator it,
|
||||
ValueFormat valFormat)
|
||||
{
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
auto out = c->extend_min (*this);
|
||||
if (unlikely (!out)) return;
|
||||
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
|
||||
if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
|
||||
|
||||
for (auto iter : it) c->copy_all (iter.second);
|
||||
+ it
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (hb_array_t<const Value> _)
|
||||
{ valFormat.serialize_copy (c, src, out, &_); })
|
||||
;
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
|
@ -668,7 +718,7 @@ struct SinglePosFormat2
|
|||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, it, valueFormat);
|
||||
SinglePos_serialize (c->serializer, this, it, valueFormat);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
|
@ -714,6 +764,7 @@ struct SinglePos
|
|||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const void *src,
|
||||
Iterator glyph_val_iter_pairs,
|
||||
ValueFormat valFormat)
|
||||
{
|
||||
|
@ -724,9 +775,9 @@ struct SinglePos
|
|||
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
case 1: u.format1.serialize (c, glyph_val_iter_pairs, valFormat);
|
||||
case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat);
|
||||
return;
|
||||
case 2: u.format2.serialize (c, glyph_val_iter_pairs, valFormat);
|
||||
case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat);
|
||||
return;
|
||||
default:return;
|
||||
}
|
||||
|
@ -755,9 +806,10 @@ struct SinglePos
|
|||
template<typename Iterator>
|
||||
static void
|
||||
SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const void *src,
|
||||
Iterator it,
|
||||
ValueFormat valFormat)
|
||||
{ c->start_embed<SinglePos> ()->serialize (c, it, valFormat); }
|
||||
{ c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat); }
|
||||
|
||||
|
||||
struct PairValueRecord
|
||||
|
@ -767,16 +819,28 @@ struct PairValueRecord
|
|||
int cmp (hb_codepoint_t k) const
|
||||
{ return secondGlyph.cmp (k); }
|
||||
|
||||
struct serialize_closure_t
|
||||
{
|
||||
const void *src_base;
|
||||
void *dst_base;
|
||||
const ValueFormat *valueFormats;
|
||||
unsigned len1; /* valueFormats[0].get_len() */
|
||||
const hb_map_t *glyph_map;
|
||||
};
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned length,
|
||||
const hb_map_t &glyph_map) const
|
||||
serialize_closure_t *closure) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->start_embed (*this);
|
||||
if (unlikely (!c->extend_min (out))) return_trace (false);
|
||||
|
||||
out->secondGlyph = glyph_map[secondGlyph];
|
||||
return_trace (c->copy (values, length));
|
||||
out->secondGlyph = (*closure->glyph_map)[secondGlyph];
|
||||
|
||||
closure->valueFormats[0].serialize_copy (c, closure->src_base, closure->dst_base, &values[0]);
|
||||
closure->valueFormats[1].serialize_copy (c, closure->src_base, closure->dst_base, &values[closure->len1]);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -867,12 +931,21 @@ struct PairSet
|
|||
unsigned len2 = valueFormats[1].get_len ();
|
||||
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
|
||||
|
||||
PairValueRecord::serialize_closure_t closure =
|
||||
{
|
||||
this,
|
||||
out,
|
||||
valueFormats,
|
||||
len1,
|
||||
&glyph_map
|
||||
};
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned count = len, num = 0;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (!glyphset.has (record->secondGlyph)) continue;
|
||||
if (record->serialize (c->serializer, len1 + len2, glyph_map)) num++;
|
||||
if (record->serialize (c->serializer, &closure)) num++;
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
|
||||
|
@ -1005,7 +1078,7 @@ struct PairPosFormat1
|
|||
unsigned int len2 = valueFormat[1].get_len ();
|
||||
PairSet::sanitize_closure_t closure =
|
||||
{
|
||||
this,
|
||||
&pairSet,
|
||||
valueFormat,
|
||||
len1,
|
||||
1 + len1 + len2
|
||||
|
@ -1099,7 +1172,8 @@ struct PairPosFormat2
|
|||
out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map);
|
||||
out->class2Count = klass2_map.get_population ();
|
||||
|
||||
unsigned record_len = valueFormat1.get_len () + valueFormat2.get_len ();
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
|
||||
+ hb_range ((unsigned) class1Count)
|
||||
| hb_filter (klass1_map)
|
||||
|
@ -1109,9 +1183,9 @@ struct PairPosFormat2
|
|||
| hb_filter (klass2_map)
|
||||
| hb_apply ([&] (const unsigned class2_idx)
|
||||
{
|
||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_len;
|
||||
for (unsigned i = 0; i < record_len; i++)
|
||||
c->serializer->copy (values[idx+i]);
|
||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||
valueFormat1.serialize_copy (c->serializer, this, out, &values[idx]);
|
||||
valueFormat2.serialize_copy (c->serializer, this, out, &values[idx + len1]);
|
||||
})
|
||||
;
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue