Skip to main content

read_fonts/generated/
generated_stat.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 Stat<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.offset_to_axis_value_offsets_byte_range().end
11    }
12    fn min_table_bytes(&self) -> &'a [u8] {
13        let range = self.min_byte_range();
14        self.offset_data().as_bytes().get(range).unwrap_or_default()
15    }
16}
17
18impl TopLevelTable for Stat<'_> {
19    /// `STAT`
20    const TAG: Tag = Tag::new(b"STAT");
21}
22
23impl ReadArgs for Stat<'_> {
24    type Args = ();
25}
26
27impl<'a> FontRead<'a> for Stat<'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        let Some(data) = TableDataRef::new(data.as_bytes()) else {
34            return Err(ReadError::OutOfBounds);
35        };
36        Ok(Self { data })
37    }
38}
39
40/// The fields at the start of the table, which are read directly.
41#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
42#[repr(C, packed)]
43#[doc(hidden)]
44pub struct StatFixedHeader {
45    pub version: BigEndian<MajorMinor>,
46    pub design_axis_size: BigEndian<u16>,
47    pub design_axis_count: BigEndian<u16>,
48    pub design_axes_offset: BigEndian<Offset32>,
49    pub axis_value_count: BigEndian<u16>,
50    pub offset_to_axis_value_offsets: BigEndian<Nullable<Offset32>>,
51}
52
53#[allow(clippy::absurd_extreme_comparisons)]
54const _: () = assert!(std::mem::size_of::<StatFixedHeader>() <= Stat::MIN_SIZE);
55
56/// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table)
57#[derive(Clone)]
58pub struct Stat<'a> {
59    data: TableDataRef<'a, StatFixedHeader>,
60}
61
62#[allow(clippy::needless_lifetimes)]
63impl<'a> Stat<'a> {
64    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
65        + u16::RAW_BYTE_LEN
66        + u16::RAW_BYTE_LEN
67        + Offset32::RAW_BYTE_LEN
68        + u16::RAW_BYTE_LEN
69        + Offset32::RAW_BYTE_LEN);
70    basic_table_impls!(impl_the_methods);
71
72    /// Major/minor version number. Set to 1.2 for new fonts.
73    pub fn version(&self) -> MajorMinor {
74        self.data.header().version.get()
75    }
76
77    /// The size in bytes of each axis record.
78    pub fn design_axis_size(&self) -> u16 {
79        self.data.header().design_axis_size.get()
80    }
81
82    /// The number of axis records. In a font with an 'fvar' table,
83    /// this value must be greater than or equal to the axisCount value
84    /// in the 'fvar' table. In all fonts, must be greater than zero if
85    /// axisValueCount is greater than zero.
86    pub fn design_axis_count(&self) -> u16 {
87        self.data.header().design_axis_count.get()
88    }
89
90    /// Offset in bytes from the beginning of the STAT table to the
91    /// start of the design axes array. If designAxisCount is zero, set
92    /// to zero; if designAxisCount is greater than zero, must be
93    /// greater than zero.
94    pub fn design_axes_offset(&self) -> Offset32 {
95        self.data.header().design_axes_offset.get()
96    }
97
98    /// Attempt to resolve [`design_axes_offset`][Self::design_axes_offset].
99    pub fn design_axes(&self) -> Result<&'a [AxisRecord], ReadError> {
100        let data = self.offset_data();
101        let args = self.design_axis_count();
102        self.design_axes_offset().resolve_with_args(data, args)
103    }
104
105    /// The number of axis value tables.
106    pub fn axis_value_count(&self) -> u16 {
107        self.data.header().axis_value_count.get()
108    }
109
110    /// Offset in bytes from the beginning of the STAT table to the
111    /// start of the design axes value offsets array. If axisValueCount
112    /// is zero, set to zero; if axisValueCount is greater than zero,
113    /// must be greater than zero.
114    pub fn offset_to_axis_value_offsets(&self) -> Nullable<Offset32> {
115        self.data.header().offset_to_axis_value_offsets.get()
116    }
117
118    /// Attempt to resolve [`offset_to_axis_value_offsets`][Self::offset_to_axis_value_offsets].
119    pub fn offset_to_axis_values(&self) -> Option<Result<AxisValueArray<'a>, ReadError>> {
120        let data = self.offset_data();
121        let args = self.axis_value_count();
122        self.offset_to_axis_value_offsets()
123            .resolve_with_args(data, args)
124    }
125
126    /// Name ID used as fallback when projection of names into a
127    /// particular font model produces a subfamily name containing only
128    /// elidable elements.
129    pub fn elided_fallback_name_id(&self) -> Option<NameId> {
130        let range = self.elided_fallback_name_id_byte_range();
131        (!range.is_empty())
132            .then(|| self.offset_data().read_at(range.start).ok())
133            .flatten()
134    }
135
136    pub fn version_byte_range(&self) -> Range<usize> {
137        let start = 0;
138        let end = start + MajorMinor::RAW_BYTE_LEN;
139        start..end
140    }
141
142    pub fn design_axis_size_byte_range(&self) -> Range<usize> {
143        let start = self.version_byte_range().end;
144        let end = start + u16::RAW_BYTE_LEN;
145        start..end
146    }
147
148    pub fn design_axis_count_byte_range(&self) -> Range<usize> {
149        let start = self.design_axis_size_byte_range().end;
150        let end = start + u16::RAW_BYTE_LEN;
151        start..end
152    }
153
154    pub fn design_axes_offset_byte_range(&self) -> Range<usize> {
155        let start = self.design_axis_count_byte_range().end;
156        let end = start + Offset32::RAW_BYTE_LEN;
157        start..end
158    }
159
160    pub fn axis_value_count_byte_range(&self) -> Range<usize> {
161        let start = self.design_axes_offset_byte_range().end;
162        let end = start + u16::RAW_BYTE_LEN;
163        start..end
164    }
165
166    pub fn offset_to_axis_value_offsets_byte_range(&self) -> Range<usize> {
167        let start = self.axis_value_count_byte_range().end;
168        let end = start + Offset32::RAW_BYTE_LEN;
169        start..end
170    }
171
172    pub fn elided_fallback_name_id_byte_range(&self) -> Range<usize> {
173        let start = self.offset_to_axis_value_offsets_byte_range().end;
174        let end = if self.version().compatible((1u16, 1u16)) {
175            start + NameId::RAW_BYTE_LEN
176        } else {
177            start
178        };
179        start..end
180    }
181}
182
183const _: () = assert!(FontData::default_data_long_enough(Stat::MIN_SIZE));
184
185impl Default for Stat<'_> {
186    fn default() -> Self {
187        Self {
188            data: TableDataRef::new(FontData::default_table_data().as_bytes())
189                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
190        }
191    }
192}
193
194/// [Axis Records](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-records)
195#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
196#[repr(C)]
197#[repr(packed)]
198pub struct AxisRecord {
199    /// A tag identifying the axis of design variation.
200    pub axis_tag: BigEndian<Tag>,
201    /// The name ID for entries in the 'name' table that provide a
202    /// display string for this axis.
203    pub axis_name_id: BigEndian<NameId>,
204    /// A value that applications can use to determine primary sorting
205    /// of face names, or for ordering of labels when composing family
206    /// or face names.
207    pub axis_ordering: BigEndian<u16>,
208}
209
210impl AxisRecord {
211    /// A tag identifying the axis of design variation.
212    pub fn axis_tag(&self) -> Tag {
213        self.axis_tag.get()
214    }
215
216    /// The name ID for entries in the 'name' table that provide a
217    /// display string for this axis.
218    pub fn axis_name_id(&self) -> NameId {
219        self.axis_name_id.get()
220    }
221
222    /// A value that applications can use to determine primary sorting
223    /// of face names, or for ordering of labels when composing family
224    /// or face names.
225    pub fn axis_ordering(&self) -> u16 {
226        self.axis_ordering.get()
227    }
228}
229
230impl FixedSize for AxisRecord {
231    const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
232}
233
234impl<'a> MinByteRange<'a> for AxisValueArray<'a> {
235    fn min_byte_range(&self) -> Range<usize> {
236        0..self.axis_value_offsets_byte_range().end
237    }
238    fn min_table_bytes(&self) -> &'a [u8] {
239        let range = self.min_byte_range();
240        self.offset_data().as_bytes().get(range).unwrap_or_default()
241    }
242}
243
244impl ReadArgs for AxisValueArray<'_> {
245    type Args = u16;
246}
247
248impl<'a> FontRead<'a> for AxisValueArray<'a> {
249    fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
250        let axis_value_count = args;
251
252        #[allow(clippy::absurd_extreme_comparisons)]
253        if data.len() < Self::MIN_SIZE {
254            return Err(ReadError::OutOfBounds);
255        }
256        let Some(data) = TableDataRef::new(data.as_bytes()) else {
257            return Err(ReadError::OutOfBounds);
258        };
259        Ok(Self {
260            data,
261            axis_value_count,
262        })
263    }
264}
265
266impl<'a> AxisValueArray<'a> {
267    /// A constructor that requires additional arguments.
268    ///
269    /// This type requires some external state in order to be
270    /// parsed.
271    pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
272        let args = axis_value_count;
273        Self::read_with_args(data, args)
274    }
275}
276
277/// The fields at the start of the table, which are read directly.
278#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
279#[repr(C, packed)]
280#[doc(hidden)]
281pub struct AxisValueArrayFixedHeader {}
282
283#[allow(clippy::absurd_extreme_comparisons)]
284const _: () = assert!(std::mem::size_of::<AxisValueArrayFixedHeader>() <= AxisValueArray::MIN_SIZE);
285
286/// An array of [AxisValue] tables.
287#[derive(Clone)]
288pub struct AxisValueArray<'a> {
289    data: TableDataRef<'a, AxisValueArrayFixedHeader>,
290    axis_value_count: u16,
291}
292
293#[allow(clippy::needless_lifetimes)]
294impl<'a> AxisValueArray<'a> {
295    pub const MIN_SIZE: usize = 0;
296    basic_table_impls!(impl_the_methods);
297
298    /// Array of offsets to axis value tables, in bytes from the start
299    /// of the axis value offsets array.
300    pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
301        let range = self.axis_value_offsets_byte_range();
302        self.offset_data()
303            .read_array(range)
304            .ok()
305            .unwrap_or_default()
306    }
307
308    /// A dynamically resolving wrapper for [`axis_value_offsets`][Self::axis_value_offsets].
309    pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
310        let data = self.offset_data();
311        let offsets = self.axis_value_offsets();
312        ArrayOfOffsets::new(offsets, data, ())
313    }
314
315    pub(crate) fn axis_value_count(&self) -> u16 {
316        self.axis_value_count
317    }
318
319    pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
320        let axis_value_count = self.axis_value_count();
321        let start = 0;
322        let end =
323            start + (transforms::to_usize(axis_value_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
324        start..end
325    }
326}
327
328#[allow(clippy::absurd_extreme_comparisons)]
329const _: () = assert!(FontData::default_data_long_enough(AxisValueArray::MIN_SIZE));
330
331impl Default for AxisValueArray<'_> {
332    fn default() -> Self {
333        Self {
334            data: TableDataRef::new(FontData::default_table_data().as_bytes())
335                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
336            axis_value_count: Default::default(),
337        }
338    }
339}
340
341/// [Axis Value Tables](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-tables)
342#[derive(Clone)]
343pub enum AxisValue<'a> {
344    Format1(AxisValueFormat1<'a>),
345    Format2(AxisValueFormat2<'a>),
346    Format3(AxisValueFormat3<'a>),
347    Format4(AxisValueFormat4<'a>),
348}
349
350impl Default for AxisValue<'_> {
351    fn default() -> Self {
352        Self::Format1(Default::default())
353    }
354}
355
356impl<'a> AxisValue<'a> {
357    ///Return the `FontData` used to resolve offsets for this table.
358    pub fn offset_data(&self) -> FontData<'a> {
359        match self {
360            Self::Format1(item) => item.offset_data(),
361            Self::Format2(item) => item.offset_data(),
362            Self::Format3(item) => item.offset_data(),
363            Self::Format4(item) => item.offset_data(),
364        }
365    }
366
367    /// Format identifier — set to 1.
368    pub fn format(&self) -> u16 {
369        match self {
370            Self::Format1(item) => item.format(),
371            Self::Format2(item) => item.format(),
372            Self::Format3(item) => item.format(),
373            Self::Format4(item) => item.format(),
374        }
375    }
376
377    /// Flags — see below for details.
378    pub fn flags(&self) -> AxisValueTableFlags {
379        match self {
380            Self::Format1(item) => item.flags(),
381            Self::Format2(item) => item.flags(),
382            Self::Format3(item) => item.flags(),
383            Self::Format4(item) => item.flags(),
384        }
385    }
386
387    /// The name ID for entries in the 'name' table that provide a
388    /// display string for this attribute value.
389    pub fn value_name_id(&self) -> NameId {
390        match self {
391            Self::Format1(item) => item.value_name_id(),
392            Self::Format2(item) => item.value_name_id(),
393            Self::Format3(item) => item.value_name_id(),
394            Self::Format4(item) => item.value_name_id(),
395        }
396    }
397}
398
399impl ReadArgs for AxisValue<'_> {
400    type Args = ();
401}
402
403impl<'a> FontRead<'a> for AxisValue<'a> {
404    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
405        let format: u16 = data.read_at(0usize)?;
406        match format {
407            AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
408            AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
409            AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
410            AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
411            other => Err(ReadError::InvalidFormat(other.into())),
412        }
413    }
414}
415
416impl<'a> MinByteRange<'a> for AxisValue<'a> {
417    fn min_byte_range(&self) -> Range<usize> {
418        match self {
419            Self::Format1(item) => item.min_byte_range(),
420            Self::Format2(item) => item.min_byte_range(),
421            Self::Format3(item) => item.min_byte_range(),
422            Self::Format4(item) => item.min_byte_range(),
423        }
424    }
425    fn min_table_bytes(&self) -> &'a [u8] {
426        match self {
427            Self::Format1(item) => item.min_table_bytes(),
428            Self::Format2(item) => item.min_table_bytes(),
429            Self::Format3(item) => item.min_table_bytes(),
430            Self::Format4(item) => item.min_table_bytes(),
431        }
432    }
433}
434
435impl Format<u16> for AxisValueFormat1<'_> {
436    const FORMAT: u16 = 1;
437}
438
439impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
440    fn min_byte_range(&self) -> Range<usize> {
441        0..self.value_byte_range().end
442    }
443    fn min_table_bytes(&self) -> &'a [u8] {
444        let range = self.min_byte_range();
445        self.offset_data().as_bytes().get(range).unwrap_or_default()
446    }
447}
448
449impl ReadArgs for AxisValueFormat1<'_> {
450    type Args = ();
451}
452
453impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
454    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
455        #[allow(clippy::absurd_extreme_comparisons)]
456        if data.len() < Self::MIN_SIZE {
457            return Err(ReadError::OutOfBounds);
458        }
459        let Some(data) = TableDataRef::new(data.as_bytes()) else {
460            return Err(ReadError::OutOfBounds);
461        };
462        Ok(Self { data })
463    }
464}
465
466/// The fields at the start of the table, which are read directly.
467#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
468#[repr(C, packed)]
469#[doc(hidden)]
470pub struct AxisValueFormat1FixedHeader {
471    pub format: BigEndian<u16>,
472    pub axis_index: BigEndian<u16>,
473    pub flags: BigEndian<AxisValueTableFlags>,
474    pub value_name_id: BigEndian<NameId>,
475    pub value: BigEndian<Fixed>,
476}
477
478#[allow(clippy::absurd_extreme_comparisons)]
479const _: () =
480    assert!(std::mem::size_of::<AxisValueFormat1FixedHeader>() <= AxisValueFormat1::MIN_SIZE);
481
482/// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1)
483#[derive(Clone)]
484pub struct AxisValueFormat1<'a> {
485    data: TableDataRef<'a, AxisValueFormat1FixedHeader>,
486}
487
488#[allow(clippy::needless_lifetimes)]
489impl<'a> AxisValueFormat1<'a> {
490    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
491        + u16::RAW_BYTE_LEN
492        + AxisValueTableFlags::RAW_BYTE_LEN
493        + NameId::RAW_BYTE_LEN
494        + Fixed::RAW_BYTE_LEN);
495    basic_table_impls!(impl_the_methods);
496
497    /// Format identifier — set to 1.
498    pub fn format(&self) -> u16 {
499        self.data.header().format.get()
500    }
501
502    /// Zero-base index into the axis record array identifying the axis
503    /// of design variation to which the axis value table applies. Must
504    /// be less than designAxisCount.
505    pub fn axis_index(&self) -> u16 {
506        self.data.header().axis_index.get()
507    }
508
509    /// Flags — see below for details.
510    pub fn flags(&self) -> AxisValueTableFlags {
511        self.data.header().flags.get()
512    }
513
514    /// The name ID for entries in the 'name' table that provide a
515    /// display string for this attribute value.
516    pub fn value_name_id(&self) -> NameId {
517        self.data.header().value_name_id.get()
518    }
519
520    /// A numeric value for this attribute value.
521    pub fn value(&self) -> Fixed {
522        self.data.header().value.get()
523    }
524
525    pub fn format_byte_range(&self) -> Range<usize> {
526        let start = 0;
527        let end = start + u16::RAW_BYTE_LEN;
528        start..end
529    }
530
531    pub fn axis_index_byte_range(&self) -> Range<usize> {
532        let start = self.format_byte_range().end;
533        let end = start + u16::RAW_BYTE_LEN;
534        start..end
535    }
536
537    pub fn flags_byte_range(&self) -> Range<usize> {
538        let start = self.axis_index_byte_range().end;
539        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
540        start..end
541    }
542
543    pub fn value_name_id_byte_range(&self) -> Range<usize> {
544        let start = self.flags_byte_range().end;
545        let end = start + NameId::RAW_BYTE_LEN;
546        start..end
547    }
548
549    pub fn value_byte_range(&self) -> Range<usize> {
550        let start = self.value_name_id_byte_range().end;
551        let end = start + Fixed::RAW_BYTE_LEN;
552        start..end
553    }
554}
555
556const _: () = assert!(FontData::default_data_long_enough(
557    AxisValueFormat1::MIN_SIZE
558));
559
560impl Default for AxisValueFormat1<'_> {
561    fn default() -> Self {
562        Self {
563            data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
564                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
565        }
566    }
567}
568
569impl Format<u16> for AxisValueFormat2<'_> {
570    const FORMAT: u16 = 2;
571}
572
573impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
574    fn min_byte_range(&self) -> Range<usize> {
575        0..self.range_max_value_byte_range().end
576    }
577    fn min_table_bytes(&self) -> &'a [u8] {
578        let range = self.min_byte_range();
579        self.offset_data().as_bytes().get(range).unwrap_or_default()
580    }
581}
582
583impl ReadArgs for AxisValueFormat2<'_> {
584    type Args = ();
585}
586
587impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
588    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
589        #[allow(clippy::absurd_extreme_comparisons)]
590        if data.len() < Self::MIN_SIZE {
591            return Err(ReadError::OutOfBounds);
592        }
593        let Some(data) = TableDataRef::new(data.as_bytes()) else {
594            return Err(ReadError::OutOfBounds);
595        };
596        Ok(Self { data })
597    }
598}
599
600/// The fields at the start of the table, which are read directly.
601#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
602#[repr(C, packed)]
603#[doc(hidden)]
604pub struct AxisValueFormat2FixedHeader {
605    pub format: BigEndian<u16>,
606    pub axis_index: BigEndian<u16>,
607    pub flags: BigEndian<AxisValueTableFlags>,
608    pub value_name_id: BigEndian<NameId>,
609    pub nominal_value: BigEndian<Fixed>,
610    pub range_min_value: BigEndian<Fixed>,
611    pub range_max_value: BigEndian<Fixed>,
612}
613
614#[allow(clippy::absurd_extreme_comparisons)]
615const _: () =
616    assert!(std::mem::size_of::<AxisValueFormat2FixedHeader>() <= AxisValueFormat2::MIN_SIZE);
617
618/// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2)
619#[derive(Clone)]
620pub struct AxisValueFormat2<'a> {
621    data: TableDataRef<'a, AxisValueFormat2FixedHeader>,
622}
623
624#[allow(clippy::needless_lifetimes)]
625impl<'a> AxisValueFormat2<'a> {
626    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
627        + u16::RAW_BYTE_LEN
628        + AxisValueTableFlags::RAW_BYTE_LEN
629        + NameId::RAW_BYTE_LEN
630        + Fixed::RAW_BYTE_LEN
631        + Fixed::RAW_BYTE_LEN
632        + Fixed::RAW_BYTE_LEN);
633    basic_table_impls!(impl_the_methods);
634
635    /// Format identifier — set to 2.
636    pub fn format(&self) -> u16 {
637        self.data.header().format.get()
638    }
639
640    /// Zero-base index into the axis record array identifying the axis
641    /// of design variation to which the axis value table applies. Must
642    /// be less than designAxisCount.
643    pub fn axis_index(&self) -> u16 {
644        self.data.header().axis_index.get()
645    }
646
647    /// Flags — see below for details.
648    pub fn flags(&self) -> AxisValueTableFlags {
649        self.data.header().flags.get()
650    }
651
652    /// The name ID for entries in the 'name' table that provide a
653    /// display string for this attribute value.
654    pub fn value_name_id(&self) -> NameId {
655        self.data.header().value_name_id.get()
656    }
657
658    /// A nominal numeric value for this attribute value.
659    pub fn nominal_value(&self) -> Fixed {
660        self.data.header().nominal_value.get()
661    }
662
663    /// The minimum value for a range associated with the specified
664    /// name ID.
665    pub fn range_min_value(&self) -> Fixed {
666        self.data.header().range_min_value.get()
667    }
668
669    /// The maximum value for a range associated with the specified
670    /// name ID.
671    pub fn range_max_value(&self) -> Fixed {
672        self.data.header().range_max_value.get()
673    }
674
675    pub fn format_byte_range(&self) -> Range<usize> {
676        let start = 0;
677        let end = start + u16::RAW_BYTE_LEN;
678        start..end
679    }
680
681    pub fn axis_index_byte_range(&self) -> Range<usize> {
682        let start = self.format_byte_range().end;
683        let end = start + u16::RAW_BYTE_LEN;
684        start..end
685    }
686
687    pub fn flags_byte_range(&self) -> Range<usize> {
688        let start = self.axis_index_byte_range().end;
689        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
690        start..end
691    }
692
693    pub fn value_name_id_byte_range(&self) -> Range<usize> {
694        let start = self.flags_byte_range().end;
695        let end = start + NameId::RAW_BYTE_LEN;
696        start..end
697    }
698
699    pub fn nominal_value_byte_range(&self) -> Range<usize> {
700        let start = self.value_name_id_byte_range().end;
701        let end = start + Fixed::RAW_BYTE_LEN;
702        start..end
703    }
704
705    pub fn range_min_value_byte_range(&self) -> Range<usize> {
706        let start = self.nominal_value_byte_range().end;
707        let end = start + Fixed::RAW_BYTE_LEN;
708        start..end
709    }
710
711    pub fn range_max_value_byte_range(&self) -> Range<usize> {
712        let start = self.range_min_value_byte_range().end;
713        let end = start + Fixed::RAW_BYTE_LEN;
714        start..end
715    }
716}
717
718impl Format<u16> for AxisValueFormat3<'_> {
719    const FORMAT: u16 = 3;
720}
721
722impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
723    fn min_byte_range(&self) -> Range<usize> {
724        0..self.linked_value_byte_range().end
725    }
726    fn min_table_bytes(&self) -> &'a [u8] {
727        let range = self.min_byte_range();
728        self.offset_data().as_bytes().get(range).unwrap_or_default()
729    }
730}
731
732impl ReadArgs for AxisValueFormat3<'_> {
733    type Args = ();
734}
735
736impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
737    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
738        #[allow(clippy::absurd_extreme_comparisons)]
739        if data.len() < Self::MIN_SIZE {
740            return Err(ReadError::OutOfBounds);
741        }
742        let Some(data) = TableDataRef::new(data.as_bytes()) else {
743            return Err(ReadError::OutOfBounds);
744        };
745        Ok(Self { data })
746    }
747}
748
749/// The fields at the start of the table, which are read directly.
750#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
751#[repr(C, packed)]
752#[doc(hidden)]
753pub struct AxisValueFormat3FixedHeader {
754    pub format: BigEndian<u16>,
755    pub axis_index: BigEndian<u16>,
756    pub flags: BigEndian<AxisValueTableFlags>,
757    pub value_name_id: BigEndian<NameId>,
758    pub value: BigEndian<Fixed>,
759    pub linked_value: BigEndian<Fixed>,
760}
761
762#[allow(clippy::absurd_extreme_comparisons)]
763const _: () =
764    assert!(std::mem::size_of::<AxisValueFormat3FixedHeader>() <= AxisValueFormat3::MIN_SIZE);
765
766/// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3)
767#[derive(Clone)]
768pub struct AxisValueFormat3<'a> {
769    data: TableDataRef<'a, AxisValueFormat3FixedHeader>,
770}
771
772#[allow(clippy::needless_lifetimes)]
773impl<'a> AxisValueFormat3<'a> {
774    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
775        + u16::RAW_BYTE_LEN
776        + AxisValueTableFlags::RAW_BYTE_LEN
777        + NameId::RAW_BYTE_LEN
778        + Fixed::RAW_BYTE_LEN
779        + Fixed::RAW_BYTE_LEN);
780    basic_table_impls!(impl_the_methods);
781
782    /// Format identifier — set to 3.
783    pub fn format(&self) -> u16 {
784        self.data.header().format.get()
785    }
786
787    /// Zero-base index into the axis record array identifying the axis
788    /// of design variation to which the axis value table applies. Must
789    /// be less than designAxisCount.
790    pub fn axis_index(&self) -> u16 {
791        self.data.header().axis_index.get()
792    }
793
794    /// Flags — see below for details.
795    pub fn flags(&self) -> AxisValueTableFlags {
796        self.data.header().flags.get()
797    }
798
799    /// The name ID for entries in the 'name' table that provide a
800    /// display string for this attribute value.
801    pub fn value_name_id(&self) -> NameId {
802        self.data.header().value_name_id.get()
803    }
804
805    /// A numeric value for this attribute value.
806    pub fn value(&self) -> Fixed {
807        self.data.header().value.get()
808    }
809
810    /// The numeric value for a style-linked mapping from this value.
811    pub fn linked_value(&self) -> Fixed {
812        self.data.header().linked_value.get()
813    }
814
815    pub fn format_byte_range(&self) -> Range<usize> {
816        let start = 0;
817        let end = start + u16::RAW_BYTE_LEN;
818        start..end
819    }
820
821    pub fn axis_index_byte_range(&self) -> Range<usize> {
822        let start = self.format_byte_range().end;
823        let end = start + u16::RAW_BYTE_LEN;
824        start..end
825    }
826
827    pub fn flags_byte_range(&self) -> Range<usize> {
828        let start = self.axis_index_byte_range().end;
829        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
830        start..end
831    }
832
833    pub fn value_name_id_byte_range(&self) -> Range<usize> {
834        let start = self.flags_byte_range().end;
835        let end = start + NameId::RAW_BYTE_LEN;
836        start..end
837    }
838
839    pub fn value_byte_range(&self) -> Range<usize> {
840        let start = self.value_name_id_byte_range().end;
841        let end = start + Fixed::RAW_BYTE_LEN;
842        start..end
843    }
844
845    pub fn linked_value_byte_range(&self) -> Range<usize> {
846        let start = self.value_byte_range().end;
847        let end = start + Fixed::RAW_BYTE_LEN;
848        start..end
849    }
850}
851
852impl Format<u16> for AxisValueFormat4<'_> {
853    const FORMAT: u16 = 4;
854}
855
856impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
857    fn min_byte_range(&self) -> Range<usize> {
858        0..self.axis_values_byte_range().end
859    }
860    fn min_table_bytes(&self) -> &'a [u8] {
861        let range = self.min_byte_range();
862        self.offset_data().as_bytes().get(range).unwrap_or_default()
863    }
864}
865
866impl ReadArgs for AxisValueFormat4<'_> {
867    type Args = ();
868}
869
870impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
871    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
872        #[allow(clippy::absurd_extreme_comparisons)]
873        if data.len() < Self::MIN_SIZE {
874            return Err(ReadError::OutOfBounds);
875        }
876        let Some(data) = TableDataRef::new(data.as_bytes()) else {
877            return Err(ReadError::OutOfBounds);
878        };
879        Ok(Self { data })
880    }
881}
882
883/// The fields at the start of the table, which are read directly.
884#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
885#[repr(C, packed)]
886#[doc(hidden)]
887pub struct AxisValueFormat4FixedHeader {
888    pub format: BigEndian<u16>,
889    pub axis_count: BigEndian<u16>,
890    pub flags: BigEndian<AxisValueTableFlags>,
891    pub value_name_id: BigEndian<NameId>,
892}
893
894#[allow(clippy::absurd_extreme_comparisons)]
895const _: () =
896    assert!(std::mem::size_of::<AxisValueFormat4FixedHeader>() <= AxisValueFormat4::MIN_SIZE);
897
898/// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4)
899#[derive(Clone)]
900pub struct AxisValueFormat4<'a> {
901    data: TableDataRef<'a, AxisValueFormat4FixedHeader>,
902}
903
904#[allow(clippy::needless_lifetimes)]
905impl<'a> AxisValueFormat4<'a> {
906    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
907        + u16::RAW_BYTE_LEN
908        + AxisValueTableFlags::RAW_BYTE_LEN
909        + NameId::RAW_BYTE_LEN);
910    basic_table_impls!(impl_the_methods);
911
912    /// Format identifier — set to 4.
913    pub fn format(&self) -> u16 {
914        self.data.header().format.get()
915    }
916
917    /// The total number of axes contributing to this axis-values
918    /// combination.
919    pub fn axis_count(&self) -> u16 {
920        self.data.header().axis_count.get()
921    }
922
923    /// Flags — see below for details.
924    pub fn flags(&self) -> AxisValueTableFlags {
925        self.data.header().flags.get()
926    }
927
928    /// The name ID for entries in the 'name' table that provide a
929    /// display string for this combination of axis values.
930    pub fn value_name_id(&self) -> NameId {
931        self.data.header().value_name_id.get()
932    }
933
934    /// Array of AxisValue records that provide the combination of axis
935    /// values, one for each contributing axis.
936    pub fn axis_values(&self) -> &'a [AxisValueRecord] {
937        let range = self.axis_values_byte_range();
938        self.offset_data()
939            .read_array(range)
940            .ok()
941            .unwrap_or_default()
942    }
943
944    pub fn format_byte_range(&self) -> Range<usize> {
945        let start = 0;
946        let end = start + u16::RAW_BYTE_LEN;
947        start..end
948    }
949
950    pub fn axis_count_byte_range(&self) -> Range<usize> {
951        let start = self.format_byte_range().end;
952        let end = start + u16::RAW_BYTE_LEN;
953        start..end
954    }
955
956    pub fn flags_byte_range(&self) -> Range<usize> {
957        let start = self.axis_count_byte_range().end;
958        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
959        start..end
960    }
961
962    pub fn value_name_id_byte_range(&self) -> Range<usize> {
963        let start = self.flags_byte_range().end;
964        let end = start + NameId::RAW_BYTE_LEN;
965        start..end
966    }
967
968    pub fn axis_values_byte_range(&self) -> Range<usize> {
969        let axis_count = self.axis_count();
970        let start = self.value_name_id_byte_range().end;
971        let end = start
972            + (transforms::to_usize(axis_count)).saturating_mul(AxisValueRecord::RAW_BYTE_LEN);
973        start..end
974    }
975}
976
977/// Part of [AxisValueFormat4]
978#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
979#[repr(C)]
980#[repr(packed)]
981pub struct AxisValueRecord {
982    /// Zero-base index into the axis record array identifying the axis
983    /// to which this value applies. Must be less than designAxisCount.
984    pub axis_index: BigEndian<u16>,
985    /// A numeric value for this attribute value.
986    pub value: BigEndian<Fixed>,
987}
988
989impl AxisValueRecord {
990    /// Zero-base index into the axis record array identifying the axis
991    /// to which this value applies. Must be less than designAxisCount.
992    pub fn axis_index(&self) -> u16 {
993        self.axis_index.get()
994    }
995
996    /// A numeric value for this attribute value.
997    pub fn value(&self) -> Fixed {
998        self.value.get()
999    }
1000}
1001
1002impl FixedSize for AxisValueRecord {
1003    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1004}
1005
1006/// [Axis value table flags](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#flags).
1007#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1008#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1009#[repr(transparent)]
1010pub struct AxisValueTableFlags {
1011    bits: u16,
1012}
1013
1014impl AxisValueTableFlags {
1015    /// If set, this axis value table provides axis value information
1016    /// that is applicable to other fonts within the same font family.
1017    /// This is used if the other fonts were released earlier and did
1018    /// not include information about values for some axis. If newer
1019    /// versions of the other fonts include the information themselves
1020    /// and are present, then this table is ignored.
1021    pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1022
1023    /// If set, it indicates that the axis value represents the
1024    /// “normal” value for the axis and may be omitted when
1025    /// composing name strings.
1026    pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1027}
1028
1029impl AxisValueTableFlags {
1030    ///  Returns an empty set of flags.
1031    #[inline]
1032    pub const fn empty() -> Self {
1033        Self { bits: 0 }
1034    }
1035
1036    /// Returns the set containing all flags.
1037    #[inline]
1038    pub const fn all() -> Self {
1039        Self {
1040            bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1041        }
1042    }
1043
1044    /// Returns the raw value of the flags currently stored.
1045    #[inline]
1046    pub const fn bits(&self) -> u16 {
1047        self.bits
1048    }
1049
1050    /// Convert from underlying bit representation, unless that
1051    /// representation contains bits that do not correspond to a flag.
1052    #[inline]
1053    pub const fn from_bits(bits: u16) -> Option<Self> {
1054        if (bits & !Self::all().bits()) == 0 {
1055            Some(Self { bits })
1056        } else {
1057            None
1058        }
1059    }
1060
1061    /// Convert from underlying bit representation, dropping any bits
1062    /// that do not correspond to flags.
1063    #[inline]
1064    pub const fn from_bits_truncate(bits: u16) -> Self {
1065        Self {
1066            bits: bits & Self::all().bits,
1067        }
1068    }
1069
1070    /// Returns `true` if no flags are currently stored.
1071    #[inline]
1072    pub const fn is_empty(&self) -> bool {
1073        self.bits() == Self::empty().bits()
1074    }
1075
1076    /// Returns `true` if there are flags common to both `self` and `other`.
1077    #[inline]
1078    pub const fn intersects(&self, other: Self) -> bool {
1079        !(Self {
1080            bits: self.bits & other.bits,
1081        })
1082        .is_empty()
1083    }
1084
1085    /// Returns `true` if all of the flags in `other` are contained within `self`.
1086    #[inline]
1087    pub const fn contains(&self, other: Self) -> bool {
1088        (self.bits & other.bits) == other.bits
1089    }
1090
1091    /// Inserts the specified flags in-place.
1092    #[inline]
1093    pub fn insert(&mut self, other: Self) {
1094        self.bits |= other.bits;
1095    }
1096
1097    /// Removes the specified flags in-place.
1098    #[inline]
1099    pub fn remove(&mut self, other: Self) {
1100        self.bits &= !other.bits;
1101    }
1102
1103    /// Toggles the specified flags in-place.
1104    #[inline]
1105    pub fn toggle(&mut self, other: Self) {
1106        self.bits ^= other.bits;
1107    }
1108
1109    /// Returns the intersection between the flags in `self` and
1110    /// `other`.
1111    ///
1112    /// Specifically, the returned set contains only the flags which are
1113    /// present in *both* `self` *and* `other`.
1114    ///
1115    /// This is equivalent to using the `&` operator (e.g.
1116    /// [`ops::BitAnd`]), as in `flags & other`.
1117    ///
1118    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
1119    #[inline]
1120    #[must_use]
1121    pub const fn intersection(self, other: Self) -> Self {
1122        Self {
1123            bits: self.bits & other.bits,
1124        }
1125    }
1126
1127    /// Returns the union of between the flags in `self` and `other`.
1128    ///
1129    /// Specifically, the returned set contains all flags which are
1130    /// present in *either* `self` *or* `other`, including any which are
1131    /// present in both.
1132    ///
1133    /// This is equivalent to using the `|` operator (e.g.
1134    /// [`ops::BitOr`]), as in `flags | other`.
1135    ///
1136    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
1137    #[inline]
1138    #[must_use]
1139    pub const fn union(self, other: Self) -> Self {
1140        Self {
1141            bits: self.bits | other.bits,
1142        }
1143    }
1144
1145    /// Returns the difference between the flags in `self` and `other`.
1146    ///
1147    /// Specifically, the returned set contains all flags present in
1148    /// `self`, except for the ones present in `other`.
1149    ///
1150    /// It is also conceptually equivalent to the "bit-clear" operation:
1151    /// `flags & !other` (and this syntax is also supported).
1152    ///
1153    /// This is equivalent to using the `-` operator (e.g.
1154    /// [`ops::Sub`]), as in `flags - other`.
1155    ///
1156    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
1157    #[inline]
1158    #[must_use]
1159    pub const fn difference(self, other: Self) -> Self {
1160        Self {
1161            bits: self.bits & !other.bits,
1162        }
1163    }
1164}
1165
1166impl std::ops::BitOr for AxisValueTableFlags {
1167    type Output = Self;
1168
1169    /// Returns the union of the two sets of flags.
1170    #[inline]
1171    fn bitor(self, other: AxisValueTableFlags) -> Self {
1172        Self {
1173            bits: self.bits | other.bits,
1174        }
1175    }
1176}
1177
1178impl std::ops::BitOrAssign for AxisValueTableFlags {
1179    /// Adds the set of flags.
1180    #[inline]
1181    fn bitor_assign(&mut self, other: Self) {
1182        self.bits |= other.bits;
1183    }
1184}
1185
1186impl std::ops::BitXor for AxisValueTableFlags {
1187    type Output = Self;
1188
1189    /// Returns the left flags, but with all the right flags toggled.
1190    #[inline]
1191    fn bitxor(self, other: Self) -> Self {
1192        Self {
1193            bits: self.bits ^ other.bits,
1194        }
1195    }
1196}
1197
1198impl std::ops::BitXorAssign for AxisValueTableFlags {
1199    /// Toggles the set of flags.
1200    #[inline]
1201    fn bitxor_assign(&mut self, other: Self) {
1202        self.bits ^= other.bits;
1203    }
1204}
1205
1206impl std::ops::BitAnd for AxisValueTableFlags {
1207    type Output = Self;
1208
1209    /// Returns the intersection between the two sets of flags.
1210    #[inline]
1211    fn bitand(self, other: Self) -> Self {
1212        Self {
1213            bits: self.bits & other.bits,
1214        }
1215    }
1216}
1217
1218impl std::ops::BitAndAssign for AxisValueTableFlags {
1219    /// Disables all flags disabled in the set.
1220    #[inline]
1221    fn bitand_assign(&mut self, other: Self) {
1222        self.bits &= other.bits;
1223    }
1224}
1225
1226impl std::ops::Sub for AxisValueTableFlags {
1227    type Output = Self;
1228
1229    /// Returns the set difference of the two sets of flags.
1230    #[inline]
1231    fn sub(self, other: Self) -> Self {
1232        Self {
1233            bits: self.bits & !other.bits,
1234        }
1235    }
1236}
1237
1238impl std::ops::SubAssign for AxisValueTableFlags {
1239    /// Disables all flags enabled in the set.
1240    #[inline]
1241    fn sub_assign(&mut self, other: Self) {
1242        self.bits &= !other.bits;
1243    }
1244}
1245
1246impl std::ops::Not for AxisValueTableFlags {
1247    type Output = Self;
1248
1249    /// Returns the complement of this set of flags.
1250    #[inline]
1251    fn not(self) -> Self {
1252        Self { bits: !self.bits } & Self::all()
1253    }
1254}
1255
1256impl std::fmt::Debug for AxisValueTableFlags {
1257    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1258        let members: &[(&str, Self)] = &[
1259            (
1260                "OLDER_SIBLING_FONT_ATTRIBUTE",
1261                Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1262            ),
1263            ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1264        ];
1265        let mut first = true;
1266        for (name, value) in members {
1267            if self.contains(*value) {
1268                if !first {
1269                    f.write_str(" | ")?;
1270                }
1271                first = false;
1272                f.write_str(name)?;
1273            }
1274        }
1275        if first {
1276            f.write_str("(empty)")?;
1277        }
1278        Ok(())
1279    }
1280}
1281
1282impl std::fmt::Binary for AxisValueTableFlags {
1283    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1284        std::fmt::Binary::fmt(&self.bits, f)
1285    }
1286}
1287
1288impl std::fmt::Octal for AxisValueTableFlags {
1289    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1290        std::fmt::Octal::fmt(&self.bits, f)
1291    }
1292}
1293
1294impl std::fmt::LowerHex for AxisValueTableFlags {
1295    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1296        std::fmt::LowerHex::fmt(&self.bits, f)
1297    }
1298}
1299
1300impl std::fmt::UpperHex for AxisValueTableFlags {
1301    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1302        std::fmt::UpperHex::fmt(&self.bits, f)
1303    }
1304}
1305
1306impl font_types::Scalar for AxisValueTableFlags {
1307    type Raw = <u16 as font_types::Scalar>::Raw;
1308    fn to_raw(self) -> Self::Raw {
1309        self.bits().to_raw()
1310    }
1311    fn from_raw(raw: Self::Raw) -> Self {
1312        let t = <u16>::from_raw(raw);
1313        Self::from_bits_truncate(t)
1314    }
1315}