use types::{BigEndian, Fixed, FixedSize, NameId};
#[cfg(feature = "experimental_traverse")]
use crate::traversal::{Field, RecordResolver, SomeRecord};
use crate::{ComputeSize, FontData, FontReadWithArgs, ReadArgs, ReadError};
#[derive(Clone, Debug)]
pub struct InstanceRecord<'a> {
pub subfamily_name_id: NameId,
pub flags: u16,
pub coordinates: &'a [BigEndian<Fixed>],
pub post_script_name_id: Option<NameId>,
}
impl ReadArgs for InstanceRecord<'_> {
type Args = (u16, u16);
}
impl<'a> InstanceRecord<'a> {
pub fn read(
data: FontData<'a>,
axis_count: u16,
instance_size: u16,
) -> Result<Self, ReadError> {
let args = (axis_count, instance_size);
Self::read_with_args(data, &args)
}
}
impl<'a> FontReadWithArgs<'a> for InstanceRecord<'a> {
fn read_with_args(data: FontData<'a>, args: &Self::Args) -> Result<Self, ReadError> {
let axis_count = args.0 as usize;
let instance_size = args.1 as usize;
let mut cursor = data.cursor();
let subfamily_name_id = cursor.read()?;
let flags = cursor.read()?;
let coordinates = cursor.read_array(axis_count)?;
let common_byte_len = u16::RAW_BYTE_LEN * 2 + (axis_count * Fixed::RAW_BYTE_LEN);
let has_post_script_name_id = instance_size >= common_byte_len + u16::RAW_BYTE_LEN;
let post_script_name_id = if has_post_script_name_id {
let id: NameId = cursor.read()?;
(id.to_u16() != 0xFFFF).then_some(id)
} else {
None
};
Ok(InstanceRecord {
subfamily_name_id,
flags,
coordinates,
post_script_name_id,
})
}
}
impl ComputeSize for InstanceRecord<'_> {
#[inline]
fn compute_size(args: &(u16, u16)) -> Result<usize, ReadError> {
Ok(args.1 as usize)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> InstanceRecord<'a> {
pub(crate) fn get_field(&self, idx: usize, _data: FontData<'a>) -> Option<Field<'a>> {
match idx {
0 => Some(Field::new("subfamily_name_id", self.subfamily_name_id)),
1 => Some(Field::new("flags", self.flags)),
2 => Some(Field::new("coordinates", self.coordinates)),
3 => Some(Field::new("post_script_name_id", self.post_script_name_id?)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for InstanceRecord<'a> {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "InstanceRecord",
data,
get_field: Box::new(move |idx, data| self.get_field(idx, data)),
}
}
}