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 layers: Vec<Layer>,
15 active_layer_stack: Vec<usize>,
16}
17
18#[derive(Default)]
19pub struct Layer {
20 clip_bounds: Option<RectF>,
21 quads: Vec<Quad>,
22 shadows: Vec<Shadow>,
23 glyphs: Vec<Glyph>,
24 icons: Vec<Icon>,
25 paths: Vec<Path>,
26}
27
28#[derive(Default, Debug)]
29pub struct Quad {
30 pub bounds: RectF,
31 pub background: Option<Color>,
32 pub border: Border,
33 pub corner_radius: f32,
34}
35
36#[derive(Debug)]
37pub struct Shadow {
38 pub bounds: RectF,
39 pub corner_radius: f32,
40 pub sigma: f32,
41 pub color: Color,
42}
43
44#[derive(Debug)]
45pub struct Glyph {
46 pub font_id: FontId,
47 pub font_size: f32,
48 pub id: GlyphId,
49 pub origin: Vector2F,
50 pub color: Color,
51}
52
53pub struct Icon {
54 pub bounds: RectF,
55 pub svg: usvg::Tree,
56 pub path: Cow<'static, str>,
57 pub color: Color,
58}
59
60#[derive(Clone, Copy, Default, Debug, Deserialize)]
61pub struct Border {
62 #[serde(default = "default_border_width")]
63 pub width: f32,
64 #[serde(default)]
65 pub color: Option<Color>,
66 #[serde(default)]
67 pub top: bool,
68 #[serde(default)]
69 pub right: bool,
70 #[serde(default)]
71 pub bottom: bool,
72 #[serde(default)]
73 pub left: bool,
74}
75
76fn default_border_width() -> f32 {
77 1.0
78}
79
80#[derive(Debug)]
81pub struct Path {
82 pub bounds: RectF,
83 pub color: Color,
84 pub vertices: Vec<PathVertex>,
85}
86
87#[derive(Debug)]
88pub struct PathVertex {
89 pub xy_position: Vector2F,
90 pub st_position: Vector2F,
91}
92
93impl Scene {
94 pub fn new(scale_factor: f32) -> Self {
95 Scene {
96 scale_factor,
97 layers: vec![Layer::new(None)],
98 active_layer_stack: vec![0],
99 }
100 }
101
102 pub fn scale_factor(&self) -> f32 {
103 self.scale_factor
104 }
105
106 pub fn layers(&self) -> &[Layer] {
107 self.layers.as_slice()
108 }
109
110 pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
111 let ix = self.layers.len();
112 self.layers.push(Layer::new(clip_bounds));
113 self.active_layer_stack.push(ix);
114 }
115
116 pub fn pop_layer(&mut self) {
117 assert!(self.active_layer_stack.len() > 1);
118 self.active_layer_stack.pop();
119 }
120
121 pub fn push_quad(&mut self, quad: Quad) {
122 self.active_layer().push_quad(quad)
123 }
124
125 pub fn push_shadow(&mut self, shadow: Shadow) {
126 self.active_layer().push_shadow(shadow)
127 }
128
129 pub fn push_glyph(&mut self, glyph: Glyph) {
130 self.active_layer().push_glyph(glyph)
131 }
132
133 pub fn push_icon(&mut self, icon: Icon) {
134 self.active_layer().push_icon(icon)
135 }
136
137 pub fn push_path(&mut self, path: Path) {
138 self.active_layer().push_path(path);
139 }
140
141 fn active_layer(&mut self) -> &mut Layer {
142 &mut self.layers[*self.active_layer_stack.last().unwrap()]
143 }
144}
145
146impl Layer {
147 pub fn new(clip_bounds: Option<RectF>) -> Self {
148 Self {
149 clip_bounds,
150 quads: Vec::new(),
151 shadows: Vec::new(),
152 glyphs: Vec::new(),
153 icons: Vec::new(),
154 paths: Vec::new(),
155 }
156 }
157
158 pub fn clip_bounds(&self) -> Option<RectF> {
159 self.clip_bounds
160 }
161
162 fn push_quad(&mut self, quad: Quad) {
163 self.quads.push(quad);
164 }
165
166 pub fn quads(&self) -> &[Quad] {
167 self.quads.as_slice()
168 }
169
170 fn push_shadow(&mut self, shadow: Shadow) {
171 self.shadows.push(shadow);
172 }
173
174 pub fn shadows(&self) -> &[Shadow] {
175 self.shadows.as_slice()
176 }
177
178 fn push_glyph(&mut self, glyph: Glyph) {
179 self.glyphs.push(glyph);
180 }
181
182 pub fn glyphs(&self) -> &[Glyph] {
183 self.glyphs.as_slice()
184 }
185
186 pub fn push_icon(&mut self, icon: Icon) {
187 self.icons.push(icon);
188 }
189
190 pub fn icons(&self) -> &[Icon] {
191 self.icons.as_slice()
192 }
193
194 fn push_path(&mut self, path: Path) {
195 if !path.bounds.is_empty() {
196 self.paths.push(path);
197 }
198 }
199
200 pub fn paths(&self) -> &[Path] {
201 self.paths.as_slice()
202 }
203}
204
205impl Border {
206 pub fn new(width: f32, color: Color) -> Self {
207 Self {
208 width,
209 color: Some(color),
210 top: false,
211 left: false,
212 bottom: false,
213 right: false,
214 }
215 }
216
217 pub fn all(width: f32, color: Color) -> Self {
218 Self {
219 width,
220 color: Some(color),
221 top: true,
222 left: true,
223 bottom: true,
224 right: true,
225 }
226 }
227
228 pub fn top(width: f32, color: Color) -> Self {
229 let mut border = Self::new(width, color);
230 border.top = true;
231 border
232 }
233
234 pub fn left(width: f32, color: Color) -> Self {
235 let mut border = Self::new(width, color);
236 border.left = true;
237 border
238 }
239
240 pub fn bottom(width: f32, color: Color) -> Self {
241 let mut border = Self::new(width, color);
242 border.bottom = true;
243 border
244 }
245
246 pub fn right(width: f32, color: Color) -> Self {
247 let mut border = Self::new(width, color);
248 border.right = true;
249 border
250 }
251
252 pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
253 self.top = top;
254 self.left = left;
255 self.bottom = bottom;
256 self.right = right;
257 self
258 }
259
260 pub fn top_width(&self) -> f32 {
261 if self.top {
262 self.width
263 } else {
264 0.0
265 }
266 }
267
268 pub fn left_width(&self) -> f32 {
269 if self.left {
270 self.width
271 } else {
272 0.0
273 }
274 }
275}
276
277impl ToJson for Border {
278 fn to_json(&self) -> serde_json::Value {
279 let mut value = json!({});
280 if self.top {
281 value["top"] = json!(self.width);
282 }
283 if self.right {
284 value["right"] = json!(self.width);
285 }
286 if self.bottom {
287 value["bottom"] = json!(self.width);
288 }
289 if self.left {
290 value["left"] = json!(self.width);
291 }
292 value
293 }
294}