swash/internal/
head.rs

1//! Font header tables.
2
3use super::{raw_tag, Bytes, RawFont, RawTag};
4
5pub const HEAD: RawTag = raw_tag(b"head");
6pub const OS_2: RawTag = raw_tag(b"OS/2");
7pub const POST: RawTag = raw_tag(b"post");
8pub const MAXP: RawTag = raw_tag(b"maxp");
9pub const HHEA: RawTag = raw_tag(b"hhea");
10pub const VHEA: RawTag = raw_tag(b"vhea");
11
12/// Font header table.
13#[derive(Copy, Clone)]
14pub struct Head<'a>(Bytes<'a>);
15
16impl<'a> Head<'a> {
17    /// The expected value of the 'magic' field in the header table.
18    pub const MAGIC: u32 = 0x5F0F3CF5;
19
20    /// Creates a font header table wrapping the specified data.
21    pub fn new(data: &'a [u8]) -> Self {
22        Self(Bytes::new(data))
23    }
24
25    /// Creates a font header table from the specified font.
26    /// Returns `None` if the font does not contain a `head` table.    
27    pub fn from_font(font: impl RawFont<'a>) -> Option<Self> {
28        Some(Self::new(font.table_data(HEAD)?))
29    }
30
31    /// Returns the underlying bytes of the table.
32    pub fn data(&self) -> &'a [u8] {
33        self.0.data()
34    }
35
36    /// Returns the major version of the header table. Set to 1.
37    pub fn major_version(&self) -> u16 {
38        self.0.read(0).unwrap_or(0)
39    }
40
41    /// Returns the minor version of the header table. Set to 0.
42    pub fn minor_version(&self) -> u16 {
43        self.0.read(2).unwrap_or(0)
44    }
45
46    /// Returns a revision value. Set by font manufacturer.
47    pub fn revision(&self) -> u32 {
48        self.0.read(4).unwrap_or(0)
49    }
50
51    /// Returns a checksum adjustment value.
52    pub fn checksum_adjustment(&self) -> u32 {
53        self.0.read(8).unwrap_or(0)
54    }
55
56    /// Returns a magic number for validation. Set to 0x5F0F3CF5.
57    pub fn magic(&self) -> u32 {
58        self.0.read(12).unwrap_or(0)
59    }
60
61    /// Returns a set of header bit flags.
62    /// - 0: Baseline at y = 0
63    /// - 1: Left sidebearing at x = 0
64    /// - 2: Instructions may depend on point size
65    /// - 3: Force ppem to integer values
66    /// - 4: Instructions may alter advance width
67    /// - 5-10: Unused
68    /// - 11: Font data is lossless
69    /// - 12: Font has been converted
70    /// - 13: Optimized for ClearType
71    /// - 14: Last resort font
72    pub fn flags(&self) -> u16 {
73        self.0.read(16).unwrap_or(0)
74    }
75
76    /// Returns the design units per em. Valid values are 16..=16384.
77    pub fn units_per_em(&self) -> u16 {
78        self.0.read(18).unwrap_or(0)
79    }
80
81    /// Number of seconds since 12:00 midnight that started January 1st 1904 in GMT/UTC time zone.
82    pub fn created(&self) -> u64 {
83        self.0.read(20).unwrap_or(0)
84    }
85
86    /// Number of seconds since 12:00 midnight that started January 1st 1904 in GMT/UTC time zone.
87    pub fn modified(&self) -> u64 {
88        self.0.read(28).unwrap_or(0)
89    }
90
91    /// Returns the union of all glyph bounding boxes.
92    pub fn bounds(&self) -> [(i16, i16); 2] {
93        [
94            (
95                self.0.read_or_default::<i16>(36),
96                self.0.read_or_default::<i16>(38),
97            ),
98            (
99                self.0.read_or_default::<i16>(40),
100                self.0.read_or_default::<i16>(42),
101            ),
102        ]
103    }
104
105    /// Returns the mac style bit flags.
106    /// - 0: Bold
107    /// - 1: Italic
108    /// - 2: Underline
109    /// - 3: Outline
110    /// - 4: Shadow
111    /// - 5: Condensed
112    /// - 6: Extended
113    /// - 7-15: Reserved
114    pub fn mac_style(&self) -> u16 {
115        self.0.read(44).unwrap_or(0)
116    }
117
118    /// Returns the smallest readable size in pixels.
119    pub fn lowest_recommended_ppem(&self) -> u16 {
120        self.0.read(46).unwrap_or(0)
121    }
122
123    /// Deprecated. Returns a hint about the directionality of the glyphs.
124    /// Set to 2.
125    pub fn direction_hint(&self) -> u16 {
126        self.0.read(48).unwrap_or(0)
127    }
128
129    /// Returns the format the the offset array in the 'loca' table.
130    /// - 0: 16-bit offsets (divided by 2)
131    /// - 1: 32-bit offsets
132    pub fn index_to_location_format(&self) -> u16 {
133        self.0.read(50).unwrap_or(0)
134    }
135
136    /// Unused. Set to 0.
137    pub fn glyph_data_format(&self) -> i16 {
138        self.0.read(52).unwrap_or(0)
139    }
140}
141
142/// OS/2 and Windows metrics table.
143#[derive(Copy, Clone)]
144pub struct Os2<'a>(Bytes<'a>);
145
146impl<'a> Os2<'a> {
147    /// Creates an OS/2 table wrapping the specified data.
148    pub fn new(data: &'a [u8]) -> Self {
149        Self(Bytes::new(data))
150    }
151
152    /// Creates an OS/2 table from the specified font.
153    /// Returns `None` if the font does not contain an `OS/2` table.    
154    pub fn from_font(font: impl RawFont<'a>) -> Option<Self> {
155        Some(Self::new(font.table_data(OS_2)?))
156    }
157
158    /// Returns the underlying bytes of the table.
159    pub fn data(&self) -> &'a [u8] {
160        self.0.data()
161    }
162
163    /// Returns the version number for the OS/2 table: 0x0000 to 0x0005.
164    pub fn version(&self) -> u16 {
165        self.0.read(0).unwrap_or(0)
166    }
167
168    /// Returns the average advance width of all non-zero width glyphs in the
169    /// font.
170    pub fn average_char_width(&self) -> i16 {
171        self.0.read(2).unwrap_or(0)
172    }
173
174    /// Returns the visual weight class on a scale from 1 to 1000.  
175    /// Common values:
176    /// - 100: Thin
177    /// - 200: Extra-light (Ultra-light)
178    /// - 300: Light
179    /// - 400: Normal (Regular)
180    /// - 500: Medium
181    /// - 600: Semi-bold
182    /// - 700: Bold
183    /// - 800: Extra-bold (Ultra-bold)
184    /// - 900: Black (Heavy)
185    pub fn weight_class(&self) -> i16 {
186        self.0.read(4).unwrap_or(0)
187    }
188
189    /// Returns the visual width class-- a relative change from the normal aspect
190    /// ratio.
191    /// - 1: Ultra-condensed
192    /// - 2: Extra-condensed
193    /// - 3: Condensed
194    /// - 4: Semi-condensed
195    /// - 5: Medium (Normal)
196    /// - 6: Semi-expanded
197    /// - 7: Expanded
198    /// - 8: Extra-expanded
199    /// - 9: Ultra-expanded
200    pub fn width_class(&self) -> i16 {
201        self.0.read(6).unwrap_or(0)
202    }
203
204    /// Returns the font type bit flags.  
205    /// Bits:
206    /// - 0-3: Usage permissions
207    /// - 4-7: Reserved (set to 0)
208    /// - 8: No subsetting
209    /// - 9: Bitmap embedding only
210    /// - 10-15: Reserved (set to 0)
211    pub fn type_flags(&self) -> i16 {
212        self.0.read(8).unwrap_or(0)
213    }
214
215    /// Returns a rectangle describing suggested subscript positioning.
216    pub fn subscript(&self) -> [(i32, i32); 2] {
217        [
218            (
219                self.0.read::<i16>(14).unwrap_or(0) as i32,
220                self.0.read::<i16>(16).unwrap_or(0) as i32,
221            ),
222            (
223                self.0.read::<i16>(10).unwrap_or(0) as i32,
224                self.0.read::<i16>(12).unwrap_or(0) as i32,
225            ),
226        ]
227    }
228
229    /// Returns a rectangle describing suggested superscript positioning.    
230    pub fn superscript(&self) -> [(i32, i32); 2] {
231        [
232            (
233                self.0.read::<i16>(22).unwrap_or(0) as i32,
234                self.0.read::<i16>(24).unwrap_or(0) as i32,
235            ),
236            (
237                self.0.read::<i16>(18).unwrap_or(0) as i32,
238                self.0.read::<i16>(20).unwrap_or(0) as i32,
239            ),
240        ]
241    }
242
243    /// Returns the suggested position of the top of the strikeout stroke from
244    /// the baseline.
245    pub fn strikeout_position(&self) -> i16 {
246        self.0.read(28).unwrap_or(0)
247    }
248
249    /// Returns the suggested thickness for the strikeout stroke.
250    pub fn strikeout_size(&self) -> i16 {
251        self.0.read(26).unwrap_or(0)
252    }
253
254    /// Returns the font family class and subclass. For values:
255    /// <https://docs.microsoft.com/en-us/typography/opentype/spec/ibmfc>
256    pub fn family_class(&self) -> i16 {
257        self.0.read(30).unwrap_or(0)
258    }
259
260    /// Returns a 10-byte PANOSE classification number.
261    /// <https://monotype.github.io/panose/>
262    pub fn panose(&self) -> &'a [u8] {
263        self.0
264            .read_bytes(32, 10)
265            .unwrap_or(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
266    }
267
268    /// Returns a 128-bit value describing the Unicode blocks that are
269    /// supported by the font.
270    pub fn unicode_range(&self) -> (u32, u32, u32, u32) {
271        (
272            self.0.read::<u32>(42).unwrap_or(0),
273            self.0.read::<u32>(46).unwrap_or(0),
274            self.0.read::<u32>(50).unwrap_or(0),
275            self.0.read::<u32>(54).unwrap_or(0),
276        )
277    }
278
279    /// Returns a four character font vendor identifier.
280    pub fn vendor_id(&self) -> &'a str {
281        core::str::from_utf8(self.0.read_bytes(58, 4).unwrap_or(b"none")).unwrap_or("none")
282    }
283
284    /// Returns the font selection bit flags.  
285    /// Bits:
286    /// - 0: Italic
287    /// - 1: Underscore
288    /// - 2: Negative
289    /// - 3: Outlined
290    /// - 4: Strikeout
291    /// - 5: Bold
292    /// - 6: Regular
293    /// - 7: Use typographic metrics
294    /// - 8: WWS (Weight/Width/Slope names)
295    /// - 9: Oblique
296    /// - 10-15: Reserved (set to 0)
297    pub fn selection_flags(&self) -> Flags {
298        Flags(self.0.read(62).unwrap_or(0))
299    }
300
301    /// Returns the minimum and maximum Unicode codepoints supported by the
302    /// font. Note that this does not cover supplementary characters.
303    pub fn char_range(&self) -> (u16, u16) {
304        (
305            self.0.read::<u16>(64).unwrap_or(0),
306            self.0.read::<u16>(66).unwrap_or(0),
307        )
308    }
309
310    /// Returns the typographic ascender.
311    pub fn typographic_ascender(&self) -> i16 {
312        self.0.read(68).unwrap_or(0)
313    }
314
315    /// Returns the typographic descender.
316    pub fn typographic_descender(&self) -> i16 {
317        self.0.read(70).unwrap_or(0)
318    }
319
320    /// Returns the typographic line gap.
321    pub fn typographic_line_gap(&self) -> i16 {
322        self.0.read(72).unwrap_or(0)
323    }
324
325    /// Returns a Windows specific value that defines the upper extent of
326    /// the clipping region.
327    pub fn win_ascent(&self) -> u16 {
328        self.0.read(74).unwrap_or(0)
329    }
330
331    /// Returns a Windows specific value that defines the lower extent of
332    /// the clipping region.
333    pub fn win_descent(&self) -> u16 {
334        self.0.read(76).unwrap_or(0)
335    }
336
337    /// Returns Windows specific code page ranges supported by the font.
338    /// (table version >= 1)
339    pub fn code_page_range(&self) -> (u32, u32) {
340        if self.version() < 1 {
341            return (0, 0);
342        }
343        (
344            self.0.read::<u32>(78).unwrap_or(0),
345            self.0.read::<u32>(82).unwrap_or(0),
346        )
347    }
348
349    /// Returns the approximate distance above the baseline for non-descending
350    /// lowercase letters (table version >= 2)
351    pub fn x_height(&self) -> i16 {
352        if self.version() < 2 {
353            return 0;
354        }
355        self.0.read(86).unwrap_or(0)
356    }
357
358    /// Returns the approximate distance above the baseline for uppercase letters.
359    /// (table version >= 2)
360    pub fn cap_height(&self) -> i16 {
361        if self.version() < 2 {
362            return 0;
363        }
364        self.0.read(88).unwrap_or(0)
365    }
366
367    /// Returns a Unicode codepoint for the default character to use if
368    /// a requested character is not supported by the font.
369    /// (table version >= 2)
370    pub fn default_char(&self) -> u16 {
371        if self.version() < 2 {
372            return 0;
373        }
374        self.0.read(90).unwrap_or(0)
375    }
376
377    /// Returns a Unicode codepoint for the default character used to separate
378    /// words and justify text. (table version >= 2)
379    pub fn break_char(&self) -> u16 {
380        if self.version() < 2 {
381            return 0;
382        }
383        self.0.read(92).unwrap_or(0)
384    }
385
386    /// Returns the maximum length of a target glyph context for any feature in
387    /// the font. (table version >= 2)
388    pub fn max_context(&self) -> u16 {
389        if self.version() < 2 {
390            return 0;
391        }
392        self.0.read(94).unwrap_or(0)
393    }
394
395    /// Returns the lower value of the size range for which this font has been
396    /// designed. The units are TWIPS (1/20 points). (table version >= 5)
397    pub fn lower_optical_point_size(&self) -> u16 {
398        if self.version() < 5 {
399            return 0;
400        }
401        self.0.read(96).unwrap_or(0)
402    }
403
404    /// Returns the upper value of the size range for which this font has been
405    /// designed. The units are TWIPS (1/20 points). (table version >= 5)
406    pub fn upper_optical_point_size(&self) -> u16 {
407        if self.version() < 5 {
408            return 0;
409        }
410        self.0.read(98).unwrap_or(0)
411    }
412}
413
414/// OS/2 selection flags.
415#[derive(Copy, Clone)]
416pub struct Flags(pub u16);
417
418impl Flags {
419    /// Font contains italic glyphs.
420    pub fn italic(self) -> bool {
421        self.bit(0)
422    }
423
424    /// Glyphs are underscored.
425    pub fn underscore(self) -> bool {
426        self.bit(1)
427    }
428
429    /// Glyphs have their foreground and background reversed.
430    pub fn negative(self) -> bool {
431        self.bit(2)
432    }
433
434    /// Hollow glyphs.
435    pub fn outlined(self) -> bool {
436        self.bit(3)
437    }
438
439    /// Glyphs are overstruck.
440    pub fn strikeout(self) -> bool {
441        self.bit(4)
442    }
443
444    /// Glyphs are emboldened.
445    pub fn bold(self) -> bool {
446        self.bit(5)
447    }
448
449    /// Glyphs are in the standard weight/style for the font.
450    pub fn regular(self) -> bool {
451        self.bit(6)
452    }
453
454    /// Typographic metrics are recommended for default line spacing.
455    pub fn use_typographic_metrics(self) -> bool {
456        self.bit(7)
457    }
458
459    /// Font has name table strings consistent with WWS family naming.
460    pub fn wws_names(self) -> bool {
461        self.bit(8)
462    }
463
464    /// Font contains oblique glyphs.
465    pub fn oblique(self) -> bool {
466        self.bit(9)
467    }
468
469    fn bit(self, bit: u16) -> bool {
470        self.0 & 1 << bit != 0
471    }
472}
473
474/// PostScript table.
475#[derive(Copy, Clone)]
476pub struct Post<'a>(Bytes<'a>);
477
478impl<'a> Post<'a> {
479    /// Creates a PostScript table wrapping the specified data.
480    pub fn new(data: &'a [u8]) -> Self {
481        Self(Bytes::new(data))
482    }
483
484    /// Creates a PostScript table from the specified font.
485    /// Returns `None` if the font does not contain a `post` table.    
486    pub fn from_font(font: impl RawFont<'a>) -> Option<Self> {
487        Some(Self::new(font.table_data(POST)?))
488    }
489
490    /// Returns the underlying bytes of the table.
491    pub fn data(&self) -> &'a [u8] {
492        self.0.data()
493    }
494
495    /// Returns the version of the PostScript table.
496    pub fn version(&self) -> u32 {
497        self.0.read(0).unwrap_or(0)
498    }
499
500    /// Returns the italic angle in counter-clockwise degrees from the vertical.
501    pub fn italic_angle(&self) -> u32 {
502        self.0.read(4).unwrap_or(0)
503    }
504
505    /// Returns the suggested position of the top of the underline stroke from
506    /// the baseline.
507    pub fn underline_position(&self) -> i16 {
508        self.0.read(8).unwrap_or(0)
509    }
510
511    /// Returns the suggested thickness for the underline stroke.
512    pub fn underline_size(&self) -> i16 {
513        self.0.read(10).unwrap_or(0)
514    }
515
516    /// Returns true if the font is not proportionally spaced (i.e. monospaced).
517    pub fn is_fixed_pitch(&self) -> bool {
518        self.0.read::<u32>(12).unwrap_or(0) != 0
519    }
520
521    /// Returns true if the table can provide glyph names. Only versions 1.0
522    /// (0x00010000) and 2.0 (0x00020000).
523    pub fn has_names(&self) -> bool {
524        let v = self.version();
525        v == 0x10000 || v == 0x20000
526    }
527
528    /// Returns the name of the specified glyph id if available.
529    pub fn name(&self, glyph_id: u16) -> Option<&'a str> {
530        if !self.has_names() {
531            return None;
532        }
533        let v = self.version();
534        if v == 0x10000 {
535            if glyph_id >= 258 {
536                return None;
537            }
538            return Some(DEFAULT_GLYPH_NAMES[glyph_id as usize]);
539        } else if v == 0x20000 {
540            let b = &self.0;
541            let count = b.read::<u16>(32)?;
542            if glyph_id >= count {
543                return None;
544            }
545            let mut index = b.read::<u16>(34 + glyph_id as usize * 2)? as usize;
546            if index < 258 {
547                return Some(DEFAULT_GLYPH_NAMES[index]);
548            }
549            index -= 258;
550            let mut base = 34 + count as usize * 2;
551            for _ in 0..index {
552                let len = b.read::<u8>(base)? as usize;
553                base += len + 1;
554            }
555            let len = b.read::<u8>(base)? as usize;
556            base += 1;
557            let bytes = b.read_bytes(base, len)?;
558            return core::str::from_utf8(bytes).ok();
559        }
560        None
561    }
562}
563
564/// Maximum profile table.
565#[derive(Copy, Clone)]
566pub struct Maxp<'a>(Bytes<'a>);
567
568impl<'a> Maxp<'a> {
569    /// Creates a maximum profile table wrapping the specified data.
570    pub fn new(data: &'a [u8]) -> Self {
571        Self(Bytes::new(data))
572    }
573
574    /// Creates a maximum profile table from the specified font.
575    /// Returns `None` if the font does not contain a `maxp` table.    
576    pub fn from_font(font: impl RawFont<'a>) -> Option<Self> {
577        Some(Self::new(font.table_data(MAXP)?))
578    }
579
580    /// Returns the underlying bytes of the table.
581    pub fn data(&self) -> &'a [u8] {
582        self.0.data()
583    }
584
585    /// Returns the version of the table.
586    /// - 0x00005000: Version 0.5 - only `num_glyphs` will return a meaningful value.
587    /// - 0x00010000: Version 1.0
588    pub fn version(&self) -> u32 {
589        self.0.read(0).unwrap_or(0)
590    }
591
592    /// Returns the number of glyphs in the font.
593    pub fn glyph_count(&self) -> u16 {
594        self.0.read(4).unwrap_or(0)
595    }
596
597    /// Returns true if the 'max_' methods will return meaningful values--
598    /// specifically, if the table version is 1.0 (0x00010000).
599    pub fn is_truetype(&self) -> bool {
600        self.version() == 0x00010000
601    }
602
603    /// Returns the maximum points in a simple glyph.
604    pub fn max_points(&self) -> u16 {
605        self.0.read(6).unwrap_or(0)
606    }
607
608    /// Returns the maximum contours in a simple glyph.
609    pub fn max_contours(&self) -> u16 {
610        self.0.read(8).unwrap_or(0)
611    }
612
613    /// Returns the maximum points in a composite glyph.
614    pub fn max_composite_points(&self) -> u16 {
615        self.0.read(10).unwrap_or(0)
616    }
617
618    /// Returns the maximum contours in a composite glyph.
619    pub fn max_composite_contours(&self) -> u16 {
620        self.0.read(12).unwrap_or(0)
621    }
622
623    /// Returns 2 if instructions require a 'twilight zone' or 1 otherwise.
624    pub fn max_zones(&self) -> u16 {
625        self.0.read(14).unwrap_or(0)
626    }
627
628    /// Returns the maximum twilight points used in zone 0.
629    pub fn max_twilight_points(&self) -> u16 {
630        self.0.read(16).unwrap_or(0)
631    }
632
633    /// Returns the maximum storage area locations.
634    pub fn max_storage(&self) -> u16 {
635        self.0.read(18).unwrap_or(0)
636    }
637
638    /// Returns the maximum function definitions.
639    pub fn max_function_definitions(&self) -> u16 {
640        self.0.read(20).unwrap_or(0)
641    }
642
643    /// Returns the maximum instruction definitions.
644    pub fn max_instruction_definitions(&self) -> u16 {
645        self.0.read(22).unwrap_or(0)
646    }
647
648    /// Returns the maximum stack depth across all programs in the font.
649    pub fn max_stack_depth(&self) -> u16 {
650        self.0.read(24).unwrap_or(0)
651    }
652
653    /// Returns the maximum size of glyph instructions.
654    pub fn max_instructions_size(&self) -> u16 {
655        self.0.read(26).unwrap_or(0)
656    }
657
658    /// Returns the maximum number of components for a single composite glyph.
659    pub fn max_component_elements(&self) -> u16 {
660        self.0.read(28).unwrap_or(0)
661    }
662
663    /// Returns the maximum nesting level for any composite glyph.
664    pub fn max_component_depth(&self) -> u16 {
665        self.0.read(30).unwrap_or(0)
666    }
667}
668
669/// Horizontal header table.
670#[derive(Copy, Clone)]
671pub struct Hhea<'a>(Bytes<'a>);
672
673impl<'a> Hhea<'a> {
674    /// Creates a horizontal header table wrapping the specified data.
675    pub fn new(data: &'a [u8]) -> Self {
676        Self(Bytes::new(data))
677    }
678
679    /// Creates a horizontal header table from the specified font.
680    /// Returns `None` if the font does not contain an `hhea` table.    
681    pub fn from_font(font: impl RawFont<'a>) -> Option<Self> {
682        Some(Self::new(font.table_data(HHEA)?))
683    }
684
685    /// Returns the underlying bytes of the table.
686    pub fn data(&self) -> &'a [u8] {
687        self.0.data()
688    }
689
690    /// Returns the major version of the horizontal header table. Set to 1.
691    pub fn major_version(&self) -> u16 {
692        self.0.read(0).unwrap_or(0)
693    }
694
695    /// Returns the minor version of the horizontal header table. Set to 0.
696    pub fn minor_version(&self) -> u16 {
697        self.0.read(2).unwrap_or(0)
698    }
699
700    /// Returns the typographic ascender.
701    pub fn ascender(&self) -> i16 {
702        self.0.read(4).unwrap_or(0)
703    }
704
705    /// Returns the typographic descender.
706    pub fn descender(&self) -> i16 {
707        self.0.read(6).unwrap_or(0)
708    }
709
710    /// Returns the typographic line gap.
711    pub fn line_gap(&self) -> i16 {
712        self.0.read(8).unwrap_or(0)
713    }
714
715    /// Returns the maximum advance width.
716    pub fn max_advance(&self) -> u16 {
717        self.0.read(10).unwrap_or(0)
718    }
719
720    /// Returns the minimum left sidebearing.
721    pub fn min_lsb(&self) -> i16 {
722        self.0.read(12).unwrap_or(0)
723    }
724
725    /// Returns the minimum right sidebearing. (min(advance - lsb - (xmax - xmin)))
726    pub fn min_rsb(&self) -> i16 {
727        self.0.read(14).unwrap_or(0)
728    }
729
730    /// Returns the maximum horizontal extent. (max(lsb + (xmax - xmin)))
731    pub fn max_extent(&self) -> i16 {
732        self.0.read(16).unwrap_or(0)
733    }
734
735    /// Returns the slope of the cursor in the form (rise, run).
736    pub fn caret_slope(&self) -> (i16, i16) {
737        (self.0.read(18).unwrap_or(0), self.0.read(20).unwrap_or(0))
738    }
739
740    /// Returns the amount by which a slanted highlight on a glyph should be
741    /// shifted.
742    pub fn caret_offset(&self) -> i16 {
743        self.0.read(22).unwrap_or(0)
744    }
745
746    /// Unused in current format. Set to 0.
747    pub fn metric_data_format(&self) -> i16 {
748        self.0.read(32).unwrap_or(0)
749    }
750
751    /// Returns the number of "long" metric entries in the horizontal metrics
752    /// table.
753    pub fn num_long_metrics(&self) -> u16 {
754        self.0.read(34).unwrap_or(0)
755    }
756}
757
758/// Vertical header table.
759#[derive(Copy, Clone)]
760pub struct Vhea<'a>(Bytes<'a>);
761
762impl<'a> Vhea<'a> {
763    /// Creates a vertical header table wrapping the specified data.
764    pub fn new(data: &'a [u8]) -> Self {
765        Self(Bytes::new(data))
766    }
767
768    /// Creates a vertical header table from the specified font.
769    /// Returns `None` if the font does not contain a `vhea` table.    
770    pub fn from_font(font: impl RawFont<'a>) -> Option<Self> {
771        Some(Self::new(font.table_data(VHEA)?))
772    }
773
774    /// Returns the underlying bytes of the table.
775    pub fn data(&self) -> &'a [u8] {
776        self.0.data()
777    }
778
779    /// Returns the major version of the vertical header table. Set to 1.
780    pub fn major_version(&self) -> u16 {
781        self.0.read(0).unwrap_or(0)
782    }
783
784    /// Returns the minor version of the vertical header table. Set to 0.
785    pub fn minor_version(&self) -> u16 {
786        self.0.read(2).unwrap_or(0)
787    }
788
789    /// Returns the distance in design units from the centerline to the
790    /// previous line's descent.
791    pub fn ascender(&self) -> i16 {
792        self.0.read(4).unwrap_or(0)
793    }
794
795    /// Returns the distance in design units from the centerline to the next
796    /// line's ascent.
797    pub fn descender(&self) -> i16 {
798        self.0.read(6).unwrap_or(0)
799    }
800
801    /// Recommended additional spacing between columns of vertical text.
802    pub fn line_gap(&self) -> i16 {
803        self.0.read(8).unwrap_or(0)
804    }
805
806    /// Returns the maximum advance height.
807    pub fn max_advance(&self) -> u16 {
808        self.0.read(10).unwrap_or(0)
809    }
810
811    /// Returns the minimum top sidebearing.
812    pub fn min_tsb(&self) -> i16 {
813        self.0.read(12).unwrap_or(0)
814    }
815
816    /// Returns the minimum bottom sidebearing.
817    pub fn min_bsb(&self) -> i16 {
818        self.0.read(14).unwrap_or(0)
819    }
820
821    /// Returns the maximum vertical extent. (max(tsb + (ymax - ymin)))
822    pub fn max_extent(&self) -> i16 {
823        self.0.read(16).unwrap_or(0)
824    }
825
826    /// Returns the slope of the cursor in the form (rise, run).
827    pub fn caret_slope(&self) -> (i16, i16) {
828        (self.0.read(18).unwrap_or(0), self.0.read(20).unwrap_or(0))
829    }
830
831    /// Returns the amount by which a slanted highlight on a glyph should be
832    /// shifted.
833    pub fn caret_offset(&self) -> i16 {
834        self.0.read(22).unwrap_or(0)
835    }
836
837    /// Unused in current format. Set to 0.
838    pub fn metric_data_format(&self) -> i16 {
839        self.0.read(32).unwrap_or(0)
840    }
841
842    /// Returns the number of "long" metric entries in the vertical metrics
843    /// table.
844    pub fn num_long_metrics(&self) -> u16 {
845        self.0.read(34).unwrap_or(0)
846    }
847}
848
849#[rustfmt::skip]
850const DEFAULT_GLYPH_NAMES: [&'static str; 258] = [
851    ".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl", "numbersign", "dollar", 
852    "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", 
853    "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", 
854    "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", 
855    "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", 
856    "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", 
857    "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", 
858    "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", 
859    "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", 
860    "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", 
861    "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", 
862    "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", 
863    "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", 
864    "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", 
865    "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", 
866    "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", 
867    "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", 
868    "Delta", "guillemotleft", "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", 
869    "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", 
870    "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", 
871    "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", 
872    "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", 
873    "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", 
874    "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", 
875    "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", 
876    "Scaron", "scaron", "Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn", 
877    "thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", 
878    "onequarter", "threequarters", "franc", "Gbreve", "gbreve", "Idotaccent", "Scedilla", 
879    "scedilla", "Cacute", "cacute", "Ccaron", "ccaron", "dcroat",     
880];