Skip to main content

read_fonts/generated/
generated_variations.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 TupleVariationHeader<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.intermediate_end_tuple_byte_range().end
11    }
12    fn min_table_bytes(&self) -> &'a [u8] {
13        let range = self.min_byte_range();
14        self.offset_data().as_bytes().get(range).unwrap_or_default()
15    }
16}
17
18impl ReadArgs for TupleVariationHeader<'_> {
19    type Args = u16;
20}
21
22impl<'a> FontRead<'a> for TupleVariationHeader<'a> {
23    fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
24        let axis_count = args;
25
26        #[allow(clippy::absurd_extreme_comparisons)]
27        if data.len() < Self::MIN_SIZE {
28            return Err(ReadError::OutOfBounds);
29        }
30        let Some(data) = TableDataRef::new(data.as_bytes()) else {
31            return Err(ReadError::OutOfBounds);
32        };
33        Ok(Self { data, axis_count })
34    }
35}
36
37impl<'a> TupleVariationHeader<'a> {
38    /// A constructor that requires additional arguments.
39    ///
40    /// This type requires some external state in order to be
41    /// parsed.
42    pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
43        let args = axis_count;
44        Self::read_with_args(data, args)
45    }
46}
47
48/// The fields at the start of the table, which are read directly.
49#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
50#[repr(C, packed)]
51#[doc(hidden)]
52pub struct TupleVariationHeaderFixedHeader {
53    pub variation_data_size: BigEndian<u16>,
54    pub tuple_index: BigEndian<TupleIndex>,
55}
56
57#[allow(clippy::absurd_extreme_comparisons)]
58const _: () = assert!(
59    std::mem::size_of::<TupleVariationHeaderFixedHeader>() <= TupleVariationHeader::MIN_SIZE
60);
61
62/// [TupleVariationHeader](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader)
63#[derive(Clone)]
64pub struct TupleVariationHeader<'a> {
65    data: TableDataRef<'a, TupleVariationHeaderFixedHeader>,
66    axis_count: u16,
67}
68
69#[allow(clippy::needless_lifetimes)]
70impl<'a> TupleVariationHeader<'a> {
71    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + TupleIndex::RAW_BYTE_LEN);
72    basic_table_impls!(impl_the_methods);
73
74    /// The size in bytes of the serialized data for this tuple
75    /// variation table.
76    pub fn variation_data_size(&self) -> u16 {
77        self.data.header().variation_data_size.get()
78    }
79
80    /// A packed field. The high 4 bits are flags (see below). The low
81    /// 12 bits are an index into a shared tuple records array.
82    pub fn tuple_index(&self) -> TupleIndex {
83        self.data.header().tuple_index.get()
84    }
85
86    pub(crate) fn axis_count(&self) -> u16 {
87        self.axis_count
88    }
89
90    pub fn variation_data_size_byte_range(&self) -> Range<usize> {
91        let start = 0;
92        let end = start + u16::RAW_BYTE_LEN;
93        start..end
94    }
95
96    pub fn tuple_index_byte_range(&self) -> Range<usize> {
97        let start = self.variation_data_size_byte_range().end;
98        let end = start + TupleIndex::RAW_BYTE_LEN;
99        start..end
100    }
101
102    pub fn peak_tuple_byte_range(&self) -> Range<usize> {
103        let tuple_index = self.tuple_index();
104        let axis_count = self.axis_count();
105        let start = self.tuple_index_byte_range().end;
106        let end = start
107            + (TupleIndex::tuple_len(tuple_index, axis_count, 0_usize))
108                .saturating_mul(F2Dot14::RAW_BYTE_LEN);
109        start..end
110    }
111
112    pub fn intermediate_start_tuple_byte_range(&self) -> Range<usize> {
113        let tuple_index = self.tuple_index();
114        let axis_count = self.axis_count();
115        let start = self.peak_tuple_byte_range().end;
116        let end = start
117            + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
118                .saturating_mul(F2Dot14::RAW_BYTE_LEN);
119        start..end
120    }
121
122    pub fn intermediate_end_tuple_byte_range(&self) -> Range<usize> {
123        let tuple_index = self.tuple_index();
124        let axis_count = self.axis_count();
125        let start = self.intermediate_start_tuple_byte_range().end;
126        let end = start
127            + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
128                .saturating_mul(F2Dot14::RAW_BYTE_LEN);
129        start..end
130    }
131}
132
133const _: () = assert!(FontData::default_data_long_enough(
134    TupleVariationHeader::MIN_SIZE
135));
136
137impl Default for TupleVariationHeader<'_> {
138    fn default() -> Self {
139        Self {
140            data: TableDataRef::new(FontData::default_table_data().as_bytes())
141                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
142            axis_count: Default::default(),
143        }
144    }
145}
146
147/// A [Tuple Record](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuple-records)
148///
149/// The tuple variation store formats reference regions within the font’s
150/// variation space using tuple records. A tuple record identifies a position
151/// in terms of normalized coordinates, which use F2DOT14 values.
152#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub struct Tuple<'a> {
154    /// Coordinate array specifying a position within the font’s variation space.
155    ///
156    /// The number of elements must match the axisCount specified in the
157    /// 'fvar' table.
158    pub values: &'a [BigEndian<F2Dot14>],
159}
160
161impl<'a> Tuple<'a> {
162    /// Coordinate array specifying a position within the font’s variation space.
163    ///
164    /// The number of elements must match the axisCount specified in the
165    /// 'fvar' table.
166    pub fn values(&self) -> &'a [BigEndian<F2Dot14>] {
167        self.values
168    }
169}
170
171impl ReadArgs for Tuple<'_> {
172    type Args = u16;
173}
174
175impl ComputeSize for Tuple<'_> {
176    #[allow(clippy::needless_question_mark)]
177    fn compute_size(args: u16) -> Result<usize, ReadError> {
178        let axis_count = args;
179        Ok((transforms::to_usize(axis_count)).saturating_mul(F2Dot14::RAW_BYTE_LEN))
180    }
181}
182
183impl<'a> FontRead<'a> for Tuple<'a> {
184    fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
185        let mut cursor = data.cursor();
186        let axis_count = args;
187        Ok(Self {
188            values: cursor.read_array(transforms::to_usize(axis_count))?,
189        })
190    }
191}
192
193crate::impl_font_read_at!(Tuple<'a>);
194
195#[allow(clippy::needless_lifetimes)]
196impl<'a> Tuple<'a> {
197    /// A constructor that requires additional arguments.
198    ///
199    /// This type requires some external state in order to be
200    /// parsed.
201    pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
202        let args = axis_count;
203        Self::read_with_args(data, args)
204    }
205}
206
207impl Format<u8> for DeltaSetIndexMapFormat0<'_> {
208    const FORMAT: u8 = 0;
209}
210
211impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat0<'a> {
212    fn min_byte_range(&self) -> Range<usize> {
213        0..self.map_data_byte_range().end
214    }
215    fn min_table_bytes(&self) -> &'a [u8] {
216        let range = self.min_byte_range();
217        self.offset_data().as_bytes().get(range).unwrap_or_default()
218    }
219}
220
221impl ReadArgs for DeltaSetIndexMapFormat0<'_> {
222    type Args = ();
223}
224
225impl<'a> FontRead<'a> for DeltaSetIndexMapFormat0<'a> {
226    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
227        #[allow(clippy::absurd_extreme_comparisons)]
228        if data.len() < Self::MIN_SIZE {
229            return Err(ReadError::OutOfBounds);
230        }
231        let Some(data) = TableDataRef::new(data.as_bytes()) else {
232            return Err(ReadError::OutOfBounds);
233        };
234        Ok(Self { data })
235    }
236}
237
238/// The fields at the start of the table, which are read directly.
239#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
240#[repr(C, packed)]
241#[doc(hidden)]
242pub struct DeltaSetIndexMapFormat0FixedHeader {
243    pub format: u8,
244    pub entry_format: BigEndian<EntryFormat>,
245    pub map_count: BigEndian<u16>,
246}
247
248#[allow(clippy::absurd_extreme_comparisons)]
249const _: () = assert!(
250    std::mem::size_of::<DeltaSetIndexMapFormat0FixedHeader>() <= DeltaSetIndexMapFormat0::MIN_SIZE
251);
252
253/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 0
254#[derive(Clone)]
255pub struct DeltaSetIndexMapFormat0<'a> {
256    data: TableDataRef<'a, DeltaSetIndexMapFormat0FixedHeader>,
257}
258
259#[allow(clippy::needless_lifetimes)]
260impl<'a> DeltaSetIndexMapFormat0<'a> {
261    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
262    basic_table_impls!(impl_the_methods);
263
264    /// DeltaSetIndexMap format: set to 0.
265    pub fn format(&self) -> u8 {
266        self.data.header().format
267    }
268
269    /// A packed field that describes the compressed representation of
270    /// delta-set indices. See details below.
271    pub fn entry_format(&self) -> EntryFormat {
272        self.data.header().entry_format.get()
273    }
274
275    /// The number of mapping entries.
276    pub fn map_count(&self) -> u16 {
277        self.data.header().map_count.get()
278    }
279
280    /// The delta-set index mapping data. See details below.
281    pub fn map_data(&self) -> &'a [u8] {
282        let range = self.map_data_byte_range();
283        self.offset_data()
284            .read_array(range)
285            .ok()
286            .unwrap_or_default()
287    }
288
289    pub fn format_byte_range(&self) -> Range<usize> {
290        let start = 0;
291        let end = start + u8::RAW_BYTE_LEN;
292        start..end
293    }
294
295    pub fn entry_format_byte_range(&self) -> Range<usize> {
296        let start = self.format_byte_range().end;
297        let end = start + EntryFormat::RAW_BYTE_LEN;
298        start..end
299    }
300
301    pub fn map_count_byte_range(&self) -> Range<usize> {
302        let start = self.entry_format_byte_range().end;
303        let end = start + u16::RAW_BYTE_LEN;
304        start..end
305    }
306
307    pub fn map_data_byte_range(&self) -> Range<usize> {
308        let entry_format = self.entry_format();
309        let map_count = self.map_count();
310        let start = self.map_count_byte_range().end;
311        let end = start
312            + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN);
313        start..end
314    }
315}
316
317const _: () = assert!(FontData::default_data_long_enough(
318    DeltaSetIndexMapFormat0::MIN_SIZE
319));
320
321impl Default for DeltaSetIndexMapFormat0<'_> {
322    fn default() -> Self {
323        Self {
324            data: TableDataRef::new(FontData::default_table_data().as_bytes())
325                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
326        }
327    }
328}
329
330impl Format<u8> for DeltaSetIndexMapFormat1<'_> {
331    const FORMAT: u8 = 1;
332}
333
334impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat1<'a> {
335    fn min_byte_range(&self) -> Range<usize> {
336        0..self.map_data_byte_range().end
337    }
338    fn min_table_bytes(&self) -> &'a [u8] {
339        let range = self.min_byte_range();
340        self.offset_data().as_bytes().get(range).unwrap_or_default()
341    }
342}
343
344impl ReadArgs for DeltaSetIndexMapFormat1<'_> {
345    type Args = ();
346}
347
348impl<'a> FontRead<'a> for DeltaSetIndexMapFormat1<'a> {
349    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
350        #[allow(clippy::absurd_extreme_comparisons)]
351        if data.len() < Self::MIN_SIZE {
352            return Err(ReadError::OutOfBounds);
353        }
354        let Some(data) = TableDataRef::new(data.as_bytes()) else {
355            return Err(ReadError::OutOfBounds);
356        };
357        Ok(Self { data })
358    }
359}
360
361/// The fields at the start of the table, which are read directly.
362#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
363#[repr(C, packed)]
364#[doc(hidden)]
365pub struct DeltaSetIndexMapFormat1FixedHeader {
366    pub format: u8,
367    pub entry_format: BigEndian<EntryFormat>,
368    pub map_count: BigEndian<u32>,
369}
370
371#[allow(clippy::absurd_extreme_comparisons)]
372const _: () = assert!(
373    std::mem::size_of::<DeltaSetIndexMapFormat1FixedHeader>() <= DeltaSetIndexMapFormat1::MIN_SIZE
374);
375
376/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 1
377#[derive(Clone)]
378pub struct DeltaSetIndexMapFormat1<'a> {
379    data: TableDataRef<'a, DeltaSetIndexMapFormat1FixedHeader>,
380}
381
382#[allow(clippy::needless_lifetimes)]
383impl<'a> DeltaSetIndexMapFormat1<'a> {
384    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
385    basic_table_impls!(impl_the_methods);
386
387    /// DeltaSetIndexMap format: set to 1.
388    pub fn format(&self) -> u8 {
389        self.data.header().format
390    }
391
392    /// A packed field that describes the compressed representation of
393    /// delta-set indices. See details below.
394    pub fn entry_format(&self) -> EntryFormat {
395        self.data.header().entry_format.get()
396    }
397
398    /// The number of mapping entries.
399    pub fn map_count(&self) -> u32 {
400        self.data.header().map_count.get()
401    }
402
403    /// The delta-set index mapping data. See details below.
404    pub fn map_data(&self) -> &'a [u8] {
405        let range = self.map_data_byte_range();
406        self.offset_data()
407            .read_array(range)
408            .ok()
409            .unwrap_or_default()
410    }
411
412    pub fn format_byte_range(&self) -> Range<usize> {
413        let start = 0;
414        let end = start + u8::RAW_BYTE_LEN;
415        start..end
416    }
417
418    pub fn entry_format_byte_range(&self) -> Range<usize> {
419        let start = self.format_byte_range().end;
420        let end = start + EntryFormat::RAW_BYTE_LEN;
421        start..end
422    }
423
424    pub fn map_count_byte_range(&self) -> Range<usize> {
425        let start = self.entry_format_byte_range().end;
426        let end = start + u32::RAW_BYTE_LEN;
427        start..end
428    }
429
430    pub fn map_data_byte_range(&self) -> Range<usize> {
431        let entry_format = self.entry_format();
432        let map_count = self.map_count();
433        let start = self.map_count_byte_range().end;
434        let end = start
435            + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN);
436        start..end
437    }
438}
439
440const _: () = assert!(FontData::default_data_long_enough(
441    DeltaSetIndexMapFormat1::MIN_SIZE
442));
443
444impl Default for DeltaSetIndexMapFormat1<'_> {
445    fn default() -> Self {
446        Self {
447            data: TableDataRef::new(FontData::default_format_1_u8_table_data().as_bytes())
448                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
449        }
450    }
451}
452
453/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table
454#[derive(Clone)]
455pub enum DeltaSetIndexMap<'a> {
456    Format0(DeltaSetIndexMapFormat0<'a>),
457    Format1(DeltaSetIndexMapFormat1<'a>),
458}
459
460impl Default for DeltaSetIndexMap<'_> {
461    fn default() -> Self {
462        Self::Format0(Default::default())
463    }
464}
465
466impl<'a> DeltaSetIndexMap<'a> {
467    ///Return the `FontData` used to resolve offsets for this table.
468    pub fn offset_data(&self) -> FontData<'a> {
469        match self {
470            Self::Format0(item) => item.offset_data(),
471            Self::Format1(item) => item.offset_data(),
472        }
473    }
474
475    /// DeltaSetIndexMap format: set to 0.
476    pub fn format(&self) -> u8 {
477        match self {
478            Self::Format0(item) => item.format(),
479            Self::Format1(item) => item.format(),
480        }
481    }
482
483    /// A packed field that describes the compressed representation of
484    /// delta-set indices. See details below.
485    pub fn entry_format(&self) -> EntryFormat {
486        match self {
487            Self::Format0(item) => item.entry_format(),
488            Self::Format1(item) => item.entry_format(),
489        }
490    }
491
492    /// The delta-set index mapping data. See details below.
493    pub fn map_data(&self) -> &'a [u8] {
494        match self {
495            Self::Format0(item) => item.map_data(),
496            Self::Format1(item) => item.map_data(),
497        }
498    }
499}
500
501impl ReadArgs for DeltaSetIndexMap<'_> {
502    type Args = ();
503}
504
505impl<'a> FontRead<'a> for DeltaSetIndexMap<'a> {
506    #[inline]
507    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
508        let format: u8 = data.read_at(0usize)?;
509        match format {
510            DeltaSetIndexMapFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
511            DeltaSetIndexMapFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
512            other => Err(ReadError::InvalidFormat(other.into())),
513        }
514    }
515}
516
517impl<'a> MinByteRange<'a> for DeltaSetIndexMap<'a> {
518    fn min_byte_range(&self) -> Range<usize> {
519        match self {
520            Self::Format0(item) => item.min_byte_range(),
521            Self::Format1(item) => item.min_byte_range(),
522        }
523    }
524    fn min_table_bytes(&self) -> &'a [u8] {
525        match self {
526            Self::Format0(item) => item.min_table_bytes(),
527            Self::Format1(item) => item.min_table_bytes(),
528        }
529    }
530}
531
532/// Entry format for a [DeltaSetIndexMap].
533#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
534#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
535#[repr(transparent)]
536pub struct EntryFormat {
537    bits: u8,
538}
539
540impl EntryFormat {
541    /// Mask for the low 4 bits, which give the count of bits minus one that are used in each entry for the inner-level index.
542    pub const INNER_INDEX_BIT_COUNT_MASK: Self = Self { bits: 0x0F };
543
544    /// Mask for bits that indicate the size in bytes minus one of each entry.
545    pub const MAP_ENTRY_SIZE_MASK: Self = Self { bits: 0x30 };
546}
547
548impl EntryFormat {
549    ///  Returns an empty set of flags.
550    #[inline]
551    pub const fn empty() -> Self {
552        Self { bits: 0 }
553    }
554
555    /// Returns the set containing all flags.
556    #[inline]
557    pub const fn all() -> Self {
558        Self {
559            bits: Self::INNER_INDEX_BIT_COUNT_MASK.bits | Self::MAP_ENTRY_SIZE_MASK.bits,
560        }
561    }
562
563    /// Returns the raw value of the flags currently stored.
564    #[inline]
565    pub const fn bits(&self) -> u8 {
566        self.bits
567    }
568
569    /// Convert from underlying bit representation, unless that
570    /// representation contains bits that do not correspond to a flag.
571    #[inline]
572    pub const fn from_bits(bits: u8) -> Option<Self> {
573        if (bits & !Self::all().bits()) == 0 {
574            Some(Self { bits })
575        } else {
576            None
577        }
578    }
579
580    /// Convert from underlying bit representation, dropping any bits
581    /// that do not correspond to flags.
582    #[inline]
583    pub const fn from_bits_truncate(bits: u8) -> Self {
584        Self {
585            bits: bits & Self::all().bits,
586        }
587    }
588
589    /// Returns `true` if no flags are currently stored.
590    #[inline]
591    pub const fn is_empty(&self) -> bool {
592        self.bits() == Self::empty().bits()
593    }
594
595    /// Returns `true` if there are flags common to both `self` and `other`.
596    #[inline]
597    pub const fn intersects(&self, other: Self) -> bool {
598        !(Self {
599            bits: self.bits & other.bits,
600        })
601        .is_empty()
602    }
603
604    /// Returns `true` if all of the flags in `other` are contained within `self`.
605    #[inline]
606    pub const fn contains(&self, other: Self) -> bool {
607        (self.bits & other.bits) == other.bits
608    }
609
610    /// Inserts the specified flags in-place.
611    #[inline]
612    pub fn insert(&mut self, other: Self) {
613        self.bits |= other.bits;
614    }
615
616    /// Removes the specified flags in-place.
617    #[inline]
618    pub fn remove(&mut self, other: Self) {
619        self.bits &= !other.bits;
620    }
621
622    /// Toggles the specified flags in-place.
623    #[inline]
624    pub fn toggle(&mut self, other: Self) {
625        self.bits ^= other.bits;
626    }
627
628    /// Returns the intersection between the flags in `self` and
629    /// `other`.
630    ///
631    /// Specifically, the returned set contains only the flags which are
632    /// present in *both* `self` *and* `other`.
633    ///
634    /// This is equivalent to using the `&` operator (e.g.
635    /// [`ops::BitAnd`]), as in `flags & other`.
636    ///
637    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
638    #[inline]
639    #[must_use]
640    pub const fn intersection(self, other: Self) -> Self {
641        Self {
642            bits: self.bits & other.bits,
643        }
644    }
645
646    /// Returns the union of between the flags in `self` and `other`.
647    ///
648    /// Specifically, the returned set contains all flags which are
649    /// present in *either* `self` *or* `other`, including any which are
650    /// present in both.
651    ///
652    /// This is equivalent to using the `|` operator (e.g.
653    /// [`ops::BitOr`]), as in `flags | other`.
654    ///
655    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
656    #[inline]
657    #[must_use]
658    pub const fn union(self, other: Self) -> Self {
659        Self {
660            bits: self.bits | other.bits,
661        }
662    }
663
664    /// Returns the difference between the flags in `self` and `other`.
665    ///
666    /// Specifically, the returned set contains all flags present in
667    /// `self`, except for the ones present in `other`.
668    ///
669    /// It is also conceptually equivalent to the "bit-clear" operation:
670    /// `flags & !other` (and this syntax is also supported).
671    ///
672    /// This is equivalent to using the `-` operator (e.g.
673    /// [`ops::Sub`]), as in `flags - other`.
674    ///
675    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
676    #[inline]
677    #[must_use]
678    pub const fn difference(self, other: Self) -> Self {
679        Self {
680            bits: self.bits & !other.bits,
681        }
682    }
683}
684
685impl std::ops::BitOr for EntryFormat {
686    type Output = Self;
687
688    /// Returns the union of the two sets of flags.
689    #[inline]
690    fn bitor(self, other: EntryFormat) -> Self {
691        Self {
692            bits: self.bits | other.bits,
693        }
694    }
695}
696
697impl std::ops::BitOrAssign for EntryFormat {
698    /// Adds the set of flags.
699    #[inline]
700    fn bitor_assign(&mut self, other: Self) {
701        self.bits |= other.bits;
702    }
703}
704
705impl std::ops::BitXor for EntryFormat {
706    type Output = Self;
707
708    /// Returns the left flags, but with all the right flags toggled.
709    #[inline]
710    fn bitxor(self, other: Self) -> Self {
711        Self {
712            bits: self.bits ^ other.bits,
713        }
714    }
715}
716
717impl std::ops::BitXorAssign for EntryFormat {
718    /// Toggles the set of flags.
719    #[inline]
720    fn bitxor_assign(&mut self, other: Self) {
721        self.bits ^= other.bits;
722    }
723}
724
725impl std::ops::BitAnd for EntryFormat {
726    type Output = Self;
727
728    /// Returns the intersection between the two sets of flags.
729    #[inline]
730    fn bitand(self, other: Self) -> Self {
731        Self {
732            bits: self.bits & other.bits,
733        }
734    }
735}
736
737impl std::ops::BitAndAssign for EntryFormat {
738    /// Disables all flags disabled in the set.
739    #[inline]
740    fn bitand_assign(&mut self, other: Self) {
741        self.bits &= other.bits;
742    }
743}
744
745impl std::ops::Sub for EntryFormat {
746    type Output = Self;
747
748    /// Returns the set difference of the two sets of flags.
749    #[inline]
750    fn sub(self, other: Self) -> Self {
751        Self {
752            bits: self.bits & !other.bits,
753        }
754    }
755}
756
757impl std::ops::SubAssign for EntryFormat {
758    /// Disables all flags enabled in the set.
759    #[inline]
760    fn sub_assign(&mut self, other: Self) {
761        self.bits &= !other.bits;
762    }
763}
764
765impl std::ops::Not for EntryFormat {
766    type Output = Self;
767
768    /// Returns the complement of this set of flags.
769    #[inline]
770    fn not(self) -> Self {
771        Self { bits: !self.bits } & Self::all()
772    }
773}
774
775impl std::fmt::Debug for EntryFormat {
776    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
777        let members: &[(&str, Self)] = &[
778            (
779                "INNER_INDEX_BIT_COUNT_MASK",
780                Self::INNER_INDEX_BIT_COUNT_MASK,
781            ),
782            ("MAP_ENTRY_SIZE_MASK", Self::MAP_ENTRY_SIZE_MASK),
783        ];
784        let mut first = true;
785        for (name, value) in members {
786            if self.contains(*value) {
787                if !first {
788                    f.write_str(" | ")?;
789                }
790                first = false;
791                f.write_str(name)?;
792            }
793        }
794        if first {
795            f.write_str("(empty)")?;
796        }
797        Ok(())
798    }
799}
800
801impl std::fmt::Binary for EntryFormat {
802    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
803        std::fmt::Binary::fmt(&self.bits, f)
804    }
805}
806
807impl std::fmt::Octal for EntryFormat {
808    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
809        std::fmt::Octal::fmt(&self.bits, f)
810    }
811}
812
813impl std::fmt::LowerHex for EntryFormat {
814    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
815        std::fmt::LowerHex::fmt(&self.bits, f)
816    }
817}
818
819impl std::fmt::UpperHex for EntryFormat {
820    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
821        std::fmt::UpperHex::fmt(&self.bits, f)
822    }
823}
824
825impl font_types::Scalar for EntryFormat {
826    type Raw = <u8 as font_types::Scalar>::Raw;
827    fn to_raw(self) -> Self::Raw {
828        self.bits().to_raw()
829    }
830    fn from_raw(raw: Self::Raw) -> Self {
831        let t = <u8>::from_raw(raw);
832        Self::from_bits_truncate(t)
833    }
834}
835
836impl<'a> MinByteRange<'a> for VariationRegionList<'a> {
837    fn min_byte_range(&self) -> Range<usize> {
838        0..self.variation_regions_byte_range().end
839    }
840    fn min_table_bytes(&self) -> &'a [u8] {
841        let range = self.min_byte_range();
842        self.offset_data().as_bytes().get(range).unwrap_or_default()
843    }
844}
845
846impl ReadArgs for VariationRegionList<'_> {
847    type Args = ();
848}
849
850impl<'a> FontRead<'a> for VariationRegionList<'a> {
851    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
852        #[allow(clippy::absurd_extreme_comparisons)]
853        if data.len() < Self::MIN_SIZE {
854            return Err(ReadError::OutOfBounds);
855        }
856        let Some(data) = TableDataRef::new(data.as_bytes()) else {
857            return Err(ReadError::OutOfBounds);
858        };
859        Ok(Self { data })
860    }
861}
862
863/// The fields at the start of the table, which are read directly.
864#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
865#[repr(C, packed)]
866#[doc(hidden)]
867pub struct VariationRegionListFixedHeader {
868    pub axis_count: BigEndian<u16>,
869    pub region_count: BigEndian<u16>,
870}
871
872#[allow(clippy::absurd_extreme_comparisons)]
873const _: () =
874    assert!(std::mem::size_of::<VariationRegionListFixedHeader>() <= VariationRegionList::MIN_SIZE);
875
876/// The [VariationRegionList](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) table
877#[derive(Clone)]
878pub struct VariationRegionList<'a> {
879    data: TableDataRef<'a, VariationRegionListFixedHeader>,
880}
881
882#[allow(clippy::needless_lifetimes)]
883impl<'a> VariationRegionList<'a> {
884    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
885    basic_table_impls!(impl_the_methods);
886
887    /// The number of variation axes for this font. This must be the
888    /// same number as axisCount in the 'fvar' table.
889    pub fn axis_count(&self) -> u16 {
890        self.data.header().axis_count.get()
891    }
892
893    /// The number of variation region tables in the variation region
894    /// list. Must be less than 32,768.
895    pub fn region_count(&self) -> u16 {
896        self.data.header().region_count.get()
897    }
898
899    /// Array of variation regions.
900    pub fn variation_regions(&self) -> ComputedArray<'a, VariationRegion<'a>> {
901        let range = self.variation_regions_byte_range();
902        ComputedArray::new(self.offset_data(), range, self.axis_count()).unwrap_or_default()
903    }
904
905    pub fn axis_count_byte_range(&self) -> Range<usize> {
906        let start = 0;
907        let end = start + u16::RAW_BYTE_LEN;
908        start..end
909    }
910
911    pub fn region_count_byte_range(&self) -> Range<usize> {
912        let start = self.axis_count_byte_range().end;
913        let end = start + u16::RAW_BYTE_LEN;
914        start..end
915    }
916
917    pub fn variation_regions_byte_range(&self) -> Range<usize> {
918        let region_count = self.region_count();
919        let start = self.region_count_byte_range().end;
920        let end = start
921            + (transforms::to_usize(region_count)).saturating_mul(
922                <VariationRegion as ComputeSize>::compute_size(self.axis_count()).unwrap_or(0),
923            );
924        start..end
925    }
926}
927
928const _: () = assert!(FontData::default_data_long_enough(
929    VariationRegionList::MIN_SIZE
930));
931
932impl Default for VariationRegionList<'_> {
933    fn default() -> Self {
934        Self {
935            data: TableDataRef::new(FontData::default_table_data().as_bytes())
936                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
937        }
938    }
939}
940
941/// The [VariationRegion](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) record
942#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
943pub struct VariationRegion<'a> {
944    /// Array of region axis coordinates records, in the order of axes
945    /// given in the 'fvar' table.
946    pub region_axes: &'a [RegionAxisCoordinates],
947}
948
949impl<'a> VariationRegion<'a> {
950    /// Array of region axis coordinates records, in the order of axes
951    /// given in the 'fvar' table.
952    pub fn region_axes(&self) -> &'a [RegionAxisCoordinates] {
953        self.region_axes
954    }
955}
956
957impl ReadArgs for VariationRegion<'_> {
958    type Args = u16;
959}
960
961impl ComputeSize for VariationRegion<'_> {
962    #[allow(clippy::needless_question_mark)]
963    fn compute_size(args: u16) -> Result<usize, ReadError> {
964        let axis_count = args;
965        Ok((transforms::to_usize(axis_count)).saturating_mul(RegionAxisCoordinates::RAW_BYTE_LEN))
966    }
967}
968
969impl<'a> FontRead<'a> for VariationRegion<'a> {
970    fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
971        let mut cursor = data.cursor();
972        let axis_count = args;
973        Ok(Self {
974            region_axes: cursor.read_array(transforms::to_usize(axis_count))?,
975        })
976    }
977}
978
979crate::impl_font_read_at!(VariationRegion<'a>);
980
981#[allow(clippy::needless_lifetimes)]
982impl<'a> VariationRegion<'a> {
983    /// A constructor that requires additional arguments.
984    ///
985    /// This type requires some external state in order to be
986    /// parsed.
987    pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
988        let args = axis_count;
989        Self::read_with_args(data, args)
990    }
991}
992
993/// The [RegionAxisCoordinates](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) record
994#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
995#[repr(C)]
996#[repr(packed)]
997pub struct RegionAxisCoordinates {
998    /// The region start coordinate value for the current axis.
999    pub start_coord: BigEndian<F2Dot14>,
1000    /// The region peak coordinate value for the current axis.
1001    pub peak_coord: BigEndian<F2Dot14>,
1002    /// The region end coordinate value for the current axis.
1003    pub end_coord: BigEndian<F2Dot14>,
1004}
1005
1006impl RegionAxisCoordinates {
1007    /// The region start coordinate value for the current axis.
1008    pub fn start_coord(&self) -> F2Dot14 {
1009        self.start_coord.get()
1010    }
1011
1012    /// The region peak coordinate value for the current axis.
1013    pub fn peak_coord(&self) -> F2Dot14 {
1014        self.peak_coord.get()
1015    }
1016
1017    /// The region end coordinate value for the current axis.
1018    pub fn end_coord(&self) -> F2Dot14 {
1019        self.end_coord.get()
1020    }
1021}
1022
1023impl FixedSize for RegionAxisCoordinates {
1024    const RAW_BYTE_LEN: usize =
1025        F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
1026}
1027
1028impl<'a> MinByteRange<'a> for ItemVariationStore<'a> {
1029    fn min_byte_range(&self) -> Range<usize> {
1030        0..self.item_variation_data_offsets_byte_range().end
1031    }
1032    fn min_table_bytes(&self) -> &'a [u8] {
1033        let range = self.min_byte_range();
1034        self.offset_data().as_bytes().get(range).unwrap_or_default()
1035    }
1036}
1037
1038impl ReadArgs for ItemVariationStore<'_> {
1039    type Args = ();
1040}
1041
1042impl<'a> FontRead<'a> for ItemVariationStore<'a> {
1043    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1044        #[allow(clippy::absurd_extreme_comparisons)]
1045        if data.len() < Self::MIN_SIZE {
1046            return Err(ReadError::OutOfBounds);
1047        }
1048        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1049            return Err(ReadError::OutOfBounds);
1050        };
1051        Ok(Self { data })
1052    }
1053}
1054
1055/// The fields at the start of the table, which are read directly.
1056#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1057#[repr(C, packed)]
1058#[doc(hidden)]
1059pub struct ItemVariationStoreFixedHeader {
1060    pub format: BigEndian<u16>,
1061    pub variation_region_list_offset: BigEndian<Offset32>,
1062    pub item_variation_data_count: BigEndian<u16>,
1063}
1064
1065#[allow(clippy::absurd_extreme_comparisons)]
1066const _: () =
1067    assert!(std::mem::size_of::<ItemVariationStoreFixedHeader>() <= ItemVariationStore::MIN_SIZE);
1068
1069/// The [ItemVariationStore](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) table
1070#[derive(Clone)]
1071pub struct ItemVariationStore<'a> {
1072    data: TableDataRef<'a, ItemVariationStoreFixedHeader>,
1073}
1074
1075#[allow(clippy::needless_lifetimes)]
1076impl<'a> ItemVariationStore<'a> {
1077    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1078    basic_table_impls!(impl_the_methods);
1079
1080    /// Format— set to 1
1081    pub fn format(&self) -> u16 {
1082        self.data.header().format.get()
1083    }
1084
1085    /// Offset in bytes from the start of the item variation store to
1086    /// the variation region list.
1087    pub fn variation_region_list_offset(&self) -> Offset32 {
1088        self.data.header().variation_region_list_offset.get()
1089    }
1090
1091    /// Attempt to resolve [`variation_region_list_offset`][Self::variation_region_list_offset].
1092    pub fn variation_region_list(&self) -> Result<VariationRegionList<'a>, ReadError> {
1093        let data = self.offset_data();
1094        self.variation_region_list_offset().resolve(data)
1095    }
1096
1097    /// The number of item variation data subtables.
1098    pub fn item_variation_data_count(&self) -> u16 {
1099        self.data.header().item_variation_data_count.get()
1100    }
1101
1102    /// Offsets in bytes from the start of the item variation store to
1103    /// each item variation data subtable.
1104    pub fn item_variation_data_offsets(&self) -> &'a [BigEndian<Nullable<Offset32>>] {
1105        let range = self.item_variation_data_offsets_byte_range();
1106        self.offset_data()
1107            .read_array(range)
1108            .ok()
1109            .unwrap_or_default()
1110    }
1111
1112    /// A dynamically resolving wrapper for [`item_variation_data_offsets`][Self::item_variation_data_offsets].
1113    pub fn item_variation_data(
1114        &self,
1115    ) -> ArrayOfNullableOffsets<'a, ItemVariationData<'a>, Offset32> {
1116        let data = self.offset_data();
1117        let offsets = self.item_variation_data_offsets();
1118        ArrayOfNullableOffsets::new(offsets, data, ())
1119    }
1120
1121    pub fn format_byte_range(&self) -> Range<usize> {
1122        let start = 0;
1123        let end = start + u16::RAW_BYTE_LEN;
1124        start..end
1125    }
1126
1127    pub fn variation_region_list_offset_byte_range(&self) -> Range<usize> {
1128        let start = self.format_byte_range().end;
1129        let end = start + Offset32::RAW_BYTE_LEN;
1130        start..end
1131    }
1132
1133    pub fn item_variation_data_count_byte_range(&self) -> Range<usize> {
1134        let start = self.variation_region_list_offset_byte_range().end;
1135        let end = start + u16::RAW_BYTE_LEN;
1136        start..end
1137    }
1138
1139    pub fn item_variation_data_offsets_byte_range(&self) -> Range<usize> {
1140        let item_variation_data_count = self.item_variation_data_count();
1141        let start = self.item_variation_data_count_byte_range().end;
1142        let end = start
1143            + (transforms::to_usize(item_variation_data_count))
1144                .saturating_mul(Offset32::RAW_BYTE_LEN);
1145        start..end
1146    }
1147}
1148
1149const _: () = assert!(FontData::default_data_long_enough(
1150    ItemVariationStore::MIN_SIZE
1151));
1152
1153impl Default for ItemVariationStore<'_> {
1154    fn default() -> Self {
1155        Self {
1156            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1157                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1158        }
1159    }
1160}
1161
1162impl<'a> MinByteRange<'a> for ItemVariationData<'a> {
1163    fn min_byte_range(&self) -> Range<usize> {
1164        0..self.delta_sets_byte_range().end
1165    }
1166    fn min_table_bytes(&self) -> &'a [u8] {
1167        let range = self.min_byte_range();
1168        self.offset_data().as_bytes().get(range).unwrap_or_default()
1169    }
1170}
1171
1172impl ReadArgs for ItemVariationData<'_> {
1173    type Args = ();
1174}
1175
1176impl<'a> FontRead<'a> for ItemVariationData<'a> {
1177    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1178        #[allow(clippy::absurd_extreme_comparisons)]
1179        if data.len() < Self::MIN_SIZE {
1180            return Err(ReadError::OutOfBounds);
1181        }
1182        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1183            return Err(ReadError::OutOfBounds);
1184        };
1185        Ok(Self { data })
1186    }
1187}
1188
1189/// The fields at the start of the table, which are read directly.
1190#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1191#[repr(C, packed)]
1192#[doc(hidden)]
1193pub struct ItemVariationDataFixedHeader {
1194    pub item_count: BigEndian<u16>,
1195    pub word_delta_count: BigEndian<u16>,
1196    pub region_index_count: BigEndian<u16>,
1197}
1198
1199#[allow(clippy::absurd_extreme_comparisons)]
1200const _: () =
1201    assert!(std::mem::size_of::<ItemVariationDataFixedHeader>() <= ItemVariationData::MIN_SIZE);
1202
1203/// The [ItemVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) subtable
1204#[derive(Clone)]
1205pub struct ItemVariationData<'a> {
1206    data: TableDataRef<'a, ItemVariationDataFixedHeader>,
1207}
1208
1209#[allow(clippy::needless_lifetimes)]
1210impl<'a> ItemVariationData<'a> {
1211    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1212    basic_table_impls!(impl_the_methods);
1213
1214    /// The number of delta sets for distinct items.
1215    pub fn item_count(&self) -> u16 {
1216        self.data.header().item_count.get()
1217    }
1218
1219    /// A packed field: the high bit is a flag—see details below.
1220    pub fn word_delta_count(&self) -> u16 {
1221        self.data.header().word_delta_count.get()
1222    }
1223
1224    /// The number of variation regions referenced.
1225    pub fn region_index_count(&self) -> u16 {
1226        self.data.header().region_index_count.get()
1227    }
1228
1229    /// Array of indices into the variation region list for the regions
1230    /// referenced by this item variation data table.
1231    pub fn region_indexes(&self) -> &'a [BigEndian<u16>] {
1232        let range = self.region_indexes_byte_range();
1233        self.offset_data()
1234            .read_array(range)
1235            .ok()
1236            .unwrap_or_default()
1237    }
1238
1239    /// Delta-set rows.
1240    pub fn delta_sets(&self) -> &'a [u8] {
1241        let range = self.delta_sets_byte_range();
1242        self.offset_data()
1243            .read_array(range)
1244            .ok()
1245            .unwrap_or_default()
1246    }
1247
1248    pub fn item_count_byte_range(&self) -> Range<usize> {
1249        let start = 0;
1250        let end = start + u16::RAW_BYTE_LEN;
1251        start..end
1252    }
1253
1254    pub fn word_delta_count_byte_range(&self) -> Range<usize> {
1255        let start = self.item_count_byte_range().end;
1256        let end = start + u16::RAW_BYTE_LEN;
1257        start..end
1258    }
1259
1260    pub fn region_index_count_byte_range(&self) -> Range<usize> {
1261        let start = self.word_delta_count_byte_range().end;
1262        let end = start + u16::RAW_BYTE_LEN;
1263        start..end
1264    }
1265
1266    pub fn region_indexes_byte_range(&self) -> Range<usize> {
1267        let region_index_count = self.region_index_count();
1268        let start = self.region_index_count_byte_range().end;
1269        let end =
1270            start + (transforms::to_usize(region_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
1271        start..end
1272    }
1273
1274    pub fn delta_sets_byte_range(&self) -> Range<usize> {
1275        let item_count = self.item_count();
1276        let word_delta_count = self.word_delta_count();
1277        let region_index_count = self.region_index_count();
1278        let start = self.region_indexes_byte_range().end;
1279        let end = start
1280            + (ItemVariationData::delta_sets_len(item_count, word_delta_count, region_index_count))
1281                .saturating_mul(u8::RAW_BYTE_LEN);
1282        start..end
1283    }
1284}
1285
1286const _: () = assert!(FontData::default_data_long_enough(
1287    ItemVariationData::MIN_SIZE
1288));
1289
1290impl Default for ItemVariationData<'_> {
1291    fn default() -> Self {
1292        Self {
1293            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1294                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1295        }
1296    }
1297}