Skip to main content

write_fonts/generated/
generated_ift.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::ift::{
9    EntryFormatFlags, GlyphKeyedFlags, PatchMapFieldPresenceFlags, TablePatchFlags,
10};
11
12#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub enum Ift {
15    Format1(PatchMapFormat1),
16    Format2(PatchMapFormat2),
17}
18
19impl Ift {
20    /// Construct a new `PatchMapFormat1` subtable
21    #[allow(clippy::too_many_arguments)]
22    pub fn format_1(
23        field_flags: PatchMapFieldPresenceFlags,
24        compatibility_id: CompatibilityId,
25        max_entry_index: u16,
26        max_glyph_map_entry_index: u16,
27        glyph_count: Uint24,
28        glyph_map: GlyphMap,
29        feature_map: Option<FeatureMap>,
30        applied_entries_bitmap: Vec<u8>,
31        url_template_length: u16,
32        url_template: Vec<u8>,
33        patch_format: u8,
34    ) -> Self {
35        Self::Format1(PatchMapFormat1::new(
36            field_flags,
37            compatibility_id,
38            max_entry_index,
39            max_glyph_map_entry_index,
40            glyph_count,
41            glyph_map,
42            feature_map,
43            applied_entries_bitmap,
44            url_template_length,
45            url_template,
46            patch_format,
47        ))
48    }
49
50    /// Construct a new `PatchMapFormat2` subtable
51    #[allow(clippy::too_many_arguments)]
52    pub fn format_2(
53        field_flags: PatchMapFieldPresenceFlags,
54        compatibility_id: CompatibilityId,
55        default_patch_format: u8,
56        entry_count: Uint24,
57        entries: MappingEntries,
58        entry_id_string_data: Option<IdStringData>,
59        url_template_length: u16,
60        url_template: Vec<u8>,
61    ) -> Self {
62        Self::Format2(PatchMapFormat2::new(
63            field_flags,
64            compatibility_id,
65            default_patch_format,
66            entry_count,
67            entries,
68            entry_id_string_data,
69            url_template_length,
70            url_template,
71        ))
72    }
73}
74
75impl Default for Ift {
76    fn default() -> Self {
77        Self::Format1(Default::default())
78    }
79}
80
81impl FontWrite for Ift {
82    fn write_into(&self, writer: &mut TableWriter) {
83        match self {
84            Self::Format1(item) => item.write_into(writer),
85            Self::Format2(item) => item.write_into(writer),
86        }
87    }
88    fn table_type(&self) -> TableType {
89        match self {
90            Self::Format1(item) => item.table_type(),
91            Self::Format2(item) => item.table_type(),
92        }
93    }
94}
95
96impl Validate for Ift {
97    fn validate_impl(&self, ctx: &mut ValidationCtx) {
98        match self {
99            Self::Format1(item) => item.validate_impl(ctx),
100            Self::Format2(item) => item.validate_impl(ctx),
101        }
102    }
103}
104
105impl FromObjRef<read_fonts::tables::ift::Ift<'_>> for Ift {
106    fn from_obj_ref(obj: &read_fonts::tables::ift::Ift, _: FontData) -> Self {
107        use read_fonts::tables::ift::Ift as ObjRefType;
108        match obj {
109            ObjRefType::Format1(item) => Ift::Format1(item.to_owned_table()),
110            ObjRefType::Format2(item) => Ift::Format2(item.to_owned_table()),
111        }
112    }
113}
114
115impl FromTableRef<read_fonts::tables::ift::Ift<'_>> for Ift {}
116
117impl ReadArgs for Ift {
118    type Args = ();
119}
120
121impl<'a> FontRead<'a> for Ift {
122    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
123        <read_fonts::tables::ift::Ift as FontRead>::read(data).map(|x| x.to_owned_table())
124    }
125}
126
127impl From<PatchMapFormat1> for Ift {
128    fn from(src: PatchMapFormat1) -> Ift {
129        Ift::Format1(src)
130    }
131}
132
133impl From<PatchMapFormat2> for Ift {
134    fn from(src: PatchMapFormat2) -> Ift {
135        Ift::Format2(src)
136    }
137}
138
139impl FontWrite for PatchMapFieldPresenceFlags {
140    fn write_into(&self, writer: &mut TableWriter) {
141        writer.write_slice(&self.bits().to_be_bytes())
142    }
143}
144
145/// [Patch Map Format Format 1](https://w3c.github.io/IFT/Overview.html#patch-map-format-1)
146#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
147#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
148pub struct PatchMapFormat1 {
149    pub field_flags: PatchMapFieldPresenceFlags,
150    /// Unique ID that identifies compatible patches.
151    pub compatibility_id: CompatibilityId,
152    /// Largest entry index which appears in either the glyph map or feature map.
153    pub max_entry_index: u16,
154    /// Largest entry index which appears in the glyph map.
155    pub max_glyph_map_entry_index: u16,
156    pub glyph_count: Uint24,
157    /// Sub table that maps glyph ids to entry indices.
158    pub glyph_map: OffsetMarker<GlyphMap, WIDTH_32>,
159    /// Sub table that maps feature and glyph ids to entry indices.
160    pub feature_map: NullableOffsetMarker<FeatureMap, WIDTH_32>,
161    pub applied_entries_bitmap: Vec<u8>,
162    pub url_template_length: u16,
163    pub url_template: Vec<u8>,
164    /// Patch format number for patches referenced by this mapping.
165    pub patch_format: u8,
166    pub cff_charstrings_offset: Option<u32>,
167    pub cff2_charstrings_offset: Option<u32>,
168}
169
170impl PatchMapFormat1 {
171    /// Construct a new `PatchMapFormat1`
172    #[allow(clippy::too_many_arguments)]
173    pub fn new(
174        field_flags: PatchMapFieldPresenceFlags,
175        compatibility_id: CompatibilityId,
176        max_entry_index: u16,
177        max_glyph_map_entry_index: u16,
178        glyph_count: Uint24,
179        glyph_map: GlyphMap,
180        feature_map: Option<FeatureMap>,
181        applied_entries_bitmap: Vec<u8>,
182        url_template_length: u16,
183        url_template: Vec<u8>,
184        patch_format: u8,
185    ) -> Self {
186        Self {
187            field_flags,
188            compatibility_id,
189            max_entry_index,
190            max_glyph_map_entry_index,
191            glyph_count,
192            glyph_map: glyph_map.into(),
193            feature_map: feature_map.into(),
194            applied_entries_bitmap,
195            url_template_length,
196            url_template,
197            patch_format,
198            ..Default::default()
199        }
200    }
201}
202
203impl FontWrite for PatchMapFormat1 {
204    #[allow(clippy::unnecessary_cast)]
205    fn write_into(&self, writer: &mut TableWriter) {
206        (1 as u8).write_into(writer);
207        (0 as u8).write_into(writer);
208        (0 as u8).write_into(writer);
209        (0 as u8).write_into(writer);
210        self.field_flags.write_into(writer);
211        self.compatibility_id.write_into(writer);
212        self.max_entry_index.write_into(writer);
213        self.max_glyph_map_entry_index.write_into(writer);
214        self.glyph_count.write_into(writer);
215        self.glyph_map.write_into(writer);
216        self.feature_map.write_into(writer);
217        self.applied_entries_bitmap.write_into(writer);
218        self.url_template_length.write_into(writer);
219        self.url_template.write_into(writer);
220        self.patch_format.write_into(writer);
221        self.field_flags
222            .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET)
223            .then(|| {
224                self.cff_charstrings_offset
225                    .as_ref()
226                    .expect("missing conditional field should have failed validation")
227                    .write_into(writer)
228            });
229        self.field_flags
230            .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET)
231            .then(|| {
232                self.cff2_charstrings_offset
233                    .as_ref()
234                    .expect("missing conditional field should have failed validation")
235                    .write_into(writer)
236            });
237    }
238    fn table_type(&self) -> TableType {
239        TableType::Named("PatchMapFormat1")
240    }
241}
242
243impl Validate for PatchMapFormat1 {
244    fn validate_impl(&self, ctx: &mut ValidationCtx) {
245        ctx.in_table("PatchMapFormat1", |ctx| {
246            ctx.in_field("glyph_map", |ctx| {
247                self.glyph_map.validate_impl(ctx);
248            });
249            ctx.in_field("feature_map", |ctx| {
250                self.feature_map.validate_impl(ctx);
251            });
252            ctx.in_field("url_template", |ctx| {
253                if self.url_template.len() > to_usize(u16::MAX) {
254                    ctx.report("array exceeds max length");
255                }
256            });
257            ctx.in_field("cff_charstrings_offset", |ctx| {
258                if !(self
259                    .field_flags
260                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
261                    && self.cff_charstrings_offset.is_some()
262                {
263                    ctx.report(
264                        "'cff_charstrings_offset' is present but CFF_CHARSTRINGS_OFFSET not set",
265                    )
266                }
267                if (self
268                    .field_flags
269                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
270                    && self.cff_charstrings_offset.is_none()
271                {
272                    ctx.report("CFF_CHARSTRINGS_OFFSET is set but 'cff_charstrings_offset' is None")
273                }
274            });
275            ctx.in_field("cff2_charstrings_offset", |ctx| {
276                if !(self
277                    .field_flags
278                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
279                    && self.cff2_charstrings_offset.is_some()
280                {
281                    ctx.report(
282                        "'cff2_charstrings_offset' is present but CFF2_CHARSTRINGS_OFFSET not set",
283                    )
284                }
285                if (self
286                    .field_flags
287                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
288                    && self.cff2_charstrings_offset.is_none()
289                {
290                    ctx.report(
291                        "CFF2_CHARSTRINGS_OFFSET is set but 'cff2_charstrings_offset' is None",
292                    )
293                }
294            });
295        })
296    }
297}
298
299impl<'a> FromObjRef<read_fonts::tables::ift::PatchMapFormat1<'a>> for PatchMapFormat1 {
300    fn from_obj_ref(obj: &read_fonts::tables::ift::PatchMapFormat1<'a>, _: FontData) -> Self {
301        let offset_data = obj.offset_data();
302        PatchMapFormat1 {
303            field_flags: obj.field_flags(),
304            compatibility_id: obj.compatibility_id(),
305            max_entry_index: obj.max_entry_index(),
306            max_glyph_map_entry_index: obj.max_glyph_map_entry_index(),
307            glyph_count: obj.glyph_count(),
308            glyph_map: obj.glyph_map().to_owned_table(),
309            feature_map: obj.feature_map().to_owned_table(),
310            applied_entries_bitmap: obj.applied_entries_bitmap().to_owned_obj(offset_data),
311            url_template_length: obj.url_template_length(),
312            url_template: obj.url_template().to_owned_obj(offset_data),
313            patch_format: obj.patch_format(),
314            cff_charstrings_offset: obj.cff_charstrings_offset(),
315            cff2_charstrings_offset: obj.cff2_charstrings_offset(),
316        }
317    }
318}
319
320#[allow(clippy::needless_lifetimes)]
321impl<'a> FromTableRef<read_fonts::tables::ift::PatchMapFormat1<'a>> for PatchMapFormat1 {}
322
323impl ReadArgs for PatchMapFormat1 {
324    type Args = ();
325}
326
327impl<'a> FontRead<'a> for PatchMapFormat1 {
328    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
329        <read_fonts::tables::ift::PatchMapFormat1 as FontRead>::read(data)
330            .map(|x| x.to_owned_table())
331    }
332}
333
334#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
335#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
336pub struct GlyphMap {
337    pub first_mapped_glyph: u16,
338}
339
340impl GlyphMap {
341    /// Construct a new `GlyphMap`
342    pub fn new(first_mapped_glyph: u16) -> Self {
343        Self { first_mapped_glyph }
344    }
345}
346
347impl FontWrite for GlyphMap {
348    #[allow(clippy::unnecessary_cast)]
349    fn write_into(&self, writer: &mut TableWriter) {
350        self.first_mapped_glyph.write_into(writer);
351    }
352    fn table_type(&self) -> TableType {
353        TableType::Named("GlyphMap")
354    }
355}
356
357impl Validate for GlyphMap {
358    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
359}
360
361impl<'a> FromObjRef<read_fonts::tables::ift::GlyphMap<'a>> for GlyphMap {
362    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphMap<'a>, _: FontData) -> Self {
363        let offset_data = obj.offset_data();
364        GlyphMap {
365            first_mapped_glyph: obj.first_mapped_glyph(),
366        }
367    }
368}
369
370#[allow(clippy::needless_lifetimes)]
371impl<'a> FromTableRef<read_fonts::tables::ift::GlyphMap<'a>> for GlyphMap {}
372
373#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
374#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
375pub struct FeatureMap {
376    pub feature_count: u16,
377    pub entry_map_data: Vec<u8>,
378}
379
380impl FeatureMap {
381    /// Construct a new `FeatureMap`
382    pub fn new(feature_count: u16, entry_map_data: Vec<u8>) -> Self {
383        Self {
384            feature_count,
385            entry_map_data,
386        }
387    }
388}
389
390impl FontWrite for FeatureMap {
391    #[allow(clippy::unnecessary_cast)]
392    fn write_into(&self, writer: &mut TableWriter) {
393        self.feature_count.write_into(writer);
394        self.entry_map_data.write_into(writer);
395    }
396    fn table_type(&self) -> TableType {
397        TableType::Named("FeatureMap")
398    }
399}
400
401impl Validate for FeatureMap {
402    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
403}
404
405impl<'a> FromObjRef<read_fonts::tables::ift::FeatureMap<'a>> for FeatureMap {
406    fn from_obj_ref(obj: &read_fonts::tables::ift::FeatureMap<'a>, _: FontData) -> Self {
407        let offset_data = obj.offset_data();
408        FeatureMap {
409            feature_count: obj.feature_count(),
410            entry_map_data: obj.entry_map_data().to_owned_obj(offset_data),
411        }
412    }
413}
414
415#[allow(clippy::needless_lifetimes)]
416impl<'a> FromTableRef<read_fonts::tables::ift::FeatureMap<'a>> for FeatureMap {}
417
418#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
419#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
420pub struct FeatureRecord {
421    pub feature_tag: Tag,
422}
423
424impl FeatureRecord {
425    /// Construct a new `FeatureRecord`
426    pub fn new(feature_tag: Tag) -> Self {
427        Self { feature_tag }
428    }
429}
430
431impl FontWrite for FeatureRecord {
432    #[allow(clippy::unnecessary_cast)]
433    fn write_into(&self, writer: &mut TableWriter) {
434        self.feature_tag.write_into(writer);
435    }
436    fn table_type(&self) -> TableType {
437        TableType::Named("FeatureRecord")
438    }
439}
440
441impl Validate for FeatureRecord {
442    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
443}
444
445impl FromObjRef<read_fonts::tables::ift::FeatureRecord> for FeatureRecord {
446    fn from_obj_ref(obj: &read_fonts::tables::ift::FeatureRecord, offset_data: FontData) -> Self {
447        FeatureRecord {
448            feature_tag: obj.feature_tag(),
449        }
450    }
451}
452
453#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
454#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
455pub struct EntryMapRecord {}
456
457impl EntryMapRecord {
458    /// Construct a new `EntryMapRecord`
459    pub fn new() -> Self {
460        Self {}
461    }
462}
463
464impl FontWrite for EntryMapRecord {
465    #[allow(clippy::unnecessary_cast)]
466    fn write_into(&self, writer: &mut TableWriter) {}
467    fn table_type(&self) -> TableType {
468        TableType::Named("EntryMapRecord")
469    }
470}
471
472impl Validate for EntryMapRecord {
473    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
474}
475
476impl FromObjRef<read_fonts::tables::ift::EntryMapRecord> for EntryMapRecord {
477    fn from_obj_ref(obj: &read_fonts::tables::ift::EntryMapRecord, offset_data: FontData) -> Self {
478        EntryMapRecord {}
479    }
480}
481
482/// [Patch Map Format Format 2](https://w3c.github.io/IFT/Overview.html#patch-map-format-2)
483#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
484#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
485pub struct PatchMapFormat2 {
486    pub field_flags: PatchMapFieldPresenceFlags,
487    /// Unique ID that identifies compatible patches.
488    pub compatibility_id: CompatibilityId,
489    /// Patch format number for patches referenced by this mapping.
490    pub default_patch_format: u8,
491    pub entry_count: Uint24,
492    pub entries: OffsetMarker<MappingEntries, WIDTH_32>,
493    pub entry_id_string_data: NullableOffsetMarker<IdStringData, WIDTH_32>,
494    pub url_template_length: u16,
495    pub url_template: Vec<u8>,
496    pub cff_charstrings_offset: Option<u32>,
497    pub cff2_charstrings_offset: Option<u32>,
498}
499
500impl PatchMapFormat2 {
501    /// Construct a new `PatchMapFormat2`
502    #[allow(clippy::too_many_arguments)]
503    pub fn new(
504        field_flags: PatchMapFieldPresenceFlags,
505        compatibility_id: CompatibilityId,
506        default_patch_format: u8,
507        entry_count: Uint24,
508        entries: MappingEntries,
509        entry_id_string_data: Option<IdStringData>,
510        url_template_length: u16,
511        url_template: Vec<u8>,
512    ) -> Self {
513        Self {
514            field_flags,
515            compatibility_id,
516            default_patch_format,
517            entry_count,
518            entries: entries.into(),
519            entry_id_string_data: entry_id_string_data.into(),
520            url_template_length,
521            url_template,
522            ..Default::default()
523        }
524    }
525}
526
527impl FontWrite for PatchMapFormat2 {
528    #[allow(clippy::unnecessary_cast)]
529    fn write_into(&self, writer: &mut TableWriter) {
530        (2 as u8).write_into(writer);
531        (0 as u8).write_into(writer);
532        (0 as u8).write_into(writer);
533        (0 as u8).write_into(writer);
534        self.field_flags.write_into(writer);
535        self.compatibility_id.write_into(writer);
536        self.default_patch_format.write_into(writer);
537        self.entry_count.write_into(writer);
538        self.entries.write_into(writer);
539        self.entry_id_string_data.write_into(writer);
540        self.url_template_length.write_into(writer);
541        self.url_template.write_into(writer);
542        self.field_flags
543            .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET)
544            .then(|| {
545                self.cff_charstrings_offset
546                    .as_ref()
547                    .expect("missing conditional field should have failed validation")
548                    .write_into(writer)
549            });
550        self.field_flags
551            .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET)
552            .then(|| {
553                self.cff2_charstrings_offset
554                    .as_ref()
555                    .expect("missing conditional field should have failed validation")
556                    .write_into(writer)
557            });
558    }
559    fn table_type(&self) -> TableType {
560        TableType::Named("PatchMapFormat2")
561    }
562}
563
564impl Validate for PatchMapFormat2 {
565    fn validate_impl(&self, ctx: &mut ValidationCtx) {
566        ctx.in_table("PatchMapFormat2", |ctx| {
567            ctx.in_field("entries", |ctx| {
568                self.entries.validate_impl(ctx);
569            });
570            ctx.in_field("entry_id_string_data", |ctx| {
571                self.entry_id_string_data.validate_impl(ctx);
572            });
573            ctx.in_field("url_template", |ctx| {
574                if self.url_template.len() > to_usize(u16::MAX) {
575                    ctx.report("array exceeds max length");
576                }
577            });
578            ctx.in_field("cff_charstrings_offset", |ctx| {
579                if !(self
580                    .field_flags
581                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
582                    && self.cff_charstrings_offset.is_some()
583                {
584                    ctx.report(
585                        "'cff_charstrings_offset' is present but CFF_CHARSTRINGS_OFFSET not set",
586                    )
587                }
588                if (self
589                    .field_flags
590                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
591                    && self.cff_charstrings_offset.is_none()
592                {
593                    ctx.report("CFF_CHARSTRINGS_OFFSET is set but 'cff_charstrings_offset' is None")
594                }
595            });
596            ctx.in_field("cff2_charstrings_offset", |ctx| {
597                if !(self
598                    .field_flags
599                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
600                    && self.cff2_charstrings_offset.is_some()
601                {
602                    ctx.report(
603                        "'cff2_charstrings_offset' is present but CFF2_CHARSTRINGS_OFFSET not set",
604                    )
605                }
606                if (self
607                    .field_flags
608                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
609                    && self.cff2_charstrings_offset.is_none()
610                {
611                    ctx.report(
612                        "CFF2_CHARSTRINGS_OFFSET is set but 'cff2_charstrings_offset' is None",
613                    )
614                }
615            });
616        })
617    }
618}
619
620impl<'a> FromObjRef<read_fonts::tables::ift::PatchMapFormat2<'a>> for PatchMapFormat2 {
621    fn from_obj_ref(obj: &read_fonts::tables::ift::PatchMapFormat2<'a>, _: FontData) -> Self {
622        let offset_data = obj.offset_data();
623        PatchMapFormat2 {
624            field_flags: obj.field_flags(),
625            compatibility_id: obj.compatibility_id(),
626            default_patch_format: obj.default_patch_format(),
627            entry_count: obj.entry_count(),
628            entries: obj.entries().to_owned_table(),
629            entry_id_string_data: obj.entry_id_string_data().to_owned_table(),
630            url_template_length: obj.url_template_length(),
631            url_template: obj.url_template().to_owned_obj(offset_data),
632            cff_charstrings_offset: obj.cff_charstrings_offset(),
633            cff2_charstrings_offset: obj.cff2_charstrings_offset(),
634        }
635    }
636}
637
638#[allow(clippy::needless_lifetimes)]
639impl<'a> FromTableRef<read_fonts::tables::ift::PatchMapFormat2<'a>> for PatchMapFormat2 {}
640
641impl ReadArgs for PatchMapFormat2 {
642    type Args = ();
643}
644
645impl<'a> FontRead<'a> for PatchMapFormat2 {
646    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
647        <read_fonts::tables::ift::PatchMapFormat2 as FontRead>::read(data)
648            .map(|x| x.to_owned_table())
649    }
650}
651
652#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
653#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
654pub struct MappingEntries {
655    pub entry_data: Vec<u8>,
656}
657
658impl MappingEntries {
659    /// Construct a new `MappingEntries`
660    pub fn new(entry_data: Vec<u8>) -> Self {
661        Self { entry_data }
662    }
663}
664
665impl FontWrite for MappingEntries {
666    fn write_into(&self, writer: &mut TableWriter) {
667        self.entry_data.write_into(writer);
668    }
669    fn table_type(&self) -> TableType {
670        TableType::Named("MappingEntries")
671    }
672}
673
674impl Validate for MappingEntries {
675    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
676}
677
678impl<'a> FromObjRef<read_fonts::tables::ift::MappingEntries<'a>> for MappingEntries {
679    fn from_obj_ref(obj: &read_fonts::tables::ift::MappingEntries<'a>, _: FontData) -> Self {
680        let offset_data = obj.offset_data();
681        MappingEntries {
682            entry_data: obj.entry_data().to_owned_obj(offset_data),
683        }
684    }
685}
686
687#[allow(clippy::needless_lifetimes)]
688impl<'a> FromTableRef<read_fonts::tables::ift::MappingEntries<'a>> for MappingEntries {}
689
690impl ReadArgs for MappingEntries {
691    type Args = ();
692}
693
694impl<'a> FontRead<'a> for MappingEntries {
695    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
696        <read_fonts::tables::ift::MappingEntries as FontRead>::read(data)
697            .map(|x| x.to_owned_table())
698    }
699}
700
701#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
702#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
703pub struct EntryData {
704    pub format_flags: EntryFormatFlags,
705    pub feature_count: Option<u8>,
706    pub feature_tags: Option<Vec<Tag>>,
707    pub design_space_count: Option<u16>,
708    pub design_space_segments: Option<Vec<DesignSpaceSegment>>,
709    pub child_indices: Option<Vec<Uint24>>,
710    pub trailing_data: Vec<u8>,
711}
712
713impl EntryData {
714    /// Construct a new `EntryData`
715    pub fn new(format_flags: EntryFormatFlags, trailing_data: Vec<u8>) -> Self {
716        Self {
717            format_flags,
718            trailing_data,
719            ..Default::default()
720        }
721    }
722}
723
724impl FontWrite for EntryData {
725    #[allow(clippy::unnecessary_cast)]
726    fn write_into(&self, writer: &mut TableWriter) {
727        self.format_flags.write_into(writer);
728        self.format_flags
729            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
730            .then(|| {
731                self.feature_count
732                    .as_ref()
733                    .expect("missing conditional field should have failed validation")
734                    .write_into(writer)
735            });
736        self.format_flags
737            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
738            .then(|| {
739                self.feature_tags
740                    .as_ref()
741                    .expect("missing conditional field should have failed validation")
742                    .write_into(writer)
743            });
744        self.format_flags
745            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
746            .then(|| {
747                self.design_space_count
748                    .as_ref()
749                    .expect("missing conditional field should have failed validation")
750                    .write_into(writer)
751            });
752        self.format_flags
753            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
754            .then(|| {
755                self.design_space_segments
756                    .as_ref()
757                    .expect("missing conditional field should have failed validation")
758                    .write_into(writer)
759            });
760        self.format_flags
761            .contains(EntryFormatFlags::CHILD_INDICES)
762            .then(|| {
763                self.child_indices
764                    .as_ref()
765                    .expect("missing conditional field should have failed validation")
766                    .write_into(writer)
767            });
768        self.trailing_data.write_into(writer);
769    }
770    fn table_type(&self) -> TableType {
771        TableType::Named("EntryData")
772    }
773}
774
775impl Validate for EntryData {
776    fn validate_impl(&self, ctx: &mut ValidationCtx) {
777        ctx.in_table("EntryData", |ctx| {
778            ctx.in_field("feature_count", |ctx| {
779                if !(self
780                    .format_flags
781                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
782                    && self.feature_count.is_some()
783                {
784                    ctx.report("'feature_count' is present but FEATURES_AND_DESIGN_SPACE not set")
785                }
786                if (self
787                    .format_flags
788                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
789                    && self.feature_count.is_none()
790                {
791                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'feature_count' is None")
792                }
793            });
794            ctx.in_field("feature_tags", |ctx| {
795                if !(self
796                    .format_flags
797                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
798                    && self.feature_tags.is_some()
799                {
800                    ctx.report("'feature_tags' is present but FEATURES_AND_DESIGN_SPACE not set")
801                }
802                if (self
803                    .format_flags
804                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
805                    && self.feature_tags.is_none()
806                {
807                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'feature_tags' is None")
808                }
809                if self.feature_tags.is_some()
810                    && self.feature_tags.as_ref().unwrap().len() > to_usize(u8::MAX)
811                {
812                    ctx.report("array exceeds max length");
813                }
814            });
815            ctx.in_field("design_space_count", |ctx| {
816                if !(self
817                    .format_flags
818                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
819                    && self.design_space_count.is_some()
820                {
821                    ctx.report(
822                        "'design_space_count' is present but FEATURES_AND_DESIGN_SPACE not set",
823                    )
824                }
825                if (self
826                    .format_flags
827                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
828                    && self.design_space_count.is_none()
829                {
830                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'design_space_count' is None")
831                }
832            });
833            ctx.in_field("design_space_segments", |ctx| {
834                if !(self
835                    .format_flags
836                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
837                    && self.design_space_segments.is_some()
838                {
839                    ctx.report(
840                        "'design_space_segments' is present but FEATURES_AND_DESIGN_SPACE not set",
841                    )
842                }
843                if (self
844                    .format_flags
845                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
846                    && self.design_space_segments.is_none()
847                {
848                    ctx.report(
849                        "FEATURES_AND_DESIGN_SPACE is set but 'design_space_segments' is None",
850                    )
851                }
852                if self.design_space_segments.is_some()
853                    && self.design_space_segments.as_ref().unwrap().len() > to_usize(u16::MAX)
854                {
855                    ctx.report("array exceeds max length");
856                }
857                self.design_space_segments.validate_impl(ctx);
858            });
859            ctx.in_field("child_indices", |ctx| {
860                if !(self.format_flags.contains(EntryFormatFlags::CHILD_INDICES))
861                    && self.child_indices.is_some()
862                {
863                    ctx.report("'child_indices' is present but CHILD_INDICES not set")
864                }
865                if (self.format_flags.contains(EntryFormatFlags::CHILD_INDICES))
866                    && self.child_indices.is_none()
867                {
868                    ctx.report("CHILD_INDICES is set but 'child_indices' is None")
869                }
870            });
871        })
872    }
873}
874
875impl<'a> FromObjRef<read_fonts::tables::ift::EntryData<'a>> for EntryData {
876    fn from_obj_ref(obj: &read_fonts::tables::ift::EntryData<'a>, _: FontData) -> Self {
877        let offset_data = obj.offset_data();
878        EntryData {
879            format_flags: obj.format_flags(),
880            feature_count: obj.feature_count(),
881            feature_tags: obj.feature_tags().to_owned_obj(offset_data),
882            design_space_count: obj.design_space_count(),
883            design_space_segments: obj.design_space_segments().to_owned_obj(offset_data),
884            child_indices: obj.child_indices().to_owned_obj(offset_data),
885            trailing_data: obj.trailing_data().to_owned_obj(offset_data),
886        }
887    }
888}
889
890#[allow(clippy::needless_lifetimes)]
891impl<'a> FromTableRef<read_fonts::tables::ift::EntryData<'a>> for EntryData {}
892
893impl ReadArgs for EntryData {
894    type Args = ();
895}
896
897impl<'a> FontRead<'a> for EntryData {
898    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
899        <read_fonts::tables::ift::EntryData as FontRead>::read(data).map(|x| x.to_owned_table())
900    }
901}
902
903impl FontWrite for EntryFormatFlags {
904    fn write_into(&self, writer: &mut TableWriter) {
905        writer.write_slice(&self.bits().to_be_bytes())
906    }
907}
908
909#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
910#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
911pub struct DesignSpaceSegment {
912    pub axis_tag: Tag,
913    pub start: Fixed,
914    pub end: Fixed,
915}
916
917impl DesignSpaceSegment {
918    /// Construct a new `DesignSpaceSegment`
919    pub fn new(axis_tag: Tag, start: Fixed, end: Fixed) -> Self {
920        Self {
921            axis_tag,
922            start,
923            end,
924        }
925    }
926}
927
928impl FontWrite for DesignSpaceSegment {
929    fn write_into(&self, writer: &mut TableWriter) {
930        self.axis_tag.write_into(writer);
931        self.start.write_into(writer);
932        self.end.write_into(writer);
933    }
934    fn table_type(&self) -> TableType {
935        TableType::Named("DesignSpaceSegment")
936    }
937}
938
939impl Validate for DesignSpaceSegment {
940    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
941}
942
943impl FromObjRef<read_fonts::tables::ift::DesignSpaceSegment> for DesignSpaceSegment {
944    fn from_obj_ref(obj: &read_fonts::tables::ift::DesignSpaceSegment, _: FontData) -> Self {
945        DesignSpaceSegment {
946            axis_tag: obj.axis_tag(),
947            start: obj.start(),
948            end: obj.end(),
949        }
950    }
951}
952
953#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
954#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
955pub struct IdStringData {
956    pub id_data: Vec<u8>,
957}
958
959impl IdStringData {
960    /// Construct a new `IdStringData`
961    pub fn new(id_data: Vec<u8>) -> Self {
962        Self { id_data }
963    }
964}
965
966impl FontWrite for IdStringData {
967    fn write_into(&self, writer: &mut TableWriter) {
968        self.id_data.write_into(writer);
969    }
970    fn table_type(&self) -> TableType {
971        TableType::Named("IdStringData")
972    }
973}
974
975impl Validate for IdStringData {
976    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
977}
978
979impl<'a> FromObjRef<read_fonts::tables::ift::IdStringData<'a>> for IdStringData {
980    fn from_obj_ref(obj: &read_fonts::tables::ift::IdStringData<'a>, _: FontData) -> Self {
981        let offset_data = obj.offset_data();
982        IdStringData {
983            id_data: obj.id_data().to_owned_obj(offset_data),
984        }
985    }
986}
987
988#[allow(clippy::needless_lifetimes)]
989impl<'a> FromTableRef<read_fonts::tables::ift::IdStringData<'a>> for IdStringData {}
990
991impl ReadArgs for IdStringData {
992    type Args = ();
993}
994
995impl<'a> FontRead<'a> for IdStringData {
996    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
997        <read_fonts::tables::ift::IdStringData as FontRead>::read(data).map(|x| x.to_owned_table())
998    }
999}
1000
1001/// [Table Keyed Patch](https://w3c.github.io/IFT/Overview.html#table-keyed)
1002#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1003#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1004pub struct TableKeyedPatch {
1005    pub format: Tag,
1006    /// Unique ID that identifies compatible patches.
1007    pub compatibility_id: CompatibilityId,
1008    pub patches_count: u16,
1009    pub patches: Vec<OffsetMarker<TablePatch, WIDTH_32>>,
1010}
1011
1012impl TableKeyedPatch {
1013    /// Construct a new `TableKeyedPatch`
1014    pub fn new(
1015        format: Tag,
1016        compatibility_id: CompatibilityId,
1017        patches_count: u16,
1018        patches: Vec<TablePatch>,
1019    ) -> Self {
1020        Self {
1021            format,
1022            compatibility_id,
1023            patches_count,
1024            patches: patches.into_iter().map(Into::into).collect(),
1025        }
1026    }
1027}
1028
1029impl FontWrite for TableKeyedPatch {
1030    #[allow(clippy::unnecessary_cast)]
1031    fn write_into(&self, writer: &mut TableWriter) {
1032        self.format.write_into(writer);
1033        (0 as u32).write_into(writer);
1034        self.compatibility_id.write_into(writer);
1035        self.patches_count.write_into(writer);
1036        self.patches.write_into(writer);
1037    }
1038    fn table_type(&self) -> TableType {
1039        TableType::Named("TableKeyedPatch")
1040    }
1041}
1042
1043impl Validate for TableKeyedPatch {
1044    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1045        ctx.in_table("TableKeyedPatch", |ctx| {
1046            ctx.in_field("patches", |ctx| {
1047                self.patches.validate_impl(ctx);
1048            });
1049        })
1050    }
1051}
1052
1053impl<'a> FromObjRef<read_fonts::tables::ift::TableKeyedPatch<'a>> for TableKeyedPatch {
1054    fn from_obj_ref(obj: &read_fonts::tables::ift::TableKeyedPatch<'a>, _: FontData) -> Self {
1055        TableKeyedPatch {
1056            format: obj.format(),
1057            compatibility_id: obj.compatibility_id(),
1058            patches_count: obj.patches_count(),
1059            patches: obj.patches().to_owned_table(),
1060        }
1061    }
1062}
1063
1064#[allow(clippy::needless_lifetimes)]
1065impl<'a> FromTableRef<read_fonts::tables::ift::TableKeyedPatch<'a>> for TableKeyedPatch {}
1066
1067impl ReadArgs for TableKeyedPatch {
1068    type Args = ();
1069}
1070
1071impl<'a> FontRead<'a> for TableKeyedPatch {
1072    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1073        <read_fonts::tables::ift::TableKeyedPatch as FontRead>::read(data)
1074            .map(|x| x.to_owned_table())
1075    }
1076}
1077
1078/// [TablePatch](https://w3c.github.io/IFT/Overview.html#tablepatch)
1079#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1080#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1081pub struct TablePatch {
1082    pub tag: Tag,
1083    pub flags: TablePatchFlags,
1084    pub max_uncompressed_length: u32,
1085    pub brotli_stream: Vec<u8>,
1086}
1087
1088impl TablePatch {
1089    /// Construct a new `TablePatch`
1090    pub fn new(
1091        tag: Tag,
1092        flags: TablePatchFlags,
1093        max_uncompressed_length: u32,
1094        brotli_stream: Vec<u8>,
1095    ) -> Self {
1096        Self {
1097            tag,
1098            flags,
1099            max_uncompressed_length,
1100            brotli_stream,
1101        }
1102    }
1103}
1104
1105impl FontWrite for TablePatch {
1106    fn write_into(&self, writer: &mut TableWriter) {
1107        self.tag.write_into(writer);
1108        self.flags.write_into(writer);
1109        self.max_uncompressed_length.write_into(writer);
1110        self.brotli_stream.write_into(writer);
1111    }
1112    fn table_type(&self) -> TableType {
1113        TableType::Named("TablePatch")
1114    }
1115}
1116
1117impl Validate for TablePatch {
1118    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1119}
1120
1121impl<'a> FromObjRef<read_fonts::tables::ift::TablePatch<'a>> for TablePatch {
1122    fn from_obj_ref(obj: &read_fonts::tables::ift::TablePatch<'a>, _: FontData) -> Self {
1123        let offset_data = obj.offset_data();
1124        TablePatch {
1125            tag: obj.tag(),
1126            flags: obj.flags(),
1127            max_uncompressed_length: obj.max_uncompressed_length(),
1128            brotli_stream: obj.brotli_stream().to_owned_obj(offset_data),
1129        }
1130    }
1131}
1132
1133#[allow(clippy::needless_lifetimes)]
1134impl<'a> FromTableRef<read_fonts::tables::ift::TablePatch<'a>> for TablePatch {}
1135
1136impl ReadArgs for TablePatch {
1137    type Args = ();
1138}
1139
1140impl<'a> FontRead<'a> for TablePatch {
1141    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1142        <read_fonts::tables::ift::TablePatch as FontRead>::read(data).map(|x| x.to_owned_table())
1143    }
1144}
1145
1146impl FontWrite for TablePatchFlags {
1147    fn write_into(&self, writer: &mut TableWriter) {
1148        writer.write_slice(&self.bits().to_be_bytes())
1149    }
1150}
1151
1152/// [Glyph Keyed Patch](https://w3c.github.io/IFT/Overview.html#glyph-keyed)
1153#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1155pub struct GlyphKeyedPatch {
1156    pub format: Tag,
1157    pub flags: GlyphKeyedFlags,
1158    pub compatibility_id: CompatibilityId,
1159    pub max_uncompressed_length: u32,
1160    pub brotli_stream: Vec<u8>,
1161}
1162
1163impl GlyphKeyedPatch {
1164    /// Construct a new `GlyphKeyedPatch`
1165    pub fn new(
1166        format: Tag,
1167        flags: GlyphKeyedFlags,
1168        compatibility_id: CompatibilityId,
1169        max_uncompressed_length: u32,
1170        brotli_stream: Vec<u8>,
1171    ) -> Self {
1172        Self {
1173            format,
1174            flags,
1175            compatibility_id,
1176            max_uncompressed_length,
1177            brotli_stream,
1178        }
1179    }
1180}
1181
1182impl FontWrite for GlyphKeyedPatch {
1183    #[allow(clippy::unnecessary_cast)]
1184    fn write_into(&self, writer: &mut TableWriter) {
1185        self.format.write_into(writer);
1186        (0 as u32).write_into(writer);
1187        self.flags.write_into(writer);
1188        self.compatibility_id.write_into(writer);
1189        self.max_uncompressed_length.write_into(writer);
1190        self.brotli_stream.write_into(writer);
1191    }
1192    fn table_type(&self) -> TableType {
1193        TableType::Named("GlyphKeyedPatch")
1194    }
1195}
1196
1197impl Validate for GlyphKeyedPatch {
1198    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1199}
1200
1201impl<'a> FromObjRef<read_fonts::tables::ift::GlyphKeyedPatch<'a>> for GlyphKeyedPatch {
1202    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphKeyedPatch<'a>, _: FontData) -> Self {
1203        let offset_data = obj.offset_data();
1204        GlyphKeyedPatch {
1205            format: obj.format(),
1206            flags: obj.flags(),
1207            compatibility_id: obj.compatibility_id(),
1208            max_uncompressed_length: obj.max_uncompressed_length(),
1209            brotli_stream: obj.brotli_stream().to_owned_obj(offset_data),
1210        }
1211    }
1212}
1213
1214#[allow(clippy::needless_lifetimes)]
1215impl<'a> FromTableRef<read_fonts::tables::ift::GlyphKeyedPatch<'a>> for GlyphKeyedPatch {}
1216
1217impl ReadArgs for GlyphKeyedPatch {
1218    type Args = ();
1219}
1220
1221impl<'a> FontRead<'a> for GlyphKeyedPatch {
1222    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1223        <read_fonts::tables::ift::GlyphKeyedPatch as FontRead>::read(data)
1224            .map(|x| x.to_owned_table())
1225    }
1226}
1227
1228impl FontWrite for GlyphKeyedFlags {
1229    fn write_into(&self, writer: &mut TableWriter) {
1230        writer.write_slice(&self.bits().to_be_bytes())
1231    }
1232}
1233
1234/// [GlyphPatches](https://w3c.github.io/IFT/Overview.html#glyphpatches)
1235#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1236#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1237pub struct GlyphPatches {
1238    pub glyph_count: u32,
1239    pub table_count: u8,
1240    pub tables: Vec<Tag>,
1241    pub glyph_data: Vec<OffsetMarker<GlyphData, WIDTH_32>>,
1242}
1243
1244impl GlyphPatches {
1245    /// Construct a new `GlyphPatches`
1246    pub fn new(
1247        glyph_count: u32,
1248        table_count: u8,
1249        tables: Vec<Tag>,
1250        glyph_data: Vec<GlyphData>,
1251    ) -> Self {
1252        Self {
1253            glyph_count,
1254            table_count,
1255            tables,
1256            glyph_data: glyph_data.into_iter().map(Into::into).collect(),
1257        }
1258    }
1259}
1260
1261impl FontWrite for GlyphPatches {
1262    #[allow(clippy::unnecessary_cast)]
1263    fn write_into(&self, writer: &mut TableWriter) {
1264        self.glyph_count.write_into(writer);
1265        self.table_count.write_into(writer);
1266        self.tables.write_into(writer);
1267        self.glyph_data.write_into(writer);
1268    }
1269    fn table_type(&self) -> TableType {
1270        TableType::Named("GlyphPatches")
1271    }
1272}
1273
1274impl Validate for GlyphPatches {
1275    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1276        ctx.in_table("GlyphPatches", |ctx| {
1277            ctx.in_field("tables", |ctx| {
1278                if self.tables.len() > to_usize(u8::MAX) {
1279                    ctx.report("array exceeds max length");
1280                }
1281            });
1282            ctx.in_field("glyph_data", |ctx| {
1283                self.glyph_data.validate_impl(ctx);
1284            });
1285        })
1286    }
1287}
1288
1289impl<'a> FromObjRef<read_fonts::tables::ift::GlyphPatches<'a>> for GlyphPatches {
1290    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphPatches<'a>, _: FontData) -> Self {
1291        let offset_data = obj.offset_data();
1292        GlyphPatches {
1293            glyph_count: obj.glyph_count(),
1294            table_count: obj.table_count(),
1295            tables: obj.tables().to_owned_obj(offset_data),
1296            glyph_data: obj.glyph_data().to_owned_table(),
1297        }
1298    }
1299}
1300
1301#[allow(clippy::needless_lifetimes)]
1302impl<'a> FromTableRef<read_fonts::tables::ift::GlyphPatches<'a>> for GlyphPatches {}
1303
1304#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1305#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1306pub struct GlyphData {
1307    pub data: Vec<u8>,
1308}
1309
1310impl GlyphData {
1311    /// Construct a new `GlyphData`
1312    pub fn new(data: Vec<u8>) -> Self {
1313        Self { data }
1314    }
1315}
1316
1317impl FontWrite for GlyphData {
1318    fn write_into(&self, writer: &mut TableWriter) {
1319        self.data.write_into(writer);
1320    }
1321    fn table_type(&self) -> TableType {
1322        TableType::Named("GlyphData")
1323    }
1324}
1325
1326impl Validate for GlyphData {
1327    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1328}
1329
1330impl<'a> FromObjRef<read_fonts::tables::ift::GlyphData<'a>> for GlyphData {
1331    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphData<'a>, _: FontData) -> Self {
1332        let offset_data = obj.offset_data();
1333        GlyphData {
1334            data: obj.data().to_owned_obj(offset_data),
1335        }
1336    }
1337}
1338
1339#[allow(clippy::needless_lifetimes)]
1340impl<'a> FromTableRef<read_fonts::tables::ift::GlyphData<'a>> for GlyphData {}
1341
1342impl ReadArgs for GlyphData {
1343    type Args = ();
1344}
1345
1346impl<'a> FontRead<'a> for GlyphData {
1347    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1348        <read_fonts::tables::ift::GlyphData as FontRead>::read(data).map(|x| x.to_owned_table())
1349    }
1350}