ttf_parser/tables/
avar.rs1use core::convert::TryFrom;
5
6use crate::parser::{FromData, LazyArray16, Stream};
7use crate::NormalizedCoordinate;
8
9#[derive(Clone, Copy, Debug)]
11pub struct AxisValueMap {
12 pub from_coordinate: i16,
14 pub to_coordinate: i16,
16}
17
18impl FromData for AxisValueMap {
19 const SIZE: usize = 4;
20
21 #[inline]
22 fn parse(data: &[u8]) -> Option<Self> {
23 let mut s = Stream::new(data);
24 Some(AxisValueMap {
25 from_coordinate: s.read::<i16>()?,
26 to_coordinate: s.read::<i16>()?,
27 })
28 }
29}
30
31#[derive(Clone, Copy)]
38pub struct SegmentMaps<'a> {
39 count: u16,
40 data: &'a [u8],
41}
42
43impl<'a> SegmentMaps<'a> {
44 pub fn len(&self) -> u16 {
46 self.count
47 }
48
49 pub fn is_empty(&self) -> bool {
51 self.count == 0
52 }
53}
54
55impl core::fmt::Debug for SegmentMaps<'_> {
56 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
57 write!(f, "SegmentMaps {{ ... }}")
58 }
59}
60
61impl<'a> IntoIterator for SegmentMaps<'a> {
62 type Item = LazyArray16<'a, AxisValueMap>;
63 type IntoIter = SegmentMapsIter<'a>;
64
65 #[inline]
66 fn into_iter(self) -> Self::IntoIter {
67 SegmentMapsIter {
68 stream: Stream::new(self.data),
69 }
70 }
71}
72
73#[allow(missing_debug_implementations)]
75pub struct SegmentMapsIter<'a> {
76 stream: Stream<'a>,
77}
78
79impl<'a> Iterator for SegmentMapsIter<'a> {
80 type Item = LazyArray16<'a, AxisValueMap>;
81
82 fn next(&mut self) -> Option<Self::Item> {
83 let count = self.stream.read::<u16>()?;
84 self.stream.read_array16::<AxisValueMap>(count)
85 }
86}
87
88#[derive(Clone, Copy, Debug)]
91pub struct Table<'a> {
92 pub segment_maps: SegmentMaps<'a>,
95}
96
97impl<'a> Table<'a> {
98 pub fn parse(data: &'a [u8]) -> Option<Self> {
100 let mut s = Stream::new(data);
101
102 let version = s.read::<u32>()?;
103 if version != 0x00010000 {
104 return None;
105 }
106
107 s.skip::<u16>(); Some(Self {
109 segment_maps: SegmentMaps {
110 count: s.read::<u16>()?,
112 data: s.tail()?,
113 },
114 })
115 }
116
117 pub fn map_coordinate(
119 &self,
120 coordinates: &mut [NormalizedCoordinate],
121 coordinate_index: usize,
122 ) -> Option<()> {
123 if usize::from(self.segment_maps.count) != coordinates.len() {
124 return None;
125 }
126
127 if let Some((map, coord)) = self
128 .segment_maps
129 .into_iter()
130 .zip(coordinates)
131 .nth(coordinate_index)
132 {
133 *coord = NormalizedCoordinate::from(map_value(&map, coord.0)?);
134 }
135
136 Some(())
137 }
138}
139
140fn map_value(map: &LazyArray16<AxisValueMap>, value: i16) -> Option<i16> {
141 if map.is_empty() {
144 return Some(value);
145 } else if map.len() == 1 {
146 let record = map.get(0)?;
147 return Some(value - record.from_coordinate + record.to_coordinate);
148 }
149
150 let record_0 = map.get(0)?;
151 if value <= record_0.from_coordinate {
152 return Some(value - record_0.from_coordinate + record_0.to_coordinate);
153 }
154
155 let mut i = 1;
156 while i < map.len() && value > map.get(i)?.from_coordinate {
157 i += 1;
158 }
159
160 if i == map.len() {
161 i -= 1;
162 }
163
164 let record_curr = map.get(i)?;
165 let curr_from = record_curr.from_coordinate;
166 let curr_to = record_curr.to_coordinate;
167 if value >= curr_from {
168 return Some(value - curr_from + curr_to);
169 }
170
171 let record_prev = map.get(i - 1)?;
172 let prev_from = record_prev.from_coordinate;
173 let prev_to = record_prev.to_coordinate;
174 if prev_from == curr_from {
175 return Some(prev_to);
176 }
177
178 let curr_from = i32::from(curr_from);
179 let curr_to = i32::from(curr_to);
180 let prev_from = i32::from(prev_from);
181 let prev_to = i32::from(prev_to);
182
183 let denom = curr_from - prev_from;
184 let k = (curr_to - prev_to) * (i32::from(value) - prev_from) + denom / 2;
185 let value = prev_to + k / denom;
186 i16::try_from(value).ok()
187}