1use std::fmt::{Display, Formatter};
4
5use fontdrasil::types::GlyphName;
6use smol_str::SmolStr;
7use write_fonts::tables::gpos::builders::AnchorBuilder;
8pub use write_fonts::types::GlyphId16;
9
10mod glyph_class;
11mod glyph_map;
12
13pub(crate) use glyph_class::GlyphClass;
14
15pub use glyph_class::GlyphSet;
16pub use glyph_map::GlyphMap;
17
18#[derive(Debug, Clone, PartialEq)]
22pub(crate) enum GlyphOrClass {
23 Glyph(GlyphId16),
25 Class(GlyphClass),
27 Null,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
33pub enum GlyphIdent {
34 Name(GlyphName),
36 Cid(u16),
38}
39
40#[derive(Clone, Debug, Default)]
41pub(crate) struct MarkClass {
42 pub(crate) members: Vec<(GlyphClass, Option<AnchorBuilder>)>,
43}
44
45impl MarkClass {
46 pub(crate) fn is_empty(&self) -> bool {
51 self.members.iter().all(|(glyphs, _)| glyphs.is_empty())
52 }
53}
54
55impl From<u16> for GlyphIdent {
56 fn from(src: u16) -> GlyphIdent {
57 GlyphIdent::Cid(src)
58 }
59}
60
61impl From<GlyphName> for GlyphIdent {
62 fn from(src: GlyphName) -> GlyphIdent {
63 GlyphIdent::Name(src)
64 }
65}
66
67impl From<&str> for GlyphIdent {
68 fn from(src: &str) -> GlyphIdent {
69 GlyphIdent::Name(src.into())
70 }
71}
72
73impl From<SmolStr> for GlyphIdent {
74 fn from(src: SmolStr) -> GlyphIdent {
75 GlyphIdent::Name(src.into())
76 }
77}
78
79impl Display for GlyphIdent {
80 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
81 match self {
82 GlyphIdent::Name(name) => write!(f, "{name}"),
83 GlyphIdent::Cid(cid) => write!(f, "Cid({cid})"),
84 }
85 }
86}
87
88impl GlyphOrClass {
89 pub(crate) fn len(&self) -> usize {
90 match self {
91 GlyphOrClass::Class(cls) => cls.len(),
92 _ => 1,
93 }
94 }
95
96 pub(crate) fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99
100 pub(crate) fn is_class(&self) -> bool {
101 matches!(self, GlyphOrClass::Class(_))
102 }
103
104 pub(crate) fn is_null(&self) -> bool {
105 matches!(self, GlyphOrClass::Null)
106 }
107
108 pub(crate) fn to_class(&self) -> Option<GlyphClass> {
109 match self {
110 GlyphOrClass::Glyph(gid) => Some((*gid).into()),
111 GlyphOrClass::Class(class) => Some(class.clone()),
112 GlyphOrClass::Null => None,
113 }
114 }
115
116 pub(crate) fn to_glyph(&self) -> Option<GlyphId16> {
117 match self {
118 GlyphOrClass::Glyph(gid) => Some(*gid),
119 _ => None,
120 }
121 }
122
123 pub(crate) fn single_glyph(&self) -> Option<GlyphId16> {
125 match self {
126 GlyphOrClass::Glyph(gid) => Some(*gid),
127 GlyphOrClass::Class(class) if class.len() == 1 => class.iter().next(),
128 _ => None,
129 }
130 }
131
132 pub(crate) fn extend(&mut self, other: &GlyphOrClass) {
137 *self = GlyphOrClass::Class(self.iter().chain(other.iter()).collect());
138 }
139
140 pub(crate) fn iter(&self) -> impl Iterator<Item = GlyphId16> + '_ {
141 let mut idx = 0;
142 std::iter::from_fn(move || {
143 let next = match &self {
144 GlyphOrClass::Glyph(id) if idx == 0 => Some(*id),
145 GlyphOrClass::Class(cls) => cls.items().get(idx).copied(),
146 _ => None,
147 };
148 idx += 1;
149 next
150 })
151 }
152
153 pub(crate) fn into_iter_for_target(self) -> impl Iterator<Item = GlyphId16> {
158 let mut idx = 0;
159 std::iter::from_fn(move || {
160 let next = match &self {
161 GlyphOrClass::Glyph(id) if idx == 0 => Some(*id),
162 GlyphOrClass::Null if idx == 0 => Some(GlyphId16::NOTDEF),
163 GlyphOrClass::Class(cls) => cls.items().get(idx).copied(),
164 _ => None,
165 };
166 idx += 1;
167 idx %= self.len();
168 next
169 })
170 }
171}