ttf_parser/tables/
feat.rs1use 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    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
35#[derive(Clone, Copy, Debug)]
37pub struct SettingName {
38    pub setting: u16,
40    pub name_index: u16,
42}
43
44impl FromData for SettingName {
45    const SIZE: usize = 4;
46
47    #[inline]
48    fn parse(data: &[u8]) -> Option<Self> {
49        let mut s = Stream::new(data);
50        Some(SettingName {
51            setting: s.read::<u16>()?,
52            name_index: s.read::<u16>()?,
53        })
54    }
55}
56
57
58#[derive(Clone, Copy, Debug)]
60pub struct FeatureName<'a> {
61    pub feature: u16,
63    pub setting_names: LazyArray16<'a, SettingName>,
65    pub default_setting_index: u8,
67    pub exclusive: bool,
69    pub name_index: u16,
71}
72
73
74#[derive(Clone, Copy)]
76pub struct FeatureNames<'a> {
77    data: &'a [u8],
78    records: LazyArray16<'a, FeatureNameRecord>,
79}
80
81impl<'a> FeatureNames<'a> {
82    pub fn get(&self, index: u16) -> Option<FeatureName<'a>> {
84        let record = self.records.get(index)?;
85        let data = self.data.get(record.setting_table_offset.to_usize()..)?;
86        let mut s = Stream::new(data);
87        let setting_names = s.read_array16::<SettingName>(record.setting_table_records_count)?;
88        Some(FeatureName {
89            feature: record.feature,
90            setting_names,
91            default_setting_index:
92                if record.flags & 0x40 != 0 { record.default_setting_index } else { 0 },
93            exclusive: record.flags & 0x80 != 0,
94            name_index: record.name_index,
95        })
96    }
97
98    pub fn find(&self, feature: u16) -> Option<FeatureName<'a>> {
100        let index = self.records
101            .binary_search_by(|name| name.feature.cmp(&feature)).map(|(i, _)| i)?;
102        self.get(index)
103    }
104
105    pub fn len(&self) -> u16 {
107        self.records.len()
108    }
109}
110
111impl<'a> core::fmt::Debug for FeatureNames<'a> {
112    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
113        f.debug_list().entries(self.into_iter()).finish()
114    }
115}
116
117impl<'a> IntoIterator for FeatureNames<'a> {
118    type Item = FeatureName<'a>;
119    type IntoIter = FeatureNamesIter<'a>;
120
121    #[inline]
122    fn into_iter(self) -> Self::IntoIter {
123        FeatureNamesIter {
124            names: self,
125            index: 0,
126        }
127    }
128}
129
130#[allow(missing_debug_implementations)]
132pub struct FeatureNamesIter<'a> {
133    names: FeatureNames<'a>,
134    index: u16,
135}
136
137impl<'a> Iterator for FeatureNamesIter<'a> {
138    type Item = FeatureName<'a>;
139
140    fn next(&mut self) -> Option<Self::Item> {
141        if self.index < self.names.len() {
142            self.index += 1;
143            self.names.get(self.index - 1)
144        } else {
145            None
146        }
147    }
148}
149
150
151#[derive(Clone, Copy, Debug)]
154pub struct Table<'a> {
155    pub names: FeatureNames<'a>,
157}
158
159impl<'a> Table<'a> {
160    pub fn parse(data: &'a [u8]) -> Option<Self> {
162        let mut s = Stream::new(data);
163
164        let version = s.read::<u32>()?;
165        if version != 0x00010000 {
166            return None;
167        }
168
169        let count = s.read::<u16>()?;
170        s.advance_checked(6)?; let records = s.read_array16::<FeatureNameRecord>(count)?;
172
173        Some(Table {
174            names: FeatureNames {
175                data,
176                records,
177            }
178        })
179    }
180}