scene.rs

  1use serde::Deserialize;
  2use serde_json::json;
  3use std::borrow::Cow;
  4
  5use crate::{
  6    color::Color,
  7    fonts::{FontId, GlyphId},
  8    geometry::{rect::RectF, vector::Vector2F},
  9    json::ToJson,
 10};
 11
 12pub struct Scene {
 13    scale_factor: f32,
 14    layers: Vec<Layer>,
 15    active_layer_stack: Vec<usize>,
 16}
 17
 18#[derive(Default)]
 19pub struct Layer {
 20    clip_bounds: Option<RectF>,
 21    quads: Vec<Quad>,
 22    shadows: Vec<Shadow>,
 23    glyphs: Vec<Glyph>,
 24    icons: Vec<Icon>,
 25    paths: Vec<Path>,
 26}
 27
 28#[derive(Default, Debug)]
 29pub struct Quad {
 30    pub bounds: RectF,
 31    pub background: Option<Color>,
 32    pub border: Border,
 33    pub corner_radius: f32,
 34}
 35
 36#[derive(Debug)]
 37pub struct Shadow {
 38    pub bounds: RectF,
 39    pub corner_radius: f32,
 40    pub sigma: f32,
 41    pub color: Color,
 42}
 43
 44#[derive(Debug)]
 45pub struct Glyph {
 46    pub font_id: FontId,
 47    pub font_size: f32,
 48    pub id: GlyphId,
 49    pub origin: Vector2F,
 50    pub color: Color,
 51}
 52
 53pub struct Icon {
 54    pub bounds: RectF,
 55    pub svg: usvg::Tree,
 56    pub path: Cow<'static, str>,
 57    pub color: Color,
 58}
 59
 60#[derive(Clone, Copy, Default, Debug)]
 61pub struct Border {
 62    pub width: f32,
 63    pub color: Color,
 64    pub top: bool,
 65    pub right: bool,
 66    pub bottom: bool,
 67    pub left: bool,
 68}
 69
 70impl<'de> Deserialize<'de> for Border {
 71    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 72    where
 73        D: serde::Deserializer<'de>,
 74    {
 75        #[derive(Deserialize)]
 76        struct BorderData {
 77            pub width: f32,
 78            pub color: Color,
 79            #[serde(default)]
 80            pub top: bool,
 81            #[serde(default)]
 82            pub right: bool,
 83            #[serde(default)]
 84            pub bottom: bool,
 85            #[serde(default)]
 86            pub left: bool,
 87        }
 88
 89        let data = BorderData::deserialize(deserializer)?;
 90        let mut border = Border {
 91            width: data.width,
 92            color: data.color,
 93            top: data.top,
 94            bottom: data.bottom,
 95            left: data.left,
 96            right: data.right,
 97        };
 98        if !border.top && !border.bottom && !border.left && !border.right {
 99            border.top = true;
100            border.bottom = true;
101            border.left = true;
102            border.right = true;
103        }
104        Ok(border)
105    }
106}
107
108#[derive(Debug)]
109pub struct Path {
110    pub bounds: RectF,
111    pub color: Color,
112    pub vertices: Vec<PathVertex>,
113}
114
115#[derive(Debug)]
116pub struct PathVertex {
117    pub xy_position: Vector2F,
118    pub st_position: Vector2F,
119}
120
121impl Scene {
122    pub fn new(scale_factor: f32) -> Self {
123        Scene {
124            scale_factor,
125            layers: vec![Layer::new(None)],
126            active_layer_stack: vec![0],
127        }
128    }
129
130    pub fn scale_factor(&self) -> f32 {
131        self.scale_factor
132    }
133
134    pub fn layers(&self) -> &[Layer] {
135        self.layers.as_slice()
136    }
137
138    pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
139        let ix = self.layers.len();
140        self.layers.push(Layer::new(clip_bounds));
141        self.active_layer_stack.push(ix);
142    }
143
144    pub fn pop_layer(&mut self) {
145        assert!(self.active_layer_stack.len() > 1);
146        self.active_layer_stack.pop();
147    }
148
149    pub fn push_quad(&mut self, quad: Quad) {
150        self.active_layer().push_quad(quad)
151    }
152
153    pub fn push_shadow(&mut self, shadow: Shadow) {
154        self.active_layer().push_shadow(shadow)
155    }
156
157    pub fn push_glyph(&mut self, glyph: Glyph) {
158        self.active_layer().push_glyph(glyph)
159    }
160
161    pub fn push_icon(&mut self, icon: Icon) {
162        self.active_layer().push_icon(icon)
163    }
164
165    pub fn push_path(&mut self, path: Path) {
166        self.active_layer().push_path(path);
167    }
168
169    fn active_layer(&mut self) -> &mut Layer {
170        &mut self.layers[*self.active_layer_stack.last().unwrap()]
171    }
172}
173
174impl Layer {
175    pub fn new(clip_bounds: Option<RectF>) -> Self {
176        Self {
177            clip_bounds,
178            quads: Vec::new(),
179            shadows: Vec::new(),
180            glyphs: Vec::new(),
181            icons: Vec::new(),
182            paths: Vec::new(),
183        }
184    }
185
186    pub fn clip_bounds(&self) -> Option<RectF> {
187        self.clip_bounds
188    }
189
190    fn push_quad(&mut self, quad: Quad) {
191        self.quads.push(quad);
192    }
193
194    pub fn quads(&self) -> &[Quad] {
195        self.quads.as_slice()
196    }
197
198    fn push_shadow(&mut self, shadow: Shadow) {
199        self.shadows.push(shadow);
200    }
201
202    pub fn shadows(&self) -> &[Shadow] {
203        self.shadows.as_slice()
204    }
205
206    fn push_glyph(&mut self, glyph: Glyph) {
207        self.glyphs.push(glyph);
208    }
209
210    pub fn glyphs(&self) -> &[Glyph] {
211        self.glyphs.as_slice()
212    }
213
214    pub fn push_icon(&mut self, icon: Icon) {
215        self.icons.push(icon);
216    }
217
218    pub fn icons(&self) -> &[Icon] {
219        self.icons.as_slice()
220    }
221
222    fn push_path(&mut self, path: Path) {
223        if !path.bounds.is_empty() {
224            self.paths.push(path);
225        }
226    }
227
228    pub fn paths(&self) -> &[Path] {
229        self.paths.as_slice()
230    }
231}
232
233impl Border {
234    pub fn new(width: f32, color: Color) -> Self {
235        Self {
236            width,
237            color,
238            top: false,
239            left: false,
240            bottom: false,
241            right: false,
242        }
243    }
244
245    pub fn all(width: f32, color: Color) -> Self {
246        Self {
247            width,
248            color,
249            top: true,
250            left: true,
251            bottom: true,
252            right: true,
253        }
254    }
255
256    pub fn top(width: f32, color: Color) -> Self {
257        let mut border = Self::new(width, color);
258        border.top = true;
259        border
260    }
261
262    pub fn left(width: f32, color: Color) -> Self {
263        let mut border = Self::new(width, color);
264        border.left = true;
265        border
266    }
267
268    pub fn bottom(width: f32, color: Color) -> Self {
269        let mut border = Self::new(width, color);
270        border.bottom = true;
271        border
272    }
273
274    pub fn right(width: f32, color: Color) -> Self {
275        let mut border = Self::new(width, color);
276        border.right = true;
277        border
278    }
279
280    pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
281        self.top = top;
282        self.left = left;
283        self.bottom = bottom;
284        self.right = right;
285        self
286    }
287
288    pub fn top_width(&self) -> f32 {
289        if self.top {
290            self.width
291        } else {
292            0.0
293        }
294    }
295
296    pub fn left_width(&self) -> f32 {
297        if self.left {
298            self.width
299        } else {
300            0.0
301        }
302    }
303}
304
305impl ToJson for Border {
306    fn to_json(&self) -> serde_json::Value {
307        let mut value = json!({});
308        if self.top {
309            value["top"] = json!(self.width);
310        }
311        if self.right {
312            value["right"] = json!(self.width);
313        }
314        if self.bottom {
315            value["bottom"] = json!(self.width);
316        }
317        if self.left {
318            value["left"] = json!(self.width);
319        }
320        value
321    }
322}