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