1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Varc<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.var_composite_glyphs_offset_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 Varc<'_> {
19 const TAG: Tag = Tag::new(b"VARC");
21}
22
23impl ReadArgs for Varc<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Varc<'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)]
41pub struct Varc<'a> {
42 data: FontData<'a>,
43}
44
45#[allow(clippy::needless_lifetimes)]
46impl<'a> Varc<'a> {
47 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
48 + Offset32::RAW_BYTE_LEN
49 + Offset32::RAW_BYTE_LEN
50 + Offset32::RAW_BYTE_LEN
51 + Offset32::RAW_BYTE_LEN
52 + Offset32::RAW_BYTE_LEN);
53 basic_table_impls!(impl_the_methods);
54
55 pub fn version(&self) -> MajorMinor {
57 let range = self.version_byte_range();
58 self.data.read_at(range.start).ok().unwrap()
59 }
60
61 pub fn coverage_offset(&self) -> Offset32 {
62 let range = self.coverage_offset_byte_range();
63 self.data.read_at(range.start).ok().unwrap()
64 }
65
66 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
68 let data = self.data;
69 self.coverage_offset().resolve(data)
70 }
71
72 pub fn multi_var_store_offset(&self) -> Nullable<Offset32> {
73 let range = self.multi_var_store_offset_byte_range();
74 self.data.read_at(range.start).ok().unwrap()
75 }
76
77 pub fn multi_var_store(&self) -> Option<Result<MultiItemVariationStore<'a>, ReadError>> {
79 let data = self.data;
80 self.multi_var_store_offset().resolve(data)
81 }
82
83 pub fn condition_list_offset(&self) -> Nullable<Offset32> {
84 let range = self.condition_list_offset_byte_range();
85 self.data.read_at(range.start).ok().unwrap()
86 }
87
88 pub fn condition_list(&self) -> Option<Result<ConditionList<'a>, ReadError>> {
90 let data = self.data;
91 self.condition_list_offset().resolve(data)
92 }
93
94 pub fn axis_indices_list_offset(&self) -> Nullable<Offset32> {
95 let range = self.axis_indices_list_offset_byte_range();
96 self.data.read_at(range.start).ok().unwrap()
97 }
98
99 pub fn axis_indices_list(&self) -> Option<Result<Index2<'a>, ReadError>> {
101 let data = self.data;
102 self.axis_indices_list_offset().resolve(data)
103 }
104
105 pub fn var_composite_glyphs_offset(&self) -> Offset32 {
106 let range = self.var_composite_glyphs_offset_byte_range();
107 self.data.read_at(range.start).ok().unwrap()
108 }
109
110 pub fn var_composite_glyphs(&self) -> Result<Index2<'a>, ReadError> {
112 let data = self.data;
113 self.var_composite_glyphs_offset().resolve(data)
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 coverage_offset_byte_range(&self) -> Range<usize> {
123 let start = self.version_byte_range().end;
124 let end = start + Offset32::RAW_BYTE_LEN;
125 start..end
126 }
127
128 pub fn multi_var_store_offset_byte_range(&self) -> Range<usize> {
129 let start = self.coverage_offset_byte_range().end;
130 let end = start + Offset32::RAW_BYTE_LEN;
131 start..end
132 }
133
134 pub fn condition_list_offset_byte_range(&self) -> Range<usize> {
135 let start = self.multi_var_store_offset_byte_range().end;
136 let end = start + Offset32::RAW_BYTE_LEN;
137 start..end
138 }
139
140 pub fn axis_indices_list_offset_byte_range(&self) -> Range<usize> {
141 let start = self.condition_list_offset_byte_range().end;
142 let end = start + Offset32::RAW_BYTE_LEN;
143 start..end
144 }
145
146 pub fn var_composite_glyphs_offset_byte_range(&self) -> Range<usize> {
147 let start = self.axis_indices_list_offset_byte_range().end;
148 let end = start + Offset32::RAW_BYTE_LEN;
149 start..end
150 }
151}
152
153const _: () = assert!(FontData::default_data_long_enough(Varc::MIN_SIZE));
154
155impl Default for Varc<'_> {
156 fn default() -> Self {
157 Self {
158 data: FontData::default_table_data(),
159 }
160 }
161}
162
163impl Format<u16> for MultiItemVariationStore<'_> {
164 const FORMAT: u16 = 1;
165}
166
167impl<'a> MinByteRange<'a> for MultiItemVariationStore<'a> {
168 fn min_byte_range(&self) -> Range<usize> {
169 0..self.variation_data_offsets_byte_range().end
170 }
171 fn min_table_bytes(&self) -> &'a [u8] {
172 let range = self.min_byte_range();
173 self.data.as_bytes().get(range).unwrap_or_default()
174 }
175}
176
177impl ReadArgs for MultiItemVariationStore<'_> {
178 type Args = ();
179}
180
181impl<'a> FontRead<'a> for MultiItemVariationStore<'a> {
182 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
183 #[allow(clippy::absurd_extreme_comparisons)]
184 if data.len() < Self::MIN_SIZE {
185 return Err(ReadError::OutOfBounds);
186 }
187 Ok(Self { data })
188 }
189}
190
191#[derive(Clone)]
194pub struct MultiItemVariationStore<'a> {
195 data: FontData<'a>,
196}
197
198#[allow(clippy::needless_lifetimes)]
199impl<'a> MultiItemVariationStore<'a> {
200 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
201 basic_table_impls!(impl_the_methods);
202
203 pub fn format(&self) -> u16 {
204 let range = self.format_byte_range();
205 self.data.read_at(range.start).ok().unwrap()
206 }
207
208 pub fn region_list_offset(&self) -> Offset32 {
209 let range = self.region_list_offset_byte_range();
210 self.data.read_at(range.start).ok().unwrap()
211 }
212
213 pub fn region_list(&self) -> Result<SparseVariationRegionList<'a>, ReadError> {
215 let data = self.data;
216 self.region_list_offset().resolve(data)
217 }
218
219 pub fn variation_data_count(&self) -> u16 {
220 let range = self.variation_data_count_byte_range();
221 self.data.read_at(range.start).ok().unwrap()
222 }
223
224 pub fn variation_data_offsets(&self) -> &'a [BigEndian<Offset32>] {
225 let range = self.variation_data_offsets_byte_range();
226 self.data.read_array(range).ok().unwrap_or_default()
227 }
228
229 pub fn variation_data(&self) -> ArrayOfOffsets<'a, MultiItemVariationData<'a>, Offset32> {
231 let data = self.data;
232 let offsets = self.variation_data_offsets();
233 ArrayOfOffsets::new(offsets, data, ())
234 }
235
236 pub fn format_byte_range(&self) -> Range<usize> {
237 let start = 0;
238 let end = start + u16::RAW_BYTE_LEN;
239 start..end
240 }
241
242 pub fn region_list_offset_byte_range(&self) -> Range<usize> {
243 let start = self.format_byte_range().end;
244 let end = start + Offset32::RAW_BYTE_LEN;
245 start..end
246 }
247
248 pub fn variation_data_count_byte_range(&self) -> Range<usize> {
249 let start = self.region_list_offset_byte_range().end;
250 let end = start + u16::RAW_BYTE_LEN;
251 start..end
252 }
253
254 pub fn variation_data_offsets_byte_range(&self) -> Range<usize> {
255 let variation_data_count = self.variation_data_count();
256 let start = self.variation_data_count_byte_range().end;
257 let end = start
258 + (transforms::to_usize(variation_data_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
259 start..end
260 }
261}
262
263const _: () = assert!(FontData::default_data_long_enough(
264 MultiItemVariationStore::MIN_SIZE
265));
266
267impl Default for MultiItemVariationStore<'_> {
268 fn default() -> Self {
269 Self {
270 data: FontData::default_format_1_u16_table_data(),
271 }
272 }
273}
274
275impl<'a> MinByteRange<'a> for SparseVariationRegionList<'a> {
276 fn min_byte_range(&self) -> Range<usize> {
277 0..self.region_offsets_byte_range().end
278 }
279 fn min_table_bytes(&self) -> &'a [u8] {
280 let range = self.min_byte_range();
281 self.data.as_bytes().get(range).unwrap_or_default()
282 }
283}
284
285impl ReadArgs for SparseVariationRegionList<'_> {
286 type Args = ();
287}
288
289impl<'a> FontRead<'a> for SparseVariationRegionList<'a> {
290 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
291 #[allow(clippy::absurd_extreme_comparisons)]
292 if data.len() < Self::MIN_SIZE {
293 return Err(ReadError::OutOfBounds);
294 }
295 Ok(Self { data })
296 }
297}
298
299#[derive(Clone)]
300pub struct SparseVariationRegionList<'a> {
301 data: FontData<'a>,
302}
303
304#[allow(clippy::needless_lifetimes)]
305impl<'a> SparseVariationRegionList<'a> {
306 pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
307 basic_table_impls!(impl_the_methods);
308
309 pub fn region_count(&self) -> u32 {
310 let range = self.region_count_byte_range();
311 self.data.read_at(range.start).ok().unwrap()
312 }
313
314 pub fn region_offsets(&self) -> &'a [BigEndian<Offset32>] {
315 let range = self.region_offsets_byte_range();
316 self.data.read_array(range).ok().unwrap_or_default()
317 }
318
319 pub fn regions(&self) -> ArrayOfOffsets<'a, SparseVariationRegion<'a>, Offset32> {
321 let data = self.data;
322 let offsets = self.region_offsets();
323 ArrayOfOffsets::new(offsets, data, ())
324 }
325
326 pub fn region_count_byte_range(&self) -> Range<usize> {
327 let start = 0;
328 let end = start + u32::RAW_BYTE_LEN;
329 start..end
330 }
331
332 pub fn region_offsets_byte_range(&self) -> Range<usize> {
333 let region_count = self.region_count();
334 let start = self.region_count_byte_range().end;
335 let end =
336 start + (transforms::to_usize(region_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
337 start..end
338 }
339}
340
341const _: () = assert!(FontData::default_data_long_enough(
342 SparseVariationRegionList::MIN_SIZE
343));
344
345impl Default for SparseVariationRegionList<'_> {
346 fn default() -> Self {
347 Self {
348 data: FontData::default_table_data(),
349 }
350 }
351}
352
353impl<'a> MinByteRange<'a> for SparseVariationRegion<'a> {
354 fn min_byte_range(&self) -> Range<usize> {
355 0..self.axis_coordinate_offsets_byte_range().end
356 }
357 fn min_table_bytes(&self) -> &'a [u8] {
358 let range = self.min_byte_range();
359 self.data.as_bytes().get(range).unwrap_or_default()
360 }
361}
362
363impl ReadArgs for SparseVariationRegion<'_> {
364 type Args = ();
365}
366
367impl<'a> FontRead<'a> for SparseVariationRegion<'a> {
368 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
369 #[allow(clippy::absurd_extreme_comparisons)]
370 if data.len() < Self::MIN_SIZE {
371 return Err(ReadError::OutOfBounds);
372 }
373 Ok(Self { data })
374 }
375}
376
377#[derive(Clone)]
378pub struct SparseVariationRegion<'a> {
379 data: FontData<'a>,
380}
381
382#[allow(clippy::needless_lifetimes)]
383impl<'a> SparseVariationRegion<'a> {
384 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
385 basic_table_impls!(impl_the_methods);
386
387 pub fn region_axis_count(&self) -> u16 {
388 let range = self.region_axis_count_byte_range();
389 self.data.read_at(range.start).ok().unwrap()
390 }
391
392 pub fn axis_coordinate_offsets(&self) -> &'a [BigEndian<Offset32>] {
393 let range = self.axis_coordinate_offsets_byte_range();
394 self.data.read_array(range).ok().unwrap_or_default()
395 }
396
397 pub fn axis_coordinates(
399 &self,
400 ) -> ArrayOfOffsets<'a, SparseRegionAxisCoordinates<'a>, Offset32> {
401 let data = self.data;
402 let offsets = self.axis_coordinate_offsets();
403 ArrayOfOffsets::new(offsets, data, ())
404 }
405
406 pub fn region_axis_count_byte_range(&self) -> Range<usize> {
407 let start = 0;
408 let end = start + u16::RAW_BYTE_LEN;
409 start..end
410 }
411
412 pub fn axis_coordinate_offsets_byte_range(&self) -> Range<usize> {
413 let region_axis_count = self.region_axis_count();
414 let start = self.region_axis_count_byte_range().end;
415 let end = start
416 + (transforms::to_usize(region_axis_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
417 start..end
418 }
419}
420
421const _: () = assert!(FontData::default_data_long_enough(
422 SparseVariationRegion::MIN_SIZE
423));
424
425impl Default for SparseVariationRegion<'_> {
426 fn default() -> Self {
427 Self {
428 data: FontData::default_table_data(),
429 }
430 }
431}
432
433impl<'a> MinByteRange<'a> for SparseRegionAxisCoordinates<'a> {
434 fn min_byte_range(&self) -> Range<usize> {
435 0..self.end_byte_range().end
436 }
437 fn min_table_bytes(&self) -> &'a [u8] {
438 let range = self.min_byte_range();
439 self.data.as_bytes().get(range).unwrap_or_default()
440 }
441}
442
443impl ReadArgs for SparseRegionAxisCoordinates<'_> {
444 type Args = ();
445}
446
447impl<'a> FontRead<'a> for SparseRegionAxisCoordinates<'a> {
448 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
449 #[allow(clippy::absurd_extreme_comparisons)]
450 if data.len() < Self::MIN_SIZE {
451 return Err(ReadError::OutOfBounds);
452 }
453 Ok(Self { data })
454 }
455}
456
457#[derive(Clone)]
458pub struct SparseRegionAxisCoordinates<'a> {
459 data: FontData<'a>,
460}
461
462#[allow(clippy::needless_lifetimes)]
463impl<'a> SparseRegionAxisCoordinates<'a> {
464 pub const MIN_SIZE: usize =
465 (u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
466 basic_table_impls!(impl_the_methods);
467
468 pub fn axis_index(&self) -> u16 {
469 let range = self.axis_index_byte_range();
470 self.data.read_at(range.start).ok().unwrap()
471 }
472
473 pub fn start(&self) -> F2Dot14 {
474 let range = self.start_byte_range();
475 self.data.read_at(range.start).ok().unwrap()
476 }
477
478 pub fn peak(&self) -> F2Dot14 {
479 let range = self.peak_byte_range();
480 self.data.read_at(range.start).ok().unwrap()
481 }
482
483 pub fn end(&self) -> F2Dot14 {
484 let range = self.end_byte_range();
485 self.data.read_at(range.start).ok().unwrap()
486 }
487
488 pub fn axis_index_byte_range(&self) -> Range<usize> {
489 let start = 0;
490 let end = start + u16::RAW_BYTE_LEN;
491 start..end
492 }
493
494 pub fn start_byte_range(&self) -> Range<usize> {
495 let start = self.axis_index_byte_range().end;
496 let end = start + F2Dot14::RAW_BYTE_LEN;
497 start..end
498 }
499
500 pub fn peak_byte_range(&self) -> Range<usize> {
501 let start = self.start_byte_range().end;
502 let end = start + F2Dot14::RAW_BYTE_LEN;
503 start..end
504 }
505
506 pub fn end_byte_range(&self) -> Range<usize> {
507 let start = self.peak_byte_range().end;
508 let end = start + F2Dot14::RAW_BYTE_LEN;
509 start..end
510 }
511}
512
513const _: () = assert!(FontData::default_data_long_enough(
514 SparseRegionAxisCoordinates::MIN_SIZE
515));
516
517impl Default for SparseRegionAxisCoordinates<'_> {
518 fn default() -> Self {
519 Self {
520 data: FontData::default_table_data(),
521 }
522 }
523}
524
525impl Format<u8> for MultiItemVariationData<'_> {
526 const FORMAT: u8 = 1;
527}
528
529impl<'a> MinByteRange<'a> for MultiItemVariationData<'a> {
530 fn min_byte_range(&self) -> Range<usize> {
531 0..self.delta_sets_offset_byte_range().end
532 }
533 fn min_table_bytes(&self) -> &'a [u8] {
534 let range = self.min_byte_range();
535 self.data.as_bytes().get(range).unwrap_or_default()
536 }
537}
538
539impl ReadArgs for MultiItemVariationData<'_> {
540 type Args = ();
541}
542
543impl<'a> FontRead<'a> for MultiItemVariationData<'a> {
544 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
545 #[allow(clippy::absurd_extreme_comparisons)]
546 if data.len() < Self::MIN_SIZE {
547 return Err(ReadError::OutOfBounds);
548 }
549 Ok(Self { data })
550 }
551}
552
553#[derive(Clone)]
554pub struct MultiItemVariationData<'a> {
555 data: FontData<'a>,
556}
557
558#[allow(clippy::needless_lifetimes)]
559impl<'a> MultiItemVariationData<'a> {
560 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN);
561 basic_table_impls!(impl_the_methods);
562
563 pub fn format(&self) -> u8 {
564 let range = self.format_byte_range();
565 self.data.read_at(range.start).ok().unwrap()
566 }
567
568 pub fn region_index_count(&self) -> u16 {
569 let range = self.region_index_count_byte_range();
570 self.data.read_at(range.start).ok().unwrap()
571 }
572
573 pub fn region_indices(&self) -> &'a [BigEndian<u16>] {
574 let range = self.region_indices_byte_range();
575 self.data.read_array(range).ok().unwrap_or_default()
576 }
577
578 pub fn delta_sets_offset(&self) -> Offset32 {
579 let range = self.delta_sets_offset_byte_range();
580 self.data
581 .read_at(range.start)
582 .ok()
583 .unwrap_or(Offset32::new(Default::default()))
584 }
585
586 pub fn delta_sets(&self) -> Result<Index2<'a>, ReadError> {
588 let data = self.data;
589 self.delta_sets_offset().resolve(data)
590 }
591
592 pub fn format_byte_range(&self) -> Range<usize> {
593 let start = 0;
594 let end = start + u8::RAW_BYTE_LEN;
595 start..end
596 }
597
598 pub fn region_index_count_byte_range(&self) -> Range<usize> {
599 let start = self.format_byte_range().end;
600 let end = start + u16::RAW_BYTE_LEN;
601 start..end
602 }
603
604 pub fn region_indices_byte_range(&self) -> Range<usize> {
605 let region_index_count = self.region_index_count();
606 let start = self.region_index_count_byte_range().end;
607 let end =
608 start + (transforms::to_usize(region_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
609 start..end
610 }
611
612 pub fn delta_sets_offset_byte_range(&self) -> Range<usize> {
613 let start = self.region_indices_byte_range().end;
614 let end = start + Offset32::RAW_BYTE_LEN;
615 start..end
616 }
617}
618
619const _: () = assert!(FontData::default_data_long_enough(
620 MultiItemVariationData::MIN_SIZE
621));
622
623impl Default for MultiItemVariationData<'_> {
624 fn default() -> Self {
625 Self {
626 data: FontData::default_format_1_u8_table_data(),
627 }
628 }
629}
630
631impl<'a> MinByteRange<'a> for ConditionList<'a> {
632 fn min_byte_range(&self) -> Range<usize> {
633 0..self.condition_offsets_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 ReadArgs for ConditionList<'_> {
642 type Args = ();
643}
644
645impl<'a> FontRead<'a> for ConditionList<'a> {
646 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
647 #[allow(clippy::absurd_extreme_comparisons)]
648 if data.len() < Self::MIN_SIZE {
649 return Err(ReadError::OutOfBounds);
650 }
651 Ok(Self { data })
652 }
653}
654
655#[derive(Clone)]
656pub struct ConditionList<'a> {
657 data: FontData<'a>,
658}
659
660#[allow(clippy::needless_lifetimes)]
661impl<'a> ConditionList<'a> {
662 pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
663 basic_table_impls!(impl_the_methods);
664
665 pub fn condition_count(&self) -> u32 {
666 let range = self.condition_count_byte_range();
667 self.data.read_at(range.start).ok().unwrap()
668 }
669
670 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
671 let range = self.condition_offsets_byte_range();
672 self.data.read_array(range).ok().unwrap_or_default()
673 }
674
675 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
677 let data = self.data;
678 let offsets = self.condition_offsets();
679 ArrayOfOffsets::new(offsets, data, ())
680 }
681
682 pub fn condition_count_byte_range(&self) -> Range<usize> {
683 let start = 0;
684 let end = start + u32::RAW_BYTE_LEN;
685 start..end
686 }
687
688 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
689 let condition_count = self.condition_count();
690 let start = self.condition_count_byte_range().end;
691 let end =
692 start + (transforms::to_usize(condition_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
693 start..end
694 }
695}
696
697const _: () = assert!(FontData::default_data_long_enough(ConditionList::MIN_SIZE));
698
699impl Default for ConditionList<'_> {
700 fn default() -> Self {
701 Self {
702 data: FontData::default_table_data(),
703 }
704 }
705}
706
707#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
711#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
712#[repr(transparent)]
713pub struct VarcFlags {
714 bits: u32,
715}
716
717impl VarcFlags {
718 pub const RESET_UNSPECIFIED_AXES: Self = Self {
719 bits: 0b0000_0000_0000_0001,
720 };
721
722 pub const HAVE_AXES: Self = Self {
723 bits: 0b0000_0000_0000_0010,
724 };
725
726 pub const AXIS_VALUES_HAVE_VARIATION: Self = Self {
727 bits: 0b0000_0000_0000_0100,
728 };
729
730 pub const TRANSFORM_HAS_VARIATION: Self = Self {
731 bits: 0b0000_0000_0000_1000,
732 };
733
734 pub const HAVE_TRANSLATE_X: Self = Self {
735 bits: 0b0000_0000_0001_0000,
736 };
737
738 pub const HAVE_TRANSLATE_Y: Self = Self {
739 bits: 0b0000_0000_0010_0000,
740 };
741
742 pub const HAVE_ROTATION: Self = Self {
743 bits: 0b0000_0000_0100_0000,
744 };
745
746 pub const HAVE_CONDITION: Self = Self {
747 bits: 0b0000_0000_1000_0000,
748 };
749
750 pub const HAVE_SCALE_X: Self = Self {
751 bits: 0b0000_0001_0000_0000,
752 };
753
754 pub const HAVE_SCALE_Y: Self = Self {
755 bits: 0b0000_0010_0000_0000,
756 };
757
758 pub const HAVE_TCENTER_X: Self = Self {
759 bits: 0b0000_0100_0000_0000,
760 };
761
762 pub const HAVE_TCENTER_Y: Self = Self {
763 bits: 0b0000_1000_0000_0000,
764 };
765
766 pub const GID_IS_24BIT: Self = Self {
767 bits: 0b0001_0000_0000_0000,
768 };
769
770 pub const HAVE_SKEW_X: Self = Self {
771 bits: 0b0010_0000_0000_0000,
772 };
773
774 pub const HAVE_SKEW_Y: Self = Self {
775 bits: 0b0100_0000_0000_0000,
776 };
777
778 pub const RESERVED_MASK: Self = Self { bits: 0xFFFF8000 };
779}
780
781impl VarcFlags {
782 #[inline]
784 pub const fn empty() -> Self {
785 Self { bits: 0 }
786 }
787
788 #[inline]
790 pub const fn all() -> Self {
791 Self {
792 bits: Self::RESET_UNSPECIFIED_AXES.bits
793 | Self::HAVE_AXES.bits
794 | Self::AXIS_VALUES_HAVE_VARIATION.bits
795 | Self::TRANSFORM_HAS_VARIATION.bits
796 | Self::HAVE_TRANSLATE_X.bits
797 | Self::HAVE_TRANSLATE_Y.bits
798 | Self::HAVE_ROTATION.bits
799 | Self::HAVE_CONDITION.bits
800 | Self::HAVE_SCALE_X.bits
801 | Self::HAVE_SCALE_Y.bits
802 | Self::HAVE_TCENTER_X.bits
803 | Self::HAVE_TCENTER_Y.bits
804 | Self::GID_IS_24BIT.bits
805 | Self::HAVE_SKEW_X.bits
806 | Self::HAVE_SKEW_Y.bits
807 | Self::RESERVED_MASK.bits,
808 }
809 }
810
811 #[inline]
813 pub const fn bits(&self) -> u32 {
814 self.bits
815 }
816
817 #[inline]
820 pub const fn from_bits(bits: u32) -> Option<Self> {
821 if (bits & !Self::all().bits()) == 0 {
822 Some(Self { bits })
823 } else {
824 None
825 }
826 }
827
828 #[inline]
831 pub const fn from_bits_truncate(bits: u32) -> Self {
832 Self {
833 bits: bits & Self::all().bits,
834 }
835 }
836
837 #[inline]
839 pub const fn is_empty(&self) -> bool {
840 self.bits() == Self::empty().bits()
841 }
842
843 #[inline]
845 pub const fn intersects(&self, other: Self) -> bool {
846 !(Self {
847 bits: self.bits & other.bits,
848 })
849 .is_empty()
850 }
851
852 #[inline]
854 pub const fn contains(&self, other: Self) -> bool {
855 (self.bits & other.bits) == other.bits
856 }
857
858 #[inline]
860 pub fn insert(&mut self, other: Self) {
861 self.bits |= other.bits;
862 }
863
864 #[inline]
866 pub fn remove(&mut self, other: Self) {
867 self.bits &= !other.bits;
868 }
869
870 #[inline]
872 pub fn toggle(&mut self, other: Self) {
873 self.bits ^= other.bits;
874 }
875
876 #[inline]
887 #[must_use]
888 pub const fn intersection(self, other: Self) -> Self {
889 Self {
890 bits: self.bits & other.bits,
891 }
892 }
893
894 #[inline]
905 #[must_use]
906 pub const fn union(self, other: Self) -> Self {
907 Self {
908 bits: self.bits | other.bits,
909 }
910 }
911
912 #[inline]
925 #[must_use]
926 pub const fn difference(self, other: Self) -> Self {
927 Self {
928 bits: self.bits & !other.bits,
929 }
930 }
931}
932
933impl std::ops::BitOr for VarcFlags {
934 type Output = Self;
935
936 #[inline]
938 fn bitor(self, other: VarcFlags) -> Self {
939 Self {
940 bits: self.bits | other.bits,
941 }
942 }
943}
944
945impl std::ops::BitOrAssign for VarcFlags {
946 #[inline]
948 fn bitor_assign(&mut self, other: Self) {
949 self.bits |= other.bits;
950 }
951}
952
953impl std::ops::BitXor for VarcFlags {
954 type Output = Self;
955
956 #[inline]
958 fn bitxor(self, other: Self) -> Self {
959 Self {
960 bits: self.bits ^ other.bits,
961 }
962 }
963}
964
965impl std::ops::BitXorAssign for VarcFlags {
966 #[inline]
968 fn bitxor_assign(&mut self, other: Self) {
969 self.bits ^= other.bits;
970 }
971}
972
973impl std::ops::BitAnd for VarcFlags {
974 type Output = Self;
975
976 #[inline]
978 fn bitand(self, other: Self) -> Self {
979 Self {
980 bits: self.bits & other.bits,
981 }
982 }
983}
984
985impl std::ops::BitAndAssign for VarcFlags {
986 #[inline]
988 fn bitand_assign(&mut self, other: Self) {
989 self.bits &= other.bits;
990 }
991}
992
993impl std::ops::Sub for VarcFlags {
994 type Output = Self;
995
996 #[inline]
998 fn sub(self, other: Self) -> Self {
999 Self {
1000 bits: self.bits & !other.bits,
1001 }
1002 }
1003}
1004
1005impl std::ops::SubAssign for VarcFlags {
1006 #[inline]
1008 fn sub_assign(&mut self, other: Self) {
1009 self.bits &= !other.bits;
1010 }
1011}
1012
1013impl std::ops::Not for VarcFlags {
1014 type Output = Self;
1015
1016 #[inline]
1018 fn not(self) -> Self {
1019 Self { bits: !self.bits } & Self::all()
1020 }
1021}
1022
1023impl std::fmt::Debug for VarcFlags {
1024 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1025 let members: &[(&str, Self)] = &[
1026 ("RESET_UNSPECIFIED_AXES", Self::RESET_UNSPECIFIED_AXES),
1027 ("HAVE_AXES", Self::HAVE_AXES),
1028 (
1029 "AXIS_VALUES_HAVE_VARIATION",
1030 Self::AXIS_VALUES_HAVE_VARIATION,
1031 ),
1032 ("TRANSFORM_HAS_VARIATION", Self::TRANSFORM_HAS_VARIATION),
1033 ("HAVE_TRANSLATE_X", Self::HAVE_TRANSLATE_X),
1034 ("HAVE_TRANSLATE_Y", Self::HAVE_TRANSLATE_Y),
1035 ("HAVE_ROTATION", Self::HAVE_ROTATION),
1036 ("HAVE_CONDITION", Self::HAVE_CONDITION),
1037 ("HAVE_SCALE_X", Self::HAVE_SCALE_X),
1038 ("HAVE_SCALE_Y", Self::HAVE_SCALE_Y),
1039 ("HAVE_TCENTER_X", Self::HAVE_TCENTER_X),
1040 ("HAVE_TCENTER_Y", Self::HAVE_TCENTER_Y),
1041 ("GID_IS_24BIT", Self::GID_IS_24BIT),
1042 ("HAVE_SKEW_X", Self::HAVE_SKEW_X),
1043 ("HAVE_SKEW_Y", Self::HAVE_SKEW_Y),
1044 ("RESERVED_MASK", Self::RESERVED_MASK),
1045 ];
1046 let mut first = true;
1047 for (name, value) in members {
1048 if self.contains(*value) {
1049 if !first {
1050 f.write_str(" | ")?;
1051 }
1052 first = false;
1053 f.write_str(name)?;
1054 }
1055 }
1056 if first {
1057 f.write_str("(empty)")?;
1058 }
1059 Ok(())
1060 }
1061}
1062
1063impl std::fmt::Binary for VarcFlags {
1064 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1065 std::fmt::Binary::fmt(&self.bits, f)
1066 }
1067}
1068
1069impl std::fmt::Octal for VarcFlags {
1070 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1071 std::fmt::Octal::fmt(&self.bits, f)
1072 }
1073}
1074
1075impl std::fmt::LowerHex for VarcFlags {
1076 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1077 std::fmt::LowerHex::fmt(&self.bits, f)
1078 }
1079}
1080
1081impl std::fmt::UpperHex for VarcFlags {
1082 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1083 std::fmt::UpperHex::fmt(&self.bits, f)
1084 }
1085}
1086
1087impl font_types::Scalar for VarcFlags {
1088 type Raw = <u32 as font_types::Scalar>::Raw;
1089 fn to_raw(self) -> Self::Raw {
1090 self.bits().to_raw()
1091 }
1092 fn from_raw(raw: Self::Raw) -> Self {
1093 let t = <u32>::from_raw(raw);
1094 Self::from_bits_truncate(t)
1095 }
1096}