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
430const _: () = assert!(FontData::default_data_long_enough(Sbix::MIN_SIZE));
431
432impl Default for Sbix<'_> {
433    fn default() -> Self {
434        Self {
435            data: FontData::default_table_data(),
436            num_glyphs: Default::default(),
437        }
438    }
439}
440
441#[cfg(feature = "experimental_traverse")]
442impl<'a> SomeTable<'a> for Sbix<'a> {
443    fn type_name(&self) -> &str {
444        "Sbix"
445    }
446    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
447        match idx {
448            0usize => Some(Field::new("version", self.version())),
449            1usize => Some(Field::new("flags", self.flags())),
450            2usize => Some(Field::new("num_strikes", self.num_strikes())),
451            3usize => Some(Field::new(
452                "strike_offsets",
453                FieldType::from(self.strikes()),
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
556const _: () = assert!(FontData::default_data_long_enough(Strike::MIN_SIZE));
557
558impl Default for Strike<'_> {
559    fn default() -> Self {
560        Self {
561            data: FontData::default_table_data(),
562            num_glyphs: Default::default(),
563        }
564    }
565}
566
567#[cfg(feature = "experimental_traverse")]
568impl<'a> SomeTable<'a> for Strike<'a> {
569    fn type_name(&self) -> &str {
570        "Strike"
571    }
572    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
573        match idx {
574            0usize => Some(Field::new("ppem", self.ppem())),
575            1usize => Some(Field::new("ppi", self.ppi())),
576            2usize => Some(Field::new("glyph_data_offsets", self.glyph_data_offsets())),
577            _ => None,
578        }
579    }
580}
581
582#[cfg(feature = "experimental_traverse")]
583#[allow(clippy::needless_lifetimes)]
584impl<'a> std::fmt::Debug for Strike<'a> {
585    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
586        (self as &dyn SomeTable<'a>).fmt(f)
587    }
588}
589
590impl<'a> MinByteRange<'a> for GlyphData<'a> {
591    fn min_byte_range(&self) -> Range<usize> {
592        0..self.data_byte_range().end
593    }
594    fn min_table_bytes(&self) -> &'a [u8] {
595        let range = self.min_byte_range();
596        self.data.as_bytes().get(range).unwrap_or_default()
597    }
598}
599
600impl<'a> FontRead<'a> for GlyphData<'a> {
601    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
602        #[allow(clippy::absurd_extreme_comparisons)]
603        if data.len() < Self::MIN_SIZE {
604            return Err(ReadError::OutOfBounds);
605        }
606        Ok(Self { data })
607    }
608}
609
610/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table
611#[derive(Clone)]
612pub struct GlyphData<'a> {
613    data: FontData<'a>,
614}
615
616#[allow(clippy::needless_lifetimes)]
617impl<'a> GlyphData<'a> {
618    pub const MIN_SIZE: usize = (i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Tag::RAW_BYTE_LEN);
619    basic_table_impls!(impl_the_methods);
620
621    /// The horizontal (x-axis) position of the left edge of the bitmap graphic in relation to the glyph design space origin.
622    pub fn origin_offset_x(&self) -> i16 {
623        let range = self.origin_offset_x_byte_range();
624        self.data.read_at(range.start).ok().unwrap()
625    }
626
627    /// The vertical (y-axis) position of the bottom edge of the bitmap graphic in relation to the glyph design space origin.
628    pub fn origin_offset_y(&self) -> i16 {
629        let range = self.origin_offset_y_byte_range();
630        self.data.read_at(range.start).ok().unwrap()
631    }
632
633    /// Indicates the format of the embedded graphic data: one of 'jpg ', 'png ' or 'tiff', or the special format 'dupe'.
634    pub fn graphic_type(&self) -> Tag {
635        let range = self.graphic_type_byte_range();
636        self.data.read_at(range.start).ok().unwrap()
637    }
638
639    /// 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.
640    pub fn data(&self) -> &'a [u8] {
641        let range = self.data_byte_range();
642        self.data.read_array(range).ok().unwrap_or_default()
643    }
644
645    pub fn origin_offset_x_byte_range(&self) -> Range<usize> {
646        let start = 0;
647        start..start + i16::RAW_BYTE_LEN
648    }
649
650    pub fn origin_offset_y_byte_range(&self) -> Range<usize> {
651        let start = self.origin_offset_x_byte_range().end;
652        start..start + i16::RAW_BYTE_LEN
653    }
654
655    pub fn graphic_type_byte_range(&self) -> Range<usize> {
656        let start = self.origin_offset_y_byte_range().end;
657        start..start + Tag::RAW_BYTE_LEN
658    }
659
660    pub fn data_byte_range(&self) -> Range<usize> {
661        let start = self.graphic_type_byte_range().end;
662        start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
663    }
664}
665
666const _: () = assert!(FontData::default_data_long_enough(GlyphData::MIN_SIZE));
667
668impl Default for GlyphData<'_> {
669    fn default() -> Self {
670        Self {
671            data: FontData::default_table_data(),
672        }
673    }
674}
675
676#[cfg(feature = "experimental_traverse")]
677impl<'a> SomeTable<'a> for GlyphData<'a> {
678    fn type_name(&self) -> &str {
679        "GlyphData"
680    }
681    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
682        match idx {
683            0usize => Some(Field::new("origin_offset_x", self.origin_offset_x())),
684            1usize => Some(Field::new("origin_offset_y", self.origin_offset_y())),
685            2usize => Some(Field::new("graphic_type", self.graphic_type())),
686            3usize => Some(Field::new("data", self.data())),
687            _ => None,
688        }
689    }
690}
691
692#[cfg(feature = "experimental_traverse")]
693#[allow(clippy::needless_lifetimes)]
694impl<'a> std::fmt::Debug for GlyphData<'a> {
695    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
696        (self as &dyn SomeTable<'a>).fmt(f)
697    }
698}