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_bitmap.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
/// [BitmapSize](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmapsize-record) record.
9
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
10
#[repr(C)]
11
#[repr(packed)]
12
pub struct BitmapSize {
13
    /// Offset to IndexSubtableList, from beginning of EBLC/CBLC.
14
    pub index_subtable_list_offset: BigEndian<u32>,
15
    /// Total size in bytes of the IndexSubtableList including its array of IndexSubtables.
16
    pub index_subtable_list_size: BigEndian<u32>,
17
    /// Number of IndexSubtables in the IndexSubtableList.
18
    pub number_of_index_subtables: BigEndian<u32>,
19
    /// Not used; set to 0.
20
    pub color_ref: BigEndian<u32>,
21
    /// Line metrics for text rendered horizontally.
22
    pub hori: SbitLineMetrics,
23
    /// Line metrics for text rendered vertically.
24
    pub vert: SbitLineMetrics,
25
    /// Lowest glyph index for this size.
26
    pub start_glyph_index: BigEndian<GlyphId16>,
27
    /// Highest glyph index for this size.
28
    pub end_glyph_index: BigEndian<GlyphId16>,
29
    /// Horizontal pixels per em.
30
    pub ppem_x: u8,
31
    /// Vertical pixels per em.
32
    pub ppem_y: u8,
33
    /// The Microsoft rasterizer v.1.7 or greater supports the following
34
    /// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC).
35
    pub bit_depth: u8,
36
    /// Vertical or horizontal.
37
    pub flags: BigEndian<BitmapFlags>,
38
}
39
40
impl BitmapSize {
41
    /// Offset to IndexSubtableList, from beginning of EBLC/CBLC.
42
0
    pub fn index_subtable_list_offset(&self) -> u32 {
43
0
        self.index_subtable_list_offset.get()
44
0
    }
45
46
    /// Total size in bytes of the IndexSubtableList including its array of IndexSubtables.
47
0
    pub fn index_subtable_list_size(&self) -> u32 {
48
0
        self.index_subtable_list_size.get()
49
0
    }
50
51
    /// Number of IndexSubtables in the IndexSubtableList.
52
0
    pub fn number_of_index_subtables(&self) -> u32 {
53
0
        self.number_of_index_subtables.get()
54
0
    }
55
56
    /// Not used; set to 0.
57
0
    pub fn color_ref(&self) -> u32 {
58
0
        self.color_ref.get()
59
0
    }
60
61
    /// Line metrics for text rendered horizontally.
62
0
    pub fn hori(&self) -> &SbitLineMetrics {
63
0
        &self.hori
64
0
    }
65
66
    /// Line metrics for text rendered vertically.
67
0
    pub fn vert(&self) -> &SbitLineMetrics {
68
0
        &self.vert
69
0
    }
70
71
    /// Lowest glyph index for this size.
72
0
    pub fn start_glyph_index(&self) -> GlyphId16 {
73
0
        self.start_glyph_index.get()
74
0
    }
75
76
    /// Highest glyph index for this size.
77
0
    pub fn end_glyph_index(&self) -> GlyphId16 {
78
0
        self.end_glyph_index.get()
79
0
    }
80
81
    /// Horizontal pixels per em.
82
0
    pub fn ppem_x(&self) -> u8 {
83
0
        self.ppem_x
84
0
    }
85
86
    /// Vertical pixels per em.
87
0
    pub fn ppem_y(&self) -> u8 {
88
0
        self.ppem_y
89
0
    }
90
91
    /// The Microsoft rasterizer v.1.7 or greater supports the following
92
    /// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC).
93
0
    pub fn bit_depth(&self) -> u8 {
94
0
        self.bit_depth
95
0
    }
96
97
    /// Vertical or horizontal.
98
0
    pub fn flags(&self) -> BitmapFlags {
99
0
        self.flags.get()
100
0
    }
101
}
102
103
impl FixedSize for BitmapSize {
104
    const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN
105
        + u32::RAW_BYTE_LEN
106
        + u32::RAW_BYTE_LEN
107
        + u32::RAW_BYTE_LEN
108
        + SbitLineMetrics::RAW_BYTE_LEN
109
        + SbitLineMetrics::RAW_BYTE_LEN
110
        + GlyphId16::RAW_BYTE_LEN
111
        + GlyphId16::RAW_BYTE_LEN
112
        + u8::RAW_BYTE_LEN
113
        + u8::RAW_BYTE_LEN
114
        + u8::RAW_BYTE_LEN
115
        + BitmapFlags::RAW_BYTE_LEN;
116
}
117
118
/// [SbitLineMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record) record.
119
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
120
#[repr(C)]
121
#[repr(packed)]
122
pub struct SbitLineMetrics {
123
    pub ascender: BigEndian<i8>,
124
    pub descender: BigEndian<i8>,
125
    pub width_max: u8,
126
    pub caret_slope_numerator: BigEndian<i8>,
127
    pub caret_slope_denominator: u8,
128
    pub caret_offset: BigEndian<i8>,
129
    pub min_origin_sb: BigEndian<i8>,
130
    pub min_advance_sb: BigEndian<i8>,
131
    pub max_before_bl: BigEndian<i8>,
132
    pub min_after_bl: BigEndian<i8>,
133
    pub pad1: BigEndian<i8>,
134
    pub pad2: BigEndian<i8>,
135
}
136
137
impl SbitLineMetrics {
138
0
    pub fn ascender(&self) -> i8 {
139
0
        self.ascender.get()
140
0
    }
141
142
0
    pub fn descender(&self) -> i8 {
143
0
        self.descender.get()
144
0
    }
145
146
0
    pub fn width_max(&self) -> u8 {
147
0
        self.width_max
148
0
    }
149
150
0
    pub fn caret_slope_numerator(&self) -> i8 {
151
0
        self.caret_slope_numerator.get()
152
0
    }
153
154
0
    pub fn caret_slope_denominator(&self) -> u8 {
155
0
        self.caret_slope_denominator
156
0
    }
157
158
0
    pub fn caret_offset(&self) -> i8 {
159
0
        self.caret_offset.get()
160
0
    }
161
162
0
    pub fn min_origin_sb(&self) -> i8 {
163
0
        self.min_origin_sb.get()
164
0
    }
165
166
0
    pub fn min_advance_sb(&self) -> i8 {
167
0
        self.min_advance_sb.get()
168
0
    }
169
170
0
    pub fn max_before_bl(&self) -> i8 {
171
0
        self.max_before_bl.get()
172
0
    }
173
174
0
    pub fn min_after_bl(&self) -> i8 {
175
0
        self.min_after_bl.get()
176
0
    }
177
178
0
    pub fn pad1(&self) -> i8 {
179
0
        self.pad1.get()
180
0
    }
181
182
0
    pub fn pad2(&self) -> i8 {
183
0
        self.pad2.get()
184
0
    }
185
}
186
187
impl FixedSize for SbitLineMetrics {
188
    const RAW_BYTE_LEN: usize = i8::RAW_BYTE_LEN
189
        + i8::RAW_BYTE_LEN
190
        + u8::RAW_BYTE_LEN
191
        + i8::RAW_BYTE_LEN
192
        + u8::RAW_BYTE_LEN
193
        + i8::RAW_BYTE_LEN
194
        + i8::RAW_BYTE_LEN
195
        + i8::RAW_BYTE_LEN
196
        + i8::RAW_BYTE_LEN
197
        + i8::RAW_BYTE_LEN
198
        + i8::RAW_BYTE_LEN
199
        + i8::RAW_BYTE_LEN;
200
}
201
202
/// [Bitmap flags](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmap-flags).
203
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
204
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
205
#[repr(transparent)]
206
pub struct BitmapFlags {
207
    bits: u8,
208
}
209
210
impl BitmapFlags {
211
    /// Horizontal
212
    pub const HORIZONTAL_METRICS: Self = Self { bits: 0x01 };
213
214
    /// Vertical
215
    pub const VERTICAL_METRICS: Self = Self { bits: 0x02 };
216
}
217
218
impl BitmapFlags {
219
    ///  Returns an empty set of flags.
220
    #[inline]
221
0
    pub const fn empty() -> Self {
222
0
        Self { bits: 0 }
223
0
    }
224
225
    /// Returns the set containing all flags.
226
    #[inline]
227
0
    pub const fn all() -> Self {
228
0
        Self {
229
0
            bits: Self::HORIZONTAL_METRICS.bits | Self::VERTICAL_METRICS.bits,
230
0
        }
231
0
    }
232
233
    /// Returns the raw value of the flags currently stored.
234
    #[inline]
235
0
    pub const fn bits(&self) -> u8 {
236
0
        self.bits
237
0
    }
238
239
    /// Convert from underlying bit representation, unless that
240
    /// representation contains bits that do not correspond to a flag.
241
    #[inline]
242
0
    pub const fn from_bits(bits: u8) -> Option<Self> {
243
0
        if (bits & !Self::all().bits()) == 0 {
244
0
            Some(Self { bits })
245
        } else {
246
0
            None
247
        }
248
0
    }
249
250
    /// Convert from underlying bit representation, dropping any bits
251
    /// that do not correspond to flags.
252
    #[inline]
253
0
    pub const fn from_bits_truncate(bits: u8) -> Self {
254
0
        Self {
255
0
            bits: bits & Self::all().bits,
256
0
        }
257
0
    }
258
259
    /// Returns `true` if no flags are currently stored.
260
    #[inline]
261
0
    pub const fn is_empty(&self) -> bool {
262
0
        self.bits() == Self::empty().bits()
263
0
    }
264
265
    /// Returns `true` if there are flags common to both `self` and `other`.
266
    #[inline]
267
0
    pub const fn intersects(&self, other: Self) -> bool {
268
0
        !(Self {
269
0
            bits: self.bits & other.bits,
270
0
        })
271
0
        .is_empty()
272
0
    }
273
274
    /// Returns `true` if all of the flags in `other` are contained within `self`.
275
    #[inline]
276
0
    pub const fn contains(&self, other: Self) -> bool {
277
0
        (self.bits & other.bits) == other.bits
278
0
    }
279
280
    /// Inserts the specified flags in-place.
281
    #[inline]
282
0
    pub fn insert(&mut self, other: Self) {
283
0
        self.bits |= other.bits;
284
0
    }
285
286
    /// Removes the specified flags in-place.
287
    #[inline]
288
0
    pub fn remove(&mut self, other: Self) {
289
0
        self.bits &= !other.bits;
290
0
    }
291
292
    /// Toggles the specified flags in-place.
293
    #[inline]
294
0
    pub fn toggle(&mut self, other: Self) {
295
0
        self.bits ^= other.bits;
296
0
    }
297
298
    /// Returns the intersection between the flags in `self` and
299
    /// `other`.
300
    ///
301
    /// Specifically, the returned set contains only the flags which are
302
    /// present in *both* `self` *and* `other`.
303
    ///
304
    /// This is equivalent to using the `&` operator (e.g.
305
    /// [`ops::BitAnd`]), as in `flags & other`.
306
    ///
307
    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
308
    #[inline]
309
    #[must_use]
310
0
    pub const fn intersection(self, other: Self) -> Self {
311
0
        Self {
312
0
            bits: self.bits & other.bits,
313
0
        }
314
0
    }
315
316
    /// Returns the union of between the flags in `self` and `other`.
317
    ///
318
    /// Specifically, the returned set contains all flags which are
319
    /// present in *either* `self` *or* `other`, including any which are
320
    /// present in both.
321
    ///
322
    /// This is equivalent to using the `|` operator (e.g.
323
    /// [`ops::BitOr`]), as in `flags | other`.
324
    ///
325
    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
326
    #[inline]
327
    #[must_use]
328
0
    pub const fn union(self, other: Self) -> Self {
329
0
        Self {
330
0
            bits: self.bits | other.bits,
331
0
        }
332
0
    }
333
334
    /// Returns the difference between the flags in `self` and `other`.
335
    ///
336
    /// Specifically, the returned set contains all flags present in
337
    /// `self`, except for the ones present in `other`.
338
    ///
339
    /// It is also conceptually equivalent to the "bit-clear" operation:
340
    /// `flags & !other` (and this syntax is also supported).
341
    ///
342
    /// This is equivalent to using the `-` operator (e.g.
343
    /// [`ops::Sub`]), as in `flags - other`.
344
    ///
345
    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
346
    #[inline]
347
    #[must_use]
348
0
    pub const fn difference(self, other: Self) -> Self {
349
0
        Self {
350
0
            bits: self.bits & !other.bits,
351
0
        }
352
0
    }
353
}
354
355
impl std::ops::BitOr for BitmapFlags {
356
    type Output = Self;
357
358
    /// Returns the union of the two sets of flags.
359
    #[inline]
360
0
    fn bitor(self, other: BitmapFlags) -> Self {
361
0
        Self {
362
0
            bits: self.bits | other.bits,
363
0
        }
364
0
    }
365
}
366
367
impl std::ops::BitOrAssign for BitmapFlags {
368
    /// Adds the set of flags.
369
    #[inline]
370
0
    fn bitor_assign(&mut self, other: Self) {
371
0
        self.bits |= other.bits;
372
0
    }
373
}
374
375
impl std::ops::BitXor for BitmapFlags {
376
    type Output = Self;
377
378
    /// Returns the left flags, but with all the right flags toggled.
379
    #[inline]
380
0
    fn bitxor(self, other: Self) -> Self {
381
0
        Self {
382
0
            bits: self.bits ^ other.bits,
383
0
        }
384
0
    }
385
}
386
387
impl std::ops::BitXorAssign for BitmapFlags {
388
    /// Toggles the set of flags.
389
    #[inline]
390
0
    fn bitxor_assign(&mut self, other: Self) {
391
0
        self.bits ^= other.bits;
392
0
    }
393
}
394
395
impl std::ops::BitAnd for BitmapFlags {
396
    type Output = Self;
397
398
    /// Returns the intersection between the two sets of flags.
399
    #[inline]
400
0
    fn bitand(self, other: Self) -> Self {
401
0
        Self {
402
0
            bits: self.bits & other.bits,
403
0
        }
404
0
    }
405
}
406
407
impl std::ops::BitAndAssign for BitmapFlags {
408
    /// Disables all flags disabled in the set.
409
    #[inline]
410
0
    fn bitand_assign(&mut self, other: Self) {
411
0
        self.bits &= other.bits;
412
0
    }
413
}
414
415
impl std::ops::Sub for BitmapFlags {
416
    type Output = Self;
417
418
    /// Returns the set difference of the two sets of flags.
419
    #[inline]
420
0
    fn sub(self, other: Self) -> Self {
421
0
        Self {
422
0
            bits: self.bits & !other.bits,
423
0
        }
424
0
    }
425
}
426
427
impl std::ops::SubAssign for BitmapFlags {
428
    /// Disables all flags enabled in the set.
429
    #[inline]
430
0
    fn sub_assign(&mut self, other: Self) {
431
0
        self.bits &= !other.bits;
432
0
    }
433
}
434
435
impl std::ops::Not for BitmapFlags {
436
    type Output = Self;
437
438
    /// Returns the complement of this set of flags.
439
    #[inline]
440
0
    fn not(self) -> Self {
441
0
        Self { bits: !self.bits } & Self::all()
442
0
    }
443
}
444
445
impl std::fmt::Debug for BitmapFlags {
446
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
447
0
        let members: &[(&str, Self)] = &[
448
0
            ("HORIZONTAL_METRICS", Self::HORIZONTAL_METRICS),
449
0
            ("VERTICAL_METRICS", Self::VERTICAL_METRICS),
450
0
        ];
451
0
        let mut first = true;
452
0
        for (name, value) in members {
453
0
            if self.contains(*value) {
454
0
                if !first {
455
0
                    f.write_str(" | ")?;
456
0
                }
457
0
                first = false;
458
0
                f.write_str(name)?;
459
0
            }
460
        }
461
0
        if first {
462
0
            f.write_str("(empty)")?;
463
0
        }
464
0
        Ok(())
465
0
    }
466
}
467
468
impl std::fmt::Binary for BitmapFlags {
469
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
470
0
        std::fmt::Binary::fmt(&self.bits, f)
471
0
    }
472
}
473
474
impl std::fmt::Octal for BitmapFlags {
475
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
476
0
        std::fmt::Octal::fmt(&self.bits, f)
477
0
    }
478
}
479
480
impl std::fmt::LowerHex for BitmapFlags {
481
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
482
0
        std::fmt::LowerHex::fmt(&self.bits, f)
483
0
    }
484
}
485
486
impl std::fmt::UpperHex for BitmapFlags {
487
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
488
0
        std::fmt::UpperHex::fmt(&self.bits, f)
489
0
    }
490
}
491
492
impl font_types::Scalar for BitmapFlags {
493
    type Raw = <u8 as font_types::Scalar>::Raw;
494
0
    fn to_raw(self) -> Self::Raw {
495
0
        self.bits().to_raw()
496
0
    }
497
0
    fn from_raw(raw: Self::Raw) -> Self {
498
0
        let t = <u8>::from_raw(raw);
499
0
        Self::from_bits_truncate(t)
500
0
    }
501
}
502
503
/// [BigGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bigglyphmetrics) record.
504
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
505
#[repr(C)]
506
#[repr(packed)]
507
pub struct BigGlyphMetrics {
508
    /// Number of rows of data.
509
    pub height: u8,
510
    /// Number of columns of data.
511
    pub width: u8,
512
    /// Distance in pixels from the horizontal origin to the left edge of the bitmap.
513
    pub hori_bearing_x: BigEndian<i8>,
514
    /// Distance in pixels from the horizontal origin to the top edge of the bitmap.
515
    pub hori_bearing_y: BigEndian<i8>,
516
    /// Horizontal advance width in pixels.
517
    pub hori_advance: u8,
518
    /// Distance in pixels from the vertical origin to the left edge of the bitmap.
519
    pub vert_bearing_x: BigEndian<i8>,
520
    /// Distance in pixels from the vertical origin to the top edge of the bitmap.
521
    pub vert_bearing_y: BigEndian<i8>,
522
    /// Vertical advance width in pixels.
523
    pub vert_advance: u8,
524
}
525
526
impl BigGlyphMetrics {
527
    /// Number of rows of data.
528
0
    pub fn height(&self) -> u8 {
529
0
        self.height
530
0
    }
531
532
    /// Number of columns of data.
533
0
    pub fn width(&self) -> u8 {
534
0
        self.width
535
0
    }
536
537
    /// Distance in pixels from the horizontal origin to the left edge of the bitmap.
538
0
    pub fn hori_bearing_x(&self) -> i8 {
539
0
        self.hori_bearing_x.get()
540
0
    }
541
542
    /// Distance in pixels from the horizontal origin to the top edge of the bitmap.
543
0
    pub fn hori_bearing_y(&self) -> i8 {
544
0
        self.hori_bearing_y.get()
545
0
    }
546
547
    /// Horizontal advance width in pixels.
548
0
    pub fn hori_advance(&self) -> u8 {
549
0
        self.hori_advance
550
0
    }
551
552
    /// Distance in pixels from the vertical origin to the left edge of the bitmap.
553
0
    pub fn vert_bearing_x(&self) -> i8 {
554
0
        self.vert_bearing_x.get()
555
0
    }
556
557
    /// Distance in pixels from the vertical origin to the top edge of the bitmap.
558
0
    pub fn vert_bearing_y(&self) -> i8 {
559
0
        self.vert_bearing_y.get()
560
0
    }
561
562
    /// Vertical advance width in pixels.
563
0
    pub fn vert_advance(&self) -> u8 {
564
0
        self.vert_advance
565
0
    }
566
}
567
568
impl FixedSize for BigGlyphMetrics {
569
    const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
570
        + u8::RAW_BYTE_LEN
571
        + i8::RAW_BYTE_LEN
572
        + i8::RAW_BYTE_LEN
573
        + u8::RAW_BYTE_LEN
574
        + i8::RAW_BYTE_LEN
575
        + i8::RAW_BYTE_LEN
576
        + u8::RAW_BYTE_LEN;
577
}
578
579
/// [SmallGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#smallglyphmetrics) record.
580
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
581
#[repr(C)]
582
#[repr(packed)]
583
pub struct SmallGlyphMetrics {
584
    /// Number of rows of data.
585
    pub height: u8,
586
    /// Number of columns of data.
587
    pub width: u8,
588
    /// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text).
589
    pub bearing_x: BigEndian<i8>,
590
    /// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text).
591
    pub bearing_y: BigEndian<i8>,
592
    /// Horizontal or vertical advance width in pixels.
593
    pub advance: u8,
594
}
595
596
impl SmallGlyphMetrics {
597
    /// Number of rows of data.
598
0
    pub fn height(&self) -> u8 {
599
0
        self.height
600
0
    }
601
602
    /// Number of columns of data.
603
0
    pub fn width(&self) -> u8 {
604
0
        self.width
605
0
    }
606
607
    /// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text).
608
0
    pub fn bearing_x(&self) -> i8 {
609
0
        self.bearing_x.get()
610
0
    }
611
612
    /// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text).
613
0
    pub fn bearing_y(&self) -> i8 {
614
0
        self.bearing_y.get()
615
0
    }
616
617
    /// Horizontal or vertical advance width in pixels.
618
0
    pub fn advance(&self) -> u8 {
619
0
        self.advance
620
0
    }
621
}
622
623
impl FixedSize for SmallGlyphMetrics {
624
    const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
625
        + u8::RAW_BYTE_LEN
626
        + i8::RAW_BYTE_LEN
627
        + i8::RAW_BYTE_LEN
628
        + u8::RAW_BYTE_LEN;
629
}
630
631
impl<'a> MinByteRange<'a> for IndexSubtableList<'a> {
632
0
    fn min_byte_range(&self) -> Range<usize> {
633
0
        0..self.index_subtable_records_byte_range().end
634
0
    }
635
0
    fn min_table_bytes(&self) -> &'a [u8] {
636
0
        let range = self.min_byte_range();
637
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
638
0
    }
639
}
640
641
impl ReadArgs for IndexSubtableList<'_> {
642
    type Args = u32;
643
}
644
645
impl<'a> FontRead<'a> for IndexSubtableList<'a> {
646
0
    fn read_with_args(data: FontData<'a>, args: u32) -> Result<Self, ReadError> {
647
0
        let number_of_index_subtables = args;
648
649
        #[allow(clippy::absurd_extreme_comparisons)]
650
0
        if data.len() < Self::MIN_SIZE {
651
0
            return Err(ReadError::OutOfBounds);
652
0
        }
653
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
654
0
            return Err(ReadError::OutOfBounds);
655
        };
656
0
        Ok(Self {
657
0
            data,
658
0
            number_of_index_subtables,
659
0
        })
660
0
    }
661
}
662
663
impl<'a> IndexSubtableList<'a> {
664
    /// A constructor that requires additional arguments.
665
    ///
666
    /// This type requires some external state in order to be
667
    /// parsed.
668
0
    pub fn read(data: FontData<'a>, number_of_index_subtables: u32) -> Result<Self, ReadError> {
669
0
        let args = number_of_index_subtables;
670
0
        Self::read_with_args(data, args)
671
0
    }
672
}
673
674
/// The fields at the start of the table, which are read directly.
675
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
676
#[repr(C, packed)]
677
#[doc(hidden)]
678
pub struct IndexSubtableListFixedHeader {}
679
680
#[allow(clippy::absurd_extreme_comparisons)]
681
const _: () =
682
    assert!(std::mem::size_of::<IndexSubtableListFixedHeader>() <= IndexSubtableList::MIN_SIZE);
683
684
/// [IndexSubtableList](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablelist) table.
685
#[derive(Clone)]
686
pub struct IndexSubtableList<'a> {
687
    data: TableDataRef<'a, IndexSubtableListFixedHeader>,
688
    number_of_index_subtables: u32,
689
}
690
691
#[allow(clippy::needless_lifetimes)]
692
impl<'a> IndexSubtableList<'a> {
693
    pub const MIN_SIZE: usize = 0;
694
    basic_table_impls!(impl_the_methods);
695
696
    /// Array of IndexSubtableRecords.
697
0
    pub fn index_subtable_records(&self) -> &'a [IndexSubtableRecord] {
698
0
        let range = self.index_subtable_records_byte_range();
699
0
        self.offset_data()
700
0
            .read_array(range)
701
0
            .ok()
702
0
            .unwrap_or_default()
703
0
    }
704
705
0
    pub(crate) fn number_of_index_subtables(&self) -> u32 {
706
0
        self.number_of_index_subtables
707
0
    }
708
709
0
    pub fn index_subtable_records_byte_range(&self) -> Range<usize> {
710
0
        let number_of_index_subtables = self.number_of_index_subtables();
711
0
        let start = 0;
712
0
        let end = start
713
0
            + (transforms::to_usize(number_of_index_subtables))
714
0
                .saturating_mul(IndexSubtableRecord::RAW_BYTE_LEN);
715
0
        start..end
716
0
    }
717
}
718
719
#[allow(clippy::absurd_extreme_comparisons)]
720
const _: () = assert!(FontData::default_data_long_enough(
721
    IndexSubtableList::MIN_SIZE
722
));
723
724
impl Default for IndexSubtableList<'_> {
725
0
    fn default() -> Self {
726
        Self {
727
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
728
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
729
0
            number_of_index_subtables: Default::default(),
730
        }
731
0
    }
732
}
733
734
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
735
#[repr(C)]
736
#[repr(packed)]
737
pub struct IndexSubtableRecord {
738
    /// First glyph ID of this range.
739
    pub first_glyph_index: BigEndian<GlyphId16>,
740
    /// Last glyph ID of this range (inclusive).
741
    pub last_glyph_index: BigEndian<GlyphId16>,
742
    /// Offset to an IndexSubtable from the start of the IndexSubtableList.
743
    pub index_subtable_offset: BigEndian<Offset32>,
744
}
745
746
impl IndexSubtableRecord {
747
    /// First glyph ID of this range.
748
0
    pub fn first_glyph_index(&self) -> GlyphId16 {
749
0
        self.first_glyph_index.get()
750
0
    }
751
752
    /// Last glyph ID of this range (inclusive).
753
0
    pub fn last_glyph_index(&self) -> GlyphId16 {
754
0
        self.last_glyph_index.get()
755
0
    }
756
757
    /// Offset to an IndexSubtable from the start of the IndexSubtableList.
758
0
    pub fn index_subtable_offset(&self) -> Offset32 {
759
0
        self.index_subtable_offset.get()
760
0
    }
761
762
    /// Offset to an IndexSubtable from the start of the IndexSubtableList.
763
    ///
764
    /// The `data` argument should be retrieved from the parent table
765
    /// By calling its `offset_data` method.
766
0
    pub fn index_subtable<'a>(&self, data: FontData<'a>) -> Result<IndexSubtable<'a>, ReadError> {
767
0
        let args = (self.last_glyph_index(), self.first_glyph_index());
768
0
        self.index_subtable_offset().resolve_with_args(data, args)
769
0
    }
770
}
771
772
impl FixedSize for IndexSubtableRecord {
773
    const RAW_BYTE_LEN: usize =
774
        GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
775
}
776
777
impl Format<u16> for IndexSubtable1<'_> {
778
    const FORMAT: u16 = 1;
779
}
780
781
impl<'a> MinByteRange<'a> for IndexSubtable1<'a> {
782
0
    fn min_byte_range(&self) -> Range<usize> {
783
0
        0..self.sbit_offsets_byte_range().end
784
0
    }
785
0
    fn min_table_bytes(&self) -> &'a [u8] {
786
0
        let range = self.min_byte_range();
787
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
788
0
    }
789
}
790
791
impl ReadArgs for IndexSubtable1<'_> {
792
    type Args = (GlyphId16, GlyphId16);
793
}
794
795
impl<'a> FontRead<'a> for IndexSubtable1<'a> {
796
0
    fn read_with_args(data: FontData<'a>, args: (GlyphId16, GlyphId16)) -> Result<Self, ReadError> {
797
0
        let (last_glyph_index, first_glyph_index) = args;
798
799
        #[allow(clippy::absurd_extreme_comparisons)]
800
0
        if data.len() < Self::MIN_SIZE {
801
0
            return Err(ReadError::OutOfBounds);
802
0
        }
803
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
804
0
            return Err(ReadError::OutOfBounds);
805
        };
806
0
        Ok(Self {
807
0
            data,
808
0
            last_glyph_index,
809
0
            first_glyph_index,
810
0
        })
811
0
    }
812
}
813
814
impl<'a> IndexSubtable1<'a> {
815
    /// A constructor that requires additional arguments.
816
    ///
817
    /// This type requires some external state in order to be
818
    /// parsed.
819
0
    pub fn read(
820
0
        data: FontData<'a>,
821
0
        last_glyph_index: GlyphId16,
822
0
        first_glyph_index: GlyphId16,
823
0
    ) -> Result<Self, ReadError> {
824
0
        let args = (last_glyph_index, first_glyph_index);
825
0
        Self::read_with_args(data, args)
826
0
    }
827
}
828
829
/// The fields at the start of the table, which are read directly.
830
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
831
#[repr(C, packed)]
832
#[doc(hidden)]
833
pub struct IndexSubtable1FixedHeader {
834
    pub index_format: BigEndian<u16>,
835
    pub image_format: BigEndian<u16>,
836
    pub image_data_offset: BigEndian<u32>,
837
}
838
839
#[allow(clippy::absurd_extreme_comparisons)]
840
const _: () = assert!(std::mem::size_of::<IndexSubtable1FixedHeader>() <= IndexSubtable1::MIN_SIZE);
841
842
/// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets.
843
#[derive(Clone)]
844
pub struct IndexSubtable1<'a> {
845
    data: TableDataRef<'a, IndexSubtable1FixedHeader>,
846
    last_glyph_index: GlyphId16,
847
    first_glyph_index: GlyphId16,
848
}
849
850
#[allow(clippy::needless_lifetimes)]
851
impl<'a> IndexSubtable1<'a> {
852
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
853
    basic_table_impls!(impl_the_methods);
854
855
    /// Format of this IndexSubTable.
856
0
    pub fn index_format(&self) -> u16 {
857
0
        self.data.header().index_format.get()
858
0
    }
859
860
    /// Format of EBDT image data.
861
0
    pub fn image_format(&self) -> u16 {
862
0
        self.data.header().image_format.get()
863
0
    }
864
865
    /// Offset to image data in EBDT table.
866
0
    pub fn image_data_offset(&self) -> u32 {
867
0
        self.data.header().image_data_offset.get()
868
0
    }
869
870
0
    pub fn sbit_offsets(&self) -> &'a [BigEndian<u32>] {
871
0
        let range = self.sbit_offsets_byte_range();
872
0
        self.offset_data()
873
0
            .read_array(range)
874
0
            .ok()
875
0
            .unwrap_or_default()
876
0
    }
877
878
0
    pub(crate) fn last_glyph_index(&self) -> GlyphId16 {
879
0
        self.last_glyph_index
880
0
    }
881
882
0
    pub(crate) fn first_glyph_index(&self) -> GlyphId16 {
883
0
        self.first_glyph_index
884
0
    }
885
886
0
    pub fn index_format_byte_range(&self) -> Range<usize> {
887
0
        let start = 0;
888
0
        let end = start + u16::RAW_BYTE_LEN;
889
0
        start..end
890
0
    }
891
892
0
    pub fn image_format_byte_range(&self) -> Range<usize> {
893
0
        let start = self.index_format_byte_range().end;
894
0
        let end = start + u16::RAW_BYTE_LEN;
895
0
        start..end
896
0
    }
897
898
0
    pub fn image_data_offset_byte_range(&self) -> Range<usize> {
899
0
        let start = self.image_format_byte_range().end;
900
0
        let end = start + u32::RAW_BYTE_LEN;
901
0
        start..end
902
0
    }
903
904
0
    pub fn sbit_offsets_byte_range(&self) -> Range<usize> {
905
0
        let last_glyph_index = self.last_glyph_index();
906
0
        let first_glyph_index = self.first_glyph_index();
907
0
        let start = self.image_data_offset_byte_range().end;
908
0
        let end = start
909
0
            + (transforms::subtract_add_two(last_glyph_index, first_glyph_index))
910
0
                .saturating_mul(u32::RAW_BYTE_LEN);
911
0
        start..end
912
0
    }
913
}
914
915
const _: () = assert!(FontData::default_data_long_enough(IndexSubtable1::MIN_SIZE));
916
917
impl Default for IndexSubtable1<'_> {
918
0
    fn default() -> Self {
919
        Self {
920
0
            data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
921
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
922
0
            last_glyph_index: Default::default(),
923
0
            first_glyph_index: Default::default(),
924
        }
925
0
    }
926
}
927
928
impl Format<u16> for IndexSubtable2<'_> {
929
    const FORMAT: u16 = 2;
930
}
931
932
impl<'a> MinByteRange<'a> for IndexSubtable2<'a> {
933
0
    fn min_byte_range(&self) -> Range<usize> {
934
0
        0..self.big_metrics_byte_range().end
935
0
    }
936
0
    fn min_table_bytes(&self) -> &'a [u8] {
937
0
        let range = self.min_byte_range();
938
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
939
0
    }
940
}
941
942
impl ReadArgs for IndexSubtable2<'_> {
943
    type Args = ();
944
}
945
946
impl<'a> FontRead<'a> for IndexSubtable2<'a> {
947
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
948
        #[allow(clippy::absurd_extreme_comparisons)]
949
0
        if data.len() < Self::MIN_SIZE {
950
0
            return Err(ReadError::OutOfBounds);
951
0
        }
952
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
953
0
            return Err(ReadError::OutOfBounds);
954
        };
955
0
        Ok(Self { data })
956
0
    }
957
}
958
959
/// The fields at the start of the table, which are read directly.
960
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
961
#[repr(C, packed)]
962
#[doc(hidden)]
963
pub struct IndexSubtable2FixedHeader {
964
    pub index_format: BigEndian<u16>,
965
    pub image_format: BigEndian<u16>,
966
    pub image_data_offset: BigEndian<u32>,
967
    pub image_size: BigEndian<u32>,
968
    pub big_metrics: BigGlyphMetrics,
969
}
970
971
#[allow(clippy::absurd_extreme_comparisons)]
972
const _: () = assert!(std::mem::size_of::<IndexSubtable2FixedHeader>() <= IndexSubtable2::MIN_SIZE);
973
974
/// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics.
975
#[derive(Clone)]
976
pub struct IndexSubtable2<'a> {
977
    data: TableDataRef<'a, IndexSubtable2FixedHeader>,
978
}
979
980
#[allow(clippy::needless_lifetimes)]
981
impl<'a> IndexSubtable2<'a> {
982
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
983
        + u16::RAW_BYTE_LEN
984
        + u32::RAW_BYTE_LEN
985
        + u32::RAW_BYTE_LEN
986
        + BigGlyphMetrics::RAW_BYTE_LEN);
987
    basic_table_impls!(impl_the_methods);
988
989
    /// Format of this IndexSubTable.
990
0
    pub fn index_format(&self) -> u16 {
991
0
        self.data.header().index_format.get()
992
0
    }
993
994
    /// Format of EBDT image data.
995
0
    pub fn image_format(&self) -> u16 {
996
0
        self.data.header().image_format.get()
997
0
    }
998
999
    /// Offset to image data in EBDT table.
1000
0
    pub fn image_data_offset(&self) -> u32 {
1001
0
        self.data.header().image_data_offset.get()
1002
0
    }
1003
1004
    /// All the glyphs are of the same size.
1005
0
    pub fn image_size(&self) -> u32 {
1006
0
        self.data.header().image_size.get()
1007
0
    }
1008
1009
    /// All glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned.
1010
0
    pub fn big_metrics(&self) -> &'a BigGlyphMetrics {
1011
0
        &self.data.header().big_metrics
1012
0
    }
1013
1014
0
    pub fn index_format_byte_range(&self) -> Range<usize> {
1015
0
        let start = 0;
1016
0
        let end = start + u16::RAW_BYTE_LEN;
1017
0
        start..end
1018
0
    }
1019
1020
0
    pub fn image_format_byte_range(&self) -> Range<usize> {
1021
0
        let start = self.index_format_byte_range().end;
1022
0
        let end = start + u16::RAW_BYTE_LEN;
1023
0
        start..end
1024
0
    }
1025
1026
0
    pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1027
0
        let start = self.image_format_byte_range().end;
1028
0
        let end = start + u32::RAW_BYTE_LEN;
1029
0
        start..end
1030
0
    }
1031
1032
0
    pub fn image_size_byte_range(&self) -> Range<usize> {
1033
0
        let start = self.image_data_offset_byte_range().end;
1034
0
        let end = start + u32::RAW_BYTE_LEN;
1035
0
        start..end
1036
0
    }
1037
1038
0
    pub fn big_metrics_byte_range(&self) -> Range<usize> {
1039
0
        let start = self.image_size_byte_range().end;
1040
0
        let end = start + BigGlyphMetrics::RAW_BYTE_LEN;
1041
0
        start..end
1042
0
    }
1043
}
1044
1045
impl Format<u16> for IndexSubtable3<'_> {
1046
    const FORMAT: u16 = 3;
1047
}
1048
1049
impl<'a> MinByteRange<'a> for IndexSubtable3<'a> {
1050
0
    fn min_byte_range(&self) -> Range<usize> {
1051
0
        0..self.sbit_offsets_byte_range().end
1052
0
    }
1053
0
    fn min_table_bytes(&self) -> &'a [u8] {
1054
0
        let range = self.min_byte_range();
1055
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1056
0
    }
1057
}
1058
1059
impl ReadArgs for IndexSubtable3<'_> {
1060
    type Args = (GlyphId16, GlyphId16);
1061
}
1062
1063
impl<'a> FontRead<'a> for IndexSubtable3<'a> {
1064
0
    fn read_with_args(data: FontData<'a>, args: (GlyphId16, GlyphId16)) -> Result<Self, ReadError> {
1065
0
        let (last_glyph_index, first_glyph_index) = args;
1066
1067
        #[allow(clippy::absurd_extreme_comparisons)]
1068
0
        if data.len() < Self::MIN_SIZE {
1069
0
            return Err(ReadError::OutOfBounds);
1070
0
        }
1071
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1072
0
            return Err(ReadError::OutOfBounds);
1073
        };
1074
0
        Ok(Self {
1075
0
            data,
1076
0
            last_glyph_index,
1077
0
            first_glyph_index,
1078
0
        })
1079
0
    }
1080
}
1081
1082
impl<'a> IndexSubtable3<'a> {
1083
    /// A constructor that requires additional arguments.
1084
    ///
1085
    /// This type requires some external state in order to be
1086
    /// parsed.
1087
0
    pub fn read(
1088
0
        data: FontData<'a>,
1089
0
        last_glyph_index: GlyphId16,
1090
0
        first_glyph_index: GlyphId16,
1091
0
    ) -> Result<Self, ReadError> {
1092
0
        let args = (last_glyph_index, first_glyph_index);
1093
0
        Self::read_with_args(data, args)
1094
0
    }
1095
}
1096
1097
/// The fields at the start of the table, which are read directly.
1098
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1099
#[repr(C, packed)]
1100
#[doc(hidden)]
1101
pub struct IndexSubtable3FixedHeader {
1102
    pub index_format: BigEndian<u16>,
1103
    pub image_format: BigEndian<u16>,
1104
    pub image_data_offset: BigEndian<u32>,
1105
}
1106
1107
#[allow(clippy::absurd_extreme_comparisons)]
1108
const _: () = assert!(std::mem::size_of::<IndexSubtable3FixedHeader>() <= IndexSubtable3::MIN_SIZE);
1109
1110
/// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets.
1111
#[derive(Clone)]
1112
pub struct IndexSubtable3<'a> {
1113
    data: TableDataRef<'a, IndexSubtable3FixedHeader>,
1114
    last_glyph_index: GlyphId16,
1115
    first_glyph_index: GlyphId16,
1116
}
1117
1118
#[allow(clippy::needless_lifetimes)]
1119
impl<'a> IndexSubtable3<'a> {
1120
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1121
    basic_table_impls!(impl_the_methods);
1122
1123
    /// Format of this IndexSubTable.
1124
0
    pub fn index_format(&self) -> u16 {
1125
0
        self.data.header().index_format.get()
1126
0
    }
1127
1128
    /// Format of EBDT image data.
1129
0
    pub fn image_format(&self) -> u16 {
1130
0
        self.data.header().image_format.get()
1131
0
    }
1132
1133
    /// Offset to image data in EBDT table.
1134
0
    pub fn image_data_offset(&self) -> u32 {
1135
0
        self.data.header().image_data_offset.get()
1136
0
    }
1137
1138
0
    pub fn sbit_offsets(&self) -> &'a [BigEndian<u16>] {
1139
0
        let range = self.sbit_offsets_byte_range();
1140
0
        self.offset_data()
1141
0
            .read_array(range)
1142
0
            .ok()
1143
0
            .unwrap_or_default()
1144
0
    }
1145
1146
0
    pub(crate) fn last_glyph_index(&self) -> GlyphId16 {
1147
0
        self.last_glyph_index
1148
0
    }
1149
1150
0
    pub(crate) fn first_glyph_index(&self) -> GlyphId16 {
1151
0
        self.first_glyph_index
1152
0
    }
1153
1154
0
    pub fn index_format_byte_range(&self) -> Range<usize> {
1155
0
        let start = 0;
1156
0
        let end = start + u16::RAW_BYTE_LEN;
1157
0
        start..end
1158
0
    }
1159
1160
0
    pub fn image_format_byte_range(&self) -> Range<usize> {
1161
0
        let start = self.index_format_byte_range().end;
1162
0
        let end = start + u16::RAW_BYTE_LEN;
1163
0
        start..end
1164
0
    }
1165
1166
0
    pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1167
0
        let start = self.image_format_byte_range().end;
1168
0
        let end = start + u32::RAW_BYTE_LEN;
1169
0
        start..end
1170
0
    }
1171
1172
0
    pub fn sbit_offsets_byte_range(&self) -> Range<usize> {
1173
0
        let last_glyph_index = self.last_glyph_index();
1174
0
        let first_glyph_index = self.first_glyph_index();
1175
0
        let start = self.image_data_offset_byte_range().end;
1176
0
        let end = start
1177
0
            + (transforms::subtract_add_two(last_glyph_index, first_glyph_index))
1178
0
                .saturating_mul(u16::RAW_BYTE_LEN);
1179
0
        start..end
1180
0
    }
1181
}
1182
1183
impl Format<u16> for IndexSubtable4<'_> {
1184
    const FORMAT: u16 = 4;
1185
}
1186
1187
impl<'a> MinByteRange<'a> for IndexSubtable4<'a> {
1188
0
    fn min_byte_range(&self) -> Range<usize> {
1189
0
        0..self.glyph_array_byte_range().end
1190
0
    }
1191
0
    fn min_table_bytes(&self) -> &'a [u8] {
1192
0
        let range = self.min_byte_range();
1193
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1194
0
    }
1195
}
1196
1197
impl ReadArgs for IndexSubtable4<'_> {
1198
    type Args = ();
1199
}
1200
1201
impl<'a> FontRead<'a> for IndexSubtable4<'a> {
1202
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1203
        #[allow(clippy::absurd_extreme_comparisons)]
1204
0
        if data.len() < Self::MIN_SIZE {
1205
0
            return Err(ReadError::OutOfBounds);
1206
0
        }
1207
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1208
0
            return Err(ReadError::OutOfBounds);
1209
        };
1210
0
        Ok(Self { data })
1211
0
    }
1212
}
1213
1214
/// The fields at the start of the table, which are read directly.
1215
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1216
#[repr(C, packed)]
1217
#[doc(hidden)]
1218
pub struct IndexSubtable4FixedHeader {
1219
    pub index_format: BigEndian<u16>,
1220
    pub image_format: BigEndian<u16>,
1221
    pub image_data_offset: BigEndian<u32>,
1222
    pub num_glyphs: BigEndian<u32>,
1223
}
1224
1225
#[allow(clippy::absurd_extreme_comparisons)]
1226
const _: () = assert!(std::mem::size_of::<IndexSubtable4FixedHeader>() <= IndexSubtable4::MIN_SIZE);
1227
1228
/// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes.
1229
#[derive(Clone)]
1230
pub struct IndexSubtable4<'a> {
1231
    data: TableDataRef<'a, IndexSubtable4FixedHeader>,
1232
}
1233
1234
#[allow(clippy::needless_lifetimes)]
1235
impl<'a> IndexSubtable4<'a> {
1236
    pub const MIN_SIZE: usize =
1237
        (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
1238
    basic_table_impls!(impl_the_methods);
1239
1240
    /// Format of this IndexSubTable.
1241
0
    pub fn index_format(&self) -> u16 {
1242
0
        self.data.header().index_format.get()
1243
0
    }
1244
1245
    /// Format of EBDT image data.
1246
0
    pub fn image_format(&self) -> u16 {
1247
0
        self.data.header().image_format.get()
1248
0
    }
1249
1250
    /// Offset to image data in EBDT table.
1251
0
    pub fn image_data_offset(&self) -> u32 {
1252
0
        self.data.header().image_data_offset.get()
1253
0
    }
1254
1255
    /// Array length.
1256
0
    pub fn num_glyphs(&self) -> u32 {
1257
0
        self.data.header().num_glyphs.get()
1258
0
    }
1259
1260
    /// One per glyph.
1261
0
    pub fn glyph_array(&self) -> &'a [GlyphIdOffsetPair] {
1262
0
        let range = self.glyph_array_byte_range();
1263
0
        self.offset_data()
1264
0
            .read_array(range)
1265
0
            .ok()
1266
0
            .unwrap_or_default()
1267
0
    }
1268
1269
0
    pub fn index_format_byte_range(&self) -> Range<usize> {
1270
0
        let start = 0;
1271
0
        let end = start + u16::RAW_BYTE_LEN;
1272
0
        start..end
1273
0
    }
1274
1275
0
    pub fn image_format_byte_range(&self) -> Range<usize> {
1276
0
        let start = self.index_format_byte_range().end;
1277
0
        let end = start + u16::RAW_BYTE_LEN;
1278
0
        start..end
1279
0
    }
1280
1281
0
    pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1282
0
        let start = self.image_format_byte_range().end;
1283
0
        let end = start + u32::RAW_BYTE_LEN;
1284
0
        start..end
1285
0
    }
1286
1287
0
    pub fn num_glyphs_byte_range(&self) -> Range<usize> {
1288
0
        let start = self.image_data_offset_byte_range().end;
1289
0
        let end = start + u32::RAW_BYTE_LEN;
1290
0
        start..end
1291
0
    }
1292
1293
0
    pub fn glyph_array_byte_range(&self) -> Range<usize> {
1294
0
        let num_glyphs = self.num_glyphs();
1295
0
        let start = self.num_glyphs_byte_range().end;
1296
0
        let end = start
1297
0
            + (transforms::add(num_glyphs, 1_usize))
1298
0
                .saturating_mul(GlyphIdOffsetPair::RAW_BYTE_LEN);
1299
0
        start..end
1300
0
    }
1301
}
1302
1303
/// [GlyphIdOffsetPair](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#glyphidoffsetpair-record) record.
1304
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1305
#[repr(C)]
1306
#[repr(packed)]
1307
pub struct GlyphIdOffsetPair {
1308
    /// Glyph ID of glyph present.
1309
    pub glyph_id: BigEndian<GlyphId16>,
1310
    /// Location in EBDT.
1311
    pub sbit_offset: BigEndian<u16>,
1312
}
1313
1314
impl GlyphIdOffsetPair {
1315
    /// Glyph ID of glyph present.
1316
0
    pub fn glyph_id(&self) -> GlyphId16 {
1317
0
        self.glyph_id.get()
1318
0
    }
1319
1320
    /// Location in EBDT.
1321
0
    pub fn sbit_offset(&self) -> u16 {
1322
0
        self.sbit_offset.get()
1323
0
    }
1324
}
1325
1326
impl FixedSize for GlyphIdOffsetPair {
1327
    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1328
}
1329
1330
impl Format<u16> for IndexSubtable5<'_> {
1331
    const FORMAT: u16 = 5;
1332
}
1333
1334
impl<'a> MinByteRange<'a> for IndexSubtable5<'a> {
1335
0
    fn min_byte_range(&self) -> Range<usize> {
1336
0
        0..self.glyph_array_byte_range().end
1337
0
    }
1338
0
    fn min_table_bytes(&self) -> &'a [u8] {
1339
0
        let range = self.min_byte_range();
1340
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1341
0
    }
1342
}
1343
1344
impl ReadArgs for IndexSubtable5<'_> {
1345
    type Args = ();
1346
}
1347
1348
impl<'a> FontRead<'a> for IndexSubtable5<'a> {
1349
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1350
        #[allow(clippy::absurd_extreme_comparisons)]
1351
0
        if data.len() < Self::MIN_SIZE {
1352
0
            return Err(ReadError::OutOfBounds);
1353
0
        }
1354
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1355
0
            return Err(ReadError::OutOfBounds);
1356
        };
1357
0
        Ok(Self { data })
1358
0
    }
1359
}
1360
1361
/// The fields at the start of the table, which are read directly.
1362
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1363
#[repr(C, packed)]
1364
#[doc(hidden)]
1365
pub struct IndexSubtable5FixedHeader {
1366
    pub index_format: BigEndian<u16>,
1367
    pub image_format: BigEndian<u16>,
1368
    pub image_data_offset: BigEndian<u32>,
1369
    pub image_size: BigEndian<u32>,
1370
    pub big_metrics: BigGlyphMetrics,
1371
    pub num_glyphs: BigEndian<u32>,
1372
}
1373
1374
#[allow(clippy::absurd_extreme_comparisons)]
1375
const _: () = assert!(std::mem::size_of::<IndexSubtable5FixedHeader>() <= IndexSubtable5::MIN_SIZE);
1376
1377
/// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes
1378
#[derive(Clone)]
1379
pub struct IndexSubtable5<'a> {
1380
    data: TableDataRef<'a, IndexSubtable5FixedHeader>,
1381
}
1382
1383
#[allow(clippy::needless_lifetimes)]
1384
impl<'a> IndexSubtable5<'a> {
1385
    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1386
        + u16::RAW_BYTE_LEN
1387
        + u32::RAW_BYTE_LEN
1388
        + u32::RAW_BYTE_LEN
1389
        + BigGlyphMetrics::RAW_BYTE_LEN
1390
        + u32::RAW_BYTE_LEN);
1391
    basic_table_impls!(impl_the_methods);
1392
1393
    /// Format of this IndexSubTable.
1394
0
    pub fn index_format(&self) -> u16 {
1395
0
        self.data.header().index_format.get()
1396
0
    }
1397
1398
    /// Format of EBDT image data.
1399
0
    pub fn image_format(&self) -> u16 {
1400
0
        self.data.header().image_format.get()
1401
0
    }
1402
1403
    /// Offset to image data in EBDT table.
1404
0
    pub fn image_data_offset(&self) -> u32 {
1405
0
        self.data.header().image_data_offset.get()
1406
0
    }
1407
1408
    /// All glyphs have the same data size.
1409
0
    pub fn image_size(&self) -> u32 {
1410
0
        self.data.header().image_size.get()
1411
0
    }
1412
1413
    /// All glyphs have the same metrics.
1414
0
    pub fn big_metrics(&self) -> &'a BigGlyphMetrics {
1415
0
        &self.data.header().big_metrics
1416
0
    }
1417
1418
    /// Array length.
1419
0
    pub fn num_glyphs(&self) -> u32 {
1420
0
        self.data.header().num_glyphs.get()
1421
0
    }
1422
1423
    /// One per glyph, sorted by glyhph ID.
1424
0
    pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
1425
0
        let range = self.glyph_array_byte_range();
1426
0
        self.offset_data()
1427
0
            .read_array(range)
1428
0
            .ok()
1429
0
            .unwrap_or_default()
1430
0
    }
1431
1432
0
    pub fn index_format_byte_range(&self) -> Range<usize> {
1433
0
        let start = 0;
1434
0
        let end = start + u16::RAW_BYTE_LEN;
1435
0
        start..end
1436
0
    }
1437
1438
0
    pub fn image_format_byte_range(&self) -> Range<usize> {
1439
0
        let start = self.index_format_byte_range().end;
1440
0
        let end = start + u16::RAW_BYTE_LEN;
1441
0
        start..end
1442
0
    }
1443
1444
0
    pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1445
0
        let start = self.image_format_byte_range().end;
1446
0
        let end = start + u32::RAW_BYTE_LEN;
1447
0
        start..end
1448
0
    }
1449
1450
0
    pub fn image_size_byte_range(&self) -> Range<usize> {
1451
0
        let start = self.image_data_offset_byte_range().end;
1452
0
        let end = start + u32::RAW_BYTE_LEN;
1453
0
        start..end
1454
0
    }
1455
1456
0
    pub fn big_metrics_byte_range(&self) -> Range<usize> {
1457
0
        let start = self.image_size_byte_range().end;
1458
0
        let end = start + BigGlyphMetrics::RAW_BYTE_LEN;
1459
0
        start..end
1460
0
    }
1461
1462
0
    pub fn num_glyphs_byte_range(&self) -> Range<usize> {
1463
0
        let start = self.big_metrics_byte_range().end;
1464
0
        let end = start + u32::RAW_BYTE_LEN;
1465
0
        start..end
1466
0
    }
1467
1468
0
    pub fn glyph_array_byte_range(&self) -> Range<usize> {
1469
0
        let num_glyphs = self.num_glyphs();
1470
0
        let start = self.num_glyphs_byte_range().end;
1471
0
        let end =
1472
0
            start + (transforms::to_usize(num_glyphs)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1473
0
        start..end
1474
0
    }
1475
}
1476
1477
/// [EbdtComponent](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#ebdtcomponent-record) record.
1478
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1479
#[repr(C)]
1480
#[repr(packed)]
1481
pub struct BdtComponent {
1482
    /// Component glyph ID.
1483
    pub glyph_id: BigEndian<GlyphId16>,
1484
    /// Position of component left.
1485
    pub x_offset: BigEndian<i8>,
1486
    /// Position of component top.
1487
    pub y_offset: BigEndian<i8>,
1488
}
1489
1490
impl BdtComponent {
1491
    /// Component glyph ID.
1492
0
    pub fn glyph_id(&self) -> GlyphId16 {
1493
0
        self.glyph_id.get()
1494
0
    }
1495
1496
    /// Position of component left.
1497
0
    pub fn x_offset(&self) -> i8 {
1498
0
        self.x_offset.get()
1499
0
    }
1500
1501
    /// Position of component top.
1502
0
    pub fn y_offset(&self) -> i8 {
1503
0
        self.y_offset.get()
1504
0
    }
1505
}
1506
1507
impl FixedSize for BdtComponent {
1508
    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN;
1509
}