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 {
23 Self::with_bounds(renderer, Rectangle::with_size(size))
24 }
25
26 pub fn with_bounds(renderer: &Renderer, bounds: Rectangle) -> Self {
28 Self {
29 raw: renderer.new_frame(bounds),
30 }
31 }
32
33 pub fn width(&self) -> f32 {
35 self.raw.width()
36 }
37
38 pub fn height(&self) -> f32 {
40 self.raw.height()
41 }
42
43 pub fn size(&self) -> Size {
45 self.raw.size()
46 }
47
48 pub fn center(&self) -> Point {
50 self.raw.center()
51 }
52
53 pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) {
56 self.raw.fill(path, fill);
57 }
58
59 pub fn fill_rectangle(
62 &mut self,
63 top_left: Point,
64 size: Size,
65 fill: impl Into<Fill>,
66 ) {
67 self.raw.fill_rectangle(top_left, size, fill);
68 }
69
70 pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {
73 self.raw.stroke(path, stroke);
74 }
75
76 pub fn stroke_rectangle<'a>(
79 &mut self,
80 top_left: Point,
81 size: Size,
82 stroke: impl Into<Stroke<'a>>,
83 ) {
84 self.raw.stroke_rectangle(top_left, size, stroke);
85 }
86
87 pub fn fill_text(&mut self, text: impl Into<Text>) {
94 self.raw.fill_text(text);
95 }
96
97 #[cfg(feature = "image")]
99 pub fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
100 self.raw.draw_image(bounds, image);
101 }
102
103 #[cfg(feature = "svg")]
105 pub fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>) {
106 self.raw.draw_svg(bounds, svg);
107 }
108
109 #[inline]
115 pub fn with_save<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
116 self.push_transform();
117
118 let result = f(self);
119
120 self.pop_transform();
121
122 result
123 }
124
125 pub fn push_transform(&mut self) {
127 self.raw.push_transform();
128 }
129
130 pub fn pop_transform(&mut self) {
132 self.raw.pop_transform();
133 }
134
135 #[inline]
142 pub fn with_clip<R>(
143 &mut self,
144 region: Rectangle,
145 f: impl FnOnce(&mut Self) -> R,
146 ) -> R {
147 let mut frame = self.draft(region);
148
149 let result = f(&mut frame);
150 self.paste(frame);
151
152 result
153 }
154
155 fn draft(&mut self, clip_bounds: Rectangle) -> Self {
161 Self {
162 raw: self.raw.draft(clip_bounds),
163 }
164 }
165
166 fn paste(&mut self, frame: Self) {
168 self.raw.paste(frame.raw);
169 }
170
171 pub fn translate(&mut self, translation: Vector) {
173 self.raw.translate(translation);
174 }
175
176 pub fn rotate(&mut self, angle: impl Into<Radians>) {
178 self.raw.rotate(angle);
179 }
180
181 pub fn scale(&mut self, scale: impl Into<f32>) {
183 self.raw.scale(scale);
184 }
185
186 pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
188 self.raw.scale_nonuniform(scale);
189 }
190
191 pub fn into_geometry(self) -> Renderer::Geometry {
193 self.raw.into_geometry()
194 }
195}
196
197#[allow(missing_docs)]
202pub trait Backend: Sized {
203 type Geometry;
204
205 fn width(&self) -> f32;
206 fn height(&self) -> f32;
207 fn size(&self) -> Size;
208 fn center(&self) -> Point;
209
210 fn push_transform(&mut self);
211 fn pop_transform(&mut self);
212
213 fn translate(&mut self, translation: Vector);
214 fn rotate(&mut self, angle: impl Into<Radians>);
215 fn scale(&mut self, scale: impl Into<f32>);
216 fn scale_nonuniform(&mut self, scale: impl Into<Vector>);
217
218 fn draft(&mut self, clip_bounds: Rectangle) -> Self;
219 fn paste(&mut self, frame: Self);
220
221 fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>);
222 fn stroke_rectangle<'a>(
223 &mut self,
224 top_left: Point,
225 size: Size,
226 stroke: impl Into<Stroke<'a>>,
227 );
228 fn stroke_text<'a>(
229 &mut self,
230 text: impl Into<Text>,
231 stroke: impl Into<Stroke<'a>>,
232 );
233
234 fn fill(&mut self, path: &Path, fill: impl Into<Fill>);
235 fn fill_text(&mut self, text: impl Into<Text>);
236 fn fill_rectangle(
237 &mut self,
238 top_left: Point,
239 size: Size,
240 fill: impl Into<Fill>,
241 );
242
243 fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>);
244 fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>);
245
246 fn into_geometry(self) -> Self::Geometry;
247}
248
249#[cfg(debug_assertions)]
250impl Backend for () {
251 type Geometry = ();
252
253 fn width(&self) -> f32 {
254 0.0
255 }
256
257 fn height(&self) -> f32 {
258 0.0
259 }
260
261 fn size(&self) -> Size {
262 Size::ZERO
263 }
264
265 fn center(&self) -> Point {
266 Point::ORIGIN
267 }
268
269 fn push_transform(&mut self) {}
270 fn pop_transform(&mut self) {}
271
272 fn translate(&mut self, _translation: Vector) {}
273 fn rotate(&mut self, _angle: impl Into<Radians>) {}
274 fn scale(&mut self, _scale: impl Into<f32>) {}
275 fn scale_nonuniform(&mut self, _scale: impl Into<Vector>) {}
276
277 fn draft(&mut self, _clip_bounds: Rectangle) -> Self {}
278 fn paste(&mut self, _frame: Self) {}
279
280 fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {}
281 fn stroke_rectangle<'a>(
282 &mut self,
283 _top_left: Point,
284 _size: Size,
285 _stroke: impl Into<Stroke<'a>>,
286 ) {
287 }
288 fn stroke_text<'a>(
289 &mut self,
290 _text: impl Into<Text>,
291 _stroke: impl Into<Stroke<'a>>,
292 ) {
293 }
294
295 fn fill(&mut self, _path: &Path, _fill: impl Into<Fill>) {}
296 fn fill_text(&mut self, _text: impl Into<Text>) {}
297 fn fill_rectangle(
298 &mut self,
299 _top_left: Point,
300 _size: Size,
301 _fill: impl Into<Fill>,
302 ) {
303 }
304
305 fn draw_image(&mut self, _bounds: Rectangle, _image: impl Into<Image>) {}
306 fn draw_svg(&mut self, _bounds: Rectangle, _svg: impl Into<Svg>) {}
307
308 fn into_geometry(self) -> Self::Geometry {}
309}