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    #[inline]
405    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
406        let format: u16 = data.read_at(0usize)?;
407        match format {
408            AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
409            AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
410            AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
411            AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
412            other => Err(ReadError::InvalidFormat(other.into())),
413        }
414    }
415}
416
417impl<'a> MinByteRange<'a> for AxisValue<'a> {
418    fn min_byte_range(&self) -> Range<usize> {
419        match self {
420            Self::Format1(item) => item.min_byte_range(),
421            Self::Format2(item) => item.min_byte_range(),
422            Self::Format3(item) => item.min_byte_range(),
423            Self::Format4(item) => item.min_byte_range(),
424        }
425    }
426    fn min_table_bytes(&self) -> &'a [u8] {
427        match self {
428            Self::Format1(item) => item.min_table_bytes(),
429            Self::Format2(item) => item.min_table_bytes(),
430            Self::Format3(item) => item.min_table_bytes(),
431            Self::Format4(item) => item.min_table_bytes(),
432        }
433    }
434}
435
436impl Format<u16> for AxisValueFormat1<'_> {
437    const FORMAT: u16 = 1;
438}
439
440impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
441    fn min_byte_range(&self) -> Range<usize> {
442        0..self.value_byte_range().end
443    }
444    fn min_table_bytes(&self) -> &'a [u8] {
445        let range = self.min_byte_range();
446        self.offset_data().as_bytes().get(range).unwrap_or_default()
447    }
448}
449
450impl ReadArgs for AxisValueFormat1<'_> {
451    type Args = ();
452}
453
454impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
455    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
456        #[allow(clippy::absurd_extreme_comparisons)]
457        if data.len() < Self::MIN_SIZE {
458            return Err(ReadError::OutOfBounds);
459        }
460        let Some(data) = TableDataRef::new(data.as_bytes()) else {
461            return Err(ReadError::OutOfBounds);
462        };
463        Ok(Self { data })
464    }
465}
466
467/// The fields at the start of the table, which are read directly.
468#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
469#[repr(C, packed)]
470#[doc(hidden)]
471pub struct AxisValueFormat1FixedHeader {
472    pub format: BigEndian<u16>,
473    pub axis_index: BigEndian<u16>,
474    pub flags: BigEndian<AxisValueTableFlags>,
475    pub value_name_id: BigEndian<NameId>,
476    pub value: BigEndian<Fixed>,
477}
478
479#[allow(clippy::absurd_extreme_comparisons)]
480const _: () =
481    assert!(std::mem::size_of::<AxisValueFormat1FixedHeader>() <= AxisValueFormat1::MIN_SIZE);
482
483/// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1)
484#[derive(Clone)]
485pub struct AxisValueFormat1<'a> {
486    data: TableDataRef<'a, AxisValueFormat1FixedHeader>,
487}
488
489#[allow(clippy::needless_lifetimes)]
490impl<'a> AxisValueFormat1<'a> {
491    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
492        + u16::RAW_BYTE_LEN
493        + AxisValueTableFlags::RAW_BYTE_LEN
494        + NameId::RAW_BYTE_LEN
495        + Fixed::RAW_BYTE_LEN);
496    basic_table_impls!(impl_the_methods);
497
498    /// Format identifier — set to 1.
499    pub fn format(&self) -> u16 {
500        self.data.header().format.get()
501    }
502
503    /// Zero-base index into the axis record array identifying the axis
504    /// of design variation to which the axis value table applies. Must
505    /// be less than designAxisCount.
506    pub fn axis_index(&self) -> u16 {
507        self.data.header().axis_index.get()
508    }
509
510    /// Flags — see below for details.
511    pub fn flags(&self) -> AxisValueTableFlags {
512        self.data.header().flags.get()
513    }
514
515    /// The name ID for entries in the 'name' table that provide a
516    /// display string for this attribute value.
517    pub fn value_name_id(&self) -> NameId {
518        self.data.header().value_name_id.get()
519    }
520
521    /// A numeric value for this attribute value.
522    pub fn value(&self) -> Fixed {
523        self.data.header().value.get()
524    }
525
526    pub fn format_byte_range(&self) -> Range<usize> {
527        let start = 0;
528        let end = start + u16::RAW_BYTE_LEN;
529        start..end
530    }
531
532    pub fn axis_index_byte_range(&self) -> Range<usize> {
533        let start = self.format_byte_range().end;
534        let end = start + u16::RAW_BYTE_LEN;
535        start..end
536    }
537
538    pub fn flags_byte_range(&self) -> Range<usize> {
539        let start = self.axis_index_byte_range().end;
540        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
541        start..end
542    }
543
544    pub fn value_name_id_byte_range(&self) -> Range<usize> {
545        let start = self.flags_byte_range().end;
546        let end = start + NameId::RAW_BYTE_LEN;
547        start..end
548    }
549
550    pub fn value_byte_range(&self) -> Range<usize> {
551        let start = self.value_name_id_byte_range().end;
552        let end = start + Fixed::RAW_BYTE_LEN;
553        start..end
554    }
555}
556
557const _: () = assert!(FontData::default_data_long_enough(
558    AxisValueFormat1::MIN_SIZE
559));
560
561impl Default for AxisValueFormat1<'_> {
562    fn default() -> Self {
563        Self {
564            data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
565                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
566        }
567    }
568}
569
570impl Format<u16> for AxisValueFormat2<'_> {
571    const FORMAT: u16 = 2;
572}
573
574impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
575    fn min_byte_range(&self) -> Range<usize> {
576        0..self.range_max_value_byte_range().end
577    }
578    fn min_table_bytes(&self) -> &'a [u8] {
579        let range = self.min_byte_range();
580        self.offset_data().as_bytes().get(range).unwrap_or_default()
581    }
582}
583
584impl ReadArgs for AxisValueFormat2<'_> {
585    type Args = ();
586}
587
588impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
589    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
590        #[allow(clippy::absurd_extreme_comparisons)]
591        if data.len() < Self::MIN_SIZE {
592            return Err(ReadError::OutOfBounds);
593        }
594        let Some(data) = TableDataRef::new(data.as_bytes()) else {
595            return Err(ReadError::OutOfBounds);
596        };
597        Ok(Self { data })
598    }
599}
600
601/// The fields at the start of the table, which are read directly.
602#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
603#[repr(C, packed)]
604#[doc(hidden)]
605pub struct AxisValueFormat2FixedHeader {
606    pub format: BigEndian<u16>,
607    pub axis_index: BigEndian<u16>,
608    pub flags: BigEndian<AxisValueTableFlags>,
609    pub value_name_id: BigEndian<NameId>,
610    pub nominal_value: BigEndian<Fixed>,
611    pub range_min_value: BigEndian<Fixed>,
612    pub range_max_value: BigEndian<Fixed>,
613}
614
615#[allow(clippy::absurd_extreme_comparisons)]
616const _: () =
617    assert!(std::mem::size_of::<AxisValueFormat2FixedHeader>() <= AxisValueFormat2::MIN_SIZE);
618
619/// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2)
620#[derive(Clone)]
621pub struct AxisValueFormat2<'a> {
622    data: TableDataRef<'a, AxisValueFormat2FixedHeader>,
623}
624
625#[allow(clippy::needless_lifetimes)]
626impl<'a> AxisValueFormat2<'a> {
627    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
628        + u16::RAW_BYTE_LEN
629        + AxisValueTableFlags::RAW_BYTE_LEN
630        + NameId::RAW_BYTE_LEN
631        + Fixed::RAW_BYTE_LEN
632        + Fixed::RAW_BYTE_LEN
633        + Fixed::RAW_BYTE_LEN);
634    basic_table_impls!(impl_the_methods);
635
636    /// Format identifier — set to 2.
637    pub fn format(&self) -> u16 {
638        self.data.header().format.get()
639    }
640
641    /// Zero-base index into the axis record array identifying the axis
642    /// of design variation to which the axis value table applies. Must
643    /// be less than designAxisCount.
644    pub fn axis_index(&self) -> u16 {
645        self.data.header().axis_index.get()
646    }
647
648    /// Flags — see below for details.
649    pub fn flags(&self) -> AxisValueTableFlags {
650        self.data.header().flags.get()
651    }
652
653    /// The name ID for entries in the 'name' table that provide a
654    /// display string for this attribute value.
655    pub fn value_name_id(&self) -> NameId {
656        self.data.header().value_name_id.get()
657    }
658
659    /// A nominal numeric value for this attribute value.
660    pub fn nominal_value(&self) -> Fixed {
661        self.data.header().nominal_value.get()
662    }
663
664    /// The minimum value for a range associated with the specified
665    /// name ID.
666    pub fn range_min_value(&self) -> Fixed {
667        self.data.header().range_min_value.get()
668    }
669
670    /// The maximum value for a range associated with the specified
671    /// name ID.
672    pub fn range_max_value(&self) -> Fixed {
673        self.data.header().range_max_value.get()
674    }
675
676    pub fn format_byte_range(&self) -> Range<usize> {
677        let start = 0;
678        let end = start + u16::RAW_BYTE_LEN;
679        start..end
680    }
681
682    pub fn axis_index_byte_range(&self) -> Range<usize> {
683        let start = self.format_byte_range().end;
684        let end = start + u16::RAW_BYTE_LEN;
685        start..end
686    }
687
688    pub fn flags_byte_range(&self) -> Range<usize> {
689        let start = self.axis_index_byte_range().end;
690        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
691        start..end
692    }
693
694    pub fn value_name_id_byte_range(&self) -> Range<usize> {
695        let start = self.flags_byte_range().end;
696        let end = start + NameId::RAW_BYTE_LEN;
697        start..end
698    }
699
700    pub fn nominal_value_byte_range(&self) -> Range<usize> {
701        let start = self.value_name_id_byte_range().end;
702        let end = start + Fixed::RAW_BYTE_LEN;
703        start..end
704    }
705
706    pub fn range_min_value_byte_range(&self) -> Range<usize> {
707        let start = self.nominal_value_byte_range().end;
708        let end = start + Fixed::RAW_BYTE_LEN;
709        start..end
710    }
711
712    pub fn range_max_value_byte_range(&self) -> Range<usize> {
713        let start = self.range_min_value_byte_range().end;
714        let end = start + Fixed::RAW_BYTE_LEN;
715        start..end
716    }
717}
718
719impl Format<u16> for AxisValueFormat3<'_> {
720    const FORMAT: u16 = 3;
721}
722
723impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
724    fn min_byte_range(&self) -> Range<usize> {
725        0..self.linked_value_byte_range().end
726    }
727    fn min_table_bytes(&self) -> &'a [u8] {
728        let range = self.min_byte_range();
729        self.offset_data().as_bytes().get(range).unwrap_or_default()
730    }
731}
732
733impl ReadArgs for AxisValueFormat3<'_> {
734    type Args = ();
735}
736
737impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
738    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
739        #[allow(clippy::absurd_extreme_comparisons)]
740        if data.len() < Self::MIN_SIZE {
741            return Err(ReadError::OutOfBounds);
742        }
743        let Some(data) = TableDataRef::new(data.as_bytes()) else {
744            return Err(ReadError::OutOfBounds);
745        };
746        Ok(Self { data })
747    }
748}
749
750/// The fields at the start of the table, which are read directly.
751#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
752#[repr(C, packed)]
753#[doc(hidden)]
754pub struct AxisValueFormat3FixedHeader {
755    pub format: BigEndian<u16>,
756    pub axis_index: BigEndian<u16>,
757    pub flags: BigEndian<AxisValueTableFlags>,
758    pub value_name_id: BigEndian<NameId>,
759    pub value: BigEndian<Fixed>,
760    pub linked_value: BigEndian<Fixed>,
761}
762
763#[allow(clippy::absurd_extreme_comparisons)]
764const _: () =
765    assert!(std::mem::size_of::<AxisValueFormat3FixedHeader>() <= AxisValueFormat3::MIN_SIZE);
766
767/// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3)
768#[derive(Clone)]
769pub struct AxisValueFormat3<'a> {
770    data: TableDataRef<'a, AxisValueFormat3FixedHeader>,
771}
772
773#[allow(clippy::needless_lifetimes)]
774impl<'a> AxisValueFormat3<'a> {
775    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
776        + u16::RAW_BYTE_LEN
777        + AxisValueTableFlags::RAW_BYTE_LEN
778        + NameId::RAW_BYTE_LEN
779        + Fixed::RAW_BYTE_LEN
780        + Fixed::RAW_BYTE_LEN);
781    basic_table_impls!(impl_the_methods);
782
783    /// Format identifier — set to 3.
784    pub fn format(&self) -> u16 {
785        self.data.header().format.get()
786    }
787
788    /// Zero-base index into the axis record array identifying the axis
789    /// of design variation to which the axis value table applies. Must
790    /// be less than designAxisCount.
791    pub fn axis_index(&self) -> u16 {
792        self.data.header().axis_index.get()
793    }
794
795    /// Flags — see below for details.
796    pub fn flags(&self) -> AxisValueTableFlags {
797        self.data.header().flags.get()
798    }
799
800    /// The name ID for entries in the 'name' table that provide a
801    /// display string for this attribute value.
802    pub fn value_name_id(&self) -> NameId {
803        self.data.header().value_name_id.get()
804    }
805
806    /// A numeric value for this attribute value.
807    pub fn value(&self) -> Fixed {
808        self.data.header().value.get()
809    }
810
811    /// The numeric value for a style-linked mapping from this value.
812    pub fn linked_value(&self) -> Fixed {
813        self.data.header().linked_value.get()
814    }
815
816    pub fn format_byte_range(&self) -> Range<usize> {
817        let start = 0;
818        let end = start + u16::RAW_BYTE_LEN;
819        start..end
820    }
821
822    pub fn axis_index_byte_range(&self) -> Range<usize> {
823        let start = self.format_byte_range().end;
824        let end = start + u16::RAW_BYTE_LEN;
825        start..end
826    }
827
828    pub fn flags_byte_range(&self) -> Range<usize> {
829        let start = self.axis_index_byte_range().end;
830        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
831        start..end
832    }
833
834    pub fn value_name_id_byte_range(&self) -> Range<usize> {
835        let start = self.flags_byte_range().end;
836        let end = start + NameId::RAW_BYTE_LEN;
837        start..end
838    }
839
840    pub fn value_byte_range(&self) -> Range<usize> {
841        let start = self.value_name_id_byte_range().end;
842        let end = start + Fixed::RAW_BYTE_LEN;
843        start..end
844    }
845
846    pub fn linked_value_byte_range(&self) -> Range<usize> {
847        let start = self.value_byte_range().end;
848        let end = start + Fixed::RAW_BYTE_LEN;
849        start..end
850    }
851}
852
853impl Format<u16> for AxisValueFormat4<'_> {
854    const FORMAT: u16 = 4;
855}
856
857impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
858    fn min_byte_range(&self) -> Range<usize> {
859        0..self.axis_values_byte_range().end
860    }
861    fn min_table_bytes(&self) -> &'a [u8] {
862        let range = self.min_byte_range();
863        self.offset_data().as_bytes().get(range).unwrap_or_default()
864    }
865}
866
867impl ReadArgs for AxisValueFormat4<'_> {
868    type Args = ();
869}
870
871impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
872    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
873        #[allow(clippy::absurd_extreme_comparisons)]
874        if data.len() < Self::MIN_SIZE {
875            return Err(ReadError::OutOfBounds);
876        }
877        let Some(data) = TableDataRef::new(data.as_bytes()) else {
878            return Err(ReadError::OutOfBounds);
879        };
880        Ok(Self { data })
881    }
882}
883
884/// The fields at the start of the table, which are read directly.
885#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
886#[repr(C, packed)]
887#[doc(hidden)]
888pub struct AxisValueFormat4FixedHeader {
889    pub format: BigEndian<u16>,
890    pub axis_count: BigEndian<u16>,
891    pub flags: BigEndian<AxisValueTableFlags>,
892    pub value_name_id: BigEndian<NameId>,
893}
894
895#[allow(clippy::absurd_extreme_comparisons)]
896const _: () =
897    assert!(std::mem::size_of::<AxisValueFormat4FixedHeader>() <= AxisValueFormat4::MIN_SIZE);
898
899/// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4)
900#[derive(Clone)]
901pub struct AxisValueFormat4<'a> {
902    data: TableDataRef<'a, AxisValueFormat4FixedHeader>,
903}
904
905#[allow(clippy::needless_lifetimes)]
906impl<'a> AxisValueFormat4<'a> {
907    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
908        + u16::RAW_BYTE_LEN
909        + AxisValueTableFlags::RAW_BYTE_LEN
910        + NameId::RAW_BYTE_LEN);
911    basic_table_impls!(impl_the_methods);
912
913    /// Format identifier — set to 4.
914    pub fn format(&self) -> u16 {
915        self.data.header().format.get()
916    }
917
918    /// The total number of axes contributing to this axis-values
919    /// combination.
920    pub fn axis_count(&self) -> u16 {
921        self.data.header().axis_count.get()
922    }
923
924    /// Flags — see below for details.
925    pub fn flags(&self) -> AxisValueTableFlags {
926        self.data.header().flags.get()
927    }
928
929    /// The name ID for entries in the 'name' table that provide a
930    /// display string for this combination of axis values.
931    pub fn value_name_id(&self) -> NameId {
932        self.data.header().value_name_id.get()
933    }
934
935    /// Array of AxisValue records that provide the combination of axis
936    /// values, one for each contributing axis.
937    pub fn axis_values(&self) -> &'a [AxisValueRecord] {
938        let range = self.axis_values_byte_range();
939        self.offset_data()
940            .read_array(range)
941            .ok()
942            .unwrap_or_default()
943    }
944
945    pub fn format_byte_range(&self) -> Range<usize> {
946        let start = 0;
947        let end = start + u16::RAW_BYTE_LEN;
948        start..end
949    }
950
951    pub fn axis_count_byte_range(&self) -> Range<usize> {
952        let start = self.format_byte_range().end;
953        let end = start + u16::RAW_BYTE_LEN;
954        start..end
955    }
956
957    pub fn flags_byte_range(&self) -> Range<usize> {
958        let start = self.axis_count_byte_range().end;
959        let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
960        start..end
961    }
962
963    pub fn value_name_id_byte_range(&self) -> Range<usize> {
964        let start = self.flags_byte_range().end;
965        let end = start + NameId::RAW_BYTE_LEN;
966        start..end
967    }
968
969    pub fn axis_values_byte_range(&self) -> Range<usize> {
970        let axis_count = self.axis_count();
971        let start = self.value_name_id_byte_range().end;
972        let end = start
973            + (transforms::to_usize(axis_count)).saturating_mul(AxisValueRecord::RAW_BYTE_LEN);
974        start..end
975    }
976}
977
978/// Part of [AxisValueFormat4]
979#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
980#[repr(C)]
981#[repr(packed)]
982pub struct AxisValueRecord {
983    /// Zero-base index into the axis record array identifying the axis
984    /// to which this value applies. Must be less than designAxisCount.
985    pub axis_index: BigEndian<u16>,
986    /// A numeric value for this attribute value.
987    pub value: BigEndian<Fixed>,
988}
989
990impl AxisValueRecord {
991    /// Zero-base index into the axis record array identifying the axis
992    /// to which this value applies. Must be less than designAxisCount.
993    pub fn axis_index(&self) -> u16 {
994        self.axis_index.get()
995    }
996
997    /// A numeric value for this attribute value.
998    pub fn value(&self) -> Fixed {
999        self.value.get()
1000    }
1001}
1002
1003impl FixedSize for AxisValueRecord {
1004    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1005}
1006
1007/// [Axis value table flags](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#flags).
1008#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1009#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1010#[repr(transparent)]
1011pub struct AxisValueTableFlags {
1012    bits: u16,
1013}
1014
1015impl AxisValueTableFlags {
1016    /// If set, this axis value table provides axis value information
1017    /// that is applicable to other fonts within the same font family.
1018    /// This is used if the other fonts were released earlier and did
1019    /// not include information about values for some axis. If newer
1020    /// versions of the other fonts include the information themselves
1021    /// and are present, then this table is ignored.
1022    pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1023
1024    /// If set, it indicates that the axis value represents the
1025    /// “normal” value for the axis and may be omitted when
1026    /// composing name strings.
1027    pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1028}
1029
1030impl AxisValueTableFlags {
1031    ///  Returns an empty set of flags.
1032    #[inline]
1033    pub const fn empty() -> Self {
1034        Self { bits: 0 }
1035    }
1036
1037    /// Returns the set containing all flags.
1038    #[inline]
1039    pub const fn all() -> Self {
1040        Self {
1041            bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1042        }
1043    }
1044
1045    /// Returns the raw value of the flags currently stored.
1046    #[inline]
1047    pub const fn bits(&self) -> u16 {
1048        self.bits
1049    }
1050
1051    /// Convert from underlying bit representation, unless that
1052    /// representation contains bits that do not correspond to a flag.
1053    #[inline]
1054    pub const fn from_bits(bits: u16) -> Option<Self> {
1055        if (bits & !Self::all().bits()) == 0 {
1056            Some(Self { bits })
1057        } else {
1058            None
1059        }
1060    }
1061
1062    /// Convert from underlying bit representation, dropping any bits
1063    /// that do not correspond to flags.
1064    #[inline]
1065    pub const fn from_bits_truncate(bits: u16) -> Self {
1066        Self {
1067            bits: bits & Self::all().bits,
1068        }
1069    }
1070
1071    /// Returns `true` if no flags are currently stored.
1072    #[inline]
1073    pub const fn is_empty(&self) -> bool {
1074        self.bits() == Self::empty().bits()
1075    }
1076
1077    /// Returns `true` if there are flags common to both `self` and `other`.
1078    #[inline]
1079    pub const fn intersects(&self, other: Self) -> bool {
1080        !(Self {
1081            bits: self.bits & other.bits,
1082        })
1083        .is_empty()
1084    }
1085
1086    /// Returns `true` if all of the flags in `other` are contained within `self`.
1087    #[inline]
1088    pub const fn contains(&self, other: Self) -> bool {
1089        (self.bits & other.bits) == other.bits
1090    }
1091
1092    /// Inserts the specified flags in-place.
1093    #[inline]
1094    pub fn insert(&mut self, other: Self) {
1095        self.bits |= other.bits;
1096    }
1097
1098    /// Removes the specified flags in-place.
1099    #[inline]
1100    pub fn remove(&mut self, other: Self) {
1101        self.bits &= !other.bits;
1102    }
1103
1104    /// Toggles the specified flags in-place.
1105    #[inline]
1106    pub fn toggle(&mut self, other: Self) {
1107        self.bits ^= other.bits;
1108    }
1109
1110    /// Returns the intersection between the flags in `self` and
1111    /// `other`.
1112    ///
1113    /// Specifically, the returned set contains only the flags which are
1114    /// present in *both* `self` *and* `other`.
1115    ///
1116    /// This is equivalent to using the `&` operator (e.g.
1117    /// [`ops::BitAnd`]), as in `flags & other`.
1118    ///
1119    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
1120    #[inline]
1121    #[must_use]
1122    pub const fn intersection(self, other: Self) -> Self {
1123        Self {
1124            bits: self.bits & other.bits,
1125        }
1126    }
1127
1128    /// Returns the union of between the flags in `self` and `other`.
1129    ///
1130    /// Specifically, the returned set contains all flags which are
1131    /// present in *either* `self` *or* `other`, including any which are
1132    /// present in both.
1133    ///
1134    /// This is equivalent to using the `|` operator (e.g.
1135    /// [`ops::BitOr`]), as in `flags | other`.
1136    ///
1137    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
1138    #[inline]
1139    #[must_use]
1140    pub const fn union(self, other: Self) -> Self {
1141        Self {
1142            bits: self.bits | other.bits,
1143        }
1144    }
1145
1146    /// Returns the difference between the flags in `self` and `other`.
1147    ///
1148    /// Specifically, the returned set contains all flags present in
1149    /// `self`, except for the ones present in `other`.
1150    ///
1151    /// It is also conceptually equivalent to the "bit-clear" operation:
1152    /// `flags & !other` (and this syntax is also supported).
1153    ///
1154    /// This is equivalent to using the `-` operator (e.g.
1155    /// [`ops::Sub`]), as in `flags - other`.
1156    ///
1157    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
1158    #[inline]
1159    #[must_use]
1160    pub const fn difference(self, other: Self) -> Self {
1161        Self {
1162            bits: self.bits & !other.bits,
1163        }
1164    }
1165}
1166
1167impl std::ops::BitOr for AxisValueTableFlags {
1168    type Output = Self;
1169
1170    /// Returns the union of the two sets of flags.
1171    #[inline]
1172    fn bitor(self, other: AxisValueTableFlags) -> Self {
1173        Self {
1174            bits: self.bits | other.bits,
1175        }
1176    }
1177}
1178
1179impl std::ops::BitOrAssign for AxisValueTableFlags {
1180    /// Adds the set of flags.
1181    #[inline]
1182    fn bitor_assign(&mut self, other: Self) {
1183        self.bits |= other.bits;
1184    }
1185}
1186
1187impl std::ops::BitXor for AxisValueTableFlags {
1188    type Output = Self;
1189
1190    /// Returns the left flags, but with all the right flags toggled.
1191    #[inline]
1192    fn bitxor(self, other: Self) -> Self {
1193        Self {
1194            bits: self.bits ^ other.bits,
1195        }
1196    }
1197}
1198
1199impl std::ops::BitXorAssign for AxisValueTableFlags {
1200    /// Toggles the set of flags.
1201    #[inline]
1202    fn bitxor_assign(&mut self, other: Self) {
1203        self.bits ^= other.bits;
1204    }
1205}
1206
1207impl std::ops::BitAnd for AxisValueTableFlags {
1208    type Output = Self;
1209
1210    /// Returns the intersection between the two sets of flags.
1211    #[inline]
1212    fn bitand(self, other: Self) -> Self {
1213        Self {
1214            bits: self.bits & other.bits,
1215        }
1216    }
1217}
1218
1219impl std::ops::BitAndAssign for AxisValueTableFlags {
1220    /// Disables all flags disabled in the set.
1221    #[inline]
1222    fn bitand_assign(&mut self, other: Self) {
1223        self.bits &= other.bits;
1224    }
1225}
1226
1227impl std::ops::Sub for AxisValueTableFlags {
1228    type Output = Self;
1229
1230    /// Returns the set difference of the two sets of flags.
1231    #[inline]
1232    fn sub(self, other: Self) -> Self {
1233        Self {
1234            bits: self.bits & !other.bits,
1235        }
1236    }
1237}
1238
1239impl std::ops::SubAssign for AxisValueTableFlags {
1240    /// Disables all flags enabled in the set.
1241    #[inline]
1242    fn sub_assign(&mut self, other: Self) {
1243        self.bits &= !other.bits;
1244    }
1245}
1246
1247impl std::ops::Not for AxisValueTableFlags {
1248    type Output = Self;
1249
1250    /// Returns the complement of this set of flags.
1251    #[inline]
1252    fn not(self) -> Self {
1253        Self { bits: !self.bits } & Self::all()
1254    }
1255}
1256
1257impl std::fmt::Debug for AxisValueTableFlags {
1258    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1259        let members: &[(&str, Self)] = &[
1260            (
1261                "OLDER_SIBLING_FONT_ATTRIBUTE",
1262                Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1263            ),
1264            ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1265        ];
1266        let mut first = true;
1267        for (name, value) in members {
1268            if self.contains(*value) {
1269                if !first {
1270                    f.write_str(" | ")?;
1271                }
1272                first = false;
1273                f.write_str(name)?;
1274            }
1275        }
1276        if first {
1277            f.write_str("(empty)")?;
1278        }
1279        Ok(())
1280    }
1281}
1282
1283impl std::fmt::Binary for AxisValueTableFlags {
1284    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1285        std::fmt::Binary::fmt(&self.bits, f)
1286    }
1287}
1288
1289impl std::fmt::Octal for AxisValueTableFlags {
1290    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1291        std::fmt::Octal::fmt(&self.bits, f)
1292    }
1293}
1294
1295impl std::fmt::LowerHex for AxisValueTableFlags {
1296    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1297        std::fmt::LowerHex::fmt(&self.bits, f)
1298    }
1299}
1300
1301impl std::fmt::UpperHex for AxisValueTableFlags {
1302    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1303        std::fmt::UpperHex::fmt(&self.bits, f)
1304    }
1305}
1306
1307impl font_types::Scalar for AxisValueTableFlags {
1308    type Raw = <u16 as font_types::Scalar>::Raw;
1309    fn to_raw(self) -> Self::Raw {
1310        self.bits().to_raw()
1311    }
1312    fn from_raw(raw: Self::Raw) -> Self {
1313        let t = <u16>::from_raw(raw);
1314        Self::from_bits_truncate(t)
1315    }
1316}