@pixerate/editor 0.108.0 → 0.109.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.
Files changed (74) hide show
  1. package/dist/animation/index.cjs +5 -5
  2. package/dist/animation/index.cjs.map +1 -1
  3. package/dist/animation/index.js +9 -9
  4. package/dist/animation-editor/index.cjs +59 -59
  5. package/dist/animation-editor/index.cjs.map +1 -1
  6. package/dist/animation-editor/index.d.cts +2 -1
  7. package/dist/animation-editor/index.d.ts +2 -1
  8. package/dist/animation-editor/index.js +29 -29
  9. package/dist/canvas/index.cjs +27 -27
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.js +11 -11
  12. package/dist/{chunk-2FGRTYJN.cjs → chunk-477UVMNR.cjs} +3 -3
  13. package/dist/{chunk-2FGRTYJN.cjs.map → chunk-477UVMNR.cjs.map} +1 -1
  14. package/dist/{chunk-T3QZ6S47.cjs → chunk-AZTZRLDI.cjs} +40 -2
  15. package/dist/chunk-AZTZRLDI.cjs.map +1 -0
  16. package/dist/{chunk-HUQ7EHVI.js → chunk-BLWCAQCW.js} +723 -1975
  17. package/dist/chunk-BLWCAQCW.js.map +1 -0
  18. package/dist/{chunk-G4BIYE6R.js → chunk-CFMWALBM.js} +39 -1
  19. package/dist/chunk-CFMWALBM.js.map +1 -0
  20. package/dist/{chunk-FRD3FUXI.cjs → chunk-D37BX2ZA.cjs} +2081 -460
  21. package/dist/chunk-D37BX2ZA.cjs.map +1 -0
  22. package/dist/chunk-JLYX4V57.cjs +2001 -0
  23. package/dist/chunk-JLYX4V57.cjs.map +1 -0
  24. package/dist/chunk-KB2YBCVS.js +2001 -0
  25. package/dist/chunk-KB2YBCVS.js.map +1 -0
  26. package/dist/{chunk-SOROZ2BF.js → chunk-RE77QYUF.js} +1938 -317
  27. package/dist/chunk-RE77QYUF.js.map +1 -0
  28. package/dist/{chunk-UTEVPQTS.cjs → chunk-W3GXSUSQ.cjs} +746 -1998
  29. package/dist/chunk-W3GXSUSQ.cjs.map +1 -0
  30. package/dist/{chunk-JK6M6V7G.js → chunk-Z3YWVUWT.js} +4 -4
  31. package/dist/{export-a9bnF7Cl.d.ts → export-BLPLaE6Z.d.ts} +417 -16
  32. package/dist/{export-JGWQEPJn.d.cts → export-DSUc4fQD.d.cts} +417 -16
  33. package/dist/image-editor/index.cjs +1527 -1001
  34. package/dist/image-editor/index.cjs.map +1 -1
  35. package/dist/image-editor/index.d.cts +73 -9
  36. package/dist/image-editor/index.d.ts +73 -9
  37. package/dist/image-editor/index.js +814 -288
  38. package/dist/image-editor/index.js.map +1 -1
  39. package/dist/paint-editor/index.cjs +56 -53
  40. package/dist/paint-editor/index.cjs.map +1 -1
  41. package/dist/paint-editor/index.d.cts +5 -2
  42. package/dist/paint-editor/index.d.ts +5 -2
  43. package/dist/paint-editor/index.js +6 -3
  44. package/dist/paint-editor/index.js.map +1 -1
  45. package/dist/raster/index.cjs +4 -2
  46. package/dist/raster/index.cjs.map +1 -1
  47. package/dist/raster/index.d.cts +3 -129
  48. package/dist/raster/index.d.ts +3 -129
  49. package/dist/raster/index.js +3 -1
  50. package/dist/{compositor-D92URMlm.d.cts → render-C-fO_mes.d.cts} +135 -1
  51. package/dist/{compositor-Kt_M4ruo.d.ts → render-OLIMk_v0.d.ts} +135 -1
  52. package/dist/{svg-SseJTIrA.d.ts → svg-D_cfkhlB.d.cts} +3 -629
  53. package/dist/{svg-ClVIG4T7.d.cts → svg-wIaKLrU0.d.ts} +3 -629
  54. package/dist/types-DtL_qLFz.d.ts +630 -0
  55. package/dist/types-DyQq-WPY.d.cts +630 -0
  56. package/dist/vector/index.cjs +563 -563
  57. package/dist/vector/index.cjs.map +1 -1
  58. package/dist/vector/index.d.cts +4 -2
  59. package/dist/vector/index.d.ts +4 -2
  60. package/dist/vector/index.js +69 -69
  61. package/dist/video-editor/index.cjs +3 -3
  62. package/dist/video-editor/index.js +2 -2
  63. package/package.json +1 -1
  64. package/dist/chunk-DWGZUSES.cjs +0 -694
  65. package/dist/chunk-DWGZUSES.cjs.map +0 -1
  66. package/dist/chunk-FRD3FUXI.cjs.map +0 -1
  67. package/dist/chunk-G4BIYE6R.js.map +0 -1
  68. package/dist/chunk-HUQ7EHVI.js.map +0 -1
  69. package/dist/chunk-KKREERP2.js +0 -694
  70. package/dist/chunk-KKREERP2.js.map +0 -1
  71. package/dist/chunk-SOROZ2BF.js.map +0 -1
  72. package/dist/chunk-T3QZ6S47.cjs.map +0 -1
  73. package/dist/chunk-UTEVPQTS.cjs.map +0 -1
  74. /package/dist/{chunk-JK6M6V7G.js.map → chunk-Z3YWVUWT.js.map} +0 -0
@@ -9,7 +9,6 @@ import {
9
9
  fitCubicRun,
10
10
  fitCubics,
11
11
  flattenChain,
12
- formatNumber,
13
12
  isStraightCubic,
14
13
  normalizeBezierPath,
15
14
  offsetPath,
@@ -34,33 +33,6 @@ import {
34
33
  windingNumber
35
34
  } from "./chunk-YCSFS3GK.js";
36
35
  import {
37
- IDENTITY_MATRIX,
38
- WARP_STYLES,
39
- WARP_STYLE_LABELS,
40
- applyMatrix,
41
- clampMeshCount,
42
- decomposeRigid,
43
- evalWarpMesh,
44
- evenKnots,
45
- fitWarpMesh,
46
- identityWarpMesh,
47
- invertMatrix,
48
- isIdentityMatrix,
49
- isValidWarpMesh,
50
- lerpVec2,
51
- mapWarpMeshPoints,
52
- matrixRotation,
53
- multiplyMatrices,
54
- resizeWarpMesh,
55
- rotateMatrix,
56
- scaleMatrix,
57
- translateMatrix,
58
- warpMeshColumns,
59
- warpMeshRows,
60
- warpPresetMesh
61
- } from "./chunk-KKREERP2.js";
62
- import {
63
- mixColorsOklab,
64
36
  oklabToRgb,
65
37
  rgbToOklab
66
38
  } from "./chunk-ZRJMJIQU.js";
@@ -69,9 +41,6 @@ import {
69
41
  normalizeTokenColor,
70
42
  rgbaToHex
71
43
  } from "./chunk-TGD52FEZ.js";
72
- import {
73
- evaluateEasing
74
- } from "./chunk-AGR4P4UZ.js";
75
44
 
76
45
  // src/vector/types.ts
77
46
  var VECTOR_CORNER_KINDS = ["round", "inverted", "chamfer"];
@@ -539,12 +508,12 @@ function vectorGradientHandles(g, bounds, toWorld = IDENTITY) {
539
508
  const p = vectorGradientPoints(g);
540
509
  const m = mul(vectorGradientUnitsMatrix(g, bounds), toWorld);
541
510
  const f = g.type === "radial" ? unitFocal(g) : null;
542
- const frame2 = mul(framePointsMatrix(p), m);
511
+ const frame = mul(framePointsMatrix(p), m);
543
512
  return {
544
513
  start: apply(m, p.start),
545
514
  end: apply(m, p.end),
546
515
  aspect: isCentredVectorGradient(g.type) ? apply(m, p.width) : null,
547
- focal: g.type === "radial" ? apply(frame2, f?.f ?? { x: 0, y: 0 }) : null
516
+ focal: g.type === "radial" ? apply(frame, f?.f ?? { x: 0, y: 0 }) : null
548
517
  };
549
518
  }
550
519
  function withMainAxis(p, start, end) {
@@ -590,15 +559,15 @@ function moveVectorGradientHandle(g, bounds, handle, to, from = to) {
590
559
  return set({ width, focal });
591
560
  }
592
561
  case "focal": {
593
- const frame2 = framePointsMatrix(p);
594
- const inv = invert(frame2);
562
+ const frame = framePointsMatrix(p);
563
+ const inv = invert(frame);
595
564
  if (!inv) return pinned;
596
565
  let q = apply(inv, to);
597
566
  const r = Math.hypot(q.x, q.y);
598
567
  if (r < 1e-6) return set({ focal: null });
599
568
  const reach = FOCAL_MAX * (1 - p.focalRadius);
600
569
  if (r > reach) q = scale(q, reach / r);
601
- return set({ focal: apply(frame2, q) });
570
+ return set({ focal: apply(frame, q) });
602
571
  }
603
572
  }
604
573
  }
@@ -938,6 +907,65 @@ function applyVectorGradientPatch(g, patch) {
938
907
  return clean2;
939
908
  }
940
909
 
910
+ // src/geom/affine.ts
911
+ var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
912
+ function multiplyMatrices(a, b) {
913
+ const [a0, a1, a2, a3, a4, a5] = a;
914
+ const [b0, b1, b2, b3, b4, b5] = b;
915
+ return [b0 * a0 + b2 * a1, b1 * a0 + b3 * a1, b0 * a2 + b2 * a3, b1 * a2 + b3 * a3, b0 * a4 + b2 * a5 + b4, b1 * a4 + b3 * a5 + b5];
916
+ }
917
+ var translateMatrix = (dx, dy) => [1, 0, 0, 1, dx, dy];
918
+ function scaleMatrix(sx, sy, origin = { x: 0, y: 0 }) {
919
+ return [sx, 0, 0, sy, origin.x - sx * origin.x, origin.y - sy * origin.y];
920
+ }
921
+ function rotateMatrix(degrees, origin = { x: 0, y: 0 }) {
922
+ const r = degrees * Math.PI / 180;
923
+ const cos = Math.cos(r);
924
+ const sin = Math.sin(r);
925
+ return [cos, sin, -sin, cos, origin.x - cos * origin.x + sin * origin.y, origin.y - sin * origin.x - cos * origin.y];
926
+ }
927
+ function matrixAbout(m, origin) {
928
+ return multiplyMatrices(multiplyMatrices(translateMatrix(-origin.x, -origin.y), m), translateMatrix(origin.x, origin.y));
929
+ }
930
+ function skewMatrix(ax, ay, origin = { x: 0, y: 0 }) {
931
+ const tx = Math.tan(ax * Math.PI / 180);
932
+ const ty = Math.tan(ay * Math.PI / 180);
933
+ return matrixAbout([1, ty, tx, 1, 0, 0], origin);
934
+ }
935
+ function applyMatrix(m, p) {
936
+ return { x: m[0] * p.x + m[2] * p.y + m[4], y: m[1] * p.x + m[3] * p.y + m[5] };
937
+ }
938
+ function isIdentityMatrix(m, eps = 1e-12) {
939
+ return Math.abs(m[0] - 1) < eps && Math.abs(m[1]) < eps && Math.abs(m[2]) < eps && Math.abs(m[3] - 1) < eps && Math.abs(m[4]) < eps && Math.abs(m[5]) < eps;
940
+ }
941
+ function invertMatrix(m) {
942
+ const [a, b, c, d, e, f] = m;
943
+ const det = a * d - b * c;
944
+ if (!det || !Number.isFinite(det)) return IDENTITY_MATRIX;
945
+ return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
946
+ }
947
+ function applyMatrixLinear(m, v2) {
948
+ return { x: m[0] * v2.x + m[2] * v2.y, y: m[1] * v2.x + m[3] * v2.y };
949
+ }
950
+ function matrixRotation(m) {
951
+ const [a, b, c, d] = m;
952
+ const mirrored = a * d - b * c < 0;
953
+ const deg = (mirrored ? Math.atan2(-b - c, d - a) : Math.atan2(b - c, a + d)) * 180 / Math.PI;
954
+ return Math.abs(deg) < 1e-9 ? 0 : deg;
955
+ }
956
+ function decomposeRigid(m) {
957
+ const [a, b, c, d, e, f] = m;
958
+ const deg = matrixRotation(m);
959
+ if (deg === 0) return { rigid: IDENTITY_MATRIX, residual: m };
960
+ const r = deg * Math.PI / 180;
961
+ const cos = Math.cos(r);
962
+ const sin = Math.sin(r);
963
+ return {
964
+ rigid: [cos, sin, -sin, cos, e, f],
965
+ residual: [cos * a + sin * b, -sin * a + cos * b, cos * c + sin * d, -sin * c + cos * d, 0, 0]
966
+ };
967
+ }
968
+
941
969
  // src/vector/corners.ts
942
970
  var EPS = 1e-9;
943
971
  var MIN_SINE = 1e-6;
@@ -1281,8 +1309,8 @@ function removeWidthPoints(points, indices) {
1281
1309
  }
1282
1310
  function ease(u, e) {
1283
1311
  const x = Math.min(Math.max(u, 0), 1);
1284
- const round3 = Math.sqrt(Math.max(0, 1 - (1 - x) * (1 - x)));
1285
- return x + (round3 - x) * Math.min(Math.max(e, 0), 1);
1312
+ const round2 = Math.sqrt(Math.max(0, 1 - (1 - x) * (1 - x)));
1313
+ return x + (round2 - x) * Math.min(Math.max(e, 0), 1);
1286
1314
  }
1287
1315
  function taperWaveFactor(t, taper, wave) {
1288
1316
  let k = 1;
@@ -1561,10 +1589,10 @@ function variableStrokeRings(path, options) {
1561
1589
  if (closed && out.length > 1 && dist(out[0], out[out.length - 1]) <= 1e-12) out.pop();
1562
1590
  return out;
1563
1591
  };
1564
- const left2 = side(1);
1592
+ const left = side(1);
1565
1593
  const right = side(-1);
1566
1594
  if (closed) {
1567
- rings.push(left2, right.reverse());
1595
+ rings.push(left, right.reverse());
1568
1596
  continue;
1569
1597
  }
1570
1598
  const capPoints = (atStart) => {
@@ -1586,7 +1614,7 @@ function variableStrokeRings(path, options) {
1586
1614
  return atStart ? [along(R, o, ext), along(L, o, ext)] : [along(L, o, ext), along(R, o, ext)];
1587
1615
  };
1588
1616
  const ring = [];
1589
- for (const q of [...left2, ...capPoints(false), ...right.reverse(), ...capPoints(true)]) push(ring, q);
1617
+ for (const q of [...left, ...capPoints(false), ...right.reverse(), ...capPoints(true)]) push(ring, q);
1590
1618
  if (ring.length > 2) rings.push(ring);
1591
1619
  }
1592
1620
  }
@@ -1702,8 +1730,8 @@ function vectorStrokeLineArea(parts, style, tolerance) {
1702
1730
  }
1703
1731
  var capExtent = (style, width) => style.strokeLinecap === "round" || style.strokeLinecap === "square" ? width / 2 : 0;
1704
1732
  function arrowheadWeight(style, end) {
1705
- const scale3 = end === "start" ? style.startArrowScale : style.endArrowScale;
1706
- const s = typeof scale3 === "number" && scale3 > 0 && Number.isFinite(scale3) ? scale3 : 1;
1733
+ const scale2 = end === "start" ? style.startArrowScale : style.endArrowScale;
1734
+ const s = typeof scale2 === "number" && scale2 > 0 && Number.isFinite(scale2) ? scale2 : 1;
1707
1735
  const width = style.strokeWidth ?? 1;
1708
1736
  const profile = strokeWidthProfileOf(style);
1709
1737
  const at2 = profile ? widthProfileAt(profile, end === "start" ? 0 : 1) : null;
@@ -2359,9 +2387,9 @@ function facesOf(path, fillRule) {
2359
2387
  function splitIntoFaces(path, fillRule = "nonzero") {
2360
2388
  return facesOf(path, fillRule).map(faceToPath);
2361
2389
  }
2362
- function rootsInUnit(a, b, c, d, scale3) {
2390
+ function rootsInUnit(a, b, c, d, scale2) {
2363
2391
  const f = (t) => ((a * t + b) * t + c) * t + d;
2364
- const tol = 1e-12 * Math.max(1, scale3);
2392
+ const tol = 1e-12 * Math.max(1, scale2);
2365
2393
  const cuts = [0];
2366
2394
  const qa = 3 * a;
2367
2395
  const qb = 2 * b;
@@ -2418,9 +2446,9 @@ function lineHits(p, q, seg) {
2418
2446
  coeffs = [-h0 + 3 * h1 - 3 * h2 + h3, 3 * h0 - 6 * h1 + 3 * h2, -3 * h0 + 3 * h1, h0];
2419
2447
  }
2420
2448
  if (coeffs.every((c) => Math.abs(c) < 1e-12 * Math.max(1, len2))) return [];
2421
- const scale3 = Math.sqrt(len2) * Math.max(1, ...seg.map((pt2) => Math.abs(pt2[0]) + Math.abs(pt2[1])));
2449
+ const scale2 = Math.sqrt(len2) * Math.max(1, ...seg.map((pt2) => Math.abs(pt2[0]) + Math.abs(pt2[1])));
2422
2450
  const out = [];
2423
- for (const t of rootsInUnit(...coeffs, scale3)) {
2451
+ for (const t of rootsInUnit(...coeffs, scale2)) {
2424
2452
  const point = segmentPoint(seg, t);
2425
2453
  const s = ((point[0] - p[0]) * dx + (point[1] - p[1]) * dy) / len2;
2426
2454
  if (s >= -1e-9 && s <= 1 + 1e-9) out.push({ s: Math.min(1, Math.max(0, s)), t, point });
@@ -3084,6 +3112,600 @@ function vectorMaskRenderData(group, id, filterId, precision = 3) {
3084
3112
  return { type: group.mask.type, invert: invert2, id, bounds, filter: `url(#${filterId})`, invertFilter: filter };
3085
3113
  }
3086
3114
 
3115
+ // src/geom/warp.ts
3116
+ var WARP_STYLES = [
3117
+ "arc",
3118
+ "arcLower",
3119
+ "arcUpper",
3120
+ "arch",
3121
+ "bulge",
3122
+ "shellLower",
3123
+ "shellUpper",
3124
+ "flag",
3125
+ "wave",
3126
+ "fish",
3127
+ "rise",
3128
+ "fisheye",
3129
+ "inflate",
3130
+ "squeeze",
3131
+ "twist"
3132
+ ];
3133
+ var WARP_STYLE_LABELS = {
3134
+ arc: "Arc",
3135
+ arcLower: "Arc Lower",
3136
+ arcUpper: "Arc Upper",
3137
+ arch: "Arch",
3138
+ bulge: "Bulge",
3139
+ shellLower: "Shell Lower",
3140
+ shellUpper: "Shell Upper",
3141
+ flag: "Flag",
3142
+ wave: "Wave",
3143
+ fish: "Fish",
3144
+ rise: "Rise",
3145
+ fisheye: "Fisheye",
3146
+ inflate: "Inflate",
3147
+ squeeze: "Squeeze",
3148
+ twist: "Twist"
3149
+ };
3150
+ function restGrid() {
3151
+ return [0, 1, 2, 3].map((j) => [0, 1, 2, 3].map((i) => [i / 3, j / 3]));
3152
+ }
3153
+ function edgeArc(y, b, up, h) {
3154
+ if (Math.abs(b) < 1e-9) return [0, 1, 2, 3].map((i) => [i / 3, y]);
3155
+ const th = Math.abs(b) * Math.PI;
3156
+ const k = 4 / 3 * Math.tan(th / 4) * 0.5 / Math.sin(th / 2);
3157
+ const s = b > 0 === up ? -1 : 1;
3158
+ const c = Math.cos(th / 2);
3159
+ const n = Math.sin(th / 2);
3160
+ const dy = s * k * n / h;
3161
+ return [
3162
+ [0, y],
3163
+ [k * c, y + dy],
3164
+ [1 - k * c, y + dy],
3165
+ [1, y]
3166
+ ];
3167
+ }
3168
+ function arcGrid(b, h) {
3169
+ if (Math.abs(b) < 1e-9) return restGrid();
3170
+ const up = b > 0;
3171
+ const th = Math.abs(b) * Math.PI;
3172
+ const r = 0.5 / Math.sin(th / 2);
3173
+ const k = 4 / 3 * Math.tan(th / 4);
3174
+ const s = up ? -1 : 1;
3175
+ const cy = up ? h + r * Math.cos(th / 2) : -r * Math.cos(th / 2);
3176
+ return [0, 1, 2, 3].map((j) => {
3177
+ const v2 = j / 3;
3178
+ const big = r + h * (up ? 1 - v2 : v2);
3179
+ const at2 = (a) => [0.5 + big * Math.sin(a), cy + s * big * Math.cos(a)];
3180
+ const tangent2 = (a) => [Math.cos(a), -s * Math.sin(a)];
3181
+ const p0 = at2(-th / 2);
3182
+ const p3 = at2(th / 2);
3183
+ const t0 = tangent2(-th / 2);
3184
+ const t1 = tangent2(th / 2);
3185
+ const l = k * big;
3186
+ const pts = [p0, [p0[0] + l * t0[0], p0[1] + l * t0[1]], [p3[0] - l * t1[0], p3[1] - l * t1[1]], p3];
3187
+ return pts.map((p) => [p[0], p[1] / h]);
3188
+ });
3189
+ }
3190
+ function blendRows(top, bottom) {
3191
+ return [0, 1, 2, 3].map((j) => {
3192
+ const t = j / 3;
3193
+ return [0, 1, 2, 3].map((i) => [top[i][0] + (bottom[i][0] - top[i][0]) * t, top[i][1] + (bottom[i][1] - top[i][1]) * t]);
3194
+ });
3195
+ }
3196
+ var INNER = [
3197
+ [1, 1, -1, -1],
3198
+ [1, 2, 1, -1],
3199
+ [2, 1, -1, 1],
3200
+ [2, 2, 1, 1]
3201
+ ];
3202
+ function warpPresetGrid(style, b, hd, vd, vertical, aspect) {
3203
+ const h = vertical ? 1 / aspect : aspect;
3204
+ if (vertical) [hd, vd] = [vd, hd];
3205
+ let g = restGrid();
3206
+ switch (style) {
3207
+ case "arc":
3208
+ g = arcGrid(b, h);
3209
+ break;
3210
+ case "arch":
3211
+ g = [0, 1, 2, 3].map((j) => edgeArc(j / 3, b, true, h));
3212
+ break;
3213
+ case "bulge":
3214
+ g = blendRows(edgeArc(0, b, true, h), edgeArc(1, b, false, h));
3215
+ break;
3216
+ case "arcLower":
3217
+ g = blendRows(g[0], edgeArc(1, b, false, h));
3218
+ break;
3219
+ case "arcUpper":
3220
+ g = blendRows(edgeArc(0, b, true, h), g[3]);
3221
+ break;
3222
+ // The bulging edge and the outer points of the row next to it come from Arc (bent the other
3223
+ // way for Shell Lower); the rest stays put.
3224
+ case "shellLower": {
3225
+ const a = arcGrid(-b, h);
3226
+ g[3] = a[3];
3227
+ g[2][0] = a[2][0];
3228
+ g[2][3] = a[2][3];
3229
+ break;
3230
+ }
3231
+ case "shellUpper": {
3232
+ const a = arcGrid(b, h);
3233
+ g[0] = a[0];
3234
+ g[1][0] = a[1][0];
3235
+ g[1][3] = a[1][3];
3236
+ break;
3237
+ }
3238
+ case "flag":
3239
+ for (const row of g) {
3240
+ row[1][1] -= 2 * b;
3241
+ row[2][1] += 2 * b;
3242
+ }
3243
+ break;
3244
+ case "wave":
3245
+ for (const row of g.slice(1, 3)) {
3246
+ row[1][1] += 4 / 3 * b;
3247
+ row[2][1] -= 4 / 3 * b;
3248
+ }
3249
+ break;
3250
+ case "fish":
3251
+ [-2, -2 / 3, 2 / 3, 2].forEach((f, j) => {
3252
+ g[j][1][1] += f * b;
3253
+ g[j][2][1] -= f * b;
3254
+ });
3255
+ break;
3256
+ case "rise":
3257
+ for (const row of g) {
3258
+ row[0][1] += 2 * b;
3259
+ row[1][1] += 2 * b;
3260
+ }
3261
+ break;
3262
+ case "fisheye":
3263
+ for (const [j, i, dx, dy] of INNER) {
3264
+ g[j][i][0] += dx * 2 * b / 3;
3265
+ g[j][i][1] += dy * 2 * b / 3;
3266
+ }
3267
+ break;
3268
+ // Edge midpoints move out (Inflate) or the sides in (Squeeze) by b/3, the inner points by b/9.
3269
+ case "inflate":
3270
+ case "squeeze": {
3271
+ const s = style === "inflate" ? 1 : -1;
3272
+ for (const p of g[0].slice(1, 3)) p[1] -= b / 3;
3273
+ for (const p of g[3].slice(1, 3)) p[1] += b / 3;
3274
+ for (const row of g.slice(1, 3)) {
3275
+ row[0][0] -= s * b / 3;
3276
+ row[3][0] += s * b / 3;
3277
+ }
3278
+ for (const [j, i, dx, dy] of INNER) {
3279
+ g[j][i][0] += s * dx * b / 9;
3280
+ g[j][i][1] += dy * b / 9;
3281
+ }
3282
+ break;
3283
+ }
3284
+ // The inner points turn round the centre (the other way for a negative bend).
3285
+ case "twist": {
3286
+ const a = Math.abs(b);
3287
+ if (b >= 0) {
3288
+ g[1][1][0] += a;
3289
+ g[1][2][1] += a;
3290
+ g[2][1][1] -= a;
3291
+ g[2][2][0] -= a;
3292
+ } else {
3293
+ g[1][1][1] += a;
3294
+ g[1][2][0] -= a;
3295
+ g[2][1][0] += a;
3296
+ g[2][2][1] -= a;
3297
+ }
3298
+ break;
3299
+ }
3300
+ }
3301
+ if (vd !== 0) {
3302
+ const moved = (row, s) => {
3303
+ const m = [(row[0][0] + row[3][0]) / 2, (row[0][1] + row[3][1]) / 2];
3304
+ return row.map((p) => [m[0] + (p[0] - m[0]) * s - p[0], m[1] + (p[1] - m[1]) * s - p[1]]);
3305
+ };
3306
+ const d0 = moved(g[0], 1 - vd);
3307
+ const d3 = moved(g[3], 1 + vd);
3308
+ g.forEach((row, j) => {
3309
+ const t = j / 3;
3310
+ row.forEach((p, i) => {
3311
+ p[0] += d0[i][0] + (d3[i][0] - d0[i][0]) * t;
3312
+ p[1] += d0[i][1] + (d3[i][1] - d0[i][1]) * t;
3313
+ });
3314
+ });
3315
+ }
3316
+ if (hd !== 0) {
3317
+ for (let i = 0; i < 4; i++) {
3318
+ const s = 1 + hd * (2 * i / 3 - 1);
3319
+ const m = [(g[0][i][0] + g[3][i][0]) / 2, (g[0][i][1] + g[3][i][1]) / 2];
3320
+ for (const row of g) row[i] = [m[0] + (row[i][0] - m[0]) * s, m[1] + (row[i][1] - m[1]) * s];
3321
+ }
3322
+ }
3323
+ if (vertical) g = [0, 1, 2, 3].map((j) => [0, 1, 2, 3].map((i) => [g[i][j][1], g[i][j][0]]));
3324
+ return g;
3325
+ }
3326
+ function bernstein(t) {
3327
+ const s = 1 - t;
3328
+ return [s * s * s, 3 * s * s * t, 3 * s * t * t, t * t * t];
3329
+ }
3330
+ var lerpVec2 = (a, b, t) => ({ x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t });
3331
+ function splitCubic(p, t) {
3332
+ const a = lerpVec2(p[0], p[1], t);
3333
+ const b = lerpVec2(p[1], p[2], t);
3334
+ const c = lerpVec2(p[2], p[3], t);
3335
+ const d = lerpVec2(a, b, t);
3336
+ const e = lerpVec2(b, c, t);
3337
+ return [p[0], a, d, lerpVec2(d, e, t), e, c, p[3]];
3338
+ }
3339
+ var BERN_INV = [
3340
+ [1, 0, 0, 0],
3341
+ [-5 / 6, 3, -1.5, 1 / 3],
3342
+ [1 / 3, -1.5, 3, -5 / 6],
3343
+ [0, 0, 0, 1]
3344
+ ];
3345
+ var pct = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? Math.min(1, Math.max(-1, v2 / 100)) : 0;
3346
+ function warpPresetMesh(preset, bounds) {
3347
+ if (!WARP_STYLES.includes(preset.style)) return null;
3348
+ const { x, y, width: w, height: h } = bounds;
3349
+ if (!(w > 0 && h > 0)) return null;
3350
+ const b = pct(preset.bend);
3351
+ const hd = pct(preset.horizontal);
3352
+ const vd = pct(preset.vertical);
3353
+ if (b === 0 && hd === 0 && vd === 0) return null;
3354
+ const grid = warpPresetGrid(preset.style, b, hd, vd, preset.orientation === "vertical", h / w);
3355
+ return { us: [0, 1], vs: [0, 1], points: grid.flat().map((p) => ({ x: x + p[0] * w, y: y + p[1] * h })) };
3356
+ }
3357
+ var warpMeshColumns = (m) => 3 * (m.us.length - 1) + 1;
3358
+ var warpMeshRows = (m) => 3 * (m.vs.length - 1) + 1;
3359
+ function isValidWarpMesh(m) {
3360
+ if (!m || typeof m !== "object") return false;
3361
+ const { us, vs, points } = m;
3362
+ const knots = (k) => Array.isArray(k) && k.length >= 2 && k.length <= 65 && k[0] === 0 && k[k.length - 1] === 1 && k.every((v2, i) => typeof v2 === "number" && (i === 0 || v2 > k[i - 1]));
3363
+ if (!knots(us) || !knots(vs) || !Array.isArray(points)) return false;
3364
+ return points.length === (3 * (us.length - 1) + 1) * (3 * (vs.length - 1) + 1) && points.every((p) => !!p && Number.isFinite(p.x) && Number.isFinite(p.y));
3365
+ }
3366
+ function fitWarpMesh(f, us, vs) {
3367
+ const pc = us.length - 1;
3368
+ const pr = vs.length - 1;
3369
+ const nx = 3 * pc + 1;
3370
+ const points = new Array((3 * pr + 1) * nx);
3371
+ for (let pj = 0; pj < pr; pj++) {
3372
+ for (let pi = 0; pi < pc; pi++) {
3373
+ const s = [0, 1, 2, 3].map(
3374
+ (j) => [0, 1, 2, 3].map((i) => f(us[pi] + (us[pi + 1] - us[pi]) * i / 3, vs[pj] + (vs[pj + 1] - vs[pj]) * j / 3))
3375
+ );
3376
+ for (let j = 0; j < 4; j++) {
3377
+ for (let i = 0; i < 4; i++) {
3378
+ let x = 0;
3379
+ let y = 0;
3380
+ for (let a = 0; a < 4; a++) {
3381
+ for (let b = 0; b < 4; b++) {
3382
+ const k = BERN_INV[j][a] * BERN_INV[i][b];
3383
+ x += k * s[a][b].x;
3384
+ y += k * s[a][b].y;
3385
+ }
3386
+ }
3387
+ points[(3 * pj + j) * nx + 3 * pi + i] = { x, y };
3388
+ }
3389
+ }
3390
+ }
3391
+ }
3392
+ return { us: us.slice(), vs: vs.slice(), points };
3393
+ }
3394
+ var evenKnots = (n) => Array.from({ length: n + 1 }, (_, i) => i / n);
3395
+ var clampMeshCount = (n) => Math.min(64, Math.max(1, Math.round(Number.isFinite(n) ? n : 1)));
3396
+ function identityWarpMesh(bounds, columns = 1, rows = 1) {
3397
+ return fitWarpMesh((s, t) => ({ x: bounds.x + s * bounds.width, y: bounds.y + t * bounds.height }), evenKnots(clampMeshCount(columns)), evenKnots(clampMeshCount(rows)));
3398
+ }
3399
+ function locate(knots, s) {
3400
+ const n = knots.length - 1;
3401
+ let i = 0;
3402
+ while (i + 1 < n && s > knots[i + 1]) i++;
3403
+ const w = knots[i + 1] - knots[i];
3404
+ return [i, w > 0 ? (s - knots[i]) / w : 0];
3405
+ }
3406
+ function evalWarpMesh(m, s, t) {
3407
+ const [pi, a] = locate(m.us, s);
3408
+ const [pj, b] = locate(m.vs, t);
3409
+ const ba = bernstein(a);
3410
+ const bb = bernstein(b);
3411
+ const nx = warpMeshColumns(m);
3412
+ let x = 0;
3413
+ let y = 0;
3414
+ for (let j = 0; j < 4; j++) {
3415
+ for (let i = 0; i < 4; i++) {
3416
+ const p = m.points[(3 * pj + j) * nx + 3 * pi + i];
3417
+ const k = ba[i] * bb[j];
3418
+ x += p.x * k;
3419
+ y += p.y * k;
3420
+ }
3421
+ }
3422
+ return { x, y };
3423
+ }
3424
+ function transposeMesh(m) {
3425
+ const nx = warpMeshColumns(m);
3426
+ const ny = warpMeshRows(m);
3427
+ const points = new Array(nx * ny);
3428
+ for (let j = 0; j < ny; j++) for (let i = 0; i < nx; i++) points[i * ny + j] = m.points[j * nx + i];
3429
+ return { us: m.vs.slice(), vs: m.us.slice(), points };
3430
+ }
3431
+ function splitWarpMeshU(m, s) {
3432
+ const [pi, a] = locate(m.us, s);
3433
+ if (!(a >= 0.01 && a <= 0.99)) return null;
3434
+ const nx = warpMeshColumns(m);
3435
+ const ny = warpMeshRows(m);
3436
+ const points = [];
3437
+ for (let j = 0; j < ny; j++) {
3438
+ const row = m.points.slice(j * nx, (j + 1) * nx);
3439
+ points.push(...row.slice(0, 3 * pi), ...splitCubic(row.slice(3 * pi, 3 * pi + 4), a), ...row.slice(3 * pi + 4));
3440
+ }
3441
+ const us = m.us.slice();
3442
+ us.splice(pi + 1, 0, Math.min(1, Math.max(0, s)));
3443
+ return { us, vs: m.vs.slice(), points };
3444
+ }
3445
+ function splitWarpMeshV(m, t) {
3446
+ const out = splitWarpMeshU(transposeMesh(m), t);
3447
+ return out && transposeMesh(out);
3448
+ }
3449
+ function removeWarpMeshSplitU(m, k) {
3450
+ if (k <= 0 || k + 1 >= m.us.length) return null;
3451
+ const a = (m.us[k] - m.us[k - 1]) / (m.us[k + 1] - m.us[k - 1]);
3452
+ const nx = warpMeshColumns(m);
3453
+ const ny = warpMeshRows(m);
3454
+ const c0 = 3 * (k - 1);
3455
+ const points = [];
3456
+ for (let j = 0; j < ny; j++) {
3457
+ const row = m.points.slice(j * nx, (j + 1) * nx);
3458
+ const [p0, q1, r2, p3] = [row[c0], row[c0 + 1], row[c0 + 5], row[c0 + 6]];
3459
+ const p1 = { x: (q1.x - (1 - a) * p0.x) / a, y: (q1.y - (1 - a) * p0.y) / a };
3460
+ const p2 = { x: (r2.x - a * p3.x) / (1 - a), y: (r2.y - a * p3.y) / (1 - a) };
3461
+ points.push(...row.slice(0, c0), p0, p1, p2, p3, ...row.slice(c0 + 7));
3462
+ }
3463
+ const us = m.us.slice();
3464
+ us.splice(k, 1);
3465
+ return { us, vs: m.vs.slice(), points };
3466
+ }
3467
+ function removeWarpMeshSplitV(m, k) {
3468
+ const out = removeWarpMeshSplitU(transposeMesh(m), k);
3469
+ return out && transposeMesh(out);
3470
+ }
3471
+ function mapWarpMeshPoints(m, f) {
3472
+ return { us: m.us.slice(), vs: m.vs.slice(), points: m.points.map((p) => f(p)) };
3473
+ }
3474
+ function resizeWarpMesh(m, columns, rows) {
3475
+ const cols = clampMeshCount(columns);
3476
+ const rws = clampMeshCount(rows);
3477
+ if (m.us.length - 1 === cols && m.vs.length - 1 === rws) return m;
3478
+ const us = evenKnots(cols);
3479
+ const vs = evenKnots(rws);
3480
+ const has = (list, v2) => list.some((k) => Math.abs(k - v2) < 1e-12);
3481
+ if (m.us.every((u) => has(us, u)) && m.vs.every((v2) => has(vs, v2))) {
3482
+ let out = m;
3483
+ for (const u of us) if (!has(out.us, u)) out = splitWarpMeshU(out, u) ?? out;
3484
+ for (const v2 of vs) if (!has(out.vs, v2)) out = splitWarpMeshV(out, v2) ?? out;
3485
+ return out;
3486
+ }
3487
+ return fitWarpMesh((s, t) => evalWarpMesh(m, s, t), us, vs);
3488
+ }
3489
+ function warpMeshControlBounds(m) {
3490
+ let minX = Infinity;
3491
+ let minY = Infinity;
3492
+ let maxX = -Infinity;
3493
+ let maxY = -Infinity;
3494
+ for (const p of m.points) {
3495
+ minX = Math.min(minX, p.x);
3496
+ minY = Math.min(minY, p.y);
3497
+ maxX = Math.max(maxX, p.x);
3498
+ maxY = Math.max(maxY, p.y);
3499
+ }
3500
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
3501
+ }
3502
+ function warpMeshParamAt(m, p) {
3503
+ const n = 48;
3504
+ let best = { s: 0.5, t: 0.5, d: Infinity };
3505
+ for (let j = 0; j <= n; j++) {
3506
+ for (let i = 0; i <= n; i++) {
3507
+ const q2 = evalWarpMesh(m, i / n, j / n);
3508
+ const d = (q2.x - p.x) ** 2 + (q2.y - p.y) ** 2;
3509
+ if (d < best.d) best = { s: i / n, t: j / n, d };
3510
+ }
3511
+ }
3512
+ let { s, t } = best;
3513
+ for (let k = 0; k < 12; k++) {
3514
+ const h = 1e-5;
3515
+ const q2 = evalWarpMesh(m, s, t);
3516
+ const qs = evalWarpMesh(m, s + h, t);
3517
+ const qt = evalWarpMesh(m, s, t + h);
3518
+ const a = (qs.x - q2.x) / h;
3519
+ const b = (qt.x - q2.x) / h;
3520
+ const c = (qs.y - q2.y) / h;
3521
+ const d = (qt.y - q2.y) / h;
3522
+ const det = a * d - b * c;
3523
+ if (Math.abs(det) < 1e-12) break;
3524
+ const ex = p.x - q2.x;
3525
+ const ey = p.y - q2.y;
3526
+ s = Math.min(1, Math.max(0, s + (d * ex - b * ey) / det));
3527
+ t = Math.min(1, Math.max(0, t + (a * ey - c * ex) / det));
3528
+ }
3529
+ const q = evalWarpMesh(m, s, t);
3530
+ return { s, t, distance: Math.hypot(q.x - p.x, q.y - p.y) };
3531
+ }
3532
+ function smoothLines(m, i0, i1, j0, j1) {
3533
+ const nx = warpMeshColumns(m);
3534
+ i1 = Math.min(i1, nx);
3535
+ j1 = Math.min(j1, warpMeshRows(m));
3536
+ const triples = [];
3537
+ for (let a = 1; a < m.us.length - 1; a++) {
3538
+ if (3 * a >= i0 && 3 * a < i1)
3539
+ for (let j = j0; j < j1; j++) triples.push([j * nx + 3 * a - 1, j * nx + 3 * a, j * nx + 3 * a + 1, m.us[a] - m.us[a - 1], m.us[a + 1] - m.us[a]]);
3540
+ }
3541
+ for (let b = 1; b < m.vs.length - 1; b++) {
3542
+ if (3 * b >= j0 && 3 * b < j1)
3543
+ for (let i = i0; i < i1; i++) triples.push([(3 * b - 1) * nx + i, 3 * b * nx + i, (3 * b + 1) * nx + i, m.vs[b] - m.vs[b - 1], m.vs[b + 1] - m.vs[b]]);
3544
+ }
3545
+ for (const [l, c, r, hl, hr] of triples) {
3546
+ const pl = m.points[l];
3547
+ const pc = m.points[c];
3548
+ const pr = m.points[r];
3549
+ const tx = ((pc.x - pl.x) / hl + (pr.x - pc.x) / hr) / 2;
3550
+ const ty = ((pc.y - pl.y) / hl + (pr.y - pc.y) / hr) / 2;
3551
+ m.points[l] = { x: pc.x - tx * hl, y: pc.y - ty * hl };
3552
+ m.points[r] = { x: pc.x + tx * hr, y: pc.y + ty * hr };
3553
+ }
3554
+ }
3555
+ function dragWarpMeshPoint(base, index, d) {
3556
+ if (index < 0 || index >= base.points.length || !Number.isFinite(d.x) || !Number.isFinite(d.y)) return base;
3557
+ const out = { us: base.us.slice(), vs: base.vs.slice(), points: base.points.slice() };
3558
+ const nx = warpMeshColumns(base);
3559
+ const ny = warpMeshRows(base);
3560
+ const i = index % nx;
3561
+ const j = Math.floor(index / nx);
3562
+ const shift = (ii, jj, v2) => {
3563
+ if (ii < 0 || jj < 0 || ii >= nx || jj >= ny) return;
3564
+ const p = out.points[jj * nx + ii];
3565
+ out.points[jj * nx + ii] = { x: p.x + v2.x, y: p.y + v2.y };
3566
+ };
3567
+ const span = (knots, k) => k > 0 && k + 1 < knots.length ? [knots[k] - knots[k - 1], knots[k + 1] - knots[k]] : null;
3568
+ const ri = i % 3;
3569
+ const rj = j % 3;
3570
+ if (ri === 0 && rj === 0) {
3571
+ for (let dj = -1; dj <= 1; dj++) for (let di = -1; di <= 1; di++) shift(i + di, j + dj, d);
3572
+ } else if (ri === 0) {
3573
+ for (let di = -1; di <= 1; di++) shift(i + di, j, d);
3574
+ const sp = span(base.vs, Math.floor(j / 3) + (rj === 2 ? 1 : 0));
3575
+ if (sp) {
3576
+ const [other, k] = rj === 1 ? [j - 2, sp[0] / sp[1]] : [j + 2, sp[1] / sp[0]];
3577
+ for (let di = -1; di <= 1; di++) shift(i + di, other, { x: -d.x * k, y: -d.y * k });
3578
+ }
3579
+ } else if (rj === 0) {
3580
+ for (let dj = -1; dj <= 1; dj++) shift(i, j + dj, d);
3581
+ const sp = span(base.us, Math.floor(i / 3) + (ri === 2 ? 1 : 0));
3582
+ if (sp) {
3583
+ const [other, k] = ri === 1 ? [i - 2, sp[0] / sp[1]] : [i + 2, sp[1] / sp[0]];
3584
+ for (let dj = -1; dj <= 1; dj++) shift(other, j + dj, { x: -d.x * k, y: -d.y * k });
3585
+ }
3586
+ } else shift(i, j, d);
3587
+ return out;
3588
+ }
3589
+ function pullWarpMesh(base, s, t, d) {
3590
+ const BORDER_ZONE = 0.12;
3591
+ const REACH = 1.8;
3592
+ if (!Number.isFinite(d.x) || !Number.isFinite(d.y)) return base;
3593
+ const m = { us: base.us.slice(), vs: base.vs.slice(), points: base.points.slice() };
3594
+ const cols = m.us.length - 1;
3595
+ const rows = m.vs.length - 1;
3596
+ const [pi, a] = locate(m.us, s);
3597
+ const [pj, b] = locate(m.vs, t);
3598
+ const ba = bernstein(a);
3599
+ const bb = bernstein(b);
3600
+ const nx = warpMeshColumns(m);
3601
+ const ny = warpMeshRows(m);
3602
+ const anchor = (ai, aj) => base.points[3 * aj * nx + 3 * ai] ?? { x: 0, y: 0 };
3603
+ const at0 = evalWarpMesh(base, s, t);
3604
+ const target = { x: at0.x + d.x, y: at0.y + d.y };
3605
+ let size = 1;
3606
+ for (const k of ["x", "y"]) {
3607
+ const vals = [anchor(pi, pj)[k], anchor(pi + 1, pj)[k], anchor(pi, pj + 1)[k], anchor(pi + 1, pj + 1)[k]];
3608
+ size = Math.max(size, Math.max(...vals) - Math.min(...vals));
3609
+ }
3610
+ const radius = REACH * size;
3611
+ const innerW = (ba[1] + ba[2]) * (bb[1] + bb[2]);
3612
+ const interior = Math.min(1, Math.max(0, innerW / 0.5625));
3613
+ const toBorder = Math.min(s, 1 - s, t, 1 - t);
3614
+ const nearBorder = Math.min(1, Math.max(0, 1 - toBorder / BORDER_ZONE));
3615
+ const meshCorner = (ai, aj) => (ai === 0 || ai === cols) && (aj === 0 || aj === rows);
3616
+ const onBorder = (ai, aj) => ai === 0 || ai === cols || aj === 0 || aj === rows;
3617
+ const reach = (ai, aj, wa, wb) => meshCorner(ai, aj) ? 0 : wa * wb * (onBorder(ai, aj) ? nearBorder : 1);
3618
+ const corner = [
3619
+ [pi, pj, reach(pi, pj, ba[0] + ba[1], bb[0] + bb[1])],
3620
+ [pi + 1, pj, reach(pi + 1, pj, ba[2] + ba[3], bb[0] + bb[1])],
3621
+ [pi, pj + 1, reach(pi, pj + 1, ba[0] + ba[1], bb[2] + bb[3])],
3622
+ [pi + 1, pj + 1, reach(pi + 1, pj + 1, ba[2] + ba[3], bb[2] + bb[3])]
3623
+ ];
3624
+ const share = new Array((cols + 1) * (rows + 1)).fill(0);
3625
+ for (let aj = 0; aj <= rows; aj++) {
3626
+ for (let ai = 0; ai <= cols; ai++) {
3627
+ const p = anchor(ai, aj);
3628
+ const x = Math.min(1, Math.max(0, Math.hypot(p.x - at0.x, p.y - at0.y) / radius));
3629
+ const fall = 0.5 * (1 + Math.cos(Math.PI * x));
3630
+ const edge = meshCorner(ai, aj) ? 0 : onBorder(ai, aj) ? nearBorder : 1;
3631
+ share[aj * (cols + 1) + ai] = fall * edge;
3632
+ }
3633
+ }
3634
+ for (const [ai, aj, w] of corner) share[aj * (cols + 1) + ai] = Math.max(share[aj * (cols + 1) + ai], (1 - interior) * w);
3635
+ const move = (idx, k, v2) => {
3636
+ const p = m.points[idx];
3637
+ m.points[idx] = { x: p.x + v2.x * k, y: p.y + v2.y * k };
3638
+ };
3639
+ for (let j = 0; j < ny; j++) {
3640
+ for (let i = 0; i < nx; i++) {
3641
+ const ai = Math.min(cols, Math.floor((i + 1) / 3));
3642
+ const aj = Math.min(rows, Math.floor((j + 1) / 3));
3643
+ move(j * nx + i, share[aj * (cols + 1) + ai], d);
3644
+ }
3645
+ }
3646
+ let norm = 0;
3647
+ for (const j of [1, 2]) for (const i of [1, 2]) norm += (ba[i] * bb[j]) ** 2;
3648
+ const cornerNorm = corner.reduce((acc, c) => acc + c[2] * c[2], 0);
3649
+ const innerPart = cornerNorm > 1e-12 ? Math.min(1, innerW / 0.15) : 1;
3650
+ const edgeHandles = [];
3651
+ for (const k of [1, 2]) {
3652
+ if (pi === 0) edgeHandles.push([(3 * pj + k) * nx + 3 * pi, ba[0] * bb[k]]);
3653
+ if (pi + 1 === cols) edgeHandles.push([(3 * pj + k) * nx + 3 * pi + 3, ba[3] * bb[k]]);
3654
+ if (pj === 0) edgeHandles.push([3 * pj * nx + 3 * pi + k, ba[k] * bb[0]]);
3655
+ if (pj + 1 === rows) edgeHandles.push([(3 * pj + 3) * nx + 3 * pi + k, ba[k] * bb[3]]);
3656
+ }
3657
+ const edgeNorm = edgeHandles.reduce((acc, e) => acc + e[1] * e[1], 0);
3658
+ const edgePart = edgeNorm > 1e-12 ? nearBorder : 0;
3659
+ const innerShare = (1 - edgePart) * innerPart;
3660
+ const cornerShare = (1 - edgePart) * (1 - innerPart);
3661
+ for (let iter = 0; iter < 60; iter++) {
3662
+ const now = evalWarpMesh(m, s, t);
3663
+ const rem = { x: target.x - now.x, y: target.y - now.y };
3664
+ if (Math.hypot(rem.x, rem.y) < 1e-9) break;
3665
+ if (innerShare > 0 && norm > 0) for (const j of [1, 2]) for (const i of [1, 2]) move((3 * pj + j) * nx + 3 * pi + i, ba[i] * bb[j] / norm * innerShare, rem);
3666
+ if (edgePart > 0) for (const [idx, w] of edgeHandles) move(idx, w / edgeNorm * edgePart, rem);
3667
+ if (cornerShare > 0 && cornerNorm > 0) {
3668
+ for (const [ai, aj, w] of corner) {
3669
+ const k = w / cornerNorm * cornerShare;
3670
+ for (let dj = -1; dj <= 1; dj++) {
3671
+ for (let di = -1; di <= 1; di++) {
3672
+ const i = 3 * ai + di;
3673
+ const j = 3 * aj + dj;
3674
+ if (i >= 0 && j >= 0 && i < nx && j < ny) move(j * nx + i, k, rem);
3675
+ }
3676
+ }
3677
+ }
3678
+ }
3679
+ for (let k = 0; k < 3; k++) smoothLines(m, Math.max(0, 3 * pi - 3), 3 * pi + 7, Math.max(0, 3 * pj - 3), 3 * pj + 7);
3680
+ }
3681
+ return m;
3682
+ }
3683
+ function warpMeshEditPoints(m) {
3684
+ const nx = warpMeshColumns(m);
3685
+ const ny = warpMeshRows(m);
3686
+ const anchors = [];
3687
+ const handles = [];
3688
+ for (let j = 0; j < ny; j++) {
3689
+ for (let i = 0; i < nx; i++) {
3690
+ const ri = i % 3;
3691
+ const rj = j % 3;
3692
+ if (ri === 0 && rj === 0) anchors.push(j * nx + i);
3693
+ else if (ri === 0) handles.push({ index: j * nx + i, anchor: (rj === 1 ? j - 1 : j + 1) * nx + i });
3694
+ else if (rj === 0) handles.push({ index: j * nx + i, anchor: j * nx + (ri === 1 ? i - 1 : i + 1) });
3695
+ }
3696
+ }
3697
+ return { anchors, handles };
3698
+ }
3699
+ function warpMeshGridCurves(m) {
3700
+ const nx = warpMeshColumns(m);
3701
+ const ny = warpMeshRows(m);
3702
+ const pt2 = (i, j) => m.points[j * nx + i];
3703
+ const out = [];
3704
+ for (let j = 0; j < ny; j += 3) for (let i = 0; i + 3 < nx; i += 3) out.push([pt2(i, j), pt2(i + 1, j), pt2(i + 2, j), pt2(i + 3, j)]);
3705
+ for (let i = 0; i < nx; i += 3) for (let j = 0; j + 3 < ny; j += 3) out.push([pt2(i, j), pt2(i, j + 1), pt2(i, j + 2), pt2(i, j + 3)]);
3706
+ return out;
3707
+ }
3708
+
3087
3709
  // src/vector/warp.ts
3088
3710
  function polylineAt(pts) {
3089
3711
  const acc = [0];
@@ -4203,12 +4825,12 @@ function insertAnchor(sp, segment, t) {
4203
4825
  const ia = segment;
4204
4826
  const ib = (segment + 1) % n;
4205
4827
  const seg = subpathSegment(sp, segment);
4206
- const [left2, right] = splitSegment(seg, t);
4207
- const mid = left2[left2.length - 1];
4828
+ const [left, right] = splitSegment(seg, t);
4829
+ const mid = left[left.length - 1];
4208
4830
  const anchor = { x: mid[0], y: mid[1] };
4209
4831
  if (seg.length === 4) {
4210
- anchors[ia].out = { x: left2[1][0], y: left2[1][1] };
4211
- anchor.in = { x: left2[2][0], y: left2[2][1] };
4832
+ anchors[ia].out = { x: left[1][0], y: left[1][1] };
4833
+ anchor.in = { x: left[2][0], y: left[2][1] };
4212
4834
  anchor.out = { x: right[1][0], y: right[1][1] };
4213
4835
  anchor.type = "smooth";
4214
4836
  anchors[ib].in = { x: right[2][0], y: right[2][1] };
@@ -4500,9 +5122,9 @@ function twistPaths(paths, angle, center) {
4500
5122
  };
4501
5123
  return paths.map((p) => {
4502
5124
  const out = [];
4503
- for (const sub5 of subsOf(p)) {
5125
+ for (const sub4 of subsOf(p)) {
4504
5126
  const segs = [];
4505
- for (const seg of sub5.segs) {
5127
+ for (const seg of sub4.segs) {
4506
5128
  const cubic = seg.length === 2 ? [seg[0], seg[0], seg[1], seg[1]] : seg;
4507
5129
  const len2 = segmentLength(seg);
4508
5130
  const m = Math.min(64, Math.max(1, Math.ceil(Math.abs(a) * len2 / rmax / 0.15 + len2 / 50)));
@@ -4515,13 +5137,13 @@ function twistPaths(paths, angle, center) {
4515
5137
  segs.push([p0, [p0[0] + h1[0], p0[1] + h1[1]], [p3[0] + h2[0], p3[1] + h2[1]], p3]);
4516
5138
  }
4517
5139
  }
4518
- out.push({ segs, closed: sub5.closed });
5140
+ out.push({ segs, closed: sub4.closed });
4519
5141
  }
4520
5142
  return subsToPath(out);
4521
5143
  });
4522
5144
  }
4523
- function resample(sub5, m) {
4524
- const segs = sub5.segs;
5145
+ function resample(sub4, m) {
5146
+ const segs = sub4.segs;
4525
5147
  const n = segs.length;
4526
5148
  const lens = segs.map((s) => segmentLength(s));
4527
5149
  const out = [];
@@ -4530,7 +5152,7 @@ function resample(sub5, m) {
4530
5152
  for (let k = 0; k < m; k++) {
4531
5153
  if (k === 0) {
4532
5154
  const tout = startTangent(segs[j]);
4533
- const prev = sub5.closed || j > 0 ? (j + n - 1) % n : null;
5155
+ const prev = sub4.closed || j > 0 ? (j + n - 1) % n : null;
4534
5156
  let tan = tout;
4535
5157
  if (prev !== null) {
4536
5158
  const tin = endTangent(segs[prev]);
@@ -4543,7 +5165,7 @@ function resample(sub5, m) {
4543
5165
  }
4544
5166
  }
4545
5167
  }
4546
- if (!sub5.closed) {
5168
+ if (!sub4.closed) {
4547
5169
  const last = segs[n - 1];
4548
5170
  out.push({ p: last[last.length - 1], tan: endTangent(last), lenPrev: lens[n - 1] / m, lenNext: 0 });
4549
5171
  }
@@ -4571,14 +5193,14 @@ function zigzagPaths(paths, size, ridges, smooth = false) {
4571
5193
  const m = Math.min(1e3, Math.max(0, Math.round(Number.isFinite(ridges) ? ridges : 0))) + 1;
4572
5194
  return paths.map((p) => {
4573
5195
  const out = [];
4574
- for (const sub5 of subsOf(p)) {
4575
- const s = resample(sub5, m);
5196
+ for (const sub4 of subsOf(p)) {
5197
+ const s = resample(sub4, m);
4576
5198
  const disp = s.map((x, i) => {
4577
5199
  const n = perp2(x.tan);
4578
5200
  const d = i % 2 === 0 ? size : -size;
4579
5201
  return [n[0] * d, n[1] * d];
4580
5202
  });
4581
- const e = emit(s, disp, sub5.closed, smooth, 0.36);
5203
+ const e = emit(s, disp, sub4.closed, smooth, 0.36);
4582
5204
  if (e) out.push(e);
4583
5205
  }
4584
5206
  return subsToPath(out);
@@ -4617,8 +5239,8 @@ function wigglePaths(paths, w) {
4617
5239
  let idx = 0;
4618
5240
  return paths.map((p) => {
4619
5241
  const out = [];
4620
- for (const sub5 of subsOf(p)) {
4621
- const s = resample(sub5, m);
5242
+ for (const sub4 of subsOf(p)) {
5243
+ const s = resample(sub4, m);
4622
5244
  const disp = s.map(() => {
4623
5245
  const i = BigInt(idx);
4624
5246
  const ox = noise(seed, i * 2n, t + idx * 0.37);
@@ -4626,7 +5248,7 @@ function wigglePaths(paths, w) {
4626
5248
  idx++;
4627
5249
  return [(sx * corr + ox * (1 - corr)) * w.size, (sy * corr + oy * (1 - corr)) * w.size];
4628
5250
  });
4629
- const e = emit(s, disp, sub5.closed, w.smooth, 1 / 3);
5251
+ const e = emit(s, disp, sub4.closed, w.smooth, 1 / 3);
4630
5252
  if (e) out.push(e);
4631
5253
  }
4632
5254
  return subsToPath(out);
@@ -4667,1885 +5289,6 @@ function pathsCenter(paths) {
4667
5289
  return b ? { x: (b.minX + b.maxX) / 2, y: (b.minY + b.maxY) / 2 } : { x: 0, y: 0 };
4668
5290
  }
4669
5291
 
4670
- // src/vector/blend.ts
4671
- var lerpN = (a, b, t) => a + (b - a) * t;
4672
- var lerpP = (a, b, t) => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
4673
- var toP = (v2) => [v2.x, v2.y];
4674
- var mapP = (m, p) => [m[0] * p[0] + m[2] * p[1] + m[4], m[1] * p[0] + m[3] * p[1] + m[5]];
4675
- var curvesOf = (c) => Math.max(0, (c.pts.length - 1) / 3) | 0;
4676
- function subpathToMorphContour(sp, m = IDENTITY_MATRIX) {
4677
- const n = sp.anchors.length;
4678
- if (!n) return null;
4679
- const first = mapP(m, toP(sp.anchors[0]));
4680
- const pts = [first];
4681
- const count = n < 2 ? 0 : sp.closed ? n : n - 1;
4682
- for (let i = 0; i < count; i++) {
4683
- const a = sp.anchors[i];
4684
- const b = sp.anchors[(i + 1) % n];
4685
- const pa = toP(a);
4686
- const pb = toP(b);
4687
- const straight = (!a.out || a.out.x === a.x && a.out.y === a.y) && (!b.in || b.in.x === b.x && b.in.y === b.y);
4688
- const c1 = straight ? lerpP(pa, pb, 1 / 3) : toP(a.out ?? a);
4689
- const c2 = straight ? lerpP(pa, pb, 2 / 3) : toP(b.in ?? b);
4690
- pts.push(mapP(m, c1), mapP(m, c2), i === count - 1 && sp.closed ? first : mapP(m, pb));
4691
- }
4692
- return { closed: sp.closed && count > 0, pts };
4693
- }
4694
- function isStraight(p0, p1, p2, p3) {
4695
- const dx = p3[0] - p0[0];
4696
- const dy = p3[1] - p0[1];
4697
- const len2 = Math.hypot(dx, dy);
4698
- const tol = Math.max(1e-7, len2 * 1e-7);
4699
- if (len2 < 1e-12) return Math.hypot(p1[0] - p0[0], p1[1] - p0[1]) < tol && Math.hypot(p2[0] - p0[0], p2[1] - p0[1]) < tol;
4700
- const off = (p) => Math.abs((p[0] - p0[0]) * dy - (p[1] - p0[1]) * dx) / len2;
4701
- const along2 = (p) => ((p[0] - p0[0]) * dx + (p[1] - p0[1]) * dy) / (len2 * len2);
4702
- const u1 = along2(p1);
4703
- const u2 = along2(p2);
4704
- return off(p1) < tol && off(p2) < tol && u1 >= -1e-9 && u1 <= 1 + 1e-9 && u2 >= -1e-9 && u2 <= 1 + 1e-9;
4705
- }
4706
- function morphContourToSubpath(c, m = IDENTITY_MATRIX, closed = c.closed) {
4707
- const pts = isIdentityMatrix(m) ? c.pts : c.pts.map((p) => mapP(m, p));
4708
- const curves = curvesOf(c);
4709
- const dropLast = closed && c.closed && curves > 0;
4710
- const count = dropLast ? curves : curves + 1;
4711
- const anchors = [];
4712
- for (let k = 0; k < count; k++) anchors.push({ x: pts[3 * k][0], y: pts[3 * k][1] });
4713
- for (let k = 0; k < curves; k++) {
4714
- const p0 = pts[3 * k];
4715
- const p1 = pts[3 * k + 1];
4716
- const p2 = pts[3 * k + 2];
4717
- const p3 = pts[3 * k + 3];
4718
- if (isStraight(p0, p1, p2, p3)) continue;
4719
- anchors[k].out = { x: p1[0], y: p1[1] };
4720
- anchors[(k + 1) % count].in = { x: p2[0], y: p2[1] };
4721
- }
4722
- for (const a of anchors) {
4723
- const type = inferAnchorType(a);
4724
- if (type !== "corner") a.type = type;
4725
- }
4726
- const isClosed = closed && curves > 0;
4727
- return { anchors: dropCollinear(anchors, isClosed), closed: isClosed };
4728
- }
4729
- function dropCollinear(anchors, closed) {
4730
- const out = anchors.slice();
4731
- const min = closed ? 3 : 2;
4732
- let i = closed ? 0 : 1;
4733
- while (out.length > min && i < out.length - (closed ? 0 : 1)) {
4734
- const n = out.length;
4735
- const a = out[(i - 1 + n) % n];
4736
- const b = out[i];
4737
- const c = out[(i + 1) % n];
4738
- const plain2 = !b.in && !b.out && !a.out && !c.in;
4739
- const ux = b.x - a.x;
4740
- const uy = b.y - a.y;
4741
- const vx = c.x - b.x;
4742
- const vy = c.y - b.y;
4743
- const len2 = Math.hypot(ux, uy) + Math.hypot(vx, vy);
4744
- if (plain2 && Math.abs(ux * vy - uy * vx) <= 1e-9 * Math.max(1, len2 * len2) && ux * vx + uy * vy >= 0) out.splice(i, 1);
4745
- else i++;
4746
- }
4747
- return out;
4748
- }
4749
- var segOf = (c, k) => c.pts.slice(3 * k, 3 * k + 4);
4750
- function refineMorphContour(c, segments) {
4751
- const have = curvesOf(c);
4752
- if (have === 0) return { contour: { closed: c.closed, pts: Array.from({ length: 1 + 3 * segments }, () => [c.pts[0][0], c.pts[0][1]]) }, anchors: [0] };
4753
- const identity = Array.from({ length: c.closed ? have : have + 1 }, (_, i) => i);
4754
- if (have >= segments) return { contour: c, anchors: identity };
4755
- const segs = Array.from({ length: have }, (_, k) => segOf(c, k));
4756
- const lens = segs.map((s) => segmentLength(s));
4757
- const sum = lens.reduce((a, b) => a + b, 0);
4758
- const extra = segments - have;
4759
- const want = lens.map((l) => sum > 1e-12 ? l / sum * extra : extra / have);
4760
- const parts = want.map((w) => 1 + Math.floor(w));
4761
- let left2 = segments - parts.reduce((a, b) => a + b, 0);
4762
- const frac = want.map((w) => w - Math.floor(w));
4763
- const order = parts.map((_, i) => i).sort((a, b) => Math.abs(frac[b] - frac[a]) > 1e-9 ? frac[b] - frac[a] : a - b);
4764
- for (let i = 0; left2 > 0; i = (i + 1) % order.length, left2--) parts[order[i]]++;
4765
- const pts = [c.pts[0]];
4766
- const anchors = [0];
4767
- let at2 = 0;
4768
- segs.forEach((seg, k) => {
4769
- const pieces = parts[k];
4770
- let rest = seg.slice();
4771
- let t0 = 0;
4772
- for (let j = 1; j < pieces; j++) {
4773
- const t = segmentParamAtLength(seg, lens[k] * j / pieces, lens[k]);
4774
- const u = Math.min(1, Math.max(0, (t - t0) / (1 - t0 || 1)));
4775
- const [l, r] = splitSegment(rest, u);
4776
- pts.push(l[1], l[2], l[3]);
4777
- rest = r;
4778
- t0 = t;
4779
- }
4780
- pts.push(rest[1], rest[2], k === have - 1 && c.closed ? c.pts[0] : rest[3]);
4781
- at2 += pieces;
4782
- if (k < have - 1 || !c.closed) anchors.push(at2);
4783
- });
4784
- return { contour: { closed: c.closed, pts }, anchors };
4785
- }
4786
- function reverseMorphContour(c) {
4787
- return { closed: c.closed, pts: c.pts.slice().reverse() };
4788
- }
4789
- function turnMorphContour(c, s) {
4790
- const n = curvesOf(c);
4791
- if (!c.closed || n === 0) return c;
4792
- const k = (s % n + n) % n;
4793
- if (k === 0) return c;
4794
- const body = c.pts.slice(1);
4795
- return { closed: true, pts: [c.pts[3 * k], ...body.slice(3 * k), ...body.slice(0, 3 * k)] };
4796
- }
4797
- function anchorPoints(c) {
4798
- const n = curvesOf(c);
4799
- const count = c.closed ? n : n + 1;
4800
- return Array.from({ length: Math.max(1, count) }, (_, k) => c.pts[3 * k]);
4801
- }
4802
- function polygonArea(pts) {
4803
- let s = 0;
4804
- for (let i = 0; i < pts.length; i++) {
4805
- const a = pts[i];
4806
- const b = pts[(i + 1) % pts.length];
4807
- s += a[0] * b[1] - b[0] * a[1];
4808
- }
4809
- return s / 2;
4810
- }
4811
- function frame(v2) {
4812
- const n = Math.max(1, v2.length);
4813
- let cx = 0;
4814
- let cy = 0;
4815
- for (const p of v2) {
4816
- cx += p[0];
4817
- cy += p[1];
4818
- }
4819
- cx /= n;
4820
- cy /= n;
4821
- let s = 0;
4822
- for (const p of v2) s += (p[0] - cx) ** 2 + (p[1] - cy) ** 2;
4823
- return { c: [cx, cy], r: Math.max(1e-9, Math.sqrt(s / n)) };
4824
- }
4825
- var RBINS = 5;
4826
- var ABINS = 12;
4827
- var TURN_WEIGHT = 0.1;
4828
- function shapeContexts(v2, closed) {
4829
- const { r } = frame(v2);
4830
- const n = v2.length;
4831
- return v2.map((p, i) => {
4832
- const prev = v2[closed ? (i - 1 + n) % n : Math.max(0, i - 1)];
4833
- const next = v2[closed ? (i + 1) % n : Math.min(n - 1, i + 1)];
4834
- const dir = Math.atan2(next[1] - prev[1], next[0] - prev[0]);
4835
- const h = new Float64Array(RBINS * ABINS);
4836
- let total = 0;
4837
- for (let j = 0; j < n; j++) {
4838
- if (i === j) continue;
4839
- const dx = v2[j][0] - p[0];
4840
- const dy = v2[j][1] - p[1];
4841
- const d = Math.hypot(dx, dy) / r;
4842
- const lr = (Math.log2(Math.max(d, 1e-6)) + 3) / 4 * RBINS;
4843
- if (!(lr >= 0 && lr < RBINS)) continue;
4844
- let ang = Math.atan2(dy, dx) - dir;
4845
- ang = (ang % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI);
4846
- h[Math.floor(lr) * ABINS + Math.min(ABINS - 1, Math.floor(ang / (2 * Math.PI) * ABINS))] += 1;
4847
- total++;
4848
- }
4849
- if (total > 0) for (let k = 0; k < h.length; k++) h[k] /= total;
4850
- return h;
4851
- });
4852
- }
4853
- function chi2(a, b) {
4854
- let s = 0;
4855
- for (let k = 0; k < a.length; k++) {
4856
- const t = a[k] + b[k];
4857
- if (t > 1e-12) s += (a[k] - b[k]) * (a[k] - b[k]) / t;
4858
- }
4859
- return s / 2;
4860
- }
4861
- function bestStart(fixed, free, useShapeContext) {
4862
- const fa = anchorPoints(fixed);
4863
- const ga = anchorPoints(free);
4864
- const n = ga.length;
4865
- const ff = frame(fa);
4866
- const gf = frame(ga);
4867
- const fn = fa.map((p) => [(p[0] - ff.c[0]) / ff.r, (p[1] - ff.c[1]) / ff.r]);
4868
- const gn = ga.map((p) => [(p[0] - gf.c[0]) / gf.r, (p[1] - gf.c[1]) / gf.r]);
4869
- const fsc = useShapeContext ? shapeContexts(fa, fixed.closed) : null;
4870
- const gsc = useShapeContext ? shapeContexts(ga, free.closed) : null;
4871
- const m = Math.max(1, fn.length);
4872
- const cost = (s) => {
4873
- let dot3 = 0;
4874
- let cross2 = 0;
4875
- let sc = 0;
4876
- for (let i = 0; i < fn.length; i++) {
4877
- const j = free.closed ? (i + s) % n : i;
4878
- const p = fn[i];
4879
- const q = gn[j];
4880
- dot3 += p[0] * q[0] + p[1] * q[1];
4881
- cross2 += p[0] * q[1] - p[1] * q[0];
4882
- if (fsc && gsc) sc += chi2(fsc[i], gsc[j]);
4883
- }
4884
- const residual = Math.max(0, 1 - (dot3 * dot3 + cross2 * cross2) / (m * m));
4885
- const turn = 1 - Math.cos(Math.atan2(cross2, dot3));
4886
- return residual + TURN_WEIGHT * turn + sc / m;
4887
- };
4888
- if (!free.closed) return { start: 0, cost: cost(0) };
4889
- const stride = n > 96 ? Math.ceil(n / 48) : 1;
4890
- let best = { start: 0, cost: Infinity };
4891
- for (let s = 0; s < n; s += stride) {
4892
- const c = cost(s);
4893
- if (c < best.cost - 1e-12) best = { start: s, cost: c };
4894
- }
4895
- if (stride > 1) {
4896
- const s0 = best.start;
4897
- for (let d = 1; d < stride; d++)
4898
- for (const s of [(s0 + d) % n, (s0 - d + n) % n]) {
4899
- const c = cost(s);
4900
- if (c < best.cost - 1e-12) best = { start: s, cost: c };
4901
- }
4902
- }
4903
- return best;
4904
- }
4905
- function placeIn(c, from, to) {
4906
- const b = unionBounds([boundsOfPoints(c.pts)]);
4907
- const p = b ? [b.x + b.width / 2, b.y + b.height / 2] : c.pts[0];
4908
- if (!from || !to) return p;
4909
- const fx = from.width > 0 ? (p[0] - from.x) / from.width : 0.5;
4910
- const fy = from.height > 0 ? (p[1] - from.y) / from.height : 0.5;
4911
- return [to.x + to.width * fx, to.y + to.height * fy];
4912
- }
4913
- function boundsOfPoints(pts) {
4914
- if (!pts.length) return null;
4915
- let x0 = Infinity;
4916
- let y0 = Infinity;
4917
- let x1 = -Infinity;
4918
- let y1 = -Infinity;
4919
- for (const p of pts) {
4920
- x0 = Math.min(x0, p[0]);
4921
- y0 = Math.min(y0, p[1]);
4922
- x1 = Math.max(x1, p[0]);
4923
- y1 = Math.max(y1, p[1]);
4924
- }
4925
- return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
4926
- }
4927
- function correspondMorphContours(a, b, options = {}) {
4928
- const minSeg = Math.max(1, Math.round(options.minSegments ?? 16));
4929
- const maxSeg = Math.max(minSeg, Math.round(options.maxSegments ?? 400));
4930
- const spacing = options.spacing && options.spacing > 0 ? options.spacing : null;
4931
- const useSC = options.shapeContext !== false;
4932
- const match = options.matchStart !== false;
4933
- const ba = boundsOfPoints(a.flatMap((c) => c.pts));
4934
- const bb = boundsOfPoints(b.flatMap((c) => c.pts));
4935
- const contourLength = (c) => {
4936
- let l = 0;
4937
- for (let k = 0; k < curvesOf(c); k++) l += segmentLength(segOf(c, k));
4938
- return l;
4939
- };
4940
- const pairs = [];
4941
- const [sa, sb] = options.starts ?? [];
4942
- for (let k = 0; k < Math.max(a.length, b.length); k++) {
4943
- const ca = a[k];
4944
- const cb = b[k];
4945
- const explicitA = k === 0 && sa !== null && sa !== void 0 ? sa : null;
4946
- const explicitB = k === 0 && sb !== null && sb !== void 0 ? sb : null;
4947
- const counts = [ca ? curvesOf(ca) : 0, cb ? curvesOf(cb) : 0];
4948
- const longest = Math.max(ca ? contourLength(ca) : 0, cb ? contourLength(cb) : 0);
4949
- let n = Math.max(counts[0], counts[1], minSeg, spacing ? Math.ceil(longest / spacing) : 0);
4950
- n = Math.max(counts[0], counts[1], Math.min(n, maxSeg));
4951
- const point = (c, from, to) => {
4952
- const p = placeIn(c, from, to);
4953
- return { closed: c.closed, pts: Array.from({ length: 1 + 3 * n }, () => [p[0], p[1]]) };
4954
- };
4955
- if (ca && cb) {
4956
- const ra = refineMorphContour(ca, n);
4957
- const rb = refineMorphContour(cb, n);
4958
- pairs.push({
4959
- x: ra.contour,
4960
- y: rb.contour,
4961
- point: false,
4962
- startX: explicitA === null ? null : ra.anchors[explicitA] ?? null,
4963
- startY: explicitB === null ? null : explicitB === rb.anchors.length - 1 && !cb.closed ? -1 : rb.anchors[explicitB] ?? null
4964
- });
4965
- if (explicitA !== null && !ca.closed && explicitA === ra.anchors.length - 1 && explicitA > 0) pairs[pairs.length - 1].startX = -1;
4966
- } else if (ca) pairs.push({ x: refineMorphContour(ca, n).contour, y: point(ca, ba, bb), point: true, startX: null, startY: null });
4967
- else if (cb) pairs.push({ x: point(cb, bb, ba), y: refineMorphContour(cb, n).contour, point: true, startX: null, startY: null });
4968
- }
4969
- const startAt = (c, s) => {
4970
- if (s === null) return c;
4971
- if (s === -1) return reverseMorphContour(c);
4972
- return c.closed ? turnMorphContour(c, s) : c;
4973
- };
4974
- const explicit = pairs.length > 0 && (pairs[0].startX !== null || pairs[0].startY !== null);
4975
- const ref = pairs.find((p) => !p.point && p.x.closed && p.y.closed);
4976
- const fixedBack = ref ? Math.sign(polygonArea(anchorPoints(ref.x))) !== Math.sign(polygonArea(anchorPoints(ref.y))) && Math.abs(polygonArea(anchorPoints(ref.y))) > 1e-12 : explicit ? false : null;
4977
- let best = null;
4978
- for (const back of fixedBack === null ? [false, true] : [fixedBack]) {
4979
- const xs = [];
4980
- const ys = [];
4981
- let cost = 0;
4982
- pairs.forEach((p, k) => {
4983
- let x = k === 0 ? startAt(p.x, p.startX) : p.x;
4984
- let y = k === 0 ? startAt(p.y, p.startY) : p.y;
4985
- if (back) y = reverseMorphContour(y);
4986
- if (p.point) {
4987
- xs.push(x);
4988
- ys.push(y);
4989
- return;
4990
- }
4991
- const pinned = k === 0 && explicit;
4992
- const turnX = !y.closed && x.closed;
4993
- if (match && !pinned && (y.closed || turnX)) {
4994
- const r = turnX ? bestStart(y, x, useSC) : bestStart(x, y, useSC);
4995
- if (turnX) x = turnMorphContour(x, r.start);
4996
- else y = turnMorphContour(y, r.start);
4997
- cost += r.cost;
4998
- } else cost += bestStart(x, { ...y, closed: false }, useSC).cost;
4999
- xs.push(x);
5000
- ys.push(y);
5001
- });
5002
- if (!best || cost < best.cost - 1e-9) best = { xs, ys, cost, back };
5003
- }
5004
- return best ? { a: best.xs, b: best.ys, reversed: best.back } : { a: [], b: [], reversed: false };
5005
- }
5006
- function morphPathsCross(a, b) {
5007
- let count = 0;
5008
- const d = (p, q, r) => (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0]);
5009
- for (let k = 0; k < Math.min(a.length, b.length); k++) {
5010
- const pa = anchorPoints(a[k]);
5011
- const pb = anchorPoints(b[k]);
5012
- const n = Math.min(pa.length, pb.length);
5013
- for (let i = 0; i < n; i++)
5014
- for (let j = i + 1; j < n; j++) {
5015
- const d1 = d(pa[j], pb[j], pa[i]);
5016
- const d2 = d(pa[j], pb[j], pb[i]);
5017
- const d3 = d(pa[i], pb[i], pa[j]);
5018
- const d4 = d(pa[i], pb[i], pb[j]);
5019
- if (d1 * d2 < 0 && d3 * d4 < 0) count++;
5020
- }
5021
- }
5022
- return count;
5023
- }
5024
- function procrustes(a, b) {
5025
- const pa = a.flatMap(anchorPoints);
5026
- const pb = b.flatMap(anchorPoints);
5027
- const ca = frame(pa).c;
5028
- const cb = frame(pb).c;
5029
- let ss = 0;
5030
- let dot3 = 0;
5031
- let cross2 = 0;
5032
- for (let i = 0; i < Math.min(pa.length, pb.length); i++) {
5033
- const p = [pa[i][0] - ca[0], pa[i][1] - ca[1]];
5034
- const q = [pb[i][0] - cb[0], pb[i][1] - cb[1]];
5035
- ss += p[0] * p[0] + p[1] * p[1];
5036
- dot3 += p[0] * q[0] + p[1] * q[1];
5037
- cross2 += p[0] * q[1] - p[1] * q[0];
5038
- }
5039
- return { ca, cb, theta: Math.atan2(cross2, dot3), s: ss > 1e-12 ? Math.hypot(dot3, cross2) / ss : 1 };
5040
- }
5041
- function interpolateMorphContours(a, b, u, options = {}) {
5042
- const w = options.linear ? 0 : Math.min(1, Math.max(0, options.rigidity ?? 1));
5043
- const sim = w > 0 ? options.similarity ?? procrustes(a, b) : null;
5044
- const rot = (p, ang, k) => {
5045
- const c = Math.cos(ang);
5046
- const s = Math.sin(ang);
5047
- return [k * (c * p[0] - s * p[1]), k * (s * p[0] + c * p[1])];
5048
- };
5049
- const thetaU = sim ? sim.theta * u : 0;
5050
- const sU = sim ? Math.max(1e-9, sim.s) ** u : 1;
5051
- const cU = sim ? lerpP(sim.ca, sim.cb, u) : [0, 0];
5052
- return a.map((ca, k) => {
5053
- const cb = b[k];
5054
- const pts = ca.pts.map((p, i) => {
5055
- const q = cb.pts[i] ?? p;
5056
- const linear = lerpP(p, q, u);
5057
- if (!sim) return linear;
5058
- const d = [p[0] - sim.ca[0], p[1] - sim.ca[1]];
5059
- const full = rot(d, sim.theta, sim.s);
5060
- const resid = [q[0] - (full[0] + sim.cb[0]), q[1] - (full[1] + sim.cb[1])];
5061
- const part = rot(d, thetaU, sU);
5062
- const rigid = [part[0] + cU[0] + resid[0] * u, part[1] + cU[1] + resid[1] * u];
5063
- return lerpP(linear, rigid, w);
5064
- });
5065
- return { closed: ca.closed && cb.closed, pts };
5066
- });
5067
- }
5068
- function interpolateRigidMatrix(a, b, t) {
5069
- const decompose = (m) => {
5070
- const sx2 = Math.hypot(m[0], m[1]);
5071
- const ang2 = sx2 > 1e-12 ? Math.atan2(m[1], m[0]) : 0;
5072
- const c2 = Math.cos(ang2);
5073
- const s2 = Math.sin(ang2);
5074
- return { e: m[4], f: m[5], ang: ang2, sx: sx2, sh: c2 * m[2] + s2 * m[3], sy: -s2 * m[2] + c2 * m[3] };
5075
- };
5076
- const p = decompose(a);
5077
- const q = decompose(b);
5078
- let turn = q.ang - p.ang;
5079
- turn = ((turn + Math.PI) % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI) - Math.PI;
5080
- const ang = p.ang + turn * t;
5081
- const sx = lerpN(p.sx, q.sx, t);
5082
- const sh = lerpN(p.sh, q.sh, t);
5083
- const sy = lerpN(p.sy, q.sy, t);
5084
- const c = Math.cos(ang);
5085
- const s = Math.sin(ang);
5086
- return [c * sx, s * sx, c * sh - s * sy, s * sh + c * sy, lerpN(p.e, q.e, t), lerpN(p.f, q.f, t)];
5087
- }
5088
- function interpolateVectorColor(a, b, t) {
5089
- if (t <= 0) return a;
5090
- if (t >= 1) return b;
5091
- return mixColorsOklab(a, b, t) ?? (t < 0.5 ? a : b);
5092
- }
5093
- function resampleGradientStops(g, offsets) {
5094
- return offsets.map((offset) => {
5095
- const s = sampleVectorGradient(g, offset);
5096
- return s.opacity < 1 ? { offset, color: s.color, opacity: Math.round(s.opacity * 1e4) / 1e4 } : { offset, color: s.color };
5097
- });
5098
- }
5099
- function lerpAngle(a, b, t) {
5100
- const d = ((b - a + 180) % 360 + 360) % 360 - 180;
5101
- return a + d * t;
5102
- }
5103
- var lerpPoint = (a, b, t) => ({ x: lerpN(a.x, b.x, t), y: lerpN(a.y, b.y, t) });
5104
- var sameColourModel = (a, b) => (a.interpolation ?? "srgb") === (b.interpolation ?? "srgb") && (a.smoothness ?? 0) === (b.smoothness ?? 0);
5105
- function lerpStops(a, b, t) {
5106
- let stopsA = sortedVectorGradientStops(a);
5107
- let stopsB = sortedVectorGradientStops(b);
5108
- const resampled = stopsA.length !== stopsB.length || !sameColourModel(a, b);
5109
- if (resampled) {
5110
- const offs = [...expandVectorGradientStops(a), ...expandVectorGradientStops(b), ...stopsA, ...stopsB].map((s) => s.offset).filter(Number.isFinite).sort((x, y) => x - y);
5111
- const common = offs.filter((o, i) => i === 0 || o - offs[i - 1] > 1e-4);
5112
- stopsA = resampleGradientStops(a, common);
5113
- stopsB = resampleGradientStops(b, common);
5114
- }
5115
- const stops = stopsA.map((x, i) => {
5116
- const y = stopsB[i];
5117
- const opacity = lerpN(x.opacity ?? 1, y.opacity ?? 1, t);
5118
- const stop = { offset: lerpN(x.offset, y.offset, t), color: interpolateVectorColor(x.color, y.color, t) };
5119
- if (opacity < 1) stop.opacity = opacity;
5120
- const mid = lerpN(x.midpoint ?? 0.5, y.midpoint ?? 0.5, t);
5121
- if (Math.abs(mid - 0.5) > 1e-6) stop.midpoint = mid;
5122
- return stop;
5123
- });
5124
- return { stops, resampled };
5125
- }
5126
- function lerpGradient(a, b, t) {
5127
- if (a.type !== b.type) return null;
5128
- const { stops, resampled } = lerpStops(a, b, t);
5129
- const near2 = t < 0.5 ? a : b;
5130
- const out = { type: a.type, stops };
5131
- if (!resampled) {
5132
- if (a.interpolation && a.interpolation !== "srgb") out.interpolation = a.interpolation;
5133
- if (a.smoothness) out.smoothness = a.smoothness;
5134
- }
5135
- if (near2.spread && near2.spread !== "pad") out.spread = near2.spread;
5136
- if (near2.strokeMode && near2.strokeMode !== "within") out.strokeMode = near2.strokeMode;
5137
- const ea = hasExplicitGradientGeometry(a);
5138
- const eb = hasExplicitGradientGeometry(b);
5139
- if (!ea && !eb) {
5140
- if (a.angle !== void 0 || b.angle !== void 0 || a.type === "linear" || a.type === "reflected") {
5141
- const fallback = a.type === "linear" || a.type === "reflected" ? 180 : 90;
5142
- out.angle = lerpAngle(a.angle ?? fallback, b.angle ?? fallback, t);
5143
- }
5144
- if (a.type !== "linear" && a.type !== "reflected") {
5145
- out.cx = lerpN(a.cx ?? 0.5, b.cx ?? 0.5, t);
5146
- out.cy = lerpN(a.cy ?? 0.5, b.cy ?? 0.5, t);
5147
- out.r = lerpN(a.r ?? 0.5, b.r ?? 0.5, t);
5148
- }
5149
- return out;
5150
- }
5151
- const pa = vectorGradientPoints(a);
5152
- const pb = vectorGradientPoints(b);
5153
- if (pa.units !== pb.units) {
5154
- const src = explicitVectorGradient(near2);
5155
- return { ...src, stops: out.stops, ...out.interpolation ? { interpolation: out.interpolation } : {}, ...out.smoothness ? { smoothness: out.smoothness } : {} };
5156
- }
5157
- out.start = lerpPoint(pa.start, pb.start, t);
5158
- out.end = lerpPoint(pa.end, pb.end, t);
5159
- out.width = lerpPoint(pa.width, pb.width, t);
5160
- out.units = pa.units;
5161
- if (a.type === "radial") {
5162
- if (pa.focal || pb.focal) out.focal = lerpPoint(pa.focal ?? pa.start, pb.focal ?? pb.start, t);
5163
- const fr = lerpN(pa.focalRadius, pb.focalRadius, t);
5164
- if (fr > 0) out.focalRadius = fr;
5165
- }
5166
- return out;
5167
- }
5168
- function solidLike(color, like) {
5169
- return { ...like, stops: like.stops.map((s) => color === null ? { offset: s.offset, color: s.color, opacity: 0 } : { offset: s.offset, color }) };
5170
- }
5171
- function interpolateVectorPaint(a, b, t) {
5172
- if (t <= 0) return a;
5173
- if (t >= 1) return b;
5174
- const pa = hasPaint(a);
5175
- const pb = hasPaint(b);
5176
- if (!pa && !pb) return t < 0.5 ? a : b;
5177
- if (typeof a === "string" && pa && typeof b === "string" && pb) return interpolateVectorColor(a, b, t);
5178
- if (!pa && typeof b === "string") return interpolateVectorColor("transparent", b, t);
5179
- if (!pb && typeof a === "string") return interpolateVectorColor(a, "transparent", t);
5180
- const ga = pa && isVectorGradient(a) ? a : null;
5181
- const gb = pb && isVectorGradient(b) ? b : null;
5182
- if (ga && gb) return lerpGradient(ga, gb, t) ?? (t < 0.5 ? a : b);
5183
- if (gb) return lerpGradient(solidLike(pa ? a : null, gb), gb, t) ?? b;
5184
- if (ga) return lerpGradient(ga, solidLike(pb ? b : null, ga), t) ?? a;
5185
- return t < 0.5 ? a : b;
5186
- }
5187
- function interpolateWidthProfiles(a, b, t) {
5188
- if (!a?.length && !b?.length) return null;
5189
- const at2 = [...a ?? [], ...b ?? [], { t: 0 }, { t: 1 }].map((p) => p.t).sort((x, y) => x - y);
5190
- const ts = at2.filter((v2, i) => i === 0 || v2 - at2[i - 1] > 1e-6);
5191
- return ts.map((pos) => {
5192
- const x = widthProfileAt(a, pos);
5193
- const y = widthProfileAt(b, pos);
5194
- return { t: pos, left: lerpN(x.left, y.left, t), right: lerpN(x.right, y.right, t) };
5195
- });
5196
- }
5197
- function lerpDashes(a, b, t) {
5198
- const dashed = (d) => !!d?.length && d.some((v2) => v2 > 0);
5199
- if (!dashed(a) && !dashed(b)) return t < 0.5 ? a : b;
5200
- const even = (p) => p.length % 2 ? [...p, ...p] : p;
5201
- const solid = (p) => {
5202
- const e = even(p);
5203
- const out = [];
5204
- for (let i = 0; i < e.length; i += 2) out.push(e[i] + e[i + 1], 0);
5205
- return out;
5206
- };
5207
- const x = dashed(a) ? even(a) : solid(b);
5208
- const y = dashed(b) ? even(b) : solid(a);
5209
- if (x.length !== y.length) return t < 0.5 ? a : b;
5210
- return x.map((v2, i) => lerpN(v2, y[i], t));
5211
- }
5212
- var SWITCHED_KEYS = ["strokeLinecap", "strokeLinejoin", "fillRule", "strokeAlign", "startArrow", "endArrow", "arrowAlign"];
5213
- function interpolateVectorStyle(a, b, t) {
5214
- const near2 = t < 0.5 ? a : b;
5215
- const out = {};
5216
- const fill = interpolateVectorPaint(a.fill, b.fill, t);
5217
- if (fill !== void 0) out.fill = fill;
5218
- const stroke = interpolateVectorPaint(a.stroke, b.stroke, t);
5219
- if (stroke !== void 0) out.stroke = stroke;
5220
- if (a.strokeWidth !== void 0 || b.strokeWidth !== void 0) out.strokeWidth = lerpN(a.strokeWidth ?? 1, b.strokeWidth ?? 1, t);
5221
- for (const key of SWITCHED_KEYS) if (near2[key] !== void 0 && near2[key] !== null) out[key] = near2[key];
5222
- for (const key of ["startArrowScale", "endArrowScale"])
5223
- if (a[key] !== void 0 || b[key] !== void 0) out[key] = lerpN(a[key] ?? 1, b[key] ?? 1, t);
5224
- const dash = lerpDashes(a.strokeDasharray, b.strokeDasharray, t);
5225
- if (dash?.length) out.strokeDasharray = dash;
5226
- const profile = interpolateWidthProfiles(a.strokeWidthProfile, b.strokeWidthProfile, t);
5227
- if (profile) out.strokeWidthProfile = profile;
5228
- return out;
5229
- }
5230
- function reversedStyle(s) {
5231
- const out = { ...s };
5232
- out.startArrow = s.endArrow;
5233
- out.endArrow = s.startArrow;
5234
- out.startArrowScale = s.endArrowScale;
5235
- out.endArrowScale = s.startArrowScale;
5236
- if (s.strokeWidthProfile?.length) out.strokeWidthProfile = reverseWidthProfile(s.strokeWidthProfile);
5237
- for (const k of ["startArrow", "endArrow", "startArrowScale", "endArrowScale"]) if (out[k] === void 0) delete out[k];
5238
- return out;
5239
- }
5240
- var STYLE_KEYS = [
5241
- "fill",
5242
- "stroke",
5243
- "strokeWidth",
5244
- "strokeLinecap",
5245
- "strokeLinejoin",
5246
- "strokeDasharray",
5247
- "fillRule",
5248
- "strokeAlign",
5249
- "startArrow",
5250
- "endArrow",
5251
- "arrowAlign",
5252
- "startArrowScale",
5253
- "endArrowScale",
5254
- "strokeWidthProfile"
5255
- ];
5256
- function styleOf(n) {
5257
- const out = {};
5258
- for (const k of STYLE_KEYS) if (n[k] !== void 0) out[k] = n[k];
5259
- return out;
5260
- }
5261
- function contoursOf(node, m) {
5262
- return expandVectorCorners(node.subpaths).map((sp) => subpathToMorphContour(sp, m)).filter((c) => !!c);
5263
- }
5264
- function preparePathMorph(a, b, options, ma = nodeMatrix(a), mb = nodeMatrix(b)) {
5265
- const corr = correspondMorphContours(contoursOf(a, ma), contoursOf(b, mb), options);
5266
- const sim = procrustes(corr.a, corr.b);
5267
- const styleA = styleOf(a);
5268
- const styleB = corr.reversed ? reversedStyle(styleOf(b)) : styleOf(b);
5269
- const rigid = !isIdentityMatrix(ma) || !isIdentityMatrix(mb);
5270
- const id = options.id ?? a.id;
5271
- return (t) => {
5272
- const contours = interpolateMorphContours(corr.a, corr.b, t, { linear: options.linear, rigidity: options.rigidity, similarity: sim });
5273
- const m = rigid ? interpolateRigidMatrix(ma, mb, t) : IDENTITY_MATRIX;
5274
- const back = rigid ? invertMatrix(m) : IDENTITY_MATRIX;
5275
- const subpaths = contours.map((c, k) => {
5276
- const closed = t <= 0 ? corr.a[k].closed : t >= 1 ? corr.b[k].closed : corr.a[k].closed && corr.b[k].closed;
5277
- return morphContourToSubpath({ closed: corr.a[k].closed && corr.b[k].closed, pts: c.pts }, back, closed);
5278
- });
5279
- const node = { id, type: "path", subpaths, ...interpolateVectorStyle(styleA, styleB, t) };
5280
- const opacity = lerpN(a.opacity ?? 1, b.opacity ?? 1, t);
5281
- if (opacity < 1) node.opacity = opacity;
5282
- if (rigid && !isIdentityMatrix(m)) node.transform = m;
5283
- return node;
5284
- };
5285
- }
5286
- function flattenPaths(node, parent = IDENTITY_MATRIX) {
5287
- const m = multiplyMatrices(nodeMatrix(node), parent);
5288
- if (node.type === "path") return [{ path: node, m, opacity: 1 }];
5289
- const o = node.opacity ?? 1;
5290
- return node.children.filter((c) => c.visible !== false).flatMap((c) => flattenPaths(c, m)).map((e) => ({ ...e, opacity: e.opacity * o }));
5291
- }
5292
- var placedBounds = (path, m) => boundsOfPoints(contoursOf(path, m).flatMap((c) => c.pts));
5293
- function collapsedPath(path, m, from, to) {
5294
- const own = placedBounds(path, m);
5295
- const c = own ? [own.x + own.width / 2, own.y + own.height / 2] : [0, 0];
5296
- const fx = from && from.width > 0 ? (c[0] - from.x) / from.width : 0.5;
5297
- const fy = from && from.height > 0 ? (c[1] - from.y) / from.height : 0.5;
5298
- const p = to ? { x: to.x + to.width * fx, y: to.y + to.height * fy } : { x: c[0], y: c[1] };
5299
- const subpaths = path.subpaths.map((sp) => ({ closed: sp.closed, anchors: sp.anchors.map(() => ({ x: p.x, y: p.y })) }));
5300
- const { transform: _t, ...rest } = path;
5301
- return { ...rest, subpaths };
5302
- }
5303
- function createVectorMorph(a, b, options = {}) {
5304
- if (a.type === "path" && b.type === "path") {
5305
- const at2 = preparePathMorph(a, b, options);
5306
- return { at: at2 };
5307
- }
5308
- const pa = flattenPaths(a);
5309
- const pb = flattenPaths(b);
5310
- const ba = unionBounds(pa.map((e) => placedBounds(e.path, e.m)));
5311
- const bb = unionBounds(pb.map((e) => placedBounds(e.path, e.m)));
5312
- const id = options.id ?? a.id;
5313
- const parts = [];
5314
- const opacities = [];
5315
- for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
5316
- const x = pa[i];
5317
- const y = pb[i];
5318
- const sub5 = { ...options, id: `${id}-${i}`, starts: void 0 };
5319
- if (x && y) {
5320
- parts.push(preparePathMorph(x.path, y.path, sub5, x.m, y.m));
5321
- opacities.push([x.opacity, y.opacity]);
5322
- } else if (x) {
5323
- parts.push(preparePathMorph(x.path, collapsedPath(x.path, x.m, ba, bb), sub5, x.m, IDENTITY_MATRIX));
5324
- opacities.push([x.opacity, x.opacity]);
5325
- } else if (y) {
5326
- parts.push(preparePathMorph(collapsedPath(y.path, y.m, bb, ba), y.path, sub5, IDENTITY_MATRIX, y.m));
5327
- opacities.push([y.opacity, y.opacity]);
5328
- }
5329
- }
5330
- return {
5331
- at: (t) => {
5332
- const children = parts.map((p, i) => {
5333
- const n = p(t);
5334
- const o = lerpN(opacities[i][0], opacities[i][1], t) * (n.opacity ?? 1);
5335
- if (o < 1) n.opacity = o;
5336
- else delete n.opacity;
5337
- return n;
5338
- });
5339
- const group = { id, type: "group", children };
5340
- return group;
5341
- }
5342
- };
5343
- }
5344
- function interpolateVectorPaths(a, b, t, options = {}) {
5345
- return createVectorMorph(a, b, options).at(t);
5346
- }
5347
- var keyframeMorphs = /* @__PURE__ */ new WeakMap();
5348
- function evaluateVectorPathKeyframes(keyframes, time, options = {}) {
5349
- const keys = keyframes.filter((k) => Number.isFinite(k.time)).sort((x, y) => x.time - y.time);
5350
- if (!keys.length) return null;
5351
- if (!(time > keys[0].time)) return keys[0].value;
5352
- const last = keys[keys.length - 1];
5353
- if (time >= last.time) return last.value;
5354
- let i = 0;
5355
- while (i + 1 < keys.length && keys[i + 1].time <= time) i++;
5356
- const a = keys[i];
5357
- const b = keys[i + 1];
5358
- if (time === a.time) return a.value;
5359
- if (a.easing === "hold") return a.value;
5360
- const span = b.time - a.time;
5361
- const u = Math.min(1, Math.max(0, evaluateEasing(a.easing, (time - a.time) / span, span)));
5362
- let inner = keyframeMorphs.get(a.value);
5363
- if (!inner) keyframeMorphs.set(a.value, inner = /* @__PURE__ */ new WeakMap());
5364
- let morph = inner.get(b.value);
5365
- if (!morph) inner.set(b.value, morph = createVectorMorph(a.value, b.value, options));
5366
- return morph.at(u);
5367
- }
5368
-
5369
- // src/vector/gradientStroke.ts
5370
- var SHARP = 1.25;
5371
- var TOLERANCE = 0.2;
5372
- var OVERLAP = 0.5;
5373
- var fmt2 = (n, digits = 3) => {
5374
- const k = 10 ** digits;
5375
- const v2 = Math.round(n * k) / k;
5376
- return Object.is(v2, -0) ? "0" : String(v2);
5377
- };
5378
- var toSvgStops2 = (stops) => stops.map((s) => ({ offset: `${fmt2(s.offset * 100)}%`, stopColor: s.color, ...s.opacity !== void 0 && s.opacity !== 1 ? { stopOpacity: Math.round(s.opacity * 1e4) / 1e4 } : {} }));
5379
- var polygonD2 = (pts, precision) => `M${pts.map((p) => `${fmt2(p.x, precision)} ${fmt2(p.y, precision)}`).join("L")}Z`;
5380
- var add4 = (a, b) => ({ x: a.x + b.x, y: a.y + b.y });
5381
- var sub4 = (a, b) => ({ x: a.x - b.x, y: a.y - b.y });
5382
- var scale2 = (a, k) => ({ x: a.x * k, y: a.y * k });
5383
- var left = (d) => ({ x: d.y, y: -d.x });
5384
- var unit3 = (v2) => {
5385
- const l = Math.hypot(v2.x, v2.y);
5386
- return l > 1e-12 ? { x: v2.x / l, y: v2.y / l } : { x: 1, y: 0 };
5387
- };
5388
- function flattenedSubpaths(node) {
5389
- const out = [];
5390
- for (const contour of pathToContours(subpathsToBezier(node.subpaths))) {
5391
- const segs = closeContour(contour);
5392
- if (!segs.length) continue;
5393
- const ring = flattenChain(segs, TOLERANCE);
5394
- const pts = ring.map(([x, y]) => ({ x, y })).filter((p, i, a) => i === 0 || Math.hypot(p.x - a[i - 1].x, p.y - a[i - 1].y) > 1e-9);
5395
- if (contour.closed && pts.length > 2 && Math.hypot(pts[0].x - pts[pts.length - 1].x, pts[0].y - pts[pts.length - 1].y) < 1e-9) pts.pop();
5396
- if (pts.length >= 2) out.push({ pts, closed: contour.closed && pts.length > 2 });
5397
- }
5398
- return out;
5399
- }
5400
- var signedArea = (pts) => {
5401
- let a = 0;
5402
- for (let i = 0; i < pts.length; i++) {
5403
- const p = pts[i];
5404
- const q = pts[(i + 1) % pts.length];
5405
- a += p.x * q.y - q.x * p.y;
5406
- }
5407
- return a / 2;
5408
- };
5409
- function vectorStrokeGradientDefs(g, id, node, options = {}) {
5410
- const precision = options.precision ?? 3;
5411
- const mode = g.strokeMode === "across" ? "across" : "along";
5412
- const expanded = expandVectorGradientStops(g);
5413
- const reach = vectorStrokeReach(node) + 1;
5414
- const area = options.area ?? vectorGradientArea(options.bounds && { x: options.bounds.x - reach, y: options.bounds.y - reach, width: options.bounds.width + 2 * reach, height: options.bounds.height + 2 * reach });
5415
- const width = node.strokeWidth ?? 1;
5416
- const align = node.strokeAlign ?? "center";
5417
- const profile = strokeWidthProfileOf(node);
5418
- const gradients = [];
5419
- const patches = [];
5420
- const slices = [];
5421
- const colourAt = (t) => {
5422
- const s = spanVectorGradientStops(g, t, t, expanded)[0];
5423
- return s;
5424
- };
5425
- let counter = 0;
5426
- const solid = (pts, t) => {
5427
- const s = colourAt(t);
5428
- const gid = `${id}-p${counter++}`;
5429
- gradients.push({ id: gid, type: "linear", attrs: { gradientUnits: "userSpaceOnUse", x1: 0, y1: 0, x2: 1, y2: 0 }, stops: toSvgStops2([{ ...s, offset: 0 }]) });
5430
- patches.push({ d: polygonD2(pts, precision), fill: `url(#${gid})` });
5431
- };
5432
- const disc = (c, r) => Array.from({ length: 16 }, (_, k) => add4(c, scale2({ x: Math.cos(k * Math.PI / 8), y: Math.sin(k * Math.PI / 8) }, r)));
5433
- for (const { pts, closed } of flattenedSubpaths(node)) {
5434
- const n = pts.length;
5435
- const segCount = closed ? n : n - 1;
5436
- const dirs = [];
5437
- const lengths = [0];
5438
- for (let i = 0; i < segCount; i++) {
5439
- const a = pts[i];
5440
- const b = pts[(i + 1) % n];
5441
- dirs.push(unit3(sub4(b, a)));
5442
- lengths.push(lengths[i] + Math.hypot(b.x - a.x, b.y - a.y));
5443
- }
5444
- const total = lengths[segCount];
5445
- if (!(total > 1e-9)) continue;
5446
- const tAt = (i) => lengths[i] / total;
5447
- const clockwise = closed && signedArea(pts) > 0;
5448
- const visibleLeft = align === "center" || !closed ? null : align === "inside" ? !clockwise : clockwise;
5449
- const ribs = [];
5450
- for (let i = 0; i < n; i++) {
5451
- const p = pts[i];
5452
- const din = i > 0 || closed ? dirs[(i - 1 + segCount) % segCount] : null;
5453
- const dout = i < segCount ? dirs[i] : null;
5454
- const square = (d) => ({ l: add4(p, scale2(left(d), reach)), r: sub4(p, scale2(left(d), reach)) });
5455
- if (!din || !dout) {
5456
- const rib = square(din ?? dout);
5457
- ribs.push({ before: rib, after: rib });
5458
- continue;
5459
- }
5460
- const nin = left(din);
5461
- const nout = left(dout);
5462
- const den = 1 + nin.x * nout.x + nin.y * nout.y;
5463
- const stretch = den > 1e-12 ? Math.sqrt(2 / den) : Infinity;
5464
- if (stretch <= SHARP) {
5465
- const m = scale2(add4(nin, nout), reach / den);
5466
- const rib = { l: add4(p, m), r: sub4(p, m) };
5467
- ribs.push({ before: rib, after: rib });
5468
- } else {
5469
- ribs.push({ before: square(din), after: square(dout) });
5470
- solid(disc(p, reach * 1.5), tAt(i));
5471
- }
5472
- }
5473
- if (!closed) {
5474
- const d0 = dirs[0];
5475
- const d1 = dirs[segCount - 1];
5476
- const a = pts[0];
5477
- const b = pts[n - 1];
5478
- const cap = (p, d) => [add4(p, scale2(left(d), reach)), add4(add4(p, scale2(d, reach)), scale2(left(d), reach)), sub4(add4(p, scale2(d, reach)), scale2(left(d), reach)), sub4(p, scale2(left(d), reach))];
5479
- solid(cap(a, scale2(d0, -1)), 0);
5480
- solid(cap(b, d1), 1);
5481
- }
5482
- for (let i = 0; i < segCount; i++) {
5483
- const j = (i + 1) % n;
5484
- const a = pts[i];
5485
- const b = pts[j];
5486
- const d = dirs[i];
5487
- const from = ribs[i].after;
5488
- const to = ribs[j].before;
5489
- const ext = scale2(d, OVERLAP);
5490
- const quad = [from.l, add4(to.l, ext), add4(to.r, ext), from.r];
5491
- const gid = `${id}-s${counter++}`;
5492
- const t0 = tAt(i);
5493
- const t1 = closed && i === segCount - 1 ? 1 : tAt(i + 1);
5494
- if (mode === "along") {
5495
- gradients.push({
5496
- id: gid,
5497
- type: "linear",
5498
- attrs: { gradientUnits: "userSpaceOnUse", x1: fmt2(a.x, 4), y1: fmt2(a.y, 4), x2: fmt2(b.x, 4), y2: fmt2(b.y, 4) },
5499
- stops: toSvgStops2(spanVectorGradientStops(g, t0, t1, expanded))
5500
- });
5501
- } else {
5502
- const mid = scale2(add4(a, b), 0.5);
5503
- const side = widthProfileAt(profile, (t0 + t1) / 2);
5504
- const nrm = left(d);
5505
- const reachL = visibleLeft === null ? width / 2 * side.left : visibleLeft ? width * side.left : 0;
5506
- const reachR = visibleLeft === null ? width / 2 * side.right : visibleLeft ? 0 : width * side.right;
5507
- const p0 = add4(mid, scale2(nrm, reachL));
5508
- const p1 = sub4(mid, scale2(nrm, reachR));
5509
- gradients.push({
5510
- id: gid,
5511
- type: "linear",
5512
- attrs: { gradientUnits: "userSpaceOnUse", x1: fmt2(p0.x, 4), y1: fmt2(p0.y, 4), x2: fmt2(p1.x, 4), y2: fmt2(p1.y, 4) },
5513
- stops: toSvgStops2(expanded)
5514
- });
5515
- }
5516
- slices.push({ d: polygonD2(quad, precision), fill: `url(#${gid})` });
5517
- }
5518
- }
5519
- const def = {
5520
- id,
5521
- type: "pattern",
5522
- attrs: patternAttrs(area),
5523
- gradients,
5524
- tiles: [...patches, ...slices]
5525
- };
5526
- return [def];
5527
- }
5528
-
5529
- // src/vector/svg.ts
5530
- function vectorCornersAttribute(subpaths, precision = 3) {
5531
- const out = [];
5532
- subpaths.forEach(
5533
- (sp, s) => sp.anchors.forEach((a, i) => {
5534
- if (!a.corner || !(a.corner.radius > 0)) return;
5535
- out.push(`${s}.${i}:${formatNumber(a.corner.radius, precision)}${a.corner.kind && a.corner.kind !== "round" ? `:${a.corner.kind}` : ""}`);
5536
- })
5537
- );
5538
- return out.join(" ");
5539
- }
5540
- function applyVectorCornersAttribute(subpaths, value) {
5541
- for (const item of value.trim().split(/\s+/)) {
5542
- const m = /^(\d+)\.(\d+):([\d.eE+-]+)(?::([a-z]+))?$/.exec(item);
5543
- if (!m) continue;
5544
- const a = subpaths[+m[1]]?.anchors[+m[2]];
5545
- const radius = parseFloat(m[3]);
5546
- if (!a || !(radius > 0)) continue;
5547
- const kind = VECTOR_CORNER_KINDS.includes(m[4]) ? m[4] : void 0;
5548
- a.corner = { radius, ...kind && kind !== "round" ? { kind } : {} };
5549
- }
5550
- return subpaths;
5551
- }
5552
- var escapeAttr2 = (value) => value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
5553
- function vectorPathLocalBounds(node) {
5554
- const b = bezierPathBounds(subpathsToBezier(node.subpaths));
5555
- return b ? { x: b.minX, y: b.minY, width: b.maxX - b.minX, height: b.maxY - b.minY } : null;
5556
- }
5557
- var paintCache = /* @__PURE__ */ new WeakMap();
5558
- function vectorPaintToSvg(paint, gradientId, options = {}) {
5559
- if (!hasPaint(paint)) return { value: "none", defs: [] };
5560
- if (typeof paint === "string") return { value: paint, defs: [] };
5561
- if (!isVectorGradient(paint)) return { value: "none", defs: [] };
5562
- const role = options.role ?? "fill";
5563
- const precision = options.precision ?? 3;
5564
- const key = `${gradientId}|${role}|${precision}`;
5565
- const owner = options.node ?? paint;
5566
- const cached = paintCache.get(owner)?.get(key);
5567
- if (cached && (!options.node || (role === "fill" ? options.node.fill : options.node.stroke) === paint)) return { value: `url(#${gradientId})`, defs: cached };
5568
- const node = options.node;
5569
- const bounds = node ? vectorPathLocalBounds(node) : null;
5570
- const reach = node && role === "stroke" ? vectorStrokeReach(node) + 1 : 1;
5571
- const area = bounds ? { x: bounds.x - reach, y: bounds.y - reach, width: bounds.width + 2 * reach, height: bounds.height + 2 * reach } : null;
5572
- const defs = node && role === "stroke" && (paint.strokeMode === "along" || paint.strokeMode === "across") ? vectorStrokeGradientDefs(paint, gradientId, node, { bounds, area, precision }) : vectorGradientSvgDefs(paint, gradientId, { bounds, area, precision });
5573
- let byKey = paintCache.get(owner);
5574
- if (!byKey) paintCache.set(owner, byKey = /* @__PURE__ */ new Map());
5575
- byKey.set(key, defs);
5576
- return { value: `url(#${gradientId})`, defs };
5577
- }
5578
- var partsCache = /* @__PURE__ */ new WeakMap();
5579
- function vectorStrokeSvgParts(node, clipId, precision = 3) {
5580
- if (!hasPaint(node.stroke) || !hasStrokeExtras(node)) return void 0;
5581
- const hit = partsCache.get(node);
5582
- if (hit && hit.clipId === clipId && hit.precision === precision) return hit.parts;
5583
- const parts = computeStrokeSvgParts(node, clipId, precision);
5584
- partsCache.set(node, { clipId, precision, parts });
5585
- return parts;
5586
- }
5587
- function computeStrokeSvgParts(node, clipId, precision) {
5588
- const path = subpathsToBezier(node.subpaths);
5589
- const parts = vectorStrokeParts(path, node);
5590
- const profiled = !!strokeWidthProfileOf(node);
5591
- if (parts.align === "center" && !parts.heads.length && !profiled) return void 0;
5592
- let clip = null;
5593
- if (parts.align !== "center") {
5594
- const b = bezierPathBounds(path);
5595
- const pad = vectorStrokeReach(node) + 1;
5596
- const bounds = b ? { x: round2(b.minX - pad), y: round2(b.minY - pad), width: round2(b.maxX - b.minX + 2 * pad), height: round2(b.maxY - b.minY + 2 * pad) } : { x: 0, y: 0, width: 0, height: 0 };
5597
- clip = { kind: parts.align === "inside" ? "clip" : "mask", id: clipId, bounds };
5598
- }
5599
- return {
5600
- align: parts.align,
5601
- d: bezierPathToSvg(parts.line, { precision }),
5602
- width: parts.drawWidth,
5603
- ...profiled && (node.strokeWidth ?? 1) > 0 ? { outline: bezierPathToSvg(vectorStrokeLineArea(parts, node), { precision }) } : {},
5604
- clip,
5605
- heads: parts.heads.map((h) => bezierPathToSvg(h.path, { precision }))
5606
- };
5607
- }
5608
- function vectorNodeLocalPaintBounds(node) {
5609
- const drawn = expandVectorAppearance(node);
5610
- const reach = (n) => n.type === "path" ? vectorStrokeStackReach(n) : Math.max(0, ...n.children.map(reach));
5611
- let b;
5612
- if (drawn.type === "path") b = vectorPathLocalBounds(drawn);
5613
- else b = unionBounds(drawn.children.filter((c) => c.visible !== false).map((c) => vectorNodeBounds(c, IDENTITY_MATRIX)));
5614
- if (!b) return null;
5615
- const pad = reach(drawn);
5616
- return { x: b.x - pad, y: b.y - pad, width: b.width + 2 * pad, height: b.height + 2 * pad };
5617
- }
5618
- var filterCache = /* @__PURE__ */ new WeakMap();
5619
- function vectorNodeFilterSvg(node, id) {
5620
- if (!node.filters?.length) return null;
5621
- const hit = filterCache.get(node);
5622
- if (hit && hit.id === id) return hit.filter;
5623
- const active = activeVectorFilters(node);
5624
- const filter = active.length ? vectorFilterSvg(active, id, vectorNodeLocalPaintBounds(node)) : null;
5625
- filterCache.set(node, { id, filter });
5626
- return filter;
5627
- }
5628
- function widthProfileToAttribute(points, precision = 4) {
5629
- return points.map((p) => [p.t, p.left, p.right].map((n) => formatNumber(n, precision)).join(",")).join(";");
5630
- }
5631
- function widthProfileFromAttribute(value) {
5632
- if (!value) return [];
5633
- return sanitizeWidthProfile(
5634
- value.split(";").map((part) => {
5635
- const [t, left2, right] = part.split(",").map((n) => parseFloat(n));
5636
- return { t, left: left2, right: Number.isFinite(right) ? right : left2 };
5637
- })
5638
- );
5639
- }
5640
- var round2 = (n) => Math.round(n * 100) / 100;
5641
- function gradientMarkup(def, extra = "") {
5642
- const tag = def.type === "radial" ? "radialGradient" : "linearGradient";
5643
- const attrs = Object.entries(def.attrs).map(([k, v2]) => ` ${k}="${escapeAttr2(String(v2))}"`).join("");
5644
- const stops = def.stops.map((s) => `<stop offset="${s.offset}" stop-color="${escapeAttr2(s.stopColor)}"${s.stopOpacity !== void 0 ? ` stop-opacity="${s.stopOpacity}"` : ""}/>`).join("");
5645
- return `<${tag} id="${escapeAttr2(def.id)}"${attrs}${extra}>${stops}</${tag}>`;
5646
- }
5647
- function paintDefMarkup(def, gradient) {
5648
- const extra = gradient ? ` data-vector-gradient="${escapeAttr2(JSON.stringify(gradient))}"` : "";
5649
- if (def.type !== "pattern") return gradientMarkup(def, extra);
5650
- const attrs = Object.entries(def.attrs).map(([k, v2]) => ` ${k}="${escapeAttr2(String(v2))}"`).join("");
5651
- const inner = def.gradients.map((g) => gradientMarkup(g)).join("") + def.tiles.map((t) => `<path d="${t.d}" fill="${escapeAttr2(t.fill)}"/>`).join("");
5652
- return `<pattern id="${escapeAttr2(def.id)}"${attrs}${extra}>${inner}</pattern>`;
5653
- }
5654
- var paintMarkup = (paint, defs) => defs.map((d, i) => paintDefMarkup(d, i === 0 && isVectorGradient(paint) ? paint : void 0));
5655
- function blendFromAttribute(value, m) {
5656
- if (!value) return null;
5657
- let raw;
5658
- try {
5659
- raw = JSON.parse(value);
5660
- } catch {
5661
- return null;
5662
- }
5663
- if (!raw || typeof raw !== "object") return null;
5664
- const r = raw;
5665
- const out = {};
5666
- if (r.spacing === "steps" || r.spacing === "distance" || r.spacing === "smoothColor") out.spacing = r.spacing;
5667
- if (typeof r.steps === "number" && Number.isFinite(r.steps)) out.steps = Math.min(1e3, Math.max(1, Math.round(r.steps)));
5668
- if (typeof r.distance === "number" && r.distance > 0) out.distance = r.distance;
5669
- if (typeof r.orientToSpine === "boolean") out.orientToSpine = r.orientToSpine;
5670
- if (typeof r.linear === "boolean") out.linear = r.linear;
5671
- if (r.starts && typeof r.starts === "object") {
5672
- const starts = Object.fromEntries(Object.entries(r.starts).filter((e) => Number.isInteger(e[1]) && e[1] >= 0));
5673
- if (Object.keys(starts).length) out.starts = starts;
5674
- }
5675
- const spine = r.spine;
5676
- if (spine && Array.isArray(spine.anchors) && spine.anchors.every((a) => a && Number.isFinite(a.x) && Number.isFinite(a.y))) {
5677
- const sp = { closed: !!spine.closed, anchors: spine.anchors.map((a) => ({ x: a.x, y: a.y, ...a.in ? { in: { x: a.in.x, y: a.in.y } } : {}, ...a.out ? { out: { x: a.out.x, y: a.out.y } } : {} })) };
5678
- out.spine = m === IDENTITY_MATRIX ? sp : transformVectorNode({ id: "", type: "path", subpaths: [sp] }, m).subpaths[0];
5679
- }
5680
- return out;
5681
- }
5682
- function vectorDocumentToSvg(doc, options = {}) {
5683
- const precision = options.precision ?? 3;
5684
- const prefix = options.idPrefix ?? "vg-";
5685
- const pretty = options.pretty !== false;
5686
- const defs = [];
5687
- const lines = [];
5688
- const num2 = (n) => formatNumber(n, precision);
5689
- const indent = (depth) => pretty ? " ".repeat(depth) : "";
5690
- const common = (node) => {
5691
- let out2 = ` id="${escapeAttr2(node.id)}"`;
5692
- if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) => formatNumber(n, 6)).join(" ")})"`;
5693
- if (node.opacity !== void 0 && node.opacity < 1) out2 += ` opacity="${num2(node.opacity)}"`;
5694
- if (node.visible === false) out2 += ` display="none"`;
5695
- if (node.blendStep) out2 += ` data-vector-blend-step=""`;
5696
- if (node.type === "group" && node.blend) out2 += ` data-vector-blend="${escapeAttr2(JSON.stringify(node.blend))}"`;
5697
- if (node.booleanOperation) out2 += ` data-vector-boolean-operation="${node.booleanOperation}"`;
5698
- const blend = vectorBlendModeCss(node.blendMode);
5699
- if (blend) out2 += ` style="mix-blend-mode:${blend}"`;
5700
- if (node.filters?.length) {
5701
- const filter = vectorNodeFilterSvg(node, `${prefix}filter-${node.id}`);
5702
- const data = ` data-vector-filters="${escapeAttr2(JSON.stringify(node.filters))}"`;
5703
- if (filter) {
5704
- defs.push(vectorFilterMarkup(filter, data));
5705
- out2 += ` filter="url(#${escapeAttr2(filter.id)})"`;
5706
- } else out2 += data;
5707
- }
5708
- return out2;
5709
- };
5710
- const layerAttrs = (layer) => {
5711
- let out2 = "";
5712
- if (layer.opacity !== void 0 && layer.opacity < 1) out2 += ` opacity="${num2(layer.opacity)}"`;
5713
- const blend = vectorBlendModeCss(layer.blendMode);
5714
- if (blend) out2 += ` style="mix-blend-mode:${blend}"`;
5715
- return out2;
5716
- };
5717
- const strokePartLines = (node, parts, strokeValue, d, lineAttrs, depth) => {
5718
- const out2 = [];
5719
- if (options.strokes === "outline") {
5720
- const area = bezierPathToSvg(vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
5721
- out2.push(`${indent(depth)}<path data-vector-part="stroke-outline" d="${area}" fill="${escapeAttr2(strokeValue)}"/>`);
5722
- return out2;
5723
- }
5724
- let clip = "";
5725
- if (parts.clip) {
5726
- const rule = node.fillRule === "evenodd" ? "evenodd" : "nonzero";
5727
- const id = escapeAttr2(parts.clip.id);
5728
- if (parts.clip.kind === "clip") {
5729
- defs.push(`<clipPath id="${id}"><path d="${d}" clip-rule="${rule}"/></clipPath>`);
5730
- clip = ` clip-path="url(#${id})"`;
5731
- } else {
5732
- const b = parts.clip.bounds;
5733
- const box = `x="${num2(b.x)}" y="${num2(b.y)}" width="${num2(b.width)}" height="${num2(b.height)}"`;
5734
- defs.push(`<mask id="${id}" maskUnits="userSpaceOnUse" ${box}><rect ${box} fill="#fff"/><path d="${d}" fill="#000" fill-rule="${rule}"/></mask>`);
5735
- clip = ` mask="url(#${id})"`;
5736
- }
5737
- }
5738
- if (parts.outline !== void 0) out2.push(`${indent(depth)}<path data-vector-part="stroke-outline" d="${parts.outline}" fill="${escapeAttr2(strokeValue)}"${clip}/>`);
5739
- else out2.push(`${indent(depth)}<path data-vector-part="stroke" d="${parts.d}" fill="none"${lineAttrs(parts.width)}${clip}/>`);
5740
- for (const h2 of parts.heads) out2.push(`${indent(depth)}<path data-vector-part="head" d="${h2}" fill="${escapeAttr2(strokeValue)}"/>`);
5741
- return out2;
5742
- };
5743
- const lineAttrsOf = (node, strokeValue) => (width) => {
5744
- let out2 = ` stroke="${escapeAttr2(strokeValue)}" stroke-width="${num2(width)}"`;
5745
- if (node.strokeLinecap && node.strokeLinecap !== "butt") out2 += ` stroke-linecap="${node.strokeLinecap}"`;
5746
- if (node.strokeLinejoin && node.strokeLinejoin !== "miter") out2 += ` stroke-linejoin="${node.strokeLinejoin}"`;
5747
- if (node.strokeDasharray?.length) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
5748
- return out2;
5749
- };
5750
- const liveCorners = (node) => {
5751
- const corners = vectorCornersAttribute(node.subpaths, precision);
5752
- return corners ? ` data-vector-d="${bezierPathToSvg(subpathsToBezier(node.subpaths, { corners: false }), { precision })}" data-vector-corners="${corners}"` : "";
5753
- };
5754
- const emitStacked = (node, depth) => {
5755
- const d = vectorPathData(node, precision);
5756
- const rule = node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : "";
5757
- let data = ` data-vector-path="" data-vector-fills="${escapeAttr2(JSON.stringify(vectorFills(node)))}" data-vector-strokes="${escapeAttr2(JSON.stringify(vectorStrokes(node)))}"`;
5758
- if (node.fillRule === "evenodd") data += ` data-vector-fill-rule="evenodd"`;
5759
- lines.push(`${indent(depth)}<g${common(node)}${data}>`);
5760
- const layers = vectorPaintLayerNodes(node).filter((l) => l.drawn);
5761
- let geometry = liveCorners(node);
5762
- if (!layers.some((l) => l.kind === "fill")) {
5763
- lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}" fill="none"${rule}${geometry}/>`);
5764
- geometry = "";
5765
- }
5766
- for (const l of layers) {
5767
- const id = `${prefix}${l.kind}-${node.id}-${l.index}`;
5768
- const paint = vectorPaintToSvg(l.layer.paint, id, { node: l.node, precision, ...l.kind === "stroke" ? { role: "stroke" } : {} });
5769
- defs.push(...paintMarkup(l.layer.paint, paint.defs));
5770
- const attrs = ` data-vector-layer="${l.index}"${layerAttrs(l.layer)}`;
5771
- if (l.kind === "fill") {
5772
- lines.push(`${indent(depth + 1)}<path data-vector-part="fill"${attrs} d="${d}" fill="${escapeAttr2(paint.value)}"${rule}${geometry}/>`);
5773
- geometry = "";
5774
- continue;
5775
- }
5776
- const lineAttrs = lineAttrsOf(l.node, paint.value);
5777
- const parts = vectorStrokeSvgParts(l.node, `${prefix}clip-${node.id}-${l.index}`, precision);
5778
- if (!parts) {
5779
- lines.push(`${indent(depth + 1)}<path data-vector-part="stroke"${attrs} d="${d}" fill="none"${lineAttrs(l.node.strokeWidth ?? 1)}/>`);
5780
- continue;
5781
- }
5782
- lines.push(`${indent(depth + 1)}<g data-vector-part="stroke-layer"${attrs}>`);
5783
- lines.push(...strokePartLines(l.node, parts, paint.value, d, lineAttrs, depth + 2));
5784
- lines.push(`${indent(depth + 1)}</g>`);
5785
- }
5786
- lines.push(`${indent(depth)}</g>`);
5787
- };
5788
- const emit2 = (node, depth) => {
5789
- if (node.visible === false && !options.includeHidden) return;
5790
- const wrappers = options.wrap?.[node.id] ?? [];
5791
- wrappers.forEach((w2, i) => {
5792
- let attrs = w2.id !== void 0 ? ` id="${escapeAttr2(w2.id)}"` : "";
5793
- if (w2.transform) attrs += ` transform="${escapeAttr2(w2.transform)}"`;
5794
- if (w2.clip) {
5795
- const shape = Object.entries(w2.clip.attrs).map(([k, v2]) => ` ${k}="${formatNumber(v2, 4)}"`).join("");
5796
- defs.push(`<clipPath id="${escapeAttr2(w2.clip.id)}" clipPathUnits="objectBoundingBox"><${w2.clip.shape}${w2.clip.shapeId !== void 0 ? ` id="${escapeAttr2(w2.clip.shapeId)}"` : ""}${shape}/></clipPath>`);
5797
- attrs += ` clip-path="url(#${escapeAttr2(w2.clip.id)})"`;
5798
- }
5799
- lines.push(`${indent(depth + i)}<g${attrs}>`);
5800
- });
5801
- emitNode(node, depth + wrappers.length);
5802
- for (let i = wrappers.length - 1; i >= 0; i--) lines.push(`${indent(depth + i)}</g>`);
5803
- };
5804
- const capture = (fn) => {
5805
- const at2 = lines.length;
5806
- fn();
5807
- return lines.splice(at2).map((l) => l.trim()).join("");
5808
- };
5809
- const emitMaskGroup = (node, depth) => {
5810
- const [source, ...contents] = node.children;
5811
- const body = node.effects?.length && contents.length ? [{ id: `${node.id}~content`, type: "group", effects: node.effects, children: contents }] : contents;
5812
- const settings = { type: node.mask.type, ...node.mask.invert ? { invert: true } : {} };
5813
- lines.push(`${indent(depth)}<g${common(node)} data-vector-mask="${escapeAttr2(JSON.stringify(settings))}">`);
5814
- const mask = vectorMaskRenderData(node, `${prefix}mask-${node.id}`, `${prefix}mask-filter-${node.id}`, precision);
5815
- let ref = "";
5816
- if (mask && mask.type !== "clip") {
5817
- const b = mask.bounds;
5818
- const box = `x="${num2(b.x)}" y="${num2(b.y)}" width="${num2(b.width)}" height="${num2(b.height)}"`;
5819
- if (mask.invertFilter) defs.push(vectorFilterMarkup(mask.invertFilter));
5820
- const inner = capture(() => emitNode(source, depth + 1));
5821
- const drawn = mask.filter ? `<g data-vector-part="mask-invert" filter="${escapeAttr2(mask.filter)}">${inner}</g>` : inner;
5822
- defs.push(`<mask id="${escapeAttr2(mask.id)}" data-vector-part="mask-source" maskUnits="userSpaceOnUse" ${box}${mask.type === "alpha" ? ' mask-type="alpha"' : ""}>${drawn}</mask>`);
5823
- ref = ` mask="url(#${escapeAttr2(mask.id)})"`;
5824
- } else {
5825
- lines.push(`${indent(depth + 1)}<g data-vector-part="mask-source" display="none">`);
5826
- emitNode(source, depth + 2);
5827
- lines.push(`${indent(depth + 1)}</g>`);
5828
- if (mask?.clip) {
5829
- defs.push(`<clipPath id="${escapeAttr2(mask.id)}">${mask.clip.map((c) => `<path d="${c.d}" clip-rule="${c.clipRule}"/>`).join("")}</clipPath>`);
5830
- ref = ` clip-path="url(#${escapeAttr2(mask.id)})"`;
5831
- }
5832
- }
5833
- lines.push(`${indent(depth + 1)}<g data-vector-part="masked"${ref}>`);
5834
- for (const child of body) emit2(child, depth + 2);
5835
- lines.push(`${indent(depth + 1)}</g>`);
5836
- lines.push(`${indent(depth)}</g>`);
5837
- };
5838
- const emitNode = (node, depth) => {
5839
- if (isVectorMaskGroup(node)) {
5840
- emitMaskGroup(node, depth);
5841
- return;
5842
- }
5843
- if (hasOwnVectorAppearance(node)) {
5844
- const live2 = {
5845
- kind: node.type,
5846
- ...node.effects?.length ? { effects: node.effects } : {},
5847
- ...node.type === "group" && node.liveBoolean ? { liveBoolean: node.liveBoolean } : {}
5848
- };
5849
- lines.push(`${indent(depth)}<g${common(node)} data-vector-live="${escapeAttr2(JSON.stringify(live2))}">`);
5850
- lines.push(`${indent(depth + 1)}<g data-vector-part="appearance">`);
5851
- for (const shape of vectorAppearanceNodes(node)) emit2(shape, depth + 2);
5852
- lines.push(`${indent(depth + 1)}</g>`);
5853
- lines.push(`${indent(depth + 1)}<g data-vector-part="source" display="none">`);
5854
- if (node.type === "path") {
5855
- const { effects: _e, transform: _t, opacity: _o, visible: _v, booleanOperation: _b, blendStep: _s, blendMode: _bm, filters: _f, ...source } = node;
5856
- emit2({ ...source, id: `${node.id}~src` }, depth + 2);
5857
- } else for (const child of node.children) emit2(child, depth + 2);
5858
- lines.push(`${indent(depth + 1)}</g>`);
5859
- lines.push(`${indent(depth)}</g>`);
5860
- return;
5861
- }
5862
- if (node.type === "group") {
5863
- lines.push(`${indent(depth)}<g${common(node)}>`);
5864
- for (const child of node.children) emit2(child, depth + 1);
5865
- lines.push(`${indent(depth)}</g>`);
5866
- return;
5867
- }
5868
- if (needsVectorPaintLayers(node)) {
5869
- emitStacked(node, depth);
5870
- return;
5871
- }
5872
- const fill = vectorPaintToSvg(node.fill, `${prefix}fill-${node.id}`, { node, precision });
5873
- const stroke = vectorPaintToSvg(node.stroke, `${prefix}stroke-${node.id}`, { node, role: "stroke", precision });
5874
- defs.push(...paintMarkup(node.fill, fill.defs), ...paintMarkup(node.stroke, stroke.defs));
5875
- const d = vectorPathData(node, precision);
5876
- const live = liveCorners(node);
5877
- const fillAttrs = ` fill="${escapeAttr2(fill.value)}"${node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : ""}`;
5878
- const lineAttrs = lineAttrsOf(node, stroke.value);
5879
- const parts = stroke.value !== "none" ? vectorStrokeSvgParts(node, `${prefix}clip-${node.id}`, precision) : void 0;
5880
- if (!parts) {
5881
- lines.push(`${indent(depth)}<path${common(node)} d="${d}"${fillAttrs}${stroke.value !== "none" ? lineAttrs(node.strokeWidth ?? 1) : ""}${live}/>`);
5882
- return;
5883
- }
5884
- let data = ` data-vector-path="" data-vector-stroke-width="${num2(node.strokeWidth ?? 1)}"`;
5885
- if (parts.align !== "center") data += ` data-vector-stroke-align="${parts.align}"`;
5886
- if (node.startArrow) data += ` data-vector-start-arrow="${node.startArrow}"`;
5887
- if (node.endArrow) data += ` data-vector-end-arrow="${node.endArrow}"`;
5888
- if (node.arrowAlign && node.arrowAlign !== "extend") data += ` data-vector-arrow-align="${node.arrowAlign}"`;
5889
- if (node.startArrowScale !== void 0 && node.startArrowScale !== 1) data += ` data-vector-start-arrow-scale="${num2(node.startArrowScale)}"`;
5890
- if (node.endArrowScale !== void 0 && node.endArrowScale !== 1) data += ` data-vector-end-arrow-scale="${num2(node.endArrowScale)}"`;
5891
- const profile = strokeWidthProfileOf(node);
5892
- if (profile) {
5893
- data += ` data-vector-width-profile="${widthProfileToAttribute(profile)}"`;
5894
- if (node.strokeLinecap && node.strokeLinecap !== "butt") data += ` data-vector-stroke-linecap="${node.strokeLinecap}"`;
5895
- if (node.strokeLinejoin && node.strokeLinejoin !== "miter") data += ` data-vector-stroke-linejoin="${node.strokeLinejoin}"`;
5896
- if (node.strokeDasharray?.length) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
5897
- }
5898
- lines.push(`${indent(depth)}<g${common(node)}${data}>`);
5899
- lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
5900
- lines.push(...strokePartLines(node, parts, stroke.value, d, lineAttrs, depth + 1));
5901
- lines.push(`${indent(depth)}</g>`);
5902
- };
5903
- for (const node of doc.nodes) emit2(node, 1);
5904
- const w = num2(doc.width);
5905
- const h = num2(doc.height);
5906
- const nl = pretty ? "\n" : "";
5907
- const out = [`<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}">`];
5908
- if (defs.length) out.push(`${indent(1)}<defs>${defs.join("")}</defs>`);
5909
- if (doc.background && options.background !== false && hasPaint(doc.background)) {
5910
- out.push(`${indent(1)}<rect width="${w}" height="${h}" fill="${escapeAttr2(doc.background)}"/>`);
5911
- }
5912
- out.push(...lines, "</svg>");
5913
- return out.join(nl);
5914
- }
5915
- var BOOLEAN_OPERATIONS = ["union", "subtract", "intersect", "exclude"];
5916
- function parseXml(source) {
5917
- const text = source.replace(/<!--[\s\S]*?-->/g, "").replace(/<\?[\s\S]*?\?>/g, "").replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, "").replace(/<!DOCTYPE[^>[]*(\[[\s\S]*?\])?\s*>/gi, "");
5918
- const root = { name: "#root", attrs: {}, children: [] };
5919
- const stack = [root];
5920
- const tag = /<(\/?)([A-Za-z_][\w:.-]*)((?:\s+[^\s=/>]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*)\s*(\/?)>/g;
5921
- const attr = /([^\s=/>]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
5922
- let m;
5923
- while (m = tag.exec(text)) {
5924
- const [, closing, rawName, rawAttrs, selfClosing] = m;
5925
- const name = rawName.replace(/^svg:/, "");
5926
- if (closing) {
5927
- for (let i = stack.length - 1; i > 0; i--) {
5928
- if (stack[i].name === name) {
5929
- stack.length = i;
5930
- break;
5931
- }
5932
- }
5933
- continue;
5934
- }
5935
- const attrs = {};
5936
- let a;
5937
- attr.lastIndex = 0;
5938
- while (a = attr.exec(rawAttrs)) attrs[a[1]] = decodeEntities(a[2] ?? a[3] ?? a[4] ?? "");
5939
- const el = { name, attrs, children: [] };
5940
- stack[stack.length - 1].children.push(el);
5941
- if (!selfClosing) stack.push(el);
5942
- }
5943
- const find = (el) => {
5944
- if (el.name === "svg") return el;
5945
- for (const c of el.children) {
5946
- const f = find(c);
5947
- if (f) return f;
5948
- }
5949
- return null;
5950
- };
5951
- return find(root);
5952
- }
5953
- function decodeEntities(s) {
5954
- return s.replace(/&#x([0-9a-f]+);/gi, (_, h) => String.fromCodePoint(parseInt(h, 16))).replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(parseInt(d, 10))).replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
5955
- }
5956
- var numberList = (s) => (s ?? "").trim().split(/[\s,]+|(?=-)(?<![eE])/).filter(Boolean).map(Number).filter((n) => Number.isFinite(n));
5957
- var length = (s, fallback = 0) => {
5958
- if (s === void 0) return fallback;
5959
- const n = parseFloat(s);
5960
- return Number.isFinite(n) ? n : fallback;
5961
- };
5962
- function parseSvgTransform(value) {
5963
- let m = IDENTITY_MATRIX;
5964
- if (!value) return m;
5965
- const re = /(matrix|translate|scale|rotate|skewX|skewY)\s*\(([^)]*)\)/g;
5966
- let t;
5967
- while (t = re.exec(value)) {
5968
- const n = numberList(t[2]);
5969
- let step = IDENTITY_MATRIX;
5970
- switch (t[1]) {
5971
- case "matrix":
5972
- if (n.length >= 6) step = [n[0], n[1], n[2], n[3], n[4], n[5]];
5973
- break;
5974
- case "translate":
5975
- step = translateMatrix(n[0] ?? 0, n[1] ?? 0);
5976
- break;
5977
- case "scale":
5978
- step = scaleMatrix(n[0] ?? 1, n[1] ?? n[0] ?? 1);
5979
- break;
5980
- case "rotate":
5981
- step = rotateMatrix(n[0] ?? 0, { x: n[1] ?? 0, y: n[2] ?? 0 });
5982
- break;
5983
- case "skewX":
5984
- step = [1, 0, Math.tan((n[0] ?? 0) * Math.PI / 180), 1, 0, 0];
5985
- break;
5986
- case "skewY":
5987
- step = [1, Math.tan((n[0] ?? 0) * Math.PI / 180), 0, 1, 0, 0];
5988
- break;
5989
- }
5990
- m = multiplyMatrices(step, m);
5991
- }
5992
- return m;
5993
- }
5994
- var STYLE_KEYS2 = {
5995
- fill: "fill",
5996
- stroke: "stroke",
5997
- "stroke-width": "strokeWidth",
5998
- "stroke-linecap": "strokeLinecap",
5999
- "stroke-linejoin": "strokeLinejoin",
6000
- "stroke-dasharray": "strokeDasharray",
6001
- "fill-rule": "fillRule",
6002
- "fill-opacity": "fillOpacity",
6003
- "stroke-opacity": "strokeOpacity",
6004
- "mix-blend-mode": "mixBlendMode",
6005
- filter: "filter"
6006
- };
6007
- function readStyle(el, parent) {
6008
- const { mixBlendMode: _m, filter: _f, ...inherited } = parent;
6009
- const out = { ...inherited };
6010
- for (const [attr, key] of Object.entries(STYLE_KEYS2)) if (el.attrs[attr] !== void 0) out[key] = el.attrs[attr].trim();
6011
- for (const decl of (el.attrs.style ?? "").split(";")) {
6012
- const i = decl.indexOf(":");
6013
- if (i < 0) continue;
6014
- const key = STYLE_KEYS2[decl.slice(0, i).trim()];
6015
- if (key) out[key] = decl.slice(i + 1).replace(/!important/, "").trim();
6016
- }
6017
- return out;
6018
- }
6019
- function readStops(el) {
6020
- return el.children.filter((c) => c.name === "stop").map((c) => {
6021
- const style = Object.fromEntries(
6022
- (c.attrs.style ?? "").split(";").map((d) => d.split(":").map((s) => s.trim())).filter((d) => d.length === 2)
6023
- );
6024
- const raw = c.attrs.offset ?? "0";
6025
- const offset = raw.endsWith("%") ? parseFloat(raw) / 100 : parseFloat(raw);
6026
- const opacity = style["stop-opacity"] ?? c.attrs["stop-opacity"];
6027
- return {
6028
- offset: Number.isFinite(offset) ? Math.max(0, Math.min(1, offset)) : 0,
6029
- color: style["stop-color"] ?? c.attrs["stop-color"] ?? "#000",
6030
- ...opacity !== void 0 ? { opacity: parseFloat(opacity) } : {}
6031
- };
6032
- });
6033
- }
6034
- var fraction = (s, fallback) => {
6035
- if (s === void 0) return fallback;
6036
- const n = parseFloat(s);
6037
- if (!Number.isFinite(n)) return fallback;
6038
- return s.trim().endsWith("%") ? n / 100 : n;
6039
- };
6040
- var PAINT_SERVERS = /* @__PURE__ */ new Set(["linearGradient", "radialGradient", "pattern"]);
6041
- function collectGradients(el, raw) {
6042
- if (PAINT_SERVERS.has(el.name) && el.attrs.id) raw.set(el.attrs.id, el);
6043
- for (const c of el.children) collectGradients(c, raw);
6044
- }
6045
- function collectMasks(el, raw) {
6046
- if ((el.name === "clipPath" || el.name === "mask") && el.attrs.id) raw.set(el.attrs.id, el);
6047
- for (const c of el.children) collectMasks(c, raw);
6048
- }
6049
- function attrOrStyle(el, name) {
6050
- for (const decl of (el.attrs.style ?? "").split(";")) {
6051
- const i = decl.indexOf(":");
6052
- if (i >= 0 && decl.slice(0, i).trim() === name) return decl.slice(i + 1).replace(/!important/, "").trim();
6053
- }
6054
- return el.attrs[name];
6055
- }
6056
- function urlId(value) {
6057
- return /^url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec((value ?? "").trim())?.[1] ?? null;
6058
- }
6059
- function clipRulesAsFillRules(el) {
6060
- const attrs = { ...el.attrs };
6061
- const rule = attrOrStyle(el, "clip-rule");
6062
- if (rule) attrs["fill-rule"] = rule;
6063
- return { ...el, attrs, children: el.children.map(clipRulesAsFillRules) };
6064
- }
6065
- function collectFilters(el, raw) {
6066
- if (el.name === "filter" && el.attrs.id) raw.set(el.attrs.id, el);
6067
- for (const c of el.children) collectFilters(c, raw);
6068
- }
6069
- function filtersFromElement(el) {
6070
- const own = el.attrs["data-vector-filters"];
6071
- if (own !== void 0) {
6072
- try {
6073
- return sanitizeVectorFilters(JSON.parse(own));
6074
- } catch {
6075
- return [];
6076
- }
6077
- }
6078
- const prims = el.children.filter((c) => c.name.startsWith("fe"));
6079
- const out = [];
6080
- for (const p of prims) {
6081
- const std = numberList(p.attrs.stdDeviation)[0] ?? 0;
6082
- if (p.name === "feDropShadow") {
6083
- const style = Object.fromEntries(
6084
- (p.attrs.style ?? "").split(";").map((d) => d.split(":").map((x) => x.trim())).filter((d) => d.length === 2)
6085
- );
6086
- const opacity = parseFloat(style["flood-opacity"] ?? p.attrs["flood-opacity"] ?? "1");
6087
- out.push({
6088
- type: "dropShadow",
6089
- params: {
6090
- color: style["flood-color"] ?? p.attrs["flood-color"] ?? "#000000",
6091
- opacity: Number.isFinite(opacity) ? opacity : 1,
6092
- offsetX: length(p.attrs.dx, 2),
6093
- offsetY: length(p.attrs.dy, 2),
6094
- blur: std * 2,
6095
- spread: 0
6096
- }
6097
- });
6098
- } else if (p.name === "feGaussianBlur" && prims.length === 1 && (p.attrs.in === void 0 || p.attrs.in === "SourceGraphic")) {
6099
- out.push({ type: "layerBlur", params: { radius: std * 2 } });
6100
- } else return [];
6101
- }
6102
- return sanitizeVectorFilters(out);
6103
- }
6104
- function gradientFromAttribute(value) {
6105
- if (!value) return null;
6106
- try {
6107
- return sanitizeVectorGradient(JSON.parse(value));
6108
- } catch {
6109
- return null;
6110
- }
6111
- }
6112
- function resolveGradient(id, raw) {
6113
- const first = raw.get(id);
6114
- if (!first) return null;
6115
- const own = gradientFromAttribute(first.attrs["data-vector-gradient"]);
6116
- if (own) return own;
6117
- if (first.name === "pattern") return null;
6118
- const chain = [];
6119
- for (let el = first; el && !chain.includes(el) && chain.length < 32; ) {
6120
- chain.push(el);
6121
- const href = el.attrs.href ?? el.attrs["xlink:href"];
6122
- el = href?.startsWith("#") ? raw.get(href.slice(1)) : void 0;
6123
- }
6124
- const attr = (name) => chain.find((el) => el.attrs[name] !== void 0)?.attrs[name];
6125
- const stops = chain.map(readStops).find((s) => s.length) ?? [];
6126
- if (!stops.length) return null;
6127
- const user = attr("gradientUnits") === "userSpaceOnUse";
6128
- const t = parseSvgTransform(attr("gradientTransform"));
6129
- const plain2 = t === IDENTITY_MATRIX || t[0] === 1 && t[1] === 0 && t[2] === 0 && t[3] === 1 && t[4] === 0 && t[5] === 0;
6130
- const at2 = (name, fallback) => user ? length(attr(name), fallback) : fraction(attr(name), fallback);
6131
- const spreadAttr = attr("spreadMethod");
6132
- const spread = spreadAttr === "reflect" || spreadAttr === "repeat" ? { spread: spreadAttr } : {};
6133
- const map = (p) => applySvgMatrix(t, p);
6134
- if (first.name === "radialGradient") {
6135
- const cx = at2("cx", user ? 0 : 0.5);
6136
- const cy = at2("cy", user ? 0 : 0.5);
6137
- const r = at2("r", user ? 0 : 0.5);
6138
- const fx = attr("fx") !== void 0 ? at2("fx", cx) : cx;
6139
- const fy = attr("fy") !== void 0 ? at2("fy", cy) : cy;
6140
- const fr = attr("fr") !== void 0 ? at2("fr", 0) : 0;
6141
- const focal = Math.abs(fx - cx) > 1e-9 || Math.abs(fy - cy) > 1e-9;
6142
- if (!user && plain2 && !focal && !(fr > 0)) return { type: "radial", cx, cy, r, stops, ...spread };
6143
- const g = {
6144
- type: "radial",
6145
- stops,
6146
- start: map({ x: cx, y: cy }),
6147
- end: map({ x: cx + r, y: cy }),
6148
- width: map({ x: cx, y: cy + r }),
6149
- units: user ? "userSpaceOnUse" : "objectBoundingBox",
6150
- ...spread
6151
- };
6152
- if (focal) g.focal = map({ x: fx, y: fy });
6153
- if (fr > 0 && r > 0) g.focalRadius = Math.min(0.99, fr / r);
6154
- return g;
6155
- }
6156
- const x1 = at2("x1", 0);
6157
- const y1 = at2("y1", 0);
6158
- const x2 = attr("x2") !== void 0 ? at2("x2", 1) : user ? 0 : 1;
6159
- const y2 = at2("y2", 0);
6160
- if (!user && plain2) {
6161
- const angle = Math.round((Math.atan2(x2 - x1, -(y2 - y1)) * 180 / Math.PI + 360) % 360);
6162
- const c = angleToSvgLinearCoords(angle);
6163
- const len2 = Math.hypot(x2 - x1, y2 - y1);
6164
- const d = len2 > 0 ? { x: (x2 - x1) / len2, y: (y2 - y1) / len2 } : { x: 0, y: 1 };
6165
- const along2 = (x, y) => x * d.x + y * d.y;
6166
- const same2 = len2 > 0 && Math.abs((c.x2 - c.x1) * d.y - (c.y2 - c.y1) * d.x) < 1e-3 && Math.abs(along2(c.x1, c.y1) - along2(x1, y1)) < 1e-3 && Math.abs(along2(c.x2, c.y2) - along2(x2, y2)) < 1e-3;
6167
- if (same2) return { type: "linear", angle, stops, ...spread };
6168
- }
6169
- const start = { x: x1, y: y1 };
6170
- const end = { x: x2, y: y2 };
6171
- return {
6172
- type: "linear",
6173
- stops,
6174
- start: map(start),
6175
- end: map(end),
6176
- width: map({ x: x1 - (y2 - y1), y: y1 + (x2 - x1) }),
6177
- units: user ? "userSpaceOnUse" : "objectBoundingBox",
6178
- ...spread
6179
- };
6180
- }
6181
- var applySvgMatrix = (m, p) => ({ x: m[0] * p.x + m[2] * p.y + m[4], y: m[1] * p.x + m[3] * p.y + m[5] });
6182
- function parseVectorSvg(svg, options = {}) {
6183
- const root = parseXml(svg);
6184
- if (!root) throw new Error("The markup has no <svg> element.");
6185
- let counter = 0;
6186
- const usedIds = /* @__PURE__ */ new Set();
6187
- const createId = options.createId ?? (() => `node-${++counter}`);
6188
- const idFor = (el) => {
6189
- const id = el.attrs.id;
6190
- if (id && !usedIds.has(id)) {
6191
- usedIds.add(id);
6192
- return id;
6193
- }
6194
- let next = createId();
6195
- while (usedIds.has(next)) next = createId();
6196
- usedIds.add(next);
6197
- return next;
6198
- };
6199
- const rawGradients = /* @__PURE__ */ new Map();
6200
- collectGradients(root, rawGradients);
6201
- const rawFilters = /* @__PURE__ */ new Map();
6202
- collectFilters(root, rawFilters);
6203
- const rawMasks = /* @__PURE__ */ new Map();
6204
- collectMasks(root, rawMasks);
6205
- const resolving = /* @__PURE__ */ new Set();
6206
- const filtersOf = (value) => {
6207
- const url = /^url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec((value ?? "").trim());
6208
- const el = url ? rawFilters.get(url[1]) : void 0;
6209
- return el ? filtersFromElement(el) : [];
6210
- };
6211
- const paint = (value) => {
6212
- const v2 = value.trim();
6213
- const url = /^url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec(v2);
6214
- if (url) return resolveGradient(url[1], rawGradients) ?? null;
6215
- if (v2 === "none" || v2 === "") return null;
6216
- return v2;
6217
- };
6218
- const viewBox = numberList(root.attrs.viewBox);
6219
- const width = viewBox.length === 4 ? viewBox[2] : length(root.attrs.width, 300);
6220
- const height = viewBox.length === 4 ? viewBox[3] : length(root.attrs.height, 150);
6221
- const rootMatrix = viewBox.length === 4 ? translateMatrix(-viewBox[0], -viewBox[1]) : IDENTITY_MATRIX;
6222
- const SKIP = /* @__PURE__ */ new Set(["defs", "clipPath", "mask", "symbol", "style", "title", "desc", "metadata", "pattern", "marker", "filter", "text", "image", "use", "linearGradient", "radialGradient", "script", "foreignObject"]);
6223
- const shapeOf = (el) => {
6224
- const a = el.attrs;
6225
- switch (el.name) {
6226
- case "path": {
6227
- if (a["data-vector-d"] && a["data-vector-corners"]) {
6228
- const sharp = bezierToSubpaths(a["data-vector-d"]);
6229
- if (sharp.length) return applyVectorCornersAttribute(sharp, a["data-vector-corners"]);
6230
- }
6231
- return a.d ? bezierToSubpaths(a.d) : null;
6232
- }
6233
- case "rect": {
6234
- const w = length(a.width);
6235
- const h = length(a.height);
6236
- if (w <= 0 || h <= 0) return null;
6237
- const r = length(a.rx ?? a.ry, 0);
6238
- return [rectSubpath({ x: length(a.x), y: length(a.y), width: w, height: h }, r)];
6239
- }
6240
- case "circle": {
6241
- const r = length(a.r);
6242
- if (r <= 0) return null;
6243
- const cx = length(a.cx);
6244
- const cy = length(a.cy);
6245
- return [ellipseSubpath({ x: cx - r, y: cy - r, width: 2 * r, height: 2 * r })];
6246
- }
6247
- case "ellipse": {
6248
- const rx = length(a.rx);
6249
- const ry = length(a.ry);
6250
- if (rx <= 0 || ry <= 0) return null;
6251
- return [ellipseSubpath({ x: length(a.cx) - rx, y: length(a.cy) - ry, width: 2 * rx, height: 2 * ry })];
6252
- }
6253
- case "line":
6254
- return [lineSubpath({ x: length(a.x1), y: length(a.y1) }, { x: length(a.x2), y: length(a.y2) })];
6255
- case "polyline":
6256
- case "polygon": {
6257
- const n = numberList(a.points);
6258
- if (n.length < 4) return null;
6259
- const anchors = [];
6260
- for (let i = 0; i + 1 < n.length; i += 2) anchors.push({ x: n[i], y: n[i + 1] });
6261
- return [{ anchors, closed: el.name === "polygon" }];
6262
- }
6263
- }
6264
- return null;
6265
- };
6266
- const strokeStyle = (s) => ({
6267
- ...s.strokeWidth ? { strokeWidth: length(s.strokeWidth, 1) } : {},
6268
- ...s.strokeLinecap ? { strokeLinecap: s.strokeLinecap } : {},
6269
- ...s.strokeLinejoin ? { strokeLinejoin: s.strokeLinejoin } : {},
6270
- ...s.strokeDasharray && s.strokeDasharray !== "none" ? { strokeDasharray: numberList(s.strokeDasharray) } : {},
6271
- ...s.fillRule === "evenodd" ? { fillRule: "evenodd" } : {}
6272
- });
6273
- const placed = (node, m) => {
6274
- if (m === IDENTITY_MATRIX) return node;
6275
- const next = transformVectorNode(node, m);
6276
- const strokeScale = Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2]));
6277
- if (strokeScale > 0 && Math.abs(strokeScale - 1) > 1e-9) {
6278
- if (hasPaint(next.stroke)) next.strokeWidth = (next.strokeWidth ?? 1) * strokeScale;
6279
- if (Array.isArray(next.strokes)) next.strokes = next.strokes.map((l) => (l.kind ?? "paint") === "paint" ? { ...l, strokeWidth: (l.strokeWidth ?? 1) * strokeScale } : l);
6280
- }
6281
- return normalizeVectorPaintStacks(next, "stack");
6282
- };
6283
- const withOpacities = (node, s) => {
6284
- let out = node;
6285
- const fo = s.fillOpacity !== void 0 ? fraction(s.fillOpacity, 1) : 1;
6286
- const so = s.strokeOpacity !== void 0 ? fraction(s.strokeOpacity, 1) : 1;
6287
- if (fo < 1 && hasPaint(out.fill)) out = withVectorFills(out, [{ paint: out.fill, opacity: Math.max(0, fo) }]);
6288
- if (so < 1 && hasPaint(out.stroke)) out = withVectorStrokes(out, vectorStrokes(out).map((l) => ({ ...l, opacity: Math.max(0, so) })));
6289
- return out;
6290
- };
6291
- const stackedPath = (g, _style, m, meta) => {
6292
- const fillEl = g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === "fill");
6293
- const subpaths = fillEl ? shapeOf(fillEl) : null;
6294
- if (!subpaths?.length) return null;
6295
- const parse = (v2) => {
6296
- try {
6297
- return v2 ? JSON.parse(v2) : [];
6298
- } catch {
6299
- return [];
6300
- }
6301
- };
6302
- let node = { id: idFor(g), type: "path", ...meta, subpaths, fill: null, stroke: null };
6303
- if (g.attrs["data-vector-fill-rule"] === "evenodd") node.fillRule = "evenodd";
6304
- node = withVectorFills(node, sanitizeVectorFills(parse(g.attrs["data-vector-fills"])));
6305
- node = withVectorStrokes(node, sanitizeVectorStrokes(parse(g.attrs["data-vector-strokes"])));
6306
- return placed(node, m);
6307
- };
6308
- const mergeStacked = (nodes2) => {
6309
- const out = [];
6310
- const key = (n) => JSON.stringify([n.subpaths, n.transform ?? null, n.opacity ?? 1, n.visible !== false, n.filters ?? null, n.blendMode ?? "normal", n.fillRule ?? "nonzero", n.booleanOperation ?? null]);
6311
- for (const n of nodes2) {
6312
- const prev = out[out.length - 1];
6313
- if (prev?.type === "path" && n.type === "path" && key(prev) === key(n)) {
6314
- const fills = vectorFills(n);
6315
- const strokesBefore = vectorStrokes(prev);
6316
- if (!(fills.length && strokesBefore.length)) {
6317
- let merged = withVectorFills(prev, [...vectorFills(prev), ...fills]);
6318
- merged = withVectorStrokes(merged, [...strokesBefore, ...vectorStrokes(n)]);
6319
- out[out.length - 1] = merged;
6320
- continue;
6321
- }
6322
- }
6323
- out.push(n);
6324
- }
6325
- return out;
6326
- };
6327
- const mergedPath = (g, style, m, meta) => {
6328
- const part = (name) => g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === name);
6329
- const fillEl = part("fill");
6330
- const subpaths = fillEl ? shapeOf(fillEl) : null;
6331
- if (!fillEl || !subpaths?.length) return null;
6332
- const a = g.attrs;
6333
- const fs = readStyle(fillEl, style);
6334
- const strokeEl = part("stroke");
6335
- const outlineEl = part("stroke-outline");
6336
- const ss = strokeEl ? readStyle(strokeEl, style) : null;
6337
- const width2 = length(a["data-vector-stroke-width"], ss ? length(ss.strokeWidth, 1) : 1);
6338
- const arrow = (v2) => VECTOR_ARROWHEADS.includes(v2) ? v2 : void 0;
6339
- const scale3 = (v2) => {
6340
- const n = v2 === void 0 ? NaN : parseFloat(v2);
6341
- return n > 0 ? n : void 0;
6342
- };
6343
- const align = a["data-vector-stroke-align"];
6344
- const profile = widthProfileFromAttribute(a["data-vector-width-profile"]);
6345
- const kept = (key, values) => values.includes(a[key]) ? a[key] : void 0;
6346
- const keptCap = kept("data-vector-stroke-linecap", ["round", "square"]);
6347
- const keptJoin = kept("data-vector-stroke-linejoin", ["round", "bevel"]);
6348
- const keptDash = a["data-vector-stroke-dasharray"] ? numberList(a["data-vector-stroke-dasharray"]) : void 0;
6349
- const node = {
6350
- id: idFor(g),
6351
- type: "path",
6352
- ...meta,
6353
- subpaths,
6354
- fill: paint(fs.fill),
6355
- stroke: ss ? paint(ss.stroke) : outlineEl ? paint(readStyle(outlineEl, style).fill) : null,
6356
- ...ss ? strokeStyle(ss) : {},
6357
- ...fs.fillRule === "evenodd" ? { fillRule: "evenodd" } : {},
6358
- strokeWidth: width2,
6359
- ...align === "inside" || align === "outside" ? { strokeAlign: align } : {},
6360
- ...arrow(a["data-vector-start-arrow"]) ? { startArrow: arrow(a["data-vector-start-arrow"]) } : {},
6361
- ...arrow(a["data-vector-end-arrow"]) ? { endArrow: arrow(a["data-vector-end-arrow"]) } : {},
6362
- ...a["data-vector-arrow-align"] === "tip" ? { arrowAlign: "tip" } : {},
6363
- ...scale3(a["data-vector-start-arrow-scale"]) ? { startArrowScale: scale3(a["data-vector-start-arrow-scale"]) } : {},
6364
- ...scale3(a["data-vector-end-arrow-scale"]) ? { endArrowScale: scale3(a["data-vector-end-arrow-scale"]) } : {},
6365
- ...profile.length ? { strokeWidthProfile: profile } : {},
6366
- ...keptCap ? { strokeLinecap: keptCap } : {},
6367
- ...keptJoin ? { strokeLinejoin: keptJoin } : {},
6368
- ...keptDash?.length ? { strokeDasharray: keptDash } : {}
6369
- };
6370
- return placed(node, m);
6371
- };
6372
- const liveNode = (g, style, m, meta) => {
6373
- let raw = {};
6374
- try {
6375
- raw = JSON.parse(g.attrs["data-vector-live"]) ?? {};
6376
- } catch {
6377
- raw = {};
6378
- }
6379
- const sourceEl = g.children.find((c) => c.name === "g" && c.attrs["data-vector-part"] === "source");
6380
- if (!sourceEl) return null;
6381
- const inner = visit(sourceEl, style, m);
6382
- const effects = sanitizeVectorEffects(raw.effects);
6383
- const liveBoolean = BOOLEAN_OPERATIONS.includes(raw.liveBoolean) ? raw.liveBoolean : null;
6384
- const id = idFor(g);
6385
- if (raw.kind === "path") {
6386
- const path = inner.find((n) => n.type === "path");
6387
- if (!path) return null;
6388
- const { residual } = decomposeRigid(m);
6389
- const { visible: _v, ...rest } = path;
6390
- return { ...rest, id, ...meta, ...effects.length ? { effects: transformVectorEffects(effects, residual) } : {} };
6391
- }
6392
- if (!inner.length) return null;
6393
- const group = { id, type: "group", ...meta, children: inner };
6394
- if (effects.length) group.effects = transformVectorEffects(effects, m);
6395
- if (liveBoolean) group.liveBoolean = liveBoolean;
6396
- const blend = blendFromAttribute(g.attrs["data-vector-blend"], m);
6397
- if (blend) group.blend = blend;
6398
- return group;
6399
- };
6400
- const visit = (el, style, matrix) => {
6401
- const out = [];
6402
- for (const child of el.children) {
6403
- if (SKIP.has(child.name)) continue;
6404
- const nodes2 = visitOne(child, style, matrix);
6405
- out.push(...nodes2.length ? masked(child, nodes2, multiplyMatrices(parseSvgTransform(child.attrs.transform), matrix)) : nodes2);
6406
- }
6407
- return options.mergeStackedShapes ? mergeStacked(out) : out;
6408
- };
6409
- let rootStyle = { fill: "#000", stroke: "none", strokeWidth: "" };
6410
- const bboxMatrix = (nodes2) => {
6411
- const b = unionBounds(nodes2.map((n) => vectorNodeBounds(n)));
6412
- return b && b.width > 0 && b.height > 0 ? [b.width, 0, 0, b.height, b.x, b.y] : null;
6413
- };
6414
- const maskNode = (el, m, nodes2, units) => {
6415
- const id = el.attrs.id;
6416
- if (!id || resolving.has(id)) return null;
6417
- let space = m;
6418
- if (units === "objectBoundingBox") {
6419
- const box = bboxMatrix(nodes2);
6420
- if (!box) return null;
6421
- space = box;
6422
- }
6423
- resolving.add(id);
6424
- const isClip = el.name === "clipPath";
6425
- const content = isClip ? clipRulesAsFillRules(el) : el;
6426
- const inner = visit(content, readStyle(content, rootStyle), multiplyMatrices(parseSvgTransform(el.attrs.transform), space));
6427
- resolving.delete(id);
6428
- const strip2 = (n) => n.type === "path" ? withVectorStrokes(withVectorFills({ ...n, fill: null, stroke: null }, []), []) : { ...n, children: n.children.map(strip2) };
6429
- const list = isClip ? inner.map(strip2) : inner;
6430
- if (!list.length) return null;
6431
- return list.length === 1 ? list[0] : { id: idFor({ name: "g", attrs: {}, children: [] }), type: "group", name: isClip ? "Clip" : "Mask", children: list };
6432
- };
6433
- const masked = (el, nodes2, m) => {
6434
- let out = nodes2;
6435
- const clipEl = rawMasks.get(urlId(attrOrStyle(el, "clip-path")) ?? "");
6436
- if (clipEl?.name === "clipPath") {
6437
- const source = maskNode(clipEl, m, out, clipEl.attrs.clipPathUnits);
6438
- if (source) out = [{ id: idFor({ name: "g", attrs: {}, children: [] }), type: "group", name: "Clip Group", mask: { type: "clip" }, children: [source, ...out] }];
6439
- }
6440
- const maskEl = rawMasks.get(urlId(attrOrStyle(el, "mask")) ?? "");
6441
- if (maskEl?.name === "mask") {
6442
- const source = maskNode(maskEl, m, out, maskEl.attrs.maskContentUnits);
6443
- const type = attrOrStyle(maskEl, "mask-type") === "alpha" ? "alpha" : "luminance";
6444
- if (source) out = [{ id: idFor({ name: "g", attrs: {}, children: [] }), type: "group", name: "Opacity Mask", mask: { type }, children: [source, ...out] }];
6445
- }
6446
- return out;
6447
- };
6448
- const maskGroup = (g, style, m, meta) => {
6449
- let raw = null;
6450
- try {
6451
- raw = JSON.parse(g.attrs["data-vector-mask"]);
6452
- } catch {
6453
- raw = null;
6454
- }
6455
- const mask = sanitizeVectorMask(raw);
6456
- const part = (name) => g.children.find((c) => c.name === "g" && c.attrs["data-vector-part"] === name);
6457
- const maskedEl = part("masked");
6458
- if (!mask || !maskedEl) return null;
6459
- const id = idFor(g);
6460
- let sourceEl = part("mask-source");
6461
- if (!sourceEl) {
6462
- const el = rawMasks.get(urlId(maskedEl.attrs.mask) ?? "");
6463
- const invert2 = el?.children.find((c) => c.name === "g" && c.attrs["data-vector-part"] === "mask-invert");
6464
- sourceEl = invert2 ?? el;
6465
- }
6466
- const source = sourceEl ? visit(sourceEl, style, m)[0] : void 0;
6467
- let contents = visit(maskedEl, style, m);
6468
- let effects;
6469
- const wrapper = contents.length === 1 && contents[0].type === "group" && contents[0].id === `${id}~content` ? contents[0] : null;
6470
- if (wrapper?.type === "group") {
6471
- effects = wrapper.effects ?? void 0;
6472
- contents = wrapper.children;
6473
- }
6474
- if (!source) return contents.length ? { id, type: "group", ...meta, children: contents } : null;
6475
- return { id, type: "group", ...meta, mask, ...effects?.length ? { effects } : {}, children: [source, ...contents] };
6476
- };
6477
- const visitOne = (child, style, matrix) => {
6478
- const out = [];
6479
- const m = multiplyMatrices(parseSvgTransform(child.attrs.transform), matrix);
6480
- const s = readStyle(child, style);
6481
- const opacity = child.attrs.opacity !== void 0 ? parseFloat(child.attrs.opacity) : void 0;
6482
- const hidden = child.attrs.display === "none" || child.attrs.visibility === "hidden";
6483
- const blendMode = vectorBlendModeFromCss(s.mixBlendMode);
6484
- const filters = filtersOf(s.filter);
6485
- const meta = {
6486
- ...child.attrs["inkscape:label"] || child.attrs["data-name"] ? { name: child.attrs["inkscape:label"] ?? child.attrs["data-name"] } : {},
6487
- ...opacity !== void 0 && Number.isFinite(opacity) && opacity < 1 ? { opacity } : {},
6488
- ...hidden ? { visible: false } : {},
6489
- ...blendMode && blendMode !== "normal" ? { blendMode } : {},
6490
- ...filters.length ? { filters } : {}
6491
- };
6492
- if (child.attrs["data-vector-blend-step"] !== void 0) return out;
6493
- const operation = child.attrs["data-vector-boolean-operation"];
6494
- if (BOOLEAN_OPERATIONS.includes(operation)) meta.booleanOperation = operation;
6495
- if (child.name === "g" && child.attrs["data-vector-mask"] !== void 0) {
6496
- const node2 = maskGroup(child, s, m, meta);
6497
- if (node2) out.push(node2);
6498
- return out;
6499
- }
6500
- if (child.name === "g" && child.attrs["data-vector-live"] !== void 0) {
6501
- const node2 = liveNode(child, s, m, meta);
6502
- if (node2) out.push(node2);
6503
- return out;
6504
- }
6505
- if (child.name === "g" && child.attrs["data-vector-path"] !== void 0 && child.attrs["data-vector-fills"] !== void 0) {
6506
- const node2 = stackedPath(child, s, m, meta);
6507
- if (node2) out.push(node2);
6508
- return out;
6509
- }
6510
- if (child.name === "g" && child.attrs["data-vector-path"] !== void 0) {
6511
- const node2 = mergedPath(child, s, m, meta);
6512
- if (node2) out.push(node2);
6513
- return out;
6514
- }
6515
- if (child.name === "g" || child.name === "svg" || child.name === "a" || child.name === "switch") {
6516
- const children = visit(child, s, m);
6517
- if (!children.length) return out;
6518
- const group = { id: idFor(child), type: "group", ...meta, children };
6519
- const blend = child.name === "g" ? blendFromAttribute(child.attrs["data-vector-blend"], m) : null;
6520
- if (blend) group.blend = blend;
6521
- out.push(group);
6522
- return out;
6523
- }
6524
- const subpaths = shapeOf(child);
6525
- if (!subpaths || !subpaths.length) return out;
6526
- const node = placed(
6527
- withOpacities(
6528
- {
6529
- id: idFor(child),
6530
- type: "path",
6531
- ...meta,
6532
- subpaths,
6533
- fill: child.name === "line" ? null : paint(s.fill),
6534
- stroke: paint(s.stroke),
6535
- ...strokeStyle(s)
6536
- },
6537
- s
6538
- ),
6539
- m
6540
- );
6541
- out.push(node);
6542
- return out;
6543
- };
6544
- rootStyle = readStyle(root, rootStyle);
6545
- const nodes = visit(root, rootStyle, rootMatrix);
6546
- return { width, height, nodes };
6547
- }
6548
-
6549
5292
  export {
6550
5293
  VECTOR_CORNER_KINDS,
6551
5294
  VECTOR_GRADIENT_TYPES,
@@ -6611,6 +5354,19 @@ export {
6611
5354
  convertVectorGradient,
6612
5355
  defaultVectorGradient,
6613
5356
  applyVectorGradientPatch,
5357
+ IDENTITY_MATRIX,
5358
+ multiplyMatrices,
5359
+ translateMatrix,
5360
+ scaleMatrix,
5361
+ rotateMatrix,
5362
+ matrixAbout,
5363
+ skewMatrix,
5364
+ applyMatrix,
5365
+ isIdentityMatrix,
5366
+ invertMatrix,
5367
+ applyMatrixLinear,
5368
+ matrixRotation,
5369
+ decomposeRigid,
6614
5370
  vectorCornerAt,
6615
5371
  vectorCorners,
6616
5372
  cornerSetback,
@@ -6741,6 +5497,28 @@ export {
6741
5497
  vectorMaskedLocalBounds,
6742
5498
  vectorMaskContentBounds,
6743
5499
  vectorMaskRenderData,
5500
+ WARP_STYLES,
5501
+ WARP_STYLE_LABELS,
5502
+ warpPresetGrid,
5503
+ warpPresetMesh,
5504
+ warpMeshColumns,
5505
+ warpMeshRows,
5506
+ isValidWarpMesh,
5507
+ fitWarpMesh,
5508
+ identityWarpMesh,
5509
+ evalWarpMesh,
5510
+ splitWarpMeshU,
5511
+ splitWarpMeshV,
5512
+ removeWarpMeshSplitU,
5513
+ removeWarpMeshSplitV,
5514
+ mapWarpMeshPoints,
5515
+ resizeWarpMesh,
5516
+ warpMeshControlBounds,
5517
+ warpMeshParamAt,
5518
+ dragWarpMeshPoint,
5519
+ pullWarpMesh,
5520
+ warpMeshEditPoints,
5521
+ warpMeshGridCurves,
6744
5522
  vectorMeshFromOutline,
6745
5523
  vectorMeshOutline,
6746
5524
  VECTOR_EFFECT_DEFAULTS,
@@ -6814,36 +5592,6 @@ export {
6814
5592
  polygonSubpath,
6815
5593
  starSubpath,
6816
5594
  lineSubpath,
6817
- roundSubpaths,
6818
- subpathToMorphContour,
6819
- morphContourToSubpath,
6820
- refineMorphContour,
6821
- reverseMorphContour,
6822
- turnMorphContour,
6823
- correspondMorphContours,
6824
- morphPathsCross,
6825
- interpolateMorphContours,
6826
- interpolateRigidMatrix,
6827
- interpolateVectorColor,
6828
- resampleGradientStops,
6829
- interpolateVectorPaint,
6830
- interpolateWidthProfiles,
6831
- interpolateVectorStyle,
6832
- createVectorMorph,
6833
- interpolateVectorPaths,
6834
- evaluateVectorPathKeyframes,
6835
- vectorStrokeGradientDefs,
6836
- vectorCornersAttribute,
6837
- applyVectorCornersAttribute,
6838
- vectorPathLocalBounds,
6839
- vectorPaintToSvg,
6840
- vectorStrokeSvgParts,
6841
- vectorNodeLocalPaintBounds,
6842
- vectorNodeFilterSvg,
6843
- widthProfileToAttribute,
6844
- widthProfileFromAttribute,
6845
- vectorDocumentToSvg,
6846
- parseSvgTransform,
6847
- parseVectorSvg
5595
+ roundSubpaths
6848
5596
  };
6849
- //# sourceMappingURL=chunk-HUQ7EHVI.js.map
5597
+ //# sourceMappingURL=chunk-BLWCAQCW.js.map