1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Clone)]
11pub enum Lookup<'a> {
12 Format0(Lookup0<'a>),
13 Format2(Lookup2<'a>),
14 Format4(Lookup4<'a>),
15 Format6(Lookup6<'a>),
16 Format8(Lookup8<'a>),
17 Format10(Lookup10<'a>),
18}
19
20impl<'a> Lookup<'a> {
21 pub fn offset_data(&self) -> FontData<'a> {
23 match self {
24 Self::Format0(item) => item.offset_data(),
25 Self::Format2(item) => item.offset_data(),
26 Self::Format4(item) => item.offset_data(),
27 Self::Format6(item) => item.offset_data(),
28 Self::Format8(item) => item.offset_data(),
29 Self::Format10(item) => item.offset_data(),
30 }
31 }
32
33 pub fn format(&self) -> u16 {
35 match self {
36 Self::Format0(item) => item.format(),
37 Self::Format2(item) => item.format(),
38 Self::Format4(item) => item.format(),
39 Self::Format6(item) => item.format(),
40 Self::Format8(item) => item.format(),
41 Self::Format10(item) => item.format(),
42 }
43 }
44}
45
46impl<'a> FontRead<'a> for Lookup<'a> {
47 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
48 let format: u16 = data.read_at(0usize)?;
49 match format {
50 Lookup0Marker::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
51 Lookup2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
52 Lookup4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
53 Lookup6Marker::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
54 Lookup8Marker::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
55 Lookup10Marker::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
56 other => Err(ReadError::InvalidFormat(other.into())),
57 }
58 }
59}
60
61impl MinByteRange for Lookup<'_> {
62 fn min_byte_range(&self) -> Range<usize> {
63 match self {
64 Self::Format0(item) => item.min_byte_range(),
65 Self::Format2(item) => item.min_byte_range(),
66 Self::Format4(item) => item.min_byte_range(),
67 Self::Format6(item) => item.min_byte_range(),
68 Self::Format8(item) => item.min_byte_range(),
69 Self::Format10(item) => item.min_byte_range(),
70 }
71 }
72}
73
74#[cfg(feature = "experimental_traverse")]
75impl<'a> Lookup<'a> {
76 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
77 match self {
78 Self::Format0(table) => table,
79 Self::Format2(table) => table,
80 Self::Format4(table) => table,
81 Self::Format6(table) => table,
82 Self::Format8(table) => table,
83 Self::Format10(table) => table,
84 }
85 }
86}
87
88#[cfg(feature = "experimental_traverse")]
89impl std::fmt::Debug for Lookup<'_> {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 self.dyn_inner().fmt(f)
92 }
93}
94
95#[cfg(feature = "experimental_traverse")]
96impl<'a> SomeTable<'a> for Lookup<'a> {
97 fn type_name(&self) -> &str {
98 self.dyn_inner().type_name()
99 }
100 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
101 self.dyn_inner().get_field(idx)
102 }
103}
104
105impl Format<u16> for Lookup0Marker {
106 const FORMAT: u16 = 0;
107}
108
109#[derive(Debug, Clone, Copy)]
112#[doc(hidden)]
113pub struct Lookup0Marker {
114 values_data_byte_len: usize,
115}
116
117impl Lookup0Marker {
118 pub fn format_byte_range(&self) -> Range<usize> {
119 let start = 0;
120 start..start + u16::RAW_BYTE_LEN
121 }
122
123 pub fn values_data_byte_range(&self) -> Range<usize> {
124 let start = self.format_byte_range().end;
125 start..start + self.values_data_byte_len
126 }
127}
128
129impl MinByteRange for Lookup0Marker {
130 fn min_byte_range(&self) -> Range<usize> {
131 0..self.values_data_byte_range().end
132 }
133}
134
135impl<'a> FontRead<'a> for Lookup0<'a> {
136 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
137 let mut cursor = data.cursor();
138 cursor.advance::<u16>();
139 let values_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
140 cursor.advance_by(values_data_byte_len);
141 cursor.finish(Lookup0Marker {
142 values_data_byte_len,
143 })
144 }
145}
146
147pub type Lookup0<'a> = TableRef<'a, Lookup0Marker>;
150
151#[allow(clippy::needless_lifetimes)]
152impl<'a> Lookup0<'a> {
153 pub fn format(&self) -> u16 {
155 let range = self.shape.format_byte_range();
156 self.data.read_at(range.start).unwrap()
157 }
158
159 pub fn values_data(&self) -> &'a [u8] {
161 let range = self.shape.values_data_byte_range();
162 self.data.read_array(range).unwrap()
163 }
164}
165
166#[cfg(feature = "experimental_traverse")]
167impl<'a> SomeTable<'a> for Lookup0<'a> {
168 fn type_name(&self) -> &str {
169 "Lookup0"
170 }
171 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
172 match idx {
173 0usize => Some(Field::new("format", self.format())),
174 1usize => Some(Field::new("values_data", self.values_data())),
175 _ => None,
176 }
177 }
178}
179
180#[cfg(feature = "experimental_traverse")]
181#[allow(clippy::needless_lifetimes)]
182impl<'a> std::fmt::Debug for Lookup0<'a> {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 (self as &dyn SomeTable<'a>).fmt(f)
185 }
186}
187
188impl Format<u16> for Lookup2Marker {
189 const FORMAT: u16 = 2;
190}
191
192#[derive(Debug, Clone, Copy)]
196#[doc(hidden)]
197pub struct Lookup2Marker {
198 segments_data_byte_len: usize,
199}
200
201impl Lookup2Marker {
202 pub fn format_byte_range(&self) -> Range<usize> {
203 let start = 0;
204 start..start + u16::RAW_BYTE_LEN
205 }
206
207 pub fn unit_size_byte_range(&self) -> Range<usize> {
208 let start = self.format_byte_range().end;
209 start..start + u16::RAW_BYTE_LEN
210 }
211
212 pub fn n_units_byte_range(&self) -> Range<usize> {
213 let start = self.unit_size_byte_range().end;
214 start..start + u16::RAW_BYTE_LEN
215 }
216
217 pub fn search_range_byte_range(&self) -> Range<usize> {
218 let start = self.n_units_byte_range().end;
219 start..start + u16::RAW_BYTE_LEN
220 }
221
222 pub fn entry_selector_byte_range(&self) -> Range<usize> {
223 let start = self.search_range_byte_range().end;
224 start..start + u16::RAW_BYTE_LEN
225 }
226
227 pub fn range_shift_byte_range(&self) -> Range<usize> {
228 let start = self.entry_selector_byte_range().end;
229 start..start + u16::RAW_BYTE_LEN
230 }
231
232 pub fn segments_data_byte_range(&self) -> Range<usize> {
233 let start = self.range_shift_byte_range().end;
234 start..start + self.segments_data_byte_len
235 }
236}
237
238impl MinByteRange for Lookup2Marker {
239 fn min_byte_range(&self) -> Range<usize> {
240 0..self.segments_data_byte_range().end
241 }
242}
243
244impl<'a> FontRead<'a> for Lookup2<'a> {
245 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
246 let mut cursor = data.cursor();
247 cursor.advance::<u16>();
248 let unit_size: u16 = cursor.read()?;
249 let n_units: u16 = cursor.read()?;
250 cursor.advance::<u16>();
251 cursor.advance::<u16>();
252 cursor.advance::<u16>();
253 let segments_data_byte_len = (transforms::add_multiply(unit_size, 0_usize, n_units))
254 .checked_mul(u8::RAW_BYTE_LEN)
255 .ok_or(ReadError::OutOfBounds)?;
256 cursor.advance_by(segments_data_byte_len);
257 cursor.finish(Lookup2Marker {
258 segments_data_byte_len,
259 })
260 }
261}
262
263pub type Lookup2<'a> = TableRef<'a, Lookup2Marker>;
267
268#[allow(clippy::needless_lifetimes)]
269impl<'a> Lookup2<'a> {
270 pub fn format(&self) -> u16 {
272 let range = self.shape.format_byte_range();
273 self.data.read_at(range.start).unwrap()
274 }
275
276 pub fn unit_size(&self) -> u16 {
278 let range = self.shape.unit_size_byte_range();
279 self.data.read_at(range.start).unwrap()
280 }
281
282 pub fn n_units(&self) -> u16 {
284 let range = self.shape.n_units_byte_range();
285 self.data.read_at(range.start).unwrap()
286 }
287
288 pub fn search_range(&self) -> u16 {
290 let range = self.shape.search_range_byte_range();
291 self.data.read_at(range.start).unwrap()
292 }
293
294 pub fn entry_selector(&self) -> u16 {
296 let range = self.shape.entry_selector_byte_range();
297 self.data.read_at(range.start).unwrap()
298 }
299
300 pub fn range_shift(&self) -> u16 {
302 let range = self.shape.range_shift_byte_range();
303 self.data.read_at(range.start).unwrap()
304 }
305
306 pub fn segments_data(&self) -> &'a [u8] {
308 let range = self.shape.segments_data_byte_range();
309 self.data.read_array(range).unwrap()
310 }
311}
312
313#[cfg(feature = "experimental_traverse")]
314impl<'a> SomeTable<'a> for Lookup2<'a> {
315 fn type_name(&self) -> &str {
316 "Lookup2"
317 }
318 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
319 match idx {
320 0usize => Some(Field::new("format", self.format())),
321 1usize => Some(Field::new("unit_size", self.unit_size())),
322 2usize => Some(Field::new("n_units", self.n_units())),
323 3usize => Some(Field::new("search_range", self.search_range())),
324 4usize => Some(Field::new("entry_selector", self.entry_selector())),
325 5usize => Some(Field::new("range_shift", self.range_shift())),
326 6usize => Some(Field::new("segments_data", self.segments_data())),
327 _ => None,
328 }
329 }
330}
331
332#[cfg(feature = "experimental_traverse")]
333#[allow(clippy::needless_lifetimes)]
334impl<'a> std::fmt::Debug for Lookup2<'a> {
335 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
336 (self as &dyn SomeTable<'a>).fmt(f)
337 }
338}
339
340impl Format<u16> for Lookup4Marker {
341 const FORMAT: u16 = 4;
342}
343
344#[derive(Debug, Clone, Copy)]
348#[doc(hidden)]
349pub struct Lookup4Marker {
350 segments_byte_len: usize,
351}
352
353impl Lookup4Marker {
354 pub fn format_byte_range(&self) -> Range<usize> {
355 let start = 0;
356 start..start + u16::RAW_BYTE_LEN
357 }
358
359 pub fn unit_size_byte_range(&self) -> Range<usize> {
360 let start = self.format_byte_range().end;
361 start..start + u16::RAW_BYTE_LEN
362 }
363
364 pub fn n_units_byte_range(&self) -> Range<usize> {
365 let start = self.unit_size_byte_range().end;
366 start..start + u16::RAW_BYTE_LEN
367 }
368
369 pub fn search_range_byte_range(&self) -> Range<usize> {
370 let start = self.n_units_byte_range().end;
371 start..start + u16::RAW_BYTE_LEN
372 }
373
374 pub fn entry_selector_byte_range(&self) -> Range<usize> {
375 let start = self.search_range_byte_range().end;
376 start..start + u16::RAW_BYTE_LEN
377 }
378
379 pub fn range_shift_byte_range(&self) -> Range<usize> {
380 let start = self.entry_selector_byte_range().end;
381 start..start + u16::RAW_BYTE_LEN
382 }
383
384 pub fn segments_byte_range(&self) -> Range<usize> {
385 let start = self.range_shift_byte_range().end;
386 start..start + self.segments_byte_len
387 }
388}
389
390impl MinByteRange for Lookup4Marker {
391 fn min_byte_range(&self) -> Range<usize> {
392 0..self.segments_byte_range().end
393 }
394}
395
396impl<'a> FontRead<'a> for Lookup4<'a> {
397 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
398 let mut cursor = data.cursor();
399 cursor.advance::<u16>();
400 cursor.advance::<u16>();
401 let n_units: u16 = cursor.read()?;
402 cursor.advance::<u16>();
403 cursor.advance::<u16>();
404 cursor.advance::<u16>();
405 let segments_byte_len = (n_units as usize)
406 .checked_mul(LookupSegment4::RAW_BYTE_LEN)
407 .ok_or(ReadError::OutOfBounds)?;
408 cursor.advance_by(segments_byte_len);
409 cursor.finish(Lookup4Marker { segments_byte_len })
410 }
411}
412
413pub type Lookup4<'a> = TableRef<'a, Lookup4Marker>;
417
418#[allow(clippy::needless_lifetimes)]
419impl<'a> Lookup4<'a> {
420 pub fn format(&self) -> u16 {
422 let range = self.shape.format_byte_range();
423 self.data.read_at(range.start).unwrap()
424 }
425
426 pub fn unit_size(&self) -> u16 {
428 let range = self.shape.unit_size_byte_range();
429 self.data.read_at(range.start).unwrap()
430 }
431
432 pub fn n_units(&self) -> u16 {
434 let range = self.shape.n_units_byte_range();
435 self.data.read_at(range.start).unwrap()
436 }
437
438 pub fn search_range(&self) -> u16 {
440 let range = self.shape.search_range_byte_range();
441 self.data.read_at(range.start).unwrap()
442 }
443
444 pub fn entry_selector(&self) -> u16 {
446 let range = self.shape.entry_selector_byte_range();
447 self.data.read_at(range.start).unwrap()
448 }
449
450 pub fn range_shift(&self) -> u16 {
452 let range = self.shape.range_shift_byte_range();
453 self.data.read_at(range.start).unwrap()
454 }
455
456 pub fn segments(&self) -> &'a [LookupSegment4] {
458 let range = self.shape.segments_byte_range();
459 self.data.read_array(range).unwrap()
460 }
461}
462
463#[cfg(feature = "experimental_traverse")]
464impl<'a> SomeTable<'a> for Lookup4<'a> {
465 fn type_name(&self) -> &str {
466 "Lookup4"
467 }
468 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
469 match idx {
470 0usize => Some(Field::new("format", self.format())),
471 1usize => Some(Field::new("unit_size", self.unit_size())),
472 2usize => Some(Field::new("n_units", self.n_units())),
473 3usize => Some(Field::new("search_range", self.search_range())),
474 4usize => Some(Field::new("entry_selector", self.entry_selector())),
475 5usize => Some(Field::new("range_shift", self.range_shift())),
476 6usize => Some(Field::new(
477 "segments",
478 traversal::FieldType::array_of_records(
479 stringify!(LookupSegment4),
480 self.segments(),
481 self.offset_data(),
482 ),
483 )),
484 _ => None,
485 }
486 }
487}
488
489#[cfg(feature = "experimental_traverse")]
490#[allow(clippy::needless_lifetimes)]
491impl<'a> std::fmt::Debug for Lookup4<'a> {
492 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
493 (self as &dyn SomeTable<'a>).fmt(f)
494 }
495}
496
497#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
499#[repr(C)]
500#[repr(packed)]
501pub struct LookupSegment4 {
502 pub last_glyph: BigEndian<u16>,
504 pub first_glyph: BigEndian<u16>,
506 pub value_offset: BigEndian<u16>,
508}
509
510impl LookupSegment4 {
511 pub fn last_glyph(&self) -> u16 {
513 self.last_glyph.get()
514 }
515
516 pub fn first_glyph(&self) -> u16 {
518 self.first_glyph.get()
519 }
520
521 pub fn value_offset(&self) -> u16 {
523 self.value_offset.get()
524 }
525}
526
527impl FixedSize for LookupSegment4 {
528 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
529}
530
531#[cfg(feature = "experimental_traverse")]
532impl<'a> SomeRecord<'a> for LookupSegment4 {
533 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
534 RecordResolver {
535 name: "LookupSegment4",
536 get_field: Box::new(move |idx, _data| match idx {
537 0usize => Some(Field::new("last_glyph", self.last_glyph())),
538 1usize => Some(Field::new("first_glyph", self.first_glyph())),
539 2usize => Some(Field::new("value_offset", self.value_offset())),
540 _ => None,
541 }),
542 data,
543 }
544 }
545}
546
547impl Format<u16> for Lookup6Marker {
548 const FORMAT: u16 = 6;
549}
550
551#[derive(Debug, Clone, Copy)]
554#[doc(hidden)]
555pub struct Lookup6Marker {
556 entries_data_byte_len: usize,
557}
558
559impl Lookup6Marker {
560 pub fn format_byte_range(&self) -> Range<usize> {
561 let start = 0;
562 start..start + u16::RAW_BYTE_LEN
563 }
564
565 pub fn unit_size_byte_range(&self) -> Range<usize> {
566 let start = self.format_byte_range().end;
567 start..start + u16::RAW_BYTE_LEN
568 }
569
570 pub fn n_units_byte_range(&self) -> Range<usize> {
571 let start = self.unit_size_byte_range().end;
572 start..start + u16::RAW_BYTE_LEN
573 }
574
575 pub fn search_range_byte_range(&self) -> Range<usize> {
576 let start = self.n_units_byte_range().end;
577 start..start + u16::RAW_BYTE_LEN
578 }
579
580 pub fn entry_selector_byte_range(&self) -> Range<usize> {
581 let start = self.search_range_byte_range().end;
582 start..start + u16::RAW_BYTE_LEN
583 }
584
585 pub fn range_shift_byte_range(&self) -> Range<usize> {
586 let start = self.entry_selector_byte_range().end;
587 start..start + u16::RAW_BYTE_LEN
588 }
589
590 pub fn entries_data_byte_range(&self) -> Range<usize> {
591 let start = self.range_shift_byte_range().end;
592 start..start + self.entries_data_byte_len
593 }
594}
595
596impl MinByteRange for Lookup6Marker {
597 fn min_byte_range(&self) -> Range<usize> {
598 0..self.entries_data_byte_range().end
599 }
600}
601
602impl<'a> FontRead<'a> for Lookup6<'a> {
603 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
604 let mut cursor = data.cursor();
605 cursor.advance::<u16>();
606 let unit_size: u16 = cursor.read()?;
607 let n_units: u16 = cursor.read()?;
608 cursor.advance::<u16>();
609 cursor.advance::<u16>();
610 cursor.advance::<u16>();
611 let entries_data_byte_len = (transforms::add_multiply(unit_size, 0_usize, n_units))
612 .checked_mul(u8::RAW_BYTE_LEN)
613 .ok_or(ReadError::OutOfBounds)?;
614 cursor.advance_by(entries_data_byte_len);
615 cursor.finish(Lookup6Marker {
616 entries_data_byte_len,
617 })
618 }
619}
620
621pub type Lookup6<'a> = TableRef<'a, Lookup6Marker>;
624
625#[allow(clippy::needless_lifetimes)]
626impl<'a> Lookup6<'a> {
627 pub fn format(&self) -> u16 {
629 let range = self.shape.format_byte_range();
630 self.data.read_at(range.start).unwrap()
631 }
632
633 pub fn unit_size(&self) -> u16 {
635 let range = self.shape.unit_size_byte_range();
636 self.data.read_at(range.start).unwrap()
637 }
638
639 pub fn n_units(&self) -> u16 {
641 let range = self.shape.n_units_byte_range();
642 self.data.read_at(range.start).unwrap()
643 }
644
645 pub fn search_range(&self) -> u16 {
647 let range = self.shape.search_range_byte_range();
648 self.data.read_at(range.start).unwrap()
649 }
650
651 pub fn entry_selector(&self) -> u16 {
653 let range = self.shape.entry_selector_byte_range();
654 self.data.read_at(range.start).unwrap()
655 }
656
657 pub fn range_shift(&self) -> u16 {
659 let range = self.shape.range_shift_byte_range();
660 self.data.read_at(range.start).unwrap()
661 }
662
663 pub fn entries_data(&self) -> &'a [u8] {
665 let range = self.shape.entries_data_byte_range();
666 self.data.read_array(range).unwrap()
667 }
668}
669
670#[cfg(feature = "experimental_traverse")]
671impl<'a> SomeTable<'a> for Lookup6<'a> {
672 fn type_name(&self) -> &str {
673 "Lookup6"
674 }
675 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
676 match idx {
677 0usize => Some(Field::new("format", self.format())),
678 1usize => Some(Field::new("unit_size", self.unit_size())),
679 2usize => Some(Field::new("n_units", self.n_units())),
680 3usize => Some(Field::new("search_range", self.search_range())),
681 4usize => Some(Field::new("entry_selector", self.entry_selector())),
682 5usize => Some(Field::new("range_shift", self.range_shift())),
683 6usize => Some(Field::new("entries_data", self.entries_data())),
684 _ => None,
685 }
686 }
687}
688
689#[cfg(feature = "experimental_traverse")]
690#[allow(clippy::needless_lifetimes)]
691impl<'a> std::fmt::Debug for Lookup6<'a> {
692 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
693 (self as &dyn SomeTable<'a>).fmt(f)
694 }
695}
696
697impl Format<u16> for Lookup8Marker {
698 const FORMAT: u16 = 8;
699}
700
701#[derive(Debug, Clone, Copy)]
704#[doc(hidden)]
705pub struct Lookup8Marker {
706 value_array_byte_len: usize,
707}
708
709impl Lookup8Marker {
710 pub fn format_byte_range(&self) -> Range<usize> {
711 let start = 0;
712 start..start + u16::RAW_BYTE_LEN
713 }
714
715 pub fn first_glyph_byte_range(&self) -> Range<usize> {
716 let start = self.format_byte_range().end;
717 start..start + u16::RAW_BYTE_LEN
718 }
719
720 pub fn glyph_count_byte_range(&self) -> Range<usize> {
721 let start = self.first_glyph_byte_range().end;
722 start..start + u16::RAW_BYTE_LEN
723 }
724
725 pub fn value_array_byte_range(&self) -> Range<usize> {
726 let start = self.glyph_count_byte_range().end;
727 start..start + self.value_array_byte_len
728 }
729}
730
731impl MinByteRange for Lookup8Marker {
732 fn min_byte_range(&self) -> Range<usize> {
733 0..self.value_array_byte_range().end
734 }
735}
736
737impl<'a> FontRead<'a> for Lookup8<'a> {
738 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
739 let mut cursor = data.cursor();
740 cursor.advance::<u16>();
741 cursor.advance::<u16>();
742 let glyph_count: u16 = cursor.read()?;
743 let value_array_byte_len = (glyph_count as usize)
744 .checked_mul(u16::RAW_BYTE_LEN)
745 .ok_or(ReadError::OutOfBounds)?;
746 cursor.advance_by(value_array_byte_len);
747 cursor.finish(Lookup8Marker {
748 value_array_byte_len,
749 })
750 }
751}
752
753pub type Lookup8<'a> = TableRef<'a, Lookup8Marker>;
756
757#[allow(clippy::needless_lifetimes)]
758impl<'a> Lookup8<'a> {
759 pub fn format(&self) -> u16 {
761 let range = self.shape.format_byte_range();
762 self.data.read_at(range.start).unwrap()
763 }
764
765 pub fn first_glyph(&self) -> u16 {
767 let range = self.shape.first_glyph_byte_range();
768 self.data.read_at(range.start).unwrap()
769 }
770
771 pub fn glyph_count(&self) -> u16 {
774 let range = self.shape.glyph_count_byte_range();
775 self.data.read_at(range.start).unwrap()
776 }
777
778 pub fn value_array(&self) -> &'a [BigEndian<u16>] {
781 let range = self.shape.value_array_byte_range();
782 self.data.read_array(range).unwrap()
783 }
784}
785
786#[cfg(feature = "experimental_traverse")]
787impl<'a> SomeTable<'a> for Lookup8<'a> {
788 fn type_name(&self) -> &str {
789 "Lookup8"
790 }
791 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
792 match idx {
793 0usize => Some(Field::new("format", self.format())),
794 1usize => Some(Field::new("first_glyph", self.first_glyph())),
795 2usize => Some(Field::new("glyph_count", self.glyph_count())),
796 3usize => Some(Field::new("value_array", self.value_array())),
797 _ => None,
798 }
799 }
800}
801
802#[cfg(feature = "experimental_traverse")]
803#[allow(clippy::needless_lifetimes)]
804impl<'a> std::fmt::Debug for Lookup8<'a> {
805 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
806 (self as &dyn SomeTable<'a>).fmt(f)
807 }
808}
809
810impl Format<u16> for Lookup10Marker {
811 const FORMAT: u16 = 10;
812}
813
814#[derive(Debug, Clone, Copy)]
817#[doc(hidden)]
818pub struct Lookup10Marker {
819 values_data_byte_len: usize,
820}
821
822impl Lookup10Marker {
823 pub fn format_byte_range(&self) -> Range<usize> {
824 let start = 0;
825 start..start + u16::RAW_BYTE_LEN
826 }
827
828 pub fn unit_size_byte_range(&self) -> Range<usize> {
829 let start = self.format_byte_range().end;
830 start..start + u16::RAW_BYTE_LEN
831 }
832
833 pub fn first_glyph_byte_range(&self) -> Range<usize> {
834 let start = self.unit_size_byte_range().end;
835 start..start + u16::RAW_BYTE_LEN
836 }
837
838 pub fn glyph_count_byte_range(&self) -> Range<usize> {
839 let start = self.first_glyph_byte_range().end;
840 start..start + u16::RAW_BYTE_LEN
841 }
842
843 pub fn values_data_byte_range(&self) -> Range<usize> {
844 let start = self.glyph_count_byte_range().end;
845 start..start + self.values_data_byte_len
846 }
847}
848
849impl MinByteRange for Lookup10Marker {
850 fn min_byte_range(&self) -> Range<usize> {
851 0..self.values_data_byte_range().end
852 }
853}
854
855impl<'a> FontRead<'a> for Lookup10<'a> {
856 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
857 let mut cursor = data.cursor();
858 cursor.advance::<u16>();
859 let unit_size: u16 = cursor.read()?;
860 cursor.advance::<u16>();
861 let glyph_count: u16 = cursor.read()?;
862 let values_data_byte_len = (transforms::add_multiply(glyph_count, 0_usize, unit_size))
863 .checked_mul(u8::RAW_BYTE_LEN)
864 .ok_or(ReadError::OutOfBounds)?;
865 cursor.advance_by(values_data_byte_len);
866 cursor.finish(Lookup10Marker {
867 values_data_byte_len,
868 })
869 }
870}
871
872pub type Lookup10<'a> = TableRef<'a, Lookup10Marker>;
875
876#[allow(clippy::needless_lifetimes)]
877impl<'a> Lookup10<'a> {
878 pub fn format(&self) -> u16 {
880 let range = self.shape.format_byte_range();
881 self.data.read_at(range.start).unwrap()
882 }
883
884 pub fn unit_size(&self) -> u16 {
887 let range = self.shape.unit_size_byte_range();
888 self.data.read_at(range.start).unwrap()
889 }
890
891 pub fn first_glyph(&self) -> u16 {
893 let range = self.shape.first_glyph_byte_range();
894 self.data.read_at(range.start).unwrap()
895 }
896
897 pub fn glyph_count(&self) -> u16 {
900 let range = self.shape.glyph_count_byte_range();
901 self.data.read_at(range.start).unwrap()
902 }
903
904 pub fn values_data(&self) -> &'a [u8] {
907 let range = self.shape.values_data_byte_range();
908 self.data.read_array(range).unwrap()
909 }
910}
911
912#[cfg(feature = "experimental_traverse")]
913impl<'a> SomeTable<'a> for Lookup10<'a> {
914 fn type_name(&self) -> &str {
915 "Lookup10"
916 }
917 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
918 match idx {
919 0usize => Some(Field::new("format", self.format())),
920 1usize => Some(Field::new("unit_size", self.unit_size())),
921 2usize => Some(Field::new("first_glyph", self.first_glyph())),
922 3usize => Some(Field::new("glyph_count", self.glyph_count())),
923 4usize => Some(Field::new("values_data", self.values_data())),
924 _ => None,
925 }
926 }
927}
928
929#[cfg(feature = "experimental_traverse")]
930#[allow(clippy::needless_lifetimes)]
931impl<'a> std::fmt::Debug for Lookup10<'a> {
932 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
933 (self as &dyn SomeTable<'a>).fmt(f)
934 }
935}
936
937#[derive(Debug, Clone, Copy)]
939#[doc(hidden)]
940pub struct StateHeaderMarker {}
941
942impl StateHeaderMarker {
943 pub fn state_size_byte_range(&self) -> Range<usize> {
944 let start = 0;
945 start..start + u16::RAW_BYTE_LEN
946 }
947
948 pub fn class_table_offset_byte_range(&self) -> Range<usize> {
949 let start = self.state_size_byte_range().end;
950 start..start + Offset16::RAW_BYTE_LEN
951 }
952
953 pub fn state_array_offset_byte_range(&self) -> Range<usize> {
954 let start = self.class_table_offset_byte_range().end;
955 start..start + Offset16::RAW_BYTE_LEN
956 }
957
958 pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
959 let start = self.state_array_offset_byte_range().end;
960 start..start + Offset16::RAW_BYTE_LEN
961 }
962}
963
964impl MinByteRange for StateHeaderMarker {
965 fn min_byte_range(&self) -> Range<usize> {
966 0..self.entry_table_offset_byte_range().end
967 }
968}
969
970impl<'a> FontRead<'a> for StateHeader<'a> {
971 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
972 let mut cursor = data.cursor();
973 cursor.advance::<u16>();
974 cursor.advance::<Offset16>();
975 cursor.advance::<Offset16>();
976 cursor.advance::<Offset16>();
977 cursor.finish(StateHeaderMarker {})
978 }
979}
980
981pub type StateHeader<'a> = TableRef<'a, StateHeaderMarker>;
983
984#[allow(clippy::needless_lifetimes)]
985impl<'a> StateHeader<'a> {
986 pub fn state_size(&self) -> u16 {
989 let range = self.shape.state_size_byte_range();
990 self.data.read_at(range.start).unwrap()
991 }
992
993 pub fn class_table_offset(&self) -> Offset16 {
995 let range = self.shape.class_table_offset_byte_range();
996 self.data.read_at(range.start).unwrap()
997 }
998
999 pub fn class_table(&self) -> Result<ClassSubtable<'a>, ReadError> {
1001 let data = self.data;
1002 self.class_table_offset().resolve(data)
1003 }
1004
1005 pub fn state_array_offset(&self) -> Offset16 {
1007 let range = self.shape.state_array_offset_byte_range();
1008 self.data.read_at(range.start).unwrap()
1009 }
1010
1011 pub fn state_array(&self) -> Result<RawBytes<'a>, ReadError> {
1013 let data = self.data;
1014 self.state_array_offset().resolve(data)
1015 }
1016
1017 pub fn entry_table_offset(&self) -> Offset16 {
1019 let range = self.shape.entry_table_offset_byte_range();
1020 self.data.read_at(range.start).unwrap()
1021 }
1022
1023 pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
1025 let data = self.data;
1026 self.entry_table_offset().resolve(data)
1027 }
1028}
1029
1030#[cfg(feature = "experimental_traverse")]
1031impl<'a> SomeTable<'a> for StateHeader<'a> {
1032 fn type_name(&self) -> &str {
1033 "StateHeader"
1034 }
1035 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1036 match idx {
1037 0usize => Some(Field::new("state_size", self.state_size())),
1038 1usize => Some(Field::new(
1039 "class_table_offset",
1040 FieldType::offset(self.class_table_offset(), self.class_table()),
1041 )),
1042 2usize => Some(Field::new(
1043 "state_array_offset",
1044 FieldType::offset(self.state_array_offset(), self.state_array()),
1045 )),
1046 3usize => Some(Field::new(
1047 "entry_table_offset",
1048 FieldType::offset(self.entry_table_offset(), self.entry_table()),
1049 )),
1050 _ => None,
1051 }
1052 }
1053}
1054
1055#[cfg(feature = "experimental_traverse")]
1056#[allow(clippy::needless_lifetimes)]
1057impl<'a> std::fmt::Debug for StateHeader<'a> {
1058 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1059 (self as &dyn SomeTable<'a>).fmt(f)
1060 }
1061}
1062
1063#[derive(Debug, Clone, Copy)]
1065#[doc(hidden)]
1066pub struct ClassSubtableMarker {
1067 class_array_byte_len: usize,
1068}
1069
1070impl ClassSubtableMarker {
1071 pub fn first_glyph_byte_range(&self) -> Range<usize> {
1072 let start = 0;
1073 start..start + u16::RAW_BYTE_LEN
1074 }
1075
1076 pub fn n_glyphs_byte_range(&self) -> Range<usize> {
1077 let start = self.first_glyph_byte_range().end;
1078 start..start + u16::RAW_BYTE_LEN
1079 }
1080
1081 pub fn class_array_byte_range(&self) -> Range<usize> {
1082 let start = self.n_glyphs_byte_range().end;
1083 start..start + self.class_array_byte_len
1084 }
1085}
1086
1087impl MinByteRange for ClassSubtableMarker {
1088 fn min_byte_range(&self) -> Range<usize> {
1089 0..self.class_array_byte_range().end
1090 }
1091}
1092
1093impl<'a> FontRead<'a> for ClassSubtable<'a> {
1094 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1095 let mut cursor = data.cursor();
1096 cursor.advance::<u16>();
1097 let n_glyphs: u16 = cursor.read()?;
1098 let class_array_byte_len = (n_glyphs as usize)
1099 .checked_mul(u8::RAW_BYTE_LEN)
1100 .ok_or(ReadError::OutOfBounds)?;
1101 cursor.advance_by(class_array_byte_len);
1102 cursor.finish(ClassSubtableMarker {
1103 class_array_byte_len,
1104 })
1105 }
1106}
1107
1108pub type ClassSubtable<'a> = TableRef<'a, ClassSubtableMarker>;
1110
1111#[allow(clippy::needless_lifetimes)]
1112impl<'a> ClassSubtable<'a> {
1113 pub fn first_glyph(&self) -> u16 {
1115 let range = self.shape.first_glyph_byte_range();
1116 self.data.read_at(range.start).unwrap()
1117 }
1118
1119 pub fn n_glyphs(&self) -> u16 {
1121 let range = self.shape.n_glyphs_byte_range();
1122 self.data.read_at(range.start).unwrap()
1123 }
1124
1125 pub fn class_array(&self) -> &'a [u8] {
1128 let range = self.shape.class_array_byte_range();
1129 self.data.read_array(range).unwrap()
1130 }
1131}
1132
1133#[cfg(feature = "experimental_traverse")]
1134impl<'a> SomeTable<'a> for ClassSubtable<'a> {
1135 fn type_name(&self) -> &str {
1136 "ClassSubtable"
1137 }
1138 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1139 match idx {
1140 0usize => Some(Field::new("first_glyph", self.first_glyph())),
1141 1usize => Some(Field::new("n_glyphs", self.n_glyphs())),
1142 2usize => Some(Field::new("class_array", self.class_array())),
1143 _ => None,
1144 }
1145 }
1146}
1147
1148#[cfg(feature = "experimental_traverse")]
1149#[allow(clippy::needless_lifetimes)]
1150impl<'a> std::fmt::Debug for ClassSubtable<'a> {
1151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1152 (self as &dyn SomeTable<'a>).fmt(f)
1153 }
1154}
1155
1156#[derive(Debug, Clone, Copy)]
1158#[doc(hidden)]
1159pub struct RawBytesMarker {
1160 data_byte_len: usize,
1161}
1162
1163impl RawBytesMarker {
1164 pub fn data_byte_range(&self) -> Range<usize> {
1165 let start = 0;
1166 start..start + self.data_byte_len
1167 }
1168}
1169
1170impl MinByteRange for RawBytesMarker {
1171 fn min_byte_range(&self) -> Range<usize> {
1172 0..self.data_byte_range().end
1173 }
1174}
1175
1176impl<'a> FontRead<'a> for RawBytes<'a> {
1177 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1178 let mut cursor = data.cursor();
1179 let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
1180 cursor.advance_by(data_byte_len);
1181 cursor.finish(RawBytesMarker { data_byte_len })
1182 }
1183}
1184
1185pub type RawBytes<'a> = TableRef<'a, RawBytesMarker>;
1187
1188#[allow(clippy::needless_lifetimes)]
1189impl<'a> RawBytes<'a> {
1190 pub fn data(&self) -> &'a [u8] {
1191 let range = self.shape.data_byte_range();
1192 self.data.read_array(range).unwrap()
1193 }
1194}
1195
1196#[cfg(feature = "experimental_traverse")]
1197impl<'a> SomeTable<'a> for RawBytes<'a> {
1198 fn type_name(&self) -> &str {
1199 "RawBytes"
1200 }
1201 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1202 match idx {
1203 0usize => Some(Field::new("data", self.data())),
1204 _ => None,
1205 }
1206 }
1207}
1208
1209#[cfg(feature = "experimental_traverse")]
1210#[allow(clippy::needless_lifetimes)]
1211impl<'a> std::fmt::Debug for RawBytes<'a> {
1212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1213 (self as &dyn SomeTable<'a>).fmt(f)
1214 }
1215}
1216
1217#[derive(Debug, Clone, Copy)]
1219#[doc(hidden)]
1220pub struct StxHeaderMarker {}
1221
1222impl StxHeaderMarker {
1223 pub fn n_classes_byte_range(&self) -> Range<usize> {
1224 let start = 0;
1225 start..start + u32::RAW_BYTE_LEN
1226 }
1227
1228 pub fn class_table_offset_byte_range(&self) -> Range<usize> {
1229 let start = self.n_classes_byte_range().end;
1230 start..start + Offset32::RAW_BYTE_LEN
1231 }
1232
1233 pub fn state_array_offset_byte_range(&self) -> Range<usize> {
1234 let start = self.class_table_offset_byte_range().end;
1235 start..start + Offset32::RAW_BYTE_LEN
1236 }
1237
1238 pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
1239 let start = self.state_array_offset_byte_range().end;
1240 start..start + Offset32::RAW_BYTE_LEN
1241 }
1242}
1243
1244impl MinByteRange for StxHeaderMarker {
1245 fn min_byte_range(&self) -> Range<usize> {
1246 0..self.entry_table_offset_byte_range().end
1247 }
1248}
1249
1250impl<'a> FontRead<'a> for StxHeader<'a> {
1251 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1252 let mut cursor = data.cursor();
1253 cursor.advance::<u32>();
1254 cursor.advance::<Offset32>();
1255 cursor.advance::<Offset32>();
1256 cursor.advance::<Offset32>();
1257 cursor.finish(StxHeaderMarker {})
1258 }
1259}
1260
1261pub type StxHeader<'a> = TableRef<'a, StxHeaderMarker>;
1263
1264#[allow(clippy::needless_lifetimes)]
1265impl<'a> StxHeader<'a> {
1266 pub fn n_classes(&self) -> u32 {
1268 let range = self.shape.n_classes_byte_range();
1269 self.data.read_at(range.start).unwrap()
1270 }
1271
1272 pub fn class_table_offset(&self) -> Offset32 {
1274 let range = self.shape.class_table_offset_byte_range();
1275 self.data.read_at(range.start).unwrap()
1276 }
1277
1278 pub fn class_table(&self) -> Result<LookupU16<'a>, ReadError> {
1280 let data = self.data;
1281 self.class_table_offset().resolve(data)
1282 }
1283
1284 pub fn state_array_offset(&self) -> Offset32 {
1286 let range = self.shape.state_array_offset_byte_range();
1287 self.data.read_at(range.start).unwrap()
1288 }
1289
1290 pub fn state_array(&self) -> Result<RawWords<'a>, ReadError> {
1292 let data = self.data;
1293 self.state_array_offset().resolve(data)
1294 }
1295
1296 pub fn entry_table_offset(&self) -> Offset32 {
1298 let range = self.shape.entry_table_offset_byte_range();
1299 self.data.read_at(range.start).unwrap()
1300 }
1301
1302 pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
1304 let data = self.data;
1305 self.entry_table_offset().resolve(data)
1306 }
1307}
1308
1309#[cfg(feature = "experimental_traverse")]
1310impl<'a> SomeTable<'a> for StxHeader<'a> {
1311 fn type_name(&self) -> &str {
1312 "StxHeader"
1313 }
1314 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1315 match idx {
1316 0usize => Some(Field::new("n_classes", self.n_classes())),
1317 1usize => Some(Field::new(
1318 "class_table_offset",
1319 FieldType::offset(self.class_table_offset(), self.class_table()),
1320 )),
1321 2usize => Some(Field::new(
1322 "state_array_offset",
1323 FieldType::offset(self.state_array_offset(), self.state_array()),
1324 )),
1325 3usize => Some(Field::new(
1326 "entry_table_offset",
1327 FieldType::offset(self.entry_table_offset(), self.entry_table()),
1328 )),
1329 _ => None,
1330 }
1331 }
1332}
1333
1334#[cfg(feature = "experimental_traverse")]
1335#[allow(clippy::needless_lifetimes)]
1336impl<'a> std::fmt::Debug for StxHeader<'a> {
1337 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1338 (self as &dyn SomeTable<'a>).fmt(f)
1339 }
1340}
1341
1342#[derive(Debug, Clone, Copy)]
1344#[doc(hidden)]
1345pub struct RawWordsMarker {
1346 data_byte_len: usize,
1347}
1348
1349impl RawWordsMarker {
1350 pub fn data_byte_range(&self) -> Range<usize> {
1351 let start = 0;
1352 start..start + self.data_byte_len
1353 }
1354}
1355
1356impl MinByteRange for RawWordsMarker {
1357 fn min_byte_range(&self) -> Range<usize> {
1358 0..self.data_byte_range().end
1359 }
1360}
1361
1362impl<'a> FontRead<'a> for RawWords<'a> {
1363 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1364 let mut cursor = data.cursor();
1365 let data_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
1366 cursor.advance_by(data_byte_len);
1367 cursor.finish(RawWordsMarker { data_byte_len })
1368 }
1369}
1370
1371pub type RawWords<'a> = TableRef<'a, RawWordsMarker>;
1373
1374#[allow(clippy::needless_lifetimes)]
1375impl<'a> RawWords<'a> {
1376 pub fn data(&self) -> &'a [BigEndian<u16>] {
1377 let range = self.shape.data_byte_range();
1378 self.data.read_array(range).unwrap()
1379 }
1380}
1381
1382#[cfg(feature = "experimental_traverse")]
1383impl<'a> SomeTable<'a> for RawWords<'a> {
1384 fn type_name(&self) -> &str {
1385 "RawWords"
1386 }
1387 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1388 match idx {
1389 0usize => Some(Field::new("data", self.data())),
1390 _ => None,
1391 }
1392 }
1393}
1394
1395#[cfg(feature = "experimental_traverse")]
1396#[allow(clippy::needless_lifetimes)]
1397impl<'a> std::fmt::Debug for RawWords<'a> {
1398 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1399 (self as &dyn SomeTable<'a>).fmt(f)
1400 }
1401}