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