1 | import { __extends } from "tslib";
|
2 | import Path from '../graphic/Path.js';
|
3 | import PathProxy from '../core/PathProxy.js';
|
4 | import transformPath from './transformPath.js';
|
5 | import { extend } from '../core/util.js';
|
6 | var mathSqrt = Math.sqrt;
|
7 | var mathSin = Math.sin;
|
8 | var mathCos = Math.cos;
|
9 | var PI = Math.PI;
|
10 | function vMag(v) {
|
11 | return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
|
12 | }
|
13 | ;
|
14 | function vRatio(u, v) {
|
15 | return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));
|
16 | }
|
17 | ;
|
18 | function vAngle(u, v) {
|
19 | return (u[0] * v[1] < u[1] * v[0] ? -1 : 1)
|
20 | * Math.acos(vRatio(u, v));
|
21 | }
|
22 | ;
|
23 | function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) {
|
24 | var psi = psiDeg * (PI / 180.0);
|
25 | var xp = mathCos(psi) * (x1 - x2) / 2.0
|
26 | + mathSin(psi) * (y1 - y2) / 2.0;
|
27 | var yp = -1 * mathSin(psi) * (x1 - x2) / 2.0
|
28 | + mathCos(psi) * (y1 - y2) / 2.0;
|
29 | var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
|
30 | if (lambda > 1) {
|
31 | rx *= mathSqrt(lambda);
|
32 | ry *= mathSqrt(lambda);
|
33 | }
|
34 | var f = (fa === fs ? -1 : 1)
|
35 | * mathSqrt((((rx * rx) * (ry * ry))
|
36 | - ((rx * rx) * (yp * yp))
|
37 | - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp)
|
38 | + (ry * ry) * (xp * xp))) || 0;
|
39 | var cxp = f * rx * yp / ry;
|
40 | var cyp = f * -ry * xp / rx;
|
41 | var cx = (x1 + x2) / 2.0
|
42 | + mathCos(psi) * cxp
|
43 | - mathSin(psi) * cyp;
|
44 | var cy = (y1 + y2) / 2.0
|
45 | + mathSin(psi) * cxp
|
46 | + mathCos(psi) * cyp;
|
47 | var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]);
|
48 | var u = [(xp - cxp) / rx, (yp - cyp) / ry];
|
49 | var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
|
50 | var dTheta = vAngle(u, v);
|
51 | if (vRatio(u, v) <= -1) {
|
52 | dTheta = PI;
|
53 | }
|
54 | if (vRatio(u, v) >= 1) {
|
55 | dTheta = 0;
|
56 | }
|
57 | if (dTheta < 0) {
|
58 | var n = Math.round(dTheta / PI * 1e6) / 1e6;
|
59 | dTheta = PI * 2 + (n % 2) * PI;
|
60 | }
|
61 | path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs);
|
62 | }
|
63 | var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig;
|
64 | var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;
|
65 | function createPathProxyFromString(data) {
|
66 | var path = new PathProxy();
|
67 | if (!data) {
|
68 | return path;
|
69 | }
|
70 | var cpx = 0;
|
71 | var cpy = 0;
|
72 | var subpathX = cpx;
|
73 | var subpathY = cpy;
|
74 | var prevCmd;
|
75 | var CMD = PathProxy.CMD;
|
76 | var cmdList = data.match(commandReg);
|
77 | if (!cmdList) {
|
78 | return path;
|
79 | }
|
80 | for (var l = 0; l < cmdList.length; l++) {
|
81 | var cmdText = cmdList[l];
|
82 | var cmdStr = cmdText.charAt(0);
|
83 | var cmd = void 0;
|
84 | var p = cmdText.match(numberReg) || [];
|
85 | var pLen = p.length;
|
86 | for (var i = 0; i < pLen; i++) {
|
87 | p[i] = parseFloat(p[i]);
|
88 | }
|
89 | var off = 0;
|
90 | while (off < pLen) {
|
91 | var ctlPtx = void 0;
|
92 | var ctlPty = void 0;
|
93 | var rx = void 0;
|
94 | var ry = void 0;
|
95 | var psi = void 0;
|
96 | var fa = void 0;
|
97 | var fs = void 0;
|
98 | var x1 = cpx;
|
99 | var y1 = cpy;
|
100 | var len = void 0;
|
101 | var pathData = void 0;
|
102 | switch (cmdStr) {
|
103 | case 'l':
|
104 | cpx += p[off++];
|
105 | cpy += p[off++];
|
106 | cmd = CMD.L;
|
107 | path.addData(cmd, cpx, cpy);
|
108 | break;
|
109 | case 'L':
|
110 | cpx = p[off++];
|
111 | cpy = p[off++];
|
112 | cmd = CMD.L;
|
113 | path.addData(cmd, cpx, cpy);
|
114 | break;
|
115 | case 'm':
|
116 | cpx += p[off++];
|
117 | cpy += p[off++];
|
118 | cmd = CMD.M;
|
119 | path.addData(cmd, cpx, cpy);
|
120 | subpathX = cpx;
|
121 | subpathY = cpy;
|
122 | cmdStr = 'l';
|
123 | break;
|
124 | case 'M':
|
125 | cpx = p[off++];
|
126 | cpy = p[off++];
|
127 | cmd = CMD.M;
|
128 | path.addData(cmd, cpx, cpy);
|
129 | subpathX = cpx;
|
130 | subpathY = cpy;
|
131 | cmdStr = 'L';
|
132 | break;
|
133 | case 'h':
|
134 | cpx += p[off++];
|
135 | cmd = CMD.L;
|
136 | path.addData(cmd, cpx, cpy);
|
137 | break;
|
138 | case 'H':
|
139 | cpx = p[off++];
|
140 | cmd = CMD.L;
|
141 | path.addData(cmd, cpx, cpy);
|
142 | break;
|
143 | case 'v':
|
144 | cpy += p[off++];
|
145 | cmd = CMD.L;
|
146 | path.addData(cmd, cpx, cpy);
|
147 | break;
|
148 | case 'V':
|
149 | cpy = p[off++];
|
150 | cmd = CMD.L;
|
151 | path.addData(cmd, cpx, cpy);
|
152 | break;
|
153 | case 'C':
|
154 | cmd = CMD.C;
|
155 | path.addData(cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]);
|
156 | cpx = p[off - 2];
|
157 | cpy = p[off - 1];
|
158 | break;
|
159 | case 'c':
|
160 | cmd = CMD.C;
|
161 | path.addData(cmd, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy);
|
162 | cpx += p[off - 2];
|
163 | cpy += p[off - 1];
|
164 | break;
|
165 | case 'S':
|
166 | ctlPtx = cpx;
|
167 | ctlPty = cpy;
|
168 | len = path.len();
|
169 | pathData = path.data;
|
170 | if (prevCmd === CMD.C) {
|
171 | ctlPtx += cpx - pathData[len - 4];
|
172 | ctlPty += cpy - pathData[len - 3];
|
173 | }
|
174 | cmd = CMD.C;
|
175 | x1 = p[off++];
|
176 | y1 = p[off++];
|
177 | cpx = p[off++];
|
178 | cpy = p[off++];
|
179 | path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
|
180 | break;
|
181 | case 's':
|
182 | ctlPtx = cpx;
|
183 | ctlPty = cpy;
|
184 | len = path.len();
|
185 | pathData = path.data;
|
186 | if (prevCmd === CMD.C) {
|
187 | ctlPtx += cpx - pathData[len - 4];
|
188 | ctlPty += cpy - pathData[len - 3];
|
189 | }
|
190 | cmd = CMD.C;
|
191 | x1 = cpx + p[off++];
|
192 | y1 = cpy + p[off++];
|
193 | cpx += p[off++];
|
194 | cpy += p[off++];
|
195 | path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
|
196 | break;
|
197 | case 'Q':
|
198 | x1 = p[off++];
|
199 | y1 = p[off++];
|
200 | cpx = p[off++];
|
201 | cpy = p[off++];
|
202 | cmd = CMD.Q;
|
203 | path.addData(cmd, x1, y1, cpx, cpy);
|
204 | break;
|
205 | case 'q':
|
206 | x1 = p[off++] + cpx;
|
207 | y1 = p[off++] + cpy;
|
208 | cpx += p[off++];
|
209 | cpy += p[off++];
|
210 | cmd = CMD.Q;
|
211 | path.addData(cmd, x1, y1, cpx, cpy);
|
212 | break;
|
213 | case 'T':
|
214 | ctlPtx = cpx;
|
215 | ctlPty = cpy;
|
216 | len = path.len();
|
217 | pathData = path.data;
|
218 | if (prevCmd === CMD.Q) {
|
219 | ctlPtx += cpx - pathData[len - 4];
|
220 | ctlPty += cpy - pathData[len - 3];
|
221 | }
|
222 | cpx = p[off++];
|
223 | cpy = p[off++];
|
224 | cmd = CMD.Q;
|
225 | path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
|
226 | break;
|
227 | case 't':
|
228 | ctlPtx = cpx;
|
229 | ctlPty = cpy;
|
230 | len = path.len();
|
231 | pathData = path.data;
|
232 | if (prevCmd === CMD.Q) {
|
233 | ctlPtx += cpx - pathData[len - 4];
|
234 | ctlPty += cpy - pathData[len - 3];
|
235 | }
|
236 | cpx += p[off++];
|
237 | cpy += p[off++];
|
238 | cmd = CMD.Q;
|
239 | path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
|
240 | break;
|
241 | case 'A':
|
242 | rx = p[off++];
|
243 | ry = p[off++];
|
244 | psi = p[off++];
|
245 | fa = p[off++];
|
246 | fs = p[off++];
|
247 | x1 = cpx, y1 = cpy;
|
248 | cpx = p[off++];
|
249 | cpy = p[off++];
|
250 | cmd = CMD.A;
|
251 | processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);
|
252 | break;
|
253 | case 'a':
|
254 | rx = p[off++];
|
255 | ry = p[off++];
|
256 | psi = p[off++];
|
257 | fa = p[off++];
|
258 | fs = p[off++];
|
259 | x1 = cpx, y1 = cpy;
|
260 | cpx += p[off++];
|
261 | cpy += p[off++];
|
262 | cmd = CMD.A;
|
263 | processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);
|
264 | break;
|
265 | }
|
266 | }
|
267 | if (cmdStr === 'z' || cmdStr === 'Z') {
|
268 | cmd = CMD.Z;
|
269 | path.addData(cmd);
|
270 | cpx = subpathX;
|
271 | cpy = subpathY;
|
272 | }
|
273 | prevCmd = cmd;
|
274 | }
|
275 | path.toStatic();
|
276 | return path;
|
277 | }
|
278 | var SVGPath = (function (_super) {
|
279 | __extends(SVGPath, _super);
|
280 | function SVGPath() {
|
281 | return _super !== null && _super.apply(this, arguments) || this;
|
282 | }
|
283 | SVGPath.prototype.applyTransform = function (m) { };
|
284 | return SVGPath;
|
285 | }(Path));
|
286 | function isPathProxy(path) {
|
287 | return path.setData != null;
|
288 | }
|
289 | function createPathOptions(str, opts) {
|
290 | var pathProxy = createPathProxyFromString(str);
|
291 | var innerOpts = extend({}, opts);
|
292 | innerOpts.buildPath = function (path) {
|
293 | if (isPathProxy(path)) {
|
294 | path.setData(pathProxy.data);
|
295 | var ctx = path.getContext();
|
296 | if (ctx) {
|
297 | path.rebuildPath(ctx, 1);
|
298 | }
|
299 | }
|
300 | else {
|
301 | var ctx = path;
|
302 | pathProxy.rebuildPath(ctx, 1);
|
303 | }
|
304 | };
|
305 | innerOpts.applyTransform = function (m) {
|
306 | transformPath(pathProxy, m);
|
307 | this.dirtyShape();
|
308 | };
|
309 | return innerOpts;
|
310 | }
|
311 | export function createFromString(str, opts) {
|
312 | return new SVGPath(createPathOptions(str, opts));
|
313 | }
|
314 | export function extendFromString(str, defaultOpts) {
|
315 | var innerOpts = createPathOptions(str, defaultOpts);
|
316 | var Sub = (function (_super) {
|
317 | __extends(Sub, _super);
|
318 | function Sub(opts) {
|
319 | var _this = _super.call(this, opts) || this;
|
320 | _this.applyTransform = innerOpts.applyTransform;
|
321 | _this.buildPath = innerOpts.buildPath;
|
322 | return _this;
|
323 | }
|
324 | return Sub;
|
325 | }(SVGPath));
|
326 | return Sub;
|
327 | }
|
328 | export function mergePath(pathEls, opts) {
|
329 | var pathList = [];
|
330 | var len = pathEls.length;
|
331 | for (var i = 0; i < len; i++) {
|
332 | var pathEl = pathEls[i];
|
333 | pathList.push(pathEl.getUpdatedPathProxy(true));
|
334 | }
|
335 | var pathBundle = new Path(opts);
|
336 | pathBundle.createPathProxy();
|
337 | pathBundle.buildPath = function (path) {
|
338 | if (isPathProxy(path)) {
|
339 | path.appendPath(pathList);
|
340 | var ctx = path.getContext();
|
341 | if (ctx) {
|
342 | path.rebuildPath(ctx, 1);
|
343 | }
|
344 | }
|
345 | };
|
346 | return pathBundle;
|
347 | }
|
348 | export function clonePath(sourcePath, opts) {
|
349 | opts = opts || {};
|
350 | var path = new Path();
|
351 | if (sourcePath.shape) {
|
352 | path.setShape(sourcePath.shape);
|
353 | }
|
354 | path.setStyle(sourcePath.style);
|
355 | if (opts.bakeTransform) {
|
356 | transformPath(path.path, sourcePath.getComputedTransform());
|
357 | }
|
358 | else {
|
359 | if (opts.toLocal) {
|
360 | path.setLocalTransform(sourcePath.getComputedTransform());
|
361 | }
|
362 | else {
|
363 | path.copyTransform(sourcePath);
|
364 | }
|
365 | }
|
366 | path.buildPath = sourcePath.buildPath;
|
367 | path.applyTransform = path.applyTransform;
|
368 | path.z = sourcePath.z;
|
369 | path.z2 = sourcePath.z2;
|
370 | path.zlevel = sourcePath.zlevel;
|
371 | return path;
|
372 | }
|