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 attach_list_offset(&self) -> Nullable<Offset16> {
84 self.data.header().attach_list_offset.get()
85 }
86
87 pub fn lig_caret_list_offset(&self) -> Nullable<Offset16> {
90 self.data.header().lig_caret_list_offset.get()
91 }
92
93 pub fn mark_attach_class_def_offset(&self) -> Nullable<Offset16> {
96 self.data.header().mark_attach_class_def_offset.get()
97 }
98
99 pub fn mark_glyph_sets_def_offset(&self) -> Option<Nullable<Offset16>> {
102 let range = self.mark_glyph_sets_def_offset_byte_range();
103 (!range.is_empty())
104 .then(|| self.offset_data().read_at(range.start).ok())
105 .flatten()
106 }
107
108 pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> {
111 let range = self.item_var_store_offset_byte_range();
112 (!range.is_empty())
113 .then(|| self.offset_data().read_at(range.start).ok())
114 .flatten()
115 }
116
117 pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
119 let data = self.offset_data();
120 self.item_var_store_offset().map(|x| x.resolve(data))?
121 }
122
123 pub fn glyph_class_def2_offset(&self) -> Option<Nullable<Offset32>> {
125 let range = self.glyph_class_def2_offset_byte_range();
126 (!range.is_empty())
127 .then(|| self.offset_data().read_at(range.start).ok())
128 .flatten()
129 }
130
131 pub fn glyph_class_def2(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
133 let data = self.offset_data();
134 self.glyph_class_def2_offset().map(|x| x.resolve(data))?
135 }
136
137 pub fn attach_list2_offset(&self) -> Option<Nullable<Offset32>> {
139 let range = self.attach_list2_offset_byte_range();
140 (!range.is_empty())
141 .then(|| self.offset_data().read_at(range.start).ok())
142 .flatten()
143 }
144
145 pub fn attach_list2(&self) -> Option<Result<AttachList<'a>, ReadError>> {
147 let data = self.offset_data();
148 self.attach_list2_offset().map(|x| x.resolve(data))?
149 }
150
151 pub fn lig_caret_list2_offset(&self) -> Option<Nullable<Offset32>> {
153 let range = self.lig_caret_list2_offset_byte_range();
154 (!range.is_empty())
155 .then(|| self.offset_data().read_at(range.start).ok())
156 .flatten()
157 }
158
159 pub fn lig_caret_list2(&self) -> Option<Result<LigCaretList2<'a>, ReadError>> {
161 let data = self.offset_data();
162 self.lig_caret_list2_offset().map(|x| x.resolve(data))?
163 }
164
165 pub fn mark_attach_class_def2_offset(&self) -> Option<Nullable<Offset32>> {
167 let range = self.mark_attach_class_def2_offset_byte_range();
168 (!range.is_empty())
169 .then(|| self.offset_data().read_at(range.start).ok())
170 .flatten()
171 }
172
173 pub fn mark_attach_class_def2(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
175 let data = self.offset_data();
176 self.mark_attach_class_def2_offset()
177 .map(|x| x.resolve(data))?
178 }
179
180 pub fn mark_glyph_sets_def2_offset(&self) -> Option<Nullable<Offset32>> {
182 let range = self.mark_glyph_sets_def2_offset_byte_range();
183 (!range.is_empty())
184 .then(|| self.offset_data().read_at(range.start).ok())
185 .flatten()
186 }
187
188 pub fn mark_glyph_sets_def2(&self) -> Option<Result<MarkGlyphSets<'a>, ReadError>> {
190 let data = self.offset_data();
191 self.mark_glyph_sets_def2_offset()
192 .map(|x| x.resolve(data))?
193 }
194
195 pub fn version_byte_range(&self) -> Range<usize> {
196 let start = 0;
197 let end = start + MajorMinor::RAW_BYTE_LEN;
198 start..end
199 }
200
201 pub fn glyph_class_def_offset_byte_range(&self) -> Range<usize> {
202 let start = self.version_byte_range().end;
203 let end = start + Offset16::RAW_BYTE_LEN;
204 start..end
205 }
206
207 pub fn attach_list_offset_byte_range(&self) -> Range<usize> {
208 let start = self.glyph_class_def_offset_byte_range().end;
209 let end = start + Offset16::RAW_BYTE_LEN;
210 start..end
211 }
212
213 pub fn lig_caret_list_offset_byte_range(&self) -> Range<usize> {
214 let start = self.attach_list_offset_byte_range().end;
215 let end = start + Offset16::RAW_BYTE_LEN;
216 start..end
217 }
218
219 pub fn mark_attach_class_def_offset_byte_range(&self) -> Range<usize> {
220 let start = self.lig_caret_list_offset_byte_range().end;
221 let end = start + Offset16::RAW_BYTE_LEN;
222 start..end
223 }
224
225 pub fn mark_glyph_sets_def_offset_byte_range(&self) -> Range<usize> {
226 let start = self.mark_attach_class_def_offset_byte_range().end;
227 let end = if self.version().compatible((1u16, 2u16)) {
228 start + Offset16::RAW_BYTE_LEN
229 } else {
230 start
231 };
232 start..end
233 }
234
235 pub fn item_var_store_offset_byte_range(&self) -> Range<usize> {
236 let start = self.mark_glyph_sets_def_offset_byte_range().end;
237 let end = if self.version().compatible((1u16, 3u16)) {
238 start + Offset32::RAW_BYTE_LEN
239 } else {
240 start
241 };
242 start..end
243 }
244
245 pub fn glyph_class_def2_offset_byte_range(&self) -> Range<usize> {
246 let start = self.item_var_store_offset_byte_range().end;
247 let end = if self.version().compatible((1u16, 4u16)) {
248 start + Offset32::RAW_BYTE_LEN
249 } else {
250 start
251 };
252 start..end
253 }
254
255 pub fn attach_list2_offset_byte_range(&self) -> Range<usize> {
256 let start = self.glyph_class_def2_offset_byte_range().end;
257 let end = if self.version().compatible((1u16, 4u16)) {
258 start + Offset32::RAW_BYTE_LEN
259 } else {
260 start
261 };
262 start..end
263 }
264
265 pub fn lig_caret_list2_offset_byte_range(&self) -> Range<usize> {
266 let start = self.attach_list2_offset_byte_range().end;
267 let end = if self.version().compatible((1u16, 4u16)) {
268 start + Offset32::RAW_BYTE_LEN
269 } else {
270 start
271 };
272 start..end
273 }
274
275 pub fn mark_attach_class_def2_offset_byte_range(&self) -> Range<usize> {
276 let start = self.lig_caret_list2_offset_byte_range().end;
277 let end = if self.version().compatible((1u16, 4u16)) {
278 start + Offset32::RAW_BYTE_LEN
279 } else {
280 start
281 };
282 start..end
283 }
284
285 pub fn mark_glyph_sets_def2_offset_byte_range(&self) -> Range<usize> {
286 let start = self.mark_attach_class_def2_offset_byte_range().end;
287 let end = if self.version().compatible((1u16, 4u16)) {
288 start + Offset32::RAW_BYTE_LEN
289 } else {
290 start
291 };
292 start..end
293 }
294}
295
296const _: () = assert!(FontData::default_data_long_enough(Gdef::MIN_SIZE));
297
298impl Default for Gdef<'_> {
299 fn default() -> Self {
300 Self {
301 data: TableDataRef::new(FontData::default_table_data().as_bytes())
302 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
303 }
304 }
305}
306
307#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
309#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
310#[repr(u16)]
311#[allow(clippy::manual_non_exhaustive)]
312pub enum GlyphClassDef {
313 #[default]
314 Base = 1,
315 Ligature = 2,
316 Mark = 3,
317 Component = 4,
318 #[doc(hidden)]
319 Unknown,
321}
322
323impl GlyphClassDef {
324 pub fn new(raw: u16) -> Self {
328 match raw {
329 1 => Self::Base,
330 2 => Self::Ligature,
331 3 => Self::Mark,
332 4 => Self::Component,
333 _ => Self::Unknown,
334 }
335 }
336}
337
338impl font_types::Scalar for GlyphClassDef {
339 type Raw = <u16 as font_types::Scalar>::Raw;
340 fn to_raw(self) -> Self::Raw {
341 (self as u16).to_raw()
342 }
343 fn from_raw(raw: Self::Raw) -> Self {
344 let t = <u16>::from_raw(raw);
345 Self::new(t)
346 }
347}
348
349impl<'a> MinByteRange<'a> for AttachList<'a> {
350 fn min_byte_range(&self) -> Range<usize> {
351 0..self.attach_point_offsets_byte_range().end
352 }
353 fn min_table_bytes(&self) -> &'a [u8] {
354 let range = self.min_byte_range();
355 self.offset_data().as_bytes().get(range).unwrap_or_default()
356 }
357}
358
359impl ReadArgs for AttachList<'_> {
360 type Args = ();
361}
362
363impl<'a> FontRead<'a> for AttachList<'a> {
364 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
365 #[allow(clippy::absurd_extreme_comparisons)]
366 if data.len() < Self::MIN_SIZE {
367 return Err(ReadError::OutOfBounds);
368 }
369 let Some(data) = TableDataRef::new(data.as_bytes()) else {
370 return Err(ReadError::OutOfBounds);
371 };
372 Ok(Self { data })
373 }
374}
375
376#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
378#[repr(C, packed)]
379#[doc(hidden)]
380pub struct AttachListFixedHeader {
381 pub coverage_offset: BigEndian<Offset16>,
382 pub glyph_count: BigEndian<u16>,
383}
384
385#[allow(clippy::absurd_extreme_comparisons)]
386const _: () = assert!(std::mem::size_of::<AttachListFixedHeader>() <= AttachList::MIN_SIZE);
387
388#[derive(Clone)]
390pub struct AttachList<'a> {
391 data: TableDataRef<'a, AttachListFixedHeader>,
392}
393
394#[allow(clippy::needless_lifetimes)]
395impl<'a> AttachList<'a> {
396 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
397 basic_table_impls!(impl_the_methods);
398
399 pub fn coverage_offset(&self) -> Offset16 {
401 self.data.header().coverage_offset.get()
402 }
403
404 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
406 let data = self.offset_data();
407 self.coverage_offset().resolve(data)
408 }
409
410 pub fn glyph_count(&self) -> u16 {
412 self.data.header().glyph_count.get()
413 }
414
415 pub fn attach_point_offsets(&self) -> &'a [BigEndian<Offset16>] {
418 let range = self.attach_point_offsets_byte_range();
419 self.offset_data()
420 .read_array(range)
421 .ok()
422 .unwrap_or_default()
423 }
424
425 pub fn attach_points(&self) -> ArrayOfOffsets<'a, AttachPoint<'a>, Offset16> {
427 let data = self.offset_data();
428 let offsets = self.attach_point_offsets();
429 ArrayOfOffsets::new(offsets, data, ())
430 }
431
432 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
433 let start = 0;
434 let end = start + Offset16::RAW_BYTE_LEN;
435 start..end
436 }
437
438 pub fn glyph_count_byte_range(&self) -> Range<usize> {
439 let start = self.coverage_offset_byte_range().end;
440 let end = start + u16::RAW_BYTE_LEN;
441 start..end
442 }
443
444 pub fn attach_point_offsets_byte_range(&self) -> Range<usize> {
445 let glyph_count = self.glyph_count();
446 let start = self.glyph_count_byte_range().end;
447 let end =
448 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
449 start..end
450 }
451}
452
453const _: () = assert!(FontData::default_data_long_enough(AttachList::MIN_SIZE));
454
455impl Default for AttachList<'_> {
456 fn default() -> Self {
457 Self {
458 data: TableDataRef::new(FontData::default_table_data().as_bytes())
459 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
460 }
461 }
462}
463
464impl<'a> MinByteRange<'a> for AttachPoint<'a> {
465 fn min_byte_range(&self) -> Range<usize> {
466 0..self.point_indices_byte_range().end
467 }
468 fn min_table_bytes(&self) -> &'a [u8] {
469 let range = self.min_byte_range();
470 self.offset_data().as_bytes().get(range).unwrap_or_default()
471 }
472}
473
474impl ReadArgs for AttachPoint<'_> {
475 type Args = ();
476}
477
478impl<'a> FontRead<'a> for AttachPoint<'a> {
479 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
480 #[allow(clippy::absurd_extreme_comparisons)]
481 if data.len() < Self::MIN_SIZE {
482 return Err(ReadError::OutOfBounds);
483 }
484 let Some(data) = TableDataRef::new(data.as_bytes()) else {
485 return Err(ReadError::OutOfBounds);
486 };
487 Ok(Self { data })
488 }
489}
490
491#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
493#[repr(C, packed)]
494#[doc(hidden)]
495pub struct AttachPointFixedHeader {
496 pub point_count: BigEndian<u16>,
497}
498
499#[allow(clippy::absurd_extreme_comparisons)]
500const _: () = assert!(std::mem::size_of::<AttachPointFixedHeader>() <= AttachPoint::MIN_SIZE);
501
502#[derive(Clone)]
504pub struct AttachPoint<'a> {
505 data: TableDataRef<'a, AttachPointFixedHeader>,
506}
507
508#[allow(clippy::needless_lifetimes)]
509impl<'a> AttachPoint<'a> {
510 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
511 basic_table_impls!(impl_the_methods);
512
513 pub fn point_count(&self) -> u16 {
515 self.data.header().point_count.get()
516 }
517
518 pub fn point_indices(&self) -> &'a [BigEndian<u16>] {
520 let range = self.point_indices_byte_range();
521 self.offset_data()
522 .read_array(range)
523 .ok()
524 .unwrap_or_default()
525 }
526
527 pub fn point_count_byte_range(&self) -> Range<usize> {
528 let start = 0;
529 let end = start + u16::RAW_BYTE_LEN;
530 start..end
531 }
532
533 pub fn point_indices_byte_range(&self) -> Range<usize> {
534 let point_count = self.point_count();
535 let start = self.point_count_byte_range().end;
536 let end = start + (transforms::to_usize(point_count)).saturating_mul(u16::RAW_BYTE_LEN);
537 start..end
538 }
539}
540
541const _: () = assert!(FontData::default_data_long_enough(AttachPoint::MIN_SIZE));
542
543impl Default for AttachPoint<'_> {
544 fn default() -> Self {
545 Self {
546 data: TableDataRef::new(FontData::default_table_data().as_bytes())
547 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
548 }
549 }
550}
551
552impl<'a> MinByteRange<'a> for LigCaretList<'a> {
553 fn min_byte_range(&self) -> Range<usize> {
554 0..self.lig_glyph_offsets_byte_range().end
555 }
556 fn min_table_bytes(&self) -> &'a [u8] {
557 let range = self.min_byte_range();
558 self.offset_data().as_bytes().get(range).unwrap_or_default()
559 }
560}
561
562impl ReadArgs for LigCaretList<'_> {
563 type Args = ();
564}
565
566impl<'a> FontRead<'a> for LigCaretList<'a> {
567 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
568 #[allow(clippy::absurd_extreme_comparisons)]
569 if data.len() < Self::MIN_SIZE {
570 return Err(ReadError::OutOfBounds);
571 }
572 let Some(data) = TableDataRef::new(data.as_bytes()) else {
573 return Err(ReadError::OutOfBounds);
574 };
575 Ok(Self { data })
576 }
577}
578
579#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
581#[repr(C, packed)]
582#[doc(hidden)]
583pub struct LigCaretListFixedHeader {
584 pub coverage_offset: BigEndian<Offset16>,
585 pub lig_glyph_count: BigEndian<u16>,
586}
587
588#[allow(clippy::absurd_extreme_comparisons)]
589const _: () = assert!(std::mem::size_of::<LigCaretListFixedHeader>() <= LigCaretList::MIN_SIZE);
590
591#[derive(Clone)]
593pub struct LigCaretList<'a> {
594 data: TableDataRef<'a, LigCaretListFixedHeader>,
595}
596
597#[allow(clippy::needless_lifetimes)]
598impl<'a> LigCaretList<'a> {
599 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
600 basic_table_impls!(impl_the_methods);
601
602 pub fn coverage_offset(&self) -> Offset16 {
604 self.data.header().coverage_offset.get()
605 }
606
607 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
609 let data = self.offset_data();
610 self.coverage_offset().resolve(data)
611 }
612
613 pub fn lig_glyph_count(&self) -> u16 {
615 self.data.header().lig_glyph_count.get()
616 }
617
618 pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset16>] {
621 let range = self.lig_glyph_offsets_byte_range();
622 self.offset_data()
623 .read_array(range)
624 .ok()
625 .unwrap_or_default()
626 }
627
628 pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset16> {
630 let data = self.offset_data();
631 let offsets = self.lig_glyph_offsets();
632 ArrayOfOffsets::new(offsets, data, ())
633 }
634
635 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
636 let start = 0;
637 let end = start + Offset16::RAW_BYTE_LEN;
638 start..end
639 }
640
641 pub fn lig_glyph_count_byte_range(&self) -> Range<usize> {
642 let start = self.coverage_offset_byte_range().end;
643 let end = start + u16::RAW_BYTE_LEN;
644 start..end
645 }
646
647 pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> {
648 let lig_glyph_count = self.lig_glyph_count();
649 let start = self.lig_glyph_count_byte_range().end;
650 let end =
651 start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
652 start..end
653 }
654}
655
656const _: () = assert!(FontData::default_data_long_enough(LigCaretList::MIN_SIZE));
657
658impl Default for LigCaretList<'_> {
659 fn default() -> Self {
660 Self {
661 data: TableDataRef::new(FontData::default_table_data().as_bytes())
662 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
663 }
664 }
665}
666
667impl<'a> MinByteRange<'a> for LigGlyph<'a> {
668 fn min_byte_range(&self) -> Range<usize> {
669 0..self.caret_value_offsets_byte_range().end
670 }
671 fn min_table_bytes(&self) -> &'a [u8] {
672 let range = self.min_byte_range();
673 self.offset_data().as_bytes().get(range).unwrap_or_default()
674 }
675}
676
677impl ReadArgs for LigGlyph<'_> {
678 type Args = ();
679}
680
681impl<'a> FontRead<'a> for LigGlyph<'a> {
682 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
683 #[allow(clippy::absurd_extreme_comparisons)]
684 if data.len() < Self::MIN_SIZE {
685 return Err(ReadError::OutOfBounds);
686 }
687 let Some(data) = TableDataRef::new(data.as_bytes()) else {
688 return Err(ReadError::OutOfBounds);
689 };
690 Ok(Self { data })
691 }
692}
693
694#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
696#[repr(C, packed)]
697#[doc(hidden)]
698pub struct LigGlyphFixedHeader {
699 pub caret_count: BigEndian<u16>,
700}
701
702#[allow(clippy::absurd_extreme_comparisons)]
703const _: () = assert!(std::mem::size_of::<LigGlyphFixedHeader>() <= LigGlyph::MIN_SIZE);
704
705#[derive(Clone)]
707pub struct LigGlyph<'a> {
708 data: TableDataRef<'a, LigGlyphFixedHeader>,
709}
710
711#[allow(clippy::needless_lifetimes)]
712impl<'a> LigGlyph<'a> {
713 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
714 basic_table_impls!(impl_the_methods);
715
716 pub fn caret_count(&self) -> u16 {
718 self.data.header().caret_count.get()
719 }
720
721 pub fn caret_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
724 let range = self.caret_value_offsets_byte_range();
725 self.offset_data()
726 .read_array(range)
727 .ok()
728 .unwrap_or_default()
729 }
730
731 pub fn caret_values(&self) -> ArrayOfOffsets<'a, CaretValue<'a>, Offset16> {
733 let data = self.offset_data();
734 let offsets = self.caret_value_offsets();
735 ArrayOfOffsets::new(offsets, data, ())
736 }
737
738 pub fn caret_count_byte_range(&self) -> Range<usize> {
739 let start = 0;
740 let end = start + u16::RAW_BYTE_LEN;
741 start..end
742 }
743
744 pub fn caret_value_offsets_byte_range(&self) -> Range<usize> {
745 let caret_count = self.caret_count();
746 let start = self.caret_count_byte_range().end;
747 let end =
748 start + (transforms::to_usize(caret_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
749 start..end
750 }
751}
752
753const _: () = assert!(FontData::default_data_long_enough(LigGlyph::MIN_SIZE));
754
755impl Default for LigGlyph<'_> {
756 fn default() -> Self {
757 Self {
758 data: TableDataRef::new(FontData::default_table_data().as_bytes())
759 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
760 }
761 }
762}
763
764#[derive(Clone)]
766pub enum CaretValue<'a> {
767 Format1(CaretValueFormat1<'a>),
768 Format2(CaretValueFormat2<'a>),
769 Format3(CaretValueFormat3<'a>),
770}
771
772impl Default for CaretValue<'_> {
773 fn default() -> Self {
774 Self::Format1(Default::default())
775 }
776}
777
778impl<'a> CaretValue<'a> {
779 pub fn offset_data(&self) -> FontData<'a> {
781 match self {
782 Self::Format1(item) => item.offset_data(),
783 Self::Format2(item) => item.offset_data(),
784 Self::Format3(item) => item.offset_data(),
785 }
786 }
787
788 pub fn caret_value_format(&self) -> u16 {
790 match self {
791 Self::Format1(item) => item.caret_value_format(),
792 Self::Format2(item) => item.caret_value_format(),
793 Self::Format3(item) => item.caret_value_format(),
794 }
795 }
796}
797
798impl ReadArgs for CaretValue<'_> {
799 type Args = ();
800}
801
802impl<'a> FontRead<'a> for CaretValue<'a> {
803 #[inline]
804 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
805 let format: u16 = data.read_at(0usize)?;
806 match format {
807 CaretValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
808 CaretValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
809 CaretValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
810 other => Err(ReadError::InvalidFormat(other.into())),
811 }
812 }
813}
814
815impl<'a> MinByteRange<'a> for CaretValue<'a> {
816 fn min_byte_range(&self) -> Range<usize> {
817 match self {
818 Self::Format1(item) => item.min_byte_range(),
819 Self::Format2(item) => item.min_byte_range(),
820 Self::Format3(item) => item.min_byte_range(),
821 }
822 }
823 fn min_table_bytes(&self) -> &'a [u8] {
824 match self {
825 Self::Format1(item) => item.min_table_bytes(),
826 Self::Format2(item) => item.min_table_bytes(),
827 Self::Format3(item) => item.min_table_bytes(),
828 }
829 }
830}
831
832impl Format<u16> for CaretValueFormat1<'_> {
833 const FORMAT: u16 = 1;
834}
835
836impl<'a> MinByteRange<'a> for CaretValueFormat1<'a> {
837 fn min_byte_range(&self) -> Range<usize> {
838 0..self.coordinate_byte_range().end
839 }
840 fn min_table_bytes(&self) -> &'a [u8] {
841 let range = self.min_byte_range();
842 self.offset_data().as_bytes().get(range).unwrap_or_default()
843 }
844}
845
846impl ReadArgs for CaretValueFormat1<'_> {
847 type Args = ();
848}
849
850impl<'a> FontRead<'a> for CaretValueFormat1<'a> {
851 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
852 #[allow(clippy::absurd_extreme_comparisons)]
853 if data.len() < Self::MIN_SIZE {
854 return Err(ReadError::OutOfBounds);
855 }
856 let Some(data) = TableDataRef::new(data.as_bytes()) else {
857 return Err(ReadError::OutOfBounds);
858 };
859 Ok(Self { data })
860 }
861}
862
863#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
865#[repr(C, packed)]
866#[doc(hidden)]
867pub struct CaretValueFormat1FixedHeader {
868 pub caret_value_format: BigEndian<u16>,
869 pub coordinate: BigEndian<i16>,
870}
871
872#[allow(clippy::absurd_extreme_comparisons)]
873const _: () =
874 assert!(std::mem::size_of::<CaretValueFormat1FixedHeader>() <= CaretValueFormat1::MIN_SIZE);
875
876#[derive(Clone)]
878pub struct CaretValueFormat1<'a> {
879 data: TableDataRef<'a, CaretValueFormat1FixedHeader>,
880}
881
882#[allow(clippy::needless_lifetimes)]
883impl<'a> CaretValueFormat1<'a> {
884 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
885 basic_table_impls!(impl_the_methods);
886
887 pub fn caret_value_format(&self) -> u16 {
889 self.data.header().caret_value_format.get()
890 }
891
892 pub fn coordinate(&self) -> i16 {
894 self.data.header().coordinate.get()
895 }
896
897 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
898 let start = 0;
899 let end = start + u16::RAW_BYTE_LEN;
900 start..end
901 }
902
903 pub fn coordinate_byte_range(&self) -> Range<usize> {
904 let start = self.caret_value_format_byte_range().end;
905 let end = start + i16::RAW_BYTE_LEN;
906 start..end
907 }
908}
909
910const _: () = assert!(FontData::default_data_long_enough(
911 CaretValueFormat1::MIN_SIZE
912));
913
914impl Default for CaretValueFormat1<'_> {
915 fn default() -> Self {
916 Self {
917 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
918 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
919 }
920 }
921}
922
923impl Format<u16> for CaretValueFormat2<'_> {
924 const FORMAT: u16 = 2;
925}
926
927impl<'a> MinByteRange<'a> for CaretValueFormat2<'a> {
928 fn min_byte_range(&self) -> Range<usize> {
929 0..self.caret_value_point_index_byte_range().end
930 }
931 fn min_table_bytes(&self) -> &'a [u8] {
932 let range = self.min_byte_range();
933 self.offset_data().as_bytes().get(range).unwrap_or_default()
934 }
935}
936
937impl ReadArgs for CaretValueFormat2<'_> {
938 type Args = ();
939}
940
941impl<'a> FontRead<'a> for CaretValueFormat2<'a> {
942 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
943 #[allow(clippy::absurd_extreme_comparisons)]
944 if data.len() < Self::MIN_SIZE {
945 return Err(ReadError::OutOfBounds);
946 }
947 let Some(data) = TableDataRef::new(data.as_bytes()) else {
948 return Err(ReadError::OutOfBounds);
949 };
950 Ok(Self { data })
951 }
952}
953
954#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
956#[repr(C, packed)]
957#[doc(hidden)]
958pub struct CaretValueFormat2FixedHeader {
959 pub caret_value_format: BigEndian<u16>,
960 pub caret_value_point_index: BigEndian<u16>,
961}
962
963#[allow(clippy::absurd_extreme_comparisons)]
964const _: () =
965 assert!(std::mem::size_of::<CaretValueFormat2FixedHeader>() <= CaretValueFormat2::MIN_SIZE);
966
967#[derive(Clone)]
969pub struct CaretValueFormat2<'a> {
970 data: TableDataRef<'a, CaretValueFormat2FixedHeader>,
971}
972
973#[allow(clippy::needless_lifetimes)]
974impl<'a> CaretValueFormat2<'a> {
975 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
976 basic_table_impls!(impl_the_methods);
977
978 pub fn caret_value_format(&self) -> u16 {
980 self.data.header().caret_value_format.get()
981 }
982
983 pub fn caret_value_point_index(&self) -> u16 {
985 self.data.header().caret_value_point_index.get()
986 }
987
988 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
989 let start = 0;
990 let end = start + u16::RAW_BYTE_LEN;
991 start..end
992 }
993
994 pub fn caret_value_point_index_byte_range(&self) -> Range<usize> {
995 let start = self.caret_value_format_byte_range().end;
996 let end = start + u16::RAW_BYTE_LEN;
997 start..end
998 }
999}
1000
1001impl Format<u16> for CaretValueFormat3<'_> {
1002 const FORMAT: u16 = 3;
1003}
1004
1005impl<'a> MinByteRange<'a> for CaretValueFormat3<'a> {
1006 fn min_byte_range(&self) -> Range<usize> {
1007 0..self.device_offset_byte_range().end
1008 }
1009 fn min_table_bytes(&self) -> &'a [u8] {
1010 let range = self.min_byte_range();
1011 self.offset_data().as_bytes().get(range).unwrap_or_default()
1012 }
1013}
1014
1015impl ReadArgs for CaretValueFormat3<'_> {
1016 type Args = ();
1017}
1018
1019impl<'a> FontRead<'a> for CaretValueFormat3<'a> {
1020 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1021 #[allow(clippy::absurd_extreme_comparisons)]
1022 if data.len() < Self::MIN_SIZE {
1023 return Err(ReadError::OutOfBounds);
1024 }
1025 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1026 return Err(ReadError::OutOfBounds);
1027 };
1028 Ok(Self { data })
1029 }
1030}
1031
1032#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1034#[repr(C, packed)]
1035#[doc(hidden)]
1036pub struct CaretValueFormat3FixedHeader {
1037 pub caret_value_format: BigEndian<u16>,
1038 pub coordinate: BigEndian<i16>,
1039 pub device_offset: BigEndian<Offset16>,
1040}
1041
1042#[allow(clippy::absurd_extreme_comparisons)]
1043const _: () =
1044 assert!(std::mem::size_of::<CaretValueFormat3FixedHeader>() <= CaretValueFormat3::MIN_SIZE);
1045
1046#[derive(Clone)]
1048pub struct CaretValueFormat3<'a> {
1049 data: TableDataRef<'a, CaretValueFormat3FixedHeader>,
1050}
1051
1052#[allow(clippy::needless_lifetimes)]
1053impl<'a> CaretValueFormat3<'a> {
1054 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
1055 basic_table_impls!(impl_the_methods);
1056
1057 pub fn caret_value_format(&self) -> u16 {
1059 self.data.header().caret_value_format.get()
1060 }
1061
1062 pub fn coordinate(&self) -> i16 {
1064 self.data.header().coordinate.get()
1065 }
1066
1067 pub fn device_offset(&self) -> Offset16 {
1071 self.data.header().device_offset.get()
1072 }
1073
1074 pub fn device(&self) -> Result<DeviceOrVariationIndex<'a>, ReadError> {
1076 let data = self.offset_data();
1077 self.device_offset().resolve(data)
1078 }
1079
1080 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
1081 let start = 0;
1082 let end = start + u16::RAW_BYTE_LEN;
1083 start..end
1084 }
1085
1086 pub fn coordinate_byte_range(&self) -> Range<usize> {
1087 let start = self.caret_value_format_byte_range().end;
1088 let end = start + i16::RAW_BYTE_LEN;
1089 start..end
1090 }
1091
1092 pub fn device_offset_byte_range(&self) -> Range<usize> {
1093 let start = self.coordinate_byte_range().end;
1094 let end = start + Offset16::RAW_BYTE_LEN;
1095 start..end
1096 }
1097}
1098
1099impl Format<u16> for MarkGlyphSets<'_> {
1100 const FORMAT: u16 = 1;
1101}
1102
1103impl<'a> MinByteRange<'a> for MarkGlyphSets<'a> {
1104 fn min_byte_range(&self) -> Range<usize> {
1105 0..self.coverage_offsets_byte_range().end
1106 }
1107 fn min_table_bytes(&self) -> &'a [u8] {
1108 let range = self.min_byte_range();
1109 self.offset_data().as_bytes().get(range).unwrap_or_default()
1110 }
1111}
1112
1113impl ReadArgs for MarkGlyphSets<'_> {
1114 type Args = ();
1115}
1116
1117impl<'a> FontRead<'a> for MarkGlyphSets<'a> {
1118 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1119 #[allow(clippy::absurd_extreme_comparisons)]
1120 if data.len() < Self::MIN_SIZE {
1121 return Err(ReadError::OutOfBounds);
1122 }
1123 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1124 return Err(ReadError::OutOfBounds);
1125 };
1126 Ok(Self { data })
1127 }
1128}
1129
1130#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1132#[repr(C, packed)]
1133#[doc(hidden)]
1134pub struct MarkGlyphSetsFixedHeader {
1135 pub format: BigEndian<u16>,
1136 pub mark_glyph_set_count: BigEndian<u16>,
1137}
1138
1139#[allow(clippy::absurd_extreme_comparisons)]
1140const _: () = assert!(std::mem::size_of::<MarkGlyphSetsFixedHeader>() <= MarkGlyphSets::MIN_SIZE);
1141
1142#[derive(Clone)]
1144pub struct MarkGlyphSets<'a> {
1145 data: TableDataRef<'a, MarkGlyphSetsFixedHeader>,
1146}
1147
1148#[allow(clippy::needless_lifetimes)]
1149impl<'a> MarkGlyphSets<'a> {
1150 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1151 basic_table_impls!(impl_the_methods);
1152
1153 pub fn format(&self) -> u16 {
1155 self.data.header().format.get()
1156 }
1157
1158 pub fn mark_glyph_set_count(&self) -> u16 {
1160 self.data.header().mark_glyph_set_count.get()
1161 }
1162
1163 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset32>] {
1166 let range = self.coverage_offsets_byte_range();
1167 self.offset_data()
1168 .read_array(range)
1169 .ok()
1170 .unwrap_or_default()
1171 }
1172
1173 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset32> {
1175 let data = self.offset_data();
1176 let offsets = self.coverage_offsets();
1177 ArrayOfOffsets::new(offsets, data, ())
1178 }
1179
1180 pub fn format_byte_range(&self) -> Range<usize> {
1181 let start = 0;
1182 let end = start + u16::RAW_BYTE_LEN;
1183 start..end
1184 }
1185
1186 pub fn mark_glyph_set_count_byte_range(&self) -> Range<usize> {
1187 let start = self.format_byte_range().end;
1188 let end = start + u16::RAW_BYTE_LEN;
1189 start..end
1190 }
1191
1192 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
1193 let mark_glyph_set_count = self.mark_glyph_set_count();
1194 let start = self.mark_glyph_set_count_byte_range().end;
1195 let end = start
1196 + (transforms::to_usize(mark_glyph_set_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
1197 start..end
1198 }
1199}
1200
1201const _: () = assert!(FontData::default_data_long_enough(MarkGlyphSets::MIN_SIZE));
1202
1203impl Default for MarkGlyphSets<'_> {
1204 fn default() -> Self {
1205 Self {
1206 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1207 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1208 }
1209 }
1210}
1211
1212impl<'a> MinByteRange<'a> for LigCaretList2<'a> {
1213 fn min_byte_range(&self) -> Range<usize> {
1214 0..self.lig_glyph_offsets_byte_range().end
1215 }
1216 fn min_table_bytes(&self) -> &'a [u8] {
1217 let range = self.min_byte_range();
1218 self.offset_data().as_bytes().get(range).unwrap_or_default()
1219 }
1220}
1221
1222impl ReadArgs for LigCaretList2<'_> {
1223 type Args = ();
1224}
1225
1226impl<'a> FontRead<'a> for LigCaretList2<'a> {
1227 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1228 #[allow(clippy::absurd_extreme_comparisons)]
1229 if data.len() < Self::MIN_SIZE {
1230 return Err(ReadError::OutOfBounds);
1231 }
1232 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1233 return Err(ReadError::OutOfBounds);
1234 };
1235 Ok(Self { data })
1236 }
1237}
1238
1239#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1241#[repr(C, packed)]
1242#[doc(hidden)]
1243pub struct LigCaretList2FixedHeader {
1244 pub coverage_offset: BigEndian<Offset32>,
1245 pub lig_glyph_count: BigEndian<Uint24>,
1246}
1247
1248#[allow(clippy::absurd_extreme_comparisons)]
1249const _: () = assert!(std::mem::size_of::<LigCaretList2FixedHeader>() <= LigCaretList2::MIN_SIZE);
1250
1251#[derive(Clone)]
1253pub struct LigCaretList2<'a> {
1254 data: TableDataRef<'a, LigCaretList2FixedHeader>,
1255}
1256
1257#[allow(clippy::needless_lifetimes)]
1258impl<'a> LigCaretList2<'a> {
1259 pub const MIN_SIZE: usize = (Offset32::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN);
1260 basic_table_impls!(impl_the_methods);
1261
1262 pub fn coverage_offset(&self) -> Offset32 {
1264 self.data.header().coverage_offset.get()
1265 }
1266
1267 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1269 let data = self.offset_data();
1270 self.coverage_offset().resolve(data)
1271 }
1272
1273 pub fn lig_glyph_count(&self) -> Uint24 {
1275 self.data.header().lig_glyph_count.get()
1276 }
1277
1278 pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset24>] {
1281 let range = self.lig_glyph_offsets_byte_range();
1282 self.offset_data()
1283 .read_array(range)
1284 .ok()
1285 .unwrap_or_default()
1286 }
1287
1288 pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset24> {
1290 let data = self.offset_data();
1291 let offsets = self.lig_glyph_offsets();
1292 ArrayOfOffsets::new(offsets, data, ())
1293 }
1294
1295 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1296 let start = 0;
1297 let end = start + Offset32::RAW_BYTE_LEN;
1298 start..end
1299 }
1300
1301 pub fn lig_glyph_count_byte_range(&self) -> Range<usize> {
1302 let start = self.coverage_offset_byte_range().end;
1303 let end = start + Uint24::RAW_BYTE_LEN;
1304 start..end
1305 }
1306
1307 pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> {
1308 let lig_glyph_count = self.lig_glyph_count();
1309 let start = self.lig_glyph_count_byte_range().end;
1310 let end =
1311 start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
1312 start..end
1313 }
1314}
1315
1316const _: () = assert!(FontData::default_data_long_enough(LigCaretList2::MIN_SIZE));
1317
1318impl Default for LigCaretList2<'_> {
1319 fn default() -> Self {
1320 Self {
1321 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1322 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1323 }
1324 }
1325}