Skip to main content

read_fonts/generated/
generated_cmap.rs

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