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.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 Ok(Self { data })
34 }
35}
36
37#[derive(Clone)]
39pub struct Cmap<'a> {
40 data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Cmap<'a> {
45 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
46 basic_table_impls!(impl_the_methods);
47
48 pub fn version(&self) -> u16 {
50 let range = self.version_byte_range();
51 self.data.read_at(range.start).ok().unwrap()
52 }
53
54 pub fn num_tables(&self) -> u16 {
56 let range = self.num_tables_byte_range();
57 self.data.read_at(range.start).ok().unwrap()
58 }
59
60 pub fn encoding_records(&self) -> &'a [EncodingRecord] {
61 let range = self.encoding_records_byte_range();
62 self.data.read_array(range).ok().unwrap_or_default()
63 }
64
65 pub fn version_byte_range(&self) -> Range<usize> {
66 let start = 0;
67 let end = start + u16::RAW_BYTE_LEN;
68 start..end
69 }
70
71 pub fn num_tables_byte_range(&self) -> Range<usize> {
72 let start = self.version_byte_range().end;
73 let end = start + u16::RAW_BYTE_LEN;
74 start..end
75 }
76
77 pub fn encoding_records_byte_range(&self) -> Range<usize> {
78 let num_tables = self.num_tables();
79 let start = self.num_tables_byte_range().end;
80 let end =
81 start + (transforms::to_usize(num_tables)).saturating_mul(EncodingRecord::RAW_BYTE_LEN);
82 start..end
83 }
84}
85
86const _: () = assert!(FontData::default_data_long_enough(Cmap::MIN_SIZE));
87
88impl Default for Cmap<'_> {
89 fn default() -> Self {
90 Self {
91 data: FontData::default_table_data(),
92 }
93 }
94}
95
96#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
98#[repr(C)]
99#[repr(packed)]
100pub struct EncodingRecord {
101 pub platform_id: BigEndian<PlatformId>,
103 pub encoding_id: BigEndian<u16>,
105 pub subtable_offset: BigEndian<Offset32>,
108}
109
110impl EncodingRecord {
111 pub fn platform_id(&self) -> PlatformId {
113 self.platform_id.get()
114 }
115
116 pub fn encoding_id(&self) -> u16 {
118 self.encoding_id.get()
119 }
120
121 pub fn subtable_offset(&self) -> Offset32 {
124 self.subtable_offset.get()
125 }
126
127 pub fn subtable<'a>(&self, data: FontData<'a>) -> Result<CmapSubtable<'a>, ReadError> {
133 self.subtable_offset().resolve(data)
134 }
135}
136
137impl FixedSize for EncodingRecord {
138 const RAW_BYTE_LEN: usize =
139 PlatformId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
140}
141
142#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
144#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
145#[repr(u16)]
146#[allow(clippy::manual_non_exhaustive)]
147pub enum PlatformId {
148 #[default]
149 Unicode = 0,
150 Macintosh = 1,
151 ISO = 2,
152 Windows = 3,
153 Custom = 4,
154 #[doc(hidden)]
155 Unknown,
157}
158
159impl PlatformId {
160 pub fn new(raw: u16) -> Self {
164 match raw {
165 0 => Self::Unicode,
166 1 => Self::Macintosh,
167 2 => Self::ISO,
168 3 => Self::Windows,
169 4 => Self::Custom,
170 _ => Self::Unknown,
171 }
172 }
173}
174
175impl font_types::Scalar for PlatformId {
176 type Raw = <u16 as font_types::Scalar>::Raw;
177 fn to_raw(self) -> Self::Raw {
178 (self as u16).to_raw()
179 }
180 fn from_raw(raw: Self::Raw) -> Self {
181 let t = <u16>::from_raw(raw);
182 Self::new(t)
183 }
184}
185
186#[derive(Clone)]
188pub enum CmapSubtable<'a> {
189 Format0(Cmap0<'a>),
190 Format2(Cmap2<'a>),
191 Format4(Cmap4<'a>),
192 Format6(Cmap6<'a>),
193 Format8(Cmap8<'a>),
194 Format10(Cmap10<'a>),
195 Format12(Cmap12<'a>),
196 Format13(Cmap13<'a>),
197 Format14(Cmap14<'a>),
198}
199
200impl Default for CmapSubtable<'_> {
201 fn default() -> Self {
202 Self::Format0(Default::default())
203 }
204}
205
206impl<'a> CmapSubtable<'a> {
207 pub fn offset_data(&self) -> FontData<'a> {
209 match self {
210 Self::Format0(item) => item.offset_data(),
211 Self::Format2(item) => item.offset_data(),
212 Self::Format4(item) => item.offset_data(),
213 Self::Format6(item) => item.offset_data(),
214 Self::Format8(item) => item.offset_data(),
215 Self::Format10(item) => item.offset_data(),
216 Self::Format12(item) => item.offset_data(),
217 Self::Format13(item) => item.offset_data(),
218 Self::Format14(item) => item.offset_data(),
219 }
220 }
221
222 pub fn format(&self) -> u16 {
224 match self {
225 Self::Format0(item) => item.format(),
226 Self::Format2(item) => item.format(),
227 Self::Format4(item) => item.format(),
228 Self::Format6(item) => item.format(),
229 Self::Format8(item) => item.format(),
230 Self::Format10(item) => item.format(),
231 Self::Format12(item) => item.format(),
232 Self::Format13(item) => item.format(),
233 Self::Format14(item) => item.format(),
234 }
235 }
236}
237
238impl ReadArgs for CmapSubtable<'_> {
239 type Args = ();
240}
241
242impl<'a> FontRead<'a> for CmapSubtable<'a> {
243 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
244 let format: u16 = data.read_at(0usize)?;
245 match format {
246 Cmap0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
247 Cmap2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
248 Cmap4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
249 Cmap6::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
250 Cmap8::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
251 Cmap10::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
252 Cmap12::FORMAT => Ok(Self::Format12(FontRead::read(data)?)),
253 Cmap13::FORMAT => Ok(Self::Format13(FontRead::read(data)?)),
254 Cmap14::FORMAT => Ok(Self::Format14(FontRead::read(data)?)),
255 other => Err(ReadError::InvalidFormat(other.into())),
256 }
257 }
258}
259
260impl<'a> MinByteRange<'a> for CmapSubtable<'a> {
261 fn min_byte_range(&self) -> Range<usize> {
262 match self {
263 Self::Format0(item) => item.min_byte_range(),
264 Self::Format2(item) => item.min_byte_range(),
265 Self::Format4(item) => item.min_byte_range(),
266 Self::Format6(item) => item.min_byte_range(),
267 Self::Format8(item) => item.min_byte_range(),
268 Self::Format10(item) => item.min_byte_range(),
269 Self::Format12(item) => item.min_byte_range(),
270 Self::Format13(item) => item.min_byte_range(),
271 Self::Format14(item) => item.min_byte_range(),
272 }
273 }
274 fn min_table_bytes(&self) -> &'a [u8] {
275 match self {
276 Self::Format0(item) => item.min_table_bytes(),
277 Self::Format2(item) => item.min_table_bytes(),
278 Self::Format4(item) => item.min_table_bytes(),
279 Self::Format6(item) => item.min_table_bytes(),
280 Self::Format8(item) => item.min_table_bytes(),
281 Self::Format10(item) => item.min_table_bytes(),
282 Self::Format12(item) => item.min_table_bytes(),
283 Self::Format13(item) => item.min_table_bytes(),
284 Self::Format14(item) => item.min_table_bytes(),
285 }
286 }
287}
288
289impl Format<u16> for Cmap0<'_> {
290 const FORMAT: u16 = 0;
291}
292
293impl<'a> MinByteRange<'a> for Cmap0<'a> {
294 fn min_byte_range(&self) -> Range<usize> {
295 0..self.glyph_id_array_byte_range().end
296 }
297 fn min_table_bytes(&self) -> &'a [u8] {
298 let range = self.min_byte_range();
299 self.data.as_bytes().get(range).unwrap_or_default()
300 }
301}
302
303impl ReadArgs for Cmap0<'_> {
304 type Args = ();
305}
306
307impl<'a> FontRead<'a> for Cmap0<'a> {
308 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
309 #[allow(clippy::absurd_extreme_comparisons)]
310 if data.len() < Self::MIN_SIZE {
311 return Err(ReadError::OutOfBounds);
312 }
313 Ok(Self { data })
314 }
315}
316
317#[derive(Clone)]
319pub struct Cmap0<'a> {
320 data: FontData<'a>,
321}
322
323#[allow(clippy::needless_lifetimes)]
324impl<'a> Cmap0<'a> {
325 pub const MIN_SIZE: usize =
326 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN * 256_usize);
327 basic_table_impls!(impl_the_methods);
328
329 pub fn format(&self) -> u16 {
331 let range = self.format_byte_range();
332 self.data.read_at(range.start).ok().unwrap()
333 }
334
335 pub fn length(&self) -> u16 {
337 let range = self.length_byte_range();
338 self.data.read_at(range.start).ok().unwrap()
339 }
340
341 pub fn language(&self) -> u16 {
344 let range = self.language_byte_range();
345 self.data.read_at(range.start).ok().unwrap()
346 }
347
348 pub fn glyph_id_array(&self) -> &'a [u8] {
350 let range = self.glyph_id_array_byte_range();
351 self.data.read_array(range).ok().unwrap()
352 }
353
354 pub fn format_byte_range(&self) -> Range<usize> {
355 let start = 0;
356 let end = start + u16::RAW_BYTE_LEN;
357 start..end
358 }
359
360 pub fn length_byte_range(&self) -> Range<usize> {
361 let start = self.format_byte_range().end;
362 let end = start + u16::RAW_BYTE_LEN;
363 start..end
364 }
365
366 pub fn language_byte_range(&self) -> Range<usize> {
367 let start = self.length_byte_range().end;
368 let end = start + u16::RAW_BYTE_LEN;
369 start..end
370 }
371
372 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
373 let start = self.language_byte_range().end;
374 let end = start + (256_usize).saturating_mul(u8::RAW_BYTE_LEN);
375 start..end
376 }
377}
378
379const _: () = assert!(FontData::default_data_long_enough(Cmap0::MIN_SIZE));
380
381impl Default for Cmap0<'_> {
382 fn default() -> Self {
383 Self {
384 data: FontData::default_table_data(),
385 }
386 }
387}
388
389impl Format<u16> for Cmap2<'_> {
390 const FORMAT: u16 = 2;
391}
392
393impl<'a> MinByteRange<'a> for Cmap2<'a> {
394 fn min_byte_range(&self) -> Range<usize> {
395 0..self.sub_header_keys_byte_range().end
396 }
397 fn min_table_bytes(&self) -> &'a [u8] {
398 let range = self.min_byte_range();
399 self.data.as_bytes().get(range).unwrap_or_default()
400 }
401}
402
403impl ReadArgs for Cmap2<'_> {
404 type Args = ();
405}
406
407impl<'a> FontRead<'a> for Cmap2<'a> {
408 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
409 #[allow(clippy::absurd_extreme_comparisons)]
410 if data.len() < Self::MIN_SIZE {
411 return Err(ReadError::OutOfBounds);
412 }
413 Ok(Self { data })
414 }
415}
416
417#[derive(Clone)]
419pub struct Cmap2<'a> {
420 data: FontData<'a>,
421}
422
423#[allow(clippy::needless_lifetimes)]
424impl<'a> Cmap2<'a> {
425 pub const MIN_SIZE: usize =
426 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN * 256_usize);
427 basic_table_impls!(impl_the_methods);
428
429 pub fn format(&self) -> u16 {
431 let range = self.format_byte_range();
432 self.data.read_at(range.start).ok().unwrap()
433 }
434
435 pub fn length(&self) -> u16 {
437 let range = self.length_byte_range();
438 self.data.read_at(range.start).ok().unwrap()
439 }
440
441 pub fn language(&self) -> u16 {
444 let range = self.language_byte_range();
445 self.data.read_at(range.start).ok().unwrap()
446 }
447
448 pub fn sub_header_keys(&self) -> &'a [BigEndian<u16>] {
451 let range = self.sub_header_keys_byte_range();
452 self.data.read_array(range).ok().unwrap()
453 }
454
455 pub fn format_byte_range(&self) -> Range<usize> {
456 let start = 0;
457 let end = start + u16::RAW_BYTE_LEN;
458 start..end
459 }
460
461 pub fn length_byte_range(&self) -> Range<usize> {
462 let start = self.format_byte_range().end;
463 let end = start + u16::RAW_BYTE_LEN;
464 start..end
465 }
466
467 pub fn language_byte_range(&self) -> Range<usize> {
468 let start = self.length_byte_range().end;
469 let end = start + u16::RAW_BYTE_LEN;
470 start..end
471 }
472
473 pub fn sub_header_keys_byte_range(&self) -> Range<usize> {
474 let start = self.language_byte_range().end;
475 let end = start + (256_usize).saturating_mul(u16::RAW_BYTE_LEN);
476 start..end
477 }
478}
479
480#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
482#[repr(C)]
483#[repr(packed)]
484pub struct SubHeader {
485 pub first_code: BigEndian<u16>,
487 pub entry_count: BigEndian<u16>,
489 pub id_delta: BigEndian<i16>,
491 pub id_range_offset: BigEndian<u16>,
493}
494
495impl SubHeader {
496 pub fn first_code(&self) -> u16 {
498 self.first_code.get()
499 }
500
501 pub fn entry_count(&self) -> u16 {
503 self.entry_count.get()
504 }
505
506 pub fn id_delta(&self) -> i16 {
508 self.id_delta.get()
509 }
510
511 pub fn id_range_offset(&self) -> u16 {
513 self.id_range_offset.get()
514 }
515}
516
517impl FixedSize for SubHeader {
518 const RAW_BYTE_LEN: usize =
519 u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
520}
521
522impl Format<u16> for Cmap4<'_> {
523 const FORMAT: u16 = 4;
524}
525
526impl<'a> MinByteRange<'a> for Cmap4<'a> {
527 fn min_byte_range(&self) -> Range<usize> {
528 0..self.glyph_id_array_byte_range().end
529 }
530 fn min_table_bytes(&self) -> &'a [u8] {
531 let range = self.min_byte_range();
532 self.data.as_bytes().get(range).unwrap_or_default()
533 }
534}
535
536impl ReadArgs for Cmap4<'_> {
537 type Args = ();
538}
539
540impl<'a> FontRead<'a> for Cmap4<'a> {
541 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
542 #[allow(clippy::absurd_extreme_comparisons)]
543 if data.len() < Self::MIN_SIZE {
544 return Err(ReadError::OutOfBounds);
545 }
546 Ok(Self { data })
547 }
548}
549
550#[derive(Clone)]
552pub struct Cmap4<'a> {
553 data: FontData<'a>,
554}
555
556#[allow(clippy::needless_lifetimes)]
557impl<'a> Cmap4<'a> {
558 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
559 + u16::RAW_BYTE_LEN
560 + u16::RAW_BYTE_LEN
561 + u16::RAW_BYTE_LEN
562 + u16::RAW_BYTE_LEN
563 + u16::RAW_BYTE_LEN
564 + u16::RAW_BYTE_LEN
565 + u16::RAW_BYTE_LEN);
566 basic_table_impls!(impl_the_methods);
567
568 pub fn format(&self) -> u16 {
570 let range = self.format_byte_range();
571 self.data.read_at(range.start).ok().unwrap()
572 }
573
574 pub fn length(&self) -> u16 {
576 let range = self.length_byte_range();
577 self.data.read_at(range.start).ok().unwrap()
578 }
579
580 pub fn language(&self) -> u16 {
583 let range = self.language_byte_range();
584 self.data.read_at(range.start).ok().unwrap()
585 }
586
587 pub fn seg_count_x2(&self) -> u16 {
589 let range = self.seg_count_x2_byte_range();
590 self.data.read_at(range.start).ok().unwrap()
591 }
592
593 pub fn search_range(&self) -> u16 {
597 let range = self.search_range_byte_range();
598 self.data.read_at(range.start).ok().unwrap()
599 }
600
601 pub fn entry_selector(&self) -> u16 {
604 let range = self.entry_selector_byte_range();
605 self.data.read_at(range.start).ok().unwrap()
606 }
607
608 pub fn range_shift(&self) -> u16 {
611 let range = self.range_shift_byte_range();
612 self.data.read_at(range.start).ok().unwrap()
613 }
614
615 pub fn end_code(&self) -> &'a [BigEndian<u16>] {
617 let range = self.end_code_byte_range();
618 self.data.read_array(range).ok().unwrap_or_default()
619 }
620
621 pub fn start_code(&self) -> &'a [BigEndian<u16>] {
623 let range = self.start_code_byte_range();
624 self.data.read_array(range).ok().unwrap_or_default()
625 }
626
627 pub fn id_delta(&self) -> &'a [BigEndian<i16>] {
629 let range = self.id_delta_byte_range();
630 self.data.read_array(range).ok().unwrap_or_default()
631 }
632
633 pub fn id_range_offsets(&self) -> &'a [BigEndian<u16>] {
635 let range = self.id_range_offsets_byte_range();
636 self.data.read_array(range).ok().unwrap_or_default()
637 }
638
639 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
641 let range = self.glyph_id_array_byte_range();
642 self.data.read_array(range).ok().unwrap_or_default()
643 }
644
645 pub fn format_byte_range(&self) -> Range<usize> {
646 let start = 0;
647 let end = start + u16::RAW_BYTE_LEN;
648 start..end
649 }
650
651 pub fn length_byte_range(&self) -> Range<usize> {
652 let start = self.format_byte_range().end;
653 let end = start + u16::RAW_BYTE_LEN;
654 start..end
655 }
656
657 pub fn language_byte_range(&self) -> Range<usize> {
658 let start = self.length_byte_range().end;
659 let end = start + u16::RAW_BYTE_LEN;
660 start..end
661 }
662
663 pub fn seg_count_x2_byte_range(&self) -> Range<usize> {
664 let start = self.language_byte_range().end;
665 let end = start + u16::RAW_BYTE_LEN;
666 start..end
667 }
668
669 pub fn search_range_byte_range(&self) -> Range<usize> {
670 let start = self.seg_count_x2_byte_range().end;
671 let end = start + u16::RAW_BYTE_LEN;
672 start..end
673 }
674
675 pub fn entry_selector_byte_range(&self) -> Range<usize> {
676 let start = self.search_range_byte_range().end;
677 let end = start + u16::RAW_BYTE_LEN;
678 start..end
679 }
680
681 pub fn range_shift_byte_range(&self) -> Range<usize> {
682 let start = self.entry_selector_byte_range().end;
683 let end = start + u16::RAW_BYTE_LEN;
684 start..end
685 }
686
687 pub fn end_code_byte_range(&self) -> Range<usize> {
688 let seg_count_x2 = self.seg_count_x2();
689 let start = self.range_shift_byte_range().end;
690 let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
691 start..end
692 }
693
694 pub fn reserved_pad_byte_range(&self) -> Range<usize> {
695 let start = self.end_code_byte_range().end;
696 let end = start + u16::RAW_BYTE_LEN;
697 start..end
698 }
699
700 pub fn start_code_byte_range(&self) -> Range<usize> {
701 let seg_count_x2 = self.seg_count_x2();
702 let start = self.reserved_pad_byte_range().end;
703 let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
704 start..end
705 }
706
707 pub fn id_delta_byte_range(&self) -> Range<usize> {
708 let seg_count_x2 = self.seg_count_x2();
709 let start = self.start_code_byte_range().end;
710 let end = start + (transforms::half(seg_count_x2)).saturating_mul(i16::RAW_BYTE_LEN);
711 start..end
712 }
713
714 pub fn id_range_offsets_byte_range(&self) -> Range<usize> {
715 let seg_count_x2 = self.seg_count_x2();
716 let start = self.id_delta_byte_range().end;
717 let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
718 start..end
719 }
720
721 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
722 let start = self.id_range_offsets_byte_range().end;
723 let end =
724 start + self.data.len().saturating_sub(start) / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
725 start..end
726 }
727}
728
729impl Format<u16> for Cmap6<'_> {
730 const FORMAT: u16 = 6;
731}
732
733impl<'a> MinByteRange<'a> for Cmap6<'a> {
734 fn min_byte_range(&self) -> Range<usize> {
735 0..self.glyph_id_array_byte_range().end
736 }
737 fn min_table_bytes(&self) -> &'a [u8] {
738 let range = self.min_byte_range();
739 self.data.as_bytes().get(range).unwrap_or_default()
740 }
741}
742
743impl ReadArgs for Cmap6<'_> {
744 type Args = ();
745}
746
747impl<'a> FontRead<'a> for Cmap6<'a> {
748 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
749 #[allow(clippy::absurd_extreme_comparisons)]
750 if data.len() < Self::MIN_SIZE {
751 return Err(ReadError::OutOfBounds);
752 }
753 Ok(Self { data })
754 }
755}
756
757#[derive(Clone)]
759pub struct Cmap6<'a> {
760 data: FontData<'a>,
761}
762
763#[allow(clippy::needless_lifetimes)]
764impl<'a> Cmap6<'a> {
765 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
766 + u16::RAW_BYTE_LEN
767 + u16::RAW_BYTE_LEN
768 + u16::RAW_BYTE_LEN
769 + u16::RAW_BYTE_LEN);
770 basic_table_impls!(impl_the_methods);
771
772 pub fn format(&self) -> u16 {
774 let range = self.format_byte_range();
775 self.data.read_at(range.start).ok().unwrap()
776 }
777
778 pub fn length(&self) -> u16 {
780 let range = self.length_byte_range();
781 self.data.read_at(range.start).ok().unwrap()
782 }
783
784 pub fn language(&self) -> u16 {
787 let range = self.language_byte_range();
788 self.data.read_at(range.start).ok().unwrap()
789 }
790
791 pub fn first_code(&self) -> u16 {
793 let range = self.first_code_byte_range();
794 self.data.read_at(range.start).ok().unwrap()
795 }
796
797 pub fn entry_count(&self) -> u16 {
799 let range = self.entry_count_byte_range();
800 self.data.read_at(range.start).ok().unwrap()
801 }
802
803 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
805 let range = self.glyph_id_array_byte_range();
806 self.data.read_array(range).ok().unwrap_or_default()
807 }
808
809 pub fn format_byte_range(&self) -> Range<usize> {
810 let start = 0;
811 let end = start + u16::RAW_BYTE_LEN;
812 start..end
813 }
814
815 pub fn length_byte_range(&self) -> Range<usize> {
816 let start = self.format_byte_range().end;
817 let end = start + u16::RAW_BYTE_LEN;
818 start..end
819 }
820
821 pub fn language_byte_range(&self) -> Range<usize> {
822 let start = self.length_byte_range().end;
823 let end = start + u16::RAW_BYTE_LEN;
824 start..end
825 }
826
827 pub fn first_code_byte_range(&self) -> Range<usize> {
828 let start = self.language_byte_range().end;
829 let end = start + u16::RAW_BYTE_LEN;
830 start..end
831 }
832
833 pub fn entry_count_byte_range(&self) -> Range<usize> {
834 let start = self.first_code_byte_range().end;
835 let end = start + u16::RAW_BYTE_LEN;
836 start..end
837 }
838
839 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
840 let entry_count = self.entry_count();
841 let start = self.entry_count_byte_range().end;
842 let end = start + (transforms::to_usize(entry_count)).saturating_mul(u16::RAW_BYTE_LEN);
843 start..end
844 }
845}
846
847impl Format<u16> for Cmap8<'_> {
848 const FORMAT: u16 = 8;
849}
850
851impl<'a> MinByteRange<'a> for Cmap8<'a> {
852 fn min_byte_range(&self) -> Range<usize> {
853 0..self.groups_byte_range().end
854 }
855 fn min_table_bytes(&self) -> &'a [u8] {
856 let range = self.min_byte_range();
857 self.data.as_bytes().get(range).unwrap_or_default()
858 }
859}
860
861impl ReadArgs for Cmap8<'_> {
862 type Args = ();
863}
864
865impl<'a> FontRead<'a> for Cmap8<'a> {
866 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
867 #[allow(clippy::absurd_extreme_comparisons)]
868 if data.len() < Self::MIN_SIZE {
869 return Err(ReadError::OutOfBounds);
870 }
871 Ok(Self { data })
872 }
873}
874
875#[derive(Clone)]
877pub struct Cmap8<'a> {
878 data: FontData<'a>,
879}
880
881#[allow(clippy::needless_lifetimes)]
882impl<'a> Cmap8<'a> {
883 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
884 + u16::RAW_BYTE_LEN
885 + u32::RAW_BYTE_LEN
886 + u32::RAW_BYTE_LEN
887 + u8::RAW_BYTE_LEN * 8192_usize
888 + u32::RAW_BYTE_LEN);
889 basic_table_impls!(impl_the_methods);
890
891 pub fn format(&self) -> u16 {
893 let range = self.format_byte_range();
894 self.data.read_at(range.start).ok().unwrap()
895 }
896
897 pub fn length(&self) -> u32 {
899 let range = self.length_byte_range();
900 self.data.read_at(range.start).ok().unwrap()
901 }
902
903 pub fn language(&self) -> u32 {
906 let range = self.language_byte_range();
907 self.data.read_at(range.start).ok().unwrap()
908 }
909
910 pub fn is32(&self) -> &'a [u8] {
914 let range = self.is32_byte_range();
915 self.data.read_array(range).ok().unwrap()
916 }
917
918 pub fn num_groups(&self) -> u32 {
920 let range = self.num_groups_byte_range();
921 self.data.read_at(range.start).ok().unwrap()
922 }
923
924 pub fn groups(&self) -> &'a [SequentialMapGroup] {
926 let range = self.groups_byte_range();
927 self.data.read_array(range).ok().unwrap_or_default()
928 }
929
930 pub fn format_byte_range(&self) -> Range<usize> {
931 let start = 0;
932 let end = start + u16::RAW_BYTE_LEN;
933 start..end
934 }
935
936 pub fn reserved_byte_range(&self) -> Range<usize> {
937 let start = self.format_byte_range().end;
938 let end = start + u16::RAW_BYTE_LEN;
939 start..end
940 }
941
942 pub fn length_byte_range(&self) -> Range<usize> {
943 let start = self.reserved_byte_range().end;
944 let end = start + u32::RAW_BYTE_LEN;
945 start..end
946 }
947
948 pub fn language_byte_range(&self) -> Range<usize> {
949 let start = self.length_byte_range().end;
950 let end = start + u32::RAW_BYTE_LEN;
951 start..end
952 }
953
954 pub fn is32_byte_range(&self) -> Range<usize> {
955 let start = self.language_byte_range().end;
956 let end = start + (8192_usize).saturating_mul(u8::RAW_BYTE_LEN);
957 start..end
958 }
959
960 pub fn num_groups_byte_range(&self) -> Range<usize> {
961 let start = self.is32_byte_range().end;
962 let end = start + u32::RAW_BYTE_LEN;
963 start..end
964 }
965
966 pub fn groups_byte_range(&self) -> Range<usize> {
967 let num_groups = self.num_groups();
968 let start = self.num_groups_byte_range().end;
969 let end = start
970 + (transforms::to_usize(num_groups)).saturating_mul(SequentialMapGroup::RAW_BYTE_LEN);
971 start..end
972 }
973}
974
975#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
977#[repr(C)]
978#[repr(packed)]
979pub struct SequentialMapGroup {
980 pub start_char_code: BigEndian<u32>,
985 pub end_char_code: BigEndian<u32>,
988 pub start_glyph_id: BigEndian<u32>,
990}
991
992impl SequentialMapGroup {
993 pub fn start_char_code(&self) -> u32 {
998 self.start_char_code.get()
999 }
1000
1001 pub fn end_char_code(&self) -> u32 {
1004 self.end_char_code.get()
1005 }
1006
1007 pub fn start_glyph_id(&self) -> u32 {
1009 self.start_glyph_id.get()
1010 }
1011}
1012
1013impl FixedSize for SequentialMapGroup {
1014 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1015}
1016
1017impl Format<u16> for Cmap10<'_> {
1018 const FORMAT: u16 = 10;
1019}
1020
1021impl<'a> MinByteRange<'a> for Cmap10<'a> {
1022 fn min_byte_range(&self) -> Range<usize> {
1023 0..self.glyph_id_array_byte_range().end
1024 }
1025 fn min_table_bytes(&self) -> &'a [u8] {
1026 let range = self.min_byte_range();
1027 self.data.as_bytes().get(range).unwrap_or_default()
1028 }
1029}
1030
1031impl ReadArgs for Cmap10<'_> {
1032 type Args = ();
1033}
1034
1035impl<'a> FontRead<'a> for Cmap10<'a> {
1036 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1037 #[allow(clippy::absurd_extreme_comparisons)]
1038 if data.len() < Self::MIN_SIZE {
1039 return Err(ReadError::OutOfBounds);
1040 }
1041 Ok(Self { data })
1042 }
1043}
1044
1045#[derive(Clone)]
1047pub struct Cmap10<'a> {
1048 data: FontData<'a>,
1049}
1050
1051#[allow(clippy::needless_lifetimes)]
1052impl<'a> Cmap10<'a> {
1053 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1054 + u16::RAW_BYTE_LEN
1055 + u32::RAW_BYTE_LEN
1056 + u32::RAW_BYTE_LEN
1057 + u32::RAW_BYTE_LEN
1058 + u32::RAW_BYTE_LEN);
1059 basic_table_impls!(impl_the_methods);
1060
1061 pub fn format(&self) -> u16 {
1063 let range = self.format_byte_range();
1064 self.data.read_at(range.start).ok().unwrap()
1065 }
1066
1067 pub fn length(&self) -> u32 {
1069 let range = self.length_byte_range();
1070 self.data.read_at(range.start).ok().unwrap()
1071 }
1072
1073 pub fn language(&self) -> u32 {
1076 let range = self.language_byte_range();
1077 self.data.read_at(range.start).ok().unwrap()
1078 }
1079
1080 pub fn start_char_code(&self) -> u32 {
1082 let range = self.start_char_code_byte_range();
1083 self.data.read_at(range.start).ok().unwrap()
1084 }
1085
1086 pub fn num_chars(&self) -> u32 {
1088 let range = self.num_chars_byte_range();
1089 self.data.read_at(range.start).ok().unwrap()
1090 }
1091
1092 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
1094 let range = self.glyph_id_array_byte_range();
1095 self.data.read_array(range).ok().unwrap_or_default()
1096 }
1097
1098 pub fn format_byte_range(&self) -> Range<usize> {
1099 let start = 0;
1100 let end = start + u16::RAW_BYTE_LEN;
1101 start..end
1102 }
1103
1104 pub fn reserved_byte_range(&self) -> Range<usize> {
1105 let start = self.format_byte_range().end;
1106 let end = start + u16::RAW_BYTE_LEN;
1107 start..end
1108 }
1109
1110 pub fn length_byte_range(&self) -> Range<usize> {
1111 let start = self.reserved_byte_range().end;
1112 let end = start + u32::RAW_BYTE_LEN;
1113 start..end
1114 }
1115
1116 pub fn language_byte_range(&self) -> Range<usize> {
1117 let start = self.length_byte_range().end;
1118 let end = start + u32::RAW_BYTE_LEN;
1119 start..end
1120 }
1121
1122 pub fn start_char_code_byte_range(&self) -> Range<usize> {
1123 let start = self.language_byte_range().end;
1124 let end = start + u32::RAW_BYTE_LEN;
1125 start..end
1126 }
1127
1128 pub fn num_chars_byte_range(&self) -> Range<usize> {
1129 let start = self.start_char_code_byte_range().end;
1130 let end = start + u32::RAW_BYTE_LEN;
1131 start..end
1132 }
1133
1134 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
1135 let num_chars = self.num_chars();
1136 let start = self.num_chars_byte_range().end;
1137 let end = start + (transforms::to_usize(num_chars)).saturating_mul(u16::RAW_BYTE_LEN);
1138 start..end
1139 }
1140}
1141
1142impl Format<u16> for Cmap12<'_> {
1143 const FORMAT: u16 = 12;
1144}
1145
1146impl<'a> MinByteRange<'a> for Cmap12<'a> {
1147 fn min_byte_range(&self) -> Range<usize> {
1148 0..self.groups_byte_range().end
1149 }
1150 fn min_table_bytes(&self) -> &'a [u8] {
1151 let range = self.min_byte_range();
1152 self.data.as_bytes().get(range).unwrap_or_default()
1153 }
1154}
1155
1156impl ReadArgs for Cmap12<'_> {
1157 type Args = ();
1158}
1159
1160impl<'a> FontRead<'a> for Cmap12<'a> {
1161 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1162 #[allow(clippy::absurd_extreme_comparisons)]
1163 if data.len() < Self::MIN_SIZE {
1164 return Err(ReadError::OutOfBounds);
1165 }
1166 Ok(Self { data })
1167 }
1168}
1169
1170#[derive(Clone)]
1172pub struct Cmap12<'a> {
1173 data: FontData<'a>,
1174}
1175
1176#[allow(clippy::needless_lifetimes)]
1177impl<'a> Cmap12<'a> {
1178 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1179 + u16::RAW_BYTE_LEN
1180 + u32::RAW_BYTE_LEN
1181 + u32::RAW_BYTE_LEN
1182 + u32::RAW_BYTE_LEN);
1183 basic_table_impls!(impl_the_methods);
1184
1185 pub fn format(&self) -> u16 {
1187 let range = self.format_byte_range();
1188 self.data.read_at(range.start).ok().unwrap()
1189 }
1190
1191 pub fn length(&self) -> u32 {
1193 let range = self.length_byte_range();
1194 self.data.read_at(range.start).ok().unwrap()
1195 }
1196
1197 pub fn language(&self) -> u32 {
1200 let range = self.language_byte_range();
1201 self.data.read_at(range.start).ok().unwrap()
1202 }
1203
1204 pub fn num_groups(&self) -> u32 {
1206 let range = self.num_groups_byte_range();
1207 self.data.read_at(range.start).ok().unwrap()
1208 }
1209
1210 pub fn groups(&self) -> &'a [SequentialMapGroup] {
1212 let range = self.groups_byte_range();
1213 self.data.read_array(range).ok().unwrap_or_default()
1214 }
1215
1216 pub fn format_byte_range(&self) -> Range<usize> {
1217 let start = 0;
1218 let end = start + u16::RAW_BYTE_LEN;
1219 start..end
1220 }
1221
1222 pub fn reserved_byte_range(&self) -> Range<usize> {
1223 let start = self.format_byte_range().end;
1224 let end = start + u16::RAW_BYTE_LEN;
1225 start..end
1226 }
1227
1228 pub fn length_byte_range(&self) -> Range<usize> {
1229 let start = self.reserved_byte_range().end;
1230 let end = start + u32::RAW_BYTE_LEN;
1231 start..end
1232 }
1233
1234 pub fn language_byte_range(&self) -> Range<usize> {
1235 let start = self.length_byte_range().end;
1236 let end = start + u32::RAW_BYTE_LEN;
1237 start..end
1238 }
1239
1240 pub fn num_groups_byte_range(&self) -> Range<usize> {
1241 let start = self.language_byte_range().end;
1242 let end = start + u32::RAW_BYTE_LEN;
1243 start..end
1244 }
1245
1246 pub fn groups_byte_range(&self) -> Range<usize> {
1247 let num_groups = self.num_groups();
1248 let start = self.num_groups_byte_range().end;
1249 let end = start
1250 + (transforms::to_usize(num_groups)).saturating_mul(SequentialMapGroup::RAW_BYTE_LEN);
1251 start..end
1252 }
1253}
1254
1255impl Format<u16> for Cmap13<'_> {
1256 const FORMAT: u16 = 13;
1257}
1258
1259impl<'a> MinByteRange<'a> for Cmap13<'a> {
1260 fn min_byte_range(&self) -> Range<usize> {
1261 0..self.groups_byte_range().end
1262 }
1263 fn min_table_bytes(&self) -> &'a [u8] {
1264 let range = self.min_byte_range();
1265 self.data.as_bytes().get(range).unwrap_or_default()
1266 }
1267}
1268
1269impl ReadArgs for Cmap13<'_> {
1270 type Args = ();
1271}
1272
1273impl<'a> FontRead<'a> for Cmap13<'a> {
1274 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1275 #[allow(clippy::absurd_extreme_comparisons)]
1276 if data.len() < Self::MIN_SIZE {
1277 return Err(ReadError::OutOfBounds);
1278 }
1279 Ok(Self { data })
1280 }
1281}
1282
1283#[derive(Clone)]
1285pub struct Cmap13<'a> {
1286 data: FontData<'a>,
1287}
1288
1289#[allow(clippy::needless_lifetimes)]
1290impl<'a> Cmap13<'a> {
1291 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1292 + u16::RAW_BYTE_LEN
1293 + u32::RAW_BYTE_LEN
1294 + u32::RAW_BYTE_LEN
1295 + u32::RAW_BYTE_LEN);
1296 basic_table_impls!(impl_the_methods);
1297
1298 pub fn format(&self) -> u16 {
1300 let range = self.format_byte_range();
1301 self.data.read_at(range.start).ok().unwrap()
1302 }
1303
1304 pub fn length(&self) -> u32 {
1306 let range = self.length_byte_range();
1307 self.data.read_at(range.start).ok().unwrap()
1308 }
1309
1310 pub fn language(&self) -> u32 {
1313 let range = self.language_byte_range();
1314 self.data.read_at(range.start).ok().unwrap()
1315 }
1316
1317 pub fn num_groups(&self) -> u32 {
1319 let range = self.num_groups_byte_range();
1320 self.data.read_at(range.start).ok().unwrap()
1321 }
1322
1323 pub fn groups(&self) -> &'a [ConstantMapGroup] {
1325 let range = self.groups_byte_range();
1326 self.data.read_array(range).ok().unwrap_or_default()
1327 }
1328
1329 pub fn format_byte_range(&self) -> Range<usize> {
1330 let start = 0;
1331 let end = start + u16::RAW_BYTE_LEN;
1332 start..end
1333 }
1334
1335 pub fn reserved_byte_range(&self) -> Range<usize> {
1336 let start = self.format_byte_range().end;
1337 let end = start + u16::RAW_BYTE_LEN;
1338 start..end
1339 }
1340
1341 pub fn length_byte_range(&self) -> Range<usize> {
1342 let start = self.reserved_byte_range().end;
1343 let end = start + u32::RAW_BYTE_LEN;
1344 start..end
1345 }
1346
1347 pub fn language_byte_range(&self) -> Range<usize> {
1348 let start = self.length_byte_range().end;
1349 let end = start + u32::RAW_BYTE_LEN;
1350 start..end
1351 }
1352
1353 pub fn num_groups_byte_range(&self) -> Range<usize> {
1354 let start = self.language_byte_range().end;
1355 let end = start + u32::RAW_BYTE_LEN;
1356 start..end
1357 }
1358
1359 pub fn groups_byte_range(&self) -> Range<usize> {
1360 let num_groups = self.num_groups();
1361 let start = self.num_groups_byte_range().end;
1362 let end = start
1363 + (transforms::to_usize(num_groups)).saturating_mul(ConstantMapGroup::RAW_BYTE_LEN);
1364 start..end
1365 }
1366}
1367
1368#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1370#[repr(C)]
1371#[repr(packed)]
1372pub struct ConstantMapGroup {
1373 pub start_char_code: BigEndian<u32>,
1375 pub end_char_code: BigEndian<u32>,
1377 pub glyph_id: BigEndian<u32>,
1380}
1381
1382impl ConstantMapGroup {
1383 pub fn start_char_code(&self) -> u32 {
1385 self.start_char_code.get()
1386 }
1387
1388 pub fn end_char_code(&self) -> u32 {
1390 self.end_char_code.get()
1391 }
1392
1393 pub fn glyph_id(&self) -> u32 {
1396 self.glyph_id.get()
1397 }
1398}
1399
1400impl FixedSize for ConstantMapGroup {
1401 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1402}
1403
1404impl Format<u16> for Cmap14<'_> {
1405 const FORMAT: u16 = 14;
1406}
1407
1408impl<'a> MinByteRange<'a> for Cmap14<'a> {
1409 fn min_byte_range(&self) -> Range<usize> {
1410 0..self.var_selector_byte_range().end
1411 }
1412 fn min_table_bytes(&self) -> &'a [u8] {
1413 let range = self.min_byte_range();
1414 self.data.as_bytes().get(range).unwrap_or_default()
1415 }
1416}
1417
1418impl ReadArgs for Cmap14<'_> {
1419 type Args = ();
1420}
1421
1422impl<'a> FontRead<'a> for Cmap14<'a> {
1423 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1424 #[allow(clippy::absurd_extreme_comparisons)]
1425 if data.len() < Self::MIN_SIZE {
1426 return Err(ReadError::OutOfBounds);
1427 }
1428 Ok(Self { data })
1429 }
1430}
1431
1432#[derive(Clone)]
1434pub struct Cmap14<'a> {
1435 data: FontData<'a>,
1436}
1437
1438#[allow(clippy::needless_lifetimes)]
1439impl<'a> Cmap14<'a> {
1440 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1441 basic_table_impls!(impl_the_methods);
1442
1443 pub fn format(&self) -> u16 {
1445 let range = self.format_byte_range();
1446 self.data.read_at(range.start).ok().unwrap()
1447 }
1448
1449 pub fn length(&self) -> u32 {
1451 let range = self.length_byte_range();
1452 self.data.read_at(range.start).ok().unwrap()
1453 }
1454
1455 pub fn num_var_selector_records(&self) -> u32 {
1457 let range = self.num_var_selector_records_byte_range();
1458 self.data.read_at(range.start).ok().unwrap()
1459 }
1460
1461 pub fn var_selector(&self) -> &'a [VariationSelector] {
1463 let range = self.var_selector_byte_range();
1464 self.data.read_array(range).ok().unwrap_or_default()
1465 }
1466
1467 pub fn format_byte_range(&self) -> Range<usize> {
1468 let start = 0;
1469 let end = start + u16::RAW_BYTE_LEN;
1470 start..end
1471 }
1472
1473 pub fn length_byte_range(&self) -> Range<usize> {
1474 let start = self.format_byte_range().end;
1475 let end = start + u32::RAW_BYTE_LEN;
1476 start..end
1477 }
1478
1479 pub fn num_var_selector_records_byte_range(&self) -> Range<usize> {
1480 let start = self.length_byte_range().end;
1481 let end = start + u32::RAW_BYTE_LEN;
1482 start..end
1483 }
1484
1485 pub fn var_selector_byte_range(&self) -> Range<usize> {
1486 let num_var_selector_records = self.num_var_selector_records();
1487 let start = self.num_var_selector_records_byte_range().end;
1488 let end = start
1489 + (transforms::to_usize(num_var_selector_records))
1490 .saturating_mul(VariationSelector::RAW_BYTE_LEN);
1491 start..end
1492 }
1493}
1494
1495#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1497#[repr(C)]
1498#[repr(packed)]
1499pub struct VariationSelector {
1500 pub var_selector: BigEndian<Uint24>,
1502 pub default_uvs_offset: BigEndian<Nullable<Offset32>>,
1505 pub non_default_uvs_offset: BigEndian<Nullable<Offset32>>,
1508}
1509
1510impl VariationSelector {
1511 pub fn var_selector(&self) -> Uint24 {
1513 self.var_selector.get()
1514 }
1515
1516 pub fn default_uvs_offset(&self) -> Nullable<Offset32> {
1519 self.default_uvs_offset.get()
1520 }
1521
1522 pub fn default_uvs<'a>(&self, data: FontData<'a>) -> Option<Result<DefaultUvs<'a>, ReadError>> {
1528 self.default_uvs_offset().resolve(data)
1529 }
1530
1531 pub fn non_default_uvs_offset(&self) -> Nullable<Offset32> {
1534 self.non_default_uvs_offset.get()
1535 }
1536
1537 pub fn non_default_uvs<'a>(
1543 &self,
1544 data: FontData<'a>,
1545 ) -> Option<Result<NonDefaultUvs<'a>, ReadError>> {
1546 self.non_default_uvs_offset().resolve(data)
1547 }
1548}
1549
1550impl FixedSize for VariationSelector {
1551 const RAW_BYTE_LEN: usize =
1552 Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
1553}
1554
1555impl<'a> MinByteRange<'a> for DefaultUvs<'a> {
1556 fn min_byte_range(&self) -> Range<usize> {
1557 0..self.ranges_byte_range().end
1558 }
1559 fn min_table_bytes(&self) -> &'a [u8] {
1560 let range = self.min_byte_range();
1561 self.data.as_bytes().get(range).unwrap_or_default()
1562 }
1563}
1564
1565impl ReadArgs for DefaultUvs<'_> {
1566 type Args = ();
1567}
1568
1569impl<'a> FontRead<'a> for DefaultUvs<'a> {
1570 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1571 #[allow(clippy::absurd_extreme_comparisons)]
1572 if data.len() < Self::MIN_SIZE {
1573 return Err(ReadError::OutOfBounds);
1574 }
1575 Ok(Self { data })
1576 }
1577}
1578
1579#[derive(Clone)]
1581pub struct DefaultUvs<'a> {
1582 data: FontData<'a>,
1583}
1584
1585#[allow(clippy::needless_lifetimes)]
1586impl<'a> DefaultUvs<'a> {
1587 pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
1588 basic_table_impls!(impl_the_methods);
1589
1590 pub fn num_unicode_value_ranges(&self) -> u32 {
1592 let range = self.num_unicode_value_ranges_byte_range();
1593 self.data.read_at(range.start).ok().unwrap()
1594 }
1595
1596 pub fn ranges(&self) -> &'a [UnicodeRange] {
1598 let range = self.ranges_byte_range();
1599 self.data.read_array(range).ok().unwrap_or_default()
1600 }
1601
1602 pub fn num_unicode_value_ranges_byte_range(&self) -> Range<usize> {
1603 let start = 0;
1604 let end = start + u32::RAW_BYTE_LEN;
1605 start..end
1606 }
1607
1608 pub fn ranges_byte_range(&self) -> Range<usize> {
1609 let num_unicode_value_ranges = self.num_unicode_value_ranges();
1610 let start = self.num_unicode_value_ranges_byte_range().end;
1611 let end = start
1612 + (transforms::to_usize(num_unicode_value_ranges))
1613 .saturating_mul(UnicodeRange::RAW_BYTE_LEN);
1614 start..end
1615 }
1616}
1617
1618const _: () = assert!(FontData::default_data_long_enough(DefaultUvs::MIN_SIZE));
1619
1620impl Default for DefaultUvs<'_> {
1621 fn default() -> Self {
1622 Self {
1623 data: FontData::default_table_data(),
1624 }
1625 }
1626}
1627
1628impl<'a> MinByteRange<'a> for NonDefaultUvs<'a> {
1629 fn min_byte_range(&self) -> Range<usize> {
1630 0..self.uvs_mapping_byte_range().end
1631 }
1632 fn min_table_bytes(&self) -> &'a [u8] {
1633 let range = self.min_byte_range();
1634 self.data.as_bytes().get(range).unwrap_or_default()
1635 }
1636}
1637
1638impl ReadArgs for NonDefaultUvs<'_> {
1639 type Args = ();
1640}
1641
1642impl<'a> FontRead<'a> for NonDefaultUvs<'a> {
1643 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1644 #[allow(clippy::absurd_extreme_comparisons)]
1645 if data.len() < Self::MIN_SIZE {
1646 return Err(ReadError::OutOfBounds);
1647 }
1648 Ok(Self { data })
1649 }
1650}
1651
1652#[derive(Clone)]
1654pub struct NonDefaultUvs<'a> {
1655 data: FontData<'a>,
1656}
1657
1658#[allow(clippy::needless_lifetimes)]
1659impl<'a> NonDefaultUvs<'a> {
1660 pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
1661 basic_table_impls!(impl_the_methods);
1662
1663 pub fn num_uvs_mappings(&self) -> u32 {
1664 let range = self.num_uvs_mappings_byte_range();
1665 self.data.read_at(range.start).ok().unwrap()
1666 }
1667
1668 pub fn uvs_mapping(&self) -> &'a [UvsMapping] {
1669 let range = self.uvs_mapping_byte_range();
1670 self.data.read_array(range).ok().unwrap_or_default()
1671 }
1672
1673 pub fn num_uvs_mappings_byte_range(&self) -> Range<usize> {
1674 let start = 0;
1675 let end = start + u32::RAW_BYTE_LEN;
1676 start..end
1677 }
1678
1679 pub fn uvs_mapping_byte_range(&self) -> Range<usize> {
1680 let num_uvs_mappings = self.num_uvs_mappings();
1681 let start = self.num_uvs_mappings_byte_range().end;
1682 let end = start
1683 + (transforms::to_usize(num_uvs_mappings)).saturating_mul(UvsMapping::RAW_BYTE_LEN);
1684 start..end
1685 }
1686}
1687
1688const _: () = assert!(FontData::default_data_long_enough(NonDefaultUvs::MIN_SIZE));
1689
1690impl Default for NonDefaultUvs<'_> {
1691 fn default() -> Self {
1692 Self {
1693 data: FontData::default_table_data(),
1694 }
1695 }
1696}
1697
1698#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1700#[repr(C)]
1701#[repr(packed)]
1702pub struct UvsMapping {
1703 pub unicode_value: BigEndian<Uint24>,
1705 pub glyph_id: BigEndian<u16>,
1707}
1708
1709impl UvsMapping {
1710 pub fn unicode_value(&self) -> Uint24 {
1712 self.unicode_value.get()
1713 }
1714
1715 pub fn glyph_id(&self) -> u16 {
1717 self.glyph_id.get()
1718 }
1719}
1720
1721impl FixedSize for UvsMapping {
1722 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1723}
1724
1725#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1727#[repr(C)]
1728#[repr(packed)]
1729pub struct UnicodeRange {
1730 pub start_unicode_value: BigEndian<Uint24>,
1732 pub additional_count: u8,
1734}
1735
1736impl UnicodeRange {
1737 pub fn start_unicode_value(&self) -> Uint24 {
1739 self.start_unicode_value.get()
1740 }
1741
1742 pub fn additional_count(&self) -> u8 {
1744 self.additional_count
1745 }
1746}
1747
1748impl FixedSize for UnicodeRange {
1749 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
1750}