// 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::*; /// [BitmapSize](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmapsize-record) record. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] #[repr(C)] #[repr(packed)] pub struct BitmapSize { /// Offset to IndexSubtableList, from beginning of EBLC/CBLC. pub index_subtable_list_offset: BigEndian, /// Total size in bytes of the IndexSubtableList including its array of IndexSubtables. pub index_subtable_list_size: BigEndian, /// Number of IndexSubtables in the IndexSubtableList. pub number_of_index_subtables: BigEndian, /// Not used; set to 0. pub color_ref: BigEndian, /// Line metrics for text rendered horizontally. pub hori: SbitLineMetrics, /// Line metrics for text rendered vertically. pub vert: SbitLineMetrics, /// Lowest glyph index for this size. pub start_glyph_index: BigEndian, /// Highest glyph index for this size. pub end_glyph_index: BigEndian, /// Horizontal pixels per em. pub ppem_x: u8, /// Vertical pixels per em. pub ppem_y: u8, /// The Microsoft rasterizer v.1.7 or greater supports the following /// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC). pub bit_depth: u8, /// Vertical or horizontal. pub flags: BigEndian, } impl BitmapSize { /// Offset to IndexSubtableList, from beginning of EBLC/CBLC. pub fn index_subtable_list_offset(&self) -> u32 { self.index_subtable_list_offset.get() } /// Total size in bytes of the IndexSubtableList including its array of IndexSubtables. pub fn index_subtable_list_size(&self) -> u32 { self.index_subtable_list_size.get() } /// Number of IndexSubtables in the IndexSubtableList. pub fn number_of_index_subtables(&self) -> u32 { self.number_of_index_subtables.get() } /// Not used; set to 0. pub fn color_ref(&self) -> u32 { self.color_ref.get() } /// Line metrics for text rendered horizontally. pub fn hori(&self) -> &SbitLineMetrics { &self.hori } /// Line metrics for text rendered vertically. pub fn vert(&self) -> &SbitLineMetrics { &self.vert } /// Lowest glyph index for this size. pub fn start_glyph_index(&self) -> GlyphId16 { self.start_glyph_index.get() } /// Highest glyph index for this size. pub fn end_glyph_index(&self) -> GlyphId16 { self.end_glyph_index.get() } /// Horizontal pixels per em. pub fn ppem_x(&self) -> u8 { self.ppem_x } /// Vertical pixels per em. pub fn ppem_y(&self) -> u8 { self.ppem_y } /// The Microsoft rasterizer v.1.7 or greater supports the following /// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC). pub fn bit_depth(&self) -> u8 { self.bit_depth } /// Vertical or horizontal. pub fn flags(&self) -> BitmapFlags { self.flags.get() } } impl FixedSize for BitmapSize { const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + SbitLineMetrics::RAW_BYTE_LEN + SbitLineMetrics::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + BitmapFlags::RAW_BYTE_LEN; } #[cfg(feature = "experimental_traverse")] impl<'a> SomeRecord<'a> for BitmapSize { fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { RecordResolver { name: "BitmapSize", get_field: Box::new(move |idx, _data| match idx { 0usize => Some(Field::new( "index_subtable_list_offset", self.index_subtable_list_offset(), )), 1usize => Some(Field::new( "index_subtable_list_size", self.index_subtable_list_size(), )), 2usize => Some(Field::new( "number_of_index_subtables", self.number_of_index_subtables(), )), 3usize => Some(Field::new("color_ref", self.color_ref())), 4usize => Some(Field::new("hori", self.hori().traversal_type(_data))), 5usize => Some(Field::new("vert", self.vert().traversal_type(_data))), 6usize => Some(Field::new("start_glyph_index", self.start_glyph_index())), 7usize => Some(Field::new("end_glyph_index", self.end_glyph_index())), 8usize => Some(Field::new("ppem_x", self.ppem_x())), 9usize => Some(Field::new("ppem_y", self.ppem_y())), 10usize => Some(Field::new("bit_depth", self.bit_depth())), 11usize => Some(Field::new("flags", self.flags())), _ => None, }), data, } } } /// [SbitLineMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record) record. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] #[repr(C)] #[repr(packed)] pub struct SbitLineMetrics { pub ascender: BigEndian, pub descender: BigEndian, pub width_max: u8, pub caret_slope_numerator: BigEndian, pub caret_slope_denominator: u8, pub caret_offset: BigEndian, pub min_origin_sb: BigEndian, pub min_advance_sb: BigEndian, pub max_before_bl: BigEndian, pub min_after_bl: BigEndian, pub pad1: BigEndian, pub pad2: BigEndian, } impl SbitLineMetrics { pub fn ascender(&self) -> i8 { self.ascender.get() } pub fn descender(&self) -> i8 { self.descender.get() } pub fn width_max(&self) -> u8 { self.width_max } pub fn caret_slope_numerator(&self) -> i8 { self.caret_slope_numerator.get() } pub fn caret_slope_denominator(&self) -> u8 { self.caret_slope_denominator } pub fn caret_offset(&self) -> i8 { self.caret_offset.get() } pub fn min_origin_sb(&self) -> i8 { self.min_origin_sb.get() } pub fn min_advance_sb(&self) -> i8 { self.min_advance_sb.get() } pub fn max_before_bl(&self) -> i8 { self.max_before_bl.get() } pub fn min_after_bl(&self) -> i8 { self.min_after_bl.get() } pub fn pad1(&self) -> i8 { self.pad1.get() } pub fn pad2(&self) -> i8 { self.pad2.get() } } impl FixedSize for SbitLineMetrics { const RAW_BYTE_LEN: usize = i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN; } #[cfg(feature = "experimental_traverse")] impl<'a> SomeRecord<'a> for SbitLineMetrics { fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { RecordResolver { name: "SbitLineMetrics", get_field: Box::new(move |idx, _data| match idx { 0usize => Some(Field::new("ascender", self.ascender())), 1usize => Some(Field::new("descender", self.descender())), 2usize => Some(Field::new("width_max", self.width_max())), 3usize => Some(Field::new( "caret_slope_numerator", self.caret_slope_numerator(), )), 4usize => Some(Field::new( "caret_slope_denominator", self.caret_slope_denominator(), )), 5usize => Some(Field::new("caret_offset", self.caret_offset())), 6usize => Some(Field::new("min_origin_sb", self.min_origin_sb())), 7usize => Some(Field::new("min_advance_sb", self.min_advance_sb())), 8usize => Some(Field::new("max_before_bl", self.max_before_bl())), 9usize => Some(Field::new("min_after_bl", self.min_after_bl())), 10usize => Some(Field::new("pad1", self.pad1())), 11usize => Some(Field::new("pad2", self.pad2())), _ => None, }), data, } } } /// [Bitmap flags](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmap-flags). #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[repr(transparent)] pub struct BitmapFlags { bits: u8, } impl BitmapFlags { /// Horizontal pub const HORIZONTAL_METRICS: Self = Self { bits: 0x01 }; /// Vertical pub const VERTICAL_METRICS: Self = Self { bits: 0x02 }; } impl BitmapFlags { /// Returns an empty set of flags. #[inline] pub const fn empty() -> Self { Self { bits: 0 } } /// Returns the set containing all flags. #[inline] pub const fn all() -> Self { Self { bits: Self::HORIZONTAL_METRICS.bits | Self::VERTICAL_METRICS.bits, } } /// Returns the raw value of the flags currently stored. #[inline] pub const fn bits(&self) -> u8 { self.bits } /// Convert from underlying bit representation, unless that /// representation contains bits that do not correspond to a flag. #[inline] pub const fn from_bits(bits: u8) -> Option { if (bits & !Self::all().bits()) == 0 { Some(Self { bits }) } else { None } } /// Convert from underlying bit representation, dropping any bits /// that do not correspond to flags. #[inline] pub const fn from_bits_truncate(bits: u8) -> Self { Self { bits: bits & Self::all().bits, } } /// Returns `true` if no flags are currently stored. #[inline] pub const fn is_empty(&self) -> bool { self.bits() == Self::empty().bits() } /// Returns `true` if there are flags common to both `self` and `other`. #[inline] pub const fn intersects(&self, other: Self) -> bool { !(Self { bits: self.bits & other.bits, }) .is_empty() } /// Returns `true` if all of the flags in `other` are contained within `self`. #[inline] pub const fn contains(&self, other: Self) -> bool { (self.bits & other.bits) == other.bits } /// Inserts the specified flags in-place. #[inline] pub fn insert(&mut self, other: Self) { self.bits |= other.bits; } /// Removes the specified flags in-place. #[inline] pub fn remove(&mut self, other: Self) { self.bits &= !other.bits; } /// Toggles the specified flags in-place. #[inline] pub fn toggle(&mut self, other: Self) { self.bits ^= other.bits; } /// Returns the intersection between the flags in `self` and /// `other`. /// /// Specifically, the returned set contains only the flags which are /// present in *both* `self` *and* `other`. /// /// This is equivalent to using the `&` operator (e.g. /// [`ops::BitAnd`]), as in `flags & other`. /// /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html #[inline] #[must_use] pub const fn intersection(self, other: Self) -> Self { Self { bits: self.bits & other.bits, } } /// Returns the union of between the flags in `self` and `other`. /// /// Specifically, the returned set contains all flags which are /// present in *either* `self` *or* `other`, including any which are /// present in both. /// /// This is equivalent to using the `|` operator (e.g. /// [`ops::BitOr`]), as in `flags | other`. /// /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html #[inline] #[must_use] pub const fn union(self, other: Self) -> Self { Self { bits: self.bits | other.bits, } } /// Returns the difference between the flags in `self` and `other`. /// /// Specifically, the returned set contains all flags present in /// `self`, except for the ones present in `other`. /// /// It is also conceptually equivalent to the "bit-clear" operation: /// `flags & !other` (and this syntax is also supported). /// /// This is equivalent to using the `-` operator (e.g. /// [`ops::Sub`]), as in `flags - other`. /// /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html #[inline] #[must_use] pub const fn difference(self, other: Self) -> Self { Self { bits: self.bits & !other.bits, } } } impl std::ops::BitOr for BitmapFlags { type Output = Self; /// Returns the union of the two sets of flags. #[inline] fn bitor(self, other: BitmapFlags) -> Self { Self { bits: self.bits | other.bits, } } } impl std::ops::BitOrAssign for BitmapFlags { /// Adds the set of flags. #[inline] fn bitor_assign(&mut self, other: Self) { self.bits |= other.bits; } } impl std::ops::BitXor for BitmapFlags { type Output = Self; /// Returns the left flags, but with all the right flags toggled. #[inline] fn bitxor(self, other: Self) -> Self { Self { bits: self.bits ^ other.bits, } } } impl std::ops::BitXorAssign for BitmapFlags { /// Toggles the set of flags. #[inline] fn bitxor_assign(&mut self, other: Self) { self.bits ^= other.bits; } } impl std::ops::BitAnd for BitmapFlags { type Output = Self; /// Returns the intersection between the two sets of flags. #[inline] fn bitand(self, other: Self) -> Self { Self { bits: self.bits & other.bits, } } } impl std::ops::BitAndAssign for BitmapFlags { /// Disables all flags disabled in the set. #[inline] fn bitand_assign(&mut self, other: Self) { self.bits &= other.bits; } } impl std::ops::Sub for BitmapFlags { type Output = Self; /// Returns the set difference of the two sets of flags. #[inline] fn sub(self, other: Self) -> Self { Self { bits: self.bits & !other.bits, } } } impl std::ops::SubAssign for BitmapFlags { /// Disables all flags enabled in the set. #[inline] fn sub_assign(&mut self, other: Self) { self.bits &= !other.bits; } } impl std::ops::Not for BitmapFlags { type Output = Self; /// Returns the complement of this set of flags. #[inline] fn not(self) -> Self { Self { bits: !self.bits } & Self::all() } } impl std::fmt::Debug for BitmapFlags { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let members: &[(&str, Self)] = &[ ("HORIZONTAL_METRICS", Self::HORIZONTAL_METRICS), ("VERTICAL_METRICS", Self::VERTICAL_METRICS), ]; let mut first = true; for (name, value) in members { if self.contains(*value) { if !first { f.write_str(" | ")?; } first = false; f.write_str(name)?; } } if first { f.write_str("(empty)")?; } Ok(()) } } impl std::fmt::Binary for BitmapFlags { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Binary::fmt(&self.bits, f) } } impl std::fmt::Octal for BitmapFlags { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Octal::fmt(&self.bits, f) } } impl std::fmt::LowerHex for BitmapFlags { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::LowerHex::fmt(&self.bits, f) } } impl std::fmt::UpperHex for BitmapFlags { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::UpperHex::fmt(&self.bits, f) } } impl font_types::Scalar for BitmapFlags { type Raw = ::Raw; fn to_raw(self) -> Self::Raw { self.bits().to_raw() } fn from_raw(raw: Self::Raw) -> Self { let t = ::from_raw(raw); Self::from_bits_truncate(t) } } #[cfg(feature = "experimental_traverse")] impl<'a> From for FieldType<'a> { fn from(src: BitmapFlags) -> FieldType<'a> { src.bits().into() } } /// [BigGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bigglyphmetrics) record. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] #[repr(C)] #[repr(packed)] pub struct BigGlyphMetrics { /// Number of rows of data. pub height: u8, /// Number of columns of data. pub width: u8, /// Distance in pixels from the horizontal origin to the left edge of the bitmap. pub hori_bearing_x: BigEndian, /// Distance in pixels from the horizontal origin to the top edge of the bitmap. pub hori_bearing_y: BigEndian, /// Horizontal advance width in pixels. pub hori_advance: u8, /// Distance in pixels from the vertical origin to the left edge of the bitmap. pub vert_bearing_x: BigEndian, /// Distance in pixels from the vertical origin to the top edge of the bitmap. pub vert_bearing_y: BigEndian, /// Vertical advance width in pixels. pub vert_advance: u8, } impl BigGlyphMetrics { /// Number of rows of data. pub fn height(&self) -> u8 { self.height } /// Number of columns of data. pub fn width(&self) -> u8 { self.width } /// Distance in pixels from the horizontal origin to the left edge of the bitmap. pub fn hori_bearing_x(&self) -> i8 { self.hori_bearing_x.get() } /// Distance in pixels from the horizontal origin to the top edge of the bitmap. pub fn hori_bearing_y(&self) -> i8 { self.hori_bearing_y.get() } /// Horizontal advance width in pixels. pub fn hori_advance(&self) -> u8 { self.hori_advance } /// Distance in pixels from the vertical origin to the left edge of the bitmap. pub fn vert_bearing_x(&self) -> i8 { self.vert_bearing_x.get() } /// Distance in pixels from the vertical origin to the top edge of the bitmap. pub fn vert_bearing_y(&self) -> i8 { self.vert_bearing_y.get() } /// Vertical advance width in pixels. pub fn vert_advance(&self) -> u8 { self.vert_advance } } impl FixedSize for BigGlyphMetrics { const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN; } #[cfg(feature = "experimental_traverse")] impl<'a> SomeRecord<'a> for BigGlyphMetrics { fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { RecordResolver { name: "BigGlyphMetrics", get_field: Box::new(move |idx, _data| match idx { 0usize => Some(Field::new("height", self.height())), 1usize => Some(Field::new("width", self.width())), 2usize => Some(Field::new("hori_bearing_x", self.hori_bearing_x())), 3usize => Some(Field::new("hori_bearing_y", self.hori_bearing_y())), 4usize => Some(Field::new("hori_advance", self.hori_advance())), 5usize => Some(Field::new("vert_bearing_x", self.vert_bearing_x())), 6usize => Some(Field::new("vert_bearing_y", self.vert_bearing_y())), 7usize => Some(Field::new("vert_advance", self.vert_advance())), _ => None, }), data, } } } /// [SmallGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#smallglyphmetrics) record. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] #[repr(C)] #[repr(packed)] pub struct SmallGlyphMetrics { /// Number of rows of data. pub height: u8, /// Number of columns of data. pub width: u8, /// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text). pub bearing_x: BigEndian, /// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text). pub bearing_y: BigEndian, /// Horizontal or vertical advance width in pixels. pub advance: u8, } impl SmallGlyphMetrics { /// Number of rows of data. pub fn height(&self) -> u8 { self.height } /// Number of columns of data. pub fn width(&self) -> u8 { self.width } /// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text). pub fn bearing_x(&self) -> i8 { self.bearing_x.get() } /// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text). pub fn bearing_y(&self) -> i8 { self.bearing_y.get() } /// Horizontal or vertical advance width in pixels. pub fn advance(&self) -> u8 { self.advance } } impl FixedSize for SmallGlyphMetrics { const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN; } #[cfg(feature = "experimental_traverse")] impl<'a> SomeRecord<'a> for SmallGlyphMetrics { fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { RecordResolver { name: "SmallGlyphMetrics", get_field: Box::new(move |idx, _data| match idx { 0usize => Some(Field::new("height", self.height())), 1usize => Some(Field::new("width", self.width())), 2usize => Some(Field::new("bearing_x", self.bearing_x())), 3usize => Some(Field::new("bearing_y", self.bearing_y())), 4usize => Some(Field::new("advance", self.advance())), _ => None, }), data, } } } /// [IndexSubtableList](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablelist) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] pub struct IndexSubtableListMarker { index_subtable_records_byte_len: usize, } impl IndexSubtableListMarker { pub fn index_subtable_records_byte_range(&self) -> Range { let start = 0; start..start + self.index_subtable_records_byte_len } } impl MinByteRange for IndexSubtableListMarker { fn min_byte_range(&self) -> Range { 0..self.index_subtable_records_byte_range().end } } impl ReadArgs for IndexSubtableList<'_> { type Args = u32; } impl<'a> FontReadWithArgs<'a> for IndexSubtableList<'a> { fn read_with_args(data: FontData<'a>, args: &u32) -> Result { let number_of_index_subtables = *args; let mut cursor = data.cursor(); let index_subtable_records_byte_len = (number_of_index_subtables as usize) .checked_mul(IndexSubtableRecord::RAW_BYTE_LEN) .ok_or(ReadError::OutOfBounds)?; cursor.advance_by(index_subtable_records_byte_len); cursor.finish(IndexSubtableListMarker { index_subtable_records_byte_len, }) } } impl<'a> IndexSubtableList<'a> { /// A constructor that requires additional arguments. /// /// This type requires some external state in order to be /// parsed. pub fn read(data: FontData<'a>, number_of_index_subtables: u32) -> Result { let args = number_of_index_subtables; Self::read_with_args(data, &args) } } /// [IndexSubtableList](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablelist) table. pub type IndexSubtableList<'a> = TableRef<'a, IndexSubtableListMarker>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtableList<'a> { /// Array of IndexSubtableRecords. pub fn index_subtable_records(&self) -> &'a [IndexSubtableRecord] { let range = self.shape.index_subtable_records_byte_range(); self.data.read_array(range).unwrap() } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for IndexSubtableList<'a> { fn type_name(&self) -> &str { "IndexSubtableList" } fn get_field(&self, idx: usize) -> Option> { match idx { 0usize => Some(Field::new( "index_subtable_records", traversal::FieldType::array_of_records( stringify!(IndexSubtableRecord), self.index_subtable_records(), self.offset_data(), ), )), _ => None, } } } #[cfg(feature = "experimental_traverse")] #[allow(clippy::needless_lifetimes)] impl<'a> std::fmt::Debug for IndexSubtableList<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { (self as &dyn SomeTable<'a>).fmt(f) } } #[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)] #[repr(C)] #[repr(packed)] pub struct IndexSubtableRecord { /// First glyph ID of this range. pub first_glyph_index: BigEndian, /// Last glyph ID of this range (inclusive). pub last_glyph_index: BigEndian, /// Offset to an IndexSubtable from the start of the IndexSubtableList. pub index_subtable_offset: BigEndian, } impl IndexSubtableRecord { /// First glyph ID of this range. pub fn first_glyph_index(&self) -> GlyphId16 { self.first_glyph_index.get() } /// Last glyph ID of this range (inclusive). pub fn last_glyph_index(&self) -> GlyphId16 { self.last_glyph_index.get() } /// Offset to an IndexSubtable from the start of the IndexSubtableList. pub fn index_subtable_offset(&self) -> Offset32 { self.index_subtable_offset.get() } /// Offset to an IndexSubtable from the start of the IndexSubtableList. /// /// The `data` argument should be retrieved from the parent table /// By calling its `offset_data` method. pub fn index_subtable<'a>(&self, data: FontData<'a>) -> Result, ReadError> { let args = (self.last_glyph_index(), self.first_glyph_index()); self.index_subtable_offset().resolve_with_args(data, &args) } } impl FixedSize for IndexSubtableRecord { const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN; } #[cfg(feature = "experimental_traverse")] impl<'a> SomeRecord<'a> for IndexSubtableRecord { fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { RecordResolver { name: "IndexSubtableRecord", get_field: Box::new(move |idx, _data| match idx { 0usize => Some(Field::new("first_glyph_index", self.first_glyph_index())), 1usize => Some(Field::new("last_glyph_index", self.last_glyph_index())), 2usize => Some(Field::new( "index_subtable_offset", FieldType::offset(self.index_subtable_offset(), self.index_subtable(_data)), )), _ => None, }), data, } } } impl Format for IndexSubtable1Marker { const FORMAT: u16 = 1; } /// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets. #[derive(Debug, Clone, Copy)] #[doc(hidden)] pub struct IndexSubtable1Marker { sbit_offsets_byte_len: usize, } impl IndexSubtable1Marker { pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN } pub fn image_format_byte_range(&self) -> Range { let start = self.index_format_byte_range().end; start..start + u16::RAW_BYTE_LEN } pub fn image_data_offset_byte_range(&self) -> Range { let start = self.image_format_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn sbit_offsets_byte_range(&self) -> Range { let start = self.image_data_offset_byte_range().end; start..start + self.sbit_offsets_byte_len } } impl MinByteRange for IndexSubtable1Marker { fn min_byte_range(&self) -> Range { 0..self.sbit_offsets_byte_range().end } } impl ReadArgs for IndexSubtable1<'_> { type Args = (GlyphId16, GlyphId16); } impl<'a> FontReadWithArgs<'a> for IndexSubtable1<'a> { fn read_with_args( data: FontData<'a>, args: &(GlyphId16, GlyphId16), ) -> Result { let (last_glyph_index, first_glyph_index) = *args; let mut cursor = data.cursor(); cursor.advance::(); cursor.advance::(); cursor.advance::(); let sbit_offsets_byte_len = (transforms::subtract_add_two(last_glyph_index, first_glyph_index)) .checked_mul(u32::RAW_BYTE_LEN) .ok_or(ReadError::OutOfBounds)?; cursor.advance_by(sbit_offsets_byte_len); cursor.finish(IndexSubtable1Marker { sbit_offsets_byte_len, }) } } impl<'a> IndexSubtable1<'a> { /// A constructor that requires additional arguments. /// /// This type requires some external state in order to be /// parsed. pub fn read( data: FontData<'a>, last_glyph_index: GlyphId16, first_glyph_index: GlyphId16, ) -> Result { let args = (last_glyph_index, first_glyph_index); Self::read_with_args(data, &args) } } /// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets. pub type IndexSubtable1<'a> = TableRef<'a, IndexSubtable1Marker>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtable1<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { let range = self.shape.index_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { let range = self.shape.image_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { let range = self.shape.image_data_offset_byte_range(); self.data.read_at(range.start).unwrap() } pub fn sbit_offsets(&self) -> &'a [BigEndian] { let range = self.shape.sbit_offsets_byte_range(); self.data.read_array(range).unwrap() } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for IndexSubtable1<'a> { fn type_name(&self) -> &str { "IndexSubtable1" } fn get_field(&self, idx: usize) -> Option> { match idx { 0usize => Some(Field::new("index_format", self.index_format())), 1usize => Some(Field::new("image_format", self.image_format())), 2usize => Some(Field::new("image_data_offset", self.image_data_offset())), 3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())), _ => None, } } } #[cfg(feature = "experimental_traverse")] #[allow(clippy::needless_lifetimes)] impl<'a> std::fmt::Debug for IndexSubtable1<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { (self as &dyn SomeTable<'a>).fmt(f) } } impl Format for IndexSubtable2Marker { const FORMAT: u16 = 2; } /// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics. #[derive(Debug, Clone, Copy)] #[doc(hidden)] pub struct IndexSubtable2Marker { big_metrics_byte_len: usize, } impl IndexSubtable2Marker { pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN } pub fn image_format_byte_range(&self) -> Range { let start = self.index_format_byte_range().end; start..start + u16::RAW_BYTE_LEN } pub fn image_data_offset_byte_range(&self) -> Range { let start = self.image_format_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn image_size_byte_range(&self) -> Range { let start = self.image_data_offset_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn big_metrics_byte_range(&self) -> Range { let start = self.image_size_byte_range().end; start..start + self.big_metrics_byte_len } } impl MinByteRange for IndexSubtable2Marker { fn min_byte_range(&self) -> Range { 0..self.big_metrics_byte_range().end } } impl<'a> FontRead<'a> for IndexSubtable2<'a> { fn read(data: FontData<'a>) -> Result { let mut cursor = data.cursor(); cursor.advance::(); cursor.advance::(); cursor.advance::(); cursor.advance::(); let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN; cursor.advance_by(big_metrics_byte_len); cursor.finish(IndexSubtable2Marker { big_metrics_byte_len, }) } } /// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics. pub type IndexSubtable2<'a> = TableRef<'a, IndexSubtable2Marker>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtable2<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { let range = self.shape.index_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { let range = self.shape.image_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { let range = self.shape.image_data_offset_byte_range(); self.data.read_at(range.start).unwrap() } /// All the glyphs are of the same size. pub fn image_size(&self) -> u32 { let range = self.shape.image_size_byte_range(); self.data.read_at(range.start).unwrap() } /// All glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned. pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] { let range = self.shape.big_metrics_byte_range(); self.data.read_array(range).unwrap() } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for IndexSubtable2<'a> { fn type_name(&self) -> &str { "IndexSubtable2" } fn get_field(&self, idx: usize) -> Option> { match idx { 0usize => Some(Field::new("index_format", self.index_format())), 1usize => Some(Field::new("image_format", self.image_format())), 2usize => Some(Field::new("image_data_offset", self.image_data_offset())), 3usize => Some(Field::new("image_size", self.image_size())), 4usize => Some(Field::new( "big_metrics", traversal::FieldType::array_of_records( stringify!(BigGlyphMetrics), self.big_metrics(), self.offset_data(), ), )), _ => None, } } } #[cfg(feature = "experimental_traverse")] #[allow(clippy::needless_lifetimes)] impl<'a> std::fmt::Debug for IndexSubtable2<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { (self as &dyn SomeTable<'a>).fmt(f) } } impl Format for IndexSubtable3Marker { const FORMAT: u16 = 3; } /// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets. #[derive(Debug, Clone, Copy)] #[doc(hidden)] pub struct IndexSubtable3Marker { sbit_offsets_byte_len: usize, } impl IndexSubtable3Marker { pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN } pub fn image_format_byte_range(&self) -> Range { let start = self.index_format_byte_range().end; start..start + u16::RAW_BYTE_LEN } pub fn image_data_offset_byte_range(&self) -> Range { let start = self.image_format_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn sbit_offsets_byte_range(&self) -> Range { let start = self.image_data_offset_byte_range().end; start..start + self.sbit_offsets_byte_len } } impl MinByteRange for IndexSubtable3Marker { fn min_byte_range(&self) -> Range { 0..self.sbit_offsets_byte_range().end } } impl ReadArgs for IndexSubtable3<'_> { type Args = (GlyphId16, GlyphId16); } impl<'a> FontReadWithArgs<'a> for IndexSubtable3<'a> { fn read_with_args( data: FontData<'a>, args: &(GlyphId16, GlyphId16), ) -> Result { let (last_glyph_index, first_glyph_index) = *args; let mut cursor = data.cursor(); cursor.advance::(); cursor.advance::(); cursor.advance::(); let sbit_offsets_byte_len = (transforms::subtract_add_two(last_glyph_index, first_glyph_index)) .checked_mul(u16::RAW_BYTE_LEN) .ok_or(ReadError::OutOfBounds)?; cursor.advance_by(sbit_offsets_byte_len); cursor.finish(IndexSubtable3Marker { sbit_offsets_byte_len, }) } } impl<'a> IndexSubtable3<'a> { /// A constructor that requires additional arguments. /// /// This type requires some external state in order to be /// parsed. pub fn read( data: FontData<'a>, last_glyph_index: GlyphId16, first_glyph_index: GlyphId16, ) -> Result { let args = (last_glyph_index, first_glyph_index); Self::read_with_args(data, &args) } } /// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets. pub type IndexSubtable3<'a> = TableRef<'a, IndexSubtable3Marker>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtable3<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { let range = self.shape.index_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { let range = self.shape.image_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { let range = self.shape.image_data_offset_byte_range(); self.data.read_at(range.start).unwrap() } pub fn sbit_offsets(&self) -> &'a [BigEndian] { let range = self.shape.sbit_offsets_byte_range(); self.data.read_array(range).unwrap() } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for IndexSubtable3<'a> { fn type_name(&self) -> &str { "IndexSubtable3" } fn get_field(&self, idx: usize) -> Option> { match idx { 0usize => Some(Field::new("index_format", self.index_format())), 1usize => Some(Field::new("image_format", self.image_format())), 2usize => Some(Field::new("image_data_offset", self.image_data_offset())), 3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())), _ => None, } } } #[cfg(feature = "experimental_traverse")] #[allow(clippy::needless_lifetimes)] impl<'a> std::fmt::Debug for IndexSubtable3<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { (self as &dyn SomeTable<'a>).fmt(f) } } impl Format for IndexSubtable4Marker { const FORMAT: u16 = 4; } /// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes. #[derive(Debug, Clone, Copy)] #[doc(hidden)] pub struct IndexSubtable4Marker { glyph_array_byte_len: usize, } impl IndexSubtable4Marker { pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN } pub fn image_format_byte_range(&self) -> Range { let start = self.index_format_byte_range().end; start..start + u16::RAW_BYTE_LEN } pub fn image_data_offset_byte_range(&self) -> Range { let start = self.image_format_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn num_glyphs_byte_range(&self) -> Range { let start = self.image_data_offset_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn glyph_array_byte_range(&self) -> Range { let start = self.num_glyphs_byte_range().end; start..start + self.glyph_array_byte_len } } impl MinByteRange for IndexSubtable4Marker { fn min_byte_range(&self) -> Range { 0..self.glyph_array_byte_range().end } } impl<'a> FontRead<'a> for IndexSubtable4<'a> { fn read(data: FontData<'a>) -> Result { let mut cursor = data.cursor(); cursor.advance::(); cursor.advance::(); cursor.advance::(); let num_glyphs: u32 = cursor.read()?; let glyph_array_byte_len = (transforms::add(num_glyphs, 1_usize)) .checked_mul(GlyphIdOffsetPair::RAW_BYTE_LEN) .ok_or(ReadError::OutOfBounds)?; cursor.advance_by(glyph_array_byte_len); cursor.finish(IndexSubtable4Marker { glyph_array_byte_len, }) } } /// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes. pub type IndexSubtable4<'a> = TableRef<'a, IndexSubtable4Marker>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtable4<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { let range = self.shape.index_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { let range = self.shape.image_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { let range = self.shape.image_data_offset_byte_range(); self.data.read_at(range.start).unwrap() } /// Array length. pub fn num_glyphs(&self) -> u32 { let range = self.shape.num_glyphs_byte_range(); self.data.read_at(range.start).unwrap() } /// One per glyph. pub fn glyph_array(&self) -> &'a [GlyphIdOffsetPair] { let range = self.shape.glyph_array_byte_range(); self.data.read_array(range).unwrap() } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for IndexSubtable4<'a> { fn type_name(&self) -> &str { "IndexSubtable4" } fn get_field(&self, idx: usize) -> Option> { match idx { 0usize => Some(Field::new("index_format", self.index_format())), 1usize => Some(Field::new("image_format", self.image_format())), 2usize => Some(Field::new("image_data_offset", self.image_data_offset())), 3usize => Some(Field::new("num_glyphs", self.num_glyphs())), 4usize => Some(Field::new( "glyph_array", traversal::FieldType::array_of_records( stringify!(GlyphIdOffsetPair), self.glyph_array(), self.offset_data(), ), )), _ => None, } } } #[cfg(feature = "experimental_traverse")] #[allow(clippy::needless_lifetimes)] impl<'a> std::fmt::Debug for IndexSubtable4<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { (self as &dyn SomeTable<'a>).fmt(f) } } /// [GlyphIdOffsetPair](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#glyphidoffsetpair-record) record. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] #[repr(C)] #[repr(packed)] pub struct GlyphIdOffsetPair { /// Glyph ID of glyph present. pub glyph_id: BigEndian, /// Location in EBDT. pub sbit_offset: BigEndian, } impl GlyphIdOffsetPair { /// Glyph ID of glyph present. pub fn glyph_id(&self) -> GlyphId16 { self.glyph_id.get() } /// Location in EBDT. pub fn sbit_offset(&self) -> u16 { self.sbit_offset.get() } } impl FixedSize for GlyphIdOffsetPair { const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN; } #[cfg(feature = "experimental_traverse")] impl<'a> SomeRecord<'a> for GlyphIdOffsetPair { fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { RecordResolver { name: "GlyphIdOffsetPair", get_field: Box::new(move |idx, _data| match idx { 0usize => Some(Field::new("glyph_id", self.glyph_id())), 1usize => Some(Field::new("sbit_offset", self.sbit_offset())), _ => None, }), data, } } } impl Format for IndexSubtable5Marker { const FORMAT: u16 = 5; } /// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes #[derive(Debug, Clone, Copy)] #[doc(hidden)] pub struct IndexSubtable5Marker { big_metrics_byte_len: usize, glyph_array_byte_len: usize, } impl IndexSubtable5Marker { pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN } pub fn image_format_byte_range(&self) -> Range { let start = self.index_format_byte_range().end; start..start + u16::RAW_BYTE_LEN } pub fn image_data_offset_byte_range(&self) -> Range { let start = self.image_format_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn image_size_byte_range(&self) -> Range { let start = self.image_data_offset_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn big_metrics_byte_range(&self) -> Range { let start = self.image_size_byte_range().end; start..start + self.big_metrics_byte_len } pub fn num_glyphs_byte_range(&self) -> Range { let start = self.big_metrics_byte_range().end; start..start + u32::RAW_BYTE_LEN } pub fn glyph_array_byte_range(&self) -> Range { let start = self.num_glyphs_byte_range().end; start..start + self.glyph_array_byte_len } } impl MinByteRange for IndexSubtable5Marker { fn min_byte_range(&self) -> Range { 0..self.glyph_array_byte_range().end } } impl<'a> FontRead<'a> for IndexSubtable5<'a> { fn read(data: FontData<'a>) -> Result { let mut cursor = data.cursor(); cursor.advance::(); cursor.advance::(); cursor.advance::(); cursor.advance::(); let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN; cursor.advance_by(big_metrics_byte_len); let num_glyphs: u32 = cursor.read()?; let glyph_array_byte_len = (num_glyphs as usize) .checked_mul(GlyphId16::RAW_BYTE_LEN) .ok_or(ReadError::OutOfBounds)?; cursor.advance_by(glyph_array_byte_len); cursor.finish(IndexSubtable5Marker { big_metrics_byte_len, glyph_array_byte_len, }) } } /// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes pub type IndexSubtable5<'a> = TableRef<'a, IndexSubtable5Marker>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtable5<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { let range = self.shape.index_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { let range = self.shape.image_format_byte_range(); self.data.read_at(range.start).unwrap() } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { let range = self.shape.image_data_offset_byte_range(); self.data.read_at(range.start).unwrap() } /// All glyphs have the same data size. pub fn image_size(&self) -> u32 { let range = self.shape.image_size_byte_range(); self.data.read_at(range.start).unwrap() } /// All glyphs have the same metrics. pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] { let range = self.shape.big_metrics_byte_range(); self.data.read_array(range).unwrap() } /// Array length. pub fn num_glyphs(&self) -> u32 { let range = self.shape.num_glyphs_byte_range(); self.data.read_at(range.start).unwrap() } /// One per glyph, sorted by glyhph ID. pub fn glyph_array(&self) -> &'a [BigEndian] { let range = self.shape.glyph_array_byte_range(); self.data.read_array(range).unwrap() } } #[cfg(feature = "experimental_traverse")] impl<'a> SomeTable<'a> for IndexSubtable5<'a> { fn type_name(&self) -> &str { "IndexSubtable5" } fn get_field(&self, idx: usize) -> Option> { match idx { 0usize => Some(Field::new("index_format", self.index_format())), 1usize => Some(Field::new("image_format", self.image_format())), 2usize => Some(Field::new("image_data_offset", self.image_data_offset())), 3usize => Some(Field::new("image_size", self.image_size())), 4usize => Some(Field::new( "big_metrics", traversal::FieldType::array_of_records( stringify!(BigGlyphMetrics), self.big_metrics(), self.offset_data(), ), )), 5usize => Some(Field::new("num_glyphs", self.num_glyphs())), 6usize => Some(Field::new("glyph_array", self.glyph_array())), _ => None, } } } #[cfg(feature = "experimental_traverse")] #[allow(clippy::needless_lifetimes)] impl<'a> std::fmt::Debug for IndexSubtable5<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { (self as &dyn SomeTable<'a>).fmt(f) } } /// [EbdtComponent](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#ebdtcomponent-record) record. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] #[repr(C)] #[repr(packed)] pub struct BdtComponent { /// Component glyph ID. pub glyph_id: BigEndian, /// Position of component left. pub x_offset: BigEndian, /// Position of component top. pub y_offset: BigEndian, } impl BdtComponent { /// Component glyph ID. pub fn glyph_id(&self) -> GlyphId16 { self.glyph_id.get() } /// Position of component left. pub fn x_offset(&self) -> i8 { self.x_offset.get() } /// Position of component top. pub fn y_offset(&self) -> i8 { self.y_offset.get() } } impl FixedSize for BdtComponent { const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN; } #[cfg(feature = "experimental_traverse")] impl<'a> SomeRecord<'a> for BdtComponent { fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { RecordResolver { name: "BdtComponent", get_field: Box::new(move |idx, _data| match idx { 0usize => Some(Field::new("glyph_id", self.glyph_id())), 1usize => Some(Field::new("x_offset", self.x_offset())), 2usize => Some(Field::new("y_offset", self.y_offset())), _ => None, }), data, } } }