read_fonts/
table_provider.rs

1//! a trait for things that can serve font tables
2
3use types::{BigEndian, Tag};
4
5use crate::{tables, FontData, FontRead, ReadError};
6
7/// A table that has an associated tag.
8///
9/// This is true of top-level tables, but not their various subtables.
10pub trait TopLevelTable {
11    /// The table's tag.
12    const TAG: Tag;
13}
14
15/// An interface for accessing tables from a font (or font-like object)
16pub trait TableProvider<'a> {
17    fn data_for_tag(&self, tag: Tag) -> Option<FontData<'a>>;
18
19    fn expect_data_for_tag(&self, tag: Tag) -> Result<FontData<'a>, ReadError> {
20        self.data_for_tag(tag).ok_or(ReadError::TableIsMissing(tag))
21    }
22
23    fn expect_table<T: TopLevelTable + FontRead<'a>>(&self) -> Result<T, ReadError> {
24        self.expect_data_for_tag(T::TAG).and_then(FontRead::read)
25    }
26
27    fn head(&self) -> Result<tables::head::Head<'a>, ReadError> {
28        self.expect_table()
29    }
30
31    fn name(&self) -> Result<tables::name::Name<'a>, ReadError> {
32        self.expect_table()
33    }
34
35    fn hhea(&self) -> Result<tables::hhea::Hhea<'a>, ReadError> {
36        self.expect_table()
37    }
38
39    fn vhea(&self) -> Result<tables::vhea::Vhea<'a>, ReadError> {
40        self.expect_table()
41    }
42
43    fn hmtx(&self) -> Result<tables::hmtx::Hmtx<'a>, ReadError> {
44        //FIXME: should we make the user pass these in?
45        let num_glyphs = self.maxp().map(|maxp| maxp.num_glyphs())?;
46        let number_of_h_metrics = self.hhea().map(|hhea| hhea.number_of_h_metrics())?;
47        let data = self.expect_data_for_tag(tables::hmtx::Hmtx::TAG)?;
48        tables::hmtx::Hmtx::read(data, number_of_h_metrics, num_glyphs)
49    }
50
51    fn hdmx(&self) -> Result<tables::hdmx::Hdmx<'a>, ReadError> {
52        let num_glyphs = self.maxp().map(|maxp| maxp.num_glyphs())?;
53        let data = self.expect_data_for_tag(tables::hdmx::Hdmx::TAG)?;
54        tables::hdmx::Hdmx::read(data, num_glyphs)
55    }
56
57    fn vmtx(&self) -> Result<tables::vmtx::Vmtx<'a>, ReadError> {
58        //FIXME: should we make the user pass these in?
59        let num_glyphs = self.maxp().map(|maxp| maxp.num_glyphs())?;
60        let number_of_v_metrics = self.vhea().map(|vhea| vhea.number_of_long_ver_metrics())?;
61        let data = self.expect_data_for_tag(tables::vmtx::Vmtx::TAG)?;
62        tables::vmtx::Vmtx::read(data, number_of_v_metrics, num_glyphs)
63    }
64
65    fn vorg(&self) -> Result<tables::vorg::Vorg<'a>, ReadError> {
66        self.expect_table()
67    }
68
69    fn fvar(&self) -> Result<tables::fvar::Fvar<'a>, ReadError> {
70        self.expect_table()
71    }
72
73    fn avar(&self) -> Result<tables::avar::Avar<'a>, ReadError> {
74        self.expect_table()
75    }
76
77    fn hvar(&self) -> Result<tables::hvar::Hvar<'a>, ReadError> {
78        self.expect_table()
79    }
80
81    fn vvar(&self) -> Result<tables::vvar::Vvar<'a>, ReadError> {
82        self.expect_table()
83    }
84
85    fn mvar(&self) -> Result<tables::mvar::Mvar<'a>, ReadError> {
86        self.expect_table()
87    }
88
89    fn maxp(&self) -> Result<tables::maxp::Maxp<'a>, ReadError> {
90        self.expect_table()
91    }
92
93    fn os2(&self) -> Result<tables::os2::Os2<'a>, ReadError> {
94        self.expect_table()
95    }
96
97    fn post(&self) -> Result<tables::post::Post<'a>, ReadError> {
98        self.expect_table()
99    }
100
101    fn gasp(&self) -> Result<tables::gasp::Gasp<'a>, ReadError> {
102        self.expect_table()
103    }
104
105    /// is_long can be optionally provided, if known, otherwise we look it up in head.
106    fn loca(&self, is_long: impl Into<Option<bool>>) -> Result<tables::loca::Loca<'a>, ReadError> {
107        let is_long = match is_long.into() {
108            Some(val) => val,
109            None => self.head()?.index_to_loc_format() == 1,
110        };
111        let data = self.expect_data_for_tag(tables::loca::Loca::TAG)?;
112        tables::loca::Loca::read(data, is_long)
113    }
114
115    fn glyf(&self) -> Result<tables::glyf::Glyf<'a>, ReadError> {
116        self.expect_table()
117    }
118
119    fn gvar(&self) -> Result<tables::gvar::Gvar<'a>, ReadError> {
120        self.expect_table()
121    }
122
123    /// Returns the array of entries for the control value table which is used
124    /// for TrueType hinting.
125    fn cvt(&self) -> Result<&'a [BigEndian<i16>], ReadError> {
126        let table_data = self.expect_data_for_tag(Tag::new(b"cvt "))?;
127        table_data.read_array(0..table_data.len())
128    }
129
130    fn cvar(&self) -> Result<tables::cvar::Cvar<'a>, ReadError> {
131        self.expect_table()
132    }
133
134    fn cff(&self) -> Result<tables::cff::Cff<'a>, ReadError> {
135        self.expect_table()
136    }
137
138    fn cff2(&self) -> Result<tables::cff2::Cff2<'a>, ReadError> {
139        self.expect_table()
140    }
141
142    fn cmap(&self) -> Result<tables::cmap::Cmap<'a>, ReadError> {
143        self.expect_table()
144    }
145
146    fn gdef(&self) -> Result<tables::gdef::Gdef<'a>, ReadError> {
147        self.expect_table()
148    }
149
150    fn gpos(&self) -> Result<tables::gpos::Gpos<'a>, ReadError> {
151        self.expect_table()
152    }
153
154    fn gsub(&self) -> Result<tables::gsub::Gsub<'a>, ReadError> {
155        self.expect_table()
156    }
157
158    fn feat(&self) -> Result<tables::feat::Feat<'a>, ReadError> {
159        self.expect_table()
160    }
161
162    fn ltag(&self) -> Result<tables::ltag::Ltag<'a>, ReadError> {
163        self.expect_table()
164    }
165
166    fn ankr(&self) -> Result<tables::ankr::Ankr<'a>, ReadError> {
167        self.expect_table()
168    }
169
170    fn colr(&self) -> Result<tables::colr::Colr<'a>, ReadError> {
171        self.expect_table()
172    }
173
174    fn cpal(&self) -> Result<tables::cpal::Cpal<'a>, ReadError> {
175        self.expect_table()
176    }
177
178    fn cblc(&self) -> Result<tables::cblc::Cblc<'a>, ReadError> {
179        self.expect_table()
180    }
181
182    fn cbdt(&self) -> Result<tables::cbdt::Cbdt<'a>, ReadError> {
183        self.expect_table()
184    }
185
186    fn eblc(&self) -> Result<tables::eblc::Eblc<'a>, ReadError> {
187        self.expect_table()
188    }
189
190    fn ebdt(&self) -> Result<tables::ebdt::Ebdt<'a>, ReadError> {
191        self.expect_table()
192    }
193
194    fn sbix(&self) -> Result<tables::sbix::Sbix<'a>, ReadError> {
195        // should we make the user pass this in?
196        let num_glyphs = self.maxp().map(|maxp| maxp.num_glyphs())?;
197        let data = self.expect_data_for_tag(tables::sbix::Sbix::TAG)?;
198        tables::sbix::Sbix::read(data, num_glyphs)
199    }
200
201    fn stat(&self) -> Result<tables::stat::Stat<'a>, ReadError> {
202        self.expect_table()
203    }
204
205    fn svg(&self) -> Result<tables::svg::Svg<'a>, ReadError> {
206        self.expect_table()
207    }
208
209    fn varc(&self) -> Result<tables::varc::Varc<'a>, ReadError> {
210        self.expect_table()
211    }
212
213    #[cfg(feature = "ift")]
214    fn ift(&self) -> Result<tables::ift::Ift<'a>, ReadError> {
215        self.expect_data_for_tag(tables::ift::IFT_TAG)
216            .and_then(FontRead::read)
217    }
218
219    #[cfg(feature = "ift")]
220    fn iftx(&self) -> Result<tables::ift::Ift<'a>, ReadError> {
221        self.expect_data_for_tag(tables::ift::IFTX_TAG)
222            .and_then(FontRead::read)
223    }
224
225    fn meta(&self) -> Result<tables::meta::Meta<'a>, ReadError> {
226        self.expect_table()
227    }
228
229    fn base(&self) -> Result<tables::base::Base<'a>, ReadError> {
230        self.expect_table()
231    }
232}
233
234#[cfg(test)]
235mod tests {
236
237    use super::*;
238
239    /// https://github.com/googlefonts/fontations/issues/105
240    #[test]
241    fn bug_105() {
242        // serve some dummy versions of the tables used to compute hmtx. The only
243        // fields that matter are maxp::num_glyphs and hhea::number_of_h_metrics,
244        // everything else is zero'd out
245        struct DummyProvider;
246        impl TableProvider<'static> for DummyProvider {
247            fn data_for_tag(&self, tag: Tag) -> Option<FontData<'static>> {
248                if tag == Tag::new(b"maxp") {
249                    Some(FontData::new(&[
250                        0, 0, 0x50, 0, // version 0.5
251                        0, 3, // num_glyphs = 3
252                    ]))
253                } else if tag == Tag::new(b"hhea") {
254                    Some(FontData::new(&[
255                        0, 1, 0, 0, // version 1.0
256                        0, 0, 0, 0, // ascender/descender
257                        0, 0, 0, 0, // line gap/advance width
258                        0, 0, 0, 0, // min left/right side bearing
259                        0, 0, 0, 0, // x_max, caret_slope_rise
260                        0, 0, 0, 0, // caret_slope_run, caret_offset
261                        0, 0, 0, 0, // reserved1/2
262                        0, 0, 0, 0, // reserved 3/4
263                        0, 0, 0, 1, // metric format, number_of_h_metrics
264                    ]))
265                } else if tag == Tag::new(b"hmtx") {
266                    Some(FontData::new(&[
267                        0, 4, 0, 6, // LongHorMetric: 4, 6
268                        0, 30, 0, 111, // two lsb entries
269                    ]))
270                } else {
271                    None
272                }
273            }
274        }
275
276        let number_of_h_metrics = DummyProvider.hhea().unwrap().number_of_h_metrics();
277        let num_glyphs = DummyProvider.maxp().unwrap().num_glyphs();
278        let hmtx = DummyProvider.hmtx().unwrap();
279
280        assert_eq!(number_of_h_metrics, 1);
281        assert_eq!(num_glyphs, 3);
282        assert_eq!(hmtx.h_metrics().len(), 1);
283        assert_eq!(hmtx.left_side_bearings().len(), 2);
284    }
285}