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
158#[cfg(feature = "experimental_traverse")]
159impl<'a> SomeTable<'a> for Stat<'a> {
160 fn type_name(&self) -> &str {
161 "Stat"
162 }
163 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
164 match idx {
165 0usize => Some(Field::new("version", self.version())),
166 1usize => Some(Field::new("design_axis_size", self.design_axis_size())),
167 2usize => Some(Field::new("design_axis_count", self.design_axis_count())),
168 3usize => Some(Field::new(
169 "design_axes_offset",
170 traversal::FieldType::offset_to_array_of_records(
171 self.design_axes_offset(),
172 self.design_axes(),
173 stringify!(AxisRecord),
174 self.offset_data(),
175 ),
176 )),
177 4usize => Some(Field::new("axis_value_count", self.axis_value_count())),
178 5usize => Some(Field::new(
179 "offset_to_axis_value_offsets",
180 FieldType::offset(
181 self.offset_to_axis_value_offsets(),
182 self.offset_to_axis_values(),
183 ),
184 )),
185 6usize if self.version().compatible((1u16, 1u16)) => Some(Field::new(
186 "elided_fallback_name_id",
187 self.elided_fallback_name_id().unwrap(),
188 )),
189 _ => None,
190 }
191 }
192}
193
194#[cfg(feature = "experimental_traverse")]
195#[allow(clippy::needless_lifetimes)]
196impl<'a> std::fmt::Debug for Stat<'a> {
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 (self as &dyn SomeTable<'a>).fmt(f)
199 }
200}
201
202#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
204#[repr(C)]
205#[repr(packed)]
206pub struct AxisRecord {
207 pub axis_tag: BigEndian<Tag>,
209 pub axis_name_id: BigEndian<NameId>,
212 pub axis_ordering: BigEndian<u16>,
216}
217
218impl AxisRecord {
219 pub fn axis_tag(&self) -> Tag {
221 self.axis_tag.get()
222 }
223
224 pub fn axis_name_id(&self) -> NameId {
227 self.axis_name_id.get()
228 }
229
230 pub fn axis_ordering(&self) -> u16 {
234 self.axis_ordering.get()
235 }
236}
237
238impl FixedSize for AxisRecord {
239 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
240}
241
242#[cfg(feature = "experimental_traverse")]
243impl<'a> SomeRecord<'a> for AxisRecord {
244 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
245 RecordResolver {
246 name: "AxisRecord",
247 get_field: Box::new(move |idx, _data| match idx {
248 0usize => Some(Field::new("axis_tag", self.axis_tag())),
249 1usize => Some(Field::new("axis_name_id", self.axis_name_id())),
250 2usize => Some(Field::new("axis_ordering", self.axis_ordering())),
251 _ => None,
252 }),
253 data,
254 }
255 }
256}
257
258impl<'a> MinByteRange<'a> for AxisValueArray<'a> {
259 fn min_byte_range(&self) -> Range<usize> {
260 0..self.axis_value_offsets_byte_range().end
261 }
262 fn min_table_bytes(&self) -> &'a [u8] {
263 let range = self.min_byte_range();
264 self.data.as_bytes().get(range).unwrap_or_default()
265 }
266}
267
268impl ReadArgs for AxisValueArray<'_> {
269 type Args = u16;
270}
271
272impl<'a> FontReadWithArgs<'a> for AxisValueArray<'a> {
273 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
274 let axis_value_count = *args;
275
276 #[allow(clippy::absurd_extreme_comparisons)]
277 if data.len() < Self::MIN_SIZE {
278 return Err(ReadError::OutOfBounds);
279 }
280 Ok(Self {
281 data,
282 axis_value_count,
283 })
284 }
285}
286
287impl<'a> AxisValueArray<'a> {
288 pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
293 let args = axis_value_count;
294 Self::read_with_args(data, &args)
295 }
296}
297
298#[derive(Clone)]
300pub struct AxisValueArray<'a> {
301 data: FontData<'a>,
302 axis_value_count: u16,
303}
304
305#[allow(clippy::needless_lifetimes)]
306impl<'a> AxisValueArray<'a> {
307 pub const MIN_SIZE: usize = 0;
308 basic_table_impls!(impl_the_methods);
309
310 pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
313 let range = self.axis_value_offsets_byte_range();
314 self.data.read_array(range).ok().unwrap_or_default()
315 }
316
317 pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
319 let data = self.data;
320 let offsets = self.axis_value_offsets();
321 ArrayOfOffsets::new(offsets, data, ())
322 }
323
324 pub(crate) fn axis_value_count(&self) -> u16 {
325 self.axis_value_count
326 }
327
328 pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
329 let axis_value_count = self.axis_value_count();
330 let start = 0;
331 start..start + (axis_value_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
332 }
333}
334
335#[cfg(feature = "experimental_traverse")]
336impl<'a> SomeTable<'a> for AxisValueArray<'a> {
337 fn type_name(&self) -> &str {
338 "AxisValueArray"
339 }
340 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
341 match idx {
342 0usize => Some({
343 let data = self.data;
344 Field::new(
345 "axis_value_offsets",
346 FieldType::array_of_offsets(
347 better_type_name::<AxisValue>(),
348 self.axis_value_offsets(),
349 move |off| {
350 let target = off.get().resolve::<AxisValue>(data);
351 FieldType::offset(off.get(), target)
352 },
353 ),
354 )
355 }),
356 _ => None,
357 }
358 }
359}
360
361#[cfg(feature = "experimental_traverse")]
362#[allow(clippy::needless_lifetimes)]
363impl<'a> std::fmt::Debug for AxisValueArray<'a> {
364 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
365 (self as &dyn SomeTable<'a>).fmt(f)
366 }
367}
368
369#[derive(Clone)]
371pub enum AxisValue<'a> {
372 Format1(AxisValueFormat1<'a>),
373 Format2(AxisValueFormat2<'a>),
374 Format3(AxisValueFormat3<'a>),
375 Format4(AxisValueFormat4<'a>),
376}
377
378impl<'a> AxisValue<'a> {
379 pub fn offset_data(&self) -> FontData<'a> {
381 match self {
382 Self::Format1(item) => item.offset_data(),
383 Self::Format2(item) => item.offset_data(),
384 Self::Format3(item) => item.offset_data(),
385 Self::Format4(item) => item.offset_data(),
386 }
387 }
388
389 pub fn format(&self) -> u16 {
391 match self {
392 Self::Format1(item) => item.format(),
393 Self::Format2(item) => item.format(),
394 Self::Format3(item) => item.format(),
395 Self::Format4(item) => item.format(),
396 }
397 }
398
399 pub fn flags(&self) -> AxisValueTableFlags {
401 match self {
402 Self::Format1(item) => item.flags(),
403 Self::Format2(item) => item.flags(),
404 Self::Format3(item) => item.flags(),
405 Self::Format4(item) => item.flags(),
406 }
407 }
408
409 pub fn value_name_id(&self) -> NameId {
412 match self {
413 Self::Format1(item) => item.value_name_id(),
414 Self::Format2(item) => item.value_name_id(),
415 Self::Format3(item) => item.value_name_id(),
416 Self::Format4(item) => item.value_name_id(),
417 }
418 }
419}
420
421impl<'a> FontRead<'a> for AxisValue<'a> {
422 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
423 let format: u16 = data.read_at(0usize)?;
424 match format {
425 AxisValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
426 AxisValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
427 AxisValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
428 AxisValueFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
429 other => Err(ReadError::InvalidFormat(other.into())),
430 }
431 }
432}
433
434impl<'a> MinByteRange<'a> for AxisValue<'a> {
435 fn min_byte_range(&self) -> Range<usize> {
436 match self {
437 Self::Format1(item) => item.min_byte_range(),
438 Self::Format2(item) => item.min_byte_range(),
439 Self::Format3(item) => item.min_byte_range(),
440 Self::Format4(item) => item.min_byte_range(),
441 }
442 }
443 fn min_table_bytes(&self) -> &'a [u8] {
444 match self {
445 Self::Format1(item) => item.min_table_bytes(),
446 Self::Format2(item) => item.min_table_bytes(),
447 Self::Format3(item) => item.min_table_bytes(),
448 Self::Format4(item) => item.min_table_bytes(),
449 }
450 }
451}
452
453#[cfg(feature = "experimental_traverse")]
454impl<'a> AxisValue<'a> {
455 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
456 match self {
457 Self::Format1(table) => table,
458 Self::Format2(table) => table,
459 Self::Format3(table) => table,
460 Self::Format4(table) => table,
461 }
462 }
463}
464
465#[cfg(feature = "experimental_traverse")]
466impl std::fmt::Debug for AxisValue<'_> {
467 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
468 self.dyn_inner().fmt(f)
469 }
470}
471
472#[cfg(feature = "experimental_traverse")]
473impl<'a> SomeTable<'a> for AxisValue<'a> {
474 fn type_name(&self) -> &str {
475 self.dyn_inner().type_name()
476 }
477 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
478 self.dyn_inner().get_field(idx)
479 }
480}
481
482impl Format<u16> for AxisValueFormat1<'_> {
483 const FORMAT: u16 = 1;
484}
485
486impl<'a> MinByteRange<'a> for AxisValueFormat1<'a> {
487 fn min_byte_range(&self) -> Range<usize> {
488 0..self.value_byte_range().end
489 }
490 fn min_table_bytes(&self) -> &'a [u8] {
491 let range = self.min_byte_range();
492 self.data.as_bytes().get(range).unwrap_or_default()
493 }
494}
495
496impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
497 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
498 #[allow(clippy::absurd_extreme_comparisons)]
499 if data.len() < Self::MIN_SIZE {
500 return Err(ReadError::OutOfBounds);
501 }
502 Ok(Self { data })
503 }
504}
505
506#[derive(Clone)]
508pub struct AxisValueFormat1<'a> {
509 data: FontData<'a>,
510}
511
512#[allow(clippy::needless_lifetimes)]
513impl<'a> AxisValueFormat1<'a> {
514 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
515 + u16::RAW_BYTE_LEN
516 + AxisValueTableFlags::RAW_BYTE_LEN
517 + NameId::RAW_BYTE_LEN
518 + Fixed::RAW_BYTE_LEN);
519 basic_table_impls!(impl_the_methods);
520
521 pub fn format(&self) -> u16 {
523 let range = self.format_byte_range();
524 self.data.read_at(range.start).ok().unwrap()
525 }
526
527 pub fn axis_index(&self) -> u16 {
531 let range = self.axis_index_byte_range();
532 self.data.read_at(range.start).ok().unwrap()
533 }
534
535 pub fn flags(&self) -> AxisValueTableFlags {
537 let range = self.flags_byte_range();
538 self.data.read_at(range.start).ok().unwrap()
539 }
540
541 pub fn value_name_id(&self) -> NameId {
544 let range = self.value_name_id_byte_range();
545 self.data.read_at(range.start).ok().unwrap()
546 }
547
548 pub fn value(&self) -> Fixed {
550 let range = self.value_byte_range();
551 self.data.read_at(range.start).ok().unwrap()
552 }
553
554 pub fn format_byte_range(&self) -> Range<usize> {
555 let start = 0;
556 start..start + u16::RAW_BYTE_LEN
557 }
558
559 pub fn axis_index_byte_range(&self) -> Range<usize> {
560 let start = self.format_byte_range().end;
561 start..start + u16::RAW_BYTE_LEN
562 }
563
564 pub fn flags_byte_range(&self) -> Range<usize> {
565 let start = self.axis_index_byte_range().end;
566 start..start + AxisValueTableFlags::RAW_BYTE_LEN
567 }
568
569 pub fn value_name_id_byte_range(&self) -> Range<usize> {
570 let start = self.flags_byte_range().end;
571 start..start + NameId::RAW_BYTE_LEN
572 }
573
574 pub fn value_byte_range(&self) -> Range<usize> {
575 let start = self.value_name_id_byte_range().end;
576 start..start + Fixed::RAW_BYTE_LEN
577 }
578}
579
580#[cfg(feature = "experimental_traverse")]
581impl<'a> SomeTable<'a> for AxisValueFormat1<'a> {
582 fn type_name(&self) -> &str {
583 "AxisValueFormat1"
584 }
585 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
586 match idx {
587 0usize => Some(Field::new("format", self.format())),
588 1usize => Some(Field::new("axis_index", self.axis_index())),
589 2usize => Some(Field::new("flags", self.flags())),
590 3usize => Some(Field::new("value_name_id", self.value_name_id())),
591 4usize => Some(Field::new("value", self.value())),
592 _ => None,
593 }
594 }
595}
596
597#[cfg(feature = "experimental_traverse")]
598#[allow(clippy::needless_lifetimes)]
599impl<'a> std::fmt::Debug for AxisValueFormat1<'a> {
600 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
601 (self as &dyn SomeTable<'a>).fmt(f)
602 }
603}
604
605impl Format<u16> for AxisValueFormat2<'_> {
606 const FORMAT: u16 = 2;
607}
608
609impl<'a> MinByteRange<'a> for AxisValueFormat2<'a> {
610 fn min_byte_range(&self) -> Range<usize> {
611 0..self.range_max_value_byte_range().end
612 }
613 fn min_table_bytes(&self) -> &'a [u8] {
614 let range = self.min_byte_range();
615 self.data.as_bytes().get(range).unwrap_or_default()
616 }
617}
618
619impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
620 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
621 #[allow(clippy::absurd_extreme_comparisons)]
622 if data.len() < Self::MIN_SIZE {
623 return Err(ReadError::OutOfBounds);
624 }
625 Ok(Self { data })
626 }
627}
628
629#[derive(Clone)]
631pub struct AxisValueFormat2<'a> {
632 data: FontData<'a>,
633}
634
635#[allow(clippy::needless_lifetimes)]
636impl<'a> AxisValueFormat2<'a> {
637 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
638 + u16::RAW_BYTE_LEN
639 + AxisValueTableFlags::RAW_BYTE_LEN
640 + NameId::RAW_BYTE_LEN
641 + Fixed::RAW_BYTE_LEN
642 + Fixed::RAW_BYTE_LEN
643 + Fixed::RAW_BYTE_LEN);
644 basic_table_impls!(impl_the_methods);
645
646 pub fn format(&self) -> u16 {
648 let range = self.format_byte_range();
649 self.data.read_at(range.start).ok().unwrap()
650 }
651
652 pub fn axis_index(&self) -> u16 {
656 let range = self.axis_index_byte_range();
657 self.data.read_at(range.start).ok().unwrap()
658 }
659
660 pub fn flags(&self) -> AxisValueTableFlags {
662 let range = self.flags_byte_range();
663 self.data.read_at(range.start).ok().unwrap()
664 }
665
666 pub fn value_name_id(&self) -> NameId {
669 let range = self.value_name_id_byte_range();
670 self.data.read_at(range.start).ok().unwrap()
671 }
672
673 pub fn nominal_value(&self) -> Fixed {
675 let range = self.nominal_value_byte_range();
676 self.data.read_at(range.start).ok().unwrap()
677 }
678
679 pub fn range_min_value(&self) -> Fixed {
682 let range = self.range_min_value_byte_range();
683 self.data.read_at(range.start).ok().unwrap()
684 }
685
686 pub fn range_max_value(&self) -> Fixed {
689 let range = self.range_max_value_byte_range();
690 self.data.read_at(range.start).ok().unwrap()
691 }
692
693 pub fn format_byte_range(&self) -> Range<usize> {
694 let start = 0;
695 start..start + u16::RAW_BYTE_LEN
696 }
697
698 pub fn axis_index_byte_range(&self) -> Range<usize> {
699 let start = self.format_byte_range().end;
700 start..start + u16::RAW_BYTE_LEN
701 }
702
703 pub fn flags_byte_range(&self) -> Range<usize> {
704 let start = self.axis_index_byte_range().end;
705 start..start + AxisValueTableFlags::RAW_BYTE_LEN
706 }
707
708 pub fn value_name_id_byte_range(&self) -> Range<usize> {
709 let start = self.flags_byte_range().end;
710 start..start + NameId::RAW_BYTE_LEN
711 }
712
713 pub fn nominal_value_byte_range(&self) -> Range<usize> {
714 let start = self.value_name_id_byte_range().end;
715 start..start + Fixed::RAW_BYTE_LEN
716 }
717
718 pub fn range_min_value_byte_range(&self) -> Range<usize> {
719 let start = self.nominal_value_byte_range().end;
720 start..start + Fixed::RAW_BYTE_LEN
721 }
722
723 pub fn range_max_value_byte_range(&self) -> Range<usize> {
724 let start = self.range_min_value_byte_range().end;
725 start..start + Fixed::RAW_BYTE_LEN
726 }
727}
728
729#[cfg(feature = "experimental_traverse")]
730impl<'a> SomeTable<'a> for AxisValueFormat2<'a> {
731 fn type_name(&self) -> &str {
732 "AxisValueFormat2"
733 }
734 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
735 match idx {
736 0usize => Some(Field::new("format", self.format())),
737 1usize => Some(Field::new("axis_index", self.axis_index())),
738 2usize => Some(Field::new("flags", self.flags())),
739 3usize => Some(Field::new("value_name_id", self.value_name_id())),
740 4usize => Some(Field::new("nominal_value", self.nominal_value())),
741 5usize => Some(Field::new("range_min_value", self.range_min_value())),
742 6usize => Some(Field::new("range_max_value", self.range_max_value())),
743 _ => None,
744 }
745 }
746}
747
748#[cfg(feature = "experimental_traverse")]
749#[allow(clippy::needless_lifetimes)]
750impl<'a> std::fmt::Debug for AxisValueFormat2<'a> {
751 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
752 (self as &dyn SomeTable<'a>).fmt(f)
753 }
754}
755
756impl Format<u16> for AxisValueFormat3<'_> {
757 const FORMAT: u16 = 3;
758}
759
760impl<'a> MinByteRange<'a> for AxisValueFormat3<'a> {
761 fn min_byte_range(&self) -> Range<usize> {
762 0..self.linked_value_byte_range().end
763 }
764 fn min_table_bytes(&self) -> &'a [u8] {
765 let range = self.min_byte_range();
766 self.data.as_bytes().get(range).unwrap_or_default()
767 }
768}
769
770impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
771 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
772 #[allow(clippy::absurd_extreme_comparisons)]
773 if data.len() < Self::MIN_SIZE {
774 return Err(ReadError::OutOfBounds);
775 }
776 Ok(Self { data })
777 }
778}
779
780#[derive(Clone)]
782pub struct AxisValueFormat3<'a> {
783 data: FontData<'a>,
784}
785
786#[allow(clippy::needless_lifetimes)]
787impl<'a> AxisValueFormat3<'a> {
788 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
789 + u16::RAW_BYTE_LEN
790 + AxisValueTableFlags::RAW_BYTE_LEN
791 + NameId::RAW_BYTE_LEN
792 + Fixed::RAW_BYTE_LEN
793 + Fixed::RAW_BYTE_LEN);
794 basic_table_impls!(impl_the_methods);
795
796 pub fn format(&self) -> u16 {
798 let range = self.format_byte_range();
799 self.data.read_at(range.start).ok().unwrap()
800 }
801
802 pub fn axis_index(&self) -> u16 {
806 let range = self.axis_index_byte_range();
807 self.data.read_at(range.start).ok().unwrap()
808 }
809
810 pub fn flags(&self) -> AxisValueTableFlags {
812 let range = self.flags_byte_range();
813 self.data.read_at(range.start).ok().unwrap()
814 }
815
816 pub fn value_name_id(&self) -> NameId {
819 let range = self.value_name_id_byte_range();
820 self.data.read_at(range.start).ok().unwrap()
821 }
822
823 pub fn value(&self) -> Fixed {
825 let range = self.value_byte_range();
826 self.data.read_at(range.start).ok().unwrap()
827 }
828
829 pub fn linked_value(&self) -> Fixed {
831 let range = self.linked_value_byte_range();
832 self.data.read_at(range.start).ok().unwrap()
833 }
834
835 pub fn format_byte_range(&self) -> Range<usize> {
836 let start = 0;
837 start..start + u16::RAW_BYTE_LEN
838 }
839
840 pub fn axis_index_byte_range(&self) -> Range<usize> {
841 let start = self.format_byte_range().end;
842 start..start + u16::RAW_BYTE_LEN
843 }
844
845 pub fn flags_byte_range(&self) -> Range<usize> {
846 let start = self.axis_index_byte_range().end;
847 start..start + AxisValueTableFlags::RAW_BYTE_LEN
848 }
849
850 pub fn value_name_id_byte_range(&self) -> Range<usize> {
851 let start = self.flags_byte_range().end;
852 start..start + NameId::RAW_BYTE_LEN
853 }
854
855 pub fn value_byte_range(&self) -> Range<usize> {
856 let start = self.value_name_id_byte_range().end;
857 start..start + Fixed::RAW_BYTE_LEN
858 }
859
860 pub fn linked_value_byte_range(&self) -> Range<usize> {
861 let start = self.value_byte_range().end;
862 start..start + Fixed::RAW_BYTE_LEN
863 }
864}
865
866#[cfg(feature = "experimental_traverse")]
867impl<'a> SomeTable<'a> for AxisValueFormat3<'a> {
868 fn type_name(&self) -> &str {
869 "AxisValueFormat3"
870 }
871 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
872 match idx {
873 0usize => Some(Field::new("format", self.format())),
874 1usize => Some(Field::new("axis_index", self.axis_index())),
875 2usize => Some(Field::new("flags", self.flags())),
876 3usize => Some(Field::new("value_name_id", self.value_name_id())),
877 4usize => Some(Field::new("value", self.value())),
878 5usize => Some(Field::new("linked_value", self.linked_value())),
879 _ => None,
880 }
881 }
882}
883
884#[cfg(feature = "experimental_traverse")]
885#[allow(clippy::needless_lifetimes)]
886impl<'a> std::fmt::Debug for AxisValueFormat3<'a> {
887 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
888 (self as &dyn SomeTable<'a>).fmt(f)
889 }
890}
891
892impl Format<u16> for AxisValueFormat4<'_> {
893 const FORMAT: u16 = 4;
894}
895
896impl<'a> MinByteRange<'a> for AxisValueFormat4<'a> {
897 fn min_byte_range(&self) -> Range<usize> {
898 0..self.axis_values_byte_range().end
899 }
900 fn min_table_bytes(&self) -> &'a [u8] {
901 let range = self.min_byte_range();
902 self.data.as_bytes().get(range).unwrap_or_default()
903 }
904}
905
906impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
907 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
908 #[allow(clippy::absurd_extreme_comparisons)]
909 if data.len() < Self::MIN_SIZE {
910 return Err(ReadError::OutOfBounds);
911 }
912 Ok(Self { data })
913 }
914}
915
916#[derive(Clone)]
918pub struct AxisValueFormat4<'a> {
919 data: FontData<'a>,
920}
921
922#[allow(clippy::needless_lifetimes)]
923impl<'a> AxisValueFormat4<'a> {
924 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
925 + u16::RAW_BYTE_LEN
926 + AxisValueTableFlags::RAW_BYTE_LEN
927 + NameId::RAW_BYTE_LEN);
928 basic_table_impls!(impl_the_methods);
929
930 pub fn format(&self) -> u16 {
932 let range = self.format_byte_range();
933 self.data.read_at(range.start).ok().unwrap()
934 }
935
936 pub fn axis_count(&self) -> u16 {
939 let range = self.axis_count_byte_range();
940 self.data.read_at(range.start).ok().unwrap()
941 }
942
943 pub fn flags(&self) -> AxisValueTableFlags {
945 let range = self.flags_byte_range();
946 self.data.read_at(range.start).ok().unwrap()
947 }
948
949 pub fn value_name_id(&self) -> NameId {
952 let range = self.value_name_id_byte_range();
953 self.data.read_at(range.start).ok().unwrap()
954 }
955
956 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
959 let range = self.axis_values_byte_range();
960 self.data.read_array(range).ok().unwrap_or_default()
961 }
962
963 pub fn format_byte_range(&self) -> Range<usize> {
964 let start = 0;
965 start..start + u16::RAW_BYTE_LEN
966 }
967
968 pub fn axis_count_byte_range(&self) -> Range<usize> {
969 let start = self.format_byte_range().end;
970 start..start + u16::RAW_BYTE_LEN
971 }
972
973 pub fn flags_byte_range(&self) -> Range<usize> {
974 let start = self.axis_count_byte_range().end;
975 start..start + AxisValueTableFlags::RAW_BYTE_LEN
976 }
977
978 pub fn value_name_id_byte_range(&self) -> Range<usize> {
979 let start = self.flags_byte_range().end;
980 start..start + NameId::RAW_BYTE_LEN
981 }
982
983 pub fn axis_values_byte_range(&self) -> Range<usize> {
984 let axis_count = self.axis_count();
985 let start = self.value_name_id_byte_range().end;
986 start..start + (axis_count as usize).saturating_mul(AxisValueRecord::RAW_BYTE_LEN)
987 }
988}
989
990#[cfg(feature = "experimental_traverse")]
991impl<'a> SomeTable<'a> for AxisValueFormat4<'a> {
992 fn type_name(&self) -> &str {
993 "AxisValueFormat4"
994 }
995 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
996 match idx {
997 0usize => Some(Field::new("format", self.format())),
998 1usize => Some(Field::new("axis_count", self.axis_count())),
999 2usize => Some(Field::new("flags", self.flags())),
1000 3usize => Some(Field::new("value_name_id", self.value_name_id())),
1001 4usize => Some(Field::new(
1002 "axis_values",
1003 traversal::FieldType::array_of_records(
1004 stringify!(AxisValueRecord),
1005 self.axis_values(),
1006 self.offset_data(),
1007 ),
1008 )),
1009 _ => None,
1010 }
1011 }
1012}
1013
1014#[cfg(feature = "experimental_traverse")]
1015#[allow(clippy::needless_lifetimes)]
1016impl<'a> std::fmt::Debug for AxisValueFormat4<'a> {
1017 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1018 (self as &dyn SomeTable<'a>).fmt(f)
1019 }
1020}
1021
1022#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1024#[repr(C)]
1025#[repr(packed)]
1026pub struct AxisValueRecord {
1027 pub axis_index: BigEndian<u16>,
1030 pub value: BigEndian<Fixed>,
1032}
1033
1034impl AxisValueRecord {
1035 pub fn axis_index(&self) -> u16 {
1038 self.axis_index.get()
1039 }
1040
1041 pub fn value(&self) -> Fixed {
1043 self.value.get()
1044 }
1045}
1046
1047impl FixedSize for AxisValueRecord {
1048 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1049}
1050
1051#[cfg(feature = "experimental_traverse")]
1052impl<'a> SomeRecord<'a> for AxisValueRecord {
1053 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1054 RecordResolver {
1055 name: "AxisValueRecord",
1056 get_field: Box::new(move |idx, _data| match idx {
1057 0usize => Some(Field::new("axis_index", self.axis_index())),
1058 1usize => Some(Field::new("value", self.value())),
1059 _ => None,
1060 }),
1061 data,
1062 }
1063 }
1064}
1065
1066#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1068#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1069#[repr(transparent)]
1070pub struct AxisValueTableFlags {
1071 bits: u16,
1072}
1073
1074impl AxisValueTableFlags {
1075 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1082
1083 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1087}
1088
1089impl AxisValueTableFlags {
1090 #[inline]
1092 pub const fn empty() -> Self {
1093 Self { bits: 0 }
1094 }
1095
1096 #[inline]
1098 pub const fn all() -> Self {
1099 Self {
1100 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1101 }
1102 }
1103
1104 #[inline]
1106 pub const fn bits(&self) -> u16 {
1107 self.bits
1108 }
1109
1110 #[inline]
1113 pub const fn from_bits(bits: u16) -> Option<Self> {
1114 if (bits & !Self::all().bits()) == 0 {
1115 Some(Self { bits })
1116 } else {
1117 None
1118 }
1119 }
1120
1121 #[inline]
1124 pub const fn from_bits_truncate(bits: u16) -> Self {
1125 Self {
1126 bits: bits & Self::all().bits,
1127 }
1128 }
1129
1130 #[inline]
1132 pub const fn is_empty(&self) -> bool {
1133 self.bits() == Self::empty().bits()
1134 }
1135
1136 #[inline]
1138 pub const fn intersects(&self, other: Self) -> bool {
1139 !(Self {
1140 bits: self.bits & other.bits,
1141 })
1142 .is_empty()
1143 }
1144
1145 #[inline]
1147 pub const fn contains(&self, other: Self) -> bool {
1148 (self.bits & other.bits) == other.bits
1149 }
1150
1151 #[inline]
1153 pub fn insert(&mut self, other: Self) {
1154 self.bits |= other.bits;
1155 }
1156
1157 #[inline]
1159 pub fn remove(&mut self, other: Self) {
1160 self.bits &= !other.bits;
1161 }
1162
1163 #[inline]
1165 pub fn toggle(&mut self, other: Self) {
1166 self.bits ^= other.bits;
1167 }
1168
1169 #[inline]
1180 #[must_use]
1181 pub const fn intersection(self, other: Self) -> Self {
1182 Self {
1183 bits: self.bits & other.bits,
1184 }
1185 }
1186
1187 #[inline]
1198 #[must_use]
1199 pub const fn union(self, other: Self) -> Self {
1200 Self {
1201 bits: self.bits | other.bits,
1202 }
1203 }
1204
1205 #[inline]
1218 #[must_use]
1219 pub const fn difference(self, other: Self) -> Self {
1220 Self {
1221 bits: self.bits & !other.bits,
1222 }
1223 }
1224}
1225
1226impl std::ops::BitOr for AxisValueTableFlags {
1227 type Output = Self;
1228
1229 #[inline]
1231 fn bitor(self, other: AxisValueTableFlags) -> Self {
1232 Self {
1233 bits: self.bits | other.bits,
1234 }
1235 }
1236}
1237
1238impl std::ops::BitOrAssign for AxisValueTableFlags {
1239 #[inline]
1241 fn bitor_assign(&mut self, other: Self) {
1242 self.bits |= other.bits;
1243 }
1244}
1245
1246impl std::ops::BitXor for AxisValueTableFlags {
1247 type Output = Self;
1248
1249 #[inline]
1251 fn bitxor(self, other: Self) -> Self {
1252 Self {
1253 bits: self.bits ^ other.bits,
1254 }
1255 }
1256}
1257
1258impl std::ops::BitXorAssign for AxisValueTableFlags {
1259 #[inline]
1261 fn bitxor_assign(&mut self, other: Self) {
1262 self.bits ^= other.bits;
1263 }
1264}
1265
1266impl std::ops::BitAnd for AxisValueTableFlags {
1267 type Output = Self;
1268
1269 #[inline]
1271 fn bitand(self, other: Self) -> Self {
1272 Self {
1273 bits: self.bits & other.bits,
1274 }
1275 }
1276}
1277
1278impl std::ops::BitAndAssign for AxisValueTableFlags {
1279 #[inline]
1281 fn bitand_assign(&mut self, other: Self) {
1282 self.bits &= other.bits;
1283 }
1284}
1285
1286impl std::ops::Sub for AxisValueTableFlags {
1287 type Output = Self;
1288
1289 #[inline]
1291 fn sub(self, other: Self) -> Self {
1292 Self {
1293 bits: self.bits & !other.bits,
1294 }
1295 }
1296}
1297
1298impl std::ops::SubAssign for AxisValueTableFlags {
1299 #[inline]
1301 fn sub_assign(&mut self, other: Self) {
1302 self.bits &= !other.bits;
1303 }
1304}
1305
1306impl std::ops::Not for AxisValueTableFlags {
1307 type Output = Self;
1308
1309 #[inline]
1311 fn not(self) -> Self {
1312 Self { bits: !self.bits } & Self::all()
1313 }
1314}
1315
1316impl std::fmt::Debug for AxisValueTableFlags {
1317 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1318 let members: &[(&str, Self)] = &[
1319 (
1320 "OLDER_SIBLING_FONT_ATTRIBUTE",
1321 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1322 ),
1323 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1324 ];
1325 let mut first = true;
1326 for (name, value) in members {
1327 if self.contains(*value) {
1328 if !first {
1329 f.write_str(" | ")?;
1330 }
1331 first = false;
1332 f.write_str(name)?;
1333 }
1334 }
1335 if first {
1336 f.write_str("(empty)")?;
1337 }
1338 Ok(())
1339 }
1340}
1341
1342impl std::fmt::Binary for AxisValueTableFlags {
1343 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1344 std::fmt::Binary::fmt(&self.bits, f)
1345 }
1346}
1347
1348impl std::fmt::Octal for AxisValueTableFlags {
1349 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1350 std::fmt::Octal::fmt(&self.bits, f)
1351 }
1352}
1353
1354impl std::fmt::LowerHex for AxisValueTableFlags {
1355 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1356 std::fmt::LowerHex::fmt(&self.bits, f)
1357 }
1358}
1359
1360impl std::fmt::UpperHex for AxisValueTableFlags {
1361 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1362 std::fmt::UpperHex::fmt(&self.bits, f)
1363 }
1364}
1365
1366impl font_types::Scalar for AxisValueTableFlags {
1367 type Raw = <u16 as font_types::Scalar>::Raw;
1368 fn to_raw(self) -> Self::Raw {
1369 self.bits().to_raw()
1370 }
1371 fn from_raw(raw: Self::Raw) -> Self {
1372 let t = <u16>::from_raw(raw);
1373 Self::from_bits_truncate(t)
1374 }
1375}
1376
1377#[cfg(feature = "experimental_traverse")]
1378impl<'a> From<AxisValueTableFlags> for FieldType<'a> {
1379 fn from(src: AxisValueTableFlags) -> FieldType<'a> {
1380 src.bits().into()
1381 }
1382}