read_fonts/tables/postscript/
index.rs1use super::{Error, Index1, Index2};
6use crate::codegen_prelude::*;
7
8#[derive(Clone)]
10pub enum Index<'a> {
11 Empty,
12 Format1(Index1<'a>),
13 Format2(Index2<'a>),
14}
15
16impl<'a> Index<'a> {
17 pub fn new(data: &'a [u8], is_cff2: bool) -> Result<Self, Error> {
21 let data = FontData::new(data);
22 Ok(if is_cff2 {
23 Index2::read(data).map(|ix| ix.into())?
24 } else {
25 Index1::read(data).map(|ix| ix.into())?
26 })
27 }
28
29 pub fn count(&self) -> u32 {
31 match self {
32 Self::Empty => 0,
33 Self::Format1(ix) => ix.count() as u32,
34 Self::Format2(ix) => ix.count(),
35 }
36 }
37
38 pub fn subr_bias(&self) -> i32 {
43 let count = self.count();
44 if count < 1240 {
45 107
46 } else if count < 33900 {
47 1131
48 } else {
49 32768
50 }
51 }
52
53 pub fn size_in_bytes(&self) -> Result<usize, ReadError> {
55 match self {
56 Self::Empty => Ok(0),
57 Self::Format1(ix) => ix.size_in_bytes(),
58 Self::Format2(ix) => ix.size_in_bytes(),
59 }
60 }
61
62 pub fn get_offset(&self, index: usize) -> Result<usize, Error> {
64 match self {
65 Self::Empty => Err(ReadError::OutOfBounds.into()),
66 Self::Format1(ix) => ix.get_offset(index),
67 Self::Format2(ix) => ix.get_offset(index),
68 }
69 }
70
71 pub fn get(&self, index: usize) -> Result<&'a [u8], Error> {
73 match self {
74 Self::Empty => Err(ReadError::OutOfBounds.into()),
75 Self::Format1(ix) => ix.get(index),
76 Self::Format2(ix) => ix.get(index),
77 }
78 }
79
80 pub fn off_size(&self) -> u8 {
81 match self {
82 Self::Empty => 0,
83 Self::Format1(ix) => ix.off_size(),
84 Self::Format2(ix) => ix.off_size(),
85 }
86 }
87}
88
89impl<'a> From<Index1<'a>> for Index<'a> {
90 fn from(value: Index1<'a>) -> Self {
91 Self::Format1(value)
92 }
93}
94
95impl<'a> From<Index2<'a>> for Index<'a> {
96 fn from(value: Index2<'a>) -> Self {
97 Self::Format2(value)
98 }
99}
100
101impl Default for Index<'_> {
102 fn default() -> Self {
103 Self::Empty
104 }
105}
106
107impl<'a> Index1<'a> {
108 pub fn size_in_bytes(&self) -> Result<usize, ReadError> {
110 const HEADER_SIZE: usize = 3;
112 const EMPTY_SIZE: usize = 2;
114 let count = self.count() as usize;
115 Ok(match count {
116 0 => EMPTY_SIZE,
117 _ => {
118 HEADER_SIZE
119 + self.offsets().len()
120 + self.get_offset(count).map_err(|_| ReadError::OutOfBounds)?
121 }
122 })
123 }
124
125 pub fn get_offset(&self, index: usize) -> Result<usize, Error> {
127 read_offset(
128 index,
129 self.count() as usize,
130 self.off_size(),
131 self.offsets(),
132 )
133 }
134
135 pub fn get(&self, index: usize) -> Result<&'a [u8], Error> {
137 self.data()
138 .get(self.get_offset(index)?..self.get_offset(index + 1)?)
139 .ok_or(ReadError::OutOfBounds.into())
140 }
141}
142
143impl<'a> Index2<'a> {
144 pub fn size_in_bytes(&self) -> Result<usize, ReadError> {
146 const HEADER_SIZE: usize = 5;
148 const EMPTY_SIZE: usize = 4;
150 let count = self.count() as usize;
151 Ok(match count {
152 0 => EMPTY_SIZE,
153 _ => {
154 HEADER_SIZE
155 + self.offsets().len()
156 + self.get_offset(count).map_err(|_| ReadError::OutOfBounds)?
157 }
158 })
159 }
160
161 pub fn get_offset(&self, index: usize) -> Result<usize, Error> {
163 read_offset(
164 index,
165 self.count() as usize,
166 self.off_size(),
167 self.offsets(),
168 )
169 }
170
171 pub fn get(&self, index: usize) -> Result<&'a [u8], Error> {
173 self.data()
174 .get(self.get_offset(index)?..self.get_offset(index + 1)?)
175 .ok_or(ReadError::OutOfBounds.into())
176 }
177}
178
179fn read_offset(
181 index: usize,
182 count: usize,
183 offset_size: u8,
184 offset_data: &[u8],
185) -> Result<usize, Error> {
186 if index > count {
196 Err(ReadError::OutOfBounds)?;
197 }
198 let data_offset = index * offset_size as usize;
199 let offset_data = FontData::new(offset_data);
200 match offset_size {
201 1 => offset_data.read_at::<u8>(data_offset)? as usize,
202 2 => offset_data.read_at::<u16>(data_offset)? as usize,
203 3 => offset_data.read_at::<Uint24>(data_offset)?.to_u32() as usize,
204 4 => offset_data.read_at::<u32>(data_offset)? as usize,
205 _ => return Err(Error::InvalidIndexOffsetSize(offset_size)),
206 }
207 .checked_sub(1)
209 .ok_or(Error::ZeroOffsetInIndex)
210}
211
212#[cfg(test)]
213mod tests {
214 use font_test_data::bebuffer::BeBuffer;
215
216 use super::*;
217
218 enum IndexParams {
219 Format1 { off_size: u8, count: usize },
220 Format2 { off_size: u8, count: usize },
221 }
222
223 #[test]
224 fn index_format1_offsize1_count4() {
225 test_index(IndexParams::Format1 {
226 off_size: 1,
227 count: 4,
228 });
229 }
230
231 #[test]
232 fn index_format1_offsize2_count64() {
233 test_index(IndexParams::Format1 {
234 off_size: 2,
235 count: 64,
236 });
237 }
238
239 #[test]
240 fn index_format1_offsize3_count128() {
241 test_index(IndexParams::Format1 {
242 off_size: 3,
243 count: 128,
244 });
245 }
246
247 #[test]
248 fn index_format1_offsize4_count256() {
249 test_index(IndexParams::Format1 {
250 off_size: 4,
251 count: 256,
252 });
253 }
254
255 #[test]
256 fn index_format2_offsize1_count4() {
257 test_index(IndexParams::Format2 {
258 off_size: 4,
259 count: 256,
260 });
261 }
262
263 #[test]
264 fn index_format2_offsize2_count64() {
265 test_index(IndexParams::Format2 {
266 off_size: 2,
267 count: 64,
268 });
269 }
270
271 #[test]
272 fn index_format2_offsize3_count128() {
273 test_index(IndexParams::Format2 {
274 off_size: 3,
275 count: 128,
276 });
277 }
278
279 #[test]
280 fn index_format2_offsize4_count256() {
281 test_index(IndexParams::Format2 {
282 off_size: 4,
283 count: 256,
284 });
285 }
286
287 fn test_index(params: IndexParams) {
288 let (fmt, off_size, count) = match params {
289 IndexParams::Format1 { off_size, count } => (1, off_size, count),
290 IndexParams::Format2 { off_size, count } => (2, off_size, count),
291 };
292 let buf = make_index(fmt, off_size, count);
293 let index = Index::new(buf.data(), fmt == 2).unwrap();
294 let built_off_size = match &index {
295 Index::Empty => 0,
296 Index::Format1(v1) => v1.off_size(),
297 Index::Format2(v2) => v2.off_size(),
298 };
299 assert_eq!(built_off_size, off_size);
300 assert_eq!(index.count(), count as u32);
301 for i in 0..count {
302 let object = index.get(i).unwrap();
303 let expected_len = (i + 1) * 10;
304 let expected_bytes = vec![i as u8; expected_len];
305 assert_eq!(object, expected_bytes);
306 }
307 }
308
309 fn make_index(fmt: u8, off_size: u8, count: usize) -> BeBuffer {
310 let mut buf = BeBuffer::new();
313 match fmt {
314 1 => buf = buf.push(count as u16),
315 2 => buf = buf.push(count as u32),
316 _ => panic!("INDEX fmt should be 1 or 2"),
317 }
318 if count == 0 {
319 return buf;
320 }
321 buf = buf.push(off_size);
322 let mut offset = 1usize;
324 for i in 0..count + 1 {
325 buf = match off_size {
326 1 => buf.push(offset as u8),
327 2 => buf.push(offset as u16),
328 3 => buf.push(Uint24::checked_new(offset as u32).unwrap()),
329 4 => buf.push(offset as u32),
330 _ => panic!("off_size should be 1-4"),
331 };
332 offset += (i + 1) * 10;
333 }
334 for i in 0..count {
336 buf = buf.extend(std::iter::repeat(i as u8).take((i + 1) * 10));
337 }
338 buf
339 }
340}