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, Deserialize)]
 61pub struct Border {
 62    #[serde(default = "default_border_width")]
 63    pub width: f32,
 64    #[serde(default)]
 65    pub color: Option<Color>,
 66    #[serde(default)]
 67    pub top: bool,
 68    #[serde(default)]
 69    pub right: bool,
 70    #[serde(default)]
 71    pub bottom: bool,
 72    #[serde(default)]
 73    pub left: bool,
 74}
 75
 76fn default_border_width() -> f32 {
 77    1.0
 78}
 79
 80#[derive(Debug)]
 81pub struct Path {
 82    pub bounds: RectF,
 83    pub color: Color,
 84    pub vertices: Vec<PathVertex>,
 85}
 86
 87#[derive(Debug)]
 88pub struct PathVertex {
 89    pub xy_position: Vector2F,
 90    pub st_position: Vector2F,
 91}
 92
 93impl Scene {
 94    pub fn new(scale_factor: f32) -> Self {
 95        Scene {
 96            scale_factor,
 97            layers: vec![Layer::new(None)],
 98            active_layer_stack: vec![0],
 99        }
100    }
101
102    pub fn scale_factor(&self) -> f32 {
103        self.scale_factor
104    }
105
106    pub fn layers(&self) -> &[Layer] {
107        self.layers.as_slice()
108    }
109
110    pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
111        let ix = self.layers.len();
112        self.layers.push(Layer::new(clip_bounds));
113        self.active_layer_stack.push(ix);
114    }
115
116    pub fn pop_layer(&mut self) {
117        assert!(self.active_layer_stack.len() > 1);
118        self.active_layer_stack.pop();
119    }
120
121    pub fn push_quad(&mut self, quad: Quad) {
122        self.active_layer().push_quad(quad)
123    }
124
125    pub fn push_shadow(&mut self, shadow: Shadow) {
126        self.active_layer().push_shadow(shadow)
127    }
128
129    pub fn push_glyph(&mut self, glyph: Glyph) {
130        self.active_layer().push_glyph(glyph)
131    }
132
133    pub fn push_icon(&mut self, icon: Icon) {
134        self.active_layer().push_icon(icon)
135    }
136
137    pub fn push_path(&mut self, path: Path) {
138        self.active_layer().push_path(path);
139    }
140
141    fn active_layer(&mut self) -> &mut Layer {
142        &mut self.layers[*self.active_layer_stack.last().unwrap()]
143    }
144}
145
146impl Layer {
147    pub fn new(clip_bounds: Option<RectF>) -> Self {
148        Self {
149            clip_bounds,
150            quads: Vec::new(),
151            shadows: Vec::new(),
152            glyphs: Vec::new(),
153            icons: Vec::new(),
154            paths: Vec::new(),
155        }
156    }
157
158    pub fn clip_bounds(&self) -> Option<RectF> {
159        self.clip_bounds
160    }
161
162    fn push_quad(&mut self, quad: Quad) {
163        self.quads.push(quad);
164    }
165
166    pub fn quads(&self) -> &[Quad] {
167        self.quads.as_slice()
168    }
169
170    fn push_shadow(&mut self, shadow: Shadow) {
171        self.shadows.push(shadow);
172    }
173
174    pub fn shadows(&self) -> &[Shadow] {
175        self.shadows.as_slice()
176    }
177
178    fn push_glyph(&mut self, glyph: Glyph) {
179        self.glyphs.push(glyph);
180    }
181
182    pub fn glyphs(&self) -> &[Glyph] {
183        self.glyphs.as_slice()
184    }
185
186    pub fn push_icon(&mut self, icon: Icon) {
187        self.icons.push(icon);
188    }
189
190    pub fn icons(&self) -> &[Icon] {
191        self.icons.as_slice()
192    }
193
194    fn push_path(&mut self, path: Path) {
195        if !path.bounds.is_empty() {
196            self.paths.push(path);
197        }
198    }
199
200    pub fn paths(&self) -> &[Path] {
201        self.paths.as_slice()
202    }
203}
204
205impl Border {
206    pub fn new(width: f32, color: Color) -> Self {
207        Self {
208            width,
209            color: Some(color),
210            top: false,
211            left: false,
212            bottom: false,
213            right: false,
214        }
215    }
216
217    pub fn all(width: f32, color: Color) -> Self {
218        Self {
219            width,
220            color: Some(color),
221            top: true,
222            left: true,
223            bottom: true,
224            right: true,
225        }
226    }
227
228    pub fn top(width: f32, color: Color) -> Self {
229        let mut border = Self::new(width, color);
230        border.top = true;
231        border
232    }
233
234    pub fn left(width: f32, color: Color) -> Self {
235        let mut border = Self::new(width, color);
236        border.left = true;
237        border
238    }
239
240    pub fn bottom(width: f32, color: Color) -> Self {
241        let mut border = Self::new(width, color);
242        border.bottom = true;
243        border
244    }
245
246    pub fn right(width: f32, color: Color) -> Self {
247        let mut border = Self::new(width, color);
248        border.right = true;
249        border
250    }
251
252    pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
253        self.top = top;
254        self.left = left;
255        self.bottom = bottom;
256        self.right = right;
257        self
258    }
259
260    pub fn top_width(&self) -> f32 {
261        if self.top {
262            self.width
263        } else {
264            0.0
265        }
266    }
267
268    pub fn left_width(&self) -> f32 {
269        if self.left {
270            self.width
271        } else {
272            0.0
273        }
274    }
275}
276
277impl ToJson for Border {
278    fn to_json(&self) -> serde_json::Value {
279        let mut value = json!({});
280        if self.top {
281            value["top"] = json!(self.width);
282        }
283        if self.right {
284            value["right"] = json!(self.width);
285        }
286        if self.bottom {
287            value["bottom"] = json!(self.width);
288        }
289        if self.left {
290            value["left"] = json!(self.width);
291        }
292        value
293    }
294}