1use alloc::vec::Vec;
16
17use super::path::{zf, Path};
18use super::raster::Raster;
19use super::{Dc, Surface, CAP_BUTT, CAP_ROUND, CAP_SQUARE, JOIN_MITER, JOIN_ROUND};
20use rt::fx::{maxss, minss, sqrt};
21
22const EPS: f32 = 0.0001;
23
24struct St<'a> {
25 hw: f32,
26 p: (f32, f32),
27 di: (f32, f32),
28 dout: (f32, f32),
29 cs: f32,
30 sn: f32,
31 join: u32,
32 cap: u32,
33 pts: &'a [(f32, f32)],
34 base: usize,
35 n: usize,
36 v: (f32, f32),
37 t: (f32, f32),
38 spts: Vec<(f32, f32)>,
39}
40
41impl St<'_> {
42 fn pt(&self, i: usize) -> (f32, f32) {
43 self.pts[self.base + i]
44 }
45
46 fn dir(&self, i: usize, j: usize) -> (f32, f32) {
48 let a = self.pt(i);
49 let b = self.pt(j);
50 let dx = b.0 - a.0;
51 let dy = b.1 - a.1;
52 let len = sqrt(dx * dx + dy * dy);
53 if zf(len, 0.0) {
54 return (1.0, 0.0);
55 }
56 (dx / len, dy / len)
57 }
58
59 fn add(&mut self, x: f32, y: f32) {
61 if let Some(&l) = self.spts.last() {
62 if zf(x, l.0) && zf(y, l.1) {
63 return;
64 }
65 }
66 self.spts.push((x, y));
67 }
68
69 fn emit_off(&mut self, sign: f32, d: (f32, f32)) {
71 let x = d.1 * self.hw * sign + self.p.0;
72 let y = (0.0 - d.0) * self.hw * sign + self.p.1;
73 self.add(x, y);
74 }
75
76 fn join(&mut self) {
78 let cross = self.di.0 * self.dout.1 - self.di.1 * self.dout.0;
79 let dot = self.di.0 * self.dout.0 + self.di.1 * self.dout.1;
80 if !(cross.abs() >= EPS) && dot >= 0.0 {
81 let d = self.dout;
82 self.emit_off(1.0, d); return;
84 }
85 if !(cross >= 0.0) {
86 let di = self.di;
88 self.emit_off(1.0, di);
89 let p = self.p;
90 self.add(p.0, p.1);
91 let d = self.dout;
92 self.emit_off(1.0, d);
93 return;
94 }
95 let di = self.di;
96 self.emit_off(1.0, di);
97 if self.join == JOIN_ROUND {
98 self.v = (self.di.1, 0.0 - self.di.0);
99 self.t = (self.dout.1, 0.0 - self.dout.0);
100 self.arc();
101 } else if self.join == JOIN_MITER {
102 let m = dot + 1.0;
103 if m >= 0.125 {
104 let nx = self.di.1 + self.dout.1;
106 let ny = 0.0 - (self.di.0 + self.dout.0);
107 let k = self.hw / m;
108 let p = self.p;
109 self.add(nx * k + p.0, ny * k + p.1);
110 }
111 }
112 let d = self.dout;
113 self.emit_off(1.0, d);
114 }
115
116 fn arc(&mut self) {
118 for _ in 0..64 {
119 let nx = self.v.0 * self.cs - self.v.1 * self.sn;
120 let ny = self.v.0 * self.sn + self.v.1 * self.cs;
121 if !(nx * self.t.1 - ny * self.t.0 >= EPS) {
122 return;
123 }
124 self.v = (nx, ny);
125 let p = self.p;
126 self.add(nx * self.hw + p.0, ny * self.hw + p.1);
127 }
128 }
129
130 fn cap(&mut self, d: (f32, f32)) {
132 let (dx, dy) = d;
133 if self.cap == CAP_SQUARE {
134 let p = self.p;
135 self.add((dy + dx) * self.hw + p.0, (dy - dx) * self.hw + p.1);
136 self.add((dx - dy) * self.hw + p.0, (dy + dx) * self.hw + p.1);
137 } else if self.cap == CAP_ROUND {
138 self.v = (dy, 0.0 - dx);
139 self.t = (dx, dy);
140 self.arc();
141 let p = self.p;
142 self.add(dx * self.hw + p.0, dy * self.hw + p.1);
143 self.v = (dx, dy);
144 self.t = (0.0 - dy, dx);
145 self.arc();
146 }
147 self.emit_off(-1.0, d);
148 }
149
150 fn flush(&mut self, ras: &mut Raster) {
152 let n = self.spts.len();
153 if n >= 2 {
154 for i in 0..n {
155 let a = self.spts[i];
156 let b = self.spts[if i + 1 < n { i + 1 } else { 0 }];
157 ras.emit_line(a.0, a.1, b.0, b.1);
158 }
159 }
160 self.spts.clear();
161 }
162
163 fn open(&mut self, ras: &mut Raster) {
165 self.spts.clear();
166 let last = self.n - 1;
167 let d0 = self.dir(0, 1);
168 self.p = self.pt(0);
169 self.emit_off(1.0, d0);
170 for i in 1..last {
171 self.di = self.dir(i - 1, i);
172 self.dout = self.dir(i, i + 1);
173 self.p = self.pt(i);
174 self.join();
175 }
176 let dl = self.dir(last - 1, last);
177 self.p = self.pt(last);
178 self.emit_off(1.0, dl);
179 self.cap(dl);
180 let mut i = last as isize - 1;
181 while i >= 1 {
182 let k = i as usize;
183 self.di = self.dir(k + 1, k);
184 self.dout = self.dir(k, k - 1);
185 self.p = self.pt(k);
186 self.join();
187 i -= 1;
188 }
189 self.p = self.pt(0);
190 let back = (0.0 - d0.0, 0.0 - d0.1);
191 self.emit_off(1.0, back);
192 self.cap(back);
193 self.flush(ras);
194 }
195
196 fn closed(&mut self, ras: &mut Raster) {
198 let n = self.n;
199 if n < 2 {
200 return;
201 }
202 self.spts.clear();
203 for i in 0..n {
204 self.di = self.dir((i + n - 1) % n, i);
205 self.dout = self.dir(i, (i + 1) % n);
206 self.p = self.pt(i);
207 self.join();
208 }
209 self.flush(ras);
210 self.spts.clear();
211 for i in (0..n).rev() {
212 self.di = self.dir((i + 1) % n, i);
213 self.dout = self.dir(i, (i + n - 1) % n);
214 self.p = self.pt(i);
215 self.join();
216 }
217 self.flush(ras);
218 }
219
220 fn dot(&mut self, ras: &mut Raster) {
222 self.p = self.pt(0);
223 if self.cap == CAP_BUTT {
224 return;
225 }
226 self.spts.clear();
227 self.emit_off(1.0, (1.0, 0.0));
228 self.cap((1.0, 0.0));
229 self.cap((-1.0, 0.0));
230 self.flush(ras);
231 }
232}
233
234impl Path {
235 pub fn stroke_lines(&self, ras: &mut Raster, width: i32, style: u32) {
238 let hw = maxss(width as f32 * 0.001953125, 0.25); let mut s = sqrt(0.4 / hw);
241 s = s + s;
242 let s = minss(s, 0.5);
243 let s2 = s * s;
244 let cs = (s2 * 0.041666668 - 0.5) * s2 + 1.0;
245 let sn = ((s2 * 0.008333334 - 0.16666667) * s2 + 1.0) * s;
246 let mut st = St {
247 hw,
248 p: (0.0, 0.0),
249 di: (0.0, 0.0),
250 dout: (0.0, 0.0),
251 cs,
252 sn,
253 join: style & 15,
254 cap: (style >> 4) & 15,
255 pts: &self.pts,
256 base: 0,
257 n: 0,
258 v: (0.0, 0.0),
259 t: (0.0, 0.0),
260 spts: Vec::new(),
261 };
262 ras.lines_begin();
263 for sub in &self.subs {
264 let mut n = sub.count;
265 if n == 0 {
266 continue;
267 }
268 st.base = sub.start;
269 if n >= 2 && sub.closed {
271 let a = self.pts[sub.start];
272 let b = self.pts[sub.start + n - 1];
273 if zf(a.0, b.0) && zf(a.1, b.1) {
274 n -= 1;
275 }
276 }
277 st.n = n;
278 if n == 1 {
279 st.dot(ras);
280 } else if sub.closed {
281 st.closed(ras);
282 } else {
283 st.open(ras);
284 }
285 }
286 }
287
288 pub fn stroke(&self, ras: &mut Raster, dc: &Dc, sf: &mut Surface, width: i32, style: u32) {
290 self.stroke_lines(ras, width, style);
291 ras.fill(dc, sf, 0);
292 }
293}