ttf_parser/tables/
feat.rs

1//! A [Feature Name Table](
2//! https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html) implementation.
3
4use crate::parser::{FromData, LazyArray16, Offset, Offset32, Stream};
5
6#[derive(Clone, Copy, Debug)]
7struct FeatureNameRecord {
8    feature: u16,
9    setting_table_records_count: u16,
10    // Offset from the beginning of the table.
11    setting_table_offset: Offset32,
12    flags: u8,
13    default_setting_index: u8,
14    name_index: u16,
15}
16
17impl FromData for FeatureNameRecord {
18    const SIZE: usize = 12;
19
20    #[inline]
21    fn parse(data: &[u8]) -> Option<Self> {
22        let mut s = Stream::new(data);
23        Some(FeatureNameRecord {
24            feature: s.read::<u16>()?,
25            setting_table_records_count: s.read::<u16>()?,
26            setting_table_offset: s.read::<Offset32>()?,
27            flags: s.read::<u8>()?,
28            default_setting_index: s.read::<u8>()?,
29            name_index: s.read::<u16>()?,
30        })
31    }
32}
33
34/// A setting name.
35#[derive(Clone, Copy, Debug)]
36pub struct SettingName {
37    /// The setting.
38    pub setting: u16,
39    /// The `name` table index for the feature's name in a 256..32768 range.
40    pub name_index: u16,
41}
42
43impl FromData for SettingName {
44    const SIZE: usize = 4;
45
46    #[inline]
47    fn parse(data: &[u8]) -> Option<Self> {
48        let mut s = Stream::new(data);
49        Some(SettingName {
50            setting: s.read::<u16>()?,
51            name_index: s.read::<u16>()?,
52        })
53    }
54}
55
56/// A feature names.
57#[derive(Clone, Copy, Debug)]
58pub struct FeatureName<'a> {
59    /// The feature's ID.
60    pub feature: u16,
61    /// The feature's setting names.
62    pub setting_names: LazyArray16<'a, SettingName>,
63    /// The index of the default setting in the `setting_names`.
64    pub default_setting_index: u8,
65    /// The feature's exclusive settings. If set, the feature settings are mutually exclusive.
66    pub exclusive: bool,
67    /// The `name` table index for the feature's name in a 256..32768 range.
68    pub name_index: u16,
69}
70
71/// A list of feature names.
72#[derive(Clone, Copy)]
73pub struct FeatureNames<'a> {
74    data: &'a [u8],
75    records: LazyArray16<'a, FeatureNameRecord>,
76}
77
78impl<'a> FeatureNames<'a> {
79    /// Returns a feature name at an index.
80    pub fn get(&self, index: u16) -> Option<FeatureName<'a>> {
81        let record = self.records.get(index)?;
82        let data = self.data.get(record.setting_table_offset.to_usize()..)?;
83        let mut s = Stream::new(data);
84        let setting_names = s.read_array16::<SettingName>(record.setting_table_records_count)?;
85        Some(FeatureName {
86            feature: record.feature,
87            setting_names,
88            default_setting_index: if record.flags & 0x40 != 0 {
89                record.default_setting_index
90            } else {
91                0
92            },
93            exclusive: record.flags & 0x80 != 0,
94            name_index: record.name_index,
95        })
96    }
97
98    /// Finds a feature name by ID.
99    pub fn find(&self, feature: u16) -> Option<FeatureName<'a>> {
100        let index = self
101            .records
102            .binary_search_by(|name| name.feature.cmp(&feature))
103            .map(|(i, _)| i)?;
104        self.get(index)
105    }
106
107    /// Returns the number of feature names.
108    pub fn len(&self) -> u16 {
109        self.records.len()
110    }
111
112    /// Checks if there are any feature names.
113    pub fn is_empty(&self) -> bool {
114        self.records.is_empty()
115    }
116}
117
118impl<'a> core::fmt::Debug for FeatureNames<'a> {
119    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
120        f.debug_list().entries(*self).finish()
121    }
122}
123
124impl<'a> IntoIterator for FeatureNames<'a> {
125    type Item = FeatureName<'a>;
126    type IntoIter = FeatureNamesIter<'a>;
127
128    #[inline]
129    fn into_iter(self) -> Self::IntoIter {
130        FeatureNamesIter {
131            names: self,
132            index: 0,
133        }
134    }
135}
136
137/// An iterator over [`FeatureNames`].
138#[allow(missing_debug_implementations)]
139pub struct FeatureNamesIter<'a> {
140    names: FeatureNames<'a>,
141    index: u16,
142}
143
144impl<'a> Iterator for FeatureNamesIter<'a> {
145    type Item = FeatureName<'a>;
146
147    fn next(&mut self) -> Option<Self::Item> {
148        if self.index < self.names.len() {
149            self.index += 1;
150            self.names.get(self.index - 1)
151        } else {
152            None
153        }
154    }
155}
156
157/// A [Feature Name Table](
158/// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html).
159#[derive(Clone, Copy, Debug)]
160pub struct Table<'a> {
161    /// A list of feature names. Sorted by `FeatureName.feature`.
162    pub names: FeatureNames<'a>,
163}
164
165impl<'a> Table<'a> {
166    /// Parses a table from raw data.
167    pub fn parse(data: &'a [u8]) -> Option<Self> {
168        let mut s = Stream::new(data);
169
170        let version = s.read::<u32>()?;
171        if version != 0x00010000 {
172            return None;
173        }
174
175        let count = s.read::<u16>()?;
176        s.advance_checked(6)?; // reserved
177        let records = s.read_array16::<FeatureNameRecord>(count)?;
178
179        Some(Table {
180            names: FeatureNames { data, records },
181        })
182    }
183}