1use crate::core::{Point, Radians, Rectangle, Size, Vector};
3use crate::geometry::{self, Fill, Image, Path, Stroke, Svg, Text};
4
5pub struct Frame<Renderer>
7where
8 Renderer: geometry::Renderer,
9{
10 raw: Renderer::Frame,
11}
12
13impl<Renderer> Frame<Renderer>
14where
15 Renderer: geometry::Renderer,
16{
17 pub fn new(renderer: &Renderer, size: Size) -> Self {
22 Self::with_bounds(renderer, Rectangle::with_size(size))
23 }
24
25 pub fn with_bounds(renderer: &Renderer, bounds: Rectangle) -> Self {
27 Self {
28 raw: renderer.new_frame(bounds),
29 }
30 }
31
32 pub fn width(&self) -> f32 {
34 self.raw.width()
35 }
36
37 pub fn height(&self) -> f32 {
39 self.raw.height()
40 }
41
42 pub fn size(&self) -> Size {
44 self.raw.size()
45 }
46
47 pub fn center(&self) -> Point {
49 self.raw.center()
50 }
51
52 pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) {
55 self.raw.fill(path, fill);
56 }
57
58 pub fn fill_rectangle(&mut self, top_left: Point, size: Size, fill: impl Into<Fill>) {
61 self.raw.fill_rectangle(top_left, size, fill);
62 }
63
64 pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {
67 self.raw.stroke(path, stroke);
68 }
69
70 pub fn stroke_rectangle<'a>(
73 &mut self,
74 top_left: Point,
75 size: Size,
76 stroke: impl Into<Stroke<'a>>,
77 ) {
78 self.raw.stroke_rectangle(top_left, size, stroke);
79 }
80
81 pub fn fill_text(&mut self, text: impl Into<Text>) {
88 self.raw.fill_text(text);
89 }
90
91 #[cfg(feature = "image")]
93 pub fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
94 self.raw.draw_image(bounds, image);
95 }
96
97 #[cfg(feature = "svg")]
99 pub fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>) {
100 self.raw.draw_svg(bounds, svg);
101 }
102
103 #[inline]
109 pub fn with_save<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
110 self.push_transform();
111
112 let result = f(self);
113
114 self.pop_transform();
115
116 result
117 }
118
119 pub fn push_transform(&mut self) {
121 self.raw.push_transform();
122 }
123
124 pub fn pop_transform(&mut self) {
126 self.raw.pop_transform();
127 }
128
129 #[inline]
136 pub fn with_clip<R>(&mut self, region: Rectangle, f: impl FnOnce(&mut Self) -> R) -> R {
137 let mut frame = self.draft(region);
138
139 let result = f(&mut frame);
140 self.paste(frame);
141
142 result
143 }
144
145 fn draft(&mut self, clip_bounds: Rectangle) -> Self {
151 Self {
152 raw: self.raw.draft(clip_bounds),
153 }
154 }
155
156 fn paste(&mut self, frame: Self) {
158 self.raw.paste(frame.raw);
159 }
160
161 pub fn translate(&mut self, translation: Vector) {
163 self.raw.translate(translation);
164 }
165
166 pub fn rotate(&mut self, angle: impl Into<Radians>) {
168 self.raw.rotate(angle);
169 }
170
171 pub fn scale(&mut self, scale: impl Into<f32>) {
173 self.raw.scale(scale);
174 }
175
176 pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
178 self.raw.scale_nonuniform(scale);
179 }
180
181 pub fn into_geometry(self) -> Renderer::Geometry {
183 self.raw.into_geometry()
184 }
185}
186
187#[allow(missing_docs)]
192pub trait Backend: Sized {
193 type Geometry;
194
195 fn width(&self) -> f32;
196 fn height(&self) -> f32;
197 fn size(&self) -> Size;
198 fn center(&self) -> Point;
199
200 fn push_transform(&mut self);
201 fn pop_transform(&mut self);
202
203 fn translate(&mut self, translation: Vector);
204 fn rotate(&mut self, angle: impl Into<Radians>);
205 fn scale(&mut self, scale: impl Into<f32>);
206 fn scale_nonuniform(&mut self, scale: impl Into<Vector>);
207
208 fn draft(&mut self, clip_bounds: Rectangle) -> Self;
209 fn paste(&mut self, frame: Self);
210
211 fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>);
212 fn stroke_rectangle<'a>(&mut self, top_left: Point, size: Size, stroke: impl Into<Stroke<'a>>);
213 fn stroke_text<'a>(&mut self, text: impl Into<Text>, stroke: impl Into<Stroke<'a>>);
214
215 fn fill(&mut self, path: &Path, fill: impl Into<Fill>);
216 fn fill_text(&mut self, text: impl Into<Text>);
217 fn fill_rectangle(&mut self, top_left: Point, size: Size, fill: impl Into<Fill>);
218
219 fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>);
220 fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into<Svg>);
221
222 fn into_geometry(self) -> Self::Geometry;
223}
224
225#[cfg(debug_assertions)]
226impl Backend for () {
227 type Geometry = ();
228
229 fn width(&self) -> f32 {
230 0.0
231 }
232
233 fn height(&self) -> f32 {
234 0.0
235 }
236
237 fn size(&self) -> Size {
238 Size::ZERO
239 }
240
241 fn center(&self) -> Point {
242 Point::ORIGIN
243 }
244
245 fn push_transform(&mut self) {}
246 fn pop_transform(&mut self) {}
247
248 fn translate(&mut self, _translation: Vector) {}
249 fn rotate(&mut self, _angle: impl Into<Radians>) {}
250 fn scale(&mut self, _scale: impl Into<f32>) {}
251 fn scale_nonuniform(&mut self, _scale: impl Into<Vector>) {}
252
253 fn draft(&mut self, _clip_bounds: Rectangle) -> Self {}
254 fn paste(&mut self, _frame: Self) {}
255
256 fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {}
257 fn stroke_rectangle<'a>(
258 &mut self,
259 _top_left: Point,
260 _size: Size,
261 _stroke: impl Into<Stroke<'a>>,
262 ) {
263 }
264 fn stroke_text<'a>(&mut self, _text: impl Into<Text>, _stroke: impl Into<Stroke<'a>>) {}
265
266 fn fill(&mut self, _path: &Path, _fill: impl Into<Fill>) {}
267 fn fill_text(&mut self, _text: impl Into<Text>) {}
268 fn fill_rectangle(&mut self, _top_left: Point, _size: Size, _fill: impl Into<Fill>) {}
269
270 fn draw_image(&mut self, _bounds: Rectangle, _image: impl Into<Image>) {}
271 fn draw_svg(&mut self, _bounds: Rectangle, _svg: impl Into<Svg>) {}
272
273 fn into_geometry(self) -> Self::Geometry {}
274}