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<Underline>,
 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
 79#[derive(Clone, Copy, Default, Debug)]
 80pub struct Underline {
 81    pub origin: Vector2F,
 82    pub width: f32,
 83    pub thickness: f32,
 84    pub color: Color,
 85    pub squiggly: bool,
 86}
 87
 88impl<'de> Deserialize<'de> for Border {
 89    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 90    where
 91        D: serde::Deserializer<'de>,
 92    {
 93        #[derive(Deserialize)]
 94        struct BorderData {
 95            pub width: f32,
 96            pub color: Color,
 97            #[serde(default)]
 98            pub overlay: bool,
 99            #[serde(default)]
100            pub top: bool,
101            #[serde(default)]
102            pub right: bool,
103            #[serde(default)]
104            pub bottom: bool,
105            #[serde(default)]
106            pub left: bool,
107        }
108
109        let data = BorderData::deserialize(deserializer)?;
110        let mut border = Border {
111            width: data.width,
112            color: data.color,
113            overlay: data.overlay,
114            top: data.top,
115            bottom: data.bottom,
116            left: data.left,
117            right: data.right,
118        };
119        if !border.top && !border.bottom && !border.left && !border.right {
120            border.top = true;
121            border.bottom = true;
122            border.left = true;
123            border.right = true;
124        }
125        Ok(border)
126    }
127}
128
129#[derive(Debug)]
130pub struct Path {
131    pub bounds: RectF,
132    pub color: Color,
133    pub vertices: Vec<PathVertex>,
134}
135
136#[derive(Debug)]
137pub struct PathVertex {
138    pub xy_position: Vector2F,
139    pub st_position: Vector2F,
140}
141
142pub struct Image {
143    pub bounds: RectF,
144    pub border: Border,
145    pub corner_radius: f32,
146    pub data: Arc<ImageData>,
147}
148
149impl Scene {
150    pub fn new(scale_factor: f32) -> Self {
151        let stacking_context = StackingContext::new(None);
152        Scene {
153            scale_factor,
154            stacking_contexts: vec![stacking_context],
155            active_stacking_context_stack: vec![0],
156        }
157    }
158
159    pub fn scale_factor(&self) -> f32 {
160        self.scale_factor
161    }
162
163    pub fn layers(&self) -> impl Iterator<Item = &Layer> {
164        self.stacking_contexts.iter().flat_map(|s| &s.layers)
165    }
166
167    pub fn push_stacking_context(&mut self, clip_bounds: Option<RectF>) {
168        self.active_stacking_context_stack
169            .push(self.stacking_contexts.len());
170        self.stacking_contexts
171            .push(StackingContext::new(clip_bounds))
172    }
173
174    pub fn pop_stacking_context(&mut self) {
175        self.active_stacking_context_stack.pop();
176        assert!(!self.active_stacking_context_stack.is_empty());
177    }
178
179    pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
180        self.active_stacking_context().push_layer(clip_bounds);
181    }
182
183    pub fn pop_layer(&mut self) {
184        self.active_stacking_context().pop_layer();
185    }
186
187    pub fn push_quad(&mut self, quad: Quad) {
188        self.active_layer().push_quad(quad)
189    }
190
191    pub fn push_image(&mut self, image: Image) {
192        self.active_layer().push_image(image)
193    }
194
195    pub fn push_underline(&mut self, underline: Underline) {
196        self.active_layer().push_underline(underline)
197    }
198
199    pub fn push_shadow(&mut self, shadow: Shadow) {
200        self.active_layer().push_shadow(shadow)
201    }
202
203    pub fn push_glyph(&mut self, glyph: Glyph) {
204        self.active_layer().push_glyph(glyph)
205    }
206
207    pub fn push_icon(&mut self, icon: Icon) {
208        self.active_layer().push_icon(icon)
209    }
210
211    pub fn push_path(&mut self, path: Path) {
212        self.active_layer().push_path(path);
213    }
214
215    fn active_stacking_context(&mut self) -> &mut StackingContext {
216        let ix = *self.active_stacking_context_stack.last().unwrap();
217        &mut self.stacking_contexts[ix]
218    }
219
220    fn active_layer(&mut self) -> &mut Layer {
221        self.active_stacking_context().active_layer()
222    }
223}
224
225impl StackingContext {
226    fn new(clip_bounds: Option<RectF>) -> Self {
227        Self {
228            layers: vec![Layer::new(clip_bounds)],
229            active_layer_stack: vec![0],
230        }
231    }
232
233    fn active_layer(&mut self) -> &mut Layer {
234        &mut self.layers[*self.active_layer_stack.last().unwrap()]
235    }
236
237    fn push_layer(&mut self, clip_bounds: Option<RectF>) {
238        let parent_clip_bounds = self.active_layer().clip_bounds();
239        let clip_bounds = clip_bounds
240            .map(|clip_bounds| {
241                clip_bounds
242                    .intersection(parent_clip_bounds.unwrap_or(clip_bounds))
243                    .unwrap_or_else(|| {
244                        if !clip_bounds.is_empty() {
245                            log::warn!("specified clip bounds are disjoint from parent layer");
246                        }
247                        RectF::default()
248                    })
249            })
250            .or(parent_clip_bounds);
251
252        let ix = self.layers.len();
253        self.layers.push(Layer::new(clip_bounds));
254        self.active_layer_stack.push(ix);
255    }
256
257    fn pop_layer(&mut self) {
258        self.active_layer_stack.pop().unwrap();
259        assert!(!self.active_layer_stack.is_empty());
260    }
261}
262
263impl Layer {
264    pub fn new(clip_bounds: Option<RectF>) -> Self {
265        Self {
266            clip_bounds,
267            quads: Vec::new(),
268            underlines: Vec::new(),
269            images: Vec::new(),
270            shadows: Vec::new(),
271            glyphs: Vec::new(),
272            icons: Vec::new(),
273            paths: Vec::new(),
274        }
275    }
276
277    pub fn clip_bounds(&self) -> Option<RectF> {
278        self.clip_bounds
279    }
280
281    fn push_quad(&mut self, quad: Quad) {
282        if can_draw(quad.bounds) {
283            self.quads.push(quad);
284        }
285    }
286
287    pub fn quads(&self) -> &[Quad] {
288        self.quads.as_slice()
289    }
290
291    fn push_underline(&mut self, underline: Underline) {
292        if underline.width > 0. {
293            self.underlines.push(underline);
294        }
295    }
296
297    pub fn underlines(&self) -> &[Underline] {
298        self.underlines.as_slice()
299    }
300
301    fn push_image(&mut self, image: Image) {
302        if can_draw(image.bounds) {
303            self.images.push(image);
304        }
305    }
306
307    pub fn images(&self) -> &[Image] {
308        self.images.as_slice()
309    }
310
311    fn push_shadow(&mut self, shadow: Shadow) {
312        if can_draw(shadow.bounds) {
313            self.shadows.push(shadow);
314        }
315    }
316
317    pub fn shadows(&self) -> &[Shadow] {
318        self.shadows.as_slice()
319    }
320
321    fn push_glyph(&mut self, glyph: Glyph) {
322        self.glyphs.push(glyph);
323    }
324
325    pub fn glyphs(&self) -> &[Glyph] {
326        self.glyphs.as_slice()
327    }
328
329    pub fn push_icon(&mut self, icon: Icon) {
330        if can_draw(icon.bounds) {
331            self.icons.push(icon);
332        }
333    }
334
335    pub fn icons(&self) -> &[Icon] {
336        self.icons.as_slice()
337    }
338
339    fn push_path(&mut self, path: Path) {
340        if can_draw(path.bounds) {
341            self.paths.push(path);
342        }
343    }
344
345    pub fn paths(&self) -> &[Path] {
346        self.paths.as_slice()
347    }
348}
349
350impl Border {
351    pub fn new(width: f32, color: Color) -> Self {
352        Self {
353            width,
354            color,
355            overlay: false,
356            top: false,
357            left: false,
358            bottom: false,
359            right: false,
360        }
361    }
362
363    pub fn all(width: f32, color: Color) -> Self {
364        Self {
365            width,
366            color,
367            overlay: false,
368            top: true,
369            left: true,
370            bottom: true,
371            right: true,
372        }
373    }
374
375    pub fn top(width: f32, color: Color) -> Self {
376        let mut border = Self::new(width, color);
377        border.top = true;
378        border
379    }
380
381    pub fn left(width: f32, color: Color) -> Self {
382        let mut border = Self::new(width, color);
383        border.left = true;
384        border
385    }
386
387    pub fn bottom(width: f32, color: Color) -> Self {
388        let mut border = Self::new(width, color);
389        border.bottom = true;
390        border
391    }
392
393    pub fn right(width: f32, color: Color) -> Self {
394        let mut border = Self::new(width, color);
395        border.right = true;
396        border
397    }
398
399    pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
400        self.top = top;
401        self.left = left;
402        self.bottom = bottom;
403        self.right = right;
404        self
405    }
406
407    pub fn top_width(&self) -> f32 {
408        if self.top {
409            self.width
410        } else {
411            0.0
412        }
413    }
414
415    pub fn left_width(&self) -> f32 {
416        if self.left {
417            self.width
418        } else {
419            0.0
420        }
421    }
422}
423
424impl ToJson for Border {
425    fn to_json(&self) -> serde_json::Value {
426        let mut value = json!({});
427        if self.top {
428            value["top"] = json!(self.width);
429        }
430        if self.right {
431            value["right"] = json!(self.width);
432        }
433        if self.bottom {
434            value["bottom"] = json!(self.width);
435        }
436        if self.left {
437            value["left"] = json!(self.width);
438        }
439        value
440    }
441}
442
443fn can_draw(bounds: RectF) -> bool {
444    let size = bounds.size();
445    size.x() > 0. && size.y() > 0.
446}