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_kern.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 OtKern<'a> {
9
0
    fn min_byte_range(&self) -> Range<usize> {
10
0
        0..self.subtable_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 OtKern<'_> {
19
    type Args = ();
20
}
21
22
impl<'a> FontRead<'a> for OtKern<'a> {
23
1.15k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
24
        #[allow(clippy::absurd_extreme_comparisons)]
25
1.15k
        if data.len() < Self::MIN_SIZE {
26
2
            return Err(ReadError::OutOfBounds);
27
1.15k
        }
28
1.15k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
29
0
            return Err(ReadError::OutOfBounds);
30
        };
31
1.15k
        Ok(Self { data })
32
1.15k
    }
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 OtKernFixedHeader {
40
    pub version: BigEndian<u16>,
41
    pub n_tables: BigEndian<u16>,
42
}
43
44
#[allow(clippy::absurd_extreme_comparisons)]
45
const _: () = assert!(std::mem::size_of::<OtKernFixedHeader>() <= OtKern::MIN_SIZE);
46
47
/// The OpenType [kerning](https://learn.microsoft.com/en-us/typography/opentype/spec/kern) table.
48
#[derive(Clone)]
49
pub struct OtKern<'a> {
50
    data: TableDataRef<'a, OtKernFixedHeader>,
51
}
52
53
#[allow(clippy::needless_lifetimes)]
54
impl<'a> OtKern<'a> {
55
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
56
    basic_table_impls!(impl_the_methods);
57
58
    /// Table version number—set to 0.
59
0
    pub fn version(&self) -> u16 {
60
0
        self.data.header().version.get()
61
0
    }
62
63
    /// Number of subtables in the kerning table.
64
5.34k
    pub fn n_tables(&self) -> u16 {
65
5.34k
        self.data.header().n_tables.get()
66
5.34k
    }
67
68
    /// Data for subtables, immediately following the header.
69
5.34k
    pub fn subtable_data(&self) -> &'a [u8] {
70
5.34k
        let range = self.subtable_data_byte_range();
71
5.34k
        self.offset_data()
72
5.34k
            .read_array(range)
73
5.34k
            .ok()
74
5.34k
            .unwrap_or_default()
75
5.34k
    }
76
77
5.34k
    pub fn version_byte_range(&self) -> Range<usize> {
78
5.34k
        let start = 0;
79
5.34k
        let end = start + u16::RAW_BYTE_LEN;
80
5.34k
        start..end
81
5.34k
    }
82
83
5.34k
    pub fn n_tables_byte_range(&self) -> Range<usize> {
84
5.34k
        let start = self.version_byte_range().end;
85
5.34k
        let end = start + u16::RAW_BYTE_LEN;
86
5.34k
        start..end
87
5.34k
    }
88
89
5.34k
    pub fn subtable_data_byte_range(&self) -> Range<usize> {
90
5.34k
        let start = self.n_tables_byte_range().end;
91
5.34k
        let end = start
92
5.34k
            + self.offset_data().len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
93
5.34k
        start..end
94
5.34k
    }
95
}
96
97
const _: () = assert!(FontData::default_data_long_enough(OtKern::MIN_SIZE));
98
99
impl Default for OtKern<'_> {
100
0
    fn default() -> Self {
101
        Self {
102
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
103
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
104
        }
105
0
    }
106
}
107
108
impl<'a> MinByteRange<'a> for AatKern<'a> {
109
0
    fn min_byte_range(&self) -> Range<usize> {
110
0
        0..self.subtable_data_byte_range().end
111
0
    }
112
0
    fn min_table_bytes(&self) -> &'a [u8] {
113
0
        let range = self.min_byte_range();
114
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
115
0
    }
116
}
117
118
impl ReadArgs for AatKern<'_> {
119
    type Args = ();
120
}
121
122
impl<'a> FontRead<'a> for AatKern<'a> {
123
135
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
124
        #[allow(clippy::absurd_extreme_comparisons)]
125
135
        if data.len() < Self::MIN_SIZE {
126
2
            return Err(ReadError::OutOfBounds);
127
133
        }
128
133
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
129
0
            return Err(ReadError::OutOfBounds);
130
        };
131
133
        Ok(Self { data })
132
135
    }
133
}
134
135
/// The fields at the start of the table, which are read directly.
136
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
137
#[repr(C, packed)]
138
#[doc(hidden)]
139
pub struct AatKernFixedHeader {
140
    pub version: BigEndian<MajorMinor>,
141
    pub n_tables: BigEndian<u32>,
142
}
143
144
#[allow(clippy::absurd_extreme_comparisons)]
145
const _: () = assert!(std::mem::size_of::<AatKernFixedHeader>() <= AatKern::MIN_SIZE);
146
147
/// The Apple Advanced Typography [kerning](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html) table.
148
#[derive(Clone)]
149
pub struct AatKern<'a> {
150
    data: TableDataRef<'a, AatKernFixedHeader>,
151
}
152
153
#[allow(clippy::needless_lifetimes)]
154
impl<'a> AatKern<'a> {
155
    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
156
    basic_table_impls!(impl_the_methods);
157
158
    /// The version number of the kerning table (0x00010000 for the current version).
159
0
    pub fn version(&self) -> MajorMinor {
160
0
        self.data.header().version.get()
161
0
    }
162
163
    /// The number of subtables included in the kerning table.
164
588
    pub fn n_tables(&self) -> u32 {
165
588
        self.data.header().n_tables.get()
166
588
    }
167
168
    /// Data for subtables, immediately following the header.    
169
588
    pub fn subtable_data(&self) -> &'a [u8] {
170
588
        let range = self.subtable_data_byte_range();
171
588
        self.offset_data()
172
588
            .read_array(range)
173
588
            .ok()
174
588
            .unwrap_or_default()
175
588
    }
176
177
588
    pub fn version_byte_range(&self) -> Range<usize> {
178
588
        let start = 0;
179
588
        let end = start + MajorMinor::RAW_BYTE_LEN;
180
588
        start..end
181
588
    }
182
183
588
    pub fn n_tables_byte_range(&self) -> Range<usize> {
184
588
        let start = self.version_byte_range().end;
185
588
        let end = start + u32::RAW_BYTE_LEN;
186
588
        start..end
187
588
    }
188
189
588
    pub fn subtable_data_byte_range(&self) -> Range<usize> {
190
588
        let start = self.n_tables_byte_range().end;
191
588
        let end = start
192
588
            + self.offset_data().len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
193
588
        start..end
194
588
    }
195
}
196
197
const _: () = assert!(FontData::default_data_long_enough(AatKern::MIN_SIZE));
198
199
impl Default for AatKern<'_> {
200
0
    fn default() -> Self {
201
        Self {
202
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
203
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
204
        }
205
0
    }
206
}
207
208
impl<'a> MinByteRange<'a> for OtSubtable<'a> {
209
0
    fn min_byte_range(&self) -> Range<usize> {
210
0
        0..self.data_byte_range().end
211
0
    }
212
0
    fn min_table_bytes(&self) -> &'a [u8] {
213
0
        let range = self.min_byte_range();
214
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
215
0
    }
216
}
217
218
impl ReadArgs for OtSubtable<'_> {
219
    type Args = ();
220
}
221
222
impl<'a> FontRead<'a> for OtSubtable<'a> {
223
14.5k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
224
        #[allow(clippy::absurd_extreme_comparisons)]
225
14.5k
        if data.len() < Self::MIN_SIZE {
226
367
            return Err(ReadError::OutOfBounds);
227
14.1k
        }
228
14.1k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
229
0
            return Err(ReadError::OutOfBounds);
230
        };
231
14.1k
        Ok(Self { data })
232
14.5k
    }
233
}
234
235
/// The fields at the start of the table, which are read directly.
236
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
237
#[repr(C, packed)]
238
#[doc(hidden)]
239
pub struct OtSubtableFixedHeader {
240
    pub version: BigEndian<u16>,
241
    pub length: BigEndian<u16>,
242
    pub coverage: BigEndian<u16>,
243
}
244
245
#[allow(clippy::absurd_extreme_comparisons)]
246
const _: () = assert!(std::mem::size_of::<OtSubtableFixedHeader>() <= OtSubtable::MIN_SIZE);
247
248
/// A subtable in an OT `kern` table.
249
#[derive(Clone)]
250
pub struct OtSubtable<'a> {
251
    data: TableDataRef<'a, OtSubtableFixedHeader>,
252
}
253
254
#[allow(clippy::needless_lifetimes)]
255
impl<'a> OtSubtable<'a> {
256
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
257
    basic_table_impls!(impl_the_methods);
258
259
    /// Kern subtable version number-- set to 0.
260
0
    pub fn version(&self) -> u16 {
261
0
        self.data.header().version.get()
262
0
    }
263
264
    /// The length of this subtable in bytes, including this header.
265
0
    pub fn length(&self) -> u16 {
266
0
        self.data.header().length.get()
267
0
    }
268
269
    /// Circumstances under which this table is used.
270
23.1k
    pub fn coverage(&self) -> u16 {
271
23.1k
        self.data.header().coverage.get()
272
23.1k
    }
273
274
    /// Subtable specific data.
275
7.08k
    pub fn data(&self) -> &'a [u8] {
276
7.08k
        let range = self.data_byte_range();
277
7.08k
        self.offset_data()
278
7.08k
            .read_array(range)
279
7.08k
            .ok()
280
7.08k
            .unwrap_or_default()
281
7.08k
    }
282
283
7.08k
    pub fn version_byte_range(&self) -> Range<usize> {
284
7.08k
        let start = 0;
285
7.08k
        let end = start + u16::RAW_BYTE_LEN;
286
7.08k
        start..end
287
7.08k
    }
288
289
7.08k
    pub fn length_byte_range(&self) -> Range<usize> {
290
7.08k
        let start = self.version_byte_range().end;
291
7.08k
        let end = start + u16::RAW_BYTE_LEN;
292
7.08k
        start..end
293
7.08k
    }
294
295
7.08k
    pub fn coverage_byte_range(&self) -> Range<usize> {
296
7.08k
        let start = self.length_byte_range().end;
297
7.08k
        let end = start + u16::RAW_BYTE_LEN;
298
7.08k
        start..end
299
7.08k
    }
300
301
7.08k
    pub fn data_byte_range(&self) -> Range<usize> {
302
7.08k
        let start = self.coverage_byte_range().end;
303
7.08k
        let end = start
304
7.08k
            + self.offset_data().len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
305
7.08k
        start..end
306
7.08k
    }
307
}
308
309
const _: () = assert!(FontData::default_data_long_enough(OtSubtable::MIN_SIZE));
310
311
impl Default for OtSubtable<'_> {
312
0
    fn default() -> Self {
313
        Self {
314
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
315
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
316
        }
317
0
    }
318
}
319
320
impl<'a> MinByteRange<'a> for AatSubtable<'a> {
321
0
    fn min_byte_range(&self) -> Range<usize> {
322
0
        0..self.data_byte_range().end
323
0
    }
324
0
    fn min_table_bytes(&self) -> &'a [u8] {
325
0
        let range = self.min_byte_range();
326
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
327
0
    }
328
}
329
330
impl ReadArgs for AatSubtable<'_> {
331
    type Args = ();
332
}
333
334
impl<'a> FontRead<'a> for AatSubtable<'a> {
335
1.40k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
336
        #[allow(clippy::absurd_extreme_comparisons)]
337
1.40k
        if data.len() < Self::MIN_SIZE {
338
44
            return Err(ReadError::OutOfBounds);
339
1.36k
        }
340
1.36k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
341
0
            return Err(ReadError::OutOfBounds);
342
        };
343
1.36k
        Ok(Self { data })
344
1.40k
    }
345
}
346
347
/// The fields at the start of the table, which are read directly.
348
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
349
#[repr(C, packed)]
350
#[doc(hidden)]
351
pub struct AatSubtableFixedHeader {
352
    pub length: BigEndian<u32>,
353
    pub coverage: BigEndian<u16>,
354
    pub tuple_index: BigEndian<u16>,
355
}
356
357
#[allow(clippy::absurd_extreme_comparisons)]
358
const _: () = assert!(std::mem::size_of::<AatSubtableFixedHeader>() <= AatSubtable::MIN_SIZE);
359
360
/// A subtable in an AAT `kern` table.
361
#[derive(Clone)]
362
pub struct AatSubtable<'a> {
363
    data: TableDataRef<'a, AatSubtableFixedHeader>,
364
}
365
366
#[allow(clippy::needless_lifetimes)]
367
impl<'a> AatSubtable<'a> {
368
    pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
369
    basic_table_impls!(impl_the_methods);
370
371
    /// The length of this subtable in bytes, including this header.
372
0
    pub fn length(&self) -> u32 {
373
0
        self.data.header().length.get()
374
0
    }
375
376
    /// Circumstances under which this table is used.
377
2.74k
    pub fn coverage(&self) -> u16 {
378
2.74k
        self.data.header().coverage.get()
379
2.74k
    }
380
381
    /// The tuple index (used for variations fonts). This value specifies which tuple this subtable covers.
382
0
    pub fn tuple_index(&self) -> u16 {
383
0
        self.data.header().tuple_index.get()
384
0
    }
385
386
    /// Subtable specific data.
387
1.03k
    pub fn data(&self) -> &'a [u8] {
388
1.03k
        let range = self.data_byte_range();
389
1.03k
        self.offset_data()
390
1.03k
            .read_array(range)
391
1.03k
            .ok()
392
1.03k
            .unwrap_or_default()
393
1.03k
    }
394
395
1.03k
    pub fn length_byte_range(&self) -> Range<usize> {
396
1.03k
        let start = 0;
397
1.03k
        let end = start + u32::RAW_BYTE_LEN;
398
1.03k
        start..end
399
1.03k
    }
400
401
1.03k
    pub fn coverage_byte_range(&self) -> Range<usize> {
402
1.03k
        let start = self.length_byte_range().end;
403
1.03k
        let end = start + u16::RAW_BYTE_LEN;
404
1.03k
        start..end
405
1.03k
    }
406
407
1.03k
    pub fn tuple_index_byte_range(&self) -> Range<usize> {
408
1.03k
        let start = self.coverage_byte_range().end;
409
1.03k
        let end = start + u16::RAW_BYTE_LEN;
410
1.03k
        start..end
411
1.03k
    }
412
413
1.03k
    pub fn data_byte_range(&self) -> Range<usize> {
414
1.03k
        let start = self.tuple_index_byte_range().end;
415
1.03k
        let end = start
416
1.03k
            + self.offset_data().len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
417
1.03k
        start..end
418
1.03k
    }
419
}
420
421
const _: () = assert!(FontData::default_data_long_enough(AatSubtable::MIN_SIZE));
422
423
impl Default for AatSubtable<'_> {
424
0
    fn default() -> Self {
425
        Self {
426
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
427
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
428
        }
429
0
    }
430
}
431
432
impl<'a> MinByteRange<'a> for Subtable0<'a> {
433
0
    fn min_byte_range(&self) -> Range<usize> {
434
0
        0..self.pairs_byte_range().end
435
0
    }
436
0
    fn min_table_bytes(&self) -> &'a [u8] {
437
0
        let range = self.min_byte_range();
438
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
439
0
    }
440
}
441
442
impl ReadArgs for Subtable0<'_> {
443
    type Args = ();
444
}
445
446
impl<'a> FontRead<'a> for Subtable0<'a> {
447
446
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
448
        #[allow(clippy::absurd_extreme_comparisons)]
449
446
        if data.len() < Self::MIN_SIZE {
450
184
            return Err(ReadError::OutOfBounds);
451
262
        }
452
262
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
453
0
            return Err(ReadError::OutOfBounds);
454
        };
455
262
        Ok(Self { data })
456
446
    }
457
}
458
459
/// The fields at the start of the table, which are read directly.
460
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
461
#[repr(C, packed)]
462
#[doc(hidden)]
463
pub struct Subtable0FixedHeader {
464
    pub n_pairs: BigEndian<u16>,
465
    pub search_range: BigEndian<u16>,
466
    pub entry_selector: BigEndian<u16>,
467
    pub range_shift: BigEndian<u16>,
468
}
469
470
#[allow(clippy::absurd_extreme_comparisons)]
471
const _: () = assert!(std::mem::size_of::<Subtable0FixedHeader>() <= Subtable0::MIN_SIZE);
472
473
/// The type 0 `kern` subtable.
474
#[derive(Clone)]
475
pub struct Subtable0<'a> {
476
    data: TableDataRef<'a, Subtable0FixedHeader>,
477
}
478
479
#[allow(clippy::needless_lifetimes)]
480
impl<'a> Subtable0<'a> {
481
    pub const MIN_SIZE: usize =
482
        (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
483
    basic_table_impls!(impl_the_methods);
484
485
    /// The number of kerning pairs in this subtable.
486
2.15k
    pub fn n_pairs(&self) -> u16 {
487
2.15k
        self.data.header().n_pairs.get()
488
2.15k
    }
489
490
    /// The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the subtable.
491
0
    pub fn search_range(&self) -> u16 {
492
0
        self.data.header().search_range.get()
493
0
    }
494
495
    /// This is calculated as log2 of the largest power of two less than or equal to the value of nPairs. This value indicates how many iterations of the search loop have to be made. For example, in a list of eight items, there would be three iterations of the loop.
496
0
    pub fn entry_selector(&self) -> u16 {
497
0
        self.data.header().entry_selector.get()
498
0
    }
499
500
    /// The value of nPairs minus the largest power of two less than or equal to nPairs. This is multiplied by the size in bytes of an entry in the table.
501
0
    pub fn range_shift(&self) -> u16 {
502
0
        self.data.header().range_shift.get()
503
0
    }
504
505
    /// Kerning records.
506
2.15k
    pub fn pairs(&self) -> &'a [Subtable0Pair] {
507
2.15k
        let range = self.pairs_byte_range();
508
2.15k
        self.offset_data()
509
2.15k
            .read_array(range)
510
2.15k
            .ok()
511
2.15k
            .unwrap_or_default()
512
2.15k
    }
513
514
2.15k
    pub fn n_pairs_byte_range(&self) -> Range<usize> {
515
2.15k
        let start = 0;
516
2.15k
        let end = start + u16::RAW_BYTE_LEN;
517
2.15k
        start..end
518
2.15k
    }
519
520
2.15k
    pub fn search_range_byte_range(&self) -> Range<usize> {
521
2.15k
        let start = self.n_pairs_byte_range().end;
522
2.15k
        let end = start + u16::RAW_BYTE_LEN;
523
2.15k
        start..end
524
2.15k
    }
525
526
2.15k
    pub fn entry_selector_byte_range(&self) -> Range<usize> {
527
2.15k
        let start = self.search_range_byte_range().end;
528
2.15k
        let end = start + u16::RAW_BYTE_LEN;
529
2.15k
        start..end
530
2.15k
    }
531
532
2.15k
    pub fn range_shift_byte_range(&self) -> Range<usize> {
533
2.15k
        let start = self.entry_selector_byte_range().end;
534
2.15k
        let end = start + u16::RAW_BYTE_LEN;
535
2.15k
        start..end
536
2.15k
    }
537
538
2.15k
    pub fn pairs_byte_range(&self) -> Range<usize> {
539
2.15k
        let n_pairs = self.n_pairs();
540
2.15k
        let start = self.range_shift_byte_range().end;
541
2.15k
        let end =
542
2.15k
            start + (transforms::to_usize(n_pairs)).saturating_mul(Subtable0Pair::RAW_BYTE_LEN);
543
2.15k
        start..end
544
2.15k
    }
545
}
546
547
const _: () = assert!(FontData::default_data_long_enough(Subtable0::MIN_SIZE));
548
549
impl Default for Subtable0<'_> {
550
0
    fn default() -> Self {
551
        Self {
552
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
553
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
554
        }
555
0
    }
556
}
557
558
impl<'a> MinByteRange<'a> for Subtable2ClassTable<'a> {
559
0
    fn min_byte_range(&self) -> Range<usize> {
560
0
        0..self.offsets_byte_range().end
561
0
    }
562
0
    fn min_table_bytes(&self) -> &'a [u8] {
563
0
        let range = self.min_byte_range();
564
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
565
0
    }
566
}
567
568
impl ReadArgs for Subtable2ClassTable<'_> {
569
    type Args = ();
570
}
571
572
impl<'a> FontRead<'a> for Subtable2ClassTable<'a> {
573
163
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
574
        #[allow(clippy::absurd_extreme_comparisons)]
575
163
        if data.len() < Self::MIN_SIZE {
576
4
            return Err(ReadError::OutOfBounds);
577
159
        }
578
159
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
579
0
            return Err(ReadError::OutOfBounds);
580
        };
581
159
        Ok(Self { data })
582
163
    }
583
}
584
585
/// The fields at the start of the table, which are read directly.
586
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
587
#[repr(C, packed)]
588
#[doc(hidden)]
589
pub struct Subtable2ClassTableFixedHeader {
590
    pub first_glyph: BigEndian<GlyphId16>,
591
    pub n_glyphs: BigEndian<u16>,
592
}
593
594
#[allow(clippy::absurd_extreme_comparisons)]
595
const _: () =
596
    assert!(std::mem::size_of::<Subtable2ClassTableFixedHeader>() <= Subtable2ClassTable::MIN_SIZE);
597
598
/// Class table for the type 2 `kern` subtable.
599
#[derive(Clone)]
600
pub struct Subtable2ClassTable<'a> {
601
    data: TableDataRef<'a, Subtable2ClassTableFixedHeader>,
602
}
603
604
#[allow(clippy::needless_lifetimes)]
605
impl<'a> Subtable2ClassTable<'a> {
606
    pub const MIN_SIZE: usize = (GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
607
    basic_table_impls!(impl_the_methods);
608
609
    /// First glyph in class range.
610
1.54k
    pub fn first_glyph(&self) -> GlyphId16 {
611
1.54k
        self.data.header().first_glyph.get()
612
1.54k
    }
613
614
    /// Number of glyph in class range.
615
1.54k
    pub fn n_glyphs(&self) -> u16 {
616
1.54k
        self.data.header().n_glyphs.get()
617
1.54k
    }
618
619
    /// The offsets array for all of the glyphs in the range.
620
1.39k
    pub fn offsets(&self) -> &'a [BigEndian<u16>] {
621
1.39k
        let range = self.offsets_byte_range();
622
1.39k
        self.offset_data()
623
1.39k
            .read_array(range)
624
1.39k
            .ok()
625
1.39k
            .unwrap_or_default()
626
1.39k
    }
627
628
1.39k
    pub fn first_glyph_byte_range(&self) -> Range<usize> {
629
1.39k
        let start = 0;
630
1.39k
        let end = start + GlyphId16::RAW_BYTE_LEN;
631
1.39k
        start..end
632
1.39k
    }
633
634
1.39k
    pub fn n_glyphs_byte_range(&self) -> Range<usize> {
635
1.39k
        let start = self.first_glyph_byte_range().end;
636
1.39k
        let end = start + u16::RAW_BYTE_LEN;
637
1.39k
        start..end
638
1.39k
    }
639
640
1.39k
    pub fn offsets_byte_range(&self) -> Range<usize> {
641
1.39k
        let n_glyphs = self.n_glyphs();
642
1.39k
        let start = self.n_glyphs_byte_range().end;
643
1.39k
        let end = start + (transforms::to_usize(n_glyphs)).saturating_mul(u16::RAW_BYTE_LEN);
644
1.39k
        start..end
645
1.39k
    }
646
}
647
648
const _: () = assert!(FontData::default_data_long_enough(
649
    Subtable2ClassTable::MIN_SIZE
650
));
651
652
impl Default for Subtable2ClassTable<'_> {
653
0
    fn default() -> Self {
654
        Self {
655
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
656
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
657
        }
658
0
    }
659
}
660
661
impl<'a> MinByteRange<'a> for Subtable3<'a> {
662
0
    fn min_byte_range(&self) -> Range<usize> {
663
0
        0..self.kern_index_byte_range().end
664
0
    }
665
0
    fn min_table_bytes(&self) -> &'a [u8] {
666
0
        let range = self.min_byte_range();
667
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
668
0
    }
669
}
670
671
impl ReadArgs for Subtable3<'_> {
672
    type Args = ();
673
}
674
675
impl<'a> FontRead<'a> for Subtable3<'a> {
676
217
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
677
        #[allow(clippy::absurd_extreme_comparisons)]
678
217
        if data.len() < Self::MIN_SIZE {
679
9
            return Err(ReadError::OutOfBounds);
680
208
        }
681
208
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
682
0
            return Err(ReadError::OutOfBounds);
683
        };
684
208
        Ok(Self { data })
685
217
    }
686
}
687
688
/// The fields at the start of the table, which are read directly.
689
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
690
#[repr(C, packed)]
691
#[doc(hidden)]
692
pub struct Subtable3FixedHeader {
693
    pub glyph_count: BigEndian<u16>,
694
    pub kern_value_count: u8,
695
    pub left_class_count: u8,
696
    pub right_class_count: u8,
697
    pub flags: u8,
698
}
699
700
#[allow(clippy::absurd_extreme_comparisons)]
701
const _: () = assert!(std::mem::size_of::<Subtable3FixedHeader>() <= Subtable3::MIN_SIZE);
702
703
/// The type 3 'kern' subtable.
704
#[derive(Clone)]
705
pub struct Subtable3<'a> {
706
    data: TableDataRef<'a, Subtable3FixedHeader>,
707
}
708
709
#[allow(clippy::needless_lifetimes)]
710
impl<'a> Subtable3<'a> {
711
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
712
        + u8::RAW_BYTE_LEN
713
        + u8::RAW_BYTE_LEN
714
        + u8::RAW_BYTE_LEN
715
        + u8::RAW_BYTE_LEN);
716
    basic_table_impls!(impl_the_methods);
717
718
    /// The number of glyphs in this font.
719
7.53k
    pub fn glyph_count(&self) -> u16 {
720
7.53k
        self.data.header().glyph_count.get()
721
7.53k
    }
722
723
    /// The number of kerning values.
724
5.78k
    pub fn kern_value_count(&self) -> u8 {
725
5.78k
        self.data.header().kern_value_count
726
5.78k
    }
727
728
    /// The number of left-hand classes.
729
361
    pub fn left_class_count(&self) -> u8 {
730
361
        self.data.header().left_class_count
731
361
    }
732
733
    /// The number of right-hand classes.
734
722
    pub fn right_class_count(&self) -> u8 {
735
722
        self.data.header().right_class_count
736
722
    }
737
738
    /// Set to zero (reserved for future use).
739
0
    pub fn flags(&self) -> u8 {
740
0
        self.data.header().flags
741
0
    }
742
743
    /// The kerning values.
744
170
    pub fn kern_value(&self) -> &'a [BigEndian<i16>] {
745
170
        let range = self.kern_value_byte_range();
746
170
        self.offset_data()
747
170
            .read_array(range)
748
170
            .ok()
749
170
            .unwrap_or_default()
750
170
    }
751
752
    /// The left-hand classes.
753
4.09k
    pub fn left_class(&self) -> &'a [u8] {
754
4.09k
        let range = self.left_class_byte_range();
755
4.09k
        self.offset_data()
756
4.09k
            .read_array(range)
757
4.09k
            .ok()
758
4.09k
            .unwrap_or_default()
759
4.09k
    }
760
761
    /// The right-hand classes.
762
1.15k
    pub fn right_class(&self) -> &'a [u8] {
763
1.15k
        let range = self.right_class_byte_range();
764
1.15k
        self.offset_data()
765
1.15k
            .read_array(range)
766
1.15k
            .ok()
767
1.15k
            .unwrap_or_default()
768
1.15k
    }
769
770
    /// The indices into the kernValue array.
771
361
    pub fn kern_index(&self) -> &'a [u8] {
772
361
        let range = self.kern_index_byte_range();
773
361
        self.offset_data()
774
361
            .read_array(range)
775
361
            .ok()
776
361
            .unwrap_or_default()
777
361
    }
778
779
5.78k
    pub fn glyph_count_byte_range(&self) -> Range<usize> {
780
5.78k
        let start = 0;
781
5.78k
        let end = start + u16::RAW_BYTE_LEN;
782
5.78k
        start..end
783
5.78k
    }
784
785
5.78k
    pub fn kern_value_count_byte_range(&self) -> Range<usize> {
786
5.78k
        let start = self.glyph_count_byte_range().end;
787
5.78k
        let end = start + u8::RAW_BYTE_LEN;
788
5.78k
        start..end
789
5.78k
    }
790
791
5.78k
    pub fn left_class_count_byte_range(&self) -> Range<usize> {
792
5.78k
        let start = self.kern_value_count_byte_range().end;
793
5.78k
        let end = start + u8::RAW_BYTE_LEN;
794
5.78k
        start..end
795
5.78k
    }
796
797
5.78k
    pub fn right_class_count_byte_range(&self) -> Range<usize> {
798
5.78k
        let start = self.left_class_count_byte_range().end;
799
5.78k
        let end = start + u8::RAW_BYTE_LEN;
800
5.78k
        start..end
801
5.78k
    }
802
803
5.78k
    pub fn flags_byte_range(&self) -> Range<usize> {
804
5.78k
        let start = self.right_class_count_byte_range().end;
805
5.78k
        let end = start + u8::RAW_BYTE_LEN;
806
5.78k
        start..end
807
5.78k
    }
808
809
5.78k
    pub fn kern_value_byte_range(&self) -> Range<usize> {
810
5.78k
        let kern_value_count = self.kern_value_count();
811
5.78k
        let start = self.flags_byte_range().end;
812
5.78k
        let end =
813
5.78k
            start + (transforms::to_usize(kern_value_count)).saturating_mul(i16::RAW_BYTE_LEN);
814
5.78k
        start..end
815
5.78k
    }
816
817
5.61k
    pub fn left_class_byte_range(&self) -> Range<usize> {
818
5.61k
        let glyph_count = self.glyph_count();
819
5.61k
        let start = self.kern_value_byte_range().end;
820
5.61k
        let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u8::RAW_BYTE_LEN);
821
5.61k
        start..end
822
5.61k
    }
823
824
1.51k
    pub fn right_class_byte_range(&self) -> Range<usize> {
825
1.51k
        let glyph_count = self.glyph_count();
826
1.51k
        let start = self.left_class_byte_range().end;
827
1.51k
        let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u8::RAW_BYTE_LEN);
828
1.51k
        start..end
829
1.51k
    }
830
831
361
    pub fn kern_index_byte_range(&self) -> Range<usize> {
832
361
        let left_class_count = self.left_class_count();
833
361
        let right_class_count = self.right_class_count();
834
361
        let start = self.right_class_byte_range().end;
835
361
        let end = start
836
361
            + (transforms::add_multiply(left_class_count, 0_usize, right_class_count))
837
361
                .saturating_mul(u8::RAW_BYTE_LEN);
838
361
        start..end
839
361
    }
840
}
841
842
const _: () = assert!(FontData::default_data_long_enough(Subtable3::MIN_SIZE));
843
844
impl Default for Subtable3<'_> {
845
0
    fn default() -> Self {
846
        Self {
847
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
848
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
849
        }
850
0
    }
851
}