1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[repr(transparent)]
12pub struct HeaderFlags {
13 bits: u16,
14}
15
16impl HeaderFlags {
17 pub const ALWAYS_SET: Self = Self { bits: 0x0001 };
19
20 pub const DRAW_OUTLINES: Self = Self { bits: 0x0002 };
22}
23
24impl HeaderFlags {
25 #[inline]
27 pub const fn empty() -> Self {
28 Self { bits: 0 }
29 }
30
31 #[inline]
33 pub const fn all() -> Self {
34 Self {
35 bits: Self::ALWAYS_SET.bits | Self::DRAW_OUTLINES.bits,
36 }
37 }
38
39 #[inline]
41 pub const fn bits(&self) -> u16 {
42 self.bits
43 }
44
45 #[inline]
48 pub const fn from_bits(bits: u16) -> Option<Self> {
49 if (bits & !Self::all().bits()) == 0 {
50 Some(Self { bits })
51 } else {
52 None
53 }
54 }
55
56 #[inline]
59 pub const fn from_bits_truncate(bits: u16) -> Self {
60 Self {
61 bits: bits & Self::all().bits,
62 }
63 }
64
65 #[inline]
67 pub const fn is_empty(&self) -> bool {
68 self.bits() == Self::empty().bits()
69 }
70
71 #[inline]
73 pub const fn intersects(&self, other: Self) -> bool {
74 !(Self {
75 bits: self.bits & other.bits,
76 })
77 .is_empty()
78 }
79
80 #[inline]
82 pub const fn contains(&self, other: Self) -> bool {
83 (self.bits & other.bits) == other.bits
84 }
85
86 #[inline]
88 pub fn insert(&mut self, other: Self) {
89 self.bits |= other.bits;
90 }
91
92 #[inline]
94 pub fn remove(&mut self, other: Self) {
95 self.bits &= !other.bits;
96 }
97
98 #[inline]
100 pub fn toggle(&mut self, other: Self) {
101 self.bits ^= other.bits;
102 }
103
104 #[inline]
115 #[must_use]
116 pub const fn intersection(self, other: Self) -> Self {
117 Self {
118 bits: self.bits & other.bits,
119 }
120 }
121
122 #[inline]
133 #[must_use]
134 pub const fn union(self, other: Self) -> Self {
135 Self {
136 bits: self.bits | other.bits,
137 }
138 }
139
140 #[inline]
153 #[must_use]
154 pub const fn difference(self, other: Self) -> Self {
155 Self {
156 bits: self.bits & !other.bits,
157 }
158 }
159}
160
161impl std::ops::BitOr for HeaderFlags {
162 type Output = Self;
163
164 #[inline]
166 fn bitor(self, other: HeaderFlags) -> Self {
167 Self {
168 bits: self.bits | other.bits,
169 }
170 }
171}
172
173impl std::ops::BitOrAssign for HeaderFlags {
174 #[inline]
176 fn bitor_assign(&mut self, other: Self) {
177 self.bits |= other.bits;
178 }
179}
180
181impl std::ops::BitXor for HeaderFlags {
182 type Output = Self;
183
184 #[inline]
186 fn bitxor(self, other: Self) -> Self {
187 Self {
188 bits: self.bits ^ other.bits,
189 }
190 }
191}
192
193impl std::ops::BitXorAssign for HeaderFlags {
194 #[inline]
196 fn bitxor_assign(&mut self, other: Self) {
197 self.bits ^= other.bits;
198 }
199}
200
201impl std::ops::BitAnd for HeaderFlags {
202 type Output = Self;
203
204 #[inline]
206 fn bitand(self, other: Self) -> Self {
207 Self {
208 bits: self.bits & other.bits,
209 }
210 }
211}
212
213impl std::ops::BitAndAssign for HeaderFlags {
214 #[inline]
216 fn bitand_assign(&mut self, other: Self) {
217 self.bits &= other.bits;
218 }
219}
220
221impl std::ops::Sub for HeaderFlags {
222 type Output = Self;
223
224 #[inline]
226 fn sub(self, other: Self) -> Self {
227 Self {
228 bits: self.bits & !other.bits,
229 }
230 }
231}
232
233impl std::ops::SubAssign for HeaderFlags {
234 #[inline]
236 fn sub_assign(&mut self, other: Self) {
237 self.bits &= !other.bits;
238 }
239}
240
241impl std::ops::Not for HeaderFlags {
242 type Output = Self;
243
244 #[inline]
246 fn not(self) -> Self {
247 Self { bits: !self.bits } & Self::all()
248 }
249}
250
251impl std::fmt::Debug for HeaderFlags {
252 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
253 let members: &[(&str, Self)] = &[
254 ("ALWAYS_SET", Self::ALWAYS_SET),
255 ("DRAW_OUTLINES", Self::DRAW_OUTLINES),
256 ];
257 let mut first = true;
258 for (name, value) in members {
259 if self.contains(*value) {
260 if !first {
261 f.write_str(" | ")?;
262 }
263 first = false;
264 f.write_str(name)?;
265 }
266 }
267 if first {
268 f.write_str("(empty)")?;
269 }
270 Ok(())
271 }
272}
273
274impl std::fmt::Binary for HeaderFlags {
275 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
276 std::fmt::Binary::fmt(&self.bits, f)
277 }
278}
279
280impl std::fmt::Octal for HeaderFlags {
281 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
282 std::fmt::Octal::fmt(&self.bits, f)
283 }
284}
285
286impl std::fmt::LowerHex for HeaderFlags {
287 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
288 std::fmt::LowerHex::fmt(&self.bits, f)
289 }
290}
291
292impl std::fmt::UpperHex for HeaderFlags {
293 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
294 std::fmt::UpperHex::fmt(&self.bits, f)
295 }
296}
297
298impl font_types::Scalar for HeaderFlags {
299 type Raw = <u16 as font_types::Scalar>::Raw;
300 fn to_raw(self) -> Self::Raw {
301 self.bits().to_raw()
302 }
303 fn from_raw(raw: Self::Raw) -> Self {
304 let t = <u16>::from_raw(raw);
305 Self::from_bits_truncate(t)
306 }
307}
308
309#[cfg(feature = "experimental_traverse")]
310impl<'a> From<HeaderFlags> for FieldType<'a> {
311 fn from(src: HeaderFlags) -> FieldType<'a> {
312 src.bits().into()
313 }
314}
315
316#[derive(Debug, Clone, Copy)]
318#[doc(hidden)]
319pub struct SbixMarker {
320 num_glyphs: u16,
321 strike_offsets_byte_len: usize,
322}
323
324impl SbixMarker {
325 pub fn version_byte_range(&self) -> Range<usize> {
326 let start = 0;
327 start..start + u16::RAW_BYTE_LEN
328 }
329
330 pub fn flags_byte_range(&self) -> Range<usize> {
331 let start = self.version_byte_range().end;
332 start..start + HeaderFlags::RAW_BYTE_LEN
333 }
334
335 pub fn num_strikes_byte_range(&self) -> Range<usize> {
336 let start = self.flags_byte_range().end;
337 start..start + u32::RAW_BYTE_LEN
338 }
339
340 pub fn strike_offsets_byte_range(&self) -> Range<usize> {
341 let start = self.num_strikes_byte_range().end;
342 start..start + self.strike_offsets_byte_len
343 }
344}
345
346impl MinByteRange for SbixMarker {
347 fn min_byte_range(&self) -> Range<usize> {
348 0..self.strike_offsets_byte_range().end
349 }
350}
351
352impl TopLevelTable for Sbix<'_> {
353 const TAG: Tag = Tag::new(b"sbix");
355}
356
357impl ReadArgs for Sbix<'_> {
358 type Args = u16;
359}
360
361impl<'a> FontReadWithArgs<'a> for Sbix<'a> {
362 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
363 let num_glyphs = *args;
364 let mut cursor = data.cursor();
365 cursor.advance::<u16>();
366 cursor.advance::<HeaderFlags>();
367 let num_strikes: u32 = cursor.read()?;
368 let strike_offsets_byte_len = (num_strikes as usize)
369 .checked_mul(Offset32::RAW_BYTE_LEN)
370 .ok_or(ReadError::OutOfBounds)?;
371 cursor.advance_by(strike_offsets_byte_len);
372 cursor.finish(SbixMarker {
373 num_glyphs,
374 strike_offsets_byte_len,
375 })
376 }
377}
378
379impl<'a> Sbix<'a> {
380 pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
385 let args = num_glyphs;
386 Self::read_with_args(data, &args)
387 }
388}
389
390pub type Sbix<'a> = TableRef<'a, SbixMarker>;
392
393#[allow(clippy::needless_lifetimes)]
394impl<'a> Sbix<'a> {
395 pub fn version(&self) -> u16 {
397 let range = self.shape.version_byte_range();
398 self.data.read_at(range.start).unwrap()
399 }
400
401 pub fn flags(&self) -> HeaderFlags {
405 let range = self.shape.flags_byte_range();
406 self.data.read_at(range.start).unwrap()
407 }
408
409 pub fn num_strikes(&self) -> u32 {
411 let range = self.shape.num_strikes_byte_range();
412 self.data.read_at(range.start).unwrap()
413 }
414
415 pub fn strike_offsets(&self) -> &'a [BigEndian<Offset32>] {
417 let range = self.shape.strike_offsets_byte_range();
418 self.data.read_array(range).unwrap()
419 }
420
421 pub fn strikes(&self) -> ArrayOfOffsets<'a, Strike<'a>, Offset32> {
423 let data = self.data;
424 let offsets = self.strike_offsets();
425 let args = self.num_glyphs();
426 ArrayOfOffsets::new(offsets, data, args)
427 }
428
429 pub(crate) fn num_glyphs(&self) -> u16 {
430 self.shape.num_glyphs
431 }
432}
433
434#[cfg(feature = "experimental_traverse")]
435impl<'a> SomeTable<'a> for Sbix<'a> {
436 fn type_name(&self) -> &str {
437 "Sbix"
438 }
439 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
440 match idx {
441 0usize => Some(Field::new("version", self.version())),
442 1usize => Some(Field::new("flags", self.flags())),
443 2usize => Some(Field::new("num_strikes", self.num_strikes())),
444 3usize => Some({
445 let data = self.data;
446 let args = self.num_glyphs();
447 Field::new(
448 "strike_offsets",
449 FieldType::array_of_offsets(
450 better_type_name::<Strike>(),
451 self.strike_offsets(),
452 move |off| {
453 let target = off.get().resolve_with_args::<Strike>(data, &args);
454 FieldType::offset(off.get(), target)
455 },
456 ),
457 )
458 }),
459 _ => None,
460 }
461 }
462}
463
464#[cfg(feature = "experimental_traverse")]
465#[allow(clippy::needless_lifetimes)]
466impl<'a> std::fmt::Debug for Sbix<'a> {
467 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
468 (self as &dyn SomeTable<'a>).fmt(f)
469 }
470}
471
472#[derive(Debug, Clone, Copy)]
474#[doc(hidden)]
475pub struct StrikeMarker {
476 glyph_data_offsets_byte_len: usize,
477}
478
479impl StrikeMarker {
480 pub fn ppem_byte_range(&self) -> Range<usize> {
481 let start = 0;
482 start..start + u16::RAW_BYTE_LEN
483 }
484
485 pub fn ppi_byte_range(&self) -> Range<usize> {
486 let start = self.ppem_byte_range().end;
487 start..start + u16::RAW_BYTE_LEN
488 }
489
490 pub fn glyph_data_offsets_byte_range(&self) -> Range<usize> {
491 let start = self.ppi_byte_range().end;
492 start..start + self.glyph_data_offsets_byte_len
493 }
494}
495
496impl MinByteRange for StrikeMarker {
497 fn min_byte_range(&self) -> Range<usize> {
498 0..self.glyph_data_offsets_byte_range().end
499 }
500}
501
502impl ReadArgs for Strike<'_> {
503 type Args = u16;
504}
505
506impl<'a> FontReadWithArgs<'a> for Strike<'a> {
507 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
508 let num_glyphs = *args;
509 let mut cursor = data.cursor();
510 cursor.advance::<u16>();
511 cursor.advance::<u16>();
512 let glyph_data_offsets_byte_len = (transforms::add(num_glyphs, 1_usize))
513 .checked_mul(u32::RAW_BYTE_LEN)
514 .ok_or(ReadError::OutOfBounds)?;
515 cursor.advance_by(glyph_data_offsets_byte_len);
516 cursor.finish(StrikeMarker {
517 glyph_data_offsets_byte_len,
518 })
519 }
520}
521
522impl<'a> Strike<'a> {
523 pub fn read(data: FontData<'a>, num_glyphs: u16) -> Result<Self, ReadError> {
528 let args = num_glyphs;
529 Self::read_with_args(data, &args)
530 }
531}
532
533pub type Strike<'a> = TableRef<'a, StrikeMarker>;
535
536#[allow(clippy::needless_lifetimes)]
537impl<'a> Strike<'a> {
538 pub fn ppem(&self) -> u16 {
540 let range = self.shape.ppem_byte_range();
541 self.data.read_at(range.start).unwrap()
542 }
543
544 pub fn ppi(&self) -> u16 {
546 let range = self.shape.ppi_byte_range();
547 self.data.read_at(range.start).unwrap()
548 }
549
550 pub fn glyph_data_offsets(&self) -> &'a [BigEndian<u32>] {
552 let range = self.shape.glyph_data_offsets_byte_range();
553 self.data.read_array(range).unwrap()
554 }
555}
556
557#[cfg(feature = "experimental_traverse")]
558impl<'a> SomeTable<'a> for Strike<'a> {
559 fn type_name(&self) -> &str {
560 "Strike"
561 }
562 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
563 match idx {
564 0usize => Some(Field::new("ppem", self.ppem())),
565 1usize => Some(Field::new("ppi", self.ppi())),
566 2usize => Some(Field::new("glyph_data_offsets", self.glyph_data_offsets())),
567 _ => None,
568 }
569 }
570}
571
572#[cfg(feature = "experimental_traverse")]
573#[allow(clippy::needless_lifetimes)]
574impl<'a> std::fmt::Debug for Strike<'a> {
575 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576 (self as &dyn SomeTable<'a>).fmt(f)
577 }
578}
579
580#[derive(Debug, Clone, Copy)]
582#[doc(hidden)]
583pub struct GlyphDataMarker {
584 data_byte_len: usize,
585}
586
587impl GlyphDataMarker {
588 pub fn origin_offset_x_byte_range(&self) -> Range<usize> {
589 let start = 0;
590 start..start + i16::RAW_BYTE_LEN
591 }
592
593 pub fn origin_offset_y_byte_range(&self) -> Range<usize> {
594 let start = self.origin_offset_x_byte_range().end;
595 start..start + i16::RAW_BYTE_LEN
596 }
597
598 pub fn graphic_type_byte_range(&self) -> Range<usize> {
599 let start = self.origin_offset_y_byte_range().end;
600 start..start + Tag::RAW_BYTE_LEN
601 }
602
603 pub fn data_byte_range(&self) -> Range<usize> {
604 let start = self.graphic_type_byte_range().end;
605 start..start + self.data_byte_len
606 }
607}
608
609impl MinByteRange for GlyphDataMarker {
610 fn min_byte_range(&self) -> Range<usize> {
611 0..self.data_byte_range().end
612 }
613}
614
615impl<'a> FontRead<'a> for GlyphData<'a> {
616 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
617 let mut cursor = data.cursor();
618 cursor.advance::<i16>();
619 cursor.advance::<i16>();
620 cursor.advance::<Tag>();
621 let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
622 cursor.advance_by(data_byte_len);
623 cursor.finish(GlyphDataMarker { data_byte_len })
624 }
625}
626
627pub type GlyphData<'a> = TableRef<'a, GlyphDataMarker>;
629
630#[allow(clippy::needless_lifetimes)]
631impl<'a> GlyphData<'a> {
632 pub fn origin_offset_x(&self) -> i16 {
634 let range = self.shape.origin_offset_x_byte_range();
635 self.data.read_at(range.start).unwrap()
636 }
637
638 pub fn origin_offset_y(&self) -> i16 {
640 let range = self.shape.origin_offset_y_byte_range();
641 self.data.read_at(range.start).unwrap()
642 }
643
644 pub fn graphic_type(&self) -> Tag {
646 let range = self.shape.graphic_type_byte_range();
647 self.data.read_at(range.start).unwrap()
648 }
649
650 pub fn data(&self) -> &'a [u8] {
652 let range = self.shape.data_byte_range();
653 self.data.read_array(range).unwrap()
654 }
655}
656
657#[cfg(feature = "experimental_traverse")]
658impl<'a> SomeTable<'a> for GlyphData<'a> {
659 fn type_name(&self) -> &str {
660 "GlyphData"
661 }
662 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
663 match idx {
664 0usize => Some(Field::new("origin_offset_x", self.origin_offset_x())),
665 1usize => Some(Field::new("origin_offset_y", self.origin_offset_y())),
666 2usize => Some(Field::new("graphic_type", self.graphic_type())),
667 3usize => Some(Field::new("data", self.data())),
668 _ => None,
669 }
670 }
671}
672
673#[cfg(feature = "experimental_traverse")]
674#[allow(clippy::needless_lifetimes)]
675impl<'a> std::fmt::Debug for GlyphData<'a> {
676 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
677 (self as &dyn SomeTable<'a>).fmt(f)
678 }
679}