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