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}