From c828d7bf76dd039be1775edff1d798dbcc10708b Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Wed, 15 Jan 2020 15:32:44 -0800 Subject: [PATCH] [subset] fixed GPOS device table sanitize & serialize (#2087) --- src/hb-ot-layout-gpos-table.hh | 112 +++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 19 deletions(-) diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 32c9c5e5c..c469366d3 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -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& get_device (Value* value) { return *static_cast *> (value); @@ -240,6 +277,7 @@ struct ValueFormat : HBUINT16 template static void SinglePos_serialize (hb_serialize_context_t *c, + const void *src, Iterator it, ValueFormat valFormat); @@ -542,13 +580,19 @@ struct SinglePosFormat1 template 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 _) + { 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 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 _) + { 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 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 static void SinglePos_serialize (hb_serialize_context_t *c, + const void *src, Iterator it, ValueFormat valFormat) -{ c->start_embed ()->serialize (c, it, valFormat); } +{ c->start_embed ()->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 (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]); }) ; })