read_fonts/tables/
trak.rs1include!("../../generated/generated_trak.rs");
4
5impl<'a> TrackData<'a> {
6 pub fn size_table(
10 &self,
11 offset_data: FontData<'a>,
12 ) -> Result<&'a [BigEndian<Fixed>], ReadError> {
13 let mut cursor = offset_data
14 .split_off(self.size_table_offset() as usize)
15 .ok_or(ReadError::OutOfBounds)?
16 .cursor();
17 cursor.read_array(self.n_sizes() as usize)
18 }
19}
20
21impl TrackTableEntry {
22 pub fn per_size_values<'a>(
27 &self,
28 offset_data: FontData<'a>,
29 n_sizes: u16,
30 ) -> Result<&'a [BigEndian<i16>], ReadError> {
31 let mut cursor = offset_data
32 .split_off(self.offset() as usize)
33 .ok_or(ReadError::OutOfBounds)?
34 .cursor();
35 cursor.read_array(n_sizes as usize)
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use font_test_data::bebuffer::BeBuffer;
43
44 #[test]
45 fn parse_header() {
46 let table_data = example_track_table();
47 let trak = Trak::read(FontData::new(&table_data)).unwrap();
48 assert_eq!(trak.version(), MajorMinor::VERSION_1_0);
49 let _ = trak.horiz().unwrap().unwrap();
50 assert!(trak.vert().is_none());
51 }
52
53 #[test]
54 fn parse_tracks() {
55 let table_data = example_track_table();
56 let trak = Trak::read(FontData::new(&table_data)).unwrap();
57 let horiz = trak.horiz().unwrap().unwrap();
58 let track_table = horiz.track_table();
59 let expected_tracks = [
60 (Fixed::from_i32(-1), NameId::new(256), 52),
61 (Fixed::from_i32(0), NameId::new(258), 60),
62 (Fixed::from_i32(1), NameId::new(257), 56),
63 ];
64 let tracks = track_table
65 .iter()
66 .map(|track| (track.track(), track.name_index(), track.offset()))
67 .collect::<Vec<_>>();
68 assert_eq!(tracks, expected_tracks);
69 let expected_per_size_tracking_values = [[-15i16, -7], [0, 0], [50, 20]];
70 for (track, expected_values) in track_table.iter().zip(expected_per_size_tracking_values) {
71 let values = track
72 .per_size_values(trak.offset_data(), horiz.n_sizes())
73 .unwrap()
74 .iter()
75 .map(|v| v.get())
76 .collect::<Vec<_>>();
77 assert_eq!(values, expected_values);
78 }
79 }
80
81 #[test]
82 fn parse_per_size_values() {
83 let table_data = example_track_table();
84 let trak = Trak::read(FontData::new(&table_data)).unwrap();
85 let horiz = trak.horiz().unwrap().unwrap();
86 let track_table = horiz.track_table();
87 let expected_per_size_tracking_values = [[-15i16, -7], [0, 0], [50, 20]];
88 for (track, expected_values) in track_table.iter().zip(expected_per_size_tracking_values) {
89 let values = track
90 .per_size_values(trak.offset_data(), horiz.n_sizes())
91 .unwrap()
92 .iter()
93 .map(|v| v.get())
94 .collect::<Vec<_>>();
95 assert_eq!(values, expected_values);
96 }
97 }
98
99 #[test]
100 fn parse_sizes() {
101 let table_data = example_track_table();
102 let trak = Trak::read(FontData::new(&table_data)).unwrap();
103 let horiz = trak.horiz().unwrap().unwrap();
104 let size_table = horiz
105 .size_table(trak.offset_data())
106 .unwrap()
107 .iter()
108 .map(|v| v.get())
109 .collect::<Vec<_>>();
110 let expected_sizes = [Fixed::from_i32(12), Fixed::from_i32(24)];
111 assert_eq!(size_table, expected_sizes);
112 }
113
114 #[test]
115 fn insufficient_data() {
116 let mut table_data = example_track_table();
117 table_data.pop();
119 let trak = Trak::read(FontData::new(&table_data)).unwrap();
120 let horiz = trak.horiz().unwrap().unwrap();
121 let track_table = horiz.track_table();
122 let expected_per_size_tracking_values = [Some([-15i16, -7]), None, Some([50, 20])];
124 for (track, expected_values) in track_table.iter().zip(expected_per_size_tracking_values) {
125 let values = track
126 .per_size_values(trak.offset_data(), horiz.n_sizes())
127 .ok()
128 .map(|values| values.iter().map(|v| v.get()).collect::<Vec<_>>());
129 assert_eq!(
130 values,
131 expected_values.map(|value| value.into_iter().collect())
132 );
133 }
134 }
135
136 #[test]
137 fn bad_offset() {
138 let mut table_data = example_track_table();
139 table_data[26] = 255;
141 let trak = Trak::read(FontData::new(&table_data)).unwrap();
142 let horiz = trak.horiz().unwrap().unwrap();
143 let track_table = horiz.track_table();
144 assert!(matches!(
145 track_table[0].per_size_values(trak.offset_data(), horiz.n_sizes()),
146 Err(ReadError::OutOfBounds)
147 ));
148 }
149
150 fn example_track_table() -> Vec<u8> {
152 let mut buf = BeBuffer::new();
153 buf = buf.push(MajorMinor::VERSION_1_0);
155 buf = buf.extend([0u16, 12, 0, 0]);
156 buf = buf.extend([3u16, 2]);
158 buf = buf.push(44u32);
159 buf = buf.push(0xFFFF0000u32).extend([256u16, 52]);
161 buf = buf.push(0x00000000u32).extend([258u16, 60]);
162 buf = buf.push(0x00010000u32).extend([257u16, 56]);
163 buf = buf.push(0x000C0000u32);
165 buf = buf.push(0x00180000u32);
166 buf = buf.extend([-15i16, -7, 50, 20, 0, 0]);
168 buf.to_vec()
169 }
170}