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