1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
//! The lookup flag type.
//!
//! This is kind-of-but-not-quite-exactly a bit enumeration, and so we implement
//! it manually.
use core::ops::{BitOr, BitOrAssign};
/// The [LookupFlag](https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookupFlag) bit enumeration.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LookupFlag(u16);
//NOTE: this impl has the potential to make garbage if used on two lookupflag
//instances which have different mark attachment masks set, but as that field
//is not really used in compilation, which is where this impl will be helpful,
//the risk that this is the source of an actual bug seems very low,
impl BitOr for LookupFlag {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl BitOrAssign for LookupFlag {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0
}
}
impl LookupFlag {
/// This bit relates only to the correct processing of GPOS type 3 (cursive attachment) lookups
///
/// When this bit is set, the last glyph in a given sequence to which the cursive
/// attachment lookup is applied, will be positioned on the baseline.
pub const RIGHT_TO_LEFT: Self = LookupFlag(0x0001);
/// If set, skips over base glyphs
pub const IGNORE_BASE_GLYPHS: Self = LookupFlag(0x002);
/// If set, skips over ligatures
pub const IGNORE_LIGATURES: Self = LookupFlag(0x004);
/// If set, skips over all combining marks
pub const IGNORE_MARKS: Self = LookupFlag(0x008);
/// If set, indicates that the lookup table structure is followed by a MarkFilteringSet field.
///
/// The layout engine skips over all mark glyphs not in the mark filtering set indicated.
pub const USE_MARK_FILTERING_SET: Self = LookupFlag(0x010);
/// Return new, empty flags
pub fn empty() -> Self {
Self(0)
}
/// Construct a LookupFlag from a raw value, discarding invalid bits
pub fn from_bits_truncate(bits: u16) -> Self {
const VALID_BITS: u16 = !0x00E0;
Self(bits & VALID_BITS)
}
/// Raw transmutation to u16.
pub fn to_bits(self) -> u16 {
self.0
}
/// This bit relates only to the correct processing of the cursive attachment
/// lookup type (GPOS lookup type 3).
///
/// When this bit is set, the last glyph in a given sequence to which the
/// cursive attachment lookup is applied, will be positioned on the baseline.
pub fn right_to_left(self) -> bool {
(self.0 & 0x0001) != 0
}
/// This bit relates only to the correct processing of the cursive attachment
/// lookup type (GPOS lookup type 3).
///
/// When this bit is set, the last glyph in a given sequence to which the
/// cursive attachment lookup is applied, will be positioned on the baseline.
pub fn set_right_to_left(&mut self, val: bool) {
if val {
self.0 |= 0x0001
} else {
self.0 &= !0x0001
}
}
/// If set, skips over base glyphs
pub fn ignore_base_glyphs(self) -> bool {
(self.0 & 0x0002) != 0
}
/// If set, skips over base glyphs
pub fn set_ignore_base_glyphs(&mut self, val: bool) {
if val {
self.0 |= 0x0002
} else {
self.0 &= !0x0002
}
}
/// If set, skips over ligatures
pub fn ignore_ligatures(self) -> bool {
(self.0 & 0x0004) != 0
}
/// If set, skips over ligatures
pub fn set_ignore_ligatures(&mut self, val: bool) {
if val {
self.0 |= 0x0004
} else {
self.0 &= !0x0004
}
}
/// If set, skips over all combining marks
pub fn ignore_marks(self) -> bool {
(self.0 & 0x0008) != 0
}
/// If set, skips over all combining marks
pub fn set_ignore_marks(&mut self, val: bool) {
if val {
self.0 |= 0x0008
} else {
self.0 &= !0x0008
}
}
/// If set, indicates that the lookup table structure is followed by a
/// MarkFilteringSet field.
///
/// The layout engine skips over all mark glyphs not in the mark filtering set
/// indicated.
pub fn use_mark_filtering_set(self) -> bool {
(self.0 & 0x0010) != 0
}
/// If set, indicates that the lookup table structure is followed by a
/// MarkFilteringSet field.
///
/// The layout engine skips over all mark glyphs not in the mark filtering set
/// indicated.
pub fn set_use_mark_filtering_set(&mut self, val: bool) {
if val {
self.0 |= 0x0010
} else {
self.0 &= !0x0010
}
}
/// If not zero, skips over all marks of attachment type different from specified.
pub fn mark_attachment_type_mask(self) -> Option<u16> {
let val = self.0 & 0xff00;
if val == 0 {
None
} else {
Some(val >> 8)
}
}
/// If not zero, skips over all marks of attachment type different from specified.
pub fn set_mark_attachment_type(&mut self, val: u16) {
let val = (val & 0xff) << 8;
self.0 = (self.0 & 0xff) | val;
}
}
impl types::Scalar for LookupFlag {
type Raw = <u16 as types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
self.0.to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self(t)
}
}