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