1mod afm;
6pub use afm::{is_standard_14, standard_14_width};
7
8const WIN_ANSI_80_9F: [Option<char>; 32] = [
11 Some('\u{20AC}'),
12 None,
13 Some('\u{201A}'),
14 Some('\u{0192}'),
15 Some('\u{201E}'),
16 Some('\u{2026}'),
17 Some('\u{2020}'),
18 Some('\u{2021}'),
19 Some('\u{02C6}'),
20 Some('\u{2030}'),
21 Some('\u{0160}'),
22 Some('\u{2039}'),
23 Some('\u{0152}'),
24 None,
25 Some('\u{017D}'),
26 None,
27 None,
28 Some('\u{2018}'),
29 Some('\u{2019}'),
30 Some('\u{201C}'),
31 Some('\u{201D}'),
32 Some('\u{2022}'),
33 Some('\u{2013}'),
34 Some('\u{2014}'),
35 Some('\u{02DC}'),
36 Some('\u{2122}'),
37 Some('\u{0161}'),
38 Some('\u{203A}'),
39 Some('\u{0153}'),
40 None,
41 Some('\u{017E}'),
42 Some('\u{0178}'),
43];
44
45pub fn win_ansi(code: u8) -> Option<char> {
47 match code {
48 0x20..=0x7E => Some(code as char),
49 0x80..=0x9F => WIN_ANSI_80_9F[(code - 0x80) as usize],
50 0xA0..=0xFF => Some(code as char),
51 _ => None,
52 }
53}
54
55const MAC_ROMAN_HIGH: [char; 128] = [
57 '\u{C4}', '\u{C5}', '\u{C7}', '\u{C9}', '\u{D1}', '\u{D6}', '\u{DC}', '\u{E1}', '\u{E0}',
58 '\u{E2}', '\u{E4}', '\u{E3}', '\u{E5}', '\u{E7}', '\u{E9}', '\u{E8}', '\u{EA}', '\u{EB}',
59 '\u{ED}', '\u{EC}', '\u{EE}', '\u{EF}', '\u{F1}', '\u{F3}', '\u{F2}', '\u{F4}', '\u{F6}',
60 '\u{F5}', '\u{FA}', '\u{F9}', '\u{FB}', '\u{FC}', '\u{2020}', '\u{B0}', '\u{A2}', '\u{A3}',
61 '\u{A7}', '\u{2022}', '\u{B6}', '\u{DF}', '\u{AE}', '\u{A9}', '\u{2122}', '\u{B4}', '\u{A8}',
62 '\u{2260}', '\u{C6}', '\u{D8}', '\u{221E}', '\u{B1}', '\u{2264}', '\u{2265}', '\u{A5}',
63 '\u{B5}', '\u{2202}', '\u{2211}', '\u{220F}', '\u{3C0}', '\u{222B}', '\u{AA}', '\u{BA}',
64 '\u{3A9}', '\u{E6}', '\u{F8}', '\u{BF}', '\u{A1}', '\u{AC}', '\u{221A}', '\u{192}', '\u{2248}',
65 '\u{2206}', '\u{AB}', '\u{BB}', '\u{2026}', '\u{A0}', '\u{C0}', '\u{C3}', '\u{D5}', '\u{152}',
66 '\u{153}', '\u{2013}', '\u{2014}', '\u{201C}', '\u{201D}', '\u{2018}', '\u{2019}', '\u{F7}',
67 '\u{25CA}', '\u{FF}', '\u{178}', '\u{2044}', '\u{20AC}', '\u{2039}', '\u{203A}', '\u{FB01}',
68 '\u{FB02}', '\u{2021}', '\u{B7}', '\u{201A}', '\u{201E}', '\u{2030}', '\u{C2}', '\u{CA}',
69 '\u{C1}', '\u{CB}', '\u{C8}', '\u{CD}', '\u{CE}', '\u{CF}', '\u{CC}', '\u{D3}', '\u{D4}',
70 '\u{F8FF}', '\u{D2}', '\u{DA}', '\u{DB}', '\u{D9}', '\u{131}', '\u{2C6}', '\u{2DC}', '\u{AF}',
71 '\u{2D8}', '\u{2D9}', '\u{2DA}', '\u{B8}', '\u{2DD}', '\u{2DB}', '\u{2C7}',
72];
73
74pub fn mac_roman(code: u8) -> Option<char> {
76 match code {
77 0x20..=0x7E => Some(code as char),
78 0x80..=0xFF => Some(MAC_ROMAN_HIGH[(code - 0x80) as usize]),
79 _ => None,
80 }
81}
82
83const STANDARD_HIGH: &[(u8, char)] = &[
85 (0xA1, '\u{A1}'),
86 (0xA2, '\u{A2}'),
87 (0xA3, '\u{A3}'),
88 (0xA4, '\u{2044}'),
89 (0xA5, '\u{A5}'),
90 (0xA6, '\u{192}'),
91 (0xA7, '\u{A7}'),
92 (0xA8, '\u{A4}'),
93 (0xA9, '\u{27}'),
94 (0xAA, '\u{201C}'),
95 (0xAB, '\u{AB}'),
96 (0xAC, '\u{2039}'),
97 (0xAD, '\u{203A}'),
98 (0xAE, '\u{FB01}'),
99 (0xAF, '\u{FB02}'),
100 (0xB1, '\u{2013}'),
101 (0xB2, '\u{2020}'),
102 (0xB3, '\u{2021}'),
103 (0xB4, '\u{B7}'),
104 (0xB6, '\u{B6}'),
105 (0xB7, '\u{2022}'),
106 (0xB8, '\u{201A}'),
107 (0xB9, '\u{201E}'),
108 (0xBA, '\u{201D}'),
109 (0xBB, '\u{BB}'),
110 (0xBC, '\u{2026}'),
111 (0xBD, '\u{2030}'),
112 (0xBF, '\u{BF}'),
113 (0xC1, '\u{60}'),
114 (0xC2, '\u{B4}'),
115 (0xC3, '\u{2C6}'),
116 (0xC4, '\u{2DC}'),
117 (0xC5, '\u{AF}'),
118 (0xC6, '\u{2D8}'),
119 (0xC7, '\u{2D9}'),
120 (0xC8, '\u{A8}'),
121 (0xCA, '\u{2DA}'),
122 (0xCB, '\u{B8}'),
123 (0xCD, '\u{2DD}'),
124 (0xCE, '\u{2DB}'),
125 (0xCF, '\u{2C7}'),
126 (0xD0, '\u{2014}'),
127 (0xE1, '\u{C6}'),
128 (0xE3, '\u{AA}'),
129 (0xE8, '\u{141}'),
130 (0xE9, '\u{D8}'),
131 (0xEA, '\u{152}'),
132 (0xEB, '\u{BA}'),
133 (0xF1, '\u{E6}'),
134 (0xF5, '\u{131}'),
135 (0xF8, '\u{142}'),
136 (0xF9, '\u{F8}'),
137 (0xFA, '\u{153}'),
138 (0xFB, '\u{DF}'),
139];
140
141pub fn standard(code: u8) -> Option<char> {
143 match code {
144 0x27 => Some('\u{2019}'),
145 0x60 => Some('\u{2018}'),
146 0x20..=0x7E => Some(code as char),
147 0xA1..=0xFF => STANDARD_HIGH
148 .iter()
149 .find(|&&(c, _)| c == code)
150 .map(|&(_, u)| u),
151 _ => None,
152 }
153}
154
155const STANDARD_ASCII_NAMES: [&str; 95] = [
161 "space",
162 "exclam",
163 "quotedbl",
164 "numbersign",
165 "dollar",
166 "percent",
167 "ampersand",
168 "quoteright",
169 "parenleft",
170 "parenright",
171 "asterisk",
172 "plus",
173 "comma",
174 "hyphen",
175 "period",
176 "slash",
177 "zero",
178 "one",
179 "two",
180 "three",
181 "four",
182 "five",
183 "six",
184 "seven",
185 "eight",
186 "nine",
187 "colon",
188 "semicolon",
189 "less",
190 "equal",
191 "greater",
192 "question",
193 "at",
194 "A",
195 "B",
196 "C",
197 "D",
198 "E",
199 "F",
200 "G",
201 "H",
202 "I",
203 "J",
204 "K",
205 "L",
206 "M",
207 "N",
208 "O",
209 "P",
210 "Q",
211 "R",
212 "S",
213 "T",
214 "U",
215 "V",
216 "W",
217 "X",
218 "Y",
219 "Z",
220 "bracketleft",
221 "backslash",
222 "bracketright",
223 "asciicircum",
224 "underscore",
225 "quoteleft",
226 "a",
227 "b",
228 "c",
229 "d",
230 "e",
231 "f",
232 "g",
233 "h",
234 "i",
235 "j",
236 "k",
237 "l",
238 "m",
239 "n",
240 "o",
241 "p",
242 "q",
243 "r",
244 "s",
245 "t",
246 "u",
247 "v",
248 "w",
249 "x",
250 "y",
251 "z",
252 "braceleft",
253 "bar",
254 "braceright",
255 "asciitilde",
256];
257
258const STANDARD_HIGH_NAMES: &[(u8, &str)] = &[
262 (0xA1, "exclamdown"),
263 (0xA2, "cent"),
264 (0xA3, "sterling"),
265 (0xA4, "fraction"),
266 (0xA5, "yen"),
267 (0xA6, "florin"),
268 (0xA7, "section"),
269 (0xA8, "currency"),
270 (0xA9, "quotesingle"),
271 (0xAA, "quotedblleft"),
272 (0xAB, "guillemotleft"),
273 (0xAC, "guilsinglleft"),
274 (0xAD, "guilsinglright"),
275 (0xAE, "fi"),
276 (0xAF, "fl"),
277 (0xB1, "endash"),
278 (0xB2, "dagger"),
279 (0xB3, "daggerdbl"),
280 (0xB4, "periodcentered"),
281 (0xB6, "paragraph"),
282 (0xB7, "bullet"),
283 (0xB8, "quotesinglbase"),
284 (0xB9, "quotedblbase"),
285 (0xBA, "quotedblright"),
286 (0xBB, "guillemotright"),
287 (0xBC, "ellipsis"),
288 (0xBD, "perthousand"),
289 (0xBF, "questiondown"),
290 (0xC1, "grave"),
291 (0xC2, "acute"),
292 (0xC3, "circumflex"),
293 (0xC4, "tilde"),
294 (0xC5, "macron"),
295 (0xC6, "breve"),
296 (0xC7, "dotaccent"),
297 (0xC8, "dieresis"),
298 (0xCA, "ring"),
299 (0xCB, "cedilla"),
300 (0xCD, "hungarumlaut"),
301 (0xCE, "ogonek"),
302 (0xCF, "caron"),
303 (0xD0, "emdash"),
304 (0xE1, "AE"),
305 (0xE3, "ordfeminine"),
306 (0xE8, "Lslash"),
307 (0xE9, "Oslash"),
308 (0xEA, "OE"),
309 (0xEB, "ordmasculine"),
310 (0xF1, "ae"),
311 (0xF5, "dotlessi"),
312 (0xF8, "lslash"),
313 (0xF9, "oslash"),
314 (0xFA, "oe"),
315 (0xFB, "germandbls"),
316];
317
318pub fn standard_encoding_name(code: u8) -> Option<&'static str> {
325 match code {
326 0x20..=0x7E => Some(STANDARD_ASCII_NAMES[(code - 0x20) as usize]),
327 0xA1..=0xFF => STANDARD_HIGH_NAMES
328 .iter()
329 .find(|&&(c, _)| c == code)
330 .map(|&(_, n)| n),
331 _ => None,
332 }
333}
334
335pub fn glyph_to_unicode(name: &str) -> Option<char> {
339 if let Some(hex) = name.strip_prefix("uni") {
340 if hex.len() == 4 && hex.bytes().all(|b| b.is_ascii_hexdigit()) {
341 return char::from_u32(u32::from_str_radix(hex, 16).ok()?);
342 }
343 }
344 if let Some(hex) = name.strip_prefix('u') {
345 if (4..=6).contains(&hex.len()) && hex.bytes().all(|b| b.is_ascii_hexdigit()) {
346 return char::from_u32(u32::from_str_radix(hex, 16).ok()?);
347 }
348 }
349 let mut chars = name.chars();
350 if let (Some(c), None) = (chars.next(), chars.next()) {
351 if c.is_ascii_alphabetic() {
352 return Some(c);
353 }
354 }
355 GLYPH_TABLES
356 .iter()
357 .flat_map(|t| t.iter())
358 .find(|&&(n, _)| n == name)
359 .map(|&(_, u)| u)
360}
361
362const GLYPH_TABLES: [&[(&str, char)]; 5] = [
364 GLYPHS_ASCII,
365 GLYPHS_LATIN1,
366 GLYPHS_PUNCT,
367 GLYPHS_GREEK,
368 GLYPHS_MISC,
369];
370
371const GLYPHS_ASCII: &[(&str, char)] = &[
373 ("space", ' '),
374 ("exclam", '!'),
375 ("quotedbl", '"'),
376 ("numbersign", '#'),
377 ("dollar", '$'),
378 ("percent", '%'),
379 ("ampersand", '&'),
380 ("quotesingle", '\''),
381 ("parenleft", '('),
382 ("parenright", ')'),
383 ("asterisk", '*'),
384 ("plus", '+'),
385 ("comma", ','),
386 ("hyphen", '-'),
387 ("period", '.'),
388 ("slash", '/'),
389 ("zero", '0'),
390 ("one", '1'),
391 ("two", '2'),
392 ("three", '3'),
393 ("four", '4'),
394 ("five", '5'),
395 ("six", '6'),
396 ("seven", '7'),
397 ("eight", '8'),
398 ("nine", '9'),
399 ("colon", ':'),
400 ("semicolon", ';'),
401 ("less", '<'),
402 ("equal", '='),
403 ("greater", '>'),
404 ("question", '?'),
405 ("at", '@'),
406 ("bracketleft", '['),
407 ("backslash", '\\'),
408 ("bracketright", ']'),
409 ("asciicircum", '^'),
410 ("underscore", '_'),
411 ("grave", '`'),
412 ("braceleft", '{'),
413 ("bar", '|'),
414 ("braceright", '}'),
415 ("asciitilde", '~'),
416];
417
418const GLYPHS_LATIN1: &[(&str, char)] = &[
420 ("exclamdown", '\u{A1}'),
421 ("cent", '\u{A2}'),
422 ("sterling", '\u{A3}'),
423 ("currency", '\u{A4}'),
424 ("yen", '\u{A5}'),
425 ("brokenbar", '\u{A6}'),
426 ("section", '\u{A7}'),
427 ("dieresis", '\u{A8}'),
428 ("copyright", '\u{A9}'),
429 ("ordfeminine", '\u{AA}'),
430 ("guillemotleft", '\u{AB}'),
431 ("logicalnot", '\u{AC}'),
432 ("registered", '\u{AE}'),
433 ("macron", '\u{AF}'),
434 ("degree", '\u{B0}'),
435 ("plusminus", '\u{B1}'),
436 ("twosuperior", '\u{B2}'),
437 ("threesuperior", '\u{B3}'),
438 ("acute", '\u{B4}'),
439 ("mu", '\u{B5}'),
440 ("paragraph", '\u{B6}'),
441 ("periodcentered", '\u{B7}'),
442 ("cedilla", '\u{B8}'),
443 ("onesuperior", '\u{B9}'),
444 ("ordmasculine", '\u{BA}'),
445 ("guillemotright", '\u{BB}'),
446 ("onequarter", '\u{BC}'),
447 ("onehalf", '\u{BD}'),
448 ("threequarters", '\u{BE}'),
449 ("questiondown", '\u{BF}'),
450 ("Agrave", '\u{C0}'),
451 ("Aacute", '\u{C1}'),
452 ("Acircumflex", '\u{C2}'),
453 ("Atilde", '\u{C3}'),
454 ("Adieresis", '\u{C4}'),
455 ("Aring", '\u{C5}'),
456 ("AE", '\u{C6}'),
457 ("Ccedilla", '\u{C7}'),
458 ("Egrave", '\u{C8}'),
459 ("Eacute", '\u{C9}'),
460 ("Ecircumflex", '\u{CA}'),
461 ("Edieresis", '\u{CB}'),
462 ("Igrave", '\u{CC}'),
463 ("Iacute", '\u{CD}'),
464 ("Icircumflex", '\u{CE}'),
465 ("Idieresis", '\u{CF}'),
466 ("Eth", '\u{D0}'),
467 ("Ntilde", '\u{D1}'),
468 ("Ograve", '\u{D2}'),
469 ("Oacute", '\u{D3}'),
470 ("Ocircumflex", '\u{D4}'),
471 ("Otilde", '\u{D5}'),
472 ("Odieresis", '\u{D6}'),
473 ("multiply", '\u{D7}'),
474 ("Oslash", '\u{D8}'),
475 ("Ugrave", '\u{D9}'),
476 ("Uacute", '\u{DA}'),
477 ("Ucircumflex", '\u{DB}'),
478 ("Udieresis", '\u{DC}'),
479 ("Yacute", '\u{DD}'),
480 ("Thorn", '\u{DE}'),
481 ("germandbls", '\u{DF}'),
482 ("agrave", '\u{E0}'),
483 ("aacute", '\u{E1}'),
484 ("acircumflex", '\u{E2}'),
485 ("atilde", '\u{E3}'),
486 ("adieresis", '\u{E4}'),
487 ("aring", '\u{E5}'),
488 ("ae", '\u{E6}'),
489 ("ccedilla", '\u{E7}'),
490 ("egrave", '\u{E8}'),
491 ("eacute", '\u{E9}'),
492 ("ecircumflex", '\u{EA}'),
493 ("edieresis", '\u{EB}'),
494 ("igrave", '\u{EC}'),
495 ("iacute", '\u{ED}'),
496 ("icircumflex", '\u{EE}'),
497 ("idieresis", '\u{EF}'),
498 ("eth", '\u{F0}'),
499 ("ntilde", '\u{F1}'),
500 ("ograve", '\u{F2}'),
501 ("oacute", '\u{F3}'),
502 ("ocircumflex", '\u{F4}'),
503 ("otilde", '\u{F5}'),
504 ("odieresis", '\u{F6}'),
505 ("divide", '\u{F7}'),
506 ("oslash", '\u{F8}'),
507 ("ugrave", '\u{F9}'),
508 ("uacute", '\u{FA}'),
509 ("ucircumflex", '\u{FB}'),
510 ("udieresis", '\u{FC}'),
511 ("yacute", '\u{FD}'),
512 ("thorn", '\u{FE}'),
513 ("ydieresis", '\u{FF}'),
514];
515
516const GLYPHS_PUNCT: &[(&str, char)] = &[
518 ("quoteleft", '\u{2018}'),
519 ("quoteright", '\u{2019}'),
520 ("quotesinglbase", '\u{201A}'),
521 ("quotedblleft", '\u{201C}'),
522 ("quotedblright", '\u{201D}'),
523 ("quotedblbase", '\u{201E}'),
524 ("endash", '\u{2013}'),
525 ("emdash", '\u{2014}'),
526 ("bullet", '\u{2022}'),
527 ("ellipsis", '\u{2026}'),
528 ("dagger", '\u{2020}'),
529 ("daggerdbl", '\u{2021}'),
530 ("perthousand", '\u{2030}'),
531 ("guilsinglleft", '\u{2039}'),
532 ("guilsinglright", '\u{203A}'),
533 ("fraction", '\u{2044}'),
534 ("minus", '\u{2212}'),
535 ("florin", '\u{192}'),
536 ("Euro", '\u{20AC}'),
537 ("trademark", '\u{2122}'),
538 ("fi", '\u{FB01}'),
539 ("fl", '\u{FB02}'),
540 ("ff", '\u{FB00}'),
541 ("ffi", '\u{FB03}'),
542 ("ffl", '\u{FB04}'),
543 ("circumflex", '\u{2C6}'),
544 ("caron", '\u{2C7}'),
545 ("breve", '\u{2D8}'),
546 ("dotaccent", '\u{2D9}'),
547 ("ring", '\u{2DA}'),
548 ("ogonek", '\u{2DB}'),
549 ("tilde", '\u{2DC}'),
550 ("hungarumlaut", '\u{2DD}'),
551 ("OE", '\u{152}'),
552 ("oe", '\u{153}'),
553 ("Scaron", '\u{160}'),
554 ("scaron", '\u{161}'),
555 ("Zcaron", '\u{17D}'),
556 ("zcaron", '\u{17E}'),
557 ("Ydieresis", '\u{178}'),
558 ("Lslash", '\u{141}'),
559 ("lslash", '\u{142}'),
560 ("dotlessi", '\u{131}'),
561 ("nbspace", '\u{A0}'),
562 ("sfthyphen", '\u{AD}'),
563];
564
565const GLYPHS_GREEK: &[(&str, char)] = &[
568 ("Alpha", '\u{391}'),
569 ("Beta", '\u{392}'),
570 ("Gamma", '\u{393}'),
571 ("Delta", '\u{2206}'),
572 ("Epsilon", '\u{395}'),
573 ("Zeta", '\u{396}'),
574 ("Eta", '\u{397}'),
575 ("Theta", '\u{398}'),
576 ("Iota", '\u{399}'),
577 ("Kappa", '\u{39A}'),
578 ("Lambda", '\u{39B}'),
579 ("Mu", '\u{39C}'),
580 ("Nu", '\u{39D}'),
581 ("Xi", '\u{39E}'),
582 ("Omicron", '\u{39F}'),
583 ("Pi", '\u{3A0}'),
584 ("Rho", '\u{3A1}'),
585 ("Sigma", '\u{3A3}'),
586 ("Tau", '\u{3A4}'),
587 ("Upsilon", '\u{3A5}'),
588 ("Phi", '\u{3A6}'),
589 ("Chi", '\u{3A7}'),
590 ("Psi", '\u{3A8}'),
591 ("Omega", '\u{2126}'),
592 ("alpha", '\u{3B1}'),
593 ("beta", '\u{3B2}'),
594 ("gamma", '\u{3B3}'),
595 ("delta", '\u{3B4}'),
596 ("epsilon", '\u{3B5}'),
597 ("zeta", '\u{3B6}'),
598 ("eta", '\u{3B7}'),
599 ("theta", '\u{3B8}'),
600 ("iota", '\u{3B9}'),
601 ("kappa", '\u{3BA}'),
602 ("lambda", '\u{3BB}'),
603 ("nu", '\u{3BD}'),
604 ("xi", '\u{3BE}'),
605 ("omicron", '\u{3BF}'),
606 ("pi", '\u{3C0}'),
607 ("rho", '\u{3C1}'),
608 ("sigma", '\u{3C3}'),
609 ("sigma1", '\u{3C2}'),
610 ("tau", '\u{3C4}'),
611 ("upsilon", '\u{3C5}'),
612 ("phi", '\u{3C6}'),
613 ("chi", '\u{3C7}'),
614 ("psi", '\u{3C8}'),
615 ("omega", '\u{3C9}'),
616];
617
618const GLYPHS_MISC: &[(&str, char)] = &[
620 ("infinity", '\u{221E}'),
621 ("notequal", '\u{2260}'),
622 ("lessequal", '\u{2264}'),
623 ("greaterequal", '\u{2265}'),
624 ("partialdiff", '\u{2202}'),
625 ("summation", '\u{2211}'),
626 ("product", '\u{220F}'),
627 ("integral", '\u{222B}'),
628 ("radical", '\u{221A}'),
629 ("approxequal", '\u{2248}'),
630 ("equivalence", '\u{2261}'),
631 ("element", '\u{2208}'),
632 ("intersection", '\u{2229}'),
633 ("union", '\u{222A}'),
634 ("arrowleft", '\u{2190}'),
635 ("arrowup", '\u{2191}'),
636 ("arrowright", '\u{2192}'),
637 ("arrowdown", '\u{2193}'),
638 ("arrowboth", '\u{2194}'),
639 ("lozenge", '\u{25CA}'),
640 ("apple", '\u{F8FF}'),
641];
642
643#[cfg(test)]
644mod tests {
645 use super::*;
646
647 #[test]
648 fn win_ansi_spot_checks() {
649 assert_eq!(win_ansi(b'A'), Some('A'));
650 assert_eq!(win_ansi(0x93), Some('\u{201C}')); assert_eq!(win_ansi(0x80), Some('\u{20AC}')); assert_eq!(win_ansi(0xE9), Some('\u{E9}')); assert_eq!(win_ansi(0x81), None); assert_eq!(win_ansi(0x0A), None); }
656
657 #[test]
658 fn mac_roman_spot_checks() {
659 assert_eq!(mac_roman(b'A'), Some('A'));
660 assert_eq!(mac_roman(0xD0), Some('\u{2013}')); assert_eq!(mac_roman(0x80), Some('\u{C4}')); assert_eq!(mac_roman(0xA5), Some('\u{2022}')); assert_eq!(mac_roman(0xFF), Some('\u{2C7}')); assert_eq!(mac_roman(0x00), None);
665 }
666
667 #[test]
668 fn standard_spot_checks() {
669 assert_eq!(standard(b'A'), Some('A'));
670 assert_eq!(standard(0xA9), Some('\u{27}')); assert_eq!(standard(0x27), Some('\u{2019}')); assert_eq!(standard(0x60), Some('\u{2018}')); assert_eq!(standard(0xD0), Some('\u{2014}')); assert_eq!(standard(0x7F), None);
675 assert_eq!(standard(0xA0), None); }
677
678 #[test]
679 fn glyph_names_hex_forms() {
680 assert_eq!(glyph_to_unicode("uni03B1"), Some('\u{3B1}'));
681 assert_eq!(glyph_to_unicode("uni20AC"), Some('\u{20AC}'));
682 assert_eq!(glyph_to_unicode("u1F600"), Some('\u{1F600}'));
683 assert_eq!(glyph_to_unicode("u00E9"), Some('\u{E9}'));
684 assert_eq!(glyph_to_unicode("uniD800"), None); assert_eq!(glyph_to_unicode("uniXYZW"), None);
686 }
687
688 #[test]
697 fn standard_encoding_name_matches_standard_table() {
698 for code in 0u16..=255 {
699 let code = code as u8;
700 assert_eq!(
701 standard_encoding_name(code).is_some(),
702 standard(code).is_some(),
703 "code {code:#04x}: standard_encoding_name/standard domain mismatch"
704 );
705 if let (Some(name), Some(expected)) = (standard_encoding_name(code), standard(code)) {
706 if let Some(resolved) = glyph_to_unicode(name) {
707 assert_eq!(
708 resolved, expected,
709 "code {code:#04x} name {name:?}: glyph_to_unicode disagrees with standard"
710 );
711 }
712 }
713 }
714 }
715
716 #[test]
717 fn standard_encoding_name_spot_checks() {
718 assert_eq!(standard_encoding_name(b'A'), Some("A"));
719 assert_eq!(standard_encoding_name(0x27), Some("quoteright"));
720 assert_eq!(standard_encoding_name(0x60), Some("quoteleft"));
721 assert_eq!(standard_encoding_name(0xA1), Some("exclamdown"));
722 assert_eq!(standard_encoding_name(0xA4), Some("fraction"));
723 assert_eq!(standard_encoding_name(0xA6), Some("florin"));
724 assert_eq!(standard_encoding_name(0xC1), Some("grave"));
725 assert_eq!(standard_encoding_name(0xC6), Some("breve"));
726 assert_eq!(standard_encoding_name(0xE1), Some("AE"));
727 assert_eq!(standard_encoding_name(0xF1), Some("ae"));
728 assert_eq!(standard_encoding_name(0xFB), Some("germandbls"));
729 assert_eq!(standard_encoding_name(0x7F), None);
730 assert_eq!(standard_encoding_name(0xA0), None);
731 }
732
733 #[test]
734 fn glyph_names_letters_and_tables() {
735 assert_eq!(glyph_to_unicode("A"), Some('A'));
736 assert_eq!(glyph_to_unicode("z"), Some('z'));
737 assert_eq!(glyph_to_unicode("alpha"), Some('\u{3B1}'));
738 assert_eq!(glyph_to_unicode("eacute"), Some('\u{E9}'));
739 assert_eq!(glyph_to_unicode("quotedblleft"), Some('\u{201C}'));
740 assert_eq!(glyph_to_unicode("seven"), Some('7'));
741 assert_eq!(glyph_to_unicode("union"), Some('\u{222A}'));
742 assert_eq!(glyph_to_unicode("nosuchglyphname"), None);
743 }
744}