1#[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 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#[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 pub fn version(&self) -> u16 {
50 let range = self.version_byte_range();
51 self.data.read_at(range.start).ok().unwrap()
52 }
53
54 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 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 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 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 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 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 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 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 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 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 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 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 let end = start + u16::RAW_BYTE_LEN;
163 start..end
164 }
165
166 pub fn num_palette_entries_byte_range(&self) -> Range<usize> {
167 let start = self.version_byte_range().end;
168 let end = start + u16::RAW_BYTE_LEN;
169 start..end
170 }
171
172 pub fn num_palettes_byte_range(&self) -> Range<usize> {
173 let start = self.num_palette_entries_byte_range().end;
174 let end = start + u16::RAW_BYTE_LEN;
175 start..end
176 }
177
178 pub fn num_color_records_byte_range(&self) -> Range<usize> {
179 let start = self.num_palettes_byte_range().end;
180 let end = start + u16::RAW_BYTE_LEN;
181 start..end
182 }
183
184 pub fn color_records_array_offset_byte_range(&self) -> Range<usize> {
185 let start = self.num_color_records_byte_range().end;
186 let end = start + Offset32::RAW_BYTE_LEN;
187 start..end
188 }
189
190 pub fn color_record_indices_byte_range(&self) -> Range<usize> {
191 let num_palettes = self.num_palettes();
192 let start = self.color_records_array_offset_byte_range().end;
193 let end = start + (transforms::to_usize(num_palettes)).saturating_mul(u16::RAW_BYTE_LEN);
194 start..end
195 }
196
197 pub fn palette_types_array_offset_byte_range(&self) -> Range<usize> {
198 let start = self.color_record_indices_byte_range().end;
199 let end = if self.version().compatible(1u16) {
200 start + Offset32::RAW_BYTE_LEN
201 } else {
202 start
203 };
204 start..end
205 }
206
207 pub fn palette_labels_array_offset_byte_range(&self) -> Range<usize> {
208 let start = self.palette_types_array_offset_byte_range().end;
209 let end = if self.version().compatible(1u16) {
210 start + Offset32::RAW_BYTE_LEN
211 } else {
212 start
213 };
214 start..end
215 }
216
217 pub fn palette_entry_labels_array_offset_byte_range(&self) -> Range<usize> {
218 let start = self.palette_labels_array_offset_byte_range().end;
219 let end = if self.version().compatible(1u16) {
220 start + Offset32::RAW_BYTE_LEN
221 } else {
222 start
223 };
224 start..end
225 }
226}
227
228const _: () = assert!(FontData::default_data_long_enough(Cpal::MIN_SIZE));
229
230impl Default for Cpal<'_> {
231 fn default() -> Self {
232 Self {
233 data: FontData::default_table_data(),
234 }
235 }
236}
237
238#[cfg(feature = "experimental_traverse")]
239impl<'a> SomeTable<'a> for Cpal<'a> {
240 fn type_name(&self) -> &str {
241 "Cpal"
242 }
243 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
244 match idx {
245 0usize => Some(Field::new("version", self.version())),
246 1usize => Some(Field::new(
247 "num_palette_entries",
248 self.num_palette_entries(),
249 )),
250 2usize => Some(Field::new("num_palettes", self.num_palettes())),
251 3usize => Some(Field::new("num_color_records", self.num_color_records())),
252 4usize => Some(Field::new(
253 "color_records_array_offset",
254 traversal::FieldType::offset_to_array_of_records(
255 self.color_records_array_offset(),
256 self.color_records_array(),
257 stringify!(ColorRecord),
258 self.offset_data(),
259 ),
260 )),
261 5usize => Some(Field::new(
262 "color_record_indices",
263 self.color_record_indices(),
264 )),
265 6usize if self.version().compatible(1u16) => Some(Field::new(
266 "palette_types_array_offset",
267 FieldType::offset_to_array_of_scalars(
268 self.palette_types_array_offset().unwrap(),
269 self.palette_types_array(),
270 ),
271 )),
272 7usize if self.version().compatible(1u16) => Some(Field::new(
273 "palette_labels_array_offset",
274 FieldType::offset_to_array_of_scalars(
275 self.palette_labels_array_offset().unwrap(),
276 self.palette_labels_array(),
277 ),
278 )),
279 8usize if self.version().compatible(1u16) => Some(Field::new(
280 "palette_entry_labels_array_offset",
281 FieldType::offset_to_array_of_scalars(
282 self.palette_entry_labels_array_offset().unwrap(),
283 self.palette_entry_labels_array(),
284 ),
285 )),
286 _ => None,
287 }
288 }
289}
290
291#[cfg(feature = "experimental_traverse")]
292#[allow(clippy::needless_lifetimes)]
293impl<'a> std::fmt::Debug for Cpal<'a> {
294 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
295 (self as &dyn SomeTable<'a>).fmt(f)
296 }
297}
298
299#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
301#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
302#[repr(transparent)]
303pub struct PaletteType {
304 bits: u32,
305}
306
307impl PaletteType {
308 pub const USABLE_WITH_LIGHT_BACKGROUND: Self = Self { bits: 0x0001 };
310
311 pub const USABLE_WITH_DARK_BACKGROUND: Self = Self { bits: 0x0002 };
313}
314
315impl PaletteType {
316 #[inline]
318 pub const fn empty() -> Self {
319 Self { bits: 0 }
320 }
321
322 #[inline]
324 pub const fn all() -> Self {
325 Self {
326 bits: Self::USABLE_WITH_LIGHT_BACKGROUND.bits | Self::USABLE_WITH_DARK_BACKGROUND.bits,
327 }
328 }
329
330 #[inline]
332 pub const fn bits(&self) -> u32 {
333 self.bits
334 }
335
336 #[inline]
339 pub const fn from_bits(bits: u32) -> Option<Self> {
340 if (bits & !Self::all().bits()) == 0 {
341 Some(Self { bits })
342 } else {
343 None
344 }
345 }
346
347 #[inline]
350 pub const fn from_bits_truncate(bits: u32) -> Self {
351 Self {
352 bits: bits & Self::all().bits,
353 }
354 }
355
356 #[inline]
358 pub const fn is_empty(&self) -> bool {
359 self.bits() == Self::empty().bits()
360 }
361
362 #[inline]
364 pub const fn intersects(&self, other: Self) -> bool {
365 !(Self {
366 bits: self.bits & other.bits,
367 })
368 .is_empty()
369 }
370
371 #[inline]
373 pub const fn contains(&self, other: Self) -> bool {
374 (self.bits & other.bits) == other.bits
375 }
376
377 #[inline]
379 pub fn insert(&mut self, other: Self) {
380 self.bits |= other.bits;
381 }
382
383 #[inline]
385 pub fn remove(&mut self, other: Self) {
386 self.bits &= !other.bits;
387 }
388
389 #[inline]
391 pub fn toggle(&mut self, other: Self) {
392 self.bits ^= other.bits;
393 }
394
395 #[inline]
406 #[must_use]
407 pub const fn intersection(self, other: Self) -> Self {
408 Self {
409 bits: self.bits & other.bits,
410 }
411 }
412
413 #[inline]
424 #[must_use]
425 pub const fn union(self, other: Self) -> Self {
426 Self {
427 bits: self.bits | other.bits,
428 }
429 }
430
431 #[inline]
444 #[must_use]
445 pub const fn difference(self, other: Self) -> Self {
446 Self {
447 bits: self.bits & !other.bits,
448 }
449 }
450}
451
452impl std::ops::BitOr for PaletteType {
453 type Output = Self;
454
455 #[inline]
457 fn bitor(self, other: PaletteType) -> Self {
458 Self {
459 bits: self.bits | other.bits,
460 }
461 }
462}
463
464impl std::ops::BitOrAssign for PaletteType {
465 #[inline]
467 fn bitor_assign(&mut self, other: Self) {
468 self.bits |= other.bits;
469 }
470}
471
472impl std::ops::BitXor for PaletteType {
473 type Output = Self;
474
475 #[inline]
477 fn bitxor(self, other: Self) -> Self {
478 Self {
479 bits: self.bits ^ other.bits,
480 }
481 }
482}
483
484impl std::ops::BitXorAssign for PaletteType {
485 #[inline]
487 fn bitxor_assign(&mut self, other: Self) {
488 self.bits ^= other.bits;
489 }
490}
491
492impl std::ops::BitAnd for PaletteType {
493 type Output = Self;
494
495 #[inline]
497 fn bitand(self, other: Self) -> Self {
498 Self {
499 bits: self.bits & other.bits,
500 }
501 }
502}
503
504impl std::ops::BitAndAssign for PaletteType {
505 #[inline]
507 fn bitand_assign(&mut self, other: Self) {
508 self.bits &= other.bits;
509 }
510}
511
512impl std::ops::Sub for PaletteType {
513 type Output = Self;
514
515 #[inline]
517 fn sub(self, other: Self) -> Self {
518 Self {
519 bits: self.bits & !other.bits,
520 }
521 }
522}
523
524impl std::ops::SubAssign for PaletteType {
525 #[inline]
527 fn sub_assign(&mut self, other: Self) {
528 self.bits &= !other.bits;
529 }
530}
531
532impl std::ops::Not for PaletteType {
533 type Output = Self;
534
535 #[inline]
537 fn not(self) -> Self {
538 Self { bits: !self.bits } & Self::all()
539 }
540}
541
542impl std::fmt::Debug for PaletteType {
543 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
544 let members: &[(&str, Self)] = &[
545 (
546 "USABLE_WITH_LIGHT_BACKGROUND",
547 Self::USABLE_WITH_LIGHT_BACKGROUND,
548 ),
549 (
550 "USABLE_WITH_DARK_BACKGROUND",
551 Self::USABLE_WITH_DARK_BACKGROUND,
552 ),
553 ];
554 let mut first = true;
555 for (name, value) in members {
556 if self.contains(*value) {
557 if !first {
558 f.write_str(" | ")?;
559 }
560 first = false;
561 f.write_str(name)?;
562 }
563 }
564 if first {
565 f.write_str("(empty)")?;
566 }
567 Ok(())
568 }
569}
570
571impl std::fmt::Binary for PaletteType {
572 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
573 std::fmt::Binary::fmt(&self.bits, f)
574 }
575}
576
577impl std::fmt::Octal for PaletteType {
578 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
579 std::fmt::Octal::fmt(&self.bits, f)
580 }
581}
582
583impl std::fmt::LowerHex for PaletteType {
584 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
585 std::fmt::LowerHex::fmt(&self.bits, f)
586 }
587}
588
589impl std::fmt::UpperHex for PaletteType {
590 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
591 std::fmt::UpperHex::fmt(&self.bits, f)
592 }
593}
594
595impl font_types::Scalar for PaletteType {
596 type Raw = <u32 as font_types::Scalar>::Raw;
597 fn to_raw(self) -> Self::Raw {
598 self.bits().to_raw()
599 }
600 fn from_raw(raw: Self::Raw) -> Self {
601 let t = <u32>::from_raw(raw);
602 Self::from_bits_truncate(t)
603 }
604}
605
606#[cfg(feature = "experimental_traverse")]
607impl<'a> From<PaletteType> for FieldType<'a> {
608 fn from(src: PaletteType) -> FieldType<'a> {
609 src.bits().into()
610 }
611}
612
613#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
617#[repr(C)]
618#[repr(packed)]
619pub struct ColorRecord {
620 pub blue: u8,
622 pub green: u8,
624 pub red: u8,
626 pub alpha: u8,
628}
629
630impl ColorRecord {
631 pub fn blue(&self) -> u8 {
633 self.blue
634 }
635
636 pub fn green(&self) -> u8 {
638 self.green
639 }
640
641 pub fn red(&self) -> u8 {
643 self.red
644 }
645
646 pub fn alpha(&self) -> u8 {
648 self.alpha
649 }
650}
651
652impl FixedSize for ColorRecord {
653 const RAW_BYTE_LEN: usize =
654 u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
655}
656
657#[cfg(feature = "experimental_traverse")]
658impl<'a> SomeRecord<'a> for ColorRecord {
659 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
660 RecordResolver {
661 name: "ColorRecord",
662 get_field: Box::new(move |idx, _data| match idx {
663 0usize => Some(Field::new("blue", self.blue())),
664 1usize => Some(Field::new("green", self.green())),
665 2usize => Some(Field::new("red", self.red())),
666 3usize => Some(Field::new("alpha", self.alpha())),
667 _ => None,
668 }),
669 data,
670 }
671 }
672}