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