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