scene.rs

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