[subset] implement value record optimization for PairPosFormat2.

This commit is contained in:
Garret Rieger 2021-04-23 17:06:06 -07:00
parent badb8e409b
commit f9fbe4817e
1 changed files with 40 additions and 19 deletions

View File

@ -1029,7 +1029,6 @@ struct SinglePos
u.format = format;
switch (u.format) {
// TODO(grieger): pass reference to src lookup instead of separate src + format
case 1: u.format1.serialize (c,
src,
glyph_val_iter_pairs,
@ -1517,9 +1516,6 @@ struct PairPosFormat2
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
// TODO(grieger): compute new formats
out->valueFormat1 = valueFormat1;
out->valueFormat2 = valueFormat2;
hb_map_t klass1_map;
out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, &(this + coverage));
@ -1532,21 +1528,22 @@ struct PairPosFormat2
unsigned len1 = valueFormat1.get_len ();
unsigned len2 = valueFormat2.get_len ();
+ hb_range ((unsigned) class1Count)
| hb_filter (klass1_map)
| hb_apply ([&] (const unsigned class1_idx)
{
+ hb_range ((unsigned) class2Count)
| hb_filter (klass2_map)
| hb_apply ([&] (const unsigned class2_idx)
{
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
valueFormat1.copy_values (c->serializer, valueFormat1, this, &values[idx], c->plan->layout_variation_idx_map);
valueFormat2.copy_values (c->serializer, valueFormat2, this, &values[idx + len1], c->plan->layout_variation_idx_map);
})
;
})
;
hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
if (c->plan->drop_hints)
newFormats = compute_effective_value_formats (klass1_map, klass2_map);
out->valueFormat1 = newFormats.first;
out->valueFormat2 = newFormats.second;
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
{
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
{
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
}
}
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
@ -1561,6 +1558,30 @@ struct PairPosFormat2
return_trace (out->class1Count && out->class2Count && bool (it));
}
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
const hb_map_t& klass2_map) const
{
unsigned len1 = valueFormat1.get_len ();
unsigned len2 = valueFormat2.get_len ();
unsigned format1 = 0;
unsigned format2 = 0;
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
{
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
{
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
}
}
return hb_pair (format1, format2);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);