1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Stat<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.offset_to_axis_value_offsets_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.offset_data().as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl TopLevelTable for Stat<'_> {
19 const TAG: Tag = Tag::new(b"STAT");
21}
22
23impl ReadArgs for Stat<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Stat<'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 let Some(data) = TableDataRef::new(data.as_bytes()) else {
34 return Err(ReadError::OutOfBounds);
35 };
36 Ok(Self { data })
37 }
38}
39
40#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
42#[repr(C, packed)]
43#[doc(hidden)]
44pub struct StatFixedHeader {
45 pub version: BigEndian<MajorMinor>,
46 pub design_axis_size: BigEndian<u16>,
47 pub design_axis_count: BigEndian<u16>,
48 pub design_axes_offset: BigEndian<Offset32>,
49 pub axis_value_count: BigEndian<u16>,
50 pub offset_to_axis_value_offsets: BigEndian<Nullable<Offset32>>,
51}
52
53#[allow(clippy::absurd_extreme_comparisons)]
54const _: () = assert!(std::mem::size_of::<StatFixedHeader>() <= Stat::MIN_SIZE);
55
56#[derive(Clone)]
58pub struct Stat<'a> {
59 data: TableDataRef<'a, StatFixedHeader>,
60}
61
62#[allow(clippy::needless_lifetimes)]
63impl<'a> Stat<'a> {
64 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
65 + u16::RAW_BYTE_LEN
66 + u16::RAW_BYTE_LEN
67 + Offset32::RAW_BYTE_LEN
68 + u16::RAW_BYTE_LEN
69 + Offset32::RAW_BYTE_LEN);
70 basic_table_impls!(impl_the_methods);
71
72 pub fn version(&self) -> MajorMinor {
74 self.data.header().version.get()
75 }
76
77 pub fn design_axis_size(&self) -> u16 {
79 self.data.header().design_axis_size.get()
80 }
81
82 pub fn design_axis_count(&self) -> u16 {
87 self.data.header().design_axis_count.get()
88 }
89
90 pub fn design_axes_offset(&self) -> Offset32 {
95 self.data.header().design_axes_offset.get()
96 }
97
98 pub fn design_axes(&self) -> Result<&'a [AxisRecord], ReadError> {
100 let data = self.offset_data();
101 let args = self.design_axis_count();
102 self.design_axes_offset().resolve_with_args(data, args)
103 }
104
105 pub fn axis_value_count(&self) -> u16 {
107 self.data.header().axis_value_count.get()
108 }
109
110 pub fn offset_to_axis_value_offsets(&self) -> Nullable<Offset32> {
115 self.data.header().offset_to_axis_value_offsets.get()
116 }
117
118 pub fn offset_to_axis_values(&self) -> Option<Result<AxisValueArray<'a>, ReadError>> {
120 let data = self.offset_data();
121 let args = self.axis_value_count();
122 self.offset_to_axis_value_offsets()
123 .resolve_with_args(data, args)
124 }
125
126 pub fn elided_fallback_name_id(&self) -> Option<NameId> {
130 let range = self.elided_fallback_name_id_byte_range();
131 (!range.is_empty())
132 .then(|| self.offset_data().read_at(range.start).ok())
133 .flatten()
134 }
135
136 pub fn version_byte_range(&self) -> Range<usize> {
137 let start = 0;
138 let end = start + MajorMinor::RAW_BYTE_LEN;
139 start..end
140 }
141
142 pub fn design_axis_size_byte_range(&self) -> Range<usize> {
143 let start = self.version_byte_range().end;
144 let end = start + u16::RAW_BYTE_LEN;
145 start..end
146 }
147
148 pub fn design_axis_count_byte_range(&self) -> Range<usize> {
149 let start = self.design_axis_size_byte_range().end;
150 let end = start + u16::RAW_BYTE_LEN;
151 start..end
152 }
153
154 pub fn design_axes_offset_byte_range(&self) -> Range<usize> {
155 let start = self.design_axis_count_byte_range().end;
156 let end = start + Offset32::RAW_BYTE_LEN;
157 start..end
158 }
159
160 pub fn axis_value_count_byte_range(&self) -> Range<usize> {
161 let start = self.design_axes_offset_byte_range().end;
162 let end = start + u16::RAW_BYTE_LEN;
163 start..end
164 }
165
166 pub fn offset_to_axis_value_offsets_byte_range(&self) -> Range<usize> {
167 let start = self.axis_value_count_byte_range().end;
168 let end = start + Offset32::RAW_BYTE_LEN;
169 start..end
170 }
171
172 pub fn elided_fallback_name_id_byte_range(&self) -> Range<usize> {
173 let start = self.offset_to_axis_value_offsets_byte_range().end;
174 let end = if self.version().compatible((1u16, 1u16)) {
175 start + NameId::RAW_BYTE_LEN
176 } else {
177 start
178 };
179 start..end
180 }
181}
182
183const _: () = assert!(FontData::default_data_long_enough(Stat::MIN_SIZE));
184
185impl Default for Stat<'_> {
186 fn default() -> Self {
187 Self {
188 data: TableDataRef::new(FontData::default_table_data().as_bytes())
189 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
190 }
191 }
192}
193
194#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
196#[repr(C)]
197#[repr(packed)]
198pub struct AxisRecord {
199 pub axis_tag: BigEndian<Tag>,
201 pub axis_name_id: BigEndian<NameId>,
204 pub axis_ordering: BigEndian<u16>,
208}
209
210impl AxisRecord {
211 pub fn axis_tag(&self) -> Tag {
213 self.axis_tag.get()
214 }
215
216 pub fn axis_name_id(&self) -> NameId {
219 self.axis_name_id.get()
220 }
221
222 pub fn axis_ordering(&self) -> u16 {
226 self.axis_ordering.get()
227 }
228}
229
230impl FixedSize for AxisRecord {
231 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
232}
233
234impl<'a> MinByteRange<'a> for AxisValueArray<'a> {
235 fn min_byte_range(&self) -> Range<usize> {
236 0..self.axis_value_offsets_byte_range().end
237 }
238 fn min_table_bytes(&self) -> &'a [u8] {
239 let range = self.min_byte_range();
240 self.offset_data().as_bytes().get(range).unwrap_or_default()
241 }
242}
243
244impl ReadArgs for AxisValueArray<'_> {
245 type Args = u16;
246}
247
248impl<'a> FontRead<'a> for AxisValueArray<'a> {
249 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
250 let axis_value_count = args;
251
252 #[allow(clippy::absurd_extreme_comparisons)]
253 if data.len() < Self::MIN_SIZE {
254 return Err(ReadError::OutOfBounds);
255 }
256 let Some(data) = TableDataRef::new(data.as_bytes()) else {
257 return Err(ReadError::OutOfBounds);
258 };
259 Ok(Self {
260 data,
261 axis_value_count,
262 })
263 }
264}
265
266impl<'a> AxisValueArray<'a> {
267 pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
272 let args = axis_value_count;
273 Self::read_with_args(data, args)
274 }
275}
276
277#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
279#[repr(C, packed)]
280#[doc(hidden)]
281pub struct AxisValueArrayFixedHeader {}
282
283#[allow(clippy::absurd_extreme_comparisons)]
284const _: () = assert!(std::mem::size_of::<AxisValueArrayFixedHeader>() <= AxisValueArray::MIN_SIZE);
285
286#[derive(Clone)]
288pub struct AxisValueArray<'a> {
289 data: TableDataRef<'a, AxisValueArrayFixedHeader>,
290 axis_value_count: u16,
291}
292
293#[allow(clippy::needless_lifetimes)]
294impl<'a> AxisValueArray<'a> {
295 pub const MIN_SIZE: usize = 0;
296 basic_table_impls!(impl_the_methods);
297
298 pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
301 let range = self.axis_value_offsets_byte_range();
302 self.offset_data()
303 .read_array(range)
304 .ok()
305 .unwrap_or_default()
306 }
307
308 pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
310 let data = self.offset_data();
311 let offsets = self.axis_value_offsets();
312 ArrayOfOffsets::new(offsets, data, ())
313 }
314
315 pub(crate) fn axis_value_count(&self) -> u16 {
316 self.axis_value_count
317 }
318
319 pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
320 let axis_value_count = self.axis_value_count();
321 let start = 0;
322 let end =
323 start + (transforms::to_usize(axis_value_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
324 start..end
325 }
326}
327
328#[allow(clippy::absurd_extreme_comparisons)]
329const _: () = assert!(FontData::default_data_long_enough(AxisValueArray::MIN_SIZE));
330
331impl Default for AxisValueArray<'_> {
332 fn default() -> Self {
333 Self {
334 data: TableDataRef::new(FontData::default_table_data().as_bytes())
335 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
336 axis_value_count: Default::default(),
337 }
338 }
339}
340
341#[derive(Clone)]
343pub enum AxisValue<'a> {
344 Format1(AxisValueFormat1<'a>),
345 Format2(AxisValueFormat2<'a>),
346 Format3(AxisValueFormat3<'a>),
347 Format4(AxisValueFormat4<'a>),
348}
349
350impl Default for AxisValue<'_> {
351 fn default() -> Self {
352 Self::Format1(Default::default())
353 }
354}
355
356impl<'a> AxisValue<'a> {
357 pub fn offset_data(&self) -> FontData<'a> {
359 match self {
360 Self::Format1(item) => item.offset_data(),
361 Self::Format2(item) => item.offset_data(),
362 Self::Format3(item) => item.offset_data(),
363 Self::Format4(item) => item.offset_data(),
364 }
365 }
366
367 pub fn format(&self) -> u16 {
369 match self {
370 Self::Format1(item) => item.format(),
371 Self::Format2(item) => item.format(),
372 Self::Format3(item) => item.format(),
373 Self::Format4(item) => item.format(),
374 }
375 }
376
377 pub fn flags(&self) -> AxisValueTableFlags {
379 match self {
380 Self::Format1(item) => item.flags(),
381 Self::Format2(item) => item.flags(),
382 Self::Format3(item) => item.flags(),
383 Self::Format4(item) => item.flags(),
384 }
385 }
386
387 pub fn value_name_id(&self) -> NameId {
390 match self {
391 Self::Format1(item) => item.value_name_id(),
392 Self::Format2(item) => item.value_name_id(),
393 Self::Format3(item) => item.value_name_id(),
394 Self::Format4(item) => item.value_name_id(),
395 }
396 }
397}
398
399impl ReadArgs for AxisValue<'_> {
400 type Args = ();
401}
402
403impl<'a> FontRead<'a> for AxisValue<'a> {
404 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
405 let format: u16 = data.read_at(0usize)?;
406 match format {
407 AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
408 AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
409 AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
410 AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
411 other => Err(ReadError::InvalidFormat(other.into())),
412 }
413 }
414}
415
416impl<'a> MinByteRange<'a> for AxisValue<'a> {
417 fn min_byte_range(&self) -> Range<usize> {
418 match self {
419 Self::Format1(item) => item.min_byte_range(),
420 Self::Format2(item) => item.min_byte_range(),
421 Self::Format3(item) => item.min_byte_range(),
422 Self::Format4(item) => item.min_byte_range(),
423 }
424 }
425 fn min_table_bytes(&self) -> &'a [u8] {
426 match self {
427 Self::Format1(item) => item.min_table_bytes(),
428 Self::Format2(item) => item.min_table_bytes(),
429 Self::Format3(item) => item.min_table_bytes(),
430 Self::Format4(item) => item.min_table_bytes(),
431 }
432 }
433}
434
435impl Format<u16> for AxisValueFormat1<'_> {
436 const FORMAT: u16 = 1;
437}
438
439impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
440 fn min_byte_range(&self) -> Range<usize> {
441 0..self.value_byte_range().end
442 }
443 fn min_table_bytes(&self) -> &'a [u8] {
444 let range = self.min_byte_range();
445 self.offset_data().as_bytes().get(range).unwrap_or_default()
446 }
447}
448
449impl ReadArgs for AxisValueFormat1<'_> {
450 type Args = ();
451}
452
453impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
454 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
455 #[allow(clippy::absurd_extreme_comparisons)]
456 if data.len() < Self::MIN_SIZE {
457 return Err(ReadError::OutOfBounds);
458 }
459 let Some(data) = TableDataRef::new(data.as_bytes()) else {
460 return Err(ReadError::OutOfBounds);
461 };
462 Ok(Self { data })
463 }
464}
465
466#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
468#[repr(C, packed)]
469#[doc(hidden)]
470pub struct AxisValueFormat1FixedHeader {
471 pub format: BigEndian<u16>,
472 pub axis_index: BigEndian<u16>,
473 pub flags: BigEndian<AxisValueTableFlags>,
474 pub value_name_id: BigEndian<NameId>,
475 pub value: BigEndian<Fixed>,
476}
477
478#[allow(clippy::absurd_extreme_comparisons)]
479const _: () =
480 assert!(std::mem::size_of::<AxisValueFormat1FixedHeader>() <= AxisValueFormat1::MIN_SIZE);
481
482#[derive(Clone)]
484pub struct AxisValueFormat1<'a> {
485 data: TableDataRef<'a, AxisValueFormat1FixedHeader>,
486}
487
488#[allow(clippy::needless_lifetimes)]
489impl<'a> AxisValueFormat1<'a> {
490 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
491 + u16::RAW_BYTE_LEN
492 + AxisValueTableFlags::RAW_BYTE_LEN
493 + NameId::RAW_BYTE_LEN
494 + Fixed::RAW_BYTE_LEN);
495 basic_table_impls!(impl_the_methods);
496
497 pub fn format(&self) -> u16 {
499 self.data.header().format.get()
500 }
501
502 pub fn axis_index(&self) -> u16 {
506 self.data.header().axis_index.get()
507 }
508
509 pub fn flags(&self) -> AxisValueTableFlags {
511 self.data.header().flags.get()
512 }
513
514 pub fn value_name_id(&self) -> NameId {
517 self.data.header().value_name_id.get()
518 }
519
520 pub fn value(&self) -> Fixed {
522 self.data.header().value.get()
523 }
524
525 pub fn format_byte_range(&self) -> Range<usize> {
526 let start = 0;
527 let end = start + u16::RAW_BYTE_LEN;
528 start..end
529 }
530
531 pub fn axis_index_byte_range(&self) -> Range<usize> {
532 let start = self.format_byte_range().end;
533 let end = start + u16::RAW_BYTE_LEN;
534 start..end
535 }
536
537 pub fn flags_byte_range(&self) -> Range<usize> {
538 let start = self.axis_index_byte_range().end;
539 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
540 start..end
541 }
542
543 pub fn value_name_id_byte_range(&self) -> Range<usize> {
544 let start = self.flags_byte_range().end;
545 let end = start + NameId::RAW_BYTE_LEN;
546 start..end
547 }
548
549 pub fn value_byte_range(&self) -> Range<usize> {
550 let start = self.value_name_id_byte_range().end;
551 let end = start + Fixed::RAW_BYTE_LEN;
552 start..end
553 }
554}
555
556const _: () = assert!(FontData::default_data_long_enough(
557 AxisValueFormat1::MIN_SIZE
558));
559
560impl Default for AxisValueFormat1<'_> {
561 fn default() -> Self {
562 Self {
563 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
564 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
565 }
566 }
567}
568
569impl Format<u16> for AxisValueFormat2<'_> {
570 const FORMAT: u16 = 2;
571}
572
573impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
574 fn min_byte_range(&self) -> Range<usize> {
575 0..self.range_max_value_byte_range().end
576 }
577 fn min_table_bytes(&self) -> &'a [u8] {
578 let range = self.min_byte_range();
579 self.offset_data().as_bytes().get(range).unwrap_or_default()
580 }
581}
582
583impl ReadArgs for AxisValueFormat2<'_> {
584 type Args = ();
585}
586
587impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
588 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
589 #[allow(clippy::absurd_extreme_comparisons)]
590 if data.len() < Self::MIN_SIZE {
591 return Err(ReadError::OutOfBounds);
592 }
593 let Some(data) = TableDataRef::new(data.as_bytes()) else {
594 return Err(ReadError::OutOfBounds);
595 };
596 Ok(Self { data })
597 }
598}
599
600#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
602#[repr(C, packed)]
603#[doc(hidden)]
604pub struct AxisValueFormat2FixedHeader {
605 pub format: BigEndian<u16>,
606 pub axis_index: BigEndian<u16>,
607 pub flags: BigEndian<AxisValueTableFlags>,
608 pub value_name_id: BigEndian<NameId>,
609 pub nominal_value: BigEndian<Fixed>,
610 pub range_min_value: BigEndian<Fixed>,
611 pub range_max_value: BigEndian<Fixed>,
612}
613
614#[allow(clippy::absurd_extreme_comparisons)]
615const _: () =
616 assert!(std::mem::size_of::<AxisValueFormat2FixedHeader>() <= AxisValueFormat2::MIN_SIZE);
617
618#[derive(Clone)]
620pub struct AxisValueFormat2<'a> {
621 data: TableDataRef<'a, AxisValueFormat2FixedHeader>,
622}
623
624#[allow(clippy::needless_lifetimes)]
625impl<'a> AxisValueFormat2<'a> {
626 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
627 + u16::RAW_BYTE_LEN
628 + AxisValueTableFlags::RAW_BYTE_LEN
629 + NameId::RAW_BYTE_LEN
630 + Fixed::RAW_BYTE_LEN
631 + Fixed::RAW_BYTE_LEN
632 + Fixed::RAW_BYTE_LEN);
633 basic_table_impls!(impl_the_methods);
634
635 pub fn format(&self) -> u16 {
637 self.data.header().format.get()
638 }
639
640 pub fn axis_index(&self) -> u16 {
644 self.data.header().axis_index.get()
645 }
646
647 pub fn flags(&self) -> AxisValueTableFlags {
649 self.data.header().flags.get()
650 }
651
652 pub fn value_name_id(&self) -> NameId {
655 self.data.header().value_name_id.get()
656 }
657
658 pub fn nominal_value(&self) -> Fixed {
660 self.data.header().nominal_value.get()
661 }
662
663 pub fn range_min_value(&self) -> Fixed {
666 self.data.header().range_min_value.get()
667 }
668
669 pub fn range_max_value(&self) -> Fixed {
672 self.data.header().range_max_value.get()
673 }
674
675 pub fn format_byte_range(&self) -> Range<usize> {
676 let start = 0;
677 let end = start + u16::RAW_BYTE_LEN;
678 start..end
679 }
680
681 pub fn axis_index_byte_range(&self) -> Range<usize> {
682 let start = self.format_byte_range().end;
683 let end = start + u16::RAW_BYTE_LEN;
684 start..end
685 }
686
687 pub fn flags_byte_range(&self) -> Range<usize> {
688 let start = self.axis_index_byte_range().end;
689 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
690 start..end
691 }
692
693 pub fn value_name_id_byte_range(&self) -> Range<usize> {
694 let start = self.flags_byte_range().end;
695 let end = start + NameId::RAW_BYTE_LEN;
696 start..end
697 }
698
699 pub fn nominal_value_byte_range(&self) -> Range<usize> {
700 let start = self.value_name_id_byte_range().end;
701 let end = start + Fixed::RAW_BYTE_LEN;
702 start..end
703 }
704
705 pub fn range_min_value_byte_range(&self) -> Range<usize> {
706 let start = self.nominal_value_byte_range().end;
707 let end = start + Fixed::RAW_BYTE_LEN;
708 start..end
709 }
710
711 pub fn range_max_value_byte_range(&self) -> Range<usize> {
712 let start = self.range_min_value_byte_range().end;
713 let end = start + Fixed::RAW_BYTE_LEN;
714 start..end
715 }
716}
717
718impl Format<u16> for AxisValueFormat3<'_> {
719 const FORMAT: u16 = 3;
720}
721
722impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
723 fn min_byte_range(&self) -> Range<usize> {
724 0..self.linked_value_byte_range().end
725 }
726 fn min_table_bytes(&self) -> &'a [u8] {
727 let range = self.min_byte_range();
728 self.offset_data().as_bytes().get(range).unwrap_or_default()
729 }
730}
731
732impl ReadArgs for AxisValueFormat3<'_> {
733 type Args = ();
734}
735
736impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
737 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
738 #[allow(clippy::absurd_extreme_comparisons)]
739 if data.len() < Self::MIN_SIZE {
740 return Err(ReadError::OutOfBounds);
741 }
742 let Some(data) = TableDataRef::new(data.as_bytes()) else {
743 return Err(ReadError::OutOfBounds);
744 };
745 Ok(Self { data })
746 }
747}
748
749#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
751#[repr(C, packed)]
752#[doc(hidden)]
753pub struct AxisValueFormat3FixedHeader {
754 pub format: BigEndian<u16>,
755 pub axis_index: BigEndian<u16>,
756 pub flags: BigEndian<AxisValueTableFlags>,
757 pub value_name_id: BigEndian<NameId>,
758 pub value: BigEndian<Fixed>,
759 pub linked_value: BigEndian<Fixed>,
760}
761
762#[allow(clippy::absurd_extreme_comparisons)]
763const _: () =
764 assert!(std::mem::size_of::<AxisValueFormat3FixedHeader>() <= AxisValueFormat3::MIN_SIZE);
765
766#[derive(Clone)]
768pub struct AxisValueFormat3<'a> {
769 data: TableDataRef<'a, AxisValueFormat3FixedHeader>,
770}
771
772#[allow(clippy::needless_lifetimes)]
773impl<'a> AxisValueFormat3<'a> {
774 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
775 + u16::RAW_BYTE_LEN
776 + AxisValueTableFlags::RAW_BYTE_LEN
777 + NameId::RAW_BYTE_LEN
778 + Fixed::RAW_BYTE_LEN
779 + Fixed::RAW_BYTE_LEN);
780 basic_table_impls!(impl_the_methods);
781
782 pub fn format(&self) -> u16 {
784 self.data.header().format.get()
785 }
786
787 pub fn axis_index(&self) -> u16 {
791 self.data.header().axis_index.get()
792 }
793
794 pub fn flags(&self) -> AxisValueTableFlags {
796 self.data.header().flags.get()
797 }
798
799 pub fn value_name_id(&self) -> NameId {
802 self.data.header().value_name_id.get()
803 }
804
805 pub fn value(&self) -> Fixed {
807 self.data.header().value.get()
808 }
809
810 pub fn linked_value(&self) -> Fixed {
812 self.data.header().linked_value.get()
813 }
814
815 pub fn format_byte_range(&self) -> Range<usize> {
816 let start = 0;
817 let end = start + u16::RAW_BYTE_LEN;
818 start..end
819 }
820
821 pub fn axis_index_byte_range(&self) -> Range<usize> {
822 let start = self.format_byte_range().end;
823 let end = start + u16::RAW_BYTE_LEN;
824 start..end
825 }
826
827 pub fn flags_byte_range(&self) -> Range<usize> {
828 let start = self.axis_index_byte_range().end;
829 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
830 start..end
831 }
832
833 pub fn value_name_id_byte_range(&self) -> Range<usize> {
834 let start = self.flags_byte_range().end;
835 let end = start + NameId::RAW_BYTE_LEN;
836 start..end
837 }
838
839 pub fn value_byte_range(&self) -> Range<usize> {
840 let start = self.value_name_id_byte_range().end;
841 let end = start + Fixed::RAW_BYTE_LEN;
842 start..end
843 }
844
845 pub fn linked_value_byte_range(&self) -> Range<usize> {
846 let start = self.value_byte_range().end;
847 let end = start + Fixed::RAW_BYTE_LEN;
848 start..end
849 }
850}
851
852impl Format<u16> for AxisValueFormat4<'_> {
853 const FORMAT: u16 = 4;
854}
855
856impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
857 fn min_byte_range(&self) -> Range<usize> {
858 0..self.axis_values_byte_range().end
859 }
860 fn min_table_bytes(&self) -> &'a [u8] {
861 let range = self.min_byte_range();
862 self.offset_data().as_bytes().get(range).unwrap_or_default()
863 }
864}
865
866impl ReadArgs for AxisValueFormat4<'_> {
867 type Args = ();
868}
869
870impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
871 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
872 #[allow(clippy::absurd_extreme_comparisons)]
873 if data.len() < Self::MIN_SIZE {
874 return Err(ReadError::OutOfBounds);
875 }
876 let Some(data) = TableDataRef::new(data.as_bytes()) else {
877 return Err(ReadError::OutOfBounds);
878 };
879 Ok(Self { data })
880 }
881}
882
883#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
885#[repr(C, packed)]
886#[doc(hidden)]
887pub struct AxisValueFormat4FixedHeader {
888 pub format: BigEndian<u16>,
889 pub axis_count: BigEndian<u16>,
890 pub flags: BigEndian<AxisValueTableFlags>,
891 pub value_name_id: BigEndian<NameId>,
892}
893
894#[allow(clippy::absurd_extreme_comparisons)]
895const _: () =
896 assert!(std::mem::size_of::<AxisValueFormat4FixedHeader>() <= AxisValueFormat4::MIN_SIZE);
897
898#[derive(Clone)]
900pub struct AxisValueFormat4<'a> {
901 data: TableDataRef<'a, AxisValueFormat4FixedHeader>,
902}
903
904#[allow(clippy::needless_lifetimes)]
905impl<'a> AxisValueFormat4<'a> {
906 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
907 + u16::RAW_BYTE_LEN
908 + AxisValueTableFlags::RAW_BYTE_LEN
909 + NameId::RAW_BYTE_LEN);
910 basic_table_impls!(impl_the_methods);
911
912 pub fn format(&self) -> u16 {
914 self.data.header().format.get()
915 }
916
917 pub fn axis_count(&self) -> u16 {
920 self.data.header().axis_count.get()
921 }
922
923 pub fn flags(&self) -> AxisValueTableFlags {
925 self.data.header().flags.get()
926 }
927
928 pub fn value_name_id(&self) -> NameId {
931 self.data.header().value_name_id.get()
932 }
933
934 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
937 let range = self.axis_values_byte_range();
938 self.offset_data()
939 .read_array(range)
940 .ok()
941 .unwrap_or_default()
942 }
943
944 pub fn format_byte_range(&self) -> Range<usize> {
945 let start = 0;
946 let end = start + u16::RAW_BYTE_LEN;
947 start..end
948 }
949
950 pub fn axis_count_byte_range(&self) -> Range<usize> {
951 let start = self.format_byte_range().end;
952 let end = start + u16::RAW_BYTE_LEN;
953 start..end
954 }
955
956 pub fn flags_byte_range(&self) -> Range<usize> {
957 let start = self.axis_count_byte_range().end;
958 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
959 start..end
960 }
961
962 pub fn value_name_id_byte_range(&self) -> Range<usize> {
963 let start = self.flags_byte_range().end;
964 let end = start + NameId::RAW_BYTE_LEN;
965 start..end
966 }
967
968 pub fn axis_values_byte_range(&self) -> Range<usize> {
969 let axis_count = self.axis_count();
970 let start = self.value_name_id_byte_range().end;
971 let end = start
972 + (transforms::to_usize(axis_count)).saturating_mul(AxisValueRecord::RAW_BYTE_LEN);
973 start..end
974 }
975}
976
977#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
979#[repr(C)]
980#[repr(packed)]
981pub struct AxisValueRecord {
982 pub axis_index: BigEndian<u16>,
985 pub value: BigEndian<Fixed>,
987}
988
989impl AxisValueRecord {
990 pub fn axis_index(&self) -> u16 {
993 self.axis_index.get()
994 }
995
996 pub fn value(&self) -> Fixed {
998 self.value.get()
999 }
1000}
1001
1002impl FixedSize for AxisValueRecord {
1003 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1004}
1005
1006#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1008#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1009#[repr(transparent)]
1010pub struct AxisValueTableFlags {
1011 bits: u16,
1012}
1013
1014impl AxisValueTableFlags {
1015 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1022
1023 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1027}
1028
1029impl AxisValueTableFlags {
1030 #[inline]
1032 pub const fn empty() -> Self {
1033 Self { bits: 0 }
1034 }
1035
1036 #[inline]
1038 pub const fn all() -> Self {
1039 Self {
1040 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1041 }
1042 }
1043
1044 #[inline]
1046 pub const fn bits(&self) -> u16 {
1047 self.bits
1048 }
1049
1050 #[inline]
1053 pub const fn from_bits(bits: u16) -> Option<Self> {
1054 if (bits & !Self::all().bits()) == 0 {
1055 Some(Self { bits })
1056 } else {
1057 None
1058 }
1059 }
1060
1061 #[inline]
1064 pub const fn from_bits_truncate(bits: u16) -> Self {
1065 Self {
1066 bits: bits & Self::all().bits,
1067 }
1068 }
1069
1070 #[inline]
1072 pub const fn is_empty(&self) -> bool {
1073 self.bits() == Self::empty().bits()
1074 }
1075
1076 #[inline]
1078 pub const fn intersects(&self, other: Self) -> bool {
1079 !(Self {
1080 bits: self.bits & other.bits,
1081 })
1082 .is_empty()
1083 }
1084
1085 #[inline]
1087 pub const fn contains(&self, other: Self) -> bool {
1088 (self.bits & other.bits) == other.bits
1089 }
1090
1091 #[inline]
1093 pub fn insert(&mut self, other: Self) {
1094 self.bits |= other.bits;
1095 }
1096
1097 #[inline]
1099 pub fn remove(&mut self, other: Self) {
1100 self.bits &= !other.bits;
1101 }
1102
1103 #[inline]
1105 pub fn toggle(&mut self, other: Self) {
1106 self.bits ^= other.bits;
1107 }
1108
1109 #[inline]
1120 #[must_use]
1121 pub const fn intersection(self, other: Self) -> Self {
1122 Self {
1123 bits: self.bits & other.bits,
1124 }
1125 }
1126
1127 #[inline]
1138 #[must_use]
1139 pub const fn union(self, other: Self) -> Self {
1140 Self {
1141 bits: self.bits | other.bits,
1142 }
1143 }
1144
1145 #[inline]
1158 #[must_use]
1159 pub const fn difference(self, other: Self) -> Self {
1160 Self {
1161 bits: self.bits & !other.bits,
1162 }
1163 }
1164}
1165
1166impl std::ops::BitOr for AxisValueTableFlags {
1167 type Output = Self;
1168
1169 #[inline]
1171 fn bitor(self, other: AxisValueTableFlags) -> Self {
1172 Self {
1173 bits: self.bits | other.bits,
1174 }
1175 }
1176}
1177
1178impl std::ops::BitOrAssign for AxisValueTableFlags {
1179 #[inline]
1181 fn bitor_assign(&mut self, other: Self) {
1182 self.bits |= other.bits;
1183 }
1184}
1185
1186impl std::ops::BitXor for AxisValueTableFlags {
1187 type Output = Self;
1188
1189 #[inline]
1191 fn bitxor(self, other: Self) -> Self {
1192 Self {
1193 bits: self.bits ^ other.bits,
1194 }
1195 }
1196}
1197
1198impl std::ops::BitXorAssign for AxisValueTableFlags {
1199 #[inline]
1201 fn bitxor_assign(&mut self, other: Self) {
1202 self.bits ^= other.bits;
1203 }
1204}
1205
1206impl std::ops::BitAnd for AxisValueTableFlags {
1207 type Output = Self;
1208
1209 #[inline]
1211 fn bitand(self, other: Self) -> Self {
1212 Self {
1213 bits: self.bits & other.bits,
1214 }
1215 }
1216}
1217
1218impl std::ops::BitAndAssign for AxisValueTableFlags {
1219 #[inline]
1221 fn bitand_assign(&mut self, other: Self) {
1222 self.bits &= other.bits;
1223 }
1224}
1225
1226impl std::ops::Sub for AxisValueTableFlags {
1227 type Output = Self;
1228
1229 #[inline]
1231 fn sub(self, other: Self) -> Self {
1232 Self {
1233 bits: self.bits & !other.bits,
1234 }
1235 }
1236}
1237
1238impl std::ops::SubAssign for AxisValueTableFlags {
1239 #[inline]
1241 fn sub_assign(&mut self, other: Self) {
1242 self.bits &= !other.bits;
1243 }
1244}
1245
1246impl std::ops::Not for AxisValueTableFlags {
1247 type Output = Self;
1248
1249 #[inline]
1251 fn not(self) -> Self {
1252 Self { bits: !self.bits } & Self::all()
1253 }
1254}
1255
1256impl std::fmt::Debug for AxisValueTableFlags {
1257 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1258 let members: &[(&str, Self)] = &[
1259 (
1260 "OLDER_SIBLING_FONT_ATTRIBUTE",
1261 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1262 ),
1263 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1264 ];
1265 let mut first = true;
1266 for (name, value) in members {
1267 if self.contains(*value) {
1268 if !first {
1269 f.write_str(" | ")?;
1270 }
1271 first = false;
1272 f.write_str(name)?;
1273 }
1274 }
1275 if first {
1276 f.write_str("(empty)")?;
1277 }
1278 Ok(())
1279 }
1280}
1281
1282impl std::fmt::Binary for AxisValueTableFlags {
1283 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1284 std::fmt::Binary::fmt(&self.bits, f)
1285 }
1286}
1287
1288impl std::fmt::Octal for AxisValueTableFlags {
1289 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1290 std::fmt::Octal::fmt(&self.bits, f)
1291 }
1292}
1293
1294impl std::fmt::LowerHex for AxisValueTableFlags {
1295 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1296 std::fmt::LowerHex::fmt(&self.bits, f)
1297 }
1298}
1299
1300impl std::fmt::UpperHex for AxisValueTableFlags {
1301 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1302 std::fmt::UpperHex::fmt(&self.bits, f)
1303 }
1304}
1305
1306impl font_types::Scalar for AxisValueTableFlags {
1307 type Raw = <u16 as font_types::Scalar>::Raw;
1308 fn to_raw(self) -> Self::Raw {
1309 self.bits().to_raw()
1310 }
1311 fn from_raw(raw: Self::Raw) -> Self {
1312 let t = <u16>::from_raw(raw);
1313 Self::from_bits_truncate(t)
1314 }
1315}