@emasoft/svg-matrix 1.0.27 → 1.0.29

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 (46) hide show
  1. package/README.md +325 -0
  2. package/bin/svg-matrix.js +994 -378
  3. package/bin/svglinter.cjs +4172 -433
  4. package/bin/svgm.js +744 -184
  5. package/package.json +16 -4
  6. package/src/animation-references.js +71 -52
  7. package/src/arc-length.js +160 -96
  8. package/src/bezier-analysis.js +257 -117
  9. package/src/bezier-intersections.js +411 -148
  10. package/src/browser-verify.js +240 -100
  11. package/src/clip-path-resolver.js +350 -142
  12. package/src/convert-path-data.js +279 -134
  13. package/src/css-specificity.js +78 -70
  14. package/src/flatten-pipeline.js +751 -263
  15. package/src/geometry-to-path.js +511 -182
  16. package/src/index.js +191 -46
  17. package/src/inkscape-support.js +404 -0
  18. package/src/marker-resolver.js +278 -164
  19. package/src/mask-resolver.js +209 -98
  20. package/src/matrix.js +147 -67
  21. package/src/mesh-gradient.js +187 -96
  22. package/src/off-canvas-detection.js +201 -104
  23. package/src/path-analysis.js +187 -107
  24. package/src/path-data-plugins.js +628 -167
  25. package/src/path-simplification.js +0 -1
  26. package/src/pattern-resolver.js +125 -88
  27. package/src/polygon-clip.js +111 -66
  28. package/src/svg-boolean-ops.js +194 -118
  29. package/src/svg-collections.js +48 -19
  30. package/src/svg-flatten.js +282 -164
  31. package/src/svg-parser.js +427 -200
  32. package/src/svg-rendering-context.js +147 -104
  33. package/src/svg-toolbox.js +16411 -3298
  34. package/src/svg2-polyfills.js +114 -245
  35. package/src/transform-decomposition.js +46 -41
  36. package/src/transform-optimization.js +89 -68
  37. package/src/transforms2d.js +49 -16
  38. package/src/transforms3d.js +58 -22
  39. package/src/use-symbol-resolver.js +150 -110
  40. package/src/vector.js +67 -15
  41. package/src/vendor/README.md +110 -0
  42. package/src/vendor/inkscape-hatch-polyfill.js +401 -0
  43. package/src/vendor/inkscape-hatch-polyfill.min.js +8 -0
  44. package/src/vendor/inkscape-mesh-polyfill.js +843 -0
  45. package/src/vendor/inkscape-mesh-polyfill.min.js +8 -0
  46. package/src/verification.js +288 -124
@@ -43,16 +43,16 @@
43
43
  * @module mask-resolver
44
44
  */
45
45
 
46
- import Decimal from 'decimal.js';
47
- import { Matrix } from './matrix.js';
48
- import * as Transforms2D from './transforms2d.js';
49
- import * as PolygonClip from './polygon-clip.js';
50
- import * as ClipPathResolver from './clip-path-resolver.js';
51
- import * as MeshGradient from './mesh-gradient.js';
46
+ import Decimal from "decimal.js";
47
+ import { Matrix as _Matrix } from "./matrix.js";
48
+ import * as _Transforms2D from "./transforms2d.js";
49
+ import * as PolygonClip from "./polygon-clip.js";
50
+ import * as ClipPathResolver from "./clip-path-resolver.js";
51
+ import * as MeshGradient from "./mesh-gradient.js";
52
52
 
53
53
  Decimal.set({ precision: 80 });
54
54
 
55
- const D = x => (x instanceof Decimal ? x : new Decimal(x));
55
+ const D = (x) => (x instanceof Decimal ? x : new Decimal(x));
56
56
 
57
57
  // Default mask bounds (SVG spec: -10% to 120% in each dimension)
58
58
  const DEFAULT_MASK_X = -0.1;
@@ -84,8 +84,8 @@ const DEFAULT_MASK_HEIGHT = 1.2;
84
84
  * };
85
85
  */
86
86
  export const MaskType = {
87
- LUMINANCE: 'luminance',
88
- ALPHA: 'alpha'
87
+ LUMINANCE: "luminance",
88
+ ALPHA: "alpha",
89
89
  };
90
90
 
91
91
  /**
@@ -132,25 +132,30 @@ export const MaskType = {
132
132
  */
133
133
  export function parseMaskElement(maskElement) {
134
134
  const data = {
135
- id: maskElement.getAttribute('id') || '',
136
- maskUnits: maskElement.getAttribute('maskUnits') || 'objectBoundingBox',
137
- maskContentUnits: maskElement.getAttribute('maskContentUnits') || 'userSpaceOnUse',
138
- maskType: maskElement.getAttribute('mask-type') ||
139
- maskElement.style?.maskType || 'luminance',
140
- x: maskElement.getAttribute('x'),
141
- y: maskElement.getAttribute('y'),
142
- width: maskElement.getAttribute('width'),
143
- height: maskElement.getAttribute('height'),
144
- transform: maskElement.getAttribute('transform') || null,
145
- children: []
135
+ id: maskElement.getAttribute("id") || "",
136
+ maskUnits: maskElement.getAttribute("maskUnits") || "objectBoundingBox",
137
+ maskContentUnits:
138
+ maskElement.getAttribute("maskContentUnits") || "userSpaceOnUse",
139
+ maskType:
140
+ maskElement.getAttribute("mask-type") ||
141
+ maskElement.style?.maskType ||
142
+ "luminance",
143
+ x: maskElement.getAttribute("x"),
144
+ y: maskElement.getAttribute("y"),
145
+ width: maskElement.getAttribute("width"),
146
+ height: maskElement.getAttribute("height"),
147
+ transform: maskElement.getAttribute("transform") || null,
148
+ children: [],
146
149
  };
147
150
 
148
151
  // Set defaults based on maskUnits
149
- if (data.maskUnits === 'objectBoundingBox') {
152
+ if (data.maskUnits === "objectBoundingBox") {
150
153
  data.x = data.x !== null ? parseFloat(data.x) : DEFAULT_MASK_X;
151
154
  data.y = data.y !== null ? parseFloat(data.y) : DEFAULT_MASK_Y;
152
- data.width = data.width !== null ? parseFloat(data.width) : DEFAULT_MASK_WIDTH;
153
- data.height = data.height !== null ? parseFloat(data.height) : DEFAULT_MASK_HEIGHT;
155
+ data.width =
156
+ data.width !== null ? parseFloat(data.width) : DEFAULT_MASK_WIDTH;
157
+ data.height =
158
+ data.height !== null ? parseFloat(data.height) : DEFAULT_MASK_HEIGHT;
154
159
  } else {
155
160
  data.x = data.x !== null ? parseFloat(data.x) : null;
156
161
  data.y = data.y !== null ? parseFloat(data.y) : null;
@@ -163,52 +168,54 @@ export function parseMaskElement(maskElement) {
163
168
  const tagName = child.tagName.toLowerCase();
164
169
  const childData = {
165
170
  type: tagName,
166
- fill: child.getAttribute('fill') || child.style?.fill || 'black',
167
- fillOpacity: parseFloat(child.getAttribute('fill-opacity') ||
168
- child.style?.fillOpacity || '1'),
169
- opacity: parseFloat(child.getAttribute('opacity') ||
170
- child.style?.opacity || '1'),
171
- transform: child.getAttribute('transform') || null
171
+ fill: child.getAttribute("fill") || child.style?.fill || "black",
172
+ fillOpacity: parseFloat(
173
+ child.getAttribute("fill-opacity") || child.style?.fillOpacity || "1",
174
+ ),
175
+ opacity: parseFloat(
176
+ child.getAttribute("opacity") || child.style?.opacity || "1",
177
+ ),
178
+ transform: child.getAttribute("transform") || null,
172
179
  };
173
180
 
174
181
  // Parse shape-specific attributes
175
182
  switch (tagName) {
176
- case 'rect':
177
- childData.x = parseFloat(child.getAttribute('x') || '0');
178
- childData.y = parseFloat(child.getAttribute('y') || '0');
179
- childData.width = parseFloat(child.getAttribute('width') || '0');
180
- childData.height = parseFloat(child.getAttribute('height') || '0');
181
- childData.rx = parseFloat(child.getAttribute('rx') || '0');
182
- childData.ry = parseFloat(child.getAttribute('ry') || '0');
183
+ case "rect":
184
+ childData.x = parseFloat(child.getAttribute("x") || "0");
185
+ childData.y = parseFloat(child.getAttribute("y") || "0");
186
+ childData.width = parseFloat(child.getAttribute("width") || "0");
187
+ childData.height = parseFloat(child.getAttribute("height") || "0");
188
+ childData.rx = parseFloat(child.getAttribute("rx") || "0");
189
+ childData.ry = parseFloat(child.getAttribute("ry") || "0");
183
190
  break;
184
- case 'circle':
185
- childData.cx = parseFloat(child.getAttribute('cx') || '0');
186
- childData.cy = parseFloat(child.getAttribute('cy') || '0');
187
- childData.r = parseFloat(child.getAttribute('r') || '0');
191
+ case "circle":
192
+ childData.cx = parseFloat(child.getAttribute("cx") || "0");
193
+ childData.cy = parseFloat(child.getAttribute("cy") || "0");
194
+ childData.r = parseFloat(child.getAttribute("r") || "0");
188
195
  break;
189
- case 'ellipse':
190
- childData.cx = parseFloat(child.getAttribute('cx') || '0');
191
- childData.cy = parseFloat(child.getAttribute('cy') || '0');
192
- childData.rx = parseFloat(child.getAttribute('rx') || '0');
193
- childData.ry = parseFloat(child.getAttribute('ry') || '0');
196
+ case "ellipse":
197
+ childData.cx = parseFloat(child.getAttribute("cx") || "0");
198
+ childData.cy = parseFloat(child.getAttribute("cy") || "0");
199
+ childData.rx = parseFloat(child.getAttribute("rx") || "0");
200
+ childData.ry = parseFloat(child.getAttribute("ry") || "0");
194
201
  break;
195
- case 'path':
196
- childData.d = child.getAttribute('d') || '';
202
+ case "path":
203
+ childData.d = child.getAttribute("d") || "";
197
204
  break;
198
- case 'polygon':
199
- childData.points = child.getAttribute('points') || '';
205
+ case "polygon":
206
+ childData.points = child.getAttribute("points") || "";
200
207
  break;
201
- case 'polyline':
202
- childData.points = child.getAttribute('points') || '';
208
+ case "polyline":
209
+ childData.points = child.getAttribute("points") || "";
203
210
  break;
204
- case 'g':
211
+ case "g":
205
212
  // Recursively parse group children
206
213
  childData.children = [];
207
214
  for (const gc of child.children) {
208
215
  // Simplified - just store the tag and basic info
209
216
  childData.children.push({
210
217
  type: gc.tagName.toLowerCase(),
211
- fill: gc.getAttribute('fill') || 'inherit'
218
+ fill: gc.getAttribute("fill") || "inherit",
212
219
  });
213
220
  }
214
221
  break;
@@ -266,22 +273,34 @@ export function parseMaskElement(maskElement) {
266
273
  * // region.y = 50 (absolute)
267
274
  */
268
275
  export function getMaskRegion(maskData, targetBBox) {
269
- if (maskData.maskUnits === 'objectBoundingBox') {
276
+ if (maskData.maskUnits === "objectBoundingBox") {
270
277
  // Coordinates are relative to target bounding box
271
278
  return {
272
279
  x: D(targetBBox.x).plus(D(maskData.x).mul(targetBBox.width)),
273
280
  y: D(targetBBox.y).plus(D(maskData.y).mul(targetBBox.height)),
274
281
  width: D(maskData.width).mul(targetBBox.width),
275
- height: D(maskData.height).mul(targetBBox.height)
282
+ height: D(maskData.height).mul(targetBBox.height),
276
283
  };
277
284
  }
278
285
 
279
286
  // userSpaceOnUse - use values directly (or defaults if null)
280
287
  return {
281
- x: maskData.x !== null ? D(maskData.x) : D(targetBBox.x).minus(D(targetBBox.width).mul(0.1)),
282
- y: maskData.y !== null ? D(maskData.y) : D(targetBBox.y).minus(D(targetBBox.height).mul(0.1)),
283
- width: maskData.width !== null ? D(maskData.width) : D(targetBBox.width).mul(1.2),
284
- height: maskData.height !== null ? D(maskData.height) : D(targetBBox.height).mul(1.2)
288
+ x:
289
+ maskData.x !== null
290
+ ? D(maskData.x)
291
+ : D(targetBBox.x).minus(D(targetBBox.width).mul(0.1)),
292
+ y:
293
+ maskData.y !== null
294
+ ? D(maskData.y)
295
+ : D(targetBBox.y).minus(D(targetBBox.height).mul(0.1)),
296
+ width:
297
+ maskData.width !== null
298
+ ? D(maskData.width)
299
+ : D(targetBBox.width).mul(1.2),
300
+ height:
301
+ maskData.height !== null
302
+ ? D(maskData.height)
303
+ : D(targetBBox.height).mul(1.2),
285
304
  };
286
305
  }
287
306
 
@@ -315,22 +334,27 @@ export function getMaskRegion(maskData, targetBBox) {
315
334
  * const polygon = maskChildToPolygon(child, bbox, 'userSpaceOnUse', 32);
316
335
  * // Result: 32-sided polygon approximating the circle
317
336
  */
318
- export function maskChildToPolygon(child, targetBBox, contentUnits, samples = 20) {
337
+ export function maskChildToPolygon(
338
+ child,
339
+ targetBBox,
340
+ contentUnits,
341
+ samples = 20,
342
+ ) {
319
343
  // Create element-like object for ClipPathResolver
320
344
  const element = {
321
345
  type: child.type,
322
346
  ...child,
323
- transform: child.transform
347
+ transform: child.transform,
324
348
  };
325
349
 
326
350
  // Get polygon using ClipPathResolver
327
351
  let polygon = ClipPathResolver.shapeToPolygon(element, null, samples);
328
352
 
329
353
  // Apply objectBoundingBox scaling if needed
330
- if (contentUnits === 'objectBoundingBox' && polygon.length > 0) {
331
- polygon = polygon.map(p => ({
354
+ if (contentUnits === "objectBoundingBox" && polygon.length > 0) {
355
+ polygon = polygon.map((p) => ({
332
356
  x: D(targetBBox.x).plus(p.x.mul(targetBBox.width)),
333
- y: D(targetBBox.y).plus(p.y.mul(targetBBox.height))
357
+ y: D(targetBBox.y).plus(p.y.mul(targetBBox.height)),
334
358
  }));
335
359
  }
336
360
 
@@ -384,16 +408,16 @@ export function maskChildToPolygon(child, targetBBox, contentUnits, samples = 20
384
408
  * const effectiveOpacity = luminance * maskChild.opacity; // 0.5 * 0.8 = 0.4
385
409
  */
386
410
  export function colorToLuminance(colorStr) {
387
- if (!colorStr || colorStr === 'none' || colorStr === 'transparent') {
411
+ if (!colorStr || colorStr === "none" || colorStr === "transparent") {
388
412
  return 0;
389
413
  }
390
414
 
391
415
  // Parse RGB values
392
416
  const rgbMatch = colorStr.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i);
393
417
  if (rgbMatch) {
394
- const r = parseInt(rgbMatch[1]) / 255;
395
- const g = parseInt(rgbMatch[2]) / 255;
396
- const b = parseInt(rgbMatch[3]) / 255;
418
+ const r = parseInt(rgbMatch[1], 10) / 255;
419
+ const g = parseInt(rgbMatch[2], 10) / 255;
420
+ const b = parseInt(rgbMatch[3], 10) / 255;
397
421
  return 0.2126 * r + 0.7152 * g + 0.0722 * b;
398
422
  }
399
423
 
@@ -421,7 +445,7 @@ export function colorToLuminance(colorStr) {
421
445
  cyan: 0.7874,
422
446
  magenta: 0.2848,
423
447
  gray: 0.5,
424
- grey: 0.5
448
+ grey: 0.5,
425
449
  };
426
450
 
427
451
  const lower = colorStr.toLowerCase();
@@ -539,7 +563,7 @@ export function resolveMask(maskData, targetBBox, options = {}) {
539
563
  child,
540
564
  targetBBox,
541
565
  maskData.maskContentUnits,
542
- samples
566
+ samples,
543
567
  );
544
568
 
545
569
  if (polygon.length >= 3) {
@@ -612,7 +636,10 @@ export function applyMask(targetPolygon, maskData, targetBBox, options = {}) {
612
636
  for (const { polygon: maskPoly, opacity } of maskRegions) {
613
637
  if (opacity <= 0) continue;
614
638
 
615
- const intersection = PolygonClip.polygonIntersection(targetPolygon, maskPoly);
639
+ const intersection = PolygonClip.polygonIntersection(
640
+ targetPolygon,
641
+ maskPoly,
642
+ );
616
643
 
617
644
  for (const clippedPoly of intersection) {
618
645
  if (clippedPoly.length >= 3) {
@@ -672,7 +699,12 @@ export function applyMask(targetPolygon, maskData, targetBBox, options = {}) {
672
699
  * `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`
673
700
  * ).join(' ') + ' Z';
674
701
  */
675
- export function maskToClipPath(maskData, targetBBox, opacityThreshold = 0.5, options = {}) {
702
+ export function maskToClipPath(
703
+ maskData,
704
+ targetBBox,
705
+ opacityThreshold = 0.5,
706
+ options = {},
707
+ ) {
676
708
  const maskRegions = resolveMask(maskData, targetBBox, options);
677
709
 
678
710
  // Union all regions above threshold
@@ -737,16 +769,16 @@ export function maskToClipPath(maskData, targetBBox, opacityThreshold = 0.5, opt
737
769
  export function maskToPathData(maskData, targetBBox, options = {}) {
738
770
  const polygon = maskToClipPath(maskData, targetBBox, 0.5, options);
739
771
 
740
- if (polygon.length < 3) return '';
772
+ if (polygon.length < 3) return "";
741
773
 
742
- let d = '';
774
+ let d = "";
743
775
  for (let i = 0; i < polygon.length; i++) {
744
776
  const p = polygon[i];
745
777
  const x = Number(p.x).toFixed(6);
746
778
  const y = Number(p.y).toFixed(6);
747
779
  d += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;
748
780
  }
749
- d += ' Z';
781
+ d += " Z";
750
782
 
751
783
  return d;
752
784
  }
@@ -786,7 +818,7 @@ export function maskToPathData(maskData, targetBBox, options = {}) {
786
818
  * }
787
819
  */
788
820
  export function parseGradientReference(fill) {
789
- if (!fill || typeof fill !== 'string') return null;
821
+ if (!fill || typeof fill !== "string") return null;
790
822
 
791
823
  const match = fill.match(/url\s*\(\s*#([^)\s]+)\s*\)/i);
792
824
  return match ? match[1] : null;
@@ -883,12 +915,19 @@ export function rgbToLuminance(color) {
883
915
  * console.log(`Region with ${polygon.length} vertices, opacity: ${opacity.toFixed(2)}`);
884
916
  * });
885
917
  */
886
- export function sampleMeshGradientForMask(meshData, shapeBBox, maskType = 'luminance', options = {}) {
918
+ export function sampleMeshGradientForMask(
919
+ meshData,
920
+ shapeBBox,
921
+ maskType = "luminance",
922
+ options = {},
923
+ ) {
887
924
  const { subdivisions = 4 } = options;
888
925
  const result = [];
889
926
 
890
927
  // Get mesh gradient polygons with colors
891
- const meshPolygons = MeshGradient.meshGradientToPolygons(meshData, { subdivisions });
928
+ const meshPolygons = MeshGradient.meshGradientToPolygons(meshData, {
929
+ subdivisions,
930
+ });
892
931
 
893
932
  for (const { polygon, color } of meshPolygons) {
894
933
  if (polygon.length < 3) continue;
@@ -955,14 +994,28 @@ export function sampleMeshGradientForMask(meshData, shapeBBox, maskType = 'lumin
955
994
  * renderPolygon(polygon, { fillOpacity: opacity });
956
995
  * });
957
996
  */
958
- export function applyMeshGradientMask(targetPolygon, meshData, targetBBox, maskType = 'luminance', options = {}) {
959
- const meshMaskRegions = sampleMeshGradientForMask(meshData, targetBBox, maskType, options);
997
+ export function applyMeshGradientMask(
998
+ targetPolygon,
999
+ meshData,
1000
+ targetBBox,
1001
+ maskType = "luminance",
1002
+ options = {},
1003
+ ) {
1004
+ const meshMaskRegions = sampleMeshGradientForMask(
1005
+ meshData,
1006
+ targetBBox,
1007
+ maskType,
1008
+ options,
1009
+ );
960
1010
  const result = [];
961
1011
 
962
1012
  for (const { polygon: maskPoly, opacity } of meshMaskRegions) {
963
1013
  if (opacity <= 0) continue;
964
1014
 
965
- const intersection = PolygonClip.polygonIntersection(targetPolygon, maskPoly);
1015
+ const intersection = PolygonClip.polygonIntersection(
1016
+ targetPolygon,
1017
+ maskPoly,
1018
+ );
966
1019
 
967
1020
  for (const clippedPoly of intersection) {
968
1021
  if (clippedPoly.length >= 3) {
@@ -1038,7 +1091,12 @@ export function applyMeshGradientMask(targetPolygon, meshData, targetBBox, maskT
1038
1091
  * // Each polygon is a piece of the gradient, clipped by the mask child shape
1039
1092
  * });
1040
1093
  */
1041
- export function resolveMaskWithGradients(maskData, targetBBox, gradientDefs = {}, options = {}) {
1094
+ export function resolveMaskWithGradients(
1095
+ maskData,
1096
+ targetBBox,
1097
+ gradientDefs = {},
1098
+ options = {},
1099
+ ) {
1042
1100
  const { samples = 20, subdivisions = 4 } = options;
1043
1101
  const maskType = maskData.maskType || MaskType.LUMINANCE;
1044
1102
  const result = [];
@@ -1055,29 +1113,36 @@ export function resolveMaskWithGradients(maskData, targetBBox, gradientDefs = {}
1055
1113
  child,
1056
1114
  targetBBox,
1057
1115
  maskData.maskContentUnits,
1058
- samples
1116
+ samples,
1059
1117
  );
1060
1118
 
1061
1119
  if (shapePolygon.length < 3) continue;
1062
1120
 
1063
1121
  // Check if it's a mesh gradient
1064
- if (gradientData.type === 'meshgradient' || gradientData.patches) {
1122
+ if (gradientData.type === "meshgradient" || gradientData.patches) {
1065
1123
  // Sample mesh gradient within the shape
1066
1124
  const meshMaskRegions = sampleMeshGradientForMask(
1067
1125
  gradientData,
1068
1126
  targetBBox,
1069
1127
  maskType,
1070
- { subdivisions }
1128
+ { subdivisions },
1071
1129
  );
1072
1130
 
1073
1131
  // Clip mesh regions to the shape
1074
- for (const { polygon: meshPoly, opacity: meshOpacity } of meshMaskRegions) {
1075
- const clipped = PolygonClip.polygonIntersection(shapePolygon, meshPoly);
1132
+ for (const {
1133
+ polygon: meshPoly,
1134
+ opacity: meshOpacity,
1135
+ } of meshMaskRegions) {
1136
+ const clipped = PolygonClip.polygonIntersection(
1137
+ shapePolygon,
1138
+ meshPoly,
1139
+ );
1076
1140
 
1077
1141
  for (const clippedPoly of clipped) {
1078
1142
  if (clippedPoly.length >= 3) {
1079
1143
  // Combine mesh opacity with child opacity
1080
- const combinedOpacity = meshOpacity * (child.opacity || 1) * (child.fillOpacity || 1);
1144
+ const combinedOpacity =
1145
+ meshOpacity * (child.opacity || 1) * (child.fillOpacity || 1);
1081
1146
  if (combinedOpacity > 0) {
1082
1147
  result.push({ polygon: clippedPoly, opacity: combinedOpacity });
1083
1148
  }
@@ -1092,7 +1157,7 @@ export function resolveMaskWithGradients(maskData, targetBBox, gradientDefs = {}
1092
1157
  child,
1093
1158
  targetBBox,
1094
1159
  maskData.maskContentUnits,
1095
- samples
1160
+ samples,
1096
1161
  );
1097
1162
 
1098
1163
  if (polygon.length >= 3) {
@@ -1158,14 +1223,24 @@ export function resolveMaskWithGradients(maskData, targetBBox, gradientDefs = {}
1158
1223
  * // Apply region to rendering pipeline
1159
1224
  * });
1160
1225
  */
1161
- export function createMeshGradientMask(meshData, bounds, maskType = 'luminance', options = {}) {
1162
- const regions = sampleMeshGradientForMask(meshData, bounds, maskType, options);
1226
+ export function createMeshGradientMask(
1227
+ meshData,
1228
+ bounds,
1229
+ maskType = "luminance",
1230
+ options = {},
1231
+ ) {
1232
+ const regions = sampleMeshGradientForMask(
1233
+ meshData,
1234
+ bounds,
1235
+ maskType,
1236
+ options,
1237
+ );
1163
1238
 
1164
1239
  return {
1165
- type: 'meshGradientMask',
1240
+ type: "meshGradientMask",
1166
1241
  bounds,
1167
1242
  maskType,
1168
- regions
1243
+ regions,
1169
1244
  };
1170
1245
  }
1171
1246
 
@@ -1237,7 +1312,10 @@ export function getMeshGradientBoundary(meshData, options = {}) {
1237
1312
  allPoints.push(...rightPoints);
1238
1313
  }
1239
1314
  if (patch.bottom) {
1240
- const bottomPoints = MeshGradient.sampleBezierCurve(patch.bottom, samples);
1315
+ const bottomPoints = MeshGradient.sampleBezierCurve(
1316
+ patch.bottom,
1317
+ samples,
1318
+ );
1241
1319
  allPoints.push(...bottomPoints);
1242
1320
  }
1243
1321
  if (patch.left) {
@@ -1311,11 +1389,17 @@ export function getMeshGradientBoundary(meshData, options = {}) {
1311
1389
  * const clipped = clipWithMeshGradientShape(targetPolygon, meshData, { subdivisions: 6 });
1312
1390
  * // All patches unioned into one shape before clipping
1313
1391
  */
1314
- export function clipWithMeshGradientShape(targetPolygon, meshData, options = {}) {
1392
+ export function clipWithMeshGradientShape(
1393
+ targetPolygon,
1394
+ meshData,
1395
+ options = {},
1396
+ ) {
1315
1397
  const { subdivisions = 4 } = options;
1316
1398
 
1317
1399
  // Get all patch polygons (ignoring colors)
1318
- const meshPolygons = MeshGradient.meshGradientToPolygons(meshData, { subdivisions });
1400
+ const meshPolygons = MeshGradient.meshGradientToPolygons(meshData, {
1401
+ subdivisions,
1402
+ });
1319
1403
 
1320
1404
  if (meshPolygons.length === 0) {
1321
1405
  return [];
@@ -1325,7 +1409,10 @@ export function clipWithMeshGradientShape(targetPolygon, meshData, options = {})
1325
1409
  let meshShape = meshPolygons[0].polygon;
1326
1410
 
1327
1411
  for (let i = 1; i < meshPolygons.length; i++) {
1328
- const unionResult = PolygonClip.polygonUnion(meshShape, meshPolygons[i].polygon);
1412
+ const unionResult = PolygonClip.polygonUnion(
1413
+ meshShape,
1414
+ meshPolygons[i].polygon,
1415
+ );
1329
1416
  if (unionResult.length > 0 && unionResult[0].length >= 3) {
1330
1417
  meshShape = unionResult[0];
1331
1418
  }
@@ -1384,7 +1471,9 @@ export function clipWithMeshGradientShape(targetPolygon, meshData, options = {})
1384
1471
  export function meshGradientToClipPath(meshData, options = {}) {
1385
1472
  const { subdivisions = 4 } = options;
1386
1473
 
1387
- const meshPolygons = MeshGradient.meshGradientToPolygons(meshData, { subdivisions });
1474
+ const meshPolygons = MeshGradient.meshGradientToPolygons(meshData, {
1475
+ subdivisions,
1476
+ });
1388
1477
 
1389
1478
  if (meshPolygons.length === 0) {
1390
1479
  return [];
@@ -1405,3 +1494,25 @@ export function meshGradientToClipPath(meshData, options = {}) {
1405
1494
 
1406
1495
  return result;
1407
1496
  }
1497
+
1498
+ export default {
1499
+ MaskType,
1500
+ parseMaskElement,
1501
+ getMaskRegion,
1502
+ maskChildToPolygon,
1503
+ colorToLuminance,
1504
+ getMaskChildOpacity,
1505
+ resolveMask,
1506
+ applyMask,
1507
+ maskToClipPath,
1508
+ maskToPathData,
1509
+ parseGradientReference,
1510
+ rgbToLuminance,
1511
+ sampleMeshGradientForMask,
1512
+ applyMeshGradientMask,
1513
+ resolveMaskWithGradients,
1514
+ createMeshGradientMask,
1515
+ getMeshGradientBoundary,
1516
+ clipWithMeshGradientShape,
1517
+ meshGradientToClipPath,
1518
+ };