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    fn stroke_text<'a>(
221        &mut self,
222        text: impl Into<Text>,
223        stroke: impl Into<Stroke<'a>>,
224    );
225
226    fn fill(&mut self, path: &Path, fill: impl Into<Fill>);
227    fn fill_text(&mut self, text: impl Into<Text>);
228    fn fill_rectangle(
229        &mut self,
230        top_left: Point,
231        size: Size,
232        fill: impl Into<Fill>,
233    );
234
235    fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>);
236    fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>);
237
238    fn into_geometry(self) -> Self::Geometry;
239}
240
241#[cfg(debug_assertions)]
242impl Backend for () {
243    type Geometry = ();
244
245    fn width(&self) -> f32 {
246        0.0
247    }
248
249    fn height(&self) -> f32 {
250        0.0
251    }
252
253    fn size(&self) -> Size {
254        Size::ZERO
255    }
256
257    fn center(&self) -> Point {
258        Point::ORIGIN
259    }
260
261    fn push_transform(&mut self) {}
262    fn pop_transform(&mut self) {}
263
264    fn translate(&mut self, _translation: Vector) {}
265    fn rotate(&mut self, _angle: impl Into<Radians>) {}
266    fn scale(&mut self, _scale: impl Into<f32>) {}
267    fn scale_nonuniform(&mut self, _scale: impl Into<Vector>) {}
268
269    fn draft(&mut self, _clip_bounds: Rectangle) -> Self {}
270    fn paste(&mut self, _frame: Self) {}
271
272    fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {}
273    fn stroke_rectangle<'a>(
274        &mut self,
275        _top_left: Point,
276        _size: Size,
277        _stroke: impl Into<Stroke<'a>>,
278    ) {
279    }
280    fn stroke_text<'a>(
281        &mut self,
282        _text: impl Into<Text>,
283        _stroke: impl Into<Stroke<'a>>,
284    ) {
285    }
286
287    fn fill(&mut self, _path: &Path, _fill: impl Into<Fill>) {}
288    fn fill_text(&mut self, _text: impl Into<Text>) {}
289    fn fill_rectangle(
290        &mut self,
291        _top_left: Point,
292        _size: Size,
293        _fill: impl Into<Fill>,
294    ) {
295    }
296
297    fn draw_image(&mut self, _bounds: Rectangle, _image: impl Into<Image>) {}
298    fn draw_svg(&mut self, _bounds: Rectangle, _svg: impl Into<Svg>) {}
299
300    fn into_geometry(self) -> Self::Geometry {}
301}