1use crate::{LineMetrics, GlyphId};
4use crate::parser::{Stream, Fixed, LazyArray16};
5
6
7const TABLE_SIZE: usize = 32;
8const ITALIC_ANGLE_OFFSET: usize = 4;
9const UNDERLINE_POSITION_OFFSET: usize = 8;
10const UNDERLINE_THICKNESS_OFFSET: usize = 10;
11const IS_FIXED_PITCH_OFFSET: usize = 12;
12
13const MACINTOSH_NAMES: &[&str] = &[
15 ".notdef",
16 ".null",
17 "nonmarkingreturn",
18 "space",
19 "exclam",
20 "quotedbl",
21 "numbersign",
22 "dollar",
23 "percent",
24 "ampersand",
25 "quotesingle",
26 "parenleft",
27 "parenright",
28 "asterisk",
29 "plus",
30 "comma",
31 "hyphen",
32 "period",
33 "slash",
34 "zero",
35 "one",
36 "two",
37 "three",
38 "four",
39 "five",
40 "six",
41 "seven",
42 "eight",
43 "nine",
44 "colon",
45 "semicolon",
46 "less",
47 "equal",
48 "greater",
49 "question",
50 "at",
51 "A",
52 "B",
53 "C",
54 "D",
55 "E",
56 "F",
57 "G",
58 "H",
59 "I",
60 "J",
61 "K",
62 "L",
63 "M",
64 "N",
65 "O",
66 "P",
67 "Q",
68 "R",
69 "S",
70 "T",
71 "U",
72 "V",
73 "W",
74 "X",
75 "Y",
76 "Z",
77 "bracketleft",
78 "backslash",
79 "bracketright",
80 "asciicircum",
81 "underscore",
82 "grave",
83 "a",
84 "b",
85 "c",
86 "d",
87 "e",
88 "f",
89 "g",
90 "h",
91 "i",
92 "j",
93 "k",
94 "l",
95 "m",
96 "n",
97 "o",
98 "p",
99 "q",
100 "r",
101 "s",
102 "t",
103 "u",
104 "v",
105 "w",
106 "x",
107 "y",
108 "z",
109 "braceleft",
110 "bar",
111 "braceright",
112 "asciitilde",
113 "Adieresis",
114 "Aring",
115 "Ccedilla",
116 "Eacute",
117 "Ntilde",
118 "Odieresis",
119 "Udieresis",
120 "aacute",
121 "agrave",
122 "acircumflex",
123 "adieresis",
124 "atilde",
125 "aring",
126 "ccedilla",
127 "eacute",
128 "egrave",
129 "ecircumflex",
130 "edieresis",
131 "iacute",
132 "igrave",
133 "icircumflex",
134 "idieresis",
135 "ntilde",
136 "oacute",
137 "ograve",
138 "ocircumflex",
139 "odieresis",
140 "otilde",
141 "uacute",
142 "ugrave",
143 "ucircumflex",
144 "udieresis",
145 "dagger",
146 "degree",
147 "cent",
148 "sterling",
149 "section",
150 "bullet",
151 "paragraph",
152 "germandbls",
153 "registered",
154 "copyright",
155 "trademark",
156 "acute",
157 "dieresis",
158 "notequal",
159 "AE",
160 "Oslash",
161 "infinity",
162 "plusminus",
163 "lessequal",
164 "greaterequal",
165 "yen",
166 "mu",
167 "partialdiff",
168 "summation",
169 "product",
170 "pi",
171 "integral",
172 "ordfeminine",
173 "ordmasculine",
174 "Omega",
175 "ae",
176 "oslash",
177 "questiondown",
178 "exclamdown",
179 "logicalnot",
180 "radical",
181 "florin",
182 "approxequal",
183 "Delta",
184 "guillemotleft",
185 "guillemotright",
186 "ellipsis",
187 "nonbreakingspace",
188 "Agrave",
189 "Atilde",
190 "Otilde",
191 "OE",
192 "oe",
193 "endash",
194 "emdash",
195 "quotedblleft",
196 "quotedblright",
197 "quoteleft",
198 "quoteright",
199 "divide",
200 "lozenge",
201 "ydieresis",
202 "Ydieresis",
203 "fraction",
204 "currency",
205 "guilsinglleft",
206 "guilsinglright",
207 "fi",
208 "fl",
209 "daggerdbl",
210 "periodcentered",
211 "quotesinglbase",
212 "quotedblbase",
213 "perthousand",
214 "Acircumflex",
215 "Ecircumflex",
216 "Aacute",
217 "Edieresis",
218 "Egrave",
219 "Iacute",
220 "Icircumflex",
221 "Idieresis",
222 "Igrave",
223 "Oacute",
224 "Ocircumflex",
225 "apple",
226 "Ograve",
227 "Uacute",
228 "Ucircumflex",
229 "Ugrave",
230 "dotlessi",
231 "circumflex",
232 "tilde",
233 "macron",
234 "breve",
235 "dotaccent",
236 "ring",
237 "cedilla",
238 "hungarumlaut",
239 "ogonek",
240 "caron",
241 "Lslash",
242 "lslash",
243 "Scaron",
244 "scaron",
245 "Zcaron",
246 "zcaron",
247 "brokenbar",
248 "Eth",
249 "eth",
250 "Yacute",
251 "yacute",
252 "Thorn",
253 "thorn",
254 "minus",
255 "multiply",
256 "onesuperior",
257 "twosuperior",
258 "threesuperior",
259 "onehalf",
260 "onequarter",
261 "threequarters",
262 "franc",
263 "Gbreve",
264 "gbreve",
265 "Idotaccent",
266 "Scedilla",
267 "scedilla",
268 "Cacute",
269 "cacute",
270 "Ccaron",
271 "ccaron",
272 "dcroat",
273];
274
275
276#[derive(Clone, Copy)]
277pub struct Table<'a> {
278 italic_angle: f32,
279 underline: LineMetrics,
280 is_monospaced: bool,
281 name_indexes: LazyArray16<'a, u16>,
282 names: &'a [u8],
283}
284
285impl<'a> Table<'a> {
286 pub fn parse(data: &'a [u8]) -> Option<Self> {
287 if data.len() < TABLE_SIZE {
288 return None;
289 }
290
291 let version: u32 = Stream::new(data).read()?;
292 if !(version == 0x00010000 || version == 0x00020000 ||
293 version == 0x00025000 || version == 0x00030000 ||
294 version == 0x00040000)
295 {
296 return None;
297 }
298
299 let italic_angle = Stream::read_at::<Fixed>(data, ITALIC_ANGLE_OFFSET)?.0;
300
301 let underline = LineMetrics {
302 position: Stream::read_at::<i16>(data, UNDERLINE_POSITION_OFFSET)?,
303 thickness: Stream::read_at::<i16>(data, UNDERLINE_THICKNESS_OFFSET)?,
304 };
305
306 let is_monospaced = Stream::read_at::<u32>(data, IS_FIXED_PITCH_OFFSET)? != 0;
307
308 let mut name_indexes = LazyArray16::default();
309 let mut names: &[u8] = &[];
310
311 if version == 0x00020000 {
313 let mut s = Stream::new_at(data, TABLE_SIZE)?;
314 let count: u16 = s.read()?;
315 name_indexes = s.read_array16::<u16>(count)?;
316 names = s.tail()?;
317 }
318
319 Some(Table {
320 italic_angle,
321 underline,
322 is_monospaced,
323 name_indexes,
324 names,
325 })
326 }
327
328 #[inline]
329 pub fn italic_angle(&self) -> f32 {
330 self.italic_angle
331 }
332
333 #[inline]
334 pub fn underline_metrics(&self) -> LineMetrics {
335 self.underline
336 }
337
338 #[inline]
339 pub fn is_monospaced(&self) -> bool {
340 self.is_monospaced
341 }
342
343 #[inline]
344 pub fn glyph_name(&self, glyph_id: GlyphId) -> Option<&'a str> {
345 let mut index = self.name_indexes.get(glyph_id.0)?;
346
347 if usize::from(index) < MACINTOSH_NAMES.len() {
350 Some(MACINTOSH_NAMES[usize::from(index)])
351 } else {
352 index -= MACINTOSH_NAMES.len() as u16;
355
356 let mut s = Stream::new(self.names);
357 let mut i = 0;
358 while !s.at_end() && i < core::u16::MAX {
359 let len: u8 = s.read()?;
360
361 if i == index {
362 if len == 0 {
363 break;
365 } else {
366 let name = s.read_bytes(usize::from(len))?;
367 return core::str::from_utf8(name).ok();
368 }
369 } else {
370 s.advance(usize::from(len));
371 }
372
373 i += 1;
374 }
375
376 None
377 }
378 }
379}