write_fonts/generated/
generated_cmap.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8pub use read_fonts::tables::cmap::PlatformId;
9
10/// [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#overview)
11#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Cmap {
14    pub encoding_records: Vec<EncodingRecord>,
15}
16
17impl Cmap {
18    /// Construct a new `Cmap`
19    pub fn new(encoding_records: Vec<EncodingRecord>) -> Self {
20        Self { encoding_records }
21    }
22}
23
24impl FontWrite for Cmap {
25    #[allow(clippy::unnecessary_cast)]
26    fn write_into(&self, writer: &mut TableWriter) {
27        (0 as u16).write_into(writer);
28        (u16::try_from(array_len(&self.encoding_records)).unwrap()).write_into(writer);
29        self.encoding_records.write_into(writer);
30    }
31    fn table_type(&self) -> TableType {
32        TableType::TopLevel(Cmap::TAG)
33    }
34}
35
36impl Validate for Cmap {
37    fn validate_impl(&self, ctx: &mut ValidationCtx) {
38        ctx.in_table("Cmap", |ctx| {
39            ctx.in_field("encoding_records", |ctx| {
40                if self.encoding_records.len() > (u16::MAX as usize) {
41                    ctx.report("array exceeds max length");
42                }
43                self.encoding_records.validate_impl(ctx);
44            });
45        })
46    }
47}
48
49impl TopLevelTable for Cmap {
50    const TAG: Tag = Tag::new(b"cmap");
51}
52
53impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap<'a>> for Cmap {
54    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap<'a>, _: FontData) -> Self {
55        let offset_data = obj.offset_data();
56        Cmap {
57            encoding_records: obj.encoding_records().to_owned_obj(offset_data),
58        }
59    }
60}
61
62#[allow(clippy::needless_lifetimes)]
63impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap<'a>> for Cmap {}
64
65impl<'a> FontRead<'a> for Cmap {
66    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
67        <read_fonts::tables::cmap::Cmap as FontRead>::read(data).map(|x| x.to_owned_table())
68    }
69}
70
71/// [Encoding Record](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#encoding-records-and-encodings)
72#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
73#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
74pub struct EncodingRecord {
75    /// Platform ID.
76    pub platform_id: PlatformId,
77    /// Platform-specific encoding ID.
78    pub encoding_id: u16,
79    /// Byte offset from beginning of the [`Cmap`] table to the subtable for this
80    /// encoding.
81    pub subtable: OffsetMarker<CmapSubtable, WIDTH_32>,
82}
83
84impl EncodingRecord {
85    /// Construct a new `EncodingRecord`
86    pub fn new(platform_id: PlatformId, encoding_id: u16, subtable: CmapSubtable) -> Self {
87        Self {
88            platform_id,
89            encoding_id,
90            subtable: subtable.into(),
91        }
92    }
93}
94
95impl FontWrite for EncodingRecord {
96    fn write_into(&self, writer: &mut TableWriter) {
97        self.platform_id.write_into(writer);
98        self.encoding_id.write_into(writer);
99        self.subtable.write_into(writer);
100    }
101    fn table_type(&self) -> TableType {
102        TableType::Named("EncodingRecord")
103    }
104}
105
106impl Validate for EncodingRecord {
107    fn validate_impl(&self, ctx: &mut ValidationCtx) {
108        ctx.in_table("EncodingRecord", |ctx| {
109            ctx.in_field("subtable", |ctx| {
110                self.subtable.validate_impl(ctx);
111            });
112        })
113    }
114}
115
116impl FromObjRef<read_fonts::tables::cmap::EncodingRecord> for EncodingRecord {
117    fn from_obj_ref(obj: &read_fonts::tables::cmap::EncodingRecord, offset_data: FontData) -> Self {
118        EncodingRecord {
119            platform_id: obj.platform_id(),
120            encoding_id: obj.encoding_id(),
121            subtable: obj.subtable(offset_data).to_owned_table(),
122        }
123    }
124}
125
126impl FontWrite for PlatformId {
127    fn write_into(&self, writer: &mut TableWriter) {
128        let val = *self as u16;
129        writer.write_slice(&val.to_be_bytes())
130    }
131}
132
133/// The different cmap subtable formats.
134#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
135#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
136pub enum CmapSubtable {
137    Format0(Cmap0),
138    Format2(Cmap2),
139    Format4(Cmap4),
140    Format6(Cmap6),
141    Format8(Cmap8),
142    Format10(Cmap10),
143    Format12(Cmap12),
144    Format13(Cmap13),
145    Format14(Cmap14),
146}
147
148impl CmapSubtable {
149    /// Construct a new `Cmap0` subtable
150    pub fn format_0(language: u16, glyph_id_array: Vec<u8>) -> Self {
151        Self::Format0(Cmap0::new(language, glyph_id_array))
152    }
153
154    /// Construct a new `Cmap2` subtable
155    pub fn format_2(length: u16, language: u16, sub_header_keys: Vec<u16>) -> Self {
156        Self::Format2(Cmap2::new(length, language, sub_header_keys))
157    }
158
159    /// Construct a new `Cmap4` subtable
160    pub fn format_4(
161        language: u16,
162        end_code: Vec<u16>,
163        start_code: Vec<u16>,
164        id_delta: Vec<i16>,
165        id_range_offsets: Vec<u16>,
166        glyph_id_array: Vec<u16>,
167    ) -> Self {
168        Self::Format4(Cmap4::new(
169            language,
170            end_code,
171            start_code,
172            id_delta,
173            id_range_offsets,
174            glyph_id_array,
175        ))
176    }
177
178    /// Construct a new `Cmap6` subtable
179    pub fn format_6(
180        length: u16,
181        language: u16,
182        first_code: u16,
183        entry_count: u16,
184        glyph_id_array: Vec<u16>,
185    ) -> Self {
186        Self::Format6(Cmap6::new(
187            length,
188            language,
189            first_code,
190            entry_count,
191            glyph_id_array,
192        ))
193    }
194
195    /// Construct a new `Cmap8` subtable
196    pub fn format_8(
197        length: u32,
198        language: u32,
199        is32: Vec<u8>,
200        num_groups: u32,
201        groups: Vec<SequentialMapGroup>,
202    ) -> Self {
203        Self::Format8(Cmap8::new(length, language, is32, num_groups, groups))
204    }
205
206    /// Construct a new `Cmap10` subtable
207    pub fn format_10(
208        length: u32,
209        language: u32,
210        start_char_code: u32,
211        num_chars: u32,
212        glyph_id_array: Vec<u16>,
213    ) -> Self {
214        Self::Format10(Cmap10::new(
215            length,
216            language,
217            start_char_code,
218            num_chars,
219            glyph_id_array,
220        ))
221    }
222
223    /// Construct a new `Cmap12` subtable
224    pub fn format_12(language: u32, groups: Vec<SequentialMapGroup>) -> Self {
225        Self::Format12(Cmap12::new(language, groups))
226    }
227
228    /// Construct a new `Cmap13` subtable
229    pub fn format_13(
230        length: u32,
231        language: u32,
232        num_groups: u32,
233        groups: Vec<ConstantMapGroup>,
234    ) -> Self {
235        Self::Format13(Cmap13::new(length, language, num_groups, groups))
236    }
237
238    /// Construct a new `Cmap14` subtable
239    pub fn format_14(
240        length: u32,
241        num_var_selector_records: u32,
242        var_selector: Vec<VariationSelector>,
243    ) -> Self {
244        Self::Format14(Cmap14::new(length, num_var_selector_records, var_selector))
245    }
246}
247
248impl Default for CmapSubtable {
249    fn default() -> Self {
250        Self::Format0(Default::default())
251    }
252}
253
254impl FontWrite for CmapSubtable {
255    fn write_into(&self, writer: &mut TableWriter) {
256        match self {
257            Self::Format0(item) => item.write_into(writer),
258            Self::Format2(item) => item.write_into(writer),
259            Self::Format4(item) => item.write_into(writer),
260            Self::Format6(item) => item.write_into(writer),
261            Self::Format8(item) => item.write_into(writer),
262            Self::Format10(item) => item.write_into(writer),
263            Self::Format12(item) => item.write_into(writer),
264            Self::Format13(item) => item.write_into(writer),
265            Self::Format14(item) => item.write_into(writer),
266        }
267    }
268    fn table_type(&self) -> TableType {
269        match self {
270            Self::Format0(item) => item.table_type(),
271            Self::Format2(item) => item.table_type(),
272            Self::Format4(item) => item.table_type(),
273            Self::Format6(item) => item.table_type(),
274            Self::Format8(item) => item.table_type(),
275            Self::Format10(item) => item.table_type(),
276            Self::Format12(item) => item.table_type(),
277            Self::Format13(item) => item.table_type(),
278            Self::Format14(item) => item.table_type(),
279        }
280    }
281}
282
283impl Validate for CmapSubtable {
284    fn validate_impl(&self, ctx: &mut ValidationCtx) {
285        match self {
286            Self::Format0(item) => item.validate_impl(ctx),
287            Self::Format2(item) => item.validate_impl(ctx),
288            Self::Format4(item) => item.validate_impl(ctx),
289            Self::Format6(item) => item.validate_impl(ctx),
290            Self::Format8(item) => item.validate_impl(ctx),
291            Self::Format10(item) => item.validate_impl(ctx),
292            Self::Format12(item) => item.validate_impl(ctx),
293            Self::Format13(item) => item.validate_impl(ctx),
294            Self::Format14(item) => item.validate_impl(ctx),
295        }
296    }
297}
298
299impl FromObjRef<read_fonts::tables::cmap::CmapSubtable<'_>> for CmapSubtable {
300    fn from_obj_ref(obj: &read_fonts::tables::cmap::CmapSubtable, _: FontData) -> Self {
301        use read_fonts::tables::cmap::CmapSubtable as ObjRefType;
302        match obj {
303            ObjRefType::Format0(item) => CmapSubtable::Format0(item.to_owned_table()),
304            ObjRefType::Format2(item) => CmapSubtable::Format2(item.to_owned_table()),
305            ObjRefType::Format4(item) => CmapSubtable::Format4(item.to_owned_table()),
306            ObjRefType::Format6(item) => CmapSubtable::Format6(item.to_owned_table()),
307            ObjRefType::Format8(item) => CmapSubtable::Format8(item.to_owned_table()),
308            ObjRefType::Format10(item) => CmapSubtable::Format10(item.to_owned_table()),
309            ObjRefType::Format12(item) => CmapSubtable::Format12(item.to_owned_table()),
310            ObjRefType::Format13(item) => CmapSubtable::Format13(item.to_owned_table()),
311            ObjRefType::Format14(item) => CmapSubtable::Format14(item.to_owned_table()),
312        }
313    }
314}
315
316impl FromTableRef<read_fonts::tables::cmap::CmapSubtable<'_>> for CmapSubtable {}
317
318impl<'a> FontRead<'a> for CmapSubtable {
319    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
320        <read_fonts::tables::cmap::CmapSubtable as FontRead>::read(data).map(|x| x.to_owned_table())
321    }
322}
323
324impl From<Cmap0> for CmapSubtable {
325    fn from(src: Cmap0) -> CmapSubtable {
326        CmapSubtable::Format0(src)
327    }
328}
329
330impl From<Cmap2> for CmapSubtable {
331    fn from(src: Cmap2) -> CmapSubtable {
332        CmapSubtable::Format2(src)
333    }
334}
335
336impl From<Cmap4> for CmapSubtable {
337    fn from(src: Cmap4) -> CmapSubtable {
338        CmapSubtable::Format4(src)
339    }
340}
341
342impl From<Cmap6> for CmapSubtable {
343    fn from(src: Cmap6) -> CmapSubtable {
344        CmapSubtable::Format6(src)
345    }
346}
347
348impl From<Cmap8> for CmapSubtable {
349    fn from(src: Cmap8) -> CmapSubtable {
350        CmapSubtable::Format8(src)
351    }
352}
353
354impl From<Cmap10> for CmapSubtable {
355    fn from(src: Cmap10) -> CmapSubtable {
356        CmapSubtable::Format10(src)
357    }
358}
359
360impl From<Cmap12> for CmapSubtable {
361    fn from(src: Cmap12) -> CmapSubtable {
362        CmapSubtable::Format12(src)
363    }
364}
365
366impl From<Cmap13> for CmapSubtable {
367    fn from(src: Cmap13) -> CmapSubtable {
368        CmapSubtable::Format13(src)
369    }
370}
371
372impl From<Cmap14> for CmapSubtable {
373    fn from(src: Cmap14) -> CmapSubtable {
374        CmapSubtable::Format14(src)
375    }
376}
377
378/// [cmap Format 0](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-0-byte-encoding-table): Byte encoding table
379#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
380#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
381pub struct Cmap0 {
382    /// For requirements on use of the language field, see “Use of
383    /// the language field in 'cmap' subtables” in this document.
384    pub language: u16,
385    /// An array that maps character codes to glyph index values.
386    pub glyph_id_array: Vec<u8>,
387}
388
389impl Cmap0 {
390    /// Construct a new `Cmap0`
391    pub fn new(language: u16, glyph_id_array: Vec<u8>) -> Self {
392        Self {
393            language,
394            glyph_id_array,
395        }
396    }
397}
398
399impl FontWrite for Cmap0 {
400    #[allow(clippy::unnecessary_cast)]
401    fn write_into(&self, writer: &mut TableWriter) {
402        (0 as u16).write_into(writer);
403        (256 + 6 as u16).write_into(writer);
404        self.language.write_into(writer);
405        self.glyph_id_array.write_into(writer);
406    }
407    fn table_type(&self) -> TableType {
408        TableType::Named("Cmap0")
409    }
410}
411
412impl Validate for Cmap0 {
413    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
414}
415
416impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap0<'a>> for Cmap0 {
417    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap0<'a>, _: FontData) -> Self {
418        let offset_data = obj.offset_data();
419        Cmap0 {
420            language: obj.language(),
421            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
422        }
423    }
424}
425
426#[allow(clippy::needless_lifetimes)]
427impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap0<'a>> for Cmap0 {}
428
429impl<'a> FontRead<'a> for Cmap0 {
430    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
431        <read_fonts::tables::cmap::Cmap0 as FontRead>::read(data).map(|x| x.to_owned_table())
432    }
433}
434
435/// [cmap Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-2-high-byte-mapping-through-table): High-byte mapping through table
436#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
437#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
438pub struct Cmap2 {
439    /// This is the length in bytes of the subtable.
440    pub length: u16,
441    /// For requirements on use of the language field, see “Use of
442    /// the language field in 'cmap' subtables” in this document.
443    pub language: u16,
444    /// Array that maps high bytes to subHeaders: value is subHeader
445    /// index × 8.
446    pub sub_header_keys: Vec<u16>,
447}
448
449impl Cmap2 {
450    /// Construct a new `Cmap2`
451    pub fn new(length: u16, language: u16, sub_header_keys: Vec<u16>) -> Self {
452        Self {
453            length,
454            language,
455            sub_header_keys,
456        }
457    }
458}
459
460impl FontWrite for Cmap2 {
461    #[allow(clippy::unnecessary_cast)]
462    fn write_into(&self, writer: &mut TableWriter) {
463        (2 as u16).write_into(writer);
464        self.length.write_into(writer);
465        self.language.write_into(writer);
466        self.sub_header_keys.write_into(writer);
467    }
468    fn table_type(&self) -> TableType {
469        TableType::Named("Cmap2")
470    }
471}
472
473impl Validate for Cmap2 {
474    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
475}
476
477impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap2<'a>> for Cmap2 {
478    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap2<'a>, _: FontData) -> Self {
479        let offset_data = obj.offset_data();
480        Cmap2 {
481            length: obj.length(),
482            language: obj.language(),
483            sub_header_keys: obj.sub_header_keys().to_owned_obj(offset_data),
484        }
485    }
486}
487
488#[allow(clippy::needless_lifetimes)]
489impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap2<'a>> for Cmap2 {}
490
491impl<'a> FontRead<'a> for Cmap2 {
492    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
493        <read_fonts::tables::cmap::Cmap2 as FontRead>::read(data).map(|x| x.to_owned_table())
494    }
495}
496
497/// Part of [Cmap2]
498#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
499#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
500pub struct SubHeader {
501    /// First valid low byte for this SubHeader.
502    pub first_code: u16,
503    /// Number of valid low bytes for this SubHeader.
504    pub entry_count: u16,
505    /// See text below.
506    pub id_delta: i16,
507    /// See text below.
508    pub id_range_offset: u16,
509}
510
511impl SubHeader {
512    /// Construct a new `SubHeader`
513    pub fn new(first_code: u16, entry_count: u16, id_delta: i16, id_range_offset: u16) -> Self {
514        Self {
515            first_code,
516            entry_count,
517            id_delta,
518            id_range_offset,
519        }
520    }
521}
522
523impl FontWrite for SubHeader {
524    fn write_into(&self, writer: &mut TableWriter) {
525        self.first_code.write_into(writer);
526        self.entry_count.write_into(writer);
527        self.id_delta.write_into(writer);
528        self.id_range_offset.write_into(writer);
529    }
530    fn table_type(&self) -> TableType {
531        TableType::Named("SubHeader")
532    }
533}
534
535impl Validate for SubHeader {
536    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
537}
538
539impl FromObjRef<read_fonts::tables::cmap::SubHeader> for SubHeader {
540    fn from_obj_ref(obj: &read_fonts::tables::cmap::SubHeader, _: FontData) -> Self {
541        SubHeader {
542            first_code: obj.first_code(),
543            entry_count: obj.entry_count(),
544            id_delta: obj.id_delta(),
545            id_range_offset: obj.id_range_offset(),
546        }
547    }
548}
549
550/// [cmap Format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values): Segment mapping to delta values
551#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
552#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
553pub struct Cmap4 {
554    /// For requirements on use of the language field, see “Use of
555    /// the language field in 'cmap' subtables” in this document.
556    pub language: u16,
557    /// End characterCode for each segment, last=0xFFFF.
558    pub end_code: Vec<u16>,
559    /// Start character code for each segment.
560    pub start_code: Vec<u16>,
561    /// Delta for all character codes in segment.
562    pub id_delta: Vec<i16>,
563    /// Offsets into glyphIdArray or 0
564    pub id_range_offsets: Vec<u16>,
565    /// Glyph index array (arbitrary length)
566    pub glyph_id_array: Vec<u16>,
567}
568
569impl Cmap4 {
570    /// Construct a new `Cmap4`
571    pub fn new(
572        language: u16,
573        end_code: Vec<u16>,
574        start_code: Vec<u16>,
575        id_delta: Vec<i16>,
576        id_range_offsets: Vec<u16>,
577        glyph_id_array: Vec<u16>,
578    ) -> Self {
579        Self {
580            language,
581            end_code,
582            start_code,
583            id_delta,
584            id_range_offsets,
585            glyph_id_array,
586        }
587    }
588}
589
590impl FontWrite for Cmap4 {
591    #[allow(clippy::unnecessary_cast)]
592    fn write_into(&self, writer: &mut TableWriter) {
593        (4 as u16).write_into(writer);
594        (self.compute_length() as u16).write_into(writer);
595        self.language.write_into(writer);
596        (u16::try_from(2 * array_len(&self.end_code)).unwrap()).write_into(writer);
597        (self.compute_search_range() as u16).write_into(writer);
598        (self.compute_entry_selector() as u16).write_into(writer);
599        (self.compute_range_shift() as u16).write_into(writer);
600        self.end_code.write_into(writer);
601        (0 as u16).write_into(writer);
602        self.start_code.write_into(writer);
603        self.id_delta.write_into(writer);
604        self.id_range_offsets.write_into(writer);
605        self.glyph_id_array.write_into(writer);
606    }
607    fn table_type(&self) -> TableType {
608        TableType::Named("Cmap4")
609    }
610}
611
612impl Validate for Cmap4 {
613    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
614}
615
616impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap4<'a>> for Cmap4 {
617    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap4<'a>, _: FontData) -> Self {
618        let offset_data = obj.offset_data();
619        Cmap4 {
620            language: obj.language(),
621            end_code: obj.end_code().to_owned_obj(offset_data),
622            start_code: obj.start_code().to_owned_obj(offset_data),
623            id_delta: obj.id_delta().to_owned_obj(offset_data),
624            id_range_offsets: obj.id_range_offsets().to_owned_obj(offset_data),
625            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
626        }
627    }
628}
629
630#[allow(clippy::needless_lifetimes)]
631impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap4<'a>> for Cmap4 {}
632
633impl<'a> FontRead<'a> for Cmap4 {
634    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
635        <read_fonts::tables::cmap::Cmap4 as FontRead>::read(data).map(|x| x.to_owned_table())
636    }
637}
638
639/// [cmap Format 6](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-6-trimmed-table-mapping): Trimmed table mapping
640#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
641#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
642pub struct Cmap6 {
643    /// This is the length in bytes of the subtable.
644    pub length: u16,
645    /// For requirements on use of the language field, see “Use of
646    /// the language field in 'cmap' subtables” in this document.
647    pub language: u16,
648    /// First character code of subrange.
649    pub first_code: u16,
650    /// Number of character codes in subrange.
651    pub entry_count: u16,
652    /// Array of glyph index values for character codes in the range.
653    pub glyph_id_array: Vec<u16>,
654}
655
656impl Cmap6 {
657    /// Construct a new `Cmap6`
658    pub fn new(
659        length: u16,
660        language: u16,
661        first_code: u16,
662        entry_count: u16,
663        glyph_id_array: Vec<u16>,
664    ) -> Self {
665        Self {
666            length,
667            language,
668            first_code,
669            entry_count,
670            glyph_id_array,
671        }
672    }
673}
674
675impl FontWrite for Cmap6 {
676    #[allow(clippy::unnecessary_cast)]
677    fn write_into(&self, writer: &mut TableWriter) {
678        (6 as u16).write_into(writer);
679        self.length.write_into(writer);
680        self.language.write_into(writer);
681        self.first_code.write_into(writer);
682        self.entry_count.write_into(writer);
683        self.glyph_id_array.write_into(writer);
684    }
685    fn table_type(&self) -> TableType {
686        TableType::Named("Cmap6")
687    }
688}
689
690impl Validate for Cmap6 {
691    fn validate_impl(&self, ctx: &mut ValidationCtx) {
692        ctx.in_table("Cmap6", |ctx| {
693            ctx.in_field("glyph_id_array", |ctx| {
694                if self.glyph_id_array.len() > (u16::MAX as usize) {
695                    ctx.report("array exceeds max length");
696                }
697            });
698        })
699    }
700}
701
702impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap6<'a>> for Cmap6 {
703    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap6<'a>, _: FontData) -> Self {
704        let offset_data = obj.offset_data();
705        Cmap6 {
706            length: obj.length(),
707            language: obj.language(),
708            first_code: obj.first_code(),
709            entry_count: obj.entry_count(),
710            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
711        }
712    }
713}
714
715#[allow(clippy::needless_lifetimes)]
716impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap6<'a>> for Cmap6 {}
717
718impl<'a> FontRead<'a> for Cmap6 {
719    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
720        <read_fonts::tables::cmap::Cmap6 as FontRead>::read(data).map(|x| x.to_owned_table())
721    }
722}
723
724/// [cmap Format 8](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-8-mixed-16-bit-and-32-bit-coverage): mixed 16-bit and 32-bit coverage
725#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
726#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
727pub struct Cmap8 {
728    /// Byte length of this subtable (including the header)
729    pub length: u32,
730    /// For requirements on use of the language field, see “Use of
731    /// the language field in 'cmap' subtables” in this document.
732    pub language: u32,
733    /// Tightly packed array of bits (8K bytes total) indicating
734    /// whether the particular 16-bit (index) value is the start of a
735    /// 32-bit character code
736    pub is32: Vec<u8>,
737    /// Number of groupings which follow
738    pub num_groups: u32,
739    /// Array of SequentialMapGroup records.
740    pub groups: Vec<SequentialMapGroup>,
741}
742
743impl Cmap8 {
744    /// Construct a new `Cmap8`
745    pub fn new(
746        length: u32,
747        language: u32,
748        is32: Vec<u8>,
749        num_groups: u32,
750        groups: Vec<SequentialMapGroup>,
751    ) -> Self {
752        Self {
753            length,
754            language,
755            is32,
756            num_groups,
757            groups,
758        }
759    }
760}
761
762impl FontWrite for Cmap8 {
763    #[allow(clippy::unnecessary_cast)]
764    fn write_into(&self, writer: &mut TableWriter) {
765        (8 as u16).write_into(writer);
766        (0 as u16).write_into(writer);
767        self.length.write_into(writer);
768        self.language.write_into(writer);
769        self.is32.write_into(writer);
770        self.num_groups.write_into(writer);
771        self.groups.write_into(writer);
772    }
773    fn table_type(&self) -> TableType {
774        TableType::Named("Cmap8")
775    }
776}
777
778impl Validate for Cmap8 {
779    fn validate_impl(&self, ctx: &mut ValidationCtx) {
780        ctx.in_table("Cmap8", |ctx| {
781            ctx.in_field("groups", |ctx| {
782                if self.groups.len() > (u32::MAX as usize) {
783                    ctx.report("array exceeds max length");
784                }
785                self.groups.validate_impl(ctx);
786            });
787        })
788    }
789}
790
791impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap8<'a>> for Cmap8 {
792    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap8<'a>, _: FontData) -> Self {
793        let offset_data = obj.offset_data();
794        Cmap8 {
795            length: obj.length(),
796            language: obj.language(),
797            is32: obj.is32().to_owned_obj(offset_data),
798            num_groups: obj.num_groups(),
799            groups: obj.groups().to_owned_obj(offset_data),
800        }
801    }
802}
803
804#[allow(clippy::needless_lifetimes)]
805impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap8<'a>> for Cmap8 {}
806
807impl<'a> FontRead<'a> for Cmap8 {
808    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
809        <read_fonts::tables::cmap::Cmap8 as FontRead>::read(data).map(|x| x.to_owned_table())
810    }
811}
812
813/// Used in [Cmap8] and [Cmap12]
814#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
815#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
816pub struct SequentialMapGroup {
817    /// First character code in this group; note that if this group is
818    /// for one or more 16-bit character codes (which is determined
819    /// from the is32 array), this 32-bit value will have the high
820    /// 16-bits set to zero
821    pub start_char_code: u32,
822    /// Last character code in this group; same condition as listed
823    /// above for the startCharCode
824    pub end_char_code: u32,
825    /// Glyph index corresponding to the starting character code
826    pub start_glyph_id: u32,
827}
828
829impl SequentialMapGroup {
830    /// Construct a new `SequentialMapGroup`
831    pub fn new(start_char_code: u32, end_char_code: u32, start_glyph_id: u32) -> Self {
832        Self {
833            start_char_code,
834            end_char_code,
835            start_glyph_id,
836        }
837    }
838}
839
840impl FontWrite for SequentialMapGroup {
841    fn write_into(&self, writer: &mut TableWriter) {
842        self.start_char_code.write_into(writer);
843        self.end_char_code.write_into(writer);
844        self.start_glyph_id.write_into(writer);
845    }
846    fn table_type(&self) -> TableType {
847        TableType::Named("SequentialMapGroup")
848    }
849}
850
851impl Validate for SequentialMapGroup {
852    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
853}
854
855impl FromObjRef<read_fonts::tables::cmap::SequentialMapGroup> for SequentialMapGroup {
856    fn from_obj_ref(obj: &read_fonts::tables::cmap::SequentialMapGroup, _: FontData) -> Self {
857        SequentialMapGroup {
858            start_char_code: obj.start_char_code(),
859            end_char_code: obj.end_char_code(),
860            start_glyph_id: obj.start_glyph_id(),
861        }
862    }
863}
864
865/// [cmap Format 10](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-10-trimmed-array): Tr
866#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
867#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
868pub struct Cmap10 {
869    /// Byte length of this subtable (including the header)
870    pub length: u32,
871    /// For requirements on use of the language field, see “Use of
872    /// the language field in 'cmap' subtables” in this document.
873    pub language: u32,
874    /// First character code covered
875    pub start_char_code: u32,
876    /// Number of character codes covered
877    pub num_chars: u32,
878    /// Array of glyph indices for the character codes covered
879    pub glyph_id_array: Vec<u16>,
880}
881
882impl Cmap10 {
883    /// Construct a new `Cmap10`
884    pub fn new(
885        length: u32,
886        language: u32,
887        start_char_code: u32,
888        num_chars: u32,
889        glyph_id_array: Vec<u16>,
890    ) -> Self {
891        Self {
892            length,
893            language,
894            start_char_code,
895            num_chars,
896            glyph_id_array,
897        }
898    }
899}
900
901impl FontWrite for Cmap10 {
902    #[allow(clippy::unnecessary_cast)]
903    fn write_into(&self, writer: &mut TableWriter) {
904        (10 as u16).write_into(writer);
905        (0 as u16).write_into(writer);
906        self.length.write_into(writer);
907        self.language.write_into(writer);
908        self.start_char_code.write_into(writer);
909        self.num_chars.write_into(writer);
910        self.glyph_id_array.write_into(writer);
911    }
912    fn table_type(&self) -> TableType {
913        TableType::Named("Cmap10")
914    }
915}
916
917impl Validate for Cmap10 {
918    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
919}
920
921impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap10<'a>> for Cmap10 {
922    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap10<'a>, _: FontData) -> Self {
923        let offset_data = obj.offset_data();
924        Cmap10 {
925            length: obj.length(),
926            language: obj.language(),
927            start_char_code: obj.start_char_code(),
928            num_chars: obj.num_chars(),
929            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
930        }
931    }
932}
933
934#[allow(clippy::needless_lifetimes)]
935impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap10<'a>> for Cmap10 {}
936
937impl<'a> FontRead<'a> for Cmap10 {
938    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
939        <read_fonts::tables::cmap::Cmap10 as FontRead>::read(data).map(|x| x.to_owned_table())
940    }
941}
942
943/// [cmap Format 12](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage): Segmented coverage
944#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
945#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
946pub struct Cmap12 {
947    /// For requirements on use of the language field, see “Use of
948    /// the language field in 'cmap' subtables” in this document.
949    pub language: u32,
950    /// Array of SequentialMapGroup records.
951    pub groups: Vec<SequentialMapGroup>,
952}
953
954impl Cmap12 {
955    /// Construct a new `Cmap12`
956    pub fn new(language: u32, groups: Vec<SequentialMapGroup>) -> Self {
957        Self { language, groups }
958    }
959}
960
961impl FontWrite for Cmap12 {
962    #[allow(clippy::unnecessary_cast)]
963    fn write_into(&self, writer: &mut TableWriter) {
964        (12 as u16).write_into(writer);
965        (0 as u16).write_into(writer);
966        (self.compute_length() as u32).write_into(writer);
967        self.language.write_into(writer);
968        (u32::try_from(array_len(&self.groups)).unwrap()).write_into(writer);
969        self.groups.write_into(writer);
970    }
971    fn table_type(&self) -> TableType {
972        TableType::Named("Cmap12")
973    }
974}
975
976impl Validate for Cmap12 {
977    fn validate_impl(&self, ctx: &mut ValidationCtx) {
978        ctx.in_table("Cmap12", |ctx| {
979            ctx.in_field("groups", |ctx| {
980                if self.groups.len() > (u32::MAX as usize) {
981                    ctx.report("array exceeds max length");
982                }
983                self.groups.validate_impl(ctx);
984            });
985        })
986    }
987}
988
989impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap12<'a>> for Cmap12 {
990    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap12<'a>, _: FontData) -> Self {
991        let offset_data = obj.offset_data();
992        Cmap12 {
993            language: obj.language(),
994            groups: obj.groups().to_owned_obj(offset_data),
995        }
996    }
997}
998
999#[allow(clippy::needless_lifetimes)]
1000impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap12<'a>> for Cmap12 {}
1001
1002impl<'a> FontRead<'a> for Cmap12 {
1003    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1004        <read_fonts::tables::cmap::Cmap12 as FontRead>::read(data).map(|x| x.to_owned_table())
1005    }
1006}
1007
1008/// [cmap Format 13](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-13-many-to-one-range-mappings): Many-to-one range mappings
1009#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1010#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1011pub struct Cmap13 {
1012    /// Byte length of this subtable (including the header)
1013    pub length: u32,
1014    /// For requirements on use of the language field, see “Use of
1015    /// the language field in 'cmap' subtables” in this document.
1016    pub language: u32,
1017    /// Number of groupings which follow
1018    pub num_groups: u32,
1019    /// Array of ConstantMapGroup records.
1020    pub groups: Vec<ConstantMapGroup>,
1021}
1022
1023impl Cmap13 {
1024    /// Construct a new `Cmap13`
1025    pub fn new(length: u32, language: u32, num_groups: u32, groups: Vec<ConstantMapGroup>) -> Self {
1026        Self {
1027            length,
1028            language,
1029            num_groups,
1030            groups,
1031        }
1032    }
1033}
1034
1035impl FontWrite for Cmap13 {
1036    #[allow(clippy::unnecessary_cast)]
1037    fn write_into(&self, writer: &mut TableWriter) {
1038        (13 as u16).write_into(writer);
1039        (0 as u16).write_into(writer);
1040        self.length.write_into(writer);
1041        self.language.write_into(writer);
1042        self.num_groups.write_into(writer);
1043        self.groups.write_into(writer);
1044    }
1045    fn table_type(&self) -> TableType {
1046        TableType::Named("Cmap13")
1047    }
1048}
1049
1050impl Validate for Cmap13 {
1051    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1052        ctx.in_table("Cmap13", |ctx| {
1053            ctx.in_field("groups", |ctx| {
1054                if self.groups.len() > (u32::MAX as usize) {
1055                    ctx.report("array exceeds max length");
1056                }
1057                self.groups.validate_impl(ctx);
1058            });
1059        })
1060    }
1061}
1062
1063impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap13<'a>> for Cmap13 {
1064    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap13<'a>, _: FontData) -> Self {
1065        let offset_data = obj.offset_data();
1066        Cmap13 {
1067            length: obj.length(),
1068            language: obj.language(),
1069            num_groups: obj.num_groups(),
1070            groups: obj.groups().to_owned_obj(offset_data),
1071        }
1072    }
1073}
1074
1075#[allow(clippy::needless_lifetimes)]
1076impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap13<'a>> for Cmap13 {}
1077
1078impl<'a> FontRead<'a> for Cmap13 {
1079    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1080        <read_fonts::tables::cmap::Cmap13 as FontRead>::read(data).map(|x| x.to_owned_table())
1081    }
1082}
1083
1084/// Part of [Cmap13]
1085#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1086#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1087pub struct ConstantMapGroup {
1088    /// First character code in this group
1089    pub start_char_code: u32,
1090    /// Last character code in this group
1091    pub end_char_code: u32,
1092    /// Glyph index to be used for all the characters in the group’s
1093    /// range.
1094    pub glyph_id: u32,
1095}
1096
1097impl ConstantMapGroup {
1098    /// Construct a new `ConstantMapGroup`
1099    pub fn new(start_char_code: u32, end_char_code: u32, glyph_id: u32) -> Self {
1100        Self {
1101            start_char_code,
1102            end_char_code,
1103            glyph_id,
1104        }
1105    }
1106}
1107
1108impl FontWrite for ConstantMapGroup {
1109    fn write_into(&self, writer: &mut TableWriter) {
1110        self.start_char_code.write_into(writer);
1111        self.end_char_code.write_into(writer);
1112        self.glyph_id.write_into(writer);
1113    }
1114    fn table_type(&self) -> TableType {
1115        TableType::Named("ConstantMapGroup")
1116    }
1117}
1118
1119impl Validate for ConstantMapGroup {
1120    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1121}
1122
1123impl FromObjRef<read_fonts::tables::cmap::ConstantMapGroup> for ConstantMapGroup {
1124    fn from_obj_ref(obj: &read_fonts::tables::cmap::ConstantMapGroup, _: FontData) -> Self {
1125        ConstantMapGroup {
1126            start_char_code: obj.start_char_code(),
1127            end_char_code: obj.end_char_code(),
1128            glyph_id: obj.glyph_id(),
1129        }
1130    }
1131}
1132
1133/// [cmap Format 14](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-14-unicode-variation-sequences): Unicode Variation Sequences
1134#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1135#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1136pub struct Cmap14 {
1137    /// Byte length of this subtable (including this header)
1138    pub length: u32,
1139    /// Number of variation Selector Records
1140    pub num_var_selector_records: u32,
1141    /// Array of VariationSelector records.
1142    pub var_selector: Vec<VariationSelector>,
1143}
1144
1145impl Cmap14 {
1146    /// Construct a new `Cmap14`
1147    pub fn new(
1148        length: u32,
1149        num_var_selector_records: u32,
1150        var_selector: Vec<VariationSelector>,
1151    ) -> Self {
1152        Self {
1153            length,
1154            num_var_selector_records,
1155            var_selector,
1156        }
1157    }
1158}
1159
1160impl FontWrite for Cmap14 {
1161    #[allow(clippy::unnecessary_cast)]
1162    fn write_into(&self, writer: &mut TableWriter) {
1163        (14 as u16).write_into(writer);
1164        self.length.write_into(writer);
1165        self.num_var_selector_records.write_into(writer);
1166        self.var_selector.write_into(writer);
1167    }
1168    fn table_type(&self) -> TableType {
1169        TableType::Named("Cmap14")
1170    }
1171}
1172
1173impl Validate for Cmap14 {
1174    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1175        ctx.in_table("Cmap14", |ctx| {
1176            ctx.in_field("var_selector", |ctx| {
1177                if self.var_selector.len() > (u32::MAX as usize) {
1178                    ctx.report("array exceeds max length");
1179                }
1180                self.var_selector.validate_impl(ctx);
1181            });
1182        })
1183    }
1184}
1185
1186impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap14<'a>> for Cmap14 {
1187    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap14<'a>, _: FontData) -> Self {
1188        let offset_data = obj.offset_data();
1189        Cmap14 {
1190            length: obj.length(),
1191            num_var_selector_records: obj.num_var_selector_records(),
1192            var_selector: obj.var_selector().to_owned_obj(offset_data),
1193        }
1194    }
1195}
1196
1197#[allow(clippy::needless_lifetimes)]
1198impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap14<'a>> for Cmap14 {}
1199
1200impl<'a> FontRead<'a> for Cmap14 {
1201    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1202        <read_fonts::tables::cmap::Cmap14 as FontRead>::read(data).map(|x| x.to_owned_table())
1203    }
1204}
1205
1206/// Part of [Cmap14]
1207#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1208#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1209pub struct VariationSelector {
1210    /// Variation selector
1211    pub var_selector: Uint24,
1212    /// Offset from the start of the [`Cmap14`] subtable to Default UVS
1213    /// Table. May be NULL.
1214    pub default_uvs: NullableOffsetMarker<DefaultUvs, WIDTH_32>,
1215    /// Offset from the start of the [`Cmap14`] subtable to Non-Default
1216    /// UVS Table. May be NULL.
1217    pub non_default_uvs: NullableOffsetMarker<NonDefaultUvs, WIDTH_32>,
1218}
1219
1220impl VariationSelector {
1221    /// Construct a new `VariationSelector`
1222    pub fn new(
1223        var_selector: Uint24,
1224        default_uvs: Option<DefaultUvs>,
1225        non_default_uvs: Option<NonDefaultUvs>,
1226    ) -> Self {
1227        Self {
1228            var_selector,
1229            default_uvs: default_uvs.into(),
1230            non_default_uvs: non_default_uvs.into(),
1231        }
1232    }
1233}
1234
1235impl FontWrite for VariationSelector {
1236    fn write_into(&self, writer: &mut TableWriter) {
1237        self.var_selector.write_into(writer);
1238        self.default_uvs.write_into(writer);
1239        self.non_default_uvs.write_into(writer);
1240    }
1241    fn table_type(&self) -> TableType {
1242        TableType::Named("VariationSelector")
1243    }
1244}
1245
1246impl Validate for VariationSelector {
1247    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1248        ctx.in_table("VariationSelector", |ctx| {
1249            ctx.in_field("default_uvs", |ctx| {
1250                self.default_uvs.validate_impl(ctx);
1251            });
1252            ctx.in_field("non_default_uvs", |ctx| {
1253                self.non_default_uvs.validate_impl(ctx);
1254            });
1255        })
1256    }
1257}
1258
1259impl FromObjRef<read_fonts::tables::cmap::VariationSelector> for VariationSelector {
1260    fn from_obj_ref(
1261        obj: &read_fonts::tables::cmap::VariationSelector,
1262        offset_data: FontData,
1263    ) -> Self {
1264        VariationSelector {
1265            var_selector: obj.var_selector(),
1266            default_uvs: obj.default_uvs(offset_data).to_owned_table(),
1267            non_default_uvs: obj.non_default_uvs(offset_data).to_owned_table(),
1268        }
1269    }
1270}
1271
1272/// [Default UVS table](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#default-uvs-table)
1273#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1274#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1275pub struct DefaultUvs {
1276    /// Number of Unicode character ranges.
1277    pub num_unicode_value_ranges: u32,
1278    /// Array of UnicodeRange records.
1279    pub ranges: Vec<UnicodeRange>,
1280}
1281
1282impl DefaultUvs {
1283    /// Construct a new `DefaultUvs`
1284    pub fn new(num_unicode_value_ranges: u32, ranges: Vec<UnicodeRange>) -> Self {
1285        Self {
1286            num_unicode_value_ranges,
1287            ranges,
1288        }
1289    }
1290}
1291
1292impl FontWrite for DefaultUvs {
1293    fn write_into(&self, writer: &mut TableWriter) {
1294        self.num_unicode_value_ranges.write_into(writer);
1295        self.ranges.write_into(writer);
1296    }
1297    fn table_type(&self) -> TableType {
1298        TableType::Named("DefaultUvs")
1299    }
1300}
1301
1302impl Validate for DefaultUvs {
1303    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1304        ctx.in_table("DefaultUvs", |ctx| {
1305            ctx.in_field("ranges", |ctx| {
1306                if self.ranges.len() > (u32::MAX as usize) {
1307                    ctx.report("array exceeds max length");
1308                }
1309                self.ranges.validate_impl(ctx);
1310            });
1311        })
1312    }
1313}
1314
1315impl<'a> FromObjRef<read_fonts::tables::cmap::DefaultUvs<'a>> for DefaultUvs {
1316    fn from_obj_ref(obj: &read_fonts::tables::cmap::DefaultUvs<'a>, _: FontData) -> Self {
1317        let offset_data = obj.offset_data();
1318        DefaultUvs {
1319            num_unicode_value_ranges: obj.num_unicode_value_ranges(),
1320            ranges: obj.ranges().to_owned_obj(offset_data),
1321        }
1322    }
1323}
1324
1325#[allow(clippy::needless_lifetimes)]
1326impl<'a> FromTableRef<read_fonts::tables::cmap::DefaultUvs<'a>> for DefaultUvs {}
1327
1328impl<'a> FontRead<'a> for DefaultUvs {
1329    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1330        <read_fonts::tables::cmap::DefaultUvs as FontRead>::read(data).map(|x| x.to_owned_table())
1331    }
1332}
1333
1334/// [Non-Default UVS table](https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#non-default-uvs-table)
1335#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1336#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1337pub struct NonDefaultUvs {
1338    pub num_uvs_mappings: u32,
1339    pub uvs_mapping: Vec<UvsMapping>,
1340}
1341
1342impl NonDefaultUvs {
1343    /// Construct a new `NonDefaultUvs`
1344    pub fn new(num_uvs_mappings: u32, uvs_mapping: Vec<UvsMapping>) -> Self {
1345        Self {
1346            num_uvs_mappings,
1347            uvs_mapping,
1348        }
1349    }
1350}
1351
1352impl FontWrite for NonDefaultUvs {
1353    fn write_into(&self, writer: &mut TableWriter) {
1354        self.num_uvs_mappings.write_into(writer);
1355        self.uvs_mapping.write_into(writer);
1356    }
1357    fn table_type(&self) -> TableType {
1358        TableType::Named("NonDefaultUvs")
1359    }
1360}
1361
1362impl Validate for NonDefaultUvs {
1363    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1364        ctx.in_table("NonDefaultUvs", |ctx| {
1365            ctx.in_field("uvs_mapping", |ctx| {
1366                if self.uvs_mapping.len() > (u32::MAX as usize) {
1367                    ctx.report("array exceeds max length");
1368                }
1369                self.uvs_mapping.validate_impl(ctx);
1370            });
1371        })
1372    }
1373}
1374
1375impl<'a> FromObjRef<read_fonts::tables::cmap::NonDefaultUvs<'a>> for NonDefaultUvs {
1376    fn from_obj_ref(obj: &read_fonts::tables::cmap::NonDefaultUvs<'a>, _: FontData) -> Self {
1377        let offset_data = obj.offset_data();
1378        NonDefaultUvs {
1379            num_uvs_mappings: obj.num_uvs_mappings(),
1380            uvs_mapping: obj.uvs_mapping().to_owned_obj(offset_data),
1381        }
1382    }
1383}
1384
1385#[allow(clippy::needless_lifetimes)]
1386impl<'a> FromTableRef<read_fonts::tables::cmap::NonDefaultUvs<'a>> for NonDefaultUvs {}
1387
1388impl<'a> FontRead<'a> for NonDefaultUvs {
1389    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1390        <read_fonts::tables::cmap::NonDefaultUvs as FontRead>::read(data)
1391            .map(|x| x.to_owned_table())
1392    }
1393}
1394
1395/// Part of [Cmap14]
1396#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1397#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1398pub struct UvsMapping {
1399    /// Base Unicode value of the UVS
1400    pub unicode_value: Uint24,
1401    /// Glyph ID of the UVS
1402    pub glyph_id: u16,
1403}
1404
1405impl UvsMapping {
1406    /// Construct a new `UvsMapping`
1407    pub fn new(unicode_value: Uint24, glyph_id: u16) -> Self {
1408        Self {
1409            unicode_value,
1410            glyph_id,
1411        }
1412    }
1413}
1414
1415impl FontWrite for UvsMapping {
1416    fn write_into(&self, writer: &mut TableWriter) {
1417        self.unicode_value.write_into(writer);
1418        self.glyph_id.write_into(writer);
1419    }
1420    fn table_type(&self) -> TableType {
1421        TableType::Named("UvsMapping")
1422    }
1423}
1424
1425impl Validate for UvsMapping {
1426    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1427}
1428
1429impl FromObjRef<read_fonts::tables::cmap::UvsMapping> for UvsMapping {
1430    fn from_obj_ref(obj: &read_fonts::tables::cmap::UvsMapping, _: FontData) -> Self {
1431        UvsMapping {
1432            unicode_value: obj.unicode_value(),
1433            glyph_id: obj.glyph_id(),
1434        }
1435    }
1436}
1437
1438/// Part of [Cmap14]
1439#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1440#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1441pub struct UnicodeRange {
1442    /// First value in this range
1443    pub start_unicode_value: Uint24,
1444    /// Number of additional values in this range
1445    pub additional_count: u8,
1446}
1447
1448impl UnicodeRange {
1449    /// Construct a new `UnicodeRange`
1450    pub fn new(start_unicode_value: Uint24, additional_count: u8) -> Self {
1451        Self {
1452            start_unicode_value,
1453            additional_count,
1454        }
1455    }
1456}
1457
1458impl FontWrite for UnicodeRange {
1459    fn write_into(&self, writer: &mut TableWriter) {
1460        self.start_unicode_value.write_into(writer);
1461        self.additional_count.write_into(writer);
1462    }
1463    fn table_type(&self) -> TableType {
1464        TableType::Named("UnicodeRange")
1465    }
1466}
1467
1468impl Validate for UnicodeRange {
1469    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1470}
1471
1472impl FromObjRef<read_fonts::tables::cmap::UnicodeRange> for UnicodeRange {
1473    fn from_obj_ref(obj: &read_fonts::tables::cmap::UnicodeRange, _: FontData) -> Self {
1474        UnicodeRange {
1475            start_unicode_value: obj.start_unicode_value(),
1476            additional_count: obj.additional_count(),
1477        }
1478    }
1479}