@emasoft/svg-matrix 1.1.0 → 1.2.0
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/bin/svg-matrix.js +7 -6
- package/bin/svgm.js +109 -40
- package/dist/svg-matrix.min.js +7 -7
- package/dist/svg-toolbox.min.js +148 -228
- package/dist/svgm.min.js +152 -232
- package/dist/version.json +5 -5
- package/package.json +1 -1
- package/scripts/postinstall.js +72 -41
- package/scripts/test-postinstall.js +18 -16
- package/scripts/version-sync.js +78 -60
- package/src/animation-optimization.js +190 -98
- package/src/animation-references.js +11 -3
- package/src/arc-length.js +23 -20
- package/src/bezier-analysis.js +9 -13
- package/src/bezier-intersections.js +18 -4
- package/src/browser-verify.js +35 -8
- package/src/clip-path-resolver.js +285 -114
- package/src/convert-path-data.js +20 -8
- package/src/css-specificity.js +33 -9
- package/src/douglas-peucker.js +272 -141
- package/src/geometry-to-path.js +79 -22
- package/src/gjk-collision.js +287 -126
- package/src/index.js +56 -21
- package/src/inkscape-support.js +122 -101
- package/src/logger.js +43 -27
- package/src/marker-resolver.js +201 -121
- package/src/mask-resolver.js +231 -98
- package/src/matrix.js +9 -5
- package/src/mesh-gradient.js +22 -14
- package/src/off-canvas-detection.js +53 -17
- package/src/path-optimization.js +356 -171
- package/src/path-simplification.js +671 -256
- package/src/pattern-resolver.js +1 -3
- package/src/polygon-clip.js +396 -78
- package/src/svg-boolean-ops.js +90 -23
- package/src/svg-collections.js +1546 -667
- package/src/svg-flatten.js +152 -38
- package/src/svg-matrix-lib.js +2 -2
- package/src/svg-parser.js +5 -1
- package/src/svg-rendering-context.js +3 -1
- package/src/svg-toolbox-lib.js +2 -2
- package/src/svg-toolbox.js +99 -457
- package/src/svg-validation-data.js +513 -345
- package/src/svg2-polyfills.js +156 -93
- package/src/svgm-lib.js +8 -4
- package/src/transform-optimization.js +168 -51
- package/src/transforms2d.js +73 -40
- package/src/transforms3d.js +34 -27
- package/src/use-symbol-resolver.js +175 -76
- package/src/vector.js +80 -44
- package/src/vendor/inkscape-hatch-polyfill.js +143 -108
- package/src/vendor/inkscape-hatch-polyfill.min.js +291 -1
- package/src/vendor/inkscape-mesh-polyfill.js +953 -766
- package/src/vendor/inkscape-mesh-polyfill.min.js +896 -1
- package/src/verification.js +3 -4
package/src/bezier-analysis.js
CHANGED
|
@@ -49,9 +49,7 @@ function _assertFinite(val, context) {
|
|
|
49
49
|
// INPUT VALIDATION: Ensure val is a Decimal instance
|
|
50
50
|
// WHY: Calling .isFinite() on null/undefined/non-Decimal throws errors
|
|
51
51
|
if (!val || !(val instanceof Decimal)) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`${context}: expected Decimal instance, got ${typeof val}`,
|
|
54
|
-
);
|
|
52
|
+
throw new Error(`${context}: expected Decimal instance, got ${typeof val}`);
|
|
55
53
|
}
|
|
56
54
|
if (!val.isFinite()) {
|
|
57
55
|
throw new Error(`${context}: encountered non-finite value ${val}`);
|
|
@@ -982,9 +980,7 @@ function findRootsBySubdivision(coeffs, t0, t1, maxDepth) {
|
|
|
982
980
|
const t0D = t0 instanceof Decimal ? t0 : D(t0);
|
|
983
981
|
const t1D = t1 instanceof Decimal ? t1 : D(t1);
|
|
984
982
|
if (!t0D.isFinite() || !t1D.isFinite()) {
|
|
985
|
-
throw new Error(
|
|
986
|
-
"findRootsBySubdivision: t0 and t1 must be finite numbers",
|
|
987
|
-
);
|
|
983
|
+
throw new Error("findRootsBySubdivision: t0 and t1 must be finite numbers");
|
|
988
984
|
}
|
|
989
985
|
if (t1D.lte(t0D)) {
|
|
990
986
|
throw new Error("findRootsBySubdivision: t1 must be greater than t0");
|
|
@@ -1189,14 +1185,10 @@ export function polynomialToBezier(xCoeffs, yCoeffs) {
|
|
|
1189
1185
|
// WHY: Arithmetic operations fail on null/undefined values
|
|
1190
1186
|
for (let i = 0; i < xCoeffs.length; i++) {
|
|
1191
1187
|
if (xCoeffs[i] == null) {
|
|
1192
|
-
throw new Error(
|
|
1193
|
-
`polynomialToBezier: xCoeffs[${i}] is null or undefined`,
|
|
1194
|
-
);
|
|
1188
|
+
throw new Error(`polynomialToBezier: xCoeffs[${i}] is null or undefined`);
|
|
1195
1189
|
}
|
|
1196
1190
|
if (yCoeffs[i] == null) {
|
|
1197
|
-
throw new Error(
|
|
1198
|
-
`polynomialToBezier: yCoeffs[${i}] is null or undefined`,
|
|
1199
|
-
);
|
|
1191
|
+
throw new Error(`polynomialToBezier: yCoeffs[${i}] is null or undefined`);
|
|
1200
1192
|
}
|
|
1201
1193
|
}
|
|
1202
1194
|
|
|
@@ -1686,7 +1678,11 @@ export function verifyBoundingBox(points, samples = 100, tolerance = "1e-40") {
|
|
|
1686
1678
|
|
|
1687
1679
|
// PARAMETER VALIDATION: Ensure samples is a positive integer
|
|
1688
1680
|
// WHY: Non-positive or non-integer samples would cause loop errors or division by zero
|
|
1689
|
-
if (
|
|
1681
|
+
if (
|
|
1682
|
+
typeof samples !== "number" ||
|
|
1683
|
+
samples < 1 ||
|
|
1684
|
+
!Number.isInteger(samples)
|
|
1685
|
+
) {
|
|
1690
1686
|
throw new Error(
|
|
1691
1687
|
`verifyBoundingBox: samples must be a positive integer, got ${samples}`,
|
|
1692
1688
|
);
|
|
@@ -989,7 +989,11 @@ function refineSelfIntersection(bezier, t1Init, t2Init, tol, minSep) {
|
|
|
989
989
|
const tryT2 = Decimal.max(D(0), Decimal.min(D(1), t2.plus(dt2)));
|
|
990
990
|
const [tx1, ty1] = bezierPoint(bezier, tryT1);
|
|
991
991
|
const [tx2, ty2] = bezierPoint(bezier, tryT2);
|
|
992
|
-
const tryError = tx1
|
|
992
|
+
const tryError = tx1
|
|
993
|
+
.minus(tx2)
|
|
994
|
+
.pow(2)
|
|
995
|
+
.plus(ty1.minus(ty2).pow(2))
|
|
996
|
+
.sqrt();
|
|
993
997
|
|
|
994
998
|
if (tryError.lt(bestError)) {
|
|
995
999
|
bestError = tryError;
|
|
@@ -1256,7 +1260,11 @@ export function verifyLineLineIntersection(
|
|
|
1256
1260
|
if (intersection.t2 === undefined || intersection.t2 === null) {
|
|
1257
1261
|
return { valid: false, reason: "intersection.t2 is missing" };
|
|
1258
1262
|
}
|
|
1259
|
-
if (
|
|
1263
|
+
if (
|
|
1264
|
+
!intersection.point ||
|
|
1265
|
+
!Array.isArray(intersection.point) ||
|
|
1266
|
+
intersection.point.length < 2
|
|
1267
|
+
) {
|
|
1260
1268
|
return { valid: false, reason: "intersection.point is missing or invalid" };
|
|
1261
1269
|
}
|
|
1262
1270
|
|
|
@@ -1386,7 +1394,11 @@ export function verifyBezierLineIntersection(
|
|
|
1386
1394
|
if (intersection.t2 === undefined || intersection.t2 === null) {
|
|
1387
1395
|
return { valid: false, reason: "intersection.t2 is missing" };
|
|
1388
1396
|
}
|
|
1389
|
-
if (
|
|
1397
|
+
if (
|
|
1398
|
+
!intersection.point ||
|
|
1399
|
+
!Array.isArray(intersection.point) ||
|
|
1400
|
+
intersection.point.length < 2
|
|
1401
|
+
) {
|
|
1390
1402
|
return { valid: false, reason: "intersection.point is missing or invalid" };
|
|
1391
1403
|
}
|
|
1392
1404
|
|
|
@@ -1754,7 +1766,9 @@ export function verifyPathPathIntersection(
|
|
|
1754
1766
|
export function verifyAllIntersectionFunctions(tolerance = "1e-30") {
|
|
1755
1767
|
// WHY: Validate tolerance parameter to prevent invalid configuration
|
|
1756
1768
|
if (tolerance === undefined || tolerance === null) {
|
|
1757
|
-
throw new Error(
|
|
1769
|
+
throw new Error(
|
|
1770
|
+
"verifyAllIntersectionFunctions: tolerance cannot be undefined or null",
|
|
1771
|
+
);
|
|
1758
1772
|
}
|
|
1759
1773
|
|
|
1760
1774
|
const results = {};
|
package/src/browser-verify.js
CHANGED
|
@@ -160,7 +160,9 @@ export class BrowserVerifier {
|
|
|
160
160
|
}
|
|
161
161
|
const ctm = rect.getCTM();
|
|
162
162
|
if (!ctm) {
|
|
163
|
-
throw new Error(
|
|
163
|
+
throw new Error(
|
|
164
|
+
"getCTM() returned null - element may not be rendered",
|
|
165
|
+
);
|
|
164
166
|
}
|
|
165
167
|
return { a: ctm.a, b: ctm.b, c: ctm.c, d: ctm.d, e: ctm.e, f: ctm.f };
|
|
166
168
|
} finally {
|
|
@@ -309,7 +311,9 @@ export class BrowserVerifier {
|
|
|
309
311
|
}
|
|
310
312
|
const ctm = rect.getCTM();
|
|
311
313
|
if (!ctm) {
|
|
312
|
-
throw new Error(
|
|
314
|
+
throw new Error(
|
|
315
|
+
"getCTM() returned null - element may not be rendered",
|
|
316
|
+
);
|
|
313
317
|
}
|
|
314
318
|
if (!svg.createSVGPoint || typeof svg.createSVGPoint !== "function") {
|
|
315
319
|
throw new Error("Browser does not support createSVGPoint API");
|
|
@@ -317,7 +321,10 @@ export class BrowserVerifier {
|
|
|
317
321
|
const point = svg.createSVGPoint();
|
|
318
322
|
point.x = px;
|
|
319
323
|
point.y = py;
|
|
320
|
-
if (
|
|
324
|
+
if (
|
|
325
|
+
!point.matrixTransform ||
|
|
326
|
+
typeof point.matrixTransform !== "function"
|
|
327
|
+
) {
|
|
321
328
|
throw new Error("Browser does not support matrixTransform API");
|
|
322
329
|
}
|
|
323
330
|
const transformed = point.matrixTransform(ctm);
|
|
@@ -356,7 +363,11 @@ export class BrowserVerifier {
|
|
|
356
363
|
"matrix.data must have at least 2 rows with at least 3 columns each",
|
|
357
364
|
);
|
|
358
365
|
}
|
|
359
|
-
if (
|
|
366
|
+
if (
|
|
367
|
+
typeof tolerance !== "number" ||
|
|
368
|
+
!isFinite(tolerance) ||
|
|
369
|
+
tolerance < 0
|
|
370
|
+
) {
|
|
360
371
|
throw new Error("tolerance must be a non-negative finite number");
|
|
361
372
|
}
|
|
362
373
|
// Validate that matrix.data contains Decimal objects with toNumber() method
|
|
@@ -432,7 +443,11 @@ export class BrowserVerifier {
|
|
|
432
443
|
) {
|
|
433
444
|
throw new Error("preserveAspectRatio must be a non-empty string");
|
|
434
445
|
}
|
|
435
|
-
if (
|
|
446
|
+
if (
|
|
447
|
+
typeof tolerance !== "number" ||
|
|
448
|
+
!isFinite(tolerance) ||
|
|
449
|
+
tolerance < 0
|
|
450
|
+
) {
|
|
436
451
|
throw new Error("tolerance must be a non-negative finite number");
|
|
437
452
|
}
|
|
438
453
|
|
|
@@ -476,7 +491,11 @@ export class BrowserVerifier {
|
|
|
476
491
|
if (typeof transform !== "string" || transform.trim().length === 0) {
|
|
477
492
|
throw new Error("transform must be a non-empty string");
|
|
478
493
|
}
|
|
479
|
-
if (
|
|
494
|
+
if (
|
|
495
|
+
typeof tolerance !== "number" ||
|
|
496
|
+
!isFinite(tolerance) ||
|
|
497
|
+
tolerance < 0
|
|
498
|
+
) {
|
|
480
499
|
throw new Error("tolerance must be a non-negative finite number");
|
|
481
500
|
}
|
|
482
501
|
|
|
@@ -522,7 +541,11 @@ export class BrowserVerifier {
|
|
|
522
541
|
if (!config || typeof config !== "object") {
|
|
523
542
|
throw new Error("config must be a valid object");
|
|
524
543
|
}
|
|
525
|
-
if (
|
|
544
|
+
if (
|
|
545
|
+
typeof tolerance !== "number" ||
|
|
546
|
+
!isFinite(tolerance) ||
|
|
547
|
+
tolerance < 0
|
|
548
|
+
) {
|
|
526
549
|
throw new Error("tolerance must be a non-negative finite number");
|
|
527
550
|
}
|
|
528
551
|
|
|
@@ -568,7 +591,11 @@ export class BrowserVerifier {
|
|
|
568
591
|
if (!Array.isArray(testCases)) {
|
|
569
592
|
throw new Error("testCases must be an array");
|
|
570
593
|
}
|
|
571
|
-
if (
|
|
594
|
+
if (
|
|
595
|
+
typeof tolerance !== "number" ||
|
|
596
|
+
!isFinite(tolerance) ||
|
|
597
|
+
tolerance < 0
|
|
598
|
+
) {
|
|
572
599
|
throw new Error("tolerance must be a non-negative finite number");
|
|
573
600
|
}
|
|
574
601
|
|