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        let end = start + u16::RAW_BYTE_LEN;
411        start..end
412    }
413
414    pub fn flags_byte_range(&self) -> Range<usize> {
415        let start = self.version_byte_range().end;
416        let end = start + HeaderFlags::RAW_BYTE_LEN;
417        start..end
418    }
419
420    pub fn num_strikes_byte_range(&self) -> Range<usize> {
421        let start = self.flags_byte_range().end;
422        let end = start + u32::RAW_BYTE_LEN;
423        start..end
424    }
425
426    pub fn strike_offsets_byte_range(&self) -> Range<usize> {
427        let num_strikes = self.num_strikes();
428        let start = self.num_strikes_byte_range().end;
429        let end =
430            start + (transforms::to_usize(num_strikes)).saturating_mul(Offset32::RAW_BYTE_LEN);
431        start..end
432    }
433}
434
435const _: () = assert!(FontData::default_data_long_enough(Sbix::MIN_SIZE));
436
437impl Default for Sbix<'_> {
438    fn default() -> Self {
439        Self {
440            data: FontData::default_table_data(),
441            num_glyphs: Default::default(),
442        }
443    }
444}
445
446#[cfg(feature = "experimental_traverse")]
447impl<'a> SomeTable<'a> for Sbix<'a> {
448    fn type_name(&self) -> &str {
449        "Sbix"
450    }
451    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
452        match idx {
453            0usize => Some(Field::new("version", self.version())),
454            1usize => Some(Field::new("flags", self.flags())),
455            2usize => Some(Field::new("num_strikes", self.num_strikes())),
456            3usize => Some(Field::new(
457                "strike_offsets",
458                FieldType::from(self.strikes()),
459            )),
460            _ => None,
461        }
462    }
463}
464
465#[cfg(feature = "experimental_traverse")]
466#[allow(clippy::needless_lifetimes)]
467impl<'a> std::fmt::Debug for Sbix<'a> {
468    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
469        (self as &dyn SomeTable<'a>).fmt(f)
470    }
471}
472
473impl<'a> MinByteRange<'a> for Strike<'a> {
474    fn min_byte_range(&self) -> Range<usize> {
475        0..self.glyph_data_offsets_byte_range().end
476    }
477    fn min_table_bytes(&self) -> &'a [u8] {
478        let range = self.min_byte_range();
479        self.data.as_bytes().get(range).unwrap_or_default()
480    }
481}
482
483impl ReadArgs for Strike<'_> {
484    type Args = u16;
485}
486
487impl<'a> FontReadWithArgs<'a> for Strike<'a> {
488    fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
489        let num_glyphs = *args;
490
491        #[allow(clippy::absurd_extreme_comparisons)]
492        if data.len() < Self::MIN_SIZE {
493            return Err(ReadError::OutOfBounds);
494        }
495        Ok(Self { data, num_glyphs })
496    }
497}
498
499impl<'a> Strike<'a> {
500    /// A constructor that requires additional arguments.
501    ///
502    /// This type requires some external state in order to be
503    /// parsed.
504    pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
505        let args = num_glyphs;
506        Self::read_with_args(data, &args)
507    }
508}
509
510/// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table
511#[derive(Clone)]
512pub struct Strike<'a> {
513    data: FontData<'a>,
514    num_glyphs: u16,
515}
516
517#[allow(clippy::needless_lifetimes)]
518impl<'a> Strike<'a> {
519    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
520    basic_table_impls!(impl_the_methods);
521
522    /// The PPEM size for which this strike was designed.
523    pub fn ppem(&self) -> u16 {
524        let range = self.ppem_byte_range();
525        self.data.read_at(range.start).ok().unwrap()
526    }
527
528    /// The device pixel density (in PPI) for which this strike was designed. (E.g., 96 PPI, 192 PPI.)
529    pub fn ppi(&self) -> u16 {
530        let range = self.ppi_byte_range();
531        self.data.read_at(range.start).ok().unwrap()
532    }
533
534    /// Offset from the beginning of the strike data header to bitmap data for an individual glyph ID.
535    pub fn glyph_data_offsets(&self) -> &'a [BigEndian<u32>] {
536        let range = self.glyph_data_offsets_byte_range();
537        self.data.read_array(range).ok().unwrap_or_default()
538    }
539
540    pub(crate) fn num_glyphs(&self) -> u16 {
541        self.num_glyphs
542    }
543
544    pub fn ppem_byte_range(&self) -> Range<usize> {
545        let start = 0;
546        let end = start + u16::RAW_BYTE_LEN;
547        start..end
548    }
549
550    pub fn ppi_byte_range(&self) -> Range<usize> {
551        let start = self.ppem_byte_range().end;
552        let end = start + u16::RAW_BYTE_LEN;
553        start..end
554    }
555
556    pub fn glyph_data_offsets_byte_range(&self) -> Range<usize> {
557        let num_glyphs = self.num_glyphs();
558        let start = self.ppi_byte_range().end;
559        let end = start + (transforms::add(num_glyphs, 1_usize)).saturating_mul(u32::RAW_BYTE_LEN);
560        start..end
561    }
562}
563
564const _: () = assert!(FontData::default_data_long_enough(Strike::MIN_SIZE));
565
566impl Default for Strike<'_> {
567    fn default() -> Self {
568        Self {
569            data: FontData::default_table_data(),
570            num_glyphs: Default::default(),
571        }
572    }
573}
574
575#[cfg(feature = "experimental_traverse")]
576impl<'a> SomeTable<'a> for Strike<'a> {
577    fn type_name(&self) -> &str {
578        "Strike"
579    }
580    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
581        match idx {
582            0usize => Some(Field::new("ppem", self.ppem())),
583            1usize => Some(Field::new("ppi", self.ppi())),
584            2usize => Some(Field::new("glyph_data_offsets", self.glyph_data_offsets())),
585            _ => None,
586        }
587    }
588}
589
590#[cfg(feature = "experimental_traverse")]
591#[allow(clippy::needless_lifetimes)]
592impl<'a> std::fmt::Debug for Strike<'a> {
593    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
594        (self as &dyn SomeTable<'a>).fmt(f)
595    }
596}
597
598impl<'a> MinByteRange<'a> for GlyphData<'a> {
599    fn min_byte_range(&self) -> Range<usize> {
600        0..self.data_byte_range().end
601    }
602    fn min_table_bytes(&self) -> &'a [u8] {
603        let range = self.min_byte_range();
604        self.data.as_bytes().get(range).unwrap_or_default()
605    }
606}
607
608impl<'a> FontRead<'a> for GlyphData<'a> {
609    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
610        #[allow(clippy::absurd_extreme_comparisons)]
611        if data.len() < Self::MIN_SIZE {
612            return Err(ReadError::OutOfBounds);
613        }
614        Ok(Self { data })
615    }
616}
617
618/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table
619#[derive(Clone)]
620pub struct GlyphData<'a> {
621    data: FontData<'a>,
622}
623
624#[allow(clippy::needless_lifetimes)]
625impl<'a> GlyphData<'a> {
626    pub const MIN_SIZE: usize = (i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Tag::RAW_BYTE_LEN);
627    basic_table_impls!(impl_the_methods);
628
629    /// The horizontal (x-axis) position of the left edge of the bitmap graphic in relation to the glyph design space origin.
630    pub fn origin_offset_x(&self) -> i16 {
631        let range = self.origin_offset_x_byte_range();
632        self.data.read_at(range.start).ok().unwrap()
633    }
634
635    /// The vertical (y-axis) position of the bottom edge of the bitmap graphic in relation to the glyph design space origin.
636    pub fn origin_offset_y(&self) -> i16 {
637        let range = self.origin_offset_y_byte_range();
638        self.data.read_at(range.start).ok().unwrap()
639    }
640
641    /// Indicates the format of the embedded graphic data: one of 'jpg ', 'png ' or 'tiff', or the special format 'dupe'.
642    pub fn graphic_type(&self) -> Tag {
643        let range = self.graphic_type_byte_range();
644        self.data.read_at(range.start).ok().unwrap()
645    }
646
647    /// 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.
648    pub fn data(&self) -> &'a [u8] {
649        let range = self.data_byte_range();
650        self.data.read_array(range).ok().unwrap_or_default()
651    }
652
653    pub fn origin_offset_x_byte_range(&self) -> Range<usize> {
654        let start = 0;
655        let end = start + i16::RAW_BYTE_LEN;
656        start..end
657    }
658
659    pub fn origin_offset_y_byte_range(&self) -> Range<usize> {
660        let start = self.origin_offset_x_byte_range().end;
661        let end = start + i16::RAW_BYTE_LEN;
662        start..end
663    }
664
665    pub fn graphic_type_byte_range(&self) -> Range<usize> {
666        let start = self.origin_offset_y_byte_range().end;
667        let end = start + Tag::RAW_BYTE_LEN;
668        start..end
669    }
670
671    pub fn data_byte_range(&self) -> Range<usize> {
672        let start = self.graphic_type_byte_range().end;
673        let end =
674            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
675        start..end
676    }
677}
678
679const _: () = assert!(FontData::default_data_long_enough(GlyphData::MIN_SIZE));
680
681impl Default for GlyphData<'_> {
682    fn default() -> Self {
683        Self {
684            data: FontData::default_table_data(),
685        }
686    }
687}
688
689#[cfg(feature = "experimental_traverse")]
690impl<'a> SomeTable<'a> for GlyphData<'a> {
691    fn type_name(&self) -> &str {
692        "GlyphData"
693    }
694    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
695        match idx {
696            0usize => Some(Field::new("origin_offset_x", self.origin_offset_x())),
697            1usize => Some(Field::new("origin_offset_y", self.origin_offset_y())),
698            2usize => Some(Field::new("graphic_type", self.graphic_type())),
699            3usize => Some(Field::new("data", self.data())),
700            _ => None,
701        }
702    }
703}
704
705#[cfg(feature = "experimental_traverse")]
706#[allow(clippy::needless_lifetimes)]
707impl<'a> std::fmt::Debug for GlyphData<'a> {
708    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
709        (self as &dyn SomeTable<'a>).fmt(f)
710    }
711}