From 5af5a565938505a4a549a5cee49b62ee03d73a18 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 30 May 2022 08:32:50 -0600 Subject: [PATCH] [VarStore] Implement writing 32bit var-store Untested. Finishes fixing https://github.com/harfbuzz/harfbuzz/issues/2965 --- src/hb-ot-layout-common.hh | 49 +++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index bd5762e79..f9a11657d 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2771,44 +2771,65 @@ struct VarData if (unlikely (!c->extend_min (this))) return_trace (false); itemCount = inner_map.get_next_value (); - /* Optimize short count */ - unsigned short ri_count = src->regionIndices.len; - enum delta_size_t { kZero=0, kByte, kShort }; + /* Optimize word count */ + unsigned ri_count = src->regionIndices.len; + enum delta_size_t { kZero=0, kNonWord, kWord }; hb_vector_t delta_sz; hb_vector_t ri_map; /* maps old index to new index */ delta_sz.resize (ri_count); ri_map.resize (ri_count); - unsigned int new_short_count = 0; + unsigned int new_word_count = 0; 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++) { delta_sz[r] = kZero; for (unsigned int i = 0; i < inner_map.get_next_value (); i++) { unsigned int old = inner_map.backward (i); - int16_t delta = src->get_item_delta (old, r); - if (delta < -128 || 127 < delta) + int32_t delta = src->get_item_delta (old, r); + if (delta < min_threshold || max_threshold < delta) { - delta_sz[r] = kShort; - new_short_count++; + delta_sz[r] = kWord; + new_word_count++; break; } 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; for (r = 0; r < ri_count; 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++; } - /* XXX TODO Support serializing 32bit VarStore. */ - wordSizeCount = new_short_count; + wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0); regionIndices.len = new_ri_count;