Skip to main content

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