// THIS FILE IS AUTOGENERATED.
// Any changes to this file will be overwritten.
// For more information about how codegen works, see font-codegen/README.md

#[allow(unused_imports)]
use crate::codegen_prelude::*;

/// [COLR (Color)](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#colr-header) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ColrMarker {
    base_glyph_list_offset_byte_start: Option<usize>,
    layer_list_offset_byte_start: Option<usize>,
    clip_list_offset_byte_start: Option<usize>,
    var_index_map_offset_byte_start: Option<usize>,
    item_variation_store_offset_byte_start: Option<usize>,
}

impl ColrMarker {
    pub fn version_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u16::RAW_BYTE_LEN
    }

    pub fn num_base_glyph_records_byte_range(&self) -> Range<usize> {
        let start = self.version_byte_range().end;
        start..start + u16::RAW_BYTE_LEN
    }

    pub fn base_glyph_records_offset_byte_range(&self) -> Range<usize> {
        let start = self.num_base_glyph_records_byte_range().end;
        start..start + Offset32::RAW_BYTE_LEN
    }

    pub fn layer_records_offset_byte_range(&self) -> Range<usize> {
        let start = self.base_glyph_records_offset_byte_range().end;
        start..start + Offset32::RAW_BYTE_LEN
    }

    pub fn num_layer_records_byte_range(&self) -> Range<usize> {
        let start = self.layer_records_offset_byte_range().end;
        start..start + u16::RAW_BYTE_LEN
    }

    pub fn base_glyph_list_offset_byte_range(&self) -> Option<Range<usize>> {
        let start = self.base_glyph_list_offset_byte_start?;
        Some(start..start + Offset32::RAW_BYTE_LEN)
    }

    pub fn layer_list_offset_byte_range(&self) -> Option<Range<usize>> {
        let start = self.layer_list_offset_byte_start?;
        Some(start..start + Offset32::RAW_BYTE_LEN)
    }

    pub fn clip_list_offset_byte_range(&self) -> Option<Range<usize>> {
        let start = self.clip_list_offset_byte_start?;
        Some(start..start + Offset32::RAW_BYTE_LEN)
    }

    pub fn var_index_map_offset_byte_range(&self) -> Option<Range<usize>> {
        let start = self.var_index_map_offset_byte_start?;
        Some(start..start + Offset32::RAW_BYTE_LEN)
    }

    pub fn item_variation_store_offset_byte_range(&self) -> Option<Range<usize>> {
        let start = self.item_variation_store_offset_byte_start?;
        Some(start..start + Offset32::RAW_BYTE_LEN)
    }
}

impl MinByteRange for ColrMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.num_layer_records_byte_range().end
    }
}

impl TopLevelTable for Colr<'_> {
    /// `COLR`
    const TAG: Tag = Tag::new(b"COLR");
}

impl<'a> FontRead<'a> for Colr<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        let version: u16 = cursor.read()?;
        cursor.advance::<u16>();
        cursor.advance::<Offset32>();
        cursor.advance::<Offset32>();
        cursor.advance::<u16>();
        let base_glyph_list_offset_byte_start = version
            .compatible(1u16)
            .then(|| cursor.position())
            .transpose()?;
        version
            .compatible(1u16)
            .then(|| cursor.advance::<Offset32>());
        let layer_list_offset_byte_start = version
            .compatible(1u16)
            .then(|| cursor.position())
            .transpose()?;
        version
            .compatible(1u16)
            .then(|| cursor.advance::<Offset32>());
        let clip_list_offset_byte_start = version
            .compatible(1u16)
            .then(|| cursor.position())
            .transpose()?;
        version
            .compatible(1u16)
            .then(|| cursor.advance::<Offset32>());
        let var_index_map_offset_byte_start = version
            .compatible(1u16)
            .then(|| cursor.position())
            .transpose()?;
        version
            .compatible(1u16)
            .then(|| cursor.advance::<Offset32>());
        let item_variation_store_offset_byte_start = version
            .compatible(1u16)
            .then(|| cursor.position())
            .transpose()?;
        version
            .compatible(1u16)
            .then(|| cursor.advance::<Offset32>());
        cursor.finish(ColrMarker {
            base_glyph_list_offset_byte_start,
            layer_list_offset_byte_start,
            clip_list_offset_byte_start,
            var_index_map_offset_byte_start,
            item_variation_store_offset_byte_start,
        })
    }
}

/// [COLR (Color)](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#colr-header) table
pub type Colr<'a> = TableRef<'a, ColrMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> Colr<'a> {
    /// Table version number - set to 0 or 1.
    pub fn version(&self) -> u16 {
        let range = self.shape.version_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Number of BaseGlyph records; may be 0 in a version 1 table.
    pub fn num_base_glyph_records(&self) -> u16 {
        let range = self.shape.num_base_glyph_records_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to baseGlyphRecords array (may be NULL).
    pub fn base_glyph_records_offset(&self) -> Nullable<Offset32> {
        let range = self.shape.base_glyph_records_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`base_glyph_records_offset`][Self::base_glyph_records_offset].
    pub fn base_glyph_records(&self) -> Option<Result<&'a [BaseGlyph], ReadError>> {
        let data = self.data;
        let args = self.num_base_glyph_records();
        self.base_glyph_records_offset()
            .resolve_with_args(data, &args)
    }

    /// Offset to layerRecords array (may be NULL).
    pub fn layer_records_offset(&self) -> Nullable<Offset32> {
        let range = self.shape.layer_records_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`layer_records_offset`][Self::layer_records_offset].
    pub fn layer_records(&self) -> Option<Result<&'a [Layer], ReadError>> {
        let data = self.data;
        let args = self.num_layer_records();
        self.layer_records_offset().resolve_with_args(data, &args)
    }

    /// Number of Layer records; may be 0 in a version 1 table.
    pub fn num_layer_records(&self) -> u16 {
        let range = self.shape.num_layer_records_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to BaseGlyphList table.
    pub fn base_glyph_list_offset(&self) -> Option<Nullable<Offset32>> {
        let range = self.shape.base_glyph_list_offset_byte_range()?;
        Some(self.data.read_at(range.start).unwrap())
    }

    /// Attempt to resolve [`base_glyph_list_offset`][Self::base_glyph_list_offset].
    pub fn base_glyph_list(&self) -> Option<Result<BaseGlyphList<'a>, ReadError>> {
        let data = self.data;
        self.base_glyph_list_offset().map(|x| x.resolve(data))?
    }

    /// Offset to LayerList table (may be NULL).
    pub fn layer_list_offset(&self) -> Option<Nullable<Offset32>> {
        let range = self.shape.layer_list_offset_byte_range()?;
        Some(self.data.read_at(range.start).unwrap())
    }

    /// Attempt to resolve [`layer_list_offset`][Self::layer_list_offset].
    pub fn layer_list(&self) -> Option<Result<LayerList<'a>, ReadError>> {
        let data = self.data;
        self.layer_list_offset().map(|x| x.resolve(data))?
    }

    /// Offset to ClipList table (may be NULL).
    pub fn clip_list_offset(&self) -> Option<Nullable<Offset32>> {
        let range = self.shape.clip_list_offset_byte_range()?;
        Some(self.data.read_at(range.start).unwrap())
    }

    /// Attempt to resolve [`clip_list_offset`][Self::clip_list_offset].
    pub fn clip_list(&self) -> Option<Result<ClipList<'a>, ReadError>> {
        let data = self.data;
        self.clip_list_offset().map(|x| x.resolve(data))?
    }

    /// Offset to DeltaSetIndexMap table (may be NULL).
    pub fn var_index_map_offset(&self) -> Option<Nullable<Offset32>> {
        let range = self.shape.var_index_map_offset_byte_range()?;
        Some(self.data.read_at(range.start).unwrap())
    }

    /// Attempt to resolve [`var_index_map_offset`][Self::var_index_map_offset].
    pub fn var_index_map(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
        let data = self.data;
        self.var_index_map_offset().map(|x| x.resolve(data))?
    }

    /// Offset to ItemVariationStore (may be NULL).
    pub fn item_variation_store_offset(&self) -> Option<Nullable<Offset32>> {
        let range = self.shape.item_variation_store_offset_byte_range()?;
        Some(self.data.read_at(range.start).unwrap())
    }

    /// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset].
    pub fn item_variation_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
        let data = self.data;
        self.item_variation_store_offset()
            .map(|x| x.resolve(data))?
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Colr<'a> {
    fn type_name(&self) -> &str {
        "Colr"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        let version = self.version();
        match idx {
            0usize => Some(Field::new("version", self.version())),
            1usize => Some(Field::new(
                "num_base_glyph_records",
                self.num_base_glyph_records(),
            )),
            2usize => Some(Field::new(
                "base_glyph_records_offset",
                traversal::FieldType::offset_to_array_of_records(
                    self.base_glyph_records_offset(),
                    self.base_glyph_records(),
                    stringify!(BaseGlyph),
                    self.offset_data(),
                ),
            )),
            3usize => Some(Field::new(
                "layer_records_offset",
                traversal::FieldType::offset_to_array_of_records(
                    self.layer_records_offset(),
                    self.layer_records(),
                    stringify!(Layer),
                    self.offset_data(),
                ),
            )),
            4usize => Some(Field::new("num_layer_records", self.num_layer_records())),
            5usize if version.compatible(1u16) => Some(Field::new(
                "base_glyph_list_offset",
                FieldType::offset(
                    self.base_glyph_list_offset().unwrap(),
                    self.base_glyph_list(),
                ),
            )),
            6usize if version.compatible(1u16) => Some(Field::new(
                "layer_list_offset",
                FieldType::offset(self.layer_list_offset().unwrap(), self.layer_list()),
            )),
            7usize if version.compatible(1u16) => Some(Field::new(
                "clip_list_offset",
                FieldType::offset(self.clip_list_offset().unwrap(), self.clip_list()),
            )),
            8usize if version.compatible(1u16) => Some(Field::new(
                "var_index_map_offset",
                FieldType::offset(self.var_index_map_offset().unwrap(), self.var_index_map()),
            )),
            9usize if version.compatible(1u16) => Some(Field::new(
                "item_variation_store_offset",
                FieldType::offset(
                    self.item_variation_store_offset().unwrap(),
                    self.item_variation_store(),
                ),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Colr<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [BaseGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyph-and-layer-records) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct BaseGlyph {
    /// Glyph ID of the base glyph.
    pub glyph_id: BigEndian<GlyphId16>,
    /// Index (base 0) into the layerRecords array.
    pub first_layer_index: BigEndian<u16>,
    /// Number of color layers associated with this glyph.
    pub num_layers: BigEndian<u16>,
}

impl BaseGlyph {
    /// Glyph ID of the base glyph.
    pub fn glyph_id(&self) -> GlyphId16 {
        self.glyph_id.get()
    }

    /// Index (base 0) into the layerRecords array.
    pub fn first_layer_index(&self) -> u16 {
        self.first_layer_index.get()
    }

    /// Number of color layers associated with this glyph.
    pub fn num_layers(&self) -> u16 {
        self.num_layers.get()
    }
}

impl FixedSize for BaseGlyph {
    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for BaseGlyph {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "BaseGlyph",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("glyph_id", self.glyph_id())),
                1usize => Some(Field::new("first_layer_index", self.first_layer_index())),
                2usize => Some(Field::new("num_layers", self.num_layers())),
                _ => None,
            }),
            data,
        }
    }
}

/// [Layer](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyph-and-layer-records) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct Layer {
    /// Glyph ID of the glyph used for a given layer.
    pub glyph_id: BigEndian<GlyphId16>,
    /// Index (base 0) for a palette entry in the CPAL table.
    pub palette_index: BigEndian<u16>,
}

impl Layer {
    /// Glyph ID of the glyph used for a given layer.
    pub fn glyph_id(&self) -> GlyphId16 {
        self.glyph_id.get()
    }

    /// Index (base 0) for a palette entry in the CPAL table.
    pub fn palette_index(&self) -> u16 {
        self.palette_index.get()
    }
}

impl FixedSize for Layer {
    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for Layer {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "Layer",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("glyph_id", self.glyph_id())),
                1usize => Some(Field::new("palette_index", self.palette_index())),
                _ => None,
            }),
            data,
        }
    }
}

/// [BaseGlyphList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct BaseGlyphListMarker {
    base_glyph_paint_records_byte_len: usize,
}

impl BaseGlyphListMarker {
    pub fn num_base_glyph_paint_records_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u32::RAW_BYTE_LEN
    }

    pub fn base_glyph_paint_records_byte_range(&self) -> Range<usize> {
        let start = self.num_base_glyph_paint_records_byte_range().end;
        start..start + self.base_glyph_paint_records_byte_len
    }
}

impl MinByteRange for BaseGlyphListMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.base_glyph_paint_records_byte_range().end
    }
}

impl<'a> FontRead<'a> for BaseGlyphList<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        let num_base_glyph_paint_records: u32 = cursor.read()?;
        let base_glyph_paint_records_byte_len = (num_base_glyph_paint_records as usize)
            .checked_mul(BaseGlyphPaint::RAW_BYTE_LEN)
            .ok_or(ReadError::OutOfBounds)?;
        cursor.advance_by(base_glyph_paint_records_byte_len);
        cursor.finish(BaseGlyphListMarker {
            base_glyph_paint_records_byte_len,
        })
    }
}

/// [BaseGlyphList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
pub type BaseGlyphList<'a> = TableRef<'a, BaseGlyphListMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> BaseGlyphList<'a> {
    pub fn num_base_glyph_paint_records(&self) -> u32 {
        let range = self.shape.num_base_glyph_paint_records_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    pub fn base_glyph_paint_records(&self) -> &'a [BaseGlyphPaint] {
        let range = self.shape.base_glyph_paint_records_byte_range();
        self.data.read_array(range).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for BaseGlyphList<'a> {
    fn type_name(&self) -> &str {
        "BaseGlyphList"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new(
                "num_base_glyph_paint_records",
                self.num_base_glyph_paint_records(),
            )),
            1usize => Some(Field::new(
                "base_glyph_paint_records",
                traversal::FieldType::array_of_records(
                    stringify!(BaseGlyphPaint),
                    self.base_glyph_paint_records(),
                    self.offset_data(),
                ),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for BaseGlyphList<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [BaseGlyphPaint](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct BaseGlyphPaint {
    /// Glyph ID of the base glyph.
    pub glyph_id: BigEndian<GlyphId16>,
    /// Offset to a Paint table, from the beginning of the [`BaseGlyphList`] table.
    pub paint_offset: BigEndian<Offset32>,
}

impl BaseGlyphPaint {
    /// Glyph ID of the base glyph.
    pub fn glyph_id(&self) -> GlyphId16 {
        self.glyph_id.get()
    }

    /// Offset to a Paint table, from the beginning of the [`BaseGlyphList`] table.
    pub fn paint_offset(&self) -> Offset32 {
        self.paint_offset.get()
    }

    /// Offset to a Paint table, from the beginning of the [`BaseGlyphList`] table.
    ///
    /// The `data` argument should be retrieved from the parent table
    /// By calling its `offset_data` method.
    pub fn paint<'a>(&self, data: FontData<'a>) -> Result<Paint<'a>, ReadError> {
        self.paint_offset().resolve(data)
    }
}

impl FixedSize for BaseGlyphPaint {
    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for BaseGlyphPaint {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "BaseGlyphPaint",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("glyph_id", self.glyph_id())),
                1usize => Some(Field::new(
                    "paint_offset",
                    FieldType::offset(self.paint_offset(), self.paint(_data)),
                )),
                _ => None,
            }),
            data,
        }
    }
}

/// [LayerList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct LayerListMarker {
    paint_offsets_byte_len: usize,
}

impl LayerListMarker {
    pub fn num_layers_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u32::RAW_BYTE_LEN
    }

    pub fn paint_offsets_byte_range(&self) -> Range<usize> {
        let start = self.num_layers_byte_range().end;
        start..start + self.paint_offsets_byte_len
    }
}

impl MinByteRange for LayerListMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.paint_offsets_byte_range().end
    }
}

impl<'a> FontRead<'a> for LayerList<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        let num_layers: u32 = cursor.read()?;
        let paint_offsets_byte_len = (num_layers as usize)
            .checked_mul(Offset32::RAW_BYTE_LEN)
            .ok_or(ReadError::OutOfBounds)?;
        cursor.advance_by(paint_offsets_byte_len);
        cursor.finish(LayerListMarker {
            paint_offsets_byte_len,
        })
    }
}

/// [LayerList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
pub type LayerList<'a> = TableRef<'a, LayerListMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> LayerList<'a> {
    pub fn num_layers(&self) -> u32 {
        let range = self.shape.num_layers_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offsets to Paint tables.
    pub fn paint_offsets(&self) -> &'a [BigEndian<Offset32>] {
        let range = self.shape.paint_offsets_byte_range();
        self.data.read_array(range).unwrap()
    }

    /// A dynamically resolving wrapper for [`paint_offsets`][Self::paint_offsets].
    pub fn paints(&self) -> ArrayOfOffsets<'a, Paint<'a>, Offset32> {
        let data = self.data;
        let offsets = self.paint_offsets();
        ArrayOfOffsets::new(offsets, data, ())
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for LayerList<'a> {
    fn type_name(&self) -> &str {
        "LayerList"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("num_layers", self.num_layers())),
            1usize => Some({
                let data = self.data;
                Field::new(
                    "paint_offsets",
                    FieldType::array_of_offsets(
                        better_type_name::<Paint>(),
                        self.paint_offsets(),
                        move |off| {
                            let target = off.get().resolve::<Paint>(data);
                            FieldType::offset(off.get(), target)
                        },
                    ),
                )
            }),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for LayerList<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [ClipList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ClipListMarker {
    clips_byte_len: usize,
}

impl ClipListMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn num_clips_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }

    pub fn clips_byte_range(&self) -> Range<usize> {
        let start = self.num_clips_byte_range().end;
        start..start + self.clips_byte_len
    }
}

impl MinByteRange for ClipListMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.clips_byte_range().end
    }
}

impl<'a> FontRead<'a> for ClipList<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        let num_clips: u32 = cursor.read()?;
        let clips_byte_len = (num_clips as usize)
            .checked_mul(Clip::RAW_BYTE_LEN)
            .ok_or(ReadError::OutOfBounds)?;
        cursor.advance_by(clips_byte_len);
        cursor.finish(ClipListMarker { clips_byte_len })
    }
}

/// [ClipList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
pub type ClipList<'a> = TableRef<'a, ClipListMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> ClipList<'a> {
    /// Set to 1.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Number of Clip records.
    pub fn num_clips(&self) -> u32 {
        let range = self.shape.num_clips_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Clip records. Sorted by startGlyphID.
    pub fn clips(&self) -> &'a [Clip] {
        let range = self.shape.clips_byte_range();
        self.data.read_array(range).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClipList<'a> {
    fn type_name(&self) -> &str {
        "ClipList"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new("num_clips", self.num_clips())),
            2usize => Some(Field::new(
                "clips",
                traversal::FieldType::array_of_records(
                    stringify!(Clip),
                    self.clips(),
                    self.offset_data(),
                ),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ClipList<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [Clip](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct Clip {
    /// First glyph ID in the range.
    pub start_glyph_id: BigEndian<GlyphId16>,
    /// Last glyph ID in the range.
    pub end_glyph_id: BigEndian<GlyphId16>,
    /// Offset to a ClipBox table, from the beginning of the [`ClipList`] table.
    pub clip_box_offset: BigEndian<Offset24>,
}

impl Clip {
    /// First glyph ID in the range.
    pub fn start_glyph_id(&self) -> GlyphId16 {
        self.start_glyph_id.get()
    }

    /// Last glyph ID in the range.
    pub fn end_glyph_id(&self) -> GlyphId16 {
        self.end_glyph_id.get()
    }

    /// Offset to a ClipBox table, from the beginning of the [`ClipList`] table.
    pub fn clip_box_offset(&self) -> Offset24 {
        self.clip_box_offset.get()
    }

    /// Offset to a ClipBox table, from the beginning of the [`ClipList`] table.
    ///
    /// The `data` argument should be retrieved from the parent table
    /// By calling its `offset_data` method.
    pub fn clip_box<'a>(&self, data: FontData<'a>) -> Result<ClipBox<'a>, ReadError> {
        self.clip_box_offset().resolve(data)
    }
}

impl FixedSize for Clip {
    const RAW_BYTE_LEN: usize =
        GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for Clip {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "Clip",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
                1usize => Some(Field::new("end_glyph_id", self.end_glyph_id())),
                2usize => Some(Field::new(
                    "clip_box_offset",
                    FieldType::offset(self.clip_box_offset(), self.clip_box(_data)),
                )),
                _ => None,
            }),
            data,
        }
    }
}

/// [ClipBox](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table
#[derive(Clone)]
pub enum ClipBox<'a> {
    Format1(ClipBoxFormat1<'a>),
    Format2(ClipBoxFormat2<'a>),
}

impl<'a> ClipBox<'a> {
    ///Return the `FontData` used to resolve offsets for this table.
    pub fn offset_data(&self) -> FontData<'a> {
        match self {
            Self::Format1(item) => item.offset_data(),
            Self::Format2(item) => item.offset_data(),
        }
    }

    /// Set to 1.
    pub fn format(&self) -> u8 {
        match self {
            Self::Format1(item) => item.format(),
            Self::Format2(item) => item.format(),
        }
    }

    /// Minimum x of clip box.
    pub fn x_min(&self) -> FWord {
        match self {
            Self::Format1(item) => item.x_min(),
            Self::Format2(item) => item.x_min(),
        }
    }

    /// Minimum y of clip box.
    pub fn y_min(&self) -> FWord {
        match self {
            Self::Format1(item) => item.y_min(),
            Self::Format2(item) => item.y_min(),
        }
    }

    /// Maximum x of clip box.
    pub fn x_max(&self) -> FWord {
        match self {
            Self::Format1(item) => item.x_max(),
            Self::Format2(item) => item.x_max(),
        }
    }

    /// Maximum y of clip box.
    pub fn y_max(&self) -> FWord {
        match self {
            Self::Format1(item) => item.y_max(),
            Self::Format2(item) => item.y_max(),
        }
    }
}

impl<'a> FontRead<'a> for ClipBox<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let format: u8 = data.read_at(0usize)?;
        match format {
            ClipBoxFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
            ClipBoxFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
            other => Err(ReadError::InvalidFormat(other.into())),
        }
    }
}

impl MinByteRange for ClipBox<'_> {
    fn min_byte_range(&self) -> Range<usize> {
        match self {
            Self::Format1(item) => item.min_byte_range(),
            Self::Format2(item) => item.min_byte_range(),
        }
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> ClipBox<'a> {
    fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
        match self {
            Self::Format1(table) => table,
            Self::Format2(table) => table,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for ClipBox<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.dyn_inner().fmt(f)
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClipBox<'a> {
    fn type_name(&self) -> &str {
        self.dyn_inner().type_name()
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        self.dyn_inner().get_field(idx)
    }
}

impl Format<u8> for ClipBoxFormat1Marker {
    const FORMAT: u8 = 1;
}

/// [ClipBoxFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ClipBoxFormat1Marker {}

impl ClipBoxFormat1Marker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn x_min_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y_min_byte_range(&self) -> Range<usize> {
        let start = self.x_min_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn x_max_byte_range(&self) -> Range<usize> {
        let start = self.y_min_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y_max_byte_range(&self) -> Range<usize> {
        let start = self.x_max_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for ClipBoxFormat1Marker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.y_max_byte_range().end
    }
}

impl<'a> FontRead<'a> for ClipBoxFormat1<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.finish(ClipBoxFormat1Marker {})
    }
}

/// [ClipBoxFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
pub type ClipBoxFormat1<'a> = TableRef<'a, ClipBoxFormat1Marker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> ClipBoxFormat1<'a> {
    /// Set to 1.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Minimum x of clip box.
    pub fn x_min(&self) -> FWord {
        let range = self.shape.x_min_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Minimum y of clip box.
    pub fn y_min(&self) -> FWord {
        let range = self.shape.y_min_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Maximum x of clip box.
    pub fn x_max(&self) -> FWord {
        let range = self.shape.x_max_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Maximum y of clip box.
    pub fn y_max(&self) -> FWord {
        let range = self.shape.y_max_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClipBoxFormat1<'a> {
    fn type_name(&self) -> &str {
        "ClipBoxFormat1"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new("x_min", self.x_min())),
            2usize => Some(Field::new("y_min", self.y_min())),
            3usize => Some(Field::new("x_max", self.x_max())),
            4usize => Some(Field::new("y_max", self.y_max())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ClipBoxFormat1<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for ClipBoxFormat2Marker {
    const FORMAT: u8 = 2;
}

/// [ClipBoxFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ClipBoxFormat2Marker {}

impl ClipBoxFormat2Marker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn x_min_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y_min_byte_range(&self) -> Range<usize> {
        let start = self.x_min_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn x_max_byte_range(&self) -> Range<usize> {
        let start = self.y_min_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y_max_byte_range(&self) -> Range<usize> {
        let start = self.x_max_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.y_max_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for ClipBoxFormat2Marker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for ClipBoxFormat2<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<u32>();
        cursor.finish(ClipBoxFormat2Marker {})
    }
}

/// [ClipBoxFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record
pub type ClipBoxFormat2<'a> = TableRef<'a, ClipBoxFormat2Marker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> ClipBoxFormat2<'a> {
    /// Set to 2.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Minimum x of clip box. For variation, use varIndexBase + 0.
    pub fn x_min(&self) -> FWord {
        let range = self.shape.x_min_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Minimum y of clip box. For variation, use varIndexBase + 1.
    pub fn y_min(&self) -> FWord {
        let range = self.shape.y_min_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Maximum x of clip box. For variation, use varIndexBase + 2.
    pub fn x_max(&self) -> FWord {
        let range = self.shape.x_max_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Maximum y of clip box. For variation, use varIndexBase + 3.
    pub fn y_max(&self) -> FWord {
        let range = self.shape.y_max_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClipBoxFormat2<'a> {
    fn type_name(&self) -> &str {
        "ClipBoxFormat2"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new("x_min", self.x_min())),
            2usize => Some(Field::new("y_min", self.y_min())),
            3usize => Some(Field::new("x_max", self.x_max())),
            4usize => Some(Field::new("y_max", self.y_max())),
            5usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ClipBoxFormat2<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [ColorIndex](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ColorIndex {
    /// Index for a CPAL palette entry.
    pub palette_index: BigEndian<u16>,
    /// Alpha value.
    pub alpha: BigEndian<F2Dot14>,
}

impl ColorIndex {
    /// Index for a CPAL palette entry.
    pub fn palette_index(&self) -> u16 {
        self.palette_index.get()
    }

    /// Alpha value.
    pub fn alpha(&self) -> F2Dot14 {
        self.alpha.get()
    }
}

impl FixedSize for ColorIndex {
    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ColorIndex {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "ColorIndex",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("palette_index", self.palette_index())),
                1usize => Some(Field::new("alpha", self.alpha())),
                _ => None,
            }),
            data,
        }
    }
}

/// [VarColorIndex](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct VarColorIndex {
    /// Index for a CPAL palette entry.
    pub palette_index: BigEndian<u16>,
    /// Alpha value. For variation, use varIndexBase + 0.
    pub alpha: BigEndian<F2Dot14>,
    /// Base index into DeltaSetIndexMap.
    pub var_index_base: BigEndian<u32>,
}

impl VarColorIndex {
    /// Index for a CPAL palette entry.
    pub fn palette_index(&self) -> u16 {
        self.palette_index.get()
    }

    /// Alpha value. For variation, use varIndexBase + 0.
    pub fn alpha(&self) -> F2Dot14 {
        self.alpha.get()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        self.var_index_base.get()
    }
}

impl FixedSize for VarColorIndex {
    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for VarColorIndex {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "VarColorIndex",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("palette_index", self.palette_index())),
                1usize => Some(Field::new("alpha", self.alpha())),
                2usize => Some(Field::new("var_index_base", self.var_index_base())),
                _ => None,
            }),
            data,
        }
    }
}

/// [ColorStop](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ColorStop {
    /// Position on a color line.
    pub stop_offset: BigEndian<F2Dot14>,
    /// Index for a CPAL palette entry.
    pub palette_index: BigEndian<u16>,
    /// Alpha value.
    pub alpha: BigEndian<F2Dot14>,
}

impl ColorStop {
    /// Position on a color line.
    pub fn stop_offset(&self) -> F2Dot14 {
        self.stop_offset.get()
    }

    /// Index for a CPAL palette entry.
    pub fn palette_index(&self) -> u16 {
        self.palette_index.get()
    }

    /// Alpha value.
    pub fn alpha(&self) -> F2Dot14 {
        self.alpha.get()
    }
}

impl FixedSize for ColorStop {
    const RAW_BYTE_LEN: usize = F2Dot14::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ColorStop {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "ColorStop",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("stop_offset", self.stop_offset())),
                1usize => Some(Field::new("palette_index", self.palette_index())),
                2usize => Some(Field::new("alpha", self.alpha())),
                _ => None,
            }),
            data,
        }
    }
}

/// [VarColorStop](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct VarColorStop {
    /// Position on a color line. For variation, use varIndexBase + 0.
    pub stop_offset: BigEndian<F2Dot14>,
    /// Index for a CPAL palette entry.
    pub palette_index: BigEndian<u16>,
    /// Alpha value. For variation, use varIndexBase + 1.
    pub alpha: BigEndian<F2Dot14>,
    /// Base index into DeltaSetIndexMap.
    pub var_index_base: BigEndian<u32>,
}

impl VarColorStop {
    /// Position on a color line. For variation, use varIndexBase + 0.
    pub fn stop_offset(&self) -> F2Dot14 {
        self.stop_offset.get()
    }

    /// Index for a CPAL palette entry.
    pub fn palette_index(&self) -> u16 {
        self.palette_index.get()
    }

    /// Alpha value. For variation, use varIndexBase + 1.
    pub fn alpha(&self) -> F2Dot14 {
        self.alpha.get()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        self.var_index_base.get()
    }
}

impl FixedSize for VarColorStop {
    const RAW_BYTE_LEN: usize =
        F2Dot14::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for VarColorStop {
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
        RecordResolver {
            name: "VarColorStop",
            get_field: Box::new(move |idx, _data| match idx {
                0usize => Some(Field::new("stop_offset", self.stop_offset())),
                1usize => Some(Field::new("palette_index", self.palette_index())),
                2usize => Some(Field::new("alpha", self.alpha())),
                3usize => Some(Field::new("var_index_base", self.var_index_base())),
                _ => None,
            }),
            data,
        }
    }
}

/// [ColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ColorLineMarker {
    color_stops_byte_len: usize,
}

impl ColorLineMarker {
    pub fn extend_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + Extend::RAW_BYTE_LEN
    }

    pub fn num_stops_byte_range(&self) -> Range<usize> {
        let start = self.extend_byte_range().end;
        start..start + u16::RAW_BYTE_LEN
    }

    pub fn color_stops_byte_range(&self) -> Range<usize> {
        let start = self.num_stops_byte_range().end;
        start..start + self.color_stops_byte_len
    }
}

impl MinByteRange for ColorLineMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.color_stops_byte_range().end
    }
}

impl<'a> FontRead<'a> for ColorLine<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<Extend>();
        let num_stops: u16 = cursor.read()?;
        let color_stops_byte_len = (num_stops as usize)
            .checked_mul(ColorStop::RAW_BYTE_LEN)
            .ok_or(ReadError::OutOfBounds)?;
        cursor.advance_by(color_stops_byte_len);
        cursor.finish(ColorLineMarker {
            color_stops_byte_len,
        })
    }
}

/// [ColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table
pub type ColorLine<'a> = TableRef<'a, ColorLineMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> ColorLine<'a> {
    /// An Extend enum value.
    pub fn extend(&self) -> Extend {
        let range = self.shape.extend_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Number of ColorStop records.
    pub fn num_stops(&self) -> u16 {
        let range = self.shape.num_stops_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    pub fn color_stops(&self) -> &'a [ColorStop] {
        let range = self.shape.color_stops_byte_range();
        self.data.read_array(range).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ColorLine<'a> {
    fn type_name(&self) -> &str {
        "ColorLine"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("extend", self.extend())),
            1usize => Some(Field::new("num_stops", self.num_stops())),
            2usize => Some(Field::new(
                "color_stops",
                traversal::FieldType::array_of_records(
                    stringify!(ColorStop),
                    self.color_stops(),
                    self.offset_data(),
                ),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ColorLine<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [VarColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VarColorLineMarker {
    color_stops_byte_len: usize,
}

impl VarColorLineMarker {
    pub fn extend_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + Extend::RAW_BYTE_LEN
    }

    pub fn num_stops_byte_range(&self) -> Range<usize> {
        let start = self.extend_byte_range().end;
        start..start + u16::RAW_BYTE_LEN
    }

    pub fn color_stops_byte_range(&self) -> Range<usize> {
        let start = self.num_stops_byte_range().end;
        start..start + self.color_stops_byte_len
    }
}

impl MinByteRange for VarColorLineMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.color_stops_byte_range().end
    }
}

impl<'a> FontRead<'a> for VarColorLine<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<Extend>();
        let num_stops: u16 = cursor.read()?;
        let color_stops_byte_len = (num_stops as usize)
            .checked_mul(VarColorStop::RAW_BYTE_LEN)
            .ok_or(ReadError::OutOfBounds)?;
        cursor.advance_by(color_stops_byte_len);
        cursor.finish(VarColorLineMarker {
            color_stops_byte_len,
        })
    }
}

/// [VarColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table
pub type VarColorLine<'a> = TableRef<'a, VarColorLineMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> VarColorLine<'a> {
    /// An Extend enum value.
    pub fn extend(&self) -> Extend {
        let range = self.shape.extend_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Number of ColorStop records.
    pub fn num_stops(&self) -> u16 {
        let range = self.shape.num_stops_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Allows for variations.
    pub fn color_stops(&self) -> &'a [VarColorStop] {
        let range = self.shape.color_stops_byte_range();
        self.data.read_array(range).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for VarColorLine<'a> {
    fn type_name(&self) -> &str {
        "VarColorLine"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("extend", self.extend())),
            1usize => Some(Field::new("num_stops", self.num_stops())),
            2usize => Some(Field::new(
                "color_stops",
                traversal::FieldType::array_of_records(
                    stringify!(VarColorStop),
                    self.color_stops(),
                    self.offset_data(),
                ),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for VarColorLine<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [Extend](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) enumeration
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
#[allow(clippy::manual_non_exhaustive)]
pub enum Extend {
    #[default]
    Pad = 0,
    Repeat = 1,
    Reflect = 2,
    #[doc(hidden)]
    /// If font data is malformed we will map unknown values to this variant
    Unknown,
}

impl Extend {
    /// Create from a raw scalar.
    ///
    /// This will never fail; unknown values will be mapped to the `Unknown` variant
    pub fn new(raw: u8) -> Self {
        match raw {
            0 => Self::Pad,
            1 => Self::Repeat,
            2 => Self::Reflect,
            _ => Self::Unknown,
        }
    }
}

impl font_types::Scalar for Extend {
    type Raw = <u8 as font_types::Scalar>::Raw;
    fn to_raw(self) -> Self::Raw {
        (self as u8).to_raw()
    }
    fn from_raw(raw: Self::Raw) -> Self {
        let t = <u8>::from_raw(raw);
        Self::new(t)
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> From<Extend> for FieldType<'a> {
    fn from(src: Extend) -> FieldType<'a> {
        (src as u8).into()
    }
}

/// [Paint](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#paint-tables) tables
#[derive(Clone)]
pub enum Paint<'a> {
    ColrLayers(PaintColrLayers<'a>),
    Solid(PaintSolid<'a>),
    VarSolid(PaintVarSolid<'a>),
    LinearGradient(PaintLinearGradient<'a>),
    VarLinearGradient(PaintVarLinearGradient<'a>),
    RadialGradient(PaintRadialGradient<'a>),
    VarRadialGradient(PaintVarRadialGradient<'a>),
    SweepGradient(PaintSweepGradient<'a>),
    VarSweepGradient(PaintVarSweepGradient<'a>),
    Glyph(PaintGlyph<'a>),
    ColrGlyph(PaintColrGlyph<'a>),
    Transform(PaintTransform<'a>),
    VarTransform(PaintVarTransform<'a>),
    Translate(PaintTranslate<'a>),
    VarTranslate(PaintVarTranslate<'a>),
    Scale(PaintScale<'a>),
    VarScale(PaintVarScale<'a>),
    ScaleAroundCenter(PaintScaleAroundCenter<'a>),
    VarScaleAroundCenter(PaintVarScaleAroundCenter<'a>),
    ScaleUniform(PaintScaleUniform<'a>),
    VarScaleUniform(PaintVarScaleUniform<'a>),
    ScaleUniformAroundCenter(PaintScaleUniformAroundCenter<'a>),
    VarScaleUniformAroundCenter(PaintVarScaleUniformAroundCenter<'a>),
    Rotate(PaintRotate<'a>),
    VarRotate(PaintVarRotate<'a>),
    RotateAroundCenter(PaintRotateAroundCenter<'a>),
    VarRotateAroundCenter(PaintVarRotateAroundCenter<'a>),
    Skew(PaintSkew<'a>),
    VarSkew(PaintVarSkew<'a>),
    SkewAroundCenter(PaintSkewAroundCenter<'a>),
    VarSkewAroundCenter(PaintVarSkewAroundCenter<'a>),
    Composite(PaintComposite<'a>),
}

impl<'a> Paint<'a> {
    ///Return the `FontData` used to resolve offsets for this table.
    pub fn offset_data(&self) -> FontData<'a> {
        match self {
            Self::ColrLayers(item) => item.offset_data(),
            Self::Solid(item) => item.offset_data(),
            Self::VarSolid(item) => item.offset_data(),
            Self::LinearGradient(item) => item.offset_data(),
            Self::VarLinearGradient(item) => item.offset_data(),
            Self::RadialGradient(item) => item.offset_data(),
            Self::VarRadialGradient(item) => item.offset_data(),
            Self::SweepGradient(item) => item.offset_data(),
            Self::VarSweepGradient(item) => item.offset_data(),
            Self::Glyph(item) => item.offset_data(),
            Self::ColrGlyph(item) => item.offset_data(),
            Self::Transform(item) => item.offset_data(),
            Self::VarTransform(item) => item.offset_data(),
            Self::Translate(item) => item.offset_data(),
            Self::VarTranslate(item) => item.offset_data(),
            Self::Scale(item) => item.offset_data(),
            Self::VarScale(item) => item.offset_data(),
            Self::ScaleAroundCenter(item) => item.offset_data(),
            Self::VarScaleAroundCenter(item) => item.offset_data(),
            Self::ScaleUniform(item) => item.offset_data(),
            Self::VarScaleUniform(item) => item.offset_data(),
            Self::ScaleUniformAroundCenter(item) => item.offset_data(),
            Self::VarScaleUniformAroundCenter(item) => item.offset_data(),
            Self::Rotate(item) => item.offset_data(),
            Self::VarRotate(item) => item.offset_data(),
            Self::RotateAroundCenter(item) => item.offset_data(),
            Self::VarRotateAroundCenter(item) => item.offset_data(),
            Self::Skew(item) => item.offset_data(),
            Self::VarSkew(item) => item.offset_data(),
            Self::SkewAroundCenter(item) => item.offset_data(),
            Self::VarSkewAroundCenter(item) => item.offset_data(),
            Self::Composite(item) => item.offset_data(),
        }
    }

    /// Set to 1.
    pub fn format(&self) -> u8 {
        match self {
            Self::ColrLayers(item) => item.format(),
            Self::Solid(item) => item.format(),
            Self::VarSolid(item) => item.format(),
            Self::LinearGradient(item) => item.format(),
            Self::VarLinearGradient(item) => item.format(),
            Self::RadialGradient(item) => item.format(),
            Self::VarRadialGradient(item) => item.format(),
            Self::SweepGradient(item) => item.format(),
            Self::VarSweepGradient(item) => item.format(),
            Self::Glyph(item) => item.format(),
            Self::ColrGlyph(item) => item.format(),
            Self::Transform(item) => item.format(),
            Self::VarTransform(item) => item.format(),
            Self::Translate(item) => item.format(),
            Self::VarTranslate(item) => item.format(),
            Self::Scale(item) => item.format(),
            Self::VarScale(item) => item.format(),
            Self::ScaleAroundCenter(item) => item.format(),
            Self::VarScaleAroundCenter(item) => item.format(),
            Self::ScaleUniform(item) => item.format(),
            Self::VarScaleUniform(item) => item.format(),
            Self::ScaleUniformAroundCenter(item) => item.format(),
            Self::VarScaleUniformAroundCenter(item) => item.format(),
            Self::Rotate(item) => item.format(),
            Self::VarRotate(item) => item.format(),
            Self::RotateAroundCenter(item) => item.format(),
            Self::VarRotateAroundCenter(item) => item.format(),
            Self::Skew(item) => item.format(),
            Self::VarSkew(item) => item.format(),
            Self::SkewAroundCenter(item) => item.format(),
            Self::VarSkewAroundCenter(item) => item.format(),
            Self::Composite(item) => item.format(),
        }
    }
}

impl<'a> FontRead<'a> for Paint<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let format: u8 = data.read_at(0usize)?;
        match format {
            PaintColrLayersMarker::FORMAT => Ok(Self::ColrLayers(FontRead::read(data)?)),
            PaintSolidMarker::FORMAT => Ok(Self::Solid(FontRead::read(data)?)),
            PaintVarSolidMarker::FORMAT => Ok(Self::VarSolid(FontRead::read(data)?)),
            PaintLinearGradientMarker::FORMAT => Ok(Self::LinearGradient(FontRead::read(data)?)),
            PaintVarLinearGradientMarker::FORMAT => {
                Ok(Self::VarLinearGradient(FontRead::read(data)?))
            }
            PaintRadialGradientMarker::FORMAT => Ok(Self::RadialGradient(FontRead::read(data)?)),
            PaintVarRadialGradientMarker::FORMAT => {
                Ok(Self::VarRadialGradient(FontRead::read(data)?))
            }
            PaintSweepGradientMarker::FORMAT => Ok(Self::SweepGradient(FontRead::read(data)?)),
            PaintVarSweepGradientMarker::FORMAT => {
                Ok(Self::VarSweepGradient(FontRead::read(data)?))
            }
            PaintGlyphMarker::FORMAT => Ok(Self::Glyph(FontRead::read(data)?)),
            PaintColrGlyphMarker::FORMAT => Ok(Self::ColrGlyph(FontRead::read(data)?)),
            PaintTransformMarker::FORMAT => Ok(Self::Transform(FontRead::read(data)?)),
            PaintVarTransformMarker::FORMAT => Ok(Self::VarTransform(FontRead::read(data)?)),
            PaintTranslateMarker::FORMAT => Ok(Self::Translate(FontRead::read(data)?)),
            PaintVarTranslateMarker::FORMAT => Ok(Self::VarTranslate(FontRead::read(data)?)),
            PaintScaleMarker::FORMAT => Ok(Self::Scale(FontRead::read(data)?)),
            PaintVarScaleMarker::FORMAT => Ok(Self::VarScale(FontRead::read(data)?)),
            PaintScaleAroundCenterMarker::FORMAT => {
                Ok(Self::ScaleAroundCenter(FontRead::read(data)?))
            }
            PaintVarScaleAroundCenterMarker::FORMAT => {
                Ok(Self::VarScaleAroundCenter(FontRead::read(data)?))
            }
            PaintScaleUniformMarker::FORMAT => Ok(Self::ScaleUniform(FontRead::read(data)?)),
            PaintVarScaleUniformMarker::FORMAT => Ok(Self::VarScaleUniform(FontRead::read(data)?)),
            PaintScaleUniformAroundCenterMarker::FORMAT => {
                Ok(Self::ScaleUniformAroundCenter(FontRead::read(data)?))
            }
            PaintVarScaleUniformAroundCenterMarker::FORMAT => {
                Ok(Self::VarScaleUniformAroundCenter(FontRead::read(data)?))
            }
            PaintRotateMarker::FORMAT => Ok(Self::Rotate(FontRead::read(data)?)),
            PaintVarRotateMarker::FORMAT => Ok(Self::VarRotate(FontRead::read(data)?)),
            PaintRotateAroundCenterMarker::FORMAT => {
                Ok(Self::RotateAroundCenter(FontRead::read(data)?))
            }
            PaintVarRotateAroundCenterMarker::FORMAT => {
                Ok(Self::VarRotateAroundCenter(FontRead::read(data)?))
            }
            PaintSkewMarker::FORMAT => Ok(Self::Skew(FontRead::read(data)?)),
            PaintVarSkewMarker::FORMAT => Ok(Self::VarSkew(FontRead::read(data)?)),
            PaintSkewAroundCenterMarker::FORMAT => {
                Ok(Self::SkewAroundCenter(FontRead::read(data)?))
            }
            PaintVarSkewAroundCenterMarker::FORMAT => {
                Ok(Self::VarSkewAroundCenter(FontRead::read(data)?))
            }
            PaintCompositeMarker::FORMAT => Ok(Self::Composite(FontRead::read(data)?)),
            other => Err(ReadError::InvalidFormat(other.into())),
        }
    }
}

impl MinByteRange for Paint<'_> {
    fn min_byte_range(&self) -> Range<usize> {
        match self {
            Self::ColrLayers(item) => item.min_byte_range(),
            Self::Solid(item) => item.min_byte_range(),
            Self::VarSolid(item) => item.min_byte_range(),
            Self::LinearGradient(item) => item.min_byte_range(),
            Self::VarLinearGradient(item) => item.min_byte_range(),
            Self::RadialGradient(item) => item.min_byte_range(),
            Self::VarRadialGradient(item) => item.min_byte_range(),
            Self::SweepGradient(item) => item.min_byte_range(),
            Self::VarSweepGradient(item) => item.min_byte_range(),
            Self::Glyph(item) => item.min_byte_range(),
            Self::ColrGlyph(item) => item.min_byte_range(),
            Self::Transform(item) => item.min_byte_range(),
            Self::VarTransform(item) => item.min_byte_range(),
            Self::Translate(item) => item.min_byte_range(),
            Self::VarTranslate(item) => item.min_byte_range(),
            Self::Scale(item) => item.min_byte_range(),
            Self::VarScale(item) => item.min_byte_range(),
            Self::ScaleAroundCenter(item) => item.min_byte_range(),
            Self::VarScaleAroundCenter(item) => item.min_byte_range(),
            Self::ScaleUniform(item) => item.min_byte_range(),
            Self::VarScaleUniform(item) => item.min_byte_range(),
            Self::ScaleUniformAroundCenter(item) => item.min_byte_range(),
            Self::VarScaleUniformAroundCenter(item) => item.min_byte_range(),
            Self::Rotate(item) => item.min_byte_range(),
            Self::VarRotate(item) => item.min_byte_range(),
            Self::RotateAroundCenter(item) => item.min_byte_range(),
            Self::VarRotateAroundCenter(item) => item.min_byte_range(),
            Self::Skew(item) => item.min_byte_range(),
            Self::VarSkew(item) => item.min_byte_range(),
            Self::SkewAroundCenter(item) => item.min_byte_range(),
            Self::VarSkewAroundCenter(item) => item.min_byte_range(),
            Self::Composite(item) => item.min_byte_range(),
        }
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> Paint<'a> {
    fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
        match self {
            Self::ColrLayers(table) => table,
            Self::Solid(table) => table,
            Self::VarSolid(table) => table,
            Self::LinearGradient(table) => table,
            Self::VarLinearGradient(table) => table,
            Self::RadialGradient(table) => table,
            Self::VarRadialGradient(table) => table,
            Self::SweepGradient(table) => table,
            Self::VarSweepGradient(table) => table,
            Self::Glyph(table) => table,
            Self::ColrGlyph(table) => table,
            Self::Transform(table) => table,
            Self::VarTransform(table) => table,
            Self::Translate(table) => table,
            Self::VarTranslate(table) => table,
            Self::Scale(table) => table,
            Self::VarScale(table) => table,
            Self::ScaleAroundCenter(table) => table,
            Self::VarScaleAroundCenter(table) => table,
            Self::ScaleUniform(table) => table,
            Self::VarScaleUniform(table) => table,
            Self::ScaleUniformAroundCenter(table) => table,
            Self::VarScaleUniformAroundCenter(table) => table,
            Self::Rotate(table) => table,
            Self::VarRotate(table) => table,
            Self::RotateAroundCenter(table) => table,
            Self::VarRotateAroundCenter(table) => table,
            Self::Skew(table) => table,
            Self::VarSkew(table) => table,
            Self::SkewAroundCenter(table) => table,
            Self::VarSkewAroundCenter(table) => table,
            Self::Composite(table) => table,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for Paint<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.dyn_inner().fmt(f)
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Paint<'a> {
    fn type_name(&self) -> &str {
        self.dyn_inner().type_name()
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        self.dyn_inner().get_field(idx)
    }
}

impl Format<u8> for PaintColrLayersMarker {
    const FORMAT: u8 = 1;
}

/// [PaintColrLayers](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-1-paintcolrlayers) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintColrLayersMarker {}

impl PaintColrLayersMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn num_layers_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn first_layer_index_byte_range(&self) -> Range<usize> {
        let start = self.num_layers_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintColrLayersMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.first_layer_index_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintColrLayers<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<u8>();
        cursor.advance::<u32>();
        cursor.finish(PaintColrLayersMarker {})
    }
}

/// [PaintColrLayers](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-1-paintcolrlayers) table
pub type PaintColrLayers<'a> = TableRef<'a, PaintColrLayersMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintColrLayers<'a> {
    /// Set to 1.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Number of offsets to paint tables to read from LayerList.
    pub fn num_layers(&self) -> u8 {
        let range = self.shape.num_layers_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Index (base 0) into the LayerList.
    pub fn first_layer_index(&self) -> u32 {
        let range = self.shape.first_layer_index_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintColrLayers<'a> {
    fn type_name(&self) -> &str {
        "PaintColrLayers"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new("num_layers", self.num_layers())),
            2usize => Some(Field::new("first_layer_index", self.first_layer_index())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintColrLayers<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintSolidMarker {
    const FORMAT: u8 = 2;
}

/// [PaintSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintSolidMarker {}

impl PaintSolidMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn palette_index_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + u16::RAW_BYTE_LEN
    }

    pub fn alpha_byte_range(&self) -> Range<usize> {
        let start = self.palette_index_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintSolidMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.alpha_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintSolid<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<u16>();
        cursor.advance::<F2Dot14>();
        cursor.finish(PaintSolidMarker {})
    }
}

/// [PaintSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table
pub type PaintSolid<'a> = TableRef<'a, PaintSolidMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintSolid<'a> {
    /// Set to 2.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Index for a CPAL palette entry.
    pub fn palette_index(&self) -> u16 {
        let range = self.shape.palette_index_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Alpha value.
    pub fn alpha(&self) -> F2Dot14 {
        let range = self.shape.alpha_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintSolid<'a> {
    fn type_name(&self) -> &str {
        "PaintSolid"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new("palette_index", self.palette_index())),
            2usize => Some(Field::new("alpha", self.alpha())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintSolid<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarSolidMarker {
    const FORMAT: u8 = 3;
}

/// [PaintVarSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarSolidMarker {}

impl PaintVarSolidMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn palette_index_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + u16::RAW_BYTE_LEN
    }

    pub fn alpha_byte_range(&self) -> Range<usize> {
        let start = self.palette_index_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.alpha_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarSolidMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarSolid<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<u16>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarSolidMarker {})
    }
}

/// [PaintVarSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table
pub type PaintVarSolid<'a> = TableRef<'a, PaintVarSolidMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarSolid<'a> {
    /// Set to 3.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Index for a CPAL palette entry.
    pub fn palette_index(&self) -> u16 {
        let range = self.shape.palette_index_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Alpha value. For variation, use varIndexBase + 0.
    pub fn alpha(&self) -> F2Dot14 {
        let range = self.shape.alpha_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarSolid<'a> {
    fn type_name(&self) -> &str {
        "PaintVarSolid"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new("palette_index", self.palette_index())),
            2usize => Some(Field::new("alpha", self.alpha())),
            3usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarSolid<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintLinearGradientMarker {
    const FORMAT: u8 = 4;
}

/// [PaintLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintLinearGradientMarker {}

impl PaintLinearGradientMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x0_byte_range(&self) -> Range<usize> {
        let start = self.color_line_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y0_byte_range(&self) -> Range<usize> {
        let start = self.x0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn x1_byte_range(&self) -> Range<usize> {
        let start = self.y0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y1_byte_range(&self) -> Range<usize> {
        let start = self.x1_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn x2_byte_range(&self) -> Range<usize> {
        let start = self.y1_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y2_byte_range(&self) -> Range<usize> {
        let start = self.x2_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintLinearGradientMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.y2_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintLinearGradient<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.finish(PaintLinearGradientMarker {})
    }
}

/// [PaintLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table
pub type PaintLinearGradient<'a> = TableRef<'a, PaintLinearGradientMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintLinearGradient<'a> {
    /// Set to 4.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to ColorLine table.
    pub fn color_line_offset(&self) -> Offset24 {
        let range = self.shape.color_line_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
    pub fn color_line(&self) -> Result<ColorLine<'a>, ReadError> {
        let data = self.data;
        self.color_line_offset().resolve(data)
    }

    /// Start point (p₀) x coordinate.
    pub fn x0(&self) -> FWord {
        let range = self.shape.x0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start point (p₀) y coordinate.
    pub fn y0(&self) -> FWord {
        let range = self.shape.y0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End point (p₁) x coordinate.
    pub fn x1(&self) -> FWord {
        let range = self.shape.x1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End point (p₁) y coordinate.
    pub fn y1(&self) -> FWord {
        let range = self.shape.y1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Rotation point (p₂) x coordinate.
    pub fn x2(&self) -> FWord {
        let range = self.shape.x2_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Rotation point (p₂) y coordinate.
    pub fn y2(&self) -> FWord {
        let range = self.shape.y2_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintLinearGradient<'a> {
    fn type_name(&self) -> &str {
        "PaintLinearGradient"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "color_line_offset",
                FieldType::offset(self.color_line_offset(), self.color_line()),
            )),
            2usize => Some(Field::new("x0", self.x0())),
            3usize => Some(Field::new("y0", self.y0())),
            4usize => Some(Field::new("x1", self.x1())),
            5usize => Some(Field::new("y1", self.y1())),
            6usize => Some(Field::new("x2", self.x2())),
            7usize => Some(Field::new("y2", self.y2())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintLinearGradient<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarLinearGradientMarker {
    const FORMAT: u8 = 5;
}

/// [PaintVarLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarLinearGradientMarker {}

impl PaintVarLinearGradientMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x0_byte_range(&self) -> Range<usize> {
        let start = self.color_line_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y0_byte_range(&self) -> Range<usize> {
        let start = self.x0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn x1_byte_range(&self) -> Range<usize> {
        let start = self.y0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y1_byte_range(&self) -> Range<usize> {
        let start = self.x1_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn x2_byte_range(&self) -> Range<usize> {
        let start = self.y1_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y2_byte_range(&self) -> Range<usize> {
        let start = self.x2_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.y2_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarLinearGradientMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarLinearGradient<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarLinearGradientMarker {})
    }
}

/// [PaintVarLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table
pub type PaintVarLinearGradient<'a> = TableRef<'a, PaintVarLinearGradientMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarLinearGradient<'a> {
    /// Set to 5.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to VarColorLine table.
    pub fn color_line_offset(&self) -> Offset24 {
        let range = self.shape.color_line_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
    pub fn color_line(&self) -> Result<VarColorLine<'a>, ReadError> {
        let data = self.data;
        self.color_line_offset().resolve(data)
    }

    /// Start point (p₀) x coordinate. For variation, use
    /// varIndexBase + 0.
    pub fn x0(&self) -> FWord {
        let range = self.shape.x0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start point (p₀) y coordinate. For variation, use
    /// varIndexBase + 1.
    pub fn y0(&self) -> FWord {
        let range = self.shape.y0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End point (p₁) x coordinate. For variation, use varIndexBase
    /// + 2.
    pub fn x1(&self) -> FWord {
        let range = self.shape.x1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End point (p₁) y coordinate. For variation, use varIndexBase
    /// + 3.
    pub fn y1(&self) -> FWord {
        let range = self.shape.y1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Rotation point (p₂) x coordinate. For variation, use
    /// varIndexBase + 4.
    pub fn x2(&self) -> FWord {
        let range = self.shape.x2_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Rotation point (p₂) y coordinate. For variation, use
    /// varIndexBase + 5.
    pub fn y2(&self) -> FWord {
        let range = self.shape.y2_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarLinearGradient<'a> {
    fn type_name(&self) -> &str {
        "PaintVarLinearGradient"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "color_line_offset",
                FieldType::offset(self.color_line_offset(), self.color_line()),
            )),
            2usize => Some(Field::new("x0", self.x0())),
            3usize => Some(Field::new("y0", self.y0())),
            4usize => Some(Field::new("x1", self.x1())),
            5usize => Some(Field::new("y1", self.y1())),
            6usize => Some(Field::new("x2", self.x2())),
            7usize => Some(Field::new("y2", self.y2())),
            8usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarLinearGradient<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintRadialGradientMarker {
    const FORMAT: u8 = 6;
}

/// [PaintRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintRadialGradientMarker {}

impl PaintRadialGradientMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x0_byte_range(&self) -> Range<usize> {
        let start = self.color_line_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y0_byte_range(&self) -> Range<usize> {
        let start = self.x0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn radius0_byte_range(&self) -> Range<usize> {
        let start = self.y0_byte_range().end;
        start..start + UfWord::RAW_BYTE_LEN
    }

    pub fn x1_byte_range(&self) -> Range<usize> {
        let start = self.radius0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y1_byte_range(&self) -> Range<usize> {
        let start = self.x1_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn radius1_byte_range(&self) -> Range<usize> {
        let start = self.y1_byte_range().end;
        start..start + UfWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintRadialGradientMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.radius1_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintRadialGradient<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<UfWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<UfWord>();
        cursor.finish(PaintRadialGradientMarker {})
    }
}

/// [PaintRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table
pub type PaintRadialGradient<'a> = TableRef<'a, PaintRadialGradientMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintRadialGradient<'a> {
    /// Set to 6.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to ColorLine table.
    pub fn color_line_offset(&self) -> Offset24 {
        let range = self.shape.color_line_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
    pub fn color_line(&self) -> Result<ColorLine<'a>, ReadError> {
        let data = self.data;
        self.color_line_offset().resolve(data)
    }

    /// Start circle center x coordinate.
    pub fn x0(&self) -> FWord {
        let range = self.shape.x0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start circle center y coordinate.
    pub fn y0(&self) -> FWord {
        let range = self.shape.y0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start circle radius.
    pub fn radius0(&self) -> UfWord {
        let range = self.shape.radius0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End circle center x coordinate.
    pub fn x1(&self) -> FWord {
        let range = self.shape.x1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End circle center y coordinate.
    pub fn y1(&self) -> FWord {
        let range = self.shape.y1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End circle radius.
    pub fn radius1(&self) -> UfWord {
        let range = self.shape.radius1_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintRadialGradient<'a> {
    fn type_name(&self) -> &str {
        "PaintRadialGradient"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "color_line_offset",
                FieldType::offset(self.color_line_offset(), self.color_line()),
            )),
            2usize => Some(Field::new("x0", self.x0())),
            3usize => Some(Field::new("y0", self.y0())),
            4usize => Some(Field::new("radius0", self.radius0())),
            5usize => Some(Field::new("x1", self.x1())),
            6usize => Some(Field::new("y1", self.y1())),
            7usize => Some(Field::new("radius1", self.radius1())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintRadialGradient<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarRadialGradientMarker {
    const FORMAT: u8 = 7;
}

/// [PaintVarRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarRadialGradientMarker {}

impl PaintVarRadialGradientMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x0_byte_range(&self) -> Range<usize> {
        let start = self.color_line_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y0_byte_range(&self) -> Range<usize> {
        let start = self.x0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn radius0_byte_range(&self) -> Range<usize> {
        let start = self.y0_byte_range().end;
        start..start + UfWord::RAW_BYTE_LEN
    }

    pub fn x1_byte_range(&self) -> Range<usize> {
        let start = self.radius0_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn y1_byte_range(&self) -> Range<usize> {
        let start = self.x1_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn radius1_byte_range(&self) -> Range<usize> {
        let start = self.y1_byte_range().end;
        start..start + UfWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.radius1_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarRadialGradientMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarRadialGradient<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<UfWord>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<UfWord>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarRadialGradientMarker {})
    }
}

/// [PaintVarRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table
pub type PaintVarRadialGradient<'a> = TableRef<'a, PaintVarRadialGradientMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarRadialGradient<'a> {
    /// Set to 7.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to VarColorLine table.
    pub fn color_line_offset(&self) -> Offset24 {
        let range = self.shape.color_line_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
    pub fn color_line(&self) -> Result<VarColorLine<'a>, ReadError> {
        let data = self.data;
        self.color_line_offset().resolve(data)
    }

    /// Start circle center x coordinate. For variation, use
    /// varIndexBase + 0.
    pub fn x0(&self) -> FWord {
        let range = self.shape.x0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start circle center y coordinate. For variation, use
    /// varIndexBase + 1.
    pub fn y0(&self) -> FWord {
        let range = self.shape.y0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start circle radius. For variation, use varIndexBase + 2.
    pub fn radius0(&self) -> UfWord {
        let range = self.shape.radius0_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End circle center x coordinate. For variation, use varIndexBase
    /// + 3.
    pub fn x1(&self) -> FWord {
        let range = self.shape.x1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End circle center y coordinate. For variation, use varIndexBase
    /// + 4.
    pub fn y1(&self) -> FWord {
        let range = self.shape.y1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End circle radius. For variation, use varIndexBase + 5.
    pub fn radius1(&self) -> UfWord {
        let range = self.shape.radius1_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarRadialGradient<'a> {
    fn type_name(&self) -> &str {
        "PaintVarRadialGradient"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "color_line_offset",
                FieldType::offset(self.color_line_offset(), self.color_line()),
            )),
            2usize => Some(Field::new("x0", self.x0())),
            3usize => Some(Field::new("y0", self.y0())),
            4usize => Some(Field::new("radius0", self.radius0())),
            5usize => Some(Field::new("x1", self.x1())),
            6usize => Some(Field::new("y1", self.y1())),
            7usize => Some(Field::new("radius1", self.radius1())),
            8usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarRadialGradient<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintSweepGradientMarker {
    const FORMAT: u8 = 8;
}

/// [PaintSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintSweepGradientMarker {}

impl PaintSweepGradientMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.color_line_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn start_angle_byte_range(&self) -> Range<usize> {
        let start = self.center_y_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn end_angle_byte_range(&self) -> Range<usize> {
        let start = self.start_angle_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintSweepGradientMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.end_angle_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintSweepGradient<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.finish(PaintSweepGradientMarker {})
    }
}

/// [PaintSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table
pub type PaintSweepGradient<'a> = TableRef<'a, PaintSweepGradientMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintSweepGradient<'a> {
    /// Set to 8.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to ColorLine table.
    pub fn color_line_offset(&self) -> Offset24 {
        let range = self.shape.color_line_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
    pub fn color_line(&self) -> Result<ColorLine<'a>, ReadError> {
        let data = self.data;
        self.color_line_offset().resolve(data)
    }

    /// Center x coordinate.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Center y coordinate.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start of the angular range of the gradient, 180° in
    /// counter-clockwise degrees per 1.0 of value.
    pub fn start_angle(&self) -> F2Dot14 {
        let range = self.shape.start_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End of the angular range of the gradient, 180° in
    /// counter-clockwise degrees per 1.0 of value.
    pub fn end_angle(&self) -> F2Dot14 {
        let range = self.shape.end_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintSweepGradient<'a> {
    fn type_name(&self) -> &str {
        "PaintSweepGradient"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "color_line_offset",
                FieldType::offset(self.color_line_offset(), self.color_line()),
            )),
            2usize => Some(Field::new("center_x", self.center_x())),
            3usize => Some(Field::new("center_y", self.center_y())),
            4usize => Some(Field::new("start_angle", self.start_angle())),
            5usize => Some(Field::new("end_angle", self.end_angle())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintSweepGradient<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarSweepGradientMarker {
    const FORMAT: u8 = 9;
}

/// [PaintVarSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarSweepGradientMarker {}

impl PaintVarSweepGradientMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn color_line_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.color_line_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn start_angle_byte_range(&self) -> Range<usize> {
        let start = self.center_y_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn end_angle_byte_range(&self) -> Range<usize> {
        let start = self.start_angle_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.end_angle_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarSweepGradientMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarSweepGradient<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarSweepGradientMarker {})
    }
}

/// [PaintVarSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table
pub type PaintVarSweepGradient<'a> = TableRef<'a, PaintVarSweepGradientMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarSweepGradient<'a> {
    /// Set to 9.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to VarColorLine table.
    pub fn color_line_offset(&self) -> Offset24 {
        let range = self.shape.color_line_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`color_line_offset`][Self::color_line_offset].
    pub fn color_line(&self) -> Result<VarColorLine<'a>, ReadError> {
        let data = self.data;
        self.color_line_offset().resolve(data)
    }

    /// Center x coordinate. For variation, use varIndexBase + 0.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Center y coordinate. For variation, use varIndexBase + 1.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Start of the angular range of the gradient, 180° in
    /// counter-clockwise degrees per 1.0 of value. For variation, use
    /// varIndexBase + 2.
    pub fn start_angle(&self) -> F2Dot14 {
        let range = self.shape.start_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// End of the angular range of the gradient, 180° in
    /// counter-clockwise degrees per 1.0 of value. For variation, use
    /// varIndexBase + 3.
    pub fn end_angle(&self) -> F2Dot14 {
        let range = self.shape.end_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarSweepGradient<'a> {
    fn type_name(&self) -> &str {
        "PaintVarSweepGradient"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "color_line_offset",
                FieldType::offset(self.color_line_offset(), self.color_line()),
            )),
            2usize => Some(Field::new("center_x", self.center_x())),
            3usize => Some(Field::new("center_y", self.center_y())),
            4usize => Some(Field::new("start_angle", self.start_angle())),
            5usize => Some(Field::new("end_angle", self.end_angle())),
            6usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarSweepGradient<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintGlyphMarker {
    const FORMAT: u8 = 10;
}

/// [PaintGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-10-paintglyph) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintGlyphMarker {}

impl PaintGlyphMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn glyph_id_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + GlyphId16::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintGlyphMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.glyph_id_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintGlyph<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<GlyphId16>();
        cursor.finish(PaintGlyphMarker {})
    }
}

/// [PaintGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-10-paintglyph) table
pub type PaintGlyph<'a> = TableRef<'a, PaintGlyphMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintGlyph<'a> {
    /// Set to 10.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint table.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Glyph ID for the source outline.
    pub fn glyph_id(&self) -> GlyphId16 {
        let range = self.shape.glyph_id_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintGlyph<'a> {
    fn type_name(&self) -> &str {
        "PaintGlyph"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("glyph_id", self.glyph_id())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintGlyph<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintColrGlyphMarker {
    const FORMAT: u8 = 11;
}

/// [PaintColrGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-11-paintcolrglyph) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintColrGlyphMarker {}

impl PaintColrGlyphMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn glyph_id_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + GlyphId16::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintColrGlyphMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.glyph_id_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintColrGlyph<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<GlyphId16>();
        cursor.finish(PaintColrGlyphMarker {})
    }
}

/// [PaintColrGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-11-paintcolrglyph) table
pub type PaintColrGlyph<'a> = TableRef<'a, PaintColrGlyphMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintColrGlyph<'a> {
    /// Set to 11.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Glyph ID for a BaseGlyphList base glyph.
    pub fn glyph_id(&self) -> GlyphId16 {
        let range = self.shape.glyph_id_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintColrGlyph<'a> {
    fn type_name(&self) -> &str {
        "PaintColrGlyph"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new("glyph_id", self.glyph_id())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintColrGlyph<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintTransformMarker {
    const FORMAT: u8 = 12;
}

/// [PaintTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintTransformMarker {}

impl PaintTransformMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn transform_offset_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintTransformMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.transform_offset_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintTransform<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<Offset24>();
        cursor.finish(PaintTransformMarker {})
    }
}

/// [PaintTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table
pub type PaintTransform<'a> = TableRef<'a, PaintTransformMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintTransform<'a> {
    /// Set to 12.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Offset to an Affine2x3 table.
    pub fn transform_offset(&self) -> Offset24 {
        let range = self.shape.transform_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`transform_offset`][Self::transform_offset].
    pub fn transform(&self) -> Result<Affine2x3<'a>, ReadError> {
        let data = self.data;
        self.transform_offset().resolve(data)
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintTransform<'a> {
    fn type_name(&self) -> &str {
        "PaintTransform"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new(
                "transform_offset",
                FieldType::offset(self.transform_offset(), self.transform()),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintTransform<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarTransformMarker {
    const FORMAT: u8 = 13;
}

/// [PaintVarTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarTransformMarker {}

impl PaintVarTransformMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn transform_offset_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarTransformMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.transform_offset_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarTransform<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<Offset24>();
        cursor.finish(PaintVarTransformMarker {})
    }
}

/// [PaintVarTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table
pub type PaintVarTransform<'a> = TableRef<'a, PaintVarTransformMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarTransform<'a> {
    /// Set to 13.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Offset to a VarAffine2x3 table.
    pub fn transform_offset(&self) -> Offset24 {
        let range = self.shape.transform_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`transform_offset`][Self::transform_offset].
    pub fn transform(&self) -> Result<VarAffine2x3<'a>, ReadError> {
        let data = self.data;
        self.transform_offset().resolve(data)
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarTransform<'a> {
    fn type_name(&self) -> &str {
        "PaintVarTransform"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new(
                "transform_offset",
                FieldType::offset(self.transform_offset(), self.transform()),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarTransform<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [Affine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Affine2x3Marker {}

impl Affine2x3Marker {
    pub fn xx_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn yx_byte_range(&self) -> Range<usize> {
        let start = self.xx_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn xy_byte_range(&self) -> Range<usize> {
        let start = self.yx_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn yy_byte_range(&self) -> Range<usize> {
        let start = self.xy_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn dx_byte_range(&self) -> Range<usize> {
        let start = self.yy_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn dy_byte_range(&self) -> Range<usize> {
        let start = self.dx_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }
}

impl MinByteRange for Affine2x3Marker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.dy_byte_range().end
    }
}

impl<'a> FontRead<'a> for Affine2x3<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.finish(Affine2x3Marker {})
    }
}

/// [Affine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record
pub type Affine2x3<'a> = TableRef<'a, Affine2x3Marker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> Affine2x3<'a> {
    /// x-component of transformed x-basis vector.
    pub fn xx(&self) -> Fixed {
        let range = self.shape.xx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y-component of transformed x-basis vector.
    pub fn yx(&self) -> Fixed {
        let range = self.shape.yx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x-component of transformed y-basis vector.
    pub fn xy(&self) -> Fixed {
        let range = self.shape.xy_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y-component of transformed y-basis vector.
    pub fn yy(&self) -> Fixed {
        let range = self.shape.yy_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Translation in x direction.
    pub fn dx(&self) -> Fixed {
        let range = self.shape.dx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Translation in y direction.
    pub fn dy(&self) -> Fixed {
        let range = self.shape.dy_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Affine2x3<'a> {
    fn type_name(&self) -> &str {
        "Affine2x3"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("xx", self.xx())),
            1usize => Some(Field::new("yx", self.yx())),
            2usize => Some(Field::new("xy", self.xy())),
            3usize => Some(Field::new("yy", self.yy())),
            4usize => Some(Field::new("dx", self.dx())),
            5usize => Some(Field::new("dy", self.dy())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Affine2x3<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [VarAffine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VarAffine2x3Marker {}

impl VarAffine2x3Marker {
    pub fn xx_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn yx_byte_range(&self) -> Range<usize> {
        let start = self.xx_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn xy_byte_range(&self) -> Range<usize> {
        let start = self.yx_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn yy_byte_range(&self) -> Range<usize> {
        let start = self.xy_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn dx_byte_range(&self) -> Range<usize> {
        let start = self.yy_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn dy_byte_range(&self) -> Range<usize> {
        let start = self.dx_byte_range().end;
        start..start + Fixed::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.dy_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for VarAffine2x3Marker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for VarAffine2x3<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<Fixed>();
        cursor.advance::<u32>();
        cursor.finish(VarAffine2x3Marker {})
    }
}

/// [VarAffine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record
pub type VarAffine2x3<'a> = TableRef<'a, VarAffine2x3Marker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> VarAffine2x3<'a> {
    /// x-component of transformed x-basis vector. For variation, use
    /// varIndexBase + 0.
    pub fn xx(&self) -> Fixed {
        let range = self.shape.xx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y-component of transformed x-basis vector. For variation, use
    /// varIndexBase + 1.
    pub fn yx(&self) -> Fixed {
        let range = self.shape.yx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x-component of transformed y-basis vector. For variation, use
    /// varIndexBase + 2.
    pub fn xy(&self) -> Fixed {
        let range = self.shape.xy_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y-component of transformed y-basis vector. For variation, use
    /// varIndexBase + 3.
    pub fn yy(&self) -> Fixed {
        let range = self.shape.yy_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Translation in x direction. For variation, use varIndexBase + 4.
    pub fn dx(&self) -> Fixed {
        let range = self.shape.dx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Translation in y direction. For variation, use varIndexBase + 5.
    pub fn dy(&self) -> Fixed {
        let range = self.shape.dy_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for VarAffine2x3<'a> {
    fn type_name(&self) -> &str {
        "VarAffine2x3"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("xx", self.xx())),
            1usize => Some(Field::new("yx", self.yx())),
            2usize => Some(Field::new("xy", self.xy())),
            3usize => Some(Field::new("yy", self.yy())),
            4usize => Some(Field::new("dx", self.dx())),
            5usize => Some(Field::new("dy", self.dy())),
            6usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for VarAffine2x3<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintTranslateMarker {
    const FORMAT: u8 = 14;
}

/// [PaintTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintTranslateMarker {}

impl PaintTranslateMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn dx_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn dy_byte_range(&self) -> Range<usize> {
        let start = self.dx_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintTranslateMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.dy_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintTranslate<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.finish(PaintTranslateMarker {})
    }
}

/// [PaintTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table
pub type PaintTranslate<'a> = TableRef<'a, PaintTranslateMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintTranslate<'a> {
    /// Set to 14.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Translation in x direction.
    pub fn dx(&self) -> FWord {
        let range = self.shape.dx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Translation in y direction.
    pub fn dy(&self) -> FWord {
        let range = self.shape.dy_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintTranslate<'a> {
    fn type_name(&self) -> &str {
        "PaintTranslate"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("dx", self.dx())),
            3usize => Some(Field::new("dy", self.dy())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintTranslate<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarTranslateMarker {
    const FORMAT: u8 = 15;
}

/// [PaintVarTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarTranslateMarker {}

impl PaintVarTranslateMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn dx_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn dy_byte_range(&self) -> Range<usize> {
        let start = self.dx_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.dy_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarTranslateMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarTranslate<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarTranslateMarker {})
    }
}

/// [PaintVarTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table
pub type PaintVarTranslate<'a> = TableRef<'a, PaintVarTranslateMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarTranslate<'a> {
    /// Set to 15.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Translation in x direction. For variation, use varIndexBase + 0.
    pub fn dx(&self) -> FWord {
        let range = self.shape.dx_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Translation in y direction. For variation, use varIndexBase + 1.
    pub fn dy(&self) -> FWord {
        let range = self.shape.dy_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarTranslate<'a> {
    fn type_name(&self) -> &str {
        "PaintVarTranslate"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("dx", self.dx())),
            3usize => Some(Field::new("dy", self.dy())),
            4usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarTranslate<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintScaleMarker {
    const FORMAT: u8 = 16;
}

/// [PaintScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintScaleMarker {}

impl PaintScaleMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_x_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn scale_y_byte_range(&self) -> Range<usize> {
        let start = self.scale_x_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintScaleMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.scale_y_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintScale<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.finish(PaintScaleMarker {})
    }
}

/// [PaintScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintScale<'a> = TableRef<'a, PaintScaleMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintScale<'a> {
    /// Set to 16.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x direction.
    pub fn scale_x(&self) -> F2Dot14 {
        let range = self.shape.scale_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Scale factor in y direction.
    pub fn scale_y(&self) -> F2Dot14 {
        let range = self.shape.scale_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintScale<'a> {
    fn type_name(&self) -> &str {
        "PaintScale"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale_x", self.scale_x())),
            3usize => Some(Field::new("scale_y", self.scale_y())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintScale<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarScaleMarker {
    const FORMAT: u8 = 17;
}

/// [PaintVarScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarScaleMarker {}

impl PaintVarScaleMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_x_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn scale_y_byte_range(&self) -> Range<usize> {
        let start = self.scale_x_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.scale_y_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarScaleMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarScale<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarScaleMarker {})
    }
}

/// [PaintVarScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintVarScale<'a> = TableRef<'a, PaintVarScaleMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarScale<'a> {
    /// Set to 17.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x direction. For variation, use varIndexBase +
    /// 0.
    pub fn scale_x(&self) -> F2Dot14 {
        let range = self.shape.scale_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Scale factor in y direction. For variation, use varIndexBase +
    /// 1.
    pub fn scale_y(&self) -> F2Dot14 {
        let range = self.shape.scale_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarScale<'a> {
    fn type_name(&self) -> &str {
        "PaintVarScale"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale_x", self.scale_x())),
            3usize => Some(Field::new("scale_y", self.scale_y())),
            4usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarScale<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintScaleAroundCenterMarker {
    const FORMAT: u8 = 18;
}

/// [PaintScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintScaleAroundCenterMarker {}

impl PaintScaleAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_x_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn scale_y_byte_range(&self) -> Range<usize> {
        let start = self.scale_x_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.scale_y_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintScaleAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.center_y_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintScaleAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.finish(PaintScaleAroundCenterMarker {})
    }
}

/// [PaintScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintScaleAroundCenter<'a> = TableRef<'a, PaintScaleAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintScaleAroundCenter<'a> {
    /// Set to 18.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x direction.
    pub fn scale_x(&self) -> F2Dot14 {
        let range = self.shape.scale_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Scale factor in y direction.
    pub fn scale_y(&self) -> F2Dot14 {
        let range = self.shape.scale_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of scaling.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of scaling.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintScaleAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintScaleAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale_x", self.scale_x())),
            3usize => Some(Field::new("scale_y", self.scale_y())),
            4usize => Some(Field::new("center_x", self.center_x())),
            5usize => Some(Field::new("center_y", self.center_y())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintScaleAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarScaleAroundCenterMarker {
    const FORMAT: u8 = 19;
}

/// [PaintVarScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarScaleAroundCenterMarker {}

impl PaintVarScaleAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_x_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn scale_y_byte_range(&self) -> Range<usize> {
        let start = self.scale_x_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.scale_y_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.center_y_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarScaleAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarScaleAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarScaleAroundCenterMarker {})
    }
}

/// [PaintVarScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintVarScaleAroundCenter<'a> = TableRef<'a, PaintVarScaleAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarScaleAroundCenter<'a> {
    /// Set to 19.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x direction. For variation, use varIndexBase +
    /// 0.
    pub fn scale_x(&self) -> F2Dot14 {
        let range = self.shape.scale_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Scale factor in y direction. For variation, use varIndexBase +
    /// 1.
    pub fn scale_y(&self) -> F2Dot14 {
        let range = self.shape.scale_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of scaling. For variation, use
    /// varIndexBase + 2.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of scaling. For variation, use
    /// varIndexBase + 3.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarScaleAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintVarScaleAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale_x", self.scale_x())),
            3usize => Some(Field::new("scale_y", self.scale_y())),
            4usize => Some(Field::new("center_x", self.center_x())),
            5usize => Some(Field::new("center_y", self.center_y())),
            6usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarScaleAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintScaleUniformMarker {
    const FORMAT: u8 = 20;
}

/// [PaintScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintScaleUniformMarker {}

impl PaintScaleUniformMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintScaleUniformMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.scale_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintScaleUniform<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.finish(PaintScaleUniformMarker {})
    }
}

/// [PaintScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintScaleUniform<'a> = TableRef<'a, PaintScaleUniformMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintScaleUniform<'a> {
    /// Set to 20.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x and y directions.
    pub fn scale(&self) -> F2Dot14 {
        let range = self.shape.scale_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintScaleUniform<'a> {
    fn type_name(&self) -> &str {
        "PaintScaleUniform"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale", self.scale())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintScaleUniform<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarScaleUniformMarker {
    const FORMAT: u8 = 21;
}

/// [PaintVarScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarScaleUniformMarker {}

impl PaintVarScaleUniformMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.scale_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarScaleUniformMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarScaleUniform<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarScaleUniformMarker {})
    }
}

/// [PaintVarScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintVarScaleUniform<'a> = TableRef<'a, PaintVarScaleUniformMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarScaleUniform<'a> {
    /// Set to 21.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x and y directions. For variation, use
    /// varIndexBase + 0.
    pub fn scale(&self) -> F2Dot14 {
        let range = self.shape.scale_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarScaleUniform<'a> {
    fn type_name(&self) -> &str {
        "PaintVarScaleUniform"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale", self.scale())),
            3usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarScaleUniform<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintScaleUniformAroundCenterMarker {
    const FORMAT: u8 = 22;
}

/// [PaintScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintScaleUniformAroundCenterMarker {}

impl PaintScaleUniformAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.scale_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintScaleUniformAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.center_y_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintScaleUniformAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.finish(PaintScaleUniformAroundCenterMarker {})
    }
}

/// [PaintScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintScaleUniformAroundCenter<'a> = TableRef<'a, PaintScaleUniformAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintScaleUniformAroundCenter<'a> {
    /// Set to 22.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x and y directions.
    pub fn scale(&self) -> F2Dot14 {
        let range = self.shape.scale_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of scaling.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of scaling.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintScaleUniformAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintScaleUniformAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale", self.scale())),
            3usize => Some(Field::new("center_x", self.center_x())),
            4usize => Some(Field::new("center_y", self.center_y())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintScaleUniformAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarScaleUniformAroundCenterMarker {
    const FORMAT: u8 = 23;
}

/// [PaintVarScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarScaleUniformAroundCenterMarker {}

impl PaintVarScaleUniformAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn scale_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.scale_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.center_y_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarScaleUniformAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarScaleUniformAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarScaleUniformAroundCenterMarker {})
    }
}

/// [PaintVarScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table
pub type PaintVarScaleUniformAroundCenter<'a> =
    TableRef<'a, PaintVarScaleUniformAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarScaleUniformAroundCenter<'a> {
    /// Set to 23.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Scale factor in x and y directions. For variation, use
    /// varIndexBase + 0.
    pub fn scale(&self) -> F2Dot14 {
        let range = self.shape.scale_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of scaling. For variation, use
    /// varIndexBase + 1.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of scaling. For variation, use
    /// varIndexBase + 2.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarScaleUniformAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintVarScaleUniformAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("scale", self.scale())),
            3usize => Some(Field::new("center_x", self.center_x())),
            4usize => Some(Field::new("center_y", self.center_y())),
            5usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarScaleUniformAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintRotateMarker {
    const FORMAT: u8 = 24;
}

/// [PaintRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintRotateMarker {}

impl PaintRotateMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintRotateMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.angle_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintRotate<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.finish(PaintRotateMarker {})
    }
}

/// [PaintRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
pub type PaintRotate<'a> = TableRef<'a, PaintRotateMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintRotate<'a> {
    /// Set to 24.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
    /// value.
    pub fn angle(&self) -> F2Dot14 {
        let range = self.shape.angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintRotate<'a> {
    fn type_name(&self) -> &str {
        "PaintRotate"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("angle", self.angle())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintRotate<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarRotateMarker {
    const FORMAT: u8 = 25;
}

/// [PaintVarRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarRotateMarker {}

impl PaintVarRotateMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.angle_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarRotateMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarRotate<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarRotateMarker {})
    }
}

/// [PaintVarRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
pub type PaintVarRotate<'a> = TableRef<'a, PaintVarRotateMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarRotate<'a> {
    /// Set to 25.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
    /// value. For variation, use varIndexBase + 0.
    pub fn angle(&self) -> F2Dot14 {
        let range = self.shape.angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarRotate<'a> {
    fn type_name(&self) -> &str {
        "PaintVarRotate"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("angle", self.angle())),
            3usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarRotate<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintRotateAroundCenterMarker {
    const FORMAT: u8 = 26;
}

/// [PaintRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintRotateAroundCenterMarker {}

impl PaintRotateAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.angle_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintRotateAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.center_y_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintRotateAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.finish(PaintRotateAroundCenterMarker {})
    }
}

/// [PaintRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
pub type PaintRotateAroundCenter<'a> = TableRef<'a, PaintRotateAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintRotateAroundCenter<'a> {
    /// Set to 26.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
    /// value.
    pub fn angle(&self) -> F2Dot14 {
        let range = self.shape.angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of rotation.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of rotation.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintRotateAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintRotateAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("angle", self.angle())),
            3usize => Some(Field::new("center_x", self.center_x())),
            4usize => Some(Field::new("center_y", self.center_y())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintRotateAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarRotateAroundCenterMarker {
    const FORMAT: u8 = 27;
}

/// [PaintVarRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarRotateAroundCenterMarker {}

impl PaintVarRotateAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.angle_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.center_y_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarRotateAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarRotateAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarRotateAroundCenterMarker {})
    }
}

/// [PaintVarRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table
pub type PaintVarRotateAroundCenter<'a> = TableRef<'a, PaintVarRotateAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarRotateAroundCenter<'a> {
    /// Set to 27.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of
    /// value. For variation, use varIndexBase + 0.
    pub fn angle(&self) -> F2Dot14 {
        let range = self.shape.angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of rotation. For variation, use
    /// varIndexBase + 1.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of rotation. For variation, use
    /// varIndexBase + 2.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarRotateAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintVarRotateAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("angle", self.angle())),
            3usize => Some(Field::new("center_x", self.center_x())),
            4usize => Some(Field::new("center_y", self.center_y())),
            5usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarRotateAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintSkewMarker {
    const FORMAT: u8 = 28;
}

/// [PaintSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintSkewMarker {}

impl PaintSkewMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.x_skew_angle_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintSkewMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.y_skew_angle_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintSkew<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.finish(PaintSkewMarker {})
    }
}

/// [PaintSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
pub type PaintSkew<'a> = TableRef<'a, PaintSkewMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintSkew<'a> {
    /// Set to 28.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Angle of skew in the direction of the x-axis, 180° in
    /// counter-clockwise degrees per 1.0 of value.
    pub fn x_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.x_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Angle of skew in the direction of the y-axis, 180° in
    /// counter-clockwise degrees per 1.0 of value.
    pub fn y_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.y_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintSkew<'a> {
    fn type_name(&self) -> &str {
        "PaintSkew"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("x_skew_angle", self.x_skew_angle())),
            3usize => Some(Field::new("y_skew_angle", self.y_skew_angle())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintSkew<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarSkewMarker {
    const FORMAT: u8 = 29;
}

/// [PaintVarSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarSkewMarker {}

impl PaintVarSkewMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.x_skew_angle_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.y_skew_angle_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarSkewMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarSkew<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarSkewMarker {})
    }
}

/// [PaintVarSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
pub type PaintVarSkew<'a> = TableRef<'a, PaintVarSkewMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarSkew<'a> {
    /// Set to 29.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Angle of skew in the direction of the x-axis, 180° ┬░ in
    /// counter-clockwise degrees per 1.0 of value. For variation, use
    /// varIndexBase + 0.
    pub fn x_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.x_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Angle of skew in the direction of the y-axis, 180° in
    /// counter-clockwise degrees per 1.0 of value. For variation, use
    /// varIndexBase + 1.
    pub fn y_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.y_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarSkew<'a> {
    fn type_name(&self) -> &str {
        "PaintVarSkew"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("x_skew_angle", self.x_skew_angle())),
            3usize => Some(Field::new("y_skew_angle", self.y_skew_angle())),
            4usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarSkew<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintSkewAroundCenterMarker {
    const FORMAT: u8 = 30;
}

/// [PaintSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintSkewAroundCenterMarker {}

impl PaintSkewAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.x_skew_angle_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.y_skew_angle_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintSkewAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.center_y_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintSkewAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.finish(PaintSkewAroundCenterMarker {})
    }
}

/// [PaintSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
pub type PaintSkewAroundCenter<'a> = TableRef<'a, PaintSkewAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintSkewAroundCenter<'a> {
    /// Set to 30.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Angle of skew in the direction of the x-axis, 180° in
    /// counter-clockwise degrees per 1.0 of value.
    pub fn x_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.x_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Angle of skew in the direction of the y-axis, 180° in
    /// counter-clockwise degrees per 1.0 of value.
    pub fn y_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.y_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of rotation.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of rotation.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintSkewAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintSkewAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("x_skew_angle", self.x_skew_angle())),
            3usize => Some(Field::new("y_skew_angle", self.y_skew_angle())),
            4usize => Some(Field::new("center_x", self.center_x())),
            5usize => Some(Field::new("center_y", self.center_y())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintSkewAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintVarSkewAroundCenterMarker {
    const FORMAT: u8 = 31;
}

/// [PaintVarSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintVarSkewAroundCenterMarker {}

impl PaintVarSkewAroundCenterMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn x_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.paint_offset_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn y_skew_angle_byte_range(&self) -> Range<usize> {
        let start = self.x_skew_angle_byte_range().end;
        start..start + F2Dot14::RAW_BYTE_LEN
    }

    pub fn center_x_byte_range(&self) -> Range<usize> {
        let start = self.y_skew_angle_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn center_y_byte_range(&self) -> Range<usize> {
        let start = self.center_x_byte_range().end;
        start..start + FWord::RAW_BYTE_LEN
    }

    pub fn var_index_base_byte_range(&self) -> Range<usize> {
        let start = self.center_y_byte_range().end;
        start..start + u32::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintVarSkewAroundCenterMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.var_index_base_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintVarSkewAroundCenter<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<F2Dot14>();
        cursor.advance::<FWord>();
        cursor.advance::<FWord>();
        cursor.advance::<u32>();
        cursor.finish(PaintVarSkewAroundCenterMarker {})
    }
}

/// [PaintVarSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table
pub type PaintVarSkewAroundCenter<'a> = TableRef<'a, PaintVarSkewAroundCenterMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintVarSkewAroundCenter<'a> {
    /// Set to 31.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a Paint subtable.
    pub fn paint_offset(&self) -> Offset24 {
        let range = self.shape.paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`paint_offset`][Self::paint_offset].
    pub fn paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.paint_offset().resolve(data)
    }

    /// Angle of skew in the direction of the x-axis, 180° in
    /// counter-clockwise degrees per 1.0 of value. For variation, use
    /// varIndexBase + 0.
    pub fn x_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.x_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Angle of skew in the direction of the y-axis, 180° in
    /// counter-clockwise degrees per 1.0 of value. For variation, use
    /// varIndexBase + 1.
    pub fn y_skew_angle(&self) -> F2Dot14 {
        let range = self.shape.y_skew_angle_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// x coordinate for the center of rotation. For variation, use
    /// varIndexBase + 2.
    pub fn center_x(&self) -> FWord {
        let range = self.shape.center_x_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// y coordinate for the center of rotation. For variation, use
    /// varIndexBase + 3.
    pub fn center_y(&self) -> FWord {
        let range = self.shape.center_y_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Base index into DeltaSetIndexMap.
    pub fn var_index_base(&self) -> u32 {
        let range = self.shape.var_index_base_byte_range();
        self.data.read_at(range.start).unwrap()
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintVarSkewAroundCenter<'a> {
    fn type_name(&self) -> &str {
        "PaintVarSkewAroundCenter"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "paint_offset",
                FieldType::offset(self.paint_offset(), self.paint()),
            )),
            2usize => Some(Field::new("x_skew_angle", self.x_skew_angle())),
            3usize => Some(Field::new("y_skew_angle", self.y_skew_angle())),
            4usize => Some(Field::new("center_x", self.center_x())),
            5usize => Some(Field::new("center_y", self.center_y())),
            6usize => Some(Field::new("var_index_base", self.var_index_base())),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintVarSkewAroundCenter<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

impl Format<u8> for PaintCompositeMarker {
    const FORMAT: u8 = 32;
}

/// [PaintComposite](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PaintCompositeMarker {}

impl PaintCompositeMarker {
    pub fn format_byte_range(&self) -> Range<usize> {
        let start = 0;
        start..start + u8::RAW_BYTE_LEN
    }

    pub fn source_paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.format_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }

    pub fn composite_mode_byte_range(&self) -> Range<usize> {
        let start = self.source_paint_offset_byte_range().end;
        start..start + CompositeMode::RAW_BYTE_LEN
    }

    pub fn backdrop_paint_offset_byte_range(&self) -> Range<usize> {
        let start = self.composite_mode_byte_range().end;
        start..start + Offset24::RAW_BYTE_LEN
    }
}

impl MinByteRange for PaintCompositeMarker {
    fn min_byte_range(&self) -> Range<usize> {
        0..self.backdrop_paint_offset_byte_range().end
    }
}

impl<'a> FontRead<'a> for PaintComposite<'a> {
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
        let mut cursor = data.cursor();
        cursor.advance::<u8>();
        cursor.advance::<Offset24>();
        cursor.advance::<CompositeMode>();
        cursor.advance::<Offset24>();
        cursor.finish(PaintCompositeMarker {})
    }
}

/// [PaintComposite](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) table
pub type PaintComposite<'a> = TableRef<'a, PaintCompositeMarker>;

#[allow(clippy::needless_lifetimes)]
impl<'a> PaintComposite<'a> {
    /// Set to 32.
    pub fn format(&self) -> u8 {
        let range = self.shape.format_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a source Paint table.
    pub fn source_paint_offset(&self) -> Offset24 {
        let range = self.shape.source_paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`source_paint_offset`][Self::source_paint_offset].
    pub fn source_paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.source_paint_offset().resolve(data)
    }

    /// A CompositeMode enumeration value.
    pub fn composite_mode(&self) -> CompositeMode {
        let range = self.shape.composite_mode_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Offset to a backdrop Paint table.
    pub fn backdrop_paint_offset(&self) -> Offset24 {
        let range = self.shape.backdrop_paint_offset_byte_range();
        self.data.read_at(range.start).unwrap()
    }

    /// Attempt to resolve [`backdrop_paint_offset`][Self::backdrop_paint_offset].
    pub fn backdrop_paint(&self) -> Result<Paint<'a>, ReadError> {
        let data = self.data;
        self.backdrop_paint_offset().resolve(data)
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for PaintComposite<'a> {
    fn type_name(&self) -> &str {
        "PaintComposite"
    }
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
        match idx {
            0usize => Some(Field::new("format", self.format())),
            1usize => Some(Field::new(
                "source_paint_offset",
                FieldType::offset(self.source_paint_offset(), self.source_paint()),
            )),
            2usize => Some(Field::new("composite_mode", self.composite_mode())),
            3usize => Some(Field::new(
                "backdrop_paint_offset",
                FieldType::offset(self.backdrop_paint_offset(), self.backdrop_paint()),
            )),
            _ => None,
        }
    }
}

#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for PaintComposite<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self as &dyn SomeTable<'a>).fmt(f)
    }
}

/// [CompositeMode](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) enumeration
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
#[allow(clippy::manual_non_exhaustive)]
pub enum CompositeMode {
    Clear = 0,
    Src = 1,
    Dest = 2,
    #[default]
    SrcOver = 3,
    DestOver = 4,
    SrcIn = 5,
    DestIn = 6,
    SrcOut = 7,
    DestOut = 8,
    SrcAtop = 9,
    DestAtop = 10,
    Xor = 11,
    Plus = 12,
    Screen = 13,
    Overlay = 14,
    Darken = 15,
    Lighten = 16,
    ColorDodge = 17,
    ColorBurn = 18,
    HardLight = 19,
    SoftLight = 20,
    Difference = 21,
    Exclusion = 22,
    Multiply = 23,
    HslHue = 24,
    HslSaturation = 25,
    HslColor = 26,
    HslLuminosity = 27,
    #[doc(hidden)]
    /// If font data is malformed we will map unknown values to this variant
    Unknown,
}

impl CompositeMode {
    /// Create from a raw scalar.
    ///
    /// This will never fail; unknown values will be mapped to the `Unknown` variant
    pub fn new(raw: u8) -> Self {
        match raw {
            0 => Self::Clear,
            1 => Self::Src,
            2 => Self::Dest,
            3 => Self::SrcOver,
            4 => Self::DestOver,
            5 => Self::SrcIn,
            6 => Self::DestIn,
            7 => Self::SrcOut,
            8 => Self::DestOut,
            9 => Self::SrcAtop,
            10 => Self::DestAtop,
            11 => Self::Xor,
            12 => Self::Plus,
            13 => Self::Screen,
            14 => Self::Overlay,
            15 => Self::Darken,
            16 => Self::Lighten,
            17 => Self::ColorDodge,
            18 => Self::ColorBurn,
            19 => Self::HardLight,
            20 => Self::SoftLight,
            21 => Self::Difference,
            22 => Self::Exclusion,
            23 => Self::Multiply,
            24 => Self::HslHue,
            25 => Self::HslSaturation,
            26 => Self::HslColor,
            27 => Self::HslLuminosity,
            _ => Self::Unknown,
        }
    }
}

impl font_types::Scalar for CompositeMode {
    type Raw = <u8 as font_types::Scalar>::Raw;
    fn to_raw(self) -> Self::Raw {
        (self as u8).to_raw()
    }
    fn from_raw(raw: Self::Raw) -> Self {
        let t = <u8>::from_raw(raw);
        Self::new(t)
    }
}

#[cfg(feature = "experimental_traverse")]
impl<'a> From<CompositeMode> for FieldType<'a> {
    fn from(src: CompositeMode) -> FieldType<'a> {
        (src as u8).into()
    }
}
