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