@remotion/paths 4.0.0-alpha8 → 4.0.0-alpha9
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/get-bounding-box.js +23 -1
- package/dist/get-point-at-length.d.ts +1 -1
- package/dist/get-point-at-length.js +1 -1
- package/dist/helpers/iterate.d.ts +2 -0
- package/dist/helpers/iterate.js +52 -10
- package/dist/helpers/remove-a-s-t-curves.js +31 -20
- package/dist/normalize-path.js +22 -12
- package/package.json +4 -3
package/dist/get-bounding-box.js
CHANGED
|
@@ -85,9 +85,29 @@ const getBoundingBoxFromInstructions = (instructions) => {
|
|
|
85
85
|
let maxY = -Infinity;
|
|
86
86
|
let x = 0;
|
|
87
87
|
let y = 0;
|
|
88
|
+
let lastMoveX = 0;
|
|
89
|
+
let lastMoveY = 0;
|
|
88
90
|
for (const seg of instructions) {
|
|
89
91
|
switch (seg.type) {
|
|
90
|
-
case 'M':
|
|
92
|
+
case 'M': {
|
|
93
|
+
lastMoveX = seg.x;
|
|
94
|
+
lastMoveY = seg.y;
|
|
95
|
+
if (minX > seg.x) {
|
|
96
|
+
minX = seg.x;
|
|
97
|
+
}
|
|
98
|
+
if (minY > seg.y) {
|
|
99
|
+
minY = seg.y;
|
|
100
|
+
}
|
|
101
|
+
if (maxX < seg.x) {
|
|
102
|
+
maxX = seg.x;
|
|
103
|
+
}
|
|
104
|
+
if (maxY < seg.y) {
|
|
105
|
+
maxY = seg.y;
|
|
106
|
+
}
|
|
107
|
+
x = seg.x;
|
|
108
|
+
y = seg.y;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
91
111
|
case 'L': {
|
|
92
112
|
if (minX > seg.x) {
|
|
93
113
|
minX = seg.x;
|
|
@@ -144,6 +164,8 @@ const getBoundingBoxFromInstructions = (instructions) => {
|
|
|
144
164
|
break;
|
|
145
165
|
}
|
|
146
166
|
case 'Z':
|
|
167
|
+
x = lastMoveX;
|
|
168
|
+
y = lastMoveY;
|
|
147
169
|
break;
|
|
148
170
|
default:
|
|
149
171
|
// @ts-expect-error
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* @param {string} path A valid SVG path
|
|
4
4
|
* @param {number} length The length at which the point should be sampled
|
|
5
5
|
* @see [Documentation](https://remotion.dev/docs/paths/get-point-at-length)
|
|
6
|
-
*/
|
|
6
|
+
*/
|
|
7
7
|
export declare const getPointAtLength: (path: string, length: number) => import("./helpers/types").Point;
|
|
@@ -8,7 +8,7 @@ const get_part_at_length_1 = require("./helpers/get-part-at-length");
|
|
|
8
8
|
* @param {string} path A valid SVG path
|
|
9
9
|
* @param {number} length The length at which the point should be sampled
|
|
10
10
|
* @see [Documentation](https://remotion.dev/docs/paths/get-point-at-length)
|
|
11
|
-
*/
|
|
11
|
+
*/
|
|
12
12
|
const getPointAtLength = (path, length) => {
|
|
13
13
|
const constructed = (0, construct_1.construct)(path);
|
|
14
14
|
const fractionPart = (0, get_part_at_length_1.getPartAtLength)(path, length);
|
package/dist/helpers/iterate.js
CHANGED
|
@@ -6,6 +6,8 @@ const iterateOverSegments = ({ segments, iterate, }) => {
|
|
|
6
6
|
let y = 0;
|
|
7
7
|
let initialX = 0;
|
|
8
8
|
let initialY = 0;
|
|
9
|
+
let cpX = null;
|
|
10
|
+
let cpY = null;
|
|
9
11
|
const newSegments = segments.map((s, i) => {
|
|
10
12
|
var _a;
|
|
11
13
|
const newSeg = iterate({
|
|
@@ -15,33 +17,73 @@ const iterateOverSegments = ({ segments, iterate, }) => {
|
|
|
15
17
|
prevSegment: (_a = segments[i - 1]) !== null && _a !== void 0 ? _a : null,
|
|
16
18
|
initialX,
|
|
17
19
|
initialY,
|
|
20
|
+
cpX,
|
|
21
|
+
cpY,
|
|
18
22
|
});
|
|
19
23
|
switch (s.type) {
|
|
20
24
|
case 'M':
|
|
21
25
|
initialX = s.x;
|
|
22
26
|
initialY = s.y;
|
|
23
|
-
|
|
27
|
+
x = s.x;
|
|
28
|
+
y = s.y;
|
|
29
|
+
cpX = null;
|
|
30
|
+
cpY = null;
|
|
31
|
+
break;
|
|
32
|
+
case 'Q':
|
|
33
|
+
x = s.x;
|
|
34
|
+
y = s.y;
|
|
35
|
+
cpX = s.cpx;
|
|
36
|
+
cpY = s.cpy;
|
|
37
|
+
break;
|
|
24
38
|
case 'A':
|
|
39
|
+
x = s.x;
|
|
40
|
+
y = s.y;
|
|
41
|
+
cpX = null;
|
|
42
|
+
cpY = null;
|
|
43
|
+
break;
|
|
25
44
|
case 'C':
|
|
26
|
-
|
|
45
|
+
x = s.x;
|
|
46
|
+
y = s.y;
|
|
47
|
+
cpX = s.cp2x;
|
|
48
|
+
cpY = s.cp2y;
|
|
49
|
+
break;
|
|
27
50
|
case 'S':
|
|
51
|
+
x = s.x;
|
|
52
|
+
y = s.y;
|
|
53
|
+
cpX = s.cpx;
|
|
54
|
+
cpY = s.cpy;
|
|
55
|
+
break;
|
|
28
56
|
case 'T':
|
|
29
|
-
|
|
57
|
+
// Order of if statement is important here
|
|
58
|
+
if (cpX !== null && cpY !== null) {
|
|
59
|
+
cpX = x - (cpX - x);
|
|
60
|
+
cpY = y - (cpY - y);
|
|
61
|
+
}
|
|
62
|
+
x = s.x;
|
|
63
|
+
y = s.y;
|
|
64
|
+
break;
|
|
65
|
+
case 'L':
|
|
30
66
|
x = s.x;
|
|
31
67
|
y = s.y;
|
|
68
|
+
cpX = null;
|
|
69
|
+
cpY = null;
|
|
32
70
|
break;
|
|
33
|
-
|
|
34
|
-
case 'V': {
|
|
71
|
+
case 'V':
|
|
35
72
|
y = s.y;
|
|
73
|
+
cpX = null;
|
|
74
|
+
cpY = null;
|
|
36
75
|
break;
|
|
37
|
-
|
|
38
|
-
case 'H': {
|
|
76
|
+
case 'H':
|
|
39
77
|
x = s.x;
|
|
78
|
+
cpX = null;
|
|
79
|
+
cpY = null;
|
|
40
80
|
break;
|
|
41
|
-
|
|
42
|
-
|
|
81
|
+
case 'Z':
|
|
82
|
+
x = initialX;
|
|
83
|
+
y = initialY;
|
|
84
|
+
cpX = null;
|
|
85
|
+
cpY = null;
|
|
43
86
|
break;
|
|
44
|
-
}
|
|
45
87
|
default:
|
|
46
88
|
// @ts-expect-error
|
|
47
89
|
throw new Error(`Unexpected instruction ${s.type}`);
|
|
@@ -92,13 +92,9 @@ function arcToCircle({ x1, y1, x2, y2, largeArcFlag, sweepFlag, rx, ry, phi, })
|
|
|
92
92
|
}
|
|
93
93
|
// Requires path to be normalized
|
|
94
94
|
const removeATSHVInstructions = (segments) => {
|
|
95
|
-
let prevControlX = 0;
|
|
96
|
-
let prevControlY = 0;
|
|
97
|
-
let curControlX = 0;
|
|
98
|
-
let curControlY = 0;
|
|
99
95
|
return (0, iterate_1.iterateOverSegments)({
|
|
100
96
|
segments,
|
|
101
|
-
iterate: ({ segment, prevSegment, x, y }) => {
|
|
97
|
+
iterate: ({ segment, prevSegment, x, y, cpX, cpY }) => {
|
|
102
98
|
if (segment.type === 'H') {
|
|
103
99
|
return [{ type: 'L', x: segment.x, y }];
|
|
104
100
|
}
|
|
@@ -144,42 +140,57 @@ const removeATSHVInstructions = (segments) => {
|
|
|
144
140
|
return result;
|
|
145
141
|
}
|
|
146
142
|
if (segment.type === 'T') {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
143
|
+
let prevControlX = 0;
|
|
144
|
+
let prevControlY = 0;
|
|
145
|
+
if (prevSegment &&
|
|
146
|
+
(prevSegment.type === 'Q' || prevSegment.type === 'T')) {
|
|
147
|
+
prevControlX = cpX;
|
|
148
|
+
prevControlY = cpY;
|
|
150
149
|
}
|
|
151
150
|
else {
|
|
152
|
-
prevControlX =
|
|
153
|
-
prevControlY =
|
|
151
|
+
prevControlX = x;
|
|
152
|
+
prevControlY = y;
|
|
154
153
|
}
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
// New first control point is reflection of previous second control point
|
|
155
|
+
const vectorX = prevControlX - x;
|
|
156
|
+
const vectorY = prevControlY - y;
|
|
157
|
+
const newControlX = x - vectorX;
|
|
158
|
+
const newControlY = y - vectorY;
|
|
157
159
|
return [
|
|
158
160
|
{
|
|
159
161
|
type: 'Q',
|
|
160
|
-
cpx:
|
|
161
|
-
cpy:
|
|
162
|
+
cpx: newControlX,
|
|
163
|
+
cpy: newControlY,
|
|
162
164
|
x: segment.x,
|
|
163
165
|
y: segment.y,
|
|
164
166
|
},
|
|
165
167
|
];
|
|
166
168
|
}
|
|
167
169
|
if (segment.type === 'S') {
|
|
170
|
+
let prevControlX = 0;
|
|
171
|
+
let prevControlY = 0;
|
|
168
172
|
if (prevSegment && prevSegment.type === 'C') {
|
|
169
173
|
prevControlX = prevSegment.cp2x;
|
|
170
174
|
prevControlY = prevSegment.cp2y;
|
|
171
175
|
}
|
|
176
|
+
else if (prevSegment && prevSegment.type === 'S') {
|
|
177
|
+
prevControlX = prevSegment.cpx;
|
|
178
|
+
prevControlY = prevSegment.cpy;
|
|
179
|
+
}
|
|
172
180
|
else {
|
|
173
|
-
prevControlX =
|
|
174
|
-
prevControlY =
|
|
181
|
+
prevControlX = x;
|
|
182
|
+
prevControlY = y;
|
|
175
183
|
}
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
// New first control point is reflection of previous second control point
|
|
185
|
+
const vectorX = prevControlX - x;
|
|
186
|
+
const vectorY = prevControlY - y;
|
|
187
|
+
const newControlX = x - vectorX;
|
|
188
|
+
const newControlY = y - vectorY;
|
|
178
189
|
return [
|
|
179
190
|
{
|
|
180
191
|
type: 'C',
|
|
181
|
-
cp1x:
|
|
182
|
-
cp1y:
|
|
192
|
+
cp1x: newControlX,
|
|
193
|
+
cp1y: newControlY,
|
|
183
194
|
cp2x: segment.cpx,
|
|
184
195
|
cp2y: segment.cpy,
|
|
185
196
|
x: segment.x,
|
package/dist/normalize-path.js
CHANGED
|
@@ -19,10 +19,18 @@ const normalizeInstructions = (instructions) => {
|
|
|
19
19
|
const normalized = [];
|
|
20
20
|
let x = 0;
|
|
21
21
|
let y = 0;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
let moveX = 0;
|
|
23
|
+
let moveY = 0;
|
|
24
24
|
for (let i = 0; i < instructions.length; i++) {
|
|
25
25
|
const instruction = instructions[i];
|
|
26
|
+
if (instruction.type === 'M') {
|
|
27
|
+
moveX = instruction.x;
|
|
28
|
+
moveY = instruction.y;
|
|
29
|
+
}
|
|
30
|
+
else if (instruction.type === 'm') {
|
|
31
|
+
moveX += instruction.dx;
|
|
32
|
+
moveY += instruction.dy;
|
|
33
|
+
}
|
|
26
34
|
if (instruction.type === 'A' ||
|
|
27
35
|
instruction.type === 'C' ||
|
|
28
36
|
instruction.type === 'L' ||
|
|
@@ -42,6 +50,8 @@ const normalizeInstructions = (instructions) => {
|
|
|
42
50
|
instruction.type === 'q' ||
|
|
43
51
|
instruction.type === 's' ||
|
|
44
52
|
instruction.type === 't') {
|
|
53
|
+
const currentX = x;
|
|
54
|
+
const currentY = y;
|
|
45
55
|
x += instruction.dx;
|
|
46
56
|
y += instruction.dy;
|
|
47
57
|
if (instruction.type === 'a') {
|
|
@@ -60,10 +70,10 @@ const normalizeInstructions = (instructions) => {
|
|
|
60
70
|
if (instruction.type === 'c') {
|
|
61
71
|
normalized.push({
|
|
62
72
|
type: 'C',
|
|
63
|
-
cp1x: instruction.cp1dx +
|
|
64
|
-
cp1y: instruction.cp1dy +
|
|
65
|
-
cp2x: instruction.cp2dx +
|
|
66
|
-
cp2y: instruction.cp2dy +
|
|
73
|
+
cp1x: instruction.cp1dx + currentX,
|
|
74
|
+
cp1y: instruction.cp1dy + currentY,
|
|
75
|
+
cp2x: instruction.cp2dx + currentX,
|
|
76
|
+
cp2y: instruction.cp2dy + currentY,
|
|
67
77
|
x,
|
|
68
78
|
y,
|
|
69
79
|
});
|
|
@@ -88,8 +98,8 @@ const normalizeInstructions = (instructions) => {
|
|
|
88
98
|
if (instruction.type === 'q') {
|
|
89
99
|
normalized.push({
|
|
90
100
|
type: 'Q',
|
|
91
|
-
cpx: instruction.cpdx +
|
|
92
|
-
cpy: instruction.cpdy +
|
|
101
|
+
cpx: instruction.cpdx + currentX,
|
|
102
|
+
cpy: instruction.cpdy + currentY,
|
|
93
103
|
x,
|
|
94
104
|
y,
|
|
95
105
|
});
|
|
@@ -98,8 +108,8 @@ const normalizeInstructions = (instructions) => {
|
|
|
98
108
|
if (instruction.type === 's') {
|
|
99
109
|
normalized.push({
|
|
100
110
|
type: 'S',
|
|
101
|
-
cpx: instruction.cpdx +
|
|
102
|
-
cpy: instruction.cpdy +
|
|
111
|
+
cpx: instruction.cpdx + currentX,
|
|
112
|
+
cpy: instruction.cpdy + currentY,
|
|
103
113
|
x,
|
|
104
114
|
y,
|
|
105
115
|
});
|
|
@@ -126,8 +136,8 @@ const normalizeInstructions = (instructions) => {
|
|
|
126
136
|
}
|
|
127
137
|
if (instruction.type === 'Z') {
|
|
128
138
|
normalized.push(instruction);
|
|
129
|
-
x =
|
|
130
|
-
y =
|
|
139
|
+
x = moveX;
|
|
140
|
+
y = moveY;
|
|
131
141
|
continue;
|
|
132
142
|
}
|
|
133
143
|
if (instruction.type === 'h') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/paths",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-alpha9",
|
|
4
4
|
"description": "Utility functions for SVG paths",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@jonny/eslint-config": "3.0.266",
|
|
17
|
-
"@types/node": "
|
|
17
|
+
"@types/node": "18.14.6",
|
|
18
18
|
"eslint": "8.25.0",
|
|
19
19
|
"prettier": "^2.7.1",
|
|
20
20
|
"prettier-plugin-organize-imports": "^2.3.4",
|
|
21
21
|
"typescript": "^4.7.0",
|
|
22
|
-
"vitest": "0.
|
|
22
|
+
"vitest": "0.31.1"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
25
25
|
"svg",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
|
+
"formatting": "prettier src --check",
|
|
33
34
|
"lint": "eslint src --ext ts,tsx",
|
|
34
35
|
"watch": "tsc -w",
|
|
35
36
|
"build": "tsc -d",
|