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