[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;
|
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:
|
private:
|
||||||
bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
|
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;
|
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)
|
static inline OffsetTo<Device>& get_device (Value* value)
|
||||||
{
|
{
|
||||||
return *static_cast<OffsetTo<Device> *> (value);
|
return *static_cast<OffsetTo<Device> *> (value);
|
||||||
|
@ -240,6 +277,7 @@ struct ValueFormat : HBUINT16
|
||||||
|
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
static void SinglePos_serialize (hb_serialize_context_t *c,
|
static void SinglePos_serialize (hb_serialize_context_t *c,
|
||||||
|
const void *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
ValueFormat valFormat);
|
ValueFormat valFormat);
|
||||||
|
|
||||||
|
@ -542,13 +580,19 @@ struct SinglePosFormat1
|
||||||
template<typename Iterator,
|
template<typename Iterator,
|
||||||
hb_requires (hb_is_iterator (Iterator))>
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
void serialize (hb_serialize_context_t *c,
|
void serialize (hb_serialize_context_t *c,
|
||||||
|
const void *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
ValueFormat valFormat)
|
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 (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 =
|
auto glyphs =
|
||||||
+ it
|
+ it
|
||||||
|
@ -572,7 +616,7 @@ struct SinglePosFormat1
|
||||||
;
|
;
|
||||||
|
|
||||||
bool ret = bool (it);
|
bool ret = bool (it);
|
||||||
SinglePos_serialize (c->serializer, it, valueFormat);
|
SinglePos_serialize (c->serializer, this, it, valueFormat);
|
||||||
return_trace (ret);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,14 +674,20 @@ struct SinglePosFormat2
|
||||||
template<typename Iterator,
|
template<typename Iterator,
|
||||||
hb_requires (hb_is_iterator (Iterator))>
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
void serialize (hb_serialize_context_t *c,
|
void serialize (hb_serialize_context_t *c,
|
||||||
|
const void *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
ValueFormat valFormat)
|
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 (valueFormat, valFormat))) return;
|
||||||
if (unlikely (!c->check_assign (valueCount, it.len ()))) 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 =
|
auto glyphs =
|
||||||
+ it
|
+ it
|
||||||
|
@ -668,7 +718,7 @@ struct SinglePosFormat2
|
||||||
;
|
;
|
||||||
|
|
||||||
bool ret = bool (it);
|
bool ret = bool (it);
|
||||||
SinglePos_serialize (c->serializer, it, valueFormat);
|
SinglePos_serialize (c->serializer, this, it, valueFormat);
|
||||||
return_trace (ret);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,6 +764,7 @@ struct SinglePos
|
||||||
template<typename Iterator,
|
template<typename Iterator,
|
||||||
hb_requires (hb_is_iterator (Iterator))>
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
void serialize (hb_serialize_context_t *c,
|
void serialize (hb_serialize_context_t *c,
|
||||||
|
const void *src,
|
||||||
Iterator glyph_val_iter_pairs,
|
Iterator glyph_val_iter_pairs,
|
||||||
ValueFormat valFormat)
|
ValueFormat valFormat)
|
||||||
{
|
{
|
||||||
|
@ -724,9 +775,9 @@ struct SinglePos
|
||||||
|
|
||||||
u.format = format;
|
u.format = format;
|
||||||
switch (u.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;
|
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;
|
return;
|
||||||
default:return;
|
default:return;
|
||||||
}
|
}
|
||||||
|
@ -755,9 +806,10 @@ struct SinglePos
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
static void
|
static void
|
||||||
SinglePos_serialize (hb_serialize_context_t *c,
|
SinglePos_serialize (hb_serialize_context_t *c,
|
||||||
|
const void *src,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
ValueFormat valFormat)
|
ValueFormat valFormat)
|
||||||
{ c->start_embed<SinglePos> ()->serialize (c, it, valFormat); }
|
{ c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat); }
|
||||||
|
|
||||||
|
|
||||||
struct PairValueRecord
|
struct PairValueRecord
|
||||||
|
@ -767,16 +819,28 @@ struct PairValueRecord
|
||||||
int cmp (hb_codepoint_t k) const
|
int cmp (hb_codepoint_t k) const
|
||||||
{ return secondGlyph.cmp (k); }
|
{ 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,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
unsigned length,
|
serialize_closure_t *closure) const
|
||||||
const hb_map_t &glyph_map) const
|
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
auto *out = c->start_embed (*this);
|
auto *out = c->start_embed (*this);
|
||||||
if (unlikely (!c->extend_min (out))) return_trace (false);
|
if (unlikely (!c->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
out->secondGlyph = glyph_map[secondGlyph];
|
out->secondGlyph = (*closure->glyph_map)[secondGlyph];
|
||||||
return_trace (c->copy (values, length));
|
|
||||||
|
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:
|
protected:
|
||||||
|
@ -867,12 +931,21 @@ struct PairSet
|
||||||
unsigned len2 = valueFormats[1].get_len ();
|
unsigned len2 = valueFormats[1].get_len ();
|
||||||
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
|
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;
|
const PairValueRecord *record = &firstPairValueRecord;
|
||||||
unsigned count = len, num = 0;
|
unsigned count = len, num = 0;
|
||||||
for (unsigned i = 0; i < count; i++)
|
for (unsigned i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (!glyphset.has (record->secondGlyph)) continue;
|
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);
|
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,7 +1078,7 @@ struct PairPosFormat1
|
||||||
unsigned int len2 = valueFormat[1].get_len ();
|
unsigned int len2 = valueFormat[1].get_len ();
|
||||||
PairSet::sanitize_closure_t closure =
|
PairSet::sanitize_closure_t closure =
|
||||||
{
|
{
|
||||||
this,
|
&pairSet,
|
||||||
valueFormat,
|
valueFormat,
|
||||||
len1,
|
len1,
|
||||||
1 + len1 + len2
|
1 + len1 + len2
|
||||||
|
@ -1099,7 +1172,8 @@ struct PairPosFormat2
|
||||||
out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map);
|
out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map);
|
||||||
out->class2Count = klass2_map.get_population ();
|
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_range ((unsigned) class1Count)
|
||||||
| hb_filter (klass1_map)
|
| hb_filter (klass1_map)
|
||||||
|
@ -1109,9 +1183,9 @@ struct PairPosFormat2
|
||||||
| hb_filter (klass2_map)
|
| hb_filter (klass2_map)
|
||||||
| hb_apply ([&] (const unsigned class2_idx)
|
| hb_apply ([&] (const unsigned class2_idx)
|
||||||
{
|
{
|
||||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_len;
|
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||||
for (unsigned i = 0; i < record_len; i++)
|
valueFormat1.serialize_copy (c->serializer, this, out, &values[idx]);
|
||||||
c->serializer->copy (values[idx+i]);
|
valueFormat2.serialize_copy (c->serializer, this, out, &values[idx + len1]);
|
||||||
})
|
})
|
||||||
;
|
;
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue