1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8pub use read_fonts::tables::stat::AxisValueTableFlags;
9
10#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Stat {
14 pub design_axes: OffsetMarker<Vec<AxisRecord>, WIDTH_32>,
19 pub offset_to_axis_values: NullableOffsetMarker<Vec<OffsetMarker<AxisValue>>, WIDTH_32>,
24 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#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
102pub struct AxisRecord {
103 pub axis_tag: Tag,
105 pub axis_name_id: NameId,
108 pub axis_ordering: u16,
112}
113
114impl AxisRecord {
115 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#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
152#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
153pub struct AxisValueArray {
154 pub axis_values: Vec<OffsetMarker<AxisValue>>,
157}
158
159impl AxisValueArray {
160 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#[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 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 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 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 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#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
359#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
360pub struct AxisValueFormat1 {
361 pub axis_index: u16,
365 pub flags: AxisValueTableFlags,
367 pub value_name_id: NameId,
370 pub value: Fixed,
372}
373
374impl AxisValueFormat1 {
375 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#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
436#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
437pub struct AxisValueFormat2 {
438 pub axis_index: u16,
442 pub flags: AxisValueTableFlags,
444 pub value_name_id: NameId,
447 pub nominal_value: Fixed,
449 pub range_min_value: Fixed,
452 pub range_max_value: Fixed,
455}
456
457impl AxisValueFormat2 {
458 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#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
527#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
528pub struct AxisValueFormat3 {
529 pub axis_index: u16,
533 pub flags: AxisValueTableFlags,
535 pub value_name_id: NameId,
538 pub value: Fixed,
540 pub linked_value: Fixed,
542}
543
544impl AxisValueFormat3 {
545 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#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
610#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
611pub struct AxisValueFormat4 {
612 pub flags: AxisValueTableFlags,
614 pub value_name_id: NameId,
617 pub axis_values: Vec<AxisValueRecord>,
620}
621
622impl AxisValueFormat4 {
623 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#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
691#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
692pub struct AxisValueRecord {
693 pub axis_index: u16,
696 pub value: Fixed,
698}
699
700impl AxisValueRecord {
701 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}