ttf_parser/tables/
avar.rs
1use core::convert::TryFrom;
4use core::num::NonZeroU16;
5
6use crate::NormalizedCoordinate;
7use crate::parser::{Stream, FromData, LazyArray16};
8
9
10#[derive(Clone, Copy)]
11pub(crate) struct Table<'a> {
12 axis_count: NonZeroU16,
13 data: &'a [u8],
14}
15
16impl<'a> Table<'a> {
17 pub fn parse(data: &'a [u8]) -> Option<Self> {
18 let mut s = Stream::new(data);
19
20 let version: u32 = s.read()?;
21 if version != 0x00010000 {
22 return None;
23 }
24
25 s.skip::<u16>(); let axis_count: u16 = s.read()?;
28 let axis_count = NonZeroU16::new(axis_count)?;
29
30 let data = s.tail()?;
31
32 for _ in 0..axis_count.get() {
34 let count: u16 = s.read()?;
35 s.advance_checked(AxisValueMapRecord::SIZE * usize::from(count))?;
36 }
37
38 Some(Table {
39 axis_count,
40 data,
41 })
42 }
43
44 pub fn map_coordinates(&self, coordinates: &mut [NormalizedCoordinate]) -> Option<()> {
45 if usize::from(self.axis_count.get()) != coordinates.len() {
46 return None;
47 }
48
49 let mut s = Stream::new(self.data);
50 for coord in coordinates {
51 let count: u16 = s.read()?;
52 let map = s.read_array16::<AxisValueMapRecord>(count)?;
53 *coord = NormalizedCoordinate::from(map_value(&map, coord.0)?);
54 }
55
56 Some(())
57 }
58}
59
60fn map_value(map: &LazyArray16<AxisValueMapRecord>, value: i16) -> Option<i16> {
61 if map.len() == 0 {
64 return Some(value);
65 } else if map.len() == 1 {
66 let record = map.get(0)?;
67 return Some(value - record.from_coordinate + record.to_coordinate);
68 }
69
70 let record_0 = map.get(0)?;
71 if value <= record_0.from_coordinate {
72 return Some(value - record_0.from_coordinate + record_0.to_coordinate);
73 }
74
75 let mut i = 1;
76 while i < map.len() && value > map.get(i)?.from_coordinate {
77 i += 1;
78 }
79
80 if i == map.len() {
81 i -= 1;
82 }
83
84 let record_curr = map.get(i)?;
85 let curr_from = record_curr.from_coordinate;
86 let curr_to = record_curr.to_coordinate;
87 if value >= curr_from {
88 return Some(value - curr_from + curr_to);
89 }
90
91 let record_prev = map.get(i - 1)?;
92 let prev_from = record_prev.from_coordinate;
93 let prev_to = record_prev.to_coordinate;
94 if prev_from == curr_from {
95 return Some(prev_to);
96 }
97
98 let curr_from = i32::from(curr_from);
99 let curr_to = i32::from(curr_to);
100 let prev_from = i32::from(prev_from);
101 let prev_to = i32::from(prev_to);
102
103 let denom = curr_from - prev_from;
104 let k = (curr_to - prev_to) * (i32::from(value) - prev_from) + denom / 2;
105 let value = prev_to + k / denom;
106 i16::try_from(value).ok()
107}
108
109
110#[derive(Clone, Copy)]
111struct AxisValueMapRecord {
112 from_coordinate: i16,
113 to_coordinate: i16,
114}
115
116impl FromData for AxisValueMapRecord {
117 const SIZE: usize = 4;
118
119 #[inline]
120 fn parse(data: &[u8]) -> Option<Self> {
121 let mut s = Stream::new(data);
122 Some(AxisValueMapRecord {
123 from_coordinate: s.read::<i16>()?,
124 to_coordinate: s.read::<i16>()?,
125 })
126 }
127}