read_fonts/generated/
generated_cpal.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/// [CPAL (Color Palette Table)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-table-header) table
9#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct CpalMarker {
12    color_record_indices_byte_len: usize,
13    palette_types_array_offset_byte_start: Option<usize>,
14    palette_labels_array_offset_byte_start: Option<usize>,
15    palette_entry_labels_array_offset_byte_start: Option<usize>,
16}
17
18impl CpalMarker {
19    pub fn version_byte_range(&self) -> Range<usize> {
20        let start = 0;
21        start..start + u16::RAW_BYTE_LEN
22    }
23
24    pub fn num_palette_entries_byte_range(&self) -> Range<usize> {
25        let start = self.version_byte_range().end;
26        start..start + u16::RAW_BYTE_LEN
27    }
28
29    pub fn num_palettes_byte_range(&self) -> Range<usize> {
30        let start = self.num_palette_entries_byte_range().end;
31        start..start + u16::RAW_BYTE_LEN
32    }
33
34    pub fn num_color_records_byte_range(&self) -> Range<usize> {
35        let start = self.num_palettes_byte_range().end;
36        start..start + u16::RAW_BYTE_LEN
37    }
38
39    pub fn color_records_array_offset_byte_range(&self) -> Range<usize> {
40        let start = self.num_color_records_byte_range().end;
41        start..start + Offset32::RAW_BYTE_LEN
42    }
43
44    pub fn color_record_indices_byte_range(&self) -> Range<usize> {
45        let start = self.color_records_array_offset_byte_range().end;
46        start..start + self.color_record_indices_byte_len
47    }
48
49    pub fn palette_types_array_offset_byte_range(&self) -> Option<Range<usize>> {
50        let start = self.palette_types_array_offset_byte_start?;
51        Some(start..start + Offset32::RAW_BYTE_LEN)
52    }
53
54    pub fn palette_labels_array_offset_byte_range(&self) -> Option<Range<usize>> {
55        let start = self.palette_labels_array_offset_byte_start?;
56        Some(start..start + Offset32::RAW_BYTE_LEN)
57    }
58
59    pub fn palette_entry_labels_array_offset_byte_range(&self) -> Option<Range<usize>> {
60        let start = self.palette_entry_labels_array_offset_byte_start?;
61        Some(start..start + Offset32::RAW_BYTE_LEN)
62    }
63}
64
65impl MinByteRange for CpalMarker {
66    fn min_byte_range(&self) -> Range<usize> {
67        0..self.color_record_indices_byte_range().end
68    }
69}
70
71impl TopLevelTable for Cpal<'_> {
72    /// `CPAL`
73    const TAG: Tag = Tag::new(b"CPAL");
74}
75
76impl<'a> FontRead<'a> for Cpal<'a> {
77    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
78        let mut cursor = data.cursor();
79        let version: u16 = cursor.read()?;
80        cursor.advance::<u16>();
81        let num_palettes: u16 = cursor.read()?;
82        cursor.advance::<u16>();
83        cursor.advance::<Offset32>();
84        let color_record_indices_byte_len = (num_palettes as usize)
85            .checked_mul(u16::RAW_BYTE_LEN)
86            .ok_or(ReadError::OutOfBounds)?;
87        cursor.advance_by(color_record_indices_byte_len);
88        let palette_types_array_offset_byte_start = version
89            .compatible(1u16)
90            .then(|| cursor.position())
91            .transpose()?;
92        version
93            .compatible(1u16)
94            .then(|| cursor.advance::<Offset32>());
95        let palette_labels_array_offset_byte_start = version
96            .compatible(1u16)
97            .then(|| cursor.position())
98            .transpose()?;
99        version
100            .compatible(1u16)
101            .then(|| cursor.advance::<Offset32>());
102        let palette_entry_labels_array_offset_byte_start = version
103            .compatible(1u16)
104            .then(|| cursor.position())
105            .transpose()?;
106        version
107            .compatible(1u16)
108            .then(|| cursor.advance::<Offset32>());
109        cursor.finish(CpalMarker {
110            color_record_indices_byte_len,
111            palette_types_array_offset_byte_start,
112            palette_labels_array_offset_byte_start,
113            palette_entry_labels_array_offset_byte_start,
114        })
115    }
116}
117
118/// [CPAL (Color Palette Table)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-table-header) table
119pub type Cpal<'a> = TableRef<'a, CpalMarker>;
120
121#[allow(clippy::needless_lifetimes)]
122impl<'a> Cpal<'a> {
123    /// Table version number (=0).
124    pub fn version(&self) -> u16 {
125        let range = self.shape.version_byte_range();
126        self.data.read_at(range.start).unwrap()
127    }
128
129    /// Number of palette entries in each palette.
130    pub fn num_palette_entries(&self) -> u16 {
131        let range = self.shape.num_palette_entries_byte_range();
132        self.data.read_at(range.start).unwrap()
133    }
134
135    /// Number of palettes in the table.
136    pub fn num_palettes(&self) -> u16 {
137        let range = self.shape.num_palettes_byte_range();
138        self.data.read_at(range.start).unwrap()
139    }
140
141    /// Total number of color records, combined for all palettes.
142    pub fn num_color_records(&self) -> u16 {
143        let range = self.shape.num_color_records_byte_range();
144        self.data.read_at(range.start).unwrap()
145    }
146
147    /// Offset from the beginning of CPAL table to the first
148    /// ColorRecord.
149    pub fn color_records_array_offset(&self) -> Nullable<Offset32> {
150        let range = self.shape.color_records_array_offset_byte_range();
151        self.data.read_at(range.start).unwrap()
152    }
153
154    /// Attempt to resolve [`color_records_array_offset`][Self::color_records_array_offset].
155    pub fn color_records_array(&self) -> Option<Result<&'a [ColorRecord], ReadError>> {
156        let data = self.data;
157        let args = self.num_color_records();
158        self.color_records_array_offset()
159            .resolve_with_args(data, &args)
160    }
161
162    /// Index of each palette’s first color record in the combined
163    /// color record array.
164    pub fn color_record_indices(&self) -> &'a [BigEndian<u16>] {
165        let range = self.shape.color_record_indices_byte_range();
166        self.data.read_array(range).unwrap()
167    }
168
169    /// Offset from the beginning of CPAL table to the [Palette Types Array][].
170    ///
171    /// This is an array of 32-bit flag fields that describe properties of each palette.
172    ///
173    /// [Palette Types Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-type-array
174    pub fn palette_types_array_offset(&self) -> Option<Nullable<Offset32>> {
175        let range = self.shape.palette_types_array_offset_byte_range()?;
176        Some(self.data.read_at(range.start).unwrap())
177    }
178
179    /// Attempt to resolve [`palette_types_array_offset`][Self::palette_types_array_offset].
180    pub fn palette_types_array(&self) -> Option<Result<&'a [BigEndian<PaletteType>], ReadError>> {
181        let data = self.data;
182        let args = self.num_palettes();
183        self.palette_types_array_offset()
184            .map(|x| x.resolve_with_args(data, &args))?
185    }
186
187    /// Offset from the beginning of CPAL table to the [Palette Labels Array][].
188    ///
189    /// This is an array of 'name' table IDs (typically in the font-specific name
190    /// ID range) that specify user interface strings associated with  each palette.
191    /// Use 0xFFFF if no name ID is provided for a palette.
192    ///
193    /// [Palette Labels Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-labels-array
194    pub fn palette_labels_array_offset(&self) -> Option<Nullable<Offset32>> {
195        let range = self.shape.palette_labels_array_offset_byte_range()?;
196        Some(self.data.read_at(range.start).unwrap())
197    }
198
199    /// Attempt to resolve [`palette_labels_array_offset`][Self::palette_labels_array_offset].
200    pub fn palette_labels_array(&self) -> Option<Result<&'a [BigEndian<u16>], ReadError>> {
201        let data = self.data;
202        let args = self.num_palettes();
203        self.palette_labels_array_offset()
204            .map(|x| x.resolve_with_args(data, &args))?
205    }
206
207    /// Offset from the beginning of CPAL table to the [Palette Entry Labels Array][].
208    ///
209    /// This is an array of 'name' table IDs (typically in the font-specific name
210    /// ID range) that specify user interface strings associated with  each palette
211    /// entry, e.g. “Outline”, “Fill”. This set of palette entry labels applies
212    /// to all palettes in the font. Use  0xFFFF if no name ID is provided for a
213    /// palette entry.
214    ///
215    /// [Palette Entry Labels Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-entry-label-array
216    pub fn palette_entry_labels_array_offset(&self) -> Option<Nullable<Offset32>> {
217        let range = self.shape.palette_entry_labels_array_offset_byte_range()?;
218        Some(self.data.read_at(range.start).unwrap())
219    }
220
221    /// Attempt to resolve [`palette_entry_labels_array_offset`][Self::palette_entry_labels_array_offset].
222    pub fn palette_entry_labels_array(&self) -> Option<Result<&'a [BigEndian<NameId>], ReadError>> {
223        let data = self.data;
224        let args = self.num_palette_entries();
225        self.palette_entry_labels_array_offset()
226            .map(|x| x.resolve_with_args(data, &args))?
227    }
228}
229
230#[cfg(feature = "experimental_traverse")]
231impl<'a> SomeTable<'a> for Cpal<'a> {
232    fn type_name(&self) -> &str {
233        "Cpal"
234    }
235    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
236        let version = self.version();
237        match idx {
238            0usize => Some(Field::new("version", self.version())),
239            1usize => Some(Field::new(
240                "num_palette_entries",
241                self.num_palette_entries(),
242            )),
243            2usize => Some(Field::new("num_palettes", self.num_palettes())),
244            3usize => Some(Field::new("num_color_records", self.num_color_records())),
245            4usize => Some(Field::new(
246                "color_records_array_offset",
247                traversal::FieldType::offset_to_array_of_records(
248                    self.color_records_array_offset(),
249                    self.color_records_array(),
250                    stringify!(ColorRecord),
251                    self.offset_data(),
252                ),
253            )),
254            5usize => Some(Field::new(
255                "color_record_indices",
256                self.color_record_indices(),
257            )),
258            6usize if version.compatible(1u16) => Some(Field::new(
259                "palette_types_array_offset",
260                FieldType::offset_to_array_of_scalars(
261                    self.palette_types_array_offset().unwrap(),
262                    self.palette_types_array(),
263                ),
264            )),
265            7usize if version.compatible(1u16) => Some(Field::new(
266                "palette_labels_array_offset",
267                FieldType::offset_to_array_of_scalars(
268                    self.palette_labels_array_offset().unwrap(),
269                    self.palette_labels_array(),
270                ),
271            )),
272            8usize if version.compatible(1u16) => Some(Field::new(
273                "palette_entry_labels_array_offset",
274                FieldType::offset_to_array_of_scalars(
275                    self.palette_entry_labels_array_offset().unwrap(),
276                    self.palette_entry_labels_array(),
277                ),
278            )),
279            _ => None,
280        }
281    }
282}
283
284#[cfg(feature = "experimental_traverse")]
285#[allow(clippy::needless_lifetimes)]
286impl<'a> std::fmt::Debug for Cpal<'a> {
287    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288        (self as &dyn SomeTable<'a>).fmt(f)
289    }
290}
291
292/// The [PaletteType](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-type-array) flags.
293#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
294#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
295#[repr(transparent)]
296pub struct PaletteType {
297    bits: u32,
298}
299
300impl PaletteType {
301    /// Bit 0: palette is appropriate to use when displaying the font on a light background such as white.
302    pub const USABLE_WITH_LIGHT_BACKGROUND: Self = Self { bits: 0x0001 };
303
304    /// Bit 1: palette is appropriate to use when displaying the font on a dark background such as black.
305    pub const USABLE_WITH_DARK_BACKGROUND: Self = Self { bits: 0x0002 };
306}
307
308impl PaletteType {
309    ///  Returns an empty set of flags.
310    #[inline]
311    pub const fn empty() -> Self {
312        Self { bits: 0 }
313    }
314
315    /// Returns the set containing all flags.
316    #[inline]
317    pub const fn all() -> Self {
318        Self {
319            bits: Self::USABLE_WITH_LIGHT_BACKGROUND.bits | Self::USABLE_WITH_DARK_BACKGROUND.bits,
320        }
321    }
322
323    /// Returns the raw value of the flags currently stored.
324    #[inline]
325    pub const fn bits(&self) -> u32 {
326        self.bits
327    }
328
329    /// Convert from underlying bit representation, unless that
330    /// representation contains bits that do not correspond to a flag.
331    #[inline]
332    pub const fn from_bits(bits: u32) -> Option<Self> {
333        if (bits & !Self::all().bits()) == 0 {
334            Some(Self { bits })
335        } else {
336            None
337        }
338    }
339
340    /// Convert from underlying bit representation, dropping any bits
341    /// that do not correspond to flags.
342    #[inline]
343    pub const fn from_bits_truncate(bits: u32) -> Self {
344        Self {
345            bits: bits & Self::all().bits,
346        }
347    }
348
349    /// Returns `true` if no flags are currently stored.
350    #[inline]
351    pub const fn is_empty(&self) -> bool {
352        self.bits() == Self::empty().bits()
353    }
354
355    /// Returns `true` if there are flags common to both `self` and `other`.
356    #[inline]
357    pub const fn intersects(&self, other: Self) -> bool {
358        !(Self {
359            bits: self.bits & other.bits,
360        })
361        .is_empty()
362    }
363
364    /// Returns `true` if all of the flags in `other` are contained within `self`.
365    #[inline]
366    pub const fn contains(&self, other: Self) -> bool {
367        (self.bits & other.bits) == other.bits
368    }
369
370    /// Inserts the specified flags in-place.
371    #[inline]
372    pub fn insert(&mut self, other: Self) {
373        self.bits |= other.bits;
374    }
375
376    /// Removes the specified flags in-place.
377    #[inline]
378    pub fn remove(&mut self, other: Self) {
379        self.bits &= !other.bits;
380    }
381
382    /// Toggles the specified flags in-place.
383    #[inline]
384    pub fn toggle(&mut self, other: Self) {
385        self.bits ^= other.bits;
386    }
387
388    /// Returns the intersection between the flags in `self` and
389    /// `other`.
390    ///
391    /// Specifically, the returned set contains only the flags which are
392    /// present in *both* `self` *and* `other`.
393    ///
394    /// This is equivalent to using the `&` operator (e.g.
395    /// [`ops::BitAnd`]), as in `flags & other`.
396    ///
397    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
398    #[inline]
399    #[must_use]
400    pub const fn intersection(self, other: Self) -> Self {
401        Self {
402            bits: self.bits & other.bits,
403        }
404    }
405
406    /// Returns the union of between the flags in `self` and `other`.
407    ///
408    /// Specifically, the returned set contains all flags which are
409    /// present in *either* `self` *or* `other`, including any which are
410    /// present in both.
411    ///
412    /// This is equivalent to using the `|` operator (e.g.
413    /// [`ops::BitOr`]), as in `flags | other`.
414    ///
415    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
416    #[inline]
417    #[must_use]
418    pub const fn union(self, other: Self) -> Self {
419        Self {
420            bits: self.bits | other.bits,
421        }
422    }
423
424    /// Returns the difference between the flags in `self` and `other`.
425    ///
426    /// Specifically, the returned set contains all flags present in
427    /// `self`, except for the ones present in `other`.
428    ///
429    /// It is also conceptually equivalent to the "bit-clear" operation:
430    /// `flags & !other` (and this syntax is also supported).
431    ///
432    /// This is equivalent to using the `-` operator (e.g.
433    /// [`ops::Sub`]), as in `flags - other`.
434    ///
435    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
436    #[inline]
437    #[must_use]
438    pub const fn difference(self, other: Self) -> Self {
439        Self {
440            bits: self.bits & !other.bits,
441        }
442    }
443}
444
445impl std::ops::BitOr for PaletteType {
446    type Output = Self;
447
448    /// Returns the union of the two sets of flags.
449    #[inline]
450    fn bitor(self, other: PaletteType) -> Self {
451        Self {
452            bits: self.bits | other.bits,
453        }
454    }
455}
456
457impl std::ops::BitOrAssign for PaletteType {
458    /// Adds the set of flags.
459    #[inline]
460    fn bitor_assign(&mut self, other: Self) {
461        self.bits |= other.bits;
462    }
463}
464
465impl std::ops::BitXor for PaletteType {
466    type Output = Self;
467
468    /// Returns the left flags, but with all the right flags toggled.
469    #[inline]
470    fn bitxor(self, other: Self) -> Self {
471        Self {
472            bits: self.bits ^ other.bits,
473        }
474    }
475}
476
477impl std::ops::BitXorAssign for PaletteType {
478    /// Toggles the set of flags.
479    #[inline]
480    fn bitxor_assign(&mut self, other: Self) {
481        self.bits ^= other.bits;
482    }
483}
484
485impl std::ops::BitAnd for PaletteType {
486    type Output = Self;
487
488    /// Returns the intersection between the two sets of flags.
489    #[inline]
490    fn bitand(self, other: Self) -> Self {
491        Self {
492            bits: self.bits & other.bits,
493        }
494    }
495}
496
497impl std::ops::BitAndAssign for PaletteType {
498    /// Disables all flags disabled in the set.
499    #[inline]
500    fn bitand_assign(&mut self, other: Self) {
501        self.bits &= other.bits;
502    }
503}
504
505impl std::ops::Sub for PaletteType {
506    type Output = Self;
507
508    /// Returns the set difference of the two sets of flags.
509    #[inline]
510    fn sub(self, other: Self) -> Self {
511        Self {
512            bits: self.bits & !other.bits,
513        }
514    }
515}
516
517impl std::ops::SubAssign for PaletteType {
518    /// Disables all flags enabled in the set.
519    #[inline]
520    fn sub_assign(&mut self, other: Self) {
521        self.bits &= !other.bits;
522    }
523}
524
525impl std::ops::Not for PaletteType {
526    type Output = Self;
527
528    /// Returns the complement of this set of flags.
529    #[inline]
530    fn not(self) -> Self {
531        Self { bits: !self.bits } & Self::all()
532    }
533}
534
535impl std::fmt::Debug for PaletteType {
536    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
537        let members: &[(&str, Self)] = &[
538            (
539                "USABLE_WITH_LIGHT_BACKGROUND",
540                Self::USABLE_WITH_LIGHT_BACKGROUND,
541            ),
542            (
543                "USABLE_WITH_DARK_BACKGROUND",
544                Self::USABLE_WITH_DARK_BACKGROUND,
545            ),
546        ];
547        let mut first = true;
548        for (name, value) in members {
549            if self.contains(*value) {
550                if !first {
551                    f.write_str(" | ")?;
552                }
553                first = false;
554                f.write_str(name)?;
555            }
556        }
557        if first {
558            f.write_str("(empty)")?;
559        }
560        Ok(())
561    }
562}
563
564impl std::fmt::Binary for PaletteType {
565    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
566        std::fmt::Binary::fmt(&self.bits, f)
567    }
568}
569
570impl std::fmt::Octal for PaletteType {
571    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
572        std::fmt::Octal::fmt(&self.bits, f)
573    }
574}
575
576impl std::fmt::LowerHex for PaletteType {
577    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
578        std::fmt::LowerHex::fmt(&self.bits, f)
579    }
580}
581
582impl std::fmt::UpperHex for PaletteType {
583    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
584        std::fmt::UpperHex::fmt(&self.bits, f)
585    }
586}
587
588impl font_types::Scalar for PaletteType {
589    type Raw = <u32 as font_types::Scalar>::Raw;
590    fn to_raw(self) -> Self::Raw {
591        self.bits().to_raw()
592    }
593    fn from_raw(raw: Self::Raw) -> Self {
594        let t = <u32>::from_raw(raw);
595        Self::from_bits_truncate(t)
596    }
597}
598
599#[cfg(feature = "experimental_traverse")]
600impl<'a> From<PaletteType> for FieldType<'a> {
601    fn from(src: PaletteType) -> FieldType<'a> {
602        src.bits().into()
603    }
604}
605
606/// [CPAL (Color Record)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-entries-and-color-records) record
607#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
608#[repr(C)]
609#[repr(packed)]
610pub struct ColorRecord {
611    /// Blue value (B0).
612    pub blue: u8,
613    /// Green value (B1).
614    pub green: u8,
615    ///     Red value (B2).
616    pub red: u8,
617    /// Alpha value (B3).
618    pub alpha: u8,
619}
620
621impl ColorRecord {
622    /// Blue value (B0).
623    pub fn blue(&self) -> u8 {
624        self.blue
625    }
626
627    /// Green value (B1).
628    pub fn green(&self) -> u8 {
629        self.green
630    }
631
632    ///     Red value (B2).
633    pub fn red(&self) -> u8 {
634        self.red
635    }
636
637    /// Alpha value (B3).
638    pub fn alpha(&self) -> u8 {
639        self.alpha
640    }
641}
642
643impl FixedSize for ColorRecord {
644    const RAW_BYTE_LEN: usize =
645        u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
646}
647
648#[cfg(feature = "experimental_traverse")]
649impl<'a> SomeRecord<'a> for ColorRecord {
650    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
651        RecordResolver {
652            name: "ColorRecord",
653            get_field: Box::new(move |idx, _data| match idx {
654                0usize => Some(Field::new("blue", self.blue())),
655                1usize => Some(Field::new("green", self.green())),
656                2usize => Some(Field::new("red", self.red())),
657                3usize => Some(Field::new("alpha", self.alpha())),
658                _ => None,
659            }),
660            data,
661        }
662    }
663}