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, Transformation, Vector,
8};
9
10/// Whether anti-aliasing should be avoided by snapping primitive coordinates to the
11/// pixel grid.
12pub const CRISP: bool = cfg!(feature = "crisp");
13
14/// A component that can be used by widgets to draw themselves on a screen.
15pub trait Renderer {
16 /// Starts recording a new layer.
17 fn start_layer(&mut self, bounds: Rectangle);
18
19 /// Ends recording a new layer.
20 ///
21 /// The new layer will clip its contents to the provided `bounds`.
22 fn end_layer(&mut self);
23
24 /// Draws the primitives recorded in the given closure in a new layer.
25 ///
26 /// The layer will clip its contents to the provided `bounds`.
27 fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
28 self.start_layer(bounds);
29 f(self);
30 self.end_layer();
31 }
32
33 /// Starts recording with a new [`Transformation`].
34 fn start_transformation(&mut self, transformation: Transformation);
35
36 /// Ends recording a new layer.
37 ///
38 /// The new layer will clip its contents to the provided `bounds`.
39 fn end_transformation(&mut self);
40
41 /// Applies a [`Transformation`] to the primitives recorded in the given closure.
42 fn with_transformation(&mut self, transformation: Transformation, f: impl FnOnce(&mut Self)) {
43 self.start_transformation(transformation);
44 f(self);
45 self.end_transformation();
46 }
47
48 /// Applies a translation to the primitives recorded in the given closure.
49 fn with_translation(&mut self, translation: Vector, f: impl FnOnce(&mut Self)) {
50 self.with_transformation(Transformation::translate(translation.x, translation.y), f);
51 }
52
53 /// Fills a [`Quad`] with the provided [`Background`].
54 fn fill_quad(&mut self, quad: Quad, background: impl Into<Background>);
55
56 /// Creates an [`image::Allocation`] for the given [`image::Handle`] and calls the given callback with it.
57 fn allocate_image(
58 &mut self,
59 handle: &image::Handle,
60 callback: impl FnOnce(Result<image::Allocation, image::Error>) + Send + 'static,
61 );
62
63 /// Provides hints to the [`Renderer`] about the rendering target.
64 ///
65 /// This may be used internally by the [`Renderer`] to perform optimizations
66 /// and/or improve rendering quality.
67 ///
68 /// For instance, providing a [`Scale`] may be used by some renderers to
69 /// perform metrics hinting internally in physical coordinates while keeping
70 /// layout coordinates logical and, therefore, maintain linearity.
71 fn hint(&mut self, scale: Scale);
72
73 /// Returns the last [`Scale`] provided as a [`hint`](Self::hint).
74 fn scale(&self) -> Option<Scale>;
75
76 /// Returns the last hint factor provided as a [`hint`](Self::hint),
77 /// only if [`Settings::metrics_hinting`] is enabled.
78 fn hint_factor(&self) -> Option<f32> {
79 if !self.settings().metrics_hinting {
80 return None;
81 }
82
83 self.scale().map(Scale::total)
84 }
85
86 /// Resets the [`Renderer`] to start drawing in the `new_bounds` from scratch.
87 fn reset(&mut self, new_bounds: Rectangle);
88
89 /// Returns the [`Settings`] of this [`Renderer`].
90 fn settings(&self) -> Settings;
91
92 /// Polls any concurrent computations that may be pending in the [`Renderer`].
93 ///
94 /// By default, it does nothing.
95 fn tick(&mut self) {}
96}
97
98/// A polygon with four sides.
99#[derive(Debug, Clone, Copy, PartialEq)]
100pub struct Quad {
101 /// The bounds of the [`Quad`].
102 pub bounds: Rectangle,
103
104 /// The [`Border`] of the [`Quad`]. The border is drawn on the inside of the [`Quad`].
105 pub border: Border,
106
107 /// The [`Shadow`] of the [`Quad`].
108 pub shadow: Shadow,
109
110 /// Whether the [`Quad`] should be snapped to the pixel grid.
111 pub snap: bool,
112}
113
114impl Default for Quad {
115 fn default() -> Self {
116 Self {
117 bounds: Rectangle::with_size(Size::ZERO),
118 border: Border::default(),
119 shadow: Shadow::default(),
120 snap: CRISP,
121 }
122 }
123}
124
125/// The styling attributes of a [`Renderer`].
126#[derive(Debug, Clone, Copy, PartialEq)]
127pub struct Style {
128 /// The text color
129 pub text_color: Color,
130}
131
132impl Default for Style {
133 fn default() -> Self {
134 Style {
135 text_color: Color::BLACK,
136 }
137 }
138}
139
140/// A headless renderer is a renderer that can render offscreen without
141/// a window nor a compositor.
142pub trait Headless {
143 /// Creates a new [`Headless`] renderer;
144 fn new(settings: Settings, backend: Option<&str>) -> impl Future<Output = Option<Self>>
145 where
146 Self: Sized;
147
148 /// Returns the unique name of the renderer.
149 ///
150 /// This name may be used by testing libraries to uniquely identify
151 /// snapshots.
152 fn name(&self) -> String;
153
154 /// Draws offscreen into a screenshot, returning a collection of
155 /// bytes representing the rendered pixels in RGBA order.
156 fn screenshot(
157 &mut self,
158 size: Size<u32>,
159 scale_factor: f32,
160 background_color: Color,
161 ) -> Vec<u8>;
162}
163
164/// The settings of a [`Renderer`].
165#[derive(Debug, Clone, Copy, PartialEq)]
166pub struct Settings {
167 /// The default [`Font`] to use.
168 pub default_font: Font,
169
170 /// The default size of text.
171 ///
172 /// By default, it will be set to `16.0`.
173 pub default_text_size: Pixels,
174
175 /// Whether the [`Renderer`] should perform metrics hinting.
176 ///
177 /// By default, it is enabled.
178 pub metrics_hinting: bool,
179}
180
181impl Default for Settings {
182 fn default() -> Self {
183 Self {
184 default_font: Font::DEFAULT,
185 default_text_size: Pixels(16.0),
186 metrics_hinting: true,
187 }
188 }
189}
190
191/// The scale factor of a [`Renderer`].
192#[derive(Debug, Clone, Copy, PartialEq)]
193pub struct Scale {
194 /// The global scale factor of the window.
195 ///
196 /// This is normally controlled by the OS, and applied globally to all apps.
197 pub window: f32,
198
199 /// The local scale factor of the application.
200 pub application: f32,
201}
202
203impl Scale {
204 /// Returns the total scale factor applied by the [`Renderer`].
205 ///
206 /// This is the product of the window and application scale factors.
207 pub fn total(self) -> f32 {
208 self.window * self.application
209 }
210}
211
212impl Default for Scale {
213 fn default() -> Self {
214 Self {
215 window: 1.0,
216 application: 1.0,
217 }
218 }
219}