scene.rs

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