[VarStore] Implement writing 32bit var-store

Untested.

Finishes fixing https://github.com/harfbuzz/harfbuzz/issues/2965
This commit is contained in:
Behdad Esfahbod 2022-05-30 08:32:50 -06:00
parent 75112098ac
commit 5af5a56593
1 changed files with 35 additions and 14 deletions

View File

@ -2771,44 +2771,65 @@ struct VarData
if (unlikely (!c->extend_min (this))) return_trace (false); if (unlikely (!c->extend_min (this))) return_trace (false);
itemCount = inner_map.get_next_value (); itemCount = inner_map.get_next_value ();
/* Optimize short count */ /* Optimize word count */
unsigned short ri_count = src->regionIndices.len; unsigned ri_count = src->regionIndices.len;
enum delta_size_t { kZero=0, kByte, kShort }; enum delta_size_t { kZero=0, kNonWord, kWord };
hb_vector_t<delta_size_t> delta_sz; hb_vector_t<delta_size_t> delta_sz;
hb_vector_t<unsigned int> ri_map; /* maps old index to new index */ hb_vector_t<unsigned int> ri_map; /* maps old index to new index */
delta_sz.resize (ri_count); delta_sz.resize (ri_count);
ri_map.resize (ri_count); ri_map.resize (ri_count);
unsigned int new_short_count = 0; unsigned int new_word_count = 0;
unsigned int r; unsigned int r;
bool has_long = false;
if (src->longWords ())
{
for (r = 0; r < ri_count; r++)
{
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
{
unsigned int old = inner_map.backward (i);
int32_t delta = src->get_item_delta (old, r);
if (delta < -65536 || 65535 < delta)
{
has_long = true;
break;
}
}
}
}
signed min_threshold = has_long ? -65536 : -128;
signed max_threshold = has_long ? +65535 : +127;
for (r = 0; r < ri_count; r++) for (r = 0; r < ri_count; r++)
{ {
delta_sz[r] = kZero; delta_sz[r] = kZero;
for (unsigned int i = 0; i < inner_map.get_next_value (); i++) for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
{ {
unsigned int old = inner_map.backward (i); unsigned int old = inner_map.backward (i);
int16_t delta = src->get_item_delta (old, r); int32_t delta = src->get_item_delta (old, r);
if (delta < -128 || 127 < delta) if (delta < min_threshold || max_threshold < delta)
{ {
delta_sz[r] = kShort; delta_sz[r] = kWord;
new_short_count++; new_word_count++;
break; break;
} }
else if (delta != 0) else if (delta != 0)
delta_sz[r] = kByte; delta_sz[r] = kNonWord;
} }
} }
unsigned int short_index = 0;
unsigned int byte_index = new_short_count; unsigned int word_index = 0;
unsigned int non_word_index = new_word_count;
unsigned int new_ri_count = 0; unsigned int new_ri_count = 0;
for (r = 0; r < ri_count; r++) for (r = 0; r < ri_count; r++)
if (delta_sz[r]) if (delta_sz[r])
{ {
ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++; ri_map[r] = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
new_ri_count++; new_ri_count++;
} }
/* XXX TODO Support serializing 32bit VarStore. */ wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
wordSizeCount = new_short_count;
regionIndices.len = new_ri_count; regionIndices.len = new_ri_count;