/rust/registry/src/index.crates.io-1949cf8c6b5b557f/read-fonts-0.46.0/generated/generated_gdef.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 Gdef<'a> { |
9 | 0 | fn min_byte_range(&self) -> Range<usize> { |
10 | 0 | 0..self.mark_attach_class_def_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.offset_data().as_bytes().get(range).unwrap_or_default() |
15 | 0 | } |
16 | | } |
17 | | |
18 | | impl TopLevelTable for Gdef<'_> { |
19 | | /// `GDEF` |
20 | | const TAG: Tag = Tag::new(b"GDEF"); |
21 | | } |
22 | | |
23 | | impl ReadArgs for Gdef<'_> { |
24 | | type Args = (); |
25 | | } |
26 | | |
27 | | impl<'a> FontRead<'a> for Gdef<'a> { |
28 | 296 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
29 | | #[allow(clippy::absurd_extreme_comparisons)] |
30 | 296 | if data.len() < Self::MIN_SIZE { |
31 | 4 | return Err(ReadError::OutOfBounds); |
32 | 292 | } |
33 | 292 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
34 | 0 | return Err(ReadError::OutOfBounds); |
35 | | }; |
36 | 292 | Ok(Self { data }) |
37 | 296 | } |
38 | | } |
39 | | |
40 | | /// The fields at the start of the table, which are read directly. |
41 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
42 | | #[repr(C, packed)] |
43 | | #[doc(hidden)] |
44 | | pub struct GdefFixedHeader { |
45 | | pub version: BigEndian<MajorMinor>, |
46 | | pub glyph_class_def_offset: BigEndian<Nullable<Offset16>>, |
47 | | pub attach_list_offset: BigEndian<Nullable<Offset16>>, |
48 | | pub lig_caret_list_offset: BigEndian<Nullable<Offset16>>, |
49 | | pub mark_attach_class_def_offset: BigEndian<Nullable<Offset16>>, |
50 | | } |
51 | | |
52 | | #[allow(clippy::absurd_extreme_comparisons)] |
53 | | const _: () = assert!(std::mem::size_of::<GdefFixedHeader>() <= Gdef::MIN_SIZE); |
54 | | |
55 | | /// [GDEF](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#gdef-header) 1.0 |
56 | | #[derive(Clone)] |
57 | | pub struct Gdef<'a> { |
58 | | data: TableDataRef<'a, GdefFixedHeader>, |
59 | | } |
60 | | |
61 | | #[allow(clippy::needless_lifetimes)] |
62 | | impl<'a> Gdef<'a> { |
63 | | pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN |
64 | | + Offset16::RAW_BYTE_LEN |
65 | | + Offset16::RAW_BYTE_LEN |
66 | | + Offset16::RAW_BYTE_LEN |
67 | | + Offset16::RAW_BYTE_LEN); |
68 | | basic_table_impls!(impl_the_methods); |
69 | | |
70 | | /// The major/minor version of the GDEF table |
71 | 6.42k | pub fn version(&self) -> MajorMinor { |
72 | 6.42k | self.data.header().version.get() |
73 | 6.42k | } |
74 | | |
75 | | /// Offset to class definition table for glyph type, from beginning |
76 | | /// of GDEF header (may be NULL) |
77 | 292 | pub fn glyph_class_def_offset(&self) -> Nullable<Offset16> { |
78 | 292 | self.data.header().glyph_class_def_offset.get() |
79 | 292 | } |
80 | | |
81 | | /// Offset to attachment point list table, from beginning of GDEF |
82 | | /// header (may be NULL) |
83 | 0 | pub fn attach_list_offset(&self) -> Nullable<Offset16> { |
84 | 0 | self.data.header().attach_list_offset.get() |
85 | 0 | } |
86 | | |
87 | | /// Offset to ligature caret list table, from beginning of GDEF |
88 | | /// header (may be NULL) |
89 | 0 | pub fn lig_caret_list_offset(&self) -> Nullable<Offset16> { |
90 | 0 | self.data.header().lig_caret_list_offset.get() |
91 | 0 | } |
92 | | |
93 | | /// Offset to class definition table for mark attachment type, from |
94 | | /// beginning of GDEF header (may be NULL) |
95 | 292 | pub fn mark_attach_class_def_offset(&self) -> Nullable<Offset16> { |
96 | 292 | self.data.header().mark_attach_class_def_offset.get() |
97 | 292 | } |
98 | | |
99 | | /// Offset to the table of mark glyph set definitions, from |
100 | | /// beginning of GDEF header (may be NULL) |
101 | 292 | pub fn mark_glyph_sets_def_offset(&self) -> Option<Nullable<Offset16>> { |
102 | 292 | let range = self.mark_glyph_sets_def_offset_byte_range(); |
103 | 292 | (!range.is_empty()) |
104 | 292 | .then(|| self.offset_data().read_at(range.start).ok()) |
105 | 292 | .flatten() |
106 | 292 | } |
107 | | |
108 | | /// Offset to the Item Variation Store table, from beginning of |
109 | | /// GDEF header (may be NULL) |
110 | 292 | pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> { |
111 | 292 | let range = self.item_var_store_offset_byte_range(); |
112 | 292 | (!range.is_empty()) |
113 | 292 | .then(|| self.offset_data().read_at(range.start).ok()) |
114 | 292 | .flatten() |
115 | 292 | } |
116 | | |
117 | | /// Attempt to resolve [`item_var_store_offset`][Self::item_var_store_offset]. |
118 | 292 | pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> { |
119 | 292 | let data = self.offset_data(); |
120 | 292 | self.item_var_store_offset().map(|x| x.resolve(data))? |
121 | 292 | } |
122 | | |
123 | | /// 32-bit offset taking precedence over glyph_class_def_offset when nonzero. |
124 | 292 | pub fn glyph_class_def2_offset(&self) -> Option<Nullable<Offset32>> { |
125 | 292 | let range = self.glyph_class_def2_offset_byte_range(); |
126 | 292 | (!range.is_empty()) |
127 | 292 | .then(|| self.offset_data().read_at(range.start).ok()) |
128 | 292 | .flatten() |
129 | 292 | } |
130 | | |
131 | | /// Attempt to resolve [`glyph_class_def2_offset`][Self::glyph_class_def2_offset]. |
132 | 0 | pub fn glyph_class_def2(&self) -> Option<Result<ClassDef<'a>, ReadError>> { |
133 | 0 | let data = self.offset_data(); |
134 | 0 | self.glyph_class_def2_offset().map(|x| x.resolve(data))? |
135 | 0 | } |
136 | | |
137 | | /// 32-bit offset taking precedence over attach_list_offset when nonzero. |
138 | 0 | pub fn attach_list2_offset(&self) -> Option<Nullable<Offset32>> { |
139 | 0 | let range = self.attach_list2_offset_byte_range(); |
140 | 0 | (!range.is_empty()) |
141 | 0 | .then(|| self.offset_data().read_at(range.start).ok()) |
142 | 0 | .flatten() |
143 | 0 | } |
144 | | |
145 | | /// Attempt to resolve [`attach_list2_offset`][Self::attach_list2_offset]. |
146 | 0 | pub fn attach_list2(&self) -> Option<Result<AttachList<'a>, ReadError>> { |
147 | 0 | let data = self.offset_data(); |
148 | 0 | self.attach_list2_offset().map(|x| x.resolve(data))? |
149 | 0 | } |
150 | | |
151 | | /// 32-bit offset taking precedence over lig_caret_list_offset when nonzero. |
152 | 0 | pub fn lig_caret_list2_offset(&self) -> Option<Nullable<Offset32>> { |
153 | 0 | let range = self.lig_caret_list2_offset_byte_range(); |
154 | 0 | (!range.is_empty()) |
155 | 0 | .then(|| self.offset_data().read_at(range.start).ok()) |
156 | 0 | .flatten() |
157 | 0 | } |
158 | | |
159 | | /// Attempt to resolve [`lig_caret_list2_offset`][Self::lig_caret_list2_offset]. |
160 | 0 | pub fn lig_caret_list2(&self) -> Option<Result<LigCaretList2<'a>, ReadError>> { |
161 | 0 | let data = self.offset_data(); |
162 | 0 | self.lig_caret_list2_offset().map(|x| x.resolve(data))? |
163 | 0 | } |
164 | | |
165 | | /// 32-bit offset taking precedence over mark_attach_class_def_offset when nonzero. |
166 | 292 | pub fn mark_attach_class_def2_offset(&self) -> Option<Nullable<Offset32>> { |
167 | 292 | let range = self.mark_attach_class_def2_offset_byte_range(); |
168 | 292 | (!range.is_empty()) |
169 | 292 | .then(|| self.offset_data().read_at(range.start).ok()) |
170 | 292 | .flatten() |
171 | 292 | } |
172 | | |
173 | | /// Attempt to resolve [`mark_attach_class_def2_offset`][Self::mark_attach_class_def2_offset]. |
174 | 0 | pub fn mark_attach_class_def2(&self) -> Option<Result<ClassDef<'a>, ReadError>> { |
175 | 0 | let data = self.offset_data(); |
176 | 0 | self.mark_attach_class_def2_offset() |
177 | 0 | .map(|x| x.resolve(data))? |
178 | 0 | } |
179 | | |
180 | | /// 32-bit offset taking precedence over mark_glyph_sets_def_offset when nonzero. |
181 | 292 | pub fn mark_glyph_sets_def2_offset(&self) -> Option<Nullable<Offset32>> { |
182 | 292 | let range = self.mark_glyph_sets_def2_offset_byte_range(); |
183 | 292 | (!range.is_empty()) |
184 | 292 | .then(|| self.offset_data().read_at(range.start).ok()) |
185 | 292 | .flatten() |
186 | 292 | } |
187 | | |
188 | | /// Attempt to resolve [`mark_glyph_sets_def2_offset`][Self::mark_glyph_sets_def2_offset]. |
189 | 0 | pub fn mark_glyph_sets_def2(&self) -> Option<Result<MarkGlyphSets<'a>, ReadError>> { |
190 | 0 | let data = self.offset_data(); |
191 | 0 | self.mark_glyph_sets_def2_offset() |
192 | 0 | .map(|x| x.resolve(data))? |
193 | 0 | } |
194 | | |
195 | 1.46k | pub fn version_byte_range(&self) -> Range<usize> { |
196 | 1.46k | let start = 0; |
197 | 1.46k | let end = start + MajorMinor::RAW_BYTE_LEN; |
198 | 1.46k | start..end |
199 | 1.46k | } |
200 | | |
201 | 1.46k | pub fn glyph_class_def_offset_byte_range(&self) -> Range<usize> { |
202 | 1.46k | let start = self.version_byte_range().end; |
203 | 1.46k | let end = start + Offset16::RAW_BYTE_LEN; |
204 | 1.46k | start..end |
205 | 1.46k | } |
206 | | |
207 | 1.46k | pub fn attach_list_offset_byte_range(&self) -> Range<usize> { |
208 | 1.46k | let start = self.glyph_class_def_offset_byte_range().end; |
209 | 1.46k | let end = start + Offset16::RAW_BYTE_LEN; |
210 | 1.46k | start..end |
211 | 1.46k | } |
212 | | |
213 | 1.46k | pub fn lig_caret_list_offset_byte_range(&self) -> Range<usize> { |
214 | 1.46k | let start = self.attach_list_offset_byte_range().end; |
215 | 1.46k | let end = start + Offset16::RAW_BYTE_LEN; |
216 | 1.46k | start..end |
217 | 1.46k | } |
218 | | |
219 | 1.46k | pub fn mark_attach_class_def_offset_byte_range(&self) -> Range<usize> { |
220 | 1.46k | let start = self.lig_caret_list_offset_byte_range().end; |
221 | 1.46k | let end = start + Offset16::RAW_BYTE_LEN; |
222 | 1.46k | start..end |
223 | 1.46k | } |
224 | | |
225 | 1.46k | pub fn mark_glyph_sets_def_offset_byte_range(&self) -> Range<usize> { |
226 | 1.46k | let start = self.mark_attach_class_def_offset_byte_range().end; |
227 | 1.46k | let end = if self.version().compatible((1u16, 2u16)) { |
228 | 805 | start + Offset16::RAW_BYTE_LEN |
229 | | } else { |
230 | 655 | start |
231 | | }; |
232 | 1.46k | start..end |
233 | 1.46k | } |
234 | | |
235 | 1.16k | pub fn item_var_store_offset_byte_range(&self) -> Range<usize> { |
236 | 1.16k | let start = self.mark_glyph_sets_def_offset_byte_range().end; |
237 | 1.16k | let end = if self.version().compatible((1u16, 3u16)) { |
238 | 640 | start + Offset32::RAW_BYTE_LEN |
239 | | } else { |
240 | 528 | start |
241 | | }; |
242 | 1.16k | start..end |
243 | 1.16k | } |
244 | | |
245 | 876 | pub fn glyph_class_def2_offset_byte_range(&self) -> Range<usize> { |
246 | 876 | let start = self.item_var_store_offset_byte_range().end; |
247 | 876 | let end = if self.version().compatible((1u16, 4u16)) { |
248 | 480 | start + Offset32::RAW_BYTE_LEN |
249 | | } else { |
250 | 396 | start |
251 | | }; |
252 | 876 | start..end |
253 | 876 | } |
254 | | |
255 | 584 | pub fn attach_list2_offset_byte_range(&self) -> Range<usize> { |
256 | 584 | let start = self.glyph_class_def2_offset_byte_range().end; |
257 | 584 | let end = if self.version().compatible((1u16, 4u16)) { |
258 | 320 | start + Offset32::RAW_BYTE_LEN |
259 | | } else { |
260 | 264 | start |
261 | | }; |
262 | 584 | start..end |
263 | 584 | } |
264 | | |
265 | 584 | pub fn lig_caret_list2_offset_byte_range(&self) -> Range<usize> { |
266 | 584 | let start = self.attach_list2_offset_byte_range().end; |
267 | 584 | let end = if self.version().compatible((1u16, 4u16)) { |
268 | 320 | start + Offset32::RAW_BYTE_LEN |
269 | | } else { |
270 | 264 | start |
271 | | }; |
272 | 584 | start..end |
273 | 584 | } |
274 | | |
275 | 584 | pub fn mark_attach_class_def2_offset_byte_range(&self) -> Range<usize> { |
276 | 584 | let start = self.lig_caret_list2_offset_byte_range().end; |
277 | 584 | let end = if self.version().compatible((1u16, 4u16)) { |
278 | 320 | start + Offset32::RAW_BYTE_LEN |
279 | | } else { |
280 | 264 | start |
281 | | }; |
282 | 584 | start..end |
283 | 584 | } |
284 | | |
285 | 292 | pub fn mark_glyph_sets_def2_offset_byte_range(&self) -> Range<usize> { |
286 | 292 | let start = self.mark_attach_class_def2_offset_byte_range().end; |
287 | 292 | let end = if self.version().compatible((1u16, 4u16)) { |
288 | 160 | start + Offset32::RAW_BYTE_LEN |
289 | | } else { |
290 | 132 | start |
291 | | }; |
292 | 292 | start..end |
293 | 292 | } |
294 | | } |
295 | | |
296 | | const _: () = assert!(FontData::default_data_long_enough(Gdef::MIN_SIZE)); |
297 | | |
298 | | impl Default for Gdef<'_> { |
299 | 0 | fn default() -> Self { |
300 | | Self { |
301 | 0 | data: TableDataRef::new(FontData::default_table_data().as_bytes()) |
302 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
303 | | } |
304 | 0 | } |
305 | | } |
306 | | |
307 | | /// Used in the [Glyph Class Definition Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#glyph-class-definition-table) |
308 | | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] |
309 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
310 | | #[repr(u16)] |
311 | | #[allow(clippy::manual_non_exhaustive)] |
312 | | pub enum GlyphClassDef { |
313 | | #[default] |
314 | | Base = 1, |
315 | | Ligature = 2, |
316 | | Mark = 3, |
317 | | Component = 4, |
318 | | #[doc(hidden)] |
319 | | /// If font data is malformed we will map unknown values to this variant |
320 | | Unknown, |
321 | | } |
322 | | |
323 | | impl GlyphClassDef { |
324 | | /// Create from a raw scalar. |
325 | | /// |
326 | | /// This will never fail; unknown values will be mapped to the `Unknown` variant |
327 | 0 | pub fn new(raw: u16) -> Self { |
328 | 0 | match raw { |
329 | 0 | 1 => Self::Base, |
330 | 0 | 2 => Self::Ligature, |
331 | 0 | 3 => Self::Mark, |
332 | 0 | 4 => Self::Component, |
333 | 0 | _ => Self::Unknown, |
334 | | } |
335 | 0 | } |
336 | | } |
337 | | |
338 | | impl font_types::Scalar for GlyphClassDef { |
339 | | type Raw = <u16 as font_types::Scalar>::Raw; |
340 | 0 | fn to_raw(self) -> Self::Raw { |
341 | 0 | (self as u16).to_raw() |
342 | 0 | } |
343 | 0 | fn from_raw(raw: Self::Raw) -> Self { |
344 | 0 | let t = <u16>::from_raw(raw); |
345 | 0 | Self::new(t) |
346 | 0 | } |
347 | | } |
348 | | |
349 | | impl<'a> MinByteRange<'a> for AttachList<'a> { |
350 | 0 | fn min_byte_range(&self) -> Range<usize> { |
351 | 0 | 0..self.attach_point_offsets_byte_range().end |
352 | 0 | } |
353 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
354 | 0 | let range = self.min_byte_range(); |
355 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
356 | 0 | } |
357 | | } |
358 | | |
359 | | impl ReadArgs for AttachList<'_> { |
360 | | type Args = (); |
361 | | } |
362 | | |
363 | | impl<'a> FontRead<'a> for AttachList<'a> { |
364 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
365 | | #[allow(clippy::absurd_extreme_comparisons)] |
366 | 0 | if data.len() < Self::MIN_SIZE { |
367 | 0 | return Err(ReadError::OutOfBounds); |
368 | 0 | } |
369 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
370 | 0 | return Err(ReadError::OutOfBounds); |
371 | | }; |
372 | 0 | Ok(Self { data }) |
373 | 0 | } |
374 | | } |
375 | | |
376 | | /// The fields at the start of the table, which are read directly. |
377 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
378 | | #[repr(C, packed)] |
379 | | #[doc(hidden)] |
380 | | pub struct AttachListFixedHeader { |
381 | | pub coverage_offset: BigEndian<Offset16>, |
382 | | pub glyph_count: BigEndian<u16>, |
383 | | } |
384 | | |
385 | | #[allow(clippy::absurd_extreme_comparisons)] |
386 | | const _: () = assert!(std::mem::size_of::<AttachListFixedHeader>() <= AttachList::MIN_SIZE); |
387 | | |
388 | | /// [Attachment Point List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#attachment-point-list-table) |
389 | | #[derive(Clone)] |
390 | | pub struct AttachList<'a> { |
391 | | data: TableDataRef<'a, AttachListFixedHeader>, |
392 | | } |
393 | | |
394 | | #[allow(clippy::needless_lifetimes)] |
395 | | impl<'a> AttachList<'a> { |
396 | | pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
397 | | basic_table_impls!(impl_the_methods); |
398 | | |
399 | | /// Offset to Coverage table - from beginning of AttachList table |
400 | 0 | pub fn coverage_offset(&self) -> Offset16 { |
401 | 0 | self.data.header().coverage_offset.get() |
402 | 0 | } |
403 | | |
404 | | /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. |
405 | 0 | pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> { |
406 | 0 | let data = self.offset_data(); |
407 | 0 | self.coverage_offset().resolve(data) |
408 | 0 | } |
409 | | |
410 | | /// Number of glyphs with attachment points |
411 | 0 | pub fn glyph_count(&self) -> u16 { |
412 | 0 | self.data.header().glyph_count.get() |
413 | 0 | } |
414 | | |
415 | | /// Array of offsets to AttachPoint tables-from beginning of |
416 | | /// AttachList table-in Coverage Index order |
417 | 0 | pub fn attach_point_offsets(&self) -> &'a [BigEndian<Offset16>] { |
418 | 0 | let range = self.attach_point_offsets_byte_range(); |
419 | 0 | self.offset_data() |
420 | 0 | .read_array(range) |
421 | 0 | .ok() |
422 | 0 | .unwrap_or_default() |
423 | 0 | } |
424 | | |
425 | | /// A dynamically resolving wrapper for [`attach_point_offsets`][Self::attach_point_offsets]. |
426 | 0 | pub fn attach_points(&self) -> ArrayOfOffsets<'a, AttachPoint<'a>, Offset16> { |
427 | 0 | let data = self.offset_data(); |
428 | 0 | let offsets = self.attach_point_offsets(); |
429 | 0 | ArrayOfOffsets::new(offsets, data, ()) |
430 | 0 | } |
431 | | |
432 | 0 | pub fn coverage_offset_byte_range(&self) -> Range<usize> { |
433 | 0 | let start = 0; |
434 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
435 | 0 | start..end |
436 | 0 | } |
437 | | |
438 | 0 | pub fn glyph_count_byte_range(&self) -> Range<usize> { |
439 | 0 | let start = self.coverage_offset_byte_range().end; |
440 | 0 | let end = start + u16::RAW_BYTE_LEN; |
441 | 0 | start..end |
442 | 0 | } |
443 | | |
444 | 0 | pub fn attach_point_offsets_byte_range(&self) -> Range<usize> { |
445 | 0 | let glyph_count = self.glyph_count(); |
446 | 0 | let start = self.glyph_count_byte_range().end; |
447 | 0 | let end = |
448 | 0 | start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN); |
449 | 0 | start..end |
450 | 0 | } |
451 | | } |
452 | | |
453 | | const _: () = assert!(FontData::default_data_long_enough(AttachList::MIN_SIZE)); |
454 | | |
455 | | impl Default for AttachList<'_> { |
456 | 0 | fn default() -> Self { |
457 | | Self { |
458 | 0 | data: TableDataRef::new(FontData::default_table_data().as_bytes()) |
459 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
460 | | } |
461 | 0 | } |
462 | | } |
463 | | |
464 | | impl<'a> MinByteRange<'a> for AttachPoint<'a> { |
465 | 0 | fn min_byte_range(&self) -> Range<usize> { |
466 | 0 | 0..self.point_indices_byte_range().end |
467 | 0 | } |
468 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
469 | 0 | let range = self.min_byte_range(); |
470 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
471 | 0 | } |
472 | | } |
473 | | |
474 | | impl ReadArgs for AttachPoint<'_> { |
475 | | type Args = (); |
476 | | } |
477 | | |
478 | | impl<'a> FontRead<'a> for AttachPoint<'a> { |
479 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
480 | | #[allow(clippy::absurd_extreme_comparisons)] |
481 | 0 | if data.len() < Self::MIN_SIZE { |
482 | 0 | return Err(ReadError::OutOfBounds); |
483 | 0 | } |
484 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
485 | 0 | return Err(ReadError::OutOfBounds); |
486 | | }; |
487 | 0 | Ok(Self { data }) |
488 | 0 | } |
489 | | } |
490 | | |
491 | | /// The fields at the start of the table, which are read directly. |
492 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
493 | | #[repr(C, packed)] |
494 | | #[doc(hidden)] |
495 | | pub struct AttachPointFixedHeader { |
496 | | pub point_count: BigEndian<u16>, |
497 | | } |
498 | | |
499 | | #[allow(clippy::absurd_extreme_comparisons)] |
500 | | const _: () = assert!(std::mem::size_of::<AttachPointFixedHeader>() <= AttachPoint::MIN_SIZE); |
501 | | |
502 | | /// Part of [AttachList] |
503 | | #[derive(Clone)] |
504 | | pub struct AttachPoint<'a> { |
505 | | data: TableDataRef<'a, AttachPointFixedHeader>, |
506 | | } |
507 | | |
508 | | #[allow(clippy::needless_lifetimes)] |
509 | | impl<'a> AttachPoint<'a> { |
510 | | pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN; |
511 | | basic_table_impls!(impl_the_methods); |
512 | | |
513 | | /// Number of attachment points on this glyph |
514 | 0 | pub fn point_count(&self) -> u16 { |
515 | 0 | self.data.header().point_count.get() |
516 | 0 | } |
517 | | |
518 | | /// Array of contour point indices -in increasing numerical order |
519 | 0 | pub fn point_indices(&self) -> &'a [BigEndian<u16>] { |
520 | 0 | let range = self.point_indices_byte_range(); |
521 | 0 | self.offset_data() |
522 | 0 | .read_array(range) |
523 | 0 | .ok() |
524 | 0 | .unwrap_or_default() |
525 | 0 | } |
526 | | |
527 | 0 | pub fn point_count_byte_range(&self) -> Range<usize> { |
528 | 0 | let start = 0; |
529 | 0 | let end = start + u16::RAW_BYTE_LEN; |
530 | 0 | start..end |
531 | 0 | } |
532 | | |
533 | 0 | pub fn point_indices_byte_range(&self) -> Range<usize> { |
534 | 0 | let point_count = self.point_count(); |
535 | 0 | let start = self.point_count_byte_range().end; |
536 | 0 | let end = start + (transforms::to_usize(point_count)).saturating_mul(u16::RAW_BYTE_LEN); |
537 | 0 | start..end |
538 | 0 | } |
539 | | } |
540 | | |
541 | | const _: () = assert!(FontData::default_data_long_enough(AttachPoint::MIN_SIZE)); |
542 | | |
543 | | impl Default for AttachPoint<'_> { |
544 | 0 | fn default() -> Self { |
545 | | Self { |
546 | 0 | data: TableDataRef::new(FontData::default_table_data().as_bytes()) |
547 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
548 | | } |
549 | 0 | } |
550 | | } |
551 | | |
552 | | impl<'a> MinByteRange<'a> for LigCaretList<'a> { |
553 | 0 | fn min_byte_range(&self) -> Range<usize> { |
554 | 0 | 0..self.lig_glyph_offsets_byte_range().end |
555 | 0 | } |
556 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
557 | 0 | let range = self.min_byte_range(); |
558 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
559 | 0 | } |
560 | | } |
561 | | |
562 | | impl ReadArgs for LigCaretList<'_> { |
563 | | type Args = (); |
564 | | } |
565 | | |
566 | | impl<'a> FontRead<'a> for LigCaretList<'a> { |
567 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
568 | | #[allow(clippy::absurd_extreme_comparisons)] |
569 | 0 | if data.len() < Self::MIN_SIZE { |
570 | 0 | return Err(ReadError::OutOfBounds); |
571 | 0 | } |
572 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
573 | 0 | return Err(ReadError::OutOfBounds); |
574 | | }; |
575 | 0 | Ok(Self { data }) |
576 | 0 | } |
577 | | } |
578 | | |
579 | | /// The fields at the start of the table, which are read directly. |
580 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
581 | | #[repr(C, packed)] |
582 | | #[doc(hidden)] |
583 | | pub struct LigCaretListFixedHeader { |
584 | | pub coverage_offset: BigEndian<Offset16>, |
585 | | pub lig_glyph_count: BigEndian<u16>, |
586 | | } |
587 | | |
588 | | #[allow(clippy::absurd_extreme_comparisons)] |
589 | | const _: () = assert!(std::mem::size_of::<LigCaretListFixedHeader>() <= LigCaretList::MIN_SIZE); |
590 | | |
591 | | /// [Ligature Caret List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-caret-list-table) |
592 | | #[derive(Clone)] |
593 | | pub struct LigCaretList<'a> { |
594 | | data: TableDataRef<'a, LigCaretListFixedHeader>, |
595 | | } |
596 | | |
597 | | #[allow(clippy::needless_lifetimes)] |
598 | | impl<'a> LigCaretList<'a> { |
599 | | pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
600 | | basic_table_impls!(impl_the_methods); |
601 | | |
602 | | /// Offset to Coverage table - from beginning of LigCaretList table |
603 | 0 | pub fn coverage_offset(&self) -> Offset16 { |
604 | 0 | self.data.header().coverage_offset.get() |
605 | 0 | } |
606 | | |
607 | | /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. |
608 | 0 | pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> { |
609 | 0 | let data = self.offset_data(); |
610 | 0 | self.coverage_offset().resolve(data) |
611 | 0 | } |
612 | | |
613 | | /// Number of ligature glyphs |
614 | 0 | pub fn lig_glyph_count(&self) -> u16 { |
615 | 0 | self.data.header().lig_glyph_count.get() |
616 | 0 | } |
617 | | |
618 | | /// Array of offsets to LigGlyph tables, from beginning of |
619 | | /// LigCaretList table —in Coverage Index order |
620 | 0 | pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset16>] { |
621 | 0 | let range = self.lig_glyph_offsets_byte_range(); |
622 | 0 | self.offset_data() |
623 | 0 | .read_array(range) |
624 | 0 | .ok() |
625 | 0 | .unwrap_or_default() |
626 | 0 | } |
627 | | |
628 | | /// A dynamically resolving wrapper for [`lig_glyph_offsets`][Self::lig_glyph_offsets]. |
629 | 0 | pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset16> { |
630 | 0 | let data = self.offset_data(); |
631 | 0 | let offsets = self.lig_glyph_offsets(); |
632 | 0 | ArrayOfOffsets::new(offsets, data, ()) |
633 | 0 | } |
634 | | |
635 | 0 | pub fn coverage_offset_byte_range(&self) -> Range<usize> { |
636 | 0 | let start = 0; |
637 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
638 | 0 | start..end |
639 | 0 | } |
640 | | |
641 | 0 | pub fn lig_glyph_count_byte_range(&self) -> Range<usize> { |
642 | 0 | let start = self.coverage_offset_byte_range().end; |
643 | 0 | let end = start + u16::RAW_BYTE_LEN; |
644 | 0 | start..end |
645 | 0 | } |
646 | | |
647 | 0 | pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> { |
648 | 0 | let lig_glyph_count = self.lig_glyph_count(); |
649 | 0 | let start = self.lig_glyph_count_byte_range().end; |
650 | 0 | let end = |
651 | 0 | start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN); |
652 | 0 | start..end |
653 | 0 | } |
654 | | } |
655 | | |
656 | | const _: () = assert!(FontData::default_data_long_enough(LigCaretList::MIN_SIZE)); |
657 | | |
658 | | impl Default for LigCaretList<'_> { |
659 | 0 | fn default() -> Self { |
660 | | Self { |
661 | 0 | data: TableDataRef::new(FontData::default_table_data().as_bytes()) |
662 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
663 | | } |
664 | 0 | } |
665 | | } |
666 | | |
667 | | impl<'a> MinByteRange<'a> for LigGlyph<'a> { |
668 | 0 | fn min_byte_range(&self) -> Range<usize> { |
669 | 0 | 0..self.caret_value_offsets_byte_range().end |
670 | 0 | } |
671 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
672 | 0 | let range = self.min_byte_range(); |
673 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
674 | 0 | } |
675 | | } |
676 | | |
677 | | impl ReadArgs for LigGlyph<'_> { |
678 | | type Args = (); |
679 | | } |
680 | | |
681 | | impl<'a> FontRead<'a> for LigGlyph<'a> { |
682 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
683 | | #[allow(clippy::absurd_extreme_comparisons)] |
684 | 0 | if data.len() < Self::MIN_SIZE { |
685 | 0 | return Err(ReadError::OutOfBounds); |
686 | 0 | } |
687 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
688 | 0 | return Err(ReadError::OutOfBounds); |
689 | | }; |
690 | 0 | Ok(Self { data }) |
691 | 0 | } |
692 | | } |
693 | | |
694 | | /// The fields at the start of the table, which are read directly. |
695 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
696 | | #[repr(C, packed)] |
697 | | #[doc(hidden)] |
698 | | pub struct LigGlyphFixedHeader { |
699 | | pub caret_count: BigEndian<u16>, |
700 | | } |
701 | | |
702 | | #[allow(clippy::absurd_extreme_comparisons)] |
703 | | const _: () = assert!(std::mem::size_of::<LigGlyphFixedHeader>() <= LigGlyph::MIN_SIZE); |
704 | | |
705 | | /// [Ligature Glyph Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-glyph-table) |
706 | | #[derive(Clone)] |
707 | | pub struct LigGlyph<'a> { |
708 | | data: TableDataRef<'a, LigGlyphFixedHeader>, |
709 | | } |
710 | | |
711 | | #[allow(clippy::needless_lifetimes)] |
712 | | impl<'a> LigGlyph<'a> { |
713 | | pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN; |
714 | | basic_table_impls!(impl_the_methods); |
715 | | |
716 | | /// Number of CaretValue tables for this ligature (components - 1) |
717 | 0 | pub fn caret_count(&self) -> u16 { |
718 | 0 | self.data.header().caret_count.get() |
719 | 0 | } |
720 | | |
721 | | /// Array of offsets to CaretValue tables, from beginning of |
722 | | /// LigGlyph table — in increasing coordinate order |
723 | 0 | pub fn caret_value_offsets(&self) -> &'a [BigEndian<Offset16>] { |
724 | 0 | let range = self.caret_value_offsets_byte_range(); |
725 | 0 | self.offset_data() |
726 | 0 | .read_array(range) |
727 | 0 | .ok() |
728 | 0 | .unwrap_or_default() |
729 | 0 | } |
730 | | |
731 | | /// A dynamically resolving wrapper for [`caret_value_offsets`][Self::caret_value_offsets]. |
732 | 0 | pub fn caret_values(&self) -> ArrayOfOffsets<'a, CaretValue<'a>, Offset16> { |
733 | 0 | let data = self.offset_data(); |
734 | 0 | let offsets = self.caret_value_offsets(); |
735 | 0 | ArrayOfOffsets::new(offsets, data, ()) |
736 | 0 | } |
737 | | |
738 | 0 | pub fn caret_count_byte_range(&self) -> Range<usize> { |
739 | 0 | let start = 0; |
740 | 0 | let end = start + u16::RAW_BYTE_LEN; |
741 | 0 | start..end |
742 | 0 | } |
743 | | |
744 | 0 | pub fn caret_value_offsets_byte_range(&self) -> Range<usize> { |
745 | 0 | let caret_count = self.caret_count(); |
746 | 0 | let start = self.caret_count_byte_range().end; |
747 | 0 | let end = |
748 | 0 | start + (transforms::to_usize(caret_count)).saturating_mul(Offset16::RAW_BYTE_LEN); |
749 | 0 | start..end |
750 | 0 | } |
751 | | } |
752 | | |
753 | | const _: () = assert!(FontData::default_data_long_enough(LigGlyph::MIN_SIZE)); |
754 | | |
755 | | impl Default for LigGlyph<'_> { |
756 | 0 | fn default() -> Self { |
757 | | Self { |
758 | 0 | data: TableDataRef::new(FontData::default_table_data().as_bytes()) |
759 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
760 | | } |
761 | 0 | } |
762 | | } |
763 | | |
764 | | /// [Caret Value Tables](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caret-value-tables) |
765 | | #[derive(Clone)] |
766 | | pub enum CaretValue<'a> { |
767 | | Format1(CaretValueFormat1<'a>), |
768 | | Format2(CaretValueFormat2<'a>), |
769 | | Format3(CaretValueFormat3<'a>), |
770 | | } |
771 | | |
772 | | impl Default for CaretValue<'_> { |
773 | 0 | fn default() -> Self { |
774 | 0 | Self::Format1(Default::default()) |
775 | 0 | } |
776 | | } |
777 | | |
778 | | impl<'a> CaretValue<'a> { |
779 | | ///Return the `FontData` used to resolve offsets for this table. |
780 | 0 | pub fn offset_data(&self) -> FontData<'a> { |
781 | 0 | match self { |
782 | 0 | Self::Format1(item) => item.offset_data(), |
783 | 0 | Self::Format2(item) => item.offset_data(), |
784 | 0 | Self::Format3(item) => item.offset_data(), |
785 | | } |
786 | 0 | } |
787 | | |
788 | | /// Format identifier: format = 1 |
789 | 0 | pub fn caret_value_format(&self) -> u16 { |
790 | 0 | match self { |
791 | 0 | Self::Format1(item) => item.caret_value_format(), |
792 | 0 | Self::Format2(item) => item.caret_value_format(), |
793 | 0 | Self::Format3(item) => item.caret_value_format(), |
794 | | } |
795 | 0 | } |
796 | | } |
797 | | |
798 | | impl ReadArgs for CaretValue<'_> { |
799 | | type Args = (); |
800 | | } |
801 | | |
802 | | impl<'a> FontRead<'a> for CaretValue<'a> { |
803 | | #[inline] |
804 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
805 | 0 | let format: u16 = data.read_at(0usize)?; |
806 | 0 | match format { |
807 | 0 | CaretValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)), |
808 | 0 | CaretValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)), |
809 | 0 | CaretValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)), |
810 | 0 | other => Err(ReadError::InvalidFormat(other.into())), |
811 | | } |
812 | 0 | } |
813 | | } |
814 | | |
815 | | impl<'a> MinByteRange<'a> for CaretValue<'a> { |
816 | 0 | fn min_byte_range(&self) -> Range<usize> { |
817 | 0 | match self { |
818 | 0 | Self::Format1(item) => item.min_byte_range(), |
819 | 0 | Self::Format2(item) => item.min_byte_range(), |
820 | 0 | Self::Format3(item) => item.min_byte_range(), |
821 | | } |
822 | 0 | } |
823 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
824 | 0 | match self { |
825 | 0 | Self::Format1(item) => item.min_table_bytes(), |
826 | 0 | Self::Format2(item) => item.min_table_bytes(), |
827 | 0 | Self::Format3(item) => item.min_table_bytes(), |
828 | | } |
829 | 0 | } |
830 | | } |
831 | | |
832 | | impl Format<u16> for CaretValueFormat1<'_> { |
833 | | const FORMAT: u16 = 1; |
834 | | } |
835 | | |
836 | | impl<'a> MinByteRange<'a> for CaretValueFormat1<'a> { |
837 | 0 | fn min_byte_range(&self) -> Range<usize> { |
838 | 0 | 0..self.coordinate_byte_range().end |
839 | 0 | } |
840 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
841 | 0 | let range = self.min_byte_range(); |
842 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
843 | 0 | } |
844 | | } |
845 | | |
846 | | impl ReadArgs for CaretValueFormat1<'_> { |
847 | | type Args = (); |
848 | | } |
849 | | |
850 | | impl<'a> FontRead<'a> for CaretValueFormat1<'a> { |
851 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
852 | | #[allow(clippy::absurd_extreme_comparisons)] |
853 | 0 | if data.len() < Self::MIN_SIZE { |
854 | 0 | return Err(ReadError::OutOfBounds); |
855 | 0 | } |
856 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
857 | 0 | return Err(ReadError::OutOfBounds); |
858 | | }; |
859 | 0 | Ok(Self { data }) |
860 | 0 | } |
861 | | } |
862 | | |
863 | | /// The fields at the start of the table, which are read directly. |
864 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
865 | | #[repr(C, packed)] |
866 | | #[doc(hidden)] |
867 | | pub struct CaretValueFormat1FixedHeader { |
868 | | pub caret_value_format: BigEndian<u16>, |
869 | | pub coordinate: BigEndian<i16>, |
870 | | } |
871 | | |
872 | | #[allow(clippy::absurd_extreme_comparisons)] |
873 | | const _: () = |
874 | | assert!(std::mem::size_of::<CaretValueFormat1FixedHeader>() <= CaretValueFormat1::MIN_SIZE); |
875 | | |
876 | | /// [CaretValue Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-1) |
877 | | #[derive(Clone)] |
878 | | pub struct CaretValueFormat1<'a> { |
879 | | data: TableDataRef<'a, CaretValueFormat1FixedHeader>, |
880 | | } |
881 | | |
882 | | #[allow(clippy::needless_lifetimes)] |
883 | | impl<'a> CaretValueFormat1<'a> { |
884 | | pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN); |
885 | | basic_table_impls!(impl_the_methods); |
886 | | |
887 | | /// Format identifier: format = 1 |
888 | 0 | pub fn caret_value_format(&self) -> u16 { |
889 | 0 | self.data.header().caret_value_format.get() |
890 | 0 | } |
891 | | |
892 | | /// X or Y value, in design units |
893 | 0 | pub fn coordinate(&self) -> i16 { |
894 | 0 | self.data.header().coordinate.get() |
895 | 0 | } |
896 | | |
897 | 0 | pub fn caret_value_format_byte_range(&self) -> Range<usize> { |
898 | 0 | let start = 0; |
899 | 0 | let end = start + u16::RAW_BYTE_LEN; |
900 | 0 | start..end |
901 | 0 | } |
902 | | |
903 | 0 | pub fn coordinate_byte_range(&self) -> Range<usize> { |
904 | 0 | let start = self.caret_value_format_byte_range().end; |
905 | 0 | let end = start + i16::RAW_BYTE_LEN; |
906 | 0 | start..end |
907 | 0 | } |
908 | | } |
909 | | |
910 | | const _: () = assert!(FontData::default_data_long_enough( |
911 | | CaretValueFormat1::MIN_SIZE |
912 | | )); |
913 | | |
914 | | impl Default for CaretValueFormat1<'_> { |
915 | 0 | fn default() -> Self { |
916 | | Self { |
917 | 0 | data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes()) |
918 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
919 | | } |
920 | 0 | } |
921 | | } |
922 | | |
923 | | impl Format<u16> for CaretValueFormat2<'_> { |
924 | | const FORMAT: u16 = 2; |
925 | | } |
926 | | |
927 | | impl<'a> MinByteRange<'a> for CaretValueFormat2<'a> { |
928 | 0 | fn min_byte_range(&self) -> Range<usize> { |
929 | 0 | 0..self.caret_value_point_index_byte_range().end |
930 | 0 | } |
931 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
932 | 0 | let range = self.min_byte_range(); |
933 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
934 | 0 | } |
935 | | } |
936 | | |
937 | | impl ReadArgs for CaretValueFormat2<'_> { |
938 | | type Args = (); |
939 | | } |
940 | | |
941 | | impl<'a> FontRead<'a> for CaretValueFormat2<'a> { |
942 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
943 | | #[allow(clippy::absurd_extreme_comparisons)] |
944 | 0 | if data.len() < Self::MIN_SIZE { |
945 | 0 | return Err(ReadError::OutOfBounds); |
946 | 0 | } |
947 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
948 | 0 | return Err(ReadError::OutOfBounds); |
949 | | }; |
950 | 0 | Ok(Self { data }) |
951 | 0 | } |
952 | | } |
953 | | |
954 | | /// The fields at the start of the table, which are read directly. |
955 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
956 | | #[repr(C, packed)] |
957 | | #[doc(hidden)] |
958 | | pub struct CaretValueFormat2FixedHeader { |
959 | | pub caret_value_format: BigEndian<u16>, |
960 | | pub caret_value_point_index: BigEndian<u16>, |
961 | | } |
962 | | |
963 | | #[allow(clippy::absurd_extreme_comparisons)] |
964 | | const _: () = |
965 | | assert!(std::mem::size_of::<CaretValueFormat2FixedHeader>() <= CaretValueFormat2::MIN_SIZE); |
966 | | |
967 | | /// [CaretValue Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-2) |
968 | | #[derive(Clone)] |
969 | | pub struct CaretValueFormat2<'a> { |
970 | | data: TableDataRef<'a, CaretValueFormat2FixedHeader>, |
971 | | } |
972 | | |
973 | | #[allow(clippy::needless_lifetimes)] |
974 | | impl<'a> CaretValueFormat2<'a> { |
975 | | pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
976 | | basic_table_impls!(impl_the_methods); |
977 | | |
978 | | /// Format identifier: format = 2 |
979 | 0 | pub fn caret_value_format(&self) -> u16 { |
980 | 0 | self.data.header().caret_value_format.get() |
981 | 0 | } |
982 | | |
983 | | /// Contour point index on glyph |
984 | 0 | pub fn caret_value_point_index(&self) -> u16 { |
985 | 0 | self.data.header().caret_value_point_index.get() |
986 | 0 | } |
987 | | |
988 | 0 | pub fn caret_value_format_byte_range(&self) -> Range<usize> { |
989 | 0 | let start = 0; |
990 | 0 | let end = start + u16::RAW_BYTE_LEN; |
991 | 0 | start..end |
992 | 0 | } |
993 | | |
994 | 0 | pub fn caret_value_point_index_byte_range(&self) -> Range<usize> { |
995 | 0 | let start = self.caret_value_format_byte_range().end; |
996 | 0 | let end = start + u16::RAW_BYTE_LEN; |
997 | 0 | start..end |
998 | 0 | } |
999 | | } |
1000 | | |
1001 | | impl Format<u16> for CaretValueFormat3<'_> { |
1002 | | const FORMAT: u16 = 3; |
1003 | | } |
1004 | | |
1005 | | impl<'a> MinByteRange<'a> for CaretValueFormat3<'a> { |
1006 | 0 | fn min_byte_range(&self) -> Range<usize> { |
1007 | 0 | 0..self.device_offset_byte_range().end |
1008 | 0 | } |
1009 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
1010 | 0 | let range = self.min_byte_range(); |
1011 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
1012 | 0 | } |
1013 | | } |
1014 | | |
1015 | | impl ReadArgs for CaretValueFormat3<'_> { |
1016 | | type Args = (); |
1017 | | } |
1018 | | |
1019 | | impl<'a> FontRead<'a> for CaretValueFormat3<'a> { |
1020 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
1021 | | #[allow(clippy::absurd_extreme_comparisons)] |
1022 | 0 | if data.len() < Self::MIN_SIZE { |
1023 | 0 | return Err(ReadError::OutOfBounds); |
1024 | 0 | } |
1025 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
1026 | 0 | return Err(ReadError::OutOfBounds); |
1027 | | }; |
1028 | 0 | Ok(Self { data }) |
1029 | 0 | } |
1030 | | } |
1031 | | |
1032 | | /// The fields at the start of the table, which are read directly. |
1033 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
1034 | | #[repr(C, packed)] |
1035 | | #[doc(hidden)] |
1036 | | pub struct CaretValueFormat3FixedHeader { |
1037 | | pub caret_value_format: BigEndian<u16>, |
1038 | | pub coordinate: BigEndian<i16>, |
1039 | | pub device_offset: BigEndian<Offset16>, |
1040 | | } |
1041 | | |
1042 | | #[allow(clippy::absurd_extreme_comparisons)] |
1043 | | const _: () = |
1044 | | assert!(std::mem::size_of::<CaretValueFormat3FixedHeader>() <= CaretValueFormat3::MIN_SIZE); |
1045 | | |
1046 | | /// [CaretValue Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-3) |
1047 | | #[derive(Clone)] |
1048 | | pub struct CaretValueFormat3<'a> { |
1049 | | data: TableDataRef<'a, CaretValueFormat3FixedHeader>, |
1050 | | } |
1051 | | |
1052 | | #[allow(clippy::needless_lifetimes)] |
1053 | | impl<'a> CaretValueFormat3<'a> { |
1054 | | pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN); |
1055 | | basic_table_impls!(impl_the_methods); |
1056 | | |
1057 | | /// Format identifier-format = 3 |
1058 | 0 | pub fn caret_value_format(&self) -> u16 { |
1059 | 0 | self.data.header().caret_value_format.get() |
1060 | 0 | } |
1061 | | |
1062 | | /// X or Y value, in design units |
1063 | 0 | pub fn coordinate(&self) -> i16 { |
1064 | 0 | self.data.header().coordinate.get() |
1065 | 0 | } |
1066 | | |
1067 | | /// Offset to Device table (non-variable font) / Variation Index |
1068 | | /// table (variable font) for X or Y value-from beginning of |
1069 | | /// CaretValue table |
1070 | 0 | pub fn device_offset(&self) -> Offset16 { |
1071 | 0 | self.data.header().device_offset.get() |
1072 | 0 | } |
1073 | | |
1074 | | /// Attempt to resolve [`device_offset`][Self::device_offset]. |
1075 | 0 | pub fn device(&self) -> Result<DeviceOrVariationIndex<'a>, ReadError> { |
1076 | 0 | let data = self.offset_data(); |
1077 | 0 | self.device_offset().resolve(data) |
1078 | 0 | } |
1079 | | |
1080 | 0 | pub fn caret_value_format_byte_range(&self) -> Range<usize> { |
1081 | 0 | let start = 0; |
1082 | 0 | let end = start + u16::RAW_BYTE_LEN; |
1083 | 0 | start..end |
1084 | 0 | } |
1085 | | |
1086 | 0 | pub fn coordinate_byte_range(&self) -> Range<usize> { |
1087 | 0 | let start = self.caret_value_format_byte_range().end; |
1088 | 0 | let end = start + i16::RAW_BYTE_LEN; |
1089 | 0 | start..end |
1090 | 0 | } |
1091 | | |
1092 | 0 | pub fn device_offset_byte_range(&self) -> Range<usize> { |
1093 | 0 | let start = self.coordinate_byte_range().end; |
1094 | 0 | let end = start + Offset16::RAW_BYTE_LEN; |
1095 | 0 | start..end |
1096 | 0 | } |
1097 | | } |
1098 | | |
1099 | | impl Format<u16> for MarkGlyphSets<'_> { |
1100 | | const FORMAT: u16 = 1; |
1101 | | } |
1102 | | |
1103 | | impl<'a> MinByteRange<'a> for MarkGlyphSets<'a> { |
1104 | 0 | fn min_byte_range(&self) -> Range<usize> { |
1105 | 0 | 0..self.coverage_offsets_byte_range().end |
1106 | 0 | } |
1107 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
1108 | 0 | let range = self.min_byte_range(); |
1109 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
1110 | 0 | } |
1111 | | } |
1112 | | |
1113 | | impl ReadArgs for MarkGlyphSets<'_> { |
1114 | | type Args = (); |
1115 | | } |
1116 | | |
1117 | | impl<'a> FontRead<'a> for MarkGlyphSets<'a> { |
1118 | 72 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
1119 | | #[allow(clippy::absurd_extreme_comparisons)] |
1120 | 72 | if data.len() < Self::MIN_SIZE { |
1121 | 0 | return Err(ReadError::OutOfBounds); |
1122 | 72 | } |
1123 | 72 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
1124 | 0 | return Err(ReadError::OutOfBounds); |
1125 | | }; |
1126 | 72 | Ok(Self { data }) |
1127 | 72 | } |
1128 | | } |
1129 | | |
1130 | | /// The fields at the start of the table, which are read directly. |
1131 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
1132 | | #[repr(C, packed)] |
1133 | | #[doc(hidden)] |
1134 | | pub struct MarkGlyphSetsFixedHeader { |
1135 | | pub format: BigEndian<u16>, |
1136 | | pub mark_glyph_set_count: BigEndian<u16>, |
1137 | | } |
1138 | | |
1139 | | #[allow(clippy::absurd_extreme_comparisons)] |
1140 | | const _: () = assert!(std::mem::size_of::<MarkGlyphSetsFixedHeader>() <= MarkGlyphSets::MIN_SIZE); |
1141 | | |
1142 | | /// [Mark Glyph Sets Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#mark-glyph-sets-table) |
1143 | | #[derive(Clone)] |
1144 | | pub struct MarkGlyphSets<'a> { |
1145 | | data: TableDataRef<'a, MarkGlyphSetsFixedHeader>, |
1146 | | } |
1147 | | |
1148 | | #[allow(clippy::needless_lifetimes)] |
1149 | | impl<'a> MarkGlyphSets<'a> { |
1150 | | pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN); |
1151 | | basic_table_impls!(impl_the_methods); |
1152 | | |
1153 | | /// Format identifier == 1 |
1154 | 0 | pub fn format(&self) -> u16 { |
1155 | 0 | self.data.header().format.get() |
1156 | 0 | } |
1157 | | |
1158 | | /// Number of mark glyph sets defined |
1159 | 72 | pub fn mark_glyph_set_count(&self) -> u16 { |
1160 | 72 | self.data.header().mark_glyph_set_count.get() |
1161 | 72 | } |
1162 | | |
1163 | | /// Array of offsets to mark glyph set coverage tables, from the |
1164 | | /// start of the MarkGlyphSets table. |
1165 | 72 | pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset32>] { |
1166 | 72 | let range = self.coverage_offsets_byte_range(); |
1167 | 72 | self.offset_data() |
1168 | 72 | .read_array(range) |
1169 | 72 | .ok() |
1170 | 72 | .unwrap_or_default() |
1171 | 72 | } |
1172 | | |
1173 | | /// A dynamically resolving wrapper for [`coverage_offsets`][Self::coverage_offsets]. |
1174 | 72 | pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset32> { |
1175 | 72 | let data = self.offset_data(); |
1176 | 72 | let offsets = self.coverage_offsets(); |
1177 | 72 | ArrayOfOffsets::new(offsets, data, ()) |
1178 | 72 | } |
1179 | | |
1180 | 72 | pub fn format_byte_range(&self) -> Range<usize> { |
1181 | 72 | let start = 0; |
1182 | 72 | let end = start + u16::RAW_BYTE_LEN; |
1183 | 72 | start..end |
1184 | 72 | } |
1185 | | |
1186 | 72 | pub fn mark_glyph_set_count_byte_range(&self) -> Range<usize> { |
1187 | 72 | let start = self.format_byte_range().end; |
1188 | 72 | let end = start + u16::RAW_BYTE_LEN; |
1189 | 72 | start..end |
1190 | 72 | } |
1191 | | |
1192 | 72 | pub fn coverage_offsets_byte_range(&self) -> Range<usize> { |
1193 | 72 | let mark_glyph_set_count = self.mark_glyph_set_count(); |
1194 | 72 | let start = self.mark_glyph_set_count_byte_range().end; |
1195 | 72 | let end = start |
1196 | 72 | + (transforms::to_usize(mark_glyph_set_count)).saturating_mul(Offset32::RAW_BYTE_LEN); |
1197 | 72 | start..end |
1198 | 72 | } |
1199 | | } |
1200 | | |
1201 | | const _: () = assert!(FontData::default_data_long_enough(MarkGlyphSets::MIN_SIZE)); |
1202 | | |
1203 | | impl Default for MarkGlyphSets<'_> { |
1204 | 0 | fn default() -> Self { |
1205 | | Self { |
1206 | 0 | data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes()) |
1207 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
1208 | | } |
1209 | 0 | } |
1210 | | } |
1211 | | |
1212 | | impl<'a> MinByteRange<'a> for LigCaretList2<'a> { |
1213 | 0 | fn min_byte_range(&self) -> Range<usize> { |
1214 | 0 | 0..self.lig_glyph_offsets_byte_range().end |
1215 | 0 | } |
1216 | 0 | fn min_table_bytes(&self) -> &'a [u8] { |
1217 | 0 | let range = self.min_byte_range(); |
1218 | 0 | self.offset_data().as_bytes().get(range).unwrap_or_default() |
1219 | 0 | } |
1220 | | } |
1221 | | |
1222 | | impl ReadArgs for LigCaretList2<'_> { |
1223 | | type Args = (); |
1224 | | } |
1225 | | |
1226 | | impl<'a> FontRead<'a> for LigCaretList2<'a> { |
1227 | 0 | fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> { |
1228 | | #[allow(clippy::absurd_extreme_comparisons)] |
1229 | 0 | if data.len() < Self::MIN_SIZE { |
1230 | 0 | return Err(ReadError::OutOfBounds); |
1231 | 0 | } |
1232 | 0 | let Some(data) = TableDataRef::new(data.as_bytes()) else { |
1233 | 0 | return Err(ReadError::OutOfBounds); |
1234 | | }; |
1235 | 0 | Ok(Self { data }) |
1236 | 0 | } |
1237 | | } |
1238 | | |
1239 | | /// The fields at the start of the table, which are read directly. |
1240 | | #[derive(Clone, Copy, bytemuck :: AnyBitPattern)] |
1241 | | #[repr(C, packed)] |
1242 | | #[doc(hidden)] |
1243 | | pub struct LigCaretList2FixedHeader { |
1244 | | pub coverage_offset: BigEndian<Offset32>, |
1245 | | pub lig_glyph_count: BigEndian<Uint24>, |
1246 | | } |
1247 | | |
1248 | | #[allow(clippy::absurd_extreme_comparisons)] |
1249 | | const _: () = assert!(std::mem::size_of::<LigCaretList2FixedHeader>() <= LigCaretList2::MIN_SIZE); |
1250 | | |
1251 | | /// LigCaretList2 (ISO/IEC 14496-22:2026). |
1252 | | #[derive(Clone)] |
1253 | | pub struct LigCaretList2<'a> { |
1254 | | data: TableDataRef<'a, LigCaretList2FixedHeader>, |
1255 | | } |
1256 | | |
1257 | | #[allow(clippy::needless_lifetimes)] |
1258 | | impl<'a> LigCaretList2<'a> { |
1259 | | pub const MIN_SIZE: usize = (Offset32::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN); |
1260 | | basic_table_impls!(impl_the_methods); |
1261 | | |
1262 | | /// Offset to Coverage table - from beginning of LigCaretList2 table |
1263 | 0 | pub fn coverage_offset(&self) -> Offset32 { |
1264 | 0 | self.data.header().coverage_offset.get() |
1265 | 0 | } |
1266 | | |
1267 | | /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. |
1268 | 0 | pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> { |
1269 | 0 | let data = self.offset_data(); |
1270 | 0 | self.coverage_offset().resolve(data) |
1271 | 0 | } |
1272 | | |
1273 | | /// Number of ligature glyphs |
1274 | 0 | pub fn lig_glyph_count(&self) -> Uint24 { |
1275 | 0 | self.data.header().lig_glyph_count.get() |
1276 | 0 | } |
1277 | | |
1278 | | /// Array of offsets to LigGlyph tables, from beginning of |
1279 | | /// LigCaretList2 table —in Coverage Index order |
1280 | 0 | pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset24>] { |
1281 | 0 | let range = self.lig_glyph_offsets_byte_range(); |
1282 | 0 | self.offset_data() |
1283 | 0 | .read_array(range) |
1284 | 0 | .ok() |
1285 | 0 | .unwrap_or_default() |
1286 | 0 | } |
1287 | | |
1288 | | /// A dynamically resolving wrapper for [`lig_glyph_offsets`][Self::lig_glyph_offsets]. |
1289 | 0 | pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset24> { |
1290 | 0 | let data = self.offset_data(); |
1291 | 0 | let offsets = self.lig_glyph_offsets(); |
1292 | 0 | ArrayOfOffsets::new(offsets, data, ()) |
1293 | 0 | } |
1294 | | |
1295 | 0 | pub fn coverage_offset_byte_range(&self) -> Range<usize> { |
1296 | 0 | let start = 0; |
1297 | 0 | let end = start + Offset32::RAW_BYTE_LEN; |
1298 | 0 | start..end |
1299 | 0 | } |
1300 | | |
1301 | 0 | pub fn lig_glyph_count_byte_range(&self) -> Range<usize> { |
1302 | 0 | let start = self.coverage_offset_byte_range().end; |
1303 | 0 | let end = start + Uint24::RAW_BYTE_LEN; |
1304 | 0 | start..end |
1305 | 0 | } |
1306 | | |
1307 | 0 | pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> { |
1308 | 0 | let lig_glyph_count = self.lig_glyph_count(); |
1309 | 0 | let start = self.lig_glyph_count_byte_range().end; |
1310 | 0 | let end = |
1311 | 0 | start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset24::RAW_BYTE_LEN); |
1312 | 0 | start..end |
1313 | 0 | } |
1314 | | } |
1315 | | |
1316 | | const _: () = assert!(FontData::default_data_long_enough(LigCaretList2::MIN_SIZE)); |
1317 | | |
1318 | | impl Default for LigCaretList2<'_> { |
1319 | 0 | fn default() -> Self { |
1320 | | Self { |
1321 | 0 | data: TableDataRef::new(FontData::default_table_data().as_bytes()) |
1322 | 0 | .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")), |
1323 | | } |
1324 | 0 | } |
1325 | | } |