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