Skip to main content

read_fonts/generated/
generated_colr.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 Colr<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.num_layer_records_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 Colr<'_> {
19    /// `COLR`
20    const TAG: Tag = Tag::new(b"COLR");
21}
22
23impl ReadArgs for Colr<'_> {
24    type Args = ();
25}
26
27impl<'a> FontRead<'a> for Colr<'a> {
28    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
29        #[allow(clippy::absurd_extreme_comparisons)]
30        if data.len() < Self::MIN_SIZE {
31            return Err(ReadError::OutOfBounds);
32        }
33        Ok(Self { data })
34    }
35}
36
37/// [COLR (Color)](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#colr-header) table
38#[derive(Clone)]
39pub struct Colr<'a> {
40    data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Colr<'a> {
45    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
46        + u16::RAW_BYTE_LEN
47        + Offset32::RAW_BYTE_LEN
48        + Offset32::RAW_BYTE_LEN
49        + u16::RAW_BYTE_LEN);
50    basic_table_impls!(impl_the_methods);
51
52    /// Table version number - set to 0 or 1.
53    pub fn version(&self) -> u16 {
54        let range = self.version_byte_range();
55        self.data.read_at(range.start).ok().unwrap()
56    }
57
58    /// Number of BaseGlyph records; may be 0 in a version 1 table.
59    pub fn num_base_glyph_records(&self) -> u16 {
60        let range = self.num_base_glyph_records_byte_range();
61        self.data.read_at(range.start).ok().unwrap()
62    }
63
64    /// Offset to baseGlyphRecords array (may be NULL).
65    pub fn base_glyph_records_offset(&self) -> Nullable<Offset32> {
66        let range = self.base_glyph_records_offset_byte_range();
67        self.data.read_at(range.start).ok().unwrap()
68    }
69
70    /// Attempt to resolve [`base_glyph_records_offset`][Self::base_glyph_records_offset].
71    pub fn base_glyph_records(&self) -> Option<Result<&'a [BaseGlyph], ReadError>> {
72        let data = self.data;
73        let args = self.num_base_glyph_records();
74        self.base_glyph_records_offset()
75            .resolve_with_args(data, args)
76    }
77
78    /// Offset to layerRecords array (may be NULL).
79    pub fn layer_records_offset(&self) -> Nullable<Offset32> {
80        let range = self.layer_records_offset_byte_range();
81        self.data.read_at(range.start).ok().unwrap()
82    }
83
84    /// Attempt to resolve [`layer_records_offset`][Self::layer_records_offset].
85    pub fn layer_records(&self) -> Option<Result<&'a [Layer], ReadError>> {
86        let data = self.data;
87        let args = self.num_layer_records();
88        self.layer_records_offset().resolve_with_args(data, args)
89    }
90
91    /// Number of Layer records; may be 0 in a version 1 table.
92    pub fn num_layer_records(&self) -> u16 {
93        let range = self.num_layer_records_byte_range();
94        self.data.read_at(range.start).ok().unwrap()
95    }
96
97    /// Offset to BaseGlyphList table.
98    pub fn base_glyph_list_offset(&self) -> Option<Nullable<Offset32>> {
99        let range = self.base_glyph_list_offset_byte_range();
100        (!range.is_empty())
101            .then(|| self.data.read_at(range.start).ok())
102            .flatten()
103    }
104
105    /// Attempt to resolve [`base_glyph_list_offset`][Self::base_glyph_list_offset].
106    pub fn base_glyph_list(&self) -> Option<Result<BaseGlyphList<'a>, ReadError>> {
107        let data = self.data;
108        self.base_glyph_list_offset().map(|x| x.resolve(data))?
109    }
110
111    /// Offset to LayerList table (may be NULL).
112    pub fn layer_list_offset(&self) -> Option<Nullable<Offset32>> {
113        let range = self.layer_list_offset_byte_range();
114        (!range.is_empty())
115            .then(|| self.data.read_at(range.start).ok())
116            .flatten()
117    }
118
119    /// Attempt to resolve [`layer_list_offset`][Self::layer_list_offset].
120    pub fn layer_list(&self) -> Option<Result<LayerList<'a>, ReadError>> {
121        let data = self.data;
122        self.layer_list_offset().map(|x| x.resolve(data))?
123    }
124
125    /// Offset to ClipList table (may be NULL).
126    pub fn clip_list_offset(&self) -> Option<Nullable<Offset32>> {
127        let range = self.clip_list_offset_byte_range();
128        (!range.is_empty())
129            .then(|| self.data.read_at(range.start).ok())
130            .flatten()
131    }
132
133    /// Attempt to resolve [`clip_list_offset`][Self::clip_list_offset].
134    pub fn clip_list(&self) -> Option<Result<ClipList<'a>, ReadError>> {
135        let data = self.data;
136        self.clip_list_offset().map(|x| x.resolve(data))?
137    }
138
139    /// Offset to DeltaSetIndexMap table (may be NULL).
140    pub fn var_index_map_offset(&self) -> Option<Nullable<Offset32>> {
141        let range = self.var_index_map_offset_byte_range();
142        (!range.is_empty())
143            .then(|| self.data.read_at(range.start).ok())
144            .flatten()
145    }
146
147    /// Attempt to resolve [`var_index_map_offset`][Self::var_index_map_offset].
148    pub fn var_index_map(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
149        let data = self.data;
150        self.var_index_map_offset().map(|x| x.resolve(data))?
151    }
152
153    /// Offset to ItemVariationStore (may be NULL).
154    pub fn item_variation_store_offset(&self) -> Option<Nullable<Offset32>> {
155        let range = self.item_variation_store_offset_byte_range();
156        (!range.is_empty())
157            .then(|| self.data.read_at(range.start).ok())
158            .flatten()
159    }
160
161    /// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset].
162    pub fn item_variation_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
163        let data = self.data;
164        self.item_variation_store_offset()
165            .map(|x| x.resolve(data))?
166    }
167
168    pub fn version_byte_range(&self) -> Range<usize> {
169        let start = 0;
170        let end = start + u16::RAW_BYTE_LEN;
171        start..end
172    }
173
174    pub fn num_base_glyph_records_byte_range(&self) -> Range<usize> {
175        let start = self.version_byte_range().end;
176        let end = start + u16::RAW_BYTE_LEN;
177        start..end
178    }
179
180    pub fn base_glyph_records_offset_byte_range(&self) -> Range<usize> {
181        let start = self.num_base_glyph_records_byte_range().end;
182        let end = start + Offset32::RAW_BYTE_LEN;
183        start..end
184    }
185
186    pub fn layer_records_offset_byte_range(&self) -> Range<usize> {
187        let start = self.base_glyph_records_offset_byte_range().end;
188        let end = start + Offset32::RAW_BYTE_LEN;
189        start..end
190    }
191
192    pub fn num_layer_records_byte_range(&self) -> Range<usize> {
193        let start = self.layer_records_offset_byte_range().end;
194        let end = start + u16::RAW_BYTE_LEN;
195        start..end
196    }
197
198    pub fn base_glyph_list_offset_byte_range(&self) -> Range<usize> {
199        let start = self.num_layer_records_byte_range().end;
200        let end = if self.version().compatible(1u16) {
201            start + Offset32::RAW_BYTE_LEN
202        } else {
203            start
204        };
205        start..end
206    }
207
208    pub fn layer_list_offset_byte_range(&self) -> Range<usize> {
209        let start = self.base_glyph_list_offset_byte_range().end;
210        let end = if self.version().compatible(1u16) {
211            start + Offset32::RAW_BYTE_LEN
212        } else {
213            start
214        };
215        start..end
216    }
217
218    pub fn clip_list_offset_byte_range(&self) -> Range<usize> {
219        let start = self.layer_list_offset_byte_range().end;
220        let end = if self.version().compatible(1u16) {
221            start + Offset32::RAW_BYTE_LEN
222        } else {
223            start
224        };
225        start..end
226    }
227
228    pub fn var_index_map_offset_byte_range(&self) -> Range<usize> {
229        let start = self.clip_list_offset_byte_range().end;
230        let end = if self.version().compatible(1u16) {
231            start + Offset32::RAW_BYTE_LEN
232        } else {
233            start
234        };
235        start..end
236    }
237
238    pub fn item_variation_store_offset_byte_range(&self) -> Range<usize> {
239        let start = self.var_index_map_offset_byte_range().end;
240        let end = if self.version().compatible(1u16) {
241            start + Offset32::RAW_BYTE_LEN
242        } else {
243            start
244        };
245        start..end
246    }
247}
248
249const _: () = assert!(FontData::default_data_long_enough(Colr::MIN_SIZE));
250
251impl Default for Colr<'_> {
252    fn default() -> Self {
253        Self {
254            data: FontData::default_table_data(),
255        }
256    }
257}
258
259/// [BaseGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyph-and-layer-records) record
260#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
261#[repr(C)]
262#[repr(packed)]
263pub struct BaseGlyph {
264    /// Glyph ID of the base glyph.
265    pub glyph_id: BigEndian<GlyphId16>,
266    /// Index (base 0) into the layerRecords array.
267    pub first_layer_index: BigEndian<u16>,
268    /// Number of color layers associated with this glyph.
269    pub num_layers: BigEndian<u16>,
270}
271
272impl BaseGlyph {
273    /// Glyph ID of the base glyph.
274    pub fn glyph_id(&self) -> GlyphId16 {
275        self.glyph_id.get()
276    }
277
278    /// Index (base 0) into the layerRecords array.
279    pub fn first_layer_index(&self) -> u16 {
280        self.first_layer_index.get()
281    }
282
283    /// Number of color layers associated with this glyph.
284    pub fn num_layers(&self) -> u16 {
285        self.num_layers.get()
286    }
287}
288
289impl FixedSize for BaseGlyph {
290    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
291}
292
293/// [Layer](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyph-and-layer-records) record
294#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
295#[repr(C)]
296#[repr(packed)]
297pub struct Layer {
298    /// Glyph ID of the glyph used for a given layer.
299    pub glyph_id: BigEndian<GlyphId16>,
300    /// Index (base 0) for a palette entry in the CPAL table.
301    pub palette_index: BigEndian<u16>,
302}
303
304impl Layer {
305    /// Glyph ID of the glyph used for a given layer.
306    pub fn glyph_id(&self) -> GlyphId16 {
307        self.glyph_id.get()
308    }
309
310    /// Index (base 0) for a palette entry in the CPAL table.
311    pub fn palette_index(&self) -> u16 {
312        self.palette_index.get()
313    }
314}
315
316impl FixedSize for Layer {
317    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
318}
319
320impl<'a> MinByteRange<'a> for BaseGlyphList<'a> {
321    fn min_byte_range(&self) -> Range<usize> {
322        0..self.base_glyph_paint_records_byte_range().end
323    }
324    fn min_table_bytes(&self) -> &'a [u8] {
325        let range = self.min_byte_range();
326        self.data.as_bytes().get(range).unwrap_or_default()
327    }
328}
329
330impl ReadArgs for BaseGlyphList<'_> {
331    type Args = ();
332}
333
334impl<'a> FontRead<'a> for BaseGlyphList<'a> {
335    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
336        #[allow(clippy::absurd_extreme_comparisons)]
337        if data.len() < Self::MIN_SIZE {
338            return Err(ReadError::OutOfBounds);
339        }
340        Ok(Self { data })
341    }
342}
343
344/// [BaseGlyphList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
345#[derive(Clone)]
346pub struct BaseGlyphList<'a> {
347    data: FontData<'a>,
348}
349
350#[allow(clippy::needless_lifetimes)]
351impl<'a> BaseGlyphList<'a> {
352    pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
353    basic_table_impls!(impl_the_methods);
354
355    pub fn num_base_glyph_paint_records(&self) -> u32 {
356        let range = self.num_base_glyph_paint_records_byte_range();
357        self.data.read_at(range.start).ok().unwrap()
358    }
359
360    pub fn base_glyph_paint_records(&self) -> &'a [BaseGlyphPaint] {
361        let range = self.base_glyph_paint_records_byte_range();
362        self.data.read_array(range).ok().unwrap_or_default()
363    }
364
365    pub fn num_base_glyph_paint_records_byte_range(&self) -> Range<usize> {
366        let start = 0;
367        let end = start + u32::RAW_BYTE_LEN;
368        start..end
369    }
370
371    pub fn base_glyph_paint_records_byte_range(&self) -> Range<usize> {
372        let num_base_glyph_paint_records = self.num_base_glyph_paint_records();
373        let start = self.num_base_glyph_paint_records_byte_range().end;
374        let end = start
375            + (transforms::to_usize(num_base_glyph_paint_records))
376                .saturating_mul(BaseGlyphPaint::RAW_BYTE_LEN);
377        start..end
378    }
379}
380
381const _: () = assert!(FontData::default_data_long_enough(BaseGlyphList::MIN_SIZE));
382
383impl Default for BaseGlyphList<'_> {
384    fn default() -> Self {
385        Self {
386            data: FontData::default_table_data(),
387        }
388    }
389}
390
391/// [BaseGlyphPaint](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
392#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
393#[repr(C)]
394#[repr(packed)]
395pub struct BaseGlyphPaint {
396    /// Glyph ID of the base glyph.
397    pub glyph_id: BigEndian<GlyphId16>,
398    /// Offset to a Paint table, from the beginning of the [`BaseGlyphList`] table.
399    pub paint_offset: BigEndian<Offset32>,
400}
401
402impl BaseGlyphPaint {
403    /// Glyph ID of the base glyph.
404    pub fn glyph_id(&self) -> GlyphId16 {
405        self.glyph_id.get()
406    }
407
408    /// Offset to a Paint table, from the beginning of the [`BaseGlyphList`] table.
409    pub fn paint_offset(&self) -> Offset32 {
410        self.paint_offset.get()
411    }
412
413    /// Offset to a Paint table, from the beginning of the [`BaseGlyphList`] table.
414    ///
415    /// The `data` argument should be retrieved from the parent table
416    /// By calling its `offset_data` method.
417    pub fn paint<'a>(&self, data: FontData<'a>) -> Result<Paint<'a>, ReadError> {
418        self.paint_offset().resolve(data)
419    }
420}
421
422impl FixedSize for BaseGlyphPaint {
423    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
424}
425
426impl<'a> MinByteRange<'a> for LayerList<'a> {
427    fn min_byte_range(&self) -> Range<usize> {
428        0..self.paint_offsets_byte_range().end
429    }
430    fn min_table_bytes(&self) -> &'a [u8] {
431        let range = self.min_byte_range();
432        self.data.as_bytes().get(range).unwrap_or_default()
433    }
434}
435
436impl ReadArgs for LayerList<'_> {
437    type Args = ();
438}
439
440impl<'a> FontRead<'a> for LayerList<'a> {
441    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
442        #[allow(clippy::absurd_extreme_comparisons)]
443        if data.len() < Self::MIN_SIZE {
444            return Err(ReadError::OutOfBounds);
445        }
446        Ok(Self { data })
447    }
448}
449
450/// [LayerList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
451#[derive(Clone)]
452pub struct LayerList<'a> {
453    data: FontData<'a>,
454}
455
456#[allow(clippy::needless_lifetimes)]
457impl<'a> LayerList<'a> {
458    pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
459    basic_table_impls!(impl_the_methods);
460
461    pub fn num_layers(&self) -> u32 {
462        let range = self.num_layers_byte_range();
463        self.data.read_at(range.start).ok().unwrap()
464    }
465
466    /// Offsets to Paint tables.
467    pub fn paint_offsets(&self) -> &'a [BigEndian<Offset32>] {
468        let range = self.paint_offsets_byte_range();
469        self.data.read_array(range).ok().unwrap_or_default()
470    }
471
472    /// A dynamically resolving wrapper for [`paint_offsets`][Self::paint_offsets].
473    pub fn paints(&self) -> ArrayOfOffsets<'a, Paint<'a>, Offset32> {
474        let data = self.data;
475        let offsets = self.paint_offsets();
476        ArrayOfOffsets::new(offsets, data, ())
477    }
478
479    pub fn num_layers_byte_range(&self) -> Range<usize> {
480        let start = 0;
481        let end = start + u32::RAW_BYTE_LEN;
482        start..end
483    }
484
485    pub fn paint_offsets_byte_range(&self) -> Range<usize> {
486        let num_layers = self.num_layers();
487        let start = self.num_layers_byte_range().end;
488        let end = start + (transforms::to_usize(num_layers)).saturating_mul(Offset32::RAW_BYTE_LEN);
489        start..end
490    }
491}
492
493const _: () = assert!(FontData::default_data_long_enough(LayerList::MIN_SIZE));
494
495impl Default for LayerList<'_> {
496    fn default() -> Self {
497        Self {
498            data: FontData::default_table_data(),
499        }
500    }
501}
502
503impl<'a> MinByteRange<'a> for ClipList<'a> {
504    fn min_byte_range(&self) -> Range<usize> {
505        0..self.clips_byte_range().end
506    }
507    fn min_table_bytes(&self) -> &'a [u8] {
508        let range = self.min_byte_range();
509        self.data.as_bytes().get(range).unwrap_or_default()
510    }
511}
512
513impl ReadArgs for ClipList<'_> {
514    type Args = ();
515}
516
517impl<'a> FontRead<'a> for ClipList<'a> {
518    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
519        #[allow(clippy::absurd_extreme_comparisons)]
520        if data.len() < Self::MIN_SIZE {
521            return Err(ReadError::OutOfBounds);
522        }
523        Ok(Self { data })
524    }
525}
526
527/// [ClipList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
528#[derive(Clone)]
529pub struct ClipList<'a> {
530    data: FontData<'a>,
531}
532
533#[allow(clippy::needless_lifetimes)]
534impl<'a> ClipList<'a> {
535    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
536    basic_table_impls!(impl_the_methods);
537
538    /// Set to 1.
539    pub fn format(&self) -> u8 {
540        let range = self.format_byte_range();
541        self.data.read_at(range.start).ok().unwrap()
542    }
543
544    /// Number of Clip records.
545    pub fn num_clips(&self) -> u32 {
546        let range = self.num_clips_byte_range();
547        self.data.read_at(range.start).ok().unwrap()
548    }
549
550    /// Clip records. Sorted by startGlyphID.
551    pub fn clips(&self) -> &'a [Clip] {
552        let range = self.clips_byte_range();
553        self.data.read_array(range).ok().unwrap_or_default()
554    }
555
556    pub fn format_byte_range(&self) -> Range<usize> {
557        let start = 0;
558        let end = start + u8::RAW_BYTE_LEN;
559        start..end
560    }
561
562    pub fn num_clips_byte_range(&self) -> Range<usize> {
563        let start = self.format_byte_range().end;
564        let end = start + u32::RAW_BYTE_LEN;
565        start..end
566    }
567
568    pub fn clips_byte_range(&self) -> Range<usize> {
569        let num_clips = self.num_clips();
570        let start = self.num_clips_byte_range().end;
571        let end = start + (transforms::to_usize(num_clips)).saturating_mul(Clip::RAW_BYTE_LEN);
572        start..end
573    }
574}
575
576const _: () = assert!(FontData::default_data_long_enough(ClipList::MIN_SIZE));
577
578impl Default for ClipList<'_> {
579    fn default() -> Self {
580        Self {
581            data: FontData::default_table_data(),
582        }
583    }
584}
585
586/// [Clip](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
587#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
588#[repr(C)]
589#[repr(packed)]
590pub struct Clip {
591    /// First glyph ID in the range.
592    pub start_glyph_id: BigEndian<GlyphId16>,
593    /// Last glyph ID in the range.
594    pub end_glyph_id: BigEndian<GlyphId16>,
595    /// Offset to a ClipBox table, from the beginning of the [`ClipList`] table.
596    pub clip_box_offset: BigEndian<Offset24>,
597}
598
599impl Clip {
600    /// First glyph ID in the range.
601    pub fn start_glyph_id(&self) -> GlyphId16 {
602        self.start_glyph_id.get()
603    }
604
605    /// Last glyph ID in the range.
606    pub fn end_glyph_id(&self) -> GlyphId16 {
607        self.end_glyph_id.get()
608    }
609
610    /// Offset to a ClipBox table, from the beginning of the [`ClipList`] table.
611    pub fn clip_box_offset(&self) -> Offset24 {
612        self.clip_box_offset.get()
613    }
614
615    /// Offset to a ClipBox table, from the beginning of the [`ClipList`] table.
616    ///
617    /// The `data` argument should be retrieved from the parent table
618    /// By calling its `offset_data` method.
619    pub fn clip_box<'a>(&self, data: FontData<'a>) -> Result<ClipBox<'a>, ReadError> {
620        self.clip_box_offset().resolve(data)
621    }
622}
623
624impl FixedSize for Clip {
625    const RAW_BYTE_LEN: usize =
626        GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN;
627}
628
629/// [ClipBox](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
630#[derive(Clone)]
631pub enum ClipBox<'a> {
632    Format1(ClipBoxFormat1<'a>),
633    Format2(ClipBoxFormat2<'a>),
634}
635
636impl Default for ClipBox<'_> {
637    fn default() -> Self {
638        Self::Format1(Default::default())
639    }
640}
641
642impl<'a> ClipBox<'a> {
643    ///Return the `FontData` used to resolve offsets for this table.
644    pub fn offset_data(&self) -> FontData<'a> {
645        match self {
646            Self::Format1(item) => item.offset_data(),
647            Self::Format2(item) => item.offset_data(),
648        }
649    }
650
651    /// Set to 1.
652    pub fn format(&self) -> u8 {
653        match self {
654            Self::Format1(item) => item.format(),
655            Self::Format2(item) => item.format(),
656        }
657    }
658
659    /// Minimum x of clip box.
660    pub fn x_min(&self) -> FWord {
661        match self {
662            Self::Format1(item) => item.x_min(),
663            Self::Format2(item) => item.x_min(),
664        }
665    }
666
667    /// Minimum y of clip box.
668    pub fn y_min(&self) -> FWord {
669        match self {
670            Self::Format1(item) => item.y_min(),
671            Self::Format2(item) => item.y_min(),
672        }
673    }
674
675    /// Maximum x of clip box.
676    pub fn x_max(&self) -> FWord {
677        match self {
678            Self::Format1(item) => item.x_max(),
679            Self::Format2(item) => item.x_max(),
680        }
681    }
682
683    /// Maximum y of clip box.
684    pub fn y_max(&self) -> FWord {
685        match self {
686            Self::Format1(item) => item.y_max(),
687            Self::Format2(item) => item.y_max(),
688        }
689    }
690}
691
692impl ReadArgs for ClipBox<'_> {
693    type Args = ();
694}
695
696impl<'a> FontRead<'a> for ClipBox<'a> {
697    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
698        let format: u8 = data.read_at(0usize)?;
699        match format {
700            ClipBoxFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
701            ClipBoxFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
702            other => Err(ReadError::InvalidFormat(other.into())),
703        }
704    }
705}
706
707impl<'a> MinByteRange<'a> for ClipBox<'a> {
708    fn min_byte_range(&self) -> Range<usize> {
709        match self {
710            Self::Format1(item) => item.min_byte_range(),
711            Self::Format2(item) => item.min_byte_range(),
712        }
713    }
714    fn min_table_bytes(&self) -> &'a [u8] {
715        match self {
716            Self::Format1(item) => item.min_table_bytes(),
717            Self::Format2(item) => item.min_table_bytes(),
718        }
719    }
720}
721
722impl Format<u8> for ClipBoxFormat1<'_> {
723    const FORMAT: u8 = 1;
724}
725
726impl<'a> MinByteRange<'a> for ClipBoxFormat1<'a> {
727    fn min_byte_range(&self) -> Range<usize> {
728        0..self.y_max_byte_range().end
729    }
730    fn min_table_bytes(&self) -> &'a [u8] {
731        let range = self.min_byte_range();
732        self.data.as_bytes().get(range).unwrap_or_default()
733    }
734}
735
736impl ReadArgs for ClipBoxFormat1<'_> {
737    type Args = ();
738}
739
740impl<'a> FontRead<'a> for ClipBoxFormat1<'a> {
741    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
742        #[allow(clippy::absurd_extreme_comparisons)]
743        if data.len() < Self::MIN_SIZE {
744            return Err(ReadError::OutOfBounds);
745        }
746        Ok(Self { data })
747    }
748}
749
750/// [ClipBoxFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
751#[derive(Clone)]
752pub struct ClipBoxFormat1<'a> {
753    data: FontData<'a>,
754}
755
756#[allow(clippy::needless_lifetimes)]
757impl<'a> ClipBoxFormat1<'a> {
758    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
759        + FWord::RAW_BYTE_LEN
760        + FWord::RAW_BYTE_LEN
761        + FWord::RAW_BYTE_LEN
762        + FWord::RAW_BYTE_LEN);
763    basic_table_impls!(impl_the_methods);
764
765    /// Set to 1.
766    pub fn format(&self) -> u8 {
767        let range = self.format_byte_range();
768        self.data.read_at(range.start).ok().unwrap()
769    }
770
771    /// Minimum x of clip box.
772    pub fn x_min(&self) -> FWord {
773        let range = self.x_min_byte_range();
774        self.data.read_at(range.start).ok().unwrap()
775    }
776
777    /// Minimum y of clip box.
778    pub fn y_min(&self) -> FWord {
779        let range = self.y_min_byte_range();
780        self.data.read_at(range.start).ok().unwrap()
781    }
782
783    /// Maximum x of clip box.
784    pub fn x_max(&self) -> FWord {
785        let range = self.x_max_byte_range();
786        self.data.read_at(range.start).ok().unwrap()
787    }
788
789    /// Maximum y of clip box.
790    pub fn y_max(&self) -> FWord {
791        let range = self.y_max_byte_range();
792        self.data.read_at(range.start).ok().unwrap()
793    }
794
795    pub fn format_byte_range(&self) -> Range<usize> {
796        let start = 0;
797        let end = start + u8::RAW_BYTE_LEN;
798        start..end
799    }
800
801    pub fn x_min_byte_range(&self) -> Range<usize> {
802        let start = self.format_byte_range().end;
803        let end = start + FWord::RAW_BYTE_LEN;
804        start..end
805    }
806
807    pub fn y_min_byte_range(&self) -> Range<usize> {
808        let start = self.x_min_byte_range().end;
809        let end = start + FWord::RAW_BYTE_LEN;
810        start..end
811    }
812
813    pub fn x_max_byte_range(&self) -> Range<usize> {
814        let start = self.y_min_byte_range().end;
815        let end = start + FWord::RAW_BYTE_LEN;
816        start..end
817    }
818
819    pub fn y_max_byte_range(&self) -> Range<usize> {
820        let start = self.x_max_byte_range().end;
821        let end = start + FWord::RAW_BYTE_LEN;
822        start..end
823    }
824}
825
826const _: () = assert!(FontData::default_data_long_enough(ClipBoxFormat1::MIN_SIZE));
827
828impl Default for ClipBoxFormat1<'_> {
829    fn default() -> Self {
830        Self {
831            data: FontData::default_format_1_u8_table_data(),
832        }
833    }
834}
835
836impl Format<u8> for ClipBoxFormat2<'_> {
837    const FORMAT: u8 = 2;
838}
839
840impl<'a> MinByteRange<'a> for ClipBoxFormat2<'a> {
841    fn min_byte_range(&self) -> Range<usize> {
842        0..self.var_index_base_byte_range().end
843    }
844    fn min_table_bytes(&self) -> &'a [u8] {
845        let range = self.min_byte_range();
846        self.data.as_bytes().get(range).unwrap_or_default()
847    }
848}
849
850impl ReadArgs for ClipBoxFormat2<'_> {
851    type Args = ();
852}
853
854impl<'a> FontRead<'a> for ClipBoxFormat2<'a> {
855    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
856        #[allow(clippy::absurd_extreme_comparisons)]
857        if data.len() < Self::MIN_SIZE {
858            return Err(ReadError::OutOfBounds);
859        }
860        Ok(Self { data })
861    }
862}
863
864/// [ClipBoxFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
865#[derive(Clone)]
866pub struct ClipBoxFormat2<'a> {
867    data: FontData<'a>,
868}
869
870#[allow(clippy::needless_lifetimes)]
871impl<'a> ClipBoxFormat2<'a> {
872    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
873        + FWord::RAW_BYTE_LEN
874        + FWord::RAW_BYTE_LEN
875        + FWord::RAW_BYTE_LEN
876        + FWord::RAW_BYTE_LEN
877        + u32::RAW_BYTE_LEN);
878    basic_table_impls!(impl_the_methods);
879
880    /// Set to 2.
881    pub fn format(&self) -> u8 {
882        let range = self.format_byte_range();
883        self.data.read_at(range.start).ok().unwrap()
884    }
885
886    /// Minimum x of clip box. For variation, use varIndexBase + 0.
887    pub fn x_min(&self) -> FWord {
888        let range = self.x_min_byte_range();
889        self.data.read_at(range.start).ok().unwrap()
890    }
891
892    /// Minimum y of clip box. For variation, use varIndexBase + 1.
893    pub fn y_min(&self) -> FWord {
894        let range = self.y_min_byte_range();
895        self.data.read_at(range.start).ok().unwrap()
896    }
897
898    /// Maximum x of clip box. For variation, use varIndexBase + 2.
899    pub fn x_max(&self) -> FWord {
900        let range = self.x_max_byte_range();
901        self.data.read_at(range.start).ok().unwrap()
902    }
903
904    /// Maximum y of clip box. For variation, use varIndexBase + 3.
905    pub fn y_max(&self) -> FWord {
906        let range = self.y_max_byte_range();
907        self.data.read_at(range.start).ok().unwrap()
908    }
909
910    /// Base index into DeltaSetIndexMap.
911    pub fn var_index_base(&self) -> u32 {
912        let range = self.var_index_base_byte_range();
913        self.data.read_at(range.start).ok().unwrap()
914    }
915
916    pub fn format_byte_range(&self) -> Range<usize> {
917        let start = 0;
918        let end = start + u8::RAW_BYTE_LEN;
919        start..end
920    }
921
922    pub fn x_min_byte_range(&self) -> Range<usize> {
923        let start = self.format_byte_range().end;
924        let end = start + FWord::RAW_BYTE_LEN;
925        start..end
926    }
927
928    pub fn y_min_byte_range(&self) -> Range<usize> {
929        let start = self.x_min_byte_range().end;
930        let end = start + FWord::RAW_BYTE_LEN;
931        start..end
932    }
933
934    pub fn x_max_byte_range(&self) -> Range<usize> {
935        let start = self.y_min_byte_range().end;
936        let end = start + FWord::RAW_BYTE_LEN;
937        start..end
938    }
939
940    pub fn y_max_byte_range(&self) -> Range<usize> {
941        let start = self.x_max_byte_range().end;
942        let end = start + FWord::RAW_BYTE_LEN;
943        start..end
944    }
945
946    pub fn var_index_base_byte_range(&self) -> Range<usize> {
947        let start = self.y_max_byte_range().end;
948        let end = start + u32::RAW_BYTE_LEN;
949        start..end
950    }
951}
952
953/// [ColorIndex](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
954#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
955#[repr(C)]
956#[repr(packed)]
957pub struct ColorIndex {
958    /// Index for a CPAL palette entry.
959    pub palette_index: BigEndian<u16>,
960    /// Alpha value.
961    pub alpha: BigEndian<F2Dot14>,
962}
963
964impl ColorIndex {
965    /// Index for a CPAL palette entry.
966    pub fn palette_index(&self) -> u16 {
967        self.palette_index.get()
968    }
969
970    /// Alpha value.
971    pub fn alpha(&self) -> F2Dot14 {
972        self.alpha.get()
973    }
974}
975
976impl FixedSize for ColorIndex {
977    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
978}
979
980/// [VarColorIndex](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
981#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
982#[repr(C)]
983#[repr(packed)]
984pub struct VarColorIndex {
985    /// Index for a CPAL palette entry.
986    pub palette_index: BigEndian<u16>,
987    /// Alpha value. For variation, use varIndexBase + 0.
988    pub alpha: BigEndian<F2Dot14>,
989    /// Base index into DeltaSetIndexMap.
990    pub var_index_base: BigEndian<u32>,
991}
992
993impl VarColorIndex {
994    /// Index for a CPAL palette entry.
995    pub fn palette_index(&self) -> u16 {
996        self.palette_index.get()
997    }
998
999    /// Alpha value. For variation, use varIndexBase + 0.
1000    pub fn alpha(&self) -> F2Dot14 {
1001        self.alpha.get()
1002    }
1003
1004    /// Base index into DeltaSetIndexMap.
1005    pub fn var_index_base(&self) -> u32 {
1006        self.var_index_base.get()
1007    }
1008}
1009
1010impl FixedSize for VarColorIndex {
1011    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1012}
1013
1014/// [ColorStop](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
1015#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1016#[repr(C)]
1017#[repr(packed)]
1018pub struct ColorStop {
1019    /// Position on a color line.
1020    pub stop_offset: BigEndian<F2Dot14>,
1021    /// Index for a CPAL palette entry.
1022    pub palette_index: BigEndian<u16>,
1023    /// Alpha value.
1024    pub alpha: BigEndian<F2Dot14>,
1025}
1026
1027impl ColorStop {
1028    /// Position on a color line.
1029    pub fn stop_offset(&self) -> F2Dot14 {
1030        self.stop_offset.get()
1031    }
1032
1033    /// Index for a CPAL palette entry.
1034    pub fn palette_index(&self) -> u16 {
1035        self.palette_index.get()
1036    }
1037
1038    /// Alpha value.
1039    pub fn alpha(&self) -> F2Dot14 {
1040        self.alpha.get()
1041    }
1042}
1043
1044impl FixedSize for ColorStop {
1045    const RAW_BYTE_LEN: usize = F2Dot14::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
1046}
1047
1048/// [VarColorStop](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
1049#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1050#[repr(C)]
1051#[repr(packed)]
1052pub struct VarColorStop {
1053    /// Position on a color line. For variation, use varIndexBase + 0.
1054    pub stop_offset: BigEndian<F2Dot14>,
1055    /// Index for a CPAL palette entry.
1056    pub palette_index: BigEndian<u16>,
1057    /// Alpha value. For variation, use varIndexBase + 1.
1058    pub alpha: BigEndian<F2Dot14>,
1059    /// Base index into DeltaSetIndexMap.
1060    pub var_index_base: BigEndian<u32>,
1061}
1062
1063impl VarColorStop {
1064    /// Position on a color line. For variation, use varIndexBase + 0.
1065    pub fn stop_offset(&self) -> F2Dot14 {
1066        self.stop_offset.get()
1067    }
1068
1069    /// Index for a CPAL palette entry.
1070    pub fn palette_index(&self) -> u16 {
1071        self.palette_index.get()
1072    }
1073
1074    /// Alpha value. For variation, use varIndexBase + 1.
1075    pub fn alpha(&self) -> F2Dot14 {
1076        self.alpha.get()
1077    }
1078
1079    /// Base index into DeltaSetIndexMap.
1080    pub fn var_index_base(&self) -> u32 {
1081        self.var_index_base.get()
1082    }
1083}
1084
1085impl FixedSize for VarColorStop {
1086    const RAW_BYTE_LEN: usize =
1087        F2Dot14::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1088}
1089
1090impl<'a> MinByteRange<'a> for ColorLine<'a> {
1091    fn min_byte_range(&self) -> Range<usize> {
1092        0..self.color_stops_byte_range().end
1093    }
1094    fn min_table_bytes(&self) -> &'a [u8] {
1095        let range = self.min_byte_range();
1096        self.data.as_bytes().get(range).unwrap_or_default()
1097    }
1098}
1099
1100impl ReadArgs for ColorLine<'_> {
1101    type Args = ();
1102}
1103
1104impl<'a> FontRead<'a> for ColorLine<'a> {
1105    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1106        #[allow(clippy::absurd_extreme_comparisons)]
1107        if data.len() < Self::MIN_SIZE {
1108            return Err(ReadError::OutOfBounds);
1109        }
1110        Ok(Self { data })
1111    }
1112}
1113
1114/// [ColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table
1115#[derive(Clone)]
1116pub struct ColorLine<'a> {
1117    data: FontData<'a>,
1118}
1119
1120#[allow(clippy::needless_lifetimes)]
1121impl<'a> ColorLine<'a> {
1122    pub const MIN_SIZE: usize = (Extend::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1123    basic_table_impls!(impl_the_methods);
1124
1125    /// An Extend enum value.
1126    pub fn extend(&self) -> Extend {
1127        let range = self.extend_byte_range();
1128        self.data.read_at(range.start).ok().unwrap()
1129    }
1130
1131    /// Number of ColorStop records.
1132    pub fn num_stops(&self) -> u16 {
1133        let range = self.num_stops_byte_range();
1134        self.data.read_at(range.start).ok().unwrap()
1135    }
1136
1137    pub fn color_stops(&self) -> &'a [ColorStop] {
1138        let range = self.color_stops_byte_range();
1139        self.data.read_array(range).ok().unwrap_or_default()
1140    }
1141
1142    pub fn extend_byte_range(&self) -> Range<usize> {
1143        let start = 0;
1144        let end = start + Extend::RAW_BYTE_LEN;
1145        start..end
1146    }
1147
1148    pub fn num_stops_byte_range(&self) -> Range<usize> {
1149        let start = self.extend_byte_range().end;
1150        let end = start + u16::RAW_BYTE_LEN;
1151        start..end
1152    }
1153
1154    pub fn color_stops_byte_range(&self) -> Range<usize> {
1155        let num_stops = self.num_stops();
1156        let start = self.num_stops_byte_range().end;
1157        let end = start + (transforms::to_usize(num_stops)).saturating_mul(ColorStop::RAW_BYTE_LEN);
1158        start..end
1159    }
1160}
1161
1162const _: () = assert!(FontData::default_data_long_enough(ColorLine::MIN_SIZE));
1163
1164impl Default for ColorLine<'_> {
1165    fn default() -> Self {
1166        Self {
1167            data: FontData::default_table_data(),
1168        }
1169    }
1170}
1171
1172impl<'a> MinByteRange<'a> for VarColorLine<'a> {
1173    fn min_byte_range(&self) -> Range<usize> {
1174        0..self.color_stops_byte_range().end
1175    }
1176    fn min_table_bytes(&self) -> &'a [u8] {
1177        let range = self.min_byte_range();
1178        self.data.as_bytes().get(range).unwrap_or_default()
1179    }
1180}
1181
1182impl ReadArgs for VarColorLine<'_> {
1183    type Args = ();
1184}
1185
1186impl<'a> FontRead<'a> for VarColorLine<'a> {
1187    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1188        #[allow(clippy::absurd_extreme_comparisons)]
1189        if data.len() < Self::MIN_SIZE {
1190            return Err(ReadError::OutOfBounds);
1191        }
1192        Ok(Self { data })
1193    }
1194}
1195
1196/// [VarColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table
1197#[derive(Clone)]
1198pub struct VarColorLine<'a> {
1199    data: FontData<'a>,
1200}
1201
1202#[allow(clippy::needless_lifetimes)]
1203impl<'a> VarColorLine<'a> {
1204    pub const MIN_SIZE: usize = (Extend::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1205    basic_table_impls!(impl_the_methods);
1206
1207    /// An Extend enum value.
1208    pub fn extend(&self) -> Extend {
1209        let range = self.extend_byte_range();
1210        self.data.read_at(range.start).ok().unwrap()
1211    }
1212
1213    /// Number of ColorStop records.
1214    pub fn num_stops(&self) -> u16 {
1215        let range = self.num_stops_byte_range();
1216        self.data.read_at(range.start).ok().unwrap()
1217    }
1218
1219    /// Allows for variations.
1220    pub fn color_stops(&self) -> &'a [VarColorStop] {
1221        let range = self.color_stops_byte_range();
1222        self.data.read_array(range).ok().unwrap_or_default()
1223    }
1224
1225    pub fn extend_byte_range(&self) -> Range<usize> {
1226        let start = 0;
1227        let end = start + Extend::RAW_BYTE_LEN;
1228        start..end
1229    }
1230
1231    pub fn num_stops_byte_range(&self) -> Range<usize> {
1232        let start = self.extend_byte_range().end;
1233        let end = start + u16::RAW_BYTE_LEN;
1234        start..end
1235    }
1236
1237    pub fn color_stops_byte_range(&self) -> Range<usize> {
1238        let num_stops = self.num_stops();
1239        let start = self.num_stops_byte_range().end;
1240        let end =
1241            start + (transforms::to_usize(num_stops)).saturating_mul(VarColorStop::RAW_BYTE_LEN);
1242        start..end
1243    }
1244}
1245
1246const _: () = assert!(FontData::default_data_long_enough(VarColorLine::MIN_SIZE));
1247
1248impl Default for VarColorLine<'_> {
1249    fn default() -> Self {
1250        Self {
1251            data: FontData::default_table_data(),
1252        }
1253    }
1254}
1255
1256/// [Extend](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) enumeration
1257#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
1258#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1259#[repr(u8)]
1260#[allow(clippy::manual_non_exhaustive)]
1261pub enum Extend {
1262    #[default]
1263    Pad = 0,
1264    Repeat = 1,
1265    Reflect = 2,
1266    #[doc(hidden)]
1267    /// If font data is malformed we will map unknown values to this variant
1268    Unknown,
1269}
1270
1271impl Extend {
1272    /// Create from a raw scalar.
1273    ///
1274    /// This will never fail; unknown values will be mapped to the `Unknown` variant
1275    pub fn new(raw: u8) -> Self {
1276        match raw {
1277            0 => Self::Pad,
1278            1 => Self::Repeat,
1279            2 => Self::Reflect,
1280            _ => Self::Unknown,
1281        }
1282    }
1283}
1284
1285impl font_types::Scalar for Extend {
1286    type Raw = <u8 as font_types::Scalar>::Raw;
1287    fn to_raw(self) -> Self::Raw {
1288        (self as u8).to_raw()
1289    }
1290    fn from_raw(raw: Self::Raw) -> Self {
1291        let t = <u8>::from_raw(raw);
1292        Self::new(t)
1293    }
1294}
1295
1296/// [Paint](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#paint-tables) tables
1297#[derive(Clone)]
1298pub enum Paint<'a> {
1299    ColrLayers(PaintColrLayers<'a>),
1300    Solid(PaintSolid<'a>),
1301    VarSolid(PaintVarSolid<'a>),
1302    LinearGradient(PaintLinearGradient<'a>),
1303    VarLinearGradient(PaintVarLinearGradient<'a>),
1304    RadialGradient(PaintRadialGradient<'a>),
1305    VarRadialGradient(PaintVarRadialGradient<'a>),
1306    SweepGradient(PaintSweepGradient<'a>),
1307    VarSweepGradient(PaintVarSweepGradient<'a>),
1308    Glyph(PaintGlyph<'a>),
1309    ColrGlyph(PaintColrGlyph<'a>),
1310    Transform(PaintTransform<'a>),
1311    VarTransform(PaintVarTransform<'a>),
1312    Translate(PaintTranslate<'a>),
1313    VarTranslate(PaintVarTranslate<'a>),
1314    Scale(PaintScale<'a>),
1315    VarScale(PaintVarScale<'a>),
1316    ScaleAroundCenter(PaintScaleAroundCenter<'a>),
1317    VarScaleAroundCenter(PaintVarScaleAroundCenter<'a>),
1318    ScaleUniform(PaintScaleUniform<'a>),
1319    VarScaleUniform(PaintVarScaleUniform<'a>),
1320    ScaleUniformAroundCenter(PaintScaleUniformAroundCenter<'a>),
1321    VarScaleUniformAroundCenter(PaintVarScaleUniformAroundCenter<'a>),
1322    Rotate(PaintRotate<'a>),
1323    VarRotate(PaintVarRotate<'a>),
1324    RotateAroundCenter(PaintRotateAroundCenter<'a>),
1325    VarRotateAroundCenter(PaintVarRotateAroundCenter<'a>),
1326    Skew(PaintSkew<'a>),
1327    VarSkew(PaintVarSkew<'a>),
1328    SkewAroundCenter(PaintSkewAroundCenter<'a>),
1329    VarSkewAroundCenter(PaintVarSkewAroundCenter<'a>),
1330    Composite(PaintComposite<'a>),
1331}
1332
1333impl Default for Paint<'_> {
1334    fn default() -> Self {
1335        Self::ColrLayers(Default::default())
1336    }
1337}
1338
1339impl<'a> Paint<'a> {
1340    ///Return the `FontData` used to resolve offsets for this table.
1341    pub fn offset_data(&self) -> FontData<'a> {
1342        match self {
1343            Self::ColrLayers(item) => item.offset_data(),
1344            Self::Solid(item) => item.offset_data(),
1345            Self::VarSolid(item) => item.offset_data(),
1346            Self::LinearGradient(item) => item.offset_data(),
1347            Self::VarLinearGradient(item) => item.offset_data(),
1348            Self::RadialGradient(item) => item.offset_data(),
1349            Self::VarRadialGradient(item) => item.offset_data(),
1350            Self::SweepGradient(item) => item.offset_data(),
1351            Self::VarSweepGradient(item) => item.offset_data(),
1352            Self::Glyph(item) => item.offset_data(),
1353            Self::ColrGlyph(item) => item.offset_data(),
1354            Self::Transform(item) => item.offset_data(),
1355            Self::VarTransform(item) => item.offset_data(),
1356            Self::Translate(item) => item.offset_data(),
1357            Self::VarTranslate(item) => item.offset_data(),
1358            Self::Scale(item) => item.offset_data(),
1359            Self::VarScale(item) => item.offset_data(),
1360            Self::ScaleAroundCenter(item) => item.offset_data(),
1361            Self::VarScaleAroundCenter(item) => item.offset_data(),
1362            Self::ScaleUniform(item) => item.offset_data(),
1363            Self::VarScaleUniform(item) => item.offset_data(),
1364            Self::ScaleUniformAroundCenter(item) => item.offset_data(),
1365            Self::VarScaleUniformAroundCenter(item) => item.offset_data(),
1366            Self::Rotate(item) => item.offset_data(),
1367            Self::VarRotate(item) => item.offset_data(),
1368            Self::RotateAroundCenter(item) => item.offset_data(),
1369            Self::VarRotateAroundCenter(item) => item.offset_data(),
1370            Self::Skew(item) => item.offset_data(),
1371            Self::VarSkew(item) => item.offset_data(),
1372            Self::SkewAroundCenter(item) => item.offset_data(),
1373            Self::VarSkewAroundCenter(item) => item.offset_data(),
1374            Self::Composite(item) => item.offset_data(),
1375        }
1376    }
1377
1378    /// Set to 1.
1379    pub fn format(&self) -> u8 {
1380        match self {
1381            Self::ColrLayers(item) => item.format(),
1382            Self::Solid(item) => item.format(),
1383            Self::VarSolid(item) => item.format(),
1384            Self::LinearGradient(item) => item.format(),
1385            Self::VarLinearGradient(item) => item.format(),
1386            Self::RadialGradient(item) => item.format(),
1387            Self::VarRadialGradient(item) => item.format(),
1388            Self::SweepGradient(item) => item.format(),
1389            Self::VarSweepGradient(item) => item.format(),
1390            Self::Glyph(item) => item.format(),
1391            Self::ColrGlyph(item) => item.format(),
1392            Self::Transform(item) => item.format(),
1393            Self::VarTransform(item) => item.format(),
1394            Self::Translate(item) => item.format(),
1395            Self::VarTranslate(item) => item.format(),
1396            Self::Scale(item) => item.format(),
1397            Self::VarScale(item) => item.format(),
1398            Self::ScaleAroundCenter(item) => item.format(),
1399            Self::VarScaleAroundCenter(item) => item.format(),
1400            Self::ScaleUniform(item) => item.format(),
1401            Self::VarScaleUniform(item) => item.format(),
1402            Self::ScaleUniformAroundCenter(item) => item.format(),
1403            Self::VarScaleUniformAroundCenter(item) => item.format(),
1404            Self::Rotate(item) => item.format(),
1405            Self::VarRotate(item) => item.format(),
1406            Self::RotateAroundCenter(item) => item.format(),
1407            Self::VarRotateAroundCenter(item) => item.format(),
1408            Self::Skew(item) => item.format(),
1409            Self::VarSkew(item) => item.format(),
1410            Self::SkewAroundCenter(item) => item.format(),
1411            Self::VarSkewAroundCenter(item) => item.format(),
1412            Self::Composite(item) => item.format(),
1413        }
1414    }
1415}
1416
1417impl ReadArgs for Paint<'_> {
1418    type Args = ();
1419}
1420
1421impl<'a> FontRead<'a> for Paint<'a> {
1422    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1423        let format: u8 = data.read_at(0usize)?;
1424        match format {
1425            PaintColrLayers::FORMAT => Ok(Self::ColrLayers(FontRead::read(data)?)),
1426            PaintSolid::FORMAT => Ok(Self::Solid(FontRead::read(data)?)),
1427            PaintVarSolid::FORMAT => Ok(Self::VarSolid(FontRead::read(data)?)),
1428            PaintLinearGradient::FORMAT => Ok(Self::LinearGradient(FontRead::read(data)?)),
1429            PaintVarLinearGradient::FORMAT => Ok(Self::VarLinearGradient(FontRead::read(data)?)),
1430            PaintRadialGradient::FORMAT => Ok(Self::RadialGradient(FontRead::read(data)?)),
1431            PaintVarRadialGradient::FORMAT => Ok(Self::VarRadialGradient(FontRead::read(data)?)),
1432            PaintSweepGradient::FORMAT => Ok(Self::SweepGradient(FontRead::read(data)?)),
1433            PaintVarSweepGradient::FORMAT => Ok(Self::VarSweepGradient(FontRead::read(data)?)),
1434            PaintGlyph::FORMAT => Ok(Self::Glyph(FontRead::read(data)?)),
1435            PaintColrGlyph::FORMAT => Ok(Self::ColrGlyph(FontRead::read(data)?)),
1436            PaintTransform::FORMAT => Ok(Self::Transform(FontRead::read(data)?)),
1437            PaintVarTransform::FORMAT => Ok(Self::VarTransform(FontRead::read(data)?)),
1438            PaintTranslate::FORMAT => Ok(Self::Translate(FontRead::read(data)?)),
1439            PaintVarTranslate::FORMAT => Ok(Self::VarTranslate(FontRead::read(data)?)),
1440            PaintScale::FORMAT => Ok(Self::Scale(FontRead::read(data)?)),
1441            PaintVarScale::FORMAT => Ok(Self::VarScale(FontRead::read(data)?)),
1442            PaintScaleAroundCenter::FORMAT => Ok(Self::ScaleAroundCenter(FontRead::read(data)?)),
1443            PaintVarScaleAroundCenter::FORMAT => {
1444                Ok(Self::VarScaleAroundCenter(FontRead::read(data)?))
1445            }
1446            PaintScaleUniform::FORMAT => Ok(Self::ScaleUniform(FontRead::read(data)?)),
1447            PaintVarScaleUniform::FORMAT => Ok(Self::VarScaleUniform(FontRead::read(data)?)),
1448            PaintScaleUniformAroundCenter::FORMAT => {
1449                Ok(Self::ScaleUniformAroundCenter(FontRead::read(data)?))
1450            }
1451            PaintVarScaleUniformAroundCenter::FORMAT => {
1452                Ok(Self::VarScaleUniformAroundCenter(FontRead::read(data)?))
1453            }
1454            PaintRotate::FORMAT => Ok(Self::Rotate(FontRead::read(data)?)),
1455            PaintVarRotate::FORMAT => Ok(Self::VarRotate(FontRead::read(data)?)),
1456            PaintRotateAroundCenter::FORMAT => Ok(Self::RotateAroundCenter(FontRead::read(data)?)),
1457            PaintVarRotateAroundCenter::FORMAT => {
1458                Ok(Self::VarRotateAroundCenter(FontRead::read(data)?))
1459            }
1460            PaintSkew::FORMAT => Ok(Self::Skew(FontRead::read(data)?)),
1461            PaintVarSkew::FORMAT => Ok(Self::VarSkew(FontRead::read(data)?)),
1462            PaintSkewAroundCenter::FORMAT => Ok(Self::SkewAroundCenter(FontRead::read(data)?)),
1463            PaintVarSkewAroundCenter::FORMAT => {
1464                Ok(Self::VarSkewAroundCenter(FontRead::read(data)?))
1465            }
1466            PaintComposite::FORMAT => Ok(Self::Composite(FontRead::read(data)?)),
1467            other => Err(ReadError::InvalidFormat(other.into())),
1468        }
1469    }
1470}
1471
1472impl<'a> MinByteRange<'a> for Paint<'a> {
1473    fn min_byte_range(&self) -> Range<usize> {
1474        match self {
1475            Self::ColrLayers(item) => item.min_byte_range(),
1476            Self::Solid(item) => item.min_byte_range(),
1477            Self::VarSolid(item) => item.min_byte_range(),
1478            Self::LinearGradient(item) => item.min_byte_range(),
1479            Self::VarLinearGradient(item) => item.min_byte_range(),
1480            Self::RadialGradient(item) => item.min_byte_range(),
1481            Self::VarRadialGradient(item) => item.min_byte_range(),
1482            Self::SweepGradient(item) => item.min_byte_range(),
1483            Self::VarSweepGradient(item) => item.min_byte_range(),
1484            Self::Glyph(item) => item.min_byte_range(),
1485            Self::ColrGlyph(item) => item.min_byte_range(),
1486            Self::Transform(item) => item.min_byte_range(),
1487            Self::VarTransform(item) => item.min_byte_range(),
1488            Self::Translate(item) => item.min_byte_range(),
1489            Self::VarTranslate(item) => item.min_byte_range(),
1490            Self::Scale(item) => item.min_byte_range(),
1491            Self::VarScale(item) => item.min_byte_range(),
1492            Self::ScaleAroundCenter(item) => item.min_byte_range(),
1493            Self::VarScaleAroundCenter(item) => item.min_byte_range(),
1494            Self::ScaleUniform(item) => item.min_byte_range(),
1495            Self::VarScaleUniform(item) => item.min_byte_range(),
1496            Self::ScaleUniformAroundCenter(item) => item.min_byte_range(),
1497            Self::VarScaleUniformAroundCenter(item) => item.min_byte_range(),
1498            Self::Rotate(item) => item.min_byte_range(),
1499            Self::VarRotate(item) => item.min_byte_range(),
1500            Self::RotateAroundCenter(item) => item.min_byte_range(),
1501            Self::VarRotateAroundCenter(item) => item.min_byte_range(),
1502            Self::Skew(item) => item.min_byte_range(),
1503            Self::VarSkew(item) => item.min_byte_range(),
1504            Self::SkewAroundCenter(item) => item.min_byte_range(),
1505            Self::VarSkewAroundCenter(item) => item.min_byte_range(),
1506            Self::Composite(item) => item.min_byte_range(),
1507        }
1508    }
1509    fn min_table_bytes(&self) -> &'a [u8] {
1510        match self {
1511            Self::ColrLayers(item) => item.min_table_bytes(),
1512            Self::Solid(item) => item.min_table_bytes(),
1513            Self::VarSolid(item) => item.min_table_bytes(),
1514            Self::LinearGradient(item) => item.min_table_bytes(),
1515            Self::VarLinearGradient(item) => item.min_table_bytes(),
1516            Self::RadialGradient(item) => item.min_table_bytes(),
1517            Self::VarRadialGradient(item) => item.min_table_bytes(),
1518            Self::SweepGradient(item) => item.min_table_bytes(),
1519            Self::VarSweepGradient(item) => item.min_table_bytes(),
1520            Self::Glyph(item) => item.min_table_bytes(),
1521            Self::ColrGlyph(item) => item.min_table_bytes(),
1522            Self::Transform(item) => item.min_table_bytes(),
1523            Self::VarTransform(item) => item.min_table_bytes(),
1524            Self::Translate(item) => item.min_table_bytes(),
1525            Self::VarTranslate(item) => item.min_table_bytes(),
1526            Self::Scale(item) => item.min_table_bytes(),
1527            Self::VarScale(item) => item.min_table_bytes(),
1528            Self::ScaleAroundCenter(item) => item.min_table_bytes(),
1529            Self::VarScaleAroundCenter(item) => item.min_table_bytes(),
1530            Self::ScaleUniform(item) => item.min_table_bytes(),
1531            Self::VarScaleUniform(item) => item.min_table_bytes(),
1532            Self::ScaleUniformAroundCenter(item) => item.min_table_bytes(),
1533            Self::VarScaleUniformAroundCenter(item) => item.min_table_bytes(),
1534            Self::Rotate(item) => item.min_table_bytes(),
1535            Self::VarRotate(item) => item.min_table_bytes(),
1536            Self::RotateAroundCenter(item) => item.min_table_bytes(),
1537            Self::VarRotateAroundCenter(item) => item.min_table_bytes(),
1538            Self::Skew(item) => item.min_table_bytes(),
1539            Self::VarSkew(item) => item.min_table_bytes(),
1540            Self::SkewAroundCenter(item) => item.min_table_bytes(),
1541            Self::VarSkewAroundCenter(item) => item.min_table_bytes(),
1542            Self::Composite(item) => item.min_table_bytes(),
1543        }
1544    }
1545}
1546
1547impl Format<u8> for PaintColrLayers<'_> {
1548    const FORMAT: u8 = 1;
1549}
1550
1551impl<'a> MinByteRange<'a> for PaintColrLayers<'a> {
1552    fn min_byte_range(&self) -> Range<usize> {
1553        0..self.first_layer_index_byte_range().end
1554    }
1555    fn min_table_bytes(&self) -> &'a [u8] {
1556        let range = self.min_byte_range();
1557        self.data.as_bytes().get(range).unwrap_or_default()
1558    }
1559}
1560
1561impl ReadArgs for PaintColrLayers<'_> {
1562    type Args = ();
1563}
1564
1565impl<'a> FontRead<'a> for PaintColrLayers<'a> {
1566    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1567        #[allow(clippy::absurd_extreme_comparisons)]
1568        if data.len() < Self::MIN_SIZE {
1569            return Err(ReadError::OutOfBounds);
1570        }
1571        Ok(Self { data })
1572    }
1573}
1574
1575/// [PaintColrLayers](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-1-paintcolrlayers) table
1576#[derive(Clone)]
1577pub struct PaintColrLayers<'a> {
1578    data: FontData<'a>,
1579}
1580
1581#[allow(clippy::needless_lifetimes)]
1582impl<'a> PaintColrLayers<'a> {
1583    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1584    basic_table_impls!(impl_the_methods);
1585
1586    /// Set to 1.
1587    pub fn format(&self) -> u8 {
1588        let range = self.format_byte_range();
1589        self.data.read_at(range.start).ok().unwrap()
1590    }
1591
1592    /// Number of offsets to paint tables to read from LayerList.
1593    pub fn num_layers(&self) -> u8 {
1594        let range = self.num_layers_byte_range();
1595        self.data.read_at(range.start).ok().unwrap()
1596    }
1597
1598    /// Index (base 0) into the LayerList.
1599    pub fn first_layer_index(&self) -> u32 {
1600        let range = self.first_layer_index_byte_range();
1601        self.data.read_at(range.start).ok().unwrap()
1602    }
1603
1604    pub fn format_byte_range(&self) -> Range<usize> {
1605        let start = 0;
1606        let end = start + u8::RAW_BYTE_LEN;
1607        start..end
1608    }
1609
1610    pub fn num_layers_byte_range(&self) -> Range<usize> {
1611        let start = self.format_byte_range().end;
1612        let end = start + u8::RAW_BYTE_LEN;
1613        start..end
1614    }
1615
1616    pub fn first_layer_index_byte_range(&self) -> Range<usize> {
1617        let start = self.num_layers_byte_range().end;
1618        let end = start + u32::RAW_BYTE_LEN;
1619        start..end
1620    }
1621}
1622
1623const _: () = assert!(FontData::default_data_long_enough(
1624    PaintColrLayers::MIN_SIZE
1625));
1626
1627impl Default for PaintColrLayers<'_> {
1628    fn default() -> Self {
1629        Self {
1630            data: FontData::default_format_1_u8_table_data(),
1631        }
1632    }
1633}
1634
1635impl Format<u8> for PaintSolid<'_> {
1636    const FORMAT: u8 = 2;
1637}
1638
1639impl<'a> MinByteRange<'a> for PaintSolid<'a> {
1640    fn min_byte_range(&self) -> Range<usize> {
1641        0..self.alpha_byte_range().end
1642    }
1643    fn min_table_bytes(&self) -> &'a [u8] {
1644        let range = self.min_byte_range();
1645        self.data.as_bytes().get(range).unwrap_or_default()
1646    }
1647}
1648
1649impl ReadArgs for PaintSolid<'_> {
1650    type Args = ();
1651}
1652
1653impl<'a> FontRead<'a> for PaintSolid<'a> {
1654    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1655        #[allow(clippy::absurd_extreme_comparisons)]
1656        if data.len() < Self::MIN_SIZE {
1657            return Err(ReadError::OutOfBounds);
1658        }
1659        Ok(Self { data })
1660    }
1661}
1662
1663/// [PaintSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table
1664#[derive(Clone)]
1665pub struct PaintSolid<'a> {
1666    data: FontData<'a>,
1667}
1668
1669#[allow(clippy::needless_lifetimes)]
1670impl<'a> PaintSolid<'a> {
1671    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
1672    basic_table_impls!(impl_the_methods);
1673
1674    /// Set to 2.
1675    pub fn format(&self) -> u8 {
1676        let range = self.format_byte_range();
1677        self.data.read_at(range.start).ok().unwrap()
1678    }
1679
1680    /// Index for a CPAL palette entry.
1681    pub fn palette_index(&self) -> u16 {
1682        let range = self.palette_index_byte_range();
1683        self.data.read_at(range.start).ok().unwrap()
1684    }
1685
1686    /// Alpha value.
1687    pub fn alpha(&self) -> F2Dot14 {
1688        let range = self.alpha_byte_range();
1689        self.data.read_at(range.start).ok().unwrap()
1690    }
1691
1692    pub fn format_byte_range(&self) -> Range<usize> {
1693        let start = 0;
1694        let end = start + u8::RAW_BYTE_LEN;
1695        start..end
1696    }
1697
1698    pub fn palette_index_byte_range(&self) -> Range<usize> {
1699        let start = self.format_byte_range().end;
1700        let end = start + u16::RAW_BYTE_LEN;
1701        start..end
1702    }
1703
1704    pub fn alpha_byte_range(&self) -> Range<usize> {
1705        let start = self.palette_index_byte_range().end;
1706        let end = start + F2Dot14::RAW_BYTE_LEN;
1707        start..end
1708    }
1709}
1710
1711impl Format<u8> for PaintVarSolid<'_> {
1712    const FORMAT: u8 = 3;
1713}
1714
1715impl<'a> MinByteRange<'a> for PaintVarSolid<'a> {
1716    fn min_byte_range(&self) -> Range<usize> {
1717        0..self.var_index_base_byte_range().end
1718    }
1719    fn min_table_bytes(&self) -> &'a [u8] {
1720        let range = self.min_byte_range();
1721        self.data.as_bytes().get(range).unwrap_or_default()
1722    }
1723}
1724
1725impl ReadArgs for PaintVarSolid<'_> {
1726    type Args = ();
1727}
1728
1729impl<'a> FontRead<'a> for PaintVarSolid<'a> {
1730    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1731        #[allow(clippy::absurd_extreme_comparisons)]
1732        if data.len() < Self::MIN_SIZE {
1733            return Err(ReadError::OutOfBounds);
1734        }
1735        Ok(Self { data })
1736    }
1737}
1738
1739/// [PaintVarSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table
1740#[derive(Clone)]
1741pub struct PaintVarSolid<'a> {
1742    data: FontData<'a>,
1743}
1744
1745#[allow(clippy::needless_lifetimes)]
1746impl<'a> PaintVarSolid<'a> {
1747    pub const MIN_SIZE: usize =
1748        (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1749    basic_table_impls!(impl_the_methods);
1750
1751    /// Set to 3.
1752    pub fn format(&self) -> u8 {
1753        let range = self.format_byte_range();
1754        self.data.read_at(range.start).ok().unwrap()
1755    }
1756
1757    /// Index for a CPAL palette entry.
1758    pub fn palette_index(&self) -> u16 {
1759        let range = self.palette_index_byte_range();
1760        self.data.read_at(range.start).ok().unwrap()
1761    }
1762
1763    /// Alpha value. For variation, use varIndexBase + 0.
1764    pub fn alpha(&self) -> F2Dot14 {
1765        let range = self.alpha_byte_range();
1766        self.data.read_at(range.start).ok().unwrap()
1767    }
1768
1769    /// Base index into DeltaSetIndexMap.
1770    pub fn var_index_base(&self) -> u32 {
1771        let range = self.var_index_base_byte_range();
1772        self.data.read_at(range.start).ok().unwrap()
1773    }
1774
1775    pub fn format_byte_range(&self) -> Range<usize> {
1776        let start = 0;
1777        let end = start + u8::RAW_BYTE_LEN;
1778        start..end
1779    }
1780
1781    pub fn palette_index_byte_range(&self) -> Range<usize> {
1782        let start = self.format_byte_range().end;
1783        let end = start + u16::RAW_BYTE_LEN;
1784        start..end
1785    }
1786
1787    pub fn alpha_byte_range(&self) -> Range<usize> {
1788        let start = self.palette_index_byte_range().end;
1789        let end = start + F2Dot14::RAW_BYTE_LEN;
1790        start..end
1791    }
1792
1793    pub fn var_index_base_byte_range(&self) -> Range<usize> {
1794        let start = self.alpha_byte_range().end;
1795        let end = start + u32::RAW_BYTE_LEN;
1796        start..end
1797    }
1798}
1799
1800impl Format<u8> for PaintLinearGradient<'_> {
1801    const FORMAT: u8 = 4;
1802}
1803
1804impl<'a> MinByteRange<'a> for PaintLinearGradient<'a> {
1805    fn min_byte_range(&self) -> Range<usize> {
1806        0..self.y2_byte_range().end
1807    }
1808    fn min_table_bytes(&self) -> &'a [u8] {
1809        let range = self.min_byte_range();
1810        self.data.as_bytes().get(range).unwrap_or_default()
1811    }
1812}
1813
1814impl ReadArgs for PaintLinearGradient<'_> {
1815    type Args = ();
1816}
1817
1818impl<'a> FontRead<'a> for PaintLinearGradient<'a> {
1819    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1820        #[allow(clippy::absurd_extreme_comparisons)]
1821        if data.len() < Self::MIN_SIZE {
1822            return Err(ReadError::OutOfBounds);
1823        }
1824        Ok(Self { data })
1825    }
1826}
1827
1828/// [PaintLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table
1829#[derive(Clone)]
1830pub struct PaintLinearGradient<'a> {
1831    data: FontData<'a>,
1832}
1833
1834#[allow(clippy::needless_lifetimes)]
1835impl<'a> PaintLinearGradient<'a> {
1836    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
1837        + Offset24::RAW_BYTE_LEN
1838        + FWord::RAW_BYTE_LEN
1839        + FWord::RAW_BYTE_LEN
1840        + FWord::RAW_BYTE_LEN
1841        + FWord::RAW_BYTE_LEN
1842        + FWord::RAW_BYTE_LEN
1843        + FWord::RAW_BYTE_LEN);
1844    basic_table_impls!(impl_the_methods);
1845
1846    /// Set to 4.
1847    pub fn format(&self) -> u8 {
1848        let range = self.format_byte_range();
1849        self.data.read_at(range.start).ok().unwrap()
1850    }
1851
1852    /// Offset to ColorLine table.
1853    pub fn color_line_offset(&self) -> Offset24 {
1854        let range = self.color_line_offset_byte_range();
1855        self.data.read_at(range.start).ok().unwrap()
1856    }
1857
1858    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
1859    pub fn color_line(&self) -> Result<ColorLine<'a>, ReadError> {
1860        let data = self.data;
1861        self.color_line_offset().resolve(data)
1862    }
1863
1864    /// Start point (p₀) x coordinate.
1865    pub fn x0(&self) -> FWord {
1866        let range = self.x0_byte_range();
1867        self.data.read_at(range.start).ok().unwrap()
1868    }
1869
1870    /// Start point (p₀) y coordinate.
1871    pub fn y0(&self) -> FWord {
1872        let range = self.y0_byte_range();
1873        self.data.read_at(range.start).ok().unwrap()
1874    }
1875
1876    /// End point (p₁) x coordinate.
1877    pub fn x1(&self) -> FWord {
1878        let range = self.x1_byte_range();
1879        self.data.read_at(range.start).ok().unwrap()
1880    }
1881
1882    /// End point (p₁) y coordinate.
1883    pub fn y1(&self) -> FWord {
1884        let range = self.y1_byte_range();
1885        self.data.read_at(range.start).ok().unwrap()
1886    }
1887
1888    /// Rotation point (p₂) x coordinate.
1889    pub fn x2(&self) -> FWord {
1890        let range = self.x2_byte_range();
1891        self.data.read_at(range.start).ok().unwrap()
1892    }
1893
1894    /// Rotation point (p₂) y coordinate.
1895    pub fn y2(&self) -> FWord {
1896        let range = self.y2_byte_range();
1897        self.data.read_at(range.start).ok().unwrap()
1898    }
1899
1900    pub fn format_byte_range(&self) -> Range<usize> {
1901        let start = 0;
1902        let end = start + u8::RAW_BYTE_LEN;
1903        start..end
1904    }
1905
1906    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
1907        let start = self.format_byte_range().end;
1908        let end = start + Offset24::RAW_BYTE_LEN;
1909        start..end
1910    }
1911
1912    pub fn x0_byte_range(&self) -> Range<usize> {
1913        let start = self.color_line_offset_byte_range().end;
1914        let end = start + FWord::RAW_BYTE_LEN;
1915        start..end
1916    }
1917
1918    pub fn y0_byte_range(&self) -> Range<usize> {
1919        let start = self.x0_byte_range().end;
1920        let end = start + FWord::RAW_BYTE_LEN;
1921        start..end
1922    }
1923
1924    pub fn x1_byte_range(&self) -> Range<usize> {
1925        let start = self.y0_byte_range().end;
1926        let end = start + FWord::RAW_BYTE_LEN;
1927        start..end
1928    }
1929
1930    pub fn y1_byte_range(&self) -> Range<usize> {
1931        let start = self.x1_byte_range().end;
1932        let end = start + FWord::RAW_BYTE_LEN;
1933        start..end
1934    }
1935
1936    pub fn x2_byte_range(&self) -> Range<usize> {
1937        let start = self.y1_byte_range().end;
1938        let end = start + FWord::RAW_BYTE_LEN;
1939        start..end
1940    }
1941
1942    pub fn y2_byte_range(&self) -> Range<usize> {
1943        let start = self.x2_byte_range().end;
1944        let end = start + FWord::RAW_BYTE_LEN;
1945        start..end
1946    }
1947}
1948
1949impl Format<u8> for PaintVarLinearGradient<'_> {
1950    const FORMAT: u8 = 5;
1951}
1952
1953impl<'a> MinByteRange<'a> for PaintVarLinearGradient<'a> {
1954    fn min_byte_range(&self) -> Range<usize> {
1955        0..self.var_index_base_byte_range().end
1956    }
1957    fn min_table_bytes(&self) -> &'a [u8] {
1958        let range = self.min_byte_range();
1959        self.data.as_bytes().get(range).unwrap_or_default()
1960    }
1961}
1962
1963impl ReadArgs for PaintVarLinearGradient<'_> {
1964    type Args = ();
1965}
1966
1967impl<'a> FontRead<'a> for PaintVarLinearGradient<'a> {
1968    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1969        #[allow(clippy::absurd_extreme_comparisons)]
1970        if data.len() < Self::MIN_SIZE {
1971            return Err(ReadError::OutOfBounds);
1972        }
1973        Ok(Self { data })
1974    }
1975}
1976
1977/// [PaintVarLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table
1978#[derive(Clone)]
1979pub struct PaintVarLinearGradient<'a> {
1980    data: FontData<'a>,
1981}
1982
1983#[allow(clippy::needless_lifetimes)]
1984impl<'a> PaintVarLinearGradient<'a> {
1985    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
1986        + Offset24::RAW_BYTE_LEN
1987        + FWord::RAW_BYTE_LEN
1988        + FWord::RAW_BYTE_LEN
1989        + FWord::RAW_BYTE_LEN
1990        + FWord::RAW_BYTE_LEN
1991        + FWord::RAW_BYTE_LEN
1992        + FWord::RAW_BYTE_LEN
1993        + u32::RAW_BYTE_LEN);
1994    basic_table_impls!(impl_the_methods);
1995
1996    /// Set to 5.
1997    pub fn format(&self) -> u8 {
1998        let range = self.format_byte_range();
1999        self.data.read_at(range.start).ok().unwrap()
2000    }
2001
2002    /// Offset to VarColorLine table.
2003    pub fn color_line_offset(&self) -> Offset24 {
2004        let range = self.color_line_offset_byte_range();
2005        self.data.read_at(range.start).ok().unwrap()
2006    }
2007
2008    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
2009    pub fn color_line(&self) -> Result<VarColorLine<'a>, ReadError> {
2010        let data = self.data;
2011        self.color_line_offset().resolve(data)
2012    }
2013
2014    /// Start point (p₀) x coordinate. For variation, use
2015    /// varIndexBase + 0.
2016    pub fn x0(&self) -> FWord {
2017        let range = self.x0_byte_range();
2018        self.data.read_at(range.start).ok().unwrap()
2019    }
2020
2021    /// Start point (p₀) y coordinate. For variation, use
2022    /// varIndexBase + 1.
2023    pub fn y0(&self) -> FWord {
2024        let range = self.y0_byte_range();
2025        self.data.read_at(range.start).ok().unwrap()
2026    }
2027
2028    /// End point (p₁) x coordinate. For variation, use varIndexBase
2029    /// + 2.
2030    pub fn x1(&self) -> FWord {
2031        let range = self.x1_byte_range();
2032        self.data.read_at(range.start).ok().unwrap()
2033    }
2034
2035    /// End point (p₁) y coordinate. For variation, use varIndexBase
2036    /// + 3.
2037    pub fn y1(&self) -> FWord {
2038        let range = self.y1_byte_range();
2039        self.data.read_at(range.start).ok().unwrap()
2040    }
2041
2042    /// Rotation point (p₂) x coordinate. For variation, use
2043    /// varIndexBase + 4.
2044    pub fn x2(&self) -> FWord {
2045        let range = self.x2_byte_range();
2046        self.data.read_at(range.start).ok().unwrap()
2047    }
2048
2049    /// Rotation point (p₂) y coordinate. For variation, use
2050    /// varIndexBase + 5.
2051    pub fn y2(&self) -> FWord {
2052        let range = self.y2_byte_range();
2053        self.data.read_at(range.start).ok().unwrap()
2054    }
2055
2056    /// Base index into DeltaSetIndexMap.
2057    pub fn var_index_base(&self) -> u32 {
2058        let range = self.var_index_base_byte_range();
2059        self.data.read_at(range.start).ok().unwrap()
2060    }
2061
2062    pub fn format_byte_range(&self) -> Range<usize> {
2063        let start = 0;
2064        let end = start + u8::RAW_BYTE_LEN;
2065        start..end
2066    }
2067
2068    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
2069        let start = self.format_byte_range().end;
2070        let end = start + Offset24::RAW_BYTE_LEN;
2071        start..end
2072    }
2073
2074    pub fn x0_byte_range(&self) -> Range<usize> {
2075        let start = self.color_line_offset_byte_range().end;
2076        let end = start + FWord::RAW_BYTE_LEN;
2077        start..end
2078    }
2079
2080    pub fn y0_byte_range(&self) -> Range<usize> {
2081        let start = self.x0_byte_range().end;
2082        let end = start + FWord::RAW_BYTE_LEN;
2083        start..end
2084    }
2085
2086    pub fn x1_byte_range(&self) -> Range<usize> {
2087        let start = self.y0_byte_range().end;
2088        let end = start + FWord::RAW_BYTE_LEN;
2089        start..end
2090    }
2091
2092    pub fn y1_byte_range(&self) -> Range<usize> {
2093        let start = self.x1_byte_range().end;
2094        let end = start + FWord::RAW_BYTE_LEN;
2095        start..end
2096    }
2097
2098    pub fn x2_byte_range(&self) -> Range<usize> {
2099        let start = self.y1_byte_range().end;
2100        let end = start + FWord::RAW_BYTE_LEN;
2101        start..end
2102    }
2103
2104    pub fn y2_byte_range(&self) -> Range<usize> {
2105        let start = self.x2_byte_range().end;
2106        let end = start + FWord::RAW_BYTE_LEN;
2107        start..end
2108    }
2109
2110    pub fn var_index_base_byte_range(&self) -> Range<usize> {
2111        let start = self.y2_byte_range().end;
2112        let end = start + u32::RAW_BYTE_LEN;
2113        start..end
2114    }
2115}
2116
2117impl Format<u8> for PaintRadialGradient<'_> {
2118    const FORMAT: u8 = 6;
2119}
2120
2121impl<'a> MinByteRange<'a> for PaintRadialGradient<'a> {
2122    fn min_byte_range(&self) -> Range<usize> {
2123        0..self.radius1_byte_range().end
2124    }
2125    fn min_table_bytes(&self) -> &'a [u8] {
2126        let range = self.min_byte_range();
2127        self.data.as_bytes().get(range).unwrap_or_default()
2128    }
2129}
2130
2131impl ReadArgs for PaintRadialGradient<'_> {
2132    type Args = ();
2133}
2134
2135impl<'a> FontRead<'a> for PaintRadialGradient<'a> {
2136    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2137        #[allow(clippy::absurd_extreme_comparisons)]
2138        if data.len() < Self::MIN_SIZE {
2139            return Err(ReadError::OutOfBounds);
2140        }
2141        Ok(Self { data })
2142    }
2143}
2144
2145/// [PaintRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table
2146#[derive(Clone)]
2147pub struct PaintRadialGradient<'a> {
2148    data: FontData<'a>,
2149}
2150
2151#[allow(clippy::needless_lifetimes)]
2152impl<'a> PaintRadialGradient<'a> {
2153    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
2154        + Offset24::RAW_BYTE_LEN
2155        + FWord::RAW_BYTE_LEN
2156        + FWord::RAW_BYTE_LEN
2157        + UfWord::RAW_BYTE_LEN
2158        + FWord::RAW_BYTE_LEN
2159        + FWord::RAW_BYTE_LEN
2160        + UfWord::RAW_BYTE_LEN);
2161    basic_table_impls!(impl_the_methods);
2162
2163    /// Set to 6.
2164    pub fn format(&self) -> u8 {
2165        let range = self.format_byte_range();
2166        self.data.read_at(range.start).ok().unwrap()
2167    }
2168
2169    /// Offset to ColorLine table.
2170    pub fn color_line_offset(&self) -> Offset24 {
2171        let range = self.color_line_offset_byte_range();
2172        self.data.read_at(range.start).ok().unwrap()
2173    }
2174
2175    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
2176    pub fn color_line(&self) -> Result<ColorLine<'a>, ReadError> {
2177        let data = self.data;
2178        self.color_line_offset().resolve(data)
2179    }
2180
2181    /// Start circle center x coordinate.
2182    pub fn x0(&self) -> FWord {
2183        let range = self.x0_byte_range();
2184        self.data.read_at(range.start).ok().unwrap()
2185    }
2186
2187    /// Start circle center y coordinate.
2188    pub fn y0(&self) -> FWord {
2189        let range = self.y0_byte_range();
2190        self.data.read_at(range.start).ok().unwrap()
2191    }
2192
2193    /// Start circle radius.
2194    pub fn radius0(&self) -> UfWord {
2195        let range = self.radius0_byte_range();
2196        self.data.read_at(range.start).ok().unwrap()
2197    }
2198
2199    /// End circle center x coordinate.
2200    pub fn x1(&self) -> FWord {
2201        let range = self.x1_byte_range();
2202        self.data.read_at(range.start).ok().unwrap()
2203    }
2204
2205    /// End circle center y coordinate.
2206    pub fn y1(&self) -> FWord {
2207        let range = self.y1_byte_range();
2208        self.data.read_at(range.start).ok().unwrap()
2209    }
2210
2211    /// End circle radius.
2212    pub fn radius1(&self) -> UfWord {
2213        let range = self.radius1_byte_range();
2214        self.data.read_at(range.start).ok().unwrap()
2215    }
2216
2217    pub fn format_byte_range(&self) -> Range<usize> {
2218        let start = 0;
2219        let end = start + u8::RAW_BYTE_LEN;
2220        start..end
2221    }
2222
2223    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
2224        let start = self.format_byte_range().end;
2225        let end = start + Offset24::RAW_BYTE_LEN;
2226        start..end
2227    }
2228
2229    pub fn x0_byte_range(&self) -> Range<usize> {
2230        let start = self.color_line_offset_byte_range().end;
2231        let end = start + FWord::RAW_BYTE_LEN;
2232        start..end
2233    }
2234
2235    pub fn y0_byte_range(&self) -> Range<usize> {
2236        let start = self.x0_byte_range().end;
2237        let end = start + FWord::RAW_BYTE_LEN;
2238        start..end
2239    }
2240
2241    pub fn radius0_byte_range(&self) -> Range<usize> {
2242        let start = self.y0_byte_range().end;
2243        let end = start + UfWord::RAW_BYTE_LEN;
2244        start..end
2245    }
2246
2247    pub fn x1_byte_range(&self) -> Range<usize> {
2248        let start = self.radius0_byte_range().end;
2249        let end = start + FWord::RAW_BYTE_LEN;
2250        start..end
2251    }
2252
2253    pub fn y1_byte_range(&self) -> Range<usize> {
2254        let start = self.x1_byte_range().end;
2255        let end = start + FWord::RAW_BYTE_LEN;
2256        start..end
2257    }
2258
2259    pub fn radius1_byte_range(&self) -> Range<usize> {
2260        let start = self.y1_byte_range().end;
2261        let end = start + UfWord::RAW_BYTE_LEN;
2262        start..end
2263    }
2264}
2265
2266impl Format<u8> for PaintVarRadialGradient<'_> {
2267    const FORMAT: u8 = 7;
2268}
2269
2270impl<'a> MinByteRange<'a> for PaintVarRadialGradient<'a> {
2271    fn min_byte_range(&self) -> Range<usize> {
2272        0..self.var_index_base_byte_range().end
2273    }
2274    fn min_table_bytes(&self) -> &'a [u8] {
2275        let range = self.min_byte_range();
2276        self.data.as_bytes().get(range).unwrap_or_default()
2277    }
2278}
2279
2280impl ReadArgs for PaintVarRadialGradient<'_> {
2281    type Args = ();
2282}
2283
2284impl<'a> FontRead<'a> for PaintVarRadialGradient<'a> {
2285    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2286        #[allow(clippy::absurd_extreme_comparisons)]
2287        if data.len() < Self::MIN_SIZE {
2288            return Err(ReadError::OutOfBounds);
2289        }
2290        Ok(Self { data })
2291    }
2292}
2293
2294/// [PaintVarRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table
2295#[derive(Clone)]
2296pub struct PaintVarRadialGradient<'a> {
2297    data: FontData<'a>,
2298}
2299
2300#[allow(clippy::needless_lifetimes)]
2301impl<'a> PaintVarRadialGradient<'a> {
2302    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
2303        + Offset24::RAW_BYTE_LEN
2304        + FWord::RAW_BYTE_LEN
2305        + FWord::RAW_BYTE_LEN
2306        + UfWord::RAW_BYTE_LEN
2307        + FWord::RAW_BYTE_LEN
2308        + FWord::RAW_BYTE_LEN
2309        + UfWord::RAW_BYTE_LEN
2310        + u32::RAW_BYTE_LEN);
2311    basic_table_impls!(impl_the_methods);
2312
2313    /// Set to 7.
2314    pub fn format(&self) -> u8 {
2315        let range = self.format_byte_range();
2316        self.data.read_at(range.start).ok().unwrap()
2317    }
2318
2319    /// Offset to VarColorLine table.
2320    pub fn color_line_offset(&self) -> Offset24 {
2321        let range = self.color_line_offset_byte_range();
2322        self.data.read_at(range.start).ok().unwrap()
2323    }
2324
2325    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
2326    pub fn color_line(&self) -> Result<VarColorLine<'a>, ReadError> {
2327        let data = self.data;
2328        self.color_line_offset().resolve(data)
2329    }
2330
2331    /// Start circle center x coordinate. For variation, use
2332    /// varIndexBase + 0.
2333    pub fn x0(&self) -> FWord {
2334        let range = self.x0_byte_range();
2335        self.data.read_at(range.start).ok().unwrap()
2336    }
2337
2338    /// Start circle center y coordinate. For variation, use
2339    /// varIndexBase + 1.
2340    pub fn y0(&self) -> FWord {
2341        let range = self.y0_byte_range();
2342        self.data.read_at(range.start).ok().unwrap()
2343    }
2344
2345    /// Start circle radius. For variation, use varIndexBase + 2.
2346    pub fn radius0(&self) -> UfWord {
2347        let range = self.radius0_byte_range();
2348        self.data.read_at(range.start).ok().unwrap()
2349    }
2350
2351    /// End circle center x coordinate. For variation, use varIndexBase
2352    /// + 3.
2353    pub fn x1(&self) -> FWord {
2354        let range = self.x1_byte_range();
2355        self.data.read_at(range.start).ok().unwrap()
2356    }
2357
2358    /// End circle center y coordinate. For variation, use varIndexBase
2359    /// + 4.
2360    pub fn y1(&self) -> FWord {
2361        let range = self.y1_byte_range();
2362        self.data.read_at(range.start).ok().unwrap()
2363    }
2364
2365    /// End circle radius. For variation, use varIndexBase + 5.
2366    pub fn radius1(&self) -> UfWord {
2367        let range = self.radius1_byte_range();
2368        self.data.read_at(range.start).ok().unwrap()
2369    }
2370
2371    /// Base index into DeltaSetIndexMap.
2372    pub fn var_index_base(&self) -> u32 {
2373        let range = self.var_index_base_byte_range();
2374        self.data.read_at(range.start).ok().unwrap()
2375    }
2376
2377    pub fn format_byte_range(&self) -> Range<usize> {
2378        let start = 0;
2379        let end = start + u8::RAW_BYTE_LEN;
2380        start..end
2381    }
2382
2383    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
2384        let start = self.format_byte_range().end;
2385        let end = start + Offset24::RAW_BYTE_LEN;
2386        start..end
2387    }
2388
2389    pub fn x0_byte_range(&self) -> Range<usize> {
2390        let start = self.color_line_offset_byte_range().end;
2391        let end = start + FWord::RAW_BYTE_LEN;
2392        start..end
2393    }
2394
2395    pub fn y0_byte_range(&self) -> Range<usize> {
2396        let start = self.x0_byte_range().end;
2397        let end = start + FWord::RAW_BYTE_LEN;
2398        start..end
2399    }
2400
2401    pub fn radius0_byte_range(&self) -> Range<usize> {
2402        let start = self.y0_byte_range().end;
2403        let end = start + UfWord::RAW_BYTE_LEN;
2404        start..end
2405    }
2406
2407    pub fn x1_byte_range(&self) -> Range<usize> {
2408        let start = self.radius0_byte_range().end;
2409        let end = start + FWord::RAW_BYTE_LEN;
2410        start..end
2411    }
2412
2413    pub fn y1_byte_range(&self) -> Range<usize> {
2414        let start = self.x1_byte_range().end;
2415        let end = start + FWord::RAW_BYTE_LEN;
2416        start..end
2417    }
2418
2419    pub fn radius1_byte_range(&self) -> Range<usize> {
2420        let start = self.y1_byte_range().end;
2421        let end = start + UfWord::RAW_BYTE_LEN;
2422        start..end
2423    }
2424
2425    pub fn var_index_base_byte_range(&self) -> Range<usize> {
2426        let start = self.radius1_byte_range().end;
2427        let end = start + u32::RAW_BYTE_LEN;
2428        start..end
2429    }
2430}
2431
2432impl Format<u8> for PaintSweepGradient<'_> {
2433    const FORMAT: u8 = 8;
2434}
2435
2436impl<'a> MinByteRange<'a> for PaintSweepGradient<'a> {
2437    fn min_byte_range(&self) -> Range<usize> {
2438        0..self.end_angle_byte_range().end
2439    }
2440    fn min_table_bytes(&self) -> &'a [u8] {
2441        let range = self.min_byte_range();
2442        self.data.as_bytes().get(range).unwrap_or_default()
2443    }
2444}
2445
2446impl ReadArgs for PaintSweepGradient<'_> {
2447    type Args = ();
2448}
2449
2450impl<'a> FontRead<'a> for PaintSweepGradient<'a> {
2451    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2452        #[allow(clippy::absurd_extreme_comparisons)]
2453        if data.len() < Self::MIN_SIZE {
2454            return Err(ReadError::OutOfBounds);
2455        }
2456        Ok(Self { data })
2457    }
2458}
2459
2460/// [PaintSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table
2461#[derive(Clone)]
2462pub struct PaintSweepGradient<'a> {
2463    data: FontData<'a>,
2464}
2465
2466#[allow(clippy::needless_lifetimes)]
2467impl<'a> PaintSweepGradient<'a> {
2468    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
2469        + Offset24::RAW_BYTE_LEN
2470        + FWord::RAW_BYTE_LEN
2471        + FWord::RAW_BYTE_LEN
2472        + F2Dot14::RAW_BYTE_LEN
2473        + F2Dot14::RAW_BYTE_LEN);
2474    basic_table_impls!(impl_the_methods);
2475
2476    /// Set to 8.
2477    pub fn format(&self) -> u8 {
2478        let range = self.format_byte_range();
2479        self.data.read_at(range.start).ok().unwrap()
2480    }
2481
2482    /// Offset to ColorLine table.
2483    pub fn color_line_offset(&self) -> Offset24 {
2484        let range = self.color_line_offset_byte_range();
2485        self.data.read_at(range.start).ok().unwrap()
2486    }
2487
2488    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
2489    pub fn color_line(&self) -> Result<ColorLine<'a>, ReadError> {
2490        let data = self.data;
2491        self.color_line_offset().resolve(data)
2492    }
2493
2494    /// Center x coordinate.
2495    pub fn center_x(&self) -> FWord {
2496        let range = self.center_x_byte_range();
2497        self.data.read_at(range.start).ok().unwrap()
2498    }
2499
2500    /// Center y coordinate.
2501    pub fn center_y(&self) -> FWord {
2502        let range = self.center_y_byte_range();
2503        self.data.read_at(range.start).ok().unwrap()
2504    }
2505
2506    /// Start of the angular range of the gradient, 180° in
2507    /// counter-clockwise degrees per 1.0 of value.
2508    pub fn start_angle(&self) -> F2Dot14 {
2509        let range = self.start_angle_byte_range();
2510        self.data.read_at(range.start).ok().unwrap()
2511    }
2512
2513    /// End of the angular range of the gradient, 180° in
2514    /// counter-clockwise degrees per 1.0 of value.
2515    pub fn end_angle(&self) -> F2Dot14 {
2516        let range = self.end_angle_byte_range();
2517        self.data.read_at(range.start).ok().unwrap()
2518    }
2519
2520    pub fn format_byte_range(&self) -> Range<usize> {
2521        let start = 0;
2522        let end = start + u8::RAW_BYTE_LEN;
2523        start..end
2524    }
2525
2526    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
2527        let start = self.format_byte_range().end;
2528        let end = start + Offset24::RAW_BYTE_LEN;
2529        start..end
2530    }
2531
2532    pub fn center_x_byte_range(&self) -> Range<usize> {
2533        let start = self.color_line_offset_byte_range().end;
2534        let end = start + FWord::RAW_BYTE_LEN;
2535        start..end
2536    }
2537
2538    pub fn center_y_byte_range(&self) -> Range<usize> {
2539        let start = self.center_x_byte_range().end;
2540        let end = start + FWord::RAW_BYTE_LEN;
2541        start..end
2542    }
2543
2544    pub fn start_angle_byte_range(&self) -> Range<usize> {
2545        let start = self.center_y_byte_range().end;
2546        let end = start + F2Dot14::RAW_BYTE_LEN;
2547        start..end
2548    }
2549
2550    pub fn end_angle_byte_range(&self) -> Range<usize> {
2551        let start = self.start_angle_byte_range().end;
2552        let end = start + F2Dot14::RAW_BYTE_LEN;
2553        start..end
2554    }
2555}
2556
2557impl Format<u8> for PaintVarSweepGradient<'_> {
2558    const FORMAT: u8 = 9;
2559}
2560
2561impl<'a> MinByteRange<'a> for PaintVarSweepGradient<'a> {
2562    fn min_byte_range(&self) -> Range<usize> {
2563        0..self.var_index_base_byte_range().end
2564    }
2565    fn min_table_bytes(&self) -> &'a [u8] {
2566        let range = self.min_byte_range();
2567        self.data.as_bytes().get(range).unwrap_or_default()
2568    }
2569}
2570
2571impl ReadArgs for PaintVarSweepGradient<'_> {
2572    type Args = ();
2573}
2574
2575impl<'a> FontRead<'a> for PaintVarSweepGradient<'a> {
2576    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2577        #[allow(clippy::absurd_extreme_comparisons)]
2578        if data.len() < Self::MIN_SIZE {
2579            return Err(ReadError::OutOfBounds);
2580        }
2581        Ok(Self { data })
2582    }
2583}
2584
2585/// [PaintVarSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table
2586#[derive(Clone)]
2587pub struct PaintVarSweepGradient<'a> {
2588    data: FontData<'a>,
2589}
2590
2591#[allow(clippy::needless_lifetimes)]
2592impl<'a> PaintVarSweepGradient<'a> {
2593    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
2594        + Offset24::RAW_BYTE_LEN
2595        + FWord::RAW_BYTE_LEN
2596        + FWord::RAW_BYTE_LEN
2597        + F2Dot14::RAW_BYTE_LEN
2598        + F2Dot14::RAW_BYTE_LEN
2599        + u32::RAW_BYTE_LEN);
2600    basic_table_impls!(impl_the_methods);
2601
2602    /// Set to 9.
2603    pub fn format(&self) -> u8 {
2604        let range = self.format_byte_range();
2605        self.data.read_at(range.start).ok().unwrap()
2606    }
2607
2608    /// Offset to VarColorLine table.
2609    pub fn color_line_offset(&self) -> Offset24 {
2610        let range = self.color_line_offset_byte_range();
2611        self.data.read_at(range.start).ok().unwrap()
2612    }
2613
2614    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
2615    pub fn color_line(&self) -> Result<VarColorLine<'a>, ReadError> {
2616        let data = self.data;
2617        self.color_line_offset().resolve(data)
2618    }
2619
2620    /// Center x coordinate. For variation, use varIndexBase + 0.
2621    pub fn center_x(&self) -> FWord {
2622        let range = self.center_x_byte_range();
2623        self.data.read_at(range.start).ok().unwrap()
2624    }
2625
2626    /// Center y coordinate. For variation, use varIndexBase + 1.
2627    pub fn center_y(&self) -> FWord {
2628        let range = self.center_y_byte_range();
2629        self.data.read_at(range.start).ok().unwrap()
2630    }
2631
2632    /// Start of the angular range of the gradient, 180° in
2633    /// counter-clockwise degrees per 1.0 of value. For variation, use
2634    /// varIndexBase + 2.
2635    pub fn start_angle(&self) -> F2Dot14 {
2636        let range = self.start_angle_byte_range();
2637        self.data.read_at(range.start).ok().unwrap()
2638    }
2639
2640    /// End of the angular range of the gradient, 180° in
2641    /// counter-clockwise degrees per 1.0 of value. For variation, use
2642    /// varIndexBase + 3.
2643    pub fn end_angle(&self) -> F2Dot14 {
2644        let range = self.end_angle_byte_range();
2645        self.data.read_at(range.start).ok().unwrap()
2646    }
2647
2648    /// Base index into DeltaSetIndexMap.
2649    pub fn var_index_base(&self) -> u32 {
2650        let range = self.var_index_base_byte_range();
2651        self.data.read_at(range.start).ok().unwrap()
2652    }
2653
2654    pub fn format_byte_range(&self) -> Range<usize> {
2655        let start = 0;
2656        let end = start + u8::RAW_BYTE_LEN;
2657        start..end
2658    }
2659
2660    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
2661        let start = self.format_byte_range().end;
2662        let end = start + Offset24::RAW_BYTE_LEN;
2663        start..end
2664    }
2665
2666    pub fn center_x_byte_range(&self) -> Range<usize> {
2667        let start = self.color_line_offset_byte_range().end;
2668        let end = start + FWord::RAW_BYTE_LEN;
2669        start..end
2670    }
2671
2672    pub fn center_y_byte_range(&self) -> Range<usize> {
2673        let start = self.center_x_byte_range().end;
2674        let end = start + FWord::RAW_BYTE_LEN;
2675        start..end
2676    }
2677
2678    pub fn start_angle_byte_range(&self) -> Range<usize> {
2679        let start = self.center_y_byte_range().end;
2680        let end = start + F2Dot14::RAW_BYTE_LEN;
2681        start..end
2682    }
2683
2684    pub fn end_angle_byte_range(&self) -> Range<usize> {
2685        let start = self.start_angle_byte_range().end;
2686        let end = start + F2Dot14::RAW_BYTE_LEN;
2687        start..end
2688    }
2689
2690    pub fn var_index_base_byte_range(&self) -> Range<usize> {
2691        let start = self.end_angle_byte_range().end;
2692        let end = start + u32::RAW_BYTE_LEN;
2693        start..end
2694    }
2695}
2696
2697impl Format<u8> for PaintGlyph<'_> {
2698    const FORMAT: u8 = 10;
2699}
2700
2701impl<'a> MinByteRange<'a> for PaintGlyph<'a> {
2702    fn min_byte_range(&self) -> Range<usize> {
2703        0..self.glyph_id_byte_range().end
2704    }
2705    fn min_table_bytes(&self) -> &'a [u8] {
2706        let range = self.min_byte_range();
2707        self.data.as_bytes().get(range).unwrap_or_default()
2708    }
2709}
2710
2711impl ReadArgs for PaintGlyph<'_> {
2712    type Args = ();
2713}
2714
2715impl<'a> FontRead<'a> for PaintGlyph<'a> {
2716    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2717        #[allow(clippy::absurd_extreme_comparisons)]
2718        if data.len() < Self::MIN_SIZE {
2719            return Err(ReadError::OutOfBounds);
2720        }
2721        Ok(Self { data })
2722    }
2723}
2724
2725/// [PaintGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-10-paintglyph) table
2726#[derive(Clone)]
2727pub struct PaintGlyph<'a> {
2728    data: FontData<'a>,
2729}
2730
2731#[allow(clippy::needless_lifetimes)]
2732impl<'a> PaintGlyph<'a> {
2733    pub const MIN_SIZE: usize =
2734        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN);
2735    basic_table_impls!(impl_the_methods);
2736
2737    /// Set to 10.
2738    pub fn format(&self) -> u8 {
2739        let range = self.format_byte_range();
2740        self.data.read_at(range.start).ok().unwrap()
2741    }
2742
2743    /// Offset to a Paint table.
2744    pub fn paint_offset(&self) -> Offset24 {
2745        let range = self.paint_offset_byte_range();
2746        self.data.read_at(range.start).ok().unwrap()
2747    }
2748
2749    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
2750    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
2751        let data = self.data;
2752        self.paint_offset().resolve(data)
2753    }
2754
2755    /// Glyph ID for the source outline.
2756    pub fn glyph_id(&self) -> GlyphId16 {
2757        let range = self.glyph_id_byte_range();
2758        self.data.read_at(range.start).ok().unwrap()
2759    }
2760
2761    pub fn format_byte_range(&self) -> Range<usize> {
2762        let start = 0;
2763        let end = start + u8::RAW_BYTE_LEN;
2764        start..end
2765    }
2766
2767    pub fn paint_offset_byte_range(&self) -> Range<usize> {
2768        let start = self.format_byte_range().end;
2769        let end = start + Offset24::RAW_BYTE_LEN;
2770        start..end
2771    }
2772
2773    pub fn glyph_id_byte_range(&self) -> Range<usize> {
2774        let start = self.paint_offset_byte_range().end;
2775        let end = start + GlyphId16::RAW_BYTE_LEN;
2776        start..end
2777    }
2778}
2779
2780impl Format<u8> for PaintColrGlyph<'_> {
2781    const FORMAT: u8 = 11;
2782}
2783
2784impl<'a> MinByteRange<'a> for PaintColrGlyph<'a> {
2785    fn min_byte_range(&self) -> Range<usize> {
2786        0..self.glyph_id_byte_range().end
2787    }
2788    fn min_table_bytes(&self) -> &'a [u8] {
2789        let range = self.min_byte_range();
2790        self.data.as_bytes().get(range).unwrap_or_default()
2791    }
2792}
2793
2794impl ReadArgs for PaintColrGlyph<'_> {
2795    type Args = ();
2796}
2797
2798impl<'a> FontRead<'a> for PaintColrGlyph<'a> {
2799    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2800        #[allow(clippy::absurd_extreme_comparisons)]
2801        if data.len() < Self::MIN_SIZE {
2802            return Err(ReadError::OutOfBounds);
2803        }
2804        Ok(Self { data })
2805    }
2806}
2807
2808/// [PaintColrGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-11-paintcolrglyph) table
2809#[derive(Clone)]
2810pub struct PaintColrGlyph<'a> {
2811    data: FontData<'a>,
2812}
2813
2814#[allow(clippy::needless_lifetimes)]
2815impl<'a> PaintColrGlyph<'a> {
2816    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN);
2817    basic_table_impls!(impl_the_methods);
2818
2819    /// Set to 11.
2820    pub fn format(&self) -> u8 {
2821        let range = self.format_byte_range();
2822        self.data.read_at(range.start).ok().unwrap()
2823    }
2824
2825    /// Glyph ID for a BaseGlyphList base glyph.
2826    pub fn glyph_id(&self) -> GlyphId16 {
2827        let range = self.glyph_id_byte_range();
2828        self.data.read_at(range.start).ok().unwrap()
2829    }
2830
2831    pub fn format_byte_range(&self) -> Range<usize> {
2832        let start = 0;
2833        let end = start + u8::RAW_BYTE_LEN;
2834        start..end
2835    }
2836
2837    pub fn glyph_id_byte_range(&self) -> Range<usize> {
2838        let start = self.format_byte_range().end;
2839        let end = start + GlyphId16::RAW_BYTE_LEN;
2840        start..end
2841    }
2842}
2843
2844impl Format<u8> for PaintTransform<'_> {
2845    const FORMAT: u8 = 12;
2846}
2847
2848impl<'a> MinByteRange<'a> for PaintTransform<'a> {
2849    fn min_byte_range(&self) -> Range<usize> {
2850        0..self.transform_offset_byte_range().end
2851    }
2852    fn min_table_bytes(&self) -> &'a [u8] {
2853        let range = self.min_byte_range();
2854        self.data.as_bytes().get(range).unwrap_or_default()
2855    }
2856}
2857
2858impl ReadArgs for PaintTransform<'_> {
2859    type Args = ();
2860}
2861
2862impl<'a> FontRead<'a> for PaintTransform<'a> {
2863    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2864        #[allow(clippy::absurd_extreme_comparisons)]
2865        if data.len() < Self::MIN_SIZE {
2866            return Err(ReadError::OutOfBounds);
2867        }
2868        Ok(Self { data })
2869    }
2870}
2871
2872/// [PaintTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table
2873#[derive(Clone)]
2874pub struct PaintTransform<'a> {
2875    data: FontData<'a>,
2876}
2877
2878#[allow(clippy::needless_lifetimes)]
2879impl<'a> PaintTransform<'a> {
2880    pub const MIN_SIZE: usize =
2881        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
2882    basic_table_impls!(impl_the_methods);
2883
2884    /// Set to 12.
2885    pub fn format(&self) -> u8 {
2886        let range = self.format_byte_range();
2887        self.data.read_at(range.start).ok().unwrap()
2888    }
2889
2890    /// Offset to a Paint subtable.
2891    pub fn paint_offset(&self) -> Offset24 {
2892        let range = self.paint_offset_byte_range();
2893        self.data.read_at(range.start).ok().unwrap()
2894    }
2895
2896    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
2897    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
2898        let data = self.data;
2899        self.paint_offset().resolve(data)
2900    }
2901
2902    /// Offset to an Affine2x3 table.
2903    pub fn transform_offset(&self) -> Offset24 {
2904        let range = self.transform_offset_byte_range();
2905        self.data.read_at(range.start).ok().unwrap()
2906    }
2907
2908    /// Attempt to resolve [`transform_offset`][Self::transform_offset].
2909    pub fn transform(&self) -> Result<Affine2x3<'a>, ReadError> {
2910        let data = self.data;
2911        self.transform_offset().resolve(data)
2912    }
2913
2914    pub fn format_byte_range(&self) -> Range<usize> {
2915        let start = 0;
2916        let end = start + u8::RAW_BYTE_LEN;
2917        start..end
2918    }
2919
2920    pub fn paint_offset_byte_range(&self) -> Range<usize> {
2921        let start = self.format_byte_range().end;
2922        let end = start + Offset24::RAW_BYTE_LEN;
2923        start..end
2924    }
2925
2926    pub fn transform_offset_byte_range(&self) -> Range<usize> {
2927        let start = self.paint_offset_byte_range().end;
2928        let end = start + Offset24::RAW_BYTE_LEN;
2929        start..end
2930    }
2931}
2932
2933impl Format<u8> for PaintVarTransform<'_> {
2934    const FORMAT: u8 = 13;
2935}
2936
2937impl<'a> MinByteRange<'a> for PaintVarTransform<'a> {
2938    fn min_byte_range(&self) -> Range<usize> {
2939        0..self.transform_offset_byte_range().end
2940    }
2941    fn min_table_bytes(&self) -> &'a [u8] {
2942        let range = self.min_byte_range();
2943        self.data.as_bytes().get(range).unwrap_or_default()
2944    }
2945}
2946
2947impl ReadArgs for PaintVarTransform<'_> {
2948    type Args = ();
2949}
2950
2951impl<'a> FontRead<'a> for PaintVarTransform<'a> {
2952    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2953        #[allow(clippy::absurd_extreme_comparisons)]
2954        if data.len() < Self::MIN_SIZE {
2955            return Err(ReadError::OutOfBounds);
2956        }
2957        Ok(Self { data })
2958    }
2959}
2960
2961/// [PaintVarTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table
2962#[derive(Clone)]
2963pub struct PaintVarTransform<'a> {
2964    data: FontData<'a>,
2965}
2966
2967#[allow(clippy::needless_lifetimes)]
2968impl<'a> PaintVarTransform<'a> {
2969    pub const MIN_SIZE: usize =
2970        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
2971    basic_table_impls!(impl_the_methods);
2972
2973    /// Set to 13.
2974    pub fn format(&self) -> u8 {
2975        let range = self.format_byte_range();
2976        self.data.read_at(range.start).ok().unwrap()
2977    }
2978
2979    /// Offset to a Paint subtable.
2980    pub fn paint_offset(&self) -> Offset24 {
2981        let range = self.paint_offset_byte_range();
2982        self.data.read_at(range.start).ok().unwrap()
2983    }
2984
2985    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
2986    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
2987        let data = self.data;
2988        self.paint_offset().resolve(data)
2989    }
2990
2991    /// Offset to a VarAffine2x3 table.
2992    pub fn transform_offset(&self) -> Offset24 {
2993        let range = self.transform_offset_byte_range();
2994        self.data.read_at(range.start).ok().unwrap()
2995    }
2996
2997    /// Attempt to resolve [`transform_offset`][Self::transform_offset].
2998    pub fn transform(&self) -> Result<VarAffine2x3<'a>, ReadError> {
2999        let data = self.data;
3000        self.transform_offset().resolve(data)
3001    }
3002
3003    pub fn format_byte_range(&self) -> Range<usize> {
3004        let start = 0;
3005        let end = start + u8::RAW_BYTE_LEN;
3006        start..end
3007    }
3008
3009    pub fn paint_offset_byte_range(&self) -> Range<usize> {
3010        let start = self.format_byte_range().end;
3011        let end = start + Offset24::RAW_BYTE_LEN;
3012        start..end
3013    }
3014
3015    pub fn transform_offset_byte_range(&self) -> Range<usize> {
3016        let start = self.paint_offset_byte_range().end;
3017        let end = start + Offset24::RAW_BYTE_LEN;
3018        start..end
3019    }
3020}
3021
3022impl<'a> MinByteRange<'a> for Affine2x3<'a> {
3023    fn min_byte_range(&self) -> Range<usize> {
3024        0..self.dy_byte_range().end
3025    }
3026    fn min_table_bytes(&self) -> &'a [u8] {
3027        let range = self.min_byte_range();
3028        self.data.as_bytes().get(range).unwrap_or_default()
3029    }
3030}
3031
3032impl ReadArgs for Affine2x3<'_> {
3033    type Args = ();
3034}
3035
3036impl<'a> FontRead<'a> for Affine2x3<'a> {
3037    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3038        #[allow(clippy::absurd_extreme_comparisons)]
3039        if data.len() < Self::MIN_SIZE {
3040            return Err(ReadError::OutOfBounds);
3041        }
3042        Ok(Self { data })
3043    }
3044}
3045
3046/// [Affine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record
3047#[derive(Clone)]
3048pub struct Affine2x3<'a> {
3049    data: FontData<'a>,
3050}
3051
3052#[allow(clippy::needless_lifetimes)]
3053impl<'a> Affine2x3<'a> {
3054    pub const MIN_SIZE: usize = (Fixed::RAW_BYTE_LEN
3055        + Fixed::RAW_BYTE_LEN
3056        + Fixed::RAW_BYTE_LEN
3057        + Fixed::RAW_BYTE_LEN
3058        + Fixed::RAW_BYTE_LEN
3059        + Fixed::RAW_BYTE_LEN);
3060    basic_table_impls!(impl_the_methods);
3061
3062    /// x-component of transformed x-basis vector.
3063    pub fn xx(&self) -> Fixed {
3064        let range = self.xx_byte_range();
3065        self.data.read_at(range.start).ok().unwrap()
3066    }
3067
3068    /// y-component of transformed x-basis vector.
3069    pub fn yx(&self) -> Fixed {
3070        let range = self.yx_byte_range();
3071        self.data.read_at(range.start).ok().unwrap()
3072    }
3073
3074    /// x-component of transformed y-basis vector.
3075    pub fn xy(&self) -> Fixed {
3076        let range = self.xy_byte_range();
3077        self.data.read_at(range.start).ok().unwrap()
3078    }
3079
3080    /// y-component of transformed y-basis vector.
3081    pub fn yy(&self) -> Fixed {
3082        let range = self.yy_byte_range();
3083        self.data.read_at(range.start).ok().unwrap()
3084    }
3085
3086    /// Translation in x direction.
3087    pub fn dx(&self) -> Fixed {
3088        let range = self.dx_byte_range();
3089        self.data.read_at(range.start).ok().unwrap()
3090    }
3091
3092    /// Translation in y direction.
3093    pub fn dy(&self) -> Fixed {
3094        let range = self.dy_byte_range();
3095        self.data.read_at(range.start).ok().unwrap()
3096    }
3097
3098    pub fn xx_byte_range(&self) -> Range<usize> {
3099        let start = 0;
3100        let end = start + Fixed::RAW_BYTE_LEN;
3101        start..end
3102    }
3103
3104    pub fn yx_byte_range(&self) -> Range<usize> {
3105        let start = self.xx_byte_range().end;
3106        let end = start + Fixed::RAW_BYTE_LEN;
3107        start..end
3108    }
3109
3110    pub fn xy_byte_range(&self) -> Range<usize> {
3111        let start = self.yx_byte_range().end;
3112        let end = start + Fixed::RAW_BYTE_LEN;
3113        start..end
3114    }
3115
3116    pub fn yy_byte_range(&self) -> Range<usize> {
3117        let start = self.xy_byte_range().end;
3118        let end = start + Fixed::RAW_BYTE_LEN;
3119        start..end
3120    }
3121
3122    pub fn dx_byte_range(&self) -> Range<usize> {
3123        let start = self.yy_byte_range().end;
3124        let end = start + Fixed::RAW_BYTE_LEN;
3125        start..end
3126    }
3127
3128    pub fn dy_byte_range(&self) -> Range<usize> {
3129        let start = self.dx_byte_range().end;
3130        let end = start + Fixed::RAW_BYTE_LEN;
3131        start..end
3132    }
3133}
3134
3135const _: () = assert!(FontData::default_data_long_enough(Affine2x3::MIN_SIZE));
3136
3137impl Default for Affine2x3<'_> {
3138    fn default() -> Self {
3139        Self {
3140            data: FontData::default_table_data(),
3141        }
3142    }
3143}
3144
3145impl<'a> MinByteRange<'a> for VarAffine2x3<'a> {
3146    fn min_byte_range(&self) -> Range<usize> {
3147        0..self.var_index_base_byte_range().end
3148    }
3149    fn min_table_bytes(&self) -> &'a [u8] {
3150        let range = self.min_byte_range();
3151        self.data.as_bytes().get(range).unwrap_or_default()
3152    }
3153}
3154
3155impl ReadArgs for VarAffine2x3<'_> {
3156    type Args = ();
3157}
3158
3159impl<'a> FontRead<'a> for VarAffine2x3<'a> {
3160    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3161        #[allow(clippy::absurd_extreme_comparisons)]
3162        if data.len() < Self::MIN_SIZE {
3163            return Err(ReadError::OutOfBounds);
3164        }
3165        Ok(Self { data })
3166    }
3167}
3168
3169/// [VarAffine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record
3170#[derive(Clone)]
3171pub struct VarAffine2x3<'a> {
3172    data: FontData<'a>,
3173}
3174
3175#[allow(clippy::needless_lifetimes)]
3176impl<'a> VarAffine2x3<'a> {
3177    pub const MIN_SIZE: usize = (Fixed::RAW_BYTE_LEN
3178        + Fixed::RAW_BYTE_LEN
3179        + Fixed::RAW_BYTE_LEN
3180        + Fixed::RAW_BYTE_LEN
3181        + Fixed::RAW_BYTE_LEN
3182        + Fixed::RAW_BYTE_LEN
3183        + u32::RAW_BYTE_LEN);
3184    basic_table_impls!(impl_the_methods);
3185
3186    /// x-component of transformed x-basis vector. For variation, use
3187    /// varIndexBase + 0.
3188    pub fn xx(&self) -> Fixed {
3189        let range = self.xx_byte_range();
3190        self.data.read_at(range.start).ok().unwrap()
3191    }
3192
3193    /// y-component of transformed x-basis vector. For variation, use
3194    /// varIndexBase + 1.
3195    pub fn yx(&self) -> Fixed {
3196        let range = self.yx_byte_range();
3197        self.data.read_at(range.start).ok().unwrap()
3198    }
3199
3200    /// x-component of transformed y-basis vector. For variation, use
3201    /// varIndexBase + 2.
3202    pub fn xy(&self) -> Fixed {
3203        let range = self.xy_byte_range();
3204        self.data.read_at(range.start).ok().unwrap()
3205    }
3206
3207    /// y-component of transformed y-basis vector. For variation, use
3208    /// varIndexBase + 3.
3209    pub fn yy(&self) -> Fixed {
3210        let range = self.yy_byte_range();
3211        self.data.read_at(range.start).ok().unwrap()
3212    }
3213
3214    /// Translation in x direction. For variation, use varIndexBase + 4.
3215    pub fn dx(&self) -> Fixed {
3216        let range = self.dx_byte_range();
3217        self.data.read_at(range.start).ok().unwrap()
3218    }
3219
3220    /// Translation in y direction. For variation, use varIndexBase + 5.
3221    pub fn dy(&self) -> Fixed {
3222        let range = self.dy_byte_range();
3223        self.data.read_at(range.start).ok().unwrap()
3224    }
3225
3226    /// Base index into DeltaSetIndexMap.
3227    pub fn var_index_base(&self) -> u32 {
3228        let range = self.var_index_base_byte_range();
3229        self.data.read_at(range.start).ok().unwrap()
3230    }
3231
3232    pub fn xx_byte_range(&self) -> Range<usize> {
3233        let start = 0;
3234        let end = start + Fixed::RAW_BYTE_LEN;
3235        start..end
3236    }
3237
3238    pub fn yx_byte_range(&self) -> Range<usize> {
3239        let start = self.xx_byte_range().end;
3240        let end = start + Fixed::RAW_BYTE_LEN;
3241        start..end
3242    }
3243
3244    pub fn xy_byte_range(&self) -> Range<usize> {
3245        let start = self.yx_byte_range().end;
3246        let end = start + Fixed::RAW_BYTE_LEN;
3247        start..end
3248    }
3249
3250    pub fn yy_byte_range(&self) -> Range<usize> {
3251        let start = self.xy_byte_range().end;
3252        let end = start + Fixed::RAW_BYTE_LEN;
3253        start..end
3254    }
3255
3256    pub fn dx_byte_range(&self) -> Range<usize> {
3257        let start = self.yy_byte_range().end;
3258        let end = start + Fixed::RAW_BYTE_LEN;
3259        start..end
3260    }
3261
3262    pub fn dy_byte_range(&self) -> Range<usize> {
3263        let start = self.dx_byte_range().end;
3264        let end = start + Fixed::RAW_BYTE_LEN;
3265        start..end
3266    }
3267
3268    pub fn var_index_base_byte_range(&self) -> Range<usize> {
3269        let start = self.dy_byte_range().end;
3270        let end = start + u32::RAW_BYTE_LEN;
3271        start..end
3272    }
3273}
3274
3275const _: () = assert!(FontData::default_data_long_enough(VarAffine2x3::MIN_SIZE));
3276
3277impl Default for VarAffine2x3<'_> {
3278    fn default() -> Self {
3279        Self {
3280            data: FontData::default_table_data(),
3281        }
3282    }
3283}
3284
3285impl Format<u8> for PaintTranslate<'_> {
3286    const FORMAT: u8 = 14;
3287}
3288
3289impl<'a> MinByteRange<'a> for PaintTranslate<'a> {
3290    fn min_byte_range(&self) -> Range<usize> {
3291        0..self.dy_byte_range().end
3292    }
3293    fn min_table_bytes(&self) -> &'a [u8] {
3294        let range = self.min_byte_range();
3295        self.data.as_bytes().get(range).unwrap_or_default()
3296    }
3297}
3298
3299impl ReadArgs for PaintTranslate<'_> {
3300    type Args = ();
3301}
3302
3303impl<'a> FontRead<'a> for PaintTranslate<'a> {
3304    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3305        #[allow(clippy::absurd_extreme_comparisons)]
3306        if data.len() < Self::MIN_SIZE {
3307            return Err(ReadError::OutOfBounds);
3308        }
3309        Ok(Self { data })
3310    }
3311}
3312
3313/// [PaintTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table
3314#[derive(Clone)]
3315pub struct PaintTranslate<'a> {
3316    data: FontData<'a>,
3317}
3318
3319#[allow(clippy::needless_lifetimes)]
3320impl<'a> PaintTranslate<'a> {
3321    pub const MIN_SIZE: usize =
3322        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN);
3323    basic_table_impls!(impl_the_methods);
3324
3325    /// Set to 14.
3326    pub fn format(&self) -> u8 {
3327        let range = self.format_byte_range();
3328        self.data.read_at(range.start).ok().unwrap()
3329    }
3330
3331    /// Offset to a Paint subtable.
3332    pub fn paint_offset(&self) -> Offset24 {
3333        let range = self.paint_offset_byte_range();
3334        self.data.read_at(range.start).ok().unwrap()
3335    }
3336
3337    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
3338    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
3339        let data = self.data;
3340        self.paint_offset().resolve(data)
3341    }
3342
3343    /// Translation in x direction.
3344    pub fn dx(&self) -> FWord {
3345        let range = self.dx_byte_range();
3346        self.data.read_at(range.start).ok().unwrap()
3347    }
3348
3349    /// Translation in y direction.
3350    pub fn dy(&self) -> FWord {
3351        let range = self.dy_byte_range();
3352        self.data.read_at(range.start).ok().unwrap()
3353    }
3354
3355    pub fn format_byte_range(&self) -> Range<usize> {
3356        let start = 0;
3357        let end = start + u8::RAW_BYTE_LEN;
3358        start..end
3359    }
3360
3361    pub fn paint_offset_byte_range(&self) -> Range<usize> {
3362        let start = self.format_byte_range().end;
3363        let end = start + Offset24::RAW_BYTE_LEN;
3364        start..end
3365    }
3366
3367    pub fn dx_byte_range(&self) -> Range<usize> {
3368        let start = self.paint_offset_byte_range().end;
3369        let end = start + FWord::RAW_BYTE_LEN;
3370        start..end
3371    }
3372
3373    pub fn dy_byte_range(&self) -> Range<usize> {
3374        let start = self.dx_byte_range().end;
3375        let end = start + FWord::RAW_BYTE_LEN;
3376        start..end
3377    }
3378}
3379
3380impl Format<u8> for PaintVarTranslate<'_> {
3381    const FORMAT: u8 = 15;
3382}
3383
3384impl<'a> MinByteRange<'a> for PaintVarTranslate<'a> {
3385    fn min_byte_range(&self) -> Range<usize> {
3386        0..self.var_index_base_byte_range().end
3387    }
3388    fn min_table_bytes(&self) -> &'a [u8] {
3389        let range = self.min_byte_range();
3390        self.data.as_bytes().get(range).unwrap_or_default()
3391    }
3392}
3393
3394impl ReadArgs for PaintVarTranslate<'_> {
3395    type Args = ();
3396}
3397
3398impl<'a> FontRead<'a> for PaintVarTranslate<'a> {
3399    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3400        #[allow(clippy::absurd_extreme_comparisons)]
3401        if data.len() < Self::MIN_SIZE {
3402            return Err(ReadError::OutOfBounds);
3403        }
3404        Ok(Self { data })
3405    }
3406}
3407
3408/// [PaintVarTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table
3409#[derive(Clone)]
3410pub struct PaintVarTranslate<'a> {
3411    data: FontData<'a>,
3412}
3413
3414#[allow(clippy::needless_lifetimes)]
3415impl<'a> PaintVarTranslate<'a> {
3416    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
3417        + Offset24::RAW_BYTE_LEN
3418        + FWord::RAW_BYTE_LEN
3419        + FWord::RAW_BYTE_LEN
3420        + u32::RAW_BYTE_LEN);
3421    basic_table_impls!(impl_the_methods);
3422
3423    /// Set to 15.
3424    pub fn format(&self) -> u8 {
3425        let range = self.format_byte_range();
3426        self.data.read_at(range.start).ok().unwrap()
3427    }
3428
3429    /// Offset to a Paint subtable.
3430    pub fn paint_offset(&self) -> Offset24 {
3431        let range = self.paint_offset_byte_range();
3432        self.data.read_at(range.start).ok().unwrap()
3433    }
3434
3435    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
3436    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
3437        let data = self.data;
3438        self.paint_offset().resolve(data)
3439    }
3440
3441    /// Translation in x direction. For variation, use varIndexBase + 0.
3442    pub fn dx(&self) -> FWord {
3443        let range = self.dx_byte_range();
3444        self.data.read_at(range.start).ok().unwrap()
3445    }
3446
3447    /// Translation in y direction. For variation, use varIndexBase + 1.
3448    pub fn dy(&self) -> FWord {
3449        let range = self.dy_byte_range();
3450        self.data.read_at(range.start).ok().unwrap()
3451    }
3452
3453    /// Base index into DeltaSetIndexMap.
3454    pub fn var_index_base(&self) -> u32 {
3455        let range = self.var_index_base_byte_range();
3456        self.data.read_at(range.start).ok().unwrap()
3457    }
3458
3459    pub fn format_byte_range(&self) -> Range<usize> {
3460        let start = 0;
3461        let end = start + u8::RAW_BYTE_LEN;
3462        start..end
3463    }
3464
3465    pub fn paint_offset_byte_range(&self) -> Range<usize> {
3466        let start = self.format_byte_range().end;
3467        let end = start + Offset24::RAW_BYTE_LEN;
3468        start..end
3469    }
3470
3471    pub fn dx_byte_range(&self) -> Range<usize> {
3472        let start = self.paint_offset_byte_range().end;
3473        let end = start + FWord::RAW_BYTE_LEN;
3474        start..end
3475    }
3476
3477    pub fn dy_byte_range(&self) -> Range<usize> {
3478        let start = self.dx_byte_range().end;
3479        let end = start + FWord::RAW_BYTE_LEN;
3480        start..end
3481    }
3482
3483    pub fn var_index_base_byte_range(&self) -> Range<usize> {
3484        let start = self.dy_byte_range().end;
3485        let end = start + u32::RAW_BYTE_LEN;
3486        start..end
3487    }
3488}
3489
3490impl Format<u8> for PaintScale<'_> {
3491    const FORMAT: u8 = 16;
3492}
3493
3494impl<'a> MinByteRange<'a> for PaintScale<'a> {
3495    fn min_byte_range(&self) -> Range<usize> {
3496        0..self.scale_y_byte_range().end
3497    }
3498    fn min_table_bytes(&self) -> &'a [u8] {
3499        let range = self.min_byte_range();
3500        self.data.as_bytes().get(range).unwrap_or_default()
3501    }
3502}
3503
3504impl ReadArgs for PaintScale<'_> {
3505    type Args = ();
3506}
3507
3508impl<'a> FontRead<'a> for PaintScale<'a> {
3509    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3510        #[allow(clippy::absurd_extreme_comparisons)]
3511        if data.len() < Self::MIN_SIZE {
3512            return Err(ReadError::OutOfBounds);
3513        }
3514        Ok(Self { data })
3515    }
3516}
3517
3518/// [PaintScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
3519#[derive(Clone)]
3520pub struct PaintScale<'a> {
3521    data: FontData<'a>,
3522}
3523
3524#[allow(clippy::needless_lifetimes)]
3525impl<'a> PaintScale<'a> {
3526    pub const MIN_SIZE: usize =
3527        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
3528    basic_table_impls!(impl_the_methods);
3529
3530    /// Set to 16.
3531    pub fn format(&self) -> u8 {
3532        let range = self.format_byte_range();
3533        self.data.read_at(range.start).ok().unwrap()
3534    }
3535
3536    /// Offset to a Paint subtable.
3537    pub fn paint_offset(&self) -> Offset24 {
3538        let range = self.paint_offset_byte_range();
3539        self.data.read_at(range.start).ok().unwrap()
3540    }
3541
3542    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
3543    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
3544        let data = self.data;
3545        self.paint_offset().resolve(data)
3546    }
3547
3548    /// Scale factor in x direction.
3549    pub fn scale_x(&self) -> F2Dot14 {
3550        let range = self.scale_x_byte_range();
3551        self.data.read_at(range.start).ok().unwrap()
3552    }
3553
3554    /// Scale factor in y direction.
3555    pub fn scale_y(&self) -> F2Dot14 {
3556        let range = self.scale_y_byte_range();
3557        self.data.read_at(range.start).ok().unwrap()
3558    }
3559
3560    pub fn format_byte_range(&self) -> Range<usize> {
3561        let start = 0;
3562        let end = start + u8::RAW_BYTE_LEN;
3563        start..end
3564    }
3565
3566    pub fn paint_offset_byte_range(&self) -> Range<usize> {
3567        let start = self.format_byte_range().end;
3568        let end = start + Offset24::RAW_BYTE_LEN;
3569        start..end
3570    }
3571
3572    pub fn scale_x_byte_range(&self) -> Range<usize> {
3573        let start = self.paint_offset_byte_range().end;
3574        let end = start + F2Dot14::RAW_BYTE_LEN;
3575        start..end
3576    }
3577
3578    pub fn scale_y_byte_range(&self) -> Range<usize> {
3579        let start = self.scale_x_byte_range().end;
3580        let end = start + F2Dot14::RAW_BYTE_LEN;
3581        start..end
3582    }
3583}
3584
3585impl Format<u8> for PaintVarScale<'_> {
3586    const FORMAT: u8 = 17;
3587}
3588
3589impl<'a> MinByteRange<'a> for PaintVarScale<'a> {
3590    fn min_byte_range(&self) -> Range<usize> {
3591        0..self.var_index_base_byte_range().end
3592    }
3593    fn min_table_bytes(&self) -> &'a [u8] {
3594        let range = self.min_byte_range();
3595        self.data.as_bytes().get(range).unwrap_or_default()
3596    }
3597}
3598
3599impl ReadArgs for PaintVarScale<'_> {
3600    type Args = ();
3601}
3602
3603impl<'a> FontRead<'a> for PaintVarScale<'a> {
3604    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3605        #[allow(clippy::absurd_extreme_comparisons)]
3606        if data.len() < Self::MIN_SIZE {
3607            return Err(ReadError::OutOfBounds);
3608        }
3609        Ok(Self { data })
3610    }
3611}
3612
3613/// [PaintVarScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
3614#[derive(Clone)]
3615pub struct PaintVarScale<'a> {
3616    data: FontData<'a>,
3617}
3618
3619#[allow(clippy::needless_lifetimes)]
3620impl<'a> PaintVarScale<'a> {
3621    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
3622        + Offset24::RAW_BYTE_LEN
3623        + F2Dot14::RAW_BYTE_LEN
3624        + F2Dot14::RAW_BYTE_LEN
3625        + u32::RAW_BYTE_LEN);
3626    basic_table_impls!(impl_the_methods);
3627
3628    /// Set to 17.
3629    pub fn format(&self) -> u8 {
3630        let range = self.format_byte_range();
3631        self.data.read_at(range.start).ok().unwrap()
3632    }
3633
3634    /// Offset to a Paint subtable.
3635    pub fn paint_offset(&self) -> Offset24 {
3636        let range = self.paint_offset_byte_range();
3637        self.data.read_at(range.start).ok().unwrap()
3638    }
3639
3640    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
3641    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
3642        let data = self.data;
3643        self.paint_offset().resolve(data)
3644    }
3645
3646    /// Scale factor in x direction. For variation, use varIndexBase +
3647    /// 0.
3648    pub fn scale_x(&self) -> F2Dot14 {
3649        let range = self.scale_x_byte_range();
3650        self.data.read_at(range.start).ok().unwrap()
3651    }
3652
3653    /// Scale factor in y direction. For variation, use varIndexBase +
3654    /// 1.
3655    pub fn scale_y(&self) -> F2Dot14 {
3656        let range = self.scale_y_byte_range();
3657        self.data.read_at(range.start).ok().unwrap()
3658    }
3659
3660    /// Base index into DeltaSetIndexMap.
3661    pub fn var_index_base(&self) -> u32 {
3662        let range = self.var_index_base_byte_range();
3663        self.data.read_at(range.start).ok().unwrap()
3664    }
3665
3666    pub fn format_byte_range(&self) -> Range<usize> {
3667        let start = 0;
3668        let end = start + u8::RAW_BYTE_LEN;
3669        start..end
3670    }
3671
3672    pub fn paint_offset_byte_range(&self) -> Range<usize> {
3673        let start = self.format_byte_range().end;
3674        let end = start + Offset24::RAW_BYTE_LEN;
3675        start..end
3676    }
3677
3678    pub fn scale_x_byte_range(&self) -> Range<usize> {
3679        let start = self.paint_offset_byte_range().end;
3680        let end = start + F2Dot14::RAW_BYTE_LEN;
3681        start..end
3682    }
3683
3684    pub fn scale_y_byte_range(&self) -> Range<usize> {
3685        let start = self.scale_x_byte_range().end;
3686        let end = start + F2Dot14::RAW_BYTE_LEN;
3687        start..end
3688    }
3689
3690    pub fn var_index_base_byte_range(&self) -> Range<usize> {
3691        let start = self.scale_y_byte_range().end;
3692        let end = start + u32::RAW_BYTE_LEN;
3693        start..end
3694    }
3695}
3696
3697impl Format<u8> for PaintScaleAroundCenter<'_> {
3698    const FORMAT: u8 = 18;
3699}
3700
3701impl<'a> MinByteRange<'a> for PaintScaleAroundCenter<'a> {
3702    fn min_byte_range(&self) -> Range<usize> {
3703        0..self.center_y_byte_range().end
3704    }
3705    fn min_table_bytes(&self) -> &'a [u8] {
3706        let range = self.min_byte_range();
3707        self.data.as_bytes().get(range).unwrap_or_default()
3708    }
3709}
3710
3711impl ReadArgs for PaintScaleAroundCenter<'_> {
3712    type Args = ();
3713}
3714
3715impl<'a> FontRead<'a> for PaintScaleAroundCenter<'a> {
3716    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3717        #[allow(clippy::absurd_extreme_comparisons)]
3718        if data.len() < Self::MIN_SIZE {
3719            return Err(ReadError::OutOfBounds);
3720        }
3721        Ok(Self { data })
3722    }
3723}
3724
3725/// [PaintScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
3726#[derive(Clone)]
3727pub struct PaintScaleAroundCenter<'a> {
3728    data: FontData<'a>,
3729}
3730
3731#[allow(clippy::needless_lifetimes)]
3732impl<'a> PaintScaleAroundCenter<'a> {
3733    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
3734        + Offset24::RAW_BYTE_LEN
3735        + F2Dot14::RAW_BYTE_LEN
3736        + F2Dot14::RAW_BYTE_LEN
3737        + FWord::RAW_BYTE_LEN
3738        + FWord::RAW_BYTE_LEN);
3739    basic_table_impls!(impl_the_methods);
3740
3741    /// Set to 18.
3742    pub fn format(&self) -> u8 {
3743        let range = self.format_byte_range();
3744        self.data.read_at(range.start).ok().unwrap()
3745    }
3746
3747    /// Offset to a Paint subtable.
3748    pub fn paint_offset(&self) -> Offset24 {
3749        let range = self.paint_offset_byte_range();
3750        self.data.read_at(range.start).ok().unwrap()
3751    }
3752
3753    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
3754    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
3755        let data = self.data;
3756        self.paint_offset().resolve(data)
3757    }
3758
3759    /// Scale factor in x direction.
3760    pub fn scale_x(&self) -> F2Dot14 {
3761        let range = self.scale_x_byte_range();
3762        self.data.read_at(range.start).ok().unwrap()
3763    }
3764
3765    /// Scale factor in y direction.
3766    pub fn scale_y(&self) -> F2Dot14 {
3767        let range = self.scale_y_byte_range();
3768        self.data.read_at(range.start).ok().unwrap()
3769    }
3770
3771    /// x coordinate for the center of scaling.
3772    pub fn center_x(&self) -> FWord {
3773        let range = self.center_x_byte_range();
3774        self.data.read_at(range.start).ok().unwrap()
3775    }
3776
3777    /// y coordinate for the center of scaling.
3778    pub fn center_y(&self) -> FWord {
3779        let range = self.center_y_byte_range();
3780        self.data.read_at(range.start).ok().unwrap()
3781    }
3782
3783    pub fn format_byte_range(&self) -> Range<usize> {
3784        let start = 0;
3785        let end = start + u8::RAW_BYTE_LEN;
3786        start..end
3787    }
3788
3789    pub fn paint_offset_byte_range(&self) -> Range<usize> {
3790        let start = self.format_byte_range().end;
3791        let end = start + Offset24::RAW_BYTE_LEN;
3792        start..end
3793    }
3794
3795    pub fn scale_x_byte_range(&self) -> Range<usize> {
3796        let start = self.paint_offset_byte_range().end;
3797        let end = start + F2Dot14::RAW_BYTE_LEN;
3798        start..end
3799    }
3800
3801    pub fn scale_y_byte_range(&self) -> Range<usize> {
3802        let start = self.scale_x_byte_range().end;
3803        let end = start + F2Dot14::RAW_BYTE_LEN;
3804        start..end
3805    }
3806
3807    pub fn center_x_byte_range(&self) -> Range<usize> {
3808        let start = self.scale_y_byte_range().end;
3809        let end = start + FWord::RAW_BYTE_LEN;
3810        start..end
3811    }
3812
3813    pub fn center_y_byte_range(&self) -> Range<usize> {
3814        let start = self.center_x_byte_range().end;
3815        let end = start + FWord::RAW_BYTE_LEN;
3816        start..end
3817    }
3818}
3819
3820impl Format<u8> for PaintVarScaleAroundCenter<'_> {
3821    const FORMAT: u8 = 19;
3822}
3823
3824impl<'a> MinByteRange<'a> for PaintVarScaleAroundCenter<'a> {
3825    fn min_byte_range(&self) -> Range<usize> {
3826        0..self.var_index_base_byte_range().end
3827    }
3828    fn min_table_bytes(&self) -> &'a [u8] {
3829        let range = self.min_byte_range();
3830        self.data.as_bytes().get(range).unwrap_or_default()
3831    }
3832}
3833
3834impl ReadArgs for PaintVarScaleAroundCenter<'_> {
3835    type Args = ();
3836}
3837
3838impl<'a> FontRead<'a> for PaintVarScaleAroundCenter<'a> {
3839    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3840        #[allow(clippy::absurd_extreme_comparisons)]
3841        if data.len() < Self::MIN_SIZE {
3842            return Err(ReadError::OutOfBounds);
3843        }
3844        Ok(Self { data })
3845    }
3846}
3847
3848/// [PaintVarScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
3849#[derive(Clone)]
3850pub struct PaintVarScaleAroundCenter<'a> {
3851    data: FontData<'a>,
3852}
3853
3854#[allow(clippy::needless_lifetimes)]
3855impl<'a> PaintVarScaleAroundCenter<'a> {
3856    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
3857        + Offset24::RAW_BYTE_LEN
3858        + F2Dot14::RAW_BYTE_LEN
3859        + F2Dot14::RAW_BYTE_LEN
3860        + FWord::RAW_BYTE_LEN
3861        + FWord::RAW_BYTE_LEN
3862        + u32::RAW_BYTE_LEN);
3863    basic_table_impls!(impl_the_methods);
3864
3865    /// Set to 19.
3866    pub fn format(&self) -> u8 {
3867        let range = self.format_byte_range();
3868        self.data.read_at(range.start).ok().unwrap()
3869    }
3870
3871    /// Offset to a Paint subtable.
3872    pub fn paint_offset(&self) -> Offset24 {
3873        let range = self.paint_offset_byte_range();
3874        self.data.read_at(range.start).ok().unwrap()
3875    }
3876
3877    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
3878    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
3879        let data = self.data;
3880        self.paint_offset().resolve(data)
3881    }
3882
3883    /// Scale factor in x direction. For variation, use varIndexBase +
3884    /// 0.
3885    pub fn scale_x(&self) -> F2Dot14 {
3886        let range = self.scale_x_byte_range();
3887        self.data.read_at(range.start).ok().unwrap()
3888    }
3889
3890    /// Scale factor in y direction. For variation, use varIndexBase +
3891    /// 1.
3892    pub fn scale_y(&self) -> F2Dot14 {
3893        let range = self.scale_y_byte_range();
3894        self.data.read_at(range.start).ok().unwrap()
3895    }
3896
3897    /// x coordinate for the center of scaling. For variation, use
3898    /// varIndexBase + 2.
3899    pub fn center_x(&self) -> FWord {
3900        let range = self.center_x_byte_range();
3901        self.data.read_at(range.start).ok().unwrap()
3902    }
3903
3904    /// y coordinate for the center of scaling. For variation, use
3905    /// varIndexBase + 3.
3906    pub fn center_y(&self) -> FWord {
3907        let range = self.center_y_byte_range();
3908        self.data.read_at(range.start).ok().unwrap()
3909    }
3910
3911    /// Base index into DeltaSetIndexMap.
3912    pub fn var_index_base(&self) -> u32 {
3913        let range = self.var_index_base_byte_range();
3914        self.data.read_at(range.start).ok().unwrap()
3915    }
3916
3917    pub fn format_byte_range(&self) -> Range<usize> {
3918        let start = 0;
3919        let end = start + u8::RAW_BYTE_LEN;
3920        start..end
3921    }
3922
3923    pub fn paint_offset_byte_range(&self) -> Range<usize> {
3924        let start = self.format_byte_range().end;
3925        let end = start + Offset24::RAW_BYTE_LEN;
3926        start..end
3927    }
3928
3929    pub fn scale_x_byte_range(&self) -> Range<usize> {
3930        let start = self.paint_offset_byte_range().end;
3931        let end = start + F2Dot14::RAW_BYTE_LEN;
3932        start..end
3933    }
3934
3935    pub fn scale_y_byte_range(&self) -> Range<usize> {
3936        let start = self.scale_x_byte_range().end;
3937        let end = start + F2Dot14::RAW_BYTE_LEN;
3938        start..end
3939    }
3940
3941    pub fn center_x_byte_range(&self) -> Range<usize> {
3942        let start = self.scale_y_byte_range().end;
3943        let end = start + FWord::RAW_BYTE_LEN;
3944        start..end
3945    }
3946
3947    pub fn center_y_byte_range(&self) -> Range<usize> {
3948        let start = self.center_x_byte_range().end;
3949        let end = start + FWord::RAW_BYTE_LEN;
3950        start..end
3951    }
3952
3953    pub fn var_index_base_byte_range(&self) -> Range<usize> {
3954        let start = self.center_y_byte_range().end;
3955        let end = start + u32::RAW_BYTE_LEN;
3956        start..end
3957    }
3958}
3959
3960impl Format<u8> for PaintScaleUniform<'_> {
3961    const FORMAT: u8 = 20;
3962}
3963
3964impl<'a> MinByteRange<'a> for PaintScaleUniform<'a> {
3965    fn min_byte_range(&self) -> Range<usize> {
3966        0..self.scale_byte_range().end
3967    }
3968    fn min_table_bytes(&self) -> &'a [u8] {
3969        let range = self.min_byte_range();
3970        self.data.as_bytes().get(range).unwrap_or_default()
3971    }
3972}
3973
3974impl ReadArgs for PaintScaleUniform<'_> {
3975    type Args = ();
3976}
3977
3978impl<'a> FontRead<'a> for PaintScaleUniform<'a> {
3979    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3980        #[allow(clippy::absurd_extreme_comparisons)]
3981        if data.len() < Self::MIN_SIZE {
3982            return Err(ReadError::OutOfBounds);
3983        }
3984        Ok(Self { data })
3985    }
3986}
3987
3988/// [PaintScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
3989#[derive(Clone)]
3990pub struct PaintScaleUniform<'a> {
3991    data: FontData<'a>,
3992}
3993
3994#[allow(clippy::needless_lifetimes)]
3995impl<'a> PaintScaleUniform<'a> {
3996    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
3997    basic_table_impls!(impl_the_methods);
3998
3999    /// Set to 20.
4000    pub fn format(&self) -> u8 {
4001        let range = self.format_byte_range();
4002        self.data.read_at(range.start).ok().unwrap()
4003    }
4004
4005    /// Offset to a Paint subtable.
4006    pub fn paint_offset(&self) -> Offset24 {
4007        let range = self.paint_offset_byte_range();
4008        self.data.read_at(range.start).ok().unwrap()
4009    }
4010
4011    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4012    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4013        let data = self.data;
4014        self.paint_offset().resolve(data)
4015    }
4016
4017    /// Scale factor in x and y directions.
4018    pub fn scale(&self) -> F2Dot14 {
4019        let range = self.scale_byte_range();
4020        self.data.read_at(range.start).ok().unwrap()
4021    }
4022
4023    pub fn format_byte_range(&self) -> Range<usize> {
4024        let start = 0;
4025        let end = start + u8::RAW_BYTE_LEN;
4026        start..end
4027    }
4028
4029    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4030        let start = self.format_byte_range().end;
4031        let end = start + Offset24::RAW_BYTE_LEN;
4032        start..end
4033    }
4034
4035    pub fn scale_byte_range(&self) -> Range<usize> {
4036        let start = self.paint_offset_byte_range().end;
4037        let end = start + F2Dot14::RAW_BYTE_LEN;
4038        start..end
4039    }
4040}
4041
4042impl Format<u8> for PaintVarScaleUniform<'_> {
4043    const FORMAT: u8 = 21;
4044}
4045
4046impl<'a> MinByteRange<'a> for PaintVarScaleUniform<'a> {
4047    fn min_byte_range(&self) -> Range<usize> {
4048        0..self.var_index_base_byte_range().end
4049    }
4050    fn min_table_bytes(&self) -> &'a [u8] {
4051        let range = self.min_byte_range();
4052        self.data.as_bytes().get(range).unwrap_or_default()
4053    }
4054}
4055
4056impl ReadArgs for PaintVarScaleUniform<'_> {
4057    type Args = ();
4058}
4059
4060impl<'a> FontRead<'a> for PaintVarScaleUniform<'a> {
4061    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4062        #[allow(clippy::absurd_extreme_comparisons)]
4063        if data.len() < Self::MIN_SIZE {
4064            return Err(ReadError::OutOfBounds);
4065        }
4066        Ok(Self { data })
4067    }
4068}
4069
4070/// [PaintVarScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
4071#[derive(Clone)]
4072pub struct PaintVarScaleUniform<'a> {
4073    data: FontData<'a>,
4074}
4075
4076#[allow(clippy::needless_lifetimes)]
4077impl<'a> PaintVarScaleUniform<'a> {
4078    pub const MIN_SIZE: usize =
4079        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4080    basic_table_impls!(impl_the_methods);
4081
4082    /// Set to 21.
4083    pub fn format(&self) -> u8 {
4084        let range = self.format_byte_range();
4085        self.data.read_at(range.start).ok().unwrap()
4086    }
4087
4088    /// Offset to a Paint subtable.
4089    pub fn paint_offset(&self) -> Offset24 {
4090        let range = self.paint_offset_byte_range();
4091        self.data.read_at(range.start).ok().unwrap()
4092    }
4093
4094    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4095    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4096        let data = self.data;
4097        self.paint_offset().resolve(data)
4098    }
4099
4100    /// Scale factor in x and y directions. For variation, use
4101    /// varIndexBase + 0.
4102    pub fn scale(&self) -> F2Dot14 {
4103        let range = self.scale_byte_range();
4104        self.data.read_at(range.start).ok().unwrap()
4105    }
4106
4107    /// Base index into DeltaSetIndexMap.
4108    pub fn var_index_base(&self) -> u32 {
4109        let range = self.var_index_base_byte_range();
4110        self.data.read_at(range.start).ok().unwrap()
4111    }
4112
4113    pub fn format_byte_range(&self) -> Range<usize> {
4114        let start = 0;
4115        let end = start + u8::RAW_BYTE_LEN;
4116        start..end
4117    }
4118
4119    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4120        let start = self.format_byte_range().end;
4121        let end = start + Offset24::RAW_BYTE_LEN;
4122        start..end
4123    }
4124
4125    pub fn scale_byte_range(&self) -> Range<usize> {
4126        let start = self.paint_offset_byte_range().end;
4127        let end = start + F2Dot14::RAW_BYTE_LEN;
4128        start..end
4129    }
4130
4131    pub fn var_index_base_byte_range(&self) -> Range<usize> {
4132        let start = self.scale_byte_range().end;
4133        let end = start + u32::RAW_BYTE_LEN;
4134        start..end
4135    }
4136}
4137
4138impl Format<u8> for PaintScaleUniformAroundCenter<'_> {
4139    const FORMAT: u8 = 22;
4140}
4141
4142impl<'a> MinByteRange<'a> for PaintScaleUniformAroundCenter<'a> {
4143    fn min_byte_range(&self) -> Range<usize> {
4144        0..self.center_y_byte_range().end
4145    }
4146    fn min_table_bytes(&self) -> &'a [u8] {
4147        let range = self.min_byte_range();
4148        self.data.as_bytes().get(range).unwrap_or_default()
4149    }
4150}
4151
4152impl ReadArgs for PaintScaleUniformAroundCenter<'_> {
4153    type Args = ();
4154}
4155
4156impl<'a> FontRead<'a> for PaintScaleUniformAroundCenter<'a> {
4157    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4158        #[allow(clippy::absurd_extreme_comparisons)]
4159        if data.len() < Self::MIN_SIZE {
4160            return Err(ReadError::OutOfBounds);
4161        }
4162        Ok(Self { data })
4163    }
4164}
4165
4166/// [PaintScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
4167#[derive(Clone)]
4168pub struct PaintScaleUniformAroundCenter<'a> {
4169    data: FontData<'a>,
4170}
4171
4172#[allow(clippy::needless_lifetimes)]
4173impl<'a> PaintScaleUniformAroundCenter<'a> {
4174    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
4175        + Offset24::RAW_BYTE_LEN
4176        + F2Dot14::RAW_BYTE_LEN
4177        + FWord::RAW_BYTE_LEN
4178        + FWord::RAW_BYTE_LEN);
4179    basic_table_impls!(impl_the_methods);
4180
4181    /// Set to 22.
4182    pub fn format(&self) -> u8 {
4183        let range = self.format_byte_range();
4184        self.data.read_at(range.start).ok().unwrap()
4185    }
4186
4187    /// Offset to a Paint subtable.
4188    pub fn paint_offset(&self) -> Offset24 {
4189        let range = self.paint_offset_byte_range();
4190        self.data.read_at(range.start).ok().unwrap()
4191    }
4192
4193    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4194    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4195        let data = self.data;
4196        self.paint_offset().resolve(data)
4197    }
4198
4199    /// Scale factor in x and y directions.
4200    pub fn scale(&self) -> F2Dot14 {
4201        let range = self.scale_byte_range();
4202        self.data.read_at(range.start).ok().unwrap()
4203    }
4204
4205    /// x coordinate for the center of scaling.
4206    pub fn center_x(&self) -> FWord {
4207        let range = self.center_x_byte_range();
4208        self.data.read_at(range.start).ok().unwrap()
4209    }
4210
4211    /// y coordinate for the center of scaling.
4212    pub fn center_y(&self) -> FWord {
4213        let range = self.center_y_byte_range();
4214        self.data.read_at(range.start).ok().unwrap()
4215    }
4216
4217    pub fn format_byte_range(&self) -> Range<usize> {
4218        let start = 0;
4219        let end = start + u8::RAW_BYTE_LEN;
4220        start..end
4221    }
4222
4223    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4224        let start = self.format_byte_range().end;
4225        let end = start + Offset24::RAW_BYTE_LEN;
4226        start..end
4227    }
4228
4229    pub fn scale_byte_range(&self) -> Range<usize> {
4230        let start = self.paint_offset_byte_range().end;
4231        let end = start + F2Dot14::RAW_BYTE_LEN;
4232        start..end
4233    }
4234
4235    pub fn center_x_byte_range(&self) -> Range<usize> {
4236        let start = self.scale_byte_range().end;
4237        let end = start + FWord::RAW_BYTE_LEN;
4238        start..end
4239    }
4240
4241    pub fn center_y_byte_range(&self) -> Range<usize> {
4242        let start = self.center_x_byte_range().end;
4243        let end = start + FWord::RAW_BYTE_LEN;
4244        start..end
4245    }
4246}
4247
4248impl Format<u8> for PaintVarScaleUniformAroundCenter<'_> {
4249    const FORMAT: u8 = 23;
4250}
4251
4252impl<'a> MinByteRange<'a> for PaintVarScaleUniformAroundCenter<'a> {
4253    fn min_byte_range(&self) -> Range<usize> {
4254        0..self.var_index_base_byte_range().end
4255    }
4256    fn min_table_bytes(&self) -> &'a [u8] {
4257        let range = self.min_byte_range();
4258        self.data.as_bytes().get(range).unwrap_or_default()
4259    }
4260}
4261
4262impl ReadArgs for PaintVarScaleUniformAroundCenter<'_> {
4263    type Args = ();
4264}
4265
4266impl<'a> FontRead<'a> for PaintVarScaleUniformAroundCenter<'a> {
4267    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4268        #[allow(clippy::absurd_extreme_comparisons)]
4269        if data.len() < Self::MIN_SIZE {
4270            return Err(ReadError::OutOfBounds);
4271        }
4272        Ok(Self { data })
4273    }
4274}
4275
4276/// [PaintVarScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
4277#[derive(Clone)]
4278pub struct PaintVarScaleUniformAroundCenter<'a> {
4279    data: FontData<'a>,
4280}
4281
4282#[allow(clippy::needless_lifetimes)]
4283impl<'a> PaintVarScaleUniformAroundCenter<'a> {
4284    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
4285        + Offset24::RAW_BYTE_LEN
4286        + F2Dot14::RAW_BYTE_LEN
4287        + FWord::RAW_BYTE_LEN
4288        + FWord::RAW_BYTE_LEN
4289        + u32::RAW_BYTE_LEN);
4290    basic_table_impls!(impl_the_methods);
4291
4292    /// Set to 23.
4293    pub fn format(&self) -> u8 {
4294        let range = self.format_byte_range();
4295        self.data.read_at(range.start).ok().unwrap()
4296    }
4297
4298    /// Offset to a Paint subtable.
4299    pub fn paint_offset(&self) -> Offset24 {
4300        let range = self.paint_offset_byte_range();
4301        self.data.read_at(range.start).ok().unwrap()
4302    }
4303
4304    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4305    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4306        let data = self.data;
4307        self.paint_offset().resolve(data)
4308    }
4309
4310    /// Scale factor in x and y directions. For variation, use
4311    /// varIndexBase + 0.
4312    pub fn scale(&self) -> F2Dot14 {
4313        let range = self.scale_byte_range();
4314        self.data.read_at(range.start).ok().unwrap()
4315    }
4316
4317    /// x coordinate for the center of scaling. For variation, use
4318    /// varIndexBase + 1.
4319    pub fn center_x(&self) -> FWord {
4320        let range = self.center_x_byte_range();
4321        self.data.read_at(range.start).ok().unwrap()
4322    }
4323
4324    /// y coordinate for the center of scaling. For variation, use
4325    /// varIndexBase + 2.
4326    pub fn center_y(&self) -> FWord {
4327        let range = self.center_y_byte_range();
4328        self.data.read_at(range.start).ok().unwrap()
4329    }
4330
4331    /// Base index into DeltaSetIndexMap.
4332    pub fn var_index_base(&self) -> u32 {
4333        let range = self.var_index_base_byte_range();
4334        self.data.read_at(range.start).ok().unwrap()
4335    }
4336
4337    pub fn format_byte_range(&self) -> Range<usize> {
4338        let start = 0;
4339        let end = start + u8::RAW_BYTE_LEN;
4340        start..end
4341    }
4342
4343    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4344        let start = self.format_byte_range().end;
4345        let end = start + Offset24::RAW_BYTE_LEN;
4346        start..end
4347    }
4348
4349    pub fn scale_byte_range(&self) -> Range<usize> {
4350        let start = self.paint_offset_byte_range().end;
4351        let end = start + F2Dot14::RAW_BYTE_LEN;
4352        start..end
4353    }
4354
4355    pub fn center_x_byte_range(&self) -> Range<usize> {
4356        let start = self.scale_byte_range().end;
4357        let end = start + FWord::RAW_BYTE_LEN;
4358        start..end
4359    }
4360
4361    pub fn center_y_byte_range(&self) -> Range<usize> {
4362        let start = self.center_x_byte_range().end;
4363        let end = start + FWord::RAW_BYTE_LEN;
4364        start..end
4365    }
4366
4367    pub fn var_index_base_byte_range(&self) -> Range<usize> {
4368        let start = self.center_y_byte_range().end;
4369        let end = start + u32::RAW_BYTE_LEN;
4370        start..end
4371    }
4372}
4373
4374impl Format<u8> for PaintRotate<'_> {
4375    const FORMAT: u8 = 24;
4376}
4377
4378impl<'a> MinByteRange<'a> for PaintRotate<'a> {
4379    fn min_byte_range(&self) -> Range<usize> {
4380        0..self.angle_byte_range().end
4381    }
4382    fn min_table_bytes(&self) -> &'a [u8] {
4383        let range = self.min_byte_range();
4384        self.data.as_bytes().get(range).unwrap_or_default()
4385    }
4386}
4387
4388impl ReadArgs for PaintRotate<'_> {
4389    type Args = ();
4390}
4391
4392impl<'a> FontRead<'a> for PaintRotate<'a> {
4393    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4394        #[allow(clippy::absurd_extreme_comparisons)]
4395        if data.len() < Self::MIN_SIZE {
4396            return Err(ReadError::OutOfBounds);
4397        }
4398        Ok(Self { data })
4399    }
4400}
4401
4402/// [PaintRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
4403#[derive(Clone)]
4404pub struct PaintRotate<'a> {
4405    data: FontData<'a>,
4406}
4407
4408#[allow(clippy::needless_lifetimes)]
4409impl<'a> PaintRotate<'a> {
4410    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
4411    basic_table_impls!(impl_the_methods);
4412
4413    /// Set to 24.
4414    pub fn format(&self) -> u8 {
4415        let range = self.format_byte_range();
4416        self.data.read_at(range.start).ok().unwrap()
4417    }
4418
4419    /// Offset to a Paint subtable.
4420    pub fn paint_offset(&self) -> Offset24 {
4421        let range = self.paint_offset_byte_range();
4422        self.data.read_at(range.start).ok().unwrap()
4423    }
4424
4425    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4426    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4427        let data = self.data;
4428        self.paint_offset().resolve(data)
4429    }
4430
4431    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
4432    /// value.
4433    pub fn angle(&self) -> F2Dot14 {
4434        let range = self.angle_byte_range();
4435        self.data.read_at(range.start).ok().unwrap()
4436    }
4437
4438    pub fn format_byte_range(&self) -> Range<usize> {
4439        let start = 0;
4440        let end = start + u8::RAW_BYTE_LEN;
4441        start..end
4442    }
4443
4444    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4445        let start = self.format_byte_range().end;
4446        let end = start + Offset24::RAW_BYTE_LEN;
4447        start..end
4448    }
4449
4450    pub fn angle_byte_range(&self) -> Range<usize> {
4451        let start = self.paint_offset_byte_range().end;
4452        let end = start + F2Dot14::RAW_BYTE_LEN;
4453        start..end
4454    }
4455}
4456
4457impl Format<u8> for PaintVarRotate<'_> {
4458    const FORMAT: u8 = 25;
4459}
4460
4461impl<'a> MinByteRange<'a> for PaintVarRotate<'a> {
4462    fn min_byte_range(&self) -> Range<usize> {
4463        0..self.var_index_base_byte_range().end
4464    }
4465    fn min_table_bytes(&self) -> &'a [u8] {
4466        let range = self.min_byte_range();
4467        self.data.as_bytes().get(range).unwrap_or_default()
4468    }
4469}
4470
4471impl ReadArgs for PaintVarRotate<'_> {
4472    type Args = ();
4473}
4474
4475impl<'a> FontRead<'a> for PaintVarRotate<'a> {
4476    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4477        #[allow(clippy::absurd_extreme_comparisons)]
4478        if data.len() < Self::MIN_SIZE {
4479            return Err(ReadError::OutOfBounds);
4480        }
4481        Ok(Self { data })
4482    }
4483}
4484
4485/// [PaintVarRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
4486#[derive(Clone)]
4487pub struct PaintVarRotate<'a> {
4488    data: FontData<'a>,
4489}
4490
4491#[allow(clippy::needless_lifetimes)]
4492impl<'a> PaintVarRotate<'a> {
4493    pub const MIN_SIZE: usize =
4494        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4495    basic_table_impls!(impl_the_methods);
4496
4497    /// Set to 25.
4498    pub fn format(&self) -> u8 {
4499        let range = self.format_byte_range();
4500        self.data.read_at(range.start).ok().unwrap()
4501    }
4502
4503    /// Offset to a Paint subtable.
4504    pub fn paint_offset(&self) -> Offset24 {
4505        let range = self.paint_offset_byte_range();
4506        self.data.read_at(range.start).ok().unwrap()
4507    }
4508
4509    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4510    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4511        let data = self.data;
4512        self.paint_offset().resolve(data)
4513    }
4514
4515    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
4516    /// value. For variation, use varIndexBase + 0.
4517    pub fn angle(&self) -> F2Dot14 {
4518        let range = self.angle_byte_range();
4519        self.data.read_at(range.start).ok().unwrap()
4520    }
4521
4522    /// Base index into DeltaSetIndexMap.
4523    pub fn var_index_base(&self) -> u32 {
4524        let range = self.var_index_base_byte_range();
4525        self.data.read_at(range.start).ok().unwrap()
4526    }
4527
4528    pub fn format_byte_range(&self) -> Range<usize> {
4529        let start = 0;
4530        let end = start + u8::RAW_BYTE_LEN;
4531        start..end
4532    }
4533
4534    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4535        let start = self.format_byte_range().end;
4536        let end = start + Offset24::RAW_BYTE_LEN;
4537        start..end
4538    }
4539
4540    pub fn angle_byte_range(&self) -> Range<usize> {
4541        let start = self.paint_offset_byte_range().end;
4542        let end = start + F2Dot14::RAW_BYTE_LEN;
4543        start..end
4544    }
4545
4546    pub fn var_index_base_byte_range(&self) -> Range<usize> {
4547        let start = self.angle_byte_range().end;
4548        let end = start + u32::RAW_BYTE_LEN;
4549        start..end
4550    }
4551}
4552
4553impl Format<u8> for PaintRotateAroundCenter<'_> {
4554    const FORMAT: u8 = 26;
4555}
4556
4557impl<'a> MinByteRange<'a> for PaintRotateAroundCenter<'a> {
4558    fn min_byte_range(&self) -> Range<usize> {
4559        0..self.center_y_byte_range().end
4560    }
4561    fn min_table_bytes(&self) -> &'a [u8] {
4562        let range = self.min_byte_range();
4563        self.data.as_bytes().get(range).unwrap_or_default()
4564    }
4565}
4566
4567impl ReadArgs for PaintRotateAroundCenter<'_> {
4568    type Args = ();
4569}
4570
4571impl<'a> FontRead<'a> for PaintRotateAroundCenter<'a> {
4572    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4573        #[allow(clippy::absurd_extreme_comparisons)]
4574        if data.len() < Self::MIN_SIZE {
4575            return Err(ReadError::OutOfBounds);
4576        }
4577        Ok(Self { data })
4578    }
4579}
4580
4581/// [PaintRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
4582#[derive(Clone)]
4583pub struct PaintRotateAroundCenter<'a> {
4584    data: FontData<'a>,
4585}
4586
4587#[allow(clippy::needless_lifetimes)]
4588impl<'a> PaintRotateAroundCenter<'a> {
4589    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
4590        + Offset24::RAW_BYTE_LEN
4591        + F2Dot14::RAW_BYTE_LEN
4592        + FWord::RAW_BYTE_LEN
4593        + FWord::RAW_BYTE_LEN);
4594    basic_table_impls!(impl_the_methods);
4595
4596    /// Set to 26.
4597    pub fn format(&self) -> u8 {
4598        let range = self.format_byte_range();
4599        self.data.read_at(range.start).ok().unwrap()
4600    }
4601
4602    /// Offset to a Paint subtable.
4603    pub fn paint_offset(&self) -> Offset24 {
4604        let range = self.paint_offset_byte_range();
4605        self.data.read_at(range.start).ok().unwrap()
4606    }
4607
4608    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4609    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4610        let data = self.data;
4611        self.paint_offset().resolve(data)
4612    }
4613
4614    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
4615    /// value.
4616    pub fn angle(&self) -> F2Dot14 {
4617        let range = self.angle_byte_range();
4618        self.data.read_at(range.start).ok().unwrap()
4619    }
4620
4621    /// x coordinate for the center of rotation.
4622    pub fn center_x(&self) -> FWord {
4623        let range = self.center_x_byte_range();
4624        self.data.read_at(range.start).ok().unwrap()
4625    }
4626
4627    /// y coordinate for the center of rotation.
4628    pub fn center_y(&self) -> FWord {
4629        let range = self.center_y_byte_range();
4630        self.data.read_at(range.start).ok().unwrap()
4631    }
4632
4633    pub fn format_byte_range(&self) -> Range<usize> {
4634        let start = 0;
4635        let end = start + u8::RAW_BYTE_LEN;
4636        start..end
4637    }
4638
4639    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4640        let start = self.format_byte_range().end;
4641        let end = start + Offset24::RAW_BYTE_LEN;
4642        start..end
4643    }
4644
4645    pub fn angle_byte_range(&self) -> Range<usize> {
4646        let start = self.paint_offset_byte_range().end;
4647        let end = start + F2Dot14::RAW_BYTE_LEN;
4648        start..end
4649    }
4650
4651    pub fn center_x_byte_range(&self) -> Range<usize> {
4652        let start = self.angle_byte_range().end;
4653        let end = start + FWord::RAW_BYTE_LEN;
4654        start..end
4655    }
4656
4657    pub fn center_y_byte_range(&self) -> Range<usize> {
4658        let start = self.center_x_byte_range().end;
4659        let end = start + FWord::RAW_BYTE_LEN;
4660        start..end
4661    }
4662}
4663
4664impl Format<u8> for PaintVarRotateAroundCenter<'_> {
4665    const FORMAT: u8 = 27;
4666}
4667
4668impl<'a> MinByteRange<'a> for PaintVarRotateAroundCenter<'a> {
4669    fn min_byte_range(&self) -> Range<usize> {
4670        0..self.var_index_base_byte_range().end
4671    }
4672    fn min_table_bytes(&self) -> &'a [u8] {
4673        let range = self.min_byte_range();
4674        self.data.as_bytes().get(range).unwrap_or_default()
4675    }
4676}
4677
4678impl ReadArgs for PaintVarRotateAroundCenter<'_> {
4679    type Args = ();
4680}
4681
4682impl<'a> FontRead<'a> for PaintVarRotateAroundCenter<'a> {
4683    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4684        #[allow(clippy::absurd_extreme_comparisons)]
4685        if data.len() < Self::MIN_SIZE {
4686            return Err(ReadError::OutOfBounds);
4687        }
4688        Ok(Self { data })
4689    }
4690}
4691
4692/// [PaintVarRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
4693#[derive(Clone)]
4694pub struct PaintVarRotateAroundCenter<'a> {
4695    data: FontData<'a>,
4696}
4697
4698#[allow(clippy::needless_lifetimes)]
4699impl<'a> PaintVarRotateAroundCenter<'a> {
4700    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
4701        + Offset24::RAW_BYTE_LEN
4702        + F2Dot14::RAW_BYTE_LEN
4703        + FWord::RAW_BYTE_LEN
4704        + FWord::RAW_BYTE_LEN
4705        + u32::RAW_BYTE_LEN);
4706    basic_table_impls!(impl_the_methods);
4707
4708    /// Set to 27.
4709    pub fn format(&self) -> u8 {
4710        let range = self.format_byte_range();
4711        self.data.read_at(range.start).ok().unwrap()
4712    }
4713
4714    /// Offset to a Paint subtable.
4715    pub fn paint_offset(&self) -> Offset24 {
4716        let range = self.paint_offset_byte_range();
4717        self.data.read_at(range.start).ok().unwrap()
4718    }
4719
4720    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4721    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4722        let data = self.data;
4723        self.paint_offset().resolve(data)
4724    }
4725
4726    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
4727    /// value. For variation, use varIndexBase + 0.
4728    pub fn angle(&self) -> F2Dot14 {
4729        let range = self.angle_byte_range();
4730        self.data.read_at(range.start).ok().unwrap()
4731    }
4732
4733    /// x coordinate for the center of rotation. For variation, use
4734    /// varIndexBase + 1.
4735    pub fn center_x(&self) -> FWord {
4736        let range = self.center_x_byte_range();
4737        self.data.read_at(range.start).ok().unwrap()
4738    }
4739
4740    /// y coordinate for the center of rotation. For variation, use
4741    /// varIndexBase + 2.
4742    pub fn center_y(&self) -> FWord {
4743        let range = self.center_y_byte_range();
4744        self.data.read_at(range.start).ok().unwrap()
4745    }
4746
4747    /// Base index into DeltaSetIndexMap.
4748    pub fn var_index_base(&self) -> u32 {
4749        let range = self.var_index_base_byte_range();
4750        self.data.read_at(range.start).ok().unwrap()
4751    }
4752
4753    pub fn format_byte_range(&self) -> Range<usize> {
4754        let start = 0;
4755        let end = start + u8::RAW_BYTE_LEN;
4756        start..end
4757    }
4758
4759    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4760        let start = self.format_byte_range().end;
4761        let end = start + Offset24::RAW_BYTE_LEN;
4762        start..end
4763    }
4764
4765    pub fn angle_byte_range(&self) -> Range<usize> {
4766        let start = self.paint_offset_byte_range().end;
4767        let end = start + F2Dot14::RAW_BYTE_LEN;
4768        start..end
4769    }
4770
4771    pub fn center_x_byte_range(&self) -> Range<usize> {
4772        let start = self.angle_byte_range().end;
4773        let end = start + FWord::RAW_BYTE_LEN;
4774        start..end
4775    }
4776
4777    pub fn center_y_byte_range(&self) -> Range<usize> {
4778        let start = self.center_x_byte_range().end;
4779        let end = start + FWord::RAW_BYTE_LEN;
4780        start..end
4781    }
4782
4783    pub fn var_index_base_byte_range(&self) -> Range<usize> {
4784        let start = self.center_y_byte_range().end;
4785        let end = start + u32::RAW_BYTE_LEN;
4786        start..end
4787    }
4788}
4789
4790impl Format<u8> for PaintSkew<'_> {
4791    const FORMAT: u8 = 28;
4792}
4793
4794impl<'a> MinByteRange<'a> for PaintSkew<'a> {
4795    fn min_byte_range(&self) -> Range<usize> {
4796        0..self.y_skew_angle_byte_range().end
4797    }
4798    fn min_table_bytes(&self) -> &'a [u8] {
4799        let range = self.min_byte_range();
4800        self.data.as_bytes().get(range).unwrap_or_default()
4801    }
4802}
4803
4804impl ReadArgs for PaintSkew<'_> {
4805    type Args = ();
4806}
4807
4808impl<'a> FontRead<'a> for PaintSkew<'a> {
4809    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4810        #[allow(clippy::absurd_extreme_comparisons)]
4811        if data.len() < Self::MIN_SIZE {
4812            return Err(ReadError::OutOfBounds);
4813        }
4814        Ok(Self { data })
4815    }
4816}
4817
4818/// [PaintSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
4819#[derive(Clone)]
4820pub struct PaintSkew<'a> {
4821    data: FontData<'a>,
4822}
4823
4824#[allow(clippy::needless_lifetimes)]
4825impl<'a> PaintSkew<'a> {
4826    pub const MIN_SIZE: usize =
4827        (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
4828    basic_table_impls!(impl_the_methods);
4829
4830    /// Set to 28.
4831    pub fn format(&self) -> u8 {
4832        let range = self.format_byte_range();
4833        self.data.read_at(range.start).ok().unwrap()
4834    }
4835
4836    /// Offset to a Paint subtable.
4837    pub fn paint_offset(&self) -> Offset24 {
4838        let range = self.paint_offset_byte_range();
4839        self.data.read_at(range.start).ok().unwrap()
4840    }
4841
4842    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4843    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4844        let data = self.data;
4845        self.paint_offset().resolve(data)
4846    }
4847
4848    /// Angle of skew in the direction of the x-axis, 180° in
4849    /// counter-clockwise degrees per 1.0 of value.
4850    pub fn x_skew_angle(&self) -> F2Dot14 {
4851        let range = self.x_skew_angle_byte_range();
4852        self.data.read_at(range.start).ok().unwrap()
4853    }
4854
4855    /// Angle of skew in the direction of the y-axis, 180° in
4856    /// counter-clockwise degrees per 1.0 of value.
4857    pub fn y_skew_angle(&self) -> F2Dot14 {
4858        let range = self.y_skew_angle_byte_range();
4859        self.data.read_at(range.start).ok().unwrap()
4860    }
4861
4862    pub fn format_byte_range(&self) -> Range<usize> {
4863        let start = 0;
4864        let end = start + u8::RAW_BYTE_LEN;
4865        start..end
4866    }
4867
4868    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4869        let start = self.format_byte_range().end;
4870        let end = start + Offset24::RAW_BYTE_LEN;
4871        start..end
4872    }
4873
4874    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
4875        let start = self.paint_offset_byte_range().end;
4876        let end = start + F2Dot14::RAW_BYTE_LEN;
4877        start..end
4878    }
4879
4880    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
4881        let start = self.x_skew_angle_byte_range().end;
4882        let end = start + F2Dot14::RAW_BYTE_LEN;
4883        start..end
4884    }
4885}
4886
4887impl Format<u8> for PaintVarSkew<'_> {
4888    const FORMAT: u8 = 29;
4889}
4890
4891impl<'a> MinByteRange<'a> for PaintVarSkew<'a> {
4892    fn min_byte_range(&self) -> Range<usize> {
4893        0..self.var_index_base_byte_range().end
4894    }
4895    fn min_table_bytes(&self) -> &'a [u8] {
4896        let range = self.min_byte_range();
4897        self.data.as_bytes().get(range).unwrap_or_default()
4898    }
4899}
4900
4901impl ReadArgs for PaintVarSkew<'_> {
4902    type Args = ();
4903}
4904
4905impl<'a> FontRead<'a> for PaintVarSkew<'a> {
4906    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4907        #[allow(clippy::absurd_extreme_comparisons)]
4908        if data.len() < Self::MIN_SIZE {
4909            return Err(ReadError::OutOfBounds);
4910        }
4911        Ok(Self { data })
4912    }
4913}
4914
4915/// [PaintVarSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
4916#[derive(Clone)]
4917pub struct PaintVarSkew<'a> {
4918    data: FontData<'a>,
4919}
4920
4921#[allow(clippy::needless_lifetimes)]
4922impl<'a> PaintVarSkew<'a> {
4923    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
4924        + Offset24::RAW_BYTE_LEN
4925        + F2Dot14::RAW_BYTE_LEN
4926        + F2Dot14::RAW_BYTE_LEN
4927        + u32::RAW_BYTE_LEN);
4928    basic_table_impls!(impl_the_methods);
4929
4930    /// Set to 29.
4931    pub fn format(&self) -> u8 {
4932        let range = self.format_byte_range();
4933        self.data.read_at(range.start).ok().unwrap()
4934    }
4935
4936    /// Offset to a Paint subtable.
4937    pub fn paint_offset(&self) -> Offset24 {
4938        let range = self.paint_offset_byte_range();
4939        self.data.read_at(range.start).ok().unwrap()
4940    }
4941
4942    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
4943    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
4944        let data = self.data;
4945        self.paint_offset().resolve(data)
4946    }
4947
4948    /// Angle of skew in the direction of the x-axis, 180° ┬░ in
4949    /// counter-clockwise degrees per 1.0 of value. For variation, use
4950    /// varIndexBase + 0.
4951    pub fn x_skew_angle(&self) -> F2Dot14 {
4952        let range = self.x_skew_angle_byte_range();
4953        self.data.read_at(range.start).ok().unwrap()
4954    }
4955
4956    /// Angle of skew in the direction of the y-axis, 180° in
4957    /// counter-clockwise degrees per 1.0 of value. For variation, use
4958    /// varIndexBase + 1.
4959    pub fn y_skew_angle(&self) -> F2Dot14 {
4960        let range = self.y_skew_angle_byte_range();
4961        self.data.read_at(range.start).ok().unwrap()
4962    }
4963
4964    /// Base index into DeltaSetIndexMap.
4965    pub fn var_index_base(&self) -> u32 {
4966        let range = self.var_index_base_byte_range();
4967        self.data.read_at(range.start).ok().unwrap()
4968    }
4969
4970    pub fn format_byte_range(&self) -> Range<usize> {
4971        let start = 0;
4972        let end = start + u8::RAW_BYTE_LEN;
4973        start..end
4974    }
4975
4976    pub fn paint_offset_byte_range(&self) -> Range<usize> {
4977        let start = self.format_byte_range().end;
4978        let end = start + Offset24::RAW_BYTE_LEN;
4979        start..end
4980    }
4981
4982    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
4983        let start = self.paint_offset_byte_range().end;
4984        let end = start + F2Dot14::RAW_BYTE_LEN;
4985        start..end
4986    }
4987
4988    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
4989        let start = self.x_skew_angle_byte_range().end;
4990        let end = start + F2Dot14::RAW_BYTE_LEN;
4991        start..end
4992    }
4993
4994    pub fn var_index_base_byte_range(&self) -> Range<usize> {
4995        let start = self.y_skew_angle_byte_range().end;
4996        let end = start + u32::RAW_BYTE_LEN;
4997        start..end
4998    }
4999}
5000
5001impl Format<u8> for PaintSkewAroundCenter<'_> {
5002    const FORMAT: u8 = 30;
5003}
5004
5005impl<'a> MinByteRange<'a> for PaintSkewAroundCenter<'a> {
5006    fn min_byte_range(&self) -> Range<usize> {
5007        0..self.center_y_byte_range().end
5008    }
5009    fn min_table_bytes(&self) -> &'a [u8] {
5010        let range = self.min_byte_range();
5011        self.data.as_bytes().get(range).unwrap_or_default()
5012    }
5013}
5014
5015impl ReadArgs for PaintSkewAroundCenter<'_> {
5016    type Args = ();
5017}
5018
5019impl<'a> FontRead<'a> for PaintSkewAroundCenter<'a> {
5020    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5021        #[allow(clippy::absurd_extreme_comparisons)]
5022        if data.len() < Self::MIN_SIZE {
5023            return Err(ReadError::OutOfBounds);
5024        }
5025        Ok(Self { data })
5026    }
5027}
5028
5029/// [PaintSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
5030#[derive(Clone)]
5031pub struct PaintSkewAroundCenter<'a> {
5032    data: FontData<'a>,
5033}
5034
5035#[allow(clippy::needless_lifetimes)]
5036impl<'a> PaintSkewAroundCenter<'a> {
5037    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
5038        + Offset24::RAW_BYTE_LEN
5039        + F2Dot14::RAW_BYTE_LEN
5040        + F2Dot14::RAW_BYTE_LEN
5041        + FWord::RAW_BYTE_LEN
5042        + FWord::RAW_BYTE_LEN);
5043    basic_table_impls!(impl_the_methods);
5044
5045    /// Set to 30.
5046    pub fn format(&self) -> u8 {
5047        let range = self.format_byte_range();
5048        self.data.read_at(range.start).ok().unwrap()
5049    }
5050
5051    /// Offset to a Paint subtable.
5052    pub fn paint_offset(&self) -> Offset24 {
5053        let range = self.paint_offset_byte_range();
5054        self.data.read_at(range.start).ok().unwrap()
5055    }
5056
5057    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
5058    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
5059        let data = self.data;
5060        self.paint_offset().resolve(data)
5061    }
5062
5063    /// Angle of skew in the direction of the x-axis, 180° in
5064    /// counter-clockwise degrees per 1.0 of value.
5065    pub fn x_skew_angle(&self) -> F2Dot14 {
5066        let range = self.x_skew_angle_byte_range();
5067        self.data.read_at(range.start).ok().unwrap()
5068    }
5069
5070    /// Angle of skew in the direction of the y-axis, 180° in
5071    /// counter-clockwise degrees per 1.0 of value.
5072    pub fn y_skew_angle(&self) -> F2Dot14 {
5073        let range = self.y_skew_angle_byte_range();
5074        self.data.read_at(range.start).ok().unwrap()
5075    }
5076
5077    /// x coordinate for the center of rotation.
5078    pub fn center_x(&self) -> FWord {
5079        let range = self.center_x_byte_range();
5080        self.data.read_at(range.start).ok().unwrap()
5081    }
5082
5083    /// y coordinate for the center of rotation.
5084    pub fn center_y(&self) -> FWord {
5085        let range = self.center_y_byte_range();
5086        self.data.read_at(range.start).ok().unwrap()
5087    }
5088
5089    pub fn format_byte_range(&self) -> Range<usize> {
5090        let start = 0;
5091        let end = start + u8::RAW_BYTE_LEN;
5092        start..end
5093    }
5094
5095    pub fn paint_offset_byte_range(&self) -> Range<usize> {
5096        let start = self.format_byte_range().end;
5097        let end = start + Offset24::RAW_BYTE_LEN;
5098        start..end
5099    }
5100
5101    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
5102        let start = self.paint_offset_byte_range().end;
5103        let end = start + F2Dot14::RAW_BYTE_LEN;
5104        start..end
5105    }
5106
5107    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
5108        let start = self.x_skew_angle_byte_range().end;
5109        let end = start + F2Dot14::RAW_BYTE_LEN;
5110        start..end
5111    }
5112
5113    pub fn center_x_byte_range(&self) -> Range<usize> {
5114        let start = self.y_skew_angle_byte_range().end;
5115        let end = start + FWord::RAW_BYTE_LEN;
5116        start..end
5117    }
5118
5119    pub fn center_y_byte_range(&self) -> Range<usize> {
5120        let start = self.center_x_byte_range().end;
5121        let end = start + FWord::RAW_BYTE_LEN;
5122        start..end
5123    }
5124}
5125
5126impl Format<u8> for PaintVarSkewAroundCenter<'_> {
5127    const FORMAT: u8 = 31;
5128}
5129
5130impl<'a> MinByteRange<'a> for PaintVarSkewAroundCenter<'a> {
5131    fn min_byte_range(&self) -> Range<usize> {
5132        0..self.var_index_base_byte_range().end
5133    }
5134    fn min_table_bytes(&self) -> &'a [u8] {
5135        let range = self.min_byte_range();
5136        self.data.as_bytes().get(range).unwrap_or_default()
5137    }
5138}
5139
5140impl ReadArgs for PaintVarSkewAroundCenter<'_> {
5141    type Args = ();
5142}
5143
5144impl<'a> FontRead<'a> for PaintVarSkewAroundCenter<'a> {
5145    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5146        #[allow(clippy::absurd_extreme_comparisons)]
5147        if data.len() < Self::MIN_SIZE {
5148            return Err(ReadError::OutOfBounds);
5149        }
5150        Ok(Self { data })
5151    }
5152}
5153
5154/// [PaintVarSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
5155#[derive(Clone)]
5156pub struct PaintVarSkewAroundCenter<'a> {
5157    data: FontData<'a>,
5158}
5159
5160#[allow(clippy::needless_lifetimes)]
5161impl<'a> PaintVarSkewAroundCenter<'a> {
5162    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
5163        + Offset24::RAW_BYTE_LEN
5164        + F2Dot14::RAW_BYTE_LEN
5165        + F2Dot14::RAW_BYTE_LEN
5166        + FWord::RAW_BYTE_LEN
5167        + FWord::RAW_BYTE_LEN
5168        + u32::RAW_BYTE_LEN);
5169    basic_table_impls!(impl_the_methods);
5170
5171    /// Set to 31.
5172    pub fn format(&self) -> u8 {
5173        let range = self.format_byte_range();
5174        self.data.read_at(range.start).ok().unwrap()
5175    }
5176
5177    /// Offset to a Paint subtable.
5178    pub fn paint_offset(&self) -> Offset24 {
5179        let range = self.paint_offset_byte_range();
5180        self.data.read_at(range.start).ok().unwrap()
5181    }
5182
5183    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
5184    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
5185        let data = self.data;
5186        self.paint_offset().resolve(data)
5187    }
5188
5189    /// Angle of skew in the direction of the x-axis, 180° in
5190    /// counter-clockwise degrees per 1.0 of value. For variation, use
5191    /// varIndexBase + 0.
5192    pub fn x_skew_angle(&self) -> F2Dot14 {
5193        let range = self.x_skew_angle_byte_range();
5194        self.data.read_at(range.start).ok().unwrap()
5195    }
5196
5197    /// Angle of skew in the direction of the y-axis, 180° in
5198    /// counter-clockwise degrees per 1.0 of value. For variation, use
5199    /// varIndexBase + 1.
5200    pub fn y_skew_angle(&self) -> F2Dot14 {
5201        let range = self.y_skew_angle_byte_range();
5202        self.data.read_at(range.start).ok().unwrap()
5203    }
5204
5205    /// x coordinate for the center of rotation. For variation, use
5206    /// varIndexBase + 2.
5207    pub fn center_x(&self) -> FWord {
5208        let range = self.center_x_byte_range();
5209        self.data.read_at(range.start).ok().unwrap()
5210    }
5211
5212    /// y coordinate for the center of rotation. For variation, use
5213    /// varIndexBase + 3.
5214    pub fn center_y(&self) -> FWord {
5215        let range = self.center_y_byte_range();
5216        self.data.read_at(range.start).ok().unwrap()
5217    }
5218
5219    /// Base index into DeltaSetIndexMap.
5220    pub fn var_index_base(&self) -> u32 {
5221        let range = self.var_index_base_byte_range();
5222        self.data.read_at(range.start).ok().unwrap()
5223    }
5224
5225    pub fn format_byte_range(&self) -> Range<usize> {
5226        let start = 0;
5227        let end = start + u8::RAW_BYTE_LEN;
5228        start..end
5229    }
5230
5231    pub fn paint_offset_byte_range(&self) -> Range<usize> {
5232        let start = self.format_byte_range().end;
5233        let end = start + Offset24::RAW_BYTE_LEN;
5234        start..end
5235    }
5236
5237    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
5238        let start = self.paint_offset_byte_range().end;
5239        let end = start + F2Dot14::RAW_BYTE_LEN;
5240        start..end
5241    }
5242
5243    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
5244        let start = self.x_skew_angle_byte_range().end;
5245        let end = start + F2Dot14::RAW_BYTE_LEN;
5246        start..end
5247    }
5248
5249    pub fn center_x_byte_range(&self) -> Range<usize> {
5250        let start = self.y_skew_angle_byte_range().end;
5251        let end = start + FWord::RAW_BYTE_LEN;
5252        start..end
5253    }
5254
5255    pub fn center_y_byte_range(&self) -> Range<usize> {
5256        let start = self.center_x_byte_range().end;
5257        let end = start + FWord::RAW_BYTE_LEN;
5258        start..end
5259    }
5260
5261    pub fn var_index_base_byte_range(&self) -> Range<usize> {
5262        let start = self.center_y_byte_range().end;
5263        let end = start + u32::RAW_BYTE_LEN;
5264        start..end
5265    }
5266}
5267
5268impl Format<u8> for PaintComposite<'_> {
5269    const FORMAT: u8 = 32;
5270}
5271
5272impl<'a> MinByteRange<'a> for PaintComposite<'a> {
5273    fn min_byte_range(&self) -> Range<usize> {
5274        0..self.backdrop_paint_offset_byte_range().end
5275    }
5276    fn min_table_bytes(&self) -> &'a [u8] {
5277        let range = self.min_byte_range();
5278        self.data.as_bytes().get(range).unwrap_or_default()
5279    }
5280}
5281
5282impl ReadArgs for PaintComposite<'_> {
5283    type Args = ();
5284}
5285
5286impl<'a> FontRead<'a> for PaintComposite<'a> {
5287    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5288        #[allow(clippy::absurd_extreme_comparisons)]
5289        if data.len() < Self::MIN_SIZE {
5290            return Err(ReadError::OutOfBounds);
5291        }
5292        Ok(Self { data })
5293    }
5294}
5295
5296/// [PaintComposite](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) table
5297#[derive(Clone)]
5298pub struct PaintComposite<'a> {
5299    data: FontData<'a>,
5300}
5301
5302#[allow(clippy::needless_lifetimes)]
5303impl<'a> PaintComposite<'a> {
5304    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
5305        + Offset24::RAW_BYTE_LEN
5306        + CompositeMode::RAW_BYTE_LEN
5307        + Offset24::RAW_BYTE_LEN);
5308    basic_table_impls!(impl_the_methods);
5309
5310    /// Set to 32.
5311    pub fn format(&self) -> u8 {
5312        let range = self.format_byte_range();
5313        self.data.read_at(range.start).ok().unwrap()
5314    }
5315
5316    /// Offset to a source Paint table.
5317    pub fn source_paint_offset(&self) -> Offset24 {
5318        let range = self.source_paint_offset_byte_range();
5319        self.data.read_at(range.start).ok().unwrap()
5320    }
5321
5322    /// Attempt to resolve [`source_paint_offset`][Self::source_paint_offset].
5323    pub fn source_paint(&self) -> Result<Paint<'a>, ReadError> {
5324        let data = self.data;
5325        self.source_paint_offset().resolve(data)
5326    }
5327
5328    /// A CompositeMode enumeration value.
5329    pub fn composite_mode(&self) -> CompositeMode {
5330        let range = self.composite_mode_byte_range();
5331        self.data.read_at(range.start).ok().unwrap()
5332    }
5333
5334    /// Offset to a backdrop Paint table.
5335    pub fn backdrop_paint_offset(&self) -> Offset24 {
5336        let range = self.backdrop_paint_offset_byte_range();
5337        self.data.read_at(range.start).ok().unwrap()
5338    }
5339
5340    /// Attempt to resolve [`backdrop_paint_offset`][Self::backdrop_paint_offset].
5341    pub fn backdrop_paint(&self) -> Result<Paint<'a>, ReadError> {
5342        let data = self.data;
5343        self.backdrop_paint_offset().resolve(data)
5344    }
5345
5346    pub fn format_byte_range(&self) -> Range<usize> {
5347        let start = 0;
5348        let end = start + u8::RAW_BYTE_LEN;
5349        start..end
5350    }
5351
5352    pub fn source_paint_offset_byte_range(&self) -> Range<usize> {
5353        let start = self.format_byte_range().end;
5354        let end = start + Offset24::RAW_BYTE_LEN;
5355        start..end
5356    }
5357
5358    pub fn composite_mode_byte_range(&self) -> Range<usize> {
5359        let start = self.source_paint_offset_byte_range().end;
5360        let end = start + CompositeMode::RAW_BYTE_LEN;
5361        start..end
5362    }
5363
5364    pub fn backdrop_paint_offset_byte_range(&self) -> Range<usize> {
5365        let start = self.composite_mode_byte_range().end;
5366        let end = start + Offset24::RAW_BYTE_LEN;
5367        start..end
5368    }
5369}
5370
5371/// [CompositeMode](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) enumeration
5372#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
5373#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5374#[repr(u8)]
5375#[allow(clippy::manual_non_exhaustive)]
5376pub enum CompositeMode {
5377    Clear = 0,
5378    Src = 1,
5379    Dest = 2,
5380    #[default]
5381    SrcOver = 3,
5382    DestOver = 4,
5383    SrcIn = 5,
5384    DestIn = 6,
5385    SrcOut = 7,
5386    DestOut = 8,
5387    SrcAtop = 9,
5388    DestAtop = 10,
5389    Xor = 11,
5390    Plus = 12,
5391    Screen = 13,
5392    Overlay = 14,
5393    Darken = 15,
5394    Lighten = 16,
5395    ColorDodge = 17,
5396    ColorBurn = 18,
5397    HardLight = 19,
5398    SoftLight = 20,
5399    Difference = 21,
5400    Exclusion = 22,
5401    Multiply = 23,
5402    HslHue = 24,
5403    HslSaturation = 25,
5404    HslColor = 26,
5405    HslLuminosity = 27,
5406    #[doc(hidden)]
5407    /// If font data is malformed we will map unknown values to this variant
5408    Unknown,
5409}
5410
5411impl CompositeMode {
5412    /// Create from a raw scalar.
5413    ///
5414    /// This will never fail; unknown values will be mapped to the `Unknown` variant
5415    pub fn new(raw: u8) -> Self {
5416        match raw {
5417            0 => Self::Clear,
5418            1 => Self::Src,
5419            2 => Self::Dest,
5420            3 => Self::SrcOver,
5421            4 => Self::DestOver,
5422            5 => Self::SrcIn,
5423            6 => Self::DestIn,
5424            7 => Self::SrcOut,
5425            8 => Self::DestOut,
5426            9 => Self::SrcAtop,
5427            10 => Self::DestAtop,
5428            11 => Self::Xor,
5429            12 => Self::Plus,
5430            13 => Self::Screen,
5431            14 => Self::Overlay,
5432            15 => Self::Darken,
5433            16 => Self::Lighten,
5434            17 => Self::ColorDodge,
5435            18 => Self::ColorBurn,
5436            19 => Self::HardLight,
5437            20 => Self::SoftLight,
5438            21 => Self::Difference,
5439            22 => Self::Exclusion,
5440            23 => Self::Multiply,
5441            24 => Self::HslHue,
5442            25 => Self::HslSaturation,
5443            26 => Self::HslColor,
5444            27 => Self::HslLuminosity,
5445            _ => Self::Unknown,
5446        }
5447    }
5448}
5449
5450impl font_types::Scalar for CompositeMode {
5451    type Raw = <u8 as font_types::Scalar>::Raw;
5452    fn to_raw(self) -> Self::Raw {
5453        (self as u8).to_raw()
5454    }
5455    fn from_raw(raw: Self::Raw) -> Self {
5456        let t = <u8>::from_raw(raw);
5457        Self::new(t)
5458    }
5459}