| // 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::*; |
| |
| /// Lookup tables provide a way of looking up information about a glyph index. |
| /// The different cmap subtable formats. |
| #[derive(Clone)] |
| pub enum Lookup<'a> { |
| Format0(Lookup0<'a>), |
| Format2(Lookup2<'a>), |
| Format4(Lookup4<'a>), |
| Format6(Lookup6<'a>), |
| Format8(Lookup8<'a>), |
| Format10(Lookup10<'a>), |
| } |
| |
| impl<'a> Lookup<'a> { |
| ///Return the `FontData` used to resolve offsets for this table. |
| pub fn offset_data(&self) -> FontData<'a> { |
| match self { |
| Self::Format0(item) => item.offset_data(), |
| Self::Format2(item) => item.offset_data(), |
| Self::Format4(item) => item.offset_data(), |
| Self::Format6(item) => item.offset_data(), |
| Self::Format8(item) => item.offset_data(), |
| Self::Format10(item) => item.offset_data(), |
| } |
| } |
| |
| /// Format number is set to 0. |
| pub fn format(&self) -> u16 { |
| match self { |
| Self::Format0(item) => item.format(), |
| Self::Format2(item) => item.format(), |
| Self::Format4(item) => item.format(), |
| Self::Format6(item) => item.format(), |
| Self::Format8(item) => item.format(), |
| Self::Format10(item) => item.format(), |
| } |
| } |
| } |
| |
| impl<'a> FontRead<'a> for Lookup<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let format: u16 = data.read_at(0usize)?; |
| match format { |
| Lookup0Marker::FORMAT => Ok(Self::Format0(FontRead::read(data)?)), |
| Lookup2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)), |
| Lookup4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)), |
| Lookup6Marker::FORMAT => Ok(Self::Format6(FontRead::read(data)?)), |
| Lookup8Marker::FORMAT => Ok(Self::Format8(FontRead::read(data)?)), |
| Lookup10Marker::FORMAT => Ok(Self::Format10(FontRead::read(data)?)), |
| other => Err(ReadError::InvalidFormat(other.into())), |
| } |
| } |
| } |
| |
| impl MinByteRange for Lookup<'_> { |
| fn min_byte_range(&self) -> Range<usize> { |
| match self { |
| Self::Format0(item) => item.min_byte_range(), |
| Self::Format2(item) => item.min_byte_range(), |
| Self::Format4(item) => item.min_byte_range(), |
| Self::Format6(item) => item.min_byte_range(), |
| Self::Format8(item) => item.min_byte_range(), |
| Self::Format10(item) => item.min_byte_range(), |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> Lookup<'a> { |
| fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> { |
| match self { |
| Self::Format0(table) => table, |
| Self::Format2(table) => table, |
| Self::Format4(table) => table, |
| Self::Format6(table) => table, |
| Self::Format8(table) => table, |
| Self::Format10(table) => table, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl std::fmt::Debug for Lookup<'_> { |
| 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 Lookup<'a> { |
| fn type_name(&self) -> &str { |
| self.dyn_inner().type_name() |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| self.dyn_inner().get_field(idx) |
| } |
| } |
| |
| impl Format<u16> for Lookup0Marker { |
| const FORMAT: u16 = 0; |
| } |
| |
| /// Simple array format. The lookup data is an array of lookup values, indexed |
| /// by glyph index. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct Lookup0Marker { |
| values_data_byte_len: usize, |
| } |
| |
| impl Lookup0Marker { |
| pub fn format_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn values_data_byte_range(&self) -> Range<usize> { |
| let start = self.format_byte_range().end; |
| start..start + self.values_data_byte_len |
| } |
| } |
| |
| impl MinByteRange for Lookup0Marker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.values_data_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for Lookup0<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| let values_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; |
| cursor.advance_by(values_data_byte_len); |
| cursor.finish(Lookup0Marker { |
| values_data_byte_len, |
| }) |
| } |
| } |
| |
| /// Simple array format. The lookup data is an array of lookup values, indexed |
| /// by glyph index. |
| pub type Lookup0<'a> = TableRef<'a, Lookup0Marker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> Lookup0<'a> { |
| /// Format number is set to 0. |
| pub fn format(&self) -> u16 { |
| let range = self.shape.format_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Values, indexed by glyph index. |
| pub fn values_data(&self) -> &'a [u8] { |
| let range = self.shape.values_data_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for Lookup0<'a> { |
| fn type_name(&self) -> &str { |
| "Lookup0" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("format", self.format())), |
| 1usize => Some(Field::new("values_data", self.values_data())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for Lookup0<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| impl Format<u16> for Lookup2Marker { |
| const FORMAT: u16 = 2; |
| } |
| |
| /// Segment single format. Each non-overlapping segment has a single lookup |
| /// value that applies to all glyphs in the segment. A segment is defined as |
| /// a contiguous range of glyph indexes. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct Lookup2Marker { |
| segments_data_byte_len: usize, |
| } |
| |
| impl Lookup2Marker { |
| pub fn format_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn unit_size_byte_range(&self) -> Range<usize> { |
| let start = self.format_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn n_units_byte_range(&self) -> Range<usize> { |
| let start = self.unit_size_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn search_range_byte_range(&self) -> Range<usize> { |
| let start = self.n_units_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn entry_selector_byte_range(&self) -> Range<usize> { |
| let start = self.search_range_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn range_shift_byte_range(&self) -> Range<usize> { |
| let start = self.entry_selector_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn segments_data_byte_range(&self) -> Range<usize> { |
| let start = self.range_shift_byte_range().end; |
| start..start + self.segments_data_byte_len |
| } |
| } |
| |
| impl MinByteRange for Lookup2Marker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.segments_data_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for Lookup2<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| let unit_size: u16 = cursor.read()?; |
| let n_units: u16 = cursor.read()?; |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| let segments_data_byte_len = (transforms::add_multiply(unit_size, 0_usize, n_units)) |
| .checked_mul(u8::RAW_BYTE_LEN) |
| .ok_or(ReadError::OutOfBounds)?; |
| cursor.advance_by(segments_data_byte_len); |
| cursor.finish(Lookup2Marker { |
| segments_data_byte_len, |
| }) |
| } |
| } |
| |
| /// Segment single format. Each non-overlapping segment has a single lookup |
| /// value that applies to all glyphs in the segment. A segment is defined as |
| /// a contiguous range of glyph indexes. |
| pub type Lookup2<'a> = TableRef<'a, Lookup2Marker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> Lookup2<'a> { |
| /// Format number is set to 2. |
| pub fn format(&self) -> u16 { |
| let range = self.shape.format_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Size of a lookup unit for this search in bytes. |
| pub fn unit_size(&self) -> u16 { |
| let range = self.shape.unit_size_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Number of units of the preceding size to be searched. |
| pub fn n_units(&self) -> u16 { |
| let range = self.shape.n_units_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits. |
| pub fn search_range(&self) -> u16 { |
| let range = self.shape.search_range_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits. |
| pub fn entry_selector(&self) -> u16 { |
| let range = self.shape.entry_selector_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits. |
| pub fn range_shift(&self) -> u16 { |
| let range = self.shape.range_shift_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Segments. |
| pub fn segments_data(&self) -> &'a [u8] { |
| let range = self.shape.segments_data_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for Lookup2<'a> { |
| fn type_name(&self) -> &str { |
| "Lookup2" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("format", self.format())), |
| 1usize => Some(Field::new("unit_size", self.unit_size())), |
| 2usize => Some(Field::new("n_units", self.n_units())), |
| 3usize => Some(Field::new("search_range", self.search_range())), |
| 4usize => Some(Field::new("entry_selector", self.entry_selector())), |
| 5usize => Some(Field::new("range_shift", self.range_shift())), |
| 6usize => Some(Field::new("segments_data", self.segments_data())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for Lookup2<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| impl Format<u16> for Lookup4Marker { |
| const FORMAT: u16 = 4; |
| } |
| |
| /// Segment array format. A segment mapping is performed (as with Format 2), |
| /// but instead of a single lookup value for all the glyphs in the segment, |
| /// each glyph in the segment gets its own separate lookup value. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct Lookup4Marker { |
| segments_byte_len: usize, |
| } |
| |
| impl Lookup4Marker { |
| pub fn format_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn unit_size_byte_range(&self) -> Range<usize> { |
| let start = self.format_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn n_units_byte_range(&self) -> Range<usize> { |
| let start = self.unit_size_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn search_range_byte_range(&self) -> Range<usize> { |
| let start = self.n_units_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn entry_selector_byte_range(&self) -> Range<usize> { |
| let start = self.search_range_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn range_shift_byte_range(&self) -> Range<usize> { |
| let start = self.entry_selector_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn segments_byte_range(&self) -> Range<usize> { |
| let start = self.range_shift_byte_range().end; |
| start..start + self.segments_byte_len |
| } |
| } |
| |
| impl MinByteRange for Lookup4Marker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.segments_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for Lookup4<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| let n_units: u16 = cursor.read()?; |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| let segments_byte_len = (n_units as usize) |
| .checked_mul(LookupSegment4::RAW_BYTE_LEN) |
| .ok_or(ReadError::OutOfBounds)?; |
| cursor.advance_by(segments_byte_len); |
| cursor.finish(Lookup4Marker { segments_byte_len }) |
| } |
| } |
| |
| /// Segment array format. A segment mapping is performed (as with Format 2), |
| /// but instead of a single lookup value for all the glyphs in the segment, |
| /// each glyph in the segment gets its own separate lookup value. |
| pub type Lookup4<'a> = TableRef<'a, Lookup4Marker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> Lookup4<'a> { |
| /// Format number is set to 4. |
| pub fn format(&self) -> u16 { |
| let range = self.shape.format_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Size of a lookup unit for this search in bytes. |
| pub fn unit_size(&self) -> u16 { |
| let range = self.shape.unit_size_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Number of units of the preceding size to be searched. |
| pub fn n_units(&self) -> u16 { |
| let range = self.shape.n_units_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits. |
| pub fn search_range(&self) -> u16 { |
| let range = self.shape.search_range_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits. |
| pub fn entry_selector(&self) -> u16 { |
| let range = self.shape.entry_selector_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits. |
| pub fn range_shift(&self) -> u16 { |
| let range = self.shape.range_shift_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Segments. |
| pub fn segments(&self) -> &'a [LookupSegment4] { |
| let range = self.shape.segments_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for Lookup4<'a> { |
| fn type_name(&self) -> &str { |
| "Lookup4" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("format", self.format())), |
| 1usize => Some(Field::new("unit_size", self.unit_size())), |
| 2usize => Some(Field::new("n_units", self.n_units())), |
| 3usize => Some(Field::new("search_range", self.search_range())), |
| 4usize => Some(Field::new("entry_selector", self.entry_selector())), |
| 5usize => Some(Field::new("range_shift", self.range_shift())), |
| 6usize => Some(Field::new( |
| "segments", |
| traversal::FieldType::array_of_records( |
| stringify!(LookupSegment4), |
| self.segments(), |
| self.offset_data(), |
| ), |
| )), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for Lookup4<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| /// Lookup segment for format 4. |
| #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] |
| #[repr(C)] |
| #[repr(packed)] |
| pub struct LookupSegment4 { |
| /// Last glyph index in this segment. |
| pub last_glyph: BigEndian<u16>, |
| /// First glyph index in this segment. |
| pub first_glyph: BigEndian<u16>, |
| /// A 16-bit offset from the start of the table to the data. |
| pub value_offset: BigEndian<u16>, |
| } |
| |
| impl LookupSegment4 { |
| /// Last glyph index in this segment. |
| pub fn last_glyph(&self) -> u16 { |
| self.last_glyph.get() |
| } |
| |
| /// First glyph index in this segment. |
| pub fn first_glyph(&self) -> u16 { |
| self.first_glyph.get() |
| } |
| |
| /// A 16-bit offset from the start of the table to the data. |
| pub fn value_offset(&self) -> u16 { |
| self.value_offset.get() |
| } |
| } |
| |
| impl FixedSize for LookupSegment4 { |
| const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN; |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeRecord<'a> for LookupSegment4 { |
| fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { |
| RecordResolver { |
| name: "LookupSegment4", |
| get_field: Box::new(move |idx, _data| match idx { |
| 0usize => Some(Field::new("last_glyph", self.last_glyph())), |
| 1usize => Some(Field::new("first_glyph", self.first_glyph())), |
| 2usize => Some(Field::new("value_offset", self.value_offset())), |
| _ => None, |
| }), |
| data, |
| } |
| } |
| } |
| |
| impl Format<u16> for Lookup6Marker { |
| const FORMAT: u16 = 6; |
| } |
| |
| /// Single table format. The lookup data is a sorted list of |
| /// <glyph index,lookup value> pairs. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct Lookup6Marker { |
| entries_data_byte_len: usize, |
| } |
| |
| impl Lookup6Marker { |
| pub fn format_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn unit_size_byte_range(&self) -> Range<usize> { |
| let start = self.format_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn n_units_byte_range(&self) -> Range<usize> { |
| let start = self.unit_size_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn search_range_byte_range(&self) -> Range<usize> { |
| let start = self.n_units_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn entry_selector_byte_range(&self) -> Range<usize> { |
| let start = self.search_range_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn range_shift_byte_range(&self) -> Range<usize> { |
| let start = self.entry_selector_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn entries_data_byte_range(&self) -> Range<usize> { |
| let start = self.range_shift_byte_range().end; |
| start..start + self.entries_data_byte_len |
| } |
| } |
| |
| impl MinByteRange for Lookup6Marker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.entries_data_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for Lookup6<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| let unit_size: u16 = cursor.read()?; |
| let n_units: u16 = cursor.read()?; |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| let entries_data_byte_len = (transforms::add_multiply(unit_size, 0_usize, n_units)) |
| .checked_mul(u8::RAW_BYTE_LEN) |
| .ok_or(ReadError::OutOfBounds)?; |
| cursor.advance_by(entries_data_byte_len); |
| cursor.finish(Lookup6Marker { |
| entries_data_byte_len, |
| }) |
| } |
| } |
| |
| /// Single table format. The lookup data is a sorted list of |
| /// <glyph index,lookup value> pairs. |
| pub type Lookup6<'a> = TableRef<'a, Lookup6Marker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> Lookup6<'a> { |
| /// Format number is set to 6. |
| pub fn format(&self) -> u16 { |
| let range = self.shape.format_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Size of a lookup unit for this search in bytes. |
| pub fn unit_size(&self) -> u16 { |
| let range = self.shape.unit_size_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Number of units of the preceding size to be searched. |
| pub fn n_units(&self) -> u16 { |
| let range = self.shape.n_units_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits. |
| pub fn search_range(&self) -> u16 { |
| let range = self.shape.search_range_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits. |
| pub fn entry_selector(&self) -> u16 { |
| let range = self.shape.entry_selector_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits. |
| pub fn range_shift(&self) -> u16 { |
| let range = self.shape.range_shift_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Values, indexed by glyph index. |
| pub fn entries_data(&self) -> &'a [u8] { |
| let range = self.shape.entries_data_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for Lookup6<'a> { |
| fn type_name(&self) -> &str { |
| "Lookup6" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("format", self.format())), |
| 1usize => Some(Field::new("unit_size", self.unit_size())), |
| 2usize => Some(Field::new("n_units", self.n_units())), |
| 3usize => Some(Field::new("search_range", self.search_range())), |
| 4usize => Some(Field::new("entry_selector", self.entry_selector())), |
| 5usize => Some(Field::new("range_shift", self.range_shift())), |
| 6usize => Some(Field::new("entries_data", self.entries_data())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for Lookup6<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| impl Format<u16> for Lookup8Marker { |
| const FORMAT: u16 = 8; |
| } |
| |
| /// Trimmed array format. The lookup data is a simple trimmed array |
| /// indexed by glyph index. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct Lookup8Marker { |
| value_array_byte_len: usize, |
| } |
| |
| impl Lookup8Marker { |
| pub fn format_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn first_glyph_byte_range(&self) -> Range<usize> { |
| let start = self.format_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn glyph_count_byte_range(&self) -> Range<usize> { |
| let start = self.first_glyph_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn value_array_byte_range(&self) -> Range<usize> { |
| let start = self.glyph_count_byte_range().end; |
| start..start + self.value_array_byte_len |
| } |
| } |
| |
| impl MinByteRange for Lookup8Marker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.value_array_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for Lookup8<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| let value_array_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN; |
| cursor.advance_by(value_array_byte_len); |
| cursor.finish(Lookup8Marker { |
| value_array_byte_len, |
| }) |
| } |
| } |
| |
| /// Trimmed array format. The lookup data is a simple trimmed array |
| /// indexed by glyph index. |
| pub type Lookup8<'a> = TableRef<'a, Lookup8Marker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> Lookup8<'a> { |
| /// Format number is set to 8. |
| pub fn format(&self) -> u16 { |
| let range = self.shape.format_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// First glyph index included in the trimmed array. |
| pub fn first_glyph(&self) -> u16 { |
| let range = self.shape.first_glyph_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Total number of glyphs (equivalent to the last glyph minus the value |
| /// of firstGlyph plus 1). |
| pub fn glyph_count(&self) -> u16 { |
| let range = self.shape.glyph_count_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The lookup values (indexed by the glyph index minus the value of |
| /// firstGlyph). Entries in the value array must be two bytes. |
| pub fn value_array(&self) -> &'a [BigEndian<u16>] { |
| let range = self.shape.value_array_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for Lookup8<'a> { |
| fn type_name(&self) -> &str { |
| "Lookup8" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("format", self.format())), |
| 1usize => Some(Field::new("first_glyph", self.first_glyph())), |
| 2usize => Some(Field::new("glyph_count", self.glyph_count())), |
| 3usize => Some(Field::new("value_array", self.value_array())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for Lookup8<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| impl Format<u16> for Lookup10Marker { |
| const FORMAT: u16 = 10; |
| } |
| |
| /// Trimmed array format. The lookup data is a simple trimmed array |
| /// indexed by glyph index. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct Lookup10Marker { |
| values_data_byte_len: usize, |
| } |
| |
| impl Lookup10Marker { |
| pub fn format_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn unit_size_byte_range(&self) -> Range<usize> { |
| let start = self.format_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn first_glyph_byte_range(&self) -> Range<usize> { |
| let start = self.unit_size_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn glyph_count_byte_range(&self) -> Range<usize> { |
| let start = self.first_glyph_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn values_data_byte_range(&self) -> Range<usize> { |
| let start = self.glyph_count_byte_range().end; |
| start..start + self.values_data_byte_len |
| } |
| } |
| |
| impl MinByteRange for Lookup10Marker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.values_data_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for Lookup10<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| cursor.advance::<u16>(); |
| let values_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; |
| cursor.advance_by(values_data_byte_len); |
| cursor.finish(Lookup10Marker { |
| values_data_byte_len, |
| }) |
| } |
| } |
| |
| /// Trimmed array format. The lookup data is a simple trimmed array |
| /// indexed by glyph index. |
| pub type Lookup10<'a> = TableRef<'a, Lookup10Marker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> Lookup10<'a> { |
| /// Format number is set to 10. |
| pub fn format(&self) -> u16 { |
| let range = self.shape.format_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Size of a lookup unit for this lookup table in bytes. Allowed values |
| /// are 1, 2, 4, and 8. |
| pub fn unit_size(&self) -> u16 { |
| let range = self.shape.unit_size_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// First glyph index included in the trimmed array. |
| pub fn first_glyph(&self) -> u16 { |
| let range = self.shape.first_glyph_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Total number of glyphs (equivalent to the last glyph minus the value |
| /// of firstGlyph plus 1). |
| pub fn glyph_count(&self) -> u16 { |
| let range = self.shape.glyph_count_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The lookup values (indexed by the glyph index minus the value of |
| /// firstGlyph). |
| pub fn values_data(&self) -> &'a [u8] { |
| let range = self.shape.values_data_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for Lookup10<'a> { |
| fn type_name(&self) -> &str { |
| "Lookup10" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("format", self.format())), |
| 1usize => Some(Field::new("unit_size", self.unit_size())), |
| 2usize => Some(Field::new("first_glyph", self.first_glyph())), |
| 3usize => Some(Field::new("glyph_count", self.glyph_count())), |
| 4usize => Some(Field::new("values_data", self.values_data())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for Lookup10<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| /// Header for a state table. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct StateHeaderMarker {} |
| |
| impl StateHeaderMarker { |
| pub fn state_size_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn class_table_offset_byte_range(&self) -> Range<usize> { |
| let start = self.state_size_byte_range().end; |
| start..start + Offset16::RAW_BYTE_LEN |
| } |
| |
| pub fn state_array_offset_byte_range(&self) -> Range<usize> { |
| let start = self.class_table_offset_byte_range().end; |
| start..start + Offset16::RAW_BYTE_LEN |
| } |
| |
| pub fn entry_table_offset_byte_range(&self) -> Range<usize> { |
| let start = self.state_array_offset_byte_range().end; |
| start..start + Offset16::RAW_BYTE_LEN |
| } |
| } |
| |
| impl MinByteRange for StateHeaderMarker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.entry_table_offset_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for StateHeader<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| cursor.advance::<Offset16>(); |
| cursor.advance::<Offset16>(); |
| cursor.advance::<Offset16>(); |
| cursor.finish(StateHeaderMarker {}) |
| } |
| } |
| |
| /// Header for a state table. |
| pub type StateHeader<'a> = TableRef<'a, StateHeaderMarker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> StateHeader<'a> { |
| /// Size of a state, in bytes. The size is limited to 8 bits, although the |
| /// field is 16 bits for alignment. |
| pub fn state_size(&self) -> u16 { |
| let range = self.shape.state_size_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Byte offset from the beginning of the state table to the class subtable. |
| pub fn class_table_offset(&self) -> Offset16 { |
| let range = self.shape.class_table_offset_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Attempt to resolve [`class_table_offset`][Self::class_table_offset]. |
| pub fn class_table(&self) -> Result<ClassSubtable<'a>, ReadError> { |
| let data = self.data; |
| self.class_table_offset().resolve(data) |
| } |
| |
| /// Byte offset from the beginning of the state table to the state array. |
| pub fn state_array_offset(&self) -> Offset16 { |
| let range = self.shape.state_array_offset_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Attempt to resolve [`state_array_offset`][Self::state_array_offset]. |
| pub fn state_array(&self) -> Result<RawBytes<'a>, ReadError> { |
| let data = self.data; |
| self.state_array_offset().resolve(data) |
| } |
| |
| /// Byte offset from the beginning of the state table to the entry subtable. |
| pub fn entry_table_offset(&self) -> Offset16 { |
| let range = self.shape.entry_table_offset_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Attempt to resolve [`entry_table_offset`][Self::entry_table_offset]. |
| pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> { |
| let data = self.data; |
| self.entry_table_offset().resolve(data) |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for StateHeader<'a> { |
| fn type_name(&self) -> &str { |
| "StateHeader" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("state_size", self.state_size())), |
| 1usize => Some(Field::new( |
| "class_table_offset", |
| FieldType::offset(self.class_table_offset(), self.class_table()), |
| )), |
| 2usize => Some(Field::new( |
| "state_array_offset", |
| FieldType::offset(self.state_array_offset(), self.state_array()), |
| )), |
| 3usize => Some(Field::new( |
| "entry_table_offset", |
| FieldType::offset(self.entry_table_offset(), self.entry_table()), |
| )), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for StateHeader<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| /// Maps the glyph indexes of your font into classes. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct ClassSubtableMarker { |
| class_array_byte_len: usize, |
| } |
| |
| impl ClassSubtableMarker { |
| pub fn first_glyph_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn n_glyphs_byte_range(&self) -> Range<usize> { |
| let start = self.first_glyph_byte_range().end; |
| start..start + u16::RAW_BYTE_LEN |
| } |
| |
| pub fn class_array_byte_range(&self) -> Range<usize> { |
| let start = self.n_glyphs_byte_range().end; |
| start..start + self.class_array_byte_len |
| } |
| } |
| |
| impl MinByteRange for ClassSubtableMarker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.class_array_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for ClassSubtable<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u16>(); |
| let n_glyphs: u16 = cursor.read()?; |
| let class_array_byte_len = (n_glyphs as usize) |
| .checked_mul(u8::RAW_BYTE_LEN) |
| .ok_or(ReadError::OutOfBounds)?; |
| cursor.advance_by(class_array_byte_len); |
| cursor.finish(ClassSubtableMarker { |
| class_array_byte_len, |
| }) |
| } |
| } |
| |
| /// Maps the glyph indexes of your font into classes. |
| pub type ClassSubtable<'a> = TableRef<'a, ClassSubtableMarker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> ClassSubtable<'a> { |
| /// Glyph index of the first glyph in the class table. |
| pub fn first_glyph(&self) -> u16 { |
| let range = self.shape.first_glyph_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Number of glyphs in class table. |
| pub fn n_glyphs(&self) -> u16 { |
| let range = self.shape.n_glyphs_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// The class codes (indexed by glyph index minus firstGlyph). Class codes |
| /// range from 0 to the value of stateSize minus 1. |
| pub fn class_array(&self) -> &'a [u8] { |
| let range = self.shape.class_array_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for ClassSubtable<'a> { |
| fn type_name(&self) -> &str { |
| "ClassSubtable" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("first_glyph", self.first_glyph())), |
| 1usize => Some(Field::new("n_glyphs", self.n_glyphs())), |
| 2usize => Some(Field::new("class_array", self.class_array())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for ClassSubtable<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| /// Used for the `state_array` and `entry_table` fields in [`StateHeader`]. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct RawBytesMarker { |
| data_byte_len: usize, |
| } |
| |
| impl RawBytesMarker { |
| pub fn data_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + self.data_byte_len |
| } |
| } |
| |
| impl MinByteRange for RawBytesMarker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.data_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for RawBytes<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; |
| cursor.advance_by(data_byte_len); |
| cursor.finish(RawBytesMarker { data_byte_len }) |
| } |
| } |
| |
| /// Used for the `state_array` and `entry_table` fields in [`StateHeader`]. |
| pub type RawBytes<'a> = TableRef<'a, RawBytesMarker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> RawBytes<'a> { |
| pub fn data(&self) -> &'a [u8] { |
| let range = self.shape.data_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for RawBytes<'a> { |
| fn type_name(&self) -> &str { |
| "RawBytes" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("data", self.data())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for RawBytes<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| /// Header for an extended state table. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct StxHeaderMarker {} |
| |
| impl StxHeaderMarker { |
| pub fn n_classes_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + u32::RAW_BYTE_LEN |
| } |
| |
| pub fn class_table_offset_byte_range(&self) -> Range<usize> { |
| let start = self.n_classes_byte_range().end; |
| start..start + Offset32::RAW_BYTE_LEN |
| } |
| |
| pub fn state_array_offset_byte_range(&self) -> Range<usize> { |
| let start = self.class_table_offset_byte_range().end; |
| start..start + Offset32::RAW_BYTE_LEN |
| } |
| |
| pub fn entry_table_offset_byte_range(&self) -> Range<usize> { |
| let start = self.state_array_offset_byte_range().end; |
| start..start + Offset32::RAW_BYTE_LEN |
| } |
| } |
| |
| impl MinByteRange for StxHeaderMarker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.entry_table_offset_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for StxHeader<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| cursor.advance::<u32>(); |
| cursor.advance::<Offset32>(); |
| cursor.advance::<Offset32>(); |
| cursor.advance::<Offset32>(); |
| cursor.finish(StxHeaderMarker {}) |
| } |
| } |
| |
| /// Header for an extended state table. |
| pub type StxHeader<'a> = TableRef<'a, StxHeaderMarker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> StxHeader<'a> { |
| /// Number of classes, which is the number of 16-bit entry indices in a single line in the state array. |
| pub fn n_classes(&self) -> u32 { |
| let range = self.shape.n_classes_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Byte offset from the beginning of the state table to the class subtable. |
| pub fn class_table_offset(&self) -> Offset32 { |
| let range = self.shape.class_table_offset_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Attempt to resolve [`class_table_offset`][Self::class_table_offset]. |
| pub fn class_table(&self) -> Result<LookupU16<'a>, ReadError> { |
| let data = self.data; |
| self.class_table_offset().resolve(data) |
| } |
| |
| /// Byte offset from the beginning of the state table to the state array. |
| pub fn state_array_offset(&self) -> Offset32 { |
| let range = self.shape.state_array_offset_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Attempt to resolve [`state_array_offset`][Self::state_array_offset]. |
| pub fn state_array(&self) -> Result<RawWords<'a>, ReadError> { |
| let data = self.data; |
| self.state_array_offset().resolve(data) |
| } |
| |
| /// Byte offset from the beginning of the state table to the entry subtable. |
| pub fn entry_table_offset(&self) -> Offset32 { |
| let range = self.shape.entry_table_offset_byte_range(); |
| self.data.read_at(range.start).unwrap() |
| } |
| |
| /// Attempt to resolve [`entry_table_offset`][Self::entry_table_offset]. |
| pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> { |
| let data = self.data; |
| self.entry_table_offset().resolve(data) |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for StxHeader<'a> { |
| fn type_name(&self) -> &str { |
| "StxHeader" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("n_classes", self.n_classes())), |
| 1usize => Some(Field::new( |
| "class_table_offset", |
| FieldType::offset(self.class_table_offset(), self.class_table()), |
| )), |
| 2usize => Some(Field::new( |
| "state_array_offset", |
| FieldType::offset(self.state_array_offset(), self.state_array()), |
| )), |
| 3usize => Some(Field::new( |
| "entry_table_offset", |
| FieldType::offset(self.entry_table_offset(), self.entry_table()), |
| )), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for StxHeader<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |
| |
| /// Used for the `state_array` in [`StxHeader`]. |
| #[derive(Debug, Clone, Copy)] |
| #[doc(hidden)] |
| pub struct RawWordsMarker { |
| data_byte_len: usize, |
| } |
| |
| impl RawWordsMarker { |
| pub fn data_byte_range(&self) -> Range<usize> { |
| let start = 0; |
| start..start + self.data_byte_len |
| } |
| } |
| |
| impl MinByteRange for RawWordsMarker { |
| fn min_byte_range(&self) -> Range<usize> { |
| 0..self.data_byte_range().end |
| } |
| } |
| |
| impl<'a> FontRead<'a> for RawWords<'a> { |
| fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
| let mut cursor = data.cursor(); |
| let data_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN; |
| cursor.advance_by(data_byte_len); |
| cursor.finish(RawWordsMarker { data_byte_len }) |
| } |
| } |
| |
| /// Used for the `state_array` in [`StxHeader`]. |
| pub type RawWords<'a> = TableRef<'a, RawWordsMarker>; |
| |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> RawWords<'a> { |
| pub fn data(&self) -> &'a [BigEndian<u16>] { |
| let range = self.shape.data_byte_range(); |
| self.data.read_array(range).unwrap() |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| impl<'a> SomeTable<'a> for RawWords<'a> { |
| fn type_name(&self) -> &str { |
| "RawWords" |
| } |
| fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
| match idx { |
| 0usize => Some(Field::new("data", self.data())), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(feature = "experimental_traverse")] |
| #[allow(clippy::needless_lifetimes)] |
| impl<'a> std::fmt::Debug for RawWords<'a> { |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| (self as &dyn SomeTable<'a>).fmt(f) |
| } |
| } |