1use super::*;
12use agg_gui::draw_ctx::DrawCtx;
13use agg_gui::text::{measure_text_metrics, TextMetrics};
14use agg_gui::CompOp;
15use agg_rust::arc::Arc as AggArc;
16use agg_rust::basics::PATH_FLAGS_NONE;
17use agg_rust::rounded_rect::RoundedRect;
18
19impl DrawCtx for WgpuGfxCtx {
20 fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
21 Some(self as &mut dyn std::any::Any)
22 }
23
24 fn set_fill_color(&mut self, c: Color) {
27 self.fill_color = c;
28 self.fill_linear_gradient = None;
29 self.fill_radial_gradient = None;
30 }
31
32 fn set_fill_linear_gradient(&mut self, gradient: LinearGradientPaint) {
33 self.fill_linear_gradient = Some(gradient);
34 self.fill_radial_gradient = None;
35 }
36
37 fn supports_fill_linear_gradient(&self) -> bool {
38 true
39 }
40
41 fn set_fill_radial_gradient(&mut self, gradient: RadialGradientPaint) {
42 self.fill_linear_gradient = None;
43 self.fill_radial_gradient = Some(gradient);
44 }
45
46 fn supports_fill_radial_gradient(&self) -> bool {
47 true
48 }
49
50 fn set_stroke_color(&mut self, c: Color) {
51 self.stroke_color = c;
52 self.stroke_linear_gradient = None;
53 self.stroke_radial_gradient = None;
54 }
55
56 fn set_stroke_linear_gradient(&mut self, gradient: LinearGradientPaint) {
57 self.stroke_linear_gradient = Some(gradient);
58 self.stroke_radial_gradient = None;
59 }
60
61 fn supports_stroke_linear_gradient(&self) -> bool {
62 true
63 }
64
65 fn set_stroke_radial_gradient(&mut self, gradient: RadialGradientPaint) {
66 self.stroke_linear_gradient = None;
67 self.stroke_radial_gradient = Some(gradient);
68 }
69
70 fn supports_stroke_radial_gradient(&self) -> bool {
71 true
72 }
73
74 fn set_line_width(&mut self, w: f64) {
75 self.line_width = w;
76 }
77
78 fn set_line_join(&mut self, j: LineJoin) {
79 self.line_join = j;
80 }
81
82 fn set_line_cap(&mut self, c: LineCap) {
83 self.line_cap = c;
84 }
85
86 fn set_miter_limit(&mut self, limit: f64) {
87 self.miter_limit = limit.max(1.0);
88 }
89
90 fn set_line_dash(&mut self, dashes: &[f64], offset: f64) {
91 self.line_dash.clear();
92 self.line_dash
93 .extend(dashes.iter().copied().filter(|v| *v > 0.0));
94 self.dash_offset = offset;
95 }
96
97 fn set_blend_mode(&mut self, _mode: CompOp) {
98 }
101
102 fn set_global_alpha(&mut self, a: f64) {
103 self.global_alpha = a;
104 }
105
106 fn set_fill_rule(&mut self, rule: agg_gui::draw_ctx::FillRule) {
107 self.fill_rule = rule;
108 }
109
110 fn set_font(&mut self, font: std::sync::Arc<Font>) {
113 self.font = Some(font);
114 }
115
116 fn set_font_size(&mut self, size: f64) {
117 self.font_size = size;
118 }
119
120 fn clip_rect(&mut self, x: f64, y: f64, w: f64, h: f64) {
123 let (mut x0, mut y0) = (x, y);
125 let (mut x1, mut y1) = (x + w, y + h);
126 self.ctm().transform(&mut x0, &mut y0);
127 self.ctm().transform(&mut x1, &mut y1);
128 let (lx, rx) = if x0 < x1 { (x0, x1) } else { (x1, x0) };
129 let (by, ty) = if y0 < y1 { (y0, y1) } else { (y1, y0) };
130 let [nx, ny, nw, nh] = Self::compute_scissor(lx, by, rx, ty);
131
132 let [ix, iy, iw, ih] = if let Some([ex, ey, ew, eh]) = self.current_clip() {
134 let nx2 = nx.saturating_add(nw).min(ex.saturating_add(ew));
135 let ny2 = ny.saturating_add(nh).min(ey.saturating_add(eh));
136 let rx2 = nx.max(ex);
137 let ry2 = ny.max(ey);
138 [
139 rx2,
140 ry2,
141 nx2.saturating_sub(rx2).max(0),
142 ny2.saturating_sub(ry2).max(0),
143 ]
144 } else {
145 [nx, ny, nw, nh]
146 };
147
148 self.state_stack.last_mut().unwrap().1 = Some([ix, iy, iw, ih]);
149 }
150
151 fn reset_clip(&mut self) {
152 self.state_stack.last_mut().unwrap().1 = None;
153 }
154
155 fn clip_path(&mut self) {
156 self.clip_path_impl();
157 }
158
159 fn supports_clip_path(&self) -> bool {
160 true
161 }
162
163 fn clear(&mut self, color: Color) {
166 self.commands.push(DrawCommand::Clear(color));
167 }
168
169 fn begin_path(&mut self) {
172 self.path = PathStorage::new();
173 }
174
175 fn move_to(&mut self, x: f64, y: f64) {
176 self.path.move_to(x, y);
177 }
178
179 fn line_to(&mut self, x: f64, y: f64) {
180 self.path.line_to(x, y);
181 }
182
183 fn cubic_to(&mut self, cx1: f64, cy1: f64, cx2: f64, cy2: f64, x: f64, y: f64) {
184 self.path.curve4(cx1, cy1, cx2, cy2, x, y);
185 }
186
187 fn quad_to(&mut self, cx: f64, cy: f64, x: f64, y: f64) {
188 self.path.curve3(cx, cy, x, y);
189 }
190
191 fn arc_to(&mut self, cx: f64, cy: f64, r: f64, start_angle: f64, end_angle: f64, ccw: bool) {
192 let mut arc = AggArc::new(cx, cy, r, r, start_angle, end_angle, ccw);
193 self.path.concat_path(&mut arc, 0);
194 }
195
196 fn circle(&mut self, cx: f64, cy: f64, r: f64) {
197 self.arc_to(cx, cy, r, 0.0, std::f64::consts::TAU, true);
198 self.path.close_polygon(PATH_FLAGS_NONE);
199 }
200
201 fn rect(&mut self, x: f64, y: f64, w: f64, h: f64) {
202 self.path.move_to(x, y);
203 self.path.line_to(x + w, y);
204 self.path.line_to(x + w, y + h);
205 self.path.line_to(x, y + h);
206 self.path.close_polygon(PATH_FLAGS_NONE);
207 }
208
209 fn rounded_rect(&mut self, x: f64, y: f64, w: f64, h: f64, r: f64) {
210 let r = r.min(w * 0.5).min(h * 0.5).max(0.0);
211 let mut rr = RoundedRect::new(x, y, x + w, y + h, r);
212 rr.normalize_radius();
213 self.path.concat_path(&mut rr, 0);
214 }
215
216 fn close_path(&mut self) {
217 self.path.close_polygon(PATH_FLAGS_NONE);
218 }
219
220 fn fill(&mut self) {
223 self.do_fill();
224 }
225
226 fn stroke(&mut self) {
227 self.do_stroke();
228 }
229
230 fn fill_and_stroke(&mut self) {
231 self.do_fill();
233 self.do_stroke();
234 }
235
236 fn draw_triangles_aa(&mut self, vertices: &[[f32; 3]], indices: &[u32], color: Color) {
237 if vertices.is_empty() || indices.is_empty() {
238 return;
239 }
240 let ctm = *self.ctm();
242 let transformed: Vec<[f32; 3]> = vertices
243 .iter()
244 .map(|v| {
245 let (mut x, mut y) = (v[0] as f64, v[1] as f64);
246 ctm.transform(&mut x, &mut y);
247 [x as f32, y as f32, v[2]]
248 })
249 .collect();
250 self.commands.push(DrawCommand::AaSolid {
251 verts: transformed,
252 indices: indices.to_vec(),
253 color,
254 global_alpha: self.global_alpha as f32,
255 clip: self.current_clip(),
256 });
257 }
258
259 fn fill_text(&mut self, text: &str, x: f64, y: f64) {
262 self.fill_text_impl(text, x, y);
263 }
264
265 fn fill_text_gsv(&mut self, _text: &str, _x: f64, _y: f64, _size: f64) {
266 }
269
270 fn measure_text(&self, text: &str) -> Option<TextMetrics> {
271 let font = self.font.as_ref()?;
272 Some(measure_text_metrics(font, text, self.font_size))
273 }
274
275 fn has_image_blit(&self) -> bool {
278 true
279 }
280
281 fn draw_image_rgba(
282 &mut self,
283 data: &[u8],
284 img_w: u32,
285 img_h: u32,
286 dst_x: f64,
287 dst_y: f64,
288 dst_w: f64,
289 dst_h: f64,
290 ) {
291 self.draw_image_rgba_slice_impl(data, img_w, img_h, dst_x, dst_y, dst_w, dst_h);
292 }
293
294 fn draw_image_rgba_arc(
295 &mut self,
296 data: &std::sync::Arc<Vec<u8>>,
297 img_w: u32,
298 img_h: u32,
299 dst_x: f64,
300 dst_y: f64,
301 dst_w: f64,
302 dst_h: f64,
303 ) {
304 self.draw_image_rgba_arc_impl(data, img_w, img_h, dst_x, dst_y, dst_w, dst_h);
305 }
306
307 fn draw_image_rgba_corners(
308 &mut self,
309 data: &std::sync::Arc<Vec<u8>>,
310 img_w: u32,
311 img_h: u32,
312 corners: [(f64, f64); 4],
313 ) {
314 self.draw_image_rgba_corners_impl(data, img_w, img_h, corners);
315 }
316
317 fn has_lcd_mask_composite(&self) -> bool {
318 true
319 }
320
321 fn draw_lcd_mask(
322 &mut self,
323 mask: &[u8],
324 mask_w: u32,
325 mask_h: u32,
326 src_color: agg_gui::Color,
327 dst_x: f64,
328 dst_y: f64,
329 ) {
330 self.draw_lcd_mask_slice_impl(mask, mask_w, mask_h, src_color, dst_x, dst_y);
331 }
332
333 fn draw_lcd_mask_arc(
334 &mut self,
335 mask: &std::sync::Arc<Vec<u8>>,
336 mask_w: u32,
337 mask_h: u32,
338 src_color: agg_gui::Color,
339 dst_x: f64,
340 dst_y: f64,
341 ) {
342 self.draw_lcd_mask_arc_impl(mask, mask_w, mask_h, src_color, dst_x, dst_y);
343 }
344
345 fn draw_lcd_backbuffer_arc(
346 &mut self,
347 color: &std::sync::Arc<Vec<u8>>,
348 alpha: &std::sync::Arc<Vec<u8>>,
349 content_version: u64,
350 w: u32,
351 h: u32,
352 dst_x: f64,
353 dst_y: f64,
354 dst_w: f64,
355 dst_h: f64,
356 ) {
357 self.draw_lcd_backbuffer_arc_impl(
358 color,
359 alpha,
360 content_version,
361 w,
362 h,
363 dst_x,
364 dst_y,
365 dst_w,
366 dst_h,
367 );
368 }
369
370 fn transform(&self) -> TransAffine {
373 *self.ctm()
374 }
375
376 fn root_transform(&self) -> TransAffine {
377 let mut t = *self.ctm();
378 for layer in self.layer_stack.iter().rev() {
379 t.premultiply(&TransAffine::new_translation(
380 layer.origin_x,
381 layer.origin_y,
382 ));
383 }
384 t
385 }
386
387 fn save(&mut self) {
388 let top = *self.state_stack.last().unwrap();
389 self.state_stack.push(top);
390 }
391
392 fn restore(&mut self) {
393 while self.state_stack.len() == 1
397 && self
398 .layer_stack
399 .last()
400 .is_some_and(|l| l.clip_mask.is_some())
401 {
402 self.pop_layer_impl();
403 }
404 if self.state_stack.len() > 1 {
405 self.state_stack.pop();
406 self.apply_scissor();
408 }
409 }
410
411 fn translate(&mut self, tx: f64, ty: f64) {
412 self.ctm_mut()
413 .premultiply(&TransAffine::new_translation(tx, ty));
414 }
415
416 fn rotate(&mut self, radians: f64) {
417 self.ctm_mut()
418 .premultiply(&TransAffine::new_rotation(radians));
419 }
420
421 fn scale(&mut self, sx: f64, sy: f64) {
422 self.ctm_mut()
423 .premultiply(&TransAffine::new_scaling(sx, sy));
424 }
425
426 fn set_transform(&mut self, m: TransAffine) {
427 *self.ctm_mut() = m;
428 }
429
430 fn reset_transform(&mut self) {
431 *self.ctm_mut() = TransAffine::new();
432 }
433
434 fn supports_compositing_layers(&self) -> bool {
437 true
438 }
439
440 fn supports_retained_layers(&self) -> bool {
441 true
442 }
443
444 fn push_layer(&mut self, width: f64, height: f64) {
445 self.push_layer_with_alpha_impl(width, height, 1.0, None);
446 }
447
448 fn push_layer_with_alpha(&mut self, width: f64, height: f64, alpha: f64) {
449 self.push_layer_with_alpha_impl(width, height, alpha, None);
450 }
451
452 fn pop_layer(&mut self) {
453 self.pop_layer_impl();
454 }
455
456 fn set_layer_rounded_clip(&mut self, x: f64, y: f64, w: f64, h: f64, r: f64) {
457 self.set_layer_rounded_clip_impl(x, y, w, h, r);
458 }
459
460 fn set_layer_opaque_backdrop(&mut self, opaque: bool) {
461 self.set_layer_opaque_backdrop_impl(opaque);
462 }
463
464 fn composite_retained_layer(&mut self, key: u64, width: f64, height: f64, alpha: f64) -> bool {
465 self.composite_retained_layer_impl(key, width, height, alpha)
466 }
467
468 fn push_retained_layer_with_alpha(&mut self, key: u64, width: f64, height: f64, alpha: f64) {
469 self.push_layer_with_alpha_impl(width, height, alpha, Some(key));
470 }
471
472 fn gl_paint(&mut self, _screen_rect: agg_gui::Rect, _painter: &mut dyn agg_gui::GlPaint) {
475 }
494
495 fn capture_screenshot(&mut self) -> bool {
498 self.capture_screenshot_impl()
499 }
500
501 fn has_captured_screenshot(&self) -> bool {
502 self.capture_texture.is_some()
503 }
504
505 fn captured_screenshot_size(&self) -> Option<(u32, u32)> {
506 self.capture_texture.as_ref().map(|(_, _, w, h)| (*w, *h))
507 }
508
509 fn draw_captured_screenshot(&mut self, dst_x: f64, dst_y: f64, dst_w: f64, dst_h: f64) -> bool {
510 self.draw_captured_screenshot_impl(dst_x, dst_y, dst_w, dst_h)
511 }
512
513 fn read_captured_screenshot(&mut self) -> (Vec<u8>, u32, u32) {
514 self.read_captured_screenshot_impl()
515 }
516}