1use super::*;
4
5#[derive(Clone, Debug)]
8pub struct AlphaMaskPaint {
9 pub path: kurbo::BezPath,
10 pub transform: kurbo::Affine,
11 pub fill: Paint,
12 pub opacity: f64,
13 pub paint_bounds: kurbo::Rect,
15 pub composition: Option<(u32, f32)>,
17}
18
19#[derive(Clone, Debug)]
21pub struct ReplayCanvasLayerUpdate {
22 pub layer: usize,
23 pub regions: Option<Vec<kurbo::Rect>>,
26}
27
28#[derive(Clone, Copy, Debug, PartialEq)]
31pub struct OpacityScope {
32 pub node_id: u32,
33 pub opacity: f32,
34}
35
36impl crate::Interpolatable for OpacityScope {}
37
38pub trait RenderContext {
40 #[cfg(feature = "shaders")]
44 fn begin_shader_effect(
45 &mut self,
46 _layer: usize,
47 _id: u32,
48 _z: i32,
49 _effect: &ShaderEffect,
50 _transform: kurbo::Affine,
51 _bounds: (f64, f64),
52 _scopes: &[OpacityScope],
53 _children: &[u32],
54 ) -> bool {
55 panic!("shader effects require the WGPU renderer; this backend does not support them")
56 }
57 #[cfg(feature = "shaders")]
59 fn end_shader_effect(&mut self, _layer: usize, _id: u32) {}
60 fn fill(&mut self, layer: usize, path: kurbo::BezPath, fill: &Paint) {
63 self.fill_with_opacity(layer, path, fill, 1.0);
64 }
65 fn fill_with_opacity(&mut self, layer: usize, path: kurbo::BezPath, fill: &Paint, opacity: f64);
67 fn fill_with_material_and_opacity(
69 &mut self,
70 layer: usize,
71 path: kurbo::BezPath,
72 fill: &Paint,
73 _material: &ResolvedMaterial,
74 opacity: f64,
75 ) {
76 self.fill_with_opacity(layer, path, fill, opacity);
77 }
78 fn fill_with_material_and_opacity_and_smoothing(
80 &mut self,
81 layer: usize,
82 path: kurbo::BezPath,
83 fill: &Paint,
84 material: &ResolvedMaterial,
85 opacity: f64,
86 smoothing: PathSmoothing,
87 ) {
88 let path = crate::drawing::path_smoothing::smooth_bez_path(&path, smoothing);
89 self.fill_with_material_and_opacity(layer, path, fill, material, opacity);
90 }
91 fn stroke(&mut self, layer: usize, path: kurbo::BezPath, stroke: &ResolvedStroke) {
93 self.stroke_with_opacity(layer, path, stroke, 1.0);
94 }
95 fn stroke_with_opacity(
97 &mut self,
98 layer: usize,
99 path: kurbo::BezPath,
100 stroke: &ResolvedStroke,
101 opacity: f64,
102 );
103 fn stroke_with_material_and_opacity(
105 &mut self,
106 layer: usize,
107 path: kurbo::BezPath,
108 stroke: &ResolvedStroke,
109 _material: &ResolvedMaterial,
110 opacity: f64,
111 ) {
112 self.stroke_with_opacity(layer, path, stroke, opacity);
113 }
114 fn stroke_with_material_and_opacity_and_smoothing(
116 &mut self,
117 layer: usize,
118 path: kurbo::BezPath,
119 stroke: &ResolvedStroke,
120 material: &ResolvedMaterial,
121 opacity: f64,
122 smoothing: PathSmoothing,
123 ) {
124 let path = crate::drawing::path_smoothing::smooth_bez_path(&path, smoothing);
125 self.stroke_with_material_and_opacity(layer, path, stroke, material, opacity);
126 }
127 fn stroke_with_draw_range_and_material_and_opacity(
129 &mut self,
130 layer: usize,
131 path: kurbo::BezPath,
132 stroke: &ResolvedStroke,
133 material: &ResolvedMaterial,
134 opacity: f64,
135 draw_start: f64,
136 draw_end: f64,
137 );
138 fn stroke_with_draw_range_and_material_and_opacity_and_smoothing(
140 &mut self,
141 layer: usize,
142 path: kurbo::BezPath,
143 stroke: &ResolvedStroke,
144 material: &ResolvedMaterial,
145 opacity: f64,
146 draw_start: f64,
147 draw_end: f64,
148 smoothing: PathSmoothing,
149 ) {
150 let path = crate::drawing::path_smoothing::smooth_bez_path(&path, smoothing);
151 self.stroke_with_draw_range_and_material_and_opacity(
152 layer, path, stroke, material, opacity, draw_start, draw_end,
153 );
154 }
155
156 fn save(&mut self, layer: usize);
159 fn restore(&mut self, layer: usize);
161 fn clip(&mut self, layer: usize, path: BezPath);
163 fn clip_alpha(&mut self, _layer: usize, _paints: &[AlphaMaskPaint], _feather: f64) {
166 panic!("this rendering backend does not implement alpha masks");
167 }
168 fn supports_alpha_source_capture(&self) -> bool {
170 false
171 }
172 fn alpha_source_layer(&self) -> Option<usize> {
175 None
176 }
177 fn begin_alpha_source(
180 &mut self,
181 _layer: usize,
182 _world_to_surface: kurbo::Affine,
183 _inherited_scopes: usize,
184 _feather: f64,
185 ) {
186 panic!("this rendering backend does not implement alpha-source capture");
187 }
188 fn end_alpha_source(&mut self, _layer: usize) {}
190 fn transform(&mut self, layer: usize, affine: kurbo::Affine);
192
193 fn load_image(&mut self, identifier: &str, image: &[u8], width: usize, height: usize);
196 fn draw_image(&mut self, layer: usize, image_path: &str, rect: kurbo::Rect) {
198 self.draw_image_with_opacity(layer, image_path, rect, 1.0);
199 }
200 fn draw_image_with_opacity(
203 &mut self,
204 layer: usize,
205 image_path: &str,
206 rect: kurbo::Rect,
207 opacity: f64,
208 );
209 fn get_image_size(&mut self, image_path: &str) -> Option<(usize, usize)>;
211 fn image_loaded(&self, image_path: &str) -> bool;
213
214 fn layers(&self) -> usize;
217 fn resize_layers_to(&mut self, layer_count: usize, dirty_canvases: Rc<RefCell<Vec<bool>>>);
219 fn clear(&mut self, layer: usize);
221 fn flush(&mut self, layer: usize, dirty_canvases: Rc<RefCell<Vec<bool>>>);
223 fn resize(&mut self, width: usize, height: usize);
225 fn refresh_layers(&mut self, layers: &[usize]);
227 fn set_scene_lighting(&mut self, _layer: usize, _lighting: &SceneLighting) {}
229 fn clear_targeted_replay(&mut self, _layer: usize) {}
231 fn take_ready_canvas_layers(&mut self) -> Vec<usize> {
233 vec![]
234 }
235
236 fn take_replay_canvas_layers(&mut self) -> Vec<usize> {
238 vec![]
239 }
240
241 fn take_replay_canvas_layer_updates(&mut self) -> Vec<ReplayCanvasLayerUpdate> {
243 self.take_replay_canvas_layers()
244 .into_iter()
245 .map(|layer| ReplayCanvasLayerUpdate {
246 layer,
247 regions: None,
248 })
249 .collect()
250 }
251
252 fn request_layer_screenshot(&mut self, _layer: usize, _request_id: u32) {}
254
255 fn take_layer_screenshot(&mut self, _layer: usize, _request_id: u32) -> Option<ScreenshotData> {
257 None
258 }
259
260 fn take_layer_surface_screenshots(
262 &mut self,
263 layer: usize,
264 request_id: u32,
265 ) -> Vec<LayerSurfaceScreenshotData> {
266 self.take_layer_screenshot(layer, request_id)
267 .map(|screenshot| {
268 vec![LayerSurfaceScreenshotData {
269 id: screenshot.id,
270 key: "single".to_string(),
271 data: screenshot.data,
272 width: screenshot.width,
273 height: screenshot.height,
274 origin_x: 0.0,
275 origin_y: 0.0,
276 logical_width: screenshot.width as f32,
277 logical_height: screenshot.height as f32,
278 }]
279 })
280 .unwrap_or_default()
281 }
282
283 fn retains_canvas_nodes(&self) -> bool {
285 true
286 }
287
288 fn begin_node(
290 &mut self,
291 _layer: usize,
292 _node_id: u32,
293 _z_index: i32,
294 _light_mask: u32,
295 ) -> bool {
296 true
297 }
298
299 fn begin_node_with_bounds(
301 &mut self,
302 layer: usize,
303 node_id: u32,
304 z_index: i32,
305 _coverage_bounds: kurbo::Rect,
306 light_mask: u32,
307 ) -> bool {
308 self.begin_node(layer, node_id, z_index, light_mask)
309 }
310
311 fn take_clean_skipped_node(&mut self, _layer: usize, _node_id: u32) -> bool {
313 false
314 }
315
316 fn supports_subtree_opacity(&self) -> bool {
319 false
320 }
321
322 fn set_node_opacity_scopes(&mut self, _layer: usize, _node_id: u32, _scopes: &[OpacityScope]) {}
324
325 fn end_node(&mut self, _layer: usize, _node_id: u32) -> bool {
327 true
328 }
329
330 fn remove_node(&mut self, _layer: usize, _node_id: u32) -> bool {
332 true
333 }
334}
335
336pub fn bez_path_to_svg_path_data(path: &BezPath) -> String {
338 use kurbo::PathEl;
339
340 let mut data = String::new();
341 for element in path.elements() {
342 match element {
343 PathEl::MoveTo(point) => data.push_str(&format!("M{:.3},{:.3}", point.x, point.y)),
344 PathEl::LineTo(point) => data.push_str(&format!("L{:.3},{:.3}", point.x, point.y)),
345 PathEl::QuadTo(ctrl, point) => data.push_str(&format!(
346 "Q{:.3},{:.3} {:.3},{:.3}",
347 ctrl.x, ctrl.y, point.x, point.y
348 )),
349 PathEl::CurveTo(ctrl1, ctrl2, point) => data.push_str(&format!(
350 "C{:.3},{:.3} {:.3},{:.3} {:.3},{:.3}",
351 ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, point.x, point.y
352 )),
353 PathEl::ClosePath => data.push('Z'),
354 }
355 }
356 data
357}
358
359#[derive(Debug, Clone, Copy, PartialEq)]
361pub enum Layer {
362 Native,
364 NativeNonOccluding,
366 Canvas,
368 DontCare,
370}