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
162#[cfg(feature = "experimental_traverse")]
163impl<'a> SomeTable<'a> for Gvar<'a> {
164 fn type_name(&self) -> &str {
165 "Gvar"
166 }
167 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
168 match idx {
169 0usize => Some(Field::new("version", self.version())),
170 1usize => Some(Field::new("axis_count", self.axis_count())),
171 2usize => Some(Field::new("shared_tuple_count", self.shared_tuple_count())),
172 3usize => Some(Field::new(
173 "shared_tuples_offset",
174 FieldType::offset(self.shared_tuples_offset(), self.shared_tuples()),
175 )),
176 4usize => Some(Field::new("glyph_count", self.glyph_count())),
177 5usize => Some(Field::new("flags", self.flags())),
178 6usize => Some(Field::new(
179 "glyph_variation_data_array_offset",
180 self.glyph_variation_data_array_offset(),
181 )),
182 7usize => Some(Field::new(
183 "glyph_variation_data_offsets",
184 traversal::FieldType::Unknown,
185 )),
186 _ => None,
187 }
188 }
189}
190
191#[cfg(feature = "experimental_traverse")]
192#[allow(clippy::needless_lifetimes)]
193impl<'a> std::fmt::Debug for Gvar<'a> {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195 (self as &dyn SomeTable<'a>).fmt(f)
196 }
197}
198
199#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
200#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
201#[repr(transparent)]
202pub struct GvarFlags {
203 bits: u16,
204}
205
206impl GvarFlags {
207 pub const LONG_OFFSETS: Self = Self { bits: 1 };
209}
210
211impl GvarFlags {
212 #[inline]
214 pub const fn empty() -> Self {
215 Self { bits: 0 }
216 }
217
218 #[inline]
220 pub const fn all() -> Self {
221 Self {
222 bits: Self::LONG_OFFSETS.bits,
223 }
224 }
225
226 #[inline]
228 pub const fn bits(&self) -> u16 {
229 self.bits
230 }
231
232 #[inline]
235 pub const fn from_bits(bits: u16) -> Option<Self> {
236 if (bits & !Self::all().bits()) == 0 {
237 Some(Self { bits })
238 } else {
239 None
240 }
241 }
242
243 #[inline]
246 pub const fn from_bits_truncate(bits: u16) -> Self {
247 Self {
248 bits: bits & Self::all().bits,
249 }
250 }
251
252 #[inline]
254 pub const fn is_empty(&self) -> bool {
255 self.bits() == Self::empty().bits()
256 }
257
258 #[inline]
260 pub const fn intersects(&self, other: Self) -> bool {
261 !(Self {
262 bits: self.bits & other.bits,
263 })
264 .is_empty()
265 }
266
267 #[inline]
269 pub const fn contains(&self, other: Self) -> bool {
270 (self.bits & other.bits) == other.bits
271 }
272
273 #[inline]
275 pub fn insert(&mut self, other: Self) {
276 self.bits |= other.bits;
277 }
278
279 #[inline]
281 pub fn remove(&mut self, other: Self) {
282 self.bits &= !other.bits;
283 }
284
285 #[inline]
287 pub fn toggle(&mut self, other: Self) {
288 self.bits ^= other.bits;
289 }
290
291 #[inline]
302 #[must_use]
303 pub const fn intersection(self, other: Self) -> Self {
304 Self {
305 bits: self.bits & other.bits,
306 }
307 }
308
309 #[inline]
320 #[must_use]
321 pub const fn union(self, other: Self) -> Self {
322 Self {
323 bits: self.bits | other.bits,
324 }
325 }
326
327 #[inline]
340 #[must_use]
341 pub const fn difference(self, other: Self) -> Self {
342 Self {
343 bits: self.bits & !other.bits,
344 }
345 }
346}
347
348impl std::ops::BitOr for GvarFlags {
349 type Output = Self;
350
351 #[inline]
353 fn bitor(self, other: GvarFlags) -> Self {
354 Self {
355 bits: self.bits | other.bits,
356 }
357 }
358}
359
360impl std::ops::BitOrAssign for GvarFlags {
361 #[inline]
363 fn bitor_assign(&mut self, other: Self) {
364 self.bits |= other.bits;
365 }
366}
367
368impl std::ops::BitXor for GvarFlags {
369 type Output = Self;
370
371 #[inline]
373 fn bitxor(self, other: Self) -> Self {
374 Self {
375 bits: self.bits ^ other.bits,
376 }
377 }
378}
379
380impl std::ops::BitXorAssign for GvarFlags {
381 #[inline]
383 fn bitxor_assign(&mut self, other: Self) {
384 self.bits ^= other.bits;
385 }
386}
387
388impl std::ops::BitAnd for GvarFlags {
389 type Output = Self;
390
391 #[inline]
393 fn bitand(self, other: Self) -> Self {
394 Self {
395 bits: self.bits & other.bits,
396 }
397 }
398}
399
400impl std::ops::BitAndAssign for GvarFlags {
401 #[inline]
403 fn bitand_assign(&mut self, other: Self) {
404 self.bits &= other.bits;
405 }
406}
407
408impl std::ops::Sub for GvarFlags {
409 type Output = Self;
410
411 #[inline]
413 fn sub(self, other: Self) -> Self {
414 Self {
415 bits: self.bits & !other.bits,
416 }
417 }
418}
419
420impl std::ops::SubAssign for GvarFlags {
421 #[inline]
423 fn sub_assign(&mut self, other: Self) {
424 self.bits &= !other.bits;
425 }
426}
427
428impl std::ops::Not for GvarFlags {
429 type Output = Self;
430
431 #[inline]
433 fn not(self) -> Self {
434 Self { bits: !self.bits } & Self::all()
435 }
436}
437
438impl std::fmt::Debug for GvarFlags {
439 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
440 let members: &[(&str, Self)] = &[("LONG_OFFSETS", Self::LONG_OFFSETS)];
441 let mut first = true;
442 for (name, value) in members {
443 if self.contains(*value) {
444 if !first {
445 f.write_str(" | ")?;
446 }
447 first = false;
448 f.write_str(name)?;
449 }
450 }
451 if first {
452 f.write_str("(empty)")?;
453 }
454 Ok(())
455 }
456}
457
458impl std::fmt::Binary for GvarFlags {
459 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
460 std::fmt::Binary::fmt(&self.bits, f)
461 }
462}
463
464impl std::fmt::Octal for GvarFlags {
465 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
466 std::fmt::Octal::fmt(&self.bits, f)
467 }
468}
469
470impl std::fmt::LowerHex for GvarFlags {
471 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
472 std::fmt::LowerHex::fmt(&self.bits, f)
473 }
474}
475
476impl std::fmt::UpperHex for GvarFlags {
477 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
478 std::fmt::UpperHex::fmt(&self.bits, f)
479 }
480}
481
482impl font_types::Scalar for GvarFlags {
483 type Raw = <u16 as font_types::Scalar>::Raw;
484 fn to_raw(self) -> Self::Raw {
485 self.bits().to_raw()
486 }
487 fn from_raw(raw: Self::Raw) -> Self {
488 let t = <u16>::from_raw(raw);
489 Self::from_bits_truncate(t)
490 }
491}
492
493#[cfg(feature = "experimental_traverse")]
494impl<'a> From<GvarFlags> for FieldType<'a> {
495 fn from(src: GvarFlags) -> FieldType<'a> {
496 src.bits().into()
497 }
498}
499
500impl<'a> MinByteRange<'a> for SharedTuples<'a> {
501 fn min_byte_range(&self) -> Range<usize> {
502 0..self.tuples_byte_range().end
503 }
504 fn min_table_bytes(&self) -> &'a [u8] {
505 let range = self.min_byte_range();
506 self.data.as_bytes().get(range).unwrap_or_default()
507 }
508}
509
510impl ReadArgs for SharedTuples<'_> {
511 type Args = (u16, u16);
512}
513
514impl<'a> FontReadWithArgs<'a> for SharedTuples<'a> {
515 fn read_with_args(data: FontData<'a>, args: &(u16, u16)) -> Result<Self, ReadError> {
516 let (shared_tuple_count, axis_count) = *args;
517
518 #[allow(clippy::absurd_extreme_comparisons)]
519 if data.len() < Self::MIN_SIZE {
520 return Err(ReadError::OutOfBounds);
521 }
522 Ok(Self {
523 data,
524 shared_tuple_count,
525 axis_count,
526 })
527 }
528}
529
530impl<'a> SharedTuples<'a> {
531 pub fn read(
536 data: FontData<'a>,
537 shared_tuple_count: u16,
538 axis_count: u16,
539 ) -> Result<Self, ReadError> {
540 let args = (shared_tuple_count, axis_count);
541 Self::read_with_args(data, &args)
542 }
543}
544
545#[derive(Clone)]
547pub struct SharedTuples<'a> {
548 data: FontData<'a>,
549 shared_tuple_count: u16,
550 axis_count: u16,
551}
552
553#[allow(clippy::needless_lifetimes)]
554impl<'a> SharedTuples<'a> {
555 pub const MIN_SIZE: usize = 0;
556 basic_table_impls!(impl_the_methods);
557
558 pub fn tuples(&self) -> ComputedArray<'a, Tuple<'a>> {
559 let range = self.tuples_byte_range();
560 self.data
561 .read_with_args(range, &self.axis_count())
562 .unwrap_or_default()
563 }
564
565 pub(crate) fn shared_tuple_count(&self) -> u16 {
566 self.shared_tuple_count
567 }
568
569 pub(crate) fn axis_count(&self) -> u16 {
570 self.axis_count
571 }
572
573 pub fn tuples_byte_range(&self) -> Range<usize> {
574 let shared_tuple_count = self.shared_tuple_count();
575 let start = 0;
576 start
577 ..start
578 + (shared_tuple_count as usize).saturating_mul(
579 <Tuple as ComputeSize>::compute_size(&self.axis_count()).unwrap_or(0),
580 )
581 }
582}
583
584#[cfg(feature = "experimental_traverse")]
585impl<'a> SomeTable<'a> for SharedTuples<'a> {
586 fn type_name(&self) -> &str {
587 "SharedTuples"
588 }
589 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
590 match idx {
591 0usize => Some(Field::new(
592 "tuples",
593 traversal::FieldType::computed_array("Tuple", self.tuples(), self.offset_data()),
594 )),
595 _ => None,
596 }
597 }
598}
599
600#[cfg(feature = "experimental_traverse")]
601#[allow(clippy::needless_lifetimes)]
602impl<'a> std::fmt::Debug for SharedTuples<'a> {
603 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
604 (self as &dyn SomeTable<'a>).fmt(f)
605 }
606}
607
608impl<'a> MinByteRange<'a> for GlyphVariationDataHeader<'a> {
609 fn min_byte_range(&self) -> Range<usize> {
610 0..self.tuple_variation_headers_byte_range().end
611 }
612 fn min_table_bytes(&self) -> &'a [u8] {
613 let range = self.min_byte_range();
614 self.data.as_bytes().get(range).unwrap_or_default()
615 }
616}
617
618impl<'a> FontRead<'a> for GlyphVariationDataHeader<'a> {
619 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
620 #[allow(clippy::absurd_extreme_comparisons)]
621 if data.len() < Self::MIN_SIZE {
622 return Err(ReadError::OutOfBounds);
623 }
624 Ok(Self { data })
625 }
626}
627
628#[derive(Clone)]
630pub struct GlyphVariationDataHeader<'a> {
631 data: FontData<'a>,
632}
633
634#[allow(clippy::needless_lifetimes)]
635impl<'a> GlyphVariationDataHeader<'a> {
636 pub const MIN_SIZE: usize = (TupleVariationCount::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
637 basic_table_impls!(impl_the_methods);
638
639 pub fn tuple_variation_count(&self) -> TupleVariationCount {
644 let range = self.tuple_variation_count_byte_range();
645 self.data.read_at(range.start).ok().unwrap()
646 }
647
648 pub fn serialized_data_offset(&self) -> Offset16 {
651 let range = self.serialized_data_offset_byte_range();
652 self.data.read_at(range.start).ok().unwrap()
653 }
654
655 pub fn serialized_data(&self) -> Result<FontData<'a>, ReadError> {
657 let data = self.data;
658 self.serialized_data_offset().resolve(data)
659 }
660
661 pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader<'a>> {
663 let range = self.tuple_variation_headers_byte_range();
664 self.data
665 .split_off(range.start)
666 .and_then(|d| VarLenArray::read(d).ok())
667 .unwrap_or_default()
668 }
669
670 pub fn tuple_variation_count_byte_range(&self) -> Range<usize> {
671 let start = 0;
672 start..start + TupleVariationCount::RAW_BYTE_LEN
673 }
674
675 pub fn serialized_data_offset_byte_range(&self) -> Range<usize> {
676 let start = self.tuple_variation_count_byte_range().end;
677 start..start + Offset16::RAW_BYTE_LEN
678 }
679
680 pub fn tuple_variation_headers_byte_range(&self) -> Range<usize> {
681 let start = self.serialized_data_offset_byte_range().end;
682 start..start + self.data.len().saturating_sub(start)
683 }
684}
685
686#[cfg(feature = "experimental_traverse")]
687impl<'a> SomeTable<'a> for GlyphVariationDataHeader<'a> {
688 fn type_name(&self) -> &str {
689 "GlyphVariationDataHeader"
690 }
691 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
692 match idx {
693 0usize => Some(Field::new(
694 "tuple_variation_count",
695 traversal::FieldType::Unknown,
696 )),
697 1usize => Some(Field::new(
698 "serialized_data_offset",
699 traversal::FieldType::Unknown,
700 )),
701 2usize => Some(Field::new(
702 "tuple_variation_headers",
703 traversal::FieldType::Unknown,
704 )),
705 _ => None,
706 }
707 }
708}
709
710#[cfg(feature = "experimental_traverse")]
711#[allow(clippy::needless_lifetimes)]
712impl<'a> std::fmt::Debug for GlyphVariationDataHeader<'a> {
713 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
714 (self as &dyn SomeTable<'a>).fmt(f)
715 }
716}