/src/fontations/read-fonts/generated/generated_stat.rs
Line | Count | Source |
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)] |
6 | | use crate::codegen_prelude::*; |
7 | | |
8 | | /// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table) |
9 | | #[derive(Debug, Clone, Copy)] |
10 | | #[doc(hidden)] |
11 | | pub struct StatMarker { |
12 | | elided_fallback_name_id_byte_start: Option<usize>, |
13 | | } |
14 | | |
15 | | impl StatMarker { |
16 | | pub fn version_byte_range(&self) -> Range<usize> { |
17 | | let start = 0; |
18 | | start..start + MajorMinor::RAW_BYTE_LEN |
19 | | } |
20 | | |
21 | | pub fn design_axis_size_byte_range(&self) -> Range<usize> { |
22 | | let start = self.version_byte_range().end; |
23 | | start..start + u16::RAW_BYTE_LEN |
24 | | } |
25 | | |
26 | | pub fn design_axis_count_byte_range(&self) -> Range<usize> { |
27 | | let start = self.design_axis_size_byte_range().end; |
28 | | start..start + u16::RAW_BYTE_LEN |
29 | | } |
30 | | |
31 | | pub fn design_axes_offset_byte_range(&self) -> Range<usize> { |
32 | | let start = self.design_axis_count_byte_range().end; |
33 | | start..start + Offset32::RAW_BYTE_LEN |
34 | | } |
35 | | |
36 | | pub fn axis_value_count_byte_range(&self) -> Range<usize> { |
37 | | let start = self.design_axes_offset_byte_range().end; |
38 | | start..start + u16::RAW_BYTE_LEN |
39 | | } |
40 | | |
41 | | pub fn offset_to_axis_value_offsets_byte_range(&self) -> Range<usize> { |
42 | | let start = self.axis_value_count_byte_range().end; |
43 | | start..start + Offset32::RAW_BYTE_LEN |
44 | | } |
45 | | |
46 | | pub fn elided_fallback_name_id_byte_range(&self) -> Option<Range<usize>> { |
47 | | let start = self.elided_fallback_name_id_byte_start?; |
48 | | Some(start..start + NameId::RAW_BYTE_LEN) |
49 | | } |
50 | | } |
51 | | |
52 | | impl MinByteRange for StatMarker { |
53 | | fn min_byte_range(&self) -> Range<usize> { |
54 | | 0..self.offset_to_axis_value_offsets_byte_range().end |
55 | | } |
56 | | } |
57 | | |
58 | | impl TopLevelTable for Stat<'_> { |
59 | | /// `STAT` |
60 | | const TAG: Tag = Tag::new(b"STAT"); |
61 | | } |
62 | | |
63 | | impl<'a> FontRead<'a> for Stat<'a> { |
64 | | fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
65 | | let mut cursor = data.cursor(); |
66 | | let version: MajorMinor = cursor.read()?; |
67 | | cursor.advance::<u16>(); |
68 | | cursor.advance::<u16>(); |
69 | | cursor.advance::<Offset32>(); |
70 | | cursor.advance::<u16>(); |
71 | | cursor.advance::<Offset32>(); |
72 | | let elided_fallback_name_id_byte_start = version |
73 | | .compatible((1u16, 1u16)) |
74 | | .then(|| cursor.position()) |
75 | | .transpose()?; |
76 | | version |
77 | | .compatible((1u16, 1u16)) |
78 | | .then(|| cursor.advance::<NameId>()); |
79 | | cursor.finish(StatMarker { |
80 | | elided_fallback_name_id_byte_start, |
81 | | }) |
82 | | } |
83 | | } |
84 | | |
85 | | /// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table) |
86 | | pub type Stat<'a> = TableRef<'a, StatMarker>; |
87 | | |
88 | | #[allow(clippy::needless_lifetimes)] |
89 | | impl<'a> Stat<'a> { |
90 | | /// Major/minor version number. Set to 1.2 for new fonts. |
91 | | pub fn version(&self) -> MajorMinor { |
92 | | let range = self.shape.version_byte_range(); |
93 | | self.data.read_at(range.start).unwrap() |
94 | | } |
95 | | |
96 | | /// The size in bytes of each axis record. |
97 | | pub fn design_axis_size(&self) -> u16 { |
98 | | let range = self.shape.design_axis_size_byte_range(); |
99 | | self.data.read_at(range.start).unwrap() |
100 | | } |
101 | | |
102 | | /// The number of axis records. In a font with an 'fvar' table, |
103 | | /// this value must be greater than or equal to the axisCount value |
104 | | /// in the 'fvar' table. In all fonts, must be greater than zero if |
105 | | /// axisValueCount is greater than zero. |
106 | | pub fn design_axis_count(&self) -> u16 { |
107 | | let range = self.shape.design_axis_count_byte_range(); |
108 | | self.data.read_at(range.start).unwrap() |
109 | | } |
110 | | |
111 | | /// Offset in bytes from the beginning of the STAT table to the |
112 | | /// start of the design axes array. If designAxisCount is zero, set |
113 | | /// to zero; if designAxisCount is greater than zero, must be |
114 | | /// greater than zero. |
115 | | pub fn design_axes_offset(&self) -> Offset32 { |
116 | | let range = self.shape.design_axes_offset_byte_range(); |
117 | | self.data.read_at(range.start).unwrap() |
118 | | } |
119 | | |
120 | | /// Attempt to resolve [`design_axes_offset`][Self::design_axes_offset]. |
121 | | pub fn design_axes(&self) -> Result<&'a [AxisRecord], ReadError> { |
122 | | let data = self.data; |
123 | | let args = self.design_axis_count(); |
124 | | self.design_axes_offset().resolve_with_args(data, &args) |
125 | | } |
126 | | |
127 | | /// The number of axis value tables. |
128 | | pub fn axis_value_count(&self) -> u16 { |
129 | | let range = self.shape.axis_value_count_byte_range(); |
130 | | self.data.read_at(range.start).unwrap() |
131 | | } |
132 | | |
133 | | /// Offset in bytes from the beginning of the STAT table to the |
134 | | /// start of the design axes value offsets array. If axisValueCount |
135 | | /// is zero, set to zero; if axisValueCount is greater than zero, |
136 | | /// must be greater than zero. |
137 | | pub fn offset_to_axis_value_offsets(&self) -> Nullable<Offset32> { |
138 | | let range = self.shape.offset_to_axis_value_offsets_byte_range(); |
139 | | self.data.read_at(range.start).unwrap() |
140 | | } |
141 | | |
142 | | /// Attempt to resolve [`offset_to_axis_value_offsets`][Self::offset_to_axis_value_offsets]. |
143 | | pub fn offset_to_axis_values(&self) -> Option<Result<AxisValueArray<'a>, ReadError>> { |
144 | | let data = self.data; |
145 | | let args = self.axis_value_count(); |
146 | | self.offset_to_axis_value_offsets() |
147 | | .resolve_with_args(data, &args) |
148 | | } |
149 | | |
150 | | /// Name ID used as fallback when projection of names into a |
151 | | /// particular font model produces a subfamily name containing only |
152 | | /// elidable elements. |
153 | | pub fn elided_fallback_name_id(&self) -> Option<NameId> { |
154 | | let range = self.shape.elided_fallback_name_id_byte_range()?; |
155 | | Some(self.data.read_at(range.start).unwrap()) |
156 | | } |
157 | | } |
158 | | |
159 | | #[cfg(feature = "experimental_traverse")] |
160 | | impl<'a> SomeTable<'a> for Stat<'a> { |
161 | | fn type_name(&self) -> &str { |
162 | | "Stat" |
163 | | } |
164 | | fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
165 | | let version = self.version(); |
166 | | match idx { |
167 | | 0usize => Some(Field::new("version", self.version())), |
168 | | 1usize => Some(Field::new("design_axis_size", self.design_axis_size())), |
169 | | 2usize => Some(Field::new("design_axis_count", self.design_axis_count())), |
170 | | 3usize => Some(Field::new( |
171 | | "design_axes_offset", |
172 | | traversal::FieldType::offset_to_array_of_records( |
173 | | self.design_axes_offset(), |
174 | | self.design_axes(), |
175 | | stringify!(AxisRecord), |
176 | | self.offset_data(), |
177 | | ), |
178 | | )), |
179 | | 4usize => Some(Field::new("axis_value_count", self.axis_value_count())), |
180 | | 5usize => Some(Field::new( |
181 | | "offset_to_axis_value_offsets", |
182 | | FieldType::offset( |
183 | | self.offset_to_axis_value_offsets(), |
184 | | self.offset_to_axis_values(), |
185 | | ), |
186 | | )), |
187 | | 6usize if version.compatible((1u16, 1u16)) => Some(Field::new( |
188 | | "elided_fallback_name_id", |
189 | | self.elided_fallback_name_id().unwrap(), |
190 | | )), |
191 | | _ => None, |
192 | | } |
193 | | } |
194 | | } |
195 | | |
196 | | #[cfg(feature = "experimental_traverse")] |
197 | | #[allow(clippy::needless_lifetimes)] |
198 | | impl<'a> std::fmt::Debug for Stat<'a> { |
199 | | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
200 | | (self as &dyn SomeTable<'a>).fmt(f) |
201 | | } |
202 | | } |
203 | | |
204 | | /// [Axis Records](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-records) |
205 | | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] |
206 | | #[repr(C)] |
207 | | #[repr(packed)] |
208 | | pub struct AxisRecord { |
209 | | /// A tag identifying the axis of design variation. |
210 | | pub axis_tag: BigEndian<Tag>, |
211 | | /// The name ID for entries in the 'name' table that provide a |
212 | | /// display string for this axis. |
213 | | pub axis_name_id: BigEndian<NameId>, |
214 | | /// A value that applications can use to determine primary sorting |
215 | | /// of face names, or for ordering of labels when composing family |
216 | | /// or face names. |
217 | | pub axis_ordering: BigEndian<u16>, |
218 | | } |
219 | | |
220 | | impl AxisRecord { |
221 | | /// A tag identifying the axis of design variation. |
222 | | pub fn axis_tag(&self) -> Tag { |
223 | | self.axis_tag.get() |
224 | | } |
225 | | |
226 | | /// The name ID for entries in the 'name' table that provide a |
227 | | /// display string for this axis. |
228 | | pub fn axis_name_id(&self) -> NameId { |
229 | | self.axis_name_id.get() |
230 | | } |
231 | | |
232 | | /// A value that applications can use to determine primary sorting |
233 | | /// of face names, or for ordering of labels when composing family |
234 | | /// or face names. |
235 | | pub fn axis_ordering(&self) -> u16 { |
236 | | self.axis_ordering.get() |
237 | | } |
238 | | } |
239 | | |
240 | | impl FixedSize for AxisRecord { |
241 | | const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN; |
242 | | } |
243 | | |
244 | | #[cfg(feature = "experimental_traverse")] |
245 | | impl<'a> SomeRecord<'a> for AxisRecord { |
246 | | fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { |
247 | | RecordResolver { |
248 | | name: "AxisRecord", |
249 | | get_field: Box::new(move |idx, _data| match idx { |
250 | | 0usize => Some(Field::new("axis_tag", self.axis_tag())), |
251 | | 1usize => Some(Field::new("axis_name_id", self.axis_name_id())), |
252 | | 2usize => Some(Field::new("axis_ordering", self.axis_ordering())), |
253 | | _ => None, |
254 | | }), |
255 | | data, |
256 | | } |
257 | | } |
258 | | } |
259 | | |
260 | | /// An array of [AxisValue] tables. |
261 | | #[derive(Debug, Clone, Copy)] |
262 | | #[doc(hidden)] |
263 | | pub struct AxisValueArrayMarker { |
264 | | axis_value_offsets_byte_len: usize, |
265 | | } |
266 | | |
267 | | impl AxisValueArrayMarker { |
268 | | pub fn axis_value_offsets_byte_range(&self) -> Range<usize> { |
269 | | let start = 0; |
270 | | start..start + self.axis_value_offsets_byte_len |
271 | | } |
272 | | } |
273 | | |
274 | | impl MinByteRange for AxisValueArrayMarker { |
275 | | fn min_byte_range(&self) -> Range<usize> { |
276 | | 0..self.axis_value_offsets_byte_range().end |
277 | | } |
278 | | } |
279 | | |
280 | | impl ReadArgs for AxisValueArray<'_> { |
281 | | type Args = u16; |
282 | | } |
283 | | |
284 | | impl<'a> FontReadWithArgs<'a> for AxisValueArray<'a> { |
285 | | fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> { |
286 | | let axis_value_count = *args; |
287 | | let mut cursor = data.cursor(); |
288 | | let axis_value_offsets_byte_len = (axis_value_count as usize) |
289 | | .checked_mul(Offset16::RAW_BYTE_LEN) |
290 | | .ok_or(ReadError::OutOfBounds)?; |
291 | | cursor.advance_by(axis_value_offsets_byte_len); |
292 | | cursor.finish(AxisValueArrayMarker { |
293 | | axis_value_offsets_byte_len, |
294 | | }) |
295 | | } |
296 | | } |
297 | | |
298 | | impl<'a> AxisValueArray<'a> { |
299 | | /// A constructor that requires additional arguments. |
300 | | /// |
301 | | /// This type requires some external state in order to be |
302 | | /// parsed. |
303 | | pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> { |
304 | | let args = axis_value_count; |
305 | | Self::read_with_args(data, &args) |
306 | | } |
307 | | } |
308 | | |
309 | | /// An array of [AxisValue] tables. |
310 | | pub type AxisValueArray<'a> = TableRef<'a, AxisValueArrayMarker>; |
311 | | |
312 | | #[allow(clippy::needless_lifetimes)] |
313 | | impl<'a> AxisValueArray<'a> { |
314 | | /// Array of offsets to axis value tables, in bytes from the start |
315 | | /// of the axis value offsets array. |
316 | | pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] { |
317 | | let range = self.shape.axis_value_offsets_byte_range(); |
318 | | self.data.read_array(range).unwrap() |
319 | | } |
320 | | |
321 | | /// A dynamically resolving wrapper for [`axis_value_offsets`][Self::axis_value_offsets]. |
322 | | pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> { |
323 | | let data = self.data; |
324 | | let offsets = self.axis_value_offsets(); |
325 | | ArrayOfOffsets::new(offsets, data, ()) |
326 | | } |
327 | | } |
328 | | |
329 | | #[cfg(feature = "experimental_traverse")] |
330 | | impl<'a> SomeTable<'a> for AxisValueArray<'a> { |
331 | | fn type_name(&self) -> &str { |
332 | | "AxisValueArray" |
333 | | } |
334 | | fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
335 | | match idx { |
336 | | 0usize => Some({ |
337 | | let data = self.data; |
338 | | Field::new( |
339 | | "axis_value_offsets", |
340 | | FieldType::array_of_offsets( |
341 | | better_type_name::<AxisValue>(), |
342 | | self.axis_value_offsets(), |
343 | | move |off| { |
344 | | let target = off.get().resolve::<AxisValue>(data); |
345 | | FieldType::offset(off.get(), target) |
346 | | }, |
347 | | ), |
348 | | ) |
349 | | }), |
350 | | _ => None, |
351 | | } |
352 | | } |
353 | | } |
354 | | |
355 | | #[cfg(feature = "experimental_traverse")] |
356 | | #[allow(clippy::needless_lifetimes)] |
357 | | impl<'a> std::fmt::Debug for AxisValueArray<'a> { |
358 | | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
359 | | (self as &dyn SomeTable<'a>).fmt(f) |
360 | | } |
361 | | } |
362 | | |
363 | | /// [Axis Value Tables](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-tables) |
364 | | #[derive(Clone)] |
365 | | pub enum AxisValue<'a> { |
366 | | Format1(AxisValueFormat1<'a>), |
367 | | Format2(AxisValueFormat2<'a>), |
368 | | Format3(AxisValueFormat3<'a>), |
369 | | Format4(AxisValueFormat4<'a>), |
370 | | } |
371 | | |
372 | | impl<'a> AxisValue<'a> { |
373 | | ///Return the `FontData` used to resolve offsets for this table. |
374 | | pub fn offset_data(&self) -> FontData<'a> { |
375 | | match self { |
376 | | Self::Format1(item) => item.offset_data(), |
377 | | Self::Format2(item) => item.offset_data(), |
378 | | Self::Format3(item) => item.offset_data(), |
379 | | Self::Format4(item) => item.offset_data(), |
380 | | } |
381 | | } |
382 | | |
383 | | /// Format identifier — set to 1. |
384 | | pub fn format(&self) -> u16 { |
385 | | match self { |
386 | | Self::Format1(item) => item.format(), |
387 | | Self::Format2(item) => item.format(), |
388 | | Self::Format3(item) => item.format(), |
389 | | Self::Format4(item) => item.format(), |
390 | | } |
391 | | } |
392 | | |
393 | | /// Flags — see below for details. |
394 | | pub fn flags(&self) -> AxisValueTableFlags { |
395 | | match self { |
396 | | Self::Format1(item) => item.flags(), |
397 | | Self::Format2(item) => item.flags(), |
398 | | Self::Format3(item) => item.flags(), |
399 | | Self::Format4(item) => item.flags(), |
400 | | } |
401 | | } |
402 | | |
403 | | /// The name ID for entries in the 'name' table that provide a |
404 | | /// display string for this attribute value. |
405 | | pub fn value_name_id(&self) -> NameId { |
406 | | match self { |
407 | | Self::Format1(item) => item.value_name_id(), |
408 | | Self::Format2(item) => item.value_name_id(), |
409 | | Self::Format3(item) => item.value_name_id(), |
410 | | Self::Format4(item) => item.value_name_id(), |
411 | | } |
412 | | } |
413 | | } |
414 | | |
415 | | impl<'a> FontRead<'a> for AxisValue<'a> { |
416 | | fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
417 | | let format: u16 = data.read_at(0usize)?; |
418 | | match format { |
419 | | AxisValueFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)), |
420 | | AxisValueFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)), |
421 | | AxisValueFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)), |
422 | | AxisValueFormat4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)), |
423 | | other => Err(ReadError::InvalidFormat(other.into())), |
424 | | } |
425 | | } |
426 | | } |
427 | | |
428 | | impl MinByteRange for AxisValue<'_> { |
429 | | fn min_byte_range(&self) -> Range<usize> { |
430 | | match self { |
431 | | Self::Format1(item) => item.min_byte_range(), |
432 | | Self::Format2(item) => item.min_byte_range(), |
433 | | Self::Format3(item) => item.min_byte_range(), |
434 | | Self::Format4(item) => item.min_byte_range(), |
435 | | } |
436 | | } |
437 | | } |
438 | | |
439 | | #[cfg(feature = "experimental_traverse")] |
440 | | impl<'a> AxisValue<'a> { |
441 | | fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> { |
442 | | match self { |
443 | | Self::Format1(table) => table, |
444 | | Self::Format2(table) => table, |
445 | | Self::Format3(table) => table, |
446 | | Self::Format4(table) => table, |
447 | | } |
448 | | } |
449 | | } |
450 | | |
451 | | #[cfg(feature = "experimental_traverse")] |
452 | | impl std::fmt::Debug for AxisValue<'_> { |
453 | | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
454 | | self.dyn_inner().fmt(f) |
455 | | } |
456 | | } |
457 | | |
458 | | #[cfg(feature = "experimental_traverse")] |
459 | | impl<'a> SomeTable<'a> for AxisValue<'a> { |
460 | | fn type_name(&self) -> &str { |
461 | | self.dyn_inner().type_name() |
462 | | } |
463 | | fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
464 | | self.dyn_inner().get_field(idx) |
465 | | } |
466 | | } |
467 | | |
468 | | impl Format<u16> for AxisValueFormat1Marker { |
469 | | const FORMAT: u16 = 1; |
470 | | } |
471 | | |
472 | | /// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1) |
473 | | #[derive(Debug, Clone, Copy)] |
474 | | #[doc(hidden)] |
475 | | pub struct AxisValueFormat1Marker {} |
476 | | |
477 | | impl AxisValueFormat1Marker { |
478 | | pub fn format_byte_range(&self) -> Range<usize> { |
479 | | let start = 0; |
480 | | start..start + u16::RAW_BYTE_LEN |
481 | | } |
482 | | |
483 | | pub fn axis_index_byte_range(&self) -> Range<usize> { |
484 | | let start = self.format_byte_range().end; |
485 | | start..start + u16::RAW_BYTE_LEN |
486 | | } |
487 | | |
488 | | pub fn flags_byte_range(&self) -> Range<usize> { |
489 | | let start = self.axis_index_byte_range().end; |
490 | | start..start + AxisValueTableFlags::RAW_BYTE_LEN |
491 | | } |
492 | | |
493 | | pub fn value_name_id_byte_range(&self) -> Range<usize> { |
494 | | let start = self.flags_byte_range().end; |
495 | | start..start + NameId::RAW_BYTE_LEN |
496 | | } |
497 | | |
498 | | pub fn value_byte_range(&self) -> Range<usize> { |
499 | | let start = self.value_name_id_byte_range().end; |
500 | | start..start + Fixed::RAW_BYTE_LEN |
501 | | } |
502 | | } |
503 | | |
504 | | impl MinByteRange for AxisValueFormat1Marker { |
505 | | fn min_byte_range(&self) -> Range<usize> { |
506 | | 0..self.value_byte_range().end |
507 | | } |
508 | | } |
509 | | |
510 | | impl<'a> FontRead<'a> for AxisValueFormat1<'a> { |
511 | | fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
512 | | let mut cursor = data.cursor(); |
513 | | cursor.advance::<u16>(); |
514 | | cursor.advance::<u16>(); |
515 | | cursor.advance::<AxisValueTableFlags>(); |
516 | | cursor.advance::<NameId>(); |
517 | | cursor.advance::<Fixed>(); |
518 | | cursor.finish(AxisValueFormat1Marker {}) |
519 | | } |
520 | | } |
521 | | |
522 | | /// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1) |
523 | | pub type AxisValueFormat1<'a> = TableRef<'a, AxisValueFormat1Marker>; |
524 | | |
525 | | #[allow(clippy::needless_lifetimes)] |
526 | | impl<'a> AxisValueFormat1<'a> { |
527 | | /// Format identifier — set to 1. |
528 | | pub fn format(&self) -> u16 { |
529 | | let range = self.shape.format_byte_range(); |
530 | | self.data.read_at(range.start).unwrap() |
531 | | } |
532 | | |
533 | | /// Zero-base index into the axis record array identifying the axis |
534 | | /// of design variation to which the axis value table applies. Must |
535 | | /// be less than designAxisCount. |
536 | | pub fn axis_index(&self) -> u16 { |
537 | | let range = self.shape.axis_index_byte_range(); |
538 | | self.data.read_at(range.start).unwrap() |
539 | | } |
540 | | |
541 | | /// Flags — see below for details. |
542 | | pub fn flags(&self) -> AxisValueTableFlags { |
543 | | let range = self.shape.flags_byte_range(); |
544 | | self.data.read_at(range.start).unwrap() |
545 | | } |
546 | | |
547 | | /// The name ID for entries in the 'name' table that provide a |
548 | | /// display string for this attribute value. |
549 | | pub fn value_name_id(&self) -> NameId { |
550 | | let range = self.shape.value_name_id_byte_range(); |
551 | | self.data.read_at(range.start).unwrap() |
552 | | } |
553 | | |
554 | | /// A numeric value for this attribute value. |
555 | | pub fn value(&self) -> Fixed { |
556 | | let range = self.shape.value_byte_range(); |
557 | | self.data.read_at(range.start).unwrap() |
558 | | } |
559 | | } |
560 | | |
561 | | #[cfg(feature = "experimental_traverse")] |
562 | | impl<'a> SomeTable<'a> for AxisValueFormat1<'a> { |
563 | | fn type_name(&self) -> &str { |
564 | | "AxisValueFormat1" |
565 | | } |
566 | | fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
567 | | match idx { |
568 | | 0usize => Some(Field::new("format", self.format())), |
569 | | 1usize => Some(Field::new("axis_index", self.axis_index())), |
570 | | 2usize => Some(Field::new("flags", self.flags())), |
571 | | 3usize => Some(Field::new("value_name_id", self.value_name_id())), |
572 | | 4usize => Some(Field::new("value", self.value())), |
573 | | _ => None, |
574 | | } |
575 | | } |
576 | | } |
577 | | |
578 | | #[cfg(feature = "experimental_traverse")] |
579 | | #[allow(clippy::needless_lifetimes)] |
580 | | impl<'a> std::fmt::Debug for AxisValueFormat1<'a> { |
581 | | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
582 | | (self as &dyn SomeTable<'a>).fmt(f) |
583 | | } |
584 | | } |
585 | | |
586 | | impl Format<u16> for AxisValueFormat2Marker { |
587 | | const FORMAT: u16 = 2; |
588 | | } |
589 | | |
590 | | /// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2) |
591 | | #[derive(Debug, Clone, Copy)] |
592 | | #[doc(hidden)] |
593 | | pub struct AxisValueFormat2Marker {} |
594 | | |
595 | | impl AxisValueFormat2Marker { |
596 | | pub fn format_byte_range(&self) -> Range<usize> { |
597 | | let start = 0; |
598 | | start..start + u16::RAW_BYTE_LEN |
599 | | } |
600 | | |
601 | | pub fn axis_index_byte_range(&self) -> Range<usize> { |
602 | | let start = self.format_byte_range().end; |
603 | | start..start + u16::RAW_BYTE_LEN |
604 | | } |
605 | | |
606 | | pub fn flags_byte_range(&self) -> Range<usize> { |
607 | | let start = self.axis_index_byte_range().end; |
608 | | start..start + AxisValueTableFlags::RAW_BYTE_LEN |
609 | | } |
610 | | |
611 | | pub fn value_name_id_byte_range(&self) -> Range<usize> { |
612 | | let start = self.flags_byte_range().end; |
613 | | start..start + NameId::RAW_BYTE_LEN |
614 | | } |
615 | | |
616 | | pub fn nominal_value_byte_range(&self) -> Range<usize> { |
617 | | let start = self.value_name_id_byte_range().end; |
618 | | start..start + Fixed::RAW_BYTE_LEN |
619 | | } |
620 | | |
621 | | pub fn range_min_value_byte_range(&self) -> Range<usize> { |
622 | | let start = self.nominal_value_byte_range().end; |
623 | | start..start + Fixed::RAW_BYTE_LEN |
624 | | } |
625 | | |
626 | | pub fn range_max_value_byte_range(&self) -> Range<usize> { |
627 | | let start = self.range_min_value_byte_range().end; |
628 | | start..start + Fixed::RAW_BYTE_LEN |
629 | | } |
630 | | } |
631 | | |
632 | | impl MinByteRange for AxisValueFormat2Marker { |
633 | | fn min_byte_range(&self) -> Range<usize> { |
634 | | 0..self.range_max_value_byte_range().end |
635 | | } |
636 | | } |
637 | | |
638 | | impl<'a> FontRead<'a> for AxisValueFormat2<'a> { |
639 | | fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
640 | | let mut cursor = data.cursor(); |
641 | | cursor.advance::<u16>(); |
642 | | cursor.advance::<u16>(); |
643 | | cursor.advance::<AxisValueTableFlags>(); |
644 | | cursor.advance::<NameId>(); |
645 | | cursor.advance::<Fixed>(); |
646 | | cursor.advance::<Fixed>(); |
647 | | cursor.advance::<Fixed>(); |
648 | | cursor.finish(AxisValueFormat2Marker {}) |
649 | | } |
650 | | } |
651 | | |
652 | | /// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2) |
653 | | pub type AxisValueFormat2<'a> = TableRef<'a, AxisValueFormat2Marker>; |
654 | | |
655 | | #[allow(clippy::needless_lifetimes)] |
656 | | impl<'a> AxisValueFormat2<'a> { |
657 | | /// Format identifier — set to 2. |
658 | | pub fn format(&self) -> u16 { |
659 | | let range = self.shape.format_byte_range(); |
660 | | self.data.read_at(range.start).unwrap() |
661 | | } |
662 | | |
663 | | /// Zero-base index into the axis record array identifying the axis |
664 | | /// of design variation to which the axis value table applies. Must |
665 | | /// be less than designAxisCount. |
666 | | pub fn axis_index(&self) -> u16 { |
667 | | let range = self.shape.axis_index_byte_range(); |
668 | | self.data.read_at(range.start).unwrap() |
669 | | } |
670 | | |
671 | | /// Flags — see below for details. |
672 | | pub fn flags(&self) -> AxisValueTableFlags { |
673 | | let range = self.shape.flags_byte_range(); |
674 | | self.data.read_at(range.start).unwrap() |
675 | | } |
676 | | |
677 | | /// The name ID for entries in the 'name' table that provide a |
678 | | /// display string for this attribute value. |
679 | | pub fn value_name_id(&self) -> NameId { |
680 | | let range = self.shape.value_name_id_byte_range(); |
681 | | self.data.read_at(range.start).unwrap() |
682 | | } |
683 | | |
684 | | /// A nominal numeric value for this attribute value. |
685 | | pub fn nominal_value(&self) -> Fixed { |
686 | | let range = self.shape.nominal_value_byte_range(); |
687 | | self.data.read_at(range.start).unwrap() |
688 | | } |
689 | | |
690 | | /// The minimum value for a range associated with the specified |
691 | | /// name ID. |
692 | | pub fn range_min_value(&self) -> Fixed { |
693 | | let range = self.shape.range_min_value_byte_range(); |
694 | | self.data.read_at(range.start).unwrap() |
695 | | } |
696 | | |
697 | | /// The maximum value for a range associated with the specified |
698 | | /// name ID. |
699 | | pub fn range_max_value(&self) -> Fixed { |
700 | | let range = self.shape.range_max_value_byte_range(); |
701 | | self.data.read_at(range.start).unwrap() |
702 | | } |
703 | | } |
704 | | |
705 | | #[cfg(feature = "experimental_traverse")] |
706 | | impl<'a> SomeTable<'a> for AxisValueFormat2<'a> { |
707 | | fn type_name(&self) -> &str { |
708 | | "AxisValueFormat2" |
709 | | } |
710 | | fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
711 | | match idx { |
712 | | 0usize => Some(Field::new("format", self.format())), |
713 | | 1usize => Some(Field::new("axis_index", self.axis_index())), |
714 | | 2usize => Some(Field::new("flags", self.flags())), |
715 | | 3usize => Some(Field::new("value_name_id", self.value_name_id())), |
716 | | 4usize => Some(Field::new("nominal_value", self.nominal_value())), |
717 | | 5usize => Some(Field::new("range_min_value", self.range_min_value())), |
718 | | 6usize => Some(Field::new("range_max_value", self.range_max_value())), |
719 | | _ => None, |
720 | | } |
721 | | } |
722 | | } |
723 | | |
724 | | #[cfg(feature = "experimental_traverse")] |
725 | | #[allow(clippy::needless_lifetimes)] |
726 | | impl<'a> std::fmt::Debug for AxisValueFormat2<'a> { |
727 | | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
728 | | (self as &dyn SomeTable<'a>).fmt(f) |
729 | | } |
730 | | } |
731 | | |
732 | | impl Format<u16> for AxisValueFormat3Marker { |
733 | | const FORMAT: u16 = 3; |
734 | | } |
735 | | |
736 | | /// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3) |
737 | | #[derive(Debug, Clone, Copy)] |
738 | | #[doc(hidden)] |
739 | | pub struct AxisValueFormat3Marker {} |
740 | | |
741 | | impl AxisValueFormat3Marker { |
742 | | pub fn format_byte_range(&self) -> Range<usize> { |
743 | | let start = 0; |
744 | | start..start + u16::RAW_BYTE_LEN |
745 | | } |
746 | | |
747 | | pub fn axis_index_byte_range(&self) -> Range<usize> { |
748 | | let start = self.format_byte_range().end; |
749 | | start..start + u16::RAW_BYTE_LEN |
750 | | } |
751 | | |
752 | | pub fn flags_byte_range(&self) -> Range<usize> { |
753 | | let start = self.axis_index_byte_range().end; |
754 | | start..start + AxisValueTableFlags::RAW_BYTE_LEN |
755 | | } |
756 | | |
757 | | pub fn value_name_id_byte_range(&self) -> Range<usize> { |
758 | | let start = self.flags_byte_range().end; |
759 | | start..start + NameId::RAW_BYTE_LEN |
760 | | } |
761 | | |
762 | | pub fn value_byte_range(&self) -> Range<usize> { |
763 | | let start = self.value_name_id_byte_range().end; |
764 | | start..start + Fixed::RAW_BYTE_LEN |
765 | | } |
766 | | |
767 | | pub fn linked_value_byte_range(&self) -> Range<usize> { |
768 | | let start = self.value_byte_range().end; |
769 | | start..start + Fixed::RAW_BYTE_LEN |
770 | | } |
771 | | } |
772 | | |
773 | | impl MinByteRange for AxisValueFormat3Marker { |
774 | | fn min_byte_range(&self) -> Range<usize> { |
775 | | 0..self.linked_value_byte_range().end |
776 | | } |
777 | | } |
778 | | |
779 | | impl<'a> FontRead<'a> for AxisValueFormat3<'a> { |
780 | | fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
781 | | let mut cursor = data.cursor(); |
782 | | cursor.advance::<u16>(); |
783 | | cursor.advance::<u16>(); |
784 | | cursor.advance::<AxisValueTableFlags>(); |
785 | | cursor.advance::<NameId>(); |
786 | | cursor.advance::<Fixed>(); |
787 | | cursor.advance::<Fixed>(); |
788 | | cursor.finish(AxisValueFormat3Marker {}) |
789 | | } |
790 | | } |
791 | | |
792 | | /// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3) |
793 | | pub type AxisValueFormat3<'a> = TableRef<'a, AxisValueFormat3Marker>; |
794 | | |
795 | | #[allow(clippy::needless_lifetimes)] |
796 | | impl<'a> AxisValueFormat3<'a> { |
797 | | /// Format identifier — set to 3. |
798 | | pub fn format(&self) -> u16 { |
799 | | let range = self.shape.format_byte_range(); |
800 | | self.data.read_at(range.start).unwrap() |
801 | | } |
802 | | |
803 | | /// Zero-base index into the axis record array identifying the axis |
804 | | /// of design variation to which the axis value table applies. Must |
805 | | /// be less than designAxisCount. |
806 | | pub fn axis_index(&self) -> u16 { |
807 | | let range = self.shape.axis_index_byte_range(); |
808 | | self.data.read_at(range.start).unwrap() |
809 | | } |
810 | | |
811 | | /// Flags — see below for details. |
812 | | pub fn flags(&self) -> AxisValueTableFlags { |
813 | | let range = self.shape.flags_byte_range(); |
814 | | self.data.read_at(range.start).unwrap() |
815 | | } |
816 | | |
817 | | /// The name ID for entries in the 'name' table that provide a |
818 | | /// display string for this attribute value. |
819 | | pub fn value_name_id(&self) -> NameId { |
820 | | let range = self.shape.value_name_id_byte_range(); |
821 | | self.data.read_at(range.start).unwrap() |
822 | | } |
823 | | |
824 | | /// A numeric value for this attribute value. |
825 | | pub fn value(&self) -> Fixed { |
826 | | let range = self.shape.value_byte_range(); |
827 | | self.data.read_at(range.start).unwrap() |
828 | | } |
829 | | |
830 | | /// The numeric value for a style-linked mapping from this value. |
831 | | pub fn linked_value(&self) -> Fixed { |
832 | | let range = self.shape.linked_value_byte_range(); |
833 | | self.data.read_at(range.start).unwrap() |
834 | | } |
835 | | } |
836 | | |
837 | | #[cfg(feature = "experimental_traverse")] |
838 | | impl<'a> SomeTable<'a> for AxisValueFormat3<'a> { |
839 | | fn type_name(&self) -> &str { |
840 | | "AxisValueFormat3" |
841 | | } |
842 | | fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
843 | | match idx { |
844 | | 0usize => Some(Field::new("format", self.format())), |
845 | | 1usize => Some(Field::new("axis_index", self.axis_index())), |
846 | | 2usize => Some(Field::new("flags", self.flags())), |
847 | | 3usize => Some(Field::new("value_name_id", self.value_name_id())), |
848 | | 4usize => Some(Field::new("value", self.value())), |
849 | | 5usize => Some(Field::new("linked_value", self.linked_value())), |
850 | | _ => None, |
851 | | } |
852 | | } |
853 | | } |
854 | | |
855 | | #[cfg(feature = "experimental_traverse")] |
856 | | #[allow(clippy::needless_lifetimes)] |
857 | | impl<'a> std::fmt::Debug for AxisValueFormat3<'a> { |
858 | | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
859 | | (self as &dyn SomeTable<'a>).fmt(f) |
860 | | } |
861 | | } |
862 | | |
863 | | impl Format<u16> for AxisValueFormat4Marker { |
864 | | const FORMAT: u16 = 4; |
865 | | } |
866 | | |
867 | | /// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4) |
868 | | #[derive(Debug, Clone, Copy)] |
869 | | #[doc(hidden)] |
870 | | pub struct AxisValueFormat4Marker { |
871 | | axis_values_byte_len: usize, |
872 | | } |
873 | | |
874 | | impl AxisValueFormat4Marker { |
875 | | pub fn format_byte_range(&self) -> Range<usize> { |
876 | | let start = 0; |
877 | | start..start + u16::RAW_BYTE_LEN |
878 | | } |
879 | | |
880 | | pub fn axis_count_byte_range(&self) -> Range<usize> { |
881 | | let start = self.format_byte_range().end; |
882 | | start..start + u16::RAW_BYTE_LEN |
883 | | } |
884 | | |
885 | | pub fn flags_byte_range(&self) -> Range<usize> { |
886 | | let start = self.axis_count_byte_range().end; |
887 | | start..start + AxisValueTableFlags::RAW_BYTE_LEN |
888 | | } |
889 | | |
890 | | pub fn value_name_id_byte_range(&self) -> Range<usize> { |
891 | | let start = self.flags_byte_range().end; |
892 | | start..start + NameId::RAW_BYTE_LEN |
893 | | } |
894 | | |
895 | | pub fn axis_values_byte_range(&self) -> Range<usize> { |
896 | | let start = self.value_name_id_byte_range().end; |
897 | | start..start + self.axis_values_byte_len |
898 | | } |
899 | | } |
900 | | |
901 | | impl MinByteRange for AxisValueFormat4Marker { |
902 | | fn min_byte_range(&self) -> Range<usize> { |
903 | | 0..self.axis_values_byte_range().end |
904 | | } |
905 | | } |
906 | | |
907 | | impl<'a> FontRead<'a> for AxisValueFormat4<'a> { |
908 | | fn read(data: FontData<'a>) -> Result<Self, ReadError> { |
909 | | let mut cursor = data.cursor(); |
910 | | cursor.advance::<u16>(); |
911 | | let axis_count: u16 = cursor.read()?; |
912 | | cursor.advance::<AxisValueTableFlags>(); |
913 | | cursor.advance::<NameId>(); |
914 | | let axis_values_byte_len = (axis_count as usize) |
915 | | .checked_mul(AxisValueRecord::RAW_BYTE_LEN) |
916 | | .ok_or(ReadError::OutOfBounds)?; |
917 | | cursor.advance_by(axis_values_byte_len); |
918 | | cursor.finish(AxisValueFormat4Marker { |
919 | | axis_values_byte_len, |
920 | | }) |
921 | | } |
922 | | } |
923 | | |
924 | | /// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4) |
925 | | pub type AxisValueFormat4<'a> = TableRef<'a, AxisValueFormat4Marker>; |
926 | | |
927 | | #[allow(clippy::needless_lifetimes)] |
928 | | impl<'a> AxisValueFormat4<'a> { |
929 | | /// Format identifier — set to 4. |
930 | | pub fn format(&self) -> u16 { |
931 | | let range = self.shape.format_byte_range(); |
932 | | self.data.read_at(range.start).unwrap() |
933 | | } |
934 | | |
935 | | /// The total number of axes contributing to this axis-values |
936 | | /// combination. |
937 | | pub fn axis_count(&self) -> u16 { |
938 | | let range = self.shape.axis_count_byte_range(); |
939 | | self.data.read_at(range.start).unwrap() |
940 | | } |
941 | | |
942 | | /// Flags — see below for details. |
943 | | pub fn flags(&self) -> AxisValueTableFlags { |
944 | | let range = self.shape.flags_byte_range(); |
945 | | self.data.read_at(range.start).unwrap() |
946 | | } |
947 | | |
948 | | /// The name ID for entries in the 'name' table that provide a |
949 | | /// display string for this combination of axis values. |
950 | | pub fn value_name_id(&self) -> NameId { |
951 | | let range = self.shape.value_name_id_byte_range(); |
952 | | self.data.read_at(range.start).unwrap() |
953 | | } |
954 | | |
955 | | /// Array of AxisValue records that provide the combination of axis |
956 | | /// values, one for each contributing axis. |
957 | | pub fn axis_values(&self) -> &'a [AxisValueRecord] { |
958 | | let range = self.shape.axis_values_byte_range(); |
959 | | self.data.read_array(range).unwrap() |
960 | | } |
961 | | } |
962 | | |
963 | | #[cfg(feature = "experimental_traverse")] |
964 | | impl<'a> SomeTable<'a> for AxisValueFormat4<'a> { |
965 | | fn type_name(&self) -> &str { |
966 | | "AxisValueFormat4" |
967 | | } |
968 | | fn get_field(&self, idx: usize) -> Option<Field<'a>> { |
969 | | match idx { |
970 | | 0usize => Some(Field::new("format", self.format())), |
971 | | 1usize => Some(Field::new("axis_count", self.axis_count())), |
972 | | 2usize => Some(Field::new("flags", self.flags())), |
973 | | 3usize => Some(Field::new("value_name_id", self.value_name_id())), |
974 | | 4usize => Some(Field::new( |
975 | | "axis_values", |
976 | | traversal::FieldType::array_of_records( |
977 | | stringify!(AxisValueRecord), |
978 | | self.axis_values(), |
979 | | self.offset_data(), |
980 | | ), |
981 | | )), |
982 | | _ => None, |
983 | | } |
984 | | } |
985 | | } |
986 | | |
987 | | #[cfg(feature = "experimental_traverse")] |
988 | | #[allow(clippy::needless_lifetimes)] |
989 | | impl<'a> std::fmt::Debug for AxisValueFormat4<'a> { |
990 | | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
991 | | (self as &dyn SomeTable<'a>).fmt(f) |
992 | | } |
993 | | } |
994 | | |
995 | | /// Part of [AxisValueFormat4] |
996 | | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)] |
997 | | #[repr(C)] |
998 | | #[repr(packed)] |
999 | | pub struct AxisValueRecord { |
1000 | | /// Zero-base index into the axis record array identifying the axis |
1001 | | /// to which this value applies. Must be less than designAxisCount. |
1002 | | pub axis_index: BigEndian<u16>, |
1003 | | /// A numeric value for this attribute value. |
1004 | | pub value: BigEndian<Fixed>, |
1005 | | } |
1006 | | |
1007 | | impl AxisValueRecord { |
1008 | | /// Zero-base index into the axis record array identifying the axis |
1009 | | /// to which this value applies. Must be less than designAxisCount. |
1010 | | pub fn axis_index(&self) -> u16 { |
1011 | | self.axis_index.get() |
1012 | | } |
1013 | | |
1014 | | /// A numeric value for this attribute value. |
1015 | | pub fn value(&self) -> Fixed { |
1016 | | self.value.get() |
1017 | | } |
1018 | | } |
1019 | | |
1020 | | impl FixedSize for AxisValueRecord { |
1021 | | const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN; |
1022 | | } |
1023 | | |
1024 | | #[cfg(feature = "experimental_traverse")] |
1025 | | impl<'a> SomeRecord<'a> for AxisValueRecord { |
1026 | | fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { |
1027 | | RecordResolver { |
1028 | | name: "AxisValueRecord", |
1029 | | get_field: Box::new(move |idx, _data| match idx { |
1030 | | 0usize => Some(Field::new("axis_index", self.axis_index())), |
1031 | | 1usize => Some(Field::new("value", self.value())), |
1032 | | _ => None, |
1033 | | }), |
1034 | | data, |
1035 | | } |
1036 | | } |
1037 | | } |
1038 | | |
1039 | | /// [Axis value table flags](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#flags). |
1040 | | #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)] |
1041 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
1042 | | #[repr(transparent)] |
1043 | | pub struct AxisValueTableFlags { |
1044 | | bits: u16, |
1045 | | } |
1046 | | |
1047 | | impl AxisValueTableFlags { |
1048 | | /// If set, this axis value table provides axis value information |
1049 | | /// that is applicable to other fonts within the same font family. |
1050 | | /// This is used if the other fonts were released earlier and did |
1051 | | /// not include information about values for some axis. If newer |
1052 | | /// versions of the other fonts include the information themselves |
1053 | | /// and are present, then this table is ignored. |
1054 | | pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 }; |
1055 | | |
1056 | | /// If set, it indicates that the axis value represents the |
1057 | | /// “normal” value for the axis and may be omitted when |
1058 | | /// composing name strings. |
1059 | | pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 }; |
1060 | | } |
1061 | | |
1062 | | impl AxisValueTableFlags { |
1063 | | /// Returns an empty set of flags. |
1064 | | #[inline] |
1065 | | pub const fn empty() -> Self { |
1066 | | Self { bits: 0 } |
1067 | | } |
1068 | | |
1069 | | /// Returns the set containing all flags. |
1070 | | #[inline] |
1071 | | pub const fn all() -> Self { |
1072 | | Self { |
1073 | | bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits, |
1074 | | } |
1075 | | } |
1076 | | |
1077 | | /// Returns the raw value of the flags currently stored. |
1078 | | #[inline] |
1079 | 0 | pub const fn bits(&self) -> u16 { |
1080 | 0 | self.bits |
1081 | 0 | } |
1082 | | |
1083 | | /// Convert from underlying bit representation, unless that |
1084 | | /// representation contains bits that do not correspond to a flag. |
1085 | | #[inline] |
1086 | | pub const fn from_bits(bits: u16) -> Option<Self> { |
1087 | | if (bits & !Self::all().bits()) == 0 { |
1088 | | Some(Self { bits }) |
1089 | | } else { |
1090 | | None |
1091 | | } |
1092 | | } |
1093 | | |
1094 | | /// Convert from underlying bit representation, dropping any bits |
1095 | | /// that do not correspond to flags. |
1096 | | #[inline] |
1097 | | pub const fn from_bits_truncate(bits: u16) -> Self { |
1098 | | Self { |
1099 | | bits: bits & Self::all().bits, |
1100 | | } |
1101 | | } |
1102 | | |
1103 | | /// Returns `true` if no flags are currently stored. |
1104 | | #[inline] |
1105 | | pub const fn is_empty(&self) -> bool { |
1106 | | self.bits() == Self::empty().bits() |
1107 | | } |
1108 | | |
1109 | | /// Returns `true` if there are flags common to both `self` and `other`. |
1110 | | #[inline] |
1111 | | pub const fn intersects(&self, other: Self) -> bool { |
1112 | | !(Self { |
1113 | | bits: self.bits & other.bits, |
1114 | | }) |
1115 | | .is_empty() |
1116 | | } |
1117 | | |
1118 | | /// Returns `true` if all of the flags in `other` are contained within `self`. |
1119 | | #[inline] |
1120 | | pub const fn contains(&self, other: Self) -> bool { |
1121 | | (self.bits & other.bits) == other.bits |
1122 | | } |
1123 | | |
1124 | | /// Inserts the specified flags in-place. |
1125 | | #[inline] |
1126 | | pub fn insert(&mut self, other: Self) { |
1127 | | self.bits |= other.bits; |
1128 | | } |
1129 | | |
1130 | | /// Removes the specified flags in-place. |
1131 | | #[inline] |
1132 | | pub fn remove(&mut self, other: Self) { |
1133 | | self.bits &= !other.bits; |
1134 | | } |
1135 | | |
1136 | | /// Toggles the specified flags in-place. |
1137 | | #[inline] |
1138 | | pub fn toggle(&mut self, other: Self) { |
1139 | | self.bits ^= other.bits; |
1140 | | } |
1141 | | |
1142 | | /// Returns the intersection between the flags in `self` and |
1143 | | /// `other`. |
1144 | | /// |
1145 | | /// Specifically, the returned set contains only the flags which are |
1146 | | /// present in *both* `self` *and* `other`. |
1147 | | /// |
1148 | | /// This is equivalent to using the `&` operator (e.g. |
1149 | | /// [`ops::BitAnd`]), as in `flags & other`. |
1150 | | /// |
1151 | | /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html |
1152 | | #[inline] |
1153 | | #[must_use] |
1154 | | pub const fn intersection(self, other: Self) -> Self { |
1155 | | Self { |
1156 | | bits: self.bits & other.bits, |
1157 | | } |
1158 | | } |
1159 | | |
1160 | | /// Returns the union of between the flags in `self` and `other`. |
1161 | | /// |
1162 | | /// Specifically, the returned set contains all flags which are |
1163 | | /// present in *either* `self` *or* `other`, including any which are |
1164 | | /// present in both. |
1165 | | /// |
1166 | | /// This is equivalent to using the `|` operator (e.g. |
1167 | | /// [`ops::BitOr`]), as in `flags | other`. |
1168 | | /// |
1169 | | /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html |
1170 | | #[inline] |
1171 | | #[must_use] |
1172 | | pub const fn union(self, other: Self) -> Self { |
1173 | | Self { |
1174 | | bits: self.bits | other.bits, |
1175 | | } |
1176 | | } |
1177 | | |
1178 | | /// Returns the difference between the flags in `self` and `other`. |
1179 | | /// |
1180 | | /// Specifically, the returned set contains all flags present in |
1181 | | /// `self`, except for the ones present in `other`. |
1182 | | /// |
1183 | | /// It is also conceptually equivalent to the "bit-clear" operation: |
1184 | | /// `flags & !other` (and this syntax is also supported). |
1185 | | /// |
1186 | | /// This is equivalent to using the `-` operator (e.g. |
1187 | | /// [`ops::Sub`]), as in `flags - other`. |
1188 | | /// |
1189 | | /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html |
1190 | | #[inline] |
1191 | | #[must_use] |
1192 | | pub const fn difference(self, other: Self) -> Self { |
1193 | | Self { |
1194 | | bits: self.bits & !other.bits, |
1195 | | } |
1196 | | } |
1197 | | } |
1198 | | |
1199 | | impl std::ops::BitOr for AxisValueTableFlags { |
1200 | | type Output = Self; |
1201 | | |
1202 | | /// Returns the union of the two sets of flags. |
1203 | | #[inline] |
1204 | | fn bitor(self, other: AxisValueTableFlags) -> Self { |
1205 | | Self { |
1206 | | bits: self.bits | other.bits, |
1207 | | } |
1208 | | } |
1209 | | } |
1210 | | |
1211 | | impl std::ops::BitOrAssign for AxisValueTableFlags { |
1212 | | /// Adds the set of flags. |
1213 | | #[inline] |
1214 | | fn bitor_assign(&mut self, other: Self) { |
1215 | | self.bits |= other.bits; |
1216 | | } |
1217 | | } |
1218 | | |
1219 | | impl std::ops::BitXor for AxisValueTableFlags { |
1220 | | type Output = Self; |
1221 | | |
1222 | | /// Returns the left flags, but with all the right flags toggled. |
1223 | | #[inline] |
1224 | | fn bitxor(self, other: Self) -> Self { |
1225 | | Self { |
1226 | | bits: self.bits ^ other.bits, |
1227 | | } |
1228 | | } |
1229 | | } |
1230 | | |
1231 | | impl std::ops::BitXorAssign for AxisValueTableFlags { |
1232 | | /// Toggles the set of flags. |
1233 | | #[inline] |
1234 | | fn bitxor_assign(&mut self, other: Self) { |
1235 | | self.bits ^= other.bits; |
1236 | | } |
1237 | | } |
1238 | | |
1239 | | impl std::ops::BitAnd for AxisValueTableFlags { |
1240 | | type Output = Self; |
1241 | | |
1242 | | /// Returns the intersection between the two sets of flags. |
1243 | | #[inline] |
1244 | | fn bitand(self, other: Self) -> Self { |
1245 | | Self { |
1246 | | bits: self.bits & other.bits, |
1247 | | } |
1248 | | } |
1249 | | } |
1250 | | |
1251 | | impl std::ops::BitAndAssign for AxisValueTableFlags { |
1252 | | /// Disables all flags disabled in the set. |
1253 | | #[inline] |
1254 | | fn bitand_assign(&mut self, other: Self) { |
1255 | | self.bits &= other.bits; |
1256 | | } |
1257 | | } |
1258 | | |
1259 | | impl std::ops::Sub for AxisValueTableFlags { |
1260 | | type Output = Self; |
1261 | | |
1262 | | /// Returns the set difference of the two sets of flags. |
1263 | | #[inline] |
1264 | | fn sub(self, other: Self) -> Self { |
1265 | | Self { |
1266 | | bits: self.bits & !other.bits, |
1267 | | } |
1268 | | } |
1269 | | } |
1270 | | |
1271 | | impl std::ops::SubAssign for AxisValueTableFlags { |
1272 | | /// Disables all flags enabled in the set. |
1273 | | #[inline] |
1274 | | fn sub_assign(&mut self, other: Self) { |
1275 | | self.bits &= !other.bits; |
1276 | | } |
1277 | | } |
1278 | | |
1279 | | impl std::ops::Not for AxisValueTableFlags { |
1280 | | type Output = Self; |
1281 | | |
1282 | | /// Returns the complement of this set of flags. |
1283 | | #[inline] |
1284 | | fn not(self) -> Self { |
1285 | | Self { bits: !self.bits } & Self::all() |
1286 | | } |
1287 | | } |
1288 | | |
1289 | | impl std::fmt::Debug for AxisValueTableFlags { |
1290 | | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
1291 | | let members: &[(&str, Self)] = &[ |
1292 | | ( |
1293 | | "OLDER_SIBLING_FONT_ATTRIBUTE", |
1294 | | Self::OLDER_SIBLING_FONT_ATTRIBUTE, |
1295 | | ), |
1296 | | ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME), |
1297 | | ]; |
1298 | | let mut first = true; |
1299 | | for (name, value) in members { |
1300 | | if self.contains(*value) { |
1301 | | if !first { |
1302 | | f.write_str(" | ")?; |
1303 | | } |
1304 | | first = false; |
1305 | | f.write_str(name)?; |
1306 | | } |
1307 | | } |
1308 | | if first { |
1309 | | f.write_str("(empty)")?; |
1310 | | } |
1311 | | Ok(()) |
1312 | | } |
1313 | | } |
1314 | | |
1315 | | impl std::fmt::Binary for AxisValueTableFlags { |
1316 | | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
1317 | | std::fmt::Binary::fmt(&self.bits, f) |
1318 | | } |
1319 | | } |
1320 | | |
1321 | | impl std::fmt::Octal for AxisValueTableFlags { |
1322 | | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
1323 | | std::fmt::Octal::fmt(&self.bits, f) |
1324 | | } |
1325 | | } |
1326 | | |
1327 | | impl std::fmt::LowerHex for AxisValueTableFlags { |
1328 | | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
1329 | | std::fmt::LowerHex::fmt(&self.bits, f) |
1330 | | } |
1331 | | } |
1332 | | |
1333 | | impl std::fmt::UpperHex for AxisValueTableFlags { |
1334 | | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
1335 | | std::fmt::UpperHex::fmt(&self.bits, f) |
1336 | | } |
1337 | | } |
1338 | | |
1339 | | impl font_types::Scalar for AxisValueTableFlags { |
1340 | | type Raw = <u16 as font_types::Scalar>::Raw; |
1341 | | fn to_raw(self) -> Self::Raw { |
1342 | | self.bits().to_raw() |
1343 | | } |
1344 | | fn from_raw(raw: Self::Raw) -> Self { |
1345 | | let t = <u16>::from_raw(raw); |
1346 | | Self::from_bits_truncate(t) |
1347 | | } |
1348 | | } |
1349 | | |
1350 | | #[cfg(feature = "experimental_traverse")] |
1351 | | impl<'a> From<AxisValueTableFlags> for FieldType<'a> { |
1352 | | fn from(src: AxisValueTableFlags) -> FieldType<'a> { |
1353 | | src.bits().into() |
1354 | | } |
1355 | | } |