| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 2012 Google, Inc. | 2 * Copyright © 2012 Google, Inc. |
| 3 * | 3 * |
| 4 * This is part of HarfBuzz, a text shaping library. | 4 * This is part of HarfBuzz, a text shaping library. |
| 5 * | 5 * |
| 6 * Permission is hereby granted, without written agreement and without | 6 * Permission is hereby granted, without written agreement and without |
| 7 * license or royalty fees, to use, copy, modify, and distribute this | 7 * license or royalty fees, to use, copy, modify, and distribute this |
| 8 * software and its documentation for any purpose, provided that the | 8 * software and its documentation for any purpose, provided that the |
| 9 * above copyright notice and the following two paragraphs appear in | 9 * above copyright notice and the following two paragraphs appear in |
| 10 * all copies of this software. | 10 * all copies of this software. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 */ | 25 */ |
| 26 | 26 |
| 27 #ifndef HB_SET_PRIVATE_HH | 27 #ifndef HB_SET_PRIVATE_HH |
| 28 #define HB_SET_PRIVATE_HH | 28 #define HB_SET_PRIVATE_HH |
| 29 | 29 |
| 30 #include "hb-private.hh" | 30 #include "hb-private.hh" |
| 31 #include "hb-set.h" | 31 #include "hb-set.h" |
| 32 #include "hb-object-private.hh" | 32 #include "hb-object-private.hh" |
| 33 | 33 |
| 34 | 34 |
| 35 struct hb_set_digest_common_bits_t | 35 /* |
| 36 { | 36 * The set digests here implement various "filters" that support |
| 37 ASSERT_POD (); | 37 * "approximate member query". Conceptually these are like Bloom |
| 38 * Filter and Quotient Filter, however, much smaller, faster, and |
| 39 * designed to fit the requirements of our uses for glyph coverage |
| 40 * queries. As a result, our filters have much higher. |
| 41 */ |
| 38 | 42 |
| 39 typedef unsigned int mask_t; | 43 template <typename mask_t, unsigned int shift> |
| 40 | |
| 41 inline void init (void) { | |
| 42 mask = ~0; | |
| 43 value = (mask_t) -1; | |
| 44 } | |
| 45 | |
| 46 inline void add (hb_codepoint_t g) { | |
| 47 if (unlikely (value == (mask_t) -1)) { | |
| 48 value = g; | |
| 49 return; | |
| 50 } | |
| 51 | |
| 52 mask ^= (g & mask) ^ value; | |
| 53 value &= mask; | |
| 54 } | |
| 55 | |
| 56 inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { | |
| 57 /* The negation here stands for ~(x-1). */ | |
| 58 mask &= -(1 << _hb_bit_storage (a ^ b)); | |
| 59 value &= mask; | |
| 60 } | |
| 61 | |
| 62 inline bool may_have (hb_codepoint_t g) const { | |
| 63 return (g & mask) == value; | |
| 64 } | |
| 65 | |
| 66 private: | |
| 67 mask_t mask; | |
| 68 mask_t value; | |
| 69 }; | |
| 70 | |
| 71 struct hb_set_digest_lowest_bits_t | 44 struct hb_set_digest_lowest_bits_t |
| 72 { | 45 { |
| 73 ASSERT_POD (); | 46 ASSERT_POD (); |
| 74 | 47 |
| 75 typedef unsigned long mask_t; | 48 static const unsigned int mask_bytes = sizeof (mask_t); |
| 49 static const unsigned int mask_bits = sizeof (mask_t) * 8; |
| 50 static const unsigned int num_bits = 0 |
| 51 » » » » + (mask_bytes >= 1 ? 3 : 0) |
| 52 » » » » + (mask_bytes >= 2 ? 1 : 0) |
| 53 » » » » + (mask_bytes >= 4 ? 1 : 0) |
| 54 » » » » + (mask_bytes >= 8 ? 1 : 0) |
| 55 » » » » + (mask_bytes >= 16? 1 : 0) |
| 56 » » » » + 0; |
| 57 |
| 58 ASSERT_STATIC (shift < sizeof (hb_codepoint_t) * 8); |
| 59 ASSERT_STATIC (shift + num_bits <= sizeof (hb_codepoint_t) * 8); |
| 76 | 60 |
| 77 inline void init (void) { | 61 inline void init (void) { |
| 78 mask = 0; | 62 mask = 0; |
| 79 } | 63 } |
| 80 | 64 |
| 81 inline void add (hb_codepoint_t g) { | 65 inline void add (hb_codepoint_t g) { |
| 82 mask |= mask_for (g); | 66 mask |= mask_for (g); |
| 83 } | 67 } |
| 84 | 68 |
| 85 inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { | 69 inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { |
| 86 if (b - a >= sizeof (mask_t) * 8 - 1) | 70 if ((b >> shift) - (a >> shift) >= mask_bits - 1) |
| 87 mask = (mask_t) -1; | 71 mask = (mask_t) -1; |
| 88 else { | 72 else { |
| 89 mask_t ma = mask_for (a); | 73 mask_t ma = mask_for (a); |
| 90 mask_t mb = mask_for (b); | 74 mask_t mb = mask_for (b); |
| 91 mask |= mb + (mb - ma) - (mb < ma); | 75 mask |= mb + (mb - ma) - (mb < ma); |
| 92 } | 76 } |
| 93 } | 77 } |
| 94 | 78 |
| 95 inline bool may_have (hb_codepoint_t g) const { | 79 inline bool may_have (hb_codepoint_t g) const { |
| 96 return !!(mask & mask_for (g)); | 80 return !!(mask & mask_for (g)); |
| 97 } | 81 } |
| 98 | 82 |
| 99 private: | 83 private: |
| 100 | 84 |
| 101 static inline mask_t mask_for (hb_codepoint_t g) { return ((mask_t) 1) << (g &
(sizeof (mask_t) * 8 - 1)); } | 85 static inline mask_t mask_for (hb_codepoint_t g) { |
| 86 return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); |
| 87 } |
| 102 mask_t mask; | 88 mask_t mask; |
| 103 }; | 89 }; |
| 104 | 90 |
| 105 struct hb_set_digest_t | 91 template <typename head_t, typename tail_t> |
| 92 struct hb_set_digest_combiner_t |
| 106 { | 93 { |
| 107 ASSERT_POD (); | 94 ASSERT_POD (); |
| 108 | 95 |
| 109 inline void init (void) { | 96 inline void init (void) { |
| 110 digest1.init (); | 97 head.init (); |
| 111 digest2.init (); | 98 tail.init (); |
| 112 } | 99 } |
| 113 | 100 |
| 114 inline void add (hb_codepoint_t g) { | 101 inline void add (hb_codepoint_t g) { |
| 115 digest1.add (g); | 102 head.add (g); |
| 116 digest2.add (g); | 103 tail.add (g); |
| 117 } | 104 } |
| 118 | 105 |
| 119 inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { | 106 inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { |
| 120 digest1.add_range (a, b); | 107 head.add_range (a, b); |
| 121 digest2.add_range (a, b); | 108 tail.add_range (a, b); |
| 122 } | 109 } |
| 123 | 110 |
| 124 inline bool may_have (hb_codepoint_t g) const { | 111 inline bool may_have (hb_codepoint_t g) const { |
| 125 return digest1.may_have (g) && digest2.may_have (g); | 112 return head.may_have (g) && tail.may_have (g); |
| 126 } | 113 } |
| 127 | 114 |
| 128 private: | 115 private: |
| 129 hb_set_digest_common_bits_t digest1; | 116 head_t head; |
| 130 hb_set_digest_lowest_bits_t digest2; | 117 tail_t tail; |
| 131 }; | 118 }; |
| 132 | 119 |
| 133 | 120 |
| 121 /* |
| 122 * hb_set_digest_t |
| 123 * |
| 124 * This is a combination of digests that performs "best". |
| 125 * There is not much science to this: it's a result of intuition |
| 126 * and testing. |
| 127 */ |
| 128 typedef hb_set_digest_combiner_t |
| 129 < |
| 130 hb_set_digest_lowest_bits_t<unsigned long, 4>, |
| 131 hb_set_digest_combiner_t |
| 132 < |
| 133 hb_set_digest_lowest_bits_t<unsigned long, 0>, |
| 134 hb_set_digest_lowest_bits_t<unsigned long, 9> |
| 135 > |
| 136 > hb_set_digest_t; |
| 137 |
| 138 |
| 139 |
| 140 /* |
| 141 * hb_set_t |
| 142 */ |
| 143 |
| 144 |
| 134 /* TODO Make this faster and memmory efficient. */ | 145 /* TODO Make this faster and memmory efficient. */ |
| 135 | 146 |
| 136 struct hb_set_t | 147 struct hb_set_t |
| 137 { | 148 { |
| 138 hb_object_header_t header; | 149 hb_object_header_t header; |
| 139 ASSERT_POD (); | 150 ASSERT_POD (); |
| 140 bool in_error; | 151 bool in_error; |
| 141 | 152 |
| 142 inline void init (void) { | 153 inline void init (void) { |
| 143 header.init (); | 154 header.init (); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 { | 290 { |
| 280 unsigned int count = 0; | 291 unsigned int count = 0; |
| 281 for (unsigned int i = 0; i < ELTS; i++) | 292 for (unsigned int i = 0; i < ELTS; i++) |
| 282 count += _hb_popcount32 (elts[i]); | 293 count += _hb_popcount32 (elts[i]); |
| 283 return count; | 294 return count; |
| 284 } | 295 } |
| 285 inline hb_codepoint_t get_min (void) const | 296 inline hb_codepoint_t get_min (void) const |
| 286 { | 297 { |
| 287 for (unsigned int i = 0; i < ELTS; i++) | 298 for (unsigned int i = 0; i < ELTS; i++) |
| 288 if (elts[i]) | 299 if (elts[i]) |
| 289 » for (unsigned int j = 0; i < BITS; j++) | 300 » for (unsigned int j = 0; j < BITS; j++) |
| 290 if (elts[i] & (1 << j)) | 301 if (elts[i] & (1 << j)) |
| 291 return i * BITS + j; | 302 return i * BITS + j; |
| 292 return SENTINEL; | 303 return SENTINEL; |
| 293 } | 304 } |
| 294 inline hb_codepoint_t get_max (void) const | 305 inline hb_codepoint_t get_max (void) const |
| 295 { | 306 { |
| 296 for (unsigned int i = ELTS; i; i--) | 307 for (unsigned int i = ELTS; i; i--) |
| 297 if (elts[i - 1]) | 308 if (elts[i - 1]) |
| 298 for (unsigned int j = BITS; j; j--) | 309 for (unsigned int j = BITS; j; j--) |
| 299 if (elts[i - 1] & (1 << (j - 1))) | 310 if (elts[i - 1] & (1 << (j - 1))) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 315 | 326 |
| 316 elt_t elts[ELTS]; /* XXX 8kb */ | 327 elt_t elts[ELTS]; /* XXX 8kb */ |
| 317 | 328 |
| 318 ASSERT_STATIC (sizeof (elt_t) * 8 == BITS); | 329 ASSERT_STATIC (sizeof (elt_t) * 8 == BITS); |
| 319 ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G); | 330 ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G); |
| 320 }; | 331 }; |
| 321 | 332 |
| 322 | 333 |
| 323 | 334 |
| 324 #endif /* HB_SET_PRIVATE_HH */ | 335 #endif /* HB_SET_PRIVATE_HH */ |
| OLD | NEW |