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