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#[cfg(feature = "experimental_traverse")]
181impl<'a> SomeTable<'a> for Stat<'a> {
182 fn type_name(&self) -> &str {
183 "Stat"
184 }
185 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
186 match idx {
187 0usize => Some(Field::new("version", self.version())),
188 1usize => Some(Field::new("design_axis_size", self.design_axis_size())),
189 2usize => Some(Field::new("design_axis_count", self.design_axis_count())),
190 3usize => Some(Field::new(
191 "design_axes_offset",
192 traversal::FieldType::offset_to_array_of_records(
193 self.design_axes_offset(),
194 self.design_axes(),
195 stringify!(AxisRecord),
196 self.offset_data(),
197 ),
198 )),
199 4usize => Some(Field::new("axis_value_count", self.axis_value_count())),
200 5usize => Some(Field::new(
201 "offset_to_axis_value_offsets",
202 FieldType::offset(
203 self.offset_to_axis_value_offsets(),
204 self.offset_to_axis_values(),
205 ),
206 )),
207 6usize if self.version().compatible((1u16, 1u16)) => Some(Field::new(
208 "elided_fallback_name_id",
209 self.elided_fallback_name_id().unwrap(),
210 )),
211 _ => None,
212 }
213 }
214}
215
216#[cfg(feature = "experimental_traverse")]
217#[allow(clippy::needless_lifetimes)]
218impl<'a> std::fmt::Debug for Stat<'a> {
219 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
220 (self as &dyn SomeTable<'a>).fmt(f)
221 }
222}
223
224#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
226#[repr(C)]
227#[repr(packed)]
228pub struct AxisRecord {
229 pub axis_tag: BigEndian<Tag>,
231 pub axis_name_id: BigEndian<NameId>,
234 pub axis_ordering: BigEndian<u16>,
238}
239
240impl AxisRecord {
241 pub fn axis_tag(&self) -> Tag {
243 self.axis_tag.get()
244 }
245
246 pub fn axis_name_id(&self) -> NameId {
249 self.axis_name_id.get()
250 }
251
252 pub fn axis_ordering(&self) -> u16 {
256 self.axis_ordering.get()
257 }
258}
259
260impl FixedSize for AxisRecord {
261 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
262}
263
264#[cfg(feature = "experimental_traverse")]
265impl<'a> SomeRecord<'a> for AxisRecord {
266 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
267 RecordResolver {
268 name: "AxisRecord",
269 get_field: Box::new(move |idx, _data| match idx {
270 0usize => Some(Field::new("axis_tag", self.axis_tag())),
271 1usize => Some(Field::new("axis_name_id", self.axis_name_id())),
272 2usize => Some(Field::new("axis_ordering", self.axis_ordering())),
273 _ => None,
274 }),
275 data,
276 }
277 }
278}
279
280impl<'a> MinByteRange<'a> for AxisValueArray<'a> {
281 fn min_byte_range(&self) -> Range<usize> {
282 0..self.axis_value_offsets_byte_range().end
283 }
284 fn min_table_bytes(&self) -> &'a [u8] {
285 let range = self.min_byte_range();
286 self.data.as_bytes().get(range).unwrap_or_default()
287 }
288}
289
290impl ReadArgs for AxisValueArray<'_> {
291 type Args = u16;
292}
293
294impl<'a> FontRead<'a> for AxisValueArray<'a> {
295 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
296 let axis_value_count = args;
297
298 #[allow(clippy::absurd_extreme_comparisons)]
299 if data.len() < Self::MIN_SIZE {
300 return Err(ReadError::OutOfBounds);
301 }
302 Ok(Self {
303 data,
304 axis_value_count,
305 })
306 }
307}
308
309impl<'a> AxisValueArray<'a> {
310 pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
315 let args = axis_value_count;
316 Self::read_with_args(data, args)
317 }
318}
319
320#[derive(Clone)]
322pub struct AxisValueArray<'a> {
323 data: FontData<'a>,
324 axis_value_count: u16,
325}
326
327#[allow(clippy::needless_lifetimes)]
328impl<'a> AxisValueArray<'a> {
329 pub const MIN_SIZE: usize = 0;
330 basic_table_impls!(impl_the_methods);
331
332 pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
335 let range = self.axis_value_offsets_byte_range();
336 self.data.read_array(range).ok().unwrap_or_default()
337 }
338
339 pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
341 let data = self.data;
342 let offsets = self.axis_value_offsets();
343 ArrayOfOffsets::new(offsets, data, ())
344 }
345
346 pub(crate) fn axis_value_count(&self) -> u16 {
347 self.axis_value_count
348 }
349
350 pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
351 let axis_value_count = self.axis_value_count();
352 let start = 0;
353 let end =
354 start + (transforms::to_usize(axis_value_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
355 start..end
356 }
357}
358
359#[allow(clippy::absurd_extreme_comparisons)]
360const _: () = assert!(FontData::default_data_long_enough(AxisValueArray::MIN_SIZE));
361
362impl Default for AxisValueArray<'_> {
363 fn default() -> Self {
364 Self {
365 data: FontData::default_table_data(),
366 axis_value_count: Default::default(),
367 }
368 }
369}
370
371#[cfg(feature = "experimental_traverse")]
372impl<'a> SomeTable<'a> for AxisValueArray<'a> {
373 fn type_name(&self) -> &str {
374 "AxisValueArray"
375 }
376 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
377 match idx {
378 0usize => Some(Field::new(
379 "axis_value_offsets",
380 FieldType::from(self.axis_values()),
381 )),
382 _ => None,
383 }
384 }
385}
386
387#[cfg(feature = "experimental_traverse")]
388#[allow(clippy::needless_lifetimes)]
389impl<'a> std::fmt::Debug for AxisValueArray<'a> {
390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 (self as &dyn SomeTable<'a>).fmt(f)
392 }
393}
394
395#[derive(Clone)]
397pub enum AxisValue<'a> {
398 Format1(AxisValueFormat1<'a>),
399 Format2(AxisValueFormat2<'a>),
400 Format3(AxisValueFormat3<'a>),
401 Format4(AxisValueFormat4<'a>),
402}
403
404impl Default for AxisValue<'_> {
405 fn default() -> Self {
406 Self::Format1(Default::default())
407 }
408}
409
410impl<'a> AxisValue<'a> {
411 pub fn offset_data(&self) -> FontData<'a> {
413 match self {
414 Self::Format1(item) => item.offset_data(),
415 Self::Format2(item) => item.offset_data(),
416 Self::Format3(item) => item.offset_data(),
417 Self::Format4(item) => item.offset_data(),
418 }
419 }
420
421 pub fn format(&self) -> u16 {
423 match self {
424 Self::Format1(item) => item.format(),
425 Self::Format2(item) => item.format(),
426 Self::Format3(item) => item.format(),
427 Self::Format4(item) => item.format(),
428 }
429 }
430
431 pub fn flags(&self) -> AxisValueTableFlags {
433 match self {
434 Self::Format1(item) => item.flags(),
435 Self::Format2(item) => item.flags(),
436 Self::Format3(item) => item.flags(),
437 Self::Format4(item) => item.flags(),
438 }
439 }
440
441 pub fn value_name_id(&self) -> NameId {
444 match self {
445 Self::Format1(item) => item.value_name_id(),
446 Self::Format2(item) => item.value_name_id(),
447 Self::Format3(item) => item.value_name_id(),
448 Self::Format4(item) => item.value_name_id(),
449 }
450 }
451}
452
453impl ReadArgs for AxisValue<'_> {
454 type Args = ();
455}
456
457impl<'a> FontRead<'a> for AxisValue<'a> {
458 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
459 let format: u16 = data.read_at(0usize)?;
460 match format {
461 AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
462 AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
463 AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
464 AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
465 other => Err(ReadError::InvalidFormat(other.into())),
466 }
467 }
468}
469
470impl<'a> MinByteRange<'a> for AxisValue<'a> {
471 fn min_byte_range(&self) -> Range<usize> {
472 match self {
473 Self::Format1(item) => item.min_byte_range(),
474 Self::Format2(item) => item.min_byte_range(),
475 Self::Format3(item) => item.min_byte_range(),
476 Self::Format4(item) => item.min_byte_range(),
477 }
478 }
479 fn min_table_bytes(&self) -> &'a [u8] {
480 match self {
481 Self::Format1(item) => item.min_table_bytes(),
482 Self::Format2(item) => item.min_table_bytes(),
483 Self::Format3(item) => item.min_table_bytes(),
484 Self::Format4(item) => item.min_table_bytes(),
485 }
486 }
487}
488
489#[cfg(feature = "experimental_traverse")]
490impl<'a> AxisValue<'a> {
491 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
492 match self {
493 Self::Format1(table) => table,
494 Self::Format2(table) => table,
495 Self::Format3(table) => table,
496 Self::Format4(table) => table,
497 }
498 }
499}
500
501#[cfg(feature = "experimental_traverse")]
502impl std::fmt::Debug for AxisValue<'_> {
503 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
504 self.dyn_inner().fmt(f)
505 }
506}
507
508#[cfg(feature = "experimental_traverse")]
509impl<'a> SomeTable<'a> for AxisValue<'a> {
510 fn type_name(&self) -> &str {
511 self.dyn_inner().type_name()
512 }
513 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
514 self.dyn_inner().get_field(idx)
515 }
516}
517
518impl Format<u16> for AxisValueFormat1<'_> {
519 const FORMAT: u16 = 1;
520}
521
522impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
523 fn min_byte_range(&self) -> Range<usize> {
524 0..self.value_byte_range().end
525 }
526 fn min_table_bytes(&self) -> &'a [u8] {
527 let range = self.min_byte_range();
528 self.data.as_bytes().get(range).unwrap_or_default()
529 }
530}
531
532impl ReadArgs for AxisValueFormat1<'_> {
533 type Args = ();
534}
535
536impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
537 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
538 #[allow(clippy::absurd_extreme_comparisons)]
539 if data.len() < Self::MIN_SIZE {
540 return Err(ReadError::OutOfBounds);
541 }
542 Ok(Self { data })
543 }
544}
545
546#[derive(Clone)]
548pub struct AxisValueFormat1<'a> {
549 data: FontData<'a>,
550}
551
552#[allow(clippy::needless_lifetimes)]
553impl<'a> AxisValueFormat1<'a> {
554 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
555 + u16::RAW_BYTE_LEN
556 + AxisValueTableFlags::RAW_BYTE_LEN
557 + NameId::RAW_BYTE_LEN
558 + Fixed::RAW_BYTE_LEN);
559 basic_table_impls!(impl_the_methods);
560
561 pub fn format(&self) -> u16 {
563 let range = self.format_byte_range();
564 self.data.read_at(range.start).ok().unwrap()
565 }
566
567 pub fn axis_index(&self) -> u16 {
571 let range = self.axis_index_byte_range();
572 self.data.read_at(range.start).ok().unwrap()
573 }
574
575 pub fn flags(&self) -> AxisValueTableFlags {
577 let range = self.flags_byte_range();
578 self.data.read_at(range.start).ok().unwrap()
579 }
580
581 pub fn value_name_id(&self) -> NameId {
584 let range = self.value_name_id_byte_range();
585 self.data.read_at(range.start).ok().unwrap()
586 }
587
588 pub fn value(&self) -> Fixed {
590 let range = self.value_byte_range();
591 self.data.read_at(range.start).ok().unwrap()
592 }
593
594 pub fn format_byte_range(&self) -> Range<usize> {
595 let start = 0;
596 let end = start + u16::RAW_BYTE_LEN;
597 start..end
598 }
599
600 pub fn axis_index_byte_range(&self) -> Range<usize> {
601 let start = self.format_byte_range().end;
602 let end = start + u16::RAW_BYTE_LEN;
603 start..end
604 }
605
606 pub fn flags_byte_range(&self) -> Range<usize> {
607 let start = self.axis_index_byte_range().end;
608 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
609 start..end
610 }
611
612 pub fn value_name_id_byte_range(&self) -> Range<usize> {
613 let start = self.flags_byte_range().end;
614 let end = start + NameId::RAW_BYTE_LEN;
615 start..end
616 }
617
618 pub fn value_byte_range(&self) -> Range<usize> {
619 let start = self.value_name_id_byte_range().end;
620 let end = start + Fixed::RAW_BYTE_LEN;
621 start..end
622 }
623}
624
625const _: () = assert!(FontData::default_data_long_enough(
626 AxisValueFormat1::MIN_SIZE
627));
628
629impl Default for AxisValueFormat1<'_> {
630 fn default() -> Self {
631 Self {
632 data: FontData::default_format_1_u16_table_data(),
633 }
634 }
635}
636
637#[cfg(feature = "experimental_traverse")]
638impl<'a> SomeTable<'a> for AxisValueFormat1<'a> {
639 fn type_name(&self) -> &str {
640 "AxisValueFormat1"
641 }
642 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
643 match idx {
644 0usize => Some(Field::new("format", self.format())),
645 1usize => Some(Field::new("axis_index", self.axis_index())),
646 2usize => Some(Field::new("flags", self.flags())),
647 3usize => Some(Field::new("value_name_id", self.value_name_id())),
648 4usize => Some(Field::new("value", self.value())),
649 _ => None,
650 }
651 }
652}
653
654#[cfg(feature = "experimental_traverse")]
655#[allow(clippy::needless_lifetimes)]
656impl<'a> std::fmt::Debug for AxisValueFormat1<'a> {
657 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
658 (self as &dyn SomeTable<'a>).fmt(f)
659 }
660}
661
662impl Format<u16> for AxisValueFormat2<'_> {
663 const FORMAT: u16 = 2;
664}
665
666impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
667 fn min_byte_range(&self) -> Range<usize> {
668 0..self.range_max_value_byte_range().end
669 }
670 fn min_table_bytes(&self) -> &'a [u8] {
671 let range = self.min_byte_range();
672 self.data.as_bytes().get(range).unwrap_or_default()
673 }
674}
675
676impl ReadArgs for AxisValueFormat2<'_> {
677 type Args = ();
678}
679
680impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
681 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
682 #[allow(clippy::absurd_extreme_comparisons)]
683 if data.len() < Self::MIN_SIZE {
684 return Err(ReadError::OutOfBounds);
685 }
686 Ok(Self { data })
687 }
688}
689
690#[derive(Clone)]
692pub struct AxisValueFormat2<'a> {
693 data: FontData<'a>,
694}
695
696#[allow(clippy::needless_lifetimes)]
697impl<'a> AxisValueFormat2<'a> {
698 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
699 + u16::RAW_BYTE_LEN
700 + AxisValueTableFlags::RAW_BYTE_LEN
701 + NameId::RAW_BYTE_LEN
702 + Fixed::RAW_BYTE_LEN
703 + Fixed::RAW_BYTE_LEN
704 + Fixed::RAW_BYTE_LEN);
705 basic_table_impls!(impl_the_methods);
706
707 pub fn format(&self) -> u16 {
709 let range = self.format_byte_range();
710 self.data.read_at(range.start).ok().unwrap()
711 }
712
713 pub fn axis_index(&self) -> u16 {
717 let range = self.axis_index_byte_range();
718 self.data.read_at(range.start).ok().unwrap()
719 }
720
721 pub fn flags(&self) -> AxisValueTableFlags {
723 let range = self.flags_byte_range();
724 self.data.read_at(range.start).ok().unwrap()
725 }
726
727 pub fn value_name_id(&self) -> NameId {
730 let range = self.value_name_id_byte_range();
731 self.data.read_at(range.start).ok().unwrap()
732 }
733
734 pub fn nominal_value(&self) -> Fixed {
736 let range = self.nominal_value_byte_range();
737 self.data.read_at(range.start).ok().unwrap()
738 }
739
740 pub fn range_min_value(&self) -> Fixed {
743 let range = self.range_min_value_byte_range();
744 self.data.read_at(range.start).ok().unwrap()
745 }
746
747 pub fn range_max_value(&self) -> Fixed {
750 let range = self.range_max_value_byte_range();
751 self.data.read_at(range.start).ok().unwrap()
752 }
753
754 pub fn format_byte_range(&self) -> Range<usize> {
755 let start = 0;
756 let end = start + u16::RAW_BYTE_LEN;
757 start..end
758 }
759
760 pub fn axis_index_byte_range(&self) -> Range<usize> {
761 let start = self.format_byte_range().end;
762 let end = start + u16::RAW_BYTE_LEN;
763 start..end
764 }
765
766 pub fn flags_byte_range(&self) -> Range<usize> {
767 let start = self.axis_index_byte_range().end;
768 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
769 start..end
770 }
771
772 pub fn value_name_id_byte_range(&self) -> Range<usize> {
773 let start = self.flags_byte_range().end;
774 let end = start + NameId::RAW_BYTE_LEN;
775 start..end
776 }
777
778 pub fn nominal_value_byte_range(&self) -> Range<usize> {
779 let start = self.value_name_id_byte_range().end;
780 let end = start + Fixed::RAW_BYTE_LEN;
781 start..end
782 }
783
784 pub fn range_min_value_byte_range(&self) -> Range<usize> {
785 let start = self.nominal_value_byte_range().end;
786 let end = start + Fixed::RAW_BYTE_LEN;
787 start..end
788 }
789
790 pub fn range_max_value_byte_range(&self) -> Range<usize> {
791 let start = self.range_min_value_byte_range().end;
792 let end = start + Fixed::RAW_BYTE_LEN;
793 start..end
794 }
795}
796
797#[cfg(feature = "experimental_traverse")]
798impl<'a> SomeTable<'a> for AxisValueFormat2<'a> {
799 fn type_name(&self) -> &str {
800 "AxisValueFormat2"
801 }
802 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
803 match idx {
804 0usize => Some(Field::new("format", self.format())),
805 1usize => Some(Field::new("axis_index", self.axis_index())),
806 2usize => Some(Field::new("flags", self.flags())),
807 3usize => Some(Field::new("value_name_id", self.value_name_id())),
808 4usize => Some(Field::new("nominal_value", self.nominal_value())),
809 5usize => Some(Field::new("range_min_value", self.range_min_value())),
810 6usize => Some(Field::new("range_max_value", self.range_max_value())),
811 _ => None,
812 }
813 }
814}
815
816#[cfg(feature = "experimental_traverse")]
817#[allow(clippy::needless_lifetimes)]
818impl<'a> std::fmt::Debug for AxisValueFormat2<'a> {
819 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
820 (self as &dyn SomeTable<'a>).fmt(f)
821 }
822}
823
824impl Format<u16> for AxisValueFormat3<'_> {
825 const FORMAT: u16 = 3;
826}
827
828impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
829 fn min_byte_range(&self) -> Range<usize> {
830 0..self.linked_value_byte_range().end
831 }
832 fn min_table_bytes(&self) -> &'a [u8] {
833 let range = self.min_byte_range();
834 self.data.as_bytes().get(range).unwrap_or_default()
835 }
836}
837
838impl ReadArgs for AxisValueFormat3<'_> {
839 type Args = ();
840}
841
842impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
843 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
844 #[allow(clippy::absurd_extreme_comparisons)]
845 if data.len() < Self::MIN_SIZE {
846 return Err(ReadError::OutOfBounds);
847 }
848 Ok(Self { data })
849 }
850}
851
852#[derive(Clone)]
854pub struct AxisValueFormat3<'a> {
855 data: FontData<'a>,
856}
857
858#[allow(clippy::needless_lifetimes)]
859impl<'a> AxisValueFormat3<'a> {
860 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
861 + u16::RAW_BYTE_LEN
862 + AxisValueTableFlags::RAW_BYTE_LEN
863 + NameId::RAW_BYTE_LEN
864 + Fixed::RAW_BYTE_LEN
865 + Fixed::RAW_BYTE_LEN);
866 basic_table_impls!(impl_the_methods);
867
868 pub fn format(&self) -> u16 {
870 let range = self.format_byte_range();
871 self.data.read_at(range.start).ok().unwrap()
872 }
873
874 pub fn axis_index(&self) -> u16 {
878 let range = self.axis_index_byte_range();
879 self.data.read_at(range.start).ok().unwrap()
880 }
881
882 pub fn flags(&self) -> AxisValueTableFlags {
884 let range = self.flags_byte_range();
885 self.data.read_at(range.start).ok().unwrap()
886 }
887
888 pub fn value_name_id(&self) -> NameId {
891 let range = self.value_name_id_byte_range();
892 self.data.read_at(range.start).ok().unwrap()
893 }
894
895 pub fn value(&self) -> Fixed {
897 let range = self.value_byte_range();
898 self.data.read_at(range.start).ok().unwrap()
899 }
900
901 pub fn linked_value(&self) -> Fixed {
903 let range = self.linked_value_byte_range();
904 self.data.read_at(range.start).ok().unwrap()
905 }
906
907 pub fn format_byte_range(&self) -> Range<usize> {
908 let start = 0;
909 let end = start + u16::RAW_BYTE_LEN;
910 start..end
911 }
912
913 pub fn axis_index_byte_range(&self) -> Range<usize> {
914 let start = self.format_byte_range().end;
915 let end = start + u16::RAW_BYTE_LEN;
916 start..end
917 }
918
919 pub fn flags_byte_range(&self) -> Range<usize> {
920 let start = self.axis_index_byte_range().end;
921 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
922 start..end
923 }
924
925 pub fn value_name_id_byte_range(&self) -> Range<usize> {
926 let start = self.flags_byte_range().end;
927 let end = start + NameId::RAW_BYTE_LEN;
928 start..end
929 }
930
931 pub fn value_byte_range(&self) -> Range<usize> {
932 let start = self.value_name_id_byte_range().end;
933 let end = start + Fixed::RAW_BYTE_LEN;
934 start..end
935 }
936
937 pub fn linked_value_byte_range(&self) -> Range<usize> {
938 let start = self.value_byte_range().end;
939 let end = start + Fixed::RAW_BYTE_LEN;
940 start..end
941 }
942}
943
944#[cfg(feature = "experimental_traverse")]
945impl<'a> SomeTable<'a> for AxisValueFormat3<'a> {
946 fn type_name(&self) -> &str {
947 "AxisValueFormat3"
948 }
949 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
950 match idx {
951 0usize => Some(Field::new("format", self.format())),
952 1usize => Some(Field::new("axis_index", self.axis_index())),
953 2usize => Some(Field::new("flags", self.flags())),
954 3usize => Some(Field::new("value_name_id", self.value_name_id())),
955 4usize => Some(Field::new("value", self.value())),
956 5usize => Some(Field::new("linked_value", self.linked_value())),
957 _ => None,
958 }
959 }
960}
961
962#[cfg(feature = "experimental_traverse")]
963#[allow(clippy::needless_lifetimes)]
964impl<'a> std::fmt::Debug for AxisValueFormat3<'a> {
965 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
966 (self as &dyn SomeTable<'a>).fmt(f)
967 }
968}
969
970impl Format<u16> for AxisValueFormat4<'_> {
971 const FORMAT: u16 = 4;
972}
973
974impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
975 fn min_byte_range(&self) -> Range<usize> {
976 0..self.axis_values_byte_range().end
977 }
978 fn min_table_bytes(&self) -> &'a [u8] {
979 let range = self.min_byte_range();
980 self.data.as_bytes().get(range).unwrap_or_default()
981 }
982}
983
984impl ReadArgs for AxisValueFormat4<'_> {
985 type Args = ();
986}
987
988impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
989 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
990 #[allow(clippy::absurd_extreme_comparisons)]
991 if data.len() < Self::MIN_SIZE {
992 return Err(ReadError::OutOfBounds);
993 }
994 Ok(Self { data })
995 }
996}
997
998#[derive(Clone)]
1000pub struct AxisValueFormat4<'a> {
1001 data: FontData<'a>,
1002}
1003
1004#[allow(clippy::needless_lifetimes)]
1005impl<'a> AxisValueFormat4<'a> {
1006 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1007 + u16::RAW_BYTE_LEN
1008 + AxisValueTableFlags::RAW_BYTE_LEN
1009 + NameId::RAW_BYTE_LEN);
1010 basic_table_impls!(impl_the_methods);
1011
1012 pub fn format(&self) -> u16 {
1014 let range = self.format_byte_range();
1015 self.data.read_at(range.start).ok().unwrap()
1016 }
1017
1018 pub fn axis_count(&self) -> u16 {
1021 let range = self.axis_count_byte_range();
1022 self.data.read_at(range.start).ok().unwrap()
1023 }
1024
1025 pub fn flags(&self) -> AxisValueTableFlags {
1027 let range = self.flags_byte_range();
1028 self.data.read_at(range.start).ok().unwrap()
1029 }
1030
1031 pub fn value_name_id(&self) -> NameId {
1034 let range = self.value_name_id_byte_range();
1035 self.data.read_at(range.start).ok().unwrap()
1036 }
1037
1038 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
1041 let range = self.axis_values_byte_range();
1042 self.data.read_array(range).ok().unwrap_or_default()
1043 }
1044
1045 pub fn format_byte_range(&self) -> Range<usize> {
1046 let start = 0;
1047 let end = start + u16::RAW_BYTE_LEN;
1048 start..end
1049 }
1050
1051 pub fn axis_count_byte_range(&self) -> Range<usize> {
1052 let start = self.format_byte_range().end;
1053 let end = start + u16::RAW_BYTE_LEN;
1054 start..end
1055 }
1056
1057 pub fn flags_byte_range(&self) -> Range<usize> {
1058 let start = self.axis_count_byte_range().end;
1059 let end = start + AxisValueTableFlags::RAW_BYTE_LEN;
1060 start..end
1061 }
1062
1063 pub fn value_name_id_byte_range(&self) -> Range<usize> {
1064 let start = self.flags_byte_range().end;
1065 let end = start + NameId::RAW_BYTE_LEN;
1066 start..end
1067 }
1068
1069 pub fn axis_values_byte_range(&self) -> Range<usize> {
1070 let axis_count = self.axis_count();
1071 let start = self.value_name_id_byte_range().end;
1072 let end = start
1073 + (transforms::to_usize(axis_count)).saturating_mul(AxisValueRecord::RAW_BYTE_LEN);
1074 start..end
1075 }
1076}
1077
1078#[cfg(feature = "experimental_traverse")]
1079impl<'a> SomeTable<'a> for AxisValueFormat4<'a> {
1080 fn type_name(&self) -> &str {
1081 "AxisValueFormat4"
1082 }
1083 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1084 match idx {
1085 0usize => Some(Field::new("format", self.format())),
1086 1usize => Some(Field::new("axis_count", self.axis_count())),
1087 2usize => Some(Field::new("flags", self.flags())),
1088 3usize => Some(Field::new("value_name_id", self.value_name_id())),
1089 4usize => Some(Field::new(
1090 "axis_values",
1091 traversal::FieldType::array_of_records(
1092 stringify!(AxisValueRecord),
1093 self.axis_values(),
1094 self.offset_data(),
1095 ),
1096 )),
1097 _ => None,
1098 }
1099 }
1100}
1101
1102#[cfg(feature = "experimental_traverse")]
1103#[allow(clippy::needless_lifetimes)]
1104impl<'a> std::fmt::Debug for AxisValueFormat4<'a> {
1105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1106 (self as &dyn SomeTable<'a>).fmt(f)
1107 }
1108}
1109
1110#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1112#[repr(C)]
1113#[repr(packed)]
1114pub struct AxisValueRecord {
1115 pub axis_index: BigEndian<u16>,
1118 pub value: BigEndian<Fixed>,
1120}
1121
1122impl AxisValueRecord {
1123 pub fn axis_index(&self) -> u16 {
1126 self.axis_index.get()
1127 }
1128
1129 pub fn value(&self) -> Fixed {
1131 self.value.get()
1132 }
1133}
1134
1135impl FixedSize for AxisValueRecord {
1136 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1137}
1138
1139#[cfg(feature = "experimental_traverse")]
1140impl<'a> SomeRecord<'a> for AxisValueRecord {
1141 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1142 RecordResolver {
1143 name: "AxisValueRecord",
1144 get_field: Box::new(move |idx, _data| match idx {
1145 0usize => Some(Field::new("axis_index", self.axis_index())),
1146 1usize => Some(Field::new("value", self.value())),
1147 _ => None,
1148 }),
1149 data,
1150 }
1151 }
1152}
1153
1154#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1156#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1157#[repr(transparent)]
1158pub struct AxisValueTableFlags {
1159 bits: u16,
1160}
1161
1162impl AxisValueTableFlags {
1163 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1170
1171 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1175}
1176
1177impl AxisValueTableFlags {
1178 #[inline]
1180 pub const fn empty() -> Self {
1181 Self { bits: 0 }
1182 }
1183
1184 #[inline]
1186 pub const fn all() -> Self {
1187 Self {
1188 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1189 }
1190 }
1191
1192 #[inline]
1194 pub const fn bits(&self) -> u16 {
1195 self.bits
1196 }
1197
1198 #[inline]
1201 pub const fn from_bits(bits: u16) -> Option<Self> {
1202 if (bits & !Self::all().bits()) == 0 {
1203 Some(Self { bits })
1204 } else {
1205 None
1206 }
1207 }
1208
1209 #[inline]
1212 pub const fn from_bits_truncate(bits: u16) -> Self {
1213 Self {
1214 bits: bits & Self::all().bits,
1215 }
1216 }
1217
1218 #[inline]
1220 pub const fn is_empty(&self) -> bool {
1221 self.bits() == Self::empty().bits()
1222 }
1223
1224 #[inline]
1226 pub const fn intersects(&self, other: Self) -> bool {
1227 !(Self {
1228 bits: self.bits & other.bits,
1229 })
1230 .is_empty()
1231 }
1232
1233 #[inline]
1235 pub const fn contains(&self, other: Self) -> bool {
1236 (self.bits & other.bits) == other.bits
1237 }
1238
1239 #[inline]
1241 pub fn insert(&mut self, other: Self) {
1242 self.bits |= other.bits;
1243 }
1244
1245 #[inline]
1247 pub fn remove(&mut self, other: Self) {
1248 self.bits &= !other.bits;
1249 }
1250
1251 #[inline]
1253 pub fn toggle(&mut self, other: Self) {
1254 self.bits ^= other.bits;
1255 }
1256
1257 #[inline]
1268 #[must_use]
1269 pub const fn intersection(self, other: Self) -> Self {
1270 Self {
1271 bits: self.bits & other.bits,
1272 }
1273 }
1274
1275 #[inline]
1286 #[must_use]
1287 pub const fn union(self, other: Self) -> Self {
1288 Self {
1289 bits: self.bits | other.bits,
1290 }
1291 }
1292
1293 #[inline]
1306 #[must_use]
1307 pub const fn difference(self, other: Self) -> Self {
1308 Self {
1309 bits: self.bits & !other.bits,
1310 }
1311 }
1312}
1313
1314impl std::ops::BitOr for AxisValueTableFlags {
1315 type Output = Self;
1316
1317 #[inline]
1319 fn bitor(self, other: AxisValueTableFlags) -> Self {
1320 Self {
1321 bits: self.bits | other.bits,
1322 }
1323 }
1324}
1325
1326impl std::ops::BitOrAssign for AxisValueTableFlags {
1327 #[inline]
1329 fn bitor_assign(&mut self, other: Self) {
1330 self.bits |= other.bits;
1331 }
1332}
1333
1334impl std::ops::BitXor for AxisValueTableFlags {
1335 type Output = Self;
1336
1337 #[inline]
1339 fn bitxor(self, other: Self) -> Self {
1340 Self {
1341 bits: self.bits ^ other.bits,
1342 }
1343 }
1344}
1345
1346impl std::ops::BitXorAssign for AxisValueTableFlags {
1347 #[inline]
1349 fn bitxor_assign(&mut self, other: Self) {
1350 self.bits ^= other.bits;
1351 }
1352}
1353
1354impl std::ops::BitAnd for AxisValueTableFlags {
1355 type Output = Self;
1356
1357 #[inline]
1359 fn bitand(self, other: Self) -> Self {
1360 Self {
1361 bits: self.bits & other.bits,
1362 }
1363 }
1364}
1365
1366impl std::ops::BitAndAssign for AxisValueTableFlags {
1367 #[inline]
1369 fn bitand_assign(&mut self, other: Self) {
1370 self.bits &= other.bits;
1371 }
1372}
1373
1374impl std::ops::Sub for AxisValueTableFlags {
1375 type Output = Self;
1376
1377 #[inline]
1379 fn sub(self, other: Self) -> Self {
1380 Self {
1381 bits: self.bits & !other.bits,
1382 }
1383 }
1384}
1385
1386impl std::ops::SubAssign for AxisValueTableFlags {
1387 #[inline]
1389 fn sub_assign(&mut self, other: Self) {
1390 self.bits &= !other.bits;
1391 }
1392}
1393
1394impl std::ops::Not for AxisValueTableFlags {
1395 type Output = Self;
1396
1397 #[inline]
1399 fn not(self) -> Self {
1400 Self { bits: !self.bits } & Self::all()
1401 }
1402}
1403
1404impl std::fmt::Debug for AxisValueTableFlags {
1405 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1406 let members: &[(&str, Self)] = &[
1407 (
1408 "OLDER_SIBLING_FONT_ATTRIBUTE",
1409 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1410 ),
1411 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1412 ];
1413 let mut first = true;
1414 for (name, value) in members {
1415 if self.contains(*value) {
1416 if !first {
1417 f.write_str(" | ")?;
1418 }
1419 first = false;
1420 f.write_str(name)?;
1421 }
1422 }
1423 if first {
1424 f.write_str("(empty)")?;
1425 }
1426 Ok(())
1427 }
1428}
1429
1430impl std::fmt::Binary for AxisValueTableFlags {
1431 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1432 std::fmt::Binary::fmt(&self.bits, f)
1433 }
1434}
1435
1436impl std::fmt::Octal for AxisValueTableFlags {
1437 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1438 std::fmt::Octal::fmt(&self.bits, f)
1439 }
1440}
1441
1442impl std::fmt::LowerHex for AxisValueTableFlags {
1443 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1444 std::fmt::LowerHex::fmt(&self.bits, f)
1445 }
1446}
1447
1448impl std::fmt::UpperHex for AxisValueTableFlags {
1449 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1450 std::fmt::UpperHex::fmt(&self.bits, f)
1451 }
1452}
1453
1454impl font_types::Scalar for AxisValueTableFlags {
1455 type Raw = <u16 as font_types::Scalar>::Raw;
1456 fn to_raw(self) -> Self::Raw {
1457 self.bits().to_raw()
1458 }
1459 fn from_raw(raw: Self::Raw) -> Self {
1460 let t = <u16>::from_raw(raw);
1461 Self::from_bits_truncate(t)
1462 }
1463}
1464
1465#[cfg(feature = "experimental_traverse")]
1466impl<'a> From<AxisValueTableFlags> for FieldType<'a> {
1467 fn from(src: AxisValueTableFlags) -> FieldType<'a> {
1468 src.bits().into()
1469 }
1470}