// 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::*; impl<'a> MinByteRange<'a> for Colr<'a> { fn min_byte_range(&self) -> Range { 0..self.num_layer_records_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } 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 { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [COLR (Color)](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#colr-header) table #[derive(Clone)] pub struct Colr<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> Colr<'a> { pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Table version number - set to 0 or 1. pub fn version(&self) -> u16 { let range = self.version_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Number of BaseGlyph records; may be 0 in a version 1 table. pub fn num_base_glyph_records(&self) -> u16 { let range = self.num_base_glyph_records_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to baseGlyphRecords array (may be NULL). pub fn base_glyph_records_offset(&self) -> Nullable { let range = self.base_glyph_records_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`base_glyph_records_offset`][Self::base_glyph_records_offset]. pub fn base_glyph_records(&self) -> Option> { 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 { let range = self.layer_records_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`layer_records_offset`][Self::layer_records_offset]. pub fn layer_records(&self) -> Option> { 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.num_layer_records_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to BaseGlyphList table. pub fn base_glyph_list_offset(&self) -> Option> { let range = self.base_glyph_list_offset_byte_range(); (!range.is_empty()) .then(|| self.data.read_at(range.start).ok()) .flatten() } /// Attempt to resolve [`base_glyph_list_offset`][Self::base_glyph_list_offset]. pub fn base_glyph_list(&self) -> Option, 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> { let range = self.layer_list_offset_byte_range(); (!range.is_empty()) .then(|| self.data.read_at(range.start).ok()) .flatten() } /// Attempt to resolve [`layer_list_offset`][Self::layer_list_offset]. pub fn layer_list(&self) -> Option, 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> { let range = self.clip_list_offset_byte_range(); (!range.is_empty()) .then(|| self.data.read_at(range.start).ok()) .flatten() } /// Attempt to resolve [`clip_list_offset`][Self::clip_list_offset]. pub fn clip_list(&self) -> Option, 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> { let range = self.var_index_map_offset_byte_range(); (!range.is_empty()) .then(|| self.data.read_at(range.start).ok()) .flatten() } /// Attempt to resolve [`var_index_map_offset`][Self::var_index_map_offset]. pub fn var_index_map(&self) -> Option, 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> { let range = self.item_variation_store_offset_byte_range(); (!range.is_empty()) .then(|| self.data.read_at(range.start).ok()) .flatten() } /// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset]. pub fn item_variation_store(&self) -> Option, ReadError>> { let data = self.data; self.item_variation_store_offset() .map(|x| x.resolve(data))? } pub fn version_byte_range(&self) -> Range { let start = 0; let end = start + u16::RAW_BYTE_LEN; start..end } pub fn num_base_glyph_records_byte_range(&self) -> Range { let start = self.version_byte_range().end; let end = start + u16::RAW_BYTE_LEN; start..end } pub fn base_glyph_records_offset_byte_range(&self) -> Range { let start = self.num_base_glyph_records_byte_range().end; let end = start + Offset32::RAW_BYTE_LEN; start..end } pub fn layer_records_offset_byte_range(&self) -> Range { let start = self.base_glyph_records_offset_byte_range().end; let end = start + Offset32::RAW_BYTE_LEN; start..end } pub fn num_layer_records_byte_range(&self) -> Range { let start = self.layer_records_offset_byte_range().end; let end = start + u16::RAW_BYTE_LEN; start..end } pub fn base_glyph_list_offset_byte_range(&self) -> Range { let start = self.num_layer_records_byte_range().end; let end = if self.version().compatible(1u16) { start + Offset32::RAW_BYTE_LEN } else { start }; start..end } pub fn layer_list_offset_byte_range(&self) -> Range { let start = self.base_glyph_list_offset_byte_range().end; let end = if self.version().compatible(1u16) { start + Offset32::RAW_BYTE_LEN } else { start }; start..end } pub fn clip_list_offset_byte_range(&self) -> Range { let start = self.layer_list_offset_byte_range().end; let end = if self.version().compatible(1u16) { start + Offset32::RAW_BYTE_LEN } else { start }; start..end } pub fn var_index_map_offset_byte_range(&self) -> Range { let start = self.clip_list_offset_byte_range().end; let end = if self.version().compatible(1u16) { start + Offset32::RAW_BYTE_LEN } else { start }; start..end } pub fn item_variation_store_offset_byte_range(&self) -> Range { let start = self.var_index_map_offset_byte_range().end; let end = if self.version().compatible(1u16) { start + Offset32::RAW_BYTE_LEN } else { start }; start..end } } const _: () = assert!(FontData::default_data_long_enough(Colr::MIN_SIZE)); impl Default for Colr<'_> { fn default() -> Self { Self { data: FontData::default_table_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> { 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 self.version().compatible(1u16) => Some(Field::new( "base_glyph_list_offset", FieldType::offset( self.base_glyph_list_offset().unwrap(), self.base_glyph_list(), ), )), 6usize if self.version().compatible(1u16) => Some(Field::new( "layer_list_offset", FieldType::offset(self.layer_list_offset().unwrap(), self.layer_list()), )), 7usize if self.version().compatible(1u16) => Some(Field::new( "clip_list_offset", FieldType::offset(self.clip_list_offset().unwrap(), self.clip_list()), )), 8usize if self.version().compatible(1u16) => Some(Field::new( "var_index_map_offset", FieldType::offset(self.var_index_map_offset().unwrap(), self.var_index_map()), )), 9usize if self.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, /// Index (base 0) into the layerRecords array. pub first_layer_index: BigEndian, /// Number of color layers associated with this glyph. pub num_layers: BigEndian, } 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, /// Index (base 0) for a palette entry in the CPAL table. pub palette_index: BigEndian, } 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, } } } impl<'a> MinByteRange<'a> for BaseGlyphList<'a> { fn min_byte_range(&self) -> Range { 0..self.base_glyph_paint_records_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for BaseGlyphList<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [BaseGlyphList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table #[derive(Clone)] pub struct BaseGlyphList<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> BaseGlyphList<'a> { pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN; basic_table_impls!(impl_the_methods); pub fn num_base_glyph_paint_records(&self) -> u32 { let range = self.num_base_glyph_paint_records_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn base_glyph_paint_records(&self) -> &'a [BaseGlyphPaint] { let range = self.base_glyph_paint_records_byte_range(); self.data.read_array(range).ok().unwrap_or_default() } pub fn num_base_glyph_paint_records_byte_range(&self) -> Range { let start = 0; let end = start + u32::RAW_BYTE_LEN; start..end } pub fn base_glyph_paint_records_byte_range(&self) -> Range { let num_base_glyph_paint_records = self.num_base_glyph_paint_records(); let start = self.num_base_glyph_paint_records_byte_range().end; let end = start + (transforms::to_usize(num_base_glyph_paint_records)) .saturating_mul(BaseGlyphPaint::RAW_BYTE_LEN); start..end } } const _: () = assert!(FontData::default_data_long_enough(BaseGlyphList::MIN_SIZE)); impl Default for BaseGlyphList<'_> { fn default() -> Self { Self { data: FontData::default_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for BaseGlyphList<'a> { fn type_name(&self) -> &str { "BaseGlyphList" } fn get_field(&self, idx: usize) -> Option> { 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, /// Offset to a Paint table, from the beginning of the [`BaseGlyphList`] table. pub paint_offset: BigEndian, } 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, 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, } } } impl<'a> MinByteRange<'a> for LayerList<'a> { fn min_byte_range(&self) -> Range { 0..self.paint_offsets_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for LayerList<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [LayerList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table #[derive(Clone)] pub struct LayerList<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> LayerList<'a> { pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN; basic_table_impls!(impl_the_methods); pub fn num_layers(&self) -> u32 { let range = self.num_layers_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offsets to Paint tables. pub fn paint_offsets(&self) -> &'a [BigEndian] { let range = self.paint_offsets_byte_range(); self.data.read_array(range).ok().unwrap_or_default() } /// 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, ()) } pub fn num_layers_byte_range(&self) -> Range { let start = 0; let end = start + u32::RAW_BYTE_LEN; start..end } pub fn paint_offsets_byte_range(&self) -> Range { let num_layers = self.num_layers(); let start = self.num_layers_byte_range().end; let end = start + (transforms::to_usize(num_layers)).saturating_mul(Offset32::RAW_BYTE_LEN); start..end } } const _: () = assert!(FontData::default_data_long_enough(LayerList::MIN_SIZE)); impl Default for LayerList<'_> { fn default() -> Self { Self { data: FontData::default_table_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> { match idx { 0usize => Some(Field::new("num_layers", self.num_layers())), 1usize => Some(Field::new("paint_offsets", FieldType::from(self.paints()))), _ => 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) } } impl<'a> MinByteRange<'a> for ClipList<'a> { fn min_byte_range(&self) -> Range { 0..self.clips_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for ClipList<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [ClipList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table #[derive(Clone)] pub struct ClipList<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> ClipList<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 1. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Number of Clip records. pub fn num_clips(&self) -> u32 { let range = self.num_clips_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Clip records. Sorted by startGlyphID. pub fn clips(&self) -> &'a [Clip] { let range = self.clips_byte_range(); self.data.read_array(range).ok().unwrap_or_default() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn num_clips_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } pub fn clips_byte_range(&self) -> Range { let num_clips = self.num_clips(); let start = self.num_clips_byte_range().end; let end = start + (transforms::to_usize(num_clips)).saturating_mul(Clip::RAW_BYTE_LEN); start..end } } const _: () = assert!(FontData::default_data_long_enough(ClipList::MIN_SIZE)); impl Default for ClipList<'_> { fn default() -> Self { Self { data: FontData::default_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for ClipList<'a> { fn type_name(&self) -> &str { "ClipList" } fn get_field(&self, idx: usize) -> Option> { 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, /// Last glyph ID in the range. pub end_glyph_id: BigEndian, /// Offset to a ClipBox table, from the beginning of the [`ClipList`] table. pub clip_box_offset: BigEndian, } 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, 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 Default for ClipBox<'_> { fn default() -> Self { Self::Format1(Default::default()) } } 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 { let format: u8 = data.read_at(0usize)?; match format { ClipBoxFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)), ClipBoxFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)), other => Err(ReadError::InvalidFormat(other.into())), } } } impl<'a> MinByteRange<'a> for ClipBox<'a> { fn min_byte_range(&self) -> Range { match self { Self::Format1(item) => item.min_byte_range(), Self::Format2(item) => item.min_byte_range(), } } fn min_table_bytes(&self) -> &'a [u8] { match self { Self::Format1(item) => item.min_table_bytes(), Self::Format2(item) => item.min_table_bytes(), } } } #[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> { self.dyn_inner().get_field(idx) } } impl Format for ClipBoxFormat1<'_> { const FORMAT: u8 = 1; } impl<'a> MinByteRange<'a> for ClipBoxFormat1<'a> { fn min_byte_range(&self) -> Range { 0..self.y_max_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for ClipBoxFormat1<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [ClipBoxFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record #[derive(Clone)] pub struct ClipBoxFormat1<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> ClipBoxFormat1<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 1. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Minimum x of clip box. pub fn x_min(&self) -> FWord { let range = self.x_min_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Minimum y of clip box. pub fn y_min(&self) -> FWord { let range = self.y_min_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Maximum x of clip box. pub fn x_max(&self) -> FWord { let range = self.x_max_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Maximum y of clip box. pub fn y_max(&self) -> FWord { let range = self.y_max_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn x_min_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y_min_byte_range(&self) -> Range { let start = self.x_min_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn x_max_byte_range(&self) -> Range { let start = self.y_min_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y_max_byte_range(&self) -> Range { let start = self.x_max_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } } const _: () = assert!(FontData::default_data_long_enough(ClipBoxFormat1::MIN_SIZE)); impl Default for ClipBoxFormat1<'_> { fn default() -> Self { Self { data: FontData::default_format_1_u8_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for ClipBoxFormat1<'a> { fn type_name(&self) -> &str { "ClipBoxFormat1" } fn get_field(&self, idx: usize) -> Option> { 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 for ClipBoxFormat2<'_> { const FORMAT: u8 = 2; } impl<'a> MinByteRange<'a> for ClipBoxFormat2<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for ClipBoxFormat2<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [ClipBoxFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record #[derive(Clone)] pub struct ClipBoxFormat2<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> ClipBoxFormat2<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 2. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Minimum x of clip box. For variation, use varIndexBase + 0. pub fn x_min(&self) -> FWord { let range = self.x_min_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Minimum y of clip box. For variation, use varIndexBase + 1. pub fn y_min(&self) -> FWord { let range = self.y_min_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Maximum x of clip box. For variation, use varIndexBase + 2. pub fn x_max(&self) -> FWord { let range = self.x_max_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Maximum y of clip box. For variation, use varIndexBase + 3. pub fn y_max(&self) -> FWord { let range = self.y_max_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn x_min_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y_min_byte_range(&self) -> Range { let start = self.x_min_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn x_max_byte_range(&self) -> Range { let start = self.y_min_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y_max_byte_range(&self) -> Range { let start = self.x_max_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.y_max_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for ClipBoxFormat2<'a> { fn type_name(&self) -> &str { "ClipBoxFormat2" } fn get_field(&self, idx: usize) -> Option> { 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, /// Alpha value. pub alpha: BigEndian, } 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, /// Alpha value. For variation, use varIndexBase + 0. pub alpha: BigEndian, /// Base index into DeltaSetIndexMap. pub var_index_base: BigEndian, } 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, /// Index for a CPAL palette entry. pub palette_index: BigEndian, /// Alpha value. pub alpha: BigEndian, } 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, /// Index for a CPAL palette entry. pub palette_index: BigEndian, /// Alpha value. For variation, use varIndexBase + 1. pub alpha: BigEndian, /// Base index into DeltaSetIndexMap. pub var_index_base: BigEndian, } 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, } } } impl<'a> MinByteRange<'a> for ColorLine<'a> { fn min_byte_range(&self) -> Range { 0..self.color_stops_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for ColorLine<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [ColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table #[derive(Clone)] pub struct ColorLine<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> ColorLine<'a> { pub const MIN_SIZE: usize = (Extend::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// An Extend enum value. pub fn extend(&self) -> Extend { let range = self.extend_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Number of ColorStop records. pub fn num_stops(&self) -> u16 { let range = self.num_stops_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn color_stops(&self) -> &'a [ColorStop] { let range = self.color_stops_byte_range(); self.data.read_array(range).ok().unwrap_or_default() } pub fn extend_byte_range(&self) -> Range { let start = 0; let end = start + Extend::RAW_BYTE_LEN; start..end } pub fn num_stops_byte_range(&self) -> Range { let start = self.extend_byte_range().end; let end = start + u16::RAW_BYTE_LEN; start..end } pub fn color_stops_byte_range(&self) -> Range { let num_stops = self.num_stops(); let start = self.num_stops_byte_range().end; let end = start + (transforms::to_usize(num_stops)).saturating_mul(ColorStop::RAW_BYTE_LEN); start..end } } const _: () = assert!(FontData::default_data_long_enough(ColorLine::MIN_SIZE)); impl Default for ColorLine<'_> { fn default() -> Self { Self { data: FontData::default_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for ColorLine<'a> { fn type_name(&self) -> &str { "ColorLine" } fn get_field(&self, idx: usize) -> Option> { 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) } } impl<'a> MinByteRange<'a> for VarColorLine<'a> { fn min_byte_range(&self) -> Range { 0..self.color_stops_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for VarColorLine<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [VarColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table #[derive(Clone)] pub struct VarColorLine<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> VarColorLine<'a> { pub const MIN_SIZE: usize = (Extend::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// An Extend enum value. pub fn extend(&self) -> Extend { let range = self.extend_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Number of ColorStop records. pub fn num_stops(&self) -> u16 { let range = self.num_stops_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Allows for variations. pub fn color_stops(&self) -> &'a [VarColorStop] { let range = self.color_stops_byte_range(); self.data.read_array(range).ok().unwrap_or_default() } pub fn extend_byte_range(&self) -> Range { let start = 0; let end = start + Extend::RAW_BYTE_LEN; start..end } pub fn num_stops_byte_range(&self) -> Range { let start = self.extend_byte_range().end; let end = start + u16::RAW_BYTE_LEN; start..end } pub fn color_stops_byte_range(&self) -> Range { let num_stops = self.num_stops(); let start = self.num_stops_byte_range().end; let end = start + (transforms::to_usize(num_stops)).saturating_mul(VarColorStop::RAW_BYTE_LEN); start..end } } const _: () = assert!(FontData::default_data_long_enough(VarColorLine::MIN_SIZE)); impl Default for VarColorLine<'_> { fn default() -> Self { Self { data: FontData::default_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for VarColorLine<'a> { fn type_name(&self) -> &str { "VarColorLine" } fn get_field(&self, idx: usize) -> Option> { 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 = ::Raw; fn to_raw(self) -> Self::Raw { (self as u8).to_raw() } fn from_raw(raw: Self::Raw) -> Self { let t = ::from_raw(raw); Self::new(t) } } #[cfg(feature = "experimental_traverse")] impl<'a> From 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 Default for Paint<'_> { fn default() -> Self { Self::ColrLayers(Default::default()) } } 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 { let format: u8 = data.read_at(0usize)?; match format { PaintColrLayers::FORMAT => Ok(Self::ColrLayers(FontRead::read(data)?)), PaintSolid::FORMAT => Ok(Self::Solid(FontRead::read(data)?)), PaintVarSolid::FORMAT => Ok(Self::VarSolid(FontRead::read(data)?)), PaintLinearGradient::FORMAT => Ok(Self::LinearGradient(FontRead::read(data)?)), PaintVarLinearGradient::FORMAT => Ok(Self::VarLinearGradient(FontRead::read(data)?)), PaintRadialGradient::FORMAT => Ok(Self::RadialGradient(FontRead::read(data)?)), PaintVarRadialGradient::FORMAT => Ok(Self::VarRadialGradient(FontRead::read(data)?)), PaintSweepGradient::FORMAT => Ok(Self::SweepGradient(FontRead::read(data)?)), PaintVarSweepGradient::FORMAT => Ok(Self::VarSweepGradient(FontRead::read(data)?)), PaintGlyph::FORMAT => Ok(Self::Glyph(FontRead::read(data)?)), PaintColrGlyph::FORMAT => Ok(Self::ColrGlyph(FontRead::read(data)?)), PaintTransform::FORMAT => Ok(Self::Transform(FontRead::read(data)?)), PaintVarTransform::FORMAT => Ok(Self::VarTransform(FontRead::read(data)?)), PaintTranslate::FORMAT => Ok(Self::Translate(FontRead::read(data)?)), PaintVarTranslate::FORMAT => Ok(Self::VarTranslate(FontRead::read(data)?)), PaintScale::FORMAT => Ok(Self::Scale(FontRead::read(data)?)), PaintVarScale::FORMAT => Ok(Self::VarScale(FontRead::read(data)?)), PaintScaleAroundCenter::FORMAT => Ok(Self::ScaleAroundCenter(FontRead::read(data)?)), PaintVarScaleAroundCenter::FORMAT => { Ok(Self::VarScaleAroundCenter(FontRead::read(data)?)) } PaintScaleUniform::FORMAT => Ok(Self::ScaleUniform(FontRead::read(data)?)), PaintVarScaleUniform::FORMAT => Ok(Self::VarScaleUniform(FontRead::read(data)?)), PaintScaleUniformAroundCenter::FORMAT => { Ok(Self::ScaleUniformAroundCenter(FontRead::read(data)?)) } PaintVarScaleUniformAroundCenter::FORMAT => { Ok(Self::VarScaleUniformAroundCenter(FontRead::read(data)?)) } PaintRotate::FORMAT => Ok(Self::Rotate(FontRead::read(data)?)), PaintVarRotate::FORMAT => Ok(Self::VarRotate(FontRead::read(data)?)), PaintRotateAroundCenter::FORMAT => Ok(Self::RotateAroundCenter(FontRead::read(data)?)), PaintVarRotateAroundCenter::FORMAT => { Ok(Self::VarRotateAroundCenter(FontRead::read(data)?)) } PaintSkew::FORMAT => Ok(Self::Skew(FontRead::read(data)?)), PaintVarSkew::FORMAT => Ok(Self::VarSkew(FontRead::read(data)?)), PaintSkewAroundCenter::FORMAT => Ok(Self::SkewAroundCenter(FontRead::read(data)?)), PaintVarSkewAroundCenter::FORMAT => { Ok(Self::VarSkewAroundCenter(FontRead::read(data)?)) } PaintComposite::FORMAT => Ok(Self::Composite(FontRead::read(data)?)), other => Err(ReadError::InvalidFormat(other.into())), } } } impl<'a> MinByteRange<'a> for Paint<'a> { fn min_byte_range(&self) -> Range { 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(), } } fn min_table_bytes(&self) -> &'a [u8] { match self { Self::ColrLayers(item) => item.min_table_bytes(), Self::Solid(item) => item.min_table_bytes(), Self::VarSolid(item) => item.min_table_bytes(), Self::LinearGradient(item) => item.min_table_bytes(), Self::VarLinearGradient(item) => item.min_table_bytes(), Self::RadialGradient(item) => item.min_table_bytes(), Self::VarRadialGradient(item) => item.min_table_bytes(), Self::SweepGradient(item) => item.min_table_bytes(), Self::VarSweepGradient(item) => item.min_table_bytes(), Self::Glyph(item) => item.min_table_bytes(), Self::ColrGlyph(item) => item.min_table_bytes(), Self::Transform(item) => item.min_table_bytes(), Self::VarTransform(item) => item.min_table_bytes(), Self::Translate(item) => item.min_table_bytes(), Self::VarTranslate(item) => item.min_table_bytes(), Self::Scale(item) => item.min_table_bytes(), Self::VarScale(item) => item.min_table_bytes(), Self::ScaleAroundCenter(item) => item.min_table_bytes(), Self::VarScaleAroundCenter(item) => item.min_table_bytes(), Self::ScaleUniform(item) => item.min_table_bytes(), Self::VarScaleUniform(item) => item.min_table_bytes(), Self::ScaleUniformAroundCenter(item) => item.min_table_bytes(), Self::VarScaleUniformAroundCenter(item) => item.min_table_bytes(), Self::Rotate(item) => item.min_table_bytes(), Self::VarRotate(item) => item.min_table_bytes(), Self::RotateAroundCenter(item) => item.min_table_bytes(), Self::VarRotateAroundCenter(item) => item.min_table_bytes(), Self::Skew(item) => item.min_table_bytes(), Self::VarSkew(item) => item.min_table_bytes(), Self::SkewAroundCenter(item) => item.min_table_bytes(), Self::VarSkewAroundCenter(item) => item.min_table_bytes(), Self::Composite(item) => item.min_table_bytes(), } } } #[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> { self.dyn_inner().get_field(idx) } } impl Format for PaintColrLayers<'_> { const FORMAT: u8 = 1; } impl<'a> MinByteRange<'a> for PaintColrLayers<'a> { fn min_byte_range(&self) -> Range { 0..self.first_layer_index_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintColrLayers<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintColrLayers](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-1-paintcolrlayers) table #[derive(Clone)] pub struct PaintColrLayers<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintColrLayers<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 1. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Number of offsets to paint tables to read from LayerList. pub fn num_layers(&self) -> u8 { let range = self.num_layers_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Index (base 0) into the LayerList. pub fn first_layer_index(&self) -> u32 { let range = self.first_layer_index_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn num_layers_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn first_layer_index_byte_range(&self) -> Range { let start = self.num_layers_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } const _: () = assert!(FontData::default_data_long_enough( PaintColrLayers::MIN_SIZE )); impl Default for PaintColrLayers<'_> { fn default() -> Self { Self { data: FontData::default_format_1_u8_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintColrLayers<'a> { fn type_name(&self) -> &str { "PaintColrLayers" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintSolid<'_> { const FORMAT: u8 = 2; } impl<'a> MinByteRange<'a> for PaintSolid<'a> { fn min_byte_range(&self) -> Range { 0..self.alpha_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintSolid<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table #[derive(Clone)] pub struct PaintSolid<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintSolid<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 2. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Index for a CPAL palette entry. pub fn palette_index(&self) -> u16 { let range = self.palette_index_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Alpha value. pub fn alpha(&self) -> F2Dot14 { let range = self.alpha_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn palette_index_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + u16::RAW_BYTE_LEN; start..end } pub fn alpha_byte_range(&self) -> Range { let start = self.palette_index_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintSolid<'a> { fn type_name(&self) -> &str { "PaintSolid" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarSolid<'_> { const FORMAT: u8 = 3; } impl<'a> MinByteRange<'a> for PaintVarSolid<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarSolid<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table #[derive(Clone)] pub struct PaintVarSolid<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarSolid<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 3. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Index for a CPAL palette entry. pub fn palette_index(&self) -> u16 { let range = self.palette_index_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Alpha value. For variation, use varIndexBase + 0. pub fn alpha(&self) -> F2Dot14 { let range = self.alpha_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn palette_index_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + u16::RAW_BYTE_LEN; start..end } pub fn alpha_byte_range(&self) -> Range { let start = self.palette_index_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.alpha_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarSolid<'a> { fn type_name(&self) -> &str { "PaintVarSolid" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintLinearGradient<'_> { const FORMAT: u8 = 4; } impl<'a> MinByteRange<'a> for PaintLinearGradient<'a> { fn min_byte_range(&self) -> Range { 0..self.y2_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintLinearGradient<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table #[derive(Clone)] pub struct PaintLinearGradient<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintLinearGradient<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 4. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to ColorLine table. pub fn color_line_offset(&self) -> Offset24 { let range = self.color_line_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. pub fn color_line(&self) -> Result, ReadError> { let data = self.data; self.color_line_offset().resolve(data) } /// Start point (p₀) x coordinate. pub fn x0(&self) -> FWord { let range = self.x0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Start point (p₀) y coordinate. pub fn y0(&self) -> FWord { let range = self.y0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End point (p₁) x coordinate. pub fn x1(&self) -> FWord { let range = self.x1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End point (p₁) y coordinate. pub fn y1(&self) -> FWord { let range = self.y1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Rotation point (p₂) x coordinate. pub fn x2(&self) -> FWord { let range = self.x2_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Rotation point (p₂) y coordinate. pub fn y2(&self) -> FWord { let range = self.y2_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn color_line_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x0_byte_range(&self) -> Range { let start = self.color_line_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y0_byte_range(&self) -> Range { let start = self.x0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn x1_byte_range(&self) -> Range { let start = self.y0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y1_byte_range(&self) -> Range { let start = self.x1_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn x2_byte_range(&self) -> Range { let start = self.y1_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y2_byte_range(&self) -> Range { let start = self.x2_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintLinearGradient<'a> { fn type_name(&self) -> &str { "PaintLinearGradient" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarLinearGradient<'_> { const FORMAT: u8 = 5; } impl<'a> MinByteRange<'a> for PaintVarLinearGradient<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarLinearGradient<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table #[derive(Clone)] pub struct PaintVarLinearGradient<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarLinearGradient<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 5. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to VarColorLine table. pub fn color_line_offset(&self) -> Offset24 { let range = self.color_line_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. pub fn color_line(&self) -> Result, 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.x0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Start point (p₀) y coordinate. For variation, use /// varIndexBase + 1. pub fn y0(&self) -> FWord { let range = self.y0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End point (p₁) x coordinate. For variation, use varIndexBase /// + 2. pub fn x1(&self) -> FWord { let range = self.x1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End point (p₁) y coordinate. For variation, use varIndexBase /// + 3. pub fn y1(&self) -> FWord { let range = self.y1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Rotation point (p₂) x coordinate. For variation, use /// varIndexBase + 4. pub fn x2(&self) -> FWord { let range = self.x2_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Rotation point (p₂) y coordinate. For variation, use /// varIndexBase + 5. pub fn y2(&self) -> FWord { let range = self.y2_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn color_line_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x0_byte_range(&self) -> Range { let start = self.color_line_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y0_byte_range(&self) -> Range { let start = self.x0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn x1_byte_range(&self) -> Range { let start = self.y0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y1_byte_range(&self) -> Range { let start = self.x1_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn x2_byte_range(&self) -> Range { let start = self.y1_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y2_byte_range(&self) -> Range { let start = self.x2_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.y2_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarLinearGradient<'a> { fn type_name(&self) -> &str { "PaintVarLinearGradient" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintRadialGradient<'_> { const FORMAT: u8 = 6; } impl<'a> MinByteRange<'a> for PaintRadialGradient<'a> { fn min_byte_range(&self) -> Range { 0..self.radius1_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintRadialGradient<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table #[derive(Clone)] pub struct PaintRadialGradient<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintRadialGradient<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + UfWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + UfWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 6. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to ColorLine table. pub fn color_line_offset(&self) -> Offset24 { let range = self.color_line_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. pub fn color_line(&self) -> Result, ReadError> { let data = self.data; self.color_line_offset().resolve(data) } /// Start circle center x coordinate. pub fn x0(&self) -> FWord { let range = self.x0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Start circle center y coordinate. pub fn y0(&self) -> FWord { let range = self.y0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Start circle radius. pub fn radius0(&self) -> UfWord { let range = self.radius0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End circle center x coordinate. pub fn x1(&self) -> FWord { let range = self.x1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End circle center y coordinate. pub fn y1(&self) -> FWord { let range = self.y1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End circle radius. pub fn radius1(&self) -> UfWord { let range = self.radius1_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn color_line_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x0_byte_range(&self) -> Range { let start = self.color_line_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y0_byte_range(&self) -> Range { let start = self.x0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn radius0_byte_range(&self) -> Range { let start = self.y0_byte_range().end; let end = start + UfWord::RAW_BYTE_LEN; start..end } pub fn x1_byte_range(&self) -> Range { let start = self.radius0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y1_byte_range(&self) -> Range { let start = self.x1_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn radius1_byte_range(&self) -> Range { let start = self.y1_byte_range().end; let end = start + UfWord::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintRadialGradient<'a> { fn type_name(&self) -> &str { "PaintRadialGradient" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarRadialGradient<'_> { const FORMAT: u8 = 7; } impl<'a> MinByteRange<'a> for PaintVarRadialGradient<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarRadialGradient<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table #[derive(Clone)] pub struct PaintVarRadialGradient<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarRadialGradient<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + UfWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + UfWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 7. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to VarColorLine table. pub fn color_line_offset(&self) -> Offset24 { let range = self.color_line_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. pub fn color_line(&self) -> Result, 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.x0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Start circle center y coordinate. For variation, use /// varIndexBase + 1. pub fn y0(&self) -> FWord { let range = self.y0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Start circle radius. For variation, use varIndexBase + 2. pub fn radius0(&self) -> UfWord { let range = self.radius0_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End circle center x coordinate. For variation, use varIndexBase /// + 3. pub fn x1(&self) -> FWord { let range = self.x1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End circle center y coordinate. For variation, use varIndexBase /// + 4. pub fn y1(&self) -> FWord { let range = self.y1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// End circle radius. For variation, use varIndexBase + 5. pub fn radius1(&self) -> UfWord { let range = self.radius1_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn color_line_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x0_byte_range(&self) -> Range { let start = self.color_line_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y0_byte_range(&self) -> Range { let start = self.x0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn radius0_byte_range(&self) -> Range { let start = self.y0_byte_range().end; let end = start + UfWord::RAW_BYTE_LEN; start..end } pub fn x1_byte_range(&self) -> Range { let start = self.radius0_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn y1_byte_range(&self) -> Range { let start = self.x1_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn radius1_byte_range(&self) -> Range { let start = self.y1_byte_range().end; let end = start + UfWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.radius1_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarRadialGradient<'a> { fn type_name(&self) -> &str { "PaintVarRadialGradient" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintSweepGradient<'_> { const FORMAT: u8 = 8; } impl<'a> MinByteRange<'a> for PaintSweepGradient<'a> { fn min_byte_range(&self) -> Range { 0..self.end_angle_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintSweepGradient<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table #[derive(Clone)] pub struct PaintSweepGradient<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintSweepGradient<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 8. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to ColorLine table. pub fn color_line_offset(&self) -> Offset24 { let range = self.color_line_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. pub fn color_line(&self) -> Result, ReadError> { let data = self.data; self.color_line_offset().resolve(data) } /// Center x coordinate. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Center y coordinate. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().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.start_angle_byte_range(); self.data.read_at(range.start).ok().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.end_angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn color_line_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.color_line_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn start_angle_byte_range(&self) -> Range { let start = self.center_y_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn end_angle_byte_range(&self) -> Range { let start = self.start_angle_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintSweepGradient<'a> { fn type_name(&self) -> &str { "PaintSweepGradient" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarSweepGradient<'_> { const FORMAT: u8 = 9; } impl<'a> MinByteRange<'a> for PaintVarSweepGradient<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarSweepGradient<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table #[derive(Clone)] pub struct PaintVarSweepGradient<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarSweepGradient<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 9. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to VarColorLine table. pub fn color_line_offset(&self) -> Offset24 { let range = self.color_line_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. pub fn color_line(&self) -> Result, 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.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Center y coordinate. For variation, use varIndexBase + 1. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().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.start_angle_byte_range(); self.data.read_at(range.start).ok().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.end_angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn color_line_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.color_line_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn start_angle_byte_range(&self) -> Range { let start = self.center_y_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn end_angle_byte_range(&self) -> Range { let start = self.start_angle_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.end_angle_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarSweepGradient<'a> { fn type_name(&self) -> &str { "PaintVarSweepGradient" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintGlyph<'_> { const FORMAT: u8 = 10; } impl<'a> MinByteRange<'a> for PaintGlyph<'a> { fn min_byte_range(&self) -> Range { 0..self.glyph_id_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintGlyph<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-10-paintglyph) table #[derive(Clone)] pub struct PaintGlyph<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintGlyph<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 10. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint table. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.glyph_id_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn glyph_id_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + GlyphId16::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintGlyph<'a> { fn type_name(&self) -> &str { "PaintGlyph" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintColrGlyph<'_> { const FORMAT: u8 = 11; } impl<'a> MinByteRange<'a> for PaintColrGlyph<'a> { fn min_byte_range(&self) -> Range { 0..self.glyph_id_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintColrGlyph<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintColrGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-11-paintcolrglyph) table #[derive(Clone)] pub struct PaintColrGlyph<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintColrGlyph<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 11. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Glyph ID for a BaseGlyphList base glyph. pub fn glyph_id(&self) -> GlyphId16 { let range = self.glyph_id_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn glyph_id_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + GlyphId16::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintColrGlyph<'a> { fn type_name(&self) -> &str { "PaintColrGlyph" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintTransform<'_> { const FORMAT: u8 = 12; } impl<'a> MinByteRange<'a> for PaintTransform<'a> { fn min_byte_range(&self) -> Range { 0..self.transform_offset_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintTransform<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table #[derive(Clone)] pub struct PaintTransform<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintTransform<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 12. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, ReadError> { let data = self.data; self.paint_offset().resolve(data) } /// Offset to an Affine2x3 table. pub fn transform_offset(&self) -> Offset24 { let range = self.transform_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`transform_offset`][Self::transform_offset]. pub fn transform(&self) -> Result, ReadError> { let data = self.data; self.transform_offset().resolve(data) } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn transform_offset_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintTransform<'a> { fn type_name(&self) -> &str { "PaintTransform" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarTransform<'_> { const FORMAT: u8 = 13; } impl<'a> MinByteRange<'a> for PaintVarTransform<'a> { fn min_byte_range(&self) -> Range { 0..self.transform_offset_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarTransform<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table #[derive(Clone)] pub struct PaintVarTransform<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarTransform<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 13. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, ReadError> { let data = self.data; self.paint_offset().resolve(data) } /// Offset to a VarAffine2x3 table. pub fn transform_offset(&self) -> Offset24 { let range = self.transform_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`transform_offset`][Self::transform_offset]. pub fn transform(&self) -> Result, ReadError> { let data = self.data; self.transform_offset().resolve(data) } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn transform_offset_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarTransform<'a> { fn type_name(&self) -> &str { "PaintVarTransform" } fn get_field(&self, idx: usize) -> Option> { 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) } } impl<'a> MinByteRange<'a> for Affine2x3<'a> { fn min_byte_range(&self) -> Range { 0..self.dy_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for Affine2x3<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [Affine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record #[derive(Clone)] pub struct Affine2x3<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> Affine2x3<'a> { pub const MIN_SIZE: usize = (Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// x-component of transformed x-basis vector. pub fn xx(&self) -> Fixed { let range = self.xx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y-component of transformed x-basis vector. pub fn yx(&self) -> Fixed { let range = self.yx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x-component of transformed y-basis vector. pub fn xy(&self) -> Fixed { let range = self.xy_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y-component of transformed y-basis vector. pub fn yy(&self) -> Fixed { let range = self.yy_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Translation in x direction. pub fn dx(&self) -> Fixed { let range = self.dx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Translation in y direction. pub fn dy(&self) -> Fixed { let range = self.dy_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn xx_byte_range(&self) -> Range { let start = 0; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn yx_byte_range(&self) -> Range { let start = self.xx_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn xy_byte_range(&self) -> Range { let start = self.yx_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn yy_byte_range(&self) -> Range { let start = self.xy_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn dx_byte_range(&self) -> Range { let start = self.yy_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn dy_byte_range(&self) -> Range { let start = self.dx_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } } const _: () = assert!(FontData::default_data_long_enough(Affine2x3::MIN_SIZE)); impl Default for Affine2x3<'_> { fn default() -> Self { Self { data: FontData::default_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for Affine2x3<'a> { fn type_name(&self) -> &str { "Affine2x3" } fn get_field(&self, idx: usize) -> Option> { 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) } } impl<'a> MinByteRange<'a> for VarAffine2x3<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for VarAffine2x3<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [VarAffine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record #[derive(Clone)] pub struct VarAffine2x3<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> VarAffine2x3<'a> { pub const MIN_SIZE: usize = (Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// x-component of transformed x-basis vector. For variation, use /// varIndexBase + 0. pub fn xx(&self) -> Fixed { let range = self.xx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y-component of transformed x-basis vector. For variation, use /// varIndexBase + 1. pub fn yx(&self) -> Fixed { let range = self.yx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x-component of transformed y-basis vector. For variation, use /// varIndexBase + 2. pub fn xy(&self) -> Fixed { let range = self.xy_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y-component of transformed y-basis vector. For variation, use /// varIndexBase + 3. pub fn yy(&self) -> Fixed { let range = self.yy_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Translation in x direction. For variation, use varIndexBase + 4. pub fn dx(&self) -> Fixed { let range = self.dx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Translation in y direction. For variation, use varIndexBase + 5. pub fn dy(&self) -> Fixed { let range = self.dy_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn xx_byte_range(&self) -> Range { let start = 0; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn yx_byte_range(&self) -> Range { let start = self.xx_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn xy_byte_range(&self) -> Range { let start = self.yx_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn yy_byte_range(&self) -> Range { let start = self.xy_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn dx_byte_range(&self) -> Range { let start = self.yy_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn dy_byte_range(&self) -> Range { let start = self.dx_byte_range().end; let end = start + Fixed::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.dy_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } const _: () = assert!(FontData::default_data_long_enough(VarAffine2x3::MIN_SIZE)); impl Default for VarAffine2x3<'_> { fn default() -> Self { Self { data: FontData::default_table_data(), } } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for VarAffine2x3<'a> { fn type_name(&self) -> &str { "VarAffine2x3" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintTranslate<'_> { const FORMAT: u8 = 14; } impl<'a> MinByteRange<'a> for PaintTranslate<'a> { fn min_byte_range(&self) -> Range { 0..self.dy_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintTranslate<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table #[derive(Clone)] pub struct PaintTranslate<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintTranslate<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 14. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, ReadError> { let data = self.data; self.paint_offset().resolve(data) } /// Translation in x direction. pub fn dx(&self) -> FWord { let range = self.dx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Translation in y direction. pub fn dy(&self) -> FWord { let range = self.dy_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn dx_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn dy_byte_range(&self) -> Range { let start = self.dx_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintTranslate<'a> { fn type_name(&self) -> &str { "PaintTranslate" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarTranslate<'_> { const FORMAT: u8 = 15; } impl<'a> MinByteRange<'a> for PaintVarTranslate<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarTranslate<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table #[derive(Clone)] pub struct PaintVarTranslate<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarTranslate<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 15. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.dx_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Translation in y direction. For variation, use varIndexBase + 1. pub fn dy(&self) -> FWord { let range = self.dy_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn dx_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn dy_byte_range(&self) -> Range { let start = self.dx_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.dy_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarTranslate<'a> { fn type_name(&self) -> &str { "PaintVarTranslate" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintScale<'_> { const FORMAT: u8 = 16; } impl<'a> MinByteRange<'a> for PaintScale<'a> { fn min_byte_range(&self) -> Range { 0..self.scale_y_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintScale<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintScale<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintScale<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 16. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, ReadError> { let data = self.data; self.paint_offset().resolve(data) } /// Scale factor in x direction. pub fn scale_x(&self) -> F2Dot14 { let range = self.scale_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Scale factor in y direction. pub fn scale_y(&self) -> F2Dot14 { let range = self.scale_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_x_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn scale_y_byte_range(&self) -> Range { let start = self.scale_x_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintScale<'a> { fn type_name(&self) -> &str { "PaintScale" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarScale<'_> { const FORMAT: u8 = 17; } impl<'a> MinByteRange<'a> for PaintVarScale<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarScale<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintVarScale<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarScale<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 17. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.scale_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Scale factor in y direction. For variation, use varIndexBase + /// 1. pub fn scale_y(&self) -> F2Dot14 { let range = self.scale_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_x_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn scale_y_byte_range(&self) -> Range { let start = self.scale_x_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.scale_y_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarScale<'a> { fn type_name(&self) -> &str { "PaintVarScale" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintScaleAroundCenter<'_> { const FORMAT: u8 = 18; } impl<'a> MinByteRange<'a> for PaintScaleAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.center_y_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintScaleAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintScaleAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintScaleAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 18. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, ReadError> { let data = self.data; self.paint_offset().resolve(data) } /// Scale factor in x direction. pub fn scale_x(&self) -> F2Dot14 { let range = self.scale_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Scale factor in y direction. pub fn scale_y(&self) -> F2Dot14 { let range = self.scale_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of scaling. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of scaling. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_x_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn scale_y_byte_range(&self) -> Range { let start = self.scale_x_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.scale_y_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintScaleAroundCenter<'a> { fn type_name(&self) -> &str { "PaintScaleAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarScaleAroundCenter<'_> { const FORMAT: u8 = 19; } impl<'a> MinByteRange<'a> for PaintVarScaleAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarScaleAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintVarScaleAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarScaleAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 19. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.scale_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Scale factor in y direction. For variation, use varIndexBase + /// 1. pub fn scale_y(&self) -> F2Dot14 { let range = self.scale_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of scaling. For variation, use /// varIndexBase + 2. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of scaling. For variation, use /// varIndexBase + 3. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_x_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn scale_y_byte_range(&self) -> Range { let start = self.scale_x_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.scale_y_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.center_y_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarScaleAroundCenter<'a> { fn type_name(&self) -> &str { "PaintVarScaleAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintScaleUniform<'_> { const FORMAT: u8 = 20; } impl<'a> MinByteRange<'a> for PaintScaleUniform<'a> { fn min_byte_range(&self) -> Range { 0..self.scale_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintScaleUniform<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintScaleUniform<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintScaleUniform<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 20. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.scale_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintScaleUniform<'a> { fn type_name(&self) -> &str { "PaintScaleUniform" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarScaleUniform<'_> { const FORMAT: u8 = 21; } impl<'a> MinByteRange<'a> for PaintVarScaleUniform<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarScaleUniform<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintVarScaleUniform<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarScaleUniform<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 21. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.scale_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.scale_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarScaleUniform<'a> { fn type_name(&self) -> &str { "PaintVarScaleUniform" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintScaleUniformAroundCenter<'_> { const FORMAT: u8 = 22; } impl<'a> MinByteRange<'a> for PaintScaleUniformAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.center_y_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintScaleUniformAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintScaleUniformAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintScaleUniformAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 22. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.scale_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of scaling. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of scaling. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.scale_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintScaleUniformAroundCenter<'a> { fn type_name(&self) -> &str { "PaintScaleUniformAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarScaleUniformAroundCenter<'_> { const FORMAT: u8 = 23; } impl<'a> MinByteRange<'a> for PaintVarScaleUniformAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarScaleUniformAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Clone)] pub struct PaintVarScaleUniformAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarScaleUniformAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 23. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.scale_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of scaling. For variation, use /// varIndexBase + 1. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of scaling. For variation, use /// varIndexBase + 2. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn scale_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.scale_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.center_y_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarScaleUniformAroundCenter<'a> { fn type_name(&self) -> &str { "PaintVarScaleUniformAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintRotate<'_> { const FORMAT: u8 = 24; } impl<'a> MinByteRange<'a> for PaintRotate<'a> { fn min_byte_range(&self) -> Range { 0..self.angle_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintRotate<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Clone)] pub struct PaintRotate<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintRotate<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 24. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintRotate<'a> { fn type_name(&self) -> &str { "PaintRotate" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarRotate<'_> { const FORMAT: u8 = 25; } impl<'a> MinByteRange<'a> for PaintVarRotate<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarRotate<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Clone)] pub struct PaintVarRotate<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarRotate<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 25. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.angle_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarRotate<'a> { fn type_name(&self) -> &str { "PaintVarRotate" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintRotateAroundCenter<'_> { const FORMAT: u8 = 26; } impl<'a> MinByteRange<'a> for PaintRotateAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.center_y_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintRotateAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Clone)] pub struct PaintRotateAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintRotateAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 26. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of rotation. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of rotation. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.angle_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintRotateAroundCenter<'a> { fn type_name(&self) -> &str { "PaintRotateAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarRotateAroundCenter<'_> { const FORMAT: u8 = 27; } impl<'a> MinByteRange<'a> for PaintVarRotateAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarRotateAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Clone)] pub struct PaintVarRotateAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarRotateAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 27. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of rotation. For variation, use /// varIndexBase + 1. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of rotation. For variation, use /// varIndexBase + 2. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.angle_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.center_y_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarRotateAroundCenter<'a> { fn type_name(&self) -> &str { "PaintVarRotateAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintSkew<'_> { const FORMAT: u8 = 28; } impl<'a> MinByteRange<'a> for PaintSkew<'a> { fn min_byte_range(&self) -> Range { 0..self.y_skew_angle_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintSkew<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Clone)] pub struct PaintSkew<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintSkew<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 28. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.x_skew_angle_byte_range(); self.data.read_at(range.start).ok().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.y_skew_angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x_skew_angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn y_skew_angle_byte_range(&self) -> Range { let start = self.x_skew_angle_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintSkew<'a> { fn type_name(&self) -> &str { "PaintSkew" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarSkew<'_> { const FORMAT: u8 = 29; } impl<'a> MinByteRange<'a> for PaintVarSkew<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarSkew<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Clone)] pub struct PaintVarSkew<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarSkew<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 29. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.x_skew_angle_byte_range(); self.data.read_at(range.start).ok().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.y_skew_angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x_skew_angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn y_skew_angle_byte_range(&self) -> Range { let start = self.x_skew_angle_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.y_skew_angle_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarSkew<'a> { fn type_name(&self) -> &str { "PaintVarSkew" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintSkewAroundCenter<'_> { const FORMAT: u8 = 30; } impl<'a> MinByteRange<'a> for PaintSkewAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.center_y_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintSkewAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Clone)] pub struct PaintSkewAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintSkewAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 30. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.x_skew_angle_byte_range(); self.data.read_at(range.start).ok().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.y_skew_angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of rotation. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of rotation. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x_skew_angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn y_skew_angle_byte_range(&self) -> Range { let start = self.x_skew_angle_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.y_skew_angle_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintSkewAroundCenter<'a> { fn type_name(&self) -> &str { "PaintSkewAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintVarSkewAroundCenter<'_> { const FORMAT: u8 = 31; } impl<'a> MinByteRange<'a> for PaintVarSkewAroundCenter<'a> { fn min_byte_range(&self) -> Range { 0..self.var_index_base_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintVarSkewAroundCenter<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintVarSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Clone)] pub struct PaintVarSkewAroundCenter<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintVarSkewAroundCenter<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + FWord::RAW_BYTE_LEN + u32::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 31. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { let range = self.paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. pub fn paint(&self) -> Result, 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.x_skew_angle_byte_range(); self.data.read_at(range.start).ok().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.y_skew_angle_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// x coordinate for the center of rotation. For variation, use /// varIndexBase + 2. pub fn center_x(&self) -> FWord { let range = self.center_x_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// y coordinate for the center of rotation. For variation, use /// varIndexBase + 3. pub fn center_y(&self) -> FWord { let range = self.center_y_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { let range = self.var_index_base_byte_range(); self.data.read_at(range.start).ok().unwrap() } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn x_skew_angle_byte_range(&self) -> Range { let start = self.paint_offset_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn y_skew_angle_byte_range(&self) -> Range { let start = self.x_skew_angle_byte_range().end; let end = start + F2Dot14::RAW_BYTE_LEN; start..end } pub fn center_x_byte_range(&self) -> Range { let start = self.y_skew_angle_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn center_y_byte_range(&self) -> Range { let start = self.center_x_byte_range().end; let end = start + FWord::RAW_BYTE_LEN; start..end } pub fn var_index_base_byte_range(&self) -> Range { let start = self.center_y_byte_range().end; let end = start + u32::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintVarSkewAroundCenter<'a> { fn type_name(&self) -> &str { "PaintVarSkewAroundCenter" } fn get_field(&self, idx: usize) -> Option> { 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 for PaintComposite<'_> { const FORMAT: u8 = 32; } impl<'a> MinByteRange<'a> for PaintComposite<'a> { fn min_byte_range(&self) -> Range { 0..self.backdrop_paint_offset_byte_range().end } fn min_table_bytes(&self) -> &'a [u8] { let range = self.min_byte_range(); self.data.as_bytes().get(range).unwrap_or_default() } } impl<'a> FontRead<'a> for PaintComposite<'a> { fn read(data: FontData<'a>) -> Result { #[allow(clippy::absurd_extreme_comparisons)] if data.len() < Self::MIN_SIZE { return Err(ReadError::OutOfBounds); } Ok(Self { data }) } } /// [PaintComposite](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) table #[derive(Clone)] pub struct PaintComposite<'a> { data: FontData<'a>, } #[allow(clippy::needless_lifetimes)] impl<'a> PaintComposite<'a> { pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN + CompositeMode::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN); basic_table_impls!(impl_the_methods); /// Set to 32. pub fn format(&self) -> u8 { let range = self.format_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a source Paint table. pub fn source_paint_offset(&self) -> Offset24 { let range = self.source_paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`source_paint_offset`][Self::source_paint_offset]. pub fn source_paint(&self) -> Result, ReadError> { let data = self.data; self.source_paint_offset().resolve(data) } /// A CompositeMode enumeration value. pub fn composite_mode(&self) -> CompositeMode { let range = self.composite_mode_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Offset to a backdrop Paint table. pub fn backdrop_paint_offset(&self) -> Offset24 { let range = self.backdrop_paint_offset_byte_range(); self.data.read_at(range.start).ok().unwrap() } /// Attempt to resolve [`backdrop_paint_offset`][Self::backdrop_paint_offset]. pub fn backdrop_paint(&self) -> Result, ReadError> { let data = self.data; self.backdrop_paint_offset().resolve(data) } pub fn format_byte_range(&self) -> Range { let start = 0; let end = start + u8::RAW_BYTE_LEN; start..end } pub fn source_paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } pub fn composite_mode_byte_range(&self) -> Range { let start = self.source_paint_offset_byte_range().end; let end = start + CompositeMode::RAW_BYTE_LEN; start..end } pub fn backdrop_paint_offset_byte_range(&self) -> Range { let start = self.composite_mode_byte_range().end; let end = start + Offset24::RAW_BYTE_LEN; start..end } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for PaintComposite<'a> { fn type_name(&self) -> &str { "PaintComposite" } fn get_field(&self, idx: usize) -> Option> { 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 = ::Raw; fn to_raw(self) -> Self::Raw { (self as u8).to_raw() } fn from_raw(raw: Self::Raw) -> Self { let t = ::from_raw(raw); Self::new(t) } } #[cfg(feature = "experimental_traverse")] impl<'a> From for FieldType<'a> { fn from(src: CompositeMode) -> FieldType<'a> { (src as u8).into() } }