devpage_design/display/
paint.rs1use kurbo::{Affine, BezPath, Rect as KRect};
6
7use crate::render::Draw;
8
9use super::*;
10
11pub trait Target {
15 fn draw(&mut self, draw: &Draw, t: Affine);
16 fn push_clip(&mut self, path: &BezPath, t: Affine);
17 fn push_layer(&mut self, blend: Blend, bounds: Option<&BezPath>, t: Affine, area: KRect);
21 fn pop(&mut self);
22}
23
24#[derive(Clone, Copy, PartialEq, Debug)]
25pub(super) enum Layer {
26 Clip(Id),
27 Effect(Id),
28}
29
30pub fn paint(list: &List, area: KRect, scale: f64, target: &mut impl Target) {
35 let view = Affine::scale(scale) * Affine::translate((-area.x0, -area.y0));
36 let pixels = KRect::new(0.0, 0.0, area.width() * scale, area.height() * scale);
37 let mut open: Vec<Layer> = Vec::new();
38 let place = |transform: Id| view * Affine::translate(list.world(transform));
39 for (origin, _, command) in list.query(area, 1.0 / scale) {
40 let want = layers(list, command.clip, command.effect);
41 let keep = open.iter().zip(&want).take_while(|(a, b)| a == b).count();
42 while open.len() > keep {
43 open.pop();
44 target.pop();
45 }
46 for layer in &want[keep..] {
47 match *layer {
48 Layer::Clip(id) => {
49 let c = list.trees.clips.get(id);
50 target.push_clip(&c.path, place(c.transform));
51 }
52 Layer::Effect(id) => {
53 let e = list.trees.effects.get(id);
54 target.push_layer(e.blend, e.bounds.as_ref(), place(e.transform), pixels);
55 }
56 }
57 open.push(*layer);
58 }
59 target.draw(&command.draw, view * Affine::translate(origin));
60 }
61 for _ in open {
62 target.pop();
63 }
64}
65
66pub(super) fn layers(list: &List, clip: Id, effect: Option<Id>) -> Vec<Layer> {
70 let mut effects = Vec::new();
71 let mut at = effect;
72 while let Some(e) = at {
73 effects.push(e);
74 at = list.trees.effects.get(e).parent;
75 }
76 effects.reverse();
77 let mut out = Vec::new();
78 let mut inside: Option<Id> = None;
79 for e in effects {
80 let to = list.trees.effects.get(e).clip;
81 clips(list, inside, to, &mut out);
82 out.push(Layer::Effect(e));
83 inside = Some(to);
84 }
85 clips(list, inside, clip, &mut out);
86 out
87}
88
89pub(super) fn clips(list: &List, from: Option<Id>, to: Id, out: &mut Vec<Layer>) {
91 let mut chain = Vec::new();
92 let mut at = Some(to);
93 while let Some(c) = at {
94 if Some(c) == from {
95 break;
96 }
97 chain.push(Layer::Clip(c));
98 at = list.trees.clips.get(c).parent;
99 }
100 out.extend(chain.into_iter().rev());
101}