@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
@@ -7,14 +7,14 @@
7
7
  * @module mesh-gradient
8
8
  */
9
9
 
10
- import Decimal from 'decimal.js';
11
- import { Matrix } from './matrix.js';
12
- import * as Transforms2D from './transforms2d.js';
13
- import * as PolygonClip from './polygon-clip.js';
10
+ import Decimal from "decimal.js";
11
+ import { Matrix as _Matrix } from "./matrix.js";
12
+ import * as _Transforms2D from "./transforms2d.js";
13
+ import * as PolygonClip from "./polygon-clip.js";
14
14
 
15
15
  Decimal.set({ precision: 80 });
16
16
 
17
- const D = x => (x instanceof Decimal ? x : new Decimal(x));
17
+ const D = (x) => (x instanceof Decimal ? x : new Decimal(x));
18
18
 
19
19
  // Default samples per patch edge for rasterization
20
20
  const DEFAULT_PATCH_SAMPLES = 16;
@@ -66,7 +66,12 @@ export function point(x, y) {
66
66
  * const blue = color(0, 0, 255, 128);
67
67
  */
68
68
  export function color(r, g, b, a = 255) {
69
- return { r: Math.round(r), g: Math.round(g), b: Math.round(b), a: Math.round(a) };
69
+ return {
70
+ r: Math.round(r),
71
+ g: Math.round(g),
72
+ b: Math.round(b),
73
+ a: Math.round(a),
74
+ };
70
75
  }
71
76
 
72
77
  /**
@@ -103,14 +108,16 @@ export function parseColor(colorStr, opacity = 1) {
103
108
  if (!colorStr) return color(0, 0, 0, 255);
104
109
 
105
110
  // Handle rgb() and rgba()
106
- const rgbMatch = colorStr.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/i);
111
+ const rgbMatch = colorStr.match(
112
+ /rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/i,
113
+ );
107
114
  if (rgbMatch) {
108
115
  const a = rgbMatch[4] !== undefined ? parseFloat(rgbMatch[4]) * 255 : 255;
109
116
  return color(
110
- parseInt(rgbMatch[1]),
111
- parseInt(rgbMatch[2]),
112
- parseInt(rgbMatch[3]),
113
- a * opacity
117
+ parseInt(rgbMatch[1], 10),
118
+ parseInt(rgbMatch[2], 10),
119
+ parseInt(rgbMatch[3], 10),
120
+ a * opacity,
114
121
  );
115
122
  }
116
123
 
@@ -123,30 +130,36 @@ export function parseColor(colorStr, opacity = 1) {
123
130
  parseInt(hex[0] + hex[0], 16),
124
131
  parseInt(hex[1] + hex[1], 16),
125
132
  parseInt(hex[2] + hex[2], 16),
126
- 255 * opacity
133
+ 255 * opacity,
127
134
  );
128
135
  } else if (hex.length === 6) {
129
136
  return color(
130
137
  parseInt(hex.slice(0, 2), 16),
131
138
  parseInt(hex.slice(2, 4), 16),
132
139
  parseInt(hex.slice(4, 6), 16),
133
- 255 * opacity
140
+ 255 * opacity,
134
141
  );
135
142
  } else if (hex.length === 8) {
136
143
  return color(
137
144
  parseInt(hex.slice(0, 2), 16),
138
145
  parseInt(hex.slice(2, 4), 16),
139
146
  parseInt(hex.slice(4, 6), 16),
140
- parseInt(hex.slice(6, 8), 16) * opacity
147
+ parseInt(hex.slice(6, 8), 16) * opacity,
141
148
  );
142
149
  }
143
150
  }
144
151
 
145
152
  // Named colors (subset for common ones)
146
153
  const namedColors = {
147
- black: [0, 0, 0], white: [255, 255, 255], red: [255, 0, 0],
148
- green: [0, 128, 0], blue: [0, 0, 255], yellow: [255, 255, 0],
149
- cyan: [0, 255, 255], magenta: [255, 0, 255], transparent: [0, 0, 0, 0]
154
+ black: [0, 0, 0],
155
+ white: [255, 255, 255],
156
+ red: [255, 0, 0],
157
+ green: [0, 128, 0],
158
+ blue: [0, 0, 255],
159
+ yellow: [255, 255, 0],
160
+ cyan: [0, 255, 255],
161
+ magenta: [255, 0, 255],
162
+ transparent: [0, 0, 0, 0],
150
163
  };
151
164
  const named = namedColors[colorStr.toLowerCase()];
152
165
  if (named) {
@@ -192,7 +205,7 @@ export function lerpColor(c1, c2, t) {
192
205
  c1.r * mt + c2.r * tNum,
193
206
  c1.g * mt + c2.g * tNum,
194
207
  c1.b * mt + c2.b * tNum,
195
- c1.a * mt + c2.a * tNum
208
+ c1.a * mt + c2.a * tNum,
196
209
  );
197
210
  }
198
211
 
@@ -231,10 +244,22 @@ export function bilinearColor(c00, c10, c01, c11, u, v) {
231
244
  const mv = 1 - vNum;
232
245
 
233
246
  return color(
234
- mu * mv * c00.r + uNum * mv * c10.r + mu * vNum * c01.r + uNum * vNum * c11.r,
235
- mu * mv * c00.g + uNum * mv * c10.g + mu * vNum * c01.g + uNum * vNum * c11.g,
236
- mu * mv * c00.b + uNum * mv * c10.b + mu * vNum * c01.b + uNum * vNum * c11.b,
237
- mu * mv * c00.a + uNum * mv * c10.a + mu * vNum * c01.a + uNum * vNum * c11.a
247
+ mu * mv * c00.r +
248
+ uNum * mv * c10.r +
249
+ mu * vNum * c01.r +
250
+ uNum * vNum * c11.r,
251
+ mu * mv * c00.g +
252
+ uNum * mv * c10.g +
253
+ mu * vNum * c01.g +
254
+ uNum * vNum * c11.g,
255
+ mu * mv * c00.b +
256
+ uNum * mv * c10.b +
257
+ mu * vNum * c01.b +
258
+ uNum * vNum * c11.b,
259
+ mu * mv * c00.a +
260
+ uNum * mv * c10.a +
261
+ mu * vNum * c01.a +
262
+ uNum * vNum * c11.a,
238
263
  );
239
264
  }
240
265
 
@@ -284,10 +309,16 @@ export function evalCubicBezier(p0, p1, p2, p3, t) {
284
309
  const t3 = t2.mul(t);
285
310
 
286
311
  return {
287
- x: mt3.mul(p0.x).plus(D(3).mul(mt2).mul(t).mul(p1.x))
288
- .plus(D(3).mul(mt).mul(t2).mul(p2.x)).plus(t3.mul(p3.x)),
289
- y: mt3.mul(p0.y).plus(D(3).mul(mt2).mul(t).mul(p1.y))
290
- .plus(D(3).mul(mt).mul(t2).mul(p2.y)).plus(t3.mul(p3.y))
312
+ x: mt3
313
+ .mul(p0.x)
314
+ .plus(D(3).mul(mt2).mul(t).mul(p1.x))
315
+ .plus(D(3).mul(mt).mul(t2).mul(p2.x))
316
+ .plus(t3.mul(p3.x)),
317
+ y: mt3
318
+ .mul(p0.y)
319
+ .plus(D(3).mul(mt2).mul(t).mul(p1.y))
320
+ .plus(D(3).mul(mt).mul(t2).mul(p2.y))
321
+ .plus(t3.mul(p3.y)),
291
322
  };
292
323
  }
293
324
 
@@ -332,7 +363,7 @@ export function splitBezier(curve) {
332
363
  // De Casteljau subdivision at t=0.5
333
364
  const mid = (a, b) => ({
334
365
  x: a.x.plus(b.x).div(2),
335
- y: a.y.plus(b.y).div(2)
366
+ y: a.y.plus(b.y).div(2),
336
367
  });
337
368
 
338
369
  const q0 = p0;
@@ -345,7 +376,10 @@ export function splitBezier(curve) {
345
376
  const r2 = mid(p2, p3);
346
377
  const r3 = p3;
347
378
 
348
- return [[q0, q1, q2, q3], [r0, r1, r2, r3]];
379
+ return [
380
+ [q0, q1, q2, q3],
381
+ [r0, r1, r2, r3],
382
+ ];
349
383
  }
350
384
 
351
385
  // ============================================================================
@@ -449,10 +483,10 @@ export class CoonsPatch {
449
483
  */
450
484
  evaluate(u, v) {
451
485
  // Boundary curves
452
- const Lc = evalCubicBezier(...this.top, u); // L_c(u,0)
453
- const Ld = evalCubicBezier(...this.bottom, u); // L_d(u,1)
454
- const La = evalCubicBezier(...this.left, v); // L_a(0,v)
455
- const Lb = evalCubicBezier(...this.right, v); // L_b(1,v)
486
+ const Lc = evalCubicBezier(...this.top, u); // L_c(u,0)
487
+ const Ld = evalCubicBezier(...this.bottom, u); // L_d(u,1)
488
+ const La = evalCubicBezier(...this.left, v); // L_a(0,v)
489
+ const Lb = evalCubicBezier(...this.right, v); // L_b(1,v)
456
490
 
457
491
  // Corner points
458
492
  const P00 = this.top[0];
@@ -474,11 +508,15 @@ export class CoonsPatch {
474
508
  const Sd_y = mu.mul(La.y).plus(u.mul(Lb.y));
475
509
 
476
510
  // Bilinear interpolation of corners
477
- const B_x = mu.mul(mv).mul(P00.x)
511
+ const B_x = mu
512
+ .mul(mv)
513
+ .mul(P00.x)
478
514
  .plus(u.mul(mv).mul(P10.x))
479
515
  .plus(mu.mul(v).mul(P01.x))
480
516
  .plus(u.mul(v).mul(P11.x));
481
- const B_y = mu.mul(mv).mul(P00.y)
517
+ const B_y = mu
518
+ .mul(mv)
519
+ .mul(P00.y)
482
520
  .plus(u.mul(mv).mul(P10.y))
483
521
  .plus(mu.mul(v).mul(P01.y))
484
522
  .plus(u.mul(v).mul(P11.y));
@@ -486,14 +524,17 @@ export class CoonsPatch {
486
524
  // Coons formula: Sc + Sd - B
487
525
  const pt = {
488
526
  x: Sc_x.plus(Sd_x).minus(B_x),
489
- y: Sc_y.plus(Sd_y).minus(B_y)
527
+ y: Sc_y.plus(Sd_y).minus(B_y),
490
528
  };
491
529
 
492
530
  // Color interpolation (bilinear)
493
531
  const col = bilinearColor(
494
- this.colors[0][0], this.colors[0][1],
495
- this.colors[1][0], this.colors[1][1],
496
- u, v
532
+ this.colors[0][0],
533
+ this.colors[0][1],
534
+ this.colors[1][0],
535
+ this.colors[1][1],
536
+ u,
537
+ v,
497
538
  );
498
539
 
499
540
  return { point: pt, color: col };
@@ -550,7 +591,12 @@ export class CoonsPatch {
550
591
  const midH = [midLeft.point, midLeft.point, center.point, center.point];
551
592
  const midH2 = [center.point, center.point, midRight.point, midRight.point];
552
593
  const midV = [midTop.point, midTop.point, center.point, center.point];
553
- const midV2 = [center.point, center.point, midBottom.point, midBottom.point];
594
+ const midV2 = [
595
+ center.point,
596
+ center.point,
597
+ midBottom.point,
598
+ midBottom.point,
599
+ ];
554
600
 
555
601
  // Colors at subdivided corners
556
602
  const c00 = this.colors[0][0];
@@ -565,13 +611,25 @@ export class CoonsPatch {
565
611
 
566
612
  return [
567
613
  // Top-left
568
- new CoonsPatch(topL, midV, midH, leftT, [[c00, cTop], [cLeft, cMid]]),
614
+ new CoonsPatch(topL, midV, midH, leftT, [
615
+ [c00, cTop],
616
+ [cLeft, cMid],
617
+ ]),
569
618
  // Top-right
570
- new CoonsPatch(topR, rightT, midH2, midV, [[cTop, c10], [cMid, cRight]]),
619
+ new CoonsPatch(topR, rightT, midH2, midV, [
620
+ [cTop, c10],
621
+ [cMid, cRight],
622
+ ]),
571
623
  // Bottom-left
572
- new CoonsPatch(midH, midV2, bottomL, leftB, [[cLeft, cMid], [c01, cBottom]]),
624
+ new CoonsPatch(midH, midV2, bottomL, leftB, [
625
+ [cLeft, cMid],
626
+ [c01, cBottom],
627
+ ]),
573
628
  // Bottom-right
574
- new CoonsPatch(midH2, rightB, bottomR, midV2, [[cMid, cRight], [cBottom, c11]])
629
+ new CoonsPatch(midH2, rightB, bottomR, midV2, [
630
+ [cMid, cRight],
631
+ [cBottom, c11],
632
+ ]),
575
633
  ];
576
634
  }
577
635
 
@@ -614,15 +672,27 @@ export class CoonsPatch {
614
672
  const len2 = dx.mul(dx).plus(dy.mul(dy));
615
673
  if (len2.lt(1e-10)) return true;
616
674
 
617
- const dist1 = dx.mul(p1.y.minus(p0.y)).minus(dy.mul(p1.x.minus(p0.x))).abs();
618
- const dist2 = dx.mul(p2.y.minus(p0.y)).minus(dy.mul(p2.x.minus(p0.x))).abs();
619
-
620
- return dist1.div(len2.sqrt()).lt(SUBDIVISION_THRESHOLD) &&
621
- dist2.div(len2.sqrt()).lt(SUBDIVISION_THRESHOLD);
675
+ const dist1 = dx
676
+ .mul(p1.y.minus(p0.y))
677
+ .minus(dy.mul(p1.x.minus(p0.x)))
678
+ .abs();
679
+ const dist2 = dx
680
+ .mul(p2.y.minus(p0.y))
681
+ .minus(dy.mul(p2.x.minus(p0.x)))
682
+ .abs();
683
+
684
+ return (
685
+ dist1.div(len2.sqrt()).lt(SUBDIVISION_THRESHOLD) &&
686
+ dist2.div(len2.sqrt()).lt(SUBDIVISION_THRESHOLD)
687
+ );
622
688
  };
623
689
 
624
- return curveFlat(this.top) && curveFlat(this.right) &&
625
- curveFlat(this.bottom) && curveFlat(this.left);
690
+ return (
691
+ curveFlat(this.top) &&
692
+ curveFlat(this.right) &&
693
+ curveFlat(this.bottom) &&
694
+ curveFlat(this.left)
695
+ );
626
696
  }
627
697
 
628
698
  /**
@@ -647,9 +717,16 @@ export class CoonsPatch {
647
717
  * bbox.maxY >= 0 && bbox.minY <= viewportHeight;
648
718
  */
649
719
  getBBox() {
650
- const allPoints = [...this.top, ...this.right, ...this.bottom, ...this.left];
651
- let minX = allPoints[0].x, maxX = allPoints[0].x;
652
- let minY = allPoints[0].y, maxY = allPoints[0].y;
720
+ const allPoints = [
721
+ ...this.top,
722
+ ...this.right,
723
+ ...this.bottom,
724
+ ...this.left,
725
+ ];
726
+ let minX = allPoints[0].x,
727
+ maxX = allPoints[0].x;
728
+ let minY = allPoints[0].y,
729
+ maxY = allPoints[0].y;
653
730
 
654
731
  for (const p of allPoints) {
655
732
  if (p.x.lt(minX)) minX = p.x;
@@ -722,8 +799,8 @@ export class CoonsPatch {
722
799
  export function parseMeshGradient(meshGradientDef) {
723
800
  const x = D(meshGradientDef.x || 0);
724
801
  const y = D(meshGradientDef.y || 0);
725
- const type = meshGradientDef.type || 'bilinear';
726
- const gradientUnits = meshGradientDef.gradientUnits || 'userSpaceOnUse';
802
+ const type = meshGradientDef.type || "bilinear";
803
+ const gradientUnits = meshGradientDef.gradientUnits || "userSpaceOnUse";
727
804
  const gradientTransform = meshGradientDef.gradientTransform || null;
728
805
 
729
806
  const patches = [];
@@ -734,8 +811,8 @@ export function parseMeshGradient(meshGradientDef) {
734
811
  const nodes = [[point(x, y)]];
735
812
  const colors = [[]];
736
813
 
737
- let currentX = x;
738
- let currentY = y;
814
+ const _currentX = x;
815
+ const _currentY = y;
739
816
 
740
817
  for (let rowIdx = 0; rowIdx < meshRows.length; rowIdx++) {
741
818
  const row = meshRows[rowIdx];
@@ -753,23 +830,28 @@ export function parseMeshGradient(meshGradientDef) {
753
830
  // Each patch has up to 4 stops defining edges
754
831
  for (let stopIdx = 0; stopIdx < stops.length; stopIdx++) {
755
832
  const stop = stops[stopIdx];
756
- const pathData = stop.path || '';
757
- const stopColor = stop.color ? parseColor(stop.color, stop.opacity || 1) : null;
833
+ const pathData = stop.path || "";
834
+ const stopColor = stop.color
835
+ ? parseColor(stop.color, stop.opacity || 1)
836
+ : null;
758
837
 
759
838
  // Parse path command (c/C/l/L for bezier/line)
760
839
  const pathMatch = pathData.match(/^\s*([cClL])\s*(.*)/);
761
840
  if (pathMatch) {
762
841
  const cmd = pathMatch[1];
763
- const coords = pathMatch[2].trim().split(/[\s,]+/).map(Number);
842
+ const _coords = pathMatch[2]
843
+ .trim()
844
+ .split(/[\s,]+/)
845
+ .map(Number);
764
846
 
765
- if (cmd === 'c' || cmd === 'C') {
847
+ if (cmd === "c" || cmd === "C") {
766
848
  // Cubic bezier: c x1,y1 x2,y2 x3,y3 (relative)
767
849
  // or C x1,y1 x2,y2 x3,y3 (absolute)
768
- const isRelative = cmd === 'c';
850
+ const _isRelative = cmd === "c";
769
851
  // Store bezier control points for patch construction
770
- } else if (cmd === 'l' || cmd === 'L') {
852
+ } else if (cmd === "l" || cmd === "L") {
771
853
  // Line: l dx,dy (relative) or L x,y (absolute)
772
- const isRelative = cmd === 'l';
854
+ const _isRelative = cmd === "l";
773
855
  }
774
856
  }
775
857
 
@@ -787,7 +869,7 @@ export function parseMeshGradient(meshGradientDef) {
787
869
  gradientUnits,
788
870
  gradientTransform,
789
871
  x: Number(x),
790
- y: Number(y)
872
+ y: Number(y),
791
873
  };
792
874
  }
793
875
 
@@ -822,32 +904,32 @@ export function parseMeshGradient(meshGradientDef) {
822
904
  */
823
905
  export function parseMeshGradientElement(element) {
824
906
  const data = {
825
- x: element.getAttribute('x') || '0',
826
- y: element.getAttribute('y') || '0',
827
- type: element.getAttribute('type') || 'bilinear',
828
- gradientUnits: element.getAttribute('gradientUnits') || 'userSpaceOnUse',
829
- gradientTransform: element.getAttribute('gradientTransform'),
830
- meshrows: []
907
+ x: element.getAttribute("x") || "0",
908
+ y: element.getAttribute("y") || "0",
909
+ type: element.getAttribute("type") || "bilinear",
910
+ gradientUnits: element.getAttribute("gradientUnits") || "userSpaceOnUse",
911
+ gradientTransform: element.getAttribute("gradientTransform"),
912
+ meshrows: [],
831
913
  };
832
914
 
833
- const meshRows = element.querySelectorAll('meshrow');
834
- meshRows.forEach(row => {
915
+ const meshRows = element.querySelectorAll("meshrow");
916
+ meshRows.forEach((row) => {
835
917
  const rowData = { meshpatches: [] };
836
- const meshPatches = row.querySelectorAll('meshpatch');
918
+ const meshPatches = row.querySelectorAll("meshpatch");
837
919
 
838
- meshPatches.forEach(patch => {
920
+ meshPatches.forEach((patch) => {
839
921
  const patchData = { stops: [] };
840
- const stops = patch.querySelectorAll('stop');
922
+ const stops = patch.querySelectorAll("stop");
841
923
 
842
- stops.forEach(stop => {
843
- const style = stop.getAttribute('style') || '';
924
+ stops.forEach((stop) => {
925
+ const style = stop.getAttribute("style") || "";
844
926
  const colorMatch = style.match(/stop-color:\s*([^;]+)/);
845
927
  const opacityMatch = style.match(/stop-opacity:\s*([^;]+)/);
846
928
 
847
929
  patchData.stops.push({
848
- path: stop.getAttribute('path') || '',
930
+ path: stop.getAttribute("path") || "",
849
931
  color: colorMatch ? colorMatch[1].trim() : null,
850
- opacity: opacityMatch ? parseFloat(opacityMatch[1]) : 1
932
+ opacity: opacityMatch ? parseFloat(opacityMatch[1]) : 1,
851
933
  });
852
934
  });
853
935
 
@@ -975,22 +1057,31 @@ function renderPatchQuad(patch, imageData, width, height) {
975
1057
  for (let y = minY; y <= maxY; y++) {
976
1058
  for (let x = minX; x <= maxX; x++) {
977
1059
  // Convert pixel to patch (u,v) coordinates
978
- const u = D(x).minus(bbox.minX).div(bbox.maxX.minus(bbox.minX) || D(1));
979
- const v = D(y).minus(bbox.minY).div(bbox.maxY.minus(bbox.minY) || D(1));
1060
+ const u = D(x)
1061
+ .minus(bbox.minX)
1062
+ .div(bbox.maxX.minus(bbox.minX) || D(1));
1063
+ const v = D(y)
1064
+ .minus(bbox.minY)
1065
+ .div(bbox.maxY.minus(bbox.minY) || D(1));
980
1066
 
981
1067
  if (u.gte(0) && u.lte(1) && v.gte(0) && v.lte(1)) {
982
- const { color } = patch.evaluate(u, v);
1068
+ const { color: patchColor } = patch.evaluate(u, v);
983
1069
  const idx = (y * width + x) * 4;
984
1070
 
985
1071
  // Alpha blending
986
- const srcA = color.a / 255;
1072
+ const srcA = patchColor.a / 255;
987
1073
  const dstA = imageData[idx + 3] / 255;
988
1074
  const outA = srcA + dstA * (1 - srcA);
989
1075
 
990
1076
  if (outA > 0) {
991
- imageData[idx] = (color.r * srcA + imageData[idx] * dstA * (1 - srcA)) / outA;
992
- imageData[idx + 1] = (color.g * srcA + imageData[idx + 1] * dstA * (1 - srcA)) / outA;
993
- imageData[idx + 2] = (color.b * srcA + imageData[idx + 2] * dstA * (1 - srcA)) / outA;
1077
+ imageData[idx] =
1078
+ (patchColor.r * srcA + imageData[idx] * dstA * (1 - srcA)) / outA;
1079
+ imageData[idx + 1] =
1080
+ (patchColor.g * srcA + imageData[idx + 1] * dstA * (1 - srcA)) /
1081
+ outA;
1082
+ imageData[idx + 2] =
1083
+ (patchColor.b * srcA + imageData[idx + 2] * dstA * (1 - srcA)) /
1084
+ outA;
994
1085
  imageData[idx + 3] = outA * 255;
995
1086
  }
996
1087
  }
@@ -1082,7 +1173,7 @@ function patchToPolygons(patch, subdivisions) {
1082
1173
  r: (p00.color.r + p10.color.r + p01.color.r + p11.color.r) / 4,
1083
1174
  g: (p00.color.g + p10.color.g + p01.color.g + p11.color.g) / 4,
1084
1175
  b: (p00.color.b + p10.color.b + p01.color.b + p11.color.b) / 4,
1085
- a: (p00.color.a + p10.color.a + p01.color.a + p11.color.a) / 4
1176
+ a: (p00.color.a + p10.color.a + p01.color.a + p11.color.a) / 4,
1086
1177
  };
1087
1178
 
1088
1179
  result.push({
@@ -1090,9 +1181,9 @@ function patchToPolygons(patch, subdivisions) {
1090
1181
  PolygonClip.point(p00.point.x, p00.point.y),
1091
1182
  PolygonClip.point(p10.point.x, p10.point.y),
1092
1183
  PolygonClip.point(p11.point.x, p11.point.y),
1093
- PolygonClip.point(p01.point.x, p01.point.y)
1184
+ PolygonClip.point(p01.point.x, p01.point.y),
1094
1185
  ],
1095
- color: avgColor
1186
+ color: avgColor,
1096
1187
  });
1097
1188
  }
1098
1189
  }
@@ -1151,12 +1242,12 @@ export function clipMeshGradient(meshData, clipPolygon, options = {}) {
1151
1242
  // Clip each polygon
1152
1243
  const clippedPolygons = [];
1153
1244
 
1154
- for (const { polygon, color } of meshPolygons) {
1245
+ for (const { polygon, color: polyColor } of meshPolygons) {
1155
1246
  const clipped = PolygonClip.polygonIntersection(polygon, clipPolygon);
1156
1247
 
1157
1248
  for (const clippedPoly of clipped) {
1158
1249
  if (clippedPoly.length >= 3) {
1159
- clippedPolygons.push({ polygon: clippedPoly, color });
1250
+ clippedPolygons.push({ polygon: clippedPoly, color: polyColor });
1160
1251
  }
1161
1252
  }
1162
1253
  }
@@ -1196,8 +1287,8 @@ export function clipMeshGradient(meshData, clipPolygon, options = {}) {
1196
1287
  * ).join('\n');
1197
1288
  */
1198
1289
  export function clippedMeshToSVG(clippedPolygons) {
1199
- return clippedPolygons.map(({ polygon, color }) => {
1200
- let pathData = '';
1290
+ return clippedPolygons.map(({ polygon, color: polyColor }) => {
1291
+ let pathData = "";
1201
1292
  for (let i = 0; i < polygon.length; i++) {
1202
1293
  const p = polygon[i];
1203
1294
  if (i === 0) {
@@ -1206,9 +1297,9 @@ export function clippedMeshToSVG(clippedPolygons) {
1206
1297
  pathData += ` L ${Number(p.x).toFixed(6)} ${Number(p.y).toFixed(6)}`;
1207
1298
  }
1208
1299
  }
1209
- pathData += ' Z';
1300
+ pathData += " Z";
1210
1301
 
1211
- const fill = `rgba(${Math.round(color.r)},${Math.round(color.g)},${Math.round(color.b)},${(color.a / 255).toFixed(3)})`;
1302
+ const fill = `rgba(${Math.round(polyColor.r)},${Math.round(polyColor.g)},${Math.round(polyColor.b)},${(polyColor.a / 255).toFixed(3)})`;
1212
1303
 
1213
1304
  return { pathData, fill };
1214
1305
  });