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