Merge pull request #3606 from harfbuzz/32bit-varstore

32bit varstore
This commit is contained in:
Behdad Esfahbod 2022-05-31 11:22:32 +01:00 committed by GitHub
commit f8b26f43ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 86 additions and 27 deletions

View File

@ -2689,7 +2689,7 @@ struct VarData
{ return regionIndices.len; } { return regionIndices.len; }
unsigned int get_row_size () const unsigned int get_row_size () const
{ return shortCount + regionIndices.len; } { return (wordCount () + regionIndices.len) * (longWords () ? 2 : 1); }
unsigned int get_size () const unsigned int get_size () const
{ return min_size { return min_size
@ -2706,7 +2706,10 @@ struct VarData
return 0.; return 0.;
unsigned int count = regionIndices.len; unsigned int count = regionIndices.len;
unsigned int scount = shortCount; bool is_long = longWords ();
unsigned word_count = wordCount ();
unsigned int scount = is_long ? count - word_count : word_count;
unsigned int lcount = is_long ? word_count : 0;
const HBUINT8 *bytes = get_delta_bytes (); const HBUINT8 *bytes = get_delta_bytes ();
const HBUINT8 *row = bytes + inner * (scount + count); const HBUINT8 *row = bytes + inner * (scount + count);
@ -2714,7 +2717,13 @@ struct VarData
float delta = 0.; float delta = 0.;
unsigned int i = 0; unsigned int i = 0;
const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row); const HBINT16 *lcursor = reinterpret_cast<const HBINT16 *> (row);
for (; i < lcount; i++)
{
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
delta += scalar * *lcursor++;
}
const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
for (; i < scount; i++) for (; i < scount; i++)
{ {
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache); float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
@ -2747,7 +2756,7 @@ struct VarData
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && return_trace (c->check_struct (this) &&
regionIndices.sanitize (c) && regionIndices.sanitize (c) &&
shortCount <= regionIndices.len && wordCount () <= regionIndices.len &&
c->check_range (get_delta_bytes (), c->check_range (get_delta_bytes (),
itemCount, itemCount,
get_row_size ())); get_row_size ()));
@ -2762,43 +2771,66 @@ 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++;
} }
shortCount = new_short_count; wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
regionIndices.len = new_ri_count; regionIndices.len = new_ri_count;
if (unlikely (!c->extend (this))) return_trace (false); if (unlikely (!c->extend (this))) return_trace (false);
@ -2838,28 +2870,55 @@ struct VarData
HBUINT8 *get_delta_bytes () HBUINT8 *get_delta_bytes ()
{ return &StructAfter<HBUINT8> (regionIndices); } { return &StructAfter<HBUINT8> (regionIndices); }
int16_t get_item_delta (unsigned int item, unsigned int region) const int32_t get_item_delta (unsigned int item, unsigned int region) const
{ {
if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0; if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size (); const HBINT8 *p = (const HBINT8 *) get_delta_bytes () + item * get_row_size ();
if (region < shortCount) unsigned word_count = wordCount ();
return ((const HBINT16 *)p)[region]; bool is_long = longWords ();
if (is_long)
{
if (region < word_count)
return ((const HBINT32 *) p)[region];
else else
return (p + HBINT16::static_size * shortCount)[region - shortCount]; return ((const HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count];
}
else
{
if (region < word_count)
return ((const HBINT16 *) p)[region];
else
return (p + HBINT16::static_size * word_count)[region - word_count];
}
} }
void set_item_delta (unsigned int item, unsigned int region, int16_t delta) void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
{ {
HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size (); HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
if (region < shortCount) unsigned word_count = wordCount ();
((HBINT16 *)p)[region] = delta; bool is_long = longWords ();
if (is_long)
{
if (region < word_count)
((HBINT32 *) p)[region] = delta;
else else
(p + HBINT16::static_size * shortCount)[region - shortCount] = delta; ((HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count] = delta;
} }
else
{
if (region < word_count)
((HBINT16 *) p)[region] = delta;
else
(p + HBINT16::static_size * word_count)[region - word_count] = delta;
}
}
bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
protected: protected:
HBUINT16 itemCount; HBUINT16 itemCount;
HBUINT16 shortCount; HBUINT16 wordSizeCount;
Array16Of<HBUINT16> regionIndices; Array16Of<HBUINT16> regionIndices;
/*UnsizedArrayOf<HBUINT8>bytesX;*/ /*UnsizedArrayOf<HBUINT8>bytesX;*/
public: public: