[subset] Begin implementing ValueRecord optimization:

remove value records which have a zero value.
This commit is contained in:
Garret Rieger 2021-04-23 15:21:30 -07:00
parent 5df7c668ba
commit 2f50283cd3
1 changed files with 76 additions and 15 deletions

View File

@ -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<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
unsigned int get_effective_format (Iterator it) {
unsigned int new_format = 0;
for (const hb_array_t<const Value>& 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<const Value>& 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<typename Iterator>
@ -755,19 +798,20 @@ struct SinglePosFormat1
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
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<const Value>& _ : + 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<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
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<const Value> _)
{ 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;
}