svg-path-commander 0.1.10-alpha3 → 0.1.10
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/svg-path-commander.esm.js +217 -205
- package/dist/svg-path-commander.esm.min.js +2 -2
- package/dist/svg-path-commander.js +226 -212
- package/dist/svg-path-commander.min.js +2 -2
- package/index.js +3 -0
- package/package.json +7 -6
- package/rollup.config.js +58 -0
- package/src/convert/pathToAbsolute.js +7 -5
- package/src/convert/pathToCurve.js +5 -5
- package/src/convert/pathToRelative.js +7 -6
- package/src/convert/pathToString.js +3 -3
- package/src/math/epsilon.js +1 -1
- package/src/parser/finalizeSegment.js +13 -18
- package/src/parser/isPathCommand.js +1 -1
- package/src/parser/parsePathString.js +6 -7
- package/src/parser/{svgPathArray.js → pathParser.js} +3 -3
- package/src/parser/scanFlag.js +1 -1
- package/src/parser/scanParam.js +1 -1
- package/src/parser/scanSegment.js +1 -1
- package/src/parser/skipSpaces.js +1 -1
- package/src/process/clonePath.js +4 -5
- package/src/process/fixArc.js +2 -2
- package/src/process/getSVGMatrix.js +8 -11
- package/src/process/lineToCubic.js +1 -1
- package/src/process/normalizePath.js +4 -3
- package/src/process/normalizeSegment.js +3 -3
- package/src/process/optimizePath.js +6 -3
- package/src/process/projection2d.js +1 -1
- package/src/process/quadToCubic.js +7 -7
- package/src/process/reverseCurve.js +2 -2
- package/src/process/reversePath.js +2 -2
- package/src/process/roundPath.js +27 -12
- package/src/process/segmentToCubic.js +4 -4
- package/src/process/splitCubic.js +1 -1
- package/src/process/splitPath.js +1 -1
- package/src/process/transformPath.js +2 -2
- package/src/svg-path-commander.js +17 -17
- package/src/util/getCubicSize.js +1 -1
- package/src/util/getDrawDirection.js +1 -1
- package/src/util/getPathArea.js +3 -3
- package/src/util/getPathBBox.js +2 -2
- package/src/util/getPathLength.js +1 -1
- package/src/util/getPointAtLength.js +1 -1
- package/src/util/isAbsoluteArray.js +1 -1
- package/src/util/isCurveArray.js +1 -1
- package/src/util/isNormalizedArray.js +1 -1
- package/src/util/isPathArray.js +1 -1
- package/src/util/isRelativeArray.js +1 -1
- package/src/util/isValidPath.js +2 -2
- package/src/util/shapeToPath.js +26 -26
- package/types/convert/pathToAbsolute.d.ts +1 -0
- package/types/convert/pathToCurve.d.ts +1 -0
- package/types/convert/pathToRelative.d.ts +1 -0
- package/types/convert/pathToString.d.ts +1 -0
- package/types/index.d.ts +74 -840
- package/types/math/epsilon.d.ts +2 -0
- package/types/math/midPoint.d.ts +1 -0
- package/types/math/rotateVector.d.ts +4 -0
- package/types/options/options.d.ts +6 -0
- package/types/parser/finalizeSegment.d.ts +1 -0
- package/types/parser/invalidPathValue.d.ts +2 -0
- package/types/parser/isArcCommand.d.ts +1 -0
- package/types/parser/isDigit.d.ts +1 -0
- package/types/parser/isDigitStart.d.ts +1 -0
- package/types/parser/isPathCommand.d.ts +1 -0
- package/types/parser/isSpace.d.ts +1 -0
- package/types/parser/paramsCount.d.ts +4 -0
- package/types/parser/parsePathString.d.ts +1 -0
- package/types/parser/pathParser.d.ts +12 -0
- package/types/parser/scanFlag.d.ts +1 -0
- package/types/parser/scanParam.d.ts +1 -0
- package/types/parser/scanSegment.d.ts +1 -0
- package/types/parser/skipSpaces.d.ts +1 -0
- package/types/process/arcToCubic.d.ts +1 -0
- package/types/process/clonePath.d.ts +1 -0
- package/types/process/fixArc.d.ts +1 -0
- package/types/process/getSVGMatrix.d.ts +2 -0
- package/types/process/lineToCubic.d.ts +1 -0
- package/types/process/normalizePath.d.ts +1 -0
- package/types/process/normalizeSegment.d.ts +1 -0
- package/types/process/optimizePath.d.ts +1 -0
- package/types/process/projection2d.d.ts +1 -0
- package/types/process/quadToCubic.d.ts +1 -0
- package/types/process/reverseCurve.d.ts +1 -0
- package/types/process/reversePath.d.ts +1 -0
- package/types/process/roundPath.d.ts +1 -0
- package/types/process/segmentToCubic.d.ts +1 -0
- package/types/process/shorthandToCubic.d.ts +4 -0
- package/types/process/shorthandToQuad.d.ts +4 -0
- package/types/process/splitPath.d.ts +1 -0
- package/types/process/transformEllipse.d.ts +5 -0
- package/types/process/transformPath.d.ts +1 -0
- package/types/svg-path-commander.d.ts +18 -0
- package/types/util/getCubicSize.d.ts +1 -0
- package/types/util/getDrawDirection.d.ts +1 -0
- package/types/util/getPathArea.d.ts +1 -0
- package/types/util/getPathBBox.d.ts +1 -0
- package/types/util/getPathLength.d.ts +1 -0
- package/types/util/getPointAtLength.d.ts +1 -0
- package/types/util/getPointAtSegLength.d.ts +4 -0
- package/types/util/getSegCubicLength.d.ts +1 -0
- package/types/util/isAbsoluteArray.d.ts +1 -0
- package/types/util/isCurveArray.d.ts +1 -0
- package/types/util/isNormalizedArray.d.ts +1 -0
- package/types/util/isPathArray.d.ts +1 -0
- package/types/util/isRelativeArray.d.ts +1 -0
- package/types/util/isValidPath.d.ts +1 -0
- package/types/util/shapeToPath.d.ts +6 -0
- package/types/util/util.d.ts +61 -0
- package/types/util/version.d.ts +2 -0
- package/src/index.js +0 -3
- package/types/types.d.ts +0 -83
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* SVGPathCommander v0.1.
|
|
2
|
+
* SVGPathCommander v0.1.10 (http://thednp.github.io/svg-path-commander)
|
|
3
3
|
* Copyright 2021 © thednp
|
|
4
4
|
* Licensed under MIT (https://github.com/thednp/svg-path-commander/blob/master/LICENSE)
|
|
5
5
|
*/
|
|
@@ -23,31 +23,26 @@ const paramsCount = {
|
|
|
23
23
|
/**
|
|
24
24
|
* Breaks the parsing of a pathString once a segment is finalized.
|
|
25
25
|
*
|
|
26
|
-
* @param {
|
|
26
|
+
* @param {svgpcNS.pathParser} path the `PathParser` instance
|
|
27
27
|
*/
|
|
28
28
|
function finalizeSegment(path) {
|
|
29
29
|
let pathCommand = path.pathValue[path.segmentStart];
|
|
30
|
-
let
|
|
31
|
-
let
|
|
30
|
+
let LK = pathCommand.toLowerCase();
|
|
31
|
+
let { data } = path;
|
|
32
32
|
|
|
33
33
|
// Process duplicated commands (without comand name)
|
|
34
|
-
if (
|
|
35
|
-
path.segments.push([pathCommand,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pathCommand =
|
|
34
|
+
if (LK === 'm' && data.length > 2) {
|
|
35
|
+
path.segments.push([pathCommand, data[0], data[1]]);
|
|
36
|
+
data = data.slice(2);
|
|
37
|
+
LK = 'l';
|
|
38
|
+
pathCommand = pathCommand === 'm' ? 'l' : 'L';
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
while (data.length >= paramsCount[LK]) {
|
|
42
42
|
// @ts-ignore
|
|
43
|
-
path.segments.push([pathCommand].concat(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// @ts-ignore
|
|
47
|
-
path.segments.push([pathCommand].concat(params.splice(0, paramsCount[pathComLK])));
|
|
48
|
-
if (!paramsCount[pathComLK]) {
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
43
|
+
path.segments.push([pathCommand].concat(data.splice(0, paramsCount[LK])));
|
|
44
|
+
if (!paramsCount[LK]) {
|
|
45
|
+
break;
|
|
51
46
|
}
|
|
52
47
|
}
|
|
53
48
|
}
|
|
@@ -58,7 +53,7 @@ const invalidPathValue = 'Invalid path value';
|
|
|
58
53
|
* Validates an A (arc-to) specific path command value.
|
|
59
54
|
* Usually a `large-arc-flag` or `sweep-flag`.
|
|
60
55
|
*
|
|
61
|
-
* @param {
|
|
56
|
+
* @param {svgpcNS.pathParser} path the `PathParser` instance
|
|
62
57
|
*/
|
|
63
58
|
function scanFlag(path) {
|
|
64
59
|
const { index } = path;
|
|
@@ -93,7 +88,7 @@ function isDigit(code) {
|
|
|
93
88
|
* Validates every character of the path string,
|
|
94
89
|
* every path command, negative numbers or floating point numbers.
|
|
95
90
|
*
|
|
96
|
-
* @param {
|
|
91
|
+
* @param {svgpcNS.pathParser} path the `PathParser` instance
|
|
97
92
|
*/
|
|
98
93
|
function scanParam(path) {
|
|
99
94
|
const { max, pathValue, index: start } = path;
|
|
@@ -205,7 +200,7 @@ function isSpace(ch) {
|
|
|
205
200
|
* path string every time it encounters any kind of
|
|
206
201
|
* space character.
|
|
207
202
|
*
|
|
208
|
-
* @param {
|
|
203
|
+
* @param {svgpcNS.pathParser} path the `PathParser` instance
|
|
209
204
|
*/
|
|
210
205
|
function skipSpaces(path) {
|
|
211
206
|
const { pathValue, max } = path;
|
|
@@ -233,7 +228,7 @@ function isPathCommand(code) {
|
|
|
233
228
|
case 0x71/* q */:
|
|
234
229
|
case 0x74/* t */:
|
|
235
230
|
case 0x61/* a */:
|
|
236
|
-
case 0x72/* r */:
|
|
231
|
+
// case 0x72/* r */: // R is not supported
|
|
237
232
|
return true;
|
|
238
233
|
default:
|
|
239
234
|
return false;
|
|
@@ -269,7 +264,7 @@ function isArcCommand(code) {
|
|
|
269
264
|
* Scans every character in the path string to determine
|
|
270
265
|
* where a segment starts and where it ends.
|
|
271
266
|
*
|
|
272
|
-
* @param {
|
|
267
|
+
* @param {svgpcNS.pathParser} path the `PathParser` instance
|
|
273
268
|
*/
|
|
274
269
|
function scanSegment(path) {
|
|
275
270
|
const { max, pathValue, index } = path;
|
|
@@ -326,29 +321,28 @@ function scanSegment(path) {
|
|
|
326
321
|
finalizeSegment(path);
|
|
327
322
|
}
|
|
328
323
|
|
|
329
|
-
// @ts-nocheck
|
|
330
324
|
/**
|
|
331
325
|
* Returns a clone of an existing `pathArray`.
|
|
332
326
|
*
|
|
333
|
-
* @param {
|
|
334
|
-
* @returns {
|
|
327
|
+
* @param {svgpcNS.pathArray | any[] | string} path the source `pathArray`
|
|
328
|
+
* @returns {any} the cloned `pathArray`
|
|
335
329
|
*/
|
|
336
330
|
function clonePath(path) {
|
|
337
|
-
return path.map((x) => {
|
|
331
|
+
return Array.isArray(path) ? path.map((x) => {
|
|
338
332
|
if (Array.isArray(x)) {
|
|
339
333
|
return clonePath(x);
|
|
340
334
|
}
|
|
341
335
|
return !Number.isNaN(+x) ? +x : x;
|
|
342
|
-
});
|
|
336
|
+
}) : path;
|
|
343
337
|
}
|
|
344
338
|
|
|
345
339
|
/**
|
|
346
|
-
* The `
|
|
340
|
+
* The `PathParser` used by the parser.
|
|
347
341
|
*
|
|
348
342
|
* @param {string} pathString
|
|
349
343
|
*/
|
|
350
|
-
function
|
|
351
|
-
/** @type {
|
|
344
|
+
function PathParser(pathString) {
|
|
345
|
+
/** @type {svgpcNS.pathArray} */
|
|
352
346
|
this.segments = [];
|
|
353
347
|
/** @type {string} */
|
|
354
348
|
this.pathValue = pathString;
|
|
@@ -369,7 +363,7 @@ function SVGPathArray(pathString) {
|
|
|
369
363
|
/**
|
|
370
364
|
* Iterates an array to check if it's an actual `pathArray`.
|
|
371
365
|
*
|
|
372
|
-
* @param {string |
|
|
366
|
+
* @param {string | svgpcNS.pathArray} path the `pathArray` to be checked
|
|
373
367
|
* @returns {boolean} iteration result
|
|
374
368
|
*/
|
|
375
369
|
function isPathArray(path) {
|
|
@@ -383,16 +377,15 @@ function isPathArray(path) {
|
|
|
383
377
|
* Parses a path string value and returns an array
|
|
384
378
|
* of segments we like to call `pathArray`.
|
|
385
379
|
*
|
|
386
|
-
* @param {
|
|
387
|
-
* @returns {
|
|
380
|
+
* @param {svgpcNS.pathArray | string} pathInput the string to be parsed
|
|
381
|
+
* @returns {svgpcNS.pathArray} the resulted `pathArray`
|
|
388
382
|
*/
|
|
389
383
|
function parsePathString(pathInput) {
|
|
390
384
|
if (isPathArray(pathInput)) {
|
|
391
|
-
// @ts-ignore
|
|
392
385
|
return clonePath(pathInput);
|
|
393
386
|
}
|
|
394
|
-
|
|
395
|
-
const path = new
|
|
387
|
+
|
|
388
|
+
const path = new PathParser(`${pathInput}`); // TS expects string
|
|
396
389
|
|
|
397
390
|
skipSpaces(path);
|
|
398
391
|
|
|
@@ -403,7 +396,7 @@ function parsePathString(pathInput) {
|
|
|
403
396
|
if (path.err.length) {
|
|
404
397
|
path.segments = [];
|
|
405
398
|
} else if (path.segments.length) {
|
|
406
|
-
if ('mM'.
|
|
399
|
+
if (!'mM'.includes(path.segments[0][0])) {
|
|
407
400
|
path.err = `${invalidPathValue}: missing M/m`;
|
|
408
401
|
path.segments = [];
|
|
409
402
|
} else {
|
|
@@ -418,7 +411,7 @@ function parsePathString(pathInput) {
|
|
|
418
411
|
* Iterates an array to check if it's a `pathArray`
|
|
419
412
|
* with all absolute values.
|
|
420
413
|
*
|
|
421
|
-
* @param {string |
|
|
414
|
+
* @param {string | svgpcNS.pathArray} path the `pathArray` to be checked
|
|
422
415
|
* @returns {boolean} iteration result
|
|
423
416
|
*/
|
|
424
417
|
function isAbsoluteArray(path) {
|
|
@@ -430,17 +423,17 @@ function isAbsoluteArray(path) {
|
|
|
430
423
|
* Parses a path string value or object and returns an array
|
|
431
424
|
* of segments, all converted to absolute values.
|
|
432
425
|
*
|
|
433
|
-
* @param {
|
|
434
|
-
* @returns {
|
|
426
|
+
* @param {svgpcNS.pathArray | string} pathInput the path string | object
|
|
427
|
+
* @returns {svgpcNS.pathArray} the resulted `pathArray` with absolute values
|
|
435
428
|
*/
|
|
436
429
|
function pathToAbsolute(pathInput) {
|
|
437
|
-
if (
|
|
430
|
+
if (isAbsoluteArray(pathInput)) {
|
|
438
431
|
return clonePath(pathInput);
|
|
439
432
|
}
|
|
440
433
|
|
|
441
434
|
const path = parsePathString(pathInput);
|
|
442
435
|
const ii = path.length;
|
|
443
|
-
/** @type {
|
|
436
|
+
/** @type {svgpcNS.pathArray} */
|
|
444
437
|
const resultArray = [];
|
|
445
438
|
let x = 0;
|
|
446
439
|
let y = 0;
|
|
@@ -461,6 +454,8 @@ function pathToAbsolute(pathInput) {
|
|
|
461
454
|
const segment = path[i];
|
|
462
455
|
const [pathCommand] = segment;
|
|
463
456
|
const absCommand = pathCommand.toUpperCase();
|
|
457
|
+
/** @type {svgpcNS.pathSegment} */
|
|
458
|
+
// @ts-ignore -- trust me
|
|
464
459
|
const absoluteSegment = [];
|
|
465
460
|
let newSeg = [];
|
|
466
461
|
|
|
@@ -495,7 +490,7 @@ function pathToAbsolute(pathInput) {
|
|
|
495
490
|
absoluteSegment.push(segment[j]);
|
|
496
491
|
}
|
|
497
492
|
}
|
|
498
|
-
|
|
493
|
+
|
|
499
494
|
resultArray.push(absoluteSegment);
|
|
500
495
|
|
|
501
496
|
const segLength = absoluteSegment.length;
|
|
@@ -528,7 +523,7 @@ function pathToAbsolute(pathInput) {
|
|
|
528
523
|
* Iterates an array to check if it's a `pathArray`
|
|
529
524
|
* with relative values.
|
|
530
525
|
*
|
|
531
|
-
* @param {string |
|
|
526
|
+
* @param {string | svgpcNS.pathArray} path the `pathArray` to be checked
|
|
532
527
|
* @returns {boolean} iteration result
|
|
533
528
|
*/
|
|
534
529
|
function isRelativeArray(path) {
|
|
@@ -540,17 +535,17 @@ function isRelativeArray(path) {
|
|
|
540
535
|
* Parses a path string value or object and returns an array
|
|
541
536
|
* of segments, all converted to relative values.
|
|
542
537
|
*
|
|
543
|
-
* @param {string |
|
|
544
|
-
* @returns {
|
|
538
|
+
* @param {string | svgpcNS.pathArray} pathInput the path string | object
|
|
539
|
+
* @returns {svgpcNS.pathArray} the resulted `pathArray` with relative values
|
|
545
540
|
*/
|
|
546
541
|
function pathToRelative(pathInput) {
|
|
547
|
-
if (
|
|
542
|
+
if (isRelativeArray(pathInput)) {
|
|
548
543
|
return clonePath(pathInput);
|
|
549
544
|
}
|
|
550
545
|
|
|
551
546
|
const path = parsePathString(pathInput);
|
|
552
547
|
const ii = path.length;
|
|
553
|
-
/** @type {
|
|
548
|
+
/** @type {svgpcNS.pathArray} */
|
|
554
549
|
const resultArray = [];
|
|
555
550
|
let x = 0;
|
|
556
551
|
let y = 0;
|
|
@@ -571,7 +566,9 @@ function pathToRelative(pathInput) {
|
|
|
571
566
|
const segment = path[i];
|
|
572
567
|
const [pathCommand] = segment;
|
|
573
568
|
const relativeCommand = pathCommand.toLowerCase();
|
|
574
|
-
|
|
569
|
+
/** @type {svgpcNS.pathSegment} */
|
|
570
|
+
// @ts-ignore -- trust me DON'T CHANGE
|
|
571
|
+
const relativeSegment = [];
|
|
575
572
|
let newSeg = [];
|
|
576
573
|
|
|
577
574
|
if (pathCommand !== relativeCommand) {
|
|
@@ -607,7 +604,6 @@ function pathToRelative(pathInput) {
|
|
|
607
604
|
relativeSegment.push(segment[j]);
|
|
608
605
|
}
|
|
609
606
|
}
|
|
610
|
-
// @ts-ignore
|
|
611
607
|
resultArray.push(relativeSegment);
|
|
612
608
|
|
|
613
609
|
const segLength = relativeSegment.length;
|
|
@@ -635,39 +631,54 @@ function pathToRelative(pathInput) {
|
|
|
635
631
|
* Rounds the values of a `pathArray` instance to
|
|
636
632
|
* a specified amount of decimals and returns it.
|
|
637
633
|
*
|
|
638
|
-
* @param {
|
|
639
|
-
* @param {
|
|
640
|
-
* @returns {
|
|
634
|
+
* @param {svgpcNS.pathArray} path the source `pathArray`
|
|
635
|
+
* @param {number | boolean | null} round the amount of decimals to round numbers to
|
|
636
|
+
* @returns {svgpcNS.pathArray} the resulted `pathArray` with rounded values
|
|
641
637
|
*/
|
|
642
638
|
function roundPath(path, round) {
|
|
643
639
|
const { round: defaultRound, decimals: defaultDecimals } = SVGPCO;
|
|
644
640
|
const decimalsOption = round && !Number.isNaN(+round) ? +round
|
|
645
641
|
: defaultRound && defaultDecimals;
|
|
646
642
|
|
|
647
|
-
if (!decimalsOption) return clonePath(path);
|
|
643
|
+
if (round === false || (!defaultRound && !decimalsOption)) return clonePath(path);
|
|
648
644
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
645
|
+
const dc = 10 ** decimalsOption;
|
|
646
|
+
/** @type {svgpcNS.pathArray} */
|
|
647
|
+
const result = [];
|
|
648
|
+
const pl = path.length;
|
|
649
|
+
/** @type {svgpcNS.pathSegment} */
|
|
650
|
+
let segment;
|
|
651
|
+
/** @type {number} */
|
|
652
|
+
let n = 0;
|
|
653
|
+
let pi = [];
|
|
654
|
+
|
|
655
|
+
// FOR works best with TS
|
|
656
|
+
for (let i = 0; i < pl; i += 1) {
|
|
657
|
+
pi = path[i];
|
|
658
|
+
segment = [''];
|
|
659
|
+
for (let j = 0; j < pi.length; j += 1) {
|
|
660
|
+
if (!j) segment[j] = pi[j];
|
|
661
|
+
else {
|
|
662
|
+
n = +pi[j];
|
|
663
|
+
segment.push(!j || n % 1 === 0 ? n : Math.round(n * dc) / dc);
|
|
664
|
+
}
|
|
655
665
|
}
|
|
656
|
-
|
|
657
|
-
}
|
|
666
|
+
result.push(segment);
|
|
667
|
+
}
|
|
668
|
+
return result;
|
|
658
669
|
}
|
|
659
670
|
|
|
660
671
|
/**
|
|
661
672
|
* Returns a valid `d` attribute string value created
|
|
662
673
|
* by rounding values and concatenating the `pathArray` segments.
|
|
663
674
|
*
|
|
664
|
-
* @param {
|
|
665
|
-
* @param {
|
|
675
|
+
* @param {svgpcNS.pathArray} path the `pathArray` object
|
|
676
|
+
* @param {any} round amount of decimals to round values to
|
|
666
677
|
* @returns {string} the concatenated path string
|
|
667
678
|
*/
|
|
668
679
|
function pathToString(path, round) {
|
|
669
680
|
return roundPath(path, round)
|
|
670
|
-
.map((x) => x[0]
|
|
681
|
+
.map((x) => x[0] + (x.slice(1).join(' '))).join('');
|
|
671
682
|
}
|
|
672
683
|
|
|
673
684
|
/**
|
|
@@ -707,9 +718,9 @@ function shorthandToCubic(x1, y1, x2, y2, prevCommand) {
|
|
|
707
718
|
/**
|
|
708
719
|
* Normalizes a single segment of a `pathArray` object.
|
|
709
720
|
*
|
|
710
|
-
* @param {
|
|
721
|
+
* @param {svgpcNS.pathSegment} segment the segment object
|
|
711
722
|
* @param {any} params the coordinates of the previous segment
|
|
712
|
-
* @param {
|
|
723
|
+
* @param {string} prevCommand the path command of the previous segment
|
|
713
724
|
* @returns {any} the normalized segment
|
|
714
725
|
*/
|
|
715
726
|
function normalizeSegment(segment, params, prevCommand) {
|
|
@@ -717,7 +728,7 @@ function normalizeSegment(segment, params, prevCommand) {
|
|
|
717
728
|
const xy = segment.slice(1);
|
|
718
729
|
let result = segment.slice();
|
|
719
730
|
|
|
720
|
-
if ('TQ'.
|
|
731
|
+
if (!'TQ'.includes(segment[0])) {
|
|
721
732
|
// optional but good to be cautious
|
|
722
733
|
params.qx = null;
|
|
723
734
|
params.qy = null;
|
|
@@ -750,7 +761,7 @@ function normalizeSegment(segment, params, prevCommand) {
|
|
|
750
761
|
* with all segments are in non-shorthand notation
|
|
751
762
|
* with absolute values.
|
|
752
763
|
*
|
|
753
|
-
* @param {string |
|
|
764
|
+
* @param {string | svgpcNS.pathArray} path the `pathArray` to be checked
|
|
754
765
|
* @returns {boolean} iteration result
|
|
755
766
|
*/
|
|
756
767
|
function isNormalizedArray(path) {
|
|
@@ -765,8 +776,8 @@ function isNormalizedArray(path) {
|
|
|
765
776
|
* * convert segments to absolute values
|
|
766
777
|
* * convert shorthand path commands to their non-shorthand notation
|
|
767
778
|
*
|
|
768
|
-
* @param {string |
|
|
769
|
-
* @returns {
|
|
779
|
+
* @param {string | svgpcNS.pathArray} pathInput the string to be parsed or 'pathArray'
|
|
780
|
+
* @returns {svgpcNS.pathArray} the normalized `pathArray`
|
|
770
781
|
*/
|
|
771
782
|
function normalizePath(pathInput) { // path|pathString
|
|
772
783
|
if (Array.isArray(pathInput) && isNormalizedArray(pathInput)) {
|
|
@@ -779,13 +790,14 @@ function normalizePath(pathInput) { // path|pathString
|
|
|
779
790
|
};
|
|
780
791
|
const allPathCommands = [];
|
|
781
792
|
const ii = path.length;
|
|
793
|
+
let pathCommand = '';
|
|
782
794
|
let prevCommand = '';
|
|
783
795
|
let segment;
|
|
784
796
|
let seglen;
|
|
785
797
|
|
|
786
798
|
for (let i = 0; i < ii; i += 1) {
|
|
787
799
|
// save current path command
|
|
788
|
-
|
|
800
|
+
[pathCommand] = path[i];
|
|
789
801
|
|
|
790
802
|
// Save current path command
|
|
791
803
|
allPathCommands[i] = pathCommand;
|
|
@@ -809,8 +821,8 @@ function normalizePath(pathInput) { // path|pathString
|
|
|
809
821
|
* Reverses all segments and their values of a `pathArray`
|
|
810
822
|
* and returns a new instance.
|
|
811
823
|
*
|
|
812
|
-
* @param {
|
|
813
|
-
* @returns {
|
|
824
|
+
* @param {svgpcNS.pathArray} pathInput the source `pathArray`
|
|
825
|
+
* @returns {svgpcNS.pathArray} the reversed `pathArray`
|
|
814
826
|
*/
|
|
815
827
|
function reversePath(pathInput) {
|
|
816
828
|
const absolutePath = pathToAbsolute(pathInput);
|
|
@@ -899,7 +911,7 @@ function reversePath(pathInput) {
|
|
|
899
911
|
* In the process, values are converted to absolute
|
|
900
912
|
* for visual consistency.
|
|
901
913
|
*
|
|
902
|
-
* @param {
|
|
914
|
+
* @param {svgpcNS.pathArray | string} pathInput the cubic-bezier parameters
|
|
903
915
|
* @return {string[]} an array with all sub-path strings
|
|
904
916
|
*/
|
|
905
917
|
function splitPath(pathInput) {
|
|
@@ -916,16 +928,19 @@ function splitPath(pathInput) {
|
|
|
916
928
|
* * create a new `pathArray` with elements with shortest segments
|
|
917
929
|
* from absolute and relative `pathArray`s
|
|
918
930
|
*
|
|
919
|
-
* @param {string |
|
|
931
|
+
* @param {string | svgpcNS.pathArray} pathInput a string or `pathArray`
|
|
920
932
|
* @param {number | null} round the amount of decimals to round values to
|
|
921
|
-
* @returns {
|
|
933
|
+
* @returns {svgpcNS.pathArray} the optimized `pathArray`
|
|
922
934
|
*/
|
|
923
935
|
function optimizePath(pathInput, round) {
|
|
924
936
|
const absolutePath = roundPath(pathToAbsolute(pathInput), round);
|
|
925
937
|
const relativePath = roundPath(pathToRelative(pathInput), round);
|
|
938
|
+
|
|
926
939
|
return absolutePath.map((x, i) => {
|
|
927
940
|
if (i) {
|
|
928
|
-
return x.join('').length < relativePath[i].join('').length
|
|
941
|
+
return x.join('').length < relativePath[i].join('').length
|
|
942
|
+
? x
|
|
943
|
+
: relativePath[i];
|
|
929
944
|
}
|
|
930
945
|
return x;
|
|
931
946
|
});
|
|
@@ -934,7 +949,7 @@ function optimizePath(pathInput, round) {
|
|
|
934
949
|
/**
|
|
935
950
|
* A global namespace for epsilon.
|
|
936
951
|
*
|
|
937
|
-
* @type {
|
|
952
|
+
* @type {number}
|
|
938
953
|
*/
|
|
939
954
|
const epsilon = 1e-9;
|
|
940
955
|
|
|
@@ -1069,13 +1084,13 @@ function arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, recursive) {
|
|
|
1069
1084
|
/**
|
|
1070
1085
|
* Converts a Q (quadratic-bezier) segment to C (cubic-bezier).
|
|
1071
1086
|
*
|
|
1072
|
-
* @param {
|
|
1073
|
-
* @param {
|
|
1074
|
-
* @param {
|
|
1075
|
-
* @param {
|
|
1076
|
-
* @param {
|
|
1077
|
-
* @param {
|
|
1078
|
-
* @returns {
|
|
1087
|
+
* @param {number} x1 curve start x
|
|
1088
|
+
* @param {number} y1 curve start y
|
|
1089
|
+
* @param {number} qx control point x
|
|
1090
|
+
* @param {number} qy control point y
|
|
1091
|
+
* @param {number} x2 curve end x
|
|
1092
|
+
* @param {number} y2 curve end y
|
|
1093
|
+
* @returns {number[]} the cubic-bezier segment
|
|
1079
1094
|
*/
|
|
1080
1095
|
function quadToCubic(x1, y1, qx, qy, x2, y2) {
|
|
1081
1096
|
const r13 = 1 / 3;
|
|
@@ -1150,7 +1165,7 @@ function lineToCubic(x1, y1, x2, y2) {
|
|
|
1150
1165
|
const p4 = midPoint(p2, p3, t);
|
|
1151
1166
|
const p5 = midPoint(p3, p4, t);
|
|
1152
1167
|
const p6 = midPoint(p4, p5, t);
|
|
1153
|
-
// @ts-ignore
|
|
1168
|
+
// @ts-ignore -- rest operator won't fix
|
|
1154
1169
|
const cp1 = getPointAtSegLength.apply(0, p0.concat(p2, p4, p6, t));
|
|
1155
1170
|
// @ts-ignore
|
|
1156
1171
|
const cp2 = getPointAtSegLength.apply(0, p6.concat(p5, p3, p1, 0));
|
|
@@ -1161,12 +1176,12 @@ function lineToCubic(x1, y1, x2, y2) {
|
|
|
1161
1176
|
/**
|
|
1162
1177
|
* Converts any segment to C (cubic-bezier).
|
|
1163
1178
|
*
|
|
1164
|
-
* @param {
|
|
1165
|
-
* @param {
|
|
1166
|
-
* @returns {
|
|
1179
|
+
* @param {svgpcNS.pathSegment} segment the source segment
|
|
1180
|
+
* @param {svgpcNS.parserParams} params the source segment parameters
|
|
1181
|
+
* @returns {svgpcNS.pathSegment} the cubic-bezier segment
|
|
1167
1182
|
*/
|
|
1168
1183
|
function segmentToCubic(segment, params) {
|
|
1169
|
-
if ('TQ'.
|
|
1184
|
+
if (!'TQ'.includes(segment[0])) {
|
|
1170
1185
|
params.qx = null;
|
|
1171
1186
|
params.qy = null;
|
|
1172
1187
|
}
|
|
@@ -1199,7 +1214,7 @@ function segmentToCubic(segment, params) {
|
|
|
1199
1214
|
/**
|
|
1200
1215
|
* Splits an extended A (arc-to) segment into two cubic-bezier segments.
|
|
1201
1216
|
*
|
|
1202
|
-
* @param {
|
|
1217
|
+
* @param {svgpcNS.pathArray} path the `pathArray` this segment belongs to
|
|
1203
1218
|
* @param {string[]} allPathCommands all previous path commands
|
|
1204
1219
|
* @param {Number} i the index of the segment
|
|
1205
1220
|
*/
|
|
@@ -1213,23 +1228,13 @@ function fixArc(path, allPathCommands, i) {
|
|
|
1213
1228
|
// if created multiple C:s, their original seg is saved
|
|
1214
1229
|
allPathCommands[i] = 'A';
|
|
1215
1230
|
// path.splice(i++, 0, ['C'].concat(segment.splice(0, 6)));
|
|
1216
|
-
// @ts-ignore
|
|
1231
|
+
// @ts-ignore -- cannot fix
|
|
1217
1232
|
path.splice(ni += 1, 0, ['C'].concat(segment.splice(0, 6)));
|
|
1218
1233
|
}
|
|
1219
1234
|
path.splice(i, 1);
|
|
1220
1235
|
}
|
|
1221
1236
|
}
|
|
1222
1237
|
|
|
1223
|
-
var version$1 = "0.0.16alpha4";
|
|
1224
|
-
|
|
1225
|
-
// @ts-ignore
|
|
1226
|
-
|
|
1227
|
-
/**
|
|
1228
|
-
* A global namespace for library version.
|
|
1229
|
-
* @type {string}
|
|
1230
|
-
*/
|
|
1231
|
-
const DMVersion = version$1;
|
|
1232
|
-
|
|
1233
1238
|
// DOMMatrix Static methods
|
|
1234
1239
|
// * `fromFloat64Array` and `fromFloat32Array` methods are not supported;
|
|
1235
1240
|
// * `fromArray` a more simple implementation, should also accept float[32/64]Array;
|
|
@@ -1291,25 +1296,25 @@ function fromArray(array) {
|
|
|
1291
1296
|
m.m34 = m34;
|
|
1292
1297
|
m.m44 = m44;
|
|
1293
1298
|
} else if (a.length === 6) {
|
|
1294
|
-
const [
|
|
1299
|
+
const [M11, M12, M21, M22, M41, M42] = a;
|
|
1295
1300
|
|
|
1296
|
-
m.m11 =
|
|
1297
|
-
m.a =
|
|
1301
|
+
m.m11 = M11;
|
|
1302
|
+
m.a = M11;
|
|
1298
1303
|
|
|
1299
|
-
m.m12 =
|
|
1300
|
-
m.b =
|
|
1304
|
+
m.m12 = M12;
|
|
1305
|
+
m.b = M12;
|
|
1301
1306
|
|
|
1302
|
-
m.m21 =
|
|
1303
|
-
m.c =
|
|
1307
|
+
m.m21 = M21;
|
|
1308
|
+
m.c = M21;
|
|
1304
1309
|
|
|
1305
|
-
m.m22 =
|
|
1306
|
-
m.d =
|
|
1310
|
+
m.m22 = M22;
|
|
1311
|
+
m.d = M22;
|
|
1307
1312
|
|
|
1308
|
-
m.m41 =
|
|
1309
|
-
m.e =
|
|
1313
|
+
m.m41 = M41;
|
|
1314
|
+
m.e = M41;
|
|
1310
1315
|
|
|
1311
|
-
m.m42 =
|
|
1312
|
-
m.f =
|
|
1316
|
+
m.m42 = M42;
|
|
1317
|
+
m.f = M42;
|
|
1313
1318
|
} else {
|
|
1314
1319
|
throw new TypeError('CSSMatrix: expecting an Array of 6/16 values.');
|
|
1315
1320
|
}
|
|
@@ -1320,7 +1325,7 @@ function fromArray(array) {
|
|
|
1320
1325
|
* Creates a new mutable `CSSMatrix` instance given an existing matrix or a
|
|
1321
1326
|
* `DOMMatrix` instance which provides the values for its properties.
|
|
1322
1327
|
*
|
|
1323
|
-
* @param {CSSMatrix | DOMMatrix |
|
|
1328
|
+
* @param {CSSMatrix | DOMMatrix | CSSMatrixNS.JSONMatrix} m the source matrix to feed values from.
|
|
1324
1329
|
* @return {CSSMatrix} the resulted matrix.
|
|
1325
1330
|
*/
|
|
1326
1331
|
function fromMatrix(m) {
|
|
@@ -1359,9 +1364,20 @@ function fromString(source) {
|
|
|
1359
1364
|
}
|
|
1360
1365
|
const str = String(source).replace(/\s/g, '');
|
|
1361
1366
|
let m = new CSSMatrix();
|
|
1367
|
+
const invalidStringError = `CSSMatrix: invalid transform string "${source}"`;
|
|
1362
1368
|
let is2D = true;
|
|
1369
|
+
// const transformFunctions = [
|
|
1370
|
+
// 'matrix', 'matrix3d', 'perspective', 'translate3d',
|
|
1371
|
+
// 'translate', 'translateX', 'translateY', 'translateZ',
|
|
1372
|
+
// 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ',
|
|
1373
|
+
// 'scale', 'scale3d', 'skewX', 'skewY'];
|
|
1363
1374
|
const tramsformObject = str.split(')').filter((f) => f).map((fn) => {
|
|
1364
1375
|
const [prop, value] = fn.split('(');
|
|
1376
|
+
if (!value) {
|
|
1377
|
+
// invalidate
|
|
1378
|
+
throw TypeError(invalidStringError);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1365
1381
|
const components = value.split(',')
|
|
1366
1382
|
.map((n) => (n.includes('rad') ? parseFloat(n) * (180 / Math.PI) : parseFloat(n)));
|
|
1367
1383
|
const [x, y, z, a] = components;
|
|
@@ -1421,6 +1437,8 @@ function fromString(source) {
|
|
|
1421
1437
|
// @ts-ignore unfortunately
|
|
1422
1438
|
m = m[fn](...axeValues);
|
|
1423
1439
|
}
|
|
1440
|
+
} else {
|
|
1441
|
+
throw TypeError(invalidStringError);
|
|
1424
1442
|
}
|
|
1425
1443
|
});
|
|
1426
1444
|
|
|
@@ -1711,7 +1729,7 @@ class CSSMatrix {
|
|
|
1711
1729
|
/**
|
|
1712
1730
|
* Sets a new `Boolean` flag value for `this.isIdentity` matrix property.
|
|
1713
1731
|
*
|
|
1714
|
-
* @param {
|
|
1732
|
+
* @param {boolean} value sets a new flag for this property
|
|
1715
1733
|
*/
|
|
1716
1734
|
set isIdentity(value) {
|
|
1717
1735
|
this.isIdentity = value;
|
|
@@ -1722,7 +1740,7 @@ class CSSMatrix {
|
|
|
1722
1740
|
* matrix is one in which every value is 0 except those on the main diagonal from top-left
|
|
1723
1741
|
* to bottom-right corner (in other words, where the offsets in each direction are equal).
|
|
1724
1742
|
*
|
|
1725
|
-
* @return {
|
|
1743
|
+
* @return {boolean} the current property value
|
|
1726
1744
|
*/
|
|
1727
1745
|
get isIdentity() {
|
|
1728
1746
|
const m = this;
|
|
@@ -1736,7 +1754,7 @@ class CSSMatrix {
|
|
|
1736
1754
|
* A `Boolean` flag whose value is `true` if the matrix was initialized as a 2D matrix
|
|
1737
1755
|
* and `false` if the matrix is 3D.
|
|
1738
1756
|
*
|
|
1739
|
-
* @return {
|
|
1757
|
+
* @return {boolean} the current property value
|
|
1740
1758
|
*/
|
|
1741
1759
|
get is2D() {
|
|
1742
1760
|
const m = this;
|
|
@@ -1746,7 +1764,7 @@ class CSSMatrix {
|
|
|
1746
1764
|
/**
|
|
1747
1765
|
* Sets a new `Boolean` flag value for `this.is2D` matrix property.
|
|
1748
1766
|
*
|
|
1749
|
-
* @param {
|
|
1767
|
+
* @param {boolean} value sets a new flag for this property
|
|
1750
1768
|
*/
|
|
1751
1769
|
set is2D(value) {
|
|
1752
1770
|
this.is2D = value;
|
|
@@ -1833,7 +1851,7 @@ class CSSMatrix {
|
|
|
1833
1851
|
* The result can also be used as a second parameter for the `fromMatrix` static method
|
|
1834
1852
|
* to load values into a matrix instance.
|
|
1835
1853
|
*
|
|
1836
|
-
* @return {
|
|
1854
|
+
* @return {CSSMatrixNS.JSONMatrix} an *Object* with all matrix values.
|
|
1837
1855
|
*/
|
|
1838
1856
|
toJSON() {
|
|
1839
1857
|
return JSON.parse(JSON.stringify(this));
|
|
@@ -1844,7 +1862,7 @@ class CSSMatrix {
|
|
|
1844
1862
|
* matrix multiplied by the passed matrix, with the passed matrix to the right.
|
|
1845
1863
|
* This matrix is not modified.
|
|
1846
1864
|
*
|
|
1847
|
-
* @param {CSSMatrix | DOMMatrix |
|
|
1865
|
+
* @param {CSSMatrix | DOMMatrix | CSSMatrixNS.JSONMatrix} m2 CSSMatrix
|
|
1848
1866
|
* @return {CSSMatrix} The resulted matrix.
|
|
1849
1867
|
*/
|
|
1850
1868
|
multiply(m2) {
|
|
@@ -1965,8 +1983,8 @@ class CSSMatrix {
|
|
|
1965
1983
|
*
|
|
1966
1984
|
* @copyright thednp © 2021
|
|
1967
1985
|
*
|
|
1968
|
-
* @param {
|
|
1969
|
-
* @return {
|
|
1986
|
+
* @param {CSSMatrixNS.PointTuple | DOMPoint} v Tuple or DOMPoint
|
|
1987
|
+
* @return {CSSMatrixNS.PointTuple} the resulting Tuple
|
|
1970
1988
|
*/
|
|
1971
1989
|
transformPoint(v) {
|
|
1972
1990
|
const M = this;
|
|
@@ -1988,8 +2006,8 @@ class CSSMatrix {
|
|
|
1988
2006
|
* {x,y,z,w} Tuple *Object* comprising the transformed vector.
|
|
1989
2007
|
* Neither the matrix nor the original vector are altered.
|
|
1990
2008
|
*
|
|
1991
|
-
* @param {
|
|
1992
|
-
* @return {
|
|
2009
|
+
* @param {CSSMatrixNS.PointTuple} t Tuple with `{x,y,z,w}` components
|
|
2010
|
+
* @return {CSSMatrixNS.PointTuple} the resulting Tuple
|
|
1993
2011
|
*/
|
|
1994
2012
|
transform(t) {
|
|
1995
2013
|
const m = this;
|
|
@@ -2018,19 +2036,18 @@ CSSMatrix.Multiply = Multiply;
|
|
|
2018
2036
|
CSSMatrix.fromArray = fromArray;
|
|
2019
2037
|
CSSMatrix.fromMatrix = fromMatrix;
|
|
2020
2038
|
CSSMatrix.fromString = fromString;
|
|
2021
|
-
CSSMatrix.Version = DMVersion;
|
|
2022
2039
|
|
|
2023
2040
|
/**
|
|
2024
2041
|
* Returns a transformation matrix to apply to `<path>` elements.
|
|
2025
2042
|
*
|
|
2026
|
-
* @param {
|
|
2043
|
+
* @param {svgpcNS.transformObject} transform the `transformObject`
|
|
2027
2044
|
* @returns {CSSMatrix} a new transformation matrix
|
|
2028
2045
|
*/
|
|
2029
2046
|
function getSVGMatrix(transform) {
|
|
2030
2047
|
let matrix = new CSSMatrix();
|
|
2031
2048
|
const { origin } = transform;
|
|
2032
|
-
const originX =
|
|
2033
|
-
const originY =
|
|
2049
|
+
const originX = origin[0];
|
|
2050
|
+
const originY = origin[1];
|
|
2034
2051
|
const { translate } = transform;
|
|
2035
2052
|
const { rotate } = transform;
|
|
2036
2053
|
const { skew } = transform;
|
|
@@ -2040,22 +2057,20 @@ function getSVGMatrix(transform) {
|
|
|
2040
2057
|
if ((Array.isArray(translate) && translate.some((x) => +x !== 0)) || !Number.isNaN(translate)) {
|
|
2041
2058
|
matrix = Array.isArray(translate)
|
|
2042
2059
|
? matrix.translate(+translate[0] || 0, +translate[1] || 0, +translate[2] || 0)
|
|
2043
|
-
|
|
2044
|
-
: matrix.translate(+translate || 0);
|
|
2060
|
+
: matrix.translate(+translate || 0, 0, 0);
|
|
2045
2061
|
}
|
|
2046
2062
|
|
|
2047
2063
|
if (rotate || skew || scale) {
|
|
2048
2064
|
// set SVG transform-origin, always defined
|
|
2049
2065
|
// matrix = matrix.translate(+originX,+originY,+originZ)
|
|
2050
|
-
// @ts-ignore
|
|
2066
|
+
// @ts-ignore -- SVG transform origin is always 2D
|
|
2051
2067
|
matrix = matrix.translate(+originX, +originY);
|
|
2052
2068
|
|
|
2053
2069
|
// set rotation
|
|
2054
2070
|
if (rotate) {
|
|
2055
2071
|
matrix = Array.isArray(rotate) && rotate.some((x) => +x !== 0)
|
|
2056
2072
|
? matrix.rotate(+rotate[0] || 0, +rotate[1] || 0, +rotate[2] || 0)
|
|
2057
|
-
|
|
2058
|
-
: matrix.rotate(+rotate || 0);
|
|
2073
|
+
: matrix.rotate(0, 0, +rotate || 0);
|
|
2059
2074
|
}
|
|
2060
2075
|
// set skew(s)
|
|
2061
2076
|
if (Array.isArray(skew) && skew.some((x) => +x !== 0)) {
|
|
@@ -2070,12 +2085,11 @@ function getSVGMatrix(transform) {
|
|
|
2070
2085
|
if (!Number.isNaN(scale) || (Array.isArray(scale) && scale.some((x) => +x !== 1))) {
|
|
2071
2086
|
matrix = Array.isArray(scale)
|
|
2072
2087
|
? (matrix.scale(+scale[0] || 1, +scale[1] || 1, +scale[2] || 1))
|
|
2073
|
-
|
|
2074
|
-
: matrix.scale(+scale || 1);
|
|
2088
|
+
: matrix.scale(+scale || 1, +scale || 1, +scale || 1);
|
|
2075
2089
|
}
|
|
2076
2090
|
// set SVG transform-origin
|
|
2077
2091
|
// matrix = matrix.translate(-originX,-originY,-originZ)
|
|
2078
|
-
// @ts-ignore
|
|
2092
|
+
// @ts-ignore -- SVG transform origin is always 2D
|
|
2079
2093
|
matrix = matrix.translate(-originX, -originY);
|
|
2080
2094
|
}
|
|
2081
2095
|
return matrix;
|
|
@@ -2162,7 +2176,7 @@ function transformEllipse(m, rx, ry, ax) {
|
|
|
2162
2176
|
* Details =>
|
|
2163
2177
|
* https://stackoverflow.com/questions/23792505/predicted-rendering-of-css-3d-transformed-pixel
|
|
2164
2178
|
*
|
|
2165
|
-
* @param {
|
|
2179
|
+
* @param {svgpcNS.CSSMatrix} m the transformation matrix
|
|
2166
2180
|
* @param {Number[]} point2D the initial [x,y] coordinates
|
|
2167
2181
|
* @param {number[]} origin the initial [x,y] coordinates
|
|
2168
2182
|
* @returns {Number[]} the projected [x,y] coordinates
|
|
@@ -2190,9 +2204,9 @@ function projection2d(m, point2D, origin) {
|
|
|
2190
2204
|
* Since *SVGElement* doesn't support 3D transformation, this function
|
|
2191
2205
|
* creates a 2D projection of the <path> element.
|
|
2192
2206
|
*
|
|
2193
|
-
* @param {
|
|
2207
|
+
* @param {svgpcNS.pathArray} path the `pathArray` to apply transformation
|
|
2194
2208
|
* @param {any} transform the transform functions `Object`
|
|
2195
|
-
* @returns {
|
|
2209
|
+
* @returns {svgpcNS.pathArray} the resulted `pathArray`
|
|
2196
2210
|
*/
|
|
2197
2211
|
function transformPath(path, transform) {
|
|
2198
2212
|
let x = 0; let y = 0; let i; let j; let ii; let jj; let lx; let ly; let te;
|
|
@@ -2324,7 +2338,7 @@ function transformPath(path, transform) {
|
|
|
2324
2338
|
* @param {number} c2y the second control point Y
|
|
2325
2339
|
* @param {number} p2x the ending point X
|
|
2326
2340
|
* @param {number} p2y the ending point Y
|
|
2327
|
-
* @returns {
|
|
2341
|
+
* @returns {svgpcNS.segmentLimits} the length of the cubic-bezier segment
|
|
2328
2342
|
*/
|
|
2329
2343
|
function getCubicSize(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
|
|
2330
2344
|
let a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x);
|
|
@@ -2380,7 +2394,7 @@ function getCubicSize(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
|
|
|
2380
2394
|
* Iterates an array to check if it's a `pathArray`
|
|
2381
2395
|
* with all C (cubic bezier) segments.
|
|
2382
2396
|
*
|
|
2383
|
-
* @param {string |
|
|
2397
|
+
* @param {string | svgpcNS.pathArray} path the `Array` to be checked
|
|
2384
2398
|
* @returns {boolean} iteration result
|
|
2385
2399
|
*/
|
|
2386
2400
|
function isCurveArray(path) {
|
|
@@ -2392,11 +2406,11 @@ function isCurveArray(path) {
|
|
|
2392
2406
|
* Parses a path string value or 'pathArray' and returns a new one
|
|
2393
2407
|
* in which all segments are converted to cubic-bezier.
|
|
2394
2408
|
*
|
|
2395
|
-
* @param {string |
|
|
2396
|
-
* @returns {
|
|
2409
|
+
* @param {string | svgpcNS.pathArray} pathInput the string to be parsed or object
|
|
2410
|
+
* @returns {svgpcNS.pathArray} the resulted `pathArray` converted to cubic-bezier
|
|
2397
2411
|
*/
|
|
2398
2412
|
function pathToCurve(pathInput) {
|
|
2399
|
-
if (
|
|
2413
|
+
if (isCurveArray(pathInput)) {
|
|
2400
2414
|
return clonePath(pathInput);
|
|
2401
2415
|
}
|
|
2402
2416
|
|
|
@@ -2404,15 +2418,15 @@ function pathToCurve(pathInput) {
|
|
|
2404
2418
|
const params = {
|
|
2405
2419
|
x1: 0, y1: 0, x2: 0, y2: 0, x: 0, y: 0, qx: null, qy: null,
|
|
2406
2420
|
};
|
|
2421
|
+
/** @type {string[]} */
|
|
2407
2422
|
const allPathCommands = [];
|
|
2408
|
-
let pathCommand = '';
|
|
2423
|
+
let pathCommand = ''; // ts-lint
|
|
2409
2424
|
let ii = path.length;
|
|
2410
2425
|
|
|
2411
2426
|
for (let i = 0; i < ii; i += 1) {
|
|
2412
2427
|
const segment = path[i];
|
|
2413
2428
|
const seglen = segment.length;
|
|
2414
2429
|
if (segment) [pathCommand] = segment;
|
|
2415
|
-
|
|
2416
2430
|
allPathCommands[i] = pathCommand;
|
|
2417
2431
|
path[i] = segmentToCubic(segment, params);
|
|
2418
2432
|
|
|
@@ -2431,8 +2445,8 @@ function pathToCurve(pathInput) {
|
|
|
2431
2445
|
/**
|
|
2432
2446
|
* Returns the bounding box of a shape.
|
|
2433
2447
|
*
|
|
2434
|
-
* @param {
|
|
2435
|
-
* @returns {
|
|
2448
|
+
* @param {svgpcNS.pathArray} path the shape `pathArray`
|
|
2449
|
+
* @returns {svgpcNS.pathBBox} the length of the cubic-bezier segment
|
|
2436
2450
|
*/
|
|
2437
2451
|
function getPathBBox(path) {
|
|
2438
2452
|
if (!path) {
|
|
@@ -2513,7 +2527,7 @@ function getCubicSegArea(x0, y0, x1, y1, x2, y2, x3, y3) {
|
|
|
2513
2527
|
*
|
|
2514
2528
|
* => https://github.com/paperjs/paper.js/blob/develop/src/path/Path.js
|
|
2515
2529
|
*
|
|
2516
|
-
* @param {
|
|
2530
|
+
* @param {svgpcNS.pathArray} path the shape `pathArray`
|
|
2517
2531
|
* @returns {number} the length of the cubic-bezier segment
|
|
2518
2532
|
*/
|
|
2519
2533
|
function getPathArea(path) {
|
|
@@ -2524,8 +2538,8 @@ function getPathArea(path) {
|
|
|
2524
2538
|
switch (seg[0]) {
|
|
2525
2539
|
case 'M':
|
|
2526
2540
|
case 'Z':
|
|
2527
|
-
|
|
2528
|
-
my = seg[0] === 'M' ? seg[2] : my;
|
|
2541
|
+
// @ts-ignore
|
|
2542
|
+
mx = seg[0] === 'M' ? seg[1] : mx; my = seg[0] === 'M' ? seg[2] : my;
|
|
2529
2543
|
x = mx;
|
|
2530
2544
|
y = my;
|
|
2531
2545
|
return 0;
|
|
@@ -2597,7 +2611,7 @@ function getSegCubicLength(x1, y1, x2, y2, x3, y3, x4, y4, z) {
|
|
|
2597
2611
|
* or the equivalent to `shape.getTotalLength()`
|
|
2598
2612
|
* pathToCurve version
|
|
2599
2613
|
*
|
|
2600
|
-
* @param {
|
|
2614
|
+
* @param {svgpcNS.pathArray} path the ending point Y
|
|
2601
2615
|
* @returns {number} the shape total length
|
|
2602
2616
|
*/
|
|
2603
2617
|
function getPathLength(path) {
|
|
@@ -2614,7 +2628,7 @@ function getPathLength(path) {
|
|
|
2614
2628
|
* Check if a path is drawn clockwise and returns true if so,
|
|
2615
2629
|
* false otherwise.
|
|
2616
2630
|
*
|
|
2617
|
-
* @param {string |
|
|
2631
|
+
* @param {string | svgpcNS.pathArray} path the path string or `pathArray`
|
|
2618
2632
|
* @returns {boolean} true when clockwise or false if not
|
|
2619
2633
|
*/
|
|
2620
2634
|
function getDrawDirection(path) {
|
|
@@ -2624,7 +2638,7 @@ function getDrawDirection(path) {
|
|
|
2624
2638
|
/**
|
|
2625
2639
|
* Returns [x,y] coordinates of a point at a given length of a shape.
|
|
2626
2640
|
*
|
|
2627
|
-
* @param {string |
|
|
2641
|
+
* @param {string | svgpcNS.pathArray} path the `pathArray` to look into
|
|
2628
2642
|
* @param {number} length the length of the shape to look at
|
|
2629
2643
|
* @returns {number[]} the requested [x,y] coordinates
|
|
2630
2644
|
*/
|
|
@@ -2665,7 +2679,7 @@ function isValidPath(pathString) {
|
|
|
2665
2679
|
return false;
|
|
2666
2680
|
}
|
|
2667
2681
|
|
|
2668
|
-
const path = new
|
|
2682
|
+
const path = new PathParser(pathString);
|
|
2669
2683
|
|
|
2670
2684
|
skipSpaces(path);
|
|
2671
2685
|
|
|
@@ -2678,6 +2692,7 @@ function isValidPath(pathString) {
|
|
|
2678
2692
|
|
|
2679
2693
|
/**
|
|
2680
2694
|
* Supported shapes and their specific parameters.
|
|
2695
|
+
* @type {Object.<string, string[]>}
|
|
2681
2696
|
*/
|
|
2682
2697
|
const shapeParams = {
|
|
2683
2698
|
circle: ['cx', 'cy', 'r'],
|
|
@@ -2691,8 +2706,8 @@ const shapeParams = {
|
|
|
2691
2706
|
/**
|
|
2692
2707
|
* Returns a new `pathArray` from line attributes.
|
|
2693
2708
|
*
|
|
2694
|
-
* @param {
|
|
2695
|
-
* @return {
|
|
2709
|
+
* @param {svgpcNS.lineAttr} attr shape configuration
|
|
2710
|
+
* @return {svgpcNS.pathArray} a new line `pathArray`
|
|
2696
2711
|
*/
|
|
2697
2712
|
function getLinePath(attr) {
|
|
2698
2713
|
const {
|
|
@@ -2704,11 +2719,11 @@ function getLinePath(attr) {
|
|
|
2704
2719
|
/**
|
|
2705
2720
|
* Returns a new `pathArray` like from polyline/polygon attributes.
|
|
2706
2721
|
*
|
|
2707
|
-
* @param {
|
|
2708
|
-
* @return {
|
|
2722
|
+
* @param {svgpcNS.polyAttr} attr shape configuration
|
|
2723
|
+
* @return {svgpcNS.pathArray} a new polygon/polyline `pathArray`
|
|
2709
2724
|
*/
|
|
2710
2725
|
function getPolyPath(attr) {
|
|
2711
|
-
/** @type {
|
|
2726
|
+
/** @type {svgpcNS.pathArray} */
|
|
2712
2727
|
const pathArray = [];
|
|
2713
2728
|
const points = attr.points.split(/[\s|,]/).map(Number);
|
|
2714
2729
|
|
|
@@ -2724,8 +2739,8 @@ function getPolyPath(attr) {
|
|
|
2724
2739
|
/**
|
|
2725
2740
|
* Returns a new `pathArray` from circle attributes.
|
|
2726
2741
|
*
|
|
2727
|
-
* @param {
|
|
2728
|
-
* @return {
|
|
2742
|
+
* @param {svgpcNS.circleAttr} attr shape configuration
|
|
2743
|
+
* @return {svgpcNS.pathArray} a circle `pathArray`
|
|
2729
2744
|
*/
|
|
2730
2745
|
function getCirclePath(attr) {
|
|
2731
2746
|
const {
|
|
@@ -2742,8 +2757,8 @@ function getCirclePath(attr) {
|
|
|
2742
2757
|
/**
|
|
2743
2758
|
* Returns a new `pathArray` from ellipse attributes.
|
|
2744
2759
|
*
|
|
2745
|
-
* @param {
|
|
2746
|
-
* @return {
|
|
2760
|
+
* @param {svgpcNS.ellipseAttr} attr shape configuration
|
|
2761
|
+
* @return {svgpcNS.pathArray} an ellipse `pathArray`
|
|
2747
2762
|
*/
|
|
2748
2763
|
function getEllipsePath(attr) {
|
|
2749
2764
|
const {
|
|
@@ -2760,8 +2775,8 @@ function getEllipsePath(attr) {
|
|
|
2760
2775
|
/**
|
|
2761
2776
|
* Returns a new `pathArray` like from rect attributes.
|
|
2762
2777
|
*
|
|
2763
|
-
* @param {
|
|
2764
|
-
* @return {
|
|
2778
|
+
* @param {svgpcNS.rectAttr} attr object with properties above
|
|
2779
|
+
* @return {svgpcNS.pathArray} a new `pathArray` from `<rect>` attributes
|
|
2765
2780
|
*/
|
|
2766
2781
|
function getRectanglePath(attr) {
|
|
2767
2782
|
const x = +attr.x || 0;
|
|
@@ -2809,7 +2824,7 @@ function getRectanglePath(attr) {
|
|
|
2809
2824
|
* The newly created `<path>` element keeps all non-specific
|
|
2810
2825
|
* attributes like `class`, `fill`, etc.
|
|
2811
2826
|
*
|
|
2812
|
-
* @param {
|
|
2827
|
+
* @param {svgpcNS.shapeTypes} element target shape
|
|
2813
2828
|
* @param {boolean} replace option to replace target
|
|
2814
2829
|
* @return {?SVGPathElement} the newly created `<path>` element
|
|
2815
2830
|
*/
|
|
@@ -2822,13 +2837,13 @@ function shapeToPath(element, replace) {
|
|
|
2822
2837
|
|
|
2823
2838
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
2824
2839
|
const type = element.tagName;
|
|
2825
|
-
/** @ts-ignore */
|
|
2826
2840
|
const shapeAttrs = shapeParams[type];
|
|
2827
|
-
|
|
2828
|
-
|
|
2841
|
+
/** set config
|
|
2842
|
+
* @type {any}
|
|
2843
|
+
*/
|
|
2829
2844
|
const config = {};
|
|
2830
2845
|
config.type = type;
|
|
2831
|
-
|
|
2846
|
+
|
|
2832
2847
|
shapeAttrs.forEach((p) => { config[p] = element.getAttribute(p); });
|
|
2833
2848
|
|
|
2834
2849
|
// set no-specific shape attributes: fill, stroke, etc
|
|
@@ -2838,16 +2853,14 @@ function shapeToPath(element, replace) {
|
|
|
2838
2853
|
|
|
2839
2854
|
// set d
|
|
2840
2855
|
let description;
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
else if (['polyline', 'polygon'].includes(type)) description = pathToString(getPolyPath(config));
|
|
2847
|
-
|
|
2848
|
-
else if (type === '
|
|
2849
|
-
/** @ts-ignore */
|
|
2850
|
-
else if (type === 'line') description = pathToString(getLinePath(config));
|
|
2856
|
+
const { round, decimals } = SVGPCO;
|
|
2857
|
+
const rounding = round && decimals ? decimals : null;
|
|
2858
|
+
|
|
2859
|
+
if (type === 'circle') description = pathToString(getCirclePath(config), rounding);
|
|
2860
|
+
else if (type === 'ellipse') description = pathToString(getEllipsePath(config), rounding);
|
|
2861
|
+
else if (['polyline', 'polygon'].includes(type)) description = pathToString(getPolyPath(config), rounding);
|
|
2862
|
+
else if (type === 'rect') description = pathToString(getRectanglePath(config), rounding);
|
|
2863
|
+
else if (type === 'line') description = pathToString(getLinePath(config), rounding);
|
|
2851
2864
|
else if (type === 'glyph') description = element.getAttribute('d');
|
|
2852
2865
|
|
|
2853
2866
|
// replace target element
|
|
@@ -2866,8 +2879,8 @@ function shapeToPath(element, replace) {
|
|
|
2866
2879
|
* Reverses all segments and their values from a `pathArray`
|
|
2867
2880
|
* which consists of only C (cubic-bezier) path commands.
|
|
2868
2881
|
*
|
|
2869
|
-
* @param {
|
|
2870
|
-
* @returns {
|
|
2882
|
+
* @param {svgpcNS.pathArray} path the source `pathArray`
|
|
2883
|
+
* @returns {svgpcNS.pathArray} the reversed `pathArray`
|
|
2871
2884
|
*/
|
|
2872
2885
|
function reverseCurve(path) {
|
|
2873
2886
|
const rotatedCurve = path.slice(1)
|
|
@@ -2883,7 +2896,7 @@ function reverseCurve(path) {
|
|
|
2883
2896
|
.concat(rotatedCurve.map((x) => ['C'].concat(x.slice(2))));
|
|
2884
2897
|
}
|
|
2885
2898
|
|
|
2886
|
-
var version = "0.1.
|
|
2899
|
+
var version = "0.1.10";
|
|
2887
2900
|
|
|
2888
2901
|
// @ts-ignore
|
|
2889
2902
|
|
|
@@ -2925,8 +2938,6 @@ const Util = {
|
|
|
2925
2938
|
Version,
|
|
2926
2939
|
};
|
|
2927
2940
|
|
|
2928
|
-
// import isPathArray from './util/isPathArray';
|
|
2929
|
-
|
|
2930
2941
|
/**
|
|
2931
2942
|
* Creates a new SVGPathCommander instance.
|
|
2932
2943
|
*
|
|
@@ -2948,13 +2959,13 @@ class SVGPathCommander {
|
|
|
2948
2959
|
round = 0;
|
|
2949
2960
|
}
|
|
2950
2961
|
|
|
2951
|
-
const { decimals } = round
|
|
2962
|
+
const { decimals } = round ? (options || SVGPCO) : { decimals: false };
|
|
2952
2963
|
|
|
2953
2964
|
// set instance options
|
|
2954
|
-
this.round =
|
|
2965
|
+
this.round = decimals;
|
|
2955
2966
|
// ZERO | FALSE will disable rounding numbers
|
|
2956
2967
|
|
|
2957
|
-
/** @type {
|
|
2968
|
+
/** @type {svgpcNS.pathArray} */
|
|
2958
2969
|
this.segments = parsePathString(pathValue);
|
|
2959
2970
|
|
|
2960
2971
|
/** * @type {string} */
|
|
@@ -2994,20 +3005,21 @@ class SVGPathCommander {
|
|
|
2994
3005
|
const { segments } = this;
|
|
2995
3006
|
const split = splitPath(this.toString());
|
|
2996
3007
|
const subPath = split.length > 1 ? split : 0;
|
|
3008
|
+
/**
|
|
3009
|
+
* @param {svgpcNS.pathArray} x
|
|
3010
|
+
* @param {number} i
|
|
3011
|
+
*/
|
|
3012
|
+
const reverser = (x, i) => {
|
|
3013
|
+
if (onlySubpath) {
|
|
3014
|
+
return i ? reversePath(x) : parsePathString(x);
|
|
3015
|
+
}
|
|
3016
|
+
return reversePath(x);
|
|
3017
|
+
};
|
|
2997
3018
|
|
|
2998
|
-
const absoluteMultiPath = subPath && clonePath(subPath)
|
|
2999
|
-
.map((x, i) => {
|
|
3000
|
-
if (onlySubpath) {
|
|
3001
|
-
// @ts-ignore
|
|
3002
|
-
return i ? reversePath(x) : parsePathString(x);
|
|
3003
|
-
}
|
|
3004
|
-
// @ts-ignore
|
|
3005
|
-
return reversePath(x);
|
|
3006
|
-
});
|
|
3019
|
+
const absoluteMultiPath = subPath && clonePath(subPath).map(reverser);
|
|
3007
3020
|
|
|
3008
3021
|
let path = [];
|
|
3009
3022
|
if (subPath) {
|
|
3010
|
-
// @ts-ignore
|
|
3011
3023
|
path = absoluteMultiPath.flat(1);
|
|
3012
3024
|
} else {
|
|
3013
3025
|
path = onlySubpath ? segments : reversePath(segments);
|
|
@@ -3045,7 +3057,7 @@ class SVGPathCommander {
|
|
|
3045
3057
|
|
|
3046
3058
|
/**
|
|
3047
3059
|
* Transform path using values from an `Object` defined as `transformObject`.
|
|
3048
|
-
* @see
|
|
3060
|
+
* @see svgpcNS.transformObject for a quick refference
|
|
3049
3061
|
*
|
|
3050
3062
|
* @param {Object.<string, (number | number[])>} source a `transformObject`as described above
|
|
3051
3063
|
* @public
|
|
@@ -3061,7 +3073,7 @@ class SVGPathCommander {
|
|
|
3061
3073
|
// it's important that we have one
|
|
3062
3074
|
if (!transform.origin) {
|
|
3063
3075
|
const BBox = getPathBBox(segments);
|
|
3064
|
-
transform.origin = [BBox.cx, BBox.cy
|
|
3076
|
+
transform.origin = [+BBox.cx, +BBox.cy];
|
|
3065
3077
|
}
|
|
3066
3078
|
|
|
3067
3079
|
this.segments = transformPath(segments, transform);
|