svg-path-commander 2.1.2 → 2.1.5

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 (97) hide show
  1. package/README.md +4 -4
  2. package/dist/svg-path-commander.cjs +1 -1
  3. package/dist/svg-path-commander.cjs.map +1 -1
  4. package/dist/svg-path-commander.d.ts +755 -849
  5. package/dist/svg-path-commander.js +1 -1
  6. package/dist/svg-path-commander.js.map +1 -1
  7. package/dist/svg-path-commander.mjs +947 -611
  8. package/dist/svg-path-commander.mjs.map +1 -1
  9. package/package.json +14 -22
  10. package/.eslintrc.cjs +0 -225
  11. package/.prettierrc.json +0 -15
  12. package/dts.config.ts +0 -15
  13. package/src/convert/pathToAbsolute.ts +0 -18
  14. package/src/convert/pathToCurve.ts +0 -43
  15. package/src/convert/pathToRelative.ts +0 -18
  16. package/src/convert/pathToString.ts +0 -50
  17. package/src/index.ts +0 -454
  18. package/src/interface.ts +0 -130
  19. package/src/math/arcTools.ts +0 -396
  20. package/src/math/bezier.ts +0 -261
  21. package/src/math/cubicTools.ts +0 -124
  22. package/src/math/distanceSquareRoot.ts +0 -15
  23. package/src/math/lineTools.ts +0 -69
  24. package/src/math/midPoint.ts +0 -18
  25. package/src/math/polygonTools.ts +0 -48
  26. package/src/math/quadTools.ts +0 -100
  27. package/src/math/rotateVector.ts +0 -17
  28. package/src/math/roundTo.ts +0 -7
  29. package/src/options/options.ts +0 -9
  30. package/src/parser/error.ts +0 -2
  31. package/src/parser/finalizeSegment.ts +0 -35
  32. package/src/parser/invalidPathValue.ts +0 -2
  33. package/src/parser/isArcCommand.ts +0 -11
  34. package/src/parser/isDigit.ts +0 -12
  35. package/src/parser/isDigitStart.ts +0 -14
  36. package/src/parser/isMoveCommand.ts +0 -17
  37. package/src/parser/isPathCommand.ts +0 -28
  38. package/src/parser/isSpace.ts +0 -23
  39. package/src/parser/paramsCount.ts +0 -16
  40. package/src/parser/paramsParser.ts +0 -14
  41. package/src/parser/parsePathString.ts +0 -33
  42. package/src/parser/pathParser.ts +0 -29
  43. package/src/parser/scanFlag.ts +0 -29
  44. package/src/parser/scanParam.ts +0 -102
  45. package/src/parser/scanSegment.ts +0 -84
  46. package/src/parser/skipSpaces.ts +0 -17
  47. package/src/process/absolutizeSegment.ts +0 -63
  48. package/src/process/arcToCubic.ts +0 -128
  49. package/src/process/getSVGMatrix.ts +0 -70
  50. package/src/process/iterate.ts +0 -58
  51. package/src/process/lineToCubic.ts +0 -17
  52. package/src/process/normalizePath.ts +0 -33
  53. package/src/process/normalizeSegment.ts +0 -84
  54. package/src/process/optimizePath.ts +0 -63
  55. package/src/process/projection2d.ts +0 -52
  56. package/src/process/quadToCubic.ts +0 -31
  57. package/src/process/relativizeSegment.ts +0 -59
  58. package/src/process/reverseCurve.ts +0 -24
  59. package/src/process/reversePath.ts +0 -114
  60. package/src/process/roundPath.ts +0 -33
  61. package/src/process/roundSegment.ts +0 -9
  62. package/src/process/segmentToCubic.ts +0 -48
  63. package/src/process/shortenSegment.ts +0 -71
  64. package/src/process/splitCubic.ts +0 -29
  65. package/src/process/splitPath.ts +0 -63
  66. package/src/process/transformPath.ts +0 -110
  67. package/src/types.ts +0 -228
  68. package/src/util/distanceEpsilon.ts +0 -3
  69. package/src/util/getClosestPoint.ts +0 -15
  70. package/src/util/getDrawDirection.ts +0 -16
  71. package/src/util/getPathArea.ts +0 -70
  72. package/src/util/getPathBBox.ts +0 -98
  73. package/src/util/getPointAtLength.ts +0 -110
  74. package/src/util/getPropertiesAtLength.ts +0 -67
  75. package/src/util/getPropertiesAtPoint.ts +0 -84
  76. package/src/util/getSegmentAtLength.ts +0 -15
  77. package/src/util/getSegmentOfPoint.ts +0 -18
  78. package/src/util/getTotalLength.ts +0 -68
  79. package/src/util/isAbsoluteArray.ts +0 -18
  80. package/src/util/isCurveArray.ts +0 -15
  81. package/src/util/isNormalizedArray.ts +0 -16
  82. package/src/util/isPathArray.ts +0 -24
  83. package/src/util/isPointInStroke.ts +0 -16
  84. package/src/util/isRelativeArray.ts +0 -18
  85. package/src/util/isValidPath.ts +0 -27
  86. package/src/util/shapeParams.ts +0 -16
  87. package/src/util/shapeToPath.ts +0 -86
  88. package/src/util/shapeToPathArray.ts +0 -183
  89. package/test/class.test.ts +0 -504
  90. package/test/fixtures/getMarkup.ts +0 -17
  91. package/test/fixtures/shapeObjects.ts +0 -11
  92. package/test/fixtures/shapes.js +0 -104
  93. package/test/fixtures/simpleShapes.js +0 -75
  94. package/test/static.test.ts +0 -330
  95. package/vite.config.mts +0 -41
  96. package/vitest.config-ui.mts +0 -26
  97. package/vitest.config.mts +0 -26
@@ -1,63 +0,0 @@
1
- import pathToAbsolute from '../convert/pathToAbsolute';
2
- import shortenSegment from './shortenSegment';
3
- import paramsParser from '../parser/paramsParser';
4
- import type { AbsoluteSegment, PathArray, PathCommand } from '../types';
5
- import iterate from './iterate';
6
- import normalizeSegment from './normalizeSegment';
7
- import relativizeSegment from './relativizeSegment';
8
- import roundSegment from './roundSegment';
9
-
10
- /**
11
- * Optimizes a `pathArray` object:
12
- * * convert segments to shorthand if possible
13
- * * select shortest segments from absolute and relative `pathArray`s
14
- *
15
- * @param pathInput a string or `pathArray`
16
- * @param roundOption the amount of decimals to round values to
17
- * @returns the optimized `pathArray`
18
- */
19
- const optimizePath = (pathInput: PathArray, roundOption: number) => {
20
- const path = pathToAbsolute(pathInput);
21
- // allow for ZERO decimals or use an aggressive value of 2
22
- const round =
23
- typeof roundOption === 'number' && roundOption >= 0 ? roundOption : /* istanbul ignore next @preserve */ 2;
24
- // this utility overrides the iterator params
25
- const optimParams = { ...paramsParser };
26
-
27
- const allPathCommands = [] as PathCommand[];
28
- let pathCommand = 'M' as PathCommand;
29
- let prevCommand = 'Z' as PathCommand;
30
-
31
- return iterate(path, (seg, i, lastX, lastY) => {
32
- optimParams.x = lastX;
33
- optimParams.y = lastY;
34
- // const absoluteSegment = absolutizeSegment(seg, optimParams);
35
- const normalizedSegment = normalizeSegment(seg, optimParams);
36
- let result = seg;
37
- [pathCommand] = seg;
38
-
39
- // Save current path command
40
- allPathCommands[i] = pathCommand;
41
- if (i) {
42
- // Get previous path command for `shortenSegment`
43
- prevCommand = allPathCommands[i - 1];
44
- const shortSegment = shortenSegment(seg as AbsoluteSegment, normalizedSegment, optimParams, prevCommand);
45
- const absSegment = roundSegment(shortSegment, round);
46
- const absString = absSegment.join('');
47
- const relativeSegment = relativizeSegment(shortSegment, i, lastX, lastY);
48
- const relSegment = roundSegment(relativeSegment, round);
49
- const relString = relSegment.join('');
50
- result = absString.length < relString.length ? absSegment : relSegment;
51
- }
52
-
53
- const seglen = normalizedSegment.length;
54
- optimParams.x1 = +normalizedSegment[seglen - 2];
55
- optimParams.y1 = +normalizedSegment[seglen - 1];
56
- optimParams.x2 = +normalizedSegment[seglen - 4] || optimParams.x1;
57
- optimParams.y2 = +normalizedSegment[seglen - 3] || optimParams.y1;
58
-
59
- return result;
60
- });
61
- };
62
-
63
- export default optimizePath;
@@ -1,52 +0,0 @@
1
- import CSSMatrix from '@thednp/dommatrix';
2
- import { type PointTuple } from '../types';
3
-
4
- /**
5
- * Transforms a specified point using a matrix, returning a new
6
- * Tuple *Object* comprising of the transformed point.
7
- * Neither the matrix nor the original point are altered.
8
- *
9
- * @copyright thednp © 2021
10
- *
11
- * @param cssm CSSMatrix instance
12
- * @param v Tuple
13
- * @return the resulting Tuple
14
- */
15
- const translatePoint = (cssm: CSSMatrix, v: [number, number, number, number]): [number, number, number, number] => {
16
- let m = CSSMatrix.Translate(v[0], v[1], v[2]);
17
-
18
- [, , , m.m44] = v;
19
- m = cssm.multiply(m);
20
-
21
- return [m.m41, m.m42, m.m43, m.m44];
22
- };
23
-
24
- /**
25
- * Returns the [x,y] projected coordinates for a given an [x,y] point
26
- * and an [x,y,z] perspective origin point.
27
- *
28
- * Equation found here =>
29
- * http://en.wikipedia.org/wiki/3D_projection#Diagram
30
- * Details =>
31
- * https://stackoverflow.com/questions/23792505/predicted-rendering-of-css-3d-transformed-pixel
32
- *
33
- * @param m the transformation matrix
34
- * @param point2D the initial [x,y] coordinates
35
- * @param origin the [x,y,z] transform origin
36
- * @returns the projected [x,y] coordinates
37
- */
38
- const projection2d = (m: CSSMatrix, point2D: PointTuple, origin: [number, number, number]): PointTuple => {
39
- const [originX, originY, originZ] = origin;
40
- const [x, y, z] = translatePoint(m, [point2D[0], point2D[1], 0, 1]);
41
-
42
- const relativePositionX = x - originX;
43
- const relativePositionY = y - originY;
44
- const relativePositionZ = z - originZ;
45
-
46
- return [
47
- // protect against division by ZERO
48
- relativePositionX * (Math.abs(originZ) / Math.abs(relativePositionZ) || 1) + originX,
49
- relativePositionY * (Math.abs(originZ) / Math.abs(relativePositionZ) || 1) + originY,
50
- ];
51
- };
52
- export default projection2d;
@@ -1,31 +0,0 @@
1
- /**
2
- * Converts a Q (quadratic-bezier) segment to C (cubic-bezier).
3
- *
4
- * @param x1 curve start x
5
- * @param y1 curve start y
6
- * @param qx control point x
7
- * @param qy control point y
8
- * @param x2 curve end x
9
- * @param y2 curve end y
10
- * @returns the cubic-bezier segment
11
- */
12
- const quadToCubic = (
13
- x1: number,
14
- y1: number,
15
- qx: number,
16
- qy: number,
17
- x2: number,
18
- y2: number,
19
- ): [number, number, number, number, number, number] => {
20
- const r13 = 1 / 3;
21
- const r23 = 2 / 3;
22
- return [
23
- r13 * x1 + r23 * qx, // cpx1
24
- r13 * y1 + r23 * qy, // cpy1
25
- r13 * x2 + r23 * qx, // cpx2
26
- r13 * y2 + r23 * qy, // cpy2
27
- x2,
28
- y2, // x,y
29
- ];
30
- };
31
- export default quadToCubic;
@@ -1,59 +0,0 @@
1
- import type {
2
- RelativeSegment,
3
- RelativeCommand,
4
- PathSegment,
5
- aSegment,
6
- vSegment,
7
- hSegment,
8
- qSegment,
9
- tSegment,
10
- sSegment,
11
- cSegment,
12
- MSegment,
13
- lSegment,
14
- } from '../types';
15
-
16
- /**
17
- * Returns a relative segment of a `PathArray` object.
18
- *
19
- * @param segment the segment object
20
- * @param index the segment index
21
- * @param lastX the last known X value
22
- * @param lastY the last known Y value
23
- * @returns the relative segment
24
- */
25
- const relativizeSegment = (segment: PathSegment, index: number, lastX: number, lastY: number) => {
26
- const [pathCommand] = segment;
27
- const relCommand = pathCommand.toLowerCase() as RelativeCommand;
28
- const isRelative = pathCommand === relCommand;
29
-
30
- /* istanbul ignore else @preserve */
31
- if (index === 0 || isRelative) return segment as MSegment | RelativeSegment;
32
-
33
- if (relCommand === 'a') {
34
- return [
35
- relCommand,
36
- segment[1],
37
- segment[2],
38
- segment[3],
39
- segment[4],
40
- segment[5],
41
- (segment as aSegment)[6] - lastX,
42
- (segment as aSegment)[7] - lastY,
43
- ] as aSegment;
44
- } else if (relCommand === 'v') {
45
- return [relCommand, (segment as vSegment)[1] - lastY] as vSegment;
46
- } else if (relCommand === 'h') {
47
- return [relCommand, (segment as hSegment)[1] - lastX] as hSegment;
48
- } else if (relCommand === 'l') {
49
- return [relCommand, (segment as lSegment)[1] - lastX, (segment as lSegment)[2] - lastY] as lSegment;
50
- } else {
51
- // use brakets for `eslint: no-case-declaration`
52
- // https://stackoverflow.com/a/50753272/803358
53
- const relValues = (segment.slice(1) as number[]).map((n, j) => n - (j % 2 ? lastY : lastX));
54
- // for c, s, q, t
55
- return [relCommand as RelativeCommand | number].concat(relValues) as qSegment | tSegment | sSegment | cSegment;
56
- }
57
- };
58
-
59
- export default relativizeSegment;
@@ -1,24 +0,0 @@
1
- import type { CSegment, CurveArray, MSegment, PathCommand } from '../types';
2
-
3
- /**
4
- * Reverses all segments of a `pathArray`
5
- * which consists of only C (cubic-bezier) path commands.
6
- *
7
- * @param path the source `pathArray`
8
- * @returns the reversed `pathArray`
9
- */
10
- const reverseCurve = (path: CurveArray) => {
11
- const rotatedCurve = path
12
- .slice(1)
13
- .map((x, i, curveOnly) =>
14
- !i ? path[0].slice(1).concat(x.slice(1) as number[]) : curveOnly[i - 1].slice(-2).concat(x.slice(1)),
15
- )
16
- .map(x => x.map((_, i) => x[x.length - i - 2 * (1 - (i % 2))]))
17
- .reverse() as (MSegment | CSegment)[];
18
-
19
- return [['M' as PathCommand | number].concat(rotatedCurve[0].slice(0, 2))].concat(
20
- rotatedCurve.map(x => ['C' as PathCommand | number].concat(x.slice(2))),
21
- ) as CurveArray;
22
- };
23
-
24
- export default reverseCurve;
@@ -1,114 +0,0 @@
1
- import type {
2
- ASegment,
3
- CSegment,
4
- HSegment,
5
- MSegment,
6
- PathArray,
7
- PathSegment,
8
- PointTuple,
9
- QSegment,
10
- SSegment,
11
- TSegment,
12
- VSegment,
13
- } from '../types';
14
- import pathToAbsolute from '../convert/pathToAbsolute';
15
- import normalizePath from './normalizePath';
16
- import iterate from './iterate';
17
-
18
- /**
19
- * Reverses all segments of a `pathArray` and returns a new `pathArray` instance
20
- * with absolute values.
21
- *
22
- * @param pathInput the source `pathArray`
23
- * @returns the reversed `pathArray`
24
- */
25
- const reversePath = (pathInput: PathArray) => {
26
- const absolutePath = pathToAbsolute(pathInput);
27
- const normalizedPath = normalizePath(absolutePath);
28
- const pLen = absolutePath.length;
29
- const isClosed = absolutePath[pLen - 1][0] === 'Z';
30
-
31
- const reversedPath = iterate(absolutePath, (segment, i) => {
32
- const normalizedSegment = normalizedPath[i];
33
- const prevSeg = i && absolutePath[i - 1];
34
- const prevCommand = prevSeg && prevSeg[0];
35
- const nextSeg = absolutePath[i + 1];
36
- const nextCommand = nextSeg && nextSeg[0];
37
- const [pathCommand] = segment;
38
- const [x, y] = normalizedPath[i ? i - 1 : pLen - 1].slice(-2) as PointTuple;
39
- let result = segment;
40
-
41
- switch (pathCommand) {
42
- case 'M':
43
- result = (isClosed ? ['Z'] : [pathCommand, x, y]) as PathSegment;
44
- break;
45
- case 'A':
46
- result = [
47
- pathCommand,
48
- segment[1],
49
- segment[2],
50
- segment[3],
51
- segment[4],
52
- segment[5] === 1 ? 0 : 1,
53
- x,
54
- y,
55
- ] as ASegment;
56
- break;
57
- case 'C':
58
- if (nextSeg && nextCommand === 'S') {
59
- result = ['S', segment[1], segment[2], x, y] as SSegment;
60
- } else {
61
- result = [pathCommand, segment[3], segment[4], segment[1], segment[2], x, y] as CSegment;
62
- }
63
- break;
64
- case 'S':
65
- if (prevCommand && 'CS'.includes(prevCommand) && (!nextSeg || nextCommand !== 'S')) {
66
- result = [
67
- 'C',
68
- normalizedSegment[3],
69
- normalizedSegment[4],
70
- normalizedSegment[1],
71
- normalizedSegment[2],
72
- x,
73
- y,
74
- ] as CSegment;
75
- } else {
76
- result = [pathCommand, normalizedSegment[1], normalizedSegment[2], x, y] as SSegment;
77
- }
78
- break;
79
- case 'Q':
80
- if (nextSeg && nextCommand === 'T') {
81
- result = ['T', x, y] as TSegment;
82
- } else {
83
- result = [pathCommand, segment[1], segment[2], x, y] as QSegment;
84
- }
85
- break;
86
- case 'T':
87
- if (prevCommand && 'QT'.includes(prevCommand) && (!nextSeg || nextCommand !== 'T')) {
88
- result = ['Q', normalizedSegment[1], normalizedSegment[2], x, y] as QSegment;
89
- } else {
90
- result = [pathCommand, x, y] as TSegment;
91
- }
92
- break;
93
- case 'Z':
94
- result = ['M', x, y] as MSegment;
95
- break;
96
- case 'H':
97
- result = [pathCommand, x] as HSegment;
98
- break;
99
- case 'V':
100
- result = [pathCommand, y] as VSegment;
101
- break;
102
- default:
103
- result = [pathCommand as typeof pathCommand | number].concat(segment.slice(1, -2), x, y) as PathSegment;
104
- }
105
-
106
- return result;
107
- });
108
-
109
- return (
110
- isClosed ? reversedPath.reverse() : [reversedPath[0] as PathSegment].concat(reversedPath.slice(1).reverse())
111
- ) as PathArray;
112
- };
113
-
114
- export default reversePath;
@@ -1,33 +0,0 @@
1
- import type { PathArray } from '../types';
2
- import defaultOptions from '../options/options';
3
- import iterate from './iterate';
4
- import roundSegment from './roundSegment';
5
-
6
- /**
7
- * Rounds the values of a `pathArray` instance to
8
- * a specified amount of decimals and returns it.
9
- *
10
- * @param path the source `pathArray`
11
- * @param roundOption the amount of decimals to round numbers to
12
- * @returns the resulted `pathArray` with rounded values
13
- */
14
- const roundPath = (path: PathArray, roundOption?: number | 'off') => {
15
- let { round } = defaultOptions;
16
- // allow for ZERO decimals
17
- round =
18
- roundOption === 'off'
19
- ? roundOption
20
- : typeof roundOption === 'number' && roundOption >= 0
21
- ? roundOption
22
- : typeof round === 'number' && round >= 0
23
- ? round
24
- : /* istanbul ignore next @preserve */ 'off';
25
-
26
- /* istanbul ignore else @preserve */
27
- if (round === 'off') return path.slice(0) as PathArray;
28
-
29
- return iterate<typeof path>(path, segment => {
30
- return roundSegment(segment, round);
31
- });
32
- };
33
- export default roundPath;
@@ -1,9 +0,0 @@
1
- import type { PathCommand, PathSegment } from '../types';
2
- import roundTo from '../math/roundTo';
3
-
4
- const roundSegment = <T extends PathSegment>(segment: T, roundOption: number) => {
5
- const values = (segment.slice(1) as number[]).map(n => roundTo(n, roundOption));
6
- return [segment[0] as PathCommand | number].concat(values) as T;
7
- };
8
-
9
- export default roundSegment;
@@ -1,48 +0,0 @@
1
- import arcToCubic from './arcToCubic';
2
- import quadToCubic from './quadToCubic';
3
- import lineToCubic from './lineToCubic';
4
- import type { CSegment, MSegment, PathSegment } from '../types';
5
- import type { ParserParams } from '../interface';
6
-
7
- /**
8
- * Converts any segment to C (cubic-bezier).
9
- *
10
- * @param segment the source segment
11
- * @param params the source segment parameters
12
- * @returns the cubic-bezier segment
13
- */
14
- const segmentToCubic = (segment: PathSegment, params: ParserParams) => {
15
- const [pathCommand] = segment;
16
- const values = segment.slice(1).map(Number);
17
- const [x, y] = values;
18
- // let args;
19
- const { x1: px1, y1: py1, x: px, y: py } = params;
20
-
21
- if (!'TQ'.includes(pathCommand)) {
22
- params.qx = null;
23
- params.qy = null;
24
- }
25
-
26
- if (pathCommand === 'M') {
27
- params.x = x;
28
- params.y = y;
29
- return segment;
30
- } else if (pathCommand === 'A') {
31
- return ['C' as string | number].concat(
32
- arcToCubic(px1, py1, values[0], values[1], values[2], values[3], values[4], values[5], values[6]),
33
- ) as CSegment;
34
- } else if (pathCommand === 'Q') {
35
- params.qx = x;
36
- params.qy = y;
37
- return ['C' as string | number].concat(
38
- quadToCubic(px1, py1, values[0], values[1], values[2], values[3]),
39
- ) as CSegment;
40
- } else if (pathCommand === 'L') {
41
- return ['C' as string | number].concat(lineToCubic(px1, py1, x, y)) as CSegment;
42
- } else if (pathCommand === 'Z') {
43
- return ['C' as string | number].concat(lineToCubic(px1, py1, px, py)) as CSegment;
44
- }
45
-
46
- return segment as MSegment | CSegment;
47
- };
48
- export default segmentToCubic;
@@ -1,71 +0,0 @@
1
- import defaultOptions from '../options/options';
2
- import type { ParserParams } from '../interface';
3
- import roundTo from '../math/roundTo';
4
- import type { AbsoluteSegment, NormalSegment, PathCommand, ShortSegment, SSegment, TSegment } from '../types';
5
-
6
- /**
7
- * Shorten a single segment of a `pathArray` object.
8
- *
9
- * @param segment the `absoluteSegment` object
10
- * @param normalSegment the `normalSegment` object
11
- * @param params the coordinates of the previous segment
12
- * @param prevCommand the path command of the previous segment
13
- * @returns the shortened segment
14
- */
15
- const shortenSegment = (
16
- segment: AbsoluteSegment,
17
- normalSegment: NormalSegment,
18
- params: ParserParams,
19
- prevCommand: PathCommand,
20
- ): ShortSegment => {
21
- const [pathCommand] = segment;
22
- const { round: defaultRound } = defaultOptions;
23
- const round = typeof defaultRound === 'number' ? defaultRound : /* istanbul ignore next */ 4;
24
- const normalValues = normalSegment.slice(1) as number[];
25
- const { x1, y1, x2, y2, x, y } = params;
26
- const [nx, ny] = normalValues.slice(-2);
27
- const result = segment;
28
-
29
- if (!'TQ'.includes(pathCommand)) {
30
- // optional but good to be cautious
31
- params.qx = null;
32
- params.qy = null;
33
- }
34
-
35
- if (pathCommand === 'L') {
36
- if (roundTo(x, round) === roundTo(nx, round)) {
37
- return ['V', ny];
38
- } else if (roundTo(y, round) === roundTo(ny, round)) {
39
- return ['H', nx];
40
- }
41
- } else if (pathCommand === 'C') {
42
- const [nx1, ny1] = normalValues;
43
- params.x1 = nx1;
44
- params.y1 = ny1;
45
-
46
- if (
47
- 'CS'.includes(prevCommand) &&
48
- ((roundTo(nx1, round) === roundTo(x1 * 2 - x2, round) && roundTo(ny1, round) === roundTo(y1 * 2 - y2, round)) ||
49
- (roundTo(x1, round) === roundTo(x2 * 2 - x, round) && roundTo(y1, round) === roundTo(y2 * 2 - y, round)))
50
- ) {
51
- return ['S', normalValues[2], normalValues[3], normalValues[4], normalValues[5]] as SSegment;
52
- }
53
- } else if (pathCommand === 'Q') {
54
- const [qx, qy] = normalValues;
55
- params.qx = qx;
56
- params.qy = qy;
57
-
58
- if (
59
- 'QT'.includes(prevCommand) &&
60
- roundTo(qx, round) === roundTo(x1 * 2 - x2, round) &&
61
- roundTo(qy, round) === roundTo(y1 * 2 - y2, round)
62
- ) {
63
- return ['T', normalValues[2], normalValues[3]] as TSegment;
64
- }
65
- }
66
-
67
- // ['V', 'H', 'S', 'T', 'Z'].includes(pathCommand)
68
- return result as ShortSegment;
69
- };
70
-
71
- export default shortenSegment;
@@ -1,29 +0,0 @@
1
- import midPoint from '../math/midPoint';
2
- import type { CubicSegment, PointTuple } from '../types';
3
-
4
- /**
5
- * Split a cubic-bezier segment into two.
6
- *
7
- * @param pts the cubic-bezier parameters
8
- * @param ratio the cubic-bezier parameters
9
- * @return two new cubic-bezier segments
10
- */
11
- const splitCubic = (pts: number[], ratio = 0.5): [CubicSegment, CubicSegment] => {
12
- const t = ratio;
13
- const p0 = pts.slice(0, 2) as PointTuple;
14
- const p1 = pts.slice(2, 4) as PointTuple;
15
- const p2 = pts.slice(4, 6) as PointTuple;
16
- const p3 = pts.slice(6, 8) as PointTuple;
17
- const p4 = midPoint(p0, p1, t);
18
- const p5 = midPoint(p1, p2, t);
19
- const p6 = midPoint(p2, p3, t);
20
- const p7 = midPoint(p4, p5, t);
21
- const p8 = midPoint(p5, p6, t);
22
- const p9 = midPoint(p7, p8, t);
23
-
24
- return [
25
- ['C', p4[0], p4[1], p7[0], p7[1], p9[0], p9[1]],
26
- ['C', p8[0], p8[1], p6[0], p6[1], p3[0], p3[1]],
27
- ];
28
- };
29
- export default splitCubic;
@@ -1,63 +0,0 @@
1
- import paramsParser from '../parser/paramsParser';
2
- import type { AbsoluteCommand, HSegment, MSegment, PathArray, PointTuple, RelativeCommand, VSegment } from '../types';
3
-
4
- /**
5
- * Split a path into an `Array` of sub-path strings.
6
- *
7
- * In the process, values are converted to absolute
8
- * for visual consistency.
9
- *
10
- * @param pathInput the source `pathArray`
11
- * @return an array with all sub-path strings
12
- */
13
- const splitPath = (pathInput: PathArray): PathArray[] => {
14
- const composite = [] as PathArray[];
15
- let path: PathArray;
16
- let pi = -1;
17
- let x = 0;
18
- let y = 0;
19
- let mx = 0;
20
- let my = 0;
21
- const params = { ...paramsParser };
22
-
23
- pathInput.forEach(seg => {
24
- const [pathCommand] = seg;
25
- const absCommand = pathCommand.toUpperCase() as AbsoluteCommand;
26
- const relCommand = pathCommand.toLowerCase() as RelativeCommand;
27
- const isRelative = pathCommand === relCommand;
28
- const values = seg.slice(1) as number[];
29
-
30
- if (absCommand === 'M') {
31
- pi += 1;
32
- [x, y] = values as PointTuple;
33
- x += isRelative ? params.x : 0;
34
- y += isRelative ? params.y : 0;
35
- mx = x;
36
- my = y;
37
- path = [(isRelative ? [absCommand, mx, my] : seg) as MSegment];
38
- } else {
39
- if (absCommand === 'Z') {
40
- x = mx;
41
- y = my;
42
- } else if (absCommand === 'H') {
43
- [, x] = seg as HSegment;
44
- x += isRelative ? params.x : /* istanbul ignore next @preserve */ 0;
45
- } else if (absCommand === 'V') {
46
- [, y] = seg as VSegment;
47
- y += isRelative ? params.y : /* istanbul ignore next @preserve */ 0;
48
- } else {
49
- [x, y] = seg.slice(-2) as PointTuple;
50
- x += isRelative ? params.x : 0;
51
- y += isRelative ? params.y : 0;
52
- }
53
- path.push(seg);
54
- }
55
-
56
- params.x = x;
57
- params.y = y;
58
- composite[pi] = path;
59
- });
60
-
61
- return composite;
62
- };
63
- export default splitPath;