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 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}