#[allow(unused_imports)]
use crate::codegen_prelude::*;
impl<'a> MinByteRange<'a> for ScriptList<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.script_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ScriptList<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ScriptList<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ScriptList<'a> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn script_count(&self) -> u16 {
let range = self.script_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn script_records(&self) -> &'a [ScriptRecord] {
let range = self.script_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 script_count = self.script_count();
let start = self.script_count_byte_range().end;
start..start + (script_count as usize).saturating_mul(ScriptRecord::RAW_BYTE_LEN)
}
}
#[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,
}
}
}
impl<'a> MinByteRange<'a> for Script<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.lang_sys_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for Script<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct Script<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> Script<'a> {
pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn default_lang_sys_offset(&self) -> Nullable<Offset16> {
let range = self.default_lang_sys_offset_byte_range();
self.data.read_at(range.start).ok().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.lang_sys_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn lang_sys_records(&self) -> &'a [LangSysRecord] {
let range = self.lang_sys_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 lang_sys_count = self.lang_sys_count();
let start = self.lang_sys_count_byte_range().end;
start..start + (lang_sys_count as usize).saturating_mul(LangSysRecord::RAW_BYTE_LEN)
}
}
#[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,
}
}
}
impl<'a> MinByteRange<'a> for LangSys<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.feature_indices_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for LangSys<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct LangSys<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> LangSys<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn required_feature_index(&self) -> u16 {
let range = self.required_feature_index_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn feature_index_count(&self) -> u16 {
let range = self.feature_index_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn feature_indices(&self) -> &'a [BigEndian<u16>] {
let range = self.feature_indices_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 feature_index_count = self.feature_index_count();
let start = self.feature_index_count_byte_range().end;
start..start + (feature_index_count as usize).saturating_mul(u16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for FeatureList<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.feature_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for FeatureList<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct FeatureList<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> FeatureList<'a> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn feature_count(&self) -> u16 {
let range = self.feature_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn feature_records(&self) -> &'a [FeatureRecord] {
let range = self.feature_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 feature_count = self.feature_count();
let start = self.feature_count_byte_range().end;
start..start + (feature_count as usize).saturating_mul(FeatureRecord::RAW_BYTE_LEN)
}
}
#[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,
}
}
}
impl<'a> MinByteRange<'a> for Feature<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.lookup_list_indices_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl 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;
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data, feature_tag })
}
}
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)
}
}
#[derive(Clone)]
pub struct Feature<'a> {
data: FontData<'a>,
feature_tag: Tag,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> Feature<'a> {
pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn feature_params_offset(&self) -> Nullable<Offset16> {
let range = self.feature_params_offset_byte_range();
self.data.read_at(range.start).ok().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.lookup_index_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn lookup_list_indices(&self) -> &'a [BigEndian<u16>] {
let range = self.lookup_list_indices_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub(crate) fn feature_tag(&self) -> Tag {
self.feature_tag
}
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 lookup_index_count = self.lookup_index_count();
let start = self.lookup_index_count_byte_range().end;
start..start + (lookup_index_count as usize).saturating_mul(u16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a, T> MinByteRange<'a> for LookupList<'a, T> {
fn min_byte_range(&self) -> Range<usize> {
0..self.lookup_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a, T> FontRead<'a> for LookupList<'a, T> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self {
data,
offset_type: std::marker::PhantomData,
})
}
}
impl<'a> LookupList<'a, ()> {
#[allow(dead_code)]
pub(crate) fn into_concrete<T>(self) -> LookupList<'a, T> {
LookupList {
data: self.data,
offset_type: std::marker::PhantomData,
}
}
}
impl<'a, T> LookupList<'a, T> {
#[allow(dead_code)]
pub(crate) fn of_unit_type(&self) -> LookupList<'a, ()> {
LookupList {
data: self.data,
offset_type: std::marker::PhantomData,
}
}
}
#[derive(Clone)]
pub struct LookupList<'a, T = ()> {
data: FontData<'a>,
offset_type: std::marker::PhantomData<*const T>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a, T> LookupList<'a, T> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn lookup_count(&self) -> u16 {
let range = self.lookup_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn lookup_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.lookup_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 lookup_count = self.lookup_count();
let start = self.lookup_count_byte_range().end;
start..start + (lookup_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a, T> MinByteRange<'a> for Lookup<'a, T> {
fn min_byte_range(&self) -> Range<usize> {
0..self.subtable_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a, T> FontRead<'a> for Lookup<'a, T> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self {
data,
offset_type: std::marker::PhantomData,
})
}
}
impl<'a> Lookup<'a, ()> {
#[allow(dead_code)]
pub(crate) fn into_concrete<T>(self) -> Lookup<'a, T> {
Lookup {
data: self.data,
offset_type: std::marker::PhantomData,
}
}
}
impl<'a, T> Lookup<'a, T> {
#[allow(dead_code)]
pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
Lookup {
data: self.data,
offset_type: std::marker::PhantomData,
}
}
}
#[derive(Clone)]
pub struct Lookup<'a, T = ()> {
data: FontData<'a>,
offset_type: std::marker::PhantomData<*const T>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a, T> Lookup<'a, T> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + LookupFlag::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn lookup_type(&self) -> u16 {
let range = self.lookup_type_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn lookup_flag(&self) -> LookupFlag {
let range = self.lookup_flag_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn sub_table_count(&self) -> u16 {
let range = self.sub_table_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn subtable_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.subtable_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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.mark_filtering_set_byte_range();
(!range.is_empty())
.then(|| self.data.read_at(range.start).ok())
.flatten()
}
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 sub_table_count = self.sub_table_count();
let start = self.sub_table_count_byte_range().end;
start..start + (sub_table_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
pub fn mark_filtering_set_byte_range(&self) -> Range<usize> {
let start = self.subtable_offsets_byte_range().end;
start
..(self
.lookup_flag()
.contains(LookupFlag::USE_MARK_FILTERING_SET))
.then(|| start + u16::RAW_BYTE_LEN)
.unwrap_or(start)
}
}
#[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>> {
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 self
.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 CoverageFormat1<'_> {
const FORMAT: u16 = 1;
}
impl<'a> MinByteRange<'a> for CoverageFormat1<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.glyph_array_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for CoverageFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct CoverageFormat1<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> CoverageFormat1<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn coverage_format(&self) -> u16 {
let range = self.coverage_format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn glyph_count(&self) -> u16 {
let range = self.glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.glyph_array_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 glyph_count = self.glyph_count();
let start = self.glyph_count_byte_range().end;
start..start + (glyph_count as usize).saturating_mul(GlyphId16::RAW_BYTE_LEN)
}
}
#[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 CoverageFormat2<'_> {
const FORMAT: u16 = 2;
}
impl<'a> MinByteRange<'a> for CoverageFormat2<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.range_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for CoverageFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct CoverageFormat2<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> CoverageFormat2<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn coverage_format(&self) -> u16 {
let range = self.coverage_format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn range_count(&self) -> u16 {
let range = self.range_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn range_records(&self) -> &'a [RangeRecord] {
let range = self.range_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 range_count = self.range_count();
let start = self.range_count_byte_range().end;
start..start + (range_count as usize).saturating_mul(RangeRecord::RAW_BYTE_LEN)
}
}
#[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 {
CoverageFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
CoverageFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl<'a> MinByteRange<'a> for CoverageTable<'a> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Format1(item) => item.min_byte_range(),
Self::Format2(item) => item.min_byte_range(),
}
}
fn min_table_bytes(&self) -> &'a [u8] {
match self {
Self::Format1(item) => item.min_table_bytes(),
Self::Format2(item) => item.min_table_bytes(),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> 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 ClassDefFormat1<'_> {
const FORMAT: u16 = 1;
}
impl<'a> MinByteRange<'a> for ClassDefFormat1<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.class_value_array_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ClassDefFormat1<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassDefFormat1<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn class_format(&self) -> u16 {
let range = self.class_format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn start_glyph_id(&self) -> GlyphId16 {
let range = self.start_glyph_id_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn glyph_count(&self) -> u16 {
let range = self.glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
let range = self.class_value_array_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 glyph_count = self.glyph_count();
let start = self.glyph_count_byte_range().end;
start..start + (glyph_count as usize).saturating_mul(u16::RAW_BYTE_LEN)
}
}
#[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 ClassDefFormat2<'_> {
const FORMAT: u16 = 2;
}
impl<'a> MinByteRange<'a> for ClassDefFormat2<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.class_range_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ClassDefFormat2<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassDefFormat2<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn class_format(&self) -> u16 {
let range = self.class_format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn class_range_count(&self) -> u16 {
let range = self.class_range_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
let range = self.class_range_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 class_range_count = self.class_range_count();
let start = self.class_range_count_byte_range().end;
start..start + (class_range_count as usize).saturating_mul(ClassRangeRecord::RAW_BYTE_LEN)
}
}
#[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 {
ClassDefFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
ClassDefFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl<'a> MinByteRange<'a> for ClassDef<'a> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Format1(item) => item.min_byte_range(),
Self::Format2(item) => item.min_byte_range(),
}
}
fn min_table_bytes(&self) -> &'a [u8] {
match self {
Self::Format1(item) => item.min_table_bytes(),
Self::Format2(item) => item.min_table_bytes(),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> 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 SequenceContextFormat1<'_> {
const FORMAT: u16 = 1;
}
impl<'a> MinByteRange<'a> for SequenceContextFormat1<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_rule_set_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct SequenceContextFormat1<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceContextFormat1<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.coverage_offset_byte_range();
self.data.read_at(range.start).ok().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.seq_rule_set_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.seq_rule_set_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 seq_rule_set_count = self.seq_rule_set_count();
let start = self.seq_rule_set_count_byte_range().end;
start..start + (seq_rule_set_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for SequenceRuleSet<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_rule_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct SequenceRuleSet<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceRuleSet<'a> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn seq_rule_count(&self) -> u16 {
let range = self.seq_rule_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.seq_rule_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
let data = self.data;
let offsets = self.seq_rule_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
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 seq_rule_count = self.seq_rule_count();
let start = self.seq_rule_count_byte_range().end;
start..start + (seq_rule_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for SequenceRule<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_lookup_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for SequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct SequenceRule<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceRule<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn glyph_count(&self) -> u16 {
let range = self.glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.seq_lookup_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.input_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.seq_lookup_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 glyph_count = self.glyph_count();
let start = self.seq_lookup_count_byte_range().end;
start
..start
+ (transforms::subtract(glyph_count, 1_usize))
.saturating_mul(GlyphId16::RAW_BYTE_LEN)
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let seq_lookup_count = self.seq_lookup_count();
let start = self.input_sequence_byte_range().end;
start
..start + (seq_lookup_count as usize).saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN)
}
}
#[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 SequenceContextFormat2<'_> {
const FORMAT: u16 = 2;
}
impl<'a> MinByteRange<'a> for SequenceContextFormat2<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.class_seq_rule_set_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct SequenceContextFormat2<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceContextFormat2<'a> {
pub const MIN_SIZE: usize =
(u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.coverage_offset_byte_range();
self.data.read_at(range.start).ok().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.class_def_offset_byte_range();
self.data.read_at(range.start).ok().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.class_seq_rule_set_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.class_seq_rule_set_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 class_seq_rule_set_count = self.class_seq_rule_set_count();
let start = self.class_seq_rule_set_count_byte_range().end;
start..start + (class_seq_rule_set_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for ClassSequenceRuleSet<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.class_seq_rule_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ClassSequenceRuleSet<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassSequenceRuleSet<'a> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn class_seq_rule_count(&self) -> u16 {
let range = self.class_seq_rule_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.class_seq_rule_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 class_seq_rule_count = self.class_seq_rule_count();
let start = self.class_seq_rule_count_byte_range().end;
start..start + (class_seq_rule_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for ClassSequenceRule<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_lookup_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ClassSequenceRule<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ClassSequenceRule<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn glyph_count(&self) -> u16 {
let range = self.glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.seq_lookup_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.input_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.seq_lookup_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 glyph_count = self.glyph_count();
let start = self.seq_lookup_count_byte_range().end;
start
..start + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN)
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let seq_lookup_count = self.seq_lookup_count();
let start = self.input_sequence_byte_range().end;
start
..start + (seq_lookup_count as usize).saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN)
}
}
#[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 SequenceContextFormat3<'_> {
const FORMAT: u16 = 3;
}
impl<'a> MinByteRange<'a> for SequenceContextFormat3<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_lookup_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct SequenceContextFormat3<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> SequenceContextFormat3<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn glyph_count(&self) -> u16 {
let range = self.glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.seq_lookup_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.coverage_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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.seq_lookup_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 glyph_count = self.glyph_count();
let start = self.seq_lookup_count_byte_range().end;
start..start + (glyph_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
let seq_lookup_count = self.seq_lookup_count();
let start = self.coverage_offsets_byte_range().end;
start
..start + (seq_lookup_count as usize).saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN)
}
}
#[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 {
SequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
SequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
SequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl<'a> MinByteRange<'a> for SequenceContext<'a> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Format1(item) => item.min_byte_range(),
Self::Format2(item) => item.min_byte_range(),
Self::Format3(item) => item.min_byte_range(),
}
}
fn min_table_bytes(&self) -> &'a [u8] {
match self {
Self::Format1(item) => item.min_table_bytes(),
Self::Format2(item) => item.min_table_bytes(),
Self::Format3(item) => item.min_table_bytes(),
}
}
}
#[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 ChainedSequenceContextFormat1<'_> {
const FORMAT: u16 = 1;
}
impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat1<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.chained_seq_rule_set_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ChainedSequenceContextFormat1<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceContextFormat1<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.coverage_offset_byte_range();
self.data.read_at(range.start).ok().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.chained_seq_rule_set_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.chained_seq_rule_set_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 chained_seq_rule_set_count = self.chained_seq_rule_set_count();
let start = self.chained_seq_rule_set_count_byte_range().end;
start..start + (chained_seq_rule_set_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for ChainedSequenceRuleSet<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.chained_seq_rule_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ChainedSequenceRuleSet<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceRuleSet<'a> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn chained_seq_rule_count(&self) -> u16 {
let range = self.chained_seq_rule_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.chained_seq_rule_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 chained_seq_rule_count = self.chained_seq_rule_count();
let start = self.chained_seq_rule_count_byte_range().end;
start..start + (chained_seq_rule_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for ChainedSequenceRule<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_lookup_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ChainedSequenceRule<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceRule<'a> {
pub const MIN_SIZE: usize =
(u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn backtrack_glyph_count(&self) -> u16 {
let range = self.backtrack_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.backtrack_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn input_glyph_count(&self) -> u16 {
let range = self.input_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.input_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn lookahead_glyph_count(&self) -> u16 {
let range = self.lookahead_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
let range = self.lookahead_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.seq_lookup_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.seq_lookup_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 backtrack_glyph_count = self.backtrack_glyph_count();
let start = self.backtrack_glyph_count_byte_range().end;
start..start + (backtrack_glyph_count as usize).saturating_mul(GlyphId16::RAW_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 input_glyph_count = self.input_glyph_count();
let start = self.input_glyph_count_byte_range().end;
start
..start
+ (transforms::subtract(input_glyph_count, 1_usize))
.saturating_mul(GlyphId16::RAW_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 lookahead_glyph_count = self.lookahead_glyph_count();
let start = self.lookahead_glyph_count_byte_range().end;
start..start + (lookahead_glyph_count as usize).saturating_mul(GlyphId16::RAW_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 seq_lookup_count = self.seq_lookup_count();
let start = self.seq_lookup_count_byte_range().end;
start
..start + (seq_lookup_count as usize).saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN)
}
}
#[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 ChainedSequenceContextFormat2<'_> {
const FORMAT: u16 = 2;
}
impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat2<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.chained_class_seq_rule_set_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ChainedSequenceContextFormat2<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceContextFormat2<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
+ Offset16::RAW_BYTE_LEN
+ Offset16::RAW_BYTE_LEN
+ Offset16::RAW_BYTE_LEN
+ Offset16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn coverage_offset(&self) -> Offset16 {
let range = self.coverage_offset_byte_range();
self.data.read_at(range.start).ok().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.backtrack_class_def_offset_byte_range();
self.data.read_at(range.start).ok().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.input_class_def_offset_byte_range();
self.data.read_at(range.start).ok().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.lookahead_class_def_offset_byte_range();
self.data.read_at(range.start).ok().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.chained_class_seq_rule_set_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
let range = self.chained_class_seq_rule_set_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 chained_class_seq_rule_set_count = self.chained_class_seq_rule_set_count();
let start = self.chained_class_seq_rule_set_count_byte_range().end;
start
..start
+ (chained_class_seq_rule_set_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for ChainedClassSequenceRuleSet<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.chained_class_seq_rule_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ChainedClassSequenceRuleSet<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedClassSequenceRuleSet<'a> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn chained_class_seq_rule_count(&self) -> u16 {
let range = self.chained_class_seq_rule_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.chained_class_seq_rule_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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, ())
}
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 chained_class_seq_rule_count = self.chained_class_seq_rule_count();
let start = self.chained_class_seq_rule_count_byte_range().end;
start
..start + (chained_class_seq_rule_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for ChainedClassSequenceRule<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_lookup_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ChainedClassSequenceRule<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedClassSequenceRule<'a> {
pub const MIN_SIZE: usize =
(u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn backtrack_glyph_count(&self) -> u16 {
let range = self.backtrack_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.backtrack_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn input_glyph_count(&self) -> u16 {
let range = self.input_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.input_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn lookahead_glyph_count(&self) -> u16 {
let range = self.lookahead_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
let range = self.lookahead_sequence_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn seq_lookup_count(&self) -> u16 {
let range = self.seq_lookup_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.seq_lookup_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 backtrack_glyph_count = self.backtrack_glyph_count();
let start = self.backtrack_glyph_count_byte_range().end;
start..start + (backtrack_glyph_count as usize).saturating_mul(u16::RAW_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 input_glyph_count = self.input_glyph_count();
let start = self.input_glyph_count_byte_range().end;
start
..start
+ (transforms::subtract(input_glyph_count, 1_usize))
.saturating_mul(u16::RAW_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 lookahead_glyph_count = self.lookahead_glyph_count();
let start = self.lookahead_glyph_count_byte_range().end;
start..start + (lookahead_glyph_count as usize).saturating_mul(u16::RAW_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 seq_lookup_count = self.seq_lookup_count();
let start = self.seq_lookup_count_byte_range().end;
start
..start + (seq_lookup_count as usize).saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN)
}
}
#[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 ChainedSequenceContextFormat3<'_> {
const FORMAT: u16 = 3;
}
impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat3<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.seq_lookup_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ChainedSequenceContextFormat3<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ChainedSequenceContextFormat3<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn backtrack_glyph_count(&self) -> u16 {
let range = self.backtrack_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.backtrack_coverage_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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.input_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.input_coverage_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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.lookahead_glyph_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.lookahead_coverage_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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.seq_lookup_count_byte_range();
self.data.read_at(range.start).ok().unwrap_or_default()
}
pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
let range = self.seq_lookup_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 backtrack_glyph_count = self.backtrack_glyph_count();
let start = self.backtrack_glyph_count_byte_range().end;
start..start + (backtrack_glyph_count as usize).saturating_mul(Offset16::RAW_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 input_glyph_count = self.input_glyph_count();
let start = self.input_glyph_count_byte_range().end;
start..start + (input_glyph_count as usize).saturating_mul(Offset16::RAW_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 lookahead_glyph_count = self.lookahead_glyph_count();
let start = self.lookahead_glyph_count_byte_range().end;
start..start + (lookahead_glyph_count as usize).saturating_mul(Offset16::RAW_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 seq_lookup_count = self.seq_lookup_count();
let start = self.seq_lookup_count_byte_range().end;
start
..start + (seq_lookup_count as usize).saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN)
}
}
#[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 {
ChainedSequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
ChainedSequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
ChainedSequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl<'a> MinByteRange<'a> for ChainedSequenceContext<'a> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Format1(item) => item.min_byte_range(),
Self::Format2(item) => item.min_byte_range(),
Self::Format3(item) => item.min_byte_range(),
}
}
fn min_table_bytes(&self) -> &'a [u8] {
match self {
Self::Format1(item) => item.min_table_bytes(),
Self::Format2(item) => item.min_table_bytes(),
Self::Format3(item) => item.min_table_bytes(),
}
}
}
#[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()
}
}
impl<'a> MinByteRange<'a> for Device<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.delta_value_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for Device<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct Device<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> Device<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn start_size(&self) -> u16 {
let range = self.start_size_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn end_size(&self) -> u16 {
let range = self.end_size_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn delta_format(&self) -> DeltaFormat {
let range = self.delta_format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
let range = self.delta_value_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 delta_format = self.delta_format();
let start_size = self.start_size();
let end_size = self.end_size();
let start = self.delta_format_byte_range().end;
start
..start
+ (DeltaFormat::value_count(delta_format, start_size, end_size))
.saturating_mul(u16::RAW_BYTE_LEN)
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for VariationIndex<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.delta_format_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for VariationIndex<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct VariationIndex<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> VariationIndex<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn delta_set_outer_index(&self) -> u16 {
let range = self.delta_set_outer_index_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn delta_set_inner_index(&self) -> u16 {
let range = self.delta_set_inner_index_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn delta_format(&self) -> DeltaFormat {
let range = self.delta_format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
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
}
}
#[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())),
}
}
}
impl<'a> MinByteRange<'a> for DeviceOrVariationIndex<'a> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Device(item) => item.min_byte_range(),
Self::VariationIndex(item) => item.min_byte_range(),
}
}
fn min_table_bytes(&self) -> &'a [u8] {
match self {
Self::Device(item) => item.min_table_bytes(),
Self::VariationIndex(item) => item.min_table_bytes(),
}
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for FeatureVariations<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.feature_variation_records_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for FeatureVariations<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct FeatureVariations<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> FeatureVariations<'a> {
pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn version(&self) -> MajorMinor {
let range = self.version_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn feature_variation_record_count(&self) -> u32 {
let range = self.feature_variation_record_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
let range = self.feature_variation_records_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 feature_variation_record_count = self.feature_variation_record_count();
let start = self.feature_variation_record_count_byte_range().end;
start
..start
+ (feature_variation_record_count as usize)
.saturating_mul(FeatureVariationRecord::RAW_BYTE_LEN)
}
}
#[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,
}
}
}
impl<'a> MinByteRange<'a> for ConditionSet<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.condition_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ConditionSet<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ConditionSet<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionSet<'a> {
pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
basic_table_impls!(impl_the_methods);
pub fn condition_count(&self) -> u16 {
let range = self.condition_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
let range = self.condition_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
let data = self.data;
let offsets = self.condition_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
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 condition_count = self.condition_count();
let start = self.condition_count_byte_range().end;
start..start + (condition_count as usize).saturating_mul(Offset32::RAW_BYTE_LEN)
}
}
#[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 {
ConditionFormat1::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
ConditionFormat2::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
ConditionFormat3::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
ConditionFormat4::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
ConditionFormat5::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl<'a> MinByteRange<'a> for Condition<'a> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Format1AxisRange(item) => item.min_byte_range(),
Self::Format2VariableValue(item) => item.min_byte_range(),
Self::Format3And(item) => item.min_byte_range(),
Self::Format4Or(item) => item.min_byte_range(),
Self::Format5Negate(item) => item.min_byte_range(),
}
}
fn min_table_bytes(&self) -> &'a [u8] {
match self {
Self::Format1AxisRange(item) => item.min_table_bytes(),
Self::Format2VariableValue(item) => item.min_table_bytes(),
Self::Format3And(item) => item.min_table_bytes(),
Self::Format4Or(item) => item.min_table_bytes(),
Self::Format5Negate(item) => item.min_table_bytes(),
}
}
}
#[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 ConditionFormat1<'_> {
const FORMAT: u16 = 1;
}
impl<'a> MinByteRange<'a> for ConditionFormat1<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.filter_range_max_value_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ConditionFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ConditionFormat1<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat1<'a> {
pub const MIN_SIZE: usize =
(u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn axis_index(&self) -> u16 {
let range = self.axis_index_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn filter_range_min_value(&self) -> F2Dot14 {
let range = self.filter_range_min_value_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn filter_range_max_value(&self) -> F2Dot14 {
let range = self.filter_range_max_value_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
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
}
}
#[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 ConditionFormat2<'_> {
const FORMAT: u16 = 2;
}
impl<'a> MinByteRange<'a> for ConditionFormat2<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.var_index_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ConditionFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ConditionFormat2<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat2<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn default_value(&self) -> i16 {
let range = self.default_value_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn var_index(&self) -> u32 {
let range = self.var_index_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
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
}
}
#[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 ConditionFormat3<'_> {
const FORMAT: u16 = 3;
}
impl<'a> MinByteRange<'a> for ConditionFormat3<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.condition_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ConditionFormat3<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ConditionFormat3<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat3<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn condition_count(&self) -> u8 {
let range = self.condition_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
let range = self.condition_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
let data = self.data;
let offsets = self.condition_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
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 condition_count = self.condition_count();
let start = self.condition_count_byte_range().end;
start..start + (condition_count as usize).saturating_mul(Offset24::RAW_BYTE_LEN)
}
}
#[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 ConditionFormat4<'_> {
const FORMAT: u16 = 4;
}
impl<'a> MinByteRange<'a> for ConditionFormat4<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.condition_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ConditionFormat4<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ConditionFormat4<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat4<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn condition_count(&self) -> u8 {
let range = self.condition_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
let range = self.condition_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
let data = self.data;
let offsets = self.condition_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
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 condition_count = self.condition_count();
let start = self.condition_count_byte_range().end;
start..start + (condition_count as usize).saturating_mul(Offset24::RAW_BYTE_LEN)
}
}
#[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 ConditionFormat5<'_> {
const FORMAT: u16 = 5;
}
impl<'a> MinByteRange<'a> for ConditionFormat5<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.condition_offset_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ConditionFormat5<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ConditionFormat5<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ConditionFormat5<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn condition_offset(&self) -> Offset24 {
let range = self.condition_offset_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
let data = self.data;
self.condition_offset().resolve(data)
}
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
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for FeatureTableSubstitution<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.substitutions_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct FeatureTableSubstitution<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> FeatureTableSubstitution<'a> {
pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn version(&self) -> MajorMinor {
let range = self.version_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn substitution_count(&self) -> u16 {
let range = self.substitution_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
let range = self.substitutions_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 substitution_count = self.substitution_count();
let start = self.substitution_count_byte_range().end;
start
..start
+ (substitution_count as usize)
.saturating_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN)
}
}
#[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,
}
}
}
impl<'a> MinByteRange<'a> for SizeParams<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.range_end_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for SizeParams<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct SizeParams<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> SizeParams<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn design_size(&self) -> u16 {
let range = self.design_size_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn identifier(&self) -> u16 {
let range = self.identifier_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn name_entry(&self) -> u16 {
let range = self.name_entry_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn range_start(&self) -> u16 {
let range = self.range_start_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn range_end(&self) -> u16 {
let range = self.range_end_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
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
}
}
#[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)
}
}
impl<'a> MinByteRange<'a> for StylisticSetParams<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.ui_name_id_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for StylisticSetParams<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct StylisticSetParams<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> StylisticSetParams<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn version(&self) -> u16 {
let range = self.version_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn ui_name_id(&self) -> NameId {
let range = self.ui_name_id_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
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
}
}
#[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 CharacterVariantParams<'_> {
const FORMAT: u16 = 0;
}
impl<'a> MinByteRange<'a> for CharacterVariantParams<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.character_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct CharacterVariantParams<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> CharacterVariantParams<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
+ NameId::RAW_BYTE_LEN
+ NameId::RAW_BYTE_LEN
+ NameId::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN
+ NameId::RAW_BYTE_LEN
+ u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn feat_ui_label_name_id(&self) -> NameId {
let range = self.feat_ui_label_name_id_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
let range = self.feat_ui_tooltip_text_name_id_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn sample_text_name_id(&self) -> NameId {
let range = self.sample_text_name_id_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn num_named_parameters(&self) -> u16 {
let range = self.num_named_parameters_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn first_param_ui_label_name_id(&self) -> NameId {
let range = self.first_param_ui_label_name_id_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn char_count(&self) -> u16 {
let range = self.char_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn character(&self) -> &'a [BigEndian<Uint24>] {
let range = self.character_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
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 char_count = self.char_count();
let start = self.char_count_byte_range().end;
start..start + (char_count as usize).saturating_mul(Uint24::RAW_BYTE_LEN)
}
}
#[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)
}
}