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
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#[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 pub const USABLE_WITH_LIGHT_BACKGROUND: Self = Self { bits: 0x0001 };
288
289 pub const USABLE_WITH_DARK_BACKGROUND: Self = Self { bits: 0x0002 };
291}
292
293impl PaletteType {
294 #[inline]
296 pub const fn empty() -> Self {
297 Self { bits: 0 }
298 }
299
300 #[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 #[inline]
310 pub const fn bits(&self) -> u32 {
311 self.bits
312 }
313
314 #[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 #[inline]
328 pub const fn from_bits_truncate(bits: u32) -> Self {
329 Self {
330 bits: bits & Self::all().bits,
331 }
332 }
333
334 #[inline]
336 pub const fn is_empty(&self) -> bool {
337 self.bits() == Self::empty().bits()
338 }
339
340 #[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 #[inline]
351 pub const fn contains(&self, other: Self) -> bool {
352 (self.bits & other.bits) == other.bits
353 }
354
355 #[inline]
357 pub fn insert(&mut self, other: Self) {
358 self.bits |= other.bits;
359 }
360
361 #[inline]
363 pub fn remove(&mut self, other: Self) {
364 self.bits &= !other.bits;
365 }
366
367 #[inline]
369 pub fn toggle(&mut self, other: Self) {
370 self.bits ^= other.bits;
371 }
372
373 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
595#[repr(C)]
596#[repr(packed)]
597pub struct ColorRecord {
598 pub blue: u8,
600 pub green: u8,
602 pub red: u8,
604 pub alpha: u8,
606}
607
608impl ColorRecord {
609 pub fn blue(&self) -> u8 {
611 self.blue
612 }
613
614 pub fn green(&self) -> u8 {
616 self.green
617 }
618
619 pub fn red(&self) -> u8 {
621 self.red
622 }
623
624 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}