1 //! a trait for things that can serve font tables 2 3 use types::Tag; 4 5 use 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. 10 pub 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) 16 pub trait TableProvider<'a> { data_for_tag(&self, tag: Tag) -> Option<FontData<'a>>17 fn data_for_tag(&self, tag: Tag) -> Option<FontData<'a>>; 18 expect_data_for_tag(&self, tag: Tag) -> Result<FontData<'a>, ReadError>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 expect_table<T: TopLevelTable + FontRead<'a>>(&self) -> Result<T, ReadError>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 head(&self) -> Result<tables::head::Head<'a>, ReadError>27 fn head(&self) -> Result<tables::head::Head<'a>, ReadError> { 28 self.expect_table() 29 } 30 name(&self) -> Result<tables::name::Name<'a>, ReadError>31 fn name(&self) -> Result<tables::name::Name<'a>, ReadError> { 32 self.expect_table() 33 } 34 hhea(&self) -> Result<tables::hhea::Hhea<'a>, ReadError>35 fn hhea(&self) -> Result<tables::hhea::Hhea<'a>, ReadError> { 36 self.expect_table() 37 } 38 vhea(&self) -> Result<tables::vhea::Vhea<'a>, ReadError>39 fn vhea(&self) -> Result<tables::vhea::Vhea<'a>, ReadError> { 40 self.expect_table() 41 } 42 hmtx(&self) -> Result<tables::hmtx::Hmtx<'a>, ReadError>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_long_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 vmtx(&self) -> Result<tables::vmtx::Vmtx<'a>, ReadError>51 fn vmtx(&self) -> Result<tables::vmtx::Vmtx<'a>, ReadError> { 52 //FIXME: should we make the user pass these in? 53 let num_glyphs = self.maxp().map(|maxp| maxp.num_glyphs())?; 54 let number_of_v_metrics = self.vhea().map(|vhea| vhea.number_of_long_ver_metrics())?; 55 let data = self.expect_data_for_tag(tables::vmtx::Vmtx::TAG)?; 56 tables::vmtx::Vmtx::read(data, number_of_v_metrics, num_glyphs) 57 } 58 fvar(&self) -> Result<tables::fvar::Fvar<'a>, ReadError>59 fn fvar(&self) -> Result<tables::fvar::Fvar<'a>, ReadError> { 60 self.expect_table() 61 } 62 avar(&self) -> Result<tables::avar::Avar<'a>, ReadError>63 fn avar(&self) -> Result<tables::avar::Avar<'a>, ReadError> { 64 self.expect_table() 65 } 66 hvar(&self) -> Result<tables::hvar::Hvar<'a>, ReadError>67 fn hvar(&self) -> Result<tables::hvar::Hvar<'a>, ReadError> { 68 self.expect_table() 69 } 70 vvar(&self) -> Result<tables::vvar::Vvar<'a>, ReadError>71 fn vvar(&self) -> Result<tables::vvar::Vvar<'a>, ReadError> { 72 self.expect_table() 73 } 74 mvar(&self) -> Result<tables::mvar::Mvar<'a>, ReadError>75 fn mvar(&self) -> Result<tables::mvar::Mvar<'a>, ReadError> { 76 self.expect_table() 77 } 78 maxp(&self) -> Result<tables::maxp::Maxp<'a>, ReadError>79 fn maxp(&self) -> Result<tables::maxp::Maxp<'a>, ReadError> { 80 self.expect_table() 81 } 82 os2(&self) -> Result<tables::os2::Os2<'a>, ReadError>83 fn os2(&self) -> Result<tables::os2::Os2<'a>, ReadError> { 84 self.expect_table() 85 } 86 post(&self) -> Result<tables::post::Post<'a>, ReadError>87 fn post(&self) -> Result<tables::post::Post<'a>, ReadError> { 88 self.expect_table() 89 } 90 91 /// is_long can be optionally provided, if known, otherwise we look it up in head. loca(&self, is_long: impl Into<Option<bool>>) -> Result<tables::loca::Loca<'a>, ReadError>92 fn loca(&self, is_long: impl Into<Option<bool>>) -> Result<tables::loca::Loca<'a>, ReadError> { 93 let is_long = match is_long.into() { 94 Some(val) => val, 95 None => self.head()?.index_to_loc_format() == 1, 96 }; 97 let data = self.expect_data_for_tag(tables::loca::Loca::TAG)?; 98 tables::loca::Loca::read(data, is_long) 99 } 100 glyf(&self) -> Result<tables::glyf::Glyf<'a>, ReadError>101 fn glyf(&self) -> Result<tables::glyf::Glyf<'a>, ReadError> { 102 self.expect_table() 103 } 104 gvar(&self) -> Result<tables::gvar::Gvar<'a>, ReadError>105 fn gvar(&self) -> Result<tables::gvar::Gvar<'a>, ReadError> { 106 self.expect_table() 107 } 108 cff(&self) -> Result<tables::cff::Cff<'a>, ReadError>109 fn cff(&self) -> Result<tables::cff::Cff<'a>, ReadError> { 110 self.expect_table() 111 } 112 cff2(&self) -> Result<tables::cff2::Cff2<'a>, ReadError>113 fn cff2(&self) -> Result<tables::cff2::Cff2<'a>, ReadError> { 114 self.expect_table() 115 } 116 cmap(&self) -> Result<tables::cmap::Cmap<'a>, ReadError>117 fn cmap(&self) -> Result<tables::cmap::Cmap<'a>, ReadError> { 118 self.expect_table() 119 } 120 gdef(&self) -> Result<tables::gdef::Gdef<'a>, ReadError>121 fn gdef(&self) -> Result<tables::gdef::Gdef<'a>, ReadError> { 122 self.expect_table() 123 } 124 gpos(&self) -> Result<tables::gpos::Gpos<'a>, ReadError>125 fn gpos(&self) -> Result<tables::gpos::Gpos<'a>, ReadError> { 126 self.expect_table() 127 } 128 gsub(&self) -> Result<tables::gsub::Gsub<'a>, ReadError>129 fn gsub(&self) -> Result<tables::gsub::Gsub<'a>, ReadError> { 130 self.expect_table() 131 } 132 colr(&self) -> Result<tables::colr::Colr<'a>, ReadError>133 fn colr(&self) -> Result<tables::colr::Colr<'a>, ReadError> { 134 self.expect_table() 135 } 136 cpal(&self) -> Result<tables::cpal::Cpal<'a>, ReadError>137 fn cpal(&self) -> Result<tables::cpal::Cpal<'a>, ReadError> { 138 self.expect_table() 139 } 140 cblc(&self) -> Result<tables::cblc::Cblc<'a>, ReadError>141 fn cblc(&self) -> Result<tables::cblc::Cblc<'a>, ReadError> { 142 self.expect_table() 143 } 144 cbdt(&self) -> Result<tables::cbdt::Cbdt<'a>, ReadError>145 fn cbdt(&self) -> Result<tables::cbdt::Cbdt<'a>, ReadError> { 146 self.expect_table() 147 } 148 eblc(&self) -> Result<tables::eblc::Eblc<'a>, ReadError>149 fn eblc(&self) -> Result<tables::eblc::Eblc<'a>, ReadError> { 150 self.expect_table() 151 } 152 ebdt(&self) -> Result<tables::ebdt::Ebdt<'a>, ReadError>153 fn ebdt(&self) -> Result<tables::ebdt::Ebdt<'a>, ReadError> { 154 self.expect_table() 155 } 156 sbix(&self) -> Result<tables::sbix::Sbix<'a>, ReadError>157 fn sbix(&self) -> Result<tables::sbix::Sbix<'a>, ReadError> { 158 // should we make the user pass this in? 159 let num_glyphs = self.maxp().map(|maxp| maxp.num_glyphs())?; 160 let data = self.expect_data_for_tag(tables::sbix::Sbix::TAG)?; 161 tables::sbix::Sbix::read(data, num_glyphs) 162 } 163 stat(&self) -> Result<tables::stat::Stat<'a>, ReadError>164 fn stat(&self) -> Result<tables::stat::Stat<'a>, ReadError> { 165 self.expect_table() 166 } 167 } 168 169 #[cfg(test)] 170 mod tests { 171 172 use super::*; 173 174 /// https://github.com/googlefonts/fontations/issues/105 175 #[test] bug_105()176 fn bug_105() { 177 // serve some dummy versions of the tables used to compute hmtx. The only 178 // fields that matter are maxp::num_glyphs and hhea::number_of_h_metrics, 179 // everything else is zero'd out 180 struct DummyProvider; 181 impl TableProvider<'static> for DummyProvider { 182 fn data_for_tag(&self, tag: Tag) -> Option<FontData<'static>> { 183 if tag == Tag::new(b"maxp") { 184 Some(FontData::new(&[ 185 0, 0, 0x50, 0, // version 0.5 186 0, 3, // num_glyphs = 3 187 ])) 188 } else if tag == Tag::new(b"hhea") { 189 Some(FontData::new(&[ 190 0, 1, 0, 0, // version 1.0 191 0, 0, 0, 0, // ascender/descender 192 0, 0, 0, 0, // line gap/advance width 193 0, 0, 0, 0, // min left/right side bearing 194 0, 0, 0, 0, // x_max, caret_slope_rise 195 0, 0, 0, 0, // caret_slope_run, caret_offset 196 0, 0, 0, 0, // reserved1/2 197 0, 0, 0, 0, // reserved 3/4 198 0, 0, 0, 1, // metric format, number_of_h_metrics 199 ])) 200 } else if tag == Tag::new(b"hmtx") { 201 Some(FontData::new(&[ 202 0, 4, 0, 6, // LongHorMetric: 4, 6 203 0, 30, 0, 111, // two lsb entries 204 ])) 205 } else { 206 None 207 } 208 } 209 } 210 211 let number_of_h_metrics = DummyProvider.hhea().unwrap().number_of_long_metrics(); 212 let num_glyphs = DummyProvider.maxp().unwrap().num_glyphs(); 213 let hmtx = DummyProvider.hmtx().unwrap(); 214 215 assert_eq!(number_of_h_metrics, 1); 216 assert_eq!(num_glyphs, 3); 217 assert_eq!(hmtx.h_metrics().len(), 1); 218 assert_eq!(hmtx.left_side_bearings().len(), 2); 219 } 220 } 221