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}
625
626impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap4<'a>> for Cmap4 {
627    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap4<'a>, _: FontData) -> Self {
628        let offset_data = obj.offset_data();
629        Cmap4 {
630            language: obj.language(),
631            end_code: obj.end_code().to_owned_obj(offset_data),
632            start_code: obj.start_code().to_owned_obj(offset_data),
633            id_delta: obj.id_delta().to_owned_obj(offset_data),
634            id_range_offsets: obj.id_range_offsets().to_owned_obj(offset_data),
635            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
636        }
637    }
638}
639
640#[allow(clippy::needless_lifetimes)]
641impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap4<'a>> for Cmap4 {}
642
643impl ReadArgs for Cmap4 {
644    type Args = ();
645}
646
647impl<'a> FontRead<'a> for Cmap4 {
648    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
649        <read_fonts::tables::cmap::Cmap4 as FontRead>::read(data).map(|x| x.to_owned_table())
650    }
651}
652
653/// [cmap Format 6](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-6-trimmed-table-mapping): Trimmed table mapping
654#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
655#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
656pub struct Cmap6 {
657    /// This is the length in bytes of the subtable.
658    pub length: u16,
659    /// For requirements on use of the language field, see “Use of
660    /// the language field in 'cmap' subtables” in this document.
661    pub language: u16,
662    /// First character code of subrange.
663    pub first_code: u16,
664    /// Number of character codes in subrange.
665    pub entry_count: u16,
666    /// Array of glyph index values for character codes in the range.
667    pub glyph_id_array: Vec<u16>,
668}
669
670impl Cmap6 {
671    /// Construct a new `Cmap6`
672    pub fn new(
673        length: u16,
674        language: u16,
675        first_code: u16,
676        entry_count: u16,
677        glyph_id_array: Vec<u16>,
678    ) -> Self {
679        Self {
680            length,
681            language,
682            first_code,
683            entry_count,
684            glyph_id_array,
685        }
686    }
687}
688
689impl FontWrite for Cmap6 {
690    #[allow(clippy::unnecessary_cast)]
691    fn write_into(&self, writer: &mut TableWriter) {
692        (6 as u16).write_into(writer);
693        self.length.write_into(writer);
694        self.language.write_into(writer);
695        self.first_code.write_into(writer);
696        self.entry_count.write_into(writer);
697        self.glyph_id_array.write_into(writer);
698    }
699    fn table_type(&self) -> TableType {
700        TableType::Named("Cmap6")
701    }
702}
703
704impl Validate for Cmap6 {
705    fn validate_impl(&self, ctx: &mut ValidationCtx) {
706        ctx.in_table("Cmap6", |ctx| {
707            ctx.in_field("glyph_id_array", |ctx| {
708                if self.glyph_id_array.len() > to_usize(u16::MAX) {
709                    ctx.report("array exceeds max length");
710                }
711            });
712        })
713    }
714}
715
716impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap6<'a>> for Cmap6 {
717    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap6<'a>, _: FontData) -> Self {
718        let offset_data = obj.offset_data();
719        Cmap6 {
720            length: obj.length(),
721            language: obj.language(),
722            first_code: obj.first_code(),
723            entry_count: obj.entry_count(),
724            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
725        }
726    }
727}
728
729#[allow(clippy::needless_lifetimes)]
730impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap6<'a>> for Cmap6 {}
731
732impl ReadArgs for Cmap6 {
733    type Args = ();
734}
735
736impl<'a> FontRead<'a> for Cmap6 {
737    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
738        <read_fonts::tables::cmap::Cmap6 as FontRead>::read(data).map(|x| x.to_owned_table())
739    }
740}
741
742/// [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
743#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
744#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
745pub struct Cmap8 {
746    /// Byte length of this subtable (including the header)
747    pub length: u32,
748    /// For requirements on use of the language field, see “Use of
749    /// the language field in 'cmap' subtables” in this document.
750    pub language: u32,
751    /// Tightly packed array of bits (8K bytes total) indicating
752    /// whether the particular 16-bit (index) value is the start of a
753    /// 32-bit character code
754    pub is32: Vec<u8>,
755    /// Number of groupings which follow
756    pub num_groups: u32,
757    /// Array of SequentialMapGroup records.
758    pub groups: Vec<SequentialMapGroup>,
759}
760
761impl Cmap8 {
762    /// Construct a new `Cmap8`
763    pub fn new(
764        length: u32,
765        language: u32,
766        is32: Vec<u8>,
767        num_groups: u32,
768        groups: Vec<SequentialMapGroup>,
769    ) -> Self {
770        Self {
771            length,
772            language,
773            is32,
774            num_groups,
775            groups,
776        }
777    }
778}
779
780impl FontWrite for Cmap8 {
781    #[allow(clippy::unnecessary_cast)]
782    fn write_into(&self, writer: &mut TableWriter) {
783        (8 as u16).write_into(writer);
784        (0 as u16).write_into(writer);
785        self.length.write_into(writer);
786        self.language.write_into(writer);
787        self.is32.write_into(writer);
788        self.num_groups.write_into(writer);
789        self.groups.write_into(writer);
790    }
791    fn table_type(&self) -> TableType {
792        TableType::Named("Cmap8")
793    }
794}
795
796impl Validate for Cmap8 {
797    fn validate_impl(&self, ctx: &mut ValidationCtx) {
798        ctx.in_table("Cmap8", |ctx| {
799            ctx.in_field("groups", |ctx| {
800                if self.groups.len() > to_usize(u32::MAX) {
801                    ctx.report("array exceeds max length");
802                }
803                self.groups.validate_impl(ctx);
804            });
805        })
806    }
807}
808
809impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap8<'a>> for Cmap8 {
810    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap8<'a>, _: FontData) -> Self {
811        let offset_data = obj.offset_data();
812        Cmap8 {
813            length: obj.length(),
814            language: obj.language(),
815            is32: obj.is32().to_owned_obj(offset_data),
816            num_groups: obj.num_groups(),
817            groups: obj.groups().to_owned_obj(offset_data),
818        }
819    }
820}
821
822#[allow(clippy::needless_lifetimes)]
823impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap8<'a>> for Cmap8 {}
824
825impl ReadArgs for Cmap8 {
826    type Args = ();
827}
828
829impl<'a> FontRead<'a> for Cmap8 {
830    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
831        <read_fonts::tables::cmap::Cmap8 as FontRead>::read(data).map(|x| x.to_owned_table())
832    }
833}
834
835/// Used in [Cmap8] and [Cmap12]
836#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
837#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
838pub struct SequentialMapGroup {
839    /// First character code in this group; note that if this group is
840    /// for one or more 16-bit character codes (which is determined
841    /// from the is32 array), this 32-bit value will have the high
842    /// 16-bits set to zero
843    pub start_char_code: u32,
844    /// Last character code in this group; same condition as listed
845    /// above for the startCharCode
846    pub end_char_code: u32,
847    /// Glyph index corresponding to the starting character code
848    pub start_glyph_id: u32,
849}
850
851impl SequentialMapGroup {
852    /// Construct a new `SequentialMapGroup`
853    pub fn new(start_char_code: u32, end_char_code: u32, start_glyph_id: u32) -> Self {
854        Self {
855            start_char_code,
856            end_char_code,
857            start_glyph_id,
858        }
859    }
860}
861
862impl FontWrite for SequentialMapGroup {
863    fn write_into(&self, writer: &mut TableWriter) {
864        self.start_char_code.write_into(writer);
865        self.end_char_code.write_into(writer);
866        self.start_glyph_id.write_into(writer);
867    }
868    fn table_type(&self) -> TableType {
869        TableType::Named("SequentialMapGroup")
870    }
871}
872
873impl Validate for SequentialMapGroup {
874    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
875}
876
877impl FromObjRef<read_fonts::tables::cmap::SequentialMapGroup> for SequentialMapGroup {
878    fn from_obj_ref(obj: &read_fonts::tables::cmap::SequentialMapGroup, _: FontData) -> Self {
879        SequentialMapGroup {
880            start_char_code: obj.start_char_code(),
881            end_char_code: obj.end_char_code(),
882            start_glyph_id: obj.start_glyph_id(),
883        }
884    }
885}
886
887/// [cmap Format 10](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-10-trimmed-array): Tr
888#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
889#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
890pub struct Cmap10 {
891    /// Byte length of this subtable (including the header)
892    pub length: u32,
893    /// For requirements on use of the language field, see “Use of
894    /// the language field in 'cmap' subtables” in this document.
895    pub language: u32,
896    /// First character code covered
897    pub start_char_code: u32,
898    /// Array of glyph indices for the character codes covered
899    pub glyph_id_array: Vec<u16>,
900}
901
902impl Cmap10 {
903    /// Construct a new `Cmap10`
904    pub fn new(length: u32, language: u32, start_char_code: u32, glyph_id_array: Vec<u16>) -> Self {
905        Self {
906            length,
907            language,
908            start_char_code,
909            glyph_id_array,
910        }
911    }
912}
913
914impl FontWrite for Cmap10 {
915    #[allow(clippy::unnecessary_cast)]
916    fn write_into(&self, writer: &mut TableWriter) {
917        (10 as u16).write_into(writer);
918        (0 as u16).write_into(writer);
919        self.length.write_into(writer);
920        self.language.write_into(writer);
921        self.start_char_code.write_into(writer);
922        (u32::try_from(array_len(&self.glyph_id_array)).unwrap()).write_into(writer);
923        self.glyph_id_array.write_into(writer);
924    }
925    fn table_type(&self) -> TableType {
926        TableType::Named("Cmap10")
927    }
928}
929
930impl Validate for Cmap10 {
931    fn validate_impl(&self, ctx: &mut ValidationCtx) {
932        ctx.in_table("Cmap10", |ctx| {
933            ctx.in_field("glyph_id_array", |ctx| {
934                if self.glyph_id_array.len() > to_usize(u32::MAX) {
935                    ctx.report("array exceeds max length");
936                }
937            });
938        })
939    }
940}
941
942impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap10<'a>> for Cmap10 {
943    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap10<'a>, _: FontData) -> Self {
944        let offset_data = obj.offset_data();
945        Cmap10 {
946            length: obj.length(),
947            language: obj.language(),
948            start_char_code: obj.start_char_code(),
949            glyph_id_array: obj.glyph_id_array().to_owned_obj(offset_data),
950        }
951    }
952}
953
954#[allow(clippy::needless_lifetimes)]
955impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap10<'a>> for Cmap10 {}
956
957impl ReadArgs for Cmap10 {
958    type Args = ();
959}
960
961impl<'a> FontRead<'a> for Cmap10 {
962    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
963        <read_fonts::tables::cmap::Cmap10 as FontRead>::read(data).map(|x| x.to_owned_table())
964    }
965}
966
967/// [cmap Format 12](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage): Segmented coverage
968#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
969#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
970pub struct Cmap12 {
971    /// For requirements on use of the language field, see “Use of
972    /// the language field in 'cmap' subtables” in this document.
973    pub language: u32,
974    /// Array of SequentialMapGroup records.
975    pub groups: Vec<SequentialMapGroup>,
976}
977
978impl Cmap12 {
979    /// Construct a new `Cmap12`
980    pub fn new(language: u32, groups: Vec<SequentialMapGroup>) -> Self {
981        Self { language, groups }
982    }
983}
984
985impl FontWrite for Cmap12 {
986    #[allow(clippy::unnecessary_cast)]
987    fn write_into(&self, writer: &mut TableWriter) {
988        (12 as u16).write_into(writer);
989        (0 as u16).write_into(writer);
990        (self.compute_length() as u32).write_into(writer);
991        self.language.write_into(writer);
992        (u32::try_from(array_len(&self.groups)).unwrap()).write_into(writer);
993        self.groups.write_into(writer);
994    }
995    fn table_type(&self) -> TableType {
996        TableType::Named("Cmap12")
997    }
998}
999
1000impl Validate for Cmap12 {
1001    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1002        ctx.in_table("Cmap12", |ctx| {
1003            ctx.in_field("groups", |ctx| {
1004                if self.groups.len() > to_usize(u32::MAX) {
1005                    ctx.report("array exceeds max length");
1006                }
1007                self.groups.validate_impl(ctx);
1008            });
1009        })
1010    }
1011}
1012
1013impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap12<'a>> for Cmap12 {
1014    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap12<'a>, _: FontData) -> Self {
1015        let offset_data = obj.offset_data();
1016        Cmap12 {
1017            language: obj.language(),
1018            groups: obj.groups().to_owned_obj(offset_data),
1019        }
1020    }
1021}
1022
1023#[allow(clippy::needless_lifetimes)]
1024impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap12<'a>> for Cmap12 {}
1025
1026impl ReadArgs for Cmap12 {
1027    type Args = ();
1028}
1029
1030impl<'a> FontRead<'a> for Cmap12 {
1031    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1032        <read_fonts::tables::cmap::Cmap12 as FontRead>::read(data).map(|x| x.to_owned_table())
1033    }
1034}
1035
1036/// [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
1037#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1038#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1039pub struct Cmap13 {
1040    /// Byte length of this subtable (including the header)
1041    pub length: u32,
1042    /// For requirements on use of the language field, see “Use of
1043    /// the language field in 'cmap' subtables” in this document.
1044    pub language: u32,
1045    /// Number of groupings which follow
1046    pub num_groups: u32,
1047    /// Array of ConstantMapGroup records.
1048    pub groups: Vec<ConstantMapGroup>,
1049}
1050
1051impl Cmap13 {
1052    /// Construct a new `Cmap13`
1053    pub fn new(length: u32, language: u32, num_groups: u32, groups: Vec<ConstantMapGroup>) -> Self {
1054        Self {
1055            length,
1056            language,
1057            num_groups,
1058            groups,
1059        }
1060    }
1061}
1062
1063impl FontWrite for Cmap13 {
1064    #[allow(clippy::unnecessary_cast)]
1065    fn write_into(&self, writer: &mut TableWriter) {
1066        (13 as u16).write_into(writer);
1067        (0 as u16).write_into(writer);
1068        self.length.write_into(writer);
1069        self.language.write_into(writer);
1070        self.num_groups.write_into(writer);
1071        self.groups.write_into(writer);
1072    }
1073    fn table_type(&self) -> TableType {
1074        TableType::Named("Cmap13")
1075    }
1076}
1077
1078impl Validate for Cmap13 {
1079    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1080        ctx.in_table("Cmap13", |ctx| {
1081            ctx.in_field("groups", |ctx| {
1082                if self.groups.len() > to_usize(u32::MAX) {
1083                    ctx.report("array exceeds max length");
1084                }
1085                self.groups.validate_impl(ctx);
1086            });
1087        })
1088    }
1089}
1090
1091impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap13<'a>> for Cmap13 {
1092    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap13<'a>, _: FontData) -> Self {
1093        let offset_data = obj.offset_data();
1094        Cmap13 {
1095            length: obj.length(),
1096            language: obj.language(),
1097            num_groups: obj.num_groups(),
1098            groups: obj.groups().to_owned_obj(offset_data),
1099        }
1100    }
1101}
1102
1103#[allow(clippy::needless_lifetimes)]
1104impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap13<'a>> for Cmap13 {}
1105
1106impl ReadArgs for Cmap13 {
1107    type Args = ();
1108}
1109
1110impl<'a> FontRead<'a> for Cmap13 {
1111    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1112        <read_fonts::tables::cmap::Cmap13 as FontRead>::read(data).map(|x| x.to_owned_table())
1113    }
1114}
1115
1116/// Part of [Cmap13]
1117#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1118#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1119pub struct ConstantMapGroup {
1120    /// First character code in this group
1121    pub start_char_code: u32,
1122    /// Last character code in this group
1123    pub end_char_code: u32,
1124    /// Glyph index to be used for all the characters in the group’s
1125    /// range.
1126    pub glyph_id: u32,
1127}
1128
1129impl ConstantMapGroup {
1130    /// Construct a new `ConstantMapGroup`
1131    pub fn new(start_char_code: u32, end_char_code: u32, glyph_id: u32) -> Self {
1132        Self {
1133            start_char_code,
1134            end_char_code,
1135            glyph_id,
1136        }
1137    }
1138}
1139
1140impl FontWrite for ConstantMapGroup {
1141    fn write_into(&self, writer: &mut TableWriter) {
1142        self.start_char_code.write_into(writer);
1143        self.end_char_code.write_into(writer);
1144        self.glyph_id.write_into(writer);
1145    }
1146    fn table_type(&self) -> TableType {
1147        TableType::Named("ConstantMapGroup")
1148    }
1149}
1150
1151impl Validate for ConstantMapGroup {
1152    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1153}
1154
1155impl FromObjRef<read_fonts::tables::cmap::ConstantMapGroup> for ConstantMapGroup {
1156    fn from_obj_ref(obj: &read_fonts::tables::cmap::ConstantMapGroup, _: FontData) -> Self {
1157        ConstantMapGroup {
1158            start_char_code: obj.start_char_code(),
1159            end_char_code: obj.end_char_code(),
1160            glyph_id: obj.glyph_id(),
1161        }
1162    }
1163}
1164
1165/// [cmap Format 14](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-14-unicode-variation-sequences): Unicode Variation Sequences
1166#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1167#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1168pub struct Cmap14 {
1169    /// Array of VariationSelector records.
1170    pub var_selector: Vec<VariationSelector>,
1171}
1172
1173impl Cmap14 {
1174    /// Construct a new `Cmap14`
1175    pub fn new(var_selector: Vec<VariationSelector>) -> Self {
1176        Self { var_selector }
1177    }
1178}
1179
1180impl Validate for Cmap14 {
1181    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1182        ctx.in_table("Cmap14", |ctx| {
1183            ctx.in_field("var_selector", |ctx| {
1184                if self.var_selector.len() > to_usize(u32::MAX) {
1185                    ctx.report("array exceeds max length");
1186                }
1187                self.var_selector.validate_impl(ctx);
1188            });
1189        })
1190    }
1191}
1192
1193impl<'a> FromObjRef<read_fonts::tables::cmap::Cmap14<'a>> for Cmap14 {
1194    fn from_obj_ref(obj: &read_fonts::tables::cmap::Cmap14<'a>, _: FontData) -> Self {
1195        let offset_data = obj.offset_data();
1196        Cmap14 {
1197            var_selector: obj.var_selector().to_owned_obj(offset_data),
1198        }
1199    }
1200}
1201
1202#[allow(clippy::needless_lifetimes)]
1203impl<'a> FromTableRef<read_fonts::tables::cmap::Cmap14<'a>> for Cmap14 {}
1204
1205impl ReadArgs for Cmap14 {
1206    type Args = ();
1207}
1208
1209impl<'a> FontRead<'a> for Cmap14 {
1210    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1211        <read_fonts::tables::cmap::Cmap14 as FontRead>::read(data).map(|x| x.to_owned_table())
1212    }
1213}
1214
1215/// Part of [Cmap14]
1216#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1217#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1218pub struct VariationSelector {
1219    /// Variation selector
1220    pub var_selector: Uint24,
1221    /// Offset from the start of the [`Cmap14`] subtable to Default UVS
1222    /// Table. May be NULL.
1223    pub default_uvs: NullableOffsetMarker<DefaultUvs, WIDTH_32>,
1224    /// Offset from the start of the [`Cmap14`] subtable to Non-Default
1225    /// UVS Table. May be NULL.
1226    pub non_default_uvs: NullableOffsetMarker<NonDefaultUvs, WIDTH_32>,
1227}
1228
1229impl VariationSelector {
1230    /// Construct a new `VariationSelector`
1231    pub fn new(
1232        var_selector: Uint24,
1233        default_uvs: Option<DefaultUvs>,
1234        non_default_uvs: Option<NonDefaultUvs>,
1235    ) -> Self {
1236        Self {
1237            var_selector,
1238            default_uvs: default_uvs.into(),
1239            non_default_uvs: non_default_uvs.into(),
1240        }
1241    }
1242}
1243
1244impl FontWrite for VariationSelector {
1245    fn write_into(&self, writer: &mut TableWriter) {
1246        self.var_selector.write_into(writer);
1247        self.default_uvs.write_into(writer);
1248        self.non_default_uvs.write_into(writer);
1249    }
1250    fn table_type(&self) -> TableType {
1251        TableType::Named("VariationSelector")
1252    }
1253}
1254
1255impl Validate for VariationSelector {
1256    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1257        ctx.in_table("VariationSelector", |ctx| {
1258            ctx.in_field("default_uvs", |ctx| {
1259                self.default_uvs.validate_impl(ctx);
1260            });
1261            ctx.in_field("non_default_uvs", |ctx| {
1262                self.non_default_uvs.validate_impl(ctx);
1263            });
1264        })
1265    }
1266}
1267
1268impl FromObjRef<read_fonts::tables::cmap::VariationSelector> for VariationSelector {
1269    fn from_obj_ref(
1270        obj: &read_fonts::tables::cmap::VariationSelector,
1271        offset_data: FontData,
1272    ) -> Self {
1273        VariationSelector {
1274            var_selector: obj.var_selector(),
1275            default_uvs: obj.default_uvs(offset_data).to_owned_table(),
1276            non_default_uvs: obj.non_default_uvs(offset_data).to_owned_table(),
1277        }
1278    }
1279}
1280
1281/// [Default UVS table](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#default-uvs-table)
1282#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1283#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1284pub struct DefaultUvs {
1285    /// Number of Unicode character ranges.
1286    pub num_unicode_value_ranges: u32,
1287    /// Array of UnicodeRange records.
1288    pub ranges: Vec<UnicodeRange>,
1289}
1290
1291impl DefaultUvs {
1292    /// Construct a new `DefaultUvs`
1293    pub fn new(num_unicode_value_ranges: u32, ranges: Vec<UnicodeRange>) -> Self {
1294        Self {
1295            num_unicode_value_ranges,
1296            ranges,
1297        }
1298    }
1299}
1300
1301impl FontWrite for DefaultUvs {
1302    fn write_into(&self, writer: &mut TableWriter) {
1303        self.num_unicode_value_ranges.write_into(writer);
1304        self.ranges.write_into(writer);
1305    }
1306    fn table_type(&self) -> TableType {
1307        TableType::Named("DefaultUvs")
1308    }
1309}
1310
1311impl Validate for DefaultUvs {
1312    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1313        ctx.in_table("DefaultUvs", |ctx| {
1314            ctx.in_field("ranges", |ctx| {
1315                if self.ranges.len() > to_usize(u32::MAX) {
1316                    ctx.report("array exceeds max length");
1317                }
1318                self.ranges.validate_impl(ctx);
1319            });
1320        })
1321    }
1322}
1323
1324impl<'a> FromObjRef<read_fonts::tables::cmap::DefaultUvs<'a>> for DefaultUvs {
1325    fn from_obj_ref(obj: &read_fonts::tables::cmap::DefaultUvs<'a>, _: FontData) -> Self {
1326        let offset_data = obj.offset_data();
1327        DefaultUvs {
1328            num_unicode_value_ranges: obj.num_unicode_value_ranges(),
1329            ranges: obj.ranges().to_owned_obj(offset_data),
1330        }
1331    }
1332}
1333
1334#[allow(clippy::needless_lifetimes)]
1335impl<'a> FromTableRef<read_fonts::tables::cmap::DefaultUvs<'a>> for DefaultUvs {}
1336
1337impl ReadArgs for DefaultUvs {
1338    type Args = ();
1339}
1340
1341impl<'a> FontRead<'a> for DefaultUvs {
1342    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1343        <read_fonts::tables::cmap::DefaultUvs as FontRead>::read(data).map(|x| x.to_owned_table())
1344    }
1345}
1346
1347/// [Non-Default UVS table](https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#non-default-uvs-table)
1348#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1349#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1350pub struct NonDefaultUvs {
1351    pub num_uvs_mappings: u32,
1352    pub uvs_mapping: Vec<UvsMapping>,
1353}
1354
1355impl NonDefaultUvs {
1356    /// Construct a new `NonDefaultUvs`
1357    pub fn new(num_uvs_mappings: u32, uvs_mapping: Vec<UvsMapping>) -> Self {
1358        Self {
1359            num_uvs_mappings,
1360            uvs_mapping,
1361        }
1362    }
1363}
1364
1365impl FontWrite for NonDefaultUvs {
1366    fn write_into(&self, writer: &mut TableWriter) {
1367        self.num_uvs_mappings.write_into(writer);
1368        self.uvs_mapping.write_into(writer);
1369    }
1370    fn table_type(&self) -> TableType {
1371        TableType::Named("NonDefaultUvs")
1372    }
1373}
1374
1375impl Validate for NonDefaultUvs {
1376    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1377        ctx.in_table("NonDefaultUvs", |ctx| {
1378            ctx.in_field("uvs_mapping", |ctx| {
1379                if self.uvs_mapping.len() > to_usize(u32::MAX) {
1380                    ctx.report("array exceeds max length");
1381                }
1382                self.uvs_mapping.validate_impl(ctx);
1383            });
1384        })
1385    }
1386}
1387
1388impl<'a> FromObjRef<read_fonts::tables::cmap::NonDefaultUvs<'a>> for NonDefaultUvs {
1389    fn from_obj_ref(obj: &read_fonts::tables::cmap::NonDefaultUvs<'a>, _: FontData) -> Self {
1390        let offset_data = obj.offset_data();
1391        NonDefaultUvs {
1392            num_uvs_mappings: obj.num_uvs_mappings(),
1393            uvs_mapping: obj.uvs_mapping().to_owned_obj(offset_data),
1394        }
1395    }
1396}
1397
1398#[allow(clippy::needless_lifetimes)]
1399impl<'a> FromTableRef<read_fonts::tables::cmap::NonDefaultUvs<'a>> for NonDefaultUvs {}
1400
1401impl ReadArgs for NonDefaultUvs {
1402    type Args = ();
1403}
1404
1405impl<'a> FontRead<'a> for NonDefaultUvs {
1406    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1407        <read_fonts::tables::cmap::NonDefaultUvs as FontRead>::read(data)
1408            .map(|x| x.to_owned_table())
1409    }
1410}
1411
1412/// Part of [Cmap14]
1413#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1414#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1415pub struct UvsMapping {
1416    /// Base Unicode value of the UVS
1417    pub unicode_value: Uint24,
1418    /// Glyph ID of the UVS
1419    pub glyph_id: u16,
1420}
1421
1422impl UvsMapping {
1423    /// Construct a new `UvsMapping`
1424    pub fn new(unicode_value: Uint24, glyph_id: u16) -> Self {
1425        Self {
1426            unicode_value,
1427            glyph_id,
1428        }
1429    }
1430}
1431
1432impl FontWrite for UvsMapping {
1433    fn write_into(&self, writer: &mut TableWriter) {
1434        self.unicode_value.write_into(writer);
1435        self.glyph_id.write_into(writer);
1436    }
1437    fn table_type(&self) -> TableType {
1438        TableType::Named("UvsMapping")
1439    }
1440}
1441
1442impl Validate for UvsMapping {
1443    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1444}
1445
1446impl FromObjRef<read_fonts::tables::cmap::UvsMapping> for UvsMapping {
1447    fn from_obj_ref(obj: &read_fonts::tables::cmap::UvsMapping, _: FontData) -> Self {
1448        UvsMapping {
1449            unicode_value: obj.unicode_value(),
1450            glyph_id: obj.glyph_id(),
1451        }
1452    }
1453}
1454
1455/// Part of [Cmap14]
1456#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1457#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1458pub struct UnicodeRange {
1459    /// First value in this range
1460    pub start_unicode_value: Uint24,
1461    /// Number of additional values in this range
1462    pub additional_count: u8,
1463}
1464
1465impl UnicodeRange {
1466    /// Construct a new `UnicodeRange`
1467    pub fn new(start_unicode_value: Uint24, additional_count: u8) -> Self {
1468        Self {
1469            start_unicode_value,
1470            additional_count,
1471        }
1472    }
1473}
1474
1475impl FontWrite for UnicodeRange {
1476    fn write_into(&self, writer: &mut TableWriter) {
1477        self.start_unicode_value.write_into(writer);
1478        self.additional_count.write_into(writer);
1479    }
1480    fn table_type(&self) -> TableType {
1481        TableType::Named("UnicodeRange")
1482    }
1483}
1484
1485impl Validate for UnicodeRange {
1486    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1487}
1488
1489impl FromObjRef<read_fonts::tables::cmap::UnicodeRange> for UnicodeRange {
1490    fn from_obj_ref(obj: &read_fonts::tables::cmap::UnicodeRange, _: FontData) -> Self {
1491        UnicodeRange {
1492            start_unicode_value: obj.start_unicode_value(),
1493            additional_count: obj.additional_count(),
1494        }
1495    }
1496}