1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Gasp<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.gasp_ranges_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl TopLevelTable for Gasp<'_> {
19 const TAG: Tag = Tag::new(b"gasp");
21}
22
23impl<'a> FontRead<'a> for Gasp<'a> {
24 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25 #[allow(clippy::absurd_extreme_comparisons)]
26 if data.len() < Self::MIN_SIZE {
27 return Err(ReadError::OutOfBounds);
28 }
29 Ok(Self { data })
30 }
31}
32
33#[derive(Clone)]
35pub struct Gasp<'a> {
36 data: FontData<'a>,
37}
38
39#[allow(clippy::needless_lifetimes)]
40impl<'a> Gasp<'a> {
41 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
42 basic_table_impls!(impl_the_methods);
43
44 pub fn version(&self) -> u16 {
46 let range = self.version_byte_range();
47 self.data.read_at(range.start).ok().unwrap()
48 }
49
50 pub fn num_ranges(&self) -> u16 {
52 let range = self.num_ranges_byte_range();
53 self.data.read_at(range.start).ok().unwrap()
54 }
55
56 pub fn gasp_ranges(&self) -> &'a [GaspRange] {
58 let range = self.gasp_ranges_byte_range();
59 self.data.read_array(range).ok().unwrap_or_default()
60 }
61
62 pub fn version_byte_range(&self) -> Range<usize> {
63 let start = 0;
64 start..start + u16::RAW_BYTE_LEN
65 }
66
67 pub fn num_ranges_byte_range(&self) -> Range<usize> {
68 let start = self.version_byte_range().end;
69 start..start + u16::RAW_BYTE_LEN
70 }
71
72 pub fn gasp_ranges_byte_range(&self) -> Range<usize> {
73 let num_ranges = self.num_ranges();
74 let start = self.num_ranges_byte_range().end;
75 start..start + (num_ranges as usize).saturating_mul(GaspRange::RAW_BYTE_LEN)
76 }
77}
78
79#[cfg(feature = "experimental_traverse")]
80impl<'a> SomeTable<'a> for Gasp<'a> {
81 fn type_name(&self) -> &str {
82 "Gasp"
83 }
84 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
85 match idx {
86 0usize => Some(Field::new("version", self.version())),
87 1usize => Some(Field::new("num_ranges", self.num_ranges())),
88 2usize => Some(Field::new(
89 "gasp_ranges",
90 traversal::FieldType::array_of_records(
91 stringify!(GaspRange),
92 self.gasp_ranges(),
93 self.offset_data(),
94 ),
95 )),
96 _ => None,
97 }
98 }
99}
100
101#[cfg(feature = "experimental_traverse")]
102#[allow(clippy::needless_lifetimes)]
103impl<'a> std::fmt::Debug for Gasp<'a> {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 (self as &dyn SomeTable<'a>).fmt(f)
106 }
107}
108
109#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
110#[repr(C)]
111#[repr(packed)]
112pub struct GaspRange {
113 pub range_max_ppem: BigEndian<u16>,
115 pub range_gasp_behavior: BigEndian<GaspRangeBehavior>,
117}
118
119impl GaspRange {
120 pub fn range_max_ppem(&self) -> u16 {
122 self.range_max_ppem.get()
123 }
124
125 pub fn range_gasp_behavior(&self) -> GaspRangeBehavior {
127 self.range_gasp_behavior.get()
128 }
129}
130
131impl FixedSize for GaspRange {
132 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + GaspRangeBehavior::RAW_BYTE_LEN;
133}
134
135#[cfg(feature = "experimental_traverse")]
136impl<'a> SomeRecord<'a> for GaspRange {
137 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
138 RecordResolver {
139 name: "GaspRange",
140 get_field: Box::new(move |idx, _data| match idx {
141 0usize => Some(Field::new("range_max_ppem", self.range_max_ppem())),
142 1usize => Some(Field::new(
143 "range_gasp_behavior",
144 self.range_gasp_behavior(),
145 )),
146 _ => None,
147 }),
148 data,
149 }
150 }
151}
152
153#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
155#[repr(transparent)]
156pub struct GaspRangeBehavior {
157 bits: u16,
158}
159
160impl GaspRangeBehavior {
161 pub const GASP_GRIDFIT: Self = Self { bits: 0x0001 };
163
164 pub const GASP_DOGRAY: Self = Self { bits: 0x0002 };
166
167 pub const GASP_SYMMETRIC_GRIDFIT: Self = Self { bits: 0x0004 };
170
171 pub const GASP_SYMMETRIC_SMOOTHING: Self = Self { bits: 0x0008 };
174}
175
176impl GaspRangeBehavior {
177 #[inline]
179 pub const fn empty() -> Self {
180 Self { bits: 0 }
181 }
182
183 #[inline]
185 pub const fn all() -> Self {
186 Self {
187 bits: Self::GASP_GRIDFIT.bits
188 | Self::GASP_DOGRAY.bits
189 | Self::GASP_SYMMETRIC_GRIDFIT.bits
190 | Self::GASP_SYMMETRIC_SMOOTHING.bits,
191 }
192 }
193
194 #[inline]
196 pub const fn bits(&self) -> u16 {
197 self.bits
198 }
199
200 #[inline]
203 pub const fn from_bits(bits: u16) -> Option<Self> {
204 if (bits & !Self::all().bits()) == 0 {
205 Some(Self { bits })
206 } else {
207 None
208 }
209 }
210
211 #[inline]
214 pub const fn from_bits_truncate(bits: u16) -> Self {
215 Self {
216 bits: bits & Self::all().bits,
217 }
218 }
219
220 #[inline]
222 pub const fn is_empty(&self) -> bool {
223 self.bits() == Self::empty().bits()
224 }
225
226 #[inline]
228 pub const fn intersects(&self, other: Self) -> bool {
229 !(Self {
230 bits: self.bits & other.bits,
231 })
232 .is_empty()
233 }
234
235 #[inline]
237 pub const fn contains(&self, other: Self) -> bool {
238 (self.bits & other.bits) == other.bits
239 }
240
241 #[inline]
243 pub fn insert(&mut self, other: Self) {
244 self.bits |= other.bits;
245 }
246
247 #[inline]
249 pub fn remove(&mut self, other: Self) {
250 self.bits &= !other.bits;
251 }
252
253 #[inline]
255 pub fn toggle(&mut self, other: Self) {
256 self.bits ^= other.bits;
257 }
258
259 #[inline]
270 #[must_use]
271 pub const fn intersection(self, other: Self) -> Self {
272 Self {
273 bits: self.bits & other.bits,
274 }
275 }
276
277 #[inline]
288 #[must_use]
289 pub const fn union(self, other: Self) -> Self {
290 Self {
291 bits: self.bits | other.bits,
292 }
293 }
294
295 #[inline]
308 #[must_use]
309 pub const fn difference(self, other: Self) -> Self {
310 Self {
311 bits: self.bits & !other.bits,
312 }
313 }
314}
315
316impl std::ops::BitOr for GaspRangeBehavior {
317 type Output = Self;
318
319 #[inline]
321 fn bitor(self, other: GaspRangeBehavior) -> Self {
322 Self {
323 bits: self.bits | other.bits,
324 }
325 }
326}
327
328impl std::ops::BitOrAssign for GaspRangeBehavior {
329 #[inline]
331 fn bitor_assign(&mut self, other: Self) {
332 self.bits |= other.bits;
333 }
334}
335
336impl std::ops::BitXor for GaspRangeBehavior {
337 type Output = Self;
338
339 #[inline]
341 fn bitxor(self, other: Self) -> Self {
342 Self {
343 bits: self.bits ^ other.bits,
344 }
345 }
346}
347
348impl std::ops::BitXorAssign for GaspRangeBehavior {
349 #[inline]
351 fn bitxor_assign(&mut self, other: Self) {
352 self.bits ^= other.bits;
353 }
354}
355
356impl std::ops::BitAnd for GaspRangeBehavior {
357 type Output = Self;
358
359 #[inline]
361 fn bitand(self, other: Self) -> Self {
362 Self {
363 bits: self.bits & other.bits,
364 }
365 }
366}
367
368impl std::ops::BitAndAssign for GaspRangeBehavior {
369 #[inline]
371 fn bitand_assign(&mut self, other: Self) {
372 self.bits &= other.bits;
373 }
374}
375
376impl std::ops::Sub for GaspRangeBehavior {
377 type Output = Self;
378
379 #[inline]
381 fn sub(self, other: Self) -> Self {
382 Self {
383 bits: self.bits & !other.bits,
384 }
385 }
386}
387
388impl std::ops::SubAssign for GaspRangeBehavior {
389 #[inline]
391 fn sub_assign(&mut self, other: Self) {
392 self.bits &= !other.bits;
393 }
394}
395
396impl std::ops::Not for GaspRangeBehavior {
397 type Output = Self;
398
399 #[inline]
401 fn not(self) -> Self {
402 Self { bits: !self.bits } & Self::all()
403 }
404}
405
406impl std::fmt::Debug for GaspRangeBehavior {
407 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
408 let members: &[(&str, Self)] = &[
409 ("GASP_GRIDFIT", Self::GASP_GRIDFIT),
410 ("GASP_DOGRAY", Self::GASP_DOGRAY),
411 ("GASP_SYMMETRIC_GRIDFIT", Self::GASP_SYMMETRIC_GRIDFIT),
412 ("GASP_SYMMETRIC_SMOOTHING", Self::GASP_SYMMETRIC_SMOOTHING),
413 ];
414 let mut first = true;
415 for (name, value) in members {
416 if self.contains(*value) {
417 if !first {
418 f.write_str(" | ")?;
419 }
420 first = false;
421 f.write_str(name)?;
422 }
423 }
424 if first {
425 f.write_str("(empty)")?;
426 }
427 Ok(())
428 }
429}
430
431impl std::fmt::Binary for GaspRangeBehavior {
432 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
433 std::fmt::Binary::fmt(&self.bits, f)
434 }
435}
436
437impl std::fmt::Octal for GaspRangeBehavior {
438 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
439 std::fmt::Octal::fmt(&self.bits, f)
440 }
441}
442
443impl std::fmt::LowerHex for GaspRangeBehavior {
444 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
445 std::fmt::LowerHex::fmt(&self.bits, f)
446 }
447}
448
449impl std::fmt::UpperHex for GaspRangeBehavior {
450 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
451 std::fmt::UpperHex::fmt(&self.bits, f)
452 }
453}
454
455impl font_types::Scalar for GaspRangeBehavior {
456 type Raw = <u16 as font_types::Scalar>::Raw;
457 fn to_raw(self) -> Self::Raw {
458 self.bits().to_raw()
459 }
460 fn from_raw(raw: Self::Raw) -> Self {
461 let t = <u16>::from_raw(raw);
462 Self::from_bits_truncate(t)
463 }
464}
465
466#[cfg(feature = "experimental_traverse")]
467impl<'a> From<GaspRangeBehavior> for FieldType<'a> {
468 fn from(src: GaspRangeBehavior) -> FieldType<'a> {
469 src.bits().into()
470 }
471}