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