Skip to main content

pdfboss_encoding/
afm.rs

1//! Standard-14 advance-width tables, from the public Adobe Core-14
2//! AFM metrics (see ISO 32000-1 Annex D / Adobe's PDF Reference for the
3//! standard-14 font names). Widths are in the 1000-unit glyph space
4//! used throughout PDF (ISO 32000-1 9.2.4), i.e. thousandths of the
5//! font's em square; multiply by `font_size / 1000` for text space.
6//!
7//! These tables back [`standard_14_width`], used as a fallback advance
8//! when a PDF's `/Widths` array is absent or incomplete and the font
9//! program itself isn't embedded (font substitution).
10
11/// Strips a PDF font-subset tag (`ISO 32000-1` 9.6.4: six uppercase
12/// letters followed by `+`, e.g. `ABCDEF+Times-Bold`) from `base_font`.
13fn strip_subset_prefix(base_font: &str) -> &str {
14    let bytes = base_font.as_bytes();
15    // `> 7`, not `> 6`: the guard must require at least one character after
16    // the `+` for the strip to be meaningful, so the degenerate
17    // `"ABCDEF+"` (len 7) is left unstripped instead of yielding an empty
18    // name. Matches `substitute.rs`'s `strip_subset_prefix` guard exactly.
19    if bytes.len() > 7 && bytes[6] == b'+' && bytes[..6].iter().all(u8::is_ascii_uppercase) {
20        &base_font[7..]
21    } else {
22        base_font
23    }
24}
25
26/// A standard-14 font family (weight/slant resolved separately).
27#[derive(Clone, Copy, PartialEq, Eq, Debug)]
28enum Family {
29    Helvetica,
30    Times,
31    Courier,
32}
33
34/// Recognized family stems, longest first. Ordering matters: a shorter
35/// stem that is itself a prefix of a longer one (`times` vs.
36/// `timesnewroman` vs. `timesnewromanps`, `courier` vs. `couriernew`)
37/// must never shadow the more specific match, or the leftover
38/// remainder handed to [`strip_style_tokens`] would contain stem
39/// characters instead of style/noise ones. `classify` walks this list
40/// in order and takes the first hit.
41const FAMILY_STEMS: &[(&str, Family)] = &[
42    ("timesnewromanps", Family::Times),
43    ("timesnewroman", Family::Times),
44    ("couriernew", Family::Courier),
45    ("helvetica", Family::Helvetica),
46    ("courier", Family::Courier),
47    ("arial", Family::Helvetica),
48    ("times", Family::Times),
49];
50
51/// Style/noise tokens recognized after the family stem, longest first
52/// (so, e.g., `psmt` is tried whole rather than stopping at `ps`).
53/// `mt`/`ps`/`psmt` are TrueType-alias noise suffixes (`Arial-BoldMT`,
54/// `TimesNewRomanPSMT`). Anything left over after greedily stripping
55/// these tokens means the name carries a real, metrically distinct
56/// qualifier (`Narrow`, `Neue`, `Condensed`, `Light`, `Ten`, ...) and
57/// so isn't one of the standard 14.
58const STYLE_TOKENS: &[&str] = &[
59    "oblique", "regular", "italic", "roman", "bold", "book", "psmt", "ps", "mt",
60];
61
62/// Greedily strips [`STYLE_TOKENS`] from the front of `rest`, folding
63/// them into `(bold, italic)` flags, until `rest` is fully consumed.
64/// Returns `None` the moment a prefix token isn't recognized, i.e. the
65/// name has a qualifier this module doesn't tabulate.
66fn strip_style_tokens(mut rest: &str) -> Option<(bool, bool)> {
67    let mut bold = false;
68    let mut italic = false;
69    while !rest.is_empty() {
70        let tok = *STYLE_TOKENS.iter().find(|&&t| rest.starts_with(t))?;
71        match tok {
72            "bold" => bold = true,
73            "italic" | "oblique" => italic = true,
74            _ => {}
75        }
76        rest = &rest[tok.len()..];
77    }
78    Some((bold, italic))
79}
80
81/// Classifies a (subset-prefix-stripped) `/BaseFont` name into a
82/// standard-14 family plus bold/italic flags. The name is lowercased
83/// and separator-stripped (`-`, `,`, space) before matching, so
84/// `Arial-BoldMT`, `arial-bold`, and `Arial,Bold` all resolve alike.
85/// The (separator-stripped) name must then start with one of the
86/// [`FAMILY_STEMS`] (recognizing the common PostScript and TrueType
87/// aliases: `Arial` -> Helvetica, `TimesNewRoman`/`TimesNewRomanPS` ->
88/// Times, `CourierNew` -> Courier), and everything after the stem must
89/// fully reduce to [`STYLE_TOKENS`] noise.
90///
91/// This is deliberately strict: a font that merely shares a standard-14
92/// prefix but is metrically distinct — `Helvetica-Narrow`, `Helvetica
93/// Neue`, `HelveticaNeue-Bold`, `TimesTen-Bold`, `Helvetica-Light`,
94/// `Times New Roman Condensed` — leaves an unrecognized token after the
95/// stem and so classifies as `None`, same as Symbol, ZapfDingbats, or
96/// any other name that isn't one of the standard 14. Returning `None`
97/// here is correct even though it's plausible-looking: the caller then
98/// falls back to the substitute face's own `hmtx` widths rather than a
99/// wrong Core-14 advance.
100fn classify(base_font: &str) -> Option<(Family, bool, bool)> {
101    let stripped = strip_subset_prefix(base_font);
102    let lower = stripped.to_lowercase();
103    let compact: String = lower
104        .chars()
105        .filter(|c| !matches!(c, '-' | ',' | ' '))
106        .collect();
107    let (family, rest) = FAMILY_STEMS
108        .iter()
109        .find_map(|&(stem, family)| compact.strip_prefix(stem).map(|rest| (family, rest)))?;
110    let (bold, italic) = strip_style_tokens(rest)?;
111    Some((family, bold, italic))
112}
113
114/// Binary-searches a `(glyph_name, width)` table sorted by name.
115fn lookup(table: &[(&str, u16)], glyph_name: &str) -> Option<f32> {
116    table
117        .binary_search_by_key(&glyph_name, |&(name, _)| name)
118        .ok()
119        .map(|i| table[i].1 as f32)
120}
121
122/// The advance width (1000-unit glyph space) of `glyph_name` in the
123/// standard-14 font whose PDF `/BaseFont` (or a recognized alias, or a
124/// subsetted variant) is `base_font`, or `None` if `base_font` isn't one
125/// of the standard 14 (including Symbol/ZapfDingbats, which this module
126/// doesn't tabulate) or `glyph_name` is unknown to that font. Courier's
127/// four variants are monospaced (every glyph is 600 units wide per the
128/// Adobe Core-14 AFM metrics) and so always return `Some(600.0)`.
129/// Oblique variants share their upright counterpart's widths (Helvetica
130/// and Helvetica-Oblique are metrically identical, likewise the bold
131/// pair), so only upright/bold tables are stored.
132pub fn standard_14_width(base_font: &str, glyph_name: &str) -> Option<f32> {
133    let (family, bold, italic) = classify(base_font)?;
134    match family {
135        Family::Courier => Some(600.0),
136        Family::Helvetica => {
137            let table = if bold { HELVETICA_BOLD } else { HELVETICA };
138            lookup(table, glyph_name)
139        }
140        Family::Times => {
141            let table = match (bold, italic) {
142                (true, true) => TIMES_BOLD_ITALIC,
143                (true, false) => TIMES_BOLD,
144                (false, true) => TIMES_ITALIC,
145                (false, false) => TIMES_ROMAN,
146            };
147            lookup(table, glyph_name)
148        }
149    }
150}
151
152/// Whether `base_font` (after subset-prefix stripping and alias
153/// normalization) names one of the standard 14 fonts.
154pub fn is_standard_14(base_font: &str) -> bool {
155    classify(base_font).is_some()
156}
157
158/// `Helvetica` glyph widths, sorted by
159/// glyph name for binary search (Adobe Core-14 AFM metrics).
160#[rustfmt::skip]
161const HELVETICA: &[(&str, u16)] = &[
162    ("A", 667),
163    ("AE", 1000),
164    ("Aacute", 667),
165    ("Acircumflex", 667),
166    ("Adieresis", 667),
167    ("Agrave", 667),
168    ("Aring", 667),
169    ("Atilde", 667),
170    ("B", 667),
171    ("C", 722),
172    ("Ccedilla", 722),
173    ("D", 722),
174    ("E", 667),
175    ("Eacute", 667),
176    ("Ecircumflex", 667),
177    ("Edieresis", 667),
178    ("Egrave", 667),
179    ("Eth", 722),
180    ("F", 611),
181    ("G", 778),
182    ("H", 722),
183    ("I", 278),
184    ("Iacute", 278),
185    ("Icircumflex", 278),
186    ("Idieresis", 278),
187    ("Igrave", 278),
188    ("J", 500),
189    ("K", 667),
190    ("L", 556),
191    ("Lslash", 556),
192    ("M", 833),
193    ("N", 722),
194    ("Ntilde", 722),
195    ("O", 778),
196    ("OE", 1000),
197    ("Oacute", 778),
198    ("Ocircumflex", 778),
199    ("Odieresis", 778),
200    ("Ograve", 778),
201    ("Oslash", 778),
202    ("Otilde", 778),
203    ("P", 667),
204    ("Q", 778),
205    ("R", 722),
206    ("S", 667),
207    ("Scaron", 667),
208    ("T", 611),
209    ("Thorn", 667),
210    ("U", 722),
211    ("Uacute", 722),
212    ("Ucircumflex", 722),
213    ("Udieresis", 722),
214    ("Ugrave", 722),
215    ("V", 667),
216    ("W", 944),
217    ("X", 667),
218    ("Y", 667),
219    ("Yacute", 667),
220    ("Ydieresis", 667),
221    ("Z", 611),
222    ("Zcaron", 611),
223    ("a", 556),
224    ("aacute", 556),
225    ("acircumflex", 556),
226    ("acute", 333),
227    ("adieresis", 556),
228    ("ae", 889),
229    ("agrave", 556),
230    ("ampersand", 667),
231    ("aring", 556),
232    ("asciicircum", 469),
233    ("asciitilde", 584),
234    ("asterisk", 389),
235    ("at", 1015),
236    ("atilde", 556),
237    ("b", 556),
238    ("backslash", 278),
239    ("bar", 260),
240    ("braceleft", 334),
241    ("braceright", 334),
242    ("bracketleft", 278),
243    ("bracketright", 278),
244    ("breve", 333),
245    ("brokenbar", 260),
246    ("bullet", 350),
247    ("c", 500),
248    ("caron", 333),
249    ("ccedilla", 500),
250    ("cedilla", 333),
251    ("cent", 556),
252    ("circumflex", 333),
253    ("colon", 278),
254    ("comma", 278),
255    ("copyright", 737),
256    ("currency", 556),
257    ("d", 556),
258    ("dagger", 556),
259    ("daggerdbl", 556),
260    ("degree", 400),
261    ("dieresis", 333),
262    ("divide", 584),
263    ("dollar", 556),
264    ("dotaccent", 333),
265    ("dotlessi", 278),
266    ("e", 556),
267    ("eacute", 556),
268    ("ecircumflex", 556),
269    ("edieresis", 556),
270    ("egrave", 556),
271    ("eight", 556),
272    ("ellipsis", 1000),
273    ("emdash", 1000),
274    ("endash", 556),
275    ("equal", 584),
276    ("eth", 556),
277    ("exclam", 278),
278    ("exclamdown", 333),
279    ("f", 278),
280    ("fi", 500),
281    ("five", 556),
282    ("fl", 500),
283    ("florin", 556),
284    ("four", 556),
285    ("fraction", 167),
286    ("g", 556),
287    ("germandbls", 611),
288    ("grave", 333),
289    ("greater", 584),
290    ("guillemotleft", 556),
291    ("guillemotright", 556),
292    ("guilsinglleft", 333),
293    ("guilsinglright", 333),
294    ("h", 556),
295    ("hungarumlaut", 333),
296    ("hyphen", 333),
297    ("i", 222),
298    ("iacute", 278),
299    ("icircumflex", 278),
300    ("idieresis", 278),
301    ("igrave", 278),
302    ("j", 222),
303    ("k", 500),
304    ("l", 222),
305    ("less", 584),
306    ("logicalnot", 584),
307    ("lslash", 222),
308    ("m", 833),
309    ("macron", 333),
310    ("minus", 584),
311    ("mu", 556),
312    ("multiply", 584),
313    ("n", 556),
314    ("nine", 556),
315    ("ntilde", 556),
316    ("numbersign", 556),
317    ("o", 556),
318    ("oacute", 556),
319    ("ocircumflex", 556),
320    ("odieresis", 556),
321    ("oe", 944),
322    ("ogonek", 333),
323    ("ograve", 556),
324    ("one", 556),
325    ("onehalf", 834),
326    ("onequarter", 834),
327    ("onesuperior", 333),
328    ("ordfeminine", 370),
329    ("ordmasculine", 365),
330    ("oslash", 611),
331    ("otilde", 556),
332    ("p", 556),
333    ("paragraph", 537),
334    ("parenleft", 333),
335    ("parenright", 333),
336    ("percent", 889),
337    ("period", 278),
338    ("periodcentered", 278),
339    ("perthousand", 1000),
340    ("plus", 584),
341    ("plusminus", 584),
342    ("q", 556),
343    ("question", 556),
344    ("questiondown", 611),
345    ("quotedbl", 355),
346    ("quotedblbase", 333),
347    ("quotedblleft", 333),
348    ("quotedblright", 333),
349    ("quoteleft", 222),
350    ("quoteright", 222),
351    ("quotesinglbase", 222),
352    ("quotesingle", 191),
353    ("r", 333),
354    ("registered", 737),
355    ("ring", 333),
356    ("s", 500),
357    ("scaron", 500),
358    ("section", 556),
359    ("semicolon", 278),
360    ("seven", 556),
361    ("six", 556),
362    ("slash", 278),
363    ("space", 278),
364    ("sterling", 556),
365    ("t", 278),
366    ("thorn", 556),
367    ("three", 556),
368    ("threequarters", 834),
369    ("threesuperior", 333),
370    ("tilde", 333),
371    ("trademark", 1000),
372    ("two", 556),
373    ("twosuperior", 333),
374    ("u", 556),
375    ("uacute", 556),
376    ("ucircumflex", 556),
377    ("udieresis", 556),
378    ("ugrave", 556),
379    ("underscore", 556),
380    ("v", 500),
381    ("w", 722),
382    ("x", 500),
383    ("y", 500),
384    ("yacute", 500),
385    ("ydieresis", 500),
386    ("yen", 556),
387    ("z", 500),
388    ("zcaron", 500),
389    ("zero", 556),
390];
391
392/// `Helvetica Bold` glyph widths, sorted by
393/// glyph name for binary search (Adobe Core-14 AFM metrics).
394#[rustfmt::skip]
395const HELVETICA_BOLD: &[(&str, u16)] = &[
396    ("A", 722),
397    ("AE", 1000),
398    ("Aacute", 722),
399    ("Acircumflex", 722),
400    ("Adieresis", 722),
401    ("Agrave", 722),
402    ("Aring", 722),
403    ("Atilde", 722),
404    ("B", 722),
405    ("C", 722),
406    ("Ccedilla", 722),
407    ("D", 722),
408    ("E", 667),
409    ("Eacute", 667),
410    ("Ecircumflex", 667),
411    ("Edieresis", 667),
412    ("Egrave", 667),
413    ("Eth", 722),
414    ("F", 611),
415    ("G", 778),
416    ("H", 722),
417    ("I", 278),
418    ("Iacute", 278),
419    ("Icircumflex", 278),
420    ("Idieresis", 278),
421    ("Igrave", 278),
422    ("J", 556),
423    ("K", 722),
424    ("L", 611),
425    ("Lslash", 611),
426    ("M", 833),
427    ("N", 722),
428    ("Ntilde", 722),
429    ("O", 778),
430    ("OE", 1000),
431    ("Oacute", 778),
432    ("Ocircumflex", 778),
433    ("Odieresis", 778),
434    ("Ograve", 778),
435    ("Oslash", 778),
436    ("Otilde", 778),
437    ("P", 667),
438    ("Q", 778),
439    ("R", 722),
440    ("S", 667),
441    ("Scaron", 667),
442    ("T", 611),
443    ("Thorn", 667),
444    ("U", 722),
445    ("Uacute", 722),
446    ("Ucircumflex", 722),
447    ("Udieresis", 722),
448    ("Ugrave", 722),
449    ("V", 667),
450    ("W", 944),
451    ("X", 667),
452    ("Y", 667),
453    ("Yacute", 667),
454    ("Ydieresis", 667),
455    ("Z", 611),
456    ("Zcaron", 611),
457    ("a", 556),
458    ("aacute", 556),
459    ("acircumflex", 556),
460    ("acute", 333),
461    ("adieresis", 556),
462    ("ae", 889),
463    ("agrave", 556),
464    ("ampersand", 722),
465    ("aring", 556),
466    ("asciicircum", 584),
467    ("asciitilde", 584),
468    ("asterisk", 389),
469    ("at", 975),
470    ("atilde", 556),
471    ("b", 611),
472    ("backslash", 278),
473    ("bar", 280),
474    ("braceleft", 389),
475    ("braceright", 389),
476    ("bracketleft", 333),
477    ("bracketright", 333),
478    ("breve", 333),
479    ("brokenbar", 280),
480    ("bullet", 350),
481    ("c", 556),
482    ("caron", 333),
483    ("ccedilla", 556),
484    ("cedilla", 333),
485    ("cent", 556),
486    ("circumflex", 333),
487    ("colon", 333),
488    ("comma", 278),
489    ("copyright", 737),
490    ("currency", 556),
491    ("d", 611),
492    ("dagger", 556),
493    ("daggerdbl", 556),
494    ("degree", 400),
495    ("dieresis", 333),
496    ("divide", 584),
497    ("dollar", 556),
498    ("dotaccent", 333),
499    ("dotlessi", 278),
500    ("e", 556),
501    ("eacute", 556),
502    ("ecircumflex", 556),
503    ("edieresis", 556),
504    ("egrave", 556),
505    ("eight", 556),
506    ("ellipsis", 1000),
507    ("emdash", 1000),
508    ("endash", 556),
509    ("equal", 584),
510    ("eth", 611),
511    ("exclam", 333),
512    ("exclamdown", 333),
513    ("f", 333),
514    ("fi", 611),
515    ("five", 556),
516    ("fl", 611),
517    ("florin", 556),
518    ("four", 556),
519    ("fraction", 167),
520    ("g", 611),
521    ("germandbls", 611),
522    ("grave", 333),
523    ("greater", 584),
524    ("guillemotleft", 556),
525    ("guillemotright", 556),
526    ("guilsinglleft", 333),
527    ("guilsinglright", 333),
528    ("h", 611),
529    ("hungarumlaut", 333),
530    ("hyphen", 333),
531    ("i", 278),
532    ("iacute", 278),
533    ("icircumflex", 278),
534    ("idieresis", 278),
535    ("igrave", 278),
536    ("j", 278),
537    ("k", 556),
538    ("l", 278),
539    ("less", 584),
540    ("logicalnot", 584),
541    ("lslash", 278),
542    ("m", 889),
543    ("macron", 333),
544    ("minus", 584),
545    ("mu", 611),
546    ("multiply", 584),
547    ("n", 611),
548    ("nine", 556),
549    ("ntilde", 611),
550    ("numbersign", 556),
551    ("o", 611),
552    ("oacute", 611),
553    ("ocircumflex", 611),
554    ("odieresis", 611),
555    ("oe", 944),
556    ("ogonek", 333),
557    ("ograve", 611),
558    ("one", 556),
559    ("onehalf", 834),
560    ("onequarter", 834),
561    ("onesuperior", 333),
562    ("ordfeminine", 370),
563    ("ordmasculine", 365),
564    ("oslash", 611),
565    ("otilde", 611),
566    ("p", 611),
567    ("paragraph", 556),
568    ("parenleft", 333),
569    ("parenright", 333),
570    ("percent", 889),
571    ("period", 278),
572    ("periodcentered", 278),
573    ("perthousand", 1000),
574    ("plus", 584),
575    ("plusminus", 584),
576    ("q", 611),
577    ("question", 611),
578    ("questiondown", 611),
579    ("quotedbl", 474),
580    ("quotedblbase", 500),
581    ("quotedblleft", 500),
582    ("quotedblright", 500),
583    ("quoteleft", 278),
584    ("quoteright", 278),
585    ("quotesinglbase", 278),
586    ("quotesingle", 238),
587    ("r", 389),
588    ("registered", 737),
589    ("ring", 333),
590    ("s", 556),
591    ("scaron", 556),
592    ("section", 556),
593    ("semicolon", 333),
594    ("seven", 556),
595    ("six", 556),
596    ("slash", 278),
597    ("space", 278),
598    ("sterling", 556),
599    ("t", 333),
600    ("thorn", 611),
601    ("three", 556),
602    ("threequarters", 834),
603    ("threesuperior", 333),
604    ("tilde", 333),
605    ("trademark", 1000),
606    ("two", 556),
607    ("twosuperior", 333),
608    ("u", 611),
609    ("uacute", 611),
610    ("ucircumflex", 611),
611    ("udieresis", 611),
612    ("ugrave", 611),
613    ("underscore", 556),
614    ("v", 556),
615    ("w", 778),
616    ("x", 556),
617    ("y", 556),
618    ("yacute", 556),
619    ("ydieresis", 556),
620    ("yen", 556),
621    ("z", 500),
622    ("zcaron", 500),
623    ("zero", 556),
624];
625
626/// `Times Roman` glyph widths, sorted by
627/// glyph name for binary search (Adobe Core-14 AFM metrics).
628#[rustfmt::skip]
629const TIMES_ROMAN: &[(&str, u16)] = &[
630    ("A", 722),
631    ("AE", 889),
632    ("Aacute", 722),
633    ("Acircumflex", 722),
634    ("Adieresis", 722),
635    ("Agrave", 722),
636    ("Aring", 722),
637    ("Atilde", 722),
638    ("B", 667),
639    ("C", 667),
640    ("Ccedilla", 667),
641    ("D", 722),
642    ("E", 611),
643    ("Eacute", 611),
644    ("Ecircumflex", 611),
645    ("Edieresis", 611),
646    ("Egrave", 611),
647    ("Eth", 722),
648    ("F", 556),
649    ("G", 722),
650    ("H", 722),
651    ("I", 333),
652    ("Iacute", 333),
653    ("Icircumflex", 333),
654    ("Idieresis", 333),
655    ("Igrave", 333),
656    ("J", 389),
657    ("K", 722),
658    ("L", 611),
659    ("Lslash", 611),
660    ("M", 889),
661    ("N", 722),
662    ("Ntilde", 722),
663    ("O", 722),
664    ("OE", 889),
665    ("Oacute", 722),
666    ("Ocircumflex", 722),
667    ("Odieresis", 722),
668    ("Ograve", 722),
669    ("Oslash", 722),
670    ("Otilde", 722),
671    ("P", 556),
672    ("Q", 722),
673    ("R", 667),
674    ("S", 556),
675    ("Scaron", 556),
676    ("T", 611),
677    ("Thorn", 556),
678    ("U", 722),
679    ("Uacute", 722),
680    ("Ucircumflex", 722),
681    ("Udieresis", 722),
682    ("Ugrave", 722),
683    ("V", 722),
684    ("W", 944),
685    ("X", 722),
686    ("Y", 722),
687    ("Yacute", 722),
688    ("Ydieresis", 722),
689    ("Z", 611),
690    ("Zcaron", 611),
691    ("a", 444),
692    ("aacute", 444),
693    ("acircumflex", 444),
694    ("acute", 333),
695    ("adieresis", 444),
696    ("ae", 667),
697    ("agrave", 444),
698    ("ampersand", 778),
699    ("aring", 444),
700    ("asciicircum", 469),
701    ("asciitilde", 541),
702    ("asterisk", 500),
703    ("at", 921),
704    ("atilde", 444),
705    ("b", 500),
706    ("backslash", 278),
707    ("bar", 200),
708    ("braceleft", 480),
709    ("braceright", 480),
710    ("bracketleft", 333),
711    ("bracketright", 333),
712    ("breve", 333),
713    ("brokenbar", 200),
714    ("bullet", 350),
715    ("c", 444),
716    ("caron", 333),
717    ("ccedilla", 444),
718    ("cedilla", 333),
719    ("cent", 500),
720    ("circumflex", 333),
721    ("colon", 278),
722    ("comma", 250),
723    ("copyright", 760),
724    ("currency", 500),
725    ("d", 500),
726    ("dagger", 500),
727    ("daggerdbl", 500),
728    ("degree", 400),
729    ("dieresis", 333),
730    ("divide", 564),
731    ("dollar", 500),
732    ("dotaccent", 333),
733    ("dotlessi", 278),
734    ("e", 444),
735    ("eacute", 444),
736    ("ecircumflex", 444),
737    ("edieresis", 444),
738    ("egrave", 444),
739    ("eight", 500),
740    ("ellipsis", 1000),
741    ("emdash", 1000),
742    ("endash", 500),
743    ("equal", 564),
744    ("eth", 500),
745    ("exclam", 333),
746    ("exclamdown", 333),
747    ("f", 333),
748    ("fi", 556),
749    ("five", 500),
750    ("fl", 556),
751    ("florin", 500),
752    ("four", 500),
753    ("fraction", 167),
754    ("g", 500),
755    ("germandbls", 500),
756    ("grave", 333),
757    ("greater", 564),
758    ("guillemotleft", 500),
759    ("guillemotright", 500),
760    ("guilsinglleft", 333),
761    ("guilsinglright", 333),
762    ("h", 500),
763    ("hungarumlaut", 333),
764    ("hyphen", 333),
765    ("i", 278),
766    ("iacute", 278),
767    ("icircumflex", 278),
768    ("idieresis", 278),
769    ("igrave", 278),
770    ("j", 278),
771    ("k", 500),
772    ("l", 278),
773    ("less", 564),
774    ("logicalnot", 564),
775    ("lslash", 278),
776    ("m", 778),
777    ("macron", 333),
778    ("minus", 564),
779    ("mu", 500),
780    ("multiply", 564),
781    ("n", 500),
782    ("nine", 500),
783    ("ntilde", 500),
784    ("numbersign", 500),
785    ("o", 500),
786    ("oacute", 500),
787    ("ocircumflex", 500),
788    ("odieresis", 500),
789    ("oe", 722),
790    ("ogonek", 333),
791    ("ograve", 500),
792    ("one", 500),
793    ("onehalf", 750),
794    ("onequarter", 750),
795    ("onesuperior", 300),
796    ("ordfeminine", 276),
797    ("ordmasculine", 310),
798    ("oslash", 500),
799    ("otilde", 500),
800    ("p", 500),
801    ("paragraph", 453),
802    ("parenleft", 333),
803    ("parenright", 333),
804    ("percent", 833),
805    ("period", 250),
806    ("periodcentered", 250),
807    ("perthousand", 1000),
808    ("plus", 564),
809    ("plusminus", 564),
810    ("q", 500),
811    ("question", 444),
812    ("questiondown", 444),
813    ("quotedbl", 408),
814    ("quotedblbase", 444),
815    ("quotedblleft", 444),
816    ("quotedblright", 444),
817    ("quoteleft", 333),
818    ("quoteright", 333),
819    ("quotesinglbase", 333),
820    ("quotesingle", 180),
821    ("r", 333),
822    ("registered", 760),
823    ("ring", 333),
824    ("s", 389),
825    ("scaron", 389),
826    ("section", 500),
827    ("semicolon", 278),
828    ("seven", 500),
829    ("six", 500),
830    ("slash", 278),
831    ("space", 250),
832    ("sterling", 500),
833    ("t", 278),
834    ("thorn", 500),
835    ("three", 500),
836    ("threequarters", 750),
837    ("threesuperior", 300),
838    ("tilde", 333),
839    ("trademark", 980),
840    ("two", 500),
841    ("twosuperior", 300),
842    ("u", 500),
843    ("uacute", 500),
844    ("ucircumflex", 500),
845    ("udieresis", 500),
846    ("ugrave", 500),
847    ("underscore", 500),
848    ("v", 500),
849    ("w", 722),
850    ("x", 500),
851    ("y", 500),
852    ("yacute", 500),
853    ("ydieresis", 500),
854    ("yen", 500),
855    ("z", 444),
856    ("zcaron", 444),
857    ("zero", 500),
858];
859
860/// `Times Bold` glyph widths, sorted by
861/// glyph name for binary search (Adobe Core-14 AFM metrics).
862#[rustfmt::skip]
863const TIMES_BOLD: &[(&str, u16)] = &[
864    ("A", 722),
865    ("AE", 1000),
866    ("Aacute", 722),
867    ("Acircumflex", 722),
868    ("Adieresis", 722),
869    ("Agrave", 722),
870    ("Aring", 722),
871    ("Atilde", 722),
872    ("B", 667),
873    ("C", 722),
874    ("Ccedilla", 722),
875    ("D", 722),
876    ("E", 667),
877    ("Eacute", 667),
878    ("Ecircumflex", 667),
879    ("Edieresis", 667),
880    ("Egrave", 667),
881    ("Eth", 722),
882    ("F", 611),
883    ("G", 778),
884    ("H", 778),
885    ("I", 389),
886    ("Iacute", 389),
887    ("Icircumflex", 389),
888    ("Idieresis", 389),
889    ("Igrave", 389),
890    ("J", 500),
891    ("K", 778),
892    ("L", 667),
893    ("Lslash", 667),
894    ("M", 944),
895    ("N", 722),
896    ("Ntilde", 722),
897    ("O", 778),
898    ("OE", 1000),
899    ("Oacute", 778),
900    ("Ocircumflex", 778),
901    ("Odieresis", 778),
902    ("Ograve", 778),
903    ("Oslash", 778),
904    ("Otilde", 778),
905    ("P", 611),
906    ("Q", 778),
907    ("R", 722),
908    ("S", 556),
909    ("Scaron", 556),
910    ("T", 667),
911    ("Thorn", 611),
912    ("U", 722),
913    ("Uacute", 722),
914    ("Ucircumflex", 722),
915    ("Udieresis", 722),
916    ("Ugrave", 722),
917    ("V", 722),
918    ("W", 1000),
919    ("X", 722),
920    ("Y", 722),
921    ("Yacute", 722),
922    ("Ydieresis", 722),
923    ("Z", 667),
924    ("Zcaron", 667),
925    ("a", 500),
926    ("aacute", 500),
927    ("acircumflex", 500),
928    ("acute", 333),
929    ("adieresis", 500),
930    ("ae", 722),
931    ("agrave", 500),
932    ("ampersand", 833),
933    ("aring", 500),
934    ("asciicircum", 581),
935    ("asciitilde", 520),
936    ("asterisk", 500),
937    ("at", 930),
938    ("atilde", 500),
939    ("b", 556),
940    ("backslash", 278),
941    ("bar", 220),
942    ("braceleft", 394),
943    ("braceright", 394),
944    ("bracketleft", 333),
945    ("bracketright", 333),
946    ("breve", 333),
947    ("brokenbar", 220),
948    ("bullet", 350),
949    ("c", 444),
950    ("caron", 333),
951    ("ccedilla", 444),
952    ("cedilla", 333),
953    ("cent", 500),
954    ("circumflex", 333),
955    ("colon", 333),
956    ("comma", 250),
957    ("copyright", 747),
958    ("currency", 500),
959    ("d", 556),
960    ("dagger", 500),
961    ("daggerdbl", 500),
962    ("degree", 400),
963    ("dieresis", 333),
964    ("divide", 570),
965    ("dollar", 500),
966    ("dotaccent", 333),
967    ("dotlessi", 278),
968    ("e", 444),
969    ("eacute", 444),
970    ("ecircumflex", 444),
971    ("edieresis", 444),
972    ("egrave", 444),
973    ("eight", 500),
974    ("ellipsis", 1000),
975    ("emdash", 1000),
976    ("endash", 500),
977    ("equal", 570),
978    ("eth", 500),
979    ("exclam", 333),
980    ("exclamdown", 333),
981    ("f", 333),
982    ("fi", 556),
983    ("five", 500),
984    ("fl", 556),
985    ("florin", 500),
986    ("four", 500),
987    ("fraction", 167),
988    ("g", 500),
989    ("germandbls", 556),
990    ("grave", 333),
991    ("greater", 570),
992    ("guillemotleft", 500),
993    ("guillemotright", 500),
994    ("guilsinglleft", 333),
995    ("guilsinglright", 333),
996    ("h", 556),
997    ("hungarumlaut", 333),
998    ("hyphen", 333),
999    ("i", 278),
1000    ("iacute", 278),
1001    ("icircumflex", 278),
1002    ("idieresis", 278),
1003    ("igrave", 278),
1004    ("j", 333),
1005    ("k", 556),
1006    ("l", 278),
1007    ("less", 570),
1008    ("logicalnot", 570),
1009    ("lslash", 278),
1010    ("m", 833),
1011    ("macron", 333),
1012    ("minus", 570),
1013    ("mu", 556),
1014    ("multiply", 570),
1015    ("n", 556),
1016    ("nine", 500),
1017    ("ntilde", 556),
1018    ("numbersign", 500),
1019    ("o", 500),
1020    ("oacute", 500),
1021    ("ocircumflex", 500),
1022    ("odieresis", 500),
1023    ("oe", 722),
1024    ("ogonek", 333),
1025    ("ograve", 500),
1026    ("one", 500),
1027    ("onehalf", 750),
1028    ("onequarter", 750),
1029    ("onesuperior", 300),
1030    ("ordfeminine", 300),
1031    ("ordmasculine", 330),
1032    ("oslash", 500),
1033    ("otilde", 500),
1034    ("p", 556),
1035    ("paragraph", 540),
1036    ("parenleft", 333),
1037    ("parenright", 333),
1038    ("percent", 1000),
1039    ("period", 250),
1040    ("periodcentered", 250),
1041    ("perthousand", 1000),
1042    ("plus", 570),
1043    ("plusminus", 570),
1044    ("q", 556),
1045    ("question", 500),
1046    ("questiondown", 500),
1047    ("quotedbl", 555),
1048    ("quotedblbase", 500),
1049    ("quotedblleft", 500),
1050    ("quotedblright", 500),
1051    ("quoteleft", 333),
1052    ("quoteright", 333),
1053    ("quotesinglbase", 333),
1054    ("quotesingle", 278),
1055    ("r", 444),
1056    ("registered", 747),
1057    ("ring", 333),
1058    ("s", 389),
1059    ("scaron", 389),
1060    ("section", 500),
1061    ("semicolon", 333),
1062    ("seven", 500),
1063    ("six", 500),
1064    ("slash", 278),
1065    ("space", 250),
1066    ("sterling", 500),
1067    ("t", 333),
1068    ("thorn", 556),
1069    ("three", 500),
1070    ("threequarters", 750),
1071    ("threesuperior", 300),
1072    ("tilde", 333),
1073    ("trademark", 1000),
1074    ("two", 500),
1075    ("twosuperior", 300),
1076    ("u", 556),
1077    ("uacute", 556),
1078    ("ucircumflex", 556),
1079    ("udieresis", 556),
1080    ("ugrave", 556),
1081    ("underscore", 500),
1082    ("v", 500),
1083    ("w", 722),
1084    ("x", 500),
1085    ("y", 500),
1086    ("yacute", 500),
1087    ("ydieresis", 500),
1088    ("yen", 500),
1089    ("z", 444),
1090    ("zcaron", 444),
1091    ("zero", 500),
1092];
1093
1094/// `Times Italic` glyph widths, sorted by
1095/// glyph name for binary search (Adobe Core-14 AFM metrics).
1096#[rustfmt::skip]
1097const TIMES_ITALIC: &[(&str, u16)] = &[
1098    ("A", 611),
1099    ("AE", 889),
1100    ("Aacute", 611),
1101    ("Acircumflex", 611),
1102    ("Adieresis", 611),
1103    ("Agrave", 611),
1104    ("Aring", 611),
1105    ("Atilde", 611),
1106    ("B", 611),
1107    ("C", 667),
1108    ("Ccedilla", 667),
1109    ("D", 722),
1110    ("E", 611),
1111    ("Eacute", 611),
1112    ("Ecircumflex", 611),
1113    ("Edieresis", 611),
1114    ("Egrave", 611),
1115    ("Eth", 722),
1116    ("F", 611),
1117    ("G", 722),
1118    ("H", 722),
1119    ("I", 333),
1120    ("Iacute", 333),
1121    ("Icircumflex", 333),
1122    ("Idieresis", 333),
1123    ("Igrave", 333),
1124    ("J", 444),
1125    ("K", 667),
1126    ("L", 556),
1127    ("Lslash", 556),
1128    ("M", 833),
1129    ("N", 667),
1130    ("Ntilde", 667),
1131    ("O", 722),
1132    ("OE", 944),
1133    ("Oacute", 722),
1134    ("Ocircumflex", 722),
1135    ("Odieresis", 722),
1136    ("Ograve", 722),
1137    ("Oslash", 722),
1138    ("Otilde", 722),
1139    ("P", 611),
1140    ("Q", 722),
1141    ("R", 611),
1142    ("S", 500),
1143    ("Scaron", 500),
1144    ("T", 556),
1145    ("Thorn", 611),
1146    ("U", 722),
1147    ("Uacute", 722),
1148    ("Ucircumflex", 722),
1149    ("Udieresis", 722),
1150    ("Ugrave", 722),
1151    ("V", 611),
1152    ("W", 833),
1153    ("X", 611),
1154    ("Y", 556),
1155    ("Yacute", 556),
1156    ("Ydieresis", 556),
1157    ("Z", 556),
1158    ("Zcaron", 556),
1159    ("a", 500),
1160    ("aacute", 500),
1161    ("acircumflex", 500),
1162    ("acute", 333),
1163    ("adieresis", 500),
1164    ("ae", 667),
1165    ("agrave", 500),
1166    ("ampersand", 778),
1167    ("aring", 500),
1168    ("asciicircum", 422),
1169    ("asciitilde", 541),
1170    ("asterisk", 500),
1171    ("at", 920),
1172    ("atilde", 500),
1173    ("b", 500),
1174    ("backslash", 278),
1175    ("bar", 275),
1176    ("braceleft", 400),
1177    ("braceright", 400),
1178    ("bracketleft", 389),
1179    ("bracketright", 389),
1180    ("breve", 333),
1181    ("brokenbar", 275),
1182    ("bullet", 350),
1183    ("c", 444),
1184    ("caron", 333),
1185    ("ccedilla", 444),
1186    ("cedilla", 333),
1187    ("cent", 500),
1188    ("circumflex", 333),
1189    ("colon", 333),
1190    ("comma", 250),
1191    ("copyright", 760),
1192    ("currency", 500),
1193    ("d", 500),
1194    ("dagger", 500),
1195    ("daggerdbl", 500),
1196    ("degree", 400),
1197    ("dieresis", 333),
1198    ("divide", 675),
1199    ("dollar", 500),
1200    ("dotaccent", 333),
1201    ("dotlessi", 278),
1202    ("e", 444),
1203    ("eacute", 444),
1204    ("ecircumflex", 444),
1205    ("edieresis", 444),
1206    ("egrave", 444),
1207    ("eight", 500),
1208    ("ellipsis", 889),
1209    ("emdash", 889),
1210    ("endash", 500),
1211    ("equal", 675),
1212    ("eth", 500),
1213    ("exclam", 333),
1214    ("exclamdown", 389),
1215    ("f", 278),
1216    ("fi", 500),
1217    ("five", 500),
1218    ("fl", 500),
1219    ("florin", 500),
1220    ("four", 500),
1221    ("fraction", 167),
1222    ("g", 500),
1223    ("germandbls", 500),
1224    ("grave", 333),
1225    ("greater", 675),
1226    ("guillemotleft", 500),
1227    ("guillemotright", 500),
1228    ("guilsinglleft", 333),
1229    ("guilsinglright", 333),
1230    ("h", 500),
1231    ("hungarumlaut", 333),
1232    ("hyphen", 333),
1233    ("i", 278),
1234    ("iacute", 278),
1235    ("icircumflex", 278),
1236    ("idieresis", 278),
1237    ("igrave", 278),
1238    ("j", 278),
1239    ("k", 444),
1240    ("l", 278),
1241    ("less", 675),
1242    ("logicalnot", 675),
1243    ("lslash", 278),
1244    ("m", 722),
1245    ("macron", 333),
1246    ("minus", 675),
1247    ("mu", 500),
1248    ("multiply", 675),
1249    ("n", 500),
1250    ("nine", 500),
1251    ("ntilde", 500),
1252    ("numbersign", 500),
1253    ("o", 500),
1254    ("oacute", 500),
1255    ("ocircumflex", 500),
1256    ("odieresis", 500),
1257    ("oe", 667),
1258    ("ogonek", 333),
1259    ("ograve", 500),
1260    ("one", 500),
1261    ("onehalf", 750),
1262    ("onequarter", 750),
1263    ("onesuperior", 300),
1264    ("ordfeminine", 276),
1265    ("ordmasculine", 310),
1266    ("oslash", 500),
1267    ("otilde", 500),
1268    ("p", 500),
1269    ("paragraph", 523),
1270    ("parenleft", 333),
1271    ("parenright", 333),
1272    ("percent", 833),
1273    ("period", 250),
1274    ("periodcentered", 250),
1275    ("perthousand", 1000),
1276    ("plus", 675),
1277    ("plusminus", 675),
1278    ("q", 500),
1279    ("question", 500),
1280    ("questiondown", 500),
1281    ("quotedbl", 420),
1282    ("quotedblbase", 556),
1283    ("quotedblleft", 556),
1284    ("quotedblright", 556),
1285    ("quoteleft", 333),
1286    ("quoteright", 333),
1287    ("quotesinglbase", 333),
1288    ("quotesingle", 214),
1289    ("r", 389),
1290    ("registered", 760),
1291    ("ring", 333),
1292    ("s", 389),
1293    ("scaron", 389),
1294    ("section", 500),
1295    ("semicolon", 333),
1296    ("seven", 500),
1297    ("six", 500),
1298    ("slash", 278),
1299    ("space", 250),
1300    ("sterling", 500),
1301    ("t", 278),
1302    ("thorn", 500),
1303    ("three", 500),
1304    ("threequarters", 750),
1305    ("threesuperior", 300),
1306    ("tilde", 333),
1307    ("trademark", 980),
1308    ("two", 500),
1309    ("twosuperior", 300),
1310    ("u", 500),
1311    ("uacute", 500),
1312    ("ucircumflex", 500),
1313    ("udieresis", 500),
1314    ("ugrave", 500),
1315    ("underscore", 500),
1316    ("v", 444),
1317    ("w", 667),
1318    ("x", 444),
1319    ("y", 444),
1320    ("yacute", 444),
1321    ("ydieresis", 444),
1322    ("yen", 500),
1323    ("z", 389),
1324    ("zcaron", 389),
1325    ("zero", 500),
1326];
1327
1328/// `Times Bold Italic` glyph widths, sorted by
1329/// glyph name for binary search (Adobe Core-14 AFM metrics).
1330#[rustfmt::skip]
1331const TIMES_BOLD_ITALIC: &[(&str, u16)] = &[
1332    ("A", 667),
1333    ("AE", 944),
1334    ("Aacute", 667),
1335    ("Acircumflex", 667),
1336    ("Adieresis", 667),
1337    ("Agrave", 667),
1338    ("Aring", 667),
1339    ("Atilde", 667),
1340    ("B", 667),
1341    ("C", 667),
1342    ("Ccedilla", 667),
1343    ("D", 722),
1344    ("E", 667),
1345    ("Eacute", 667),
1346    ("Ecircumflex", 667),
1347    ("Edieresis", 667),
1348    ("Egrave", 667),
1349    ("Eth", 722),
1350    ("F", 667),
1351    ("G", 722),
1352    ("H", 778),
1353    ("I", 389),
1354    ("Iacute", 389),
1355    ("Icircumflex", 389),
1356    ("Idieresis", 389),
1357    ("Igrave", 389),
1358    ("J", 500),
1359    ("K", 667),
1360    ("L", 611),
1361    ("Lslash", 611),
1362    ("M", 889),
1363    ("N", 722),
1364    ("Ntilde", 722),
1365    ("O", 722),
1366    ("OE", 944),
1367    ("Oacute", 722),
1368    ("Ocircumflex", 722),
1369    ("Odieresis", 722),
1370    ("Ograve", 722),
1371    ("Oslash", 722),
1372    ("Otilde", 722),
1373    ("P", 611),
1374    ("Q", 722),
1375    ("R", 667),
1376    ("S", 556),
1377    ("Scaron", 556),
1378    ("T", 611),
1379    ("Thorn", 611),
1380    ("U", 722),
1381    ("Uacute", 722),
1382    ("Ucircumflex", 722),
1383    ("Udieresis", 722),
1384    ("Ugrave", 722),
1385    ("V", 667),
1386    ("W", 889),
1387    ("X", 667),
1388    ("Y", 611),
1389    ("Yacute", 611),
1390    ("Ydieresis", 611),
1391    ("Z", 611),
1392    ("Zcaron", 611),
1393    ("a", 500),
1394    ("aacute", 500),
1395    ("acircumflex", 500),
1396    ("acute", 333),
1397    ("adieresis", 500),
1398    ("ae", 722),
1399    ("agrave", 500),
1400    ("ampersand", 778),
1401    ("aring", 500),
1402    ("asciicircum", 570),
1403    ("asciitilde", 570),
1404    ("asterisk", 500),
1405    ("at", 832),
1406    ("atilde", 500),
1407    ("b", 500),
1408    ("backslash", 278),
1409    ("bar", 220),
1410    ("braceleft", 348),
1411    ("braceright", 348),
1412    ("bracketleft", 333),
1413    ("bracketright", 333),
1414    ("breve", 333),
1415    ("brokenbar", 220),
1416    ("bullet", 350),
1417    ("c", 444),
1418    ("caron", 333),
1419    ("ccedilla", 444),
1420    ("cedilla", 333),
1421    ("cent", 500),
1422    ("circumflex", 333),
1423    ("colon", 333),
1424    ("comma", 250),
1425    ("copyright", 747),
1426    ("currency", 500),
1427    ("d", 500),
1428    ("dagger", 500),
1429    ("daggerdbl", 500),
1430    ("degree", 400),
1431    ("dieresis", 333),
1432    ("divide", 570),
1433    ("dollar", 500),
1434    ("dotaccent", 333),
1435    ("dotlessi", 278),
1436    ("e", 444),
1437    ("eacute", 444),
1438    ("ecircumflex", 444),
1439    ("edieresis", 444),
1440    ("egrave", 444),
1441    ("eight", 500),
1442    ("ellipsis", 1000),
1443    ("emdash", 1000),
1444    ("endash", 500),
1445    ("equal", 570),
1446    ("eth", 500),
1447    ("exclam", 389),
1448    ("exclamdown", 389),
1449    ("f", 333),
1450    ("fi", 556),
1451    ("five", 500),
1452    ("fl", 556),
1453    ("florin", 500),
1454    ("four", 500),
1455    ("fraction", 167),
1456    ("g", 500),
1457    ("germandbls", 500),
1458    ("grave", 333),
1459    ("greater", 570),
1460    ("guillemotleft", 500),
1461    ("guillemotright", 500),
1462    ("guilsinglleft", 333),
1463    ("guilsinglright", 333),
1464    ("h", 556),
1465    ("hungarumlaut", 333),
1466    ("hyphen", 333),
1467    ("i", 278),
1468    ("iacute", 278),
1469    ("icircumflex", 278),
1470    ("idieresis", 278),
1471    ("igrave", 278),
1472    ("j", 278),
1473    ("k", 500),
1474    ("l", 278),
1475    ("less", 570),
1476    ("logicalnot", 606),
1477    ("lslash", 278),
1478    ("m", 778),
1479    ("macron", 333),
1480    ("minus", 606),
1481    ("mu", 576),
1482    ("multiply", 570),
1483    ("n", 556),
1484    ("nine", 500),
1485    ("ntilde", 556),
1486    ("numbersign", 500),
1487    ("o", 500),
1488    ("oacute", 500),
1489    ("ocircumflex", 500),
1490    ("odieresis", 500),
1491    ("oe", 722),
1492    ("ogonek", 333),
1493    ("ograve", 500),
1494    ("one", 500),
1495    ("onehalf", 750),
1496    ("onequarter", 750),
1497    ("onesuperior", 300),
1498    ("ordfeminine", 266),
1499    ("ordmasculine", 300),
1500    ("oslash", 500),
1501    ("otilde", 500),
1502    ("p", 500),
1503    ("paragraph", 500),
1504    ("parenleft", 333),
1505    ("parenright", 333),
1506    ("percent", 833),
1507    ("period", 250),
1508    ("periodcentered", 250),
1509    ("perthousand", 1000),
1510    ("plus", 570),
1511    ("plusminus", 570),
1512    ("q", 500),
1513    ("question", 500),
1514    ("questiondown", 500),
1515    ("quotedbl", 555),
1516    ("quotedblbase", 500),
1517    ("quotedblleft", 500),
1518    ("quotedblright", 500),
1519    ("quoteleft", 333),
1520    ("quoteright", 333),
1521    ("quotesinglbase", 333),
1522    ("quotesingle", 278),
1523    ("r", 389),
1524    ("registered", 747),
1525    ("ring", 333),
1526    ("s", 389),
1527    ("scaron", 389),
1528    ("section", 500),
1529    ("semicolon", 333),
1530    ("seven", 500),
1531    ("six", 500),
1532    ("slash", 278),
1533    ("space", 250),
1534    ("sterling", 500),
1535    ("t", 278),
1536    ("thorn", 500),
1537    ("three", 500),
1538    ("threequarters", 750),
1539    ("threesuperior", 300),
1540    ("tilde", 333),
1541    ("trademark", 1000),
1542    ("two", 500),
1543    ("twosuperior", 300),
1544    ("u", 556),
1545    ("uacute", 556),
1546    ("ucircumflex", 556),
1547    ("udieresis", 556),
1548    ("ugrave", 556),
1549    ("underscore", 500),
1550    ("v", 444),
1551    ("w", 667),
1552    ("x", 500),
1553    ("y", 444),
1554    ("yacute", 444),
1555    ("ydieresis", 444),
1556    ("yen", 500),
1557    ("z", 389),
1558    ("zcaron", 389),
1559    ("zero", 500),
1560];
1561
1562#[cfg(test)]
1563mod tests {
1564    use super::*;
1565
1566    #[test]
1567    fn standard_14_known_widths() {
1568        assert_eq!(standard_14_width("Helvetica", "space"), Some(278.0));
1569        assert_eq!(standard_14_width("Helvetica", "A"), Some(667.0));
1570        assert_eq!(standard_14_width("Helvetica-Bold", "A"), Some(722.0));
1571        assert_eq!(standard_14_width("Times-Roman", "A"), Some(722.0));
1572        assert_eq!(standard_14_width("Times-Italic", "a"), Some(500.0));
1573        // Courier is monospaced: every glyph is 600 units wide.
1574        assert_eq!(standard_14_width("Courier", "A"), Some(600.0));
1575        assert_eq!(standard_14_width("Courier-BoldOblique", "m"), Some(600.0));
1576        // Oblique variants share their upright counterpart's widths.
1577        assert_eq!(
1578            standard_14_width("Helvetica-Oblique", "A"),
1579            standard_14_width("Helvetica", "A")
1580        );
1581        assert_eq!(
1582            standard_14_width("Helvetica-BoldOblique", "A"),
1583            standard_14_width("Helvetica-Bold", "A")
1584        );
1585    }
1586
1587    #[test]
1588    fn standard_14_aliases_and_non_members() {
1589        assert_eq!(standard_14_width("Arial", "space"), Some(278.0)); // Arial -> Helvetica
1590        assert_eq!(standard_14_width("ABCDEF+Times-Bold", "A"), Some(722.0)); // subset prefix stripped
1591        assert_eq!(standard_14_width("TimesNewRomanPSMT", "A"), Some(722.0)); // TrueType alias -> Times-Roman
1592        assert_eq!(standard_14_width("CourierNewPS-BoldMT", "A"), Some(600.0)); // TrueType alias -> Courier-Bold
1593        assert!(standard_14_width("Symbol", "alpha").is_none()); // out of scope
1594        assert!(standard_14_width("SomeEmbeddedFont", "A").is_none());
1595        assert!(is_standard_14("Courier-Bold") && !is_standard_14("Comic Sans"));
1596        assert!(is_standard_14("Arial-BoldMT"));
1597        assert!(!is_standard_14("ZapfDingbats"));
1598    }
1599
1600    // Review-fix regression: `classify()` must reject metrically-distinct
1601    // siblings that merely share a standard-14 prefix (see module docs on
1602    // `classify`), rather than silently returning a wrong-but-plausible
1603    // Core-14 width.
1604    #[test]
1605    fn standard_14_review_fix_positive() {
1606        assert_eq!(standard_14_width("Helvetica-Bold", "A"), Some(722.0));
1607        assert_eq!(standard_14_width("Arial-BoldMT", "space"), Some(278.0));
1608        assert!(standard_14_width("TimesNewRomanPS-BoldItalicMT", "A").is_some());
1609        assert_eq!(standard_14_width("CourierNew-Bold", "x"), Some(600.0));
1610        // Internal spaces are handled (stripped before stem matching).
1611        assert!(standard_14_width("TimesNewRoman", "A").is_some());
1612        assert!(standard_14_width("Times New Roman", "A").is_some());
1613    }
1614
1615    #[test]
1616    fn standard_14_rejects_metrically_distinct_siblings() {
1617        assert!(standard_14_width("Helvetica-Narrow", "A").is_none());
1618        assert!(standard_14_width("HelveticaNeue-Bold", "A").is_none());
1619        assert!(standard_14_width("Helvetica Neue", "A").is_none());
1620        assert!(standard_14_width("TimesTen-Bold", "A").is_none());
1621        assert!(standard_14_width("Helvetica-Light", "A").is_none());
1622        assert!(standard_14_width("Times New Roman Condensed", "A").is_none());
1623    }
1624
1625    #[test]
1626    fn standard_14_classify_case_folds() {
1627        // classify() lowercases internally, same as
1628        // `FaceRequest::from_font_dict`'s normalization.
1629        assert_eq!(standard_14_width("arial-bold", "A"), Some(722.0));
1630    }
1631}