modern-path2d 0.0.5 → 0.1.0

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
@@ -1,3 +1,205 @@
1
+ var __defProp$6 = Object.defineProperty;
2
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField$6 = (obj, key, value) => {
4
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ class Matrix3 {
8
+ constructor(n11 = 1, n12 = 0, n13 = 0, n21 = 0, n22 = 1, n23 = 0, n31 = 0, n32 = 0, n33 = 1) {
9
+ __publicField$6(this, "elements", []);
10
+ this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33);
11
+ }
12
+ set(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
13
+ const te = this.elements;
14
+ te[0] = n11;
15
+ te[1] = n21;
16
+ te[2] = n31;
17
+ te[3] = n12;
18
+ te[4] = n22;
19
+ te[5] = n32;
20
+ te[6] = n13;
21
+ te[7] = n23;
22
+ te[8] = n33;
23
+ return this;
24
+ }
25
+ identity() {
26
+ this.set(
27
+ 1,
28
+ 0,
29
+ 0,
30
+ 0,
31
+ 1,
32
+ 0,
33
+ 0,
34
+ 0,
35
+ 1
36
+ );
37
+ return this;
38
+ }
39
+ copy(m) {
40
+ const te = this.elements;
41
+ const me = m.elements;
42
+ te[0] = me[0];
43
+ te[1] = me[1];
44
+ te[2] = me[2];
45
+ te[3] = me[3];
46
+ te[4] = me[4];
47
+ te[5] = me[5];
48
+ te[6] = me[6];
49
+ te[7] = me[7];
50
+ te[8] = me[8];
51
+ return this;
52
+ }
53
+ multiply(m) {
54
+ return this.multiplyMatrices(this, m);
55
+ }
56
+ premultiply(m) {
57
+ return this.multiplyMatrices(m, this);
58
+ }
59
+ multiplyMatrices(a, b) {
60
+ const ae = a.elements;
61
+ const be = b.elements;
62
+ const te = this.elements;
63
+ const a11 = ae[0];
64
+ const a12 = ae[3];
65
+ const a13 = ae[6];
66
+ const a21 = ae[1];
67
+ const a22 = ae[4];
68
+ const a23 = ae[7];
69
+ const a31 = ae[2];
70
+ const a32 = ae[5];
71
+ const a33 = ae[8];
72
+ const b11 = be[0];
73
+ const b12 = be[3];
74
+ const b13 = be[6];
75
+ const b21 = be[1];
76
+ const b22 = be[4];
77
+ const b23 = be[7];
78
+ const b31 = be[2];
79
+ const b32 = be[5];
80
+ const b33 = be[8];
81
+ te[0] = a11 * b11 + a12 * b21 + a13 * b31;
82
+ te[3] = a11 * b12 + a12 * b22 + a13 * b32;
83
+ te[6] = a11 * b13 + a12 * b23 + a13 * b33;
84
+ te[1] = a21 * b11 + a22 * b21 + a23 * b31;
85
+ te[4] = a21 * b12 + a22 * b22 + a23 * b32;
86
+ te[7] = a21 * b13 + a22 * b23 + a23 * b33;
87
+ te[2] = a31 * b11 + a32 * b21 + a33 * b31;
88
+ te[5] = a31 * b12 + a32 * b22 + a33 * b32;
89
+ te[8] = a31 * b13 + a32 * b23 + a33 * b33;
90
+ return this;
91
+ }
92
+ invert() {
93
+ const te = this.elements;
94
+ const n11 = te[0];
95
+ const n21 = te[1];
96
+ const n31 = te[2];
97
+ const n12 = te[3];
98
+ const n22 = te[4];
99
+ const n32 = te[5];
100
+ const n13 = te[6];
101
+ const n23 = te[7];
102
+ const n33 = te[8];
103
+ const t11 = n33 * n22 - n32 * n23;
104
+ const t12 = n32 * n13 - n33 * n12;
105
+ const t13 = n23 * n12 - n22 * n13;
106
+ const det = n11 * t11 + n21 * t12 + n31 * t13;
107
+ if (det === 0)
108
+ return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
109
+ const detInv = 1 / det;
110
+ te[0] = t11 * detInv;
111
+ te[1] = (n31 * n23 - n33 * n21) * detInv;
112
+ te[2] = (n32 * n21 - n31 * n22) * detInv;
113
+ te[3] = t12 * detInv;
114
+ te[4] = (n33 * n11 - n31 * n13) * detInv;
115
+ te[5] = (n31 * n12 - n32 * n11) * detInv;
116
+ te[6] = t13 * detInv;
117
+ te[7] = (n21 * n13 - n23 * n11) * detInv;
118
+ te[8] = (n22 * n11 - n21 * n12) * detInv;
119
+ return this;
120
+ }
121
+ transpose() {
122
+ let tmp;
123
+ const m = this.elements;
124
+ tmp = m[1];
125
+ m[1] = m[3];
126
+ m[3] = tmp;
127
+ tmp = m[2];
128
+ m[2] = m[6];
129
+ m[6] = tmp;
130
+ tmp = m[5];
131
+ m[5] = m[7];
132
+ m[7] = tmp;
133
+ return this;
134
+ }
135
+ scale(sx, sy) {
136
+ this.premultiply(_m3.makeScale(sx, sy));
137
+ return this;
138
+ }
139
+ rotate(theta) {
140
+ this.premultiply(_m3.makeRotation(-theta));
141
+ return this;
142
+ }
143
+ translate(tx, ty) {
144
+ this.premultiply(_m3.makeTranslation(tx, ty));
145
+ return this;
146
+ }
147
+ makeTranslation(x, y) {
148
+ this.set(
149
+ 1,
150
+ 0,
151
+ x,
152
+ 0,
153
+ 1,
154
+ y,
155
+ 0,
156
+ 0,
157
+ 1
158
+ );
159
+ return this;
160
+ }
161
+ makeRotation(theta) {
162
+ const c = Math.cos(theta);
163
+ const s = Math.sin(theta);
164
+ this.set(
165
+ c,
166
+ -s,
167
+ 0,
168
+ s,
169
+ c,
170
+ 0,
171
+ 0,
172
+ 0,
173
+ 1
174
+ );
175
+ return this;
176
+ }
177
+ makeScale(x, y) {
178
+ this.set(
179
+ x,
180
+ 0,
181
+ 0,
182
+ 0,
183
+ y,
184
+ 0,
185
+ 0,
186
+ 0,
187
+ 1
188
+ );
189
+ return this;
190
+ }
191
+ fromArray(array, offset = 0) {
192
+ for (let i = 0; i < 9; i++) {
193
+ this.elements[i] = array[i + offset];
194
+ }
195
+ return this;
196
+ }
197
+ clone() {
198
+ return new this.constructor().fromArray(this.elements);
199
+ }
200
+ }
201
+ const _m3 = /* @__PURE__ */ new Matrix3();
202
+
1
203
  class Point2D {
2
204
  constructor(x = 0, y = 0) {
3
205
  this.x = x;
@@ -59,6 +261,15 @@ class Point2D {
59
261
  equals(point) {
60
262
  return this.x === point.x && this.y === point.y;
61
263
  }
264
+ applyMatrix3(matrix3) {
265
+ const [a, c, tx, b, d, ty] = matrix3.elements;
266
+ const { x, y } = this;
267
+ this.set(
268
+ a * x + c * y + tx,
269
+ b * x + d * y + ty
270
+ );
271
+ return this;
272
+ }
62
273
  copy(point) {
63
274
  this.x = point.x;
64
275
  this.y = point.y;
@@ -69,6 +280,574 @@ class Point2D {
69
280
  }
70
281
  }
71
282
 
283
+ function svgAngle(ux, uy, vx, vy) {
284
+ const dot = ux * vx + uy * vy;
285
+ const len = Math.sqrt(ux * ux + uy * uy) * Math.sqrt(vx * vx + vy * vy);
286
+ let ang = Math.acos(Math.max(-1, Math.min(1, dot / len)));
287
+ if (ux * vy - uy * vx < 0)
288
+ ang = -ang;
289
+ return ang;
290
+ }
291
+ function parseArcCommand(path, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, start, end) {
292
+ if (rx === 0 || ry === 0) {
293
+ path.lineTo(end.x, end.y);
294
+ return;
295
+ }
296
+ xAxisRotation = xAxisRotation * Math.PI / 180;
297
+ rx = Math.abs(rx);
298
+ ry = Math.abs(ry);
299
+ const dx2 = (start.x - end.x) / 2;
300
+ const dy2 = (start.y - end.y) / 2;
301
+ const x1p = Math.cos(xAxisRotation) * dx2 + Math.sin(xAxisRotation) * dy2;
302
+ const y1p = -Math.sin(xAxisRotation) * dx2 + Math.cos(xAxisRotation) * dy2;
303
+ let rxs = rx * rx;
304
+ let rys = ry * ry;
305
+ const x1ps = x1p * x1p;
306
+ const y1ps = y1p * y1p;
307
+ const cr = x1ps / rxs + y1ps / rys;
308
+ if (cr > 1) {
309
+ const s = Math.sqrt(cr);
310
+ rx = s * rx;
311
+ ry = s * ry;
312
+ rxs = rx * rx;
313
+ rys = ry * ry;
314
+ }
315
+ const dq = rxs * y1ps + rys * x1ps;
316
+ const pq = (rxs * rys - dq) / dq;
317
+ let q = Math.sqrt(Math.max(0, pq));
318
+ if (largeArcFlag === sweepFlag)
319
+ q = -q;
320
+ const cxp = q * rx * y1p / ry;
321
+ const cyp = -q * ry * x1p / rx;
322
+ const cx = Math.cos(xAxisRotation) * cxp - Math.sin(xAxisRotation) * cyp + (start.x + end.x) / 2;
323
+ const cy = Math.sin(xAxisRotation) * cxp + Math.cos(xAxisRotation) * cyp + (start.y + end.y) / 2;
324
+ const theta = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
325
+ const delta = svgAngle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry) % (Math.PI * 2);
326
+ path.currentPath.absellipse(cx, cy, rx, ry, theta, theta + delta, sweepFlag === 0, xAxisRotation);
327
+ }
328
+
329
+ function getReflection(a, b) {
330
+ return a - (b - a);
331
+ }
332
+ function addPathCommandsToPath2D(commands, path) {
333
+ const point = new Point2D();
334
+ const control = new Point2D();
335
+ const firstPoint = new Point2D();
336
+ let isFirstPoint = true;
337
+ let doSetFirstPoint = false;
338
+ for (let i = 0, l = commands.length; i < l; i++) {
339
+ const command = commands[i];
340
+ if (isFirstPoint) {
341
+ doSetFirstPoint = true;
342
+ isFirstPoint = false;
343
+ }
344
+ if (command.type === "m" || command.type === "M") {
345
+ if (command.type === "m") {
346
+ point.x += command.x;
347
+ point.y += command.y;
348
+ } else {
349
+ point.x = command.x;
350
+ point.y = command.y;
351
+ }
352
+ control.x = point.x;
353
+ control.y = point.y;
354
+ path.moveTo(point.x, point.y);
355
+ if (i === 0)
356
+ firstPoint.copy(point);
357
+ } else if (command.type === "h" || command.type === "H") {
358
+ if (command.type === "h") {
359
+ point.x += command.x;
360
+ } else {
361
+ point.x = command.x;
362
+ }
363
+ control.x = point.x;
364
+ control.y = point.y;
365
+ path.lineTo(point.x, point.y);
366
+ if (doSetFirstPoint)
367
+ firstPoint.copy(point);
368
+ } else if (command.type === "v" || command.type === "V") {
369
+ if (command.type === "v") {
370
+ point.y += command.y;
371
+ } else {
372
+ point.y = command.y;
373
+ }
374
+ control.x = point.x;
375
+ control.y = point.y;
376
+ path.lineTo(point.x, point.y);
377
+ if (doSetFirstPoint)
378
+ firstPoint.copy(point);
379
+ } else if (command.type === "l" || command.type === "L") {
380
+ if (command.type === "l") {
381
+ point.x += command.x;
382
+ point.y += command.y;
383
+ } else {
384
+ point.x = command.x;
385
+ point.y = command.y;
386
+ }
387
+ control.x = point.x;
388
+ control.y = point.y;
389
+ path.lineTo(point.x, point.y);
390
+ if (doSetFirstPoint)
391
+ firstPoint.copy(point);
392
+ } else if (command.type === "c" || command.type === "C") {
393
+ if (command.type === "c") {
394
+ path.bezierCurveTo(
395
+ point.x + command.x1,
396
+ point.y + command.y1,
397
+ point.x + command.x2,
398
+ point.y + command.y2,
399
+ point.x + command.x,
400
+ point.y + command.y
401
+ );
402
+ control.x = point.x + command.x2;
403
+ control.y = point.y + command.y2;
404
+ point.x += command.x;
405
+ point.y += command.y;
406
+ } else {
407
+ path.bezierCurveTo(
408
+ command.x1,
409
+ command.y1,
410
+ command.x2,
411
+ command.y2,
412
+ command.x,
413
+ command.y
414
+ );
415
+ control.x = command.x2;
416
+ control.y = command.y2;
417
+ point.x = command.x;
418
+ point.y = command.y;
419
+ }
420
+ if (doSetFirstPoint)
421
+ firstPoint.copy(point);
422
+ } else if (command.type === "s" || command.type === "S") {
423
+ if (command.type === "s") {
424
+ path.bezierCurveTo(
425
+ getReflection(point.x, control.x),
426
+ getReflection(point.y, control.y),
427
+ point.x + command.x2,
428
+ point.y + command.y2,
429
+ point.x + command.x,
430
+ point.y + command.y
431
+ );
432
+ control.x = point.x + command.x2;
433
+ control.y = point.y + command.y2;
434
+ point.x += command.x;
435
+ point.y += command.y;
436
+ } else {
437
+ path.bezierCurveTo(
438
+ getReflection(point.x, control.x),
439
+ getReflection(point.y, control.y),
440
+ command.x2,
441
+ command.y2,
442
+ command.x,
443
+ command.y
444
+ );
445
+ control.x = command.x2;
446
+ control.y = command.y2;
447
+ point.x = command.x;
448
+ point.y = command.y;
449
+ }
450
+ if (doSetFirstPoint)
451
+ firstPoint.copy(point);
452
+ } else if (command.type === "q" || command.type === "Q") {
453
+ if (command.type === "q") {
454
+ path.quadraticCurveTo(
455
+ point.x + command.x1,
456
+ point.y + command.y1,
457
+ point.x + command.x,
458
+ point.y + command.y
459
+ );
460
+ control.x = point.x + command.x1;
461
+ control.y = point.y + command.y1;
462
+ point.x += command.x;
463
+ point.y += command.y;
464
+ } else {
465
+ path.quadraticCurveTo(
466
+ command.x1,
467
+ command.y1,
468
+ command.x,
469
+ command.y
470
+ );
471
+ control.x = command.x1;
472
+ control.y = command.y1;
473
+ point.x = command.x;
474
+ point.y = command.y;
475
+ }
476
+ if (doSetFirstPoint)
477
+ firstPoint.copy(point);
478
+ } else if (command.type === "t" || command.type === "T") {
479
+ const rx = getReflection(point.x, control.x);
480
+ const ry = getReflection(point.y, control.y);
481
+ control.x = rx;
482
+ control.y = ry;
483
+ if (command.type === "t") {
484
+ path.quadraticCurveTo(
485
+ rx,
486
+ ry,
487
+ point.x + command.x,
488
+ point.y + command.y
489
+ );
490
+ point.x += command.x;
491
+ point.y += command.y;
492
+ } else {
493
+ path.quadraticCurveTo(
494
+ rx,
495
+ ry,
496
+ command.x,
497
+ command.y
498
+ );
499
+ point.x = command.x;
500
+ point.y = command.y;
501
+ }
502
+ if (doSetFirstPoint)
503
+ firstPoint.copy(point);
504
+ } else if (command.type === "a" || command.type === "A") {
505
+ if (command.type === "a") {
506
+ if (command.x === 0 && command.y === 0)
507
+ continue;
508
+ point.x += command.x;
509
+ point.y += command.y;
510
+ } else {
511
+ if (command.x === point.x && command.y === point.y)
512
+ continue;
513
+ point.x = command.x;
514
+ point.y = command.y;
515
+ }
516
+ const start = point.clone();
517
+ control.x = point.x;
518
+ control.y = point.y;
519
+ parseArcCommand(
520
+ path,
521
+ command.rx,
522
+ command.ry,
523
+ command.angle,
524
+ command.largeArcFlag,
525
+ command.sweepFlag,
526
+ start,
527
+ point
528
+ );
529
+ if (doSetFirstPoint)
530
+ firstPoint.copy(point);
531
+ } else if (command.type === "z" || command.type === "Z") {
532
+ path.currentPath.autoClose = true;
533
+ if (path.currentPath.curves.length > 0) {
534
+ point.copy(firstPoint);
535
+ path.currentPath.currentPoint.copy(point);
536
+ isFirstPoint = true;
537
+ }
538
+ } else {
539
+ console.warn(command);
540
+ }
541
+ doSetFirstPoint = false;
542
+ }
543
+ }
544
+
545
+ const RE$3 = {
546
+ SEPARATOR: /[ \t\r\n,.\-+]/,
547
+ WHITESPACE: /[ \t\r\n]/,
548
+ DIGIT: /\d/,
549
+ SIGN: /[-+]/,
550
+ POINT: /\./,
551
+ COMMA: /,/,
552
+ EXP: /e/i,
553
+ FLAGS: /[01]/
554
+ };
555
+ function parsePathDataArgs(input, flags, stride = 0) {
556
+ const SEP = 0;
557
+ const INT = 1;
558
+ const FLOAT = 2;
559
+ const EXP = 3;
560
+ let state = SEP;
561
+ let seenComma = true;
562
+ let number = "";
563
+ let exponent = "";
564
+ const result = [];
565
+ function throwSyntaxError(current2, i, partial) {
566
+ const error = new SyntaxError(`Unexpected character "${current2}" at index ${i}.`);
567
+ error.partial = partial;
568
+ throw error;
569
+ }
570
+ function newNumber() {
571
+ if (number !== "") {
572
+ if (exponent === "")
573
+ result.push(Number(number));
574
+ else
575
+ result.push(Number(number) * 10 ** Number(exponent));
576
+ }
577
+ number = "";
578
+ exponent = "";
579
+ }
580
+ let current;
581
+ const length = input.length;
582
+ for (let i = 0; i < length; i++) {
583
+ current = input[i];
584
+ if (Array.isArray(flags) && flags.includes(result.length % stride) && RE$3.FLAGS.test(current)) {
585
+ state = INT;
586
+ number = current;
587
+ newNumber();
588
+ continue;
589
+ }
590
+ if (state === SEP) {
591
+ if (RE$3.WHITESPACE.test(current)) {
592
+ continue;
593
+ }
594
+ if (RE$3.DIGIT.test(current) || RE$3.SIGN.test(current)) {
595
+ state = INT;
596
+ number = current;
597
+ continue;
598
+ }
599
+ if (RE$3.POINT.test(current)) {
600
+ state = FLOAT;
601
+ number = current;
602
+ continue;
603
+ }
604
+ if (RE$3.COMMA.test(current)) {
605
+ if (seenComma) {
606
+ throwSyntaxError(current, i, result);
607
+ }
608
+ seenComma = true;
609
+ }
610
+ }
611
+ if (state === INT) {
612
+ if (RE$3.DIGIT.test(current)) {
613
+ number += current;
614
+ continue;
615
+ }
616
+ if (RE$3.POINT.test(current)) {
617
+ number += current;
618
+ state = FLOAT;
619
+ continue;
620
+ }
621
+ if (RE$3.EXP.test(current)) {
622
+ state = EXP;
623
+ continue;
624
+ }
625
+ if (RE$3.SIGN.test(current) && number.length === 1 && RE$3.SIGN.test(number[0])) {
626
+ throwSyntaxError(current, i, result);
627
+ }
628
+ }
629
+ if (state === FLOAT) {
630
+ if (RE$3.DIGIT.test(current)) {
631
+ number += current;
632
+ continue;
633
+ }
634
+ if (RE$3.EXP.test(current)) {
635
+ state = EXP;
636
+ continue;
637
+ }
638
+ if (RE$3.POINT.test(current) && number[number.length - 1] === ".") {
639
+ throwSyntaxError(current, i, result);
640
+ }
641
+ }
642
+ if (state === EXP) {
643
+ if (RE$3.DIGIT.test(current)) {
644
+ exponent += current;
645
+ continue;
646
+ }
647
+ if (RE$3.SIGN.test(current)) {
648
+ if (exponent === "") {
649
+ exponent += current;
650
+ continue;
651
+ }
652
+ if (exponent.length === 1 && RE$3.SIGN.test(exponent)) {
653
+ throwSyntaxError(current, i, result);
654
+ }
655
+ }
656
+ }
657
+ if (RE$3.WHITESPACE.test(current)) {
658
+ newNumber();
659
+ state = SEP;
660
+ seenComma = false;
661
+ } else if (RE$3.COMMA.test(current)) {
662
+ newNumber();
663
+ state = SEP;
664
+ seenComma = true;
665
+ } else if (RE$3.SIGN.test(current)) {
666
+ newNumber();
667
+ state = INT;
668
+ number = current;
669
+ } else if (RE$3.POINT.test(current)) {
670
+ newNumber();
671
+ state = FLOAT;
672
+ number = current;
673
+ } else {
674
+ throwSyntaxError(current, i, result);
675
+ }
676
+ }
677
+ newNumber();
678
+ return result;
679
+ }
680
+
681
+ function commandToData(cmd) {
682
+ switch (cmd.type) {
683
+ case "m":
684
+ case "M":
685
+ return `${cmd.type} ${cmd.x} ${cmd.y}`;
686
+ case "h":
687
+ case "H":
688
+ return `${cmd.type} ${cmd.x}`;
689
+ case "v":
690
+ case "V":
691
+ return `${cmd.type} ${cmd.y}`;
692
+ case "l":
693
+ case "L":
694
+ return `${cmd.type} ${cmd.x} ${cmd.y}`;
695
+ case "c":
696
+ case "C":
697
+ return `${cmd.type} ${cmd.x1} ${cmd.y1} ${cmd.x2} ${cmd.y2} ${cmd.x} ${cmd.y}`;
698
+ case "s":
699
+ case "S":
700
+ return `${cmd.type} ${cmd.x2} ${cmd.y2} ${cmd.x} ${cmd.y}`;
701
+ case "q":
702
+ case "Q":
703
+ return `${cmd.type} ${cmd.x1} ${cmd.y1} ${cmd.x} ${cmd.y}`;
704
+ case "t":
705
+ case "T":
706
+ return `${cmd.type} ${cmd.x} ${cmd.y}`;
707
+ case "a":
708
+ case "A":
709
+ return `${cmd.type} ${cmd.rx} ${cmd.ry} ${cmd.angle} ${cmd.largeArcFlag} ${cmd.sweepFlag} ${cmd.x} ${cmd.y}`;
710
+ case "z":
711
+ case "Z":
712
+ return cmd.type;
713
+ default:
714
+ return "";
715
+ }
716
+ }
717
+ function pathCommandsToPathData(commands) {
718
+ let data = "";
719
+ for (let i = 0, len = commands.length; i < len; i++) {
720
+ data += `${commandToData(commands[i])} `;
721
+ }
722
+ return data;
723
+ }
724
+
725
+ const RE$2 = /[a-df-z][^a-df-z]*/gi;
726
+ function pathDataToPathCommands(d) {
727
+ const commands = [];
728
+ const matched = d.match(RE$2);
729
+ if (!matched) {
730
+ return commands;
731
+ }
732
+ for (let i = 0, len = matched.length; i < len; i++) {
733
+ const command = matched[i];
734
+ const type = command.charAt(0);
735
+ const data = command.slice(1).trim();
736
+ let args;
737
+ switch (type) {
738
+ case "m":
739
+ case "M":
740
+ args = parsePathDataArgs(data);
741
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
742
+ if (i2 === 0) {
743
+ commands.push({ type, x: args[i2], y: args[i2 + 1] });
744
+ } else {
745
+ commands.push({ type: type === "m" ? "l" : "L", x: args[i2], y: args[i2 + 1] });
746
+ }
747
+ }
748
+ break;
749
+ case "h":
750
+ case "H":
751
+ args = parsePathDataArgs(data);
752
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2++) {
753
+ commands.push({ type, x: args[i2] });
754
+ }
755
+ break;
756
+ case "v":
757
+ case "V":
758
+ args = parsePathDataArgs(data);
759
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2++) {
760
+ commands.push({ type, y: args[i2] });
761
+ }
762
+ break;
763
+ case "l":
764
+ case "L":
765
+ args = parsePathDataArgs(data);
766
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
767
+ commands.push({ type, x: args[i2], y: args[i2 + 1] });
768
+ }
769
+ break;
770
+ case "c":
771
+ case "C":
772
+ args = parsePathDataArgs(data);
773
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 6) {
774
+ commands.push({
775
+ type,
776
+ x1: args[i2],
777
+ y1: args[i2 + 1],
778
+ x2: args[i2 + 2],
779
+ y2: args[i2 + 3],
780
+ x: args[i2 + 4],
781
+ y: args[i2 + 5]
782
+ });
783
+ }
784
+ break;
785
+ case "s":
786
+ case "S":
787
+ args = parsePathDataArgs(data);
788
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 4) {
789
+ commands.push({
790
+ type,
791
+ x2: args[i2],
792
+ y2: args[i2 + 1],
793
+ x: args[i2 + 2],
794
+ y: args[i2 + 3]
795
+ });
796
+ }
797
+ break;
798
+ case "q":
799
+ case "Q":
800
+ args = parsePathDataArgs(data);
801
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 4) {
802
+ commands.push({
803
+ type,
804
+ x1: args[i2],
805
+ y1: args[i2 + 1],
806
+ x: args[i2 + 2],
807
+ y: args[i2 + 3]
808
+ });
809
+ }
810
+ break;
811
+ case "t":
812
+ case "T":
813
+ args = parsePathDataArgs(data);
814
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 2) {
815
+ commands.push({
816
+ type,
817
+ x: args[i2],
818
+ y: args[i2 + 1]
819
+ });
820
+ }
821
+ break;
822
+ case "a":
823
+ case "A":
824
+ args = parsePathDataArgs(data, [3, 4], 7);
825
+ for (let i2 = 0, len2 = args.length; i2 < len2; i2 += 7) {
826
+ commands.push({
827
+ type,
828
+ rx: args[i2],
829
+ ry: args[i2 + 1],
830
+ angle: args[i2 + 2],
831
+ largeArcFlag: args[i2 + 3],
832
+ sweepFlag: args[i2 + 4],
833
+ x: args[i2 + 5],
834
+ y: args[i2 + 6]
835
+ });
836
+ }
837
+ break;
838
+ case "z":
839
+ case "Z":
840
+ commands.push({
841
+ type
842
+ });
843
+ break;
844
+ default:
845
+ console.warn(command);
846
+ }
847
+ }
848
+ return commands;
849
+ }
850
+
72
851
  var __defProp$5 = Object.defineProperty;
73
852
  var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
74
853
  var __publicField$5 = (obj, key, value) => {
@@ -81,12 +860,6 @@ class Curve {
81
860
  __publicField$5(this, "_cacheArcLengths");
82
861
  __publicField$5(this, "_needsUpdate", false);
83
862
  }
84
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
85
- return { min, max };
86
- }
87
- getDivisions(divisions) {
88
- return divisions;
89
- }
90
863
  getPointAt(u, output = new Point2D()) {
91
864
  return this.getPoint(this.getUtoTmapping(u), output);
92
865
  }
@@ -179,25 +952,30 @@ class Curve {
179
952
  getTangentAt(u, output = new Point2D()) {
180
953
  return this.getTangent(this.getUtoTmapping(u), output);
181
954
  }
955
+ /** overrideable */
956
+ // eslint-disable-next-line unused-imports/no-unused-vars
957
+ transform(matrix) {
958
+ return this;
959
+ }
960
+ /** overrideable */
961
+ getDivisions(divisions) {
962
+ return divisions;
963
+ }
964
+ /** overrideable */
965
+ getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
966
+ return { min, max };
967
+ }
968
+ /** overrideable */
969
+ getCommands() {
970
+ return [];
971
+ }
182
972
  getData() {
183
- return this.getCommands().map((cmd) => {
184
- switch (cmd.type) {
185
- case "M":
186
- return `M ${cmd.x} ${cmd.y}`;
187
- case "L":
188
- return `L ${cmd.x} ${cmd.y}`;
189
- case "C":
190
- return `C ${cmd.x1} ${cmd.y1} ${cmd.x2} ${cmd.y2} ${cmd.x} ${cmd.y}`;
191
- case "Q":
192
- return `Q ${cmd.x1} ${cmd.y1} ${cmd.x} ${cmd.y}`;
193
- case "A":
194
- return `A ${cmd.rx} ${cmd.ry} ${cmd.xAxisRotation} ${cmd.largeArcFlag} ${cmd.sweepFlag} ${cmd.x} ${cmd.y}`;
195
- case "Z":
196
- return "Z";
197
- default:
198
- return "";
199
- }
200
- }).join(" ");
973
+ return pathCommandsToPathData(this.getCommands());
974
+ }
975
+ /** overrideable */
976
+ // eslint-disable-next-line unused-imports/no-unused-vars
977
+ drawTo(ctx) {
978
+ return this;
201
979
  }
202
980
  clone() {
203
981
  return new this.constructor().copy(this);
@@ -216,13 +994,6 @@ class CircleCurve extends Curve {
216
994
  this.start = start;
217
995
  this.end = end;
218
996
  }
219
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
220
- min.x = Math.min(min.x, this.center.x - this.radius);
221
- min.y = Math.min(min.y, this.center.y - this.radius);
222
- max.x = Math.max(max.x, this.center.x + this.radius);
223
- max.y = Math.max(max.y, this.center.y + this.radius);
224
- return { min, max };
225
- }
226
997
  getPoint(t) {
227
998
  const { radius, center } = this;
228
999
  return center.clone().add(this.getNormal(t).clone().multiplyScalar(radius));
@@ -236,10 +1007,12 @@ class CircleCurve extends Curve {
236
1007
  const _t = t * (end - start) + start - 0.5 * Math.PI;
237
1008
  return new Point2D(Math.cos(_t), Math.sin(_t));
238
1009
  }
239
- getCommands() {
240
- return [];
241
- }
242
- drawTo(_ctx) {
1010
+ getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
1011
+ min.x = Math.min(min.x, this.center.x - this.radius);
1012
+ min.y = Math.min(min.y, this.center.y - this.radius);
1013
+ max.x = Math.max(max.x, this.center.x + this.radius);
1014
+ max.y = Math.max(max.y, this.center.y + this.radius);
1015
+ return { min, max };
243
1016
  }
244
1017
  }
245
1018
 
@@ -305,6 +1078,13 @@ class CubicBezierCurve extends Curve {
305
1078
  max.y = Math.max(max.y, v0.y, v1.y, v2.y, v3.y);
306
1079
  return { min, max };
307
1080
  }
1081
+ transform(matrix) {
1082
+ this.v0.applyMatrix3(matrix);
1083
+ this.v1.applyMatrix3(matrix);
1084
+ this.v2.applyMatrix3(matrix);
1085
+ this.v3.applyMatrix3(matrix);
1086
+ return this;
1087
+ }
308
1088
  getCommands() {
309
1089
  const { v0, v1, v2, v3 } = this;
310
1090
  return [
@@ -316,6 +1096,7 @@ class CubicBezierCurve extends Curve {
316
1096
  const { v0, v1, v2, v3 } = this;
317
1097
  ctx.moveTo(v0.x, v0.y);
318
1098
  ctx.bezierCurveTo(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y);
1099
+ return this;
319
1100
  }
320
1101
  copy(source) {
321
1102
  super.copy(source);
@@ -327,13 +1108,17 @@ class CubicBezierCurve extends Curve {
327
1108
  }
328
1109
  }
329
1110
 
1111
+ const tempTransform0$1 = new Matrix3();
1112
+ const tempTransform1$1 = new Matrix3();
1113
+ const tempTransform2$1 = new Matrix3();
1114
+ const tempV2 = new Point2D();
330
1115
  class EllipseCurve extends Curve {
331
- constructor(x = 0, y = 0, rx = 1, ry = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false, rotation = 0) {
1116
+ constructor(x = 0, y = 0, radiusX = 1, radiusY = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false, rotation = 0) {
332
1117
  super();
333
1118
  this.x = x;
334
1119
  this.y = y;
335
- this.rx = rx;
336
- this.ry = ry;
1120
+ this.radiusX = radiusX;
1121
+ this.radiusY = radiusY;
337
1122
  this.startAngle = startAngle;
338
1123
  this.endAngle = endAngle;
339
1124
  this.clockwise = clockwise;
@@ -365,8 +1150,8 @@ class EllipseCurve extends Curve {
365
1150
  }
366
1151
  }
367
1152
  const angle = this.startAngle + t * deltaAngle;
368
- let _x = this.x + this.rx * Math.cos(angle);
369
- let _y = this.y + this.ry * Math.sin(angle);
1153
+ let _x = this.x + this.radiusX * Math.cos(angle);
1154
+ let _y = this.y + this.radiusY * Math.sin(angle);
370
1155
  if (this.rotation !== 0) {
371
1156
  const cos = Math.cos(this.rotation);
372
1157
  const sin = Math.sin(this.rotation);
@@ -378,50 +1163,65 @@ class EllipseCurve extends Curve {
378
1163
  return output.set(_x, _y);
379
1164
  }
380
1165
  getCommands() {
381
- const { x, y, rx, ry, startAngle, endAngle, clockwise } = this;
1166
+ const { x, y, radiusX, radiusY, startAngle, endAngle, clockwise } = this;
382
1167
  const anticlockwise = !clockwise;
383
- const startX = x + rx * Math.cos(startAngle);
384
- const startY = y + ry * Math.sin(startAngle);
385
- const endX = x + rx * Math.cos(endAngle);
386
- const endY = y + ry * Math.sin(endAngle);
1168
+ const startX = x + radiusX * Math.cos(startAngle);
1169
+ const startY = y + radiusY * Math.sin(startAngle);
1170
+ const endX = x + radiusX * Math.cos(endAngle);
1171
+ const endY = y + radiusY * Math.sin(endAngle);
387
1172
  const angleDiff = Math.abs(startAngle - endAngle);
388
1173
  const largeArcFlag = angleDiff > Math.PI ? 1 : 0;
389
1174
  const sweepFlag = anticlockwise ? 0 : 1;
390
- const midX = x + rx * Math.cos(startAngle + (endAngle - startAngle) / 2);
391
- const midY = y + ry * Math.sin(startAngle + (endAngle - startAngle) / 2);
1175
+ const midX = x + radiusX * Math.cos(startAngle + (endAngle - startAngle) / 2);
1176
+ const midY = y + radiusY * Math.sin(startAngle + (endAngle - startAngle) / 2);
392
1177
  if (angleDiff >= 2 * Math.PI) {
393
1178
  return [
394
1179
  { type: "M", x: startX, y: startY },
395
- { type: "A", rx, ry, xAxisRotation: 0, largeArcFlag: 1, sweepFlag, x: midX, y: midY },
396
- { type: "A", rx, ry, xAxisRotation: 0, largeArcFlag: 1, sweepFlag, x: startX, y: startY }
1180
+ { type: "A", rx: radiusX, ry: radiusY, angle: 0, largeArcFlag: 1, sweepFlag, x: midX, y: midY },
1181
+ { type: "A", rx: radiusX, ry: radiusY, angle: 0, largeArcFlag: 1, sweepFlag, x: startX, y: startY }
397
1182
  ];
398
1183
  } else {
399
1184
  return [
400
1185
  { type: "M", x: startX, y: startY },
401
- { type: "A", rx, ry, xAxisRotation: 0, largeArcFlag, sweepFlag, x: endX, y: endY }
1186
+ { type: "A", rx: radiusX, ry: radiusY, angle: 0, largeArcFlag, sweepFlag, x: endX, y: endY }
402
1187
  ];
403
1188
  }
404
1189
  }
405
1190
  drawTo(ctx) {
406
- const { x, y, rx, ry, startAngle } = this;
407
- const startX = x + rx * Math.cos(startAngle);
408
- const startY = y + ry * Math.sin(startAngle);
1191
+ const { x, y, radiusX, radiusY, rotation, startAngle, endAngle, clockwise } = this;
1192
+ const startX = x + radiusX * Math.cos(startAngle);
1193
+ const startY = y + radiusY * Math.sin(startAngle);
409
1194
  ctx.moveTo(startX, startY);
410
- ctx.arc(
411
- this.x,
412
- this.y,
413
- this.rx,
414
- this.startAngle,
415
- this.endAngle,
416
- !this.clockwise
1195
+ ctx.ellipse(
1196
+ x,
1197
+ y,
1198
+ radiusX,
1199
+ radiusY,
1200
+ rotation,
1201
+ startAngle,
1202
+ endAngle,
1203
+ !clockwise
417
1204
  );
1205
+ return this;
1206
+ }
1207
+ transform(matrix) {
1208
+ tempV2.set(this.x, this.y);
1209
+ tempV2.applyMatrix3(matrix);
1210
+ this.x = tempV2.x;
1211
+ this.y = tempV2.y;
1212
+ if (isTransformSkewed(matrix)) {
1213
+ transfEllipseGeneric(this, matrix);
1214
+ } else {
1215
+ transfEllipseNoSkew(this, matrix);
1216
+ }
1217
+ return this;
418
1218
  }
419
1219
  copy(source) {
420
1220
  super.copy(source);
421
1221
  this.x = source.x;
422
1222
  this.y = source.y;
423
- this.rx = source.rx;
424
- this.ry = source.ry;
1223
+ this.radiusX = source.radiusX;
1224
+ this.radiusY = source.radiusY;
425
1225
  this.startAngle = source.startAngle;
426
1226
  this.endAngle = source.endAngle;
427
1227
  this.clockwise = source.clockwise;
@@ -429,6 +1229,145 @@ class EllipseCurve extends Curve {
429
1229
  return this;
430
1230
  }
431
1231
  }
1232
+ function transfEllipseGeneric(curve, m) {
1233
+ const a = curve.radiusX;
1234
+ const b = curve.radiusY;
1235
+ const cosTheta = Math.cos(curve.rotation);
1236
+ const sinTheta = Math.sin(curve.rotation);
1237
+ const v1 = new Point2D(a * cosTheta, a * sinTheta);
1238
+ const v2 = new Point2D(-b * sinTheta, b * cosTheta);
1239
+ const f1 = v1.applyMatrix3(m);
1240
+ const f2 = v2.applyMatrix3(m);
1241
+ const mF = tempTransform0$1.set(
1242
+ f1.x,
1243
+ f2.x,
1244
+ 0,
1245
+ f1.y,
1246
+ f2.y,
1247
+ 0,
1248
+ 0,
1249
+ 0,
1250
+ 1
1251
+ );
1252
+ const mFInv = tempTransform1$1.copy(mF).invert();
1253
+ const mFInvT = tempTransform2$1.copy(mFInv).transpose();
1254
+ const mQ = mFInvT.multiply(mFInv);
1255
+ const mQe = mQ.elements;
1256
+ const ed = eigenDecomposition(mQe[0], mQe[1], mQe[4]);
1257
+ const rt1sqrt = Math.sqrt(ed.rt1);
1258
+ const rt2sqrt = Math.sqrt(ed.rt2);
1259
+ curve.radiusX = 1 / rt1sqrt;
1260
+ curve.radiusY = 1 / rt2sqrt;
1261
+ curve.rotation = Math.atan2(ed.sn, ed.cs);
1262
+ const isFullEllipse = (curve.endAngle - curve.startAngle) % (2 * Math.PI) < Number.EPSILON;
1263
+ if (!isFullEllipse) {
1264
+ const mDsqrt = tempTransform1$1.set(
1265
+ rt1sqrt,
1266
+ 0,
1267
+ 0,
1268
+ 0,
1269
+ rt2sqrt,
1270
+ 0,
1271
+ 0,
1272
+ 0,
1273
+ 1
1274
+ );
1275
+ const mRT = tempTransform2$1.set(
1276
+ ed.cs,
1277
+ ed.sn,
1278
+ 0,
1279
+ -ed.sn,
1280
+ ed.cs,
1281
+ 0,
1282
+ 0,
1283
+ 0,
1284
+ 1
1285
+ );
1286
+ const mDRF = mDsqrt.multiply(mRT).multiply(mF);
1287
+ const transformAngle = (phi) => {
1288
+ const { x: cosR, y: sinR } = new Point2D(Math.cos(phi), Math.sin(phi)).applyMatrix3(mDRF);
1289
+ return Math.atan2(sinR, cosR);
1290
+ };
1291
+ curve.startAngle = transformAngle(curve.startAngle);
1292
+ curve.endAngle = transformAngle(curve.endAngle);
1293
+ if (isTransformFlipped(m)) {
1294
+ curve.clockwise = !curve.clockwise;
1295
+ }
1296
+ }
1297
+ }
1298
+ function transfEllipseNoSkew(curve, m) {
1299
+ const sx = getTransformScaleX(m);
1300
+ const sy = getTransformScaleY(m);
1301
+ curve.radiusX *= sx;
1302
+ curve.radiusY *= sy;
1303
+ const theta = sx > Number.EPSILON ? Math.atan2(m.elements[1], m.elements[0]) : Math.atan2(-m.elements[3], m.elements[4]);
1304
+ curve.rotation += theta;
1305
+ if (isTransformFlipped(m)) {
1306
+ curve.startAngle *= -1;
1307
+ curve.endAngle *= -1;
1308
+ curve.clockwise = !curve.clockwise;
1309
+ }
1310
+ }
1311
+ function isTransformFlipped(m) {
1312
+ const te = m.elements;
1313
+ return te[0] * te[4] - te[1] * te[3] < 0;
1314
+ }
1315
+ function isTransformSkewed(m) {
1316
+ const te = m.elements;
1317
+ const basisDot = te[0] * te[3] + te[1] * te[4];
1318
+ if (basisDot === 0)
1319
+ return false;
1320
+ const sx = getTransformScaleX(m);
1321
+ const sy = getTransformScaleY(m);
1322
+ return Math.abs(basisDot / (sx * sy)) > Number.EPSILON;
1323
+ }
1324
+ function getTransformScaleX(m) {
1325
+ const te = m.elements;
1326
+ return Math.sqrt(te[0] * te[0] + te[1] * te[1]);
1327
+ }
1328
+ function getTransformScaleY(m) {
1329
+ const te = m.elements;
1330
+ return Math.sqrt(te[3] * te[3] + te[4] * te[4]);
1331
+ }
1332
+ function eigenDecomposition(A, B, C) {
1333
+ let rt1, rt2, cs, sn, t;
1334
+ const sm = A + C;
1335
+ const df = A - C;
1336
+ const rt = Math.sqrt(df * df + 4 * B * B);
1337
+ if (sm > 0) {
1338
+ rt1 = 0.5 * (sm + rt);
1339
+ t = 1 / rt1;
1340
+ rt2 = A * t * C - B * t * B;
1341
+ } else if (sm < 0) {
1342
+ rt2 = 0.5 * (sm - rt);
1343
+ } else {
1344
+ rt1 = 0.5 * rt;
1345
+ rt2 = -0.5 * rt;
1346
+ }
1347
+ if (df > 0) {
1348
+ cs = df + rt;
1349
+ } else {
1350
+ cs = df - rt;
1351
+ }
1352
+ if (Math.abs(cs) > 2 * Math.abs(B)) {
1353
+ t = -2 * B / cs;
1354
+ sn = 1 / Math.sqrt(1 + t * t);
1355
+ cs = t * sn;
1356
+ } else if (Math.abs(B) === 0) {
1357
+ cs = 1;
1358
+ sn = 0;
1359
+ } else {
1360
+ t = -0.5 * cs / B;
1361
+ cs = 1 / Math.sqrt(1 + t * t);
1362
+ sn = t * cs;
1363
+ }
1364
+ if (df > 0) {
1365
+ t = cs;
1366
+ cs = -sn;
1367
+ sn = t;
1368
+ }
1369
+ return { rt1, rt2, cs, sn };
1370
+ }
432
1371
 
433
1372
  class LineCurve extends Curve {
434
1373
  constructor(v1 = new Point2D(), v2 = new Point2D()) {
@@ -472,10 +1411,16 @@ class LineCurve extends Curve {
472
1411
  max.y = Math.max(max.y, v1.y, v2.y);
473
1412
  return { min, max };
474
1413
  }
1414
+ transform(matrix) {
1415
+ this.v1.applyMatrix3(matrix);
1416
+ this.v2.applyMatrix3(matrix);
1417
+ return this;
1418
+ }
475
1419
  drawTo(ctx) {
476
1420
  const { v1, v2 } = this;
477
1421
  ctx.moveTo(v1.x, v1.y);
478
1422
  ctx.lineTo(v2.x, v2.y);
1423
+ return this;
479
1424
  }
480
1425
  copy(source) {
481
1426
  super.copy(source);
@@ -558,6 +1503,7 @@ class HeartCurve extends Curve {
558
1503
  }
559
1504
  drawTo(ctx) {
560
1505
  this.curves.forEach((curve) => curve.drawTo(ctx));
1506
+ return this;
561
1507
  }
562
1508
  }
563
1509
 
@@ -620,6 +1566,7 @@ class PloygonCurve extends Curve {
620
1566
  }
621
1567
  drawTo(ctx) {
622
1568
  this.curves.forEach((curve) => curve.drawTo(ctx));
1569
+ return this;
623
1570
  }
624
1571
  }
625
1572
 
@@ -657,10 +1604,17 @@ class QuadraticBezierCurve extends Curve {
657
1604
  max.y = Math.max(max.y, v0.y, v2.y, y1, y2);
658
1605
  return { min, max };
659
1606
  }
1607
+ transform(matrix) {
1608
+ this.v0.applyMatrix3(matrix);
1609
+ this.v1.applyMatrix3(matrix);
1610
+ this.v2.applyMatrix3(matrix);
1611
+ return this;
1612
+ }
660
1613
  drawTo(ctx) {
661
1614
  const { v0, v1, v2 } = this;
662
1615
  ctx.moveTo(v0.x, v0.y);
663
1616
  ctx.quadraticCurveTo(v1.x, v1.y, v2.x, v2.y);
1617
+ return this;
664
1618
  }
665
1619
  copy(source) {
666
1620
  super.copy(source);
@@ -754,6 +1708,7 @@ class RectangularCurve extends Curve {
754
1708
  }
755
1709
  drawTo(ctx) {
756
1710
  this.curves.forEach((curve) => curve.drawTo(ctx));
1711
+ return this;
757
1712
  }
758
1713
  }
759
1714
 
@@ -780,11 +1735,6 @@ class SplineCurve extends Curve {
780
1735
  );
781
1736
  return output;
782
1737
  }
783
- getCommands() {
784
- return [];
785
- }
786
- drawTo(_ctx) {
787
- }
788
1738
  copy(source) {
789
1739
  super.copy(source);
790
1740
  this.points = [];
@@ -956,13 +1906,13 @@ class CurvePath extends Curve {
956
1906
  this.absellipse(x, y, radius, radius, startAngle, endAngle, clockwise);
957
1907
  return this;
958
1908
  }
959
- ellipse(x, y, xRadius, yRadius, startAngle, endAngle, clockwise = false, rotation = 0) {
1909
+ ellipse(x, y, radiusX, radiusY, startAngle, endAngle, clockwise = false, rotation = 0) {
960
1910
  const point = this.currentPoint;
961
- this.absellipse(x + point.x, y + point.y, xRadius, yRadius, startAngle, endAngle, clockwise, rotation);
1911
+ this.absellipse(x + point.x, y + point.y, radiusX, radiusY, startAngle, endAngle, clockwise, rotation);
962
1912
  return this;
963
1913
  }
964
- absellipse(x, y, xRadius, yRadius, startAngle, endAngle, clockwise = false, rotation = 0) {
965
- const curve = new EllipseCurve(x, y, xRadius, yRadius, startAngle, endAngle, clockwise, rotation);
1914
+ absellipse(x, y, radiusX, radiusY, startAngle, endAngle, clockwise = false, rotation = 0) {
1915
+ const curve = new EllipseCurve(x, y, radiusX, radiusY, startAngle, endAngle, clockwise, rotation);
966
1916
  if (this.curves.length > 0) {
967
1917
  const firstPoint = curve.getPoint(0);
968
1918
  if (!firstPoint.equals(this.currentPoint)) {
@@ -982,6 +1932,7 @@ class CurvePath extends Curve {
982
1932
  }
983
1933
  drawTo(ctx) {
984
1934
  this.curves.forEach((curve) => curve.drawTo(ctx));
1935
+ return this;
985
1936
  }
986
1937
  copy(source) {
987
1938
  super.copy(source);
@@ -1006,6 +1957,7 @@ class Path2D {
1006
1957
  constructor(path) {
1007
1958
  __publicField(this, "currentPath", new CurvePath());
1008
1959
  __publicField(this, "paths", [this.currentPath]);
1960
+ __publicField(this, "userData");
1009
1961
  if (path) {
1010
1962
  if (path instanceof Path2D) {
1011
1963
  this.addPath(path);
@@ -1017,38 +1969,13 @@ class Path2D {
1017
1969
  }
1018
1970
  }
1019
1971
  addPath(path) {
1020
- this.paths.push(...path.paths.map((v) => v.clone()));
1021
- return this;
1022
- }
1023
- addCommands(commands) {
1024
- for (let i = 0, len = commands.length; i < len; i++) {
1025
- const cmd = commands[i];
1026
- switch (cmd.type) {
1027
- case "M":
1028
- this.moveTo(cmd.x, cmd.y);
1029
- break;
1030
- case "L":
1031
- this.lineTo(cmd.x, cmd.y);
1032
- break;
1033
- case "C":
1034
- this.bezierCurveTo(cmd.x2, cmd.y2, cmd.x1, cmd.y1, cmd.x, cmd.y);
1035
- break;
1036
- case "Q":
1037
- this.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
1038
- break;
1039
- case "A":
1040
- break;
1041
- case "Z":
1042
- this.closePath();
1043
- break;
1044
- }
1972
+ if (path instanceof Path2D) {
1973
+ this.paths.push(...path.paths.map((v) => v.clone()));
1974
+ } else {
1975
+ this.paths.push(path);
1045
1976
  }
1046
1977
  return this;
1047
1978
  }
1048
- addData(data) {
1049
- console.error("TODO", data);
1050
- return this;
1051
- }
1052
1979
  closePath() {
1053
1980
  this.currentPath.closePath();
1054
1981
  return this;
@@ -1113,12 +2040,28 @@ class Path2D {
1113
2040
  this.currentPath.rect(x, y, w, h);
1114
2041
  return this;
1115
2042
  }
2043
+ addCommands(commands) {
2044
+ addPathCommandsToPath2D(commands, this);
2045
+ return this;
2046
+ }
2047
+ addData(data) {
2048
+ this.addCommands(pathDataToPathCommands(data));
2049
+ return this;
2050
+ }
1116
2051
  splineThru(points) {
1117
2052
  this.currentPath.splineThru(points);
1118
2053
  return this;
1119
2054
  }
2055
+ forEachCurve(cb) {
2056
+ this.paths.forEach((path) => path.curves.forEach((curve) => cb(curve)));
2057
+ return this;
2058
+ }
2059
+ transform(matrix) {
2060
+ this.forEachCurve((curve) => curve.transform(matrix));
2061
+ return this;
2062
+ }
1120
2063
  getMinMax(min = new Point2D(), max = new Point2D()) {
1121
- this.paths.forEach((path) => path.curves.forEach((curve) => curve.getMinMax(min, max)));
2064
+ this.forEachCurve((curve) => curve.getMinMax(min, max));
1122
2065
  return { min, max };
1123
2066
  }
1124
2067
  getCommands() {
@@ -1128,9 +2071,7 @@ class Path2D {
1128
2071
  return this.paths.map((path) => path.getData()).join(" ");
1129
2072
  }
1130
2073
  getBoundingBox() {
1131
- const min = Point2D.MAX;
1132
- const max = Point2D.MIN;
1133
- this.paths.forEach((path) => path.getMinMax(min, max));
2074
+ const { min, max } = this.getMinMax();
1134
2075
  return {
1135
2076
  x: min.x,
1136
2077
  y: min.y,
@@ -1146,10 +2087,8 @@ class Path2D {
1146
2087
  return `data:image/svg+xml;base64,${btoa(this.getSvgString())}`;
1147
2088
  }
1148
2089
  drawTo(ctx) {
1149
- this.paths.forEach((path) => {
1150
- path.curves.forEach((curve) => {
1151
- curve.drawTo(ctx);
1152
- });
2090
+ this.forEachCurve((curve) => {
2091
+ curve.drawTo(ctx);
1153
2092
  });
1154
2093
  }
1155
2094
  strokeTo(ctx) {
@@ -1162,4 +2101,511 @@ class Path2D {
1162
2101
  }
1163
2102
  }
1164
2103
 
1165
- export { CircleCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, HeartCurve, LineCurve, Path2D, PloygonCurve, Point2D, QuadraticBezierCurve, RectangularCurve, SplineCurve, catmullRom, cubicBezier, quadraticBezier };
2104
+ const defaultUnit = "px";
2105
+ const defaultDPI = 90;
2106
+ const units = ["mm", "cm", "in", "pt", "pc", "px"];
2107
+ const unitConversion = {
2108
+ mm: {
2109
+ mm: 1,
2110
+ cm: 0.1,
2111
+ in: 1 / 25.4,
2112
+ pt: 72 / 25.4,
2113
+ pc: 6 / 25.4,
2114
+ px: -1
2115
+ },
2116
+ cm: {
2117
+ mm: 10,
2118
+ cm: 1,
2119
+ in: 1 / 2.54,
2120
+ pt: 72 / 2.54,
2121
+ pc: 6 / 2.54,
2122
+ px: -1
2123
+ },
2124
+ in: {
2125
+ mm: 25.4,
2126
+ cm: 2.54,
2127
+ in: 1,
2128
+ pt: 72,
2129
+ pc: 6,
2130
+ px: -1
2131
+ },
2132
+ pt: {
2133
+ mm: 25.4 / 72,
2134
+ cm: 2.54 / 72,
2135
+ in: 1 / 72,
2136
+ pt: 1,
2137
+ pc: 6 / 72,
2138
+ px: -1
2139
+ },
2140
+ pc: {
2141
+ mm: 25.4 / 6,
2142
+ cm: 2.54 / 6,
2143
+ in: 1 / 6,
2144
+ pt: 72 / 6,
2145
+ pc: 1,
2146
+ px: -1
2147
+ },
2148
+ px: {
2149
+ px: 1
2150
+ }
2151
+ };
2152
+ function parseFloatWithUnits(string) {
2153
+ let theUnit = "px";
2154
+ if (typeof string === "string" || string instanceof String) {
2155
+ for (let i = 0, n = units.length; i < n; i++) {
2156
+ const u = units[i];
2157
+ if (string.endsWith(u)) {
2158
+ theUnit = u;
2159
+ string = string.substring(0, string.length - u.length);
2160
+ break;
2161
+ }
2162
+ }
2163
+ }
2164
+ let scale;
2165
+ if (theUnit === "px" && defaultUnit !== "px") {
2166
+ scale = unitConversion.in[defaultUnit] / defaultDPI;
2167
+ } else {
2168
+ scale = unitConversion[theUnit][defaultUnit];
2169
+ if (scale < 0) {
2170
+ scale = unitConversion[theUnit].in * defaultDPI;
2171
+ }
2172
+ }
2173
+ return scale * Number.parseFloat(string);
2174
+ }
2175
+
2176
+ const tempTransform0 = new Matrix3();
2177
+ const tempTransform1 = new Matrix3();
2178
+ const tempTransform2 = new Matrix3();
2179
+ const tempTransform3 = new Matrix3();
2180
+ function getNodeTransform(node, currentTransform, transformStack) {
2181
+ if (!(node.hasAttribute("transform") || node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y")))) {
2182
+ return null;
2183
+ }
2184
+ const transform = parseNodeTransform(node);
2185
+ if (transformStack.length > 0) {
2186
+ transform.premultiply(transformStack[transformStack.length - 1]);
2187
+ }
2188
+ currentTransform.copy(transform);
2189
+ transformStack.push(transform);
2190
+ return transform;
2191
+ }
2192
+ function parseNodeTransform(node) {
2193
+ const transform = new Matrix3();
2194
+ const currentTransform = tempTransform0;
2195
+ if (node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y"))) {
2196
+ transform.translate(
2197
+ parseFloatWithUnits(node.getAttribute("x")),
2198
+ parseFloatWithUnits(node.getAttribute("y"))
2199
+ );
2200
+ }
2201
+ if (node.hasAttribute("transform")) {
2202
+ const transformsTexts = node.getAttribute("transform").split(")");
2203
+ for (let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex--) {
2204
+ const transformText = transformsTexts[tIndex].trim();
2205
+ if (transformText === "")
2206
+ continue;
2207
+ const openParPos = transformText.indexOf("(");
2208
+ const closeParPos = transformText.length;
2209
+ if (openParPos > 0 && openParPos < closeParPos) {
2210
+ const transformType = transformText.slice(0, openParPos);
2211
+ const array = parsePathDataArgs(transformText.slice(openParPos + 1));
2212
+ currentTransform.identity();
2213
+ switch (transformType) {
2214
+ case "translate":
2215
+ if (array.length >= 1) {
2216
+ const tx = array[0];
2217
+ let ty = 0;
2218
+ if (array.length >= 2) {
2219
+ ty = array[1];
2220
+ }
2221
+ currentTransform.translate(tx, ty);
2222
+ }
2223
+ break;
2224
+ case "rotate":
2225
+ if (array.length >= 1) {
2226
+ let angle = 0;
2227
+ let cx = 0;
2228
+ let cy = 0;
2229
+ angle = array[0] * Math.PI / 180;
2230
+ if (array.length >= 3) {
2231
+ cx = array[1];
2232
+ cy = array[2];
2233
+ }
2234
+ tempTransform1.makeTranslation(-cx, -cy);
2235
+ tempTransform2.makeRotation(angle);
2236
+ tempTransform3.multiplyMatrices(tempTransform2, tempTransform1);
2237
+ tempTransform1.makeTranslation(cx, cy);
2238
+ currentTransform.multiplyMatrices(tempTransform1, tempTransform3);
2239
+ }
2240
+ break;
2241
+ case "scale":
2242
+ if (array.length >= 1) {
2243
+ currentTransform.scale(
2244
+ array[0],
2245
+ array[1] ?? array[0]
2246
+ );
2247
+ }
2248
+ break;
2249
+ case "skewX":
2250
+ if (array.length === 1) {
2251
+ currentTransform.set(
2252
+ 1,
2253
+ Math.tan(array[0] * Math.PI / 180),
2254
+ 0,
2255
+ 0,
2256
+ 1,
2257
+ 0,
2258
+ 0,
2259
+ 0,
2260
+ 1
2261
+ );
2262
+ }
2263
+ break;
2264
+ case "skewY":
2265
+ if (array.length === 1) {
2266
+ currentTransform.set(
2267
+ 1,
2268
+ 0,
2269
+ 0,
2270
+ Math.tan(array[0] * Math.PI / 180),
2271
+ 1,
2272
+ 0,
2273
+ 0,
2274
+ 0,
2275
+ 1
2276
+ );
2277
+ }
2278
+ break;
2279
+ case "matrix":
2280
+ if (array.length === 6) {
2281
+ currentTransform.set(
2282
+ array[0],
2283
+ array[2],
2284
+ array[4],
2285
+ array[1],
2286
+ array[3],
2287
+ array[5],
2288
+ 0,
2289
+ 0,
2290
+ 1
2291
+ );
2292
+ }
2293
+ break;
2294
+ }
2295
+ }
2296
+ transform.premultiply(currentTransform);
2297
+ }
2298
+ }
2299
+ return transform;
2300
+ }
2301
+
2302
+ function parseCircleNode(node) {
2303
+ return new Path2D().addPath(
2304
+ new CurvePath().absarc(
2305
+ parseFloatWithUnits(node.getAttribute("cx") || 0),
2306
+ parseFloatWithUnits(node.getAttribute("cy") || 0),
2307
+ parseFloatWithUnits(node.getAttribute("r") || 0),
2308
+ 0,
2309
+ Math.PI * 2
2310
+ )
2311
+ );
2312
+ }
2313
+
2314
+ function parseCSSStylesheet(node, stylesheets) {
2315
+ if (!node.sheet || !node.sheet.cssRules || !node.sheet.cssRules.length)
2316
+ return;
2317
+ for (let i = 0; i < node.sheet.cssRules.length; i++) {
2318
+ const stylesheet = node.sheet.cssRules[i];
2319
+ if (stylesheet.type !== 1)
2320
+ continue;
2321
+ const selectorList = stylesheet.selectorText.split(/,/g).filter(Boolean).map((i2) => i2.trim());
2322
+ for (let j = 0; j < selectorList.length; j++) {
2323
+ const definitions = Object.fromEntries(
2324
+ Object.entries(stylesheet.style).filter(([, v]) => v !== "")
2325
+ );
2326
+ stylesheets[selectorList[j]] = Object.assign(
2327
+ stylesheets[selectorList[j]] || {},
2328
+ definitions
2329
+ );
2330
+ }
2331
+ }
2332
+ }
2333
+
2334
+ function parseEllipseNode(node) {
2335
+ return new Path2D().addPath(
2336
+ new CurvePath().absellipse(
2337
+ parseFloatWithUnits(node.getAttribute("cx") || 0),
2338
+ parseFloatWithUnits(node.getAttribute("cy") || 0),
2339
+ parseFloatWithUnits(node.getAttribute("rx") || 0),
2340
+ parseFloatWithUnits(node.getAttribute("ry") || 0),
2341
+ 0,
2342
+ Math.PI * 2
2343
+ )
2344
+ );
2345
+ }
2346
+
2347
+ function parseLineNode(node) {
2348
+ return new Path2D().moveTo(
2349
+ parseFloatWithUnits(node.getAttribute("x1") || 0),
2350
+ parseFloatWithUnits(node.getAttribute("y1") || 0)
2351
+ ).lineTo(
2352
+ parseFloatWithUnits(node.getAttribute("x2") || 0),
2353
+ parseFloatWithUnits(node.getAttribute("y2") || 0)
2354
+ );
2355
+ }
2356
+
2357
+ function parsePathNode(node) {
2358
+ const path = new Path2D();
2359
+ const d = node.getAttribute("d");
2360
+ if (!d || d === "none")
2361
+ return null;
2362
+ path.addData(d);
2363
+ return path;
2364
+ }
2365
+
2366
+ const RE$1 = /([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)(?:,|\s)([+-]?\d*\.?\d+(?:e[+-]?\d+)?)/g;
2367
+ function parsePolygonNode(node) {
2368
+ const path = new Path2D();
2369
+ let index = 0;
2370
+ node.getAttribute("points")?.replace(RE$1, (match, a, b) => {
2371
+ const x = parseFloatWithUnits(a);
2372
+ const y = parseFloatWithUnits(b);
2373
+ if (index === 0) {
2374
+ path.moveTo(x, y);
2375
+ } else {
2376
+ path.lineTo(x, y);
2377
+ }
2378
+ index++;
2379
+ return match;
2380
+ });
2381
+ path.currentPath.autoClose = true;
2382
+ return path;
2383
+ }
2384
+
2385
+ const RE = /([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)(?:,|\s)([+-]?\d*\.?\d+(?:e[+-]?\d+)?)/g;
2386
+ function parsePolylineNode(node) {
2387
+ const path = new Path2D();
2388
+ let index = 0;
2389
+ node.getAttribute("points")?.replace(RE, (match, a, b) => {
2390
+ const x = parseFloatWithUnits(a);
2391
+ const y = parseFloatWithUnits(b);
2392
+ if (index === 0) {
2393
+ path.moveTo(x, y);
2394
+ } else {
2395
+ path.lineTo(x, y);
2396
+ }
2397
+ index++;
2398
+ return match;
2399
+ });
2400
+ path.currentPath.autoClose = false;
2401
+ return path;
2402
+ }
2403
+
2404
+ function parseRectNode(node) {
2405
+ const x = parseFloatWithUnits(node.getAttribute("x") || 0);
2406
+ const y = parseFloatWithUnits(node.getAttribute("y") || 0);
2407
+ const rx = parseFloatWithUnits(node.getAttribute("rx") || node.getAttribute("ry") || 0);
2408
+ const ry = parseFloatWithUnits(node.getAttribute("ry") || node.getAttribute("rx") || 0);
2409
+ const w = parseFloatWithUnits(node.getAttribute("width"));
2410
+ const h = parseFloatWithUnits(node.getAttribute("height"));
2411
+ const bci = 1 - 0.551915024494;
2412
+ const path = new Path2D();
2413
+ path.moveTo(x + rx, y);
2414
+ path.lineTo(x + w - rx, y);
2415
+ if (rx !== 0 || ry !== 0) {
2416
+ path.bezierCurveTo(
2417
+ x + w - rx * bci,
2418
+ y,
2419
+ x + w,
2420
+ y + ry * bci,
2421
+ x + w,
2422
+ y + ry
2423
+ );
2424
+ }
2425
+ path.lineTo(x + w, y + h - ry);
2426
+ if (rx !== 0 || ry !== 0) {
2427
+ path.bezierCurveTo(
2428
+ x + w,
2429
+ y + h - ry * bci,
2430
+ x + w - rx * bci,
2431
+ y + h,
2432
+ x + w - rx,
2433
+ y + h
2434
+ );
2435
+ }
2436
+ path.lineTo(x + rx, y + h);
2437
+ if (rx !== 0 || ry !== 0) {
2438
+ path.bezierCurveTo(
2439
+ x + rx * bci,
2440
+ y + h,
2441
+ x,
2442
+ y + h - ry * bci,
2443
+ x,
2444
+ y + h - ry
2445
+ );
2446
+ }
2447
+ path.lineTo(x, y + ry);
2448
+ if (rx !== 0 || ry !== 0) {
2449
+ path.bezierCurveTo(x, y + ry * bci, x + rx * bci, y, x + rx, y);
2450
+ }
2451
+ return path;
2452
+ }
2453
+
2454
+ function parseStyle(node, style, stylesheets) {
2455
+ style = Object.assign({}, style);
2456
+ let stylesheetStyles = {};
2457
+ if (node.hasAttribute("class")) {
2458
+ const classSelectors = node.getAttribute("class").split(/\s/).filter(Boolean).map((i) => i.trim());
2459
+ for (let i = 0; i < classSelectors.length; i++) {
2460
+ stylesheetStyles = Object.assign(stylesheetStyles, stylesheets[`.${classSelectors[i]}`]);
2461
+ }
2462
+ }
2463
+ if (node.hasAttribute("id")) {
2464
+ stylesheetStyles = Object.assign(stylesheetStyles, stylesheets[`#${node.getAttribute("id")}`]);
2465
+ }
2466
+ function addStyle(svgName, jsName, adjustFunction) {
2467
+ if (adjustFunction === void 0) {
2468
+ adjustFunction = function copy(v) {
2469
+ if (v.startsWith("url"))
2470
+ console.warn("url access in attributes is not implemented.");
2471
+ return v;
2472
+ };
2473
+ }
2474
+ if (node.hasAttribute(svgName))
2475
+ style[jsName] = adjustFunction(node.getAttribute(svgName));
2476
+ if (stylesheetStyles[svgName])
2477
+ style[jsName] = adjustFunction(stylesheetStyles[svgName]);
2478
+ if (node.style && node.style[svgName] !== "")
2479
+ style[jsName] = adjustFunction(node.style[svgName]);
2480
+ }
2481
+ function clamp(v) {
2482
+ return Math.max(0, Math.min(1, parseFloatWithUnits(v)));
2483
+ }
2484
+ function positive(v) {
2485
+ return Math.max(0, parseFloatWithUnits(v));
2486
+ }
2487
+ addStyle("fill", "fill");
2488
+ addStyle("fill-opacity", "fillOpacity", clamp);
2489
+ addStyle("fill-rule", "fillRule");
2490
+ addStyle("opacity", "opacity", clamp);
2491
+ addStyle("stroke", "stroke");
2492
+ addStyle("stroke-dashoffset", "strokeDashoffset");
2493
+ addStyle("stroke-dasharray", "strokeDasharray");
2494
+ addStyle("stroke-linecap", "strokeLineCap");
2495
+ addStyle("stroke-linejoin", "strokeLineJoin");
2496
+ addStyle("stroke-miterlimit", "strokeMiterLimit", positive);
2497
+ addStyle("stroke-opacity", "strokeOpacity", clamp);
2498
+ addStyle("stroke-width", "strokeWidth", positive);
2499
+ addStyle("visibility", "visibility");
2500
+ return style;
2501
+ }
2502
+
2503
+ function parseNode(node, style, paths = []) {
2504
+ if (node.nodeType !== 1)
2505
+ return paths;
2506
+ let isDefsNode = false;
2507
+ let path = null;
2508
+ const stylesheets = {};
2509
+ switch (node.nodeName) {
2510
+ case "svg":
2511
+ style = parseStyle(node, style, stylesheets);
2512
+ break;
2513
+ case "style":
2514
+ parseCSSStylesheet(node, stylesheets);
2515
+ break;
2516
+ case "g":
2517
+ style = parseStyle(node, style, stylesheets);
2518
+ break;
2519
+ case "path":
2520
+ style = parseStyle(node, style, stylesheets);
2521
+ if (node.hasAttribute("d"))
2522
+ path = parsePathNode(node);
2523
+ break;
2524
+ case "rect":
2525
+ style = parseStyle(node, style, stylesheets);
2526
+ path = parseRectNode(node);
2527
+ break;
2528
+ case "polygon":
2529
+ style = parseStyle(node, style, stylesheets);
2530
+ path = parsePolygonNode(node);
2531
+ break;
2532
+ case "polyline":
2533
+ style = parseStyle(node, style, stylesheets);
2534
+ path = parsePolylineNode(node);
2535
+ break;
2536
+ case "circle":
2537
+ style = parseStyle(node, style, stylesheets);
2538
+ path = parseCircleNode(node);
2539
+ break;
2540
+ case "ellipse":
2541
+ style = parseStyle(node, style, stylesheets);
2542
+ path = parseEllipseNode(node);
2543
+ break;
2544
+ case "line":
2545
+ style = parseStyle(node, style, stylesheets);
2546
+ path = parseLineNode(node);
2547
+ break;
2548
+ case "defs":
2549
+ isDefsNode = true;
2550
+ break;
2551
+ case "use": {
2552
+ style = parseStyle(node, style, stylesheets);
2553
+ const href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href") || "";
2554
+ const usedNodeId = href.substring(1);
2555
+ const usedNode = node.viewportElement?.getElementById(usedNodeId);
2556
+ if (usedNode) {
2557
+ parseNode(usedNode, style, paths);
2558
+ } else {
2559
+ console.warn(`'use node' references non-existent node id: ${usedNodeId}`);
2560
+ }
2561
+ break;
2562
+ }
2563
+ default:
2564
+ console.warn(node);
2565
+ break;
2566
+ }
2567
+ const currentTransform = new Matrix3();
2568
+ const transformStack = [];
2569
+ const transform = getNodeTransform(node, currentTransform, transformStack);
2570
+ if (path) {
2571
+ path.transform(currentTransform);
2572
+ paths.push(path);
2573
+ path.userData = { node, style };
2574
+ }
2575
+ const childNodes = node.childNodes;
2576
+ for (let i = 0, len = childNodes.length; i < len; i++) {
2577
+ const node2 = childNodes[i];
2578
+ if (isDefsNode && node2.nodeName !== "style" && node2.nodeName !== "defs")
2579
+ continue;
2580
+ parseNode(node2, style, paths);
2581
+ }
2582
+ if (transform) {
2583
+ transformStack.pop();
2584
+ if (transformStack.length > 0) {
2585
+ currentTransform.copy(transformStack[transformStack.length - 1]);
2586
+ } else {
2587
+ currentTransform.identity();
2588
+ }
2589
+ }
2590
+ return paths;
2591
+ }
2592
+
2593
+ function parseSvg(svg) {
2594
+ let node;
2595
+ if (typeof svg === "string") {
2596
+ node = new DOMParser().parseFromString(svg, "image/svg+xml").documentElement;
2597
+ } else {
2598
+ node = svg;
2599
+ }
2600
+ return parseNode(node, {
2601
+ fill: "#000",
2602
+ fillOpacity: 1,
2603
+ strokeOpacity: 1,
2604
+ strokeWidth: 1,
2605
+ strokeLineJoin: "miter",
2606
+ strokeLineCap: "butt",
2607
+ strokeMiterLimit: 4
2608
+ });
2609
+ }
2610
+
2611
+ export { CircleCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, HeartCurve, LineCurve, Matrix3, Path2D, PloygonCurve, Point2D, QuadraticBezierCurve, RectangularCurve, SplineCurve, parseSvg };