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