plotboilerplate 1.20.0 → 1.20.1
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/README.md +1 -0
- package/package.json +1 -1
- package/src/cjs/utils/parsers/svg/parseSVGPathData.d.ts +2 -1
- package/src/cjs/utils/parsers/svg/parseSVGPathData.js +228 -205
- package/src/cjs/utils/parsers/svg/parseSVGPathData.js.map +1 -1
- package/src/cjs/utils/parsers/svg/splitSVGPathData.js +6 -2
- package/src/cjs/utils/parsers/svg/splitSVGPathData.js.map +1 -1
- package/src/cjs/utils/parsers/svg/types.d.ts +29 -9
- package/src/cjs/utils/parsers/svg/types.js +4 -3
- package/src/cjs/utils/parsers/svg/types.js.map +1 -1
- package/src/esm/utils/parsers/svg/parseSVGPathData.d.ts +2 -1
- package/src/esm/utils/parsers/svg/parseSVGPathData.js +228 -205
- package/src/esm/utils/parsers/svg/parseSVGPathData.js.map +1 -1
- package/src/esm/utils/parsers/svg/splitSVGPathData.js +6 -2
- package/src/esm/utils/parsers/svg/splitSVGPathData.js.map +1 -1
- package/src/esm/utils/parsers/svg/types.d.ts +29 -9
- package/src/esm/utils/parsers/svg/types.js +4 -3
- package/src/esm/utils/parsers/svg/types.js.map +1 -1
- package/src/ts/utils/parsers/svg/parseSVGPathData.ts +271 -212
- package/src/ts/utils/parsers/svg/splitSVGPathData.ts +6 -2
- package/src/ts/utils/parsers/svg/types.ts +29 -9
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* @author Ikaros Kappler
|
|
10
10
|
* @date 2022-11-06
|
|
11
11
|
* @modified 2022-12-21 (winter solstice) Porting this to Typescript.
|
|
12
|
-
* @
|
|
12
|
+
* @modified 2023-01-17 Handling multiple parameter sets now.
|
|
13
|
+
* @version 0.0.2-alpha
|
|
13
14
|
**/
|
|
14
15
|
|
|
15
16
|
import { CubicBezierCurve } from "../../../CubicBezierCurve";
|
|
@@ -55,9 +56,10 @@ export const parseSVGPathData = (dataString: string): Array<Line | CubicBezierCu
|
|
|
55
56
|
const result: Array<Line | CubicBezierCurve> = [];
|
|
56
57
|
|
|
57
58
|
var i = 0;
|
|
58
|
-
const firstPoint = { x: NaN, y: NaN };
|
|
59
|
-
const lastPoint = { x: NaN, y: NaN };
|
|
60
|
-
const lastControlPoint = { x: NaN, y: NaN };
|
|
59
|
+
const firstPoint: XYCoords = { x: NaN, y: NaN };
|
|
60
|
+
const lastPoint: XYCoords = { x: NaN, y: NaN };
|
|
61
|
+
const lastControlPoint: XYCoords = { x: NaN, y: NaN };
|
|
62
|
+
const lastQuadraticControlPoint: XYCoords = { x: NaN, y: NaN };
|
|
61
63
|
|
|
62
64
|
while (i < dataElements.length) {
|
|
63
65
|
// Could this also be SVGPathShorthandQuadraticCurveToCommand?
|
|
@@ -191,28 +193,29 @@ const _handleLineTo = (
|
|
|
191
193
|
lastControlPoint: XYCoords,
|
|
192
194
|
result: Array<Line | CubicBezierCurve>
|
|
193
195
|
) => {
|
|
194
|
-
// console.log("Handle LINETO", data);
|
|
195
196
|
if (data.length < 3) {
|
|
196
197
|
throw "Unsufficient params for LINETO";
|
|
197
198
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
199
|
+
|
|
200
|
+
for (var i = 1; i + 1 < data.length; i += 2) {
|
|
201
|
+
const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
|
|
202
|
+
if (isRelative) {
|
|
203
|
+
line.b.x += Number(data[i]);
|
|
204
|
+
line.b.y += Number(data[i + 1]);
|
|
205
|
+
} else {
|
|
206
|
+
line.b.x = Number(data[i]);
|
|
207
|
+
line.b.y = Number(data[i + 1]);
|
|
208
|
+
}
|
|
209
|
+
result.push(line);
|
|
210
|
+
lastPoint.x = line.b.x;
|
|
211
|
+
lastPoint.y = line.b.y;
|
|
212
|
+
lastControlPoint.x = line.b.x;
|
|
213
|
+
lastControlPoint.y = line.b.y;
|
|
214
|
+
if (isNaN(firstPoint.y)) {
|
|
215
|
+
firstPoint.x = line.a.x;
|
|
216
|
+
firstPoint.y = line.a.y;
|
|
217
|
+
}
|
|
218
|
+
console.log("LINETO LINE", i, line.toString());
|
|
216
219
|
}
|
|
217
220
|
};
|
|
218
221
|
|
|
@@ -228,23 +231,24 @@ const _handleHorizontalLineTo = (
|
|
|
228
231
|
if (data.length < 2) {
|
|
229
232
|
throw "Unsufficient params for HORIZONTALLINETO";
|
|
230
233
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
234
|
+
|
|
235
|
+
for (var i = 1; i < data.length; i++) {
|
|
236
|
+
const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
|
|
237
|
+
if (isRelative) {
|
|
238
|
+
line.b.x += Number(data[i]);
|
|
239
|
+
// line.b.y += Number(data[2]);
|
|
240
|
+
} else {
|
|
241
|
+
line.b.x = Number(data[i]);
|
|
242
|
+
// line.b.y = Number(data[2]);
|
|
243
|
+
}
|
|
244
|
+
result.push(line);
|
|
245
|
+
lastPoint.x = line.b.x;
|
|
246
|
+
// lastPoint.y = line.b.y;
|
|
247
|
+
lastControlPoint.x = line.b.x;
|
|
248
|
+
if (isNaN(firstPoint.y)) {
|
|
249
|
+
firstPoint.x = line.a.x;
|
|
250
|
+
firstPoint.y = line.a.y;
|
|
251
|
+
}
|
|
248
252
|
}
|
|
249
253
|
};
|
|
250
254
|
|
|
@@ -256,27 +260,25 @@ const _handleVerticalLineTo = (
|
|
|
256
260
|
lastControlPoint: XYCoords,
|
|
257
261
|
result: Array<Line | CubicBezierCurve>
|
|
258
262
|
) => {
|
|
259
|
-
// console.log("Handle VERTICALLINETO", data);
|
|
260
263
|
if (data.length < 2) {
|
|
261
264
|
throw "Unsufficient params for VERTICALLINETO";
|
|
262
265
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
firstPoint.y = line.a.y;
|
|
266
|
+
|
|
267
|
+
for (var i = 1; i < data.length; i++) {
|
|
268
|
+
const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
|
|
269
|
+
if (isRelative) {
|
|
270
|
+
line.b.y += Number(data[i]);
|
|
271
|
+
} else {
|
|
272
|
+
line.b.y = Number(data[i]);
|
|
273
|
+
}
|
|
274
|
+
result.push(line);
|
|
275
|
+
// lastPoint.x = line.b.x;
|
|
276
|
+
lastPoint.y = line.b.y;
|
|
277
|
+
lastControlPoint.y = line.b.y;
|
|
278
|
+
if (isNaN(firstPoint.y)) {
|
|
279
|
+
firstPoint.x = line.a.x;
|
|
280
|
+
firstPoint.y = line.a.y;
|
|
281
|
+
}
|
|
280
282
|
}
|
|
281
283
|
};
|
|
282
284
|
|
|
@@ -293,32 +295,38 @@ const _handleCubicBezierTo = (
|
|
|
293
295
|
if (data.length < 7) {
|
|
294
296
|
throw "Unsufficient params for CUBICBEZIERTO";
|
|
295
297
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
298
|
+
|
|
299
|
+
for (var i = 1; i + 5 < data.length; i += 6) {
|
|
300
|
+
const curve = new CubicBezierCurve(
|
|
301
|
+
new Vertex(lastPoint),
|
|
302
|
+
new Vertex(lastPoint),
|
|
303
|
+
new Vertex(lastPoint),
|
|
304
|
+
new Vertex(lastPoint)
|
|
305
|
+
);
|
|
306
|
+
if (isRelative) {
|
|
307
|
+
curve.startControlPoint.x += Number(data[i]);
|
|
308
|
+
curve.startControlPoint.y += Number(data[i + 1]);
|
|
309
|
+
curve.endControlPoint.x += Number(data[i + 2]);
|
|
310
|
+
curve.endControlPoint.y += Number(data[i + 3]);
|
|
311
|
+
curve.endPoint.x += Number(data[i + 4]);
|
|
312
|
+
curve.endPoint.y += Number(data[i + 5]);
|
|
313
|
+
} else {
|
|
314
|
+
curve.startControlPoint.x = Number(data[i]);
|
|
315
|
+
curve.startControlPoint.y = Number(data[i + 1]);
|
|
316
|
+
curve.endControlPoint.x = Number(data[i + 2]);
|
|
317
|
+
curve.endControlPoint.y = Number(data[i + 3]);
|
|
318
|
+
curve.endPoint.x = Number(data[i + 4]);
|
|
319
|
+
curve.endPoint.y = Number(data[i + 5]);
|
|
320
|
+
}
|
|
321
|
+
result.push(curve);
|
|
322
|
+
lastPoint.x = curve.endPoint.x;
|
|
323
|
+
lastPoint.y = curve.endPoint.y;
|
|
324
|
+
lastControlPoint.x = curve.endControlPoint.x;
|
|
325
|
+
lastControlPoint.y = curve.endControlPoint.y;
|
|
326
|
+
if (isNaN(firstPoint.x)) {
|
|
327
|
+
firstPoint.x = curve.startPoint.x;
|
|
328
|
+
firstPoint.y = curve.startPoint.y;
|
|
329
|
+
}
|
|
322
330
|
}
|
|
323
331
|
};
|
|
324
332
|
|
|
@@ -335,102 +343,147 @@ const _handleQuadraticCurveTo = (
|
|
|
335
343
|
if (data.length < 5) {
|
|
336
344
|
throw "Unsufficient params for QUADRATICBEZIERTO";
|
|
337
345
|
}
|
|
338
|
-
// console.log("Y: ", Number(data[2]), "lastPoint", lastPoint);
|
|
339
|
-
// result.push( new)
|
|
340
|
-
const curve = new CubicBezierCurve(new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint));
|
|
341
|
-
if (isRelative) {
|
|
342
|
-
curve.startControlPoint.x += curve.startPoint.x + (Number(data[1]) - curve.startControlPoint.x); // * 0.666;
|
|
343
|
-
curve.startControlPoint.y += curve.startPoint.y + (Number(data[2]) - curve.startControlPoint.y); // * 0.666;
|
|
344
|
-
curve.endPoint.x += Number(data[3]);
|
|
345
|
-
curve.endPoint.y += Number(data[4]);
|
|
346
|
-
curve.endControlPoint.x = curve.startControlPoint.x;
|
|
347
|
-
curve.endControlPoint.y = curve.startControlPoint.y;
|
|
348
|
-
} else {
|
|
349
|
-
curve.startControlPoint.x = curve.startPoint.x + (Number(data[1]) - curve.startControlPoint.x); // * 0.666;
|
|
350
|
-
curve.startControlPoint.y = curve.startPoint.y + (Number(data[2]) - curve.startControlPoint.y); // * 0.666;
|
|
351
|
-
curve.endPoint.x = Number(data[3]);
|
|
352
|
-
curve.endPoint.y = Number(data[4]);
|
|
353
|
-
curve.endControlPoint.x = curve.startControlPoint.x;
|
|
354
|
-
curve.endControlPoint.y = curve.startControlPoint.y;
|
|
355
|
-
}
|
|
356
|
-
// var lastQuadraticControlPoint = { x: Number(data[1]), y: Number(data[2]) };
|
|
357
|
-
const lastQuadraticControlPoint = { x: curve.endControlPoint.x, y: curve.endControlPoint.y };
|
|
358
|
-
// Convert quadratic curve to cubic curve
|
|
359
|
-
curve.startControlPoint.x = curve.startPoint.x + (curve.startControlPoint.x - curve.startPoint.x) * 0.666;
|
|
360
|
-
curve.startControlPoint.y = curve.startPoint.y + (curve.startControlPoint.y - curve.startPoint.y) * 0.666;
|
|
361
|
-
curve.endControlPoint.x = curve.endPoint.x + (curve.endControlPoint.x - curve.endPoint.x) * 0.666;
|
|
362
|
-
curve.endControlPoint.y = curve.endPoint.y + (curve.endControlPoint.y - curve.endPoint.y) * 0.666;
|
|
363
346
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
347
|
+
var i = 1;
|
|
348
|
+
var localLastQuadraticControlPoint = { x: 0, y: 0 };
|
|
349
|
+
// This loops runs at least once
|
|
350
|
+
while (i + 3 < data.length && data[i] !== "t" && data[i] !== "T") {
|
|
351
|
+
const curve = new CubicBezierCurve(
|
|
352
|
+
new Vertex(lastPoint),
|
|
353
|
+
new Vertex(lastPoint),
|
|
354
|
+
new Vertex(lastPoint),
|
|
355
|
+
new Vertex(lastPoint)
|
|
356
|
+
);
|
|
357
|
+
if (isRelative) {
|
|
358
|
+
curve.startControlPoint.x += curve.startPoint.x + (Number(data[i]) - curve.startControlPoint.x); // * 0.666;
|
|
359
|
+
curve.startControlPoint.y += curve.startPoint.y + (Number(data[i + 1]) - curve.startControlPoint.y); // * 0.666;
|
|
360
|
+
curve.endPoint.x += Number(data[i + 2]);
|
|
361
|
+
curve.endPoint.y += Number(data[i + 3]);
|
|
362
|
+
curve.endControlPoint.x = curve.startControlPoint.x;
|
|
363
|
+
curve.endControlPoint.y = curve.startControlPoint.y;
|
|
364
|
+
} else {
|
|
365
|
+
curve.startControlPoint.x = curve.startPoint.x + (Number(data[i]) - curve.startControlPoint.x); // * 0.666;
|
|
366
|
+
curve.startControlPoint.y = curve.startPoint.y + (Number(data[i + 1]) - curve.startControlPoint.y); // * 0.666;
|
|
367
|
+
curve.endPoint.x = Number(data[i + 2]);
|
|
368
|
+
curve.endPoint.y = Number(data[i + 3]);
|
|
369
|
+
curve.endControlPoint.x = curve.startControlPoint.x;
|
|
370
|
+
curve.endControlPoint.y = curve.startControlPoint.y;
|
|
371
|
+
}
|
|
372
|
+
// var lastQuadraticControlPoint = { x: Number(data[1]), y: Number(data[2]) };
|
|
373
|
+
localLastQuadraticControlPoint = { x: curve.endControlPoint.x, y: curve.endControlPoint.y };
|
|
374
|
+
// Convert quadratic curve to cubic curve
|
|
375
|
+
curve.startControlPoint.x = curve.startPoint.x + (curve.startControlPoint.x - curve.startPoint.x) * 0.666;
|
|
376
|
+
curve.startControlPoint.y = curve.startPoint.y + (curve.startControlPoint.y - curve.startPoint.y) * 0.666;
|
|
377
|
+
curve.endControlPoint.x = curve.endPoint.x + (curve.endControlPoint.x - curve.endPoint.x) * 0.666;
|
|
378
|
+
curve.endControlPoint.y = curve.endPoint.y + (curve.endControlPoint.y - curve.endPoint.y) * 0.666;
|
|
379
|
+
|
|
380
|
+
result.push(curve);
|
|
381
|
+
lastPoint.x = curve.endPoint.x;
|
|
382
|
+
lastPoint.y = curve.endPoint.y;
|
|
383
|
+
lastControlPoint.x = curve.endControlPoint.x;
|
|
384
|
+
lastControlPoint.y = curve.endControlPoint.y;
|
|
385
|
+
if (isNaN(firstPoint.x)) {
|
|
386
|
+
firstPoint.x = curve.startPoint.x;
|
|
387
|
+
firstPoint.y = curve.startPoint.y;
|
|
388
|
+
}
|
|
389
|
+
i += 4;
|
|
390
|
+
} // END while
|
|
373
391
|
|
|
374
392
|
// 'T' or 't' command may follow
|
|
375
|
-
if (data.length >= 8) {
|
|
393
|
+
// if (data.length >= 8) {
|
|
394
|
+
if (i < data.length && (data[i] == "t" || data[i] === "T")) {
|
|
376
395
|
// TODO: think about this type cast!
|
|
377
396
|
const subData: SVGPathShorthandQuadraticCurveToCommand = data.slice(5) as SVGPathShorthandQuadraticCurveToCommand;
|
|
378
397
|
// var lastQuadraticControlPoint = { x: Number(data[1]), y: Number(data[2]) };
|
|
379
398
|
if (subData[0] === "T") {
|
|
380
|
-
// _handleShorthandQuadraticCurveTo(subData, false, firstPoint, lastPoint, lastControlPoint, result);
|
|
381
|
-
_handleShorthandQuadraticCurveTo(
|
|
399
|
+
// _handleShorthandQuadraticCurveTo(subData, false, firstPoint, lastPoint, lastControlPoint, lastQuadraticControlPoint, result);
|
|
400
|
+
_handleShorthandQuadraticCurveTo(
|
|
401
|
+
subData,
|
|
402
|
+
false,
|
|
403
|
+
firstPoint,
|
|
404
|
+
lastPoint,
|
|
405
|
+
lastControlPoint,
|
|
406
|
+
localLastQuadraticControlPoint,
|
|
407
|
+
result
|
|
408
|
+
);
|
|
382
409
|
} else if (subData[0] === "t") {
|
|
383
|
-
// _handleShorthandQuadraticCurveTo(subData, true, firstPoint, lastPoint, lastControlPoint, result);
|
|
384
|
-
_handleShorthandQuadraticCurveTo(
|
|
410
|
+
// _handleShorthandQuadraticCurveTo(subData, true, firstPoint, lastPoint, lastControlPoint, lastQuadraticControlPoint, result);
|
|
411
|
+
_handleShorthandQuadraticCurveTo(
|
|
412
|
+
subData,
|
|
413
|
+
true,
|
|
414
|
+
firstPoint,
|
|
415
|
+
lastPoint,
|
|
416
|
+
lastControlPoint,
|
|
417
|
+
localLastQuadraticControlPoint,
|
|
418
|
+
result
|
|
419
|
+
);
|
|
385
420
|
}
|
|
386
421
|
}
|
|
387
422
|
};
|
|
388
423
|
|
|
389
424
|
// This is a helper function and works only in combination with Quadratic Bézier Curves
|
|
390
|
-
// T|t x y
|
|
425
|
+
// T|t (x y)+
|
|
391
426
|
const _handleShorthandQuadraticCurveTo = (
|
|
392
427
|
data: SVGPathShorthandQuadraticCurveToCommand,
|
|
393
428
|
isRelative: boolean,
|
|
394
429
|
firstPoint: XYCoords,
|
|
395
430
|
lastPoint: XYCoords,
|
|
396
431
|
lastControlPoint: XYCoords,
|
|
432
|
+
lastQuadraticControlPoint: XYCoords,
|
|
397
433
|
result: Array<Line | CubicBezierCurve>
|
|
398
434
|
) => {
|
|
399
|
-
// console.log("Handle SHORTHANDQUADRATICCURVETO", data);
|
|
400
435
|
if (data.length < 3) {
|
|
401
436
|
throw "Unsufficient params for SHORTHANDQUADRATICCURVETO";
|
|
402
437
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
curve
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
438
|
+
var i = 1;
|
|
439
|
+
while (i + 1 < data.length) {
|
|
440
|
+
// Respect multiple 'T|t' commands here
|
|
441
|
+
if (data[i] === "T" || data[i] === "t") {
|
|
442
|
+
i++;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
const curve = new CubicBezierCurve(
|
|
446
|
+
new Vertex(lastPoint),
|
|
447
|
+
new Vertex(lastPoint),
|
|
448
|
+
new Vertex(lastPoint),
|
|
449
|
+
new Vertex(lastPoint)
|
|
450
|
+
);
|
|
451
|
+
if (isRelative) {
|
|
452
|
+
curve.endPoint.x += Number(data[i]);
|
|
453
|
+
curve.endPoint.y += Number(data[i + 1]);
|
|
454
|
+
curve.startControlPoint.x += curve.startPoint.x - (lastQuadraticControlPoint.x - lastPoint.x);
|
|
455
|
+
curve.startControlPoint.y += curve.startPoint.y - (lastQuadraticControlPoint.y - lastPoint.y);
|
|
456
|
+
} else {
|
|
457
|
+
curve.endPoint.x = Number(data[i]);
|
|
458
|
+
curve.endPoint.y = Number(data[i + 1]);
|
|
459
|
+
curve.startControlPoint.x = curve.startPoint.x - (lastQuadraticControlPoint.x - lastPoint.x);
|
|
460
|
+
curve.startControlPoint.y = curve.startPoint.y - (lastQuadraticControlPoint.y - lastPoint.y);
|
|
461
|
+
}
|
|
462
|
+
// First handle as symmetrical cubic curve
|
|
463
|
+
curve.endControlPoint.x = curve.startControlPoint.x;
|
|
464
|
+
curve.endControlPoint.y = curve.startControlPoint.y;
|
|
465
|
+
lastQuadraticControlPoint.y = curve.endControlPoint.y;
|
|
466
|
+
lastQuadraticControlPoint.x = curve.endControlPoint.x;
|
|
418
467
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
468
|
+
// Convert quadratic curve to cubic curve
|
|
469
|
+
var scaleFactor = 0.666; // i === 1 ? 0.666 : 1.0;
|
|
470
|
+
curve.startControlPoint.x = curve.startPoint.x + (curve.startControlPoint.x - curve.startPoint.x) * scaleFactor;
|
|
471
|
+
curve.startControlPoint.y = curve.startPoint.y + (curve.startControlPoint.y - curve.startPoint.y) * scaleFactor;
|
|
472
|
+
curve.endControlPoint.x = curve.endPoint.x + (curve.endControlPoint.x - curve.endPoint.x) * scaleFactor;
|
|
473
|
+
curve.endControlPoint.y = curve.endPoint.y + (curve.endControlPoint.y - curve.endPoint.y) * scaleFactor;
|
|
424
474
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
475
|
+
// console.log("ADDING T CURVE", curve);
|
|
476
|
+
result.push(curve);
|
|
477
|
+
lastPoint.x = curve.endPoint.x;
|
|
478
|
+
lastPoint.y = curve.endPoint.y;
|
|
479
|
+
lastControlPoint.x = curve.endControlPoint.x;
|
|
480
|
+
lastControlPoint.y = curve.endControlPoint.y;
|
|
481
|
+
if (isNaN(firstPoint.x)) {
|
|
482
|
+
firstPoint.x = curve.startPoint.x;
|
|
483
|
+
firstPoint.y = curve.startPoint.y;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
i += 2;
|
|
434
487
|
}
|
|
435
488
|
};
|
|
436
489
|
|
|
@@ -486,70 +539,76 @@ const _handleArcTo = (
|
|
|
486
539
|
lastControlPoint: XYCoords,
|
|
487
540
|
result: Array<Line | CubicBezierCurve>
|
|
488
541
|
) => {
|
|
489
|
-
// console.log("Handle ARCTO", data);
|
|
490
542
|
if (data.length < 8) {
|
|
491
543
|
throw "Unsufficient params for ARCTO";
|
|
492
544
|
}
|
|
493
545
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
// console.log(
|
|
501
|
-
// "lastPoint.x",
|
|
502
|
-
// lastPoint.x, // x1
|
|
503
|
-
// "lastPoint.y",
|
|
504
|
-
// lastPoint.y, // y1
|
|
505
|
-
// "data[1]",
|
|
506
|
-
// Number(data[1]), // rx
|
|
507
|
-
// "data[2]",
|
|
508
|
-
// Number(data[2]), // ry
|
|
509
|
-
// "data[3]",
|
|
510
|
-
// Number(data[3]), // phi: number,
|
|
511
|
-
// "data[4]",
|
|
512
|
-
// Boolean(data[4]), // fa: boolean,
|
|
513
|
-
// "data[5]",
|
|
514
|
-
// Boolean(data[5]), // fs: boolean,
|
|
515
|
-
// "data[6]",
|
|
516
|
-
// arcEndPoint.x, // Number(data[6]), // x2: number,
|
|
517
|
-
// "data[7]",
|
|
518
|
-
// arcEndPoint.y // Number(data[7]) // y2: number
|
|
519
|
-
// );
|
|
520
|
-
// A 5 4 0 1 1 -10 -5
|
|
521
|
-
// TODO: respect relative/absolute here
|
|
522
|
-
const ellipseSector = VEllipseSector.ellipseSectorUtils.endpointToCenterParameters(
|
|
523
|
-
lastPoint.x,
|
|
524
|
-
lastPoint.y,
|
|
525
|
-
Number(data[1]),
|
|
526
|
-
Number(data[2]),
|
|
527
|
-
Number(data[3]) * DEG_TO_RAD,
|
|
528
|
-
Boolean(data[4]),
|
|
529
|
-
Boolean(data[5]),
|
|
530
|
-
arcEndPoint.x,
|
|
531
|
-
arcEndPoint.y // Number(data[7]) // y2: number
|
|
532
|
-
);
|
|
533
|
-
|
|
534
|
-
// console.log("ellipseSector", ellipseSector);
|
|
535
|
-
const curves = ellipseSector.toCubicBezier(4); // 4 segments already seems to be a good approximation
|
|
536
|
-
for (var i = 0; i < curves.length; i++) {
|
|
537
|
-
result.push(curves[i]); // Destruct!
|
|
538
|
-
}
|
|
539
|
-
// result.push(ellipseSector.ellipse);
|
|
540
|
-
if (curves.length > 0) {
|
|
541
|
-
// console.log("curves", curves);
|
|
542
|
-
const lastCurve = curves[curves.length - 1];
|
|
543
|
-
lastPoint.x = lastCurve.endPoint.x;
|
|
544
|
-
lastPoint.y = lastCurve.endPoint.y;
|
|
545
|
-
lastControlPoint.x = lastCurve.endControlPoint.x;
|
|
546
|
-
lastControlPoint.y = lastCurve.endControlPoint.y;
|
|
547
|
-
if (isNaN(firstPoint.x)) {
|
|
548
|
-
firstPoint.x = curves[0].startPoint.x;
|
|
549
|
-
firstPoint.y = curves[0].startPoint.y;
|
|
546
|
+
for (var i = 1; i + 6 < data.length; i += 7) {
|
|
547
|
+
const arcEndPoint = { x: Number(data[i + 5]), y: Number(data[i + 6]) };
|
|
548
|
+
if (isRelative) {
|
|
549
|
+
arcEndPoint.x += lastPoint.x;
|
|
550
|
+
arcEndPoint.y += lastPoint.y;
|
|
550
551
|
}
|
|
551
|
-
|
|
552
|
+
// console.log(
|
|
553
|
+
// "ARC",
|
|
554
|
+
// "data.length",
|
|
555
|
+
// data.length,
|
|
556
|
+
// "i",
|
|
557
|
+
// i,
|
|
558
|
+
// "lastPoint.x",
|
|
559
|
+
// lastPoint.x, // x1
|
|
560
|
+
// "lastPoint.y",
|
|
561
|
+
// lastPoint.y, // y1
|
|
562
|
+
// "data[i]",
|
|
563
|
+
// Number(data[i]), // rx
|
|
564
|
+
// "data[i+1]",
|
|
565
|
+
// Number(data[i + 1]), // ry
|
|
566
|
+
// "data[i+2]",
|
|
567
|
+
// Number(data[i + 2]), // phi: number,
|
|
568
|
+
// "data[i+3]",
|
|
569
|
+
// Boolean(data[i + 3]), // fa: boolean,
|
|
570
|
+
// "data[i+4]",
|
|
571
|
+
// Boolean(data[i + 4]), // fs: boolean,
|
|
572
|
+
// "data[i+5]",
|
|
573
|
+
// arcEndPoint.x, // Number(data[6]), // x2: number,
|
|
574
|
+
// "data[i+6]",
|
|
575
|
+
// arcEndPoint.y // Number(data[7]) // y2: number
|
|
576
|
+
// );
|
|
577
|
+
// A 5 4 0 1 1 -10 -5
|
|
578
|
+
// TODO: respect relative/absolute here
|
|
579
|
+
const ellipseSector = VEllipseSector.ellipseSectorUtils.endpointToCenterParameters(
|
|
580
|
+
lastPoint.x,
|
|
581
|
+
lastPoint.y,
|
|
582
|
+
Number(data[i]),
|
|
583
|
+
Number(data[i + 1]),
|
|
584
|
+
Number(data[i + 2]) * DEG_TO_RAD,
|
|
585
|
+
Boolean(data[i + 3]),
|
|
586
|
+
Boolean(data[i + 4]),
|
|
587
|
+
arcEndPoint.x,
|
|
588
|
+
arcEndPoint.y // Number(data[7]) // y2: number
|
|
589
|
+
);
|
|
552
590
|
|
|
591
|
+
// console.log("ellipseSector", ellipseSector);
|
|
592
|
+
const curves = ellipseSector.toCubicBezier(4); // 4 segments already seems to be a good approximation
|
|
593
|
+
for (var j = 0; j < curves.length; j++) {
|
|
594
|
+
result.push(curves[j]); // Destruct!
|
|
595
|
+
}
|
|
596
|
+
// result.push(ellipseSector.ellipse);
|
|
597
|
+
if (curves.length > 0) {
|
|
598
|
+
// console.log("curves", curves);
|
|
599
|
+
const lastCurve = curves[curves.length - 1];
|
|
600
|
+
// lastPoint.x = lastCurve.endPoint.x;
|
|
601
|
+
// lastPoint.y = lastCurve.endPoint.y;
|
|
602
|
+
lastControlPoint.x = lastCurve.endControlPoint.x;
|
|
603
|
+
lastControlPoint.y = lastCurve.endControlPoint.y;
|
|
604
|
+
if (isNaN(firstPoint.x)) {
|
|
605
|
+
firstPoint.x = curves[0].startPoint.x;
|
|
606
|
+
firstPoint.y = curves[0].startPoint.y;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
lastPoint.x = arcEndPoint.x;
|
|
610
|
+
lastPoint.y = arcEndPoint.y;
|
|
611
|
+
} // END for
|
|
553
612
|
// TODO: track first/last/control point
|
|
554
613
|
};
|
|
555
614
|
|
|
@@ -20,13 +20,17 @@ import { SVGPathCommand } from "./types";
|
|
|
20
20
|
* @param {string} dataString - The SVG path data to split. This should be some string
|
|
21
21
|
**/
|
|
22
22
|
export const splitSVGPathData = (dataString: string): Array<SVGPathCommand> | null => {
|
|
23
|
+
// I used a modified version of this Josh Frank's SVG path data RexEx.
|
|
23
24
|
// Source
|
|
24
25
|
// https://javascript.plainenglish.io/june-3-parsing-and-validating-svg-paths-with-regex-7bd0e245115
|
|
26
|
+
// const validCommand =
|
|
27
|
+
// /([ml](\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))|([hv](\s?-?((\d+(\.\d+)?)|(\.\d+))))|(c(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){5})|(q(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3}(\s?t?(\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))*)|(a(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2}[,\s]?[01][,\s]+[01][,\s]+([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2})|(s(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})|z/gi;
|
|
28
|
+
//
|
|
29
|
+
// My Version allows multiple param sets, too, like 'm|M (x y)+' or 'q|Q (x1 y1 x y)+'. Look at the plus.
|
|
25
30
|
const validCommand =
|
|
26
|
-
/([ml](\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))|([hv](\s?-?((\d+(\.\d+)?)|(\.\d+))))|(c(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){5})|(q(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3}(\s?t?(\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))*)|(a(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2}[,\s]?[01][,\s]+[01][,\s]+([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2})|(s(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})|z/gi;
|
|
31
|
+
/([ml]((\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))+)|([hv]((\s?-?((\d+(\.\d+)?)|(\.\d+))))+)|(c((\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){5})+)|(q((\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})+(\s?(t?(\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))*)+)|(a((\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2}[,\s]?[01][,\s]+[01][,\s]+([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2})+)|(s(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})|z/gi;
|
|
27
32
|
|
|
28
33
|
const dataElements = dataString.match(validCommand);
|
|
29
|
-
// console.log("Splitted: ", dataElements);
|
|
30
34
|
if (!dataElements) {
|
|
31
35
|
return null;
|
|
32
36
|
}
|