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