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<'a> FontRead<'a> for Stat<'a> {
24 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25 #[allow(clippy::absurd_extreme_comparisons)]
26 if data.len() < Self::MIN_SIZE {
27 return Err(ReadError::OutOfBounds);
28 }
29 Ok(Self { data })
30 }
31}
32
33#[derive(Clone)]
35pub struct Stat<'a> {
36 data: FontData<'a>,
37}
38
39#[allow(clippy::needless_lifetimes)]
40impl<'a> Stat<'a> {
41 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
42 + u16::RAW_BYTE_LEN
43 + u16::RAW_BYTE_LEN
44 + Offset32::RAW_BYTE_LEN
45 + u16::RAW_BYTE_LEN
46 + Offset32::RAW_BYTE_LEN);
47 basic_table_impls!(impl_the_methods);
48
49 pub fn version(&self) -> MajorMinor {
51 let range = self.version_byte_range();
52 self.data.read_at(range.start).ok().unwrap()
53 }
54
55 pub fn design_axis_size(&self) -> u16 {
57 let range = self.design_axis_size_byte_range();
58 self.data.read_at(range.start).ok().unwrap()
59 }
60
61 pub fn design_axis_count(&self) -> u16 {
66 let range = self.design_axis_count_byte_range();
67 self.data.read_at(range.start).ok().unwrap()
68 }
69
70 pub fn design_axes_offset(&self) -> Offset32 {
75 let range = self.design_axes_offset_byte_range();
76 self.data.read_at(range.start).ok().unwrap()
77 }
78
79 pub fn design_axes(&self) -> Result<&'a [AxisRecord], ReadError> {
81 let data = self.data;
82 let args = self.design_axis_count();
83 self.design_axes_offset().resolve_with_args(data, &args)
84 }
85
86 pub fn axis_value_count(&self) -> u16 {
88 let range = self.axis_value_count_byte_range();
89 self.data.read_at(range.start).ok().unwrap()
90 }
91
92 pub fn offset_to_axis_value_offsets(&self) -> Nullable<Offset32> {
97 let range = self.offset_to_axis_value_offsets_byte_range();
98 self.data.read_at(range.start).ok().unwrap()
99 }
100
101 pub fn offset_to_axis_values(&self) -> Option<Result<AxisValueArray<'a>, ReadError>> {
103 let data = self.data;
104 let args = self.axis_value_count();
105 self.offset_to_axis_value_offsets()
106 .resolve_with_args(data, &args)
107 }
108
109 pub fn elided_fallback_name_id(&self) -> Option<NameId> {
113 let range = self.elided_fallback_name_id_byte_range();
114 (!range.is_empty())
115 .then(|| self.data.read_at(range.start).ok())
116 .flatten()
117 }
118
119 pub fn version_byte_range(&self) -> Range<usize> {
120 let start = 0;
121 start..start + MajorMinor::RAW_BYTE_LEN
122 }
123
124 pub fn design_axis_size_byte_range(&self) -> Range<usize> {
125 let start = self.version_byte_range().end;
126 start..start + u16::RAW_BYTE_LEN
127 }
128
129 pub fn design_axis_count_byte_range(&self) -> Range<usize> {
130 let start = self.design_axis_size_byte_range().end;
131 start..start + u16::RAW_BYTE_LEN
132 }
133
134 pub fn design_axes_offset_byte_range(&self) -> Range<usize> {
135 let start = self.design_axis_count_byte_range().end;
136 start..start + Offset32::RAW_BYTE_LEN
137 }
138
139 pub fn axis_value_count_byte_range(&self) -> Range<usize> {
140 let start = self.design_axes_offset_byte_range().end;
141 start..start + u16::RAW_BYTE_LEN
142 }
143
144 pub fn offset_to_axis_value_offsets_byte_range(&self) -> Range<usize> {
145 let start = self.axis_value_count_byte_range().end;
146 start..start + Offset32::RAW_BYTE_LEN
147 }
148
149 pub fn elided_fallback_name_id_byte_range(&self) -> Range<usize> {
150 let start = self.offset_to_axis_value_offsets_byte_range().end;
151 start
152 ..(self.version().compatible((1u16, 1u16)))
153 .then(|| start + NameId::RAW_BYTE_LEN)
154 .unwrap_or(start)
155 }
156}
157
158const _: () = assert!(FontData::default_data_long_enough(Stat::MIN_SIZE));
159
160impl Default for Stat<'_> {
161 fn default() -> Self {
162 Self {
163 data: FontData::default_table_data(),
164 }
165 }
166}
167
168#[cfg(feature = "experimental_traverse")]
169impl<'a> SomeTable<'a> for Stat<'a> {
170 fn type_name(&self) -> &str {
171 "Stat"
172 }
173 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
174 match idx {
175 0usize => Some(Field::new("version", self.version())),
176 1usize => Some(Field::new("design_axis_size", self.design_axis_size())),
177 2usize => Some(Field::new("design_axis_count", self.design_axis_count())),
178 3usize => Some(Field::new(
179 "design_axes_offset",
180 traversal::FieldType::offset_to_array_of_records(
181 self.design_axes_offset(),
182 self.design_axes(),
183 stringify!(AxisRecord),
184 self.offset_data(),
185 ),
186 )),
187 4usize => Some(Field::new("axis_value_count", self.axis_value_count())),
188 5usize => Some(Field::new(
189 "offset_to_axis_value_offsets",
190 FieldType::offset(
191 self.offset_to_axis_value_offsets(),
192 self.offset_to_axis_values(),
193 ),
194 )),
195 6usize if self.version().compatible((1u16, 1u16)) => Some(Field::new(
196 "elided_fallback_name_id",
197 self.elided_fallback_name_id().unwrap(),
198 )),
199 _ => None,
200 }
201 }
202}
203
204#[cfg(feature = "experimental_traverse")]
205#[allow(clippy::needless_lifetimes)]
206impl<'a> std::fmt::Debug for Stat<'a> {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 (self as &dyn SomeTable<'a>).fmt(f)
209 }
210}
211
212#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
214#[repr(C)]
215#[repr(packed)]
216pub struct AxisRecord {
217 pub axis_tag: BigEndian<Tag>,
219 pub axis_name_id: BigEndian<NameId>,
222 pub axis_ordering: BigEndian<u16>,
226}
227
228impl AxisRecord {
229 pub fn axis_tag(&self) -> Tag {
231 self.axis_tag.get()
232 }
233
234 pub fn axis_name_id(&self) -> NameId {
237 self.axis_name_id.get()
238 }
239
240 pub fn axis_ordering(&self) -> u16 {
244 self.axis_ordering.get()
245 }
246}
247
248impl FixedSize for AxisRecord {
249 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
250}
251
252#[cfg(feature = "experimental_traverse")]
253impl<'a> SomeRecord<'a> for AxisRecord {
254 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
255 RecordResolver {
256 name: "AxisRecord",
257 get_field: Box::new(move |idx, _data| match idx {
258 0usize => Some(Field::new("axis_tag", self.axis_tag())),
259 1usize => Some(Field::new("axis_name_id", self.axis_name_id())),
260 2usize => Some(Field::new("axis_ordering", self.axis_ordering())),
261 _ => None,
262 }),
263 data,
264 }
265 }
266}
267
268impl<'a> MinByteRange<'a> for AxisValueArray<'a> {
269 fn min_byte_range(&self) -> Range<usize> {
270 0..self.axis_value_offsets_byte_range().end
271 }
272 fn min_table_bytes(&self) -> &'a [u8] {
273 let range = self.min_byte_range();
274 self.data.as_bytes().get(range).unwrap_or_default()
275 }
276}
277
278impl ReadArgs for AxisValueArray<'_> {
279 type Args = u16;
280}
281
282impl<'a> FontReadWithArgs<'a> for AxisValueArray<'a> {
283 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
284 let axis_value_count = *args;
285
286 #[allow(clippy::absurd_extreme_comparisons)]
287 if data.len() < Self::MIN_SIZE {
288 return Err(ReadError::OutOfBounds);
289 }
290 Ok(Self {
291 data,
292 axis_value_count,
293 })
294 }
295}
296
297impl<'a> AxisValueArray<'a> {
298 pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
303 let args = axis_value_count;
304 Self::read_with_args(data, &args)
305 }
306}
307
308#[derive(Clone)]
310pub struct AxisValueArray<'a> {
311 data: FontData<'a>,
312 axis_value_count: u16,
313}
314
315#[allow(clippy::needless_lifetimes)]
316impl<'a> AxisValueArray<'a> {
317 pub const MIN_SIZE: usize = 0;
318 basic_table_impls!(impl_the_methods);
319
320 pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
323 let range = self.axis_value_offsets_byte_range();
324 self.data.read_array(range).ok().unwrap_or_default()
325 }
326
327 pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
329 let data = self.data;
330 let offsets = self.axis_value_offsets();
331 ArrayOfOffsets::new(offsets, data, ())
332 }
333
334 pub(crate) fn axis_value_count(&self) -> u16 {
335 self.axis_value_count
336 }
337
338 pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
339 let axis_value_count = self.axis_value_count();
340 let start = 0;
341 start
342 ..start
343 + (transforms::to_usize(axis_value_count)).saturating_mul(Offset16::RAW_BYTE_LEN)
344 }
345}
346
347#[allow(clippy::absurd_extreme_comparisons)]
348const _: () = assert!(FontData::default_data_long_enough(AxisValueArray::MIN_SIZE));
349
350impl Default for AxisValueArray<'_> {
351 fn default() -> Self {
352 Self {
353 data: FontData::default_table_data(),
354 axis_value_count: Default::default(),
355 }
356 }
357}
358
359#[cfg(feature = "experimental_traverse")]
360impl<'a> SomeTable<'a> for AxisValueArray<'a> {
361 fn type_name(&self) -> &str {
362 "AxisValueArray"
363 }
364 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
365 match idx {
366 0usize => Some(Field::new(
367 "axis_value_offsets",
368 FieldType::from(self.axis_values()),
369 )),
370 _ => None,
371 }
372 }
373}
374
375#[cfg(feature = "experimental_traverse")]
376#[allow(clippy::needless_lifetimes)]
377impl<'a> std::fmt::Debug for AxisValueArray<'a> {
378 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
379 (self as &dyn SomeTable<'a>).fmt(f)
380 }
381}
382
383#[derive(Clone)]
385pub enum AxisValue<'a> {
386 Format1(AxisValueFormat1<'a>),
387 Format2(AxisValueFormat2<'a>),
388 Format3(AxisValueFormat3<'a>),
389 Format4(AxisValueFormat4<'a>),
390}
391
392impl Default for AxisValue<'_> {
393 fn default() -> Self {
394 Self::Format1(Default::default())
395 }
396}
397
398impl<'a> AxisValue<'a> {
399 pub fn offset_data(&self) -> FontData<'a> {
401 match self {
402 Self::Format1(item) => item.offset_data(),
403 Self::Format2(item) => item.offset_data(),
404 Self::Format3(item) => item.offset_data(),
405 Self::Format4(item) => item.offset_data(),
406 }
407 }
408
409 pub fn format(&self) -> u16 {
411 match self {
412 Self::Format1(item) => item.format(),
413 Self::Format2(item) => item.format(),
414 Self::Format3(item) => item.format(),
415 Self::Format4(item) => item.format(),
416 }
417 }
418
419 pub fn flags(&self) -> AxisValueTableFlags {
421 match self {
422 Self::Format1(item) => item.flags(),
423 Self::Format2(item) => item.flags(),
424 Self::Format3(item) => item.flags(),
425 Self::Format4(item) => item.flags(),
426 }
427 }
428
429 pub fn value_name_id(&self) -> NameId {
432 match self {
433 Self::Format1(item) => item.value_name_id(),
434 Self::Format2(item) => item.value_name_id(),
435 Self::Format3(item) => item.value_name_id(),
436 Self::Format4(item) => item.value_name_id(),
437 }
438 }
439}
440
441impl<'a> FontRead<'a> for AxisValue<'a> {
442 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
443 let format: u16 = data.read_at(0usize)?;
444 match format {
445 AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
446 AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
447 AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
448 AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
449 other => Err(ReadError::InvalidFormat(other.into())),
450 }
451 }
452}
453
454impl<'a> MinByteRange<'a> for AxisValue<'a> {
455 fn min_byte_range(&self) -> Range<usize> {
456 match self {
457 Self::Format1(item) => item.min_byte_range(),
458 Self::Format2(item) => item.min_byte_range(),
459 Self::Format3(item) => item.min_byte_range(),
460 Self::Format4(item) => item.min_byte_range(),
461 }
462 }
463 fn min_table_bytes(&self) -> &'a [u8] {
464 match self {
465 Self::Format1(item) => item.min_table_bytes(),
466 Self::Format2(item) => item.min_table_bytes(),
467 Self::Format3(item) => item.min_table_bytes(),
468 Self::Format4(item) => item.min_table_bytes(),
469 }
470 }
471}
472
473#[cfg(feature = "experimental_traverse")]
474impl<'a> AxisValue<'a> {
475 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
476 match self {
477 Self::Format1(table) => table,
478 Self::Format2(table) => table,
479 Self::Format3(table) => table,
480 Self::Format4(table) => table,
481 }
482 }
483}
484
485#[cfg(feature = "experimental_traverse")]
486impl std::fmt::Debug for AxisValue<'_> {
487 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
488 self.dyn_inner().fmt(f)
489 }
490}
491
492#[cfg(feature = "experimental_traverse")]
493impl<'a> SomeTable<'a> for AxisValue<'a> {
494 fn type_name(&self) -> &str {
495 self.dyn_inner().type_name()
496 }
497 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
498 self.dyn_inner().get_field(idx)
499 }
500}
501
502impl Format<u16> for AxisValueFormat1<'_> {
503 const FORMAT: u16 = 1;
504}
505
506impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
507 fn min_byte_range(&self) -> Range<usize> {
508 0..self.value_byte_range().end
509 }
510 fn min_table_bytes(&self) -> &'a [u8] {
511 let range = self.min_byte_range();
512 self.data.as_bytes().get(range).unwrap_or_default()
513 }
514}
515
516impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
517 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
518 #[allow(clippy::absurd_extreme_comparisons)]
519 if data.len() < Self::MIN_SIZE {
520 return Err(ReadError::OutOfBounds);
521 }
522 Ok(Self { data })
523 }
524}
525
526#[derive(Clone)]
528pub struct AxisValueFormat1<'a> {
529 data: FontData<'a>,
530}
531
532#[allow(clippy::needless_lifetimes)]
533impl<'a> AxisValueFormat1<'a> {
534 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
535 + u16::RAW_BYTE_LEN
536 + AxisValueTableFlags::RAW_BYTE_LEN
537 + NameId::RAW_BYTE_LEN
538 + Fixed::RAW_BYTE_LEN);
539 basic_table_impls!(impl_the_methods);
540
541 pub fn format(&self) -> u16 {
543 let range = self.format_byte_range();
544 self.data.read_at(range.start).ok().unwrap()
545 }
546
547 pub fn axis_index(&self) -> u16 {
551 let range = self.axis_index_byte_range();
552 self.data.read_at(range.start).ok().unwrap()
553 }
554
555 pub fn flags(&self) -> AxisValueTableFlags {
557 let range = self.flags_byte_range();
558 self.data.read_at(range.start).ok().unwrap()
559 }
560
561 pub fn value_name_id(&self) -> NameId {
564 let range = self.value_name_id_byte_range();
565 self.data.read_at(range.start).ok().unwrap()
566 }
567
568 pub fn value(&self) -> Fixed {
570 let range = self.value_byte_range();
571 self.data.read_at(range.start).ok().unwrap()
572 }
573
574 pub fn format_byte_range(&self) -> Range<usize> {
575 let start = 0;
576 start..start + u16::RAW_BYTE_LEN
577 }
578
579 pub fn axis_index_byte_range(&self) -> Range<usize> {
580 let start = self.format_byte_range().end;
581 start..start + u16::RAW_BYTE_LEN
582 }
583
584 pub fn flags_byte_range(&self) -> Range<usize> {
585 let start = self.axis_index_byte_range().end;
586 start..start + AxisValueTableFlags::RAW_BYTE_LEN
587 }
588
589 pub fn value_name_id_byte_range(&self) -> Range<usize> {
590 let start = self.flags_byte_range().end;
591 start..start + NameId::RAW_BYTE_LEN
592 }
593
594 pub fn value_byte_range(&self) -> Range<usize> {
595 let start = self.value_name_id_byte_range().end;
596 start..start + Fixed::RAW_BYTE_LEN
597 }
598}
599
600const _: () = assert!(FontData::default_data_long_enough(
601 AxisValueFormat1::MIN_SIZE
602));
603
604impl Default for AxisValueFormat1<'_> {
605 fn default() -> Self {
606 Self {
607 data: FontData::default_format_1_u16_table_data(),
608 }
609 }
610}
611
612#[cfg(feature = "experimental_traverse")]
613impl<'a> SomeTable<'a> for AxisValueFormat1<'a> {
614 fn type_name(&self) -> &str {
615 "AxisValueFormat1"
616 }
617 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
618 match idx {
619 0usize => Some(Field::new("format", self.format())),
620 1usize => Some(Field::new("axis_index", self.axis_index())),
621 2usize => Some(Field::new("flags", self.flags())),
622 3usize => Some(Field::new("value_name_id", self.value_name_id())),
623 4usize => Some(Field::new("value", self.value())),
624 _ => None,
625 }
626 }
627}
628
629#[cfg(feature = "experimental_traverse")]
630#[allow(clippy::needless_lifetimes)]
631impl<'a> std::fmt::Debug for AxisValueFormat1<'a> {
632 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
633 (self as &dyn SomeTable<'a>).fmt(f)
634 }
635}
636
637impl Format<u16> for AxisValueFormat2<'_> {
638 const FORMAT: u16 = 2;
639}
640
641impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
642 fn min_byte_range(&self) -> Range<usize> {
643 0..self.range_max_value_byte_range().end
644 }
645 fn min_table_bytes(&self) -> &'a [u8] {
646 let range = self.min_byte_range();
647 self.data.as_bytes().get(range).unwrap_or_default()
648 }
649}
650
651impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
652 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
653 #[allow(clippy::absurd_extreme_comparisons)]
654 if data.len() < Self::MIN_SIZE {
655 return Err(ReadError::OutOfBounds);
656 }
657 Ok(Self { data })
658 }
659}
660
661#[derive(Clone)]
663pub struct AxisValueFormat2<'a> {
664 data: FontData<'a>,
665}
666
667#[allow(clippy::needless_lifetimes)]
668impl<'a> AxisValueFormat2<'a> {
669 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
670 + u16::RAW_BYTE_LEN
671 + AxisValueTableFlags::RAW_BYTE_LEN
672 + NameId::RAW_BYTE_LEN
673 + Fixed::RAW_BYTE_LEN
674 + Fixed::RAW_BYTE_LEN
675 + Fixed::RAW_BYTE_LEN);
676 basic_table_impls!(impl_the_methods);
677
678 pub fn format(&self) -> u16 {
680 let range = self.format_byte_range();
681 self.data.read_at(range.start).ok().unwrap()
682 }
683
684 pub fn axis_index(&self) -> u16 {
688 let range = self.axis_index_byte_range();
689 self.data.read_at(range.start).ok().unwrap()
690 }
691
692 pub fn flags(&self) -> AxisValueTableFlags {
694 let range = self.flags_byte_range();
695 self.data.read_at(range.start).ok().unwrap()
696 }
697
698 pub fn value_name_id(&self) -> NameId {
701 let range = self.value_name_id_byte_range();
702 self.data.read_at(range.start).ok().unwrap()
703 }
704
705 pub fn nominal_value(&self) -> Fixed {
707 let range = self.nominal_value_byte_range();
708 self.data.read_at(range.start).ok().unwrap()
709 }
710
711 pub fn range_min_value(&self) -> Fixed {
714 let range = self.range_min_value_byte_range();
715 self.data.read_at(range.start).ok().unwrap()
716 }
717
718 pub fn range_max_value(&self) -> Fixed {
721 let range = self.range_max_value_byte_range();
722 self.data.read_at(range.start).ok().unwrap()
723 }
724
725 pub fn format_byte_range(&self) -> Range<usize> {
726 let start = 0;
727 start..start + u16::RAW_BYTE_LEN
728 }
729
730 pub fn axis_index_byte_range(&self) -> Range<usize> {
731 let start = self.format_byte_range().end;
732 start..start + u16::RAW_BYTE_LEN
733 }
734
735 pub fn flags_byte_range(&self) -> Range<usize> {
736 let start = self.axis_index_byte_range().end;
737 start..start + AxisValueTableFlags::RAW_BYTE_LEN
738 }
739
740 pub fn value_name_id_byte_range(&self) -> Range<usize> {
741 let start = self.flags_byte_range().end;
742 start..start + NameId::RAW_BYTE_LEN
743 }
744
745 pub fn nominal_value_byte_range(&self) -> Range<usize> {
746 let start = self.value_name_id_byte_range().end;
747 start..start + Fixed::RAW_BYTE_LEN
748 }
749
750 pub fn range_min_value_byte_range(&self) -> Range<usize> {
751 let start = self.nominal_value_byte_range().end;
752 start..start + Fixed::RAW_BYTE_LEN
753 }
754
755 pub fn range_max_value_byte_range(&self) -> Range<usize> {
756 let start = self.range_min_value_byte_range().end;
757 start..start + Fixed::RAW_BYTE_LEN
758 }
759}
760
761#[cfg(feature = "experimental_traverse")]
762impl<'a> SomeTable<'a> for AxisValueFormat2<'a> {
763 fn type_name(&self) -> &str {
764 "AxisValueFormat2"
765 }
766 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
767 match idx {
768 0usize => Some(Field::new("format", self.format())),
769 1usize => Some(Field::new("axis_index", self.axis_index())),
770 2usize => Some(Field::new("flags", self.flags())),
771 3usize => Some(Field::new("value_name_id", self.value_name_id())),
772 4usize => Some(Field::new("nominal_value", self.nominal_value())),
773 5usize => Some(Field::new("range_min_value", self.range_min_value())),
774 6usize => Some(Field::new("range_max_value", self.range_max_value())),
775 _ => None,
776 }
777 }
778}
779
780#[cfg(feature = "experimental_traverse")]
781#[allow(clippy::needless_lifetimes)]
782impl<'a> std::fmt::Debug for AxisValueFormat2<'a> {
783 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
784 (self as &dyn SomeTable<'a>).fmt(f)
785 }
786}
787
788impl Format<u16> for AxisValueFormat3<'_> {
789 const FORMAT: u16 = 3;
790}
791
792impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
793 fn min_byte_range(&self) -> Range<usize> {
794 0..self.linked_value_byte_range().end
795 }
796 fn min_table_bytes(&self) -> &'a [u8] {
797 let range = self.min_byte_range();
798 self.data.as_bytes().get(range).unwrap_or_default()
799 }
800}
801
802impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
803 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
804 #[allow(clippy::absurd_extreme_comparisons)]
805 if data.len() < Self::MIN_SIZE {
806 return Err(ReadError::OutOfBounds);
807 }
808 Ok(Self { data })
809 }
810}
811
812#[derive(Clone)]
814pub struct AxisValueFormat3<'a> {
815 data: FontData<'a>,
816}
817
818#[allow(clippy::needless_lifetimes)]
819impl<'a> AxisValueFormat3<'a> {
820 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
821 + u16::RAW_BYTE_LEN
822 + AxisValueTableFlags::RAW_BYTE_LEN
823 + NameId::RAW_BYTE_LEN
824 + Fixed::RAW_BYTE_LEN
825 + Fixed::RAW_BYTE_LEN);
826 basic_table_impls!(impl_the_methods);
827
828 pub fn format(&self) -> u16 {
830 let range = self.format_byte_range();
831 self.data.read_at(range.start).ok().unwrap()
832 }
833
834 pub fn axis_index(&self) -> u16 {
838 let range = self.axis_index_byte_range();
839 self.data.read_at(range.start).ok().unwrap()
840 }
841
842 pub fn flags(&self) -> AxisValueTableFlags {
844 let range = self.flags_byte_range();
845 self.data.read_at(range.start).ok().unwrap()
846 }
847
848 pub fn value_name_id(&self) -> NameId {
851 let range = self.value_name_id_byte_range();
852 self.data.read_at(range.start).ok().unwrap()
853 }
854
855 pub fn value(&self) -> Fixed {
857 let range = self.value_byte_range();
858 self.data.read_at(range.start).ok().unwrap()
859 }
860
861 pub fn linked_value(&self) -> Fixed {
863 let range = self.linked_value_byte_range();
864 self.data.read_at(range.start).ok().unwrap()
865 }
866
867 pub fn format_byte_range(&self) -> Range<usize> {
868 let start = 0;
869 start..start + u16::RAW_BYTE_LEN
870 }
871
872 pub fn axis_index_byte_range(&self) -> Range<usize> {
873 let start = self.format_byte_range().end;
874 start..start + u16::RAW_BYTE_LEN
875 }
876
877 pub fn flags_byte_range(&self) -> Range<usize> {
878 let start = self.axis_index_byte_range().end;
879 start..start + AxisValueTableFlags::RAW_BYTE_LEN
880 }
881
882 pub fn value_name_id_byte_range(&self) -> Range<usize> {
883 let start = self.flags_byte_range().end;
884 start..start + NameId::RAW_BYTE_LEN
885 }
886
887 pub fn value_byte_range(&self) -> Range<usize> {
888 let start = self.value_name_id_byte_range().end;
889 start..start + Fixed::RAW_BYTE_LEN
890 }
891
892 pub fn linked_value_byte_range(&self) -> Range<usize> {
893 let start = self.value_byte_range().end;
894 start..start + Fixed::RAW_BYTE_LEN
895 }
896}
897
898#[cfg(feature = "experimental_traverse")]
899impl<'a> SomeTable<'a> for AxisValueFormat3<'a> {
900 fn type_name(&self) -> &str {
901 "AxisValueFormat3"
902 }
903 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
904 match idx {
905 0usize => Some(Field::new("format", self.format())),
906 1usize => Some(Field::new("axis_index", self.axis_index())),
907 2usize => Some(Field::new("flags", self.flags())),
908 3usize => Some(Field::new("value_name_id", self.value_name_id())),
909 4usize => Some(Field::new("value", self.value())),
910 5usize => Some(Field::new("linked_value", self.linked_value())),
911 _ => None,
912 }
913 }
914}
915
916#[cfg(feature = "experimental_traverse")]
917#[allow(clippy::needless_lifetimes)]
918impl<'a> std::fmt::Debug for AxisValueFormat3<'a> {
919 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
920 (self as &dyn SomeTable<'a>).fmt(f)
921 }
922}
923
924impl Format<u16> for AxisValueFormat4<'_> {
925 const FORMAT: u16 = 4;
926}
927
928impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
929 fn min_byte_range(&self) -> Range<usize> {
930 0..self.axis_values_byte_range().end
931 }
932 fn min_table_bytes(&self) -> &'a [u8] {
933 let range = self.min_byte_range();
934 self.data.as_bytes().get(range).unwrap_or_default()
935 }
936}
937
938impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
939 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
940 #[allow(clippy::absurd_extreme_comparisons)]
941 if data.len() < Self::MIN_SIZE {
942 return Err(ReadError::OutOfBounds);
943 }
944 Ok(Self { data })
945 }
946}
947
948#[derive(Clone)]
950pub struct AxisValueFormat4<'a> {
951 data: FontData<'a>,
952}
953
954#[allow(clippy::needless_lifetimes)]
955impl<'a> AxisValueFormat4<'a> {
956 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
957 + u16::RAW_BYTE_LEN
958 + AxisValueTableFlags::RAW_BYTE_LEN
959 + NameId::RAW_BYTE_LEN);
960 basic_table_impls!(impl_the_methods);
961
962 pub fn format(&self) -> u16 {
964 let range = self.format_byte_range();
965 self.data.read_at(range.start).ok().unwrap()
966 }
967
968 pub fn axis_count(&self) -> u16 {
971 let range = self.axis_count_byte_range();
972 self.data.read_at(range.start).ok().unwrap()
973 }
974
975 pub fn flags(&self) -> AxisValueTableFlags {
977 let range = self.flags_byte_range();
978 self.data.read_at(range.start).ok().unwrap()
979 }
980
981 pub fn value_name_id(&self) -> NameId {
984 let range = self.value_name_id_byte_range();
985 self.data.read_at(range.start).ok().unwrap()
986 }
987
988 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
991 let range = self.axis_values_byte_range();
992 self.data.read_array(range).ok().unwrap_or_default()
993 }
994
995 pub fn format_byte_range(&self) -> Range<usize> {
996 let start = 0;
997 start..start + u16::RAW_BYTE_LEN
998 }
999
1000 pub fn axis_count_byte_range(&self) -> Range<usize> {
1001 let start = self.format_byte_range().end;
1002 start..start + u16::RAW_BYTE_LEN
1003 }
1004
1005 pub fn flags_byte_range(&self) -> Range<usize> {
1006 let start = self.axis_count_byte_range().end;
1007 start..start + AxisValueTableFlags::RAW_BYTE_LEN
1008 }
1009
1010 pub fn value_name_id_byte_range(&self) -> Range<usize> {
1011 let start = self.flags_byte_range().end;
1012 start..start + NameId::RAW_BYTE_LEN
1013 }
1014
1015 pub fn axis_values_byte_range(&self) -> Range<usize> {
1016 let axis_count = self.axis_count();
1017 let start = self.value_name_id_byte_range().end;
1018 start
1019 ..start
1020 + (transforms::to_usize(axis_count)).saturating_mul(AxisValueRecord::RAW_BYTE_LEN)
1021 }
1022}
1023
1024#[cfg(feature = "experimental_traverse")]
1025impl<'a> SomeTable<'a> for AxisValueFormat4<'a> {
1026 fn type_name(&self) -> &str {
1027 "AxisValueFormat4"
1028 }
1029 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1030 match idx {
1031 0usize => Some(Field::new("format", self.format())),
1032 1usize => Some(Field::new("axis_count", self.axis_count())),
1033 2usize => Some(Field::new("flags", self.flags())),
1034 3usize => Some(Field::new("value_name_id", self.value_name_id())),
1035 4usize => Some(Field::new(
1036 "axis_values",
1037 traversal::FieldType::array_of_records(
1038 stringify!(AxisValueRecord),
1039 self.axis_values(),
1040 self.offset_data(),
1041 ),
1042 )),
1043 _ => None,
1044 }
1045 }
1046}
1047
1048#[cfg(feature = "experimental_traverse")]
1049#[allow(clippy::needless_lifetimes)]
1050impl<'a> std::fmt::Debug for AxisValueFormat4<'a> {
1051 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1052 (self as &dyn SomeTable<'a>).fmt(f)
1053 }
1054}
1055
1056#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1058#[repr(C)]
1059#[repr(packed)]
1060pub struct AxisValueRecord {
1061 pub axis_index: BigEndian<u16>,
1064 pub value: BigEndian<Fixed>,
1066}
1067
1068impl AxisValueRecord {
1069 pub fn axis_index(&self) -> u16 {
1072 self.axis_index.get()
1073 }
1074
1075 pub fn value(&self) -> Fixed {
1077 self.value.get()
1078 }
1079}
1080
1081impl FixedSize for AxisValueRecord {
1082 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1083}
1084
1085#[cfg(feature = "experimental_traverse")]
1086impl<'a> SomeRecord<'a> for AxisValueRecord {
1087 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1088 RecordResolver {
1089 name: "AxisValueRecord",
1090 get_field: Box::new(move |idx, _data| match idx {
1091 0usize => Some(Field::new("axis_index", self.axis_index())),
1092 1usize => Some(Field::new("value", self.value())),
1093 _ => None,
1094 }),
1095 data,
1096 }
1097 }
1098}
1099
1100#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1102#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1103#[repr(transparent)]
1104pub struct AxisValueTableFlags {
1105 bits: u16,
1106}
1107
1108impl AxisValueTableFlags {
1109 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1116
1117 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1121}
1122
1123impl AxisValueTableFlags {
1124 #[inline]
1126 pub const fn empty() -> Self {
1127 Self { bits: 0 }
1128 }
1129
1130 #[inline]
1132 pub const fn all() -> Self {
1133 Self {
1134 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1135 }
1136 }
1137
1138 #[inline]
1140 pub const fn bits(&self) -> u16 {
1141 self.bits
1142 }
1143
1144 #[inline]
1147 pub const fn from_bits(bits: u16) -> Option<Self> {
1148 if (bits & !Self::all().bits()) == 0 {
1149 Some(Self { bits })
1150 } else {
1151 None
1152 }
1153 }
1154
1155 #[inline]
1158 pub const fn from_bits_truncate(bits: u16) -> Self {
1159 Self {
1160 bits: bits & Self::all().bits,
1161 }
1162 }
1163
1164 #[inline]
1166 pub const fn is_empty(&self) -> bool {
1167 self.bits() == Self::empty().bits()
1168 }
1169
1170 #[inline]
1172 pub const fn intersects(&self, other: Self) -> bool {
1173 !(Self {
1174 bits: self.bits & other.bits,
1175 })
1176 .is_empty()
1177 }
1178
1179 #[inline]
1181 pub const fn contains(&self, other: Self) -> bool {
1182 (self.bits & other.bits) == other.bits
1183 }
1184
1185 #[inline]
1187 pub fn insert(&mut self, other: Self) {
1188 self.bits |= other.bits;
1189 }
1190
1191 #[inline]
1193 pub fn remove(&mut self, other: Self) {
1194 self.bits &= !other.bits;
1195 }
1196
1197 #[inline]
1199 pub fn toggle(&mut self, other: Self) {
1200 self.bits ^= other.bits;
1201 }
1202
1203 #[inline]
1214 #[must_use]
1215 pub const fn intersection(self, other: Self) -> Self {
1216 Self {
1217 bits: self.bits & other.bits,
1218 }
1219 }
1220
1221 #[inline]
1232 #[must_use]
1233 pub const fn union(self, other: Self) -> Self {
1234 Self {
1235 bits: self.bits | other.bits,
1236 }
1237 }
1238
1239 #[inline]
1252 #[must_use]
1253 pub const fn difference(self, other: Self) -> Self {
1254 Self {
1255 bits: self.bits & !other.bits,
1256 }
1257 }
1258}
1259
1260impl std::ops::BitOr for AxisValueTableFlags {
1261 type Output = Self;
1262
1263 #[inline]
1265 fn bitor(self, other: AxisValueTableFlags) -> Self {
1266 Self {
1267 bits: self.bits | other.bits,
1268 }
1269 }
1270}
1271
1272impl std::ops::BitOrAssign for AxisValueTableFlags {
1273 #[inline]
1275 fn bitor_assign(&mut self, other: Self) {
1276 self.bits |= other.bits;
1277 }
1278}
1279
1280impl std::ops::BitXor for AxisValueTableFlags {
1281 type Output = Self;
1282
1283 #[inline]
1285 fn bitxor(self, other: Self) -> Self {
1286 Self {
1287 bits: self.bits ^ other.bits,
1288 }
1289 }
1290}
1291
1292impl std::ops::BitXorAssign for AxisValueTableFlags {
1293 #[inline]
1295 fn bitxor_assign(&mut self, other: Self) {
1296 self.bits ^= other.bits;
1297 }
1298}
1299
1300impl std::ops::BitAnd for AxisValueTableFlags {
1301 type Output = Self;
1302
1303 #[inline]
1305 fn bitand(self, other: Self) -> Self {
1306 Self {
1307 bits: self.bits & other.bits,
1308 }
1309 }
1310}
1311
1312impl std::ops::BitAndAssign for AxisValueTableFlags {
1313 #[inline]
1315 fn bitand_assign(&mut self, other: Self) {
1316 self.bits &= other.bits;
1317 }
1318}
1319
1320impl std::ops::Sub for AxisValueTableFlags {
1321 type Output = Self;
1322
1323 #[inline]
1325 fn sub(self, other: Self) -> Self {
1326 Self {
1327 bits: self.bits & !other.bits,
1328 }
1329 }
1330}
1331
1332impl std::ops::SubAssign for AxisValueTableFlags {
1333 #[inline]
1335 fn sub_assign(&mut self, other: Self) {
1336 self.bits &= !other.bits;
1337 }
1338}
1339
1340impl std::ops::Not for AxisValueTableFlags {
1341 type Output = Self;
1342
1343 #[inline]
1345 fn not(self) -> Self {
1346 Self { bits: !self.bits } & Self::all()
1347 }
1348}
1349
1350impl std::fmt::Debug for AxisValueTableFlags {
1351 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1352 let members: &[(&str, Self)] = &[
1353 (
1354 "OLDER_SIBLING_FONT_ATTRIBUTE",
1355 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1356 ),
1357 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1358 ];
1359 let mut first = true;
1360 for (name, value) in members {
1361 if self.contains(*value) {
1362 if !first {
1363 f.write_str(" | ")?;
1364 }
1365 first = false;
1366 f.write_str(name)?;
1367 }
1368 }
1369 if first {
1370 f.write_str("(empty)")?;
1371 }
1372 Ok(())
1373 }
1374}
1375
1376impl std::fmt::Binary for AxisValueTableFlags {
1377 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1378 std::fmt::Binary::fmt(&self.bits, f)
1379 }
1380}
1381
1382impl std::fmt::Octal for AxisValueTableFlags {
1383 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1384 std::fmt::Octal::fmt(&self.bits, f)
1385 }
1386}
1387
1388impl std::fmt::LowerHex for AxisValueTableFlags {
1389 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1390 std::fmt::LowerHex::fmt(&self.bits, f)
1391 }
1392}
1393
1394impl std::fmt::UpperHex for AxisValueTableFlags {
1395 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1396 std::fmt::UpperHex::fmt(&self.bits, f)
1397 }
1398}
1399
1400impl font_types::Scalar for AxisValueTableFlags {
1401 type Raw = <u16 as font_types::Scalar>::Raw;
1402 fn to_raw(self) -> Self::Raw {
1403 self.bits().to_raw()
1404 }
1405 fn from_raw(raw: Self::Raw) -> Self {
1406 let t = <u16>::from_raw(raw);
1407 Self::from_bits_truncate(t)
1408 }
1409}
1410
1411#[cfg(feature = "experimental_traverse")]
1412impl<'a> From<AxisValueTableFlags> for FieldType<'a> {
1413 fn from(src: AxisValueTableFlags) -> FieldType<'a> {
1414 src.bits().into()
1415 }
1416}