@pixerate/editor 0.136.0 → 0.137.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 (132) hide show
  1. package/dist/animation-editor/index.cjs +60 -55
  2. package/dist/animation-editor/index.cjs.map +1 -1
  3. package/dist/animation-editor/index.d.cts +4 -4
  4. package/dist/animation-editor/index.d.ts +4 -4
  5. package/dist/animation-editor/index.js +7 -2
  6. package/dist/animation-editor/index.js.map +1 -1
  7. package/dist/{bezier-CdccFsF8.d.cts → bezier-CZ2AhjID.d.cts} +1 -1
  8. package/dist/{bezier-DG9qNZQV.d.ts → bezier-Dywv3Bw8.d.ts} +1 -1
  9. package/dist/blending-D7jCmjO6.d.cts +1026 -0
  10. package/dist/blending-NgF3qo3d.d.ts +1026 -0
  11. package/dist/brushes-CnvZSYYU.d.cts +744 -0
  12. package/dist/brushes-DJmUbIgz.d.ts +744 -0
  13. package/dist/{brushstrokeRender-SII6MG4R.js → brushstrokeRender-2FAXA3XC.js} +13 -16
  14. package/dist/{brushstrokeRender-SII6MG4R.js.map → brushstrokeRender-2FAXA3XC.js.map} +1 -1
  15. package/dist/{brushstrokeRender-JNHVEUFG.cjs → brushstrokeRender-IMFY3FF6.cjs} +16 -19
  16. package/dist/brushstrokeRender-IMFY3FF6.cjs.map +1 -0
  17. package/dist/canvas/index.cjs +10 -10
  18. package/dist/canvas/index.cjs.map +1 -1
  19. package/dist/canvas/index.d.cts +7 -7
  20. package/dist/canvas/index.d.ts +7 -7
  21. package/dist/canvas/index.js +4 -4
  22. package/dist/{chunk-W4LNKTHT.cjs → chunk-2XS6LTUP.cjs} +63 -63
  23. package/dist/{chunk-W4LNKTHT.cjs.map → chunk-2XS6LTUP.cjs.map} +1 -1
  24. package/dist/{chunk-MAHQC3SK.js → chunk-3D77LOBM.js} +222 -135
  25. package/dist/chunk-3D77LOBM.js.map +1 -0
  26. package/dist/{chunk-BR7EKQUP.js → chunk-3G6J7UFV.js} +322 -2
  27. package/dist/chunk-3G6J7UFV.js.map +1 -0
  28. package/dist/{chunk-62XUO5LB.js → chunk-3X6IAJUQ.js} +2 -2
  29. package/dist/{chunk-EM3FMJWE.js → chunk-5FSRTP6E.js} +320 -3
  30. package/dist/chunk-5FSRTP6E.js.map +1 -0
  31. package/dist/{chunk-2R3UW57U.cjs → chunk-5OOIUXNJ.cjs} +333 -246
  32. package/dist/chunk-5OOIUXNJ.cjs.map +1 -0
  33. package/dist/{chunk-KZXLZCQ7.js → chunk-6S6362D2.js} +2 -2
  34. package/dist/{chunk-24ATT2PE.cjs → chunk-AEAAN4AD.cjs} +120 -120
  35. package/dist/{chunk-24ATT2PE.cjs.map → chunk-AEAAN4AD.cjs.map} +1 -1
  36. package/dist/{chunk-SVYE5HIM.js → chunk-EQQMGO42.js} +2 -2
  37. package/dist/{chunk-FHPVDTI2.cjs → chunk-F2Y4E4GU.cjs} +22 -22
  38. package/dist/{chunk-FHPVDTI2.cjs.map → chunk-F2Y4E4GU.cjs.map} +1 -1
  39. package/dist/{chunk-UYQUPUR6.js → chunk-HUO3TI4C.js} +3 -3
  40. package/dist/{chunk-DDSO4HS7.cjs → chunk-KEENUAFN.cjs} +2 -2
  41. package/dist/{chunk-DDSO4HS7.cjs.map → chunk-KEENUAFN.cjs.map} +1 -1
  42. package/dist/{chunk-2HC4DRF4.js → chunk-LLFHCSU2.js} +2 -2
  43. package/dist/{chunk-J5BA3BQ6.cjs → chunk-O7LUD7MH.cjs} +323 -3
  44. package/dist/chunk-O7LUD7MH.cjs.map +1 -0
  45. package/dist/{chunk-ILYFOJUN.js → chunk-OIBIRXRG.js} +3 -3
  46. package/dist/{chunk-B2CUCM7Y.cjs → chunk-PRSRYHQD.cjs} +36 -36
  47. package/dist/{chunk-B2CUCM7Y.cjs.map → chunk-PRSRYHQD.cjs.map} +1 -1
  48. package/dist/{chunk-6GFRKLLS.cjs → chunk-QBWEH3IM.cjs} +429 -112
  49. package/dist/chunk-QBWEH3IM.cjs.map +1 -0
  50. package/dist/{chunk-6QQR4LKE.js → chunk-SYT2TLQF.js} +35 -37
  51. package/dist/{chunk-6QQR4LKE.js.map → chunk-SYT2TLQF.js.map} +1 -1
  52. package/dist/{chunk-YT3JL7YM.cjs → chunk-TLCTTQFF.cjs} +53 -53
  53. package/dist/{chunk-YT3JL7YM.cjs.map → chunk-TLCTTQFF.cjs.map} +1 -1
  54. package/dist/{chunk-JLGNZMUV.cjs → chunk-XN2NBLV5.cjs} +313 -315
  55. package/dist/chunk-XN2NBLV5.cjs.map +1 -0
  56. package/dist/effects/index.d.cts +4 -4
  57. package/dist/effects/index.d.ts +4 -4
  58. package/dist/{export-Ds7zgGD8.d.ts → export-41rL6Cne.d.ts} +1 -1
  59. package/dist/{export-BOheWw2R.d.cts → export-CyJdfP_Z.d.cts} +5 -4
  60. package/dist/{export-CEYeRQXH.d.cts → export-D9mXp05Q.d.cts} +1 -1
  61. package/dist/{export-ByKKIA2S.d.ts → export-DwnZ_hvQ.d.ts} +5 -4
  62. package/dist/{helpers--ns3W2D7.d.ts → helpers-C-RgeyvH.d.ts} +18 -7
  63. package/dist/{helpers-BVkU4oUi.d.cts → helpers-v6GMazzg.d.cts} +18 -7
  64. package/dist/image-editor/index.cjs +984 -987
  65. package/dist/image-editor/index.cjs.map +1 -1
  66. package/dist/image-editor/index.d.cts +12 -11
  67. package/dist/image-editor/index.d.ts +12 -11
  68. package/dist/image-editor/index.js +92 -95
  69. package/dist/image-editor/index.js.map +1 -1
  70. package/dist/{opentype-yi-Kz4ND.d.cts → opentype-KR_jj6b_.d.cts} +1 -1
  71. package/dist/{opentype-DfoVYgmG.d.ts → opentype-a1KAW-qs.d.ts} +1 -1
  72. package/dist/paint/index.cjs +5 -8
  73. package/dist/paint/index.cjs.map +1 -1
  74. package/dist/paint/index.d.cts +4 -2
  75. package/dist/paint/index.d.ts +4 -2
  76. package/dist/paint/index.js +15 -18
  77. package/dist/paint-editor/index.cjs +403 -404
  78. package/dist/paint-editor/index.cjs.map +1 -1
  79. package/dist/paint-editor/index.d.cts +12 -748
  80. package/dist/paint-editor/index.d.ts +12 -748
  81. package/dist/paint-editor/index.js +77 -78
  82. package/dist/paint-editor/index.js.map +1 -1
  83. package/dist/{pathfinder-7JkMwYvC.d.cts → pathfinder-BHS4vQNm.d.cts} +1 -1
  84. package/dist/{pathfinder-GM3UWdBZ.d.ts → pathfinder-BVvTIBMo.d.ts} +1 -1
  85. package/dist/{pool-CkTxlLMC.d.ts → pool-CZQOrSXZ.d.ts} +1 -1
  86. package/dist/{pool-04qp8iW4.d.cts → pool-FjZZmZ80.d.cts} +1 -1
  87. package/dist/rand-8xbUb6ur.d.ts +1118 -0
  88. package/dist/rand-Cw9VLrVC.d.cts +1118 -0
  89. package/dist/raster/index.cjs +17 -19
  90. package/dist/raster/index.cjs.map +1 -1
  91. package/dist/raster/index.js +9 -11
  92. package/dist/raster/index.js.map +1 -1
  93. package/dist/{svg-rV6_HPmn.d.ts → svg-CSz3mzkw.d.ts} +2 -2
  94. package/dist/{svg-BDDKvWWY.d.cts → svg-DTb40ICU.d.cts} +2 -2
  95. package/dist/{tools-DPYerqeR.d.ts → tools-B0wXP5cF.d.ts} +1 -1
  96. package/dist/{tools-BAjSbTdY.d.cts → tools-Ca0kI1qo.d.cts} +1 -1
  97. package/dist/vector/index.cjs +1459 -1259
  98. package/dist/vector/index.cjs.map +1 -1
  99. package/dist/vector/index.d.cts +87 -11
  100. package/dist/vector/index.d.ts +87 -11
  101. package/dist/vector/index.js +213 -13
  102. package/dist/vector/index.js.map +1 -1
  103. package/dist/video-editor/index.d.cts +4 -4
  104. package/dist/video-editor/index.d.ts +4 -4
  105. package/dist/{warp-DQh9R7Ie.d.cts → warp-DTOp0lON.d.cts} +1 -1
  106. package/dist/{warp-XVL6SpSh.d.ts → warp-pd7hrH4T.d.ts} +1 -1
  107. package/package.json +1 -1
  108. package/skills/pixerate-vector/SKILL.md +8 -0
  109. package/dist/brushstrokeRender-JNHVEUFG.cjs.map +0 -1
  110. package/dist/chunk-2R3UW57U.cjs.map +0 -1
  111. package/dist/chunk-64PYNEHJ.js +0 -340
  112. package/dist/chunk-64PYNEHJ.js.map +0 -1
  113. package/dist/chunk-6GFRKLLS.cjs.map +0 -1
  114. package/dist/chunk-7QN76ESJ.js +0 -323
  115. package/dist/chunk-7QN76ESJ.js.map +0 -1
  116. package/dist/chunk-BR7EKQUP.js.map +0 -1
  117. package/dist/chunk-DCLJNVZS.cjs +0 -323
  118. package/dist/chunk-DCLJNVZS.cjs.map +0 -1
  119. package/dist/chunk-EM3FMJWE.js.map +0 -1
  120. package/dist/chunk-J5BA3BQ6.cjs.map +0 -1
  121. package/dist/chunk-JLGNZMUV.cjs.map +0 -1
  122. package/dist/chunk-MAHQC3SK.js.map +0 -1
  123. package/dist/chunk-Z6OUCS2K.cjs +0 -340
  124. package/dist/chunk-Z6OUCS2K.cjs.map +0 -1
  125. package/dist/rand-BszBST4s.d.ts +0 -2140
  126. package/dist/rand-DOH_aMvm.d.cts +0 -2140
  127. /package/dist/{chunk-62XUO5LB.js.map → chunk-3X6IAJUQ.js.map} +0 -0
  128. /package/dist/{chunk-KZXLZCQ7.js.map → chunk-6S6362D2.js.map} +0 -0
  129. /package/dist/{chunk-SVYE5HIM.js.map → chunk-EQQMGO42.js.map} +0 -0
  130. /package/dist/{chunk-UYQUPUR6.js.map → chunk-HUO3TI4C.js.map} +0 -0
  131. /package/dist/{chunk-2HC4DRF4.js.map → chunk-LLFHCSU2.js.map} +0 -0
  132. /package/dist/{chunk-ILYFOJUN.js.map → chunk-OIBIRXRG.js.map} +0 -0
@@ -1,3 +1,6 @@
1
+ import {
2
+ BUILTIN_BRUSHES
3
+ } from "./chunk-HUO3TI4C.js";
1
4
  import {
2
5
  parseProvenance
3
6
  } from "./chunk-A3BVTI3G.js";
@@ -39,6 +42,11 @@ import {
39
42
  formatNumber,
40
43
  isStraightCubic
41
44
  } from "./chunk-KHNZ6MOU.js";
45
+ import {
46
+ BrushstrokeCache,
47
+ brushstrokeDataUrl,
48
+ isBrushstrokeBrush
49
+ } from "./chunk-5FSRTP6E.js";
42
50
  import {
43
51
  oklabToRgb,
44
52
  rgbToOklab
@@ -2387,6 +2395,193 @@ function vectorStrokeReach(style) {
2387
2395
  return reach;
2388
2396
  }
2389
2397
 
2398
+ // src/vector/extrude.ts
2399
+ function vectorPaintSolid(paint) {
2400
+ if (paint == null || paint === "none") return null;
2401
+ if (typeof paint === "string") return paint;
2402
+ const stops = paint.stops;
2403
+ if (stops?.length) return stops.reduce((a, b) => Math.abs(b.offset - 0.5) < Math.abs(a.offset - 0.5) ? b : a).color;
2404
+ const colors = paint.colors;
2405
+ if (colors?.length) return colors[0];
2406
+ const points = paint.points;
2407
+ return points?.find((p) => typeof p.color === "string")?.color ?? null;
2408
+ }
2409
+ function shadeVectorColor(color2, amount) {
2410
+ const c = parseVectorColor(color2);
2411
+ if (!c) return color2;
2412
+ const a = Math.min(1, Math.max(-1, amount));
2413
+ const target = a >= 0 ? 1 : 0;
2414
+ const h = (v2) => Math.round(Math.min(1, Math.max(0, v2)) * 255).toString(16).padStart(2, "0");
2415
+ const m = [0, 1, 2].map((k) => c[k] + (target - c[k]) * Math.abs(a));
2416
+ return `#${h(m[0])}${h(m[1])}${h(m[2])}`;
2417
+ }
2418
+ function vectorPathRings(path, tolerance = 0.5) {
2419
+ const rings = [];
2420
+ for (const contour of pathToContours(path)) {
2421
+ const ring = flattenChain(closeContour(contour, true), Math.max(1e-3, tolerance));
2422
+ if (ring.length >= 2) rings.push(ring);
2423
+ }
2424
+ return rings;
2425
+ }
2426
+ function vectorExtrudeFaces(path, params) {
2427
+ const box = bezierPathBounds(path);
2428
+ if (!box || !path.length) return [];
2429
+ const perspective = params.mode === "perspective";
2430
+ const rad2 = params.angle * Math.PI / 180;
2431
+ const d = [Math.cos(rad2) * Math.max(0, params.depth), Math.sin(rad2) * Math.max(0, params.depth)];
2432
+ const vp = [(box.minX + box.maxX) / 2 + params.vanishingPoint.x, (box.minY + box.maxY) / 2 + params.vanishingPoint.y];
2433
+ const pull = Math.min(1, Math.max(0, params.toward / 100));
2434
+ const back = (p) => perspective ? [p[0] + (vp[0] - p[0]) * pull, p[1] + (vp[1] - p[1]) * pull] : [p[0] + d[0], p[1] + d[1]];
2435
+ if (perspective ? pull <= 0 : Math.hypot(d[0], d[1]) < 1e-9) return [];
2436
+ const lr = params.lightAngle * Math.PI / 180;
2437
+ const light = [Math.cos(lr), Math.sin(lr)];
2438
+ const strength = Math.min(1, Math.max(0, params.shading / 100));
2439
+ const u = perspective ? [0, 0] : [d[0] / Math.hypot(d[0], d[1]), d[1] / Math.hypot(d[0], d[1])];
2440
+ const centre = [(box.minX + box.maxX) / 2, (box.minY + box.maxY) / 2];
2441
+ const aim = Math.atan2(centre[1] - vp[1], centre[0] - vp[0]);
2442
+ const across = (p) => {
2443
+ if (!perspective) return -p[0] * u[1] + p[1] * u[0];
2444
+ let a = Math.atan2(p[1] - vp[1], p[0] - vp[0]) - aim;
2445
+ while (a > Math.PI) a -= 2 * Math.PI;
2446
+ while (a <= -Math.PI) a += 2 * Math.PI;
2447
+ return a;
2448
+ };
2449
+ const towardBack = (p, q, l) => {
2450
+ const lp = across(p);
2451
+ const lq = across(q);
2452
+ const t = Math.abs(lq - lp) < 1e-12 ? 0.5 : Math.min(1, Math.max(0, (l - lp) / (lq - lp)));
2453
+ const x = [p[0] + (q[0] - p[0]) * t, p[1] + (q[1] - p[1]) * t];
2454
+ return perspective ? -Math.hypot(vp[0] - x[0], vp[1] - x[1]) : x[0] * u[0] + x[1] * u[1];
2455
+ };
2456
+ const faces = [];
2457
+ for (const ring of vectorPathRings(path, 0.25)) {
2458
+ for (let i = 0; i < ring.length; i++) {
2459
+ const p = ring[i];
2460
+ const q = ring[(i + 1) % ring.length];
2461
+ const ex = q[0] - p[0];
2462
+ const ey = q[1] - p[1];
2463
+ const len2 = Math.hypot(ex, ey);
2464
+ if (len2 < 1e-9) continue;
2465
+ const pb = back(p);
2466
+ const qb = back(q);
2467
+ const mid = [(p[0] + q[0]) / 2, (p[1] + q[1]) / 2];
2468
+ const away = perspective ? [vp[0] - mid[0], vp[1] - mid[1]] : d;
2469
+ let n2 = [ey / len2, -ex / len2];
2470
+ if (n2[0] * away[0] + n2[1] * away[1] < 0) n2 = [-n2[0], -n2[1]];
2471
+ const shade = (n2[0] * light[0] + n2[1] * light[1]) * strength;
2472
+ const lp = across(p);
2473
+ const lq = across(q);
2474
+ faces.push({
2475
+ p,
2476
+ q,
2477
+ lo: Math.min(lp, lq),
2478
+ hi: Math.max(lp, lq),
2479
+ key: towardBack(p, q, (lp + lq) / 2),
2480
+ face: {
2481
+ shade,
2482
+ path: [{ type: "M", x: p[0], y: p[1] }, { type: "L", x: q[0], y: q[1] }, { type: "L", x: qb[0], y: qb[1] }, { type: "L", x: pb[0], y: pb[1] }, { type: "Z" }]
2483
+ }
2484
+ });
2485
+ }
2486
+ }
2487
+ faces.sort((a, b) => a.key - b.key);
2488
+ const n = faces.length;
2489
+ const after = faces.map(() => []);
2490
+ const before = new Array(n).fill(0);
2491
+ const eps = 1e-9;
2492
+ for (let i = 0; i < n; i++) {
2493
+ for (let j = i + 1; j < n; j++) {
2494
+ const lo = Math.max(faces[i].lo, faces[j].lo);
2495
+ const hi = Math.min(faces[i].hi, faces[j].hi);
2496
+ if (hi - lo <= eps * Math.max(1, Math.abs(hi))) continue;
2497
+ const l = (lo + hi) / 2;
2498
+ const di = towardBack(faces[i].p, faces[i].q, l);
2499
+ const dj = towardBack(faces[j].p, faces[j].q, l);
2500
+ if (Math.abs(di - dj) < 1e-9) continue;
2501
+ const [back0, front] = di < dj ? [i, j] : [j, i];
2502
+ after[back0].push(front);
2503
+ before[front]++;
2504
+ }
2505
+ }
2506
+ const order = [];
2507
+ const done = new Array(n).fill(false);
2508
+ let next = 0;
2509
+ while (order.length < n) {
2510
+ let pick = -1;
2511
+ for (let i = next; i < n; i++) {
2512
+ if (!done[i] && before[i] === 0) {
2513
+ pick = i;
2514
+ break;
2515
+ }
2516
+ }
2517
+ if (pick < 0) pick = done.indexOf(false);
2518
+ done[pick] = true;
2519
+ order.push(pick);
2520
+ for (const k of after[pick]) before[k]--;
2521
+ while (next < n && done[next]) next++;
2522
+ }
2523
+ return order.map((i) => faces[i].face);
2524
+ }
2525
+
2526
+ // src/vector/brushstroke.ts
2527
+ var VECTOR_BRUSHSTROKE_SCALE = 2;
2528
+ function vectorBrushstrokeBrushes() {
2529
+ return BUILTIN_BRUSHES.filter((b) => isBrushstrokeBrush(b));
2530
+ }
2531
+ function vectorBrushstrokeBrush(id) {
2532
+ return vectorBrushstrokeBrushes().find((b) => b.id === id) ?? null;
2533
+ }
2534
+ function sanitizeVectorBrushstroke(value) {
2535
+ if (!value || typeof value !== "object") return null;
2536
+ const r = value;
2537
+ if (typeof r.brushId !== "string" || !vectorBrushstrokeBrush(r.brushId)) return null;
2538
+ const out = { brushId: r.brushId };
2539
+ if (typeof r.size === "number" && Number.isFinite(r.size) && r.size > 0) out.size = Math.min(500, r.size);
2540
+ if (Array.isArray(r.pressure)) {
2541
+ const p = r.pressure.filter((v2) => typeof v2 === "number" && Number.isFinite(v2)).map((v2) => Math.min(1, Math.max(0, v2)));
2542
+ if (p.length) out.pressure = p.slice(0, 64);
2543
+ }
2544
+ return out;
2545
+ }
2546
+ function isVectorBrushstrokeLayer(layer) {
2547
+ return layer.kind === "brushstroke" && !!layer.brush && !!vectorBrushstrokeBrush(layer.brush.brushId);
2548
+ }
2549
+ function vectorBrushstrokeReach(layer) {
2550
+ if (!isVectorBrushstrokeLayer(layer)) return 0;
2551
+ return (layer.brush.size ?? vectorBrushstrokeBrush(layer.brush.brushId).tip.size) / 2;
2552
+ }
2553
+ var cache = new BrushstrokeCache(256);
2554
+ var urls = /* @__PURE__ */ new WeakMap();
2555
+ var layerCache = /* @__PURE__ */ new WeakMap();
2556
+ function vectorBrushstrokeImages(node, layer) {
2557
+ if (!isVectorBrushstrokeLayer(layer)) return [];
2558
+ let byLayer = layerCache.get(node);
2559
+ const hit = byLayer?.get(layer);
2560
+ if (hit) return hit;
2561
+ const preset = vectorBrushstrokeBrush(layer.brush.brushId);
2562
+ const brush = layer.brush.size ? { ...preset, tip: { ...preset.tip, size: layer.brush.size } } : preset;
2563
+ const solid = vectorPaintSolid(layer.paint) ?? "#000000";
2564
+ const c = parseVectorColor(solid) ?? [0, 0, 0, 1];
2565
+ const color2 = [c[0] * 255, c[1] * 255, c[2] * 255, c[3] * 255].map(Math.round);
2566
+ const out = [];
2567
+ for (const sp of node.subpaths) {
2568
+ if (sp.anchors.length < 2) continue;
2569
+ for (const contour of pathToContours(subpathsToBezier([sp]))) {
2570
+ const ring = flattenChain(closeContour(contour, contour.closed), 0.25);
2571
+ if (contour.closed && ring.length > 2) ring.push(ring[0]);
2572
+ if (ring.length < 2) continue;
2573
+ const stroke = cache.render({ points: ring.map(([x, y]) => ({ x, y })), ...layer.brush.pressure ? { pressure: layer.brush.pressure } : {} }, brush, { scale: VECTOR_BRUSHSTROKE_SCALE, color: color2, maxPixels: 2048 * 2048 });
2574
+ if (!stroke.bounds) continue;
2575
+ let href = urls.get(stroke);
2576
+ if (!href) urls.set(stroke, href = brushstrokeDataUrl(stroke));
2577
+ out.push({ href, ...stroke.bounds });
2578
+ }
2579
+ }
2580
+ if (!byLayer) layerCache.set(node, byLayer = /* @__PURE__ */ new Map());
2581
+ byLayer.set(layer, out);
2582
+ return out;
2583
+ }
2584
+
2390
2585
  // src/vector/paintLayers.ts
2391
2586
  var VECTOR_STROKE_SETTING_KEYS = [
2392
2587
  "strokeWidth",
@@ -2586,6 +2781,10 @@ function sanitizeVectorStrokeSettings(raw) {
2586
2781
  function sanitizeVectorStrokes(value) {
2587
2782
  if (!Array.isArray(value)) return [];
2588
2783
  return value.filter((l) => !!l && typeof l === "object").map((raw) => {
2784
+ if (raw.kind === "brushstroke") {
2785
+ const brush = sanitizeVectorBrushstroke(raw.brush);
2786
+ if (brush) return { ...sanitizeLayerBase(raw), kind: "brushstroke", brush };
2787
+ }
2589
2788
  if (raw.kind !== void 0 && raw.kind !== "paint") return { ...raw };
2590
2789
  return { ...sanitizeLayerBase(raw), ...sanitizeVectorStrokeSettings(raw) };
2591
2790
  });
@@ -2616,7 +2815,10 @@ function needsVectorPaintLayers(node) {
2616
2815
  }
2617
2816
  function vectorStrokeStackReach(node) {
2618
2817
  let reach = 0;
2619
- for (const l of vectorPaintLayerNodes(node)) if (l.kind === "stroke" && l.drawn) reach = Math.max(reach, vectorStrokeReach(l.node));
2818
+ for (const l of vectorPaintLayerNodes(node)) {
2819
+ if (l.kind === "stroke" && l.drawn) reach = Math.max(reach, vectorStrokeReach(l.node));
2820
+ else if (l.kind === "stroke" && l.layer.visible !== false) reach = Math.max(reach, vectorBrushstrokeReach(l.layer));
2821
+ }
2620
2822
  return reach;
2621
2823
  }
2622
2824
  function hitTestVectorPaintLayer(node, path, p, tolerance = 0) {
@@ -5560,134 +5762,6 @@ function vectorInstanceGroup(node, bake) {
5560
5762
  }
5561
5763
  var composeVectorMatrices = (a, b) => multiplyMatrices(a, b);
5562
5764
 
5563
- // src/vector/extrude.ts
5564
- function vectorPaintSolid(paint) {
5565
- if (paint == null || paint === "none") return null;
5566
- if (typeof paint === "string") return paint;
5567
- const stops = paint.stops;
5568
- if (stops?.length) return stops.reduce((a, b) => Math.abs(b.offset - 0.5) < Math.abs(a.offset - 0.5) ? b : a).color;
5569
- const colors = paint.colors;
5570
- if (colors?.length) return colors[0];
5571
- const points = paint.points;
5572
- return points?.find((p) => typeof p.color === "string")?.color ?? null;
5573
- }
5574
- function shadeVectorColor(color2, amount) {
5575
- const c = parseVectorColor(color2);
5576
- if (!c) return color2;
5577
- const a = Math.min(1, Math.max(-1, amount));
5578
- const target = a >= 0 ? 1 : 0;
5579
- const h = (v2) => Math.round(Math.min(1, Math.max(0, v2)) * 255).toString(16).padStart(2, "0");
5580
- const m = [0, 1, 2].map((k) => c[k] + (target - c[k]) * Math.abs(a));
5581
- return `#${h(m[0])}${h(m[1])}${h(m[2])}`;
5582
- }
5583
- function vectorPathRings(path, tolerance = 0.5) {
5584
- const rings = [];
5585
- for (const contour of pathToContours(path)) {
5586
- const ring = flattenChain(closeContour(contour, true), Math.max(1e-3, tolerance));
5587
- if (ring.length >= 2) rings.push(ring);
5588
- }
5589
- return rings;
5590
- }
5591
- function vectorExtrudeFaces(path, params) {
5592
- const box = bezierPathBounds(path);
5593
- if (!box || !path.length) return [];
5594
- const perspective = params.mode === "perspective";
5595
- const rad2 = params.angle * Math.PI / 180;
5596
- const d = [Math.cos(rad2) * Math.max(0, params.depth), Math.sin(rad2) * Math.max(0, params.depth)];
5597
- const vp = [(box.minX + box.maxX) / 2 + params.vanishingPoint.x, (box.minY + box.maxY) / 2 + params.vanishingPoint.y];
5598
- const pull = Math.min(1, Math.max(0, params.toward / 100));
5599
- const back = (p) => perspective ? [p[0] + (vp[0] - p[0]) * pull, p[1] + (vp[1] - p[1]) * pull] : [p[0] + d[0], p[1] + d[1]];
5600
- if (perspective ? pull <= 0 : Math.hypot(d[0], d[1]) < 1e-9) return [];
5601
- const lr = params.lightAngle * Math.PI / 180;
5602
- const light = [Math.cos(lr), Math.sin(lr)];
5603
- const strength = Math.min(1, Math.max(0, params.shading / 100));
5604
- const u = perspective ? [0, 0] : [d[0] / Math.hypot(d[0], d[1]), d[1] / Math.hypot(d[0], d[1])];
5605
- const centre = [(box.minX + box.maxX) / 2, (box.minY + box.maxY) / 2];
5606
- const aim = Math.atan2(centre[1] - vp[1], centre[0] - vp[0]);
5607
- const across = (p) => {
5608
- if (!perspective) return -p[0] * u[1] + p[1] * u[0];
5609
- let a = Math.atan2(p[1] - vp[1], p[0] - vp[0]) - aim;
5610
- while (a > Math.PI) a -= 2 * Math.PI;
5611
- while (a <= -Math.PI) a += 2 * Math.PI;
5612
- return a;
5613
- };
5614
- const towardBack = (p, q, l) => {
5615
- const lp = across(p);
5616
- const lq = across(q);
5617
- const t = Math.abs(lq - lp) < 1e-12 ? 0.5 : Math.min(1, Math.max(0, (l - lp) / (lq - lp)));
5618
- const x = [p[0] + (q[0] - p[0]) * t, p[1] + (q[1] - p[1]) * t];
5619
- return perspective ? -Math.hypot(vp[0] - x[0], vp[1] - x[1]) : x[0] * u[0] + x[1] * u[1];
5620
- };
5621
- const faces = [];
5622
- for (const ring of vectorPathRings(path, 0.25)) {
5623
- for (let i = 0; i < ring.length; i++) {
5624
- const p = ring[i];
5625
- const q = ring[(i + 1) % ring.length];
5626
- const ex = q[0] - p[0];
5627
- const ey = q[1] - p[1];
5628
- const len2 = Math.hypot(ex, ey);
5629
- if (len2 < 1e-9) continue;
5630
- const pb = back(p);
5631
- const qb = back(q);
5632
- const mid = [(p[0] + q[0]) / 2, (p[1] + q[1]) / 2];
5633
- const away = perspective ? [vp[0] - mid[0], vp[1] - mid[1]] : d;
5634
- let n2 = [ey / len2, -ex / len2];
5635
- if (n2[0] * away[0] + n2[1] * away[1] < 0) n2 = [-n2[0], -n2[1]];
5636
- const shade = (n2[0] * light[0] + n2[1] * light[1]) * strength;
5637
- const lp = across(p);
5638
- const lq = across(q);
5639
- faces.push({
5640
- p,
5641
- q,
5642
- lo: Math.min(lp, lq),
5643
- hi: Math.max(lp, lq),
5644
- key: towardBack(p, q, (lp + lq) / 2),
5645
- face: {
5646
- shade,
5647
- path: [{ type: "M", x: p[0], y: p[1] }, { type: "L", x: q[0], y: q[1] }, { type: "L", x: qb[0], y: qb[1] }, { type: "L", x: pb[0], y: pb[1] }, { type: "Z" }]
5648
- }
5649
- });
5650
- }
5651
- }
5652
- faces.sort((a, b) => a.key - b.key);
5653
- const n = faces.length;
5654
- const after = faces.map(() => []);
5655
- const before = new Array(n).fill(0);
5656
- const eps = 1e-9;
5657
- for (let i = 0; i < n; i++) {
5658
- for (let j = i + 1; j < n; j++) {
5659
- const lo = Math.max(faces[i].lo, faces[j].lo);
5660
- const hi = Math.min(faces[i].hi, faces[j].hi);
5661
- if (hi - lo <= eps * Math.max(1, Math.abs(hi))) continue;
5662
- const l = (lo + hi) / 2;
5663
- const di = towardBack(faces[i].p, faces[i].q, l);
5664
- const dj = towardBack(faces[j].p, faces[j].q, l);
5665
- if (Math.abs(di - dj) < 1e-9) continue;
5666
- const [back0, front] = di < dj ? [i, j] : [j, i];
5667
- after[back0].push(front);
5668
- before[front]++;
5669
- }
5670
- }
5671
- const order = [];
5672
- const done = new Array(n).fill(false);
5673
- let next = 0;
5674
- while (order.length < n) {
5675
- let pick = -1;
5676
- for (let i = next; i < n; i++) {
5677
- if (!done[i] && before[i] === 0) {
5678
- pick = i;
5679
- break;
5680
- }
5681
- }
5682
- if (pick < 0) pick = done.indexOf(false);
5683
- done[pick] = true;
5684
- order.push(pick);
5685
- for (const k of after[pick]) before[k]--;
5686
- while (next < n && done[next]) next++;
5687
- }
5688
- return order.map((i) => faces[i].face);
5689
- }
5690
-
5691
5765
  // src/vector/bevel.ts
5692
5766
  var MITER_LIMIT = 4;
5693
5767
  function crossing2(a, b, c, d) {
@@ -8313,13 +8387,19 @@ function vectorDocumentToSvg(doc, options = {}) {
8313
8387
  let data = ` data-vector-path="" data-vector-fills="${escapeAttr2(JSON.stringify(vectorFills(node)))}" data-vector-strokes="${escapeAttr2(JSON.stringify(vectorStrokes(node)))}"`;
8314
8388
  if (node.fillRule === "evenodd") data += ` data-vector-fill-rule="evenodd"`;
8315
8389
  lines.push(`${indent(depth)}<g${common(node)}${data}>`);
8316
- const layers = vectorPaintLayerNodes(node).filter((l) => l.drawn);
8390
+ const layers = vectorPaintLayerNodes(node).filter((l) => l.drawn || l.kind === "stroke" && isVectorBrushstrokeLayer(l.layer) && l.layer.visible !== false);
8317
8391
  let geometry = liveCorners(node);
8318
8392
  if (!layers.some((l) => l.kind === "fill")) {
8319
8393
  lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}" fill="none"${rule}${geometry}/>`);
8320
8394
  geometry = "";
8321
8395
  }
8322
8396
  for (const l of layers) {
8397
+ if (l.kind === "stroke" && isVectorBrushstrokeLayer(l.layer)) {
8398
+ lines.push(`${indent(depth + 1)}<g data-vector-part="brushstroke" data-vector-layer="${l.index}"${layerAttrs(l.layer)}>`);
8399
+ for (const im of vectorBrushstrokeImages(node, l.layer)) lines.push(`${indent(depth + 2)}<image href="${im.href}" x="${num3(im.x)}" y="${num3(im.y)}" width="${num3(im.width)}" height="${num3(im.height)}" preserveAspectRatio="none"/>`);
8400
+ lines.push(`${indent(depth + 1)}</g>`);
8401
+ continue;
8402
+ }
8323
8403
  const id = `${prefix}${l.kind}-${node.id}-${l.index}`;
8324
8404
  const paint = vectorPaintToSvg(l.layer.paint, id, { node: l.node, precision, ...l.kind === "stroke" ? { role: "stroke" } : {} });
8325
8405
  defs.push(...paintMarkup(l.layer.paint, paint.defs));
@@ -10374,6 +10454,17 @@ export {
10374
10454
  vectorStrokeOutlinePath,
10375
10455
  hitTestVectorStroke,
10376
10456
  vectorStrokeReach,
10457
+ vectorPaintSolid,
10458
+ shadeVectorColor,
10459
+ vectorPathRings,
10460
+ vectorExtrudeFaces,
10461
+ VECTOR_BRUSHSTROKE_SCALE,
10462
+ vectorBrushstrokeBrushes,
10463
+ vectorBrushstrokeBrush,
10464
+ sanitizeVectorBrushstroke,
10465
+ isVectorBrushstrokeLayer,
10466
+ vectorBrushstrokeReach,
10467
+ vectorBrushstrokeImages,
10377
10468
  VECTOR_STROKE_SETTING_KEYS,
10378
10469
  VECTOR_BLEND_MODE_LABELS,
10379
10470
  isVectorBlendMode,
@@ -10537,10 +10628,6 @@ export {
10537
10628
  prefixVectorIds,
10538
10629
  vectorInstanceGroup,
10539
10630
  composeVectorMatrices,
10540
- vectorPaintSolid,
10541
- shadeVectorColor,
10542
- vectorPathRings,
10543
- vectorExtrudeFaces,
10544
10631
  vectorBevelFaces,
10545
10632
  isVectorLens,
10546
10633
  VECTOR_LENS_LABELS,
@@ -10685,4 +10772,4 @@ export {
10685
10772
  lineSubpath,
10686
10773
  roundSubpaths
10687
10774
  };
10688
- //# sourceMappingURL=chunk-MAHQC3SK.js.map
10775
+ //# sourceMappingURL=chunk-3D77LOBM.js.map