1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for OtKern<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.subtable_data_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl ReadArgs for OtKern<'_> {
19 type Args = ();
20}
21
22impl<'a> FontRead<'a> for OtKern<'a> {
23 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
24 #[allow(clippy::absurd_extreme_comparisons)]
25 if data.len() < Self::MIN_SIZE {
26 return Err(ReadError::OutOfBounds);
27 }
28 Ok(Self { data })
29 }
30}
31
32#[derive(Clone)]
34pub struct OtKern<'a> {
35 data: FontData<'a>,
36}
37
38#[allow(clippy::needless_lifetimes)]
39impl<'a> OtKern<'a> {
40 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
41 basic_table_impls!(impl_the_methods);
42
43 pub fn version(&self) -> u16 {
45 let range = self.version_byte_range();
46 self.data.read_at(range.start).ok().unwrap()
47 }
48
49 pub fn n_tables(&self) -> u16 {
51 let range = self.n_tables_byte_range();
52 self.data.read_at(range.start).ok().unwrap()
53 }
54
55 pub fn subtable_data(&self) -> &'a [u8] {
57 let range = self.subtable_data_byte_range();
58 self.data.read_array(range).ok().unwrap_or_default()
59 }
60
61 pub fn version_byte_range(&self) -> Range<usize> {
62 let start = 0;
63 let end = start + u16::RAW_BYTE_LEN;
64 start..end
65 }
66
67 pub fn n_tables_byte_range(&self) -> Range<usize> {
68 let start = self.version_byte_range().end;
69 let end = start + u16::RAW_BYTE_LEN;
70 start..end
71 }
72
73 pub fn subtable_data_byte_range(&self) -> Range<usize> {
74 let start = self.n_tables_byte_range().end;
75 let end =
76 start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
77 start..end
78 }
79}
80
81const _: () = assert!(FontData::default_data_long_enough(OtKern::MIN_SIZE));
82
83impl Default for OtKern<'_> {
84 fn default() -> Self {
85 Self {
86 data: FontData::default_table_data(),
87 }
88 }
89}
90
91#[cfg(feature = "experimental_traverse")]
92impl<'a> SomeTable<'a> for OtKern<'a> {
93 fn type_name(&self) -> &str {
94 "OtKern"
95 }
96 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
97 match idx {
98 0usize => Some(Field::new("version", self.version())),
99 1usize => Some(Field::new("n_tables", self.n_tables())),
100 2usize => Some(Field::new("subtable_data", self.subtable_data())),
101 _ => None,
102 }
103 }
104}
105
106#[cfg(feature = "experimental_traverse")]
107#[allow(clippy::needless_lifetimes)]
108impl<'a> std::fmt::Debug for OtKern<'a> {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 (self as &dyn SomeTable<'a>).fmt(f)
111 }
112}
113
114impl<'a> MinByteRange<'a> for AatKern<'a> {
115 fn min_byte_range(&self) -> Range<usize> {
116 0..self.subtable_data_byte_range().end
117 }
118 fn min_table_bytes(&self) -> &'a [u8] {
119 let range = self.min_byte_range();
120 self.data.as_bytes().get(range).unwrap_or_default()
121 }
122}
123
124impl ReadArgs for AatKern<'_> {
125 type Args = ();
126}
127
128impl<'a> FontRead<'a> for AatKern<'a> {
129 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
130 #[allow(clippy::absurd_extreme_comparisons)]
131 if data.len() < Self::MIN_SIZE {
132 return Err(ReadError::OutOfBounds);
133 }
134 Ok(Self { data })
135 }
136}
137
138#[derive(Clone)]
140pub struct AatKern<'a> {
141 data: FontData<'a>,
142}
143
144#[allow(clippy::needless_lifetimes)]
145impl<'a> AatKern<'a> {
146 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
147 basic_table_impls!(impl_the_methods);
148
149 pub fn version(&self) -> MajorMinor {
151 let range = self.version_byte_range();
152 self.data.read_at(range.start).ok().unwrap()
153 }
154
155 pub fn n_tables(&self) -> u32 {
157 let range = self.n_tables_byte_range();
158 self.data.read_at(range.start).ok().unwrap()
159 }
160
161 pub fn subtable_data(&self) -> &'a [u8] {
163 let range = self.subtable_data_byte_range();
164 self.data.read_array(range).ok().unwrap_or_default()
165 }
166
167 pub fn version_byte_range(&self) -> Range<usize> {
168 let start = 0;
169 let end = start + MajorMinor::RAW_BYTE_LEN;
170 start..end
171 }
172
173 pub fn n_tables_byte_range(&self) -> Range<usize> {
174 let start = self.version_byte_range().end;
175 let end = start + u32::RAW_BYTE_LEN;
176 start..end
177 }
178
179 pub fn subtable_data_byte_range(&self) -> Range<usize> {
180 let start = self.n_tables_byte_range().end;
181 let end =
182 start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
183 start..end
184 }
185}
186
187const _: () = assert!(FontData::default_data_long_enough(AatKern::MIN_SIZE));
188
189impl Default for AatKern<'_> {
190 fn default() -> Self {
191 Self {
192 data: FontData::default_table_data(),
193 }
194 }
195}
196
197#[cfg(feature = "experimental_traverse")]
198impl<'a> SomeTable<'a> for AatKern<'a> {
199 fn type_name(&self) -> &str {
200 "AatKern"
201 }
202 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
203 match idx {
204 0usize => Some(Field::new("version", self.version())),
205 1usize => Some(Field::new("n_tables", self.n_tables())),
206 2usize => Some(Field::new("subtable_data", self.subtable_data())),
207 _ => None,
208 }
209 }
210}
211
212#[cfg(feature = "experimental_traverse")]
213#[allow(clippy::needless_lifetimes)]
214impl<'a> std::fmt::Debug for AatKern<'a> {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 (self as &dyn SomeTable<'a>).fmt(f)
217 }
218}
219
220impl<'a> MinByteRange<'a> for OtSubtable<'a> {
221 fn min_byte_range(&self) -> Range<usize> {
222 0..self.data_byte_range().end
223 }
224 fn min_table_bytes(&self) -> &'a [u8] {
225 let range = self.min_byte_range();
226 self.data.as_bytes().get(range).unwrap_or_default()
227 }
228}
229
230impl ReadArgs for OtSubtable<'_> {
231 type Args = ();
232}
233
234impl<'a> FontRead<'a> for OtSubtable<'a> {
235 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
236 #[allow(clippy::absurd_extreme_comparisons)]
237 if data.len() < Self::MIN_SIZE {
238 return Err(ReadError::OutOfBounds);
239 }
240 Ok(Self { data })
241 }
242}
243
244#[derive(Clone)]
246pub struct OtSubtable<'a> {
247 data: FontData<'a>,
248}
249
250#[allow(clippy::needless_lifetimes)]
251impl<'a> OtSubtable<'a> {
252 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
253 basic_table_impls!(impl_the_methods);
254
255 pub fn version(&self) -> u16 {
257 let range = self.version_byte_range();
258 self.data.read_at(range.start).ok().unwrap()
259 }
260
261 pub fn length(&self) -> u16 {
263 let range = self.length_byte_range();
264 self.data.read_at(range.start).ok().unwrap()
265 }
266
267 pub fn coverage(&self) -> u16 {
269 let range = self.coverage_byte_range();
270 self.data.read_at(range.start).ok().unwrap()
271 }
272
273 pub fn data(&self) -> &'a [u8] {
275 let range = self.data_byte_range();
276 self.data.read_array(range).ok().unwrap_or_default()
277 }
278
279 pub fn version_byte_range(&self) -> Range<usize> {
280 let start = 0;
281 let end = start + u16::RAW_BYTE_LEN;
282 start..end
283 }
284
285 pub fn length_byte_range(&self) -> Range<usize> {
286 let start = self.version_byte_range().end;
287 let end = start + u16::RAW_BYTE_LEN;
288 start..end
289 }
290
291 pub fn coverage_byte_range(&self) -> Range<usize> {
292 let start = self.length_byte_range().end;
293 let end = start + u16::RAW_BYTE_LEN;
294 start..end
295 }
296
297 pub fn data_byte_range(&self) -> Range<usize> {
298 let start = self.coverage_byte_range().end;
299 let end =
300 start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
301 start..end
302 }
303}
304
305const _: () = assert!(FontData::default_data_long_enough(OtSubtable::MIN_SIZE));
306
307impl Default for OtSubtable<'_> {
308 fn default() -> Self {
309 Self {
310 data: FontData::default_table_data(),
311 }
312 }
313}
314
315#[cfg(feature = "experimental_traverse")]
316impl<'a> SomeTable<'a> for OtSubtable<'a> {
317 fn type_name(&self) -> &str {
318 "OtSubtable"
319 }
320 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
321 match idx {
322 0usize => Some(Field::new("version", self.version())),
323 1usize => Some(Field::new("length", self.length())),
324 2usize => Some(Field::new("coverage", self.coverage())),
325 3usize => Some(Field::new("data", self.data())),
326 _ => None,
327 }
328 }
329}
330
331#[cfg(feature = "experimental_traverse")]
332#[allow(clippy::needless_lifetimes)]
333impl<'a> std::fmt::Debug for OtSubtable<'a> {
334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
335 (self as &dyn SomeTable<'a>).fmt(f)
336 }
337}
338
339impl<'a> MinByteRange<'a> for AatSubtable<'a> {
340 fn min_byte_range(&self) -> Range<usize> {
341 0..self.data_byte_range().end
342 }
343 fn min_table_bytes(&self) -> &'a [u8] {
344 let range = self.min_byte_range();
345 self.data.as_bytes().get(range).unwrap_or_default()
346 }
347}
348
349impl ReadArgs for AatSubtable<'_> {
350 type Args = ();
351}
352
353impl<'a> FontRead<'a> for AatSubtable<'a> {
354 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
355 #[allow(clippy::absurd_extreme_comparisons)]
356 if data.len() < Self::MIN_SIZE {
357 return Err(ReadError::OutOfBounds);
358 }
359 Ok(Self { data })
360 }
361}
362
363#[derive(Clone)]
365pub struct AatSubtable<'a> {
366 data: FontData<'a>,
367}
368
369#[allow(clippy::needless_lifetimes)]
370impl<'a> AatSubtable<'a> {
371 pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
372 basic_table_impls!(impl_the_methods);
373
374 pub fn length(&self) -> u32 {
376 let range = self.length_byte_range();
377 self.data.read_at(range.start).ok().unwrap()
378 }
379
380 pub fn coverage(&self) -> u16 {
382 let range = self.coverage_byte_range();
383 self.data.read_at(range.start).ok().unwrap()
384 }
385
386 pub fn tuple_index(&self) -> u16 {
388 let range = self.tuple_index_byte_range();
389 self.data.read_at(range.start).ok().unwrap()
390 }
391
392 pub fn data(&self) -> &'a [u8] {
394 let range = self.data_byte_range();
395 self.data.read_array(range).ok().unwrap_or_default()
396 }
397
398 pub fn length_byte_range(&self) -> Range<usize> {
399 let start = 0;
400 let end = start + u32::RAW_BYTE_LEN;
401 start..end
402 }
403
404 pub fn coverage_byte_range(&self) -> Range<usize> {
405 let start = self.length_byte_range().end;
406 let end = start + u16::RAW_BYTE_LEN;
407 start..end
408 }
409
410 pub fn tuple_index_byte_range(&self) -> Range<usize> {
411 let start = self.coverage_byte_range().end;
412 let end = start + u16::RAW_BYTE_LEN;
413 start..end
414 }
415
416 pub fn data_byte_range(&self) -> Range<usize> {
417 let start = self.tuple_index_byte_range().end;
418 let end =
419 start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
420 start..end
421 }
422}
423
424const _: () = assert!(FontData::default_data_long_enough(AatSubtable::MIN_SIZE));
425
426impl Default for AatSubtable<'_> {
427 fn default() -> Self {
428 Self {
429 data: FontData::default_table_data(),
430 }
431 }
432}
433
434#[cfg(feature = "experimental_traverse")]
435impl<'a> SomeTable<'a> for AatSubtable<'a> {
436 fn type_name(&self) -> &str {
437 "AatSubtable"
438 }
439 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
440 match idx {
441 0usize => Some(Field::new("length", self.length())),
442 1usize => Some(Field::new("coverage", self.coverage())),
443 2usize => Some(Field::new("tuple_index", self.tuple_index())),
444 3usize => Some(Field::new("data", self.data())),
445 _ => None,
446 }
447 }
448}
449
450#[cfg(feature = "experimental_traverse")]
451#[allow(clippy::needless_lifetimes)]
452impl<'a> std::fmt::Debug for AatSubtable<'a> {
453 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
454 (self as &dyn SomeTable<'a>).fmt(f)
455 }
456}
457
458impl<'a> MinByteRange<'a> for Subtable0<'a> {
459 fn min_byte_range(&self) -> Range<usize> {
460 0..self.pairs_byte_range().end
461 }
462 fn min_table_bytes(&self) -> &'a [u8] {
463 let range = self.min_byte_range();
464 self.data.as_bytes().get(range).unwrap_or_default()
465 }
466}
467
468impl ReadArgs for Subtable0<'_> {
469 type Args = ();
470}
471
472impl<'a> FontRead<'a> for Subtable0<'a> {
473 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
474 #[allow(clippy::absurd_extreme_comparisons)]
475 if data.len() < Self::MIN_SIZE {
476 return Err(ReadError::OutOfBounds);
477 }
478 Ok(Self { data })
479 }
480}
481
482#[derive(Clone)]
484pub struct Subtable0<'a> {
485 data: FontData<'a>,
486}
487
488#[allow(clippy::needless_lifetimes)]
489impl<'a> Subtable0<'a> {
490 pub const MIN_SIZE: usize =
491 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
492 basic_table_impls!(impl_the_methods);
493
494 pub fn n_pairs(&self) -> u16 {
496 let range = self.n_pairs_byte_range();
497 self.data.read_at(range.start).ok().unwrap()
498 }
499
500 pub fn search_range(&self) -> u16 {
502 let range = self.search_range_byte_range();
503 self.data.read_at(range.start).ok().unwrap()
504 }
505
506 pub fn entry_selector(&self) -> u16 {
508 let range = self.entry_selector_byte_range();
509 self.data.read_at(range.start).ok().unwrap()
510 }
511
512 pub fn range_shift(&self) -> u16 {
514 let range = self.range_shift_byte_range();
515 self.data.read_at(range.start).ok().unwrap()
516 }
517
518 pub fn pairs(&self) -> &'a [Subtable0Pair] {
520 let range = self.pairs_byte_range();
521 self.data.read_array(range).ok().unwrap_or_default()
522 }
523
524 pub fn n_pairs_byte_range(&self) -> Range<usize> {
525 let start = 0;
526 let end = start + u16::RAW_BYTE_LEN;
527 start..end
528 }
529
530 pub fn search_range_byte_range(&self) -> Range<usize> {
531 let start = self.n_pairs_byte_range().end;
532 let end = start + u16::RAW_BYTE_LEN;
533 start..end
534 }
535
536 pub fn entry_selector_byte_range(&self) -> Range<usize> {
537 let start = self.search_range_byte_range().end;
538 let end = start + u16::RAW_BYTE_LEN;
539 start..end
540 }
541
542 pub fn range_shift_byte_range(&self) -> Range<usize> {
543 let start = self.entry_selector_byte_range().end;
544 let end = start + u16::RAW_BYTE_LEN;
545 start..end
546 }
547
548 pub fn pairs_byte_range(&self) -> Range<usize> {
549 let n_pairs = self.n_pairs();
550 let start = self.range_shift_byte_range().end;
551 let end =
552 start + (transforms::to_usize(n_pairs)).saturating_mul(Subtable0Pair::RAW_BYTE_LEN);
553 start..end
554 }
555}
556
557const _: () = assert!(FontData::default_data_long_enough(Subtable0::MIN_SIZE));
558
559impl Default for Subtable0<'_> {
560 fn default() -> Self {
561 Self {
562 data: FontData::default_table_data(),
563 }
564 }
565}
566
567#[cfg(feature = "experimental_traverse")]
568impl<'a> SomeTable<'a> for Subtable0<'a> {
569 fn type_name(&self) -> &str {
570 "Subtable0"
571 }
572 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
573 match idx {
574 0usize => Some(Field::new("n_pairs", self.n_pairs())),
575 1usize => Some(Field::new("search_range", self.search_range())),
576 2usize => Some(Field::new("entry_selector", self.entry_selector())),
577 3usize => Some(Field::new("range_shift", self.range_shift())),
578 4usize => Some(Field::new(
579 "pairs",
580 traversal::FieldType::array_of_records(
581 stringify!(Subtable0Pair),
582 self.pairs(),
583 self.offset_data(),
584 ),
585 )),
586 _ => None,
587 }
588 }
589}
590
591#[cfg(feature = "experimental_traverse")]
592#[allow(clippy::needless_lifetimes)]
593impl<'a> std::fmt::Debug for Subtable0<'a> {
594 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
595 (self as &dyn SomeTable<'a>).fmt(f)
596 }
597}
598
599impl<'a> MinByteRange<'a> for Subtable2ClassTable<'a> {
600 fn min_byte_range(&self) -> Range<usize> {
601 0..self.offsets_byte_range().end
602 }
603 fn min_table_bytes(&self) -> &'a [u8] {
604 let range = self.min_byte_range();
605 self.data.as_bytes().get(range).unwrap_or_default()
606 }
607}
608
609impl ReadArgs for Subtable2ClassTable<'_> {
610 type Args = ();
611}
612
613impl<'a> FontRead<'a> for Subtable2ClassTable<'a> {
614 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
615 #[allow(clippy::absurd_extreme_comparisons)]
616 if data.len() < Self::MIN_SIZE {
617 return Err(ReadError::OutOfBounds);
618 }
619 Ok(Self { data })
620 }
621}
622
623#[derive(Clone)]
625pub struct Subtable2ClassTable<'a> {
626 data: FontData<'a>,
627}
628
629#[allow(clippy::needless_lifetimes)]
630impl<'a> Subtable2ClassTable<'a> {
631 pub const MIN_SIZE: usize = (GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
632 basic_table_impls!(impl_the_methods);
633
634 pub fn first_glyph(&self) -> GlyphId16 {
636 let range = self.first_glyph_byte_range();
637 self.data.read_at(range.start).ok().unwrap()
638 }
639
640 pub fn n_glyphs(&self) -> u16 {
642 let range = self.n_glyphs_byte_range();
643 self.data.read_at(range.start).ok().unwrap()
644 }
645
646 pub fn offsets(&self) -> &'a [BigEndian<u16>] {
648 let range = self.offsets_byte_range();
649 self.data.read_array(range).ok().unwrap_or_default()
650 }
651
652 pub fn first_glyph_byte_range(&self) -> Range<usize> {
653 let start = 0;
654 let end = start + GlyphId16::RAW_BYTE_LEN;
655 start..end
656 }
657
658 pub fn n_glyphs_byte_range(&self) -> Range<usize> {
659 let start = self.first_glyph_byte_range().end;
660 let end = start + u16::RAW_BYTE_LEN;
661 start..end
662 }
663
664 pub fn offsets_byte_range(&self) -> Range<usize> {
665 let n_glyphs = self.n_glyphs();
666 let start = self.n_glyphs_byte_range().end;
667 let end = start + (transforms::to_usize(n_glyphs)).saturating_mul(u16::RAW_BYTE_LEN);
668 start..end
669 }
670}
671
672const _: () = assert!(FontData::default_data_long_enough(
673 Subtable2ClassTable::MIN_SIZE
674));
675
676impl Default for Subtable2ClassTable<'_> {
677 fn default() -> Self {
678 Self {
679 data: FontData::default_table_data(),
680 }
681 }
682}
683
684#[cfg(feature = "experimental_traverse")]
685impl<'a> SomeTable<'a> for Subtable2ClassTable<'a> {
686 fn type_name(&self) -> &str {
687 "Subtable2ClassTable"
688 }
689 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
690 match idx {
691 0usize => Some(Field::new("first_glyph", self.first_glyph())),
692 1usize => Some(Field::new("n_glyphs", self.n_glyphs())),
693 2usize => Some(Field::new("offsets", self.offsets())),
694 _ => None,
695 }
696 }
697}
698
699#[cfg(feature = "experimental_traverse")]
700#[allow(clippy::needless_lifetimes)]
701impl<'a> std::fmt::Debug for Subtable2ClassTable<'a> {
702 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
703 (self as &dyn SomeTable<'a>).fmt(f)
704 }
705}
706
707impl<'a> MinByteRange<'a> for Subtable3<'a> {
708 fn min_byte_range(&self) -> Range<usize> {
709 0..self.kern_index_byte_range().end
710 }
711 fn min_table_bytes(&self) -> &'a [u8] {
712 let range = self.min_byte_range();
713 self.data.as_bytes().get(range).unwrap_or_default()
714 }
715}
716
717impl ReadArgs for Subtable3<'_> {
718 type Args = ();
719}
720
721impl<'a> FontRead<'a> for Subtable3<'a> {
722 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
723 #[allow(clippy::absurd_extreme_comparisons)]
724 if data.len() < Self::MIN_SIZE {
725 return Err(ReadError::OutOfBounds);
726 }
727 Ok(Self { data })
728 }
729}
730
731#[derive(Clone)]
733pub struct Subtable3<'a> {
734 data: FontData<'a>,
735}
736
737#[allow(clippy::needless_lifetimes)]
738impl<'a> Subtable3<'a> {
739 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
740 + u8::RAW_BYTE_LEN
741 + u8::RAW_BYTE_LEN
742 + u8::RAW_BYTE_LEN
743 + u8::RAW_BYTE_LEN);
744 basic_table_impls!(impl_the_methods);
745
746 pub fn glyph_count(&self) -> u16 {
748 let range = self.glyph_count_byte_range();
749 self.data.read_at(range.start).ok().unwrap()
750 }
751
752 pub fn kern_value_count(&self) -> u8 {
754 let range = self.kern_value_count_byte_range();
755 self.data.read_at(range.start).ok().unwrap()
756 }
757
758 pub fn left_class_count(&self) -> u8 {
760 let range = self.left_class_count_byte_range();
761 self.data.read_at(range.start).ok().unwrap()
762 }
763
764 pub fn right_class_count(&self) -> u8 {
766 let range = self.right_class_count_byte_range();
767 self.data.read_at(range.start).ok().unwrap()
768 }
769
770 pub fn flags(&self) -> u8 {
772 let range = self.flags_byte_range();
773 self.data.read_at(range.start).ok().unwrap()
774 }
775
776 pub fn kern_value(&self) -> &'a [BigEndian<i16>] {
778 let range = self.kern_value_byte_range();
779 self.data.read_array(range).ok().unwrap_or_default()
780 }
781
782 pub fn left_class(&self) -> &'a [u8] {
784 let range = self.left_class_byte_range();
785 self.data.read_array(range).ok().unwrap_or_default()
786 }
787
788 pub fn right_class(&self) -> &'a [u8] {
790 let range = self.right_class_byte_range();
791 self.data.read_array(range).ok().unwrap_or_default()
792 }
793
794 pub fn kern_index(&self) -> &'a [u8] {
796 let range = self.kern_index_byte_range();
797 self.data.read_array(range).ok().unwrap_or_default()
798 }
799
800 pub fn glyph_count_byte_range(&self) -> Range<usize> {
801 let start = 0;
802 let end = start + u16::RAW_BYTE_LEN;
803 start..end
804 }
805
806 pub fn kern_value_count_byte_range(&self) -> Range<usize> {
807 let start = self.glyph_count_byte_range().end;
808 let end = start + u8::RAW_BYTE_LEN;
809 start..end
810 }
811
812 pub fn left_class_count_byte_range(&self) -> Range<usize> {
813 let start = self.kern_value_count_byte_range().end;
814 let end = start + u8::RAW_BYTE_LEN;
815 start..end
816 }
817
818 pub fn right_class_count_byte_range(&self) -> Range<usize> {
819 let start = self.left_class_count_byte_range().end;
820 let end = start + u8::RAW_BYTE_LEN;
821 start..end
822 }
823
824 pub fn flags_byte_range(&self) -> Range<usize> {
825 let start = self.right_class_count_byte_range().end;
826 let end = start + u8::RAW_BYTE_LEN;
827 start..end
828 }
829
830 pub fn kern_value_byte_range(&self) -> Range<usize> {
831 let kern_value_count = self.kern_value_count();
832 let start = self.flags_byte_range().end;
833 let end =
834 start + (transforms::to_usize(kern_value_count)).saturating_mul(i16::RAW_BYTE_LEN);
835 start..end
836 }
837
838 pub fn left_class_byte_range(&self) -> Range<usize> {
839 let glyph_count = self.glyph_count();
840 let start = self.kern_value_byte_range().end;
841 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u8::RAW_BYTE_LEN);
842 start..end
843 }
844
845 pub fn right_class_byte_range(&self) -> Range<usize> {
846 let glyph_count = self.glyph_count();
847 let start = self.left_class_byte_range().end;
848 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u8::RAW_BYTE_LEN);
849 start..end
850 }
851
852 pub fn kern_index_byte_range(&self) -> Range<usize> {
853 let left_class_count = self.left_class_count();
854 let right_class_count = self.right_class_count();
855 let start = self.right_class_byte_range().end;
856 let end = start
857 + (transforms::add_multiply(left_class_count, 0_usize, right_class_count))
858 .saturating_mul(u8::RAW_BYTE_LEN);
859 start..end
860 }
861}
862
863const _: () = assert!(FontData::default_data_long_enough(Subtable3::MIN_SIZE));
864
865impl Default for Subtable3<'_> {
866 fn default() -> Self {
867 Self {
868 data: FontData::default_table_data(),
869 }
870 }
871}
872
873#[cfg(feature = "experimental_traverse")]
874impl<'a> SomeTable<'a> for Subtable3<'a> {
875 fn type_name(&self) -> &str {
876 "Subtable3"
877 }
878 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
879 match idx {
880 0usize => Some(Field::new("glyph_count", self.glyph_count())),
881 1usize => Some(Field::new("kern_value_count", self.kern_value_count())),
882 2usize => Some(Field::new("left_class_count", self.left_class_count())),
883 3usize => Some(Field::new("right_class_count", self.right_class_count())),
884 4usize => Some(Field::new("flags", self.flags())),
885 5usize => Some(Field::new("kern_value", self.kern_value())),
886 6usize => Some(Field::new("left_class", self.left_class())),
887 7usize => Some(Field::new("right_class", self.right_class())),
888 8usize => Some(Field::new("kern_index", self.kern_index())),
889 _ => None,
890 }
891 }
892}
893
894#[cfg(feature = "experimental_traverse")]
895#[allow(clippy::needless_lifetimes)]
896impl<'a> std::fmt::Debug for Subtable3<'a> {
897 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
898 (self as &dyn SomeTable<'a>).fmt(f)
899 }
900}