Skip to main content

read_fonts/generated/
generated_kern.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[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<'a> FontRead<'a> for OtKern<'a> {
19    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
20        #[allow(clippy::absurd_extreme_comparisons)]
21        if data.len() < Self::MIN_SIZE {
22            return Err(ReadError::OutOfBounds);
23        }
24        Ok(Self { data })
25    }
26}
27
28/// The OpenType [kerning](https://learn.microsoft.com/en-us/typography/opentype/spec/kern) table.
29#[derive(Clone)]
30pub struct OtKern<'a> {
31    data: FontData<'a>,
32}
33
34#[allow(clippy::needless_lifetimes)]
35impl<'a> OtKern<'a> {
36    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
37    basic_table_impls!(impl_the_methods);
38
39    /// Table version number—set to 0.
40    pub fn version(&self) -> u16 {
41        let range = self.version_byte_range();
42        self.data.read_at(range.start).ok().unwrap()
43    }
44
45    /// Number of subtables in the kerning table.
46    pub fn n_tables(&self) -> u16 {
47        let range = self.n_tables_byte_range();
48        self.data.read_at(range.start).ok().unwrap()
49    }
50
51    /// Data for subtables, immediately following the header.
52    pub fn subtable_data(&self) -> &'a [u8] {
53        let range = self.subtable_data_byte_range();
54        self.data.read_array(range).ok().unwrap_or_default()
55    }
56
57    pub fn version_byte_range(&self) -> Range<usize> {
58        let start = 0;
59        start..start + u16::RAW_BYTE_LEN
60    }
61
62    pub fn n_tables_byte_range(&self) -> Range<usize> {
63        let start = self.version_byte_range().end;
64        start..start + u16::RAW_BYTE_LEN
65    }
66
67    pub fn subtable_data_byte_range(&self) -> Range<usize> {
68        let start = self.n_tables_byte_range().end;
69        start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
70    }
71}
72
73#[cfg(feature = "experimental_traverse")]
74impl<'a> SomeTable<'a> for OtKern<'a> {
75    fn type_name(&self) -> &str {
76        "OtKern"
77    }
78    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
79        match idx {
80            0usize => Some(Field::new("version", self.version())),
81            1usize => Some(Field::new("n_tables", self.n_tables())),
82            2usize => Some(Field::new("subtable_data", self.subtable_data())),
83            _ => None,
84        }
85    }
86}
87
88#[cfg(feature = "experimental_traverse")]
89#[allow(clippy::needless_lifetimes)]
90impl<'a> std::fmt::Debug for OtKern<'a> {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        (self as &dyn SomeTable<'a>).fmt(f)
93    }
94}
95
96impl<'a> MinByteRange<'a> for AatKern<'a> {
97    fn min_byte_range(&self) -> Range<usize> {
98        0..self.subtable_data_byte_range().end
99    }
100    fn min_table_bytes(&self) -> &'a [u8] {
101        let range = self.min_byte_range();
102        self.data.as_bytes().get(range).unwrap_or_default()
103    }
104}
105
106impl<'a> FontRead<'a> for AatKern<'a> {
107    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
108        #[allow(clippy::absurd_extreme_comparisons)]
109        if data.len() < Self::MIN_SIZE {
110            return Err(ReadError::OutOfBounds);
111        }
112        Ok(Self { data })
113    }
114}
115
116/// The Apple Advanced Typography [kerning](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html) table.
117#[derive(Clone)]
118pub struct AatKern<'a> {
119    data: FontData<'a>,
120}
121
122#[allow(clippy::needless_lifetimes)]
123impl<'a> AatKern<'a> {
124    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
125    basic_table_impls!(impl_the_methods);
126
127    /// The version number of the kerning table (0x00010000 for the current version).
128    pub fn version(&self) -> MajorMinor {
129        let range = self.version_byte_range();
130        self.data.read_at(range.start).ok().unwrap()
131    }
132
133    /// The number of subtables included in the kerning table.
134    pub fn n_tables(&self) -> u32 {
135        let range = self.n_tables_byte_range();
136        self.data.read_at(range.start).ok().unwrap()
137    }
138
139    /// Data for subtables, immediately following the header.    
140    pub fn subtable_data(&self) -> &'a [u8] {
141        let range = self.subtable_data_byte_range();
142        self.data.read_array(range).ok().unwrap_or_default()
143    }
144
145    pub fn version_byte_range(&self) -> Range<usize> {
146        let start = 0;
147        start..start + MajorMinor::RAW_BYTE_LEN
148    }
149
150    pub fn n_tables_byte_range(&self) -> Range<usize> {
151        let start = self.version_byte_range().end;
152        start..start + u32::RAW_BYTE_LEN
153    }
154
155    pub fn subtable_data_byte_range(&self) -> Range<usize> {
156        let start = self.n_tables_byte_range().end;
157        start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
158    }
159}
160
161#[cfg(feature = "experimental_traverse")]
162impl<'a> SomeTable<'a> for AatKern<'a> {
163    fn type_name(&self) -> &str {
164        "AatKern"
165    }
166    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
167        match idx {
168            0usize => Some(Field::new("version", self.version())),
169            1usize => Some(Field::new("n_tables", self.n_tables())),
170            2usize => Some(Field::new("subtable_data", self.subtable_data())),
171            _ => None,
172        }
173    }
174}
175
176#[cfg(feature = "experimental_traverse")]
177#[allow(clippy::needless_lifetimes)]
178impl<'a> std::fmt::Debug for AatKern<'a> {
179    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180        (self as &dyn SomeTable<'a>).fmt(f)
181    }
182}
183
184impl<'a> MinByteRange<'a> for OtSubtable<'a> {
185    fn min_byte_range(&self) -> Range<usize> {
186        0..self.data_byte_range().end
187    }
188    fn min_table_bytes(&self) -> &'a [u8] {
189        let range = self.min_byte_range();
190        self.data.as_bytes().get(range).unwrap_or_default()
191    }
192}
193
194impl<'a> FontRead<'a> for OtSubtable<'a> {
195    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
196        #[allow(clippy::absurd_extreme_comparisons)]
197        if data.len() < Self::MIN_SIZE {
198            return Err(ReadError::OutOfBounds);
199        }
200        Ok(Self { data })
201    }
202}
203
204/// A subtable in an OT `kern` table.
205#[derive(Clone)]
206pub struct OtSubtable<'a> {
207    data: FontData<'a>,
208}
209
210#[allow(clippy::needless_lifetimes)]
211impl<'a> OtSubtable<'a> {
212    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
213    basic_table_impls!(impl_the_methods);
214
215    /// Kern subtable version number-- set to 0.
216    pub fn version(&self) -> u16 {
217        let range = self.version_byte_range();
218        self.data.read_at(range.start).ok().unwrap()
219    }
220
221    /// The length of this subtable in bytes, including this header.
222    pub fn length(&self) -> u16 {
223        let range = self.length_byte_range();
224        self.data.read_at(range.start).ok().unwrap()
225    }
226
227    /// Circumstances under which this table is used.
228    pub fn coverage(&self) -> u16 {
229        let range = self.coverage_byte_range();
230        self.data.read_at(range.start).ok().unwrap()
231    }
232
233    /// Subtable specific data.
234    pub fn data(&self) -> &'a [u8] {
235        let range = self.data_byte_range();
236        self.data.read_array(range).ok().unwrap_or_default()
237    }
238
239    pub fn version_byte_range(&self) -> Range<usize> {
240        let start = 0;
241        start..start + u16::RAW_BYTE_LEN
242    }
243
244    pub fn length_byte_range(&self) -> Range<usize> {
245        let start = self.version_byte_range().end;
246        start..start + u16::RAW_BYTE_LEN
247    }
248
249    pub fn coverage_byte_range(&self) -> Range<usize> {
250        let start = self.length_byte_range().end;
251        start..start + u16::RAW_BYTE_LEN
252    }
253
254    pub fn data_byte_range(&self) -> Range<usize> {
255        let start = self.coverage_byte_range().end;
256        start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
257    }
258}
259
260#[cfg(feature = "experimental_traverse")]
261impl<'a> SomeTable<'a> for OtSubtable<'a> {
262    fn type_name(&self) -> &str {
263        "OtSubtable"
264    }
265    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
266        match idx {
267            0usize => Some(Field::new("version", self.version())),
268            1usize => Some(Field::new("length", self.length())),
269            2usize => Some(Field::new("coverage", self.coverage())),
270            3usize => Some(Field::new("data", self.data())),
271            _ => None,
272        }
273    }
274}
275
276#[cfg(feature = "experimental_traverse")]
277#[allow(clippy::needless_lifetimes)]
278impl<'a> std::fmt::Debug for OtSubtable<'a> {
279    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
280        (self as &dyn SomeTable<'a>).fmt(f)
281    }
282}
283
284impl<'a> MinByteRange<'a> for AatSubtable<'a> {
285    fn min_byte_range(&self) -> Range<usize> {
286        0..self.data_byte_range().end
287    }
288    fn min_table_bytes(&self) -> &'a [u8] {
289        let range = self.min_byte_range();
290        self.data.as_bytes().get(range).unwrap_or_default()
291    }
292}
293
294impl<'a> FontRead<'a> for AatSubtable<'a> {
295    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
296        #[allow(clippy::absurd_extreme_comparisons)]
297        if data.len() < Self::MIN_SIZE {
298            return Err(ReadError::OutOfBounds);
299        }
300        Ok(Self { data })
301    }
302}
303
304/// A subtable in an AAT `kern` table.
305#[derive(Clone)]
306pub struct AatSubtable<'a> {
307    data: FontData<'a>,
308}
309
310#[allow(clippy::needless_lifetimes)]
311impl<'a> AatSubtable<'a> {
312    pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
313    basic_table_impls!(impl_the_methods);
314
315    /// The length of this subtable in bytes, including this header.
316    pub fn length(&self) -> u32 {
317        let range = self.length_byte_range();
318        self.data.read_at(range.start).ok().unwrap()
319    }
320
321    /// Circumstances under which this table is used.
322    pub fn coverage(&self) -> u16 {
323        let range = self.coverage_byte_range();
324        self.data.read_at(range.start).ok().unwrap()
325    }
326
327    /// The tuple index (used for variations fonts). This value specifies which tuple this subtable covers.
328    pub fn tuple_index(&self) -> u16 {
329        let range = self.tuple_index_byte_range();
330        self.data.read_at(range.start).ok().unwrap()
331    }
332
333    /// Subtable specific data.
334    pub fn data(&self) -> &'a [u8] {
335        let range = self.data_byte_range();
336        self.data.read_array(range).ok().unwrap_or_default()
337    }
338
339    pub fn length_byte_range(&self) -> Range<usize> {
340        let start = 0;
341        start..start + u32::RAW_BYTE_LEN
342    }
343
344    pub fn coverage_byte_range(&self) -> Range<usize> {
345        let start = self.length_byte_range().end;
346        start..start + u16::RAW_BYTE_LEN
347    }
348
349    pub fn tuple_index_byte_range(&self) -> Range<usize> {
350        let start = self.coverage_byte_range().end;
351        start..start + u16::RAW_BYTE_LEN
352    }
353
354    pub fn data_byte_range(&self) -> Range<usize> {
355        let start = self.tuple_index_byte_range().end;
356        start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
357    }
358}
359
360#[cfg(feature = "experimental_traverse")]
361impl<'a> SomeTable<'a> for AatSubtable<'a> {
362    fn type_name(&self) -> &str {
363        "AatSubtable"
364    }
365    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
366        match idx {
367            0usize => Some(Field::new("length", self.length())),
368            1usize => Some(Field::new("coverage", self.coverage())),
369            2usize => Some(Field::new("tuple_index", self.tuple_index())),
370            3usize => Some(Field::new("data", self.data())),
371            _ => None,
372        }
373    }
374}
375
376#[cfg(feature = "experimental_traverse")]
377#[allow(clippy::needless_lifetimes)]
378impl<'a> std::fmt::Debug for AatSubtable<'a> {
379    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
380        (self as &dyn SomeTable<'a>).fmt(f)
381    }
382}
383
384impl<'a> MinByteRange<'a> for Subtable0<'a> {
385    fn min_byte_range(&self) -> Range<usize> {
386        0..self.pairs_byte_range().end
387    }
388    fn min_table_bytes(&self) -> &'a [u8] {
389        let range = self.min_byte_range();
390        self.data.as_bytes().get(range).unwrap_or_default()
391    }
392}
393
394impl<'a> FontRead<'a> for Subtable0<'a> {
395    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
396        #[allow(clippy::absurd_extreme_comparisons)]
397        if data.len() < Self::MIN_SIZE {
398            return Err(ReadError::OutOfBounds);
399        }
400        Ok(Self { data })
401    }
402}
403
404/// The type 0 `kern` subtable.
405#[derive(Clone)]
406pub struct Subtable0<'a> {
407    data: FontData<'a>,
408}
409
410#[allow(clippy::needless_lifetimes)]
411impl<'a> Subtable0<'a> {
412    pub const MIN_SIZE: usize =
413        (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
414    basic_table_impls!(impl_the_methods);
415
416    /// The number of kerning pairs in this subtable.
417    pub fn n_pairs(&self) -> u16 {
418        let range = self.n_pairs_byte_range();
419        self.data.read_at(range.start).ok().unwrap()
420    }
421
422    /// The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the subtable.
423    pub fn search_range(&self) -> u16 {
424        let range = self.search_range_byte_range();
425        self.data.read_at(range.start).ok().unwrap()
426    }
427
428    /// This is calculated as log2 of the largest power of two less than or equal to the value of nPairs. This value indicates how many iterations of the search loop have to be made. For example, in a list of eight items, there would be three iterations of the loop.
429    pub fn entry_selector(&self) -> u16 {
430        let range = self.entry_selector_byte_range();
431        self.data.read_at(range.start).ok().unwrap()
432    }
433
434    /// The value of nPairs minus the largest power of two less than or equal to nPairs. This is multiplied by the size in bytes of an entry in the table.
435    pub fn range_shift(&self) -> u16 {
436        let range = self.range_shift_byte_range();
437        self.data.read_at(range.start).ok().unwrap()
438    }
439
440    /// Kerning records.
441    pub fn pairs(&self) -> &'a [Subtable0Pair] {
442        let range = self.pairs_byte_range();
443        self.data.read_array(range).ok().unwrap_or_default()
444    }
445
446    pub fn n_pairs_byte_range(&self) -> Range<usize> {
447        let start = 0;
448        start..start + u16::RAW_BYTE_LEN
449    }
450
451    pub fn search_range_byte_range(&self) -> Range<usize> {
452        let start = self.n_pairs_byte_range().end;
453        start..start + u16::RAW_BYTE_LEN
454    }
455
456    pub fn entry_selector_byte_range(&self) -> Range<usize> {
457        let start = self.search_range_byte_range().end;
458        start..start + u16::RAW_BYTE_LEN
459    }
460
461    pub fn range_shift_byte_range(&self) -> Range<usize> {
462        let start = self.entry_selector_byte_range().end;
463        start..start + u16::RAW_BYTE_LEN
464    }
465
466    pub fn pairs_byte_range(&self) -> Range<usize> {
467        let n_pairs = self.n_pairs();
468        let start = self.range_shift_byte_range().end;
469        start..start + (n_pairs as usize).saturating_mul(Subtable0Pair::RAW_BYTE_LEN)
470    }
471}
472
473#[cfg(feature = "experimental_traverse")]
474impl<'a> SomeTable<'a> for Subtable0<'a> {
475    fn type_name(&self) -> &str {
476        "Subtable0"
477    }
478    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
479        match idx {
480            0usize => Some(Field::new("n_pairs", self.n_pairs())),
481            1usize => Some(Field::new("search_range", self.search_range())),
482            2usize => Some(Field::new("entry_selector", self.entry_selector())),
483            3usize => Some(Field::new("range_shift", self.range_shift())),
484            4usize => Some(Field::new(
485                "pairs",
486                traversal::FieldType::array_of_records(
487                    stringify!(Subtable0Pair),
488                    self.pairs(),
489                    self.offset_data(),
490                ),
491            )),
492            _ => None,
493        }
494    }
495}
496
497#[cfg(feature = "experimental_traverse")]
498#[allow(clippy::needless_lifetimes)]
499impl<'a> std::fmt::Debug for Subtable0<'a> {
500    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
501        (self as &dyn SomeTable<'a>).fmt(f)
502    }
503}
504
505impl<'a> MinByteRange<'a> for Subtable2ClassTable<'a> {
506    fn min_byte_range(&self) -> Range<usize> {
507        0..self.offsets_byte_range().end
508    }
509    fn min_table_bytes(&self) -> &'a [u8] {
510        let range = self.min_byte_range();
511        self.data.as_bytes().get(range).unwrap_or_default()
512    }
513}
514
515impl<'a> FontRead<'a> for Subtable2ClassTable<'a> {
516    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
517        #[allow(clippy::absurd_extreme_comparisons)]
518        if data.len() < Self::MIN_SIZE {
519            return Err(ReadError::OutOfBounds);
520        }
521        Ok(Self { data })
522    }
523}
524
525/// Class table for the type 2 `kern` subtable.
526#[derive(Clone)]
527pub struct Subtable2ClassTable<'a> {
528    data: FontData<'a>,
529}
530
531#[allow(clippy::needless_lifetimes)]
532impl<'a> Subtable2ClassTable<'a> {
533    pub const MIN_SIZE: usize = (GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
534    basic_table_impls!(impl_the_methods);
535
536    /// First glyph in class range.
537    pub fn first_glyph(&self) -> GlyphId16 {
538        let range = self.first_glyph_byte_range();
539        self.data.read_at(range.start).ok().unwrap()
540    }
541
542    /// Number of glyph in class range.
543    pub fn n_glyphs(&self) -> u16 {
544        let range = self.n_glyphs_byte_range();
545        self.data.read_at(range.start).ok().unwrap()
546    }
547
548    /// The offsets array for all of the glyphs in the range.
549    pub fn offsets(&self) -> &'a [BigEndian<u16>] {
550        let range = self.offsets_byte_range();
551        self.data.read_array(range).ok().unwrap_or_default()
552    }
553
554    pub fn first_glyph_byte_range(&self) -> Range<usize> {
555        let start = 0;
556        start..start + GlyphId16::RAW_BYTE_LEN
557    }
558
559    pub fn n_glyphs_byte_range(&self) -> Range<usize> {
560        let start = self.first_glyph_byte_range().end;
561        start..start + u16::RAW_BYTE_LEN
562    }
563
564    pub fn offsets_byte_range(&self) -> Range<usize> {
565        let n_glyphs = self.n_glyphs();
566        let start = self.n_glyphs_byte_range().end;
567        start..start + (n_glyphs as usize).saturating_mul(u16::RAW_BYTE_LEN)
568    }
569}
570
571#[cfg(feature = "experimental_traverse")]
572impl<'a> SomeTable<'a> for Subtable2ClassTable<'a> {
573    fn type_name(&self) -> &str {
574        "Subtable2ClassTable"
575    }
576    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
577        match idx {
578            0usize => Some(Field::new("first_glyph", self.first_glyph())),
579            1usize => Some(Field::new("n_glyphs", self.n_glyphs())),
580            2usize => Some(Field::new("offsets", self.offsets())),
581            _ => None,
582        }
583    }
584}
585
586#[cfg(feature = "experimental_traverse")]
587#[allow(clippy::needless_lifetimes)]
588impl<'a> std::fmt::Debug for Subtable2ClassTable<'a> {
589    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
590        (self as &dyn SomeTable<'a>).fmt(f)
591    }
592}
593
594impl<'a> MinByteRange<'a> for Subtable3<'a> {
595    fn min_byte_range(&self) -> Range<usize> {
596        0..self.kern_index_byte_range().end
597    }
598    fn min_table_bytes(&self) -> &'a [u8] {
599        let range = self.min_byte_range();
600        self.data.as_bytes().get(range).unwrap_or_default()
601    }
602}
603
604impl<'a> FontRead<'a> for Subtable3<'a> {
605    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
606        #[allow(clippy::absurd_extreme_comparisons)]
607        if data.len() < Self::MIN_SIZE {
608            return Err(ReadError::OutOfBounds);
609        }
610        Ok(Self { data })
611    }
612}
613
614/// The type 3 'kern' subtable.
615#[derive(Clone)]
616pub struct Subtable3<'a> {
617    data: FontData<'a>,
618}
619
620#[allow(clippy::needless_lifetimes)]
621impl<'a> Subtable3<'a> {
622    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
623        + u8::RAW_BYTE_LEN
624        + u8::RAW_BYTE_LEN
625        + u8::RAW_BYTE_LEN
626        + u8::RAW_BYTE_LEN);
627    basic_table_impls!(impl_the_methods);
628
629    /// The number of glyphs in this font.
630    pub fn glyph_count(&self) -> u16 {
631        let range = self.glyph_count_byte_range();
632        self.data.read_at(range.start).ok().unwrap()
633    }
634
635    /// The number of kerning values.
636    pub fn kern_value_count(&self) -> u8 {
637        let range = self.kern_value_count_byte_range();
638        self.data.read_at(range.start).ok().unwrap()
639    }
640
641    /// The number of left-hand classes.
642    pub fn left_class_count(&self) -> u8 {
643        let range = self.left_class_count_byte_range();
644        self.data.read_at(range.start).ok().unwrap()
645    }
646
647    /// The number of right-hand classes.
648    pub fn right_class_count(&self) -> u8 {
649        let range = self.right_class_count_byte_range();
650        self.data.read_at(range.start).ok().unwrap()
651    }
652
653    /// Set to zero (reserved for future use).
654    pub fn flags(&self) -> u8 {
655        let range = self.flags_byte_range();
656        self.data.read_at(range.start).ok().unwrap()
657    }
658
659    /// The kerning values.
660    pub fn kern_value(&self) -> &'a [BigEndian<i16>] {
661        let range = self.kern_value_byte_range();
662        self.data.read_array(range).ok().unwrap_or_default()
663    }
664
665    /// The left-hand classes.
666    pub fn left_class(&self) -> &'a [u8] {
667        let range = self.left_class_byte_range();
668        self.data.read_array(range).ok().unwrap_or_default()
669    }
670
671    /// The right-hand classes.
672    pub fn right_class(&self) -> &'a [u8] {
673        let range = self.right_class_byte_range();
674        self.data.read_array(range).ok().unwrap_or_default()
675    }
676
677    /// The indices into the kernValue array.
678    pub fn kern_index(&self) -> &'a [u8] {
679        let range = self.kern_index_byte_range();
680        self.data.read_array(range).ok().unwrap_or_default()
681    }
682
683    pub fn glyph_count_byte_range(&self) -> Range<usize> {
684        let start = 0;
685        start..start + u16::RAW_BYTE_LEN
686    }
687
688    pub fn kern_value_count_byte_range(&self) -> Range<usize> {
689        let start = self.glyph_count_byte_range().end;
690        start..start + u8::RAW_BYTE_LEN
691    }
692
693    pub fn left_class_count_byte_range(&self) -> Range<usize> {
694        let start = self.kern_value_count_byte_range().end;
695        start..start + u8::RAW_BYTE_LEN
696    }
697
698    pub fn right_class_count_byte_range(&self) -> Range<usize> {
699        let start = self.left_class_count_byte_range().end;
700        start..start + u8::RAW_BYTE_LEN
701    }
702
703    pub fn flags_byte_range(&self) -> Range<usize> {
704        let start = self.right_class_count_byte_range().end;
705        start..start + u8::RAW_BYTE_LEN
706    }
707
708    pub fn kern_value_byte_range(&self) -> Range<usize> {
709        let kern_value_count = self.kern_value_count();
710        let start = self.flags_byte_range().end;
711        start..start + (kern_value_count as usize).saturating_mul(i16::RAW_BYTE_LEN)
712    }
713
714    pub fn left_class_byte_range(&self) -> Range<usize> {
715        let glyph_count = self.glyph_count();
716        let start = self.kern_value_byte_range().end;
717        start..start + (glyph_count as usize).saturating_mul(u8::RAW_BYTE_LEN)
718    }
719
720    pub fn right_class_byte_range(&self) -> Range<usize> {
721        let glyph_count = self.glyph_count();
722        let start = self.left_class_byte_range().end;
723        start..start + (glyph_count as usize).saturating_mul(u8::RAW_BYTE_LEN)
724    }
725
726    pub fn kern_index_byte_range(&self) -> Range<usize> {
727        let left_class_count = self.left_class_count();
728        let right_class_count = self.right_class_count();
729        let start = self.right_class_byte_range().end;
730        start
731            ..start
732                + (transforms::add_multiply(left_class_count, 0_usize, right_class_count))
733                    .saturating_mul(u8::RAW_BYTE_LEN)
734    }
735}
736
737#[cfg(feature = "experimental_traverse")]
738impl<'a> SomeTable<'a> for Subtable3<'a> {
739    fn type_name(&self) -> &str {
740        "Subtable3"
741    }
742    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
743        match idx {
744            0usize => Some(Field::new("glyph_count", self.glyph_count())),
745            1usize => Some(Field::new("kern_value_count", self.kern_value_count())),
746            2usize => Some(Field::new("left_class_count", self.left_class_count())),
747            3usize => Some(Field::new("right_class_count", self.right_class_count())),
748            4usize => Some(Field::new("flags", self.flags())),
749            5usize => Some(Field::new("kern_value", self.kern_value())),
750            6usize => Some(Field::new("left_class", self.left_class())),
751            7usize => Some(Field::new("right_class", self.right_class())),
752            8usize => Some(Field::new("kern_index", self.kern_index())),
753            _ => None,
754        }
755    }
756}
757
758#[cfg(feature = "experimental_traverse")]
759#[allow(clippy::needless_lifetimes)]
760impl<'a> std::fmt::Debug for Subtable3<'a> {
761    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
762        (self as &dyn SomeTable<'a>).fmt(f)
763    }
764}