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)] 6 use crate::codegen_prelude::*; 7 8 /// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory) 9 #[derive(Debug, Clone, Copy)] 10 #[doc(hidden)] 11 pub struct TableDirectoryMarker { 12 table_records_byte_len: usize, 13 } 14 15 impl TableDirectoryMarker { sfnt_version_byte_range(&self) -> Range<usize>16 fn sfnt_version_byte_range(&self) -> Range<usize> { 17 let start = 0; 18 start..start + u32::RAW_BYTE_LEN 19 } num_tables_byte_range(&self) -> Range<usize>20 fn num_tables_byte_range(&self) -> Range<usize> { 21 let start = self.sfnt_version_byte_range().end; 22 start..start + u16::RAW_BYTE_LEN 23 } search_range_byte_range(&self) -> Range<usize>24 fn search_range_byte_range(&self) -> Range<usize> { 25 let start = self.num_tables_byte_range().end; 26 start..start + u16::RAW_BYTE_LEN 27 } entry_selector_byte_range(&self) -> Range<usize>28 fn entry_selector_byte_range(&self) -> Range<usize> { 29 let start = self.search_range_byte_range().end; 30 start..start + u16::RAW_BYTE_LEN 31 } range_shift_byte_range(&self) -> Range<usize>32 fn range_shift_byte_range(&self) -> Range<usize> { 33 let start = self.entry_selector_byte_range().end; 34 start..start + u16::RAW_BYTE_LEN 35 } table_records_byte_range(&self) -> Range<usize>36 fn table_records_byte_range(&self) -> Range<usize> { 37 let start = self.range_shift_byte_range().end; 38 start..start + self.table_records_byte_len 39 } 40 } 41 42 impl<'a> FontRead<'a> for TableDirectory<'a> { read(data: FontData<'a>) -> Result<Self, ReadError>43 fn read(data: FontData<'a>) -> Result<Self, ReadError> { 44 let mut cursor = data.cursor(); 45 cursor.advance::<u32>(); 46 let num_tables: u16 = cursor.read()?; 47 cursor.advance::<u16>(); 48 cursor.advance::<u16>(); 49 cursor.advance::<u16>(); 50 let table_records_byte_len = num_tables as usize * TableRecord::RAW_BYTE_LEN; 51 cursor.advance_by(table_records_byte_len); 52 cursor.finish(TableDirectoryMarker { 53 table_records_byte_len, 54 }) 55 } 56 } 57 58 /// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory) 59 pub type TableDirectory<'a> = TableRef<'a, TableDirectoryMarker>; 60 61 impl<'a> TableDirectory<'a> { 62 /// 0x00010000 or 0x4F54544F sfnt_version(&self) -> u3263 pub fn sfnt_version(&self) -> u32 { 64 let range = self.shape.sfnt_version_byte_range(); 65 self.data.read_at(range.start).unwrap() 66 } 67 68 /// Number of tables. num_tables(&self) -> u1669 pub fn num_tables(&self) -> u16 { 70 let range = self.shape.num_tables_byte_range(); 71 self.data.read_at(range.start).unwrap() 72 } 73 search_range(&self) -> u1674 pub fn search_range(&self) -> u16 { 75 let range = self.shape.search_range_byte_range(); 76 self.data.read_at(range.start).unwrap() 77 } 78 entry_selector(&self) -> u1679 pub fn entry_selector(&self) -> u16 { 80 let range = self.shape.entry_selector_byte_range(); 81 self.data.read_at(range.start).unwrap() 82 } 83 range_shift(&self) -> u1684 pub fn range_shift(&self) -> u16 { 85 let range = self.shape.range_shift_byte_range(); 86 self.data.read_at(range.start).unwrap() 87 } 88 89 /// Table records array—one for each top-level table in the font table_records(&self) -> &'a [TableRecord]90 pub fn table_records(&self) -> &'a [TableRecord] { 91 let range = self.shape.table_records_byte_range(); 92 self.data.read_array(range).unwrap() 93 } 94 } 95 96 #[cfg(feature = "traversal")] 97 impl<'a> SomeTable<'a> for TableDirectory<'a> { type_name(&self) -> &str98 fn type_name(&self) -> &str { 99 "TableDirectory" 100 } get_field(&self, idx: usize) -> Option<Field<'a>>101 fn get_field(&self, idx: usize) -> Option<Field<'a>> { 102 match idx { 103 0usize => Some(Field::new("sfnt_version", self.sfnt_version())), 104 1usize => Some(Field::new("num_tables", self.num_tables())), 105 2usize => Some(Field::new("search_range", self.search_range())), 106 3usize => Some(Field::new("entry_selector", self.entry_selector())), 107 4usize => Some(Field::new("range_shift", self.range_shift())), 108 5usize => Some(Field::new( 109 "table_records", 110 traversal::FieldType::array_of_records( 111 stringify!(TableRecord), 112 self.table_records(), 113 self.offset_data(), 114 ), 115 )), 116 _ => None, 117 } 118 } 119 } 120 121 #[cfg(feature = "traversal")] 122 impl<'a> std::fmt::Debug for TableDirectory<'a> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 124 (self as &dyn SomeTable<'a>).fmt(f) 125 } 126 } 127 128 /// Record for a table in a font. 129 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 130 #[repr(C)] 131 #[repr(packed)] 132 pub struct TableRecord { 133 /// Table identifier. 134 pub tag: BigEndian<Tag>, 135 /// Checksum for the table. 136 pub checksum: BigEndian<u32>, 137 /// Offset from the beginning of the font data. 138 pub offset: BigEndian<u32>, 139 /// Length of the table. 140 pub length: BigEndian<u32>, 141 } 142 143 impl TableRecord { 144 /// Table identifier. tag(&self) -> Tag145 pub fn tag(&self) -> Tag { 146 self.tag.get() 147 } 148 149 /// Checksum for the table. checksum(&self) -> u32150 pub fn checksum(&self) -> u32 { 151 self.checksum.get() 152 } 153 154 /// Offset from the beginning of the font data. offset(&self) -> u32155 pub fn offset(&self) -> u32 { 156 self.offset.get() 157 } 158 159 /// Length of the table. length(&self) -> u32160 pub fn length(&self) -> u32 { 161 self.length.get() 162 } 163 } 164 165 impl FixedSize for TableRecord { 166 const RAW_BYTE_LEN: usize = 167 Tag::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN; 168 } 169 170 impl sealed::Sealed for TableRecord {} 171 172 /// SAFETY: see the [`FromBytes`] trait documentation. 173 unsafe impl FromBytes for TableRecord { this_trait_should_only_be_implemented_in_generated_code()174 fn this_trait_should_only_be_implemented_in_generated_code() {} 175 } 176 177 #[cfg(feature = "traversal")] 178 impl<'a> SomeRecord<'a> for TableRecord { traverse(self, data: FontData<'a>) -> RecordResolver<'a>179 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> { 180 RecordResolver { 181 name: "TableRecord", 182 get_field: Box::new(move |idx, _data| match idx { 183 0usize => Some(Field::new("tag", self.tag())), 184 1usize => Some(Field::new("checksum", self.checksum())), 185 2usize => Some(Field::new("offset", self.offset())), 186 3usize => Some(Field::new("length", self.length())), 187 _ => None, 188 }), 189 data, 190 } 191 } 192 } 193 194 /// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header) 195 #[derive(Debug, Clone, Copy)] 196 #[doc(hidden)] 197 pub struct TTCHeaderMarker { 198 table_directory_offsets_byte_len: usize, 199 dsig_tag_byte_start: Option<usize>, 200 dsig_length_byte_start: Option<usize>, 201 dsig_offset_byte_start: Option<usize>, 202 } 203 204 impl TTCHeaderMarker { ttc_tag_byte_range(&self) -> Range<usize>205 fn ttc_tag_byte_range(&self) -> Range<usize> { 206 let start = 0; 207 start..start + Tag::RAW_BYTE_LEN 208 } version_byte_range(&self) -> Range<usize>209 fn version_byte_range(&self) -> Range<usize> { 210 let start = self.ttc_tag_byte_range().end; 211 start..start + MajorMinor::RAW_BYTE_LEN 212 } num_fonts_byte_range(&self) -> Range<usize>213 fn num_fonts_byte_range(&self) -> Range<usize> { 214 let start = self.version_byte_range().end; 215 start..start + u32::RAW_BYTE_LEN 216 } table_directory_offsets_byte_range(&self) -> Range<usize>217 fn table_directory_offsets_byte_range(&self) -> Range<usize> { 218 let start = self.num_fonts_byte_range().end; 219 start..start + self.table_directory_offsets_byte_len 220 } dsig_tag_byte_range(&self) -> Option<Range<usize>>221 fn dsig_tag_byte_range(&self) -> Option<Range<usize>> { 222 let start = self.dsig_tag_byte_start?; 223 Some(start..start + u32::RAW_BYTE_LEN) 224 } dsig_length_byte_range(&self) -> Option<Range<usize>>225 fn dsig_length_byte_range(&self) -> Option<Range<usize>> { 226 let start = self.dsig_length_byte_start?; 227 Some(start..start + u32::RAW_BYTE_LEN) 228 } dsig_offset_byte_range(&self) -> Option<Range<usize>>229 fn dsig_offset_byte_range(&self) -> Option<Range<usize>> { 230 let start = self.dsig_offset_byte_start?; 231 Some(start..start + u32::RAW_BYTE_LEN) 232 } 233 } 234 235 impl<'a> FontRead<'a> for TTCHeader<'a> { read(data: FontData<'a>) -> Result<Self, ReadError>236 fn read(data: FontData<'a>) -> Result<Self, ReadError> { 237 let mut cursor = data.cursor(); 238 cursor.advance::<Tag>(); 239 let version: MajorMinor = cursor.read()?; 240 let num_fonts: u32 = cursor.read()?; 241 let table_directory_offsets_byte_len = num_fonts as usize * u32::RAW_BYTE_LEN; 242 cursor.advance_by(table_directory_offsets_byte_len); 243 let dsig_tag_byte_start = version 244 .compatible((2, 0)) 245 .then(|| cursor.position()) 246 .transpose()?; 247 version.compatible((2, 0)).then(|| cursor.advance::<u32>()); 248 let dsig_length_byte_start = version 249 .compatible((2, 0)) 250 .then(|| cursor.position()) 251 .transpose()?; 252 version.compatible((2, 0)).then(|| cursor.advance::<u32>()); 253 let dsig_offset_byte_start = version 254 .compatible((2, 0)) 255 .then(|| cursor.position()) 256 .transpose()?; 257 version.compatible((2, 0)).then(|| cursor.advance::<u32>()); 258 cursor.finish(TTCHeaderMarker { 259 table_directory_offsets_byte_len, 260 dsig_tag_byte_start, 261 dsig_length_byte_start, 262 dsig_offset_byte_start, 263 }) 264 } 265 } 266 267 /// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header) 268 pub type TTCHeader<'a> = TableRef<'a, TTCHeaderMarker>; 269 270 impl<'a> TTCHeader<'a> { 271 /// Font Collection ID string: \"ttcf\" ttc_tag(&self) -> Tag272 pub fn ttc_tag(&self) -> Tag { 273 let range = self.shape.ttc_tag_byte_range(); 274 self.data.read_at(range.start).unwrap() 275 } 276 277 /// Major/minor version of the TTC Header version(&self) -> MajorMinor278 pub fn version(&self) -> MajorMinor { 279 let range = self.shape.version_byte_range(); 280 self.data.read_at(range.start).unwrap() 281 } 282 283 /// Number of fonts in TTC num_fonts(&self) -> u32284 pub fn num_fonts(&self) -> u32 { 285 let range = self.shape.num_fonts_byte_range(); 286 self.data.read_at(range.start).unwrap() 287 } 288 289 /// Array of offsets to the TableDirectory for each font from the beginning of the file table_directory_offsets(&self) -> &'a [BigEndian<u32>]290 pub fn table_directory_offsets(&self) -> &'a [BigEndian<u32>] { 291 let range = self.shape.table_directory_offsets_byte_range(); 292 self.data.read_array(range).unwrap() 293 } 294 295 /// Tag indicating that a DSIG table exists, 0x44534947 ('DSIG') (null if no signature) dsig_tag(&self) -> Option<u32>296 pub fn dsig_tag(&self) -> Option<u32> { 297 let range = self.shape.dsig_tag_byte_range()?; 298 Some(self.data.read_at(range.start).unwrap()) 299 } 300 301 /// The length (in bytes) of the DSIG table (null if no signature) dsig_length(&self) -> Option<u32>302 pub fn dsig_length(&self) -> Option<u32> { 303 let range = self.shape.dsig_length_byte_range()?; 304 Some(self.data.read_at(range.start).unwrap()) 305 } 306 307 /// The offset (in bytes) of the DSIG table from the beginning of the TTC file (null if no signature) dsig_offset(&self) -> Option<u32>308 pub fn dsig_offset(&self) -> Option<u32> { 309 let range = self.shape.dsig_offset_byte_range()?; 310 Some(self.data.read_at(range.start).unwrap()) 311 } 312 } 313 314 #[cfg(feature = "traversal")] 315 impl<'a> SomeTable<'a> for TTCHeader<'a> { type_name(&self) -> &str316 fn type_name(&self) -> &str { 317 "TTCHeader" 318 } get_field(&self, idx: usize) -> Option<Field<'a>>319 fn get_field(&self, idx: usize) -> Option<Field<'a>> { 320 let version = self.version(); 321 match idx { 322 0usize => Some(Field::new("ttc_tag", self.ttc_tag())), 323 1usize => Some(Field::new("version", self.version())), 324 2usize => Some(Field::new("num_fonts", self.num_fonts())), 325 3usize => Some(Field::new( 326 "table_directory_offsets", 327 self.table_directory_offsets(), 328 )), 329 4usize if version.compatible((2, 0)) => { 330 Some(Field::new("dsig_tag", self.dsig_tag().unwrap())) 331 } 332 5usize if version.compatible((2, 0)) => { 333 Some(Field::new("dsig_length", self.dsig_length().unwrap())) 334 } 335 6usize if version.compatible((2, 0)) => { 336 Some(Field::new("dsig_offset", self.dsig_offset().unwrap())) 337 } 338 _ => None, 339 } 340 } 341 } 342 343 #[cfg(feature = "traversal")] 344 impl<'a> std::fmt::Debug for TTCHeader<'a> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result345 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 346 (self as &dyn SomeTable<'a>).fmt(f) 347 } 348 } 349