Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

378
vendor/read-fonts/generated/font.rs vendored Normal file
View File

@@ -0,0 +1,378 @@
// 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::*;
/// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct TableDirectoryMarker {
table_records_byte_len: usize,
}
impl TableDirectoryMarker {
pub fn sfnt_version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn num_tables_byte_range(&self) -> Range<usize> {
let start = self.sfnt_version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn search_range_byte_range(&self) -> Range<usize> {
let start = self.num_tables_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 table_records_byte_range(&self) -> Range<usize> {
let start = self.range_shift_byte_range().end;
start..start + self.table_records_byte_len
}
}
impl MinByteRange for TableDirectoryMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.table_records_byte_range().end
}
}
impl<'a> FontRead<'a> for TableDirectory<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
let num_tables: u16 = cursor.read()?;
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let table_records_byte_len = (num_tables as usize)
.checked_mul(TableRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(table_records_byte_len);
cursor.finish(TableDirectoryMarker {
table_records_byte_len,
})
}
}
/// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory)
pub type TableDirectory<'a> = TableRef<'a, TableDirectoryMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> TableDirectory<'a> {
/// 0x00010000 or 0x4F54544F
pub fn sfnt_version(&self) -> u32 {
let range = self.shape.sfnt_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of tables.
pub fn num_tables(&self) -> u16 {
let range = self.shape.num_tables_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn search_range(&self) -> u16 {
let range = self.shape.search_range_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn entry_selector(&self) -> u16 {
let range = self.shape.entry_selector_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn range_shift(&self) -> u16 {
let range = self.shape.range_shift_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Table records array—one for each top-level table in the font
pub fn table_records(&self) -> &'a [TableRecord] {
let range = self.shape.table_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for TableDirectory<'a> {
fn type_name(&self) -> &str {
"TableDirectory"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("sfnt_version", self.sfnt_version())),
1usize => Some(Field::new("num_tables", self.num_tables())),
2usize => Some(Field::new("search_range", self.search_range())),
3usize => Some(Field::new("entry_selector", self.entry_selector())),
4usize => Some(Field::new("range_shift", self.range_shift())),
5usize => Some(Field::new(
"table_records",
traversal::FieldType::array_of_records(
stringify!(TableRecord),
self.table_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for TableDirectory<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Record for a table in a font.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct TableRecord {
/// Table identifier.
pub tag: BigEndian<Tag>,
/// Checksum for the table.
pub checksum: BigEndian<u32>,
/// Offset from the beginning of the font data.
pub offset: BigEndian<u32>,
/// Length of the table.
pub length: BigEndian<u32>,
}
impl TableRecord {
/// Table identifier.
pub fn tag(&self) -> Tag {
self.tag.get()
}
/// Checksum for the table.
pub fn checksum(&self) -> u32 {
self.checksum.get()
}
/// Offset from the beginning of the font data.
pub fn offset(&self) -> u32 {
self.offset.get()
}
/// Length of the table.
pub fn length(&self) -> u32 {
self.length.get()
}
}
impl FixedSize for TableRecord {
const RAW_BYTE_LEN: usize =
Tag::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for TableRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "TableRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("tag", self.tag())),
1usize => Some(Field::new("checksum", self.checksum())),
2usize => Some(Field::new("offset", self.offset())),
3usize => Some(Field::new("length", self.length())),
_ => None,
}),
data,
}
}
}
/// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct TTCHeaderMarker {
table_directory_offsets_byte_len: usize,
dsig_tag_byte_start: Option<usize>,
dsig_length_byte_start: Option<usize>,
dsig_offset_byte_start: Option<usize>,
}
impl TTCHeaderMarker {
pub fn ttc_tag_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + Tag::RAW_BYTE_LEN
}
pub fn version_byte_range(&self) -> Range<usize> {
let start = self.ttc_tag_byte_range().end;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn num_fonts_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn table_directory_offsets_byte_range(&self) -> Range<usize> {
let start = self.num_fonts_byte_range().end;
start..start + self.table_directory_offsets_byte_len
}
pub fn dsig_tag_byte_range(&self) -> Option<Range<usize>> {
let start = self.dsig_tag_byte_start?;
Some(start..start + u32::RAW_BYTE_LEN)
}
pub fn dsig_length_byte_range(&self) -> Option<Range<usize>> {
let start = self.dsig_length_byte_start?;
Some(start..start + u32::RAW_BYTE_LEN)
}
pub fn dsig_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.dsig_offset_byte_start?;
Some(start..start + u32::RAW_BYTE_LEN)
}
}
impl MinByteRange for TTCHeaderMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.table_directory_offsets_byte_range().end
}
}
impl<'a> FontRead<'a> for TTCHeader<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<Tag>();
let version: MajorMinor = cursor.read()?;
let num_fonts: u32 = cursor.read()?;
let table_directory_offsets_byte_len = (num_fonts as usize)
.checked_mul(u32::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(table_directory_offsets_byte_len);
let dsig_tag_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((2u16, 0u16))
.then(|| cursor.advance::<u32>());
let dsig_length_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((2u16, 0u16))
.then(|| cursor.advance::<u32>());
let dsig_offset_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((2u16, 0u16))
.then(|| cursor.advance::<u32>());
cursor.finish(TTCHeaderMarker {
table_directory_offsets_byte_len,
dsig_tag_byte_start,
dsig_length_byte_start,
dsig_offset_byte_start,
})
}
}
/// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header)
pub type TTCHeader<'a> = TableRef<'a, TTCHeaderMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> TTCHeader<'a> {
/// Font Collection ID string: \"ttcf\"
pub fn ttc_tag(&self) -> Tag {
let range = self.shape.ttc_tag_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Major/minor version of the TTC Header
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of fonts in TTC
pub fn num_fonts(&self) -> u32 {
let range = self.shape.num_fonts_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Array of offsets to the TableDirectory for each font from the beginning of the file
pub fn table_directory_offsets(&self) -> &'a [BigEndian<u32>] {
let range = self.shape.table_directory_offsets_byte_range();
self.data.read_array(range).unwrap()
}
/// Tag indicating that a DSIG table exists, 0x44534947 ('DSIG') (null if no signature)
pub fn dsig_tag(&self) -> Option<u32> {
let range = self.shape.dsig_tag_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// The length (in bytes) of the DSIG table (null if no signature)
pub fn dsig_length(&self) -> Option<u32> {
let range = self.shape.dsig_length_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// The offset (in bytes) of the DSIG table from the beginning of the TTC file (null if no signature)
pub fn dsig_offset(&self) -> Option<u32> {
let range = self.shape.dsig_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for TTCHeader<'a> {
fn type_name(&self) -> &str {
"TTCHeader"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("ttc_tag", self.ttc_tag())),
1usize => Some(Field::new("version", self.version())),
2usize => Some(Field::new("num_fonts", self.num_fonts())),
3usize => Some(Field::new(
"table_directory_offsets",
self.table_directory_offsets(),
)),
4usize if version.compatible((2u16, 0u16)) => {
Some(Field::new("dsig_tag", self.dsig_tag().unwrap()))
}
5usize if version.compatible((2u16, 0u16)) => {
Some(Field::new("dsig_length", self.dsig_length().unwrap()))
}
6usize if version.compatible((2u16, 0u16)) => {
Some(Field::new("dsig_offset", self.dsig_offset().unwrap()))
}
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for TTCHeader<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,245 @@
// 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::*;
/// The [anchor point](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct AnkrMarker {}
impl AnkrMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookup_table_offset_byte_range(&self) -> Range<usize> {
let start = self.flags_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn glyph_data_table_offset_byte_range(&self) -> Range<usize> {
let start = self.lookup_table_offset_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
}
impl MinByteRange for AnkrMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.glyph_data_table_offset_byte_range().end
}
}
impl TopLevelTable for Ankr<'_> {
/// `ankr`
const TAG: Tag = Tag::new(b"ankr");
}
impl<'a> FontRead<'a> for Ankr<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<Offset32>();
cursor.advance::<u32>();
cursor.finish(AnkrMarker {})
}
}
/// The [anchor point](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html) table.
pub type Ankr<'a> = TableRef<'a, AnkrMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Ankr<'a> {
/// Version number (set to zero).
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Flags (currently unused; set to zero).
pub fn flags(&self) -> u16 {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset to the table's lookup table; currently this is always `0x0000000C`.
///
/// Lookup values are two byte offsets into the glyph data table.
pub fn lookup_table_offset(&self) -> Offset32 {
let range = self.shape.lookup_table_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`lookup_table_offset`][Self::lookup_table_offset].
pub fn lookup_table(&self) -> Result<LookupU16<'a>, ReadError> {
let data = self.data;
self.lookup_table_offset().resolve(data)
}
/// Offset to the glyph data table.
pub fn glyph_data_table_offset(&self) -> u32 {
let range = self.shape.glyph_data_table_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Ankr<'a> {
fn type_name(&self) -> &str {
"Ankr"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("flags", self.flags())),
2usize => Some(Field::new(
"lookup_table_offset",
FieldType::offset(self.lookup_table_offset(), self.lookup_table()),
)),
3usize => Some(Field::new(
"glyph_data_table_offset",
self.glyph_data_table_offset(),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Ankr<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct GlyphDataEntryMarker {
anchor_points_byte_len: usize,
}
impl GlyphDataEntryMarker {
pub fn num_points_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn anchor_points_byte_range(&self) -> Range<usize> {
let start = self.num_points_byte_range().end;
start..start + self.anchor_points_byte_len
}
}
impl MinByteRange for GlyphDataEntryMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.anchor_points_byte_range().end
}
}
impl<'a> FontRead<'a> for GlyphDataEntry<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let num_points: u32 = cursor.read()?;
let anchor_points_byte_len = (num_points as usize)
.checked_mul(AnchorPoint::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(anchor_points_byte_len);
cursor.finish(GlyphDataEntryMarker {
anchor_points_byte_len,
})
}
}
pub type GlyphDataEntry<'a> = TableRef<'a, GlyphDataEntryMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> GlyphDataEntry<'a> {
/// Number of anchor points for this glyph.
pub fn num_points(&self) -> u32 {
let range = self.shape.num_points_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Individual anchor points.
pub fn anchor_points(&self) -> &'a [AnchorPoint] {
let range = self.shape.anchor_points_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for GlyphDataEntry<'a> {
fn type_name(&self) -> &str {
"GlyphDataEntry"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("num_points", self.num_points())),
1usize => Some(Field::new(
"anchor_points",
traversal::FieldType::array_of_records(
stringify!(AnchorPoint),
self.anchor_points(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for GlyphDataEntry<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Individual anchor point.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct AnchorPoint {
pub x: BigEndian<i16>,
pub y: BigEndian<i16>,
}
impl AnchorPoint {
pub fn x(&self) -> i16 {
self.x.get()
}
pub fn y(&self) -> i16 {
self.y.get()
}
}
impl FixedSize for AnchorPoint {
const RAW_BYTE_LEN: usize = i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for AnchorPoint {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "AnchorPoint",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("x", self.x())),
1usize => Some(Field::new("y", self.y())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,264 @@
// 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::*;
/// The [avar (Axis Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/avar) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct AvarMarker {
axis_segment_maps_byte_len: usize,
axis_index_map_offset_byte_start: Option<usize>,
var_store_offset_byte_start: Option<usize>,
}
impl AvarMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn _reserved_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn axis_count_byte_range(&self) -> Range<usize> {
let start = self._reserved_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn axis_segment_maps_byte_range(&self) -> Range<usize> {
let start = self.axis_count_byte_range().end;
start..start + self.axis_segment_maps_byte_len
}
pub fn axis_index_map_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.axis_index_map_offset_byte_start?;
Some(start..start + Offset32::RAW_BYTE_LEN)
}
pub fn var_store_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.var_store_offset_byte_start?;
Some(start..start + Offset32::RAW_BYTE_LEN)
}
}
impl MinByteRange for AvarMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.axis_segment_maps_byte_range().end
}
}
impl TopLevelTable for Avar<'_> {
/// `avar`
const TAG: Tag = Tag::new(b"avar");
}
impl<'a> FontRead<'a> for Avar<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: MajorMinor = cursor.read()?;
cursor.advance::<u16>();
let axis_count: u16 = cursor.read()?;
let axis_segment_maps_byte_len = {
let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?;
<SegmentMaps as VarSize>::total_len_for_count(data, axis_count as usize)?
};
cursor.advance_by(axis_segment_maps_byte_len);
let axis_index_map_offset_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((2u16, 0u16))
.then(|| cursor.advance::<Offset32>());
let var_store_offset_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((2u16, 0u16))
.then(|| cursor.advance::<Offset32>());
cursor.finish(AvarMarker {
axis_segment_maps_byte_len,
axis_index_map_offset_byte_start,
var_store_offset_byte_start,
})
}
}
/// The [avar (Axis Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/avar) table
pub type Avar<'a> = TableRef<'a, AvarMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Avar<'a> {
/// Major version number of the axis variations table — set to 1 or 2.
/// Minor version number of the axis variations table — set to 0.
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of variation axes for this font. This must be the same number as axisCount in the 'fvar' table.
pub fn axis_count(&self) -> u16 {
let range = self.shape.axis_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The segment maps array — one segment map for each axis, in the order of axes specified in the 'fvar' table.
pub fn axis_segment_maps(&self) -> VarLenArray<'a, SegmentMaps<'a>> {
let range = self.shape.axis_segment_maps_byte_range();
VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
}
/// Offset to DeltaSetIndexMap table (may be NULL).
pub fn axis_index_map_offset(&self) -> Option<Nullable<Offset32>> {
let range = self.shape.axis_index_map_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`axis_index_map_offset`][Self::axis_index_map_offset].
pub fn axis_index_map(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.axis_index_map_offset().map(|x| x.resolve(data))?
}
/// Offset to ItemVariationStore (may be NULL).
pub fn var_store_offset(&self) -> Option<Nullable<Offset32>> {
let range = self.shape.var_store_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`var_store_offset`][Self::var_store_offset].
pub fn var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
let data = self.data;
self.var_store_offset().map(|x| x.resolve(data))?
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Avar<'a> {
fn type_name(&self) -> &str {
"Avar"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("axis_count", self.axis_count())),
2usize => Some(Field::new(
"axis_segment_maps",
traversal::FieldType::var_array(
"SegmentMaps",
self.axis_segment_maps(),
self.offset_data(),
),
)),
3usize if version.compatible((2u16, 0u16)) => Some(Field::new(
"axis_index_map_offset",
FieldType::offset(self.axis_index_map_offset().unwrap(), self.axis_index_map()),
)),
4usize if version.compatible((2u16, 0u16)) => Some(Field::new(
"var_store_offset",
FieldType::offset(self.var_store_offset().unwrap(), self.var_store()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Avar<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// [SegmentMaps](https://learn.microsoft.com/en-us/typography/opentype/spec/avar#table-formats) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SegmentMaps<'a> {
/// The number of correspondence pairs for this axis.
pub position_map_count: BigEndian<u16>,
/// The array of axis value map records for this axis.
pub axis_value_maps: &'a [AxisValueMap],
}
impl<'a> SegmentMaps<'a> {
/// The number of correspondence pairs for this axis.
pub fn position_map_count(&self) -> u16 {
self.position_map_count.get()
}
/// The array of axis value map records for this axis.
pub fn axis_value_maps(&self) -> &'a [AxisValueMap] {
self.axis_value_maps
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for SegmentMaps<'a> {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "SegmentMaps",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("position_map_count", self.position_map_count())),
1usize => Some(Field::new(
"axis_value_maps",
traversal::FieldType::array_of_records(
stringify!(AxisValueMap),
self.axis_value_maps(),
_data,
),
)),
_ => None,
}),
data,
}
}
}
/// [AxisValueMap](https://learn.microsoft.com/en-us/typography/opentype/spec/avar#table-formats) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct AxisValueMap {
/// A normalized coordinate value obtained using default normalization.
pub from_coordinate: BigEndian<F2Dot14>,
/// The modified, normalized coordinate value.
pub to_coordinate: BigEndian<F2Dot14>,
}
impl AxisValueMap {
/// A normalized coordinate value obtained using default normalization.
pub fn from_coordinate(&self) -> F2Dot14 {
self.from_coordinate.get()
}
/// The modified, normalized coordinate value.
pub fn to_coordinate(&self) -> F2Dot14 {
self.to_coordinate.get()
}
}
impl FixedSize for AxisValueMap {
const RAW_BYTE_LEN: usize = F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for AxisValueMap {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "AxisValueMap",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("from_coordinate", self.from_coordinate())),
1usize => Some(Field::new("to_coordinate", self.to_coordinate())),
_ => None,
}),
data,
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
// 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::*;
/// The [Color Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CbdtMarker {}
impl CbdtMarker {
pub fn major_version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn minor_version_byte_range(&self) -> Range<usize> {
let start = self.major_version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for CbdtMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.minor_version_byte_range().end
}
}
impl TopLevelTable for Cbdt<'_> {
/// `CBDT`
const TAG: Tag = Tag::new(b"CBDT");
}
impl<'a> FontRead<'a> for Cbdt<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.finish(CbdtMarker {})
}
}
/// The [Color Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt) table
pub type Cbdt<'a> = TableRef<'a, CbdtMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cbdt<'a> {
/// Major version of the CBDT table, = 3.
pub fn major_version(&self) -> u16 {
let range = self.shape.major_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minor version of CBDT table, = 0.
pub fn minor_version(&self) -> u16 {
let range = self.shape.minor_version_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cbdt<'a> {
fn type_name(&self) -> &str {
"Cbdt"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("major_version", self.major_version())),
1usize => Some(Field::new("minor_version", self.minor_version())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cbdt<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,123 @@
// 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::*;
/// The [Color Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/cblc) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CblcMarker {
bitmap_sizes_byte_len: usize,
}
impl CblcMarker {
pub fn major_version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn minor_version_byte_range(&self) -> Range<usize> {
let start = self.major_version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_sizes_byte_range(&self) -> Range<usize> {
let start = self.minor_version_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn bitmap_sizes_byte_range(&self) -> Range<usize> {
let start = self.num_sizes_byte_range().end;
start..start + self.bitmap_sizes_byte_len
}
}
impl MinByteRange for CblcMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.bitmap_sizes_byte_range().end
}
}
impl TopLevelTable for Cblc<'_> {
/// `CBLC`
const TAG: Tag = Tag::new(b"CBLC");
}
impl<'a> FontRead<'a> for Cblc<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
let num_sizes: u32 = cursor.read()?;
let bitmap_sizes_byte_len = (num_sizes as usize)
.checked_mul(BitmapSize::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(bitmap_sizes_byte_len);
cursor.finish(CblcMarker {
bitmap_sizes_byte_len,
})
}
}
/// The [Color Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/cblc) table
pub type Cblc<'a> = TableRef<'a, CblcMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cblc<'a> {
/// Major version of the CBLC table, = 3.
pub fn major_version(&self) -> u16 {
let range = self.shape.major_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minor version of CBLC table, = 0.
pub fn minor_version(&self) -> u16 {
let range = self.shape.minor_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of BitmapSize records.
pub fn num_sizes(&self) -> u32 {
let range = self.shape.num_sizes_byte_range();
self.data.read_at(range.start).unwrap()
}
/// BitmapSize records array.
pub fn bitmap_sizes(&self) -> &'a [BitmapSize] {
let range = self.shape.bitmap_sizes_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cblc<'a> {
fn type_name(&self) -> &str {
"Cblc"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("major_version", self.major_version())),
1usize => Some(Field::new("minor_version", self.minor_version())),
2usize => Some(Field::new("num_sizes", self.num_sizes())),
3usize => Some(Field::new(
"bitmap_sizes",
traversal::FieldType::array_of_records(
stringify!(BitmapSize),
self.bitmap_sizes(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cblc<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,140 @@
// 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::*;
/// [Compact Font Format](https://learn.microsoft.com/en-us/typography/opentype/spec/cff) table header
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CffHeaderMarker {
_padding_byte_len: usize,
trailing_data_byte_len: usize,
}
impl CffHeaderMarker {
pub fn major_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u8::RAW_BYTE_LEN
}
pub fn minor_byte_range(&self) -> Range<usize> {
let start = self.major_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn hdr_size_byte_range(&self) -> Range<usize> {
let start = self.minor_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn off_size_byte_range(&self) -> Range<usize> {
let start = self.hdr_size_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn _padding_byte_range(&self) -> Range<usize> {
let start = self.off_size_byte_range().end;
start..start + self._padding_byte_len
}
pub fn trailing_data_byte_range(&self) -> Range<usize> {
let start = self._padding_byte_range().end;
start..start + self.trailing_data_byte_len
}
}
impl MinByteRange for CffHeaderMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.trailing_data_byte_range().end
}
}
impl<'a> FontRead<'a> for CffHeader<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u8>();
cursor.advance::<u8>();
let hdr_size: u8 = cursor.read()?;
cursor.advance::<u8>();
let _padding_byte_len = (transforms::subtract(hdr_size, 4_usize))
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(_padding_byte_len);
let trailing_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(trailing_data_byte_len);
cursor.finish(CffHeaderMarker {
_padding_byte_len,
trailing_data_byte_len,
})
}
}
/// [Compact Font Format](https://learn.microsoft.com/en-us/typography/opentype/spec/cff) table header
pub type CffHeader<'a> = TableRef<'a, CffHeaderMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> CffHeader<'a> {
/// Format major version (starting at 1).
pub fn major(&self) -> u8 {
let range = self.shape.major_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Format minor version (starting at 0).
pub fn minor(&self) -> u8 {
let range = self.shape.minor_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Header size (bytes).
pub fn hdr_size(&self) -> u8 {
let range = self.shape.hdr_size_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Absolute offset size.
pub fn off_size(&self) -> u8 {
let range = self.shape.off_size_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Padding bytes before the start of the Name INDEX.
pub fn _padding(&self) -> &'a [u8] {
let range = self.shape._padding_byte_range();
self.data.read_array(range).unwrap()
}
/// Remaining table data.
pub fn trailing_data(&self) -> &'a [u8] {
let range = self.shape.trailing_data_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for CffHeader<'a> {
fn type_name(&self) -> &str {
"CffHeader"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("major", self.major())),
1usize => Some(Field::new("minor", self.minor())),
2usize => Some(Field::new("hdr_size", self.hdr_size())),
3usize => Some(Field::new("off_size", self.off_size())),
4usize => Some(Field::new("_padding", self._padding())),
5usize => Some(Field::new("trailing_data", self.trailing_data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for CffHeader<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,158 @@
// 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::*;
/// [Compact Font Format (CFF) version 2](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) table header
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cff2HeaderMarker {
_padding_byte_len: usize,
top_dict_data_byte_len: usize,
trailing_data_byte_len: usize,
}
impl Cff2HeaderMarker {
pub fn major_version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u8::RAW_BYTE_LEN
}
pub fn minor_version_byte_range(&self) -> Range<usize> {
let start = self.major_version_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn header_size_byte_range(&self) -> Range<usize> {
let start = self.minor_version_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn top_dict_length_byte_range(&self) -> Range<usize> {
let start = self.header_size_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn _padding_byte_range(&self) -> Range<usize> {
let start = self.top_dict_length_byte_range().end;
start..start + self._padding_byte_len
}
pub fn top_dict_data_byte_range(&self) -> Range<usize> {
let start = self._padding_byte_range().end;
start..start + self.top_dict_data_byte_len
}
pub fn trailing_data_byte_range(&self) -> Range<usize> {
let start = self.top_dict_data_byte_range().end;
start..start + self.trailing_data_byte_len
}
}
impl MinByteRange for Cff2HeaderMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.trailing_data_byte_range().end
}
}
impl<'a> FontRead<'a> for Cff2Header<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u8>();
cursor.advance::<u8>();
let header_size: u8 = cursor.read()?;
let top_dict_length: u16 = cursor.read()?;
let _padding_byte_len = (transforms::subtract(header_size, 5_usize))
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(_padding_byte_len);
let top_dict_data_byte_len = (top_dict_length as usize)
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(top_dict_data_byte_len);
let trailing_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(trailing_data_byte_len);
cursor.finish(Cff2HeaderMarker {
_padding_byte_len,
top_dict_data_byte_len,
trailing_data_byte_len,
})
}
}
/// [Compact Font Format (CFF) version 2](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) table header
pub type Cff2Header<'a> = TableRef<'a, Cff2HeaderMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cff2Header<'a> {
/// Format major version (set to 2).
pub fn major_version(&self) -> u8 {
let range = self.shape.major_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Format minor version (set to 0).
pub fn minor_version(&self) -> u8 {
let range = self.shape.minor_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Header size (bytes).
pub fn header_size(&self) -> u8 {
let range = self.shape.header_size_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Length of Top DICT structure in bytes.
pub fn top_dict_length(&self) -> u16 {
let range = self.shape.top_dict_length_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Padding bytes before the start of the Top DICT.
pub fn _padding(&self) -> &'a [u8] {
let range = self.shape._padding_byte_range();
self.data.read_array(range).unwrap()
}
/// Data containing the Top DICT.
pub fn top_dict_data(&self) -> &'a [u8] {
let range = self.shape.top_dict_data_byte_range();
self.data.read_array(range).unwrap()
}
/// Remaining table data.
pub fn trailing_data(&self) -> &'a [u8] {
let range = self.shape.trailing_data_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cff2Header<'a> {
fn type_name(&self) -> &str {
"Cff2Header"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("major_version", self.major_version())),
1usize => Some(Field::new("minor_version", self.minor_version())),
2usize => Some(Field::new("header_size", self.header_size())),
3usize => Some(Field::new("top_dict_length", self.top_dict_length())),
4usize => Some(Field::new("_padding", self._padding())),
5usize => Some(Field::new("top_dict_data", self.top_dict_data())),
6usize => Some(Field::new("trailing_data", self.trailing_data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cff2Header<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,663 @@
// 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::*;
/// [CPAL (Color Palette Table)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-table-header) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CpalMarker {
color_record_indices_byte_len: usize,
palette_types_array_offset_byte_start: Option<usize>,
palette_labels_array_offset_byte_start: Option<usize>,
palette_entry_labels_array_offset_byte_start: Option<usize>,
}
impl CpalMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_palette_entries_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_palettes_byte_range(&self) -> Range<usize> {
let start = self.num_palette_entries_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_color_records_byte_range(&self) -> Range<usize> {
let start = self.num_palettes_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn color_records_array_offset_byte_range(&self) -> Range<usize> {
let start = self.num_color_records_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn color_record_indices_byte_range(&self) -> Range<usize> {
let start = self.color_records_array_offset_byte_range().end;
start..start + self.color_record_indices_byte_len
}
pub fn palette_types_array_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.palette_types_array_offset_byte_start?;
Some(start..start + Offset32::RAW_BYTE_LEN)
}
pub fn palette_labels_array_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.palette_labels_array_offset_byte_start?;
Some(start..start + Offset32::RAW_BYTE_LEN)
}
pub fn palette_entry_labels_array_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.palette_entry_labels_array_offset_byte_start?;
Some(start..start + Offset32::RAW_BYTE_LEN)
}
}
impl MinByteRange for CpalMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.color_record_indices_byte_range().end
}
}
impl TopLevelTable for Cpal<'_> {
/// `CPAL`
const TAG: Tag = Tag::new(b"CPAL");
}
impl<'a> FontRead<'a> for Cpal<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: u16 = cursor.read()?;
cursor.advance::<u16>();
let num_palettes: u16 = cursor.read()?;
cursor.advance::<u16>();
cursor.advance::<Offset32>();
let color_record_indices_byte_len = (num_palettes as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(color_record_indices_byte_len);
let palette_types_array_offset_byte_start = version
.compatible(1u16)
.then(|| cursor.position())
.transpose()?;
version
.compatible(1u16)
.then(|| cursor.advance::<Offset32>());
let palette_labels_array_offset_byte_start = version
.compatible(1u16)
.then(|| cursor.position())
.transpose()?;
version
.compatible(1u16)
.then(|| cursor.advance::<Offset32>());
let palette_entry_labels_array_offset_byte_start = version
.compatible(1u16)
.then(|| cursor.position())
.transpose()?;
version
.compatible(1u16)
.then(|| cursor.advance::<Offset32>());
cursor.finish(CpalMarker {
color_record_indices_byte_len,
palette_types_array_offset_byte_start,
palette_labels_array_offset_byte_start,
palette_entry_labels_array_offset_byte_start,
})
}
}
/// [CPAL (Color Palette Table)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-table-header) table
pub type Cpal<'a> = TableRef<'a, CpalMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cpal<'a> {
/// Table version number (=0).
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of palette entries in each palette.
pub fn num_palette_entries(&self) -> u16 {
let range = self.shape.num_palette_entries_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of palettes in the table.
pub fn num_palettes(&self) -> u16 {
let range = self.shape.num_palettes_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Total number of color records, combined for all palettes.
pub fn num_color_records(&self) -> u16 {
let range = self.shape.num_color_records_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from the beginning of CPAL table to the first
/// ColorRecord.
pub fn color_records_array_offset(&self) -> Nullable<Offset32> {
let range = self.shape.color_records_array_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`color_records_array_offset`][Self::color_records_array_offset].
pub fn color_records_array(&self) -> Option<Result<&'a [ColorRecord], ReadError>> {
let data = self.data;
let args = self.num_color_records();
self.color_records_array_offset()
.resolve_with_args(data, &args)
}
/// Index of each palettes first color record in the combined
/// color record array.
pub fn color_record_indices(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.color_record_indices_byte_range();
self.data.read_array(range).unwrap()
}
/// Offset from the beginning of CPAL table to the [Palette Types Array][].
///
/// This is an array of 32-bit flag fields that describe properties of each palette.
///
/// [Palette Types Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-type-array
pub fn palette_types_array_offset(&self) -> Option<Nullable<Offset32>> {
let range = self.shape.palette_types_array_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`palette_types_array_offset`][Self::palette_types_array_offset].
pub fn palette_types_array(&self) -> Option<Result<&'a [BigEndian<PaletteType>], ReadError>> {
let data = self.data;
let args = self.num_palettes();
self.palette_types_array_offset()
.map(|x| x.resolve_with_args(data, &args))?
}
/// Offset from the beginning of CPAL table to the [Palette Labels Array][].
///
/// This is an array of 'name' table IDs (typically in the font-specific name
/// ID range) that specify user interface strings associated with each palette.
/// Use 0xFFFF if no name ID is provided for a palette.
///
/// [Palette Labels Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-labels-array
pub fn palette_labels_array_offset(&self) -> Option<Nullable<Offset32>> {
let range = self.shape.palette_labels_array_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`palette_labels_array_offset`][Self::palette_labels_array_offset].
pub fn palette_labels_array(&self) -> Option<Result<&'a [BigEndian<u16>], ReadError>> {
let data = self.data;
let args = self.num_palettes();
self.palette_labels_array_offset()
.map(|x| x.resolve_with_args(data, &args))?
}
/// Offset from the beginning of CPAL table to the [Palette Entry Labels Array][].
///
/// This is an array of 'name' table IDs (typically in the font-specific name
/// ID range) that specify user interface strings associated with each palette
/// entry, e.g. “Outline”, “Fill”. This set of palette entry labels applies
/// to all palettes in the font. Use 0xFFFF if no name ID is provided for a
/// palette entry.
///
/// [Palette Entry Labels Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-entry-label-array
pub fn palette_entry_labels_array_offset(&self) -> Option<Nullable<Offset32>> {
let range = self.shape.palette_entry_labels_array_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`palette_entry_labels_array_offset`][Self::palette_entry_labels_array_offset].
pub fn palette_entry_labels_array(&self) -> Option<Result<&'a [BigEndian<NameId>], ReadError>> {
let data = self.data;
let args = self.num_palette_entries();
self.palette_entry_labels_array_offset()
.map(|x| x.resolve_with_args(data, &args))?
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cpal<'a> {
fn type_name(&self) -> &str {
"Cpal"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"num_palette_entries",
self.num_palette_entries(),
)),
2usize => Some(Field::new("num_palettes", self.num_palettes())),
3usize => Some(Field::new("num_color_records", self.num_color_records())),
4usize => Some(Field::new(
"color_records_array_offset",
traversal::FieldType::offset_to_array_of_records(
self.color_records_array_offset(),
self.color_records_array(),
stringify!(ColorRecord),
self.offset_data(),
),
)),
5usize => Some(Field::new(
"color_record_indices",
self.color_record_indices(),
)),
6usize if version.compatible(1u16) => Some(Field::new(
"palette_types_array_offset",
FieldType::offset_to_array_of_scalars(
self.palette_types_array_offset().unwrap(),
self.palette_types_array(),
),
)),
7usize if version.compatible(1u16) => Some(Field::new(
"palette_labels_array_offset",
FieldType::offset_to_array_of_scalars(
self.palette_labels_array_offset().unwrap(),
self.palette_labels_array(),
),
)),
8usize if version.compatible(1u16) => Some(Field::new(
"palette_entry_labels_array_offset",
FieldType::offset_to_array_of_scalars(
self.palette_entry_labels_array_offset().unwrap(),
self.palette_entry_labels_array(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cpal<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The [PaletteType](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-type-array) 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 PaletteType {
bits: u32,
}
impl PaletteType {
/// Bit 0: palette is appropriate to use when displaying the font on a light background such as white.
pub const USABLE_WITH_LIGHT_BACKGROUND: Self = Self { bits: 0x0001 };
/// Bit 1: palette is appropriate to use when displaying the font on a dark background such as black.
pub const USABLE_WITH_DARK_BACKGROUND: Self = Self { bits: 0x0002 };
}
impl PaletteType {
/// 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::USABLE_WITH_LIGHT_BACKGROUND.bits | Self::USABLE_WITH_DARK_BACKGROUND.bits,
}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub const fn bits(&self) -> u32 {
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: u32) -> Option<Self> {
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: u32) -> 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 PaletteType {
type Output = Self;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: PaletteType) -> Self {
Self {
bits: self.bits | other.bits,
}
}
}
impl std::ops::BitOrAssign for PaletteType {
/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}
impl std::ops::BitXor for PaletteType {
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 PaletteType {
/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}
impl std::ops::BitAnd for PaletteType {
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 PaletteType {
/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}
impl std::ops::Sub for PaletteType {
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 PaletteType {
/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}
impl std::ops::Not for PaletteType {
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 PaletteType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let members: &[(&str, Self)] = &[
(
"USABLE_WITH_LIGHT_BACKGROUND",
Self::USABLE_WITH_LIGHT_BACKGROUND,
),
(
"USABLE_WITH_DARK_BACKGROUND",
Self::USABLE_WITH_DARK_BACKGROUND,
),
];
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 PaletteType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Binary::fmt(&self.bits, f)
}
}
impl std::fmt::Octal for PaletteType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Octal::fmt(&self.bits, f)
}
}
impl std::fmt::LowerHex for PaletteType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::LowerHex::fmt(&self.bits, f)
}
}
impl std::fmt::UpperHex for PaletteType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::UpperHex::fmt(&self.bits, f)
}
}
impl font_types::Scalar for PaletteType {
type Raw = <u32 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.bits().to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u32>::from_raw(raw);
Self::from_bits_truncate(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<PaletteType> for FieldType<'a> {
fn from(src: PaletteType) -> FieldType<'a> {
src.bits().into()
}
}
/// [CPAL (Color Record)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-entries-and-color-records) record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ColorRecord {
/// Blue value (B0).
pub blue: u8,
/// Green value (B1).
pub green: u8,
/// Red value (B2).
pub red: u8,
/// Alpha value (B3).
pub alpha: u8,
}
impl ColorRecord {
/// Blue value (B0).
pub fn blue(&self) -> u8 {
self.blue
}
/// Green value (B1).
pub fn green(&self) -> u8 {
self.green
}
/// Red value (B2).
pub fn red(&self) -> u8 {
self.red
}
/// Alpha value (B3).
pub fn alpha(&self) -> u8 {
self.alpha
}
}
impl FixedSize for ColorRecord {
const RAW_BYTE_LEN: usize =
u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ColorRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ColorRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("blue", self.blue())),
1usize => Some(Field::new("green", self.green())),
2usize => Some(Field::new("red", self.red())),
3usize => Some(Field::new("alpha", self.alpha())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,129 @@
// 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::*;
/// The [cvar](https://learn.microsoft.com/en-us/typography/opentype/spec/cvar) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CvarMarker {
tuple_variation_headers_byte_len: usize,
}
impl CvarMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn tuple_variation_count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + TupleVariationCount::RAW_BYTE_LEN
}
pub fn data_offset_byte_range(&self) -> Range<usize> {
let start = self.tuple_variation_count_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn tuple_variation_headers_byte_range(&self) -> Range<usize> {
let start = self.data_offset_byte_range().end;
start..start + self.tuple_variation_headers_byte_len
}
}
impl MinByteRange for CvarMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.tuple_variation_headers_byte_range().end
}
}
impl TopLevelTable for Cvar<'_> {
/// `cvar`
const TAG: Tag = Tag::new(b"cvar");
}
impl<'a> FontRead<'a> for Cvar<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<TupleVariationCount>();
cursor.advance::<Offset16>();
let tuple_variation_headers_byte_len = cursor.remaining_bytes();
cursor.advance_by(tuple_variation_headers_byte_len);
cursor.finish(CvarMarker {
tuple_variation_headers_byte_len,
})
}
}
/// The [cvar](https://learn.microsoft.com/en-us/typography/opentype/spec/cvar) table.
pub type Cvar<'a> = TableRef<'a, CvarMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cvar<'a> {
/// Major/minor version number of the CVT variations table — set to (1,0).
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// A packed field. The high 4 bits are flags, and the low 12 bits
/// are the number of tuple variation tables for this glyph. The
/// number of tuple variation tables can be any number between 1
/// and 4095.
pub fn tuple_variation_count(&self) -> TupleVariationCount {
let range = self.shape.tuple_variation_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from the start of the 'cvar' table to the serialized data.
pub fn data_offset(&self) -> Offset16 {
let range = self.shape.data_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`data_offset`][Self::data_offset].
pub fn data(&self) -> Result<FontData<'a>, ReadError> {
let data = self.data;
self.data_offset().resolve(data)
}
/// Array of tuple variation headers.
pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader> {
let range = self.shape.tuple_variation_headers_byte_range();
VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cvar<'a> {
fn type_name(&self) -> &str {
"Cvar"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"tuple_variation_count",
traversal::FieldType::Unknown,
)),
2usize => Some(Field::new("data_offset", traversal::FieldType::Unknown)),
3usize => Some(Field::new(
"tuple_variation_headers",
traversal::FieldType::Unknown,
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cvar<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,83 @@
// 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::*;
/// The [Embedded Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct EbdtMarker {}
impl EbdtMarker {
pub fn major_version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn minor_version_byte_range(&self) -> Range<usize> {
let start = self.major_version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for EbdtMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.minor_version_byte_range().end
}
}
impl TopLevelTable for Ebdt<'_> {
/// `EBDT`
const TAG: Tag = Tag::new(b"EBDT");
}
impl<'a> FontRead<'a> for Ebdt<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.finish(EbdtMarker {})
}
}
/// The [Embedded Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt) table
pub type Ebdt<'a> = TableRef<'a, EbdtMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Ebdt<'a> {
/// Major version of the EBDT table, = 2.
pub fn major_version(&self) -> u16 {
let range = self.shape.major_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minor version of EBDT table, = 0.
pub fn minor_version(&self) -> u16 {
let range = self.shape.minor_version_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Ebdt<'a> {
fn type_name(&self) -> &str {
"Ebdt"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("major_version", self.major_version())),
1usize => Some(Field::new("minor_version", self.minor_version())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Ebdt<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,123 @@
// 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::*;
/// The [Embedded Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct EblcMarker {
bitmap_sizes_byte_len: usize,
}
impl EblcMarker {
pub fn major_version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn minor_version_byte_range(&self) -> Range<usize> {
let start = self.major_version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_sizes_byte_range(&self) -> Range<usize> {
let start = self.minor_version_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn bitmap_sizes_byte_range(&self) -> Range<usize> {
let start = self.num_sizes_byte_range().end;
start..start + self.bitmap_sizes_byte_len
}
}
impl MinByteRange for EblcMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.bitmap_sizes_byte_range().end
}
}
impl TopLevelTable for Eblc<'_> {
/// `EBLC`
const TAG: Tag = Tag::new(b"EBLC");
}
impl<'a> FontRead<'a> for Eblc<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
let num_sizes: u32 = cursor.read()?;
let bitmap_sizes_byte_len = (num_sizes as usize)
.checked_mul(BitmapSize::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(bitmap_sizes_byte_len);
cursor.finish(EblcMarker {
bitmap_sizes_byte_len,
})
}
}
/// The [Embedded Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc) table
pub type Eblc<'a> = TableRef<'a, EblcMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Eblc<'a> {
/// Major version of the EBLC table, = 2.
pub fn major_version(&self) -> u16 {
let range = self.shape.major_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minor version of EBLC table, = 0.
pub fn minor_version(&self) -> u16 {
let range = self.shape.minor_version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of BitmapSize records.
pub fn num_sizes(&self) -> u32 {
let range = self.shape.num_sizes_byte_range();
self.data.read_at(range.start).unwrap()
}
/// BitmapSize records array.
pub fn bitmap_sizes(&self) -> &'a [BitmapSize] {
let range = self.shape.bitmap_sizes_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Eblc<'a> {
fn type_name(&self) -> &str {
"Eblc"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("major_version", self.major_version())),
1usize => Some(Field::new("minor_version", self.minor_version())),
2usize => Some(Field::new("num_sizes", self.num_sizes())),
3usize => Some(Field::new(
"bitmap_sizes",
traversal::FieldType::array_of_records(
stringify!(BitmapSize),
self.bitmap_sizes(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Eblc<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,336 @@
// 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::*;
/// The [feature name](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct FeatMarker {
names_byte_len: usize,
}
impl FeatMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn feature_name_count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn _reserved1_byte_range(&self) -> Range<usize> {
let start = self.feature_name_count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn _reserved2_byte_range(&self) -> Range<usize> {
let start = self._reserved1_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn names_byte_range(&self) -> Range<usize> {
let start = self._reserved2_byte_range().end;
start..start + self.names_byte_len
}
}
impl MinByteRange for FeatMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.names_byte_range().end
}
}
impl TopLevelTable for Feat<'_> {
/// `feat`
const TAG: Tag = Tag::new(b"feat");
}
impl<'a> FontRead<'a> for Feat<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
let feature_name_count: u16 = cursor.read()?;
cursor.advance::<u16>();
cursor.advance::<u32>();
let names_byte_len = (feature_name_count as usize)
.checked_mul(FeatureName::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(names_byte_len);
cursor.finish(FeatMarker { names_byte_len })
}
}
/// The [feature name](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html) table.
pub type Feat<'a> = TableRef<'a, FeatMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Feat<'a> {
/// Version number of the feature name table (0x00010000 for the current
/// version).
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of entries in the feature name array.
pub fn feature_name_count(&self) -> u16 {
let range = self.shape.feature_name_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The feature name array, sorted by feature type.
pub fn names(&self) -> &'a [FeatureName] {
let range = self.shape.names_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Feat<'a> {
fn type_name(&self) -> &str {
"Feat"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("feature_name_count", self.feature_name_count())),
2usize => Some(Field::new(
"names",
traversal::FieldType::array_of_records(
stringify!(FeatureName),
self.names(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Feat<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Type, flags and names for a feature.
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct FeatureName {
/// Feature type.
pub feature: BigEndian<u16>,
/// The number of records in the setting name array.
pub n_settings: BigEndian<u16>,
/// Offset in bytes from the beginning of this table to this feature's
/// setting name array. The actual type of record this offset refers
/// to will depend on the exclusivity value, as described below.
pub setting_table_offset: BigEndian<Offset32>,
/// Flags associated with the feature type.
pub feature_flags: BigEndian<u16>,
/// The name table index for the feature's name.
pub name_index: BigEndian<NameId>,
}
impl FeatureName {
/// Feature type.
pub fn feature(&self) -> u16 {
self.feature.get()
}
/// The number of records in the setting name array.
pub fn n_settings(&self) -> u16 {
self.n_settings.get()
}
/// Offset in bytes from the beginning of this table to this feature's
/// setting name array. The actual type of record this offset refers
/// to will depend on the exclusivity value, as described below.
pub fn setting_table_offset(&self) -> Offset32 {
self.setting_table_offset.get()
}
/// Offset in bytes from the beginning of this table to this feature's
/// setting name array. The actual type of record this offset refers
/// to will depend on the exclusivity value, as described below.
///
/// The `data` argument should be retrieved from the parent table
/// By calling its `offset_data` method.
pub fn setting_table<'a>(&self, data: FontData<'a>) -> Result<SettingNameArray<'a>, ReadError> {
let args = self.n_settings();
self.setting_table_offset().resolve_with_args(data, &args)
}
/// Flags associated with the feature type.
pub fn feature_flags(&self) -> u16 {
self.feature_flags.get()
}
/// The name table index for the feature's name.
pub fn name_index(&self) -> NameId {
self.name_index.get()
}
}
impl FixedSize for FeatureName {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ Offset32::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ NameId::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for FeatureName {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "FeatureName",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("feature", self.feature())),
1usize => Some(Field::new("n_settings", self.n_settings())),
2usize => Some(Field::new(
"setting_table_offset",
FieldType::offset(self.setting_table_offset(), self.setting_table(_data)),
)),
3usize => Some(Field::new("feature_flags", self.feature_flags())),
4usize => Some(Field::new("name_index", self.name_index())),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SettingNameArrayMarker {
settings_byte_len: usize,
}
impl SettingNameArrayMarker {
pub fn settings_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + self.settings_byte_len
}
}
impl MinByteRange for SettingNameArrayMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.settings_byte_range().end
}
}
impl ReadArgs for SettingNameArray<'_> {
type Args = u16;
}
impl<'a> FontReadWithArgs<'a> for SettingNameArray<'a> {
fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
let n_settings = *args;
let mut cursor = data.cursor();
let settings_byte_len = (n_settings as usize)
.checked_mul(SettingName::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(settings_byte_len);
cursor.finish(SettingNameArrayMarker { settings_byte_len })
}
}
impl<'a> SettingNameArray<'a> {
/// A constructor that requires additional arguments.
///
/// This type requires some external state in order to be
/// parsed.
pub fn read(data: FontData<'a>, n_settings: u16) -> Result<Self, ReadError> {
let args = n_settings;
Self::read_with_args(data, &args)
}
}
pub type SettingNameArray<'a> = TableRef<'a, SettingNameArrayMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SettingNameArray<'a> {
/// List of setting names for a feature.
pub fn settings(&self) -> &'a [SettingName] {
let range = self.shape.settings_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SettingNameArray<'a> {
fn type_name(&self) -> &str {
"SettingNameArray"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"settings",
traversal::FieldType::array_of_records(
stringify!(SettingName),
self.settings(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SettingNameArray<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Associates a setting with a name identifier.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct SettingName {
/// The setting.
pub setting: BigEndian<u16>,
/// The name table index for the setting's name.
pub name_index: BigEndian<NameId>,
}
impl SettingName {
/// The setting.
pub fn setting(&self) -> u16 {
self.setting.get()
}
/// The name table index for the setting's name.
pub fn name_index(&self) -> NameId {
self.name_index.get()
}
}
impl FixedSize for SettingName {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for SettingName {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "SettingName",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("setting", self.setting())),
1usize => Some(Field::new("name_index", self.name_index())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,376 @@
// 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::*;
/// The [fvar (Font Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct FvarMarker {}
impl FvarMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn axis_instance_arrays_offset_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn _reserved_byte_range(&self) -> Range<usize> {
let start = self.axis_instance_arrays_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn axis_count_byte_range(&self) -> Range<usize> {
let start = self._reserved_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn axis_size_byte_range(&self) -> Range<usize> {
let start = self.axis_count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn instance_count_byte_range(&self) -> Range<usize> {
let start = self.axis_size_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn instance_size_byte_range(&self) -> Range<usize> {
let start = self.instance_count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for FvarMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.instance_size_byte_range().end
}
}
impl TopLevelTable for Fvar<'_> {
/// `fvar`
const TAG: Tag = Tag::new(b"fvar");
}
impl<'a> FontRead<'a> for Fvar<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<Offset16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.finish(FvarMarker {})
}
}
/// The [fvar (Font Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) table
pub type Fvar<'a> = TableRef<'a, FvarMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Fvar<'a> {
/// Major version number of the font variations table — set to 1.
/// Minor version number of the font variations table — set to 0.
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset in bytes from the beginning of the table to the start of the VariationAxisRecord array. The
/// InstanceRecord array directly follows.
pub fn axis_instance_arrays_offset(&self) -> Offset16 {
let range = self.shape.axis_instance_arrays_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`axis_instance_arrays_offset`][Self::axis_instance_arrays_offset].
pub fn axis_instance_arrays(&self) -> Result<AxisInstanceArrays<'a>, ReadError> {
let data = self.data;
let args = (
self.axis_count(),
self.instance_count(),
self.instance_size(),
);
self.axis_instance_arrays_offset()
.resolve_with_args(data, &args)
}
/// The number of variation axes in the font (the number of records in the axes array).
pub fn axis_count(&self) -> u16 {
let range = self.shape.axis_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The size in bytes of each VariationAxisRecord — set to 20 (0x0014) for this version.
pub fn axis_size(&self) -> u16 {
let range = self.shape.axis_size_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of named instances defined in the font (the number of records in the instances array).
pub fn instance_count(&self) -> u16 {
let range = self.shape.instance_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The size in bytes of each InstanceRecord — set to either axisCount * sizeof(Fixed) + 4, or to axisCount * sizeof(Fixed) + 6.
pub fn instance_size(&self) -> u16 {
let range = self.shape.instance_size_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Fvar<'a> {
fn type_name(&self) -> &str {
"Fvar"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"axis_instance_arrays_offset",
FieldType::offset(
self.axis_instance_arrays_offset(),
self.axis_instance_arrays(),
),
)),
2usize => Some(Field::new("axis_count", self.axis_count())),
3usize => Some(Field::new("axis_size", self.axis_size())),
4usize => Some(Field::new("instance_count", self.instance_count())),
5usize => Some(Field::new("instance_size", self.instance_size())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Fvar<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Shim table to handle combined axis and instance arrays.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct AxisInstanceArraysMarker {
axis_count: u16,
instance_size: u16,
axes_byte_len: usize,
instances_byte_len: usize,
}
impl AxisInstanceArraysMarker {
pub fn axes_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + self.axes_byte_len
}
pub fn instances_byte_range(&self) -> Range<usize> {
let start = self.axes_byte_range().end;
start..start + self.instances_byte_len
}
}
impl MinByteRange for AxisInstanceArraysMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.instances_byte_range().end
}
}
impl ReadArgs for AxisInstanceArrays<'_> {
type Args = (u16, u16, u16);
}
impl<'a> FontReadWithArgs<'a> for AxisInstanceArrays<'a> {
fn read_with_args(data: FontData<'a>, args: &(u16, u16, u16)) -> Result<Self, ReadError> {
let (axis_count, instance_count, instance_size) = *args;
let mut cursor = data.cursor();
let axes_byte_len = (axis_count as usize)
.checked_mul(VariationAxisRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(axes_byte_len);
let instances_byte_len = (instance_count as usize)
.checked_mul(<InstanceRecord as ComputeSize>::compute_size(&(
axis_count,
instance_size,
))?)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(instances_byte_len);
cursor.finish(AxisInstanceArraysMarker {
axis_count,
instance_size,
axes_byte_len,
instances_byte_len,
})
}
}
impl<'a> AxisInstanceArrays<'a> {
/// A constructor that requires additional arguments.
///
/// This type requires some external state in order to be
/// parsed.
pub fn read(
data: FontData<'a>,
axis_count: u16,
instance_count: u16,
instance_size: u16,
) -> Result<Self, ReadError> {
let args = (axis_count, instance_count, instance_size);
Self::read_with_args(data, &args)
}
}
/// Shim table to handle combined axis and instance arrays.
pub type AxisInstanceArrays<'a> = TableRef<'a, AxisInstanceArraysMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> AxisInstanceArrays<'a> {
/// Variation axis record array.
pub fn axes(&self) -> &'a [VariationAxisRecord] {
let range = self.shape.axes_byte_range();
self.data.read_array(range).unwrap()
}
/// Instance record array.
pub fn instances(&self) -> ComputedArray<'a, InstanceRecord<'a>> {
let range = self.shape.instances_byte_range();
self.data
.read_with_args(range, &(self.axis_count(), self.instance_size()))
.unwrap()
}
pub(crate) fn axis_count(&self) -> u16 {
self.shape.axis_count
}
pub(crate) fn instance_size(&self) -> u16 {
self.shape.instance_size
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for AxisInstanceArrays<'a> {
fn type_name(&self) -> &str {
"AxisInstanceArrays"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"axes",
traversal::FieldType::array_of_records(
stringify!(VariationAxisRecord),
self.axes(),
self.offset_data(),
),
)),
1usize => Some(Field::new(
"instances",
traversal::FieldType::computed_array(
"InstanceRecord",
self.instances(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for AxisInstanceArrays<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The [VariationAxisRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/fvar#variationaxisrecord)
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct VariationAxisRecord {
/// Tag identifying the design variation for the axis.
pub axis_tag: BigEndian<Tag>,
/// The minimum coordinate value for the axis.
pub min_value: BigEndian<Fixed>,
/// The default coordinate value for the axis.
pub default_value: BigEndian<Fixed>,
/// The maximum coordinate value for the axis.
pub max_value: BigEndian<Fixed>,
/// Axis qualifiers — see details below.
pub flags: BigEndian<u16>,
/// The name ID for entries in the 'name' table that provide a display name for this axis.
pub axis_name_id: BigEndian<NameId>,
}
impl VariationAxisRecord {
/// Tag identifying the design variation for the axis.
pub fn axis_tag(&self) -> Tag {
self.axis_tag.get()
}
/// The minimum coordinate value for the axis.
pub fn min_value(&self) -> Fixed {
self.min_value.get()
}
/// The default coordinate value for the axis.
pub fn default_value(&self) -> Fixed {
self.default_value.get()
}
/// The maximum coordinate value for the axis.
pub fn max_value(&self) -> Fixed {
self.max_value.get()
}
/// Axis qualifiers — see details below.
pub fn flags(&self) -> u16 {
self.flags.get()
}
/// The name ID for entries in the 'name' table that provide a display name for this axis.
pub fn axis_name_id(&self) -> NameId {
self.axis_name_id.get()
}
}
impl FixedSize for VariationAxisRecord {
const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN
+ Fixed::RAW_BYTE_LEN
+ Fixed::RAW_BYTE_LEN
+ Fixed::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ NameId::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for VariationAxisRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "VariationAxisRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("axis_tag", self.axis_tag())),
1usize => Some(Field::new("min_value", self.min_value())),
2usize => Some(Field::new("default_value", self.default_value())),
3usize => Some(Field::new("max_value", self.max_value())),
4usize => Some(Field::new("flags", self.flags())),
5usize => Some(Field::new("axis_name_id", self.axis_name_id())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,474 @@
// 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::*;
/// [gasp](https://learn.microsoft.com/en-us/typography/opentype/spec/gasp#gasp-table-formats)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct GaspMarker {
gasp_ranges_byte_len: usize,
}
impl GaspMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_ranges_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn gasp_ranges_byte_range(&self) -> Range<usize> {
let start = self.num_ranges_byte_range().end;
start..start + self.gasp_ranges_byte_len
}
}
impl MinByteRange for GaspMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.gasp_ranges_byte_range().end
}
}
impl TopLevelTable for Gasp<'_> {
/// `gasp`
const TAG: Tag = Tag::new(b"gasp");
}
impl<'a> FontRead<'a> for Gasp<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let num_ranges: u16 = cursor.read()?;
let gasp_ranges_byte_len = (num_ranges as usize)
.checked_mul(GaspRange::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(gasp_ranges_byte_len);
cursor.finish(GaspMarker {
gasp_ranges_byte_len,
})
}
}
/// [gasp](https://learn.microsoft.com/en-us/typography/opentype/spec/gasp#gasp-table-formats)
pub type Gasp<'a> = TableRef<'a, GaspMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Gasp<'a> {
/// Version number (set to 1)
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of records to follow
pub fn num_ranges(&self) -> u16 {
let range = self.shape.num_ranges_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Sorted by ppem
pub fn gasp_ranges(&self) -> &'a [GaspRange] {
let range = self.shape.gasp_ranges_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Gasp<'a> {
fn type_name(&self) -> &str {
"Gasp"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("num_ranges", self.num_ranges())),
2usize => Some(Field::new(
"gasp_ranges",
traversal::FieldType::array_of_records(
stringify!(GaspRange),
self.gasp_ranges(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Gasp<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct GaspRange {
/// Upper limit of range, in PPEM
pub range_max_ppem: BigEndian<u16>,
/// Flags describing desired rasterizer behavior.
pub range_gasp_behavior: BigEndian<GaspRangeBehavior>,
}
impl GaspRange {
/// Upper limit of range, in PPEM
pub fn range_max_ppem(&self) -> u16 {
self.range_max_ppem.get()
}
/// Flags describing desired rasterizer behavior.
pub fn range_gasp_behavior(&self) -> GaspRangeBehavior {
self.range_gasp_behavior.get()
}
}
impl FixedSize for GaspRange {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + GaspRangeBehavior::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for GaspRange {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "GaspRange",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("range_max_ppem", self.range_max_ppem())),
1usize => Some(Field::new(
"range_gasp_behavior",
self.range_gasp_behavior(),
)),
_ => None,
}),
data,
}
}
}
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct GaspRangeBehavior {
bits: u16,
}
impl GaspRangeBehavior {
/// Use gridfitting
pub const GASP_GRIDFIT: Self = Self { bits: 0x0001 };
/// Use grayscale rendering
pub const GASP_DOGRAY: Self = Self { bits: 0x0002 };
/// Use gridfitting with ClearType symmetric smoothing Only
/// supported in version 1 'gasp'
pub const GASP_SYMMETRIC_GRIDFIT: Self = Self { bits: 0x0004 };
/// Use smoothing along multiple axes with ClearType® Only
/// supported in version 1 'gasp'
pub const GASP_SYMMETRIC_SMOOTHING: Self = Self { bits: 0x0008 };
}
impl GaspRangeBehavior {
/// 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::GASP_GRIDFIT.bits
| Self::GASP_DOGRAY.bits
| Self::GASP_SYMMETRIC_GRIDFIT.bits
| Self::GASP_SYMMETRIC_SMOOTHING.bits,
}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub const fn bits(&self) -> u16 {
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: u16) -> Option<Self> {
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: u16) -> 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 GaspRangeBehavior {
type Output = Self;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: GaspRangeBehavior) -> Self {
Self {
bits: self.bits | other.bits,
}
}
}
impl std::ops::BitOrAssign for GaspRangeBehavior {
/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}
impl std::ops::BitXor for GaspRangeBehavior {
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 GaspRangeBehavior {
/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}
impl std::ops::BitAnd for GaspRangeBehavior {
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 GaspRangeBehavior {
/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}
impl std::ops::Sub for GaspRangeBehavior {
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 GaspRangeBehavior {
/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}
impl std::ops::Not for GaspRangeBehavior {
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 GaspRangeBehavior {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let members: &[(&str, Self)] = &[
("GASP_GRIDFIT", Self::GASP_GRIDFIT),
("GASP_DOGRAY", Self::GASP_DOGRAY),
("GASP_SYMMETRIC_GRIDFIT", Self::GASP_SYMMETRIC_GRIDFIT),
("GASP_SYMMETRIC_SMOOTHING", Self::GASP_SYMMETRIC_SMOOTHING),
];
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 GaspRangeBehavior {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Binary::fmt(&self.bits, f)
}
}
impl std::fmt::Octal for GaspRangeBehavior {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Octal::fmt(&self.bits, f)
}
}
impl std::fmt::LowerHex for GaspRangeBehavior {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::LowerHex::fmt(&self.bits, f)
}
}
impl std::fmt::UpperHex for GaspRangeBehavior {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::UpperHex::fmt(&self.bits, f)
}
}
impl font_types::Scalar for GaspRangeBehavior {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.bits().to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::from_bits_truncate(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<GaspRangeBehavior> for FieldType<'a> {
fn from(src: GaspRangeBehavior) -> FieldType<'a> {
src.bits().into()
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,697 @@
// 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::*;
/// The ['gvar' header](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#gvar-header)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct GvarMarker {
glyph_variation_data_offsets_byte_len: usize,
}
impl GvarMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn axis_count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn shared_tuple_count_byte_range(&self) -> Range<usize> {
let start = self.axis_count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn shared_tuples_offset_byte_range(&self) -> Range<usize> {
let start = self.shared_tuple_count_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn glyph_count_byte_range(&self) -> Range<usize> {
let start = self.shared_tuples_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.glyph_count_byte_range().end;
start..start + GvarFlags::RAW_BYTE_LEN
}
pub fn glyph_variation_data_array_offset_byte_range(&self) -> Range<usize> {
let start = self.flags_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn glyph_variation_data_offsets_byte_range(&self) -> Range<usize> {
let start = self.glyph_variation_data_array_offset_byte_range().end;
start..start + self.glyph_variation_data_offsets_byte_len
}
}
impl MinByteRange for GvarMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.glyph_variation_data_offsets_byte_range().end
}
}
impl TopLevelTable for Gvar<'_> {
/// `gvar`
const TAG: Tag = Tag::new(b"gvar");
}
impl<'a> FontRead<'a> for Gvar<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<Offset32>();
let glyph_count: u16 = cursor.read()?;
let flags: GvarFlags = cursor.read()?;
cursor.advance::<u32>();
let glyph_variation_data_offsets_byte_len = (transforms::add(glyph_count, 1_usize))
.checked_mul(<U16Or32 as ComputeSize>::compute_size(&flags)?)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(glyph_variation_data_offsets_byte_len);
cursor.finish(GvarMarker {
glyph_variation_data_offsets_byte_len,
})
}
}
/// The ['gvar' header](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#gvar-header)
pub type Gvar<'a> = TableRef<'a, GvarMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Gvar<'a> {
/// Major/minor version number of the glyph variations table — set to (1,0).
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of variation axes for this font. This must be the
/// same number as axisCount in the 'fvar' table.
pub fn axis_count(&self) -> u16 {
let range = self.shape.axis_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of shared tuple records. Shared tuple records can be
/// referenced within glyph variation data tables for multiple
/// glyphs, as opposed to other tuple records stored directly
/// within a glyph variation data table.
pub fn shared_tuple_count(&self) -> u16 {
let range = self.shape.shared_tuple_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from the start of this table to the shared tuple records.
pub fn shared_tuples_offset(&self) -> Offset32 {
let range = self.shape.shared_tuples_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`shared_tuples_offset`][Self::shared_tuples_offset].
pub fn shared_tuples(&self) -> Result<SharedTuples<'a>, ReadError> {
let data = self.data;
let args = (self.shared_tuple_count(), self.axis_count());
self.shared_tuples_offset().resolve_with_args(data, &args)
}
/// The number of glyphs in this font. This must match the number
/// of glyphs stored elsewhere in the font.
pub fn glyph_count(&self) -> u16 {
let range = self.shape.glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Bit-field that gives the format of the offset array that
/// follows. If bit 0 is clear, the offsets are uint16; if bit 0 is
/// set, the offsets are uint32.
pub fn flags(&self) -> GvarFlags {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from the start of this table to the array of
/// GlyphVariationData tables.
pub fn glyph_variation_data_array_offset(&self) -> u32 {
let range = self.shape.glyph_variation_data_array_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offsets from the start of the GlyphVariationData array to each
/// GlyphVariationData table.
pub fn glyph_variation_data_offsets(&self) -> ComputedArray<'a, U16Or32> {
let range = self.shape.glyph_variation_data_offsets_byte_range();
self.data.read_with_args(range, &self.flags()).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Gvar<'a> {
fn type_name(&self) -> &str {
"Gvar"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("axis_count", self.axis_count())),
2usize => Some(Field::new("shared_tuple_count", self.shared_tuple_count())),
3usize => Some(Field::new(
"shared_tuples_offset",
FieldType::offset(self.shared_tuples_offset(), self.shared_tuples()),
)),
4usize => Some(Field::new("glyph_count", self.glyph_count())),
5usize => Some(Field::new("flags", self.flags())),
6usize => Some(Field::new(
"glyph_variation_data_array_offset",
self.glyph_variation_data_array_offset(),
)),
7usize => Some(Field::new(
"glyph_variation_data_offsets",
traversal::FieldType::Unknown,
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Gvar<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct GvarFlags {
bits: u16,
}
impl GvarFlags {
/// If set, offsets to GlyphVariationData are 32 bits
pub const LONG_OFFSETS: Self = Self { bits: 1 };
}
impl GvarFlags {
/// 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::LONG_OFFSETS.bits,
}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub const fn bits(&self) -> u16 {
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: u16) -> Option<Self> {
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: u16) -> 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 GvarFlags {
type Output = Self;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: GvarFlags) -> Self {
Self {
bits: self.bits | other.bits,
}
}
}
impl std::ops::BitOrAssign for GvarFlags {
/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}
impl std::ops::BitXor for GvarFlags {
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 GvarFlags {
/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}
impl std::ops::BitAnd for GvarFlags {
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 GvarFlags {
/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}
impl std::ops::Sub for GvarFlags {
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 GvarFlags {
/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}
impl std::ops::Not for GvarFlags {
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 GvarFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let members: &[(&str, Self)] = &[("LONG_OFFSETS", Self::LONG_OFFSETS)];
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 GvarFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Binary::fmt(&self.bits, f)
}
}
impl std::fmt::Octal for GvarFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Octal::fmt(&self.bits, f)
}
}
impl std::fmt::LowerHex for GvarFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::LowerHex::fmt(&self.bits, f)
}
}
impl std::fmt::UpperHex for GvarFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::UpperHex::fmt(&self.bits, f)
}
}
impl font_types::Scalar for GvarFlags {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.bits().to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::from_bits_truncate(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<GvarFlags> for FieldType<'a> {
fn from(src: GvarFlags) -> FieldType<'a> {
src.bits().into()
}
}
/// Array of tuple records shared across all glyph variation data tables.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SharedTuplesMarker {
axis_count: u16,
tuples_byte_len: usize,
}
impl SharedTuplesMarker {
pub fn tuples_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + self.tuples_byte_len
}
}
impl MinByteRange for SharedTuplesMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.tuples_byte_range().end
}
}
impl ReadArgs for SharedTuples<'_> {
type Args = (u16, u16);
}
impl<'a> FontReadWithArgs<'a> for SharedTuples<'a> {
fn read_with_args(data: FontData<'a>, args: &(u16, u16)) -> Result<Self, ReadError> {
let (shared_tuple_count, axis_count) = *args;
let mut cursor = data.cursor();
let tuples_byte_len = (shared_tuple_count as usize)
.checked_mul(<Tuple as ComputeSize>::compute_size(&axis_count)?)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(tuples_byte_len);
cursor.finish(SharedTuplesMarker {
axis_count,
tuples_byte_len,
})
}
}
impl<'a> SharedTuples<'a> {
/// A constructor that requires additional arguments.
///
/// This type requires some external state in order to be
/// parsed.
pub fn read(
data: FontData<'a>,
shared_tuple_count: u16,
axis_count: u16,
) -> Result<Self, ReadError> {
let args = (shared_tuple_count, axis_count);
Self::read_with_args(data, &args)
}
}
/// Array of tuple records shared across all glyph variation data tables.
pub type SharedTuples<'a> = TableRef<'a, SharedTuplesMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SharedTuples<'a> {
pub fn tuples(&self) -> ComputedArray<'a, Tuple<'a>> {
let range = self.shape.tuples_byte_range();
self.data.read_with_args(range, &self.axis_count()).unwrap()
}
pub(crate) fn axis_count(&self) -> u16 {
self.shape.axis_count
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SharedTuples<'a> {
fn type_name(&self) -> &str {
"SharedTuples"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"tuples",
traversal::FieldType::computed_array("Tuple", self.tuples(), self.offset_data()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SharedTuples<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The [GlyphVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#the-glyphvariationdata-table-array) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct GlyphVariationDataHeaderMarker {
tuple_variation_headers_byte_len: usize,
}
impl GlyphVariationDataHeaderMarker {
pub fn tuple_variation_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + TupleVariationCount::RAW_BYTE_LEN
}
pub fn serialized_data_offset_byte_range(&self) -> Range<usize> {
let start = self.tuple_variation_count_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn tuple_variation_headers_byte_range(&self) -> Range<usize> {
let start = self.serialized_data_offset_byte_range().end;
start..start + self.tuple_variation_headers_byte_len
}
}
impl MinByteRange for GlyphVariationDataHeaderMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.tuple_variation_headers_byte_range().end
}
}
impl<'a> FontRead<'a> for GlyphVariationDataHeader<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<TupleVariationCount>();
cursor.advance::<Offset16>();
let tuple_variation_headers_byte_len = cursor.remaining_bytes();
cursor.advance_by(tuple_variation_headers_byte_len);
cursor.finish(GlyphVariationDataHeaderMarker {
tuple_variation_headers_byte_len,
})
}
}
/// The [GlyphVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#the-glyphvariationdata-table-array) table
pub type GlyphVariationDataHeader<'a> = TableRef<'a, GlyphVariationDataHeaderMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> GlyphVariationDataHeader<'a> {
/// A packed field. The high 4 bits are flags, and the low 12 bits
/// are the number of tuple variation tables for this glyph. The
/// number of tuple variation tables can be any number between 1
/// and 4095.
pub fn tuple_variation_count(&self) -> TupleVariationCount {
let range = self.shape.tuple_variation_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from the start of the GlyphVariationData table to the
/// serialized data
pub fn serialized_data_offset(&self) -> Offset16 {
let range = self.shape.serialized_data_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`serialized_data_offset`][Self::serialized_data_offset].
pub fn serialized_data(&self) -> Result<FontData<'a>, ReadError> {
let data = self.data;
self.serialized_data_offset().resolve(data)
}
/// Array of tuple variation headers.
pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader> {
let range = self.shape.tuple_variation_headers_byte_range();
VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for GlyphVariationDataHeader<'a> {
fn type_name(&self) -> &str {
"GlyphVariationDataHeader"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"tuple_variation_count",
traversal::FieldType::Unknown,
)),
1usize => Some(Field::new(
"serialized_data_offset",
traversal::FieldType::Unknown,
)),
2usize => Some(Field::new(
"tuple_variation_headers",
traversal::FieldType::Unknown,
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for GlyphVariationDataHeader<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,150 @@
// 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::*;
/// The [Horizontal Device Metrics](https://learn.microsoft.com/en-us/typography/opentype/spec/hdmx) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct HdmxMarker {
num_glyphs: u16,
records_byte_len: usize,
}
impl HdmxMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_records_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn size_device_record_byte_range(&self) -> Range<usize> {
let start = self.num_records_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn records_byte_range(&self) -> Range<usize> {
let start = self.size_device_record_byte_range().end;
start..start + self.records_byte_len
}
}
impl MinByteRange for HdmxMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.records_byte_range().end
}
}
impl TopLevelTable for Hdmx<'_> {
/// `hdmx`
const TAG: Tag = Tag::new(b"hdmx");
}
impl ReadArgs for Hdmx<'_> {
type Args = u16;
}
impl<'a> FontReadWithArgs<'a> for Hdmx<'a> {
fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
let num_glyphs = *args;
let mut cursor = data.cursor();
cursor.advance::<u16>();
let num_records: u16 = cursor.read()?;
let size_device_record: u32 = cursor.read()?;
let records_byte_len = (num_records as usize)
.checked_mul(<DeviceRecord as ComputeSize>::compute_size(&(
num_glyphs,
size_device_record,
))?)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(records_byte_len);
cursor.finish(HdmxMarker {
num_glyphs,
records_byte_len,
})
}
}
impl<'a> Hdmx<'a> {
/// A constructor that requires additional arguments.
///
/// This type requires some external state in order to be
/// parsed.
pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
let args = num_glyphs;
Self::read_with_args(data, &args)
}
}
/// The [Horizontal Device Metrics](https://learn.microsoft.com/en-us/typography/opentype/spec/hdmx) table.
pub type Hdmx<'a> = TableRef<'a, HdmxMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Hdmx<'a> {
/// Table version number (set to 0).
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of device records.
pub fn num_records(&self) -> u16 {
let range = self.shape.num_records_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Size of device record, 32-bit aligned.
pub fn size_device_record(&self) -> u32 {
let range = self.shape.size_device_record_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Array of device records.
pub fn records(&self) -> ComputedArray<'a, DeviceRecord<'a>> {
let range = self.shape.records_byte_range();
self.data
.read_with_args(range, &(self.num_glyphs(), self.size_device_record()))
.unwrap()
}
pub(crate) fn num_glyphs(&self) -> u16 {
self.shape.num_glyphs
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Hdmx<'a> {
fn type_name(&self) -> &str {
"Hdmx"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("num_records", self.num_records())),
2usize => Some(Field::new("size_device_record", self.size_device_record())),
3usize => Some(Field::new(
"records",
traversal::FieldType::computed_array(
"DeviceRecord",
self.records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Hdmx<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,632 @@
// 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::*;
/// The `macStyle` field for the head table.
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct MacStyle {
bits: u16,
}
impl MacStyle {
/// Bit 0: Bold (if set to 1)
pub const BOLD: Self = Self { bits: 0x0001 };
/// Bit 1: Italic (if set to 1)
pub const ITALIC: Self = Self { bits: 0x0002 };
/// Bit 2: Underline (if set to 1)
pub const UNDERLINE: Self = Self { bits: 0x0004 };
/// Bit 3: Outline (if set to 1)
pub const OUTLINE: Self = Self { bits: 0x0008 };
/// Bit 4: Shadow (if set to 1)
pub const SHADOW: Self = Self { bits: 0x0010 };
/// Bit 5: Condensed (if set to 1)
pub const CONDENSED: Self = Self { bits: 0x0020 };
/// Bit 6: Extended (if set to 1)
pub const EXTENDED: Self = Self { bits: 0x0040 };
}
impl MacStyle {
/// 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::BOLD.bits
| Self::ITALIC.bits
| Self::UNDERLINE.bits
| Self::OUTLINE.bits
| Self::SHADOW.bits
| Self::CONDENSED.bits
| Self::EXTENDED.bits,
}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub const fn bits(&self) -> u16 {
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: u16) -> Option<Self> {
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: u16) -> 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 MacStyle {
type Output = Self;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: MacStyle) -> Self {
Self {
bits: self.bits | other.bits,
}
}
}
impl std::ops::BitOrAssign for MacStyle {
/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}
impl std::ops::BitXor for MacStyle {
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 MacStyle {
/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}
impl std::ops::BitAnd for MacStyle {
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 MacStyle {
/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}
impl std::ops::Sub for MacStyle {
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 MacStyle {
/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}
impl std::ops::Not for MacStyle {
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 MacStyle {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let members: &[(&str, Self)] = &[
("BOLD", Self::BOLD),
("ITALIC", Self::ITALIC),
("UNDERLINE", Self::UNDERLINE),
("OUTLINE", Self::OUTLINE),
("SHADOW", Self::SHADOW),
("CONDENSED", Self::CONDENSED),
("EXTENDED", Self::EXTENDED),
];
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 MacStyle {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Binary::fmt(&self.bits, f)
}
}
impl std::fmt::Octal for MacStyle {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Octal::fmt(&self.bits, f)
}
}
impl std::fmt::LowerHex for MacStyle {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::LowerHex::fmt(&self.bits, f)
}
}
impl std::fmt::UpperHex for MacStyle {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::UpperHex::fmt(&self.bits, f)
}
}
impl font_types::Scalar for MacStyle {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.bits().to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::from_bits_truncate(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<MacStyle> for FieldType<'a> {
fn from(src: MacStyle) -> FieldType<'a> {
src.bits().into()
}
}
/// The [head](https://docs.microsoft.com/en-us/typography/opentype/spec/head)
/// (font header) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct HeadMarker {}
impl HeadMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn font_revision_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Fixed::RAW_BYTE_LEN
}
pub fn checksum_adjustment_byte_range(&self) -> Range<usize> {
let start = self.font_revision_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn magic_number_byte_range(&self) -> Range<usize> {
let start = self.checksum_adjustment_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.magic_number_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn units_per_em_byte_range(&self) -> Range<usize> {
let start = self.flags_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn created_byte_range(&self) -> Range<usize> {
let start = self.units_per_em_byte_range().end;
start..start + LongDateTime::RAW_BYTE_LEN
}
pub fn modified_byte_range(&self) -> Range<usize> {
let start = self.created_byte_range().end;
start..start + LongDateTime::RAW_BYTE_LEN
}
pub fn x_min_byte_range(&self) -> Range<usize> {
let start = self.modified_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn y_min_byte_range(&self) -> Range<usize> {
let start = self.x_min_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn x_max_byte_range(&self) -> Range<usize> {
let start = self.y_min_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn y_max_byte_range(&self) -> Range<usize> {
let start = self.x_max_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn mac_style_byte_range(&self) -> Range<usize> {
let start = self.y_max_byte_range().end;
start..start + MacStyle::RAW_BYTE_LEN
}
pub fn lowest_rec_ppem_byte_range(&self) -> Range<usize> {
let start = self.mac_style_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn font_direction_hint_byte_range(&self) -> Range<usize> {
let start = self.lowest_rec_ppem_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn index_to_loc_format_byte_range(&self) -> Range<usize> {
let start = self.font_direction_hint_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn glyph_data_format_byte_range(&self) -> Range<usize> {
let start = self.index_to_loc_format_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
}
impl MinByteRange for HeadMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.glyph_data_format_byte_range().end
}
}
impl TopLevelTable for Head<'_> {
/// `head`
const TAG: Tag = Tag::new(b"head");
}
impl<'a> FontRead<'a> for Head<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<Fixed>();
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<LongDateTime>();
cursor.advance::<LongDateTime>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<MacStyle>();
cursor.advance::<u16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.finish(HeadMarker {})
}
}
/// The [head](https://docs.microsoft.com/en-us/typography/opentype/spec/head)
/// (font header) table.
pub type Head<'a> = TableRef<'a, HeadMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Head<'a> {
/// Version number of the font header table, set to (1, 0)
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Set by font manufacturer.
pub fn font_revision(&self) -> Fixed {
let range = self.shape.font_revision_byte_range();
self.data.read_at(range.start).unwrap()
}
/// To compute: set it to 0, sum the entire font as uint32, then
/// store 0xB1B0AFBA - sum. If the font is used as a component in a
/// font collection file, the value of this field will be
/// invalidated by changes to the file structure and font table
/// directory, and must be ignored.
pub fn checksum_adjustment(&self) -> u32 {
let range = self.shape.checksum_adjustment_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Set to 0x5F0F3CF5.
pub fn magic_number(&self) -> u32 {
let range = self.shape.magic_number_byte_range();
self.data.read_at(range.start).unwrap()
}
/// See the flags enum
pub fn flags(&self) -> u16 {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Set to a value from 16 to 16384. Any value in this range is
/// valid. In fonts that have TrueType outlines, a power of 2 is
/// recommended as this allows performance optimizations in some
/// rasterizers.
pub fn units_per_em(&self) -> u16 {
let range = self.shape.units_per_em_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of seconds since 12:00 midnight that started January 1st
/// 1904 in GMT/UTC time zone.
pub fn created(&self) -> LongDateTime {
let range = self.shape.created_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of seconds since 12:00 midnight that started January 1st
/// 1904 in GMT/UTC time zone.
pub fn modified(&self) -> LongDateTime {
let range = self.shape.modified_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum x coordinate across all glyph bounding boxes.
pub fn x_min(&self) -> i16 {
let range = self.shape.x_min_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum y coordinate across all glyph bounding boxes.
pub fn y_min(&self) -> i16 {
let range = self.shape.y_min_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Maximum x coordinate across all glyph bounding boxes.
pub fn x_max(&self) -> i16 {
let range = self.shape.x_max_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Maximum y coordinate across all glyph bounding boxes.
pub fn y_max(&self) -> i16 {
let range = self.shape.y_max_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Bits identifying the font's style; see [MacStyle]
pub fn mac_style(&self) -> MacStyle {
let range = self.shape.mac_style_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Smallest readable size in pixels.
pub fn lowest_rec_ppem(&self) -> u16 {
let range = self.shape.lowest_rec_ppem_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Deprecated (Set to 2).
pub fn font_direction_hint(&self) -> i16 {
let range = self.shape.font_direction_hint_byte_range();
self.data.read_at(range.start).unwrap()
}
/// 0 for short offsets (Offset16), 1 for long (Offset32).
pub fn index_to_loc_format(&self) -> i16 {
let range = self.shape.index_to_loc_format_byte_range();
self.data.read_at(range.start).unwrap()
}
/// 0 for current format.
pub fn glyph_data_format(&self) -> i16 {
let range = self.shape.glyph_data_format_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Head<'a> {
fn type_name(&self) -> &str {
"Head"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("font_revision", self.font_revision())),
2usize => Some(Field::new(
"checksum_adjustment",
self.checksum_adjustment(),
)),
3usize => Some(Field::new("magic_number", self.magic_number())),
4usize => Some(Field::new("flags", self.flags())),
5usize => Some(Field::new("units_per_em", self.units_per_em())),
6usize => Some(Field::new("created", self.created())),
7usize => Some(Field::new("modified", self.modified())),
8usize => Some(Field::new("x_min", self.x_min())),
9usize => Some(Field::new("y_min", self.y_min())),
10usize => Some(Field::new("x_max", self.x_max())),
11usize => Some(Field::new("y_max", self.y_max())),
12usize => Some(Field::new("mac_style", self.mac_style())),
13usize => Some(Field::new("lowest_rec_ppem", self.lowest_rec_ppem())),
14usize => Some(Field::new(
"font_direction_hint",
self.font_direction_hint(),
)),
15usize => Some(Field::new(
"index_to_loc_format",
self.index_to_loc_format(),
)),
16usize => Some(Field::new("glyph_data_format", self.glyph_data_format())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Head<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,265 @@
// 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::*;
/// [hhea](https://docs.microsoft.com/en-us/typography/opentype/spec/hhea) Horizontal Header Table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct HheaMarker {}
impl HheaMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn ascender_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn descender_byte_range(&self) -> Range<usize> {
let start = self.ascender_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn line_gap_byte_range(&self) -> Range<usize> {
let start = self.descender_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn advance_width_max_byte_range(&self) -> Range<usize> {
let start = self.line_gap_byte_range().end;
start..start + UfWord::RAW_BYTE_LEN
}
pub fn min_left_side_bearing_byte_range(&self) -> Range<usize> {
let start = self.advance_width_max_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn min_right_side_bearing_byte_range(&self) -> Range<usize> {
let start = self.min_left_side_bearing_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn x_max_extent_byte_range(&self) -> Range<usize> {
let start = self.min_right_side_bearing_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn caret_slope_rise_byte_range(&self) -> Range<usize> {
let start = self.x_max_extent_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn caret_slope_run_byte_range(&self) -> Range<usize> {
let start = self.caret_slope_rise_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn caret_offset_byte_range(&self) -> Range<usize> {
let start = self.caret_slope_run_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved1_byte_range(&self) -> Range<usize> {
let start = self.caret_offset_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved2_byte_range(&self) -> Range<usize> {
let start = self.reserved1_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved3_byte_range(&self) -> Range<usize> {
let start = self.reserved2_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved4_byte_range(&self) -> Range<usize> {
let start = self.reserved3_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn metric_data_format_byte_range(&self) -> Range<usize> {
let start = self.reserved4_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn number_of_h_metrics_byte_range(&self) -> Range<usize> {
let start = self.metric_data_format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for HheaMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.number_of_h_metrics_byte_range().end
}
}
impl TopLevelTable for Hhea<'_> {
/// `hhea`
const TAG: Tag = Tag::new(b"hhea");
}
impl<'a> FontRead<'a> for Hhea<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<UfWord>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<u16>();
cursor.finish(HheaMarker {})
}
}
/// [hhea](https://docs.microsoft.com/en-us/typography/opentype/spec/hhea) Horizontal Header Table
pub type Hhea<'a> = TableRef<'a, HheaMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Hhea<'a> {
/// The major/minor version (1, 0)
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Typographic ascent.
pub fn ascender(&self) -> FWord {
let range = self.shape.ascender_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Typographic descent.
pub fn descender(&self) -> FWord {
let range = self.shape.descender_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Typographic line gap. Negative LineGap values are treated as
/// zero in some legacy platform implementations.
pub fn line_gap(&self) -> FWord {
let range = self.shape.line_gap_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Maximum advance width value in 'hmtx' table.
pub fn advance_width_max(&self) -> UfWord {
let range = self.shape.advance_width_max_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum left sidebearing value in 'hmtx' table for glyphs with
/// contours (empty glyphs should be ignored).
pub fn min_left_side_bearing(&self) -> FWord {
let range = self.shape.min_left_side_bearing_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum right sidebearing value; calculated as min(aw - (lsb +
/// xMax - xMin)) for glyphs with contours (empty glyphs should be ignored).
pub fn min_right_side_bearing(&self) -> FWord {
let range = self.shape.min_right_side_bearing_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Max(lsb + (xMax-xMin))
pub fn x_max_extent(&self) -> FWord {
let range = self.shape.x_max_extent_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Used to calculate the slope of the cursor (rise/run); 1 for
/// vertical caret, 0 for horizontal.
pub fn caret_slope_rise(&self) -> i16 {
let range = self.shape.caret_slope_rise_byte_range();
self.data.read_at(range.start).unwrap()
}
/// 0 for vertical caret, 1 for horizontal.
pub fn caret_slope_run(&self) -> i16 {
let range = self.shape.caret_slope_run_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The amount by which a slanted highlight on a glyph needs to be
/// shifted to produce the best appearance. Set to 0 for
/// non-slanted fonts
pub fn caret_offset(&self) -> i16 {
let range = self.shape.caret_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// 0 for current format.
pub fn metric_data_format(&self) -> i16 {
let range = self.shape.metric_data_format_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of hMetric entries in 'hmtx' table
pub fn number_of_h_metrics(&self) -> u16 {
let range = self.shape.number_of_h_metrics_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Hhea<'a> {
fn type_name(&self) -> &str {
"Hhea"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("ascender", self.ascender())),
2usize => Some(Field::new("descender", self.descender())),
3usize => Some(Field::new("line_gap", self.line_gap())),
4usize => Some(Field::new("advance_width_max", self.advance_width_max())),
5usize => Some(Field::new(
"min_left_side_bearing",
self.min_left_side_bearing(),
)),
6usize => Some(Field::new(
"min_right_side_bearing",
self.min_right_side_bearing(),
)),
7usize => Some(Field::new("x_max_extent", self.x_max_extent())),
8usize => Some(Field::new("caret_slope_rise", self.caret_slope_rise())),
9usize => Some(Field::new("caret_slope_run", self.caret_slope_run())),
10usize => Some(Field::new("caret_offset", self.caret_offset())),
11usize => Some(Field::new("metric_data_format", self.metric_data_format())),
12usize => Some(Field::new(
"number_of_h_metrics",
self.number_of_h_metrics(),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Hhea<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,165 @@
// 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::*;
/// The [hmtx (Horizontal Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct HmtxMarker {
h_metrics_byte_len: usize,
left_side_bearings_byte_len: usize,
}
impl HmtxMarker {
pub fn h_metrics_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + self.h_metrics_byte_len
}
pub fn left_side_bearings_byte_range(&self) -> Range<usize> {
let start = self.h_metrics_byte_range().end;
start..start + self.left_side_bearings_byte_len
}
}
impl MinByteRange for HmtxMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.left_side_bearings_byte_range().end
}
}
impl TopLevelTable for Hmtx<'_> {
/// `hmtx`
const TAG: Tag = Tag::new(b"hmtx");
}
impl ReadArgs for Hmtx<'_> {
type Args = (u16, u16);
}
impl<'a> FontReadWithArgs<'a> for Hmtx<'a> {
fn read_with_args(data: FontData<'a>, args: &(u16, u16)) -> Result<Self, ReadError> {
let (number_of_h_metrics, num_glyphs) = *args;
let mut cursor = data.cursor();
let h_metrics_byte_len = (number_of_h_metrics as usize)
.checked_mul(LongMetric::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(h_metrics_byte_len);
let left_side_bearings_byte_len = (transforms::subtract(num_glyphs, number_of_h_metrics))
.checked_mul(i16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(left_side_bearings_byte_len);
cursor.finish(HmtxMarker {
h_metrics_byte_len,
left_side_bearings_byte_len,
})
}
}
impl<'a> Hmtx<'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_h_metrics: u16,
num_glyphs: u16,
) -> Result<Self, ReadError> {
let args = (number_of_h_metrics, num_glyphs);
Self::read_with_args(data, &args)
}
}
/// The [hmtx (Horizontal Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx) table
pub type Hmtx<'a> = TableRef<'a, HmtxMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Hmtx<'a> {
/// Paired advance width/height and left/top side bearing values for each
/// glyph. Records are indexed by glyph ID.
pub fn h_metrics(&self) -> &'a [LongMetric] {
let range = self.shape.h_metrics_byte_range();
self.data.read_array(range).unwrap()
}
/// Leading (left/top) side bearings for glyph IDs greater than or equal to
/// numberOfLongMetrics.
pub fn left_side_bearings(&self) -> &'a [BigEndian<i16>] {
let range = self.shape.left_side_bearings_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Hmtx<'a> {
fn type_name(&self) -> &str {
"Hmtx"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"h_metrics",
traversal::FieldType::array_of_records(
stringify!(LongMetric),
self.h_metrics(),
self.offset_data(),
),
)),
1usize => Some(Field::new("left_side_bearings", self.left_side_bearings())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Hmtx<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct LongMetric {
/// Advance width/height, in font design units.
pub advance: BigEndian<u16>,
/// Glyph leading (left/top) side bearing, in font design units.
pub side_bearing: BigEndian<i16>,
}
impl LongMetric {
/// Advance width/height, in font design units.
pub fn advance(&self) -> u16 {
self.advance.get()
}
/// Glyph leading (left/top) side bearing, in font design units.
pub fn side_bearing(&self) -> i16 {
self.side_bearing.get()
}
}
impl FixedSize for LongMetric {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for LongMetric {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "LongMetric",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("advance", self.advance())),
1usize => Some(Field::new("side_bearing", self.side_bearing())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,165 @@
// 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::*;
/// The [HVAR (Horizontal Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/hvar) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct HvarMarker {}
impl HvarMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn item_variation_store_offset_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn advance_width_mapping_offset_byte_range(&self) -> Range<usize> {
let start = self.item_variation_store_offset_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn lsb_mapping_offset_byte_range(&self) -> Range<usize> {
let start = self.advance_width_mapping_offset_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn rsb_mapping_offset_byte_range(&self) -> Range<usize> {
let start = self.lsb_mapping_offset_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
}
impl MinByteRange for HvarMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.rsb_mapping_offset_byte_range().end
}
}
impl TopLevelTable for Hvar<'_> {
/// `HVAR`
const TAG: Tag = Tag::new(b"HVAR");
}
impl<'a> FontRead<'a> for Hvar<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<Offset32>();
cursor.advance::<Offset32>();
cursor.advance::<Offset32>();
cursor.advance::<Offset32>();
cursor.finish(HvarMarker {})
}
}
/// The [HVAR (Horizontal Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/hvar) table
pub type Hvar<'a> = TableRef<'a, HvarMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Hvar<'a> {
/// Major version number of the horizontal metrics variations table — set to 1.
/// Minor version number of the horizontal metrics variations table — set to 0.
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset in bytes from the start of this table to the item variation store table.
pub fn item_variation_store_offset(&self) -> Offset32 {
let range = self.shape.item_variation_store_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset].
pub fn item_variation_store(&self) -> Result<ItemVariationStore<'a>, ReadError> {
let data = self.data;
self.item_variation_store_offset().resolve(data)
}
/// Offset in bytes from the start of this table to the delta-set index mapping for advance widths (may be NULL).
pub fn advance_width_mapping_offset(&self) -> Nullable<Offset32> {
let range = self.shape.advance_width_mapping_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`advance_width_mapping_offset`][Self::advance_width_mapping_offset].
pub fn advance_width_mapping(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.advance_width_mapping_offset().resolve(data)
}
/// Offset in bytes from the start of this table to the delta-set index mapping for left side bearings (may be NULL).
pub fn lsb_mapping_offset(&self) -> Nullable<Offset32> {
let range = self.shape.lsb_mapping_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`lsb_mapping_offset`][Self::lsb_mapping_offset].
pub fn lsb_mapping(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.lsb_mapping_offset().resolve(data)
}
/// Offset in bytes from the start of this table to the delta-set index mapping for right side bearings (may be NULL).
pub fn rsb_mapping_offset(&self) -> Nullable<Offset32> {
let range = self.shape.rsb_mapping_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`rsb_mapping_offset`][Self::rsb_mapping_offset].
pub fn rsb_mapping(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.rsb_mapping_offset().resolve(data)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Hvar<'a> {
fn type_name(&self) -> &str {
"Hvar"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"item_variation_store_offset",
FieldType::offset(
self.item_variation_store_offset(),
self.item_variation_store(),
),
)),
2usize => Some(Field::new(
"advance_width_mapping_offset",
FieldType::offset(
self.advance_width_mapping_offset(),
self.advance_width_mapping(),
),
)),
3usize => Some(Field::new(
"lsb_mapping_offset",
FieldType::offset(self.lsb_mapping_offset(), self.lsb_mapping()),
)),
4usize => Some(Field::new(
"rsb_mapping_offset",
FieldType::offset(self.rsb_mapping_offset(), self.rsb_mapping()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Hvar<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,787 @@
// 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::*;
/// The OpenType [kerning](https://learn.microsoft.com/en-us/typography/opentype/spec/kern) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct OtKernMarker {
subtable_data_byte_len: usize,
}
impl OtKernMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn n_tables_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn subtable_data_byte_range(&self) -> Range<usize> {
let start = self.n_tables_byte_range().end;
start..start + self.subtable_data_byte_len
}
}
impl MinByteRange for OtKernMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.subtable_data_byte_range().end
}
}
impl<'a> FontRead<'a> for OtKern<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
let subtable_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(subtable_data_byte_len);
cursor.finish(OtKernMarker {
subtable_data_byte_len,
})
}
}
/// The OpenType [kerning](https://learn.microsoft.com/en-us/typography/opentype/spec/kern) table.
pub type OtKern<'a> = TableRef<'a, OtKernMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> OtKern<'a> {
/// Table version number—set to 0.
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of subtables in the kerning table.
pub fn n_tables(&self) -> u16 {
let range = self.shape.n_tables_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Data for subtables, immediately following the header.
pub fn subtable_data(&self) -> &'a [u8] {
let range = self.shape.subtable_data_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for OtKern<'a> {
fn type_name(&self) -> &str {
"OtKern"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("n_tables", self.n_tables())),
2usize => Some(Field::new("subtable_data", self.subtable_data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for OtKern<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The Apple Advanced Typography [kerning](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct AatKernMarker {
subtable_data_byte_len: usize,
}
impl AatKernMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn n_tables_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn subtable_data_byte_range(&self) -> Range<usize> {
let start = self.n_tables_byte_range().end;
start..start + self.subtable_data_byte_len
}
}
impl MinByteRange for AatKernMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.subtable_data_byte_range().end
}
}
impl<'a> FontRead<'a> for AatKern<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<u32>();
let subtable_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(subtable_data_byte_len);
cursor.finish(AatKernMarker {
subtable_data_byte_len,
})
}
}
/// The Apple Advanced Typography [kerning](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html) table.
pub type AatKern<'a> = TableRef<'a, AatKernMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> AatKern<'a> {
/// The version number of the kerning table (0x00010000 for the current version).
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of subtables included in the kerning table.
pub fn n_tables(&self) -> u32 {
let range = self.shape.n_tables_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Data for subtables, immediately following the header.
pub fn subtable_data(&self) -> &'a [u8] {
let range = self.shape.subtable_data_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for AatKern<'a> {
fn type_name(&self) -> &str {
"AatKern"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("n_tables", self.n_tables())),
2usize => Some(Field::new("subtable_data", self.subtable_data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for AatKern<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// A subtable in an OT `kern` table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct OtSubtableMarker {
data_byte_len: usize,
}
impl OtSubtableMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn coverage_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn data_byte_range(&self) -> Range<usize> {
let start = self.coverage_byte_range().end;
start..start + self.data_byte_len
}
}
impl MinByteRange for OtSubtableMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.data_byte_range().end
}
}
impl<'a> FontRead<'a> for OtSubtable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(data_byte_len);
cursor.finish(OtSubtableMarker { data_byte_len })
}
}
/// A subtable in an OT `kern` table.
pub type OtSubtable<'a> = TableRef<'a, OtSubtableMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> OtSubtable<'a> {
/// Kern subtable version number-- set to 0.
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The length of this subtable in bytes, including this header.
pub fn length(&self) -> u16 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Circumstances under which this table is used.
pub fn coverage(&self) -> u16 {
let range = self.shape.coverage_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Subtable specific data.
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 OtSubtable<'a> {
fn type_name(&self) -> &str {
"OtSubtable"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("coverage", self.coverage())),
3usize => Some(Field::new("data", self.data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for OtSubtable<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// A subtable in an AAT `kern` table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct AatSubtableMarker {
data_byte_len: usize,
}
impl AatSubtableMarker {
pub fn length_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn coverage_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn tuple_index_byte_range(&self) -> Range<usize> {
let start = self.coverage_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn data_byte_range(&self) -> Range<usize> {
let start = self.tuple_index_byte_range().end;
start..start + self.data_byte_len
}
}
impl MinByteRange for AatSubtableMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.data_byte_range().end
}
}
impl<'a> FontRead<'a> for AatSubtable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(data_byte_len);
cursor.finish(AatSubtableMarker { data_byte_len })
}
}
/// A subtable in an AAT `kern` table.
pub type AatSubtable<'a> = TableRef<'a, AatSubtableMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> AatSubtable<'a> {
/// The length of this subtable in bytes, including this header.
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Circumstances under which this table is used.
pub fn coverage(&self) -> u16 {
let range = self.shape.coverage_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The tuple index (used for variations fonts). This value specifies which tuple this subtable covers.
pub fn tuple_index(&self) -> u16 {
let range = self.shape.tuple_index_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Subtable specific data.
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 AatSubtable<'a> {
fn type_name(&self) -> &str {
"AatSubtable"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("length", self.length())),
1usize => Some(Field::new("coverage", self.coverage())),
2usize => Some(Field::new("tuple_index", self.tuple_index())),
3usize => Some(Field::new("data", self.data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for AatSubtable<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The type 0 `kern` subtable.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Subtable0Marker {
pairs_byte_len: usize,
}
impl Subtable0Marker {
pub fn n_pairs_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn search_range_byte_range(&self) -> Range<usize> {
let start = self.n_pairs_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 pairs_byte_range(&self) -> Range<usize> {
let start = self.range_shift_byte_range().end;
start..start + self.pairs_byte_len
}
}
impl MinByteRange for Subtable0Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.pairs_byte_range().end
}
}
impl<'a> FontRead<'a> for Subtable0<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let n_pairs: u16 = cursor.read()?;
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let pairs_byte_len = (n_pairs as usize)
.checked_mul(Subtable0Pair::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(pairs_byte_len);
cursor.finish(Subtable0Marker { pairs_byte_len })
}
}
/// The type 0 `kern` subtable.
pub type Subtable0<'a> = TableRef<'a, Subtable0Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Subtable0<'a> {
/// The number of kerning pairs in this subtable.
pub fn n_pairs(&self) -> u16 {
let range = self.shape.n_pairs_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the subtable.
pub fn search_range(&self) -> u16 {
let range = self.shape.search_range_byte_range();
self.data.read_at(range.start).unwrap()
}
/// This is calculated as log2 of the largest power of two less than or equal to the value of nPairs. This value indicates how many iterations of the search loop have to be made. For example, in a list of eight items, there would be three iterations of the loop.
pub fn entry_selector(&self) -> u16 {
let range = self.shape.entry_selector_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The value of nPairs minus the largest power of two less than or equal to nPairs. This is multiplied by the size in bytes of an entry in the table.
pub fn range_shift(&self) -> u16 {
let range = self.shape.range_shift_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Kerning records.
pub fn pairs(&self) -> &'a [Subtable0Pair] {
let range = self.shape.pairs_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Subtable0<'a> {
fn type_name(&self) -> &str {
"Subtable0"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("n_pairs", self.n_pairs())),
1usize => Some(Field::new("search_range", self.search_range())),
2usize => Some(Field::new("entry_selector", self.entry_selector())),
3usize => Some(Field::new("range_shift", self.range_shift())),
4usize => Some(Field::new(
"pairs",
traversal::FieldType::array_of_records(
stringify!(Subtable0Pair),
self.pairs(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Subtable0<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Class table for the type 2 `kern` subtable.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Subtable2ClassTableMarker {
offsets_byte_len: usize,
}
impl Subtable2ClassTableMarker {
pub fn first_glyph_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + GlyphId16::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 offsets_byte_range(&self) -> Range<usize> {
let start = self.n_glyphs_byte_range().end;
start..start + self.offsets_byte_len
}
}
impl MinByteRange for Subtable2ClassTableMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.offsets_byte_range().end
}
}
impl<'a> FontRead<'a> for Subtable2ClassTable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<GlyphId16>();
let n_glyphs: u16 = cursor.read()?;
let offsets_byte_len = (n_glyphs as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(offsets_byte_len);
cursor.finish(Subtable2ClassTableMarker { offsets_byte_len })
}
}
/// Class table for the type 2 `kern` subtable.
pub type Subtable2ClassTable<'a> = TableRef<'a, Subtable2ClassTableMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Subtable2ClassTable<'a> {
/// First glyph in class range.
pub fn first_glyph(&self) -> GlyphId16 {
let range = self.shape.first_glyph_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of glyph in class range.
pub fn n_glyphs(&self) -> u16 {
let range = self.shape.n_glyphs_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The offsets array for all of the glyphs in the range.
pub fn offsets(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.offsets_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Subtable2ClassTable<'a> {
fn type_name(&self) -> &str {
"Subtable2ClassTable"
}
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("offsets", self.offsets())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Subtable2ClassTable<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The type 3 'kern' subtable.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Subtable3Marker {
kern_value_byte_len: usize,
left_class_byte_len: usize,
right_class_byte_len: usize,
kern_index_byte_len: usize,
}
impl Subtable3Marker {
pub fn glyph_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn kern_value_count_byte_range(&self) -> Range<usize> {
let start = self.glyph_count_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn left_class_count_byte_range(&self) -> Range<usize> {
let start = self.kern_value_count_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn right_class_count_byte_range(&self) -> Range<usize> {
let start = self.left_class_count_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.right_class_count_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn kern_value_byte_range(&self) -> Range<usize> {
let start = self.flags_byte_range().end;
start..start + self.kern_value_byte_len
}
pub fn left_class_byte_range(&self) -> Range<usize> {
let start = self.kern_value_byte_range().end;
start..start + self.left_class_byte_len
}
pub fn right_class_byte_range(&self) -> Range<usize> {
let start = self.left_class_byte_range().end;
start..start + self.right_class_byte_len
}
pub fn kern_index_byte_range(&self) -> Range<usize> {
let start = self.right_class_byte_range().end;
start..start + self.kern_index_byte_len
}
}
impl MinByteRange for Subtable3Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.kern_index_byte_range().end
}
}
impl<'a> FontRead<'a> for Subtable3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let glyph_count: u16 = cursor.read()?;
let kern_value_count: u8 = cursor.read()?;
let left_class_count: u8 = cursor.read()?;
let right_class_count: u8 = cursor.read()?;
cursor.advance::<u8>();
let kern_value_byte_len = (kern_value_count as usize)
.checked_mul(i16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(kern_value_byte_len);
let left_class_byte_len = (glyph_count as usize)
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(left_class_byte_len);
let right_class_byte_len = (glyph_count as usize)
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(right_class_byte_len);
let kern_index_byte_len =
(transforms::add_multiply(left_class_count, 0_usize, right_class_count))
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(kern_index_byte_len);
cursor.finish(Subtable3Marker {
kern_value_byte_len,
left_class_byte_len,
right_class_byte_len,
kern_index_byte_len,
})
}
}
/// The type 3 'kern' subtable.
pub type Subtable3<'a> = TableRef<'a, Subtable3Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Subtable3<'a> {
/// The number of glyphs in this font.
pub fn glyph_count(&self) -> u16 {
let range = self.shape.glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of kerning values.
pub fn kern_value_count(&self) -> u8 {
let range = self.shape.kern_value_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of left-hand classes.
pub fn left_class_count(&self) -> u8 {
let range = self.shape.left_class_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of right-hand classes.
pub fn right_class_count(&self) -> u8 {
let range = self.shape.right_class_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Set to zero (reserved for future use).
pub fn flags(&self) -> u8 {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The kerning values.
pub fn kern_value(&self) -> &'a [BigEndian<i16>] {
let range = self.shape.kern_value_byte_range();
self.data.read_array(range).unwrap()
}
/// The left-hand classes.
pub fn left_class(&self) -> &'a [u8] {
let range = self.shape.left_class_byte_range();
self.data.read_array(range).unwrap()
}
/// The right-hand classes.
pub fn right_class(&self) -> &'a [u8] {
let range = self.shape.right_class_byte_range();
self.data.read_array(range).unwrap()
}
/// The indices into the kernValue array.
pub fn kern_index(&self) -> &'a [u8] {
let range = self.shape.kern_index_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Subtable3<'a> {
fn type_name(&self) -> &str {
"Subtable3"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("glyph_count", self.glyph_count())),
1usize => Some(Field::new("kern_value_count", self.kern_value_count())),
2usize => Some(Field::new("left_class_count", self.left_class_count())),
3usize => Some(Field::new("right_class_count", self.right_class_count())),
4usize => Some(Field::new("flags", self.flags())),
5usize => Some(Field::new("kern_value", self.kern_value())),
6usize => Some(Field::new("left_class", self.left_class())),
7usize => Some(Field::new("right_class", self.right_class())),
8usize => Some(Field::new("kern_index", self.kern_index())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Subtable3<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,385 @@
// 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::*;
/// The [kerx (Extended Kerning)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct KerxMarker {
subtables_byte_len: usize,
}
impl KerxMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn padding_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn n_tables_byte_range(&self) -> Range<usize> {
let start = self.padding_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn subtables_byte_range(&self) -> Range<usize> {
let start = self.n_tables_byte_range().end;
start..start + self.subtables_byte_len
}
}
impl MinByteRange for KerxMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.subtables_byte_range().end
}
}
impl TopLevelTable for Kerx<'_> {
/// `kerx`
const TAG: Tag = Tag::new(b"kerx");
}
impl<'a> FontRead<'a> for Kerx<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
let n_tables: u32 = cursor.read()?;
let subtables_byte_len = {
let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?;
<Subtable as VarSize>::total_len_for_count(data, n_tables as usize)?
};
cursor.advance_by(subtables_byte_len);
cursor.finish(KerxMarker { subtables_byte_len })
}
}
/// The [kerx (Extended Kerning)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table.
pub type Kerx<'a> = TableRef<'a, KerxMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Kerx<'a> {
/// The version number of the extended kerning table (currently 2, 3, or 4)
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of subtables included in the extended kerning table.
pub fn n_tables(&self) -> u32 {
let range = self.shape.n_tables_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn subtables(&self) -> VarLenArray<'a, Subtable<'a>> {
let range = self.shape.subtables_byte_range();
VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Kerx<'a> {
fn type_name(&self) -> &str {
"Kerx"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("n_tables", self.n_tables())),
2usize => Some(Field::new(
"subtables",
traversal::FieldType::var_array("Subtable", self.subtables(), self.offset_data()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Kerx<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// A subtable in a `kerx` table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SubtableMarker {
data_byte_len: usize,
}
impl SubtableMarker {
pub fn length_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn coverage_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn tuple_count_byte_range(&self) -> Range<usize> {
let start = self.coverage_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn data_byte_range(&self) -> Range<usize> {
let start = self.tuple_count_byte_range().end;
start..start + self.data_byte_len
}
}
impl MinByteRange for SubtableMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.data_byte_range().end
}
}
impl<'a> FontRead<'a> for Subtable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u32>();
let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(data_byte_len);
cursor.finish(SubtableMarker { data_byte_len })
}
}
/// A subtable in a `kerx` table.
pub type Subtable<'a> = TableRef<'a, SubtableMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Subtable<'a> {
/// The length of this subtable in bytes, including this header.
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Circumstances under which this table is used.
pub fn coverage(&self) -> u32 {
let range = self.shape.coverage_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The tuple count. This value is only used with variation fonts and should be 0 for all other fonts. The subtable's tupleCount will be ignored if the 'kerx' table version is less than 4.
pub fn tuple_count(&self) -> u32 {
let range = self.shape.tuple_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Subtable specific data.
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 Subtable<'a> {
fn type_name(&self) -> &str {
"Subtable"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("length", self.length())),
1usize => Some(Field::new("coverage", self.coverage())),
2usize => Some(Field::new("tuple_count", self.tuple_count())),
3usize => Some(Field::new("data", self.data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Subtable<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The type 0 `kerx` subtable.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Subtable0Marker {
pairs_byte_len: usize,
}
impl Subtable0Marker {
pub fn n_pairs_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn search_range_byte_range(&self) -> Range<usize> {
let start = self.n_pairs_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn entry_selector_byte_range(&self) -> Range<usize> {
let start = self.search_range_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn range_shift_byte_range(&self) -> Range<usize> {
let start = self.entry_selector_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn pairs_byte_range(&self) -> Range<usize> {
let start = self.range_shift_byte_range().end;
start..start + self.pairs_byte_len
}
}
impl MinByteRange for Subtable0Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.pairs_byte_range().end
}
}
impl<'a> FontRead<'a> for Subtable0<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let n_pairs: u32 = cursor.read()?;
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u32>();
let pairs_byte_len = (n_pairs as usize)
.checked_mul(Subtable0Pair::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(pairs_byte_len);
cursor.finish(Subtable0Marker { pairs_byte_len })
}
}
/// The type 0 `kerx` subtable.
pub type Subtable0<'a> = TableRef<'a, Subtable0Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Subtable0<'a> {
/// The number of kerning pairs in this subtable.
pub fn n_pairs(&self) -> u32 {
let range = self.shape.n_pairs_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the subtable.
pub fn search_range(&self) -> u32 {
let range = self.shape.search_range_byte_range();
self.data.read_at(range.start).unwrap()
}
/// This is calculated as log2 of the largest power of two less than or equal to the value of nPairs. This value indicates how many iterations of the search loop have to be made. For example, in a list of eight items, there would be three iterations of the loop.
pub fn entry_selector(&self) -> u32 {
let range = self.shape.entry_selector_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The value of nPairs minus the largest power of two less than or equal to nPairs. This is multiplied by the size in bytes of an entry in the table.
pub fn range_shift(&self) -> u32 {
let range = self.shape.range_shift_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Kerning records.
pub fn pairs(&self) -> &'a [Subtable0Pair] {
let range = self.shape.pairs_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Subtable0<'a> {
fn type_name(&self) -> &str {
"Subtable0"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("n_pairs", self.n_pairs())),
1usize => Some(Field::new("search_range", self.search_range())),
2usize => Some(Field::new("entry_selector", self.entry_selector())),
3usize => Some(Field::new("range_shift", self.range_shift())),
4usize => Some(Field::new(
"pairs",
traversal::FieldType::array_of_records(
stringify!(Subtable0Pair),
self.pairs(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Subtable0<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The type 0 `kerx` subtable kerning record.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct Subtable0Pair {
/// The glyph index for the lefthand glyph in the kerning pair.
pub left: BigEndian<GlyphId16>,
/// The glyph index for the righthand glyph in the kerning pair.
pub right: BigEndian<GlyphId16>,
/// Kerning value.
pub value: BigEndian<i16>,
}
impl Subtable0Pair {
/// The glyph index for the lefthand glyph in the kerning pair.
pub fn left(&self) -> GlyphId16 {
self.left.get()
}
/// The glyph index for the righthand glyph in the kerning pair.
pub fn right(&self) -> GlyphId16 {
self.right.get()
}
/// Kerning value.
pub fn value(&self) -> i16 {
self.value.get()
}
}
impl FixedSize for Subtable0Pair {
const RAW_BYTE_LEN: usize =
GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for Subtable0Pair {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "Subtable0Pair",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("left", self.left())),
1usize => Some(Field::new("right", self.right())),
2usize => Some(Field::new("value", self.value())),
_ => None,
}),
data,
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
// 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::*;
/// The [language tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct LtagMarker {
tag_ranges_byte_len: usize,
}
impl LtagMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn num_tags_byte_range(&self) -> Range<usize> {
let start = self.flags_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn tag_ranges_byte_range(&self) -> Range<usize> {
let start = self.num_tags_byte_range().end;
start..start + self.tag_ranges_byte_len
}
}
impl MinByteRange for LtagMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.tag_ranges_byte_range().end
}
}
impl TopLevelTable for Ltag<'_> {
/// `ltag`
const TAG: Tag = Tag::new(b"ltag");
}
impl<'a> FontRead<'a> for Ltag<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
cursor.advance::<u32>();
let num_tags: u32 = cursor.read()?;
let tag_ranges_byte_len = (num_tags as usize)
.checked_mul(FTStringRange::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(tag_ranges_byte_len);
cursor.finish(LtagMarker {
tag_ranges_byte_len,
})
}
}
/// The [language tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html) table.
pub type Ltag<'a> = TableRef<'a, LtagMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Ltag<'a> {
/// Table version; currently 1.
pub fn version(&self) -> u32 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Table flags; currently none defined.
pub fn flags(&self) -> u32 {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of language tags which follow.
pub fn num_tags(&self) -> u32 {
let range = self.shape.num_tags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Range of each tag's string.
pub fn tag_ranges(&self) -> &'a [FTStringRange] {
let range = self.shape.tag_ranges_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Ltag<'a> {
fn type_name(&self) -> &str {
"Ltag"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("flags", self.flags())),
2usize => Some(Field::new("num_tags", self.num_tags())),
3usize => Some(Field::new(
"tag_ranges",
traversal::FieldType::array_of_records(
stringify!(FTStringRange),
self.tag_ranges(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Ltag<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Offset and length of string in `ltag` table.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct FTStringRange {
/// Offset from the start of the table to the beginning of the string.
pub offset: BigEndian<u16>,
/// String length (in bytes).
pub length: BigEndian<u16>,
}
impl FTStringRange {
/// Offset from the start of the table to the beginning of the string.
pub fn offset(&self) -> u16 {
self.offset.get()
}
/// String length (in bytes).
pub fn length(&self) -> u16 {
self.length.get()
}
}
impl FixedSize for FTStringRange {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for FTStringRange {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "FTStringRange",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("offset", self.offset())),
1usize => Some(Field::new("length", self.length())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,398 @@
// 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::*;
/// [`maxp`](https://docs.microsoft.com/en-us/typography/opentype/spec/maxp)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct MaxpMarker {
max_points_byte_start: Option<usize>,
max_contours_byte_start: Option<usize>,
max_composite_points_byte_start: Option<usize>,
max_composite_contours_byte_start: Option<usize>,
max_zones_byte_start: Option<usize>,
max_twilight_points_byte_start: Option<usize>,
max_storage_byte_start: Option<usize>,
max_function_defs_byte_start: Option<usize>,
max_instruction_defs_byte_start: Option<usize>,
max_stack_elements_byte_start: Option<usize>,
max_size_of_instructions_byte_start: Option<usize>,
max_component_elements_byte_start: Option<usize>,
max_component_depth_byte_start: Option<usize>,
}
impl MaxpMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + Version16Dot16::RAW_BYTE_LEN
}
pub fn num_glyphs_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn max_points_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_points_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_contours_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_contours_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_composite_points_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_composite_points_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_composite_contours_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_composite_contours_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_zones_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_zones_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_twilight_points_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_twilight_points_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_storage_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_storage_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_function_defs_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_function_defs_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_instruction_defs_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_instruction_defs_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_stack_elements_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_stack_elements_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_size_of_instructions_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_size_of_instructions_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_component_elements_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_component_elements_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn max_component_depth_byte_range(&self) -> Option<Range<usize>> {
let start = self.max_component_depth_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
}
impl MinByteRange for MaxpMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.num_glyphs_byte_range().end
}
}
impl TopLevelTable for Maxp<'_> {
/// `maxp`
const TAG: Tag = Tag::new(b"maxp");
}
impl<'a> FontRead<'a> for Maxp<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: Version16Dot16 = cursor.read()?;
cursor.advance::<u16>();
let max_points_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_contours_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_composite_points_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_composite_contours_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_zones_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_twilight_points_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_storage_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_function_defs_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_instruction_defs_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_stack_elements_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_size_of_instructions_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_component_elements_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
let max_component_depth_byte_start = version
.compatible((1u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 0u16))
.then(|| cursor.advance::<u16>());
cursor.finish(MaxpMarker {
max_points_byte_start,
max_contours_byte_start,
max_composite_points_byte_start,
max_composite_contours_byte_start,
max_zones_byte_start,
max_twilight_points_byte_start,
max_storage_byte_start,
max_function_defs_byte_start,
max_instruction_defs_byte_start,
max_stack_elements_byte_start,
max_size_of_instructions_byte_start,
max_component_elements_byte_start,
max_component_depth_byte_start,
})
}
}
/// [`maxp`](https://docs.microsoft.com/en-us/typography/opentype/spec/maxp)
pub type Maxp<'a> = TableRef<'a, MaxpMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Maxp<'a> {
/// The version: 0x00005000 for version 0.5, 0x00010000 for version 1.0.
pub fn version(&self) -> Version16Dot16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of glyphs in the font.
pub fn num_glyphs(&self) -> u16 {
let range = self.shape.num_glyphs_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Maximum points in a non-composite glyph.
pub fn max_points(&self) -> Option<u16> {
let range = self.shape.max_points_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum contours in a non-composite glyph.
pub fn max_contours(&self) -> Option<u16> {
let range = self.shape.max_contours_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum points in a composite glyph.
pub fn max_composite_points(&self) -> Option<u16> {
let range = self.shape.max_composite_points_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum contours in a composite glyph.
pub fn max_composite_contours(&self) -> Option<u16> {
let range = self.shape.max_composite_contours_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// 1 if instructions do not use the twilight zone (Z0), or 2 if
/// instructions do use Z0; should be set to 2 in most cases.
pub fn max_zones(&self) -> Option<u16> {
let range = self.shape.max_zones_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum points used in Z0.
pub fn max_twilight_points(&self) -> Option<u16> {
let range = self.shape.max_twilight_points_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Number of Storage Area locations.
pub fn max_storage(&self) -> Option<u16> {
let range = self.shape.max_storage_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Number of FDEFs, equal to the highest function number + 1.
pub fn max_function_defs(&self) -> Option<u16> {
let range = self.shape.max_function_defs_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Number of IDEFs.
pub fn max_instruction_defs(&self) -> Option<u16> {
let range = self.shape.max_instruction_defs_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum stack depth across Font Program ('fpgm' table), CVT
/// Program ('prep' table) and all glyph instructions (in the
/// 'glyf' table).
pub fn max_stack_elements(&self) -> Option<u16> {
let range = self.shape.max_stack_elements_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum byte count for glyph instructions.
pub fn max_size_of_instructions(&self) -> Option<u16> {
let range = self.shape.max_size_of_instructions_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum number of components referenced at “top level” for
/// any composite glyph.
pub fn max_component_elements(&self) -> Option<u16> {
let range = self.shape.max_component_elements_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Maximum levels of recursion; 1 for simple components.
pub fn max_component_depth(&self) -> Option<u16> {
let range = self.shape.max_component_depth_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Maxp<'a> {
fn type_name(&self) -> &str {
"Maxp"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("num_glyphs", self.num_glyphs())),
2usize if version.compatible((1u16, 0u16)) => {
Some(Field::new("max_points", self.max_points().unwrap()))
}
3usize if version.compatible((1u16, 0u16)) => {
Some(Field::new("max_contours", self.max_contours().unwrap()))
}
4usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_composite_points",
self.max_composite_points().unwrap(),
)),
5usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_composite_contours",
self.max_composite_contours().unwrap(),
)),
6usize if version.compatible((1u16, 0u16)) => {
Some(Field::new("max_zones", self.max_zones().unwrap()))
}
7usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_twilight_points",
self.max_twilight_points().unwrap(),
)),
8usize if version.compatible((1u16, 0u16)) => {
Some(Field::new("max_storage", self.max_storage().unwrap()))
}
9usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_function_defs",
self.max_function_defs().unwrap(),
)),
10usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_instruction_defs",
self.max_instruction_defs().unwrap(),
)),
11usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_stack_elements",
self.max_stack_elements().unwrap(),
)),
12usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_size_of_instructions",
self.max_size_of_instructions().unwrap(),
)),
13usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_component_elements",
self.max_component_elements().unwrap(),
)),
14usize if version.compatible((1u16, 0u16)) => Some(Field::new(
"max_component_depth",
self.max_component_depth().unwrap(),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Maxp<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,186 @@
// 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::*;
/// [`meta`](https://docs.microsoft.com/en-us/typography/opentype/spec/meta)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct MetaMarker {
data_maps_byte_len: usize,
}
impl MetaMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn reserved_byte_range(&self) -> Range<usize> {
let start = self.flags_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn data_maps_count_byte_range(&self) -> Range<usize> {
let start = self.reserved_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn data_maps_byte_range(&self) -> Range<usize> {
let start = self.data_maps_count_byte_range().end;
start..start + self.data_maps_byte_len
}
}
impl MinByteRange for MetaMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.data_maps_byte_range().end
}
}
impl TopLevelTable for Meta<'_> {
/// `meta`
const TAG: Tag = Tag::new(b"meta");
}
impl<'a> FontRead<'a> for Meta<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u32>();
let data_maps_count: u32 = cursor.read()?;
let data_maps_byte_len = (data_maps_count as usize)
.checked_mul(DataMapRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(data_maps_byte_len);
cursor.finish(MetaMarker { data_maps_byte_len })
}
}
/// [`meta`](https://docs.microsoft.com/en-us/typography/opentype/spec/meta)
pub type Meta<'a> = TableRef<'a, MetaMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Meta<'a> {
/// Version number of the metadata table — set to 1.
pub fn version(&self) -> u32 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Flags — currently unused; set to 0.
pub fn flags(&self) -> u32 {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of data maps in the table.
pub fn data_maps_count(&self) -> u32 {
let range = self.shape.data_maps_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Array of data map records.
pub fn data_maps(&self) -> &'a [DataMapRecord] {
let range = self.shape.data_maps_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Meta<'a> {
fn type_name(&self) -> &str {
"Meta"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("flags", self.flags())),
2usize => Some(Field::new("data_maps_count", self.data_maps_count())),
3usize => Some(Field::new(
"data_maps",
traversal::FieldType::array_of_records(
stringify!(DataMapRecord),
self.data_maps(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Meta<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/meta#table-formats>
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct DataMapRecord {
/// A tag indicating the type of metadata.
pub tag: BigEndian<Tag>,
/// Offset in bytes from the beginning of the metadata table to the data for this tag.
pub data_offset: BigEndian<Offset32>,
/// Length of the data, in bytes. The data is not required to be padded to any byte boundary.
pub data_length: BigEndian<u32>,
}
impl DataMapRecord {
/// A tag indicating the type of metadata.
pub fn tag(&self) -> Tag {
self.tag.get()
}
/// Offset in bytes from the beginning of the metadata table to the data for this tag.
pub fn data_offset(&self) -> Offset32 {
self.data_offset.get()
}
/// Offset in bytes from the beginning of the metadata table to the data for this tag.
///
/// The `data` argument should be retrieved from the parent table
/// By calling its `offset_data` method.
pub fn data<'a>(&self, data: FontData<'a>) -> Result<Metadata<'a>, ReadError> {
let args = (self.tag(), self.data_length());
self.data_offset().resolve_with_args(data, &args)
}
/// Length of the data, in bytes. The data is not required to be padded to any byte boundary.
pub fn data_length(&self) -> u32 {
self.data_length.get()
}
}
impl FixedSize for DataMapRecord {
const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for DataMapRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "DataMapRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("tag", self.tag())),
1usize => Some(Field::new("data_offset", traversal::FieldType::Unknown)),
2usize => Some(Field::new("data_length", self.data_length())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,521 @@
// 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::*;
/// The [morx (Extended Glyph Metamorphosis)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct MorxMarker {
chains_byte_len: usize,
}
impl MorxMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn unused_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn n_chains_byte_range(&self) -> Range<usize> {
let start = self.unused_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn chains_byte_range(&self) -> Range<usize> {
let start = self.n_chains_byte_range().end;
start..start + self.chains_byte_len
}
}
impl MinByteRange for MorxMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.chains_byte_range().end
}
}
impl TopLevelTable for Morx<'_> {
/// `morx`
const TAG: Tag = Tag::new(b"morx");
}
impl<'a> FontRead<'a> for Morx<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
let n_chains: u32 = cursor.read()?;
let chains_byte_len = {
let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?;
<Chain as VarSize>::total_len_for_count(data, n_chains as usize)?
};
cursor.advance_by(chains_byte_len);
cursor.finish(MorxMarker { chains_byte_len })
}
}
/// The [morx (Extended Glyph Metamorphosis)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table.
pub type Morx<'a> = TableRef<'a, MorxMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Morx<'a> {
/// Version number of the extended glyph metamorphosis table (either 2 or 3).
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of metamorphosis chains contained in this table.
pub fn n_chains(&self) -> u32 {
let range = self.shape.n_chains_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn chains(&self) -> VarLenArray<'a, Chain<'a>> {
let range = self.shape.chains_byte_range();
VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Morx<'a> {
fn type_name(&self) -> &str {
"Morx"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("n_chains", self.n_chains())),
2usize => Some(Field::new(
"chains",
traversal::FieldType::var_array("Chain", self.chains(), self.offset_data()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Morx<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// A chain in a `morx` table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ChainMarker {
features_byte_len: usize,
subtables_byte_len: usize,
}
impl ChainMarker {
pub fn default_flags_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn chain_length_byte_range(&self) -> Range<usize> {
let start = self.default_flags_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn n_feature_entries_byte_range(&self) -> Range<usize> {
let start = self.chain_length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn n_subtables_byte_range(&self) -> Range<usize> {
let start = self.n_feature_entries_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn features_byte_range(&self) -> Range<usize> {
let start = self.n_subtables_byte_range().end;
start..start + self.features_byte_len
}
pub fn subtables_byte_range(&self) -> Range<usize> {
let start = self.features_byte_range().end;
start..start + self.subtables_byte_len
}
}
impl MinByteRange for ChainMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.subtables_byte_range().end
}
}
impl<'a> FontRead<'a> for Chain<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
cursor.advance::<u32>();
let n_feature_entries: u32 = cursor.read()?;
let n_subtables: u32 = cursor.read()?;
let features_byte_len = (n_feature_entries as usize)
.checked_mul(Feature::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(features_byte_len);
let subtables_byte_len = {
let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?;
<Subtable as VarSize>::total_len_for_count(data, n_subtables as usize)?
};
cursor.advance_by(subtables_byte_len);
cursor.finish(ChainMarker {
features_byte_len,
subtables_byte_len,
})
}
}
/// A chain in a `morx` table.
pub type Chain<'a> = TableRef<'a, ChainMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Chain<'a> {
/// The default specification for subtables.
pub fn default_flags(&self) -> u32 {
let range = self.shape.default_flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Total byte count, including this header; must be a multiple of 4.
pub fn chain_length(&self) -> u32 {
let range = self.shape.chain_length_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of feature subtable entries.
pub fn n_feature_entries(&self) -> u32 {
let range = self.shape.n_feature_entries_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of subtables in the chain.
pub fn n_subtables(&self) -> u32 {
let range = self.shape.n_subtables_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Feature entries for this chain.
pub fn features(&self) -> &'a [Feature] {
let range = self.shape.features_byte_range();
self.data.read_array(range).unwrap()
}
/// Array of chain subtables.
pub fn subtables(&self) -> VarLenArray<'a, Subtable<'a>> {
let range = self.shape.subtables_byte_range();
VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Chain<'a> {
fn type_name(&self) -> &str {
"Chain"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("default_flags", self.default_flags())),
1usize => Some(Field::new("chain_length", self.chain_length())),
2usize => Some(Field::new("n_feature_entries", self.n_feature_entries())),
3usize => Some(Field::new("n_subtables", self.n_subtables())),
4usize => Some(Field::new(
"features",
traversal::FieldType::array_of_records(
stringify!(Feature),
self.features(),
self.offset_data(),
),
)),
5usize => Some(Field::new(
"subtables",
traversal::FieldType::var_array("Subtable", self.subtables(), self.offset_data()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Chain<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Used to compute the sub-feature flags for a list of requested features and settings.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct Feature {
/// The type of feature.
pub feature_type: BigEndian<u16>,
/// The feature's setting (aka selector).
pub feature_settings: BigEndian<u16>,
/// Flags for the settings that this feature and setting enables.
pub enable_flags: BigEndian<u32>,
/// Complement of flags for the settings that this feature and setting disable.
pub disable_flags: BigEndian<u32>,
}
impl Feature {
/// The type of feature.
pub fn feature_type(&self) -> u16 {
self.feature_type.get()
}
/// The feature's setting (aka selector).
pub fn feature_settings(&self) -> u16 {
self.feature_settings.get()
}
/// Flags for the settings that this feature and setting enables.
pub fn enable_flags(&self) -> u32 {
self.enable_flags.get()
}
/// Complement of flags for the settings that this feature and setting disable.
pub fn disable_flags(&self) -> u32 {
self.disable_flags.get()
}
}
impl FixedSize for Feature {
const RAW_BYTE_LEN: usize =
u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for Feature {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "Feature",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("feature_type", self.feature_type())),
1usize => Some(Field::new("feature_settings", self.feature_settings())),
2usize => Some(Field::new("enable_flags", self.enable_flags())),
3usize => Some(Field::new("disable_flags", self.disable_flags())),
_ => None,
}),
data,
}
}
}
/// A subtable in a `morx` chain.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SubtableMarker {
data_byte_len: usize,
}
impl SubtableMarker {
pub fn length_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn coverage_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn sub_feature_flags_byte_range(&self) -> Range<usize> {
let start = self.coverage_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn data_byte_range(&self) -> Range<usize> {
let start = self.sub_feature_flags_byte_range().end;
start..start + self.data_byte_len
}
}
impl MinByteRange for SubtableMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.data_byte_range().end
}
}
impl<'a> FontRead<'a> for Subtable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u32>();
let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(data_byte_len);
cursor.finish(SubtableMarker { data_byte_len })
}
}
/// A subtable in a `morx` chain.
pub type Subtable<'a> = TableRef<'a, SubtableMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Subtable<'a> {
/// Total subtable length, including this header.
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Coverage flags and subtable type.
pub fn coverage(&self) -> u32 {
let range = self.shape.coverage_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The 32-bit mask identifying which subtable this is (the subtable being executed if the AND of this value and the processed defaultFlags is nonzero).
pub fn sub_feature_flags(&self) -> u32 {
let range = self.shape.sub_feature_flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Data for specific subtable.
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 Subtable<'a> {
fn type_name(&self) -> &str {
"Subtable"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("length", self.length())),
1usize => Some(Field::new("coverage", self.coverage())),
2usize => Some(Field::new("sub_feature_flags", self.sub_feature_flags())),
3usize => Some(Field::new("data", self.data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Subtable<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Entry payload in a contextual subtable state machine.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ContextualEntryData {
/// Index of the substitution table for the marked glyph (use 0xFFFF for
/// none).
pub mark_index: BigEndian<u16>,
/// Index of the substitution table for the current glyph (use 0xFFFF for
/// none)
pub current_index: BigEndian<u16>,
}
impl ContextualEntryData {
/// Index of the substitution table for the marked glyph (use 0xFFFF for
/// none).
pub fn mark_index(&self) -> u16 {
self.mark_index.get()
}
/// Index of the substitution table for the current glyph (use 0xFFFF for
/// none)
pub fn current_index(&self) -> u16 {
self.current_index.get()
}
}
impl FixedSize for ContextualEntryData {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ContextualEntryData {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ContextualEntryData",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("mark_index", self.mark_index())),
1usize => Some(Field::new("current_index", self.current_index())),
_ => None,
}),
data,
}
}
}
/// Entry payload in an insertion subtable state machine.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct InsertionEntryData {
/// Zero-based index into the insertion glyph table. The number of glyphs
/// to be inserted is contained in the currentInsertCount field in the
/// flags (see below). A value of 0xFFFF indicates no insertion is to be done.
pub current_insert_index: BigEndian<u16>,
/// Zero-based index into the insertion glyph table. The number of glyphs
/// to be inserted is contained in the markedInsertCount field in the
/// flags (see below). A value of 0xFFFF indicates no insertion is to be
/// done.
pub marked_insert_index: BigEndian<u16>,
}
impl InsertionEntryData {
/// Zero-based index into the insertion glyph table. The number of glyphs
/// to be inserted is contained in the currentInsertCount field in the
/// flags (see below). A value of 0xFFFF indicates no insertion is to be done.
pub fn current_insert_index(&self) -> u16 {
self.current_insert_index.get()
}
/// Zero-based index into the insertion glyph table. The number of glyphs
/// to be inserted is contained in the markedInsertCount field in the
/// flags (see below). A value of 0xFFFF indicates no insertion is to be
/// done.
pub fn marked_insert_index(&self) -> u16 {
self.marked_insert_index.get()
}
}
impl FixedSize for InsertionEntryData {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for InsertionEntryData {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "InsertionEntryData",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new(
"current_insert_index",
self.current_insert_index(),
)),
1usize => Some(Field::new(
"marked_insert_index",
self.marked_insert_index(),
)),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,211 @@
// 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::*;
/// The [MVAR (Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct MvarMarker {
value_records_byte_len: usize,
}
impl MvarMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn _reserved_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn value_record_size_byte_range(&self) -> Range<usize> {
let start = self._reserved_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn value_record_count_byte_range(&self) -> Range<usize> {
let start = self.value_record_size_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn item_variation_store_offset_byte_range(&self) -> Range<usize> {
let start = self.value_record_count_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn value_records_byte_range(&self) -> Range<usize> {
let start = self.item_variation_store_offset_byte_range().end;
start..start + self.value_records_byte_len
}
}
impl MinByteRange for MvarMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.value_records_byte_range().end
}
}
impl TopLevelTable for Mvar<'_> {
/// `MVAR`
const TAG: Tag = Tag::new(b"MVAR");
}
impl<'a> FontRead<'a> for Mvar<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let value_record_count: u16 = cursor.read()?;
cursor.advance::<Offset16>();
let value_records_byte_len = (value_record_count as usize)
.checked_mul(ValueRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(value_records_byte_len);
cursor.finish(MvarMarker {
value_records_byte_len,
})
}
}
/// The [MVAR (Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar) table
pub type Mvar<'a> = TableRef<'a, MvarMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Mvar<'a> {
/// Major version number of the horizontal metrics variations table — set to 1.
/// Minor version number of the horizontal metrics variations table — set to 0.
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The size in bytes of each value record — must be greater than zero.
pub fn value_record_size(&self) -> u16 {
let range = self.shape.value_record_size_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of value records — may be zero.
pub fn value_record_count(&self) -> u16 {
let range = self.shape.value_record_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset in bytes from the start of this table to the item variation store table. If valueRecordCount is zero, set to zero; if valueRecordCount is greater than zero, must be greater than zero.
pub fn item_variation_store_offset(&self) -> Nullable<Offset16> {
let range = self.shape.item_variation_store_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset].
pub fn item_variation_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
let data = self.data;
self.item_variation_store_offset().resolve(data)
}
/// Array of value records that identify target items and the associated delta-set index for each. The valueTag records must be in binary order of their valueTag field.
pub fn value_records(&self) -> &'a [ValueRecord] {
let range = self.shape.value_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Mvar<'a> {
fn type_name(&self) -> &str {
"Mvar"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("value_record_size", self.value_record_size())),
2usize => Some(Field::new("value_record_count", self.value_record_count())),
3usize => Some(Field::new(
"item_variation_store_offset",
FieldType::offset(
self.item_variation_store_offset(),
self.item_variation_store(),
),
)),
4usize => Some(Field::new(
"value_records",
traversal::FieldType::array_of_records(
stringify!(ValueRecord),
self.value_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Mvar<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// [ValueRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/mvar#table-formats) metrics variation record
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ValueRecord {
/// Four-byte tag identifying a font-wide measure.
pub value_tag: BigEndian<Tag>,
/// A delta-set outer index — used to select an item variation data subtable within the item variation store.
pub delta_set_outer_index: BigEndian<u16>,
/// A delta-set inner index — used to select a delta-set row within an item variation data subtable.
pub delta_set_inner_index: BigEndian<u16>,
}
impl ValueRecord {
/// Four-byte tag identifying a font-wide measure.
pub fn value_tag(&self) -> Tag {
self.value_tag.get()
}
/// A delta-set outer index — used to select an item variation data subtable within the item variation store.
pub fn delta_set_outer_index(&self) -> u16 {
self.delta_set_outer_index.get()
}
/// A delta-set inner index — used to select a delta-set row within an item variation data subtable.
pub fn delta_set_inner_index(&self) -> u16 {
self.delta_set_inner_index.get()
}
}
impl FixedSize for ValueRecord {
const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ValueRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ValueRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("value_tag", self.value_tag())),
1usize => Some(Field::new(
"delta_set_outer_index",
self.delta_set_outer_index(),
)),
2usize => Some(Field::new(
"delta_set_inner_index",
self.delta_set_inner_index(),
)),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,307 @@
// 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::*;
/// [Naming table version 1](https://docs.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-1)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct NameMarker {
name_record_byte_len: usize,
lang_tag_count_byte_start: Option<usize>,
lang_tag_record_byte_start: Option<usize>,
lang_tag_record_byte_len: Option<usize>,
}
impl NameMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn storage_offset_byte_range(&self) -> Range<usize> {
let start = self.count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn name_record_byte_range(&self) -> Range<usize> {
let start = self.storage_offset_byte_range().end;
start..start + self.name_record_byte_len
}
pub fn lang_tag_count_byte_range(&self) -> Option<Range<usize>> {
let start = self.lang_tag_count_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn lang_tag_record_byte_range(&self) -> Option<Range<usize>> {
let start = self.lang_tag_record_byte_start?;
Some(start..start + self.lang_tag_record_byte_len?)
}
}
impl MinByteRange for NameMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.name_record_byte_range().end
}
}
impl TopLevelTable for Name<'_> {
/// `name`
const TAG: Tag = Tag::new(b"name");
}
impl<'a> FontRead<'a> for Name<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: u16 = cursor.read()?;
let count: u16 = cursor.read()?;
cursor.advance::<u16>();
let name_record_byte_len = (count as usize)
.checked_mul(NameRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(name_record_byte_len);
let lang_tag_count_byte_start = version
.compatible(1u16)
.then(|| cursor.position())
.transpose()?;
let lang_tag_count = version
.compatible(1u16)
.then(|| cursor.read::<u16>())
.transpose()?
.unwrap_or_default();
let lang_tag_record_byte_start = version
.compatible(1u16)
.then(|| cursor.position())
.transpose()?;
let lang_tag_record_byte_len = version.compatible(1u16).then_some(
(lang_tag_count as usize)
.checked_mul(LangTagRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
);
if let Some(value) = lang_tag_record_byte_len {
cursor.advance_by(value);
}
cursor.finish(NameMarker {
name_record_byte_len,
lang_tag_count_byte_start,
lang_tag_record_byte_start,
lang_tag_record_byte_len,
})
}
}
/// [Naming table version 1](https://docs.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-1)
pub type Name<'a> = TableRef<'a, NameMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Name<'a> {
/// Table version number (0 or 1)
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of name records.
pub fn count(&self) -> u16 {
let range = self.shape.count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset to start of string storage (from start of table).
pub fn storage_offset(&self) -> u16 {
let range = self.shape.storage_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The name records where count is the number of records.
pub fn name_record(&self) -> &'a [NameRecord] {
let range = self.shape.name_record_byte_range();
self.data.read_array(range).unwrap()
}
/// Number of language-tag records.
pub fn lang_tag_count(&self) -> Option<u16> {
let range = self.shape.lang_tag_count_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// The language-tag records where langTagCount is the number of records.
pub fn lang_tag_record(&self) -> Option<&'a [LangTagRecord]> {
let range = self.shape.lang_tag_record_byte_range()?;
Some(self.data.read_array(range).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Name<'a> {
fn type_name(&self) -> &str {
"Name"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("count", self.count())),
2usize => Some(Field::new("storage_offset", self.storage_offset())),
3usize => Some(Field::new(
"name_record",
traversal::FieldType::array_of_records(
stringify!(NameRecord),
self.name_record(),
self.string_data(),
),
)),
4usize if version.compatible(1u16) => {
Some(Field::new("lang_tag_count", self.lang_tag_count().unwrap()))
}
5usize if version.compatible(1u16) => Some(Field::new(
"lang_tag_record",
traversal::FieldType::array_of_records(
stringify!(LangTagRecord),
self.lang_tag_record().unwrap(),
self.string_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Name<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Part of [Name]
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct LangTagRecord {
/// Language-tag string length (in bytes)
pub length: BigEndian<u16>,
/// Language-tag string offset from start of storage area (in
/// bytes).
pub lang_tag_offset: BigEndian<Offset16>,
}
impl LangTagRecord {
/// Language-tag string length (in bytes)
pub fn length(&self) -> u16 {
self.length.get()
}
/// Language-tag string offset from start of storage area (in
/// bytes).
pub fn lang_tag_offset(&self) -> Offset16 {
self.lang_tag_offset.get()
}
}
impl FixedSize for LangTagRecord {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for LangTagRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "LangTagRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("length", self.length())),
1usize => Some(Field::new("lang_tag_offset", self.traverse_lang_tag(_data))),
_ => None,
}),
data,
}
}
}
///[Name Records](https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-records)
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct NameRecord {
/// Platform ID.
pub platform_id: BigEndian<u16>,
/// Platform-specific encoding ID.
pub encoding_id: BigEndian<u16>,
/// Language ID.
pub language_id: BigEndian<u16>,
/// Name ID.
pub name_id: BigEndian<NameId>,
/// String length (in bytes).
pub length: BigEndian<u16>,
/// String offset from start of storage area (in bytes).
pub string_offset: BigEndian<Offset16>,
}
impl NameRecord {
/// Platform ID.
pub fn platform_id(&self) -> u16 {
self.platform_id.get()
}
/// Platform-specific encoding ID.
pub fn encoding_id(&self) -> u16 {
self.encoding_id.get()
}
/// Language ID.
pub fn language_id(&self) -> u16 {
self.language_id.get()
}
/// Name ID.
pub fn name_id(&self) -> NameId {
self.name_id.get()
}
/// String length (in bytes).
pub fn length(&self) -> u16 {
self.length.get()
}
/// String offset from start of storage area (in bytes).
pub fn string_offset(&self) -> Offset16 {
self.string_offset.get()
}
}
impl FixedSize for NameRecord {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ NameId::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ Offset16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for NameRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "NameRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("platform_id", self.platform_id())),
1usize => Some(Field::new("encoding_id", self.encoding_id())),
2usize => Some(Field::new("language_id", self.language_id())),
3usize => Some(Field::new("name_id", self.name_id())),
4usize => Some(Field::new("length", self.length())),
5usize => Some(Field::new("string_offset", self.traverse_string(_data))),
_ => None,
}),
data,
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,281 @@
// 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::*;
/// [post (PostScript)](https://docs.microsoft.com/en-us/typography/opentype/spec/post#header) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct PostMarker {
num_glyphs_byte_start: Option<usize>,
glyph_name_index_byte_start: Option<usize>,
glyph_name_index_byte_len: Option<usize>,
string_data_byte_start: Option<usize>,
string_data_byte_len: Option<usize>,
}
impl PostMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + Version16Dot16::RAW_BYTE_LEN
}
pub fn italic_angle_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Fixed::RAW_BYTE_LEN
}
pub fn underline_position_byte_range(&self) -> Range<usize> {
let start = self.italic_angle_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn underline_thickness_byte_range(&self) -> Range<usize> {
let start = self.underline_position_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn is_fixed_pitch_byte_range(&self) -> Range<usize> {
let start = self.underline_thickness_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn min_mem_type42_byte_range(&self) -> Range<usize> {
let start = self.is_fixed_pitch_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn max_mem_type42_byte_range(&self) -> Range<usize> {
let start = self.min_mem_type42_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn min_mem_type1_byte_range(&self) -> Range<usize> {
let start = self.max_mem_type42_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn max_mem_type1_byte_range(&self) -> Range<usize> {
let start = self.min_mem_type1_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn num_glyphs_byte_range(&self) -> Option<Range<usize>> {
let start = self.num_glyphs_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn glyph_name_index_byte_range(&self) -> Option<Range<usize>> {
let start = self.glyph_name_index_byte_start?;
Some(start..start + self.glyph_name_index_byte_len?)
}
pub fn string_data_byte_range(&self) -> Option<Range<usize>> {
let start = self.string_data_byte_start?;
Some(start..start + self.string_data_byte_len?)
}
}
impl MinByteRange for PostMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.max_mem_type1_byte_range().end
}
}
impl TopLevelTable for Post<'_> {
/// `post`
const TAG: Tag = Tag::new(b"post");
}
impl<'a> FontRead<'a> for Post<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: Version16Dot16 = cursor.read()?;
cursor.advance::<Fixed>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u32>();
cursor.advance::<u32>();
let num_glyphs_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
let num_glyphs = version
.compatible((2u16, 0u16))
.then(|| cursor.read::<u16>())
.transpose()?
.unwrap_or_default();
let glyph_name_index_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
let glyph_name_index_byte_len = version.compatible((2u16, 0u16)).then_some(
(num_glyphs as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
);
if let Some(value) = glyph_name_index_byte_len {
cursor.advance_by(value);
}
let string_data_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
let string_data_byte_len = version
.compatible((2u16, 0u16))
.then_some(cursor.remaining_bytes());
if let Some(value) = string_data_byte_len {
cursor.advance_by(value);
}
cursor.finish(PostMarker {
num_glyphs_byte_start,
glyph_name_index_byte_start,
glyph_name_index_byte_len,
string_data_byte_start,
string_data_byte_len,
})
}
}
/// [post (PostScript)](https://docs.microsoft.com/en-us/typography/opentype/spec/post#header) table
pub type Post<'a> = TableRef<'a, PostMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Post<'a> {
/// 0x00010000 for version 1.0 0x00020000 for version 2.0
/// 0x00025000 for version 2.5 (deprecated) 0x00030000 for version
/// 3.0
pub fn version(&self) -> Version16Dot16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Italic angle in counter-clockwise degrees from the vertical.
/// Zero for upright text, negative for text that leans to the
/// right (forward).
pub fn italic_angle(&self) -> Fixed {
let range = self.shape.italic_angle_byte_range();
self.data.read_at(range.start).unwrap()
}
/// This is the suggested distance of the top of the underline from
/// the baseline (negative values indicate below baseline). The
/// PostScript definition of this FontInfo dictionary key (the y
/// coordinate of the center of the stroke) is not used for
/// historical reasons. The value of the PostScript key may be
/// calculated by subtracting half the underlineThickness from the
/// value of this field.
pub fn underline_position(&self) -> FWord {
let range = self.shape.underline_position_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Suggested values for the underline thickness. In general, the
/// underline thickness should match the thickness of the
/// underscore character (U+005F LOW LINE), and should also match
/// the strikeout thickness, which is specified in the OS/2 table.
pub fn underline_thickness(&self) -> FWord {
let range = self.shape.underline_thickness_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Set to 0 if the font is proportionally spaced, non-zero if the
/// font is not proportionally spaced (i.e. monospaced).
pub fn is_fixed_pitch(&self) -> u32 {
let range = self.shape.is_fixed_pitch_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum memory usage when an OpenType font is downloaded.
pub fn min_mem_type42(&self) -> u32 {
let range = self.shape.min_mem_type42_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Maximum memory usage when an OpenType font is downloaded.
pub fn max_mem_type42(&self) -> u32 {
let range = self.shape.max_mem_type42_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum memory usage when an OpenType font is downloaded as a
/// Type 1 font.
pub fn min_mem_type1(&self) -> u32 {
let range = self.shape.min_mem_type1_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Maximum memory usage when an OpenType font is downloaded as a
/// Type 1 font.
pub fn max_mem_type1(&self) -> u32 {
let range = self.shape.max_mem_type1_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of glyphs (this should be the same as numGlyphs in
/// 'maxp' table).
pub fn num_glyphs(&self) -> Option<u16> {
let range = self.shape.num_glyphs_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Array of indices into the string data. See below for details.
pub fn glyph_name_index(&self) -> Option<&'a [BigEndian<u16>]> {
let range = self.shape.glyph_name_index_byte_range()?;
Some(self.data.read_array(range).unwrap())
}
/// Storage for the string data.
pub fn string_data(&self) -> Option<VarLenArray<'a, PString<'a>>> {
let range = self.shape.string_data_byte_range()?;
Some(VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Post<'a> {
fn type_name(&self) -> &str {
"Post"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("italic_angle", self.italic_angle())),
2usize => Some(Field::new("underline_position", self.underline_position())),
3usize => Some(Field::new(
"underline_thickness",
self.underline_thickness(),
)),
4usize => Some(Field::new("is_fixed_pitch", self.is_fixed_pitch())),
5usize => Some(Field::new("min_mem_type42", self.min_mem_type42())),
6usize => Some(Field::new("max_mem_type42", self.max_mem_type42())),
7usize => Some(Field::new("min_mem_type1", self.min_mem_type1())),
8usize => Some(Field::new("max_mem_type1", self.max_mem_type1())),
9usize if version.compatible((2u16, 0u16)) => {
Some(Field::new("num_glyphs", self.num_glyphs().unwrap()))
}
10usize if version.compatible((2u16, 0u16)) => Some(Field::new(
"glyph_name_index",
self.glyph_name_index().unwrap(),
)),
11usize if version.compatible((2u16, 0u16)) => {
Some(Field::new("string_data", self.traverse_string_data()))
}
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Post<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,679 @@
// 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::*;
/// Sbix header 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 HeaderFlags {
bits: u16,
}
impl HeaderFlags {
/// Bit 0: Set to 1.
pub const ALWAYS_SET: Self = Self { bits: 0x0001 };
/// Bit 1: Draw outlines.
pub const DRAW_OUTLINES: Self = Self { bits: 0x0002 };
}
impl HeaderFlags {
/// 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::ALWAYS_SET.bits | Self::DRAW_OUTLINES.bits,
}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub const fn bits(&self) -> u16 {
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: u16) -> Option<Self> {
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: u16) -> 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 HeaderFlags {
type Output = Self;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: HeaderFlags) -> Self {
Self {
bits: self.bits | other.bits,
}
}
}
impl std::ops::BitOrAssign for HeaderFlags {
/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}
impl std::ops::BitXor for HeaderFlags {
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 HeaderFlags {
/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}
impl std::ops::BitAnd for HeaderFlags {
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 HeaderFlags {
/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}
impl std::ops::Sub for HeaderFlags {
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 HeaderFlags {
/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}
impl std::ops::Not for HeaderFlags {
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 HeaderFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let members: &[(&str, Self)] = &[
("ALWAYS_SET", Self::ALWAYS_SET),
("DRAW_OUTLINES", Self::DRAW_OUTLINES),
];
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 HeaderFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Binary::fmt(&self.bits, f)
}
}
impl std::fmt::Octal for HeaderFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Octal::fmt(&self.bits, f)
}
}
impl std::fmt::LowerHex for HeaderFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::LowerHex::fmt(&self.bits, f)
}
}
impl std::fmt::UpperHex for HeaderFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::UpperHex::fmt(&self.bits, f)
}
}
impl font_types::Scalar for HeaderFlags {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.bits().to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::from_bits_truncate(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<HeaderFlags> for FieldType<'a> {
fn from(src: HeaderFlags) -> FieldType<'a> {
src.bits().into()
}
}
/// The [sbix (Standard Bitmap Graphics)](https://docs.microsoft.com/en-us/typography/opentype/spec/sbix) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SbixMarker {
num_glyphs: u16,
strike_offsets_byte_len: usize,
}
impl SbixMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + HeaderFlags::RAW_BYTE_LEN
}
pub fn num_strikes_byte_range(&self) -> Range<usize> {
let start = self.flags_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn strike_offsets_byte_range(&self) -> Range<usize> {
let start = self.num_strikes_byte_range().end;
start..start + self.strike_offsets_byte_len
}
}
impl MinByteRange for SbixMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.strike_offsets_byte_range().end
}
}
impl TopLevelTable for Sbix<'_> {
/// `sbix`
const TAG: Tag = Tag::new(b"sbix");
}
impl ReadArgs for Sbix<'_> {
type Args = u16;
}
impl<'a> FontReadWithArgs<'a> for Sbix<'a> {
fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
let num_glyphs = *args;
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<HeaderFlags>();
let num_strikes: u32 = cursor.read()?;
let strike_offsets_byte_len = (num_strikes as usize)
.checked_mul(Offset32::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(strike_offsets_byte_len);
cursor.finish(SbixMarker {
num_glyphs,
strike_offsets_byte_len,
})
}
}
impl<'a> Sbix<'a> {
/// A constructor that requires additional arguments.
///
/// This type requires some external state in order to be
/// parsed.
pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
let args = num_glyphs;
Self::read_with_args(data, &args)
}
}
/// The [sbix (Standard Bitmap Graphics)](https://docs.microsoft.com/en-us/typography/opentype/spec/sbix) table
pub type Sbix<'a> = TableRef<'a, SbixMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Sbix<'a> {
/// Table version number — set to 1.
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Bit 0: Set to 1.
/// Bit 1: Draw outlines.
/// Bits 2 to 15: reserved (set to 0).
pub fn flags(&self) -> HeaderFlags {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of bitmap strikes.
pub fn num_strikes(&self) -> u32 {
let range = self.shape.num_strikes_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offsets from the beginning of the 'sbix' table to data for each individual bitmap strike.
pub fn strike_offsets(&self) -> &'a [BigEndian<Offset32>] {
let range = self.shape.strike_offsets_byte_range();
self.data.read_array(range).unwrap()
}
/// A dynamically resolving wrapper for [`strike_offsets`][Self::strike_offsets].
pub fn strikes(&self) -> ArrayOfOffsets<'a, Strike<'a>, Offset32> {
let data = self.data;
let offsets = self.strike_offsets();
let args = self.num_glyphs();
ArrayOfOffsets::new(offsets, data, args)
}
pub(crate) fn num_glyphs(&self) -> u16 {
self.shape.num_glyphs
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Sbix<'a> {
fn type_name(&self) -> &str {
"Sbix"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("flags", self.flags())),
2usize => Some(Field::new("num_strikes", self.num_strikes())),
3usize => Some({
let data = self.data;
let args = self.num_glyphs();
Field::new(
"strike_offsets",
FieldType::array_of_offsets(
better_type_name::<Strike>(),
self.strike_offsets(),
move |off| {
let target = off.get().resolve_with_args::<Strike>(data, &args);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Sbix<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct StrikeMarker {
glyph_data_offsets_byte_len: usize,
}
impl StrikeMarker {
pub fn ppem_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn ppi_byte_range(&self) -> Range<usize> {
let start = self.ppem_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn glyph_data_offsets_byte_range(&self) -> Range<usize> {
let start = self.ppi_byte_range().end;
start..start + self.glyph_data_offsets_byte_len
}
}
impl MinByteRange for StrikeMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.glyph_data_offsets_byte_range().end
}
}
impl ReadArgs for Strike<'_> {
type Args = u16;
}
impl<'a> FontReadWithArgs<'a> for Strike<'a> {
fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
let num_glyphs = *args;
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
let glyph_data_offsets_byte_len = (transforms::add(num_glyphs, 1_usize))
.checked_mul(u32::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(glyph_data_offsets_byte_len);
cursor.finish(StrikeMarker {
glyph_data_offsets_byte_len,
})
}
}
impl<'a> Strike<'a> {
/// A constructor that requires additional arguments.
///
/// This type requires some external state in order to be
/// parsed.
pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
let args = num_glyphs;
Self::read_with_args(data, &args)
}
}
/// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table
pub type Strike<'a> = TableRef<'a, StrikeMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Strike<'a> {
/// The PPEM size for which this strike was designed.
pub fn ppem(&self) -> u16 {
let range = self.shape.ppem_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The device pixel density (in PPI) for which this strike was designed. (E.g., 96 PPI, 192 PPI.)
pub fn ppi(&self) -> u16 {
let range = self.shape.ppi_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from the beginning of the strike data header to bitmap data for an individual glyph ID.
pub fn glyph_data_offsets(&self) -> &'a [BigEndian<u32>] {
let range = self.shape.glyph_data_offsets_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Strike<'a> {
fn type_name(&self) -> &str {
"Strike"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("ppem", self.ppem())),
1usize => Some(Field::new("ppi", self.ppi())),
2usize => Some(Field::new("glyph_data_offsets", self.glyph_data_offsets())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Strike<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct GlyphDataMarker {
data_byte_len: usize,
}
impl GlyphDataMarker {
pub fn origin_offset_x_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + i16::RAW_BYTE_LEN
}
pub fn origin_offset_y_byte_range(&self) -> Range<usize> {
let start = self.origin_offset_x_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn graphic_type_byte_range(&self) -> Range<usize> {
let start = self.origin_offset_y_byte_range().end;
start..start + Tag::RAW_BYTE_LEN
}
pub fn data_byte_range(&self) -> Range<usize> {
let start = self.graphic_type_byte_range().end;
start..start + self.data_byte_len
}
}
impl MinByteRange for GlyphDataMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.data_byte_range().end
}
}
impl<'a> FontRead<'a> for GlyphData<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<Tag>();
let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(data_byte_len);
cursor.finish(GlyphDataMarker { data_byte_len })
}
}
/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table
pub type GlyphData<'a> = TableRef<'a, GlyphDataMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> GlyphData<'a> {
/// The horizontal (x-axis) position of the left edge of the bitmap graphic in relation to the glyph design space origin.
pub fn origin_offset_x(&self) -> i16 {
let range = self.shape.origin_offset_x_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The vertical (y-axis) position of the bottom edge of the bitmap graphic in relation to the glyph design space origin.
pub fn origin_offset_y(&self) -> i16 {
let range = self.shape.origin_offset_y_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Indicates the format of the embedded graphic data: one of 'jpg ', 'png ' or 'tiff', or the special format 'dupe'.
pub fn graphic_type(&self) -> Tag {
let range = self.shape.graphic_type_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The actual embedded graphic data. The total length is inferred from sequential entries in the glyphDataOffsets array and the fixed size (8 bytes) of the preceding fields.
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 GlyphData<'a> {
fn type_name(&self) -> &str {
"GlyphData"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("origin_offset_x", self.origin_offset_x())),
1usize => Some(Field::new("origin_offset_y", self.origin_offset_y())),
2usize => Some(Field::new("graphic_type", self.graphic_type())),
3usize => Some(Field::new("data", self.data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for GlyphData<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,246 @@
// 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::*;
/// The [SVG](https://learn.microsoft.com/en-us/typography/opentype/spec/svg) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SvgMarker {}
impl SvgMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn svg_document_list_offset_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn _reserved_byte_range(&self) -> Range<usize> {
let start = self.svg_document_list_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for SvgMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self._reserved_byte_range().end
}
}
impl TopLevelTable for Svg<'_> {
/// `SVG `
const TAG: Tag = Tag::new(b"SVG ");
}
impl<'a> FontRead<'a> for Svg<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<Offset32>();
cursor.advance::<u16>();
cursor.finish(SvgMarker {})
}
}
/// The [SVG](https://learn.microsoft.com/en-us/typography/opentype/spec/svg) table
pub type Svg<'a> = TableRef<'a, SvgMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Svg<'a> {
/// Table version (starting at 0). Set to 0.
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset to the SVGDocumentList, from the start of the SVG table.
/// Must be non-zero.
pub fn svg_document_list_offset(&self) -> Offset32 {
let range = self.shape.svg_document_list_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`svg_document_list_offset`][Self::svg_document_list_offset].
pub fn svg_document_list(&self) -> Result<SVGDocumentList<'a>, ReadError> {
let data = self.data;
self.svg_document_list_offset().resolve(data)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Svg<'a> {
fn type_name(&self) -> &str {
"Svg"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"svg_document_list_offset",
FieldType::offset(self.svg_document_list_offset(), self.svg_document_list()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Svg<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// [SVGDocumentList](https://learn.microsoft.com/en-us/typography/opentype/spec/svg)
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SVGDocumentListMarker {
document_records_byte_len: usize,
}
impl SVGDocumentListMarker {
pub fn num_entries_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn document_records_byte_range(&self) -> Range<usize> {
let start = self.num_entries_byte_range().end;
start..start + self.document_records_byte_len
}
}
impl MinByteRange for SVGDocumentListMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.document_records_byte_range().end
}
}
impl<'a> FontRead<'a> for SVGDocumentList<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let num_entries: u16 = cursor.read()?;
let document_records_byte_len = (num_entries as usize)
.checked_mul(SVGDocumentRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(document_records_byte_len);
cursor.finish(SVGDocumentListMarker {
document_records_byte_len,
})
}
}
/// [SVGDocumentList](https://learn.microsoft.com/en-us/typography/opentype/spec/svg)
pub type SVGDocumentList<'a> = TableRef<'a, SVGDocumentListMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SVGDocumentList<'a> {
/// Number of SVGDocumentRecords. Must be non-zero.
pub fn num_entries(&self) -> u16 {
let range = self.shape.num_entries_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Array of SVGDocumentRecords.
pub fn document_records(&self) -> &'a [SVGDocumentRecord] {
let range = self.shape.document_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SVGDocumentList<'a> {
fn type_name(&self) -> &str {
"SVGDocumentList"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("num_entries", self.num_entries())),
1usize => Some(Field::new(
"document_records",
traversal::FieldType::array_of_records(
stringify!(SVGDocumentRecord),
self.document_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SVGDocumentList<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// [SVGDocumentRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/svg)
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct SVGDocumentRecord {
/// The first glyph ID for the range covered by this record.
pub start_glyph_id: BigEndian<GlyphId16>,
/// The last glyph ID for the range covered by this record.
pub end_glyph_id: BigEndian<GlyphId16>,
/// Offset from the beginning of the SVGDocumentList to an SVG
/// document. Must be non-zero.
pub svg_doc_offset: BigEndian<u32>,
/// Length of the SVG document data. Must be non-zero.
pub svg_doc_length: BigEndian<u32>,
}
impl SVGDocumentRecord {
/// The first glyph ID for the range covered by this record.
pub fn start_glyph_id(&self) -> GlyphId16 {
self.start_glyph_id.get()
}
/// The last glyph ID for the range covered by this record.
pub fn end_glyph_id(&self) -> GlyphId16 {
self.end_glyph_id.get()
}
/// Offset from the beginning of the SVGDocumentList to an SVG
/// document. Must be non-zero.
pub fn svg_doc_offset(&self) -> u32 {
self.svg_doc_offset.get()
}
/// Length of the SVG document data. Must be non-zero.
pub fn svg_doc_length(&self) -> u32 {
self.svg_doc_length.get()
}
}
impl FixedSize for SVGDocumentRecord {
const RAW_BYTE_LEN: usize =
GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for SVGDocumentRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "SVGDocumentRecord",
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("svg_doc_offset", self.svg_doc_offset())),
3usize => Some(Field::new("svg_doc_length", self.svg_doc_length())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,724 @@
// 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::*;
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct MajorMinorVersionMarker {
if_11_byte_start: Option<usize>,
if_20_byte_start: Option<usize>,
}
impl MajorMinorVersionMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn always_present_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn if_11_byte_range(&self) -> Option<Range<usize>> {
let start = self.if_11_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn if_20_byte_range(&self) -> Option<Range<usize>> {
let start = self.if_20_byte_start?;
Some(start..start + u32::RAW_BYTE_LEN)
}
}
impl MinByteRange for MajorMinorVersionMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.always_present_byte_range().end
}
}
impl<'a> FontRead<'a> for MajorMinorVersion<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: MajorMinor = cursor.read()?;
cursor.advance::<u16>();
let if_11_byte_start = version
.compatible((1u16, 1u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 1u16))
.then(|| cursor.advance::<u16>());
let if_20_byte_start = version
.compatible((2u16, 0u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((2u16, 0u16))
.then(|| cursor.advance::<u32>());
cursor.finish(MajorMinorVersionMarker {
if_11_byte_start,
if_20_byte_start,
})
}
}
pub type MajorMinorVersion<'a> = TableRef<'a, MajorMinorVersionMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> MajorMinorVersion<'a> {
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn always_present(&self) -> u16 {
let range = self.shape.always_present_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn if_11(&self) -> Option<u16> {
let range = self.shape.if_11_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
pub fn if_20(&self) -> Option<u32> {
let range = self.shape.if_20_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for MajorMinorVersion<'a> {
fn type_name(&self) -> &str {
"MajorMinorVersion"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("always_present", self.always_present())),
2usize if version.compatible((1u16, 1u16)) => {
Some(Field::new("if_11", self.if_11().unwrap()))
}
3usize if version.compatible((2u16, 0u16)) => {
Some(Field::new("if_20", self.if_20().unwrap()))
}
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for MajorMinorVersion<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct GotFlags {
bits: u16,
}
impl GotFlags {
pub const FOO: Self = Self { bits: 0x0001 };
pub const BAR: Self = Self { bits: 0x0002 };
pub const BAZ: Self = Self { bits: 0x0004 };
}
impl GotFlags {
/// 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::FOO.bits | Self::BAR.bits | Self::BAZ.bits,
}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub const fn bits(&self) -> u16 {
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: u16) -> Option<Self> {
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: u16) -> 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 GotFlags {
type Output = Self;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: GotFlags) -> Self {
Self {
bits: self.bits | other.bits,
}
}
}
impl std::ops::BitOrAssign for GotFlags {
/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}
impl std::ops::BitXor for GotFlags {
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 GotFlags {
/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}
impl std::ops::BitAnd for GotFlags {
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 GotFlags {
/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}
impl std::ops::Sub for GotFlags {
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 GotFlags {
/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}
impl std::ops::Not for GotFlags {
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 GotFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let members: &[(&str, Self)] =
&[("FOO", Self::FOO), ("BAR", Self::BAR), ("BAZ", Self::BAZ)];
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 GotFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Binary::fmt(&self.bits, f)
}
}
impl std::fmt::Octal for GotFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Octal::fmt(&self.bits, f)
}
}
impl std::fmt::LowerHex for GotFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::LowerHex::fmt(&self.bits, f)
}
}
impl std::fmt::UpperHex for GotFlags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::UpperHex::fmt(&self.bits, f)
}
}
impl font_types::Scalar for GotFlags {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.bits().to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::from_bits_truncate(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<GotFlags> for FieldType<'a> {
fn from(src: GotFlags) -> FieldType<'a> {
src.bits().into()
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct FlagDayMarker {
foo_byte_start: Option<usize>,
bar_byte_start: Option<usize>,
baz_byte_start: Option<usize>,
}
impl FlagDayMarker {
pub fn volume_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn flags_byte_range(&self) -> Range<usize> {
let start = self.volume_byte_range().end;
start..start + GotFlags::RAW_BYTE_LEN
}
pub fn foo_byte_range(&self) -> Option<Range<usize>> {
let start = self.foo_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn bar_byte_range(&self) -> Option<Range<usize>> {
let start = self.bar_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn baz_byte_range(&self) -> Option<Range<usize>> {
let start = self.baz_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
}
impl MinByteRange for FlagDayMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.flags_byte_range().end
}
}
impl<'a> FontRead<'a> for FlagDay<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let flags: GotFlags = cursor.read()?;
let foo_byte_start = flags
.contains(GotFlags::FOO)
.then(|| cursor.position())
.transpose()?;
flags
.contains(GotFlags::FOO)
.then(|| cursor.advance::<u16>());
let bar_byte_start = flags
.contains(GotFlags::BAR)
.then(|| cursor.position())
.transpose()?;
flags
.contains(GotFlags::BAR)
.then(|| cursor.advance::<u16>());
let baz_byte_start = flags
.intersects(GotFlags::BAZ | GotFlags::FOO)
.then(|| cursor.position())
.transpose()?;
flags
.intersects(GotFlags::BAZ | GotFlags::FOO)
.then(|| cursor.advance::<u16>());
cursor.finish(FlagDayMarker {
foo_byte_start,
bar_byte_start,
baz_byte_start,
})
}
}
pub type FlagDay<'a> = TableRef<'a, FlagDayMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> FlagDay<'a> {
pub fn volume(&self) -> u16 {
let range = self.shape.volume_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn flags(&self) -> GotFlags {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn foo(&self) -> Option<u16> {
let range = self.shape.foo_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
pub fn bar(&self) -> Option<u16> {
let range = self.shape.bar_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
pub fn baz(&self) -> Option<u16> {
let range = self.shape.baz_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for FlagDay<'a> {
fn type_name(&self) -> &str {
"FlagDay"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let flags = self.flags();
match idx {
0usize => Some(Field::new("volume", self.volume())),
1usize => Some(Field::new("flags", self.flags())),
2usize if flags.contains(GotFlags::FOO) => Some(Field::new("foo", self.foo().unwrap())),
3usize if flags.contains(GotFlags::BAR) => Some(Field::new("bar", self.bar().unwrap())),
4usize if flags.intersects(GotFlags::BAZ | GotFlags::FOO) => {
Some(Field::new("baz", self.baz().unwrap()))
}
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for FlagDay<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct FieldsAfterConditionalsMarker {
foo_byte_start: Option<usize>,
bar_byte_start: Option<usize>,
baz_byte_start: Option<usize>,
}
impl FieldsAfterConditionalsMarker {
pub fn flags_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + GotFlags::RAW_BYTE_LEN
}
pub fn foo_byte_range(&self) -> Option<Range<usize>> {
let start = self.foo_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn always_here_byte_range(&self) -> Range<usize> {
let start = self
.foo_byte_range()
.map(|range| range.end)
.unwrap_or_else(|| self.flags_byte_range().end);
start..start + u16::RAW_BYTE_LEN
}
pub fn bar_byte_range(&self) -> Option<Range<usize>> {
let start = self.bar_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn baz_byte_range(&self) -> Option<Range<usize>> {
let start = self.baz_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
pub fn also_always_here_byte_range(&self) -> Range<usize> {
let start = self
.baz_byte_range()
.map(|range| range.end)
.unwrap_or_else(|| {
self.bar_byte_range()
.map(|range| range.end)
.unwrap_or_else(|| self.always_here_byte_range().end)
});
start..start + u16::RAW_BYTE_LEN
}
pub fn and_me_too_byte_range(&self) -> Range<usize> {
let start = self.also_always_here_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for FieldsAfterConditionalsMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.and_me_too_byte_range().end
}
}
impl<'a> FontRead<'a> for FieldsAfterConditionals<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let flags: GotFlags = cursor.read()?;
let foo_byte_start = flags
.contains(GotFlags::FOO)
.then(|| cursor.position())
.transpose()?;
flags
.contains(GotFlags::FOO)
.then(|| cursor.advance::<u16>());
cursor.advance::<u16>();
let bar_byte_start = flags
.contains(GotFlags::BAR)
.then(|| cursor.position())
.transpose()?;
flags
.contains(GotFlags::BAR)
.then(|| cursor.advance::<u16>());
let baz_byte_start = flags
.contains(GotFlags::BAZ)
.then(|| cursor.position())
.transpose()?;
flags
.contains(GotFlags::BAZ)
.then(|| cursor.advance::<u16>());
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.finish(FieldsAfterConditionalsMarker {
foo_byte_start,
bar_byte_start,
baz_byte_start,
})
}
}
pub type FieldsAfterConditionals<'a> = TableRef<'a, FieldsAfterConditionalsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> FieldsAfterConditionals<'a> {
pub fn flags(&self) -> GotFlags {
let range = self.shape.flags_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn foo(&self) -> Option<u16> {
let range = self.shape.foo_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
pub fn always_here(&self) -> u16 {
let range = self.shape.always_here_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn bar(&self) -> Option<u16> {
let range = self.shape.bar_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
pub fn baz(&self) -> Option<u16> {
let range = self.shape.baz_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
pub fn also_always_here(&self) -> u16 {
let range = self.shape.also_always_here_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn and_me_too(&self) -> u16 {
let range = self.shape.and_me_too_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for FieldsAfterConditionals<'a> {
fn type_name(&self) -> &str {
"FieldsAfterConditionals"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let flags = self.flags();
match idx {
0usize => Some(Field::new("flags", self.flags())),
1usize if flags.contains(GotFlags::FOO) => Some(Field::new("foo", self.foo().unwrap())),
2usize => Some(Field::new("always_here", self.always_here())),
3usize if flags.contains(GotFlags::BAR) => Some(Field::new("bar", self.bar().unwrap())),
4usize if flags.contains(GotFlags::BAZ) => Some(Field::new("baz", self.baz().unwrap())),
5usize => Some(Field::new("also_always_here", self.also_always_here())),
6usize => Some(Field::new("and_me_too", self.and_me_too())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for FieldsAfterConditionals<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,148 @@
// 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::*;
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CountAll16Marker {
remainder_byte_len: usize,
}
impl CountAll16Marker {
pub fn some_field_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn remainder_byte_range(&self) -> Range<usize> {
let start = self.some_field_byte_range().end;
start..start + self.remainder_byte_len
}
}
impl MinByteRange for CountAll16Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.remainder_byte_range().end
}
}
impl<'a> FontRead<'a> for CountAll16<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let remainder_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
cursor.advance_by(remainder_byte_len);
cursor.finish(CountAll16Marker { remainder_byte_len })
}
}
pub type CountAll16<'a> = TableRef<'a, CountAll16Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> CountAll16<'a> {
pub fn some_field(&self) -> u16 {
let range = self.shape.some_field_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn remainder(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.remainder_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for CountAll16<'a> {
fn type_name(&self) -> &str {
"CountAll16"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("some_field", self.some_field())),
1usize => Some(Field::new("remainder", self.remainder())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for CountAll16<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CountAll32Marker {
remainder_byte_len: usize,
}
impl CountAll32Marker {
pub fn some_field_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn remainder_byte_range(&self) -> Range<usize> {
let start = self.some_field_byte_range().end;
start..start + self.remainder_byte_len
}
}
impl MinByteRange for CountAll32Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.remainder_byte_range().end
}
}
impl<'a> FontRead<'a> for CountAll32<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let remainder_byte_len = cursor.remaining_bytes() / u32::RAW_BYTE_LEN * u32::RAW_BYTE_LEN;
cursor.advance_by(remainder_byte_len);
cursor.finish(CountAll32Marker { remainder_byte_len })
}
}
pub type CountAll32<'a> = TableRef<'a, CountAll32Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> CountAll32<'a> {
pub fn some_field(&self) -> u16 {
let range = self.shape.some_field_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn remainder(&self) -> &'a [BigEndian<u32>] {
let range = self.shape.remainder_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for CountAll32<'a> {
fn type_name(&self) -> &str {
"CountAll32"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("some_field", self.some_field())),
1usize => Some(Field::new("remainder", self.remainder())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for CountAll32<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,134 @@
// 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::*;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u16)]
#[allow(clippy::manual_non_exhaustive)]
pub enum MyEnum1 {
/// doc me baby
/// docington bear
#[default]
ItsAZero = 0,
ItsAOne = 1,
#[doc(hidden)]
/// If font data is malformed we will map unknown values to this variant
Unknown,
}
impl MyEnum1 {
/// Create from a raw scalar.
///
/// This will never fail; unknown values will be mapped to the `Unknown` variant
pub fn new(raw: u16) -> Self {
match raw {
0 => Self::ItsAZero,
1 => Self::ItsAOne,
_ => Self::Unknown,
}
}
}
impl font_types::Scalar for MyEnum1 {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
(self as u16).to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::new(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<MyEnum1> for FieldType<'a> {
fn from(src: MyEnum1) -> FieldType<'a> {
(src as u16).into()
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u16)]
#[allow(clippy::manual_non_exhaustive)]
pub enum MyEnum2 {
ItsATwo = 2,
/// A very important three
#[default]
ItsAThree = 3,
#[doc(hidden)]
/// If font data is malformed we will map unknown values to this variant
Unknown,
}
impl MyEnum2 {
/// Create from a raw scalar.
///
/// This will never fail; unknown values will be mapped to the `Unknown` variant
pub fn new(raw: u16) -> Self {
match raw {
2 => Self::ItsATwo,
3 => Self::ItsAThree,
_ => Self::Unknown,
}
}
}
impl font_types::Scalar for MyEnum2 {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
(self as u16).to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::new(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<MyEnum2> for FieldType<'a> {
fn from(src: MyEnum2) -> FieldType<'a> {
(src as u16).into()
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct MyRecord {
pub my_enum1: BigEndian<MyEnum1>,
pub my_enum2: BigEndian<MyEnum2>,
}
impl MyRecord {
pub fn my_enum1(&self) -> MyEnum1 {
self.my_enum1.get()
}
pub fn my_enum2(&self) -> MyEnum2 {
self.my_enum2.get()
}
}
impl FixedSize for MyRecord {
const RAW_BYTE_LEN: usize = MyEnum1::RAW_BYTE_LEN + MyEnum2::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for MyRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "MyRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("my_enum1", self.my_enum1())),
1usize => Some(Field::new("my_enum2", self.my_enum2())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,314 @@
// 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::*;
/// Some 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 ValueFormat {
bits: u16,
}
impl ValueFormat {
/// Includes horizontal adjustment for placement
pub const X_PLACEMENT: Self = Self { bits: 0x0001 };
/// Includes vertical adjustment for placement
pub const Y_PLACEMENT: Self = Self { bits: 0x0002 };
}
impl ValueFormat {
/// 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::X_PLACEMENT.bits | Self::Y_PLACEMENT.bits,
}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub const fn bits(&self) -> u16 {
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: u16) -> Option<Self> {
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: u16) -> 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 ValueFormat {
type Output = Self;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: ValueFormat) -> Self {
Self {
bits: self.bits | other.bits,
}
}
}
impl std::ops::BitOrAssign for ValueFormat {
/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}
impl std::ops::BitXor for ValueFormat {
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 ValueFormat {
/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}
impl std::ops::BitAnd for ValueFormat {
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 ValueFormat {
/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}
impl std::ops::Sub for ValueFormat {
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 ValueFormat {
/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}
impl std::ops::Not for ValueFormat {
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 ValueFormat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let members: &[(&str, Self)] = &[
("X_PLACEMENT", Self::X_PLACEMENT),
("Y_PLACEMENT", Self::Y_PLACEMENT),
];
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 ValueFormat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Binary::fmt(&self.bits, f)
}
}
impl std::fmt::Octal for ValueFormat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Octal::fmt(&self.bits, f)
}
}
impl std::fmt::LowerHex for ValueFormat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::LowerHex::fmt(&self.bits, f)
}
}
impl std::fmt::UpperHex for ValueFormat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::UpperHex::fmt(&self.bits, f)
}
}
impl font_types::Scalar for ValueFormat {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.bits().to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::from_bits_truncate(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<ValueFormat> for FieldType<'a> {
fn from(src: ValueFormat) -> FieldType<'a> {
src.bits().into()
}
}

View File

@@ -0,0 +1,327 @@
// 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 Format<u16> for Table1Marker {
const FORMAT: u16 = 1;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Table1Marker {}
impl Table1Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn heft_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn flex_byte_range(&self) -> Range<usize> {
let start = self.heft_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for Table1Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.flex_byte_range().end
}
}
impl<'a> FontRead<'a> for Table1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u32>();
cursor.advance::<u16>();
cursor.finish(Table1Marker {})
}
}
pub type Table1<'a> = TableRef<'a, Table1Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Table1<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn heft(&self) -> u32 {
let range = self.shape.heft_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn flex(&self) -> u16 {
let range = self.shape.flex_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Table1<'a> {
fn type_name(&self) -> &str {
"Table1"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("heft", self.heft())),
2usize => Some(Field::new("flex", self.flex())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Table1<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for Table2Marker {
const FORMAT: u16 = 2;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Table2Marker {
values_byte_len: usize,
}
impl Table2Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn value_count_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn values_byte_range(&self) -> Range<usize> {
let start = self.value_count_byte_range().end;
start..start + self.values_byte_len
}
}
impl MinByteRange for Table2Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.values_byte_range().end
}
}
impl<'a> FontRead<'a> for Table2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let value_count: u16 = cursor.read()?;
let values_byte_len = (value_count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(values_byte_len);
cursor.finish(Table2Marker { values_byte_len })
}
}
pub type Table2<'a> = TableRef<'a, Table2Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Table2<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn value_count(&self) -> u16 {
let range = self.shape.value_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn values(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.values_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Table2<'a> {
fn type_name(&self) -> &str {
"Table2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("value_count", self.value_count())),
2usize => Some(Field::new("values", self.values())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Table2<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for Table3Marker {
const FORMAT: u16 = 3;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Table3Marker {}
impl Table3Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn something_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for Table3Marker {
fn min_byte_range(&self) -> Range<usize> {
0..self.something_byte_range().end
}
}
impl<'a> FontRead<'a> for Table3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.finish(Table3Marker {})
}
}
pub type Table3<'a> = TableRef<'a, Table3Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Table3<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn something(&self) -> u16 {
let range = self.shape.something_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Table3<'a> {
fn type_name(&self) -> &str {
"Table3"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("something", self.something())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Table3<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone)]
pub enum MyTable<'a> {
Format1(Table1<'a>),
MyFormat22(Table2<'a>),
Format3(Table3<'a>),
}
impl<'a> MyTable<'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::MyFormat22(item) => item.offset_data(),
Self::Format3(item) => item.offset_data(),
}
}
pub fn format(&self) -> u16 {
match self {
Self::Format1(item) => item.format(),
Self::MyFormat22(item) => item.format(),
Self::Format3(item) => item.format(),
}
}
}
impl<'a> FontRead<'a> for MyTable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
Table1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
Table2Marker::FORMAT => Ok(Self::MyFormat22(FontRead::read(data)?)),
Table3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl MinByteRange for MyTable<'_> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Format1(item) => item.min_byte_range(),
Self::MyFormat22(item) => item.min_byte_range(),
Self::Format3(item) => item.min_byte_range(),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> MyTable<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format1(table) => table,
Self::MyFormat22(table) => table,
Self::Format3(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for MyTable<'_> {
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 MyTable<'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)
}
}

View File

@@ -0,0 +1,890 @@
// 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::*;
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct KindsOfOffsetsMarker {
versioned_nullable_record_array_offset_byte_start: Option<usize>,
versioned_nonnullable_offset_byte_start: Option<usize>,
versioned_nullable_offset_byte_start: Option<usize>,
}
impl KindsOfOffsetsMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn nonnullable_offset_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn nullable_offset_byte_range(&self) -> Range<usize> {
let start = self.nonnullable_offset_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn array_offset_count_byte_range(&self) -> Range<usize> {
let start = self.nullable_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn array_offset_byte_range(&self) -> Range<usize> {
let start = self.array_offset_count_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn record_array_offset_byte_range(&self) -> Range<usize> {
let start = self.array_offset_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn versioned_nullable_record_array_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.versioned_nullable_record_array_offset_byte_start?;
Some(start..start + Offset16::RAW_BYTE_LEN)
}
pub fn versioned_nonnullable_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.versioned_nonnullable_offset_byte_start?;
Some(start..start + Offset16::RAW_BYTE_LEN)
}
pub fn versioned_nullable_offset_byte_range(&self) -> Option<Range<usize>> {
let start = self.versioned_nullable_offset_byte_start?;
Some(start..start + Offset32::RAW_BYTE_LEN)
}
}
impl MinByteRange for KindsOfOffsetsMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.record_array_offset_byte_range().end
}
}
impl<'a> FontRead<'a> for KindsOfOffsets<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: MajorMinor = cursor.read()?;
cursor.advance::<Offset16>();
cursor.advance::<Offset16>();
cursor.advance::<u16>();
cursor.advance::<Offset16>();
cursor.advance::<Offset16>();
let versioned_nullable_record_array_offset_byte_start = version
.compatible((1u16, 1u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 1u16))
.then(|| cursor.advance::<Offset16>());
let versioned_nonnullable_offset_byte_start = version
.compatible((1u16, 1u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 1u16))
.then(|| cursor.advance::<Offset16>());
let versioned_nullable_offset_byte_start = version
.compatible((1u16, 1u16))
.then(|| cursor.position())
.transpose()?;
version
.compatible((1u16, 1u16))
.then(|| cursor.advance::<Offset32>());
cursor.finish(KindsOfOffsetsMarker {
versioned_nullable_record_array_offset_byte_start,
versioned_nonnullable_offset_byte_start,
versioned_nullable_offset_byte_start,
})
}
}
pub type KindsOfOffsets<'a> = TableRef<'a, KindsOfOffsetsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> KindsOfOffsets<'a> {
/// The major/minor version of the GDEF table
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// A normal offset
pub fn nonnullable_offset(&self) -> Offset16 {
let range = self.shape.nonnullable_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`nonnullable_offset`][Self::nonnullable_offset].
pub fn nonnullable(&self) -> Result<Dummy<'a>, ReadError> {
let data = self.data;
self.nonnullable_offset().resolve(data)
}
/// An offset that is nullable, but always present
pub fn nullable_offset(&self) -> Nullable<Offset16> {
let range = self.shape.nullable_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`nullable_offset`][Self::nullable_offset].
pub fn nullable(&self) -> Option<Result<Dummy<'a>, ReadError>> {
let data = self.data;
self.nullable_offset().resolve(data)
}
/// count of the array at array_offset
pub fn array_offset_count(&self) -> u16 {
let range = self.shape.array_offset_count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// An offset to an array:
pub fn array_offset(&self) -> Offset16 {
let range = self.shape.array_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`array_offset`][Self::array_offset].
pub fn array(&self) -> Result<&'a [BigEndian<u16>], ReadError> {
let data = self.data;
let args = self.array_offset_count();
self.array_offset().resolve_with_args(data, &args)
}
/// An offset to an array of records
pub fn record_array_offset(&self) -> Offset16 {
let range = self.shape.record_array_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`record_array_offset`][Self::record_array_offset].
pub fn record_array(&self) -> Result<&'a [Shmecord], ReadError> {
let data = self.data;
let args = self.array_offset_count();
self.record_array_offset().resolve_with_args(data, &args)
}
/// A nullable, versioned offset to an array of records
pub fn versioned_nullable_record_array_offset(&self) -> Option<Nullable<Offset16>> {
let range = self
.shape
.versioned_nullable_record_array_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`versioned_nullable_record_array_offset`][Self::versioned_nullable_record_array_offset].
pub fn versioned_nullable_record_array(&self) -> Option<Result<&'a [Shmecord], ReadError>> {
let data = self.data;
let args = self.array_offset_count();
self.versioned_nullable_record_array_offset()
.map(|x| x.resolve_with_args(data, &args))?
}
/// A normal offset that is versioned
pub fn versioned_nonnullable_offset(&self) -> Option<Offset16> {
let range = self.shape.versioned_nonnullable_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`versioned_nonnullable_offset`][Self::versioned_nonnullable_offset].
pub fn versioned_nonnullable(&self) -> Option<Result<Dummy<'a>, ReadError>> {
let data = self.data;
self.versioned_nonnullable_offset().map(|x| x.resolve(data))
}
/// An offset that is nullable and versioned
pub fn versioned_nullable_offset(&self) -> Option<Nullable<Offset32>> {
let range = self.shape.versioned_nullable_offset_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
/// Attempt to resolve [`versioned_nullable_offset`][Self::versioned_nullable_offset].
pub fn versioned_nullable(&self) -> Option<Result<Dummy<'a>, ReadError>> {
let data = self.data;
self.versioned_nullable_offset().map(|x| x.resolve(data))?
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for KindsOfOffsets<'a> {
fn type_name(&self) -> &str {
"KindsOfOffsets"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"nonnullable_offset",
FieldType::offset(self.nonnullable_offset(), self.nonnullable()),
)),
2usize => Some(Field::new(
"nullable_offset",
FieldType::offset(self.nullable_offset(), self.nullable()),
)),
3usize => Some(Field::new("array_offset_count", self.array_offset_count())),
4usize => Some(Field::new(
"array_offset",
FieldType::offset_to_array_of_scalars(self.array_offset(), self.array()),
)),
5usize => Some(Field::new(
"record_array_offset",
traversal::FieldType::offset_to_array_of_records(
self.record_array_offset(),
self.record_array(),
stringify!(Shmecord),
self.offset_data(),
),
)),
6usize if version.compatible((1u16, 1u16)) => Some(Field::new(
"versioned_nullable_record_array_offset",
traversal::FieldType::offset_to_array_of_records(
self.versioned_nullable_record_array_offset().unwrap(),
self.versioned_nullable_record_array(),
stringify!(Shmecord),
self.offset_data(),
),
)),
7usize if version.compatible((1u16, 1u16)) => Some(Field::new(
"versioned_nonnullable_offset",
FieldType::offset(
self.versioned_nonnullable_offset().unwrap(),
self.versioned_nonnullable().unwrap(),
),
)),
8usize if version.compatible((1u16, 1u16)) => Some(Field::new(
"versioned_nullable_offset",
FieldType::offset(
self.versioned_nullable_offset().unwrap(),
self.versioned_nullable(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for KindsOfOffsets<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct KindsOfArraysOfOffsetsMarker {
nonnullable_offsets_byte_len: usize,
nullable_offsets_byte_len: usize,
versioned_nonnullable_offsets_byte_start: Option<usize>,
versioned_nonnullable_offsets_byte_len: Option<usize>,
versioned_nullable_offsets_byte_start: Option<usize>,
versioned_nullable_offsets_byte_len: Option<usize>,
}
impl KindsOfArraysOfOffsetsMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn nonnullable_offsets_byte_range(&self) -> Range<usize> {
let start = self.count_byte_range().end;
start..start + self.nonnullable_offsets_byte_len
}
pub fn nullable_offsets_byte_range(&self) -> Range<usize> {
let start = self.nonnullable_offsets_byte_range().end;
start..start + self.nullable_offsets_byte_len
}
pub fn versioned_nonnullable_offsets_byte_range(&self) -> Option<Range<usize>> {
let start = self.versioned_nonnullable_offsets_byte_start?;
Some(start..start + self.versioned_nonnullable_offsets_byte_len?)
}
pub fn versioned_nullable_offsets_byte_range(&self) -> Option<Range<usize>> {
let start = self.versioned_nullable_offsets_byte_start?;
Some(start..start + self.versioned_nullable_offsets_byte_len?)
}
}
impl MinByteRange for KindsOfArraysOfOffsetsMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.nullable_offsets_byte_range().end
}
}
impl<'a> FontRead<'a> for KindsOfArraysOfOffsets<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: MajorMinor = cursor.read()?;
let count: u16 = cursor.read()?;
let nonnullable_offsets_byte_len = (count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(nonnullable_offsets_byte_len);
let nullable_offsets_byte_len = (count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(nullable_offsets_byte_len);
let versioned_nonnullable_offsets_byte_start = version
.compatible((1u16, 1u16))
.then(|| cursor.position())
.transpose()?;
let versioned_nonnullable_offsets_byte_len = version.compatible((1u16, 1u16)).then_some(
(count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
);
if let Some(value) = versioned_nonnullable_offsets_byte_len {
cursor.advance_by(value);
}
let versioned_nullable_offsets_byte_start = version
.compatible((1u16, 1u16))
.then(|| cursor.position())
.transpose()?;
let versioned_nullable_offsets_byte_len = version.compatible((1u16, 1u16)).then_some(
(count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
);
if let Some(value) = versioned_nullable_offsets_byte_len {
cursor.advance_by(value);
}
cursor.finish(KindsOfArraysOfOffsetsMarker {
nonnullable_offsets_byte_len,
nullable_offsets_byte_len,
versioned_nonnullable_offsets_byte_start,
versioned_nonnullable_offsets_byte_len,
versioned_nullable_offsets_byte_start,
versioned_nullable_offsets_byte_len,
})
}
}
pub type KindsOfArraysOfOffsets<'a> = TableRef<'a, KindsOfArraysOfOffsetsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> KindsOfArraysOfOffsets<'a> {
/// The version
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The number of items in each array
pub fn count(&self) -> u16 {
let range = self.shape.count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// A normal array offset
pub fn nonnullable_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.nonnullable_offsets_byte_range();
self.data.read_array(range).unwrap()
}
/// A dynamically resolving wrapper for [`nonnullable_offsets`][Self::nonnullable_offsets].
pub fn nonnullables(&self) -> ArrayOfOffsets<'a, Dummy<'a>, Offset16> {
let data = self.data;
let offsets = self.nonnullable_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
/// An offset that is nullable, but always present
pub fn nullable_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.shape.nullable_offsets_byte_range();
self.data.read_array(range).unwrap()
}
/// A dynamically resolving wrapper for [`nullable_offsets`][Self::nullable_offsets].
pub fn nullables(&self) -> ArrayOfNullableOffsets<'a, Dummy<'a>, Offset16> {
let data = self.data;
let offsets = self.nullable_offsets();
ArrayOfNullableOffsets::new(offsets, data, ())
}
/// A normal offset that is versioned
pub fn versioned_nonnullable_offsets(&self) -> Option<&'a [BigEndian<Offset16>]> {
let range = self.shape.versioned_nonnullable_offsets_byte_range()?;
Some(self.data.read_array(range).unwrap())
}
/// A dynamically resolving wrapper for [`versioned_nonnullable_offsets`][Self::versioned_nonnullable_offsets].
pub fn versioned_nonnullables(&self) -> Option<ArrayOfOffsets<'a, Dummy<'a>, Offset16>> {
let data = self.data;
let offsets = self.versioned_nonnullable_offsets();
offsets.map(|offsets| ArrayOfOffsets::new(offsets, data, ()))
}
/// An offset that is nullable and versioned
pub fn versioned_nullable_offsets(&self) -> Option<&'a [BigEndian<Nullable<Offset16>>]> {
let range = self.shape.versioned_nullable_offsets_byte_range()?;
Some(self.data.read_array(range).unwrap())
}
/// A dynamically resolving wrapper for [`versioned_nullable_offsets`][Self::versioned_nullable_offsets].
pub fn versioned_nullables(&self) -> Option<ArrayOfNullableOffsets<'a, Dummy<'a>, Offset16>> {
let data = self.data;
let offsets = self.versioned_nullable_offsets();
offsets.map(|offsets| ArrayOfNullableOffsets::new(offsets, data, ()))
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for KindsOfArraysOfOffsets<'a> {
fn type_name(&self) -> &str {
"KindsOfArraysOfOffsets"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("count", self.count())),
2usize => Some({
let data = self.data;
Field::new(
"nonnullable_offsets",
FieldType::array_of_offsets(
better_type_name::<Dummy>(),
self.nonnullable_offsets(),
move |off| {
let target = off.get().resolve::<Dummy>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
3usize => Some({
let data = self.data;
Field::new(
"nullable_offsets",
FieldType::array_of_offsets(
better_type_name::<Dummy>(),
self.nullable_offsets(),
move |off| {
let target = off.get().resolve::<Dummy>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
4usize if version.compatible((1u16, 1u16)) => Some({
let data = self.data;
Field::new(
"versioned_nonnullable_offsets",
FieldType::array_of_offsets(
better_type_name::<Dummy>(),
self.versioned_nonnullable_offsets().unwrap(),
move |off| {
let target = off.get().resolve::<Dummy>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
5usize if version.compatible((1u16, 1u16)) => Some({
let data = self.data;
Field::new(
"versioned_nullable_offsets",
FieldType::array_of_offsets(
better_type_name::<Dummy>(),
self.versioned_nullable_offsets().unwrap(),
move |off| {
let target = off.get().resolve::<Dummy>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for KindsOfArraysOfOffsets<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct KindsOfArraysMarker {
scalars_byte_len: usize,
records_byte_len: usize,
versioned_scalars_byte_start: Option<usize>,
versioned_scalars_byte_len: Option<usize>,
versioned_records_byte_start: Option<usize>,
versioned_records_byte_len: Option<usize>,
}
impl KindsOfArraysMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn scalars_byte_range(&self) -> Range<usize> {
let start = self.count_byte_range().end;
start..start + self.scalars_byte_len
}
pub fn records_byte_range(&self) -> Range<usize> {
let start = self.scalars_byte_range().end;
start..start + self.records_byte_len
}
pub fn versioned_scalars_byte_range(&self) -> Option<Range<usize>> {
let start = self.versioned_scalars_byte_start?;
Some(start..start + self.versioned_scalars_byte_len?)
}
pub fn versioned_records_byte_range(&self) -> Option<Range<usize>> {
let start = self.versioned_records_byte_start?;
Some(start..start + self.versioned_records_byte_len?)
}
}
impl MinByteRange for KindsOfArraysMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.records_byte_range().end
}
}
impl<'a> FontRead<'a> for KindsOfArrays<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let version: u16 = cursor.read()?;
let count: u16 = cursor.read()?;
let scalars_byte_len = (count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(scalars_byte_len);
let records_byte_len = (count as usize)
.checked_mul(Shmecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(records_byte_len);
let versioned_scalars_byte_start = version
.compatible(1u16)
.then(|| cursor.position())
.transpose()?;
let versioned_scalars_byte_len = version.compatible(1u16).then_some(
(count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
);
if let Some(value) = versioned_scalars_byte_len {
cursor.advance_by(value);
}
let versioned_records_byte_start = version
.compatible(1u16)
.then(|| cursor.position())
.transpose()?;
let versioned_records_byte_len = version.compatible(1u16).then_some(
(count as usize)
.checked_mul(Shmecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
);
if let Some(value) = versioned_records_byte_len {
cursor.advance_by(value);
}
cursor.finish(KindsOfArraysMarker {
scalars_byte_len,
records_byte_len,
versioned_scalars_byte_start,
versioned_scalars_byte_len,
versioned_records_byte_start,
versioned_records_byte_len,
})
}
}
pub type KindsOfArrays<'a> = TableRef<'a, KindsOfArraysMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> KindsOfArrays<'a> {
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// the number of items in each array
pub fn count(&self) -> u16 {
let range = self.shape.count_byte_range();
self.data.read_at(range.start).unwrap()
}
/// an array of scalars
pub fn scalars(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.scalars_byte_range();
self.data.read_array(range).unwrap()
}
/// an array of records
pub fn records(&self) -> &'a [Shmecord] {
let range = self.shape.records_byte_range();
self.data.read_array(range).unwrap()
}
/// a versioned array of scalars
pub fn versioned_scalars(&self) -> Option<&'a [BigEndian<u16>]> {
let range = self.shape.versioned_scalars_byte_range()?;
Some(self.data.read_array(range).unwrap())
}
/// a versioned array of scalars
pub fn versioned_records(&self) -> Option<&'a [Shmecord]> {
let range = self.shape.versioned_records_byte_range()?;
Some(self.data.read_array(range).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for KindsOfArrays<'a> {
fn type_name(&self) -> &str {
"KindsOfArrays"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let version = self.version();
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("count", self.count())),
2usize => Some(Field::new("scalars", self.scalars())),
3usize => Some(Field::new(
"records",
traversal::FieldType::array_of_records(
stringify!(Shmecord),
self.records(),
self.offset_data(),
),
)),
4usize if version.compatible(1u16) => Some(Field::new(
"versioned_scalars",
self.versioned_scalars().unwrap(),
)),
5usize if version.compatible(1u16) => Some(Field::new(
"versioned_records",
traversal::FieldType::array_of_records(
stringify!(Shmecord),
self.versioned_records().unwrap(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for KindsOfArrays<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VarLenHaverMarker {
var_len_byte_len: usize,
}
impl VarLenHaverMarker {
pub fn count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn var_len_byte_range(&self) -> Range<usize> {
let start = self.count_byte_range().end;
start..start + self.var_len_byte_len
}
pub fn other_field_byte_range(&self) -> Range<usize> {
let start = self.var_len_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
}
impl MinByteRange for VarLenHaverMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.other_field_byte_range().end
}
}
impl<'a> FontRead<'a> for VarLenHaver<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let count: u16 = cursor.read()?;
let var_len_byte_len = {
let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?;
<VarSizeDummy as VarSize>::total_len_for_count(data, count as usize)?
};
cursor.advance_by(var_len_byte_len);
cursor.advance::<u32>();
cursor.finish(VarLenHaverMarker { var_len_byte_len })
}
}
pub type VarLenHaver<'a> = TableRef<'a, VarLenHaverMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> VarLenHaver<'a> {
pub fn count(&self) -> u16 {
let range = self.shape.count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn var_len(&self) -> VarLenArray<'a, VarSizeDummy> {
let range = self.shape.var_len_byte_range();
VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()
}
pub fn other_field(&self) -> u32 {
let range = self.shape.other_field_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for VarLenHaver<'a> {
fn type_name(&self) -> &str {
"VarLenHaver"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("count", self.count())),
1usize => Some(Field::new("var_len", traversal::FieldType::Unknown)),
2usize => Some(Field::new("other_field", self.other_field())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for VarLenHaver<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct DummyMarker {}
impl DummyMarker {
pub fn value_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn _reserved_byte_range(&self) -> Range<usize> {
let start = self.value_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for DummyMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self._reserved_byte_range().end
}
}
impl<'a> FontRead<'a> for Dummy<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.finish(DummyMarker {})
}
}
pub type Dummy<'a> = TableRef<'a, DummyMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Dummy<'a> {
pub fn value(&self) -> u16 {
let range = self.shape.value_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Dummy<'a> {
fn type_name(&self) -> &str {
"Dummy"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("value", self.value())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Dummy<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct Shmecord {
pub length: BigEndian<u16>,
pub breadth: BigEndian<u32>,
}
impl Shmecord {
pub fn length(&self) -> u16 {
self.length.get()
}
pub fn breadth(&self) -> u32 {
self.breadth.get()
}
}
impl FixedSize for Shmecord {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for Shmecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "Shmecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("length", self.length())),
1usize => Some(Field::new("breadth", self.breadth())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,408 @@
// 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::*;
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct BasicTableMarker {
simple_records_byte_len: usize,
array_records_byte_len: usize,
}
impl BasicTableMarker {
pub fn simple_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn simple_records_byte_range(&self) -> Range<usize> {
let start = self.simple_count_byte_range().end;
start..start + self.simple_records_byte_len
}
pub fn arrays_inner_count_byte_range(&self) -> Range<usize> {
let start = self.simple_records_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn array_records_count_byte_range(&self) -> Range<usize> {
let start = self.arrays_inner_count_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn array_records_byte_range(&self) -> Range<usize> {
let start = self.array_records_count_byte_range().end;
start..start + self.array_records_byte_len
}
}
impl MinByteRange for BasicTableMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.array_records_byte_range().end
}
}
impl<'a> FontRead<'a> for BasicTable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let simple_count: u16 = cursor.read()?;
let simple_records_byte_len = (simple_count as usize)
.checked_mul(SimpleRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(simple_records_byte_len);
let arrays_inner_count: u16 = cursor.read()?;
let array_records_count: u32 = cursor.read()?;
let array_records_byte_len = (array_records_count as usize)
.checked_mul(<ContainsArrays as ComputeSize>::compute_size(
&arrays_inner_count,
)?)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(array_records_byte_len);
cursor.finish(BasicTableMarker {
simple_records_byte_len,
array_records_byte_len,
})
}
}
pub type BasicTable<'a> = TableRef<'a, BasicTableMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> BasicTable<'a> {
pub fn simple_count(&self) -> u16 {
let range = self.shape.simple_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn simple_records(&self) -> &'a [SimpleRecord] {
let range = self.shape.simple_records_byte_range();
self.data.read_array(range).unwrap()
}
pub fn arrays_inner_count(&self) -> u16 {
let range = self.shape.arrays_inner_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn array_records_count(&self) -> u32 {
let range = self.shape.array_records_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn array_records(&self) -> ComputedArray<'a, ContainsArrays<'a>> {
let range = self.shape.array_records_byte_range();
self.data
.read_with_args(range, &self.arrays_inner_count())
.unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for BasicTable<'a> {
fn type_name(&self) -> &str {
"BasicTable"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("simple_count", self.simple_count())),
1usize => Some(Field::new(
"simple_records",
traversal::FieldType::array_of_records(
stringify!(SimpleRecord),
self.simple_records(),
self.offset_data(),
),
)),
2usize => Some(Field::new("arrays_inner_count", self.arrays_inner_count())),
3usize => Some(Field::new(
"array_records_count",
self.array_records_count(),
)),
4usize => Some(Field::new(
"array_records",
traversal::FieldType::computed_array(
"ContainsArrays",
self.array_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for BasicTable<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct SimpleRecord {
pub val1: BigEndian<u16>,
pub va2: BigEndian<u32>,
}
impl SimpleRecord {
pub fn val1(&self) -> u16 {
self.val1.get()
}
pub fn va2(&self) -> u32 {
self.va2.get()
}
}
impl FixedSize for SimpleRecord {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for SimpleRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "SimpleRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("val1", self.val1())),
1usize => Some(Field::new("va2", self.va2())),
_ => None,
}),
data,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ContainsArrays<'a> {
pub scalars: &'a [BigEndian<u16>],
pub records: &'a [SimpleRecord],
}
impl<'a> ContainsArrays<'a> {
pub fn scalars(&self) -> &'a [BigEndian<u16>] {
self.scalars
}
pub fn records(&self) -> &'a [SimpleRecord] {
self.records
}
}
impl ReadArgs for ContainsArrays<'_> {
type Args = u16;
}
impl ComputeSize for ContainsArrays<'_> {
#[allow(clippy::needless_question_mark)]
fn compute_size(args: &u16) -> Result<usize, ReadError> {
let array_len = *args;
let mut result = 0usize;
result = result
.checked_add(
(array_len as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
)
.ok_or(ReadError::OutOfBounds)?;
result = result
.checked_add(
(array_len as usize)
.checked_mul(SimpleRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?,
)
.ok_or(ReadError::OutOfBounds)?;
Ok(result)
}
}
impl<'a> FontReadWithArgs<'a> for ContainsArrays<'a> {
fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let array_len = *args;
Ok(Self {
scalars: cursor.read_array(array_len as usize)?,
records: cursor.read_array(array_len as usize)?,
})
}
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ContainsArrays<'a> {
/// A constructor that requires additional arguments.
///
/// This type requires some external state in order to be
/// parsed.
pub fn read(data: FontData<'a>, array_len: u16) -> Result<Self, ReadError> {
let args = array_len;
Self::read_with_args(data, &args)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ContainsArrays<'a> {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ContainsArrays",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("scalars", self.scalars())),
1usize => Some(Field::new(
"records",
traversal::FieldType::array_of_records(
stringify!(SimpleRecord),
self.records(),
_data,
),
)),
_ => None,
}),
data,
}
}
}
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ContainsOffsets {
pub off_array_count: BigEndian<u16>,
pub array_offset: BigEndian<Offset16>,
pub other_offset: BigEndian<Offset32>,
}
impl ContainsOffsets {
pub fn off_array_count(&self) -> u16 {
self.off_array_count.get()
}
pub fn array_offset(&self) -> Offset16 {
self.array_offset.get()
}
///
/// The `data` argument should be retrieved from the parent table
/// By calling its `offset_data` method.
pub fn array<'a>(&self, data: FontData<'a>) -> Result<&'a [SimpleRecord], ReadError> {
let args = self.off_array_count();
self.array_offset().resolve_with_args(data, &args)
}
pub fn other_offset(&self) -> Offset32 {
self.other_offset.get()
}
///
/// The `data` argument should be retrieved from the parent table
/// By calling its `offset_data` method.
pub fn other<'a>(&self, data: FontData<'a>) -> Result<BasicTable<'a>, ReadError> {
self.other_offset().resolve(data)
}
}
impl FixedSize for ContainsOffsets {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ContainsOffsets {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ContainsOffsets",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("off_array_count", self.off_array_count())),
1usize => Some(Field::new(
"array_offset",
traversal::FieldType::offset_to_array_of_records(
self.array_offset(),
self.array(_data),
stringify!(SimpleRecord),
_data,
),
)),
2usize => Some(Field::new(
"other_offset",
FieldType::offset(self.other_offset(), self.other(_data)),
)),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VarLenItemMarker {
data_byte_len: usize,
}
impl VarLenItemMarker {
pub fn length_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn data_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + self.data_byte_len
}
}
impl MinByteRange for VarLenItemMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.data_byte_range().end
}
}
impl<'a> FontRead<'a> for VarLenItem<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u32>();
let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
cursor.advance_by(data_byte_len);
cursor.finish(VarLenItemMarker { data_byte_len })
}
}
pub type VarLenItem<'a> = TableRef<'a, VarLenItemMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> VarLenItem<'a> {
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
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 VarLenItem<'a> {
fn type_name(&self) -> &str {
"VarLenItem"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("length", self.length())),
1usize => Some(Field::new("data", self.data())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for VarLenItem<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,295 @@
// 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::*;
/// The [tracking (trak)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct TrakMarker {}
impl TrakMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn format_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn horiz_offset_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn vert_offset_byte_range(&self) -> Range<usize> {
let start = self.horiz_offset_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn reserved_byte_range(&self) -> Range<usize> {
let start = self.vert_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for TrakMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.reserved_byte_range().end
}
}
impl TopLevelTable for Trak<'_> {
/// `trak`
const TAG: Tag = Tag::new(b"trak");
}
impl<'a> FontRead<'a> for Trak<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<u16>();
cursor.advance::<Offset16>();
cursor.advance::<Offset16>();
cursor.advance::<u16>();
cursor.finish(TrakMarker {})
}
}
/// The [tracking (trak)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html) table.
pub type Trak<'a> = TableRef<'a, TrakMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Trak<'a> {
/// Version number of the tracking table (0x00010000 for the current version).
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Format of the tracking table (set to 0).
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from start of tracking table to TrackData for horizontal text (or 0 if none).
pub fn horiz_offset(&self) -> Nullable<Offset16> {
let range = self.shape.horiz_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`horiz_offset`][Self::horiz_offset].
pub fn horiz(&self) -> Option<Result<TrackData<'a>, ReadError>> {
let data = self.data;
self.horiz_offset().resolve(data)
}
/// Offset from start of tracking table to TrackData for vertical text (or 0 if none).
pub fn vert_offset(&self) -> Nullable<Offset16> {
let range = self.shape.vert_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`vert_offset`][Self::vert_offset].
pub fn vert(&self) -> Option<Result<TrackData<'a>, ReadError>> {
let data = self.data;
self.vert_offset().resolve(data)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Trak<'a> {
fn type_name(&self) -> &str {
"Trak"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("format", self.format())),
2usize => Some(Field::new(
"horiz_offset",
FieldType::offset(self.horiz_offset(), self.horiz()),
)),
3usize => Some(Field::new(
"vert_offset",
FieldType::offset(self.vert_offset(), self.vert()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Trak<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// The tracking data table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct TrackDataMarker {
track_table_byte_len: usize,
}
impl TrackDataMarker {
pub fn n_tracks_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn n_sizes_byte_range(&self) -> Range<usize> {
let start = self.n_tracks_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn size_table_offset_byte_range(&self) -> Range<usize> {
let start = self.n_sizes_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn track_table_byte_range(&self) -> Range<usize> {
let start = self.size_table_offset_byte_range().end;
start..start + self.track_table_byte_len
}
}
impl MinByteRange for TrackDataMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.track_table_byte_range().end
}
}
impl<'a> FontRead<'a> for TrackData<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let n_tracks: u16 = cursor.read()?;
cursor.advance::<u16>();
cursor.advance::<u32>();
let track_table_byte_len = (n_tracks as usize)
.checked_mul(TrackTableEntry::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(track_table_byte_len);
cursor.finish(TrackDataMarker {
track_table_byte_len,
})
}
}
/// The tracking data table.
pub type TrackData<'a> = TableRef<'a, TrackDataMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> TrackData<'a> {
/// Number of separate tracks included in this table.
pub fn n_tracks(&self) -> u16 {
let range = self.shape.n_tracks_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of point sizes included in this table.
pub fn n_sizes(&self) -> u16 {
let range = self.shape.n_sizes_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset from the start of the tracking table to the start of the size subtable.
pub fn size_table_offset(&self) -> u32 {
let range = self.shape.size_table_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Array of TrackTableEntry records.
pub fn track_table(&self) -> &'a [TrackTableEntry] {
let range = self.shape.track_table_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for TrackData<'a> {
fn type_name(&self) -> &str {
"TrackData"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("n_tracks", self.n_tracks())),
1usize => Some(Field::new("n_sizes", self.n_sizes())),
2usize => Some(Field::new("size_table_offset", self.size_table_offset())),
3usize => Some(Field::new(
"track_table",
traversal::FieldType::array_of_records(
stringify!(TrackTableEntry),
self.track_table(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for TrackData<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Single entry in a tracking table.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct TrackTableEntry {
/// Track value for this record.
pub track: BigEndian<Fixed>,
/// The 'name' table index for this track (a short word or phrase like \"loose\" or \"very tight\"). NameIndex has a value greater than 255 and less than 32768.
pub name_index: BigEndian<NameId>,
/// Offset from the start of the tracking table to per-size tracking values for this track.
pub offset: BigEndian<u16>,
}
impl TrackTableEntry {
/// Track value for this record.
pub fn track(&self) -> Fixed {
self.track.get()
}
/// The 'name' table index for this track (a short word or phrase like \"loose\" or \"very tight\"). NameIndex has a value greater than 255 and less than 32768.
pub fn name_index(&self) -> NameId {
self.name_index.get()
}
/// Offset from the start of the tracking table to per-size tracking values for this track.
pub fn offset(&self) -> u16 {
self.offset.get()
}
}
impl FixedSize for TrackTableEntry {
const RAW_BYTE_LEN: usize = Fixed::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for TrackTableEntry {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "TrackTableEntry",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("track", self.track())),
1usize => Some(Field::new("name_index", self.name_index())),
2usize => Some(Field::new("offset", self.offset())),
_ => None,
}),
data,
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,264 @@
// 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::*;
/// The [vhea](https://docs.microsoft.com/en-us/typography/opentype/spec/vhea) Vertical Header Table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VheaMarker {}
impl VheaMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + Version16Dot16::RAW_BYTE_LEN
}
pub fn ascender_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn descender_byte_range(&self) -> Range<usize> {
let start = self.ascender_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn line_gap_byte_range(&self) -> Range<usize> {
let start = self.descender_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn advance_height_max_byte_range(&self) -> Range<usize> {
let start = self.line_gap_byte_range().end;
start..start + UfWord::RAW_BYTE_LEN
}
pub fn min_top_side_bearing_byte_range(&self) -> Range<usize> {
let start = self.advance_height_max_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn min_bottom_side_bearing_byte_range(&self) -> Range<usize> {
let start = self.min_top_side_bearing_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn y_max_extent_byte_range(&self) -> Range<usize> {
let start = self.min_bottom_side_bearing_byte_range().end;
start..start + FWord::RAW_BYTE_LEN
}
pub fn caret_slope_rise_byte_range(&self) -> Range<usize> {
let start = self.y_max_extent_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn caret_slope_run_byte_range(&self) -> Range<usize> {
let start = self.caret_slope_rise_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn caret_offset_byte_range(&self) -> Range<usize> {
let start = self.caret_slope_run_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved1_byte_range(&self) -> Range<usize> {
let start = self.caret_offset_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved2_byte_range(&self) -> Range<usize> {
let start = self.reserved1_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved3_byte_range(&self) -> Range<usize> {
let start = self.reserved2_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn reserved4_byte_range(&self) -> Range<usize> {
let start = self.reserved3_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn metric_data_format_byte_range(&self) -> Range<usize> {
let start = self.reserved4_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn number_of_long_ver_metrics_byte_range(&self) -> Range<usize> {
let start = self.metric_data_format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl MinByteRange for VheaMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.number_of_long_ver_metrics_byte_range().end
}
}
impl TopLevelTable for Vhea<'_> {
/// `vhea`
const TAG: Tag = Tag::new(b"vhea");
}
impl<'a> FontRead<'a> for Vhea<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<Version16Dot16>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<UfWord>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<FWord>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<i16>();
cursor.advance::<u16>();
cursor.finish(VheaMarker {})
}
}
/// The [vhea](https://docs.microsoft.com/en-us/typography/opentype/spec/vhea) Vertical Header Table
pub type Vhea<'a> = TableRef<'a, VheaMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Vhea<'a> {
/// The major/minor version (1, 1)
pub fn version(&self) -> Version16Dot16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Typographic ascent.
pub fn ascender(&self) -> FWord {
let range = self.shape.ascender_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Typographic descent.
pub fn descender(&self) -> FWord {
let range = self.shape.descender_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Typographic line gap. Negative LineGap values are treated as
/// zero in some legacy platform implementations.
pub fn line_gap(&self) -> FWord {
let range = self.shape.line_gap_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Maximum advance height value in 'vmtx' table.
pub fn advance_height_max(&self) -> UfWord {
let range = self.shape.advance_height_max_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum top sidebearing value in 'vmtx' table for glyphs with
/// contours (empty glyphs should be ignored).
pub fn min_top_side_bearing(&self) -> FWord {
let range = self.shape.min_top_side_bearing_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Minimum bottom sidebearing value
pub fn min_bottom_side_bearing(&self) -> FWord {
let range = self.shape.min_bottom_side_bearing_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Defined as max( tsb + (yMax-yMin)).
pub fn y_max_extent(&self) -> FWord {
let range = self.shape.y_max_extent_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Used to calculate the slope of the cursor (rise/run); 1 for
/// vertical caret, 0 for horizontal.
pub fn caret_slope_rise(&self) -> i16 {
let range = self.shape.caret_slope_rise_byte_range();
self.data.read_at(range.start).unwrap()
}
/// 0 for vertical caret, 1 for horizontal.
pub fn caret_slope_run(&self) -> i16 {
let range = self.shape.caret_slope_run_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The amount by which a slanted highlight on a glyph needs to be
/// shifted to produce the best appearance. Set to 0 for
/// non-slanted fonts
pub fn caret_offset(&self) -> i16 {
let range = self.shape.caret_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// 0 for current format.
pub fn metric_data_format(&self) -> i16 {
let range = self.shape.metric_data_format_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of advance heights in the vertical metrics (`vmtx`) table.
pub fn number_of_long_ver_metrics(&self) -> u16 {
let range = self.shape.number_of_long_ver_metrics_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Vhea<'a> {
fn type_name(&self) -> &str {
"Vhea"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("ascender", self.ascender())),
2usize => Some(Field::new("descender", self.descender())),
3usize => Some(Field::new("line_gap", self.line_gap())),
4usize => Some(Field::new("advance_height_max", self.advance_height_max())),
5usize => Some(Field::new(
"min_top_side_bearing",
self.min_top_side_bearing(),
)),
6usize => Some(Field::new(
"min_bottom_side_bearing",
self.min_bottom_side_bearing(),
)),
7usize => Some(Field::new("y_max_extent", self.y_max_extent())),
8usize => Some(Field::new("caret_slope_rise", self.caret_slope_rise())),
9usize => Some(Field::new("caret_slope_run", self.caret_slope_run())),
10usize => Some(Field::new("caret_offset", self.caret_offset())),
11usize => Some(Field::new("metric_data_format", self.metric_data_format())),
12usize => Some(Field::new(
"number_of_long_ver_metrics",
self.number_of_long_ver_metrics(),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Vhea<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,124 @@
// 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::*;
/// The [vmtx (Vertical Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VmtxMarker {
v_metrics_byte_len: usize,
top_side_bearings_byte_len: usize,
}
impl VmtxMarker {
pub fn v_metrics_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + self.v_metrics_byte_len
}
pub fn top_side_bearings_byte_range(&self) -> Range<usize> {
let start = self.v_metrics_byte_range().end;
start..start + self.top_side_bearings_byte_len
}
}
impl MinByteRange for VmtxMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.top_side_bearings_byte_range().end
}
}
impl TopLevelTable for Vmtx<'_> {
/// `vmtx`
const TAG: Tag = Tag::new(b"vmtx");
}
impl ReadArgs for Vmtx<'_> {
type Args = (u16, u16);
}
impl<'a> FontReadWithArgs<'a> for Vmtx<'a> {
fn read_with_args(data: FontData<'a>, args: &(u16, u16)) -> Result<Self, ReadError> {
let (number_of_long_ver_metrics, num_glyphs) = *args;
let mut cursor = data.cursor();
let v_metrics_byte_len = (number_of_long_ver_metrics as usize)
.checked_mul(LongMetric::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(v_metrics_byte_len);
let top_side_bearings_byte_len =
(transforms::subtract(num_glyphs, number_of_long_ver_metrics))
.checked_mul(i16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(top_side_bearings_byte_len);
cursor.finish(VmtxMarker {
v_metrics_byte_len,
top_side_bearings_byte_len,
})
}
}
impl<'a> Vmtx<'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_long_ver_metrics: u16,
num_glyphs: u16,
) -> Result<Self, ReadError> {
let args = (number_of_long_ver_metrics, num_glyphs);
Self::read_with_args(data, &args)
}
}
/// The [vmtx (Vertical Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx) table
pub type Vmtx<'a> = TableRef<'a, VmtxMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Vmtx<'a> {
/// Paired advance height and top side bearing values for each
/// glyph. Records are indexed by glyph ID.
pub fn v_metrics(&self) -> &'a [LongMetric] {
let range = self.shape.v_metrics_byte_range();
self.data.read_array(range).unwrap()
}
/// Top side bearings for glyph IDs greater than or equal to numberOfLongMetrics.
pub fn top_side_bearings(&self) -> &'a [BigEndian<i16>] {
let range = self.shape.top_side_bearings_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Vmtx<'a> {
fn type_name(&self) -> &str {
"Vmtx"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"v_metrics",
traversal::FieldType::array_of_records(
stringify!(LongMetric),
self.v_metrics(),
self.offset_data(),
),
)),
1usize => Some(Field::new("top_side_bearings", self.top_side_bearings())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Vmtx<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}

View File

@@ -0,0 +1,173 @@
// 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::*;
/// The [VORG (Vertical Origin)](https://docs.microsoft.com/en-us/typography/opentype/spec/vorg) table.
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VorgMarker {
vert_origin_y_metrics_byte_len: usize,
}
impl VorgMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn default_vert_origin_y_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn num_vert_origin_y_metrics_byte_range(&self) -> Range<usize> {
let start = self.default_vert_origin_y_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn vert_origin_y_metrics_byte_range(&self) -> Range<usize> {
let start = self.num_vert_origin_y_metrics_byte_range().end;
start..start + self.vert_origin_y_metrics_byte_len
}
}
impl MinByteRange for VorgMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.vert_origin_y_metrics_byte_range().end
}
}
impl TopLevelTable for Vorg<'_> {
/// `VORG`
const TAG: Tag = Tag::new(b"VORG");
}
impl<'a> FontRead<'a> for Vorg<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<i16>();
let num_vert_origin_y_metrics: u16 = cursor.read()?;
let vert_origin_y_metrics_byte_len = (num_vert_origin_y_metrics as usize)
.checked_mul(VertOriginYMetrics::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(vert_origin_y_metrics_byte_len);
cursor.finish(VorgMarker {
vert_origin_y_metrics_byte_len,
})
}
}
/// The [VORG (Vertical Origin)](https://docs.microsoft.com/en-us/typography/opentype/spec/vorg) table.
pub type Vorg<'a> = TableRef<'a, VorgMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Vorg<'a> {
/// Major/minor version number. Set to 1.0.
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// The y coordinate of a glyphs vertical origin, in the fonts design
/// coordinate system, to be used if no entry is present for the glyph
/// in the vertOriginYMetrics array.
pub fn default_vert_origin_y(&self) -> i16 {
let range = self.shape.default_vert_origin_y_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Number of elements in the vertOriginYMetrics array.
pub fn num_vert_origin_y_metrics(&self) -> u16 {
let range = self.shape.num_vert_origin_y_metrics_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Array of VertOriginYMetrics records, sorted by glyph ID.
pub fn vert_origin_y_metrics(&self) -> &'a [VertOriginYMetrics] {
let range = self.shape.vert_origin_y_metrics_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Vorg<'a> {
fn type_name(&self) -> &str {
"Vorg"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"default_vert_origin_y",
self.default_vert_origin_y(),
)),
2usize => Some(Field::new(
"num_vert_origin_y_metrics",
self.num_vert_origin_y_metrics(),
)),
3usize => Some(Field::new(
"vert_origin_y_metrics",
traversal::FieldType::array_of_records(
stringify!(VertOriginYMetrics),
self.vert_origin_y_metrics(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Vorg<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
/// Vertical origin Y metrics record.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct VertOriginYMetrics {
/// Glyph index.
pub glyph_index: BigEndian<GlyphId16>,
/// Y coordinate, in the fonts design coordinate system, of the glyphs vertical origin.
pub vert_origin_y: BigEndian<i16>,
}
impl VertOriginYMetrics {
/// Glyph index.
pub fn glyph_index(&self) -> GlyphId16 {
self.glyph_index.get()
}
/// Y coordinate, in the fonts design coordinate system, of the glyphs vertical origin.
pub fn vert_origin_y(&self) -> i16 {
self.vert_origin_y.get()
}
}
impl FixedSize for VertOriginYMetrics {
const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for VertOriginYMetrics {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "VertOriginYMetrics",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("glyph_index", self.glyph_index())),
1usize => Some(Field::new("vert_origin_y", self.vert_origin_y())),
_ => None,
}),
data,
}
}
}

View File

@@ -0,0 +1,187 @@
// 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::*;
/// The [VVAR (Vertical Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/vvar) table
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct VvarMarker {}
impl VvarMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn item_variation_store_offset_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn advance_height_mapping_offset_byte_range(&self) -> Range<usize> {
let start = self.item_variation_store_offset_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn tsb_mapping_offset_byte_range(&self) -> Range<usize> {
let start = self.advance_height_mapping_offset_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn bsb_mapping_offset_byte_range(&self) -> Range<usize> {
let start = self.tsb_mapping_offset_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
pub fn v_org_mapping_offset_byte_range(&self) -> Range<usize> {
let start = self.bsb_mapping_offset_byte_range().end;
start..start + Offset32::RAW_BYTE_LEN
}
}
impl MinByteRange for VvarMarker {
fn min_byte_range(&self) -> Range<usize> {
0..self.v_org_mapping_offset_byte_range().end
}
}
impl TopLevelTable for Vvar<'_> {
/// `VVAR`
const TAG: Tag = Tag::new(b"VVAR");
}
impl<'a> FontRead<'a> for Vvar<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
cursor.advance::<Offset32>();
cursor.advance::<Offset32>();
cursor.advance::<Offset32>();
cursor.advance::<Offset32>();
cursor.advance::<Offset32>();
cursor.finish(VvarMarker {})
}
}
/// The [VVAR (Vertical Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/vvar) table
pub type Vvar<'a> = TableRef<'a, VvarMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Vvar<'a> {
/// Major version number of the horizontal metrics variations table — set to 1.
/// Minor version number of the horizontal metrics variations table — set to 0.
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Offset in bytes from the start of this table to the item variation store table.
pub fn item_variation_store_offset(&self) -> Offset32 {
let range = self.shape.item_variation_store_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset].
pub fn item_variation_store(&self) -> Result<ItemVariationStore<'a>, ReadError> {
let data = self.data;
self.item_variation_store_offset().resolve(data)
}
/// Offset in bytes from the start of this table to the delta-set index mapping for advance heights (may be NULL).
pub fn advance_height_mapping_offset(&self) -> Nullable<Offset32> {
let range = self.shape.advance_height_mapping_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`advance_height_mapping_offset`][Self::advance_height_mapping_offset].
pub fn advance_height_mapping(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.advance_height_mapping_offset().resolve(data)
}
/// Offset in bytes from the start of this table to the delta-set index mapping for top side bearings (may be NULL).
pub fn tsb_mapping_offset(&self) -> Nullable<Offset32> {
let range = self.shape.tsb_mapping_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`tsb_mapping_offset`][Self::tsb_mapping_offset].
pub fn tsb_mapping(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.tsb_mapping_offset().resolve(data)
}
/// Offset in bytes from the start of this table to the delta-set index mapping for bottom side bearings (may be NULL).
pub fn bsb_mapping_offset(&self) -> Nullable<Offset32> {
let range = self.shape.bsb_mapping_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`bsb_mapping_offset`][Self::bsb_mapping_offset].
pub fn bsb_mapping(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.bsb_mapping_offset().resolve(data)
}
/// Offset in bytes from the start of this table to the delta-set index mapping for Y coordinates of vertical origins (may be NULL).
pub fn v_org_mapping_offset(&self) -> Nullable<Offset32> {
let range = self.shape.v_org_mapping_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
/// Attempt to resolve [`v_org_mapping_offset`][Self::v_org_mapping_offset].
pub fn v_org_mapping(&self) -> Option<Result<DeltaSetIndexMap<'a>, ReadError>> {
let data = self.data;
self.v_org_mapping_offset().resolve(data)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Vvar<'a> {
fn type_name(&self) -> &str {
"Vvar"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"item_variation_store_offset",
FieldType::offset(
self.item_variation_store_offset(),
self.item_variation_store(),
),
)),
2usize => Some(Field::new(
"advance_height_mapping_offset",
FieldType::offset(
self.advance_height_mapping_offset(),
self.advance_height_mapping(),
),
)),
3usize => Some(Field::new(
"tsb_mapping_offset",
FieldType::offset(self.tsb_mapping_offset(), self.tsb_mapping()),
)),
4usize => Some(Field::new(
"bsb_mapping_offset",
FieldType::offset(self.bsb_mapping_offset(), self.bsb_mapping()),
)),
5usize => Some(Field::new(
"v_org_mapping_offset",
FieldType::offset(self.v_org_mapping_offset(), self.v_org_mapping()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Vvar<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}