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