@emasoft/svg-matrix 1.0.34 → 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/README.md +58 -2
- 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 +125 -205
- package/dist/svgm.min.js +115 -195
- package/dist/version.json +5 -5
- package/package.json +6 -1
- package/scripts/postinstall.js +72 -41
- package/scripts/test-postinstall.js +18 -16
- package/scripts/version-sync.js +144 -49
- 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 +6 -4
- 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 +177 -87
- package/src/svgm-lib.js +10 -6
- 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/svg-boolean-ops.js
CHANGED
|
@@ -60,9 +60,16 @@ export function pointInPolygonWithRule(
|
|
|
60
60
|
fillRule = FillRule.NONZERO,
|
|
61
61
|
) {
|
|
62
62
|
if (!pt || typeof pt !== "object") {
|
|
63
|
-
throw new Error(
|
|
63
|
+
throw new Error(
|
|
64
|
+
"pointInPolygonWithRule: pt must be an object with x, y properties",
|
|
65
|
+
);
|
|
64
66
|
}
|
|
65
|
-
if (
|
|
67
|
+
if (
|
|
68
|
+
pt.x === undefined ||
|
|
69
|
+
pt.x === null ||
|
|
70
|
+
pt.y === undefined ||
|
|
71
|
+
pt.y === null
|
|
72
|
+
) {
|
|
66
73
|
throw new Error("pointInPolygonWithRule: pt must have x and y properties");
|
|
67
74
|
}
|
|
68
75
|
if (!Array.isArray(polygon)) {
|
|
@@ -121,9 +128,20 @@ function pointOnSegment(pt, a, b) {
|
|
|
121
128
|
if (!pt || !a || !b) {
|
|
122
129
|
throw new Error("pointOnSegment: pt, a, and b must be defined");
|
|
123
130
|
}
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
|
|
131
|
+
if (
|
|
132
|
+
pt.x === undefined ||
|
|
133
|
+
pt.x === null ||
|
|
134
|
+
pt.y === undefined ||
|
|
135
|
+
pt.y === null ||
|
|
136
|
+
a.x === undefined ||
|
|
137
|
+
a.x === null ||
|
|
138
|
+
a.y === undefined ||
|
|
139
|
+
a.y === null ||
|
|
140
|
+
b.x === undefined ||
|
|
141
|
+
b.x === null ||
|
|
142
|
+
b.y === undefined ||
|
|
143
|
+
b.y === null
|
|
144
|
+
) {
|
|
127
145
|
throw new Error("pointOnSegment: all points must have x and y properties");
|
|
128
146
|
}
|
|
129
147
|
const crossVal = cross(a, b, pt);
|
|
@@ -270,8 +288,14 @@ export function circleToPolygon(circle, segments = 32) {
|
|
|
270
288
|
if (circle.r === undefined || circle.r === null) {
|
|
271
289
|
throw new Error("circleToPolygon: circle must have r property");
|
|
272
290
|
}
|
|
273
|
-
if (
|
|
274
|
-
|
|
291
|
+
if (
|
|
292
|
+
typeof segments !== "number" ||
|
|
293
|
+
segments <= 0 ||
|
|
294
|
+
!Number.isFinite(segments)
|
|
295
|
+
) {
|
|
296
|
+
throw new Error(
|
|
297
|
+
"circleToPolygon: segments must be a positive finite number",
|
|
298
|
+
);
|
|
275
299
|
}
|
|
276
300
|
const cx = D(circle.cx || 0);
|
|
277
301
|
const cy = D(circle.cy || 0);
|
|
@@ -312,8 +336,14 @@ export function ellipseToPolygon(ellipse, segments = 32) {
|
|
|
312
336
|
if (ellipse.ry === undefined || ellipse.ry === null) {
|
|
313
337
|
throw new Error("ellipseToPolygon: ellipse must have ry property");
|
|
314
338
|
}
|
|
315
|
-
if (
|
|
316
|
-
|
|
339
|
+
if (
|
|
340
|
+
typeof segments !== "number" ||
|
|
341
|
+
segments <= 0 ||
|
|
342
|
+
!Number.isFinite(segments)
|
|
343
|
+
) {
|
|
344
|
+
throw new Error(
|
|
345
|
+
"ellipseToPolygon: segments must be a positive finite number",
|
|
346
|
+
);
|
|
317
347
|
}
|
|
318
348
|
const cx = D(ellipse.cx || 0);
|
|
319
349
|
const cy = D(ellipse.cy || 0);
|
|
@@ -465,8 +495,15 @@ export function svgPolygonToPolygon(points) {
|
|
|
465
495
|
throw new Error("svgPolygonToPolygon: points array cannot be empty");
|
|
466
496
|
}
|
|
467
497
|
return points.map((p) => {
|
|
468
|
-
if (
|
|
469
|
-
|
|
498
|
+
if (
|
|
499
|
+
!p ||
|
|
500
|
+
typeof p !== "object" ||
|
|
501
|
+
p.x === undefined ||
|
|
502
|
+
p.y === undefined
|
|
503
|
+
) {
|
|
504
|
+
throw new Error(
|
|
505
|
+
"svgPolygonToPolygon: each point must have x and y properties",
|
|
506
|
+
);
|
|
470
507
|
}
|
|
471
508
|
return point(p.x, p.y);
|
|
472
509
|
});
|
|
@@ -485,15 +522,21 @@ export function svgPolygonToPolygon(points) {
|
|
|
485
522
|
const coords = trimmed.split(/[\s,]+/).map(Number);
|
|
486
523
|
|
|
487
524
|
if (coords.length < 2) {
|
|
488
|
-
throw new Error(
|
|
525
|
+
throw new Error(
|
|
526
|
+
"svgPolygonToPolygon: points must contain at least one coordinate pair",
|
|
527
|
+
);
|
|
489
528
|
}
|
|
490
529
|
|
|
491
530
|
if (coords.length % 2 !== 0) {
|
|
492
|
-
throw new Error(
|
|
531
|
+
throw new Error(
|
|
532
|
+
"svgPolygonToPolygon: points must contain an even number of coordinates",
|
|
533
|
+
);
|
|
493
534
|
}
|
|
494
535
|
|
|
495
536
|
if (coords.some((c) => !Number.isFinite(c))) {
|
|
496
|
-
throw new Error(
|
|
537
|
+
throw new Error(
|
|
538
|
+
"svgPolygonToPolygon: all coordinates must be finite numbers",
|
|
539
|
+
);
|
|
497
540
|
}
|
|
498
541
|
|
|
499
542
|
const vertices = [];
|
|
@@ -688,7 +731,9 @@ export function strokeToFilledPolygon(polygon, strokeProps) {
|
|
|
688
731
|
throw new Error("strokeToFilledPolygon: strokeProps must be an object");
|
|
689
732
|
}
|
|
690
733
|
if (strokeProps.width === undefined || strokeProps.width === null) {
|
|
691
|
-
throw new Error(
|
|
734
|
+
throw new Error(
|
|
735
|
+
"strokeToFilledPolygon: strokeProps must have width property",
|
|
736
|
+
);
|
|
692
737
|
}
|
|
693
738
|
|
|
694
739
|
const halfWidth = D(strokeProps.width).div(2);
|
|
@@ -732,8 +777,12 @@ export function applyDashArray(polygon, dashArray, dashOffset = 0) {
|
|
|
732
777
|
throw new Error("applyDashArray: dashArray must be an array");
|
|
733
778
|
}
|
|
734
779
|
|
|
735
|
-
if (
|
|
736
|
-
|
|
780
|
+
if (
|
|
781
|
+
dashArray.some((d) => typeof d !== "number" || !Number.isFinite(d) || d < 0)
|
|
782
|
+
) {
|
|
783
|
+
throw new Error(
|
|
784
|
+
"applyDashArray: all dash values must be non-negative finite numbers",
|
|
785
|
+
);
|
|
737
786
|
}
|
|
738
787
|
|
|
739
788
|
// Normalize dash array (must have even length)
|
|
@@ -912,7 +961,11 @@ export class SVGRegion {
|
|
|
912
961
|
}
|
|
913
962
|
|
|
914
963
|
// Add stroke region if element has stroke
|
|
915
|
-
if (
|
|
964
|
+
if (
|
|
965
|
+
style.stroke !== "none" &&
|
|
966
|
+
typeof style.strokeWidth === "number" &&
|
|
967
|
+
style.strokeWidth > 0
|
|
968
|
+
) {
|
|
916
969
|
const sourcePolygon =
|
|
917
970
|
type === "line"
|
|
918
971
|
? lineToPolygon(props, {
|
|
@@ -925,7 +978,10 @@ export class SVGRegion {
|
|
|
925
978
|
let strokePolygons;
|
|
926
979
|
|
|
927
980
|
// Apply dash array if present
|
|
928
|
-
if (
|
|
981
|
+
if (
|
|
982
|
+
Array.isArray(style.strokeDasharray) &&
|
|
983
|
+
style.strokeDasharray.length > 0
|
|
984
|
+
) {
|
|
929
985
|
const dashedSegments = applyDashArray(
|
|
930
986
|
sourcePolygon,
|
|
931
987
|
style.strokeDasharray,
|
|
@@ -974,8 +1030,15 @@ export class SVGRegion {
|
|
|
974
1030
|
if (!pt || typeof pt !== "object") {
|
|
975
1031
|
throw new Error("SVGRegion.containsPoint: pt must be an object");
|
|
976
1032
|
}
|
|
977
|
-
if (
|
|
978
|
-
|
|
1033
|
+
if (
|
|
1034
|
+
pt.x === undefined ||
|
|
1035
|
+
pt.x === null ||
|
|
1036
|
+
pt.y === undefined ||
|
|
1037
|
+
pt.y === null
|
|
1038
|
+
) {
|
|
1039
|
+
throw new Error(
|
|
1040
|
+
"SVGRegion.containsPoint: pt must have x and y properties",
|
|
1041
|
+
);
|
|
979
1042
|
}
|
|
980
1043
|
|
|
981
1044
|
// Check fill polygons with fill rule
|
|
@@ -1012,10 +1075,14 @@ export class SVGRegion {
|
|
|
1012
1075
|
*/
|
|
1013
1076
|
export function regionIntersection(regionA, regionB) {
|
|
1014
1077
|
if (!regionA || !(regionA instanceof SVGRegion)) {
|
|
1015
|
-
throw new Error(
|
|
1078
|
+
throw new Error(
|
|
1079
|
+
"regionIntersection: regionA must be an SVGRegion instance",
|
|
1080
|
+
);
|
|
1016
1081
|
}
|
|
1017
1082
|
if (!regionB || !(regionB instanceof SVGRegion)) {
|
|
1018
|
-
throw new Error(
|
|
1083
|
+
throw new Error(
|
|
1084
|
+
"regionIntersection: regionB must be an SVGRegion instance",
|
|
1085
|
+
);
|
|
1019
1086
|
}
|
|
1020
1087
|
|
|
1021
1088
|
const resultPolygons = [];
|