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_cff.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 CffHeader<'a> {
9
0
    fn min_byte_range(&self) -> Range<usize> {
10
0
        0..self.trailing_data_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 ReadArgs for CffHeader<'_> {
19
    type Args = ();
20
}
21
22
impl<'a> FontRead<'a> for CffHeader<'a> {
23
10.8k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
24
        #[allow(clippy::absurd_extreme_comparisons)]
25
10.8k
        if data.len() < Self::MIN_SIZE {
26
5
            return Err(ReadError::OutOfBounds);
27
10.8k
        }
28
10.8k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
29
0
            return Err(ReadError::OutOfBounds);
30
        };
31
10.8k
        Ok(Self { data })
32
10.8k
    }
33
}
34
35
/// The fields at the start of the table, which are read directly.
36
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
37
#[repr(C, packed)]
38
#[doc(hidden)]
39
pub struct CffHeaderFixedHeader {
40
    pub major: u8,
41
    pub minor: u8,
42
    pub hdr_size: u8,
43
    pub off_size: u8,
44
}
45
46
#[allow(clippy::absurd_extreme_comparisons)]
47
const _: () = assert!(std::mem::size_of::<CffHeaderFixedHeader>() <= CffHeader::MIN_SIZE);
48
49
/// [Compact Font Format](https://learn.microsoft.com/en-us/typography/opentype/spec/cff) table header
50
#[derive(Clone)]
51
pub struct CffHeader<'a> {
52
    data: TableDataRef<'a, CffHeaderFixedHeader>,
53
}
54
55
#[allow(clippy::needless_lifetimes)]
56
impl<'a> CffHeader<'a> {
57
    pub const MIN_SIZE: usize =
58
        (u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
59
    basic_table_impls!(impl_the_methods);
60
61
    /// Format major version (starting at 1).
62
0
    pub fn major(&self) -> u8 {
63
0
        self.data.header().major
64
0
    }
65
66
    /// Format minor version (starting at 0).
67
0
    pub fn minor(&self) -> u8 {
68
0
        self.data.header().minor
69
0
    }
70
71
    /// Header size (bytes).
72
10.8k
    pub fn hdr_size(&self) -> u8 {
73
10.8k
        self.data.header().hdr_size
74
10.8k
    }
75
76
    /// Absolute offset size.
77
0
    pub fn off_size(&self) -> u8 {
78
0
        self.data.header().off_size
79
0
    }
80
81
    /// Padding bytes before the start of the Name INDEX.
82
0
    pub fn _padding(&self) -> &'a [u8] {
83
0
        let range = self._padding_byte_range();
84
0
        self.offset_data()
85
0
            .read_array(range)
86
0
            .ok()
87
0
            .unwrap_or_default()
88
0
    }
89
90
    /// Remaining table data.
91
10.8k
    pub fn trailing_data(&self) -> &'a [u8] {
92
10.8k
        let range = self.trailing_data_byte_range();
93
10.8k
        self.offset_data()
94
10.8k
            .read_array(range)
95
10.8k
            .ok()
96
10.8k
            .unwrap_or_default()
97
10.8k
    }
98
99
10.8k
    pub fn major_byte_range(&self) -> Range<usize> {
100
10.8k
        let start = 0;
101
10.8k
        let end = start + u8::RAW_BYTE_LEN;
102
10.8k
        start..end
103
10.8k
    }
104
105
10.8k
    pub fn minor_byte_range(&self) -> Range<usize> {
106
10.8k
        let start = self.major_byte_range().end;
107
10.8k
        let end = start + u8::RAW_BYTE_LEN;
108
10.8k
        start..end
109
10.8k
    }
110
111
10.8k
    pub fn hdr_size_byte_range(&self) -> Range<usize> {
112
10.8k
        let start = self.minor_byte_range().end;
113
10.8k
        let end = start + u8::RAW_BYTE_LEN;
114
10.8k
        start..end
115
10.8k
    }
116
117
10.8k
    pub fn off_size_byte_range(&self) -> Range<usize> {
118
10.8k
        let start = self.hdr_size_byte_range().end;
119
10.8k
        let end = start + u8::RAW_BYTE_LEN;
120
10.8k
        start..end
121
10.8k
    }
122
123
10.8k
    pub fn _padding_byte_range(&self) -> Range<usize> {
124
10.8k
        let hdr_size = self.hdr_size();
125
10.8k
        let start = self.off_size_byte_range().end;
126
10.8k
        let end =
127
10.8k
            start + (transforms::subtract(hdr_size, 4_usize)).saturating_mul(u8::RAW_BYTE_LEN);
128
10.8k
        start..end
129
10.8k
    }
130
131
10.8k
    pub fn trailing_data_byte_range(&self) -> Range<usize> {
132
10.8k
        let start = self._padding_byte_range().end;
133
10.8k
        let end = start
134
10.8k
            + self.offset_data().len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
135
10.8k
        start..end
136
10.8k
    }
137
}
138
139
const _: () = assert!(FontData::default_data_long_enough(CffHeader::MIN_SIZE));
140
141
impl Default for CffHeader<'_> {
142
0
    fn default() -> Self {
143
        Self {
144
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
145
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
146
        }
147
0
    }
148
}
149
150
impl<'a> MinByteRange<'a> for Index<'a> {
151
0
    fn min_byte_range(&self) -> Range<usize> {
152
0
        0..self.data_byte_range().end
153
0
    }
154
0
    fn min_table_bytes(&self) -> &'a [u8] {
155
0
        let range = self.min_byte_range();
156
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
157
0
    }
158
}
159
160
impl ReadArgs for Index<'_> {
161
    type Args = ();
162
}
163
164
impl<'a> FontRead<'a> for Index<'a> {
165
82.3k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
166
        #[allow(clippy::absurd_extreme_comparisons)]
167
82.3k
        if data.len() < Self::MIN_SIZE {
168
309
            return Err(ReadError::OutOfBounds);
169
82.0k
        }
170
82.0k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
171
0
            return Err(ReadError::OutOfBounds);
172
        };
173
82.0k
        Ok(Self { data })
174
82.3k
    }
175
}
176
177
/// The fields at the start of the table, which are read directly.
178
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
179
#[repr(C, packed)]
180
#[doc(hidden)]
181
pub struct IndexFixedHeader {
182
    pub count: BigEndian<u16>,
183
    pub off_size: u8,
184
}
185
186
#[allow(clippy::absurd_extreme_comparisons)]
187
const _: () = assert!(std::mem::size_of::<IndexFixedHeader>() <= Index::MIN_SIZE);
188
189
/// An array of variable-sized objects in a `CFF` table.
190
#[derive(Clone)]
191
pub struct Index<'a> {
192
    data: TableDataRef<'a, IndexFixedHeader>,
193
}
194
195
#[allow(clippy::needless_lifetimes)]
196
impl<'a> Index<'a> {
197
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
198
    basic_table_impls!(impl_the_methods);
199
200
    /// Number of objects stored in INDEX.
201
229k
    pub fn count(&self) -> u16 {
202
229k
        self.data.header().count.get()
203
229k
    }
204
205
    /// Object array element size.
206
163k
    pub fn off_size(&self) -> u8 {
207
163k
        self.data.header().off_size
208
163k
    }
209
210
    /// Bytes containing `count + 1` offsets each of `off_size`.
211
74.1k
    pub fn offsets(&self) -> &'a [u8] {
212
74.1k
        let range = self.offsets_byte_range();
213
74.1k
        self.offset_data()
214
74.1k
            .read_array(range)
215
74.1k
            .ok()
216
74.1k
            .unwrap_or_default()
217
74.1k
    }
218
219
    /// Array containing the object data.
220
26.3k
    pub fn data(&self) -> &'a [u8] {
221
26.3k
        let range = self.data_byte_range();
222
26.3k
        self.offset_data()
223
26.3k
            .read_array(range)
224
26.3k
            .ok()
225
26.3k
            .unwrap_or_default()
226
26.3k
    }
227
228
100k
    pub fn count_byte_range(&self) -> Range<usize> {
229
100k
        let start = 0;
230
100k
        let end = start + u16::RAW_BYTE_LEN;
231
100k
        start..end
232
100k
    }
233
234
100k
    pub fn off_size_byte_range(&self) -> Range<usize> {
235
100k
        let start = self.count_byte_range().end;
236
100k
        let end = start + u8::RAW_BYTE_LEN;
237
100k
        start..end
238
100k
    }
239
240
100k
    pub fn offsets_byte_range(&self) -> Range<usize> {
241
100k
        let count = self.count();
242
100k
        let off_size = self.off_size();
243
100k
        let start = self.off_size_byte_range().end;
244
100k
        let end = start
245
100k
            + (transforms::add_multiply(count, 1_usize, off_size)).saturating_mul(u8::RAW_BYTE_LEN);
246
100k
        start..end
247
100k
    }
248
249
26.3k
    pub fn data_byte_range(&self) -> Range<usize> {
250
26.3k
        let start = self.offsets_byte_range().end;
251
26.3k
        let end = start
252
26.3k
            + self.offset_data().len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
253
26.3k
        start..end
254
26.3k
    }
255
}
256
257
const _: () = assert!(FontData::default_data_long_enough(Index::MIN_SIZE));
258
259
impl Default for Index<'_> {
260
0
    fn default() -> Self {
261
        Self {
262
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
263
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
264
        }
265
0
    }
266
}
267
268
/// Associates a glyph identifier with a Font DICT.
269
#[derive(Clone)]
270
pub enum FdSelect<'a> {
271
    Format0(FdSelectFormat0<'a>),
272
    Format3(FdSelectFormat3<'a>),
273
    Format4(FdSelectFormat4<'a>),
274
}
275
276
impl Default for FdSelect<'_> {
277
0
    fn default() -> Self {
278
0
        Self::Format0(Default::default())
279
0
    }
280
}
281
282
impl<'a> FdSelect<'a> {
283
    ///Return the `FontData` used to resolve offsets for this table.
284
0
    pub fn offset_data(&self) -> FontData<'a> {
285
0
        match self {
286
0
            Self::Format0(item) => item.offset_data(),
287
0
            Self::Format3(item) => item.offset_data(),
288
0
            Self::Format4(item) => item.offset_data(),
289
        }
290
0
    }
291
292
    /// Format = 0.
293
0
    pub fn format(&self) -> u8 {
294
0
        match self {
295
0
            Self::Format0(item) => item.format(),
296
0
            Self::Format3(item) => item.format(),
297
0
            Self::Format4(item) => item.format(),
298
        }
299
0
    }
300
}
301
302
impl ReadArgs for FdSelect<'_> {
303
    type Args = ();
304
}
305
306
impl<'a> FontRead<'a> for FdSelect<'a> {
307
    #[inline]
308
234
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
309
234
        let format: u8 = data.read_at(0usize)?;
310
224
        match format {
311
54
            FdSelectFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
312
38
            FdSelectFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
313
71
            FdSelectFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
314
61
            other => Err(ReadError::InvalidFormat(other.into())),
315
        }
316
234
    }
317
}
318
319
impl<'a> MinByteRange<'a> for FdSelect<'a> {
320
0
    fn min_byte_range(&self) -> Range<usize> {
321
0
        match self {
322
0
            Self::Format0(item) => item.min_byte_range(),
323
0
            Self::Format3(item) => item.min_byte_range(),
324
0
            Self::Format4(item) => item.min_byte_range(),
325
        }
326
0
    }
327
0
    fn min_table_bytes(&self) -> &'a [u8] {
328
0
        match self {
329
0
            Self::Format0(item) => item.min_table_bytes(),
330
0
            Self::Format3(item) => item.min_table_bytes(),
331
0
            Self::Format4(item) => item.min_table_bytes(),
332
        }
333
0
    }
334
}
335
336
impl Format<u8> for FdSelectFormat0<'_> {
337
    const FORMAT: u8 = 0;
338
}
339
340
impl<'a> MinByteRange<'a> for FdSelectFormat0<'a> {
341
0
    fn min_byte_range(&self) -> Range<usize> {
342
0
        0..self.fds_byte_range().end
343
0
    }
344
0
    fn min_table_bytes(&self) -> &'a [u8] {
345
0
        let range = self.min_byte_range();
346
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
347
0
    }
348
}
349
350
impl ReadArgs for FdSelectFormat0<'_> {
351
    type Args = ();
352
}
353
354
impl<'a> FontRead<'a> for FdSelectFormat0<'a> {
355
54
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
356
        #[allow(clippy::absurd_extreme_comparisons)]
357
54
        if data.len() < Self::MIN_SIZE {
358
0
            return Err(ReadError::OutOfBounds);
359
54
        }
360
54
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
361
0
            return Err(ReadError::OutOfBounds);
362
        };
363
54
        Ok(Self { data })
364
54
    }
365
}
366
367
/// The fields at the start of the table, which are read directly.
368
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
369
#[repr(C, packed)]
370
#[doc(hidden)]
371
pub struct FdSelectFormat0FixedHeader {
372
    pub format: u8,
373
}
374
375
#[allow(clippy::absurd_extreme_comparisons)]
376
const _: () =
377
    assert!(std::mem::size_of::<FdSelectFormat0FixedHeader>() <= FdSelectFormat0::MIN_SIZE);
378
379
/// FdSelect format 0.
380
#[derive(Clone)]
381
pub struct FdSelectFormat0<'a> {
382
    data: TableDataRef<'a, FdSelectFormat0FixedHeader>,
383
}
384
385
#[allow(clippy::needless_lifetimes)]
386
impl<'a> FdSelectFormat0<'a> {
387
    pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
388
    basic_table_impls!(impl_the_methods);
389
390
    /// Format = 0.
391
0
    pub fn format(&self) -> u8 {
392
0
        self.data.header().format
393
0
    }
394
395
    /// FD selector array (one entry for each glyph).
396
32
    pub fn fds(&self) -> &'a [u8] {
397
32
        let range = self.fds_byte_range();
398
32
        self.offset_data()
399
32
            .read_array(range)
400
32
            .ok()
401
32
            .unwrap_or_default()
402
32
    }
403
404
32
    pub fn format_byte_range(&self) -> Range<usize> {
405
32
        let start = 0;
406
32
        let end = start + u8::RAW_BYTE_LEN;
407
32
        start..end
408
32
    }
409
410
32
    pub fn fds_byte_range(&self) -> Range<usize> {
411
32
        let start = self.format_byte_range().end;
412
32
        let end = start
413
32
            + self.offset_data().len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
414
32
        start..end
415
32
    }
416
}
417
418
const _: () = assert!(FontData::default_data_long_enough(
419
    FdSelectFormat0::MIN_SIZE
420
));
421
422
impl Default for FdSelectFormat0<'_> {
423
0
    fn default() -> Self {
424
        Self {
425
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
426
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
427
        }
428
0
    }
429
}
430
431
impl Format<u8> for FdSelectFormat3<'_> {
432
    const FORMAT: u8 = 3;
433
}
434
435
impl<'a> MinByteRange<'a> for FdSelectFormat3<'a> {
436
0
    fn min_byte_range(&self) -> Range<usize> {
437
0
        0..self.sentinel_byte_range().end
438
0
    }
439
0
    fn min_table_bytes(&self) -> &'a [u8] {
440
0
        let range = self.min_byte_range();
441
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
442
0
    }
443
}
444
445
impl ReadArgs for FdSelectFormat3<'_> {
446
    type Args = ();
447
}
448
449
impl<'a> FontRead<'a> for FdSelectFormat3<'a> {
450
38
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
451
        #[allow(clippy::absurd_extreme_comparisons)]
452
38
        if data.len() < Self::MIN_SIZE {
453
6
            return Err(ReadError::OutOfBounds);
454
32
        }
455
32
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
456
0
            return Err(ReadError::OutOfBounds);
457
        };
458
32
        Ok(Self { data })
459
38
    }
460
}
461
462
/// The fields at the start of the table, which are read directly.
463
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
464
#[repr(C, packed)]
465
#[doc(hidden)]
466
pub struct FdSelectFormat3FixedHeader {
467
    pub format: u8,
468
    pub n_ranges: BigEndian<u16>,
469
}
470
471
#[allow(clippy::absurd_extreme_comparisons)]
472
const _: () =
473
    assert!(std::mem::size_of::<FdSelectFormat3FixedHeader>() <= FdSelectFormat3::MIN_SIZE);
474
475
/// FdSelect format 3.
476
#[derive(Clone)]
477
pub struct FdSelectFormat3<'a> {
478
    data: TableDataRef<'a, FdSelectFormat3FixedHeader>,
479
}
480
481
#[allow(clippy::needless_lifetimes)]
482
impl<'a> FdSelectFormat3<'a> {
483
    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
484
    basic_table_impls!(impl_the_methods);
485
486
    /// Format = 3.
487
0
    pub fn format(&self) -> u8 {
488
0
        self.data.header().format
489
0
    }
490
491
    /// Number of ranges.
492
78
    pub fn n_ranges(&self) -> u16 {
493
78
        self.data.header().n_ranges.get()
494
78
    }
495
496
    /// Range3 array.
497
45
    pub fn ranges(&self) -> &'a [FdSelectRange3] {
498
45
        let range = self.ranges_byte_range();
499
45
        self.offset_data()
500
45
            .read_array(range)
501
45
            .ok()
502
45
            .unwrap_or_default()
503
45
    }
504
505
    /// Sentinel GID. Set equal to the number of glyphs in the font.
506
33
    pub fn sentinel(&self) -> u16 {
507
33
        let range = self.sentinel_byte_range();
508
33
        self.offset_data()
509
33
            .read_at(range.start)
510
33
            .ok()
511
33
            .unwrap_or_default()
512
33
    }
513
514
78
    pub fn format_byte_range(&self) -> Range<usize> {
515
78
        let start = 0;
516
78
        let end = start + u8::RAW_BYTE_LEN;
517
78
        start..end
518
78
    }
519
520
78
    pub fn n_ranges_byte_range(&self) -> Range<usize> {
521
78
        let start = self.format_byte_range().end;
522
78
        let end = start + u16::RAW_BYTE_LEN;
523
78
        start..end
524
78
    }
525
526
78
    pub fn ranges_byte_range(&self) -> Range<usize> {
527
78
        let n_ranges = self.n_ranges();
528
78
        let start = self.n_ranges_byte_range().end;
529
78
        let end =
530
78
            start + (transforms::to_usize(n_ranges)).saturating_mul(FdSelectRange3::RAW_BYTE_LEN);
531
78
        start..end
532
78
    }
533
534
33
    pub fn sentinel_byte_range(&self) -> Range<usize> {
535
33
        let start = self.ranges_byte_range().end;
536
33
        let end = start + u16::RAW_BYTE_LEN;
537
33
        start..end
538
33
    }
539
}
540
541
/// Range struct for FdSelect format 3.
542
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
543
#[repr(C)]
544
#[repr(packed)]
545
pub struct FdSelectRange3 {
546
    /// First glyph index in range.
547
    pub first: BigEndian<u16>,
548
    /// FD index for all glyphs in range.
549
    pub fd: u8,
550
}
551
552
impl FdSelectRange3 {
553
    /// First glyph index in range.
554
131
    pub fn first(&self) -> u16 {
555
131
        self.first.get()
556
131
    }
557
558
    /// FD index for all glyphs in range.
559
14
    pub fn fd(&self) -> u8 {
560
14
        self.fd
561
14
    }
562
}
563
564
impl FixedSize for FdSelectRange3 {
565
    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
566
}
567
568
impl Format<u8> for FdSelectFormat4<'_> {
569
    const FORMAT: u8 = 4;
570
}
571
572
impl<'a> MinByteRange<'a> for FdSelectFormat4<'a> {
573
0
    fn min_byte_range(&self) -> Range<usize> {
574
0
        0..self.sentinel_byte_range().end
575
0
    }
576
0
    fn min_table_bytes(&self) -> &'a [u8] {
577
0
        let range = self.min_byte_range();
578
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
579
0
    }
580
}
581
582
impl ReadArgs for FdSelectFormat4<'_> {
583
    type Args = ();
584
}
585
586
impl<'a> FontRead<'a> for FdSelectFormat4<'a> {
587
71
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
588
        #[allow(clippy::absurd_extreme_comparisons)]
589
71
        if data.len() < Self::MIN_SIZE {
590
10
            return Err(ReadError::OutOfBounds);
591
61
        }
592
61
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
593
0
            return Err(ReadError::OutOfBounds);
594
        };
595
61
        Ok(Self { data })
596
71
    }
597
}
598
599
/// The fields at the start of the table, which are read directly.
600
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
601
#[repr(C, packed)]
602
#[doc(hidden)]
603
pub struct FdSelectFormat4FixedHeader {
604
    pub format: u8,
605
    pub n_ranges: BigEndian<u32>,
606
}
607
608
#[allow(clippy::absurd_extreme_comparisons)]
609
const _: () =
610
    assert!(std::mem::size_of::<FdSelectFormat4FixedHeader>() <= FdSelectFormat4::MIN_SIZE);
611
612
/// FdSelect format 4.
613
#[derive(Clone)]
614
pub struct FdSelectFormat4<'a> {
615
    data: TableDataRef<'a, FdSelectFormat4FixedHeader>,
616
}
617
618
#[allow(clippy::needless_lifetimes)]
619
impl<'a> FdSelectFormat4<'a> {
620
    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
621
    basic_table_impls!(impl_the_methods);
622
623
    /// Format = 4.
624
0
    pub fn format(&self) -> u8 {
625
0
        self.data.header().format
626
0
    }
627
628
    /// Number of ranges.
629
157
    pub fn n_ranges(&self) -> u32 {
630
157
        self.data.header().n_ranges.get()
631
157
    }
632
633
    /// Range4 array.
634
89
    pub fn ranges(&self) -> &'a [FdSelectRange4] {
635
89
        let range = self.ranges_byte_range();
636
89
        self.offset_data()
637
89
            .read_array(range)
638
89
            .ok()
639
89
            .unwrap_or_default()
640
89
    }
641
642
    /// Sentinel GID. Set equal to the number of glyphs in the font.
643
68
    pub fn sentinel(&self) -> u32 {
644
68
        let range = self.sentinel_byte_range();
645
68
        self.offset_data()
646
68
            .read_at(range.start)
647
68
            .ok()
648
68
            .unwrap_or_default()
649
68
    }
650
651
157
    pub fn format_byte_range(&self) -> Range<usize> {
652
157
        let start = 0;
653
157
        let end = start + u8::RAW_BYTE_LEN;
654
157
        start..end
655
157
    }
656
657
157
    pub fn n_ranges_byte_range(&self) -> Range<usize> {
658
157
        let start = self.format_byte_range().end;
659
157
        let end = start + u32::RAW_BYTE_LEN;
660
157
        start..end
661
157
    }
662
663
157
    pub fn ranges_byte_range(&self) -> Range<usize> {
664
157
        let n_ranges = self.n_ranges();
665
157
        let start = self.n_ranges_byte_range().end;
666
157
        let end =
667
157
            start + (transforms::to_usize(n_ranges)).saturating_mul(FdSelectRange4::RAW_BYTE_LEN);
668
157
        start..end
669
157
    }
670
671
68
    pub fn sentinel_byte_range(&self) -> Range<usize> {
672
68
        let start = self.ranges_byte_range().end;
673
68
        let end = start + u32::RAW_BYTE_LEN;
674
68
        start..end
675
68
    }
676
}
677
678
/// Range struct for FdSelect format 4.
679
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
680
#[repr(C)]
681
#[repr(packed)]
682
pub struct FdSelectRange4 {
683
    /// First glyph index in range.
684
    pub first: BigEndian<u32>,
685
    /// FD index for all glyphs in range.
686
    pub fd: BigEndian<u16>,
687
}
688
689
impl FdSelectRange4 {
690
    /// First glyph index in range.
691
414
    pub fn first(&self) -> u32 {
692
414
        self.first.get()
693
414
    }
694
695
    /// FD index for all glyphs in range.
696
24
    pub fn fd(&self) -> u16 {
697
24
        self.fd.get()
698
24
    }
699
}
700
701
impl FixedSize for FdSelectRange4 {
702
    const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
703
}
704
705
/// Charset with custom glyph id to string id mappings.
706
#[derive(Clone)]
707
pub enum CustomCharset<'a> {
708
    Format0(CharsetFormat0<'a>),
709
    Format1(CharsetFormat1<'a>),
710
    Format2(CharsetFormat2<'a>),
711
}
712
713
impl Default for CustomCharset<'_> {
714
0
    fn default() -> Self {
715
0
        Self::Format0(Default::default())
716
0
    }
717
}
718
719
impl<'a> CustomCharset<'a> {
720
    ///Return the `FontData` used to resolve offsets for this table.
721
0
    pub fn offset_data(&self) -> FontData<'a> {
722
0
        match self {
723
0
            Self::Format0(item) => item.offset_data(),
724
0
            Self::Format1(item) => item.offset_data(),
725
0
            Self::Format2(item) => item.offset_data(),
726
        }
727
0
    }
728
729
    /// Format; =0
730
0
    pub fn format(&self) -> u8 {
731
0
        match self {
732
0
            Self::Format0(item) => item.format(),
733
0
            Self::Format1(item) => item.format(),
734
0
            Self::Format2(item) => item.format(),
735
        }
736
0
    }
737
}
738
739
impl ReadArgs for CustomCharset<'_> {
740
    type Args = ();
741
}
742
743
impl<'a> FontRead<'a> for CustomCharset<'a> {
744
    #[inline]
745
372
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
746
372
        let format: u8 = data.read_at(0usize)?;
747
354
        match format {
748
131
            CharsetFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
749
92
            CharsetFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
750
79
            CharsetFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
751
52
            other => Err(ReadError::InvalidFormat(other.into())),
752
        }
753
372
    }
754
}
755
756
impl<'a> MinByteRange<'a> for CustomCharset<'a> {
757
0
    fn min_byte_range(&self) -> Range<usize> {
758
0
        match self {
759
0
            Self::Format0(item) => item.min_byte_range(),
760
0
            Self::Format1(item) => item.min_byte_range(),
761
0
            Self::Format2(item) => item.min_byte_range(),
762
        }
763
0
    }
764
0
    fn min_table_bytes(&self) -> &'a [u8] {
765
0
        match self {
766
0
            Self::Format0(item) => item.min_table_bytes(),
767
0
            Self::Format1(item) => item.min_table_bytes(),
768
0
            Self::Format2(item) => item.min_table_bytes(),
769
        }
770
0
    }
771
}
772
773
impl Format<u8> for CharsetFormat0<'_> {
774
    const FORMAT: u8 = 0;
775
}
776
777
impl<'a> MinByteRange<'a> for CharsetFormat0<'a> {
778
0
    fn min_byte_range(&self) -> Range<usize> {
779
0
        0..self.glyph_byte_range().end
780
0
    }
781
0
    fn min_table_bytes(&self) -> &'a [u8] {
782
0
        let range = self.min_byte_range();
783
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
784
0
    }
785
}
786
787
impl ReadArgs for CharsetFormat0<'_> {
788
    type Args = ();
789
}
790
791
impl<'a> FontRead<'a> for CharsetFormat0<'a> {
792
131
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
793
        #[allow(clippy::absurd_extreme_comparisons)]
794
131
        if data.len() < Self::MIN_SIZE {
795
0
            return Err(ReadError::OutOfBounds);
796
131
        }
797
131
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
798
0
            return Err(ReadError::OutOfBounds);
799
        };
800
131
        Ok(Self { data })
801
131
    }
802
}
803
804
/// The fields at the start of the table, which are read directly.
805
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
806
#[repr(C, packed)]
807
#[doc(hidden)]
808
pub struct CharsetFormat0FixedHeader {
809
    pub format: u8,
810
}
811
812
#[allow(clippy::absurd_extreme_comparisons)]
813
const _: () = assert!(std::mem::size_of::<CharsetFormat0FixedHeader>() <= CharsetFormat0::MIN_SIZE);
814
815
/// Charset format 0.
816
#[derive(Clone)]
817
pub struct CharsetFormat0<'a> {
818
    data: TableDataRef<'a, CharsetFormat0FixedHeader>,
819
}
820
821
#[allow(clippy::needless_lifetimes)]
822
impl<'a> CharsetFormat0<'a> {
823
    pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
824
    basic_table_impls!(impl_the_methods);
825
826
    /// Format; =0
827
0
    pub fn format(&self) -> u8 {
828
0
        self.data.header().format
829
0
    }
830
831
    /// Glyph name array.
832
83
    pub fn glyph(&self) -> &'a [BigEndian<u16>] {
833
83
        let range = self.glyph_byte_range();
834
83
        self.offset_data()
835
83
            .read_array(range)
836
83
            .ok()
837
83
            .unwrap_or_default()
838
83
    }
839
840
83
    pub fn format_byte_range(&self) -> Range<usize> {
841
83
        let start = 0;
842
83
        let end = start + u8::RAW_BYTE_LEN;
843
83
        start..end
844
83
    }
845
846
83
    pub fn glyph_byte_range(&self) -> Range<usize> {
847
83
        let start = self.format_byte_range().end;
848
83
        let end = start
849
83
            + self.offset_data().len().saturating_sub(start) / u16::RAW_BYTE_LEN
850
83
                * u16::RAW_BYTE_LEN;
851
83
        start..end
852
83
    }
853
}
854
855
const _: () = assert!(FontData::default_data_long_enough(CharsetFormat0::MIN_SIZE));
856
857
impl Default for CharsetFormat0<'_> {
858
0
    fn default() -> Self {
859
        Self {
860
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
861
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
862
        }
863
0
    }
864
}
865
866
impl Format<u8> for CharsetFormat1<'_> {
867
    const FORMAT: u8 = 1;
868
}
869
870
impl<'a> MinByteRange<'a> for CharsetFormat1<'a> {
871
0
    fn min_byte_range(&self) -> Range<usize> {
872
0
        0..self.ranges_byte_range().end
873
0
    }
874
0
    fn min_table_bytes(&self) -> &'a [u8] {
875
0
        let range = self.min_byte_range();
876
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
877
0
    }
878
}
879
880
impl ReadArgs for CharsetFormat1<'_> {
881
    type Args = ();
882
}
883
884
impl<'a> FontRead<'a> for CharsetFormat1<'a> {
885
92
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
886
        #[allow(clippy::absurd_extreme_comparisons)]
887
92
        if data.len() < Self::MIN_SIZE {
888
0
            return Err(ReadError::OutOfBounds);
889
92
        }
890
92
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
891
0
            return Err(ReadError::OutOfBounds);
892
        };
893
92
        Ok(Self { data })
894
92
    }
895
}
896
897
/// The fields at the start of the table, which are read directly.
898
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
899
#[repr(C, packed)]
900
#[doc(hidden)]
901
pub struct CharsetFormat1FixedHeader {
902
    pub format: u8,
903
}
904
905
#[allow(clippy::absurd_extreme_comparisons)]
906
const _: () = assert!(std::mem::size_of::<CharsetFormat1FixedHeader>() <= CharsetFormat1::MIN_SIZE);
907
908
/// Charset format 1.
909
#[derive(Clone)]
910
pub struct CharsetFormat1<'a> {
911
    data: TableDataRef<'a, CharsetFormat1FixedHeader>,
912
}
913
914
#[allow(clippy::needless_lifetimes)]
915
impl<'a> CharsetFormat1<'a> {
916
    pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
917
    basic_table_impls!(impl_the_methods);
918
919
    /// Format; =1
920
0
    pub fn format(&self) -> u8 {
921
0
        self.data.header().format
922
0
    }
923
924
    /// Range1 array.
925
136
    pub fn ranges(&self) -> &'a [CharsetRange1] {
926
136
        let range = self.ranges_byte_range();
927
136
        self.offset_data()
928
136
            .read_array(range)
929
136
            .ok()
930
136
            .unwrap_or_default()
931
136
    }
932
933
136
    pub fn format_byte_range(&self) -> Range<usize> {
934
136
        let start = 0;
935
136
        let end = start + u8::RAW_BYTE_LEN;
936
136
        start..end
937
136
    }
938
939
136
    pub fn ranges_byte_range(&self) -> Range<usize> {
940
136
        let start = self.format_byte_range().end;
941
136
        let end = start
942
136
            + self.offset_data().len().saturating_sub(start) / CharsetRange1::RAW_BYTE_LEN
943
136
                * CharsetRange1::RAW_BYTE_LEN;
944
136
        start..end
945
136
    }
946
}
947
948
const _: () = assert!(FontData::default_data_long_enough(CharsetFormat1::MIN_SIZE));
949
950
impl Default for CharsetFormat1<'_> {
951
0
    fn default() -> Self {
952
        Self {
953
0
            data: TableDataRef::new(FontData::default_format_1_u8_table_data().as_bytes())
954
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
955
        }
956
0
    }
957
}
958
959
/// Range struct for Charset format 1.
960
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
961
#[repr(C)]
962
#[repr(packed)]
963
pub struct CharsetRange1 {
964
    /// First glyph in range.
965
    pub first: BigEndian<u16>,
966
    /// Glyphs left in range (excluding first).
967
    pub n_left: u8,
968
}
969
970
impl CharsetRange1 {
971
    /// First glyph in range.
972
0
    pub fn first(&self) -> u16 {
973
0
        self.first.get()
974
0
    }
975
976
    /// Glyphs left in range (excluding first).
977
0
    pub fn n_left(&self) -> u8 {
978
0
        self.n_left
979
0
    }
980
}
981
982
impl FixedSize for CharsetRange1 {
983
    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
984
}
985
986
impl Format<u8> for CharsetFormat2<'_> {
987
    const FORMAT: u8 = 2;
988
}
989
990
impl<'a> MinByteRange<'a> for CharsetFormat2<'a> {
991
0
    fn min_byte_range(&self) -> Range<usize> {
992
0
        0..self.ranges_byte_range().end
993
0
    }
994
0
    fn min_table_bytes(&self) -> &'a [u8] {
995
0
        let range = self.min_byte_range();
996
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
997
0
    }
998
}
999
1000
impl ReadArgs for CharsetFormat2<'_> {
1001
    type Args = ();
1002
}
1003
1004
impl<'a> FontRead<'a> for CharsetFormat2<'a> {
1005
79
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1006
        #[allow(clippy::absurd_extreme_comparisons)]
1007
79
        if data.len() < Self::MIN_SIZE {
1008
0
            return Err(ReadError::OutOfBounds);
1009
79
        }
1010
79
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1011
0
            return Err(ReadError::OutOfBounds);
1012
        };
1013
79
        Ok(Self { data })
1014
79
    }
1015
}
1016
1017
/// The fields at the start of the table, which are read directly.
1018
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1019
#[repr(C, packed)]
1020
#[doc(hidden)]
1021
pub struct CharsetFormat2FixedHeader {
1022
    pub format: u8,
1023
}
1024
1025
#[allow(clippy::absurd_extreme_comparisons)]
1026
const _: () = assert!(std::mem::size_of::<CharsetFormat2FixedHeader>() <= CharsetFormat2::MIN_SIZE);
1027
1028
/// Charset format 2.
1029
#[derive(Clone)]
1030
pub struct CharsetFormat2<'a> {
1031
    data: TableDataRef<'a, CharsetFormat2FixedHeader>,
1032
}
1033
1034
#[allow(clippy::needless_lifetimes)]
1035
impl<'a> CharsetFormat2<'a> {
1036
    pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
1037
    basic_table_impls!(impl_the_methods);
1038
1039
    /// Format; =2
1040
0
    pub fn format(&self) -> u8 {
1041
0
        self.data.header().format
1042
0
    }
1043
1044
    /// Range2 array.
1045
93
    pub fn ranges(&self) -> &'a [CharsetRange2] {
1046
93
        let range = self.ranges_byte_range();
1047
93
        self.offset_data()
1048
93
            .read_array(range)
1049
93
            .ok()
1050
93
            .unwrap_or_default()
1051
93
    }
1052
1053
93
    pub fn format_byte_range(&self) -> Range<usize> {
1054
93
        let start = 0;
1055
93
        let end = start + u8::RAW_BYTE_LEN;
1056
93
        start..end
1057
93
    }
1058
1059
93
    pub fn ranges_byte_range(&self) -> Range<usize> {
1060
93
        let start = self.format_byte_range().end;
1061
93
        let end = start
1062
93
            + self.offset_data().len().saturating_sub(start) / CharsetRange2::RAW_BYTE_LEN
1063
93
                * CharsetRange2::RAW_BYTE_LEN;
1064
93
        start..end
1065
93
    }
1066
}
1067
1068
/// Range struct for Charset format 2.
1069
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1070
#[repr(C)]
1071
#[repr(packed)]
1072
pub struct CharsetRange2 {
1073
    /// First glyph in range.
1074
    pub first: BigEndian<u16>,
1075
    /// Glyphs left in range (excluding first).
1076
    pub n_left: BigEndian<u16>,
1077
}
1078
1079
impl CharsetRange2 {
1080
    /// First glyph in range.
1081
0
    pub fn first(&self) -> u16 {
1082
0
        self.first.get()
1083
0
    }
1084
1085
    /// Glyphs left in range (excluding first).
1086
0
    pub fn n_left(&self) -> u16 {
1087
0
        self.n_left.get()
1088
0
    }
1089
}
1090
1091
impl FixedSize for CharsetRange2 {
1092
    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1093
}
1094
1095
/// Range struct for Encoding format 1.
1096
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1097
#[repr(C)]
1098
#[repr(packed)]
1099
pub struct EncodingRange1 {
1100
    /// First code in range.
1101
    pub first: u8,
1102
    /// Codes left in range (excluding first).
1103
    pub n_left: u8,
1104
}
1105
1106
impl EncodingRange1 {
1107
    /// First code in range.
1108
0
    pub fn first(&self) -> u8 {
1109
0
        self.first
1110
0
    }
1111
1112
    /// Codes left in range (excluding first).
1113
0
    pub fn n_left(&self) -> u8 {
1114
0
        self.n_left
1115
0
    }
1116
}
1117
1118
impl FixedSize for EncodingRange1 {
1119
    const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
1120
}
1121
1122
/// Supplemental encoding record.
1123
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1124
#[repr(C)]
1125
#[repr(packed)]
1126
pub struct EncodingSupplement {
1127
    /// Encoding.
1128
    pub code: u8,
1129
    /// Name.
1130
    pub glyph: BigEndian<u16>,
1131
}
1132
1133
impl EncodingSupplement {
1134
    /// Encoding.
1135
0
    pub fn code(&self) -> u8 {
1136
0
        self.code
1137
0
    }
1138
1139
    /// Name.
1140
0
    pub fn glyph(&self) -> u16 {
1141
0
        self.glyph.get()
1142
0
    }
1143
}
1144
1145
impl FixedSize for EncodingSupplement {
1146
    const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1147
}