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}