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