Add set iterator
This commit is contained in:
parent
62c3e111fc
commit
29ce446d31
|
@ -32,6 +32,7 @@
|
|||
#include "hb-object-private.hh"
|
||||
|
||||
|
||||
/* TODO Make this faster and memmory efficient. */
|
||||
|
||||
struct _hb_set_t
|
||||
{
|
||||
|
@ -51,6 +52,7 @@ struct _hb_set_t
|
|||
}
|
||||
inline void add (hb_codepoint_t g)
|
||||
{
|
||||
if (unlikely (g == SENTINEL)) return;
|
||||
if (unlikely (g > MAX_G)) return;
|
||||
elt (g) |= mask (g);
|
||||
}
|
||||
|
@ -107,6 +109,23 @@ struct _hb_set_t
|
|||
for (unsigned int i = 0; i < ELTS; i++)
|
||||
elts[i] ^= other->elts[i];
|
||||
}
|
||||
inline bool next (hb_codepoint_t *codepoint)
|
||||
{
|
||||
if (unlikely (*codepoint == SENTINEL)) {
|
||||
hb_codepoint_t i = get_min ();
|
||||
if (i != SENTINEL) {
|
||||
*codepoint = i;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++)
|
||||
if (has (i)) {
|
||||
*codepoint = i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline hb_codepoint_t get_min (void) const
|
||||
{
|
||||
for (unsigned int i = 0; i < ELTS; i++)
|
||||
|
@ -114,7 +133,7 @@ struct _hb_set_t
|
|||
for (unsigned int j = 0; i < BITS; j++)
|
||||
if (elts[i] & (1 << j))
|
||||
return i * BITS + j;
|
||||
return 0;
|
||||
return SENTINEL;
|
||||
}
|
||||
inline hb_codepoint_t get_max (void) const
|
||||
{
|
||||
|
@ -123,15 +142,16 @@ struct _hb_set_t
|
|||
for (unsigned int j = BITS; j; j--)
|
||||
if (elts[i - 1] & (1 << (j - 1)))
|
||||
return (i - 1) * BITS + (j - 1);
|
||||
return 0;
|
||||
return SENTINEL;
|
||||
}
|
||||
|
||||
typedef uint32_t elt_t;
|
||||
static const unsigned int MAX_G = 65536 - 1;
|
||||
static const unsigned int MAX_G = 65536 - 1; /* XXX Fix this... */
|
||||
static const unsigned int SHIFT = 5;
|
||||
static const unsigned int BITS = (1 << SHIFT);
|
||||
static const unsigned int MASK = BITS - 1;
|
||||
static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS;
|
||||
static const hb_codepoint_t SENTINEL = (hb_codepoint_t) -1;
|
||||
|
||||
elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
|
||||
elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
|
||||
|
|
|
@ -182,3 +182,10 @@ hb_set_max (hb_set_t *set)
|
|||
{
|
||||
return set->get_max ();
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_set_next (hb_set_t *set,
|
||||
hb_codepoint_t *codepoint)
|
||||
{
|
||||
return set->next (codepoint);
|
||||
}
|
||||
|
|
11
src/hb-set.h
11
src/hb-set.h
|
@ -77,6 +77,8 @@ hb_bool_t
|
|||
hb_set_has (hb_set_t *set,
|
||||
hb_codepoint_t codepoint);
|
||||
|
||||
/* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1
|
||||
* which we will use as a sentinel. */
|
||||
void
|
||||
hb_set_add (hb_set_t *set,
|
||||
hb_codepoint_t codepoint);
|
||||
|
@ -109,14 +111,19 @@ void
|
|||
hb_set_symmetric_difference (hb_set_t *set,
|
||||
hb_set_t *other);
|
||||
|
||||
/* Undefined if set empty */
|
||||
/* Returns -1 if set empty. */
|
||||
hb_codepoint_t
|
||||
hb_set_min (hb_set_t *set);
|
||||
|
||||
/* Undefined if set empty */
|
||||
/* Returns -1 if set empty. */
|
||||
hb_codepoint_t
|
||||
hb_set_max (hb_set_t *set);
|
||||
|
||||
/* Pass -1 in to get started. */
|
||||
hb_bool_t
|
||||
hb_set_next (hb_set_t *set,
|
||||
hb_codepoint_t *codepoint);
|
||||
|
||||
/* TODO: Add faster iteration API? */
|
||||
|
||||
|
||||
|
|
|
@ -66,11 +66,13 @@ struct shape_closure_consumer_t : option_group_t
|
|||
|
||||
hb_set_clear (glyphs);
|
||||
shaper.shape_closure (text, text_len, font, buffer, glyphs);
|
||||
|
||||
if (hb_set_empty (glyphs))
|
||||
return;
|
||||
|
||||
/* Print it out! */
|
||||
hb_codepoint_t start = hb_set_min (glyphs);
|
||||
hb_codepoint_t end = 1 + hb_set_max (glyphs);
|
||||
bool first = true;
|
||||
for (hb_codepoint_t i = start; i < end; i++)
|
||||
for (hb_codepoint_t i = -1; hb_set_next (glyphs, &i);)
|
||||
if (hb_set_has (glyphs, i)) {
|
||||
if (first)
|
||||
first = false;
|
||||
|
|
Loading…
Reference in New Issue