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