x_graphics/
canvas.rs

1use crate::{
2    bitmap::{Bitmap, BitmapBackend},
3    brush::{Brush, BrushBackend},
4    device::{DeviceContext, DeviceContextBackend},
5    error::GraphicsError,
6    font::{FontStyle, FontWeight},
7    geometry::{FRect, FSize, ISize},
8    layer::{Layer, LayerBackend},
9    matrix::{Matrix, MatrixBackend},
10    paint::{BlendMode, Cap, Color, DrawMode, Join},
11    path::{Path, PathBackend},
12    text::TextAlignment,
13    window::Window,
14    DefaultCanvas, DefaultDeviceContext, DefaultLayer, Float,
15};
16
17pub trait CanvasBackend {
18    type DeviceContextType: DeviceContextBackend;
19    type BitmapType: BitmapBackend;
20    type BrushType: BrushBackend;
21    type LayerType: LayerBackend;
22    type MatrixType: MatrixBackend;
23    type PathType: PathBackend;
24
25    fn from_layer(context: Option<&Self::DeviceContextType>, layer: &Self::LayerType) -> Result<Self, GraphicsError>
26    where
27        Self: Sized;
28    fn from_window(context: Option<&Self::DeviceContextType>, window: &Window) -> Result<Self, GraphicsError>
29    where
30        Self: Sized;
31    fn device_context(&self) -> Option<&Self::DeviceContextType>;
32    fn size(&self) -> FSize;
33    fn pixel_size(&self) -> ISize;
34    fn bounds(&self) -> FRect {
35        let size = self.size();
36        FRect::new(0.0, 0.0, size.width, size.height)
37    }
38    fn save(&mut self) -> bool;
39    fn restore(&mut self) -> bool;
40    fn begin_draw(&mut self);
41    fn end_draw(&mut self);
42    fn get_opacity(&self) -> Float;
43    fn set_opacity(&mut self, opacity: Float);
44    fn get_blend_mode(&self) -> BlendMode;
45    fn set_blend_mode(&mut self, mode: BlendMode);
46    fn get_draw_mode(&self) -> DrawMode;
47    fn set_draw_mode(&mut self, mode: DrawMode);
48    fn get_line_dash(&self) -> (Option<Vec<Float>>, Float);
49    fn set_line_dash(&mut self, dashes: &[Float], offset: Float);
50    fn get_matrix(&self) -> Self::MatrixType;
51    fn set_matrix(&mut self, matrix: &Self::MatrixType);
52    fn concat_matrix(&mut self, matrix: &Self::MatrixType);
53    fn get_miter_limit(&self) -> Float;
54    fn set_miter_limit(&mut self, miter_limit: Float);
55    fn get_smooth(&self) -> bool;
56    fn set_smooth(&mut self, smooth: bool);
57    fn get_stroke_cap(&self) -> Cap;
58    fn set_stroke_cap(&mut self, cap: Cap);
59    fn get_stroke_join(&self) -> Join;
60    fn set_stroke_join(&mut self, join: Join);
61    fn get_stroke_width(&self) -> Float;
62    fn set_stroke_width(&mut self, width: Float);
63    fn set_brush(&mut self, brush: &Self::BrushType);
64    fn get_font_family(&self) -> &str;
65    fn set_font_family(&mut self, family: &str);
66    fn get_font_size(&self) -> Float;
67    fn set_font_size(&mut self, size: Float);
68    fn get_font_style(&self) -> FontStyle;
69    fn set_font_style(&mut self, style: FontStyle);
70    fn get_font_weight(&self) -> FontWeight;
71    fn set_font_weight(&mut self, weight: FontWeight);
72    fn get_text_alignment(&self) -> TextAlignment;
73    fn set_text_alignment(&mut self, alignment: TextAlignment);
74    fn get_text_color(&self) -> Color;
75    fn set_text_color(&mut self, color: Color);
76    fn rotate(&mut self, angle: Float);
77    fn scale(&mut self, x: Float, y: Float);
78    fn translate(&mut self, x: Float, y: Float);
79    fn clear(&mut self, color: Color);
80    fn clip_to_rect(&mut self, rect: FRect);
81    fn clip_to_path(&mut self, path: &Self::PathType);
82    fn draw_line(&mut self, x1: Float, y1: Float, x2: Float, y2: Float) -> bool {
83        Self::PathType::new(None)
84            .map(|mut path| {
85                path.move_to(x1, y1);
86                path.line_to(x2, y2);
87                self.draw_path(&path)
88            })
89            .unwrap_or(false)
90    }
91    fn draw_rect(&mut self, x: Float, y: Float, width: Float, height: Float) -> bool {
92        Self::PathType::new(None)
93            .map(|mut path| {
94                path.add_rect(x, y, width, height);
95                self.draw_path(&path)
96            })
97            .unwrap_or(false)
98    }
99    fn draw_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float) -> bool {
100        Self::PathType::new(None)
101            .map(|mut path| {
102                path.add_rounded_rect(x, y, width, height, radius);
103                self.draw_path(&path)
104            })
105            .unwrap_or(false)
106    }
107    fn draw_circle(&mut self, x: Float, y: Float, radius: Float) -> bool {
108        Self::PathType::new(None)
109            .map(|mut path| {
110                path.add_circle(x, y, radius);
111                self.draw_path(&path)
112            })
113            .unwrap_or(false)
114    }
115    fn draw_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float) -> bool {
116        Self::PathType::new(None)
117            .map(|mut path| {
118                path.add_ellipse(x, y, width, height);
119                self.draw_path(&path)
120            })
121            .unwrap_or(false)
122    }
123    fn draw_path(&mut self, path: &Self::PathType) -> bool;
124    fn draw_bitmap(&mut self, bitmap: &Self::BitmapType, source_rect: Option<FRect>, dest_rect: FRect) -> bool;
125    fn draw_layer(&mut self, layer: &Self::LayerType, dest_rect: FRect) -> bool;
126    fn draw_text(&mut self, text: &str, rect: FRect) -> bool;
127    fn draw_text_at(&mut self, text: &str, x: Float, y: Float) -> bool;
128    fn fill_rect(&mut self, x: Float, y: Float, width: Float, height: Float, mask: Option<&Self::BitmapType>) -> bool;
129    fn map_rect(&self, rect: FRect) -> FRect {
130        let matrix = self.get_matrix();
131        matrix.map_rect(rect)
132    }
133}
134
135pub struct Canvas<T: CanvasBackend> {
136    pub(crate) backend: T,
137}
138
139impl<T: CanvasBackend> Canvas<T> {
140    pub fn from_layer(context: Option<&DeviceContext<T::DeviceContextType>>, layer: &Layer<T::LayerType>) -> Result<Self, GraphicsError> {
141        Ok(Self {
142            backend: T::from_layer(context.map(|ctx| &ctx.backend), &layer.backend)?,
143        })
144    }
145
146    pub fn from_window(context: Option<&DeviceContext<T::DeviceContextType>>, window: &Window) -> Result<Self, GraphicsError> {
147        Ok(Self {
148            backend: T::from_window(context.map(|ctx| &ctx.backend), window)?,
149        })
150    }
151
152    pub fn device_context(&self) -> Option<DeviceContext<T::DeviceContextType>> {
153        self.backend.device_context().map(|ctx| DeviceContext {
154            backend: ctx.clone(),
155        })
156    }
157
158    pub fn size(&self) -> FSize {
159        self.backend.size()
160    }
161
162    pub fn pixel_size(&self) -> ISize {
163        self.backend.pixel_size()
164    }
165
166    pub fn bounds(&self) -> FRect {
167        self.backend.bounds()
168    }
169
170    pub fn save(&mut self) -> bool {
171        self.backend.save()
172    }
173
174    pub fn restore(&mut self) -> bool {
175        self.backend.restore()
176    }
177
178    pub fn begin_draw(&mut self) {
179        self.backend.begin_draw()
180    }
181
182    pub fn end_draw(&mut self) {
183        self.backend.end_draw()
184    }
185
186    pub fn get_opacity(&self) -> Float {
187        self.backend.get_opacity()
188    }
189
190    pub fn set_opacity(&mut self, opacity: Float) {
191        self.backend.set_opacity(opacity)
192    }
193
194    pub fn get_blend_mode(&self) -> BlendMode {
195        self.backend.get_blend_mode()
196    }
197
198    pub fn set_blend_mode(&mut self, mode: BlendMode) {
199        self.backend.set_blend_mode(mode)
200    }
201
202    pub fn get_draw_mode(&self) -> DrawMode {
203        self.backend.get_draw_mode()
204    }
205
206    pub fn set_draw_mode(&mut self, mode: DrawMode) {
207        self.backend.set_draw_mode(mode)
208    }
209
210    pub fn get_line_dash(&self) -> (Option<Vec<Float>>, Float) {
211        self.backend.get_line_dash()
212    }
213
214    pub fn set_line_dash(&mut self, dashes: &[Float], offset: Float) {
215        self.backend.set_line_dash(dashes, offset)
216    }
217
218    pub fn get_matrix(&self) -> Matrix<T::MatrixType> {
219        Matrix {
220            backend: self.backend.get_matrix(),
221        }
222    }
223
224    pub fn set_matrix(&mut self, matrix: &Matrix<T::MatrixType>) {
225        self.backend.set_matrix(&matrix.backend)
226    }
227
228    pub fn concat_matrix(&mut self, matrix: &Matrix<T::MatrixType>) {
229        self.backend.concat_matrix(&matrix.backend)
230    }
231
232    pub fn get_miter_limit(&self) -> Float {
233        self.backend.get_miter_limit()
234    }
235
236    pub fn set_miter_limit(&mut self, miter_limit: Float) {
237        self.backend.set_miter_limit(miter_limit)
238    }
239
240    pub fn get_smooth(&self) -> bool {
241        self.backend.get_smooth()
242    }
243
244    pub fn set_smooth(&mut self, smooth: bool) {
245        self.backend.set_smooth(smooth)
246    }
247
248    pub fn get_stroke_cap(&self) -> Cap {
249        self.backend.get_stroke_cap()
250    }
251
252    pub fn set_stroke_cap(&mut self, cap: Cap) {
253        self.backend.set_stroke_cap(cap)
254    }
255
256    pub fn get_stroke_join(&self) -> Join {
257        self.backend.get_stroke_join()
258    }
259
260    pub fn set_stroke_join(&mut self, join: Join) {
261        self.backend.set_stroke_join(join)
262    }
263
264    pub fn get_stroke_width(&self) -> Float {
265        self.backend.get_stroke_width()
266    }
267
268    pub fn set_stroke_width(&mut self, width: Float) {
269        self.backend.set_stroke_width(width)
270    }
271
272    pub fn set_brush(&mut self, brush: &Brush<T::BrushType>) {
273        self.backend.set_brush(&brush.backend)
274    }
275
276    pub fn get_font_family(&self) -> &str {
277        self.backend.get_font_family()
278    }
279
280    pub fn set_font_family(&mut self, family: &str) {
281        self.backend.set_font_family(family)
282    }
283
284    pub fn get_font_size(&self) -> Float {
285        self.backend.get_font_size()
286    }
287
288    pub fn set_font_size(&mut self, size: Float) {
289        self.backend.set_font_size(size)
290    }
291
292    pub fn get_font_style(&self) -> FontStyle {
293        self.backend.get_font_style()
294    }
295
296    pub fn set_font_style(&mut self, style: FontStyle) {
297        self.backend.set_font_style(style)
298    }
299
300    pub fn get_font_weight(&self) -> FontWeight {
301        self.backend.get_font_weight()
302    }
303
304    pub fn set_font_weight(&mut self, weight: FontWeight) {
305        self.backend.set_font_weight(weight)
306    }
307
308    pub fn get_text_alignment(&self) -> TextAlignment {
309        self.backend.get_text_alignment()
310    }
311
312    pub fn set_text_alignment(&mut self, alignment: TextAlignment) {
313        self.backend.set_text_alignment(alignment)
314    }
315
316    pub fn get_text_color(&self) -> Color {
317        self.backend.get_text_color()
318    }
319
320    pub fn set_text_color(&mut self, color: Color) {
321        self.backend.set_text_color(color)
322    }
323
324    pub fn rotate(&mut self, angle: Float) {
325        self.backend.rotate(angle)
326    }
327
328    pub fn scale(&mut self, x: Float, y: Float) {
329        self.backend.scale(x, y)
330    }
331
332    pub fn translate(&mut self, x: Float, y: Float) {
333        self.backend.translate(x, y)
334    }
335
336    pub fn clear(&mut self, color: Color) {
337        self.backend.clear(color)
338    }
339
340    pub fn clip_to_rect(&mut self, rect: FRect) {
341        self.backend.clip_to_rect(rect)
342    }
343
344    pub fn clip_to_path(&mut self, path: &Path<T::PathType>) {
345        self.backend.clip_to_path(&path.backend)
346    }
347
348    pub fn draw_line(&mut self, x1: Float, y1: Float, x2: Float, y2: Float) -> bool {
349        self.backend.draw_line(x1, y1, x2, y2)
350    }
351
352    pub fn draw_rect(&mut self, x: Float, y: Float, width: Float, height: Float) -> bool {
353        self.backend.draw_rect(x, y, width, height)
354    }
355
356    pub fn draw_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float) -> bool {
357        self.backend.draw_rounded_rect(x, y, width, height, radius)
358    }
359
360    pub fn draw_circle(&mut self, x: Float, y: Float, radius: Float) -> bool {
361        self.backend.draw_circle(x, y, radius)
362    }
363
364    pub fn draw_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float) -> bool {
365        self.backend.draw_ellipse(x, y, width, height)
366    }
367
368    pub fn draw_path(&mut self, path: &Path<T::PathType>) -> bool {
369        self.backend.draw_path(&path.backend)
370    }
371
372    pub fn draw_bitmap(&mut self, bitmap: &Bitmap<T::BitmapType>, source_rect: Option<FRect>, dest_rect: FRect) -> bool {
373        self.backend.draw_bitmap(&bitmap.backend, source_rect, dest_rect)
374    }
375
376    pub fn draw_layer(&mut self, layer: &Layer<T::LayerType>, dest_rect: FRect) -> bool {
377        self.backend.draw_layer(&layer.backend, dest_rect)
378    }
379
380    pub fn draw_text(&mut self, text: &str, rect: FRect) -> bool {
381        self.backend.draw_text(text, rect)
382    }
383
384    pub fn draw_text_at(&mut self, text: &str, x: Float, y: Float) -> bool {
385        self.backend.draw_text_at(text, x, y)
386    }
387
388    pub fn map_rect(&self, rect: FRect) -> FRect {
389        self.backend.map_rect(rect)
390    }
391
392    pub fn fill_rect(&mut self, x: Float, y: Float, width: Float, height: Float, mask: Option<&Bitmap<T::BitmapType>>) -> bool {
393        self.backend.fill_rect(x, y, width, height, mask.map(|mask| &mask.backend))
394    }
395}
396
397impl Canvas<DefaultCanvas> {
398    pub fn default_from_layer(context: Option<&DeviceContext<DefaultDeviceContext>>, layer: &Layer<DefaultLayer>) -> Result<Self, GraphicsError> {
399        Self::from_layer(context, layer)
400    }
401
402    pub fn default_from_window(context: Option<&DeviceContext<DefaultDeviceContext>>, window: &Window) -> Result<Self, GraphicsError> {
403        Self::from_window(context, window)
404    }
405}