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