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