diff options
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-private.hh')
-rw-r--r-- | Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-private.hh | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-private.hh index c970b89dda7..5971e9b7a3d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-private.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-private.hh @@ -35,6 +35,9 @@ * hb_set_t */ +/* TODO Keep a free-list so we can free pages that are completely zeroed. At that + * point maybe also use a sentinel value for "all-1" pages? */ + struct hb_set_t { struct page_map_t @@ -47,9 +50,8 @@ struct hb_set_t struct page_t { - inline void init (void) { - memset (&v, 0, sizeof (v)); - } + inline void init0 (void) { memset (&v, 0, sizeof (v)); } + inline void init1 (void) { memset (&v, 0xff, sizeof (v)); } inline unsigned int len (void) const { return ARRAY_LENGTH_CONST (v); } @@ -66,6 +68,24 @@ struct hb_set_t inline void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } inline bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); } + inline void add_range (hb_codepoint_t a, hb_codepoint_t b) + { + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la |= (mask (b) << 1) - mask(a); + else + { + *la |= ~(mask (a) - 1); + la++; + + memset (la, 0xff, (char *) lb - (char *) la); + + *lb |= ((mask (b) << 1) - 1); + + } + } + inline bool is_equal (const page_t *other) const { return 0 == memcmp (&v, &other->v, sizeof (v)); @@ -196,16 +216,37 @@ struct hb_set_t if (unlikely (in_error)) return; if (unlikely (g == INVALID)) return; page_t *page = page_for_insert (g); - if (!page) - return; + if (unlikely (!page)) return; page->add (g); } inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { - if (unlikely (in_error)) return; - /* TODO Speedup */ - for (unsigned int i = a; i < b + 1; i++) - add (i); + if (unlikely (in_error || a > b || a == INVALID || b == INVALID)) return; + unsigned int ma = get_major (a); + unsigned int mb = get_major (b); + if (ma == mb) + { + page_t *page = page_for_insert (a); + if (unlikely (!page)) return; + page->add_range (a, b); + } + else + { + page_t *page = page_for_insert (a); + if (unlikely (!page)) return; + page->add_range (a, major_start (ma + 1) - 1); + + for (unsigned int m = ma + 1; m < mb; m++) + { + page = page_for_insert (major_start (m)); + if (unlikely (!page)) return; + page->init1 (); + } + + page = page_for_insert (b); + if (unlikely (!page)) return; + page->add_range (major_start (mb), b); + } } inline void del (hb_codepoint_t g) { @@ -217,6 +258,7 @@ struct hb_set_t } inline void del_range (hb_codepoint_t a, hb_codepoint_t b) { + /* TODO Optimize, like add_range(). */ if (unlikely (in_error)) return; for (unsigned int i = a; i < b + 1; i++) del (i); @@ -433,7 +475,7 @@ struct hb_set_t static const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; - page_t *page_for_insert (hb_codepoint_t g) + inline page_t *page_for_insert (hb_codepoint_t g) { page_map_t map = {get_major (g), pages.len}; unsigned int i; @@ -442,13 +484,13 @@ struct hb_set_t if (!resize (pages.len + 1)) return nullptr; - pages[map.index].init (); + pages[map.index].init0 (); memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0])); page_map[i] = map; } return &pages[page_map[i].index]; } - page_t *page_for (hb_codepoint_t g) + inline page_t *page_for (hb_codepoint_t g) { page_map_t key = {get_major (g)}; const page_map_t *found = page_map.bsearch (&key); @@ -456,7 +498,7 @@ struct hb_set_t return &pages[found->index]; return nullptr; } - const page_t *page_for (hb_codepoint_t g) const + inline const page_t *page_for (hb_codepoint_t g) const { page_map_t key = {get_major (g)}; const page_map_t *found = page_map.bsearch (&key); @@ -464,9 +506,10 @@ struct hb_set_t return &pages[found->index]; return nullptr; } - 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; } + inline page_t &page_at (unsigned int i) { return pages[page_map[i].index]; } + inline const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; } + inline unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; } + inline hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; } }; |