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 cursor.advance::<u16>();
743 let value_array_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
744 cursor.advance_by(value_array_byte_len);
745 cursor.finish(Lookup8Marker {
746 value_array_byte_len,
747 })
748 }
749}
750
751pub type Lookup8<'a> = TableRef<'a, Lookup8Marker>;
754
755#[allow(clippy::needless_lifetimes)]
756impl<'a> Lookup8<'a> {
757 pub fn format(&self) -> u16 {
759 let range = self.shape.format_byte_range();
760 self.data.read_at(range.start).unwrap()
761 }
762
763 pub fn first_glyph(&self) -> u16 {
765 let range = self.shape.first_glyph_byte_range();
766 self.data.read_at(range.start).unwrap()
767 }
768
769 pub fn glyph_count(&self) -> u16 {
772 let range = self.shape.glyph_count_byte_range();
773 self.data.read_at(range.start).unwrap()
774 }
775
776 pub fn value_array(&self) -> &'a [BigEndian<u16>] {
779 let range = self.shape.value_array_byte_range();
780 self.data.read_array(range).unwrap()
781 }
782}
783
784#[cfg(feature = "experimental_traverse")]
785impl<'a> SomeTable<'a> for Lookup8<'a> {
786 fn type_name(&self) -> &str {
787 "Lookup8"
788 }
789 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
790 match idx {
791 0usize => Some(Field::new("format", self.format())),
792 1usize => Some(Field::new("first_glyph", self.first_glyph())),
793 2usize => Some(Field::new("glyph_count", self.glyph_count())),
794 3usize => Some(Field::new("value_array", self.value_array())),
795 _ => None,
796 }
797 }
798}
799
800#[cfg(feature = "experimental_traverse")]
801#[allow(clippy::needless_lifetimes)]
802impl<'a> std::fmt::Debug for Lookup8<'a> {
803 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
804 (self as &dyn SomeTable<'a>).fmt(f)
805 }
806}
807
808impl Format<u16> for Lookup10Marker {
809 const FORMAT: u16 = 10;
810}
811
812#[derive(Debug, Clone, Copy)]
815#[doc(hidden)]
816pub struct Lookup10Marker {
817 values_data_byte_len: usize,
818}
819
820impl Lookup10Marker {
821 pub fn format_byte_range(&self) -> Range<usize> {
822 let start = 0;
823 start..start + u16::RAW_BYTE_LEN
824 }
825
826 pub fn unit_size_byte_range(&self) -> Range<usize> {
827 let start = self.format_byte_range().end;
828 start..start + u16::RAW_BYTE_LEN
829 }
830
831 pub fn first_glyph_byte_range(&self) -> Range<usize> {
832 let start = self.unit_size_byte_range().end;
833 start..start + u16::RAW_BYTE_LEN
834 }
835
836 pub fn glyph_count_byte_range(&self) -> Range<usize> {
837 let start = self.first_glyph_byte_range().end;
838 start..start + u16::RAW_BYTE_LEN
839 }
840
841 pub fn values_data_byte_range(&self) -> Range<usize> {
842 let start = self.glyph_count_byte_range().end;
843 start..start + self.values_data_byte_len
844 }
845}
846
847impl MinByteRange for Lookup10Marker {
848 fn min_byte_range(&self) -> Range<usize> {
849 0..self.values_data_byte_range().end
850 }
851}
852
853impl<'a> FontRead<'a> for Lookup10<'a> {
854 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
855 let mut cursor = data.cursor();
856 cursor.advance::<u16>();
857 cursor.advance::<u16>();
858 cursor.advance::<u16>();
859 cursor.advance::<u16>();
860 let values_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
861 cursor.advance_by(values_data_byte_len);
862 cursor.finish(Lookup10Marker {
863 values_data_byte_len,
864 })
865 }
866}
867
868pub type Lookup10<'a> = TableRef<'a, Lookup10Marker>;
871
872#[allow(clippy::needless_lifetimes)]
873impl<'a> Lookup10<'a> {
874 pub fn format(&self) -> u16 {
876 let range = self.shape.format_byte_range();
877 self.data.read_at(range.start).unwrap()
878 }
879
880 pub fn unit_size(&self) -> u16 {
883 let range = self.shape.unit_size_byte_range();
884 self.data.read_at(range.start).unwrap()
885 }
886
887 pub fn first_glyph(&self) -> u16 {
889 let range = self.shape.first_glyph_byte_range();
890 self.data.read_at(range.start).unwrap()
891 }
892
893 pub fn glyph_count(&self) -> u16 {
896 let range = self.shape.glyph_count_byte_range();
897 self.data.read_at(range.start).unwrap()
898 }
899
900 pub fn values_data(&self) -> &'a [u8] {
903 let range = self.shape.values_data_byte_range();
904 self.data.read_array(range).unwrap()
905 }
906}
907
908#[cfg(feature = "experimental_traverse")]
909impl<'a> SomeTable<'a> for Lookup10<'a> {
910 fn type_name(&self) -> &str {
911 "Lookup10"
912 }
913 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
914 match idx {
915 0usize => Some(Field::new("format", self.format())),
916 1usize => Some(Field::new("unit_size", self.unit_size())),
917 2usize => Some(Field::new("first_glyph", self.first_glyph())),
918 3usize => Some(Field::new("glyph_count", self.glyph_count())),
919 4usize => Some(Field::new("values_data", self.values_data())),
920 _ => None,
921 }
922 }
923}
924
925#[cfg(feature = "experimental_traverse")]
926#[allow(clippy::needless_lifetimes)]
927impl<'a> std::fmt::Debug for Lookup10<'a> {
928 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
929 (self as &dyn SomeTable<'a>).fmt(f)
930 }
931}
932
933#[derive(Debug, Clone, Copy)]
935#[doc(hidden)]
936pub struct StateHeaderMarker {}
937
938impl StateHeaderMarker {
939 pub fn state_size_byte_range(&self) -> Range<usize> {
940 let start = 0;
941 start..start + u16::RAW_BYTE_LEN
942 }
943
944 pub fn class_table_offset_byte_range(&self) -> Range<usize> {
945 let start = self.state_size_byte_range().end;
946 start..start + Offset16::RAW_BYTE_LEN
947 }
948
949 pub fn state_array_offset_byte_range(&self) -> Range<usize> {
950 let start = self.class_table_offset_byte_range().end;
951 start..start + Offset16::RAW_BYTE_LEN
952 }
953
954 pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
955 let start = self.state_array_offset_byte_range().end;
956 start..start + Offset16::RAW_BYTE_LEN
957 }
958}
959
960impl MinByteRange for StateHeaderMarker {
961 fn min_byte_range(&self) -> Range<usize> {
962 0..self.entry_table_offset_byte_range().end
963 }
964}
965
966impl<'a> FontRead<'a> for StateHeader<'a> {
967 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
968 let mut cursor = data.cursor();
969 cursor.advance::<u16>();
970 cursor.advance::<Offset16>();
971 cursor.advance::<Offset16>();
972 cursor.advance::<Offset16>();
973 cursor.finish(StateHeaderMarker {})
974 }
975}
976
977pub type StateHeader<'a> = TableRef<'a, StateHeaderMarker>;
979
980#[allow(clippy::needless_lifetimes)]
981impl<'a> StateHeader<'a> {
982 pub fn state_size(&self) -> u16 {
985 let range = self.shape.state_size_byte_range();
986 self.data.read_at(range.start).unwrap()
987 }
988
989 pub fn class_table_offset(&self) -> Offset16 {
991 let range = self.shape.class_table_offset_byte_range();
992 self.data.read_at(range.start).unwrap()
993 }
994
995 pub fn class_table(&self) -> Result<ClassSubtable<'a>, ReadError> {
997 let data = self.data;
998 self.class_table_offset().resolve(data)
999 }
1000
1001 pub fn state_array_offset(&self) -> Offset16 {
1003 let range = self.shape.state_array_offset_byte_range();
1004 self.data.read_at(range.start).unwrap()
1005 }
1006
1007 pub fn state_array(&self) -> Result<RawBytes<'a>, ReadError> {
1009 let data = self.data;
1010 self.state_array_offset().resolve(data)
1011 }
1012
1013 pub fn entry_table_offset(&self) -> Offset16 {
1015 let range = self.shape.entry_table_offset_byte_range();
1016 self.data.read_at(range.start).unwrap()
1017 }
1018
1019 pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
1021 let data = self.data;
1022 self.entry_table_offset().resolve(data)
1023 }
1024}
1025
1026#[cfg(feature = "experimental_traverse")]
1027impl<'a> SomeTable<'a> for StateHeader<'a> {
1028 fn type_name(&self) -> &str {
1029 "StateHeader"
1030 }
1031 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1032 match idx {
1033 0usize => Some(Field::new("state_size", self.state_size())),
1034 1usize => Some(Field::new(
1035 "class_table_offset",
1036 FieldType::offset(self.class_table_offset(), self.class_table()),
1037 )),
1038 2usize => Some(Field::new(
1039 "state_array_offset",
1040 FieldType::offset(self.state_array_offset(), self.state_array()),
1041 )),
1042 3usize => Some(Field::new(
1043 "entry_table_offset",
1044 FieldType::offset(self.entry_table_offset(), self.entry_table()),
1045 )),
1046 _ => None,
1047 }
1048 }
1049}
1050
1051#[cfg(feature = "experimental_traverse")]
1052#[allow(clippy::needless_lifetimes)]
1053impl<'a> std::fmt::Debug for StateHeader<'a> {
1054 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1055 (self as &dyn SomeTable<'a>).fmt(f)
1056 }
1057}
1058
1059#[derive(Debug, Clone, Copy)]
1061#[doc(hidden)]
1062pub struct ClassSubtableMarker {
1063 class_array_byte_len: usize,
1064}
1065
1066impl ClassSubtableMarker {
1067 pub fn first_glyph_byte_range(&self) -> Range<usize> {
1068 let start = 0;
1069 start..start + u16::RAW_BYTE_LEN
1070 }
1071
1072 pub fn n_glyphs_byte_range(&self) -> Range<usize> {
1073 let start = self.first_glyph_byte_range().end;
1074 start..start + u16::RAW_BYTE_LEN
1075 }
1076
1077 pub fn class_array_byte_range(&self) -> Range<usize> {
1078 let start = self.n_glyphs_byte_range().end;
1079 start..start + self.class_array_byte_len
1080 }
1081}
1082
1083impl MinByteRange for ClassSubtableMarker {
1084 fn min_byte_range(&self) -> Range<usize> {
1085 0..self.class_array_byte_range().end
1086 }
1087}
1088
1089impl<'a> FontRead<'a> for ClassSubtable<'a> {
1090 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1091 let mut cursor = data.cursor();
1092 cursor.advance::<u16>();
1093 let n_glyphs: u16 = cursor.read()?;
1094 let class_array_byte_len = (n_glyphs as usize)
1095 .checked_mul(u8::RAW_BYTE_LEN)
1096 .ok_or(ReadError::OutOfBounds)?;
1097 cursor.advance_by(class_array_byte_len);
1098 cursor.finish(ClassSubtableMarker {
1099 class_array_byte_len,
1100 })
1101 }
1102}
1103
1104pub type ClassSubtable<'a> = TableRef<'a, ClassSubtableMarker>;
1106
1107#[allow(clippy::needless_lifetimes)]
1108impl<'a> ClassSubtable<'a> {
1109 pub fn first_glyph(&self) -> u16 {
1111 let range = self.shape.first_glyph_byte_range();
1112 self.data.read_at(range.start).unwrap()
1113 }
1114
1115 pub fn n_glyphs(&self) -> u16 {
1117 let range = self.shape.n_glyphs_byte_range();
1118 self.data.read_at(range.start).unwrap()
1119 }
1120
1121 pub fn class_array(&self) -> &'a [u8] {
1124 let range = self.shape.class_array_byte_range();
1125 self.data.read_array(range).unwrap()
1126 }
1127}
1128
1129#[cfg(feature = "experimental_traverse")]
1130impl<'a> SomeTable<'a> for ClassSubtable<'a> {
1131 fn type_name(&self) -> &str {
1132 "ClassSubtable"
1133 }
1134 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1135 match idx {
1136 0usize => Some(Field::new("first_glyph", self.first_glyph())),
1137 1usize => Some(Field::new("n_glyphs", self.n_glyphs())),
1138 2usize => Some(Field::new("class_array", self.class_array())),
1139 _ => None,
1140 }
1141 }
1142}
1143
1144#[cfg(feature = "experimental_traverse")]
1145#[allow(clippy::needless_lifetimes)]
1146impl<'a> std::fmt::Debug for ClassSubtable<'a> {
1147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1148 (self as &dyn SomeTable<'a>).fmt(f)
1149 }
1150}
1151
1152#[derive(Debug, Clone, Copy)]
1154#[doc(hidden)]
1155pub struct RawBytesMarker {
1156 data_byte_len: usize,
1157}
1158
1159impl RawBytesMarker {
1160 pub fn data_byte_range(&self) -> Range<usize> {
1161 let start = 0;
1162 start..start + self.data_byte_len
1163 }
1164}
1165
1166impl MinByteRange for RawBytesMarker {
1167 fn min_byte_range(&self) -> Range<usize> {
1168 0..self.data_byte_range().end
1169 }
1170}
1171
1172impl<'a> FontRead<'a> for RawBytes<'a> {
1173 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1174 let mut cursor = data.cursor();
1175 let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
1176 cursor.advance_by(data_byte_len);
1177 cursor.finish(RawBytesMarker { data_byte_len })
1178 }
1179}
1180
1181pub type RawBytes<'a> = TableRef<'a, RawBytesMarker>;
1183
1184#[allow(clippy::needless_lifetimes)]
1185impl<'a> RawBytes<'a> {
1186 pub fn data(&self) -> &'a [u8] {
1187 let range = self.shape.data_byte_range();
1188 self.data.read_array(range).unwrap()
1189 }
1190}
1191
1192#[cfg(feature = "experimental_traverse")]
1193impl<'a> SomeTable<'a> for RawBytes<'a> {
1194 fn type_name(&self) -> &str {
1195 "RawBytes"
1196 }
1197 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1198 match idx {
1199 0usize => Some(Field::new("data", self.data())),
1200 _ => None,
1201 }
1202 }
1203}
1204
1205#[cfg(feature = "experimental_traverse")]
1206#[allow(clippy::needless_lifetimes)]
1207impl<'a> std::fmt::Debug for RawBytes<'a> {
1208 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1209 (self as &dyn SomeTable<'a>).fmt(f)
1210 }
1211}
1212
1213#[derive(Debug, Clone, Copy)]
1215#[doc(hidden)]
1216pub struct StxHeaderMarker {}
1217
1218impl StxHeaderMarker {
1219 pub fn n_classes_byte_range(&self) -> Range<usize> {
1220 let start = 0;
1221 start..start + u32::RAW_BYTE_LEN
1222 }
1223
1224 pub fn class_table_offset_byte_range(&self) -> Range<usize> {
1225 let start = self.n_classes_byte_range().end;
1226 start..start + Offset32::RAW_BYTE_LEN
1227 }
1228
1229 pub fn state_array_offset_byte_range(&self) -> Range<usize> {
1230 let start = self.class_table_offset_byte_range().end;
1231 start..start + Offset32::RAW_BYTE_LEN
1232 }
1233
1234 pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
1235 let start = self.state_array_offset_byte_range().end;
1236 start..start + Offset32::RAW_BYTE_LEN
1237 }
1238}
1239
1240impl MinByteRange for StxHeaderMarker {
1241 fn min_byte_range(&self) -> Range<usize> {
1242 0..self.entry_table_offset_byte_range().end
1243 }
1244}
1245
1246impl<'a> FontRead<'a> for StxHeader<'a> {
1247 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1248 let mut cursor = data.cursor();
1249 cursor.advance::<u32>();
1250 cursor.advance::<Offset32>();
1251 cursor.advance::<Offset32>();
1252 cursor.advance::<Offset32>();
1253 cursor.finish(StxHeaderMarker {})
1254 }
1255}
1256
1257pub type StxHeader<'a> = TableRef<'a, StxHeaderMarker>;
1259
1260#[allow(clippy::needless_lifetimes)]
1261impl<'a> StxHeader<'a> {
1262 pub fn n_classes(&self) -> u32 {
1264 let range = self.shape.n_classes_byte_range();
1265 self.data.read_at(range.start).unwrap()
1266 }
1267
1268 pub fn class_table_offset(&self) -> Offset32 {
1270 let range = self.shape.class_table_offset_byte_range();
1271 self.data.read_at(range.start).unwrap()
1272 }
1273
1274 pub fn class_table(&self) -> Result<LookupU16<'a>, ReadError> {
1276 let data = self.data;
1277 self.class_table_offset().resolve(data)
1278 }
1279
1280 pub fn state_array_offset(&self) -> Offset32 {
1282 let range = self.shape.state_array_offset_byte_range();
1283 self.data.read_at(range.start).unwrap()
1284 }
1285
1286 pub fn state_array(&self) -> Result<RawWords<'a>, ReadError> {
1288 let data = self.data;
1289 self.state_array_offset().resolve(data)
1290 }
1291
1292 pub fn entry_table_offset(&self) -> Offset32 {
1294 let range = self.shape.entry_table_offset_byte_range();
1295 self.data.read_at(range.start).unwrap()
1296 }
1297
1298 pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
1300 let data = self.data;
1301 self.entry_table_offset().resolve(data)
1302 }
1303}
1304
1305#[cfg(feature = "experimental_traverse")]
1306impl<'a> SomeTable<'a> for StxHeader<'a> {
1307 fn type_name(&self) -> &str {
1308 "StxHeader"
1309 }
1310 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1311 match idx {
1312 0usize => Some(Field::new("n_classes", self.n_classes())),
1313 1usize => Some(Field::new(
1314 "class_table_offset",
1315 FieldType::offset(self.class_table_offset(), self.class_table()),
1316 )),
1317 2usize => Some(Field::new(
1318 "state_array_offset",
1319 FieldType::offset(self.state_array_offset(), self.state_array()),
1320 )),
1321 3usize => Some(Field::new(
1322 "entry_table_offset",
1323 FieldType::offset(self.entry_table_offset(), self.entry_table()),
1324 )),
1325 _ => None,
1326 }
1327 }
1328}
1329
1330#[cfg(feature = "experimental_traverse")]
1331#[allow(clippy::needless_lifetimes)]
1332impl<'a> std::fmt::Debug for StxHeader<'a> {
1333 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1334 (self as &dyn SomeTable<'a>).fmt(f)
1335 }
1336}
1337
1338#[derive(Debug, Clone, Copy)]
1340#[doc(hidden)]
1341pub struct RawWordsMarker {
1342 data_byte_len: usize,
1343}
1344
1345impl RawWordsMarker {
1346 pub fn data_byte_range(&self) -> Range<usize> {
1347 let start = 0;
1348 start..start + self.data_byte_len
1349 }
1350}
1351
1352impl MinByteRange for RawWordsMarker {
1353 fn min_byte_range(&self) -> Range<usize> {
1354 0..self.data_byte_range().end
1355 }
1356}
1357
1358impl<'a> FontRead<'a> for RawWords<'a> {
1359 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1360 let mut cursor = data.cursor();
1361 let data_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
1362 cursor.advance_by(data_byte_len);
1363 cursor.finish(RawWordsMarker { data_byte_len })
1364 }
1365}
1366
1367pub type RawWords<'a> = TableRef<'a, RawWordsMarker>;
1369
1370#[allow(clippy::needless_lifetimes)]
1371impl<'a> RawWords<'a> {
1372 pub fn data(&self) -> &'a [BigEndian<u16>] {
1373 let range = self.shape.data_byte_range();
1374 self.data.read_array(range).unwrap()
1375 }
1376}
1377
1378#[cfg(feature = "experimental_traverse")]
1379impl<'a> SomeTable<'a> for RawWords<'a> {
1380 fn type_name(&self) -> &str {
1381 "RawWords"
1382 }
1383 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1384 match idx {
1385 0usize => Some(Field::new("data", self.data())),
1386 _ => None,
1387 }
1388 }
1389}
1390
1391#[cfg(feature = "experimental_traverse")]
1392#[allow(clippy::needless_lifetimes)]
1393impl<'a> std::fmt::Debug for RawWords<'a> {
1394 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1395 (self as &dyn SomeTable<'a>).fmt(f)
1396 }
1397}