Skip to main content

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