harfrust/hb/
set_digest.rs1use read_fonts::tables::layout::CoverageTable;
2
3type mask_t = u64;
4
5const HB_SET_DIGEST_SHIFTS: [u32; 3] = [4, 0, 6];
6const N: usize = HB_SET_DIGEST_SHIFTS.len();
7const MASK_BITS: u32 = mask_t::BITS;
8const MB1: u32 = MASK_BITS - 1;
9const ONE: mask_t = 1;
10const ALL: mask_t = mask_t::MAX;
11
12#[derive(Clone, Debug)]
13pub struct hb_set_digest_t {
14 masks: [mask_t; N],
15}
16
17impl Default for hb_set_digest_t {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl hb_set_digest_t {
24 pub fn new() -> Self {
25 Self { masks: [0; N] }
26 }
27
28 pub fn from_coverage(coverage: &CoverageTable) -> Self {
29 let mut digest = Self::new();
30 digest.add_coverage(coverage);
31 digest
32 }
33
34 #[allow(dead_code)]
35 pub fn clear(&mut self) {
36 self.masks = [0; N];
37 }
38
39 pub fn full() -> Self {
40 Self { masks: [ALL; N] }
41 }
42
43 pub fn union(&mut self, other: &Self) {
44 for i in 0..N {
45 self.masks[i] |= other.masks[i];
46 }
47 }
48
49 pub fn add(&mut self, g: u32) {
50 for i in 0..N {
51 let shift = HB_SET_DIGEST_SHIFTS[i];
52 let bit = (g >> shift) & MB1;
53 self.masks[i] |= ONE << bit;
54 }
55 }
56
57 pub fn add_array(&mut self, array: impl IntoIterator<Item = u32>) {
58 for g in array {
59 self.add(g);
60 }
61 }
62
63 pub fn add_range(&mut self, a: u32, b: u32) -> bool {
64 let a = a as mask_t;
65 let b = b as mask_t;
66
67 if self.masks.iter().all(|&m| m == ALL) {
68 return false;
69 }
70
71 let mut changed = false;
72 for i in 0..N {
73 let shift = HB_SET_DIGEST_SHIFTS[i] as mask_t;
74 if (b >> shift).wrapping_sub(a >> shift) >= MB1 as mask_t {
75 self.masks[i] = ALL;
76 } else {
77 let ma = ONE << ((a >> shift) & MB1 as mask_t);
78 let mb = ONE << ((b >> shift) & MB1 as mask_t);
79 self.masks[i] |= mb + mb.wrapping_sub(ma) - mask_t::from(mb < ma);
80 changed = true;
81 }
82 }
83 changed
84 }
85
86 pub fn add_coverage(&mut self, coverage: &CoverageTable) {
87 match coverage {
88 CoverageTable::Format1(table) => {
89 for glyph in table.glyph_array() {
90 self.add(glyph.get().into());
91 }
92 }
93 CoverageTable::Format2(table) => {
94 for range in table.range_records() {
95 self.add_range(range.start_glyph_id().into(), range.end_glyph_id().into());
96 }
97 }
98 }
99 }
100
101 pub fn may_have(&self, g: u32) -> bool {
102 for i in 0..N {
103 let shift = HB_SET_DIGEST_SHIFTS[i];
104 let bit = (g >> shift) & MB1;
105 if self.masks[i] & (ONE << bit) == 0 {
106 return false;
107 }
108 }
109 true
110 }
111
112 pub fn may_intersect(&self, other: &Self) -> bool {
113 for i in 0..N {
114 if self.masks[i] & other.masks[i] == 0 {
115 return false;
116 }
117 }
118 true
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_single() {
128 let mut set = hb_set_digest_t::new();
129 set.add(2);
130 assert!(set.may_have(2));
131 }
132
133 #[test]
134 fn test_multiple_1() {
135 let mut set = hb_set_digest_t::new();
136 set.add(2);
137 set.add(10);
138 set.add(300);
139 set.add(255);
140 assert!(set.may_have(2));
141 assert!(set.may_have(10));
142 assert!(set.may_have(255));
143 assert!(set.may_have(300));
144 }
145
146 #[test]
147 fn test_multiple_2() {
148 let mut set = hb_set_digest_t::new();
149 set.add(245);
150 set.add(1060);
151 set.add(300);
152 set.add(599);
153 assert!(set.may_have(245));
154 assert!(set.may_have(1060));
155 assert!(set.may_have(300));
156 assert!(set.may_have(599));
157 }
158
159 #[test]
160 fn test_range_1() {
161 let mut set = hb_set_digest_t::new();
162 set.add_range(10, 12);
163 assert!(set.may_have(10));
164 assert!(set.may_have(11));
165 assert!(set.may_have(12));
166 }
167
168 #[test]
169 fn test_range_2() {
170 let mut set = hb_set_digest_t::new();
171 set.add_range(20, 15);
172 set.add_range(15, 20);
173 for gid in 15..=20 {
174 assert!(set.may_have(gid));
175 }
176 }
177
178 #[test]
179 fn test_range_3() {
180 let mut set = hb_set_digest_t::new();
181 for i in 170..=239 {
182 set.add(i);
183 }
184 assert!(set.may_have(200));
185 }
186
187 #[test]
188 fn test_complex() {
189 let mut set = hb_set_digest_t::new();
190 set.add_range(5670, 5675);
191 set.add(3);
192 set.add(8769);
193 set.add(10000);
194 set.add_range(3456, 3460);
195
196 assert!(set.may_have(3));
197 assert!(set.may_have(5670));
198 assert!(set.may_have(5675));
199 assert!(set.may_have(8769));
200 assert!(set.may_have(10000));
201 assert!(set.may_have(3456));
202 assert!(set.may_have(3460));
203 }
204
205 #[test]
206 fn test_intersect() {
207 let mut a = hb_set_digest_t::new();
208 let mut b = hb_set_digest_t::new();
209
210 a.add(123);
211 b.add(456);
212 assert!(!a.may_intersect(&b));
213
214 b.add(123);
215 assert!(a.may_intersect(&b));
216 }
217}