ttf_parser/tables/
avar.rs1use core::convert::TryFrom;
5
6use crate::NormalizedCoordinate;
7use crate::parser::{Stream, FromData, LazyArray16};
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
32#[derive(Clone, Copy)]
39pub struct SegmentMaps<'a> {
40 count: u16,
41 data: &'a [u8],
42}
43
44impl<'a> SegmentMaps<'a> {
45 pub fn len(&self) -> u16 {
47 self.count
48 }
49}
50
51impl core::fmt::Debug for SegmentMaps<'_> {
52 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
53 write!(f, "SegmentMaps {{ ... }}")
54 }
55}
56
57impl<'a> IntoIterator for SegmentMaps<'a> {
58 type Item = LazyArray16<'a, AxisValueMap>;
59 type IntoIter = SegmentMapsIter<'a>;
60
61 #[inline]
62 fn into_iter(self) -> Self::IntoIter {
63 SegmentMapsIter {
64 stream: Stream::new(self.data),
65 }
66 }
67}
68
69#[allow(missing_debug_implementations)]
71pub struct SegmentMapsIter<'a> {
72 stream: Stream<'a>,
73}
74
75impl<'a> Iterator for SegmentMapsIter<'a> {
76 type Item = LazyArray16<'a, AxisValueMap>;
77
78 fn next(&mut self) -> Option<Self::Item> {
79 let count = self.stream.read::<u16>()?;
80 return self.stream.read_array16::<AxisValueMap>(count);
81 }
82}
83
84
85#[derive(Clone, Copy, Debug)]
88pub struct Table<'a> {
89 pub segment_maps: SegmentMaps<'a>,
92}
93
94impl<'a> Table<'a> {
95 pub fn parse(data: &'a [u8]) -> Option<Self> {
97 let mut s = Stream::new(data);
98
99 let version = s.read::<u32>()?;
100 if version != 0x00010000 {
101 return None;
102 }
103
104 s.skip::<u16>(); Some(Self {
106 segment_maps: SegmentMaps {
107 count: s.read::<u16>()?,
109 data: s.tail()?,
110 },
111 })
112 }
113
114 pub fn map_coordinates(&self, coordinates: &mut [NormalizedCoordinate]) -> Option<()> {
116 if usize::from(self.segment_maps.count) != coordinates.len() {
117 return None;
118 }
119
120 for (map, coord) in self.segment_maps.into_iter().zip(coordinates) {
121 *coord = NormalizedCoordinate::from(map_value(&map, coord.0)?);
122 }
123
124 Some(())
125 }
126}
127
128fn map_value(map: &LazyArray16<AxisValueMap>, value: i16) -> Option<i16> {
129 if map.len() == 0 {
132 return Some(value);
133 } else if map.len() == 1 {
134 let record = map.get(0)?;
135 return Some(value - record.from_coordinate + record.to_coordinate);
136 }
137
138 let record_0 = map.get(0)?;
139 if value <= record_0.from_coordinate {
140 return Some(value - record_0.from_coordinate + record_0.to_coordinate);
141 }
142
143 let mut i = 1;
144 while i < map.len() && value > map.get(i)?.from_coordinate {
145 i += 1;
146 }
147
148 if i == map.len() {
149 i -= 1;
150 }
151
152 let record_curr = map.get(i)?;
153 let curr_from = record_curr.from_coordinate;
154 let curr_to = record_curr.to_coordinate;
155 if value >= curr_from {
156 return Some(value - curr_from + curr_to);
157 }
158
159 let record_prev = map.get(i - 1)?;
160 let prev_from = record_prev.from_coordinate;
161 let prev_to = record_prev.to_coordinate;
162 if prev_from == curr_from {
163 return Some(prev_to);
164 }
165
166 let curr_from = i32::from(curr_from);
167 let curr_to = i32::from(curr_to);
168 let prev_from = i32::from(prev_from);
169 let prev_to = i32::from(prev_to);
170
171 let denom = curr_from - prev_from;
172 let k = (curr_to - prev_to) * (i32::from(value) - prev_from) + denom / 2;
173 let value = prev_to + k / denom;
174 i16::try_from(value).ok()
175}