Add set iterator

This commit is contained in:
Behdad Esfahbod 2012-05-25 14:17:54 -04:00
parent 62c3e111fc
commit 29ce446d31
4 changed files with 44 additions and 8 deletions

View File

@ -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]; }

View File

@ -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);
}

View File

@ -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? */

View File

@ -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;