write_fonts/generated/
generated_cmap.rs

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