1use crate::core::{Point, Radians, Rectangle, Size, Vector};
3use crate::geometry::{self, Fill, Image, Path, Stroke, Svg, Text};
4
5#[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 pub fn new(renderer: &Renderer, size: Size) -> Self {
20 Self {
21 raw: renderer.new_frame(size),
22 }
23 }
24
25 pub fn width(&self) -> f32 {
27 self.raw.width()
28 }
29
30 pub fn height(&self) -> f32 {
32 self.raw.height()
33 }
34
35 pub fn size(&self) -> Size {
37 self.raw.size()
38 }
39
40 pub fn center(&self) -> Point {
42 self.raw.center()
43 }
44
45 pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) {
48 self.raw.fill(path, fill);
49 }
50
51 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 pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {
65 self.raw.stroke(path, stroke);
66 }
67
68 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 pub fn fill_text(&mut self, text: impl Into<Text>) {
86 self.raw.fill_text(text);
87 }
88
89 #[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 #[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 #[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 pub fn push_transform(&mut self) {
119 self.raw.push_transform();
120 }
121
122 pub fn pop_transform(&mut self) {
124 self.raw.pop_transform();
125 }
126
127 #[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 fn draft(&mut self, clip_bounds: Rectangle) -> Self {
153 Self {
154 raw: self.raw.draft(clip_bounds),
155 }
156 }
157
158 fn paste(&mut self, frame: Self) {
160 self.raw.paste(frame.raw);
161 }
162
163 pub fn translate(&mut self, translation: Vector) {
165 self.raw.translate(translation);
166 }
167
168 pub fn rotate(&mut self, angle: impl Into<Radians>) {
170 self.raw.rotate(angle);
171 }
172
173 pub fn scale(&mut self, scale: impl Into<f32>) {
175 self.raw.scale(scale);
176 }
177
178 pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
180 self.raw.scale_nonuniform(scale);
181 }
182
183 pub fn into_geometry(self) -> Renderer::Geometry {
185 self.raw.into_geometry()
186 }
187}
188
189#[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}