scene.rs

  1use crate::{
  2    color::ColorU,
  3    fonts::{FontId, GlyphId},
  4    geometry::{rect::RectF, vector::Vector2F},
  5};
  6
  7pub struct Scene {
  8    scale_factor: f32,
  9    layers: Vec<Layer>,
 10    active_layer_stack: Vec<usize>,
 11}
 12
 13#[derive(Default)]
 14pub struct Layer {
 15    clip_bounds: Option<RectF>,
 16    quads: Vec<Quad>,
 17    shadows: Vec<Shadow>,
 18    glyphs: Vec<Glyph>,
 19    icons: Vec<Icon>,
 20    paths: Vec<Path>,
 21}
 22
 23#[derive(Default, Debug)]
 24pub struct Quad {
 25    pub bounds: RectF,
 26    pub background: Option<ColorU>,
 27    pub border: Border,
 28    pub corner_radius: f32,
 29}
 30
 31#[derive(Debug)]
 32pub struct Shadow {
 33    pub bounds: RectF,
 34    pub corner_radius: f32,
 35    pub sigma: f32,
 36    pub color: ColorU,
 37}
 38
 39#[derive(Debug)]
 40pub struct Glyph {
 41    pub font_id: FontId,
 42    pub font_size: f32,
 43    pub id: GlyphId,
 44    pub origin: Vector2F,
 45    pub color: ColorU,
 46}
 47
 48pub struct Icon {
 49    pub bounds: RectF,
 50    pub svg: usvg::Tree,
 51    pub path: String,
 52    pub color: ColorU,
 53}
 54
 55#[derive(Clone, Copy, Default, Debug)]
 56pub struct Border {
 57    pub width: f32,
 58    pub color: Option<ColorU>,
 59    pub top: bool,
 60    pub right: bool,
 61    pub bottom: bool,
 62    pub left: bool,
 63}
 64
 65#[derive(Debug)]
 66pub struct Path {
 67    pub bounds: RectF,
 68    pub color: ColorU,
 69    pub vertices: Vec<PathVertex>,
 70}
 71
 72#[derive(Debug)]
 73pub struct PathVertex {
 74    pub xy_position: Vector2F,
 75    pub st_position: Vector2F,
 76}
 77
 78impl Scene {
 79    pub fn new(scale_factor: f32) -> Self {
 80        Scene {
 81            scale_factor,
 82            layers: vec![Layer::new(None)],
 83            active_layer_stack: vec![0],
 84        }
 85    }
 86
 87    pub fn scale_factor(&self) -> f32 {
 88        self.scale_factor
 89    }
 90
 91    pub fn layers(&self) -> &[Layer] {
 92        self.layers.as_slice()
 93    }
 94
 95    pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
 96        let ix = self.layers.len();
 97        self.layers.push(Layer::new(clip_bounds));
 98        self.active_layer_stack.push(ix);
 99    }
100
101    pub fn pop_layer(&mut self) {
102        assert!(self.active_layer_stack.len() > 1);
103        self.active_layer_stack.pop();
104    }
105
106    pub fn push_quad(&mut self, quad: Quad) {
107        self.active_layer().push_quad(quad)
108    }
109
110    pub fn push_shadow(&mut self, shadow: Shadow) {
111        self.active_layer().push_shadow(shadow)
112    }
113
114    pub fn push_glyph(&mut self, glyph: Glyph) {
115        self.active_layer().push_glyph(glyph)
116    }
117
118    pub fn push_icon(&mut self, icon: Icon) {
119        self.active_layer().push_icon(icon)
120    }
121
122    pub fn push_path(&mut self, path: Path) {
123        self.active_layer().push_path(path);
124    }
125
126    fn active_layer(&mut self) -> &mut Layer {
127        &mut self.layers[*self.active_layer_stack.last().unwrap()]
128    }
129}
130
131impl Layer {
132    pub fn new(clip_bounds: Option<RectF>) -> Self {
133        Self {
134            clip_bounds,
135            quads: Vec::new(),
136            shadows: Vec::new(),
137            glyphs: Vec::new(),
138            icons: Vec::new(),
139            paths: Vec::new(),
140        }
141    }
142
143    pub fn clip_bounds(&self) -> Option<RectF> {
144        self.clip_bounds
145    }
146
147    fn push_quad(&mut self, quad: Quad) {
148        self.quads.push(quad);
149    }
150
151    pub fn quads(&self) -> &[Quad] {
152        self.quads.as_slice()
153    }
154
155    fn push_shadow(&mut self, shadow: Shadow) {
156        self.shadows.push(shadow);
157    }
158
159    pub fn shadows(&self) -> &[Shadow] {
160        self.shadows.as_slice()
161    }
162
163    fn push_glyph(&mut self, glyph: Glyph) {
164        self.glyphs.push(glyph);
165    }
166
167    pub fn glyphs(&self) -> &[Glyph] {
168        self.glyphs.as_slice()
169    }
170
171    pub fn push_icon(&mut self, icon: Icon) {
172        self.icons.push(icon);
173    }
174
175    pub fn icons(&self) -> &[Icon] {
176        self.icons.as_slice()
177    }
178
179    fn push_path(&mut self, path: Path) {
180        if !path.bounds.is_empty() {
181            self.paths.push(path);
182        }
183    }
184
185    pub fn paths(&self) -> &[Path] {
186        self.paths.as_slice()
187    }
188}
189
190impl Border {
191    pub fn new(width: f32, color: impl Into<ColorU>) -> Self {
192        Self {
193            width,
194            color: Some(color.into()),
195            top: false,
196            left: false,
197            bottom: false,
198            right: false,
199        }
200    }
201
202    pub fn all(width: f32, color: impl Into<ColorU>) -> Self {
203        Self {
204            width,
205            color: Some(color.into()),
206            top: true,
207            left: true,
208            bottom: true,
209            right: true,
210        }
211    }
212
213    pub fn top(width: f32, color: impl Into<ColorU>) -> Self {
214        let mut border = Self::new(width, color);
215        border.top = true;
216        border
217    }
218
219    pub fn left(width: f32, color: impl Into<ColorU>) -> Self {
220        let mut border = Self::new(width, color);
221        border.left = true;
222        border
223    }
224
225    pub fn bottom(width: f32, color: impl Into<ColorU>) -> Self {
226        let mut border = Self::new(width, color);
227        border.bottom = true;
228        border
229    }
230
231    pub fn right(width: f32, color: impl Into<ColorU>) -> Self {
232        let mut border = Self::new(width, color);
233        border.right = true;
234        border
235    }
236
237    pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
238        self.top = top;
239        self.left = left;
240        self.bottom = bottom;
241        self.right = right;
242        self
243    }
244
245    pub fn top_width(&self) -> f32 {
246        if self.top {
247            self.width
248        } else {
249            0.0
250        }
251    }
252
253    pub fn left_width(&self) -> f32 {
254        if self.left {
255            self.width
256        } else {
257            0.0
258        }
259    }
260}