1use super::*;
2
3#[derive(Clone, Debug, PartialEq)]
5pub struct Pen<T> {
6 pub template: T,
8}
9
10impl<V: TVertex, U: TUniform> DrawBuilder<V, U> {
11 #[inline(never)]
13 pub fn draw_line<T: ToVertex<V>>(&mut self, pen: &Pen<T>, a: Point2f, b: Point2f) {
14 let vertices = [
15 pen.template.to_vertex(a, 0),
16 pen.template.to_vertex(b, 1),
17 ];
18 let mut cv = self.begin(PrimType::Lines, 2, 1);
19 cv.add_index2(0, 1);
20 cv.add_vertices(&vertices);
21 }
22
23 #[inline(never)]
25 pub fn draw_lines<T: ToVertex<V>>(&mut self, pen: &Pen<T>, pts: &[Point2f], lines: &[(u32, u32)]) {
26 let mut cv = self.begin(PrimType::Lines, pts.len(), lines.len());
27 for i in 0..lines.len() {
28 cv.add_index2(lines[i].0, lines[i].1);
29 }
30 for i in 0..pts.len() {
31 cv.add_vertex(pen.template.to_vertex(pts[i], i));
32 }
33 }
34
35 #[inline(never)]
37 pub fn draw_line_rect<T: ToVertex<V>>(&mut self, pen: &Pen<T>, rc: &Bounds2f) {
38 let vertices = [
39 pen.template.to_vertex(rc.bottom_left(), 0),
40 pen.template.to_vertex(rc.top_left(), 1),
41 pen.template.to_vertex(rc.top_right(), 2),
42 pen.template.to_vertex(rc.bottom_right(), 3),
43 ];
44 let mut cv = self.begin(PrimType::Lines, 4, 4);
45 cv.add_indices(&[0, 1, 1, 2, 2, 3, 3, 0]);
46 cv.add_vertices(&vertices);
47 }
48
49 #[inline(never)]
51 pub fn draw_round_rect<T: ToVertex<V>>(&mut self, pen: &Pen<T>, rc: &Bounds2f, sx: f32, sy: f32, _segments: i32) {
52 let sx = if sx + sx > rc.width() { rc.width() * 0.5 } else { sx };
54 let sy = if sy + sy > rc.height() { rc.height() * 0.5 } else { sy };
55
56 if sx <= 0.0 || sy <= 0.0 {
58 return self.draw_line_rect(pen, rc);
59 }
60
61 unimplemented!()
66 }
67
68 pub fn draw_arrow<T: ToVertex<V>>(&mut self, pen: &Pen<T>, start: Point2f, end: Point2f, head: f32) {
70 let pth = (end - start).resize(head);
71 let pta = (end - pth) + pth.ccw() * 0.5;
72 let ptb = (end - pth) + pth.cw() * 0.5;
73 let vertices = [
74 pen.template.to_vertex(start, 0),
75 pen.template.to_vertex(end, 1),
76 pen.template.to_vertex(pta, 2),
77 pen.template.to_vertex(ptb, 3),
78 ];
79 let mut cv = self.begin(PrimType::Lines, 4, 3);
80 cv.add_indices(&[0, 1, 2, 1, 3, 1]);
81 cv.add_vertices(&vertices);
82 }
83
84 #[inline(never)]
86 pub fn draw_poly_line<T: ToVertex<V>>(&mut self, pen: &Pen<T>, pts: &[Point2f], close: bool) {
87 if pts.len() < 2 {
89 return;
90 }
91 let n = pts.len() - (!close) as usize;
94 let mut cv = self.begin(PrimType::Lines, pts.len(), n);
95 for i in 0..pts.len() - 1 {
97 cv.add_index2(i as u32, (i + 1) as u32);
98 }
99 if close {
100 cv.add_index2((pts.len() - 1) as u32, 0);
101 }
102 for v in 0..pts.len() {
104 cv.add_vertex(pen.template.to_vertex(pts[v], v));
105 }
106 }
107
108 #[inline(never)]
110 pub fn draw_ellipse<T: ToVertex<V>>(&mut self, pen: &Pen<T>, rc: &Bounds2f, segments: i32) {
111 let n = cmp::max(3, segments) as usize;
113 let mut cv = self.begin(PrimType::Lines, n, n);
114
115 for i in 0..n - 1 {
117 cv.add_index2(i as u32, (i + 1) as u32);
118 }
119 cv.add_index2((n - 1) as u32, 0);
120
121 let (s, c) = (Angle::TURN / (n as i32 as f32)).sin_cos();
123 let radius = rc.size() * 0.5;
124 let center = rc.top_left() + radius;
125 let mut pt = Point2(1.0, 0.0);
126
127 for v in 0..n {
130 cv.add_vertex(pen.template.to_vertex(center + pt * radius, v));
131 let x = pt.x;
133 pt.x = c * x - s * pt.y;
134 pt.y = s * x + c * pt.y;
135 }
136 }
137
138 #[inline(never)]
140 pub fn draw_arc<T: ToVertex<V>>(&mut self, pen: &Pen<T>, rc: &Bounds2f, start: Angle<f32>, sweep: Angle<f32>, segments: i32) {
141 if sweep <= -Angle::TURN || sweep >= Angle::TURN {
142 return self.draw_ellipse(pen, rc, segments);
143 }
144
145 let n = cmp::max(2, segments) as usize;
147 let mut cv = self.begin(PrimType::Lines, n + 1, n);
148
149 for i in 0..n {
151 cv.add_index2(i as u32, (i + 1) as u32);
152 }
153
154 let (s, c) = (sweep / (n as i32 as f32)).sin_cos();
156 let radius = rc.size() * 0.5;
157 let center = rc.top_left() + radius;
158 let mut pt = {
159 let (y, x) = start.sin_cos();
160 Point2(x, y)
161 };
162
163 for v in 0..n + 1 {
166 cv.add_vertex(pen.template.to_vertex(center + pt * radius, v));
167 let x = pt.x;
169 pt.x = c * x - s * pt.y;
170 pt.y = s * x + c * pt.y;
171 }
172 }
173
174 #[inline(never)]
175 pub fn draw_bezier2<T: ToVertex<V>>(&mut self, pen: &Pen<T>, pts: &[Point2f; 3], segments: i32) {
176 let n = cmp::max(2, segments) as usize;
178 let mut cv = self.begin(PrimType::Lines, n + 1, n);
179
180 for i in 0..n {
182 cv.add_index2(i as u32, (i + 1) as u32);
183 }
184
185 for v in 0..n + 1 {
187 let pt = curve::bezier2(v as i32 as f32 / n as i32 as f32, pts[0], pts[1], pts[2]);
188 cv.add_vertex(pen.template.to_vertex(pt, v));
189 }
190 }
191
192 #[inline(never)]
193 pub fn draw_bezier3<T: ToVertex<V>>(&mut self, pen: &Pen<T>, pts: &[Point2f; 4], segments: i32) {
194 let n = cmp::max(2, segments) as usize;
196 let mut cv = self.begin(PrimType::Lines, n + 1, n);
197
198 for i in 0..n {
200 cv.add_index2(i as u32, (i + 1) as u32);
201 }
202
203 for v in 0..n + 1 {
205 let pt = curve::bezier3(v as i32 as f32 / n as i32 as f32, pts[0], pts[1], pts[2], pts[3]);
206 cv.add_vertex(pen.template.to_vertex(pt, v));
207 }
208 }
209
210 #[inline(never)]
211 pub fn draw_cspline<T: ToVertex<V>>(&mut self, pen: &Pen<T>, pts: &[Point2f], tension: f32, segments: i32) {
212 if pts.len() < 2 {
214 return;
215 }
216
217 let mut u = Point2::ZERO;
219 let mut v;
220 let tension = (1.0 - tension) * 0.5;
221
222 for i in 0..pts.len() - 1 {
223 v = if i == pts.len() - 2 {
225 Point2::ZERO
227 }
228 else {
229 (pts[i + 2] - pts[i]) * tension
230 };
231 let curve = [
232 pts[i],
233 pts[i] + u * (1.0 / 3.0),
234 pts[i + 1] - v * (1.0 / 3.0),
235 pts[i + 1],
236 ];
237 self.draw_bezier3(pen, &curve, segments);
238 u = v;
239 }
240 }
241}