#[allow(unused_imports)]
use crate::codegen_prelude::*;
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ScriptListMarker {
script_records_byte_len: usize,
}
impl ScriptListMarker {
pub fn script_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn script_records_byte_range(&self) -> Range<usize> {
let start = self.script_count_byte_range().end;
start..start + self.script_records_byte_len
}
}
impl<'a> FontRead<'a> for ScriptList<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let script_count: u16 = cursor.read()?;
let script_records_byte_len = (script_count as usize)
.checked_mul(ScriptRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(script_records_byte_len);
cursor.finish(ScriptListMarker {
script_records_byte_len,
})
}
}
pub type ScriptList<'a> = TableRef<'a, ScriptListMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ScriptList<'a> {
pub fn script_count(&self) -> u16 {
let range = self.shape.script_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn script_records(&self) -> &'a [ScriptRecord] {
let range = self.shape.script_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ScriptList<'a> {
fn type_name(&self) -> &str {
"ScriptList"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("script_count", self.script_count())),
1usize => Some(Field::new(
"script_records",
traversal::FieldType::array_of_records(
stringify!(ScriptRecord),
self.script_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ScriptList<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ScriptRecord {
pub script_tag: BigEndian<Tag>,
pub script_offset: BigEndian<Offset16>,
}
impl ScriptRecord {
pub fn script_tag(&self) -> Tag {
self.script_tag.get()
}
pub fn script_offset(&self) -> Offset16 {
self.script_offset.get()
}
pub fn script<'a>(&self, data: FontData<'a>) -> Result<Script<'a>, ReadError> {
self.script_offset().resolve(data)
}
}
impl FixedSize for ScriptRecord {
const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ScriptRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ScriptRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("script_tag", self.script_tag())),
1usize => Some(Field::new(
"script_offset",
FieldType::offset(self.script_offset(), self.script(_data)),
)),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ScriptMarker {
lang_sys_records_byte_len: usize,
}
impl ScriptMarker {
pub fn default_lang_sys_offset_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn lang_sys_count_byte_range(&self) -> Range<usize> {
let start = self.default_lang_sys_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn lang_sys_records_byte_range(&self) -> Range<usize> {
let start = self.lang_sys_count_byte_range().end;
start..start + self.lang_sys_records_byte_len
}
}
impl<'a> FontRead<'a> for Script<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<Offset16>();
let lang_sys_count: u16 = cursor.read()?;
let lang_sys_records_byte_len = (lang_sys_count as usize)
.checked_mul(LangSysRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(lang_sys_records_byte_len);
cursor.finish(ScriptMarker {
lang_sys_records_byte_len,
})
}
}
pub type Script<'a> = TableRef<'a, ScriptMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Script<'a> {
pub fn default_lang_sys_offset(&self) -> Nullable<Offset16> {
let range = self.shape.default_lang_sys_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn default_lang_sys(&self) -> Option<Result<LangSys<'a>, ReadError>> {
let data = self.data;
self.default_lang_sys_offset().resolve(data)
}
pub fn lang_sys_count(&self) -> u16 {
let range = self.shape.lang_sys_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lang_sys_records(&self) -> &'a [LangSysRecord] {
let range = self.shape.lang_sys_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Script<'a> {
fn type_name(&self) -> &str {
"Script"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"default_lang_sys_offset",
FieldType::offset(self.default_lang_sys_offset(), self.default_lang_sys()),
)),
1usize => Some(Field::new("lang_sys_count", self.lang_sys_count())),
2usize => Some(Field::new(
"lang_sys_records",
traversal::FieldType::array_of_records(
stringify!(LangSysRecord),
self.lang_sys_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Script<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct LangSysRecord {
pub lang_sys_tag: BigEndian<Tag>,
pub lang_sys_offset: BigEndian<Offset16>,
}
impl LangSysRecord {
pub fn lang_sys_tag(&self) -> Tag {
self.lang_sys_tag.get()
}
pub fn lang_sys_offset(&self) -> Offset16 {
self.lang_sys_offset.get()
}
pub fn lang_sys<'a>(&self, data: FontData<'a>) -> Result<LangSys<'a>, ReadError> {
self.lang_sys_offset().resolve(data)
}
}
impl FixedSize for LangSysRecord {
const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for LangSysRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "LangSysRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("lang_sys_tag", self.lang_sys_tag())),
1usize => Some(Field::new(
"lang_sys_offset",
FieldType::offset(self.lang_sys_offset(), self.lang_sys(_data)),
)),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct LangSysMarker {
feature_indices_byte_len: usize,
}
impl LangSysMarker {
pub fn lookup_order_offset_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn required_feature_index_byte_range(&self) -> Range<usize> {
let start = self.lookup_order_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn feature_index_count_byte_range(&self) -> Range<usize> {
let start = self.required_feature_index_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn feature_indices_byte_range(&self) -> Range<usize> {
let start = self.feature_index_count_byte_range().end;
start..start + self.feature_indices_byte_len
}
}
impl<'a> FontRead<'a> for LangSys<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
let feature_index_count: u16 = cursor.read()?;
let feature_indices_byte_len = (feature_index_count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(feature_indices_byte_len);
cursor.finish(LangSysMarker {
feature_indices_byte_len,
})
}
}
pub type LangSys<'a> = TableRef<'a, LangSysMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> LangSys<'a> {
pub fn required_feature_index(&self) -> u16 {
let range = self.shape.required_feature_index_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feature_index_count(&self) -> u16 {
let range = self.shape.feature_index_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feature_indices(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.feature_indices_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for LangSys<'a> {
fn type_name(&self) -> &str {
"LangSys"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"required_feature_index",
self.required_feature_index(),
)),
1usize => Some(Field::new(
"feature_index_count",
self.feature_index_count(),
)),
2usize => Some(Field::new("feature_indices", self.feature_indices())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for LangSys<'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 FeatureListMarker {
feature_records_byte_len: usize,
}
impl FeatureListMarker {
pub fn feature_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn feature_records_byte_range(&self) -> Range<usize> {
let start = self.feature_count_byte_range().end;
start..start + self.feature_records_byte_len
}
}
impl<'a> FontRead<'a> for FeatureList<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let feature_count: u16 = cursor.read()?;
let feature_records_byte_len = (feature_count as usize)
.checked_mul(FeatureRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(feature_records_byte_len);
cursor.finish(FeatureListMarker {
feature_records_byte_len,
})
}
}
pub type FeatureList<'a> = TableRef<'a, FeatureListMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> FeatureList<'a> {
pub fn feature_count(&self) -> u16 {
let range = self.shape.feature_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feature_records(&self) -> &'a [FeatureRecord] {
let range = self.shape.feature_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for FeatureList<'a> {
fn type_name(&self) -> &str {
"FeatureList"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("feature_count", self.feature_count())),
1usize => Some(Field::new(
"feature_records",
traversal::FieldType::array_of_records(
stringify!(FeatureRecord),
self.feature_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for FeatureList<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct FeatureRecord {
pub feature_tag: BigEndian<Tag>,
pub feature_offset: BigEndian<Offset16>,
}
impl FeatureRecord {
pub fn feature_tag(&self) -> Tag {
self.feature_tag.get()
}
pub fn feature_offset(&self) -> Offset16 {
self.feature_offset.get()
}
pub fn feature<'a>(&self, data: FontData<'a>) -> Result<Feature<'a>, ReadError> {
let args = self.feature_tag();
self.feature_offset().resolve_with_args(data, &args)
}
}
impl FixedSize for FeatureRecord {
const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for FeatureRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "FeatureRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("feature_tag", self.feature_tag())),
1usize => Some(Field::new(
"feature_offset",
FieldType::offset(self.feature_offset(), self.feature(_data)),
)),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct FeatureMarker {
feature_tag: Tag,
lookup_list_indices_byte_len: usize,
}
impl FeatureMarker {
pub fn feature_params_offset_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn lookup_index_count_byte_range(&self) -> Range<usize> {
let start = self.feature_params_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookup_list_indices_byte_range(&self) -> Range<usize> {
let start = self.lookup_index_count_byte_range().end;
start..start + self.lookup_list_indices_byte_len
}
}
impl ReadArgs for Feature<'_> {
type Args = Tag;
}
impl<'a> FontReadWithArgs<'a> for Feature<'a> {
fn read_with_args(data: FontData<'a>, args: &Tag) -> Result<Self, ReadError> {
let feature_tag = *args;
let mut cursor = data.cursor();
cursor.advance::<Offset16>();
let lookup_index_count: u16 = cursor.read()?;
let lookup_list_indices_byte_len = (lookup_index_count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(lookup_list_indices_byte_len);
cursor.finish(FeatureMarker {
feature_tag,
lookup_list_indices_byte_len,
})
}
}
impl<'a> Feature<'a> {
pub fn read(data: FontData<'a>, feature_tag: Tag) -> Result<Self, ReadError> {
let args = feature_tag;
Self::read_with_args(data, &args)
}
}
pub type Feature<'a> = TableRef<'a, FeatureMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Feature<'a> {
pub fn feature_params_offset(&self) -> Nullable<Offset16> {
let range = self.shape.feature_params_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feature_params(&self) -> Option<Result<FeatureParams<'a>, ReadError>> {
let data = self.data;
let args = self.feature_tag();
self.feature_params_offset().resolve_with_args(data, &args)
}
pub fn lookup_index_count(&self) -> u16 {
let range = self.shape.lookup_index_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lookup_list_indices(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.lookup_list_indices_byte_range();
self.data.read_array(range).unwrap()
}
pub(crate) fn feature_tag(&self) -> Tag {
self.shape.feature_tag
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Feature<'a> {
fn type_name(&self) -> &str {
"Feature"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"feature_params_offset",
FieldType::offset(self.feature_params_offset(), self.feature_params()),
)),
1usize => Some(Field::new("lookup_index_count", self.lookup_index_count())),
2usize => Some(Field::new(
"lookup_list_indices",
self.lookup_list_indices(),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Feature<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug)]
#[doc(hidden)]
pub struct LookupListMarker<T = ()> {
lookup_offsets_byte_len: usize,
offset_type: std::marker::PhantomData<*const T>,
}
impl<T> LookupListMarker<T> {
pub fn lookup_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookup_offsets_byte_range(&self) -> Range<usize> {
let start = self.lookup_count_byte_range().end;
start..start + self.lookup_offsets_byte_len
}
}
impl<T> Clone for LookupListMarker<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for LookupListMarker<T> {}
impl<'a, T> FontRead<'a> for LookupList<'a, T> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let lookup_count: u16 = cursor.read()?;
let lookup_offsets_byte_len = (lookup_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(lookup_offsets_byte_len);
cursor.finish(LookupListMarker {
lookup_offsets_byte_len,
offset_type: std::marker::PhantomData,
})
}
}
impl<'a> LookupList<'a, ()> {
#[allow(dead_code)]
pub(crate) fn into_concrete<T>(self) -> LookupList<'a, T> {
let TableRef { data, shape } = self;
TableRef {
shape: LookupListMarker {
lookup_offsets_byte_len: shape.lookup_offsets_byte_len,
offset_type: std::marker::PhantomData,
},
data,
}
}
}
impl<'a, T> LookupList<'a, T> {
#[allow(dead_code)]
pub(crate) fn of_unit_type(&self) -> LookupList<'a, ()> {
let TableRef { data, shape } = self;
TableRef {
shape: LookupListMarker {
lookup_offsets_byte_len: shape.lookup_offsets_byte_len,
offset_type: std::marker::PhantomData,
},
data: *data,
}
}
}
pub type LookupList<'a, T> = TableRef<'a, LookupListMarker<T>>;
#[allow(clippy::needless_lifetimes)]
impl<'a, T> LookupList<'a, T> {
pub fn lookup_count(&self) -> u16 {
let range = self.shape.lookup_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lookup_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.lookup_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn lookups(&self) -> ArrayOfOffsets<'a, T, Offset16>
where
T: FontRead<'a>,
{
let data = self.data;
let offsets = self.lookup_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> SomeTable<'a> for LookupList<'a, T> {
fn type_name(&self) -> &str {
"LookupList"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("lookup_count", self.lookup_count())),
1usize => Some({
let data = self.data;
Field::new(
"lookup_offsets",
FieldType::array_of_offsets(
better_type_name::<T>(),
self.lookup_offsets(),
move |off| {
let target = off.get().resolve::<T>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> std::fmt::Debug for LookupList<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug)]
#[doc(hidden)]
pub struct LookupMarker<T = ()> {
subtable_offsets_byte_len: usize,
mark_filtering_set_byte_start: Option<usize>,
offset_type: std::marker::PhantomData<*const T>,
}
impl<T> LookupMarker<T> {
pub fn lookup_type_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookup_flag_byte_range(&self) -> Range<usize> {
let start = self.lookup_type_byte_range().end;
start..start + LookupFlag::RAW_BYTE_LEN
}
pub fn sub_table_count_byte_range(&self) -> Range<usize> {
let start = self.lookup_flag_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn subtable_offsets_byte_range(&self) -> Range<usize> {
let start = self.sub_table_count_byte_range().end;
start..start + self.subtable_offsets_byte_len
}
pub fn mark_filtering_set_byte_range(&self) -> Option<Range<usize>> {
let start = self.mark_filtering_set_byte_start?;
Some(start..start + u16::RAW_BYTE_LEN)
}
}
impl<T> Clone for LookupMarker<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for LookupMarker<T> {}
impl<'a, T> FontRead<'a> for Lookup<'a, T> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let lookup_flag: LookupFlag = cursor.read()?;
let sub_table_count: u16 = cursor.read()?;
let subtable_offsets_byte_len = (sub_table_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(subtable_offsets_byte_len);
let mark_filtering_set_byte_start = lookup_flag
.contains(LookupFlag::USE_MARK_FILTERING_SET)
.then(|| cursor.position())
.transpose()?;
lookup_flag
.contains(LookupFlag::USE_MARK_FILTERING_SET)
.then(|| cursor.advance::<u16>());
cursor.finish(LookupMarker {
subtable_offsets_byte_len,
mark_filtering_set_byte_start,
offset_type: std::marker::PhantomData,
})
}
}
impl<'a> Lookup<'a, ()> {
#[allow(dead_code)]
pub(crate) fn into_concrete<T>(self) -> Lookup<'a, T> {
let TableRef { data, shape } = self;
TableRef {
shape: LookupMarker {
subtable_offsets_byte_len: shape.subtable_offsets_byte_len,
mark_filtering_set_byte_start: shape.mark_filtering_set_byte_start,
offset_type: std::marker::PhantomData,
},
data,
}
}
}
impl<'a, T> Lookup<'a, T> {
#[allow(dead_code)]
pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
let TableRef { data, shape } = self;
TableRef {
shape: LookupMarker {
subtable_offsets_byte_len: shape.subtable_offsets_byte_len,
mark_filtering_set_byte_start: shape.mark_filtering_set_byte_start,
offset_type: std::marker::PhantomData,
},
data: *data,
}
}
}
pub type Lookup<'a, T> = TableRef<'a, LookupMarker<T>>;
#[allow(clippy::needless_lifetimes)]
impl<'a, T> Lookup<'a, T> {
pub fn lookup_type(&self) -> u16 {
let range = self.shape.lookup_type_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lookup_flag(&self) -> LookupFlag {
let range = self.shape.lookup_flag_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn sub_table_count(&self) -> u16 {
let range = self.shape.sub_table_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn subtable_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.subtable_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn subtables(&self) -> ArrayOfOffsets<'a, T, Offset16>
where
T: FontRead<'a>,
{
let data = self.data;
let offsets = self.subtable_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
pub fn mark_filtering_set(&self) -> Option<u16> {
let range = self.shape.mark_filtering_set_byte_range()?;
Some(self.data.read_at(range.start).unwrap())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> SomeTable<'a> for Lookup<'a, T> {
fn type_name(&self) -> &str {
"Lookup"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
let lookup_flag = self.lookup_flag();
match idx {
0usize => Some(Field::new("lookup_type", self.lookup_type())),
1usize => Some(Field::new("lookup_flag", self.traverse_lookup_flag())),
2usize => Some(Field::new("sub_table_count", self.sub_table_count())),
3usize => Some({
let data = self.data;
Field::new(
"subtable_offsets",
FieldType::array_of_offsets(
better_type_name::<T>(),
self.subtable_offsets(),
move |off| {
let target = off.get().resolve::<T>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
4usize if lookup_flag.contains(LookupFlag::USE_MARK_FILTERING_SET) => Some(Field::new(
"mark_filtering_set",
self.mark_filtering_set().unwrap(),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> std::fmt::Debug for Lookup<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for CoverageFormat1Marker {
const FORMAT: u16 = 1;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CoverageFormat1Marker {
glyph_array_byte_len: usize,
}
impl CoverageFormat1Marker {
pub fn coverage_format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn glyph_count_byte_range(&self) -> Range<usize> {
let start = self.coverage_format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn glyph_array_byte_range(&self) -> Range<usize> {
let start = self.glyph_count_byte_range().end;
start..start + self.glyph_array_byte_len
}
}
impl<'a> FontRead<'a> for CoverageFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let glyph_count: u16 = cursor.read()?;
let glyph_array_byte_len = (glyph_count as usize)
.checked_mul(GlyphId16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(glyph_array_byte_len);
cursor.finish(CoverageFormat1Marker {
glyph_array_byte_len,
})
}
}
pub type CoverageFormat1<'a> = TableRef<'a, CoverageFormat1Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> CoverageFormat1<'a> {
pub fn coverage_format(&self) -> u16 {
let range = self.shape.coverage_format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn glyph_count(&self) -> u16 {
let range = self.shape.glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.shape.glyph_array_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for CoverageFormat1<'a> {
fn type_name(&self) -> &str {
"CoverageFormat1"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("coverage_format", self.coverage_format())),
1usize => Some(Field::new("glyph_count", self.glyph_count())),
2usize => Some(Field::new("glyph_array", self.glyph_array())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for CoverageFormat1<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for CoverageFormat2Marker {
const FORMAT: u16 = 2;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CoverageFormat2Marker {
range_records_byte_len: usize,
}
impl CoverageFormat2Marker {
pub fn coverage_format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn range_count_byte_range(&self) -> Range<usize> {
let start = self.coverage_format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn range_records_byte_range(&self) -> Range<usize> {
let start = self.range_count_byte_range().end;
start..start + self.range_records_byte_len
}
}
impl<'a> FontRead<'a> for CoverageFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let range_count: u16 = cursor.read()?;
let range_records_byte_len = (range_count as usize)
.checked_mul(RangeRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(range_records_byte_len);
cursor.finish(CoverageFormat2Marker {
range_records_byte_len,
})
}
}
pub type CoverageFormat2<'a> = TableRef<'a, CoverageFormat2Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> CoverageFormat2<'a> {
pub fn coverage_format(&self) -> u16 {
let range = self.shape.coverage_format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn range_count(&self) -> u16 {
let range = self.shape.range_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn range_records(&self) -> &'a [RangeRecord] {
let range = self.shape.range_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for CoverageFormat2<'a> {
fn type_name(&self) -> &str {
"CoverageFormat2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("coverage_format", self.coverage_format())),
1usize => Some(Field::new("range_count", self.range_count())),
2usize => Some(Field::new(
"range_records",
traversal::FieldType::array_of_records(
stringify!(RangeRecord),
self.range_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for CoverageFormat2<'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 RangeRecord {
pub start_glyph_id: BigEndian<GlyphId16>,
pub end_glyph_id: BigEndian<GlyphId16>,
pub start_coverage_index: BigEndian<u16>,
}
impl RangeRecord {
pub fn start_glyph_id(&self) -> GlyphId16 {
self.start_glyph_id.get()
}
pub fn end_glyph_id(&self) -> GlyphId16 {
self.end_glyph_id.get()
}
pub fn start_coverage_index(&self) -> u16 {
self.start_coverage_index.get()
}
}
impl FixedSize for RangeRecord {
const RAW_BYTE_LEN: usize =
GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for RangeRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "RangeRecord",
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(
"start_coverage_index",
self.start_coverage_index(),
)),
_ => None,
}),
data,
}
}
}
#[derive(Clone)]
pub enum CoverageTable<'a> {
Format1(CoverageFormat1<'a>),
Format2(CoverageFormat2<'a>),
}
impl<'a> CoverageTable<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Format1(item) => item.offset_data(),
Self::Format2(item) => item.offset_data(),
}
}
pub fn coverage_format(&self) -> u16 {
match self {
Self::Format1(item) => item.coverage_format(),
Self::Format2(item) => item.coverage_format(),
}
}
}
impl<'a> FontRead<'a> for CoverageTable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
CoverageFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
CoverageFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> CoverageTable<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format1(table) => table,
Self::Format2(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for CoverageTable<'_> {
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 CoverageTable<'a> {
fn type_name(&self) -> &str {
self.dyn_inner().type_name()
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
self.dyn_inner().get_field(idx)
}
}
impl Format<u16> for ClassDefFormat1Marker {
const FORMAT: u16 = 1;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ClassDefFormat1Marker {
class_value_array_byte_len: usize,
}
impl ClassDefFormat1Marker {
pub fn class_format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
let start = self.class_format_byte_range().end;
start..start + GlyphId16::RAW_BYTE_LEN
}
pub fn glyph_count_byte_range(&self) -> Range<usize> {
let start = self.start_glyph_id_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn class_value_array_byte_range(&self) -> Range<usize> {
let start = self.glyph_count_byte_range().end;
start..start + self.class_value_array_byte_len
}
}
impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<GlyphId16>();
let glyph_count: u16 = cursor.read()?;
let class_value_array_byte_len = (glyph_count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(class_value_array_byte_len);
cursor.finish(ClassDefFormat1Marker {
class_value_array_byte_len,
})
}
}
pub type ClassDefFormat1<'a> = TableRef<'a, ClassDefFormat1Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassDefFormat1<'a> {
pub fn class_format(&self) -> u16 {
let range = self.shape.class_format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn start_glyph_id(&self) -> GlyphId16 {
let range = self.shape.start_glyph_id_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn glyph_count(&self) -> u16 {
let range = self.shape.glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.class_value_array_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClassDefFormat1<'a> {
fn type_name(&self) -> &str {
"ClassDefFormat1"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("class_format", self.class_format())),
1usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
2usize => Some(Field::new("glyph_count", self.glyph_count())),
3usize => Some(Field::new("class_value_array", self.class_value_array())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ClassDefFormat1<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for ClassDefFormat2Marker {
const FORMAT: u16 = 2;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ClassDefFormat2Marker {
class_range_records_byte_len: usize,
}
impl ClassDefFormat2Marker {
pub fn class_format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn class_range_count_byte_range(&self) -> Range<usize> {
let start = self.class_format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn class_range_records_byte_range(&self) -> Range<usize> {
let start = self.class_range_count_byte_range().end;
start..start + self.class_range_records_byte_len
}
}
impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let class_range_count: u16 = cursor.read()?;
let class_range_records_byte_len = (class_range_count as usize)
.checked_mul(ClassRangeRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(class_range_records_byte_len);
cursor.finish(ClassDefFormat2Marker {
class_range_records_byte_len,
})
}
}
pub type ClassDefFormat2<'a> = TableRef<'a, ClassDefFormat2Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassDefFormat2<'a> {
pub fn class_format(&self) -> u16 {
let range = self.shape.class_format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn class_range_count(&self) -> u16 {
let range = self.shape.class_range_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
let range = self.shape.class_range_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClassDefFormat2<'a> {
fn type_name(&self) -> &str {
"ClassDefFormat2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("class_format", self.class_format())),
1usize => Some(Field::new("class_range_count", self.class_range_count())),
2usize => Some(Field::new(
"class_range_records",
traversal::FieldType::array_of_records(
stringify!(ClassRangeRecord),
self.class_range_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ClassDefFormat2<'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 ClassRangeRecord {
pub start_glyph_id: BigEndian<GlyphId16>,
pub end_glyph_id: BigEndian<GlyphId16>,
pub class: BigEndian<u16>,
}
impl ClassRangeRecord {
pub fn start_glyph_id(&self) -> GlyphId16 {
self.start_glyph_id.get()
}
pub fn end_glyph_id(&self) -> GlyphId16 {
self.end_glyph_id.get()
}
pub fn class(&self) -> u16 {
self.class.get()
}
}
impl FixedSize for ClassRangeRecord {
const RAW_BYTE_LEN: usize =
GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ClassRangeRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ClassRangeRecord",
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("class", self.class())),
_ => None,
}),
data,
}
}
}
#[derive(Clone)]
pub enum ClassDef<'a> {
Format1(ClassDefFormat1<'a>),
Format2(ClassDefFormat2<'a>),
}
impl<'a> ClassDef<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Format1(item) => item.offset_data(),
Self::Format2(item) => item.offset_data(),
}
}
pub fn class_format(&self) -> u16 {
match self {
Self::Format1(item) => item.class_format(),
Self::Format2(item) => item.class_format(),
}
}
}
impl<'a> FontRead<'a> for ClassDef<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
ClassDefFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
ClassDefFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> ClassDef<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format1(table) => table,
Self::Format2(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for ClassDef<'_> {
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 ClassDef<'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)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct SequenceLookupRecord {
pub sequence_index: BigEndian<u16>,
pub lookup_list_index: BigEndian<u16>,
}
impl SequenceLookupRecord {
pub fn sequence_index(&self) -> u16 {
self.sequence_index.get()
}
pub fn lookup_list_index(&self) -> u16 {
self.lookup_list_index.get()
}
}
impl FixedSize for SequenceLookupRecord {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for SequenceLookupRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "SequenceLookupRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("sequence_index", self.sequence_index())),
1usize => Some(Field::new("lookup_list_index", self.lookup_list_index())),
_ => None,
}),
data,
}
}
}
impl Format<u16> for SequenceContextFormat1Marker {
const FORMAT: u16 = 1;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SequenceContextFormat1Marker {
seq_rule_set_offsets_byte_len: usize,
}
impl SequenceContextFormat1Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn coverage_offset_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
let start = self.coverage_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
let start = self.seq_rule_set_count_byte_range().end;
start..start + self.seq_rule_set_offsets_byte_len
}
}
impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<Offset16>();
let seq_rule_set_count: u16 = cursor.read()?;
let seq_rule_set_offsets_byte_len = (seq_rule_set_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_rule_set_offsets_byte_len);
cursor.finish(SequenceContextFormat1Marker {
seq_rule_set_offsets_byte_len,
})
}
}
pub type SequenceContextFormat1<'a> = TableRef<'a, SequenceContextFormat1Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceContextFormat1<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.shape.coverage_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
let data = self.data;
self.coverage_offset().resolve(data)
}
pub fn seq_rule_set_count(&self) -> u16 {
let range = self.shape.seq_rule_set_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.shape.seq_rule_set_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet<'a>, Offset16> {
let data = self.data;
let offsets = self.seq_rule_set_offsets();
ArrayOfNullableOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SequenceContextFormat1<'a> {
fn type_name(&self) -> &str {
"SequenceContextFormat1"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new(
"coverage_offset",
FieldType::offset(self.coverage_offset(), self.coverage()),
)),
2usize => Some(Field::new("seq_rule_set_count", self.seq_rule_set_count())),
3usize => Some({
let data = self.data;
Field::new(
"seq_rule_set_offsets",
FieldType::array_of_offsets(
better_type_name::<SequenceRuleSet>(),
self.seq_rule_set_offsets(),
move |off| {
let target = off.get().resolve::<SequenceRuleSet>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SequenceContextFormat1<'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 SequenceRuleSetMarker {
seq_rule_offsets_byte_len: usize,
}
impl SequenceRuleSetMarker {
pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
let start = self.seq_rule_count_byte_range().end;
start..start + self.seq_rule_offsets_byte_len
}
}
impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let seq_rule_count: u16 = cursor.read()?;
let seq_rule_offsets_byte_len = (seq_rule_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_rule_offsets_byte_len);
cursor.finish(SequenceRuleSetMarker {
seq_rule_offsets_byte_len,
})
}
}
pub type SequenceRuleSet<'a> = TableRef<'a, SequenceRuleSetMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceRuleSet<'a> {
pub fn seq_rule_count(&self) -> u16 {
let range = self.shape.seq_rule_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.seq_rule_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
let data = self.data;
let offsets = self.seq_rule_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SequenceRuleSet<'a> {
fn type_name(&self) -> &str {
"SequenceRuleSet"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("seq_rule_count", self.seq_rule_count())),
1usize => Some({
let data = self.data;
Field::new(
"seq_rule_offsets",
FieldType::array_of_offsets(
better_type_name::<SequenceRule>(),
self.seq_rule_offsets(),
move |off| {
let target = off.get().resolve::<SequenceRule>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SequenceRuleSet<'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 SequenceRuleMarker {
input_sequence_byte_len: usize,
seq_lookup_records_byte_len: usize,
}
impl SequenceRuleMarker {
pub fn glyph_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
let start = self.glyph_count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn input_sequence_byte_range(&self) -> Range<usize> {
let start = self.seq_lookup_count_byte_range().end;
start..start + self.input_sequence_byte_len
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let start = self.input_sequence_byte_range().end;
start..start + self.seq_lookup_records_byte_len
}
}
impl<'a> FontRead<'a> for SequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let glyph_count: u16 = cursor.read()?;
let seq_lookup_count: u16 = cursor.read()?;
let input_sequence_byte_len = (transforms::subtract(glyph_count, 1_usize))
.checked_mul(GlyphId16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(input_sequence_byte_len);
let seq_lookup_records_byte_len = (seq_lookup_count as usize)
.checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_lookup_records_byte_len);
cursor.finish(SequenceRuleMarker {
input_sequence_byte_len,
seq_lookup_records_byte_len,
})
}
}
pub type SequenceRule<'a> = TableRef<'a, SequenceRuleMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceRule<'a> {
pub fn glyph_count(&self) -> u16 {
let range = self.shape.glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.shape.seq_lookup_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.shape.input_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.shape.seq_lookup_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SequenceRule<'a> {
fn type_name(&self) -> &str {
"SequenceRule"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("glyph_count", self.glyph_count())),
1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2usize => Some(Field::new("input_sequence", self.input_sequence())),
3usize => Some(Field::new(
"seq_lookup_records",
traversal::FieldType::array_of_records(
stringify!(SequenceLookupRecord),
self.seq_lookup_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SequenceRule<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for SequenceContextFormat2Marker {
const FORMAT: u16 = 2;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SequenceContextFormat2Marker {
class_seq_rule_set_offsets_byte_len: usize,
}
impl SequenceContextFormat2Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn coverage_offset_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn class_def_offset_byte_range(&self) -> Range<usize> {
let start = self.coverage_offset_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
let start = self.class_def_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
let start = self.class_seq_rule_set_count_byte_range().end;
start..start + self.class_seq_rule_set_offsets_byte_len
}
}
impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<Offset16>();
cursor.advance::<Offset16>();
let class_seq_rule_set_count: u16 = cursor.read()?;
let class_seq_rule_set_offsets_byte_len = (class_seq_rule_set_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(class_seq_rule_set_offsets_byte_len);
cursor.finish(SequenceContextFormat2Marker {
class_seq_rule_set_offsets_byte_len,
})
}
}
pub type SequenceContextFormat2<'a> = TableRef<'a, SequenceContextFormat2Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceContextFormat2<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.shape.coverage_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
let data = self.data;
self.coverage_offset().resolve(data)
}
pub fn class_def_offset(&self) -> Offset16 {
let range = self.shape.class_def_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
let data = self.data;
self.class_def_offset().resolve(data)
}
pub fn class_seq_rule_set_count(&self) -> u16 {
let range = self.shape.class_seq_rule_set_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.shape.class_seq_rule_set_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn class_seq_rule_sets(
&self,
) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet<'a>, Offset16> {
let data = self.data;
let offsets = self.class_seq_rule_set_offsets();
ArrayOfNullableOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SequenceContextFormat2<'a> {
fn type_name(&self) -> &str {
"SequenceContextFormat2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new(
"coverage_offset",
FieldType::offset(self.coverage_offset(), self.coverage()),
)),
2usize => Some(Field::new(
"class_def_offset",
FieldType::offset(self.class_def_offset(), self.class_def()),
)),
3usize => Some(Field::new(
"class_seq_rule_set_count",
self.class_seq_rule_set_count(),
)),
4usize => Some({
let data = self.data;
Field::new(
"class_seq_rule_set_offsets",
FieldType::array_of_offsets(
better_type_name::<ClassSequenceRuleSet>(),
self.class_seq_rule_set_offsets(),
move |off| {
let target = off.get().resolve::<ClassSequenceRuleSet>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SequenceContextFormat2<'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 ClassSequenceRuleSetMarker {
class_seq_rule_offsets_byte_len: usize,
}
impl ClassSequenceRuleSetMarker {
pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
let start = self.class_seq_rule_count_byte_range().end;
start..start + self.class_seq_rule_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let class_seq_rule_count: u16 = cursor.read()?;
let class_seq_rule_offsets_byte_len = (class_seq_rule_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(class_seq_rule_offsets_byte_len);
cursor.finish(ClassSequenceRuleSetMarker {
class_seq_rule_offsets_byte_len,
})
}
}
pub type ClassSequenceRuleSet<'a> = TableRef<'a, ClassSequenceRuleSetMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassSequenceRuleSet<'a> {
pub fn class_seq_rule_count(&self) -> u16 {
let range = self.shape.class_seq_rule_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.class_seq_rule_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset16> {
let data = self.data;
let offsets = self.class_seq_rule_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClassSequenceRuleSet<'a> {
fn type_name(&self) -> &str {
"ClassSequenceRuleSet"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"class_seq_rule_count",
self.class_seq_rule_count(),
)),
1usize => Some({
let data = self.data;
Field::new(
"class_seq_rule_offsets",
FieldType::array_of_offsets(
better_type_name::<ClassSequenceRule>(),
self.class_seq_rule_offsets(),
move |off| {
let target = off.get().resolve::<ClassSequenceRule>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ClassSequenceRuleSet<'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 ClassSequenceRuleMarker {
input_sequence_byte_len: usize,
seq_lookup_records_byte_len: usize,
}
impl ClassSequenceRuleMarker {
pub fn glyph_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
let start = self.glyph_count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn input_sequence_byte_range(&self) -> Range<usize> {
let start = self.seq_lookup_count_byte_range().end;
start..start + self.input_sequence_byte_len
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let start = self.input_sequence_byte_range().end;
start..start + self.seq_lookup_records_byte_len
}
}
impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let glyph_count: u16 = cursor.read()?;
let seq_lookup_count: u16 = cursor.read()?;
let input_sequence_byte_len = (transforms::subtract(glyph_count, 1_usize))
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(input_sequence_byte_len);
let seq_lookup_records_byte_len = (seq_lookup_count as usize)
.checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_lookup_records_byte_len);
cursor.finish(ClassSequenceRuleMarker {
input_sequence_byte_len,
seq_lookup_records_byte_len,
})
}
}
pub type ClassSequenceRule<'a> = TableRef<'a, ClassSequenceRuleMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassSequenceRule<'a> {
pub fn glyph_count(&self) -> u16 {
let range = self.shape.glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.shape.seq_lookup_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.input_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.shape.seq_lookup_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ClassSequenceRule<'a> {
fn type_name(&self) -> &str {
"ClassSequenceRule"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("glyph_count", self.glyph_count())),
1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2usize => Some(Field::new("input_sequence", self.input_sequence())),
3usize => Some(Field::new(
"seq_lookup_records",
traversal::FieldType::array_of_records(
stringify!(SequenceLookupRecord),
self.seq_lookup_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ClassSequenceRule<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for SequenceContextFormat3Marker {
const FORMAT: u16 = 3;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SequenceContextFormat3Marker {
coverage_offsets_byte_len: usize,
seq_lookup_records_byte_len: usize,
}
impl SequenceContextFormat3Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn glyph_count_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
let start = self.glyph_count_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
let start = self.seq_lookup_count_byte_range().end;
start..start + self.coverage_offsets_byte_len
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let start = self.coverage_offsets_byte_range().end;
start..start + self.seq_lookup_records_byte_len
}
}
impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let glyph_count: u16 = cursor.read()?;
let seq_lookup_count: u16 = cursor.read()?;
let coverage_offsets_byte_len = (glyph_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(coverage_offsets_byte_len);
let seq_lookup_records_byte_len = (seq_lookup_count as usize)
.checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_lookup_records_byte_len);
cursor.finish(SequenceContextFormat3Marker {
coverage_offsets_byte_len,
seq_lookup_records_byte_len,
})
}
}
pub type SequenceContextFormat3<'a> = TableRef<'a, SequenceContextFormat3Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceContextFormat3<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn glyph_count(&self) -> u16 {
let range = self.shape.glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.shape.seq_lookup_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.coverage_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
let data = self.data;
let offsets = self.coverage_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.shape.seq_lookup_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SequenceContextFormat3<'a> {
fn type_name(&self) -> &str {
"SequenceContextFormat3"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("glyph_count", self.glyph_count())),
2usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3usize => Some({
let data = self.data;
Field::new(
"coverage_offsets",
FieldType::array_of_offsets(
better_type_name::<CoverageTable>(),
self.coverage_offsets(),
move |off| {
let target = off.get().resolve::<CoverageTable>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
4usize => Some(Field::new(
"seq_lookup_records",
traversal::FieldType::array_of_records(
stringify!(SequenceLookupRecord),
self.seq_lookup_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SequenceContextFormat3<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone)]
pub enum SequenceContext<'a> {
Format1(SequenceContextFormat1<'a>),
Format2(SequenceContextFormat2<'a>),
Format3(SequenceContextFormat3<'a>),
}
impl<'a> SequenceContext<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Format1(item) => item.offset_data(),
Self::Format2(item) => item.offset_data(),
Self::Format3(item) => item.offset_data(),
}
}
pub fn format(&self) -> u16 {
match self {
Self::Format1(item) => item.format(),
Self::Format2(item) => item.format(),
Self::Format3(item) => item.format(),
}
}
}
impl<'a> FontRead<'a> for SequenceContext<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
SequenceContextFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
SequenceContextFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
SequenceContextFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SequenceContext<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format1(table) => table,
Self::Format2(table) => table,
Self::Format3(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for SequenceContext<'_> {
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 SequenceContext<'a> {
fn type_name(&self) -> &str {
self.dyn_inner().type_name()
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
self.dyn_inner().get_field(idx)
}
}
impl Format<u16> for ChainedSequenceContextFormat1Marker {
const FORMAT: u16 = 1;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ChainedSequenceContextFormat1Marker {
chained_seq_rule_set_offsets_byte_len: usize,
}
impl ChainedSequenceContextFormat1Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn coverage_offset_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
let start = self.coverage_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
let start = self.chained_seq_rule_set_count_byte_range().end;
start..start + self.chained_seq_rule_set_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<Offset16>();
let chained_seq_rule_set_count: u16 = cursor.read()?;
let chained_seq_rule_set_offsets_byte_len = (chained_seq_rule_set_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(chained_seq_rule_set_offsets_byte_len);
cursor.finish(ChainedSequenceContextFormat1Marker {
chained_seq_rule_set_offsets_byte_len,
})
}
}
pub type ChainedSequenceContextFormat1<'a> = TableRef<'a, ChainedSequenceContextFormat1Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceContextFormat1<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.shape.coverage_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
let data = self.data;
self.coverage_offset().resolve(data)
}
pub fn chained_seq_rule_set_count(&self) -> u16 {
let range = self.shape.chained_seq_rule_set_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.shape.chained_seq_rule_set_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn chained_seq_rule_sets(
&self,
) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet<'a>, Offset16> {
let data = self.data;
let offsets = self.chained_seq_rule_set_offsets();
ArrayOfNullableOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ChainedSequenceContextFormat1<'a> {
fn type_name(&self) -> &str {
"ChainedSequenceContextFormat1"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new(
"coverage_offset",
FieldType::offset(self.coverage_offset(), self.coverage()),
)),
2usize => Some(Field::new(
"chained_seq_rule_set_count",
self.chained_seq_rule_set_count(),
)),
3usize => Some({
let data = self.data;
Field::new(
"chained_seq_rule_set_offsets",
FieldType::array_of_offsets(
better_type_name::<ChainedSequenceRuleSet>(),
self.chained_seq_rule_set_offsets(),
move |off| {
let target = off.get().resolve::<ChainedSequenceRuleSet>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ChainedSequenceContextFormat1<'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 ChainedSequenceRuleSetMarker {
chained_seq_rule_offsets_byte_len: usize,
}
impl ChainedSequenceRuleSetMarker {
pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
let start = self.chained_seq_rule_count_byte_range().end;
start..start + self.chained_seq_rule_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let chained_seq_rule_count: u16 = cursor.read()?;
let chained_seq_rule_offsets_byte_len = (chained_seq_rule_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(chained_seq_rule_offsets_byte_len);
cursor.finish(ChainedSequenceRuleSetMarker {
chained_seq_rule_offsets_byte_len,
})
}
}
pub type ChainedSequenceRuleSet<'a> = TableRef<'a, ChainedSequenceRuleSetMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceRuleSet<'a> {
pub fn chained_seq_rule_count(&self) -> u16 {
let range = self.shape.chained_seq_rule_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.chained_seq_rule_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule<'a>, Offset16> {
let data = self.data;
let offsets = self.chained_seq_rule_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ChainedSequenceRuleSet<'a> {
fn type_name(&self) -> &str {
"ChainedSequenceRuleSet"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"chained_seq_rule_count",
self.chained_seq_rule_count(),
)),
1usize => Some({
let data = self.data;
Field::new(
"chained_seq_rule_offsets",
FieldType::array_of_offsets(
better_type_name::<ChainedSequenceRule>(),
self.chained_seq_rule_offsets(),
move |off| {
let target = off.get().resolve::<ChainedSequenceRule>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ChainedSequenceRuleSet<'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 ChainedSequenceRuleMarker {
backtrack_sequence_byte_len: usize,
input_sequence_byte_len: usize,
lookahead_sequence_byte_len: usize,
seq_lookup_records_byte_len: usize,
}
impl ChainedSequenceRuleMarker {
pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
let start = self.backtrack_glyph_count_byte_range().end;
start..start + self.backtrack_sequence_byte_len
}
pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
let start = self.backtrack_sequence_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn input_sequence_byte_range(&self) -> Range<usize> {
let start = self.input_glyph_count_byte_range().end;
start..start + self.input_sequence_byte_len
}
pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
let start = self.input_sequence_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
let start = self.lookahead_glyph_count_byte_range().end;
start..start + self.lookahead_sequence_byte_len
}
pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
let start = self.lookahead_sequence_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let start = self.seq_lookup_count_byte_range().end;
start..start + self.seq_lookup_records_byte_len
}
}
impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let backtrack_glyph_count: u16 = cursor.read()?;
let backtrack_sequence_byte_len = (backtrack_glyph_count as usize)
.checked_mul(GlyphId16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(backtrack_sequence_byte_len);
let input_glyph_count: u16 = cursor.read()?;
let input_sequence_byte_len = (transforms::subtract(input_glyph_count, 1_usize))
.checked_mul(GlyphId16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(input_sequence_byte_len);
let lookahead_glyph_count: u16 = cursor.read()?;
let lookahead_sequence_byte_len = (lookahead_glyph_count as usize)
.checked_mul(GlyphId16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(lookahead_sequence_byte_len);
let seq_lookup_count: u16 = cursor.read()?;
let seq_lookup_records_byte_len = (seq_lookup_count as usize)
.checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_lookup_records_byte_len);
cursor.finish(ChainedSequenceRuleMarker {
backtrack_sequence_byte_len,
input_sequence_byte_len,
lookahead_sequence_byte_len,
seq_lookup_records_byte_len,
})
}
}
pub type ChainedSequenceRule<'a> = TableRef<'a, ChainedSequenceRuleMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceRule<'a> {
pub fn backtrack_glyph_count(&self) -> u16 {
let range = self.shape.backtrack_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.shape.backtrack_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn input_glyph_count(&self) -> u16 {
let range = self.shape.input_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.shape.input_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn lookahead_glyph_count(&self) -> u16 {
let range = self.shape.lookahead_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.shape.lookahead_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.shape.seq_lookup_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.shape.seq_lookup_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ChainedSequenceRule<'a> {
fn type_name(&self) -> &str {
"ChainedSequenceRule"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"backtrack_glyph_count",
self.backtrack_glyph_count(),
)),
1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3usize => Some(Field::new("input_sequence", self.input_sequence())),
4usize => Some(Field::new(
"lookahead_glyph_count",
self.lookahead_glyph_count(),
)),
5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
7usize => Some(Field::new(
"seq_lookup_records",
traversal::FieldType::array_of_records(
stringify!(SequenceLookupRecord),
self.seq_lookup_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ChainedSequenceRule<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for ChainedSequenceContextFormat2Marker {
const FORMAT: u16 = 2;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ChainedSequenceContextFormat2Marker {
chained_class_seq_rule_set_offsets_byte_len: usize,
}
impl ChainedSequenceContextFormat2Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn coverage_offset_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
let start = self.coverage_offset_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
let start = self.backtrack_class_def_offset_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
let start = self.input_class_def_offset_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
let start = self.lookahead_class_def_offset_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
let start = self.chained_class_seq_rule_set_count_byte_range().end;
start..start + self.chained_class_seq_rule_set_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<Offset16>();
cursor.advance::<Offset16>();
cursor.advance::<Offset16>();
cursor.advance::<Offset16>();
let chained_class_seq_rule_set_count: u16 = cursor.read()?;
let chained_class_seq_rule_set_offsets_byte_len = (chained_class_seq_rule_set_count
as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(chained_class_seq_rule_set_offsets_byte_len);
cursor.finish(ChainedSequenceContextFormat2Marker {
chained_class_seq_rule_set_offsets_byte_len,
})
}
}
pub type ChainedSequenceContextFormat2<'a> = TableRef<'a, ChainedSequenceContextFormat2Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceContextFormat2<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.shape.coverage_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
let data = self.data;
self.coverage_offset().resolve(data)
}
pub fn backtrack_class_def_offset(&self) -> Offset16 {
let range = self.shape.backtrack_class_def_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
let data = self.data;
self.backtrack_class_def_offset().resolve(data)
}
pub fn input_class_def_offset(&self) -> Offset16 {
let range = self.shape.input_class_def_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
let data = self.data;
self.input_class_def_offset().resolve(data)
}
pub fn lookahead_class_def_offset(&self) -> Offset16 {
let range = self.shape.lookahead_class_def_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
let data = self.data;
self.lookahead_class_def_offset().resolve(data)
}
pub fn chained_class_seq_rule_set_count(&self) -> u16 {
let range = self.shape.chained_class_seq_rule_set_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.shape.chained_class_seq_rule_set_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn chained_class_seq_rule_sets(
&self,
) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet<'a>, Offset16> {
let data = self.data;
let offsets = self.chained_class_seq_rule_set_offsets();
ArrayOfNullableOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ChainedSequenceContextFormat2<'a> {
fn type_name(&self) -> &str {
"ChainedSequenceContextFormat2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new(
"coverage_offset",
FieldType::offset(self.coverage_offset(), self.coverage()),
)),
2usize => Some(Field::new(
"backtrack_class_def_offset",
FieldType::offset(
self.backtrack_class_def_offset(),
self.backtrack_class_def(),
),
)),
3usize => Some(Field::new(
"input_class_def_offset",
FieldType::offset(self.input_class_def_offset(), self.input_class_def()),
)),
4usize => Some(Field::new(
"lookahead_class_def_offset",
FieldType::offset(
self.lookahead_class_def_offset(),
self.lookahead_class_def(),
),
)),
5usize => Some(Field::new(
"chained_class_seq_rule_set_count",
self.chained_class_seq_rule_set_count(),
)),
6usize => Some({
let data = self.data;
Field::new(
"chained_class_seq_rule_set_offsets",
FieldType::array_of_offsets(
better_type_name::<ChainedClassSequenceRuleSet>(),
self.chained_class_seq_rule_set_offsets(),
move |off| {
let target = off.get().resolve::<ChainedClassSequenceRuleSet>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ChainedSequenceContextFormat2<'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 ChainedClassSequenceRuleSetMarker {
chained_class_seq_rule_offsets_byte_len: usize,
}
impl ChainedClassSequenceRuleSetMarker {
pub fn chained_class_seq_rule_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
let start = self.chained_class_seq_rule_count_byte_range().end;
start..start + self.chained_class_seq_rule_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let chained_class_seq_rule_count: u16 = cursor.read()?;
let chained_class_seq_rule_offsets_byte_len = (chained_class_seq_rule_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(chained_class_seq_rule_offsets_byte_len);
cursor.finish(ChainedClassSequenceRuleSetMarker {
chained_class_seq_rule_offsets_byte_len,
})
}
}
pub type ChainedClassSequenceRuleSet<'a> = TableRef<'a, ChainedClassSequenceRuleSetMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedClassSequenceRuleSet<'a> {
pub fn chained_class_seq_rule_count(&self) -> u16 {
let range = self.shape.chained_class_seq_rule_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.chained_class_seq_rule_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn chained_class_seq_rules(
&self,
) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset16> {
let data = self.data;
let offsets = self.chained_class_seq_rule_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ChainedClassSequenceRuleSet<'a> {
fn type_name(&self) -> &str {
"ChainedClassSequenceRuleSet"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"chained_class_seq_rule_count",
self.chained_class_seq_rule_count(),
)),
1usize => Some({
let data = self.data;
Field::new(
"chained_class_seq_rule_offsets",
FieldType::array_of_offsets(
better_type_name::<ChainedClassSequenceRule>(),
self.chained_class_seq_rule_offsets(),
move |off| {
let target = off.get().resolve::<ChainedClassSequenceRule>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ChainedClassSequenceRuleSet<'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 ChainedClassSequenceRuleMarker {
backtrack_sequence_byte_len: usize,
input_sequence_byte_len: usize,
lookahead_sequence_byte_len: usize,
seq_lookup_records_byte_len: usize,
}
impl ChainedClassSequenceRuleMarker {
pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
let start = self.backtrack_glyph_count_byte_range().end;
start..start + self.backtrack_sequence_byte_len
}
pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
let start = self.backtrack_sequence_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn input_sequence_byte_range(&self) -> Range<usize> {
let start = self.input_glyph_count_byte_range().end;
start..start + self.input_sequence_byte_len
}
pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
let start = self.input_sequence_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
let start = self.lookahead_glyph_count_byte_range().end;
start..start + self.lookahead_sequence_byte_len
}
pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
let start = self.lookahead_sequence_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let start = self.seq_lookup_count_byte_range().end;
start..start + self.seq_lookup_records_byte_len
}
}
impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let backtrack_glyph_count: u16 = cursor.read()?;
let backtrack_sequence_byte_len = (backtrack_glyph_count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(backtrack_sequence_byte_len);
let input_glyph_count: u16 = cursor.read()?;
let input_sequence_byte_len = (transforms::subtract(input_glyph_count, 1_usize))
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(input_sequence_byte_len);
let lookahead_glyph_count: u16 = cursor.read()?;
let lookahead_sequence_byte_len = (lookahead_glyph_count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(lookahead_sequence_byte_len);
let seq_lookup_count: u16 = cursor.read()?;
let seq_lookup_records_byte_len = (seq_lookup_count as usize)
.checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_lookup_records_byte_len);
cursor.finish(ChainedClassSequenceRuleMarker {
backtrack_sequence_byte_len,
input_sequence_byte_len,
lookahead_sequence_byte_len,
seq_lookup_records_byte_len,
})
}
}
pub type ChainedClassSequenceRule<'a> = TableRef<'a, ChainedClassSequenceRuleMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedClassSequenceRule<'a> {
pub fn backtrack_glyph_count(&self) -> u16 {
let range = self.shape.backtrack_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.backtrack_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn input_glyph_count(&self) -> u16 {
let range = self.shape.input_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.input_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn lookahead_glyph_count(&self) -> u16 {
let range = self.shape.lookahead_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.lookahead_sequence_byte_range();
self.data.read_array(range).unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.shape.seq_lookup_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.shape.seq_lookup_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ChainedClassSequenceRule<'a> {
fn type_name(&self) -> &str {
"ChainedClassSequenceRule"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"backtrack_glyph_count",
self.backtrack_glyph_count(),
)),
1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3usize => Some(Field::new("input_sequence", self.input_sequence())),
4usize => Some(Field::new(
"lookahead_glyph_count",
self.lookahead_glyph_count(),
)),
5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
7usize => Some(Field::new(
"seq_lookup_records",
traversal::FieldType::array_of_records(
stringify!(SequenceLookupRecord),
self.seq_lookup_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ChainedClassSequenceRule<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for ChainedSequenceContextFormat3Marker {
const FORMAT: u16 = 3;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ChainedSequenceContextFormat3Marker {
backtrack_coverage_offsets_byte_len: usize,
input_coverage_offsets_byte_len: usize,
lookahead_coverage_offsets_byte_len: usize,
seq_lookup_records_byte_len: usize,
}
impl ChainedSequenceContextFormat3Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
let start = self.backtrack_glyph_count_byte_range().end;
start..start + self.backtrack_coverage_offsets_byte_len
}
pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
let start = self.backtrack_coverage_offsets_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn input_coverage_offsets_byte_range(&self) -> Range<usize> {
let start = self.input_glyph_count_byte_range().end;
start..start + self.input_coverage_offsets_byte_len
}
pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
let start = self.input_coverage_offsets_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
let start = self.lookahead_glyph_count_byte_range().end;
start..start + self.lookahead_coverage_offsets_byte_len
}
pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
let start = self.lookahead_coverage_offsets_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let start = self.seq_lookup_count_byte_range().end;
start..start + self.seq_lookup_records_byte_len
}
}
impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let backtrack_glyph_count: u16 = cursor.read()?;
let backtrack_coverage_offsets_byte_len = (backtrack_glyph_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(backtrack_coverage_offsets_byte_len);
let input_glyph_count: u16 = cursor.read()?;
let input_coverage_offsets_byte_len = (input_glyph_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(input_coverage_offsets_byte_len);
let lookahead_glyph_count: u16 = cursor.read()?;
let lookahead_coverage_offsets_byte_len = (lookahead_glyph_count as usize)
.checked_mul(Offset16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(lookahead_coverage_offsets_byte_len);
let seq_lookup_count: u16 = cursor.read()?;
let seq_lookup_records_byte_len = (seq_lookup_count as usize)
.checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(seq_lookup_records_byte_len);
cursor.finish(ChainedSequenceContextFormat3Marker {
backtrack_coverage_offsets_byte_len,
input_coverage_offsets_byte_len,
lookahead_coverage_offsets_byte_len,
seq_lookup_records_byte_len,
})
}
}
pub type ChainedSequenceContextFormat3<'a> = TableRef<'a, ChainedSequenceContextFormat3Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceContextFormat3<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn backtrack_glyph_count(&self) -> u16 {
let range = self.shape.backtrack_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.backtrack_coverage_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
let data = self.data;
let offsets = self.backtrack_coverage_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
pub fn input_glyph_count(&self) -> u16 {
let range = self.shape.input_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.input_coverage_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn input_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
let data = self.data;
let offsets = self.input_coverage_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
pub fn lookahead_glyph_count(&self) -> u16 {
let range = self.shape.lookahead_glyph_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.shape.lookahead_coverage_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
let data = self.data;
let offsets = self.lookahead_coverage_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.shape.seq_lookup_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.shape.seq_lookup_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ChainedSequenceContextFormat3<'a> {
fn type_name(&self) -> &str {
"ChainedSequenceContextFormat3"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new(
"backtrack_glyph_count",
self.backtrack_glyph_count(),
)),
2usize => Some({
let data = self.data;
Field::new(
"backtrack_coverage_offsets",
FieldType::array_of_offsets(
better_type_name::<CoverageTable>(),
self.backtrack_coverage_offsets(),
move |off| {
let target = off.get().resolve::<CoverageTable>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
3usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
4usize => Some({
let data = self.data;
Field::new(
"input_coverage_offsets",
FieldType::array_of_offsets(
better_type_name::<CoverageTable>(),
self.input_coverage_offsets(),
move |off| {
let target = off.get().resolve::<CoverageTable>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
5usize => Some(Field::new(
"lookahead_glyph_count",
self.lookahead_glyph_count(),
)),
6usize => Some({
let data = self.data;
Field::new(
"lookahead_coverage_offsets",
FieldType::array_of_offsets(
better_type_name::<CoverageTable>(),
self.lookahead_coverage_offsets(),
move |off| {
let target = off.get().resolve::<CoverageTable>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
7usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
8usize => Some(Field::new(
"seq_lookup_records",
traversal::FieldType::array_of_records(
stringify!(SequenceLookupRecord),
self.seq_lookup_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ChainedSequenceContextFormat3<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone)]
pub enum ChainedSequenceContext<'a> {
Format1(ChainedSequenceContextFormat1<'a>),
Format2(ChainedSequenceContextFormat2<'a>),
Format3(ChainedSequenceContextFormat3<'a>),
}
impl<'a> ChainedSequenceContext<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Format1(item) => item.offset_data(),
Self::Format2(item) => item.offset_data(),
Self::Format3(item) => item.offset_data(),
}
}
pub fn format(&self) -> u16 {
match self {
Self::Format1(item) => item.format(),
Self::Format2(item) => item.format(),
Self::Format3(item) => item.format(),
}
}
}
impl<'a> FontRead<'a> for ChainedSequenceContext<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
ChainedSequenceContextFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
ChainedSequenceContextFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
ChainedSequenceContextFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> ChainedSequenceContext<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format1(table) => table,
Self::Format2(table) => table,
Self::Format3(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for ChainedSequenceContext<'_> {
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 ChainedSequenceContext<'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)
}
}
#[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 DeltaFormat {
#[default]
Local2BitDeltas = 0x0001,
Local4BitDeltas = 0x0002,
Local8BitDeltas = 0x0003,
VariationIndex = 0x8000,
#[doc(hidden)]
Unknown,
}
impl DeltaFormat {
pub fn new(raw: u16) -> Self {
match raw {
0x0001 => Self::Local2BitDeltas,
0x0002 => Self::Local4BitDeltas,
0x0003 => Self::Local8BitDeltas,
0x8000 => Self::VariationIndex,
_ => Self::Unknown,
}
}
}
impl font_types::Scalar for DeltaFormat {
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<DeltaFormat> for FieldType<'a> {
fn from(src: DeltaFormat) -> FieldType<'a> {
(src as u16).into()
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct DeviceMarker {
delta_value_byte_len: usize,
}
impl DeviceMarker {
pub fn start_size_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn end_size_byte_range(&self) -> Range<usize> {
let start = self.start_size_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn delta_format_byte_range(&self) -> Range<usize> {
let start = self.end_size_byte_range().end;
start..start + DeltaFormat::RAW_BYTE_LEN
}
pub fn delta_value_byte_range(&self) -> Range<usize> {
let start = self.delta_format_byte_range().end;
start..start + self.delta_value_byte_len
}
}
impl<'a> FontRead<'a> for Device<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let start_size: u16 = cursor.read()?;
let end_size: u16 = cursor.read()?;
let delta_format: DeltaFormat = cursor.read()?;
let delta_value_byte_len = (DeltaFormat::value_count(delta_format, start_size, end_size))
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(delta_value_byte_len);
cursor.finish(DeviceMarker {
delta_value_byte_len,
})
}
}
pub type Device<'a> = TableRef<'a, DeviceMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Device<'a> {
pub fn start_size(&self) -> u16 {
let range = self.shape.start_size_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn end_size(&self) -> u16 {
let range = self.shape.end_size_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn delta_format(&self) -> DeltaFormat {
let range = self.shape.delta_format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.delta_value_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Device<'a> {
fn type_name(&self) -> &str {
"Device"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("start_size", self.start_size())),
1usize => Some(Field::new("end_size", self.end_size())),
2usize => Some(Field::new("delta_format", self.delta_format())),
3usize => Some(Field::new("delta_value", self.delta_value())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Device<'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 VariationIndexMarker {}
impl VariationIndexMarker {
pub fn delta_set_outer_index_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn delta_set_inner_index_byte_range(&self) -> Range<usize> {
let start = self.delta_set_outer_index_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn delta_format_byte_range(&self) -> Range<usize> {
let start = self.delta_set_inner_index_byte_range().end;
start..start + DeltaFormat::RAW_BYTE_LEN
}
}
impl<'a> FontRead<'a> for VariationIndex<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<DeltaFormat>();
cursor.finish(VariationIndexMarker {})
}
}
pub type VariationIndex<'a> = TableRef<'a, VariationIndexMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> VariationIndex<'a> {
pub fn delta_set_outer_index(&self) -> u16 {
let range = self.shape.delta_set_outer_index_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn delta_set_inner_index(&self) -> u16 {
let range = self.shape.delta_set_inner_index_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn delta_format(&self) -> DeltaFormat {
let range = self.shape.delta_format_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for VariationIndex<'a> {
fn type_name(&self) -> &str {
"VariationIndex"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"delta_set_outer_index",
self.delta_set_outer_index(),
)),
1usize => Some(Field::new(
"delta_set_inner_index",
self.delta_set_inner_index(),
)),
2usize => Some(Field::new("delta_format", self.delta_format())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for VariationIndex<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone)]
pub enum DeviceOrVariationIndex<'a> {
Device(Device<'a>),
VariationIndex(VariationIndex<'a>),
}
impl<'a> DeviceOrVariationIndex<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Device(item) => item.offset_data(),
Self::VariationIndex(item) => item.offset_data(),
}
}
}
impl<'a> FontRead<'a> for DeviceOrVariationIndex<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: DeltaFormat = data.read_at(4usize)?;
#[allow(clippy::redundant_guards)]
match format {
format if format != DeltaFormat::VariationIndex => {
Ok(Self::Device(FontRead::read(data)?))
}
format if format == DeltaFormat::VariationIndex => {
Ok(Self::VariationIndex(FontRead::read(data)?))
}
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> DeviceOrVariationIndex<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Device(table) => table,
Self::VariationIndex(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for DeviceOrVariationIndex<'_> {
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 DeviceOrVariationIndex<'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)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct FeatureVariationsMarker {
feature_variation_records_byte_len: usize,
}
impl FeatureVariationsMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn feature_variation_record_count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn feature_variation_records_byte_range(&self) -> Range<usize> {
let start = self.feature_variation_record_count_byte_range().end;
start..start + self.feature_variation_records_byte_len
}
}
impl<'a> FontRead<'a> for FeatureVariations<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
let feature_variation_record_count: u32 = cursor.read()?;
let feature_variation_records_byte_len = (feature_variation_record_count as usize)
.checked_mul(FeatureVariationRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(feature_variation_records_byte_len);
cursor.finish(FeatureVariationsMarker {
feature_variation_records_byte_len,
})
}
}
pub type FeatureVariations<'a> = TableRef<'a, FeatureVariationsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> FeatureVariations<'a> {
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feature_variation_record_count(&self) -> u32 {
let range = self.shape.feature_variation_record_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
let range = self.shape.feature_variation_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for FeatureVariations<'a> {
fn type_name(&self) -> &str {
"FeatureVariations"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"feature_variation_record_count",
self.feature_variation_record_count(),
)),
2usize => Some(Field::new(
"feature_variation_records",
traversal::FieldType::array_of_records(
stringify!(FeatureVariationRecord),
self.feature_variation_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for FeatureVariations<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct FeatureVariationRecord {
pub condition_set_offset: BigEndian<Nullable<Offset32>>,
pub feature_table_substitution_offset: BigEndian<Nullable<Offset32>>,
}
impl FeatureVariationRecord {
pub fn condition_set_offset(&self) -> Nullable<Offset32> {
self.condition_set_offset.get()
}
pub fn condition_set<'a>(
&self,
data: FontData<'a>,
) -> Option<Result<ConditionSet<'a>, ReadError>> {
self.condition_set_offset().resolve(data)
}
pub fn feature_table_substitution_offset(&self) -> Nullable<Offset32> {
self.feature_table_substitution_offset.get()
}
pub fn feature_table_substitution<'a>(
&self,
data: FontData<'a>,
) -> Option<Result<FeatureTableSubstitution<'a>, ReadError>> {
self.feature_table_substitution_offset().resolve(data)
}
}
impl FixedSize for FeatureVariationRecord {
const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for FeatureVariationRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "FeatureVariationRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new(
"condition_set_offset",
FieldType::offset(self.condition_set_offset(), self.condition_set(_data)),
)),
1usize => Some(Field::new(
"feature_table_substitution_offset",
FieldType::offset(
self.feature_table_substitution_offset(),
self.feature_table_substitution(_data),
),
)),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ConditionSetMarker {
condition_offsets_byte_len: usize,
}
impl ConditionSetMarker {
pub fn condition_count_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn condition_offsets_byte_range(&self) -> Range<usize> {
let start = self.condition_count_byte_range().end;
start..start + self.condition_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ConditionSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let condition_count: u16 = cursor.read()?;
let condition_offsets_byte_len = (condition_count as usize)
.checked_mul(Offset32::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(condition_offsets_byte_len);
cursor.finish(ConditionSetMarker {
condition_offsets_byte_len,
})
}
}
pub type ConditionSet<'a> = TableRef<'a, ConditionSetMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionSet<'a> {
pub fn condition_count(&self) -> u16 {
let range = self.shape.condition_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
let range = self.shape.condition_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
let data = self.data;
let offsets = self.condition_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ConditionSet<'a> {
fn type_name(&self) -> &str {
"ConditionSet"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("condition_count", self.condition_count())),
1usize => Some({
let data = self.data;
Field::new(
"condition_offsets",
FieldType::array_of_offsets(
better_type_name::<Condition>(),
self.condition_offsets(),
move |off| {
let target = off.get().resolve::<Condition>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ConditionSet<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone)]
pub enum Condition<'a> {
Format1AxisRange(ConditionFormat1<'a>),
Format2VariableValue(ConditionFormat2<'a>),
Format3And(ConditionFormat3<'a>),
Format4Or(ConditionFormat4<'a>),
Format5Negate(ConditionFormat5<'a>),
}
impl<'a> Condition<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Format1AxisRange(item) => item.offset_data(),
Self::Format2VariableValue(item) => item.offset_data(),
Self::Format3And(item) => item.offset_data(),
Self::Format4Or(item) => item.offset_data(),
Self::Format5Negate(item) => item.offset_data(),
}
}
pub fn format(&self) -> u16 {
match self {
Self::Format1AxisRange(item) => item.format(),
Self::Format2VariableValue(item) => item.format(),
Self::Format3And(item) => item.format(),
Self::Format4Or(item) => item.format(),
Self::Format5Negate(item) => item.format(),
}
}
}
impl<'a> FontRead<'a> for Condition<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
ConditionFormat1Marker::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
ConditionFormat2Marker::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
ConditionFormat3Marker::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
ConditionFormat4Marker::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
ConditionFormat5Marker::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> Condition<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format1AxisRange(table) => table,
Self::Format2VariableValue(table) => table,
Self::Format3And(table) => table,
Self::Format4Or(table) => table,
Self::Format5Negate(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for Condition<'_> {
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 Condition<'a> {
fn type_name(&self) -> &str {
self.dyn_inner().type_name()
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
self.dyn_inner().get_field(idx)
}
}
impl Format<u16> for ConditionFormat1Marker {
const FORMAT: u16 = 1;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ConditionFormat1Marker {}
impl ConditionFormat1Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn axis_index_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn filter_range_min_value_byte_range(&self) -> Range<usize> {
let start = self.axis_index_byte_range().end;
start..start + F2Dot14::RAW_BYTE_LEN
}
pub fn filter_range_max_value_byte_range(&self) -> Range<usize> {
let start = self.filter_range_min_value_byte_range().end;
start..start + F2Dot14::RAW_BYTE_LEN
}
}
impl<'a> FontRead<'a> for ConditionFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<F2Dot14>();
cursor.advance::<F2Dot14>();
cursor.finish(ConditionFormat1Marker {})
}
}
pub type ConditionFormat1<'a> = TableRef<'a, ConditionFormat1Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat1<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn axis_index(&self) -> u16 {
let range = self.shape.axis_index_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn filter_range_min_value(&self) -> F2Dot14 {
let range = self.shape.filter_range_min_value_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn filter_range_max_value(&self) -> F2Dot14 {
let range = self.shape.filter_range_max_value_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ConditionFormat1<'a> {
fn type_name(&self) -> &str {
"ConditionFormat1"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("axis_index", self.axis_index())),
2usize => Some(Field::new(
"filter_range_min_value",
self.filter_range_min_value(),
)),
3usize => Some(Field::new(
"filter_range_max_value",
self.filter_range_max_value(),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ConditionFormat1<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for ConditionFormat2Marker {
const FORMAT: u16 = 2;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ConditionFormat2Marker {}
impl ConditionFormat2Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn default_value_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + i16::RAW_BYTE_LEN
}
pub fn var_index_byte_range(&self) -> Range<usize> {
let start = self.default_value_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
}
impl<'a> FontRead<'a> for ConditionFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<i16>();
cursor.advance::<u32>();
cursor.finish(ConditionFormat2Marker {})
}
}
pub type ConditionFormat2<'a> = TableRef<'a, ConditionFormat2Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat2<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn default_value(&self) -> i16 {
let range = self.shape.default_value_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn var_index(&self) -> u32 {
let range = self.shape.var_index_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ConditionFormat2<'a> {
fn type_name(&self) -> &str {
"ConditionFormat2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("default_value", self.default_value())),
2usize => Some(Field::new("var_index", self.var_index())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ConditionFormat2<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for ConditionFormat3Marker {
const FORMAT: u16 = 3;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ConditionFormat3Marker {
condition_offsets_byte_len: usize,
}
impl ConditionFormat3Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn condition_count_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn condition_offsets_byte_range(&self) -> Range<usize> {
let start = self.condition_count_byte_range().end;
start..start + self.condition_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ConditionFormat3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let condition_count: u8 = cursor.read()?;
let condition_offsets_byte_len = (condition_count as usize)
.checked_mul(Offset24::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(condition_offsets_byte_len);
cursor.finish(ConditionFormat3Marker {
condition_offsets_byte_len,
})
}
}
pub type ConditionFormat3<'a> = TableRef<'a, ConditionFormat3Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat3<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn condition_count(&self) -> u8 {
let range = self.shape.condition_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
let range = self.shape.condition_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
let data = self.data;
let offsets = self.condition_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ConditionFormat3<'a> {
fn type_name(&self) -> &str {
"ConditionFormat3"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("condition_count", self.condition_count())),
2usize => Some({
let data = self.data;
Field::new(
"condition_offsets",
FieldType::array_of_offsets(
better_type_name::<Condition>(),
self.condition_offsets(),
move |off| {
let target = off.get().resolve::<Condition>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ConditionFormat3<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for ConditionFormat4Marker {
const FORMAT: u16 = 4;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ConditionFormat4Marker {
condition_offsets_byte_len: usize,
}
impl ConditionFormat4Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn condition_count_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u8::RAW_BYTE_LEN
}
pub fn condition_offsets_byte_range(&self) -> Range<usize> {
let start = self.condition_count_byte_range().end;
start..start + self.condition_offsets_byte_len
}
}
impl<'a> FontRead<'a> for ConditionFormat4<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let condition_count: u8 = cursor.read()?;
let condition_offsets_byte_len = (condition_count as usize)
.checked_mul(Offset24::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(condition_offsets_byte_len);
cursor.finish(ConditionFormat4Marker {
condition_offsets_byte_len,
})
}
}
pub type ConditionFormat4<'a> = TableRef<'a, ConditionFormat4Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat4<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn condition_count(&self) -> u8 {
let range = self.shape.condition_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
let range = self.shape.condition_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
let data = self.data;
let offsets = self.condition_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ConditionFormat4<'a> {
fn type_name(&self) -> &str {
"ConditionFormat4"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("condition_count", self.condition_count())),
2usize => Some({
let data = self.data;
Field::new(
"condition_offsets",
FieldType::array_of_offsets(
better_type_name::<Condition>(),
self.condition_offsets(),
move |off| {
let target = off.get().resolve::<Condition>(data);
FieldType::offset(off.get(), target)
},
),
)
}),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ConditionFormat4<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for ConditionFormat5Marker {
const FORMAT: u16 = 5;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct ConditionFormat5Marker {}
impl ConditionFormat5Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn condition_offset_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + Offset24::RAW_BYTE_LEN
}
}
impl<'a> FontRead<'a> for ConditionFormat5<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<Offset24>();
cursor.finish(ConditionFormat5Marker {})
}
}
pub type ConditionFormat5<'a> = TableRef<'a, ConditionFormat5Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat5<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn condition_offset(&self) -> Offset24 {
let range = self.shape.condition_offset_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
let data = self.data;
self.condition_offset().resolve(data)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ConditionFormat5<'a> {
fn type_name(&self) -> &str {
"ConditionFormat5"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new(
"condition_offset",
FieldType::offset(self.condition_offset(), self.condition()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ConditionFormat5<'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 FeatureTableSubstitutionMarker {
substitutions_byte_len: usize,
}
impl FeatureTableSubstitutionMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + MajorMinor::RAW_BYTE_LEN
}
pub fn substitution_count_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn substitutions_byte_range(&self) -> Range<usize> {
let start = self.substitution_count_byte_range().end;
start..start + self.substitutions_byte_len
}
}
impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<MajorMinor>();
let substitution_count: u16 = cursor.read()?;
let substitutions_byte_len = (substitution_count as usize)
.checked_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(substitutions_byte_len);
cursor.finish(FeatureTableSubstitutionMarker {
substitutions_byte_len,
})
}
}
pub type FeatureTableSubstitution<'a> = TableRef<'a, FeatureTableSubstitutionMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> FeatureTableSubstitution<'a> {
pub fn version(&self) -> MajorMinor {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn substitution_count(&self) -> u16 {
let range = self.shape.substitution_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
let range = self.shape.substitutions_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for FeatureTableSubstitution<'a> {
fn type_name(&self) -> &str {
"FeatureTableSubstitution"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("substitution_count", self.substitution_count())),
2usize => Some(Field::new(
"substitutions",
traversal::FieldType::array_of_records(
stringify!(FeatureTableSubstitutionRecord),
self.substitutions(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for FeatureTableSubstitution<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct FeatureTableSubstitutionRecord {
pub feature_index: BigEndian<u16>,
pub alternate_feature_offset: BigEndian<Offset32>,
}
impl FeatureTableSubstitutionRecord {
pub fn feature_index(&self) -> u16 {
self.feature_index.get()
}
pub fn alternate_feature_offset(&self) -> Offset32 {
self.alternate_feature_offset.get()
}
}
impl FixedSize for FeatureTableSubstitutionRecord {
const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for FeatureTableSubstitutionRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "FeatureTableSubstitutionRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("feature_index", self.feature_index())),
1usize => Some(Field::new(
"alternate_feature_offset",
FieldType::offset(
self.alternate_feature_offset(),
self.alternate_feature(_data),
),
)),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct SizeParamsMarker {}
impl SizeParamsMarker {
pub fn design_size_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn identifier_byte_range(&self) -> Range<usize> {
let start = self.design_size_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn name_entry_byte_range(&self) -> Range<usize> {
let start = self.identifier_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn range_start_byte_range(&self) -> Range<usize> {
let start = self.name_entry_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn range_end_byte_range(&self) -> Range<usize> {
let start = self.range_start_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
impl<'a> FontRead<'a> for SizeParams<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.finish(SizeParamsMarker {})
}
}
pub type SizeParams<'a> = TableRef<'a, SizeParamsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> SizeParams<'a> {
pub fn design_size(&self) -> u16 {
let range = self.shape.design_size_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn identifier(&self) -> u16 {
let range = self.shape.identifier_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn name_entry(&self) -> u16 {
let range = self.shape.name_entry_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn range_start(&self) -> u16 {
let range = self.shape.range_start_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn range_end(&self) -> u16 {
let range = self.shape.range_end_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for SizeParams<'a> {
fn type_name(&self) -> &str {
"SizeParams"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("design_size", self.design_size())),
1usize => Some(Field::new("identifier", self.identifier())),
2usize => Some(Field::new("name_entry", self.name_entry())),
3usize => Some(Field::new("range_start", self.range_start())),
4usize => Some(Field::new("range_end", self.range_end())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for SizeParams<'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 StylisticSetParamsMarker {}
impl StylisticSetParamsMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn ui_name_id_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + NameId::RAW_BYTE_LEN
}
}
impl<'a> FontRead<'a> for StylisticSetParams<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<NameId>();
cursor.finish(StylisticSetParamsMarker {})
}
}
pub type StylisticSetParams<'a> = TableRef<'a, StylisticSetParamsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> StylisticSetParams<'a> {
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn ui_name_id(&self) -> NameId {
let range = self.shape.ui_name_id_byte_range();
self.data.read_at(range.start).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for StylisticSetParams<'a> {
fn type_name(&self) -> &str {
"StylisticSetParams"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("ui_name_id", self.ui_name_id())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for StylisticSetParams<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for CharacterVariantParamsMarker {
const FORMAT: u16 = 0;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CharacterVariantParamsMarker {
character_byte_len: usize,
}
impl CharacterVariantParamsMarker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn feat_ui_label_name_id_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + NameId::RAW_BYTE_LEN
}
pub fn feat_ui_tooltip_text_name_id_byte_range(&self) -> Range<usize> {
let start = self.feat_ui_label_name_id_byte_range().end;
start..start + NameId::RAW_BYTE_LEN
}
pub fn sample_text_name_id_byte_range(&self) -> Range<usize> {
let start = self.feat_ui_tooltip_text_name_id_byte_range().end;
start..start + NameId::RAW_BYTE_LEN
}
pub fn num_named_parameters_byte_range(&self) -> Range<usize> {
let start = self.sample_text_name_id_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn first_param_ui_label_name_id_byte_range(&self) -> Range<usize> {
let start = self.num_named_parameters_byte_range().end;
start..start + NameId::RAW_BYTE_LEN
}
pub fn char_count_byte_range(&self) -> Range<usize> {
let start = self.first_param_ui_label_name_id_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn character_byte_range(&self) -> Range<usize> {
let start = self.char_count_byte_range().end;
start..start + self.character_byte_len
}
}
impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<NameId>();
cursor.advance::<NameId>();
cursor.advance::<NameId>();
cursor.advance::<u16>();
cursor.advance::<NameId>();
let char_count: u16 = cursor.read()?;
let character_byte_len = (char_count as usize)
.checked_mul(Uint24::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(character_byte_len);
cursor.finish(CharacterVariantParamsMarker { character_byte_len })
}
}
pub type CharacterVariantParams<'a> = TableRef<'a, CharacterVariantParamsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> CharacterVariantParams<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feat_ui_label_name_id(&self) -> NameId {
let range = self.shape.feat_ui_label_name_id_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
let range = self.shape.feat_ui_tooltip_text_name_id_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn sample_text_name_id(&self) -> NameId {
let range = self.shape.sample_text_name_id_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn num_named_parameters(&self) -> u16 {
let range = self.shape.num_named_parameters_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn first_param_ui_label_name_id(&self) -> NameId {
let range = self.shape.first_param_ui_label_name_id_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn char_count(&self) -> u16 {
let range = self.shape.char_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn character(&self) -> &'a [BigEndian<Uint24>] {
let range = self.shape.character_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for CharacterVariantParams<'a> {
fn type_name(&self) -> &str {
"CharacterVariantParams"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new(
"feat_ui_label_name_id",
self.feat_ui_label_name_id(),
)),
2usize => Some(Field::new(
"feat_ui_tooltip_text_name_id",
self.feat_ui_tooltip_text_name_id(),
)),
3usize => Some(Field::new(
"sample_text_name_id",
self.sample_text_name_id(),
)),
4usize => Some(Field::new(
"num_named_parameters",
self.num_named_parameters(),
)),
5usize => Some(Field::new(
"first_param_ui_label_name_id",
self.first_param_ui_label_name_id(),
)),
6usize => Some(Field::new("char_count", self.char_count())),
7usize => Some(Field::new("character", self.character())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for CharacterVariantParams<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}