1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Base<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.vert_axis_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 Base<'_> {
19 const TAG: Tag = Tag::new(b"BASE");
21}
22
23impl ReadArgs for Base<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Base<'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 Base<'a> {
40 data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Base<'a> {
45 pub const MIN_SIZE: usize =
46 (MajorMinor::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
47 basic_table_impls!(impl_the_methods);
48
49 pub fn version(&self) -> MajorMinor {
51 let range = self.version_byte_range();
52 self.data.read_at(range.start).ok().unwrap()
53 }
54
55 pub fn horiz_axis_offset(&self) -> Nullable<Offset16> {
57 let range = self.horiz_axis_offset_byte_range();
58 self.data.read_at(range.start).ok().unwrap()
59 }
60
61 pub fn horiz_axis(&self) -> Option<Result<Axis<'a>, ReadError>> {
63 let data = self.data;
64 self.horiz_axis_offset().resolve(data)
65 }
66
67 pub fn vert_axis_offset(&self) -> Nullable<Offset16> {
69 let range = self.vert_axis_offset_byte_range();
70 self.data.read_at(range.start).ok().unwrap()
71 }
72
73 pub fn vert_axis(&self) -> Option<Result<Axis<'a>, ReadError>> {
75 let data = self.data;
76 self.vert_axis_offset().resolve(data)
77 }
78
79 pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> {
81 let range = self.item_var_store_offset_byte_range();
82 (!range.is_empty())
83 .then(|| self.data.read_at(range.start).ok())
84 .flatten()
85 }
86
87 pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
89 let data = self.data;
90 self.item_var_store_offset().map(|x| x.resolve(data))?
91 }
92
93 pub fn version_byte_range(&self) -> Range<usize> {
94 let start = 0;
95 let end = start + MajorMinor::RAW_BYTE_LEN;
96 start..end
97 }
98
99 pub fn horiz_axis_offset_byte_range(&self) -> Range<usize> {
100 let start = self.version_byte_range().end;
101 let end = start + Offset16::RAW_BYTE_LEN;
102 start..end
103 }
104
105 pub fn vert_axis_offset_byte_range(&self) -> Range<usize> {
106 let start = self.horiz_axis_offset_byte_range().end;
107 let end = start + Offset16::RAW_BYTE_LEN;
108 start..end
109 }
110
111 pub fn item_var_store_offset_byte_range(&self) -> Range<usize> {
112 let start = self.vert_axis_offset_byte_range().end;
113 let end = if self.version().compatible((1u16, 1u16)) {
114 start + Offset32::RAW_BYTE_LEN
115 } else {
116 start
117 };
118 start..end
119 }
120}
121
122const _: () = assert!(FontData::default_data_long_enough(Base::MIN_SIZE));
123
124impl Default for Base<'_> {
125 fn default() -> Self {
126 Self {
127 data: FontData::default_table_data(),
128 }
129 }
130}
131
132impl<'a> MinByteRange<'a> for Axis<'a> {
133 fn min_byte_range(&self) -> Range<usize> {
134 0..self.base_script_list_offset_byte_range().end
135 }
136 fn min_table_bytes(&self) -> &'a [u8] {
137 let range = self.min_byte_range();
138 self.data.as_bytes().get(range).unwrap_or_default()
139 }
140}
141
142impl ReadArgs for Axis<'_> {
143 type Args = ();
144}
145
146impl<'a> FontRead<'a> for Axis<'a> {
147 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
148 #[allow(clippy::absurd_extreme_comparisons)]
149 if data.len() < Self::MIN_SIZE {
150 return Err(ReadError::OutOfBounds);
151 }
152 Ok(Self { data })
153 }
154}
155
156#[derive(Clone)]
158pub struct Axis<'a> {
159 data: FontData<'a>,
160}
161
162#[allow(clippy::needless_lifetimes)]
163impl<'a> Axis<'a> {
164 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
165 basic_table_impls!(impl_the_methods);
166
167 pub fn base_tag_list_offset(&self) -> Nullable<Offset16> {
170 let range = self.base_tag_list_offset_byte_range();
171 self.data.read_at(range.start).ok().unwrap()
172 }
173
174 pub fn base_tag_list(&self) -> Option<Result<BaseTagList<'a>, ReadError>> {
176 let data = self.data;
177 self.base_tag_list_offset().resolve(data)
178 }
179
180 pub fn base_script_list_offset(&self) -> Offset16 {
182 let range = self.base_script_list_offset_byte_range();
183 self.data.read_at(range.start).ok().unwrap()
184 }
185
186 pub fn base_script_list(&self) -> Result<BaseScriptList<'a>, ReadError> {
188 let data = self.data;
189 self.base_script_list_offset().resolve(data)
190 }
191
192 pub fn base_tag_list_offset_byte_range(&self) -> Range<usize> {
193 let start = 0;
194 let end = start + Offset16::RAW_BYTE_LEN;
195 start..end
196 }
197
198 pub fn base_script_list_offset_byte_range(&self) -> Range<usize> {
199 let start = self.base_tag_list_offset_byte_range().end;
200 let end = start + Offset16::RAW_BYTE_LEN;
201 start..end
202 }
203}
204
205const _: () = assert!(FontData::default_data_long_enough(Axis::MIN_SIZE));
206
207impl Default for Axis<'_> {
208 fn default() -> Self {
209 Self {
210 data: FontData::default_table_data(),
211 }
212 }
213}
214
215impl<'a> MinByteRange<'a> for BaseTagList<'a> {
216 fn min_byte_range(&self) -> Range<usize> {
217 0..self.baseline_tags_byte_range().end
218 }
219 fn min_table_bytes(&self) -> &'a [u8] {
220 let range = self.min_byte_range();
221 self.data.as_bytes().get(range).unwrap_or_default()
222 }
223}
224
225impl ReadArgs for BaseTagList<'_> {
226 type Args = ();
227}
228
229impl<'a> FontRead<'a> for BaseTagList<'a> {
230 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
231 #[allow(clippy::absurd_extreme_comparisons)]
232 if data.len() < Self::MIN_SIZE {
233 return Err(ReadError::OutOfBounds);
234 }
235 Ok(Self { data })
236 }
237}
238
239#[derive(Clone)]
241pub struct BaseTagList<'a> {
242 data: FontData<'a>,
243}
244
245#[allow(clippy::needless_lifetimes)]
246impl<'a> BaseTagList<'a> {
247 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
248 basic_table_impls!(impl_the_methods);
249
250 pub fn base_tag_count(&self) -> u16 {
253 let range = self.base_tag_count_byte_range();
254 self.data.read_at(range.start).ok().unwrap()
255 }
256
257 pub fn baseline_tags(&self) -> &'a [BigEndian<Tag>] {
260 let range = self.baseline_tags_byte_range();
261 self.data.read_array(range).ok().unwrap_or_default()
262 }
263
264 pub fn base_tag_count_byte_range(&self) -> Range<usize> {
265 let start = 0;
266 let end = start + u16::RAW_BYTE_LEN;
267 start..end
268 }
269
270 pub fn baseline_tags_byte_range(&self) -> Range<usize> {
271 let base_tag_count = self.base_tag_count();
272 let start = self.base_tag_count_byte_range().end;
273 let end = start + (transforms::to_usize(base_tag_count)).saturating_mul(Tag::RAW_BYTE_LEN);
274 start..end
275 }
276}
277
278const _: () = assert!(FontData::default_data_long_enough(BaseTagList::MIN_SIZE));
279
280impl Default for BaseTagList<'_> {
281 fn default() -> Self {
282 Self {
283 data: FontData::default_table_data(),
284 }
285 }
286}
287
288impl<'a> MinByteRange<'a> for BaseScriptList<'a> {
289 fn min_byte_range(&self) -> Range<usize> {
290 0..self.base_script_records_byte_range().end
291 }
292 fn min_table_bytes(&self) -> &'a [u8] {
293 let range = self.min_byte_range();
294 self.data.as_bytes().get(range).unwrap_or_default()
295 }
296}
297
298impl ReadArgs for BaseScriptList<'_> {
299 type Args = ();
300}
301
302impl<'a> FontRead<'a> for BaseScriptList<'a> {
303 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
304 #[allow(clippy::absurd_extreme_comparisons)]
305 if data.len() < Self::MIN_SIZE {
306 return Err(ReadError::OutOfBounds);
307 }
308 Ok(Self { data })
309 }
310}
311
312#[derive(Clone)]
314pub struct BaseScriptList<'a> {
315 data: FontData<'a>,
316}
317
318#[allow(clippy::needless_lifetimes)]
319impl<'a> BaseScriptList<'a> {
320 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
321 basic_table_impls!(impl_the_methods);
322
323 pub fn base_script_count(&self) -> u16 {
325 let range = self.base_script_count_byte_range();
326 self.data.read_at(range.start).ok().unwrap()
327 }
328
329 pub fn base_script_records(&self) -> &'a [BaseScriptRecord] {
332 let range = self.base_script_records_byte_range();
333 self.data.read_array(range).ok().unwrap_or_default()
334 }
335
336 pub fn base_script_count_byte_range(&self) -> Range<usize> {
337 let start = 0;
338 let end = start + u16::RAW_BYTE_LEN;
339 start..end
340 }
341
342 pub fn base_script_records_byte_range(&self) -> Range<usize> {
343 let base_script_count = self.base_script_count();
344 let start = self.base_script_count_byte_range().end;
345 let end = start
346 + (transforms::to_usize(base_script_count))
347 .saturating_mul(BaseScriptRecord::RAW_BYTE_LEN);
348 start..end
349 }
350}
351
352const _: () = assert!(FontData::default_data_long_enough(BaseScriptList::MIN_SIZE));
353
354impl Default for BaseScriptList<'_> {
355 fn default() -> Self {
356 Self {
357 data: FontData::default_table_data(),
358 }
359 }
360}
361
362#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
364#[repr(C)]
365#[repr(packed)]
366pub struct BaseScriptRecord {
367 pub base_script_tag: BigEndian<Tag>,
369 pub base_script_offset: BigEndian<Offset16>,
371}
372
373impl BaseScriptRecord {
374 pub fn base_script_tag(&self) -> Tag {
376 self.base_script_tag.get()
377 }
378
379 pub fn base_script_offset(&self) -> Offset16 {
381 self.base_script_offset.get()
382 }
383
384 pub fn base_script<'a>(&self, data: FontData<'a>) -> Result<BaseScript<'a>, ReadError> {
389 self.base_script_offset().resolve(data)
390 }
391}
392
393impl FixedSize for BaseScriptRecord {
394 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
395}
396
397impl<'a> MinByteRange<'a> for BaseScript<'a> {
398 fn min_byte_range(&self) -> Range<usize> {
399 0..self.base_lang_sys_records_byte_range().end
400 }
401 fn min_table_bytes(&self) -> &'a [u8] {
402 let range = self.min_byte_range();
403 self.data.as_bytes().get(range).unwrap_or_default()
404 }
405}
406
407impl ReadArgs for BaseScript<'_> {
408 type Args = ();
409}
410
411impl<'a> FontRead<'a> for BaseScript<'a> {
412 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
413 #[allow(clippy::absurd_extreme_comparisons)]
414 if data.len() < Self::MIN_SIZE {
415 return Err(ReadError::OutOfBounds);
416 }
417 Ok(Self { data })
418 }
419}
420
421#[derive(Clone)]
423pub struct BaseScript<'a> {
424 data: FontData<'a>,
425}
426
427#[allow(clippy::needless_lifetimes)]
428impl<'a> BaseScript<'a> {
429 pub const MIN_SIZE: usize =
430 (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
431 basic_table_impls!(impl_the_methods);
432
433 pub fn base_values_offset(&self) -> Nullable<Offset16> {
435 let range = self.base_values_offset_byte_range();
436 self.data.read_at(range.start).ok().unwrap()
437 }
438
439 pub fn base_values(&self) -> Option<Result<BaseValues<'a>, ReadError>> {
441 let data = self.data;
442 self.base_values_offset().resolve(data)
443 }
444
445 pub fn default_min_max_offset(&self) -> Nullable<Offset16> {
447 let range = self.default_min_max_offset_byte_range();
448 self.data.read_at(range.start).ok().unwrap()
449 }
450
451 pub fn default_min_max(&self) -> Option<Result<MinMax<'a>, ReadError>> {
453 let data = self.data;
454 self.default_min_max_offset().resolve(data)
455 }
456
457 pub fn base_lang_sys_count(&self) -> u16 {
459 let range = self.base_lang_sys_count_byte_range();
460 self.data.read_at(range.start).ok().unwrap()
461 }
462
463 pub fn base_lang_sys_records(&self) -> &'a [BaseLangSysRecord] {
466 let range = self.base_lang_sys_records_byte_range();
467 self.data.read_array(range).ok().unwrap_or_default()
468 }
469
470 pub fn base_values_offset_byte_range(&self) -> Range<usize> {
471 let start = 0;
472 let end = start + Offset16::RAW_BYTE_LEN;
473 start..end
474 }
475
476 pub fn default_min_max_offset_byte_range(&self) -> Range<usize> {
477 let start = self.base_values_offset_byte_range().end;
478 let end = start + Offset16::RAW_BYTE_LEN;
479 start..end
480 }
481
482 pub fn base_lang_sys_count_byte_range(&self) -> Range<usize> {
483 let start = self.default_min_max_offset_byte_range().end;
484 let end = start + u16::RAW_BYTE_LEN;
485 start..end
486 }
487
488 pub fn base_lang_sys_records_byte_range(&self) -> Range<usize> {
489 let base_lang_sys_count = self.base_lang_sys_count();
490 let start = self.base_lang_sys_count_byte_range().end;
491 let end = start
492 + (transforms::to_usize(base_lang_sys_count))
493 .saturating_mul(BaseLangSysRecord::RAW_BYTE_LEN);
494 start..end
495 }
496}
497
498const _: () = assert!(FontData::default_data_long_enough(BaseScript::MIN_SIZE));
499
500impl Default for BaseScript<'_> {
501 fn default() -> Self {
502 Self {
503 data: FontData::default_table_data(),
504 }
505 }
506}
507
508#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
510#[repr(C)]
511#[repr(packed)]
512pub struct BaseLangSysRecord {
513 pub base_lang_sys_tag: BigEndian<Tag>,
515 pub min_max_offset: BigEndian<Offset16>,
517}
518
519impl BaseLangSysRecord {
520 pub fn base_lang_sys_tag(&self) -> Tag {
522 self.base_lang_sys_tag.get()
523 }
524
525 pub fn min_max_offset(&self) -> Offset16 {
527 self.min_max_offset.get()
528 }
529
530 pub fn min_max<'a>(&self, data: FontData<'a>) -> Result<MinMax<'a>, ReadError> {
535 self.min_max_offset().resolve(data)
536 }
537}
538
539impl FixedSize for BaseLangSysRecord {
540 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
541}
542
543impl<'a> MinByteRange<'a> for BaseValues<'a> {
544 fn min_byte_range(&self) -> Range<usize> {
545 0..self.base_coord_offsets_byte_range().end
546 }
547 fn min_table_bytes(&self) -> &'a [u8] {
548 let range = self.min_byte_range();
549 self.data.as_bytes().get(range).unwrap_or_default()
550 }
551}
552
553impl ReadArgs for BaseValues<'_> {
554 type Args = ();
555}
556
557impl<'a> FontRead<'a> for BaseValues<'a> {
558 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
559 #[allow(clippy::absurd_extreme_comparisons)]
560 if data.len() < Self::MIN_SIZE {
561 return Err(ReadError::OutOfBounds);
562 }
563 Ok(Self { data })
564 }
565}
566
567#[derive(Clone)]
569pub struct BaseValues<'a> {
570 data: FontData<'a>,
571}
572
573#[allow(clippy::needless_lifetimes)]
574impl<'a> BaseValues<'a> {
575 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
576 basic_table_impls!(impl_the_methods);
577
578 pub fn default_baseline_index(&self) -> u16 {
582 let range = self.default_baseline_index_byte_range();
583 self.data.read_at(range.start).ok().unwrap()
584 }
585
586 pub fn base_coord_count(&self) -> u16 {
589 let range = self.base_coord_count_byte_range();
590 self.data.read_at(range.start).ok().unwrap()
591 }
592
593 pub fn base_coord_offsets(&self) -> &'a [BigEndian<Offset16>] {
597 let range = self.base_coord_offsets_byte_range();
598 self.data.read_array(range).ok().unwrap_or_default()
599 }
600
601 pub fn base_coords(&self) -> ArrayOfOffsets<'a, BaseCoord<'a>, Offset16> {
603 let data = self.data;
604 let offsets = self.base_coord_offsets();
605 ArrayOfOffsets::new(offsets, data, ())
606 }
607
608 pub fn default_baseline_index_byte_range(&self) -> Range<usize> {
609 let start = 0;
610 let end = start + u16::RAW_BYTE_LEN;
611 start..end
612 }
613
614 pub fn base_coord_count_byte_range(&self) -> Range<usize> {
615 let start = self.default_baseline_index_byte_range().end;
616 let end = start + u16::RAW_BYTE_LEN;
617 start..end
618 }
619
620 pub fn base_coord_offsets_byte_range(&self) -> Range<usize> {
621 let base_coord_count = self.base_coord_count();
622 let start = self.base_coord_count_byte_range().end;
623 let end =
624 start + (transforms::to_usize(base_coord_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
625 start..end
626 }
627}
628
629const _: () = assert!(FontData::default_data_long_enough(BaseValues::MIN_SIZE));
630
631impl Default for BaseValues<'_> {
632 fn default() -> Self {
633 Self {
634 data: FontData::default_table_data(),
635 }
636 }
637}
638
639impl<'a> MinByteRange<'a> for MinMax<'a> {
640 fn min_byte_range(&self) -> Range<usize> {
641 0..self.feat_min_max_records_byte_range().end
642 }
643 fn min_table_bytes(&self) -> &'a [u8] {
644 let range = self.min_byte_range();
645 self.data.as_bytes().get(range).unwrap_or_default()
646 }
647}
648
649impl ReadArgs for MinMax<'_> {
650 type Args = ();
651}
652
653impl<'a> FontRead<'a> for MinMax<'a> {
654 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
655 #[allow(clippy::absurd_extreme_comparisons)]
656 if data.len() < Self::MIN_SIZE {
657 return Err(ReadError::OutOfBounds);
658 }
659 Ok(Self { data })
660 }
661}
662
663#[derive(Clone)]
665pub struct MinMax<'a> {
666 data: FontData<'a>,
667}
668
669#[allow(clippy::needless_lifetimes)]
670impl<'a> MinMax<'a> {
671 pub const MIN_SIZE: usize =
672 (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
673 basic_table_impls!(impl_the_methods);
674
675 pub fn min_coord_offset(&self) -> Nullable<Offset16> {
678 let range = self.min_coord_offset_byte_range();
679 self.data.read_at(range.start).ok().unwrap()
680 }
681
682 pub fn min_coord(&self) -> Option<Result<BaseCoord<'a>, ReadError>> {
684 let data = self.data;
685 self.min_coord_offset().resolve(data)
686 }
687
688 pub fn max_coord_offset(&self) -> Nullable<Offset16> {
691 let range = self.max_coord_offset_byte_range();
692 self.data.read_at(range.start).ok().unwrap()
693 }
694
695 pub fn max_coord(&self) -> Option<Result<BaseCoord<'a>, ReadError>> {
697 let data = self.data;
698 self.max_coord_offset().resolve(data)
699 }
700
701 pub fn feat_min_max_count(&self) -> u16 {
703 let range = self.feat_min_max_count_byte_range();
704 self.data.read_at(range.start).ok().unwrap()
705 }
706
707 pub fn feat_min_max_records(&self) -> &'a [FeatMinMaxRecord] {
710 let range = self.feat_min_max_records_byte_range();
711 self.data.read_array(range).ok().unwrap_or_default()
712 }
713
714 pub fn min_coord_offset_byte_range(&self) -> Range<usize> {
715 let start = 0;
716 let end = start + Offset16::RAW_BYTE_LEN;
717 start..end
718 }
719
720 pub fn max_coord_offset_byte_range(&self) -> Range<usize> {
721 let start = self.min_coord_offset_byte_range().end;
722 let end = start + Offset16::RAW_BYTE_LEN;
723 start..end
724 }
725
726 pub fn feat_min_max_count_byte_range(&self) -> Range<usize> {
727 let start = self.max_coord_offset_byte_range().end;
728 let end = start + u16::RAW_BYTE_LEN;
729 start..end
730 }
731
732 pub fn feat_min_max_records_byte_range(&self) -> Range<usize> {
733 let feat_min_max_count = self.feat_min_max_count();
734 let start = self.feat_min_max_count_byte_range().end;
735 let end = start
736 + (transforms::to_usize(feat_min_max_count))
737 .saturating_mul(FeatMinMaxRecord::RAW_BYTE_LEN);
738 start..end
739 }
740}
741
742const _: () = assert!(FontData::default_data_long_enough(MinMax::MIN_SIZE));
743
744impl Default for MinMax<'_> {
745 fn default() -> Self {
746 Self {
747 data: FontData::default_table_data(),
748 }
749 }
750}
751
752#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
754#[repr(C)]
755#[repr(packed)]
756pub struct FeatMinMaxRecord {
757 pub feature_table_tag: BigEndian<Tag>,
760 pub min_coord_offset: BigEndian<Nullable<Offset16>>,
763 pub max_coord_offset: BigEndian<Nullable<Offset16>>,
766}
767
768impl FeatMinMaxRecord {
769 pub fn feature_table_tag(&self) -> Tag {
772 self.feature_table_tag.get()
773 }
774
775 pub fn min_coord_offset(&self) -> Nullable<Offset16> {
778 self.min_coord_offset.get()
779 }
780
781 pub fn min_coord<'a>(&self, data: FontData<'a>) -> Option<Result<BaseCoord<'a>, ReadError>> {
787 self.min_coord_offset().resolve(data)
788 }
789
790 pub fn max_coord_offset(&self) -> Nullable<Offset16> {
793 self.max_coord_offset.get()
794 }
795
796 pub fn max_coord<'a>(&self, data: FontData<'a>) -> Option<Result<BaseCoord<'a>, ReadError>> {
802 self.max_coord_offset().resolve(data)
803 }
804}
805
806impl FixedSize for FeatMinMaxRecord {
807 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
808}
809
810#[derive(Clone)]
811pub enum BaseCoord<'a> {
812 Format1(BaseCoordFormat1<'a>),
813 Format2(BaseCoordFormat2<'a>),
814 Format3(BaseCoordFormat3<'a>),
815}
816
817impl Default for BaseCoord<'_> {
818 fn default() -> Self {
819 Self::Format1(Default::default())
820 }
821}
822
823impl<'a> BaseCoord<'a> {
824 pub fn offset_data(&self) -> FontData<'a> {
826 match self {
827 Self::Format1(item) => item.offset_data(),
828 Self::Format2(item) => item.offset_data(),
829 Self::Format3(item) => item.offset_data(),
830 }
831 }
832
833 pub fn base_coord_format(&self) -> u16 {
835 match self {
836 Self::Format1(item) => item.base_coord_format(),
837 Self::Format2(item) => item.base_coord_format(),
838 Self::Format3(item) => item.base_coord_format(),
839 }
840 }
841
842 pub fn coordinate(&self) -> i16 {
844 match self {
845 Self::Format1(item) => item.coordinate(),
846 Self::Format2(item) => item.coordinate(),
847 Self::Format3(item) => item.coordinate(),
848 }
849 }
850}
851
852impl ReadArgs for BaseCoord<'_> {
853 type Args = ();
854}
855
856impl<'a> FontRead<'a> for BaseCoord<'a> {
857 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
858 let format: u16 = data.read_at(0usize)?;
859 match format {
860 BaseCoordFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
861 BaseCoordFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
862 BaseCoordFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
863 other => Err(ReadError::InvalidFormat(other.into())),
864 }
865 }
866}
867
868impl<'a> MinByteRange<'a> for BaseCoord<'a> {
869 fn min_byte_range(&self) -> Range<usize> {
870 match self {
871 Self::Format1(item) => item.min_byte_range(),
872 Self::Format2(item) => item.min_byte_range(),
873 Self::Format3(item) => item.min_byte_range(),
874 }
875 }
876 fn min_table_bytes(&self) -> &'a [u8] {
877 match self {
878 Self::Format1(item) => item.min_table_bytes(),
879 Self::Format2(item) => item.min_table_bytes(),
880 Self::Format3(item) => item.min_table_bytes(),
881 }
882 }
883}
884
885impl Format<u16> for BaseCoordFormat1<'_> {
886 const FORMAT: u16 = 1;
887}
888
889impl<'a> MinByteRange<'a> for BaseCoordFormat1<'a> {
890 fn min_byte_range(&self) -> Range<usize> {
891 0..self.coordinate_byte_range().end
892 }
893 fn min_table_bytes(&self) -> &'a [u8] {
894 let range = self.min_byte_range();
895 self.data.as_bytes().get(range).unwrap_or_default()
896 }
897}
898
899impl ReadArgs for BaseCoordFormat1<'_> {
900 type Args = ();
901}
902
903impl<'a> FontRead<'a> for BaseCoordFormat1<'a> {
904 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
905 #[allow(clippy::absurd_extreme_comparisons)]
906 if data.len() < Self::MIN_SIZE {
907 return Err(ReadError::OutOfBounds);
908 }
909 Ok(Self { data })
910 }
911}
912
913#[derive(Clone)]
915pub struct BaseCoordFormat1<'a> {
916 data: FontData<'a>,
917}
918
919#[allow(clippy::needless_lifetimes)]
920impl<'a> BaseCoordFormat1<'a> {
921 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
922 basic_table_impls!(impl_the_methods);
923
924 pub fn base_coord_format(&self) -> u16 {
926 let range = self.base_coord_format_byte_range();
927 self.data.read_at(range.start).ok().unwrap()
928 }
929
930 pub fn coordinate(&self) -> i16 {
932 let range = self.coordinate_byte_range();
933 self.data.read_at(range.start).ok().unwrap()
934 }
935
936 pub fn base_coord_format_byte_range(&self) -> Range<usize> {
937 let start = 0;
938 let end = start + u16::RAW_BYTE_LEN;
939 start..end
940 }
941
942 pub fn coordinate_byte_range(&self) -> Range<usize> {
943 let start = self.base_coord_format_byte_range().end;
944 let end = start + i16::RAW_BYTE_LEN;
945 start..end
946 }
947}
948
949const _: () = assert!(FontData::default_data_long_enough(
950 BaseCoordFormat1::MIN_SIZE
951));
952
953impl Default for BaseCoordFormat1<'_> {
954 fn default() -> Self {
955 Self {
956 data: FontData::default_format_1_u16_table_data(),
957 }
958 }
959}
960
961impl Format<u16> for BaseCoordFormat2<'_> {
962 const FORMAT: u16 = 2;
963}
964
965impl<'a> MinByteRange<'a> for BaseCoordFormat2<'a> {
966 fn min_byte_range(&self) -> Range<usize> {
967 0..self.base_coord_point_byte_range().end
968 }
969 fn min_table_bytes(&self) -> &'a [u8] {
970 let range = self.min_byte_range();
971 self.data.as_bytes().get(range).unwrap_or_default()
972 }
973}
974
975impl ReadArgs for BaseCoordFormat2<'_> {
976 type Args = ();
977}
978
979impl<'a> FontRead<'a> for BaseCoordFormat2<'a> {
980 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
981 #[allow(clippy::absurd_extreme_comparisons)]
982 if data.len() < Self::MIN_SIZE {
983 return Err(ReadError::OutOfBounds);
984 }
985 Ok(Self { data })
986 }
987}
988
989#[derive(Clone)]
991pub struct BaseCoordFormat2<'a> {
992 data: FontData<'a>,
993}
994
995#[allow(clippy::needless_lifetimes)]
996impl<'a> BaseCoordFormat2<'a> {
997 pub const MIN_SIZE: usize =
998 (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
999 basic_table_impls!(impl_the_methods);
1000
1001 pub fn base_coord_format(&self) -> u16 {
1003 let range = self.base_coord_format_byte_range();
1004 self.data.read_at(range.start).ok().unwrap()
1005 }
1006
1007 pub fn coordinate(&self) -> i16 {
1009 let range = self.coordinate_byte_range();
1010 self.data.read_at(range.start).ok().unwrap()
1011 }
1012
1013 pub fn reference_glyph(&self) -> u16 {
1015 let range = self.reference_glyph_byte_range();
1016 self.data.read_at(range.start).ok().unwrap()
1017 }
1018
1019 pub fn base_coord_point(&self) -> u16 {
1021 let range = self.base_coord_point_byte_range();
1022 self.data.read_at(range.start).ok().unwrap()
1023 }
1024
1025 pub fn base_coord_format_byte_range(&self) -> Range<usize> {
1026 let start = 0;
1027 let end = start + u16::RAW_BYTE_LEN;
1028 start..end
1029 }
1030
1031 pub fn coordinate_byte_range(&self) -> Range<usize> {
1032 let start = self.base_coord_format_byte_range().end;
1033 let end = start + i16::RAW_BYTE_LEN;
1034 start..end
1035 }
1036
1037 pub fn reference_glyph_byte_range(&self) -> Range<usize> {
1038 let start = self.coordinate_byte_range().end;
1039 let end = start + u16::RAW_BYTE_LEN;
1040 start..end
1041 }
1042
1043 pub fn base_coord_point_byte_range(&self) -> Range<usize> {
1044 let start = self.reference_glyph_byte_range().end;
1045 let end = start + u16::RAW_BYTE_LEN;
1046 start..end
1047 }
1048}
1049
1050impl Format<u16> for BaseCoordFormat3<'_> {
1051 const FORMAT: u16 = 3;
1052}
1053
1054impl<'a> MinByteRange<'a> for BaseCoordFormat3<'a> {
1055 fn min_byte_range(&self) -> Range<usize> {
1056 0..self.device_offset_byte_range().end
1057 }
1058 fn min_table_bytes(&self) -> &'a [u8] {
1059 let range = self.min_byte_range();
1060 self.data.as_bytes().get(range).unwrap_or_default()
1061 }
1062}
1063
1064impl ReadArgs for BaseCoordFormat3<'_> {
1065 type Args = ();
1066}
1067
1068impl<'a> FontRead<'a> for BaseCoordFormat3<'a> {
1069 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1070 #[allow(clippy::absurd_extreme_comparisons)]
1071 if data.len() < Self::MIN_SIZE {
1072 return Err(ReadError::OutOfBounds);
1073 }
1074 Ok(Self { data })
1075 }
1076}
1077
1078#[derive(Clone)]
1080pub struct BaseCoordFormat3<'a> {
1081 data: FontData<'a>,
1082}
1083
1084#[allow(clippy::needless_lifetimes)]
1085impl<'a> BaseCoordFormat3<'a> {
1086 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
1087 basic_table_impls!(impl_the_methods);
1088
1089 pub fn base_coord_format(&self) -> u16 {
1091 let range = self.base_coord_format_byte_range();
1092 self.data.read_at(range.start).ok().unwrap()
1093 }
1094
1095 pub fn coordinate(&self) -> i16 {
1097 let range = self.coordinate_byte_range();
1098 self.data.read_at(range.start).ok().unwrap()
1099 }
1100
1101 pub fn device_offset(&self) -> Nullable<Offset16> {
1105 let range = self.device_offset_byte_range();
1106 self.data.read_at(range.start).ok().unwrap()
1107 }
1108
1109 pub fn device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
1111 let data = self.data;
1112 self.device_offset().resolve(data)
1113 }
1114
1115 pub fn base_coord_format_byte_range(&self) -> Range<usize> {
1116 let start = 0;
1117 let end = start + u16::RAW_BYTE_LEN;
1118 start..end
1119 }
1120
1121 pub fn coordinate_byte_range(&self) -> Range<usize> {
1122 let start = self.base_coord_format_byte_range().end;
1123 let end = start + i16::RAW_BYTE_LEN;
1124 start..end
1125 }
1126
1127 pub fn device_offset_byte_range(&self) -> Range<usize> {
1128 let start = self.coordinate_byte_range().end;
1129 let end = start + Offset16::RAW_BYTE_LEN;
1130 start..end
1131 }
1132}