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.cjs CHANGED
@@ -49,9 +49,10 @@ function setCanvasContext(ctx, style) {
49
49
  }
50
50
 
51
51
  class Vector2 {
52
- constructor(x = 0, y = 0) {
53
- this.x = x;
54
- this.y = y;
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
- get array() {
63
- return [this.x, this.y];
63
+ static lerp(a, b, t) {
64
+ return new Vector2(b.x, b.y).clone().sub(a).multiply(t).add(a);
64
65
  }
65
- finite() {
66
- this.x = Number.isFinite(this.x) ? this.x : 0;
67
- this.y = Number.isFinite(this.y) ? this.y : 0;
68
- return this;
66
+ get width() {
67
+ return this.x;
69
68
  }
70
- set(x, y) {
71
- this.x = x;
72
- this.y = y;
73
- return this;
69
+ set width(val) {
70
+ this.x = val;
74
71
  }
75
- add(vec) {
76
- this.x += vec.x;
77
- this.y += vec.y;
78
- return this;
72
+ get height() {
73
+ return this.y;
79
74
  }
80
- sub(vec) {
81
- this.x -= vec.x;
82
- this.y -= vec.y;
83
- return this;
75
+ set height(val) {
76
+ this.y = val;
84
77
  }
85
- multiply(vec) {
86
- this.x *= vec.x;
87
- this.y *= vec.y;
88
- return this;
78
+ get left() {
79
+ return this.x;
89
80
  }
90
- divide(vec) {
91
- this.x /= vec.x;
92
- this.y /= vec.y;
93
- return this;
81
+ set left(val) {
82
+ this.x = val;
94
83
  }
95
- dot(vec) {
96
- return this.x * vec.x + this.y * vec.y;
84
+ get top() {
85
+ return this.y;
97
86
  }
98
- cross(vec) {
99
- return this.x * vec.y - this.y * vec.x;
87
+ set top(val) {
88
+ this.y = val;
100
89
  }
101
- rotate(a, target = { x: 0, y: 0 }) {
102
- const rotation = -a / 180 * Math.PI;
103
- const x = this.x - target.x;
104
- const y = -(this.y - target.y);
105
- const sin = Math.sin(rotation);
106
- const cos = Math.cos(rotation);
107
- this.set(
108
- target.x + (x * cos - y * sin),
109
- target.y - (x * sin + y * cos)
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
- distanceTo(vec) {
114
- return Math.sqrt(this.distanceToSquared(vec));
116
+ add(p) {
117
+ return this.set(this._x + p.x, this._y + p.y);
115
118
  }
116
- distanceToSquared(vec) {
117
- const dx = this.x - vec.x;
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
- lengthSquared() {
122
- return this.x * this.x + this.y * this.y;
122
+ subVectors(a, b) {
123
+ return this.set(a.x - b.x, a.y - b.y);
123
124
  }
124
- length() {
125
- return Math.sqrt(this.lengthSquared());
125
+ multiply(x = 0, y = x) {
126
+ return this.set(this._x * x, this._y * y);
126
127
  }
127
- scale(sx, sy = sx, target = { x: 0, y: 0 }) {
128
- const x = sx < 0 ? target.x - this.x + target.x : this.x;
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
- skew(ax, ay = 0, target = { x: 0, y: 0 }) {
135
- const dx = this.x - target.x;
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
- min(...vecs) {
142
- this.x = Math.min(this.x, ...vecs.map((v) => v.x));
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
- max(...vecs) {
147
- this.x = Math.max(this.x, ...vecs.map((v) => v.x));
148
- this.y = Math.max(this.y, ...vecs.map((v) => v.y));
149
- return this;
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
- normalize() {
152
- return this.scale(1 / (this.length() || 1));
146
+ getLength() {
147
+ const { x, y } = this;
148
+ return Math.sqrt(x * x + y * y);
153
149
  }
154
- addVectors(a, b) {
155
- this.x = a.x + b.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
- subVectors(a, b) {
160
- this.x = a.x - b.x;
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
- multiplyVectors(a, b) {
165
- this.x = a.x * b.x;
166
- this.y = a.y * b.y;
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
- divideVectors(a, b) {
170
- this.x = a.x / b.x;
171
- this.y = a.y / b.y;
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
- lerpVectors(v1, v2, alpha) {
175
- this.x = v1.x + (v2.x - v1.x) * alpha;
176
- this.y = v1.y + (v2.y - v1.y) * alpha;
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.x === vec.x && this.y === vec.y;
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
- copy(vec) {
191
- this.x = vec.x;
192
- this.y = vec.y;
193
- return this;
176
+ get array() {
177
+ return [this.x, this.y];
194
178
  }
195
- clone() {
196
- return new Vector2(this.x, this.y);
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,202 +302,6 @@ class BoundingBox {
269
302
  }
270
303
  }
271
304
 
272
- class Matrix3 {
273
- elements = [];
274
- constructor(n11 = 1, n12 = 0, n13 = 0, n21 = 0, n22 = 1, n23 = 0, n31 = 0, n32 = 0, n33 = 1) {
275
- this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33);
276
- }
277
- set(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
278
- const te = this.elements;
279
- te[0] = n11;
280
- te[1] = n21;
281
- te[2] = n31;
282
- te[3] = n12;
283
- te[4] = n22;
284
- te[5] = n32;
285
- te[6] = n13;
286
- te[7] = n23;
287
- te[8] = n33;
288
- return this;
289
- }
290
- identity() {
291
- this.set(
292
- 1,
293
- 0,
294
- 0,
295
- 0,
296
- 1,
297
- 0,
298
- 0,
299
- 0,
300
- 1
301
- );
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
- }
412
- makeTranslation(x, y) {
413
- this.set(
414
- 1,
415
- 0,
416
- x,
417
- 0,
418
- 1,
419
- y,
420
- 0,
421
- 0,
422
- 1
423
- );
424
- return this;
425
- }
426
- makeRotation(theta) {
427
- const c = Math.cos(theta);
428
- const s = Math.sin(theta);
429
- this.set(
430
- c,
431
- -s,
432
- 0,
433
- s,
434
- c,
435
- 0,
436
- 0,
437
- 0,
438
- 1
439
- );
440
- return this;
441
- }
442
- makeScale(x, y) {
443
- this.set(
444
- x,
445
- 0,
446
- 0,
447
- 0,
448
- y,
449
- 0,
450
- 0,
451
- 0,
452
- 1
453
- );
454
- return this;
455
- }
456
- fromArray(array, offset = 0) {
457
- for (let i = 0; i < 9; i++) {
458
- this.elements[i] = array[i + offset];
459
- }
460
- return this;
461
- }
462
- clone() {
463
- return new this.constructor().fromArray(this.elements);
464
- }
465
- }
466
- const _m3 = /* @__PURE__ */ new Matrix3();
467
-
468
305
  function svgAngle(ux, uy, vx, vy) {
469
306
  const dot = ux * vx + uy * vy;
470
307
  const len = Math.sqrt(ux * ux + uy * uy) * Math.sqrt(vx * vx + vy * vy);
@@ -657,10 +494,10 @@ function svgPathCommandsAddToPath2D(commands, path) {
657
494
  if (cmd.type === "m") {
658
495
  current.add(cmd);
659
496
  } else {
660
- current.copy(cmd);
497
+ current.copyFrom(cmd);
661
498
  }
662
499
  path.moveTo(current.x, current.y);
663
- control.copy(current);
500
+ control.copyFrom(current);
664
501
  } else if (cmd.type === "h" || cmd.type === "H") {
665
502
  if (cmd.type === "h") {
666
503
  current.x += cmd.x;
@@ -668,7 +505,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
668
505
  current.x = cmd.x;
669
506
  }
670
507
  path.lineTo(current.x, current.y);
671
- control.copy(current);
508
+ control.copyFrom(current);
672
509
  } else if (cmd.type === "v" || cmd.type === "V") {
673
510
  if (cmd.type === "v") {
674
511
  current.y += cmd.y;
@@ -676,15 +513,15 @@ function svgPathCommandsAddToPath2D(commands, path) {
676
513
  current.y = cmd.y;
677
514
  }
678
515
  path.lineTo(current.x, current.y);
679
- control.copy(current);
516
+ control.copyFrom(current);
680
517
  } else if (cmd.type === "l" || cmd.type === "L") {
681
518
  if (cmd.type === "l") {
682
519
  current.add(cmd);
683
520
  } else {
684
- current.copy(cmd);
521
+ current.copyFrom(cmd);
685
522
  }
686
523
  path.lineTo(current.x, current.y);
687
- control.copy(current);
524
+ control.copyFrom(current);
688
525
  } else if (cmd.type === "c" || cmd.type === "C") {
689
526
  if (cmd.type === "c") {
690
527
  path.bezierCurveTo(
@@ -709,7 +546,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
709
546
  );
710
547
  control.x = cmd.x2;
711
548
  control.y = cmd.y2;
712
- current.copy(cmd);
549
+ current.copyFrom(cmd);
713
550
  }
714
551
  } else if (cmd.type === "s" || cmd.type === "S") {
715
552
  if (cmd.type === "s") {
@@ -735,7 +572,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
735
572
  );
736
573
  control.x = cmd.x2;
737
574
  control.y = cmd.y2;
738
- current.copy(cmd);
575
+ current.copyFrom(cmd);
739
576
  }
740
577
  } else if (cmd.type === "q" || cmd.type === "Q") {
741
578
  if (cmd.type === "q") {
@@ -757,7 +594,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
757
594
  );
758
595
  control.x = cmd.x1;
759
596
  control.y = cmd.y1;
760
- current.copy(cmd);
597
+ current.copyFrom(cmd);
761
598
  }
762
599
  } else if (cmd.type === "t" || cmd.type === "T") {
763
600
  const rx = getReflection(current.x, control.x);
@@ -779,7 +616,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
779
616
  cmd.x,
780
617
  cmd.y
781
618
  );
782
- current.copy(cmd);
619
+ current.copyFrom(cmd);
783
620
  }
784
621
  } else if (cmd.type === "a" || cmd.type === "A") {
785
622
  const start = current.clone();
@@ -790,9 +627,9 @@ function svgPathCommandsAddToPath2D(commands, path) {
790
627
  } else {
791
628
  if (current.equals(cmd))
792
629
  continue;
793
- current.copy(cmd);
630
+ current.copyFrom(cmd);
794
631
  }
795
- control.copy(current);
632
+ control.copyFrom(current);
796
633
  parseArcCommand(
797
634
  path,
798
635
  cmd.rx,
@@ -805,7 +642,7 @@ function svgPathCommandsAddToPath2D(commands, path) {
805
642
  );
806
643
  } else if (cmd.type === "z" || cmd.type === "Z") {
807
644
  if (path.startPoint) {
808
- current.copy(path.startPoint);
645
+ current.copyFrom(path.startPoint);
809
646
  }
810
647
  path.closePath();
811
648
  } else {
@@ -1105,25 +942,20 @@ function parseFloatWithUnits(string) {
1105
942
  return scale * Number.parseFloat(string);
1106
943
  }
1107
944
 
1108
- const tempTransform0$1 = new Matrix3();
1109
- const tempTransform1$1 = new Matrix3();
1110
- const tempTransform2$1 = new Matrix3();
1111
- const tempTransform3 = new Matrix3();
1112
945
  function getNodeTransform(node, currentTransform, transformStack) {
1113
946
  if (!(node.hasAttribute("transform") || node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y")))) {
1114
947
  return null;
1115
948
  }
1116
949
  const transform = parseNodeTransform(node);
1117
950
  if (transformStack.length > 0) {
1118
- transform.premultiply(transformStack[transformStack.length - 1]);
951
+ transform.prepend(transformStack[transformStack.length - 1]);
1119
952
  }
1120
- currentTransform.copy(transform);
953
+ currentTransform.copyFrom(transform);
1121
954
  transformStack.push(transform);
1122
955
  return transform;
1123
956
  }
1124
957
  function parseNodeTransform(node) {
1125
- const transform = new Matrix3();
1126
- const currentTransform = tempTransform0$1;
958
+ const transform = new Transform2D();
1127
959
  if (node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y"))) {
1128
960
  transform.translate(
1129
961
  parseFloatWithUnits(node.getAttribute("x")),
@@ -1131,102 +963,7 @@ function parseNodeTransform(node) {
1131
963
  );
1132
964
  }
1133
965
  if (node.hasAttribute("transform")) {
1134
- const transformsTexts = node.getAttribute("transform").split(")");
1135
- for (let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex--) {
1136
- const transformText = transformsTexts[tIndex].trim();
1137
- if (transformText === "")
1138
- continue;
1139
- const openParPos = transformText.indexOf("(");
1140
- const closeParPos = transformText.length;
1141
- if (openParPos > 0 && openParPos < closeParPos) {
1142
- const transformType = transformText.slice(0, openParPos);
1143
- const array = parsePathDataArgs(transformText.slice(openParPos + 1));
1144
- currentTransform.identity();
1145
- switch (transformType) {
1146
- case "translate":
1147
- if (array.length >= 1) {
1148
- const tx = array[0];
1149
- let ty = 0;
1150
- if (array.length >= 2) {
1151
- ty = array[1];
1152
- }
1153
- currentTransform.translate(tx, ty);
1154
- }
1155
- break;
1156
- case "rotate":
1157
- if (array.length >= 1) {
1158
- let angle = 0;
1159
- let cx = 0;
1160
- let cy = 0;
1161
- angle = array[0] * Math.PI / 180;
1162
- if (array.length >= 3) {
1163
- cx = array[1];
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;
1226
- }
1227
- }
1228
- transform.premultiply(currentTransform);
1229
- }
966
+ transform.appendCssTransform(node.getAttribute("transform"));
1230
967
  }
1231
968
  return transform;
1232
969
  }
@@ -1503,7 +1240,7 @@ function parseNode(node, style, paths = [], stylesheets = {}) {
1503
1240
  if (_style.display === "none") {
1504
1241
  return paths;
1505
1242
  }
1506
- const currentTransform = new Matrix3();
1243
+ const currentTransform = new Transform2D();
1507
1244
  const transformStack = [];
1508
1245
  const transform = getNodeTransform(node, currentTransform, transformStack);
1509
1246
  if (path) {
@@ -1521,7 +1258,7 @@ function parseNode(node, style, paths = [], stylesheets = {}) {
1521
1258
  if (transform) {
1522
1259
  transformStack.pop();
1523
1260
  if (transformStack.length > 0) {
1524
- currentTransform.copy(transformStack[transformStack.length - 1]);
1261
+ currentTransform.copyFrom(transformStack[transformStack.length - 1]);
1525
1262
  } else {
1526
1263
  currentTransform.identity();
1527
1264
  }
@@ -1537,6 +1274,440 @@ function svgToPath2DSet(svg) {
1537
1274
  );
1538
1275
  }
1539
1276
 
1277
+ const PI = Math.PI;
1278
+ const PI_2 = PI * 2;
1279
+
1280
+ class Transform2D {
1281
+ constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
1282
+ this.a = a;
1283
+ this.b = b;
1284
+ this.c = c;
1285
+ this.d = d;
1286
+ this.tx = tx;
1287
+ this.ty = ty;
1288
+ }
1289
+ _array;
1290
+ set(a, b, c, d, tx, ty) {
1291
+ this.a = a;
1292
+ this.b = b;
1293
+ this.c = c;
1294
+ this.d = d;
1295
+ this.tx = tx;
1296
+ this.ty = ty;
1297
+ return this;
1298
+ }
1299
+ append(t2d) {
1300
+ const a1 = this.a;
1301
+ const b1 = this.b;
1302
+ const c1 = this.c;
1303
+ const d1 = this.d;
1304
+ this.a = t2d.a * a1 + t2d.b * c1;
1305
+ this.b = t2d.a * b1 + t2d.b * d1;
1306
+ this.c = t2d.c * a1 + t2d.d * c1;
1307
+ this.d = t2d.c * b1 + t2d.d * d1;
1308
+ this.tx = t2d.tx * a1 + t2d.ty * c1 + this.tx;
1309
+ this.ty = t2d.tx * b1 + t2d.ty * d1 + this.ty;
1310
+ return this;
1311
+ }
1312
+ appendFrom(a, b) {
1313
+ const a1 = a.a;
1314
+ const b1 = a.b;
1315
+ const c1 = a.c;
1316
+ const d1 = a.d;
1317
+ const tx = a.tx;
1318
+ const ty = a.ty;
1319
+ const a2 = b.a;
1320
+ const b2 = b.b;
1321
+ const c2 = b.c;
1322
+ const d2 = b.d;
1323
+ this.a = a1 * a2 + b1 * c2;
1324
+ this.b = a1 * b2 + b1 * d2;
1325
+ this.c = c1 * a2 + d1 * c2;
1326
+ this.d = c1 * b2 + d1 * d2;
1327
+ this.tx = tx * a2 + ty * c2 + b.tx;
1328
+ this.ty = tx * b2 + ty * d2 + b.ty;
1329
+ return this;
1330
+ }
1331
+ setTransform(x, y, pivotX, pivotY, scaleX, scaleY, rotation, skewX, skewY) {
1332
+ this.a = Math.cos(rotation + skewY) * scaleX;
1333
+ this.b = Math.sin(rotation + skewY) * scaleX;
1334
+ this.c = -Math.sin(rotation - skewX) * scaleY;
1335
+ this.d = Math.cos(rotation - skewX) * scaleY;
1336
+ this.tx = x - (pivotX * this.a + pivotY * this.c);
1337
+ this.ty = y - (pivotX * this.b + pivotY * this.d);
1338
+ return this;
1339
+ }
1340
+ prepend(t2d) {
1341
+ const tx1 = this.tx;
1342
+ if (t2d.a !== 1 || t2d.b !== 0 || t2d.c !== 0 || t2d.d !== 1) {
1343
+ const a1 = this.a;
1344
+ const c1 = this.c;
1345
+ this.a = a1 * t2d.a + this.b * t2d.c;
1346
+ this.b = a1 * t2d.b + this.b * t2d.d;
1347
+ this.c = c1 * t2d.a + this.d * t2d.c;
1348
+ this.d = c1 * t2d.b + this.d * t2d.d;
1349
+ }
1350
+ this.tx = tx1 * t2d.a + this.ty * t2d.c + t2d.tx;
1351
+ this.ty = tx1 * t2d.b + this.ty * t2d.d + t2d.ty;
1352
+ return this;
1353
+ }
1354
+ _skewX;
1355
+ _skewY;
1356
+ _skewXTan = 1;
1357
+ _skewYTan = 1;
1358
+ skewX(x) {
1359
+ return this.skew(x, 0);
1360
+ }
1361
+ skewY(y) {
1362
+ return this.skew(0, y);
1363
+ }
1364
+ skew(x, y) {
1365
+ if (x !== this._skewX) {
1366
+ this._skewX = x;
1367
+ this._skewXTan = Math.tan(x);
1368
+ }
1369
+ if (y !== this._skewY) {
1370
+ this._skewY = y;
1371
+ this._skewYTan = Math.tan(y);
1372
+ }
1373
+ this.b *= this._skewXTan;
1374
+ this.c *= this._skewYTan;
1375
+ return this;
1376
+ }
1377
+ translateX(x) {
1378
+ return this.translate(x, 0);
1379
+ }
1380
+ translateY(y) {
1381
+ return this.translate(0, y);
1382
+ }
1383
+ translateZ(z) {
1384
+ return this.translate(0, 0, z);
1385
+ }
1386
+ translate3d(x, y, z) {
1387
+ return this.translate(x, y, z);
1388
+ }
1389
+ translate(x, y, _z = 0) {
1390
+ this.tx += x;
1391
+ this.ty += y;
1392
+ return this;
1393
+ }
1394
+ scaleX(x) {
1395
+ return this.scale(x, 1);
1396
+ }
1397
+ scaleY(y) {
1398
+ return this.scale(1, y);
1399
+ }
1400
+ scale3d(x, y, z = 1) {
1401
+ return this.scale(x, y, z);
1402
+ }
1403
+ scale(x, y, _z = 1) {
1404
+ this.a *= x;
1405
+ this.d *= y;
1406
+ this.c *= x;
1407
+ this.b *= y;
1408
+ this.tx *= x;
1409
+ this.ty *= y;
1410
+ return this;
1411
+ }
1412
+ rotateX(x) {
1413
+ return this.scaleY(this._rotateToScale(x));
1414
+ }
1415
+ rotateY(y) {
1416
+ return this.scaleX(this._rotateToScale(y));
1417
+ }
1418
+ rotateZ(z) {
1419
+ return this.rotate(z);
1420
+ }
1421
+ rotate(angle) {
1422
+ const cos = Math.cos(angle);
1423
+ const sin = Math.sin(angle);
1424
+ const a1 = this.a;
1425
+ const c1 = this.c;
1426
+ const tx1 = this.tx;
1427
+ this.a = a1 * cos - this.b * sin;
1428
+ this.b = a1 * sin + this.b * cos;
1429
+ this.c = c1 * cos - this.d * sin;
1430
+ this.d = c1 * sin + this.d * cos;
1431
+ this.tx = tx1 * cos - this.ty * sin;
1432
+ this.ty = tx1 * sin + this.ty * cos;
1433
+ return this;
1434
+ }
1435
+ rotate3d(x, y, z, rad) {
1436
+ const [rx, ry, rz] = this._rotate3d(x, y, z, rad);
1437
+ rx && this.rotateX(rx);
1438
+ ry && this.rotateY(ry);
1439
+ rz && this.rotateZ(rz);
1440
+ return this;
1441
+ }
1442
+ _rotateToScale(rad) {
1443
+ const val = rad / PI_2;
1444
+ return val <= 0.5 ? val * -4 + 1 : (val - 1) * 4 + 1;
1445
+ }
1446
+ _rotate3d(x, y, z, rad) {
1447
+ if (x === 1 && y === 0 && z === 0) {
1448
+ return [rad, 0, 0];
1449
+ } else if (x === 0 && y === 1 && z === 0) {
1450
+ return [0, rad, 0];
1451
+ } else if (x === 0 && y === 0) {
1452
+ return [0, 0, rad];
1453
+ } else {
1454
+ const cos = Math.cos(rad);
1455
+ const sin = Math.sin(rad);
1456
+ const m11 = cos + x * x * (1 - cos);
1457
+ const m12 = x * y * (1 - cos) - z * sin;
1458
+ const m13 = x * z * (1 - cos) + y * sin;
1459
+ const m22 = cos + y * y * (1 - cos);
1460
+ const m23 = y * z * (1 - cos) - x * sin;
1461
+ const m33 = cos + z * z * (1 - cos);
1462
+ const rotateX = -Math.atan2(-m23, m22);
1463
+ const rotateY = -Math.atan2(m13, Math.sqrt(m23 * m23 + m33 * m33));
1464
+ const rotateZ = -Math.atan2(-m12, m11);
1465
+ return [rotateX, rotateY, rotateZ];
1466
+ }
1467
+ }
1468
+ decompose(pivot = { x: 0, y: 0 }, output = {
1469
+ position: { x: 0, y: 0 },
1470
+ scale: { x: 0, y: 0 },
1471
+ skew: { x: 0, y: 0 },
1472
+ rotation: 0
1473
+ }) {
1474
+ const { a, b, c, d, tx, ty } = this;
1475
+ const skewX = -Math.atan2(-c, d);
1476
+ const skewY = Math.atan2(b, a);
1477
+ const delta = Math.abs(skewX + skewY);
1478
+ if (delta < 1e-5 || Math.abs(PI_2 - delta) < 1e-5) {
1479
+ output.rotation = skewY;
1480
+ output.skew.x = output.skew.y = 0;
1481
+ } else {
1482
+ output.rotation = 0;
1483
+ output.skew.x = skewX;
1484
+ output.skew.y = skewY;
1485
+ }
1486
+ output.scale.x = Math.sqrt(a * a + b * b);
1487
+ output.scale.y = Math.sqrt(c * c + d * d);
1488
+ output.position.x = tx + (pivot.x * a + pivot.y * c);
1489
+ output.position.y = ty + (pivot.x * b + pivot.y * d);
1490
+ return output;
1491
+ }
1492
+ apply(pos, newPos) {
1493
+ newPos = newPos || new Vector2();
1494
+ const { x, y } = pos;
1495
+ newPos.x = this.a * x + this.c * y + this.tx;
1496
+ newPos.y = this.b * x + this.d * y + this.ty;
1497
+ return newPos;
1498
+ }
1499
+ affineInvert() {
1500
+ const a1 = this.a;
1501
+ const b1 = this.b;
1502
+ const c1 = this.c;
1503
+ const d1 = this.d;
1504
+ const tx1 = this.tx;
1505
+ const n = a1 * d1 - b1 * c1;
1506
+ this.a = d1 / n;
1507
+ this.b = -b1 / n;
1508
+ this.c = -c1 / n;
1509
+ this.d = a1 / n;
1510
+ this.tx = (c1 * this.ty - d1 * tx1) / n;
1511
+ this.ty = -(a1 * this.ty - b1 * tx1) / n;
1512
+ return this;
1513
+ }
1514
+ affineInverse() {
1515
+ return this.clone().affineInvert();
1516
+ }
1517
+ applyAffineInverse(pos, newPos) {
1518
+ newPos = newPos || new Vector2();
1519
+ const { a, b, c, d, tx, ty } = this;
1520
+ const id = 1 / (a * d + c * -b);
1521
+ const x = pos.x;
1522
+ const y = pos.y;
1523
+ newPos.x = d * id * x + -c * id * y + (ty * c - tx * d) * id;
1524
+ newPos.y = a * id * y + -b * id * x + (-ty * a + tx * b) * id;
1525
+ return newPos;
1526
+ }
1527
+ identity() {
1528
+ this.a = 1;
1529
+ this.b = 0;
1530
+ this.c = 0;
1531
+ this.d = 1;
1532
+ this.tx = 0;
1533
+ this.ty = 0;
1534
+ return this;
1535
+ }
1536
+ isIdentity() {
1537
+ const { a, b, c, d, tx, ty } = this;
1538
+ return a === 1 && b === 0 && c === 0 && d === 1 && tx === 0 && ty === 0;
1539
+ }
1540
+ copyTo(t2d) {
1541
+ t2d.a = this.a;
1542
+ t2d.b = this.b;
1543
+ t2d.c = this.c;
1544
+ t2d.d = this.d;
1545
+ t2d.tx = this.tx;
1546
+ t2d.ty = this.ty;
1547
+ return t2d;
1548
+ }
1549
+ copyFrom(t2d) {
1550
+ this.a = t2d.a;
1551
+ this.b = t2d.b;
1552
+ this.c = t2d.c;
1553
+ this.d = t2d.d;
1554
+ this.tx = t2d.tx;
1555
+ this.ty = t2d.ty;
1556
+ return this;
1557
+ }
1558
+ equals(t2d) {
1559
+ 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;
1560
+ }
1561
+ appendCssTransform(cssTransform) {
1562
+ const transformsTexts = cssTransform.split(")");
1563
+ const transform = new Transform2D();
1564
+ for (let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex--) {
1565
+ const transformText = transformsTexts[tIndex].trim();
1566
+ if (transformText === "")
1567
+ continue;
1568
+ const openParPos = transformText.indexOf("(");
1569
+ const closeParPos = transformText.length;
1570
+ if (openParPos > 0 && openParPos < closeParPos) {
1571
+ const transformType = transformText.slice(0, openParPos);
1572
+ const array = parsePathDataArgs(transformText.slice(openParPos + 1));
1573
+ transform.identity();
1574
+ switch (transformType) {
1575
+ case "translateX":
1576
+ transform.translateX(array[0]);
1577
+ break;
1578
+ case "translateY":
1579
+ transform.translateY(array[0]);
1580
+ break;
1581
+ case "translateZ":
1582
+ transform.translateZ(array[0]);
1583
+ break;
1584
+ case "translate":
1585
+ transform.translate(
1586
+ array[0],
1587
+ array[1] ?? array[0]
1588
+ );
1589
+ break;
1590
+ case "translate3d":
1591
+ transform.translate3d(
1592
+ array[0],
1593
+ array[1] ?? array[0],
1594
+ array[2] ?? array[1] ?? array[0]
1595
+ );
1596
+ break;
1597
+ case "scaleX":
1598
+ transform.scaleX(array[0]);
1599
+ break;
1600
+ case "scaleY":
1601
+ transform.scaleY(array[0]);
1602
+ break;
1603
+ case "scale":
1604
+ transform.scale(
1605
+ array[0],
1606
+ array[1] ?? array[0]
1607
+ );
1608
+ break;
1609
+ case "scale3d":
1610
+ transform.scale3d(
1611
+ array[0],
1612
+ array[1] ?? array[0],
1613
+ array[2] ?? array[1] ?? array[0]
1614
+ );
1615
+ break;
1616
+ case "rotate": {
1617
+ const rad = array[0] * Math.PI / 180;
1618
+ if (array.length >= 3) {
1619
+ const cx = array[1];
1620
+ const cy = array[2];
1621
+ transform.translate(-cx, -cy).rotate(rad).translate(cx, cy);
1622
+ } else {
1623
+ transform.rotate(rad);
1624
+ }
1625
+ break;
1626
+ }
1627
+ case "rotateX":
1628
+ transform.rotateX(array[0] * Math.PI / 180);
1629
+ break;
1630
+ case "rotateY":
1631
+ transform.rotateY(array[0] * Math.PI / 180);
1632
+ break;
1633
+ case "rotateZ":
1634
+ transform.rotateZ(array[0] * Math.PI / 180);
1635
+ break;
1636
+ case "rotate3d":
1637
+ transform.rotate3d(
1638
+ array[0] * Math.PI / 180,
1639
+ (array[1] ?? array[0]) * Math.PI / 180,
1640
+ (array[2] ?? array[1] ?? array[0]) * Math.PI / 180,
1641
+ (array[3] ?? array[2] ?? array[1] ?? array[0]) * Math.PI / 180
1642
+ );
1643
+ break;
1644
+ case "skewX":
1645
+ transform.set(1, 0, Math.tan(array[0] * Math.PI / 180), 1, 0, 0);
1646
+ break;
1647
+ case "skewY":
1648
+ transform.set(1, Math.tan(array[0] * Math.PI / 180), 0, 1, 0, 0);
1649
+ break;
1650
+ case "skew": {
1651
+ const ax = array[0];
1652
+ const ay = array[1] ?? 0;
1653
+ transform.set(1, Math.tan(ay * Math.PI / 180), Math.tan(ax * Math.PI / 180), 1, 0, 0);
1654
+ break;
1655
+ }
1656
+ case "matrix":
1657
+ transform.set(
1658
+ array[0],
1659
+ array[1],
1660
+ array[2],
1661
+ array[3],
1662
+ array[4],
1663
+ array[5]
1664
+ );
1665
+ break;
1666
+ }
1667
+ }
1668
+ this.prepend(transform);
1669
+ }
1670
+ return this;
1671
+ }
1672
+ clone() {
1673
+ return new Transform2D(this.a, this.b, this.c, this.d, this.tx, this.ty);
1674
+ }
1675
+ toArray(transpose, out) {
1676
+ if (!this._array) {
1677
+ this._array = new Float32Array(9);
1678
+ }
1679
+ const array = out || this._array;
1680
+ if (transpose) {
1681
+ array[0] = this.a;
1682
+ array[1] = this.b;
1683
+ array[2] = 0;
1684
+ array[3] = this.c;
1685
+ array[4] = this.d;
1686
+ array[5] = 0;
1687
+ array[6] = this.tx;
1688
+ array[7] = this.ty;
1689
+ array[8] = 1;
1690
+ } else {
1691
+ array[0] = this.a;
1692
+ array[1] = this.c;
1693
+ array[2] = this.tx;
1694
+ array[3] = this.b;
1695
+ array[4] = this.d;
1696
+ array[5] = this.ty;
1697
+ array[6] = 0;
1698
+ array[7] = 0;
1699
+ array[8] = 1;
1700
+ }
1701
+ return array;
1702
+ }
1703
+ toString() {
1704
+ return `[Transform2D a=${this.a} b=${this.b} c=${this.c} d=${this.d} tx=${this.tx} ty=${this.ty}]`;
1705
+ }
1706
+ destroy() {
1707
+ this._array = void 0;
1708
+ }
1709
+ }
1710
+
1540
1711
  function catmullRom(t, p0, p1, p2, p3) {
1541
1712
  const v0 = (p2 - p0) * 0.5;
1542
1713
  const v1 = (p3 - p1) * 0.5;
@@ -2300,7 +2471,7 @@ class Curve {
2300
2471
  if (isFunction) {
2301
2472
  transform(p);
2302
2473
  } else {
2303
- p.applyMatrix3(transform);
2474
+ transform.apply(p, p);
2304
2475
  }
2305
2476
  });
2306
2477
  return this;
@@ -2415,7 +2586,7 @@ class Curve {
2415
2586
  const delta = 1e-4;
2416
2587
  const t1 = Math.max(0, t - delta);
2417
2588
  const t2 = Math.min(1, t + delta);
2418
- return output.copy(this.getPoint(t2).sub(this.getPoint(t1)).normalize());
2589
+ return output.copyFrom(this.getPoint(t2).sub(this.getPoint(t1)).normalize());
2419
2590
  }
2420
2591
  getTangentAt(u, output) {
2421
2592
  return this.getTangent(this.getUToTMapping(u), output);
@@ -2450,8 +2621,8 @@ class Curve {
2450
2621
  const potins = this.getPoints();
2451
2622
  for (let i = 0, len = potins.length; i < len; i++) {
2452
2623
  const p = potins[i];
2453
- min.min(p);
2454
- max.max(p);
2624
+ min.clampMin(p);
2625
+ max.clampMax(p);
2455
2626
  }
2456
2627
  return { min: min.finite(), max: max.finite() };
2457
2628
  }
@@ -2503,18 +2674,18 @@ class Curve {
2503
2674
  });
2504
2675
  return this;
2505
2676
  }
2506
- copy(source) {
2677
+ copyFrom(source) {
2507
2678
  this.arcLengthDivision = source.arcLengthDivision;
2508
2679
  return this;
2509
2680
  }
2510
2681
  clone() {
2511
- return new this.constructor().copy(this);
2682
+ return new this.constructor().copyFrom(this);
2512
2683
  }
2513
2684
  }
2514
2685
 
2515
- const tempTransform0 = new Matrix3();
2516
- const tempTransform1 = new Matrix3();
2517
- const tempTransform2 = new Matrix3();
2686
+ const tempTransform0 = new Transform2D();
2687
+ const tempTransform1 = new Transform2D();
2688
+ const tempTransform2 = new Transform2D();
2518
2689
  const tempV2 = new Vector2();
2519
2690
  class RoundCurve extends Curve {
2520
2691
  constructor(_center = new Vector2(), _radius = new Vector2(), _diff = new Vector2(), rotate = 0, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
@@ -2633,15 +2804,15 @@ class RoundCurve extends Curve {
2633
2804
  );
2634
2805
  return this;
2635
2806
  }
2636
- applyTransform(matrix) {
2807
+ applyTransform(transform) {
2637
2808
  tempV2.set(this.cx, this.cy);
2638
- tempV2.applyMatrix3(matrix);
2809
+ transform.apply(tempV2, tempV2);
2639
2810
  this.cx = tempV2.x;
2640
2811
  this.cy = tempV2.y;
2641
- if (isTransformSkewed(matrix)) {
2642
- transfEllipseGeneric(this, matrix);
2812
+ if (isTransformSkewed(transform)) {
2813
+ transfEllipseGeneric(this, transform);
2643
2814
  } else {
2644
- transfEllipseNoSkew(this, matrix);
2815
+ transfEllipseNoSkew(this, transform);
2645
2816
  }
2646
2817
  return this;
2647
2818
  }
@@ -2768,8 +2939,8 @@ class RoundCurve extends Curve {
2768
2939
  }
2769
2940
  return this._getAdaptiveVerticesByArc(output);
2770
2941
  }
2771
- copy(source) {
2772
- super.copy(source);
2942
+ copyFrom(source) {
2943
+ super.copyFrom(source);
2773
2944
  this.cx = source.cx;
2774
2945
  this.cy = source.cy;
2775
2946
  this.rx = source.rx;
@@ -2790,24 +2961,17 @@ function transfEllipseGeneric(curve, m) {
2790
2961
  const sinTheta = Math.sin(curve.rotate);
2791
2962
  const v1 = new Vector2(a * cosTheta, a * sinTheta);
2792
2963
  const v2 = new Vector2(-b * sinTheta, b * cosTheta);
2793
- const f1 = v1.applyMatrix3(m);
2794
- const f2 = v2.applyMatrix3(m);
2795
- const mF = tempTransform0.set(
2796
- f1.x,
2797
- f2.x,
2798
- 0,
2799
- f1.y,
2800
- f2.y,
2801
- 0,
2802
- 0,
2803
- 0,
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]);
2964
+ const f1x = m.a * v1.x + m.c * v1.y;
2965
+ const f1y = m.b * v1.x + m.d * v1.y;
2966
+ const f2x = m.a * v2.x + m.c * v2.y;
2967
+ const f2y = m.b * v2.x + m.d * v2.y;
2968
+ const mF = tempTransform0.set(f1x, f1y, f2x, f2y, 0, 0);
2969
+ const mFInv = tempTransform1.copyFrom(mF).affineInvert();
2970
+ const { a: ia, b: ib, c: ic, d: id } = mFInv;
2971
+ const qA = ia * ia + ib * ib;
2972
+ const qB = ic * ia + id * ib;
2973
+ const qD = ic * ic + id * id;
2974
+ const ed = eigenDecomposition(qA, qB, qD);
2811
2975
  const rt1sqrt = Math.sqrt(ed.rt1);
2812
2976
  const rt2sqrt = Math.sqrt(ed.rt2);
2813
2977
  curve.rx = 1 / rt1sqrt;
@@ -2819,27 +2983,21 @@ function transfEllipseGeneric(curve, m) {
2819
2983
  rt1sqrt,
2820
2984
  0,
2821
2985
  0,
2822
- 0,
2823
2986
  rt2sqrt,
2824
2987
  0,
2825
- 0,
2826
- 0,
2827
- 1
2988
+ 0
2828
2989
  );
2829
2990
  const mRT = tempTransform2.set(
2830
2991
  ed.cs,
2831
2992
  ed.sn,
2832
- 0,
2833
2993
  -ed.sn,
2834
2994
  ed.cs,
2835
2995
  0,
2836
- 0,
2837
- 0,
2838
- 1
2996
+ 0
2839
2997
  );
2840
- const mDRF = mDsqrt.multiply(mRT).multiply(mF);
2998
+ const mDRF = mDsqrt.append(mRT).append(mF);
2841
2999
  const transformAngle = (phi) => {
2842
- const { x: cosR, y: sinR } = new Vector2(Math.cos(phi), Math.sin(phi)).applyMatrix3(mDRF);
3000
+ const { x: cosR, y: sinR } = mDRF.apply({ x: Math.cos(phi), y: Math.sin(phi) });
2843
3001
  return Math.atan2(sinR, cosR);
2844
3002
  };
2845
3003
  curve.startAngle = transformAngle(curve.startAngle);
@@ -2850,11 +3008,10 @@ function transfEllipseGeneric(curve, m) {
2850
3008
  }
2851
3009
  }
2852
3010
  function transfEllipseNoSkew(curve, m) {
2853
- const sx = getTransformScaleX(m);
2854
- const sy = getTransformScaleY(m);
2855
- curve.rx *= sx;
2856
- curve.ry *= sy;
2857
- const theta = sx > Number.EPSILON ? Math.atan2(m.elements[1], m.elements[0]) : Math.atan2(-m.elements[3], m.elements[4]);
3011
+ const { scale } = m.decompose();
3012
+ curve.rx *= scale.x;
3013
+ curve.ry *= scale.y;
3014
+ const theta = scale.x > Number.EPSILON ? Math.atan2(m.b, m.a) : Math.atan2(-m.c, m.d);
2858
3015
  curve.rotate += theta;
2859
3016
  if (isTransformFlipped(m)) {
2860
3017
  curve.startAngle *= -1;
@@ -2863,25 +3020,14 @@ function transfEllipseNoSkew(curve, m) {
2863
3020
  }
2864
3021
  }
2865
3022
  function isTransformFlipped(m) {
2866
- const te = m.elements;
2867
- return te[0] * te[4] - te[1] * te[3] < 0;
3023
+ return m.a * m.d - m.c * m.b < 0;
2868
3024
  }
2869
3025
  function isTransformSkewed(m) {
2870
- const te = m.elements;
2871
- const basisDot = te[0] * te[3] + te[1] * te[4];
3026
+ const basisDot = m.a * m.c + m.b * m.d;
2872
3027
  if (basisDot === 0)
2873
3028
  return false;
2874
- const sx = getTransformScaleX(m);
2875
- const sy = getTransformScaleY(m);
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]);
3029
+ const { scale } = m.decompose();
3030
+ return Math.abs(basisDot / (scale.x * scale.y)) > Number.EPSILON;
2885
3031
  }
2886
3032
  function eigenDecomposition(A, B, C) {
2887
3033
  let rt1, rt2, cs, sn, t;
@@ -2963,9 +3109,9 @@ class LineCurve extends Curve {
2963
3109
  }
2964
3110
  getPoint(t, output = new Vector2()) {
2965
3111
  if (t === 1) {
2966
- output.copy(this.p2);
3112
+ output.copyFrom(this.p2);
2967
3113
  } else {
2968
- output.copy(this.p2).sub(this.p1).scale(t).add(this.p1);
3114
+ output.copyFrom(this.p2).sub(this.p1).scale(t).add(this.p1);
2969
3115
  }
2970
3116
  return output;
2971
3117
  }
@@ -3031,10 +3177,10 @@ class LineCurve extends Curve {
3031
3177
  ctx.lineTo(p2.x, p2.y);
3032
3178
  return this;
3033
3179
  }
3034
- copy(source) {
3035
- super.copy(source);
3036
- this.p1.copy(source.p1);
3037
- this.p2.copy(source.p2);
3180
+ copyFrom(source) {
3181
+ super.copyFrom(source);
3182
+ this.p1.copyFrom(source.p1);
3183
+ this.p2.copyFrom(source.p2);
3038
3184
  return this;
3039
3185
  }
3040
3186
  }
@@ -3173,8 +3319,8 @@ class CompositeCurve extends Curve {
3173
3319
  this.curves.forEach((curve) => curve.drawTo(ctx));
3174
3320
  return this;
3175
3321
  }
3176
- copy(source) {
3177
- super.copy(source);
3322
+ copyFrom(source) {
3323
+ super.copyFrom(source);
3178
3324
  this.curves = source.curves.map((curve) => curve.clone());
3179
3325
  return this;
3180
3326
  }
@@ -3271,12 +3417,12 @@ class CubicBezierCurve extends Curve {
3271
3417
  ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y);
3272
3418
  return this;
3273
3419
  }
3274
- copy(source) {
3275
- super.copy(source);
3276
- this.p1.copy(source.p1);
3277
- this.cp1.copy(source.cp1);
3278
- this.cp2.copy(source.cp2);
3279
- this.p2.copy(source.p2);
3420
+ copyFrom(source) {
3421
+ super.copyFrom(source);
3422
+ this.p1.copyFrom(source.p1);
3423
+ this.cp1.copyFrom(source.cp1);
3424
+ this.cp2.copyFrom(source.cp2);
3425
+ this.p2.copyFrom(source.p2);
3280
3426
  return this;
3281
3427
  }
3282
3428
  }
@@ -3345,8 +3491,8 @@ class EquilateralPloygonCurve extends PloygonCurve {
3345
3491
  this.curves = curves;
3346
3492
  return this;
3347
3493
  }
3348
- copy(source) {
3349
- super.copy(source);
3494
+ copyFrom(source) {
3495
+ super.copyFrom(source);
3350
3496
  this.cx = source.cx;
3351
3497
  this.cy = source.cy;
3352
3498
  this.radius = source.radius;
@@ -3418,11 +3564,11 @@ class QuadraticBezierCurve extends Curve {
3418
3564
  ctx.quadraticCurveTo(cp.x, cp.y, p2.x, p2.y);
3419
3565
  return this;
3420
3566
  }
3421
- copy(source) {
3422
- super.copy(source);
3423
- this.p1.copy(source.p1);
3424
- this.cp.copy(source.cp);
3425
- this.p2.copy(source.p2);
3567
+ copyFrom(source) {
3568
+ super.copyFrom(source);
3569
+ this.p1.copyFrom(source.p1);
3570
+ this.cp.copyFrom(source.cp);
3571
+ this.p2.copyFrom(source.p2);
3426
3572
  return this;
3427
3573
  }
3428
3574
  }
@@ -3469,8 +3615,8 @@ class RectangleCurve extends PloygonCurve {
3469
3615
  y + height
3470
3616
  ];
3471
3617
  }
3472
- copy(source) {
3473
- super.copy(source);
3618
+ copyFrom(source) {
3619
+ super.copyFrom(source);
3474
3620
  this.x = source.x;
3475
3621
  this.y = source.y;
3476
3622
  this.width = source.width;
@@ -3508,8 +3654,8 @@ class RoundRectangleCurve extends RoundCurve {
3508
3654
  ctx.roundRect(x, y, width, height, radius);
3509
3655
  return this;
3510
3656
  }
3511
- copy(source) {
3512
- super.copy(source);
3657
+ copyFrom(source) {
3658
+ super.copyFrom(source);
3513
3659
  this.x = source.x;
3514
3660
  this.y = source.y;
3515
3661
  this.width = source.width;
@@ -3543,8 +3689,8 @@ class SplineCurve extends Curve {
3543
3689
  getControlPointRefs() {
3544
3690
  return this.points;
3545
3691
  }
3546
- copy(source) {
3547
- super.copy(source);
3692
+ copyFrom(source) {
3693
+ super.copyFrom(source);
3548
3694
  this.points = [];
3549
3695
  for (let i = 0, len = source.points.length; i < len; i++) {
3550
3696
  this.points.push(source.points[i].clone());
@@ -3627,7 +3773,7 @@ class CurvePath extends CompositeCurve {
3627
3773
  const end = this.currentPoint;
3628
3774
  if (end && !start.equals(end)) {
3629
3775
  this.curves.push(new LineCurve(end.clone(), start.clone()));
3630
- end.copy(start);
3776
+ end.copyFrom(start);
3631
3777
  }
3632
3778
  this.startPoint = void 0;
3633
3779
  }
@@ -3768,8 +3914,8 @@ class CurvePath extends CompositeCurve {
3768
3914
  }
3769
3915
  return this;
3770
3916
  }
3771
- copy(source) {
3772
- super.copy(source);
3917
+ copyFrom(source) {
3918
+ super.copyFrom(source);
3773
3919
  this.autoClose = source.autoClose;
3774
3920
  this.currentPoint = source.currentPoint?.clone();
3775
3921
  return this;
@@ -3963,8 +4109,8 @@ class Path2D extends CompositeCurve {
3963
4109
  pointsB[1] ?? pointsB[0]
3964
4110
  );
3965
4111
  if (point) {
3966
- pointsA[pointsA.length - 1].copy(point);
3967
- pointsB[0].copy(point);
4112
+ pointsA[pointsA.length - 1].copyFrom(point);
4113
+ pointsB[0].copyFrom(point);
3968
4114
  }
3969
4115
  });
3970
4116
  });
@@ -3995,8 +4141,8 @@ class Path2D extends CompositeCurve {
3995
4141
  point.clone().add({ x: -halfStrokeWidth, y: -halfStrokeWidth })
3996
4142
  );
3997
4143
  }
3998
- min.min(...points);
3999
- max.max(...points);
4144
+ min.clampMin(...points);
4145
+ max.clampMax(...points);
4000
4146
  }
4001
4147
  }
4002
4148
  });
@@ -4134,8 +4280,8 @@ class Path2D extends CompositeCurve {
4134
4280
  }
4135
4281
  return `<path d="${this.toData()}" style="${cssText}"></path>`;
4136
4282
  }
4137
- copy(source) {
4138
- super.copy(source);
4283
+ copyFrom(source) {
4284
+ super.copyFrom(source);
4139
4285
  this.currentCurve = source.currentCurve.clone();
4140
4286
  this.style = { ...source.style };
4141
4287
  return this;
@@ -4312,7 +4458,8 @@ exports.EllipseCurve = EllipseCurve;
4312
4458
  exports.EquilateralPloygonCurve = EquilateralPloygonCurve;
4313
4459
  exports.FFDControlGrid = FFDControlGrid;
4314
4460
  exports.LineCurve = LineCurve;
4315
- exports.Matrix3 = Matrix3;
4461
+ exports.PI = PI;
4462
+ exports.PI_2 = PI_2;
4316
4463
  exports.Path2D = Path2D;
4317
4464
  exports.Path2DSet = Path2DSet;
4318
4465
  exports.PloygonCurve = PloygonCurve;
@@ -4320,6 +4467,7 @@ exports.QuadraticBezierCurve = QuadraticBezierCurve;
4320
4467
  exports.RectangleCurve = RectangleCurve;
4321
4468
  exports.RoundRectangleCurve = RoundRectangleCurve;
4322
4469
  exports.SplineCurve = SplineCurve;
4470
+ exports.Transform2D = Transform2D;
4323
4471
  exports.Vector2 = Vector2;
4324
4472
  exports.applyFFD = applyFFD;
4325
4473
  exports.catmullRom = catmullRom;