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 let end = start + u16::RAW_BYTE_LEN;
65 start..end
66 }
67
68 pub fn num_ranges_byte_range(&self) -> Range<usize> {
69 let start = self.version_byte_range().end;
70 let end = start + u16::RAW_BYTE_LEN;
71 start..end
72 }
73
74 pub fn gasp_ranges_byte_range(&self) -> Range<usize> {
75 let num_ranges = self.num_ranges();
76 let start = self.num_ranges_byte_range().end;
77 let end =
78 start + (transforms::to_usize(num_ranges)).saturating_mul(GaspRange::RAW_BYTE_LEN);
79 start..end
80 }
81}
82
83const _: () = assert!(FontData::default_data_long_enough(Gasp::MIN_SIZE));
84
85impl Default for Gasp<'_> {
86 fn default() -> Self {
87 Self {
88 data: FontData::default_table_data(),
89 }
90 }
91}
92
93#[cfg(feature = "experimental_traverse")]
94impl<'a> SomeTable<'a> for Gasp<'a> {
95 fn type_name(&self) -> &str {
96 "Gasp"
97 }
98 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
99 match idx {
100 0usize => Some(Field::new("version", self.version())),
101 1usize => Some(Field::new("num_ranges", self.num_ranges())),
102 2usize => Some(Field::new(
103 "gasp_ranges",
104 traversal::FieldType::array_of_records(
105 stringify!(GaspRange),
106 self.gasp_ranges(),
107 self.offset_data(),
108 ),
109 )),
110 _ => None,
111 }
112 }
113}
114
115#[cfg(feature = "experimental_traverse")]
116#[allow(clippy::needless_lifetimes)]
117impl<'a> std::fmt::Debug for Gasp<'a> {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 (self as &dyn SomeTable<'a>).fmt(f)
120 }
121}
122
123#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
124#[repr(C)]
125#[repr(packed)]
126pub struct GaspRange {
127 pub range_max_ppem: BigEndian<u16>,
129 pub range_gasp_behavior: BigEndian<GaspRangeBehavior>,
131}
132
133impl GaspRange {
134 pub fn range_max_ppem(&self) -> u16 {
136 self.range_max_ppem.get()
137 }
138
139 pub fn range_gasp_behavior(&self) -> GaspRangeBehavior {
141 self.range_gasp_behavior.get()
142 }
143}
144
145impl FixedSize for GaspRange {
146 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + GaspRangeBehavior::RAW_BYTE_LEN;
147}
148
149#[cfg(feature = "experimental_traverse")]
150impl<'a> SomeRecord<'a> for GaspRange {
151 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
152 RecordResolver {
153 name: "GaspRange",
154 get_field: Box::new(move |idx, _data| match idx {
155 0usize => Some(Field::new("range_max_ppem", self.range_max_ppem())),
156 1usize => Some(Field::new(
157 "range_gasp_behavior",
158 self.range_gasp_behavior(),
159 )),
160 _ => None,
161 }),
162 data,
163 }
164 }
165}
166
167#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
168#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
169#[repr(transparent)]
170pub struct GaspRangeBehavior {
171 bits: u16,
172}
173
174impl GaspRangeBehavior {
175 pub const GASP_GRIDFIT: Self = Self { bits: 0x0001 };
177
178 pub const GASP_DOGRAY: Self = Self { bits: 0x0002 };
180
181 pub const GASP_SYMMETRIC_GRIDFIT: Self = Self { bits: 0x0004 };
184
185 pub const GASP_SYMMETRIC_SMOOTHING: Self = Self { bits: 0x0008 };
188}
189
190impl GaspRangeBehavior {
191 #[inline]
193 pub const fn empty() -> Self {
194 Self { bits: 0 }
195 }
196
197 #[inline]
199 pub const fn all() -> Self {
200 Self {
201 bits: Self::GASP_GRIDFIT.bits
202 | Self::GASP_DOGRAY.bits
203 | Self::GASP_SYMMETRIC_GRIDFIT.bits
204 | Self::GASP_SYMMETRIC_SMOOTHING.bits,
205 }
206 }
207
208 #[inline]
210 pub const fn bits(&self) -> u16 {
211 self.bits
212 }
213
214 #[inline]
217 pub const fn from_bits(bits: u16) -> Option<Self> {
218 if (bits & !Self::all().bits()) == 0 {
219 Some(Self { bits })
220 } else {
221 None
222 }
223 }
224
225 #[inline]
228 pub const fn from_bits_truncate(bits: u16) -> Self {
229 Self {
230 bits: bits & Self::all().bits,
231 }
232 }
233
234 #[inline]
236 pub const fn is_empty(&self) -> bool {
237 self.bits() == Self::empty().bits()
238 }
239
240 #[inline]
242 pub const fn intersects(&self, other: Self) -> bool {
243 !(Self {
244 bits: self.bits & other.bits,
245 })
246 .is_empty()
247 }
248
249 #[inline]
251 pub const fn contains(&self, other: Self) -> bool {
252 (self.bits & other.bits) == other.bits
253 }
254
255 #[inline]
257 pub fn insert(&mut self, other: Self) {
258 self.bits |= other.bits;
259 }
260
261 #[inline]
263 pub fn remove(&mut self, other: Self) {
264 self.bits &= !other.bits;
265 }
266
267 #[inline]
269 pub fn toggle(&mut self, other: Self) {
270 self.bits ^= other.bits;
271 }
272
273 #[inline]
284 #[must_use]
285 pub const fn intersection(self, other: Self) -> Self {
286 Self {
287 bits: self.bits & other.bits,
288 }
289 }
290
291 #[inline]
302 #[must_use]
303 pub const fn union(self, other: Self) -> Self {
304 Self {
305 bits: self.bits | other.bits,
306 }
307 }
308
309 #[inline]
322 #[must_use]
323 pub const fn difference(self, other: Self) -> Self {
324 Self {
325 bits: self.bits & !other.bits,
326 }
327 }
328}
329
330impl std::ops::BitOr for GaspRangeBehavior {
331 type Output = Self;
332
333 #[inline]
335 fn bitor(self, other: GaspRangeBehavior) -> Self {
336 Self {
337 bits: self.bits | other.bits,
338 }
339 }
340}
341
342impl std::ops::BitOrAssign for GaspRangeBehavior {
343 #[inline]
345 fn bitor_assign(&mut self, other: Self) {
346 self.bits |= other.bits;
347 }
348}
349
350impl std::ops::BitXor for GaspRangeBehavior {
351 type Output = Self;
352
353 #[inline]
355 fn bitxor(self, other: Self) -> Self {
356 Self {
357 bits: self.bits ^ other.bits,
358 }
359 }
360}
361
362impl std::ops::BitXorAssign for GaspRangeBehavior {
363 #[inline]
365 fn bitxor_assign(&mut self, other: Self) {
366 self.bits ^= other.bits;
367 }
368}
369
370impl std::ops::BitAnd for GaspRangeBehavior {
371 type Output = Self;
372
373 #[inline]
375 fn bitand(self, other: Self) -> Self {
376 Self {
377 bits: self.bits & other.bits,
378 }
379 }
380}
381
382impl std::ops::BitAndAssign for GaspRangeBehavior {
383 #[inline]
385 fn bitand_assign(&mut self, other: Self) {
386 self.bits &= other.bits;
387 }
388}
389
390impl std::ops::Sub for GaspRangeBehavior {
391 type Output = Self;
392
393 #[inline]
395 fn sub(self, other: Self) -> Self {
396 Self {
397 bits: self.bits & !other.bits,
398 }
399 }
400}
401
402impl std::ops::SubAssign for GaspRangeBehavior {
403 #[inline]
405 fn sub_assign(&mut self, other: Self) {
406 self.bits &= !other.bits;
407 }
408}
409
410impl std::ops::Not for GaspRangeBehavior {
411 type Output = Self;
412
413 #[inline]
415 fn not(self) -> Self {
416 Self { bits: !self.bits } & Self::all()
417 }
418}
419
420impl std::fmt::Debug for GaspRangeBehavior {
421 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
422 let members: &[(&str, Self)] = &[
423 ("GASP_GRIDFIT", Self::GASP_GRIDFIT),
424 ("GASP_DOGRAY", Self::GASP_DOGRAY),
425 ("GASP_SYMMETRIC_GRIDFIT", Self::GASP_SYMMETRIC_GRIDFIT),
426 ("GASP_SYMMETRIC_SMOOTHING", Self::GASP_SYMMETRIC_SMOOTHING),
427 ];
428 let mut first = true;
429 for (name, value) in members {
430 if self.contains(*value) {
431 if !first {
432 f.write_str(" | ")?;
433 }
434 first = false;
435 f.write_str(name)?;
436 }
437 }
438 if first {
439 f.write_str("(empty)")?;
440 }
441 Ok(())
442 }
443}
444
445impl std::fmt::Binary for GaspRangeBehavior {
446 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
447 std::fmt::Binary::fmt(&self.bits, f)
448 }
449}
450
451impl std::fmt::Octal for GaspRangeBehavior {
452 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
453 std::fmt::Octal::fmt(&self.bits, f)
454 }
455}
456
457impl std::fmt::LowerHex for GaspRangeBehavior {
458 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
459 std::fmt::LowerHex::fmt(&self.bits, f)
460 }
461}
462
463impl std::fmt::UpperHex for GaspRangeBehavior {
464 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
465 std::fmt::UpperHex::fmt(&self.bits, f)
466 }
467}
468
469impl font_types::Scalar for GaspRangeBehavior {
470 type Raw = <u16 as font_types::Scalar>::Raw;
471 fn to_raw(self) -> Self::Raw {
472 self.bits().to_raw()
473 }
474 fn from_raw(raw: Self::Raw) -> Self {
475 let t = <u16>::from_raw(raw);
476 Self::from_bits_truncate(t)
477 }
478}
479
480#[cfg(feature = "experimental_traverse")]
481impl<'a> From<GaspRangeBehavior> for FieldType<'a> {
482 fn from(src: GaspRangeBehavior) -> FieldType<'a> {
483 src.bits().into()
484 }
485}