diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index a56b8b43b..ac96c75ac 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -195,7 +195,6 @@ HB_OT_VAR_NO_AXIS_INDEX hb_ot_var_axis_t hb_ot_var_find_axis hb_ot_var_get_axes -hb_set_invert hb_unicode_eastasian_width_func_t hb_unicode_eastasian_width hb_unicode_funcs_set_eastasian_width_func @@ -614,6 +613,7 @@ hb_set_get_population hb_set_get_user_data hb_set_has hb_set_intersect +hb_set_invert hb_set_is_empty hb_set_is_equal hb_set_is_subset diff --git a/src/Makefile.sources b/src/Makefile.sources index 04b9cbe22..28fbf2c52 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -21,6 +21,7 @@ HB_BASE_sources = \ hb-bimap.hh \ hb-bit-page.hh \ hb-bit-set.hh \ + hb-bit-set-invertible.hh \ hb-blob.cc \ hb-blob.hh \ hb-buffer-serialize.cc \ diff --git a/src/hb-bit-set-invertible.hh b/src/hb-bit-set-invertible.hh new file mode 100644 index 000000000..a3212b4e2 --- /dev/null +++ b/src/hb-bit-set-invertible.hh @@ -0,0 +1,168 @@ +/* + * Copyright © 2012,2017 Google, Inc. + * Copyright © 2021 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_SET_INVERTIBLE_HH +#define HB_BIT_SET_INVERTIBLE_HH + +#include "hb.hh" +#include "hb-bit-set.hh" + + +struct hb_bit_set_invertible_t +{ + hb_bit_set_t s; + bool inverted; + + hb_bit_set_invertible_t () { init (); } + ~hb_bit_set_invertible_t () { fini (); } + + void init () { s.init (); inverted = false; } + void fini () { s.fini (); } + void err () { s.err (); } + bool in_error () const { return s.in_error (); } + explicit operator bool () const { return !is_empty (); } + + void reset () { s.reset (); inverted = false; } + void clear () { s.clear (); inverted = false; } + void invert () { if (!s.in_error ()) inverted = !inverted; } + + bool is_empty () const { return inverted ? /*XXX*/false : s.is_empty (); } + + void add (hb_codepoint_t g) { inverted ? s.del (g) : s.add (g); } + bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return inverted ? (s.del_range (a, b), true) : s.add_range (a, b); } + + template + void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { /*XXX(inverted)*/s.add_array (array, count, stride); } + template + void add_array (const hb_array_t& arr) { add_array (&arr, arr.len ()); } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template + bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { return /*XXX(inverted)*/s.add_sorted_array (array, count, stride); } + template + bool add_sorted_array (const hb_sorted_array_t& arr) { return add_sorted_array (&arr, arr.len ()); } + + void del (hb_codepoint_t g) { inverted ? s.add (g) : s.del (g); } + void del_range (hb_codepoint_t a, hb_codepoint_t b) { inverted ? (void) s.add_range (a, b) : s.del_range (a, b); } + + bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; } + + /* Has interface. */ + static constexpr bool SENTINEL = false; + typedef bool value_t; + value_t operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + /* Predicate. */ + bool operator () (hb_codepoint_t k) const { return has (k); } + + /* Sink interface. */ + hb_bit_set_invertible_t& operator << (hb_codepoint_t v) + { add (v); return *this; } + hb_bit_set_invertible_t& operator << (const hb_pair_t& range) + { add_range (range.first, range.second); return *this; } + + bool intersects (hb_codepoint_t first, hb_codepoint_t last) const + { return /*XXX(inverted)*/s.intersects (first, last); } + + void set (const hb_bit_set_invertible_t &other) { s.set (other.s); inverted = other.inverted; } + + bool is_equal (const hb_bit_set_invertible_t &other) const + { return inverted == other.inverted /*XXX*/ && s.is_equal (other.s); } + + bool is_subset (const hb_bit_set_invertible_t &larger_set) const + { + if (inverted && !larger_set.inverted) return false; /*XXX*/ + if (!inverted && larger_set.inverted) + { + /* TODO(iter) Write as hb_all dagger. */ + for (auto c: s) + if (larger_set.s.has (c)) + return false; + return true; + } + /* inverted == larger_set.inverted */ + return inverted ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s); + } + + template + void process (const Op& op, const hb_bit_set_invertible_t &other) + { s.process (op, other.s); } + + /*XXX(inverted)*/ + void union_ (const hb_bit_set_invertible_t &other) { process (hb_bitwise_or, other); } + /*XXX(inverted)*/ + void intersect (const hb_bit_set_invertible_t &other) { process (hb_bitwise_and, other); } + /*XXX(inverted)*/ + void subtract (const hb_bit_set_invertible_t &other) { process (hb_bitwise_sub, other); } + /*XXX(inverted)*/ + void symmetric_difference (const hb_bit_set_invertible_t &other) { process (hb_bitwise_xor, other); } + + bool next (hb_codepoint_t *codepoint) const + { + /*XXX(inverted)*/ + return s.next (codepoint); + } + bool previous (hb_codepoint_t *codepoint) const + { + /*XXX(inverted)*/ + return s.previous (codepoint); + } + bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + /*XXX(inverted)*/ + return s.next_range (first, last); + } + bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + /*XXX(inverted)*/ + return s.previous_range (first, last); + } + + unsigned int get_population () const + { return inverted ? INVALID - s.get_population () : s.get_population (); } + + hb_codepoint_t get_min () const + { return /*XXX(inverted)*/s.get_min (); } + hb_codepoint_t get_max () const + { return /*XXX(inverted)*/s.get_max (); } + + static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID; + + /* + * Iterator implementation. + */ + /*XXX(inverted)*/ + using iter_t = hb_bit_set_t::iter_t; + iter_t iter () const { return iter_t (this->s); } + operator iter_t () const { return iter (); } +}; + + +#endif /* HB_BIT_SET_INVERTIBLE_HH */ diff --git a/src/hb-bit-set.hh b/src/hb-bit-set.hh index 8e386b91e..3b5b473c6 100644 --- a/src/hb-bit-set.hh +++ b/src/hb-bit-set.hh @@ -35,14 +35,8 @@ struct hb_bit_set_t { - hb_bit_set_t () - { - init (); - } - ~hb_bit_set_t () - { - fini (); - } + hb_bit_set_t () { init (); } + ~hb_bit_set_t () { fini (); } void init () { @@ -558,6 +552,11 @@ struct hb_bit_set_t resize (newCount); } + void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); } + void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); } + void subtract (const hb_bit_set_t &other) { process (hb_bitwise_sub, other); } + void symmetric_difference (const hb_bit_set_t &other) { process (hb_bitwise_xor, other); } + bool next (hb_codepoint_t *codepoint) const { // TODO: this should be merged with prev() as both implementations diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h index 5f1912578..a130d77f7 100644 --- a/src/hb-deprecated.h +++ b/src/hb-deprecated.h @@ -107,9 +107,6 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_func_t func, void *user_data, hb_destroy_func_t destroy); -HB_EXTERN HB_DEPRECATED void -hb_set_invert (hb_set_t *set); - /** * hb_unicode_eastasian_width_func_t: * @ufuncs: A Unicode-functions structure diff --git a/src/hb-set.cc b/src/hb-set.cc index 17bbdc055..eb6f41e11 100644 --- a/src/hb-set.cc +++ b/src/hb-set.cc @@ -432,22 +432,19 @@ hb_set_symmetric_difference (hb_set_t *set, set->symmetric_difference (*other); } -#ifndef HB_DISABLE_DEPRECATED /** * hb_set_invert: * @set: A set * * Inverts the contents of @set. * - * Since: 0.9.10 - * - * Deprecated: 1.6.1 + * Since: 3.0.0 **/ void -hb_set_invert (hb_set_t *set HB_UNUSED) +hb_set_invert (hb_set_t *set) { + set->invert (); } -#endif /** * hb_set_get_population: diff --git a/src/hb-set.h b/src/hb-set.h index 7f2112e69..423225bf9 100644 --- a/src/hb-set.h +++ b/src/hb-set.h @@ -94,6 +94,9 @@ hb_set_clear (hb_set_t *set); HB_EXTERN hb_bool_t hb_set_is_empty (const hb_set_t *set); +HB_EXTERN void +hb_set_invert (hb_set_t *set); + HB_EXTERN hb_bool_t hb_set_has (const hb_set_t *set, hb_codepoint_t codepoint); diff --git a/src/hb-set.hh b/src/hb-set.hh index 221a4b337..95132200a 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -29,28 +29,25 @@ #define HB_SET_HH #include "hb.hh" -#include "hb-bit-set.hh" +#include "hb-bit-set-invertible.hh" template -struct hb_intset_t +struct hb_sparseset_t { hb_object_header_t header; impl_t s; - void init_shallow () - { - s.init (); - } + hb_sparseset_t () { init (); } + ~hb_sparseset_t () { fini (); } + + void init_shallow () { s.init (); } void init () { hb_object_init (this); init_shallow (); } - void fini_shallow () - { - s.fini (); - } + void fini_shallow () { s.fini (); } void fini () { hb_object_fini (this); @@ -63,9 +60,8 @@ struct hb_intset_t bool in_error () const { return s.in_error (); } void reset () { s.reset (); } - void clear () { s.clear (); } - + void invert () { s.invert (); } bool is_empty () const { return s.is_empty (); } void add (hb_codepoint_t g) { s.add (g); } @@ -99,24 +95,24 @@ struct hb_intset_t bool operator () (hb_codepoint_t k) const { return has (k); } /* Sink interface. */ - hb_intset_t& operator << (hb_codepoint_t v) + hb_sparseset_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_intset_t& operator << (const hb_pair_t& range) + hb_sparseset_t& operator << (const hb_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const { return s.intersects (first, last); } - void set (const hb_intset_t &other) { s.set (other.s); } + void set (const hb_sparseset_t &other) { s.set (other.s); } - bool is_equal (const hb_intset_t &other) const { return s.is_equal (other.s); } + bool is_equal (const hb_sparseset_t &other) const { return s.is_equal (other.s); } - bool is_subset (const hb_intset_t &larger_set) const { return s.is_subset (larger_set.s); } + bool is_subset (const hb_sparseset_t &larger_set) const { return s.is_subset (larger_set.s); } - void union_ (const hb_intset_t &other) { s.process (hb_bitwise_or, other.s); } - void intersect (const hb_intset_t &other) { s.process (hb_bitwise_and, other.s); } - void subtract (const hb_intset_t &other) { s.process (hb_bitwise_sub, other.s); } - void symmetric_difference (const hb_intset_t &other) { s.process (hb_bitwise_xor, other.s); } + void union_ (const hb_sparseset_t &other) { s.union_ (other.s); } + void intersect (const hb_sparseset_t &other) { s.intersect (other.s); } + void subtract (const hb_sparseset_t &other) { s.subtract (other.s); } + void symmetric_difference (const hb_sparseset_t &other) { s.symmetric_difference (other.s); } bool next (hb_codepoint_t *codepoint) const { return s.next (codepoint); } bool previous (hb_codepoint_t *codepoint) const { return s.previous (codepoint); } @@ -139,7 +135,7 @@ struct hb_intset_t operator iter_t () const { return iter (); } }; -struct hb_set_t : hb_intset_t {}; +struct hb_set_t : hb_sparseset_t {}; static_assert (hb_set_t::INVALID == HB_SET_VALUE_INVALID, "");