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