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