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 #[inline]
405 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
406 let format: u16 = data.read_at(0usize)?;
407 match format {
408 AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
409 AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
410 AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
411 AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
412 other => Err(ReadError::InvalidFormat(other.into())),
413 }
414 }
415}
416
417impl<'a> MinByteRange<'a> for AxisValue<'a> {
418 fn min_byte_range(&self) -> Range<usize> {
419 match self {
420 Self::Format1(item) => item.min_byte_range(),
421 Self::Format2(item) => item.min_byte_range(),
422 Self::Format3(item) => item.min_byte_range(),
423 Self::Format4(item) => item.min_byte_range(),
424 }
425 }
426 fn min_table_bytes(&self) -> &'a [u8] {
427 match self {
428 Self::Format1(item) => item.min_table_bytes(),
429 Self::Format2(item) => item.min_table_bytes(),
430 Self::Format3(item) => item.min_table_bytes(),
431 Self::Format4(item) => item.min_table_bytes(),
432 }
433 }
434}
435
436impl Format<u16> for AxisValueFormat1<'_> {
437 const FORMAT: u16 = 1;
438}
439
440impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
441 fn min_byte_range(&self) -> Range<usize> {
442 0..self.value_byte_range().end
443 }
444 fn min_table_bytes(&self) -> &'a [u8] {
445 let range = self.min_byte_range();
446 self.offset_data().as_bytes().get(range).unwrap_or_default()
447 }
448}
449
450impl ReadArgs for AxisValueFormat1<'_> {
451 type Args = ();
452}
453
454impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
455 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
456 #[allow(clippy::absurd_extreme_comparisons)]
457 if data.len() < Self::MIN_SIZE {
458 return Err(ReadError::OutOfBounds);
459 }
460 let Some(data) = TableDataRef::new(data.as_bytes()) else {
461 return Err(ReadError::OutOfBounds);
462 };
463 Ok(Self { data })
464 }
465}
466
467#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
469#[repr(C, packed)]
470#[doc(hidden)]
471pub struct AxisValueFormat1FixedHeader {
472 pub format: BigEndian<u16>,
473 pub axis_index: BigEndian<u16>,
474 pub flags: BigEndian<AxisValueTableFlags>,
475 pub value_name_id: BigEndian<NameId>,
476 pub value: BigEndian<Fixed>,
477}
478
479#[allow(clippy::absurd_extreme_comparisons)]
480const _: () =
481 assert!(std::mem::size_of::<AxisValueFormat1FixedHeader>() <= AxisValueFormat1::MIN_SIZE);
482
483#[derive(Clone)]
485pub struct AxisValueFormat1<'a> {
486 data: TableDataRef<'a, AxisValueFormat1FixedHeader>,
487}
488
489#[allow(clippy::needless_lifetimes)]
490impl<'a> AxisValueFormat1<'a> {
491 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
492 + u16::RAW_BYTE_LEN
493 + AxisValueTableFlags::RAW_BYTE_LEN
494 + NameId::RAW_BYTE_LEN
495 + Fixed::RAW_BYTE_LEN);
496 basic_table_impls!(impl_the_methods);
497
498 pub fn format(&self) -> u16 {
500 self.data.header().format.get()
501 }
502
503 pub fn axis_index(&self) -> u16 {
507 self.data.header().axis_index.get()
508 }
509
510 pub fn flags(&self) -> AxisValueTableFlags {
512 self.data.header().flags.get()
513 }
514
515 pub fn value_name_id(&self) -> NameId {
518 self.data.header().value_name_id.get()
519 }
520
521 pub fn value(&self) -> Fixed {
523 self.data.header().value.get()
524 }
525
526 pub fn format_byte_range(&self) -> Range<usize> {
527 let start = 0;
528 let end = start + u16::RAW_BYTE_LEN;
529 start..end
530 }
531
532 pub fn axis_index_byte_range(&self) -> Range<usize> {
533 let start = self.format_byte_range().end;
534 let end = start + u16::RAW_BYTE_LEN;
535 start..end
536 }
537
538 pub fn flags_byte_range(&self) -> Range<usize> {
539 let start = self.axis_index_byte_range().end;
540 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
541 start..end
542 }
543
544 pub fn value_name_id_byte_range(&self) -> Range<usize> {
545 let start = self.flags_byte_range().end;
546 let end = start + NameId::RAW_BYTE_LEN;
547 start..end
548 }
549
550 pub fn value_byte_range(&self) -> Range<usize> {
551 let start = self.value_name_id_byte_range().end;
552 let end = start + Fixed::RAW_BYTE_LEN;
553 start..end
554 }
555}
556
557const _: () = assert!(FontData::default_data_long_enough(
558 AxisValueFormat1::MIN_SIZE
559));
560
561impl Default for AxisValueFormat1<'_> {
562 fn default() -> Self {
563 Self {
564 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
565 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
566 }
567 }
568}
569
570impl Format<u16> for AxisValueFormat2<'_> {
571 const FORMAT: u16 = 2;
572}
573
574impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
575 fn min_byte_range(&self) -> Range<usize> {
576 0..self.range_max_value_byte_range().end
577 }
578 fn min_table_bytes(&self) -> &'a [u8] {
579 let range = self.min_byte_range();
580 self.offset_data().as_bytes().get(range).unwrap_or_default()
581 }
582}
583
584impl ReadArgs for AxisValueFormat2<'_> {
585 type Args = ();
586}
587
588impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
589 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
590 #[allow(clippy::absurd_extreme_comparisons)]
591 if data.len() < Self::MIN_SIZE {
592 return Err(ReadError::OutOfBounds);
593 }
594 let Some(data) = TableDataRef::new(data.as_bytes()) else {
595 return Err(ReadError::OutOfBounds);
596 };
597 Ok(Self { data })
598 }
599}
600
601#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
603#[repr(C, packed)]
604#[doc(hidden)]
605pub struct AxisValueFormat2FixedHeader {
606 pub format: BigEndian<u16>,
607 pub axis_index: BigEndian<u16>,
608 pub flags: BigEndian<AxisValueTableFlags>,
609 pub value_name_id: BigEndian<NameId>,
610 pub nominal_value: BigEndian<Fixed>,
611 pub range_min_value: BigEndian<Fixed>,
612 pub range_max_value: BigEndian<Fixed>,
613}
614
615#[allow(clippy::absurd_extreme_comparisons)]
616const _: () =
617 assert!(std::mem::size_of::<AxisValueFormat2FixedHeader>() <= AxisValueFormat2::MIN_SIZE);
618
619#[derive(Clone)]
621pub struct AxisValueFormat2<'a> {
622 data: TableDataRef<'a, AxisValueFormat2FixedHeader>,
623}
624
625#[allow(clippy::needless_lifetimes)]
626impl<'a> AxisValueFormat2<'a> {
627 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
628 + u16::RAW_BYTE_LEN
629 + AxisValueTableFlags::RAW_BYTE_LEN
630 + NameId::RAW_BYTE_LEN
631 + Fixed::RAW_BYTE_LEN
632 + Fixed::RAW_BYTE_LEN
633 + Fixed::RAW_BYTE_LEN);
634 basic_table_impls!(impl_the_methods);
635
636 pub fn format(&self) -> u16 {
638 self.data.header().format.get()
639 }
640
641 pub fn axis_index(&self) -> u16 {
645 self.data.header().axis_index.get()
646 }
647
648 pub fn flags(&self) -> AxisValueTableFlags {
650 self.data.header().flags.get()
651 }
652
653 pub fn value_name_id(&self) -> NameId {
656 self.data.header().value_name_id.get()
657 }
658
659 pub fn nominal_value(&self) -> Fixed {
661 self.data.header().nominal_value.get()
662 }
663
664 pub fn range_min_value(&self) -> Fixed {
667 self.data.header().range_min_value.get()
668 }
669
670 pub fn range_max_value(&self) -> Fixed {
673 self.data.header().range_max_value.get()
674 }
675
676 pub fn format_byte_range(&self) -> Range<usize> {
677 let start = 0;
678 let end = start + u16::RAW_BYTE_LEN;
679 start..end
680 }
681
682 pub fn axis_index_byte_range(&self) -> Range<usize> {
683 let start = self.format_byte_range().end;
684 let end = start + u16::RAW_BYTE_LEN;
685 start..end
686 }
687
688 pub fn flags_byte_range(&self) -> Range<usize> {
689 let start = self.axis_index_byte_range().end;
690 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
691 start..end
692 }
693
694 pub fn value_name_id_byte_range(&self) -> Range<usize> {
695 let start = self.flags_byte_range().end;
696 let end = start + NameId::RAW_BYTE_LEN;
697 start..end
698 }
699
700 pub fn nominal_value_byte_range(&self) -> Range<usize> {
701 let start = self.value_name_id_byte_range().end;
702 let end = start + Fixed::RAW_BYTE_LEN;
703 start..end
704 }
705
706 pub fn range_min_value_byte_range(&self) -> Range<usize> {
707 let start = self.nominal_value_byte_range().end;
708 let end = start + Fixed::RAW_BYTE_LEN;
709 start..end
710 }
711
712 pub fn range_max_value_byte_range(&self) -> Range<usize> {
713 let start = self.range_min_value_byte_range().end;
714 let end = start + Fixed::RAW_BYTE_LEN;
715 start..end
716 }
717}
718
719impl Format<u16> for AxisValueFormat3<'_> {
720 const FORMAT: u16 = 3;
721}
722
723impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
724 fn min_byte_range(&self) -> Range<usize> {
725 0..self.linked_value_byte_range().end
726 }
727 fn min_table_bytes(&self) -> &'a [u8] {
728 let range = self.min_byte_range();
729 self.offset_data().as_bytes().get(range).unwrap_or_default()
730 }
731}
732
733impl ReadArgs for AxisValueFormat3<'_> {
734 type Args = ();
735}
736
737impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
738 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
739 #[allow(clippy::absurd_extreme_comparisons)]
740 if data.len() < Self::MIN_SIZE {
741 return Err(ReadError::OutOfBounds);
742 }
743 let Some(data) = TableDataRef::new(data.as_bytes()) else {
744 return Err(ReadError::OutOfBounds);
745 };
746 Ok(Self { data })
747 }
748}
749
750#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
752#[repr(C, packed)]
753#[doc(hidden)]
754pub struct AxisValueFormat3FixedHeader {
755 pub format: BigEndian<u16>,
756 pub axis_index: BigEndian<u16>,
757 pub flags: BigEndian<AxisValueTableFlags>,
758 pub value_name_id: BigEndian<NameId>,
759 pub value: BigEndian<Fixed>,
760 pub linked_value: BigEndian<Fixed>,
761}
762
763#[allow(clippy::absurd_extreme_comparisons)]
764const _: () =
765 assert!(std::mem::size_of::<AxisValueFormat3FixedHeader>() <= AxisValueFormat3::MIN_SIZE);
766
767#[derive(Clone)]
769pub struct AxisValueFormat3<'a> {
770 data: TableDataRef<'a, AxisValueFormat3FixedHeader>,
771}
772
773#[allow(clippy::needless_lifetimes)]
774impl<'a> AxisValueFormat3<'a> {
775 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
776 + u16::RAW_BYTE_LEN
777 + AxisValueTableFlags::RAW_BYTE_LEN
778 + NameId::RAW_BYTE_LEN
779 + Fixed::RAW_BYTE_LEN
780 + Fixed::RAW_BYTE_LEN);
781 basic_table_impls!(impl_the_methods);
782
783 pub fn format(&self) -> u16 {
785 self.data.header().format.get()
786 }
787
788 pub fn axis_index(&self) -> u16 {
792 self.data.header().axis_index.get()
793 }
794
795 pub fn flags(&self) -> AxisValueTableFlags {
797 self.data.header().flags.get()
798 }
799
800 pub fn value_name_id(&self) -> NameId {
803 self.data.header().value_name_id.get()
804 }
805
806 pub fn value(&self) -> Fixed {
808 self.data.header().value.get()
809 }
810
811 pub fn linked_value(&self) -> Fixed {
813 self.data.header().linked_value.get()
814 }
815
816 pub fn format_byte_range(&self) -> Range<usize> {
817 let start = 0;
818 let end = start + u16::RAW_BYTE_LEN;
819 start..end
820 }
821
822 pub fn axis_index_byte_range(&self) -> Range<usize> {
823 let start = self.format_byte_range().end;
824 let end = start + u16::RAW_BYTE_LEN;
825 start..end
826 }
827
828 pub fn flags_byte_range(&self) -> Range<usize> {
829 let start = self.axis_index_byte_range().end;
830 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
831 start..end
832 }
833
834 pub fn value_name_id_byte_range(&self) -> Range<usize> {
835 let start = self.flags_byte_range().end;
836 let end = start + NameId::RAW_BYTE_LEN;
837 start..end
838 }
839
840 pub fn value_byte_range(&self) -> Range<usize> {
841 let start = self.value_name_id_byte_range().end;
842 let end = start + Fixed::RAW_BYTE_LEN;
843 start..end
844 }
845
846 pub fn linked_value_byte_range(&self) -> Range<usize> {
847 let start = self.value_byte_range().end;
848 let end = start + Fixed::RAW_BYTE_LEN;
849 start..end
850 }
851}
852
853impl Format<u16> for AxisValueFormat4<'_> {
854 const FORMAT: u16 = 4;
855}
856
857impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
858 fn min_byte_range(&self) -> Range<usize> {
859 0..self.axis_values_byte_range().end
860 }
861 fn min_table_bytes(&self) -> &'a [u8] {
862 let range = self.min_byte_range();
863 self.offset_data().as_bytes().get(range).unwrap_or_default()
864 }
865}
866
867impl ReadArgs for AxisValueFormat4<'_> {
868 type Args = ();
869}
870
871impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
872 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
873 #[allow(clippy::absurd_extreme_comparisons)]
874 if data.len() < Self::MIN_SIZE {
875 return Err(ReadError::OutOfBounds);
876 }
877 let Some(data) = TableDataRef::new(data.as_bytes()) else {
878 return Err(ReadError::OutOfBounds);
879 };
880 Ok(Self { data })
881 }
882}
883
884#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
886#[repr(C, packed)]
887#[doc(hidden)]
888pub struct AxisValueFormat4FixedHeader {
889 pub format: BigEndian<u16>,
890 pub axis_count: BigEndian<u16>,
891 pub flags: BigEndian<AxisValueTableFlags>,
892 pub value_name_id: BigEndian<NameId>,
893}
894
895#[allow(clippy::absurd_extreme_comparisons)]
896const _: () =
897 assert!(std::mem::size_of::<AxisValueFormat4FixedHeader>() <= AxisValueFormat4::MIN_SIZE);
898
899#[derive(Clone)]
901pub struct AxisValueFormat4<'a> {
902 data: TableDataRef<'a, AxisValueFormat4FixedHeader>,
903}
904
905#[allow(clippy::needless_lifetimes)]
906impl<'a> AxisValueFormat4<'a> {
907 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
908 + u16::RAW_BYTE_LEN
909 + AxisValueTableFlags::RAW_BYTE_LEN
910 + NameId::RAW_BYTE_LEN);
911 basic_table_impls!(impl_the_methods);
912
913 pub fn format(&self) -> u16 {
915 self.data.header().format.get()
916 }
917
918 pub fn axis_count(&self) -> u16 {
921 self.data.header().axis_count.get()
922 }
923
924 pub fn flags(&self) -> AxisValueTableFlags {
926 self.data.header().flags.get()
927 }
928
929 pub fn value_name_id(&self) -> NameId {
932 self.data.header().value_name_id.get()
933 }
934
935 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
938 let range = self.axis_values_byte_range();
939 self.offset_data()
940 .read_array(range)
941 .ok()
942 .unwrap_or_default()
943 }
944
945 pub fn format_byte_range(&self) -> Range<usize> {
946 let start = 0;
947 let end = start + u16::RAW_BYTE_LEN;
948 start..end
949 }
950
951 pub fn axis_count_byte_range(&self) -> Range<usize> {
952 let start = self.format_byte_range().end;
953 let end = start + u16::RAW_BYTE_LEN;
954 start..end
955 }
956
957 pub fn flags_byte_range(&self) -> Range<usize> {
958 let start = self.axis_count_byte_range().end;
959 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
960 start..end
961 }
962
963 pub fn value_name_id_byte_range(&self) -> Range<usize> {
964 let start = self.flags_byte_range().end;
965 let end = start + NameId::RAW_BYTE_LEN;
966 start..end
967 }
968
969 pub fn axis_values_byte_range(&self) -> Range<usize> {
970 let axis_count = self.axis_count();
971 let start = self.value_name_id_byte_range().end;
972 let end = start
973 + (transforms::to_usize(axis_count)).saturating_mul(AxisValueRecord::RAW_BYTE_LEN);
974 start..end
975 }
976}
977
978#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
980#[repr(C)]
981#[repr(packed)]
982pub struct AxisValueRecord {
983 pub axis_index: BigEndian<u16>,
986 pub value: BigEndian<Fixed>,
988}
989
990impl AxisValueRecord {
991 pub fn axis_index(&self) -> u16 {
994 self.axis_index.get()
995 }
996
997 pub fn value(&self) -> Fixed {
999 self.value.get()
1000 }
1001}
1002
1003impl FixedSize for AxisValueRecord {
1004 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1005}
1006
1007#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1009#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1010#[repr(transparent)]
1011pub struct AxisValueTableFlags {
1012 bits: u16,
1013}
1014
1015impl AxisValueTableFlags {
1016 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1023
1024 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1028}
1029
1030impl AxisValueTableFlags {
1031 #[inline]
1033 pub const fn empty() -> Self {
1034 Self { bits: 0 }
1035 }
1036
1037 #[inline]
1039 pub const fn all() -> Self {
1040 Self {
1041 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1042 }
1043 }
1044
1045 #[inline]
1047 pub const fn bits(&self) -> u16 {
1048 self.bits
1049 }
1050
1051 #[inline]
1054 pub const fn from_bits(bits: u16) -> Option<Self> {
1055 if (bits & !Self::all().bits()) == 0 {
1056 Some(Self { bits })
1057 } else {
1058 None
1059 }
1060 }
1061
1062 #[inline]
1065 pub const fn from_bits_truncate(bits: u16) -> Self {
1066 Self {
1067 bits: bits & Self::all().bits,
1068 }
1069 }
1070
1071 #[inline]
1073 pub const fn is_empty(&self) -> bool {
1074 self.bits() == Self::empty().bits()
1075 }
1076
1077 #[inline]
1079 pub const fn intersects(&self, other: Self) -> bool {
1080 !(Self {
1081 bits: self.bits & other.bits,
1082 })
1083 .is_empty()
1084 }
1085
1086 #[inline]
1088 pub const fn contains(&self, other: Self) -> bool {
1089 (self.bits & other.bits) == other.bits
1090 }
1091
1092 #[inline]
1094 pub fn insert(&mut self, other: Self) {
1095 self.bits |= other.bits;
1096 }
1097
1098 #[inline]
1100 pub fn remove(&mut self, other: Self) {
1101 self.bits &= !other.bits;
1102 }
1103
1104 #[inline]
1106 pub fn toggle(&mut self, other: Self) {
1107 self.bits ^= other.bits;
1108 }
1109
1110 #[inline]
1121 #[must_use]
1122 pub const fn intersection(self, other: Self) -> Self {
1123 Self {
1124 bits: self.bits & other.bits,
1125 }
1126 }
1127
1128 #[inline]
1139 #[must_use]
1140 pub const fn union(self, other: Self) -> Self {
1141 Self {
1142 bits: self.bits | other.bits,
1143 }
1144 }
1145
1146 #[inline]
1159 #[must_use]
1160 pub const fn difference(self, other: Self) -> Self {
1161 Self {
1162 bits: self.bits & !other.bits,
1163 }
1164 }
1165}
1166
1167impl std::ops::BitOr for AxisValueTableFlags {
1168 type Output = Self;
1169
1170 #[inline]
1172 fn bitor(self, other: AxisValueTableFlags) -> Self {
1173 Self {
1174 bits: self.bits | other.bits,
1175 }
1176 }
1177}
1178
1179impl std::ops::BitOrAssign for AxisValueTableFlags {
1180 #[inline]
1182 fn bitor_assign(&mut self, other: Self) {
1183 self.bits |= other.bits;
1184 }
1185}
1186
1187impl std::ops::BitXor for AxisValueTableFlags {
1188 type Output = Self;
1189
1190 #[inline]
1192 fn bitxor(self, other: Self) -> Self {
1193 Self {
1194 bits: self.bits ^ other.bits,
1195 }
1196 }
1197}
1198
1199impl std::ops::BitXorAssign for AxisValueTableFlags {
1200 #[inline]
1202 fn bitxor_assign(&mut self, other: Self) {
1203 self.bits ^= other.bits;
1204 }
1205}
1206
1207impl std::ops::BitAnd for AxisValueTableFlags {
1208 type Output = Self;
1209
1210 #[inline]
1212 fn bitand(self, other: Self) -> Self {
1213 Self {
1214 bits: self.bits & other.bits,
1215 }
1216 }
1217}
1218
1219impl std::ops::BitAndAssign for AxisValueTableFlags {
1220 #[inline]
1222 fn bitand_assign(&mut self, other: Self) {
1223 self.bits &= other.bits;
1224 }
1225}
1226
1227impl std::ops::Sub for AxisValueTableFlags {
1228 type Output = Self;
1229
1230 #[inline]
1232 fn sub(self, other: Self) -> Self {
1233 Self {
1234 bits: self.bits & !other.bits,
1235 }
1236 }
1237}
1238
1239impl std::ops::SubAssign for AxisValueTableFlags {
1240 #[inline]
1242 fn sub_assign(&mut self, other: Self) {
1243 self.bits &= !other.bits;
1244 }
1245}
1246
1247impl std::ops::Not for AxisValueTableFlags {
1248 type Output = Self;
1249
1250 #[inline]
1252 fn not(self) -> Self {
1253 Self { bits: !self.bits } & Self::all()
1254 }
1255}
1256
1257impl std::fmt::Debug for AxisValueTableFlags {
1258 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1259 let members: &[(&str, Self)] = &[
1260 (
1261 "OLDER_SIBLING_FONT_ATTRIBUTE",
1262 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1263 ),
1264 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1265 ];
1266 let mut first = true;
1267 for (name, value) in members {
1268 if self.contains(*value) {
1269 if !first {
1270 f.write_str(" | ")?;
1271 }
1272 first = false;
1273 f.write_str(name)?;
1274 }
1275 }
1276 if first {
1277 f.write_str("(empty)")?;
1278 }
1279 Ok(())
1280 }
1281}
1282
1283impl std::fmt::Binary for AxisValueTableFlags {
1284 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1285 std::fmt::Binary::fmt(&self.bits, f)
1286 }
1287}
1288
1289impl std::fmt::Octal for AxisValueTableFlags {
1290 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1291 std::fmt::Octal::fmt(&self.bits, f)
1292 }
1293}
1294
1295impl std::fmt::LowerHex for AxisValueTableFlags {
1296 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1297 std::fmt::LowerHex::fmt(&self.bits, f)
1298 }
1299}
1300
1301impl std::fmt::UpperHex for AxisValueTableFlags {
1302 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1303 std::fmt::UpperHex::fmt(&self.bits, f)
1304 }
1305}
1306
1307impl font_types::Scalar for AxisValueTableFlags {
1308 type Raw = <u16 as font_types::Scalar>::Raw;
1309 fn to_raw(self) -> Self::Raw {
1310 self.bits().to_raw()
1311 }
1312 fn from_raw(raw: Self::Raw) -> Self {
1313 let t = <u16>::from_raw(raw);
1314 Self::from_bits_truncate(t)
1315 }
1316}