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