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
316/// The [sbix (Standard Bitmap Graphics)](https://docs.microsoft.com/en-us/typography/opentype/spec/sbix) table
317#[derive(Debug, Clone, Copy)]
318#[doc(hidden)]
319pub struct SbixMarker {
320    num_glyphs: u16,
321    strike_offsets_byte_len: usize,
322}
323
324impl SbixMarker {
325    pub fn version_byte_range(&self) -> Range<usize> {
326        let start = 0;
327        start..start + u16::RAW_BYTE_LEN
328    }
329
330    pub fn flags_byte_range(&self) -> Range<usize> {
331        let start = self.version_byte_range().end;
332        start..start + HeaderFlags::RAW_BYTE_LEN
333    }
334
335    pub fn num_strikes_byte_range(&self) -> Range<usize> {
336        let start = self.flags_byte_range().end;
337        start..start + u32::RAW_BYTE_LEN
338    }
339
340    pub fn strike_offsets_byte_range(&self) -> Range<usize> {
341        let start = self.num_strikes_byte_range().end;
342        start..start + self.strike_offsets_byte_len
343    }
344}
345
346impl MinByteRange for SbixMarker {
347    fn min_byte_range(&self) -> Range<usize> {
348        0..self.strike_offsets_byte_range().end
349    }
350}
351
352impl TopLevelTable for Sbix<'_> {
353    /// `sbix`
354    const TAG: Tag = Tag::new(b"sbix");
355}
356
357impl ReadArgs for Sbix<'_> {
358    type Args = u16;
359}
360
361impl<'a> FontReadWithArgs<'a> for Sbix<'a> {
362    fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
363        let num_glyphs = *args;
364        let mut cursor = data.cursor();
365        cursor.advance::<u16>();
366        cursor.advance::<HeaderFlags>();
367        let num_strikes: u32 = cursor.read()?;
368        let strike_offsets_byte_len = (num_strikes as usize)
369            .checked_mul(Offset32::RAW_BYTE_LEN)
370            .ok_or(ReadError::OutOfBounds)?;
371        cursor.advance_by(strike_offsets_byte_len);
372        cursor.finish(SbixMarker {
373            num_glyphs,
374            strike_offsets_byte_len,
375        })
376    }
377}
378
379impl<'a> Sbix<'a> {
380    /// A constructor that requires additional arguments.
381    ///
382    /// This type requires some external state in order to be
383    /// parsed.
384    pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
385        let args = num_glyphs;
386        Self::read_with_args(data, &args)
387    }
388}
389
390/// The [sbix (Standard Bitmap Graphics)](https://docs.microsoft.com/en-us/typography/opentype/spec/sbix) table
391pub type Sbix<'a> = TableRef<'a, SbixMarker>;
392
393#[allow(clippy::needless_lifetimes)]
394impl<'a> Sbix<'a> {
395    /// Table version number — set to 1.
396    pub fn version(&self) -> u16 {
397        let range = self.shape.version_byte_range();
398        self.data.read_at(range.start).unwrap()
399    }
400
401    /// Bit 0: Set to 1.
402    /// Bit 1: Draw outlines.
403    /// Bits 2 to 15: reserved (set to 0).
404    pub fn flags(&self) -> HeaderFlags {
405        let range = self.shape.flags_byte_range();
406        self.data.read_at(range.start).unwrap()
407    }
408
409    /// Number of bitmap strikes.
410    pub fn num_strikes(&self) -> u32 {
411        let range = self.shape.num_strikes_byte_range();
412        self.data.read_at(range.start).unwrap()
413    }
414
415    /// Offsets from the beginning of the 'sbix' table to data for each individual bitmap strike.
416    pub fn strike_offsets(&self) -> &'a [BigEndian<Offset32>] {
417        let range = self.shape.strike_offsets_byte_range();
418        self.data.read_array(range).unwrap()
419    }
420
421    /// A dynamically resolving wrapper for [`strike_offsets`][Self::strike_offsets].
422    pub fn strikes(&self) -> ArrayOfOffsets<'a, Strike<'a>, Offset32> {
423        let data = self.data;
424        let offsets = self.strike_offsets();
425        let args = self.num_glyphs();
426        ArrayOfOffsets::new(offsets, data, args)
427    }
428
429    pub(crate) fn num_glyphs(&self) -> u16 {
430        self.shape.num_glyphs
431    }
432}
433
434#[cfg(feature = "experimental_traverse")]
435impl<'a> SomeTable<'a> for Sbix<'a> {
436    fn type_name(&self) -> &str {
437        "Sbix"
438    }
439    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
440        match idx {
441            0usize => Some(Field::new("version", self.version())),
442            1usize => Some(Field::new("flags", self.flags())),
443            2usize => Some(Field::new("num_strikes", self.num_strikes())),
444            3usize => Some({
445                let data = self.data;
446                let args = self.num_glyphs();
447                Field::new(
448                    "strike_offsets",
449                    FieldType::array_of_offsets(
450                        better_type_name::<Strike>(),
451                        self.strike_offsets(),
452                        move |off| {
453                            let target = off.get().resolve_with_args::<Strike>(data, &args);
454                            FieldType::offset(off.get(), target)
455                        },
456                    ),
457                )
458            }),
459            _ => None,
460        }
461    }
462}
463
464#[cfg(feature = "experimental_traverse")]
465#[allow(clippy::needless_lifetimes)]
466impl<'a> std::fmt::Debug for Sbix<'a> {
467    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
468        (self as &dyn SomeTable<'a>).fmt(f)
469    }
470}
471
472/// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table
473#[derive(Debug, Clone, Copy)]
474#[doc(hidden)]
475pub struct StrikeMarker {
476    glyph_data_offsets_byte_len: usize,
477}
478
479impl StrikeMarker {
480    pub fn ppem_byte_range(&self) -> Range<usize> {
481        let start = 0;
482        start..start + u16::RAW_BYTE_LEN
483    }
484
485    pub fn ppi_byte_range(&self) -> Range<usize> {
486        let start = self.ppem_byte_range().end;
487        start..start + u16::RAW_BYTE_LEN
488    }
489
490    pub fn glyph_data_offsets_byte_range(&self) -> Range<usize> {
491        let start = self.ppi_byte_range().end;
492        start..start + self.glyph_data_offsets_byte_len
493    }
494}
495
496impl MinByteRange for StrikeMarker {
497    fn min_byte_range(&self) -> Range<usize> {
498        0..self.glyph_data_offsets_byte_range().end
499    }
500}
501
502impl ReadArgs for Strike<'_> {
503    type Args = u16;
504}
505
506impl<'a> FontReadWithArgs<'a> for Strike<'a> {
507    fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
508        let num_glyphs = *args;
509        let mut cursor = data.cursor();
510        cursor.advance::<u16>();
511        cursor.advance::<u16>();
512        let glyph_data_offsets_byte_len = (transforms::add(num_glyphs, 1_usize))
513            .checked_mul(u32::RAW_BYTE_LEN)
514            .ok_or(ReadError::OutOfBounds)?;
515        cursor.advance_by(glyph_data_offsets_byte_len);
516        cursor.finish(StrikeMarker {
517            glyph_data_offsets_byte_len,
518        })
519    }
520}
521
522impl<'a> Strike<'a> {
523    /// A constructor that requires additional arguments.
524    ///
525    /// This type requires some external state in order to be
526    /// parsed.
527    pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
528        let args = num_glyphs;
529        Self::read_with_args(data, &args)
530    }
531}
532
533/// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table
534pub type Strike<'a> = TableRef<'a, StrikeMarker>;
535
536#[allow(clippy::needless_lifetimes)]
537impl<'a> Strike<'a> {
538    /// The PPEM size for which this strike was designed.
539    pub fn ppem(&self) -> u16 {
540        let range = self.shape.ppem_byte_range();
541        self.data.read_at(range.start).unwrap()
542    }
543
544    /// The device pixel density (in PPI) for which this strike was designed. (E.g., 96 PPI, 192 PPI.)
545    pub fn ppi(&self) -> u16 {
546        let range = self.shape.ppi_byte_range();
547        self.data.read_at(range.start).unwrap()
548    }
549
550    /// Offset from the beginning of the strike data header to bitmap data for an individual glyph ID.
551    pub fn glyph_data_offsets(&self) -> &'a [BigEndian<u32>] {
552        let range = self.shape.glyph_data_offsets_byte_range();
553        self.data.read_array(range).unwrap()
554    }
555}
556
557#[cfg(feature = "experimental_traverse")]
558impl<'a> SomeTable<'a> for Strike<'a> {
559    fn type_name(&self) -> &str {
560        "Strike"
561    }
562    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
563        match idx {
564            0usize => Some(Field::new("ppem", self.ppem())),
565            1usize => Some(Field::new("ppi", self.ppi())),
566            2usize => Some(Field::new("glyph_data_offsets", self.glyph_data_offsets())),
567            _ => None,
568        }
569    }
570}
571
572#[cfg(feature = "experimental_traverse")]
573#[allow(clippy::needless_lifetimes)]
574impl<'a> std::fmt::Debug for Strike<'a> {
575    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576        (self as &dyn SomeTable<'a>).fmt(f)
577    }
578}
579
580/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table
581#[derive(Debug, Clone, Copy)]
582#[doc(hidden)]
583pub struct GlyphDataMarker {
584    data_byte_len: usize,
585}
586
587impl GlyphDataMarker {
588    pub fn origin_offset_x_byte_range(&self) -> Range<usize> {
589        let start = 0;
590        start..start + i16::RAW_BYTE_LEN
591    }
592
593    pub fn origin_offset_y_byte_range(&self) -> Range<usize> {
594        let start = self.origin_offset_x_byte_range().end;
595        start..start + i16::RAW_BYTE_LEN
596    }
597
598    pub fn graphic_type_byte_range(&self) -> Range<usize> {
599        let start = self.origin_offset_y_byte_range().end;
600        start..start + Tag::RAW_BYTE_LEN
601    }
602
603    pub fn data_byte_range(&self) -> Range<usize> {
604        let start = self.graphic_type_byte_range().end;
605        start..start + self.data_byte_len
606    }
607}
608
609impl MinByteRange for GlyphDataMarker {
610    fn min_byte_range(&self) -> Range<usize> {
611        0..self.data_byte_range().end
612    }
613}
614
615impl<'a> FontRead<'a> for GlyphData<'a> {
616    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
617        let mut cursor = data.cursor();
618        cursor.advance::<i16>();
619        cursor.advance::<i16>();
620        cursor.advance::<Tag>();
621        let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
622        cursor.advance_by(data_byte_len);
623        cursor.finish(GlyphDataMarker { data_byte_len })
624    }
625}
626
627/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table
628pub type GlyphData<'a> = TableRef<'a, GlyphDataMarker>;
629
630#[allow(clippy::needless_lifetimes)]
631impl<'a> GlyphData<'a> {
632    /// The horizontal (x-axis) position of the left edge of the bitmap graphic in relation to the glyph design space origin.
633    pub fn origin_offset_x(&self) -> i16 {
634        let range = self.shape.origin_offset_x_byte_range();
635        self.data.read_at(range.start).unwrap()
636    }
637
638    /// The vertical (y-axis) position of the bottom edge of the bitmap graphic in relation to the glyph design space origin.
639    pub fn origin_offset_y(&self) -> i16 {
640        let range = self.shape.origin_offset_y_byte_range();
641        self.data.read_at(range.start).unwrap()
642    }
643
644    /// Indicates the format of the embedded graphic data: one of 'jpg ', 'png ' or 'tiff', or the special format 'dupe'.
645    pub fn graphic_type(&self) -> Tag {
646        let range = self.shape.graphic_type_byte_range();
647        self.data.read_at(range.start).unwrap()
648    }
649
650    /// 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.
651    pub fn data(&self) -> &'a [u8] {
652        let range = self.shape.data_byte_range();
653        self.data.read_array(range).unwrap()
654    }
655}
656
657#[cfg(feature = "experimental_traverse")]
658impl<'a> SomeTable<'a> for GlyphData<'a> {
659    fn type_name(&self) -> &str {
660        "GlyphData"
661    }
662    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
663        match idx {
664            0usize => Some(Field::new("origin_offset_x", self.origin_offset_x())),
665            1usize => Some(Field::new("origin_offset_y", self.origin_offset_y())),
666            2usize => Some(Field::new("graphic_type", self.graphic_type())),
667            3usize => Some(Field::new("data", self.data())),
668            _ => None,
669        }
670    }
671}
672
673#[cfg(feature = "experimental_traverse")]
674#[allow(clippy::needless_lifetimes)]
675impl<'a> std::fmt::Debug for GlyphData<'a> {
676    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
677        (self as &dyn SomeTable<'a>).fmt(f)
678    }
679}