1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Gdef<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.mark_attach_class_def_offset_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.offset_data().as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl TopLevelTable for Gdef<'_> {
19 const TAG: Tag = Tag::new(b"GDEF");
21}
22
23impl ReadArgs for Gdef<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Gdef<'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 let Some(data) = TableDataRef::new(data.as_bytes()) else {
34 return Err(ReadError::OutOfBounds);
35 };
36 Ok(Self { data })
37 }
38}
39
40#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
42#[repr(C, packed)]
43#[doc(hidden)]
44pub struct GdefFixedHeader {
45 pub version: BigEndian<MajorMinor>,
46 pub glyph_class_def_offset: BigEndian<Nullable<Offset16>>,
47 pub attach_list_offset: BigEndian<Nullable<Offset16>>,
48 pub lig_caret_list_offset: BigEndian<Nullable<Offset16>>,
49 pub mark_attach_class_def_offset: BigEndian<Nullable<Offset16>>,
50}
51
52#[allow(clippy::absurd_extreme_comparisons)]
53const _: () = assert!(std::mem::size_of::<GdefFixedHeader>() <= Gdef::MIN_SIZE);
54
55#[derive(Clone)]
57pub struct Gdef<'a> {
58 data: TableDataRef<'a, GdefFixedHeader>,
59}
60
61#[allow(clippy::needless_lifetimes)]
62impl<'a> Gdef<'a> {
63 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
64 + Offset16::RAW_BYTE_LEN
65 + Offset16::RAW_BYTE_LEN
66 + Offset16::RAW_BYTE_LEN
67 + Offset16::RAW_BYTE_LEN);
68 basic_table_impls!(impl_the_methods);
69
70 pub fn version(&self) -> MajorMinor {
72 self.data.header().version.get()
73 }
74
75 pub fn glyph_class_def_offset(&self) -> Nullable<Offset16> {
78 self.data.header().glyph_class_def_offset.get()
79 }
80
81 pub fn glyph_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
83 let data = self.offset_data();
84 self.glyph_class_def_offset().resolve(data)
85 }
86
87 pub fn attach_list_offset(&self) -> Nullable<Offset16> {
90 self.data.header().attach_list_offset.get()
91 }
92
93 pub fn attach_list(&self) -> Option<Result<AttachList<'a>, ReadError>> {
95 let data = self.offset_data();
96 self.attach_list_offset().resolve(data)
97 }
98
99 pub fn lig_caret_list_offset(&self) -> Nullable<Offset16> {
102 self.data.header().lig_caret_list_offset.get()
103 }
104
105 pub fn lig_caret_list(&self) -> Option<Result<LigCaretList<'a>, ReadError>> {
107 let data = self.offset_data();
108 self.lig_caret_list_offset().resolve(data)
109 }
110
111 pub fn mark_attach_class_def_offset(&self) -> Nullable<Offset16> {
114 self.data.header().mark_attach_class_def_offset.get()
115 }
116
117 pub fn mark_attach_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
119 let data = self.offset_data();
120 self.mark_attach_class_def_offset().resolve(data)
121 }
122
123 pub fn mark_glyph_sets_def_offset(&self) -> Option<Nullable<Offset16>> {
126 let range = self.mark_glyph_sets_def_offset_byte_range();
127 (!range.is_empty())
128 .then(|| self.offset_data().read_at(range.start).ok())
129 .flatten()
130 }
131
132 pub fn mark_glyph_sets_def(&self) -> Option<Result<MarkGlyphSets<'a>, ReadError>> {
134 let data = self.offset_data();
135 self.mark_glyph_sets_def_offset().map(|x| x.resolve(data))?
136 }
137
138 pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> {
141 let range = self.item_var_store_offset_byte_range();
142 (!range.is_empty())
143 .then(|| self.offset_data().read_at(range.start).ok())
144 .flatten()
145 }
146
147 pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
149 let data = self.offset_data();
150 self.item_var_store_offset().map(|x| x.resolve(data))?
151 }
152
153 pub fn version_byte_range(&self) -> Range<usize> {
154 let start = 0;
155 let end = start + MajorMinor::RAW_BYTE_LEN;
156 start..end
157 }
158
159 pub fn glyph_class_def_offset_byte_range(&self) -> Range<usize> {
160 let start = self.version_byte_range().end;
161 let end = start + Offset16::RAW_BYTE_LEN;
162 start..end
163 }
164
165 pub fn attach_list_offset_byte_range(&self) -> Range<usize> {
166 let start = self.glyph_class_def_offset_byte_range().end;
167 let end = start + Offset16::RAW_BYTE_LEN;
168 start..end
169 }
170
171 pub fn lig_caret_list_offset_byte_range(&self) -> Range<usize> {
172 let start = self.attach_list_offset_byte_range().end;
173 let end = start + Offset16::RAW_BYTE_LEN;
174 start..end
175 }
176
177 pub fn mark_attach_class_def_offset_byte_range(&self) -> Range<usize> {
178 let start = self.lig_caret_list_offset_byte_range().end;
179 let end = start + Offset16::RAW_BYTE_LEN;
180 start..end
181 }
182
183 pub fn mark_glyph_sets_def_offset_byte_range(&self) -> Range<usize> {
184 let start = self.mark_attach_class_def_offset_byte_range().end;
185 let end = if self.version().compatible((1u16, 2u16)) {
186 start + Offset16::RAW_BYTE_LEN
187 } else {
188 start
189 };
190 start..end
191 }
192
193 pub fn item_var_store_offset_byte_range(&self) -> Range<usize> {
194 let start = self.mark_glyph_sets_def_offset_byte_range().end;
195 let end = if self.version().compatible((1u16, 3u16)) {
196 start + Offset32::RAW_BYTE_LEN
197 } else {
198 start
199 };
200 start..end
201 }
202}
203
204const _: () = assert!(FontData::default_data_long_enough(Gdef::MIN_SIZE));
205
206impl Default for Gdef<'_> {
207 fn default() -> Self {
208 Self {
209 data: TableDataRef::new(FontData::default_table_data().as_bytes())
210 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
211 }
212 }
213}
214
215#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
217#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
218#[repr(u16)]
219#[allow(clippy::manual_non_exhaustive)]
220pub enum GlyphClassDef {
221 #[default]
222 Base = 1,
223 Ligature = 2,
224 Mark = 3,
225 Component = 4,
226 #[doc(hidden)]
227 Unknown,
229}
230
231impl GlyphClassDef {
232 pub fn new(raw: u16) -> Self {
236 match raw {
237 1 => Self::Base,
238 2 => Self::Ligature,
239 3 => Self::Mark,
240 4 => Self::Component,
241 _ => Self::Unknown,
242 }
243 }
244}
245
246impl font_types::Scalar for GlyphClassDef {
247 type Raw = <u16 as font_types::Scalar>::Raw;
248 fn to_raw(self) -> Self::Raw {
249 (self as u16).to_raw()
250 }
251 fn from_raw(raw: Self::Raw) -> Self {
252 let t = <u16>::from_raw(raw);
253 Self::new(t)
254 }
255}
256
257impl<'a> MinByteRange<'a> for AttachList<'a> {
258 fn min_byte_range(&self) -> Range<usize> {
259 0..self.attach_point_offsets_byte_range().end
260 }
261 fn min_table_bytes(&self) -> &'a [u8] {
262 let range = self.min_byte_range();
263 self.offset_data().as_bytes().get(range).unwrap_or_default()
264 }
265}
266
267impl ReadArgs for AttachList<'_> {
268 type Args = ();
269}
270
271impl<'a> FontRead<'a> for AttachList<'a> {
272 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
273 #[allow(clippy::absurd_extreme_comparisons)]
274 if data.len() < Self::MIN_SIZE {
275 return Err(ReadError::OutOfBounds);
276 }
277 let Some(data) = TableDataRef::new(data.as_bytes()) else {
278 return Err(ReadError::OutOfBounds);
279 };
280 Ok(Self { data })
281 }
282}
283
284#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
286#[repr(C, packed)]
287#[doc(hidden)]
288pub struct AttachListFixedHeader {
289 pub coverage_offset: BigEndian<Offset16>,
290 pub glyph_count: BigEndian<u16>,
291}
292
293#[allow(clippy::absurd_extreme_comparisons)]
294const _: () = assert!(std::mem::size_of::<AttachListFixedHeader>() <= AttachList::MIN_SIZE);
295
296#[derive(Clone)]
298pub struct AttachList<'a> {
299 data: TableDataRef<'a, AttachListFixedHeader>,
300}
301
302#[allow(clippy::needless_lifetimes)]
303impl<'a> AttachList<'a> {
304 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
305 basic_table_impls!(impl_the_methods);
306
307 pub fn coverage_offset(&self) -> Offset16 {
309 self.data.header().coverage_offset.get()
310 }
311
312 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
314 let data = self.offset_data();
315 self.coverage_offset().resolve(data)
316 }
317
318 pub fn glyph_count(&self) -> u16 {
320 self.data.header().glyph_count.get()
321 }
322
323 pub fn attach_point_offsets(&self) -> &'a [BigEndian<Offset16>] {
326 let range = self.attach_point_offsets_byte_range();
327 self.offset_data()
328 .read_array(range)
329 .ok()
330 .unwrap_or_default()
331 }
332
333 pub fn attach_points(&self) -> ArrayOfOffsets<'a, AttachPoint<'a>, Offset16> {
335 let data = self.offset_data();
336 let offsets = self.attach_point_offsets();
337 ArrayOfOffsets::new(offsets, data, ())
338 }
339
340 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
341 let start = 0;
342 let end = start + Offset16::RAW_BYTE_LEN;
343 start..end
344 }
345
346 pub fn glyph_count_byte_range(&self) -> Range<usize> {
347 let start = self.coverage_offset_byte_range().end;
348 let end = start + u16::RAW_BYTE_LEN;
349 start..end
350 }
351
352 pub fn attach_point_offsets_byte_range(&self) -> Range<usize> {
353 let glyph_count = self.glyph_count();
354 let start = self.glyph_count_byte_range().end;
355 let end =
356 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
357 start..end
358 }
359}
360
361const _: () = assert!(FontData::default_data_long_enough(AttachList::MIN_SIZE));
362
363impl Default for AttachList<'_> {
364 fn default() -> Self {
365 Self {
366 data: TableDataRef::new(FontData::default_table_data().as_bytes())
367 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
368 }
369 }
370}
371
372impl<'a> MinByteRange<'a> for AttachPoint<'a> {
373 fn min_byte_range(&self) -> Range<usize> {
374 0..self.point_indices_byte_range().end
375 }
376 fn min_table_bytes(&self) -> &'a [u8] {
377 let range = self.min_byte_range();
378 self.offset_data().as_bytes().get(range).unwrap_or_default()
379 }
380}
381
382impl ReadArgs for AttachPoint<'_> {
383 type Args = ();
384}
385
386impl<'a> FontRead<'a> for AttachPoint<'a> {
387 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
388 #[allow(clippy::absurd_extreme_comparisons)]
389 if data.len() < Self::MIN_SIZE {
390 return Err(ReadError::OutOfBounds);
391 }
392 let Some(data) = TableDataRef::new(data.as_bytes()) else {
393 return Err(ReadError::OutOfBounds);
394 };
395 Ok(Self { data })
396 }
397}
398
399#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
401#[repr(C, packed)]
402#[doc(hidden)]
403pub struct AttachPointFixedHeader {
404 pub point_count: BigEndian<u16>,
405}
406
407#[allow(clippy::absurd_extreme_comparisons)]
408const _: () = assert!(std::mem::size_of::<AttachPointFixedHeader>() <= AttachPoint::MIN_SIZE);
409
410#[derive(Clone)]
412pub struct AttachPoint<'a> {
413 data: TableDataRef<'a, AttachPointFixedHeader>,
414}
415
416#[allow(clippy::needless_lifetimes)]
417impl<'a> AttachPoint<'a> {
418 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
419 basic_table_impls!(impl_the_methods);
420
421 pub fn point_count(&self) -> u16 {
423 self.data.header().point_count.get()
424 }
425
426 pub fn point_indices(&self) -> &'a [BigEndian<u16>] {
428 let range = self.point_indices_byte_range();
429 self.offset_data()
430 .read_array(range)
431 .ok()
432 .unwrap_or_default()
433 }
434
435 pub fn point_count_byte_range(&self) -> Range<usize> {
436 let start = 0;
437 let end = start + u16::RAW_BYTE_LEN;
438 start..end
439 }
440
441 pub fn point_indices_byte_range(&self) -> Range<usize> {
442 let point_count = self.point_count();
443 let start = self.point_count_byte_range().end;
444 let end = start + (transforms::to_usize(point_count)).saturating_mul(u16::RAW_BYTE_LEN);
445 start..end
446 }
447}
448
449const _: () = assert!(FontData::default_data_long_enough(AttachPoint::MIN_SIZE));
450
451impl Default for AttachPoint<'_> {
452 fn default() -> Self {
453 Self {
454 data: TableDataRef::new(FontData::default_table_data().as_bytes())
455 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
456 }
457 }
458}
459
460impl<'a> MinByteRange<'a> for LigCaretList<'a> {
461 fn min_byte_range(&self) -> Range<usize> {
462 0..self.lig_glyph_offsets_byte_range().end
463 }
464 fn min_table_bytes(&self) -> &'a [u8] {
465 let range = self.min_byte_range();
466 self.offset_data().as_bytes().get(range).unwrap_or_default()
467 }
468}
469
470impl ReadArgs for LigCaretList<'_> {
471 type Args = ();
472}
473
474impl<'a> FontRead<'a> for LigCaretList<'a> {
475 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
476 #[allow(clippy::absurd_extreme_comparisons)]
477 if data.len() < Self::MIN_SIZE {
478 return Err(ReadError::OutOfBounds);
479 }
480 let Some(data) = TableDataRef::new(data.as_bytes()) else {
481 return Err(ReadError::OutOfBounds);
482 };
483 Ok(Self { data })
484 }
485}
486
487#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
489#[repr(C, packed)]
490#[doc(hidden)]
491pub struct LigCaretListFixedHeader {
492 pub coverage_offset: BigEndian<Offset16>,
493 pub lig_glyph_count: BigEndian<u16>,
494}
495
496#[allow(clippy::absurd_extreme_comparisons)]
497const _: () = assert!(std::mem::size_of::<LigCaretListFixedHeader>() <= LigCaretList::MIN_SIZE);
498
499#[derive(Clone)]
501pub struct LigCaretList<'a> {
502 data: TableDataRef<'a, LigCaretListFixedHeader>,
503}
504
505#[allow(clippy::needless_lifetimes)]
506impl<'a> LigCaretList<'a> {
507 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
508 basic_table_impls!(impl_the_methods);
509
510 pub fn coverage_offset(&self) -> Offset16 {
512 self.data.header().coverage_offset.get()
513 }
514
515 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
517 let data = self.offset_data();
518 self.coverage_offset().resolve(data)
519 }
520
521 pub fn lig_glyph_count(&self) -> u16 {
523 self.data.header().lig_glyph_count.get()
524 }
525
526 pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset16>] {
529 let range = self.lig_glyph_offsets_byte_range();
530 self.offset_data()
531 .read_array(range)
532 .ok()
533 .unwrap_or_default()
534 }
535
536 pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset16> {
538 let data = self.offset_data();
539 let offsets = self.lig_glyph_offsets();
540 ArrayOfOffsets::new(offsets, data, ())
541 }
542
543 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
544 let start = 0;
545 let end = start + Offset16::RAW_BYTE_LEN;
546 start..end
547 }
548
549 pub fn lig_glyph_count_byte_range(&self) -> Range<usize> {
550 let start = self.coverage_offset_byte_range().end;
551 let end = start + u16::RAW_BYTE_LEN;
552 start..end
553 }
554
555 pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> {
556 let lig_glyph_count = self.lig_glyph_count();
557 let start = self.lig_glyph_count_byte_range().end;
558 let end =
559 start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
560 start..end
561 }
562}
563
564const _: () = assert!(FontData::default_data_long_enough(LigCaretList::MIN_SIZE));
565
566impl Default for LigCaretList<'_> {
567 fn default() -> Self {
568 Self {
569 data: TableDataRef::new(FontData::default_table_data().as_bytes())
570 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
571 }
572 }
573}
574
575impl<'a> MinByteRange<'a> for LigGlyph<'a> {
576 fn min_byte_range(&self) -> Range<usize> {
577 0..self.caret_value_offsets_byte_range().end
578 }
579 fn min_table_bytes(&self) -> &'a [u8] {
580 let range = self.min_byte_range();
581 self.offset_data().as_bytes().get(range).unwrap_or_default()
582 }
583}
584
585impl ReadArgs for LigGlyph<'_> {
586 type Args = ();
587}
588
589impl<'a> FontRead<'a> for LigGlyph<'a> {
590 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
591 #[allow(clippy::absurd_extreme_comparisons)]
592 if data.len() < Self::MIN_SIZE {
593 return Err(ReadError::OutOfBounds);
594 }
595 let Some(data) = TableDataRef::new(data.as_bytes()) else {
596 return Err(ReadError::OutOfBounds);
597 };
598 Ok(Self { data })
599 }
600}
601
602#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
604#[repr(C, packed)]
605#[doc(hidden)]
606pub struct LigGlyphFixedHeader {
607 pub caret_count: BigEndian<u16>,
608}
609
610#[allow(clippy::absurd_extreme_comparisons)]
611const _: () = assert!(std::mem::size_of::<LigGlyphFixedHeader>() <= LigGlyph::MIN_SIZE);
612
613#[derive(Clone)]
615pub struct LigGlyph<'a> {
616 data: TableDataRef<'a, LigGlyphFixedHeader>,
617}
618
619#[allow(clippy::needless_lifetimes)]
620impl<'a> LigGlyph<'a> {
621 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
622 basic_table_impls!(impl_the_methods);
623
624 pub fn caret_count(&self) -> u16 {
626 self.data.header().caret_count.get()
627 }
628
629 pub fn caret_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
632 let range = self.caret_value_offsets_byte_range();
633 self.offset_data()
634 .read_array(range)
635 .ok()
636 .unwrap_or_default()
637 }
638
639 pub fn caret_values(&self) -> ArrayOfOffsets<'a, CaretValue<'a>, Offset16> {
641 let data = self.offset_data();
642 let offsets = self.caret_value_offsets();
643 ArrayOfOffsets::new(offsets, data, ())
644 }
645
646 pub fn caret_count_byte_range(&self) -> Range<usize> {
647 let start = 0;
648 let end = start + u16::RAW_BYTE_LEN;
649 start..end
650 }
651
652 pub fn caret_value_offsets_byte_range(&self) -> Range<usize> {
653 let caret_count = self.caret_count();
654 let start = self.caret_count_byte_range().end;
655 let end =
656 start + (transforms::to_usize(caret_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
657 start..end
658 }
659}
660
661const _: () = assert!(FontData::default_data_long_enough(LigGlyph::MIN_SIZE));
662
663impl Default for LigGlyph<'_> {
664 fn default() -> Self {
665 Self {
666 data: TableDataRef::new(FontData::default_table_data().as_bytes())
667 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
668 }
669 }
670}
671
672#[derive(Clone)]
674pub enum CaretValue<'a> {
675 Format1(CaretValueFormat1<'a>),
676 Format2(CaretValueFormat2<'a>),
677 Format3(CaretValueFormat3<'a>),
678}
679
680impl Default for CaretValue<'_> {
681 fn default() -> Self {
682 Self::Format1(Default::default())
683 }
684}
685
686impl<'a> CaretValue<'a> {
687 pub fn offset_data(&self) -> FontData<'a> {
689 match self {
690 Self::Format1(item) => item.offset_data(),
691 Self::Format2(item) => item.offset_data(),
692 Self::Format3(item) => item.offset_data(),
693 }
694 }
695
696 pub fn caret_value_format(&self) -> u16 {
698 match self {
699 Self::Format1(item) => item.caret_value_format(),
700 Self::Format2(item) => item.caret_value_format(),
701 Self::Format3(item) => item.caret_value_format(),
702 }
703 }
704}
705
706impl ReadArgs for CaretValue<'_> {
707 type Args = ();
708}
709
710impl<'a> FontRead<'a> for CaretValue<'a> {
711 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
712 let format: u16 = data.read_at(0usize)?;
713 match format {
714 CaretValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
715 CaretValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
716 CaretValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
717 other => Err(ReadError::InvalidFormat(other.into())),
718 }
719 }
720}
721
722impl<'a> MinByteRange<'a> for CaretValue<'a> {
723 fn min_byte_range(&self) -> Range<usize> {
724 match self {
725 Self::Format1(item) => item.min_byte_range(),
726 Self::Format2(item) => item.min_byte_range(),
727 Self::Format3(item) => item.min_byte_range(),
728 }
729 }
730 fn min_table_bytes(&self) -> &'a [u8] {
731 match self {
732 Self::Format1(item) => item.min_table_bytes(),
733 Self::Format2(item) => item.min_table_bytes(),
734 Self::Format3(item) => item.min_table_bytes(),
735 }
736 }
737}
738
739impl Format<u16> for CaretValueFormat1<'_> {
740 const FORMAT: u16 = 1;
741}
742
743impl<'a> MinByteRange<'a> for CaretValueFormat1<'a> {
744 fn min_byte_range(&self) -> Range<usize> {
745 0..self.coordinate_byte_range().end
746 }
747 fn min_table_bytes(&self) -> &'a [u8] {
748 let range = self.min_byte_range();
749 self.offset_data().as_bytes().get(range).unwrap_or_default()
750 }
751}
752
753impl ReadArgs for CaretValueFormat1<'_> {
754 type Args = ();
755}
756
757impl<'a> FontRead<'a> for CaretValueFormat1<'a> {
758 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
759 #[allow(clippy::absurd_extreme_comparisons)]
760 if data.len() < Self::MIN_SIZE {
761 return Err(ReadError::OutOfBounds);
762 }
763 let Some(data) = TableDataRef::new(data.as_bytes()) else {
764 return Err(ReadError::OutOfBounds);
765 };
766 Ok(Self { data })
767 }
768}
769
770#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
772#[repr(C, packed)]
773#[doc(hidden)]
774pub struct CaretValueFormat1FixedHeader {
775 pub caret_value_format: BigEndian<u16>,
776 pub coordinate: BigEndian<i16>,
777}
778
779#[allow(clippy::absurd_extreme_comparisons)]
780const _: () =
781 assert!(std::mem::size_of::<CaretValueFormat1FixedHeader>() <= CaretValueFormat1::MIN_SIZE);
782
783#[derive(Clone)]
785pub struct CaretValueFormat1<'a> {
786 data: TableDataRef<'a, CaretValueFormat1FixedHeader>,
787}
788
789#[allow(clippy::needless_lifetimes)]
790impl<'a> CaretValueFormat1<'a> {
791 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
792 basic_table_impls!(impl_the_methods);
793
794 pub fn caret_value_format(&self) -> u16 {
796 self.data.header().caret_value_format.get()
797 }
798
799 pub fn coordinate(&self) -> i16 {
801 self.data.header().coordinate.get()
802 }
803
804 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
805 let start = 0;
806 let end = start + u16::RAW_BYTE_LEN;
807 start..end
808 }
809
810 pub fn coordinate_byte_range(&self) -> Range<usize> {
811 let start = self.caret_value_format_byte_range().end;
812 let end = start + i16::RAW_BYTE_LEN;
813 start..end
814 }
815}
816
817const _: () = assert!(FontData::default_data_long_enough(
818 CaretValueFormat1::MIN_SIZE
819));
820
821impl Default for CaretValueFormat1<'_> {
822 fn default() -> Self {
823 Self {
824 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
825 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
826 }
827 }
828}
829
830impl Format<u16> for CaretValueFormat2<'_> {
831 const FORMAT: u16 = 2;
832}
833
834impl<'a> MinByteRange<'a> for CaretValueFormat2<'a> {
835 fn min_byte_range(&self) -> Range<usize> {
836 0..self.caret_value_point_index_byte_range().end
837 }
838 fn min_table_bytes(&self) -> &'a [u8] {
839 let range = self.min_byte_range();
840 self.offset_data().as_bytes().get(range).unwrap_or_default()
841 }
842}
843
844impl ReadArgs for CaretValueFormat2<'_> {
845 type Args = ();
846}
847
848impl<'a> FontRead<'a> for CaretValueFormat2<'a> {
849 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
850 #[allow(clippy::absurd_extreme_comparisons)]
851 if data.len() < Self::MIN_SIZE {
852 return Err(ReadError::OutOfBounds);
853 }
854 let Some(data) = TableDataRef::new(data.as_bytes()) else {
855 return Err(ReadError::OutOfBounds);
856 };
857 Ok(Self { data })
858 }
859}
860
861#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
863#[repr(C, packed)]
864#[doc(hidden)]
865pub struct CaretValueFormat2FixedHeader {
866 pub caret_value_format: BigEndian<u16>,
867 pub caret_value_point_index: BigEndian<u16>,
868}
869
870#[allow(clippy::absurd_extreme_comparisons)]
871const _: () =
872 assert!(std::mem::size_of::<CaretValueFormat2FixedHeader>() <= CaretValueFormat2::MIN_SIZE);
873
874#[derive(Clone)]
876pub struct CaretValueFormat2<'a> {
877 data: TableDataRef<'a, CaretValueFormat2FixedHeader>,
878}
879
880#[allow(clippy::needless_lifetimes)]
881impl<'a> CaretValueFormat2<'a> {
882 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
883 basic_table_impls!(impl_the_methods);
884
885 pub fn caret_value_format(&self) -> u16 {
887 self.data.header().caret_value_format.get()
888 }
889
890 pub fn caret_value_point_index(&self) -> u16 {
892 self.data.header().caret_value_point_index.get()
893 }
894
895 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
896 let start = 0;
897 let end = start + u16::RAW_BYTE_LEN;
898 start..end
899 }
900
901 pub fn caret_value_point_index_byte_range(&self) -> Range<usize> {
902 let start = self.caret_value_format_byte_range().end;
903 let end = start + u16::RAW_BYTE_LEN;
904 start..end
905 }
906}
907
908impl Format<u16> for CaretValueFormat3<'_> {
909 const FORMAT: u16 = 3;
910}
911
912impl<'a> MinByteRange<'a> for CaretValueFormat3<'a> {
913 fn min_byte_range(&self) -> Range<usize> {
914 0..self.device_offset_byte_range().end
915 }
916 fn min_table_bytes(&self) -> &'a [u8] {
917 let range = self.min_byte_range();
918 self.offset_data().as_bytes().get(range).unwrap_or_default()
919 }
920}
921
922impl ReadArgs for CaretValueFormat3<'_> {
923 type Args = ();
924}
925
926impl<'a> FontRead<'a> for CaretValueFormat3<'a> {
927 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
928 #[allow(clippy::absurd_extreme_comparisons)]
929 if data.len() < Self::MIN_SIZE {
930 return Err(ReadError::OutOfBounds);
931 }
932 let Some(data) = TableDataRef::new(data.as_bytes()) else {
933 return Err(ReadError::OutOfBounds);
934 };
935 Ok(Self { data })
936 }
937}
938
939#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
941#[repr(C, packed)]
942#[doc(hidden)]
943pub struct CaretValueFormat3FixedHeader {
944 pub caret_value_format: BigEndian<u16>,
945 pub coordinate: BigEndian<i16>,
946 pub device_offset: BigEndian<Offset16>,
947}
948
949#[allow(clippy::absurd_extreme_comparisons)]
950const _: () =
951 assert!(std::mem::size_of::<CaretValueFormat3FixedHeader>() <= CaretValueFormat3::MIN_SIZE);
952
953#[derive(Clone)]
955pub struct CaretValueFormat3<'a> {
956 data: TableDataRef<'a, CaretValueFormat3FixedHeader>,
957}
958
959#[allow(clippy::needless_lifetimes)]
960impl<'a> CaretValueFormat3<'a> {
961 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
962 basic_table_impls!(impl_the_methods);
963
964 pub fn caret_value_format(&self) -> u16 {
966 self.data.header().caret_value_format.get()
967 }
968
969 pub fn coordinate(&self) -> i16 {
971 self.data.header().coordinate.get()
972 }
973
974 pub fn device_offset(&self) -> Offset16 {
978 self.data.header().device_offset.get()
979 }
980
981 pub fn device(&self) -> Result<DeviceOrVariationIndex<'a>, ReadError> {
983 let data = self.offset_data();
984 self.device_offset().resolve(data)
985 }
986
987 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
988 let start = 0;
989 let end = start + u16::RAW_BYTE_LEN;
990 start..end
991 }
992
993 pub fn coordinate_byte_range(&self) -> Range<usize> {
994 let start = self.caret_value_format_byte_range().end;
995 let end = start + i16::RAW_BYTE_LEN;
996 start..end
997 }
998
999 pub fn device_offset_byte_range(&self) -> Range<usize> {
1000 let start = self.coordinate_byte_range().end;
1001 let end = start + Offset16::RAW_BYTE_LEN;
1002 start..end
1003 }
1004}
1005
1006impl Format<u16> for MarkGlyphSets<'_> {
1007 const FORMAT: u16 = 1;
1008}
1009
1010impl<'a> MinByteRange<'a> for MarkGlyphSets<'a> {
1011 fn min_byte_range(&self) -> Range<usize> {
1012 0..self.coverage_offsets_byte_range().end
1013 }
1014 fn min_table_bytes(&self) -> &'a [u8] {
1015 let range = self.min_byte_range();
1016 self.offset_data().as_bytes().get(range).unwrap_or_default()
1017 }
1018}
1019
1020impl ReadArgs for MarkGlyphSets<'_> {
1021 type Args = ();
1022}
1023
1024impl<'a> FontRead<'a> for MarkGlyphSets<'a> {
1025 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1026 #[allow(clippy::absurd_extreme_comparisons)]
1027 if data.len() < Self::MIN_SIZE {
1028 return Err(ReadError::OutOfBounds);
1029 }
1030 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1031 return Err(ReadError::OutOfBounds);
1032 };
1033 Ok(Self { data })
1034 }
1035}
1036
1037#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1039#[repr(C, packed)]
1040#[doc(hidden)]
1041pub struct MarkGlyphSetsFixedHeader {
1042 pub format: BigEndian<u16>,
1043 pub mark_glyph_set_count: BigEndian<u16>,
1044}
1045
1046#[allow(clippy::absurd_extreme_comparisons)]
1047const _: () = assert!(std::mem::size_of::<MarkGlyphSetsFixedHeader>() <= MarkGlyphSets::MIN_SIZE);
1048
1049#[derive(Clone)]
1051pub struct MarkGlyphSets<'a> {
1052 data: TableDataRef<'a, MarkGlyphSetsFixedHeader>,
1053}
1054
1055#[allow(clippy::needless_lifetimes)]
1056impl<'a> MarkGlyphSets<'a> {
1057 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1058 basic_table_impls!(impl_the_methods);
1059
1060 pub fn format(&self) -> u16 {
1062 self.data.header().format.get()
1063 }
1064
1065 pub fn mark_glyph_set_count(&self) -> u16 {
1067 self.data.header().mark_glyph_set_count.get()
1068 }
1069
1070 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset32>] {
1073 let range = self.coverage_offsets_byte_range();
1074 self.offset_data()
1075 .read_array(range)
1076 .ok()
1077 .unwrap_or_default()
1078 }
1079
1080 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset32> {
1082 let data = self.offset_data();
1083 let offsets = self.coverage_offsets();
1084 ArrayOfOffsets::new(offsets, data, ())
1085 }
1086
1087 pub fn format_byte_range(&self) -> Range<usize> {
1088 let start = 0;
1089 let end = start + u16::RAW_BYTE_LEN;
1090 start..end
1091 }
1092
1093 pub fn mark_glyph_set_count_byte_range(&self) -> Range<usize> {
1094 let start = self.format_byte_range().end;
1095 let end = start + u16::RAW_BYTE_LEN;
1096 start..end
1097 }
1098
1099 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
1100 let mark_glyph_set_count = self.mark_glyph_set_count();
1101 let start = self.mark_glyph_set_count_byte_range().end;
1102 let end = start
1103 + (transforms::to_usize(mark_glyph_set_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
1104 start..end
1105 }
1106}
1107
1108const _: () = assert!(FontData::default_data_long_enough(MarkGlyphSets::MIN_SIZE));
1109
1110impl Default for MarkGlyphSets<'_> {
1111 fn default() -> Self {
1112 Self {
1113 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1114 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1115 }
1116 }
1117}