summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh127
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; }
};