Skip to main content

read_fonts/generated/
generated_fvar.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 Fvar<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.instance_size_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 Fvar<'_> {
19    /// `fvar`
20    const TAG: Tag = Tag::new(b"fvar");
21}
22
23impl<'a> FontRead<'a> for Fvar<'a> {
24    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25        #[allow(clippy::absurd_extreme_comparisons)]
26        if data.len() < Self::MIN_SIZE {
27            return Err(ReadError::OutOfBounds);
28        }
29        Ok(Self { data })
30    }
31}
32
33/// The [fvar (Font Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) table
34#[derive(Clone)]
35pub struct Fvar<'a> {
36    data: FontData<'a>,
37}
38
39#[allow(clippy::needless_lifetimes)]
40impl<'a> Fvar<'a> {
41    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
42        + Offset16::RAW_BYTE_LEN
43        + u16::RAW_BYTE_LEN
44        + u16::RAW_BYTE_LEN
45        + u16::RAW_BYTE_LEN
46        + u16::RAW_BYTE_LEN
47        + u16::RAW_BYTE_LEN);
48    basic_table_impls!(impl_the_methods);
49
50    /// Major version number of the font variations table — set to 1.
51    /// Minor version number of the font variations table — set to 0.
52    pub fn version(&self) -> MajorMinor {
53        let range = self.version_byte_range();
54        self.data.read_at(range.start).ok().unwrap()
55    }
56
57    /// Offset in bytes from the beginning of the table to the start of the VariationAxisRecord array. The
58    /// InstanceRecord array directly follows.
59    pub fn axis_instance_arrays_offset(&self) -> Offset16 {
60        let range = self.axis_instance_arrays_offset_byte_range();
61        self.data.read_at(range.start).ok().unwrap()
62    }
63
64    /// Attempt to resolve [`axis_instance_arrays_offset`][Self::axis_instance_arrays_offset].
65    pub fn axis_instance_arrays(&self) -> Result<AxisInstanceArrays<'a>, ReadError> {
66        let data = self.data;
67        let args = (
68            self.axis_count(),
69            self.instance_count(),
70            self.instance_size(),
71        );
72        self.axis_instance_arrays_offset()
73            .resolve_with_args(data, &args)
74    }
75
76    /// The number of variation axes in the font (the number of records in the axes array).
77    pub fn axis_count(&self) -> u16 {
78        let range = self.axis_count_byte_range();
79        self.data.read_at(range.start).ok().unwrap()
80    }
81
82    /// The size in bytes of each VariationAxisRecord — set to 20 (0x0014) for this version.
83    pub fn axis_size(&self) -> u16 {
84        let range = self.axis_size_byte_range();
85        self.data.read_at(range.start).ok().unwrap()
86    }
87
88    /// The number of named instances defined in the font (the number of records in the instances array).
89    pub fn instance_count(&self) -> u16 {
90        let range = self.instance_count_byte_range();
91        self.data.read_at(range.start).ok().unwrap()
92    }
93
94    /// The size in bytes of each InstanceRecord — set to either axisCount * sizeof(Fixed) + 4, or to axisCount * sizeof(Fixed) + 6.
95    pub fn instance_size(&self) -> u16 {
96        let range = self.instance_size_byte_range();
97        self.data.read_at(range.start).ok().unwrap()
98    }
99
100    pub fn version_byte_range(&self) -> Range<usize> {
101        let start = 0;
102        let end = start + MajorMinor::RAW_BYTE_LEN;
103        start..end
104    }
105
106    pub fn axis_instance_arrays_offset_byte_range(&self) -> Range<usize> {
107        let start = self.version_byte_range().end;
108        let end = start + Offset16::RAW_BYTE_LEN;
109        start..end
110    }
111
112    pub fn _reserved_byte_range(&self) -> Range<usize> {
113        let start = self.axis_instance_arrays_offset_byte_range().end;
114        let end = start + u16::RAW_BYTE_LEN;
115        start..end
116    }
117
118    pub fn axis_count_byte_range(&self) -> Range<usize> {
119        let start = self._reserved_byte_range().end;
120        let end = start + u16::RAW_BYTE_LEN;
121        start..end
122    }
123
124    pub fn axis_size_byte_range(&self) -> Range<usize> {
125        let start = self.axis_count_byte_range().end;
126        let end = start + u16::RAW_BYTE_LEN;
127        start..end
128    }
129
130    pub fn instance_count_byte_range(&self) -> Range<usize> {
131        let start = self.axis_size_byte_range().end;
132        let end = start + u16::RAW_BYTE_LEN;
133        start..end
134    }
135
136    pub fn instance_size_byte_range(&self) -> Range<usize> {
137        let start = self.instance_count_byte_range().end;
138        let end = start + u16::RAW_BYTE_LEN;
139        start..end
140    }
141}
142
143const _: () = assert!(FontData::default_data_long_enough(Fvar::MIN_SIZE));
144
145impl Default for Fvar<'_> {
146    fn default() -> Self {
147        Self {
148            data: FontData::default_table_data(),
149        }
150    }
151}
152
153#[cfg(feature = "experimental_traverse")]
154impl<'a> SomeTable<'a> for Fvar<'a> {
155    fn type_name(&self) -> &str {
156        "Fvar"
157    }
158    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
159        match idx {
160            0usize => Some(Field::new("version", self.version())),
161            1usize => Some(Field::new(
162                "axis_instance_arrays_offset",
163                FieldType::offset(
164                    self.axis_instance_arrays_offset(),
165                    self.axis_instance_arrays(),
166                ),
167            )),
168            2usize => Some(Field::new("axis_count", self.axis_count())),
169            3usize => Some(Field::new("axis_size", self.axis_size())),
170            4usize => Some(Field::new("instance_count", self.instance_count())),
171            5usize => Some(Field::new("instance_size", self.instance_size())),
172            _ => None,
173        }
174    }
175}
176
177#[cfg(feature = "experimental_traverse")]
178#[allow(clippy::needless_lifetimes)]
179impl<'a> std::fmt::Debug for Fvar<'a> {
180    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181        (self as &dyn SomeTable<'a>).fmt(f)
182    }
183}
184
185impl<'a> MinByteRange<'a> for AxisInstanceArrays<'a> {
186    fn min_byte_range(&self) -> Range<usize> {
187        0..self.instances_byte_range().end
188    }
189    fn min_table_bytes(&self) -> &'a [u8] {
190        let range = self.min_byte_range();
191        self.data.as_bytes().get(range).unwrap_or_default()
192    }
193}
194
195impl ReadArgs for AxisInstanceArrays<'_> {
196    type Args = (u16, u16, u16);
197}
198
199impl<'a> FontReadWithArgs<'a> for AxisInstanceArrays<'a> {
200    fn read_with_args(data: FontData<'a>, args: &(u16, u16, u16)) -> Result<Self, ReadError> {
201        let (axis_count, instance_count, instance_size) = *args;
202
203        #[allow(clippy::absurd_extreme_comparisons)]
204        if data.len() < Self::MIN_SIZE {
205            return Err(ReadError::OutOfBounds);
206        }
207        Ok(Self {
208            data,
209            axis_count,
210            instance_count,
211            instance_size,
212        })
213    }
214}
215
216impl<'a> AxisInstanceArrays<'a> {
217    /// A constructor that requires additional arguments.
218    ///
219    /// This type requires some external state in order to be
220    /// parsed.
221    pub fn read(
222        data: FontData<'a>,
223        axis_count: u16,
224        instance_count: u16,
225        instance_size: u16,
226    ) -> Result<Self, ReadError> {
227        let args = (axis_count, instance_count, instance_size);
228        Self::read_with_args(data, &args)
229    }
230}
231
232/// Shim table to handle combined axis and instance arrays.
233#[derive(Clone)]
234pub struct AxisInstanceArrays<'a> {
235    data: FontData<'a>,
236    axis_count: u16,
237    instance_count: u16,
238    instance_size: u16,
239}
240
241#[allow(clippy::needless_lifetimes)]
242impl<'a> AxisInstanceArrays<'a> {
243    pub const MIN_SIZE: usize = 0;
244    basic_table_impls!(impl_the_methods);
245
246    /// Variation axis record array.
247    pub fn axes(&self) -> &'a [VariationAxisRecord] {
248        let range = self.axes_byte_range();
249        self.data.read_array(range).ok().unwrap_or_default()
250    }
251
252    /// Instance record array.
253    pub fn instances(&self) -> ComputedArray<'a, InstanceRecord<'a>> {
254        let range = self.instances_byte_range();
255        self.data
256            .read_with_args(range, &(self.axis_count(), self.instance_size()))
257            .unwrap_or_default()
258    }
259
260    pub(crate) fn axis_count(&self) -> u16 {
261        self.axis_count
262    }
263
264    pub(crate) fn instance_count(&self) -> u16 {
265        self.instance_count
266    }
267
268    pub(crate) fn instance_size(&self) -> u16 {
269        self.instance_size
270    }
271
272    pub fn axes_byte_range(&self) -> Range<usize> {
273        let axis_count = self.axis_count();
274        let start = 0;
275        let end = start
276            + (transforms::to_usize(axis_count)).saturating_mul(VariationAxisRecord::RAW_BYTE_LEN);
277        start..end
278    }
279
280    pub fn instances_byte_range(&self) -> Range<usize> {
281        let instance_count = self.instance_count();
282        let start = self.axes_byte_range().end;
283        let end = start
284            + (transforms::to_usize(instance_count)).saturating_mul(
285                <InstanceRecord as ComputeSize>::compute_size(&(
286                    self.axis_count(),
287                    self.instance_size(),
288                ))
289                .unwrap_or(0),
290            );
291        start..end
292    }
293}
294
295#[allow(clippy::absurd_extreme_comparisons)]
296const _: () = assert!(FontData::default_data_long_enough(
297    AxisInstanceArrays::MIN_SIZE
298));
299
300impl Default for AxisInstanceArrays<'_> {
301    fn default() -> Self {
302        Self {
303            data: FontData::default_table_data(),
304            axis_count: Default::default(),
305            instance_count: Default::default(),
306            instance_size: Default::default(),
307        }
308    }
309}
310
311#[cfg(feature = "experimental_traverse")]
312impl<'a> SomeTable<'a> for AxisInstanceArrays<'a> {
313    fn type_name(&self) -> &str {
314        "AxisInstanceArrays"
315    }
316    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
317        match idx {
318            0usize => Some(Field::new(
319                "axes",
320                traversal::FieldType::array_of_records(
321                    stringify!(VariationAxisRecord),
322                    self.axes(),
323                    self.offset_data(),
324                ),
325            )),
326            1usize => Some(Field::new(
327                "instances",
328                traversal::FieldType::computed_array(
329                    "InstanceRecord",
330                    self.instances(),
331                    self.offset_data(),
332                ),
333            )),
334            _ => None,
335        }
336    }
337}
338
339#[cfg(feature = "experimental_traverse")]
340#[allow(clippy::needless_lifetimes)]
341impl<'a> std::fmt::Debug for AxisInstanceArrays<'a> {
342    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
343        (self as &dyn SomeTable<'a>).fmt(f)
344    }
345}
346
347/// The [VariationAxisRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/fvar#variationaxisrecord)
348#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
349#[repr(C)]
350#[repr(packed)]
351pub struct VariationAxisRecord {
352    /// Tag identifying the design variation for the axis.
353    pub axis_tag: BigEndian<Tag>,
354    /// The minimum coordinate value for the axis.
355    pub min_value: BigEndian<Fixed>,
356    /// The default coordinate value for the axis.
357    pub default_value: BigEndian<Fixed>,
358    /// The maximum coordinate value for the axis.
359    pub max_value: BigEndian<Fixed>,
360    /// Axis qualifiers — see details below.
361    pub flags: BigEndian<u16>,
362    /// The name ID for entries in the 'name' table that provide a display name for this axis.
363    pub axis_name_id: BigEndian<NameId>,
364}
365
366impl VariationAxisRecord {
367    /// Tag identifying the design variation for the axis.
368    pub fn axis_tag(&self) -> Tag {
369        self.axis_tag.get()
370    }
371
372    /// The minimum coordinate value for the axis.
373    pub fn min_value(&self) -> Fixed {
374        self.min_value.get()
375    }
376
377    /// The default coordinate value for the axis.
378    pub fn default_value(&self) -> Fixed {
379        self.default_value.get()
380    }
381
382    /// The maximum coordinate value for the axis.
383    pub fn max_value(&self) -> Fixed {
384        self.max_value.get()
385    }
386
387    /// Axis qualifiers — see details below.
388    pub fn flags(&self) -> u16 {
389        self.flags.get()
390    }
391
392    /// The name ID for entries in the 'name' table that provide a display name for this axis.
393    pub fn axis_name_id(&self) -> NameId {
394        self.axis_name_id.get()
395    }
396}
397
398impl FixedSize for VariationAxisRecord {
399    const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN
400        + Fixed::RAW_BYTE_LEN
401        + Fixed::RAW_BYTE_LEN
402        + Fixed::RAW_BYTE_LEN
403        + u16::RAW_BYTE_LEN
404        + NameId::RAW_BYTE_LEN;
405}
406
407#[cfg(feature = "experimental_traverse")]
408impl<'a> SomeRecord<'a> for VariationAxisRecord {
409    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
410        RecordResolver {
411            name: "VariationAxisRecord",
412            get_field: Box::new(move |idx, _data| match idx {
413                0usize => Some(Field::new("axis_tag", self.axis_tag())),
414                1usize => Some(Field::new("min_value", self.min_value())),
415                2usize => Some(Field::new("default_value", self.default_value())),
416                3usize => Some(Field::new("max_value", self.max_value())),
417                4usize => Some(Field::new("flags", self.flags())),
418                5usize => Some(Field::new("axis_name_id", self.axis_name_id())),
419                _ => None,
420            }),
421            data,
422        }
423    }
424}