1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct FvarMarker {}
12
13impl FvarMarker {
14 pub fn version_byte_range(&self) -> Range<usize> {
15 let start = 0;
16 start..start + MajorMinor::RAW_BYTE_LEN
17 }
18
19 pub fn axis_instance_arrays_offset_byte_range(&self) -> Range<usize> {
20 let start = self.version_byte_range().end;
21 start..start + Offset16::RAW_BYTE_LEN
22 }
23
24 pub fn _reserved_byte_range(&self) -> Range<usize> {
25 let start = self.axis_instance_arrays_offset_byte_range().end;
26 start..start + u16::RAW_BYTE_LEN
27 }
28
29 pub fn axis_count_byte_range(&self) -> Range<usize> {
30 let start = self._reserved_byte_range().end;
31 start..start + u16::RAW_BYTE_LEN
32 }
33
34 pub fn axis_size_byte_range(&self) -> Range<usize> {
35 let start = self.axis_count_byte_range().end;
36 start..start + u16::RAW_BYTE_LEN
37 }
38
39 pub fn instance_count_byte_range(&self) -> Range<usize> {
40 let start = self.axis_size_byte_range().end;
41 start..start + u16::RAW_BYTE_LEN
42 }
43
44 pub fn instance_size_byte_range(&self) -> Range<usize> {
45 let start = self.instance_count_byte_range().end;
46 start..start + u16::RAW_BYTE_LEN
47 }
48}
49
50impl MinByteRange for FvarMarker {
51 fn min_byte_range(&self) -> Range<usize> {
52 0..self.instance_size_byte_range().end
53 }
54}
55
56impl TopLevelTable for Fvar<'_> {
57 const TAG: Tag = Tag::new(b"fvar");
59}
60
61impl<'a> FontRead<'a> for Fvar<'a> {
62 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
63 let mut cursor = data.cursor();
64 cursor.advance::<MajorMinor>();
65 cursor.advance::<Offset16>();
66 cursor.advance::<u16>();
67 cursor.advance::<u16>();
68 cursor.advance::<u16>();
69 cursor.advance::<u16>();
70 cursor.advance::<u16>();
71 cursor.finish(FvarMarker {})
72 }
73}
74
75pub type Fvar<'a> = TableRef<'a, FvarMarker>;
77
78#[allow(clippy::needless_lifetimes)]
79impl<'a> Fvar<'a> {
80 pub fn version(&self) -> MajorMinor {
83 let range = self.shape.version_byte_range();
84 self.data.read_at(range.start).unwrap()
85 }
86
87 pub fn axis_instance_arrays_offset(&self) -> Offset16 {
90 let range = self.shape.axis_instance_arrays_offset_byte_range();
91 self.data.read_at(range.start).unwrap()
92 }
93
94 pub fn axis_instance_arrays(&self) -> Result<AxisInstanceArrays<'a>, ReadError> {
96 let data = self.data;
97 let args = (
98 self.axis_count(),
99 self.instance_count(),
100 self.instance_size(),
101 );
102 self.axis_instance_arrays_offset()
103 .resolve_with_args(data, &args)
104 }
105
106 pub fn axis_count(&self) -> u16 {
108 let range = self.shape.axis_count_byte_range();
109 self.data.read_at(range.start).unwrap()
110 }
111
112 pub fn axis_size(&self) -> u16 {
114 let range = self.shape.axis_size_byte_range();
115 self.data.read_at(range.start).unwrap()
116 }
117
118 pub fn instance_count(&self) -> u16 {
120 let range = self.shape.instance_count_byte_range();
121 self.data.read_at(range.start).unwrap()
122 }
123
124 pub fn instance_size(&self) -> u16 {
126 let range = self.shape.instance_size_byte_range();
127 self.data.read_at(range.start).unwrap()
128 }
129}
130
131#[cfg(feature = "experimental_traverse")]
132impl<'a> SomeTable<'a> for Fvar<'a> {
133 fn type_name(&self) -> &str {
134 "Fvar"
135 }
136 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
137 match idx {
138 0usize => Some(Field::new("version", self.version())),
139 1usize => Some(Field::new(
140 "axis_instance_arrays_offset",
141 FieldType::offset(
142 self.axis_instance_arrays_offset(),
143 self.axis_instance_arrays(),
144 ),
145 )),
146 2usize => Some(Field::new("axis_count", self.axis_count())),
147 3usize => Some(Field::new("axis_size", self.axis_size())),
148 4usize => Some(Field::new("instance_count", self.instance_count())),
149 5usize => Some(Field::new("instance_size", self.instance_size())),
150 _ => None,
151 }
152 }
153}
154
155#[cfg(feature = "experimental_traverse")]
156#[allow(clippy::needless_lifetimes)]
157impl<'a> std::fmt::Debug for Fvar<'a> {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 (self as &dyn SomeTable<'a>).fmt(f)
160 }
161}
162
163#[derive(Debug, Clone, Copy)]
165#[doc(hidden)]
166pub struct AxisInstanceArraysMarker {
167 axis_count: u16,
168 instance_size: u16,
169 axes_byte_len: usize,
170 instances_byte_len: usize,
171}
172
173impl AxisInstanceArraysMarker {
174 pub fn axes_byte_range(&self) -> Range<usize> {
175 let start = 0;
176 start..start + self.axes_byte_len
177 }
178
179 pub fn instances_byte_range(&self) -> Range<usize> {
180 let start = self.axes_byte_range().end;
181 start..start + self.instances_byte_len
182 }
183}
184
185impl MinByteRange for AxisInstanceArraysMarker {
186 fn min_byte_range(&self) -> Range<usize> {
187 0..self.instances_byte_range().end
188 }
189}
190
191impl ReadArgs for AxisInstanceArrays<'_> {
192 type Args = (u16, u16, u16);
193}
194
195impl<'a> FontReadWithArgs<'a> for AxisInstanceArrays<'a> {
196 fn read_with_args(data: FontData<'a>, args: &(u16, u16, u16)) -> Result<Self, ReadError> {
197 let (axis_count, instance_count, instance_size) = *args;
198 let mut cursor = data.cursor();
199 let axes_byte_len = (axis_count as usize)
200 .checked_mul(VariationAxisRecord::RAW_BYTE_LEN)
201 .ok_or(ReadError::OutOfBounds)?;
202 cursor.advance_by(axes_byte_len);
203 let instances_byte_len = (instance_count as usize)
204 .checked_mul(<InstanceRecord as ComputeSize>::compute_size(&(
205 axis_count,
206 instance_size,
207 ))?)
208 .ok_or(ReadError::OutOfBounds)?;
209 cursor.advance_by(instances_byte_len);
210 cursor.finish(AxisInstanceArraysMarker {
211 axis_count,
212 instance_size,
213 axes_byte_len,
214 instances_byte_len,
215 })
216 }
217}
218
219impl<'a> AxisInstanceArrays<'a> {
220 pub fn read(
225 data: FontData<'a>,
226 axis_count: u16,
227 instance_count: u16,
228 instance_size: u16,
229 ) -> Result<Self, ReadError> {
230 let args = (axis_count, instance_count, instance_size);
231 Self::read_with_args(data, &args)
232 }
233}
234
235pub type AxisInstanceArrays<'a> = TableRef<'a, AxisInstanceArraysMarker>;
237
238#[allow(clippy::needless_lifetimes)]
239impl<'a> AxisInstanceArrays<'a> {
240 pub fn axes(&self) -> &'a [VariationAxisRecord] {
242 let range = self.shape.axes_byte_range();
243 self.data.read_array(range).unwrap()
244 }
245
246 pub fn instances(&self) -> ComputedArray<'a, InstanceRecord<'a>> {
248 let range = self.shape.instances_byte_range();
249 self.data
250 .read_with_args(range, &(self.axis_count(), self.instance_size()))
251 .unwrap()
252 }
253
254 pub(crate) fn axis_count(&self) -> u16 {
255 self.shape.axis_count
256 }
257
258 pub(crate) fn instance_size(&self) -> u16 {
259 self.shape.instance_size
260 }
261}
262
263#[cfg(feature = "experimental_traverse")]
264impl<'a> SomeTable<'a> for AxisInstanceArrays<'a> {
265 fn type_name(&self) -> &str {
266 "AxisInstanceArrays"
267 }
268 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
269 match idx {
270 0usize => Some(Field::new(
271 "axes",
272 traversal::FieldType::array_of_records(
273 stringify!(VariationAxisRecord),
274 self.axes(),
275 self.offset_data(),
276 ),
277 )),
278 1usize => Some(Field::new(
279 "instances",
280 traversal::FieldType::computed_array(
281 "InstanceRecord",
282 self.instances(),
283 self.offset_data(),
284 ),
285 )),
286 _ => None,
287 }
288 }
289}
290
291#[cfg(feature = "experimental_traverse")]
292#[allow(clippy::needless_lifetimes)]
293impl<'a> std::fmt::Debug for AxisInstanceArrays<'a> {
294 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
295 (self as &dyn SomeTable<'a>).fmt(f)
296 }
297}
298
299#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
301#[repr(C)]
302#[repr(packed)]
303pub struct VariationAxisRecord {
304 pub axis_tag: BigEndian<Tag>,
306 pub min_value: BigEndian<Fixed>,
308 pub default_value: BigEndian<Fixed>,
310 pub max_value: BigEndian<Fixed>,
312 pub flags: BigEndian<u16>,
314 pub axis_name_id: BigEndian<NameId>,
316}
317
318impl VariationAxisRecord {
319 pub fn axis_tag(&self) -> Tag {
321 self.axis_tag.get()
322 }
323
324 pub fn min_value(&self) -> Fixed {
326 self.min_value.get()
327 }
328
329 pub fn default_value(&self) -> Fixed {
331 self.default_value.get()
332 }
333
334 pub fn max_value(&self) -> Fixed {
336 self.max_value.get()
337 }
338
339 pub fn flags(&self) -> u16 {
341 self.flags.get()
342 }
343
344 pub fn axis_name_id(&self) -> NameId {
346 self.axis_name_id.get()
347 }
348}
349
350impl FixedSize for VariationAxisRecord {
351 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN
352 + Fixed::RAW_BYTE_LEN
353 + Fixed::RAW_BYTE_LEN
354 + Fixed::RAW_BYTE_LEN
355 + u16::RAW_BYTE_LEN
356 + NameId::RAW_BYTE_LEN;
357}
358
359#[cfg(feature = "experimental_traverse")]
360impl<'a> SomeRecord<'a> for VariationAxisRecord {
361 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
362 RecordResolver {
363 name: "VariationAxisRecord",
364 get_field: Box::new(move |idx, _data| match idx {
365 0usize => Some(Field::new("axis_tag", self.axis_tag())),
366 1usize => Some(Field::new("min_value", self.min_value())),
367 2usize => Some(Field::new("default_value", self.default_value())),
368 3usize => Some(Field::new("max_value", self.max_value())),
369 4usize => Some(Field::new("flags", self.flags())),
370 5usize => Some(Field::new("axis_name_id", self.axis_name_id())),
371 _ => None,
372 }),
373 data,
374 }
375 }
376}