svg-path-commander 0.1.25 → 0.2.0-alpha3

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.
Files changed (71) hide show
  1. package/README.md +5 -3
  2. package/dist/svg-path-commander.es5.js +3948 -0
  3. package/dist/svg-path-commander.es5.min.js +2 -0
  4. package/dist/svg-path-commander.esm.js +425 -404
  5. package/dist/svg-path-commander.esm.min.js +2 -2
  6. package/dist/svg-path-commander.js +1432 -1513
  7. package/dist/svg-path-commander.min.js +2 -2
  8. package/package.json +28 -12
  9. package/src/convert/pathToAbsolute.js +4 -4
  10. package/src/convert/pathToCurve.js +2 -2
  11. package/src/convert/pathToRelative.js +4 -4
  12. package/src/convert/pathToString.js +2 -2
  13. package/src/math/polygonLength.js +1 -2
  14. package/src/options/options.js +1 -1
  15. package/src/parser/error.js +2 -0
  16. package/src/parser/finalizeSegment.js +1 -1
  17. package/src/parser/paramsParser.js +1 -1
  18. package/src/parser/parsePathString.js +6 -11
  19. package/src/parser/pathParser.js +1 -1
  20. package/src/parser/scanFlag.js +3 -3
  21. package/src/parser/scanParam.js +7 -6
  22. package/src/parser/scanSegment.js +3 -2
  23. package/src/parser/skipSpaces.js +1 -1
  24. package/src/process/clonePath.js +1 -1
  25. package/src/process/fixArc.js +1 -1
  26. package/src/process/fixPath.js +2 -2
  27. package/src/process/getSVGMatrix.js +3 -2
  28. package/src/process/normalizePath.js +3 -3
  29. package/src/process/normalizeSegment.js +2 -2
  30. package/src/process/optimizePath.js +2 -2
  31. package/src/process/projection2d.js +2 -2
  32. package/src/process/reverseCurve.js +3 -3
  33. package/src/process/reversePath.js +4 -5
  34. package/src/process/roundPath.js +7 -6
  35. package/src/process/segmentToCubic.js +3 -3
  36. package/src/process/shortenSegment.js +3 -3
  37. package/src/process/splitCubic.js +1 -1
  38. package/src/process/splitPath.js +1 -1
  39. package/src/process/transformPath.js +8 -7
  40. package/src/svg-path-commander.js +60 -20
  41. package/src/util/getClosestPoint.js +1 -1
  42. package/src/util/getCubicSize.js +1 -1
  43. package/src/util/getDrawDirection.js +1 -1
  44. package/src/util/getPathArea.js +1 -1
  45. package/src/util/getPathBBox.js +2 -2
  46. package/src/util/getPathLength.js +1 -1
  47. package/src/util/getPointAtLength.js +1 -1
  48. package/src/util/getPropertiesAtLength.js +3 -3
  49. package/src/util/getPropertiesAtPoint.js +2 -2
  50. package/src/util/getSegmentAtLength.js +2 -2
  51. package/src/util/getSegmentOfPoint.js +2 -2
  52. package/src/util/getTotalLength.js +1 -1
  53. package/src/util/isAbsoluteArray.js +1 -1
  54. package/src/util/isCurveArray.js +1 -1
  55. package/src/util/isNormalizedArray.js +1 -1
  56. package/src/util/isPathArray.js +1 -1
  57. package/src/util/isPointInStroke.js +2 -2
  58. package/src/util/isRelativeArray.js +1 -1
  59. package/src/util/pathLengthFactory.js +3 -2
  60. package/src/util/segmentArcFactory.js +1 -1
  61. package/src/util/segmentCubicFactory.js +1 -1
  62. package/src/util/segmentLineFactory.js +1 -1
  63. package/src/util/segmentQuadFactory.js +1 -1
  64. package/src/util/shapeToPath.js +13 -13
  65. package/src/util/util.js +0 -2
  66. package/types/index.d.ts +1 -3
  67. package/types/more/modules.ts +0 -3
  68. package/types/more/svg.d.ts +11 -10
  69. package/types/svg-path-commander.d.ts +214 -226
  70. package/src/util/createPath.js +0 -17
  71. package/src/util/getPointAtPathLength.js +0 -15
@@ -1,11 +1,11 @@
1
1
  /*!
2
- * SVGPathCommander v0.1.25 (http://thednp.github.io/svg-path-commander)
2
+ * SVGPathCommander v0.2.0alpha3 (http://thednp.github.io/svg-path-commander)
3
3
  * Copyright 2022 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/svg-path-commander/blob/master/LICENSE)
5
5
  */
6
6
  /**
7
7
  * SVGPathCommander default options
8
- * @type {SVGPathCommander.options}
8
+ * @type {SVGPath.options}
9
9
  */
10
10
  const defaultOptions = {
11
11
  origin: [0, 0, 0],
@@ -23,7 +23,7 @@ const paramsCount = {
23
23
  /**
24
24
  * Breaks the parsing of a pathString once a segment is finalized.
25
25
  *
26
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
26
+ * @param {SVGPath.PathParser} path the `PathParser` instance
27
27
  */
28
28
  function finalizeSegment(path) {
29
29
  let pathCommand = path.pathValue[path.segmentStart];
@@ -51,13 +51,13 @@ function finalizeSegment(path) {
51
51
  }
52
52
  }
53
53
 
54
- const invalidPathValue = 'Invalid path value';
54
+ const error = 'SVGPathCommander error';
55
55
 
56
56
  /**
57
57
  * Validates an A (arc-to) specific path command value.
58
58
  * Usually a `large-arc-flag` or `sweep-flag`.
59
59
  *
60
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
60
+ * @param {SVGPath.PathParser} path the `PathParser` instance
61
61
  */
62
62
  function scanFlag(path) {
63
63
  const { index } = path;
@@ -75,7 +75,7 @@ function scanFlag(path) {
75
75
  return;
76
76
  }
77
77
 
78
- path.err = `${invalidPathValue}: invalid Arc flag "${ch}", expecting 0 or 1 at index ${index}`;
78
+ path.err = `${error}: invalid Arc flag "${ch}", expecting 0 or 1 at index ${index}`;
79
79
  }
80
80
 
81
81
  /**
@@ -88,11 +88,13 @@ function isDigit(code) {
88
88
  return (code >= 48 && code <= 57); // 0..9
89
89
  }
90
90
 
91
+ const invalidPathValue = 'Invalid path value';
92
+
91
93
  /**
92
94
  * Validates every character of the path string,
93
95
  * every path command, negative numbers or floating point numbers.
94
96
  *
95
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
97
+ * @param {SVGPath.PathParser} path the `PathParser` instance
96
98
  */
97
99
  function scanParam(path) {
98
100
  const { max, pathValue, index: start } = path;
@@ -105,7 +107,7 @@ function scanParam(path) {
105
107
 
106
108
  if (index >= max) {
107
109
  // path.err = 'SvgPath: missed param (at pos ' + index + ')';
108
- path.err = `${invalidPathValue} at ${index}: missing param ${pathValue[index]}`;
110
+ path.err = `${error}: ${invalidPathValue} at index ${index}, "pathValue" is missing param`;
109
111
  return;
110
112
  }
111
113
  ch = pathValue.charCodeAt(index);
@@ -119,7 +121,7 @@ function scanParam(path) {
119
121
  // https://github.com/ariya/esprimas
120
122
  if (!isDigit(ch) && ch !== 0x2E/* . */) {
121
123
  // path.err = 'SvgPath: param should start with 0..9 or `.` (at pos ' + index + ')';
122
- path.err = `${invalidPathValue} at index ${index}: ${pathValue[index]} is not a number`;
124
+ path.err = `${error}: ${invalidPathValue} at index ${index}, "${pathValue[index]}" is not a number`;
123
125
  return;
124
126
  }
125
127
 
@@ -134,7 +136,7 @@ function scanParam(path) {
134
136
  if (ch && isDigit(ch)) {
135
137
  // path.err = 'SvgPath: numbers started with `0` such as `09`
136
138
  // are illegal (at pos ' + start + ')';
137
- path.err = `${invalidPathValue} at index ${start}: ${pathValue[start]} illegal number`;
139
+ path.err = `${error}: ${invalidPathValue} at index ${start}, "${pathValue[start]}" illegal number`;
138
140
  return;
139
141
  }
140
142
  }
@@ -158,7 +160,7 @@ function scanParam(path) {
158
160
 
159
161
  if (ch === 0x65/* e */ || ch === 0x45/* E */) {
160
162
  if (hasDot && !hasCeiling && !hasDecimal) {
161
- path.err = `${invalidPathValue} at index ${index}: ${pathValue[index]} invalid float exponent`;
163
+ path.err = `${error}: ${invalidPathValue} at index ${index}, "${pathValue[index]}" invalid float exponent`;
162
164
  return;
163
165
  }
164
166
 
@@ -174,7 +176,7 @@ function scanParam(path) {
174
176
  }
175
177
  } else {
176
178
  // path.err = 'SvgPath: invalid float exponent (at pos ' + index + ')';
177
- path.err = `${invalidPathValue} at index ${index}: ${pathValue[index]} invalid float exponent`;
179
+ path.err = `${error}: ${invalidPathValue} at index ${index}: "${pathValue[index]}" invalid float exponent`;
178
180
  return;
179
181
  }
180
182
  }
@@ -204,7 +206,7 @@ function isSpace(ch) {
204
206
  * path string every time it encounters any kind of
205
207
  * space character.
206
208
  *
207
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
209
+ * @param {SVGPath.PathParser} path the `PathParser` instance
208
210
  */
209
211
  function skipSpaces(path) {
210
212
  const { pathValue, max } = path;
@@ -268,7 +270,7 @@ function isArcCommand(code) {
268
270
  * Scans every character in the path string to determine
269
271
  * where a segment starts and where it ends.
270
272
  *
271
- * @param {SVGPathCommander.PathParser} path the `PathParser` instance
273
+ * @param {SVGPath.PathParser} path the `PathParser` instance
272
274
  */
273
275
  function scanSegment(path) {
274
276
  const { max, pathValue, index } = path;
@@ -278,7 +280,7 @@ function scanSegment(path) {
278
280
  path.segmentStart = index;
279
281
 
280
282
  if (!isPathCommand(cmdCode)) {
281
- path.err = `${invalidPathValue}: ${pathValue[index]} not a path command`;
283
+ path.err = `${error}: ${invalidPathValue} "${pathValue[index]}" is not a path command`;
282
284
  return;
283
285
  }
284
286
 
@@ -328,7 +330,7 @@ function scanSegment(path) {
328
330
  /**
329
331
  * Returns a clone of an existing `pathArray`.
330
332
  *
331
- * @param {SVGPathCommander.pathArray | SVGPathCommander.pathSegment} path the source `pathArray`
333
+ * @param {SVGPath.pathArray | SVGPath.pathSegment} path the source `pathArray`
332
334
  * @returns {any} the cloned `pathArray`
333
335
  */
334
336
  function clonePath(path) {
@@ -342,7 +344,7 @@ function clonePath(path) {
342
344
  * @param {string} pathString
343
345
  */
344
346
  function PathParser(pathString) {
345
- /** @type {SVGPathCommander.pathArray} */
347
+ /** @type {SVGPath.pathArray} */
346
348
  // @ts-ignore
347
349
  this.segments = [];
348
350
  /** @type {string} */
@@ -364,7 +366,7 @@ function PathParser(pathString) {
364
366
  /**
365
367
  * Iterates an array to check if it's an actual `pathArray`.
366
368
  *
367
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
369
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
368
370
  * @returns {boolean} iteration result
369
371
  */
370
372
  function isPathArray(path) {
@@ -378,8 +380,8 @@ function isPathArray(path) {
378
380
  * Parses a path string value and returns an array
379
381
  * of segments we like to call `pathArray`.
380
382
  *
381
- * @param {SVGPathCommander.pathArray | string} pathInput the string to be parsed
382
- * @returns {SVGPathCommander.pathArray} the resulted `pathArray`
383
+ * @param {SVGPath.pathArray | string} pathInput the string to be parsed
384
+ * @returns {SVGPath.pathArray | string} the resulted `pathArray`
383
385
  */
384
386
  function parsePathString(pathInput) {
385
387
  if (isPathArray(pathInput)) {
@@ -396,27 +398,22 @@ function parsePathString(pathInput) {
396
398
  scanSegment(path);
397
399
  }
398
400
 
399
- if (path.err.length) {
400
- // @ts-ignore
401
- path.segments = [];
402
- } else if (path.segments.length) {
401
+ if (!path.err.length) {
403
402
  if (!'mM'.includes(path.segments[0][0])) {
404
- path.err = `${invalidPathValue}: missing M/m`;
405
- // @ts-ignore
406
- path.segments = [];
403
+ path.err = `${error}: missing M/m`;
407
404
  } else {
408
405
  path.segments[0][0] = 'M';
409
406
  }
410
407
  }
411
408
 
412
- return path.segments;
409
+ return path.err ? path.err : path.segments;
413
410
  }
414
411
 
415
412
  /**
416
413
  * Iterates an array to check if it's a `pathArray`
417
414
  * with all absolute values.
418
415
  *
419
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
416
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
420
417
  * @returns {boolean} iteration result
421
418
  */
422
419
  function isAbsoluteArray(path) {
@@ -429,8 +426,8 @@ function isAbsoluteArray(path) {
429
426
  * Parses a path string value or object and returns an array
430
427
  * of segments, all converted to absolute values.
431
428
  *
432
- * @param {string | SVGPathCommander.pathArray} pathInput the path string | object
433
- * @returns {SVGPathCommander.absoluteArray} the resulted `pathArray` with absolute values
429
+ * @param {string | SVGPath.pathArray} pathInput the path string | object
430
+ * @returns {SVGPath.absoluteArray} the resulted `pathArray` with absolute values
434
431
  */
435
432
  function pathToAbsolute(pathInput) {
436
433
  if (isAbsoluteArray(pathInput)) {
@@ -446,7 +443,7 @@ function pathToAbsolute(pathInput) {
446
443
  return path.map((segment) => {
447
444
  const values = segment.slice(1).map(Number);
448
445
  const [pathCommand] = segment;
449
- /** @type {SVGPathCommander.absoluteCommand} */
446
+ /** @type {SVGPath.absoluteCommand} */
450
447
  // @ts-ignore
451
448
  const absCommand = pathCommand.toUpperCase();
452
449
 
@@ -456,7 +453,7 @@ function pathToAbsolute(pathInput) {
456
453
  my = y;
457
454
  return ['M', x, y];
458
455
  }
459
- /** @type {SVGPathCommander.absoluteSegment} */
456
+ /** @type {SVGPath.absoluteSegment} */
460
457
  // @ts-ignore
461
458
  let absoluteSegment = [];
462
459
 
@@ -519,7 +516,7 @@ function pathToAbsolute(pathInput) {
519
516
  * Iterates an array to check if it's a `pathArray`
520
517
  * with relative values.
521
518
  *
522
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
519
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
523
520
  * @returns {boolean} iteration result
524
521
  */
525
522
  function isRelativeArray(path) {
@@ -532,8 +529,8 @@ function isRelativeArray(path) {
532
529
  * Parses a path string value or object and returns an array
533
530
  * of segments, all converted to relative values.
534
531
  *
535
- * @param {string | SVGPathCommander.pathArray} pathInput the path string | object
536
- * @returns {SVGPathCommander.relativeArray} the resulted `pathArray` with relative values
532
+ * @param {string | SVGPath.pathArray} pathInput the path string | object
533
+ * @returns {SVGPath.relativeArray} the resulted `pathArray` with relative values
537
534
  */
538
535
  function pathToRelative(pathInput) {
539
536
  if (isRelativeArray(pathInput)) {
@@ -549,7 +546,7 @@ function pathToRelative(pathInput) {
549
546
  return path.map((segment) => {
550
547
  const values = segment.slice(1).map(Number);
551
548
  const [pathCommand] = segment;
552
- /** @type {SVGPathCommander.relativeCommand} */
549
+ /** @type {SVGPath.relativeCommand} */
553
550
  // @ts-ignore
554
551
  const relativeCommand = pathCommand.toLowerCase();
555
552
 
@@ -560,7 +557,7 @@ function pathToRelative(pathInput) {
560
557
  return ['M', x, y];
561
558
  }
562
559
 
563
- /** @type {SVGPathCommander.relativeSegment} */
560
+ /** @type {SVGPath.relativeSegment} */
564
561
  // @ts-ignore -- trust me DON'T CHANGE
565
562
  let relativeSegment = [];
566
563
 
@@ -627,7 +624,7 @@ function pathToRelative(pathInput) {
627
624
  /**
628
625
  * Splits an extended A (arc-to) segment into two cubic-bezier segments.
629
626
  *
630
- * @param {SVGPathCommander.pathArray} path the `pathArray` this segment belongs to
627
+ * @param {SVGPath.pathArray} path the `pathArray` this segment belongs to
631
628
  * @param {string[]} allPathCommands all previous path commands
632
629
  * @param {number} i the segment index
633
630
  */
@@ -684,10 +681,10 @@ function shorthandToCubic(x1, y1, x2, y2, prevCommand) {
684
681
  /**
685
682
  * Normalizes a single segment of a `pathArray` object.
686
683
  *
687
- * @param {SVGPathCommander.pathSegment} segment the segment object
684
+ * @param {SVGPath.pathSegment} segment the segment object
688
685
  * @param {any} params the coordinates of the previous segment
689
686
  * @param {string} prevCommand the path command of the previous segment
690
- * @returns {SVGPathCommander.normalSegment} the normalized segment
687
+ * @returns {SVGPath.normalSegment} the normalized segment
691
688
  */
692
689
  function normalizeSegment(segment, params, prevCommand) {
693
690
  const [pathCommand] = segment;
@@ -734,7 +731,7 @@ function normalizeSegment(segment, params, prevCommand) {
734
731
  * with all segments are in non-shorthand notation
735
732
  * with absolute values.
736
733
  *
737
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to be checked
734
+ * @param {string | SVGPath.pathArray} path the `pathArray` to be checked
738
735
  * @returns {boolean} iteration result
739
736
  */
740
737
  function isNormalizedArray(path) {
@@ -743,7 +740,7 @@ function isNormalizedArray(path) {
743
740
  }
744
741
 
745
742
  /**
746
- * @type {SVGPathCommander.parserParams}
743
+ * @type {SVGPath.parserParams}
747
744
  */
748
745
  const paramsParser = {
749
746
  x1: 0, y1: 0, x2: 0, y2: 0, x: 0, y: 0, qx: null, qy: null,
@@ -754,8 +751,8 @@ const paramsParser = {
754
751
  * * convert segments to absolute values
755
752
  * * convert shorthand path commands to their non-shorthand notation
756
753
  *
757
- * @param {string | SVGPathCommander.pathArray} pathInput the string to be parsed or 'pathArray'
758
- * @returns {SVGPathCommander.normalArray} the normalized `pathArray`
754
+ * @param {string | SVGPath.pathArray} pathInput the string to be parsed or 'pathArray'
755
+ * @returns {SVGPath.normalArray} the normalized `pathArray`
759
756
  */
760
757
  function normalizePath(pathInput) {
761
758
  if (isNormalizedArray(pathInput)) {
@@ -763,7 +760,7 @@ function normalizePath(pathInput) {
763
760
  return clonePath(pathInput);
764
761
  }
765
762
 
766
- /** @type {SVGPathCommander.normalArray} */
763
+ /** @type {SVGPath.normalArray} */
767
764
  // @ts-ignore -- `absoluteArray` will become a `normalArray`
768
765
  const path = pathToAbsolute(pathInput);
769
766
  const params = { ...paramsParser };
@@ -804,8 +801,8 @@ function normalizePath(pathInput) {
804
801
  * use `splitPath` first and apply this utility on each
805
802
  * sub-path separately.
806
803
  *
807
- * @param {SVGPathCommander.pathArray | string} pathInput the `pathArray` source
808
- * @return {SVGPathCommander.pathArray} a fixed `pathArray`
804
+ * @param {SVGPath.pathArray | string} pathInput the `pathArray` source
805
+ * @return {SVGPath.pathArray} a fixed `pathArray`
809
806
  */
810
807
  function fixPath(pathInput) {
811
808
  const pathArray = parsePathString(pathInput);
@@ -828,7 +825,7 @@ function fixPath(pathInput) {
828
825
  * Iterates an array to check if it's a `pathArray`
829
826
  * with all C (cubic bezier) segments.
830
827
  *
831
- * @param {string | SVGPathCommander.pathArray} path the `Array` to be checked
828
+ * @param {string | SVGPath.pathArray} path the `Array` to be checked
832
829
  * @returns {boolean} iteration result
833
830
  */
834
831
  function isCurveArray(path) {
@@ -1017,7 +1014,7 @@ function distanceSquareRoot(a, b) {
1017
1014
  }
1018
1015
 
1019
1016
  /**
1020
- * Returns the length of a line (L,V,H,Z) segment,
1017
+ * Returns the length of a line (L,V,H,Z) segment
1021
1018
  * or a point at a given length.
1022
1019
  *
1023
1020
  * @param {number} x1 the starting point X
@@ -1078,9 +1075,9 @@ function lineToCubic(x1, y1, x2, y2) {
1078
1075
  /**
1079
1076
  * Converts any segment to C (cubic-bezier).
1080
1077
  *
1081
- * @param {SVGPathCommander.pathSegment} segment the source segment
1082
- * @param {SVGPathCommander.parserParams} params the source segment parameters
1083
- * @returns {SVGPathCommander.cubicSegment | SVGPathCommander.MSegment} the cubic-bezier segment
1078
+ * @param {SVGPath.pathSegment} segment the source segment
1079
+ * @param {SVGPath.parserParams} params the source segment parameters
1080
+ * @returns {SVGPath.cubicSegment | SVGPath.MSegment} the cubic-bezier segment
1084
1081
  */
1085
1082
  function segmentToCubic(segment, params) {
1086
1083
  const [pathCommand] = segment;
@@ -1129,8 +1126,8 @@ function segmentToCubic(segment, params) {
1129
1126
  * In addition, un-necessary `Z` segment is removed if previous segment
1130
1127
  * extends to the `M` segment.
1131
1128
  *
1132
- * @param {string | SVGPathCommander.pathArray} pathInput the string to be parsed or 'pathArray'
1133
- * @returns {SVGPathCommander.curveArray} the resulted `pathArray` converted to cubic-bezier
1129
+ * @param {string | SVGPath.pathArray} pathInput the string to be parsed or 'pathArray'
1130
+ * @returns {SVGPath.curveArray} the resulted `pathArray` converted to cubic-bezier
1134
1131
  */
1135
1132
  function pathToCurve(pathInput) {
1136
1133
  if (isCurveArray(pathInput)) {
@@ -1169,23 +1166,24 @@ function pathToCurve(pathInput) {
1169
1166
  * Rounds the values of a `pathArray` instance to
1170
1167
  * a specified amount of decimals and returns it.
1171
1168
  *
1172
- * @param {SVGPathCommander.pathArray} path the source `pathArray`
1173
- * @param {number | boolean} roundOption the amount of decimals to round numbers to
1174
- * @returns {SVGPathCommander.pathArray} the resulted `pathArray` with rounded values
1169
+ * @param {SVGPath.pathArray} path the source `pathArray`
1170
+ * @param {number | false} roundOption the amount of decimals to round numbers to
1171
+ * @returns {SVGPath.pathArray} the resulted `pathArray` with rounded values
1175
1172
  */
1176
1173
  function roundPath(path, roundOption) {
1177
1174
  let { round } = defaultOptions;
1178
1175
  if (roundOption === false || round === false) return clonePath(path);
1179
- round = roundOption >= 1 ? roundOption : round;
1176
+ // round = roundOption >= 1 ? roundOption : round;
1177
+ // allow for ZERO decimals
1178
+ round = roundOption >= 0 ? roundOption : round;
1180
1179
  // to round values to the power
1181
1180
  // the `round` value must be integer
1182
- // @ts-ignore
1183
1181
  const pow = round >= 1 ? (10 ** round) : 1;
1184
1182
 
1185
1183
  // @ts-ignore -- `pathSegment[]` is `pathArray`
1186
1184
  return path.map((pi) => {
1187
1185
  const values = pi.slice(1).map(Number)
1188
- .map((n) => (n % 1 === 0 ? n : Math.round(n * pow) / pow));
1186
+ .map((n) => (round ? (Math.round(n * pow) / pow) : Math.round(n)));
1189
1187
  return [pi[0], ...values];
1190
1188
  });
1191
1189
  }
@@ -1194,8 +1192,8 @@ function roundPath(path, roundOption) {
1194
1192
  * Returns a valid `d` attribute string value created
1195
1193
  * by rounding values and concatenating the `pathArray` segments.
1196
1194
  *
1197
- * @param {SVGPathCommander.pathArray} path the `pathArray` object
1198
- * @param {any} round amount of decimals to round values to
1195
+ * @param {SVGPath.pathArray} path the `pathArray` object
1196
+ * @param {number | false} round amount of decimals to round values to
1199
1197
  * @returns {string} the concatenated path string
1200
1198
  */
1201
1199
  function pathToString(path, round) {
@@ -1204,11 +1202,10 @@ function pathToString(path, round) {
1204
1202
  }
1205
1203
 
1206
1204
  /**
1207
- * Reverses all segments and their values of a `pathArray`
1208
- * and returns a new instance.
1205
+ * Reverses all segments of a `pathArray` and returns a new `pathArray` instance.
1209
1206
  *
1210
- * @param {SVGPathCommander.pathArray} pathInput the source `pathArray`
1211
- * @returns {SVGPathCommander.pathArray} the reversed `pathArray`
1207
+ * @param {SVGPath.pathArray} pathInput the source `pathArray`
1208
+ * @returns {SVGPath.pathArray} the reversed `pathArray`
1212
1209
  */
1213
1210
  function reversePath(pathInput) {
1214
1211
  const absolutePath = pathToAbsolute(pathInput);
@@ -1233,7 +1230,7 @@ function reversePath(pathInput) {
1233
1230
  /** @type {number} */
1234
1231
  const x = i ? path[i - 1].x : path[pLen - 1].x;
1235
1232
  const y = i ? path[i - 1].y : path[pLen - 1].y;
1236
- /** @type {SVGPathCommander.pathSegment} */
1233
+ /** @type {SVGPath.pathSegment} */
1237
1234
  // @ts-ignore
1238
1235
  let result = [];
1239
1236
 
@@ -1307,7 +1304,7 @@ function reversePath(pathInput) {
1307
1304
  * In the process, values are converted to absolute
1308
1305
  * for visual consistency.
1309
1306
  *
1310
- * @param {SVGPathCommander.pathArray | string} pathInput the source `pathArray`
1307
+ * @param {SVGPath.pathArray | string} pathInput the source `pathArray`
1311
1308
  * @return {string[]} an array with all sub-path strings
1312
1309
  */
1313
1310
  function splitPath(pathInput) {
@@ -1321,11 +1318,11 @@ function splitPath(pathInput) {
1321
1318
  /**
1322
1319
  * Shorten a single segment of a `pathArray` object.
1323
1320
  *
1324
- * @param {SVGPathCommander.absoluteSegment} segment the `absoluteSegment` object
1325
- * @param {SVGPathCommander.normalSegment} normalSegment the `normalSegment` object
1321
+ * @param {SVGPath.absoluteSegment} segment the `absoluteSegment` object
1322
+ * @param {SVGPath.normalSegment} normalSegment the `normalSegment` object
1326
1323
  * @param {any} params the coordinates of the previous segment
1327
1324
  * @param {string} prevCommand the path command of the previous segment
1328
- * @returns {SVGPathCommander.shortSegment | SVGPathCommander.pathSegment} the shortened segment
1325
+ * @returns {SVGPath.shortSegment | SVGPath.pathSegment} the shortened segment
1329
1326
  */
1330
1327
  function shortenSegment(segment, normalSegment, params, prevCommand) {
1331
1328
  const [pathCommand] = segment;
@@ -1389,9 +1386,9 @@ function shortenSegment(segment, normalSegment, params, prevCommand) {
1389
1386
  * * implement `auto` for rounding values based on pathBBox
1390
1387
  * * also revers path check if it's smaller string, maybe?
1391
1388
  *
1392
- * @param {SVGPathCommander.pathArray} pathInput a string or `pathArray`
1389
+ * @param {SVGPath.pathArray} pathInput a string or `pathArray`
1393
1390
  * @param {number | boolean} round the amount of decimals to round values to
1394
- * @returns {SVGPathCommander.pathArray} the optimized `pathArray`
1391
+ * @returns {SVGPath.pathArray} the optimized `pathArray`
1395
1392
  */
1396
1393
  function optimizePath(pathInput, round) {
1397
1394
  const path = pathToAbsolute(pathInput);
@@ -2277,14 +2274,15 @@ Object.assign(CSSMatrix, { Version: Version$1 });
2277
2274
  /**
2278
2275
  * Returns a transformation matrix to apply to `<path>` elements.
2279
2276
  *
2280
- * @see SVGPathCommander.transformObject
2277
+ * @see SVGPath.transformObject
2281
2278
  *
2282
- * @param {SVGPathCommander.transformObject} transform the `transformObject`
2279
+ * @param {SVGPath.transformObject} transform the `transformObject`
2283
2280
  * @returns {CSSMatrix} a new transformation matrix
2284
2281
  */
2285
2282
  function getSVGMatrix(transform) {
2286
2283
  let matrix = new CSSMatrix();
2287
2284
  const { origin } = transform;
2285
+ // @ts-ignore -- at this point the origin is surely defined
2288
2286
  const [originX, originY] = origin;
2289
2287
  const { translate } = transform;
2290
2288
  const { rotate } = transform;
@@ -2415,9 +2413,9 @@ function transformEllipse(m, rx, ry, ax) {
2415
2413
  * Details =>
2416
2414
  * https://stackoverflow.com/questions/23792505/predicted-rendering-of-css-3d-transformed-pixel
2417
2415
  *
2418
- * @param {SVGPathCommander.CSSMatrix} m the transformation matrix
2416
+ * @param {SVGPath.CSSMatrix} m the transformation matrix
2419
2417
  * @param {[number, number]} point2D the initial [x,y] coordinates
2420
- * @param {number[]} origin the initial [x,y] coordinates
2418
+ * @param {number[]} origin the [x,y,z] transform origin
2421
2419
  * @returns {[number, number]} the projected [x,y] coordinates
2422
2420
  */
2423
2421
  function projection2d(m, point2D, origin) {
@@ -2443,9 +2441,9 @@ function projection2d(m, point2D, origin) {
2443
2441
  * Since *SVGElement* doesn't support 3D transformation, this function
2444
2442
  * creates a 2D projection of the <path> element.
2445
2443
  *
2446
- * @param {SVGPathCommander.pathArray} path the `pathArray` to apply transformation
2447
- * @param {SVGPathCommander.transformObject} transform the transform functions `Object`
2448
- * @returns {SVGPathCommander.pathArray} the resulted `pathArray`
2444
+ * @param {SVGPath.pathArray} path the `pathArray` to apply transformation
2445
+ * @param {SVGPath.transformObject} transform the transform functions `Object`
2446
+ * @returns {SVGPath.pathArray} the resulted `pathArray`
2449
2447
  */
2450
2448
  function transformPath(path, transform) {
2451
2449
  let x = 0; let y = 0; let i; let j; let ii; let jj; let lx; let ly; let te;
@@ -2460,12 +2458,12 @@ function transformPath(path, transform) {
2460
2458
  const matrix2d = [a, b, c, d, e, f];
2461
2459
  const params = { ...paramsParser };
2462
2460
  /** @ts-ignore */
2463
- /** @type {SVGPathCommander.pathSegment} */
2461
+ /** @type {SVGPath.pathSegment} */
2464
2462
  // @ts-ignore
2465
2463
  let segment = [];
2466
2464
  let seglen = 0;
2467
2465
  let pathCommand = '';
2468
- /** @type {SVGPathCommander.pathTransformList[]} */
2466
+ /** @type {SVGPath.pathTransformList[]} */
2469
2467
  let transformedPath = [];
2470
2468
  const allPathCommands = []; // needed for arc to curve transformation
2471
2469
 
@@ -2504,7 +2502,7 @@ function transformPath(path, transform) {
2504
2502
  params.x2 = +(segment[seglen - 4]) || params.x1;
2505
2503
  params.y2 = +(segment[seglen - 3]) || params.y1;
2506
2504
 
2507
- /** @type {SVGPathCommander.pathTransformList} */
2505
+ /** @type {SVGPath.pathTransformList} */
2508
2506
  const result = {
2509
2507
  s: absolutePath[i], c: absolutePath[i][0], x: params.x1, y: params.y1,
2510
2508
  };
@@ -2541,6 +2539,7 @@ function transformPath(path, transform) {
2541
2539
  case 'L':
2542
2540
  case 'H':
2543
2541
  case 'V':
2542
+ // @ts-ignore
2544
2543
  [lx, ly] = projection2d(matrixInstance, [seg.x, seg.y], origin);
2545
2544
 
2546
2545
  if (x !== lx && y !== ly) {
@@ -2557,7 +2556,7 @@ function transformPath(path, transform) {
2557
2556
  default:
2558
2557
 
2559
2558
  for (j = 1, jj = segment.length; j < jj; j += 2) {
2560
- // compute line coordinates without altering previous coordinates
2559
+ // @ts-ignore compute line coordinates without altering previous coordinates
2561
2560
  [x, y] = projection2d(matrixInstance, [+segment[j], +segment[j + 1]], origin);
2562
2561
  segment[j] = x;
2563
2562
  segment[j + 1] = y;
@@ -2599,7 +2598,7 @@ function getPointAtCubicSegmentLength(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t) {
2599
2598
  }
2600
2599
 
2601
2600
  /**
2602
- * Returns the length of a C (cubic-bezier) segment,
2601
+ * Returns the length of a C (cubic-bezier) segment
2603
2602
  * or an {x,y} point at a given length.
2604
2603
  *
2605
2604
  * @param {number} x1 the starting point X
@@ -2663,7 +2662,7 @@ function segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, distance) {
2663
2662
  * @param {number} c2y the second control point Y
2664
2663
  * @param {number} x2 the ending point X
2665
2664
  * @param {number} y2 the ending point Y
2666
- * @returns {SVGPathCommander.segmentLimits} the bounding box of the cubic-bezier segment
2665
+ * @returns {SVGPath.segmentLimits} the bounding box of the cubic-bezier segment
2667
2666
  */
2668
2667
  function getCubicSize(x1, y1, c1x, c1y, c2x, c2y, x2, y2) {
2669
2668
  let a = (c2x - 2 * c1x + x1) - (x2 - 2 * c2x + c1x);
@@ -2720,8 +2719,8 @@ function getCubicSize(x1, y1, c1x, c1y, c2x, c2y, x2, y2) {
2720
2719
  /**
2721
2720
  * Returns the bounding box of a shape.
2722
2721
  *
2723
- * @param {SVGPathCommander.pathArray} path the shape `pathArray`
2724
- * @returns {SVGPathCommander.pathBBox} the length of the cubic-bezier segment
2722
+ * @param {SVGPath.pathArray} path the shape `pathArray`
2723
+ * @returns {SVGPath.pathBBox} the length of the cubic-bezier segment
2725
2724
  */
2726
2725
  function getPathBBox(path) {
2727
2726
  if (!path) {
@@ -2778,6 +2777,254 @@ function getPathBBox(path) {
2778
2777
  };
2779
2778
  }
2780
2779
 
2780
+ /**
2781
+ * Returns the length of an A (arc-to) segment
2782
+ * or an {x,y} point at a given length.
2783
+ *
2784
+ * @param {number} X1 the starting x position
2785
+ * @param {number} Y1 the starting y position
2786
+ * @param {number} RX x-radius of the arc
2787
+ * @param {number} RY y-radius of the arc
2788
+ * @param {number} angle x-axis-rotation of the arc
2789
+ * @param {number} LAF large-arc-flag of the arc
2790
+ * @param {number} SF sweep-flag of the arc
2791
+ * @param {number} X2 the ending x position
2792
+ * @param {number} Y2 the ending y position
2793
+ * @param {number} distance the point distance
2794
+ * @returns {{x: number, y: number} | number} the segment length or point
2795
+ */
2796
+ function segmentArcFactory(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, distance) {
2797
+ const cubicSeg = arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2);
2798
+ const distanceIsNumber = typeof distance === 'number';
2799
+ let [x, y] = [X1, Y1];
2800
+ const lengthMargin = 0.001;
2801
+ let totalLength = 0;
2802
+ let cubicSubseg = [];
2803
+ let argsc = [];
2804
+ let segLen = 0;
2805
+
2806
+ if (distanceIsNumber && distance < lengthMargin) {
2807
+ return { x, y };
2808
+ }
2809
+
2810
+ for (let i = 0, ii = cubicSeg.length; i < ii; i += 6) {
2811
+ cubicSubseg = cubicSeg.slice(i, i + 6);
2812
+ argsc = [x, y, ...cubicSubseg];
2813
+ // @ts-ignore
2814
+ segLen = segmentCubicFactory(...argsc);
2815
+ if (distanceIsNumber && totalLength + segLen >= distance) {
2816
+ // @ts-ignore -- this is a `cubicSegment`
2817
+ return segmentCubicFactory(...argsc, distance - totalLength);
2818
+ }
2819
+ totalLength += segLen;
2820
+ [x, y] = cubicSubseg.slice(-2);
2821
+ }
2822
+
2823
+ if (distanceIsNumber && distance >= totalLength) {
2824
+ return { x: X2, y: Y2 };
2825
+ }
2826
+
2827
+ return totalLength;
2828
+ }
2829
+
2830
+ /**
2831
+ * Returns the {x,y} coordinates of a point at a
2832
+ * given length of a quad-bezier segment.
2833
+ *
2834
+ * @see https://github.com/substack/point-at-length
2835
+ *
2836
+ * @param {number} x1 the starting point X
2837
+ * @param {number} y1 the starting point Y
2838
+ * @param {number} cx the control point X
2839
+ * @param {number} cy the control point Y
2840
+ * @param {number} x2 the ending point X
2841
+ * @param {number} y2 the ending point Y
2842
+ * @param {number} t a [0-1] ratio
2843
+ * @returns {{x: number, y: number}} the requested {x,y} coordinates
2844
+ */
2845
+ function getPointAtQuadSegmentLength(x1, y1, cx, cy, x2, y2, t) {
2846
+ const t1 = 1 - t;
2847
+ return {
2848
+ x: (t1 ** 2) * x1
2849
+ + 2 * t1 * t * cx
2850
+ + (t ** 2) * x2,
2851
+ y: (t1 ** 2) * y1
2852
+ + 2 * t1 * t * cy
2853
+ + (t ** 2) * y2,
2854
+ };
2855
+ }
2856
+
2857
+ /**
2858
+ * Returns the Q (quadratic-bezier) segment length
2859
+ * or an {x,y} point at a given length.
2860
+ *
2861
+ * @param {number} x1 the starting point X
2862
+ * @param {number} y1 the starting point Y
2863
+ * @param {number} qx the control point X
2864
+ * @param {number} qy the control point Y
2865
+ * @param {number} x2 the ending point X
2866
+ * @param {number} y2 the ending point Y
2867
+ * @param {number=} distance the distance to point
2868
+ * @returns {{x: number, y: number} | number} the segment length or point
2869
+ */
2870
+ function segmentQuadFactory(x1, y1, qx, qy, x2, y2, distance) {
2871
+ const distanceIsNumber = typeof distance === 'number';
2872
+ const lengthMargin = 0.001;
2873
+ let x = x1; let y = y1;
2874
+ let totalLength = 0;
2875
+ let prev = [x1, y1, totalLength];
2876
+ /** @type {[number, number]} */
2877
+ let cur = [x1, y1];
2878
+ let t = 0;
2879
+
2880
+ if (distanceIsNumber && distance < lengthMargin) {
2881
+ return { x, y };
2882
+ }
2883
+
2884
+ const n = 100;
2885
+ for (let j = 0; j <= n; j += 1) {
2886
+ t = j / n;
2887
+
2888
+ ({ x, y } = getPointAtQuadSegmentLength(x1, y1, qx, qy, x2, y2, t));
2889
+ totalLength += distanceSquareRoot(cur, [x, y]);
2890
+ cur = [x, y];
2891
+
2892
+ if (distanceIsNumber && totalLength >= distance) {
2893
+ const dv = (totalLength - distance) / (totalLength - prev[2]);
2894
+
2895
+ return {
2896
+ x: cur[0] * (1 - dv) + prev[0] * dv,
2897
+ y: cur[1] * (1 - dv) + prev[1] * dv,
2898
+ };
2899
+ }
2900
+ prev = [x, y, totalLength];
2901
+ }
2902
+ if (distanceIsNumber && distance >= totalLength) {
2903
+ return { x: x2, y: y2 };
2904
+ }
2905
+ return totalLength;
2906
+ }
2907
+
2908
+ /**
2909
+ * Returns a {x,y} point at a given length
2910
+ * of a shape or the shape total length.
2911
+ *
2912
+ * @param {string | SVGPath.pathArray} pathInput the `pathArray` to look into
2913
+ * @param {number=} distance the length of the shape to look at
2914
+ * @returns {{x: number, y: number} | number} the total length or point
2915
+ */
2916
+ function pathLengthFactory(pathInput, distance) {
2917
+ const path = fixPath(normalizePath(pathInput));
2918
+ const distanceIsNumber = typeof distance === 'number';
2919
+ let totalLength = 0;
2920
+ let isM = true;
2921
+ /** @type {number[]} */
2922
+ let data = [];
2923
+ let pathCommand = 'M';
2924
+ let segLen = 0;
2925
+ let x = 0;
2926
+ let y = 0;
2927
+ let mx = 0;
2928
+ let my = 0;
2929
+ let seg;
2930
+
2931
+ for (let i = 0, ll = path.length; i < ll; i += 1) {
2932
+ seg = path[i];
2933
+ [pathCommand] = seg;
2934
+ isM = pathCommand === 'M';
2935
+ // @ts-ignore
2936
+ data = !isM ? [x, y, ...seg.slice(1)] : data;
2937
+
2938
+ // this segment is always ZERO
2939
+ if (isM) {
2940
+ // remember mx, my for Z
2941
+ // @ts-ignore
2942
+ [, mx, my] = seg;
2943
+ if (distanceIsNumber && distance < 0.001) {
2944
+ return { x: mx, y: my };
2945
+ }
2946
+ } else if (pathCommand === 'L') {
2947
+ // @ts-ignore
2948
+ segLen = segmentLineFactory(...data);
2949
+ if (distanceIsNumber && totalLength + segLen >= distance) {
2950
+ // @ts-ignore
2951
+ return segmentLineFactory(...data, distance - totalLength);
2952
+ }
2953
+ totalLength += segLen;
2954
+ } else if (pathCommand === 'A') {
2955
+ // @ts-ignore
2956
+ segLen = segmentArcFactory(...data);
2957
+ if (distanceIsNumber && totalLength + segLen >= distance) {
2958
+ // @ts-ignore
2959
+ return segmentArcFactory(...data, distance - totalLength);
2960
+ }
2961
+ totalLength += segLen;
2962
+ } else if (pathCommand === 'C') {
2963
+ // @ts-ignore
2964
+ segLen = segmentCubicFactory(...data);
2965
+ if (distanceIsNumber && totalLength + segLen >= distance) {
2966
+ // @ts-ignore
2967
+ return segmentCubicFactory(...data, distance - totalLength);
2968
+ }
2969
+ totalLength += segLen;
2970
+ } else if (pathCommand === 'Q') {
2971
+ // @ts-ignore
2972
+ segLen = segmentQuadFactory(...data);
2973
+ if (distanceIsNumber && totalLength + segLen >= distance) {
2974
+ // @ts-ignore
2975
+ return segmentQuadFactory(...data, distance - totalLength);
2976
+ }
2977
+ totalLength += segLen;
2978
+ } else if (pathCommand === 'Z') {
2979
+ data = [x, y, mx, my];
2980
+ // @ts-ignore
2981
+ segLen = segmentLineFactory(...data);
2982
+ if (distanceIsNumber && totalLength + segLen >= distance) {
2983
+ // @ts-ignore
2984
+ return segmentLineFactory(...data, distance - totalLength);
2985
+ }
2986
+ totalLength += segLen;
2987
+ }
2988
+
2989
+ // @ts-ignore -- needed for the below
2990
+ [x, y] = pathCommand !== 'Z' ? seg.slice(-2) : [mx, my];
2991
+ }
2992
+
2993
+ // native `getPointAtLength` behavior when the given distance
2994
+ // is higher than total length
2995
+ if (distanceIsNumber && distance >= totalLength) {
2996
+ return { x, y };
2997
+ }
2998
+
2999
+ return totalLength;
3000
+ }
3001
+
3002
+ /**
3003
+ * Returns the shape total length, or the equivalent to `shape.getTotalLength()`.
3004
+ *
3005
+ * The `normalizePath` version is lighter, faster, more efficient and more accurate
3006
+ * with paths that are not `curveArray`.
3007
+ *
3008
+ * @param {string | SVGPath.pathArray} pathInput the target `pathArray`
3009
+ * @returns {number} the shape total length
3010
+ */
3011
+ function getTotalLength(pathInput) {
3012
+ // @ts-ignore - it's fine
3013
+ return pathLengthFactory(pathInput);
3014
+ }
3015
+
3016
+ /**
3017
+ * Returns [x,y] coordinates of a point at a given length of a shape.
3018
+ *
3019
+ * @param {string | SVGPath.pathArray} pathInput the `pathArray` to look into
3020
+ * @param {number} distance the length of the shape to look at
3021
+ * @returns {{x: number, y: number}} the requested {x, y} point coordinates
3022
+ */
3023
+ function getPointAtLength(pathInput, distance) {
3024
+ // @ts-ignore
3025
+ return pathLengthFactory(pathInput, distance);
3026
+ }
3027
+
2781
3028
  /**
2782
3029
  * Creates a new SVGPathCommander instance with the following properties:
2783
3030
  * * segments: `pathArray`
@@ -2797,18 +3044,25 @@ class SVGPathCommander {
2797
3044
  constructor(pathValue, config) {
2798
3045
  const instanceOptions = config || {};
2799
3046
 
3047
+ const undefPath = typeof pathValue === 'undefined';
3048
+
3049
+ if (undefPath || !pathValue.length) {
3050
+ throw TypeError(`${error}: "pathValue" is ${undefPath ? 'undefined' : 'empty'}`);
3051
+ }
3052
+
3053
+ const segments = parsePathString(pathValue);
3054
+ if (typeof segments === 'string') {
3055
+ throw TypeError(segments);
3056
+ }
3057
+
2800
3058
  /**
2801
- * @type {SVGPathCommander.pathArray}
3059
+ * @type {SVGPath.pathArray}
2802
3060
  */
2803
- this.segments = parsePathString(pathValue);
2804
- const BBox = getPathBBox(this.segments);
3061
+ this.segments = segments;
3062
+
2805
3063
  const {
2806
- width,
2807
- height,
2808
- cx,
2809
- cy,
2810
- cz,
2811
- } = BBox;
3064
+ width, height, cx, cy, cz,
3065
+ } = this.getBBox();
2812
3066
 
2813
3067
  // set instance options.round
2814
3068
  let { round, origin } = defaultOptions;
@@ -2817,7 +3071,7 @@ class SVGPathCommander {
2817
3071
  if (roundOption === 'auto') {
2818
3072
  const pathScale = (`${Math.floor(Math.max(width, height))}`).length;
2819
3073
  round = pathScale >= 4 ? 0 : 4 - pathScale;
2820
- } else if ((Number.isInteger(roundOption) && roundOption >= 1) || roundOption === false) {
3074
+ } else if (Number.isInteger(roundOption) || roundOption === false) {
2821
3075
  round = roundOption;
2822
3076
  }
2823
3077
 
@@ -2827,15 +3081,14 @@ class SVGPathCommander {
2827
3081
  origin = [
2828
3082
  !Number.isNaN(originX) ? originX : cx,
2829
3083
  !Number.isNaN(originY) ? originY : cy,
2830
- originZ || cz,
3084
+ !Number.isNaN(originZ) ? originZ : cz,
2831
3085
  ];
2832
3086
  } else {
2833
3087
  origin = [cx, cy, cz];
2834
3088
  }
2835
3089
 
2836
3090
  /**
2837
- * @type {number | boolean}
2838
- * @default 4
3091
+ * @type {number | false}
2839
3092
  */
2840
3093
  this.round = round;
2841
3094
  this.origin = origin;
@@ -2844,7 +3097,37 @@ class SVGPathCommander {
2844
3097
  }
2845
3098
 
2846
3099
  /**
2847
- * Convert path to absolute values
3100
+ * Returns the path bounding box, equivalent to native `path.getBBox()`.
3101
+ * @public
3102
+ * @returns {SVGPath.pathBBox}
3103
+ */
3104
+ getBBox() {
3105
+ return getPathBBox(this.segments);
3106
+ }
3107
+
3108
+ /**
3109
+ * Returns the total path length, equivalent to native `path.getTotalLength()`.
3110
+ * @public
3111
+ * @returns {number}
3112
+ */
3113
+ getTotalLength() {
3114
+ return getTotalLength(this.segments);
3115
+ }
3116
+
3117
+ /**
3118
+ * Returns an `{x,y}` point in the path stroke at a given length,
3119
+ * equivalent to the native `path.getPointAtLength()`.
3120
+ *
3121
+ * @public
3122
+ * @param {number} length the length
3123
+ * @returns {{x: number, y:number}} the requested point
3124
+ */
3125
+ getPointAtLength(length) {
3126
+ return getPointAtLength(this.segments, length);
3127
+ }
3128
+
3129
+ /**
3130
+ * Convert path to absolute values
2848
3131
  * @public
2849
3132
  */
2850
3133
  toAbsolute() {
@@ -2934,16 +3217,16 @@ class SVGPathCommander {
2934
3217
 
2935
3218
  /**
2936
3219
  * Transform path using values from an `Object` defined as `transformObject`.
2937
- * @see SVGPathCommander.transformObject for a quick refference
3220
+ * @see SVGPath.transformObject for a quick refference
2938
3221
  *
2939
- * @param {SVGPathCommander.transformObject} source a `transformObject`as described above
3222
+ * @param {SVGPath.transformObject} source a `transformObject`as described above
2940
3223
  * @public
2941
3224
  */
2942
3225
  transform(source) {
2943
3226
  if (!source || typeof source !== 'object' || (typeof source === 'object'
2944
3227
  && !['translate', 'rotate', 'skew', 'scale'].some((x) => x in source))) return this;
2945
3228
 
2946
- /** @type {SVGPathCommander.transformObject} */
3229
+ /** @type {SVGPath.transformObject} */
2947
3230
  const transform = {};
2948
3231
  Object.keys(source).forEach((fn) => {
2949
3232
  // @ts-ignore
@@ -2953,18 +3236,18 @@ class SVGPathCommander {
2953
3236
 
2954
3237
  // if origin is not specified
2955
3238
  // it's important that we have one
3239
+ const [cx, cy, cz] = this.origin;
2956
3240
  const { origin } = transform;
2957
- if (origin && origin.length >= 2) {
3241
+
3242
+ if (Array.isArray(origin) && origin.length >= 2) {
2958
3243
  const [originX, originY, originZ] = origin.map(Number);
2959
- const [cx, cy, cz] = this.origin;
2960
3244
  transform.origin = [
2961
3245
  !Number.isNaN(originX) ? originX : cx,
2962
3246
  !Number.isNaN(originY) ? originY : cy,
2963
3247
  originZ || cz,
2964
3248
  ];
2965
3249
  } else {
2966
- // @ts-ignore
2967
- transform.origin = { ...this.origin };
3250
+ transform.origin = [cx, cy, cz];
2968
3251
  }
2969
3252
 
2970
3253
  this.segments = transformPath(segments, transform);
@@ -3027,7 +3310,7 @@ function getCubicSegArea(x1, y1, c1x, c1y, c2x, c2y, x2, y2) {
3027
3310
  *
3028
3311
  * @see https://github.com/paperjs/paper.js/blob/develop/src/path/Path.js
3029
3312
  *
3030
- * @param {SVGPathCommander.pathArray} path the shape `pathArray`
3313
+ * @param {SVGPath.pathArray} path the shape `pathArray`
3031
3314
  * @returns {number} the length of the cubic-bezier segment
3032
3315
  */
3033
3316
  function getPathArea(path) {
@@ -3054,7 +3337,7 @@ function getPathArea(path) {
3054
3337
  * This is the `pathToCurve` version which is faster and more efficient for
3055
3338
  * paths that are `curveArray`.
3056
3339
  *
3057
- * @param {string | SVGPathCommander.curveArray} path the target `pathArray`
3340
+ * @param {string | SVGPath.curveArray} path the target `pathArray`
3058
3341
  * @returns {number} the `curveArray` total length
3059
3342
  */
3060
3343
  function getPathLength(path) {
@@ -3067,285 +3350,24 @@ function getPathLength(path) {
3067
3350
  return totalLength;
3068
3351
  }
3069
3352
 
3070
- /**
3071
- * Returns the length of a A (arc-to) segment,
3072
- * or an {x,y} point at a given length.
3073
- *
3074
- * @param {number} X1 the starting x position
3075
- * @param {number} Y1 the starting y position
3076
- * @param {number} RX x-radius of the arc
3077
- * @param {number} RY y-radius of the arc
3078
- * @param {number} angle x-axis-rotation of the arc
3079
- * @param {number} LAF large-arc-flag of the arc
3080
- * @param {number} SF sweep-flag of the arc
3081
- * @param {number} X2 the ending x position
3082
- * @param {number} Y2 the ending y position
3083
- * @param {number} distance the point distance
3084
- * @returns {{x: number, y: number} | number} the segment length or point
3085
- */
3086
- function segmentArcFactory(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, distance) {
3087
- const cubicSeg = arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2);
3088
- const distanceIsNumber = typeof distance === 'number';
3089
- let [x, y] = [X1, Y1];
3090
- const lengthMargin = 0.001;
3091
- let totalLength = 0;
3092
- let cubicSubseg = [];
3093
- let argsc = [];
3094
- let segLen = 0;
3095
-
3096
- if (distanceIsNumber && distance < lengthMargin) {
3097
- return { x, y };
3098
- }
3099
-
3100
- for (let i = 0, ii = cubicSeg.length; i < ii; i += 6) {
3101
- cubicSubseg = cubicSeg.slice(i, i + 6);
3102
- argsc = [x, y, ...cubicSubseg];
3103
- // @ts-ignore
3104
- segLen = segmentCubicFactory(...argsc);
3105
- if (distanceIsNumber && totalLength + segLen >= distance) {
3106
- // @ts-ignore -- this is a `cubicSegment`
3107
- return segmentCubicFactory(...argsc, distance - totalLength);
3108
- }
3109
- totalLength += segLen;
3110
- [x, y] = cubicSubseg.slice(-2);
3111
- }
3112
-
3113
- if (distanceIsNumber && distance >= totalLength) {
3114
- return { x: X2, y: Y2 };
3115
- }
3116
-
3117
- return totalLength;
3118
- }
3119
-
3120
- /**
3121
- * Returns the {x,y} coordinates of a point at a
3122
- * given length of a quad-bezier segment.
3123
- *
3124
- * @see https://github.com/substack/point-at-length
3125
- *
3126
- * @param {number} x1 the starting point X
3127
- * @param {number} y1 the starting point Y
3128
- * @param {number} cx the control point X
3129
- * @param {number} cy the control point Y
3130
- * @param {number} x2 the ending point X
3131
- * @param {number} y2 the ending point Y
3132
- * @param {number} t a [0-1] ratio
3133
- * @returns {{x: number, y: number}} the requested {x,y} coordinates
3134
- */
3135
- function getPointAtQuadSegmentLength(x1, y1, cx, cy, x2, y2, t) {
3136
- const t1 = 1 - t;
3137
- return {
3138
- x: (t1 ** 2) * x1
3139
- + 2 * t1 * t * cx
3140
- + (t ** 2) * x2,
3141
- y: (t1 ** 2) * y1
3142
- + 2 * t1 * t * cy
3143
- + (t ** 2) * y2,
3144
- };
3145
- }
3146
-
3147
- /**
3148
- * Returns the Q (quadratic-bezier) segment length,
3149
- * or an {x,y} point at a given length.
3150
- *
3151
- * @param {number} x1 the starting point X
3152
- * @param {number} y1 the starting point Y
3153
- * @param {number} qx the control point X
3154
- * @param {number} qy the control point Y
3155
- * @param {number} x2 the ending point X
3156
- * @param {number} y2 the ending point Y
3157
- * @param {number=} distance the distance to point
3158
- * @returns {{x: number, y: number} | number} the segment length or point
3159
- */
3160
- function segmentQuadFactory(x1, y1, qx, qy, x2, y2, distance) {
3161
- const distanceIsNumber = typeof distance === 'number';
3162
- const lengthMargin = 0.001;
3163
- let x = x1; let y = y1;
3164
- let totalLength = 0;
3165
- let prev = [x1, y1, totalLength];
3166
- /** @type {[number, number]} */
3167
- let cur = [x1, y1];
3168
- let t = 0;
3169
-
3170
- if (distanceIsNumber && distance < lengthMargin) {
3171
- return { x, y };
3172
- }
3173
-
3174
- const n = 100;
3175
- for (let j = 0; j <= n; j += 1) {
3176
- t = j / n;
3177
-
3178
- ({ x, y } = getPointAtQuadSegmentLength(x1, y1, qx, qy, x2, y2, t));
3179
- totalLength += distanceSquareRoot(cur, [x, y]);
3180
- cur = [x, y];
3181
-
3182
- if (distanceIsNumber && totalLength >= distance) {
3183
- const dv = (totalLength - distance) / (totalLength - prev[2]);
3184
-
3185
- return {
3186
- x: cur[0] * (1 - dv) + prev[0] * dv,
3187
- y: cur[1] * (1 - dv) + prev[1] * dv,
3188
- };
3189
- }
3190
- prev = [x, y, totalLength];
3191
- }
3192
- if (distanceIsNumber && distance >= totalLength) {
3193
- return { x: x2, y: y2 };
3194
- }
3195
- return totalLength;
3196
- }
3197
-
3198
- /**
3199
- * Returns a {x,y} point at a given length of a shape or the shape total length.
3200
- *
3201
- * @param {string | SVGPathCommander.pathArray} pathInput the `pathArray` to look into
3202
- * @param {number=} distance the length of the shape to look at
3203
- * @returns {{x: number, y: number} | number} the total length or point
3204
- */
3205
- function pathLengthFactory(pathInput, distance) {
3206
- const path = fixPath(normalizePath(pathInput));
3207
- const distanceIsNumber = typeof distance === 'number';
3208
- let totalLength = 0;
3209
- let isM = true;
3210
- /** @type {number[]} */
3211
- let data = [];
3212
- let pathCommand = 'M';
3213
- let segLen = 0;
3214
- let x = 0;
3215
- let y = 0;
3216
- let mx = 0;
3217
- let my = 0;
3218
- let seg;
3219
-
3220
- for (let i = 0, ll = path.length; i < ll; i += 1) {
3221
- seg = path[i];
3222
- [pathCommand] = seg;
3223
- isM = pathCommand === 'M';
3224
- // @ts-ignore
3225
- data = !isM ? [x, y, ...seg.slice(1)] : data;
3226
-
3227
- // this segment is always ZERO
3228
- if (isM) {
3229
- // remember mx, my for Z
3230
- // @ts-ignore
3231
- [, mx, my] = seg;
3232
- if (distanceIsNumber && distance < 0.001) {
3233
- return { x: mx, y: my };
3234
- }
3235
- } else if (pathCommand === 'L') {
3236
- // @ts-ignore
3237
- segLen = segmentLineFactory(...data);
3238
- if (distanceIsNumber && totalLength + segLen >= distance) {
3239
- // @ts-ignore
3240
- return segmentLineFactory(...data, distance - totalLength);
3241
- }
3242
- totalLength += segLen;
3243
- } else if (pathCommand === 'A') {
3244
- // @ts-ignore
3245
- segLen = segmentArcFactory(...data);
3246
- if (distanceIsNumber && totalLength + segLen >= distance) {
3247
- // @ts-ignore
3248
- return segmentArcFactory(...data, distance - totalLength);
3249
- }
3250
- totalLength += segLen;
3251
- } else if (pathCommand === 'C') {
3252
- // @ts-ignore
3253
- segLen = segmentCubicFactory(...data);
3254
- if (distanceIsNumber && totalLength + segLen >= distance) {
3255
- // @ts-ignore
3256
- return segmentCubicFactory(...data, distance - totalLength);
3257
- }
3258
- totalLength += segLen;
3259
- } else if (pathCommand === 'Q') {
3260
- // @ts-ignore
3261
- segLen = segmentQuadFactory(...data);
3262
- if (distanceIsNumber && totalLength + segLen >= distance) {
3263
- // @ts-ignore
3264
- return segmentQuadFactory(...data, distance - totalLength);
3265
- }
3266
- totalLength += segLen;
3267
- } else if (pathCommand === 'Z') {
3268
- data = [x, y, mx, my];
3269
- // @ts-ignore
3270
- segLen = segmentLineFactory(...data);
3271
- if (distanceIsNumber && totalLength + segLen >= distance) {
3272
- // @ts-ignore
3273
- return segmentLineFactory(...data, distance - totalLength);
3274
- }
3275
- totalLength += segLen;
3276
- }
3277
-
3278
- // @ts-ignore -- needed for the below
3279
- [x, y] = pathCommand !== 'Z' ? seg.slice(-2) : [mx, my];
3280
- }
3281
-
3282
- // native `getPointAtLength` behavior when the given distance
3283
- // is higher than total length
3284
- if (distanceIsNumber && distance >= totalLength) {
3285
- return { x, y };
3286
- }
3287
-
3288
- return totalLength;
3289
- }
3290
-
3291
- /**
3292
- * Returns the shape total length, or the equivalent to `shape.getTotalLength()`.
3293
- *
3294
- * The `normalizePath` version is lighter, faster, more efficient and more accurate
3295
- * with paths that are not `curveArray`.
3296
- *
3297
- * @param {string | SVGPathCommander.pathArray} pathInput the target `pathArray`
3298
- * @returns {number} the shape total length
3299
- */
3300
- function getTotalLength(pathInput) {
3301
- // @ts-ignore - it's fine
3302
- return pathLengthFactory(pathInput);
3303
- }
3304
-
3305
3353
  /**
3306
3354
  * Check if a path is drawn clockwise and returns true if so,
3307
3355
  * false otherwise.
3308
3356
  *
3309
- * @param {SVGPathCommander.pathArray} path the path string or `pathArray`
3357
+ * @param {SVGPath.pathArray} path the path string or `pathArray`
3310
3358
  * @returns {boolean} true when clockwise or false if not
3311
3359
  */
3312
3360
  function getDrawDirection(path) {
3313
3361
  return getPathArea(pathToCurve(path)) >= 0;
3314
3362
  }
3315
3363
 
3316
- /**
3317
- * Returns [x,y] coordinates of a point at a given length of a shape.
3318
- *
3319
- * @param {string | SVGPathCommander.pathArray} pathInput the `pathArray` to look into
3320
- * @param {number} distance the length of the shape to look at
3321
- * @returns {{x: number, y: number}} the requested {x, y} point coordinates
3322
- */
3323
- function getPointAtLength(pathInput, distance) {
3324
- // @ts-ignore
3325
- return pathLengthFactory(pathInput, distance);
3326
- }
3327
-
3328
- /**
3329
- * Returns [x,y] coordinates of a point at a given length of a shape.
3330
- * `pathToCurve` version.
3331
- *
3332
- * @deprecated
3333
- *
3334
- * @param {string | SVGPathCommander.pathArray} pathInput the `pathArray` to look into
3335
- * @param {number} distance the length of the shape to look at
3336
- * @returns {{x: number, y: number}} the requested {x, y} point coordinates
3337
- */
3338
- function getPointAtPathLength(pathInput, distance) {
3339
- return getPointAtLength(pathInput, distance);
3340
- }
3341
-
3342
3364
  /**
3343
3365
  * Returns the segment, its index and length as well as
3344
3366
  * the length to that segment at a given length in a path.
3345
3367
  *
3346
- * @param {string | SVGPathCommander.pathArray} pathInput target `pathArray`
3368
+ * @param {string | SVGPath.pathArray} pathInput target `pathArray`
3347
3369
  * @param {number=} distance the given length
3348
- * @returns {SVGPathCommander.segmentProperties=} the requested properties
3370
+ * @returns {SVGPath.segmentProperties=} the requested properties
3349
3371
  */
3350
3372
  function getPropertiesAtLength(pathInput, distance) {
3351
3373
  const pathArray = parsePathString(pathInput);
@@ -3357,7 +3379,7 @@ function getPropertiesAtLength(pathInput, distance) {
3357
3379
  let index = pathTemp.length - 1;
3358
3380
  let lengthAtSegment = 0;
3359
3381
  let length = 0;
3360
- /** @type {SVGPathCommander.pathSegment} */
3382
+ /** @type {SVGPath.pathSegment} */
3361
3383
  let segment = pathArray[0];
3362
3384
  const [x, y] = segment.slice(-2);
3363
3385
  const point = { x, y };
@@ -3405,9 +3427,9 @@ function getPropertiesAtLength(pathInput, distance) {
3405
3427
  * the distance to the path stroke.
3406
3428
  * @see https://bl.ocks.org/mbostock/8027637
3407
3429
  *
3408
- * @param {string | SVGPathCommander.pathArray} pathInput target `pathArray`
3430
+ * @param {string | SVGPath.pathArray} pathInput target `pathArray`
3409
3431
  * @param {{x: number, y: number}} point the given point
3410
- * @returns {SVGPathCommander.pointProperties} the requested properties
3432
+ * @returns {SVGPath.pointProperties} the requested properties
3411
3433
  */
3412
3434
  function getPropertiesAtPoint(pathInput, point) {
3413
3435
  const path = fixPath(parsePathString(pathInput));
@@ -3475,7 +3497,7 @@ function getPropertiesAtPoint(pathInput, point) {
3475
3497
  /**
3476
3498
  * Returns the point in path closest to a given point.
3477
3499
  *
3478
- * @param {string | SVGPathCommander.pathArray} pathInput target `pathArray`
3500
+ * @param {string | SVGPath.pathArray} pathInput target `pathArray`
3479
3501
  * @param {{x: number, y: number}} point the given point
3480
3502
  * @returns {{x: number, y: number}} the best match
3481
3503
  */
@@ -3486,9 +3508,9 @@ function getClosestPoint(pathInput, point) {
3486
3508
  /**
3487
3509
  * Returns the path segment which contains a given point.
3488
3510
  *
3489
- * @param {string | SVGPathCommander.pathArray} path the `pathArray` to look into
3511
+ * @param {string | SVGPath.pathArray} path the `pathArray` to look into
3490
3512
  * @param {{x: number, y: number}} point the point of the shape to look for
3491
- * @returns {SVGPathCommander.pathSegment?} the requested segment
3513
+ * @returns {SVGPath.pathSegment?} the requested segment
3492
3514
  */
3493
3515
  function getSegmentOfPoint(path, point) {
3494
3516
  const props = getPropertiesAtPoint(path, point);
@@ -3498,9 +3520,9 @@ function getSegmentOfPoint(path, point) {
3498
3520
 
3499
3521
  /**
3500
3522
  * Returns the segment at a given length.
3501
- * @param {string | SVGPathCommander.pathArray} pathInput the target `pathArray`
3523
+ * @param {string | SVGPath.pathArray} pathInput the target `pathArray`
3502
3524
  * @param {number} distance the distance in path to look at
3503
- * @returns {SVGPathCommander.pathSegment?} the requested segment
3525
+ * @returns {SVGPath.pathSegment?} the requested segment
3504
3526
  */
3505
3527
  function getSegmentAtLength(pathInput, distance) {
3506
3528
  const props = getPropertiesAtLength(pathInput, distance);
@@ -3511,8 +3533,8 @@ function getSegmentAtLength(pathInput, distance) {
3511
3533
  /**
3512
3534
  * Checks if a given point is in the stroke of a path.
3513
3535
  *
3514
- * @param {string | SVGPathCommander.pathArray} pathInput target path
3515
- * @param {{x: number, y: number}} point
3536
+ * @param {string | SVGPath.pathArray} pathInput target path
3537
+ * @param {{x: number, y: number}} point the given `{x,y}` point
3516
3538
  * @returns {boolean} the query result
3517
3539
  */
3518
3540
  function isPointInStroke(pathInput, point) {
@@ -3559,8 +3581,8 @@ const shapeParams = {
3559
3581
  /**
3560
3582
  * Returns a new `pathArray` from line attributes.
3561
3583
  *
3562
- * @param {SVGPathCommander.lineAttr} attr shape configuration
3563
- * @returns {SVGPathCommander.pathArray} a new line `pathArray`
3584
+ * @param {SVGPath.lineAttr} attr shape configuration
3585
+ * @returns {SVGPath.pathArray} a new line `pathArray`
3564
3586
  */
3565
3587
  function getLinePath(attr) {
3566
3588
  const {
@@ -3572,11 +3594,11 @@ function getLinePath(attr) {
3572
3594
  /**
3573
3595
  * Returns a new `pathArray` like from polyline/polygon attributes.
3574
3596
  *
3575
- * @param {SVGPathCommander.polyAttr} attr shape configuration
3576
- * @return {SVGPathCommander.pathArray} a new polygon/polyline `pathArray`
3597
+ * @param {SVGPath.polyAttr} attr shape configuration
3598
+ * @return {SVGPath.pathArray} a new polygon/polyline `pathArray`
3577
3599
  */
3578
3600
  function getPolyPath(attr) {
3579
- /** @type {SVGPathCommander.pathArray} */
3601
+ /** @type {SVGPath.pathArray} */
3580
3602
  // @ts-ignore -- it's an empty `pathArray`
3581
3603
  const pathArray = [];
3582
3604
  const points = attr.points.trim().split(/[\s|,]/).map(Number);
@@ -3593,8 +3615,8 @@ function getPolyPath(attr) {
3593
3615
  /**
3594
3616
  * Returns a new `pathArray` from circle attributes.
3595
3617
  *
3596
- * @param {SVGPathCommander.circleAttr} attr shape configuration
3597
- * @return {SVGPathCommander.pathArray} a circle `pathArray`
3618
+ * @param {SVGPath.circleAttr} attr shape configuration
3619
+ * @return {SVGPath.pathArray} a circle `pathArray`
3598
3620
  */
3599
3621
  function getCirclePath(attr) {
3600
3622
  const {
@@ -3611,8 +3633,8 @@ function getCirclePath(attr) {
3611
3633
  /**
3612
3634
  * Returns a new `pathArray` from ellipse attributes.
3613
3635
  *
3614
- * @param {SVGPathCommander.ellipseAttr} attr shape configuration
3615
- * @return {SVGPathCommander.pathArray} an ellipse `pathArray`
3636
+ * @param {SVGPath.ellipseAttr} attr shape configuration
3637
+ * @return {SVGPath.pathArray} an ellipse `pathArray`
3616
3638
  */
3617
3639
  function getEllipsePath(attr) {
3618
3640
  const {
@@ -3629,8 +3651,8 @@ function getEllipsePath(attr) {
3629
3651
  /**
3630
3652
  * Returns a new `pathArray` like from rect attributes.
3631
3653
  *
3632
- * @param {SVGPathCommander.rectAttr} attr object with properties above
3633
- * @return {SVGPathCommander.pathArray} a new `pathArray` from `<rect>` attributes
3654
+ * @param {SVGPath.rectAttr} attr object with properties above
3655
+ * @return {SVGPath.pathArray} a new `pathArray` from `<rect>` attributes
3634
3656
  */
3635
3657
  function getRectanglePath(attr) {
3636
3658
  const x = +attr.x || 0;
@@ -3676,12 +3698,12 @@ function getRectanglePath(attr) {
3676
3698
  * is `true`, it will replace the target.
3677
3699
  *
3678
3700
  * It can also work with an options object,
3679
- * @see SVGPathCommander.shapeOps
3701
+ * @see SVGPath.shapeOps
3680
3702
  *
3681
3703
  * The newly created `<path>` element keeps all non-specific
3682
3704
  * attributes like `class`, `fill`, etc.
3683
3705
  *
3684
- * @param {SVGPathCommander.shapeTypes | SVGPathCommander.shapeOps} element target shape
3706
+ * @param {SVGPath.shapeTypes | SVGPath.shapeOps} element target shape
3685
3707
  * @param {boolean=} replace option to replace target
3686
3708
  * @return {SVGPathElement | boolean} the newly created `<path>` element
3687
3709
  */
@@ -3735,11 +3757,11 @@ function shapeToPath(element, replace) {
3735
3757
  }
3736
3758
 
3737
3759
  /**
3738
- * Reverses all segments and their values from a `pathArray`
3760
+ * Reverses all segments of a `pathArray`
3739
3761
  * which consists of only C (cubic-bezier) path commands.
3740
3762
  *
3741
- * @param {SVGPathCommander.curveArray} path the source `pathArray`
3742
- * @returns {SVGPathCommander.curveArray} the reversed `pathArray`
3763
+ * @param {SVGPath.curveArray} path the source `pathArray`
3764
+ * @returns {SVGPath.curveArray} the reversed `pathArray`
3743
3765
  */
3744
3766
  function reverseCurve(path) {
3745
3767
  const rotatedCurve = path.slice(1)
@@ -3776,7 +3798,6 @@ const Util = {
3776
3798
  getTotalLength,
3777
3799
  getPathLength,
3778
3800
  getPointAtLength,
3779
- getPointAtPathLength,
3780
3801
  getClosestPoint,
3781
3802
  getSegmentOfPoint,
3782
3803
  getPropertiesAtPoint,
@@ -3796,7 +3817,7 @@ const Util = {
3796
3817
  options: defaultOptions,
3797
3818
  };
3798
3819
 
3799
- var version = "0.1.25";
3820
+ var version = "0.2.0alpha3";
3800
3821
 
3801
3822
  // @ts-ignore
3802
3823