iced_graphics/geometry/
frame.rs

1//! Draw and generate geometry.
2use crate::core::{Point, Radians, Rectangle, Size, Vector};
3use crate::geometry::{self, Fill, Image, Path, Stroke, Svg, Text};
4
5/// The region of a surface that can be used to draw geometry.
6#[allow(missing_debug_implementations)]
7pub struct Frame<Renderer>
8where
9    Renderer: geometry::Renderer,
10{
11    raw: Renderer::Frame,
12}
13
14impl<Renderer> Frame<Renderer>
15where
16    Renderer: geometry::Renderer,
17{
18    /// Creates a new [`Frame`] with the given dimensions.
19    pub fn new(renderer: &Renderer, size: Size) -> Self {
20        Self {
21            raw: renderer.new_frame(size),
22        }
23    }
24
25    /// Returns the width of the [`Frame`].
26    pub fn width(&self) -> f32 {
27        self.raw.width()
28    }
29
30    /// Returns the height of the [`Frame`].
31    pub fn height(&self) -> f32 {
32        self.raw.height()
33    }
34
35    /// Returns the dimensions of the [`Frame`].
36    pub fn size(&self) -> Size {
37        self.raw.size()
38    }
39
40    /// Returns the coordinate of the center of the [`Frame`].
41    pub fn center(&self) -> Point {
42        self.raw.center()
43    }
44
45    /// Draws the given [`Path`] on the [`Frame`] by filling it with the
46    /// provided style.
47    pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) {
48        self.raw.fill(path, fill);
49    }
50
51    /// Draws an axis-aligned rectangle given its top-left corner coordinate and
52    /// its `Size` on the [`Frame`] by filling it with the provided style.
53    pub fn fill_rectangle(
54        &mut self,
55        top_left: Point,
56        size: Size,
57        fill: impl Into<Fill>,
58    ) {
59        self.raw.fill_rectangle(top_left, size, fill);
60    }
61
62    /// Draws the stroke of the given [`Path`] on the [`Frame`] with the
63    /// provided style.
64    pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {
65        self.raw.stroke(path, stroke);
66    }
67
68    /// Draws the stroke of an axis-aligned rectangle with the provided style
69    /// given its top-left corner coordinate and its `Size` on the [`Frame`] .
70    pub fn stroke_rectangle<'a>(
71        &mut self,
72        top_left: Point,
73        size: Size,
74        stroke: impl Into<Stroke<'a>>,
75    ) {
76        self.raw.stroke_rectangle(top_left, size, stroke);
77    }
78
79    /// Draws the characters of the given [`Text`] on the [`Frame`], filling
80    /// them with the given color.
81    ///
82    /// __Warning:__ All text will be rendered on top of all the layers of
83    /// a `Canvas`. Therefore, it is currently only meant to be used for
84    /// overlays, which is the most common use case.
85    pub fn fill_text(&mut self, text: impl Into<Text>) {
86        self.raw.fill_text(text);
87    }
88
89    /// Draws the given [`Image`] on the [`Frame`] inside the given bounds.
90    #[cfg(feature = "image")]
91    pub fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
92        self.raw.draw_image(bounds, image);
93    }
94
95    /// Draws the given [`Svg`] on the [`Frame`] inside the given bounds.
96    #[cfg(feature = "svg")]
97    pub fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>) {
98        self.raw.draw_svg(bounds, svg);
99    }
100
101    /// Stores the current transform of the [`Frame`] and executes the given
102    /// drawing operations, restoring the transform afterwards.
103    ///
104    /// This method is useful to compose transforms and perform drawing
105    /// operations in different coordinate systems.
106    #[inline]
107    pub fn with_save<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
108        self.push_transform();
109
110        let result = f(self);
111
112        self.pop_transform();
113
114        result
115    }
116
117    /// Pushes the current transform in the transform stack.
118    pub fn push_transform(&mut self) {
119        self.raw.push_transform();
120    }
121
122    /// Pops a transform from the transform stack and sets it as the current transform.
123    pub fn pop_transform(&mut self) {
124        self.raw.pop_transform();
125    }
126
127    /// Executes the given drawing operations within a [`Rectangle`] region,
128    /// clipping any geometry that overflows its bounds. Any transformations
129    /// performed are local to the provided closure.
130    ///
131    /// This method is useful to perform drawing operations that need to be
132    /// clipped.
133    #[inline]
134    pub fn with_clip<R>(
135        &mut self,
136        region: Rectangle,
137        f: impl FnOnce(&mut Self) -> R,
138    ) -> R {
139        let mut frame = self.draft(region);
140
141        let result = f(&mut frame);
142        self.paste(frame);
143
144        result
145    }
146
147    /// Creates a new [`Frame`] with the given [`Size`].
148    ///
149    /// Draw its contents back to this [`Frame`] with [`paste`].
150    ///
151    /// [`paste`]: Self::paste
152    fn draft(&mut self, clip_bounds: Rectangle) -> Self {
153        Self {
154            raw: self.raw.draft(clip_bounds),
155        }
156    }
157
158    /// Draws the contents of the given [`Frame`] with origin at the given [`Point`].
159    fn paste(&mut self, frame: Self) {
160        self.raw.paste(frame.raw);
161    }
162
163    /// Applies a translation to the current transform of the [`Frame`].
164    pub fn translate(&mut self, translation: Vector) {
165        self.raw.translate(translation);
166    }
167
168    /// Applies a rotation in radians to the current transform of the [`Frame`].
169    pub fn rotate(&mut self, angle: impl Into<Radians>) {
170        self.raw.rotate(angle);
171    }
172
173    /// Applies a uniform scaling to the current transform of the [`Frame`].
174    pub fn scale(&mut self, scale: impl Into<f32>) {
175        self.raw.scale(scale);
176    }
177
178    /// Applies a non-uniform scaling to the current transform of the [`Frame`].
179    pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
180        self.raw.scale_nonuniform(scale);
181    }
182
183    /// Turns the [`Frame`] into its underlying geometry.
184    pub fn into_geometry(self) -> Renderer::Geometry {
185        self.raw.into_geometry()
186    }
187}
188
189/// The internal implementation of a [`Frame`].
190///
191/// Analogous to [`Frame`]. See [`Frame`] for the documentation
192/// of each method.
193#[allow(missing_docs)]
194pub trait Backend: Sized {
195    type Geometry;
196
197    fn width(&self) -> f32;
198    fn height(&self) -> f32;
199    fn size(&self) -> Size;
200    fn center(&self) -> Point;
201
202    fn push_transform(&mut self);
203    fn pop_transform(&mut self);
204
205    fn translate(&mut self, translation: Vector);
206    fn rotate(&mut self, angle: impl Into<Radians>);
207    fn scale(&mut self, scale: impl Into<f32>);
208    fn scale_nonuniform(&mut self, scale: impl Into<Vector>);
209
210    fn draft(&mut self, clip_bounds: Rectangle) -> Self;
211    fn paste(&mut self, frame: Self);
212
213    fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>);
214    fn stroke_rectangle<'a>(
215        &mut self,
216        top_left: Point,
217        size: Size,
218        stroke: impl Into<Stroke<'a>>,
219    );
220
221    fn fill(&mut self, path: &Path, fill: impl Into<Fill>);
222    fn fill_text(&mut self, text: impl Into<Text>);
223    fn fill_rectangle(
224        &mut self,
225        top_left: Point,
226        size: Size,
227        fill: impl Into<Fill>,
228    );
229
230    fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>);
231    fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>);
232
233    fn into_geometry(self) -> Self::Geometry;
234}
235
236#[cfg(debug_assertions)]
237impl Backend for () {
238    type Geometry = ();
239
240    fn width(&self) -> f32 {
241        0.0
242    }
243
244    fn height(&self) -> f32 {
245        0.0
246    }
247
248    fn size(&self) -> Size {
249        Size::ZERO
250    }
251
252    fn center(&self) -> Point {
253        Point::ORIGIN
254    }
255
256    fn push_transform(&mut self) {}
257    fn pop_transform(&mut self) {}
258
259    fn translate(&mut self, _translation: Vector) {}
260    fn rotate(&mut self, _angle: impl Into<Radians>) {}
261    fn scale(&mut self, _scale: impl Into<f32>) {}
262    fn scale_nonuniform(&mut self, _scale: impl Into<Vector>) {}
263
264    fn draft(&mut self, _clip_bounds: Rectangle) -> Self {}
265    fn paste(&mut self, _frame: Self) {}
266
267    fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {}
268    fn stroke_rectangle<'a>(
269        &mut self,
270        _top_left: Point,
271        _size: Size,
272        _stroke: impl Into<Stroke<'a>>,
273    ) {
274    }
275
276    fn fill(&mut self, _path: &Path, _fill: impl Into<Fill>) {}
277    fn fill_text(&mut self, _text: impl Into<Text>) {}
278    fn fill_rectangle(
279        &mut self,
280        _top_left: Point,
281        _size: Size,
282        _fill: impl Into<Fill>,
283    ) {
284    }
285
286    fn draw_image(&mut self, _bounds: Rectangle, _image: impl Into<Image>) {}
287    fn draw_svg(&mut self, _bounds: Rectangle, _svg: impl Into<Svg>) {}
288
289    fn into_geometry(self) -> Self::Geometry {}
290}