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}