1use super::layout::DELETED_GLYPH;
2use super::map::RangeFlags;
3use crate::hb::buffer::{hb_buffer_t, HB_BUFFER_SCRATCH_FLAG_SHAPER0};
4use crate::hb::face::hb_font_t;
5use crate::hb::face::Scale;
6use crate::hb::hb_mask_t;
7use crate::hb::ot_layout_gsubgpos::MappingCache;
8use crate::hb::ot_shape_plan::hb_ot_shape_plan_t;
9use crate::U32Set;
10use read_fonts::tables::aat::*;
11use read_fonts::types::{FixedSize, GlyphId};
12
13pub const HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED: u32 = HB_BUFFER_SCRATCH_FLAG_SHAPER0;
14
15pub(crate) const START_OF_TEXT: u16 = 0;
16
17pub(crate) type ClassCache = MappingCache;
18
19pub(crate) fn get_class<T: bytemuck::AnyBitPattern + FixedSize>(
20 machine: &ExtendedStateTable<'_, T>,
21 glyph_id: GlyphId,
22 cache: &ClassCache,
23) -> u16 {
24 if let Some(klass) = cache.get(glyph_id.to_u32()) {
25 return klass as u16;
26 }
27 let klass = machine
28 .class(glyph_id)
29 .unwrap_or(class::OUT_OF_BOUNDS as u16);
30 cache.set(glyph_id.to_u32(), klass as u32);
31 klass
32}
33
34#[doc(alias = "hb_aat_apply_context_t")]
38pub struct AatApplyContext<'a> {
39 pub plan: &'a hb_ot_shape_plan_t,
40 pub face: &'a hb_font_t<'a>,
41 pub scale: Scale,
42 pub buffer: &'a mut hb_buffer_t,
43 pub has_glyph_classes: bool,
44 pub range_flags: Option<&'a [RangeFlags]>,
45 pub subtable_flags: hb_mask_t,
46 pub(crate) buffer_is_reversed: bool,
47 using_buffer_glyph_set: bool,
49 pub(crate) first_set: Option<&'a U32Set>,
50 pub(crate) second_set: Option<&'a U32Set>,
51 pub(crate) machine_class_cache: Option<&'a ClassCache>,
52 pub(crate) start_end_safe_to_break: u64,
53}
54
55impl<'a> AatApplyContext<'a> {
56 pub fn new(
57 plan: &'a hb_ot_shape_plan_t,
58 face: &'a hb_font_t<'a>,
59 scale: Scale,
60 buffer: &'a mut hb_buffer_t,
61 ) -> Self {
62 Self {
63 plan,
64 face,
65 scale,
66 buffer,
67 has_glyph_classes: face.ot_tables.has_glyph_classes(),
68 range_flags: None,
69 subtable_flags: 0,
70 buffer_is_reversed: false,
71 using_buffer_glyph_set: false,
72 first_set: None,
73 second_set: None,
74 machine_class_cache: None,
75 start_end_safe_to_break: 0,
76 }
77 }
78
79 #[inline(always)]
80 pub(crate) fn scale_x(&self, value: i32) -> i32 {
81 self.scale.scale_x(value)
82 }
83
84 #[inline(always)]
85 pub(crate) fn scale_y(&self, value: i32) -> i32 {
86 self.scale.scale_y(value)
87 }
88
89 pub(crate) fn reverse_buffer(&mut self) {
90 self.buffer.reverse();
91 self.buffer_is_reversed = !self.buffer_is_reversed;
92 }
93
94 pub(crate) fn setup_buffer_glyph_set(&mut self) {
95 self.using_buffer_glyph_set = self.buffer.len >= 4;
96
97 if self.using_buffer_glyph_set {
98 self.buffer.update_glyph_set();
99 }
100 }
101
102 pub(crate) fn buffer_intersects_machine(&self) -> bool {
103 if let Some(first_set) = &self.first_set {
104 if self.using_buffer_glyph_set {
105 return self.buffer.glyph_set.intersects_set(first_set);
106 }
107 for info in &self.buffer.info {
108 if first_set.contains(info.glyph_id) {
109 return true;
110 }
111 }
112 false
113 } else {
114 true
115 }
116 }
117
118 pub fn output_glyph(&mut self, glyph: u32) {
119 if self.using_buffer_glyph_set {
120 self.buffer.glyph_set.insert(glyph);
121 }
122 if glyph == DELETED_GLYPH {
123 self.buffer.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
124 self.buffer.cur_mut(0).set_aat_deleted();
125 } else {
126 if self.has_glyph_classes {
127 self.buffer
128 .cur_mut(0)
129 .set_glyph_props(self.face.ot_tables.glyph_props(glyph.into()));
130 }
131 }
132 self.buffer.output_glyph(glyph);
133 }
134
135 pub fn replace_glyph(&mut self, glyph: u32) {
136 if glyph == DELETED_GLYPH {
137 self.buffer.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
138 self.buffer.cur_mut(0).set_aat_deleted();
139 }
140
141 if self.using_buffer_glyph_set {
142 self.buffer.glyph_set.insert(glyph);
143 }
144 if self.has_glyph_classes {
145 self.buffer
146 .cur_mut(0)
147 .set_glyph_props(self.face.ot_tables.glyph_props(glyph.into()));
148 }
149 self.buffer.replace_glyph(glyph);
150 }
151
152 pub fn delete_glyph(&mut self) {
153 self.buffer.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
154 self.buffer.cur_mut(0).set_aat_deleted();
155 self.buffer.replace_glyph(DELETED_GLYPH);
156 }
157
158 pub fn replace_glyph_inplace(&mut self, i: usize, glyph: u32) {
159 self.buffer.info[i].glyph_id = glyph;
160 if glyph == DELETED_GLYPH {
161 self.buffer.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
162 self.buffer.info[i].set_aat_deleted();
163 }
164 if self.using_buffer_glyph_set {
165 self.buffer.glyph_set.insert(glyph);
166 }
167 if self.has_glyph_classes {
168 self.buffer.info[i].set_glyph_props(self.face.ot_tables.glyph_props(glyph.into()));
169 }
170 }
171}
172
173pub trait TypedCollectGlyphs<T: LookupValue> {
174 fn collect_glyphs(&self, set: &mut U32Set, num_glyphs: u32) {
176 self.collect_glyphs_filtered::<_>(set, num_glyphs, |_| true);
177 }
178
179 fn collect_glyphs_filtered<F>(&self, _set: &mut U32Set, _num_glyphs: u32, _filter: F)
182 where
183 F: Fn(T) -> bool;
184}
185
186impl<T> TypedCollectGlyphs<T> for TypedLookup<'_, T>
187where
188 T: LookupValue,
189{
190 fn collect_glyphs(&self, set: &mut U32Set, num_glyphs: u32) {
191 self.lookup.collect_glyphs::<T>(set, num_glyphs);
192 }
193 fn collect_glyphs_filtered<F>(&self, set: &mut U32Set, num_glyphs: u32, filter: F)
194 where
195 F: Fn(T) -> bool,
196 {
197 self.lookup
198 .collect_glyphs_filtered::<T, F>(set, num_glyphs, filter);
199 }
200}
201
202pub trait CollectGlyphs {
203 fn collect_glyphs<T>(&self, set: &mut U32Set, num_glyphs: u32)
205 where
206 T: LookupValue,
207 {
208 self.collect_glyphs_filtered::<T, _>(set, num_glyphs, |_| true);
209 }
210
211 fn collect_glyphs_filtered<T, F>(&self, _set: &mut U32Set, _num_glyphs: u32, _filter: F)
214 where
215 T: LookupValue,
216 F: Fn(T) -> bool;
217}
218
219impl CollectGlyphs for Lookup<'_> {
220 fn collect_glyphs<T>(&self, set: &mut U32Set, num_glyphs: u32)
221 where
222 T: LookupValue,
223 {
224 match self {
225 Lookup::Format0(lookup) => lookup.collect_glyphs::<T>(set, num_glyphs),
226 Lookup::Format2(lookup) => lookup.collect_glyphs::<T>(set, num_glyphs),
227 Lookup::Format4(lookup) => lookup.collect_glyphs::<T>(set, num_glyphs),
228 Lookup::Format6(lookup) => lookup.collect_glyphs::<T>(set, num_glyphs),
229 Lookup::Format8(lookup) => lookup.collect_glyphs::<T>(set, num_glyphs),
230 Lookup::Format10(lookup) => lookup.collect_glyphs::<T>(set, num_glyphs),
231 }
232 }
233 fn collect_glyphs_filtered<T, F>(&self, set: &mut U32Set, num_glyphs: u32, filter: F)
234 where
235 T: LookupValue,
236 F: Fn(T) -> bool,
237 {
238 match self {
239 Lookup::Format0(lookup) => {
240 lookup.collect_glyphs_filtered::<T, F>(set, num_glyphs, filter);
241 }
242 Lookup::Format2(lookup) => {
243 lookup.collect_glyphs_filtered::<T, F>(set, num_glyphs, filter);
244 }
245 Lookup::Format4(lookup) => {
246 lookup.collect_glyphs_filtered::<T, F>(set, num_glyphs, filter);
247 }
248 Lookup::Format6(lookup) => {
249 lookup.collect_glyphs_filtered::<T, F>(set, num_glyphs, filter);
250 }
251 Lookup::Format8(lookup) => {
252 lookup.collect_glyphs_filtered::<T, F>(set, num_glyphs, filter);
253 }
254 Lookup::Format10(lookup) => {
255 lookup.collect_glyphs_filtered::<T, F>(set, num_glyphs, filter);
256 }
257 }
258 }
259}
260
261impl CollectGlyphs for Lookup0<'_> {
262 fn collect_glyphs<T>(&self, set: &mut U32Set, num_glyphs: u32)
263 where
264 T: LookupValue,
265 {
266 set.insert_range(0..=num_glyphs.saturating_sub(1));
267 }
268 fn collect_glyphs_filtered<T, F>(&self, set: &mut U32Set, num_glyphs: u32, filter: F)
269 where
270 T: LookupValue,
271 F: Fn(T) -> bool,
272 {
273 if let Ok(values) = self.values::<T>() {
274 for (i, value) in values.iter().take(num_glyphs as usize).enumerate() {
275 if filter(value.get()) {
276 set.insert(i as u32);
277 }
278 }
279 }
280 }
281}
282impl CollectGlyphs for Lookup2<'_> {
283 fn collect_glyphs_filtered<T, F>(&self, set: &mut U32Set, _num_glyphs: u32, filter: F)
284 where
285 T: LookupValue,
286 F: Fn(T) -> bool,
287 {
288 if let Ok(segments) = self.segments::<T>() {
289 for segment in segments {
290 let value = segment.value;
291 if filter(value.get()) {
292 if segment.first_glyph.get() as u32 == DELETED_GLYPH {
293 continue;
294 }
295 set.insert_range(
296 segment.first_glyph.get() as u32..=segment.last_glyph.get() as u32,
297 );
298 }
299 }
300 }
301 }
302}
303impl CollectGlyphs for Lookup4<'_> {
304 fn collect_glyphs<T>(&self, set: &mut U32Set, _num_glyphs: u32)
305 where
306 T: LookupValue,
307 {
308 for segment in self.segments() {
309 if segment.first_glyph.get() as u32 == DELETED_GLYPH {
310 continue;
311 }
312 set.insert_range(segment.first_glyph.get() as u32..=segment.last_glyph.get() as u32);
313 }
314 }
315 fn collect_glyphs_filtered<T, F>(&self, set: &mut U32Set, _num_glyphs: u32, filter: F)
316 where
317 T: LookupValue,
318 F: Fn(T) -> bool,
319 {
320 for (segment_idx, segment) in self.segments().iter().enumerate() {
321 if segment.first_glyph.get() as u32 == DELETED_GLYPH {
322 continue;
323 }
324 let segment_values = self.segment_values(segment_idx);
325 if let Ok(segment_values) = segment_values {
326 for (i, value) in segment_values.iter().enumerate() {
327 if filter(value.get()) {
328 set.insert(segment.first_glyph.get() as u32 + i as u32);
329 }
330 }
331 }
332 }
333 }
334}
335impl CollectGlyphs for Lookup6<'_> {
336 fn collect_glyphs_filtered<T, F>(&self, set: &mut U32Set, _num_glyphs: u32, filter: F)
337 where
338 T: LookupValue,
339 F: Fn(T) -> bool,
340 {
341 let entries = self.entries();
342 if let Ok(entries) = entries {
343 for entry in entries {
344 let value = entry.value;
345 if filter(value.get()) {
346 if entry.glyph.get() as u32 == DELETED_GLYPH {
347 continue;
348 }
349 set.insert(entry.glyph.get() as u32);
350 }
351 }
352 }
353 }
354}
355impl CollectGlyphs for Lookup8<'_> {
356 fn collect_glyphs<T>(&self, set: &mut U32Set, _num_glyphs: u32)
357 where
358 T: LookupValue,
359 {
360 let n_values = self.value_array().len();
361 let first_glyph = self.first_glyph();
362 if first_glyph as u32 == DELETED_GLYPH {
363 return;
364 }
365 set.insert_range(
366 first_glyph as u32..=first_glyph as u32 + n_values.saturating_sub(1) as u32,
367 );
368 }
369 fn collect_glyphs_filtered<T, F>(&self, set: &mut U32Set, _num_glyphs: u32, filter: F)
370 where
371 T: LookupValue,
372 F: Fn(T) -> bool,
373 {
374 let values = self.value_array();
375 let first_glyph = self.first_glyph();
376 if first_glyph as u32 == DELETED_GLYPH {
377 return;
378 }
379 for (i, value) in values.iter().enumerate() {
380 if filter(T::from_u16(value.get())) {
381 set.insert(first_glyph as u32 + i as u32);
382 }
383 }
384 }
385}
386impl CollectGlyphs for Lookup10<'_> {
387 fn collect_glyphs<T>(&self, set: &mut U32Set, _num_glyphs: u32)
388 where
389 T: LookupValue,
390 {
391 let n_values = self.glyph_count();
392 let first_glyph = self.first_glyph();
393 if first_glyph as u32 == DELETED_GLYPH {
394 return;
395 }
396 set.insert_range(
397 first_glyph as u32..=first_glyph as u32 + n_values.saturating_sub(1) as u32,
398 );
399 }
400 fn collect_glyphs_filtered<T, F>(&self, set: &mut U32Set, _num_glyphs: u32, filter: F)
401 where
402 T: LookupValue,
403 F: Fn(T) -> bool,
404 {
405 let first_glyph = self.first_glyph();
406 if first_glyph as u32 == DELETED_GLYPH {
407 return;
408 }
409 for i in 0..self.glyph_count() {
410 let idx = first_glyph as u32 + i as u32;
411 let value = self.value::<T>(idx as u16);
413 if let Ok(value) = value {
414 if filter(value) {
415 set.insert(idx);
416 }
417 }
418 }
419 }
420}