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        start..start + MajorMinor::RAW_BYTE_LEN
103    }
104
105    pub fn axis_instance_arrays_offset_byte_range(&self) -> Range<usize> {
106        let start = self.version_byte_range().end;
107        start..start + Offset16::RAW_BYTE_LEN
108    }
109
110    pub fn _reserved_byte_range(&self) -> Range<usize> {
111        let start = self.axis_instance_arrays_offset_byte_range().end;
112        start..start + u16::RAW_BYTE_LEN
113    }
114
115    pub fn axis_count_byte_range(&self) -> Range<usize> {
116        let start = self._reserved_byte_range().end;
117        start..start + u16::RAW_BYTE_LEN
118    }
119
120    pub fn axis_size_byte_range(&self) -> Range<usize> {
121        let start = self.axis_count_byte_range().end;
122        start..start + u16::RAW_BYTE_LEN
123    }
124
125    pub fn instance_count_byte_range(&self) -> Range<usize> {
126        let start = self.axis_size_byte_range().end;
127        start..start + u16::RAW_BYTE_LEN
128    }
129
130    pub fn instance_size_byte_range(&self) -> Range<usize> {
131        let start = self.instance_count_byte_range().end;
132        start..start + u16::RAW_BYTE_LEN
133    }
134}
135
136#[cfg(feature = "experimental_traverse")]
137impl<'a> SomeTable<'a> for Fvar<'a> {
138    fn type_name(&self) -> &str {
139        "Fvar"
140    }
141    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
142        match idx {
143            0usize => Some(Field::new("version", self.version())),
144            1usize => Some(Field::new(
145                "axis_instance_arrays_offset",
146                FieldType::offset(
147                    self.axis_instance_arrays_offset(),
148                    self.axis_instance_arrays(),
149                ),
150            )),
151            2usize => Some(Field::new("axis_count", self.axis_count())),
152            3usize => Some(Field::new("axis_size", self.axis_size())),
153            4usize => Some(Field::new("instance_count", self.instance_count())),
154            5usize => Some(Field::new("instance_size", self.instance_size())),
155            _ => None,
156        }
157    }
158}
159
160#[cfg(feature = "experimental_traverse")]
161#[allow(clippy::needless_lifetimes)]
162impl<'a> std::fmt::Debug for Fvar<'a> {
163    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164        (self as &dyn SomeTable<'a>).fmt(f)
165    }
166}
167
168impl<'a> MinByteRange<'a> for AxisInstanceArrays<'a> {
169    fn min_byte_range(&self) -> Range<usize> {
170        0..self.instances_byte_range().end
171    }
172    fn min_table_bytes(&self) -> &'a [u8] {
173        let range = self.min_byte_range();
174        self.data.as_bytes().get(range).unwrap_or_default()
175    }
176}
177
178impl ReadArgs for AxisInstanceArrays<'_> {
179    type Args = (u16, u16, u16);
180}
181
182impl<'a> FontReadWithArgs<'a> for AxisInstanceArrays<'a> {
183    fn read_with_args(data: FontData<'a>, args: &(u16, u16, u16)) -> Result<Self, ReadError> {
184        let (axis_count, instance_count, instance_size) = *args;
185
186        #[allow(clippy::absurd_extreme_comparisons)]
187        if data.len() < Self::MIN_SIZE {
188            return Err(ReadError::OutOfBounds);
189        }
190        Ok(Self {
191            data,
192            axis_count,
193            instance_count,
194            instance_size,
195        })
196    }
197}
198
199impl<'a> AxisInstanceArrays<'a> {
200    /// A constructor that requires additional arguments.
201    ///
202    /// This type requires some external state in order to be
203    /// parsed.
204    pub fn read(
205        data: FontData<'a>,
206        axis_count: u16,
207        instance_count: u16,
208        instance_size: u16,
209    ) -> Result<Self, ReadError> {
210        let args = (axis_count, instance_count, instance_size);
211        Self::read_with_args(data, &args)
212    }
213}
214
215/// Shim table to handle combined axis and instance arrays.
216#[derive(Clone)]
217pub struct AxisInstanceArrays<'a> {
218    data: FontData<'a>,
219    axis_count: u16,
220    instance_count: u16,
221    instance_size: u16,
222}
223
224#[allow(clippy::needless_lifetimes)]
225impl<'a> AxisInstanceArrays<'a> {
226    pub const MIN_SIZE: usize = 0;
227    basic_table_impls!(impl_the_methods);
228
229    /// Variation axis record array.
230    pub fn axes(&self) -> &'a [VariationAxisRecord] {
231        let range = self.axes_byte_range();
232        self.data.read_array(range).ok().unwrap_or_default()
233    }
234
235    /// Instance record array.
236    pub fn instances(&self) -> ComputedArray<'a, InstanceRecord<'a>> {
237        let range = self.instances_byte_range();
238        self.data
239            .read_with_args(range, &(self.axis_count(), self.instance_size()))
240            .unwrap_or_default()
241    }
242
243    pub(crate) fn axis_count(&self) -> u16 {
244        self.axis_count
245    }
246
247    pub(crate) fn instance_count(&self) -> u16 {
248        self.instance_count
249    }
250
251    pub(crate) fn instance_size(&self) -> u16 {
252        self.instance_size
253    }
254
255    pub fn axes_byte_range(&self) -> Range<usize> {
256        let axis_count = self.axis_count();
257        let start = 0;
258        start..start + (axis_count as usize).saturating_mul(VariationAxisRecord::RAW_BYTE_LEN)
259    }
260
261    pub fn instances_byte_range(&self) -> Range<usize> {
262        let instance_count = self.instance_count();
263        let start = self.axes_byte_range().end;
264        start
265            ..start
266                + (instance_count as usize).saturating_mul(
267                    <InstanceRecord as ComputeSize>::compute_size(&(
268                        self.axis_count(),
269                        self.instance_size(),
270                    ))
271                    .unwrap_or(0),
272                )
273    }
274}
275
276#[cfg(feature = "experimental_traverse")]
277impl<'a> SomeTable<'a> for AxisInstanceArrays<'a> {
278    fn type_name(&self) -> &str {
279        "AxisInstanceArrays"
280    }
281    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
282        match idx {
283            0usize => Some(Field::new(
284                "axes",
285                traversal::FieldType::array_of_records(
286                    stringify!(VariationAxisRecord),
287                    self.axes(),
288                    self.offset_data(),
289                ),
290            )),
291            1usize => Some(Field::new(
292                "instances",
293                traversal::FieldType::computed_array(
294                    "InstanceRecord",
295                    self.instances(),
296                    self.offset_data(),
297                ),
298            )),
299            _ => None,
300        }
301    }
302}
303
304#[cfg(feature = "experimental_traverse")]
305#[allow(clippy::needless_lifetimes)]
306impl<'a> std::fmt::Debug for AxisInstanceArrays<'a> {
307    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
308        (self as &dyn SomeTable<'a>).fmt(f)
309    }
310}
311
312/// The [VariationAxisRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/fvar#variationaxisrecord)
313#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
314#[repr(C)]
315#[repr(packed)]
316pub struct VariationAxisRecord {
317    /// Tag identifying the design variation for the axis.
318    pub axis_tag: BigEndian<Tag>,
319    /// The minimum coordinate value for the axis.
320    pub min_value: BigEndian<Fixed>,
321    /// The default coordinate value for the axis.
322    pub default_value: BigEndian<Fixed>,
323    /// The maximum coordinate value for the axis.
324    pub max_value: BigEndian<Fixed>,
325    /// Axis qualifiers — see details below.
326    pub flags: BigEndian<u16>,
327    /// The name ID for entries in the 'name' table that provide a display name for this axis.
328    pub axis_name_id: BigEndian<NameId>,
329}
330
331impl VariationAxisRecord {
332    /// Tag identifying the design variation for the axis.
333    pub fn axis_tag(&self) -> Tag {
334        self.axis_tag.get()
335    }
336
337    /// The minimum coordinate value for the axis.
338    pub fn min_value(&self) -> Fixed {
339        self.min_value.get()
340    }
341
342    /// The default coordinate value for the axis.
343    pub fn default_value(&self) -> Fixed {
344        self.default_value.get()
345    }
346
347    /// The maximum coordinate value for the axis.
348    pub fn max_value(&self) -> Fixed {
349        self.max_value.get()
350    }
351
352    /// Axis qualifiers — see details below.
353    pub fn flags(&self) -> u16 {
354        self.flags.get()
355    }
356
357    /// The name ID for entries in the 'name' table that provide a display name for this axis.
358    pub fn axis_name_id(&self) -> NameId {
359        self.axis_name_id.get()
360    }
361}
362
363impl FixedSize for VariationAxisRecord {
364    const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN
365        + Fixed::RAW_BYTE_LEN
366        + Fixed::RAW_BYTE_LEN
367        + Fixed::RAW_BYTE_LEN
368        + u16::RAW_BYTE_LEN
369        + NameId::RAW_BYTE_LEN;
370}
371
372#[cfg(feature = "experimental_traverse")]
373impl<'a> SomeRecord<'a> for VariationAxisRecord {
374    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
375        RecordResolver {
376            name: "VariationAxisRecord",
377            get_field: Box::new(move |idx, _data| match idx {
378                0usize => Some(Field::new("axis_tag", self.axis_tag())),
379                1usize => Some(Field::new("min_value", self.min_value())),
380                2usize => Some(Field::new("default_value", self.default_value())),
381                3usize => Some(Field::new("max_value", self.max_value())),
382                4usize => Some(Field::new("flags", self.flags())),
383                5usize => Some(Field::new("axis_name_id", self.axis_name_id())),
384                _ => None,
385            }),
386            data,
387        }
388    }
389}