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