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