Skip to main content

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