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.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 Ok(Self { data })
34 }
35}
36
37#[derive(Clone)]
39pub struct Stat<'a> {
40 data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Stat<'a> {
45 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
46 + u16::RAW_BYTE_LEN
47 + u16::RAW_BYTE_LEN
48 + Offset32::RAW_BYTE_LEN
49 + u16::RAW_BYTE_LEN
50 + Offset32::RAW_BYTE_LEN);
51 basic_table_impls!(impl_the_methods);
52
53 pub fn version(&self) -> MajorMinor {
55 let range = self.version_byte_range();
56 self.data.read_at(range.start).ok().unwrap()
57 }
58
59 pub fn design_axis_size(&self) -> u16 {
61 let range = self.design_axis_size_byte_range();
62 self.data.read_at(range.start).ok().unwrap()
63 }
64
65 pub fn design_axis_count(&self) -> u16 {
70 let range = self.design_axis_count_byte_range();
71 self.data.read_at(range.start).ok().unwrap()
72 }
73
74 pub fn design_axes_offset(&self) -> Offset32 {
79 let range = self.design_axes_offset_byte_range();
80 self.data.read_at(range.start).ok().unwrap()
81 }
82
83 pub fn design_axes(&self) -> Result<&'a [AxisRecord], ReadError> {
85 let data = self.data;
86 let args = self.design_axis_count();
87 self.design_axes_offset().resolve_with_args(data, args)
88 }
89
90 pub fn axis_value_count(&self) -> u16 {
92 let range = self.axis_value_count_byte_range();
93 self.data.read_at(range.start).ok().unwrap()
94 }
95
96 pub fn offset_to_axis_value_offsets(&self) -> Nullable<Offset32> {
101 let range = self.offset_to_axis_value_offsets_byte_range();
102 self.data.read_at(range.start).ok().unwrap()
103 }
104
105 pub fn offset_to_axis_values(&self) -> Option<Result<AxisValueArray<'a>, ReadError>> {
107 let data = self.data;
108 let args = self.axis_value_count();
109 self.offset_to_axis_value_offsets()
110 .resolve_with_args(data, args)
111 }
112
113 pub fn elided_fallback_name_id(&self) -> Option<NameId> {
117 let range = self.elided_fallback_name_id_byte_range();
118 (!range.is_empty())
119 .then(|| self.data.read_at(range.start).ok())
120 .flatten()
121 }
122
123 pub fn version_byte_range(&self) -> Range<usize> {
124 let start = 0;
125 let end = start + MajorMinor::RAW_BYTE_LEN;
126 start..end
127 }
128
129 pub fn design_axis_size_byte_range(&self) -> Range<usize> {
130 let start = self.version_byte_range().end;
131 let end = start + u16::RAW_BYTE_LEN;
132 start..end
133 }
134
135 pub fn design_axis_count_byte_range(&self) -> Range<usize> {
136 let start = self.design_axis_size_byte_range().end;
137 let end = start + u16::RAW_BYTE_LEN;
138 start..end
139 }
140
141 pub fn design_axes_offset_byte_range(&self) -> Range<usize> {
142 let start = self.design_axis_count_byte_range().end;
143 let end = start + Offset32::RAW_BYTE_LEN;
144 start..end
145 }
146
147 pub fn axis_value_count_byte_range(&self) -> Range<usize> {
148 let start = self.design_axes_offset_byte_range().end;
149 let end = start + u16::RAW_BYTE_LEN;
150 start..end
151 }
152
153 pub fn offset_to_axis_value_offsets_byte_range(&self) -> Range<usize> {
154 let start = self.axis_value_count_byte_range().end;
155 let end = start + Offset32::RAW_BYTE_LEN;
156 start..end
157 }
158
159 pub fn elided_fallback_name_id_byte_range(&self) -> Range<usize> {
160 let start = self.offset_to_axis_value_offsets_byte_range().end;
161 let end = if self.version().compatible((1u16, 1u16)) {
162 start + NameId::RAW_BYTE_LEN
163 } else {
164 start
165 };
166 start..end
167 }
168}
169
170const _: () = assert!(FontData::default_data_long_enough(Stat::MIN_SIZE));
171
172impl Default for Stat<'_> {
173 fn default() -> Self {
174 Self {
175 data: FontData::default_table_data(),
176 }
177 }
178}
179
180#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
182#[repr(C)]
183#[repr(packed)]
184pub struct AxisRecord {
185 pub axis_tag: BigEndian<Tag>,
187 pub axis_name_id: BigEndian<NameId>,
190 pub axis_ordering: BigEndian<u16>,
194}
195
196impl AxisRecord {
197 pub fn axis_tag(&self) -> Tag {
199 self.axis_tag.get()
200 }
201
202 pub fn axis_name_id(&self) -> NameId {
205 self.axis_name_id.get()
206 }
207
208 pub fn axis_ordering(&self) -> u16 {
212 self.axis_ordering.get()
213 }
214}
215
216impl FixedSize for AxisRecord {
217 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
218}
219
220impl<'a> MinByteRange<'a> for AxisValueArray<'a> {
221 fn min_byte_range(&self) -> Range<usize> {
222 0..self.axis_value_offsets_byte_range().end
223 }
224 fn min_table_bytes(&self) -> &'a [u8] {
225 let range = self.min_byte_range();
226 self.data.as_bytes().get(range).unwrap_or_default()
227 }
228}
229
230impl ReadArgs for AxisValueArray<'_> {
231 type Args = u16;
232}
233
234impl<'a> FontRead<'a> for AxisValueArray<'a> {
235 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
236 let axis_value_count = args;
237
238 #[allow(clippy::absurd_extreme_comparisons)]
239 if data.len() < Self::MIN_SIZE {
240 return Err(ReadError::OutOfBounds);
241 }
242 Ok(Self {
243 data,
244 axis_value_count,
245 })
246 }
247}
248
249impl<'a> AxisValueArray<'a> {
250 pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
255 let args = axis_value_count;
256 Self::read_with_args(data, args)
257 }
258}
259
260#[derive(Clone)]
262pub struct AxisValueArray<'a> {
263 data: FontData<'a>,
264 axis_value_count: u16,
265}
266
267#[allow(clippy::needless_lifetimes)]
268impl<'a> AxisValueArray<'a> {
269 pub const MIN_SIZE: usize = 0;
270 basic_table_impls!(impl_the_methods);
271
272 pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
275 let range = self.axis_value_offsets_byte_range();
276 self.data.read_array(range).ok().unwrap_or_default()
277 }
278
279 pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
281 let data = self.data;
282 let offsets = self.axis_value_offsets();
283 ArrayOfOffsets::new(offsets, data, ())
284 }
285
286 pub(crate) fn axis_value_count(&self) -> u16 {
287 self.axis_value_count
288 }
289
290 pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
291 let axis_value_count = self.axis_value_count();
292 let start = 0;
293 let end =
294 start + (transforms::to_usize(axis_value_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
295 start..end
296 }
297}
298
299#[allow(clippy::absurd_extreme_comparisons)]
300const _: () = assert!(FontData::default_data_long_enough(AxisValueArray::MIN_SIZE));
301
302impl Default for AxisValueArray<'_> {
303 fn default() -> Self {
304 Self {
305 data: FontData::default_table_data(),
306 axis_value_count: Default::default(),
307 }
308 }
309}
310
311#[derive(Clone)]
313pub enum AxisValue<'a> {
314 Format1(AxisValueFormat1<'a>),
315 Format2(AxisValueFormat2<'a>),
316 Format3(AxisValueFormat3<'a>),
317 Format4(AxisValueFormat4<'a>),
318}
319
320impl Default for AxisValue<'_> {
321 fn default() -> Self {
322 Self::Format1(Default::default())
323 }
324}
325
326impl<'a> AxisValue<'a> {
327 pub fn offset_data(&self) -> FontData<'a> {
329 match self {
330 Self::Format1(item) => item.offset_data(),
331 Self::Format2(item) => item.offset_data(),
332 Self::Format3(item) => item.offset_data(),
333 Self::Format4(item) => item.offset_data(),
334 }
335 }
336
337 pub fn format(&self) -> u16 {
339 match self {
340 Self::Format1(item) => item.format(),
341 Self::Format2(item) => item.format(),
342 Self::Format3(item) => item.format(),
343 Self::Format4(item) => item.format(),
344 }
345 }
346
347 pub fn flags(&self) -> AxisValueTableFlags {
349 match self {
350 Self::Format1(item) => item.flags(),
351 Self::Format2(item) => item.flags(),
352 Self::Format3(item) => item.flags(),
353 Self::Format4(item) => item.flags(),
354 }
355 }
356
357 pub fn value_name_id(&self) -> NameId {
360 match self {
361 Self::Format1(item) => item.value_name_id(),
362 Self::Format2(item) => item.value_name_id(),
363 Self::Format3(item) => item.value_name_id(),
364 Self::Format4(item) => item.value_name_id(),
365 }
366 }
367}
368
369impl ReadArgs for AxisValue<'_> {
370 type Args = ();
371}
372
373impl<'a> FontRead<'a> for AxisValue<'a> {
374 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
375 let format: u16 = data.read_at(0usize)?;
376 match format {
377 AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
378 AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
379 AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
380 AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
381 other => Err(ReadError::InvalidFormat(other.into())),
382 }
383 }
384}
385
386impl<'a> MinByteRange<'a> for AxisValue<'a> {
387 fn min_byte_range(&self) -> Range<usize> {
388 match self {
389 Self::Format1(item) => item.min_byte_range(),
390 Self::Format2(item) => item.min_byte_range(),
391 Self::Format3(item) => item.min_byte_range(),
392 Self::Format4(item) => item.min_byte_range(),
393 }
394 }
395 fn min_table_bytes(&self) -> &'a [u8] {
396 match self {
397 Self::Format1(item) => item.min_table_bytes(),
398 Self::Format2(item) => item.min_table_bytes(),
399 Self::Format3(item) => item.min_table_bytes(),
400 Self::Format4(item) => item.min_table_bytes(),
401 }
402 }
403}
404
405impl Format<u16> for AxisValueFormat1<'_> {
406 const FORMAT: u16 = 1;
407}
408
409impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
410 fn min_byte_range(&self) -> Range<usize> {
411 0..self.value_byte_range().end
412 }
413 fn min_table_bytes(&self) -> &'a [u8] {
414 let range = self.min_byte_range();
415 self.data.as_bytes().get(range).unwrap_or_default()
416 }
417}
418
419impl ReadArgs for AxisValueFormat1<'_> {
420 type Args = ();
421}
422
423impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
424 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
425 #[allow(clippy::absurd_extreme_comparisons)]
426 if data.len() < Self::MIN_SIZE {
427 return Err(ReadError::OutOfBounds);
428 }
429 Ok(Self { data })
430 }
431}
432
433#[derive(Clone)]
435pub struct AxisValueFormat1<'a> {
436 data: FontData<'a>,
437}
438
439#[allow(clippy::needless_lifetimes)]
440impl<'a> AxisValueFormat1<'a> {
441 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
442 + u16::RAW_BYTE_LEN
443 + AxisValueTableFlags::RAW_BYTE_LEN
444 + NameId::RAW_BYTE_LEN
445 + Fixed::RAW_BYTE_LEN);
446 basic_table_impls!(impl_the_methods);
447
448 pub fn format(&self) -> u16 {
450 let range = self.format_byte_range();
451 self.data.read_at(range.start).ok().unwrap()
452 }
453
454 pub fn axis_index(&self) -> u16 {
458 let range = self.axis_index_byte_range();
459 self.data.read_at(range.start).ok().unwrap()
460 }
461
462 pub fn flags(&self) -> AxisValueTableFlags {
464 let range = self.flags_byte_range();
465 self.data.read_at(range.start).ok().unwrap()
466 }
467
468 pub fn value_name_id(&self) -> NameId {
471 let range = self.value_name_id_byte_range();
472 self.data.read_at(range.start).ok().unwrap()
473 }
474
475 pub fn value(&self) -> Fixed {
477 let range = self.value_byte_range();
478 self.data.read_at(range.start).ok().unwrap()
479 }
480
481 pub fn format_byte_range(&self) -> Range<usize> {
482 let start = 0;
483 let end = start + u16::RAW_BYTE_LEN;
484 start..end
485 }
486
487 pub fn axis_index_byte_range(&self) -> Range<usize> {
488 let start = self.format_byte_range().end;
489 let end = start + u16::RAW_BYTE_LEN;
490 start..end
491 }
492
493 pub fn flags_byte_range(&self) -> Range<usize> {
494 let start = self.axis_index_byte_range().end;
495 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
496 start..end
497 }
498
499 pub fn value_name_id_byte_range(&self) -> Range<usize> {
500 let start = self.flags_byte_range().end;
501 let end = start + NameId::RAW_BYTE_LEN;
502 start..end
503 }
504
505 pub fn value_byte_range(&self) -> Range<usize> {
506 let start = self.value_name_id_byte_range().end;
507 let end = start + Fixed::RAW_BYTE_LEN;
508 start..end
509 }
510}
511
512const _: () = assert!(FontData::default_data_long_enough(
513 AxisValueFormat1::MIN_SIZE
514));
515
516impl Default for AxisValueFormat1<'_> {
517 fn default() -> Self {
518 Self {
519 data: FontData::default_format_1_u16_table_data(),
520 }
521 }
522}
523
524impl Format<u16> for AxisValueFormat2<'_> {
525 const FORMAT: u16 = 2;
526}
527
528impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
529 fn min_byte_range(&self) -> Range<usize> {
530 0..self.range_max_value_byte_range().end
531 }
532 fn min_table_bytes(&self) -> &'a [u8] {
533 let range = self.min_byte_range();
534 self.data.as_bytes().get(range).unwrap_or_default()
535 }
536}
537
538impl ReadArgs for AxisValueFormat2<'_> {
539 type Args = ();
540}
541
542impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
543 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
544 #[allow(clippy::absurd_extreme_comparisons)]
545 if data.len() < Self::MIN_SIZE {
546 return Err(ReadError::OutOfBounds);
547 }
548 Ok(Self { data })
549 }
550}
551
552#[derive(Clone)]
554pub struct AxisValueFormat2<'a> {
555 data: FontData<'a>,
556}
557
558#[allow(clippy::needless_lifetimes)]
559impl<'a> AxisValueFormat2<'a> {
560 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
561 + u16::RAW_BYTE_LEN
562 + AxisValueTableFlags::RAW_BYTE_LEN
563 + NameId::RAW_BYTE_LEN
564 + Fixed::RAW_BYTE_LEN
565 + Fixed::RAW_BYTE_LEN
566 + Fixed::RAW_BYTE_LEN);
567 basic_table_impls!(impl_the_methods);
568
569 pub fn format(&self) -> u16 {
571 let range = self.format_byte_range();
572 self.data.read_at(range.start).ok().unwrap()
573 }
574
575 pub fn axis_index(&self) -> u16 {
579 let range = self.axis_index_byte_range();
580 self.data.read_at(range.start).ok().unwrap()
581 }
582
583 pub fn flags(&self) -> AxisValueTableFlags {
585 let range = self.flags_byte_range();
586 self.data.read_at(range.start).ok().unwrap()
587 }
588
589 pub fn value_name_id(&self) -> NameId {
592 let range = self.value_name_id_byte_range();
593 self.data.read_at(range.start).ok().unwrap()
594 }
595
596 pub fn nominal_value(&self) -> Fixed {
598 let range = self.nominal_value_byte_range();
599 self.data.read_at(range.start).ok().unwrap()
600 }
601
602 pub fn range_min_value(&self) -> Fixed {
605 let range = self.range_min_value_byte_range();
606 self.data.read_at(range.start).ok().unwrap()
607 }
608
609 pub fn range_max_value(&self) -> Fixed {
612 let range = self.range_max_value_byte_range();
613 self.data.read_at(range.start).ok().unwrap()
614 }
615
616 pub fn format_byte_range(&self) -> Range<usize> {
617 let start = 0;
618 let end = start + u16::RAW_BYTE_LEN;
619 start..end
620 }
621
622 pub fn axis_index_byte_range(&self) -> Range<usize> {
623 let start = self.format_byte_range().end;
624 let end = start + u16::RAW_BYTE_LEN;
625 start..end
626 }
627
628 pub fn flags_byte_range(&self) -> Range<usize> {
629 let start = self.axis_index_byte_range().end;
630 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
631 start..end
632 }
633
634 pub fn value_name_id_byte_range(&self) -> Range<usize> {
635 let start = self.flags_byte_range().end;
636 let end = start + NameId::RAW_BYTE_LEN;
637 start..end
638 }
639
640 pub fn nominal_value_byte_range(&self) -> Range<usize> {
641 let start = self.value_name_id_byte_range().end;
642 let end = start + Fixed::RAW_BYTE_LEN;
643 start..end
644 }
645
646 pub fn range_min_value_byte_range(&self) -> Range<usize> {
647 let start = self.nominal_value_byte_range().end;
648 let end = start + Fixed::RAW_BYTE_LEN;
649 start..end
650 }
651
652 pub fn range_max_value_byte_range(&self) -> Range<usize> {
653 let start = self.range_min_value_byte_range().end;
654 let end = start + Fixed::RAW_BYTE_LEN;
655 start..end
656 }
657}
658
659impl Format<u16> for AxisValueFormat3<'_> {
660 const FORMAT: u16 = 3;
661}
662
663impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
664 fn min_byte_range(&self) -> Range<usize> {
665 0..self.linked_value_byte_range().end
666 }
667 fn min_table_bytes(&self) -> &'a [u8] {
668 let range = self.min_byte_range();
669 self.data.as_bytes().get(range).unwrap_or_default()
670 }
671}
672
673impl ReadArgs for AxisValueFormat3<'_> {
674 type Args = ();
675}
676
677impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
678 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
679 #[allow(clippy::absurd_extreme_comparisons)]
680 if data.len() < Self::MIN_SIZE {
681 return Err(ReadError::OutOfBounds);
682 }
683 Ok(Self { data })
684 }
685}
686
687#[derive(Clone)]
689pub struct AxisValueFormat3<'a> {
690 data: FontData<'a>,
691}
692
693#[allow(clippy::needless_lifetimes)]
694impl<'a> AxisValueFormat3<'a> {
695 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
696 + u16::RAW_BYTE_LEN
697 + AxisValueTableFlags::RAW_BYTE_LEN
698 + NameId::RAW_BYTE_LEN
699 + Fixed::RAW_BYTE_LEN
700 + Fixed::RAW_BYTE_LEN);
701 basic_table_impls!(impl_the_methods);
702
703 pub fn format(&self) -> u16 {
705 let range = self.format_byte_range();
706 self.data.read_at(range.start).ok().unwrap()
707 }
708
709 pub fn axis_index(&self) -> u16 {
713 let range = self.axis_index_byte_range();
714 self.data.read_at(range.start).ok().unwrap()
715 }
716
717 pub fn flags(&self) -> AxisValueTableFlags {
719 let range = self.flags_byte_range();
720 self.data.read_at(range.start).ok().unwrap()
721 }
722
723 pub fn value_name_id(&self) -> NameId {
726 let range = self.value_name_id_byte_range();
727 self.data.read_at(range.start).ok().unwrap()
728 }
729
730 pub fn value(&self) -> Fixed {
732 let range = self.value_byte_range();
733 self.data.read_at(range.start).ok().unwrap()
734 }
735
736 pub fn linked_value(&self) -> Fixed {
738 let range = self.linked_value_byte_range();
739 self.data.read_at(range.start).ok().unwrap()
740 }
741
742 pub fn format_byte_range(&self) -> Range<usize> {
743 let start = 0;
744 let end = start + u16::RAW_BYTE_LEN;
745 start..end
746 }
747
748 pub fn axis_index_byte_range(&self) -> Range<usize> {
749 let start = self.format_byte_range().end;
750 let end = start + u16::RAW_BYTE_LEN;
751 start..end
752 }
753
754 pub fn flags_byte_range(&self) -> Range<usize> {
755 let start = self.axis_index_byte_range().end;
756 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
757 start..end
758 }
759
760 pub fn value_name_id_byte_range(&self) -> Range<usize> {
761 let start = self.flags_byte_range().end;
762 let end = start + NameId::RAW_BYTE_LEN;
763 start..end
764 }
765
766 pub fn value_byte_range(&self) -> Range<usize> {
767 let start = self.value_name_id_byte_range().end;
768 let end = start + Fixed::RAW_BYTE_LEN;
769 start..end
770 }
771
772 pub fn linked_value_byte_range(&self) -> Range<usize> {
773 let start = self.value_byte_range().end;
774 let end = start + Fixed::RAW_BYTE_LEN;
775 start..end
776 }
777}
778
779impl Format<u16> for AxisValueFormat4<'_> {
780 const FORMAT: u16 = 4;
781}
782
783impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
784 fn min_byte_range(&self) -> Range<usize> {
785 0..self.axis_values_byte_range().end
786 }
787 fn min_table_bytes(&self) -> &'a [u8] {
788 let range = self.min_byte_range();
789 self.data.as_bytes().get(range).unwrap_or_default()
790 }
791}
792
793impl ReadArgs for AxisValueFormat4<'_> {
794 type Args = ();
795}
796
797impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
798 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
799 #[allow(clippy::absurd_extreme_comparisons)]
800 if data.len() < Self::MIN_SIZE {
801 return Err(ReadError::OutOfBounds);
802 }
803 Ok(Self { data })
804 }
805}
806
807#[derive(Clone)]
809pub struct AxisValueFormat4<'a> {
810 data: FontData<'a>,
811}
812
813#[allow(clippy::needless_lifetimes)]
814impl<'a> AxisValueFormat4<'a> {
815 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
816 + u16::RAW_BYTE_LEN
817 + AxisValueTableFlags::RAW_BYTE_LEN
818 + NameId::RAW_BYTE_LEN);
819 basic_table_impls!(impl_the_methods);
820
821 pub fn format(&self) -> u16 {
823 let range = self.format_byte_range();
824 self.data.read_at(range.start).ok().unwrap()
825 }
826
827 pub fn axis_count(&self) -> u16 {
830 let range = self.axis_count_byte_range();
831 self.data.read_at(range.start).ok().unwrap()
832 }
833
834 pub fn flags(&self) -> AxisValueTableFlags {
836 let range = self.flags_byte_range();
837 self.data.read_at(range.start).ok().unwrap()
838 }
839
840 pub fn value_name_id(&self) -> NameId {
843 let range = self.value_name_id_byte_range();
844 self.data.read_at(range.start).ok().unwrap()
845 }
846
847 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
850 let range = self.axis_values_byte_range();
851 self.data.read_array(range).ok().unwrap_or_default()
852 }
853
854 pub fn format_byte_range(&self) -> Range<usize> {
855 let start = 0;
856 let end = start + u16::RAW_BYTE_LEN;
857 start..end
858 }
859
860 pub fn axis_count_byte_range(&self) -> Range<usize> {
861 let start = self.format_byte_range().end;
862 let end = start + u16::RAW_BYTE_LEN;
863 start..end
864 }
865
866 pub fn flags_byte_range(&self) -> Range<usize> {
867 let start = self.axis_count_byte_range().end;
868 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
869 start..end
870 }
871
872 pub fn value_name_id_byte_range(&self) -> Range<usize> {
873 let start = self.flags_byte_range().end;
874 let end = start + NameId::RAW_BYTE_LEN;
875 start..end
876 }
877
878 pub fn axis_values_byte_range(&self) -> Range<usize> {
879 let axis_count = self.axis_count();
880 let start = self.value_name_id_byte_range().end;
881 let end = start
882 + (transforms::to_usize(axis_count)).saturating_mul(AxisValueRecord::RAW_BYTE_LEN);
883 start..end
884 }
885}
886
887#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
889#[repr(C)]
890#[repr(packed)]
891pub struct AxisValueRecord {
892 pub axis_index: BigEndian<u16>,
895 pub value: BigEndian<Fixed>,
897}
898
899impl AxisValueRecord {
900 pub fn axis_index(&self) -> u16 {
903 self.axis_index.get()
904 }
905
906 pub fn value(&self) -> Fixed {
908 self.value.get()
909 }
910}
911
912impl FixedSize for AxisValueRecord {
913 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
914}
915
916#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
918#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
919#[repr(transparent)]
920pub struct AxisValueTableFlags {
921 bits: u16,
922}
923
924impl AxisValueTableFlags {
925 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
932
933 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
937}
938
939impl AxisValueTableFlags {
940 #[inline]
942 pub const fn empty() -> Self {
943 Self { bits: 0 }
944 }
945
946 #[inline]
948 pub const fn all() -> Self {
949 Self {
950 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
951 }
952 }
953
954 #[inline]
956 pub const fn bits(&self) -> u16 {
957 self.bits
958 }
959
960 #[inline]
963 pub const fn from_bits(bits: u16) -> Option<Self> {
964 if (bits & !Self::all().bits()) == 0 {
965 Some(Self { bits })
966 } else {
967 None
968 }
969 }
970
971 #[inline]
974 pub const fn from_bits_truncate(bits: u16) -> Self {
975 Self {
976 bits: bits & Self::all().bits,
977 }
978 }
979
980 #[inline]
982 pub const fn is_empty(&self) -> bool {
983 self.bits() == Self::empty().bits()
984 }
985
986 #[inline]
988 pub const fn intersects(&self, other: Self) -> bool {
989 !(Self {
990 bits: self.bits & other.bits,
991 })
992 .is_empty()
993 }
994
995 #[inline]
997 pub const fn contains(&self, other: Self) -> bool {
998 (self.bits & other.bits) == other.bits
999 }
1000
1001 #[inline]
1003 pub fn insert(&mut self, other: Self) {
1004 self.bits |= other.bits;
1005 }
1006
1007 #[inline]
1009 pub fn remove(&mut self, other: Self) {
1010 self.bits &= !other.bits;
1011 }
1012
1013 #[inline]
1015 pub fn toggle(&mut self, other: Self) {
1016 self.bits ^= other.bits;
1017 }
1018
1019 #[inline]
1030 #[must_use]
1031 pub const fn intersection(self, other: Self) -> Self {
1032 Self {
1033 bits: self.bits & other.bits,
1034 }
1035 }
1036
1037 #[inline]
1048 #[must_use]
1049 pub const fn union(self, other: Self) -> Self {
1050 Self {
1051 bits: self.bits | other.bits,
1052 }
1053 }
1054
1055 #[inline]
1068 #[must_use]
1069 pub const fn difference(self, other: Self) -> Self {
1070 Self {
1071 bits: self.bits & !other.bits,
1072 }
1073 }
1074}
1075
1076impl std::ops::BitOr for AxisValueTableFlags {
1077 type Output = Self;
1078
1079 #[inline]
1081 fn bitor(self, other: AxisValueTableFlags) -> Self {
1082 Self {
1083 bits: self.bits | other.bits,
1084 }
1085 }
1086}
1087
1088impl std::ops::BitOrAssign for AxisValueTableFlags {
1089 #[inline]
1091 fn bitor_assign(&mut self, other: Self) {
1092 self.bits |= other.bits;
1093 }
1094}
1095
1096impl std::ops::BitXor for AxisValueTableFlags {
1097 type Output = Self;
1098
1099 #[inline]
1101 fn bitxor(self, other: Self) -> Self {
1102 Self {
1103 bits: self.bits ^ other.bits,
1104 }
1105 }
1106}
1107
1108impl std::ops::BitXorAssign for AxisValueTableFlags {
1109 #[inline]
1111 fn bitxor_assign(&mut self, other: Self) {
1112 self.bits ^= other.bits;
1113 }
1114}
1115
1116impl std::ops::BitAnd for AxisValueTableFlags {
1117 type Output = Self;
1118
1119 #[inline]
1121 fn bitand(self, other: Self) -> Self {
1122 Self {
1123 bits: self.bits & other.bits,
1124 }
1125 }
1126}
1127
1128impl std::ops::BitAndAssign for AxisValueTableFlags {
1129 #[inline]
1131 fn bitand_assign(&mut self, other: Self) {
1132 self.bits &= other.bits;
1133 }
1134}
1135
1136impl std::ops::Sub for AxisValueTableFlags {
1137 type Output = Self;
1138
1139 #[inline]
1141 fn sub(self, other: Self) -> Self {
1142 Self {
1143 bits: self.bits & !other.bits,
1144 }
1145 }
1146}
1147
1148impl std::ops::SubAssign for AxisValueTableFlags {
1149 #[inline]
1151 fn sub_assign(&mut self, other: Self) {
1152 self.bits &= !other.bits;
1153 }
1154}
1155
1156impl std::ops::Not for AxisValueTableFlags {
1157 type Output = Self;
1158
1159 #[inline]
1161 fn not(self) -> Self {
1162 Self { bits: !self.bits } & Self::all()
1163 }
1164}
1165
1166impl std::fmt::Debug for AxisValueTableFlags {
1167 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1168 let members: &[(&str, Self)] = &[
1169 (
1170 "OLDER_SIBLING_FONT_ATTRIBUTE",
1171 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1172 ),
1173 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1174 ];
1175 let mut first = true;
1176 for (name, value) in members {
1177 if self.contains(*value) {
1178 if !first {
1179 f.write_str(" | ")?;
1180 }
1181 first = false;
1182 f.write_str(name)?;
1183 }
1184 }
1185 if first {
1186 f.write_str("(empty)")?;
1187 }
1188 Ok(())
1189 }
1190}
1191
1192impl std::fmt::Binary for AxisValueTableFlags {
1193 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1194 std::fmt::Binary::fmt(&self.bits, f)
1195 }
1196}
1197
1198impl std::fmt::Octal for AxisValueTableFlags {
1199 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1200 std::fmt::Octal::fmt(&self.bits, f)
1201 }
1202}
1203
1204impl std::fmt::LowerHex for AxisValueTableFlags {
1205 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1206 std::fmt::LowerHex::fmt(&self.bits, f)
1207 }
1208}
1209
1210impl std::fmt::UpperHex for AxisValueTableFlags {
1211 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1212 std::fmt::UpperHex::fmt(&self.bits, f)
1213 }
1214}
1215
1216impl font_types::Scalar for AxisValueTableFlags {
1217 type Raw = <u16 as font_types::Scalar>::Raw;
1218 fn to_raw(self) -> Self::Raw {
1219 self.bits().to_raw()
1220 }
1221 fn from_raw(raw: Self::Raw) -> Self {
1222 let t = <u16>::from_raw(raw);
1223 Self::from_bits_truncate(t)
1224 }
1225}