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