read_fonts/generated/
generated_kerx.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
8/// The [kerx (Extended Kerning)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table.
9#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct KerxMarker {
12    subtables_byte_len: usize,
13}
14
15impl KerxMarker {
16    pub fn version_byte_range(&self) -> Range<usize> {
17        let start = 0;
18        start..start + u16::RAW_BYTE_LEN
19    }
20
21    pub fn padding_byte_range(&self) -> Range<usize> {
22        let start = self.version_byte_range().end;
23        start..start + u16::RAW_BYTE_LEN
24    }
25
26    pub fn n_tables_byte_range(&self) -> Range<usize> {
27        let start = self.padding_byte_range().end;
28        start..start + u32::RAW_BYTE_LEN
29    }
30
31    pub fn subtables_byte_range(&self) -> Range<usize> {
32        let start = self.n_tables_byte_range().end;
33        start..start + self.subtables_byte_len
34    }
35}
36
37impl MinByteRange for KerxMarker {
38    fn min_byte_range(&self) -> Range<usize> {
39        0..self.subtables_byte_range().end
40    }
41}
42
43impl TopLevelTable for Kerx<'_> {
44    /// `kerx`
45    const TAG: Tag = Tag::new(b"kerx");
46}
47
48impl<'a> FontRead<'a> for Kerx<'a> {
49    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
50        let mut cursor = data.cursor();
51        cursor.advance::<u16>();
52        cursor.advance::<u16>();
53        let n_tables: u32 = cursor.read()?;
54        let subtables_byte_len = {
55            let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?;
56            <Subtable as VarSize>::total_len_for_count(data, n_tables as usize)?
57        };
58        cursor.advance_by(subtables_byte_len);
59        cursor.finish(KerxMarker { subtables_byte_len })
60    }
61}
62
63/// The [kerx (Extended Kerning)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table.
64pub type Kerx<'a> = TableRef<'a, KerxMarker>;
65
66#[allow(clippy::needless_lifetimes)]
67impl<'a> Kerx<'a> {
68    /// The version number of the extended kerning table (currently 2, 3, or 4)
69    pub fn version(&self) -> u16 {
70        let range = self.shape.version_byte_range();
71        self.data.read_at(range.start).unwrap()
72    }
73
74    /// The number of subtables included in the extended kerning table.
75    pub fn n_tables(&self) -> u32 {
76        let range = self.shape.n_tables_byte_range();
77        self.data.read_at(range.start).unwrap()
78    }
79
80    pub fn subtables(&self) -> VarLenArray<'a, Subtable<'a>> {
81        let range = self.shape.subtables_byte_range();
82        VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
83    }
84}
85
86#[cfg(feature = "experimental_traverse")]
87impl<'a> SomeTable<'a> for Kerx<'a> {
88    fn type_name(&self) -> &str {
89        "Kerx"
90    }
91    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
92        match idx {
93            0usize => Some(Field::new("version", self.version())),
94            1usize => Some(Field::new("n_tables", self.n_tables())),
95            2usize => Some(Field::new(
96                "subtables",
97                traversal::FieldType::var_array("Subtable", self.subtables(), self.offset_data()),
98            )),
99            _ => None,
100        }
101    }
102}
103
104#[cfg(feature = "experimental_traverse")]
105#[allow(clippy::needless_lifetimes)]
106impl<'a> std::fmt::Debug for Kerx<'a> {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        (self as &dyn SomeTable<'a>).fmt(f)
109    }
110}
111
112/// A subtable in a `kerx` table.
113#[derive(Debug, Clone, Copy)]
114#[doc(hidden)]
115pub struct SubtableMarker {
116    data_byte_len: usize,
117}
118
119impl SubtableMarker {
120    pub fn length_byte_range(&self) -> Range<usize> {
121        let start = 0;
122        start..start + u32::RAW_BYTE_LEN
123    }
124
125    pub fn coverage_byte_range(&self) -> Range<usize> {
126        let start = self.length_byte_range().end;
127        start..start + u32::RAW_BYTE_LEN
128    }
129
130    pub fn tuple_count_byte_range(&self) -> Range<usize> {
131        let start = self.coverage_byte_range().end;
132        start..start + u32::RAW_BYTE_LEN
133    }
134
135    pub fn data_byte_range(&self) -> Range<usize> {
136        let start = self.tuple_count_byte_range().end;
137        start..start + self.data_byte_len
138    }
139}
140
141impl MinByteRange for SubtableMarker {
142    fn min_byte_range(&self) -> Range<usize> {
143        0..self.data_byte_range().end
144    }
145}
146
147impl<'a> FontRead<'a> for Subtable<'a> {
148    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
149        let mut cursor = data.cursor();
150        cursor.advance::<u32>();
151        cursor.advance::<u32>();
152        cursor.advance::<u32>();
153        let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
154        cursor.advance_by(data_byte_len);
155        cursor.finish(SubtableMarker { data_byte_len })
156    }
157}
158
159/// A subtable in a `kerx` table.
160pub type Subtable<'a> = TableRef<'a, SubtableMarker>;
161
162#[allow(clippy::needless_lifetimes)]
163impl<'a> Subtable<'a> {
164    /// The length of this subtable in bytes, including this header.
165    pub fn length(&self) -> u32 {
166        let range = self.shape.length_byte_range();
167        self.data.read_at(range.start).unwrap()
168    }
169
170    /// Circumstances under which this table is used.
171    pub fn coverage(&self) -> u32 {
172        let range = self.shape.coverage_byte_range();
173        self.data.read_at(range.start).unwrap()
174    }
175
176    /// The tuple count. This value is only used with variation fonts and should be 0 for all other fonts. The subtable's tupleCount will be ignored if the 'kerx' table version is less than 4.
177    pub fn tuple_count(&self) -> u32 {
178        let range = self.shape.tuple_count_byte_range();
179        self.data.read_at(range.start).unwrap()
180    }
181
182    /// Subtable specific data.
183    pub fn data(&self) -> &'a [u8] {
184        let range = self.shape.data_byte_range();
185        self.data.read_array(range).unwrap()
186    }
187}
188
189#[cfg(feature = "experimental_traverse")]
190impl<'a> SomeTable<'a> for Subtable<'a> {
191    fn type_name(&self) -> &str {
192        "Subtable"
193    }
194    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
195        match idx {
196            0usize => Some(Field::new("length", self.length())),
197            1usize => Some(Field::new("coverage", self.coverage())),
198            2usize => Some(Field::new("tuple_count", self.tuple_count())),
199            3usize => Some(Field::new("data", self.data())),
200            _ => None,
201        }
202    }
203}
204
205#[cfg(feature = "experimental_traverse")]
206#[allow(clippy::needless_lifetimes)]
207impl<'a> std::fmt::Debug for Subtable<'a> {
208    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209        (self as &dyn SomeTable<'a>).fmt(f)
210    }
211}
212
213/// The type 0 `kerx` subtable.
214#[derive(Debug, Clone, Copy)]
215#[doc(hidden)]
216pub struct Subtable0Marker {
217    pairs_byte_len: usize,
218}
219
220impl Subtable0Marker {
221    pub fn n_pairs_byte_range(&self) -> Range<usize> {
222        let start = 0;
223        start..start + u32::RAW_BYTE_LEN
224    }
225
226    pub fn search_range_byte_range(&self) -> Range<usize> {
227        let start = self.n_pairs_byte_range().end;
228        start..start + u32::RAW_BYTE_LEN
229    }
230
231    pub fn entry_selector_byte_range(&self) -> Range<usize> {
232        let start = self.search_range_byte_range().end;
233        start..start + u32::RAW_BYTE_LEN
234    }
235
236    pub fn range_shift_byte_range(&self) -> Range<usize> {
237        let start = self.entry_selector_byte_range().end;
238        start..start + u32::RAW_BYTE_LEN
239    }
240
241    pub fn pairs_byte_range(&self) -> Range<usize> {
242        let start = self.range_shift_byte_range().end;
243        start..start + self.pairs_byte_len
244    }
245}
246
247impl MinByteRange for Subtable0Marker {
248    fn min_byte_range(&self) -> Range<usize> {
249        0..self.pairs_byte_range().end
250    }
251}
252
253impl<'a> FontRead<'a> for Subtable0<'a> {
254    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
255        let mut cursor = data.cursor();
256        let n_pairs: u32 = cursor.read()?;
257        cursor.advance::<u32>();
258        cursor.advance::<u32>();
259        cursor.advance::<u32>();
260        let pairs_byte_len = (n_pairs as usize)
261            .checked_mul(Subtable0Pair::RAW_BYTE_LEN)
262            .ok_or(ReadError::OutOfBounds)?;
263        cursor.advance_by(pairs_byte_len);
264        cursor.finish(Subtable0Marker { pairs_byte_len })
265    }
266}
267
268/// The type 0 `kerx` subtable.
269pub type Subtable0<'a> = TableRef<'a, Subtable0Marker>;
270
271#[allow(clippy::needless_lifetimes)]
272impl<'a> Subtable0<'a> {
273    /// The number of kerning pairs in this subtable.
274    pub fn n_pairs(&self) -> u32 {
275        let range = self.shape.n_pairs_byte_range();
276        self.data.read_at(range.start).unwrap()
277    }
278
279    /// 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.
280    pub fn search_range(&self) -> u32 {
281        let range = self.shape.search_range_byte_range();
282        self.data.read_at(range.start).unwrap()
283    }
284
285    /// 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.
286    pub fn entry_selector(&self) -> u32 {
287        let range = self.shape.entry_selector_byte_range();
288        self.data.read_at(range.start).unwrap()
289    }
290
291    /// 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.
292    pub fn range_shift(&self) -> u32 {
293        let range = self.shape.range_shift_byte_range();
294        self.data.read_at(range.start).unwrap()
295    }
296
297    /// Kerning records.
298    pub fn pairs(&self) -> &'a [Subtable0Pair] {
299        let range = self.shape.pairs_byte_range();
300        self.data.read_array(range).unwrap()
301    }
302}
303
304#[cfg(feature = "experimental_traverse")]
305impl<'a> SomeTable<'a> for Subtable0<'a> {
306    fn type_name(&self) -> &str {
307        "Subtable0"
308    }
309    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
310        match idx {
311            0usize => Some(Field::new("n_pairs", self.n_pairs())),
312            1usize => Some(Field::new("search_range", self.search_range())),
313            2usize => Some(Field::new("entry_selector", self.entry_selector())),
314            3usize => Some(Field::new("range_shift", self.range_shift())),
315            4usize => Some(Field::new(
316                "pairs",
317                traversal::FieldType::array_of_records(
318                    stringify!(Subtable0Pair),
319                    self.pairs(),
320                    self.offset_data(),
321                ),
322            )),
323            _ => None,
324        }
325    }
326}
327
328#[cfg(feature = "experimental_traverse")]
329#[allow(clippy::needless_lifetimes)]
330impl<'a> std::fmt::Debug for Subtable0<'a> {
331    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
332        (self as &dyn SomeTable<'a>).fmt(f)
333    }
334}
335
336/// The type 0 `kerx` subtable kerning record.
337#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
338#[repr(C)]
339#[repr(packed)]
340pub struct Subtable0Pair {
341    /// The glyph index for the lefthand glyph in the kerning pair.
342    pub left: BigEndian<GlyphId16>,
343    /// The glyph index for the righthand glyph in the kerning pair.
344    pub right: BigEndian<GlyphId16>,
345    /// Kerning value.
346    pub value: BigEndian<i16>,
347}
348
349impl Subtable0Pair {
350    /// The glyph index for the lefthand glyph in the kerning pair.
351    pub fn left(&self) -> GlyphId16 {
352        self.left.get()
353    }
354
355    /// The glyph index for the righthand glyph in the kerning pair.
356    pub fn right(&self) -> GlyphId16 {
357        self.right.get()
358    }
359
360    /// Kerning value.
361    pub fn value(&self) -> i16 {
362        self.value.get()
363    }
364}
365
366impl FixedSize for Subtable0Pair {
367    const RAW_BYTE_LEN: usize =
368        GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN;
369}
370
371#[cfg(feature = "experimental_traverse")]
372impl<'a> SomeRecord<'a> for Subtable0Pair {
373    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
374        RecordResolver {
375            name: "Subtable0Pair",
376            get_field: Box::new(move |idx, _data| match idx {
377                0usize => Some(Field::new("left", self.left())),
378                1usize => Some(Field::new("right", self.right())),
379                2usize => Some(Field::new("value", self.value())),
380                _ => None,
381            }),
382            data,
383        }
384    }
385}