scene.rs

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