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