scene.rs

  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}