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