modern-path2d 1.4.16 → 1.5.1

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.mjs CHANGED
@@ -43,9 +43,10 @@ function setCanvasContext(ctx, style) {
43
43
  }
44
44
 
45
45
  class Vector2 {
46
- constructor(x = 0, y = 0) {
47
- this.x = x;
48
- this.y = y;
46
+ constructor(_x = 0, _y = 0, _onUpdate) {
47
+ this._x = _x;
48
+ this._y = _y;
49
+ this._onUpdate = _onUpdate;
49
50
  }
50
51
  static get MAX() {
51
52
  return new Vector2(Infinity, Infinity);
@@ -53,141 +54,173 @@ class Vector2 {
53
54
  static get MIN() {
54
55
  return new Vector2(-Infinity, -Infinity);
55
56
  }
56
- get array() {
57
- return [this.x, this.y];
57
+ static lerp(a, b, t) {
58
+ return new Vector2(b.x, b.y).clone().sub(a).multiply(t).add(a);
58
59
  }
59
- finite() {
60
- this.x = Number.isFinite(this.x) ? this.x : 0;
61
- this.y = Number.isFinite(this.y) ? this.y : 0;
62
- return this;
60
+ get width() {
61
+ return this.x;
63
62
  }
64
- set(x, y) {
65
- this.x = x;
66
- this.y = y;
67
- return this;
63
+ set width(val) {
64
+ this.x = val;
68
65
  }
69
- add(vec) {
70
- this.x += vec.x;
71
- this.y += vec.y;
72
- return this;
66
+ get height() {
67
+ return this.y;
73
68
  }
74
- sub(vec) {
75
- this.x -= vec.x;
76
- this.y -= vec.y;
77
- return this;
69
+ set height(val) {
70
+ this.y = val;
78
71
  }
79
- multiply(vec) {
80
- this.x *= vec.x;
81
- this.y *= vec.y;
82
- return this;
72
+ get left() {
73
+ return this.x;
83
74
  }
84
- divide(vec) {
85
- this.x /= vec.x;
86
- this.y /= vec.y;
87
- return this;
75
+ set left(val) {
76
+ this.x = val;
88
77
  }
89
- dot(vec) {
90
- return this.x * vec.x + this.y * vec.y;
78
+ get top() {
79
+ return this.y;
91
80
  }
92
- cross(vec) {
93
- return this.x * vec.y - this.y * vec.x;
81
+ set top(val) {
82
+ this.y = val;
94
83
  }
95
- rotate(a, target = { x: 0, y: 0 }) {
96
- const rotation = -a / 180 * Math.PI;
97
- const x = this.x - target.x;
98
- const y = -(this.y - target.y);
99
- const sin = Math.sin(rotation);
100
- const cos = Math.cos(rotation);
101
- this.set(
102
- target.x + (x * cos - y * sin),
103
- target.y - (x * sin + y * cos)
104
- );
84
+ get x() {
85
+ return this._x;
86
+ }
87
+ set x(value) {
88
+ if (this._x !== value) {
89
+ this._x = value;
90
+ this._onUpdate?.(this);
91
+ }
92
+ }
93
+ get y() {
94
+ return this._y;
95
+ }
96
+ set y(value) {
97
+ if (this._y !== value) {
98
+ this._y = value;
99
+ this._onUpdate?.(this);
100
+ }
101
+ }
102
+ set(x = 0, y = x) {
103
+ if (this._x !== x || this._y !== y) {
104
+ this._x = x;
105
+ this._y = y;
106
+ this._onUpdate?.(this);
107
+ }
105
108
  return this;
106
109
  }
107
- distanceTo(vec) {
108
- return Math.sqrt(this.distanceToSquared(vec));
110
+ add(p) {
111
+ return this.set(this._x + p.x, this._y + p.y);
109
112
  }
110
- distanceToSquared(vec) {
111
- const dx = this.x - vec.x;
112
- const dy = this.y - vec.y;
113
- return dx * dx + dy * dy;
113
+ sub(p) {
114
+ return this.set(this._x - p.x, this._y - p.y);
114
115
  }
115
- lengthSquared() {
116
- return this.x * this.x + this.y * this.y;
116
+ subVectors(a, b) {
117
+ return this.set(a.x - b.x, a.y - b.y);
117
118
  }
118
- length() {
119
- return Math.sqrt(this.lengthSquared());
119
+ multiply(x = 0, y = x) {
120
+ return this.set(this._x * x, this._y * y);
120
121
  }
121
- scale(sx, sy = sx, target = { x: 0, y: 0 }) {
122
- const x = sx < 0 ? target.x - this.x + target.x : this.x;
123
- const y = sy < 0 ? target.y - this.y + target.y : this.y;
124
- this.x = x * Math.abs(sx);
125
- this.y = y * Math.abs(sy);
126
- return this;
122
+ divide(x = 0, y = x) {
123
+ return this.set(this._x / x, this._y / y);
127
124
  }
128
- skew(ax, ay = 0, target = { x: 0, y: 0 }) {
129
- const dx = this.x - target.x;
130
- const dy = this.y - target.y;
131
- this.x = target.x + (dx + Math.tan(ax) * dy);
132
- this.y = target.y + (dy + Math.tan(ay) * dx);
133
- return this;
125
+ cross(p) {
126
+ return this._x * p.y - this._y * p.x;
134
127
  }
135
- min(...vecs) {
136
- this.x = Math.min(this.x, ...vecs.map((v) => v.x));
137
- this.y = Math.min(this.y, ...vecs.map((v) => v.y));
138
- return this;
128
+ dot(p) {
129
+ return this._x * p.x + this._y * p.y;
139
130
  }
140
- max(...vecs) {
141
- this.x = Math.max(this.x, ...vecs.map((v) => v.x));
142
- this.y = Math.max(this.y, ...vecs.map((v) => v.y));
143
- return this;
131
+ rotate(rad, origin = { x: 0, y: 0 }) {
132
+ const { x, y } = this;
133
+ const cos = Math.cos(rad);
134
+ const sin = Math.sin(rad);
135
+ return this.set(
136
+ (x - origin.x) * cos - (y - origin.y) * sin + origin.x,
137
+ (x - origin.x) * sin + (y - origin.y) * cos + origin.y
138
+ );
144
139
  }
145
- normalize() {
146
- return this.scale(1 / (this.length() || 1));
140
+ getLength() {
141
+ const { x, y } = this;
142
+ return Math.sqrt(x * x + y * y);
147
143
  }
148
- addVectors(a, b) {
149
- this.x = a.x + b.x;
150
- this.y = a.y + b.y;
151
- return this;
144
+ getAngle() {
145
+ return Math.atan2(-this.x, -this.y) + Math.PI;
152
146
  }
153
- subVectors(a, b) {
154
- this.x = a.x - b.x;
155
- this.y = a.y - b.y;
156
- return this;
147
+ distanceTo(p) {
148
+ return Math.hypot(p.x - this.x, p.y - this.y);
157
149
  }
158
- multiplyVectors(a, b) {
159
- this.x = a.x * b.x;
160
- this.y = a.y * b.y;
150
+ normalize() {
151
+ const scalar = 1 / (this.getLength() || 1);
152
+ this.set(this.x * scalar, this.y * scalar);
161
153
  return this;
162
154
  }
163
- divideVectors(a, b) {
164
- this.x = a.x / b.x;
165
- this.y = a.y / b.y;
155
+ copyFrom(p) {
156
+ if (this._x !== p.x || this._y !== p.y) {
157
+ this._x = p.x;
158
+ this._y = p.y;
159
+ this._onUpdate?.(this);
160
+ }
166
161
  return this;
167
162
  }
168
- lerpVectors(v1, v2, alpha) {
169
- this.x = v1.x + (v2.x - v1.x) * alpha;
170
- this.y = v1.y + (v2.y - v1.y) * alpha;
171
- return this;
163
+ copyTo(p) {
164
+ p.set(this._x, this._y);
165
+ return p;
172
166
  }
173
167
  equals(vec) {
174
- return this.x === vec.x && this.y === vec.y;
175
- }
176
- applyMatrix3(m) {
177
- const x = this.x;
178
- const y = this.y;
179
- const e = m.elements;
180
- this.x = e[0] * x + e[3] * y + e[6];
181
- this.y = e[1] * x + e[4] * y + e[7];
182
- return this;
168
+ return this._x === vec.x && this._y === vec.y;
183
169
  }
184
- copy(vec) {
185
- this.x = vec.x;
186
- this.y = vec.y;
187
- return this;
170
+ get array() {
171
+ return [this.x, this.y];
188
172
  }
189
- clone() {
190
- return new Vector2(this.x, this.y);
173
+ finite() {
174
+ return this.set(
175
+ Number.isFinite(this._x) ? this._x : 0,
176
+ Number.isFinite(this._y) ? this._y : 0
177
+ );
178
+ }
179
+ lengthSquared() {
180
+ return this._x * this._x + this._y * this._y;
181
+ }
182
+ length() {
183
+ return Math.sqrt(this.lengthSquared());
184
+ }
185
+ scale(sx, sy = sx, origin = { x: 0, y: 0 }) {
186
+ const x = sx < 0 ? origin.x - this._x + origin.x : this._x;
187
+ const y = sy < 0 ? origin.y - this._y + origin.y : this._y;
188
+ return this.set(
189
+ x * Math.abs(sx),
190
+ y * Math.abs(sy)
191
+ );
192
+ }
193
+ skew(ax, ay = 0, origin = { x: 0, y: 0 }) {
194
+ const dx = this._x - origin.x;
195
+ const dy = this._y - origin.y;
196
+ return this.set(
197
+ origin.x + (dx + Math.tan(ax) * dy),
198
+ origin.y + (dy + Math.tan(ay) * dx)
199
+ );
200
+ }
201
+ clampMin(...pList) {
202
+ return this.set(
203
+ Math.min(this._x, ...pList.map((v) => v.x)),
204
+ Math.min(this._y, ...pList.map((v) => v.y))
205
+ );
206
+ }
207
+ clampMax(...pList) {
208
+ return this.set(
209
+ Math.max(this.x, ...pList.map((v) => v.x)),
210
+ Math.max(this.y, ...pList.map((v) => v.y))
211
+ );
212
+ }
213
+ clone(_onUpdate) {
214
+ return new Vector2(this._x, this._y, _onUpdate ?? this._onUpdate);
215
+ }
216
+ toJSON() {
217
+ return {
218
+ x: this._x,
219
+ y: this._y
220
+ };
221
+ }
222
+ destroy() {
223
+ this._onUpdate = void 0;
191
224
  }
192
225
  }
193
226
 
@@ -263,202 +296,6 @@ class BoundingBox {
263
296
  }
264
297
  }
265
298
 
266
- class Matrix3 {
267
- elements = [];
268
- constructor(n11 = 1, n12 = 0, n13 = 0, n21 = 0, n22 = 1, n23 = 0, n31 = 0, n32 = 0, n33 = 1) {
269
- this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33);
270
- }
271
- set(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
272
- const te = this.elements;
273
- te[0] = n11;
274
- te[1] = n21;
275
- te[2] = n31;
276
- te[3] = n12;
277
- te[4] = n22;
278
- te[5] = n32;
279
- te[6] = n13;
280
- te[7] = n23;
281
- te[8] = n33;
282
- return this;
283
- }
284
- identity() {
285
- this.set(
286
- 1,
287
- 0,
288
- 0,
289
- 0,
290
- 1,
291
- 0,
292
- 0,
293
- 0,
294
- 1
295
- );
296
- return this;
297
- }
298
- copy(m) {
299
- const te = this.elements;
300
- const me = m.elements;
301
- te[0] = me[0];
302
- te[1] = me[1];
303
- te[2] = me[2];
304
- te[3] = me[3];
305
- te[4] = me[4];
306
- te[5] = me[5];
307
- te[6] = me[6];
308
- te[7] = me[7];
309
- te[8] = me[8];
310
- return this;
311
- }
312
- multiply(m) {
313
- return this.multiplyMatrices(this, m);
314
- }
315
- premultiply(m) {
316
- return this.multiplyMatrices(m, this);
317
- }
318
- multiplyMatrices(a, b) {
319
- const ae = a.elements;
320
- const be = b.elements;
321
- const te = this.elements;
322
- const a11 = ae[0];
323
- const a12 = ae[3];
324
- const a13 = ae[6];
325
- const a21 = ae[1];
326
- const a22 = ae[4];
327
- const a23 = ae[7];
328
- const a31 = ae[2];
329
- const a32 = ae[5];
330
- const a33 = ae[8];
331
- const b11 = be[0];
332
- const b12 = be[3];
333
- const b13 = be[6];
334
- const b21 = be[1];
335
- const b22 = be[4];
336
- const b23 = be[7];
337
- const b31 = be[2];
338
- const b32 = be[5];
339
- const b33 = be[8];
340
- te[0] = a11 * b11 + a12 * b21 + a13 * b31;
341
- te[3] = a11 * b12 + a12 * b22 + a13 * b32;
342
- te[6] = a11 * b13 + a12 * b23 + a13 * b33;
343
- te[1] = a21 * b11 + a22 * b21 + a23 * b31;
344
- te[4] = a21 * b12 + a22 * b22 + a23 * b32;
345
- te[7] = a21 * b13 + a22 * b23 + a23 * b33;
346
- te[2] = a31 * b11 + a32 * b21 + a33 * b31;
347
- te[5] = a31 * b12 + a32 * b22 + a33 * b32;
348
- te[8] = a31 * b13 + a32 * b23 + a33 * b33;
349
- return this;
350
- }
351
- invert() {
352
- const te = this.elements;
353
- const n11 = te[0];
354
- const n21 = te[1];
355
- const n31 = te[2];
356
- const n12 = te[3];
357
- const n22 = te[4];
358
- const n32 = te[5];
359
- const n13 = te[6];
360
- const n23 = te[7];
361
- const n33 = te[8];
362
- const t11 = n33 * n22 - n32 * n23;
363
- const t12 = n32 * n13 - n33 * n12;
364
- const t13 = n23 * n12 - n22 * n13;
365
- const det = n11 * t11 + n21 * t12 + n31 * t13;
366
- if (det === 0)
367
- return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
368
- const detInv = 1 / det;
369
- te[0] = t11 * detInv;
370
- te[1] = (n31 * n23 - n33 * n21) * detInv;
371
- te[2] = (n32 * n21 - n31 * n22) * detInv;
372
- te[3] = t12 * detInv;
373
- te[4] = (n33 * n11 - n31 * n13) * detInv;
374
- te[5] = (n31 * n12 - n32 * n11) * detInv;
375
- te[6] = t13 * detInv;
376
- te[7] = (n21 * n13 - n23 * n11) * detInv;
377
- te[8] = (n22 * n11 - n21 * n12) * detInv;
378
- return this;
379
- }
380
- transpose() {
381
- let tmp;
382
- const m = this.elements;
383
- tmp = m[1];
384
- m[1] = m[3];
385
- m[3] = tmp;
386
- tmp = m[2];
387
- m[2] = m[6];
388
- m[6] = tmp;
389
- tmp = m[5];
390
- m[5] = m[7];
391
- m[7] = tmp;
392
- return this;
393
- }
394
- scale(sx, sy) {
395
- this.premultiply(_m3.makeScale(sx, sy));
396
- return this;
397
- }
398
- rotate(theta) {
399
- this.premultiply(_m3.makeRotation(-theta));
400
- return this;
401
- }
402
- translate(tx, ty) {
403
- this.premultiply(_m3.makeTranslation(tx, ty));
404
- return this;
405
- }
406
- makeTranslation(x, y) {
407
- this.set(
408
- 1,
409
- 0,
410
- x,
411
- 0,
412
- 1,
413
- y,
414
- 0,
415
- 0,
416
- 1
417
- );
418
- return this;
419
- }
420
- makeRotation(theta) {
421
- const c = Math.cos(theta);
422
- const s = Math.sin(theta);
423
- this.set(
424
- c,
425
- -s,
426
- 0,
427
- s,
428
- c,
429
- 0,
430
- 0,
431
- 0,
432
- 1
433
- );
434
- return this;
435
- }
436
- makeScale(x, y) {
437
- this.set(
438
- x,
439
- 0,
440
- 0,
441
- 0,
442
- y,
443
- 0,
444
- 0,
445
- 0,
446
- 1
447
- );
448
- return this;
449
- }
450
- fromArray(array, offset = 0) {
451
- for (let i = 0; i < 9; i++) {
452
- this.elements[i] = array[i + offset];
453
- }
454
- return this;
455
- }
456
- clone() {
457
- return new this.constructor().fromArray(this.elements);
458
- }
459
- }
460
- const _m3 = /* @__PURE__ */ new Matrix3();
461
-
462
299
  function svgAngle(ux, uy, vx, vy) {
463
300
  const dot = ux * vx + uy * vy;
464
301
  const len = Math.sqrt(ux * ux + uy * uy) * Math.sqrt(vx * vx + vy * vy);
@@ -651,10 +488,10 @@ function svgPathCommandsAddToPath2D(commands, path) {
651
488
  if (cmd.type === "m") {
652
489
  current.add(cmd);
653
490
  } else {
654
- current.copy(cmd);
491
+ current.copyFrom(cmd);
655
492
  }
656
493
  path.moveTo(current.x, current.y);
657
- control.copy(current);
494
+ control.copyFrom(current);
658
495
  } else if (cmd.type === "h" || cmd.type === "H") {
659
496
  if (cmd.type === "h") {
660
497
  current.x += cmd.x;
@@ -662,7 +499,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
662
499
  current.x = cmd.x;
663
500
  }
664
501
  path.lineTo(current.x, current.y);
665
- control.copy(current);
502
+ control.copyFrom(current);
666
503
  } else if (cmd.type === "v" || cmd.type === "V") {
667
504
  if (cmd.type === "v") {
668
505
  current.y += cmd.y;
@@ -670,15 +507,15 @@ function svgPathCommandsAddToPath2D(commands, path) {
670
507
  current.y = cmd.y;
671
508
  }
672
509
  path.lineTo(current.x, current.y);
673
- control.copy(current);
510
+ control.copyFrom(current);
674
511
  } else if (cmd.type === "l" || cmd.type === "L") {
675
512
  if (cmd.type === "l") {
676
513
  current.add(cmd);
677
514
  } else {
678
- current.copy(cmd);
515
+ current.copyFrom(cmd);
679
516
  }
680
517
  path.lineTo(current.x, current.y);
681
- control.copy(current);
518
+ control.copyFrom(current);
682
519
  } else if (cmd.type === "c" || cmd.type === "C") {
683
520
  if (cmd.type === "c") {
684
521
  path.bezierCurveTo(
@@ -703,7 +540,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
703
540
  );
704
541
  control.x = cmd.x2;
705
542
  control.y = cmd.y2;
706
- current.copy(cmd);
543
+ current.copyFrom(cmd);
707
544
  }
708
545
  } else if (cmd.type === "s" || cmd.type === "S") {
709
546
  if (cmd.type === "s") {
@@ -729,7 +566,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
729
566
  );
730
567
  control.x = cmd.x2;
731
568
  control.y = cmd.y2;
732
- current.copy(cmd);
569
+ current.copyFrom(cmd);
733
570
  }
734
571
  } else if (cmd.type === "q" || cmd.type === "Q") {
735
572
  if (cmd.type === "q") {
@@ -751,7 +588,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
751
588
  );
752
589
  control.x = cmd.x1;
753
590
  control.y = cmd.y1;
754
- current.copy(cmd);
591
+ current.copyFrom(cmd);
755
592
  }
756
593
  } else if (cmd.type === "t" || cmd.type === "T") {
757
594
  const rx = getReflection(current.x, control.x);
@@ -773,7 +610,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
773
610
  cmd.x,
774
611
  cmd.y
775
612
  );
776
- current.copy(cmd);
613
+ current.copyFrom(cmd);
777
614
  }
778
615
  } else if (cmd.type === "a" || cmd.type === "A") {
779
616
  const start = current.clone();
@@ -784,9 +621,9 @@ function svgPathCommandsAddToPath2D(commands, path) {
784
621
  } else {
785
622
  if (current.equals(cmd))
786
623
  continue;
787
- current.copy(cmd);
624
+ current.copyFrom(cmd);
788
625
  }
789
- control.copy(current);
626
+ control.copyFrom(current);
790
627
  parseArcCommand(
791
628
  path,
792
629
  cmd.rx,
@@ -799,7 +636,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
799
636
  );
800
637
  } else if (cmd.type === "z" || cmd.type === "Z") {
801
638
  if (path.startPoint) {
802
- current.copy(path.startPoint);
639
+ current.copyFrom(path.startPoint);
803
640
  }
804
641
  path.closePath();
805
642
  } else {
@@ -1099,25 +936,20 @@ function parseFloatWithUnits(string) {
1099
936
  return scale * Number.parseFloat(string);
1100
937
  }
1101
938
 
1102
- const tempTransform0$1 = new Matrix3();
1103
- const tempTransform1$1 = new Matrix3();
1104
- const tempTransform2$1 = new Matrix3();
1105
- const tempTransform3 = new Matrix3();
1106
939
  function getNodeTransform(node, currentTransform, transformStack) {
1107
940
  if (!(node.hasAttribute("transform") || node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y")))) {
1108
941
  return null;
1109
942
  }
1110
943
  const transform = parseNodeTransform(node);
1111
944
  if (transformStack.length > 0) {
1112
- transform.premultiply(transformStack[transformStack.length - 1]);
945
+ transform.prepend(transformStack[transformStack.length - 1]);
1113
946
  }
1114
- currentTransform.copy(transform);
947
+ currentTransform.copyFrom(transform);
1115
948
  transformStack.push(transform);
1116
949
  return transform;
1117
950
  }
1118
951
  function parseNodeTransform(node) {
1119
- const transform = new Matrix3();
1120
- const currentTransform = tempTransform0$1;
952
+ const transform = new Transform2D();
1121
953
  if (node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y"))) {
1122
954
  transform.translate(
1123
955
  parseFloatWithUnits(node.getAttribute("x")),
@@ -1125,102 +957,7 @@ function parseNodeTransform(node) {
1125
957
  );
1126
958
  }
1127
959
  if (node.hasAttribute("transform")) {
1128
- const transformsTexts = node.getAttribute("transform").split(")");
1129
- for (let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex--) {
1130
- const transformText = transformsTexts[tIndex].trim();
1131
- if (transformText === "")
1132
- continue;
1133
- const openParPos = transformText.indexOf("(");
1134
- const closeParPos = transformText.length;
1135
- if (openParPos > 0 && openParPos < closeParPos) {
1136
- const transformType = transformText.slice(0, openParPos);
1137
- const array = parsePathDataArgs(transformText.slice(openParPos + 1));
1138
- currentTransform.identity();
1139
- switch (transformType) {
1140
- case "translate":
1141
- if (array.length >= 1) {
1142
- const tx = array[0];
1143
- let ty = 0;
1144
- if (array.length >= 2) {
1145
- ty = array[1];
1146
- }
1147
- currentTransform.translate(tx, ty);
1148
- }
1149
- break;
1150
- case "rotate":
1151
- if (array.length >= 1) {
1152
- let angle = 0;
1153
- let cx = 0;
1154
- let cy = 0;
1155
- angle = array[0] * Math.PI / 180;
1156
- if (array.length >= 3) {
1157
- cx = array[1];
1158
- cy = array[2];
1159
- }
1160
- tempTransform1$1.makeTranslation(-cx, -cy);
1161
- tempTransform2$1.makeRotation(angle);
1162
- tempTransform3.multiplyMatrices(tempTransform2$1, tempTransform1$1);
1163
- tempTransform1$1.makeTranslation(cx, cy);
1164
- currentTransform.multiplyMatrices(tempTransform1$1, tempTransform3);
1165
- }
1166
- break;
1167
- case "scale":
1168
- if (array.length >= 1) {
1169
- currentTransform.scale(
1170
- array[0],
1171
- array[1] ?? array[0]
1172
- );
1173
- }
1174
- break;
1175
- case "skewX":
1176
- if (array.length === 1) {
1177
- currentTransform.set(
1178
- 1,
1179
- Math.tan(array[0] * Math.PI / 180),
1180
- 0,
1181
- 0,
1182
- 1,
1183
- 0,
1184
- 0,
1185
- 0,
1186
- 1
1187
- );
1188
- }
1189
- break;
1190
- case "skewY":
1191
- if (array.length === 1) {
1192
- currentTransform.set(
1193
- 1,
1194
- 0,
1195
- 0,
1196
- Math.tan(array[0] * Math.PI / 180),
1197
- 1,
1198
- 0,
1199
- 0,
1200
- 0,
1201
- 1
1202
- );
1203
- }
1204
- break;
1205
- case "matrix":
1206
- if (array.length === 6) {
1207
- currentTransform.set(
1208
- array[0],
1209
- array[2],
1210
- array[4],
1211
- array[1],
1212
- array[3],
1213
- array[5],
1214
- 0,
1215
- 0,
1216
- 1
1217
- );
1218
- }
1219
- break;
1220
- }
1221
- }
1222
- transform.premultiply(currentTransform);
1223
- }
960
+ transform.appendCssTransform(node.getAttribute("transform"));
1224
961
  }
1225
962
  return transform;
1226
963
  }
@@ -1497,7 +1234,7 @@ function parseNode(node, style, paths = [], stylesheets = {}) {
1497
1234
  if (_style.display === "none") {
1498
1235
  return paths;
1499
1236
  }
1500
- const currentTransform = new Matrix3();
1237
+ const currentTransform = new Transform2D();
1501
1238
  const transformStack = [];
1502
1239
  const transform = getNodeTransform(node, currentTransform, transformStack);
1503
1240
  if (path) {
@@ -1515,7 +1252,7 @@ function parseNode(node, style, paths = [], stylesheets = {}) {
1515
1252
  if (transform) {
1516
1253
  transformStack.pop();
1517
1254
  if (transformStack.length > 0) {
1518
- currentTransform.copy(transformStack[transformStack.length - 1]);
1255
+ currentTransform.copyFrom(transformStack[transformStack.length - 1]);
1519
1256
  } else {
1520
1257
  currentTransform.identity();
1521
1258
  }
@@ -1531,6 +1268,440 @@ function svgToPath2DSet(svg) {
1531
1268
  );
1532
1269
  }
1533
1270
 
1271
+ const PI = Math.PI;
1272
+ const PI_2 = PI * 2;
1273
+
1274
+ class Transform2D {
1275
+ constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
1276
+ this.a = a;
1277
+ this.b = b;
1278
+ this.c = c;
1279
+ this.d = d;
1280
+ this.tx = tx;
1281
+ this.ty = ty;
1282
+ }
1283
+ _array;
1284
+ set(a, b, c, d, tx, ty) {
1285
+ this.a = a;
1286
+ this.b = b;
1287
+ this.c = c;
1288
+ this.d = d;
1289
+ this.tx = tx;
1290
+ this.ty = ty;
1291
+ return this;
1292
+ }
1293
+ append(t2d) {
1294
+ const a1 = this.a;
1295
+ const b1 = this.b;
1296
+ const c1 = this.c;
1297
+ const d1 = this.d;
1298
+ this.a = t2d.a * a1 + t2d.b * c1;
1299
+ this.b = t2d.a * b1 + t2d.b * d1;
1300
+ this.c = t2d.c * a1 + t2d.d * c1;
1301
+ this.d = t2d.c * b1 + t2d.d * d1;
1302
+ this.tx = t2d.tx * a1 + t2d.ty * c1 + this.tx;
1303
+ this.ty = t2d.tx * b1 + t2d.ty * d1 + this.ty;
1304
+ return this;
1305
+ }
1306
+ appendFrom(a, b) {
1307
+ const a1 = a.a;
1308
+ const b1 = a.b;
1309
+ const c1 = a.c;
1310
+ const d1 = a.d;
1311
+ const tx = a.tx;
1312
+ const ty = a.ty;
1313
+ const a2 = b.a;
1314
+ const b2 = b.b;
1315
+ const c2 = b.c;
1316
+ const d2 = b.d;
1317
+ this.a = a1 * a2 + b1 * c2;
1318
+ this.b = a1 * b2 + b1 * d2;
1319
+ this.c = c1 * a2 + d1 * c2;
1320
+ this.d = c1 * b2 + d1 * d2;
1321
+ this.tx = tx * a2 + ty * c2 + b.tx;
1322
+ this.ty = tx * b2 + ty * d2 + b.ty;
1323
+ return this;
1324
+ }
1325
+ setTransform(x, y, pivotX, pivotY, scaleX, scaleY, rotation, skewX, skewY) {
1326
+ this.a = Math.cos(rotation + skewY) * scaleX;
1327
+ this.b = Math.sin(rotation + skewY) * scaleX;
1328
+ this.c = -Math.sin(rotation - skewX) * scaleY;
1329
+ this.d = Math.cos(rotation - skewX) * scaleY;
1330
+ this.tx = x - (pivotX * this.a + pivotY * this.c);
1331
+ this.ty = y - (pivotX * this.b + pivotY * this.d);
1332
+ return this;
1333
+ }
1334
+ prepend(t2d) {
1335
+ const tx1 = this.tx;
1336
+ if (t2d.a !== 1 || t2d.b !== 0 || t2d.c !== 0 || t2d.d !== 1) {
1337
+ const a1 = this.a;
1338
+ const c1 = this.c;
1339
+ this.a = a1 * t2d.a + this.b * t2d.c;
1340
+ this.b = a1 * t2d.b + this.b * t2d.d;
1341
+ this.c = c1 * t2d.a + this.d * t2d.c;
1342
+ this.d = c1 * t2d.b + this.d * t2d.d;
1343
+ }
1344
+ this.tx = tx1 * t2d.a + this.ty * t2d.c + t2d.tx;
1345
+ this.ty = tx1 * t2d.b + this.ty * t2d.d + t2d.ty;
1346
+ return this;
1347
+ }
1348
+ _skewX;
1349
+ _skewY;
1350
+ _skewXTan = 1;
1351
+ _skewYTan = 1;
1352
+ skewX(x) {
1353
+ return this.skew(x, 0);
1354
+ }
1355
+ skewY(y) {
1356
+ return this.skew(0, y);
1357
+ }
1358
+ skew(x, y) {
1359
+ if (x !== this._skewX) {
1360
+ this._skewX = x;
1361
+ this._skewXTan = Math.tan(x);
1362
+ }
1363
+ if (y !== this._skewY) {
1364
+ this._skewY = y;
1365
+ this._skewYTan = Math.tan(y);
1366
+ }
1367
+ this.b *= this._skewXTan;
1368
+ this.c *= this._skewYTan;
1369
+ return this;
1370
+ }
1371
+ translateX(x) {
1372
+ return this.translate(x, 0);
1373
+ }
1374
+ translateY(y) {
1375
+ return this.translate(0, y);
1376
+ }
1377
+ translateZ(z) {
1378
+ return this.translate(0, 0, z);
1379
+ }
1380
+ translate3d(x, y, z) {
1381
+ return this.translate(x, y, z);
1382
+ }
1383
+ translate(x, y, _z = 0) {
1384
+ this.tx += x;
1385
+ this.ty += y;
1386
+ return this;
1387
+ }
1388
+ scaleX(x) {
1389
+ return this.scale(x, 1);
1390
+ }
1391
+ scaleY(y) {
1392
+ return this.scale(1, y);
1393
+ }
1394
+ scale3d(x, y, z = 1) {
1395
+ return this.scale(x, y, z);
1396
+ }
1397
+ scale(x, y, _z = 1) {
1398
+ this.a *= x;
1399
+ this.d *= y;
1400
+ this.c *= x;
1401
+ this.b *= y;
1402
+ this.tx *= x;
1403
+ this.ty *= y;
1404
+ return this;
1405
+ }
1406
+ rotateX(x) {
1407
+ return this.scaleY(this._rotateToScale(x));
1408
+ }
1409
+ rotateY(y) {
1410
+ return this.scaleX(this._rotateToScale(y));
1411
+ }
1412
+ rotateZ(z) {
1413
+ return this.rotate(z);
1414
+ }
1415
+ rotate(angle) {
1416
+ const cos = Math.cos(angle);
1417
+ const sin = Math.sin(angle);
1418
+ const a1 = this.a;
1419
+ const c1 = this.c;
1420
+ const tx1 = this.tx;
1421
+ this.a = a1 * cos - this.b * sin;
1422
+ this.b = a1 * sin + this.b * cos;
1423
+ this.c = c1 * cos - this.d * sin;
1424
+ this.d = c1 * sin + this.d * cos;
1425
+ this.tx = tx1 * cos - this.ty * sin;
1426
+ this.ty = tx1 * sin + this.ty * cos;
1427
+ return this;
1428
+ }
1429
+ rotate3d(x, y, z, rad) {
1430
+ const [rx, ry, rz] = this._rotate3d(x, y, z, rad);
1431
+ rx && this.rotateX(rx);
1432
+ ry && this.rotateY(ry);
1433
+ rz && this.rotateZ(rz);
1434
+ return this;
1435
+ }
1436
+ _rotateToScale(rad) {
1437
+ const val = rad / PI_2;
1438
+ return val <= 0.5 ? val * -4 + 1 : (val - 1) * 4 + 1;
1439
+ }
1440
+ _rotate3d(x, y, z, rad) {
1441
+ if (x === 1 && y === 0 && z === 0) {
1442
+ return [rad, 0, 0];
1443
+ } else if (x === 0 && y === 1 && z === 0) {
1444
+ return [0, rad, 0];
1445
+ } else if (x === 0 && y === 0) {
1446
+ return [0, 0, rad];
1447
+ } else {
1448
+ const cos = Math.cos(rad);
1449
+ const sin = Math.sin(rad);
1450
+ const m11 = cos + x * x * (1 - cos);
1451
+ const m12 = x * y * (1 - cos) - z * sin;
1452
+ const m13 = x * z * (1 - cos) + y * sin;
1453
+ const m22 = cos + y * y * (1 - cos);
1454
+ const m23 = y * z * (1 - cos) - x * sin;
1455
+ const m33 = cos + z * z * (1 - cos);
1456
+ const rotateX = -Math.atan2(-m23, m22);
1457
+ const rotateY = -Math.atan2(m13, Math.sqrt(m23 * m23 + m33 * m33));
1458
+ const rotateZ = -Math.atan2(-m12, m11);
1459
+ return [rotateX, rotateY, rotateZ];
1460
+ }
1461
+ }
1462
+ decompose(pivot = { x: 0, y: 0 }, output = {
1463
+ position: { x: 0, y: 0 },
1464
+ scale: { x: 0, y: 0 },
1465
+ skew: { x: 0, y: 0 },
1466
+ rotation: 0
1467
+ }) {
1468
+ const { a, b, c, d, tx, ty } = this;
1469
+ const skewX = -Math.atan2(-c, d);
1470
+ const skewY = Math.atan2(b, a);
1471
+ const delta = Math.abs(skewX + skewY);
1472
+ if (delta < 1e-5 || Math.abs(PI_2 - delta) < 1e-5) {
1473
+ output.rotation = skewY;
1474
+ output.skew.x = output.skew.y = 0;
1475
+ } else {
1476
+ output.rotation = 0;
1477
+ output.skew.x = skewX;
1478
+ output.skew.y = skewY;
1479
+ }
1480
+ output.scale.x = Math.sqrt(a * a + b * b);
1481
+ output.scale.y = Math.sqrt(c * c + d * d);
1482
+ output.position.x = tx + (pivot.x * a + pivot.y * c);
1483
+ output.position.y = ty + (pivot.x * b + pivot.y * d);
1484
+ return output;
1485
+ }
1486
+ apply(pos, newPos) {
1487
+ newPos = newPos || new Vector2();
1488
+ const { x, y } = pos;
1489
+ newPos.x = this.a * x + this.c * y + this.tx;
1490
+ newPos.y = this.b * x + this.d * y + this.ty;
1491
+ return newPos;
1492
+ }
1493
+ affineInvert() {
1494
+ const a1 = this.a;
1495
+ const b1 = this.b;
1496
+ const c1 = this.c;
1497
+ const d1 = this.d;
1498
+ const tx1 = this.tx;
1499
+ const n = a1 * d1 - b1 * c1;
1500
+ this.a = d1 / n;
1501
+ this.b = -b1 / n;
1502
+ this.c = -c1 / n;
1503
+ this.d = a1 / n;
1504
+ this.tx = (c1 * this.ty - d1 * tx1) / n;
1505
+ this.ty = -(a1 * this.ty - b1 * tx1) / n;
1506
+ return this;
1507
+ }
1508
+ affineInverse() {
1509
+ return this.clone().affineInvert();
1510
+ }
1511
+ applyAffineInverse(pos, newPos) {
1512
+ newPos = newPos || new Vector2();
1513
+ const { a, b, c, d, tx, ty } = this;
1514
+ const id = 1 / (a * d + c * -b);
1515
+ const x = pos.x;
1516
+ const y = pos.y;
1517
+ newPos.x = d * id * x + -c * id * y + (ty * c - tx * d) * id;
1518
+ newPos.y = a * id * y + -b * id * x + (-ty * a + tx * b) * id;
1519
+ return newPos;
1520
+ }
1521
+ identity() {
1522
+ this.a = 1;
1523
+ this.b = 0;
1524
+ this.c = 0;
1525
+ this.d = 1;
1526
+ this.tx = 0;
1527
+ this.ty = 0;
1528
+ return this;
1529
+ }
1530
+ isIdentity() {
1531
+ const { a, b, c, d, tx, ty } = this;
1532
+ return a === 1 && b === 0 && c === 0 && d === 1 && tx === 0 && ty === 0;
1533
+ }
1534
+ copyTo(t2d) {
1535
+ t2d.a = this.a;
1536
+ t2d.b = this.b;
1537
+ t2d.c = this.c;
1538
+ t2d.d = this.d;
1539
+ t2d.tx = this.tx;
1540
+ t2d.ty = this.ty;
1541
+ return t2d;
1542
+ }
1543
+ copyFrom(t2d) {
1544
+ this.a = t2d.a;
1545
+ this.b = t2d.b;
1546
+ this.c = t2d.c;
1547
+ this.d = t2d.d;
1548
+ this.tx = t2d.tx;
1549
+ this.ty = t2d.ty;
1550
+ return this;
1551
+ }
1552
+ equals(t2d) {
1553
+ 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;
1554
+ }
1555
+ appendCssTransform(cssTransform) {
1556
+ const transformsTexts = cssTransform.split(")");
1557
+ const transform = new Transform2D();
1558
+ for (let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex--) {
1559
+ const transformText = transformsTexts[tIndex].trim();
1560
+ if (transformText === "")
1561
+ continue;
1562
+ const openParPos = transformText.indexOf("(");
1563
+ const closeParPos = transformText.length;
1564
+ if (openParPos > 0 && openParPos < closeParPos) {
1565
+ const transformType = transformText.slice(0, openParPos);
1566
+ const array = parsePathDataArgs(transformText.slice(openParPos + 1));
1567
+ transform.identity();
1568
+ switch (transformType) {
1569
+ case "translateX":
1570
+ transform.translateX(array[0]);
1571
+ break;
1572
+ case "translateY":
1573
+ transform.translateY(array[0]);
1574
+ break;
1575
+ case "translateZ":
1576
+ transform.translateZ(array[0]);
1577
+ break;
1578
+ case "translate":
1579
+ transform.translate(
1580
+ array[0],
1581
+ array[1] ?? array[0]
1582
+ );
1583
+ break;
1584
+ case "translate3d":
1585
+ transform.translate3d(
1586
+ array[0],
1587
+ array[1] ?? array[0],
1588
+ array[2] ?? array[1] ?? array[0]
1589
+ );
1590
+ break;
1591
+ case "scaleX":
1592
+ transform.scaleX(array[0]);
1593
+ break;
1594
+ case "scaleY":
1595
+ transform.scaleY(array[0]);
1596
+ break;
1597
+ case "scale":
1598
+ transform.scale(
1599
+ array[0],
1600
+ array[1] ?? array[0]
1601
+ );
1602
+ break;
1603
+ case "scale3d":
1604
+ transform.scale3d(
1605
+ array[0],
1606
+ array[1] ?? array[0],
1607
+ array[2] ?? array[1] ?? array[0]
1608
+ );
1609
+ break;
1610
+ case "rotate": {
1611
+ const rad = array[0] * Math.PI / 180;
1612
+ if (array.length >= 3) {
1613
+ const cx = array[1];
1614
+ const cy = array[2];
1615
+ transform.translate(-cx, -cy).rotate(rad).translate(cx, cy);
1616
+ } else {
1617
+ transform.rotate(rad);
1618
+ }
1619
+ break;
1620
+ }
1621
+ case "rotateX":
1622
+ transform.rotateX(array[0] * Math.PI / 180);
1623
+ break;
1624
+ case "rotateY":
1625
+ transform.rotateY(array[0] * Math.PI / 180);
1626
+ break;
1627
+ case "rotateZ":
1628
+ transform.rotateZ(array[0] * Math.PI / 180);
1629
+ break;
1630
+ case "rotate3d":
1631
+ transform.rotate3d(
1632
+ array[0] * Math.PI / 180,
1633
+ (array[1] ?? array[0]) * Math.PI / 180,
1634
+ (array[2] ?? array[1] ?? array[0]) * Math.PI / 180,
1635
+ (array[3] ?? array[2] ?? array[1] ?? array[0]) * Math.PI / 180
1636
+ );
1637
+ break;
1638
+ case "skewX":
1639
+ transform.set(1, 0, Math.tan(array[0] * Math.PI / 180), 1, 0, 0);
1640
+ break;
1641
+ case "skewY":
1642
+ transform.set(1, Math.tan(array[0] * Math.PI / 180), 0, 1, 0, 0);
1643
+ break;
1644
+ case "skew": {
1645
+ const ax = array[0];
1646
+ const ay = array[1] ?? 0;
1647
+ transform.set(1, Math.tan(ay * Math.PI / 180), Math.tan(ax * Math.PI / 180), 1, 0, 0);
1648
+ break;
1649
+ }
1650
+ case "matrix":
1651
+ transform.set(
1652
+ array[0],
1653
+ array[1],
1654
+ array[2],
1655
+ array[3],
1656
+ array[4],
1657
+ array[5]
1658
+ );
1659
+ break;
1660
+ }
1661
+ }
1662
+ this.prepend(transform);
1663
+ }
1664
+ return this;
1665
+ }
1666
+ clone() {
1667
+ return new Transform2D(this.a, this.b, this.c, this.d, this.tx, this.ty);
1668
+ }
1669
+ toArray(transpose, out) {
1670
+ if (!this._array) {
1671
+ this._array = new Float32Array(9);
1672
+ }
1673
+ const array = out || this._array;
1674
+ if (transpose) {
1675
+ array[0] = this.a;
1676
+ array[1] = this.b;
1677
+ array[2] = 0;
1678
+ array[3] = this.c;
1679
+ array[4] = this.d;
1680
+ array[5] = 0;
1681
+ array[6] = this.tx;
1682
+ array[7] = this.ty;
1683
+ array[8] = 1;
1684
+ } else {
1685
+ array[0] = this.a;
1686
+ array[1] = this.c;
1687
+ array[2] = this.tx;
1688
+ array[3] = this.b;
1689
+ array[4] = this.d;
1690
+ array[5] = this.ty;
1691
+ array[6] = 0;
1692
+ array[7] = 0;
1693
+ array[8] = 1;
1694
+ }
1695
+ return array;
1696
+ }
1697
+ toString() {
1698
+ return `[Transform2D a=${this.a} b=${this.b} c=${this.c} d=${this.d} tx=${this.tx} ty=${this.ty}]`;
1699
+ }
1700
+ destroy() {
1701
+ this._array = void 0;
1702
+ }
1703
+ }
1704
+
1534
1705
  function catmullRom(t, p0, p1, p2, p3) {
1535
1706
  const v0 = (p2 - p0) * 0.5;
1536
1707
  const v1 = (p3 - p1) * 0.5;
@@ -2294,7 +2465,7 @@ class Curve {
2294
2465
  if (isFunction) {
2295
2466
  transform(p);
2296
2467
  } else {
2297
- p.applyMatrix3(transform);
2468
+ transform.apply(p, p);
2298
2469
  }
2299
2470
  });
2300
2471
  return this;
@@ -2409,7 +2580,7 @@ class Curve {
2409
2580
  const delta = 1e-4;
2410
2581
  const t1 = Math.max(0, t - delta);
2411
2582
  const t2 = Math.min(1, t + delta);
2412
- return output.copy(this.getPoint(t2).sub(this.getPoint(t1)).normalize());
2583
+ return output.copyFrom(this.getPoint(t2).sub(this.getPoint(t1)).normalize());
2413
2584
  }
2414
2585
  getTangentAt(u, output) {
2415
2586
  return this.getTangent(this.getUToTMapping(u), output);
@@ -2444,8 +2615,8 @@ class Curve {
2444
2615
  const potins = this.getPoints();
2445
2616
  for (let i = 0, len = potins.length; i < len; i++) {
2446
2617
  const p = potins[i];
2447
- min.min(p);
2448
- max.max(p);
2618
+ min.clampMin(p);
2619
+ max.clampMax(p);
2449
2620
  }
2450
2621
  return { min: min.finite(), max: max.finite() };
2451
2622
  }
@@ -2497,18 +2668,18 @@ class Curve {
2497
2668
  });
2498
2669
  return this;
2499
2670
  }
2500
- copy(source) {
2671
+ copyFrom(source) {
2501
2672
  this.arcLengthDivision = source.arcLengthDivision;
2502
2673
  return this;
2503
2674
  }
2504
2675
  clone() {
2505
- return new this.constructor().copy(this);
2676
+ return new this.constructor().copyFrom(this);
2506
2677
  }
2507
2678
  }
2508
2679
 
2509
- const tempTransform0 = new Matrix3();
2510
- const tempTransform1 = new Matrix3();
2511
- const tempTransform2 = new Matrix3();
2680
+ const tempTransform0 = new Transform2D();
2681
+ const tempTransform1 = new Transform2D();
2682
+ const tempTransform2 = new Transform2D();
2512
2683
  const tempV2 = new Vector2();
2513
2684
  class RoundCurve extends Curve {
2514
2685
  constructor(_center = new Vector2(), _radius = new Vector2(), _diff = new Vector2(), rotate = 0, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
@@ -2627,15 +2798,15 @@ class RoundCurve extends Curve {
2627
2798
  );
2628
2799
  return this;
2629
2800
  }
2630
- applyTransform(matrix) {
2801
+ applyTransform(transform) {
2631
2802
  tempV2.set(this.cx, this.cy);
2632
- tempV2.applyMatrix3(matrix);
2803
+ transform.apply(tempV2, tempV2);
2633
2804
  this.cx = tempV2.x;
2634
2805
  this.cy = tempV2.y;
2635
- if (isTransformSkewed(matrix)) {
2636
- transfEllipseGeneric(this, matrix);
2806
+ if (isTransformSkewed(transform)) {
2807
+ transfEllipseGeneric(this, transform);
2637
2808
  } else {
2638
- transfEllipseNoSkew(this, matrix);
2809
+ transfEllipseNoSkew(this, transform);
2639
2810
  }
2640
2811
  return this;
2641
2812
  }
@@ -2762,8 +2933,8 @@ class RoundCurve extends Curve {
2762
2933
  }
2763
2934
  return this._getAdaptiveVerticesByArc(output);
2764
2935
  }
2765
- copy(source) {
2766
- super.copy(source);
2936
+ copyFrom(source) {
2937
+ super.copyFrom(source);
2767
2938
  this.cx = source.cx;
2768
2939
  this.cy = source.cy;
2769
2940
  this.rx = source.rx;
@@ -2784,24 +2955,17 @@ function transfEllipseGeneric(curve, m) {
2784
2955
  const sinTheta = Math.sin(curve.rotate);
2785
2956
  const v1 = new Vector2(a * cosTheta, a * sinTheta);
2786
2957
  const v2 = new Vector2(-b * sinTheta, b * cosTheta);
2787
- const f1 = v1.applyMatrix3(m);
2788
- const f2 = v2.applyMatrix3(m);
2789
- const mF = tempTransform0.set(
2790
- f1.x,
2791
- f2.x,
2792
- 0,
2793
- f1.y,
2794
- f2.y,
2795
- 0,
2796
- 0,
2797
- 0,
2798
- 1
2799
- );
2800
- const mFInv = tempTransform1.copy(mF).invert();
2801
- const mFInvT = tempTransform2.copy(mFInv).transpose();
2802
- const mQ = mFInvT.multiply(mFInv);
2803
- const mQe = mQ.elements;
2804
- const ed = eigenDecomposition(mQe[0], mQe[1], mQe[4]);
2958
+ const f1x = m.a * v1.x + m.c * v1.y;
2959
+ const f1y = m.b * v1.x + m.d * v1.y;
2960
+ const f2x = m.a * v2.x + m.c * v2.y;
2961
+ const f2y = m.b * v2.x + m.d * v2.y;
2962
+ const mF = tempTransform0.set(f1x, f1y, f2x, f2y, 0, 0);
2963
+ const mFInv = tempTransform1.copyFrom(mF).affineInvert();
2964
+ const { a: ia, b: ib, c: ic, d: id } = mFInv;
2965
+ const qA = ia * ia + ib * ib;
2966
+ const qB = ic * ia + id * ib;
2967
+ const qD = ic * ic + id * id;
2968
+ const ed = eigenDecomposition(qA, qB, qD);
2805
2969
  const rt1sqrt = Math.sqrt(ed.rt1);
2806
2970
  const rt2sqrt = Math.sqrt(ed.rt2);
2807
2971
  curve.rx = 1 / rt1sqrt;
@@ -2813,27 +2977,21 @@ function transfEllipseGeneric(curve, m) {
2813
2977
  rt1sqrt,
2814
2978
  0,
2815
2979
  0,
2816
- 0,
2817
2980
  rt2sqrt,
2818
2981
  0,
2819
- 0,
2820
- 0,
2821
- 1
2982
+ 0
2822
2983
  );
2823
2984
  const mRT = tempTransform2.set(
2824
2985
  ed.cs,
2825
2986
  ed.sn,
2826
- 0,
2827
2987
  -ed.sn,
2828
2988
  ed.cs,
2829
2989
  0,
2830
- 0,
2831
- 0,
2832
- 1
2990
+ 0
2833
2991
  );
2834
- const mDRF = mDsqrt.multiply(mRT).multiply(mF);
2992
+ const mDRF = mDsqrt.append(mRT).append(mF);
2835
2993
  const transformAngle = (phi) => {
2836
- const { x: cosR, y: sinR } = new Vector2(Math.cos(phi), Math.sin(phi)).applyMatrix3(mDRF);
2994
+ const { x: cosR, y: sinR } = mDRF.apply({ x: Math.cos(phi), y: Math.sin(phi) });
2837
2995
  return Math.atan2(sinR, cosR);
2838
2996
  };
2839
2997
  curve.startAngle = transformAngle(curve.startAngle);
@@ -2844,11 +3002,10 @@ function transfEllipseGeneric(curve, m) {
2844
3002
  }
2845
3003
  }
2846
3004
  function transfEllipseNoSkew(curve, m) {
2847
- const sx = getTransformScaleX(m);
2848
- const sy = getTransformScaleY(m);
2849
- curve.rx *= sx;
2850
- curve.ry *= sy;
2851
- const theta = sx > Number.EPSILON ? Math.atan2(m.elements[1], m.elements[0]) : Math.atan2(-m.elements[3], m.elements[4]);
3005
+ const { scale } = m.decompose();
3006
+ curve.rx *= scale.x;
3007
+ curve.ry *= scale.y;
3008
+ const theta = scale.x > Number.EPSILON ? Math.atan2(m.b, m.a) : Math.atan2(-m.c, m.d);
2852
3009
  curve.rotate += theta;
2853
3010
  if (isTransformFlipped(m)) {
2854
3011
  curve.startAngle *= -1;
@@ -2857,25 +3014,14 @@ function transfEllipseNoSkew(curve, m) {
2857
3014
  }
2858
3015
  }
2859
3016
  function isTransformFlipped(m) {
2860
- const te = m.elements;
2861
- return te[0] * te[4] - te[1] * te[3] < 0;
3017
+ return m.a * m.d - m.c * m.b < 0;
2862
3018
  }
2863
3019
  function isTransformSkewed(m) {
2864
- const te = m.elements;
2865
- const basisDot = te[0] * te[3] + te[1] * te[4];
3020
+ const basisDot = m.a * m.c + m.b * m.d;
2866
3021
  if (basisDot === 0)
2867
3022
  return false;
2868
- const sx = getTransformScaleX(m);
2869
- const sy = getTransformScaleY(m);
2870
- return Math.abs(basisDot / (sx * sy)) > Number.EPSILON;
2871
- }
2872
- function getTransformScaleX(m) {
2873
- const te = m.elements;
2874
- return Math.sqrt(te[0] * te[0] + te[1] * te[1]);
2875
- }
2876
- function getTransformScaleY(m) {
2877
- const te = m.elements;
2878
- return Math.sqrt(te[3] * te[3] + te[4] * te[4]);
3023
+ const { scale } = m.decompose();
3024
+ return Math.abs(basisDot / (scale.x * scale.y)) > Number.EPSILON;
2879
3025
  }
2880
3026
  function eigenDecomposition(A, B, C) {
2881
3027
  let rt1, rt2, cs, sn, t;
@@ -2957,9 +3103,9 @@ class LineCurve extends Curve {
2957
3103
  }
2958
3104
  getPoint(t, output = new Vector2()) {
2959
3105
  if (t === 1) {
2960
- output.copy(this.p2);
3106
+ output.copyFrom(this.p2);
2961
3107
  } else {
2962
- output.copy(this.p2).sub(this.p1).scale(t).add(this.p1);
3108
+ output.copyFrom(this.p2).sub(this.p1).scale(t).add(this.p1);
2963
3109
  }
2964
3110
  return output;
2965
3111
  }
@@ -3025,10 +3171,10 @@ class LineCurve extends Curve {
3025
3171
  ctx.lineTo(p2.x, p2.y);
3026
3172
  return this;
3027
3173
  }
3028
- copy(source) {
3029
- super.copy(source);
3030
- this.p1.copy(source.p1);
3031
- this.p2.copy(source.p2);
3174
+ copyFrom(source) {
3175
+ super.copyFrom(source);
3176
+ this.p1.copyFrom(source.p1);
3177
+ this.p2.copyFrom(source.p2);
3032
3178
  return this;
3033
3179
  }
3034
3180
  }
@@ -3167,8 +3313,8 @@ class CompositeCurve extends Curve {
3167
3313
  this.curves.forEach((curve) => curve.drawTo(ctx));
3168
3314
  return this;
3169
3315
  }
3170
- copy(source) {
3171
- super.copy(source);
3316
+ copyFrom(source) {
3317
+ super.copyFrom(source);
3172
3318
  this.curves = source.curves.map((curve) => curve.clone());
3173
3319
  return this;
3174
3320
  }
@@ -3265,12 +3411,12 @@ class CubicBezierCurve extends Curve {
3265
3411
  ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y);
3266
3412
  return this;
3267
3413
  }
3268
- copy(source) {
3269
- super.copy(source);
3270
- this.p1.copy(source.p1);
3271
- this.cp1.copy(source.cp1);
3272
- this.cp2.copy(source.cp2);
3273
- this.p2.copy(source.p2);
3414
+ copyFrom(source) {
3415
+ super.copyFrom(source);
3416
+ this.p1.copyFrom(source.p1);
3417
+ this.cp1.copyFrom(source.cp1);
3418
+ this.cp2.copyFrom(source.cp2);
3419
+ this.p2.copyFrom(source.p2);
3274
3420
  return this;
3275
3421
  }
3276
3422
  }
@@ -3339,8 +3485,8 @@ class EquilateralPloygonCurve extends PloygonCurve {
3339
3485
  this.curves = curves;
3340
3486
  return this;
3341
3487
  }
3342
- copy(source) {
3343
- super.copy(source);
3488
+ copyFrom(source) {
3489
+ super.copyFrom(source);
3344
3490
  this.cx = source.cx;
3345
3491
  this.cy = source.cy;
3346
3492
  this.radius = source.radius;
@@ -3412,11 +3558,11 @@ class QuadraticBezierCurve extends Curve {
3412
3558
  ctx.quadraticCurveTo(cp.x, cp.y, p2.x, p2.y);
3413
3559
  return this;
3414
3560
  }
3415
- copy(source) {
3416
- super.copy(source);
3417
- this.p1.copy(source.p1);
3418
- this.cp.copy(source.cp);
3419
- this.p2.copy(source.p2);
3561
+ copyFrom(source) {
3562
+ super.copyFrom(source);
3563
+ this.p1.copyFrom(source.p1);
3564
+ this.cp.copyFrom(source.cp);
3565
+ this.p2.copyFrom(source.p2);
3420
3566
  return this;
3421
3567
  }
3422
3568
  }
@@ -3463,8 +3609,8 @@ class RectangleCurve extends PloygonCurve {
3463
3609
  y + height
3464
3610
  ];
3465
3611
  }
3466
- copy(source) {
3467
- super.copy(source);
3612
+ copyFrom(source) {
3613
+ super.copyFrom(source);
3468
3614
  this.x = source.x;
3469
3615
  this.y = source.y;
3470
3616
  this.width = source.width;
@@ -3502,8 +3648,8 @@ class RoundRectangleCurve extends RoundCurve {
3502
3648
  ctx.roundRect(x, y, width, height, radius);
3503
3649
  return this;
3504
3650
  }
3505
- copy(source) {
3506
- super.copy(source);
3651
+ copyFrom(source) {
3652
+ super.copyFrom(source);
3507
3653
  this.x = source.x;
3508
3654
  this.y = source.y;
3509
3655
  this.width = source.width;
@@ -3537,8 +3683,8 @@ class SplineCurve extends Curve {
3537
3683
  getControlPointRefs() {
3538
3684
  return this.points;
3539
3685
  }
3540
- copy(source) {
3541
- super.copy(source);
3686
+ copyFrom(source) {
3687
+ super.copyFrom(source);
3542
3688
  this.points = [];
3543
3689
  for (let i = 0, len = source.points.length; i < len; i++) {
3544
3690
  this.points.push(source.points[i].clone());
@@ -3621,7 +3767,7 @@ class CurvePath extends CompositeCurve {
3621
3767
  const end = this.currentPoint;
3622
3768
  if (end && !start.equals(end)) {
3623
3769
  this.curves.push(new LineCurve(end.clone(), start.clone()));
3624
- end.copy(start);
3770
+ end.copyFrom(start);
3625
3771
  }
3626
3772
  this.startPoint = void 0;
3627
3773
  }
@@ -3762,8 +3908,8 @@ class CurvePath extends CompositeCurve {
3762
3908
  }
3763
3909
  return this;
3764
3910
  }
3765
- copy(source) {
3766
- super.copy(source);
3911
+ copyFrom(source) {
3912
+ super.copyFrom(source);
3767
3913
  this.autoClose = source.autoClose;
3768
3914
  this.currentPoint = source.currentPoint?.clone();
3769
3915
  return this;
@@ -3957,8 +4103,8 @@ class Path2D extends CompositeCurve {
3957
4103
  pointsB[1] ?? pointsB[0]
3958
4104
  );
3959
4105
  if (point) {
3960
- pointsA[pointsA.length - 1].copy(point);
3961
- pointsB[0].copy(point);
4106
+ pointsA[pointsA.length - 1].copyFrom(point);
4107
+ pointsB[0].copyFrom(point);
3962
4108
  }
3963
4109
  });
3964
4110
  });
@@ -3989,8 +4135,8 @@ class Path2D extends CompositeCurve {
3989
4135
  point.clone().add({ x: -halfStrokeWidth, y: -halfStrokeWidth })
3990
4136
  );
3991
4137
  }
3992
- min.min(...points);
3993
- max.max(...points);
4138
+ min.clampMin(...points);
4139
+ max.clampMax(...points);
3994
4140
  }
3995
4141
  }
3996
4142
  });
@@ -4128,8 +4274,8 @@ class Path2D extends CompositeCurve {
4128
4274
  }
4129
4275
  return `<path d="${this.toData()}" style="${cssText}"></path>`;
4130
4276
  }
4131
- copy(source) {
4132
- super.copy(source);
4277
+ copyFrom(source) {
4278
+ super.copyFrom(source);
4133
4279
  this.currentCurve = source.currentCurve.clone();
4134
4280
  this.style = { ...source.style };
4135
4281
  return this;
@@ -4296,4 +4442,4 @@ function applyFFD(point, grid, width = grid.width, height = grid.height) {
4296
4442
  point.set(x, y);
4297
4443
  }
4298
4444
 
4299
- export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPloygonCurve, FFDControlGrid, LineCurve, Matrix3, Path2D, Path2DSet, PloygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parsePathDataArgs, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
4445
+ export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPloygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PloygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parsePathDataArgs, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };