read_fonts/tables/
instance_record.rs1use types::{BigEndian, Fixed, FixedSize, NameId};
4
5#[cfg(feature = "experimental_traverse")]
6use crate::traversal::{Field, RecordResolver, SomeRecord};
7use crate::{ComputeSize, FontData, FontReadWithArgs, ReadArgs, ReadError};
8
9#[derive(Clone, Debug)]
11pub struct InstanceRecord<'a> {
12 pub subfamily_name_id: NameId,
14 pub flags: u16,
16 pub coordinates: &'a [BigEndian<Fixed>],
18 pub post_script_name_id: Option<NameId>,
20}
21
22impl ReadArgs for InstanceRecord<'_> {
23 type Args = (u16, u16);
24}
25
26impl<'a> InstanceRecord<'a> {
27 pub fn read(
29 data: FontData<'a>,
30 axis_count: u16,
31 instance_size: u16,
32 ) -> Result<Self, ReadError> {
33 let args = (axis_count, instance_size);
34 Self::read_with_args(data, &args)
35 }
36}
37
38impl<'a> FontReadWithArgs<'a> for InstanceRecord<'a> {
39 fn read_with_args(data: FontData<'a>, args: &Self::Args) -> Result<Self, ReadError> {
40 let axis_count = args.0 as usize;
41 let instance_size = args.1 as usize;
42 let mut cursor = data.cursor();
43 let subfamily_name_id = cursor.read()?;
44 let flags = cursor.read()?;
45 let coordinates = cursor.read_array(axis_count)?;
46 let common_byte_len = u16::RAW_BYTE_LEN * 2 + (axis_count * Fixed::RAW_BYTE_LEN);
48 let has_post_script_name_id = instance_size >= common_byte_len + u16::RAW_BYTE_LEN;
51 let post_script_name_id = if has_post_script_name_id {
52 let id: NameId = cursor.read()?;
53 (id.to_u16() != 0xFFFF).then_some(id)
57 } else {
58 None
59 };
60 Ok(InstanceRecord {
61 subfamily_name_id,
62 flags,
63 coordinates,
64 post_script_name_id,
65 })
66 }
67}
68
69impl ComputeSize for InstanceRecord<'_> {
70 #[inline]
71 fn compute_size(args: &(u16, u16)) -> Result<usize, ReadError> {
72 Ok(args.1 as usize)
73 }
74}
75
76#[cfg(feature = "experimental_traverse")]
77impl<'a> InstanceRecord<'a> {
78 pub(crate) fn get_field(&self, idx: usize, _data: FontData<'a>) -> Option<Field<'a>> {
79 match idx {
80 0 => Some(Field::new("subfamily_name_id", self.subfamily_name_id)),
81 1 => Some(Field::new("flags", self.flags)),
82 2 => Some(Field::new("coordinates", self.coordinates)),
83 3 => Some(Field::new("post_script_name_id", self.post_script_name_id?)),
84 _ => None,
85 }
86 }
87}
88
89#[cfg(feature = "experimental_traverse")]
90impl<'a> SomeRecord<'a> for InstanceRecord<'a> {
91 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
92 RecordResolver {
93 name: "InstanceRecord",
94 data,
95 get_field: Box::new(move |idx, data| self.get_field(idx, data)),
96 }
97 }
98}