comparison mupdf-source/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*
2 * Copyright © 2012,2017 Google, Inc.
3 * Copyright © 2021 Behdad Esfahbod
4 *
5 * This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Google Author(s): Behdad Esfahbod
26 */
27
28 #ifndef HB_BIT_SET_INVERTIBLE_HH
29 #define HB_BIT_SET_INVERTIBLE_HH
30
31 #include "hb.hh"
32 #include "hb-bit-set.hh"
33
34
35 struct hb_bit_set_invertible_t
36 {
37 hb_bit_set_t s;
38 bool inverted = false;
39
40 hb_bit_set_invertible_t () = default;
41 hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default;
42 hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) : hb_bit_set_invertible_t () { hb_swap (*this, other); }
43 hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
44 hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) { hb_swap (*this, other); return *this; }
45 friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
46 {
47 if (likely (!a.s.successful || !b.s.successful))
48 return;
49 hb_swap (a.inverted, b.inverted);
50 hb_swap (a.s, b.s);
51 }
52
53 void init () { s.init (); inverted = false; }
54 void fini () { s.fini (); }
55 void err () { s.err (); }
56 bool in_error () const { return s.in_error (); }
57 explicit operator bool () const { return !is_empty (); }
58
59 void alloc (unsigned sz) { s.alloc (sz); }
60 void reset ()
61 {
62 s.reset ();
63 inverted = false;
64 }
65 void clear ()
66 {
67 s.clear ();
68 if (likely (s.successful))
69 inverted = false;
70 }
71 void invert ()
72 {
73 if (likely (s.successful))
74 inverted = !inverted;
75 }
76
77 bool is_empty () const
78 {
79 hb_codepoint_t v = INVALID;
80 next (&v);
81 return v == INVALID;
82 }
83 uint32_t hash () const { return s.hash () ^ (uint32_t) inverted; }
84
85 hb_codepoint_t get_min () const
86 {
87 hb_codepoint_t v = INVALID;
88 next (&v);
89 return v;
90 }
91 hb_codepoint_t get_max () const
92 {
93 hb_codepoint_t v = INVALID;
94 previous (&v);
95 return v;
96 }
97 unsigned int get_population () const
98 { return inverted ? INVALID - s.get_population () : s.get_population (); }
99
100
101 void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
102 bool add_range (hb_codepoint_t a, hb_codepoint_t b)
103 { return unlikely (inverted) ? ((void) s.del_range (a, b), true) : s.add_range (a, b); }
104
105 template <typename T>
106 void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
107 { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); }
108 template <typename T>
109 void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
110
111 /* Might return false if array looks unsorted.
112 * Used for faster rejection of corrupt data. */
113 template <typename T>
114 bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
115 { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); }
116 template <typename T>
117 bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
118
119 void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); }
120 void del_range (hb_codepoint_t a, hb_codepoint_t b)
121 { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
122
123 bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
124
125 /* Has interface. */
126 bool operator [] (hb_codepoint_t k) const { return get (k); }
127 bool has (hb_codepoint_t k) const { return (*this)[k]; }
128 /* Predicate. */
129 bool operator () (hb_codepoint_t k) const { return has (k); }
130
131 /* Sink interface. */
132 hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
133 { add (v); return *this; }
134 hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
135 { add_range (range.first, range.second); return *this; }
136
137 bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
138 {
139 hb_codepoint_t c = first - 1;
140 return next (&c) && c <= last;
141 }
142
143 void set (const hb_bit_set_invertible_t &other)
144 {
145 s.set (other.s);
146 if (likely (s.successful))
147 inverted = other.inverted;
148 }
149
150 bool is_equal (const hb_bit_set_invertible_t &other) const
151 {
152 if (likely (inverted == other.inverted))
153 return s.is_equal (other.s);
154 else
155 {
156 /* TODO Add iter_ranges() and use here. */
157 auto it1 = iter ();
158 auto it2 = other.iter ();
159 return hb_all (+ hb_zip (it1, it2)
160 | hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; }));
161 }
162 }
163
164 bool is_subset (const hb_bit_set_invertible_t &larger_set) const
165 {
166 if (unlikely (inverted != larger_set.inverted))
167 return hb_all (hb_iter (s) | hb_map (larger_set.s));
168 else
169 return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s);
170 }
171
172 protected:
173 template <typename Op>
174 void process (const Op& op, const hb_bit_set_invertible_t &other)
175 { s.process (op, other.s); }
176 public:
177 void union_ (const hb_bit_set_invertible_t &other)
178 {
179 if (likely (inverted == other.inverted))
180 {
181 if (unlikely (inverted))
182 process (hb_bitwise_and, other);
183 else
184 process (hb_bitwise_or, other); /* Main branch. */
185 }
186 else
187 {
188 if (unlikely (inverted))
189 process (hb_bitwise_gt, other);
190 else
191 process (hb_bitwise_lt, other);
192 }
193 if (likely (s.successful))
194 inverted = inverted || other.inverted;
195 }
196 void intersect (const hb_bit_set_invertible_t &other)
197 {
198 if (likely (inverted == other.inverted))
199 {
200 if (unlikely (inverted))
201 process (hb_bitwise_or, other);
202 else
203 process (hb_bitwise_and, other); /* Main branch. */
204 }
205 else
206 {
207 if (unlikely (inverted))
208 process (hb_bitwise_lt, other);
209 else
210 process (hb_bitwise_gt, other);
211 }
212 if (likely (s.successful))
213 inverted = inverted && other.inverted;
214 }
215 void subtract (const hb_bit_set_invertible_t &other)
216 {
217 if (likely (inverted == other.inverted))
218 {
219 if (unlikely (inverted))
220 process (hb_bitwise_lt, other);
221 else
222 process (hb_bitwise_gt, other); /* Main branch. */
223 }
224 else
225 {
226 if (unlikely (inverted))
227 process (hb_bitwise_or, other);
228 else
229 process (hb_bitwise_and, other);
230 }
231 if (likely (s.successful))
232 inverted = inverted && !other.inverted;
233 }
234 void symmetric_difference (const hb_bit_set_invertible_t &other)
235 {
236 process (hb_bitwise_xor, other);
237 if (likely (s.successful))
238 inverted = inverted ^ other.inverted;
239 }
240
241 bool next (hb_codepoint_t *codepoint) const
242 {
243 if (likely (!inverted))
244 return s.next (codepoint);
245
246 auto old = *codepoint;
247 if (unlikely (old + 1 == INVALID))
248 {
249 *codepoint = INVALID;
250 return false;
251 }
252
253 auto v = old;
254 s.next (&v);
255 if (old + 1 < v)
256 {
257 *codepoint = old + 1;
258 return true;
259 }
260
261 v = old;
262 s.next_range (&old, &v);
263
264 *codepoint = v + 1;
265 return *codepoint != INVALID;
266 }
267 bool previous (hb_codepoint_t *codepoint) const
268 {
269 if (likely (!inverted))
270 return s.previous (codepoint);
271
272 auto old = *codepoint;
273 if (unlikely (old - 1 == INVALID))
274 {
275 *codepoint = INVALID;
276 return false;
277 }
278
279 auto v = old;
280 s.previous (&v);
281
282 if (old - 1 > v || v == INVALID)
283 {
284 *codepoint = old - 1;
285 return true;
286 }
287
288 v = old;
289 s.previous_range (&v, &old);
290
291 *codepoint = v - 1;
292 return *codepoint != INVALID;
293 }
294 bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
295 {
296 if (likely (!inverted))
297 return s.next_range (first, last);
298
299 if (!next (last))
300 {
301 *last = *first = INVALID;
302 return false;
303 }
304
305 *first = *last;
306 s.next (last);
307 --*last;
308 return true;
309 }
310 bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
311 {
312 if (likely (!inverted))
313 return s.previous_range (first, last);
314
315 if (!previous (first))
316 {
317 *last = *first = INVALID;
318 return false;
319 }
320
321 *last = *first;
322 s.previous (first);
323 ++*first;
324 return true;
325 }
326
327 unsigned int next_many (hb_codepoint_t codepoint,
328 hb_codepoint_t *out,
329 unsigned int size) const
330 {
331 return inverted ? s.next_many_inverted (codepoint, out, size)
332 : s.next_many (codepoint, out, size);
333 }
334
335 static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
336
337 /*
338 * Iterator implementation.
339 */
340 struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
341 {
342 static constexpr bool is_sorted_iterator = true;
343 iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t),
344 bool init = true) : s (&s_), v (INVALID), l(0)
345 {
346 if (init)
347 {
348 l = s->get_population () + 1;
349 __next__ ();
350 }
351 }
352
353 typedef hb_codepoint_t __item_t__;
354 hb_codepoint_t __item__ () const { return v; }
355 bool __more__ () const { return v != INVALID; }
356 void __next__ () { s->next (&v); if (l) l--; }
357 void __prev__ () { s->previous (&v); }
358 unsigned __len__ () const { return l; }
359 iter_t end () const { return iter_t (*s, false); }
360 bool operator != (const iter_t& o) const
361 { return s != o.s || v != o.v; }
362
363 protected:
364 const hb_bit_set_invertible_t *s;
365 hb_codepoint_t v;
366 unsigned l;
367 };
368 iter_t iter () const { return iter_t (*this); }
369 operator iter_t () const { return iter (); }
370 };
371
372
373 #endif /* HB_BIT_SET_INVERTIBLE_HH */