1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct CmapMarker {
12 encoding_records_byte_len: usize,
13}
14
15impl CmapMarker {
16 pub fn version_byte_range(&self) -> Range<usize> {
17 let start = 0;
18 start..start + u16::RAW_BYTE_LEN
19 }
20
21 pub fn num_tables_byte_range(&self) -> Range<usize> {
22 let start = self.version_byte_range().end;
23 start..start + u16::RAW_BYTE_LEN
24 }
25
26 pub fn encoding_records_byte_range(&self) -> Range<usize> {
27 let start = self.num_tables_byte_range().end;
28 start..start + self.encoding_records_byte_len
29 }
30}
31
32impl MinByteRange for CmapMarker {
33 fn min_byte_range(&self) -> Range<usize> {
34 0..self.encoding_records_byte_range().end
35 }
36}
37
38impl TopLevelTable for Cmap<'_> {
39 const TAG: Tag = Tag::new(b"cmap");
41}
42
43impl<'a> FontRead<'a> for Cmap<'a> {
44 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
45 let mut cursor = data.cursor();
46 cursor.advance::<u16>();
47 let num_tables: u16 = cursor.read()?;
48 let encoding_records_byte_len = (num_tables as usize)
49 .checked_mul(EncodingRecord::RAW_BYTE_LEN)
50 .ok_or(ReadError::OutOfBounds)?;
51 cursor.advance_by(encoding_records_byte_len);
52 cursor.finish(CmapMarker {
53 encoding_records_byte_len,
54 })
55 }
56}
57
58pub type Cmap<'a> = TableRef<'a, CmapMarker>;
60
61#[allow(clippy::needless_lifetimes)]
62impl<'a> Cmap<'a> {
63 pub fn version(&self) -> u16 {
65 let range = self.shape.version_byte_range();
66 self.data.read_at(range.start).unwrap()
67 }
68
69 pub fn num_tables(&self) -> u16 {
71 let range = self.shape.num_tables_byte_range();
72 self.data.read_at(range.start).unwrap()
73 }
74
75 pub fn encoding_records(&self) -> &'a [EncodingRecord] {
76 let range = self.shape.encoding_records_byte_range();
77 self.data.read_array(range).unwrap()
78 }
79}
80
81#[cfg(feature = "experimental_traverse")]
82impl<'a> SomeTable<'a> for Cmap<'a> {
83 fn type_name(&self) -> &str {
84 "Cmap"
85 }
86 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
87 match idx {
88 0usize => Some(Field::new("version", self.version())),
89 1usize => Some(Field::new("num_tables", self.num_tables())),
90 2usize => Some(Field::new(
91 "encoding_records",
92 traversal::FieldType::array_of_records(
93 stringify!(EncodingRecord),
94 self.encoding_records(),
95 self.offset_data(),
96 ),
97 )),
98 _ => None,
99 }
100 }
101}
102
103#[cfg(feature = "experimental_traverse")]
104#[allow(clippy::needless_lifetimes)]
105impl<'a> std::fmt::Debug for Cmap<'a> {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 (self as &dyn SomeTable<'a>).fmt(f)
108 }
109}
110
111#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
113#[repr(C)]
114#[repr(packed)]
115pub struct EncodingRecord {
116 pub platform_id: BigEndian<PlatformId>,
118 pub encoding_id: BigEndian<u16>,
120 pub subtable_offset: BigEndian<Offset32>,
123}
124
125impl EncodingRecord {
126 pub fn platform_id(&self) -> PlatformId {
128 self.platform_id.get()
129 }
130
131 pub fn encoding_id(&self) -> u16 {
133 self.encoding_id.get()
134 }
135
136 pub fn subtable_offset(&self) -> Offset32 {
139 self.subtable_offset.get()
140 }
141
142 pub fn subtable<'a>(&self, data: FontData<'a>) -> Result<CmapSubtable<'a>, ReadError> {
148 self.subtable_offset().resolve(data)
149 }
150}
151
152impl FixedSize for EncodingRecord {
153 const RAW_BYTE_LEN: usize =
154 PlatformId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
155}
156
157#[cfg(feature = "experimental_traverse")]
158impl<'a> SomeRecord<'a> for EncodingRecord {
159 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
160 RecordResolver {
161 name: "EncodingRecord",
162 get_field: Box::new(move |idx, _data| match idx {
163 0usize => Some(Field::new("platform_id", self.platform_id())),
164 1usize => Some(Field::new("encoding_id", self.encoding_id())),
165 2usize => Some(Field::new(
166 "subtable_offset",
167 FieldType::offset(self.subtable_offset(), self.subtable(_data)),
168 )),
169 _ => None,
170 }),
171 data,
172 }
173 }
174}
175
176#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
178#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
179#[repr(u16)]
180#[allow(clippy::manual_non_exhaustive)]
181pub enum PlatformId {
182 #[default]
183 Unicode = 0,
184 Macintosh = 1,
185 ISO = 2,
186 Windows = 3,
187 Custom = 4,
188 #[doc(hidden)]
189 Unknown,
191}
192
193impl PlatformId {
194 pub fn new(raw: u16) -> Self {
198 match raw {
199 0 => Self::Unicode,
200 1 => Self::Macintosh,
201 2 => Self::ISO,
202 3 => Self::Windows,
203 4 => Self::Custom,
204 _ => Self::Unknown,
205 }
206 }
207}
208
209impl font_types::Scalar for PlatformId {
210 type Raw = <u16 as font_types::Scalar>::Raw;
211 fn to_raw(self) -> Self::Raw {
212 (self as u16).to_raw()
213 }
214 fn from_raw(raw: Self::Raw) -> Self {
215 let t = <u16>::from_raw(raw);
216 Self::new(t)
217 }
218}
219
220#[cfg(feature = "experimental_traverse")]
221impl<'a> From<PlatformId> for FieldType<'a> {
222 fn from(src: PlatformId) -> FieldType<'a> {
223 (src as u16).into()
224 }
225}
226
227#[derive(Clone)]
229pub enum CmapSubtable<'a> {
230 Format0(Cmap0<'a>),
231 Format2(Cmap2<'a>),
232 Format4(Cmap4<'a>),
233 Format6(Cmap6<'a>),
234 Format8(Cmap8<'a>),
235 Format10(Cmap10<'a>),
236 Format12(Cmap12<'a>),
237 Format13(Cmap13<'a>),
238 Format14(Cmap14<'a>),
239}
240
241impl<'a> CmapSubtable<'a> {
242 pub fn offset_data(&self) -> FontData<'a> {
244 match self {
245 Self::Format0(item) => item.offset_data(),
246 Self::Format2(item) => item.offset_data(),
247 Self::Format4(item) => item.offset_data(),
248 Self::Format6(item) => item.offset_data(),
249 Self::Format8(item) => item.offset_data(),
250 Self::Format10(item) => item.offset_data(),
251 Self::Format12(item) => item.offset_data(),
252 Self::Format13(item) => item.offset_data(),
253 Self::Format14(item) => item.offset_data(),
254 }
255 }
256
257 pub fn format(&self) -> u16 {
259 match self {
260 Self::Format0(item) => item.format(),
261 Self::Format2(item) => item.format(),
262 Self::Format4(item) => item.format(),
263 Self::Format6(item) => item.format(),
264 Self::Format8(item) => item.format(),
265 Self::Format10(item) => item.format(),
266 Self::Format12(item) => item.format(),
267 Self::Format13(item) => item.format(),
268 Self::Format14(item) => item.format(),
269 }
270 }
271}
272
273impl<'a> FontRead<'a> for CmapSubtable<'a> {
274 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
275 let format: u16 = data.read_at(0usize)?;
276 match format {
277 Cmap0Marker::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
278 Cmap2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
279 Cmap4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
280 Cmap6Marker::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
281 Cmap8Marker::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
282 Cmap10Marker::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
283 Cmap12Marker::FORMAT => Ok(Self::Format12(FontRead::read(data)?)),
284 Cmap13Marker::FORMAT => Ok(Self::Format13(FontRead::read(data)?)),
285 Cmap14Marker::FORMAT => Ok(Self::Format14(FontRead::read(data)?)),
286 other => Err(ReadError::InvalidFormat(other.into())),
287 }
288 }
289}
290
291impl MinByteRange for CmapSubtable<'_> {
292 fn min_byte_range(&self) -> Range<usize> {
293 match self {
294 Self::Format0(item) => item.min_byte_range(),
295 Self::Format2(item) => item.min_byte_range(),
296 Self::Format4(item) => item.min_byte_range(),
297 Self::Format6(item) => item.min_byte_range(),
298 Self::Format8(item) => item.min_byte_range(),
299 Self::Format10(item) => item.min_byte_range(),
300 Self::Format12(item) => item.min_byte_range(),
301 Self::Format13(item) => item.min_byte_range(),
302 Self::Format14(item) => item.min_byte_range(),
303 }
304 }
305}
306
307#[cfg(feature = "experimental_traverse")]
308impl<'a> CmapSubtable<'a> {
309 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
310 match self {
311 Self::Format0(table) => table,
312 Self::Format2(table) => table,
313 Self::Format4(table) => table,
314 Self::Format6(table) => table,
315 Self::Format8(table) => table,
316 Self::Format10(table) => table,
317 Self::Format12(table) => table,
318 Self::Format13(table) => table,
319 Self::Format14(table) => table,
320 }
321 }
322}
323
324#[cfg(feature = "experimental_traverse")]
325impl std::fmt::Debug for CmapSubtable<'_> {
326 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
327 self.dyn_inner().fmt(f)
328 }
329}
330
331#[cfg(feature = "experimental_traverse")]
332impl<'a> SomeTable<'a> for CmapSubtable<'a> {
333 fn type_name(&self) -> &str {
334 self.dyn_inner().type_name()
335 }
336 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
337 self.dyn_inner().get_field(idx)
338 }
339}
340
341impl Format<u16> for Cmap0Marker {
342 const FORMAT: u16 = 0;
343}
344
345#[derive(Debug, Clone, Copy)]
347#[doc(hidden)]
348pub struct Cmap0Marker {
349 glyph_id_array_byte_len: usize,
350}
351
352impl Cmap0Marker {
353 pub fn format_byte_range(&self) -> Range<usize> {
354 let start = 0;
355 start..start + u16::RAW_BYTE_LEN
356 }
357
358 pub fn length_byte_range(&self) -> Range<usize> {
359 let start = self.format_byte_range().end;
360 start..start + u16::RAW_BYTE_LEN
361 }
362
363 pub fn language_byte_range(&self) -> Range<usize> {
364 let start = self.length_byte_range().end;
365 start..start + u16::RAW_BYTE_LEN
366 }
367
368 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
369 let start = self.language_byte_range().end;
370 start..start + self.glyph_id_array_byte_len
371 }
372}
373
374impl MinByteRange for Cmap0Marker {
375 fn min_byte_range(&self) -> Range<usize> {
376 0..self.glyph_id_array_byte_range().end
377 }
378}
379
380impl<'a> FontRead<'a> for Cmap0<'a> {
381 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
382 let mut cursor = data.cursor();
383 cursor.advance::<u16>();
384 cursor.advance::<u16>();
385 cursor.advance::<u16>();
386 let glyph_id_array_byte_len = (256_usize)
387 .checked_mul(u8::RAW_BYTE_LEN)
388 .ok_or(ReadError::OutOfBounds)?;
389 cursor.advance_by(glyph_id_array_byte_len);
390 cursor.finish(Cmap0Marker {
391 glyph_id_array_byte_len,
392 })
393 }
394}
395
396pub type Cmap0<'a> = TableRef<'a, Cmap0Marker>;
398
399#[allow(clippy::needless_lifetimes)]
400impl<'a> Cmap0<'a> {
401 pub fn format(&self) -> u16 {
403 let range = self.shape.format_byte_range();
404 self.data.read_at(range.start).unwrap()
405 }
406
407 pub fn length(&self) -> u16 {
409 let range = self.shape.length_byte_range();
410 self.data.read_at(range.start).unwrap()
411 }
412
413 pub fn language(&self) -> u16 {
416 let range = self.shape.language_byte_range();
417 self.data.read_at(range.start).unwrap()
418 }
419
420 pub fn glyph_id_array(&self) -> &'a [u8] {
422 let range = self.shape.glyph_id_array_byte_range();
423 self.data.read_array(range).unwrap()
424 }
425}
426
427#[cfg(feature = "experimental_traverse")]
428impl<'a> SomeTable<'a> for Cmap0<'a> {
429 fn type_name(&self) -> &str {
430 "Cmap0"
431 }
432 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
433 match idx {
434 0usize => Some(Field::new("format", self.format())),
435 1usize => Some(Field::new("length", self.length())),
436 2usize => Some(Field::new("language", self.language())),
437 3usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
438 _ => None,
439 }
440 }
441}
442
443#[cfg(feature = "experimental_traverse")]
444#[allow(clippy::needless_lifetimes)]
445impl<'a> std::fmt::Debug for Cmap0<'a> {
446 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
447 (self as &dyn SomeTable<'a>).fmt(f)
448 }
449}
450
451impl Format<u16> for Cmap2Marker {
452 const FORMAT: u16 = 2;
453}
454
455#[derive(Debug, Clone, Copy)]
457#[doc(hidden)]
458pub struct Cmap2Marker {
459 sub_header_keys_byte_len: usize,
460}
461
462impl Cmap2Marker {
463 pub fn format_byte_range(&self) -> Range<usize> {
464 let start = 0;
465 start..start + u16::RAW_BYTE_LEN
466 }
467
468 pub fn length_byte_range(&self) -> Range<usize> {
469 let start = self.format_byte_range().end;
470 start..start + u16::RAW_BYTE_LEN
471 }
472
473 pub fn language_byte_range(&self) -> Range<usize> {
474 let start = self.length_byte_range().end;
475 start..start + u16::RAW_BYTE_LEN
476 }
477
478 pub fn sub_header_keys_byte_range(&self) -> Range<usize> {
479 let start = self.language_byte_range().end;
480 start..start + self.sub_header_keys_byte_len
481 }
482}
483
484impl MinByteRange for Cmap2Marker {
485 fn min_byte_range(&self) -> Range<usize> {
486 0..self.sub_header_keys_byte_range().end
487 }
488}
489
490impl<'a> FontRead<'a> for Cmap2<'a> {
491 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
492 let mut cursor = data.cursor();
493 cursor.advance::<u16>();
494 cursor.advance::<u16>();
495 cursor.advance::<u16>();
496 let sub_header_keys_byte_len = (256_usize)
497 .checked_mul(u16::RAW_BYTE_LEN)
498 .ok_or(ReadError::OutOfBounds)?;
499 cursor.advance_by(sub_header_keys_byte_len);
500 cursor.finish(Cmap2Marker {
501 sub_header_keys_byte_len,
502 })
503 }
504}
505
506pub type Cmap2<'a> = TableRef<'a, Cmap2Marker>;
508
509#[allow(clippy::needless_lifetimes)]
510impl<'a> Cmap2<'a> {
511 pub fn format(&self) -> u16 {
513 let range = self.shape.format_byte_range();
514 self.data.read_at(range.start).unwrap()
515 }
516
517 pub fn length(&self) -> u16 {
519 let range = self.shape.length_byte_range();
520 self.data.read_at(range.start).unwrap()
521 }
522
523 pub fn language(&self) -> u16 {
526 let range = self.shape.language_byte_range();
527 self.data.read_at(range.start).unwrap()
528 }
529
530 pub fn sub_header_keys(&self) -> &'a [BigEndian<u16>] {
533 let range = self.shape.sub_header_keys_byte_range();
534 self.data.read_array(range).unwrap()
535 }
536}
537
538#[cfg(feature = "experimental_traverse")]
539impl<'a> SomeTable<'a> for Cmap2<'a> {
540 fn type_name(&self) -> &str {
541 "Cmap2"
542 }
543 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
544 match idx {
545 0usize => Some(Field::new("format", self.format())),
546 1usize => Some(Field::new("length", self.length())),
547 2usize => Some(Field::new("language", self.language())),
548 3usize => Some(Field::new("sub_header_keys", self.sub_header_keys())),
549 _ => None,
550 }
551 }
552}
553
554#[cfg(feature = "experimental_traverse")]
555#[allow(clippy::needless_lifetimes)]
556impl<'a> std::fmt::Debug for Cmap2<'a> {
557 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
558 (self as &dyn SomeTable<'a>).fmt(f)
559 }
560}
561
562#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
564#[repr(C)]
565#[repr(packed)]
566pub struct SubHeader {
567 pub first_code: BigEndian<u16>,
569 pub entry_count: BigEndian<u16>,
571 pub id_delta: BigEndian<i16>,
573 pub id_range_offset: BigEndian<u16>,
575}
576
577impl SubHeader {
578 pub fn first_code(&self) -> u16 {
580 self.first_code.get()
581 }
582
583 pub fn entry_count(&self) -> u16 {
585 self.entry_count.get()
586 }
587
588 pub fn id_delta(&self) -> i16 {
590 self.id_delta.get()
591 }
592
593 pub fn id_range_offset(&self) -> u16 {
595 self.id_range_offset.get()
596 }
597}
598
599impl FixedSize for SubHeader {
600 const RAW_BYTE_LEN: usize =
601 u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
602}
603
604#[cfg(feature = "experimental_traverse")]
605impl<'a> SomeRecord<'a> for SubHeader {
606 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
607 RecordResolver {
608 name: "SubHeader",
609 get_field: Box::new(move |idx, _data| match idx {
610 0usize => Some(Field::new("first_code", self.first_code())),
611 1usize => Some(Field::new("entry_count", self.entry_count())),
612 2usize => Some(Field::new("id_delta", self.id_delta())),
613 3usize => Some(Field::new("id_range_offset", self.id_range_offset())),
614 _ => None,
615 }),
616 data,
617 }
618 }
619}
620
621impl Format<u16> for Cmap4Marker {
622 const FORMAT: u16 = 4;
623}
624
625#[derive(Debug, Clone, Copy)]
627#[doc(hidden)]
628pub struct Cmap4Marker {
629 end_code_byte_len: usize,
630 start_code_byte_len: usize,
631 id_delta_byte_len: usize,
632 id_range_offsets_byte_len: usize,
633 glyph_id_array_byte_len: usize,
634}
635
636impl Cmap4Marker {
637 pub fn format_byte_range(&self) -> Range<usize> {
638 let start = 0;
639 start..start + u16::RAW_BYTE_LEN
640 }
641
642 pub fn length_byte_range(&self) -> Range<usize> {
643 let start = self.format_byte_range().end;
644 start..start + u16::RAW_BYTE_LEN
645 }
646
647 pub fn language_byte_range(&self) -> Range<usize> {
648 let start = self.length_byte_range().end;
649 start..start + u16::RAW_BYTE_LEN
650 }
651
652 pub fn seg_count_x2_byte_range(&self) -> Range<usize> {
653 let start = self.language_byte_range().end;
654 start..start + u16::RAW_BYTE_LEN
655 }
656
657 pub fn search_range_byte_range(&self) -> Range<usize> {
658 let start = self.seg_count_x2_byte_range().end;
659 start..start + u16::RAW_BYTE_LEN
660 }
661
662 pub fn entry_selector_byte_range(&self) -> Range<usize> {
663 let start = self.search_range_byte_range().end;
664 start..start + u16::RAW_BYTE_LEN
665 }
666
667 pub fn range_shift_byte_range(&self) -> Range<usize> {
668 let start = self.entry_selector_byte_range().end;
669 start..start + u16::RAW_BYTE_LEN
670 }
671
672 pub fn end_code_byte_range(&self) -> Range<usize> {
673 let start = self.range_shift_byte_range().end;
674 start..start + self.end_code_byte_len
675 }
676
677 pub fn reserved_pad_byte_range(&self) -> Range<usize> {
678 let start = self.end_code_byte_range().end;
679 start..start + u16::RAW_BYTE_LEN
680 }
681
682 pub fn start_code_byte_range(&self) -> Range<usize> {
683 let start = self.reserved_pad_byte_range().end;
684 start..start + self.start_code_byte_len
685 }
686
687 pub fn id_delta_byte_range(&self) -> Range<usize> {
688 let start = self.start_code_byte_range().end;
689 start..start + self.id_delta_byte_len
690 }
691
692 pub fn id_range_offsets_byte_range(&self) -> Range<usize> {
693 let start = self.id_delta_byte_range().end;
694 start..start + self.id_range_offsets_byte_len
695 }
696
697 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
698 let start = self.id_range_offsets_byte_range().end;
699 start..start + self.glyph_id_array_byte_len
700 }
701}
702
703impl MinByteRange for Cmap4Marker {
704 fn min_byte_range(&self) -> Range<usize> {
705 0..self.glyph_id_array_byte_range().end
706 }
707}
708
709impl<'a> FontRead<'a> for Cmap4<'a> {
710 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
711 let mut cursor = data.cursor();
712 cursor.advance::<u16>();
713 cursor.advance::<u16>();
714 cursor.advance::<u16>();
715 let seg_count_x2: u16 = cursor.read()?;
716 cursor.advance::<u16>();
717 cursor.advance::<u16>();
718 cursor.advance::<u16>();
719 let end_code_byte_len = (transforms::half(seg_count_x2))
720 .checked_mul(u16::RAW_BYTE_LEN)
721 .ok_or(ReadError::OutOfBounds)?;
722 cursor.advance_by(end_code_byte_len);
723 cursor.advance::<u16>();
724 let start_code_byte_len = (transforms::half(seg_count_x2))
725 .checked_mul(u16::RAW_BYTE_LEN)
726 .ok_or(ReadError::OutOfBounds)?;
727 cursor.advance_by(start_code_byte_len);
728 let id_delta_byte_len = (transforms::half(seg_count_x2))
729 .checked_mul(i16::RAW_BYTE_LEN)
730 .ok_or(ReadError::OutOfBounds)?;
731 cursor.advance_by(id_delta_byte_len);
732 let id_range_offsets_byte_len = (transforms::half(seg_count_x2))
733 .checked_mul(u16::RAW_BYTE_LEN)
734 .ok_or(ReadError::OutOfBounds)?;
735 cursor.advance_by(id_range_offsets_byte_len);
736 let glyph_id_array_byte_len =
737 cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
738 cursor.advance_by(glyph_id_array_byte_len);
739 cursor.finish(Cmap4Marker {
740 end_code_byte_len,
741 start_code_byte_len,
742 id_delta_byte_len,
743 id_range_offsets_byte_len,
744 glyph_id_array_byte_len,
745 })
746 }
747}
748
749pub type Cmap4<'a> = TableRef<'a, Cmap4Marker>;
751
752#[allow(clippy::needless_lifetimes)]
753impl<'a> Cmap4<'a> {
754 pub fn format(&self) -> u16 {
756 let range = self.shape.format_byte_range();
757 self.data.read_at(range.start).unwrap()
758 }
759
760 pub fn length(&self) -> u16 {
762 let range = self.shape.length_byte_range();
763 self.data.read_at(range.start).unwrap()
764 }
765
766 pub fn language(&self) -> u16 {
769 let range = self.shape.language_byte_range();
770 self.data.read_at(range.start).unwrap()
771 }
772
773 pub fn seg_count_x2(&self) -> u16 {
775 let range = self.shape.seg_count_x2_byte_range();
776 self.data.read_at(range.start).unwrap()
777 }
778
779 pub fn search_range(&self) -> u16 {
783 let range = self.shape.search_range_byte_range();
784 self.data.read_at(range.start).unwrap()
785 }
786
787 pub fn entry_selector(&self) -> u16 {
790 let range = self.shape.entry_selector_byte_range();
791 self.data.read_at(range.start).unwrap()
792 }
793
794 pub fn range_shift(&self) -> u16 {
797 let range = self.shape.range_shift_byte_range();
798 self.data.read_at(range.start).unwrap()
799 }
800
801 pub fn end_code(&self) -> &'a [BigEndian<u16>] {
803 let range = self.shape.end_code_byte_range();
804 self.data.read_array(range).unwrap()
805 }
806
807 pub fn start_code(&self) -> &'a [BigEndian<u16>] {
809 let range = self.shape.start_code_byte_range();
810 self.data.read_array(range).unwrap()
811 }
812
813 pub fn id_delta(&self) -> &'a [BigEndian<i16>] {
815 let range = self.shape.id_delta_byte_range();
816 self.data.read_array(range).unwrap()
817 }
818
819 pub fn id_range_offsets(&self) -> &'a [BigEndian<u16>] {
821 let range = self.shape.id_range_offsets_byte_range();
822 self.data.read_array(range).unwrap()
823 }
824
825 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
827 let range = self.shape.glyph_id_array_byte_range();
828 self.data.read_array(range).unwrap()
829 }
830}
831
832#[cfg(feature = "experimental_traverse")]
833impl<'a> SomeTable<'a> for Cmap4<'a> {
834 fn type_name(&self) -> &str {
835 "Cmap4"
836 }
837 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
838 match idx {
839 0usize => Some(Field::new("format", self.format())),
840 1usize => Some(Field::new("length", self.length())),
841 2usize => Some(Field::new("language", self.language())),
842 3usize => Some(Field::new("seg_count_x2", self.seg_count_x2())),
843 4usize => Some(Field::new("search_range", self.search_range())),
844 5usize => Some(Field::new("entry_selector", self.entry_selector())),
845 6usize => Some(Field::new("range_shift", self.range_shift())),
846 7usize => Some(Field::new("end_code", self.end_code())),
847 8usize => Some(Field::new("start_code", self.start_code())),
848 9usize => Some(Field::new("id_delta", self.id_delta())),
849 10usize => Some(Field::new("id_range_offsets", self.id_range_offsets())),
850 11usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
851 _ => None,
852 }
853 }
854}
855
856#[cfg(feature = "experimental_traverse")]
857#[allow(clippy::needless_lifetimes)]
858impl<'a> std::fmt::Debug for Cmap4<'a> {
859 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
860 (self as &dyn SomeTable<'a>).fmt(f)
861 }
862}
863
864impl Format<u16> for Cmap6Marker {
865 const FORMAT: u16 = 6;
866}
867
868#[derive(Debug, Clone, Copy)]
870#[doc(hidden)]
871pub struct Cmap6Marker {
872 glyph_id_array_byte_len: usize,
873}
874
875impl Cmap6Marker {
876 pub fn format_byte_range(&self) -> Range<usize> {
877 let start = 0;
878 start..start + u16::RAW_BYTE_LEN
879 }
880
881 pub fn length_byte_range(&self) -> Range<usize> {
882 let start = self.format_byte_range().end;
883 start..start + u16::RAW_BYTE_LEN
884 }
885
886 pub fn language_byte_range(&self) -> Range<usize> {
887 let start = self.length_byte_range().end;
888 start..start + u16::RAW_BYTE_LEN
889 }
890
891 pub fn first_code_byte_range(&self) -> Range<usize> {
892 let start = self.language_byte_range().end;
893 start..start + u16::RAW_BYTE_LEN
894 }
895
896 pub fn entry_count_byte_range(&self) -> Range<usize> {
897 let start = self.first_code_byte_range().end;
898 start..start + u16::RAW_BYTE_LEN
899 }
900
901 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
902 let start = self.entry_count_byte_range().end;
903 start..start + self.glyph_id_array_byte_len
904 }
905}
906
907impl MinByteRange for Cmap6Marker {
908 fn min_byte_range(&self) -> Range<usize> {
909 0..self.glyph_id_array_byte_range().end
910 }
911}
912
913impl<'a> FontRead<'a> for Cmap6<'a> {
914 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
915 let mut cursor = data.cursor();
916 cursor.advance::<u16>();
917 cursor.advance::<u16>();
918 cursor.advance::<u16>();
919 cursor.advance::<u16>();
920 let entry_count: u16 = cursor.read()?;
921 let glyph_id_array_byte_len = (entry_count as usize)
922 .checked_mul(u16::RAW_BYTE_LEN)
923 .ok_or(ReadError::OutOfBounds)?;
924 cursor.advance_by(glyph_id_array_byte_len);
925 cursor.finish(Cmap6Marker {
926 glyph_id_array_byte_len,
927 })
928 }
929}
930
931pub type Cmap6<'a> = TableRef<'a, Cmap6Marker>;
933
934#[allow(clippy::needless_lifetimes)]
935impl<'a> Cmap6<'a> {
936 pub fn format(&self) -> u16 {
938 let range = self.shape.format_byte_range();
939 self.data.read_at(range.start).unwrap()
940 }
941
942 pub fn length(&self) -> u16 {
944 let range = self.shape.length_byte_range();
945 self.data.read_at(range.start).unwrap()
946 }
947
948 pub fn language(&self) -> u16 {
951 let range = self.shape.language_byte_range();
952 self.data.read_at(range.start).unwrap()
953 }
954
955 pub fn first_code(&self) -> u16 {
957 let range = self.shape.first_code_byte_range();
958 self.data.read_at(range.start).unwrap()
959 }
960
961 pub fn entry_count(&self) -> u16 {
963 let range = self.shape.entry_count_byte_range();
964 self.data.read_at(range.start).unwrap()
965 }
966
967 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
969 let range = self.shape.glyph_id_array_byte_range();
970 self.data.read_array(range).unwrap()
971 }
972}
973
974#[cfg(feature = "experimental_traverse")]
975impl<'a> SomeTable<'a> for Cmap6<'a> {
976 fn type_name(&self) -> &str {
977 "Cmap6"
978 }
979 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
980 match idx {
981 0usize => Some(Field::new("format", self.format())),
982 1usize => Some(Field::new("length", self.length())),
983 2usize => Some(Field::new("language", self.language())),
984 3usize => Some(Field::new("first_code", self.first_code())),
985 4usize => Some(Field::new("entry_count", self.entry_count())),
986 5usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
987 _ => None,
988 }
989 }
990}
991
992#[cfg(feature = "experimental_traverse")]
993#[allow(clippy::needless_lifetimes)]
994impl<'a> std::fmt::Debug for Cmap6<'a> {
995 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
996 (self as &dyn SomeTable<'a>).fmt(f)
997 }
998}
999
1000impl Format<u16> for Cmap8Marker {
1001 const FORMAT: u16 = 8;
1002}
1003
1004#[derive(Debug, Clone, Copy)]
1006#[doc(hidden)]
1007pub struct Cmap8Marker {
1008 is32_byte_len: usize,
1009 groups_byte_len: usize,
1010}
1011
1012impl Cmap8Marker {
1013 pub fn format_byte_range(&self) -> Range<usize> {
1014 let start = 0;
1015 start..start + u16::RAW_BYTE_LEN
1016 }
1017
1018 pub fn reserved_byte_range(&self) -> Range<usize> {
1019 let start = self.format_byte_range().end;
1020 start..start + u16::RAW_BYTE_LEN
1021 }
1022
1023 pub fn length_byte_range(&self) -> Range<usize> {
1024 let start = self.reserved_byte_range().end;
1025 start..start + u32::RAW_BYTE_LEN
1026 }
1027
1028 pub fn language_byte_range(&self) -> Range<usize> {
1029 let start = self.length_byte_range().end;
1030 start..start + u32::RAW_BYTE_LEN
1031 }
1032
1033 pub fn is32_byte_range(&self) -> Range<usize> {
1034 let start = self.language_byte_range().end;
1035 start..start + self.is32_byte_len
1036 }
1037
1038 pub fn num_groups_byte_range(&self) -> Range<usize> {
1039 let start = self.is32_byte_range().end;
1040 start..start + u32::RAW_BYTE_LEN
1041 }
1042
1043 pub fn groups_byte_range(&self) -> Range<usize> {
1044 let start = self.num_groups_byte_range().end;
1045 start..start + self.groups_byte_len
1046 }
1047}
1048
1049impl MinByteRange for Cmap8Marker {
1050 fn min_byte_range(&self) -> Range<usize> {
1051 0..self.groups_byte_range().end
1052 }
1053}
1054
1055impl<'a> FontRead<'a> for Cmap8<'a> {
1056 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1057 let mut cursor = data.cursor();
1058 cursor.advance::<u16>();
1059 cursor.advance::<u16>();
1060 cursor.advance::<u32>();
1061 cursor.advance::<u32>();
1062 let is32_byte_len = (8192_usize)
1063 .checked_mul(u8::RAW_BYTE_LEN)
1064 .ok_or(ReadError::OutOfBounds)?;
1065 cursor.advance_by(is32_byte_len);
1066 let num_groups: u32 = cursor.read()?;
1067 let groups_byte_len = (num_groups as usize)
1068 .checked_mul(SequentialMapGroup::RAW_BYTE_LEN)
1069 .ok_or(ReadError::OutOfBounds)?;
1070 cursor.advance_by(groups_byte_len);
1071 cursor.finish(Cmap8Marker {
1072 is32_byte_len,
1073 groups_byte_len,
1074 })
1075 }
1076}
1077
1078pub type Cmap8<'a> = TableRef<'a, Cmap8Marker>;
1080
1081#[allow(clippy::needless_lifetimes)]
1082impl<'a> Cmap8<'a> {
1083 pub fn format(&self) -> u16 {
1085 let range = self.shape.format_byte_range();
1086 self.data.read_at(range.start).unwrap()
1087 }
1088
1089 pub fn length(&self) -> u32 {
1091 let range = self.shape.length_byte_range();
1092 self.data.read_at(range.start).unwrap()
1093 }
1094
1095 pub fn language(&self) -> u32 {
1098 let range = self.shape.language_byte_range();
1099 self.data.read_at(range.start).unwrap()
1100 }
1101
1102 pub fn is32(&self) -> &'a [u8] {
1106 let range = self.shape.is32_byte_range();
1107 self.data.read_array(range).unwrap()
1108 }
1109
1110 pub fn num_groups(&self) -> u32 {
1112 let range = self.shape.num_groups_byte_range();
1113 self.data.read_at(range.start).unwrap()
1114 }
1115
1116 pub fn groups(&self) -> &'a [SequentialMapGroup] {
1118 let range = self.shape.groups_byte_range();
1119 self.data.read_array(range).unwrap()
1120 }
1121}
1122
1123#[cfg(feature = "experimental_traverse")]
1124impl<'a> SomeTable<'a> for Cmap8<'a> {
1125 fn type_name(&self) -> &str {
1126 "Cmap8"
1127 }
1128 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1129 match idx {
1130 0usize => Some(Field::new("format", self.format())),
1131 1usize => Some(Field::new("length", self.length())),
1132 2usize => Some(Field::new("language", self.language())),
1133 3usize => Some(Field::new("is32", self.is32())),
1134 4usize => Some(Field::new("num_groups", self.num_groups())),
1135 5usize => Some(Field::new(
1136 "groups",
1137 traversal::FieldType::array_of_records(
1138 stringify!(SequentialMapGroup),
1139 self.groups(),
1140 self.offset_data(),
1141 ),
1142 )),
1143 _ => None,
1144 }
1145 }
1146}
1147
1148#[cfg(feature = "experimental_traverse")]
1149#[allow(clippy::needless_lifetimes)]
1150impl<'a> std::fmt::Debug for Cmap8<'a> {
1151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1152 (self as &dyn SomeTable<'a>).fmt(f)
1153 }
1154}
1155
1156#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1158#[repr(C)]
1159#[repr(packed)]
1160pub struct SequentialMapGroup {
1161 pub start_char_code: BigEndian<u32>,
1166 pub end_char_code: BigEndian<u32>,
1169 pub start_glyph_id: BigEndian<u32>,
1171}
1172
1173impl SequentialMapGroup {
1174 pub fn start_char_code(&self) -> u32 {
1179 self.start_char_code.get()
1180 }
1181
1182 pub fn end_char_code(&self) -> u32 {
1185 self.end_char_code.get()
1186 }
1187
1188 pub fn start_glyph_id(&self) -> u32 {
1190 self.start_glyph_id.get()
1191 }
1192}
1193
1194impl FixedSize for SequentialMapGroup {
1195 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1196}
1197
1198#[cfg(feature = "experimental_traverse")]
1199impl<'a> SomeRecord<'a> for SequentialMapGroup {
1200 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1201 RecordResolver {
1202 name: "SequentialMapGroup",
1203 get_field: Box::new(move |idx, _data| match idx {
1204 0usize => Some(Field::new("start_char_code", self.start_char_code())),
1205 1usize => Some(Field::new("end_char_code", self.end_char_code())),
1206 2usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1207 _ => None,
1208 }),
1209 data,
1210 }
1211 }
1212}
1213
1214impl Format<u16> for Cmap10Marker {
1215 const FORMAT: u16 = 10;
1216}
1217
1218#[derive(Debug, Clone, Copy)]
1220#[doc(hidden)]
1221pub struct Cmap10Marker {
1222 glyph_id_array_byte_len: usize,
1223}
1224
1225impl Cmap10Marker {
1226 pub fn format_byte_range(&self) -> Range<usize> {
1227 let start = 0;
1228 start..start + u16::RAW_BYTE_LEN
1229 }
1230
1231 pub fn reserved_byte_range(&self) -> Range<usize> {
1232 let start = self.format_byte_range().end;
1233 start..start + u16::RAW_BYTE_LEN
1234 }
1235
1236 pub fn length_byte_range(&self) -> Range<usize> {
1237 let start = self.reserved_byte_range().end;
1238 start..start + u32::RAW_BYTE_LEN
1239 }
1240
1241 pub fn language_byte_range(&self) -> Range<usize> {
1242 let start = self.length_byte_range().end;
1243 start..start + u32::RAW_BYTE_LEN
1244 }
1245
1246 pub fn start_char_code_byte_range(&self) -> Range<usize> {
1247 let start = self.language_byte_range().end;
1248 start..start + u32::RAW_BYTE_LEN
1249 }
1250
1251 pub fn num_chars_byte_range(&self) -> Range<usize> {
1252 let start = self.start_char_code_byte_range().end;
1253 start..start + u32::RAW_BYTE_LEN
1254 }
1255
1256 pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
1257 let start = self.num_chars_byte_range().end;
1258 start..start + self.glyph_id_array_byte_len
1259 }
1260}
1261
1262impl MinByteRange for Cmap10Marker {
1263 fn min_byte_range(&self) -> Range<usize> {
1264 0..self.glyph_id_array_byte_range().end
1265 }
1266}
1267
1268impl<'a> FontRead<'a> for Cmap10<'a> {
1269 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1270 let mut cursor = data.cursor();
1271 cursor.advance::<u16>();
1272 cursor.advance::<u16>();
1273 cursor.advance::<u32>();
1274 cursor.advance::<u32>();
1275 cursor.advance::<u32>();
1276 let num_chars: u32 = cursor.read()?;
1277 let glyph_id_array_byte_len = (num_chars as usize)
1278 .checked_mul(u16::RAW_BYTE_LEN)
1279 .ok_or(ReadError::OutOfBounds)?;
1280 cursor.advance_by(glyph_id_array_byte_len);
1281 cursor.finish(Cmap10Marker {
1282 glyph_id_array_byte_len,
1283 })
1284 }
1285}
1286
1287pub type Cmap10<'a> = TableRef<'a, Cmap10Marker>;
1289
1290#[allow(clippy::needless_lifetimes)]
1291impl<'a> Cmap10<'a> {
1292 pub fn format(&self) -> u16 {
1294 let range = self.shape.format_byte_range();
1295 self.data.read_at(range.start).unwrap()
1296 }
1297
1298 pub fn length(&self) -> u32 {
1300 let range = self.shape.length_byte_range();
1301 self.data.read_at(range.start).unwrap()
1302 }
1303
1304 pub fn language(&self) -> u32 {
1307 let range = self.shape.language_byte_range();
1308 self.data.read_at(range.start).unwrap()
1309 }
1310
1311 pub fn start_char_code(&self) -> u32 {
1313 let range = self.shape.start_char_code_byte_range();
1314 self.data.read_at(range.start).unwrap()
1315 }
1316
1317 pub fn num_chars(&self) -> u32 {
1319 let range = self.shape.num_chars_byte_range();
1320 self.data.read_at(range.start).unwrap()
1321 }
1322
1323 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
1325 let range = self.shape.glyph_id_array_byte_range();
1326 self.data.read_array(range).unwrap()
1327 }
1328}
1329
1330#[cfg(feature = "experimental_traverse")]
1331impl<'a> SomeTable<'a> for Cmap10<'a> {
1332 fn type_name(&self) -> &str {
1333 "Cmap10"
1334 }
1335 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1336 match idx {
1337 0usize => Some(Field::new("format", self.format())),
1338 1usize => Some(Field::new("length", self.length())),
1339 2usize => Some(Field::new("language", self.language())),
1340 3usize => Some(Field::new("start_char_code", self.start_char_code())),
1341 4usize => Some(Field::new("num_chars", self.num_chars())),
1342 5usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
1343 _ => None,
1344 }
1345 }
1346}
1347
1348#[cfg(feature = "experimental_traverse")]
1349#[allow(clippy::needless_lifetimes)]
1350impl<'a> std::fmt::Debug for Cmap10<'a> {
1351 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1352 (self as &dyn SomeTable<'a>).fmt(f)
1353 }
1354}
1355
1356impl Format<u16> for Cmap12Marker {
1357 const FORMAT: u16 = 12;
1358}
1359
1360#[derive(Debug, Clone, Copy)]
1362#[doc(hidden)]
1363pub struct Cmap12Marker {
1364 groups_byte_len: usize,
1365}
1366
1367impl Cmap12Marker {
1368 pub fn format_byte_range(&self) -> Range<usize> {
1369 let start = 0;
1370 start..start + u16::RAW_BYTE_LEN
1371 }
1372
1373 pub fn reserved_byte_range(&self) -> Range<usize> {
1374 let start = self.format_byte_range().end;
1375 start..start + u16::RAW_BYTE_LEN
1376 }
1377
1378 pub fn length_byte_range(&self) -> Range<usize> {
1379 let start = self.reserved_byte_range().end;
1380 start..start + u32::RAW_BYTE_LEN
1381 }
1382
1383 pub fn language_byte_range(&self) -> Range<usize> {
1384 let start = self.length_byte_range().end;
1385 start..start + u32::RAW_BYTE_LEN
1386 }
1387
1388 pub fn num_groups_byte_range(&self) -> Range<usize> {
1389 let start = self.language_byte_range().end;
1390 start..start + u32::RAW_BYTE_LEN
1391 }
1392
1393 pub fn groups_byte_range(&self) -> Range<usize> {
1394 let start = self.num_groups_byte_range().end;
1395 start..start + self.groups_byte_len
1396 }
1397}
1398
1399impl MinByteRange for Cmap12Marker {
1400 fn min_byte_range(&self) -> Range<usize> {
1401 0..self.groups_byte_range().end
1402 }
1403}
1404
1405impl<'a> FontRead<'a> for Cmap12<'a> {
1406 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1407 let mut cursor = data.cursor();
1408 cursor.advance::<u16>();
1409 cursor.advance::<u16>();
1410 cursor.advance::<u32>();
1411 cursor.advance::<u32>();
1412 let num_groups: u32 = cursor.read()?;
1413 let groups_byte_len = (num_groups as usize)
1414 .checked_mul(SequentialMapGroup::RAW_BYTE_LEN)
1415 .ok_or(ReadError::OutOfBounds)?;
1416 cursor.advance_by(groups_byte_len);
1417 cursor.finish(Cmap12Marker { groups_byte_len })
1418 }
1419}
1420
1421pub type Cmap12<'a> = TableRef<'a, Cmap12Marker>;
1423
1424#[allow(clippy::needless_lifetimes)]
1425impl<'a> Cmap12<'a> {
1426 pub fn format(&self) -> u16 {
1428 let range = self.shape.format_byte_range();
1429 self.data.read_at(range.start).unwrap()
1430 }
1431
1432 pub fn length(&self) -> u32 {
1434 let range = self.shape.length_byte_range();
1435 self.data.read_at(range.start).unwrap()
1436 }
1437
1438 pub fn language(&self) -> u32 {
1441 let range = self.shape.language_byte_range();
1442 self.data.read_at(range.start).unwrap()
1443 }
1444
1445 pub fn num_groups(&self) -> u32 {
1447 let range = self.shape.num_groups_byte_range();
1448 self.data.read_at(range.start).unwrap()
1449 }
1450
1451 pub fn groups(&self) -> &'a [SequentialMapGroup] {
1453 let range = self.shape.groups_byte_range();
1454 self.data.read_array(range).unwrap()
1455 }
1456}
1457
1458#[cfg(feature = "experimental_traverse")]
1459impl<'a> SomeTable<'a> for Cmap12<'a> {
1460 fn type_name(&self) -> &str {
1461 "Cmap12"
1462 }
1463 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1464 match idx {
1465 0usize => Some(Field::new("format", self.format())),
1466 1usize => Some(Field::new("length", self.length())),
1467 2usize => Some(Field::new("language", self.language())),
1468 3usize => Some(Field::new("num_groups", self.num_groups())),
1469 4usize => Some(Field::new(
1470 "groups",
1471 traversal::FieldType::array_of_records(
1472 stringify!(SequentialMapGroup),
1473 self.groups(),
1474 self.offset_data(),
1475 ),
1476 )),
1477 _ => None,
1478 }
1479 }
1480}
1481
1482#[cfg(feature = "experimental_traverse")]
1483#[allow(clippy::needless_lifetimes)]
1484impl<'a> std::fmt::Debug for Cmap12<'a> {
1485 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1486 (self as &dyn SomeTable<'a>).fmt(f)
1487 }
1488}
1489
1490impl Format<u16> for Cmap13Marker {
1491 const FORMAT: u16 = 13;
1492}
1493
1494#[derive(Debug, Clone, Copy)]
1496#[doc(hidden)]
1497pub struct Cmap13Marker {
1498 groups_byte_len: usize,
1499}
1500
1501impl Cmap13Marker {
1502 pub fn format_byte_range(&self) -> Range<usize> {
1503 let start = 0;
1504 start..start + u16::RAW_BYTE_LEN
1505 }
1506
1507 pub fn reserved_byte_range(&self) -> Range<usize> {
1508 let start = self.format_byte_range().end;
1509 start..start + u16::RAW_BYTE_LEN
1510 }
1511
1512 pub fn length_byte_range(&self) -> Range<usize> {
1513 let start = self.reserved_byte_range().end;
1514 start..start + u32::RAW_BYTE_LEN
1515 }
1516
1517 pub fn language_byte_range(&self) -> Range<usize> {
1518 let start = self.length_byte_range().end;
1519 start..start + u32::RAW_BYTE_LEN
1520 }
1521
1522 pub fn num_groups_byte_range(&self) -> Range<usize> {
1523 let start = self.language_byte_range().end;
1524 start..start + u32::RAW_BYTE_LEN
1525 }
1526
1527 pub fn groups_byte_range(&self) -> Range<usize> {
1528 let start = self.num_groups_byte_range().end;
1529 start..start + self.groups_byte_len
1530 }
1531}
1532
1533impl MinByteRange for Cmap13Marker {
1534 fn min_byte_range(&self) -> Range<usize> {
1535 0..self.groups_byte_range().end
1536 }
1537}
1538
1539impl<'a> FontRead<'a> for Cmap13<'a> {
1540 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1541 let mut cursor = data.cursor();
1542 cursor.advance::<u16>();
1543 cursor.advance::<u16>();
1544 cursor.advance::<u32>();
1545 cursor.advance::<u32>();
1546 let num_groups: u32 = cursor.read()?;
1547 let groups_byte_len = (num_groups as usize)
1548 .checked_mul(ConstantMapGroup::RAW_BYTE_LEN)
1549 .ok_or(ReadError::OutOfBounds)?;
1550 cursor.advance_by(groups_byte_len);
1551 cursor.finish(Cmap13Marker { groups_byte_len })
1552 }
1553}
1554
1555pub type Cmap13<'a> = TableRef<'a, Cmap13Marker>;
1557
1558#[allow(clippy::needless_lifetimes)]
1559impl<'a> Cmap13<'a> {
1560 pub fn format(&self) -> u16 {
1562 let range = self.shape.format_byte_range();
1563 self.data.read_at(range.start).unwrap()
1564 }
1565
1566 pub fn length(&self) -> u32 {
1568 let range = self.shape.length_byte_range();
1569 self.data.read_at(range.start).unwrap()
1570 }
1571
1572 pub fn language(&self) -> u32 {
1575 let range = self.shape.language_byte_range();
1576 self.data.read_at(range.start).unwrap()
1577 }
1578
1579 pub fn num_groups(&self) -> u32 {
1581 let range = self.shape.num_groups_byte_range();
1582 self.data.read_at(range.start).unwrap()
1583 }
1584
1585 pub fn groups(&self) -> &'a [ConstantMapGroup] {
1587 let range = self.shape.groups_byte_range();
1588 self.data.read_array(range).unwrap()
1589 }
1590}
1591
1592#[cfg(feature = "experimental_traverse")]
1593impl<'a> SomeTable<'a> for Cmap13<'a> {
1594 fn type_name(&self) -> &str {
1595 "Cmap13"
1596 }
1597 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1598 match idx {
1599 0usize => Some(Field::new("format", self.format())),
1600 1usize => Some(Field::new("length", self.length())),
1601 2usize => Some(Field::new("language", self.language())),
1602 3usize => Some(Field::new("num_groups", self.num_groups())),
1603 4usize => Some(Field::new(
1604 "groups",
1605 traversal::FieldType::array_of_records(
1606 stringify!(ConstantMapGroup),
1607 self.groups(),
1608 self.offset_data(),
1609 ),
1610 )),
1611 _ => None,
1612 }
1613 }
1614}
1615
1616#[cfg(feature = "experimental_traverse")]
1617#[allow(clippy::needless_lifetimes)]
1618impl<'a> std::fmt::Debug for Cmap13<'a> {
1619 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1620 (self as &dyn SomeTable<'a>).fmt(f)
1621 }
1622}
1623
1624#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1626#[repr(C)]
1627#[repr(packed)]
1628pub struct ConstantMapGroup {
1629 pub start_char_code: BigEndian<u32>,
1631 pub end_char_code: BigEndian<u32>,
1633 pub glyph_id: BigEndian<u32>,
1636}
1637
1638impl ConstantMapGroup {
1639 pub fn start_char_code(&self) -> u32 {
1641 self.start_char_code.get()
1642 }
1643
1644 pub fn end_char_code(&self) -> u32 {
1646 self.end_char_code.get()
1647 }
1648
1649 pub fn glyph_id(&self) -> u32 {
1652 self.glyph_id.get()
1653 }
1654}
1655
1656impl FixedSize for ConstantMapGroup {
1657 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1658}
1659
1660#[cfg(feature = "experimental_traverse")]
1661impl<'a> SomeRecord<'a> for ConstantMapGroup {
1662 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1663 RecordResolver {
1664 name: "ConstantMapGroup",
1665 get_field: Box::new(move |idx, _data| match idx {
1666 0usize => Some(Field::new("start_char_code", self.start_char_code())),
1667 1usize => Some(Field::new("end_char_code", self.end_char_code())),
1668 2usize => Some(Field::new("glyph_id", self.glyph_id())),
1669 _ => None,
1670 }),
1671 data,
1672 }
1673 }
1674}
1675
1676impl Format<u16> for Cmap14Marker {
1677 const FORMAT: u16 = 14;
1678}
1679
1680#[derive(Debug, Clone, Copy)]
1682#[doc(hidden)]
1683pub struct Cmap14Marker {
1684 var_selector_byte_len: usize,
1685}
1686
1687impl Cmap14Marker {
1688 pub fn format_byte_range(&self) -> Range<usize> {
1689 let start = 0;
1690 start..start + u16::RAW_BYTE_LEN
1691 }
1692
1693 pub fn length_byte_range(&self) -> Range<usize> {
1694 let start = self.format_byte_range().end;
1695 start..start + u32::RAW_BYTE_LEN
1696 }
1697
1698 pub fn num_var_selector_records_byte_range(&self) -> Range<usize> {
1699 let start = self.length_byte_range().end;
1700 start..start + u32::RAW_BYTE_LEN
1701 }
1702
1703 pub fn var_selector_byte_range(&self) -> Range<usize> {
1704 let start = self.num_var_selector_records_byte_range().end;
1705 start..start + self.var_selector_byte_len
1706 }
1707}
1708
1709impl MinByteRange for Cmap14Marker {
1710 fn min_byte_range(&self) -> Range<usize> {
1711 0..self.var_selector_byte_range().end
1712 }
1713}
1714
1715impl<'a> FontRead<'a> for Cmap14<'a> {
1716 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1717 let mut cursor = data.cursor();
1718 cursor.advance::<u16>();
1719 cursor.advance::<u32>();
1720 let num_var_selector_records: u32 = cursor.read()?;
1721 let var_selector_byte_len = (num_var_selector_records as usize)
1722 .checked_mul(VariationSelector::RAW_BYTE_LEN)
1723 .ok_or(ReadError::OutOfBounds)?;
1724 cursor.advance_by(var_selector_byte_len);
1725 cursor.finish(Cmap14Marker {
1726 var_selector_byte_len,
1727 })
1728 }
1729}
1730
1731pub type Cmap14<'a> = TableRef<'a, Cmap14Marker>;
1733
1734#[allow(clippy::needless_lifetimes)]
1735impl<'a> Cmap14<'a> {
1736 pub fn format(&self) -> u16 {
1738 let range = self.shape.format_byte_range();
1739 self.data.read_at(range.start).unwrap()
1740 }
1741
1742 pub fn length(&self) -> u32 {
1744 let range = self.shape.length_byte_range();
1745 self.data.read_at(range.start).unwrap()
1746 }
1747
1748 pub fn num_var_selector_records(&self) -> u32 {
1750 let range = self.shape.num_var_selector_records_byte_range();
1751 self.data.read_at(range.start).unwrap()
1752 }
1753
1754 pub fn var_selector(&self) -> &'a [VariationSelector] {
1756 let range = self.shape.var_selector_byte_range();
1757 self.data.read_array(range).unwrap()
1758 }
1759}
1760
1761#[cfg(feature = "experimental_traverse")]
1762impl<'a> SomeTable<'a> for Cmap14<'a> {
1763 fn type_name(&self) -> &str {
1764 "Cmap14"
1765 }
1766 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1767 match idx {
1768 0usize => Some(Field::new("format", self.format())),
1769 1usize => Some(Field::new("length", self.length())),
1770 2usize => Some(Field::new(
1771 "num_var_selector_records",
1772 self.num_var_selector_records(),
1773 )),
1774 3usize => Some(Field::new(
1775 "var_selector",
1776 traversal::FieldType::array_of_records(
1777 stringify!(VariationSelector),
1778 self.var_selector(),
1779 self.offset_data(),
1780 ),
1781 )),
1782 _ => None,
1783 }
1784 }
1785}
1786
1787#[cfg(feature = "experimental_traverse")]
1788#[allow(clippy::needless_lifetimes)]
1789impl<'a> std::fmt::Debug for Cmap14<'a> {
1790 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1791 (self as &dyn SomeTable<'a>).fmt(f)
1792 }
1793}
1794
1795#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1797#[repr(C)]
1798#[repr(packed)]
1799pub struct VariationSelector {
1800 pub var_selector: BigEndian<Uint24>,
1802 pub default_uvs_offset: BigEndian<Nullable<Offset32>>,
1805 pub non_default_uvs_offset: BigEndian<Nullable<Offset32>>,
1808}
1809
1810impl VariationSelector {
1811 pub fn var_selector(&self) -> Uint24 {
1813 self.var_selector.get()
1814 }
1815
1816 pub fn default_uvs_offset(&self) -> Nullable<Offset32> {
1819 self.default_uvs_offset.get()
1820 }
1821
1822 pub fn default_uvs<'a>(&self, data: FontData<'a>) -> Option<Result<DefaultUvs<'a>, ReadError>> {
1828 self.default_uvs_offset().resolve(data)
1829 }
1830
1831 pub fn non_default_uvs_offset(&self) -> Nullable<Offset32> {
1834 self.non_default_uvs_offset.get()
1835 }
1836
1837 pub fn non_default_uvs<'a>(
1843 &self,
1844 data: FontData<'a>,
1845 ) -> Option<Result<NonDefaultUvs<'a>, ReadError>> {
1846 self.non_default_uvs_offset().resolve(data)
1847 }
1848}
1849
1850impl FixedSize for VariationSelector {
1851 const RAW_BYTE_LEN: usize =
1852 Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
1853}
1854
1855#[cfg(feature = "experimental_traverse")]
1856impl<'a> SomeRecord<'a> for VariationSelector {
1857 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1858 RecordResolver {
1859 name: "VariationSelector",
1860 get_field: Box::new(move |idx, _data| match idx {
1861 0usize => Some(Field::new("var_selector", self.var_selector())),
1862 1usize => Some(Field::new(
1863 "default_uvs_offset",
1864 FieldType::offset(self.default_uvs_offset(), self.default_uvs(_data)),
1865 )),
1866 2usize => Some(Field::new(
1867 "non_default_uvs_offset",
1868 FieldType::offset(self.non_default_uvs_offset(), self.non_default_uvs(_data)),
1869 )),
1870 _ => None,
1871 }),
1872 data,
1873 }
1874 }
1875}
1876
1877#[derive(Debug, Clone, Copy)]
1879#[doc(hidden)]
1880pub struct DefaultUvsMarker {
1881 ranges_byte_len: usize,
1882}
1883
1884impl DefaultUvsMarker {
1885 pub fn num_unicode_value_ranges_byte_range(&self) -> Range<usize> {
1886 let start = 0;
1887 start..start + u32::RAW_BYTE_LEN
1888 }
1889
1890 pub fn ranges_byte_range(&self) -> Range<usize> {
1891 let start = self.num_unicode_value_ranges_byte_range().end;
1892 start..start + self.ranges_byte_len
1893 }
1894}
1895
1896impl MinByteRange for DefaultUvsMarker {
1897 fn min_byte_range(&self) -> Range<usize> {
1898 0..self.ranges_byte_range().end
1899 }
1900}
1901
1902impl<'a> FontRead<'a> for DefaultUvs<'a> {
1903 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1904 let mut cursor = data.cursor();
1905 let num_unicode_value_ranges: u32 = cursor.read()?;
1906 let ranges_byte_len = (num_unicode_value_ranges as usize)
1907 .checked_mul(UnicodeRange::RAW_BYTE_LEN)
1908 .ok_or(ReadError::OutOfBounds)?;
1909 cursor.advance_by(ranges_byte_len);
1910 cursor.finish(DefaultUvsMarker { ranges_byte_len })
1911 }
1912}
1913
1914pub type DefaultUvs<'a> = TableRef<'a, DefaultUvsMarker>;
1916
1917#[allow(clippy::needless_lifetimes)]
1918impl<'a> DefaultUvs<'a> {
1919 pub fn num_unicode_value_ranges(&self) -> u32 {
1921 let range = self.shape.num_unicode_value_ranges_byte_range();
1922 self.data.read_at(range.start).unwrap()
1923 }
1924
1925 pub fn ranges(&self) -> &'a [UnicodeRange] {
1927 let range = self.shape.ranges_byte_range();
1928 self.data.read_array(range).unwrap()
1929 }
1930}
1931
1932#[cfg(feature = "experimental_traverse")]
1933impl<'a> SomeTable<'a> for DefaultUvs<'a> {
1934 fn type_name(&self) -> &str {
1935 "DefaultUvs"
1936 }
1937 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1938 match idx {
1939 0usize => Some(Field::new(
1940 "num_unicode_value_ranges",
1941 self.num_unicode_value_ranges(),
1942 )),
1943 1usize => Some(Field::new(
1944 "ranges",
1945 traversal::FieldType::array_of_records(
1946 stringify!(UnicodeRange),
1947 self.ranges(),
1948 self.offset_data(),
1949 ),
1950 )),
1951 _ => None,
1952 }
1953 }
1954}
1955
1956#[cfg(feature = "experimental_traverse")]
1957#[allow(clippy::needless_lifetimes)]
1958impl<'a> std::fmt::Debug for DefaultUvs<'a> {
1959 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1960 (self as &dyn SomeTable<'a>).fmt(f)
1961 }
1962}
1963
1964#[derive(Debug, Clone, Copy)]
1966#[doc(hidden)]
1967pub struct NonDefaultUvsMarker {
1968 uvs_mapping_byte_len: usize,
1969}
1970
1971impl NonDefaultUvsMarker {
1972 pub fn num_uvs_mappings_byte_range(&self) -> Range<usize> {
1973 let start = 0;
1974 start..start + u32::RAW_BYTE_LEN
1975 }
1976
1977 pub fn uvs_mapping_byte_range(&self) -> Range<usize> {
1978 let start = self.num_uvs_mappings_byte_range().end;
1979 start..start + self.uvs_mapping_byte_len
1980 }
1981}
1982
1983impl MinByteRange for NonDefaultUvsMarker {
1984 fn min_byte_range(&self) -> Range<usize> {
1985 0..self.uvs_mapping_byte_range().end
1986 }
1987}
1988
1989impl<'a> FontRead<'a> for NonDefaultUvs<'a> {
1990 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1991 let mut cursor = data.cursor();
1992 let num_uvs_mappings: u32 = cursor.read()?;
1993 let uvs_mapping_byte_len = (num_uvs_mappings as usize)
1994 .checked_mul(UvsMapping::RAW_BYTE_LEN)
1995 .ok_or(ReadError::OutOfBounds)?;
1996 cursor.advance_by(uvs_mapping_byte_len);
1997 cursor.finish(NonDefaultUvsMarker {
1998 uvs_mapping_byte_len,
1999 })
2000 }
2001}
2002
2003pub type NonDefaultUvs<'a> = TableRef<'a, NonDefaultUvsMarker>;
2005
2006#[allow(clippy::needless_lifetimes)]
2007impl<'a> NonDefaultUvs<'a> {
2008 pub fn num_uvs_mappings(&self) -> u32 {
2009 let range = self.shape.num_uvs_mappings_byte_range();
2010 self.data.read_at(range.start).unwrap()
2011 }
2012
2013 pub fn uvs_mapping(&self) -> &'a [UvsMapping] {
2014 let range = self.shape.uvs_mapping_byte_range();
2015 self.data.read_array(range).unwrap()
2016 }
2017}
2018
2019#[cfg(feature = "experimental_traverse")]
2020impl<'a> SomeTable<'a> for NonDefaultUvs<'a> {
2021 fn type_name(&self) -> &str {
2022 "NonDefaultUvs"
2023 }
2024 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2025 match idx {
2026 0usize => Some(Field::new("num_uvs_mappings", self.num_uvs_mappings())),
2027 1usize => Some(Field::new(
2028 "uvs_mapping",
2029 traversal::FieldType::array_of_records(
2030 stringify!(UvsMapping),
2031 self.uvs_mapping(),
2032 self.offset_data(),
2033 ),
2034 )),
2035 _ => None,
2036 }
2037 }
2038}
2039
2040#[cfg(feature = "experimental_traverse")]
2041#[allow(clippy::needless_lifetimes)]
2042impl<'a> std::fmt::Debug for NonDefaultUvs<'a> {
2043 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2044 (self as &dyn SomeTable<'a>).fmt(f)
2045 }
2046}
2047
2048#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2050#[repr(C)]
2051#[repr(packed)]
2052pub struct UvsMapping {
2053 pub unicode_value: BigEndian<Uint24>,
2055 pub glyph_id: BigEndian<u16>,
2057}
2058
2059impl UvsMapping {
2060 pub fn unicode_value(&self) -> Uint24 {
2062 self.unicode_value.get()
2063 }
2064
2065 pub fn glyph_id(&self) -> u16 {
2067 self.glyph_id.get()
2068 }
2069}
2070
2071impl FixedSize for UvsMapping {
2072 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
2073}
2074
2075#[cfg(feature = "experimental_traverse")]
2076impl<'a> SomeRecord<'a> for UvsMapping {
2077 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2078 RecordResolver {
2079 name: "UvsMapping",
2080 get_field: Box::new(move |idx, _data| match idx {
2081 0usize => Some(Field::new("unicode_value", self.unicode_value())),
2082 1usize => Some(Field::new("glyph_id", self.glyph_id())),
2083 _ => None,
2084 }),
2085 data,
2086 }
2087 }
2088}
2089
2090#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2092#[repr(C)]
2093#[repr(packed)]
2094pub struct UnicodeRange {
2095 pub start_unicode_value: BigEndian<Uint24>,
2097 pub additional_count: u8,
2099}
2100
2101impl UnicodeRange {
2102 pub fn start_unicode_value(&self) -> Uint24 {
2104 self.start_unicode_value.get()
2105 }
2106
2107 pub fn additional_count(&self) -> u8 {
2109 self.additional_count
2110 }
2111}
2112
2113impl FixedSize for UnicodeRange {
2114 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
2115}
2116
2117#[cfg(feature = "experimental_traverse")]
2118impl<'a> SomeRecord<'a> for UnicodeRange {
2119 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2120 RecordResolver {
2121 name: "UnicodeRange",
2122 get_field: Box::new(move |idx, _data| match idx {
2123 0usize => Some(Field::new(
2124 "start_unicode_value",
2125 self.start_unicode_value(),
2126 )),
2127 1usize => Some(Field::new("additional_count", self.additional_count())),
2128 _ => None,
2129 }),
2130 data,
2131 }
2132 }
2133}