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_factor` 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_factor: f32);
72
73 /// Returns the last scale factor provided as a [`hint`](Self::hint).
74 fn scale_factor(&self) -> Option<f32>;
75
76 /// Resets the [`Renderer`] to start drawing in the `new_bounds` from scratch.
77 fn reset(&mut self, new_bounds: Rectangle);
78
79 /// Polls any concurrent computations that may be pending in the [`Renderer`].
80 ///
81 /// By default, it does nothing.
82 fn tick(&mut self) {}
83}
84
85/// A polygon with four sides.
86#[derive(Debug, Clone, Copy, PartialEq)]
87pub struct Quad {
88 /// The bounds of the [`Quad`].
89 pub bounds: Rectangle,
90
91 /// The [`Border`] of the [`Quad`]. The border is drawn on the inside of the [`Quad`].
92 pub border: Border,
93
94 /// The [`Shadow`] of the [`Quad`].
95 pub shadow: Shadow,
96
97 /// Whether the [`Quad`] should be snapped to the pixel grid.
98 pub snap: bool,
99}
100
101impl Default for Quad {
102 fn default() -> Self {
103 Self {
104 bounds: Rectangle::with_size(Size::ZERO),
105 border: Border::default(),
106 shadow: Shadow::default(),
107 snap: CRISP,
108 }
109 }
110}
111
112/// The styling attributes of a [`Renderer`].
113#[derive(Debug, Clone, Copy, PartialEq)]
114pub struct Style {
115 /// The text color
116 pub text_color: Color,
117}
118
119impl Default for Style {
120 fn default() -> Self {
121 Style {
122 text_color: Color::BLACK,
123 }
124 }
125}
126
127/// A headless renderer is a renderer that can render offscreen without
128/// a window nor a compositor.
129pub trait Headless {
130 /// Creates a new [`Headless`] renderer;
131 fn new(
132 default_font: Font,
133 default_text_size: Pixels,
134 backend: Option<&str>,
135 ) -> impl Future<Output = Option<Self>>
136 where
137 Self: Sized;
138
139 /// Returns the unique name of the renderer.
140 ///
141 /// This name may be used by testing libraries to uniquely identify
142 /// snapshots.
143 fn name(&self) -> String;
144
145 /// Draws offscreen into a screenshot, returning a collection of
146 /// bytes representing the rendered pixels in RGBA order.
147 fn screenshot(
148 &mut self,
149 size: Size<u32>,
150 scale_factor: f32,
151 background_color: Color,
152 ) -> Vec<u8>;
153}