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