1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::{gpu::Shader, paint::Paint, Angle, Element, Method, P2, V2};
use lyon_path::Builder;
use palette::{Alpha, IntoColor, LinSrgb, LinSrgba};
pub struct Canvas {
path: Builder,
shader: Shader,
color: LinSrgba,
stroke_width: f32,
scale: f32,
elements: Vec<Element>,
}
impl Canvas {
pub(crate) fn new(default_shader: Shader, scale: f32) -> Self {
Self {
path: Builder::new(),
shader: default_shader,
color: Alpha::<LinSrgb, _>::new(1., 1., 1., 1.),
scale,
stroke_width: 1.,
elements: vec![],
}
}
pub fn paint(&mut self, element: impl Paint) {
element.paint(self);
}
pub fn set_color(&mut self, color: impl IntoColor) {
self.color = Alpha::from(color.into_rgb());
}
pub fn set_color_alpha(&mut self, color: impl IntoColor, alpha: f32) {
self.color = Alpha {
color: color.into_rgb(),
alpha,
};
}
pub fn move_to(&mut self, dest: P2) {
self.path = Builder::new();
self.path.move_to(dest * self.scale);
}
pub fn line_to(&mut self, dest: P2) {
self.path.line_to(dest * self.scale);
}
pub fn quadratic_to(&mut self, ctrl: P2, end: P2) {
self.path
.quadratic_bezier_to(ctrl * self.scale, end * self.scale);
}
pub fn cubic_to(&mut self, ctrl0: P2, ctrl1: P2, end: P2) {
self.path
.cubic_bezier_to(ctrl0 * self.scale, ctrl1 * self.scale, end * self.scale);
}
pub fn arc(&mut self, center: P2, radii: V2, sweep: Angle, phase: Angle) {
self.path
.arc(center * self.scale, radii * self.scale, sweep, phase);
}
pub fn close_path(&mut self) {
self.path.close()
}
pub fn set_stroke_width(&mut self, stroke_width: f32) {
self.stroke_width = stroke_width * self.scale;
}
pub fn fill(&mut self) {
self.push_element(Method::Fill);
}
pub fn stroke(&mut self) {
self.push_element(Method::Stroke(self.stroke_width));
}
pub fn set_shader(&mut self, shader: Shader) {
self.shader = shader;
}
fn push_element(&mut self, raster_method: Method) {
let mut path = Builder::new();
std::mem::swap(&mut self.path, &mut path);
self.elements.push(Element {
path,
color: self.color,
shader: self.shader.clone(),
raster_method,
});
}
}
impl IntoIterator for Canvas {
type Item = Element;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.elements.into_iter()
}
}