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..start + (axis_value_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
342 }
343}
344
345#[allow(clippy::absurd_extreme_comparisons)]
346const _: () = assert!(FontData::default_data_long_enough(AxisValueArray::MIN_SIZE));
347
348impl Default for AxisValueArray<'_> {
349 fn default() -> Self {
350 Self {
351 data: FontData::default_table_data(),
352 axis_value_count: Default::default(),
353 }
354 }
355}
356
357#[cfg(feature = "experimental_traverse")]
358impl<'a> SomeTable<'a> for AxisValueArray<'a> {
359 fn type_name(&self) -> &str {
360 "AxisValueArray"
361 }
362 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
363 match idx {
364 0usize => Some(Field::new(
365 "axis_value_offsets",
366 FieldType::from(self.axis_values()),
367 )),
368 _ => None,
369 }
370 }
371}
372
373#[cfg(feature = "experimental_traverse")]
374#[allow(clippy::needless_lifetimes)]
375impl<'a> std::fmt::Debug for AxisValueArray<'a> {
376 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
377 (self as &dyn SomeTable<'a>).fmt(f)
378 }
379}
380
381#[derive(Clone)]
383pub enum AxisValue<'a> {
384 Format1(AxisValueFormat1<'a>),
385 Format2(AxisValueFormat2<'a>),
386 Format3(AxisValueFormat3<'a>),
387 Format4(AxisValueFormat4<'a>),
388}
389
390impl Default for AxisValue<'_> {
391 fn default() -> Self {
392 Self::Format1(Default::default())
393 }
394}
395
396impl<'a> AxisValue<'a> {
397 pub fn offset_data(&self) -> FontData<'a> {
399 match self {
400 Self::Format1(item) => item.offset_data(),
401 Self::Format2(item) => item.offset_data(),
402 Self::Format3(item) => item.offset_data(),
403 Self::Format4(item) => item.offset_data(),
404 }
405 }
406
407 pub fn format(&self) -> u16 {
409 match self {
410 Self::Format1(item) => item.format(),
411 Self::Format2(item) => item.format(),
412 Self::Format3(item) => item.format(),
413 Self::Format4(item) => item.format(),
414 }
415 }
416
417 pub fn flags(&self) -> AxisValueTableFlags {
419 match self {
420 Self::Format1(item) => item.flags(),
421 Self::Format2(item) => item.flags(),
422 Self::Format3(item) => item.flags(),
423 Self::Format4(item) => item.flags(),
424 }
425 }
426
427 pub fn value_name_id(&self) -> NameId {
430 match self {
431 Self::Format1(item) => item.value_name_id(),
432 Self::Format2(item) => item.value_name_id(),
433 Self::Format3(item) => item.value_name_id(),
434 Self::Format4(item) => item.value_name_id(),
435 }
436 }
437}
438
439impl<'a> FontRead<'a> for AxisValue<'a> {
440 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
441 let format: u16 = data.read_at(0usize)?;
442 match format {
443 AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
444 AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
445 AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
446 AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
447 other => Err(ReadError::InvalidFormat(other.into())),
448 }
449 }
450}
451
452impl<'a> MinByteRange<'a> for AxisValue<'a> {
453 fn min_byte_range(&self) -> Range<usize> {
454 match self {
455 Self::Format1(item) => item.min_byte_range(),
456 Self::Format2(item) => item.min_byte_range(),
457 Self::Format3(item) => item.min_byte_range(),
458 Self::Format4(item) => item.min_byte_range(),
459 }
460 }
461 fn min_table_bytes(&self) -> &'a [u8] {
462 match self {
463 Self::Format1(item) => item.min_table_bytes(),
464 Self::Format2(item) => item.min_table_bytes(),
465 Self::Format3(item) => item.min_table_bytes(),
466 Self::Format4(item) => item.min_table_bytes(),
467 }
468 }
469}
470
471#[cfg(feature = "experimental_traverse")]
472impl<'a> AxisValue<'a> {
473 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
474 match self {
475 Self::Format1(table) => table,
476 Self::Format2(table) => table,
477 Self::Format3(table) => table,
478 Self::Format4(table) => table,
479 }
480 }
481}
482
483#[cfg(feature = "experimental_traverse")]
484impl std::fmt::Debug for AxisValue<'_> {
485 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
486 self.dyn_inner().fmt(f)
487 }
488}
489
490#[cfg(feature = "experimental_traverse")]
491impl<'a> SomeTable<'a> for AxisValue<'a> {
492 fn type_name(&self) -> &str {
493 self.dyn_inner().type_name()
494 }
495 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
496 self.dyn_inner().get_field(idx)
497 }
498}
499
500impl Format<u16> for AxisValueFormat1<'_> {
501 const FORMAT: u16 = 1;
502}
503
504impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
505 fn min_byte_range(&self) -> Range<usize> {
506 0..self.value_byte_range().end
507 }
508 fn min_table_bytes(&self) -> &'a [u8] {
509 let range = self.min_byte_range();
510 self.data.as_bytes().get(range).unwrap_or_default()
511 }
512}
513
514impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
515 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
516 #[allow(clippy::absurd_extreme_comparisons)]
517 if data.len() < Self::MIN_SIZE {
518 return Err(ReadError::OutOfBounds);
519 }
520 Ok(Self { data })
521 }
522}
523
524#[derive(Clone)]
526pub struct AxisValueFormat1<'a> {
527 data: FontData<'a>,
528}
529
530#[allow(clippy::needless_lifetimes)]
531impl<'a> AxisValueFormat1<'a> {
532 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
533 + u16::RAW_BYTE_LEN
534 + AxisValueTableFlags::RAW_BYTE_LEN
535 + NameId::RAW_BYTE_LEN
536 + Fixed::RAW_BYTE_LEN);
537 basic_table_impls!(impl_the_methods);
538
539 pub fn format(&self) -> u16 {
541 let range = self.format_byte_range();
542 self.data.read_at(range.start).ok().unwrap()
543 }
544
545 pub fn axis_index(&self) -> u16 {
549 let range = self.axis_index_byte_range();
550 self.data.read_at(range.start).ok().unwrap()
551 }
552
553 pub fn flags(&self) -> AxisValueTableFlags {
555 let range = self.flags_byte_range();
556 self.data.read_at(range.start).ok().unwrap()
557 }
558
559 pub fn value_name_id(&self) -> NameId {
562 let range = self.value_name_id_byte_range();
563 self.data.read_at(range.start).ok().unwrap()
564 }
565
566 pub fn value(&self) -> Fixed {
568 let range = self.value_byte_range();
569 self.data.read_at(range.start).ok().unwrap()
570 }
571
572 pub fn format_byte_range(&self) -> Range<usize> {
573 let start = 0;
574 start..start + u16::RAW_BYTE_LEN
575 }
576
577 pub fn axis_index_byte_range(&self) -> Range<usize> {
578 let start = self.format_byte_range().end;
579 start..start + u16::RAW_BYTE_LEN
580 }
581
582 pub fn flags_byte_range(&self) -> Range<usize> {
583 let start = self.axis_index_byte_range().end;
584 start..start + AxisValueTableFlags::RAW_BYTE_LEN
585 }
586
587 pub fn value_name_id_byte_range(&self) -> Range<usize> {
588 let start = self.flags_byte_range().end;
589 start..start + NameId::RAW_BYTE_LEN
590 }
591
592 pub fn value_byte_range(&self) -> Range<usize> {
593 let start = self.value_name_id_byte_range().end;
594 start..start + Fixed::RAW_BYTE_LEN
595 }
596}
597
598const _: () = assert!(FontData::default_data_long_enough(
599 AxisValueFormat1::MIN_SIZE
600));
601
602impl Default for AxisValueFormat1<'_> {
603 fn default() -> Self {
604 Self {
605 data: FontData::default_format_1_u16_table_data(),
606 }
607 }
608}
609
610#[cfg(feature = "experimental_traverse")]
611impl<'a> SomeTable<'a> for AxisValueFormat1<'a> {
612 fn type_name(&self) -> &str {
613 "AxisValueFormat1"
614 }
615 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
616 match idx {
617 0usize => Some(Field::new("format", self.format())),
618 1usize => Some(Field::new("axis_index", self.axis_index())),
619 2usize => Some(Field::new("flags", self.flags())),
620 3usize => Some(Field::new("value_name_id", self.value_name_id())),
621 4usize => Some(Field::new("value", self.value())),
622 _ => None,
623 }
624 }
625}
626
627#[cfg(feature = "experimental_traverse")]
628#[allow(clippy::needless_lifetimes)]
629impl<'a> std::fmt::Debug for AxisValueFormat1<'a> {
630 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
631 (self as &dyn SomeTable<'a>).fmt(f)
632 }
633}
634
635impl Format<u16> for AxisValueFormat2<'_> {
636 const FORMAT: u16 = 2;
637}
638
639impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
640 fn min_byte_range(&self) -> Range<usize> {
641 0..self.range_max_value_byte_range().end
642 }
643 fn min_table_bytes(&self) -> &'a [u8] {
644 let range = self.min_byte_range();
645 self.data.as_bytes().get(range).unwrap_or_default()
646 }
647}
648
649impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
650 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
651 #[allow(clippy::absurd_extreme_comparisons)]
652 if data.len() < Self::MIN_SIZE {
653 return Err(ReadError::OutOfBounds);
654 }
655 Ok(Self { data })
656 }
657}
658
659#[derive(Clone)]
661pub struct AxisValueFormat2<'a> {
662 data: FontData<'a>,
663}
664
665#[allow(clippy::needless_lifetimes)]
666impl<'a> AxisValueFormat2<'a> {
667 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
668 + u16::RAW_BYTE_LEN
669 + AxisValueTableFlags::RAW_BYTE_LEN
670 + NameId::RAW_BYTE_LEN
671 + Fixed::RAW_BYTE_LEN
672 + Fixed::RAW_BYTE_LEN
673 + Fixed::RAW_BYTE_LEN);
674 basic_table_impls!(impl_the_methods);
675
676 pub fn format(&self) -> u16 {
678 let range = self.format_byte_range();
679 self.data.read_at(range.start).ok().unwrap()
680 }
681
682 pub fn axis_index(&self) -> u16 {
686 let range = self.axis_index_byte_range();
687 self.data.read_at(range.start).ok().unwrap()
688 }
689
690 pub fn flags(&self) -> AxisValueTableFlags {
692 let range = self.flags_byte_range();
693 self.data.read_at(range.start).ok().unwrap()
694 }
695
696 pub fn value_name_id(&self) -> NameId {
699 let range = self.value_name_id_byte_range();
700 self.data.read_at(range.start).ok().unwrap()
701 }
702
703 pub fn nominal_value(&self) -> Fixed {
705 let range = self.nominal_value_byte_range();
706 self.data.read_at(range.start).ok().unwrap()
707 }
708
709 pub fn range_min_value(&self) -> Fixed {
712 let range = self.range_min_value_byte_range();
713 self.data.read_at(range.start).ok().unwrap()
714 }
715
716 pub fn range_max_value(&self) -> Fixed {
719 let range = self.range_max_value_byte_range();
720 self.data.read_at(range.start).ok().unwrap()
721 }
722
723 pub fn format_byte_range(&self) -> Range<usize> {
724 let start = 0;
725 start..start + u16::RAW_BYTE_LEN
726 }
727
728 pub fn axis_index_byte_range(&self) -> Range<usize> {
729 let start = self.format_byte_range().end;
730 start..start + u16::RAW_BYTE_LEN
731 }
732
733 pub fn flags_byte_range(&self) -> Range<usize> {
734 let start = self.axis_index_byte_range().end;
735 start..start + AxisValueTableFlags::RAW_BYTE_LEN
736 }
737
738 pub fn value_name_id_byte_range(&self) -> Range<usize> {
739 let start = self.flags_byte_range().end;
740 start..start + NameId::RAW_BYTE_LEN
741 }
742
743 pub fn nominal_value_byte_range(&self) -> Range<usize> {
744 let start = self.value_name_id_byte_range().end;
745 start..start + Fixed::RAW_BYTE_LEN
746 }
747
748 pub fn range_min_value_byte_range(&self) -> Range<usize> {
749 let start = self.nominal_value_byte_range().end;
750 start..start + Fixed::RAW_BYTE_LEN
751 }
752
753 pub fn range_max_value_byte_range(&self) -> Range<usize> {
754 let start = self.range_min_value_byte_range().end;
755 start..start + Fixed::RAW_BYTE_LEN
756 }
757}
758
759#[cfg(feature = "experimental_traverse")]
760impl<'a> SomeTable<'a> for AxisValueFormat2<'a> {
761 fn type_name(&self) -> &str {
762 "AxisValueFormat2"
763 }
764 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
765 match idx {
766 0usize => Some(Field::new("format", self.format())),
767 1usize => Some(Field::new("axis_index", self.axis_index())),
768 2usize => Some(Field::new("flags", self.flags())),
769 3usize => Some(Field::new("value_name_id", self.value_name_id())),
770 4usize => Some(Field::new("nominal_value", self.nominal_value())),
771 5usize => Some(Field::new("range_min_value", self.range_min_value())),
772 6usize => Some(Field::new("range_max_value", self.range_max_value())),
773 _ => None,
774 }
775 }
776}
777
778#[cfg(feature = "experimental_traverse")]
779#[allow(clippy::needless_lifetimes)]
780impl<'a> std::fmt::Debug for AxisValueFormat2<'a> {
781 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
782 (self as &dyn SomeTable<'a>).fmt(f)
783 }
784}
785
786impl Format<u16> for AxisValueFormat3<'_> {
787 const FORMAT: u16 = 3;
788}
789
790impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
791 fn min_byte_range(&self) -> Range<usize> {
792 0..self.linked_value_byte_range().end
793 }
794 fn min_table_bytes(&self) -> &'a [u8] {
795 let range = self.min_byte_range();
796 self.data.as_bytes().get(range).unwrap_or_default()
797 }
798}
799
800impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
801 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
802 #[allow(clippy::absurd_extreme_comparisons)]
803 if data.len() < Self::MIN_SIZE {
804 return Err(ReadError::OutOfBounds);
805 }
806 Ok(Self { data })
807 }
808}
809
810#[derive(Clone)]
812pub struct AxisValueFormat3<'a> {
813 data: FontData<'a>,
814}
815
816#[allow(clippy::needless_lifetimes)]
817impl<'a> AxisValueFormat3<'a> {
818 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
819 + u16::RAW_BYTE_LEN
820 + AxisValueTableFlags::RAW_BYTE_LEN
821 + NameId::RAW_BYTE_LEN
822 + Fixed::RAW_BYTE_LEN
823 + Fixed::RAW_BYTE_LEN);
824 basic_table_impls!(impl_the_methods);
825
826 pub fn format(&self) -> u16 {
828 let range = self.format_byte_range();
829 self.data.read_at(range.start).ok().unwrap()
830 }
831
832 pub fn axis_index(&self) -> u16 {
836 let range = self.axis_index_byte_range();
837 self.data.read_at(range.start).ok().unwrap()
838 }
839
840 pub fn flags(&self) -> AxisValueTableFlags {
842 let range = self.flags_byte_range();
843 self.data.read_at(range.start).ok().unwrap()
844 }
845
846 pub fn value_name_id(&self) -> NameId {
849 let range = self.value_name_id_byte_range();
850 self.data.read_at(range.start).ok().unwrap()
851 }
852
853 pub fn value(&self) -> Fixed {
855 let range = self.value_byte_range();
856 self.data.read_at(range.start).ok().unwrap()
857 }
858
859 pub fn linked_value(&self) -> Fixed {
861 let range = self.linked_value_byte_range();
862 self.data.read_at(range.start).ok().unwrap()
863 }
864
865 pub fn format_byte_range(&self) -> Range<usize> {
866 let start = 0;
867 start..start + u16::RAW_BYTE_LEN
868 }
869
870 pub fn axis_index_byte_range(&self) -> Range<usize> {
871 let start = self.format_byte_range().end;
872 start..start + u16::RAW_BYTE_LEN
873 }
874
875 pub fn flags_byte_range(&self) -> Range<usize> {
876 let start = self.axis_index_byte_range().end;
877 start..start + AxisValueTableFlags::RAW_BYTE_LEN
878 }
879
880 pub fn value_name_id_byte_range(&self) -> Range<usize> {
881 let start = self.flags_byte_range().end;
882 start..start + NameId::RAW_BYTE_LEN
883 }
884
885 pub fn value_byte_range(&self) -> Range<usize> {
886 let start = self.value_name_id_byte_range().end;
887 start..start + Fixed::RAW_BYTE_LEN
888 }
889
890 pub fn linked_value_byte_range(&self) -> Range<usize> {
891 let start = self.value_byte_range().end;
892 start..start + Fixed::RAW_BYTE_LEN
893 }
894}
895
896#[cfg(feature = "experimental_traverse")]
897impl<'a> SomeTable<'a> for AxisValueFormat3<'a> {
898 fn type_name(&self) -> &str {
899 "AxisValueFormat3"
900 }
901 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
902 match idx {
903 0usize => Some(Field::new("format", self.format())),
904 1usize => Some(Field::new("axis_index", self.axis_index())),
905 2usize => Some(Field::new("flags", self.flags())),
906 3usize => Some(Field::new("value_name_id", self.value_name_id())),
907 4usize => Some(Field::new("value", self.value())),
908 5usize => Some(Field::new("linked_value", self.linked_value())),
909 _ => None,
910 }
911 }
912}
913
914#[cfg(feature = "experimental_traverse")]
915#[allow(clippy::needless_lifetimes)]
916impl<'a> std::fmt::Debug for AxisValueFormat3<'a> {
917 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
918 (self as &dyn SomeTable<'a>).fmt(f)
919 }
920}
921
922impl Format<u16> for AxisValueFormat4<'_> {
923 const FORMAT: u16 = 4;
924}
925
926impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
927 fn min_byte_range(&self) -> Range<usize> {
928 0..self.axis_values_byte_range().end
929 }
930 fn min_table_bytes(&self) -> &'a [u8] {
931 let range = self.min_byte_range();
932 self.data.as_bytes().get(range).unwrap_or_default()
933 }
934}
935
936impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
937 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
938 #[allow(clippy::absurd_extreme_comparisons)]
939 if data.len() < Self::MIN_SIZE {
940 return Err(ReadError::OutOfBounds);
941 }
942 Ok(Self { data })
943 }
944}
945
946#[derive(Clone)]
948pub struct AxisValueFormat4<'a> {
949 data: FontData<'a>,
950}
951
952#[allow(clippy::needless_lifetimes)]
953impl<'a> AxisValueFormat4<'a> {
954 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
955 + u16::RAW_BYTE_LEN
956 + AxisValueTableFlags::RAW_BYTE_LEN
957 + NameId::RAW_BYTE_LEN);
958 basic_table_impls!(impl_the_methods);
959
960 pub fn format(&self) -> u16 {
962 let range = self.format_byte_range();
963 self.data.read_at(range.start).ok().unwrap()
964 }
965
966 pub fn axis_count(&self) -> u16 {
969 let range = self.axis_count_byte_range();
970 self.data.read_at(range.start).ok().unwrap()
971 }
972
973 pub fn flags(&self) -> AxisValueTableFlags {
975 let range = self.flags_byte_range();
976 self.data.read_at(range.start).ok().unwrap()
977 }
978
979 pub fn value_name_id(&self) -> NameId {
982 let range = self.value_name_id_byte_range();
983 self.data.read_at(range.start).ok().unwrap()
984 }
985
986 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
989 let range = self.axis_values_byte_range();
990 self.data.read_array(range).ok().unwrap_or_default()
991 }
992
993 pub fn format_byte_range(&self) -> Range<usize> {
994 let start = 0;
995 start..start + u16::RAW_BYTE_LEN
996 }
997
998 pub fn axis_count_byte_range(&self) -> Range<usize> {
999 let start = self.format_byte_range().end;
1000 start..start + u16::RAW_BYTE_LEN
1001 }
1002
1003 pub fn flags_byte_range(&self) -> Range<usize> {
1004 let start = self.axis_count_byte_range().end;
1005 start..start + AxisValueTableFlags::RAW_BYTE_LEN
1006 }
1007
1008 pub fn value_name_id_byte_range(&self) -> Range<usize> {
1009 let start = self.flags_byte_range().end;
1010 start..start + NameId::RAW_BYTE_LEN
1011 }
1012
1013 pub fn axis_values_byte_range(&self) -> Range<usize> {
1014 let axis_count = self.axis_count();
1015 let start = self.value_name_id_byte_range().end;
1016 start..start + (axis_count as usize).saturating_mul(AxisValueRecord::RAW_BYTE_LEN)
1017 }
1018}
1019
1020#[cfg(feature = "experimental_traverse")]
1021impl<'a> SomeTable<'a> for AxisValueFormat4<'a> {
1022 fn type_name(&self) -> &str {
1023 "AxisValueFormat4"
1024 }
1025 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1026 match idx {
1027 0usize => Some(Field::new("format", self.format())),
1028 1usize => Some(Field::new("axis_count", self.axis_count())),
1029 2usize => Some(Field::new("flags", self.flags())),
1030 3usize => Some(Field::new("value_name_id", self.value_name_id())),
1031 4usize => Some(Field::new(
1032 "axis_values",
1033 traversal::FieldType::array_of_records(
1034 stringify!(AxisValueRecord),
1035 self.axis_values(),
1036 self.offset_data(),
1037 ),
1038 )),
1039 _ => None,
1040 }
1041 }
1042}
1043
1044#[cfg(feature = "experimental_traverse")]
1045#[allow(clippy::needless_lifetimes)]
1046impl<'a> std::fmt::Debug for AxisValueFormat4<'a> {
1047 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1048 (self as &dyn SomeTable<'a>).fmt(f)
1049 }
1050}
1051
1052#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1054#[repr(C)]
1055#[repr(packed)]
1056pub struct AxisValueRecord {
1057 pub axis_index: BigEndian<u16>,
1060 pub value: BigEndian<Fixed>,
1062}
1063
1064impl AxisValueRecord {
1065 pub fn axis_index(&self) -> u16 {
1068 self.axis_index.get()
1069 }
1070
1071 pub fn value(&self) -> Fixed {
1073 self.value.get()
1074 }
1075}
1076
1077impl FixedSize for AxisValueRecord {
1078 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1079}
1080
1081#[cfg(feature = "experimental_traverse")]
1082impl<'a> SomeRecord<'a> for AxisValueRecord {
1083 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1084 RecordResolver {
1085 name: "AxisValueRecord",
1086 get_field: Box::new(move |idx, _data| match idx {
1087 0usize => Some(Field::new("axis_index", self.axis_index())),
1088 1usize => Some(Field::new("value", self.value())),
1089 _ => None,
1090 }),
1091 data,
1092 }
1093 }
1094}
1095
1096#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1098#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1099#[repr(transparent)]
1100pub struct AxisValueTableFlags {
1101 bits: u16,
1102}
1103
1104impl AxisValueTableFlags {
1105 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1112
1113 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1117}
1118
1119impl AxisValueTableFlags {
1120 #[inline]
1122 pub const fn empty() -> Self {
1123 Self { bits: 0 }
1124 }
1125
1126 #[inline]
1128 pub const fn all() -> Self {
1129 Self {
1130 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1131 }
1132 }
1133
1134 #[inline]
1136 pub const fn bits(&self) -> u16 {
1137 self.bits
1138 }
1139
1140 #[inline]
1143 pub const fn from_bits(bits: u16) -> Option<Self> {
1144 if (bits & !Self::all().bits()) == 0 {
1145 Some(Self { bits })
1146 } else {
1147 None
1148 }
1149 }
1150
1151 #[inline]
1154 pub const fn from_bits_truncate(bits: u16) -> Self {
1155 Self {
1156 bits: bits & Self::all().bits,
1157 }
1158 }
1159
1160 #[inline]
1162 pub const fn is_empty(&self) -> bool {
1163 self.bits() == Self::empty().bits()
1164 }
1165
1166 #[inline]
1168 pub const fn intersects(&self, other: Self) -> bool {
1169 !(Self {
1170 bits: self.bits & other.bits,
1171 })
1172 .is_empty()
1173 }
1174
1175 #[inline]
1177 pub const fn contains(&self, other: Self) -> bool {
1178 (self.bits & other.bits) == other.bits
1179 }
1180
1181 #[inline]
1183 pub fn insert(&mut self, other: Self) {
1184 self.bits |= other.bits;
1185 }
1186
1187 #[inline]
1189 pub fn remove(&mut self, other: Self) {
1190 self.bits &= !other.bits;
1191 }
1192
1193 #[inline]
1195 pub fn toggle(&mut self, other: Self) {
1196 self.bits ^= other.bits;
1197 }
1198
1199 #[inline]
1210 #[must_use]
1211 pub const fn intersection(self, other: Self) -> Self {
1212 Self {
1213 bits: self.bits & other.bits,
1214 }
1215 }
1216
1217 #[inline]
1228 #[must_use]
1229 pub const fn union(self, other: Self) -> Self {
1230 Self {
1231 bits: self.bits | other.bits,
1232 }
1233 }
1234
1235 #[inline]
1248 #[must_use]
1249 pub const fn difference(self, other: Self) -> Self {
1250 Self {
1251 bits: self.bits & !other.bits,
1252 }
1253 }
1254}
1255
1256impl std::ops::BitOr for AxisValueTableFlags {
1257 type Output = Self;
1258
1259 #[inline]
1261 fn bitor(self, other: AxisValueTableFlags) -> Self {
1262 Self {
1263 bits: self.bits | other.bits,
1264 }
1265 }
1266}
1267
1268impl std::ops::BitOrAssign for AxisValueTableFlags {
1269 #[inline]
1271 fn bitor_assign(&mut self, other: Self) {
1272 self.bits |= other.bits;
1273 }
1274}
1275
1276impl std::ops::BitXor for AxisValueTableFlags {
1277 type Output = Self;
1278
1279 #[inline]
1281 fn bitxor(self, other: Self) -> Self {
1282 Self {
1283 bits: self.bits ^ other.bits,
1284 }
1285 }
1286}
1287
1288impl std::ops::BitXorAssign for AxisValueTableFlags {
1289 #[inline]
1291 fn bitxor_assign(&mut self, other: Self) {
1292 self.bits ^= other.bits;
1293 }
1294}
1295
1296impl std::ops::BitAnd for AxisValueTableFlags {
1297 type Output = Self;
1298
1299 #[inline]
1301 fn bitand(self, other: Self) -> Self {
1302 Self {
1303 bits: self.bits & other.bits,
1304 }
1305 }
1306}
1307
1308impl std::ops::BitAndAssign for AxisValueTableFlags {
1309 #[inline]
1311 fn bitand_assign(&mut self, other: Self) {
1312 self.bits &= other.bits;
1313 }
1314}
1315
1316impl std::ops::Sub for AxisValueTableFlags {
1317 type Output = Self;
1318
1319 #[inline]
1321 fn sub(self, other: Self) -> Self {
1322 Self {
1323 bits: self.bits & !other.bits,
1324 }
1325 }
1326}
1327
1328impl std::ops::SubAssign for AxisValueTableFlags {
1329 #[inline]
1331 fn sub_assign(&mut self, other: Self) {
1332 self.bits &= !other.bits;
1333 }
1334}
1335
1336impl std::ops::Not for AxisValueTableFlags {
1337 type Output = Self;
1338
1339 #[inline]
1341 fn not(self) -> Self {
1342 Self { bits: !self.bits } & Self::all()
1343 }
1344}
1345
1346impl std::fmt::Debug for AxisValueTableFlags {
1347 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1348 let members: &[(&str, Self)] = &[
1349 (
1350 "OLDER_SIBLING_FONT_ATTRIBUTE",
1351 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1352 ),
1353 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1354 ];
1355 let mut first = true;
1356 for (name, value) in members {
1357 if self.contains(*value) {
1358 if !first {
1359 f.write_str(" | ")?;
1360 }
1361 first = false;
1362 f.write_str(name)?;
1363 }
1364 }
1365 if first {
1366 f.write_str("(empty)")?;
1367 }
1368 Ok(())
1369 }
1370}
1371
1372impl std::fmt::Binary for AxisValueTableFlags {
1373 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1374 std::fmt::Binary::fmt(&self.bits, f)
1375 }
1376}
1377
1378impl std::fmt::Octal for AxisValueTableFlags {
1379 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1380 std::fmt::Octal::fmt(&self.bits, f)
1381 }
1382}
1383
1384impl std::fmt::LowerHex for AxisValueTableFlags {
1385 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1386 std::fmt::LowerHex::fmt(&self.bits, f)
1387 }
1388}
1389
1390impl std::fmt::UpperHex for AxisValueTableFlags {
1391 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1392 std::fmt::UpperHex::fmt(&self.bits, f)
1393 }
1394}
1395
1396impl font_types::Scalar for AxisValueTableFlags {
1397 type Raw = <u16 as font_types::Scalar>::Raw;
1398 fn to_raw(self) -> Self::Raw {
1399 self.bits().to_raw()
1400 }
1401 fn from_raw(raw: Self::Raw) -> Self {
1402 let t = <u16>::from_raw(raw);
1403 Self::from_bits_truncate(t)
1404 }
1405}
1406
1407#[cfg(feature = "experimental_traverse")]
1408impl<'a> From<AxisValueTableFlags> for FieldType<'a> {
1409 fn from(src: AxisValueTableFlags) -> FieldType<'a> {
1410 src.bits().into()
1411 }
1412}