1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Gvar<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.glyph_variation_data_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 Gvar<'_> {
19 const TAG: Tag = Tag::new(b"gvar");
21}
22
23impl ReadArgs for Gvar<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Gvar<'a> {
28 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
29 #[allow(clippy::absurd_extreme_comparisons)]
30 if data.len() < Self::MIN_SIZE {
31 return Err(ReadError::OutOfBounds);
32 }
33 Ok(Self { data })
34 }
35}
36
37#[derive(Clone)]
39pub struct Gvar<'a> {
40 data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Gvar<'a> {
45 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
46 + u16::RAW_BYTE_LEN
47 + u16::RAW_BYTE_LEN
48 + Offset32::RAW_BYTE_LEN
49 + u16::RAW_BYTE_LEN
50 + GvarFlags::RAW_BYTE_LEN
51 + u32::RAW_BYTE_LEN);
52 basic_table_impls!(impl_the_methods);
53
54 pub fn version(&self) -> MajorMinor {
56 let range = self.version_byte_range();
57 self.data.read_at(range.start).ok().unwrap()
58 }
59
60 pub fn axis_count(&self) -> u16 {
63 let range = self.axis_count_byte_range();
64 self.data.read_at(range.start).ok().unwrap()
65 }
66
67 pub fn shared_tuple_count(&self) -> u16 {
72 let range = self.shared_tuple_count_byte_range();
73 self.data.read_at(range.start).ok().unwrap()
74 }
75
76 pub fn shared_tuples_offset(&self) -> Offset32 {
78 let range = self.shared_tuples_offset_byte_range();
79 self.data.read_at(range.start).ok().unwrap()
80 }
81
82 pub fn shared_tuples(&self) -> Result<SharedTuples<'a>, ReadError> {
84 let data = self.data;
85 let args = (self.shared_tuple_count(), self.axis_count());
86 self.shared_tuples_offset().resolve_with_args(data, args)
87 }
88
89 pub fn glyph_count(&self) -> u16 {
92 let range = self.glyph_count_byte_range();
93 self.data.read_at(range.start).ok().unwrap()
94 }
95
96 pub fn flags(&self) -> GvarFlags {
100 let range = self.flags_byte_range();
101 self.data.read_at(range.start).ok().unwrap()
102 }
103
104 pub fn glyph_variation_data_array_offset(&self) -> u32 {
107 let range = self.glyph_variation_data_array_offset_byte_range();
108 self.data.read_at(range.start).ok().unwrap()
109 }
110
111 pub fn glyph_variation_data_offsets(&self) -> ComputedArray<'a, U16Or32> {
114 let range = self.glyph_variation_data_offsets_byte_range();
115 self.data
116 .read_with_args(range, self.flags())
117 .unwrap_or_default()
118 }
119
120 pub fn version_byte_range(&self) -> Range<usize> {
121 let start = 0;
122 let end = start + MajorMinor::RAW_BYTE_LEN;
123 start..end
124 }
125
126 pub fn axis_count_byte_range(&self) -> Range<usize> {
127 let start = self.version_byte_range().end;
128 let end = start + u16::RAW_BYTE_LEN;
129 start..end
130 }
131
132 pub fn shared_tuple_count_byte_range(&self) -> Range<usize> {
133 let start = self.axis_count_byte_range().end;
134 let end = start + u16::RAW_BYTE_LEN;
135 start..end
136 }
137
138 pub fn shared_tuples_offset_byte_range(&self) -> Range<usize> {
139 let start = self.shared_tuple_count_byte_range().end;
140 let end = start + Offset32::RAW_BYTE_LEN;
141 start..end
142 }
143
144 pub fn glyph_count_byte_range(&self) -> Range<usize> {
145 let start = self.shared_tuples_offset_byte_range().end;
146 let end = start + u16::RAW_BYTE_LEN;
147 start..end
148 }
149
150 pub fn flags_byte_range(&self) -> Range<usize> {
151 let start = self.glyph_count_byte_range().end;
152 let end = start + GvarFlags::RAW_BYTE_LEN;
153 start..end
154 }
155
156 pub fn glyph_variation_data_array_offset_byte_range(&self) -> Range<usize> {
157 let start = self.flags_byte_range().end;
158 let end = start + u32::RAW_BYTE_LEN;
159 start..end
160 }
161
162 pub fn glyph_variation_data_offsets_byte_range(&self) -> Range<usize> {
163 let glyph_count = self.glyph_count();
164 let start = self.glyph_variation_data_array_offset_byte_range().end;
165 let end = start
166 + (transforms::add(glyph_count, 1_usize))
167 .saturating_mul(<U16Or32 as ComputeSize>::compute_size(self.flags()).unwrap_or(0));
168 start..end
169 }
170}
171
172const _: () = assert!(FontData::default_data_long_enough(Gvar::MIN_SIZE));
173
174impl Default for Gvar<'_> {
175 fn default() -> Self {
176 Self {
177 data: FontData::default_table_data(),
178 }
179 }
180}
181
182#[cfg(feature = "experimental_traverse")]
183impl<'a> SomeTable<'a> for Gvar<'a> {
184 fn type_name(&self) -> &str {
185 "Gvar"
186 }
187 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
188 match idx {
189 0usize => Some(Field::new("version", self.version())),
190 1usize => Some(Field::new("axis_count", self.axis_count())),
191 2usize => Some(Field::new("shared_tuple_count", self.shared_tuple_count())),
192 3usize => Some(Field::new(
193 "shared_tuples_offset",
194 FieldType::offset(self.shared_tuples_offset(), self.shared_tuples()),
195 )),
196 4usize => Some(Field::new("glyph_count", self.glyph_count())),
197 5usize => Some(Field::new("flags", self.flags())),
198 6usize => Some(Field::new(
199 "glyph_variation_data_array_offset",
200 self.glyph_variation_data_array_offset(),
201 )),
202 7usize => Some(Field::new(
203 "glyph_variation_data_offsets",
204 traversal::FieldType::Unknown,
205 )),
206 _ => None,
207 }
208 }
209}
210
211#[cfg(feature = "experimental_traverse")]
212#[allow(clippy::needless_lifetimes)]
213impl<'a> std::fmt::Debug for Gvar<'a> {
214 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215 (self as &dyn SomeTable<'a>).fmt(f)
216 }
217}
218
219#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
220#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
221#[repr(transparent)]
222pub struct GvarFlags {
223 bits: u16,
224}
225
226impl GvarFlags {
227 pub const LONG_OFFSETS: Self = Self { bits: 1 };
229}
230
231impl GvarFlags {
232 #[inline]
234 pub const fn empty() -> Self {
235 Self { bits: 0 }
236 }
237
238 #[inline]
240 pub const fn all() -> Self {
241 Self {
242 bits: Self::LONG_OFFSETS.bits,
243 }
244 }
245
246 #[inline]
248 pub const fn bits(&self) -> u16 {
249 self.bits
250 }
251
252 #[inline]
255 pub const fn from_bits(bits: u16) -> Option<Self> {
256 if (bits & !Self::all().bits()) == 0 {
257 Some(Self { bits })
258 } else {
259 None
260 }
261 }
262
263 #[inline]
266 pub const fn from_bits_truncate(bits: u16) -> Self {
267 Self {
268 bits: bits & Self::all().bits,
269 }
270 }
271
272 #[inline]
274 pub const fn is_empty(&self) -> bool {
275 self.bits() == Self::empty().bits()
276 }
277
278 #[inline]
280 pub const fn intersects(&self, other: Self) -> bool {
281 !(Self {
282 bits: self.bits & other.bits,
283 })
284 .is_empty()
285 }
286
287 #[inline]
289 pub const fn contains(&self, other: Self) -> bool {
290 (self.bits & other.bits) == other.bits
291 }
292
293 #[inline]
295 pub fn insert(&mut self, other: Self) {
296 self.bits |= other.bits;
297 }
298
299 #[inline]
301 pub fn remove(&mut self, other: Self) {
302 self.bits &= !other.bits;
303 }
304
305 #[inline]
307 pub fn toggle(&mut self, other: Self) {
308 self.bits ^= other.bits;
309 }
310
311 #[inline]
322 #[must_use]
323 pub const fn intersection(self, other: Self) -> Self {
324 Self {
325 bits: self.bits & other.bits,
326 }
327 }
328
329 #[inline]
340 #[must_use]
341 pub const fn union(self, other: Self) -> Self {
342 Self {
343 bits: self.bits | other.bits,
344 }
345 }
346
347 #[inline]
360 #[must_use]
361 pub const fn difference(self, other: Self) -> Self {
362 Self {
363 bits: self.bits & !other.bits,
364 }
365 }
366}
367
368impl std::ops::BitOr for GvarFlags {
369 type Output = Self;
370
371 #[inline]
373 fn bitor(self, other: GvarFlags) -> Self {
374 Self {
375 bits: self.bits | other.bits,
376 }
377 }
378}
379
380impl std::ops::BitOrAssign for GvarFlags {
381 #[inline]
383 fn bitor_assign(&mut self, other: Self) {
384 self.bits |= other.bits;
385 }
386}
387
388impl std::ops::BitXor for GvarFlags {
389 type Output = Self;
390
391 #[inline]
393 fn bitxor(self, other: Self) -> Self {
394 Self {
395 bits: self.bits ^ other.bits,
396 }
397 }
398}
399
400impl std::ops::BitXorAssign for GvarFlags {
401 #[inline]
403 fn bitxor_assign(&mut self, other: Self) {
404 self.bits ^= other.bits;
405 }
406}
407
408impl std::ops::BitAnd for GvarFlags {
409 type Output = Self;
410
411 #[inline]
413 fn bitand(self, other: Self) -> Self {
414 Self {
415 bits: self.bits & other.bits,
416 }
417 }
418}
419
420impl std::ops::BitAndAssign for GvarFlags {
421 #[inline]
423 fn bitand_assign(&mut self, other: Self) {
424 self.bits &= other.bits;
425 }
426}
427
428impl std::ops::Sub for GvarFlags {
429 type Output = Self;
430
431 #[inline]
433 fn sub(self, other: Self) -> Self {
434 Self {
435 bits: self.bits & !other.bits,
436 }
437 }
438}
439
440impl std::ops::SubAssign for GvarFlags {
441 #[inline]
443 fn sub_assign(&mut self, other: Self) {
444 self.bits &= !other.bits;
445 }
446}
447
448impl std::ops::Not for GvarFlags {
449 type Output = Self;
450
451 #[inline]
453 fn not(self) -> Self {
454 Self { bits: !self.bits } & Self::all()
455 }
456}
457
458impl std::fmt::Debug for GvarFlags {
459 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
460 let members: &[(&str, Self)] = &[("LONG_OFFSETS", Self::LONG_OFFSETS)];
461 let mut first = true;
462 for (name, value) in members {
463 if self.contains(*value) {
464 if !first {
465 f.write_str(" | ")?;
466 }
467 first = false;
468 f.write_str(name)?;
469 }
470 }
471 if first {
472 f.write_str("(empty)")?;
473 }
474 Ok(())
475 }
476}
477
478impl std::fmt::Binary for GvarFlags {
479 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
480 std::fmt::Binary::fmt(&self.bits, f)
481 }
482}
483
484impl std::fmt::Octal for GvarFlags {
485 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
486 std::fmt::Octal::fmt(&self.bits, f)
487 }
488}
489
490impl std::fmt::LowerHex for GvarFlags {
491 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
492 std::fmt::LowerHex::fmt(&self.bits, f)
493 }
494}
495
496impl std::fmt::UpperHex for GvarFlags {
497 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
498 std::fmt::UpperHex::fmt(&self.bits, f)
499 }
500}
501
502impl font_types::Scalar for GvarFlags {
503 type Raw = <u16 as font_types::Scalar>::Raw;
504 fn to_raw(self) -> Self::Raw {
505 self.bits().to_raw()
506 }
507 fn from_raw(raw: Self::Raw) -> Self {
508 let t = <u16>::from_raw(raw);
509 Self::from_bits_truncate(t)
510 }
511}
512
513#[cfg(feature = "experimental_traverse")]
514impl<'a> From<GvarFlags> for FieldType<'a> {
515 fn from(src: GvarFlags) -> FieldType<'a> {
516 src.bits().into()
517 }
518}
519
520impl<'a> MinByteRange<'a> for SharedTuples<'a> {
521 fn min_byte_range(&self) -> Range<usize> {
522 0..self.tuples_byte_range().end
523 }
524 fn min_table_bytes(&self) -> &'a [u8] {
525 let range = self.min_byte_range();
526 self.data.as_bytes().get(range).unwrap_or_default()
527 }
528}
529
530impl ReadArgs for SharedTuples<'_> {
531 type Args = (u16, u16);
532}
533
534impl<'a> FontRead<'a> for SharedTuples<'a> {
535 fn read_with_args(data: FontData<'a>, args: (u16, u16)) -> Result<Self, ReadError> {
536 let (shared_tuple_count, axis_count) = args;
537
538 #[allow(clippy::absurd_extreme_comparisons)]
539 if data.len() < Self::MIN_SIZE {
540 return Err(ReadError::OutOfBounds);
541 }
542 Ok(Self {
543 data,
544 shared_tuple_count,
545 axis_count,
546 })
547 }
548}
549
550impl<'a> SharedTuples<'a> {
551 pub fn read(
556 data: FontData<'a>,
557 shared_tuple_count: u16,
558 axis_count: u16,
559 ) -> Result<Self, ReadError> {
560 let args = (shared_tuple_count, axis_count);
561 Self::read_with_args(data, args)
562 }
563}
564
565#[derive(Clone)]
567pub struct SharedTuples<'a> {
568 data: FontData<'a>,
569 shared_tuple_count: u16,
570 axis_count: u16,
571}
572
573#[allow(clippy::needless_lifetimes)]
574impl<'a> SharedTuples<'a> {
575 pub const MIN_SIZE: usize = 0;
576 basic_table_impls!(impl_the_methods);
577
578 pub fn tuples(&self) -> ComputedArray<'a, Tuple<'a>> {
579 let range = self.tuples_byte_range();
580 self.data
581 .read_with_args(range, self.axis_count())
582 .unwrap_or_default()
583 }
584
585 pub(crate) fn shared_tuple_count(&self) -> u16 {
586 self.shared_tuple_count
587 }
588
589 pub(crate) fn axis_count(&self) -> u16 {
590 self.axis_count
591 }
592
593 pub fn tuples_byte_range(&self) -> Range<usize> {
594 let shared_tuple_count = self.shared_tuple_count();
595 let start = 0;
596 let end = start
597 + (transforms::to_usize(shared_tuple_count)).saturating_mul(
598 <Tuple as ComputeSize>::compute_size(self.axis_count()).unwrap_or(0),
599 );
600 start..end
601 }
602}
603
604#[allow(clippy::absurd_extreme_comparisons)]
605const _: () = assert!(FontData::default_data_long_enough(SharedTuples::MIN_SIZE));
606
607impl Default for SharedTuples<'_> {
608 fn default() -> Self {
609 Self {
610 data: FontData::default_table_data(),
611 shared_tuple_count: Default::default(),
612 axis_count: Default::default(),
613 }
614 }
615}
616
617#[cfg(feature = "experimental_traverse")]
618impl<'a> SomeTable<'a> for SharedTuples<'a> {
619 fn type_name(&self) -> &str {
620 "SharedTuples"
621 }
622 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
623 match idx {
624 0usize => Some(Field::new(
625 "tuples",
626 traversal::FieldType::computed_array("Tuple", self.tuples(), self.offset_data()),
627 )),
628 _ => None,
629 }
630 }
631}
632
633#[cfg(feature = "experimental_traverse")]
634#[allow(clippy::needless_lifetimes)]
635impl<'a> std::fmt::Debug for SharedTuples<'a> {
636 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
637 (self as &dyn SomeTable<'a>).fmt(f)
638 }
639}
640
641impl<'a> MinByteRange<'a> for GlyphVariationDataHeader<'a> {
642 fn min_byte_range(&self) -> Range<usize> {
643 0..self.tuple_variation_headers_byte_range().end
644 }
645 fn min_table_bytes(&self) -> &'a [u8] {
646 let range = self.min_byte_range();
647 self.data.as_bytes().get(range).unwrap_or_default()
648 }
649}
650
651impl ReadArgs for GlyphVariationDataHeader<'_> {
652 type Args = ();
653}
654
655impl<'a> FontRead<'a> for GlyphVariationDataHeader<'a> {
656 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
657 #[allow(clippy::absurd_extreme_comparisons)]
658 if data.len() < Self::MIN_SIZE {
659 return Err(ReadError::OutOfBounds);
660 }
661 Ok(Self { data })
662 }
663}
664
665#[derive(Clone)]
667pub struct GlyphVariationDataHeader<'a> {
668 data: FontData<'a>,
669}
670
671#[allow(clippy::needless_lifetimes)]
672impl<'a> GlyphVariationDataHeader<'a> {
673 pub const MIN_SIZE: usize = (TupleVariationCount::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
674 basic_table_impls!(impl_the_methods);
675
676 pub fn tuple_variation_count(&self) -> TupleVariationCount {
681 let range = self.tuple_variation_count_byte_range();
682 self.data.read_at(range.start).ok().unwrap()
683 }
684
685 pub fn serialized_data_offset(&self) -> Offset16 {
688 let range = self.serialized_data_offset_byte_range();
689 self.data.read_at(range.start).ok().unwrap()
690 }
691
692 pub fn serialized_data(&self) -> Result<FontData<'a>, ReadError> {
694 let data = self.data;
695 self.serialized_data_offset().resolve(data)
696 }
697
698 pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader<'a>> {
700 let range = self.tuple_variation_headers_byte_range();
701 self.data
702 .split_off(range.start)
703 .and_then(|d| VarLenArray::read(d).ok())
704 .unwrap_or_default()
705 }
706
707 pub fn tuple_variation_count_byte_range(&self) -> Range<usize> {
708 let start = 0;
709 let end = start + TupleVariationCount::RAW_BYTE_LEN;
710 start..end
711 }
712
713 pub fn serialized_data_offset_byte_range(&self) -> Range<usize> {
714 let start = self.tuple_variation_count_byte_range().end;
715 let end = start + Offset16::RAW_BYTE_LEN;
716 start..end
717 }
718
719 pub fn tuple_variation_headers_byte_range(&self) -> Range<usize> {
720 let start = self.serialized_data_offset_byte_range().end;
721 let end = start + self.data.len().saturating_sub(start);
722 start..end
723 }
724}
725
726const _: () = assert!(FontData::default_data_long_enough(
727 GlyphVariationDataHeader::MIN_SIZE
728));
729
730impl Default for GlyphVariationDataHeader<'_> {
731 fn default() -> Self {
732 Self {
733 data: FontData::default_table_data(),
734 }
735 }
736}
737
738#[cfg(feature = "experimental_traverse")]
739impl<'a> SomeTable<'a> for GlyphVariationDataHeader<'a> {
740 fn type_name(&self) -> &str {
741 "GlyphVariationDataHeader"
742 }
743 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
744 match idx {
745 0usize => Some(Field::new(
746 "tuple_variation_count",
747 traversal::FieldType::Unknown,
748 )),
749 1usize => Some(Field::new(
750 "serialized_data_offset",
751 traversal::FieldType::Unknown,
752 )),
753 2usize => Some(Field::new(
754 "tuple_variation_headers",
755 traversal::FieldType::Unknown,
756 )),
757 _ => None,
758 }
759 }
760}
761
762#[cfg(feature = "experimental_traverse")]
763#[allow(clippy::needless_lifetimes)]
764impl<'a> std::fmt::Debug for GlyphVariationDataHeader<'a> {
765 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
766 (self as &dyn SomeTable<'a>).fmt(f)
767 }
768}