read_fonts/generated/
font.rs1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for TableDirectory<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.table_records_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl ReadArgs for TableDirectory<'_> {
19 type Args = ();
20}
21
22impl<'a> FontRead<'a> for TableDirectory<'a> {
23 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
24 #[allow(clippy::absurd_extreme_comparisons)]
25 if data.len() < Self::MIN_SIZE {
26 return Err(ReadError::OutOfBounds);
27 }
28 Ok(Self { data })
29 }
30}
31
32#[derive(Clone)]
34pub struct TableDirectory<'a> {
35 data: FontData<'a>,
36}
37
38#[allow(clippy::needless_lifetimes)]
39impl<'a> TableDirectory<'a> {
40 pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN
41 + u16::RAW_BYTE_LEN
42 + u16::RAW_BYTE_LEN
43 + u16::RAW_BYTE_LEN
44 + u16::RAW_BYTE_LEN);
45 basic_table_impls!(impl_the_methods);
46
47 pub fn sfnt_version(&self) -> u32 {
49 let range = self.sfnt_version_byte_range();
50 self.data.read_at(range.start).ok().unwrap()
51 }
52
53 pub fn num_tables(&self) -> u16 {
55 let range = self.num_tables_byte_range();
56 self.data.read_at(range.start).ok().unwrap()
57 }
58
59 pub fn search_range(&self) -> u16 {
60 let range = self.search_range_byte_range();
61 self.data.read_at(range.start).ok().unwrap()
62 }
63
64 pub fn entry_selector(&self) -> u16 {
65 let range = self.entry_selector_byte_range();
66 self.data.read_at(range.start).ok().unwrap()
67 }
68
69 pub fn range_shift(&self) -> u16 {
70 let range = self.range_shift_byte_range();
71 self.data.read_at(range.start).ok().unwrap()
72 }
73
74 pub fn table_records(&self) -> &'a [TableRecord] {
76 let range = self.table_records_byte_range();
77 self.data.read_array(range).ok().unwrap_or_default()
78 }
79
80 pub fn sfnt_version_byte_range(&self) -> Range<usize> {
81 let start = 0;
82 let end = start + u32::RAW_BYTE_LEN;
83 start..end
84 }
85
86 pub fn num_tables_byte_range(&self) -> Range<usize> {
87 let start = self.sfnt_version_byte_range().end;
88 let end = start + u16::RAW_BYTE_LEN;
89 start..end
90 }
91
92 pub fn search_range_byte_range(&self) -> Range<usize> {
93 let start = self.num_tables_byte_range().end;
94 let end = start + u16::RAW_BYTE_LEN;
95 start..end
96 }
97
98 pub fn entry_selector_byte_range(&self) -> Range<usize> {
99 let start = self.search_range_byte_range().end;
100 let end = start + u16::RAW_BYTE_LEN;
101 start..end
102 }
103
104 pub fn range_shift_byte_range(&self) -> Range<usize> {
105 let start = self.entry_selector_byte_range().end;
106 let end = start + u16::RAW_BYTE_LEN;
107 start..end
108 }
109
110 pub fn table_records_byte_range(&self) -> Range<usize> {
111 let num_tables = self.num_tables();
112 let start = self.range_shift_byte_range().end;
113 let end =
114 start + (transforms::to_usize(num_tables)).saturating_mul(TableRecord::RAW_BYTE_LEN);
115 start..end
116 }
117}
118
119const _: () = assert!(FontData::default_data_long_enough(TableDirectory::MIN_SIZE));
120
121impl Default for TableDirectory<'_> {
122 fn default() -> Self {
123 Self {
124 data: FontData::default_table_data(),
125 }
126 }
127}
128
129#[cfg(feature = "experimental_traverse")]
130impl<'a> SomeTable<'a> for TableDirectory<'a> {
131 fn type_name(&self) -> &str {
132 "TableDirectory"
133 }
134 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
135 match idx {
136 0usize => Some(Field::new("sfnt_version", self.sfnt_version())),
137 1usize => Some(Field::new("num_tables", self.num_tables())),
138 2usize => Some(Field::new("search_range", self.search_range())),
139 3usize => Some(Field::new("entry_selector", self.entry_selector())),
140 4usize => Some(Field::new("range_shift", self.range_shift())),
141 5usize => Some(Field::new(
142 "table_records",
143 traversal::FieldType::array_of_records(
144 stringify!(TableRecord),
145 self.table_records(),
146 self.offset_data(),
147 ),
148 )),
149 _ => None,
150 }
151 }
152}
153
154#[cfg(feature = "experimental_traverse")]
155#[allow(clippy::needless_lifetimes)]
156impl<'a> std::fmt::Debug for TableDirectory<'a> {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 (self as &dyn SomeTable<'a>).fmt(f)
159 }
160}
161
162#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
164#[repr(C)]
165#[repr(packed)]
166pub struct TableRecord {
167 pub tag: BigEndian<Tag>,
169 pub checksum: BigEndian<u32>,
171 pub offset: BigEndian<u32>,
173 pub length: BigEndian<u32>,
175}
176
177impl TableRecord {
178 pub fn tag(&self) -> Tag {
180 self.tag.get()
181 }
182
183 pub fn checksum(&self) -> u32 {
185 self.checksum.get()
186 }
187
188 pub fn offset(&self) -> u32 {
190 self.offset.get()
191 }
192
193 pub fn length(&self) -> u32 {
195 self.length.get()
196 }
197}
198
199impl FixedSize for TableRecord {
200 const RAW_BYTE_LEN: usize =
201 Tag::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
202}
203
204#[cfg(feature = "experimental_traverse")]
205impl<'a> SomeRecord<'a> for TableRecord {
206 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
207 RecordResolver {
208 name: "TableRecord",
209 get_field: Box::new(move |idx, _data| match idx {
210 0usize => Some(Field::new("tag", self.tag())),
211 1usize => Some(Field::new("checksum", self.checksum())),
212 2usize => Some(Field::new("offset", self.offset())),
213 3usize => Some(Field::new("length", self.length())),
214 _ => None,
215 }),
216 data,
217 }
218 }
219}
220
221impl<'a> MinByteRange<'a> for TTCHeader<'a> {
222 fn min_byte_range(&self) -> Range<usize> {
223 0..self.table_directory_offsets_byte_range().end
224 }
225 fn min_table_bytes(&self) -> &'a [u8] {
226 let range = self.min_byte_range();
227 self.data.as_bytes().get(range).unwrap_or_default()
228 }
229}
230
231impl ReadArgs for TTCHeader<'_> {
232 type Args = ();
233}
234
235impl<'a> FontRead<'a> for TTCHeader<'a> {
236 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
237 #[allow(clippy::absurd_extreme_comparisons)]
238 if data.len() < Self::MIN_SIZE {
239 return Err(ReadError::OutOfBounds);
240 }
241 Ok(Self { data })
242 }
243}
244
245#[derive(Clone)]
247pub struct TTCHeader<'a> {
248 data: FontData<'a>,
249}
250
251#[allow(clippy::needless_lifetimes)]
252impl<'a> TTCHeader<'a> {
253 pub const MIN_SIZE: usize = (Tag::RAW_BYTE_LEN + MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
254 basic_table_impls!(impl_the_methods);
255
256 pub fn ttc_tag(&self) -> Tag {
258 let range = self.ttc_tag_byte_range();
259 self.data.read_at(range.start).ok().unwrap()
260 }
261
262 pub fn version(&self) -> MajorMinor {
264 let range = self.version_byte_range();
265 self.data.read_at(range.start).ok().unwrap()
266 }
267
268 pub fn num_fonts(&self) -> u32 {
270 let range = self.num_fonts_byte_range();
271 self.data.read_at(range.start).ok().unwrap()
272 }
273
274 pub fn table_directory_offsets(&self) -> &'a [BigEndian<u32>] {
276 let range = self.table_directory_offsets_byte_range();
277 self.data.read_array(range).ok().unwrap_or_default()
278 }
279
280 pub fn dsig_tag(&self) -> Option<u32> {
282 let range = self.dsig_tag_byte_range();
283 (!range.is_empty())
284 .then(|| self.data.read_at(range.start).ok())
285 .flatten()
286 }
287
288 pub fn dsig_length(&self) -> Option<u32> {
290 let range = self.dsig_length_byte_range();
291 (!range.is_empty())
292 .then(|| self.data.read_at(range.start).ok())
293 .flatten()
294 }
295
296 pub fn dsig_offset(&self) -> Option<u32> {
298 let range = self.dsig_offset_byte_range();
299 (!range.is_empty())
300 .then(|| self.data.read_at(range.start).ok())
301 .flatten()
302 }
303
304 pub fn ttc_tag_byte_range(&self) -> Range<usize> {
305 let start = 0;
306 let end = start + Tag::RAW_BYTE_LEN;
307 start..end
308 }
309
310 pub fn version_byte_range(&self) -> Range<usize> {
311 let start = self.ttc_tag_byte_range().end;
312 let end = start + MajorMinor::RAW_BYTE_LEN;
313 start..end
314 }
315
316 pub fn num_fonts_byte_range(&self) -> Range<usize> {
317 let start = self.version_byte_range().end;
318 let end = start + u32::RAW_BYTE_LEN;
319 start..end
320 }
321
322 pub fn table_directory_offsets_byte_range(&self) -> Range<usize> {
323 let num_fonts = self.num_fonts();
324 let start = self.num_fonts_byte_range().end;
325 let end = start + (transforms::to_usize(num_fonts)).saturating_mul(u32::RAW_BYTE_LEN);
326 start..end
327 }
328
329 pub fn dsig_tag_byte_range(&self) -> Range<usize> {
330 let start = self.table_directory_offsets_byte_range().end;
331 let end = if self.version().compatible((2u16, 0u16)) {
332 start + u32::RAW_BYTE_LEN
333 } else {
334 start
335 };
336 start..end
337 }
338
339 pub fn dsig_length_byte_range(&self) -> Range<usize> {
340 let start = self.dsig_tag_byte_range().end;
341 let end = if self.version().compatible((2u16, 0u16)) {
342 start + u32::RAW_BYTE_LEN
343 } else {
344 start
345 };
346 start..end
347 }
348
349 pub fn dsig_offset_byte_range(&self) -> Range<usize> {
350 let start = self.dsig_length_byte_range().end;
351 let end = if self.version().compatible((2u16, 0u16)) {
352 start + u32::RAW_BYTE_LEN
353 } else {
354 start
355 };
356 start..end
357 }
358}
359
360const _: () = assert!(FontData::default_data_long_enough(TTCHeader::MIN_SIZE));
361
362impl Default for TTCHeader<'_> {
363 fn default() -> Self {
364 Self {
365 data: FontData::default_table_data(),
366 }
367 }
368}
369
370#[cfg(feature = "experimental_traverse")]
371impl<'a> SomeTable<'a> for TTCHeader<'a> {
372 fn type_name(&self) -> &str {
373 "TTCHeader"
374 }
375 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
376 match idx {
377 0usize => Some(Field::new("ttc_tag", self.ttc_tag())),
378 1usize => Some(Field::new("version", self.version())),
379 2usize => Some(Field::new("num_fonts", self.num_fonts())),
380 3usize => Some(Field::new(
381 "table_directory_offsets",
382 self.table_directory_offsets(),
383 )),
384 4usize if self.version().compatible((2u16, 0u16)) => {
385 Some(Field::new("dsig_tag", self.dsig_tag().unwrap()))
386 }
387 5usize if self.version().compatible((2u16, 0u16)) => {
388 Some(Field::new("dsig_length", self.dsig_length().unwrap()))
389 }
390 6usize if self.version().compatible((2u16, 0u16)) => {
391 Some(Field::new("dsig_offset", self.dsig_offset().unwrap()))
392 }
393 _ => None,
394 }
395 }
396}
397
398#[cfg(feature = "experimental_traverse")]
399#[allow(clippy::needless_lifetimes)]
400impl<'a> std::fmt::Debug for TTCHeader<'a> {
401 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
402 (self as &dyn SomeTable<'a>).fmt(f)
403 }
404}