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<'a> FontRead<'a> for Stat {
90 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
91 <read_fonts::tables::stat::Stat as FontRead>::read(data).map(|x| x.to_owned_table())
92 }
93}
94
95#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
97#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
98pub struct AxisRecord {
99 pub axis_tag: Tag,
101 pub axis_name_id: NameId,
104 pub axis_ordering: u16,
108}
109
110impl AxisRecord {
111 pub fn new(axis_tag: Tag, axis_name_id: NameId, axis_ordering: u16) -> Self {
113 Self {
114 axis_tag,
115 axis_name_id,
116 axis_ordering,
117 }
118 }
119}
120
121impl FontWrite for AxisRecord {
122 fn write_into(&self, writer: &mut TableWriter) {
123 self.axis_tag.write_into(writer);
124 self.axis_name_id.write_into(writer);
125 self.axis_ordering.write_into(writer);
126 }
127 fn table_type(&self) -> TableType {
128 TableType::Named("AxisRecord")
129 }
130}
131
132impl Validate for AxisRecord {
133 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
134}
135
136impl FromObjRef<read_fonts::tables::stat::AxisRecord> for AxisRecord {
137 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisRecord, _: FontData) -> Self {
138 AxisRecord {
139 axis_tag: obj.axis_tag(),
140 axis_name_id: obj.axis_name_id(),
141 axis_ordering: obj.axis_ordering(),
142 }
143 }
144}
145
146#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
148#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
149pub struct AxisValueArray {
150 pub axis_values: Vec<OffsetMarker<AxisValue>>,
153}
154
155impl AxisValueArray {
156 pub fn new(axis_values: Vec<AxisValue>) -> Self {
158 Self {
159 axis_values: axis_values.into_iter().map(Into::into).collect(),
160 }
161 }
162}
163
164impl FontWrite for AxisValueArray {
165 fn write_into(&self, writer: &mut TableWriter) {
166 self.axis_values.write_into(writer);
167 }
168 fn table_type(&self) -> TableType {
169 TableType::Named("AxisValueArray")
170 }
171}
172
173impl Validate for AxisValueArray {
174 fn validate_impl(&self, ctx: &mut ValidationCtx) {
175 ctx.in_table("AxisValueArray", |ctx| {
176 ctx.in_field("axis_values", |ctx| {
177 if self.axis_values.len() > (u16::MAX as usize) {
178 ctx.report("array exceeds max length");
179 }
180 self.axis_values.validate_impl(ctx);
181 });
182 })
183 }
184}
185
186impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueArray<'a>> for AxisValueArray {
187 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueArray<'a>, _: FontData) -> Self {
188 AxisValueArray {
189 axis_values: obj.axis_values().to_owned_table(),
190 }
191 }
192}
193
194#[allow(clippy::needless_lifetimes)]
195impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueArray<'a>> for AxisValueArray {}
196
197#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
199#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
200pub enum AxisValue {
201 Format1(AxisValueFormat1),
202 Format2(AxisValueFormat2),
203 Format3(AxisValueFormat3),
204 Format4(AxisValueFormat4),
205}
206
207impl AxisValue {
208 pub fn format_1(
210 axis_index: u16,
211 flags: AxisValueTableFlags,
212 value_name_id: NameId,
213 value: Fixed,
214 ) -> Self {
215 Self::Format1(AxisValueFormat1::new(
216 axis_index,
217 flags,
218 value_name_id,
219 value,
220 ))
221 }
222
223 pub fn format_2(
225 axis_index: u16,
226 flags: AxisValueTableFlags,
227 value_name_id: NameId,
228 nominal_value: Fixed,
229 range_min_value: Fixed,
230 range_max_value: Fixed,
231 ) -> Self {
232 Self::Format2(AxisValueFormat2::new(
233 axis_index,
234 flags,
235 value_name_id,
236 nominal_value,
237 range_min_value,
238 range_max_value,
239 ))
240 }
241
242 pub fn format_3(
244 axis_index: u16,
245 flags: AxisValueTableFlags,
246 value_name_id: NameId,
247 value: Fixed,
248 linked_value: Fixed,
249 ) -> Self {
250 Self::Format3(AxisValueFormat3::new(
251 axis_index,
252 flags,
253 value_name_id,
254 value,
255 linked_value,
256 ))
257 }
258
259 pub fn format_4(
261 flags: AxisValueTableFlags,
262 value_name_id: NameId,
263 axis_values: Vec<AxisValueRecord>,
264 ) -> Self {
265 Self::Format4(AxisValueFormat4::new(flags, value_name_id, axis_values))
266 }
267}
268
269impl Default for AxisValue {
270 fn default() -> Self {
271 Self::Format1(Default::default())
272 }
273}
274
275impl FontWrite for AxisValue {
276 fn write_into(&self, writer: &mut TableWriter) {
277 match self {
278 Self::Format1(item) => item.write_into(writer),
279 Self::Format2(item) => item.write_into(writer),
280 Self::Format3(item) => item.write_into(writer),
281 Self::Format4(item) => item.write_into(writer),
282 }
283 }
284 fn table_type(&self) -> TableType {
285 match self {
286 Self::Format1(item) => item.table_type(),
287 Self::Format2(item) => item.table_type(),
288 Self::Format3(item) => item.table_type(),
289 Self::Format4(item) => item.table_type(),
290 }
291 }
292}
293
294impl Validate for AxisValue {
295 fn validate_impl(&self, ctx: &mut ValidationCtx) {
296 match self {
297 Self::Format1(item) => item.validate_impl(ctx),
298 Self::Format2(item) => item.validate_impl(ctx),
299 Self::Format3(item) => item.validate_impl(ctx),
300 Self::Format4(item) => item.validate_impl(ctx),
301 }
302 }
303}
304
305impl FromObjRef<read_fonts::tables::stat::AxisValue<'_>> for AxisValue {
306 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValue, _: FontData) -> Self {
307 use read_fonts::tables::stat::AxisValue as ObjRefType;
308 match obj {
309 ObjRefType::Format1(item) => AxisValue::Format1(item.to_owned_table()),
310 ObjRefType::Format2(item) => AxisValue::Format2(item.to_owned_table()),
311 ObjRefType::Format3(item) => AxisValue::Format3(item.to_owned_table()),
312 ObjRefType::Format4(item) => AxisValue::Format4(item.to_owned_table()),
313 }
314 }
315}
316
317impl FromTableRef<read_fonts::tables::stat::AxisValue<'_>> for AxisValue {}
318
319impl<'a> FontRead<'a> for AxisValue {
320 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
321 <read_fonts::tables::stat::AxisValue as FontRead>::read(data).map(|x| x.to_owned_table())
322 }
323}
324
325impl From<AxisValueFormat1> for AxisValue {
326 fn from(src: AxisValueFormat1) -> AxisValue {
327 AxisValue::Format1(src)
328 }
329}
330
331impl From<AxisValueFormat2> for AxisValue {
332 fn from(src: AxisValueFormat2) -> AxisValue {
333 AxisValue::Format2(src)
334 }
335}
336
337impl From<AxisValueFormat3> for AxisValue {
338 fn from(src: AxisValueFormat3) -> AxisValue {
339 AxisValue::Format3(src)
340 }
341}
342
343impl From<AxisValueFormat4> for AxisValue {
344 fn from(src: AxisValueFormat4) -> AxisValue {
345 AxisValue::Format4(src)
346 }
347}
348
349#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
351#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
352pub struct AxisValueFormat1 {
353 pub axis_index: u16,
357 pub flags: AxisValueTableFlags,
359 pub value_name_id: NameId,
362 pub value: Fixed,
364}
365
366impl AxisValueFormat1 {
367 pub fn new(
369 axis_index: u16,
370 flags: AxisValueTableFlags,
371 value_name_id: NameId,
372 value: Fixed,
373 ) -> Self {
374 Self {
375 axis_index,
376 flags,
377 value_name_id,
378 value,
379 }
380 }
381}
382
383impl FontWrite for AxisValueFormat1 {
384 #[allow(clippy::unnecessary_cast)]
385 fn write_into(&self, writer: &mut TableWriter) {
386 (1 as u16).write_into(writer);
387 self.axis_index.write_into(writer);
388 self.flags.write_into(writer);
389 self.value_name_id.write_into(writer);
390 self.value.write_into(writer);
391 }
392 fn table_type(&self) -> TableType {
393 TableType::Named("AxisValueFormat1")
394 }
395}
396
397impl Validate for AxisValueFormat1 {
398 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
399}
400
401impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat1<'a>> for AxisValueFormat1 {
402 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat1<'a>, _: FontData) -> Self {
403 AxisValueFormat1 {
404 axis_index: obj.axis_index(),
405 flags: obj.flags(),
406 value_name_id: obj.value_name_id(),
407 value: obj.value(),
408 }
409 }
410}
411
412#[allow(clippy::needless_lifetimes)]
413impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat1<'a>> for AxisValueFormat1 {}
414
415impl<'a> FontRead<'a> for AxisValueFormat1 {
416 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
417 <read_fonts::tables::stat::AxisValueFormat1 as FontRead>::read(data)
418 .map(|x| x.to_owned_table())
419 }
420}
421
422#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
424#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
425pub struct AxisValueFormat2 {
426 pub axis_index: u16,
430 pub flags: AxisValueTableFlags,
432 pub value_name_id: NameId,
435 pub nominal_value: Fixed,
437 pub range_min_value: Fixed,
440 pub range_max_value: Fixed,
443}
444
445impl AxisValueFormat2 {
446 pub fn new(
448 axis_index: u16,
449 flags: AxisValueTableFlags,
450 value_name_id: NameId,
451 nominal_value: Fixed,
452 range_min_value: Fixed,
453 range_max_value: Fixed,
454 ) -> Self {
455 Self {
456 axis_index,
457 flags,
458 value_name_id,
459 nominal_value,
460 range_min_value,
461 range_max_value,
462 }
463 }
464}
465
466impl FontWrite for AxisValueFormat2 {
467 #[allow(clippy::unnecessary_cast)]
468 fn write_into(&self, writer: &mut TableWriter) {
469 (2 as u16).write_into(writer);
470 self.axis_index.write_into(writer);
471 self.flags.write_into(writer);
472 self.value_name_id.write_into(writer);
473 self.nominal_value.write_into(writer);
474 self.range_min_value.write_into(writer);
475 self.range_max_value.write_into(writer);
476 }
477 fn table_type(&self) -> TableType {
478 TableType::Named("AxisValueFormat2")
479 }
480}
481
482impl Validate for AxisValueFormat2 {
483 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
484}
485
486impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat2<'a>> for AxisValueFormat2 {
487 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat2<'a>, _: FontData) -> Self {
488 AxisValueFormat2 {
489 axis_index: obj.axis_index(),
490 flags: obj.flags(),
491 value_name_id: obj.value_name_id(),
492 nominal_value: obj.nominal_value(),
493 range_min_value: obj.range_min_value(),
494 range_max_value: obj.range_max_value(),
495 }
496 }
497}
498
499#[allow(clippy::needless_lifetimes)]
500impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat2<'a>> for AxisValueFormat2 {}
501
502impl<'a> FontRead<'a> for AxisValueFormat2 {
503 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
504 <read_fonts::tables::stat::AxisValueFormat2 as FontRead>::read(data)
505 .map(|x| x.to_owned_table())
506 }
507}
508
509#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
511#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
512pub struct AxisValueFormat3 {
513 pub axis_index: u16,
517 pub flags: AxisValueTableFlags,
519 pub value_name_id: NameId,
522 pub value: Fixed,
524 pub linked_value: Fixed,
526}
527
528impl AxisValueFormat3 {
529 pub fn new(
531 axis_index: u16,
532 flags: AxisValueTableFlags,
533 value_name_id: NameId,
534 value: Fixed,
535 linked_value: Fixed,
536 ) -> Self {
537 Self {
538 axis_index,
539 flags,
540 value_name_id,
541 value,
542 linked_value,
543 }
544 }
545}
546
547impl FontWrite for AxisValueFormat3 {
548 #[allow(clippy::unnecessary_cast)]
549 fn write_into(&self, writer: &mut TableWriter) {
550 (3 as u16).write_into(writer);
551 self.axis_index.write_into(writer);
552 self.flags.write_into(writer);
553 self.value_name_id.write_into(writer);
554 self.value.write_into(writer);
555 self.linked_value.write_into(writer);
556 }
557 fn table_type(&self) -> TableType {
558 TableType::Named("AxisValueFormat3")
559 }
560}
561
562impl Validate for AxisValueFormat3 {
563 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
564}
565
566impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat3<'a>> for AxisValueFormat3 {
567 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat3<'a>, _: FontData) -> Self {
568 AxisValueFormat3 {
569 axis_index: obj.axis_index(),
570 flags: obj.flags(),
571 value_name_id: obj.value_name_id(),
572 value: obj.value(),
573 linked_value: obj.linked_value(),
574 }
575 }
576}
577
578#[allow(clippy::needless_lifetimes)]
579impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat3<'a>> for AxisValueFormat3 {}
580
581impl<'a> FontRead<'a> for AxisValueFormat3 {
582 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
583 <read_fonts::tables::stat::AxisValueFormat3 as FontRead>::read(data)
584 .map(|x| x.to_owned_table())
585 }
586}
587
588#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
590#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
591pub struct AxisValueFormat4 {
592 pub flags: AxisValueTableFlags,
594 pub value_name_id: NameId,
597 pub axis_values: Vec<AxisValueRecord>,
600}
601
602impl AxisValueFormat4 {
603 pub fn new(
605 flags: AxisValueTableFlags,
606 value_name_id: NameId,
607 axis_values: Vec<AxisValueRecord>,
608 ) -> Self {
609 Self {
610 flags,
611 value_name_id,
612 axis_values,
613 }
614 }
615}
616
617impl FontWrite for AxisValueFormat4 {
618 #[allow(clippy::unnecessary_cast)]
619 fn write_into(&self, writer: &mut TableWriter) {
620 (4 as u16).write_into(writer);
621 (u16::try_from(array_len(&self.axis_values)).unwrap()).write_into(writer);
622 self.flags.write_into(writer);
623 self.value_name_id.write_into(writer);
624 self.axis_values.write_into(writer);
625 }
626 fn table_type(&self) -> TableType {
627 TableType::Named("AxisValueFormat4")
628 }
629}
630
631impl Validate for AxisValueFormat4 {
632 fn validate_impl(&self, ctx: &mut ValidationCtx) {
633 ctx.in_table("AxisValueFormat4", |ctx| {
634 ctx.in_field("axis_values", |ctx| {
635 if self.axis_values.len() > (u16::MAX as usize) {
636 ctx.report("array exceeds max length");
637 }
638 self.axis_values.validate_impl(ctx);
639 });
640 })
641 }
642}
643
644impl<'a> FromObjRef<read_fonts::tables::stat::AxisValueFormat4<'a>> for AxisValueFormat4 {
645 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueFormat4<'a>, _: FontData) -> Self {
646 let offset_data = obj.offset_data();
647 AxisValueFormat4 {
648 flags: obj.flags(),
649 value_name_id: obj.value_name_id(),
650 axis_values: obj.axis_values().to_owned_obj(offset_data),
651 }
652 }
653}
654
655#[allow(clippy::needless_lifetimes)]
656impl<'a> FromTableRef<read_fonts::tables::stat::AxisValueFormat4<'a>> for AxisValueFormat4 {}
657
658impl<'a> FontRead<'a> for AxisValueFormat4 {
659 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
660 <read_fonts::tables::stat::AxisValueFormat4 as FontRead>::read(data)
661 .map(|x| x.to_owned_table())
662 }
663}
664
665#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
667#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
668pub struct AxisValueRecord {
669 pub axis_index: u16,
672 pub value: Fixed,
674}
675
676impl AxisValueRecord {
677 pub fn new(axis_index: u16, value: Fixed) -> Self {
679 Self { axis_index, value }
680 }
681}
682
683impl FontWrite for AxisValueRecord {
684 fn write_into(&self, writer: &mut TableWriter) {
685 self.axis_index.write_into(writer);
686 self.value.write_into(writer);
687 }
688 fn table_type(&self) -> TableType {
689 TableType::Named("AxisValueRecord")
690 }
691}
692
693impl Validate for AxisValueRecord {
694 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
695}
696
697impl FromObjRef<read_fonts::tables::stat::AxisValueRecord> for AxisValueRecord {
698 fn from_obj_ref(obj: &read_fonts::tables::stat::AxisValueRecord, _: FontData) -> Self {
699 AxisValueRecord {
700 axis_index: obj.axis_index(),
701 value: obj.value(),
702 }
703 }
704}
705
706impl FontWrite for AxisValueTableFlags {
707 fn write_into(&self, writer: &mut TableWriter) {
708 writer.write_slice(&self.bits().to_be_bytes())
709 }
710}