read_fonts/generated/
generated_os2.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8/// OS/2 [selection flags](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fsselection)
9#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[repr(transparent)]
12pub struct SelectionFlags {
13    bits: u16,
14}
15
16impl SelectionFlags {
17    /// Bit 0: Font contains italic or oblique glyphs, otherwise they are
18    /// upright.
19    pub const ITALIC: Self = Self { bits: 0x0001 };
20
21    /// Bit 1: Glyphs are underscored.
22    pub const UNDERSCORE: Self = Self { bits: 0x0002 };
23
24    /// Bit 2: Glyphs have their foreground and background reversed.
25    pub const NEGATIVE: Self = Self { bits: 0x0004 };
26
27    /// Bit 3: Outline (hollow) glyphs, otherwise they are solid.
28    pub const OUTLINED: Self = Self { bits: 0x0008 };
29
30    /// Bit 4: Glyphs are overstruck.
31    pub const STRIKEOUT: Self = Self { bits: 0x0010 };
32
33    /// Bit 5: Glyphs are emboldened.
34    pub const BOLD: Self = Self { bits: 0x0020 };
35
36    /// Bit 6: Glyphs are in the standard weight/style for the font.
37    pub const REGULAR: Self = Self { bits: 0x0040 };
38
39    /// Bit 7: If set, it is strongly recommended that applications use
40    /// OS/2.sTypoAscender - OS/2.sTypoDescender + OS/2.sTypoLineGap as
41    /// the default line spacing for this font.
42    pub const USE_TYPO_METRICS: Self = Self { bits: 0x0080 };
43
44    /// Bit 8: The font has 'name' table strings consistent with a
45    /// weight/width/slope family without requiring use of name IDs 21 and 22.
46    pub const WWS: Self = Self { bits: 0x0100 };
47
48    /// Bit 9: Font contains oblique glyphs.
49    pub const OBLIQUE: Self = Self { bits: 0x0200 };
50}
51
52impl SelectionFlags {
53    ///  Returns an empty set of flags.
54    #[inline]
55    pub const fn empty() -> Self {
56        Self { bits: 0 }
57    }
58
59    /// Returns the set containing all flags.
60    #[inline]
61    pub const fn all() -> Self {
62        Self {
63            bits: Self::ITALIC.bits
64                | Self::UNDERSCORE.bits
65                | Self::NEGATIVE.bits
66                | Self::OUTLINED.bits
67                | Self::STRIKEOUT.bits
68                | Self::BOLD.bits
69                | Self::REGULAR.bits
70                | Self::USE_TYPO_METRICS.bits
71                | Self::WWS.bits
72                | Self::OBLIQUE.bits,
73        }
74    }
75
76    /// Returns the raw value of the flags currently stored.
77    #[inline]
78    pub const fn bits(&self) -> u16 {
79        self.bits
80    }
81
82    /// Convert from underlying bit representation, unless that
83    /// representation contains bits that do not correspond to a flag.
84    #[inline]
85    pub const fn from_bits(bits: u16) -> Option<Self> {
86        if (bits & !Self::all().bits()) == 0 {
87            Some(Self { bits })
88        } else {
89            None
90        }
91    }
92
93    /// Convert from underlying bit representation, dropping any bits
94    /// that do not correspond to flags.
95    #[inline]
96    pub const fn from_bits_truncate(bits: u16) -> Self {
97        Self {
98            bits: bits & Self::all().bits,
99        }
100    }
101
102    /// Returns `true` if no flags are currently stored.
103    #[inline]
104    pub const fn is_empty(&self) -> bool {
105        self.bits() == Self::empty().bits()
106    }
107
108    /// Returns `true` if there are flags common to both `self` and `other`.
109    #[inline]
110    pub const fn intersects(&self, other: Self) -> bool {
111        !(Self {
112            bits: self.bits & other.bits,
113        })
114        .is_empty()
115    }
116
117    /// Returns `true` if all of the flags in `other` are contained within `self`.
118    #[inline]
119    pub const fn contains(&self, other: Self) -> bool {
120        (self.bits & other.bits) == other.bits
121    }
122
123    /// Inserts the specified flags in-place.
124    #[inline]
125    pub fn insert(&mut self, other: Self) {
126        self.bits |= other.bits;
127    }
128
129    /// Removes the specified flags in-place.
130    #[inline]
131    pub fn remove(&mut self, other: Self) {
132        self.bits &= !other.bits;
133    }
134
135    /// Toggles the specified flags in-place.
136    #[inline]
137    pub fn toggle(&mut self, other: Self) {
138        self.bits ^= other.bits;
139    }
140
141    /// Returns the intersection between the flags in `self` and
142    /// `other`.
143    ///
144    /// Specifically, the returned set contains only the flags which are
145    /// present in *both* `self` *and* `other`.
146    ///
147    /// This is equivalent to using the `&` operator (e.g.
148    /// [`ops::BitAnd`]), as in `flags & other`.
149    ///
150    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
151    #[inline]
152    #[must_use]
153    pub const fn intersection(self, other: Self) -> Self {
154        Self {
155            bits: self.bits & other.bits,
156        }
157    }
158
159    /// Returns the union of between the flags in `self` and `other`.
160    ///
161    /// Specifically, the returned set contains all flags which are
162    /// present in *either* `self` *or* `other`, including any which are
163    /// present in both.
164    ///
165    /// This is equivalent to using the `|` operator (e.g.
166    /// [`ops::BitOr`]), as in `flags | other`.
167    ///
168    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
169    #[inline]
170    #[must_use]
171    pub const fn union(self, other: Self) -> Self {
172        Self {
173            bits: self.bits | other.bits,
174        }
175    }
176
177    /// Returns the difference between the flags in `self` and `other`.
178    ///
179    /// Specifically, the returned set contains all flags present in
180    /// `self`, except for the ones present in `other`.
181    ///
182    /// It is also conceptually equivalent to the "bit-clear" operation:
183    /// `flags & !other` (and this syntax is also supported).
184    ///
185    /// This is equivalent to using the `-` operator (e.g.
186    /// [`ops::Sub`]), as in `flags - other`.
187    ///
188    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
189    #[inline]
190    #[must_use]
191    pub const fn difference(self, other: Self) -> Self {
192        Self {
193            bits: self.bits & !other.bits,
194        }
195    }
196}
197
198impl std::ops::BitOr for SelectionFlags {
199    type Output = Self;
200
201    /// Returns the union of the two sets of flags.
202    #[inline]
203    fn bitor(self, other: SelectionFlags) -> Self {
204        Self {
205            bits: self.bits | other.bits,
206        }
207    }
208}
209
210impl std::ops::BitOrAssign for SelectionFlags {
211    /// Adds the set of flags.
212    #[inline]
213    fn bitor_assign(&mut self, other: Self) {
214        self.bits |= other.bits;
215    }
216}
217
218impl std::ops::BitXor for SelectionFlags {
219    type Output = Self;
220
221    /// Returns the left flags, but with all the right flags toggled.
222    #[inline]
223    fn bitxor(self, other: Self) -> Self {
224        Self {
225            bits: self.bits ^ other.bits,
226        }
227    }
228}
229
230impl std::ops::BitXorAssign for SelectionFlags {
231    /// Toggles the set of flags.
232    #[inline]
233    fn bitxor_assign(&mut self, other: Self) {
234        self.bits ^= other.bits;
235    }
236}
237
238impl std::ops::BitAnd for SelectionFlags {
239    type Output = Self;
240
241    /// Returns the intersection between the two sets of flags.
242    #[inline]
243    fn bitand(self, other: Self) -> Self {
244        Self {
245            bits: self.bits & other.bits,
246        }
247    }
248}
249
250impl std::ops::BitAndAssign for SelectionFlags {
251    /// Disables all flags disabled in the set.
252    #[inline]
253    fn bitand_assign(&mut self, other: Self) {
254        self.bits &= other.bits;
255    }
256}
257
258impl std::ops::Sub for SelectionFlags {
259    type Output = Self;
260
261    /// Returns the set difference of the two sets of flags.
262    #[inline]
263    fn sub(self, other: Self) -> Self {
264        Self {
265            bits: self.bits & !other.bits,
266        }
267    }
268}
269
270impl std::ops::SubAssign for SelectionFlags {
271    /// Disables all flags enabled in the set.
272    #[inline]
273    fn sub_assign(&mut self, other: Self) {
274        self.bits &= !other.bits;
275    }
276}
277
278impl std::ops::Not for SelectionFlags {
279    type Output = Self;
280
281    /// Returns the complement of this set of flags.
282    #[inline]
283    fn not(self) -> Self {
284        Self { bits: !self.bits } & Self::all()
285    }
286}
287
288impl std::fmt::Debug for SelectionFlags {
289    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
290        let members: &[(&str, Self)] = &[
291            ("ITALIC", Self::ITALIC),
292            ("UNDERSCORE", Self::UNDERSCORE),
293            ("NEGATIVE", Self::NEGATIVE),
294            ("OUTLINED", Self::OUTLINED),
295            ("STRIKEOUT", Self::STRIKEOUT),
296            ("BOLD", Self::BOLD),
297            ("REGULAR", Self::REGULAR),
298            ("USE_TYPO_METRICS", Self::USE_TYPO_METRICS),
299            ("WWS", Self::WWS),
300            ("OBLIQUE", Self::OBLIQUE),
301        ];
302        let mut first = true;
303        for (name, value) in members {
304            if self.contains(*value) {
305                if !first {
306                    f.write_str(" | ")?;
307                }
308                first = false;
309                f.write_str(name)?;
310            }
311        }
312        if first {
313            f.write_str("(empty)")?;
314        }
315        Ok(())
316    }
317}
318
319impl std::fmt::Binary for SelectionFlags {
320    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
321        std::fmt::Binary::fmt(&self.bits, f)
322    }
323}
324
325impl std::fmt::Octal for SelectionFlags {
326    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
327        std::fmt::Octal::fmt(&self.bits, f)
328    }
329}
330
331impl std::fmt::LowerHex for SelectionFlags {
332    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
333        std::fmt::LowerHex::fmt(&self.bits, f)
334    }
335}
336
337impl std::fmt::UpperHex for SelectionFlags {
338    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
339        std::fmt::UpperHex::fmt(&self.bits, f)
340    }
341}
342
343impl font_types::Scalar for SelectionFlags {
344    type Raw = <u16 as font_types::Scalar>::Raw;
345    fn to_raw(self) -> Self::Raw {
346        self.bits().to_raw()
347    }
348    fn from_raw(raw: Self::Raw) -> Self {
349        let t = <u16>::from_raw(raw);
350        Self::from_bits_truncate(t)
351    }
352}
353
354#[cfg(feature = "experimental_traverse")]
355impl<'a> From<SelectionFlags> for FieldType<'a> {
356    fn from(src: SelectionFlags) -> FieldType<'a> {
357        src.bits().into()
358    }
359}
360
361/// [`OS/2`](https://docs.microsoft.com/en-us/typography/opentype/spec/os2)
362#[derive(Debug, Clone, Copy)]
363#[doc(hidden)]
364pub struct Os2Marker {
365    panose_10_byte_len: usize,
366    ul_code_page_range_1_byte_start: Option<usize>,
367    ul_code_page_range_2_byte_start: Option<usize>,
368    sx_height_byte_start: Option<usize>,
369    s_cap_height_byte_start: Option<usize>,
370    us_default_char_byte_start: Option<usize>,
371    us_break_char_byte_start: Option<usize>,
372    us_max_context_byte_start: Option<usize>,
373    us_lower_optical_point_size_byte_start: Option<usize>,
374    us_upper_optical_point_size_byte_start: Option<usize>,
375}
376
377impl Os2Marker {
378    pub fn version_byte_range(&self) -> Range<usize> {
379        let start = 0;
380        start..start + u16::RAW_BYTE_LEN
381    }
382
383    pub fn x_avg_char_width_byte_range(&self) -> Range<usize> {
384        let start = self.version_byte_range().end;
385        start..start + i16::RAW_BYTE_LEN
386    }
387
388    pub fn us_weight_class_byte_range(&self) -> Range<usize> {
389        let start = self.x_avg_char_width_byte_range().end;
390        start..start + u16::RAW_BYTE_LEN
391    }
392
393    pub fn us_width_class_byte_range(&self) -> Range<usize> {
394        let start = self.us_weight_class_byte_range().end;
395        start..start + u16::RAW_BYTE_LEN
396    }
397
398    pub fn fs_type_byte_range(&self) -> Range<usize> {
399        let start = self.us_width_class_byte_range().end;
400        start..start + u16::RAW_BYTE_LEN
401    }
402
403    pub fn y_subscript_x_size_byte_range(&self) -> Range<usize> {
404        let start = self.fs_type_byte_range().end;
405        start..start + i16::RAW_BYTE_LEN
406    }
407
408    pub fn y_subscript_y_size_byte_range(&self) -> Range<usize> {
409        let start = self.y_subscript_x_size_byte_range().end;
410        start..start + i16::RAW_BYTE_LEN
411    }
412
413    pub fn y_subscript_x_offset_byte_range(&self) -> Range<usize> {
414        let start = self.y_subscript_y_size_byte_range().end;
415        start..start + i16::RAW_BYTE_LEN
416    }
417
418    pub fn y_subscript_y_offset_byte_range(&self) -> Range<usize> {
419        let start = self.y_subscript_x_offset_byte_range().end;
420        start..start + i16::RAW_BYTE_LEN
421    }
422
423    pub fn y_superscript_x_size_byte_range(&self) -> Range<usize> {
424        let start = self.y_subscript_y_offset_byte_range().end;
425        start..start + i16::RAW_BYTE_LEN
426    }
427
428    pub fn y_superscript_y_size_byte_range(&self) -> Range<usize> {
429        let start = self.y_superscript_x_size_byte_range().end;
430        start..start + i16::RAW_BYTE_LEN
431    }
432
433    pub fn y_superscript_x_offset_byte_range(&self) -> Range<usize> {
434        let start = self.y_superscript_y_size_byte_range().end;
435        start..start + i16::RAW_BYTE_LEN
436    }
437
438    pub fn y_superscript_y_offset_byte_range(&self) -> Range<usize> {
439        let start = self.y_superscript_x_offset_byte_range().end;
440        start..start + i16::RAW_BYTE_LEN
441    }
442
443    pub fn y_strikeout_size_byte_range(&self) -> Range<usize> {
444        let start = self.y_superscript_y_offset_byte_range().end;
445        start..start + i16::RAW_BYTE_LEN
446    }
447
448    pub fn y_strikeout_position_byte_range(&self) -> Range<usize> {
449        let start = self.y_strikeout_size_byte_range().end;
450        start..start + i16::RAW_BYTE_LEN
451    }
452
453    pub fn s_family_class_byte_range(&self) -> Range<usize> {
454        let start = self.y_strikeout_position_byte_range().end;
455        start..start + i16::RAW_BYTE_LEN
456    }
457
458    pub fn panose_10_byte_range(&self) -> Range<usize> {
459        let start = self.s_family_class_byte_range().end;
460        start..start + self.panose_10_byte_len
461    }
462
463    pub fn ul_unicode_range_1_byte_range(&self) -> Range<usize> {
464        let start = self.panose_10_byte_range().end;
465        start..start + u32::RAW_BYTE_LEN
466    }
467
468    pub fn ul_unicode_range_2_byte_range(&self) -> Range<usize> {
469        let start = self.ul_unicode_range_1_byte_range().end;
470        start..start + u32::RAW_BYTE_LEN
471    }
472
473    pub fn ul_unicode_range_3_byte_range(&self) -> Range<usize> {
474        let start = self.ul_unicode_range_2_byte_range().end;
475        start..start + u32::RAW_BYTE_LEN
476    }
477
478    pub fn ul_unicode_range_4_byte_range(&self) -> Range<usize> {
479        let start = self.ul_unicode_range_3_byte_range().end;
480        start..start + u32::RAW_BYTE_LEN
481    }
482
483    pub fn ach_vend_id_byte_range(&self) -> Range<usize> {
484        let start = self.ul_unicode_range_4_byte_range().end;
485        start..start + Tag::RAW_BYTE_LEN
486    }
487
488    pub fn fs_selection_byte_range(&self) -> Range<usize> {
489        let start = self.ach_vend_id_byte_range().end;
490        start..start + SelectionFlags::RAW_BYTE_LEN
491    }
492
493    pub fn us_first_char_index_byte_range(&self) -> Range<usize> {
494        let start = self.fs_selection_byte_range().end;
495        start..start + u16::RAW_BYTE_LEN
496    }
497
498    pub fn us_last_char_index_byte_range(&self) -> Range<usize> {
499        let start = self.us_first_char_index_byte_range().end;
500        start..start + u16::RAW_BYTE_LEN
501    }
502
503    pub fn s_typo_ascender_byte_range(&self) -> Range<usize> {
504        let start = self.us_last_char_index_byte_range().end;
505        start..start + i16::RAW_BYTE_LEN
506    }
507
508    pub fn s_typo_descender_byte_range(&self) -> Range<usize> {
509        let start = self.s_typo_ascender_byte_range().end;
510        start..start + i16::RAW_BYTE_LEN
511    }
512
513    pub fn s_typo_line_gap_byte_range(&self) -> Range<usize> {
514        let start = self.s_typo_descender_byte_range().end;
515        start..start + i16::RAW_BYTE_LEN
516    }
517
518    pub fn us_win_ascent_byte_range(&self) -> Range<usize> {
519        let start = self.s_typo_line_gap_byte_range().end;
520        start..start + u16::RAW_BYTE_LEN
521    }
522
523    pub fn us_win_descent_byte_range(&self) -> Range<usize> {
524        let start = self.us_win_ascent_byte_range().end;
525        start..start + u16::RAW_BYTE_LEN
526    }
527
528    pub fn ul_code_page_range_1_byte_range(&self) -> Option<Range<usize>> {
529        let start = self.ul_code_page_range_1_byte_start?;
530        Some(start..start + u32::RAW_BYTE_LEN)
531    }
532
533    pub fn ul_code_page_range_2_byte_range(&self) -> Option<Range<usize>> {
534        let start = self.ul_code_page_range_2_byte_start?;
535        Some(start..start + u32::RAW_BYTE_LEN)
536    }
537
538    pub fn sx_height_byte_range(&self) -> Option<Range<usize>> {
539        let start = self.sx_height_byte_start?;
540        Some(start..start + i16::RAW_BYTE_LEN)
541    }
542
543    pub fn s_cap_height_byte_range(&self) -> Option<Range<usize>> {
544        let start = self.s_cap_height_byte_start?;
545        Some(start..start + i16::RAW_BYTE_LEN)
546    }
547
548    pub fn us_default_char_byte_range(&self) -> Option<Range<usize>> {
549        let start = self.us_default_char_byte_start?;
550        Some(start..start + u16::RAW_BYTE_LEN)
551    }
552
553    pub fn us_break_char_byte_range(&self) -> Option<Range<usize>> {
554        let start = self.us_break_char_byte_start?;
555        Some(start..start + u16::RAW_BYTE_LEN)
556    }
557
558    pub fn us_max_context_byte_range(&self) -> Option<Range<usize>> {
559        let start = self.us_max_context_byte_start?;
560        Some(start..start + u16::RAW_BYTE_LEN)
561    }
562
563    pub fn us_lower_optical_point_size_byte_range(&self) -> Option<Range<usize>> {
564        let start = self.us_lower_optical_point_size_byte_start?;
565        Some(start..start + u16::RAW_BYTE_LEN)
566    }
567
568    pub fn us_upper_optical_point_size_byte_range(&self) -> Option<Range<usize>> {
569        let start = self.us_upper_optical_point_size_byte_start?;
570        Some(start..start + u16::RAW_BYTE_LEN)
571    }
572}
573
574impl MinByteRange for Os2Marker {
575    fn min_byte_range(&self) -> Range<usize> {
576        0..self.us_win_descent_byte_range().end
577    }
578}
579
580impl TopLevelTable for Os2<'_> {
581    /// `OS/2`
582    const TAG: Tag = Tag::new(b"OS/2");
583}
584
585impl<'a> FontRead<'a> for Os2<'a> {
586    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
587        let mut cursor = data.cursor();
588        let version: u16 = cursor.read()?;
589        cursor.advance::<i16>();
590        cursor.advance::<u16>();
591        cursor.advance::<u16>();
592        cursor.advance::<u16>();
593        cursor.advance::<i16>();
594        cursor.advance::<i16>();
595        cursor.advance::<i16>();
596        cursor.advance::<i16>();
597        cursor.advance::<i16>();
598        cursor.advance::<i16>();
599        cursor.advance::<i16>();
600        cursor.advance::<i16>();
601        cursor.advance::<i16>();
602        cursor.advance::<i16>();
603        cursor.advance::<i16>();
604        let panose_10_byte_len = (10_usize)
605            .checked_mul(u8::RAW_BYTE_LEN)
606            .ok_or(ReadError::OutOfBounds)?;
607        cursor.advance_by(panose_10_byte_len);
608        cursor.advance::<u32>();
609        cursor.advance::<u32>();
610        cursor.advance::<u32>();
611        cursor.advance::<u32>();
612        cursor.advance::<Tag>();
613        cursor.advance::<SelectionFlags>();
614        cursor.advance::<u16>();
615        cursor.advance::<u16>();
616        cursor.advance::<i16>();
617        cursor.advance::<i16>();
618        cursor.advance::<i16>();
619        cursor.advance::<u16>();
620        cursor.advance::<u16>();
621        let ul_code_page_range_1_byte_start = version
622            .compatible(1u16)
623            .then(|| cursor.position())
624            .transpose()?;
625        version.compatible(1u16).then(|| cursor.advance::<u32>());
626        let ul_code_page_range_2_byte_start = version
627            .compatible(1u16)
628            .then(|| cursor.position())
629            .transpose()?;
630        version.compatible(1u16).then(|| cursor.advance::<u32>());
631        let sx_height_byte_start = version
632            .compatible(2u16)
633            .then(|| cursor.position())
634            .transpose()?;
635        version.compatible(2u16).then(|| cursor.advance::<i16>());
636        let s_cap_height_byte_start = version
637            .compatible(2u16)
638            .then(|| cursor.position())
639            .transpose()?;
640        version.compatible(2u16).then(|| cursor.advance::<i16>());
641        let us_default_char_byte_start = version
642            .compatible(2u16)
643            .then(|| cursor.position())
644            .transpose()?;
645        version.compatible(2u16).then(|| cursor.advance::<u16>());
646        let us_break_char_byte_start = version
647            .compatible(2u16)
648            .then(|| cursor.position())
649            .transpose()?;
650        version.compatible(2u16).then(|| cursor.advance::<u16>());
651        let us_max_context_byte_start = version
652            .compatible(2u16)
653            .then(|| cursor.position())
654            .transpose()?;
655        version.compatible(2u16).then(|| cursor.advance::<u16>());
656        let us_lower_optical_point_size_byte_start = version
657            .compatible(5u16)
658            .then(|| cursor.position())
659            .transpose()?;
660        version.compatible(5u16).then(|| cursor.advance::<u16>());
661        let us_upper_optical_point_size_byte_start = version
662            .compatible(5u16)
663            .then(|| cursor.position())
664            .transpose()?;
665        version.compatible(5u16).then(|| cursor.advance::<u16>());
666        cursor.finish(Os2Marker {
667            panose_10_byte_len,
668            ul_code_page_range_1_byte_start,
669            ul_code_page_range_2_byte_start,
670            sx_height_byte_start,
671            s_cap_height_byte_start,
672            us_default_char_byte_start,
673            us_break_char_byte_start,
674            us_max_context_byte_start,
675            us_lower_optical_point_size_byte_start,
676            us_upper_optical_point_size_byte_start,
677        })
678    }
679}
680
681/// [`OS/2`](https://docs.microsoft.com/en-us/typography/opentype/spec/os2)
682pub type Os2<'a> = TableRef<'a, Os2Marker>;
683
684#[allow(clippy::needless_lifetimes)]
685impl<'a> Os2<'a> {
686    pub fn version(&self) -> u16 {
687        let range = self.shape.version_byte_range();
688        self.data.read_at(range.start).unwrap()
689    }
690
691    /// [Average weighted escapement](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#xavgcharwidth).
692    ///
693    /// The Average Character Width parameter specifies the arithmetic average
694    /// of the escapement (width) of all non-zero width glyphs in the font.
695    pub fn x_avg_char_width(&self) -> i16 {
696        let range = self.shape.x_avg_char_width_byte_range();
697        self.data.read_at(range.start).unwrap()
698    }
699
700    /// [Weight class](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass).
701    ///
702    /// Indicates the visual weight (degree of blackness or thickness of
703    /// strokes) of the characters in the font. Values from 1 to 1000 are valid.
704    pub fn us_weight_class(&self) -> u16 {
705        let range = self.shape.us_weight_class_byte_range();
706        self.data.read_at(range.start).unwrap()
707    }
708
709    /// [Width class](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass).
710    ///
711    /// Indicates a relative change from the normal aspect ratio (width to height
712    /// ratio) as specified by a font designer for the glyphs in a font.
713    pub fn us_width_class(&self) -> u16 {
714        let range = self.shape.us_width_class_byte_range();
715        self.data.read_at(range.start).unwrap()
716    }
717
718    /// [Type flags](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fstype).
719    ///
720    /// Indicates font embedding licensing rights for the font.
721    pub fn fs_type(&self) -> u16 {
722        let range = self.shape.fs_type_byte_range();
723        self.data.read_at(range.start).unwrap()
724    }
725
726    /// The recommended horizontal size in font design units for subscripts for
727    /// this font.
728    pub fn y_subscript_x_size(&self) -> i16 {
729        let range = self.shape.y_subscript_x_size_byte_range();
730        self.data.read_at(range.start).unwrap()
731    }
732
733    /// The recommended vertical size in font design units for subscripts for
734    /// this font.
735    pub fn y_subscript_y_size(&self) -> i16 {
736        let range = self.shape.y_subscript_y_size_byte_range();
737        self.data.read_at(range.start).unwrap()
738    }
739
740    /// The recommended horizontal offset in font design units for subscripts
741    /// for this font.
742    pub fn y_subscript_x_offset(&self) -> i16 {
743        let range = self.shape.y_subscript_x_offset_byte_range();
744        self.data.read_at(range.start).unwrap()
745    }
746
747    /// The recommended vertical offset in font design units for subscripts
748    /// for this font.
749    pub fn y_subscript_y_offset(&self) -> i16 {
750        let range = self.shape.y_subscript_y_offset_byte_range();
751        self.data.read_at(range.start).unwrap()
752    }
753
754    /// The recommended horizontal size in font design units for superscripts
755    /// for this font.
756    pub fn y_superscript_x_size(&self) -> i16 {
757        let range = self.shape.y_superscript_x_size_byte_range();
758        self.data.read_at(range.start).unwrap()
759    }
760
761    /// The recommended vertical size in font design units for superscripts
762    /// for this font.
763    pub fn y_superscript_y_size(&self) -> i16 {
764        let range = self.shape.y_superscript_y_size_byte_range();
765        self.data.read_at(range.start).unwrap()
766    }
767
768    /// The recommended horizontal offset in font design units for superscripts
769    /// for this font.
770    pub fn y_superscript_x_offset(&self) -> i16 {
771        let range = self.shape.y_superscript_x_offset_byte_range();
772        self.data.read_at(range.start).unwrap()
773    }
774
775    /// The recommended vertical offset in font design units for superscripts
776    /// for this font.
777    pub fn y_superscript_y_offset(&self) -> i16 {
778        let range = self.shape.y_superscript_y_offset_byte_range();
779        self.data.read_at(range.start).unwrap()
780    }
781
782    /// Thickness of the strikeout stroke in font design units.
783    pub fn y_strikeout_size(&self) -> i16 {
784        let range = self.shape.y_strikeout_size_byte_range();
785        self.data.read_at(range.start).unwrap()
786    }
787
788    /// The position of the top of the strikeout stroke relative to the
789    /// baseline in font design units.
790    pub fn y_strikeout_position(&self) -> i16 {
791        let range = self.shape.y_strikeout_position_byte_range();
792        self.data.read_at(range.start).unwrap()
793    }
794
795    /// [Font-family class and subclass](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#sfamilyclass).
796    /// This parameter is a classification of font-family design.
797    pub fn s_family_class(&self) -> i16 {
798        let range = self.shape.s_family_class_byte_range();
799        self.data.read_at(range.start).unwrap()
800    }
801
802    /// [PANOSE classification number](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#panose).
803    ///
804    /// Additional specifications are required for PANOSE to classify non-Latin
805    /// character sets.
806    pub fn panose_10(&self) -> &'a [u8] {
807        let range = self.shape.panose_10_byte_range();
808        self.data.read_array(range).unwrap()
809    }
810
811    /// [Unicode Character Range](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1-bits-031ulunicoderange2-bits-3263ulunicoderange3-bits-6495ulunicoderange4-bits-96127).
812    ///
813    /// Unicode Character Range (bits 0-31).
814    pub fn ul_unicode_range_1(&self) -> u32 {
815        let range = self.shape.ul_unicode_range_1_byte_range();
816        self.data.read_at(range.start).unwrap()
817    }
818
819    /// Unicode Character Range (bits 32-63).
820    pub fn ul_unicode_range_2(&self) -> u32 {
821        let range = self.shape.ul_unicode_range_2_byte_range();
822        self.data.read_at(range.start).unwrap()
823    }
824
825    /// Unicode Character Range (bits 64-95).
826    pub fn ul_unicode_range_3(&self) -> u32 {
827        let range = self.shape.ul_unicode_range_3_byte_range();
828        self.data.read_at(range.start).unwrap()
829    }
830
831    /// Unicode Character Range (bits 96-127).
832    pub fn ul_unicode_range_4(&self) -> u32 {
833        let range = self.shape.ul_unicode_range_4_byte_range();
834        self.data.read_at(range.start).unwrap()
835    }
836
837    /// [Font Vendor Identification](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#achvendid).
838    ///
839    /// The four-character identifier for the vendor of the given type face.
840    pub fn ach_vend_id(&self) -> Tag {
841        let range = self.shape.ach_vend_id_byte_range();
842        self.data.read_at(range.start).unwrap()
843    }
844
845    /// [Font selection flags](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fsselection).
846    ///
847    /// Contains information concerning the nature of the font patterns.
848    pub fn fs_selection(&self) -> SelectionFlags {
849        let range = self.shape.fs_selection_byte_range();
850        self.data.read_at(range.start).unwrap()
851    }
852
853    /// The minimum Unicode index (character code) in this font.
854    pub fn us_first_char_index(&self) -> u16 {
855        let range = self.shape.us_first_char_index_byte_range();
856        self.data.read_at(range.start).unwrap()
857    }
858
859    /// The maximum Unicode index (character code) in this font.
860    pub fn us_last_char_index(&self) -> u16 {
861        let range = self.shape.us_last_char_index_byte_range();
862        self.data.read_at(range.start).unwrap()
863    }
864
865    /// The typographic ascender for this font.
866    pub fn s_typo_ascender(&self) -> i16 {
867        let range = self.shape.s_typo_ascender_byte_range();
868        self.data.read_at(range.start).unwrap()
869    }
870
871    /// The typographic descender for this font.
872    pub fn s_typo_descender(&self) -> i16 {
873        let range = self.shape.s_typo_descender_byte_range();
874        self.data.read_at(range.start).unwrap()
875    }
876
877    /// The typographic line gap for this font.
878    pub fn s_typo_line_gap(&self) -> i16 {
879        let range = self.shape.s_typo_line_gap_byte_range();
880        self.data.read_at(range.start).unwrap()
881    }
882
883    /// The “Windows ascender” metric.
884    ///
885    /// This should be used to specify the height above the baseline for a
886    /// clipping region.
887    pub fn us_win_ascent(&self) -> u16 {
888        let range = self.shape.us_win_ascent_byte_range();
889        self.data.read_at(range.start).unwrap()
890    }
891
892    /// The “Windows descender” metric.
893    ///
894    /// This should be used to specify the vertical extent below the baseline
895    /// for a clipping region.
896    pub fn us_win_descent(&self) -> u16 {
897        let range = self.shape.us_win_descent_byte_range();
898        self.data.read_at(range.start).unwrap()
899    }
900
901    /// Code page character range bits 0-31.
902    pub fn ul_code_page_range_1(&self) -> Option<u32> {
903        let range = self.shape.ul_code_page_range_1_byte_range()?;
904        Some(self.data.read_at(range.start).unwrap())
905    }
906
907    /// Code page character range bits 32-63.
908    pub fn ul_code_page_range_2(&self) -> Option<u32> {
909        let range = self.shape.ul_code_page_range_2_byte_range()?;
910        Some(self.data.read_at(range.start).unwrap())
911    }
912
913    /// This metric specifies the distance between the baseline and the
914    /// approximate height of non-ascending lowercase letters measured in
915    /// FUnits.
916    pub fn sx_height(&self) -> Option<i16> {
917        let range = self.shape.sx_height_byte_range()?;
918        Some(self.data.read_at(range.start).unwrap())
919    }
920
921    /// This metric specifies the distance between the baseline and the
922    /// approximate height of uppercase letters measured in FUnits.
923    pub fn s_cap_height(&self) -> Option<i16> {
924        let range = self.shape.s_cap_height_byte_range()?;
925        Some(self.data.read_at(range.start).unwrap())
926    }
927
928    /// This is the Unicode code point, in UTF-16 encoding, of a character that
929    /// can be used for a default glyph.
930    pub fn us_default_char(&self) -> Option<u16> {
931        let range = self.shape.us_default_char_byte_range()?;
932        Some(self.data.read_at(range.start).unwrap())
933    }
934
935    /// his is the Unicode code point, in UTF-16 encoding, of a character that
936    /// can be used as a default break character.
937    pub fn us_break_char(&self) -> Option<u16> {
938        let range = self.shape.us_break_char_byte_range()?;
939        Some(self.data.read_at(range.start).unwrap())
940    }
941
942    /// This field is used for fonts with multiple optical styles.
943    pub fn us_max_context(&self) -> Option<u16> {
944        let range = self.shape.us_max_context_byte_range()?;
945        Some(self.data.read_at(range.start).unwrap())
946    }
947
948    /// This field is used for fonts with multiple optical styles.
949    pub fn us_lower_optical_point_size(&self) -> Option<u16> {
950        let range = self.shape.us_lower_optical_point_size_byte_range()?;
951        Some(self.data.read_at(range.start).unwrap())
952    }
953
954    /// This field is used for fonts with multiple optical styles.
955    pub fn us_upper_optical_point_size(&self) -> Option<u16> {
956        let range = self.shape.us_upper_optical_point_size_byte_range()?;
957        Some(self.data.read_at(range.start).unwrap())
958    }
959}
960
961#[cfg(feature = "experimental_traverse")]
962impl<'a> SomeTable<'a> for Os2<'a> {
963    fn type_name(&self) -> &str {
964        "Os2"
965    }
966    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
967        let version = self.version();
968        match idx {
969            0usize => Some(Field::new("version", self.version())),
970            1usize => Some(Field::new("x_avg_char_width", self.x_avg_char_width())),
971            2usize => Some(Field::new("us_weight_class", self.us_weight_class())),
972            3usize => Some(Field::new("us_width_class", self.us_width_class())),
973            4usize => Some(Field::new("fs_type", self.fs_type())),
974            5usize => Some(Field::new("y_subscript_x_size", self.y_subscript_x_size())),
975            6usize => Some(Field::new("y_subscript_y_size", self.y_subscript_y_size())),
976            7usize => Some(Field::new(
977                "y_subscript_x_offset",
978                self.y_subscript_x_offset(),
979            )),
980            8usize => Some(Field::new(
981                "y_subscript_y_offset",
982                self.y_subscript_y_offset(),
983            )),
984            9usize => Some(Field::new(
985                "y_superscript_x_size",
986                self.y_superscript_x_size(),
987            )),
988            10usize => Some(Field::new(
989                "y_superscript_y_size",
990                self.y_superscript_y_size(),
991            )),
992            11usize => Some(Field::new(
993                "y_superscript_x_offset",
994                self.y_superscript_x_offset(),
995            )),
996            12usize => Some(Field::new(
997                "y_superscript_y_offset",
998                self.y_superscript_y_offset(),
999            )),
1000            13usize => Some(Field::new("y_strikeout_size", self.y_strikeout_size())),
1001            14usize => Some(Field::new(
1002                "y_strikeout_position",
1003                self.y_strikeout_position(),
1004            )),
1005            15usize => Some(Field::new("s_family_class", self.s_family_class())),
1006            16usize => Some(Field::new("panose_10", self.panose_10())),
1007            17usize => Some(Field::new("ul_unicode_range_1", self.ul_unicode_range_1())),
1008            18usize => Some(Field::new("ul_unicode_range_2", self.ul_unicode_range_2())),
1009            19usize => Some(Field::new("ul_unicode_range_3", self.ul_unicode_range_3())),
1010            20usize => Some(Field::new("ul_unicode_range_4", self.ul_unicode_range_4())),
1011            21usize => Some(Field::new("ach_vend_id", self.ach_vend_id())),
1012            22usize => Some(Field::new("fs_selection", self.fs_selection())),
1013            23usize => Some(Field::new(
1014                "us_first_char_index",
1015                self.us_first_char_index(),
1016            )),
1017            24usize => Some(Field::new("us_last_char_index", self.us_last_char_index())),
1018            25usize => Some(Field::new("s_typo_ascender", self.s_typo_ascender())),
1019            26usize => Some(Field::new("s_typo_descender", self.s_typo_descender())),
1020            27usize => Some(Field::new("s_typo_line_gap", self.s_typo_line_gap())),
1021            28usize => Some(Field::new("us_win_ascent", self.us_win_ascent())),
1022            29usize => Some(Field::new("us_win_descent", self.us_win_descent())),
1023            30usize if version.compatible(1u16) => Some(Field::new(
1024                "ul_code_page_range_1",
1025                self.ul_code_page_range_1().unwrap(),
1026            )),
1027            31usize if version.compatible(1u16) => Some(Field::new(
1028                "ul_code_page_range_2",
1029                self.ul_code_page_range_2().unwrap(),
1030            )),
1031            32usize if version.compatible(2u16) => {
1032                Some(Field::new("sx_height", self.sx_height().unwrap()))
1033            }
1034            33usize if version.compatible(2u16) => {
1035                Some(Field::new("s_cap_height", self.s_cap_height().unwrap()))
1036            }
1037            34usize if version.compatible(2u16) => Some(Field::new(
1038                "us_default_char",
1039                self.us_default_char().unwrap(),
1040            )),
1041            35usize if version.compatible(2u16) => {
1042                Some(Field::new("us_break_char", self.us_break_char().unwrap()))
1043            }
1044            36usize if version.compatible(2u16) => {
1045                Some(Field::new("us_max_context", self.us_max_context().unwrap()))
1046            }
1047            37usize if version.compatible(5u16) => Some(Field::new(
1048                "us_lower_optical_point_size",
1049                self.us_lower_optical_point_size().unwrap(),
1050            )),
1051            38usize if version.compatible(5u16) => Some(Field::new(
1052                "us_upper_optical_point_size",
1053                self.us_upper_optical_point_size().unwrap(),
1054            )),
1055            _ => None,
1056        }
1057    }
1058}
1059
1060#[cfg(feature = "experimental_traverse")]
1061#[allow(clippy::needless_lifetimes)]
1062impl<'a> std::fmt::Debug for Os2<'a> {
1063    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1064        (self as &dyn SomeTable<'a>).fmt(f)
1065    }
1066}