Skip to main content

read_fonts/generated/
generated_sbix.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/// Sbix header flags.
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 HeaderFlags {
13    bits: u16,
14}
15
16impl HeaderFlags {
17    /// Bit 0: Set to 1.
18    pub const ALWAYS_SET: Self = Self { bits: 0x0001 };
19
20    /// Bit 1: Draw outlines.
21    pub const DRAW_OUTLINES: Self = Self { bits: 0x0002 };
22}
23
24impl HeaderFlags {
25    ///  Returns an empty set of flags.
26    #[inline]
27    pub const fn empty() -> Self {
28        Self { bits: 0 }
29    }
30
31    /// Returns the set containing all flags.
32    #[inline]
33    pub const fn all() -> Self {
34        Self {
35            bits: Self::ALWAYS_SET.bits | Self::DRAW_OUTLINES.bits,
36        }
37    }
38
39    /// Returns the raw value of the flags currently stored.
40    #[inline]
41    pub const fn bits(&self) -> u16 {
42        self.bits
43    }
44
45    /// Convert from underlying bit representation, unless that
46    /// representation contains bits that do not correspond to a flag.
47    #[inline]
48    pub const fn from_bits(bits: u16) -> Option<Self> {
49        if (bits & !Self::all().bits()) == 0 {
50            Some(Self { bits })
51        } else {
52            None
53        }
54    }
55
56    /// Convert from underlying bit representation, dropping any bits
57    /// that do not correspond to flags.
58    #[inline]
59    pub const fn from_bits_truncate(bits: u16) -> Self {
60        Self {
61            bits: bits & Self::all().bits,
62        }
63    }
64
65    /// Returns `true` if no flags are currently stored.
66    #[inline]
67    pub const fn is_empty(&self) -> bool {
68        self.bits() == Self::empty().bits()
69    }
70
71    /// Returns `true` if there are flags common to both `self` and `other`.
72    #[inline]
73    pub const fn intersects(&self, other: Self) -> bool {
74        !(Self {
75            bits: self.bits & other.bits,
76        })
77        .is_empty()
78    }
79
80    /// Returns `true` if all of the flags in `other` are contained within `self`.
81    #[inline]
82    pub const fn contains(&self, other: Self) -> bool {
83        (self.bits & other.bits) == other.bits
84    }
85
86    /// Inserts the specified flags in-place.
87    #[inline]
88    pub fn insert(&mut self, other: Self) {
89        self.bits |= other.bits;
90    }
91
92    /// Removes the specified flags in-place.
93    #[inline]
94    pub fn remove(&mut self, other: Self) {
95        self.bits &= !other.bits;
96    }
97
98    /// Toggles the specified flags in-place.
99    #[inline]
100    pub fn toggle(&mut self, other: Self) {
101        self.bits ^= other.bits;
102    }
103
104    /// Returns the intersection between the flags in `self` and
105    /// `other`.
106    ///
107    /// Specifically, the returned set contains only the flags which are
108    /// present in *both* `self` *and* `other`.
109    ///
110    /// This is equivalent to using the `&` operator (e.g.
111    /// [`ops::BitAnd`]), as in `flags & other`.
112    ///
113    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
114    #[inline]
115    #[must_use]
116    pub const fn intersection(self, other: Self) -> Self {
117        Self {
118            bits: self.bits & other.bits,
119        }
120    }
121
122    /// Returns the union of between the flags in `self` and `other`.
123    ///
124    /// Specifically, the returned set contains all flags which are
125    /// present in *either* `self` *or* `other`, including any which are
126    /// present in both.
127    ///
128    /// This is equivalent to using the `|` operator (e.g.
129    /// [`ops::BitOr`]), as in `flags | other`.
130    ///
131    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
132    #[inline]
133    #[must_use]
134    pub const fn union(self, other: Self) -> Self {
135        Self {
136            bits: self.bits | other.bits,
137        }
138    }
139
140    /// Returns the difference between the flags in `self` and `other`.
141    ///
142    /// Specifically, the returned set contains all flags present in
143    /// `self`, except for the ones present in `other`.
144    ///
145    /// It is also conceptually equivalent to the "bit-clear" operation:
146    /// `flags & !other` (and this syntax is also supported).
147    ///
148    /// This is equivalent to using the `-` operator (e.g.
149    /// [`ops::Sub`]), as in `flags - other`.
150    ///
151    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
152    #[inline]
153    #[must_use]
154    pub const fn difference(self, other: Self) -> Self {
155        Self {
156            bits: self.bits & !other.bits,
157        }
158    }
159}
160
161impl std::ops::BitOr for HeaderFlags {
162    type Output = Self;
163
164    /// Returns the union of the two sets of flags.
165    #[inline]
166    fn bitor(self, other: HeaderFlags) -> Self {
167        Self {
168            bits: self.bits | other.bits,
169        }
170    }
171}
172
173impl std::ops::BitOrAssign for HeaderFlags {
174    /// Adds the set of flags.
175    #[inline]
176    fn bitor_assign(&mut self, other: Self) {
177        self.bits |= other.bits;
178    }
179}
180
181impl std::ops::BitXor for HeaderFlags {
182    type Output = Self;
183
184    /// Returns the left flags, but with all the right flags toggled.
185    #[inline]
186    fn bitxor(self, other: Self) -> Self {
187        Self {
188            bits: self.bits ^ other.bits,
189        }
190    }
191}
192
193impl std::ops::BitXorAssign for HeaderFlags {
194    /// Toggles the set of flags.
195    #[inline]
196    fn bitxor_assign(&mut self, other: Self) {
197        self.bits ^= other.bits;
198    }
199}
200
201impl std::ops::BitAnd for HeaderFlags {
202    type Output = Self;
203
204    /// Returns the intersection between the two sets of flags.
205    #[inline]
206    fn bitand(self, other: Self) -> Self {
207        Self {
208            bits: self.bits & other.bits,
209        }
210    }
211}
212
213impl std::ops::BitAndAssign for HeaderFlags {
214    /// Disables all flags disabled in the set.
215    #[inline]
216    fn bitand_assign(&mut self, other: Self) {
217        self.bits &= other.bits;
218    }
219}
220
221impl std::ops::Sub for HeaderFlags {
222    type Output = Self;
223
224    /// Returns the set difference of the two sets of flags.
225    #[inline]
226    fn sub(self, other: Self) -> Self {
227        Self {
228            bits: self.bits & !other.bits,
229        }
230    }
231}
232
233impl std::ops::SubAssign for HeaderFlags {
234    /// Disables all flags enabled in the set.
235    #[inline]
236    fn sub_assign(&mut self, other: Self) {
237        self.bits &= !other.bits;
238    }
239}
240
241impl std::ops::Not for HeaderFlags {
242    type Output = Self;
243
244    /// Returns the complement of this set of flags.
245    #[inline]
246    fn not(self) -> Self {
247        Self { bits: !self.bits } & Self::all()
248    }
249}
250
251impl std::fmt::Debug for HeaderFlags {
252    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
253        let members: &[(&str, Self)] = &[
254            ("ALWAYS_SET", Self::ALWAYS_SET),
255            ("DRAW_OUTLINES", Self::DRAW_OUTLINES),
256        ];
257        let mut first = true;
258        for (name, value) in members {
259            if self.contains(*value) {
260                if !first {
261                    f.write_str(" | ")?;
262                }
263                first = false;
264                f.write_str(name)?;
265            }
266        }
267        if first {
268            f.write_str("(empty)")?;
269        }
270        Ok(())
271    }
272}
273
274impl std::fmt::Binary for HeaderFlags {
275    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
276        std::fmt::Binary::fmt(&self.bits, f)
277    }
278}
279
280impl std::fmt::Octal for HeaderFlags {
281    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
282        std::fmt::Octal::fmt(&self.bits, f)
283    }
284}
285
286impl std::fmt::LowerHex for HeaderFlags {
287    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
288        std::fmt::LowerHex::fmt(&self.bits, f)
289    }
290}
291
292impl std::fmt::UpperHex for HeaderFlags {
293    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
294        std::fmt::UpperHex::fmt(&self.bits, f)
295    }
296}
297
298impl font_types::Scalar for HeaderFlags {
299    type Raw = <u16 as font_types::Scalar>::Raw;
300    fn to_raw(self) -> Self::Raw {
301        self.bits().to_raw()
302    }
303    fn from_raw(raw: Self::Raw) -> Self {
304        let t = <u16>::from_raw(raw);
305        Self::from_bits_truncate(t)
306    }
307}
308
309#[cfg(feature = "experimental_traverse")]
310impl<'a> From<HeaderFlags> for FieldType<'a> {
311    fn from(src: HeaderFlags) -> FieldType<'a> {
312        src.bits().into()
313    }
314}
315
316impl<'a> MinByteRange<'a> for Sbix<'a> {
317    fn min_byte_range(&self) -> Range<usize> {
318        0..self.strike_offsets_byte_range().end
319    }
320    fn min_table_bytes(&self) -> &'a [u8] {
321        let range = self.min_byte_range();
322        self.data.as_bytes().get(range).unwrap_or_default()
323    }
324}
325
326impl TopLevelTable for Sbix<'_> {
327    /// `sbix`
328    const TAG: Tag = Tag::new(b"sbix");
329}
330
331impl ReadArgs for Sbix<'_> {
332    type Args = u16;
333}
334
335impl<'a> FontReadWithArgs<'a> for Sbix<'a> {
336    fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
337        let num_glyphs = *args;
338
339        #[allow(clippy::absurd_extreme_comparisons)]
340        if data.len() < Self::MIN_SIZE {
341            return Err(ReadError::OutOfBounds);
342        }
343        Ok(Self { data, num_glyphs })
344    }
345}
346
347impl<'a> Sbix<'a> {
348    /// A constructor that requires additional arguments.
349    ///
350    /// This type requires some external state in order to be
351    /// parsed.
352    pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
353        let args = num_glyphs;
354        Self::read_with_args(data, &args)
355    }
356}
357
358/// The [sbix (Standard Bitmap Graphics)](https://docs.microsoft.com/en-us/typography/opentype/spec/sbix) table
359#[derive(Clone)]
360pub struct Sbix<'a> {
361    data: FontData<'a>,
362    num_glyphs: u16,
363}
364
365#[allow(clippy::needless_lifetimes)]
366impl<'a> Sbix<'a> {
367    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + HeaderFlags::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
368    basic_table_impls!(impl_the_methods);
369
370    /// Table version number — set to 1.
371    pub fn version(&self) -> u16 {
372        let range = self.version_byte_range();
373        self.data.read_at(range.start).ok().unwrap()
374    }
375
376    /// Bit 0: Set to 1.
377    /// Bit 1: Draw outlines.
378    /// Bits 2 to 15: reserved (set to 0).
379    pub fn flags(&self) -> HeaderFlags {
380        let range = self.flags_byte_range();
381        self.data.read_at(range.start).ok().unwrap()
382    }
383
384    /// Number of bitmap strikes.
385    pub fn num_strikes(&self) -> u32 {
386        let range = self.num_strikes_byte_range();
387        self.data.read_at(range.start).ok().unwrap()
388    }
389
390    /// Offsets from the beginning of the 'sbix' table to data for each individual bitmap strike.
391    pub fn strike_offsets(&self) -> &'a [BigEndian<Offset32>] {
392        let range = self.strike_offsets_byte_range();
393        self.data.read_array(range).ok().unwrap_or_default()
394    }
395
396    /// A dynamically resolving wrapper for [`strike_offsets`][Self::strike_offsets].
397    pub fn strikes(&self) -> ArrayOfOffsets<'a, Strike<'a>, Offset32> {
398        let data = self.data;
399        let offsets = self.strike_offsets();
400        let args = self.num_glyphs();
401        ArrayOfOffsets::new(offsets, data, args)
402    }
403
404    pub(crate) fn num_glyphs(&self) -> u16 {
405        self.num_glyphs
406    }
407
408    pub fn version_byte_range(&self) -> Range<usize> {
409        let start = 0;
410        start..start + u16::RAW_BYTE_LEN
411    }
412
413    pub fn flags_byte_range(&self) -> Range<usize> {
414        let start = self.version_byte_range().end;
415        start..start + HeaderFlags::RAW_BYTE_LEN
416    }
417
418    pub fn num_strikes_byte_range(&self) -> Range<usize> {
419        let start = self.flags_byte_range().end;
420        start..start + u32::RAW_BYTE_LEN
421    }
422
423    pub fn strike_offsets_byte_range(&self) -> Range<usize> {
424        let num_strikes = self.num_strikes();
425        let start = self.num_strikes_byte_range().end;
426        start..start + (num_strikes as usize).saturating_mul(Offset32::RAW_BYTE_LEN)
427    }
428}
429
430#[cfg(feature = "experimental_traverse")]
431impl<'a> SomeTable<'a> for Sbix<'a> {
432    fn type_name(&self) -> &str {
433        "Sbix"
434    }
435    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
436        match idx {
437            0usize => Some(Field::new("version", self.version())),
438            1usize => Some(Field::new("flags", self.flags())),
439            2usize => Some(Field::new("num_strikes", self.num_strikes())),
440            3usize => Some({
441                let data = self.data;
442                let args = self.num_glyphs();
443                Field::new(
444                    "strike_offsets",
445                    FieldType::array_of_offsets(
446                        better_type_name::<Strike>(),
447                        self.strike_offsets(),
448                        move |off| {
449                            let target = off.get().resolve_with_args::<Strike>(data, &args);
450                            FieldType::offset(off.get(), target)
451                        },
452                    ),
453                )
454            }),
455            _ => None,
456        }
457    }
458}
459
460#[cfg(feature = "experimental_traverse")]
461#[allow(clippy::needless_lifetimes)]
462impl<'a> std::fmt::Debug for Sbix<'a> {
463    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
464        (self as &dyn SomeTable<'a>).fmt(f)
465    }
466}
467
468impl<'a> MinByteRange<'a> for Strike<'a> {
469    fn min_byte_range(&self) -> Range<usize> {
470        0..self.glyph_data_offsets_byte_range().end
471    }
472    fn min_table_bytes(&self) -> &'a [u8] {
473        let range = self.min_byte_range();
474        self.data.as_bytes().get(range).unwrap_or_default()
475    }
476}
477
478impl ReadArgs for Strike<'_> {
479    type Args = u16;
480}
481
482impl<'a> FontReadWithArgs<'a> for Strike<'a> {
483    fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
484        let num_glyphs = *args;
485
486        #[allow(clippy::absurd_extreme_comparisons)]
487        if data.len() < Self::MIN_SIZE {
488            return Err(ReadError::OutOfBounds);
489        }
490        Ok(Self { data, num_glyphs })
491    }
492}
493
494impl<'a> Strike<'a> {
495    /// A constructor that requires additional arguments.
496    ///
497    /// This type requires some external state in order to be
498    /// parsed.
499    pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
500        let args = num_glyphs;
501        Self::read_with_args(data, &args)
502    }
503}
504
505/// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table
506#[derive(Clone)]
507pub struct Strike<'a> {
508    data: FontData<'a>,
509    num_glyphs: u16,
510}
511
512#[allow(clippy::needless_lifetimes)]
513impl<'a> Strike<'a> {
514    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
515    basic_table_impls!(impl_the_methods);
516
517    /// The PPEM size for which this strike was designed.
518    pub fn ppem(&self) -> u16 {
519        let range = self.ppem_byte_range();
520        self.data.read_at(range.start).ok().unwrap()
521    }
522
523    /// The device pixel density (in PPI) for which this strike was designed. (E.g., 96 PPI, 192 PPI.)
524    pub fn ppi(&self) -> u16 {
525        let range = self.ppi_byte_range();
526        self.data.read_at(range.start).ok().unwrap()
527    }
528
529    /// Offset from the beginning of the strike data header to bitmap data for an individual glyph ID.
530    pub fn glyph_data_offsets(&self) -> &'a [BigEndian<u32>] {
531        let range = self.glyph_data_offsets_byte_range();
532        self.data.read_array(range).ok().unwrap_or_default()
533    }
534
535    pub(crate) fn num_glyphs(&self) -> u16 {
536        self.num_glyphs
537    }
538
539    pub fn ppem_byte_range(&self) -> Range<usize> {
540        let start = 0;
541        start..start + u16::RAW_BYTE_LEN
542    }
543
544    pub fn ppi_byte_range(&self) -> Range<usize> {
545        let start = self.ppem_byte_range().end;
546        start..start + u16::RAW_BYTE_LEN
547    }
548
549    pub fn glyph_data_offsets_byte_range(&self) -> Range<usize> {
550        let num_glyphs = self.num_glyphs();
551        let start = self.ppi_byte_range().end;
552        start..start + (transforms::add(num_glyphs, 1_usize)).saturating_mul(u32::RAW_BYTE_LEN)
553    }
554}
555
556#[cfg(feature = "experimental_traverse")]
557impl<'a> SomeTable<'a> for Strike<'a> {
558    fn type_name(&self) -> &str {
559        "Strike"
560    }
561    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
562        match idx {
563            0usize => Some(Field::new("ppem", self.ppem())),
564            1usize => Some(Field::new("ppi", self.ppi())),
565            2usize => Some(Field::new("glyph_data_offsets", self.glyph_data_offsets())),
566            _ => None,
567        }
568    }
569}
570
571#[cfg(feature = "experimental_traverse")]
572#[allow(clippy::needless_lifetimes)]
573impl<'a> std::fmt::Debug for Strike<'a> {
574    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
575        (self as &dyn SomeTable<'a>).fmt(f)
576    }
577}
578
579impl<'a> MinByteRange<'a> for GlyphData<'a> {
580    fn min_byte_range(&self) -> Range<usize> {
581        0..self.data_byte_range().end
582    }
583    fn min_table_bytes(&self) -> &'a [u8] {
584        let range = self.min_byte_range();
585        self.data.as_bytes().get(range).unwrap_or_default()
586    }
587}
588
589impl<'a> FontRead<'a> for GlyphData<'a> {
590    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
591        #[allow(clippy::absurd_extreme_comparisons)]
592        if data.len() < Self::MIN_SIZE {
593            return Err(ReadError::OutOfBounds);
594        }
595        Ok(Self { data })
596    }
597}
598
599/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table
600#[derive(Clone)]
601pub struct GlyphData<'a> {
602    data: FontData<'a>,
603}
604
605#[allow(clippy::needless_lifetimes)]
606impl<'a> GlyphData<'a> {
607    pub const MIN_SIZE: usize = (i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Tag::RAW_BYTE_LEN);
608    basic_table_impls!(impl_the_methods);
609
610    /// The horizontal (x-axis) position of the left edge of the bitmap graphic in relation to the glyph design space origin.
611    pub fn origin_offset_x(&self) -> i16 {
612        let range = self.origin_offset_x_byte_range();
613        self.data.read_at(range.start).ok().unwrap()
614    }
615
616    /// The vertical (y-axis) position of the bottom edge of the bitmap graphic in relation to the glyph design space origin.
617    pub fn origin_offset_y(&self) -> i16 {
618        let range = self.origin_offset_y_byte_range();
619        self.data.read_at(range.start).ok().unwrap()
620    }
621
622    /// Indicates the format of the embedded graphic data: one of 'jpg ', 'png ' or 'tiff', or the special format 'dupe'.
623    pub fn graphic_type(&self) -> Tag {
624        let range = self.graphic_type_byte_range();
625        self.data.read_at(range.start).ok().unwrap()
626    }
627
628    /// The actual embedded graphic data. The total length is inferred from sequential entries in the glyphDataOffsets array and the fixed size (8 bytes) of the preceding fields.
629    pub fn data(&self) -> &'a [u8] {
630        let range = self.data_byte_range();
631        self.data.read_array(range).ok().unwrap_or_default()
632    }
633
634    pub fn origin_offset_x_byte_range(&self) -> Range<usize> {
635        let start = 0;
636        start..start + i16::RAW_BYTE_LEN
637    }
638
639    pub fn origin_offset_y_byte_range(&self) -> Range<usize> {
640        let start = self.origin_offset_x_byte_range().end;
641        start..start + i16::RAW_BYTE_LEN
642    }
643
644    pub fn graphic_type_byte_range(&self) -> Range<usize> {
645        let start = self.origin_offset_y_byte_range().end;
646        start..start + Tag::RAW_BYTE_LEN
647    }
648
649    pub fn data_byte_range(&self) -> Range<usize> {
650        let start = self.graphic_type_byte_range().end;
651        start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
652    }
653}
654
655#[cfg(feature = "experimental_traverse")]
656impl<'a> SomeTable<'a> for GlyphData<'a> {
657    fn type_name(&self) -> &str {
658        "GlyphData"
659    }
660    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
661        match idx {
662            0usize => Some(Field::new("origin_offset_x", self.origin_offset_x())),
663            1usize => Some(Field::new("origin_offset_y", self.origin_offset_y())),
664            2usize => Some(Field::new("graphic_type", self.graphic_type())),
665            3usize => Some(Field::new("data", self.data())),
666            _ => None,
667        }
668    }
669}
670
671#[cfg(feature = "experimental_traverse")]
672#[allow(clippy::needless_lifetimes)]
673impl<'a> std::fmt::Debug for GlyphData<'a> {
674    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
675        (self as &dyn SomeTable<'a>).fmt(f)
676    }
677}