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(var_selector: Vec<VariationSelector>) -> Self {
242        Self::Format14(Cmap14::new(var_selector))
243    }
244}
245
246impl Default for CmapSubtable {
247    fn default() -> Self {
248        Self::Format0(Default::default())
249    }
250}
251
252impl FontWrite for CmapSubtable {
253    fn write_into(&self, writer: &mut TableWriter) {
254        match self {
255            Self::Format0(item) => item.write_into(writer),
256            Self::Format2(item) => item.write_into(writer),
257            Self::Format4(item) => item.write_into(writer),
258            Self::Format6(item) => item.write_into(writer),
259            Self::Format8(item) => item.write_into(writer),
260            Self::Format10(item) => item.write_into(writer),
261            Self::Format12(item) => item.write_into(writer),
262            Self::Format13(item) => item.write_into(writer),
263            Self::Format14(item) => item.write_into(writer),
264        }
265    }
266    fn table_type(&self) -> TableType {
267        match self {
268            Self::Format0(item) => item.table_type(),
269            Self::Format2(item) => item.table_type(),
270            Self::Format4(item) => item.table_type(),
271            Self::Format6(item) => item.table_type(),
272            Self::Format8(item) => item.table_type(),
273            Self::Format10(item) => item.table_type(),
274            Self::Format12(item) => item.table_type(),
275            Self::Format13(item) => item.table_type(),
276            Self::Format14(item) => item.table_type(),
277        }
278    }
279}
280
281impl Validate for CmapSubtable {
282    fn validate_impl(&self, ctx: &mut ValidationCtx) {
283        match self {
284            Self::Format0(item) => item.validate_impl(ctx),
285            Self::Format2(item) => item.validate_impl(ctx),
286            Self::Format4(item) => item.validate_impl(ctx),
287            Self::Format6(item) => item.validate_impl(ctx),
288            Self::Format8(item) => item.validate_impl(ctx),
289            Self::Format10(item) => item.validate_impl(ctx),
290            Self::Format12(item) => item.validate_impl(ctx),
291            Self::Format13(item) => item.validate_impl(ctx),
292            Self::Format14(item) => item.validate_impl(ctx),
293        }
294    }
295}
296
297impl FromObjRef<read_fonts::tables::cmap::CmapSubtable<'_>> for CmapSubtable {
298    fn from_obj_ref(obj: &read_fonts::tables::cmap::CmapSubtable, _: FontData) -> Self {
299        use read_fonts::tables::cmap::CmapSubtable as ObjRefType;
300        match obj {
301            ObjRefType::Format0(item) => CmapSubtable::Format0(item.to_owned_table()),
302            ObjRefType::Format2(item) => CmapSubtable::Format2(item.to_owned_table()),
303            ObjRefType::Format4(item) => CmapSubtable::Format4(item.to_owned_table()),
304            ObjRefType::Format6(item) => CmapSubtable::Format6(item.to_owned_table()),
305            ObjRefType::Format8(item) => CmapSubtable::Format8(item.to_owned_table()),
306            ObjRefType::Format10(item) => CmapSubtable::Format10(item.to_owned_table()),
307            ObjRefType::Format12(item) => CmapSubtable::Format12(item.to_owned_table()),
308            ObjRefType::Format13(item) => CmapSubtable::Format13(item.to_owned_table()),
309            ObjRefType::Format14(item) => CmapSubtable::Format14(item.to_owned_table()),
310        }
311    }
312}
313
314impl FromTableRef<read_fonts::tables::cmap::CmapSubtable<'_>> for CmapSubtable {}
315
316impl ReadArgs for CmapSubtable {
317    type Args = ();
318}
319
320impl<'a> FontRead<'a> for CmapSubtable {
321    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
322        <read_fonts::tables::cmap::CmapSubtable as FontRead>::read(data).map(|x| x.to_owned_table())
323    }
324}
325
326impl From<Cmap0> for CmapSubtable {
327    fn from(src: Cmap0) -> CmapSubtable {
328        CmapSubtable::Format0(src)
329    }
330}
331
332impl From<Cmap2> for CmapSubtable {
333    fn from(src: Cmap2) -> CmapSubtable {
334        CmapSubtable::Format2(src)
335    }
336}
337
338impl From<Cmap4> for CmapSubtable {
339    fn from(src: Cmap4) -> CmapSubtable {
340        CmapSubtable::Format4(src)
341    }
342}
343
344impl From<Cmap6> for CmapSubtable {
345    fn from(src: Cmap6) -> CmapSubtable {
346        CmapSubtable::Format6(src)
347    }
348}
349
350impl From<Cmap8> for CmapSubtable {
351    fn from(src: Cmap8) -> CmapSubtable {
352        CmapSubtable::Format8(src)
353    }
354}
355
356impl From<Cmap10> for CmapSubtable {
357    fn from(src: Cmap10) -> CmapSubtable {
358        CmapSubtable::Format10(src)
359    }
360}
361
362impl From<Cmap12> for CmapSubtable {
363    fn from(src: Cmap12) -> CmapSubtable {
364        CmapSubtable::Format12(src)
365    }
366}
367
368impl From<Cmap13> for CmapSubtable {
369    fn from(src: Cmap13) -> CmapSubtable {
370        CmapSubtable::Format13(src)
371    }
372}
373
374impl From<Cmap14> for CmapSubtable {
375    fn from(src: Cmap14) -> CmapSubtable {
376        CmapSubtable::Format14(src)
377    }
378}
379
380/// [cmap Format 0](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-0-byte-encoding-table): Byte encoding table
381#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
382#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
383pub struct Cmap0 {
384    /// For requirements on use of the language field, see “Use of
385    /// the language field in 'cmap' subtables” in this document.
386    pub language: u16,
387    /// An array that maps character codes to glyph index values.
388    pub glyph_id_array: Vec<u8>,
389}
390
391impl Cmap0 {
392    /// Construct a new `Cmap0`
393    pub fn new(language: u16, glyph_id_array: Vec<u8>) -> Self {
394        Self {
395            language,
396            glyph_id_array,
397        }
398    }
399}
400
401impl FontWrite for Cmap0 {
402    #[allow(clippy::unnecessary_cast)]
403    fn write_into(&self, writer: &mut TableWriter) {
404        (0 as u16).write_into(writer);
405        (256 + 6 as u16).write_into(writer);
406        self.language.write_into(writer);
407        self.glyph_id_array.write_into(writer);
408    }
409    fn table_type(&self) -> TableType {
410        TableType::Named("Cmap0")
411    }
412}
413
414impl Validate for Cmap0 {
415    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
416}
417
418impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap0<'a>> for Cmap0 {
419    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap0<'a>, _: FontData) -> Self {
420        let offset_data = obj.offset_data();
421        Cmap0 {
422            language: obj.language(),
423            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
424        }
425    }
426}
427
428#[allow(clippy::needless_lifetimes)]
429impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap0<'a>> for Cmap0 {}
430
431impl ReadArgs for Cmap0 {
432    type Args = ();
433}
434
435impl<'a> FontRead<'a> for Cmap0 {
436    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
437        <read_fonts::tables::cmap::Cmap0 as FontRead>::read(data).map(|x| x.to_owned_table())
438    }
439}
440
441/// [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
442#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
443#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
444pub struct Cmap2 {
445    /// This is the length in bytes of the subtable.
446    pub length: u16,
447    /// For requirements on use of the language field, see “Use of
448    /// the language field in 'cmap' subtables” in this document.
449    pub language: u16,
450    /// Array that maps high bytes to subHeaders: value is subHeader
451    /// index × 8.
452    pub sub_header_keys: Vec<u16>,
453}
454
455impl Cmap2 {
456    /// Construct a new `Cmap2`
457    pub fn new(length: u16, language: u16, sub_header_keys: Vec<u16>) -> Self {
458        Self {
459            length,
460            language,
461            sub_header_keys,
462        }
463    }
464}
465
466impl FontWrite for Cmap2 {
467    #[allow(clippy::unnecessary_cast)]
468    fn write_into(&self, writer: &mut TableWriter) {
469        (2 as u16).write_into(writer);
470        self.length.write_into(writer);
471        self.language.write_into(writer);
472        self.sub_header_keys.write_into(writer);
473    }
474    fn table_type(&self) -> TableType {
475        TableType::Named("Cmap2")
476    }
477}
478
479impl Validate for Cmap2 {
480    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
481}
482
483impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap2<'a>> for Cmap2 {
484    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap2<'a>, _: FontData) -> Self {
485        let offset_data = obj.offset_data();
486        Cmap2 {
487            length: obj.length(),
488            language: obj.language(),
489            sub_header_keys: obj.sub_header_keys().to_owned_obj(offset_data),
490        }
491    }
492}
493
494#[allow(clippy::needless_lifetimes)]
495impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap2<'a>> for Cmap2 {}
496
497impl ReadArgs for Cmap2 {
498    type Args = ();
499}
500
501impl<'a> FontRead<'a> for Cmap2 {
502    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
503        <read_fonts::tables::cmap::Cmap2 as FontRead>::read(data).map(|x| x.to_owned_table())
504    }
505}
506
507/// Part of [Cmap2]
508#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
509#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
510pub struct SubHeader {
511    /// First valid low byte for this SubHeader.
512    pub first_code: u16,
513    /// Number of valid low bytes for this SubHeader.
514    pub entry_count: u16,
515    /// See text below.
516    pub id_delta: i16,
517    /// See text below.
518    pub id_range_offset: u16,
519}
520
521impl SubHeader {
522    /// Construct a new `SubHeader`
523    pub fn new(first_code: u16, entry_count: u16, id_delta: i16, id_range_offset: u16) -> Self {
524        Self {
525            first_code,
526            entry_count,
527            id_delta,
528            id_range_offset,
529        }
530    }
531}
532
533impl FontWrite for SubHeader {
534    fn write_into(&self, writer: &mut TableWriter) {
535        self.first_code.write_into(writer);
536        self.entry_count.write_into(writer);
537        self.id_delta.write_into(writer);
538        self.id_range_offset.write_into(writer);
539    }
540    fn table_type(&self) -> TableType {
541        TableType::Named("SubHeader")
542    }
543}
544
545impl Validate for SubHeader {
546    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
547}
548
549impl FromObjRef<read_fonts::tables::cmap::SubHeader> for SubHeader {
550    fn from_obj_ref(obj: &read_fonts::tables::cmap::SubHeader, _: FontData) -> Self {
551        SubHeader {
552            first_code: obj.first_code(),
553            entry_count: obj.entry_count(),
554            id_delta: obj.id_delta(),
555            id_range_offset: obj.id_range_offset(),
556        }
557    }
558}
559
560/// [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
561#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
562#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
563pub struct Cmap4 {
564    /// For requirements on use of the language field, see “Use of
565    /// the language field in 'cmap' subtables” in this document.
566    pub language: u16,
567    /// End characterCode for each segment, last=0xFFFF.
568    pub end_code: Vec<u16>,
569    /// Start character code for each segment.
570    pub start_code: Vec<u16>,
571    /// Delta for all character codes in segment.
572    pub id_delta: Vec<i16>,
573    /// Offsets into glyphIdArray or 0
574    pub id_range_offsets: Vec<u16>,
575    /// Glyph index array (arbitrary length)
576    pub glyph_id_array: Vec<u16>,
577}
578
579impl Cmap4 {
580    /// Construct a new `Cmap4`
581    pub fn new(
582        language: u16,
583        end_code: Vec<u16>,
584        start_code: Vec<u16>,
585        id_delta: Vec<i16>,
586        id_range_offsets: Vec<u16>,
587        glyph_id_array: Vec<u16>,
588    ) -> Self {
589        Self {
590            language,
591            end_code,
592            start_code,
593            id_delta,
594            id_range_offsets,
595            glyph_id_array,
596        }
597    }
598}
599
600impl FontWrite for Cmap4 {
601    #[allow(clippy::unnecessary_cast)]
602    fn write_into(&self, writer: &mut TableWriter) {
603        (4 as u16).write_into(writer);
604        (self.compute_length() as u16).write_into(writer);
605        self.language.write_into(writer);
606        (u16::try_from(2 * array_len(&self.end_code)).unwrap()).write_into(writer);
607        (self.compute_search_range() as u16).write_into(writer);
608        (self.compute_entry_selector() as u16).write_into(writer);
609        (self.compute_range_shift() as u16).write_into(writer);
610        self.end_code.write_into(writer);
611        (0 as u16).write_into(writer);
612        self.start_code.write_into(writer);
613        self.id_delta.write_into(writer);
614        self.id_range_offsets.write_into(writer);
615        self.glyph_id_array.write_into(writer);
616    }
617    fn table_type(&self) -> TableType {
618        TableType::Named("Cmap4")
619    }
620}
621
622impl Validate for Cmap4 {
623    fn validate_impl(&self, ctx: &mut ValidationCtx) {
624        ctx.in_table("Cmap4", |ctx| {
625            self.check_length(ctx);
626        })
627    }
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    /// Array of VariationSelector records.
1174    pub var_selector: Vec<VariationSelector>,
1175}
1176
1177impl Cmap14 {
1178    /// Construct a new `Cmap14`
1179    pub fn new(var_selector: Vec<VariationSelector>) -> Self {
1180        Self { var_selector }
1181    }
1182}
1183
1184impl Validate for Cmap14 {
1185    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1186        ctx.in_table("Cmap14", |ctx| {
1187            ctx.in_field("var_selector", |ctx| {
1188                if self.var_selector.len() > to_usize(u32::MAX) {
1189                    ctx.report("array exceeds max length");
1190                }
1191                self.var_selector.validate_impl(ctx);
1192            });
1193        })
1194    }
1195}
1196
1197impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap14<'a>> for Cmap14 {
1198    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap14<'a>, _: FontData) -> Self {
1199        let offset_data = obj.offset_data();
1200        Cmap14 {
1201            var_selector: obj.var_selector().to_owned_obj(offset_data),
1202        }
1203    }
1204}
1205
1206#[allow(clippy::needless_lifetimes)]
1207impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap14<'a>> for Cmap14 {}
1208
1209impl ReadArgs for Cmap14 {
1210    type Args = ();
1211}
1212
1213impl<'a> FontRead<'a> for Cmap14 {
1214    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1215        <read_fonts::tables::cmap::Cmap14 as FontRead>::read(data).map(|x| x.to_owned_table())
1216    }
1217}
1218
1219/// Part of [Cmap14]
1220#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1221#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1222pub struct VariationSelector {
1223    /// Variation selector
1224    pub var_selector: Uint24,
1225    /// Offset from the start of the [`Cmap14`] subtable to Default UVS
1226    /// Table. May be NULL.
1227    pub default_uvs: NullableOffsetMarker<DefaultUvs, WIDTH_32>,
1228    /// Offset from the start of the [`Cmap14`] subtable to Non-Default
1229    /// UVS Table. May be NULL.
1230    pub non_default_uvs: NullableOffsetMarker<NonDefaultUvs, WIDTH_32>,
1231}
1232
1233impl VariationSelector {
1234    /// Construct a new `VariationSelector`
1235    pub fn new(
1236        var_selector: Uint24,
1237        default_uvs: Option<DefaultUvs>,
1238        non_default_uvs: Option<NonDefaultUvs>,
1239    ) -> Self {
1240        Self {
1241            var_selector,
1242            default_uvs: default_uvs.into(),
1243            non_default_uvs: non_default_uvs.into(),
1244        }
1245    }
1246}
1247
1248impl FontWrite for VariationSelector {
1249    fn write_into(&self, writer: &mut TableWriter) {
1250        self.var_selector.write_into(writer);
1251        self.default_uvs.write_into(writer);
1252        self.non_default_uvs.write_into(writer);
1253    }
1254    fn table_type(&self) -> TableType {
1255        TableType::Named("VariationSelector")
1256    }
1257}
1258
1259impl Validate for VariationSelector {
1260    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1261        ctx.in_table("VariationSelector", |ctx| {
1262            ctx.in_field("default_uvs", |ctx| {
1263                self.default_uvs.validate_impl(ctx);
1264            });
1265            ctx.in_field("non_default_uvs", |ctx| {
1266                self.non_default_uvs.validate_impl(ctx);
1267            });
1268        })
1269    }
1270}
1271
1272impl FromObjRef<read_fonts::tables::cmap::VariationSelector> for VariationSelector {
1273    fn from_obj_ref(
1274        obj: &read_fonts::tables::cmap::VariationSelector,
1275        offset_data: FontData,
1276    ) -> Self {
1277        VariationSelector {
1278            var_selector: obj.var_selector(),
1279            default_uvs: obj.default_uvs(offset_data).to_owned_table(),
1280            non_default_uvs: obj.non_default_uvs(offset_data).to_owned_table(),
1281        }
1282    }
1283}
1284
1285/// [Default UVS table](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#default-uvs-table)
1286#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1287#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1288pub struct DefaultUvs {
1289    /// Number of Unicode character ranges.
1290    pub num_unicode_value_ranges: u32,
1291    /// Array of UnicodeRange records.
1292    pub ranges: Vec<UnicodeRange>,
1293}
1294
1295impl DefaultUvs {
1296    /// Construct a new `DefaultUvs`
1297    pub fn new(num_unicode_value_ranges: u32, ranges: Vec<UnicodeRange>) -> Self {
1298        Self {
1299            num_unicode_value_ranges,
1300            ranges,
1301        }
1302    }
1303}
1304
1305impl FontWrite for DefaultUvs {
1306    fn write_into(&self, writer: &mut TableWriter) {
1307        self.num_unicode_value_ranges.write_into(writer);
1308        self.ranges.write_into(writer);
1309    }
1310    fn table_type(&self) -> TableType {
1311        TableType::Named("DefaultUvs")
1312    }
1313}
1314
1315impl Validate for DefaultUvs {
1316    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1317        ctx.in_table("DefaultUvs", |ctx| {
1318            ctx.in_field("ranges", |ctx| {
1319                if self.ranges.len() > to_usize(u32::MAX) {
1320                    ctx.report("array exceeds max length");
1321                }
1322                self.ranges.validate_impl(ctx);
1323            });
1324        })
1325    }
1326}
1327
1328impl<'a> FromObjRef<read_fonts::tables::cmap::DefaultUvs<'a>> for DefaultUvs {
1329    fn from_obj_ref(obj: &read_fonts::tables::cmap::DefaultUvs<'a>, _: FontData) -> Self {
1330        let offset_data = obj.offset_data();
1331        DefaultUvs {
1332            num_unicode_value_ranges: obj.num_unicode_value_ranges(),
1333            ranges: obj.ranges().to_owned_obj(offset_data),
1334        }
1335    }
1336}
1337
1338#[allow(clippy::needless_lifetimes)]
1339impl<'a> FromTableRef<read_fonts::tables::cmap::DefaultUvs<'a>> for DefaultUvs {}
1340
1341impl ReadArgs for DefaultUvs {
1342    type Args = ();
1343}
1344
1345impl<'a> FontRead<'a> for DefaultUvs {
1346    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1347        <read_fonts::tables::cmap::DefaultUvs as FontRead>::read(data).map(|x| x.to_owned_table())
1348    }
1349}
1350
1351/// [Non-Default UVS table](https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#non-default-uvs-table)
1352#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1353#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1354pub struct NonDefaultUvs {
1355    pub num_uvs_mappings: u32,
1356    pub uvs_mapping: Vec<UvsMapping>,
1357}
1358
1359impl NonDefaultUvs {
1360    /// Construct a new `NonDefaultUvs`
1361    pub fn new(num_uvs_mappings: u32, uvs_mapping: Vec<UvsMapping>) -> Self {
1362        Self {
1363            num_uvs_mappings,
1364            uvs_mapping,
1365        }
1366    }
1367}
1368
1369impl FontWrite for NonDefaultUvs {
1370    fn write_into(&self, writer: &mut TableWriter) {
1371        self.num_uvs_mappings.write_into(writer);
1372        self.uvs_mapping.write_into(writer);
1373    }
1374    fn table_type(&self) -> TableType {
1375        TableType::Named("NonDefaultUvs")
1376    }
1377}
1378
1379impl Validate for NonDefaultUvs {
1380    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1381        ctx.in_table("NonDefaultUvs", |ctx| {
1382            ctx.in_field("uvs_mapping", |ctx| {
1383                if self.uvs_mapping.len() > to_usize(u32::MAX) {
1384                    ctx.report("array exceeds max length");
1385                }
1386                self.uvs_mapping.validate_impl(ctx);
1387            });
1388        })
1389    }
1390}
1391
1392impl<'a> FromObjRef<read_fonts::tables::cmap::NonDefaultUvs<'a>> for NonDefaultUvs {
1393    fn from_obj_ref(obj: &read_fonts::tables::cmap::NonDefaultUvs<'a>, _: FontData) -> Self {
1394        let offset_data = obj.offset_data();
1395        NonDefaultUvs {
1396            num_uvs_mappings: obj.num_uvs_mappings(),
1397            uvs_mapping: obj.uvs_mapping().to_owned_obj(offset_data),
1398        }
1399    }
1400}
1401
1402#[allow(clippy::needless_lifetimes)]
1403impl<'a> FromTableRef<read_fonts::tables::cmap::NonDefaultUvs<'a>> for NonDefaultUvs {}
1404
1405impl ReadArgs for NonDefaultUvs {
1406    type Args = ();
1407}
1408
1409impl<'a> FontRead<'a> for NonDefaultUvs {
1410    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1411        <read_fonts::tables::cmap::NonDefaultUvs as FontRead>::read(data)
1412            .map(|x| x.to_owned_table())
1413    }
1414}
1415
1416/// Part of [Cmap14]
1417#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1418#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1419pub struct UvsMapping {
1420    /// Base Unicode value of the UVS
1421    pub unicode_value: Uint24,
1422    /// Glyph ID of the UVS
1423    pub glyph_id: u16,
1424}
1425
1426impl UvsMapping {
1427    /// Construct a new `UvsMapping`
1428    pub fn new(unicode_value: Uint24, glyph_id: u16) -> Self {
1429        Self {
1430            unicode_value,
1431            glyph_id,
1432        }
1433    }
1434}
1435
1436impl FontWrite for UvsMapping {
1437    fn write_into(&self, writer: &mut TableWriter) {
1438        self.unicode_value.write_into(writer);
1439        self.glyph_id.write_into(writer);
1440    }
1441    fn table_type(&self) -> TableType {
1442        TableType::Named("UvsMapping")
1443    }
1444}
1445
1446impl Validate for UvsMapping {
1447    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1448}
1449
1450impl FromObjRef<read_fonts::tables::cmap::UvsMapping> for UvsMapping {
1451    fn from_obj_ref(obj: &read_fonts::tables::cmap::UvsMapping, _: FontData) -> Self {
1452        UvsMapping {
1453            unicode_value: obj.unicode_value(),
1454            glyph_id: obj.glyph_id(),
1455        }
1456    }
1457}
1458
1459/// Part of [Cmap14]
1460#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1461#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1462pub struct UnicodeRange {
1463    /// First value in this range
1464    pub start_unicode_value: Uint24,
1465    /// Number of additional values in this range
1466    pub additional_count: u8,
1467}
1468
1469impl UnicodeRange {
1470    /// Construct a new `UnicodeRange`
1471    pub fn new(start_unicode_value: Uint24, additional_count: u8) -> Self {
1472        Self {
1473            start_unicode_value,
1474            additional_count,
1475        }
1476    }
1477}
1478
1479impl FontWrite for UnicodeRange {
1480    fn write_into(&self, writer: &mut TableWriter) {
1481        self.start_unicode_value.write_into(writer);
1482        self.additional_count.write_into(writer);
1483    }
1484    fn table_type(&self) -> TableType {
1485        TableType::Named("UnicodeRange")
1486    }
1487}
1488
1489impl Validate for UnicodeRange {
1490    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1491}
1492
1493impl FromObjRef<read_fonts::tables::cmap::UnicodeRange> for UnicodeRange {
1494    fn from_obj_ref(obj: &read_fonts::tables::cmap::UnicodeRange, _: FontData) -> Self {
1495        UnicodeRange {
1496            start_unicode_value: obj.start_unicode_value(),
1497            additional_count: obj.additional_count(),
1498        }
1499    }
1500}