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 cursor.advance::<u32>();
1277 let glyph_id_array_byte_len =
1278 cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
1279 cursor.advance_by(glyph_id_array_byte_len);
1280 cursor.finish(Cmap10Marker {
1281 glyph_id_array_byte_len,
1282 })
1283 }
1284}
1285
1286pub type Cmap10<'a> = TableRef<'a, Cmap10Marker>;
1288
1289#[allow(clippy::needless_lifetimes)]
1290impl<'a> Cmap10<'a> {
1291 pub fn format(&self) -> u16 {
1293 let range = self.shape.format_byte_range();
1294 self.data.read_at(range.start).unwrap()
1295 }
1296
1297 pub fn length(&self) -> u32 {
1299 let range = self.shape.length_byte_range();
1300 self.data.read_at(range.start).unwrap()
1301 }
1302
1303 pub fn language(&self) -> u32 {
1306 let range = self.shape.language_byte_range();
1307 self.data.read_at(range.start).unwrap()
1308 }
1309
1310 pub fn start_char_code(&self) -> u32 {
1312 let range = self.shape.start_char_code_byte_range();
1313 self.data.read_at(range.start).unwrap()
1314 }
1315
1316 pub fn num_chars(&self) -> u32 {
1318 let range = self.shape.num_chars_byte_range();
1319 self.data.read_at(range.start).unwrap()
1320 }
1321
1322 pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
1324 let range = self.shape.glyph_id_array_byte_range();
1325 self.data.read_array(range).unwrap()
1326 }
1327}
1328
1329#[cfg(feature = "experimental_traverse")]
1330impl<'a> SomeTable<'a> for Cmap10<'a> {
1331 fn type_name(&self) -> &str {
1332 "Cmap10"
1333 }
1334 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1335 match idx {
1336 0usize => Some(Field::new("format", self.format())),
1337 1usize => Some(Field::new("length", self.length())),
1338 2usize => Some(Field::new("language", self.language())),
1339 3usize => Some(Field::new("start_char_code", self.start_char_code())),
1340 4usize => Some(Field::new("num_chars", self.num_chars())),
1341 5usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
1342 _ => None,
1343 }
1344 }
1345}
1346
1347#[cfg(feature = "experimental_traverse")]
1348#[allow(clippy::needless_lifetimes)]
1349impl<'a> std::fmt::Debug for Cmap10<'a> {
1350 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1351 (self as &dyn SomeTable<'a>).fmt(f)
1352 }
1353}
1354
1355impl Format<u16> for Cmap12Marker {
1356 const FORMAT: u16 = 12;
1357}
1358
1359#[derive(Debug, Clone, Copy)]
1361#[doc(hidden)]
1362pub struct Cmap12Marker {
1363 groups_byte_len: usize,
1364}
1365
1366impl Cmap12Marker {
1367 pub fn format_byte_range(&self) -> Range<usize> {
1368 let start = 0;
1369 start..start + u16::RAW_BYTE_LEN
1370 }
1371
1372 pub fn reserved_byte_range(&self) -> Range<usize> {
1373 let start = self.format_byte_range().end;
1374 start..start + u16::RAW_BYTE_LEN
1375 }
1376
1377 pub fn length_byte_range(&self) -> Range<usize> {
1378 let start = self.reserved_byte_range().end;
1379 start..start + u32::RAW_BYTE_LEN
1380 }
1381
1382 pub fn language_byte_range(&self) -> Range<usize> {
1383 let start = self.length_byte_range().end;
1384 start..start + u32::RAW_BYTE_LEN
1385 }
1386
1387 pub fn num_groups_byte_range(&self) -> Range<usize> {
1388 let start = self.language_byte_range().end;
1389 start..start + u32::RAW_BYTE_LEN
1390 }
1391
1392 pub fn groups_byte_range(&self) -> Range<usize> {
1393 let start = self.num_groups_byte_range().end;
1394 start..start + self.groups_byte_len
1395 }
1396}
1397
1398impl MinByteRange for Cmap12Marker {
1399 fn min_byte_range(&self) -> Range<usize> {
1400 0..self.groups_byte_range().end
1401 }
1402}
1403
1404impl<'a> FontRead<'a> for Cmap12<'a> {
1405 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1406 let mut cursor = data.cursor();
1407 cursor.advance::<u16>();
1408 cursor.advance::<u16>();
1409 cursor.advance::<u32>();
1410 cursor.advance::<u32>();
1411 let num_groups: u32 = cursor.read()?;
1412 let groups_byte_len = (num_groups as usize)
1413 .checked_mul(SequentialMapGroup::RAW_BYTE_LEN)
1414 .ok_or(ReadError::OutOfBounds)?;
1415 cursor.advance_by(groups_byte_len);
1416 cursor.finish(Cmap12Marker { groups_byte_len })
1417 }
1418}
1419
1420pub type Cmap12<'a> = TableRef<'a, Cmap12Marker>;
1422
1423#[allow(clippy::needless_lifetimes)]
1424impl<'a> Cmap12<'a> {
1425 pub fn format(&self) -> u16 {
1427 let range = self.shape.format_byte_range();
1428 self.data.read_at(range.start).unwrap()
1429 }
1430
1431 pub fn length(&self) -> u32 {
1433 let range = self.shape.length_byte_range();
1434 self.data.read_at(range.start).unwrap()
1435 }
1436
1437 pub fn language(&self) -> u32 {
1440 let range = self.shape.language_byte_range();
1441 self.data.read_at(range.start).unwrap()
1442 }
1443
1444 pub fn num_groups(&self) -> u32 {
1446 let range = self.shape.num_groups_byte_range();
1447 self.data.read_at(range.start).unwrap()
1448 }
1449
1450 pub fn groups(&self) -> &'a [SequentialMapGroup] {
1452 let range = self.shape.groups_byte_range();
1453 self.data.read_array(range).unwrap()
1454 }
1455}
1456
1457#[cfg(feature = "experimental_traverse")]
1458impl<'a> SomeTable<'a> for Cmap12<'a> {
1459 fn type_name(&self) -> &str {
1460 "Cmap12"
1461 }
1462 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1463 match idx {
1464 0usize => Some(Field::new("format", self.format())),
1465 1usize => Some(Field::new("length", self.length())),
1466 2usize => Some(Field::new("language", self.language())),
1467 3usize => Some(Field::new("num_groups", self.num_groups())),
1468 4usize => Some(Field::new(
1469 "groups",
1470 traversal::FieldType::array_of_records(
1471 stringify!(SequentialMapGroup),
1472 self.groups(),
1473 self.offset_data(),
1474 ),
1475 )),
1476 _ => None,
1477 }
1478 }
1479}
1480
1481#[cfg(feature = "experimental_traverse")]
1482#[allow(clippy::needless_lifetimes)]
1483impl<'a> std::fmt::Debug for Cmap12<'a> {
1484 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1485 (self as &dyn SomeTable<'a>).fmt(f)
1486 }
1487}
1488
1489impl Format<u16> for Cmap13Marker {
1490 const FORMAT: u16 = 13;
1491}
1492
1493#[derive(Debug, Clone, Copy)]
1495#[doc(hidden)]
1496pub struct Cmap13Marker {
1497 groups_byte_len: usize,
1498}
1499
1500impl Cmap13Marker {
1501 pub fn format_byte_range(&self) -> Range<usize> {
1502 let start = 0;
1503 start..start + u16::RAW_BYTE_LEN
1504 }
1505
1506 pub fn reserved_byte_range(&self) -> Range<usize> {
1507 let start = self.format_byte_range().end;
1508 start..start + u16::RAW_BYTE_LEN
1509 }
1510
1511 pub fn length_byte_range(&self) -> Range<usize> {
1512 let start = self.reserved_byte_range().end;
1513 start..start + u32::RAW_BYTE_LEN
1514 }
1515
1516 pub fn language_byte_range(&self) -> Range<usize> {
1517 let start = self.length_byte_range().end;
1518 start..start + u32::RAW_BYTE_LEN
1519 }
1520
1521 pub fn num_groups_byte_range(&self) -> Range<usize> {
1522 let start = self.language_byte_range().end;
1523 start..start + u32::RAW_BYTE_LEN
1524 }
1525
1526 pub fn groups_byte_range(&self) -> Range<usize> {
1527 let start = self.num_groups_byte_range().end;
1528 start..start + self.groups_byte_len
1529 }
1530}
1531
1532impl MinByteRange for Cmap13Marker {
1533 fn min_byte_range(&self) -> Range<usize> {
1534 0..self.groups_byte_range().end
1535 }
1536}
1537
1538impl<'a> FontRead<'a> for Cmap13<'a> {
1539 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1540 let mut cursor = data.cursor();
1541 cursor.advance::<u16>();
1542 cursor.advance::<u16>();
1543 cursor.advance::<u32>();
1544 cursor.advance::<u32>();
1545 let num_groups: u32 = cursor.read()?;
1546 let groups_byte_len = (num_groups as usize)
1547 .checked_mul(ConstantMapGroup::RAW_BYTE_LEN)
1548 .ok_or(ReadError::OutOfBounds)?;
1549 cursor.advance_by(groups_byte_len);
1550 cursor.finish(Cmap13Marker { groups_byte_len })
1551 }
1552}
1553
1554pub type Cmap13<'a> = TableRef<'a, Cmap13Marker>;
1556
1557#[allow(clippy::needless_lifetimes)]
1558impl<'a> Cmap13<'a> {
1559 pub fn format(&self) -> u16 {
1561 let range = self.shape.format_byte_range();
1562 self.data.read_at(range.start).unwrap()
1563 }
1564
1565 pub fn length(&self) -> u32 {
1567 let range = self.shape.length_byte_range();
1568 self.data.read_at(range.start).unwrap()
1569 }
1570
1571 pub fn language(&self) -> u32 {
1574 let range = self.shape.language_byte_range();
1575 self.data.read_at(range.start).unwrap()
1576 }
1577
1578 pub fn num_groups(&self) -> u32 {
1580 let range = self.shape.num_groups_byte_range();
1581 self.data.read_at(range.start).unwrap()
1582 }
1583
1584 pub fn groups(&self) -> &'a [ConstantMapGroup] {
1586 let range = self.shape.groups_byte_range();
1587 self.data.read_array(range).unwrap()
1588 }
1589}
1590
1591#[cfg(feature = "experimental_traverse")]
1592impl<'a> SomeTable<'a> for Cmap13<'a> {
1593 fn type_name(&self) -> &str {
1594 "Cmap13"
1595 }
1596 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1597 match idx {
1598 0usize => Some(Field::new("format", self.format())),
1599 1usize => Some(Field::new("length", self.length())),
1600 2usize => Some(Field::new("language", self.language())),
1601 3usize => Some(Field::new("num_groups", self.num_groups())),
1602 4usize => Some(Field::new(
1603 "groups",
1604 traversal::FieldType::array_of_records(
1605 stringify!(ConstantMapGroup),
1606 self.groups(),
1607 self.offset_data(),
1608 ),
1609 )),
1610 _ => None,
1611 }
1612 }
1613}
1614
1615#[cfg(feature = "experimental_traverse")]
1616#[allow(clippy::needless_lifetimes)]
1617impl<'a> std::fmt::Debug for Cmap13<'a> {
1618 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1619 (self as &dyn SomeTable<'a>).fmt(f)
1620 }
1621}
1622
1623#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1625#[repr(C)]
1626#[repr(packed)]
1627pub struct ConstantMapGroup {
1628 pub start_char_code: BigEndian<u32>,
1630 pub end_char_code: BigEndian<u32>,
1632 pub glyph_id: BigEndian<u32>,
1635}
1636
1637impl ConstantMapGroup {
1638 pub fn start_char_code(&self) -> u32 {
1640 self.start_char_code.get()
1641 }
1642
1643 pub fn end_char_code(&self) -> u32 {
1645 self.end_char_code.get()
1646 }
1647
1648 pub fn glyph_id(&self) -> u32 {
1651 self.glyph_id.get()
1652 }
1653}
1654
1655impl FixedSize for ConstantMapGroup {
1656 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1657}
1658
1659#[cfg(feature = "experimental_traverse")]
1660impl<'a> SomeRecord<'a> for ConstantMapGroup {
1661 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1662 RecordResolver {
1663 name: "ConstantMapGroup",
1664 get_field: Box::new(move |idx, _data| match idx {
1665 0usize => Some(Field::new("start_char_code", self.start_char_code())),
1666 1usize => Some(Field::new("end_char_code", self.end_char_code())),
1667 2usize => Some(Field::new("glyph_id", self.glyph_id())),
1668 _ => None,
1669 }),
1670 data,
1671 }
1672 }
1673}
1674
1675impl Format<u16> for Cmap14Marker {
1676 const FORMAT: u16 = 14;
1677}
1678
1679#[derive(Debug, Clone, Copy)]
1681#[doc(hidden)]
1682pub struct Cmap14Marker {
1683 var_selector_byte_len: usize,
1684}
1685
1686impl Cmap14Marker {
1687 pub fn format_byte_range(&self) -> Range<usize> {
1688 let start = 0;
1689 start..start + u16::RAW_BYTE_LEN
1690 }
1691
1692 pub fn length_byte_range(&self) -> Range<usize> {
1693 let start = self.format_byte_range().end;
1694 start..start + u32::RAW_BYTE_LEN
1695 }
1696
1697 pub fn num_var_selector_records_byte_range(&self) -> Range<usize> {
1698 let start = self.length_byte_range().end;
1699 start..start + u32::RAW_BYTE_LEN
1700 }
1701
1702 pub fn var_selector_byte_range(&self) -> Range<usize> {
1703 let start = self.num_var_selector_records_byte_range().end;
1704 start..start + self.var_selector_byte_len
1705 }
1706}
1707
1708impl MinByteRange for Cmap14Marker {
1709 fn min_byte_range(&self) -> Range<usize> {
1710 0..self.var_selector_byte_range().end
1711 }
1712}
1713
1714impl<'a> FontRead<'a> for Cmap14<'a> {
1715 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1716 let mut cursor = data.cursor();
1717 cursor.advance::<u16>();
1718 cursor.advance::<u32>();
1719 let num_var_selector_records: u32 = cursor.read()?;
1720 let var_selector_byte_len = (num_var_selector_records as usize)
1721 .checked_mul(VariationSelector::RAW_BYTE_LEN)
1722 .ok_or(ReadError::OutOfBounds)?;
1723 cursor.advance_by(var_selector_byte_len);
1724 cursor.finish(Cmap14Marker {
1725 var_selector_byte_len,
1726 })
1727 }
1728}
1729
1730pub type Cmap14<'a> = TableRef<'a, Cmap14Marker>;
1732
1733#[allow(clippy::needless_lifetimes)]
1734impl<'a> Cmap14<'a> {
1735 pub fn format(&self) -> u16 {
1737 let range = self.shape.format_byte_range();
1738 self.data.read_at(range.start).unwrap()
1739 }
1740
1741 pub fn length(&self) -> u32 {
1743 let range = self.shape.length_byte_range();
1744 self.data.read_at(range.start).unwrap()
1745 }
1746
1747 pub fn num_var_selector_records(&self) -> u32 {
1749 let range = self.shape.num_var_selector_records_byte_range();
1750 self.data.read_at(range.start).unwrap()
1751 }
1752
1753 pub fn var_selector(&self) -> &'a [VariationSelector] {
1755 let range = self.shape.var_selector_byte_range();
1756 self.data.read_array(range).unwrap()
1757 }
1758}
1759
1760#[cfg(feature = "experimental_traverse")]
1761impl<'a> SomeTable<'a> for Cmap14<'a> {
1762 fn type_name(&self) -> &str {
1763 "Cmap14"
1764 }
1765 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1766 match idx {
1767 0usize => Some(Field::new("format", self.format())),
1768 1usize => Some(Field::new("length", self.length())),
1769 2usize => Some(Field::new(
1770 "num_var_selector_records",
1771 self.num_var_selector_records(),
1772 )),
1773 3usize => Some(Field::new(
1774 "var_selector",
1775 traversal::FieldType::array_of_records(
1776 stringify!(VariationSelector),
1777 self.var_selector(),
1778 self.offset_data(),
1779 ),
1780 )),
1781 _ => None,
1782 }
1783 }
1784}
1785
1786#[cfg(feature = "experimental_traverse")]
1787#[allow(clippy::needless_lifetimes)]
1788impl<'a> std::fmt::Debug for Cmap14<'a> {
1789 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1790 (self as &dyn SomeTable<'a>).fmt(f)
1791 }
1792}
1793
1794#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1796#[repr(C)]
1797#[repr(packed)]
1798pub struct VariationSelector {
1799 pub var_selector: BigEndian<Uint24>,
1801 pub default_uvs_offset: BigEndian<Nullable<Offset32>>,
1804 pub non_default_uvs_offset: BigEndian<Nullable<Offset32>>,
1807}
1808
1809impl VariationSelector {
1810 pub fn var_selector(&self) -> Uint24 {
1812 self.var_selector.get()
1813 }
1814
1815 pub fn default_uvs_offset(&self) -> Nullable<Offset32> {
1818 self.default_uvs_offset.get()
1819 }
1820
1821 pub fn default_uvs<'a>(&self, data: FontData<'a>) -> Option<Result<DefaultUvs<'a>, ReadError>> {
1827 self.default_uvs_offset().resolve(data)
1828 }
1829
1830 pub fn non_default_uvs_offset(&self) -> Nullable<Offset32> {
1833 self.non_default_uvs_offset.get()
1834 }
1835
1836 pub fn non_default_uvs<'a>(
1842 &self,
1843 data: FontData<'a>,
1844 ) -> Option<Result<NonDefaultUvs<'a>, ReadError>> {
1845 self.non_default_uvs_offset().resolve(data)
1846 }
1847}
1848
1849impl FixedSize for VariationSelector {
1850 const RAW_BYTE_LEN: usize =
1851 Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
1852}
1853
1854#[cfg(feature = "experimental_traverse")]
1855impl<'a> SomeRecord<'a> for VariationSelector {
1856 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1857 RecordResolver {
1858 name: "VariationSelector",
1859 get_field: Box::new(move |idx, _data| match idx {
1860 0usize => Some(Field::new("var_selector", self.var_selector())),
1861 1usize => Some(Field::new(
1862 "default_uvs_offset",
1863 FieldType::offset(self.default_uvs_offset(), self.default_uvs(_data)),
1864 )),
1865 2usize => Some(Field::new(
1866 "non_default_uvs_offset",
1867 FieldType::offset(self.non_default_uvs_offset(), self.non_default_uvs(_data)),
1868 )),
1869 _ => None,
1870 }),
1871 data,
1872 }
1873 }
1874}
1875
1876#[derive(Debug, Clone, Copy)]
1878#[doc(hidden)]
1879pub struct DefaultUvsMarker {
1880 ranges_byte_len: usize,
1881}
1882
1883impl DefaultUvsMarker {
1884 pub fn num_unicode_value_ranges_byte_range(&self) -> Range<usize> {
1885 let start = 0;
1886 start..start + u32::RAW_BYTE_LEN
1887 }
1888
1889 pub fn ranges_byte_range(&self) -> Range<usize> {
1890 let start = self.num_unicode_value_ranges_byte_range().end;
1891 start..start + self.ranges_byte_len
1892 }
1893}
1894
1895impl MinByteRange for DefaultUvsMarker {
1896 fn min_byte_range(&self) -> Range<usize> {
1897 0..self.ranges_byte_range().end
1898 }
1899}
1900
1901impl<'a> FontRead<'a> for DefaultUvs<'a> {
1902 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1903 let mut cursor = data.cursor();
1904 let num_unicode_value_ranges: u32 = cursor.read()?;
1905 let ranges_byte_len = (num_unicode_value_ranges as usize)
1906 .checked_mul(UnicodeRange::RAW_BYTE_LEN)
1907 .ok_or(ReadError::OutOfBounds)?;
1908 cursor.advance_by(ranges_byte_len);
1909 cursor.finish(DefaultUvsMarker { ranges_byte_len })
1910 }
1911}
1912
1913pub type DefaultUvs<'a> = TableRef<'a, DefaultUvsMarker>;
1915
1916#[allow(clippy::needless_lifetimes)]
1917impl<'a> DefaultUvs<'a> {
1918 pub fn num_unicode_value_ranges(&self) -> u32 {
1920 let range = self.shape.num_unicode_value_ranges_byte_range();
1921 self.data.read_at(range.start).unwrap()
1922 }
1923
1924 pub fn ranges(&self) -> &'a [UnicodeRange] {
1926 let range = self.shape.ranges_byte_range();
1927 self.data.read_array(range).unwrap()
1928 }
1929}
1930
1931#[cfg(feature = "experimental_traverse")]
1932impl<'a> SomeTable<'a> for DefaultUvs<'a> {
1933 fn type_name(&self) -> &str {
1934 "DefaultUvs"
1935 }
1936 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1937 match idx {
1938 0usize => Some(Field::new(
1939 "num_unicode_value_ranges",
1940 self.num_unicode_value_ranges(),
1941 )),
1942 1usize => Some(Field::new(
1943 "ranges",
1944 traversal::FieldType::array_of_records(
1945 stringify!(UnicodeRange),
1946 self.ranges(),
1947 self.offset_data(),
1948 ),
1949 )),
1950 _ => None,
1951 }
1952 }
1953}
1954
1955#[cfg(feature = "experimental_traverse")]
1956#[allow(clippy::needless_lifetimes)]
1957impl<'a> std::fmt::Debug for DefaultUvs<'a> {
1958 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1959 (self as &dyn SomeTable<'a>).fmt(f)
1960 }
1961}
1962
1963#[derive(Debug, Clone, Copy)]
1965#[doc(hidden)]
1966pub struct NonDefaultUvsMarker {
1967 uvs_mapping_byte_len: usize,
1968}
1969
1970impl NonDefaultUvsMarker {
1971 pub fn num_uvs_mappings_byte_range(&self) -> Range<usize> {
1972 let start = 0;
1973 start..start + u32::RAW_BYTE_LEN
1974 }
1975
1976 pub fn uvs_mapping_byte_range(&self) -> Range<usize> {
1977 let start = self.num_uvs_mappings_byte_range().end;
1978 start..start + self.uvs_mapping_byte_len
1979 }
1980}
1981
1982impl MinByteRange for NonDefaultUvsMarker {
1983 fn min_byte_range(&self) -> Range<usize> {
1984 0..self.uvs_mapping_byte_range().end
1985 }
1986}
1987
1988impl<'a> FontRead<'a> for NonDefaultUvs<'a> {
1989 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1990 let mut cursor = data.cursor();
1991 let num_uvs_mappings: u32 = cursor.read()?;
1992 let uvs_mapping_byte_len = (num_uvs_mappings as usize)
1993 .checked_mul(UvsMapping::RAW_BYTE_LEN)
1994 .ok_or(ReadError::OutOfBounds)?;
1995 cursor.advance_by(uvs_mapping_byte_len);
1996 cursor.finish(NonDefaultUvsMarker {
1997 uvs_mapping_byte_len,
1998 })
1999 }
2000}
2001
2002pub type NonDefaultUvs<'a> = TableRef<'a, NonDefaultUvsMarker>;
2004
2005#[allow(clippy::needless_lifetimes)]
2006impl<'a> NonDefaultUvs<'a> {
2007 pub fn num_uvs_mappings(&self) -> u32 {
2008 let range = self.shape.num_uvs_mappings_byte_range();
2009 self.data.read_at(range.start).unwrap()
2010 }
2011
2012 pub fn uvs_mapping(&self) -> &'a [UvsMapping] {
2013 let range = self.shape.uvs_mapping_byte_range();
2014 self.data.read_array(range).unwrap()
2015 }
2016}
2017
2018#[cfg(feature = "experimental_traverse")]
2019impl<'a> SomeTable<'a> for NonDefaultUvs<'a> {
2020 fn type_name(&self) -> &str {
2021 "NonDefaultUvs"
2022 }
2023 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2024 match idx {
2025 0usize => Some(Field::new("num_uvs_mappings", self.num_uvs_mappings())),
2026 1usize => Some(Field::new(
2027 "uvs_mapping",
2028 traversal::FieldType::array_of_records(
2029 stringify!(UvsMapping),
2030 self.uvs_mapping(),
2031 self.offset_data(),
2032 ),
2033 )),
2034 _ => None,
2035 }
2036 }
2037}
2038
2039#[cfg(feature = "experimental_traverse")]
2040#[allow(clippy::needless_lifetimes)]
2041impl<'a> std::fmt::Debug for NonDefaultUvs<'a> {
2042 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2043 (self as &dyn SomeTable<'a>).fmt(f)
2044 }
2045}
2046
2047#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2049#[repr(C)]
2050#[repr(packed)]
2051pub struct UvsMapping {
2052 pub unicode_value: BigEndian<Uint24>,
2054 pub glyph_id: BigEndian<u16>,
2056}
2057
2058impl UvsMapping {
2059 pub fn unicode_value(&self) -> Uint24 {
2061 self.unicode_value.get()
2062 }
2063
2064 pub fn glyph_id(&self) -> u16 {
2066 self.glyph_id.get()
2067 }
2068}
2069
2070impl FixedSize for UvsMapping {
2071 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
2072}
2073
2074#[cfg(feature = "experimental_traverse")]
2075impl<'a> SomeRecord<'a> for UvsMapping {
2076 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2077 RecordResolver {
2078 name: "UvsMapping",
2079 get_field: Box::new(move |idx, _data| match idx {
2080 0usize => Some(Field::new("unicode_value", self.unicode_value())),
2081 1usize => Some(Field::new("glyph_id", self.glyph_id())),
2082 _ => None,
2083 }),
2084 data,
2085 }
2086 }
2087}
2088
2089#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2091#[repr(C)]
2092#[repr(packed)]
2093pub struct UnicodeRange {
2094 pub start_unicode_value: BigEndian<Uint24>,
2096 pub additional_count: u8,
2098}
2099
2100impl UnicodeRange {
2101 pub fn start_unicode_value(&self) -> Uint24 {
2103 self.start_unicode_value.get()
2104 }
2105
2106 pub fn additional_count(&self) -> u8 {
2108 self.additional_count
2109 }
2110}
2111
2112impl FixedSize for UnicodeRange {
2113 const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
2114}
2115
2116#[cfg(feature = "experimental_traverse")]
2117impl<'a> SomeRecord<'a> for UnicodeRange {
2118 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2119 RecordResolver {
2120 name: "UnicodeRange",
2121 get_field: Box::new(move |idx, _data| match idx {
2122 0usize => Some(Field::new(
2123 "start_unicode_value",
2124 self.start_unicode_value(),
2125 )),
2126 1usize => Some(Field::new("additional_count", self.additional_count())),
2127 _ => None,
2128 }),
2129 data,
2130 }
2131 }
2132}