Skip to main content

read_fonts/generated/
generated_feat.rs

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)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Feat<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.names_byte_range().end
11    }
12    fn min_table_bytes(&self) -> &'a [u8] {
13        let range = self.min_byte_range();
14        self.data.as_bytes().get(range).unwrap_or_default()
15    }
16}
17
18impl TopLevelTable for Feat<'_> {
19    /// `feat`
20    const TAG: Tag = Tag::new(b"feat");
21}
22
23impl<'a> FontRead<'a> for Feat<'a> {
24    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25        #[allow(clippy::absurd_extreme_comparisons)]
26        if data.len() < Self::MIN_SIZE {
27            return Err(ReadError::OutOfBounds);
28        }
29        Ok(Self { data })
30    }
31}
32
33/// The [feature name](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html) table.
34#[derive(Clone)]
35pub struct Feat<'a> {
36    data: FontData<'a>,
37}
38
39#[allow(clippy::needless_lifetimes)]
40impl<'a> Feat<'a> {
41    pub const MIN_SIZE: usize =
42        (MajorMinor::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
43    basic_table_impls!(impl_the_methods);
44
45    /// Version number of the feature name table (0x00010000 for the current
46    /// version).
47    pub fn version(&self) -> MajorMinor {
48        let range = self.version_byte_range();
49        self.data.read_at(range.start).ok().unwrap()
50    }
51
52    /// The number of entries in the feature name array.
53    pub fn feature_name_count(&self) -> u16 {
54        let range = self.feature_name_count_byte_range();
55        self.data.read_at(range.start).ok().unwrap()
56    }
57
58    /// The feature name array, sorted by feature type.
59    pub fn names(&self) -> &'a [FeatureName] {
60        let range = self.names_byte_range();
61        self.data.read_array(range).ok().unwrap_or_default()
62    }
63
64    pub fn version_byte_range(&self) -> Range<usize> {
65        let start = 0;
66        start..start + MajorMinor::RAW_BYTE_LEN
67    }
68
69    pub fn feature_name_count_byte_range(&self) -> Range<usize> {
70        let start = self.version_byte_range().end;
71        start..start + u16::RAW_BYTE_LEN
72    }
73
74    pub fn _reserved1_byte_range(&self) -> Range<usize> {
75        let start = self.feature_name_count_byte_range().end;
76        start..start + u16::RAW_BYTE_LEN
77    }
78
79    pub fn _reserved2_byte_range(&self) -> Range<usize> {
80        let start = self._reserved1_byte_range().end;
81        start..start + u32::RAW_BYTE_LEN
82    }
83
84    pub fn names_byte_range(&self) -> Range<usize> {
85        let feature_name_count = self.feature_name_count();
86        let start = self._reserved2_byte_range().end;
87        start
88            ..start
89                + (transforms::to_usize(feature_name_count))
90                    .saturating_mul(FeatureName::RAW_BYTE_LEN)
91    }
92}
93
94const _: () = assert!(FontData::default_data_long_enough(Feat::MIN_SIZE));
95
96impl Default for Feat<'_> {
97    fn default() -> Self {
98        Self {
99            data: FontData::default_table_data(),
100        }
101    }
102}
103
104#[cfg(feature = "experimental_traverse")]
105impl<'a> SomeTable<'a> for Feat<'a> {
106    fn type_name(&self) -> &str {
107        "Feat"
108    }
109    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
110        match idx {
111            0usize => Some(Field::new("version", self.version())),
112            1usize => Some(Field::new("feature_name_count", self.feature_name_count())),
113            2usize => Some(Field::new(
114                "names",
115                traversal::FieldType::array_of_records(
116                    stringify!(FeatureName),
117                    self.names(),
118                    self.offset_data(),
119                ),
120            )),
121            _ => None,
122        }
123    }
124}
125
126#[cfg(feature = "experimental_traverse")]
127#[allow(clippy::needless_lifetimes)]
128impl<'a> std::fmt::Debug for Feat<'a> {
129    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130        (self as &dyn SomeTable<'a>).fmt(f)
131    }
132}
133
134/// Type, flags and names for a feature.
135#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
136#[repr(C)]
137#[repr(packed)]
138pub struct FeatureName {
139    /// Feature type.
140    pub feature: BigEndian<u16>,
141    /// The number of records in the setting name array.
142    pub n_settings: BigEndian<u16>,
143    /// Offset in bytes from the beginning of this table to this feature's
144    /// setting name array. The actual type of record this offset refers
145    /// to will depend on the exclusivity value, as described below.
146    pub setting_table_offset: BigEndian<Offset32>,
147    /// Flags associated with the feature type.
148    pub feature_flags: BigEndian<u16>,
149    /// The name table index for the feature's name.
150    pub name_index: BigEndian<NameId>,
151}
152
153impl FeatureName {
154    /// Feature type.
155    pub fn feature(&self) -> u16 {
156        self.feature.get()
157    }
158
159    /// The number of records in the setting name array.
160    pub fn n_settings(&self) -> u16 {
161        self.n_settings.get()
162    }
163
164    /// Offset in bytes from the beginning of this table to this feature's
165    /// setting name array. The actual type of record this offset refers
166    /// to will depend on the exclusivity value, as described below.
167    pub fn setting_table_offset(&self) -> Offset32 {
168        self.setting_table_offset.get()
169    }
170
171    /// Offset in bytes from the beginning of this table to this feature's
172    /// setting name array. The actual type of record this offset refers
173    /// to will depend on the exclusivity value, as described below.
174    ///
175    /// The `data` argument should be retrieved from the parent table
176    /// By calling its `offset_data` method.
177    pub fn setting_table<'a>(&self, data: FontData<'a>) -> Result<SettingNameArray<'a>, ReadError> {
178        let args = self.n_settings();
179        self.setting_table_offset().resolve_with_args(data, &args)
180    }
181
182    /// Flags associated with the feature type.
183    pub fn feature_flags(&self) -> u16 {
184        self.feature_flags.get()
185    }
186
187    /// The name table index for the feature's name.
188    pub fn name_index(&self) -> NameId {
189        self.name_index.get()
190    }
191}
192
193impl FixedSize for FeatureName {
194    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN
195        + u16::RAW_BYTE_LEN
196        + Offset32::RAW_BYTE_LEN
197        + u16::RAW_BYTE_LEN
198        + NameId::RAW_BYTE_LEN;
199}
200
201#[cfg(feature = "experimental_traverse")]
202impl<'a> SomeRecord<'a> for FeatureName {
203    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
204        RecordResolver {
205            name: "FeatureName",
206            get_field: Box::new(move |idx, _data| match idx {
207                0usize => Some(Field::new("feature", self.feature())),
208                1usize => Some(Field::new("n_settings", self.n_settings())),
209                2usize => Some(Field::new(
210                    "setting_table_offset",
211                    FieldType::offset(self.setting_table_offset(), self.setting_table(_data)),
212                )),
213                3usize => Some(Field::new("feature_flags", self.feature_flags())),
214                4usize => Some(Field::new("name_index", self.name_index())),
215                _ => None,
216            }),
217            data,
218        }
219    }
220}
221
222impl<'a> MinByteRange<'a> for SettingNameArray<'a> {
223    fn min_byte_range(&self) -> Range<usize> {
224        0..self.settings_byte_range().end
225    }
226    fn min_table_bytes(&self) -> &'a [u8] {
227        let range = self.min_byte_range();
228        self.data.as_bytes().get(range).unwrap_or_default()
229    }
230}
231
232impl ReadArgs for SettingNameArray<'_> {
233    type Args = u16;
234}
235
236impl<'a> FontReadWithArgs<'a> for SettingNameArray<'a> {
237    fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
238        let n_settings = *args;
239
240        #[allow(clippy::absurd_extreme_comparisons)]
241        if data.len() < Self::MIN_SIZE {
242            return Err(ReadError::OutOfBounds);
243        }
244        Ok(Self { data, n_settings })
245    }
246}
247
248impl<'a> SettingNameArray<'a> {
249    /// A constructor that requires additional arguments.
250    ///
251    /// This type requires some external state in order to be
252    /// parsed.
253    pub fn read(data: FontData<'a>, n_settings: u16) -> Result<Self, ReadError> {
254        let args = n_settings;
255        Self::read_with_args(data, &args)
256    }
257}
258
259#[derive(Clone)]
260pub struct SettingNameArray<'a> {
261    data: FontData<'a>,
262    n_settings: u16,
263}
264
265#[allow(clippy::needless_lifetimes)]
266impl<'a> SettingNameArray<'a> {
267    pub const MIN_SIZE: usize = 0;
268    basic_table_impls!(impl_the_methods);
269
270    /// List of setting names for a feature.
271    pub fn settings(&self) -> &'a [SettingName] {
272        let range = self.settings_byte_range();
273        self.data.read_array(range).ok().unwrap_or_default()
274    }
275
276    pub(crate) fn n_settings(&self) -> u16 {
277        self.n_settings
278    }
279
280    pub fn settings_byte_range(&self) -> Range<usize> {
281        let n_settings = self.n_settings();
282        let start = 0;
283        start..start + (transforms::to_usize(n_settings)).saturating_mul(SettingName::RAW_BYTE_LEN)
284    }
285}
286
287#[allow(clippy::absurd_extreme_comparisons)]
288const _: () = assert!(FontData::default_data_long_enough(
289    SettingNameArray::MIN_SIZE
290));
291
292impl Default for SettingNameArray<'_> {
293    fn default() -> Self {
294        Self {
295            data: FontData::default_table_data(),
296            n_settings: Default::default(),
297        }
298    }
299}
300
301#[cfg(feature = "experimental_traverse")]
302impl<'a> SomeTable<'a> for SettingNameArray<'a> {
303    fn type_name(&self) -> &str {
304        "SettingNameArray"
305    }
306    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
307        match idx {
308            0usize => Some(Field::new(
309                "settings",
310                traversal::FieldType::array_of_records(
311                    stringify!(SettingName),
312                    self.settings(),
313                    self.offset_data(),
314                ),
315            )),
316            _ => None,
317        }
318    }
319}
320
321#[cfg(feature = "experimental_traverse")]
322#[allow(clippy::needless_lifetimes)]
323impl<'a> std::fmt::Debug for SettingNameArray<'a> {
324    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
325        (self as &dyn SomeTable<'a>).fmt(f)
326    }
327}
328
329/// Associates a setting with a name identifier.
330#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
331#[repr(C)]
332#[repr(packed)]
333pub struct SettingName {
334    /// The setting.
335    pub setting: BigEndian<u16>,
336    /// The name table index for the setting's name.
337    pub name_index: BigEndian<NameId>,
338}
339
340impl SettingName {
341    /// The setting.
342    pub fn setting(&self) -> u16 {
343        self.setting.get()
344    }
345
346    /// The name table index for the setting's name.
347    pub fn name_index(&self) -> NameId {
348        self.name_index.get()
349    }
350}
351
352impl FixedSize for SettingName {
353    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN;
354}
355
356#[cfg(feature = "experimental_traverse")]
357impl<'a> SomeRecord<'a> for SettingName {
358    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
359        RecordResolver {
360            name: "SettingName",
361            get_field: Box::new(move |idx, _data| match idx {
362                0usize => Some(Field::new("setting", self.setting())),
363                1usize => Some(Field::new("name_index", self.name_index())),
364                _ => None,
365            }),
366            data,
367        }
368    }
369}