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.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<'a> FontRead<'a> for Gdef<'a> {
24 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25 #[allow(clippy::absurd_extreme_comparisons)]
26 if data.len() < Self::MIN_SIZE {
27 return Err(ReadError::OutOfBounds);
28 }
29 Ok(Self { data })
30 }
31}
32
33#[derive(Clone)]
35pub struct Gdef<'a> {
36 data: FontData<'a>,
37}
38
39#[allow(clippy::needless_lifetimes)]
40impl<'a> Gdef<'a> {
41 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
42 + Offset16::RAW_BYTE_LEN
43 + Offset16::RAW_BYTE_LEN
44 + Offset16::RAW_BYTE_LEN
45 + Offset16::RAW_BYTE_LEN);
46 basic_table_impls!(impl_the_methods);
47
48 pub fn version(&self) -> MajorMinor {
50 let range = self.version_byte_range();
51 self.data.read_at(range.start).ok().unwrap()
52 }
53
54 pub fn glyph_class_def_offset(&self) -> Nullable<Offset16> {
57 let range = self.glyph_class_def_offset_byte_range();
58 self.data.read_at(range.start).ok().unwrap()
59 }
60
61 pub fn glyph_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
63 let data = self.data;
64 self.glyph_class_def_offset().resolve(data)
65 }
66
67 pub fn attach_list_offset(&self) -> Nullable<Offset16> {
70 let range = self.attach_list_offset_byte_range();
71 self.data.read_at(range.start).ok().unwrap()
72 }
73
74 pub fn attach_list(&self) -> Option<Result<AttachList<'a>, ReadError>> {
76 let data = self.data;
77 self.attach_list_offset().resolve(data)
78 }
79
80 pub fn lig_caret_list_offset(&self) -> Nullable<Offset16> {
83 let range = self.lig_caret_list_offset_byte_range();
84 self.data.read_at(range.start).ok().unwrap()
85 }
86
87 pub fn lig_caret_list(&self) -> Option<Result<LigCaretList<'a>, ReadError>> {
89 let data = self.data;
90 self.lig_caret_list_offset().resolve(data)
91 }
92
93 pub fn mark_attach_class_def_offset(&self) -> Nullable<Offset16> {
96 let range = self.mark_attach_class_def_offset_byte_range();
97 self.data.read_at(range.start).ok().unwrap()
98 }
99
100 pub fn mark_attach_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
102 let data = self.data;
103 self.mark_attach_class_def_offset().resolve(data)
104 }
105
106 pub fn mark_glyph_sets_def_offset(&self) -> Option<Nullable<Offset16>> {
109 let range = self.mark_glyph_sets_def_offset_byte_range();
110 (!range.is_empty())
111 .then(|| self.data.read_at(range.start).ok())
112 .flatten()
113 }
114
115 pub fn mark_glyph_sets_def(&self) -> Option<Result<MarkGlyphSets<'a>, ReadError>> {
117 let data = self.data;
118 self.mark_glyph_sets_def_offset().map(|x| x.resolve(data))?
119 }
120
121 pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> {
124 let range = self.item_var_store_offset_byte_range();
125 (!range.is_empty())
126 .then(|| self.data.read_at(range.start).ok())
127 .flatten()
128 }
129
130 pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
132 let data = self.data;
133 self.item_var_store_offset().map(|x| x.resolve(data))?
134 }
135
136 pub fn version_byte_range(&self) -> Range<usize> {
137 let start = 0;
138 start..start + MajorMinor::RAW_BYTE_LEN
139 }
140
141 pub fn glyph_class_def_offset_byte_range(&self) -> Range<usize> {
142 let start = self.version_byte_range().end;
143 start..start + Offset16::RAW_BYTE_LEN
144 }
145
146 pub fn attach_list_offset_byte_range(&self) -> Range<usize> {
147 let start = self.glyph_class_def_offset_byte_range().end;
148 start..start + Offset16::RAW_BYTE_LEN
149 }
150
151 pub fn lig_caret_list_offset_byte_range(&self) -> Range<usize> {
152 let start = self.attach_list_offset_byte_range().end;
153 start..start + Offset16::RAW_BYTE_LEN
154 }
155
156 pub fn mark_attach_class_def_offset_byte_range(&self) -> Range<usize> {
157 let start = self.lig_caret_list_offset_byte_range().end;
158 start..start + Offset16::RAW_BYTE_LEN
159 }
160
161 pub fn mark_glyph_sets_def_offset_byte_range(&self) -> Range<usize> {
162 let start = self.mark_attach_class_def_offset_byte_range().end;
163 start
164 ..(self.version().compatible((1u16, 2u16)))
165 .then(|| start + Offset16::RAW_BYTE_LEN)
166 .unwrap_or(start)
167 }
168
169 pub fn item_var_store_offset_byte_range(&self) -> Range<usize> {
170 let start = self.mark_glyph_sets_def_offset_byte_range().end;
171 start
172 ..(self.version().compatible((1u16, 3u16)))
173 .then(|| start + Offset32::RAW_BYTE_LEN)
174 .unwrap_or(start)
175 }
176}
177
178const _: () = assert!(FontData::default_data_long_enough(Gdef::MIN_SIZE));
179
180impl Default for Gdef<'_> {
181 fn default() -> Self {
182 Self {
183 data: FontData::default_table_data(),
184 }
185 }
186}
187
188#[cfg(feature = "experimental_traverse")]
189impl<'a> SomeTable<'a> for Gdef<'a> {
190 fn type_name(&self) -> &str {
191 "Gdef"
192 }
193 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
194 match idx {
195 0usize => Some(Field::new("version", self.version())),
196 1usize => Some(Field::new(
197 "glyph_class_def_offset",
198 FieldType::offset(self.glyph_class_def_offset(), self.glyph_class_def()),
199 )),
200 2usize => Some(Field::new(
201 "attach_list_offset",
202 FieldType::offset(self.attach_list_offset(), self.attach_list()),
203 )),
204 3usize => Some(Field::new(
205 "lig_caret_list_offset",
206 FieldType::offset(self.lig_caret_list_offset(), self.lig_caret_list()),
207 )),
208 4usize => Some(Field::new(
209 "mark_attach_class_def_offset",
210 FieldType::offset(
211 self.mark_attach_class_def_offset(),
212 self.mark_attach_class_def(),
213 ),
214 )),
215 5usize if self.version().compatible((1u16, 2u16)) => Some(Field::new(
216 "mark_glyph_sets_def_offset",
217 FieldType::offset(
218 self.mark_glyph_sets_def_offset().unwrap(),
219 self.mark_glyph_sets_def(),
220 ),
221 )),
222 6usize if self.version().compatible((1u16, 3u16)) => Some(Field::new(
223 "item_var_store_offset",
224 FieldType::offset(self.item_var_store_offset().unwrap(), self.item_var_store()),
225 )),
226 _ => None,
227 }
228 }
229}
230
231#[cfg(feature = "experimental_traverse")]
232#[allow(clippy::needless_lifetimes)]
233impl<'a> std::fmt::Debug for Gdef<'a> {
234 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235 (self as &dyn SomeTable<'a>).fmt(f)
236 }
237}
238
239#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
241#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
242#[repr(u16)]
243#[allow(clippy::manual_non_exhaustive)]
244pub enum GlyphClassDef {
245 #[default]
246 Base = 1,
247 Ligature = 2,
248 Mark = 3,
249 Component = 4,
250 #[doc(hidden)]
251 Unknown,
253}
254
255impl GlyphClassDef {
256 pub fn new(raw: u16) -> Self {
260 match raw {
261 1 => Self::Base,
262 2 => Self::Ligature,
263 3 => Self::Mark,
264 4 => Self::Component,
265 _ => Self::Unknown,
266 }
267 }
268}
269
270impl font_types::Scalar for GlyphClassDef {
271 type Raw = <u16 as font_types::Scalar>::Raw;
272 fn to_raw(self) -> Self::Raw {
273 (self as u16).to_raw()
274 }
275 fn from_raw(raw: Self::Raw) -> Self {
276 let t = <u16>::from_raw(raw);
277 Self::new(t)
278 }
279}
280
281#[cfg(feature = "experimental_traverse")]
282impl<'a> From<GlyphClassDef> for FieldType<'a> {
283 fn from(src: GlyphClassDef) -> FieldType<'a> {
284 (src as u16).into()
285 }
286}
287
288impl<'a> MinByteRange<'a> for AttachList<'a> {
289 fn min_byte_range(&self) -> Range<usize> {
290 0..self.attach_point_offsets_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<'a> FontRead<'a> for AttachList<'a> {
299 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
300 #[allow(clippy::absurd_extreme_comparisons)]
301 if data.len() < Self::MIN_SIZE {
302 return Err(ReadError::OutOfBounds);
303 }
304 Ok(Self { data })
305 }
306}
307
308#[derive(Clone)]
310pub struct AttachList<'a> {
311 data: FontData<'a>,
312}
313
314#[allow(clippy::needless_lifetimes)]
315impl<'a> AttachList<'a> {
316 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
317 basic_table_impls!(impl_the_methods);
318
319 pub fn coverage_offset(&self) -> Offset16 {
321 let range = self.coverage_offset_byte_range();
322 self.data.read_at(range.start).ok().unwrap()
323 }
324
325 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
327 let data = self.data;
328 self.coverage_offset().resolve(data)
329 }
330
331 pub fn glyph_count(&self) -> u16 {
333 let range = self.glyph_count_byte_range();
334 self.data.read_at(range.start).ok().unwrap()
335 }
336
337 pub fn attach_point_offsets(&self) -> &'a [BigEndian<Offset16>] {
340 let range = self.attach_point_offsets_byte_range();
341 self.data.read_array(range).ok().unwrap_or_default()
342 }
343
344 pub fn attach_points(&self) -> ArrayOfOffsets<'a, AttachPoint<'a>, Offset16> {
346 let data = self.data;
347 let offsets = self.attach_point_offsets();
348 ArrayOfOffsets::new(offsets, data, ())
349 }
350
351 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
352 let start = 0;
353 start..start + Offset16::RAW_BYTE_LEN
354 }
355
356 pub fn glyph_count_byte_range(&self) -> Range<usize> {
357 let start = self.coverage_offset_byte_range().end;
358 start..start + u16::RAW_BYTE_LEN
359 }
360
361 pub fn attach_point_offsets_byte_range(&self) -> Range<usize> {
362 let glyph_count = self.glyph_count();
363 let start = self.glyph_count_byte_range().end;
364 start..start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN)
365 }
366}
367
368const _: () = assert!(FontData::default_data_long_enough(AttachList::MIN_SIZE));
369
370impl Default for AttachList<'_> {
371 fn default() -> Self {
372 Self {
373 data: FontData::default_table_data(),
374 }
375 }
376}
377
378#[cfg(feature = "experimental_traverse")]
379impl<'a> SomeTable<'a> for AttachList<'a> {
380 fn type_name(&self) -> &str {
381 "AttachList"
382 }
383 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
384 match idx {
385 0usize => Some(Field::new(
386 "coverage_offset",
387 FieldType::offset(self.coverage_offset(), self.coverage()),
388 )),
389 1usize => Some(Field::new("glyph_count", self.glyph_count())),
390 2usize => Some(Field::new(
391 "attach_point_offsets",
392 FieldType::from(self.attach_points()),
393 )),
394 _ => None,
395 }
396 }
397}
398
399#[cfg(feature = "experimental_traverse")]
400#[allow(clippy::needless_lifetimes)]
401impl<'a> std::fmt::Debug for AttachList<'a> {
402 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
403 (self as &dyn SomeTable<'a>).fmt(f)
404 }
405}
406
407impl<'a> MinByteRange<'a> for AttachPoint<'a> {
408 fn min_byte_range(&self) -> Range<usize> {
409 0..self.point_indices_byte_range().end
410 }
411 fn min_table_bytes(&self) -> &'a [u8] {
412 let range = self.min_byte_range();
413 self.data.as_bytes().get(range).unwrap_or_default()
414 }
415}
416
417impl<'a> FontRead<'a> for AttachPoint<'a> {
418 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
419 #[allow(clippy::absurd_extreme_comparisons)]
420 if data.len() < Self::MIN_SIZE {
421 return Err(ReadError::OutOfBounds);
422 }
423 Ok(Self { data })
424 }
425}
426
427#[derive(Clone)]
429pub struct AttachPoint<'a> {
430 data: FontData<'a>,
431}
432
433#[allow(clippy::needless_lifetimes)]
434impl<'a> AttachPoint<'a> {
435 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
436 basic_table_impls!(impl_the_methods);
437
438 pub fn point_count(&self) -> u16 {
440 let range = self.point_count_byte_range();
441 self.data.read_at(range.start).ok().unwrap()
442 }
443
444 pub fn point_indices(&self) -> &'a [BigEndian<u16>] {
446 let range = self.point_indices_byte_range();
447 self.data.read_array(range).ok().unwrap_or_default()
448 }
449
450 pub fn point_count_byte_range(&self) -> Range<usize> {
451 let start = 0;
452 start..start + u16::RAW_BYTE_LEN
453 }
454
455 pub fn point_indices_byte_range(&self) -> Range<usize> {
456 let point_count = self.point_count();
457 let start = self.point_count_byte_range().end;
458 start..start + (transforms::to_usize(point_count)).saturating_mul(u16::RAW_BYTE_LEN)
459 }
460}
461
462const _: () = assert!(FontData::default_data_long_enough(AttachPoint::MIN_SIZE));
463
464impl Default for AttachPoint<'_> {
465 fn default() -> Self {
466 Self {
467 data: FontData::default_table_data(),
468 }
469 }
470}
471
472#[cfg(feature = "experimental_traverse")]
473impl<'a> SomeTable<'a> for AttachPoint<'a> {
474 fn type_name(&self) -> &str {
475 "AttachPoint"
476 }
477 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
478 match idx {
479 0usize => Some(Field::new("point_count", self.point_count())),
480 1usize => Some(Field::new("point_indices", self.point_indices())),
481 _ => None,
482 }
483 }
484}
485
486#[cfg(feature = "experimental_traverse")]
487#[allow(clippy::needless_lifetimes)]
488impl<'a> std::fmt::Debug for AttachPoint<'a> {
489 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
490 (self as &dyn SomeTable<'a>).fmt(f)
491 }
492}
493
494impl<'a> MinByteRange<'a> for LigCaretList<'a> {
495 fn min_byte_range(&self) -> Range<usize> {
496 0..self.lig_glyph_offsets_byte_range().end
497 }
498 fn min_table_bytes(&self) -> &'a [u8] {
499 let range = self.min_byte_range();
500 self.data.as_bytes().get(range).unwrap_or_default()
501 }
502}
503
504impl<'a> FontRead<'a> for LigCaretList<'a> {
505 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
506 #[allow(clippy::absurd_extreme_comparisons)]
507 if data.len() < Self::MIN_SIZE {
508 return Err(ReadError::OutOfBounds);
509 }
510 Ok(Self { data })
511 }
512}
513
514#[derive(Clone)]
516pub struct LigCaretList<'a> {
517 data: FontData<'a>,
518}
519
520#[allow(clippy::needless_lifetimes)]
521impl<'a> LigCaretList<'a> {
522 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
523 basic_table_impls!(impl_the_methods);
524
525 pub fn coverage_offset(&self) -> Offset16 {
527 let range = self.coverage_offset_byte_range();
528 self.data.read_at(range.start).ok().unwrap()
529 }
530
531 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
533 let data = self.data;
534 self.coverage_offset().resolve(data)
535 }
536
537 pub fn lig_glyph_count(&self) -> u16 {
539 let range = self.lig_glyph_count_byte_range();
540 self.data.read_at(range.start).ok().unwrap()
541 }
542
543 pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset16>] {
546 let range = self.lig_glyph_offsets_byte_range();
547 self.data.read_array(range).ok().unwrap_or_default()
548 }
549
550 pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset16> {
552 let data = self.data;
553 let offsets = self.lig_glyph_offsets();
554 ArrayOfOffsets::new(offsets, data, ())
555 }
556
557 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
558 let start = 0;
559 start..start + Offset16::RAW_BYTE_LEN
560 }
561
562 pub fn lig_glyph_count_byte_range(&self) -> Range<usize> {
563 let start = self.coverage_offset_byte_range().end;
564 start..start + u16::RAW_BYTE_LEN
565 }
566
567 pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> {
568 let lig_glyph_count = self.lig_glyph_count();
569 let start = self.lig_glyph_count_byte_range().end;
570 start
571 ..start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN)
572 }
573}
574
575const _: () = assert!(FontData::default_data_long_enough(LigCaretList::MIN_SIZE));
576
577impl Default for LigCaretList<'_> {
578 fn default() -> Self {
579 Self {
580 data: FontData::default_table_data(),
581 }
582 }
583}
584
585#[cfg(feature = "experimental_traverse")]
586impl<'a> SomeTable<'a> for LigCaretList<'a> {
587 fn type_name(&self) -> &str {
588 "LigCaretList"
589 }
590 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
591 match idx {
592 0usize => Some(Field::new(
593 "coverage_offset",
594 FieldType::offset(self.coverage_offset(), self.coverage()),
595 )),
596 1usize => Some(Field::new("lig_glyph_count", self.lig_glyph_count())),
597 2usize => Some(Field::new(
598 "lig_glyph_offsets",
599 FieldType::from(self.lig_glyphs()),
600 )),
601 _ => None,
602 }
603 }
604}
605
606#[cfg(feature = "experimental_traverse")]
607#[allow(clippy::needless_lifetimes)]
608impl<'a> std::fmt::Debug for LigCaretList<'a> {
609 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
610 (self as &dyn SomeTable<'a>).fmt(f)
611 }
612}
613
614impl<'a> MinByteRange<'a> for LigGlyph<'a> {
615 fn min_byte_range(&self) -> Range<usize> {
616 0..self.caret_value_offsets_byte_range().end
617 }
618 fn min_table_bytes(&self) -> &'a [u8] {
619 let range = self.min_byte_range();
620 self.data.as_bytes().get(range).unwrap_or_default()
621 }
622}
623
624impl<'a> FontRead<'a> for LigGlyph<'a> {
625 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
626 #[allow(clippy::absurd_extreme_comparisons)]
627 if data.len() < Self::MIN_SIZE {
628 return Err(ReadError::OutOfBounds);
629 }
630 Ok(Self { data })
631 }
632}
633
634#[derive(Clone)]
636pub struct LigGlyph<'a> {
637 data: FontData<'a>,
638}
639
640#[allow(clippy::needless_lifetimes)]
641impl<'a> LigGlyph<'a> {
642 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
643 basic_table_impls!(impl_the_methods);
644
645 pub fn caret_count(&self) -> u16 {
647 let range = self.caret_count_byte_range();
648 self.data.read_at(range.start).ok().unwrap()
649 }
650
651 pub fn caret_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
654 let range = self.caret_value_offsets_byte_range();
655 self.data.read_array(range).ok().unwrap_or_default()
656 }
657
658 pub fn caret_values(&self) -> ArrayOfOffsets<'a, CaretValue<'a>, Offset16> {
660 let data = self.data;
661 let offsets = self.caret_value_offsets();
662 ArrayOfOffsets::new(offsets, data, ())
663 }
664
665 pub fn caret_count_byte_range(&self) -> Range<usize> {
666 let start = 0;
667 start..start + u16::RAW_BYTE_LEN
668 }
669
670 pub fn caret_value_offsets_byte_range(&self) -> Range<usize> {
671 let caret_count = self.caret_count();
672 let start = self.caret_count_byte_range().end;
673 start..start + (transforms::to_usize(caret_count)).saturating_mul(Offset16::RAW_BYTE_LEN)
674 }
675}
676
677const _: () = assert!(FontData::default_data_long_enough(LigGlyph::MIN_SIZE));
678
679impl Default for LigGlyph<'_> {
680 fn default() -> Self {
681 Self {
682 data: FontData::default_table_data(),
683 }
684 }
685}
686
687#[cfg(feature = "experimental_traverse")]
688impl<'a> SomeTable<'a> for LigGlyph<'a> {
689 fn type_name(&self) -> &str {
690 "LigGlyph"
691 }
692 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
693 match idx {
694 0usize => Some(Field::new("caret_count", self.caret_count())),
695 1usize => Some(Field::new(
696 "caret_value_offsets",
697 FieldType::from(self.caret_values()),
698 )),
699 _ => None,
700 }
701 }
702}
703
704#[cfg(feature = "experimental_traverse")]
705#[allow(clippy::needless_lifetimes)]
706impl<'a> std::fmt::Debug for LigGlyph<'a> {
707 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
708 (self as &dyn SomeTable<'a>).fmt(f)
709 }
710}
711
712#[derive(Clone)]
714pub enum CaretValue<'a> {
715 Format1(CaretValueFormat1<'a>),
716 Format2(CaretValueFormat2<'a>),
717 Format3(CaretValueFormat3<'a>),
718}
719
720impl Default for CaretValue<'_> {
721 fn default() -> Self {
722 Self::Format1(Default::default())
723 }
724}
725
726impl<'a> CaretValue<'a> {
727 pub fn offset_data(&self) -> FontData<'a> {
729 match self {
730 Self::Format1(item) => item.offset_data(),
731 Self::Format2(item) => item.offset_data(),
732 Self::Format3(item) => item.offset_data(),
733 }
734 }
735
736 pub fn caret_value_format(&self) -> u16 {
738 match self {
739 Self::Format1(item) => item.caret_value_format(),
740 Self::Format2(item) => item.caret_value_format(),
741 Self::Format3(item) => item.caret_value_format(),
742 }
743 }
744}
745
746impl<'a> FontRead<'a> for CaretValue<'a> {
747 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
748 let format: u16 = data.read_at(0usize)?;
749 match format {
750 CaretValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
751 CaretValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
752 CaretValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
753 other => Err(ReadError::InvalidFormat(other.into())),
754 }
755 }
756}
757
758impl<'a> MinByteRange<'a> for CaretValue<'a> {
759 fn min_byte_range(&self) -> Range<usize> {
760 match self {
761 Self::Format1(item) => item.min_byte_range(),
762 Self::Format2(item) => item.min_byte_range(),
763 Self::Format3(item) => item.min_byte_range(),
764 }
765 }
766 fn min_table_bytes(&self) -> &'a [u8] {
767 match self {
768 Self::Format1(item) => item.min_table_bytes(),
769 Self::Format2(item) => item.min_table_bytes(),
770 Self::Format3(item) => item.min_table_bytes(),
771 }
772 }
773}
774
775#[cfg(feature = "experimental_traverse")]
776impl<'a> CaretValue<'a> {
777 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
778 match self {
779 Self::Format1(table) => table,
780 Self::Format2(table) => table,
781 Self::Format3(table) => table,
782 }
783 }
784}
785
786#[cfg(feature = "experimental_traverse")]
787impl std::fmt::Debug for CaretValue<'_> {
788 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
789 self.dyn_inner().fmt(f)
790 }
791}
792
793#[cfg(feature = "experimental_traverse")]
794impl<'a> SomeTable<'a> for CaretValue<'a> {
795 fn type_name(&self) -> &str {
796 self.dyn_inner().type_name()
797 }
798 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
799 self.dyn_inner().get_field(idx)
800 }
801}
802
803impl Format<u16> for CaretValueFormat1<'_> {
804 const FORMAT: u16 = 1;
805}
806
807impl<'a> MinByteRange<'a> for CaretValueFormat1<'a> {
808 fn min_byte_range(&self) -> Range<usize> {
809 0..self.coordinate_byte_range().end
810 }
811 fn min_table_bytes(&self) -> &'a [u8] {
812 let range = self.min_byte_range();
813 self.data.as_bytes().get(range).unwrap_or_default()
814 }
815}
816
817impl<'a> FontRead<'a> for CaretValueFormat1<'a> {
818 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
819 #[allow(clippy::absurd_extreme_comparisons)]
820 if data.len() < Self::MIN_SIZE {
821 return Err(ReadError::OutOfBounds);
822 }
823 Ok(Self { data })
824 }
825}
826
827#[derive(Clone)]
829pub struct CaretValueFormat1<'a> {
830 data: FontData<'a>,
831}
832
833#[allow(clippy::needless_lifetimes)]
834impl<'a> CaretValueFormat1<'a> {
835 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
836 basic_table_impls!(impl_the_methods);
837
838 pub fn caret_value_format(&self) -> u16 {
840 let range = self.caret_value_format_byte_range();
841 self.data.read_at(range.start).ok().unwrap()
842 }
843
844 pub fn coordinate(&self) -> i16 {
846 let range = self.coordinate_byte_range();
847 self.data.read_at(range.start).ok().unwrap()
848 }
849
850 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
851 let start = 0;
852 start..start + u16::RAW_BYTE_LEN
853 }
854
855 pub fn coordinate_byte_range(&self) -> Range<usize> {
856 let start = self.caret_value_format_byte_range().end;
857 start..start + i16::RAW_BYTE_LEN
858 }
859}
860
861const _: () = assert!(FontData::default_data_long_enough(
862 CaretValueFormat1::MIN_SIZE
863));
864
865impl Default for CaretValueFormat1<'_> {
866 fn default() -> Self {
867 Self {
868 data: FontData::default_format_1_u16_table_data(),
869 }
870 }
871}
872
873#[cfg(feature = "experimental_traverse")]
874impl<'a> SomeTable<'a> for CaretValueFormat1<'a> {
875 fn type_name(&self) -> &str {
876 "CaretValueFormat1"
877 }
878 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
879 match idx {
880 0usize => Some(Field::new("caret_value_format", self.caret_value_format())),
881 1usize => Some(Field::new("coordinate", self.coordinate())),
882 _ => None,
883 }
884 }
885}
886
887#[cfg(feature = "experimental_traverse")]
888#[allow(clippy::needless_lifetimes)]
889impl<'a> std::fmt::Debug for CaretValueFormat1<'a> {
890 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
891 (self as &dyn SomeTable<'a>).fmt(f)
892 }
893}
894
895impl Format<u16> for CaretValueFormat2<'_> {
896 const FORMAT: u16 = 2;
897}
898
899impl<'a> MinByteRange<'a> for CaretValueFormat2<'a> {
900 fn min_byte_range(&self) -> Range<usize> {
901 0..self.caret_value_point_index_byte_range().end
902 }
903 fn min_table_bytes(&self) -> &'a [u8] {
904 let range = self.min_byte_range();
905 self.data.as_bytes().get(range).unwrap_or_default()
906 }
907}
908
909impl<'a> FontRead<'a> for CaretValueFormat2<'a> {
910 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
911 #[allow(clippy::absurd_extreme_comparisons)]
912 if data.len() < Self::MIN_SIZE {
913 return Err(ReadError::OutOfBounds);
914 }
915 Ok(Self { data })
916 }
917}
918
919#[derive(Clone)]
921pub struct CaretValueFormat2<'a> {
922 data: FontData<'a>,
923}
924
925#[allow(clippy::needless_lifetimes)]
926impl<'a> CaretValueFormat2<'a> {
927 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
928 basic_table_impls!(impl_the_methods);
929
930 pub fn caret_value_format(&self) -> u16 {
932 let range = self.caret_value_format_byte_range();
933 self.data.read_at(range.start).ok().unwrap()
934 }
935
936 pub fn caret_value_point_index(&self) -> u16 {
938 let range = self.caret_value_point_index_byte_range();
939 self.data.read_at(range.start).ok().unwrap()
940 }
941
942 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
943 let start = 0;
944 start..start + u16::RAW_BYTE_LEN
945 }
946
947 pub fn caret_value_point_index_byte_range(&self) -> Range<usize> {
948 let start = self.caret_value_format_byte_range().end;
949 start..start + u16::RAW_BYTE_LEN
950 }
951}
952
953#[cfg(feature = "experimental_traverse")]
954impl<'a> SomeTable<'a> for CaretValueFormat2<'a> {
955 fn type_name(&self) -> &str {
956 "CaretValueFormat2"
957 }
958 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
959 match idx {
960 0usize => Some(Field::new("caret_value_format", self.caret_value_format())),
961 1usize => Some(Field::new(
962 "caret_value_point_index",
963 self.caret_value_point_index(),
964 )),
965 _ => None,
966 }
967 }
968}
969
970#[cfg(feature = "experimental_traverse")]
971#[allow(clippy::needless_lifetimes)]
972impl<'a> std::fmt::Debug for CaretValueFormat2<'a> {
973 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
974 (self as &dyn SomeTable<'a>).fmt(f)
975 }
976}
977
978impl Format<u16> for CaretValueFormat3<'_> {
979 const FORMAT: u16 = 3;
980}
981
982impl<'a> MinByteRange<'a> for CaretValueFormat3<'a> {
983 fn min_byte_range(&self) -> Range<usize> {
984 0..self.device_offset_byte_range().end
985 }
986 fn min_table_bytes(&self) -> &'a [u8] {
987 let range = self.min_byte_range();
988 self.data.as_bytes().get(range).unwrap_or_default()
989 }
990}
991
992impl<'a> FontRead<'a> for CaretValueFormat3<'a> {
993 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
994 #[allow(clippy::absurd_extreme_comparisons)]
995 if data.len() < Self::MIN_SIZE {
996 return Err(ReadError::OutOfBounds);
997 }
998 Ok(Self { data })
999 }
1000}
1001
1002#[derive(Clone)]
1004pub struct CaretValueFormat3<'a> {
1005 data: FontData<'a>,
1006}
1007
1008#[allow(clippy::needless_lifetimes)]
1009impl<'a> CaretValueFormat3<'a> {
1010 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
1011 basic_table_impls!(impl_the_methods);
1012
1013 pub fn caret_value_format(&self) -> u16 {
1015 let range = self.caret_value_format_byte_range();
1016 self.data.read_at(range.start).ok().unwrap()
1017 }
1018
1019 pub fn coordinate(&self) -> i16 {
1021 let range = self.coordinate_byte_range();
1022 self.data.read_at(range.start).ok().unwrap()
1023 }
1024
1025 pub fn device_offset(&self) -> Offset16 {
1029 let range = self.device_offset_byte_range();
1030 self.data.read_at(range.start).ok().unwrap()
1031 }
1032
1033 pub fn device(&self) -> Result<DeviceOrVariationIndex<'a>, ReadError> {
1035 let data = self.data;
1036 self.device_offset().resolve(data)
1037 }
1038
1039 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
1040 let start = 0;
1041 start..start + u16::RAW_BYTE_LEN
1042 }
1043
1044 pub fn coordinate_byte_range(&self) -> Range<usize> {
1045 let start = self.caret_value_format_byte_range().end;
1046 start..start + i16::RAW_BYTE_LEN
1047 }
1048
1049 pub fn device_offset_byte_range(&self) -> Range<usize> {
1050 let start = self.coordinate_byte_range().end;
1051 start..start + Offset16::RAW_BYTE_LEN
1052 }
1053}
1054
1055#[cfg(feature = "experimental_traverse")]
1056impl<'a> SomeTable<'a> for CaretValueFormat3<'a> {
1057 fn type_name(&self) -> &str {
1058 "CaretValueFormat3"
1059 }
1060 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1061 match idx {
1062 0usize => Some(Field::new("caret_value_format", self.caret_value_format())),
1063 1usize => Some(Field::new("coordinate", self.coordinate())),
1064 2usize => Some(Field::new(
1065 "device_offset",
1066 FieldType::offset(self.device_offset(), self.device()),
1067 )),
1068 _ => None,
1069 }
1070 }
1071}
1072
1073#[cfg(feature = "experimental_traverse")]
1074#[allow(clippy::needless_lifetimes)]
1075impl<'a> std::fmt::Debug for CaretValueFormat3<'a> {
1076 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1077 (self as &dyn SomeTable<'a>).fmt(f)
1078 }
1079}
1080
1081impl Format<u16> for MarkGlyphSets<'_> {
1082 const FORMAT: u16 = 1;
1083}
1084
1085impl<'a> MinByteRange<'a> for MarkGlyphSets<'a> {
1086 fn min_byte_range(&self) -> Range<usize> {
1087 0..self.coverage_offsets_byte_range().end
1088 }
1089 fn min_table_bytes(&self) -> &'a [u8] {
1090 let range = self.min_byte_range();
1091 self.data.as_bytes().get(range).unwrap_or_default()
1092 }
1093}
1094
1095impl<'a> FontRead<'a> for MarkGlyphSets<'a> {
1096 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1097 #[allow(clippy::absurd_extreme_comparisons)]
1098 if data.len() < Self::MIN_SIZE {
1099 return Err(ReadError::OutOfBounds);
1100 }
1101 Ok(Self { data })
1102 }
1103}
1104
1105#[derive(Clone)]
1107pub struct MarkGlyphSets<'a> {
1108 data: FontData<'a>,
1109}
1110
1111#[allow(clippy::needless_lifetimes)]
1112impl<'a> MarkGlyphSets<'a> {
1113 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1114 basic_table_impls!(impl_the_methods);
1115
1116 pub fn format(&self) -> u16 {
1118 let range = self.format_byte_range();
1119 self.data.read_at(range.start).ok().unwrap()
1120 }
1121
1122 pub fn mark_glyph_set_count(&self) -> u16 {
1124 let range = self.mark_glyph_set_count_byte_range();
1125 self.data.read_at(range.start).ok().unwrap()
1126 }
1127
1128 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset32>] {
1131 let range = self.coverage_offsets_byte_range();
1132 self.data.read_array(range).ok().unwrap_or_default()
1133 }
1134
1135 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset32> {
1137 let data = self.data;
1138 let offsets = self.coverage_offsets();
1139 ArrayOfOffsets::new(offsets, data, ())
1140 }
1141
1142 pub fn format_byte_range(&self) -> Range<usize> {
1143 let start = 0;
1144 start..start + u16::RAW_BYTE_LEN
1145 }
1146
1147 pub fn mark_glyph_set_count_byte_range(&self) -> Range<usize> {
1148 let start = self.format_byte_range().end;
1149 start..start + u16::RAW_BYTE_LEN
1150 }
1151
1152 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
1153 let mark_glyph_set_count = self.mark_glyph_set_count();
1154 let start = self.mark_glyph_set_count_byte_range().end;
1155 start
1156 ..start
1157 + (transforms::to_usize(mark_glyph_set_count))
1158 .saturating_mul(Offset32::RAW_BYTE_LEN)
1159 }
1160}
1161
1162const _: () = assert!(FontData::default_data_long_enough(MarkGlyphSets::MIN_SIZE));
1163
1164impl Default for MarkGlyphSets<'_> {
1165 fn default() -> Self {
1166 Self {
1167 data: FontData::default_format_1_u16_table_data(),
1168 }
1169 }
1170}
1171
1172#[cfg(feature = "experimental_traverse")]
1173impl<'a> SomeTable<'a> for MarkGlyphSets<'a> {
1174 fn type_name(&self) -> &str {
1175 "MarkGlyphSets"
1176 }
1177 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1178 match idx {
1179 0usize => Some(Field::new("format", self.format())),
1180 1usize => Some(Field::new(
1181 "mark_glyph_set_count",
1182 self.mark_glyph_set_count(),
1183 )),
1184 2usize => Some(Field::new(
1185 "coverage_offsets",
1186 FieldType::from(self.coverages()),
1187 )),
1188 _ => None,
1189 }
1190 }
1191}
1192
1193#[cfg(feature = "experimental_traverse")]
1194#[allow(clippy::needless_lifetimes)]
1195impl<'a> std::fmt::Debug for MarkGlyphSets<'a> {
1196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1197 (self as &dyn SomeTable<'a>).fmt(f)
1198 }
1199}