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