From 2f50283cd33f20b41a9efd5e851272edacf1d8c1 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 23 Apr 2021 15:21:30 -0700 Subject: [PATCH] [subset] Begin implementing ValueRecord optimization: remove value records which have a zero value. --- src/hb-ot-layout-gpos-table.hh | 91 ++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index c806bb764..9601a9613 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -162,16 +162,40 @@ struct ValueFormat : HBUINT16 return ret; } - void serialize_copy (hb_serialize_context_t *c, const void *base, - const Value *values, const hb_map_t *layout_variation_idx_map) const + unsigned int get_effective_format (const Value *values) const + { + unsigned int format = *this; + if (format & xPlacement) should_drop (*values++, xPlacement, &format); + if (format & yPlacement) should_drop (*values++, yPlacement, &format); + if (format & xAdvance) should_drop (*values++, xAdvance, &format); + if (format & yAdvance) should_drop (*values++, yAdvance, &format); + return format; + } + + template + unsigned int get_effective_format (Iterator it) { + unsigned int new_format = 0; + + for (const hb_array_t& values : it) + new_format = new_format | get_effective_format (&values); + + return new_format; + } + + void copy_values (hb_serialize_context_t *c, + unsigned int new_format, + const void *base, + const Value *values, + const hb_map_t *layout_variation_idx_map) 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 & xPlacement) copy_value (c, new_format, xPlacement, *values++); + if (format & yPlacement) copy_value (c, new_format, xPlacement, *values++); + if (format & xAdvance) copy_value (c, new_format, xPlacement, *values++); + if (format & yAdvance) copy_value (c, new_format, xPlacement, *values++); if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); @@ -179,6 +203,16 @@ struct ValueFormat : HBUINT16 if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map); } + void copy_value (hb_serialize_context_t *c, + unsigned int new_format, + Flags flag, + Value value) const + { + // Filter by new format. + if (!(new_format & flag)) return; + c->copy (value); + } + void collect_variation_indices (hb_collect_variation_indices_context_t *c, const void *base, const hb_array_t& values) const @@ -319,6 +353,15 @@ struct ValueFormat : HBUINT16 return_trace (true); } + + private: + + void should_drop (Value value, Flags flag, unsigned int* format) const + { + if (value) return; + *format = *format & ~flag; + } + }; template @@ -755,19 +798,20 @@ struct SinglePosFormat1 template void serialize (hb_serialize_context_t *c, + ValueFormat srcFormat, const void *src, Iterator it, - ValueFormat valFormat, + ValueFormat newFormat, const hb_map_t *layout_variation_idx_map) { if (unlikely (!c->extend_min (*this))) return; if (unlikely (!c->check_assign (valueFormat, - valFormat, + newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; for (const hb_array_t& _ : + it | hb_map (hb_second)) { - valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); + srcFormat.copy_values (c, newFormat, src, &_, layout_variation_idx_map); // Only serialize the first entry in the iterator, the rest are assumed to // be the same. break; @@ -873,20 +917,21 @@ struct SinglePosFormat2 template void serialize (hb_serialize_context_t *c, + ValueFormat srcFormat, const void *src, Iterator it, - ValueFormat valFormat, + ValueFormat newFormat, const hb_map_t *layout_variation_idx_map) { auto out = c->extend_min (*this); if (unlikely (!out)) return; - if (unlikely (!c->check_assign (valueFormat, valFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; + if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return; + it | hb_map (hb_second) | hb_apply ([&] (hb_array_t _) - { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); }) + { srcFormat.copy_values (c, newFormat, src, &_, layout_variation_idx_map); }) ; auto glyphs = @@ -971,14 +1016,30 @@ struct SinglePos { if (unlikely (!c->extend_min (u.format))) return; unsigned format = 2; + ValueFormat new_format = valFormat; - if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs); + if (glyph_val_iter_pairs) + { + format = get_format (glyph_val_iter_pairs); + new_format = valFormat.get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second)); + // TODO: modify iterator to iterate over new values + } u.format = format; switch (u.format) { - case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map); + case 1: u.format1.serialize (c, + valFormat, + src, + glyph_val_iter_pairs, + new_format, + layout_variation_idx_map); return; - case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map); + case 2: u.format2.serialize (c, + valFormat, + src, + glyph_val_iter_pairs, + new_format, + layout_variation_idx_map); return; default:return; }