diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh index df96b9903..9d8ba4a5a 100644 --- a/src/hb-set-private.hh +++ b/src/hb-set-private.hh @@ -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]; } diff --git a/src/hb-set.cc b/src/hb-set.cc index 7103bcd1f..504538602 100644 --- a/src/hb-set.cc +++ b/src/hb-set.cc @@ -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); +} diff --git a/src/hb-set.h b/src/hb-set.h index 38bb84b5f..97e68e48e 100644 --- a/src/hb-set.h +++ b/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? */ diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc index afd88ae28..55481c686 100644 --- a/util/hb-ot-shape-closure.cc +++ b/util/hb-ot-shape-closure.cc @@ -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;