1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Cmap<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.encoding_records_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 Cmap<'_> {
19 const TAG: Tag = Tag::new(b"cmap");
21}
22
23impl ReadArgs for Cmap<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Cmap<'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 CmapFixedHeader {
45 pub version: BigEndian<u16>,
46 pub num_tables: BigEndian<u16>,
47}
48
49#[allow(clippy::absurd_extreme_comparisons)]
50const _: () = assert!(std::mem::size_of::<CmapFixedHeader>() <= Cmap::MIN_SIZE);
51
52#[derive(Clone)]
54pub struct Cmap<'a> {
55 data: TableDataRef<'a, CmapFixedHeader>,
56}
57
58#[allow(clippy::needless_lifetimes)]
59impl<'a> Cmap<'a> {
60 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
61 basic_table_impls!(impl_the_methods);
62
63 pub fn version(&self) -> u16 {
65 self.data.header().version.get()
66 }
67
68 pub fn num_tables(&self) -> u16 {
70 self.data.header().num_tables.get()
71 }
72
73 pub fn encoding_records(&self) -> &'a [EncodingRecord] {
74 let range = self.encoding_records_byte_range();
75 self.offset_data()
76 .read_array(range)
77 .ok()
78 .unwrap_or_default()
79 }
80
81 pub fn version_byte_range(&self) -> Range<usize> {
82 let start = 0;
83 let end = start + u16::RAW_BYTE_LEN;
84 start..end
85 }
86
87 pub fn num_tables_byte_range(&self) -> Range<usize> {
88 let start = self.version_byte_range().end;
89 let end = start + u16::RAW_BYTE_LEN;
90 start..end
91 }
92
93 pub fn encoding_records_byte_range(&self) -> Range<usize> {
94 let num_tables = self.num_tables();
95 let start = self.num_tables_byte_range().end;
96 let end =
97 start + (transforms::to_usize(num_tables)).saturating_mul(EncodingRecord::RAW_BYTE_LEN);
98 start..end
99 }
100}
101
102const _: () = assert!(FontData::default_data_long_enough(Cmap::MIN_SIZE));
103
104impl Default for Cmap<'_> {
105 fn default() -> Self {
106 Self {
107 data: TableDataRef::new(FontData::default_table_data().as_bytes())
108 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
109 }
110 }
111}
112
113#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
115#[repr(C)]
116#[repr(packed)]
117pub struct EncodingRecord {
118 pub platform_id: BigEndian<PlatformId>,
120 pub encoding_id: BigEndian<u16>,
122 pub subtable_offset: BigEndian<Offset32>,
125}
126
127impl EncodingRecord {
128 pub fn platform_id(&self) -> PlatformId {
130 self.platform_id.get()
131 }
132
133 pub fn encoding_id(&self) -> u16 {
135 self.encoding_id.get()
136 }
137
138 pub fn subtable_offset(&self) -> Offset32 {
141 self.subtable_offset.get()
142 }
143
144 pub fn subtable<'a>(&self, data: FontData<'a>) -> Result<CmapSubtable<'a>, ReadError> {
150 self.subtable_offset().resolve(data)
151 }
152}
153
154impl FixedSize for EncodingRecord {
155 const RAW_BYTE_LEN: usize =
156 PlatformId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
157}
158
159#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
161#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
162#[repr(u16)]
163#[allow(clippy::manual_non_exhaustive)]
164pub enum PlatformId {
165 #[default]
166 Unicode = 0,
167 Macintosh = 1,
168 ISO = 2,
169 Windows = 3,
170 Custom = 4,
171 #[doc(hidden)]
172 Unknown,
174}
175
176impl PlatformId {
177 pub fn new(raw: u16) -> Self {
181 match raw {
182 0 => Self::Unicode,
183 1 => Self::Macintosh,
184 2 => Self::ISO,
185 3 => Self::Windows,
186 4 => Self::Custom,
187 _ => Self::Unknown,
188 }
189 }
190}
191
192impl font_types::Scalar for PlatformId {
193 type Raw = <u16 as font_types::Scalar>::Raw;
194 fn to_raw(self) -> Self::Raw {
195 (self as u16).to_raw()
196 }
197 fn from_raw(raw: Self::Raw) -> Self {
198 let t = <u16>::from_raw(raw);
199 Self::new(t)
200 }
201}
202
203#[derive(Clone)]
205pub enum CmapSubtable<'a> {
206 Format0(Cmap0<'a>),
207 Format2(Cmap2<'a>),
208 Format4(Cmap4<'a>),
209 Format6(Cmap6<'a>),
210 Format8(Cmap8<'a>),
211 Format10(Cmap10<'a>),
212 Format12(Cmap12<'a>),
213 Format13(Cmap13<'a>),
214 Format14(Cmap14<'a>),
215}
216
217impl Default for CmapSubtable<'_> {
218 fn default() -> Self {
219 Self::Format0(Default::default())
220 }
221}
222
223impl<'a> CmapSubtable<'a> {
224 pub fn offset_data(&self) -> FontData<'a> {
226 match self {
227 Self::Format0(item) => item.offset_data(),
228 Self::Format2(item) => item.offset_data(),
229 Self::Format4(item) => item.offset_data(),
230 Self::Format6(item) => item.offset_data(),
231 Self::Format8(item) => item.offset_data(),
232 Self::Format10(item) => item.offset_data(),
233 Self::Format12(item) => item.offset_data(),
234 Self::Format13(item) => item.offset_data(),
235 Self::Format14(item) => item.offset_data(),
236 }
237 }
238
239 pub fn format(&self) -> u16 {
241 match self {
242 Self::Format0(item) => item.format(),
243 Self::Format2(item) => item.format(),
244 Self::Format4(item) => item.format(),
245 Self::Format6(item) => item.format(),
246 Self::Format8(item) => item.format(),
247 Self::Format10(item) => item.format(),
248 Self::Format12(item) => item.format(),
249 Self::Format13(item) => item.format(),
250 Self::Format14(item) => item.format(),
251 }
252 }
253}
254
255impl ReadArgs for CmapSubtable<'_> {
256 type Args = ();
257}
258
259impl<'a> FontRead<'a> for CmapSubtable<'a> {
260 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
261 let format: u16 = data.read_at(0usize)?;
262 match format {
263 Cmap0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
264 Cmap2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
265 Cmap4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
266 Cmap6::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
267 Cmap8::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
268 Cmap10::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
269 Cmap12::FORMAT => Ok(Self::Format12(FontRead::read(data)?)),
270 Cmap13::FORMAT => Ok(Self::Format13(FontRead::read(data)?)),
271 Cmap14::FORMAT => Ok(Self::Format14(FontRead::read(data)?)),
272 other => Err(ReadError::InvalidFormat(other.into())),
273 }
274 }
275}
276
277impl<'a> MinByteRange<'a> for CmapSubtable<'a> {
278 fn min_byte_range(&self) -> Range<usize> {
279 match self {
280 Self::Format0(item) => item.min_byte_range(),
281 Self::Format2(item) => item.min_byte_range(),
282 Self::Format4(item) => item.min_byte_range(),
283 Self::Format6(item) => item.min_byte_range(),
284 Self::Format8(item) => item.min_byte_range(),
285 Self::Format10(item) => item.min_byte_range(),
286 Self::Format12(item) => item.min_byte_range(),
287 Self::Format13(item) => item.min_byte_range(),
288 Self::Format14(item) => item.min_byte_range(),
289 }
290 }
291 fn min_table_bytes(&self) -> &'a [u8] {
292 match self {
293 Self::Format0(item) => item.min_table_bytes(),
294 Self::Format2(item) => item.min_table_bytes(),
295 Self::Format4(item) => item.min_table_bytes(),
296 Self::Format6(item) => item.min_table_bytes(),
297 Self::Format8(item) => item.min_table_bytes(),
298 Self::Format10(item) => item.min_table_bytes(),
299 Self::Format12(item) => item.min_table_bytes(),
300 Self::Format13(item) => item.min_table_bytes(),
301 Self::Format14(item) => item.min_table_bytes(),
302 }
303 }
304}
305
306impl Format<u16> for Cmap0<'_> {
307 const FORMAT: u16 = 0;
308}
309
310impl<'a> MinByteRange<'a> for Cmap0<'a> {
311 fn min_byte_range(&self) -> Range<usize> {
312 0..self.glyph_id_array_byte_range().end
313 }
314 fn min_table_bytes(&self) -> &'a [u8] {
315 let range = self.min_byte_range();
316 self.offset_data().as_bytes().get(range).unwrap_or_default()
317 }
318}
319
320impl ReadArgs for Cmap0<'_> {
321 type Args = ();
322}
323
324impl<'a> FontRead<'a> for Cmap0<'a> {
325 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
326 #[allow(clippy::absurd_extreme_comparisons)]
327 if data.len() < Self::MIN_SIZE {
328 return Err(ReadError::OutOfBounds);
329 }
330 let Some(data) = TableDataRef::new(data.as_bytes()) else {
331 return Err(ReadError::OutOfBounds);
332 };
333 Ok(Self { data })
334 }
335}
336
337#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
339#[repr(C, packed)]
340#[doc(hidden)]
341pub struct Cmap0FixedHeader {
342 pub format: BigEndian<u16>,
343 pub length: BigEndian<u16>,
344 pub language: BigEndian<u16>,
345}
346
347#[allow(clippy::absurd_extreme_comparisons)]
348const _: () = assert!(std::mem::size_of::<Cmap0FixedHeader>() <= Cmap0::MIN_SIZE);
349
350#[derive(Clone)]
352pub struct Cmap0<'a> {
353 data: TableDataRef<'a, Cmap0FixedHeader>,
354}
355
356#[allow(clippy::needless_lifetimes)]
357impl<'a> Cmap0<'a> {
358 pub const MIN_SIZE: usize =
359 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN * 256_usize);
360 basic_table_impls!(impl_the_methods);
361
362 pub fn format(&self) -> u16 {
364 self.data.header().format.get()
365 }
366
367 pub fn length(&self) -> u16 {
369 self.data.header().length.get()
370 }
371
372 pub fn language(&self) -> u16 {
375 self.data.header().language.get()
376 }
377
378 pub fn glyph_id_array(&self) -> &'a [u8] {
380 let range = self.glyph_id_array_byte_range();
381 self.offset_data()
382 .read_array(range)
383 .ok()
384 .unwrap_or_default()
385 }
386
387 pub fn format_byte_range(&self) -> Range<usize> {
388 let start = 0;
389 let end = start + u16::RAW_BYTE_LEN;
390 start..end
391 }
392
393 pub fn length_byte_range(&self) -> Range<usize> {
394 let start = self.format_byte_range().end;
395 let end = start + u16::RAW_BYTE_LEN;
396 start..end
397 }
398
399 pub fn language_byte_range(&self) -> Range<usize> {
400 let start = self.length_byte_range().end;
401 let end = start + u16::RAW_BYTE_LEN;
402 start..end
403 }
404
405 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
406 let start = self.language_byte_range().end;
407 let end = start + (256_usize).saturating_mul(u8::RAW_BYTE_LEN);
408 start..end
409 }
410}
411
412const _: () = assert!(FontData::default_data_long_enough(Cmap0::MIN_SIZE));
413
414impl Default for Cmap0<'_> {
415 fn default() -> Self {
416 Self {
417 data: TableDataRef::new(FontData::default_table_data().as_bytes())
418 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
419 }
420 }
421}
422
423impl Format<u16> for Cmap2<'_> {
424 const FORMAT: u16 = 2;
425}
426
427impl<'a> MinByteRange<'a> for Cmap2<'a> {
428 fn min_byte_range(&self) -> Range<usize> {
429 0..self.sub_header_keys_byte_range().end
430 }
431 fn min_table_bytes(&self) -> &'a [u8] {
432 let range = self.min_byte_range();
433 self.offset_data().as_bytes().get(range).unwrap_or_default()
434 }
435}
436
437impl ReadArgs for Cmap2<'_> {
438 type Args = ();
439}
440
441impl<'a> FontRead<'a> for Cmap2<'a> {
442 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
443 #[allow(clippy::absurd_extreme_comparisons)]
444 if data.len() < Self::MIN_SIZE {
445 return Err(ReadError::OutOfBounds);
446 }
447 let Some(data) = TableDataRef::new(data.as_bytes()) else {
448 return Err(ReadError::OutOfBounds);
449 };
450 Ok(Self { data })
451 }
452}
453
454#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
456#[repr(C, packed)]
457#[doc(hidden)]
458pub struct Cmap2FixedHeader {
459 pub format: BigEndian<u16>,
460 pub length: BigEndian<u16>,
461 pub language: BigEndian<u16>,
462}
463
464#[allow(clippy::absurd_extreme_comparisons)]
465const _: () = assert!(std::mem::size_of::<Cmap2FixedHeader>() <= Cmap2::MIN_SIZE);
466
467#[derive(Clone)]
469pub struct Cmap2<'a> {
470 data: TableDataRef<'a, Cmap2FixedHeader>,
471}
472
473#[allow(clippy::needless_lifetimes)]
474impl<'a> Cmap2<'a> {
475 pub const MIN_SIZE: usize =
476 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN * 256_usize);
477 basic_table_impls!(impl_the_methods);
478
479 pub fn format(&self) -> u16 {
481 self.data.header().format.get()
482 }
483
484 pub fn length(&self) -> u16 {
486 self.data.header().length.get()
487 }
488
489 pub fn language(&self) -> u16 {
492 self.data.header().language.get()
493 }
494
495 pub fn sub_header_keys(&self) -> &'a [BigEndian<u16>] {
498 let range = self.sub_header_keys_byte_range();
499 self.offset_data()
500 .read_array(range)
501 .ok()
502 .unwrap_or_default()
503 }
504
505 pub fn format_byte_range(&self) -> Range<usize> {
506 let start = 0;
507 let end = start + u16::RAW_BYTE_LEN;
508 start..end
509 }
510
511 pub fn length_byte_range(&self) -> Range<usize> {
512 let start = self.format_byte_range().end;
513 let end = start + u16::RAW_BYTE_LEN;
514 start..end
515 }
516
517 pub fn language_byte_range(&self) -> Range<usize> {
518 let start = self.length_byte_range().end;
519 let end = start + u16::RAW_BYTE_LEN;
520 start..end
521 }
522
523 pub fn sub_header_keys_byte_range(&self) -> Range<usize> {
524 let start = self.language_byte_range().end;
525 let end = start + (256_usize).saturating_mul(u16::RAW_BYTE_LEN);
526 start..end
527 }
528}
529
530#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
532#[repr(C)]
533#[repr(packed)]
534pub struct SubHeader {
535 pub first_code: BigEndian<u16>,
537 pub entry_count: BigEndian<u16>,
539 pub id_delta: BigEndian<i16>,
541 pub id_range_offset: BigEndian<u16>,
543}
544
545impl SubHeader {
546 pub fn first_code(&self) -> u16 {
548 self.first_code.get()
549 }
550
551 pub fn entry_count(&self) -> u16 {
553 self.entry_count.get()
554 }
555
556 pub fn id_delta(&self) -> i16 {
558 self.id_delta.get()
559 }
560
561 pub fn id_range_offset(&self) -> u16 {
563 self.id_range_offset.get()
564 }
565}
566
567impl FixedSize for SubHeader {
568 const RAW_BYTE_LEN: usize =
569 u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
570}
571
572impl Format<u16> for Cmap4<'_> {
573 const FORMAT: u16 = 4;
574}
575
576impl<'a> MinByteRange<'a> for Cmap4<'a> {
577 fn min_byte_range(&self) -> Range<usize> {
578 0..self.glyph_id_array_byte_range().end
579 }
580 fn min_table_bytes(&self) -> &'a [u8] {
581 let range = self.min_byte_range();
582 self.offset_data().as_bytes().get(range).unwrap_or_default()
583 }
584}
585
586impl ReadArgs for Cmap4<'_> {
587 type Args = ();
588}
589
590impl<'a> FontRead<'a> for Cmap4<'a> {
591 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
592 #[allow(clippy::absurd_extreme_comparisons)]
593 if data.len() < Self::MIN_SIZE {
594 return Err(ReadError::OutOfBounds);
595 }
596 let Some(data) = TableDataRef::new(data.as_bytes()) else {
597 return Err(ReadError::OutOfBounds);
598 };
599 Ok(Self { data })
600 }
601}
602
603#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
605#[repr(C, packed)]
606#[doc(hidden)]
607pub struct Cmap4FixedHeader {
608 pub format: BigEndian<u16>,
609 pub length: BigEndian<u16>,
610 pub language: BigEndian<u16>,
611 pub seg_count_x2: BigEndian<u16>,
612 pub search_range: BigEndian<u16>,
613 pub entry_selector: BigEndian<u16>,
614 pub range_shift: BigEndian<u16>,
615}
616
617#[allow(clippy::absurd_extreme_comparisons)]
618const _: () = assert!(std::mem::size_of::<Cmap4FixedHeader>() <= Cmap4::MIN_SIZE);
619
620#[derive(Clone)]
622pub struct Cmap4<'a> {
623 data: TableDataRef<'a, Cmap4FixedHeader>,
624}
625
626#[allow(clippy::needless_lifetimes)]
627impl<'a> Cmap4<'a> {
628 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
629 + u16::RAW_BYTE_LEN
630 + u16::RAW_BYTE_LEN
631 + u16::RAW_BYTE_LEN
632 + u16::RAW_BYTE_LEN
633 + u16::RAW_BYTE_LEN
634 + u16::RAW_BYTE_LEN
635 + u16::RAW_BYTE_LEN);
636 basic_table_impls!(impl_the_methods);
637
638 pub fn format(&self) -> u16 {
640 self.data.header().format.get()
641 }
642
643 pub fn length(&self) -> u16 {
645 self.data.header().length.get()
646 }
647
648 pub fn language(&self) -> u16 {
651 self.data.header().language.get()
652 }
653
654 pub fn seg_count_x2(&self) -> u16 {
656 self.data.header().seg_count_x2.get()
657 }
658
659 pub fn search_range(&self) -> u16 {
663 self.data.header().search_range.get()
664 }
665
666 pub fn entry_selector(&self) -> u16 {
669 self.data.header().entry_selector.get()
670 }
671
672 pub fn range_shift(&self) -> u16 {
675 self.data.header().range_shift.get()
676 }
677
678 pub fn end_code(&self) -> &'a [BigEndian<u16>] {
680 let range = self.end_code_byte_range();
681 self.offset_data()
682 .read_array(range)
683 .ok()
684 .unwrap_or_default()
685 }
686
687 pub fn start_code(&self) -> &'a [BigEndian<u16>] {
689 let range = self.start_code_byte_range();
690 self.offset_data()
691 .read_array(range)
692 .ok()
693 .unwrap_or_default()
694 }
695
696 pub fn id_delta(&self) -> &'a [BigEndian<i16>] {
698 let range = self.id_delta_byte_range();
699 self.offset_data()
700 .read_array(range)
701 .ok()
702 .unwrap_or_default()
703 }
704
705 pub fn id_range_offsets(&self) -> &'a [BigEndian<u16>] {
707 let range = self.id_range_offsets_byte_range();
708 self.offset_data()
709 .read_array(range)
710 .ok()
711 .unwrap_or_default()
712 }
713
714 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
716 let range = self.glyph_id_array_byte_range();
717 self.offset_data()
718 .read_array(range)
719 .ok()
720 .unwrap_or_default()
721 }
722
723 pub fn format_byte_range(&self) -> Range<usize> {
724 let start = 0;
725 let end = start + u16::RAW_BYTE_LEN;
726 start..end
727 }
728
729 pub fn length_byte_range(&self) -> Range<usize> {
730 let start = self.format_byte_range().end;
731 let end = start + u16::RAW_BYTE_LEN;
732 start..end
733 }
734
735 pub fn language_byte_range(&self) -> Range<usize> {
736 let start = self.length_byte_range().end;
737 let end = start + u16::RAW_BYTE_LEN;
738 start..end
739 }
740
741 pub fn seg_count_x2_byte_range(&self) -> Range<usize> {
742 let start = self.language_byte_range().end;
743 let end = start + u16::RAW_BYTE_LEN;
744 start..end
745 }
746
747 pub fn search_range_byte_range(&self) -> Range<usize> {
748 let start = self.seg_count_x2_byte_range().end;
749 let end = start + u16::RAW_BYTE_LEN;
750 start..end
751 }
752
753 pub fn entry_selector_byte_range(&self) -> Range<usize> {
754 let start = self.search_range_byte_range().end;
755 let end = start + u16::RAW_BYTE_LEN;
756 start..end
757 }
758
759 pub fn range_shift_byte_range(&self) -> Range<usize> {
760 let start = self.entry_selector_byte_range().end;
761 let end = start + u16::RAW_BYTE_LEN;
762 start..end
763 }
764
765 pub fn end_code_byte_range(&self) -> Range<usize> {
766 let seg_count_x2 = self.seg_count_x2();
767 let start = self.range_shift_byte_range().end;
768 let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
769 start..end
770 }
771
772 pub fn reserved_pad_byte_range(&self) -> Range<usize> {
773 let start = self.end_code_byte_range().end;
774 let end = start + u16::RAW_BYTE_LEN;
775 start..end
776 }
777
778 pub fn start_code_byte_range(&self) -> Range<usize> {
779 let seg_count_x2 = self.seg_count_x2();
780 let start = self.reserved_pad_byte_range().end;
781 let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
782 start..end
783 }
784
785 pub fn id_delta_byte_range(&self) -> Range<usize> {
786 let seg_count_x2 = self.seg_count_x2();
787 let start = self.start_code_byte_range().end;
788 let end = start + (transforms::half(seg_count_x2)).saturating_mul(i16::RAW_BYTE_LEN);
789 start..end
790 }
791
792 pub fn id_range_offsets_byte_range(&self) -> Range<usize> {
793 let seg_count_x2 = self.seg_count_x2();
794 let start = self.id_delta_byte_range().end;
795 let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
796 start..end
797 }
798
799 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
800 let start = self.id_range_offsets_byte_range().end;
801 let end = start
802 + self.offset_data().len().saturating_sub(start) / u16::RAW_BYTE_LEN
803 * u16::RAW_BYTE_LEN;
804 start..end
805 }
806}
807
808impl Format<u16> for Cmap6<'_> {
809 const FORMAT: u16 = 6;
810}
811
812impl<'a> MinByteRange<'a> for Cmap6<'a> {
813 fn min_byte_range(&self) -> Range<usize> {
814 0..self.glyph_id_array_byte_range().end
815 }
816 fn min_table_bytes(&self) -> &'a [u8] {
817 let range = self.min_byte_range();
818 self.offset_data().as_bytes().get(range).unwrap_or_default()
819 }
820}
821
822impl ReadArgs for Cmap6<'_> {
823 type Args = ();
824}
825
826impl<'a> FontRead<'a> for Cmap6<'a> {
827 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
828 #[allow(clippy::absurd_extreme_comparisons)]
829 if data.len() < Self::MIN_SIZE {
830 return Err(ReadError::OutOfBounds);
831 }
832 let Some(data) = TableDataRef::new(data.as_bytes()) else {
833 return Err(ReadError::OutOfBounds);
834 };
835 Ok(Self { data })
836 }
837}
838
839#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
841#[repr(C, packed)]
842#[doc(hidden)]
843pub struct Cmap6FixedHeader {
844 pub format: BigEndian<u16>,
845 pub length: BigEndian<u16>,
846 pub language: BigEndian<u16>,
847 pub first_code: BigEndian<u16>,
848 pub entry_count: BigEndian<u16>,
849}
850
851#[allow(clippy::absurd_extreme_comparisons)]
852const _: () = assert!(std::mem::size_of::<Cmap6FixedHeader>() <= Cmap6::MIN_SIZE);
853
854#[derive(Clone)]
856pub struct Cmap6<'a> {
857 data: TableDataRef<'a, Cmap6FixedHeader>,
858}
859
860#[allow(clippy::needless_lifetimes)]
861impl<'a> Cmap6<'a> {
862 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
863 + u16::RAW_BYTE_LEN
864 + u16::RAW_BYTE_LEN
865 + u16::RAW_BYTE_LEN
866 + u16::RAW_BYTE_LEN);
867 basic_table_impls!(impl_the_methods);
868
869 pub fn format(&self) -> u16 {
871 self.data.header().format.get()
872 }
873
874 pub fn length(&self) -> u16 {
876 self.data.header().length.get()
877 }
878
879 pub fn language(&self) -> u16 {
882 self.data.header().language.get()
883 }
884
885 pub fn first_code(&self) -> u16 {
887 self.data.header().first_code.get()
888 }
889
890 pub fn entry_count(&self) -> u16 {
892 self.data.header().entry_count.get()
893 }
894
895 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
897 let range = self.glyph_id_array_byte_range();
898 self.offset_data()
899 .read_array(range)
900 .ok()
901 .unwrap_or_default()
902 }
903
904 pub fn format_byte_range(&self) -> Range<usize> {
905 let start = 0;
906 let end = start + u16::RAW_BYTE_LEN;
907 start..end
908 }
909
910 pub fn length_byte_range(&self) -> Range<usize> {
911 let start = self.format_byte_range().end;
912 let end = start + u16::RAW_BYTE_LEN;
913 start..end
914 }
915
916 pub fn language_byte_range(&self) -> Range<usize> {
917 let start = self.length_byte_range().end;
918 let end = start + u16::RAW_BYTE_LEN;
919 start..end
920 }
921
922 pub fn first_code_byte_range(&self) -> Range<usize> {
923 let start = self.language_byte_range().end;
924 let end = start + u16::RAW_BYTE_LEN;
925 start..end
926 }
927
928 pub fn entry_count_byte_range(&self) -> Range<usize> {
929 let start = self.first_code_byte_range().end;
930 let end = start + u16::RAW_BYTE_LEN;
931 start..end
932 }
933
934 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
935 let entry_count = self.entry_count();
936 let start = self.entry_count_byte_range().end;
937 let end = start + (transforms::to_usize(entry_count)).saturating_mul(u16::RAW_BYTE_LEN);
938 start..end
939 }
940}
941
942impl Format<u16> for Cmap8<'_> {
943 const FORMAT: u16 = 8;
944}
945
946impl<'a> MinByteRange<'a> for Cmap8<'a> {
947 fn min_byte_range(&self) -> Range<usize> {
948 0..self.groups_byte_range().end
949 }
950 fn min_table_bytes(&self) -> &'a [u8] {
951 let range = self.min_byte_range();
952 self.offset_data().as_bytes().get(range).unwrap_or_default()
953 }
954}
955
956impl ReadArgs for Cmap8<'_> {
957 type Args = ();
958}
959
960impl<'a> FontRead<'a> for Cmap8<'a> {
961 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
962 #[allow(clippy::absurd_extreme_comparisons)]
963 if data.len() < Self::MIN_SIZE {
964 return Err(ReadError::OutOfBounds);
965 }
966 let Some(data) = TableDataRef::new(data.as_bytes()) else {
967 return Err(ReadError::OutOfBounds);
968 };
969 Ok(Self { data })
970 }
971}
972
973#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
975#[repr(C, packed)]
976#[doc(hidden)]
977pub struct Cmap8FixedHeader {
978 pub format: BigEndian<u16>,
979 pub reserved: BigEndian<u16>,
980 pub length: BigEndian<u32>,
981 pub language: BigEndian<u32>,
982}
983
984#[allow(clippy::absurd_extreme_comparisons)]
985const _: () = assert!(std::mem::size_of::<Cmap8FixedHeader>() <= Cmap8::MIN_SIZE);
986
987#[derive(Clone)]
989pub struct Cmap8<'a> {
990 data: TableDataRef<'a, Cmap8FixedHeader>,
991}
992
993#[allow(clippy::needless_lifetimes)]
994impl<'a> Cmap8<'a> {
995 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
996 + u16::RAW_BYTE_LEN
997 + u32::RAW_BYTE_LEN
998 + u32::RAW_BYTE_LEN
999 + u8::RAW_BYTE_LEN * 8192_usize
1000 + u32::RAW_BYTE_LEN);
1001 basic_table_impls!(impl_the_methods);
1002
1003 pub fn format(&self) -> u16 {
1005 self.data.header().format.get()
1006 }
1007
1008 pub fn length(&self) -> u32 {
1010 self.data.header().length.get()
1011 }
1012
1013 pub fn language(&self) -> u32 {
1016 self.data.header().language.get()
1017 }
1018
1019 pub fn is32(&self) -> &'a [u8] {
1023 let range = self.is32_byte_range();
1024 self.offset_data()
1025 .read_array(range)
1026 .ok()
1027 .unwrap_or_default()
1028 }
1029
1030 pub fn num_groups(&self) -> u32 {
1032 let range = self.num_groups_byte_range();
1033 self.offset_data()
1034 .read_at(range.start)
1035 .ok()
1036 .unwrap_or_default()
1037 }
1038
1039 pub fn groups(&self) -> &'a [SequentialMapGroup] {
1041 let range = self.groups_byte_range();
1042 self.offset_data()
1043 .read_array(range)
1044 .ok()
1045 .unwrap_or_default()
1046 }
1047
1048 pub fn format_byte_range(&self) -> Range<usize> {
1049 let start = 0;
1050 let end = start + u16::RAW_BYTE_LEN;
1051 start..end
1052 }
1053
1054 pub fn reserved_byte_range(&self) -> Range<usize> {
1055 let start = self.format_byte_range().end;
1056 let end = start + u16::RAW_BYTE_LEN;
1057 start..end
1058 }
1059
1060 pub fn length_byte_range(&self) -> Range<usize> {
1061 let start = self.reserved_byte_range().end;
1062 let end = start + u32::RAW_BYTE_LEN;
1063 start..end
1064 }
1065
1066 pub fn language_byte_range(&self) -> Range<usize> {
1067 let start = self.length_byte_range().end;
1068 let end = start + u32::RAW_BYTE_LEN;
1069 start..end
1070 }
1071
1072 pub fn is32_byte_range(&self) -> Range<usize> {
1073 let start = self.language_byte_range().end;
1074 let end = start + (8192_usize).saturating_mul(u8::RAW_BYTE_LEN);
1075 start..end
1076 }
1077
1078 pub fn num_groups_byte_range(&self) -> Range<usize> {
1079 let start = self.is32_byte_range().end;
1080 let end = start + u32::RAW_BYTE_LEN;
1081 start..end
1082 }
1083
1084 pub fn groups_byte_range(&self) -> Range<usize> {
1085 let num_groups = self.num_groups();
1086 let start = self.num_groups_byte_range().end;
1087 let end = start
1088 + (transforms::to_usize(num_groups)).saturating_mul(SequentialMapGroup::RAW_BYTE_LEN);
1089 start..end
1090 }
1091}
1092
1093#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1095#[repr(C)]
1096#[repr(packed)]
1097pub struct SequentialMapGroup {
1098 pub start_char_code: BigEndian<u32>,
1103 pub end_char_code: BigEndian<u32>,
1106 pub start_glyph_id: BigEndian<u32>,
1108}
1109
1110impl SequentialMapGroup {
1111 pub fn start_char_code(&self) -> u32 {
1116 self.start_char_code.get()
1117 }
1118
1119 pub fn end_char_code(&self) -> u32 {
1122 self.end_char_code.get()
1123 }
1124
1125 pub fn start_glyph_id(&self) -> u32 {
1127 self.start_glyph_id.get()
1128 }
1129}
1130
1131impl FixedSize for SequentialMapGroup {
1132 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1133}
1134
1135impl Format<u16> for Cmap10<'_> {
1136 const FORMAT: u16 = 10;
1137}
1138
1139impl<'a> MinByteRange<'a> for Cmap10<'a> {
1140 fn min_byte_range(&self) -> Range<usize> {
1141 0..self.glyph_id_array_byte_range().end
1142 }
1143 fn min_table_bytes(&self) -> &'a [u8] {
1144 let range = self.min_byte_range();
1145 self.offset_data().as_bytes().get(range).unwrap_or_default()
1146 }
1147}
1148
1149impl ReadArgs for Cmap10<'_> {
1150 type Args = ();
1151}
1152
1153impl<'a> FontRead<'a> for Cmap10<'a> {
1154 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1155 #[allow(clippy::absurd_extreme_comparisons)]
1156 if data.len() < Self::MIN_SIZE {
1157 return Err(ReadError::OutOfBounds);
1158 }
1159 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1160 return Err(ReadError::OutOfBounds);
1161 };
1162 Ok(Self { data })
1163 }
1164}
1165
1166#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1168#[repr(C, packed)]
1169#[doc(hidden)]
1170pub struct Cmap10FixedHeader {
1171 pub format: BigEndian<u16>,
1172 pub reserved: BigEndian<u16>,
1173 pub length: BigEndian<u32>,
1174 pub language: BigEndian<u32>,
1175 pub start_char_code: BigEndian<u32>,
1176 pub num_chars: BigEndian<u32>,
1177}
1178
1179#[allow(clippy::absurd_extreme_comparisons)]
1180const _: () = assert!(std::mem::size_of::<Cmap10FixedHeader>() <= Cmap10::MIN_SIZE);
1181
1182#[derive(Clone)]
1184pub struct Cmap10<'a> {
1185 data: TableDataRef<'a, Cmap10FixedHeader>,
1186}
1187
1188#[allow(clippy::needless_lifetimes)]
1189impl<'a> Cmap10<'a> {
1190 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1191 + u16::RAW_BYTE_LEN
1192 + u32::RAW_BYTE_LEN
1193 + u32::RAW_BYTE_LEN
1194 + u32::RAW_BYTE_LEN
1195 + u32::RAW_BYTE_LEN);
1196 basic_table_impls!(impl_the_methods);
1197
1198 pub fn format(&self) -> u16 {
1200 self.data.header().format.get()
1201 }
1202
1203 pub fn length(&self) -> u32 {
1205 self.data.header().length.get()
1206 }
1207
1208 pub fn language(&self) -> u32 {
1211 self.data.header().language.get()
1212 }
1213
1214 pub fn start_char_code(&self) -> u32 {
1216 self.data.header().start_char_code.get()
1217 }
1218
1219 pub fn num_chars(&self) -> u32 {
1221 self.data.header().num_chars.get()
1222 }
1223
1224 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
1226 let range = self.glyph_id_array_byte_range();
1227 self.offset_data()
1228 .read_array(range)
1229 .ok()
1230 .unwrap_or_default()
1231 }
1232
1233 pub fn format_byte_range(&self) -> Range<usize> {
1234 let start = 0;
1235 let end = start + u16::RAW_BYTE_LEN;
1236 start..end
1237 }
1238
1239 pub fn reserved_byte_range(&self) -> Range<usize> {
1240 let start = self.format_byte_range().end;
1241 let end = start + u16::RAW_BYTE_LEN;
1242 start..end
1243 }
1244
1245 pub fn length_byte_range(&self) -> Range<usize> {
1246 let start = self.reserved_byte_range().end;
1247 let end = start + u32::RAW_BYTE_LEN;
1248 start..end
1249 }
1250
1251 pub fn language_byte_range(&self) -> Range<usize> {
1252 let start = self.length_byte_range().end;
1253 let end = start + u32::RAW_BYTE_LEN;
1254 start..end
1255 }
1256
1257 pub fn start_char_code_byte_range(&self) -> Range<usize> {
1258 let start = self.language_byte_range().end;
1259 let end = start + u32::RAW_BYTE_LEN;
1260 start..end
1261 }
1262
1263 pub fn num_chars_byte_range(&self) -> Range<usize> {
1264 let start = self.start_char_code_byte_range().end;
1265 let end = start + u32::RAW_BYTE_LEN;
1266 start..end
1267 }
1268
1269 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
1270 let num_chars = self.num_chars();
1271 let start = self.num_chars_byte_range().end;
1272 let end = start + (transforms::to_usize(num_chars)).saturating_mul(u16::RAW_BYTE_LEN);
1273 start..end
1274 }
1275}
1276
1277impl Format<u16> for Cmap12<'_> {
1278 const FORMAT: u16 = 12;
1279}
1280
1281impl<'a> MinByteRange<'a> for Cmap12<'a> {
1282 fn min_byte_range(&self) -> Range<usize> {
1283 0..self.groups_byte_range().end
1284 }
1285 fn min_table_bytes(&self) -> &'a [u8] {
1286 let range = self.min_byte_range();
1287 self.offset_data().as_bytes().get(range).unwrap_or_default()
1288 }
1289}
1290
1291impl ReadArgs for Cmap12<'_> {
1292 type Args = ();
1293}
1294
1295impl<'a> FontRead<'a> for Cmap12<'a> {
1296 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1297 #[allow(clippy::absurd_extreme_comparisons)]
1298 if data.len() < Self::MIN_SIZE {
1299 return Err(ReadError::OutOfBounds);
1300 }
1301 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1302 return Err(ReadError::OutOfBounds);
1303 };
1304 Ok(Self { data })
1305 }
1306}
1307
1308#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1310#[repr(C, packed)]
1311#[doc(hidden)]
1312pub struct Cmap12FixedHeader {
1313 pub format: BigEndian<u16>,
1314 pub reserved: BigEndian<u16>,
1315 pub length: BigEndian<u32>,
1316 pub language: BigEndian<u32>,
1317 pub num_groups: BigEndian<u32>,
1318}
1319
1320#[allow(clippy::absurd_extreme_comparisons)]
1321const _: () = assert!(std::mem::size_of::<Cmap12FixedHeader>() <= Cmap12::MIN_SIZE);
1322
1323#[derive(Clone)]
1325pub struct Cmap12<'a> {
1326 data: TableDataRef<'a, Cmap12FixedHeader>,
1327}
1328
1329#[allow(clippy::needless_lifetimes)]
1330impl<'a> Cmap12<'a> {
1331 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1332 + u16::RAW_BYTE_LEN
1333 + u32::RAW_BYTE_LEN
1334 + u32::RAW_BYTE_LEN
1335 + u32::RAW_BYTE_LEN);
1336 basic_table_impls!(impl_the_methods);
1337
1338 pub fn format(&self) -> u16 {
1340 self.data.header().format.get()
1341 }
1342
1343 pub fn length(&self) -> u32 {
1345 self.data.header().length.get()
1346 }
1347
1348 pub fn language(&self) -> u32 {
1351 self.data.header().language.get()
1352 }
1353
1354 pub fn num_groups(&self) -> u32 {
1356 self.data.header().num_groups.get()
1357 }
1358
1359 pub fn groups(&self) -> &'a [SequentialMapGroup] {
1361 let range = self.groups_byte_range();
1362 self.offset_data()
1363 .read_array(range)
1364 .ok()
1365 .unwrap_or_default()
1366 }
1367
1368 pub fn format_byte_range(&self) -> Range<usize> {
1369 let start = 0;
1370 let end = start + u16::RAW_BYTE_LEN;
1371 start..end
1372 }
1373
1374 pub fn reserved_byte_range(&self) -> Range<usize> {
1375 let start = self.format_byte_range().end;
1376 let end = start + u16::RAW_BYTE_LEN;
1377 start..end
1378 }
1379
1380 pub fn length_byte_range(&self) -> Range<usize> {
1381 let start = self.reserved_byte_range().end;
1382 let end = start + u32::RAW_BYTE_LEN;
1383 start..end
1384 }
1385
1386 pub fn language_byte_range(&self) -> Range<usize> {
1387 let start = self.length_byte_range().end;
1388 let end = start + u32::RAW_BYTE_LEN;
1389 start..end
1390 }
1391
1392 pub fn num_groups_byte_range(&self) -> Range<usize> {
1393 let start = self.language_byte_range().end;
1394 let end = start + u32::RAW_BYTE_LEN;
1395 start..end
1396 }
1397
1398 pub fn groups_byte_range(&self) -> Range<usize> {
1399 let num_groups = self.num_groups();
1400 let start = self.num_groups_byte_range().end;
1401 let end = start
1402 + (transforms::to_usize(num_groups)).saturating_mul(SequentialMapGroup::RAW_BYTE_LEN);
1403 start..end
1404 }
1405}
1406
1407impl Format<u16> for Cmap13<'_> {
1408 const FORMAT: u16 = 13;
1409}
1410
1411impl<'a> MinByteRange<'a> for Cmap13<'a> {
1412 fn min_byte_range(&self) -> Range<usize> {
1413 0..self.groups_byte_range().end
1414 }
1415 fn min_table_bytes(&self) -> &'a [u8] {
1416 let range = self.min_byte_range();
1417 self.offset_data().as_bytes().get(range).unwrap_or_default()
1418 }
1419}
1420
1421impl ReadArgs for Cmap13<'_> {
1422 type Args = ();
1423}
1424
1425impl<'a> FontRead<'a> for Cmap13<'a> {
1426 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1427 #[allow(clippy::absurd_extreme_comparisons)]
1428 if data.len() < Self::MIN_SIZE {
1429 return Err(ReadError::OutOfBounds);
1430 }
1431 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1432 return Err(ReadError::OutOfBounds);
1433 };
1434 Ok(Self { data })
1435 }
1436}
1437
1438#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1440#[repr(C, packed)]
1441#[doc(hidden)]
1442pub struct Cmap13FixedHeader {
1443 pub format: BigEndian<u16>,
1444 pub reserved: BigEndian<u16>,
1445 pub length: BigEndian<u32>,
1446 pub language: BigEndian<u32>,
1447 pub num_groups: BigEndian<u32>,
1448}
1449
1450#[allow(clippy::absurd_extreme_comparisons)]
1451const _: () = assert!(std::mem::size_of::<Cmap13FixedHeader>() <= Cmap13::MIN_SIZE);
1452
1453#[derive(Clone)]
1455pub struct Cmap13<'a> {
1456 data: TableDataRef<'a, Cmap13FixedHeader>,
1457}
1458
1459#[allow(clippy::needless_lifetimes)]
1460impl<'a> Cmap13<'a> {
1461 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1462 + u16::RAW_BYTE_LEN
1463 + u32::RAW_BYTE_LEN
1464 + u32::RAW_BYTE_LEN
1465 + u32::RAW_BYTE_LEN);
1466 basic_table_impls!(impl_the_methods);
1467
1468 pub fn format(&self) -> u16 {
1470 self.data.header().format.get()
1471 }
1472
1473 pub fn length(&self) -> u32 {
1475 self.data.header().length.get()
1476 }
1477
1478 pub fn language(&self) -> u32 {
1481 self.data.header().language.get()
1482 }
1483
1484 pub fn num_groups(&self) -> u32 {
1486 self.data.header().num_groups.get()
1487 }
1488
1489 pub fn groups(&self) -> &'a [ConstantMapGroup] {
1491 let range = self.groups_byte_range();
1492 self.offset_data()
1493 .read_array(range)
1494 .ok()
1495 .unwrap_or_default()
1496 }
1497
1498 pub fn format_byte_range(&self) -> Range<usize> {
1499 let start = 0;
1500 let end = start + u16::RAW_BYTE_LEN;
1501 start..end
1502 }
1503
1504 pub fn reserved_byte_range(&self) -> Range<usize> {
1505 let start = self.format_byte_range().end;
1506 let end = start + u16::RAW_BYTE_LEN;
1507 start..end
1508 }
1509
1510 pub fn length_byte_range(&self) -> Range<usize> {
1511 let start = self.reserved_byte_range().end;
1512 let end = start + u32::RAW_BYTE_LEN;
1513 start..end
1514 }
1515
1516 pub fn language_byte_range(&self) -> Range<usize> {
1517 let start = self.length_byte_range().end;
1518 let end = start + u32::RAW_BYTE_LEN;
1519 start..end
1520 }
1521
1522 pub fn num_groups_byte_range(&self) -> Range<usize> {
1523 let start = self.language_byte_range().end;
1524 let end = start + u32::RAW_BYTE_LEN;
1525 start..end
1526 }
1527
1528 pub fn groups_byte_range(&self) -> Range<usize> {
1529 let num_groups = self.num_groups();
1530 let start = self.num_groups_byte_range().end;
1531 let end = start
1532 + (transforms::to_usize(num_groups)).saturating_mul(ConstantMapGroup::RAW_BYTE_LEN);
1533 start..end
1534 }
1535}
1536
1537#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1539#[repr(C)]
1540#[repr(packed)]
1541pub struct ConstantMapGroup {
1542 pub start_char_code: BigEndian<u32>,
1544 pub end_char_code: BigEndian<u32>,
1546 pub glyph_id: BigEndian<u32>,
1549}
1550
1551impl ConstantMapGroup {
1552 pub fn start_char_code(&self) -> u32 {
1554 self.start_char_code.get()
1555 }
1556
1557 pub fn end_char_code(&self) -> u32 {
1559 self.end_char_code.get()
1560 }
1561
1562 pub fn glyph_id(&self) -> u32 {
1565 self.glyph_id.get()
1566 }
1567}
1568
1569impl FixedSize for ConstantMapGroup {
1570 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1571}
1572
1573impl Format<u16> for Cmap14<'_> {
1574 const FORMAT: u16 = 14;
1575}
1576
1577impl<'a> MinByteRange<'a> for Cmap14<'a> {
1578 fn min_byte_range(&self) -> Range<usize> {
1579 0..self.var_selector_byte_range().end
1580 }
1581 fn min_table_bytes(&self) -> &'a [u8] {
1582 let range = self.min_byte_range();
1583 self.offset_data().as_bytes().get(range).unwrap_or_default()
1584 }
1585}
1586
1587impl ReadArgs for Cmap14<'_> {
1588 type Args = ();
1589}
1590
1591impl<'a> FontRead<'a> for Cmap14<'a> {
1592 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1593 #[allow(clippy::absurd_extreme_comparisons)]
1594 if data.len() < Self::MIN_SIZE {
1595 return Err(ReadError::OutOfBounds);
1596 }
1597 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1598 return Err(ReadError::OutOfBounds);
1599 };
1600 Ok(Self { data })
1601 }
1602}
1603
1604#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1606#[repr(C, packed)]
1607#[doc(hidden)]
1608pub struct Cmap14FixedHeader {
1609 pub format: BigEndian<u16>,
1610 pub length: BigEndian<u32>,
1611 pub num_var_selector_records: BigEndian<u32>,
1612}
1613
1614#[allow(clippy::absurd_extreme_comparisons)]
1615const _: () = assert!(std::mem::size_of::<Cmap14FixedHeader>() <= Cmap14::MIN_SIZE);
1616
1617#[derive(Clone)]
1619pub struct Cmap14<'a> {
1620 data: TableDataRef<'a, Cmap14FixedHeader>,
1621}
1622
1623#[allow(clippy::needless_lifetimes)]
1624impl<'a> Cmap14<'a> {
1625 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1626 basic_table_impls!(impl_the_methods);
1627
1628 pub fn format(&self) -> u16 {
1630 self.data.header().format.get()
1631 }
1632
1633 pub fn length(&self) -> u32 {
1635 self.data.header().length.get()
1636 }
1637
1638 pub fn num_var_selector_records(&self) -> u32 {
1640 self.data.header().num_var_selector_records.get()
1641 }
1642
1643 pub fn var_selector(&self) -> &'a [VariationSelector] {
1645 let range = self.var_selector_byte_range();
1646 self.offset_data()
1647 .read_array(range)
1648 .ok()
1649 .unwrap_or_default()
1650 }
1651
1652 pub fn format_byte_range(&self) -> Range<usize> {
1653 let start = 0;
1654 let end = start + u16::RAW_BYTE_LEN;
1655 start..end
1656 }
1657
1658 pub fn length_byte_range(&self) -> Range<usize> {
1659 let start = self.format_byte_range().end;
1660 let end = start + u32::RAW_BYTE_LEN;
1661 start..end
1662 }
1663
1664 pub fn num_var_selector_records_byte_range(&self) -> Range<usize> {
1665 let start = self.length_byte_range().end;
1666 let end = start + u32::RAW_BYTE_LEN;
1667 start..end
1668 }
1669
1670 pub fn var_selector_byte_range(&self) -> Range<usize> {
1671 let num_var_selector_records = self.num_var_selector_records();
1672 let start = self.num_var_selector_records_byte_range().end;
1673 let end = start
1674 + (transforms::to_usize(num_var_selector_records))
1675 .saturating_mul(VariationSelector::RAW_BYTE_LEN);
1676 start..end
1677 }
1678}
1679
1680#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1682#[repr(C)]
1683#[repr(packed)]
1684pub struct VariationSelector {
1685 pub var_selector: BigEndian<Uint24>,
1687 pub default_uvs_offset: BigEndian<Nullable<Offset32>>,
1690 pub non_default_uvs_offset: BigEndian<Nullable<Offset32>>,
1693}
1694
1695impl VariationSelector {
1696 pub fn var_selector(&self) -> Uint24 {
1698 self.var_selector.get()
1699 }
1700
1701 pub fn default_uvs_offset(&self) -> Nullable<Offset32> {
1704 self.default_uvs_offset.get()
1705 }
1706
1707 pub fn default_uvs<'a>(&self, data: FontData<'a>) -> Option<Result<DefaultUvs<'a>, ReadError>> {
1713 self.default_uvs_offset().resolve(data)
1714 }
1715
1716 pub fn non_default_uvs_offset(&self) -> Nullable<Offset32> {
1719 self.non_default_uvs_offset.get()
1720 }
1721
1722 pub fn non_default_uvs<'a>(
1728 &self,
1729 data: FontData<'a>,
1730 ) -> Option<Result<NonDefaultUvs<'a>, ReadError>> {
1731 self.non_default_uvs_offset().resolve(data)
1732 }
1733}
1734
1735impl FixedSize for VariationSelector {
1736 const RAW_BYTE_LEN: usize =
1737 Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
1738}
1739
1740impl<'a> MinByteRange<'a> for DefaultUvs<'a> {
1741 fn min_byte_range(&self) -> Range<usize> {
1742 0..self.ranges_byte_range().end
1743 }
1744 fn min_table_bytes(&self) -> &'a [u8] {
1745 let range = self.min_byte_range();
1746 self.offset_data().as_bytes().get(range).unwrap_or_default()
1747 }
1748}
1749
1750impl ReadArgs for DefaultUvs<'_> {
1751 type Args = ();
1752}
1753
1754impl<'a> FontRead<'a> for DefaultUvs<'a> {
1755 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1756 #[allow(clippy::absurd_extreme_comparisons)]
1757 if data.len() < Self::MIN_SIZE {
1758 return Err(ReadError::OutOfBounds);
1759 }
1760 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1761 return Err(ReadError::OutOfBounds);
1762 };
1763 Ok(Self { data })
1764 }
1765}
1766
1767#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1769#[repr(C, packed)]
1770#[doc(hidden)]
1771pub struct DefaultUvsFixedHeader {
1772 pub num_unicode_value_ranges: BigEndian<u32>,
1773}
1774
1775#[allow(clippy::absurd_extreme_comparisons)]
1776const _: () = assert!(std::mem::size_of::<DefaultUvsFixedHeader>() <= DefaultUvs::MIN_SIZE);
1777
1778#[derive(Clone)]
1780pub struct DefaultUvs<'a> {
1781 data: TableDataRef<'a, DefaultUvsFixedHeader>,
1782}
1783
1784#[allow(clippy::needless_lifetimes)]
1785impl<'a> DefaultUvs<'a> {
1786 pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
1787 basic_table_impls!(impl_the_methods);
1788
1789 pub fn num_unicode_value_ranges(&self) -> u32 {
1791 self.data.header().num_unicode_value_ranges.get()
1792 }
1793
1794 pub fn ranges(&self) -> &'a [UnicodeRange] {
1796 let range = self.ranges_byte_range();
1797 self.offset_data()
1798 .read_array(range)
1799 .ok()
1800 .unwrap_or_default()
1801 }
1802
1803 pub fn num_unicode_value_ranges_byte_range(&self) -> Range<usize> {
1804 let start = 0;
1805 let end = start + u32::RAW_BYTE_LEN;
1806 start..end
1807 }
1808
1809 pub fn ranges_byte_range(&self) -> Range<usize> {
1810 let num_unicode_value_ranges = self.num_unicode_value_ranges();
1811 let start = self.num_unicode_value_ranges_byte_range().end;
1812 let end = start
1813 + (transforms::to_usize(num_unicode_value_ranges))
1814 .saturating_mul(UnicodeRange::RAW_BYTE_LEN);
1815 start..end
1816 }
1817}
1818
1819const _: () = assert!(FontData::default_data_long_enough(DefaultUvs::MIN_SIZE));
1820
1821impl Default for DefaultUvs<'_> {
1822 fn default() -> Self {
1823 Self {
1824 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1825 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1826 }
1827 }
1828}
1829
1830impl<'a> MinByteRange<'a> for NonDefaultUvs<'a> {
1831 fn min_byte_range(&self) -> Range<usize> {
1832 0..self.uvs_mapping_byte_range().end
1833 }
1834 fn min_table_bytes(&self) -> &'a [u8] {
1835 let range = self.min_byte_range();
1836 self.offset_data().as_bytes().get(range).unwrap_or_default()
1837 }
1838}
1839
1840impl ReadArgs for NonDefaultUvs<'_> {
1841 type Args = ();
1842}
1843
1844impl<'a> FontRead<'a> for NonDefaultUvs<'a> {
1845 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1846 #[allow(clippy::absurd_extreme_comparisons)]
1847 if data.len() < Self::MIN_SIZE {
1848 return Err(ReadError::OutOfBounds);
1849 }
1850 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1851 return Err(ReadError::OutOfBounds);
1852 };
1853 Ok(Self { data })
1854 }
1855}
1856
1857#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1859#[repr(C, packed)]
1860#[doc(hidden)]
1861pub struct NonDefaultUvsFixedHeader {
1862 pub num_uvs_mappings: BigEndian<u32>,
1863}
1864
1865#[allow(clippy::absurd_extreme_comparisons)]
1866const _: () = assert!(std::mem::size_of::<NonDefaultUvsFixedHeader>() <= NonDefaultUvs::MIN_SIZE);
1867
1868#[derive(Clone)]
1870pub struct NonDefaultUvs<'a> {
1871 data: TableDataRef<'a, NonDefaultUvsFixedHeader>,
1872}
1873
1874#[allow(clippy::needless_lifetimes)]
1875impl<'a> NonDefaultUvs<'a> {
1876 pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
1877 basic_table_impls!(impl_the_methods);
1878
1879 pub fn num_uvs_mappings(&self) -> u32 {
1880 self.data.header().num_uvs_mappings.get()
1881 }
1882
1883 pub fn uvs_mapping(&self) -> &'a [UvsMapping] {
1884 let range = self.uvs_mapping_byte_range();
1885 self.offset_data()
1886 .read_array(range)
1887 .ok()
1888 .unwrap_or_default()
1889 }
1890
1891 pub fn num_uvs_mappings_byte_range(&self) -> Range<usize> {
1892 let start = 0;
1893 let end = start + u32::RAW_BYTE_LEN;
1894 start..end
1895 }
1896
1897 pub fn uvs_mapping_byte_range(&self) -> Range<usize> {
1898 let num_uvs_mappings = self.num_uvs_mappings();
1899 let start = self.num_uvs_mappings_byte_range().end;
1900 let end = start
1901 + (transforms::to_usize(num_uvs_mappings)).saturating_mul(UvsMapping::RAW_BYTE_LEN);
1902 start..end
1903 }
1904}
1905
1906const _: () = assert!(FontData::default_data_long_enough(NonDefaultUvs::MIN_SIZE));
1907
1908impl Default for NonDefaultUvs<'_> {
1909 fn default() -> Self {
1910 Self {
1911 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1912 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1913 }
1914 }
1915}
1916
1917#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1919#[repr(C)]
1920#[repr(packed)]
1921pub struct UvsMapping {
1922 pub unicode_value: BigEndian<Uint24>,
1924 pub glyph_id: BigEndian<u16>,
1926}
1927
1928impl UvsMapping {
1929 pub fn unicode_value(&self) -> Uint24 {
1931 self.unicode_value.get()
1932 }
1933
1934 pub fn glyph_id(&self) -> u16 {
1936 self.glyph_id.get()
1937 }
1938}
1939
1940impl FixedSize for UvsMapping {
1941 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1942}
1943
1944#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1946#[repr(C)]
1947#[repr(packed)]
1948pub struct UnicodeRange {
1949 pub start_unicode_value: BigEndian<Uint24>,
1951 pub additional_count: u8,
1953}
1954
1955impl UnicodeRange {
1956 pub fn start_unicode_value(&self) -> Uint24 {
1958 self.start_unicode_value.get()
1959 }
1960
1961 pub fn additional_count(&self) -> u8 {
1963 self.additional_count
1964 }
1965}
1966
1967impl FixedSize for UnicodeRange {
1968 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
1969}