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 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#[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 pub const USABLE_WITH_LIGHT_BACKGROUND: Self = Self { bits: 0x0001 };
298
299 pub const USABLE_WITH_DARK_BACKGROUND: Self = Self { bits: 0x0002 };
301}
302
303impl PaletteType {
304 #[inline]
306 pub const fn empty() -> Self {
307 Self { bits: 0 }
308 }
309
310 #[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 #[inline]
320 pub const fn bits(&self) -> u32 {
321 self.bits
322 }
323
324 #[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 #[inline]
338 pub const fn from_bits_truncate(bits: u32) -> Self {
339 Self {
340 bits: bits & Self::all().bits,
341 }
342 }
343
344 #[inline]
346 pub const fn is_empty(&self) -> bool {
347 self.bits() == Self::empty().bits()
348 }
349
350 #[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 #[inline]
361 pub const fn contains(&self, other: Self) -> bool {
362 (self.bits & other.bits) == other.bits
363 }
364
365 #[inline]
367 pub fn insert(&mut self, other: Self) {
368 self.bits |= other.bits;
369 }
370
371 #[inline]
373 pub fn remove(&mut self, other: Self) {
374 self.bits &= !other.bits;
375 }
376
377 #[inline]
379 pub fn toggle(&mut self, other: Self) {
380 self.bits ^= other.bits;
381 }
382
383 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
605#[repr(C)]
606#[repr(packed)]
607pub struct ColorRecord {
608 pub blue: u8,
610 pub green: u8,
612 pub red: u8,
614 pub alpha: u8,
616}
617
618impl ColorRecord {
619 pub fn blue(&self) -> u8 {
621 self.blue
622 }
623
624 pub fn green(&self) -> u8 {
626 self.green
627 }
628
629 pub fn red(&self) -> u8 {
631 self.red
632 }
633
634 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}