1use serde::Deserialize;
2use serde_json::json;
3use std::{borrow::Cow, sync::Arc};
4
5use crate::{
6 color::Color,
7 fonts::{FontId, GlyphId},
8 geometry::{rect::RectF, vector::Vector2F},
9 json::ToJson,
10 platform::CursorStyle,
11 ImageData,
12};
13
14pub struct Scene {
15 scale_factor: f32,
16 stacking_contexts: Vec<StackingContext>,
17 active_stacking_context_stack: Vec<usize>,
18}
19
20struct StackingContext {
21 layers: Vec<Layer>,
22 active_layer_stack: Vec<usize>,
23}
24
25#[derive(Default)]
26pub struct Layer {
27 clip_bounds: Option<RectF>,
28 quads: Vec<Quad>,
29 underlines: Vec<Underline>,
30 images: Vec<Image>,
31 shadows: Vec<Shadow>,
32 glyphs: Vec<Glyph>,
33 image_glyphs: Vec<ImageGlyph>,
34 icons: Vec<Icon>,
35 paths: Vec<Path>,
36 cursor_styles: Vec<(RectF, CursorStyle)>,
37}
38
39#[derive(Default, Debug)]
40pub struct Quad {
41 pub bounds: RectF,
42 pub background: Option<Color>,
43 pub border: Border,
44 pub corner_radius: f32,
45}
46
47#[derive(Debug)]
48pub struct Shadow {
49 pub bounds: RectF,
50 pub corner_radius: f32,
51 pub sigma: f32,
52 pub color: Color,
53}
54
55#[derive(Debug)]
56pub struct Glyph {
57 pub font_id: FontId,
58 pub font_size: f32,
59 pub id: GlyphId,
60 pub origin: Vector2F,
61 pub color: Color,
62}
63
64#[derive(Debug)]
65pub struct ImageGlyph {
66 pub font_id: FontId,
67 pub font_size: f32,
68 pub id: GlyphId,
69 pub origin: Vector2F,
70}
71
72pub struct Icon {
73 pub bounds: RectF,
74 pub svg: usvg::Tree,
75 pub path: Cow<'static, str>,
76 pub color: Color,
77}
78
79#[derive(Clone, Copy, Default, Debug)]
80pub struct Border {
81 pub width: f32,
82 pub color: Color,
83 pub overlay: bool,
84 pub top: bool,
85 pub right: bool,
86 pub bottom: bool,
87 pub left: bool,
88}
89
90#[derive(Clone, Copy, Default, Debug)]
91pub struct Underline {
92 pub origin: Vector2F,
93 pub width: f32,
94 pub thickness: f32,
95 pub color: Color,
96 pub squiggly: bool,
97}
98
99impl<'de> Deserialize<'de> for Border {
100 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
101 where
102 D: serde::Deserializer<'de>,
103 {
104 #[derive(Deserialize)]
105 struct BorderData {
106 pub width: f32,
107 pub color: Color,
108 #[serde(default)]
109 pub overlay: bool,
110 #[serde(default)]
111 pub top: bool,
112 #[serde(default)]
113 pub right: bool,
114 #[serde(default)]
115 pub bottom: bool,
116 #[serde(default)]
117 pub left: bool,
118 }
119
120 let data = BorderData::deserialize(deserializer)?;
121 let mut border = Border {
122 width: data.width,
123 color: data.color,
124 overlay: data.overlay,
125 top: data.top,
126 bottom: data.bottom,
127 left: data.left,
128 right: data.right,
129 };
130 if !border.top && !border.bottom && !border.left && !border.right {
131 border.top = true;
132 border.bottom = true;
133 border.left = true;
134 border.right = true;
135 }
136 Ok(border)
137 }
138}
139
140#[derive(Debug)]
141pub struct Path {
142 pub bounds: RectF,
143 pub color: Color,
144 pub vertices: Vec<PathVertex>,
145}
146
147#[derive(Debug)]
148pub struct PathVertex {
149 pub xy_position: Vector2F,
150 pub st_position: Vector2F,
151}
152
153pub struct Image {
154 pub bounds: RectF,
155 pub border: Border,
156 pub corner_radius: f32,
157 pub data: Arc<ImageData>,
158}
159
160impl Scene {
161 pub fn new(scale_factor: f32) -> Self {
162 let stacking_context = StackingContext::new(None);
163 Scene {
164 scale_factor,
165 stacking_contexts: vec![stacking_context],
166 active_stacking_context_stack: vec![0],
167 }
168 }
169
170 pub fn scale_factor(&self) -> f32 {
171 self.scale_factor
172 }
173
174 pub fn layers(&self) -> impl Iterator<Item = &Layer> {
175 self.stacking_contexts.iter().flat_map(|s| &s.layers)
176 }
177
178 pub fn cursor_styles(&self) -> Vec<(RectF, CursorStyle)> {
179 self.layers()
180 .flat_map(|layer| &layer.cursor_styles)
181 .copied()
182 .collect()
183 }
184
185 pub fn push_stacking_context(&mut self, clip_bounds: Option<RectF>) {
186 self.active_stacking_context_stack
187 .push(self.stacking_contexts.len());
188 self.stacking_contexts
189 .push(StackingContext::new(clip_bounds))
190 }
191
192 pub fn pop_stacking_context(&mut self) {
193 self.active_stacking_context_stack.pop();
194 assert!(!self.active_stacking_context_stack.is_empty());
195 }
196
197 pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
198 self.active_stacking_context().push_layer(clip_bounds);
199 }
200
201 pub fn pop_layer(&mut self) {
202 self.active_stacking_context().pop_layer();
203 }
204
205 pub fn push_quad(&mut self, quad: Quad) {
206 self.active_layer().push_quad(quad)
207 }
208
209 pub fn push_cursor_style(&mut self, bounds: RectF, style: CursorStyle) {
210 self.active_layer().push_cursor_style(bounds, style);
211 }
212
213 pub fn push_image(&mut self, image: Image) {
214 self.active_layer().push_image(image)
215 }
216
217 pub fn push_underline(&mut self, underline: Underline) {
218 self.active_layer().push_underline(underline)
219 }
220
221 pub fn push_shadow(&mut self, shadow: Shadow) {
222 self.active_layer().push_shadow(shadow)
223 }
224
225 pub fn push_glyph(&mut self, glyph: Glyph) {
226 self.active_layer().push_glyph(glyph)
227 }
228
229 pub fn push_image_glyph(&mut self, image_glyph: ImageGlyph) {
230 self.active_layer().push_image_glyph(image_glyph)
231 }
232
233 pub fn push_icon(&mut self, icon: Icon) {
234 self.active_layer().push_icon(icon)
235 }
236
237 pub fn push_path(&mut self, path: Path) {
238 self.active_layer().push_path(path);
239 }
240
241 fn active_stacking_context(&mut self) -> &mut StackingContext {
242 let ix = *self.active_stacking_context_stack.last().unwrap();
243 &mut self.stacking_contexts[ix]
244 }
245
246 fn active_layer(&mut self) -> &mut Layer {
247 self.active_stacking_context().active_layer()
248 }
249}
250
251impl StackingContext {
252 fn new(clip_bounds: Option<RectF>) -> Self {
253 Self {
254 layers: vec![Layer::new(clip_bounds)],
255 active_layer_stack: vec![0],
256 }
257 }
258
259 fn active_layer(&mut self) -> &mut Layer {
260 &mut self.layers[*self.active_layer_stack.last().unwrap()]
261 }
262
263 fn push_layer(&mut self, clip_bounds: Option<RectF>) {
264 let parent_clip_bounds = self.active_layer().clip_bounds();
265 let clip_bounds = clip_bounds
266 .map(|clip_bounds| {
267 clip_bounds
268 .intersection(parent_clip_bounds.unwrap_or(clip_bounds))
269 .unwrap_or_else(|| {
270 if !clip_bounds.is_empty() {
271 log::warn!("specified clip bounds are disjoint from parent layer");
272 }
273 RectF::default()
274 })
275 })
276 .or(parent_clip_bounds);
277
278 let ix = self.layers.len();
279 self.layers.push(Layer::new(clip_bounds));
280 self.active_layer_stack.push(ix);
281 }
282
283 fn pop_layer(&mut self) {
284 self.active_layer_stack.pop().unwrap();
285 assert!(!self.active_layer_stack.is_empty());
286 }
287}
288
289impl Layer {
290 pub fn new(clip_bounds: Option<RectF>) -> Self {
291 Self {
292 clip_bounds,
293 quads: Default::default(),
294 underlines: Default::default(),
295 images: Default::default(),
296 shadows: Default::default(),
297 image_glyphs: Default::default(),
298 glyphs: Default::default(),
299 icons: Default::default(),
300 paths: Default::default(),
301 cursor_styles: Default::default(),
302 }
303 }
304
305 pub fn clip_bounds(&self) -> Option<RectF> {
306 self.clip_bounds
307 }
308
309 fn push_quad(&mut self, quad: Quad) {
310 if can_draw(quad.bounds) {
311 self.quads.push(quad);
312 }
313 }
314
315 pub fn quads(&self) -> &[Quad] {
316 self.quads.as_slice()
317 }
318
319 fn push_cursor_style(&mut self, bounds: RectF, style: CursorStyle) {
320 if let Some(bounds) = bounds.intersection(self.clip_bounds.unwrap_or(bounds)) {
321 if can_draw(bounds) {
322 self.cursor_styles.push((bounds, style));
323 }
324 }
325 }
326
327 fn push_underline(&mut self, underline: Underline) {
328 if underline.width > 0. {
329 self.underlines.push(underline);
330 }
331 }
332
333 pub fn underlines(&self) -> &[Underline] {
334 self.underlines.as_slice()
335 }
336
337 fn push_image(&mut self, image: Image) {
338 if can_draw(image.bounds) {
339 self.images.push(image);
340 }
341 }
342
343 pub fn images(&self) -> &[Image] {
344 self.images.as_slice()
345 }
346
347 fn push_shadow(&mut self, shadow: Shadow) {
348 if can_draw(shadow.bounds) {
349 self.shadows.push(shadow);
350 }
351 }
352
353 pub fn shadows(&self) -> &[Shadow] {
354 self.shadows.as_slice()
355 }
356
357 fn push_image_glyph(&mut self, glyph: ImageGlyph) {
358 self.image_glyphs.push(glyph);
359 }
360
361 pub fn image_glyphs(&self) -> &[ImageGlyph] {
362 self.image_glyphs.as_slice()
363 }
364
365 fn push_glyph(&mut self, glyph: Glyph) {
366 self.glyphs.push(glyph);
367 }
368
369 pub fn glyphs(&self) -> &[Glyph] {
370 self.glyphs.as_slice()
371 }
372
373 pub fn push_icon(&mut self, icon: Icon) {
374 if can_draw(icon.bounds) {
375 self.icons.push(icon);
376 }
377 }
378
379 pub fn icons(&self) -> &[Icon] {
380 self.icons.as_slice()
381 }
382
383 fn push_path(&mut self, path: Path) {
384 if can_draw(path.bounds) {
385 self.paths.push(path);
386 }
387 }
388
389 pub fn paths(&self) -> &[Path] {
390 self.paths.as_slice()
391 }
392}
393
394impl Border {
395 pub fn new(width: f32, color: Color) -> Self {
396 Self {
397 width,
398 color,
399 overlay: false,
400 top: false,
401 left: false,
402 bottom: false,
403 right: false,
404 }
405 }
406
407 pub fn all(width: f32, color: Color) -> Self {
408 Self {
409 width,
410 color,
411 overlay: false,
412 top: true,
413 left: true,
414 bottom: true,
415 right: true,
416 }
417 }
418
419 pub fn top(width: f32, color: Color) -> Self {
420 let mut border = Self::new(width, color);
421 border.top = true;
422 border
423 }
424
425 pub fn left(width: f32, color: Color) -> Self {
426 let mut border = Self::new(width, color);
427 border.left = true;
428 border
429 }
430
431 pub fn bottom(width: f32, color: Color) -> Self {
432 let mut border = Self::new(width, color);
433 border.bottom = true;
434 border
435 }
436
437 pub fn right(width: f32, color: Color) -> Self {
438 let mut border = Self::new(width, color);
439 border.right = true;
440 border
441 }
442
443 pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
444 self.top = top;
445 self.left = left;
446 self.bottom = bottom;
447 self.right = right;
448 self
449 }
450
451 pub fn top_width(&self) -> f32 {
452 if self.top {
453 self.width
454 } else {
455 0.0
456 }
457 }
458
459 pub fn left_width(&self) -> f32 {
460 if self.left {
461 self.width
462 } else {
463 0.0
464 }
465 }
466}
467
468impl ToJson for Border {
469 fn to_json(&self) -> serde_json::Value {
470 let mut value = json!({});
471 if self.top {
472 value["top"] = json!(self.width);
473 }
474 if self.right {
475 value["right"] = json!(self.width);
476 }
477 if self.bottom {
478 value["bottom"] = json!(self.width);
479 }
480 if self.left {
481 value["left"] = json!(self.width);
482 }
483 value
484 }
485}
486
487fn can_draw(bounds: RectF) -> bool {
488 let size = bounds.size();
489 size.x() > 0. && size.y() > 0.
490}