1use crate::core::image;
3use crate::core::renderer;
4use crate::core::svg;
5use crate::core::{
6 self, Background, Color, Image, Point, Rectangle, Size, Svg, Transformation,
7};
8use crate::graphics;
9use crate::graphics::compositor;
10use crate::graphics::mesh;
11
12use std::borrow::Cow;
13
14#[derive(Debug)]
19pub enum Renderer<A, B> {
20 Primary(A),
22 Secondary(B),
24}
25
26macro_rules! delegate {
27 ($renderer:expr, $name:ident, $body:expr) => {
28 match $renderer {
29 Self::Primary($name) => $body,
30 Self::Secondary($name) => $body,
31 }
32 };
33}
34
35impl<A, B> core::Renderer for Renderer<A, B>
36where
37 A: core::Renderer,
38 B: core::Renderer,
39{
40 fn fill_quad(
41 &mut self,
42 quad: renderer::Quad,
43 background: impl Into<Background>,
44 ) {
45 delegate!(self, renderer, renderer.fill_quad(quad, background.into()));
46 }
47
48 fn clear(&mut self) {
49 delegate!(self, renderer, renderer.clear());
50 }
51
52 fn start_layer(&mut self, bounds: Rectangle) {
53 delegate!(self, renderer, renderer.start_layer(bounds));
54 }
55
56 fn end_layer(&mut self) {
57 delegate!(self, renderer, renderer.end_layer());
58 }
59
60 fn start_transformation(&mut self, transformation: Transformation) {
61 delegate!(
62 self,
63 renderer,
64 renderer.start_transformation(transformation)
65 );
66 }
67
68 fn end_transformation(&mut self) {
69 delegate!(self, renderer, renderer.end_transformation());
70 }
71}
72
73impl<A, B> core::text::Renderer for Renderer<A, B>
74where
75 A: core::text::Renderer,
76 B: core::text::Renderer<
77 Font = A::Font,
78 Paragraph = A::Paragraph,
79 Editor = A::Editor,
80 >,
81{
82 type Font = A::Font;
83 type Paragraph = A::Paragraph;
84 type Editor = A::Editor;
85
86 const ICON_FONT: Self::Font = A::ICON_FONT;
87 const CHECKMARK_ICON: char = A::CHECKMARK_ICON;
88 const ARROW_DOWN_ICON: char = A::ARROW_DOWN_ICON;
89
90 fn default_font(&self) -> Self::Font {
91 delegate!(self, renderer, renderer.default_font())
92 }
93
94 fn default_size(&self) -> core::Pixels {
95 delegate!(self, renderer, renderer.default_size())
96 }
97
98 fn fill_paragraph(
99 &mut self,
100 text: &Self::Paragraph,
101 position: Point,
102 color: Color,
103 clip_bounds: Rectangle,
104 ) {
105 delegate!(
106 self,
107 renderer,
108 renderer.fill_paragraph(text, position, color, clip_bounds)
109 );
110 }
111
112 fn fill_editor(
113 &mut self,
114 editor: &Self::Editor,
115 position: Point,
116 color: Color,
117 clip_bounds: Rectangle,
118 ) {
119 delegate!(
120 self,
121 renderer,
122 renderer.fill_editor(editor, position, color, clip_bounds)
123 );
124 }
125
126 fn fill_text(
127 &mut self,
128 text: core::Text<String, Self::Font>,
129 position: Point,
130 color: Color,
131 clip_bounds: Rectangle,
132 ) {
133 delegate!(
134 self,
135 renderer,
136 renderer.fill_text(text, position, color, clip_bounds)
137 );
138 }
139}
140
141impl<A, B> image::Renderer for Renderer<A, B>
142where
143 A: image::Renderer,
144 B: image::Renderer<Handle = A::Handle>,
145{
146 type Handle = A::Handle;
147
148 fn measure_image(&self, handle: &Self::Handle) -> Size<u32> {
149 delegate!(self, renderer, renderer.measure_image(handle))
150 }
151
152 fn draw_image(&mut self, image: Image<A::Handle>, bounds: Rectangle) {
153 delegate!(self, renderer, renderer.draw_image(image, bounds));
154 }
155}
156
157impl<A, B> svg::Renderer for Renderer<A, B>
158where
159 A: svg::Renderer,
160 B: svg::Renderer,
161{
162 fn measure_svg(&self, handle: &svg::Handle) -> Size<u32> {
163 delegate!(self, renderer, renderer.measure_svg(handle))
164 }
165
166 fn draw_svg(&mut self, svg: Svg, bounds: Rectangle) {
167 delegate!(self, renderer, renderer.draw_svg(svg, bounds));
168 }
169}
170
171impl<A, B> mesh::Renderer for Renderer<A, B>
172where
173 A: mesh::Renderer,
174 B: mesh::Renderer,
175{
176 fn draw_mesh(&mut self, mesh: graphics::Mesh) {
177 delegate!(self, renderer, renderer.draw_mesh(mesh));
178 }
179}
180
181#[derive(Debug)]
185pub enum Compositor<A, B>
186where
187 A: graphics::Compositor,
188 B: graphics::Compositor,
189{
190 Primary(A),
192 Secondary(B),
194}
195
196#[derive(Debug)]
200pub enum Surface<A, B> {
201 Primary(A),
203 Secondary(B),
205}
206
207impl<A, B> graphics::Compositor for Compositor<A, B>
208where
209 A: graphics::Compositor,
210 B: graphics::Compositor,
211{
212 type Renderer = Renderer<A::Renderer, B::Renderer>;
213 type Surface = Surface<A::Surface, B::Surface>;
214
215 async fn with_backend<W: compositor::Window + Clone>(
216 settings: graphics::Settings,
217 compatible_window: W,
218 backend: Option<&str>,
219 ) -> Result<Self, graphics::Error> {
220 use std::env;
221
222 let backends = backend
223 .map(str::to_owned)
224 .or_else(|| env::var("ICED_BACKEND").ok());
225
226 let mut candidates: Vec<_> = backends
227 .map(|backends| {
228 backends
229 .split(',')
230 .filter(|candidate| !candidate.is_empty())
231 .map(str::to_owned)
232 .map(Some)
233 .collect()
234 })
235 .unwrap_or_default();
236
237 if candidates.is_empty() {
238 candidates.push(None);
239 }
240
241 let mut errors = vec![];
242
243 for backend in candidates.iter().map(Option::as_deref) {
244 match A::with_backend(settings, compatible_window.clone(), backend)
245 .await
246 {
247 Ok(compositor) => return Ok(Self::Primary(compositor)),
248 Err(error) => {
249 errors.push(error);
250 }
251 }
252
253 match B::with_backend(settings, compatible_window.clone(), backend)
254 .await
255 {
256 Ok(compositor) => return Ok(Self::Secondary(compositor)),
257 Err(error) => {
258 errors.push(error);
259 }
260 }
261 }
262
263 Err(graphics::Error::List(errors))
264 }
265
266 fn create_renderer(&self) -> Self::Renderer {
267 match self {
268 Self::Primary(compositor) => {
269 Renderer::Primary(compositor.create_renderer())
270 }
271 Self::Secondary(compositor) => {
272 Renderer::Secondary(compositor.create_renderer())
273 }
274 }
275 }
276
277 fn create_surface<W: compositor::Window + Clone>(
278 &mut self,
279 window: W,
280 width: u32,
281 height: u32,
282 ) -> Self::Surface {
283 match self {
284 Self::Primary(compositor) => Surface::Primary(
285 compositor.create_surface(window, width, height),
286 ),
287 Self::Secondary(compositor) => Surface::Secondary(
288 compositor.create_surface(window, width, height),
289 ),
290 }
291 }
292
293 fn configure_surface(
294 &mut self,
295 surface: &mut Self::Surface,
296 width: u32,
297 height: u32,
298 ) {
299 match (self, surface) {
300 (Self::Primary(compositor), Surface::Primary(surface)) => {
301 compositor.configure_surface(surface, width, height);
302 }
303 (Self::Secondary(compositor), Surface::Secondary(surface)) => {
304 compositor.configure_surface(surface, width, height);
305 }
306 _ => unreachable!(),
307 }
308 }
309
310 fn load_font(&mut self, font: Cow<'static, [u8]>) {
311 delegate!(self, compositor, compositor.load_font(font));
312 }
313
314 fn fetch_information(&self) -> compositor::Information {
315 delegate!(self, compositor, compositor.fetch_information())
316 }
317
318 fn present<T: AsRef<str>>(
319 &mut self,
320 renderer: &mut Self::Renderer,
321 surface: &mut Self::Surface,
322 viewport: &graphics::Viewport,
323 background_color: Color,
324 overlay: &[T],
325 ) -> Result<(), compositor::SurfaceError> {
326 match (self, renderer, surface) {
327 (
328 Self::Primary(compositor),
329 Renderer::Primary(renderer),
330 Surface::Primary(surface),
331 ) => compositor.present(
332 renderer,
333 surface,
334 viewport,
335 background_color,
336 overlay,
337 ),
338 (
339 Self::Secondary(compositor),
340 Renderer::Secondary(renderer),
341 Surface::Secondary(surface),
342 ) => compositor.present(
343 renderer,
344 surface,
345 viewport,
346 background_color,
347 overlay,
348 ),
349 _ => unreachable!(),
350 }
351 }
352
353 fn screenshot<T: AsRef<str>>(
354 &mut self,
355 renderer: &mut Self::Renderer,
356 viewport: &graphics::Viewport,
357 background_color: Color,
358 overlay: &[T],
359 ) -> Vec<u8> {
360 match (self, renderer) {
361 (Self::Primary(compositor), Renderer::Primary(renderer)) => {
362 compositor.screenshot(
363 renderer,
364 viewport,
365 background_color,
366 overlay,
367 )
368 }
369 (Self::Secondary(compositor), Renderer::Secondary(renderer)) => {
370 compositor.screenshot(
371 renderer,
372 viewport,
373 background_color,
374 overlay,
375 )
376 }
377 _ => unreachable!(),
378 }
379 }
380}
381
382#[cfg(feature = "wgpu")]
383impl<A, B> iced_wgpu::primitive::Renderer for Renderer<A, B>
384where
385 A: iced_wgpu::primitive::Renderer,
386 B: core::Renderer,
387{
388 fn draw_primitive(
389 &mut self,
390 bounds: Rectangle,
391 primitive: impl iced_wgpu::Primitive,
392 ) {
393 match self {
394 Self::Primary(renderer) => {
395 renderer.draw_primitive(bounds, primitive);
396 }
397 Self::Secondary(_) => {
398 log::warn!(
399 "Custom shader primitive is not supported with this renderer."
400 );
401 }
402 }
403 }
404}
405
406#[cfg(feature = "geometry")]
407mod geometry {
408 use super::Renderer;
409 use crate::core::{Point, Radians, Rectangle, Size, Svg, Vector};
410 use crate::graphics::cache::{self, Cached};
411 use crate::graphics::geometry::{self, Fill, Image, Path, Stroke, Text};
412
413 impl<A, B> geometry::Renderer for Renderer<A, B>
414 where
415 A: geometry::Renderer,
416 B: geometry::Renderer,
417 {
418 type Geometry = Geometry<A::Geometry, B::Geometry>;
419 type Frame = Frame<A::Frame, B::Frame>;
420
421 fn new_frame(&self, size: iced_graphics::core::Size) -> Self::Frame {
422 match self {
423 Self::Primary(renderer) => {
424 Frame::Primary(renderer.new_frame(size))
425 }
426 Self::Secondary(renderer) => {
427 Frame::Secondary(renderer.new_frame(size))
428 }
429 }
430 }
431
432 fn draw_geometry(&mut self, geometry: Self::Geometry) {
433 match (self, geometry) {
434 (Self::Primary(renderer), Geometry::Primary(geometry)) => {
435 renderer.draw_geometry(geometry);
436 }
437 (Self::Secondary(renderer), Geometry::Secondary(geometry)) => {
438 renderer.draw_geometry(geometry);
439 }
440 _ => unreachable!(),
441 }
442 }
443 }
444
445 #[derive(Debug, Clone)]
446 pub enum Geometry<A, B> {
447 Primary(A),
448 Secondary(B),
449 }
450
451 impl<A, B> Cached for Geometry<A, B>
452 where
453 A: Cached,
454 B: Cached,
455 {
456 type Cache = Geometry<A::Cache, B::Cache>;
457
458 fn load(cache: &Self::Cache) -> Self {
459 match cache {
460 Geometry::Primary(cache) => Self::Primary(A::load(cache)),
461 Geometry::Secondary(cache) => Self::Secondary(B::load(cache)),
462 }
463 }
464
465 fn cache(
466 self,
467 group: cache::Group,
468 previous: Option<Self::Cache>,
469 ) -> Self::Cache {
470 match (self, previous) {
471 (
472 Self::Primary(geometry),
473 Some(Geometry::Primary(previous)),
474 ) => Geometry::Primary(geometry.cache(group, Some(previous))),
475 (Self::Primary(geometry), None) => {
476 Geometry::Primary(geometry.cache(group, None))
477 }
478 (
479 Self::Secondary(geometry),
480 Some(Geometry::Secondary(previous)),
481 ) => Geometry::Secondary(geometry.cache(group, Some(previous))),
482 (Self::Secondary(geometry), None) => {
483 Geometry::Secondary(geometry.cache(group, None))
484 }
485 _ => unreachable!(),
486 }
487 }
488 }
489
490 #[derive(Debug)]
491 pub enum Frame<A, B> {
492 Primary(A),
493 Secondary(B),
494 }
495
496 impl<A, B> geometry::frame::Backend for Frame<A, B>
497 where
498 A: geometry::frame::Backend,
499 B: geometry::frame::Backend,
500 {
501 type Geometry = Geometry<A::Geometry, B::Geometry>;
502
503 fn width(&self) -> f32 {
504 delegate!(self, frame, frame.width())
505 }
506
507 fn height(&self) -> f32 {
508 delegate!(self, frame, frame.height())
509 }
510
511 fn size(&self) -> Size {
512 delegate!(self, frame, frame.size())
513 }
514
515 fn center(&self) -> Point {
516 delegate!(self, frame, frame.center())
517 }
518
519 fn fill(&mut self, path: &Path, fill: impl Into<Fill>) {
520 delegate!(self, frame, frame.fill(path, fill));
521 }
522
523 fn fill_rectangle(
524 &mut self,
525 top_left: Point,
526 size: Size,
527 fill: impl Into<Fill>,
528 ) {
529 delegate!(self, frame, frame.fill_rectangle(top_left, size, fill));
530 }
531
532 fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {
533 delegate!(self, frame, frame.stroke(path, stroke));
534 }
535
536 fn stroke_rectangle<'a>(
537 &mut self,
538 top_left: Point,
539 size: Size,
540 stroke: impl Into<Stroke<'a>>,
541 ) {
542 delegate!(
543 self,
544 frame,
545 frame.stroke_rectangle(top_left, size, stroke)
546 );
547 }
548
549 fn fill_text(&mut self, text: impl Into<Text>) {
550 delegate!(self, frame, frame.fill_text(text));
551 }
552
553 fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
554 delegate!(self, frame, frame.draw_image(bounds, image));
555 }
556
557 fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>) {
558 delegate!(self, frame, frame.draw_svg(bounds, svg));
559 }
560
561 fn push_transform(&mut self) {
562 delegate!(self, frame, frame.push_transform());
563 }
564
565 fn pop_transform(&mut self) {
566 delegate!(self, frame, frame.pop_transform());
567 }
568
569 fn draft(&mut self, bounds: Rectangle) -> Self {
570 match self {
571 Self::Primary(frame) => Self::Primary(frame.draft(bounds)),
572 Self::Secondary(frame) => Self::Secondary(frame.draft(bounds)),
573 }
574 }
575
576 fn paste(&mut self, frame: Self) {
577 match (self, frame) {
578 (Self::Primary(target), Self::Primary(source)) => {
579 target.paste(source);
580 }
581 (Self::Secondary(target), Self::Secondary(source)) => {
582 target.paste(source);
583 }
584 _ => unreachable!(),
585 }
586 }
587
588 fn translate(&mut self, translation: Vector) {
589 delegate!(self, frame, frame.translate(translation));
590 }
591
592 fn rotate(&mut self, angle: impl Into<Radians>) {
593 delegate!(self, frame, frame.rotate(angle));
594 }
595
596 fn scale(&mut self, scale: impl Into<f32>) {
597 delegate!(self, frame, frame.scale(scale));
598 }
599
600 fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
601 delegate!(self, frame, frame.scale_nonuniform(scale));
602 }
603
604 fn into_geometry(self) -> Self::Geometry {
605 match self {
606 Frame::Primary(frame) => {
607 Geometry::Primary(frame.into_geometry())
608 }
609 Frame::Secondary(frame) => {
610 Geometry::Secondary(frame.into_geometry())
611 }
612 }
613 }
614 }
615}
616
617impl<A, B> compositor::Default for Renderer<A, B>
618where
619 A: compositor::Default,
620 B: compositor::Default,
621{
622 type Compositor = Compositor<A::Compositor, B::Compositor>;
623}