scene.rs

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