1#[cfg(not(feature = "std"))]
4use alloc::{
5 string::{String, ToString},
6 vec::Vec,
7};
8use core::ops::Range;
9use rangemap::RangeMap;
10
11use crate::CacheKeyFlags;
12
13pub use fontdb::{Family, Stretch, Style, Weight};
14
15#[derive(Clone, Copy, Debug, PartialOrd, Ord, Eq, Hash, PartialEq)]
17pub struct Color(pub u32);
18
19impl Color {
20 #[inline]
22 pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
23 Self::rgba(r, g, b, 0xFF)
24 }
25
26 #[inline]
28 pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
29 Self(((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32))
30 }
31
32 #[inline]
34 pub fn as_rgba_tuple(self) -> (u8, u8, u8, u8) {
35 (self.r(), self.g(), self.b(), self.a())
36 }
37
38 #[inline]
40 pub fn as_rgba(self) -> [u8; 4] {
41 [self.r(), self.g(), self.b(), self.a()]
42 }
43
44 #[inline]
46 pub fn r(&self) -> u8 {
47 ((self.0 & 0x00_FF_00_00) >> 16) as u8
48 }
49
50 #[inline]
52 pub fn g(&self) -> u8 {
53 ((self.0 & 0x00_00_FF_00) >> 8) as u8
54 }
55
56 #[inline]
58 pub fn b(&self) -> u8 {
59 (self.0 & 0x00_00_00_FF) as u8
60 }
61
62 #[inline]
64 pub fn a(&self) -> u8 {
65 ((self.0 & 0xFF_00_00_00) >> 24) as u8
66 }
67}
68
69#[derive(Clone, Debug, Eq, Hash, PartialEq)]
71pub enum FamilyOwned {
72 Name(String),
73 Serif,
74 SansSerif,
75 Cursive,
76 Fantasy,
77 Monospace,
78}
79
80impl FamilyOwned {
81 pub fn new(family: Family) -> Self {
82 match family {
83 Family::Name(name) => FamilyOwned::Name(name.to_string()),
84 Family::Serif => FamilyOwned::Serif,
85 Family::SansSerif => FamilyOwned::SansSerif,
86 Family::Cursive => FamilyOwned::Cursive,
87 Family::Fantasy => FamilyOwned::Fantasy,
88 Family::Monospace => FamilyOwned::Monospace,
89 }
90 }
91
92 pub fn as_family(&self) -> Family {
93 match self {
94 FamilyOwned::Name(name) => Family::Name(name),
95 FamilyOwned::Serif => Family::Serif,
96 FamilyOwned::SansSerif => Family::SansSerif,
97 FamilyOwned::Cursive => Family::Cursive,
98 FamilyOwned::Fantasy => Family::Fantasy,
99 FamilyOwned::Monospace => Family::Monospace,
100 }
101 }
102}
103
104#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
106pub struct Attrs<'a> {
107 pub color_opt: Option<Color>,
109 pub family: Family<'a>,
110 pub stretch: Stretch,
111 pub style: Style,
112 pub weight: Weight,
113 pub metadata: usize,
114 pub cache_key_flags: CacheKeyFlags,
115 pub is_preedit: bool,
116}
117
118impl<'a> Attrs<'a> {
119 pub fn new() -> Self {
123 Self {
124 color_opt: None,
125 family: Family::SansSerif,
126 stretch: Stretch::Normal,
127 style: Style::Normal,
128 weight: Weight::NORMAL,
129 metadata: 0,
130 cache_key_flags: CacheKeyFlags::empty(),
131 is_preedit: false,
132 }
133 }
134
135 pub fn color(mut self, color: Color) -> Self {
137 self.color_opt = Some(color);
138 self
139 }
140
141 pub fn family(mut self, family: Family<'a>) -> Self {
143 self.family = family;
144 self
145 }
146
147 pub fn stretch(mut self, stretch: Stretch) -> Self {
149 self.stretch = stretch;
150 self
151 }
152
153 pub fn style(mut self, style: Style) -> Self {
155 self.style = style;
156 self
157 }
158
159 pub fn weight(mut self, weight: Weight) -> Self {
161 self.weight = weight;
162 self
163 }
164
165 pub fn metadata(mut self, metadata: usize) -> Self {
167 self.metadata = metadata;
168 self
169 }
170
171 pub fn cache_key_flags(mut self, cache_key_flags: CacheKeyFlags) -> Self {
173 self.cache_key_flags = cache_key_flags;
174 self
175 }
176
177 pub fn preedit(mut self, is_preedit: bool) -> Self {
179 self.is_preedit = is_preedit;
180 self
181 }
182
183 pub fn matches(&self, face: &fontdb::FaceInfo) -> bool {
185 face.post_script_name.contains("Emoji")
187 || (face.style == self.style && face.stretch == self.stretch)
188 }
189
190 pub fn compatible(&self, other: &Self) -> bool {
192 self.family == other.family
193 && self.stretch == other.stretch
194 && self.style == other.style
195 && self.weight == other.weight
196 }
197}
198
199#[derive(Clone, Debug, Eq, Hash, PartialEq)]
201pub struct FontMatchAttrs {
202 family: FamilyOwned,
203 stretch: Stretch,
204 style: Style,
205 weight: Weight,
206}
207
208impl<'a> From<Attrs<'a>> for FontMatchAttrs {
209 fn from(attrs: Attrs<'a>) -> Self {
210 Self {
211 family: FamilyOwned::new(attrs.family),
212 stretch: attrs.stretch,
213 style: attrs.style,
214 weight: attrs.weight,
215 }
216 }
217}
218
219#[derive(Clone, Debug, Eq, Hash, PartialEq)]
221pub struct AttrsOwned {
222 pub color_opt: Option<Color>,
224 pub family_owned: FamilyOwned,
225 pub stretch: Stretch,
226 pub style: Style,
227 pub weight: Weight,
228 pub metadata: usize,
229 pub cache_key_flags: CacheKeyFlags,
230 pub is_preedit: bool,
231}
232
233impl AttrsOwned {
234 pub fn new(attrs: Attrs) -> Self {
235 Self {
236 color_opt: attrs.color_opt,
237 family_owned: FamilyOwned::new(attrs.family),
238 stretch: attrs.stretch,
239 style: attrs.style,
240 weight: attrs.weight,
241 metadata: attrs.metadata,
242 cache_key_flags: attrs.cache_key_flags,
243 is_preedit: attrs.is_preedit,
244 }
245 }
246
247 pub fn as_attrs(&self) -> Attrs {
248 Attrs {
249 color_opt: self.color_opt,
250 family: self.family_owned.as_family(),
251 stretch: self.stretch,
252 style: self.style,
253 weight: self.weight,
254 metadata: self.metadata,
255 cache_key_flags: self.cache_key_flags,
256 is_preedit: self.is_preedit,
257 }
258 }
259}
260
261#[derive(Debug, Clone, Eq, PartialEq)]
264pub struct AttrsList {
265 defaults: AttrsOwned,
266 pub(crate) spans: RangeMap<usize, AttrsOwned>,
267}
268
269impl AttrsList {
270 pub fn new(defaults: Attrs) -> Self {
272 Self {
273 defaults: AttrsOwned::new(defaults),
274 spans: RangeMap::new(),
275 }
276 }
277
278 pub fn defaults(&self) -> Attrs {
280 self.defaults.as_attrs()
281 }
282
283 pub fn spans(&self) -> Vec<(&Range<usize>, &AttrsOwned)> {
285 self.spans.iter().collect()
286 }
287
288 pub fn clear_spans(&mut self) {
290 self.spans.clear();
291 }
292
293 pub fn add_span(&mut self, range: Range<usize>, attrs: Attrs) {
295 if range.is_empty() {
297 return;
298 }
299
300 self.spans.insert(range, AttrsOwned::new(attrs));
301 }
302
303 pub fn get_span(&self, index: usize) -> Attrs {
307 self.spans
308 .get(&index)
309 .map(|v| v.as_attrs())
310 .unwrap_or(self.defaults.as_attrs())
311 }
312
313 pub fn split_off(&mut self, index: usize) -> Self {
315 let mut new = Self::new(self.defaults.as_attrs());
316 let mut removes = Vec::new();
317
318 for span in self.spans.iter() {
320 if span.0.end <= index {
321 continue;
322 } else if span.0.start >= index {
323 removes.push((span.0.clone(), false));
324 } else {
325 removes.push((span.0.clone(), true));
326 }
327 }
328
329 for (key, resize) in removes {
330 let (range, attrs) = self
331 .spans
332 .get_key_value(&key.start)
333 .map(|v| (v.0.clone(), v.1.clone()))
334 .expect("attrs span not found");
335 self.spans.remove(key);
336
337 if resize {
338 new.spans.insert(0..range.end - index, attrs.clone());
339 self.spans.insert(range.start..index, attrs);
340 } else {
341 new.spans
342 .insert(range.start - index..range.end - index, attrs);
343 }
344 }
345 new
346 }
347}