read_fonts/tables/layout/lookup_flag.rs
1//! The lookup flag type.
2//!
3//! This is kind-of-but-not-quite-exactly a bit enumeration, and so we implement
4//! it manually.
5
6use core::ops::{BitOr, BitOrAssign};
7
8/// The [LookupFlag](https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookupFlag) bit enumeration.
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct LookupFlag(u16);
12
13//NOTE: this impl has the potential to make garbage if used on two lookupflag
14//instances which have different mark attachment masks set, but as that field
15//is not really used in compilation, which is where this impl will be helpful,
16//the risk that this is the source of an actual bug seems very low,
17impl BitOr for LookupFlag {
18 type Output = Self;
19
20 fn bitor(self, rhs: Self) -> Self::Output {
21 Self(self.0 | rhs.0)
22 }
23}
24
25impl BitOrAssign for LookupFlag {
26 fn bitor_assign(&mut self, rhs: Self) {
27 self.0 |= rhs.0
28 }
29}
30
31impl LookupFlag {
32 /// This bit relates only to the correct processing of GPOS type 3 (cursive attachment) lookups
33 ///
34 /// When this bit is set, the last glyph in a given sequence to which the cursive
35 /// attachment lookup is applied, will be positioned on the baseline.
36 pub const RIGHT_TO_LEFT: Self = LookupFlag(0x0001);
37 /// If set, skips over base glyphs
38 pub const IGNORE_BASE_GLYPHS: Self = LookupFlag(0x002);
39 /// If set, skips over ligatures
40 pub const IGNORE_LIGATURES: Self = LookupFlag(0x004);
41 /// If set, skips over all combining marks
42 pub const IGNORE_MARKS: Self = LookupFlag(0x008);
43 /// If set, indicates that the lookup table structure is followed by a MarkFilteringSet field.
44 ///
45 /// The layout engine skips over all mark glyphs not in the mark filtering set indicated.
46 pub const USE_MARK_FILTERING_SET: Self = LookupFlag(0x010);
47
48 // union of all flags, above
49 const FLAG_MASK: Self = LookupFlag(0x1F);
50
51 /// Return new, empty flags
52 pub fn empty() -> Self {
53 Self(0)
54 }
55
56 /// Construct a LookupFlag from a raw value, discarding invalid bits
57 pub fn from_bits_truncate(bits: u16) -> Self {
58 const VALID_BITS: u16 = !0x00E0;
59 Self(bits & VALID_BITS)
60 }
61
62 /// Raw transmutation to u16.
63 pub fn to_bits(self) -> u16 {
64 self.0
65 }
66
67 /// Returns `true` if all of the flags in `other` are contained within `self`.
68 #[inline]
69 pub const fn contains(&self, other: Self) -> bool {
70 // only count flag bits
71 let other = other.0 & Self::FLAG_MASK.0;
72 (self.0 & other) == other
73 }
74
75 /// If not zero, skips over all marks of attachment type different from specified.
76 pub fn mark_attachment_class(self) -> Option<u16> {
77 let val = self.0 & 0xff00;
78 if val == 0 {
79 None
80 } else {
81 Some(val >> 8)
82 }
83 }
84
85 /// If not zero, skips over all marks of attachment type different from specified.
86 pub fn set_mark_attachment_class(&mut self, val: u16) {
87 let val = (val & 0xff) << 8;
88 self.0 = (self.0 & 0xff) | val;
89 }
90}
91
92impl types::Scalar for LookupFlag {
93 type Raw = <u16 as types::Scalar>::Raw;
94 fn to_raw(self) -> Self::Raw {
95 self.0.to_raw()
96 }
97 fn from_raw(raw: Self::Raw) -> Self {
98 let t = <u16>::from_raw(raw);
99 Self(t)
100 }
101}