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