modern-path2d 1.4.16 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2292 -2098
- package/dist/index.d.cts +169 -72
- package/dist/index.d.mts +169 -72
- package/dist/index.d.ts +169 -72
- package/dist/index.js +16 -17
- package/dist/index.mjs +2287 -2098
- package/package.json +9 -9
package/dist/index.mjs
CHANGED
|
@@ -43,9 +43,10 @@ function setCanvasContext(ctx, style) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
class Vector2 {
|
|
46
|
-
constructor(
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
46
|
+
constructor(_x = 0, _y = 0, _onUpdate) {
|
|
47
|
+
this._x = _x;
|
|
48
|
+
this._y = _y;
|
|
49
|
+
this._onUpdate = _onUpdate;
|
|
49
50
|
}
|
|
50
51
|
static get MAX() {
|
|
51
52
|
return new Vector2(Infinity, Infinity);
|
|
@@ -53,141 +54,173 @@ class Vector2 {
|
|
|
53
54
|
static get MIN() {
|
|
54
55
|
return new Vector2(-Infinity, -Infinity);
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
-
return
|
|
57
|
+
static lerp(a, b, t) {
|
|
58
|
+
return new Vector2(b.x, b.y).clone().sub(a).multiply(t).add(a);
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.y = Number.isFinite(this.y) ? this.y : 0;
|
|
62
|
-
return this;
|
|
60
|
+
get width() {
|
|
61
|
+
return this.x;
|
|
63
62
|
}
|
|
64
|
-
set(
|
|
65
|
-
this.x =
|
|
66
|
-
this.y = y;
|
|
67
|
-
return this;
|
|
63
|
+
set width(val) {
|
|
64
|
+
this.x = val;
|
|
68
65
|
}
|
|
69
|
-
|
|
70
|
-
this.
|
|
71
|
-
this.y += vec.y;
|
|
72
|
-
return this;
|
|
66
|
+
get height() {
|
|
67
|
+
return this.y;
|
|
73
68
|
}
|
|
74
|
-
|
|
75
|
-
this.
|
|
76
|
-
this.y -= vec.y;
|
|
77
|
-
return this;
|
|
69
|
+
set height(val) {
|
|
70
|
+
this.y = val;
|
|
78
71
|
}
|
|
79
|
-
|
|
80
|
-
this.x
|
|
81
|
-
this.y *= vec.y;
|
|
82
|
-
return this;
|
|
72
|
+
get left() {
|
|
73
|
+
return this.x;
|
|
83
74
|
}
|
|
84
|
-
|
|
85
|
-
this.x
|
|
86
|
-
this.y /= vec.y;
|
|
87
|
-
return this;
|
|
75
|
+
set left(val) {
|
|
76
|
+
this.x = val;
|
|
88
77
|
}
|
|
89
|
-
|
|
90
|
-
return this.
|
|
78
|
+
get top() {
|
|
79
|
+
return this.y;
|
|
91
80
|
}
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
set top(val) {
|
|
82
|
+
this.y = val;
|
|
94
83
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
84
|
+
get x() {
|
|
85
|
+
return this._x;
|
|
86
|
+
}
|
|
87
|
+
set x(value) {
|
|
88
|
+
if (this._x !== value) {
|
|
89
|
+
this._x = value;
|
|
90
|
+
this._onUpdate?.(this);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
get y() {
|
|
94
|
+
return this._y;
|
|
95
|
+
}
|
|
96
|
+
set y(value) {
|
|
97
|
+
if (this._y !== value) {
|
|
98
|
+
this._y = value;
|
|
99
|
+
this._onUpdate?.(this);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
set(x = 0, y = x) {
|
|
103
|
+
if (this._x !== x || this._y !== y) {
|
|
104
|
+
this._x = x;
|
|
105
|
+
this._y = y;
|
|
106
|
+
this._onUpdate?.(this);
|
|
107
|
+
}
|
|
105
108
|
return this;
|
|
106
109
|
}
|
|
107
|
-
|
|
108
|
-
return
|
|
110
|
+
add(p) {
|
|
111
|
+
return this.set(this._x + p.x, this._y + p.y);
|
|
109
112
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const dy = this.y - vec.y;
|
|
113
|
-
return dx * dx + dy * dy;
|
|
113
|
+
sub(p) {
|
|
114
|
+
return this.set(this._x - p.x, this._y - p.y);
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
-
return this.x
|
|
116
|
+
subVectors(a, b) {
|
|
117
|
+
return this.set(a.x - b.x, a.y - b.y);
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
-
return
|
|
119
|
+
multiply(x = 0, y = x) {
|
|
120
|
+
return this.set(this._x * x, this._y * y);
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const y = sy < 0 ? target.y - this.y + target.y : this.y;
|
|
124
|
-
this.x = x * Math.abs(sx);
|
|
125
|
-
this.y = y * Math.abs(sy);
|
|
126
|
-
return this;
|
|
122
|
+
divide(x = 0, y = x) {
|
|
123
|
+
return this.set(this._x / x, this._y / y);
|
|
127
124
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const dy = this.y - target.y;
|
|
131
|
-
this.x = target.x + (dx + Math.tan(ax) * dy);
|
|
132
|
-
this.y = target.y + (dy + Math.tan(ay) * dx);
|
|
133
|
-
return this;
|
|
125
|
+
cross(p) {
|
|
126
|
+
return this._x * p.y - this._y * p.x;
|
|
134
127
|
}
|
|
135
|
-
|
|
136
|
-
this.
|
|
137
|
-
this.y = Math.min(this.y, ...vecs.map((v) => v.y));
|
|
138
|
-
return this;
|
|
128
|
+
dot(p) {
|
|
129
|
+
return this._x * p.x + this._y * p.y;
|
|
139
130
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
131
|
+
rotate(rad, origin = { x: 0, y: 0 }) {
|
|
132
|
+
const { x, y } = this;
|
|
133
|
+
const cos = Math.cos(rad);
|
|
134
|
+
const sin = Math.sin(rad);
|
|
135
|
+
return this.set(
|
|
136
|
+
(x - origin.x) * cos - (y - origin.y) * sin + origin.x,
|
|
137
|
+
(x - origin.x) * sin + (y - origin.y) * cos + origin.y
|
|
138
|
+
);
|
|
144
139
|
}
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
getLength() {
|
|
141
|
+
const { x, y } = this;
|
|
142
|
+
return Math.sqrt(x * x + y * y);
|
|
147
143
|
}
|
|
148
|
-
|
|
149
|
-
this.x
|
|
150
|
-
this.y = a.y + b.y;
|
|
151
|
-
return this;
|
|
144
|
+
getAngle() {
|
|
145
|
+
return Math.atan2(-this.x, -this.y) + Math.PI;
|
|
152
146
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
this.y = a.y - b.y;
|
|
156
|
-
return this;
|
|
147
|
+
distanceTo(p) {
|
|
148
|
+
return Math.hypot(p.x - this.x, p.y - this.y);
|
|
157
149
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
this.
|
|
150
|
+
normalize() {
|
|
151
|
+
const scalar = 1 / (this.getLength() || 1);
|
|
152
|
+
this.set(this.x * scalar, this.y * scalar);
|
|
161
153
|
return this;
|
|
162
154
|
}
|
|
163
|
-
|
|
164
|
-
this.
|
|
165
|
-
|
|
155
|
+
copyFrom(p) {
|
|
156
|
+
if (this._x !== p.x || this._y !== p.y) {
|
|
157
|
+
this._x = p.x;
|
|
158
|
+
this._y = p.y;
|
|
159
|
+
this._onUpdate?.(this);
|
|
160
|
+
}
|
|
166
161
|
return this;
|
|
167
162
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return this;
|
|
163
|
+
copyTo(p) {
|
|
164
|
+
p.set(this._x, this._y);
|
|
165
|
+
return p;
|
|
172
166
|
}
|
|
173
167
|
equals(vec) {
|
|
174
|
-
return this.
|
|
175
|
-
}
|
|
176
|
-
applyMatrix3(m) {
|
|
177
|
-
const x = this.x;
|
|
178
|
-
const y = this.y;
|
|
179
|
-
const e = m.elements;
|
|
180
|
-
this.x = e[0] * x + e[3] * y + e[6];
|
|
181
|
-
this.y = e[1] * x + e[4] * y + e[7];
|
|
182
|
-
return this;
|
|
168
|
+
return this._x === vec.x && this._y === vec.y;
|
|
183
169
|
}
|
|
184
|
-
|
|
185
|
-
this.x
|
|
186
|
-
this.y = vec.y;
|
|
187
|
-
return this;
|
|
170
|
+
get array() {
|
|
171
|
+
return [this.x, this.y];
|
|
188
172
|
}
|
|
189
|
-
|
|
190
|
-
return
|
|
173
|
+
finite() {
|
|
174
|
+
return this.set(
|
|
175
|
+
Number.isFinite(this._x) ? this._x : 0,
|
|
176
|
+
Number.isFinite(this._y) ? this._y : 0
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
lengthSquared() {
|
|
180
|
+
return this._x * this._x + this._y * this._y;
|
|
181
|
+
}
|
|
182
|
+
length() {
|
|
183
|
+
return Math.sqrt(this.lengthSquared());
|
|
184
|
+
}
|
|
185
|
+
scale(sx, sy = sx, origin = { x: 0, y: 0 }) {
|
|
186
|
+
const x = sx < 0 ? origin.x - this._x + origin.x : this._x;
|
|
187
|
+
const y = sy < 0 ? origin.y - this._y + origin.y : this._y;
|
|
188
|
+
return this.set(
|
|
189
|
+
x * Math.abs(sx),
|
|
190
|
+
y * Math.abs(sy)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
skew(ax, ay = 0, origin = { x: 0, y: 0 }) {
|
|
194
|
+
const dx = this._x - origin.x;
|
|
195
|
+
const dy = this._y - origin.y;
|
|
196
|
+
return this.set(
|
|
197
|
+
origin.x + (dx + Math.tan(ax) * dy),
|
|
198
|
+
origin.y + (dy + Math.tan(ay) * dx)
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
clampMin(...pList) {
|
|
202
|
+
return this.set(
|
|
203
|
+
Math.min(this._x, ...pList.map((v) => v.x)),
|
|
204
|
+
Math.min(this._y, ...pList.map((v) => v.y))
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
clampMax(...pList) {
|
|
208
|
+
return this.set(
|
|
209
|
+
Math.max(this.x, ...pList.map((v) => v.x)),
|
|
210
|
+
Math.max(this.y, ...pList.map((v) => v.y))
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
clone(_onUpdate) {
|
|
214
|
+
return new Vector2(this._x, this._y, _onUpdate ?? this._onUpdate);
|
|
215
|
+
}
|
|
216
|
+
toJSON() {
|
|
217
|
+
return {
|
|
218
|
+
x: this._x,
|
|
219
|
+
y: this._y
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
destroy() {
|
|
223
|
+
this._onUpdate = void 0;
|
|
191
224
|
}
|
|
192
225
|
}
|
|
193
226
|
|
|
@@ -263,2017 +296,2198 @@ class BoundingBox {
|
|
|
263
296
|
}
|
|
264
297
|
}
|
|
265
298
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
0,
|
|
289
|
-
0,
|
|
290
|
-
1,
|
|
291
|
-
0,
|
|
292
|
-
0,
|
|
293
|
-
0,
|
|
294
|
-
1
|
|
299
|
+
function catmullRom(t, p0, p1, p2, p3) {
|
|
300
|
+
const v0 = (p2 - p0) * 0.5;
|
|
301
|
+
const v1 = (p3 - p1) * 0.5;
|
|
302
|
+
const t2 = t * t;
|
|
303
|
+
const t3 = t * t2;
|
|
304
|
+
return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const PI = Math.PI;
|
|
308
|
+
const PI_2 = PI * 2;
|
|
309
|
+
function toKebabCase(str) {
|
|
310
|
+
return str.replace(/[^a-z0-9]/gi, "-").replace(/\B([A-Z])/g, "-$1").toLowerCase();
|
|
311
|
+
}
|
|
312
|
+
function getIntersectionPoint(p1, p2, q1, q2) {
|
|
313
|
+
const r = p2.clone().sub(p1);
|
|
314
|
+
const s = q2.clone().sub(q1);
|
|
315
|
+
const q1p1 = q1.clone().sub(p1);
|
|
316
|
+
const crossRS = r.cross(s);
|
|
317
|
+
if (crossRS === 0) {
|
|
318
|
+
return new Vector2(
|
|
319
|
+
(p1.x + q1.x) / 2,
|
|
320
|
+
(p1.y + q1.y) / 2
|
|
295
321
|
);
|
|
296
|
-
return this;
|
|
297
|
-
}
|
|
298
|
-
copy(m) {
|
|
299
|
-
const te = this.elements;
|
|
300
|
-
const me = m.elements;
|
|
301
|
-
te[0] = me[0];
|
|
302
|
-
te[1] = me[1];
|
|
303
|
-
te[2] = me[2];
|
|
304
|
-
te[3] = me[3];
|
|
305
|
-
te[4] = me[4];
|
|
306
|
-
te[5] = me[5];
|
|
307
|
-
te[6] = me[6];
|
|
308
|
-
te[7] = me[7];
|
|
309
|
-
te[8] = me[8];
|
|
310
|
-
return this;
|
|
311
|
-
}
|
|
312
|
-
multiply(m) {
|
|
313
|
-
return this.multiplyMatrices(this, m);
|
|
314
|
-
}
|
|
315
|
-
premultiply(m) {
|
|
316
|
-
return this.multiplyMatrices(m, this);
|
|
317
|
-
}
|
|
318
|
-
multiplyMatrices(a, b) {
|
|
319
|
-
const ae = a.elements;
|
|
320
|
-
const be = b.elements;
|
|
321
|
-
const te = this.elements;
|
|
322
|
-
const a11 = ae[0];
|
|
323
|
-
const a12 = ae[3];
|
|
324
|
-
const a13 = ae[6];
|
|
325
|
-
const a21 = ae[1];
|
|
326
|
-
const a22 = ae[4];
|
|
327
|
-
const a23 = ae[7];
|
|
328
|
-
const a31 = ae[2];
|
|
329
|
-
const a32 = ae[5];
|
|
330
|
-
const a33 = ae[8];
|
|
331
|
-
const b11 = be[0];
|
|
332
|
-
const b12 = be[3];
|
|
333
|
-
const b13 = be[6];
|
|
334
|
-
const b21 = be[1];
|
|
335
|
-
const b22 = be[4];
|
|
336
|
-
const b23 = be[7];
|
|
337
|
-
const b31 = be[2];
|
|
338
|
-
const b32 = be[5];
|
|
339
|
-
const b33 = be[8];
|
|
340
|
-
te[0] = a11 * b11 + a12 * b21 + a13 * b31;
|
|
341
|
-
te[3] = a11 * b12 + a12 * b22 + a13 * b32;
|
|
342
|
-
te[6] = a11 * b13 + a12 * b23 + a13 * b33;
|
|
343
|
-
te[1] = a21 * b11 + a22 * b21 + a23 * b31;
|
|
344
|
-
te[4] = a21 * b12 + a22 * b22 + a23 * b32;
|
|
345
|
-
te[7] = a21 * b13 + a22 * b23 + a23 * b33;
|
|
346
|
-
te[2] = a31 * b11 + a32 * b21 + a33 * b31;
|
|
347
|
-
te[5] = a31 * b12 + a32 * b22 + a33 * b32;
|
|
348
|
-
te[8] = a31 * b13 + a32 * b23 + a33 * b33;
|
|
349
|
-
return this;
|
|
350
|
-
}
|
|
351
|
-
invert() {
|
|
352
|
-
const te = this.elements;
|
|
353
|
-
const n11 = te[0];
|
|
354
|
-
const n21 = te[1];
|
|
355
|
-
const n31 = te[2];
|
|
356
|
-
const n12 = te[3];
|
|
357
|
-
const n22 = te[4];
|
|
358
|
-
const n32 = te[5];
|
|
359
|
-
const n13 = te[6];
|
|
360
|
-
const n23 = te[7];
|
|
361
|
-
const n33 = te[8];
|
|
362
|
-
const t11 = n33 * n22 - n32 * n23;
|
|
363
|
-
const t12 = n32 * n13 - n33 * n12;
|
|
364
|
-
const t13 = n23 * n12 - n22 * n13;
|
|
365
|
-
const det = n11 * t11 + n21 * t12 + n31 * t13;
|
|
366
|
-
if (det === 0)
|
|
367
|
-
return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
368
|
-
const detInv = 1 / det;
|
|
369
|
-
te[0] = t11 * detInv;
|
|
370
|
-
te[1] = (n31 * n23 - n33 * n21) * detInv;
|
|
371
|
-
te[2] = (n32 * n21 - n31 * n22) * detInv;
|
|
372
|
-
te[3] = t12 * detInv;
|
|
373
|
-
te[4] = (n33 * n11 - n31 * n13) * detInv;
|
|
374
|
-
te[5] = (n31 * n12 - n32 * n11) * detInv;
|
|
375
|
-
te[6] = t13 * detInv;
|
|
376
|
-
te[7] = (n21 * n13 - n23 * n11) * detInv;
|
|
377
|
-
te[8] = (n22 * n11 - n21 * n12) * detInv;
|
|
378
|
-
return this;
|
|
379
|
-
}
|
|
380
|
-
transpose() {
|
|
381
|
-
let tmp;
|
|
382
|
-
const m = this.elements;
|
|
383
|
-
tmp = m[1];
|
|
384
|
-
m[1] = m[3];
|
|
385
|
-
m[3] = tmp;
|
|
386
|
-
tmp = m[2];
|
|
387
|
-
m[2] = m[6];
|
|
388
|
-
m[6] = tmp;
|
|
389
|
-
tmp = m[5];
|
|
390
|
-
m[5] = m[7];
|
|
391
|
-
m[7] = tmp;
|
|
392
|
-
return this;
|
|
393
|
-
}
|
|
394
|
-
scale(sx, sy) {
|
|
395
|
-
this.premultiply(_m3.makeScale(sx, sy));
|
|
396
|
-
return this;
|
|
397
|
-
}
|
|
398
|
-
rotate(theta) {
|
|
399
|
-
this.premultiply(_m3.makeRotation(-theta));
|
|
400
|
-
return this;
|
|
401
|
-
}
|
|
402
|
-
translate(tx, ty) {
|
|
403
|
-
this.premultiply(_m3.makeTranslation(tx, ty));
|
|
404
|
-
return this;
|
|
405
322
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
0,
|
|
412
|
-
1,
|
|
413
|
-
y,
|
|
414
|
-
0,
|
|
415
|
-
0,
|
|
416
|
-
1
|
|
323
|
+
const t = q1p1.cross(s) / crossRS;
|
|
324
|
+
if (Math.abs(t) > 1) {
|
|
325
|
+
return new Vector2(
|
|
326
|
+
(p1.x + q1.x) / 2,
|
|
327
|
+
(p1.y + q1.y) / 2
|
|
417
328
|
);
|
|
418
|
-
return this;
|
|
419
329
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
330
|
+
return new Vector2(
|
|
331
|
+
p1.x + t * r.x,
|
|
332
|
+
p1.y + t * r.y
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const FUNCTIONS_RE = /([\w-]+)\((.+?)\)/g;
|
|
337
|
+
const ARGS_RE = /[^,]+/g;
|
|
338
|
+
const ARG_RE = /([-e.\d]+)(.*)/;
|
|
339
|
+
function parseCssFunctions(propertyValue, context = {}) {
|
|
340
|
+
const functions = [];
|
|
341
|
+
let match;
|
|
342
|
+
while ((match = FUNCTIONS_RE.exec(propertyValue)) !== null) {
|
|
343
|
+
const [, name, value] = match;
|
|
344
|
+
if (name) {
|
|
345
|
+
functions.push({
|
|
346
|
+
name,
|
|
347
|
+
args: parseCssArgs(name, value, context)
|
|
348
|
+
});
|
|
349
|
+
}
|
|
435
350
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
0,
|
|
445
|
-
|
|
446
|
-
|
|
351
|
+
return functions;
|
|
352
|
+
}
|
|
353
|
+
function parseCssArgs(name, value, context = {}) {
|
|
354
|
+
const values = [];
|
|
355
|
+
let match;
|
|
356
|
+
let i = 0;
|
|
357
|
+
while ((match = ARGS_RE.exec(value)) !== null) {
|
|
358
|
+
values.push(
|
|
359
|
+
parseCssArg(name, match[0], {
|
|
360
|
+
...context,
|
|
361
|
+
index: i++
|
|
362
|
+
})
|
|
447
363
|
);
|
|
448
|
-
return this;
|
|
449
364
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
365
|
+
return values;
|
|
366
|
+
}
|
|
367
|
+
function parseCssArg(name, value, context = {}) {
|
|
368
|
+
const { width = 1, height = 1, index = 0 } = context;
|
|
369
|
+
const matched = value.match(ARG_RE);
|
|
370
|
+
const result = {
|
|
371
|
+
unit: matched?.[2] ?? null,
|
|
372
|
+
value,
|
|
373
|
+
intValue: Number(matched?.[1]),
|
|
374
|
+
normalizedIntValue: 0,
|
|
375
|
+
normalizedDefaultIntValue: 0
|
|
376
|
+
};
|
|
377
|
+
switch (name) {
|
|
378
|
+
case "scale":
|
|
379
|
+
case "scaleX":
|
|
380
|
+
case "scaleY":
|
|
381
|
+
case "scale3d":
|
|
382
|
+
result.normalizedDefaultIntValue = 1;
|
|
383
|
+
break;
|
|
455
384
|
}
|
|
456
|
-
|
|
457
|
-
|
|
385
|
+
switch (result.unit) {
|
|
386
|
+
case "%":
|
|
387
|
+
result.normalizedIntValue = result.intValue / 100;
|
|
388
|
+
break;
|
|
389
|
+
case "rad":
|
|
390
|
+
result.normalizedIntValue = result.intValue / PI_2;
|
|
391
|
+
break;
|
|
392
|
+
case "deg":
|
|
393
|
+
result.normalizedIntValue = result.intValue / 360;
|
|
394
|
+
break;
|
|
395
|
+
case "px":
|
|
396
|
+
switch (index) {
|
|
397
|
+
case 0:
|
|
398
|
+
result.normalizedIntValue = result.intValue / width;
|
|
399
|
+
break;
|
|
400
|
+
case 1:
|
|
401
|
+
result.normalizedIntValue = result.intValue / height;
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
case "turn":
|
|
406
|
+
case "em":
|
|
407
|
+
// div fontSize
|
|
408
|
+
case "rem":
|
|
409
|
+
// div fontSize
|
|
410
|
+
default:
|
|
411
|
+
result.normalizedIntValue = result.intValue;
|
|
412
|
+
break;
|
|
458
413
|
}
|
|
414
|
+
return result;
|
|
459
415
|
}
|
|
460
|
-
const _m3 = /* @__PURE__ */ new Matrix3();
|
|
461
416
|
|
|
462
|
-
function
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
let ang = Math.acos(Math.max(-1, Math.min(1, dot / len)));
|
|
466
|
-
if (ux * vy - uy * vx < 0)
|
|
467
|
-
ang = -ang;
|
|
468
|
-
return ang;
|
|
417
|
+
function cubicBezierP0(t, p) {
|
|
418
|
+
const k = 1 - t;
|
|
419
|
+
return k * k * k * p;
|
|
469
420
|
}
|
|
470
|
-
function
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
421
|
+
function cubicBezierP1(t, p) {
|
|
422
|
+
const k = 1 - t;
|
|
423
|
+
return 3 * k * k * t * p;
|
|
424
|
+
}
|
|
425
|
+
function cubicBezierP2(t, p) {
|
|
426
|
+
return 3 * (1 - t) * t * t * p;
|
|
427
|
+
}
|
|
428
|
+
function cubicBezierP3(t, p) {
|
|
429
|
+
return t * t * t * p;
|
|
430
|
+
}
|
|
431
|
+
function cubicBezier(t, p0, p1, p2, p3) {
|
|
432
|
+
return cubicBezierP0(t, p0) + cubicBezierP1(t, p1) + cubicBezierP2(t, p2) + cubicBezierP3(t, p3);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function fillTriangulate(pointArray, options = {}) {
|
|
436
|
+
let {
|
|
437
|
+
vertices = [],
|
|
438
|
+
indices = [],
|
|
439
|
+
holes = [],
|
|
440
|
+
verticesStride = 2,
|
|
441
|
+
verticesOffset = vertices.length / verticesStride,
|
|
442
|
+
indicesOffset = indices.length
|
|
443
|
+
} = options;
|
|
444
|
+
const triangles = earcut(pointArray, holes, 2);
|
|
445
|
+
if (triangles.length) {
|
|
446
|
+
for (let i = 0; i < triangles.length; i += 3) {
|
|
447
|
+
indices[indicesOffset++] = triangles[i] + verticesOffset;
|
|
448
|
+
indices[indicesOffset++] = triangles[i + 1] + verticesOffset;
|
|
449
|
+
indices[indicesOffset++] = triangles[i + 2] + verticesOffset;
|
|
450
|
+
}
|
|
451
|
+
let index = verticesOffset * verticesStride;
|
|
452
|
+
for (let i = 0; i < pointArray.length; i += 2) {
|
|
453
|
+
vertices[index] = pointArray[i];
|
|
454
|
+
vertices[index + 1] = pointArray[i + 1];
|
|
455
|
+
index += verticesStride;
|
|
456
|
+
}
|
|
493
457
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
q = -q;
|
|
499
|
-
const cxp = q * rx * y1p / ry;
|
|
500
|
-
const cyp = -q * ry * x1p / rx;
|
|
501
|
-
const cx = Math.cos(xAxisRotation) * cxp - Math.sin(xAxisRotation) * cyp + (start.x + end.x) / 2;
|
|
502
|
-
const cy = Math.sin(xAxisRotation) * cxp + Math.cos(xAxisRotation) * cyp + (start.y + end.y) / 2;
|
|
503
|
-
const theta = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
|
|
504
|
-
const delta = svgAngle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry) % (Math.PI * 2);
|
|
505
|
-
path.ellipse(cx, cy, rx, ry, xAxisRotation, theta, theta + delta, sweepFlag === 0);
|
|
458
|
+
return {
|
|
459
|
+
vertices,
|
|
460
|
+
indices
|
|
461
|
+
};
|
|
506
462
|
}
|
|
507
463
|
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
continue;
|
|
550
|
-
}
|
|
551
|
-
if (state === SEP) {
|
|
552
|
-
if (RE$3.WHITESPACE.test(current)) {
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
if (RE$3.DIGIT.test(current) || RE$3.SIGN.test(current)) {
|
|
556
|
-
state = INT;
|
|
557
|
-
number = current;
|
|
558
|
-
continue;
|
|
559
|
-
}
|
|
560
|
-
if (RE$3.POINT.test(current)) {
|
|
561
|
-
state = FLOAT;
|
|
562
|
-
number = current;
|
|
563
|
-
continue;
|
|
564
|
-
}
|
|
565
|
-
if (RE$3.COMMA.test(current)) {
|
|
566
|
-
if (seenComma) {
|
|
567
|
-
throwSyntaxError(current, i, result);
|
|
464
|
+
const RECURSION_LIMIT$1 = 8;
|
|
465
|
+
const FLT_EPSILON$1 = 11920929e-14;
|
|
466
|
+
const PATH_DISTANCE_EPSILON$1 = 1;
|
|
467
|
+
function getAdaptiveCubicBezierCurvePoints(sX, sY, x1, y1, x2, y2, x, y, smoothness = 0.5, points = []) {
|
|
468
|
+
const scale = 1;
|
|
469
|
+
const smoothing = Math.min(
|
|
470
|
+
0.99,
|
|
471
|
+
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
|
|
472
|
+
Math.max(0, smoothness)
|
|
473
|
+
);
|
|
474
|
+
let distanceTolerance = (PATH_DISTANCE_EPSILON$1 - smoothing) / scale;
|
|
475
|
+
distanceTolerance *= distanceTolerance;
|
|
476
|
+
recursive$1(sX, sY, x1, y1, x2, y2, x, y, points, distanceTolerance, 0);
|
|
477
|
+
points.push(x, y);
|
|
478
|
+
return points;
|
|
479
|
+
}
|
|
480
|
+
function recursive$1(x1, y1, x2, y2, x3, y3, x4, y4, points, distanceTolerance, level) {
|
|
481
|
+
if (level > RECURSION_LIMIT$1)
|
|
482
|
+
return;
|
|
483
|
+
const x12 = (x1 + x2) / 2;
|
|
484
|
+
const y12 = (y1 + y2) / 2;
|
|
485
|
+
const x23 = (x2 + x3) / 2;
|
|
486
|
+
const y23 = (y2 + y3) / 2;
|
|
487
|
+
const x34 = (x3 + x4) / 2;
|
|
488
|
+
const y34 = (y3 + y4) / 2;
|
|
489
|
+
const x123 = (x12 + x23) / 2;
|
|
490
|
+
const y123 = (y12 + y23) / 2;
|
|
491
|
+
const x234 = (x23 + x34) / 2;
|
|
492
|
+
const y234 = (y23 + y34) / 2;
|
|
493
|
+
const x1234 = (x123 + x234) / 2;
|
|
494
|
+
const y1234 = (y123 + y234) / 2;
|
|
495
|
+
if (level > 0) {
|
|
496
|
+
let dx = x4 - x1;
|
|
497
|
+
let dy = y4 - y1;
|
|
498
|
+
const d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx);
|
|
499
|
+
const d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx);
|
|
500
|
+
if (d2 > FLT_EPSILON$1 && d3 > FLT_EPSILON$1) {
|
|
501
|
+
if ((d2 + d3) * (d2 + d3) <= distanceTolerance * (dx * dx + dy * dy)) {
|
|
502
|
+
{
|
|
503
|
+
points.push(x1234, y1234);
|
|
504
|
+
return;
|
|
568
505
|
}
|
|
569
|
-
seenComma = true;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
if (state === INT) {
|
|
573
|
-
if (RE$3.DIGIT.test(current)) {
|
|
574
|
-
number += current;
|
|
575
|
-
continue;
|
|
576
|
-
}
|
|
577
|
-
if (RE$3.POINT.test(current)) {
|
|
578
|
-
number += current;
|
|
579
|
-
state = FLOAT;
|
|
580
|
-
continue;
|
|
581
|
-
}
|
|
582
|
-
if (RE$3.EXP.test(current)) {
|
|
583
|
-
state = EXP;
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
if (RE$3.SIGN.test(current) && number.length === 1 && RE$3.SIGN.test(number[0])) {
|
|
587
|
-
throwSyntaxError(current, i, result);
|
|
588
506
|
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
507
|
+
} else if (d2 > FLT_EPSILON$1) {
|
|
508
|
+
if (d2 * d2 <= distanceTolerance * (dx * dx + dy * dy)) {
|
|
509
|
+
{
|
|
510
|
+
points.push(x1234, y1234);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
594
513
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
514
|
+
} else if (d3 > FLT_EPSILON$1) {
|
|
515
|
+
if (d3 * d3 <= distanceTolerance * (dx * dx + dy * dy)) {
|
|
516
|
+
{
|
|
517
|
+
points.push(x1234, y1234);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
598
520
|
}
|
|
599
|
-
|
|
600
|
-
|
|
521
|
+
} else {
|
|
522
|
+
dx = x1234 - (x1 + x4) / 2;
|
|
523
|
+
dy = y1234 - (y1 + y4) / 2;
|
|
524
|
+
if (dx * dx + dy * dy <= distanceTolerance) {
|
|
525
|
+
points.push(x1234, y1234);
|
|
526
|
+
return;
|
|
601
527
|
}
|
|
602
528
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
529
|
+
}
|
|
530
|
+
recursive$1(x1, y1, x12, y12, x123, y123, x1234, y1234, points, distanceTolerance, level + 1);
|
|
531
|
+
recursive$1(x1234, y1234, x234, y234, x34, y34, x4, y4, points, distanceTolerance, level + 1);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const RECURSION_LIMIT = 8;
|
|
535
|
+
const FLT_EPSILON = 11920929e-14;
|
|
536
|
+
const PATH_DISTANCE_EPSILON = 1;
|
|
537
|
+
function getAdaptiveQuadraticBezierCurvePoints(sX, sY, x1, y1, x, y, smoothness = 0.5, points = []) {
|
|
538
|
+
const scale = 1;
|
|
539
|
+
const smoothing = Math.min(
|
|
540
|
+
0.99,
|
|
541
|
+
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
|
|
542
|
+
Math.max(0, smoothness)
|
|
543
|
+
);
|
|
544
|
+
let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;
|
|
545
|
+
distanceTolerance *= distanceTolerance;
|
|
546
|
+
recursive(points, sX, sY, x1, y1, x, y, distanceTolerance, 0);
|
|
547
|
+
points.push(x, y);
|
|
548
|
+
return points;
|
|
549
|
+
}
|
|
550
|
+
function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
|
|
551
|
+
if (level > RECURSION_LIMIT)
|
|
552
|
+
return;
|
|
553
|
+
const x12 = (x1 + x2) / 2;
|
|
554
|
+
const y12 = (y1 + y2) / 2;
|
|
555
|
+
const x23 = (x2 + x3) / 2;
|
|
556
|
+
const y23 = (y2 + y3) / 2;
|
|
557
|
+
const x123 = (x12 + x23) / 2;
|
|
558
|
+
const y123 = (y12 + y23) / 2;
|
|
559
|
+
let dx = x3 - x1;
|
|
560
|
+
let dy = y3 - y1;
|
|
561
|
+
const d = Math.abs((x2 - x3) * dy - (y2 - y3) * dx);
|
|
562
|
+
if (d > FLT_EPSILON) {
|
|
563
|
+
if (d * d <= distanceTolerance * (dx * dx + dy * dy)) {
|
|
564
|
+
{
|
|
565
|
+
points.push(x123, y123);
|
|
566
|
+
return;
|
|
616
567
|
}
|
|
617
568
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
state = SEP;
|
|
625
|
-
seenComma = true;
|
|
626
|
-
} else if (RE$3.SIGN.test(current)) {
|
|
627
|
-
newNumber();
|
|
628
|
-
state = INT;
|
|
629
|
-
number = current;
|
|
630
|
-
} else if (RE$3.POINT.test(current)) {
|
|
631
|
-
newNumber();
|
|
632
|
-
state = FLOAT;
|
|
633
|
-
number = current;
|
|
634
|
-
} else {
|
|
635
|
-
throwSyntaxError(current, i, result);
|
|
569
|
+
} else {
|
|
570
|
+
dx = x123 - (x1 + x3) / 2;
|
|
571
|
+
dy = y123 - (y1 + y3) / 2;
|
|
572
|
+
if (dx * dx + dy * dy <= distanceTolerance) {
|
|
573
|
+
points.push(x123, y123);
|
|
574
|
+
return;
|
|
636
575
|
}
|
|
637
576
|
}
|
|
638
|
-
|
|
639
|
-
|
|
577
|
+
recursive(points, x1, y1, x12, y12, x123, y123, distanceTolerance, level + 1);
|
|
578
|
+
recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
|
|
640
579
|
}
|
|
641
580
|
|
|
642
|
-
function
|
|
643
|
-
|
|
581
|
+
function getDirectedArea(vertices) {
|
|
582
|
+
let area = 0;
|
|
583
|
+
const n = vertices.length;
|
|
584
|
+
for (let i = 0; i < n; i += 2) {
|
|
585
|
+
const x0 = vertices[i];
|
|
586
|
+
const y0 = vertices[i + 1];
|
|
587
|
+
const x1 = vertices[(i + 2) % (n - 1)];
|
|
588
|
+
const y1 = vertices[(i + 3) % n];
|
|
589
|
+
area += x0 * y1 - x1 * y0;
|
|
590
|
+
}
|
|
591
|
+
return area / 2;
|
|
644
592
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
593
|
+
|
|
594
|
+
function cross(ax, ay, bx, by, cx, cy) {
|
|
595
|
+
return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
|
|
596
|
+
}
|
|
597
|
+
function windingNumber(px, py, polygon) {
|
|
598
|
+
const polygonLen = polygon.length;
|
|
599
|
+
let wn = 0;
|
|
600
|
+
for (let i = 0, j = polygonLen - 2; i < polygonLen; j = i, i += 2) {
|
|
601
|
+
const xi = polygon[i];
|
|
602
|
+
const yi = polygon[i + 1];
|
|
603
|
+
const xj = polygon[j];
|
|
604
|
+
const yj = polygon[j + 1];
|
|
605
|
+
if (yi <= py) {
|
|
606
|
+
if (yj > py && cross(xj, yj, xi, yi, px, py) > 0)
|
|
607
|
+
wn++;
|
|
608
|
+
} else {
|
|
609
|
+
if (yj <= py && cross(xj, yj, xi, yi, px, py) < 0)
|
|
610
|
+
wn--;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return wn;
|
|
614
|
+
}
|
|
615
|
+
function distance(p1, p2) {
|
|
616
|
+
const dx = p2[0] - p1[0];
|
|
617
|
+
const dy = p2[1] - p1[1];
|
|
618
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
619
|
+
}
|
|
620
|
+
function nonzeroFillRule(paths) {
|
|
621
|
+
const results = paths.map((_, i) => ({ index: i }));
|
|
622
|
+
const testPointsGroups = paths.map((path) => {
|
|
623
|
+
const len = path.length;
|
|
624
|
+
if (!len) {
|
|
625
|
+
return [];
|
|
626
|
+
}
|
|
627
|
+
let xMinYAuto = [Number.MAX_SAFE_INTEGER, 0];
|
|
628
|
+
let xAutoYMin = [0, Number.MAX_SAFE_INTEGER];
|
|
629
|
+
let xMaxYAuto = [Number.MIN_SAFE_INTEGER, 0];
|
|
630
|
+
let xAutoYMax = [0, Number.MIN_SAFE_INTEGER];
|
|
631
|
+
for (let i = 0; i < len; i += 2) {
|
|
632
|
+
const x = path[i];
|
|
633
|
+
const y = path[i + 1];
|
|
634
|
+
if (xMinYAuto[0] > x) {
|
|
635
|
+
xMinYAuto = [x, y];
|
|
671
636
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
} else if (cmd.type === "l" || cmd.type === "L") {
|
|
675
|
-
if (cmd.type === "l") {
|
|
676
|
-
current.add(cmd);
|
|
677
|
-
} else {
|
|
678
|
-
current.copy(cmd);
|
|
637
|
+
if (xAutoYMin[1] > y) {
|
|
638
|
+
xAutoYMin = [x, y];
|
|
679
639
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
} else if (cmd.type === "c" || cmd.type === "C") {
|
|
683
|
-
if (cmd.type === "c") {
|
|
684
|
-
path.bezierCurveTo(
|
|
685
|
-
current.x + cmd.x1,
|
|
686
|
-
current.y + cmd.y1,
|
|
687
|
-
current.x + cmd.x2,
|
|
688
|
-
current.y + cmd.y2,
|
|
689
|
-
current.x + cmd.x,
|
|
690
|
-
current.y + cmd.y
|
|
691
|
-
);
|
|
692
|
-
control.x = current.x + cmd.x2;
|
|
693
|
-
control.y = current.y + cmd.y2;
|
|
694
|
-
current.add(cmd);
|
|
695
|
-
} else {
|
|
696
|
-
path.bezierCurveTo(
|
|
697
|
-
cmd.x1,
|
|
698
|
-
cmd.y1,
|
|
699
|
-
cmd.x2,
|
|
700
|
-
cmd.y2,
|
|
701
|
-
cmd.x,
|
|
702
|
-
cmd.y
|
|
703
|
-
);
|
|
704
|
-
control.x = cmd.x2;
|
|
705
|
-
control.y = cmd.y2;
|
|
706
|
-
current.copy(cmd);
|
|
640
|
+
if (xMaxYAuto[0] < x) {
|
|
641
|
+
xMaxYAuto = [x, y];
|
|
707
642
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
path.bezierCurveTo(
|
|
711
|
-
getReflection(current.x, control.x),
|
|
712
|
-
getReflection(current.y, control.y),
|
|
713
|
-
current.x + cmd.x2,
|
|
714
|
-
current.y + cmd.y2,
|
|
715
|
-
current.x + cmd.x,
|
|
716
|
-
current.y + cmd.y
|
|
717
|
-
);
|
|
718
|
-
control.x = current.x + cmd.x2;
|
|
719
|
-
control.y = current.y + cmd.y2;
|
|
720
|
-
current.add(cmd);
|
|
721
|
-
} else {
|
|
722
|
-
path.bezierCurveTo(
|
|
723
|
-
getReflection(current.x, control.x),
|
|
724
|
-
getReflection(current.y, control.y),
|
|
725
|
-
cmd.x2,
|
|
726
|
-
cmd.y2,
|
|
727
|
-
cmd.x,
|
|
728
|
-
cmd.y
|
|
729
|
-
);
|
|
730
|
-
control.x = cmd.x2;
|
|
731
|
-
control.y = cmd.y2;
|
|
732
|
-
current.copy(cmd);
|
|
643
|
+
if (xAutoYMax[1] < y) {
|
|
644
|
+
xAutoYMax = [x, y];
|
|
733
645
|
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
646
|
+
}
|
|
647
|
+
const mid = [
|
|
648
|
+
(xMinYAuto[0] + xMaxYAuto[0]) / 2,
|
|
649
|
+
(xAutoYMin[1] + xAutoYMax[1]) / 2
|
|
650
|
+
];
|
|
651
|
+
let xMidYMinDx;
|
|
652
|
+
let xMidYMaxDx;
|
|
653
|
+
let xMidYMin;
|
|
654
|
+
let xMidYMax;
|
|
655
|
+
let xMinYMidDy;
|
|
656
|
+
let xMaxYMidDy;
|
|
657
|
+
let xMinYMid;
|
|
658
|
+
let xMaxYMid;
|
|
659
|
+
for (let i = 0; i < len; i += 2) {
|
|
660
|
+
const x = path[i];
|
|
661
|
+
const y = path[i + 1];
|
|
662
|
+
const _dx = Math.abs(x - mid[0]);
|
|
663
|
+
const _dy = Math.abs(y - mid[1]);
|
|
664
|
+
if (y < mid[1] && (!xMidYMinDx || _dx < xMidYMinDx)) {
|
|
665
|
+
xMidYMinDx = _dx;
|
|
666
|
+
xMidYMin = [x, y];
|
|
755
667
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
control.x = rx;
|
|
760
|
-
control.y = ry;
|
|
761
|
-
if (cmd.type === "t") {
|
|
762
|
-
path.quadraticCurveTo(
|
|
763
|
-
rx,
|
|
764
|
-
ry,
|
|
765
|
-
current.x + cmd.x,
|
|
766
|
-
current.y + cmd.y
|
|
767
|
-
);
|
|
768
|
-
current.add(cmd);
|
|
769
|
-
} else {
|
|
770
|
-
path.quadraticCurveTo(
|
|
771
|
-
rx,
|
|
772
|
-
ry,
|
|
773
|
-
cmd.x,
|
|
774
|
-
cmd.y
|
|
775
|
-
);
|
|
776
|
-
current.copy(cmd);
|
|
668
|
+
if (y > mid[1] && (!xMidYMaxDx || _dx < xMidYMaxDx)) {
|
|
669
|
+
xMidYMaxDx = _dx;
|
|
670
|
+
xMidYMax = [x, y];
|
|
777
671
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
if (cmd.x === 0 && cmd.y === 0)
|
|
782
|
-
continue;
|
|
783
|
-
current.add(cmd);
|
|
784
|
-
} else {
|
|
785
|
-
if (current.equals(cmd))
|
|
786
|
-
continue;
|
|
787
|
-
current.copy(cmd);
|
|
672
|
+
if (x < mid[0] && (!xMinYMidDy || _dy < xMinYMidDy)) {
|
|
673
|
+
xMinYMidDy = _dy;
|
|
674
|
+
xMinYMid = [x, y];
|
|
788
675
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
cmd.rx,
|
|
793
|
-
cmd.ry,
|
|
794
|
-
cmd.angle,
|
|
795
|
-
cmd.largeArcFlag,
|
|
796
|
-
cmd.sweepFlag,
|
|
797
|
-
start,
|
|
798
|
-
current
|
|
799
|
-
);
|
|
800
|
-
} else if (cmd.type === "z" || cmd.type === "Z") {
|
|
801
|
-
if (path.startPoint) {
|
|
802
|
-
current.copy(path.startPoint);
|
|
676
|
+
if (x > mid[0] && (!xMaxYMidDy || _dy < xMaxYMidDy)) {
|
|
677
|
+
xMaxYMidDy = _dy;
|
|
678
|
+
xMaxYMid = [x, y];
|
|
803
679
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
680
|
+
}
|
|
681
|
+
return [
|
|
682
|
+
xMinYAuto,
|
|
683
|
+
xAutoYMin,
|
|
684
|
+
xMaxYAuto,
|
|
685
|
+
xAutoYMax,
|
|
686
|
+
xMidYMin,
|
|
687
|
+
xMidYMax,
|
|
688
|
+
xMinYMid,
|
|
689
|
+
xMaxYMid
|
|
690
|
+
].filter(Boolean);
|
|
691
|
+
});
|
|
692
|
+
for (let i = 0, len = paths.length; i < len; i++) {
|
|
693
|
+
const _results = [];
|
|
694
|
+
const testPoints = testPointsGroups[i];
|
|
695
|
+
for (let j = 0; j < len; j++) {
|
|
696
|
+
if (i === j)
|
|
697
|
+
continue;
|
|
698
|
+
const wnMap = {};
|
|
699
|
+
const wnList = [];
|
|
700
|
+
for (let p = 0, pLen = testPoints.length; p < pLen; p++) {
|
|
701
|
+
const [x, y] = testPoints[p];
|
|
702
|
+
const winding = windingNumber(x, y, paths[j]);
|
|
703
|
+
wnMap[winding] = (wnMap[winding] ?? 0) + 1;
|
|
704
|
+
wnList.push(winding);
|
|
705
|
+
}
|
|
706
|
+
if (wnList.filter((v) => v !== 0).length > wnList.filter((v) => v === 0).length) {
|
|
707
|
+
_results.push({
|
|
708
|
+
index: i,
|
|
709
|
+
parentIndex: j,
|
|
710
|
+
winding: Number(
|
|
711
|
+
Array.from(Object.entries(wnMap)).sort((a, b) => b[1] - a[1])?.[0]?.[0] ?? 0
|
|
712
|
+
),
|
|
713
|
+
dist: distance(testPointsGroups[i][0], testPointsGroups[j][0])
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
if (_results.reduce((total, item) => total + item.winding, 0) !== 0) {
|
|
718
|
+
_results.sort((a, b) => a.dist - b.dist);
|
|
719
|
+
results[i] = _results[0];
|
|
807
720
|
}
|
|
808
721
|
}
|
|
722
|
+
return results;
|
|
809
723
|
}
|
|
810
724
|
|
|
811
|
-
function
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
data.push(`${cmd.type} ${cmd.x} ${cmd.y}`);
|
|
824
|
-
prev = { x: cmd.x, y: cmd.y };
|
|
825
|
-
first = { x: cmd.x, y: cmd.y };
|
|
826
|
-
break;
|
|
827
|
-
case "h":
|
|
828
|
-
case "H":
|
|
829
|
-
data.push(`${cmd.type} ${cmd.x}`);
|
|
830
|
-
prev = { x: cmd.x, y: prev?.y ?? 0 };
|
|
831
|
-
break;
|
|
832
|
-
case "v":
|
|
833
|
-
case "V":
|
|
834
|
-
data.push(`${cmd.type} ${cmd.y}`);
|
|
835
|
-
prev = { x: prev?.x ?? 0, y: cmd.y };
|
|
836
|
-
break;
|
|
837
|
-
case "l":
|
|
838
|
-
case "L":
|
|
839
|
-
data.push(`${cmd.type} ${cmd.x} ${cmd.y}`);
|
|
840
|
-
prev = { x: cmd.x, y: cmd.y };
|
|
841
|
-
break;
|
|
842
|
-
case "c":
|
|
843
|
-
case "C":
|
|
844
|
-
data.push(`${cmd.type} ${cmd.x1} ${cmd.y1} ${cmd.x2} ${cmd.y2} ${cmd.x} ${cmd.y}`);
|
|
845
|
-
prev = { x: cmd.x, y: cmd.y };
|
|
846
|
-
break;
|
|
847
|
-
case "s":
|
|
848
|
-
case "S":
|
|
849
|
-
data.push(`${cmd.type} ${cmd.x2} ${cmd.y2} ${cmd.x} ${cmd.y}`);
|
|
850
|
-
prev = { x: cmd.x, y: cmd.y };
|
|
851
|
-
break;
|
|
852
|
-
case "q":
|
|
853
|
-
case "Q":
|
|
854
|
-
data.push(`${cmd.type} ${cmd.x1} ${cmd.y1} ${cmd.x} ${cmd.y}`);
|
|
855
|
-
prev = { x: cmd.x, y: cmd.y };
|
|
856
|
-
break;
|
|
857
|
-
case "t":
|
|
858
|
-
case "T":
|
|
859
|
-
data.push(`${cmd.type} ${cmd.x} ${cmd.y}`);
|
|
860
|
-
prev = { x: cmd.x, y: cmd.y };
|
|
861
|
-
break;
|
|
862
|
-
case "a":
|
|
863
|
-
case "A":
|
|
864
|
-
data.push(`${cmd.type} ${cmd.rx} ${cmd.ry} ${cmd.angle} ${cmd.largeArcFlag} ${cmd.sweepFlag} ${cmd.x} ${cmd.y}`);
|
|
865
|
-
prev = { x: cmd.x, y: cmd.y };
|
|
866
|
-
break;
|
|
867
|
-
case "z":
|
|
868
|
-
case "Z":
|
|
869
|
-
data.push(cmd.type);
|
|
870
|
-
if (first) {
|
|
871
|
-
prev = { x: first.x, y: first.y };
|
|
872
|
-
}
|
|
873
|
-
break;
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
return data.join(" ");
|
|
725
|
+
function quadraticBezierP0(t, p) {
|
|
726
|
+
const k = 1 - t;
|
|
727
|
+
return k * k * p;
|
|
728
|
+
}
|
|
729
|
+
function quadraticBezierP1(t, p) {
|
|
730
|
+
return 2 * (1 - t) * t * p;
|
|
731
|
+
}
|
|
732
|
+
function quadraticBezierP2(t, p) {
|
|
733
|
+
return t * t * p;
|
|
734
|
+
}
|
|
735
|
+
function quadraticBezier(t, p0, p1, p2) {
|
|
736
|
+
return quadraticBezierP0(t, p0) + quadraticBezierP1(t, p1) + quadraticBezierP2(t, p2);
|
|
877
737
|
}
|
|
878
738
|
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
const
|
|
883
|
-
|
|
884
|
-
|
|
739
|
+
const closePointEps = 1e-4;
|
|
740
|
+
const curveEps = 1e-4;
|
|
741
|
+
function strokeTriangulate(points, options = {}) {
|
|
742
|
+
const {
|
|
743
|
+
vertices = [],
|
|
744
|
+
indices = [],
|
|
745
|
+
lineStyle = {
|
|
746
|
+
alignment: 0.5,
|
|
747
|
+
cap: "butt",
|
|
748
|
+
join: "miter",
|
|
749
|
+
width: 1,
|
|
750
|
+
miterLimit: 10
|
|
751
|
+
},
|
|
752
|
+
flipAlignment = false,
|
|
753
|
+
closed = true
|
|
754
|
+
} = options;
|
|
755
|
+
const eps = closePointEps;
|
|
756
|
+
if (points.length === 0) {
|
|
757
|
+
return { vertices, indices };
|
|
885
758
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
case "M":
|
|
894
|
-
args = parsePathDataArgs(data2);
|
|
895
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
|
|
896
|
-
if (i2 === 0) {
|
|
897
|
-
commands.push({ type, x: args[i2], y: args[i2 + 1] });
|
|
898
|
-
} else {
|
|
899
|
-
commands.push({ type: type === "m" ? "l" : "L", x: args[i2], y: args[i2 + 1] });
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
break;
|
|
903
|
-
case "h":
|
|
904
|
-
case "H":
|
|
905
|
-
args = parsePathDataArgs(data2);
|
|
906
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2++) {
|
|
907
|
-
commands.push({ type, x: args[i2] });
|
|
908
|
-
}
|
|
909
|
-
break;
|
|
910
|
-
case "v":
|
|
911
|
-
case "V":
|
|
912
|
-
args = parsePathDataArgs(data2);
|
|
913
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2++) {
|
|
914
|
-
commands.push({ type, y: args[i2] });
|
|
915
|
-
}
|
|
916
|
-
break;
|
|
917
|
-
case "l":
|
|
918
|
-
case "L":
|
|
919
|
-
args = parsePathDataArgs(data2);
|
|
920
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
|
|
921
|
-
commands.push({ type, x: args[i2], y: args[i2 + 1] });
|
|
922
|
-
}
|
|
923
|
-
break;
|
|
924
|
-
case "c":
|
|
925
|
-
case "C":
|
|
926
|
-
args = parsePathDataArgs(data2);
|
|
927
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 6) {
|
|
928
|
-
commands.push({
|
|
929
|
-
type,
|
|
930
|
-
x1: args[i2],
|
|
931
|
-
y1: args[i2 + 1],
|
|
932
|
-
x2: args[i2 + 2],
|
|
933
|
-
y2: args[i2 + 3],
|
|
934
|
-
x: args[i2 + 4],
|
|
935
|
-
y: args[i2 + 5]
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
break;
|
|
939
|
-
case "s":
|
|
940
|
-
case "S":
|
|
941
|
-
args = parsePathDataArgs(data2);
|
|
942
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 4) {
|
|
943
|
-
commands.push({
|
|
944
|
-
type,
|
|
945
|
-
x2: args[i2],
|
|
946
|
-
y2: args[i2 + 1],
|
|
947
|
-
x: args[i2 + 2],
|
|
948
|
-
y: args[i2 + 3]
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
break;
|
|
952
|
-
case "q":
|
|
953
|
-
case "Q":
|
|
954
|
-
args = parsePathDataArgs(data2);
|
|
955
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 4) {
|
|
956
|
-
commands.push({
|
|
957
|
-
type,
|
|
958
|
-
x1: args[i2],
|
|
959
|
-
y1: args[i2 + 1],
|
|
960
|
-
x: args[i2 + 2],
|
|
961
|
-
y: args[i2 + 3]
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
break;
|
|
965
|
-
case "t":
|
|
966
|
-
case "T":
|
|
967
|
-
args = parsePathDataArgs(data2);
|
|
968
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
|
|
969
|
-
commands.push({
|
|
970
|
-
type,
|
|
971
|
-
x: args[i2],
|
|
972
|
-
y: args[i2 + 1]
|
|
973
|
-
});
|
|
974
|
-
}
|
|
975
|
-
break;
|
|
976
|
-
case "a":
|
|
977
|
-
case "A":
|
|
978
|
-
args = parsePathDataArgs(data2, [3, 4], 7);
|
|
979
|
-
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 7) {
|
|
980
|
-
commands.push({
|
|
981
|
-
type,
|
|
982
|
-
rx: args[i2],
|
|
983
|
-
ry: args[i2 + 1],
|
|
984
|
-
angle: args[i2 + 2],
|
|
985
|
-
largeArcFlag: args[i2 + 3],
|
|
986
|
-
sweepFlag: args[i2 + 4],
|
|
987
|
-
x: args[i2 + 5],
|
|
988
|
-
y: args[i2 + 6]
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
break;
|
|
992
|
-
case "z":
|
|
993
|
-
case "Z":
|
|
994
|
-
commands.push({
|
|
995
|
-
type
|
|
996
|
-
});
|
|
997
|
-
break;
|
|
998
|
-
default:
|
|
999
|
-
console.warn(command);
|
|
1000
|
-
}
|
|
759
|
+
const style = lineStyle;
|
|
760
|
+
let alignment = style.alignment;
|
|
761
|
+
if (lineStyle.alignment !== 0.5) {
|
|
762
|
+
let orientation = getOrientationOfPoints(points);
|
|
763
|
+
if (flipAlignment)
|
|
764
|
+
orientation *= -1;
|
|
765
|
+
alignment = (alignment - 0.5) * orientation + 0.5;
|
|
1001
766
|
}
|
|
1002
|
-
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
const
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
xml = atob(svg);
|
|
1014
|
-
} else if (svg.startsWith(utf8DataUri)) {
|
|
1015
|
-
svg = svg.substring(utf8DataUri.length, svg.length);
|
|
1016
|
-
xml = decodeURIComponent(svg);
|
|
1017
|
-
} else {
|
|
1018
|
-
xml = svg;
|
|
1019
|
-
}
|
|
1020
|
-
const doc = new DOMParser().parseFromString(xml, "text/xml");
|
|
1021
|
-
const error = doc.querySelector("parsererror");
|
|
1022
|
-
if (error) {
|
|
1023
|
-
throw new Error(`${error.textContent ?? "parser error"}
|
|
1024
|
-
${xml}`);
|
|
767
|
+
const firstPoint = { x: points[0], y: points[1] };
|
|
768
|
+
const lastPoint = { x: points[points.length - 2], y: points[points.length - 1] };
|
|
769
|
+
const closedShape = closed;
|
|
770
|
+
const closedPath = Math.abs(firstPoint.x - lastPoint.x) < eps && Math.abs(firstPoint.y - lastPoint.y) < eps;
|
|
771
|
+
if (closedShape) {
|
|
772
|
+
points = points.slice();
|
|
773
|
+
if (closedPath) {
|
|
774
|
+
points.pop();
|
|
775
|
+
points.pop();
|
|
776
|
+
lastPoint.x = points[points.length - 2];
|
|
777
|
+
lastPoint.y = points[points.length - 1];
|
|
1025
778
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
779
|
+
const midPointX = (firstPoint.x + lastPoint.x) * 0.5;
|
|
780
|
+
const midPointY = (lastPoint.y + firstPoint.y) * 0.5;
|
|
781
|
+
points.unshift(midPointX, midPointY);
|
|
782
|
+
points.push(midPointX, midPointY);
|
|
1029
783
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
const
|
|
1034
|
-
const
|
|
1035
|
-
const
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
mm: 25.4 / 6,
|
|
1070
|
-
cm: 2.54 / 6,
|
|
1071
|
-
in: 1 / 6,
|
|
1072
|
-
pt: 72 / 6,
|
|
1073
|
-
pc: 1,
|
|
1074
|
-
px: -1
|
|
1075
|
-
},
|
|
1076
|
-
px: {
|
|
1077
|
-
px: 1
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
|
-
function parseFloatWithUnits(string) {
|
|
1081
|
-
let theUnit = "px";
|
|
1082
|
-
if (typeof string === "string") {
|
|
1083
|
-
for (let i = 0, n = units.length; i < n; i++) {
|
|
1084
|
-
const u = units[i];
|
|
1085
|
-
if (string.endsWith(u)) {
|
|
1086
|
-
theUnit = u;
|
|
1087
|
-
string = string.substring(0, string.length - u.length);
|
|
1088
|
-
break;
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
let scale;
|
|
1093
|
-
{
|
|
1094
|
-
scale = unitConversion[theUnit][defaultUnit];
|
|
1095
|
-
if (scale < 0) {
|
|
1096
|
-
scale = unitConversion[theUnit].in * defaultDPI;
|
|
784
|
+
const verts = vertices;
|
|
785
|
+
const length = points.length / 2;
|
|
786
|
+
let indexCount = points.length;
|
|
787
|
+
const indexStart = verts.length / 2;
|
|
788
|
+
const width = style.width / 2;
|
|
789
|
+
const widthSquared = width * width;
|
|
790
|
+
const miterLimitSquared = style.miterLimit * style.miterLimit;
|
|
791
|
+
let x0 = points[0];
|
|
792
|
+
let y0 = points[1];
|
|
793
|
+
let x1 = points[2];
|
|
794
|
+
let y1 = points[3];
|
|
795
|
+
let x2 = 0;
|
|
796
|
+
let y2 = 0;
|
|
797
|
+
let perpX = -(y0 - y1);
|
|
798
|
+
let perpY = x0 - x1;
|
|
799
|
+
let perp1x = 0;
|
|
800
|
+
let perp1y = 0;
|
|
801
|
+
let dist = Math.sqrt(perpX * perpX + perpY * perpY);
|
|
802
|
+
perpX /= dist;
|
|
803
|
+
perpY /= dist;
|
|
804
|
+
perpX *= width;
|
|
805
|
+
perpY *= width;
|
|
806
|
+
const ratio = alignment;
|
|
807
|
+
const innerWeight = (1 - ratio) * 2;
|
|
808
|
+
const outerWeight = ratio * 2;
|
|
809
|
+
if (!closedShape) {
|
|
810
|
+
if (style.cap === "round") {
|
|
811
|
+
indexCount += round(
|
|
812
|
+
x0 - perpX * (innerWeight - outerWeight) * 0.5,
|
|
813
|
+
y0 - perpY * (innerWeight - outerWeight) * 0.5,
|
|
814
|
+
x0 - perpX * innerWeight,
|
|
815
|
+
y0 - perpY * innerWeight,
|
|
816
|
+
x0 + perpX * outerWeight,
|
|
817
|
+
y0 + perpY * outerWeight,
|
|
818
|
+
verts,
|
|
819
|
+
true
|
|
820
|
+
) + 2;
|
|
821
|
+
} else if (style.cap === "square") {
|
|
822
|
+
indexCount += square(x0, y0, perpX, perpY, innerWeight, outerWeight, true, verts);
|
|
1097
823
|
}
|
|
1098
824
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
const
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
cy = array[2];
|
|
1159
|
-
}
|
|
1160
|
-
tempTransform1$1.makeTranslation(-cx, -cy);
|
|
1161
|
-
tempTransform2$1.makeRotation(angle);
|
|
1162
|
-
tempTransform3.multiplyMatrices(tempTransform2$1, tempTransform1$1);
|
|
1163
|
-
tempTransform1$1.makeTranslation(cx, cy);
|
|
1164
|
-
currentTransform.multiplyMatrices(tempTransform1$1, tempTransform3);
|
|
1165
|
-
}
|
|
1166
|
-
break;
|
|
1167
|
-
case "scale":
|
|
1168
|
-
if (array.length >= 1) {
|
|
1169
|
-
currentTransform.scale(
|
|
1170
|
-
array[0],
|
|
1171
|
-
array[1] ?? array[0]
|
|
1172
|
-
);
|
|
1173
|
-
}
|
|
1174
|
-
break;
|
|
1175
|
-
case "skewX":
|
|
1176
|
-
if (array.length === 1) {
|
|
1177
|
-
currentTransform.set(
|
|
1178
|
-
1,
|
|
1179
|
-
Math.tan(array[0] * Math.PI / 180),
|
|
1180
|
-
0,
|
|
1181
|
-
0,
|
|
1182
|
-
1,
|
|
1183
|
-
0,
|
|
1184
|
-
0,
|
|
1185
|
-
0,
|
|
1186
|
-
1
|
|
1187
|
-
);
|
|
1188
|
-
}
|
|
1189
|
-
break;
|
|
1190
|
-
case "skewY":
|
|
1191
|
-
if (array.length === 1) {
|
|
1192
|
-
currentTransform.set(
|
|
1193
|
-
1,
|
|
1194
|
-
0,
|
|
1195
|
-
0,
|
|
1196
|
-
Math.tan(array[0] * Math.PI / 180),
|
|
1197
|
-
1,
|
|
1198
|
-
0,
|
|
1199
|
-
0,
|
|
1200
|
-
0,
|
|
1201
|
-
1
|
|
1202
|
-
);
|
|
1203
|
-
}
|
|
1204
|
-
break;
|
|
1205
|
-
case "matrix":
|
|
1206
|
-
if (array.length === 6) {
|
|
1207
|
-
currentTransform.set(
|
|
1208
|
-
array[0],
|
|
1209
|
-
array[2],
|
|
1210
|
-
array[4],
|
|
1211
|
-
array[1],
|
|
1212
|
-
array[3],
|
|
1213
|
-
array[5],
|
|
1214
|
-
0,
|
|
1215
|
-
0,
|
|
1216
|
-
1
|
|
1217
|
-
);
|
|
1218
|
-
}
|
|
1219
|
-
break;
|
|
825
|
+
verts.push(
|
|
826
|
+
x0 - perpX * innerWeight,
|
|
827
|
+
y0 - perpY * innerWeight
|
|
828
|
+
);
|
|
829
|
+
verts.push(
|
|
830
|
+
x0 + perpX * outerWeight,
|
|
831
|
+
y0 + perpY * outerWeight
|
|
832
|
+
);
|
|
833
|
+
for (let i = 1; i < length - 1; ++i) {
|
|
834
|
+
x0 = points[(i - 1) * 2];
|
|
835
|
+
y0 = points[(i - 1) * 2 + 1];
|
|
836
|
+
x1 = points[i * 2];
|
|
837
|
+
y1 = points[i * 2 + 1];
|
|
838
|
+
x2 = points[(i + 1) * 2];
|
|
839
|
+
y2 = points[(i + 1) * 2 + 1];
|
|
840
|
+
perpX = -(y0 - y1);
|
|
841
|
+
perpY = x0 - x1;
|
|
842
|
+
dist = Math.sqrt(perpX * perpX + perpY * perpY);
|
|
843
|
+
perpX /= dist;
|
|
844
|
+
perpY /= dist;
|
|
845
|
+
perpX *= width;
|
|
846
|
+
perpY *= width;
|
|
847
|
+
perp1x = -(y1 - y2);
|
|
848
|
+
perp1y = x1 - x2;
|
|
849
|
+
dist = Math.sqrt(perp1x * perp1x + perp1y * perp1y);
|
|
850
|
+
perp1x /= dist;
|
|
851
|
+
perp1y /= dist;
|
|
852
|
+
perp1x *= width;
|
|
853
|
+
perp1y *= width;
|
|
854
|
+
const dx0 = x1 - x0;
|
|
855
|
+
const dy0 = y0 - y1;
|
|
856
|
+
const dx1 = x1 - x2;
|
|
857
|
+
const dy1 = y2 - y1;
|
|
858
|
+
const dot = dx0 * dx1 + dy0 * dy1;
|
|
859
|
+
const cross = dy0 * dx1 - dy1 * dx0;
|
|
860
|
+
const clockwise = cross < 0;
|
|
861
|
+
if (Math.abs(cross) < 1e-3 * Math.abs(dot)) {
|
|
862
|
+
verts.push(
|
|
863
|
+
x1 - perpX * innerWeight,
|
|
864
|
+
y1 - perpY * innerWeight
|
|
865
|
+
);
|
|
866
|
+
verts.push(
|
|
867
|
+
x1 + perpX * outerWeight,
|
|
868
|
+
y1 + perpY * outerWeight
|
|
869
|
+
);
|
|
870
|
+
if (dot >= 0) {
|
|
871
|
+
if (style.join === "round") {
|
|
872
|
+
indexCount += round(
|
|
873
|
+
x1,
|
|
874
|
+
y1,
|
|
875
|
+
x1 - perpX * innerWeight,
|
|
876
|
+
y1 - perpY * innerWeight,
|
|
877
|
+
x1 - perp1x * innerWeight,
|
|
878
|
+
y1 - perp1y * innerWeight,
|
|
879
|
+
verts,
|
|
880
|
+
false
|
|
881
|
+
) + 4;
|
|
882
|
+
} else {
|
|
883
|
+
indexCount += 2;
|
|
1220
884
|
}
|
|
885
|
+
verts.push(
|
|
886
|
+
x1 - perp1x * outerWeight,
|
|
887
|
+
y1 - perp1y * outerWeight
|
|
888
|
+
);
|
|
889
|
+
verts.push(
|
|
890
|
+
x1 + perp1x * innerWeight,
|
|
891
|
+
y1 + perp1y * innerWeight
|
|
892
|
+
);
|
|
1221
893
|
}
|
|
1222
|
-
transform.premultiply(currentTransform);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
return transform;
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
function parseCircleNode(node) {
|
|
1229
|
-
return new Path2D().arc(
|
|
1230
|
-
parseFloatWithUnits(node.getAttribute("cx") || 0),
|
|
1231
|
-
parseFloatWithUnits(node.getAttribute("cy") || 0),
|
|
1232
|
-
parseFloatWithUnits(node.getAttribute("r") || 0),
|
|
1233
|
-
0,
|
|
1234
|
-
Math.PI * 2
|
|
1235
|
-
);
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
function parseCSSStylesheet(node, stylesheets) {
|
|
1239
|
-
if (!node.sheet || !node.sheet.cssRules || !node.sheet.cssRules.length)
|
|
1240
|
-
return;
|
|
1241
|
-
for (let i = 0; i < node.sheet.cssRules.length; i++) {
|
|
1242
|
-
const stylesheet = node.sheet.cssRules[i];
|
|
1243
|
-
if (stylesheet.type !== 1)
|
|
1244
894
|
continue;
|
|
1245
|
-
const selectorList = stylesheet.selectorText.split(/,/g).filter(Boolean).map((i2) => i2.trim());
|
|
1246
|
-
const definitions = {};
|
|
1247
|
-
for (let len = stylesheet.style.length, i2 = 0; i2 < len; i2++) {
|
|
1248
|
-
const name = stylesheet.style.item(i2);
|
|
1249
|
-
definitions[name] = stylesheet.style.getPropertyValue(name);
|
|
1250
|
-
}
|
|
1251
|
-
for (let j = 0; j < selectorList.length; j++) {
|
|
1252
|
-
stylesheets[selectorList[j]] = Object.assign(
|
|
1253
|
-
stylesheets[selectorList[j]] || {},
|
|
1254
|
-
{ ...definitions }
|
|
1255
|
-
);
|
|
1256
895
|
}
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
896
|
+
const c1 = (-perpX + x0) * (-perpY + y1) - (-perpX + x1) * (-perpY + y0);
|
|
897
|
+
const c2 = (-perp1x + x2) * (-perp1y + y1) - (-perp1x + x1) * (-perp1y + y2);
|
|
898
|
+
const px = (dx0 * c2 - dx1 * c1) / cross;
|
|
899
|
+
const py = (dy1 * c1 - dy0 * c2) / cross;
|
|
900
|
+
const pDist = (px - x1) * (px - x1) + (py - y1) * (py - y1);
|
|
901
|
+
const imx = x1 + (px - x1) * innerWeight;
|
|
902
|
+
const imy = y1 + (py - y1) * innerWeight;
|
|
903
|
+
const omx = x1 - (px - x1) * outerWeight;
|
|
904
|
+
const omy = y1 - (py - y1) * outerWeight;
|
|
905
|
+
const smallerInsideSegmentSq = Math.min(dx0 * dx0 + dy0 * dy0, dx1 * dx1 + dy1 * dy1);
|
|
906
|
+
const insideWeight = clockwise ? innerWeight : outerWeight;
|
|
907
|
+
const smallerInsideDiagonalSq = smallerInsideSegmentSq + insideWeight * insideWeight * widthSquared;
|
|
908
|
+
const insideMiterOk = pDist <= smallerInsideDiagonalSq;
|
|
909
|
+
if (insideMiterOk) {
|
|
910
|
+
if (style.join === "bevel" || pDist / widthSquared > miterLimitSquared) {
|
|
911
|
+
if (clockwise) {
|
|
912
|
+
verts.push(imx, imy);
|
|
913
|
+
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
|
|
914
|
+
verts.push(imx, imy);
|
|
915
|
+
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
|
|
916
|
+
} else {
|
|
917
|
+
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
|
|
918
|
+
verts.push(omx, omy);
|
|
919
|
+
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
|
|
920
|
+
verts.push(omx, omy);
|
|
921
|
+
}
|
|
922
|
+
indexCount += 2;
|
|
923
|
+
} else if (style.join === "round") {
|
|
924
|
+
if (clockwise) {
|
|
925
|
+
verts.push(imx, imy);
|
|
926
|
+
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
|
|
927
|
+
indexCount += round(
|
|
928
|
+
x1,
|
|
929
|
+
y1,
|
|
930
|
+
x1 + perpX * outerWeight,
|
|
931
|
+
y1 + perpY * outerWeight,
|
|
932
|
+
x1 + perp1x * outerWeight,
|
|
933
|
+
y1 + perp1y * outerWeight,
|
|
934
|
+
verts,
|
|
935
|
+
true
|
|
936
|
+
) + 4;
|
|
937
|
+
verts.push(imx, imy);
|
|
938
|
+
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
|
|
939
|
+
} else {
|
|
940
|
+
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
|
|
941
|
+
verts.push(omx, omy);
|
|
942
|
+
indexCount += round(
|
|
943
|
+
x1,
|
|
944
|
+
y1,
|
|
945
|
+
x1 - perpX * innerWeight,
|
|
946
|
+
y1 - perpY * innerWeight,
|
|
947
|
+
x1 - perp1x * innerWeight,
|
|
948
|
+
y1 - perp1y * innerWeight,
|
|
949
|
+
verts,
|
|
950
|
+
false
|
|
951
|
+
) + 4;
|
|
952
|
+
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
|
|
953
|
+
verts.push(omx, omy);
|
|
954
|
+
}
|
|
955
|
+
} else {
|
|
956
|
+
verts.push(imx, imy);
|
|
957
|
+
verts.push(omx, omy);
|
|
958
|
+
}
|
|
1319
959
|
} else {
|
|
1320
|
-
|
|
960
|
+
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
|
|
961
|
+
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
|
|
962
|
+
if (style.join === "round") {
|
|
963
|
+
if (clockwise) {
|
|
964
|
+
indexCount += round(
|
|
965
|
+
x1,
|
|
966
|
+
y1,
|
|
967
|
+
x1 + perpX * outerWeight,
|
|
968
|
+
y1 + perpY * outerWeight,
|
|
969
|
+
x1 + perp1x * outerWeight,
|
|
970
|
+
y1 + perp1y * outerWeight,
|
|
971
|
+
verts,
|
|
972
|
+
true
|
|
973
|
+
) + 2;
|
|
974
|
+
} else {
|
|
975
|
+
indexCount += round(
|
|
976
|
+
x1,
|
|
977
|
+
y1,
|
|
978
|
+
x1 - perpX * innerWeight,
|
|
979
|
+
y1 - perpY * innerWeight,
|
|
980
|
+
x1 - perp1x * innerWeight,
|
|
981
|
+
y1 - perp1y * innerWeight,
|
|
982
|
+
verts,
|
|
983
|
+
false
|
|
984
|
+
) + 2;
|
|
985
|
+
}
|
|
986
|
+
} else if (style.join === "miter" && pDist / widthSquared <= miterLimitSquared) {
|
|
987
|
+
if (clockwise) {
|
|
988
|
+
verts.push(omx, omy);
|
|
989
|
+
verts.push(omx, omy);
|
|
990
|
+
} else {
|
|
991
|
+
verts.push(imx, imy);
|
|
992
|
+
verts.push(imx, imy);
|
|
993
|
+
}
|
|
994
|
+
indexCount += 2;
|
|
995
|
+
}
|
|
996
|
+
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
|
|
997
|
+
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
|
|
998
|
+
indexCount += 2;
|
|
1321
999
|
}
|
|
1322
|
-
index++;
|
|
1323
|
-
return match;
|
|
1324
|
-
});
|
|
1325
|
-
path.currentCurve.autoClose = false;
|
|
1326
|
-
return path;
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
function parseRectNode(node) {
|
|
1330
|
-
const x = parseFloatWithUnits(node.getAttribute("x") || 0);
|
|
1331
|
-
const y = parseFloatWithUnits(node.getAttribute("y") || 0);
|
|
1332
|
-
const rx = parseFloatWithUnits(node.getAttribute("rx") || node.getAttribute("ry") || 0);
|
|
1333
|
-
const ry = parseFloatWithUnits(node.getAttribute("ry") || node.getAttribute("rx") || 0);
|
|
1334
|
-
const w = parseFloatWithUnits(node.getAttribute("width"));
|
|
1335
|
-
const h = parseFloatWithUnits(node.getAttribute("height"));
|
|
1336
|
-
const bci = 1 - 0.551915024494;
|
|
1337
|
-
const path = new Path2D();
|
|
1338
|
-
path.moveTo(x + rx, y);
|
|
1339
|
-
path.lineTo(x + w - rx, y);
|
|
1340
|
-
if (rx !== 0 || ry !== 0) {
|
|
1341
|
-
path.bezierCurveTo(
|
|
1342
|
-
x + w - rx * bci,
|
|
1343
|
-
y,
|
|
1344
|
-
x + w,
|
|
1345
|
-
y + ry * bci,
|
|
1346
|
-
x + w,
|
|
1347
|
-
y + ry
|
|
1348
|
-
);
|
|
1349
|
-
}
|
|
1350
|
-
path.lineTo(x + w, y + h - ry);
|
|
1351
|
-
if (rx !== 0 || ry !== 0) {
|
|
1352
|
-
path.bezierCurveTo(
|
|
1353
|
-
x + w,
|
|
1354
|
-
y + h - ry * bci,
|
|
1355
|
-
x + w - rx * bci,
|
|
1356
|
-
y + h,
|
|
1357
|
-
x + w - rx,
|
|
1358
|
-
y + h
|
|
1359
|
-
);
|
|
1360
1000
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1001
|
+
x0 = points[(length - 2) * 2];
|
|
1002
|
+
y0 = points[(length - 2) * 2 + 1];
|
|
1003
|
+
x1 = points[(length - 1) * 2];
|
|
1004
|
+
y1 = points[(length - 1) * 2 + 1];
|
|
1005
|
+
perpX = -(y0 - y1);
|
|
1006
|
+
perpY = x0 - x1;
|
|
1007
|
+
dist = Math.sqrt(perpX * perpX + perpY * perpY);
|
|
1008
|
+
perpX /= dist;
|
|
1009
|
+
perpY /= dist;
|
|
1010
|
+
perpX *= width;
|
|
1011
|
+
perpY *= width;
|
|
1012
|
+
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
|
|
1013
|
+
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
|
|
1014
|
+
if (!closedShape) {
|
|
1015
|
+
if (style.cap === "round") {
|
|
1016
|
+
indexCount += round(
|
|
1017
|
+
x1 - perpX * (innerWeight - outerWeight) * 0.5,
|
|
1018
|
+
y1 - perpY * (innerWeight - outerWeight) * 0.5,
|
|
1019
|
+
x1 - perpX * innerWeight,
|
|
1020
|
+
y1 - perpY * innerWeight,
|
|
1021
|
+
x1 + perpX * outerWeight,
|
|
1022
|
+
y1 + perpY * outerWeight,
|
|
1023
|
+
verts,
|
|
1024
|
+
false
|
|
1025
|
+
) + 2;
|
|
1026
|
+
} else if (style.cap === "square") {
|
|
1027
|
+
indexCount += square(x1, y1, perpX, perpY, innerWeight, outerWeight, false, verts);
|
|
1028
|
+
}
|
|
1371
1029
|
}
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1030
|
+
const eps2 = curveEps * curveEps;
|
|
1031
|
+
for (let i = indexStart; i < indexCount + indexStart - 2; ++i) {
|
|
1032
|
+
x0 = verts[i * 2];
|
|
1033
|
+
y0 = verts[i * 2 + 1];
|
|
1034
|
+
x1 = verts[(i + 1) * 2];
|
|
1035
|
+
y1 = verts[(i + 1) * 2 + 1];
|
|
1036
|
+
x2 = verts[(i + 2) * 2];
|
|
1037
|
+
y2 = verts[(i + 2) * 2 + 1];
|
|
1038
|
+
if (Math.abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) < eps2) {
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
indices.push(i, i + 1, i + 2);
|
|
1375
1042
|
}
|
|
1376
|
-
return
|
|
1043
|
+
return {
|
|
1044
|
+
vertices,
|
|
1045
|
+
indices
|
|
1046
|
+
};
|
|
1377
1047
|
}
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
if (node.hasAttribute("class")) {
|
|
1383
|
-
const classSelectors = node.getAttribute("class").split(/\s/).filter(Boolean).map((i) => i.trim());
|
|
1384
|
-
for (let i = 0; i < classSelectors.length; i++) {
|
|
1385
|
-
stylesheetStyles = Object.assign(stylesheetStyles, stylesheets[`.${classSelectors[i]}`]);
|
|
1386
|
-
}
|
|
1048
|
+
function getOrientationOfPoints(points) {
|
|
1049
|
+
const m = points.length;
|
|
1050
|
+
if (m < 6) {
|
|
1051
|
+
return 1;
|
|
1387
1052
|
}
|
|
1388
|
-
|
|
1389
|
-
|
|
1053
|
+
let area = 0;
|
|
1054
|
+
for (let i = 0, x1 = points[m - 2], y1 = points[m - 1]; i < m; i += 2) {
|
|
1055
|
+
const x2 = points[i];
|
|
1056
|
+
const y2 = points[i + 1];
|
|
1057
|
+
area += (x2 - x1) * (y2 + y1);
|
|
1058
|
+
x1 = x2;
|
|
1059
|
+
y1 = y2;
|
|
1390
1060
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
const value = node.style.getPropertyValue(name);
|
|
1394
|
-
style[name] = value;
|
|
1395
|
-
stylesheetStyles[name] = value;
|
|
1061
|
+
if (area < 0) {
|
|
1062
|
+
return -1;
|
|
1396
1063
|
}
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1064
|
+
return 1;
|
|
1065
|
+
}
|
|
1066
|
+
function square(x, y, nx, ny, innerWeight, outerWeight, clockwise, verts) {
|
|
1067
|
+
const ix = x - nx * innerWeight;
|
|
1068
|
+
const iy = y - ny * innerWeight;
|
|
1069
|
+
const ox = x + nx * outerWeight;
|
|
1070
|
+
const oy = y + ny * outerWeight;
|
|
1071
|
+
let exx;
|
|
1072
|
+
let eyy;
|
|
1073
|
+
if (clockwise) {
|
|
1074
|
+
exx = ny;
|
|
1075
|
+
eyy = -nx;
|
|
1076
|
+
} else {
|
|
1077
|
+
exx = -ny;
|
|
1078
|
+
eyy = nx;
|
|
1410
1079
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1080
|
+
const eix = ix + exx;
|
|
1081
|
+
const eiy = iy + eyy;
|
|
1082
|
+
const eox = ox + exx;
|
|
1083
|
+
const eoy = oy + eyy;
|
|
1084
|
+
verts.push(eix, eiy);
|
|
1085
|
+
verts.push(eox, eoy);
|
|
1086
|
+
return 2;
|
|
1087
|
+
}
|
|
1088
|
+
function round(cx, cy, sx, sy, ex, ey, verts, clockwise) {
|
|
1089
|
+
const cx2p0x = sx - cx;
|
|
1090
|
+
const cy2p0y = sy - cy;
|
|
1091
|
+
let angle0 = Math.atan2(cx2p0x, cy2p0y);
|
|
1092
|
+
let angle1 = Math.atan2(ex - cx, ey - cy);
|
|
1093
|
+
if (clockwise && angle0 < angle1) {
|
|
1094
|
+
angle0 += Math.PI * 2;
|
|
1095
|
+
} else if (!clockwise && angle0 > angle1) {
|
|
1096
|
+
angle1 += Math.PI * 2;
|
|
1413
1097
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1098
|
+
let startAngle = angle0;
|
|
1099
|
+
const angleDiff = angle1 - angle0;
|
|
1100
|
+
const absAngleDiff = Math.abs(angleDiff);
|
|
1101
|
+
const radius = Math.sqrt(cx2p0x * cx2p0x + cy2p0y * cy2p0y);
|
|
1102
|
+
const segCount = (15 * absAngleDiff * Math.sqrt(radius) / Math.PI >> 0) + 1;
|
|
1103
|
+
const angleInc = angleDiff / segCount;
|
|
1104
|
+
startAngle += angleInc;
|
|
1105
|
+
if (clockwise) {
|
|
1106
|
+
verts.push(cx, cy);
|
|
1107
|
+
verts.push(sx, sy);
|
|
1108
|
+
for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
|
|
1109
|
+
verts.push(cx, cy);
|
|
1110
|
+
verts.push(cx + Math.sin(angle) * radius, cy + Math.cos(angle) * radius);
|
|
1111
|
+
}
|
|
1112
|
+
verts.push(cx, cy);
|
|
1113
|
+
verts.push(ex, ey);
|
|
1114
|
+
} else {
|
|
1115
|
+
verts.push(sx, sy);
|
|
1116
|
+
verts.push(cx, cy);
|
|
1117
|
+
for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
|
|
1118
|
+
verts.push(cx + Math.sin(angle) * radius, cy + Math.cos(angle) * radius);
|
|
1119
|
+
verts.push(cx, cy);
|
|
1120
|
+
}
|
|
1121
|
+
verts.push(ex, ey);
|
|
1122
|
+
verts.push(cx, cy);
|
|
1416
1123
|
}
|
|
1417
|
-
|
|
1418
|
-
addStyle("fill-opacity", "fillOpacity", clamp);
|
|
1419
|
-
addStyle("fill-rule", "fillRule");
|
|
1420
|
-
addStyle("opacity", "opacity", clamp);
|
|
1421
|
-
addStyle("stroke", "stroke");
|
|
1422
|
-
addStyle("stroke-opacity", "strokeOpacity", clamp);
|
|
1423
|
-
addStyle("stroke-width", "strokeWidth", positive);
|
|
1424
|
-
addStyle("stroke-linecap", "strokeLinecap");
|
|
1425
|
-
addStyle("stroke-linejoin", "strokeLinejoin");
|
|
1426
|
-
addStyle("stroke-miterlimit", "strokeMiterlimit", positive);
|
|
1427
|
-
addStyle("stroke-dasharray", "strokeDasharray", array);
|
|
1428
|
-
addStyle("stroke-dashoffset", "strokeDashoffset", parseFloatWithUnits);
|
|
1429
|
-
addStyle("visibility", "visibility");
|
|
1430
|
-
return style;
|
|
1124
|
+
return segCount * 2;
|
|
1431
1125
|
}
|
|
1432
1126
|
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1127
|
+
class Transform2D {
|
|
1128
|
+
constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
|
|
1129
|
+
this.a = a;
|
|
1130
|
+
this.b = b;
|
|
1131
|
+
this.c = c;
|
|
1132
|
+
this.d = d;
|
|
1133
|
+
this.tx = tx;
|
|
1134
|
+
this.ty = ty;
|
|
1135
|
+
}
|
|
1136
|
+
_array;
|
|
1137
|
+
set(a, b, c, d, tx, ty) {
|
|
1138
|
+
this.a = a;
|
|
1139
|
+
this.b = b;
|
|
1140
|
+
this.c = c;
|
|
1141
|
+
this.d = d;
|
|
1142
|
+
this.tx = tx;
|
|
1143
|
+
this.ty = ty;
|
|
1144
|
+
return this;
|
|
1145
|
+
}
|
|
1146
|
+
append(t2d) {
|
|
1147
|
+
const a1 = this.a;
|
|
1148
|
+
const b1 = this.b;
|
|
1149
|
+
const c1 = this.c;
|
|
1150
|
+
const d1 = this.d;
|
|
1151
|
+
this.a = t2d.a * a1 + t2d.b * c1;
|
|
1152
|
+
this.b = t2d.a * b1 + t2d.b * d1;
|
|
1153
|
+
this.c = t2d.c * a1 + t2d.d * c1;
|
|
1154
|
+
this.d = t2d.c * b1 + t2d.d * d1;
|
|
1155
|
+
this.tx = t2d.tx * a1 + t2d.ty * c1 + this.tx;
|
|
1156
|
+
this.ty = t2d.tx * b1 + t2d.ty * d1 + this.ty;
|
|
1157
|
+
return this;
|
|
1158
|
+
}
|
|
1159
|
+
appendFrom(a, b) {
|
|
1160
|
+
const a1 = a.a;
|
|
1161
|
+
const b1 = a.b;
|
|
1162
|
+
const c1 = a.c;
|
|
1163
|
+
const d1 = a.d;
|
|
1164
|
+
const tx = a.tx;
|
|
1165
|
+
const ty = a.ty;
|
|
1166
|
+
const a2 = b.a;
|
|
1167
|
+
const b2 = b.b;
|
|
1168
|
+
const c2 = b.c;
|
|
1169
|
+
const d2 = b.d;
|
|
1170
|
+
this.a = a1 * a2 + b1 * c2;
|
|
1171
|
+
this.b = a1 * b2 + b1 * d2;
|
|
1172
|
+
this.c = c1 * a2 + d1 * c2;
|
|
1173
|
+
this.d = c1 * b2 + d1 * d2;
|
|
1174
|
+
this.tx = tx * a2 + ty * c2 + b.tx;
|
|
1175
|
+
this.ty = tx * b2 + ty * d2 + b.ty;
|
|
1176
|
+
return this;
|
|
1177
|
+
}
|
|
1178
|
+
setTransform(x, y, pivotX, pivotY, scaleX, scaleY, rotation, skewX, skewY) {
|
|
1179
|
+
this.a = Math.cos(rotation + skewY) * scaleX;
|
|
1180
|
+
this.b = Math.sin(rotation + skewY) * scaleX;
|
|
1181
|
+
this.c = -Math.sin(rotation - skewX) * scaleY;
|
|
1182
|
+
this.d = Math.cos(rotation - skewX) * scaleY;
|
|
1183
|
+
this.tx = x - (pivotX * this.a + pivotY * this.c);
|
|
1184
|
+
this.ty = y - (pivotX * this.b + pivotY * this.d);
|
|
1185
|
+
return this;
|
|
1186
|
+
}
|
|
1187
|
+
prepend(t2d) {
|
|
1188
|
+
const tx1 = this.tx;
|
|
1189
|
+
if (t2d.a !== 1 || t2d.b !== 0 || t2d.c !== 0 || t2d.d !== 1) {
|
|
1190
|
+
const a1 = this.a;
|
|
1191
|
+
const c1 = this.c;
|
|
1192
|
+
this.a = a1 * t2d.a + this.b * t2d.c;
|
|
1193
|
+
this.b = a1 * t2d.b + this.b * t2d.d;
|
|
1194
|
+
this.c = c1 * t2d.a + this.d * t2d.c;
|
|
1195
|
+
this.d = c1 * t2d.b + this.d * t2d.d;
|
|
1492
1196
|
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1197
|
+
this.tx = tx1 * t2d.a + this.ty * t2d.c + t2d.tx;
|
|
1198
|
+
this.ty = tx1 * t2d.b + this.ty * t2d.d + t2d.ty;
|
|
1199
|
+
return this;
|
|
1496
1200
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1201
|
+
_skewX;
|
|
1202
|
+
_skewY;
|
|
1203
|
+
_skewXTan = 1;
|
|
1204
|
+
_skewYTan = 1;
|
|
1205
|
+
skewX(x) {
|
|
1206
|
+
return this.skew(x, 0);
|
|
1499
1207
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
const transform = getNodeTransform(node, currentTransform, transformStack);
|
|
1503
|
-
if (path) {
|
|
1504
|
-
path.applyTransform(currentTransform);
|
|
1505
|
-
paths.push(path);
|
|
1506
|
-
path.style = { ..._style };
|
|
1208
|
+
skewY(y) {
|
|
1209
|
+
return this.skew(0, y);
|
|
1507
1210
|
}
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1211
|
+
skew(x, y) {
|
|
1212
|
+
if (x !== this._skewX) {
|
|
1213
|
+
this._skewX = x;
|
|
1214
|
+
this._skewXTan = Math.tan(x);
|
|
1215
|
+
}
|
|
1216
|
+
if (y !== this._skewY) {
|
|
1217
|
+
this._skewY = y;
|
|
1218
|
+
this._skewYTan = Math.tan(y);
|
|
1219
|
+
}
|
|
1220
|
+
this.b *= this._skewXTan;
|
|
1221
|
+
this.c *= this._skewYTan;
|
|
1222
|
+
return this;
|
|
1514
1223
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1224
|
+
translateX(x) {
|
|
1225
|
+
return this.translate(x, 0);
|
|
1226
|
+
}
|
|
1227
|
+
translateY(y) {
|
|
1228
|
+
return this.translate(0, y);
|
|
1229
|
+
}
|
|
1230
|
+
translateZ(z) {
|
|
1231
|
+
return this.translate(0, 0, z);
|
|
1232
|
+
}
|
|
1233
|
+
translate3d(x, y, z) {
|
|
1234
|
+
return this.translate(x, y, z);
|
|
1235
|
+
}
|
|
1236
|
+
translate(x, y, _z = 0) {
|
|
1237
|
+
this.tx += x;
|
|
1238
|
+
this.ty += y;
|
|
1239
|
+
return this;
|
|
1240
|
+
}
|
|
1241
|
+
scaleX(x) {
|
|
1242
|
+
return this.scale(x, 1);
|
|
1243
|
+
}
|
|
1244
|
+
scaleY(y) {
|
|
1245
|
+
return this.scale(1, y);
|
|
1246
|
+
}
|
|
1247
|
+
scale3d(x, y, z = 1) {
|
|
1248
|
+
return this.scale(x, y, z);
|
|
1249
|
+
}
|
|
1250
|
+
scale(x, y, _z = 1) {
|
|
1251
|
+
this.a *= x;
|
|
1252
|
+
this.d *= y;
|
|
1253
|
+
this.c *= x;
|
|
1254
|
+
this.b *= y;
|
|
1255
|
+
this.tx *= x;
|
|
1256
|
+
this.ty *= y;
|
|
1257
|
+
return this;
|
|
1258
|
+
}
|
|
1259
|
+
rotateX(x) {
|
|
1260
|
+
return this.scaleY(this._rotateToScale(x));
|
|
1261
|
+
}
|
|
1262
|
+
rotateY(y) {
|
|
1263
|
+
return this.scaleX(this._rotateToScale(y));
|
|
1264
|
+
}
|
|
1265
|
+
rotateZ(z) {
|
|
1266
|
+
return this.rotate(z);
|
|
1267
|
+
}
|
|
1268
|
+
rotate(angle) {
|
|
1269
|
+
const cos = Math.cos(angle);
|
|
1270
|
+
const sin = Math.sin(angle);
|
|
1271
|
+
const a1 = this.a;
|
|
1272
|
+
const c1 = this.c;
|
|
1273
|
+
const tx1 = this.tx;
|
|
1274
|
+
this.a = a1 * cos - this.b * sin;
|
|
1275
|
+
this.b = a1 * sin + this.b * cos;
|
|
1276
|
+
this.c = c1 * cos - this.d * sin;
|
|
1277
|
+
this.d = c1 * sin + this.d * cos;
|
|
1278
|
+
this.tx = tx1 * cos - this.ty * sin;
|
|
1279
|
+
this.ty = tx1 * sin + this.ty * cos;
|
|
1280
|
+
return this;
|
|
1281
|
+
}
|
|
1282
|
+
rotate3d(x, y, z, rad) {
|
|
1283
|
+
const [rx, ry, rz] = this._rotate3d(x, y, z, rad);
|
|
1284
|
+
rx && this.rotateX(rx);
|
|
1285
|
+
ry && this.rotateY(ry);
|
|
1286
|
+
rz && this.rotateZ(rz);
|
|
1287
|
+
return this;
|
|
1288
|
+
}
|
|
1289
|
+
_rotateToScale(rad) {
|
|
1290
|
+
const val = rad / PI_2;
|
|
1291
|
+
return val <= 0.5 ? val * -4 + 1 : (val - 1) * 4 + 1;
|
|
1292
|
+
}
|
|
1293
|
+
_rotate3d(x, y, z, rad) {
|
|
1294
|
+
if (x === 1 && y === 0 && z === 0) {
|
|
1295
|
+
return [rad, 0, 0];
|
|
1296
|
+
} else if (x === 0 && y === 1 && z === 0) {
|
|
1297
|
+
return [0, rad, 0];
|
|
1298
|
+
} else if (x === 0 && y === 0) {
|
|
1299
|
+
return [0, 0, rad];
|
|
1519
1300
|
} else {
|
|
1520
|
-
|
|
1301
|
+
const cos = Math.cos(rad);
|
|
1302
|
+
const sin = Math.sin(rad);
|
|
1303
|
+
const m11 = cos + x * x * (1 - cos);
|
|
1304
|
+
const m12 = x * y * (1 - cos) - z * sin;
|
|
1305
|
+
const m13 = x * z * (1 - cos) + y * sin;
|
|
1306
|
+
const m22 = cos + y * y * (1 - cos);
|
|
1307
|
+
const m23 = y * z * (1 - cos) - x * sin;
|
|
1308
|
+
const m33 = cos + z * z * (1 - cos);
|
|
1309
|
+
const rotateX = -Math.atan2(-m23, m22);
|
|
1310
|
+
const rotateY = -Math.atan2(m13, Math.sqrt(m23 * m23 + m33 * m33));
|
|
1311
|
+
const rotateZ = -Math.atan2(-m12, m11);
|
|
1312
|
+
return [rotateX, rotateY, rotateZ];
|
|
1521
1313
|
}
|
|
1522
1314
|
}
|
|
1523
|
-
|
|
1315
|
+
decompose(pivot = { x: 0, y: 0 }, output = {
|
|
1316
|
+
position: { x: 0, y: 0 },
|
|
1317
|
+
scale: { x: 0, y: 0 },
|
|
1318
|
+
skew: { x: 0, y: 0 },
|
|
1319
|
+
rotation: 0
|
|
1320
|
+
}) {
|
|
1321
|
+
const { a, b, c, d, tx, ty } = this;
|
|
1322
|
+
const skewX = -Math.atan2(-c, d);
|
|
1323
|
+
const skewY = Math.atan2(b, a);
|
|
1324
|
+
const delta = Math.abs(skewX + skewY);
|
|
1325
|
+
if (delta < 1e-5 || Math.abs(PI_2 - delta) < 1e-5) {
|
|
1326
|
+
output.rotation = skewY;
|
|
1327
|
+
output.skew.x = output.skew.y = 0;
|
|
1328
|
+
} else {
|
|
1329
|
+
output.rotation = 0;
|
|
1330
|
+
output.skew.x = skewX;
|
|
1331
|
+
output.skew.y = skewY;
|
|
1332
|
+
}
|
|
1333
|
+
output.scale.x = Math.sqrt(a * a + b * b);
|
|
1334
|
+
output.scale.y = Math.sqrt(c * c + d * d);
|
|
1335
|
+
output.position.x = tx + (pivot.x * a + pivot.y * c);
|
|
1336
|
+
output.position.y = ty + (pivot.x * b + pivot.y * d);
|
|
1337
|
+
return output;
|
|
1338
|
+
}
|
|
1339
|
+
apply(pos, newPos) {
|
|
1340
|
+
newPos = newPos || new Vector2();
|
|
1341
|
+
const { x, y } = pos;
|
|
1342
|
+
newPos.x = this.a * x + this.c * y + this.tx;
|
|
1343
|
+
newPos.y = this.b * x + this.d * y + this.ty;
|
|
1344
|
+
return newPos;
|
|
1345
|
+
}
|
|
1346
|
+
affineInvert() {
|
|
1347
|
+
const a1 = this.a;
|
|
1348
|
+
const b1 = this.b;
|
|
1349
|
+
const c1 = this.c;
|
|
1350
|
+
const d1 = this.d;
|
|
1351
|
+
const tx1 = this.tx;
|
|
1352
|
+
const n = a1 * d1 - b1 * c1;
|
|
1353
|
+
this.a = d1 / n;
|
|
1354
|
+
this.b = -b1 / n;
|
|
1355
|
+
this.c = -c1 / n;
|
|
1356
|
+
this.d = a1 / n;
|
|
1357
|
+
this.tx = (c1 * this.ty - d1 * tx1) / n;
|
|
1358
|
+
this.ty = -(a1 * this.ty - b1 * tx1) / n;
|
|
1359
|
+
return this;
|
|
1360
|
+
}
|
|
1361
|
+
affineInverse() {
|
|
1362
|
+
return this.clone().affineInvert();
|
|
1363
|
+
}
|
|
1364
|
+
applyAffineInverse(pos, newPos) {
|
|
1365
|
+
newPos = newPos || new Vector2();
|
|
1366
|
+
const { a, b, c, d, tx, ty } = this;
|
|
1367
|
+
const id = 1 / (a * d + c * -b);
|
|
1368
|
+
const x = pos.x;
|
|
1369
|
+
const y = pos.y;
|
|
1370
|
+
newPos.x = d * id * x + -c * id * y + (ty * c - tx * d) * id;
|
|
1371
|
+
newPos.y = a * id * y + -b * id * x + (-ty * a + tx * b) * id;
|
|
1372
|
+
return newPos;
|
|
1373
|
+
}
|
|
1374
|
+
identity() {
|
|
1375
|
+
this.a = 1;
|
|
1376
|
+
this.b = 0;
|
|
1377
|
+
this.c = 0;
|
|
1378
|
+
this.d = 1;
|
|
1379
|
+
this.tx = 0;
|
|
1380
|
+
this.ty = 0;
|
|
1381
|
+
return this;
|
|
1382
|
+
}
|
|
1383
|
+
isIdentity() {
|
|
1384
|
+
const { a, b, c, d, tx, ty } = this;
|
|
1385
|
+
return a === 1 && b === 0 && c === 0 && d === 1 && tx === 0 && ty === 0;
|
|
1386
|
+
}
|
|
1387
|
+
copyTo(t2d) {
|
|
1388
|
+
t2d.a = this.a;
|
|
1389
|
+
t2d.b = this.b;
|
|
1390
|
+
t2d.c = this.c;
|
|
1391
|
+
t2d.d = this.d;
|
|
1392
|
+
t2d.tx = this.tx;
|
|
1393
|
+
t2d.ty = this.ty;
|
|
1394
|
+
return t2d;
|
|
1395
|
+
}
|
|
1396
|
+
copyFrom(t2d) {
|
|
1397
|
+
this.a = t2d.a;
|
|
1398
|
+
this.b = t2d.b;
|
|
1399
|
+
this.c = t2d.c;
|
|
1400
|
+
this.d = t2d.d;
|
|
1401
|
+
this.tx = t2d.tx;
|
|
1402
|
+
this.ty = t2d.ty;
|
|
1403
|
+
return this;
|
|
1404
|
+
}
|
|
1405
|
+
equals(t2d) {
|
|
1406
|
+
return t2d.a === this.a && t2d.b === this.b && t2d.c === this.c && t2d.d === this.d && t2d.tx === this.tx && t2d.ty === this.ty;
|
|
1407
|
+
}
|
|
1408
|
+
appendCssTransform(cssTransform, ctx = {}) {
|
|
1409
|
+
const { width = 1, height = 1 } = ctx;
|
|
1410
|
+
const output = new Transform2D();
|
|
1411
|
+
parseCssFunctions(cssTransform, { width, height }).reverse().forEach(({ name, args }) => {
|
|
1412
|
+
const values = args.map((arg) => arg.normalizedIntValue);
|
|
1413
|
+
switch (name) {
|
|
1414
|
+
case "translate":
|
|
1415
|
+
output.translate(values[0] * width, (values[1] ?? values[0]) * height);
|
|
1416
|
+
break;
|
|
1417
|
+
case "translateX":
|
|
1418
|
+
output.translateX(values[0] * width);
|
|
1419
|
+
break;
|
|
1420
|
+
case "translateY":
|
|
1421
|
+
output.translateY(values[0] * height);
|
|
1422
|
+
break;
|
|
1423
|
+
case "translateZ":
|
|
1424
|
+
output.translateZ(values[0]);
|
|
1425
|
+
break;
|
|
1426
|
+
case "translate3d":
|
|
1427
|
+
output.translate3d(
|
|
1428
|
+
values[0] * width,
|
|
1429
|
+
(values[1] ?? values[0]) * height,
|
|
1430
|
+
values[2] ?? values[1] ?? values[0]
|
|
1431
|
+
);
|
|
1432
|
+
break;
|
|
1433
|
+
case "scale":
|
|
1434
|
+
output.scale(values[0], values[1] ?? values[0]);
|
|
1435
|
+
break;
|
|
1436
|
+
case "scaleX":
|
|
1437
|
+
output.scaleX(values[0]);
|
|
1438
|
+
break;
|
|
1439
|
+
case "scaleY":
|
|
1440
|
+
output.scaleY(values[0]);
|
|
1441
|
+
break;
|
|
1442
|
+
case "scale3d":
|
|
1443
|
+
output.scale3d(values[0], values[1] ?? values[0], values[2] ?? values[1] ?? values[0]);
|
|
1444
|
+
break;
|
|
1445
|
+
case "rotate":
|
|
1446
|
+
output.rotate(values[0] * PI_2);
|
|
1447
|
+
break;
|
|
1448
|
+
case "rotateX":
|
|
1449
|
+
output.rotateX(values[0] * PI_2);
|
|
1450
|
+
break;
|
|
1451
|
+
case "rotateY":
|
|
1452
|
+
output.rotateY(values[0] * PI_2);
|
|
1453
|
+
break;
|
|
1454
|
+
case "rotateZ":
|
|
1455
|
+
output.rotateZ(values[0] * PI_2);
|
|
1456
|
+
break;
|
|
1457
|
+
case "rotate3d":
|
|
1458
|
+
output.rotate3d(
|
|
1459
|
+
values[0] * PI_2,
|
|
1460
|
+
(values[1] ?? values[0]) * PI_2,
|
|
1461
|
+
(values[2] ?? values[1] ?? values[0]) * PI_2,
|
|
1462
|
+
(values[3] ?? values[2] ?? values[1] ?? values[0]) * PI_2
|
|
1463
|
+
);
|
|
1464
|
+
break;
|
|
1465
|
+
case "skew":
|
|
1466
|
+
output.skew(values[0], values[0] ?? values[1]);
|
|
1467
|
+
break;
|
|
1468
|
+
case "skewX":
|
|
1469
|
+
output.skewX(values[0]);
|
|
1470
|
+
break;
|
|
1471
|
+
case "skewY":
|
|
1472
|
+
output.skewY(values[0]);
|
|
1473
|
+
break;
|
|
1474
|
+
case "matrix":
|
|
1475
|
+
output.set(values[0], values[1], values[2], values[3], values[4], values[5]);
|
|
1476
|
+
break;
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
this.prepend(output);
|
|
1480
|
+
return this;
|
|
1481
|
+
}
|
|
1482
|
+
clone() {
|
|
1483
|
+
return new Transform2D(this.a, this.b, this.c, this.d, this.tx, this.ty);
|
|
1484
|
+
}
|
|
1485
|
+
toArray(transpose, out) {
|
|
1486
|
+
if (!this._array) {
|
|
1487
|
+
this._array = new Float32Array(9);
|
|
1488
|
+
}
|
|
1489
|
+
const array = out || this._array;
|
|
1490
|
+
if (transpose) {
|
|
1491
|
+
array[0] = this.a;
|
|
1492
|
+
array[1] = this.b;
|
|
1493
|
+
array[2] = 0;
|
|
1494
|
+
array[3] = this.c;
|
|
1495
|
+
array[4] = this.d;
|
|
1496
|
+
array[5] = 0;
|
|
1497
|
+
array[6] = this.tx;
|
|
1498
|
+
array[7] = this.ty;
|
|
1499
|
+
array[8] = 1;
|
|
1500
|
+
} else {
|
|
1501
|
+
array[0] = this.a;
|
|
1502
|
+
array[1] = this.c;
|
|
1503
|
+
array[2] = this.tx;
|
|
1504
|
+
array[3] = this.b;
|
|
1505
|
+
array[4] = this.d;
|
|
1506
|
+
array[5] = this.ty;
|
|
1507
|
+
array[6] = 0;
|
|
1508
|
+
array[7] = 0;
|
|
1509
|
+
array[8] = 1;
|
|
1510
|
+
}
|
|
1511
|
+
return array;
|
|
1512
|
+
}
|
|
1513
|
+
toString() {
|
|
1514
|
+
return `[Transform2D a=${this.a} b=${this.b} c=${this.c} d=${this.d} tx=${this.tx} ty=${this.ty}]`;
|
|
1515
|
+
}
|
|
1516
|
+
destroy() {
|
|
1517
|
+
this._array = void 0;
|
|
1518
|
+
}
|
|
1524
1519
|
}
|
|
1525
1520
|
|
|
1526
|
-
function
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1521
|
+
function svgAngle(ux, uy, vx, vy) {
|
|
1522
|
+
const dot = ux * vx + uy * vy;
|
|
1523
|
+
const len = Math.sqrt(ux * ux + uy * uy) * Math.sqrt(vx * vx + vy * vy);
|
|
1524
|
+
let ang = Math.acos(Math.max(-1, Math.min(1, dot / len)));
|
|
1525
|
+
if (ux * vy - uy * vx < 0)
|
|
1526
|
+
ang = -ang;
|
|
1527
|
+
return ang;
|
|
1532
1528
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
const
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
const
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1529
|
+
function parseArcCommand(path, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, start, end) {
|
|
1530
|
+
if (rx === 0 || ry === 0) {
|
|
1531
|
+
path.lineTo(end.x, end.y);
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
xAxisRotation = xAxisRotation * Math.PI / 180;
|
|
1535
|
+
rx = Math.abs(rx);
|
|
1536
|
+
ry = Math.abs(ry);
|
|
1537
|
+
const dx2 = (start.x - end.x) / 2;
|
|
1538
|
+
const dy2 = (start.y - end.y) / 2;
|
|
1539
|
+
const x1p = Math.cos(xAxisRotation) * dx2 + Math.sin(xAxisRotation) * dy2;
|
|
1540
|
+
const y1p = -Math.sin(xAxisRotation) * dx2 + Math.cos(xAxisRotation) * dy2;
|
|
1541
|
+
let rxs = rx * rx;
|
|
1542
|
+
let rys = ry * ry;
|
|
1543
|
+
const x1ps = x1p * x1p;
|
|
1544
|
+
const y1ps = y1p * y1p;
|
|
1545
|
+
const cr = x1ps / rxs + y1ps / rys;
|
|
1546
|
+
if (cr > 1) {
|
|
1547
|
+
const s = Math.sqrt(cr);
|
|
1548
|
+
rx = s * rx;
|
|
1549
|
+
ry = s * ry;
|
|
1550
|
+
rxs = rx * rx;
|
|
1551
|
+
rys = ry * ry;
|
|
1552
|
+
}
|
|
1553
|
+
const dq = rxs * y1ps + rys * x1ps;
|
|
1554
|
+
const pq = (rxs * rys - dq) / dq;
|
|
1555
|
+
let q = Math.sqrt(Math.max(0, pq));
|
|
1556
|
+
if (largeArcFlag === sweepFlag)
|
|
1557
|
+
q = -q;
|
|
1558
|
+
const cxp = q * rx * y1p / ry;
|
|
1559
|
+
const cyp = -q * ry * x1p / rx;
|
|
1560
|
+
const cx = Math.cos(xAxisRotation) * cxp - Math.sin(xAxisRotation) * cyp + (start.x + end.x) / 2;
|
|
1561
|
+
const cy = Math.sin(xAxisRotation) * cxp + Math.cos(xAxisRotation) * cyp + (start.y + end.y) / 2;
|
|
1562
|
+
const theta = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
|
|
1563
|
+
const delta = svgAngle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry) % (Math.PI * 2);
|
|
1564
|
+
path.ellipse(cx, cy, rx, ry, xAxisRotation, theta, theta + delta, sweepFlag === 0);
|
|
1558
1565
|
}
|
|
1559
1566
|
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1567
|
+
const RE$3 = {
|
|
1568
|
+
WHITESPACE: /[ \t\r\n]/,
|
|
1569
|
+
DIGIT: /\d/,
|
|
1570
|
+
SIGN: /[-+]/,
|
|
1571
|
+
POINT: /\./,
|
|
1572
|
+
COMMA: /,/,
|
|
1573
|
+
EXP: /e/i,
|
|
1574
|
+
FLAGS: /[01]/
|
|
1575
|
+
};
|
|
1576
|
+
function parsePathDataArgs(input, flags, stride = 0) {
|
|
1577
|
+
const SEP = 0;
|
|
1578
|
+
const INT = 1;
|
|
1579
|
+
const FLOAT = 2;
|
|
1580
|
+
const EXP = 3;
|
|
1581
|
+
let state = SEP;
|
|
1582
|
+
let seenComma = true;
|
|
1583
|
+
let number = "";
|
|
1584
|
+
let exponent = "";
|
|
1585
|
+
const result = [];
|
|
1586
|
+
function throwSyntaxError(current2, i, partial) {
|
|
1587
|
+
const error = new SyntaxError(`Unexpected character "${current2}" at index ${i}.`);
|
|
1588
|
+
error.partial = partial;
|
|
1589
|
+
throw error;
|
|
1590
|
+
}
|
|
1591
|
+
function newNumber() {
|
|
1592
|
+
if (number !== "") {
|
|
1593
|
+
if (exponent === "")
|
|
1594
|
+
result.push(Number(number));
|
|
1595
|
+
else result.push(Number(number) * 10 ** Number(exponent));
|
|
1581
1596
|
}
|
|
1597
|
+
number = "";
|
|
1598
|
+
exponent = "";
|
|
1582
1599
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
|
|
1597
|
-
Math.max(0, smoothness)
|
|
1598
|
-
);
|
|
1599
|
-
let distanceTolerance = (PATH_DISTANCE_EPSILON$1 - smoothing) / scale;
|
|
1600
|
-
distanceTolerance *= distanceTolerance;
|
|
1601
|
-
recursive$1(sX, sY, x1, y1, x2, y2, x, y, points, distanceTolerance, 0);
|
|
1602
|
-
points.push(x, y);
|
|
1603
|
-
return points;
|
|
1604
|
-
}
|
|
1605
|
-
function recursive$1(x1, y1, x2, y2, x3, y3, x4, y4, points, distanceTolerance, level) {
|
|
1606
|
-
if (level > RECURSION_LIMIT$1)
|
|
1607
|
-
return;
|
|
1608
|
-
const x12 = (x1 + x2) / 2;
|
|
1609
|
-
const y12 = (y1 + y2) / 2;
|
|
1610
|
-
const x23 = (x2 + x3) / 2;
|
|
1611
|
-
const y23 = (y2 + y3) / 2;
|
|
1612
|
-
const x34 = (x3 + x4) / 2;
|
|
1613
|
-
const y34 = (y3 + y4) / 2;
|
|
1614
|
-
const x123 = (x12 + x23) / 2;
|
|
1615
|
-
const y123 = (y12 + y23) / 2;
|
|
1616
|
-
const x234 = (x23 + x34) / 2;
|
|
1617
|
-
const y234 = (y23 + y34) / 2;
|
|
1618
|
-
const x1234 = (x123 + x234) / 2;
|
|
1619
|
-
const y1234 = (y123 + y234) / 2;
|
|
1620
|
-
if (level > 0) {
|
|
1621
|
-
let dx = x4 - x1;
|
|
1622
|
-
let dy = y4 - y1;
|
|
1623
|
-
const d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx);
|
|
1624
|
-
const d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx);
|
|
1625
|
-
if (d2 > FLT_EPSILON$1 && d3 > FLT_EPSILON$1) {
|
|
1626
|
-
if ((d2 + d3) * (d2 + d3) <= distanceTolerance * (dx * dx + dy * dy)) {
|
|
1627
|
-
{
|
|
1628
|
-
points.push(x1234, y1234);
|
|
1629
|
-
return;
|
|
1630
|
-
}
|
|
1600
|
+
let current;
|
|
1601
|
+
const length = input.length;
|
|
1602
|
+
for (let i = 0; i < length; i++) {
|
|
1603
|
+
current = input[i];
|
|
1604
|
+
if (Array.isArray(flags) && flags.includes(result.length % stride) && RE$3.FLAGS.test(current)) {
|
|
1605
|
+
state = INT;
|
|
1606
|
+
number = current;
|
|
1607
|
+
newNumber();
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
if (state === SEP) {
|
|
1611
|
+
if (RE$3.WHITESPACE.test(current)) {
|
|
1612
|
+
continue;
|
|
1631
1613
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
return;
|
|
1637
|
-
}
|
|
1614
|
+
if (RE$3.DIGIT.test(current) || RE$3.SIGN.test(current)) {
|
|
1615
|
+
state = INT;
|
|
1616
|
+
number = current;
|
|
1617
|
+
continue;
|
|
1638
1618
|
}
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
return;
|
|
1644
|
-
}
|
|
1619
|
+
if (RE$3.POINT.test(current)) {
|
|
1620
|
+
state = FLOAT;
|
|
1621
|
+
number = current;
|
|
1622
|
+
continue;
|
|
1645
1623
|
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
return;
|
|
1624
|
+
if (RE$3.COMMA.test(current)) {
|
|
1625
|
+
if (seenComma) {
|
|
1626
|
+
throwSyntaxError(current, i, result);
|
|
1627
|
+
}
|
|
1628
|
+
seenComma = true;
|
|
1652
1629
|
}
|
|
1653
1630
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
distanceTolerance *= distanceTolerance;
|
|
1671
|
-
recursive(points, sX, sY, x1, y1, x, y, distanceTolerance, 0);
|
|
1672
|
-
points.push(x, y);
|
|
1673
|
-
return points;
|
|
1674
|
-
}
|
|
1675
|
-
function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
|
|
1676
|
-
if (level > RECURSION_LIMIT)
|
|
1677
|
-
return;
|
|
1678
|
-
const x12 = (x1 + x2) / 2;
|
|
1679
|
-
const y12 = (y1 + y2) / 2;
|
|
1680
|
-
const x23 = (x2 + x3) / 2;
|
|
1681
|
-
const y23 = (y2 + y3) / 2;
|
|
1682
|
-
const x123 = (x12 + x23) / 2;
|
|
1683
|
-
const y123 = (y12 + y23) / 2;
|
|
1684
|
-
let dx = x3 - x1;
|
|
1685
|
-
let dy = y3 - y1;
|
|
1686
|
-
const d = Math.abs((x2 - x3) * dy - (y2 - y3) * dx);
|
|
1687
|
-
if (d > FLT_EPSILON) {
|
|
1688
|
-
if (d * d <= distanceTolerance * (dx * dx + dy * dy)) {
|
|
1689
|
-
{
|
|
1690
|
-
points.push(x123, y123);
|
|
1691
|
-
return;
|
|
1631
|
+
if (state === INT) {
|
|
1632
|
+
if (RE$3.DIGIT.test(current)) {
|
|
1633
|
+
number += current;
|
|
1634
|
+
continue;
|
|
1635
|
+
}
|
|
1636
|
+
if (RE$3.POINT.test(current)) {
|
|
1637
|
+
number += current;
|
|
1638
|
+
state = FLOAT;
|
|
1639
|
+
continue;
|
|
1640
|
+
}
|
|
1641
|
+
if (RE$3.EXP.test(current)) {
|
|
1642
|
+
state = EXP;
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1645
|
+
if (RE$3.SIGN.test(current) && number.length === 1 && RE$3.SIGN.test(number[0])) {
|
|
1646
|
+
throwSyntaxError(current, i, result);
|
|
1692
1647
|
}
|
|
1693
1648
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
points.push(x123, y123);
|
|
1699
|
-
return;
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
recursive(points, x1, y1, x12, y12, x123, y123, distanceTolerance, level + 1);
|
|
1703
|
-
recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
|
-
function getDirectedArea(vertices) {
|
|
1707
|
-
let area = 0;
|
|
1708
|
-
const n = vertices.length;
|
|
1709
|
-
for (let i = 0; i < n; i += 2) {
|
|
1710
|
-
const x0 = vertices[i];
|
|
1711
|
-
const y0 = vertices[i + 1];
|
|
1712
|
-
const x1 = vertices[(i + 2) % (n - 1)];
|
|
1713
|
-
const y1 = vertices[(i + 3) % n];
|
|
1714
|
-
area += x0 * y1 - x1 * y0;
|
|
1715
|
-
}
|
|
1716
|
-
return area / 2;
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
|
-
function toKebabCase(str) {
|
|
1720
|
-
return str.replace(/[^a-z0-9]/gi, "-").replace(/\B([A-Z])/g, "-$1").toLowerCase();
|
|
1721
|
-
}
|
|
1722
|
-
function getIntersectionPoint(p1, p2, q1, q2) {
|
|
1723
|
-
const r = p2.clone().sub(p1);
|
|
1724
|
-
const s = q2.clone().sub(q1);
|
|
1725
|
-
const q1p1 = q1.clone().sub(p1);
|
|
1726
|
-
const crossRS = r.cross(s);
|
|
1727
|
-
if (crossRS === 0) {
|
|
1728
|
-
return new Vector2(
|
|
1729
|
-
(p1.x + q1.x) / 2,
|
|
1730
|
-
(p1.y + q1.y) / 2
|
|
1731
|
-
);
|
|
1732
|
-
}
|
|
1733
|
-
const t = q1p1.cross(s) / crossRS;
|
|
1734
|
-
if (Math.abs(t) > 1) {
|
|
1735
|
-
return new Vector2(
|
|
1736
|
-
(p1.x + q1.x) / 2,
|
|
1737
|
-
(p1.y + q1.y) / 2
|
|
1738
|
-
);
|
|
1739
|
-
}
|
|
1740
|
-
return new Vector2(
|
|
1741
|
-
p1.x + t * r.x,
|
|
1742
|
-
p1.y + t * r.y
|
|
1743
|
-
);
|
|
1744
|
-
}
|
|
1745
|
-
|
|
1746
|
-
function cross(ax, ay, bx, by, cx, cy) {
|
|
1747
|
-
return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
|
|
1748
|
-
}
|
|
1749
|
-
function windingNumber(px, py, polygon) {
|
|
1750
|
-
const polygonLen = polygon.length;
|
|
1751
|
-
let wn = 0;
|
|
1752
|
-
for (let i = 0, j = polygonLen - 2; i < polygonLen; j = i, i += 2) {
|
|
1753
|
-
const xi = polygon[i];
|
|
1754
|
-
const yi = polygon[i + 1];
|
|
1755
|
-
const xj = polygon[j];
|
|
1756
|
-
const yj = polygon[j + 1];
|
|
1757
|
-
if (yi <= py) {
|
|
1758
|
-
if (yj > py && cross(xj, yj, xi, yi, px, py) > 0)
|
|
1759
|
-
wn++;
|
|
1760
|
-
} else {
|
|
1761
|
-
if (yj <= py && cross(xj, yj, xi, yi, px, py) < 0)
|
|
1762
|
-
wn--;
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1765
|
-
return wn;
|
|
1766
|
-
}
|
|
1767
|
-
function distance(p1, p2) {
|
|
1768
|
-
const dx = p2[0] - p1[0];
|
|
1769
|
-
const dy = p2[1] - p1[1];
|
|
1770
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
1771
|
-
}
|
|
1772
|
-
function nonzeroFillRule(paths) {
|
|
1773
|
-
const results = paths.map((_, i) => ({ index: i }));
|
|
1774
|
-
const testPointsGroups = paths.map((path) => {
|
|
1775
|
-
const len = path.length;
|
|
1776
|
-
if (!len) {
|
|
1777
|
-
return [];
|
|
1778
|
-
}
|
|
1779
|
-
let xMinYAuto = [Number.MAX_SAFE_INTEGER, 0];
|
|
1780
|
-
let xAutoYMin = [0, Number.MAX_SAFE_INTEGER];
|
|
1781
|
-
let xMaxYAuto = [Number.MIN_SAFE_INTEGER, 0];
|
|
1782
|
-
let xAutoYMax = [0, Number.MIN_SAFE_INTEGER];
|
|
1783
|
-
for (let i = 0; i < len; i += 2) {
|
|
1784
|
-
const x = path[i];
|
|
1785
|
-
const y = path[i + 1];
|
|
1786
|
-
if (xMinYAuto[0] > x) {
|
|
1787
|
-
xMinYAuto = [x, y];
|
|
1788
|
-
}
|
|
1789
|
-
if (xAutoYMin[1] > y) {
|
|
1790
|
-
xAutoYMin = [x, y];
|
|
1791
|
-
}
|
|
1792
|
-
if (xMaxYAuto[0] < x) {
|
|
1793
|
-
xMaxYAuto = [x, y];
|
|
1794
|
-
}
|
|
1795
|
-
if (xAutoYMax[1] < y) {
|
|
1796
|
-
xAutoYMax = [x, y];
|
|
1797
|
-
}
|
|
1798
|
-
}
|
|
1799
|
-
const mid = [
|
|
1800
|
-
(xMinYAuto[0] + xMaxYAuto[0]) / 2,
|
|
1801
|
-
(xAutoYMin[1] + xAutoYMax[1]) / 2
|
|
1802
|
-
];
|
|
1803
|
-
let xMidYMinDx;
|
|
1804
|
-
let xMidYMaxDx;
|
|
1805
|
-
let xMidYMin;
|
|
1806
|
-
let xMidYMax;
|
|
1807
|
-
let xMinYMidDy;
|
|
1808
|
-
let xMaxYMidDy;
|
|
1809
|
-
let xMinYMid;
|
|
1810
|
-
let xMaxYMid;
|
|
1811
|
-
for (let i = 0; i < len; i += 2) {
|
|
1812
|
-
const x = path[i];
|
|
1813
|
-
const y = path[i + 1];
|
|
1814
|
-
const _dx = Math.abs(x - mid[0]);
|
|
1815
|
-
const _dy = Math.abs(y - mid[1]);
|
|
1816
|
-
if (y < mid[1] && (!xMidYMinDx || _dx < xMidYMinDx)) {
|
|
1817
|
-
xMidYMinDx = _dx;
|
|
1818
|
-
xMidYMin = [x, y];
|
|
1819
|
-
}
|
|
1820
|
-
if (y > mid[1] && (!xMidYMaxDx || _dx < xMidYMaxDx)) {
|
|
1821
|
-
xMidYMaxDx = _dx;
|
|
1822
|
-
xMidYMax = [x, y];
|
|
1649
|
+
if (state === FLOAT) {
|
|
1650
|
+
if (RE$3.DIGIT.test(current)) {
|
|
1651
|
+
number += current;
|
|
1652
|
+
continue;
|
|
1823
1653
|
}
|
|
1824
|
-
if (
|
|
1825
|
-
|
|
1826
|
-
|
|
1654
|
+
if (RE$3.EXP.test(current)) {
|
|
1655
|
+
state = EXP;
|
|
1656
|
+
continue;
|
|
1827
1657
|
}
|
|
1828
|
-
if (
|
|
1829
|
-
|
|
1830
|
-
xMaxYMid = [x, y];
|
|
1658
|
+
if (RE$3.POINT.test(current) && number[number.length - 1] === ".") {
|
|
1659
|
+
throwSyntaxError(current, i, result);
|
|
1831
1660
|
}
|
|
1832
1661
|
}
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
xMaxYAuto,
|
|
1837
|
-
xAutoYMax,
|
|
1838
|
-
xMidYMin,
|
|
1839
|
-
xMidYMax,
|
|
1840
|
-
xMinYMid,
|
|
1841
|
-
xMaxYMid
|
|
1842
|
-
].filter(Boolean);
|
|
1843
|
-
});
|
|
1844
|
-
for (let i = 0, len = paths.length; i < len; i++) {
|
|
1845
|
-
const _results = [];
|
|
1846
|
-
const testPoints = testPointsGroups[i];
|
|
1847
|
-
for (let j = 0; j < len; j++) {
|
|
1848
|
-
if (i === j)
|
|
1662
|
+
if (state === EXP) {
|
|
1663
|
+
if (RE$3.DIGIT.test(current)) {
|
|
1664
|
+
exponent += current;
|
|
1849
1665
|
continue;
|
|
1850
|
-
const wnMap = {};
|
|
1851
|
-
const wnList = [];
|
|
1852
|
-
for (let p = 0, pLen = testPoints.length; p < pLen; p++) {
|
|
1853
|
-
const [x, y] = testPoints[p];
|
|
1854
|
-
const winding = windingNumber(x, y, paths[j]);
|
|
1855
|
-
wnMap[winding] = (wnMap[winding] ?? 0) + 1;
|
|
1856
|
-
wnList.push(winding);
|
|
1857
1666
|
}
|
|
1858
|
-
if (
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
)
|
|
1865
|
-
|
|
1866
|
-
});
|
|
1667
|
+
if (RE$3.SIGN.test(current)) {
|
|
1668
|
+
if (exponent === "") {
|
|
1669
|
+
exponent += current;
|
|
1670
|
+
continue;
|
|
1671
|
+
}
|
|
1672
|
+
if (exponent.length === 1 && RE$3.SIGN.test(exponent)) {
|
|
1673
|
+
throwSyntaxError(current, i, result);
|
|
1674
|
+
}
|
|
1867
1675
|
}
|
|
1868
1676
|
}
|
|
1869
|
-
if (
|
|
1870
|
-
|
|
1871
|
-
|
|
1677
|
+
if (RE$3.WHITESPACE.test(current)) {
|
|
1678
|
+
newNumber();
|
|
1679
|
+
state = SEP;
|
|
1680
|
+
seenComma = false;
|
|
1681
|
+
} else if (RE$3.COMMA.test(current)) {
|
|
1682
|
+
newNumber();
|
|
1683
|
+
state = SEP;
|
|
1684
|
+
seenComma = true;
|
|
1685
|
+
} else if (RE$3.SIGN.test(current)) {
|
|
1686
|
+
newNumber();
|
|
1687
|
+
state = INT;
|
|
1688
|
+
number = current;
|
|
1689
|
+
} else if (RE$3.POINT.test(current)) {
|
|
1690
|
+
newNumber();
|
|
1691
|
+
state = FLOAT;
|
|
1692
|
+
number = current;
|
|
1693
|
+
} else {
|
|
1694
|
+
throwSyntaxError(current, i, result);
|
|
1872
1695
|
}
|
|
1873
1696
|
}
|
|
1874
|
-
|
|
1697
|
+
newNumber();
|
|
1698
|
+
return result;
|
|
1875
1699
|
}
|
|
1876
1700
|
|
|
1877
|
-
function
|
|
1878
|
-
|
|
1879
|
-
return k * k * p;
|
|
1880
|
-
}
|
|
1881
|
-
function quadraticBezierP1(t, p) {
|
|
1882
|
-
return 2 * (1 - t) * t * p;
|
|
1883
|
-
}
|
|
1884
|
-
function quadraticBezierP2(t, p) {
|
|
1885
|
-
return t * t * p;
|
|
1886
|
-
}
|
|
1887
|
-
function quadraticBezier(t, p0, p1, p2) {
|
|
1888
|
-
return quadraticBezierP0(t, p0) + quadraticBezierP1(t, p1) + quadraticBezierP2(t, p2);
|
|
1701
|
+
function getReflection(a, b) {
|
|
1702
|
+
return a - (b - a);
|
|
1889
1703
|
}
|
|
1890
|
-
|
|
1891
|
-
const
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1704
|
+
function svgPathCommandsAddToPath2D(commands, path) {
|
|
1705
|
+
const current = new Vector2();
|
|
1706
|
+
const control = new Vector2();
|
|
1707
|
+
for (let i = 0, l = commands.length; i < l; i++) {
|
|
1708
|
+
const cmd = commands[i];
|
|
1709
|
+
if (cmd.type === "m" || cmd.type === "M") {
|
|
1710
|
+
if (cmd.type === "m") {
|
|
1711
|
+
current.add(cmd);
|
|
1712
|
+
} else {
|
|
1713
|
+
current.copyFrom(cmd);
|
|
1714
|
+
}
|
|
1715
|
+
path.moveTo(current.x, current.y);
|
|
1716
|
+
control.copyFrom(current);
|
|
1717
|
+
} else if (cmd.type === "h" || cmd.type === "H") {
|
|
1718
|
+
if (cmd.type === "h") {
|
|
1719
|
+
current.x += cmd.x;
|
|
1720
|
+
} else {
|
|
1721
|
+
current.x = cmd.x;
|
|
1722
|
+
}
|
|
1723
|
+
path.lineTo(current.x, current.y);
|
|
1724
|
+
control.copyFrom(current);
|
|
1725
|
+
} else if (cmd.type === "v" || cmd.type === "V") {
|
|
1726
|
+
if (cmd.type === "v") {
|
|
1727
|
+
current.y += cmd.y;
|
|
1728
|
+
} else {
|
|
1729
|
+
current.y = cmd.y;
|
|
1730
|
+
}
|
|
1731
|
+
path.lineTo(current.x, current.y);
|
|
1732
|
+
control.copyFrom(current);
|
|
1733
|
+
} else if (cmd.type === "l" || cmd.type === "L") {
|
|
1734
|
+
if (cmd.type === "l") {
|
|
1735
|
+
current.add(cmd);
|
|
1736
|
+
} else {
|
|
1737
|
+
current.copyFrom(cmd);
|
|
1738
|
+
}
|
|
1739
|
+
path.lineTo(current.x, current.y);
|
|
1740
|
+
control.copyFrom(current);
|
|
1741
|
+
} else if (cmd.type === "c" || cmd.type === "C") {
|
|
1742
|
+
if (cmd.type === "c") {
|
|
1743
|
+
path.bezierCurveTo(
|
|
1744
|
+
current.x + cmd.x1,
|
|
1745
|
+
current.y + cmd.y1,
|
|
1746
|
+
current.x + cmd.x2,
|
|
1747
|
+
current.y + cmd.y2,
|
|
1748
|
+
current.x + cmd.x,
|
|
1749
|
+
current.y + cmd.y
|
|
1750
|
+
);
|
|
1751
|
+
control.x = current.x + cmd.x2;
|
|
1752
|
+
control.y = current.y + cmd.y2;
|
|
1753
|
+
current.add(cmd);
|
|
1754
|
+
} else {
|
|
1755
|
+
path.bezierCurveTo(
|
|
1756
|
+
cmd.x1,
|
|
1757
|
+
cmd.y1,
|
|
1758
|
+
cmd.x2,
|
|
1759
|
+
cmd.y2,
|
|
1760
|
+
cmd.x,
|
|
1761
|
+
cmd.y
|
|
1762
|
+
);
|
|
1763
|
+
control.x = cmd.x2;
|
|
1764
|
+
control.y = cmd.y2;
|
|
1765
|
+
current.copyFrom(cmd);
|
|
1766
|
+
}
|
|
1767
|
+
} else if (cmd.type === "s" || cmd.type === "S") {
|
|
1768
|
+
if (cmd.type === "s") {
|
|
1769
|
+
path.bezierCurveTo(
|
|
1770
|
+
getReflection(current.x, control.x),
|
|
1771
|
+
getReflection(current.y, control.y),
|
|
1772
|
+
current.x + cmd.x2,
|
|
1773
|
+
current.y + cmd.y2,
|
|
1774
|
+
current.x + cmd.x,
|
|
1775
|
+
current.y + cmd.y
|
|
1776
|
+
);
|
|
1777
|
+
control.x = current.x + cmd.x2;
|
|
1778
|
+
control.y = current.y + cmd.y2;
|
|
1779
|
+
current.add(cmd);
|
|
1780
|
+
} else {
|
|
1781
|
+
path.bezierCurveTo(
|
|
1782
|
+
getReflection(current.x, control.x),
|
|
1783
|
+
getReflection(current.y, control.y),
|
|
1784
|
+
cmd.x2,
|
|
1785
|
+
cmd.y2,
|
|
1786
|
+
cmd.x,
|
|
1787
|
+
cmd.y
|
|
1788
|
+
);
|
|
1789
|
+
control.x = cmd.x2;
|
|
1790
|
+
control.y = cmd.y2;
|
|
1791
|
+
current.copyFrom(cmd);
|
|
1792
|
+
}
|
|
1793
|
+
} else if (cmd.type === "q" || cmd.type === "Q") {
|
|
1794
|
+
if (cmd.type === "q") {
|
|
1795
|
+
path.quadraticCurveTo(
|
|
1796
|
+
current.x + cmd.x1,
|
|
1797
|
+
current.y + cmd.y1,
|
|
1798
|
+
current.x + cmd.x,
|
|
1799
|
+
current.y + cmd.y
|
|
1800
|
+
);
|
|
1801
|
+
control.x = current.x + cmd.x1;
|
|
1802
|
+
control.y = current.y + cmd.y1;
|
|
1803
|
+
current.add(cmd);
|
|
1804
|
+
} else {
|
|
1805
|
+
path.quadraticCurveTo(
|
|
1806
|
+
cmd.x1,
|
|
1807
|
+
cmd.y1,
|
|
1808
|
+
cmd.x,
|
|
1809
|
+
cmd.y
|
|
1810
|
+
);
|
|
1811
|
+
control.x = cmd.x1;
|
|
1812
|
+
control.y = cmd.y1;
|
|
1813
|
+
current.copyFrom(cmd);
|
|
1814
|
+
}
|
|
1815
|
+
} else if (cmd.type === "t" || cmd.type === "T") {
|
|
1816
|
+
const rx = getReflection(current.x, control.x);
|
|
1817
|
+
const ry = getReflection(current.y, control.y);
|
|
1818
|
+
control.x = rx;
|
|
1819
|
+
control.y = ry;
|
|
1820
|
+
if (cmd.type === "t") {
|
|
1821
|
+
path.quadraticCurveTo(
|
|
1822
|
+
rx,
|
|
1823
|
+
ry,
|
|
1824
|
+
current.x + cmd.x,
|
|
1825
|
+
current.y + cmd.y
|
|
1826
|
+
);
|
|
1827
|
+
current.add(cmd);
|
|
1828
|
+
} else {
|
|
1829
|
+
path.quadraticCurveTo(
|
|
1830
|
+
rx,
|
|
1831
|
+
ry,
|
|
1832
|
+
cmd.x,
|
|
1833
|
+
cmd.y
|
|
1834
|
+
);
|
|
1835
|
+
current.copyFrom(cmd);
|
|
1836
|
+
}
|
|
1837
|
+
} else if (cmd.type === "a" || cmd.type === "A") {
|
|
1838
|
+
const start = current.clone();
|
|
1839
|
+
if (cmd.type === "a") {
|
|
1840
|
+
if (cmd.x === 0 && cmd.y === 0)
|
|
1841
|
+
continue;
|
|
1842
|
+
current.add(cmd);
|
|
1843
|
+
} else {
|
|
1844
|
+
if (current.equals(cmd))
|
|
1845
|
+
continue;
|
|
1846
|
+
current.copyFrom(cmd);
|
|
1847
|
+
}
|
|
1848
|
+
control.copyFrom(current);
|
|
1849
|
+
parseArcCommand(
|
|
1850
|
+
path,
|
|
1851
|
+
cmd.rx,
|
|
1852
|
+
cmd.ry,
|
|
1853
|
+
cmd.angle,
|
|
1854
|
+
cmd.largeArcFlag,
|
|
1855
|
+
cmd.sweepFlag,
|
|
1856
|
+
start,
|
|
1857
|
+
current
|
|
1858
|
+
);
|
|
1859
|
+
} else if (cmd.type === "z" || cmd.type === "Z") {
|
|
1860
|
+
if (path.startPoint) {
|
|
1861
|
+
current.copyFrom(path.startPoint);
|
|
1862
|
+
}
|
|
1863
|
+
path.closePath();
|
|
1864
|
+
} else {
|
|
1865
|
+
console.warn("Unsupported commands", cmd);
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
function svgPathCommandsToData(commands) {
|
|
1871
|
+
let first;
|
|
1872
|
+
let prev;
|
|
1873
|
+
const data = [];
|
|
1874
|
+
for (let i = 0, len = commands.length; i < len; i++) {
|
|
1875
|
+
const cmd = commands[i];
|
|
1876
|
+
switch (cmd.type) {
|
|
1877
|
+
case "m":
|
|
1878
|
+
case "M":
|
|
1879
|
+
if (cmd.x.toFixed(4) === prev?.x.toFixed(4) && cmd.y.toFixed(4) === prev?.y.toFixed(4)) {
|
|
1880
|
+
continue;
|
|
1881
|
+
}
|
|
1882
|
+
data.push(`${cmd.type} ${cmd.x} ${cmd.y}`);
|
|
1883
|
+
prev = { x: cmd.x, y: cmd.y };
|
|
1884
|
+
first = { x: cmd.x, y: cmd.y };
|
|
1885
|
+
break;
|
|
1886
|
+
case "h":
|
|
1887
|
+
case "H":
|
|
1888
|
+
data.push(`${cmd.type} ${cmd.x}`);
|
|
1889
|
+
prev = { x: cmd.x, y: prev?.y ?? 0 };
|
|
1890
|
+
break;
|
|
1891
|
+
case "v":
|
|
1892
|
+
case "V":
|
|
1893
|
+
data.push(`${cmd.type} ${cmd.y}`);
|
|
1894
|
+
prev = { x: prev?.x ?? 0, y: cmd.y };
|
|
1895
|
+
break;
|
|
1896
|
+
case "l":
|
|
1897
|
+
case "L":
|
|
1898
|
+
data.push(`${cmd.type} ${cmd.x} ${cmd.y}`);
|
|
1899
|
+
prev = { x: cmd.x, y: cmd.y };
|
|
1900
|
+
break;
|
|
1901
|
+
case "c":
|
|
1902
|
+
case "C":
|
|
1903
|
+
data.push(`${cmd.type} ${cmd.x1} ${cmd.y1} ${cmd.x2} ${cmd.y2} ${cmd.x} ${cmd.y}`);
|
|
1904
|
+
prev = { x: cmd.x, y: cmd.y };
|
|
1905
|
+
break;
|
|
1906
|
+
case "s":
|
|
1907
|
+
case "S":
|
|
1908
|
+
data.push(`${cmd.type} ${cmd.x2} ${cmd.y2} ${cmd.x} ${cmd.y}`);
|
|
1909
|
+
prev = { x: cmd.x, y: cmd.y };
|
|
1910
|
+
break;
|
|
1911
|
+
case "q":
|
|
1912
|
+
case "Q":
|
|
1913
|
+
data.push(`${cmd.type} ${cmd.x1} ${cmd.y1} ${cmd.x} ${cmd.y}`);
|
|
1914
|
+
prev = { x: cmd.x, y: cmd.y };
|
|
1915
|
+
break;
|
|
1916
|
+
case "t":
|
|
1917
|
+
case "T":
|
|
1918
|
+
data.push(`${cmd.type} ${cmd.x} ${cmd.y}`);
|
|
1919
|
+
prev = { x: cmd.x, y: cmd.y };
|
|
1920
|
+
break;
|
|
1921
|
+
case "a":
|
|
1922
|
+
case "A":
|
|
1923
|
+
data.push(`${cmd.type} ${cmd.rx} ${cmd.ry} ${cmd.angle} ${cmd.largeArcFlag} ${cmd.sweepFlag} ${cmd.x} ${cmd.y}`);
|
|
1924
|
+
prev = { x: cmd.x, y: cmd.y };
|
|
1925
|
+
break;
|
|
1926
|
+
case "z":
|
|
1927
|
+
case "Z":
|
|
1928
|
+
data.push(cmd.type);
|
|
1929
|
+
if (first) {
|
|
1930
|
+
prev = { x: first.x, y: first.y };
|
|
1931
|
+
}
|
|
1932
|
+
break;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
return data.join(" ");
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
const RE$2 = /[a-df-z][^a-df-z]*/gi;
|
|
1939
|
+
function svgPathDataToCommands(data) {
|
|
1940
|
+
const commands = [];
|
|
1941
|
+
const matched = data.match(RE$2);
|
|
1942
|
+
if (!matched) {
|
|
1943
|
+
return commands;
|
|
1944
|
+
}
|
|
1945
|
+
for (let i = 0, len = matched.length; i < len; i++) {
|
|
1946
|
+
const command = matched[i];
|
|
1947
|
+
const type = command.charAt(0);
|
|
1948
|
+
const data2 = command.slice(1).trim();
|
|
1949
|
+
let args;
|
|
1950
|
+
switch (type) {
|
|
1951
|
+
case "m":
|
|
1952
|
+
case "M":
|
|
1953
|
+
args = parsePathDataArgs(data2);
|
|
1954
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
|
|
1955
|
+
if (i2 === 0) {
|
|
1956
|
+
commands.push({ type, x: args[i2], y: args[i2 + 1] });
|
|
1957
|
+
} else {
|
|
1958
|
+
commands.push({ type: type === "m" ? "l" : "L", x: args[i2], y: args[i2 + 1] });
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
break;
|
|
1962
|
+
case "h":
|
|
1963
|
+
case "H":
|
|
1964
|
+
args = parsePathDataArgs(data2);
|
|
1965
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2++) {
|
|
1966
|
+
commands.push({ type, x: args[i2] });
|
|
1967
|
+
}
|
|
1968
|
+
break;
|
|
1969
|
+
case "v":
|
|
1970
|
+
case "V":
|
|
1971
|
+
args = parsePathDataArgs(data2);
|
|
1972
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2++) {
|
|
1973
|
+
commands.push({ type, y: args[i2] });
|
|
1974
|
+
}
|
|
1975
|
+
break;
|
|
1976
|
+
case "l":
|
|
1977
|
+
case "L":
|
|
1978
|
+
args = parsePathDataArgs(data2);
|
|
1979
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
|
|
1980
|
+
commands.push({ type, x: args[i2], y: args[i2 + 1] });
|
|
1981
|
+
}
|
|
1982
|
+
break;
|
|
1983
|
+
case "c":
|
|
1984
|
+
case "C":
|
|
1985
|
+
args = parsePathDataArgs(data2);
|
|
1986
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 6) {
|
|
1987
|
+
commands.push({
|
|
1988
|
+
type,
|
|
1989
|
+
x1: args[i2],
|
|
1990
|
+
y1: args[i2 + 1],
|
|
1991
|
+
x2: args[i2 + 2],
|
|
1992
|
+
y2: args[i2 + 3],
|
|
1993
|
+
x: args[i2 + 4],
|
|
1994
|
+
y: args[i2 + 5]
|
|
1995
|
+
});
|
|
1996
|
+
}
|
|
1997
|
+
break;
|
|
1998
|
+
case "s":
|
|
1999
|
+
case "S":
|
|
2000
|
+
args = parsePathDataArgs(data2);
|
|
2001
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 4) {
|
|
2002
|
+
commands.push({
|
|
2003
|
+
type,
|
|
2004
|
+
x2: args[i2],
|
|
2005
|
+
y2: args[i2 + 1],
|
|
2006
|
+
x: args[i2 + 2],
|
|
2007
|
+
y: args[i2 + 3]
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
break;
|
|
2011
|
+
case "q":
|
|
2012
|
+
case "Q":
|
|
2013
|
+
args = parsePathDataArgs(data2);
|
|
2014
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 4) {
|
|
2015
|
+
commands.push({
|
|
2016
|
+
type,
|
|
2017
|
+
x1: args[i2],
|
|
2018
|
+
y1: args[i2 + 1],
|
|
2019
|
+
x: args[i2 + 2],
|
|
2020
|
+
y: args[i2 + 3]
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
break;
|
|
2024
|
+
case "t":
|
|
2025
|
+
case "T":
|
|
2026
|
+
args = parsePathDataArgs(data2);
|
|
2027
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
|
|
2028
|
+
commands.push({
|
|
2029
|
+
type,
|
|
2030
|
+
x: args[i2],
|
|
2031
|
+
y: args[i2 + 1]
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
2034
|
+
break;
|
|
2035
|
+
case "a":
|
|
2036
|
+
case "A":
|
|
2037
|
+
args = parsePathDataArgs(data2, [3, 4], 7);
|
|
2038
|
+
for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 7) {
|
|
2039
|
+
commands.push({
|
|
2040
|
+
type,
|
|
2041
|
+
rx: args[i2],
|
|
2042
|
+
ry: args[i2 + 1],
|
|
2043
|
+
angle: args[i2 + 2],
|
|
2044
|
+
largeArcFlag: args[i2 + 3],
|
|
2045
|
+
sweepFlag: args[i2 + 4],
|
|
2046
|
+
x: args[i2 + 5],
|
|
2047
|
+
y: args[i2 + 6]
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
break;
|
|
2051
|
+
case "z":
|
|
2052
|
+
case "Z":
|
|
2053
|
+
commands.push({
|
|
2054
|
+
type
|
|
2055
|
+
});
|
|
2056
|
+
break;
|
|
2057
|
+
default:
|
|
2058
|
+
console.warn(command);
|
|
1930
2059
|
}
|
|
1931
|
-
const midPointX = (firstPoint.x + lastPoint.x) * 0.5;
|
|
1932
|
-
const midPointY = (lastPoint.y + firstPoint.y) * 0.5;
|
|
1933
|
-
points.unshift(midPointX, midPointY);
|
|
1934
|
-
points.push(midPointX, midPointY);
|
|
1935
2060
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
const innerWeight = (1 - ratio) * 2;
|
|
1960
|
-
const outerWeight = ratio * 2;
|
|
1961
|
-
if (!closedShape) {
|
|
1962
|
-
if (style.cap === "round") {
|
|
1963
|
-
indexCount += round(
|
|
1964
|
-
x0 - perpX * (innerWeight - outerWeight) * 0.5,
|
|
1965
|
-
y0 - perpY * (innerWeight - outerWeight) * 0.5,
|
|
1966
|
-
x0 - perpX * innerWeight,
|
|
1967
|
-
y0 - perpY * innerWeight,
|
|
1968
|
-
x0 + perpX * outerWeight,
|
|
1969
|
-
y0 + perpY * outerWeight,
|
|
1970
|
-
verts,
|
|
1971
|
-
true
|
|
1972
|
-
) + 2;
|
|
1973
|
-
} else if (style.cap === "square") {
|
|
1974
|
-
indexCount += square(x0, y0, perpX, perpY, innerWeight, outerWeight, true, verts);
|
|
2061
|
+
return commands;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
const dataUri = "data:image/svg+xml;";
|
|
2065
|
+
const base64DataUri = `${dataUri}base64,`;
|
|
2066
|
+
const utf8DataUri = `${dataUri}charset=utf8,`;
|
|
2067
|
+
function svgToDom(svg) {
|
|
2068
|
+
if (typeof svg === "string") {
|
|
2069
|
+
let xml;
|
|
2070
|
+
if (svg.startsWith(base64DataUri)) {
|
|
2071
|
+
svg = svg.substring(base64DataUri.length, svg.length);
|
|
2072
|
+
xml = atob(svg);
|
|
2073
|
+
} else if (svg.startsWith(utf8DataUri)) {
|
|
2074
|
+
svg = svg.substring(utf8DataUri.length, svg.length);
|
|
2075
|
+
xml = decodeURIComponent(svg);
|
|
2076
|
+
} else {
|
|
2077
|
+
xml = svg;
|
|
2078
|
+
}
|
|
2079
|
+
const doc = new DOMParser().parseFromString(xml, "text/xml");
|
|
2080
|
+
const error = doc.querySelector("parsererror");
|
|
2081
|
+
if (error) {
|
|
2082
|
+
throw new Error(`${error.textContent ?? "parser error"}
|
|
2083
|
+
${xml}`);
|
|
1975
2084
|
}
|
|
2085
|
+
return doc.documentElement;
|
|
2086
|
+
} else {
|
|
2087
|
+
return svg;
|
|
1976
2088
|
}
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
}
|
|
2037
|
-
verts.push(
|
|
2038
|
-
x1 - perp1x * outerWeight,
|
|
2039
|
-
y1 - perp1y * outerWeight
|
|
2040
|
-
);
|
|
2041
|
-
verts.push(
|
|
2042
|
-
x1 + perp1x * innerWeight,
|
|
2043
|
-
y1 + perp1y * innerWeight
|
|
2044
|
-
);
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
const defaultUnit = "px";
|
|
2092
|
+
const defaultDPI = 90;
|
|
2093
|
+
const units = ["mm", "cm", "in", "pt", "pc", "px"];
|
|
2094
|
+
const unitConversion = {
|
|
2095
|
+
mm: {
|
|
2096
|
+
mm: 1,
|
|
2097
|
+
cm: 0.1,
|
|
2098
|
+
in: 1 / 25.4,
|
|
2099
|
+
pt: 72 / 25.4,
|
|
2100
|
+
pc: 6 / 25.4,
|
|
2101
|
+
px: -1
|
|
2102
|
+
},
|
|
2103
|
+
cm: {
|
|
2104
|
+
mm: 10,
|
|
2105
|
+
cm: 1,
|
|
2106
|
+
in: 1 / 2.54,
|
|
2107
|
+
pt: 72 / 2.54,
|
|
2108
|
+
pc: 6 / 2.54,
|
|
2109
|
+
px: -1
|
|
2110
|
+
},
|
|
2111
|
+
in: {
|
|
2112
|
+
mm: 25.4,
|
|
2113
|
+
cm: 2.54,
|
|
2114
|
+
in: 1,
|
|
2115
|
+
pt: 72,
|
|
2116
|
+
pc: 6,
|
|
2117
|
+
px: -1
|
|
2118
|
+
},
|
|
2119
|
+
pt: {
|
|
2120
|
+
mm: 25.4 / 72,
|
|
2121
|
+
cm: 2.54 / 72,
|
|
2122
|
+
in: 1 / 72,
|
|
2123
|
+
pt: 1,
|
|
2124
|
+
pc: 6 / 72,
|
|
2125
|
+
px: -1
|
|
2126
|
+
},
|
|
2127
|
+
pc: {
|
|
2128
|
+
mm: 25.4 / 6,
|
|
2129
|
+
cm: 2.54 / 6,
|
|
2130
|
+
in: 1 / 6,
|
|
2131
|
+
pt: 72 / 6,
|
|
2132
|
+
pc: 1,
|
|
2133
|
+
px: -1
|
|
2134
|
+
},
|
|
2135
|
+
px: {
|
|
2136
|
+
px: 1
|
|
2137
|
+
}
|
|
2138
|
+
};
|
|
2139
|
+
function parseFloatWithUnits(string) {
|
|
2140
|
+
let theUnit = "px";
|
|
2141
|
+
if (typeof string === "string") {
|
|
2142
|
+
for (let i = 0, n = units.length; i < n; i++) {
|
|
2143
|
+
const u = units[i];
|
|
2144
|
+
if (string.endsWith(u)) {
|
|
2145
|
+
theUnit = u;
|
|
2146
|
+
string = string.substring(0, string.length - u.length);
|
|
2147
|
+
break;
|
|
2045
2148
|
}
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
let scale;
|
|
2152
|
+
{
|
|
2153
|
+
scale = unitConversion[theUnit][defaultUnit];
|
|
2154
|
+
if (scale < 0) {
|
|
2155
|
+
scale = unitConversion[theUnit].in * defaultDPI;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
return scale * Number.parseFloat(string);
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
function getNodeTransform(node, currentTransform, transformStack) {
|
|
2162
|
+
if (!(node.hasAttribute("transform") || node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y")))) {
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
const transform = parseNodeTransform(node);
|
|
2166
|
+
if (transformStack.length > 0) {
|
|
2167
|
+
transform.prepend(transformStack[transformStack.length - 1]);
|
|
2168
|
+
}
|
|
2169
|
+
currentTransform.copyFrom(transform);
|
|
2170
|
+
transformStack.push(transform);
|
|
2171
|
+
return transform;
|
|
2172
|
+
}
|
|
2173
|
+
function parseNodeTransform(node) {
|
|
2174
|
+
const transform = new Transform2D();
|
|
2175
|
+
if (node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y"))) {
|
|
2176
|
+
transform.translate(
|
|
2177
|
+
parseFloatWithUnits(node.getAttribute("x")),
|
|
2178
|
+
parseFloatWithUnits(node.getAttribute("y"))
|
|
2179
|
+
);
|
|
2180
|
+
}
|
|
2181
|
+
if (node.hasAttribute("transform")) {
|
|
2182
|
+
transform.appendCssTransform(node.getAttribute("transform"));
|
|
2183
|
+
}
|
|
2184
|
+
return transform;
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
function parseCircleNode(node) {
|
|
2188
|
+
return new Path2D().arc(
|
|
2189
|
+
parseFloatWithUnits(node.getAttribute("cx") || 0),
|
|
2190
|
+
parseFloatWithUnits(node.getAttribute("cy") || 0),
|
|
2191
|
+
parseFloatWithUnits(node.getAttribute("r") || 0),
|
|
2192
|
+
0,
|
|
2193
|
+
Math.PI * 2
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
function parseCSSStylesheet(node, stylesheets) {
|
|
2198
|
+
if (!node.sheet || !node.sheet.cssRules || !node.sheet.cssRules.length)
|
|
2199
|
+
return;
|
|
2200
|
+
for (let i = 0; i < node.sheet.cssRules.length; i++) {
|
|
2201
|
+
const stylesheet = node.sheet.cssRules[i];
|
|
2202
|
+
if (stylesheet.type !== 1)
|
|
2046
2203
|
continue;
|
|
2204
|
+
const selectorList = stylesheet.selectorText.split(/,/g).filter(Boolean).map((i2) => i2.trim());
|
|
2205
|
+
const definitions = {};
|
|
2206
|
+
for (let len = stylesheet.style.length, i2 = 0; i2 < len; i2++) {
|
|
2207
|
+
const name = stylesheet.style.item(i2);
|
|
2208
|
+
definitions[name] = stylesheet.style.getPropertyValue(name);
|
|
2047
2209
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
const imx = x1 + (px - x1) * innerWeight;
|
|
2054
|
-
const imy = y1 + (py - y1) * innerWeight;
|
|
2055
|
-
const omx = x1 - (px - x1) * outerWeight;
|
|
2056
|
-
const omy = y1 - (py - y1) * outerWeight;
|
|
2057
|
-
const smallerInsideSegmentSq = Math.min(dx0 * dx0 + dy0 * dy0, dx1 * dx1 + dy1 * dy1);
|
|
2058
|
-
const insideWeight = clockwise ? innerWeight : outerWeight;
|
|
2059
|
-
const smallerInsideDiagonalSq = smallerInsideSegmentSq + insideWeight * insideWeight * widthSquared;
|
|
2060
|
-
const insideMiterOk = pDist <= smallerInsideDiagonalSq;
|
|
2061
|
-
if (insideMiterOk) {
|
|
2062
|
-
if (style.join === "bevel" || pDist / widthSquared > miterLimitSquared) {
|
|
2063
|
-
if (clockwise) {
|
|
2064
|
-
verts.push(imx, imy);
|
|
2065
|
-
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
|
|
2066
|
-
verts.push(imx, imy);
|
|
2067
|
-
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
|
|
2068
|
-
} else {
|
|
2069
|
-
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
|
|
2070
|
-
verts.push(omx, omy);
|
|
2071
|
-
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
|
|
2072
|
-
verts.push(omx, omy);
|
|
2073
|
-
}
|
|
2074
|
-
indexCount += 2;
|
|
2075
|
-
} else if (style.join === "round") {
|
|
2076
|
-
if (clockwise) {
|
|
2077
|
-
verts.push(imx, imy);
|
|
2078
|
-
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
|
|
2079
|
-
indexCount += round(
|
|
2080
|
-
x1,
|
|
2081
|
-
y1,
|
|
2082
|
-
x1 + perpX * outerWeight,
|
|
2083
|
-
y1 + perpY * outerWeight,
|
|
2084
|
-
x1 + perp1x * outerWeight,
|
|
2085
|
-
y1 + perp1y * outerWeight,
|
|
2086
|
-
verts,
|
|
2087
|
-
true
|
|
2088
|
-
) + 4;
|
|
2089
|
-
verts.push(imx, imy);
|
|
2090
|
-
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
|
|
2091
|
-
} else {
|
|
2092
|
-
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
|
|
2093
|
-
verts.push(omx, omy);
|
|
2094
|
-
indexCount += round(
|
|
2095
|
-
x1,
|
|
2096
|
-
y1,
|
|
2097
|
-
x1 - perpX * innerWeight,
|
|
2098
|
-
y1 - perpY * innerWeight,
|
|
2099
|
-
x1 - perp1x * innerWeight,
|
|
2100
|
-
y1 - perp1y * innerWeight,
|
|
2101
|
-
verts,
|
|
2102
|
-
false
|
|
2103
|
-
) + 4;
|
|
2104
|
-
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
|
|
2105
|
-
verts.push(omx, omy);
|
|
2106
|
-
}
|
|
2107
|
-
} else {
|
|
2108
|
-
verts.push(imx, imy);
|
|
2109
|
-
verts.push(omx, omy);
|
|
2110
|
-
}
|
|
2111
|
-
} else {
|
|
2112
|
-
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
|
|
2113
|
-
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
|
|
2114
|
-
if (style.join === "round") {
|
|
2115
|
-
if (clockwise) {
|
|
2116
|
-
indexCount += round(
|
|
2117
|
-
x1,
|
|
2118
|
-
y1,
|
|
2119
|
-
x1 + perpX * outerWeight,
|
|
2120
|
-
y1 + perpY * outerWeight,
|
|
2121
|
-
x1 + perp1x * outerWeight,
|
|
2122
|
-
y1 + perp1y * outerWeight,
|
|
2123
|
-
verts,
|
|
2124
|
-
true
|
|
2125
|
-
) + 2;
|
|
2126
|
-
} else {
|
|
2127
|
-
indexCount += round(
|
|
2128
|
-
x1,
|
|
2129
|
-
y1,
|
|
2130
|
-
x1 - perpX * innerWeight,
|
|
2131
|
-
y1 - perpY * innerWeight,
|
|
2132
|
-
x1 - perp1x * innerWeight,
|
|
2133
|
-
y1 - perp1y * innerWeight,
|
|
2134
|
-
verts,
|
|
2135
|
-
false
|
|
2136
|
-
) + 2;
|
|
2137
|
-
}
|
|
2138
|
-
} else if (style.join === "miter" && pDist / widthSquared <= miterLimitSquared) {
|
|
2139
|
-
if (clockwise) {
|
|
2140
|
-
verts.push(omx, omy);
|
|
2141
|
-
verts.push(omx, omy);
|
|
2142
|
-
} else {
|
|
2143
|
-
verts.push(imx, imy);
|
|
2144
|
-
verts.push(imx, imy);
|
|
2145
|
-
}
|
|
2146
|
-
indexCount += 2;
|
|
2147
|
-
}
|
|
2148
|
-
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
|
|
2149
|
-
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
|
|
2150
|
-
indexCount += 2;
|
|
2210
|
+
for (let j = 0; j < selectorList.length; j++) {
|
|
2211
|
+
stylesheets[selectorList[j]] = Object.assign(
|
|
2212
|
+
stylesheets[selectorList[j]] || {},
|
|
2213
|
+
{ ...definitions }
|
|
2214
|
+
);
|
|
2151
2215
|
}
|
|
2152
2216
|
}
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
function parseEllipseNode(node) {
|
|
2220
|
+
return new Path2D().ellipse(
|
|
2221
|
+
parseFloatWithUnits(node.getAttribute("cx") || 0),
|
|
2222
|
+
parseFloatWithUnits(node.getAttribute("cy") || 0),
|
|
2223
|
+
parseFloatWithUnits(node.getAttribute("rx") || 0),
|
|
2224
|
+
parseFloatWithUnits(node.getAttribute("ry") || 0),
|
|
2225
|
+
0,
|
|
2226
|
+
0,
|
|
2227
|
+
Math.PI * 2
|
|
2228
|
+
);
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
function parseLineNode(node) {
|
|
2232
|
+
return new Path2D().moveTo(
|
|
2233
|
+
parseFloatWithUnits(node.getAttribute("x1") || 0),
|
|
2234
|
+
parseFloatWithUnits(node.getAttribute("y1") || 0)
|
|
2235
|
+
).lineTo(
|
|
2236
|
+
parseFloatWithUnits(node.getAttribute("x2") || 0),
|
|
2237
|
+
parseFloatWithUnits(node.getAttribute("y2") || 0)
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
function parsePathNode(node) {
|
|
2242
|
+
const path = new Path2D();
|
|
2243
|
+
const d = node.getAttribute("d");
|
|
2244
|
+
if (!d || d === "none")
|
|
2245
|
+
return null;
|
|
2246
|
+
path.addData(d);
|
|
2247
|
+
return path;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
const RE$1 = /([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)(?:,|\s)([+-]?\d*\.?\d+(?:e[+-]?\d+)?)/g;
|
|
2251
|
+
function parsePolygonNode(node) {
|
|
2252
|
+
const path = new Path2D();
|
|
2253
|
+
let index = 0;
|
|
2254
|
+
node.getAttribute("points")?.replace(RE$1, (match, a, b) => {
|
|
2255
|
+
const x = parseFloatWithUnits(a);
|
|
2256
|
+
const y = parseFloatWithUnits(b);
|
|
2257
|
+
if (index === 0) {
|
|
2258
|
+
path.moveTo(x, y);
|
|
2259
|
+
} else {
|
|
2260
|
+
path.lineTo(x, y);
|
|
2261
|
+
}
|
|
2262
|
+
index++;
|
|
2263
|
+
return match;
|
|
2264
|
+
});
|
|
2265
|
+
path.currentCurve.autoClose = true;
|
|
2266
|
+
return path;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
const RE = /([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)(?:,|\s)([+-]?\d*\.?\d+(?:e[+-]?\d+)?)/g;
|
|
2270
|
+
function parsePolylineNode(node) {
|
|
2271
|
+
const path = new Path2D();
|
|
2272
|
+
let index = 0;
|
|
2273
|
+
node.getAttribute("points")?.replace(RE, (match, a, b) => {
|
|
2274
|
+
const x = parseFloatWithUnits(a);
|
|
2275
|
+
const y = parseFloatWithUnits(b);
|
|
2276
|
+
if (index === 0) {
|
|
2277
|
+
path.moveTo(x, y);
|
|
2278
|
+
} else {
|
|
2279
|
+
path.lineTo(x, y);
|
|
2180
2280
|
}
|
|
2281
|
+
index++;
|
|
2282
|
+
return match;
|
|
2283
|
+
});
|
|
2284
|
+
path.currentCurve.autoClose = false;
|
|
2285
|
+
return path;
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
function parseRectNode(node) {
|
|
2289
|
+
const x = parseFloatWithUnits(node.getAttribute("x") || 0);
|
|
2290
|
+
const y = parseFloatWithUnits(node.getAttribute("y") || 0);
|
|
2291
|
+
const rx = parseFloatWithUnits(node.getAttribute("rx") || node.getAttribute("ry") || 0);
|
|
2292
|
+
const ry = parseFloatWithUnits(node.getAttribute("ry") || node.getAttribute("rx") || 0);
|
|
2293
|
+
const w = parseFloatWithUnits(node.getAttribute("width"));
|
|
2294
|
+
const h = parseFloatWithUnits(node.getAttribute("height"));
|
|
2295
|
+
const bci = 1 - 0.551915024494;
|
|
2296
|
+
const path = new Path2D();
|
|
2297
|
+
path.moveTo(x + rx, y);
|
|
2298
|
+
path.lineTo(x + w - rx, y);
|
|
2299
|
+
if (rx !== 0 || ry !== 0) {
|
|
2300
|
+
path.bezierCurveTo(
|
|
2301
|
+
x + w - rx * bci,
|
|
2302
|
+
y,
|
|
2303
|
+
x + w,
|
|
2304
|
+
y + ry * bci,
|
|
2305
|
+
x + w,
|
|
2306
|
+
y + ry
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
path.lineTo(x + w, y + h - ry);
|
|
2310
|
+
if (rx !== 0 || ry !== 0) {
|
|
2311
|
+
path.bezierCurveTo(
|
|
2312
|
+
x + w,
|
|
2313
|
+
y + h - ry * bci,
|
|
2314
|
+
x + w - rx * bci,
|
|
2315
|
+
y + h,
|
|
2316
|
+
x + w - rx,
|
|
2317
|
+
y + h
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
path.lineTo(x + rx, y + h);
|
|
2321
|
+
if (rx !== 0 || ry !== 0) {
|
|
2322
|
+
path.bezierCurveTo(
|
|
2323
|
+
x + rx * bci,
|
|
2324
|
+
y + h,
|
|
2325
|
+
x,
|
|
2326
|
+
y + h - ry * bci,
|
|
2327
|
+
x,
|
|
2328
|
+
y + h - ry
|
|
2329
|
+
);
|
|
2181
2330
|
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
y0 = verts[i * 2 + 1];
|
|
2186
|
-
x1 = verts[(i + 1) * 2];
|
|
2187
|
-
y1 = verts[(i + 1) * 2 + 1];
|
|
2188
|
-
x2 = verts[(i + 2) * 2];
|
|
2189
|
-
y2 = verts[(i + 2) * 2 + 1];
|
|
2190
|
-
if (Math.abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) < eps2) {
|
|
2191
|
-
continue;
|
|
2192
|
-
}
|
|
2193
|
-
indices.push(i, i + 1, i + 2);
|
|
2331
|
+
path.lineTo(x, y + ry);
|
|
2332
|
+
if (rx !== 0 || ry !== 0) {
|
|
2333
|
+
path.bezierCurveTo(x, y + ry * bci, x + rx * bci, y, x + rx, y);
|
|
2194
2334
|
}
|
|
2195
|
-
return
|
|
2196
|
-
vertices,
|
|
2197
|
-
indices
|
|
2198
|
-
};
|
|
2335
|
+
return path;
|
|
2199
2336
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2337
|
+
|
|
2338
|
+
function parseStyle(node, style, stylesheets) {
|
|
2339
|
+
style = Object.assign({}, style);
|
|
2340
|
+
let stylesheetStyles = {};
|
|
2341
|
+
if (node.hasAttribute("class")) {
|
|
2342
|
+
const classSelectors = node.getAttribute("class").split(/\s/).filter(Boolean).map((i) => i.trim());
|
|
2343
|
+
for (let i = 0; i < classSelectors.length; i++) {
|
|
2344
|
+
stylesheetStyles = Object.assign(stylesheetStyles, stylesheets[`.${classSelectors[i]}`]);
|
|
2345
|
+
}
|
|
2204
2346
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
const x2 = points[i];
|
|
2208
|
-
const y2 = points[i + 1];
|
|
2209
|
-
area += (x2 - x1) * (y2 + y1);
|
|
2210
|
-
x1 = x2;
|
|
2211
|
-
y1 = y2;
|
|
2347
|
+
if (node.hasAttribute("id")) {
|
|
2348
|
+
stylesheetStyles = Object.assign(stylesheetStyles, stylesheets[`#${node.getAttribute("id")}`]);
|
|
2212
2349
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2350
|
+
for (let len = node.style.length, i = 0; i < len; i++) {
|
|
2351
|
+
const name = node.style.item(i);
|
|
2352
|
+
const value = node.style.getPropertyValue(name);
|
|
2353
|
+
style[name] = value;
|
|
2354
|
+
stylesheetStyles[name] = value;
|
|
2215
2355
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
const ox = x + nx * outerWeight;
|
|
2222
|
-
const oy = y + ny * outerWeight;
|
|
2223
|
-
let exx;
|
|
2224
|
-
let eyy;
|
|
2225
|
-
if (clockwise) {
|
|
2226
|
-
exx = ny;
|
|
2227
|
-
eyy = -nx;
|
|
2228
|
-
} else {
|
|
2229
|
-
exx = -ny;
|
|
2230
|
-
eyy = nx;
|
|
2356
|
+
function addStyle(svgName, jsName, adjustFunction = copy) {
|
|
2357
|
+
if (node.hasAttribute(svgName))
|
|
2358
|
+
style[jsName] = adjustFunction(node.getAttribute(svgName));
|
|
2359
|
+
if (stylesheetStyles[svgName])
|
|
2360
|
+
style[jsName] = adjustFunction(stylesheetStyles[svgName]);
|
|
2231
2361
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
verts.push(eix, eiy);
|
|
2237
|
-
verts.push(eox, eoy);
|
|
2238
|
-
return 2;
|
|
2239
|
-
}
|
|
2240
|
-
function round(cx, cy, sx, sy, ex, ey, verts, clockwise) {
|
|
2241
|
-
const cx2p0x = sx - cx;
|
|
2242
|
-
const cy2p0y = sy - cy;
|
|
2243
|
-
let angle0 = Math.atan2(cx2p0x, cy2p0y);
|
|
2244
|
-
let angle1 = Math.atan2(ex - cx, ey - cy);
|
|
2245
|
-
if (clockwise && angle0 < angle1) {
|
|
2246
|
-
angle0 += Math.PI * 2;
|
|
2247
|
-
} else if (!clockwise && angle0 > angle1) {
|
|
2248
|
-
angle1 += Math.PI * 2;
|
|
2362
|
+
function copy(v) {
|
|
2363
|
+
if (v.startsWith("url"))
|
|
2364
|
+
console.warn("url access in attributes is not implemented.");
|
|
2365
|
+
return v;
|
|
2249
2366
|
}
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2367
|
+
function clamp(v) {
|
|
2368
|
+
return Math.max(0, Math.min(1, parseFloatWithUnits(v)));
|
|
2369
|
+
}
|
|
2370
|
+
function positive(v) {
|
|
2371
|
+
return Math.max(0, parseFloatWithUnits(v));
|
|
2372
|
+
}
|
|
2373
|
+
function array(v) {
|
|
2374
|
+
return v.split(" ").filter((v2) => v2 !== "").map((v2) => parseFloatWithUnits(v2));
|
|
2375
|
+
}
|
|
2376
|
+
addStyle("fill", "fill");
|
|
2377
|
+
addStyle("fill-opacity", "fillOpacity", clamp);
|
|
2378
|
+
addStyle("fill-rule", "fillRule");
|
|
2379
|
+
addStyle("opacity", "opacity", clamp);
|
|
2380
|
+
addStyle("stroke", "stroke");
|
|
2381
|
+
addStyle("stroke-opacity", "strokeOpacity", clamp);
|
|
2382
|
+
addStyle("stroke-width", "strokeWidth", positive);
|
|
2383
|
+
addStyle("stroke-linecap", "strokeLinecap");
|
|
2384
|
+
addStyle("stroke-linejoin", "strokeLinejoin");
|
|
2385
|
+
addStyle("stroke-miterlimit", "strokeMiterlimit", positive);
|
|
2386
|
+
addStyle("stroke-dasharray", "strokeDasharray", array);
|
|
2387
|
+
addStyle("stroke-dashoffset", "strokeDashoffset", parseFloatWithUnits);
|
|
2388
|
+
addStyle("visibility", "visibility");
|
|
2389
|
+
return style;
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
function parseNode(node, style, paths = [], stylesheets = {}) {
|
|
2393
|
+
if (node.nodeType !== 1)
|
|
2394
|
+
return paths;
|
|
2395
|
+
let isDefsNode = false;
|
|
2396
|
+
let path = null;
|
|
2397
|
+
let _style = { ...style };
|
|
2398
|
+
switch (node.nodeName) {
|
|
2399
|
+
case "svg":
|
|
2400
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2401
|
+
break;
|
|
2402
|
+
case "style":
|
|
2403
|
+
parseCSSStylesheet(node, stylesheets);
|
|
2404
|
+
break;
|
|
2405
|
+
case "g":
|
|
2406
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2407
|
+
break;
|
|
2408
|
+
case "path":
|
|
2409
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2410
|
+
if (node.hasAttribute("d"))
|
|
2411
|
+
path = parsePathNode(node);
|
|
2412
|
+
break;
|
|
2413
|
+
case "rect":
|
|
2414
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2415
|
+
path = parseRectNode(node);
|
|
2416
|
+
break;
|
|
2417
|
+
case "polygon":
|
|
2418
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2419
|
+
path = parsePolygonNode(node);
|
|
2420
|
+
break;
|
|
2421
|
+
case "polyline":
|
|
2422
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2423
|
+
path = parsePolylineNode(node);
|
|
2424
|
+
break;
|
|
2425
|
+
case "circle":
|
|
2426
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2427
|
+
path = parseCircleNode(node);
|
|
2428
|
+
break;
|
|
2429
|
+
case "ellipse":
|
|
2430
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2431
|
+
path = parseEllipseNode(node);
|
|
2432
|
+
break;
|
|
2433
|
+
case "line":
|
|
2434
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2435
|
+
path = parseLineNode(node);
|
|
2436
|
+
break;
|
|
2437
|
+
case "defs":
|
|
2438
|
+
isDefsNode = true;
|
|
2439
|
+
break;
|
|
2440
|
+
case "use": {
|
|
2441
|
+
_style = parseStyle(node, _style, stylesheets);
|
|
2442
|
+
const href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href") || node.getAttribute("href") || "";
|
|
2443
|
+
const usedNodeId = href.substring(1);
|
|
2444
|
+
const usedNode = node.viewportElement?.getElementById(usedNodeId);
|
|
2445
|
+
if (usedNode) {
|
|
2446
|
+
parseNode(usedNode, _style, paths, stylesheets);
|
|
2447
|
+
} else {
|
|
2448
|
+
console.warn(`'use node' references non-existent node id: ${usedNodeId}`);
|
|
2449
|
+
}
|
|
2450
|
+
break;
|
|
2263
2451
|
}
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2452
|
+
default:
|
|
2453
|
+
console.warn(node);
|
|
2454
|
+
break;
|
|
2455
|
+
}
|
|
2456
|
+
if (_style.display === "none") {
|
|
2457
|
+
return paths;
|
|
2458
|
+
}
|
|
2459
|
+
const currentTransform = new Transform2D();
|
|
2460
|
+
const transformStack = [];
|
|
2461
|
+
const transform = getNodeTransform(node, currentTransform, transformStack);
|
|
2462
|
+
if (path) {
|
|
2463
|
+
path.applyTransform(currentTransform);
|
|
2464
|
+
paths.push(path);
|
|
2465
|
+
path.style = { ..._style };
|
|
2466
|
+
}
|
|
2467
|
+
const childNodes = node.childNodes;
|
|
2468
|
+
for (let i = 0, len = childNodes.length; i < len; i++) {
|
|
2469
|
+
const node2 = childNodes[i];
|
|
2470
|
+
if (isDefsNode && node2.nodeName !== "style" && node2.nodeName !== "defs")
|
|
2471
|
+
continue;
|
|
2472
|
+
parseNode(node2, _style, paths, stylesheets);
|
|
2473
|
+
}
|
|
2474
|
+
if (transform) {
|
|
2475
|
+
transformStack.pop();
|
|
2476
|
+
if (transformStack.length > 0) {
|
|
2477
|
+
currentTransform.copyFrom(transformStack[transformStack.length - 1]);
|
|
2478
|
+
} else {
|
|
2479
|
+
currentTransform.identity();
|
|
2272
2480
|
}
|
|
2273
|
-
verts.push(ex, ey);
|
|
2274
|
-
verts.push(cx, cy);
|
|
2275
2481
|
}
|
|
2276
|
-
return
|
|
2482
|
+
return paths;
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
function svgToPath2DSet(svg) {
|
|
2486
|
+
const dom = svgToDom(svg);
|
|
2487
|
+
return new Path2DSet(
|
|
2488
|
+
parseNode(dom, {}),
|
|
2489
|
+
dom.getAttribute("viewBox")?.trim().split(" ").map((v) => Number(v))
|
|
2490
|
+
);
|
|
2277
2491
|
}
|
|
2278
2492
|
|
|
2279
2493
|
class Curve {
|
|
@@ -2294,7 +2508,7 @@ class Curve {
|
|
|
2294
2508
|
if (isFunction) {
|
|
2295
2509
|
transform(p);
|
|
2296
2510
|
} else {
|
|
2297
|
-
|
|
2511
|
+
transform.apply(p, p);
|
|
2298
2512
|
}
|
|
2299
2513
|
});
|
|
2300
2514
|
return this;
|
|
@@ -2409,7 +2623,7 @@ class Curve {
|
|
|
2409
2623
|
const delta = 1e-4;
|
|
2410
2624
|
const t1 = Math.max(0, t - delta);
|
|
2411
2625
|
const t2 = Math.min(1, t + delta);
|
|
2412
|
-
return output.
|
|
2626
|
+
return output.copyFrom(this.getPoint(t2).sub(this.getPoint(t1)).normalize());
|
|
2413
2627
|
}
|
|
2414
2628
|
getTangentAt(u, output) {
|
|
2415
2629
|
return this.getTangent(this.getUToTMapping(u), output);
|
|
@@ -2444,8 +2658,8 @@ class Curve {
|
|
|
2444
2658
|
const potins = this.getPoints();
|
|
2445
2659
|
for (let i = 0, len = potins.length; i < len; i++) {
|
|
2446
2660
|
const p = potins[i];
|
|
2447
|
-
min.
|
|
2448
|
-
max.
|
|
2661
|
+
min.clampMin(p);
|
|
2662
|
+
max.clampMax(p);
|
|
2449
2663
|
}
|
|
2450
2664
|
return { min: min.finite(), max: max.finite() };
|
|
2451
2665
|
}
|
|
@@ -2497,18 +2711,18 @@ class Curve {
|
|
|
2497
2711
|
});
|
|
2498
2712
|
return this;
|
|
2499
2713
|
}
|
|
2500
|
-
|
|
2714
|
+
copyFrom(source) {
|
|
2501
2715
|
this.arcLengthDivision = source.arcLengthDivision;
|
|
2502
2716
|
return this;
|
|
2503
2717
|
}
|
|
2504
2718
|
clone() {
|
|
2505
|
-
return new this.constructor().
|
|
2719
|
+
return new this.constructor().copyFrom(this);
|
|
2506
2720
|
}
|
|
2507
2721
|
}
|
|
2508
2722
|
|
|
2509
|
-
const tempTransform0 = new
|
|
2510
|
-
const tempTransform1 = new
|
|
2511
|
-
const tempTransform2 = new
|
|
2723
|
+
const tempTransform0 = new Transform2D();
|
|
2724
|
+
const tempTransform1 = new Transform2D();
|
|
2725
|
+
const tempTransform2 = new Transform2D();
|
|
2512
2726
|
const tempV2 = new Vector2();
|
|
2513
2727
|
class RoundCurve extends Curve {
|
|
2514
2728
|
constructor(_center = new Vector2(), _radius = new Vector2(), _diff = new Vector2(), rotate = 0, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
|
|
@@ -2627,15 +2841,15 @@ class RoundCurve extends Curve {
|
|
|
2627
2841
|
);
|
|
2628
2842
|
return this;
|
|
2629
2843
|
}
|
|
2630
|
-
applyTransform(
|
|
2844
|
+
applyTransform(transform) {
|
|
2631
2845
|
tempV2.set(this.cx, this.cy);
|
|
2632
|
-
|
|
2846
|
+
transform.apply(tempV2, tempV2);
|
|
2633
2847
|
this.cx = tempV2.x;
|
|
2634
2848
|
this.cy = tempV2.y;
|
|
2635
|
-
if (isTransformSkewed(
|
|
2636
|
-
transfEllipseGeneric(this,
|
|
2849
|
+
if (isTransformSkewed(transform)) {
|
|
2850
|
+
transfEllipseGeneric(this, transform);
|
|
2637
2851
|
} else {
|
|
2638
|
-
transfEllipseNoSkew(this,
|
|
2852
|
+
transfEllipseNoSkew(this, transform);
|
|
2639
2853
|
}
|
|
2640
2854
|
return this;
|
|
2641
2855
|
}
|
|
@@ -2762,8 +2976,8 @@ class RoundCurve extends Curve {
|
|
|
2762
2976
|
}
|
|
2763
2977
|
return this._getAdaptiveVerticesByArc(output);
|
|
2764
2978
|
}
|
|
2765
|
-
|
|
2766
|
-
super.
|
|
2979
|
+
copyFrom(source) {
|
|
2980
|
+
super.copyFrom(source);
|
|
2767
2981
|
this.cx = source.cx;
|
|
2768
2982
|
this.cy = source.cy;
|
|
2769
2983
|
this.rx = source.rx;
|
|
@@ -2784,24 +2998,17 @@ function transfEllipseGeneric(curve, m) {
|
|
|
2784
2998
|
const sinTheta = Math.sin(curve.rotate);
|
|
2785
2999
|
const v1 = new Vector2(a * cosTheta, a * sinTheta);
|
|
2786
3000
|
const v2 = new Vector2(-b * sinTheta, b * cosTheta);
|
|
2787
|
-
const
|
|
2788
|
-
const
|
|
2789
|
-
const
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
1
|
|
2799
|
-
);
|
|
2800
|
-
const mFInv = tempTransform1.copy(mF).invert();
|
|
2801
|
-
const mFInvT = tempTransform2.copy(mFInv).transpose();
|
|
2802
|
-
const mQ = mFInvT.multiply(mFInv);
|
|
2803
|
-
const mQe = mQ.elements;
|
|
2804
|
-
const ed = eigenDecomposition(mQe[0], mQe[1], mQe[4]);
|
|
3001
|
+
const f1x = m.a * v1.x + m.c * v1.y;
|
|
3002
|
+
const f1y = m.b * v1.x + m.d * v1.y;
|
|
3003
|
+
const f2x = m.a * v2.x + m.c * v2.y;
|
|
3004
|
+
const f2y = m.b * v2.x + m.d * v2.y;
|
|
3005
|
+
const mF = tempTransform0.set(f1x, f1y, f2x, f2y, 0, 0);
|
|
3006
|
+
const mFInv = tempTransform1.copyFrom(mF).affineInvert();
|
|
3007
|
+
const { a: ia, b: ib, c: ic, d: id } = mFInv;
|
|
3008
|
+
const qA = ia * ia + ib * ib;
|
|
3009
|
+
const qB = ic * ia + id * ib;
|
|
3010
|
+
const qD = ic * ic + id * id;
|
|
3011
|
+
const ed = eigenDecomposition(qA, qB, qD);
|
|
2805
3012
|
const rt1sqrt = Math.sqrt(ed.rt1);
|
|
2806
3013
|
const rt2sqrt = Math.sqrt(ed.rt2);
|
|
2807
3014
|
curve.rx = 1 / rt1sqrt;
|
|
@@ -2813,27 +3020,21 @@ function transfEllipseGeneric(curve, m) {
|
|
|
2813
3020
|
rt1sqrt,
|
|
2814
3021
|
0,
|
|
2815
3022
|
0,
|
|
2816
|
-
0,
|
|
2817
3023
|
rt2sqrt,
|
|
2818
3024
|
0,
|
|
2819
|
-
0
|
|
2820
|
-
0,
|
|
2821
|
-
1
|
|
3025
|
+
0
|
|
2822
3026
|
);
|
|
2823
3027
|
const mRT = tempTransform2.set(
|
|
2824
3028
|
ed.cs,
|
|
2825
3029
|
ed.sn,
|
|
2826
|
-
0,
|
|
2827
3030
|
-ed.sn,
|
|
2828
3031
|
ed.cs,
|
|
2829
3032
|
0,
|
|
2830
|
-
0
|
|
2831
|
-
0,
|
|
2832
|
-
1
|
|
3033
|
+
0
|
|
2833
3034
|
);
|
|
2834
|
-
const mDRF = mDsqrt.
|
|
3035
|
+
const mDRF = mDsqrt.append(mRT).append(mF);
|
|
2835
3036
|
const transformAngle = (phi) => {
|
|
2836
|
-
const { x: cosR, y: sinR } =
|
|
3037
|
+
const { x: cosR, y: sinR } = mDRF.apply({ x: Math.cos(phi), y: Math.sin(phi) });
|
|
2837
3038
|
return Math.atan2(sinR, cosR);
|
|
2838
3039
|
};
|
|
2839
3040
|
curve.startAngle = transformAngle(curve.startAngle);
|
|
@@ -2844,11 +3045,10 @@ function transfEllipseGeneric(curve, m) {
|
|
|
2844
3045
|
}
|
|
2845
3046
|
}
|
|
2846
3047
|
function transfEllipseNoSkew(curve, m) {
|
|
2847
|
-
const
|
|
2848
|
-
|
|
2849
|
-
curve.
|
|
2850
|
-
|
|
2851
|
-
const theta = sx > Number.EPSILON ? Math.atan2(m.elements[1], m.elements[0]) : Math.atan2(-m.elements[3], m.elements[4]);
|
|
3048
|
+
const { scale } = m.decompose();
|
|
3049
|
+
curve.rx *= scale.x;
|
|
3050
|
+
curve.ry *= scale.y;
|
|
3051
|
+
const theta = scale.x > Number.EPSILON ? Math.atan2(m.b, m.a) : Math.atan2(-m.c, m.d);
|
|
2852
3052
|
curve.rotate += theta;
|
|
2853
3053
|
if (isTransformFlipped(m)) {
|
|
2854
3054
|
curve.startAngle *= -1;
|
|
@@ -2857,25 +3057,14 @@ function transfEllipseNoSkew(curve, m) {
|
|
|
2857
3057
|
}
|
|
2858
3058
|
}
|
|
2859
3059
|
function isTransformFlipped(m) {
|
|
2860
|
-
|
|
2861
|
-
return te[0] * te[4] - te[1] * te[3] < 0;
|
|
3060
|
+
return m.a * m.d - m.c * m.b < 0;
|
|
2862
3061
|
}
|
|
2863
3062
|
function isTransformSkewed(m) {
|
|
2864
|
-
const
|
|
2865
|
-
const basisDot = te[0] * te[3] + te[1] * te[4];
|
|
3063
|
+
const basisDot = m.a * m.c + m.b * m.d;
|
|
2866
3064
|
if (basisDot === 0)
|
|
2867
3065
|
return false;
|
|
2868
|
-
const
|
|
2869
|
-
|
|
2870
|
-
return Math.abs(basisDot / (sx * sy)) > Number.EPSILON;
|
|
2871
|
-
}
|
|
2872
|
-
function getTransformScaleX(m) {
|
|
2873
|
-
const te = m.elements;
|
|
2874
|
-
return Math.sqrt(te[0] * te[0] + te[1] * te[1]);
|
|
2875
|
-
}
|
|
2876
|
-
function getTransformScaleY(m) {
|
|
2877
|
-
const te = m.elements;
|
|
2878
|
-
return Math.sqrt(te[3] * te[3] + te[4] * te[4]);
|
|
3066
|
+
const { scale } = m.decompose();
|
|
3067
|
+
return Math.abs(basisDot / (scale.x * scale.y)) > Number.EPSILON;
|
|
2879
3068
|
}
|
|
2880
3069
|
function eigenDecomposition(A, B, C) {
|
|
2881
3070
|
let rt1, rt2, cs, sn, t;
|
|
@@ -2957,9 +3146,9 @@ class LineCurve extends Curve {
|
|
|
2957
3146
|
}
|
|
2958
3147
|
getPoint(t, output = new Vector2()) {
|
|
2959
3148
|
if (t === 1) {
|
|
2960
|
-
output.
|
|
3149
|
+
output.copyFrom(this.p2);
|
|
2961
3150
|
} else {
|
|
2962
|
-
output.
|
|
3151
|
+
output.copyFrom(this.p2).sub(this.p1).scale(t).add(this.p1);
|
|
2963
3152
|
}
|
|
2964
3153
|
return output;
|
|
2965
3154
|
}
|
|
@@ -3025,10 +3214,10 @@ class LineCurve extends Curve {
|
|
|
3025
3214
|
ctx.lineTo(p2.x, p2.y);
|
|
3026
3215
|
return this;
|
|
3027
3216
|
}
|
|
3028
|
-
|
|
3029
|
-
super.
|
|
3030
|
-
this.p1.
|
|
3031
|
-
this.p2.
|
|
3217
|
+
copyFrom(source) {
|
|
3218
|
+
super.copyFrom(source);
|
|
3219
|
+
this.p1.copyFrom(source.p1);
|
|
3220
|
+
this.p2.copyFrom(source.p2);
|
|
3032
3221
|
return this;
|
|
3033
3222
|
}
|
|
3034
3223
|
}
|
|
@@ -3167,8 +3356,8 @@ class CompositeCurve extends Curve {
|
|
|
3167
3356
|
this.curves.forEach((curve) => curve.drawTo(ctx));
|
|
3168
3357
|
return this;
|
|
3169
3358
|
}
|
|
3170
|
-
|
|
3171
|
-
super.
|
|
3359
|
+
copyFrom(source) {
|
|
3360
|
+
super.copyFrom(source);
|
|
3172
3361
|
this.curves = source.curves.map((curve) => curve.clone());
|
|
3173
3362
|
return this;
|
|
3174
3363
|
}
|
|
@@ -3265,12 +3454,12 @@ class CubicBezierCurve extends Curve {
|
|
|
3265
3454
|
ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y);
|
|
3266
3455
|
return this;
|
|
3267
3456
|
}
|
|
3268
|
-
|
|
3269
|
-
super.
|
|
3270
|
-
this.p1.
|
|
3271
|
-
this.cp1.
|
|
3272
|
-
this.cp2.
|
|
3273
|
-
this.p2.
|
|
3457
|
+
copyFrom(source) {
|
|
3458
|
+
super.copyFrom(source);
|
|
3459
|
+
this.p1.copyFrom(source.p1);
|
|
3460
|
+
this.cp1.copyFrom(source.cp1);
|
|
3461
|
+
this.cp2.copyFrom(source.cp2);
|
|
3462
|
+
this.p2.copyFrom(source.p2);
|
|
3274
3463
|
return this;
|
|
3275
3464
|
}
|
|
3276
3465
|
}
|
|
@@ -3339,8 +3528,8 @@ class EquilateralPloygonCurve extends PloygonCurve {
|
|
|
3339
3528
|
this.curves = curves;
|
|
3340
3529
|
return this;
|
|
3341
3530
|
}
|
|
3342
|
-
|
|
3343
|
-
super.
|
|
3531
|
+
copyFrom(source) {
|
|
3532
|
+
super.copyFrom(source);
|
|
3344
3533
|
this.cx = source.cx;
|
|
3345
3534
|
this.cy = source.cy;
|
|
3346
3535
|
this.radius = source.radius;
|
|
@@ -3412,11 +3601,11 @@ class QuadraticBezierCurve extends Curve {
|
|
|
3412
3601
|
ctx.quadraticCurveTo(cp.x, cp.y, p2.x, p2.y);
|
|
3413
3602
|
return this;
|
|
3414
3603
|
}
|
|
3415
|
-
|
|
3416
|
-
super.
|
|
3417
|
-
this.p1.
|
|
3418
|
-
this.cp.
|
|
3419
|
-
this.p2.
|
|
3604
|
+
copyFrom(source) {
|
|
3605
|
+
super.copyFrom(source);
|
|
3606
|
+
this.p1.copyFrom(source.p1);
|
|
3607
|
+
this.cp.copyFrom(source.cp);
|
|
3608
|
+
this.p2.copyFrom(source.p2);
|
|
3420
3609
|
return this;
|
|
3421
3610
|
}
|
|
3422
3611
|
}
|
|
@@ -3463,8 +3652,8 @@ class RectangleCurve extends PloygonCurve {
|
|
|
3463
3652
|
y + height
|
|
3464
3653
|
];
|
|
3465
3654
|
}
|
|
3466
|
-
|
|
3467
|
-
super.
|
|
3655
|
+
copyFrom(source) {
|
|
3656
|
+
super.copyFrom(source);
|
|
3468
3657
|
this.x = source.x;
|
|
3469
3658
|
this.y = source.y;
|
|
3470
3659
|
this.width = source.width;
|
|
@@ -3502,8 +3691,8 @@ class RoundRectangleCurve extends RoundCurve {
|
|
|
3502
3691
|
ctx.roundRect(x, y, width, height, radius);
|
|
3503
3692
|
return this;
|
|
3504
3693
|
}
|
|
3505
|
-
|
|
3506
|
-
super.
|
|
3694
|
+
copyFrom(source) {
|
|
3695
|
+
super.copyFrom(source);
|
|
3507
3696
|
this.x = source.x;
|
|
3508
3697
|
this.y = source.y;
|
|
3509
3698
|
this.width = source.width;
|
|
@@ -3537,8 +3726,8 @@ class SplineCurve extends Curve {
|
|
|
3537
3726
|
getControlPointRefs() {
|
|
3538
3727
|
return this.points;
|
|
3539
3728
|
}
|
|
3540
|
-
|
|
3541
|
-
super.
|
|
3729
|
+
copyFrom(source) {
|
|
3730
|
+
super.copyFrom(source);
|
|
3542
3731
|
this.points = [];
|
|
3543
3732
|
for (let i = 0, len = source.points.length; i < len; i++) {
|
|
3544
3733
|
this.points.push(source.points[i].clone());
|
|
@@ -3621,7 +3810,7 @@ class CurvePath extends CompositeCurve {
|
|
|
3621
3810
|
const end = this.currentPoint;
|
|
3622
3811
|
if (end && !start.equals(end)) {
|
|
3623
3812
|
this.curves.push(new LineCurve(end.clone(), start.clone()));
|
|
3624
|
-
end.
|
|
3813
|
+
end.copyFrom(start);
|
|
3625
3814
|
}
|
|
3626
3815
|
this.startPoint = void 0;
|
|
3627
3816
|
}
|
|
@@ -3762,8 +3951,8 @@ class CurvePath extends CompositeCurve {
|
|
|
3762
3951
|
}
|
|
3763
3952
|
return this;
|
|
3764
3953
|
}
|
|
3765
|
-
|
|
3766
|
-
super.
|
|
3954
|
+
copyFrom(source) {
|
|
3955
|
+
super.copyFrom(source);
|
|
3767
3956
|
this.autoClose = source.autoClose;
|
|
3768
3957
|
this.currentPoint = source.currentPoint?.clone();
|
|
3769
3958
|
return this;
|
|
@@ -3957,8 +4146,8 @@ class Path2D extends CompositeCurve {
|
|
|
3957
4146
|
pointsB[1] ?? pointsB[0]
|
|
3958
4147
|
);
|
|
3959
4148
|
if (point) {
|
|
3960
|
-
pointsA[pointsA.length - 1].
|
|
3961
|
-
pointsB[0].
|
|
4149
|
+
pointsA[pointsA.length - 1].copyFrom(point);
|
|
4150
|
+
pointsB[0].copyFrom(point);
|
|
3962
4151
|
}
|
|
3963
4152
|
});
|
|
3964
4153
|
});
|
|
@@ -3989,8 +4178,8 @@ class Path2D extends CompositeCurve {
|
|
|
3989
4178
|
point.clone().add({ x: -halfStrokeWidth, y: -halfStrokeWidth })
|
|
3990
4179
|
);
|
|
3991
4180
|
}
|
|
3992
|
-
min.
|
|
3993
|
-
max.
|
|
4181
|
+
min.clampMin(...points);
|
|
4182
|
+
max.clampMax(...points);
|
|
3994
4183
|
}
|
|
3995
4184
|
}
|
|
3996
4185
|
});
|
|
@@ -4128,8 +4317,8 @@ class Path2D extends CompositeCurve {
|
|
|
4128
4317
|
}
|
|
4129
4318
|
return `<path d="${this.toData()}" style="${cssText}"></path>`;
|
|
4130
4319
|
}
|
|
4131
|
-
|
|
4132
|
-
super.
|
|
4320
|
+
copyFrom(source) {
|
|
4321
|
+
super.copyFrom(source);
|
|
4133
4322
|
this.currentCurve = source.currentCurve.clone();
|
|
4134
4323
|
this.style = { ...source.style };
|
|
4135
4324
|
return this;
|
|
@@ -4296,4 +4485,4 @@ function applyFFD(point, grid, width = grid.width, height = grid.height) {
|
|
|
4296
4485
|
point.set(x, y);
|
|
4297
4486
|
}
|
|
4298
4487
|
|
|
4299
|
-
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPloygonCurve, FFDControlGrid, LineCurve,
|
|
4488
|
+
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPloygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PloygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|