1use crate::{
2 tables::{Table, TableDirectory, TableError},
3 types::{BigEndian, Tag, Version16Dot16, tags, uint16},
4};
5
6#[repr(C)]
7pub struct MaxpV0 {
8 _exhaustive_but_dont_instantiate: (),
9 pub version: BigEndian<Version16Dot16>,
11}
12#[repr(C)]
13pub struct MaxpV05 {
14 v0: MaxpV0,
15 pub num_glyphs: uint16,
17}
18#[repr(C)]
19pub struct MaxpV1 {
20 v05: MaxpV05,
21 pub max_points: uint16,
23 pub max_contours: uint16,
24 pub max_composite_points: uint16,
25 pub max_composite_contours: uint16,
26 pub max_zones: uint16,
27 pub max_twilight_points: uint16,
28 pub max_storage: uint16,
29 pub max_function_defs: uint16,
30 pub max_instruction_defs: uint16,
31 pub max_stack_elements: uint16,
32 pub max_size_of_instructions: uint16,
33 pub max_component_elements: uint16,
34 pub max_component_depth: uint16,
35}
36
37const impl std::ops::Deref for MaxpV05 {
38 type Target = MaxpV0;
39 fn deref(&self) -> &Self::Target {
40 &self.v0
41 }
42}
43const impl std::ops::Deref for MaxpV1 {
44 type Target = MaxpV05;
45 fn deref(&self) -> &Self::Target {
46 &self.v05
47 }
48}
49
50impl<'a> Table<'a> for Maxp<'a> {
51 const TAG: Tag = tags::maxp;
52 fn new_in(dir: &'a TableDirectory) -> Result<Self, TableError> {
53 let rec = dir.table_record(Self::TAG).ok_or(TableError::NotFound)?;
54 let v0 = rec.raw_as::<MaxpV0>().ok_or(TableError::InvalidLen)?;
55
56 let required_len = match v0.version.get().tuple() {
57 (0, ..=4) => size_of::<MaxpV0>() as u32,
58 (0, 5..) => size_of::<MaxpV05>() as u32,
59 (1, _) => size_of::<MaxpV1>() as u32,
60 _ => return Err(TableError::UnknownVersion),
61 };
62 if rec.length.get() < required_len {
63 return Err(TableError::InvalidLen);
64 }
65
66 Ok(Self { maxp: v0 })
67 }
68}
69
70#[derive(Copy)]
71#[derive_const(Clone)]
72pub struct Maxp<'a> {
73 maxp: &'a MaxpV0,
74}
75
76const impl<'a> std::ops::Deref for Maxp<'a> {
77 type Target = &'a MaxpV0;
78 fn deref(&self) -> &Self::Target {
79 &self.maxp
80 }
81}
82
83impl<'a> Maxp<'a> {
84 pub const fn v05(&self) -> Option<&'a MaxpV05> {
85 let (major, minor) = self.version.get().tuple();
86 if major == 0 && minor >= 5 || major == 1 {
87 Some(unsafe { std::mem::transmute::<&MaxpV0, &MaxpV05>(self.maxp) })
88 } else {
89 None
90 }
91 }
92 pub const fn v1(&self) -> Option<&'a MaxpV1> {
93 if self.version.get().major() == 1 {
94 Some(unsafe { std::mem::transmute::<&MaxpV0, &MaxpV1>(self.maxp) })
95 } else {
96 None
97 }
98 }
99
100 pub const fn num_glyphs(&self) -> Option<uint16> {
102 Some(self.v05()?.num_glyphs)
103 }
104
105 pub const fn max_points(&self) -> Option<uint16> {
107 Some(self.v1()?.max_points)
108 }
109 pub const fn max_contours(&self) -> Option<uint16> {
110 Some(self.v1()?.max_contours)
111 }
112 pub const fn max_composite_points(&self) -> Option<uint16> {
113 Some(self.v1()?.max_composite_points)
114 }
115 pub const fn max_composite_contours(&self) -> Option<uint16> {
116 Some(self.v1()?.max_composite_contours)
117 }
118 pub const fn max_zones(&self) -> Option<uint16> {
119 Some(self.v1()?.max_zones)
120 }
121 pub const fn max_twilight_points(&self) -> Option<uint16> {
122 Some(self.v1()?.max_twilight_points)
123 }
124 pub const fn max_storage(&self) -> Option<uint16> {
125 Some(self.v1()?.max_storage)
126 }
127 pub const fn max_function_defs(&self) -> Option<uint16> {
128 Some(self.v1()?.max_function_defs)
129 }
130 pub const fn max_instruction_defs(&self) -> Option<uint16> {
131 Some(self.v1()?.max_instruction_defs)
132 }
133 pub const fn max_stack_elements(&self) -> Option<uint16> {
134 Some(self.v1()?.max_stack_elements)
135 }
136 pub const fn max_size_of_instructions(&self) -> Option<uint16> {
137 Some(self.v1()?.max_size_of_instructions)
138 }
139 pub const fn max_component_elements(&self) -> Option<uint16> {
140 Some(self.v1()?.max_component_elements)
141 }
142 pub const fn max_component_depth(&self) -> Option<uint16> {
143 Some(self.v1()?.max_component_depth)
144 }
145}
146
147impl std::fmt::Debug for Maxp<'_> {
148 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
149 let mut f = f.debug_struct("MaxpTable");
150 f.field("version", &self.version);
151
152 if let Some(v05) = self.v05() {
153 f.field("num_glyphs", &v05.num_glyphs.get());
154 }
155 if let Some(v1) = self.v1() {
156 f.field("max_points", &v1.max_points.get());
157 f.field("max_contours", &v1.max_contours.get());
158 f.field("max_composite_points", &v1.max_composite_points.get());
159 f.field("max_composite_contours", &v1.max_composite_contours.get());
160 f.field("max_zones", &v1.max_zones.get());
161 f.field("max_twilight_points", &v1.max_twilight_points.get());
162 f.field("max_storage", &v1.max_storage.get());
163 f.field("max_function_defs", &v1.max_function_defs.get());
164 f.field("max_instruction_defs", &v1.max_instruction_defs.get());
165 f.field("max_stack_elements", &v1.max_stack_elements.get());
166 f.field("max_size_of_instructions", &v1.max_size_of_instructions.get());
167 f.field("max_component_elements", &v1.max_component_elements.get());
168 f.field("max_component_depth", &v1.max_component_depth.get());
169 }
170
171 f.finish()
172 }
173}
174
175impl std::fmt::Debug for MaxpV0 {
177 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
178 Maxp { maxp: self }.fmt(f)
179 }
180}
181impl std::fmt::Debug for MaxpV05 {
182 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
183 Maxp { maxp: self }.fmt(f)
184 }
185}
186impl std::fmt::Debug for MaxpV1 {
187 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
188 Maxp { maxp: self }.fmt(f)
189 }
190}