iced_core/renderer.rs
1//! Write your own renderer.
2#[cfg(debug_assertions)]
3mod null;
4
5use crate::image;
6use crate::{
7 Background, Border, Color, Font, Pixels, Rectangle, Shadow, Size,
8 Transformation, Vector,
9};
10
11/// A component that can be used by widgets to draw themselves on a screen.
12pub trait Renderer {
13 /// Starts recording a new layer.
14 fn start_layer(&mut self, bounds: Rectangle);
15
16 /// Ends recording a new layer.
17 ///
18 /// The new layer will clip its contents to the provided `bounds`.
19 fn end_layer(&mut self);
20
21 /// Draws the primitives recorded in the given closure in a new layer.
22 ///
23 /// The layer will clip its contents to the provided `bounds`.
24 fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
25 self.start_layer(bounds);
26 f(self);
27 self.end_layer();
28 }
29
30 /// Starts recording with a new [`Transformation`].
31 fn start_transformation(&mut self, transformation: Transformation);
32
33 /// Ends recording a new layer.
34 ///
35 /// The new layer will clip its contents to the provided `bounds`.
36 fn end_transformation(&mut self);
37
38 /// Applies a [`Transformation`] to the primitives recorded in the given closure.
39 fn with_transformation(
40 &mut self,
41 transformation: Transformation,
42 f: impl FnOnce(&mut Self),
43 ) {
44 self.start_transformation(transformation);
45 f(self);
46 self.end_transformation();
47 }
48
49 /// Applies a translation to the primitives recorded in the given closure.
50 fn with_translation(
51 &mut self,
52 translation: Vector,
53 f: impl FnOnce(&mut Self),
54 ) {
55 self.with_transformation(
56 Transformation::translate(translation.x, translation.y),
57 f,
58 );
59 }
60
61 /// Fills a [`Quad`] with the provided [`Background`].
62 fn fill_quad(&mut self, quad: Quad, background: impl Into<Background>);
63
64 /// Resets the [`Renderer`] to start drawing in the `new_bounds` from scratch.
65 fn reset(&mut self, new_bounds: Rectangle);
66
67 /// Creates an [`image::Allocation`] for the given [`image::Handle`] and calls the given callback with it.
68 fn allocate_image(
69 &mut self,
70 handle: &image::Handle,
71 callback: impl FnOnce(Result<image::Allocation, image::Error>)
72 + Send
73 + 'static,
74 );
75}
76
77/// A polygon with four sides.
78#[derive(Debug, Clone, Copy, PartialEq)]
79pub struct Quad {
80 /// The bounds of the [`Quad`].
81 pub bounds: Rectangle,
82
83 /// The [`Border`] of the [`Quad`]. The border is drawn on the inside of the [`Quad`].
84 pub border: Border,
85
86 /// The [`Shadow`] of the [`Quad`].
87 pub shadow: Shadow,
88
89 /// Whether the [`Quad`] should be snapped to the pixel grid.
90 pub snap: bool,
91}
92
93impl Default for Quad {
94 fn default() -> Self {
95 Self {
96 bounds: Rectangle::with_size(Size::ZERO),
97 border: Border::default(),
98 shadow: Shadow::default(),
99 snap: cfg!(feature = "crisp"),
100 }
101 }
102}
103
104/// The styling attributes of a [`Renderer`].
105#[derive(Debug, Clone, Copy, PartialEq)]
106pub struct Style {
107 /// The text color
108 pub text_color: Color,
109}
110
111impl Default for Style {
112 fn default() -> Self {
113 Style {
114 text_color: Color::BLACK,
115 }
116 }
117}
118
119/// A headless renderer is a renderer that can render offscreen without
120/// a window nor a compositor.
121pub trait Headless {
122 /// Creates a new [`Headless`] renderer;
123 fn new(
124 default_font: Font,
125 default_text_size: Pixels,
126 backend: Option<&str>,
127 ) -> impl Future<Output = Option<Self>>
128 where
129 Self: Sized;
130
131 /// Returns the unique name of the renderer.
132 ///
133 /// This name may be used by testing libraries to uniquely identify
134 /// snapshots.
135 fn name(&self) -> String;
136
137 /// Draws offscreen into a screenshot, returning a collection of
138 /// bytes representing the rendered pixels in RGBA order.
139 fn screenshot(
140 &mut self,
141 size: Size<u32>,
142 scale_factor: f32,
143 background_color: Color,
144 ) -> Vec<u8>;
145}