1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct StatMarker {
12 elided_fallback_name_id_byte_start: Option<usize>,
13}
14
15impl StatMarker {
16 pub fn version_byte_range(&self) -> Range<usize> {
17 let start = 0;
18 start..start + MajorMinor::RAW_BYTE_LEN
19 }
20
21 pub fn design_axis_size_byte_range(&self) -> Range<usize> {
22 let start = self.version_byte_range().end;
23 start..start + u16::RAW_BYTE_LEN
24 }
25
26 pub fn design_axis_count_byte_range(&self) -> Range<usize> {
27 let start = self.design_axis_size_byte_range().end;
28 start..start + u16::RAW_BYTE_LEN
29 }
30
31 pub fn design_axes_offset_byte_range(&self) -> Range<usize> {
32 let start = self.design_axis_count_byte_range().end;
33 start..start + Offset32::RAW_BYTE_LEN
34 }
35
36 pub fn axis_value_count_byte_range(&self) -> Range<usize> {
37 let start = self.design_axes_offset_byte_range().end;
38 start..start + u16::RAW_BYTE_LEN
39 }
40
41 pub fn offset_to_axis_value_offsets_byte_range(&self) -> Range<usize> {
42 let start = self.axis_value_count_byte_range().end;
43 start..start + Offset32::RAW_BYTE_LEN
44 }
45
46 pub fn elided_fallback_name_id_byte_range(&self) -> Option<Range<usize>> {
47 let start = self.elided_fallback_name_id_byte_start?;
48 Some(start..start + NameId::RAW_BYTE_LEN)
49 }
50}
51
52impl MinByteRange for StatMarker {
53 fn min_byte_range(&self) -> Range<usize> {
54 0..self.offset_to_axis_value_offsets_byte_range().end
55 }
56}
57
58impl TopLevelTable for Stat<'_> {
59 const TAG: Tag = Tag::new(b"STAT");
61}
62
63impl<'a> FontRead<'a> for Stat<'a> {
64 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
65 let mut cursor = data.cursor();
66 let version: MajorMinor = cursor.read()?;
67 cursor.advance::<u16>();
68 cursor.advance::<u16>();
69 cursor.advance::<Offset32>();
70 cursor.advance::<u16>();
71 cursor.advance::<Offset32>();
72 let elided_fallback_name_id_byte_start = version
73 .compatible((1u16, 1u16))
74 .then(|| cursor.position())
75 .transpose()?;
76 version
77 .compatible((1u16, 1u16))
78 .then(|| cursor.advance::<NameId>());
79 cursor.finish(StatMarker {
80 elided_fallback_name_id_byte_start,
81 })
82 }
83}
84
85pub type Stat<'a> = TableRef<'a, StatMarker>;
87
88#[allow(clippy::needless_lifetimes)]
89impl<'a> Stat<'a> {
90 pub fn version(&self) -> MajorMinor {
92 let range = self.shape.version_byte_range();
93 self.data.read_at(range.start).unwrap()
94 }
95
96 pub fn design_axis_size(&self) -> u16 {
98 let range = self.shape.design_axis_size_byte_range();
99 self.data.read_at(range.start).unwrap()
100 }
101
102 pub fn design_axis_count(&self) -> u16 {
107 let range = self.shape.design_axis_count_byte_range();
108 self.data.read_at(range.start).unwrap()
109 }
110
111 pub fn design_axes_offset(&self) -> Offset32 {
116 let range = self.shape.design_axes_offset_byte_range();
117 self.data.read_at(range.start).unwrap()
118 }
119
120 pub fn design_axes(&self) -> Result<&'a [AxisRecord], ReadError> {
122 let data = self.data;
123 let args = self.design_axis_count();
124 self.design_axes_offset().resolve_with_args(data, &args)
125 }
126
127 pub fn axis_value_count(&self) -> u16 {
129 let range = self.shape.axis_value_count_byte_range();
130 self.data.read_at(range.start).unwrap()
131 }
132
133 pub fn offset_to_axis_value_offsets(&self) -> Nullable<Offset32> {
138 let range = self.shape.offset_to_axis_value_offsets_byte_range();
139 self.data.read_at(range.start).unwrap()
140 }
141
142 pub fn offset_to_axis_values(&self) -> Option<Result<AxisValueArray<'a>, ReadError>> {
144 let data = self.data;
145 let args = self.axis_value_count();
146 self.offset_to_axis_value_offsets()
147 .resolve_with_args(data, &args)
148 }
149
150 pub fn elided_fallback_name_id(&self) -> Option<NameId> {
154 let range = self.shape.elided_fallback_name_id_byte_range()?;
155 Some(self.data.read_at(range.start).unwrap())
156 }
157}
158
159#[cfg(feature = "experimental_traverse")]
160impl<'a> SomeTable<'a> for Stat<'a> {
161 fn type_name(&self) -> &str {
162 "Stat"
163 }
164 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
165 let version = self.version();
166 match idx {
167 0usize => Some(Field::new("version", self.version())),
168 1usize => Some(Field::new("design_axis_size", self.design_axis_size())),
169 2usize => Some(Field::new("design_axis_count", self.design_axis_count())),
170 3usize => Some(Field::new(
171 "design_axes_offset",
172 traversal::FieldType::offset_to_array_of_records(
173 self.design_axes_offset(),
174 self.design_axes(),
175 stringify!(AxisRecord),
176 self.offset_data(),
177 ),
178 )),
179 4usize => Some(Field::new("axis_value_count", self.axis_value_count())),
180 5usize => Some(Field::new(
181 "offset_to_axis_value_offsets",
182 FieldType::offset(
183 self.offset_to_axis_value_offsets(),
184 self.offset_to_axis_values(),
185 ),
186 )),
187 6usize if version.compatible((1u16, 1u16)) => Some(Field::new(
188 "elided_fallback_name_id",
189 self.elided_fallback_name_id().unwrap(),
190 )),
191 _ => None,
192 }
193 }
194}
195
196#[cfg(feature = "experimental_traverse")]
197#[allow(clippy::needless_lifetimes)]
198impl<'a> std::fmt::Debug for Stat<'a> {
199 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 (self as &dyn SomeTable<'a>).fmt(f)
201 }
202}
203
204#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
206#[repr(C)]
207#[repr(packed)]
208pub struct AxisRecord {
209 pub axis_tag: BigEndian<Tag>,
211 pub axis_name_id: BigEndian<NameId>,
214 pub axis_ordering: BigEndian<u16>,
218}
219
220impl AxisRecord {
221 pub fn axis_tag(&self) -> Tag {
223 self.axis_tag.get()
224 }
225
226 pub fn axis_name_id(&self) -> NameId {
229 self.axis_name_id.get()
230 }
231
232 pub fn axis_ordering(&self) -> u16 {
236 self.axis_ordering.get()
237 }
238}
239
240impl FixedSize for AxisRecord {
241 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
242}
243
244#[cfg(feature = "experimental_traverse")]
245impl<'a> SomeRecord<'a> for AxisRecord {
246 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
247 RecordResolver {
248 name: "AxisRecord",
249 get_field: Box::new(move |idx, _data| match idx {
250 0usize => Some(Field::new("axis_tag", self.axis_tag())),
251 1usize => Some(Field::new("axis_name_id", self.axis_name_id())),
252 2usize => Some(Field::new("axis_ordering", self.axis_ordering())),
253 _ => None,
254 }),
255 data,
256 }
257 }
258}
259
260#[derive(Debug, Clone, Copy)]
262#[doc(hidden)]
263pub struct AxisValueArrayMarker {
264 axis_value_offsets_byte_len: usize,
265}
266
267impl AxisValueArrayMarker {
268 pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
269 let start = 0;
270 start..start + self.axis_value_offsets_byte_len
271 }
272}
273
274impl MinByteRange for AxisValueArrayMarker {
275 fn min_byte_range(&self) -> Range<usize> {
276 0..self.axis_value_offsets_byte_range().end
277 }
278}
279
280impl ReadArgs for AxisValueArray<'_> {
281 type Args = u16;
282}
283
284impl<'a> FontReadWithArgs<'a> for AxisValueArray<'a> {
285 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
286 let axis_value_count = *args;
287 let mut cursor = data.cursor();
288 let axis_value_offsets_byte_len = (axis_value_count as usize)
289 .checked_mul(Offset16::RAW_BYTE_LEN)
290 .ok_or(ReadError::OutOfBounds)?;
291 cursor.advance_by(axis_value_offsets_byte_len);
292 cursor.finish(AxisValueArrayMarker {
293 axis_value_offsets_byte_len,
294 })
295 }
296}
297
298impl<'a> AxisValueArray<'a> {
299 pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
304 let args = axis_value_count;
305 Self::read_with_args(data, &args)
306 }
307}
308
309pub type AxisValueArray<'a> = TableRef<'a, AxisValueArrayMarker>;
311
312#[allow(clippy::needless_lifetimes)]
313impl<'a> AxisValueArray<'a> {
314 pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
317 let range = self.shape.axis_value_offsets_byte_range();
318 self.data.read_array(range).unwrap()
319 }
320
321 pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
323 let data = self.data;
324 let offsets = self.axis_value_offsets();
325 ArrayOfOffsets::new(offsets, data, ())
326 }
327}
328
329#[cfg(feature = "experimental_traverse")]
330impl<'a> SomeTable<'a> for AxisValueArray<'a> {
331 fn type_name(&self) -> &str {
332 "AxisValueArray"
333 }
334 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
335 match idx {
336 0usize => Some({
337 let data = self.data;
338 Field::new(
339 "axis_value_offsets",
340 FieldType::array_of_offsets(
341 better_type_name::<AxisValue>(),
342 self.axis_value_offsets(),
343 move |off| {
344 let target = off.get().resolve::<AxisValue>(data);
345 FieldType::offset(off.get(), target)
346 },
347 ),
348 )
349 }),
350 _ => None,
351 }
352 }
353}
354
355#[cfg(feature = "experimental_traverse")]
356#[allow(clippy::needless_lifetimes)]
357impl<'a> std::fmt::Debug for AxisValueArray<'a> {
358 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
359 (self as &dyn SomeTable<'a>).fmt(f)
360 }
361}
362
363#[derive(Clone)]
365pub enum AxisValue<'a> {
366 Format1(AxisValueFormat1<'a>),
367 Format2(AxisValueFormat2<'a>),
368 Format3(AxisValueFormat3<'a>),
369 Format4(AxisValueFormat4<'a>),
370}
371
372impl<'a> AxisValue<'a> {
373 pub fn offset_data(&self) -> FontData<'a> {
375 match self {
376 Self::Format1(item) => item.offset_data(),
377 Self::Format2(item) => item.offset_data(),
378 Self::Format3(item) => item.offset_data(),
379 Self::Format4(item) => item.offset_data(),
380 }
381 }
382
383 pub fn format(&self) -> u16 {
385 match self {
386 Self::Format1(item) => item.format(),
387 Self::Format2(item) => item.format(),
388 Self::Format3(item) => item.format(),
389 Self::Format4(item) => item.format(),
390 }
391 }
392
393 pub fn flags(&self) -> AxisValueTableFlags {
395 match self {
396 Self::Format1(item) => item.flags(),
397 Self::Format2(item) => item.flags(),
398 Self::Format3(item) => item.flags(),
399 Self::Format4(item) => item.flags(),
400 }
401 }
402
403 pub fn value_name_id(&self) -> NameId {
406 match self {
407 Self::Format1(item) => item.value_name_id(),
408 Self::Format2(item) => item.value_name_id(),
409 Self::Format3(item) => item.value_name_id(),
410 Self::Format4(item) => item.value_name_id(),
411 }
412 }
413}
414
415impl<'a> FontRead<'a> for AxisValue<'a> {
416 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
417 let format: u16 = data.read_at(0usize)?;
418 match format {
419 AxisValueFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
420 AxisValueFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
421 AxisValueFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
422 AxisValueFormat4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
423 other => Err(ReadError::InvalidFormat(other.into())),
424 }
425 }
426}
427
428impl MinByteRange for AxisValue<'_> {
429 fn min_byte_range(&self) -> Range<usize> {
430 match self {
431 Self::Format1(item) => item.min_byte_range(),
432 Self::Format2(item) => item.min_byte_range(),
433 Self::Format3(item) => item.min_byte_range(),
434 Self::Format4(item) => item.min_byte_range(),
435 }
436 }
437}
438
439#[cfg(feature = "experimental_traverse")]
440impl<'a> AxisValue<'a> {
441 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
442 match self {
443 Self::Format1(table) => table,
444 Self::Format2(table) => table,
445 Self::Format3(table) => table,
446 Self::Format4(table) => table,
447 }
448 }
449}
450
451#[cfg(feature = "experimental_traverse")]
452impl std::fmt::Debug for AxisValue<'_> {
453 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
454 self.dyn_inner().fmt(f)
455 }
456}
457
458#[cfg(feature = "experimental_traverse")]
459impl<'a> SomeTable<'a> for AxisValue<'a> {
460 fn type_name(&self) -> &str {
461 self.dyn_inner().type_name()
462 }
463 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
464 self.dyn_inner().get_field(idx)
465 }
466}
467
468impl Format<u16> for AxisValueFormat1Marker {
469 const FORMAT: u16 = 1;
470}
471
472#[derive(Debug, Clone, Copy)]
474#[doc(hidden)]
475pub struct AxisValueFormat1Marker {}
476
477impl AxisValueFormat1Marker {
478 pub fn format_byte_range(&self) -> Range<usize> {
479 let start = 0;
480 start..start + u16::RAW_BYTE_LEN
481 }
482
483 pub fn axis_index_byte_range(&self) -> Range<usize> {
484 let start = self.format_byte_range().end;
485 start..start + u16::RAW_BYTE_LEN
486 }
487
488 pub fn flags_byte_range(&self) -> Range<usize> {
489 let start = self.axis_index_byte_range().end;
490 start..start + AxisValueTableFlags::RAW_BYTE_LEN
491 }
492
493 pub fn value_name_id_byte_range(&self) -> Range<usize> {
494 let start = self.flags_byte_range().end;
495 start..start + NameId::RAW_BYTE_LEN
496 }
497
498 pub fn value_byte_range(&self) -> Range<usize> {
499 let start = self.value_name_id_byte_range().end;
500 start..start + Fixed::RAW_BYTE_LEN
501 }
502}
503
504impl MinByteRange for AxisValueFormat1Marker {
505 fn min_byte_range(&self) -> Range<usize> {
506 0..self.value_byte_range().end
507 }
508}
509
510impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
511 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
512 let mut cursor = data.cursor();
513 cursor.advance::<u16>();
514 cursor.advance::<u16>();
515 cursor.advance::<AxisValueTableFlags>();
516 cursor.advance::<NameId>();
517 cursor.advance::<Fixed>();
518 cursor.finish(AxisValueFormat1Marker {})
519 }
520}
521
522pub type AxisValueFormat1<'a> = TableRef<'a, AxisValueFormat1Marker>;
524
525#[allow(clippy::needless_lifetimes)]
526impl<'a> AxisValueFormat1<'a> {
527 pub fn format(&self) -> u16 {
529 let range = self.shape.format_byte_range();
530 self.data.read_at(range.start).unwrap()
531 }
532
533 pub fn axis_index(&self) -> u16 {
537 let range = self.shape.axis_index_byte_range();
538 self.data.read_at(range.start).unwrap()
539 }
540
541 pub fn flags(&self) -> AxisValueTableFlags {
543 let range = self.shape.flags_byte_range();
544 self.data.read_at(range.start).unwrap()
545 }
546
547 pub fn value_name_id(&self) -> NameId {
550 let range = self.shape.value_name_id_byte_range();
551 self.data.read_at(range.start).unwrap()
552 }
553
554 pub fn value(&self) -> Fixed {
556 let range = self.shape.value_byte_range();
557 self.data.read_at(range.start).unwrap()
558 }
559}
560
561#[cfg(feature = "experimental_traverse")]
562impl<'a> SomeTable<'a> for AxisValueFormat1<'a> {
563 fn type_name(&self) -> &str {
564 "AxisValueFormat1"
565 }
566 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
567 match idx {
568 0usize => Some(Field::new("format", self.format())),
569 1usize => Some(Field::new("axis_index", self.axis_index())),
570 2usize => Some(Field::new("flags", self.flags())),
571 3usize => Some(Field::new("value_name_id", self.value_name_id())),
572 4usize => Some(Field::new("value", self.value())),
573 _ => None,
574 }
575 }
576}
577
578#[cfg(feature = "experimental_traverse")]
579#[allow(clippy::needless_lifetimes)]
580impl<'a> std::fmt::Debug for AxisValueFormat1<'a> {
581 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
582 (self as &dyn SomeTable<'a>).fmt(f)
583 }
584}
585
586impl Format<u16> for AxisValueFormat2Marker {
587 const FORMAT: u16 = 2;
588}
589
590#[derive(Debug, Clone, Copy)]
592#[doc(hidden)]
593pub struct AxisValueFormat2Marker {}
594
595impl AxisValueFormat2Marker {
596 pub fn format_byte_range(&self) -> Range<usize> {
597 let start = 0;
598 start..start + u16::RAW_BYTE_LEN
599 }
600
601 pub fn axis_index_byte_range(&self) -> Range<usize> {
602 let start = self.format_byte_range().end;
603 start..start + u16::RAW_BYTE_LEN
604 }
605
606 pub fn flags_byte_range(&self) -> Range<usize> {
607 let start = self.axis_index_byte_range().end;
608 start..start + AxisValueTableFlags::RAW_BYTE_LEN
609 }
610
611 pub fn value_name_id_byte_range(&self) -> Range<usize> {
612 let start = self.flags_byte_range().end;
613 start..start + NameId::RAW_BYTE_LEN
614 }
615
616 pub fn nominal_value_byte_range(&self) -> Range<usize> {
617 let start = self.value_name_id_byte_range().end;
618 start..start + Fixed::RAW_BYTE_LEN
619 }
620
621 pub fn range_min_value_byte_range(&self) -> Range<usize> {
622 let start = self.nominal_value_byte_range().end;
623 start..start + Fixed::RAW_BYTE_LEN
624 }
625
626 pub fn range_max_value_byte_range(&self) -> Range<usize> {
627 let start = self.range_min_value_byte_range().end;
628 start..start + Fixed::RAW_BYTE_LEN
629 }
630}
631
632impl MinByteRange for AxisValueFormat2Marker {
633 fn min_byte_range(&self) -> Range<usize> {
634 0..self.range_max_value_byte_range().end
635 }
636}
637
638impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
639 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
640 let mut cursor = data.cursor();
641 cursor.advance::<u16>();
642 cursor.advance::<u16>();
643 cursor.advance::<AxisValueTableFlags>();
644 cursor.advance::<NameId>();
645 cursor.advance::<Fixed>();
646 cursor.advance::<Fixed>();
647 cursor.advance::<Fixed>();
648 cursor.finish(AxisValueFormat2Marker {})
649 }
650}
651
652pub type AxisValueFormat2<'a> = TableRef<'a, AxisValueFormat2Marker>;
654
655#[allow(clippy::needless_lifetimes)]
656impl<'a> AxisValueFormat2<'a> {
657 pub fn format(&self) -> u16 {
659 let range = self.shape.format_byte_range();
660 self.data.read_at(range.start).unwrap()
661 }
662
663 pub fn axis_index(&self) -> u16 {
667 let range = self.shape.axis_index_byte_range();
668 self.data.read_at(range.start).unwrap()
669 }
670
671 pub fn flags(&self) -> AxisValueTableFlags {
673 let range = self.shape.flags_byte_range();
674 self.data.read_at(range.start).unwrap()
675 }
676
677 pub fn value_name_id(&self) -> NameId {
680 let range = self.shape.value_name_id_byte_range();
681 self.data.read_at(range.start).unwrap()
682 }
683
684 pub fn nominal_value(&self) -> Fixed {
686 let range = self.shape.nominal_value_byte_range();
687 self.data.read_at(range.start).unwrap()
688 }
689
690 pub fn range_min_value(&self) -> Fixed {
693 let range = self.shape.range_min_value_byte_range();
694 self.data.read_at(range.start).unwrap()
695 }
696
697 pub fn range_max_value(&self) -> Fixed {
700 let range = self.shape.range_max_value_byte_range();
701 self.data.read_at(range.start).unwrap()
702 }
703}
704
705#[cfg(feature = "experimental_traverse")]
706impl<'a> SomeTable<'a> for AxisValueFormat2<'a> {
707 fn type_name(&self) -> &str {
708 "AxisValueFormat2"
709 }
710 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
711 match idx {
712 0usize => Some(Field::new("format", self.format())),
713 1usize => Some(Field::new("axis_index", self.axis_index())),
714 2usize => Some(Field::new("flags", self.flags())),
715 3usize => Some(Field::new("value_name_id", self.value_name_id())),
716 4usize => Some(Field::new("nominal_value", self.nominal_value())),
717 5usize => Some(Field::new("range_min_value", self.range_min_value())),
718 6usize => Some(Field::new("range_max_value", self.range_max_value())),
719 _ => None,
720 }
721 }
722}
723
724#[cfg(feature = "experimental_traverse")]
725#[allow(clippy::needless_lifetimes)]
726impl<'a> std::fmt::Debug for AxisValueFormat2<'a> {
727 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
728 (self as &dyn SomeTable<'a>).fmt(f)
729 }
730}
731
732impl Format<u16> for AxisValueFormat3Marker {
733 const FORMAT: u16 = 3;
734}
735
736#[derive(Debug, Clone, Copy)]
738#[doc(hidden)]
739pub struct AxisValueFormat3Marker {}
740
741impl AxisValueFormat3Marker {
742 pub fn format_byte_range(&self) -> Range<usize> {
743 let start = 0;
744 start..start + u16::RAW_BYTE_LEN
745 }
746
747 pub fn axis_index_byte_range(&self) -> Range<usize> {
748 let start = self.format_byte_range().end;
749 start..start + u16::RAW_BYTE_LEN
750 }
751
752 pub fn flags_byte_range(&self) -> Range<usize> {
753 let start = self.axis_index_byte_range().end;
754 start..start + AxisValueTableFlags::RAW_BYTE_LEN
755 }
756
757 pub fn value_name_id_byte_range(&self) -> Range<usize> {
758 let start = self.flags_byte_range().end;
759 start..start + NameId::RAW_BYTE_LEN
760 }
761
762 pub fn value_byte_range(&self) -> Range<usize> {
763 let start = self.value_name_id_byte_range().end;
764 start..start + Fixed::RAW_BYTE_LEN
765 }
766
767 pub fn linked_value_byte_range(&self) -> Range<usize> {
768 let start = self.value_byte_range().end;
769 start..start + Fixed::RAW_BYTE_LEN
770 }
771}
772
773impl MinByteRange for AxisValueFormat3Marker {
774 fn min_byte_range(&self) -> Range<usize> {
775 0..self.linked_value_byte_range().end
776 }
777}
778
779impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
780 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
781 let mut cursor = data.cursor();
782 cursor.advance::<u16>();
783 cursor.advance::<u16>();
784 cursor.advance::<AxisValueTableFlags>();
785 cursor.advance::<NameId>();
786 cursor.advance::<Fixed>();
787 cursor.advance::<Fixed>();
788 cursor.finish(AxisValueFormat3Marker {})
789 }
790}
791
792pub type AxisValueFormat3<'a> = TableRef<'a, AxisValueFormat3Marker>;
794
795#[allow(clippy::needless_lifetimes)]
796impl<'a> AxisValueFormat3<'a> {
797 pub fn format(&self) -> u16 {
799 let range = self.shape.format_byte_range();
800 self.data.read_at(range.start).unwrap()
801 }
802
803 pub fn axis_index(&self) -> u16 {
807 let range = self.shape.axis_index_byte_range();
808 self.data.read_at(range.start).unwrap()
809 }
810
811 pub fn flags(&self) -> AxisValueTableFlags {
813 let range = self.shape.flags_byte_range();
814 self.data.read_at(range.start).unwrap()
815 }
816
817 pub fn value_name_id(&self) -> NameId {
820 let range = self.shape.value_name_id_byte_range();
821 self.data.read_at(range.start).unwrap()
822 }
823
824 pub fn value(&self) -> Fixed {
826 let range = self.shape.value_byte_range();
827 self.data.read_at(range.start).unwrap()
828 }
829
830 pub fn linked_value(&self) -> Fixed {
832 let range = self.shape.linked_value_byte_range();
833 self.data.read_at(range.start).unwrap()
834 }
835}
836
837#[cfg(feature = "experimental_traverse")]
838impl<'a> SomeTable<'a> for AxisValueFormat3<'a> {
839 fn type_name(&self) -> &str {
840 "AxisValueFormat3"
841 }
842 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
843 match idx {
844 0usize => Some(Field::new("format", self.format())),
845 1usize => Some(Field::new("axis_index", self.axis_index())),
846 2usize => Some(Field::new("flags", self.flags())),
847 3usize => Some(Field::new("value_name_id", self.value_name_id())),
848 4usize => Some(Field::new("value", self.value())),
849 5usize => Some(Field::new("linked_value", self.linked_value())),
850 _ => None,
851 }
852 }
853}
854
855#[cfg(feature = "experimental_traverse")]
856#[allow(clippy::needless_lifetimes)]
857impl<'a> std::fmt::Debug for AxisValueFormat3<'a> {
858 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
859 (self as &dyn SomeTable<'a>).fmt(f)
860 }
861}
862
863impl Format<u16> for AxisValueFormat4Marker {
864 const FORMAT: u16 = 4;
865}
866
867#[derive(Debug, Clone, Copy)]
869#[doc(hidden)]
870pub struct AxisValueFormat4Marker {
871 axis_values_byte_len: usize,
872}
873
874impl AxisValueFormat4Marker {
875 pub fn format_byte_range(&self) -> Range<usize> {
876 let start = 0;
877 start..start + u16::RAW_BYTE_LEN
878 }
879
880 pub fn axis_count_byte_range(&self) -> Range<usize> {
881 let start = self.format_byte_range().end;
882 start..start + u16::RAW_BYTE_LEN
883 }
884
885 pub fn flags_byte_range(&self) -> Range<usize> {
886 let start = self.axis_count_byte_range().end;
887 start..start + AxisValueTableFlags::RAW_BYTE_LEN
888 }
889
890 pub fn value_name_id_byte_range(&self) -> Range<usize> {
891 let start = self.flags_byte_range().end;
892 start..start + NameId::RAW_BYTE_LEN
893 }
894
895 pub fn axis_values_byte_range(&self) -> Range<usize> {
896 let start = self.value_name_id_byte_range().end;
897 start..start + self.axis_values_byte_len
898 }
899}
900
901impl MinByteRange for AxisValueFormat4Marker {
902 fn min_byte_range(&self) -> Range<usize> {
903 0..self.axis_values_byte_range().end
904 }
905}
906
907impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
908 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
909 let mut cursor = data.cursor();
910 cursor.advance::<u16>();
911 let axis_count: u16 = cursor.read()?;
912 cursor.advance::<AxisValueTableFlags>();
913 cursor.advance::<NameId>();
914 let axis_values_byte_len = (axis_count as usize)
915 .checked_mul(AxisValueRecord::RAW_BYTE_LEN)
916 .ok_or(ReadError::OutOfBounds)?;
917 cursor.advance_by(axis_values_byte_len);
918 cursor.finish(AxisValueFormat4Marker {
919 axis_values_byte_len,
920 })
921 }
922}
923
924pub type AxisValueFormat4<'a> = TableRef<'a, AxisValueFormat4Marker>;
926
927#[allow(clippy::needless_lifetimes)]
928impl<'a> AxisValueFormat4<'a> {
929 pub fn format(&self) -> u16 {
931 let range = self.shape.format_byte_range();
932 self.data.read_at(range.start).unwrap()
933 }
934
935 pub fn axis_count(&self) -> u16 {
938 let range = self.shape.axis_count_byte_range();
939 self.data.read_at(range.start).unwrap()
940 }
941
942 pub fn flags(&self) -> AxisValueTableFlags {
944 let range = self.shape.flags_byte_range();
945 self.data.read_at(range.start).unwrap()
946 }
947
948 pub fn value_name_id(&self) -> NameId {
951 let range = self.shape.value_name_id_byte_range();
952 self.data.read_at(range.start).unwrap()
953 }
954
955 pub fn axis_values(&self) -> &'a [AxisValueRecord] {
958 let range = self.shape.axis_values_byte_range();
959 self.data.read_array(range).unwrap()
960 }
961}
962
963#[cfg(feature = "experimental_traverse")]
964impl<'a> SomeTable<'a> for AxisValueFormat4<'a> {
965 fn type_name(&self) -> &str {
966 "AxisValueFormat4"
967 }
968 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
969 match idx {
970 0usize => Some(Field::new("format", self.format())),
971 1usize => Some(Field::new("axis_count", self.axis_count())),
972 2usize => Some(Field::new("flags", self.flags())),
973 3usize => Some(Field::new("value_name_id", self.value_name_id())),
974 4usize => Some(Field::new(
975 "axis_values",
976 traversal::FieldType::array_of_records(
977 stringify!(AxisValueRecord),
978 self.axis_values(),
979 self.offset_data(),
980 ),
981 )),
982 _ => None,
983 }
984 }
985}
986
987#[cfg(feature = "experimental_traverse")]
988#[allow(clippy::needless_lifetimes)]
989impl<'a> std::fmt::Debug for AxisValueFormat4<'a> {
990 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
991 (self as &dyn SomeTable<'a>).fmt(f)
992 }
993}
994
995#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
997#[repr(C)]
998#[repr(packed)]
999pub struct AxisValueRecord {
1000 pub axis_index: BigEndian<u16>,
1003 pub value: BigEndian<Fixed>,
1005}
1006
1007impl AxisValueRecord {
1008 pub fn axis_index(&self) -> u16 {
1011 self.axis_index.get()
1012 }
1013
1014 pub fn value(&self) -> Fixed {
1016 self.value.get()
1017 }
1018}
1019
1020impl FixedSize for AxisValueRecord {
1021 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1022}
1023
1024#[cfg(feature = "experimental_traverse")]
1025impl<'a> SomeRecord<'a> for AxisValueRecord {
1026 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1027 RecordResolver {
1028 name: "AxisValueRecord",
1029 get_field: Box::new(move |idx, _data| match idx {
1030 0usize => Some(Field::new("axis_index", self.axis_index())),
1031 1usize => Some(Field::new("value", self.value())),
1032 _ => None,
1033 }),
1034 data,
1035 }
1036 }
1037}
1038
1039#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1041#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1042#[repr(transparent)]
1043pub struct AxisValueTableFlags {
1044 bits: u16,
1045}
1046
1047impl AxisValueTableFlags {
1048 pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1055
1056 pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1060}
1061
1062impl AxisValueTableFlags {
1063 #[inline]
1065 pub const fn empty() -> Self {
1066 Self { bits: 0 }
1067 }
1068
1069 #[inline]
1071 pub const fn all() -> Self {
1072 Self {
1073 bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1074 }
1075 }
1076
1077 #[inline]
1079 pub const fn bits(&self) -> u16 {
1080 self.bits
1081 }
1082
1083 #[inline]
1086 pub const fn from_bits(bits: u16) -> Option<Self> {
1087 if (bits & !Self::all().bits()) == 0 {
1088 Some(Self { bits })
1089 } else {
1090 None
1091 }
1092 }
1093
1094 #[inline]
1097 pub const fn from_bits_truncate(bits: u16) -> Self {
1098 Self {
1099 bits: bits & Self::all().bits,
1100 }
1101 }
1102
1103 #[inline]
1105 pub const fn is_empty(&self) -> bool {
1106 self.bits() == Self::empty().bits()
1107 }
1108
1109 #[inline]
1111 pub const fn intersects(&self, other: Self) -> bool {
1112 !(Self {
1113 bits: self.bits & other.bits,
1114 })
1115 .is_empty()
1116 }
1117
1118 #[inline]
1120 pub const fn contains(&self, other: Self) -> bool {
1121 (self.bits & other.bits) == other.bits
1122 }
1123
1124 #[inline]
1126 pub fn insert(&mut self, other: Self) {
1127 self.bits |= other.bits;
1128 }
1129
1130 #[inline]
1132 pub fn remove(&mut self, other: Self) {
1133 self.bits &= !other.bits;
1134 }
1135
1136 #[inline]
1138 pub fn toggle(&mut self, other: Self) {
1139 self.bits ^= other.bits;
1140 }
1141
1142 #[inline]
1153 #[must_use]
1154 pub const fn intersection(self, other: Self) -> Self {
1155 Self {
1156 bits: self.bits & other.bits,
1157 }
1158 }
1159
1160 #[inline]
1171 #[must_use]
1172 pub const fn union(self, other: Self) -> Self {
1173 Self {
1174 bits: self.bits | other.bits,
1175 }
1176 }
1177
1178 #[inline]
1191 #[must_use]
1192 pub const fn difference(self, other: Self) -> Self {
1193 Self {
1194 bits: self.bits & !other.bits,
1195 }
1196 }
1197}
1198
1199impl std::ops::BitOr for AxisValueTableFlags {
1200 type Output = Self;
1201
1202 #[inline]
1204 fn bitor(self, other: AxisValueTableFlags) -> Self {
1205 Self {
1206 bits: self.bits | other.bits,
1207 }
1208 }
1209}
1210
1211impl std::ops::BitOrAssign for AxisValueTableFlags {
1212 #[inline]
1214 fn bitor_assign(&mut self, other: Self) {
1215 self.bits |= other.bits;
1216 }
1217}
1218
1219impl std::ops::BitXor for AxisValueTableFlags {
1220 type Output = Self;
1221
1222 #[inline]
1224 fn bitxor(self, other: Self) -> Self {
1225 Self {
1226 bits: self.bits ^ other.bits,
1227 }
1228 }
1229}
1230
1231impl std::ops::BitXorAssign for AxisValueTableFlags {
1232 #[inline]
1234 fn bitxor_assign(&mut self, other: Self) {
1235 self.bits ^= other.bits;
1236 }
1237}
1238
1239impl std::ops::BitAnd for AxisValueTableFlags {
1240 type Output = Self;
1241
1242 #[inline]
1244 fn bitand(self, other: Self) -> Self {
1245 Self {
1246 bits: self.bits & other.bits,
1247 }
1248 }
1249}
1250
1251impl std::ops::BitAndAssign for AxisValueTableFlags {
1252 #[inline]
1254 fn bitand_assign(&mut self, other: Self) {
1255 self.bits &= other.bits;
1256 }
1257}
1258
1259impl std::ops::Sub for AxisValueTableFlags {
1260 type Output = Self;
1261
1262 #[inline]
1264 fn sub(self, other: Self) -> Self {
1265 Self {
1266 bits: self.bits & !other.bits,
1267 }
1268 }
1269}
1270
1271impl std::ops::SubAssign for AxisValueTableFlags {
1272 #[inline]
1274 fn sub_assign(&mut self, other: Self) {
1275 self.bits &= !other.bits;
1276 }
1277}
1278
1279impl std::ops::Not for AxisValueTableFlags {
1280 type Output = Self;
1281
1282 #[inline]
1284 fn not(self) -> Self {
1285 Self { bits: !self.bits } & Self::all()
1286 }
1287}
1288
1289impl std::fmt::Debug for AxisValueTableFlags {
1290 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1291 let members: &[(&str, Self)] = &[
1292 (
1293 "OLDER_SIBLING_FONT_ATTRIBUTE",
1294 Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1295 ),
1296 ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1297 ];
1298 let mut first = true;
1299 for (name, value) in members {
1300 if self.contains(*value) {
1301 if !first {
1302 f.write_str(" | ")?;
1303 }
1304 first = false;
1305 f.write_str(name)?;
1306 }
1307 }
1308 if first {
1309 f.write_str("(empty)")?;
1310 }
1311 Ok(())
1312 }
1313}
1314
1315impl std::fmt::Binary for AxisValueTableFlags {
1316 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1317 std::fmt::Binary::fmt(&self.bits, f)
1318 }
1319}
1320
1321impl std::fmt::Octal for AxisValueTableFlags {
1322 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1323 std::fmt::Octal::fmt(&self.bits, f)
1324 }
1325}
1326
1327impl std::fmt::LowerHex for AxisValueTableFlags {
1328 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1329 std::fmt::LowerHex::fmt(&self.bits, f)
1330 }
1331}
1332
1333impl std::fmt::UpperHex for AxisValueTableFlags {
1334 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1335 std::fmt::UpperHex::fmt(&self.bits, f)
1336 }
1337}
1338
1339impl font_types::Scalar for AxisValueTableFlags {
1340 type Raw = <u16 as font_types::Scalar>::Raw;
1341 fn to_raw(self) -> Self::Raw {
1342 self.bits().to_raw()
1343 }
1344 fn from_raw(raw: Self::Raw) -> Self {
1345 let t = <u16>::from_raw(raw);
1346 Self::from_bits_truncate(t)
1347 }
1348}
1349
1350#[cfg(feature = "experimental_traverse")]
1351impl<'a> From<AxisValueTableFlags> for FieldType<'a> {
1352 fn from(src: AxisValueTableFlags) -> FieldType<'a> {
1353 src.bits().into()
1354 }
1355}