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
12impl FontWrite for PatchMapFieldPresenceFlags {
13    fn write_into(&self, writer: &mut TableWriter) {
14        writer.write_slice(&self.bits().to_be_bytes())
15    }
16}
17
18/// [Patch Map Table](https://w3c.github.io/IFT/Overview.html#patch-map-table)
19#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct IftPatchMap {
22    /// Format identifier: format = 2
23    pub format: u8,
24    pub field_flags: PatchMapFieldPresenceFlags,
25    /// Unique ID that identifies compatible patches.
26    pub compatibility_id: CompatibilityId,
27    /// Patch format number for patches referenced by this mapping.
28    pub default_patch_format: u8,
29    pub entry_count: Uint24,
30    pub entries: OffsetMarker<MappingEntries, WIDTH_32>,
31    pub entry_id_string_data: NullableOffsetMarker<IdStringData, WIDTH_32>,
32    pub url_template_length: u16,
33    pub url_template: Vec<u8>,
34    pub cff_charstrings_offset: Option<u32>,
35    pub cff2_charstrings_offset: Option<u32>,
36}
37
38impl IftPatchMap {
39    /// Construct a new `IftPatchMap`
40    #[allow(clippy::too_many_arguments)]
41    pub fn new(
42        format: u8,
43        field_flags: PatchMapFieldPresenceFlags,
44        compatibility_id: CompatibilityId,
45        default_patch_format: u8,
46        entry_count: Uint24,
47        entries: MappingEntries,
48        entry_id_string_data: Option<IdStringData>,
49        url_template_length: u16,
50        url_template: Vec<u8>,
51    ) -> Self {
52        Self {
53            format,
54            field_flags,
55            compatibility_id,
56            default_patch_format,
57            entry_count,
58            entries: entries.into(),
59            entry_id_string_data: entry_id_string_data.into(),
60            url_template_length,
61            url_template,
62            ..Default::default()
63        }
64    }
65}
66
67impl FontWrite for IftPatchMap {
68    #[allow(clippy::unnecessary_cast)]
69    fn write_into(&self, writer: &mut TableWriter) {
70        self.format.write_into(writer);
71        (0 as u8).write_into(writer);
72        (0 as u8).write_into(writer);
73        (0 as u8).write_into(writer);
74        self.field_flags.write_into(writer);
75        self.compatibility_id.write_into(writer);
76        self.default_patch_format.write_into(writer);
77        self.entry_count.write_into(writer);
78        self.entries.write_into(writer);
79        self.entry_id_string_data.write_into(writer);
80        self.url_template_length.write_into(writer);
81        self.url_template.write_into(writer);
82        self.field_flags
83            .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET)
84            .then(|| {
85                self.cff_charstrings_offset
86                    .as_ref()
87                    .expect("missing conditional field should have failed validation")
88                    .write_into(writer)
89            });
90        self.field_flags
91            .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET)
92            .then(|| {
93                self.cff2_charstrings_offset
94                    .as_ref()
95                    .expect("missing conditional field should have failed validation")
96                    .write_into(writer)
97            });
98    }
99    fn table_type(&self) -> TableType {
100        TableType::Named("IftPatchMap")
101    }
102}
103
104impl Validate for IftPatchMap {
105    fn validate_impl(&self, ctx: &mut ValidationCtx) {
106        ctx.in_table("IftPatchMap", |ctx| {
107            ctx.in_field("entries", |ctx| {
108                self.entries.validate_impl(ctx);
109            });
110            ctx.in_field("entry_id_string_data", |ctx| {
111                self.entry_id_string_data.validate_impl(ctx);
112            });
113            ctx.in_field("url_template", |ctx| {
114                if self.url_template.len() > to_usize(u16::MAX) {
115                    ctx.report("array exceeds max length");
116                }
117            });
118            ctx.in_field("cff_charstrings_offset", |ctx| {
119                if !(self
120                    .field_flags
121                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
122                    && self.cff_charstrings_offset.is_some()
123                {
124                    ctx.report(
125                        "'cff_charstrings_offset' is present but CFF_CHARSTRINGS_OFFSET not set",
126                    )
127                }
128                if (self
129                    .field_flags
130                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
131                    && self.cff_charstrings_offset.is_none()
132                {
133                    ctx.report("CFF_CHARSTRINGS_OFFSET is set but 'cff_charstrings_offset' is None")
134                }
135            });
136            ctx.in_field("cff2_charstrings_offset", |ctx| {
137                if !(self
138                    .field_flags
139                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
140                    && self.cff2_charstrings_offset.is_some()
141                {
142                    ctx.report(
143                        "'cff2_charstrings_offset' is present but CFF2_CHARSTRINGS_OFFSET not set",
144                    )
145                }
146                if (self
147                    .field_flags
148                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
149                    && self.cff2_charstrings_offset.is_none()
150                {
151                    ctx.report(
152                        "CFF2_CHARSTRINGS_OFFSET is set but 'cff2_charstrings_offset' is None",
153                    )
154                }
155            });
156        })
157    }
158}
159
160impl<'a> FromObjRef<read_fonts::tables::ift::IftPatchMap<'a>> for IftPatchMap {
161    fn from_obj_ref(obj: &read_fonts::tables::ift::IftPatchMap<'a>, _: FontData) -> Self {
162        let offset_data = obj.offset_data();
163        IftPatchMap {
164            format: obj.format(),
165            field_flags: obj.field_flags(),
166            compatibility_id: obj.compatibility_id(),
167            default_patch_format: obj.default_patch_format(),
168            entry_count: obj.entry_count(),
169            entries: obj.entries().to_owned_table(),
170            entry_id_string_data: obj.entry_id_string_data().to_owned_table(),
171            url_template_length: obj.url_template_length(),
172            url_template: obj.url_template().to_owned_obj(offset_data),
173            cff_charstrings_offset: obj.cff_charstrings_offset(),
174            cff2_charstrings_offset: obj.cff2_charstrings_offset(),
175        }
176    }
177}
178
179#[allow(clippy::needless_lifetimes)]
180impl<'a> FromTableRef<read_fonts::tables::ift::IftPatchMap<'a>> for IftPatchMap {}
181
182impl ReadArgs for IftPatchMap {
183    type Args = ();
184}
185
186impl<'a> FontRead<'a> for IftPatchMap {
187    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
188        <read_fonts::tables::ift::IftPatchMap as FontRead>::read(data).map(|x| x.to_owned_table())
189    }
190}
191
192#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
193#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
194pub struct MappingEntries {
195    pub entry_data: Vec<u8>,
196}
197
198impl MappingEntries {
199    /// Construct a new `MappingEntries`
200    pub fn new(entry_data: Vec<u8>) -> Self {
201        Self { entry_data }
202    }
203}
204
205impl FontWrite for MappingEntries {
206    fn write_into(&self, writer: &mut TableWriter) {
207        self.entry_data.write_into(writer);
208    }
209    fn table_type(&self) -> TableType {
210        TableType::Named("MappingEntries")
211    }
212}
213
214impl Validate for MappingEntries {
215    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
216}
217
218impl<'a> FromObjRef<read_fonts::tables::ift::MappingEntries<'a>> for MappingEntries {
219    fn from_obj_ref(obj: &read_fonts::tables::ift::MappingEntries<'a>, _: FontData) -> Self {
220        let offset_data = obj.offset_data();
221        MappingEntries {
222            entry_data: obj.entry_data().to_owned_obj(offset_data),
223        }
224    }
225}
226
227#[allow(clippy::needless_lifetimes)]
228impl<'a> FromTableRef<read_fonts::tables::ift::MappingEntries<'a>> for MappingEntries {}
229
230impl ReadArgs for MappingEntries {
231    type Args = ();
232}
233
234impl<'a> FontRead<'a> for MappingEntries {
235    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
236        <read_fonts::tables::ift::MappingEntries as FontRead>::read(data)
237            .map(|x| x.to_owned_table())
238    }
239}
240
241#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
242#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
243pub struct EntryData {
244    pub format_flags: EntryFormatFlags,
245    pub feature_count: Option<u8>,
246    pub feature_tags: Option<Vec<Tag>>,
247    pub design_space_count: Option<u16>,
248    pub design_space_segments: Option<Vec<DesignSpaceSegment>>,
249    pub child_indices: Option<Vec<Uint24>>,
250    pub trailing_data: Vec<u8>,
251}
252
253impl EntryData {
254    /// Construct a new `EntryData`
255    pub fn new(format_flags: EntryFormatFlags, trailing_data: Vec<u8>) -> Self {
256        Self {
257            format_flags,
258            trailing_data,
259            ..Default::default()
260        }
261    }
262}
263
264impl FontWrite for EntryData {
265    #[allow(clippy::unnecessary_cast)]
266    fn write_into(&self, writer: &mut TableWriter) {
267        self.format_flags.write_into(writer);
268        self.format_flags
269            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
270            .then(|| {
271                self.feature_count
272                    .as_ref()
273                    .expect("missing conditional field should have failed validation")
274                    .write_into(writer)
275            });
276        self.format_flags
277            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
278            .then(|| {
279                self.feature_tags
280                    .as_ref()
281                    .expect("missing conditional field should have failed validation")
282                    .write_into(writer)
283            });
284        self.format_flags
285            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
286            .then(|| {
287                self.design_space_count
288                    .as_ref()
289                    .expect("missing conditional field should have failed validation")
290                    .write_into(writer)
291            });
292        self.format_flags
293            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
294            .then(|| {
295                self.design_space_segments
296                    .as_ref()
297                    .expect("missing conditional field should have failed validation")
298                    .write_into(writer)
299            });
300        self.format_flags
301            .contains(EntryFormatFlags::CHILD_INDICES)
302            .then(|| {
303                self.child_indices
304                    .as_ref()
305                    .expect("missing conditional field should have failed validation")
306                    .write_into(writer)
307            });
308        self.trailing_data.write_into(writer);
309    }
310    fn table_type(&self) -> TableType {
311        TableType::Named("EntryData")
312    }
313}
314
315impl Validate for EntryData {
316    fn validate_impl(&self, ctx: &mut ValidationCtx) {
317        ctx.in_table("EntryData", |ctx| {
318            ctx.in_field("feature_count", |ctx| {
319                if !(self
320                    .format_flags
321                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
322                    && self.feature_count.is_some()
323                {
324                    ctx.report("'feature_count' is present but FEATURES_AND_DESIGN_SPACE not set")
325                }
326                if (self
327                    .format_flags
328                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
329                    && self.feature_count.is_none()
330                {
331                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'feature_count' is None")
332                }
333            });
334            ctx.in_field("feature_tags", |ctx| {
335                if !(self
336                    .format_flags
337                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
338                    && self.feature_tags.is_some()
339                {
340                    ctx.report("'feature_tags' is present but FEATURES_AND_DESIGN_SPACE not set")
341                }
342                if (self
343                    .format_flags
344                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
345                    && self.feature_tags.is_none()
346                {
347                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'feature_tags' is None")
348                }
349                if self.feature_tags.is_some()
350                    && self.feature_tags.as_ref().unwrap().len() > to_usize(u8::MAX)
351                {
352                    ctx.report("array exceeds max length");
353                }
354            });
355            ctx.in_field("design_space_count", |ctx| {
356                if !(self
357                    .format_flags
358                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
359                    && self.design_space_count.is_some()
360                {
361                    ctx.report(
362                        "'design_space_count' is present but FEATURES_AND_DESIGN_SPACE not set",
363                    )
364                }
365                if (self
366                    .format_flags
367                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
368                    && self.design_space_count.is_none()
369                {
370                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'design_space_count' is None")
371                }
372            });
373            ctx.in_field("design_space_segments", |ctx| {
374                if !(self
375                    .format_flags
376                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
377                    && self.design_space_segments.is_some()
378                {
379                    ctx.report(
380                        "'design_space_segments' is present but FEATURES_AND_DESIGN_SPACE not set",
381                    )
382                }
383                if (self
384                    .format_flags
385                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
386                    && self.design_space_segments.is_none()
387                {
388                    ctx.report(
389                        "FEATURES_AND_DESIGN_SPACE is set but 'design_space_segments' is None",
390                    )
391                }
392                if self.design_space_segments.is_some()
393                    && self.design_space_segments.as_ref().unwrap().len() > to_usize(u16::MAX)
394                {
395                    ctx.report("array exceeds max length");
396                }
397                self.design_space_segments.validate_impl(ctx);
398            });
399            ctx.in_field("child_indices", |ctx| {
400                if !(self.format_flags.contains(EntryFormatFlags::CHILD_INDICES))
401                    && self.child_indices.is_some()
402                {
403                    ctx.report("'child_indices' is present but CHILD_INDICES not set")
404                }
405                if (self.format_flags.contains(EntryFormatFlags::CHILD_INDICES))
406                    && self.child_indices.is_none()
407                {
408                    ctx.report("CHILD_INDICES is set but 'child_indices' is None")
409                }
410            });
411        })
412    }
413}
414
415impl<'a> FromObjRef<read_fonts::tables::ift::EntryData<'a>> for EntryData {
416    fn from_obj_ref(obj: &read_fonts::tables::ift::EntryData<'a>, _: FontData) -> Self {
417        let offset_data = obj.offset_data();
418        EntryData {
419            format_flags: obj.format_flags(),
420            feature_count: obj.feature_count(),
421            feature_tags: obj.feature_tags().to_owned_obj(offset_data),
422            design_space_count: obj.design_space_count(),
423            design_space_segments: obj.design_space_segments().to_owned_obj(offset_data),
424            child_indices: obj.child_indices().to_owned_obj(offset_data),
425            trailing_data: obj.trailing_data().to_owned_obj(offset_data),
426        }
427    }
428}
429
430#[allow(clippy::needless_lifetimes)]
431impl<'a> FromTableRef<read_fonts::tables::ift::EntryData<'a>> for EntryData {}
432
433impl ReadArgs for EntryData {
434    type Args = ();
435}
436
437impl<'a> FontRead<'a> for EntryData {
438    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
439        <read_fonts::tables::ift::EntryData as FontRead>::read(data).map(|x| x.to_owned_table())
440    }
441}
442
443impl FontWrite for EntryFormatFlags {
444    fn write_into(&self, writer: &mut TableWriter) {
445        writer.write_slice(&self.bits().to_be_bytes())
446    }
447}
448
449#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
450#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
451pub struct DesignSpaceSegment {
452    pub axis_tag: Tag,
453    pub start: Fixed,
454    pub end: Fixed,
455}
456
457impl DesignSpaceSegment {
458    /// Construct a new `DesignSpaceSegment`
459    pub fn new(axis_tag: Tag, start: Fixed, end: Fixed) -> Self {
460        Self {
461            axis_tag,
462            start,
463            end,
464        }
465    }
466}
467
468impl FontWrite for DesignSpaceSegment {
469    fn write_into(&self, writer: &mut TableWriter) {
470        self.axis_tag.write_into(writer);
471        self.start.write_into(writer);
472        self.end.write_into(writer);
473    }
474    fn table_type(&self) -> TableType {
475        TableType::Named("DesignSpaceSegment")
476    }
477}
478
479impl Validate for DesignSpaceSegment {
480    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
481}
482
483impl FromObjRef<read_fonts::tables::ift::DesignSpaceSegment> for DesignSpaceSegment {
484    fn from_obj_ref(obj: &read_fonts::tables::ift::DesignSpaceSegment, _: FontData) -> Self {
485        DesignSpaceSegment {
486            axis_tag: obj.axis_tag(),
487            start: obj.start(),
488            end: obj.end(),
489        }
490    }
491}
492
493#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
494#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
495pub struct IdStringData {
496    pub id_data: Vec<u8>,
497}
498
499impl IdStringData {
500    /// Construct a new `IdStringData`
501    pub fn new(id_data: Vec<u8>) -> Self {
502        Self { id_data }
503    }
504}
505
506impl FontWrite for IdStringData {
507    fn write_into(&self, writer: &mut TableWriter) {
508        self.id_data.write_into(writer);
509    }
510    fn table_type(&self) -> TableType {
511        TableType::Named("IdStringData")
512    }
513}
514
515impl Validate for IdStringData {
516    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
517}
518
519impl<'a> FromObjRef<read_fonts::tables::ift::IdStringData<'a>> for IdStringData {
520    fn from_obj_ref(obj: &read_fonts::tables::ift::IdStringData<'a>, _: FontData) -> Self {
521        let offset_data = obj.offset_data();
522        IdStringData {
523            id_data: obj.id_data().to_owned_obj(offset_data),
524        }
525    }
526}
527
528#[allow(clippy::needless_lifetimes)]
529impl<'a> FromTableRef<read_fonts::tables::ift::IdStringData<'a>> for IdStringData {}
530
531impl ReadArgs for IdStringData {
532    type Args = ();
533}
534
535impl<'a> FontRead<'a> for IdStringData {
536    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
537        <read_fonts::tables::ift::IdStringData as FontRead>::read(data).map(|x| x.to_owned_table())
538    }
539}
540
541/// [Table Keyed Patch](https://w3c.github.io/IFT/Overview.html#table-keyed)
542#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
543#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
544pub struct TableKeyedPatch {
545    pub format: Tag,
546    /// Unique ID that identifies compatible patches.
547    pub compatibility_id: CompatibilityId,
548    pub patches_count: u16,
549    pub patches: Vec<OffsetMarker<TablePatch, WIDTH_32>>,
550}
551
552impl TableKeyedPatch {
553    /// Construct a new `TableKeyedPatch`
554    pub fn new(
555        format: Tag,
556        compatibility_id: CompatibilityId,
557        patches_count: u16,
558        patches: Vec<TablePatch>,
559    ) -> Self {
560        Self {
561            format,
562            compatibility_id,
563            patches_count,
564            patches: patches.into_iter().map(Into::into).collect(),
565        }
566    }
567}
568
569impl FontWrite for TableKeyedPatch {
570    #[allow(clippy::unnecessary_cast)]
571    fn write_into(&self, writer: &mut TableWriter) {
572        self.format.write_into(writer);
573        (0 as u32).write_into(writer);
574        self.compatibility_id.write_into(writer);
575        self.patches_count.write_into(writer);
576        self.patches.write_into(writer);
577    }
578    fn table_type(&self) -> TableType {
579        TableType::Named("TableKeyedPatch")
580    }
581}
582
583impl Validate for TableKeyedPatch {
584    fn validate_impl(&self, ctx: &mut ValidationCtx) {
585        ctx.in_table("TableKeyedPatch", |ctx| {
586            ctx.in_field("patches", |ctx| {
587                self.patches.validate_impl(ctx);
588            });
589        })
590    }
591}
592
593impl<'a> FromObjRef<read_fonts::tables::ift::TableKeyedPatch<'a>> for TableKeyedPatch {
594    fn from_obj_ref(obj: &read_fonts::tables::ift::TableKeyedPatch<'a>, _: FontData) -> Self {
595        TableKeyedPatch {
596            format: obj.format(),
597            compatibility_id: obj.compatibility_id(),
598            patches_count: obj.patches_count(),
599            patches: obj.patches().to_owned_table(),
600        }
601    }
602}
603
604#[allow(clippy::needless_lifetimes)]
605impl<'a> FromTableRef<read_fonts::tables::ift::TableKeyedPatch<'a>> for TableKeyedPatch {}
606
607impl ReadArgs for TableKeyedPatch {
608    type Args = ();
609}
610
611impl<'a> FontRead<'a> for TableKeyedPatch {
612    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
613        <read_fonts::tables::ift::TableKeyedPatch as FontRead>::read(data)
614            .map(|x| x.to_owned_table())
615    }
616}
617
618/// [TablePatch](https://w3c.github.io/IFT/Overview.html#tablepatch)
619#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
620#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
621pub struct TablePatch {
622    pub tag: Tag,
623    pub flags: TablePatchFlags,
624    pub max_uncompressed_length: u32,
625    pub brotli_stream: Vec<u8>,
626}
627
628impl TablePatch {
629    /// Construct a new `TablePatch`
630    pub fn new(
631        tag: Tag,
632        flags: TablePatchFlags,
633        max_uncompressed_length: u32,
634        brotli_stream: Vec<u8>,
635    ) -> Self {
636        Self {
637            tag,
638            flags,
639            max_uncompressed_length,
640            brotli_stream,
641        }
642    }
643}
644
645impl FontWrite for TablePatch {
646    fn write_into(&self, writer: &mut TableWriter) {
647        self.tag.write_into(writer);
648        self.flags.write_into(writer);
649        self.max_uncompressed_length.write_into(writer);
650        self.brotli_stream.write_into(writer);
651    }
652    fn table_type(&self) -> TableType {
653        TableType::Named("TablePatch")
654    }
655}
656
657impl Validate for TablePatch {
658    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
659}
660
661impl<'a> FromObjRef<read_fonts::tables::ift::TablePatch<'a>> for TablePatch {
662    fn from_obj_ref(obj: &read_fonts::tables::ift::TablePatch<'a>, _: FontData) -> Self {
663        let offset_data = obj.offset_data();
664        TablePatch {
665            tag: obj.tag(),
666            flags: obj.flags(),
667            max_uncompressed_length: obj.max_uncompressed_length(),
668            brotli_stream: obj.brotli_stream().to_owned_obj(offset_data),
669        }
670    }
671}
672
673#[allow(clippy::needless_lifetimes)]
674impl<'a> FromTableRef<read_fonts::tables::ift::TablePatch<'a>> for TablePatch {}
675
676impl ReadArgs for TablePatch {
677    type Args = ();
678}
679
680impl<'a> FontRead<'a> for TablePatch {
681    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
682        <read_fonts::tables::ift::TablePatch as FontRead>::read(data).map(|x| x.to_owned_table())
683    }
684}
685
686impl FontWrite for TablePatchFlags {
687    fn write_into(&self, writer: &mut TableWriter) {
688        writer.write_slice(&self.bits().to_be_bytes())
689    }
690}
691
692/// [Glyph Keyed Patch](https://w3c.github.io/IFT/Overview.html#glyph-keyed)
693#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
694#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
695pub struct GlyphKeyedPatch {
696    pub format: Tag,
697    pub flags: GlyphKeyedFlags,
698    pub compatibility_id: CompatibilityId,
699    pub max_uncompressed_length: u32,
700    pub brotli_stream: Vec<u8>,
701}
702
703impl GlyphKeyedPatch {
704    /// Construct a new `GlyphKeyedPatch`
705    pub fn new(
706        format: Tag,
707        flags: GlyphKeyedFlags,
708        compatibility_id: CompatibilityId,
709        max_uncompressed_length: u32,
710        brotli_stream: Vec<u8>,
711    ) -> Self {
712        Self {
713            format,
714            flags,
715            compatibility_id,
716            max_uncompressed_length,
717            brotli_stream,
718        }
719    }
720}
721
722impl FontWrite for GlyphKeyedPatch {
723    #[allow(clippy::unnecessary_cast)]
724    fn write_into(&self, writer: &mut TableWriter) {
725        self.format.write_into(writer);
726        (0 as u32).write_into(writer);
727        self.flags.write_into(writer);
728        self.compatibility_id.write_into(writer);
729        self.max_uncompressed_length.write_into(writer);
730        self.brotli_stream.write_into(writer);
731    }
732    fn table_type(&self) -> TableType {
733        TableType::Named("GlyphKeyedPatch")
734    }
735}
736
737impl Validate for GlyphKeyedPatch {
738    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
739}
740
741impl<'a> FromObjRef<read_fonts::tables::ift::GlyphKeyedPatch<'a>> for GlyphKeyedPatch {
742    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphKeyedPatch<'a>, _: FontData) -> Self {
743        let offset_data = obj.offset_data();
744        GlyphKeyedPatch {
745            format: obj.format(),
746            flags: obj.flags(),
747            compatibility_id: obj.compatibility_id(),
748            max_uncompressed_length: obj.max_uncompressed_length(),
749            brotli_stream: obj.brotli_stream().to_owned_obj(offset_data),
750        }
751    }
752}
753
754#[allow(clippy::needless_lifetimes)]
755impl<'a> FromTableRef<read_fonts::tables::ift::GlyphKeyedPatch<'a>> for GlyphKeyedPatch {}
756
757impl ReadArgs for GlyphKeyedPatch {
758    type Args = ();
759}
760
761impl<'a> FontRead<'a> for GlyphKeyedPatch {
762    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
763        <read_fonts::tables::ift::GlyphKeyedPatch as FontRead>::read(data)
764            .map(|x| x.to_owned_table())
765    }
766}
767
768impl FontWrite for GlyphKeyedFlags {
769    fn write_into(&self, writer: &mut TableWriter) {
770        writer.write_slice(&self.bits().to_be_bytes())
771    }
772}
773
774/// [GlyphPatches](https://w3c.github.io/IFT/Overview.html#glyphpatches)
775#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
776#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
777pub struct GlyphPatches {
778    pub glyph_count: u32,
779    pub table_count: u8,
780    pub tables: Vec<Tag>,
781    pub glyph_data: Vec<OffsetMarker<GlyphData, WIDTH_32>>,
782}
783
784impl GlyphPatches {
785    /// Construct a new `GlyphPatches`
786    pub fn new(
787        glyph_count: u32,
788        table_count: u8,
789        tables: Vec<Tag>,
790        glyph_data: Vec<GlyphData>,
791    ) -> Self {
792        Self {
793            glyph_count,
794            table_count,
795            tables,
796            glyph_data: glyph_data.into_iter().map(Into::into).collect(),
797        }
798    }
799}
800
801impl FontWrite for GlyphPatches {
802    #[allow(clippy::unnecessary_cast)]
803    fn write_into(&self, writer: &mut TableWriter) {
804        self.glyph_count.write_into(writer);
805        self.table_count.write_into(writer);
806        self.tables.write_into(writer);
807        self.glyph_data.write_into(writer);
808    }
809    fn table_type(&self) -> TableType {
810        TableType::Named("GlyphPatches")
811    }
812}
813
814impl Validate for GlyphPatches {
815    fn validate_impl(&self, ctx: &mut ValidationCtx) {
816        ctx.in_table("GlyphPatches", |ctx| {
817            ctx.in_field("tables", |ctx| {
818                if self.tables.len() > to_usize(u8::MAX) {
819                    ctx.report("array exceeds max length");
820                }
821            });
822            ctx.in_field("glyph_data", |ctx| {
823                self.glyph_data.validate_impl(ctx);
824            });
825        })
826    }
827}
828
829impl<'a> FromObjRef<read_fonts::tables::ift::GlyphPatches<'a>> for GlyphPatches {
830    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphPatches<'a>, _: FontData) -> Self {
831        let offset_data = obj.offset_data();
832        GlyphPatches {
833            glyph_count: obj.glyph_count(),
834            table_count: obj.table_count(),
835            tables: obj.tables().to_owned_obj(offset_data),
836            glyph_data: obj.glyph_data().to_owned_table(),
837        }
838    }
839}
840
841#[allow(clippy::needless_lifetimes)]
842impl<'a> FromTableRef<read_fonts::tables::ift::GlyphPatches<'a>> for GlyphPatches {}
843
844#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
845#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
846pub struct GlyphData {
847    pub data: Vec<u8>,
848}
849
850impl GlyphData {
851    /// Construct a new `GlyphData`
852    pub fn new(data: Vec<u8>) -> Self {
853        Self { data }
854    }
855}
856
857impl FontWrite for GlyphData {
858    fn write_into(&self, writer: &mut TableWriter) {
859        self.data.write_into(writer);
860    }
861    fn table_type(&self) -> TableType {
862        TableType::Named("GlyphData")
863    }
864}
865
866impl Validate for GlyphData {
867    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
868}
869
870impl<'a> FromObjRef<read_fonts::tables::ift::GlyphData<'a>> for GlyphData {
871    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphData<'a>, _: FontData) -> Self {
872        let offset_data = obj.offset_data();
873        GlyphData {
874            data: obj.data().to_owned_obj(offset_data),
875        }
876    }
877}
878
879#[allow(clippy::needless_lifetimes)]
880impl<'a> FromTableRef<read_fonts::tables::ift::GlyphData<'a>> for GlyphData {}
881
882impl ReadArgs for GlyphData {
883    type Args = ();
884}
885
886impl<'a> FontRead<'a> for GlyphData {
887    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
888        <read_fonts::tables::ift::GlyphData as FontRead>::read(data).map(|x| x.to_owned_table())
889    }
890}