1use ailloli_ui_runtime::DrawCmd;
4
5use crate::clip::ClipRenderMode;
6use crate::renderer::LayerPass;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
26pub struct LayerPlan {
27 pub rects: usize,
29 pub rrects: usize,
31 pub borders: usize,
33 pub shadows: usize,
35 pub ring_progresses: usize,
37 pub polylines: usize,
39 pub texts: usize,
41 pub images: usize,
43 pub has_clip: bool,
45 pub has_scissor: bool,
47 pub rounded_masks: usize,
49 pub has_window_root_clip: bool,
51 pub clip_mode: ClipRenderMode,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
65pub struct RenderPlan {
66 pub layers: Vec<LayerPlan>,
68}
69
70pub fn build_render_plan(layers: &[LayerPass<'_>]) -> RenderPlan {
83 let mut out = Vec::with_capacity(layers.len());
84 for l in layers {
85 let mut rects = 0;
86 let mut rrects = 0;
87 let mut borders = 0;
88 let mut shadows = 0;
89 let mut ring_progresses = 0;
90 let mut polylines = 0;
91 let mut texts = 0;
92 let mut images = 0;
93 for cmd in l.cmds {
94 match cmd {
95 DrawCmd::Rect(_) => rects += 1,
96 DrawCmd::RRect(_) => rrects += 1,
97 DrawCmd::Border(_) => borders += 1,
98 DrawCmd::BoxShadow(_) => shadows += 1,
99 DrawCmd::RingProgress(_) => ring_progresses += 1,
100 DrawCmd::Polyline(_) => polylines += 1,
101 DrawCmd::Text(_) => texts += 1,
102 DrawCmd::Image(_) => images += 1,
103 }
104 }
105 out.push(LayerPlan {
106 rects,
107 rrects,
108 borders,
109 shadows,
110 ring_progresses,
111 polylines,
112 texts,
113 images,
114 has_clip: !l.clip.is_empty(),
115 has_scissor: l.clip_plan.scissor.is_some(),
116 rounded_masks: l.clip_plan.rounded_masks.len(),
117 has_window_root_clip: l.clip.entries().iter().any(|entry| entry.is_window_root),
118 clip_mode: l.clip_plan.clip_mode,
119 });
120 }
121 RenderPlan { layers: out }
122}
123
124#[cfg(test)]
125mod tests {
127 use super::*;
128 use ailloli_ui_core::{BoxShadow, Color, Point, Radius, Rect, StrokeStyle};
129 use ailloli_ui_runtime::{DrawBoxShadow, DrawCmd, DrawPolyline, DrawRingProgress};
130
131 #[test]
132 fn render_plan_counts_box_shadows() {
133 let cmds = vec![DrawCmd::BoxShadow(DrawBoxShadow {
134 rect: Rect::new(0.0, 0.0, 10.0, 10.0),
135 radius: Radius::uniform(4.0),
136 shadow: BoxShadow::new(0.0, 2.0, 4.0, 0.0, Color::BLACK),
137 })];
138 let layers = vec![LayerPass::new(&cmds)];
139
140 let plan = build_render_plan(&layers);
141 assert_eq!(plan.layers[0].shadows, 1);
142 assert_eq!(plan.layers[0].ring_progresses, 0);
143 assert_eq!(plan.layers[0].polylines, 0);
144 assert_eq!(plan.layers[0].rects, 0);
145 }
146
147 #[test]
148 fn render_plan_counts_ring_progresses() {
149 let cmds = vec![DrawCmd::RingProgress(DrawRingProgress {
150 rect: Rect::new(0.0, 0.0, 32.0, 32.0),
151 thickness: 4.0,
152 fraction: 0.66,
153 track_color: Color::BLACK,
154 fill_color: Color::WHITE,
155 start_angle: -std::f32::consts::FRAC_PI_2,
156 })];
157 let layers = vec![LayerPass::new(&cmds)];
158
159 let plan = build_render_plan(&layers);
160 assert_eq!(plan.layers[0].ring_progresses, 1);
161 assert_eq!(plan.layers[0].shadows, 0);
162 assert_eq!(plan.layers[0].polylines, 0);
163 assert_eq!(plan.layers[0].rects, 0);
164 }
165
166 #[test]
167 fn render_plan_counts_polylines() {
168 let cmds = vec![DrawCmd::Polyline(DrawPolyline {
169 points: vec![Point::new(0.0, 0.0), Point::new(10.0, 10.0)],
170 stroke: StrokeStyle::new(2.0, Color::WHITE),
171 })];
172 let layers = vec![LayerPass::new(&cmds)];
173
174 let plan = build_render_plan(&layers);
175 assert_eq!(plan.layers[0].polylines, 1);
176 assert_eq!(plan.layers[0].ring_progresses, 0);
177 assert_eq!(plan.layers[0].rects, 0);
178 }
179}