/src/fontations/read-fonts/generated/generated_base.rs
Line | Count | Source |
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 | | impl<'a> MinByteRange<'a> for Base<'a> { |
9 | 0 | fn min_byte_range(&self) -> Range<usize> { |
10 | 0 | 0..self.vert_axis_offset_byte_range().end |
11 | 0 | } |
12 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
13 | 0 | let range = self.min_byte_range(); |
14 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
15 | 0 | } |
16 | | } |
17 | | |
18 | | impl TopLevelTable for Base<'_> { |
19 | | /// `BASE` |
20 | | const TAG: Tag = Tag::new(b"BASE"); |
21 | | } |
22 | | |
23 | | impl ReadArgs for Base<'_> { |
24 | | type Args = (); |
25 | | } |
26 | | |
27 | | impl<'a> FontRead<'a> for Base<'a> { |
28 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
29 | | #[allow(clippy::absurd_extreme_comparisons)] |
30 | 0 | if data.len() < Self::MIN_SIZE { |
31 | 0 | return Err(ReadError::OutOfBounds); |
32 | 0 | } |
33 | 0 | Ok(Self { data }) |
34 | 0 | } |
35 | | } |
36 | | |
37 | | /// The [BASE](https://learn.microsoft.com/en-us/typography/opentype/spec/base) (Baseline) table |
38 | | #[derive(Clone)] |
39 | | pub struct Base<'a> { |
40 | | data: FontData<'a>, |
41 | | } |
42 | | |
43 | | #[allow(clippy::needless_lifetimes)] |
44 | | impl<'a> Base<'a> { |
45 | | pub const MIN_SIZE: usize = |
46 | | (MajorMinor::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN); |
47 | | basic_table_impls!(impl_the_methods); |
48 | | |
49 | | /// (major, minor) Version for the BASE table (1,0) or (1,1) |
50 | 0 | pub fn version(&self) -> MajorMinor { |
51 | 0 | let range = self.version_byte_range(); |
52 | 0 | self.data.read_at(range.start).ok().unwrap() |
53 | 0 | } |
54 | | |
55 | | /// Offset to horizontal Axis table, from beginning of BASE table (may be NULL) |
56 | 0 | pub fn horiz_axis_offset(&self) -> Nullable<Offset16> { |
57 | 0 | let range = self.horiz_axis_offset_byte_range(); |
58 | 0 | self.data.read_at(range.start).ok().unwrap() |
59 | 0 | } |
60 | | |
61 | | /// Attempt to resolve [`horiz_axis_offset`][Self::horiz_axis_offset]. |
62 | 0 | pub fn horiz_axis(&self) -> Option<Result<Axis<'a>, ReadError>> { |
63 | 0 | let data = self.data; |
64 | 0 | self.horiz_axis_offset().resolve(data) |
65 | 0 | } |
66 | | |
67 | | /// Offset to vertical Axis table, from beginning of BASE table (may be NULL) |
68 | 0 | pub fn vert_axis_offset(&self) -> Nullable<Offset16> { |
69 | 0 | let range = self.vert_axis_offset_byte_range(); |
70 | 0 | self.data.read_at(range.start).ok().unwrap() |
71 | 0 | } |
72 | | |
73 | | /// Attempt to resolve [`vert_axis_offset`][Self::vert_axis_offset]. |
74 | 0 | pub fn vert_axis(&self) -> Option<Result<Axis<'a>, ReadError>> { |
75 | 0 | let data = self.data; |
76 | 0 | self.vert_axis_offset().resolve(data) |
77 | 0 | } |
78 | | |
79 | | /// Offset to Item Variation Store table, from beginning of BASE table (may be null) |
80 | 0 | pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> { |
81 | 0 | let range = self.item_var_store_offset_byte_range(); |
82 | 0 | (!range.is_empty()) |
83 | 0 | .then(|| self.data.read_at(range.start).ok()) |
84 | 0 | .flatten() |
85 | 0 | } |
86 | | |
87 | | /// Attempt to resolve [`item_var_store_offset`][Self::item_var_store_offset]. |
88 | 0 | pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> { |
89 | 0 | let data = self.data; |
90 | 0 | self.item_var_store_offset().map(|x| x.resolve(data))? |
91 | 0 | } |
92 | | |
93 | 0 | pub fn version_byte_range(&self) -> Range<usize> { |
94 | 0 | let start = 0; |
95 | 0 | let end = start + MajorMinor::RAW_BYTE_LEN; |
96 | 0 | start..end |
97 | 0 | } |
98 | | |
99 | 0 | pub fn horiz_axis_offset_byte_range(&self) -> Range<usize> { |
100 | 0 | let start = self.version_byte_range().end; |
101 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
102 | 0 | start..end |
103 | 0 | } |
104 | | |
105 | 0 | pub fn vert_axis_offset_byte_range(&self) -> Range<usize> { |
106 | 0 | let start = self.horiz_axis_offset_byte_range().end; |
107 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
108 | 0 | start..end |
109 | 0 | } |
110 | | |
111 | 0 | pub fn item_var_store_offset_byte_range(&self) -> Range<usize> { |
112 | 0 | let start = self.vert_axis_offset_byte_range().end; |
113 | 0 | let end = if self.version().compatible((1u16, 1u16)) { |
114 | 0 | start + Offset32::RAW_BYTE_LEN |
115 | | } else { |
116 | 0 | start |
117 | | }; |
118 | 0 | start..end |
119 | 0 | } |
120 | | } |
121 | | |
122 | | const _: () = assert!(FontData::default_data_long_enough(Base::MIN_SIZE)); |
123 | | |
124 | | impl Default for Base<'_> { |
125 | 0 | fn default() -> Self { |
126 | 0 | Self { |
127 | 0 | data: FontData::default_table_data(), |
128 | 0 | } |
129 | 0 | } |
130 | | } |
131 | | |
132 | | impl<'a> MinByteRange<'a> for Axis<'a> { |
133 | 0 | fn min_byte_range(&self) -> Range<usize> { |
134 | 0 | 0..self.base_script_list_offset_byte_range().end |
135 | 0 | } |
136 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
137 | 0 | let range = self.min_byte_range(); |
138 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
139 | 0 | } |
140 | | } |
141 | | |
142 | | impl ReadArgs for Axis<'_> { |
143 | | type Args = (); |
144 | | } |
145 | | |
146 | | impl<'a> FontRead<'a> for Axis<'a> { |
147 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
148 | | #[allow(clippy::absurd_extreme_comparisons)] |
149 | 0 | if data.len() < Self::MIN_SIZE { |
150 | 0 | return Err(ReadError::OutOfBounds); |
151 | 0 | } |
152 | 0 | Ok(Self { data }) |
153 | 0 | } |
154 | | } |
155 | | |
156 | | /// [Axis Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#axis-tables-horizaxis-and-vertaxis) |
157 | | #[derive(Clone)] |
158 | | pub struct Axis<'a> { |
159 | | data: FontData<'a>, |
160 | | } |
161 | | |
162 | | #[allow(clippy::needless_lifetimes)] |
163 | | impl<'a> Axis<'a> { |
164 | | pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN); |
165 | | basic_table_impls!(impl_the_methods); |
166 | | |
167 | | /// Offset to BaseTagList table, from beginning of Axis table (may |
168 | | /// be NULL) |
169 | 0 | pub fn base_tag_list_offset(&self) -> Nullable<Offset16> { |
170 | 0 | let range = self.base_tag_list_offset_byte_range(); |
171 | 0 | self.data.read_at(range.start).ok().unwrap() |
172 | 0 | } |
173 | | |
174 | | /// Attempt to resolve [`base_tag_list_offset`][Self::base_tag_list_offset]. |
175 | 0 | pub fn base_tag_list(&self) -> Option<Result<BaseTagList<'a>, ReadError>> { |
176 | 0 | let data = self.data; |
177 | 0 | self.base_tag_list_offset().resolve(data) |
178 | 0 | } |
179 | | |
180 | | /// Offset to BaseScriptList table, from beginning of Axis table |
181 | 0 | pub fn base_script_list_offset(&self) -> Offset16 { |
182 | 0 | let range = self.base_script_list_offset_byte_range(); |
183 | 0 | self.data.read_at(range.start).ok().unwrap() |
184 | 0 | } |
185 | | |
186 | | /// Attempt to resolve [`base_script_list_offset`][Self::base_script_list_offset]. |
187 | 0 | pub fn base_script_list(&self) -> Result<BaseScriptList<'a>, ReadError> { |
188 | 0 | let data = self.data; |
189 | 0 | self.base_script_list_offset().resolve(data) |
190 | 0 | } |
191 | | |
192 | 0 | pub fn base_tag_list_offset_byte_range(&self) -> Range<usize> { |
193 | 0 | let start = 0; |
194 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
195 | 0 | start..end |
196 | 0 | } |
197 | | |
198 | 0 | pub fn base_script_list_offset_byte_range(&self) -> Range<usize> { |
199 | 0 | let start = self.base_tag_list_offset_byte_range().end; |
200 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
201 | 0 | start..end |
202 | 0 | } |
203 | | } |
204 | | |
205 | | const _: () = assert!(FontData::default_data_long_enough(Axis::MIN_SIZE)); |
206 | | |
207 | | impl Default for Axis<'_> { |
208 | 0 | fn default() -> Self { |
209 | 0 | Self { |
210 | 0 | data: FontData::default_table_data(), |
211 | 0 | } |
212 | 0 | } |
213 | | } |
214 | | |
215 | | impl<'a> MinByteRange<'a> for BaseTagList<'a> { |
216 | 0 | fn min_byte_range(&self) -> Range<usize> { |
217 | 0 | 0..self.baseline_tags_byte_range().end |
218 | 0 | } |
219 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
220 | 0 | let range = self.min_byte_range(); |
221 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
222 | 0 | } |
223 | | } |
224 | | |
225 | | impl ReadArgs for BaseTagList<'_> { |
226 | | type Args = (); |
227 | | } |
228 | | |
229 | | impl<'a> FontRead<'a> for BaseTagList<'a> { |
230 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
231 | | #[allow(clippy::absurd_extreme_comparisons)] |
232 | 0 | if data.len() < Self::MIN_SIZE { |
233 | 0 | return Err(ReadError::OutOfBounds); |
234 | 0 | } |
235 | 0 | Ok(Self { data }) |
236 | 0 | } |
237 | | } |
238 | | |
239 | | /// [BaseTagList Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basetaglist-table) |
240 | | #[derive(Clone)] |
241 | | pub struct BaseTagList<'a> { |
242 | | data: FontData<'a>, |
243 | | } |
244 | | |
245 | | #[allow(clippy::needless_lifetimes)] |
246 | | impl<'a> BaseTagList<'a> { |
247 | | pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN; |
248 | | basic_table_impls!(impl_the_methods); |
249 | | |
250 | | /// Number of baseline identification tags in this text direction |
251 | | /// — may be zero (0) |
252 | 0 | pub fn base_tag_count(&self) -> u16 { |
253 | 0 | let range = self.base_tag_count_byte_range(); |
254 | 0 | self.data.read_at(range.start).ok().unwrap() |
255 | 0 | } |
256 | | |
257 | | /// Array of 4-byte baseline identification tags — must be in |
258 | | /// alphabetical order |
259 | 0 | pub fn baseline_tags(&self) -> &'a [BigEndian<Tag>] { |
260 | 0 | let range = self.baseline_tags_byte_range(); |
261 | 0 | self.data.read_array(range).ok().unwrap_or_default() |
262 | 0 | } |
263 | | |
264 | 0 | pub fn base_tag_count_byte_range(&self) -> Range<usize> { |
265 | 0 | let start = 0; |
266 | 0 | let end = start + u16::RAW_BYTE_LEN; |
267 | 0 | start..end |
268 | 0 | } |
269 | | |
270 | 0 | pub fn baseline_tags_byte_range(&self) -> Range<usize> { |
271 | 0 | let base_tag_count = self.base_tag_count(); |
272 | 0 | let start = self.base_tag_count_byte_range().end; |
273 | 0 | let end = start + (transforms::to_usize(base_tag_count)).saturating_mul(Tag::RAW_BYTE_LEN); |
274 | 0 | start..end |
275 | 0 | } |
276 | | } |
277 | | |
278 | | const _: () = assert!(FontData::default_data_long_enough(BaseTagList::MIN_SIZE)); |
279 | | |
280 | | impl Default for BaseTagList<'_> { |
281 | 0 | fn default() -> Self { |
282 | 0 | Self { |
283 | 0 | data: FontData::default_table_data(), |
284 | 0 | } |
285 | 0 | } |
286 | | } |
287 | | |
288 | | impl<'a> MinByteRange<'a> for BaseScriptList<'a> { |
289 | 0 | fn min_byte_range(&self) -> Range<usize> { |
290 | 0 | 0..self.base_script_records_byte_range().end |
291 | 0 | } |
292 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
293 | 0 | let range = self.min_byte_range(); |
294 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
295 | 0 | } |
296 | | } |
297 | | |
298 | | impl ReadArgs for BaseScriptList<'_> { |
299 | | type Args = (); |
300 | | } |
301 | | |
302 | | impl<'a> FontRead<'a> for BaseScriptList<'a> { |
303 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
304 | | #[allow(clippy::absurd_extreme_comparisons)] |
305 | 0 | if data.len() < Self::MIN_SIZE { |
306 | 0 | return Err(ReadError::OutOfBounds); |
307 | 0 | } |
308 | 0 | Ok(Self { data }) |
309 | 0 | } |
310 | | } |
311 | | |
312 | | /// [BaseScriptList Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescriptlist-table) |
313 | | #[derive(Clone)] |
314 | | pub struct BaseScriptList<'a> { |
315 | | data: FontData<'a>, |
316 | | } |
317 | | |
318 | | #[allow(clippy::needless_lifetimes)] |
319 | | impl<'a> BaseScriptList<'a> { |
320 | | pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN; |
321 | | basic_table_impls!(impl_the_methods); |
322 | | |
323 | | /// Number of BaseScriptRecords defined |
324 | 0 | pub fn base_script_count(&self) -> u16 { |
325 | 0 | let range = self.base_script_count_byte_range(); |
326 | 0 | self.data.read_at(range.start).ok().unwrap() |
327 | 0 | } |
328 | | |
329 | | /// Array of BaseScriptRecords, in alphabetical order by |
330 | | /// baseScriptTag |
331 | 0 | pub fn base_script_records(&self) -> &'a [BaseScriptRecord] { |
332 | 0 | let range = self.base_script_records_byte_range(); |
333 | 0 | self.data.read_array(range).ok().unwrap_or_default() |
334 | 0 | } |
335 | | |
336 | 0 | pub fn base_script_count_byte_range(&self) -> Range<usize> { |
337 | 0 | let start = 0; |
338 | 0 | let end = start + u16::RAW_BYTE_LEN; |
339 | 0 | start..end |
340 | 0 | } |
341 | | |
342 | 0 | pub fn base_script_records_byte_range(&self) -> Range<usize> { |
343 | 0 | let base_script_count = self.base_script_count(); |
344 | 0 | let start = self.base_script_count_byte_range().end; |
345 | 0 | let end = start |
346 | 0 | + (transforms::to_usize(base_script_count)) |
347 | 0 | .saturating_mul(BaseScriptRecord::RAW_BYTE_LEN); |
348 | 0 | start..end |
349 | 0 | } |
350 | | } |
351 | | |
352 | | const _: () = assert!(FontData::default_data_long_enough(BaseScriptList::MIN_SIZE)); |
353 | | |
354 | | impl Default for BaseScriptList<'_> { |
355 | 0 | fn default() -> Self { |
356 | 0 | Self { |
357 | 0 | data: FontData::default_table_data(), |
358 | 0 | } |
359 | 0 | } |
360 | | } |
361 | | |
362 | | /// [BaseScriptRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescriptrecord) |
363 | | #[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)] |
364 | | #[repr(C)] |
365 | | #[repr(packed)] |
366 | | pub struct BaseScriptRecord { |
367 | | /// 4-byte script identification tag |
368 | | pub base_script_tag: BigEndian<Tag>, |
369 | | /// Offset to BaseScript table, from beginning of BaseScriptList |
370 | | pub base_script_offset: BigEndian<Offset16>, |
371 | | } |
372 | | |
373 | | impl BaseScriptRecord { |
374 | | /// 4-byte script identification tag |
375 | 0 | pub fn base_script_tag(&self) -> Tag { |
376 | 0 | self.base_script_tag.get() |
377 | 0 | } |
378 | | |
379 | | /// Offset to BaseScript table, from beginning of BaseScriptList |
380 | 0 | pub fn base_script_offset(&self) -> Offset16 { |
381 | 0 | self.base_script_offset.get() |
382 | 0 | } |
383 | | |
384 | | /// Offset to BaseScript table, from beginning of BaseScriptList |
385 | | /// |
386 | | /// The `data` argument should be retrieved from the parent table |
387 | | /// By calling its `offset_data` method. |
388 | 0 | pub fn base_script<'a>(&self, data: FontData<'a>) -> Result<BaseScript<'a>, ReadError> { |
389 | 0 | self.base_script_offset().resolve(data) |
390 | 0 | } |
391 | | } |
392 | | |
393 | | impl FixedSize for BaseScriptRecord { |
394 | | const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN; |
395 | | } |
396 | | |
397 | | impl<'a> MinByteRange<'a> for BaseScript<'a> { |
398 | 0 | fn min_byte_range(&self) -> Range<usize> { |
399 | 0 | 0..self.base_lang_sys_records_byte_range().end |
400 | 0 | } |
401 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
402 | 0 | let range = self.min_byte_range(); |
403 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
404 | 0 | } |
405 | | } |
406 | | |
407 | | impl ReadArgs for BaseScript<'_> { |
408 | | type Args = (); |
409 | | } |
410 | | |
411 | | impl<'a> FontRead<'a> for BaseScript<'a> { |
412 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
413 | | #[allow(clippy::absurd_extreme_comparisons)] |
414 | 0 | if data.len() < Self::MIN_SIZE { |
415 | 0 | return Err(ReadError::OutOfBounds); |
416 | 0 | } |
417 | 0 | Ok(Self { data }) |
418 | 0 | } |
419 | | } |
420 | | |
421 | | /// [BaseScript Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescript-table) |
422 | | #[derive(Clone)] |
423 | | pub struct BaseScript<'a> { |
424 | | data: FontData<'a>, |
425 | | } |
426 | | |
427 | | #[allow(clippy::needless_lifetimes)] |
428 | | impl<'a> BaseScript<'a> { |
429 | | pub const MIN_SIZE: usize = |
430 | | (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
431 | | basic_table_impls!(impl_the_methods); |
432 | | |
433 | | /// Offset to BaseValues table, from beginning of BaseScript table (may be NULL) |
434 | 0 | pub fn base_values_offset(&self) -> Nullable<Offset16> { |
435 | 0 | let range = self.base_values_offset_byte_range(); |
436 | 0 | self.data.read_at(range.start).ok().unwrap() |
437 | 0 | } |
438 | | |
439 | | /// Attempt to resolve [`base_values_offset`][Self::base_values_offset]. |
440 | 0 | pub fn base_values(&self) -> Option<Result<BaseValues<'a>, ReadError>> { |
441 | 0 | let data = self.data; |
442 | 0 | self.base_values_offset().resolve(data) |
443 | 0 | } |
444 | | |
445 | | /// Offset to MinMax table, from beginning of BaseScript table (may be NULL) |
446 | 0 | pub fn default_min_max_offset(&self) -> Nullable<Offset16> { |
447 | 0 | let range = self.default_min_max_offset_byte_range(); |
448 | 0 | self.data.read_at(range.start).ok().unwrap() |
449 | 0 | } |
450 | | |
451 | | /// Attempt to resolve [`default_min_max_offset`][Self::default_min_max_offset]. |
452 | 0 | pub fn default_min_max(&self) -> Option<Result<MinMax<'a>, ReadError>> { |
453 | 0 | let data = self.data; |
454 | 0 | self.default_min_max_offset().resolve(data) |
455 | 0 | } |
456 | | |
457 | | /// Number of BaseLangSysRecords defined — may be zero (0) |
458 | 0 | pub fn base_lang_sys_count(&self) -> u16 { |
459 | 0 | let range = self.base_lang_sys_count_byte_range(); |
460 | 0 | self.data.read_at(range.start).ok().unwrap() |
461 | 0 | } |
462 | | |
463 | | /// Array of BaseLangSysRecords, in alphabetical order by |
464 | | /// BaseLangSysTag |
465 | 0 | pub fn base_lang_sys_records(&self) -> &'a [BaseLangSysRecord] { |
466 | 0 | let range = self.base_lang_sys_records_byte_range(); |
467 | 0 | self.data.read_array(range).ok().unwrap_or_default() |
468 | 0 | } |
469 | | |
470 | 0 | pub fn base_values_offset_byte_range(&self) -> Range<usize> { |
471 | 0 | let start = 0; |
472 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
473 | 0 | start..end |
474 | 0 | } |
475 | | |
476 | 0 | pub fn default_min_max_offset_byte_range(&self) -> Range<usize> { |
477 | 0 | let start = self.base_values_offset_byte_range().end; |
478 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
479 | 0 | start..end |
480 | 0 | } |
481 | | |
482 | 0 | pub fn base_lang_sys_count_byte_range(&self) -> Range<usize> { |
483 | 0 | let start = self.default_min_max_offset_byte_range().end; |
484 | 0 | let end = start + u16::RAW_BYTE_LEN; |
485 | 0 | start..end |
486 | 0 | } |
487 | | |
488 | 0 | pub fn base_lang_sys_records_byte_range(&self) -> Range<usize> { |
489 | 0 | let base_lang_sys_count = self.base_lang_sys_count(); |
490 | 0 | let start = self.base_lang_sys_count_byte_range().end; |
491 | 0 | let end = start |
492 | 0 | + (transforms::to_usize(base_lang_sys_count)) |
493 | 0 | .saturating_mul(BaseLangSysRecord::RAW_BYTE_LEN); |
494 | 0 | start..end |
495 | 0 | } |
496 | | } |
497 | | |
498 | | const _: () = assert!(FontData::default_data_long_enough(BaseScript::MIN_SIZE)); |
499 | | |
500 | | impl Default for BaseScript<'_> { |
501 | 0 | fn default() -> Self { |
502 | 0 | Self { |
503 | 0 | data: FontData::default_table_data(), |
504 | 0 | } |
505 | 0 | } |
506 | | } |
507 | | |
508 | | /// [BaseLangSysRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/base#baselangsysrecord) |
509 | | #[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)] |
510 | | #[repr(C)] |
511 | | #[repr(packed)] |
512 | | pub struct BaseLangSysRecord { |
513 | | /// 4-byte language system identification tag |
514 | | pub base_lang_sys_tag: BigEndian<Tag>, |
515 | | /// Offset to MinMax table, from beginning of BaseScript table |
516 | | pub min_max_offset: BigEndian<Offset16>, |
517 | | } |
518 | | |
519 | | impl BaseLangSysRecord { |
520 | | /// 4-byte language system identification tag |
521 | 0 | pub fn base_lang_sys_tag(&self) -> Tag { |
522 | 0 | self.base_lang_sys_tag.get() |
523 | 0 | } |
524 | | |
525 | | /// Offset to MinMax table, from beginning of BaseScript table |
526 | 0 | pub fn min_max_offset(&self) -> Offset16 { |
527 | 0 | self.min_max_offset.get() |
528 | 0 | } |
529 | | |
530 | | /// Offset to MinMax table, from beginning of BaseScript table |
531 | | /// |
532 | | /// The `data` argument should be retrieved from the parent table |
533 | | /// By calling its `offset_data` method. |
534 | 0 | pub fn min_max<'a>(&self, data: FontData<'a>) -> Result<MinMax<'a>, ReadError> { |
535 | 0 | self.min_max_offset().resolve(data) |
536 | 0 | } |
537 | | } |
538 | | |
539 | | impl FixedSize for BaseLangSysRecord { |
540 | | const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN; |
541 | | } |
542 | | |
543 | | impl<'a> MinByteRange<'a> for BaseValues<'a> { |
544 | 0 | fn min_byte_range(&self) -> Range<usize> { |
545 | 0 | 0..self.base_coord_offsets_byte_range().end |
546 | 0 | } |
547 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
548 | 0 | let range = self.min_byte_range(); |
549 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
550 | 0 | } |
551 | | } |
552 | | |
553 | | impl ReadArgs for BaseValues<'_> { |
554 | | type Args = (); |
555 | | } |
556 | | |
557 | | impl<'a> FontRead<'a> for BaseValues<'a> { |
558 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
559 | | #[allow(clippy::absurd_extreme_comparisons)] |
560 | 0 | if data.len() < Self::MIN_SIZE { |
561 | 0 | return Err(ReadError::OutOfBounds); |
562 | 0 | } |
563 | 0 | Ok(Self { data }) |
564 | 0 | } |
565 | | } |
566 | | |
567 | | /// [BaseValues](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basevalues-table) table |
568 | | #[derive(Clone)] |
569 | | pub struct BaseValues<'a> { |
570 | | data: FontData<'a>, |
571 | | } |
572 | | |
573 | | #[allow(clippy::needless_lifetimes)] |
574 | | impl<'a> BaseValues<'a> { |
575 | | pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
576 | | basic_table_impls!(impl_the_methods); |
577 | | |
578 | | /// Index number of default baseline for this script — equals |
579 | | /// index position of baseline tag in baselineTags array of the |
580 | | /// BaseTagList |
581 | 0 | pub fn default_baseline_index(&self) -> u16 { |
582 | 0 | let range = self.default_baseline_index_byte_range(); |
583 | 0 | self.data.read_at(range.start).ok().unwrap() |
584 | 0 | } |
585 | | |
586 | | /// Number of BaseCoord tables defined — should equal |
587 | | /// baseTagCount in the BaseTagList |
588 | 0 | pub fn base_coord_count(&self) -> u16 { |
589 | 0 | let range = self.base_coord_count_byte_range(); |
590 | 0 | self.data.read_at(range.start).ok().unwrap() |
591 | 0 | } |
592 | | |
593 | | /// Array of offsets to BaseCoord tables, from beginning of |
594 | | /// BaseValues table — order matches baselineTags array in the |
595 | | /// BaseTagList |
596 | 0 | pub fn base_coord_offsets(&self) -> &'a [BigEndian<Offset16>] { |
597 | 0 | let range = self.base_coord_offsets_byte_range(); |
598 | 0 | self.data.read_array(range).ok().unwrap_or_default() |
599 | 0 | } |
600 | | |
601 | | /// A dynamically resolving wrapper for [`base_coord_offsets`][Self::base_coord_offsets]. |
602 | 0 | pub fn base_coords(&self) -> ArrayOfOffsets<'a, BaseCoord<'a>, Offset16> { |
603 | 0 | let data = self.data; |
604 | 0 | let offsets = self.base_coord_offsets(); |
605 | 0 | ArrayOfOffsets::new(offsets, data, ()) |
606 | 0 | } |
607 | | |
608 | 0 | pub fn default_baseline_index_byte_range(&self) -> Range<usize> { |
609 | 0 | let start = 0; |
610 | 0 | let end = start + u16::RAW_BYTE_LEN; |
611 | 0 | start..end |
612 | 0 | } |
613 | | |
614 | 0 | pub fn base_coord_count_byte_range(&self) -> Range<usize> { |
615 | 0 | let start = self.default_baseline_index_byte_range().end; |
616 | 0 | let end = start + u16::RAW_BYTE_LEN; |
617 | 0 | start..end |
618 | 0 | } |
619 | | |
620 | 0 | pub fn base_coord_offsets_byte_range(&self) -> Range<usize> { |
621 | 0 | let base_coord_count = self.base_coord_count(); |
622 | 0 | let start = self.base_coord_count_byte_range().end; |
623 | 0 | let end = |
624 | 0 | start + (transforms::to_usize(base_coord_count)).saturating_mul(Offset16::RAW_BYTE_LEN); |
625 | 0 | start..end |
626 | 0 | } |
627 | | } |
628 | | |
629 | | const _: () = assert!(FontData::default_data_long_enough(BaseValues::MIN_SIZE)); |
630 | | |
631 | | impl Default for BaseValues<'_> { |
632 | 0 | fn default() -> Self { |
633 | 0 | Self { |
634 | 0 | data: FontData::default_table_data(), |
635 | 0 | } |
636 | 0 | } |
637 | | } |
638 | | |
639 | | impl<'a> MinByteRange<'a> for MinMax<'a> { |
640 | 0 | fn min_byte_range(&self) -> Range<usize> { |
641 | 0 | 0..self.feat_min_max_records_byte_range().end |
642 | 0 | } |
643 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
644 | 0 | let range = self.min_byte_range(); |
645 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
646 | 0 | } |
647 | | } |
648 | | |
649 | | impl ReadArgs for MinMax<'_> { |
650 | | type Args = (); |
651 | | } |
652 | | |
653 | | impl<'a> FontRead<'a> for MinMax<'a> { |
654 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
655 | | #[allow(clippy::absurd_extreme_comparisons)] |
656 | 0 | if data.len() < Self::MIN_SIZE { |
657 | 0 | return Err(ReadError::OutOfBounds); |
658 | 0 | } |
659 | 0 | Ok(Self { data }) |
660 | 0 | } |
661 | | } |
662 | | |
663 | | /// [MinMax](https://learn.microsoft.com/en-us/typography/opentype/spec/base#minmax-table) table |
664 | | #[derive(Clone)] |
665 | | pub struct MinMax<'a> { |
666 | | data: FontData<'a>, |
667 | | } |
668 | | |
669 | | #[allow(clippy::needless_lifetimes)] |
670 | | impl<'a> MinMax<'a> { |
671 | | pub const MIN_SIZE: usize = |
672 | | (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
673 | | basic_table_impls!(impl_the_methods); |
674 | | |
675 | | /// Offset to BaseCoord table that defines the minimum extent |
676 | | /// value, from the beginning of MinMax table (may be NULL) |
677 | 0 | pub fn min_coord_offset(&self) -> Nullable<Offset16> { |
678 | 0 | let range = self.min_coord_offset_byte_range(); |
679 | 0 | self.data.read_at(range.start).ok().unwrap() |
680 | 0 | } |
681 | | |
682 | | /// Attempt to resolve [`min_coord_offset`][Self::min_coord_offset]. |
683 | 0 | pub fn min_coord(&self) -> Option<Result<BaseCoord<'a>, ReadError>> { |
684 | 0 | let data = self.data; |
685 | 0 | self.min_coord_offset().resolve(data) |
686 | 0 | } |
687 | | |
688 | | /// Offset to BaseCoord table that defines maximum extent value, |
689 | | /// from the beginning of MinMax table (may be NULL) |
690 | 0 | pub fn max_coord_offset(&self) -> Nullable<Offset16> { |
691 | 0 | let range = self.max_coord_offset_byte_range(); |
692 | 0 | self.data.read_at(range.start).ok().unwrap() |
693 | 0 | } |
694 | | |
695 | | /// Attempt to resolve [`max_coord_offset`][Self::max_coord_offset]. |
696 | 0 | pub fn max_coord(&self) -> Option<Result<BaseCoord<'a>, ReadError>> { |
697 | 0 | let data = self.data; |
698 | 0 | self.max_coord_offset().resolve(data) |
699 | 0 | } |
700 | | |
701 | | /// Number of FeatMinMaxRecords — may be zero (0) |
702 | 0 | pub fn feat_min_max_count(&self) -> u16 { |
703 | 0 | let range = self.feat_min_max_count_byte_range(); |
704 | 0 | self.data.read_at(range.start).ok().unwrap() |
705 | 0 | } |
706 | | |
707 | | /// Array of FeatMinMaxRecords, in alphabetical order by |
708 | | /// featureTableTag |
709 | 0 | pub fn feat_min_max_records(&self) -> &'a [FeatMinMaxRecord] { |
710 | 0 | let range = self.feat_min_max_records_byte_range(); |
711 | 0 | self.data.read_array(range).ok().unwrap_or_default() |
712 | 0 | } |
713 | | |
714 | 0 | pub fn min_coord_offset_byte_range(&self) -> Range<usize> { |
715 | 0 | let start = 0; |
716 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
717 | 0 | start..end |
718 | 0 | } |
719 | | |
720 | 0 | pub fn max_coord_offset_byte_range(&self) -> Range<usize> { |
721 | 0 | let start = self.min_coord_offset_byte_range().end; |
722 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
723 | 0 | start..end |
724 | 0 | } |
725 | | |
726 | 0 | pub fn feat_min_max_count_byte_range(&self) -> Range<usize> { |
727 | 0 | let start = self.max_coord_offset_byte_range().end; |
728 | 0 | let end = start + u16::RAW_BYTE_LEN; |
729 | 0 | start..end |
730 | 0 | } |
731 | | |
732 | 0 | pub fn feat_min_max_records_byte_range(&self) -> Range<usize> { |
733 | 0 | let feat_min_max_count = self.feat_min_max_count(); |
734 | 0 | let start = self.feat_min_max_count_byte_range().end; |
735 | 0 | let end = start |
736 | 0 | + (transforms::to_usize(feat_min_max_count)) |
737 | 0 | .saturating_mul(FeatMinMaxRecord::RAW_BYTE_LEN); |
738 | 0 | start..end |
739 | 0 | } |
740 | | } |
741 | | |
742 | | const _: () = assert!(FontData::default_data_long_enough(MinMax::MIN_SIZE)); |
743 | | |
744 | | impl Default for MinMax<'_> { |
745 | 0 | fn default() -> Self { |
746 | 0 | Self { |
747 | 0 | data: FontData::default_table_data(), |
748 | 0 | } |
749 | 0 | } |
750 | | } |
751 | | |
752 | | /// [FeatMinMaxRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/base#baselangsysrecord) |
753 | | #[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)] |
754 | | #[repr(C)] |
755 | | #[repr(packed)] |
756 | | pub struct FeatMinMaxRecord { |
757 | | /// 4-byte feature identification tag — must match feature tag in |
758 | | /// FeatureList |
759 | | pub feature_table_tag: BigEndian<Tag>, |
760 | | /// Offset to BaseCoord table that defines the minimum extent |
761 | | /// value, from beginning of MinMax table (may be NULL) |
762 | | pub min_coord_offset: BigEndian<Nullable<Offset16>>, |
763 | | /// Offset to BaseCoord table that defines the maximum extent |
764 | | /// value, from beginning of MinMax table (may be NULL) |
765 | | pub max_coord_offset: BigEndian<Nullable<Offset16>>, |
766 | | } |
767 | | |
768 | | impl FeatMinMaxRecord { |
769 | | /// 4-byte feature identification tag — must match feature tag in |
770 | | /// FeatureList |
771 | 0 | pub fn feature_table_tag(&self) -> Tag { |
772 | 0 | self.feature_table_tag.get() |
773 | 0 | } |
774 | | |
775 | | /// Offset to BaseCoord table that defines the minimum extent |
776 | | /// value, from beginning of MinMax table (may be NULL) |
777 | 0 | pub fn min_coord_offset(&self) -> Nullable<Offset16> { |
778 | 0 | self.min_coord_offset.get() |
779 | 0 | } |
780 | | |
781 | | /// Offset to BaseCoord table that defines the minimum extent |
782 | | /// value, from beginning of MinMax table (may be NULL) |
783 | | /// |
784 | | /// The `data` argument should be retrieved from the parent table |
785 | | /// By calling its `offset_data` method. |
786 | 0 | pub fn min_coord<'a>(&self, data: FontData<'a>) -> Option<Result<BaseCoord<'a>, ReadError>> { |
787 | 0 | self.min_coord_offset().resolve(data) |
788 | 0 | } |
789 | | |
790 | | /// Offset to BaseCoord table that defines the maximum extent |
791 | | /// value, from beginning of MinMax table (may be NULL) |
792 | 0 | pub fn max_coord_offset(&self) -> Nullable<Offset16> { |
793 | 0 | self.max_coord_offset.get() |
794 | 0 | } |
795 | | |
796 | | /// Offset to BaseCoord table that defines the maximum extent |
797 | | /// value, from beginning of MinMax table (may be NULL) |
798 | | /// |
799 | | /// The `data` argument should be retrieved from the parent table |
800 | | /// By calling its `offset_data` method. |
801 | 0 | pub fn max_coord<'a>(&self, data: FontData<'a>) -> Option<Result<BaseCoord<'a>, ReadError>> { |
802 | 0 | self.max_coord_offset().resolve(data) |
803 | 0 | } |
804 | | } |
805 | | |
806 | | impl FixedSize for FeatMinMaxRecord { |
807 | | const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN; |
808 | | } |
809 | | |
810 | | #[derive(Clone)] |
811 | | pub enum BaseCoord<'a> { |
812 | | Format1(BaseCoordFormat1<'a>), |
813 | | Format2(BaseCoordFormat2<'a>), |
814 | | Format3(BaseCoordFormat3<'a>), |
815 | | } |
816 | | |
817 | | impl Default for BaseCoord<'_> { |
818 | 0 | fn default() -> Self { |
819 | 0 | Self::Format1(Default::default()) |
820 | 0 | } |
821 | | } |
822 | | |
823 | | impl<'a> BaseCoord<'a> { |
824 | | ///Return the `FontData` used to resolve offsets for this table. |
825 | 0 | pub fn offset_data(&self) -> FontData<'a> { |
826 | 0 | match self { |
827 | 0 | Self::Format1(item) => item.offset_data(), |
828 | 0 | Self::Format2(item) => item.offset_data(), |
829 | 0 | Self::Format3(item) => item.offset_data(), |
830 | | } |
831 | 0 | } |
832 | | |
833 | | /// Format identifier — format = 1 |
834 | 0 | pub fn base_coord_format(&self) -> u16 { |
835 | 0 | match self { |
836 | 0 | Self::Format1(item) => item.base_coord_format(), |
837 | 0 | Self::Format2(item) => item.base_coord_format(), |
838 | 0 | Self::Format3(item) => item.base_coord_format(), |
839 | | } |
840 | 0 | } |
841 | | |
842 | | /// X or Y value, in design units |
843 | 0 | pub fn coordinate(&self) -> i16 { |
844 | 0 | match self { |
845 | 0 | Self::Format1(item) => item.coordinate(), |
846 | 0 | Self::Format2(item) => item.coordinate(), |
847 | 0 | Self::Format3(item) => item.coordinate(), |
848 | | } |
849 | 0 | } |
850 | | } |
851 | | |
852 | | impl ReadArgs for BaseCoord<'_> { |
853 | | type Args = (); |
854 | | } |
855 | | |
856 | | impl<'a> FontRead<'a> for BaseCoord<'a> { |
857 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
858 | 0 | let format: u16 = data.read_at(0usize)?; |
859 | 0 | match format { |
860 | 0 | BaseCoordFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)), |
861 | 0 | BaseCoordFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)), |
862 | 0 | BaseCoordFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)), |
863 | 0 | other => Err(ReadError::InvalidFormat(other.into())), |
864 | | } |
865 | 0 | } |
866 | | } |
867 | | |
868 | | impl<'a> MinByteRange<'a> for BaseCoord<'a> { |
869 | 0 | fn min_byte_range(&self) -> Range<usize> { |
870 | 0 | match self { |
871 | 0 | Self::Format1(item) => item.min_byte_range(), |
872 | 0 | Self::Format2(item) => item.min_byte_range(), |
873 | 0 | Self::Format3(item) => item.min_byte_range(), |
874 | | } |
875 | 0 | } |
876 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
877 | 0 | match self { |
878 | 0 | Self::Format1(item) => item.min_table_bytes(), |
879 | 0 | Self::Format2(item) => item.min_table_bytes(), |
880 | 0 | Self::Format3(item) => item.min_table_bytes(), |
881 | | } |
882 | 0 | } |
883 | | } |
884 | | |
885 | | impl Format<u16> for BaseCoordFormat1<'_> { |
886 | | const FORMAT: u16 = 1; |
887 | | } |
888 | | |
889 | | impl<'a> MinByteRange<'a> for BaseCoordFormat1<'a> { |
890 | 0 | fn min_byte_range(&self) -> Range<usize> { |
891 | 0 | 0..self.coordinate_byte_range().end |
892 | 0 | } |
893 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
894 | 0 | let range = self.min_byte_range(); |
895 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
896 | 0 | } |
897 | | } |
898 | | |
899 | | impl ReadArgs for BaseCoordFormat1<'_> { |
900 | | type Args = (); |
901 | | } |
902 | | |
903 | | impl<'a> FontRead<'a> for BaseCoordFormat1<'a> { |
904 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
905 | | #[allow(clippy::absurd_extreme_comparisons)] |
906 | 0 | if data.len() < Self::MIN_SIZE { |
907 | 0 | return Err(ReadError::OutOfBounds); |
908 | 0 | } |
909 | 0 | Ok(Self { data }) |
910 | 0 | } |
911 | | } |
912 | | |
913 | | /// [BaseCoordFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-1) |
914 | | #[derive(Clone)] |
915 | | pub struct BaseCoordFormat1<'a> { |
916 | | data: FontData<'a>, |
917 | | } |
918 | | |
919 | | #[allow(clippy::needless_lifetimes)] |
920 | | impl<'a> BaseCoordFormat1<'a> { |
921 | | pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN); |
922 | | basic_table_impls!(impl_the_methods); |
923 | | |
924 | | /// Format identifier — format = 1 |
925 | 0 | pub fn base_coord_format(&self) -> u16 { |
926 | 0 | let range = self.base_coord_format_byte_range(); |
927 | 0 | self.data.read_at(range.start).ok().unwrap() |
928 | 0 | } |
929 | | |
930 | | /// X or Y value, in design units |
931 | 0 | pub fn coordinate(&self) -> i16 { |
932 | 0 | let range = self.coordinate_byte_range(); |
933 | 0 | self.data.read_at(range.start).ok().unwrap() |
934 | 0 | } |
935 | | |
936 | 0 | pub fn base_coord_format_byte_range(&self) -> Range<usize> { |
937 | 0 | let start = 0; |
938 | 0 | let end = start + u16::RAW_BYTE_LEN; |
939 | 0 | start..end |
940 | 0 | } |
941 | | |
942 | 0 | pub fn coordinate_byte_range(&self) -> Range<usize> { |
943 | 0 | let start = self.base_coord_format_byte_range().end; |
944 | 0 | let end = start + i16::RAW_BYTE_LEN; |
945 | 0 | start..end |
946 | 0 | } |
947 | | } |
948 | | |
949 | | const _: () = assert!(FontData::default_data_long_enough( |
950 | | BaseCoordFormat1::MIN_SIZE |
951 | | )); |
952 | | |
953 | | impl Default for BaseCoordFormat1<'_> { |
954 | 0 | fn default() -> Self { |
955 | 0 | Self { |
956 | 0 | data: FontData::default_format_1_u16_table_data(), |
957 | 0 | } |
958 | 0 | } |
959 | | } |
960 | | |
961 | | impl Format<u16> for BaseCoordFormat2<'_> { |
962 | | const FORMAT: u16 = 2; |
963 | | } |
964 | | |
965 | | impl<'a> MinByteRange<'a> for BaseCoordFormat2<'a> { |
966 | 0 | fn min_byte_range(&self) -> Range<usize> { |
967 | 0 | 0..self.base_coord_point_byte_range().end |
968 | 0 | } |
969 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
970 | 0 | let range = self.min_byte_range(); |
971 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
972 | 0 | } |
973 | | } |
974 | | |
975 | | impl ReadArgs for BaseCoordFormat2<'_> { |
976 | | type Args = (); |
977 | | } |
978 | | |
979 | | impl<'a> FontRead<'a> for BaseCoordFormat2<'a> { |
980 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
981 | | #[allow(clippy::absurd_extreme_comparisons)] |
982 | 0 | if data.len() < Self::MIN_SIZE { |
983 | 0 | return Err(ReadError::OutOfBounds); |
984 | 0 | } |
985 | 0 | Ok(Self { data }) |
986 | 0 | } |
987 | | } |
988 | | |
989 | | /// [BaseCoordFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-2) |
990 | | #[derive(Clone)] |
991 | | pub struct BaseCoordFormat2<'a> { |
992 | | data: FontData<'a>, |
993 | | } |
994 | | |
995 | | #[allow(clippy::needless_lifetimes)] |
996 | | impl<'a> BaseCoordFormat2<'a> { |
997 | | pub const MIN_SIZE: usize = |
998 | | (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
999 | | basic_table_impls!(impl_the_methods); |
1000 | | |
1001 | | /// Format identifier — format = 2 |
1002 | 0 | pub fn base_coord_format(&self) -> u16 { |
1003 | 0 | let range = self.base_coord_format_byte_range(); |
1004 | 0 | self.data.read_at(range.start).ok().unwrap() |
1005 | 0 | } |
1006 | | |
1007 | | /// X or Y value, in design units |
1008 | 0 | pub fn coordinate(&self) -> i16 { |
1009 | 0 | let range = self.coordinate_byte_range(); |
1010 | 0 | self.data.read_at(range.start).ok().unwrap() |
1011 | 0 | } |
1012 | | |
1013 | | /// Glyph ID of control glyph |
1014 | 0 | pub fn reference_glyph(&self) -> u16 { |
1015 | 0 | let range = self.reference_glyph_byte_range(); |
1016 | 0 | self.data.read_at(range.start).ok().unwrap() |
1017 | 0 | } |
1018 | | |
1019 | | /// Index of contour point on the reference glyph |
1020 | 0 | pub fn base_coord_point(&self) -> u16 { |
1021 | 0 | let range = self.base_coord_point_byte_range(); |
1022 | 0 | self.data.read_at(range.start).ok().unwrap() |
1023 | 0 | } |
1024 | | |
1025 | 0 | pub fn base_coord_format_byte_range(&self) -> Range<usize> { |
1026 | 0 | let start = 0; |
1027 | 0 | let end = start + u16::RAW_BYTE_LEN; |
1028 | 0 | start..end |
1029 | 0 | } |
1030 | | |
1031 | 0 | pub fn coordinate_byte_range(&self) -> Range<usize> { |
1032 | 0 | let start = self.base_coord_format_byte_range().end; |
1033 | 0 | let end = start + i16::RAW_BYTE_LEN; |
1034 | 0 | start..end |
1035 | 0 | } |
1036 | | |
1037 | 0 | pub fn reference_glyph_byte_range(&self) -> Range<usize> { |
1038 | 0 | let start = self.coordinate_byte_range().end; |
1039 | 0 | let end = start + u16::RAW_BYTE_LEN; |
1040 | 0 | start..end |
1041 | 0 | } |
1042 | | |
1043 | 0 | pub fn base_coord_point_byte_range(&self) -> Range<usize> { |
1044 | 0 | let start = self.reference_glyph_byte_range().end; |
1045 | 0 | let end = start + u16::RAW_BYTE_LEN; |
1046 | 0 | start..end |
1047 | 0 | } |
1048 | | } |
1049 | | |
1050 | | impl Format<u16> for BaseCoordFormat3<'_> { |
1051 | | const FORMAT: u16 = 3; |
1052 | | } |
1053 | | |
1054 | | impl<'a> MinByteRange<'a> for BaseCoordFormat3<'a> { |
1055 | 0 | fn min_byte_range(&self) -> Range<usize> { |
1056 | 0 | 0..self.device_offset_byte_range().end |
1057 | 0 | } |
1058 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
1059 | 0 | let range = self.min_byte_range(); |
1060 | 0 | self.data.as_bytes().get(range).unwrap_or_default() |
1061 | 0 | } |
1062 | | } |
1063 | | |
1064 | | impl ReadArgs for BaseCoordFormat3<'_> { |
1065 | | type Args = (); |
1066 | | } |
1067 | | |
1068 | | impl<'a> FontRead<'a> for BaseCoordFormat3<'a> { |
1069 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
1070 | | #[allow(clippy::absurd_extreme_comparisons)] |
1071 | 0 | if data.len() < Self::MIN_SIZE { |
1072 | 0 | return Err(ReadError::OutOfBounds); |
1073 | 0 | } |
1074 | 0 | Ok(Self { data }) |
1075 | 0 | } |
1076 | | } |
1077 | | |
1078 | | /// [BaseCoordFormat3](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-3) |
1079 | | #[derive(Clone)] |
1080 | | pub struct BaseCoordFormat3<'a> { |
1081 | | data: FontData<'a>, |
1082 | | } |
1083 | | |
1084 | | #[allow(clippy::needless_lifetimes)] |
1085 | | impl<'a> BaseCoordFormat3<'a> { |
1086 | | pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN); |
1087 | | basic_table_impls!(impl_the_methods); |
1088 | | |
1089 | | /// Format identifier — format = 3 |
1090 | 0 | pub fn base_coord_format(&self) -> u16 { |
1091 | 0 | let range = self.base_coord_format_byte_range(); |
1092 | 0 | self.data.read_at(range.start).ok().unwrap() |
1093 | 0 | } |
1094 | | |
1095 | | /// X or Y value, in design units |
1096 | 0 | pub fn coordinate(&self) -> i16 { |
1097 | 0 | let range = self.coordinate_byte_range(); |
1098 | 0 | self.data.read_at(range.start).ok().unwrap() |
1099 | 0 | } |
1100 | | |
1101 | | /// Offset to Device table (non-variable font) / Variation Index |
1102 | | /// table (variable font) for X or Y value, from beginning of |
1103 | | /// BaseCoord table (may be NULL). |
1104 | 0 | pub fn device_offset(&self) -> Nullable<Offset16> { |
1105 | 0 | let range = self.device_offset_byte_range(); |
1106 | 0 | self.data.read_at(range.start).ok().unwrap() |
1107 | 0 | } |
1108 | | |
1109 | | /// Attempt to resolve [`device_offset`][Self::device_offset]. |
1110 | 0 | pub fn device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> { |
1111 | 0 | let data = self.data; |
1112 | 0 | self.device_offset().resolve(data) |
1113 | 0 | } |
1114 | | |
1115 | 0 | pub fn base_coord_format_byte_range(&self) -> Range<usize> { |
1116 | 0 | let start = 0; |
1117 | 0 | let end = start + u16::RAW_BYTE_LEN; |
1118 | 0 | start..end |
1119 | 0 | } |
1120 | | |
1121 | 0 | pub fn coordinate_byte_range(&self) -> Range<usize> { |
1122 | 0 | let start = self.base_coord_format_byte_range().end; |
1123 | 0 | let end = start + i16::RAW_BYTE_LEN; |
1124 | 0 | start..end |
1125 | 0 | } |
1126 | | |
1127 | 0 | pub fn device_offset_byte_range(&self) -> Range<usize> { |
1128 | 0 | let start = self.coordinate_byte_range().end; |
1129 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
1130 | 0 | start..end |
1131 | 0 | } |
1132 | | } |