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