Skip to main content

write_fonts/generated/
generated_stat.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::stat::AxisValueTableFlags;
9
10/// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table)
11#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Stat {
14    /// Offset in bytes from the beginning of the STAT table to the
15    /// start of the design axes array. If designAxisCount is zero, set
16    /// to zero; if designAxisCount is greater than zero, must be
17    /// greater than zero.
18    pub design_axes: OffsetMarker<Vec<AxisRecord>, WIDTH_32>,
19    /// Offset in bytes from the beginning of the STAT table to the
20    /// start of the design axes value offsets array. If axisValueCount
21    /// is zero, set to zero; if axisValueCount is greater than zero,
22    /// must be greater than zero.
23    pub offset_to_axis_values: NullableOffsetMarker<Vec<OffsetMarker<AxisValue>>, WIDTH_32>,
24    /// Name ID used as fallback when projection of names into a
25    /// particular font model produces a subfamily name containing only
26    /// elidable elements.
27    pub elided_fallback_name_id: Option<NameId>,
28}
29
30impl FontWrite for Stat {
31    #[allow(clippy::unnecessary_cast)]
32    fn write_into(&self, writer: &mut TableWriter) {
33        let version = MajorMinor::VERSION_1_2 as MajorMinor;
34        version.write_into(writer);
35        (8 as u16).write_into(writer);
36        (u16::try_from(array_len(&self.design_axes)).unwrap()).write_into(writer);
37        self.design_axes.write_into(writer);
38        (u16::try_from(array_len(&self.offset_to_axis_values)).unwrap()).write_into(writer);
39        self.offset_to_axis_values.write_into(writer);
40        version.compatible((1u16, 1u16)).then(|| {
41            self.elided_fallback_name_id
42                .as_ref()
43                .expect("missing conditional field should have failed validation")
44                .write_into(writer)
45        });
46    }
47    fn table_type(&self) -> TableType {
48        TableType::TopLevel(Stat::TAG)
49    }
50}
51
52impl Validate for Stat {
53    fn validate_impl(&self, ctx: &mut ValidationCtx) {
54        ctx.in_table("Stat", |ctx| {
55            let version: MajorMinor = MajorMinor::VERSION_1_2;
56            ctx.in_field("design_axes", |ctx| {
57                self.design_axes.validate_impl(ctx);
58            });
59            ctx.in_field("offset_to_axis_values", |ctx| {
60                self.offset_to_axis_values.validate_impl(ctx);
61            });
62            ctx.in_field("elided_fallback_name_id", |ctx| {
63                if version.compatible((1u16, 1u16)) && self.elided_fallback_name_id.is_none() {
64                    ctx.report(format!("field must be present for version {version}"));
65                }
66            });
67        })
68    }
69}
70
71impl TopLevelTable for Stat {
72    const TAG: Tag = Tag::new(b"STAT");
73}
74
75impl<'a> FromObjRef<read_fonts::tables::stat::Stat<'a>> for Stat {
76    fn from_obj_ref(obj: &read_fonts::tables::stat::Stat<'a>, _: FontData) -> Self {
77        let offset_data = obj.offset_data();
78        Stat {
79            design_axes: obj.design_axes().to_owned_obj(offset_data),
80            offset_to_axis_values: convert_axis_value_offsets(obj.offset_to_axis_values()),
81            elided_fallback_name_id: obj.elided_fallback_name_id(),
82        }
83    }
84}
85
86#[allow(clippy::needless_lifetimes)]
87impl<'a> FromTableRef<read_fonts::tables::stat::Stat<'a>> for Stat {}
88
89impl ReadArgs for Stat {
90    type Args = ();
91}
92
93impl<'a> FontRead<'a> for Stat {
94    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
95        <read_fonts::tables::stat::Stat as FontRead>::read(data).map(|x| x.to_owned_table())
96    }
97}
98
99/// [Axis Records](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-records)
100#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
102pub struct AxisRecord {
103    /// A tag identifying the axis of design variation.
104    pub axis_tag: Tag,
105    /// The name ID for entries in the 'name' table that provide a
106    /// display string for this axis.
107    pub axis_name_id: NameId,
108    /// A value that applications can use to determine primary sorting
109    /// of face names, or for ordering of labels when composing family
110    /// or face names.
111    pub axis_ordering: u16,
112}
113
114impl AxisRecord {
115    /// Construct a new `AxisRecord`
116    pub fn new(axis_tag: Tag, axis_name_id: NameId, axis_ordering: u16) -> Self {
117        Self {
118            axis_tag,
119            axis_name_id,
120            axis_ordering,
121        }
122    }
123}
124
125impl FontWrite for AxisRecord {
126    fn write_into(&self, writer: &mut TableWriter) {
127        self.axis_tag.write_into(writer);
128        self.axis_name_id.write_into(writer);
129        self.axis_ordering.write_into(writer);
130    }
131    fn table_type(&self) -> TableType {
132        TableType::Named("AxisRecord")
133    }
134}
135
136impl Validate for AxisRecord {
137    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
138}
139
140impl FromObjRef<read_fonts::tables::stat::AxisRecord> for AxisRecord {
141    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisRecord, _: FontData) -> Self {
142        AxisRecord {
143            axis_tag: obj.axis_tag(),
144            axis_name_id: obj.axis_name_id(),
145            axis_ordering: obj.axis_ordering(),
146        }
147    }
148}
149
150/// An array of [AxisValue] tables.
151#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
152#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
153pub struct AxisValueArray {
154    /// Array of offsets to axis value tables, in bytes from the start
155    /// of the axis value offsets array.
156    pub axis_values: Vec<OffsetMarker<AxisValue>>,
157}
158
159impl AxisValueArray {
160    /// Construct a new `AxisValueArray`
161    pub fn new(axis_values: Vec<AxisValue>) -> Self {
162        Self {
163            axis_values: axis_values.into_iter().map(Into::into).collect(),
164        }
165    }
166}
167
168impl FontWrite for AxisValueArray {
169    fn write_into(&self, writer: &mut TableWriter) {
170        self.axis_values.write_into(writer);
171    }
172    fn table_type(&self) -> TableType {
173        TableType::Named("AxisValueArray")
174    }
175}
176
177impl Validate for AxisValueArray {
178    fn validate_impl(&self, ctx: &mut ValidationCtx) {
179        ctx.in_table("AxisValueArray", |ctx| {
180            ctx.in_field("axis_values", |ctx| {
181                if self.axis_values.len() > to_usize(u16::MAX) {
182                    ctx.report("array exceeds max length");
183                }
184                self.axis_values.validate_impl(ctx);
185            });
186        })
187    }
188}
189
190impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueArray<'a>> for AxisValueArray {
191    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueArray<'a>, _: FontData) -> Self {
192        AxisValueArray {
193            axis_values: obj.axis_values().to_owned_table(),
194        }
195    }
196}
197
198#[allow(clippy::needless_lifetimes)]
199impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueArray<'a>> for AxisValueArray {}
200
201/// [Axis Value Tables](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-tables)
202#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
203#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
204pub enum AxisValue {
205    Format1(AxisValueFormat1),
206    Format2(AxisValueFormat2),
207    Format3(AxisValueFormat3),
208    Format4(AxisValueFormat4),
209}
210
211impl AxisValue {
212    /// Construct a new `AxisValueFormat1` subtable
213    pub fn format_1(
214        axis_index: u16,
215        flags: AxisValueTableFlags,
216        value_name_id: NameId,
217        value: Fixed,
218    ) -> Self {
219        Self::Format1(AxisValueFormat1::new(
220            axis_index,
221            flags,
222            value_name_id,
223            value,
224        ))
225    }
226
227    /// Construct a new `AxisValueFormat2` subtable
228    pub fn format_2(
229        axis_index: u16,
230        flags: AxisValueTableFlags,
231        value_name_id: NameId,
232        nominal_value: Fixed,
233        range_min_value: Fixed,
234        range_max_value: Fixed,
235    ) -> Self {
236        Self::Format2(AxisValueFormat2::new(
237            axis_index,
238            flags,
239            value_name_id,
240            nominal_value,
241            range_min_value,
242            range_max_value,
243        ))
244    }
245
246    /// Construct a new `AxisValueFormat3` subtable
247    pub fn format_3(
248        axis_index: u16,
249        flags: AxisValueTableFlags,
250        value_name_id: NameId,
251        value: Fixed,
252        linked_value: Fixed,
253    ) -> Self {
254        Self::Format3(AxisValueFormat3::new(
255            axis_index,
256            flags,
257            value_name_id,
258            value,
259            linked_value,
260        ))
261    }
262
263    /// Construct a new `AxisValueFormat4` subtable
264    pub fn format_4(
265        flags: AxisValueTableFlags,
266        value_name_id: NameId,
267        axis_values: Vec<AxisValueRecord>,
268    ) -> Self {
269        Self::Format4(AxisValueFormat4::new(flags, value_name_id, axis_values))
270    }
271}
272
273impl Default for AxisValue {
274    fn default() -> Self {
275        Self::Format1(Default::default())
276    }
277}
278
279impl FontWrite for AxisValue {
280    fn write_into(&self, writer: &mut TableWriter) {
281        match self {
282            Self::Format1(item) => item.write_into(writer),
283            Self::Format2(item) => item.write_into(writer),
284            Self::Format3(item) => item.write_into(writer),
285            Self::Format4(item) => item.write_into(writer),
286        }
287    }
288    fn table_type(&self) -> TableType {
289        match self {
290            Self::Format1(item) => item.table_type(),
291            Self::Format2(item) => item.table_type(),
292            Self::Format3(item) => item.table_type(),
293            Self::Format4(item) => item.table_type(),
294        }
295    }
296}
297
298impl Validate for AxisValue {
299    fn validate_impl(&self, ctx: &mut ValidationCtx) {
300        match self {
301            Self::Format1(item) => item.validate_impl(ctx),
302            Self::Format2(item) => item.validate_impl(ctx),
303            Self::Format3(item) => item.validate_impl(ctx),
304            Self::Format4(item) => item.validate_impl(ctx),
305        }
306    }
307}
308
309impl FromObjRef<read_fonts::tables::stat::AxisValue<'_>> for AxisValue {
310    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValue, _: FontData) -> Self {
311        use read_fonts::tables::stat::AxisValue as ObjRefType;
312        match obj {
313            ObjRefType::Format1(item) => AxisValue::Format1(item.to_owned_table()),
314            ObjRefType::Format2(item) => AxisValue::Format2(item.to_owned_table()),
315            ObjRefType::Format3(item) => AxisValue::Format3(item.to_owned_table()),
316            ObjRefType::Format4(item) => AxisValue::Format4(item.to_owned_table()),
317        }
318    }
319}
320
321impl FromTableRef<read_fonts::tables::stat::AxisValue<'_>> for AxisValue {}
322
323impl ReadArgs for AxisValue {
324    type Args = ();
325}
326
327impl<'a> FontRead<'a> for AxisValue {
328    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
329        <read_fonts::tables::stat::AxisValue as FontRead>::read(data).map(|x| x.to_owned_table())
330    }
331}
332
333impl From<AxisValueFormat1> for AxisValue {
334    fn from(src: AxisValueFormat1) -> AxisValue {
335        AxisValue::Format1(src)
336    }
337}
338
339impl From<AxisValueFormat2> for AxisValue {
340    fn from(src: AxisValueFormat2) -> AxisValue {
341        AxisValue::Format2(src)
342    }
343}
344
345impl From<AxisValueFormat3> for AxisValue {
346    fn from(src: AxisValueFormat3) -> AxisValue {
347        AxisValue::Format3(src)
348    }
349}
350
351impl From<AxisValueFormat4> for AxisValue {
352    fn from(src: AxisValueFormat4) -> AxisValue {
353        AxisValue::Format4(src)
354    }
355}
356
357/// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1)
358#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
359#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
360pub struct AxisValueFormat1 {
361    /// Zero-base index into the axis record array identifying the axis
362    /// of design variation to which the axis value table applies. Must
363    /// be less than designAxisCount.
364    pub axis_index: u16,
365    /// Flags — see below for details.
366    pub flags: AxisValueTableFlags,
367    /// The name ID for entries in the 'name' table that provide a
368    /// display string for this attribute value.
369    pub value_name_id: NameId,
370    /// A numeric value for this attribute value.
371    pub value: Fixed,
372}
373
374impl AxisValueFormat1 {
375    /// Construct a new `AxisValueFormat1`
376    pub fn new(
377        axis_index: u16,
378        flags: AxisValueTableFlags,
379        value_name_id: NameId,
380        value: Fixed,
381    ) -> Self {
382        Self {
383            axis_index,
384            flags,
385            value_name_id,
386            value,
387        }
388    }
389}
390
391impl FontWrite for AxisValueFormat1 {
392    #[allow(clippy::unnecessary_cast)]
393    fn write_into(&self, writer: &mut TableWriter) {
394        (1 as u16).write_into(writer);
395        self.axis_index.write_into(writer);
396        self.flags.write_into(writer);
397        self.value_name_id.write_into(writer);
398        self.value.write_into(writer);
399    }
400    fn table_type(&self) -> TableType {
401        TableType::Named("AxisValueFormat1")
402    }
403}
404
405impl Validate for AxisValueFormat1 {
406    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
407}
408
409impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat1<'a>> for AxisValueFormat1 {
410    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat1<'a>, _: FontData) -> Self {
411        AxisValueFormat1 {
412            axis_index: obj.axis_index(),
413            flags: obj.flags(),
414            value_name_id: obj.value_name_id(),
415            value: obj.value(),
416        }
417    }
418}
419
420#[allow(clippy::needless_lifetimes)]
421impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat1<'a>> for AxisValueFormat1 {}
422
423impl ReadArgs for AxisValueFormat1 {
424    type Args = ();
425}
426
427impl<'a> FontRead<'a> for AxisValueFormat1 {
428    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
429        <read_fonts::tables::stat::AxisValueFormat1 as FontRead>::read(data)
430            .map(|x| x.to_owned_table())
431    }
432}
433
434/// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2)
435#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
436#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
437pub struct AxisValueFormat2 {
438    /// Zero-base index into the axis record array identifying the axis
439    /// of design variation to which the axis value table applies. Must
440    /// be less than designAxisCount.
441    pub axis_index: u16,
442    /// Flags — see below for details.
443    pub flags: AxisValueTableFlags,
444    /// The name ID for entries in the 'name' table that provide a
445    /// display string for this attribute value.
446    pub value_name_id: NameId,
447    /// A nominal numeric value for this attribute value.
448    pub nominal_value: Fixed,
449    /// The minimum value for a range associated with the specified
450    /// name ID.
451    pub range_min_value: Fixed,
452    /// The maximum value for a range associated with the specified
453    /// name ID.
454    pub range_max_value: Fixed,
455}
456
457impl AxisValueFormat2 {
458    /// Construct a new `AxisValueFormat2`
459    pub fn new(
460        axis_index: u16,
461        flags: AxisValueTableFlags,
462        value_name_id: NameId,
463        nominal_value: Fixed,
464        range_min_value: Fixed,
465        range_max_value: Fixed,
466    ) -> Self {
467        Self {
468            axis_index,
469            flags,
470            value_name_id,
471            nominal_value,
472            range_min_value,
473            range_max_value,
474        }
475    }
476}
477
478impl FontWrite for AxisValueFormat2 {
479    #[allow(clippy::unnecessary_cast)]
480    fn write_into(&self, writer: &mut TableWriter) {
481        (2 as u16).write_into(writer);
482        self.axis_index.write_into(writer);
483        self.flags.write_into(writer);
484        self.value_name_id.write_into(writer);
485        self.nominal_value.write_into(writer);
486        self.range_min_value.write_into(writer);
487        self.range_max_value.write_into(writer);
488    }
489    fn table_type(&self) -> TableType {
490        TableType::Named("AxisValueFormat2")
491    }
492}
493
494impl Validate for AxisValueFormat2 {
495    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
496}
497
498impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat2<'a>> for AxisValueFormat2 {
499    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat2<'a>, _: FontData) -> Self {
500        AxisValueFormat2 {
501            axis_index: obj.axis_index(),
502            flags: obj.flags(),
503            value_name_id: obj.value_name_id(),
504            nominal_value: obj.nominal_value(),
505            range_min_value: obj.range_min_value(),
506            range_max_value: obj.range_max_value(),
507        }
508    }
509}
510
511#[allow(clippy::needless_lifetimes)]
512impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat2<'a>> for AxisValueFormat2 {}
513
514impl ReadArgs for AxisValueFormat2 {
515    type Args = ();
516}
517
518impl<'a> FontRead<'a> for AxisValueFormat2 {
519    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
520        <read_fonts::tables::stat::AxisValueFormat2 as FontRead>::read(data)
521            .map(|x| x.to_owned_table())
522    }
523}
524
525/// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3)
526#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
527#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
528pub struct AxisValueFormat3 {
529    /// Zero-base index into the axis record array identifying the axis
530    /// of design variation to which the axis value table applies. Must
531    /// be less than designAxisCount.
532    pub axis_index: u16,
533    /// Flags — see below for details.
534    pub flags: AxisValueTableFlags,
535    /// The name ID for entries in the 'name' table that provide a
536    /// display string for this attribute value.
537    pub value_name_id: NameId,
538    /// A numeric value for this attribute value.
539    pub value: Fixed,
540    /// The numeric value for a style-linked mapping from this value.
541    pub linked_value: Fixed,
542}
543
544impl AxisValueFormat3 {
545    /// Construct a new `AxisValueFormat3`
546    pub fn new(
547        axis_index: u16,
548        flags: AxisValueTableFlags,
549        value_name_id: NameId,
550        value: Fixed,
551        linked_value: Fixed,
552    ) -> Self {
553        Self {
554            axis_index,
555            flags,
556            value_name_id,
557            value,
558            linked_value,
559        }
560    }
561}
562
563impl FontWrite for AxisValueFormat3 {
564    #[allow(clippy::unnecessary_cast)]
565    fn write_into(&self, writer: &mut TableWriter) {
566        (3 as u16).write_into(writer);
567        self.axis_index.write_into(writer);
568        self.flags.write_into(writer);
569        self.value_name_id.write_into(writer);
570        self.value.write_into(writer);
571        self.linked_value.write_into(writer);
572    }
573    fn table_type(&self) -> TableType {
574        TableType::Named("AxisValueFormat3")
575    }
576}
577
578impl Validate for AxisValueFormat3 {
579    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
580}
581
582impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat3<'a>> for AxisValueFormat3 {
583    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat3<'a>, _: FontData) -> Self {
584        AxisValueFormat3 {
585            axis_index: obj.axis_index(),
586            flags: obj.flags(),
587            value_name_id: obj.value_name_id(),
588            value: obj.value(),
589            linked_value: obj.linked_value(),
590        }
591    }
592}
593
594#[allow(clippy::needless_lifetimes)]
595impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat3<'a>> for AxisValueFormat3 {}
596
597impl ReadArgs for AxisValueFormat3 {
598    type Args = ();
599}
600
601impl<'a> FontRead<'a> for AxisValueFormat3 {
602    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
603        <read_fonts::tables::stat::AxisValueFormat3 as FontRead>::read(data)
604            .map(|x| x.to_owned_table())
605    }
606}
607
608/// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4)
609#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
610#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
611pub struct AxisValueFormat4 {
612    /// Flags — see below for details.
613    pub flags: AxisValueTableFlags,
614    /// The name ID for entries in the 'name' table that provide a
615    /// display string for this combination of axis values.
616    pub value_name_id: NameId,
617    /// Array of AxisValue records that provide the combination of axis
618    /// values, one for each contributing axis.
619    pub axis_values: Vec<AxisValueRecord>,
620}
621
622impl AxisValueFormat4 {
623    /// Construct a new `AxisValueFormat4`
624    pub fn new(
625        flags: AxisValueTableFlags,
626        value_name_id: NameId,
627        axis_values: Vec<AxisValueRecord>,
628    ) -> Self {
629        Self {
630            flags,
631            value_name_id,
632            axis_values,
633        }
634    }
635}
636
637impl FontWrite for AxisValueFormat4 {
638    #[allow(clippy::unnecessary_cast)]
639    fn write_into(&self, writer: &mut TableWriter) {
640        (4 as u16).write_into(writer);
641        (u16::try_from(array_len(&self.axis_values)).unwrap()).write_into(writer);
642        self.flags.write_into(writer);
643        self.value_name_id.write_into(writer);
644        self.axis_values.write_into(writer);
645    }
646    fn table_type(&self) -> TableType {
647        TableType::Named("AxisValueFormat4")
648    }
649}
650
651impl Validate for AxisValueFormat4 {
652    fn validate_impl(&self, ctx: &mut ValidationCtx) {
653        ctx.in_table("AxisValueFormat4", |ctx| {
654            ctx.in_field("axis_values", |ctx| {
655                if self.axis_values.len() > to_usize(u16::MAX) {
656                    ctx.report("array exceeds max length");
657                }
658                self.axis_values.validate_impl(ctx);
659            });
660        })
661    }
662}
663
664impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat4<'a>> for AxisValueFormat4 {
665    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat4<'a>, _: FontData) -> Self {
666        let offset_data = obj.offset_data();
667        AxisValueFormat4 {
668            flags: obj.flags(),
669            value_name_id: obj.value_name_id(),
670            axis_values: obj.axis_values().to_owned_obj(offset_data),
671        }
672    }
673}
674
675#[allow(clippy::needless_lifetimes)]
676impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat4<'a>> for AxisValueFormat4 {}
677
678impl ReadArgs for AxisValueFormat4 {
679    type Args = ();
680}
681
682impl<'a> FontRead<'a> for AxisValueFormat4 {
683    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
684        <read_fonts::tables::stat::AxisValueFormat4 as FontRead>::read(data)
685            .map(|x| x.to_owned_table())
686    }
687}
688
689/// Part of [AxisValueFormat4]
690#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
691#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
692pub struct AxisValueRecord {
693    /// Zero-base index into the axis record array identifying the axis
694    /// to which this value applies. Must be less than designAxisCount.
695    pub axis_index: u16,
696    /// A numeric value for this attribute value.
697    pub value: Fixed,
698}
699
700impl AxisValueRecord {
701    /// Construct a new `AxisValueRecord`
702    pub fn new(axis_index: u16, value: Fixed) -> Self {
703        Self { axis_index, value }
704    }
705}
706
707impl FontWrite for AxisValueRecord {
708    fn write_into(&self, writer: &mut TableWriter) {
709        self.axis_index.write_into(writer);
710        self.value.write_into(writer);
711    }
712    fn table_type(&self) -> TableType {
713        TableType::Named("AxisValueRecord")
714    }
715}
716
717impl Validate for AxisValueRecord {
718    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
719}
720
721impl FromObjRef<read_fonts::tables::stat::AxisValueRecord> for AxisValueRecord {
722    fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueRecord, _: FontData) -> Self {
723        AxisValueRecord {
724            axis_index: obj.axis_index(),
725            value: obj.value(),
726        }
727    }
728}
729
730impl FontWrite for AxisValueTableFlags {
731    fn write_into(&self, writer: &mut TableWriter) {
732        writer.write_slice(&self.bits().to_be_bytes())
733    }
734}