scene.rs

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