Coverage Report

Created: 2026-05-24 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fontations/read-fonts/generated/generated_fvar.rs
Line
Count
Source
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)]
6
use crate::codegen_prelude::*;
7
8
impl<'a> MinByteRange<'a> for Fvar<'a> {
9
0
    fn min_byte_range(&self) -> Range<usize> {
10
0
        0..self.instance_size_byte_range().end
11
0
    }
12
0
    fn min_table_bytes(&self) -> &'a [u8] {
13
0
        let range = self.min_byte_range();
14
0
        self.data.as_bytes().get(range).unwrap_or_default()
15
0
    }
16
}
17
18
impl TopLevelTable for Fvar<'_> {
19
    /// `fvar`
20
    const TAG: Tag = Tag::new(b"fvar");
21
}
22
23
impl<'a> FontRead<'a> for Fvar<'a> {
24
79.7k
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25
        #[allow(clippy::absurd_extreme_comparisons)]
26
79.7k
        if data.len() < Self::MIN_SIZE {
27
0
            return Err(ReadError::OutOfBounds);
28
79.7k
        }
29
79.7k
        Ok(Self { data })
30
79.7k
    }
31
}
32
33
/// The [fvar (Font Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) table
34
#[derive(Clone)]
35
pub struct Fvar<'a> {
36
    data: FontData<'a>,
37
}
38
39
#[allow(clippy::needless_lifetimes)]
40
impl<'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
0
    pub fn version(&self) -> MajorMinor {
53
0
        let range = self.version_byte_range();
54
0
        self.data.read_at(range.start).ok().unwrap()
55
0
    }
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
6.11M
    pub fn axis_instance_arrays_offset(&self) -> Offset16 {
60
6.11M
        let range = self.axis_instance_arrays_offset_byte_range();
61
6.11M
        self.data.read_at(range.start).ok().unwrap()
62
6.11M
    }
63
64
    /// Attempt to resolve [`axis_instance_arrays_offset`][Self::axis_instance_arrays_offset].
65
6.11M
    pub fn axis_instance_arrays(&self) -> Result<AxisInstanceArrays<'a>, ReadError> {
66
6.11M
        let data = self.data;
67
6.11M
        let args = (
68
6.11M
            self.axis_count(),
69
6.11M
            self.instance_count(),
70
6.11M
            self.instance_size(),
71
6.11M
        );
72
6.11M
        self.axis_instance_arrays_offset()
73
6.11M
            .resolve_with_args(data, &args)
74
6.11M
    }
75
76
    /// The number of variation axes in the font (the number of records in the axes array).
77
6.19M
    pub fn axis_count(&self) -> u16 {
78
6.19M
        let range = self.axis_count_byte_range();
79
6.19M
        self.data.read_at(range.start).ok().unwrap()
80
6.19M
    }
81
82
    /// The size in bytes of each VariationAxisRecord — set to 20 (0x0014) for this version.
83
0
    pub fn axis_size(&self) -> u16 {
84
0
        let range = self.axis_size_byte_range();
85
0
        self.data.read_at(range.start).ok().unwrap()
86
0
    }
87
88
    /// The number of named instances defined in the font (the number of records in the instances array).
89
6.11M
    pub fn instance_count(&self) -> u16 {
90
6.11M
        let range = self.instance_count_byte_range();
91
6.11M
        self.data.read_at(range.start).ok().unwrap()
92
6.11M
    }
93
94
    /// The size in bytes of each InstanceRecord — set to either axisCount * sizeof(Fixed) + 4, or to axisCount * sizeof(Fixed) + 6.
95
6.11M
    pub fn instance_size(&self) -> u16 {
96
6.11M
        let range = self.instance_size_byte_range();
97
6.11M
        self.data.read_at(range.start).ok().unwrap()
98
6.11M
    }
99
100
24.5M
    pub fn version_byte_range(&self) -> Range<usize> {
101
24.5M
        let start = 0;
102
24.5M
        start..start + MajorMinor::RAW_BYTE_LEN
103
24.5M
    }
104
105
24.5M
    pub fn axis_instance_arrays_offset_byte_range(&self) -> Range<usize> {
106
24.5M
        let start = self.version_byte_range().end;
107
24.5M
        start..start + Offset16::RAW_BYTE_LEN
108
24.5M
    }
109
110
18.4M
    pub fn _reserved_byte_range(&self) -> Range<usize> {
111
18.4M
        let start = self.axis_instance_arrays_offset_byte_range().end;
112
18.4M
        start..start + u16::RAW_BYTE_LEN
113
18.4M
    }
114
115
18.4M
    pub fn axis_count_byte_range(&self) -> Range<usize> {
116
18.4M
        let start = self._reserved_byte_range().end;
117
18.4M
        start..start + u16::RAW_BYTE_LEN
118
18.4M
    }
119
120
12.2M
    pub fn axis_size_byte_range(&self) -> Range<usize> {
121
12.2M
        let start = self.axis_count_byte_range().end;
122
12.2M
        start..start + u16::RAW_BYTE_LEN
123
12.2M
    }
124
125
12.2M
    pub fn instance_count_byte_range(&self) -> Range<usize> {
126
12.2M
        let start = self.axis_size_byte_range().end;
127
12.2M
        start..start + u16::RAW_BYTE_LEN
128
12.2M
    }
129
130
6.11M
    pub fn instance_size_byte_range(&self) -> Range<usize> {
131
6.11M
        let start = self.instance_count_byte_range().end;
132
6.11M
        start..start + u16::RAW_BYTE_LEN
133
6.11M
    }
134
}
135
136
#[cfg(feature = "experimental_traverse")]
137
impl<'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)]
162
impl<'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
168
impl<'a> MinByteRange<'a> for AxisInstanceArrays<'a> {
169
0
    fn min_byte_range(&self) -> Range<usize> {
170
0
        0..self.instances_byte_range().end
171
0
    }
172
0
    fn min_table_bytes(&self) -> &'a [u8] {
173
0
        let range = self.min_byte_range();
174
0
        self.data.as_bytes().get(range).unwrap_or_default()
175
0
    }
176
}
177
178
impl ReadArgs for AxisInstanceArrays<'_> {
179
    type Args = (u16, u16, u16);
180
}
181
182
impl<'a> FontReadWithArgs<'a> for AxisInstanceArrays<'a> {
183
1.29M
    fn read_with_args(data: FontData<'a>, args: &(u16, u16, u16)) -> Result<Self, ReadError> {
184
1.29M
        let (axis_count, instance_count, instance_size) = *args;
185
186
        #[allow(clippy::absurd_extreme_comparisons)]
187
1.29M
        if data.len() < Self::MIN_SIZE {
188
0
            return Err(ReadError::OutOfBounds);
189
1.29M
        }
190
1.29M
        Ok(Self {
191
1.29M
            data,
192
1.29M
            axis_count,
193
1.29M
            instance_count,
194
1.29M
            instance_size,
195
1.29M
        })
196
1.29M
    }
197
}
198
199
impl<'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
0
    pub fn read(
205
0
        data: FontData<'a>,
206
0
        axis_count: u16,
207
0
        instance_count: u16,
208
0
        instance_size: u16,
209
0
    ) -> Result<Self, ReadError> {
210
0
        let args = (axis_count, instance_count, instance_size);
211
0
        Self::read_with_args(data, &args)
212
0
    }
213
}
214
215
/// Shim table to handle combined axis and instance arrays.
216
#[derive(Clone)]
217
pub 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)]
225
impl<'a> AxisInstanceArrays<'a> {
226
    pub const MIN_SIZE: usize = 0;
227
    basic_table_impls!(impl_the_methods);
228
229
    /// Variation axis record array.
230
1.29M
    pub fn axes(&self) -> &'a [VariationAxisRecord] {
231
1.29M
        let range = self.axes_byte_range();
232
1.29M
        self.data.read_array(range).ok().unwrap_or_default()
233
1.29M
    }
234
235
    /// Instance record array.
236
0
    pub fn instances(&self) -> ComputedArray<'a, InstanceRecord<'a>> {
237
0
        let range = self.instances_byte_range();
238
0
        self.data
239
0
            .read_with_args(range, &(self.axis_count(), self.instance_size()))
240
0
            .unwrap_or_default()
241
0
    }
242
243
1.29M
    pub(crate) fn axis_count(&self) -> u16 {
244
1.29M
        self.axis_count
245
1.29M
    }
246
247
0
    pub(crate) fn instance_count(&self) -> u16 {
248
0
        self.instance_count
249
0
    }
250
251
0
    pub(crate) fn instance_size(&self) -> u16 {
252
0
        self.instance_size
253
0
    }
254
255
1.29M
    pub fn axes_byte_range(&self) -> Range<usize> {
256
1.29M
        let axis_count = self.axis_count();
257
1.29M
        let start = 0;
258
1.29M
        start..start + (axis_count as usize).saturating_mul(VariationAxisRecord::RAW_BYTE_LEN)
259
1.29M
    }
260
261
0
    pub fn instances_byte_range(&self) -> Range<usize> {
262
0
        let instance_count = self.instance_count();
263
0
        let start = self.axes_byte_range().end;
264
0
        start
265
0
            ..start
266
0
                + (instance_count as usize).saturating_mul(
267
0
                    <InstanceRecord as ComputeSize>::compute_size(&(
268
0
                        self.axis_count(),
269
0
                        self.instance_size(),
270
0
                    ))
271
0
                    .unwrap_or(0),
272
0
                )
273
0
    }
274
}
275
276
#[cfg(feature = "experimental_traverse")]
277
impl<'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)]
306
impl<'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)]
316
pub 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
331
impl VariationAxisRecord {
332
    /// Tag identifying the design variation for the axis.
333
12.4M
    pub fn axis_tag(&self) -> Tag {
334
12.4M
        self.axis_tag.get()
335
12.4M
    }
336
337
    /// The minimum coordinate value for the axis.
338
802k
    pub fn min_value(&self) -> Fixed {
339
802k
        self.min_value.get()
340
802k
    }
341
342
    /// The default coordinate value for the axis.
343
805k
    pub fn default_value(&self) -> Fixed {
344
805k
        self.default_value.get()
345
805k
    }
346
347
    /// The maximum coordinate value for the axis.
348
802k
    pub fn max_value(&self) -> Fixed {
349
802k
        self.max_value.get()
350
802k
    }
351
352
    /// Axis qualifiers — see details below.
353
0
    pub fn flags(&self) -> u16 {
354
0
        self.flags.get()
355
0
    }
356
357
    /// The name ID for entries in the 'name' table that provide a display name for this axis.
358
0
    pub fn axis_name_id(&self) -> NameId {
359
0
        self.axis_name_id.get()
360
0
    }
361
}
362
363
impl 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")]
373
impl<'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
}