Coverage Report

Created: 2026-10-24 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/read-fonts-0.46.0/generated/generated_cmap.rs
Line
Count
Source
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)]
6
use crate::codegen_prelude::*;
7
8
impl<'a> MinByteRange<'a> for Cmap<'a> {
9
0
    fn min_byte_range(&self) -> Range<usize> {
10
0
        0..self.encoding_records_byte_range().end
11
0
    }
12
0
    fn min_table_bytes(&self) -> &'a [u8] {
13
0
        let range = self.min_byte_range();
14
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
15
0
    }
16
}
17
18
impl TopLevelTable for Cmap<'_> {
19
    /// `cmap`
20
    const TAG: Tag = Tag::new(b"cmap");
21
}
22
23
impl ReadArgs for Cmap<'_> {
24
    type Args = ();
25
}
26
27
impl<'a> FontRead<'a> for Cmap<'a> {
28
2.17k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
29
        #[allow(clippy::absurd_extreme_comparisons)]
30
2.17k
        if data.len() < Self::MIN_SIZE {
31
4
            return Err(ReadError::OutOfBounds);
32
2.16k
        }
33
2.16k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
34
0
            return Err(ReadError::OutOfBounds);
35
        };
36
2.16k
        Ok(Self { data })
37
2.17k
    }
38
}
39
40
/// The fields at the start of the table, which are read directly.
41
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
42
#[repr(C, packed)]
43
#[doc(hidden)]
44
pub struct CmapFixedHeader {
45
    pub version: BigEndian<u16>,
46
    pub num_tables: BigEndian<u16>,
47
}
48
49
#[allow(clippy::absurd_extreme_comparisons)]
50
const _: () = assert!(std::mem::size_of::<CmapFixedHeader>() <= Cmap::MIN_SIZE);
51
52
/// [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#overview)
53
#[derive(Clone)]
54
pub struct Cmap<'a> {
55
    data: TableDataRef<'a, CmapFixedHeader>,
56
}
57
58
#[allow(clippy::needless_lifetimes)]
59
impl<'a> Cmap<'a> {
60
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
61
    basic_table_impls!(impl_the_methods);
62
63
    /// Table version number (0).
64
0
    pub fn version(&self) -> u16 {
65
0
        self.data.header().version.get()
66
0
    }
67
68
    /// Number of encoding tables that follow.
69
4.33k
    pub fn num_tables(&self) -> u16 {
70
4.33k
        self.data.header().num_tables.get()
71
4.33k
    }
72
73
4.33k
    pub fn encoding_records(&self) -> &'a [EncodingRecord] {
74
4.33k
        let range = self.encoding_records_byte_range();
75
4.33k
        self.offset_data()
76
4.33k
            .read_array(range)
77
4.33k
            .ok()
78
4.33k
            .unwrap_or_default()
79
4.33k
    }
80
81
4.33k
    pub fn version_byte_range(&self) -> Range<usize> {
82
4.33k
        let start = 0;
83
4.33k
        let end = start + u16::RAW_BYTE_LEN;
84
4.33k
        start..end
85
4.33k
    }
86
87
4.33k
    pub fn num_tables_byte_range(&self) -> Range<usize> {
88
4.33k
        let start = self.version_byte_range().end;
89
4.33k
        let end = start + u16::RAW_BYTE_LEN;
90
4.33k
        start..end
91
4.33k
    }
92
93
4.33k
    pub fn encoding_records_byte_range(&self) -> Range<usize> {
94
4.33k
        let num_tables = self.num_tables();
95
4.33k
        let start = self.num_tables_byte_range().end;
96
4.33k
        let end =
97
4.33k
            start + (transforms::to_usize(num_tables)).saturating_mul(EncodingRecord::RAW_BYTE_LEN);
98
4.33k
        start..end
99
4.33k
    }
100
}
101
102
const _: () = assert!(FontData::default_data_long_enough(Cmap::MIN_SIZE));
103
104
impl Default for Cmap<'_> {
105
0
    fn default() -> Self {
106
        Self {
107
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
108
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
109
        }
110
0
    }
111
}
112
113
impl<'a> MinByteRange<'a> for Dmap<'a> {
114
0
    fn min_byte_range(&self) -> Range<usize> {
115
0
        0..self.encoding_records_byte_range().end
116
0
    }
117
0
    fn min_table_bytes(&self) -> &'a [u8] {
118
0
        let range = self.min_byte_range();
119
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
120
0
    }
121
}
122
123
impl TopLevelTable for Dmap<'_> {
124
    /// `DMAP`
125
    const TAG: Tag = Tag::new(b"DMAP");
126
}
127
128
impl ReadArgs for Dmap<'_> {
129
    type Args = ();
130
}
131
132
impl<'a> FontRead<'a> for Dmap<'a> {
133
22
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
134
        #[allow(clippy::absurd_extreme_comparisons)]
135
22
        if data.len() < Self::MIN_SIZE {
136
6
            return Err(ReadError::OutOfBounds);
137
16
        }
138
16
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
139
0
            return Err(ReadError::OutOfBounds);
140
        };
141
16
        Ok(Self { data })
142
22
    }
143
}
144
145
/// The fields at the start of the table, which are read directly.
146
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
147
#[repr(C, packed)]
148
#[doc(hidden)]
149
pub struct DmapFixedHeader {
150
    pub version: BigEndian<u16>,
151
    pub num_tables: BigEndian<u16>,
152
}
153
154
#[allow(clippy::absurd_extreme_comparisons)]
155
const _: () = assert!(std::mem::size_of::<DmapFixedHeader>() <= Dmap::MIN_SIZE);
156
157
/// Delta map table (ISO/IEC 14496-22:2026, 5.6.15).
158
#[derive(Clone)]
159
pub struct Dmap<'a> {
160
    data: TableDataRef<'a, DmapFixedHeader>,
161
}
162
163
#[allow(clippy::needless_lifetimes)]
164
impl<'a> Dmap<'a> {
165
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
166
    basic_table_impls!(impl_the_methods);
167
168
    /// Table version number (0).
169
0
    pub fn version(&self) -> u16 {
170
0
        self.data.header().version.get()
171
0
    }
172
173
    /// Number of encoding tables that follow.
174
0
    pub fn num_tables(&self) -> u16 {
175
0
        self.data.header().num_tables.get()
176
0
    }
177
178
0
    pub fn encoding_records(&self) -> &'a [EncodingRecord] {
179
0
        let range = self.encoding_records_byte_range();
180
0
        self.offset_data()
181
0
            .read_array(range)
182
0
            .ok()
183
0
            .unwrap_or_default()
184
0
    }
185
186
0
    pub fn version_byte_range(&self) -> Range<usize> {
187
0
        let start = 0;
188
0
        let end = start + u16::RAW_BYTE_LEN;
189
0
        start..end
190
0
    }
191
192
0
    pub fn num_tables_byte_range(&self) -> Range<usize> {
193
0
        let start = self.version_byte_range().end;
194
0
        let end = start + u16::RAW_BYTE_LEN;
195
0
        start..end
196
0
    }
197
198
0
    pub fn encoding_records_byte_range(&self) -> Range<usize> {
199
0
        let num_tables = self.num_tables();
200
0
        let start = self.num_tables_byte_range().end;
201
0
        let end =
202
0
            start + (transforms::to_usize(num_tables)).saturating_mul(EncodingRecord::RAW_BYTE_LEN);
203
0
        start..end
204
0
    }
205
}
206
207
const _: () = assert!(FontData::default_data_long_enough(Dmap::MIN_SIZE));
208
209
impl Default for Dmap<'_> {
210
0
    fn default() -> Self {
211
        Self {
212
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
213
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
214
        }
215
0
    }
216
}
217
218
/// [Encoding Record](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#encoding-records-and-encodings)
219
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
220
#[repr(C)]
221
#[repr(packed)]
222
pub struct EncodingRecord {
223
    /// Platform ID.
224
    pub platform_id: BigEndian<PlatformId>,
225
    /// Platform-specific encoding ID.
226
    pub encoding_id: BigEndian<u16>,
227
    /// Byte offset from beginning of the [`Cmap`] or [`Dmap`] table to the
228
    /// subtable for this encoding.
229
    pub subtable_offset: BigEndian<Offset32>,
230
}
231
232
impl EncodingRecord {
233
    /// Platform ID.
234
2.22M
    pub fn platform_id(&self) -> PlatformId {
235
2.22M
        self.platform_id.get()
236
2.22M
    }
237
238
    /// Platform-specific encoding ID.
239
98.7k
    pub fn encoding_id(&self) -> u16 {
240
98.7k
        self.encoding_id.get()
241
98.7k
    }
242
243
    /// Byte offset from beginning of the [`Cmap`] or [`Dmap`] table to the
244
    /// subtable for this encoding.
245
5.11k
    pub fn subtable_offset(&self) -> Offset32 {
246
5.11k
        self.subtable_offset.get()
247
5.11k
    }
248
249
    /// Byte offset from beginning of the [`Cmap`] or [`Dmap`] table to the
250
    /// subtable for this encoding.
251
    ///
252
    /// The `data` argument should be retrieved from the parent table
253
    /// By calling its `offset_data` method.
254
5.11k
    pub fn subtable<'a>(&self, data: FontData<'a>) -> Result<CmapSubtable<'a>, ReadError> {
255
5.11k
        self.subtable_offset().resolve(data)
256
5.11k
    }
257
}
258
259
impl FixedSize for EncodingRecord {
260
    const RAW_BYTE_LEN: usize =
261
        PlatformId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
262
}
263
264
/// <https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#platform-ids>
265
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
266
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
267
#[repr(u16)]
268
#[allow(clippy::manual_non_exhaustive)]
269
pub enum PlatformId {
270
    #[default]
271
    Unicode = 0,
272
    Macintosh = 1,
273
    ISO = 2,
274
    Windows = 3,
275
    Custom = 4,
276
    #[doc(hidden)]
277
    /// If font data is malformed we will map unknown values to this variant
278
    Unknown,
279
}
280
281
impl PlatformId {
282
    /// Create from a raw scalar.
283
    ///
284
    /// This will never fail; unknown values will be mapped to the `Unknown` variant
285
2.22M
    pub fn new(raw: u16) -> Self {
286
2.22M
        match raw {
287
147k
            0 => Self::Unicode,
288
9.06k
            1 => Self::Macintosh,
289
6.42k
            2 => Self::ISO,
290
5.81k
            3 => Self::Windows,
291
2.82k
            4 => Self::Custom,
292
2.05M
            _ => Self::Unknown,
293
        }
294
2.22M
    }
295
}
296
297
impl font_types::Scalar for PlatformId {
298
    type Raw = <u16 as font_types::Scalar>::Raw;
299
0
    fn to_raw(self) -> Self::Raw {
300
0
        (self as u16).to_raw()
301
0
    }
302
2.22M
    fn from_raw(raw: Self::Raw) -> Self {
303
2.22M
        let t = <u16>::from_raw(raw);
304
2.22M
        Self::new(t)
305
2.22M
    }
306
}
307
308
/// The different cmap subtable formats.
309
#[derive(Clone)]
310
pub enum CmapSubtable<'a> {
311
    Format0(Cmap0<'a>),
312
    Format2(Cmap2<'a>),
313
    Format4(Cmap4<'a>),
314
    Format6(Cmap6<'a>),
315
    Format8(Cmap8<'a>),
316
    Format10(Cmap10<'a>),
317
    Format12(Cmap12<'a>),
318
    Format13(Cmap13<'a>),
319
    Format14(Cmap14<'a>),
320
    Format15(Cmap15<'a>),
321
}
322
323
impl Default for CmapSubtable<'_> {
324
0
    fn default() -> Self {
325
0
        Self::Format0(Default::default())
326
0
    }
327
}
328
329
impl<'a> CmapSubtable<'a> {
330
    ///Return the `FontData` used to resolve offsets for this table.
331
0
    pub fn offset_data(&self) -> FontData<'a> {
332
0
        match self {
333
0
            Self::Format0(item) => item.offset_data(),
334
0
            Self::Format2(item) => item.offset_data(),
335
0
            Self::Format4(item) => item.offset_data(),
336
0
            Self::Format6(item) => item.offset_data(),
337
0
            Self::Format8(item) => item.offset_data(),
338
0
            Self::Format10(item) => item.offset_data(),
339
0
            Self::Format12(item) => item.offset_data(),
340
0
            Self::Format13(item) => item.offset_data(),
341
0
            Self::Format14(item) => item.offset_data(),
342
0
            Self::Format15(item) => item.offset_data(),
343
        }
344
0
    }
345
346
    /// Format number is set to 0.
347
0
    pub fn format(&self) -> u16 {
348
0
        match self {
349
0
            Self::Format0(item) => item.format(),
350
0
            Self::Format2(item) => item.format(),
351
0
            Self::Format4(item) => item.format(),
352
0
            Self::Format6(item) => item.format(),
353
0
            Self::Format8(item) => item.format(),
354
0
            Self::Format10(item) => item.format(),
355
0
            Self::Format12(item) => item.format(),
356
0
            Self::Format13(item) => item.format(),
357
0
            Self::Format14(item) => item.format(),
358
0
            Self::Format15(item) => item.format(),
359
        }
360
0
    }
361
}
362
363
impl ReadArgs for CmapSubtable<'_> {
364
    type Args = ();
365
}
366
367
impl<'a> FontRead<'a> for CmapSubtable<'a> {
368
    #[inline]
369
1.90k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
370
1.90k
        let format: u16 = data.read_at(0usize)?;
371
1.88k
        match format {
372
121
            Cmap0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
373
4
            Cmap2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
374
436
            Cmap4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
375
159
            Cmap6::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
376
0
            Cmap8::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
377
94
            Cmap10::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
378
259
            Cmap12::FORMAT => Ok(Self::Format12(FontRead::read(data)?)),
379
365
            Cmap13::FORMAT => Ok(Self::Format13(FontRead::read(data)?)),
380
4
            Cmap14::FORMAT => Ok(Self::Format14(FontRead::read(data)?)),
381
0
            Cmap15::FORMAT => Ok(Self::Format15(FontRead::read(data)?)),
382
439
            other => Err(ReadError::InvalidFormat(other.into())),
383
        }
384
1.90k
    }
385
}
386
387
impl<'a> MinByteRange<'a> for CmapSubtable<'a> {
388
0
    fn min_byte_range(&self) -> Range<usize> {
389
0
        match self {
390
0
            Self::Format0(item) => item.min_byte_range(),
391
0
            Self::Format2(item) => item.min_byte_range(),
392
0
            Self::Format4(item) => item.min_byte_range(),
393
0
            Self::Format6(item) => item.min_byte_range(),
394
0
            Self::Format8(item) => item.min_byte_range(),
395
0
            Self::Format10(item) => item.min_byte_range(),
396
0
            Self::Format12(item) => item.min_byte_range(),
397
0
            Self::Format13(item) => item.min_byte_range(),
398
0
            Self::Format14(item) => item.min_byte_range(),
399
0
            Self::Format15(item) => item.min_byte_range(),
400
        }
401
0
    }
402
0
    fn min_table_bytes(&self) -> &'a [u8] {
403
0
        match self {
404
0
            Self::Format0(item) => item.min_table_bytes(),
405
0
            Self::Format2(item) => item.min_table_bytes(),
406
0
            Self::Format4(item) => item.min_table_bytes(),
407
0
            Self::Format6(item) => item.min_table_bytes(),
408
0
            Self::Format8(item) => item.min_table_bytes(),
409
0
            Self::Format10(item) => item.min_table_bytes(),
410
0
            Self::Format12(item) => item.min_table_bytes(),
411
0
            Self::Format13(item) => item.min_table_bytes(),
412
0
            Self::Format14(item) => item.min_table_bytes(),
413
0
            Self::Format15(item) => item.min_table_bytes(),
414
        }
415
0
    }
416
}
417
418
impl Format<u16> for Cmap0<'_> {
419
    const FORMAT: u16 = 0;
420
}
421
422
impl<'a> MinByteRange<'a> for Cmap0<'a> {
423
0
    fn min_byte_range(&self) -> Range<usize> {
424
0
        0..self.glyph_id_array_byte_range().end
425
0
    }
426
0
    fn min_table_bytes(&self) -> &'a [u8] {
427
0
        let range = self.min_byte_range();
428
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
429
0
    }
430
}
431
432
impl ReadArgs for Cmap0<'_> {
433
    type Args = ();
434
}
435
436
impl<'a> FontRead<'a> for Cmap0<'a> {
437
121
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
438
        #[allow(clippy::absurd_extreme_comparisons)]
439
121
        if data.len() < Self::MIN_SIZE {
440
59
            return Err(ReadError::OutOfBounds);
441
62
        }
442
62
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
443
0
            return Err(ReadError::OutOfBounds);
444
        };
445
62
        Ok(Self { data })
446
121
    }
447
}
448
449
/// The fields at the start of the table, which are read directly.
450
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
451
#[repr(C, packed)]
452
#[doc(hidden)]
453
pub struct Cmap0FixedHeader {
454
    pub format: BigEndian<u16>,
455
    pub length: BigEndian<u16>,
456
    pub language: BigEndian<u16>,
457
}
458
459
#[allow(clippy::absurd_extreme_comparisons)]
460
const _: () = assert!(std::mem::size_of::<Cmap0FixedHeader>() <= Cmap0::MIN_SIZE);
461
462
/// [cmap Format 0](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-0-byte-encoding-table): Byte encoding table
463
#[derive(Clone)]
464
pub struct Cmap0<'a> {
465
    data: TableDataRef<'a, Cmap0FixedHeader>,
466
}
467
468
#[allow(clippy::needless_lifetimes)]
469
impl<'a> Cmap0<'a> {
470
    pub const MIN_SIZE: usize =
471
        (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN * 256_usize);
472
    basic_table_impls!(impl_the_methods);
473
474
    /// Format number is set to 0.
475
0
    pub fn format(&self) -> u16 {
476
0
        self.data.header().format.get()
477
0
    }
478
479
    /// This is the length in bytes of the subtable.
480
0
    pub fn length(&self) -> u16 {
481
0
        self.data.header().length.get()
482
0
    }
483
484
    /// For requirements on use of the language field, see “Use of
485
    /// the language field in 'cmap' subtables” in this document.
486
0
    pub fn language(&self) -> u16 {
487
0
        self.data.header().language.get()
488
0
    }
489
490
    /// An array that maps character codes to glyph index values.
491
1.68k
    pub fn glyph_id_array(&self) -> &'a [u8] {
492
1.68k
        let range = self.glyph_id_array_byte_range();
493
1.68k
        self.offset_data()
494
1.68k
            .read_array(range)
495
1.68k
            .ok()
496
1.68k
            .unwrap_or_default()
497
1.68k
    }
498
499
1.68k
    pub fn format_byte_range(&self) -> Range<usize> {
500
1.68k
        let start = 0;
501
1.68k
        let end = start + u16::RAW_BYTE_LEN;
502
1.68k
        start..end
503
1.68k
    }
504
505
1.68k
    pub fn length_byte_range(&self) -> Range<usize> {
506
1.68k
        let start = self.format_byte_range().end;
507
1.68k
        let end = start + u16::RAW_BYTE_LEN;
508
1.68k
        start..end
509
1.68k
    }
510
511
1.68k
    pub fn language_byte_range(&self) -> Range<usize> {
512
1.68k
        let start = self.length_byte_range().end;
513
1.68k
        let end = start + u16::RAW_BYTE_LEN;
514
1.68k
        start..end
515
1.68k
    }
516
517
1.68k
    pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
518
1.68k
        let start = self.language_byte_range().end;
519
1.68k
        let end = start + (256_usize).saturating_mul(u8::RAW_BYTE_LEN);
520
1.68k
        start..end
521
1.68k
    }
522
}
523
524
const _: () = assert!(FontData::default_data_long_enough(Cmap0::MIN_SIZE));
525
526
impl Default for Cmap0<'_> {
527
0
    fn default() -> Self {
528
        Self {
529
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
530
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
531
        }
532
0
    }
533
}
534
535
impl Format<u16> for Cmap2<'_> {
536
    const FORMAT: u16 = 2;
537
}
538
539
impl<'a> MinByteRange<'a> for Cmap2<'a> {
540
0
    fn min_byte_range(&self) -> Range<usize> {
541
0
        0..self.sub_header_keys_byte_range().end
542
0
    }
543
0
    fn min_table_bytes(&self) -> &'a [u8] {
544
0
        let range = self.min_byte_range();
545
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
546
0
    }
547
}
548
549
impl ReadArgs for Cmap2<'_> {
550
    type Args = ();
551
}
552
553
impl<'a> FontRead<'a> for Cmap2<'a> {
554
4
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
555
        #[allow(clippy::absurd_extreme_comparisons)]
556
4
        if data.len() < Self::MIN_SIZE {
557
0
            return Err(ReadError::OutOfBounds);
558
4
        }
559
4
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
560
0
            return Err(ReadError::OutOfBounds);
561
        };
562
4
        Ok(Self { data })
563
4
    }
564
}
565
566
/// The fields at the start of the table, which are read directly.
567
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
568
#[repr(C, packed)]
569
#[doc(hidden)]
570
pub struct Cmap2FixedHeader {
571
    pub format: BigEndian<u16>,
572
    pub length: BigEndian<u16>,
573
    pub language: BigEndian<u16>,
574
}
575
576
#[allow(clippy::absurd_extreme_comparisons)]
577
const _: () = assert!(std::mem::size_of::<Cmap2FixedHeader>() <= Cmap2::MIN_SIZE);
578
579
/// [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
580
#[derive(Clone)]
581
pub struct Cmap2<'a> {
582
    data: TableDataRef<'a, Cmap2FixedHeader>,
583
}
584
585
#[allow(clippy::needless_lifetimes)]
586
impl<'a> Cmap2<'a> {
587
    pub const MIN_SIZE: usize =
588
        (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN * 256_usize);
589
    basic_table_impls!(impl_the_methods);
590
591
    /// Format number is set to 2.
592
0
    pub fn format(&self) -> u16 {
593
0
        self.data.header().format.get()
594
0
    }
595
596
    /// This is the length in bytes of the subtable.
597
0
    pub fn length(&self) -> u16 {
598
0
        self.data.header().length.get()
599
0
    }
600
601
    /// For requirements on use of the language field, see “Use of
602
    /// the language field in 'cmap' subtables” in this document.
603
0
    pub fn language(&self) -> u16 {
604
0
        self.data.header().language.get()
605
0
    }
606
607
    /// Array that maps high bytes to subHeaders: value is subHeader
608
    /// index × 8.
609
0
    pub fn sub_header_keys(&self) -> &'a [BigEndian<u16>] {
610
0
        let range = self.sub_header_keys_byte_range();
611
0
        self.offset_data()
612
0
            .read_array(range)
613
0
            .ok()
614
0
            .unwrap_or_default()
615
0
    }
616
617
0
    pub fn format_byte_range(&self) -> Range<usize> {
618
0
        let start = 0;
619
0
        let end = start + u16::RAW_BYTE_LEN;
620
0
        start..end
621
0
    }
622
623
0
    pub fn length_byte_range(&self) -> Range<usize> {
624
0
        let start = self.format_byte_range().end;
625
0
        let end = start + u16::RAW_BYTE_LEN;
626
0
        start..end
627
0
    }
628
629
0
    pub fn language_byte_range(&self) -> Range<usize> {
630
0
        let start = self.length_byte_range().end;
631
0
        let end = start + u16::RAW_BYTE_LEN;
632
0
        start..end
633
0
    }
634
635
0
    pub fn sub_header_keys_byte_range(&self) -> Range<usize> {
636
0
        let start = self.language_byte_range().end;
637
0
        let end = start + (256_usize).saturating_mul(u16::RAW_BYTE_LEN);
638
0
        start..end
639
0
    }
640
}
641
642
/// Part of [Cmap2]
643
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
644
#[repr(C)]
645
#[repr(packed)]
646
pub struct SubHeader {
647
    /// First valid low byte for this SubHeader.
648
    pub first_code: BigEndian<u16>,
649
    /// Number of valid low bytes for this SubHeader.
650
    pub entry_count: BigEndian<u16>,
651
    /// See text below.
652
    pub id_delta: BigEndian<i16>,
653
    /// See text below.
654
    pub id_range_offset: BigEndian<u16>,
655
}
656
657
impl SubHeader {
658
    /// First valid low byte for this SubHeader.
659
0
    pub fn first_code(&self) -> u16 {
660
0
        self.first_code.get()
661
0
    }
662
663
    /// Number of valid low bytes for this SubHeader.
664
0
    pub fn entry_count(&self) -> u16 {
665
0
        self.entry_count.get()
666
0
    }
667
668
    /// See text below.
669
0
    pub fn id_delta(&self) -> i16 {
670
0
        self.id_delta.get()
671
0
    }
672
673
    /// See text below.
674
0
    pub fn id_range_offset(&self) -> u16 {
675
0
        self.id_range_offset.get()
676
0
    }
677
}
678
679
impl FixedSize for SubHeader {
680
    const RAW_BYTE_LEN: usize =
681
        u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
682
}
683
684
impl Format<u16> for Cmap4<'_> {
685
    const FORMAT: u16 = 4;
686
}
687
688
impl<'a> MinByteRange<'a> for Cmap4<'a> {
689
0
    fn min_byte_range(&self) -> Range<usize> {
690
0
        0..self.glyph_id_array_byte_range().end
691
0
    }
692
0
    fn min_table_bytes(&self) -> &'a [u8] {
693
0
        let range = self.min_byte_range();
694
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
695
0
    }
696
}
697
698
impl ReadArgs for Cmap4<'_> {
699
    type Args = ();
700
}
701
702
impl<'a> FontRead<'a> for Cmap4<'a> {
703
436
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
704
        #[allow(clippy::absurd_extreme_comparisons)]
705
436
        if data.len() < Self::MIN_SIZE {
706
10
            return Err(ReadError::OutOfBounds);
707
426
        }
708
426
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
709
0
            return Err(ReadError::OutOfBounds);
710
        };
711
426
        Ok(Self { data })
712
436
    }
713
}
714
715
/// The fields at the start of the table, which are read directly.
716
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
717
#[repr(C, packed)]
718
#[doc(hidden)]
719
pub struct Cmap4FixedHeader {
720
    pub format: BigEndian<u16>,
721
    pub length: BigEndian<u16>,
722
    pub language: BigEndian<u16>,
723
    pub seg_count_x2: BigEndian<u16>,
724
    pub search_range: BigEndian<u16>,
725
    pub entry_selector: BigEndian<u16>,
726
    pub range_shift: BigEndian<u16>,
727
}
728
729
#[allow(clippy::absurd_extreme_comparisons)]
730
const _: () = assert!(std::mem::size_of::<Cmap4FixedHeader>() <= Cmap4::MIN_SIZE);
731
732
/// [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
733
#[derive(Clone)]
734
pub struct Cmap4<'a> {
735
    data: TableDataRef<'a, Cmap4FixedHeader>,
736
}
737
738
#[allow(clippy::needless_lifetimes)]
739
impl<'a> Cmap4<'a> {
740
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
741
        + u16::RAW_BYTE_LEN
742
        + u16::RAW_BYTE_LEN
743
        + u16::RAW_BYTE_LEN
744
        + u16::RAW_BYTE_LEN
745
        + u16::RAW_BYTE_LEN
746
        + u16::RAW_BYTE_LEN
747
        + u16::RAW_BYTE_LEN);
748
    basic_table_impls!(impl_the_methods);
749
750
    /// Format number is set to 4.
751
0
    pub fn format(&self) -> u16 {
752
0
        self.data.header().format.get()
753
0
    }
754
755
    /// This is the length in bytes of the subtable.
756
0
    pub fn length(&self) -> u16 {
757
0
        self.data.header().length.get()
758
0
    }
759
760
    /// For requirements on use of the language field, see “Use of
761
    /// the language field in 'cmap' subtables” in this document.
762
0
    pub fn language(&self) -> u16 {
763
0
        self.data.header().language.get()
764
0
    }
765
766
    /// 2 × segCount.
767
556k
    pub fn seg_count_x2(&self) -> u16 {
768
556k
        self.data.header().seg_count_x2.get()
769
556k
    }
770
771
    /// Maximum power of 2 less than or equal to segCount, times 2
772
    /// ((2**floor(log2(segCount))) * 2, where “**” is an
773
    /// exponentiation operator)
774
0
    pub fn search_range(&self) -> u16 {
775
0
        self.data.header().search_range.get()
776
0
    }
777
778
    /// Log2 of the maximum power of 2 less than or equal to numTables
779
    /// (log2(searchRange/2), which is equal to floor(log2(segCount)))
780
0
    pub fn entry_selector(&self) -> u16 {
781
0
        self.data.header().entry_selector.get()
782
0
    }
783
784
    /// segCount times 2, minus searchRange ((segCount * 2) -
785
    /// searchRange)
786
0
    pub fn range_shift(&self) -> u16 {
787
0
        self.data.header().range_shift.get()
788
0
    }
789
790
    /// End characterCode for each segment, last=0xFFFF.
791
52.4k
    pub fn end_code(&self) -> &'a [BigEndian<u16>] {
792
52.4k
        let range = self.end_code_byte_range();
793
52.4k
        self.offset_data()
794
52.4k
            .read_array(range)
795
52.4k
            .ok()
796
52.4k
            .unwrap_or_default()
797
52.4k
    }
798
799
    /// Start character code for each segment.
800
52.4k
    pub fn start_code(&self) -> &'a [BigEndian<u16>] {
801
52.4k
        let range = self.start_code_byte_range();
802
52.4k
        self.offset_data()
803
52.4k
            .read_array(range)
804
52.4k
            .ok()
805
52.4k
            .unwrap_or_default()
806
52.4k
    }
807
808
    /// Delta for all character codes in segment.
809
39.7k
    pub fn id_delta(&self) -> &'a [BigEndian<i16>] {
810
39.7k
        let range = self.id_delta_byte_range();
811
39.7k
        self.offset_data()
812
39.7k
            .read_array(range)
813
39.7k
            .ok()
814
39.7k
            .unwrap_or_default()
815
39.7k
    }
816
817
    /// Offsets into glyphIdArray or 0
818
39.7k
    pub fn id_range_offsets(&self) -> &'a [BigEndian<u16>] {
819
39.7k
        let range = self.id_range_offsets_byte_range();
820
39.7k
        self.offset_data()
821
39.7k
            .read_array(range)
822
39.7k
            .ok()
823
39.7k
            .unwrap_or_default()
824
39.7k
    }
825
826
    /// Glyph index array (arbitrary length)
827
16.8k
    pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
828
16.8k
        let range = self.glyph_id_array_byte_range();
829
16.8k
        self.offset_data()
830
16.8k
            .read_array(range)
831
16.8k
            .ok()
832
16.8k
            .unwrap_or_default()
833
16.8k
    }
834
835
201k
    pub fn format_byte_range(&self) -> Range<usize> {
836
201k
        let start = 0;
837
201k
        let end = start + u16::RAW_BYTE_LEN;
838
201k
        start..end
839
201k
    }
840
841
201k
    pub fn length_byte_range(&self) -> Range<usize> {
842
201k
        let start = self.format_byte_range().end;
843
201k
        let end = start + u16::RAW_BYTE_LEN;
844
201k
        start..end
845
201k
    }
846
847
201k
    pub fn language_byte_range(&self) -> Range<usize> {
848
201k
        let start = self.length_byte_range().end;
849
201k
        let end = start + u16::RAW_BYTE_LEN;
850
201k
        start..end
851
201k
    }
852
853
201k
    pub fn seg_count_x2_byte_range(&self) -> Range<usize> {
854
201k
        let start = self.language_byte_range().end;
855
201k
        let end = start + u16::RAW_BYTE_LEN;
856
201k
        start..end
857
201k
    }
858
859
201k
    pub fn search_range_byte_range(&self) -> Range<usize> {
860
201k
        let start = self.seg_count_x2_byte_range().end;
861
201k
        let end = start + u16::RAW_BYTE_LEN;
862
201k
        start..end
863
201k
    }
864
865
201k
    pub fn entry_selector_byte_range(&self) -> Range<usize> {
866
201k
        let start = self.search_range_byte_range().end;
867
201k
        let end = start + u16::RAW_BYTE_LEN;
868
201k
        start..end
869
201k
    }
870
871
201k
    pub fn range_shift_byte_range(&self) -> Range<usize> {
872
201k
        let start = self.entry_selector_byte_range().end;
873
201k
        let end = start + u16::RAW_BYTE_LEN;
874
201k
        start..end
875
201k
    }
876
877
201k
    pub fn end_code_byte_range(&self) -> Range<usize> {
878
201k
        let seg_count_x2 = self.seg_count_x2();
879
201k
        let start = self.range_shift_byte_range().end;
880
201k
        let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
881
201k
        start..end
882
201k
    }
883
884
148k
    pub fn reserved_pad_byte_range(&self) -> Range<usize> {
885
148k
        let start = self.end_code_byte_range().end;
886
148k
        let end = start + u16::RAW_BYTE_LEN;
887
148k
        start..end
888
148k
    }
889
890
148k
    pub fn start_code_byte_range(&self) -> Range<usize> {
891
148k
        let seg_count_x2 = self.seg_count_x2();
892
148k
        let start = self.reserved_pad_byte_range().end;
893
148k
        let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
894
148k
        start..end
895
148k
    }
896
897
96.4k
    pub fn id_delta_byte_range(&self) -> Range<usize> {
898
96.4k
        let seg_count_x2 = self.seg_count_x2();
899
96.4k
        let start = self.start_code_byte_range().end;
900
96.4k
        let end = start + (transforms::half(seg_count_x2)).saturating_mul(i16::RAW_BYTE_LEN);
901
96.4k
        start..end
902
96.4k
    }
903
904
56.6k
    pub fn id_range_offsets_byte_range(&self) -> Range<usize> {
905
56.6k
        let seg_count_x2 = self.seg_count_x2();
906
56.6k
        let start = self.id_delta_byte_range().end;
907
56.6k
        let end = start + (transforms::half(seg_count_x2)).saturating_mul(u16::RAW_BYTE_LEN);
908
56.6k
        start..end
909
56.6k
    }
910
911
16.8k
    pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
912
16.8k
        let start = self.id_range_offsets_byte_range().end;
913
16.8k
        let end = start
914
16.8k
            + self.offset_data().len().saturating_sub(start) / u16::RAW_BYTE_LEN
915
16.8k
                * u16::RAW_BYTE_LEN;
916
16.8k
        start..end
917
16.8k
    }
918
}
919
920
impl Format<u16> for Cmap6<'_> {
921
    const FORMAT: u16 = 6;
922
}
923
924
impl<'a> MinByteRange<'a> for Cmap6<'a> {
925
0
    fn min_byte_range(&self) -> Range<usize> {
926
0
        0..self.glyph_id_array_byte_range().end
927
0
    }
928
0
    fn min_table_bytes(&self) -> &'a [u8] {
929
0
        let range = self.min_byte_range();
930
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
931
0
    }
932
}
933
934
impl ReadArgs for Cmap6<'_> {
935
    type Args = ();
936
}
937
938
impl<'a> FontRead<'a> for Cmap6<'a> {
939
159
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
940
        #[allow(clippy::absurd_extreme_comparisons)]
941
159
        if data.len() < Self::MIN_SIZE {
942
10
            return Err(ReadError::OutOfBounds);
943
149
        }
944
149
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
945
0
            return Err(ReadError::OutOfBounds);
946
        };
947
149
        Ok(Self { data })
948
159
    }
949
}
950
951
/// The fields at the start of the table, which are read directly.
952
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
953
#[repr(C, packed)]
954
#[doc(hidden)]
955
pub struct Cmap6FixedHeader {
956
    pub format: BigEndian<u16>,
957
    pub length: BigEndian<u16>,
958
    pub language: BigEndian<u16>,
959
    pub first_code: BigEndian<u16>,
960
    pub entry_count: BigEndian<u16>,
961
}
962
963
#[allow(clippy::absurd_extreme_comparisons)]
964
const _: () = assert!(std::mem::size_of::<Cmap6FixedHeader>() <= Cmap6::MIN_SIZE);
965
966
/// [cmap Format 6](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-6-trimmed-table-mapping): Trimmed table mapping
967
#[derive(Clone)]
968
pub struct Cmap6<'a> {
969
    data: TableDataRef<'a, Cmap6FixedHeader>,
970
}
971
972
#[allow(clippy::needless_lifetimes)]
973
impl<'a> Cmap6<'a> {
974
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
975
        + u16::RAW_BYTE_LEN
976
        + u16::RAW_BYTE_LEN
977
        + u16::RAW_BYTE_LEN
978
        + u16::RAW_BYTE_LEN);
979
    basic_table_impls!(impl_the_methods);
980
981
    /// Format number is set to 6.
982
0
    pub fn format(&self) -> u16 {
983
0
        self.data.header().format.get()
984
0
    }
985
986
    /// This is the length in bytes of the subtable.
987
0
    pub fn length(&self) -> u16 {
988
0
        self.data.header().length.get()
989
0
    }
990
991
    /// For requirements on use of the language field, see “Use of
992
    /// the language field in 'cmap' subtables” in this document.
993
0
    pub fn language(&self) -> u16 {
994
0
        self.data.header().language.get()
995
0
    }
996
997
    /// First character code of subrange.
998
8.24k
    pub fn first_code(&self) -> u16 {
999
8.24k
        self.data.header().first_code.get()
1000
8.24k
    }
1001
1002
    /// Number of character codes in subrange.
1003
6.74k
    pub fn entry_count(&self) -> u16 {
1004
6.74k
        self.data.header().entry_count.get()
1005
6.74k
    }
1006
1007
    /// Array of glyph index values for character codes in the range.
1008
6.74k
    pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
1009
6.74k
        let range = self.glyph_id_array_byte_range();
1010
6.74k
        self.offset_data()
1011
6.74k
            .read_array(range)
1012
6.74k
            .ok()
1013
6.74k
            .unwrap_or_default()
1014
6.74k
    }
1015
1016
6.74k
    pub fn format_byte_range(&self) -> Range<usize> {
1017
6.74k
        let start = 0;
1018
6.74k
        let end = start + u16::RAW_BYTE_LEN;
1019
6.74k
        start..end
1020
6.74k
    }
1021
1022
6.74k
    pub fn length_byte_range(&self) -> Range<usize> {
1023
6.74k
        let start = self.format_byte_range().end;
1024
6.74k
        let end = start + u16::RAW_BYTE_LEN;
1025
6.74k
        start..end
1026
6.74k
    }
1027
1028
6.74k
    pub fn language_byte_range(&self) -> Range<usize> {
1029
6.74k
        let start = self.length_byte_range().end;
1030
6.74k
        let end = start + u16::RAW_BYTE_LEN;
1031
6.74k
        start..end
1032
6.74k
    }
1033
1034
6.74k
    pub fn first_code_byte_range(&self) -> Range<usize> {
1035
6.74k
        let start = self.language_byte_range().end;
1036
6.74k
        let end = start + u16::RAW_BYTE_LEN;
1037
6.74k
        start..end
1038
6.74k
    }
1039
1040
6.74k
    pub fn entry_count_byte_range(&self) -> Range<usize> {
1041
6.74k
        let start = self.first_code_byte_range().end;
1042
6.74k
        let end = start + u16::RAW_BYTE_LEN;
1043
6.74k
        start..end
1044
6.74k
    }
1045
1046
6.74k
    pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
1047
6.74k
        let entry_count = self.entry_count();
1048
6.74k
        let start = self.entry_count_byte_range().end;
1049
6.74k
        let end = start + (transforms::to_usize(entry_count)).saturating_mul(u16::RAW_BYTE_LEN);
1050
6.74k
        start..end
1051
6.74k
    }
1052
}
1053
1054
impl Format<u16> for Cmap8<'_> {
1055
    const FORMAT: u16 = 8;
1056
}
1057
1058
impl<'a> MinByteRange<'a> for Cmap8<'a> {
1059
0
    fn min_byte_range(&self) -> Range<usize> {
1060
0
        0..self.groups_byte_range().end
1061
0
    }
1062
0
    fn min_table_bytes(&self) -> &'a [u8] {
1063
0
        let range = self.min_byte_range();
1064
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1065
0
    }
1066
}
1067
1068
impl ReadArgs for Cmap8<'_> {
1069
    type Args = ();
1070
}
1071
1072
impl<'a> FontRead<'a> for Cmap8<'a> {
1073
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1074
        #[allow(clippy::absurd_extreme_comparisons)]
1075
0
        if data.len() < Self::MIN_SIZE {
1076
0
            return Err(ReadError::OutOfBounds);
1077
0
        }
1078
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1079
0
            return Err(ReadError::OutOfBounds);
1080
        };
1081
0
        Ok(Self { data })
1082
0
    }
1083
}
1084
1085
/// The fields at the start of the table, which are read directly.
1086
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1087
#[repr(C, packed)]
1088
#[doc(hidden)]
1089
pub struct Cmap8FixedHeader {
1090
    pub format: BigEndian<u16>,
1091
    pub reserved: BigEndian<u16>,
1092
    pub length: BigEndian<u32>,
1093
    pub language: BigEndian<u32>,
1094
}
1095
1096
#[allow(clippy::absurd_extreme_comparisons)]
1097
const _: () = assert!(std::mem::size_of::<Cmap8FixedHeader>() <= Cmap8::MIN_SIZE);
1098
1099
/// [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
1100
#[derive(Clone)]
1101
pub struct Cmap8<'a> {
1102
    data: TableDataRef<'a, Cmap8FixedHeader>,
1103
}
1104
1105
#[allow(clippy::needless_lifetimes)]
1106
impl<'a> Cmap8<'a> {
1107
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1108
        + u16::RAW_BYTE_LEN
1109
        + u32::RAW_BYTE_LEN
1110
        + u32::RAW_BYTE_LEN
1111
        + u8::RAW_BYTE_LEN * 8192_usize
1112
        + u32::RAW_BYTE_LEN);
1113
    basic_table_impls!(impl_the_methods);
1114
1115
    /// Subtable format; set to 8.
1116
0
    pub fn format(&self) -> u16 {
1117
0
        self.data.header().format.get()
1118
0
    }
1119
1120
    /// Byte length of this subtable (including the header)
1121
0
    pub fn length(&self) -> u32 {
1122
0
        self.data.header().length.get()
1123
0
    }
1124
1125
    /// For requirements on use of the language field, see “Use of
1126
    /// the language field in 'cmap' subtables” in this document.
1127
0
    pub fn language(&self) -> u32 {
1128
0
        self.data.header().language.get()
1129
0
    }
1130
1131
    /// Tightly packed array of bits (8K bytes total) indicating
1132
    /// whether the particular 16-bit (index) value is the start of a
1133
    /// 32-bit character code
1134
0
    pub fn is32(&self) -> &'a [u8] {
1135
0
        let range = self.is32_byte_range();
1136
0
        self.offset_data()
1137
0
            .read_array(range)
1138
0
            .ok()
1139
0
            .unwrap_or_default()
1140
0
    }
1141
1142
    /// Number of groupings which follow
1143
0
    pub fn num_groups(&self) -> u32 {
1144
0
        let range = self.num_groups_byte_range();
1145
0
        self.offset_data()
1146
0
            .read_at(range.start)
1147
0
            .ok()
1148
0
            .unwrap_or_default()
1149
0
    }
1150
1151
    /// Array of SequentialMapGroup records.
1152
0
    pub fn groups(&self) -> &'a [SequentialMapGroup] {
1153
0
        let range = self.groups_byte_range();
1154
0
        self.offset_data()
1155
0
            .read_array(range)
1156
0
            .ok()
1157
0
            .unwrap_or_default()
1158
0
    }
1159
1160
0
    pub fn format_byte_range(&self) -> Range<usize> {
1161
0
        let start = 0;
1162
0
        let end = start + u16::RAW_BYTE_LEN;
1163
0
        start..end
1164
0
    }
1165
1166
0
    pub fn reserved_byte_range(&self) -> Range<usize> {
1167
0
        let start = self.format_byte_range().end;
1168
0
        let end = start + u16::RAW_BYTE_LEN;
1169
0
        start..end
1170
0
    }
1171
1172
0
    pub fn length_byte_range(&self) -> Range<usize> {
1173
0
        let start = self.reserved_byte_range().end;
1174
0
        let end = start + u32::RAW_BYTE_LEN;
1175
0
        start..end
1176
0
    }
1177
1178
0
    pub fn language_byte_range(&self) -> Range<usize> {
1179
0
        let start = self.length_byte_range().end;
1180
0
        let end = start + u32::RAW_BYTE_LEN;
1181
0
        start..end
1182
0
    }
1183
1184
0
    pub fn is32_byte_range(&self) -> Range<usize> {
1185
0
        let start = self.language_byte_range().end;
1186
0
        let end = start + (8192_usize).saturating_mul(u8::RAW_BYTE_LEN);
1187
0
        start..end
1188
0
    }
1189
1190
0
    pub fn num_groups_byte_range(&self) -> Range<usize> {
1191
0
        let start = self.is32_byte_range().end;
1192
0
        let end = start + u32::RAW_BYTE_LEN;
1193
0
        start..end
1194
0
    }
1195
1196
0
    pub fn groups_byte_range(&self) -> Range<usize> {
1197
0
        let num_groups = self.num_groups();
1198
0
        let start = self.num_groups_byte_range().end;
1199
0
        let end = start
1200
0
            + (transforms::to_usize(num_groups)).saturating_mul(SequentialMapGroup::RAW_BYTE_LEN);
1201
0
        start..end
1202
0
    }
1203
}
1204
1205
/// Used in [Cmap8] and [Cmap12]
1206
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1207
#[repr(C)]
1208
#[repr(packed)]
1209
pub struct SequentialMapGroup {
1210
    /// First character code in this group; note that if this group is
1211
    /// for one or more 16-bit character codes (which is determined
1212
    /// from the is32 array), this 32-bit value will have the high
1213
    /// 16-bits set to zero
1214
    pub start_char_code: BigEndian<u32>,
1215
    /// Last character code in this group; same condition as listed
1216
    /// above for the startCharCode
1217
    pub end_char_code: BigEndian<u32>,
1218
    /// Glyph index corresponding to the starting character code
1219
    pub start_glyph_id: BigEndian<u32>,
1220
}
1221
1222
impl SequentialMapGroup {
1223
    /// First character code in this group; note that if this group is
1224
    /// for one or more 16-bit character codes (which is determined
1225
    /// from the is32 array), this 32-bit value will have the high
1226
    /// 16-bits set to zero
1227
87.4k
    pub fn start_char_code(&self) -> u32 {
1228
87.4k
        self.start_char_code.get()
1229
87.4k
    }
1230
1231
    /// Last character code in this group; same condition as listed
1232
    /// above for the startCharCode
1233
57.7k
    pub fn end_char_code(&self) -> u32 {
1234
57.7k
        self.end_char_code.get()
1235
57.7k
    }
1236
1237
    /// Glyph index corresponding to the starting character code
1238
29.7k
    pub fn start_glyph_id(&self) -> u32 {
1239
29.7k
        self.start_glyph_id.get()
1240
29.7k
    }
1241
}
1242
1243
impl FixedSize for SequentialMapGroup {
1244
    const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1245
}
1246
1247
impl Format<u16> for Cmap10<'_> {
1248
    const FORMAT: u16 = 10;
1249
}
1250
1251
impl<'a> MinByteRange<'a> for Cmap10<'a> {
1252
0
    fn min_byte_range(&self) -> Range<usize> {
1253
0
        0..self.glyph_id_array_byte_range().end
1254
0
    }
1255
0
    fn min_table_bytes(&self) -> &'a [u8] {
1256
0
        let range = self.min_byte_range();
1257
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1258
0
    }
1259
}
1260
1261
impl ReadArgs for Cmap10<'_> {
1262
    type Args = ();
1263
}
1264
1265
impl<'a> FontRead<'a> for Cmap10<'a> {
1266
94
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1267
        #[allow(clippy::absurd_extreme_comparisons)]
1268
94
        if data.len() < Self::MIN_SIZE {
1269
10
            return Err(ReadError::OutOfBounds);
1270
84
        }
1271
84
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1272
0
            return Err(ReadError::OutOfBounds);
1273
        };
1274
84
        Ok(Self { data })
1275
94
    }
1276
}
1277
1278
/// The fields at the start of the table, which are read directly.
1279
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1280
#[repr(C, packed)]
1281
#[doc(hidden)]
1282
pub struct Cmap10FixedHeader {
1283
    pub format: BigEndian<u16>,
1284
    pub reserved: BigEndian<u16>,
1285
    pub length: BigEndian<u32>,
1286
    pub language: BigEndian<u32>,
1287
    pub start_char_code: BigEndian<u32>,
1288
    pub num_chars: BigEndian<u32>,
1289
}
1290
1291
#[allow(clippy::absurd_extreme_comparisons)]
1292
const _: () = assert!(std::mem::size_of::<Cmap10FixedHeader>() <= Cmap10::MIN_SIZE);
1293
1294
/// [cmap Format 10](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-10-trimmed-array): Tr
1295
#[derive(Clone)]
1296
pub struct Cmap10<'a> {
1297
    data: TableDataRef<'a, Cmap10FixedHeader>,
1298
}
1299
1300
#[allow(clippy::needless_lifetimes)]
1301
impl<'a> Cmap10<'a> {
1302
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1303
        + u16::RAW_BYTE_LEN
1304
        + u32::RAW_BYTE_LEN
1305
        + u32::RAW_BYTE_LEN
1306
        + u32::RAW_BYTE_LEN
1307
        + u32::RAW_BYTE_LEN);
1308
    basic_table_impls!(impl_the_methods);
1309
1310
    /// Subtable format; set to 10.
1311
0
    pub fn format(&self) -> u16 {
1312
0
        self.data.header().format.get()
1313
0
    }
1314
1315
    /// Byte length of this subtable (including the header)
1316
0
    pub fn length(&self) -> u32 {
1317
0
        self.data.header().length.get()
1318
0
    }
1319
1320
    /// For requirements on use of the language field, see “Use of
1321
    /// the language field in 'cmap' subtables” in this document.
1322
0
    pub fn language(&self) -> u32 {
1323
0
        self.data.header().language.get()
1324
0
    }
1325
1326
    /// First character code covered
1327
2.86k
    pub fn start_char_code(&self) -> u32 {
1328
2.86k
        self.data.header().start_char_code.get()
1329
2.86k
    }
1330
1331
    /// Number of character codes covered
1332
1.37k
    pub fn num_chars(&self) -> u32 {
1333
1.37k
        self.data.header().num_chars.get()
1334
1.37k
    }
1335
1336
    /// Array of glyph indices for the character codes covered
1337
1.37k
    pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
1338
1.37k
        let range = self.glyph_id_array_byte_range();
1339
1.37k
        self.offset_data()
1340
1.37k
            .read_array(range)
1341
1.37k
            .ok()
1342
1.37k
            .unwrap_or_default()
1343
1.37k
    }
1344
1345
1.37k
    pub fn format_byte_range(&self) -> Range<usize> {
1346
1.37k
        let start = 0;
1347
1.37k
        let end = start + u16::RAW_BYTE_LEN;
1348
1.37k
        start..end
1349
1.37k
    }
1350
1351
1.37k
    pub fn reserved_byte_range(&self) -> Range<usize> {
1352
1.37k
        let start = self.format_byte_range().end;
1353
1.37k
        let end = start + u16::RAW_BYTE_LEN;
1354
1.37k
        start..end
1355
1.37k
    }
1356
1357
1.37k
    pub fn length_byte_range(&self) -> Range<usize> {
1358
1.37k
        let start = self.reserved_byte_range().end;
1359
1.37k
        let end = start + u32::RAW_BYTE_LEN;
1360
1.37k
        start..end
1361
1.37k
    }
1362
1363
1.37k
    pub fn language_byte_range(&self) -> Range<usize> {
1364
1.37k
        let start = self.length_byte_range().end;
1365
1.37k
        let end = start + u32::RAW_BYTE_LEN;
1366
1.37k
        start..end
1367
1.37k
    }
1368
1369
1.37k
    pub fn start_char_code_byte_range(&self) -> Range<usize> {
1370
1.37k
        let start = self.language_byte_range().end;
1371
1.37k
        let end = start + u32::RAW_BYTE_LEN;
1372
1.37k
        start..end
1373
1.37k
    }
1374
1375
1.37k
    pub fn num_chars_byte_range(&self) -> Range<usize> {
1376
1.37k
        let start = self.start_char_code_byte_range().end;
1377
1.37k
        let end = start + u32::RAW_BYTE_LEN;
1378
1.37k
        start..end
1379
1.37k
    }
1380
1381
1.37k
    pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
1382
1.37k
        let num_chars = self.num_chars();
1383
1.37k
        let start = self.num_chars_byte_range().end;
1384
1.37k
        let end = start + (transforms::to_usize(num_chars)).saturating_mul(u16::RAW_BYTE_LEN);
1385
1.37k
        start..end
1386
1.37k
    }
1387
}
1388
1389
impl Format<u16> for Cmap12<'_> {
1390
    const FORMAT: u16 = 12;
1391
}
1392
1393
impl<'a> MinByteRange<'a> for Cmap12<'a> {
1394
0
    fn min_byte_range(&self) -> Range<usize> {
1395
0
        0..self.groups_byte_range().end
1396
0
    }
1397
0
    fn min_table_bytes(&self) -> &'a [u8] {
1398
0
        let range = self.min_byte_range();
1399
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1400
0
    }
1401
}
1402
1403
impl ReadArgs for Cmap12<'_> {
1404
    type Args = ();
1405
}
1406
1407
impl<'a> FontRead<'a> for Cmap12<'a> {
1408
259
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1409
        #[allow(clippy::absurd_extreme_comparisons)]
1410
259
        if data.len() < Self::MIN_SIZE {
1411
16
            return Err(ReadError::OutOfBounds);
1412
243
        }
1413
243
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1414
0
            return Err(ReadError::OutOfBounds);
1415
        };
1416
243
        Ok(Self { data })
1417
259
    }
1418
}
1419
1420
/// The fields at the start of the table, which are read directly.
1421
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1422
#[repr(C, packed)]
1423
#[doc(hidden)]
1424
pub struct Cmap12FixedHeader {
1425
    pub format: BigEndian<u16>,
1426
    pub reserved: BigEndian<u16>,
1427
    pub length: BigEndian<u32>,
1428
    pub language: BigEndian<u32>,
1429
    pub num_groups: BigEndian<u32>,
1430
}
1431
1432
#[allow(clippy::absurd_extreme_comparisons)]
1433
const _: () = assert!(std::mem::size_of::<Cmap12FixedHeader>() <= Cmap12::MIN_SIZE);
1434
1435
/// [cmap Format 12](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage): Segmented coverage
1436
#[derive(Clone)]
1437
pub struct Cmap12<'a> {
1438
    data: TableDataRef<'a, Cmap12FixedHeader>,
1439
}
1440
1441
#[allow(clippy::needless_lifetimes)]
1442
impl<'a> Cmap12<'a> {
1443
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1444
        + u16::RAW_BYTE_LEN
1445
        + u32::RAW_BYTE_LEN
1446
        + u32::RAW_BYTE_LEN
1447
        + u32::RAW_BYTE_LEN);
1448
    basic_table_impls!(impl_the_methods);
1449
1450
    /// Subtable format; set to 12.
1451
0
    pub fn format(&self) -> u16 {
1452
0
        self.data.header().format.get()
1453
0
    }
1454
1455
    /// Byte length of this subtable (including the header)
1456
0
    pub fn length(&self) -> u32 {
1457
0
        self.data.header().length.get()
1458
0
    }
1459
1460
    /// For requirements on use of the language field, see “Use of
1461
    /// the language field in 'cmap' subtables” in this document.
1462
0
    pub fn language(&self) -> u32 {
1463
0
        self.data.header().language.get()
1464
0
    }
1465
1466
    /// Number of groupings which follow
1467
38.8k
    pub fn num_groups(&self) -> u32 {
1468
38.8k
        self.data.header().num_groups.get()
1469
38.8k
    }
1470
1471
    /// Array of SequentialMapGroup records.
1472
38.8k
    pub fn groups(&self) -> &'a [SequentialMapGroup] {
1473
38.8k
        let range = self.groups_byte_range();
1474
38.8k
        self.offset_data()
1475
38.8k
            .read_array(range)
1476
38.8k
            .ok()
1477
38.8k
            .unwrap_or_default()
1478
38.8k
    }
1479
1480
38.8k
    pub fn format_byte_range(&self) -> Range<usize> {
1481
38.8k
        let start = 0;
1482
38.8k
        let end = start + u16::RAW_BYTE_LEN;
1483
38.8k
        start..end
1484
38.8k
    }
1485
1486
38.8k
    pub fn reserved_byte_range(&self) -> Range<usize> {
1487
38.8k
        let start = self.format_byte_range().end;
1488
38.8k
        let end = start + u16::RAW_BYTE_LEN;
1489
38.8k
        start..end
1490
38.8k
    }
1491
1492
38.8k
    pub fn length_byte_range(&self) -> Range<usize> {
1493
38.8k
        let start = self.reserved_byte_range().end;
1494
38.8k
        let end = start + u32::RAW_BYTE_LEN;
1495
38.8k
        start..end
1496
38.8k
    }
1497
1498
38.8k
    pub fn language_byte_range(&self) -> Range<usize> {
1499
38.8k
        let start = self.length_byte_range().end;
1500
38.8k
        let end = start + u32::RAW_BYTE_LEN;
1501
38.8k
        start..end
1502
38.8k
    }
1503
1504
38.8k
    pub fn num_groups_byte_range(&self) -> Range<usize> {
1505
38.8k
        let start = self.language_byte_range().end;
1506
38.8k
        let end = start + u32::RAW_BYTE_LEN;
1507
38.8k
        start..end
1508
38.8k
    }
1509
1510
38.8k
    pub fn groups_byte_range(&self) -> Range<usize> {
1511
38.8k
        let num_groups = self.num_groups();
1512
38.8k
        let start = self.num_groups_byte_range().end;
1513
38.8k
        let end = start
1514
38.8k
            + (transforms::to_usize(num_groups)).saturating_mul(SequentialMapGroup::RAW_BYTE_LEN);
1515
38.8k
        start..end
1516
38.8k
    }
1517
}
1518
1519
impl Format<u16> for Cmap13<'_> {
1520
    const FORMAT: u16 = 13;
1521
}
1522
1523
impl<'a> MinByteRange<'a> for Cmap13<'a> {
1524
0
    fn min_byte_range(&self) -> Range<usize> {
1525
0
        0..self.groups_byte_range().end
1526
0
    }
1527
0
    fn min_table_bytes(&self) -> &'a [u8] {
1528
0
        let range = self.min_byte_range();
1529
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1530
0
    }
1531
}
1532
1533
impl ReadArgs for Cmap13<'_> {
1534
    type Args = ();
1535
}
1536
1537
impl<'a> FontRead<'a> for Cmap13<'a> {
1538
365
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1539
        #[allow(clippy::absurd_extreme_comparisons)]
1540
365
        if data.len() < Self::MIN_SIZE {
1541
10
            return Err(ReadError::OutOfBounds);
1542
355
        }
1543
355
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1544
0
            return Err(ReadError::OutOfBounds);
1545
        };
1546
355
        Ok(Self { data })
1547
365
    }
1548
}
1549
1550
/// The fields at the start of the table, which are read directly.
1551
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1552
#[repr(C, packed)]
1553
#[doc(hidden)]
1554
pub struct Cmap13FixedHeader {
1555
    pub format: BigEndian<u16>,
1556
    pub reserved: BigEndian<u16>,
1557
    pub length: BigEndian<u32>,
1558
    pub language: BigEndian<u32>,
1559
    pub num_groups: BigEndian<u32>,
1560
}
1561
1562
#[allow(clippy::absurd_extreme_comparisons)]
1563
const _: () = assert!(std::mem::size_of::<Cmap13FixedHeader>() <= Cmap13::MIN_SIZE);
1564
1565
/// [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
1566
#[derive(Clone)]
1567
pub struct Cmap13<'a> {
1568
    data: TableDataRef<'a, Cmap13FixedHeader>,
1569
}
1570
1571
#[allow(clippy::needless_lifetimes)]
1572
impl<'a> Cmap13<'a> {
1573
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1574
        + u16::RAW_BYTE_LEN
1575
        + u32::RAW_BYTE_LEN
1576
        + u32::RAW_BYTE_LEN
1577
        + u32::RAW_BYTE_LEN);
1578
    basic_table_impls!(impl_the_methods);
1579
1580
    /// Subtable format; set to 13.
1581
0
    pub fn format(&self) -> u16 {
1582
0
        self.data.header().format.get()
1583
0
    }
1584
1585
    /// Byte length of this subtable (including the header)
1586
0
    pub fn length(&self) -> u32 {
1587
0
        self.data.header().length.get()
1588
0
    }
1589
1590
    /// For requirements on use of the language field, see “Use of
1591
    /// the language field in 'cmap' subtables” in this document.
1592
0
    pub fn language(&self) -> u32 {
1593
0
        self.data.header().language.get()
1594
0
    }
1595
1596
    /// Number of groupings which follow
1597
82.7k
    pub fn num_groups(&self) -> u32 {
1598
82.7k
        self.data.header().num_groups.get()
1599
82.7k
    }
1600
1601
    /// Array of ConstantMapGroup records.
1602
82.7k
    pub fn groups(&self) -> &'a [ConstantMapGroup] {
1603
82.7k
        let range = self.groups_byte_range();
1604
82.7k
        self.offset_data()
1605
82.7k
            .read_array(range)
1606
82.7k
            .ok()
1607
82.7k
            .unwrap_or_default()
1608
82.7k
    }
1609
1610
82.7k
    pub fn format_byte_range(&self) -> Range<usize> {
1611
82.7k
        let start = 0;
1612
82.7k
        let end = start + u16::RAW_BYTE_LEN;
1613
82.7k
        start..end
1614
82.7k
    }
1615
1616
82.7k
    pub fn reserved_byte_range(&self) -> Range<usize> {
1617
82.7k
        let start = self.format_byte_range().end;
1618
82.7k
        let end = start + u16::RAW_BYTE_LEN;
1619
82.7k
        start..end
1620
82.7k
    }
1621
1622
82.7k
    pub fn length_byte_range(&self) -> Range<usize> {
1623
82.7k
        let start = self.reserved_byte_range().end;
1624
82.7k
        let end = start + u32::RAW_BYTE_LEN;
1625
82.7k
        start..end
1626
82.7k
    }
1627
1628
82.7k
    pub fn language_byte_range(&self) -> Range<usize> {
1629
82.7k
        let start = self.length_byte_range().end;
1630
82.7k
        let end = start + u32::RAW_BYTE_LEN;
1631
82.7k
        start..end
1632
82.7k
    }
1633
1634
82.7k
    pub fn num_groups_byte_range(&self) -> Range<usize> {
1635
82.7k
        let start = self.language_byte_range().end;
1636
82.7k
        let end = start + u32::RAW_BYTE_LEN;
1637
82.7k
        start..end
1638
82.7k
    }
1639
1640
82.7k
    pub fn groups_byte_range(&self) -> Range<usize> {
1641
82.7k
        let num_groups = self.num_groups();
1642
82.7k
        let start = self.num_groups_byte_range().end;
1643
82.7k
        let end = start
1644
82.7k
            + (transforms::to_usize(num_groups)).saturating_mul(ConstantMapGroup::RAW_BYTE_LEN);
1645
82.7k
        start..end
1646
82.7k
    }
1647
}
1648
1649
/// Part of [Cmap13]
1650
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1651
#[repr(C)]
1652
#[repr(packed)]
1653
pub struct ConstantMapGroup {
1654
    /// First character code in this group
1655
    pub start_char_code: BigEndian<u32>,
1656
    /// Last character code in this group
1657
    pub end_char_code: BigEndian<u32>,
1658
    /// Glyph index to be used for all the characters in the group’s
1659
    /// range.
1660
    pub glyph_id: BigEndian<u32>,
1661
}
1662
1663
impl ConstantMapGroup {
1664
    /// First character code in this group
1665
180k
    pub fn start_char_code(&self) -> u32 {
1666
180k
        self.start_char_code.get()
1667
180k
    }
1668
1669
    /// Last character code in this group
1670
118k
    pub fn end_char_code(&self) -> u32 {
1671
118k
        self.end_char_code.get()
1672
118k
    }
1673
1674
    /// Glyph index to be used for all the characters in the group’s
1675
    /// range.
1676
61.8k
    pub fn glyph_id(&self) -> u32 {
1677
61.8k
        self.glyph_id.get()
1678
61.8k
    }
1679
}
1680
1681
impl FixedSize for ConstantMapGroup {
1682
    const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
1683
}
1684
1685
impl Format<u16> for Cmap14<'_> {
1686
    const FORMAT: u16 = 14;
1687
}
1688
1689
impl<'a> MinByteRange<'a> for Cmap14<'a> {
1690
0
    fn min_byte_range(&self) -> Range<usize> {
1691
0
        0..self.var_selector_byte_range().end
1692
0
    }
1693
0
    fn min_table_bytes(&self) -> &'a [u8] {
1694
0
        let range = self.min_byte_range();
1695
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1696
0
    }
1697
}
1698
1699
impl ReadArgs for Cmap14<'_> {
1700
    type Args = ();
1701
}
1702
1703
impl<'a> FontRead<'a> for Cmap14<'a> {
1704
4
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1705
        #[allow(clippy::absurd_extreme_comparisons)]
1706
4
        if data.len() < Self::MIN_SIZE {
1707
0
            return Err(ReadError::OutOfBounds);
1708
4
        }
1709
4
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1710
0
            return Err(ReadError::OutOfBounds);
1711
        };
1712
4
        Ok(Self { data })
1713
4
    }
1714
}
1715
1716
/// The fields at the start of the table, which are read directly.
1717
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1718
#[repr(C, packed)]
1719
#[doc(hidden)]
1720
pub struct Cmap14FixedHeader {
1721
    pub format: BigEndian<u16>,
1722
    pub length: BigEndian<u32>,
1723
    pub num_var_selector_records: BigEndian<u32>,
1724
}
1725
1726
#[allow(clippy::absurd_extreme_comparisons)]
1727
const _: () = assert!(std::mem::size_of::<Cmap14FixedHeader>() <= Cmap14::MIN_SIZE);
1728
1729
/// [cmap Format 14](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-14-unicode-variation-sequences): Unicode Variation Sequences
1730
#[derive(Clone)]
1731
pub struct Cmap14<'a> {
1732
    data: TableDataRef<'a, Cmap14FixedHeader>,
1733
}
1734
1735
#[allow(clippy::needless_lifetimes)]
1736
impl<'a> Cmap14<'a> {
1737
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1738
    basic_table_impls!(impl_the_methods);
1739
1740
    /// Subtable format. Set to 14.
1741
0
    pub fn format(&self) -> u16 {
1742
0
        self.data.header().format.get()
1743
0
    }
1744
1745
    /// Byte length of this subtable (including this header)
1746
0
    pub fn length(&self) -> u32 {
1747
0
        self.data.header().length.get()
1748
0
    }
1749
1750
    /// Number of variation Selector Records
1751
1
    pub fn num_var_selector_records(&self) -> u32 {
1752
1
        self.data.header().num_var_selector_records.get()
1753
1
    }
1754
1755
    /// Array of VariationSelector records.
1756
1
    pub fn var_selector(&self) -> &'a [VariationSelector] {
1757
1
        let range = self.var_selector_byte_range();
1758
1
        self.offset_data()
1759
1
            .read_array(range)
1760
1
            .ok()
1761
1
            .unwrap_or_default()
1762
1
    }
1763
1764
1
    pub fn format_byte_range(&self) -> Range<usize> {
1765
1
        let start = 0;
1766
1
        let end = start + u16::RAW_BYTE_LEN;
1767
1
        start..end
1768
1
    }
1769
1770
1
    pub fn length_byte_range(&self) -> Range<usize> {
1771
1
        let start = self.format_byte_range().end;
1772
1
        let end = start + u32::RAW_BYTE_LEN;
1773
1
        start..end
1774
1
    }
1775
1776
1
    pub fn num_var_selector_records_byte_range(&self) -> Range<usize> {
1777
1
        let start = self.length_byte_range().end;
1778
1
        let end = start + u32::RAW_BYTE_LEN;
1779
1
        start..end
1780
1
    }
1781
1782
1
    pub fn var_selector_byte_range(&self) -> Range<usize> {
1783
1
        let num_var_selector_records = self.num_var_selector_records();
1784
1
        let start = self.num_var_selector_records_byte_range().end;
1785
1
        let end = start
1786
1
            + (transforms::to_usize(num_var_selector_records))
1787
1
                .saturating_mul(VariationSelector::RAW_BYTE_LEN);
1788
1
        start..end
1789
1
    }
1790
}
1791
1792
impl Format<u16> for Cmap15<'_> {
1793
    const FORMAT: u16 = 15;
1794
}
1795
1796
impl<'a> MinByteRange<'a> for Cmap15<'a> {
1797
0
    fn min_byte_range(&self) -> Range<usize> {
1798
0
        0..self.var_selector_byte_range().end
1799
0
    }
1800
0
    fn min_table_bytes(&self) -> &'a [u8] {
1801
0
        let range = self.min_byte_range();
1802
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1803
0
    }
1804
}
1805
1806
impl ReadArgs for Cmap15<'_> {
1807
    type Args = ();
1808
}
1809
1810
impl<'a> FontRead<'a> for Cmap15<'a> {
1811
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1812
        #[allow(clippy::absurd_extreme_comparisons)]
1813
0
        if data.len() < Self::MIN_SIZE {
1814
0
            return Err(ReadError::OutOfBounds);
1815
0
        }
1816
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1817
0
            return Err(ReadError::OutOfBounds);
1818
        };
1819
0
        Ok(Self { data })
1820
0
    }
1821
}
1822
1823
/// The fields at the start of the table, which are read directly.
1824
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1825
#[repr(C, packed)]
1826
#[doc(hidden)]
1827
pub struct Cmap15FixedHeader {
1828
    pub format: BigEndian<u16>,
1829
    pub length: BigEndian<u32>,
1830
    pub num_var_selector_records: BigEndian<u32>,
1831
}
1832
1833
#[allow(clippy::absurd_extreme_comparisons)]
1834
const _: () = assert!(std::mem::size_of::<Cmap15FixedHeader>() <= Cmap15::MIN_SIZE);
1835
1836
/// Extended glyph repertoire UVS mapping (ISO/IEC 14496-22:2026, 5.1.2.5.11).
1837
#[derive(Clone)]
1838
pub struct Cmap15<'a> {
1839
    data: TableDataRef<'a, Cmap15FixedHeader>,
1840
}
1841
1842
#[allow(clippy::needless_lifetimes)]
1843
impl<'a> Cmap15<'a> {
1844
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1845
    basic_table_impls!(impl_the_methods);
1846
1847
    /// Subtable format. Set to 15.
1848
0
    pub fn format(&self) -> u16 {
1849
0
        self.data.header().format.get()
1850
0
    }
1851
1852
    /// Byte length of this subtable (including this header).
1853
0
    pub fn length(&self) -> u32 {
1854
0
        self.data.header().length.get()
1855
0
    }
1856
1857
    /// Number of variation selector records.
1858
0
    pub fn num_var_selector_records(&self) -> u32 {
1859
0
        self.data.header().num_var_selector_records.get()
1860
0
    }
1861
1862
0
    pub fn var_selector(&self) -> &'a [VariationSelector15] {
1863
0
        let range = self.var_selector_byte_range();
1864
0
        self.offset_data()
1865
0
            .read_array(range)
1866
0
            .ok()
1867
0
            .unwrap_or_default()
1868
0
    }
1869
1870
0
    pub fn format_byte_range(&self) -> Range<usize> {
1871
0
        let start = 0;
1872
0
        let end = start + u16::RAW_BYTE_LEN;
1873
0
        start..end
1874
0
    }
1875
1876
0
    pub fn length_byte_range(&self) -> Range<usize> {
1877
0
        let start = self.format_byte_range().end;
1878
0
        let end = start + u32::RAW_BYTE_LEN;
1879
0
        start..end
1880
0
    }
1881
1882
0
    pub fn num_var_selector_records_byte_range(&self) -> Range<usize> {
1883
0
        let start = self.length_byte_range().end;
1884
0
        let end = start + u32::RAW_BYTE_LEN;
1885
0
        start..end
1886
0
    }
1887
1888
0
    pub fn var_selector_byte_range(&self) -> Range<usize> {
1889
0
        let num_var_selector_records = self.num_var_selector_records();
1890
0
        let start = self.num_var_selector_records_byte_range().end;
1891
0
        let end = start
1892
0
            + (transforms::to_usize(num_var_selector_records))
1893
0
                .saturating_mul(VariationSelector15::RAW_BYTE_LEN);
1894
0
        start..end
1895
0
    }
1896
}
1897
1898
/// Part of [Cmap15].
1899
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1900
#[repr(C)]
1901
#[repr(packed)]
1902
pub struct VariationSelector15 {
1903
    pub var_selector: BigEndian<Uint24>,
1904
    pub default_uvs_offset: BigEndian<Nullable<Offset32>>,
1905
    pub non_default_uvs_offset: BigEndian<Nullable<Offset32>>,
1906
}
1907
1908
impl VariationSelector15 {
1909
0
    pub fn var_selector(&self) -> Uint24 {
1910
0
        self.var_selector.get()
1911
0
    }
1912
1913
0
    pub fn default_uvs_offset(&self) -> Nullable<Offset32> {
1914
0
        self.default_uvs_offset.get()
1915
0
    }
1916
1917
    ///
1918
    /// The `data` argument should be retrieved from the parent table
1919
    /// By calling its `offset_data` method.
1920
0
    pub fn default_uvs<'a>(&self, data: FontData<'a>) -> Option<Result<DefaultUvs<'a>, ReadError>> {
1921
0
        self.default_uvs_offset().resolve(data)
1922
0
    }
1923
1924
0
    pub fn non_default_uvs_offset(&self) -> Nullable<Offset32> {
1925
0
        self.non_default_uvs_offset.get()
1926
0
    }
1927
1928
    ///
1929
    /// The `data` argument should be retrieved from the parent table
1930
    /// By calling its `offset_data` method.
1931
0
    pub fn non_default_uvs<'a>(
1932
0
        &self,
1933
0
        data: FontData<'a>,
1934
0
    ) -> Option<Result<NonDefaultUvs24<'a>, ReadError>> {
1935
0
        self.non_default_uvs_offset().resolve(data)
1936
0
    }
1937
}
1938
1939
impl FixedSize for VariationSelector15 {
1940
    const RAW_BYTE_LEN: usize =
1941
        Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
1942
}
1943
1944
/// Part of [Cmap14]
1945
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1946
#[repr(C)]
1947
#[repr(packed)]
1948
pub struct VariationSelector {
1949
    /// Variation selector
1950
    pub var_selector: BigEndian<Uint24>,
1951
    /// Offset from the start of the [`Cmap14`] subtable to Default UVS
1952
    /// Table. May be NULL.
1953
    pub default_uvs_offset: BigEndian<Nullable<Offset32>>,
1954
    /// Offset from the start of the [`Cmap14`] subtable to Non-Default
1955
    /// UVS Table. May be NULL.
1956
    pub non_default_uvs_offset: BigEndian<Nullable<Offset32>>,
1957
}
1958
1959
impl VariationSelector {
1960
    /// Variation selector
1961
0
    pub fn var_selector(&self) -> Uint24 {
1962
0
        self.var_selector.get()
1963
0
    }
1964
1965
    /// Offset from the start of the [`Cmap14`] subtable to Default UVS
1966
    /// Table. May be NULL.
1967
0
    pub fn default_uvs_offset(&self) -> Nullable<Offset32> {
1968
0
        self.default_uvs_offset.get()
1969
0
    }
1970
1971
    /// Offset from the start of the [`Cmap14`] subtable to Default UVS
1972
    /// Table. May be NULL.
1973
    ///
1974
    /// The `data` argument should be retrieved from the parent table
1975
    /// By calling its `offset_data` method.
1976
0
    pub fn default_uvs<'a>(&self, data: FontData<'a>) -> Option<Result<DefaultUvs<'a>, ReadError>> {
1977
0
        self.default_uvs_offset().resolve(data)
1978
0
    }
1979
1980
    /// Offset from the start of the [`Cmap14`] subtable to Non-Default
1981
    /// UVS Table. May be NULL.
1982
0
    pub fn non_default_uvs_offset(&self) -> Nullable<Offset32> {
1983
0
        self.non_default_uvs_offset.get()
1984
0
    }
1985
1986
    /// Offset from the start of the [`Cmap14`] subtable to Non-Default
1987
    /// UVS Table. May be NULL.
1988
    ///
1989
    /// The `data` argument should be retrieved from the parent table
1990
    /// By calling its `offset_data` method.
1991
0
    pub fn non_default_uvs<'a>(
1992
0
        &self,
1993
0
        data: FontData<'a>,
1994
0
    ) -> Option<Result<NonDefaultUvs<'a>, ReadError>> {
1995
0
        self.non_default_uvs_offset().resolve(data)
1996
0
    }
1997
}
1998
1999
impl FixedSize for VariationSelector {
2000
    const RAW_BYTE_LEN: usize =
2001
        Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
2002
}
2003
2004
impl<'a> MinByteRange<'a> for DefaultUvs<'a> {
2005
0
    fn min_byte_range(&self) -> Range<usize> {
2006
0
        0..self.ranges_byte_range().end
2007
0
    }
2008
0
    fn min_table_bytes(&self) -> &'a [u8] {
2009
0
        let range = self.min_byte_range();
2010
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
2011
0
    }
2012
}
2013
2014
impl ReadArgs for DefaultUvs<'_> {
2015
    type Args = ();
2016
}
2017
2018
impl<'a> FontRead<'a> for DefaultUvs<'a> {
2019
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2020
        #[allow(clippy::absurd_extreme_comparisons)]
2021
0
        if data.len() < Self::MIN_SIZE {
2022
0
            return Err(ReadError::OutOfBounds);
2023
0
        }
2024
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
2025
0
            return Err(ReadError::OutOfBounds);
2026
        };
2027
0
        Ok(Self { data })
2028
0
    }
2029
}
2030
2031
/// The fields at the start of the table, which are read directly.
2032
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2033
#[repr(C, packed)]
2034
#[doc(hidden)]
2035
pub struct DefaultUvsFixedHeader {
2036
    pub num_unicode_value_ranges: BigEndian<u32>,
2037
}
2038
2039
#[allow(clippy::absurd_extreme_comparisons)]
2040
const _: () = assert!(std::mem::size_of::<DefaultUvsFixedHeader>() <= DefaultUvs::MIN_SIZE);
2041
2042
/// [Default UVS table](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#default-uvs-table)
2043
#[derive(Clone)]
2044
pub struct DefaultUvs<'a> {
2045
    data: TableDataRef<'a, DefaultUvsFixedHeader>,
2046
}
2047
2048
#[allow(clippy::needless_lifetimes)]
2049
impl<'a> DefaultUvs<'a> {
2050
    pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
2051
    basic_table_impls!(impl_the_methods);
2052
2053
    /// Number of Unicode character ranges.
2054
0
    pub fn num_unicode_value_ranges(&self) -> u32 {
2055
0
        self.data.header().num_unicode_value_ranges.get()
2056
0
    }
2057
2058
    /// Array of UnicodeRange records.
2059
0
    pub fn ranges(&self) -> &'a [UnicodeRange] {
2060
0
        let range = self.ranges_byte_range();
2061
0
        self.offset_data()
2062
0
            .read_array(range)
2063
0
            .ok()
2064
0
            .unwrap_or_default()
2065
0
    }
2066
2067
0
    pub fn num_unicode_value_ranges_byte_range(&self) -> Range<usize> {
2068
0
        let start = 0;
2069
0
        let end = start + u32::RAW_BYTE_LEN;
2070
0
        start..end
2071
0
    }
2072
2073
0
    pub fn ranges_byte_range(&self) -> Range<usize> {
2074
0
        let num_unicode_value_ranges = self.num_unicode_value_ranges();
2075
0
        let start = self.num_unicode_value_ranges_byte_range().end;
2076
0
        let end = start
2077
0
            + (transforms::to_usize(num_unicode_value_ranges))
2078
0
                .saturating_mul(UnicodeRange::RAW_BYTE_LEN);
2079
0
        start..end
2080
0
    }
2081
}
2082
2083
const _: () = assert!(FontData::default_data_long_enough(DefaultUvs::MIN_SIZE));
2084
2085
impl Default for DefaultUvs<'_> {
2086
0
    fn default() -> Self {
2087
        Self {
2088
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
2089
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2090
        }
2091
0
    }
2092
}
2093
2094
impl<'a> MinByteRange<'a> for NonDefaultUvs<'a> {
2095
0
    fn min_byte_range(&self) -> Range<usize> {
2096
0
        0..self.uvs_mapping_byte_range().end
2097
0
    }
2098
0
    fn min_table_bytes(&self) -> &'a [u8] {
2099
0
        let range = self.min_byte_range();
2100
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
2101
0
    }
2102
}
2103
2104
impl ReadArgs for NonDefaultUvs<'_> {
2105
    type Args = ();
2106
}
2107
2108
impl<'a> FontRead<'a> for NonDefaultUvs<'a> {
2109
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2110
        #[allow(clippy::absurd_extreme_comparisons)]
2111
0
        if data.len() < Self::MIN_SIZE {
2112
0
            return Err(ReadError::OutOfBounds);
2113
0
        }
2114
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
2115
0
            return Err(ReadError::OutOfBounds);
2116
        };
2117
0
        Ok(Self { data })
2118
0
    }
2119
}
2120
2121
/// The fields at the start of the table, which are read directly.
2122
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2123
#[repr(C, packed)]
2124
#[doc(hidden)]
2125
pub struct NonDefaultUvsFixedHeader {
2126
    pub num_uvs_mappings: BigEndian<u32>,
2127
}
2128
2129
#[allow(clippy::absurd_extreme_comparisons)]
2130
const _: () = assert!(std::mem::size_of::<NonDefaultUvsFixedHeader>() <= NonDefaultUvs::MIN_SIZE);
2131
2132
/// [Non-Default UVS table](https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#non-default-uvs-table)
2133
#[derive(Clone)]
2134
pub struct NonDefaultUvs<'a> {
2135
    data: TableDataRef<'a, NonDefaultUvsFixedHeader>,
2136
}
2137
2138
#[allow(clippy::needless_lifetimes)]
2139
impl<'a> NonDefaultUvs<'a> {
2140
    pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
2141
    basic_table_impls!(impl_the_methods);
2142
2143
0
    pub fn num_uvs_mappings(&self) -> u32 {
2144
0
        self.data.header().num_uvs_mappings.get()
2145
0
    }
2146
2147
0
    pub fn uvs_mapping(&self) -> &'a [UvsMapping] {
2148
0
        let range = self.uvs_mapping_byte_range();
2149
0
        self.offset_data()
2150
0
            .read_array(range)
2151
0
            .ok()
2152
0
            .unwrap_or_default()
2153
0
    }
2154
2155
0
    pub fn num_uvs_mappings_byte_range(&self) -> Range<usize> {
2156
0
        let start = 0;
2157
0
        let end = start + u32::RAW_BYTE_LEN;
2158
0
        start..end
2159
0
    }
2160
2161
0
    pub fn uvs_mapping_byte_range(&self) -> Range<usize> {
2162
0
        let num_uvs_mappings = self.num_uvs_mappings();
2163
0
        let start = self.num_uvs_mappings_byte_range().end;
2164
0
        let end = start
2165
0
            + (transforms::to_usize(num_uvs_mappings)).saturating_mul(UvsMapping::RAW_BYTE_LEN);
2166
0
        start..end
2167
0
    }
2168
}
2169
2170
const _: () = assert!(FontData::default_data_long_enough(NonDefaultUvs::MIN_SIZE));
2171
2172
impl Default for NonDefaultUvs<'_> {
2173
0
    fn default() -> Self {
2174
        Self {
2175
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
2176
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2177
        }
2178
0
    }
2179
}
2180
2181
impl<'a> MinByteRange<'a> for NonDefaultUvs24<'a> {
2182
0
    fn min_byte_range(&self) -> Range<usize> {
2183
0
        0..self.uvs_mapping_byte_range().end
2184
0
    }
2185
0
    fn min_table_bytes(&self) -> &'a [u8] {
2186
0
        let range = self.min_byte_range();
2187
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
2188
0
    }
2189
}
2190
2191
impl ReadArgs for NonDefaultUvs24<'_> {
2192
    type Args = ();
2193
}
2194
2195
impl<'a> FontRead<'a> for NonDefaultUvs24<'a> {
2196
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2197
        #[allow(clippy::absurd_extreme_comparisons)]
2198
0
        if data.len() < Self::MIN_SIZE {
2199
0
            return Err(ReadError::OutOfBounds);
2200
0
        }
2201
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
2202
0
            return Err(ReadError::OutOfBounds);
2203
        };
2204
0
        Ok(Self { data })
2205
0
    }
2206
}
2207
2208
/// The fields at the start of the table, which are read directly.
2209
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2210
#[repr(C, packed)]
2211
#[doc(hidden)]
2212
pub struct NonDefaultUvs24FixedHeader {
2213
    pub num_uvs_mappings: BigEndian<u32>,
2214
}
2215
2216
#[allow(clippy::absurd_extreme_comparisons)]
2217
const _: () =
2218
    assert!(std::mem::size_of::<NonDefaultUvs24FixedHeader>() <= NonDefaultUvs24::MIN_SIZE);
2219
2220
/// Non-default UVS mappings with 24-bit glyph IDs, used by [Cmap15].
2221
#[derive(Clone)]
2222
pub struct NonDefaultUvs24<'a> {
2223
    data: TableDataRef<'a, NonDefaultUvs24FixedHeader>,
2224
}
2225
2226
#[allow(clippy::needless_lifetimes)]
2227
impl<'a> NonDefaultUvs24<'a> {
2228
    pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
2229
    basic_table_impls!(impl_the_methods);
2230
2231
0
    pub fn num_uvs_mappings(&self) -> u32 {
2232
0
        self.data.header().num_uvs_mappings.get()
2233
0
    }
2234
2235
0
    pub fn uvs_mapping(&self) -> &'a [UvsMapping24] {
2236
0
        let range = self.uvs_mapping_byte_range();
2237
0
        self.offset_data()
2238
0
            .read_array(range)
2239
0
            .ok()
2240
0
            .unwrap_or_default()
2241
0
    }
2242
2243
0
    pub fn num_uvs_mappings_byte_range(&self) -> Range<usize> {
2244
0
        let start = 0;
2245
0
        let end = start + u32::RAW_BYTE_LEN;
2246
0
        start..end
2247
0
    }
2248
2249
0
    pub fn uvs_mapping_byte_range(&self) -> Range<usize> {
2250
0
        let num_uvs_mappings = self.num_uvs_mappings();
2251
0
        let start = self.num_uvs_mappings_byte_range().end;
2252
0
        let end = start
2253
0
            + (transforms::to_usize(num_uvs_mappings)).saturating_mul(UvsMapping24::RAW_BYTE_LEN);
2254
0
        start..end
2255
0
    }
2256
}
2257
2258
const _: () = assert!(FontData::default_data_long_enough(
2259
    NonDefaultUvs24::MIN_SIZE
2260
));
2261
2262
impl Default for NonDefaultUvs24<'_> {
2263
0
    fn default() -> Self {
2264
        Self {
2265
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
2266
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2267
        }
2268
0
    }
2269
}
2270
2271
/// UVSMapping24 record (ISO/IEC 14496-22:2026, 5.1.2.5.11).
2272
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2273
#[repr(C)]
2274
#[repr(packed)]
2275
pub struct UvsMapping24 {
2276
    pub unicode_value: BigEndian<Uint24>,
2277
    pub glyph_id: BigEndian<Uint24>,
2278
}
2279
2280
impl UvsMapping24 {
2281
0
    pub fn unicode_value(&self) -> Uint24 {
2282
0
        self.unicode_value.get()
2283
0
    }
2284
2285
0
    pub fn glyph_id(&self) -> Uint24 {
2286
0
        self.glyph_id.get()
2287
0
    }
2288
}
2289
2290
impl FixedSize for UvsMapping24 {
2291
    const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN;
2292
}
2293
2294
/// Part of [Cmap14]
2295
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2296
#[repr(C)]
2297
#[repr(packed)]
2298
pub struct UvsMapping {
2299
    /// Base Unicode value of the UVS
2300
    pub unicode_value: BigEndian<Uint24>,
2301
    /// Glyph ID of the UVS
2302
    pub glyph_id: BigEndian<u16>,
2303
}
2304
2305
impl UvsMapping {
2306
    /// Base Unicode value of the UVS
2307
0
    pub fn unicode_value(&self) -> Uint24 {
2308
0
        self.unicode_value.get()
2309
0
    }
2310
2311
    /// Glyph ID of the UVS
2312
0
    pub fn glyph_id(&self) -> u16 {
2313
0
        self.glyph_id.get()
2314
0
    }
2315
}
2316
2317
impl FixedSize for UvsMapping {
2318
    const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
2319
}
2320
2321
/// Part of [Cmap14]
2322
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2323
#[repr(C)]
2324
#[repr(packed)]
2325
pub struct UnicodeRange {
2326
    /// First value in this range
2327
    pub start_unicode_value: BigEndian<Uint24>,
2328
    /// Number of additional values in this range
2329
    pub additional_count: u8,
2330
}
2331
2332
impl UnicodeRange {
2333
    /// First value in this range
2334
0
    pub fn start_unicode_value(&self) -> Uint24 {
2335
0
        self.start_unicode_value.get()
2336
0
    }
2337
2338
    /// Number of additional values in this range
2339
0
    pub fn additional_count(&self) -> u8 {
2340
0
        self.additional_count
2341
0
    }
2342
}
2343
2344
impl FixedSize for UnicodeRange {
2345
    const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
2346
}