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