diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh | 127 |
1 files changed, 115 insertions, 12 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh index c21778d88e..fcaff9f3be 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh @@ -35,13 +35,22 @@ struct hb_bit_set_t { - hb_bit_set_t () { init (); } - ~hb_bit_set_t () { fini (); } + hb_bit_set_t () = default; + ~hb_bit_set_t () = default; hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); } - void operator= (const hb_bit_set_t& other) { set (other); } - // TODO Add move construtor/assign - // TODO Add constructor for Iterator; with specialization for (sorted) vector / array? + hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); } + hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; } + hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; } + friend void swap (hb_bit_set_t &a, hb_bit_set_t &b) + { + if (likely (!a.successful || !b.successful)) + return; + hb_swap (a.population, b.population); + hb_swap (a.last_page_lookup, b.last_page_lookup); + hb_swap (a.page_map, b.page_map); + hb_swap (a.pages, b.pages); + } void init () { @@ -67,9 +76,9 @@ struct hb_bit_set_t uint32_t index; }; - bool successful; /* Allocations successful */ - mutable unsigned int population; - mutable unsigned int last_page_lookup; + bool successful = true; /* Allocations successful */ + mutable unsigned int population = 0; + mutable unsigned int last_page_lookup = 0; hb_sorted_vector_t<page_map_t> page_map; hb_vector_t<page_t> pages; @@ -194,7 +203,7 @@ struct hb_bit_set_t bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T)) { if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */ - if (!count) return true; + if (unlikely (!count)) return true; dirty (); hb_codepoint_t g = *array; hb_codepoint_t last_g = g; @@ -213,7 +222,7 @@ struct hb_bit_set_t if (v || page) /* The v check is to optimize out the page check if v is true. */ page->add (g); - array = (const T *) ((const char *) array + stride); + array = &StructAtOffsetUnaligned<T> (array, stride); count--; } while (count && (g = *array, g < end)); @@ -691,6 +700,99 @@ struct hb_bit_set_t return true; } + unsigned int next_many (hb_codepoint_t codepoint, + hb_codepoint_t *out, + unsigned int size) const + { + // By default, start at the first bit of the first page of values. + unsigned int start_page = 0; + unsigned int start_page_value = 0; + if (unlikely (codepoint != INVALID)) + { + const auto* page_map_array = page_map.arrayZ; + unsigned int major = get_major (codepoint); + unsigned int i = last_page_lookup; + if (unlikely (i >= page_map.length || page_map_array[i].major != major)) + { + page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (i >= page_map.length) + return 0; // codepoint is greater than our max element. + } + start_page = i; + start_page_value = page_remainder (codepoint + 1); + if (unlikely (start_page_value == 0)) + { + // The export-after value was last in the page. Start on next page. + start_page++; + start_page_value = 0; + } + } + + unsigned int initial_size = size; + for (unsigned int i = start_page; i < page_map.length && size; i++) + { + uint32_t base = major_start (page_map[i].major); + unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size); + out += n; + size -= n; + start_page_value = 0; + } + return initial_size - size; + } + + unsigned int next_many_inverted (hb_codepoint_t codepoint, + hb_codepoint_t *out, + unsigned int size) const + { + unsigned int initial_size = size; + // By default, start at the first bit of the first page of values. + unsigned int start_page = 0; + unsigned int start_page_value = 0; + if (unlikely (codepoint != INVALID)) + { + const auto* page_map_array = page_map.arrayZ; + unsigned int major = get_major (codepoint); + unsigned int i = last_page_lookup; + if (unlikely (i >= page_map.length || page_map_array[i].major != major)) + { + page_map.bfind(major, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (unlikely (i >= page_map.length)) + { + // codepoint is greater than our max element. + while (++codepoint != INVALID && size) + { + *out++ = codepoint; + size--; + } + return initial_size - size; + } + } + start_page = i; + start_page_value = page_remainder (codepoint + 1); + if (unlikely (start_page_value == 0)) + { + // The export-after value was last in the page. Start on next page. + start_page++; + start_page_value = 0; + } + } + + hb_codepoint_t next_value = codepoint + 1; + for (unsigned int i=start_page; i<page_map.length && size; i++) + { + uint32_t base = major_start (page_map[i].major); + unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value); + out += n; + size -= n; + start_page_value = 0; + } + while (next_value < HB_SET_VALUE_INVALID && size) { + *out++ = next_value++; + size--; + } + return initial_size - size; + } + bool has_population () const { return population != UINT_MAX; } unsigned int get_population () const { @@ -800,8 +902,9 @@ struct hb_bit_set_t } page_t &page_at (unsigned int i) { return pages[page_map[i].index]; } const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; } - unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; } - hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; } + unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; } + unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; } + hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; } }; |