ttf_parser/tables/
mvar.rs
1use crate::{Tag, NormalizedCoordinate};
4use crate::parser::{Stream, FromData, Offset, Offset16, LazyArray16};
5use crate::var_store::ItemVariationStore;
6
7
8#[derive(Clone, Copy)]
9struct ValueRecord {
10 value_tag: Tag,
11 delta_set_outer_index: u16,
12 delta_set_inner_index: u16,
13}
14
15impl FromData for ValueRecord {
16 const SIZE: usize = 8;
17
18 #[inline]
19 fn parse(data: &[u8]) -> Option<Self> {
20 let mut s = Stream::new(data);
21 Some(ValueRecord {
22 value_tag: s.read::<Tag>()?,
23 delta_set_outer_index: s.read::<u16>()?,
24 delta_set_inner_index: s.read::<u16>()?,
25 })
26 }
27}
28
29
30#[derive(Clone, Copy)]
31pub(crate) struct Table<'a> {
32 variation_store: ItemVariationStore<'a>,
33 records: LazyArray16<'a, ValueRecord>,
34}
35
36impl<'a> Table<'a> {
37 pub fn parse(data: &'a [u8]) -> Option<Self> {
38 let mut s = Stream::new(data);
39
40 let version: u32 = s.read()?;
41 if version != 0x00010000 {
42 return None;
43 }
44
45 s.skip::<u16>(); let value_record_size: u16 = s.read()?;
47
48 if usize::from(value_record_size) != ValueRecord::SIZE {
49 return None;
50 }
51
52 let count: u16 = s.read()?;
53 if count == 0 {
54 return None;
55 }
56
57 let var_store_offset = s.read::<Option<Offset16>>()??.to_usize();
58 let records = s.read_array16::<ValueRecord>(count)?;
59 let variation_store = ItemVariationStore::parse(Stream::new_at(data, var_store_offset)?)?;
60
61 Some(Table {
62 variation_store,
63 records,
64 })
65 }
66
67 pub fn metrics_offset(&self, tag: Tag, coordinates: &[NormalizedCoordinate]) -> Option<f32> {
68 let (_, record) = self.records.binary_search_by(|r| r.value_tag.cmp(&tag))?;
69 self.variation_store.parse_delta(
70 record.delta_set_outer_index,
71 record.delta_set_inner_index,
72 coordinates
73 )
74 }
75}