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
216const _: () = assert!(FontData::default_data_long_enough(Cpal::MIN_SIZE));
217
218impl Default for Cpal<'_> {
219    fn default() -> Self {
220        Self {
221            data: FontData::default_table_data(),
222        }
223    }
224}
225
226#[cfg(feature = "experimental_traverse")]
227impl<'a> SomeTable<'a> for Cpal<'a> {
228    fn type_name(&self) -> &str {
229        "Cpal"
230    }
231    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
232        match idx {
233            0usize => Some(Field::new("version", self.version())),
234            1usize => Some(Field::new(
235                "num_palette_entries",
236                self.num_palette_entries(),
237            )),
238            2usize => Some(Field::new("num_palettes", self.num_palettes())),
239            3usize => Some(Field::new("num_color_records", self.num_color_records())),
240            4usize => Some(Field::new(
241                "color_records_array_offset",
242                traversal::FieldType::offset_to_array_of_records(
243                    self.color_records_array_offset(),
244                    self.color_records_array(),
245                    stringify!(ColorRecord),
246                    self.offset_data(),
247                ),
248            )),
249            5usize => Some(Field::new(
250                "color_record_indices",
251                self.color_record_indices(),
252            )),
253            6usize if self.version().compatible(1u16) => Some(Field::new(
254                "palette_types_array_offset",
255                FieldType::offset_to_array_of_scalars(
256                    self.palette_types_array_offset().unwrap(),
257                    self.palette_types_array(),
258                ),
259            )),
260            7usize if self.version().compatible(1u16) => Some(Field::new(
261                "palette_labels_array_offset",
262                FieldType::offset_to_array_of_scalars(
263                    self.palette_labels_array_offset().unwrap(),
264                    self.palette_labels_array(),
265                ),
266            )),
267            8usize if self.version().compatible(1u16) => Some(Field::new(
268                "palette_entry_labels_array_offset",
269                FieldType::offset_to_array_of_scalars(
270                    self.palette_entry_labels_array_offset().unwrap(),
271                    self.palette_entry_labels_array(),
272                ),
273            )),
274            _ => None,
275        }
276    }
277}
278
279#[cfg(feature = "experimental_traverse")]
280#[allow(clippy::needless_lifetimes)]
281impl<'a> std::fmt::Debug for Cpal<'a> {
282    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283        (self as &dyn SomeTable<'a>).fmt(f)
284    }
285}
286
287/// The [PaletteType](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-type-array) flags.
288#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
289#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
290#[repr(transparent)]
291pub struct PaletteType {
292    bits: u32,
293}
294
295impl PaletteType {
296    /// Bit 0: palette is appropriate to use when displaying the font on a light background such as white.
297    pub const USABLE_WITH_LIGHT_BACKGROUND: Self = Self { bits: 0x0001 };
298
299    /// Bit 1: palette is appropriate to use when displaying the font on a dark background such as black.
300    pub const USABLE_WITH_DARK_BACKGROUND: Self = Self { bits: 0x0002 };
301}
302
303impl PaletteType {
304    ///  Returns an empty set of flags.
305    #[inline]
306    pub const fn empty() -> Self {
307        Self { bits: 0 }
308    }
309
310    /// Returns the set containing all flags.
311    #[inline]
312    pub const fn all() -> Self {
313        Self {
314            bits: Self::USABLE_WITH_LIGHT_BACKGROUND.bits | Self::USABLE_WITH_DARK_BACKGROUND.bits,
315        }
316    }
317
318    /// Returns the raw value of the flags currently stored.
319    #[inline]
320    pub const fn bits(&self) -> u32 {
321        self.bits
322    }
323
324    /// Convert from underlying bit representation, unless that
325    /// representation contains bits that do not correspond to a flag.
326    #[inline]
327    pub const fn from_bits(bits: u32) -> Option<Self> {
328        if (bits & !Self::all().bits()) == 0 {
329            Some(Self { bits })
330        } else {
331            None
332        }
333    }
334
335    /// Convert from underlying bit representation, dropping any bits
336    /// that do not correspond to flags.
337    #[inline]
338    pub const fn from_bits_truncate(bits: u32) -> Self {
339        Self {
340            bits: bits & Self::all().bits,
341        }
342    }
343
344    /// Returns `true` if no flags are currently stored.
345    #[inline]
346    pub const fn is_empty(&self) -> bool {
347        self.bits() == Self::empty().bits()
348    }
349
350    /// Returns `true` if there are flags common to both `self` and `other`.
351    #[inline]
352    pub const fn intersects(&self, other: Self) -> bool {
353        !(Self {
354            bits: self.bits & other.bits,
355        })
356        .is_empty()
357    }
358
359    /// Returns `true` if all of the flags in `other` are contained within `self`.
360    #[inline]
361    pub const fn contains(&self, other: Self) -> bool {
362        (self.bits & other.bits) == other.bits
363    }
364
365    /// Inserts the specified flags in-place.
366    #[inline]
367    pub fn insert(&mut self, other: Self) {
368        self.bits |= other.bits;
369    }
370
371    /// Removes the specified flags in-place.
372    #[inline]
373    pub fn remove(&mut self, other: Self) {
374        self.bits &= !other.bits;
375    }
376
377    /// Toggles the specified flags in-place.
378    #[inline]
379    pub fn toggle(&mut self, other: Self) {
380        self.bits ^= other.bits;
381    }
382
383    /// Returns the intersection between the flags in `self` and
384    /// `other`.
385    ///
386    /// Specifically, the returned set contains only the flags which are
387    /// present in *both* `self` *and* `other`.
388    ///
389    /// This is equivalent to using the `&` operator (e.g.
390    /// [`ops::BitAnd`]), as in `flags & other`.
391    ///
392    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
393    #[inline]
394    #[must_use]
395    pub const fn intersection(self, other: Self) -> Self {
396        Self {
397            bits: self.bits & other.bits,
398        }
399    }
400
401    /// Returns the union of between the flags in `self` and `other`.
402    ///
403    /// Specifically, the returned set contains all flags which are
404    /// present in *either* `self` *or* `other`, including any which are
405    /// present in both.
406    ///
407    /// This is equivalent to using the `|` operator (e.g.
408    /// [`ops::BitOr`]), as in `flags | other`.
409    ///
410    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
411    #[inline]
412    #[must_use]
413    pub const fn union(self, other: Self) -> Self {
414        Self {
415            bits: self.bits | other.bits,
416        }
417    }
418
419    /// Returns the difference between the flags in `self` and `other`.
420    ///
421    /// Specifically, the returned set contains all flags present in
422    /// `self`, except for the ones present in `other`.
423    ///
424    /// It is also conceptually equivalent to the "bit-clear" operation:
425    /// `flags & !other` (and this syntax is also supported).
426    ///
427    /// This is equivalent to using the `-` operator (e.g.
428    /// [`ops::Sub`]), as in `flags - other`.
429    ///
430    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
431    #[inline]
432    #[must_use]
433    pub const fn difference(self, other: Self) -> Self {
434        Self {
435            bits: self.bits & !other.bits,
436        }
437    }
438}
439
440impl std::ops::BitOr for PaletteType {
441    type Output = Self;
442
443    /// Returns the union of the two sets of flags.
444    #[inline]
445    fn bitor(self, other: PaletteType) -> Self {
446        Self {
447            bits: self.bits | other.bits,
448        }
449    }
450}
451
452impl std::ops::BitOrAssign for PaletteType {
453    /// Adds the set of flags.
454    #[inline]
455    fn bitor_assign(&mut self, other: Self) {
456        self.bits |= other.bits;
457    }
458}
459
460impl std::ops::BitXor for PaletteType {
461    type Output = Self;
462
463    /// Returns the left flags, but with all the right flags toggled.
464    #[inline]
465    fn bitxor(self, other: Self) -> Self {
466        Self {
467            bits: self.bits ^ other.bits,
468        }
469    }
470}
471
472impl std::ops::BitXorAssign for PaletteType {
473    /// Toggles the set of flags.
474    #[inline]
475    fn bitxor_assign(&mut self, other: Self) {
476        self.bits ^= other.bits;
477    }
478}
479
480impl std::ops::BitAnd for PaletteType {
481    type Output = Self;
482
483    /// Returns the intersection between the two sets of flags.
484    #[inline]
485    fn bitand(self, other: Self) -> Self {
486        Self {
487            bits: self.bits & other.bits,
488        }
489    }
490}
491
492impl std::ops::BitAndAssign for PaletteType {
493    /// Disables all flags disabled in the set.
494    #[inline]
495    fn bitand_assign(&mut self, other: Self) {
496        self.bits &= other.bits;
497    }
498}
499
500impl std::ops::Sub for PaletteType {
501    type Output = Self;
502
503    /// Returns the set difference of the two sets of flags.
504    #[inline]
505    fn sub(self, other: Self) -> Self {
506        Self {
507            bits: self.bits & !other.bits,
508        }
509    }
510}
511
512impl std::ops::SubAssign for PaletteType {
513    /// Disables all flags enabled in the set.
514    #[inline]
515    fn sub_assign(&mut self, other: Self) {
516        self.bits &= !other.bits;
517    }
518}
519
520impl std::ops::Not for PaletteType {
521    type Output = Self;
522
523    /// Returns the complement of this set of flags.
524    #[inline]
525    fn not(self) -> Self {
526        Self { bits: !self.bits } & Self::all()
527    }
528}
529
530impl std::fmt::Debug for PaletteType {
531    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
532        let members: &[(&str, Self)] = &[
533            (
534                "USABLE_WITH_LIGHT_BACKGROUND",
535                Self::USABLE_WITH_LIGHT_BACKGROUND,
536            ),
537            (
538                "USABLE_WITH_DARK_BACKGROUND",
539                Self::USABLE_WITH_DARK_BACKGROUND,
540            ),
541        ];
542        let mut first = true;
543        for (name, value) in members {
544            if self.contains(*value) {
545                if !first {
546                    f.write_str(" | ")?;
547                }
548                first = false;
549                f.write_str(name)?;
550            }
551        }
552        if first {
553            f.write_str("(empty)")?;
554        }
555        Ok(())
556    }
557}
558
559impl std::fmt::Binary for PaletteType {
560    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
561        std::fmt::Binary::fmt(&self.bits, f)
562    }
563}
564
565impl std::fmt::Octal for PaletteType {
566    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
567        std::fmt::Octal::fmt(&self.bits, f)
568    }
569}
570
571impl std::fmt::LowerHex for PaletteType {
572    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
573        std::fmt::LowerHex::fmt(&self.bits, f)
574    }
575}
576
577impl std::fmt::UpperHex for PaletteType {
578    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
579        std::fmt::UpperHex::fmt(&self.bits, f)
580    }
581}
582
583impl font_types::Scalar for PaletteType {
584    type Raw = <u32 as font_types::Scalar>::Raw;
585    fn to_raw(self) -> Self::Raw {
586        self.bits().to_raw()
587    }
588    fn from_raw(raw: Self::Raw) -> Self {
589        let t = <u32>::from_raw(raw);
590        Self::from_bits_truncate(t)
591    }
592}
593
594#[cfg(feature = "experimental_traverse")]
595impl<'a> From<PaletteType> for FieldType<'a> {
596    fn from(src: PaletteType) -> FieldType<'a> {
597        src.bits().into()
598    }
599}
600
601/// [CPAL (Color Record)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-entries-and-color-records) record
602///
603/// Contains a color in non-premultiplied BGRA form, in the sRGB color space.
604#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
605#[repr(C)]
606#[repr(packed)]
607pub struct ColorRecord {
608    /// Blue value (B0).
609    pub blue: u8,
610    /// Green value (B1).
611    pub green: u8,
612    /// Red value (B2).
613    pub red: u8,
614    /// Alpha value (B3).
615    pub alpha: u8,
616}
617
618impl ColorRecord {
619    /// Blue value (B0).
620    pub fn blue(&self) -> u8 {
621        self.blue
622    }
623
624    /// Green value (B1).
625    pub fn green(&self) -> u8 {
626        self.green
627    }
628
629    /// Red value (B2).
630    pub fn red(&self) -> u8 {
631        self.red
632    }
633
634    /// Alpha value (B3).
635    pub fn alpha(&self) -> u8 {
636        self.alpha
637    }
638}
639
640impl FixedSize for ColorRecord {
641    const RAW_BYTE_LEN: usize =
642        u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
643}
644
645#[cfg(feature = "experimental_traverse")]
646impl<'a> SomeRecord<'a> for ColorRecord {
647    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
648        RecordResolver {
649            name: "ColorRecord",
650            get_field: Box::new(move |idx, _data| match idx {
651                0usize => Some(Field::new("blue", self.blue())),
652                1usize => Some(Field::new("green", self.green())),
653                2usize => Some(Field::new("red", self.red())),
654                3usize => Some(Field::new("alpha", self.alpha())),
655                _ => None,
656            }),
657            data,
658        }
659    }
660}