@pixerate/editor 0.254.1 → 0.256.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 (81) hide show
  1. package/dist/agent/index.cjs +2 -2
  2. package/dist/agent/index.js +1 -1
  3. package/dist/animation-editor/index.cjs +59 -59
  4. package/dist/animation-editor/index.js +3 -3
  5. package/dist/brushes/index.cjs +31 -29
  6. package/dist/brushes/index.d.cts +1 -1
  7. package/dist/brushes/index.d.ts +1 -1
  8. package/dist/brushes/index.js +27 -25
  9. package/dist/brushes/library.d.cts +17 -0
  10. package/dist/brushes/library.d.ts +17 -0
  11. package/dist/{brushstrokeRender-5PYSKZIJ.js → brushstrokeRender-HCOQUSWW.js} +53 -18
  12. package/dist/{brushstrokeRender-7FLLSQEC.cjs → brushstrokeRender-ZZOXI5O5.cjs} +55 -20
  13. package/dist/canvas/brushTypes.d.cts +22 -3
  14. package/dist/canvas/brushTypes.d.ts +22 -3
  15. package/dist/canvas/brushstroke.d.cts +34 -12
  16. package/dist/canvas/brushstroke.d.ts +34 -12
  17. package/dist/canvas/brushstrokeRender.d.cts +14 -8
  18. package/dist/canvas/brushstrokeRender.d.ts +14 -8
  19. package/dist/canvas/drawController.d.cts +11 -3
  20. package/dist/canvas/drawController.d.ts +11 -3
  21. package/dist/canvas/freehand.d.cts +6 -1
  22. package/dist/canvas/freehand.d.ts +6 -1
  23. package/dist/canvas/index.cjs +114 -102
  24. package/dist/canvas/index.js +16 -4
  25. package/dist/{chunk-XVIK73LS.js → chunk-5P4JEOIV.js} +4 -4
  26. package/dist/{chunk-JPEHXIB5.cjs → chunk-5YWWQ36H.cjs} +66 -21
  27. package/dist/{chunk-CHAWTXBE.cjs → chunk-6WCQ35GI.cjs} +4 -4
  28. package/dist/{chunk-GYMMNCFT.js → chunk-AF23QK5F.js} +56 -11
  29. package/dist/{chunk-JFHBXNR2.cjs → chunk-B7V34GIH.cjs} +86 -86
  30. package/dist/{chunk-QC3OXRE4.js → chunk-DMTEQ6SH.js} +1 -1
  31. package/dist/{chunk-TLOGFIIV.cjs → chunk-GCTUOTCW.cjs} +35 -35
  32. package/dist/{chunk-34KLWUH4.cjs → chunk-HIMGBZAM.cjs} +1133 -597
  33. package/dist/{chunk-7P6VF3FG.js → chunk-HYWRU5VX.js} +1 -1
  34. package/dist/{chunk-QPHNVZHO.js → chunk-JVRLGV3C.js} +1118 -582
  35. package/dist/{chunk-LFMKWGFL.cjs → chunk-LRNUZKWV.cjs} +22 -8
  36. package/dist/chunk-PGPFWC35.cjs +517 -0
  37. package/dist/{chunk-QLSGTCYT.cjs → chunk-TBAVCLEQ.cjs} +23 -23
  38. package/dist/{chunk-2ZJ4DT3M.js → chunk-VUKUTT2W.js} +1 -1
  39. package/dist/{chunk-5JNA6LLY.js → chunk-WYGSR3IJ.js} +22 -8
  40. package/dist/chunk-YHUMGBZD.js +517 -0
  41. package/dist/commands/builtins.d.cts +1 -1
  42. package/dist/commands/builtins.d.ts +1 -1
  43. package/dist/commands/index.cjs +2 -2
  44. package/dist/commands/index.js +1 -1
  45. package/dist/image-editor/brush-presets.d.cts +32 -0
  46. package/dist/image-editor/brush-presets.d.ts +32 -0
  47. package/dist/image-editor/controller.d.cts +15 -0
  48. package/dist/image-editor/controller.d.ts +15 -0
  49. package/dist/image-editor/index.cjs +848 -775
  50. package/dist/image-editor/index.d.cts +1 -0
  51. package/dist/image-editor/index.d.ts +1 -0
  52. package/dist/image-editor/index.js +81 -8
  53. package/dist/image-editor/types.d.cts +7 -0
  54. package/dist/image-editor/types.d.ts +7 -0
  55. package/dist/paint-editor/collaboration-tools.d.cts +19 -0
  56. package/dist/paint-editor/collaboration-tools.d.ts +19 -0
  57. package/dist/paint-editor/collaboration.d.cts +180 -0
  58. package/dist/paint-editor/collaboration.d.ts +180 -0
  59. package/dist/paint-editor/controller.d.cts +54 -0
  60. package/dist/paint-editor/controller.d.ts +54 -0
  61. package/dist/paint-editor/index.cjs +816 -283
  62. package/dist/paint-editor/index.d.cts +2 -0
  63. package/dist/paint-editor/index.d.ts +2 -0
  64. package/dist/paint-editor/index.js +567 -34
  65. package/dist/vector/brushstroke.d.cts +21 -5
  66. package/dist/vector/brushstroke.d.ts +21 -5
  67. package/dist/vector/controller.d.cts +14 -1
  68. package/dist/vector/controller.d.ts +14 -1
  69. package/dist/vector/index.cjs +1220 -1199
  70. package/dist/vector/index.js +34 -13
  71. package/dist/vector/types.d.cts +7 -0
  72. package/dist/vector/types.d.ts +7 -0
  73. package/package.json +1 -1
  74. package/skills/pixerate-brushes/SKILL.md +9 -3
  75. package/skills/pixerate-canvas/SKILL.md +10 -5
  76. package/skills/pixerate-image-editor/SKILL.md +2 -1
  77. package/skills/pixerate-paint-editor/SKILL.md +31 -46
  78. package/skills/pixerate-paint-editor/references/painting-alongside.md +19 -0
  79. package/skills/pixerate-vector/SKILL.md +1 -1
  80. package/dist/chunk-HS6QDWDF.cjs +0 -1029
  81. package/dist/chunk-MTKY6K3Q.js +0 -1029
@@ -13,15 +13,7 @@ var _chunkSABJMH6Mcjs = require('../chunk-SABJMH6M.cjs');
13
13
 
14
14
 
15
15
 
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
- var _chunk34KLWUH4cjs = require('../chunk-34KLWUH4.cjs');
16
+ var _chunkPGPFWC35cjs = require('../chunk-PGPFWC35.cjs');
25
17
 
26
18
 
27
19
  var _chunkCBVNCWJMcjs = require('../chunk-CBVNCWJM.cjs');
@@ -32,7 +24,7 @@ var _chunkCBVNCWJMcjs = require('../chunk-CBVNCWJM.cjs');
32
24
 
33
25
 
34
26
 
35
- var _chunkJFHBXNR2cjs = require('../chunk-JFHBXNR2.cjs');
27
+ var _chunkB7V34GIHcjs = require('../chunk-B7V34GIH.cjs');
36
28
  require('../chunk-A2IS7EHE.cjs');
37
29
  require('../chunk-SS53NNZO.cjs');
38
30
 
@@ -88,7 +80,9 @@ var _chunkJLWLX52Lcjs = require('../chunk-JLWLX52L.cjs');
88
80
 
89
81
 
90
82
  var _chunkK7ENM55Pcjs = require('../chunk-K7ENM55P.cjs');
91
- require('../chunk-JPEHXIB5.cjs');
83
+ require('../chunk-5YWWQ36H.cjs');
84
+
85
+
92
86
 
93
87
 
94
88
 
@@ -134,7 +128,13 @@ require('../chunk-JPEHXIB5.cjs');
134
128
 
135
129
 
136
130
 
137
- var _chunkHS6QDWDFcjs = require('../chunk-HS6QDWDF.cjs');
131
+
132
+
133
+
134
+
135
+
136
+
137
+ var _chunkHIMGBZAMcjs = require('../chunk-HIMGBZAM.cjs');
138
138
 
139
139
 
140
140
 
@@ -370,8 +370,8 @@ function normalizePaper(raw = {}, base) {
370
370
  ...readOffset(r.offset, b.offset)
371
371
  };
372
372
  }
373
- function hexToRgb8(hex) {
374
- const n = parseInt(hex.slice(1, 7), 16);
373
+ function hexToRgb8(hex2) {
374
+ const n = parseInt(hex2.slice(1, 7), 16);
375
375
  return [n >> 16 & 255, n >> 8 & 255, n & 255];
376
376
  }
377
377
  function renderPaper(paper, rect, grain = new (0, _chunkPXDIAYB6cjs.PaperGrain)(paper), light) {
@@ -1616,7 +1616,7 @@ function shadowToLight(shadow) {
1616
1616
  return new (0, _chunk474IQG74cjs.TiledSurface)(1, tiles, 0);
1617
1617
  }
1618
1618
  function lightTwinBrush(brush) {
1619
- return _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0,
1619
+ return _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0,
1620
1620
  {
1621
1621
  tip: { ...brush.tip, blend: "normal", pressureOpacity: brush.tip.pressureOpacity || brush.light.pressure },
1622
1622
  behavior: { ...brush.behavior, mixing: "rgb" },
@@ -1929,8 +1929,8 @@ function sampleArt(art, x, y, out) {
1929
1929
  }
1930
1930
 
1931
1931
  // src/paint-editor/stickers.ts
1932
- function hexRgb(hex) {
1933
- const n = parseInt(hex.slice(1, 7), 16);
1932
+ function hexRgb(hex2) {
1933
+ const n = parseInt(hex2.slice(1, 7), 16);
1934
1934
  return [(n >> 16 & 255) / 255, (n >> 8 & 255) / 255, (n & 255) / 255];
1935
1935
  }
1936
1936
  function stickerRect(s) {
@@ -2014,8 +2014,8 @@ function drawArtSticker(medium, s, art) {
2014
2014
  medium.deposit(rect, cov, s.opacity, [r, g, b], null, field);
2015
2015
  return rect;
2016
2016
  }
2017
- function jitterColor(hex, amount, seed, i) {
2018
- const [r, g, b] = hexRgb(hex);
2017
+ function jitterColor(hex2, amount, seed, i) {
2018
+ const [r, g, b] = hexRgb(hex2);
2019
2019
  const lch = _chunk5UEFBM2Mcjs.oklabToOklch.call(void 0, _chunk5UEFBM2Mcjs.rgbToOklab.call(void 0, { r, g, b, a: 1 }));
2020
2020
  const l = Math.min(1, Math.max(0, lch.l + (_chunk3K6HWEXZcjs.rand01.call(void 0, seed, i, 61) - 0.5) * amount * 0.3));
2021
2021
  const h = lch.h + (_chunk3K6HWEXZcjs.rand01.call(void 0, seed, i, 63) - 0.5) * amount * 80;
@@ -2846,7 +2846,7 @@ var PaintStrokeSession = (_class12 = class _PaintStrokeSession {
2846
2846
  } else if (init.thick) {
2847
2847
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
2848
2848
  this.thickDriver = new ThickStrokeDriver({ brush, target: this.tileTarget(), channels: init.thick.channels, color: rgb(init.color), load: init.mixerLoad, seed: init.seed, copies: this.copies, paint: _nullishCoalesce(init.paint, () => ( null)), effect });
2849
- } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunkHS6QDWDFcjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
2849
+ } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunkHIMGBZAMcjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
2850
2850
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
2851
2851
  this.wet = new PaintDabStroke(brush, {
2852
2852
  target: this.tileTarget(),
@@ -2897,7 +2897,7 @@ var PaintStrokeSession = (_class12 = class _PaintStrokeSession {
2897
2897
  const init = this.init;
2898
2898
  const grey = Math.round(init.brush.light.amount * 255);
2899
2899
  const g = grey / 255;
2900
- const hex = "#" + grey.toString(16).padStart(2, "0").repeat(3);
2900
+ const hex2 = "#" + grey.toString(16).padStart(2, "0").repeat(3);
2901
2901
  const host = {
2902
2902
  update: () => {
2903
2903
  },
@@ -2906,14 +2906,14 @@ var PaintStrokeSession = (_class12 = class _PaintStrokeSession {
2906
2906
  }
2907
2907
  };
2908
2908
  const effect = init.effect ? { source: init.effect.source, pixels: { ...init.effect.pixels, data: greyPixels(init.effect.pixels.data, grey) } } : null;
2909
- const paint = init.paint ? { ...init.paint, stops: init.paint.stops.map((st) => ({ ...st, color: hex })) } : null;
2909
+ const paint = init.paint ? { ...init.paint, stops: init.paint.stops.map((st) => ({ ...st, color: hex2 })) } : null;
2910
2910
  return new _PaintStrokeSession(host, {
2911
2911
  ...init,
2912
2912
  surface: lightToShadow(light),
2913
2913
  lockTransparency: false,
2914
2914
  brush: lightTwinBrush(init.brush),
2915
2915
  color: [grey, grey, grey, 255],
2916
- colorHex: hex,
2916
+ colorHex: hex2,
2917
2917
  secondary: [grey, grey, grey, 255],
2918
2918
  inputFilter: void 0,
2919
2919
  mixerLoad: { reservoir: init.mixerLoad.reservoir ? [g, g, g] : null, amount: init.mixerLoad.amount, pickup: null },
@@ -3084,7 +3084,7 @@ function brushLoadForStroke(brush, current, color) {
3084
3084
  if (brush.engine === "mixer") return mixerLoadForStroke(brush, current, color);
3085
3085
  if (brush.engine === "impasto") return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
3086
3086
  if (brush.engine === "wet") return brush.wet.tool === "paint" ? { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null } : _chunkFQPUF2W2cjs.EMPTY_MIXER_LOAD;
3087
- if (_chunkHS6QDWDFcjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
3087
+ if (_chunkHIMGBZAMcjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
3088
3088
  return _chunkFQPUF2W2cjs.EMPTY_MIXER_LOAD;
3089
3089
  }
3090
3090
 
@@ -3346,15 +3346,15 @@ function readLoad(raw) {
3346
3346
  function readStrokeBrush(raw) {
3347
3347
  if (raw && typeof raw === "object" && "kind" in raw && !("engine" in raw)) {
3348
3348
  try {
3349
- return _chunk34KLWUH4cjs.resolveBrush.call(void 0, _chunk34KLWUH4cjs.normalizeBrushSpec.call(void 0, raw));
3349
+ return _chunkHIMGBZAMcjs.resolveBrush.call(void 0, _chunkHIMGBZAMcjs.normalizeBrushSpec.call(void 0, raw));
3350
3350
  } catch (e4) {
3351
3351
  }
3352
3352
  }
3353
- return _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, _nullishCoalesce(raw, () => ( {})));
3353
+ return _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, _nullishCoalesce(raw, () => ( {})));
3354
3354
  }
3355
3355
  function strokeToJSON(stroke) {
3356
3356
  const { brush, ...rest } = stroke;
3357
- return { ...JSON.parse(JSON.stringify(rest)), brush: _chunk34KLWUH4cjs.migrateBrushV1.call(void 0, brush) };
3357
+ return { ...JSON.parse(JSON.stringify(rest)), brush: _chunkHIMGBZAMcjs.migrateBrushV1.call(void 0, brush) };
3358
3358
  }
3359
3359
  function normalizeBrushStroke(raw) {
3360
3360
  if (!raw || typeof raw !== "object") return null;
@@ -3424,7 +3424,7 @@ function varyStroke(stroke, m, v) {
3424
3424
  if (ps !== 1) q.pressure = Math.min(1, Math.max(0, (_nullishCoalesce(p.pressure, () => ( 1))) * ps));
3425
3425
  return q;
3426
3426
  });
3427
- const brush = s !== 1 ? _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
3427
+ const brush = s !== 1 ? _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
3428
3428
  const out = { ...stroke, brush, points };
3429
3429
  if (_optionalChain([stroke, 'access', _108 => _108.paint, 'optionalAccess', _109 => _109.type]) === "gradient" && s !== 1) out.paint = _chunkFQPUF2W2cjs.scalePaintGradient.call(void 0, stroke.paint, s);
3430
3430
  if (_optionalChain([stroke, 'access', _110 => _110.paint, 'optionalAccess', _111 => _111.type]) === "effect" && stroke.paint.map && s !== 1) out.paint = { ...stroke.paint, map: { ...stroke.paint.map, length: Math.min(4096, Math.max(16, Math.round(stroke.paint.map.length * s))) } };
@@ -3574,11 +3574,11 @@ function header(state, options) {
3574
3574
  return out;
3575
3575
  }
3576
3576
  function serializePaintDocument(state, options = {}) {
3577
- const { layers, assets } = _chunkJFHBXNR2cjs.serializeLayers.call(void 0, state.layers);
3577
+ const { layers, assets } = _chunkB7V34GIHcjs.serializeLayers.call(void 0, state.layers);
3578
3578
  return { ...header(state, options), layers, assets };
3579
3579
  }
3580
3580
  async function serializePaintDocumentExternal(state, store, options = {}) {
3581
- const { layers, assets } = await _chunkJFHBXNR2cjs.serializeLayersExternal.call(void 0, state.layers, store);
3581
+ const { layers, assets } = await _chunkB7V34GIHcjs.serializeLayersExternal.call(void 0, state.layers, store);
3582
3582
  return { ...header(state, options), layers, assets };
3583
3583
  }
3584
3584
  function paintLayersOnly(layers, problems) {
@@ -3615,7 +3615,7 @@ function deserializePaintDocument(raw) {
3615
3615
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
3616
3616
  const paper = normalizePaper(_nullishCoalesce(r.paper, () => ( {})));
3617
3617
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
3618
- const layers = paintLayersOnly(_chunkJFHBXNR2cjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
3618
+ const layers = paintLayersOnly(_chunkB7V34GIHcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
3619
3619
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
3620
3620
  const activeLayerId = wanted && _chunkDPYAO5U6cjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.flattenLayers.call(void 0, layers), 'access', _125 => _125.filter, 'call', _126 => _126((l) => l.type === "pixel"), 'access', _127 => _127.pop, 'call', _128 => _128(), 'optionalAccess', _129 => _129.id]), () => ( null));
3621
3621
  const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
@@ -3631,7 +3631,7 @@ async function deserializePaintDocumentAsync(raw, store) {
3631
3631
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
3632
3632
  const r = raw;
3633
3633
  const problems = [];
3634
- const assets = await _chunkJFHBXNR2cjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
3634
+ const assets = await _chunkB7V34GIHcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
3635
3635
  const loaded = deserializePaintDocument({ ...r, assets });
3636
3636
  return { ...loaded, problems: [...problems, ...loaded.problems] };
3637
3637
  }
@@ -4461,8 +4461,8 @@ var PaintWetLayers = (_class14 = class {
4461
4461
  this.gpu = null;
4462
4462
  }
4463
4463
  }, _class14);
4464
- function wetPigmentOf(hex, body) {
4465
- const [r, g, b] = hexToRgb8(hex);
4464
+ function wetPigmentOf(hex2, body) {
4465
+ const [r, g, b] = hexToRgb8(hex2);
4466
4466
  return Array.from(_chunkKBYB7OWBcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
4467
4467
  }
4468
4468
 
@@ -4555,7 +4555,7 @@ function renderBrushThumbnail(brush, options) {
4555
4555
  const width = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.width, () => ( 160)))));
4556
4556
  const height = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.height, () => ( 48)))));
4557
4557
  const maxSize = height * 0.42;
4558
- const b = brush.tip.size > maxSize ? _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
4558
+ const b = brush.tip.size > maxSize ? _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
4559
4559
  const rgba = [...hexToRgb8(options.color), 255];
4560
4560
  let surface = _chunk474IQG74cjs.emptySurface.call(void 0, 4);
4561
4561
  if (b.engine === "eraser") {
@@ -4838,7 +4838,7 @@ var DEFAULT_SWATCHES = [
4838
4838
  // src/paint-editor/mixing-pad.ts
4839
4839
  var MIXING_PAD_WIDTH = 360;
4840
4840
  var MIXING_PAD_HEIGHT = 220;
4841
- var PAD_PAINT = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, {
4841
+ var PAD_PAINT = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, {
4842
4842
  id: "pad-paint",
4843
4843
  name: "Pad paint",
4844
4844
  category: "mixer",
@@ -4846,7 +4846,7 @@ var PAD_PAINT = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, {
4846
4846
  tip: { size: 28, hardness: 0.75, spacing: 0.1, opacity: 1, flow: 0.7, pressureSize: false, pressureOpacity: false },
4847
4847
  mixer: { wet: 0.45, load: 1, mix: 0.4, loadEachStroke: true, cleanEachStroke: true, mixing: "pigment" }
4848
4848
  });
4849
- var PAD_KNIFE = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, {
4849
+ var PAD_KNIFE = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, {
4850
4850
  id: "pad-knife",
4851
4851
  name: "Palette knife",
4852
4852
  category: "smudge",
@@ -4856,7 +4856,7 @@ var PAD_KNIFE = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, {
4856
4856
  // A knife drags streaks of paint and folds them into each other, mixing them as pigment.
4857
4857
  smudge: { strength: 0.6, length: 0.8, mixing: "pigment" }
4858
4858
  });
4859
- var PAD_BLOB = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, {
4859
+ var PAD_BLOB = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, {
4860
4860
  id: "pad-blob",
4861
4861
  name: "Pad blob",
4862
4862
  category: "custom",
@@ -4878,7 +4878,7 @@ var MixingPad = (_class16 = class {constructor() { _class16.prototype.__init106.
4878
4878
  }
4879
4879
  }
4880
4880
  let brush = options.tool === "knife" ? PAD_KNIFE : PAD_PAINT;
4881
- if (options.size !== void 0) brush = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
4881
+ if (options.size !== void 0) brush = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
4882
4882
  return this.run(brush, points, options.color);
4883
4883
  }
4884
4884
  /** Paints `points` with `brush` in `color` on the pad. */
@@ -4934,8 +4934,8 @@ var MixingPad = (_class16 = class {constructor() { _class16.prototype.__init106.
4934
4934
  A += a;
4935
4935
  }
4936
4936
  if (A === 0) return null;
4937
- const hex = (v) => Math.round(v / A).toString(16).padStart(2, "0");
4938
- return `#${hex(R)}${hex(G)}${hex(B)}`;
4937
+ const hex2 = (v) => Math.round(v / A).toString(16).padStart(2, "0");
4938
+ return `#${hex2(R)}${hex2(G)}${hex2(B)}`;
4939
4939
  }
4940
4940
  clear() {
4941
4941
  this.surface = _chunk474IQG74cjs.emptySurface.call(void 0, 4);
@@ -4977,10 +4977,10 @@ var MixingPad = (_class16 = class {constructor() { _class16.prototype.__init106.
4977
4977
  const off = used.length === 1 ? 0 : 0.45 * R;
4978
4978
  const x = Math.min(cx + R - r, Math.max(cx - R + r, cx + Math.cos(a) * off));
4979
4979
  const y = Math.min(cy + R - r, Math.max(cy - R + r, cy + Math.sin(a) * off));
4980
- const blob = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
4980
+ const blob = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
4981
4981
  this.run(blob, [{ x, y }], p.color.toLowerCase());
4982
4982
  });
4983
- const knife = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
4983
+ const knife = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
4984
4984
  for (let k = 0; k < passes; k++) {
4985
4985
  const stir = [];
4986
4986
  const turns = 1.6;
@@ -4995,9 +4995,9 @@ var MixingPad = (_class16 = class {constructor() { _class16.prototype.__init106.
4995
4995
  paints2.map((p) => hexToRgb8(p.color).map((v) => v / 255)),
4996
4996
  paints2.map((p) => p.parts)
4997
4997
  );
4998
- const core = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
4999
- const hex = "#" + mixed.map((v) => Math.round(v * 255).toString(16).padStart(2, "0")).join("");
5000
- this.run(core, [{ x: cx, y: cy }], hex);
4998
+ const core = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
4999
+ const hex2 = "#" + mixed.map((v) => Math.round(v * 255).toString(16).padStart(2, "0")).join("");
5000
+ this.run(core, [{ x: cx, y: cy }], hex2);
5001
5001
  return { color: this.pick(cx, cy, 2), bounds };
5002
5002
  }
5003
5003
  /** The pad's pixels as a PNG data URL (with alpha), for saving. */
@@ -5035,21 +5035,21 @@ var MixingPad = (_class16 = class {constructor() { _class16.prototype.__init106.
5035
5035
  var copyJSON = (v) => JSON.parse(JSON.stringify(v));
5036
5036
  var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
5037
5037
  function libraryBrush(spec, builtin, resolved) {
5038
- const brush = resolved ? _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, resolved, resolved) : _chunk34KLWUH4cjs.resolveBrush.call(void 0, spec);
5038
+ const brush = resolved ? _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, resolved, resolved) : _chunkHIMGBZAMcjs.resolveBrush.call(void 0, spec);
5039
5039
  if (builtin) brush.builtin = true;
5040
5040
  else delete brush.builtin;
5041
5041
  return { spec, brush, builtin };
5042
5042
  }
5043
5043
  var builtins = null;
5044
5044
  function builtinLibraryBrushes() {
5045
- return builtins ??= _chunk34KLWUH4cjs.BRUSH_PRESETS.map((spec) => {
5046
- const resolved = _chunkHS6QDWDFcjs.BUILTIN_BRUSHES.find((b) => b.id === spec.id);
5045
+ return builtins ??= _chunkHIMGBZAMcjs.BRUSH_PRESETS.map((spec) => {
5046
+ const resolved = _chunkHIMGBZAMcjs.BUILTIN_BRUSHES.find((b) => b.id === spec.id);
5047
5047
  return libraryBrush(spec, true, resolved);
5048
5048
  });
5049
5049
  }
5050
5050
  function seededStorage(brushes) {
5051
5051
  if (!brushes.length) return void 0;
5052
- let stored = JSON.stringify({ format: "pixerate-brushes", version: 1, brushes: brushes.map(_chunkHS6QDWDFcjs.brushToJSON) });
5052
+ let stored = JSON.stringify({ format: "pixerate-brushes", version: 1, brushes: brushes.map(_chunkHIMGBZAMcjs.brushToJSON) });
5053
5053
  return {
5054
5054
  get: async () => stored,
5055
5055
  set: async (_key, value) => {
@@ -5062,7 +5062,7 @@ var paints = (b) => {
5062
5062
  return JSON.stringify(rest);
5063
5063
  };
5064
5064
  function brushSpecOf(next, from) {
5065
- const plain = _chunk34KLWUH4cjs.migrateBrushV1.call(void 0, next);
5065
+ const plain = _chunkHIMGBZAMcjs.migrateBrushV1.call(void 0, next);
5066
5066
  const out = copyJSON(plain);
5067
5067
  if (from.description) out.description = from.description;
5068
5068
  if (_optionalChain([from, 'access', _209 => _209.tags, 'optionalAccess', _210 => _210.length])) out.tags = [...from.tags];
@@ -5082,8 +5082,8 @@ function brushSpecOf(next, from) {
5082
5082
  out.motion = { ..._nullishCoalesce(out.motion, () => ( {})), ...from.motion.live !== void 0 ? { live: from.motion.live } : {}, ...from.motion.fps !== void 0 ? { fps: from.motion.fps } : {} };
5083
5083
  }
5084
5084
  try {
5085
- const hinted = _chunk34KLWUH4cjs.normalizeBrushSpec.call(void 0, out, []);
5086
- if (paints(_chunk34KLWUH4cjs.resolveBrush.call(void 0, hinted)) === paints(_chunk34KLWUH4cjs.resolveBrush.call(void 0, plain))) return hinted;
5085
+ const hinted = _chunkHIMGBZAMcjs.normalizeBrushSpec.call(void 0, out, []);
5086
+ if (paints(_chunkHIMGBZAMcjs.resolveBrush.call(void 0, hinted)) === paints(_chunkHIMGBZAMcjs.resolveBrush.call(void 0, plain))) return hinted;
5087
5087
  } catch (e6) {
5088
5088
  }
5089
5089
  return plain;
@@ -5690,7 +5690,7 @@ async function libraryCall(call) {
5690
5690
  try {
5691
5691
  return await call();
5692
5692
  } catch (e) {
5693
- throw e instanceof _chunk34KLWUH4cjs.BrushLibraryError ? new PaintEditorError(e.message) : e;
5693
+ throw e instanceof _chunkHIMGBZAMcjs.BrushLibraryError ? new PaintEditorError(e.message) : e;
5694
5694
  }
5695
5695
  }
5696
5696
  var HEX3 = /^#[0-9a-f]{6}$/i;
@@ -5699,8 +5699,8 @@ function parseColor(value, what = "color") {
5699
5699
  if (typeof value !== "string" || !HEX3.test(value.trim())) throw new PaintEditorError(`${what} is ${JSON.stringify(value)}; use #rrggbb, e.g. "#2a4b8d".`);
5700
5700
  return value.trim().toLowerCase();
5701
5701
  }
5702
- function rgbaOf(hex) {
5703
- const [r, g, b] = hexToRgb8(hex);
5702
+ function rgbaOf(hex2) {
5703
+ const [r, g, b] = hexToRgb8(hex2);
5704
5704
  return [r, g, b, 255];
5705
5705
  }
5706
5706
  function rgbToHex(r, g, b) {
@@ -5753,74 +5753,81 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5753
5753
  __init133() {this.stickerPreview = null}
5754
5754
 
5755
5755
  __init134() {this.listeners = /* @__PURE__ */ new Set()}
5756
- __init135() {this.version = 0}
5757
- __init136() {this.cached = null}
5758
- __init137() {this.session = null}
5759
- __init138() {this.live = null}
5760
- __init139() {this.liveLayers = null}
5761
- __init140() {this.dirty = "all"}
5762
- __init141() {this.seedCounter = 1}
5763
- __init142() {this.strokeCounter = 1}
5756
+ __init135() {this.commitListeners = /* @__PURE__ */ new Set()}
5757
+ /** Origins set by `withOrigin`, innermost last. */
5758
+ __init136() {this.origins = []}
5759
+ /** `group` in progress: commits fold into one step, recorded when it ends. */
5760
+ __init137() {this.grouping = null}
5761
+ /** `previewPaint` in progress: nothing is emitted or recorded. */
5762
+ __init138() {this.previewing = false}
5763
+ __init139() {this.version = 0}
5764
+ __init140() {this.cached = null}
5765
+ __init141() {this.session = null}
5766
+ __init142() {this.live = null}
5767
+ __init143() {this.liveLayers = null}
5768
+ __init144() {this.dirty = "all"}
5769
+ __init145() {this.seedCounter = 1}
5770
+ __init146() {this.strokeCounter = 1}
5764
5771
  /** Light paint: each layer's spill settings (saved with the document, not undo steps; missing = the defaults). */
5765
- __init143() {this.lightSpills = {}}
5766
- __init144() {this.lightCaches = /* @__PURE__ */ new Map()}
5772
+ __init147() {this.lightSpills = {}}
5773
+ __init148() {this.lightCaches = /* @__PURE__ */ new Map()}
5767
5774
  /** Backlit paper: the light through the paint as drawn (live strokes too), and as committed (its spill). */
5768
- __init145() {this.backlightView = new BacklightCache()}
5769
- __init146() {this.backlightCommitted = new BacklightCache()}
5775
+ __init149() {this.backlightView = new BacklightCache()}
5776
+ __init150() {this.backlightCommitted = new BacklightCache()}
5770
5777
  /** Live effect paint: playing and the frame rate cap (editor state), and the time the view shows. */
5771
- __init147() {this.effectPlaybackState = { playing: true, fps: 30 }}
5772
- __init148() {this.effectTime = 0}
5778
+ __init151() {this.effectPlaybackState = { playing: true, fps: 30 }}
5779
+ __init152() {this.effectTime = 0}
5773
5780
  /** While a frame is drawn: the time live effect strokes are drawn at (else their own time). */
5774
- __init149() {this.liveEffectAt = null}
5781
+ __init153() {this.liveEffectAt = null}
5775
5782
  /** The view's stroke layers at `effectTime`, each with the document surface it was drawn from (stale once that changes). */
5776
- __init150() {this.animatedLayers = /* @__PURE__ */ new Map()}
5783
+ __init154() {this.animatedLayers = /* @__PURE__ */ new Map()}
5777
5784
  /** `renderAnimationFrame` / `withEffectTime`: layer surfaces at another time, for one render. */
5778
- __init151() {this.frameOverride = null}
5785
+ __init155() {this.frameOverride = null}
5779
5786
  /** The area each stroke painted (document pixels; `null`: nothing), learnt as it is painted or drawn, so a stroke layer edit redraws only where it changes (see `drawLiveStrokes`). */
5780
- __init152() {this.paintedBounds = /* @__PURE__ */ new WeakMap()}
5787
+ __init156() {this.paintedBounds = /* @__PURE__ */ new WeakMap()}
5781
5788
 
5782
- __init153() {this.swatches = DEFAULT_SWATCHES.map((s) => ({ ...s }))}
5783
- __init154() {this.pad = new MixingPad()}
5784
- __init155() {this.savedPads = []}
5785
- __init156() {this.nextPadId = 1}
5786
- __init157() {this.tracingVersion = 1}
5787
- __init158() {this.tracingCache = null}
5788
- __init159() {this.imagePixels = /* @__PURE__ */ new Map()}
5789
- __init160() {this.nextReferenceId = 1}
5790
- __init161() {this.viewCompositor = createPaintCompositor()}
5791
- __init162() {this.exportCompositor = createPaintCompositor()}
5789
+ __init157() {this.swatches = DEFAULT_SWATCHES.map((s) => ({ ...s }))}
5790
+ __init158() {this.pad = new MixingPad()}
5791
+ __init159() {this.savedPads = []}
5792
+ __init160() {this.nextPadId = 1}
5793
+ __init161() {this.tracingVersion = 1}
5794
+ __init162() {this.tracingCache = null}
5795
+ __init163() {this.imagePixels = /* @__PURE__ */ new Map()}
5796
+ __init164() {this.nextReferenceId = 1}
5797
+ __init165() {this.viewCompositor = createPaintCompositor()}
5798
+ __init166() {this.exportCompositor = createPaintCompositor()}
5792
5799
  /** Wet media: the simulation, its settings and time. */
5793
5800
 
5794
5801
 
5795
5802
  /** Where the light comes from for thick paint (saved with the document, not undo steps). */
5796
- __init163() {this.lighting = { ...DEFAULT_LIGHTING }}
5797
- __init164() {this.litCaches = /* @__PURE__ */ new Map()}
5803
+ __init167() {this.lighting = { ...DEFAULT_LIGHTING }}
5804
+ __init168() {this.litCaches = /* @__PURE__ */ new Map()}
5798
5805
  /** The live impasto stroke's channels. */
5799
- __init165() {this.liveThick = null}
5806
+ __init169() {this.liveThick = null}
5800
5807
  /** Set while an operation that changes wet paint runs: the simulation before it (for undo). */
5801
- __init166() {this.wetOp = null}
5808
+ __init170() {this.wetOp = null}
5802
5809
  /** The effects provider slot (see `setEffectsProvider`). */
5803
- __init167() {this.effects = new (0, _chunkL2JTLW6Bcjs.EffectsSlot)()}
5810
+ __init171() {this.effects = new (0, _chunkL2JTLW6Bcjs.EffectsSlot)()}
5804
5811
  /** The sticker library slot (see `setStickersProvider`). */
5805
- __init168() {this.stickers = new (0, _chunkJSDND7DFcjs.StickersSlot)(_chunkSABJMH6Mcjs.editorStickers.call(void 0, ))}
5806
- __init169() {this.stickerArt = new StickerArtCache()}
5812
+ __init172() {this.stickers = new (0, _chunkJSDND7DFcjs.StickersSlot)(_chunkSABJMH6Mcjs.editorStickers.call(void 0, ))}
5813
+ __init173() {this.stickerArt = new StickerArtCache()}
5807
5814
 
5808
- __init170() {this.effectsRenderer = new PaintEffectsRenderer()}
5809
- __init171() {this.paperEffectNodeCache = null}
5810
- constructor(options = {}) {;_class19.prototype.__init117.call(this);_class19.prototype.__init118.call(this);_class19.prototype.__init119.call(this);_class19.prototype.__init120.call(this);_class19.prototype.__init121.call(this);_class19.prototype.__init122.call(this);_class19.prototype.__init123.call(this);_class19.prototype.__init124.call(this);_class19.prototype.__init125.call(this);_class19.prototype.__init126.call(this);_class19.prototype.__init127.call(this);_class19.prototype.__init128.call(this);_class19.prototype.__init129.call(this);_class19.prototype.__init130.call(this);_class19.prototype.__init131.call(this);_class19.prototype.__init132.call(this);_class19.prototype.__init133.call(this);_class19.prototype.__init134.call(this);_class19.prototype.__init135.call(this);_class19.prototype.__init136.call(this);_class19.prototype.__init137.call(this);_class19.prototype.__init138.call(this);_class19.prototype.__init139.call(this);_class19.prototype.__init140.call(this);_class19.prototype.__init141.call(this);_class19.prototype.__init142.call(this);_class19.prototype.__init143.call(this);_class19.prototype.__init144.call(this);_class19.prototype.__init145.call(this);_class19.prototype.__init146.call(this);_class19.prototype.__init147.call(this);_class19.prototype.__init148.call(this);_class19.prototype.__init149.call(this);_class19.prototype.__init150.call(this);_class19.prototype.__init151.call(this);_class19.prototype.__init152.call(this);_class19.prototype.__init153.call(this);_class19.prototype.__init154.call(this);_class19.prototype.__init155.call(this);_class19.prototype.__init156.call(this);_class19.prototype.__init157.call(this);_class19.prototype.__init158.call(this);_class19.prototype.__init159.call(this);_class19.prototype.__init160.call(this);_class19.prototype.__init161.call(this);_class19.prototype.__init162.call(this);_class19.prototype.__init163.call(this);_class19.prototype.__init164.call(this);_class19.prototype.__init165.call(this);_class19.prototype.__init166.call(this);_class19.prototype.__init167.call(this);_class19.prototype.__init168.call(this);_class19.prototype.__init169.call(this);_class19.prototype.__init170.call(this);_class19.prototype.__init171.call(this);_class19.prototype.__init172.call(this);_class19.prototype.__init173.call(this);_class19.prototype.__init174.call(this);_class19.prototype.__init175.call(this);
5815
+ __init174() {this.effectsRenderer = new PaintEffectsRenderer()}
5816
+ __init175() {this.paperEffectNodeCache = null}
5817
+ constructor(options = {}) {;_class19.prototype.__init117.call(this);_class19.prototype.__init118.call(this);_class19.prototype.__init119.call(this);_class19.prototype.__init120.call(this);_class19.prototype.__init121.call(this);_class19.prototype.__init122.call(this);_class19.prototype.__init123.call(this);_class19.prototype.__init124.call(this);_class19.prototype.__init125.call(this);_class19.prototype.__init126.call(this);_class19.prototype.__init127.call(this);_class19.prototype.__init128.call(this);_class19.prototype.__init129.call(this);_class19.prototype.__init130.call(this);_class19.prototype.__init131.call(this);_class19.prototype.__init132.call(this);_class19.prototype.__init133.call(this);_class19.prototype.__init134.call(this);_class19.prototype.__init135.call(this);_class19.prototype.__init136.call(this);_class19.prototype.__init137.call(this);_class19.prototype.__init138.call(this);_class19.prototype.__init139.call(this);_class19.prototype.__init140.call(this);_class19.prototype.__init141.call(this);_class19.prototype.__init142.call(this);_class19.prototype.__init143.call(this);_class19.prototype.__init144.call(this);_class19.prototype.__init145.call(this);_class19.prototype.__init146.call(this);_class19.prototype.__init147.call(this);_class19.prototype.__init148.call(this);_class19.prototype.__init149.call(this);_class19.prototype.__init150.call(this);_class19.prototype.__init151.call(this);_class19.prototype.__init152.call(this);_class19.prototype.__init153.call(this);_class19.prototype.__init154.call(this);_class19.prototype.__init155.call(this);_class19.prototype.__init156.call(this);_class19.prototype.__init157.call(this);_class19.prototype.__init158.call(this);_class19.prototype.__init159.call(this);_class19.prototype.__init160.call(this);_class19.prototype.__init161.call(this);_class19.prototype.__init162.call(this);_class19.prototype.__init163.call(this);_class19.prototype.__init164.call(this);_class19.prototype.__init165.call(this);_class19.prototype.__init166.call(this);_class19.prototype.__init167.call(this);_class19.prototype.__init168.call(this);_class19.prototype.__init169.call(this);_class19.prototype.__init170.call(this);_class19.prototype.__init171.call(this);_class19.prototype.__init172.call(this);_class19.prototype.__init173.call(this);_class19.prototype.__init174.call(this);_class19.prototype.__init175.call(this);_class19.prototype.__init176.call(this);_class19.prototype.__init177.call(this);_class19.prototype.__init178.call(this);_class19.prototype.__init179.call(this);
5811
5818
  this.historyLimit = Math.max(1, _nullishCoalesce(options.historyLimit, () => ( 200)));
5812
5819
  this.rasterizeSticker = _nullishCoalesce(options.rasterizeSticker, () => ( defaultStickerRasterizer));
5813
5820
  if (options.stickers) this.stickers.set(options.stickers);
5814
5821
  this.doc = createPaintDocument({ width: options.width, height: options.height, dpi: options.dpi, paper: this.resolvePaper(options.paper) });
5815
- const seed = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
5816
- this.brushLibrary = _nullishCoalesce(options.brushLibrary, () => ( _chunk34KLWUH4cjs.createBrushLibrary.call(void 0, { storage: seededStorage(seed) })));
5817
- this.brushEntries = [...builtinLibraryBrushes(), ...seed.map((b) => libraryBrush(_chunk34KLWUH4cjs.migrateBrushV1.call(void 0, b), false, b))];
5818
- const wanted = _nullishCoalesce(options.brushId, () => ( _chunkHS6QDWDFcjs.DEFAULT_BRUSH_ID));
5819
- const start = _nullishCoalesce(this.findEntry(wanted), () => ( this.findEntry(_chunkHS6QDWDFcjs.DEFAULT_BRUSH_ID)));
5820
- this.brush = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, start.brush);
5822
+ const seed = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
5823
+ this.brushLibrary = _nullishCoalesce(options.brushLibrary, () => ( _chunkHIMGBZAMcjs.createBrushLibrary.call(void 0, { storage: seededStorage(seed) })));
5824
+ this.brushEntries = [...builtinLibraryBrushes(), ...seed.map((b) => libraryBrush(_chunkHIMGBZAMcjs.migrateBrushV1.call(void 0, b), false, b))];
5825
+ const wanted = _nullishCoalesce(options.brushId, () => ( _chunkHIMGBZAMcjs.DEFAULT_BRUSH_ID));
5826
+ const start = _nullishCoalesce(this.findEntry(wanted), () => ( this.findEntry(_chunkHIMGBZAMcjs.DEFAULT_BRUSH_ID)));
5827
+ this.brush = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, start.brush);
5821
5828
  this.brushSpec = copyJSON(start.spec);
5822
5829
  this.unsubscribeLibrary = this.brushLibrary.subscribe(() => void this.refreshBrushes().catch(() => void 0));
5823
- if (options.brushLibrary && seed.length) void this.brushLibrary.importFile(seed.map(_chunkHS6QDWDFcjs.brushToJSON)).catch(() => void 0);
5830
+ if (options.brushLibrary && seed.length) void this.brushLibrary.importFile(seed.map(_chunkHIMGBZAMcjs.brushToJSON)).catch(() => void 0);
5824
5831
  void this.refreshBrushes().catch(() => void 0);
5825
5832
  this.pendingBrushId = start.brush.id === wanted ? null : wanted;
5826
5833
  this.color = options.color ? parseColor(options.color) : "#1f2937";
@@ -5860,7 +5867,125 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5860
5867
  this.listeners.add(listener);
5861
5868
  return () => this.listeners.delete(listener);
5862
5869
  }
5870
+ /** Hears each undo step recorded, merged, undone or redone, with who made it. Returns an unsubscribe function. */
5871
+ onCommit(listener) {
5872
+ this.commitListeners.add(listener);
5873
+ return () => {
5874
+ this.commitListeners.delete(listener);
5875
+ };
5876
+ }
5877
+ notifyCommit(event) {
5878
+ if (this.previewing) return;
5879
+ for (const l of [...this.commitListeners]) l(event);
5880
+ }
5881
+ /** The origin steps are recorded with now: the innermost `withOrigin`, else `user`. */
5882
+ getOrigin() {
5883
+ return _nullishCoalesce(this.origins[this.origins.length - 1], () => ( "user"));
5884
+ }
5885
+ /**
5886
+ * Records the steps `fn` makes as made by `origin` (`agent:<id>` for an agent). When `fn` returns
5887
+ * a promise, the origin holds until it settles. Satisfies `createOriginMiddleware`'s history target,
5888
+ * so agent tool calls are recorded as the calling agent's.
5889
+ */
5890
+ withOrigin(origin, fn) {
5891
+ this.origins.push(origin);
5892
+ let pending = false;
5893
+ const pop = () => {
5894
+ const i = this.origins.lastIndexOf(origin);
5895
+ if (i >= 0) this.origins.splice(i, 1);
5896
+ };
5897
+ try {
5898
+ const result = fn();
5899
+ if (result && typeof result.then === "function") {
5900
+ pending = true;
5901
+ return Promise.resolve(result).finally(pop);
5902
+ }
5903
+ return result;
5904
+ } finally {
5905
+ if (!pending) pop();
5906
+ }
5907
+ }
5908
+ /**
5909
+ * Runs `fn` as one undo step named `label`: every change it makes (strokes, fills, new layers) is
5910
+ * undone together. Wet paint can't be grouped. Nested groups join the outer one. If `fn` throws,
5911
+ * its changes are put back and nothing is recorded.
5912
+ */
5913
+ group(label, fn) {
5914
+ if (this.grouping) return fn();
5915
+ this.requireIdle("grouping changes");
5916
+ const before = this.doc;
5917
+ const revision = this.docRevision;
5918
+ this.grouping = { label, before, changed: false };
5919
+ let result;
5920
+ try {
5921
+ result = fn();
5922
+ } catch (e) {
5923
+ this.grouping = null;
5924
+ if (this.doc !== before) {
5925
+ this.doc = before;
5926
+ this.docRevision = revision + 1;
5927
+ this.emit();
5928
+ }
5929
+ throw e;
5930
+ }
5931
+ const g = this.grouping;
5932
+ this.grouping = null;
5933
+ if (g.changed && this.doc !== before) {
5934
+ this.undoStack.push({ label, origin: this.getOrigin(), before, after: this.doc });
5935
+ if (this.undoStack.length > this.historyLimit) this.undoStack.shift();
5936
+ this.redoStack = [];
5937
+ this.notifyCommit({ kind: "execute", label, origin: this.getOrigin() });
5938
+ this.emit();
5939
+ }
5940
+ return result;
5941
+ }
5942
+ /**
5943
+ * What `fn` would paint, without changing anything: it runs on a new empty layer (above the
5944
+ * active layer, another one, or at the bottom), and the layer's pixels and the picture with them
5945
+ * come back while the document, history and listeners stay as they were. `fn` gets that layer's id and must paint on it with dry brushes (strokes, replays and
5946
+ * fills); wet paint can't be previewed. For ghost paint an agent suggests (`createPaintProposals`).
5947
+ */
5948
+ previewPaint(fn, placement = {}) {
5949
+ this.requireIdle("previewing");
5950
+ if (this.previewing) throw new PaintEditorError("A preview is already running.");
5951
+ const saved = {
5952
+ doc: this.doc,
5953
+ undo: [...this.undoStack],
5954
+ redo: this.redoStack,
5955
+ revision: this.docRevision,
5956
+ strokeCounter: this.strokeCounter,
5957
+ seedCounter: this.seedCounter,
5958
+ mixerLoad: this.mixerLoad
5959
+ };
5960
+ this.previewing = true;
5961
+ try {
5962
+ const layer = this.addLayer({ name: "Preview", ...placement.aboveId ? { aboveId: placement.aboveId } : {} });
5963
+ if (placement.bottom) this.moveLayer(layer.id, 0, null);
5964
+ fn(layer.id);
5965
+ if (this.wetOp || this.pendingWetEvents.length) throw new PaintEditorError("Wet paint can't be previewed; suggest it with a dry brush.");
5966
+ const found = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layer.id), 'optionalAccess', _265 => _265.layer]);
5967
+ const surface = found && isPixelLayer(found) ? found.surface : null;
5968
+ const bounds = surface ? _chunk474IQG74cjs.contentBounds.call(void 0, surface) : null;
5969
+ const box = bounds ? clipToCanvas(bounds, this.doc.canvas) : null;
5970
+ if (!surface || !box) return { bounds: null, pixels: new Uint8ClampedArray(0), composite: new Uint8ClampedArray(0) };
5971
+ const composite = this.exportCompositor.composite(this.renderLayers({ wet: "display" }), box, this.sources());
5972
+ return { bounds: box, pixels: _chunk474IQG74cjs.readRegion.call(void 0, surface, box), composite };
5973
+ } finally {
5974
+ this.wetOp = null;
5975
+ this.pendingWetEvents = [];
5976
+ this.doc = saved.doc;
5977
+ this.undoStack = saved.undo;
5978
+ this.redoStack = saved.redo;
5979
+ this.docRevision = saved.revision;
5980
+ this.strokeCounter = saved.strokeCounter;
5981
+ this.seedCounter = saved.seedCounter;
5982
+ this.mixerLoad = saved.mixerLoad;
5983
+ this.cached = null;
5984
+ this.previewing = false;
5985
+ }
5986
+ }
5863
5987
  emit(dirty = "all") {
5988
+ if (this.previewing) return;
5864
5989
  if (dirty === "all" || this.dirty === "all") this.dirty = "all";
5865
5990
  else this.dirty.push(...dirty);
5866
5991
  this.version++;
@@ -5889,8 +6014,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5889
6014
  selectedSticker: this.selectedSticker,
5890
6015
  canUndo: this.undoStack.length > 0 && !this.session,
5891
6016
  canRedo: this.redoStack.length > 0 && !this.session,
5892
- undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _265 => _265.label]), () => ( null)),
5893
- redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _266 => _266.label]), () => ( null)),
6017
+ undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _266 => _266.label]), () => ( null)),
6018
+ redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _267 => _267.label]), () => ( null)),
5894
6019
  guides: this.guides,
5895
6020
  swatches: this.swatches,
5896
6021
  mixingPadVersion: this.pad.version,
@@ -5903,10 +6028,10 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5903
6028
  overlay: this.wet.overlay,
5904
6029
  instantDry: this.wet.instantDry,
5905
6030
  speed: this.wet.speed,
5906
- clock: _nullishCoalesce(_optionalChain([this, 'access', _267 => _267.wet, 'access', _268 => _268.world, 'optionalAccess', _269 => _269.clock]), () => ( 0)),
6031
+ clock: _nullishCoalesce(_optionalChain([this, 'access', _268 => _268.wet, 'access', _269 => _269.world, 'optionalAccess', _270 => _270.clock]), () => ( 0)),
5907
6032
  tilt: { ...this.wet.tilt },
5908
6033
  gpu: this.wet.gpuMode,
5909
- gpuActive: Boolean(_optionalChain([this, 'access', _270 => _270.wet, 'access', _271 => _271.world, 'optionalAccess', _272 => _272.gpuActive]))
6034
+ gpuActive: Boolean(_optionalChain([this, 'access', _271 => _271.wet, 'access', _272 => _272.world, 'optionalAccess', _273 => _273.gpuActive]))
5910
6035
  },
5911
6036
  version: this.version
5912
6037
  };
@@ -5925,7 +6050,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5925
6050
  return d;
5926
6051
  }
5927
6052
  // --- History -------------------------------------------------------------------
5928
- __init172() {this.docRevision = 0}
6053
+ __init176() {this.docRevision = 0}
5929
6054
  /**
5930
6055
  * Bumped on every change to the painting (a committed or amended step, undo, redo, opening a
5931
6056
  * document), not on wet-paint frames or view changes. `createPaintEditorDocument` uses it.
@@ -5943,7 +6068,13 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5943
6068
  if (this.session) throw new PaintEditorError(`A stroke is in progress; end or cancel it before ${what}.`);
5944
6069
  }
5945
6070
  commit(label, next, before = this.doc) {
5946
- const entry = { label, before, after: next };
6071
+ if (this.grouping) {
6072
+ this.grouping.changed = true;
6073
+ this.doc = next;
6074
+ this.docRevision++;
6075
+ return;
6076
+ }
6077
+ const entry = { label, origin: this.getOrigin(), before, after: next };
5947
6078
  if (this.wetOp) {
5948
6079
  entry.wet = { before: this.wetOp.before, after: this.wet.snapshot(), lost: false };
5949
6080
  this.wetOp = null;
@@ -5954,6 +6085,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5954
6085
  this.doc = next;
5955
6086
  this.docRevision++;
5956
6087
  this.trimWetHistory();
6088
+ this.notifyCommit({ kind: "execute", label, origin: entry.origin });
5957
6089
  this.emit();
5958
6090
  }
5959
6091
  /**
@@ -5962,7 +6094,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5962
6094
  */
5963
6095
  commitOrAmend(label, next, commitToHistory) {
5964
6096
  const last = this.undoStack[this.undoStack.length - 1];
5965
- if (commitToHistory || !last || last.label !== label || last.wet || this.wetOp) {
6097
+ if (commitToHistory || !last || last.label !== label || last.wet || this.wetOp || this.grouping) {
5966
6098
  this.commit(label, next);
5967
6099
  return;
5968
6100
  }
@@ -5970,6 +6102,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
5970
6102
  this.redoStack = [];
5971
6103
  this.doc = next;
5972
6104
  this.docRevision++;
6105
+ this.notifyCommit({ kind: "merge", label, origin: last.origin });
5973
6106
  this.emit();
5974
6107
  }
5975
6108
  /** Keeps the wet snapshots in history within the wet undo memory, dropping the oldest. */
@@ -6008,9 +6141,9 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6008
6141
  return wetIds;
6009
6142
  }
6010
6143
  /** Records a wet event (for replays) in the document being built. */
6011
- __init173() {this.pendingWetEvents = []}
6144
+ __init177() {this.pendingWetEvents = []}
6012
6145
  logWet(e) {
6013
- this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _273 => _273.wet, 'access', _274 => _274.world, 'optionalAccess', _275 => _275.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
6146
+ this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _274 => _274.wet, 'access', _275 => _275.world, 'optionalAccess', _276 => _276.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
6014
6147
  }
6015
6148
  /** The document with a paint event appended (for replays). */
6016
6149
  withPaintEvent(doc, e) {
@@ -6039,6 +6172,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6039
6172
  this.wet.restore(e.wet.lost ? null : e.wet.before);
6040
6173
  if (paper !== this.doc.paper) this.wet.paperChanged();
6041
6174
  }
6175
+ this.notifyCommit({ kind: "undo", label: e.label, origin: this.getOrigin() });
6042
6176
  this.emit();
6043
6177
  return e.label;
6044
6178
  }
@@ -6057,6 +6191,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6057
6191
  this.wet.restore(e.wet.lost ? null : e.wet.after);
6058
6192
  if (paper !== this.doc.paper) this.wet.paperChanged();
6059
6193
  }
6194
+ this.notifyCommit({ kind: "redo", label: e.label, origin: this.getOrigin() });
6060
6195
  this.emit();
6061
6196
  return e.label;
6062
6197
  }
@@ -6154,7 +6289,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6154
6289
  }
6155
6290
  let next = { ...shiftDocument(this.withWetEvents(this.doc), left, top), canvas: { ...was, width, height } };
6156
6291
  for (const id of keptWet) {
6157
- const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, next.layers, id), 'optionalAccess', _276 => _276.layer]);
6292
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, next.layers, id), 'optionalAccess', _277 => _277.layer]);
6158
6293
  if (isPixelLayer(l)) next = { ...next, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, next.layers, id, () => ({ ...l, surface: _chunk474IQG74cjs.translateSurface.call(void 0, l.surface, l.offset.x, l.offset.y), offset: { x: 0, y: 0 } })) };
6159
6294
  }
6160
6295
  if (this.wet.world) {
@@ -6198,7 +6333,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6198
6333
  }
6199
6334
  // --- Layers --------------------------------------------------------------------
6200
6335
  getLayer(id) {
6201
- return _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _277 => _277.layer]);
6336
+ return _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _278 => _278.layer]);
6202
6337
  }
6203
6338
  /** The active pixel layer (or `undefined`). */
6204
6339
  getActiveLayer() {
@@ -6217,7 +6352,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6217
6352
  walk(this.doc.layers, null, 0);
6218
6353
  return out;
6219
6354
  }
6220
- describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _278 => _278.parent, 'optionalAccess', _279 => _279.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _280 => _280.path, 'access', _281 => _281.length]), () => ( 0))) {
6355
+ describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _279 => _279.parent, 'optionalAccess', _280 => _280.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _281 => _281.path, 'access', _282 => _282.length]), () => ( 0))) {
6221
6356
  let bounds = null;
6222
6357
  if (l.type === "pixel") {
6223
6358
  const b = _chunk474IQG74cjs.contentBounds.call(void 0, l.surface);
@@ -6234,8 +6369,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6234
6369
  locks: { ..._nullishCoalesce(l.locks, () => ( {})) },
6235
6370
  active: l.id === this.doc.activeLayerId,
6236
6371
  bounds,
6237
- ..._optionalChain([this, 'access', _282 => _282.doc, 'access', _283 => _283.liveStrokes, 'optionalAccess', _284 => _284[l.id]]) ? { liveStrokes: this.doc.liveStrokes[l.id].length } : {},
6238
- ..._optionalChain([l, 'access', _285 => _285.effects, 'optionalAccess', _286 => _286.items, 'access', _287 => _287.length]) ? { effects: l.effects.items.length } : {},
6372
+ ..._optionalChain([this, 'access', _283 => _283.doc, 'access', _284 => _284.liveStrokes, 'optionalAccess', _285 => _285[l.id]]) ? { liveStrokes: this.doc.liveStrokes[l.id].length } : {},
6373
+ ..._optionalChain([l, 'access', _286 => _286.effects, 'optionalAccess', _287 => _287.items, 'access', _288 => _288.length]) ? { effects: l.effects.items.length } : {},
6239
6374
  parentId,
6240
6375
  depth
6241
6376
  };
@@ -6267,7 +6402,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6267
6402
  this.requireIdle("adding a layer");
6268
6403
  const count = _chunkDPYAO5U6cjs.flattenLayers.call(void 0, this.doc.layers).length;
6269
6404
  const type = _nullishCoalesce(options.type, () => ( "pixel"));
6270
- const name = _optionalChain([options, 'access', _288 => _288.name, 'optionalAccess', _289 => _289.trim, 'call', _290 => _290()]) || (type === "group" ? `Group ${count + 1}` : type === "strokes" ? `Strokes ${count + 1}` : `Layer ${count + 1}`);
6405
+ const name = _optionalChain([options, 'access', _289 => _289.name, 'optionalAccess', _290 => _290.trim, 'call', _291 => _291()]) || (type === "group" ? `Group ${count + 1}` : type === "strokes" ? `Strokes ${count + 1}` : `Layer ${count + 1}`);
6271
6406
  const layer = type === "group" ? { type: "group", id: newPaintLayerId(), name, visible: true, opacity: 1, blend: "pass-through", children: [] } : createPaintLayer(name);
6272
6407
  let parentId = null;
6273
6408
  let index;
@@ -6279,7 +6414,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6279
6414
  } else if (above) {
6280
6415
  const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, above);
6281
6416
  if (!loc) throw new PaintEditorError(`Unknown layer "${above}". Call list_layers for the ids.`);
6282
- parentId = _nullishCoalesce(_optionalChain([loc, 'access', _291 => _291.parent, 'optionalAccess', _292 => _292.id]), () => ( null));
6417
+ parentId = _nullishCoalesce(_optionalChain([loc, 'access', _292 => _292.parent, 'optionalAccess', _293 => _293.id]), () => ( null));
6283
6418
  index = loc.index + 1;
6284
6419
  }
6285
6420
  const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, layer, parentId, index);
@@ -6385,7 +6520,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6385
6520
  }
6386
6521
  requireEffect(id, effectId) {
6387
6522
  const l = this.requireLayer(id);
6388
- const items = _nullishCoalesce(_optionalChain([l, 'access', _293 => _293.effects, 'optionalAccess', _294 => _294.items]), () => ( []));
6523
+ const items = _nullishCoalesce(_optionalChain([l, 'access', _294 => _294.effects, 'optionalAccess', _295 => _295.items]), () => ( []));
6389
6524
  const i = items.findIndex((e) => e.id === effectId);
6390
6525
  if (i === -1) throw new PaintEditorError(`Layer "${l.name}" has no effect "${effectId}". Effects: ${items.map((e) => `${e.id} (${e.kind})`).join(", ") || "none"}; call list_layer_effects.`);
6391
6526
  return i;
@@ -6408,7 +6543,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6408
6543
  }
6409
6544
  const layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
6410
6545
  let active = this.doc.activeLayerId;
6411
- if (active && !_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.flattenLayers.call(void 0, layers), 'access', _295 => _295.filter, 'call', _296 => _296((x) => x.type === "pixel"), 'access', _297 => _297.pop, 'call', _298 => _298(), 'optionalAccess', _299 => _299.id]), () => ( null));
6546
+ if (active && !_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.flattenLayers.call(void 0, layers), 'access', _296 => _296.filter, 'call', _297 => _297((x) => x.type === "pixel"), 'access', _298 => _298.pop, 'call', _299 => _299(), 'optionalAccess', _300 => _300.id]), () => ( null));
6412
6547
  this.commit("Remove layer", { ...this.doc, layers, activeLayerId: active, ...this.thickWithout(_chunkDPYAO5U6cjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.stickersWithout(_chunkDPYAO5U6cjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.liveStrokesWithout(_chunkDPYAO5U6cjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.lightWithout(_chunkDPYAO5U6cjs.flattenLayers.call(void 0, [l]).map((x) => x.id)) });
6413
6548
  return { removed: id, activeLayerId: active };
6414
6549
  }
@@ -6434,7 +6569,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6434
6569
  return l.type === "group" ? { ...l, id: id2, children: l.children.map(copy) } : { ...l, id: id2 };
6435
6570
  };
6436
6571
  const dup = { ...copy(loc.layer), name: `${loc.layer.name} copy` };
6437
- const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _300 => _300.parent, 'optionalAccess', _301 => _301.id]), () => ( null)), loc.index + 1);
6572
+ const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _301 => _301.parent, 'optionalAccess', _302 => _302.id]), () => ( null)), loc.index + 1);
6438
6573
  this.commit("Duplicate layer", this.withWetEvents({ ...this.doc, layers, activeLayerId: dup.id, ...this.doc.thick ? { thick } : {}, ...this.doc.stickers ? { stickers } : {}, ...this.doc.liveStrokes ? { liveStrokes } : {}, ...this.doc.light ? { light } : {} }));
6439
6574
  return this.describeLayer(dup);
6440
6575
  }
@@ -6443,7 +6578,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6443
6578
  this.requireIdle("moving a layer");
6444
6579
  const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id);
6445
6580
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
6446
- const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _302 => _302.parent, 'optionalAccess', _303 => _303.id]), () => ( null)) : parentId;
6581
+ const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _303 => _303.parent, 'optionalAccess', _304 => _304.id]), () => ( null)) : parentId;
6447
6582
  if (target) {
6448
6583
  const g = this.requireLayer(target);
6449
6584
  if (g.type !== "group") throw new PaintEditorError(`Layer "${g.name}" is not a group; pass a group id as parentId.`);
@@ -6462,7 +6597,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6462
6597
  const pre = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id);
6463
6598
  if (pre) {
6464
6599
  const sib = pre.parent ? pre.parent.children : this.doc.layers;
6465
- this.dryLayersFirst([id, _optionalChain([sib, 'access', _304 => _304[pre.index - 1], 'optionalAccess', _305 => _305.id])].filter((x) => Boolean(x)));
6600
+ this.dryLayersFirst([id, _optionalChain([sib, 'access', _305 => _305[pre.index - 1], 'optionalAccess', _306 => _306.id])].filter((x) => Boolean(x)));
6466
6601
  }
6467
6602
  const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id);
6468
6603
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
@@ -6482,7 +6617,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6482
6617
  const merged = { ...below, surface, offset: { x: 0, y: 0 } };
6483
6618
  const layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, upper.id, () => null), below.id, () => merged);
6484
6619
  const toDoc = (t, l) => t ? _chunk474IQG74cjs.translateSurface.call(void 0, t, l.offset.x, l.offset.y) : void 0;
6485
- const mergedLight = _optionalChain([this, 'access', _306 => _306.doc, 'access', _307 => _307.light, 'optionalAccess', _308 => _308[upper.id]]) || _optionalChain([this, 'access', _309 => _309.doc, 'access', _310 => _310.light, 'optionalAccess', _311 => _311[below.id]]) ? mergeLight(toDoc(_optionalChain([this, 'access', _312 => _312.doc, 'access', _313 => _313.light, 'optionalAccess', _314 => _314[below.id]]), below), upper.visible ? toDoc(_optionalChain([this, 'access', _315 => _315.doc, 'access', _316 => _316.light, 'optionalAccess', _317 => _317[upper.id]]), upper) : void 0, _chunk474IQG74cjs.translateSurface.call(void 0, upper.surface, upper.offset.x, upper.offset.y)) : void 0;
6620
+ const mergedLight = _optionalChain([this, 'access', _307 => _307.doc, 'access', _308 => _308.light, 'optionalAccess', _309 => _309[upper.id]]) || _optionalChain([this, 'access', _310 => _310.doc, 'access', _311 => _311.light, 'optionalAccess', _312 => _312[below.id]]) ? mergeLight(toDoc(_optionalChain([this, 'access', _313 => _313.doc, 'access', _314 => _314.light, 'optionalAccess', _315 => _315[below.id]]), below), upper.visible ? toDoc(_optionalChain([this, 'access', _316 => _316.doc, 'access', _317 => _317.light, 'optionalAccess', _318 => _318[upper.id]]), upper) : void 0, _chunk474IQG74cjs.translateSurface.call(void 0, upper.surface, upper.offset.x, upper.offset.y)) : void 0;
6486
6621
  const lightAfter = _nullishCoalesce(this.lightWithout([upper.id, below.id]).light, () => ( (this.doc.light ? { ...this.doc.light } : void 0)));
6487
6622
  const light = mergedLight ? { ..._nullishCoalesce(lightAfter, () => ( {})), [below.id]: mergedLight } : lightAfter;
6488
6623
  this.commit("Merge down", this.withWetEvents({ ...this.doc, layers, activeLayerId: below.id, ...this.thickWithout([upper.id]), ...this.stickersWithout([upper.id, below.id]), ...this.liveStrokesWithout([upper.id, below.id]), ...light ? { light } : {} }));
@@ -6497,7 +6632,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6497
6632
  this.wet.world.removeLane(l.id);
6498
6633
  }
6499
6634
  const bounds = this.describeLayer(l).bounds;
6500
- this.commit("Clear layer", this.withPaintEvent({ ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface: _chunk474IQG74cjs.emptySurface.call(void 0, 4) })), ...this.thickWithout([l.id]), ...this.stickersWithout([l.id]), ..._optionalChain([this, 'access', _318 => _318.doc, 'access', _319 => _319.liveStrokes, 'optionalAccess', _320 => _320[l.id]]) ? { liveStrokes: { ...this.doc.liveStrokes, [l.id]: [] } } : {}, ...this.lightWithout([l.id]) }, { kind: "clear", layerId: l.id }));
6635
+ this.commit("Clear layer", this.withPaintEvent({ ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface: _chunk474IQG74cjs.emptySurface.call(void 0, 4) })), ...this.thickWithout([l.id]), ...this.stickersWithout([l.id]), ..._optionalChain([this, 'access', _319 => _319.doc, 'access', _320 => _320.liveStrokes, 'optionalAccess', _321 => _321[l.id]]) ? { liveStrokes: { ...this.doc.liveStrokes, [l.id]: [] } } : {}, ...this.lightWithout([l.id]) }, { kind: "clear", layerId: l.id }));
6501
6636
  return { layerId: l.id, bounds };
6502
6637
  }
6503
6638
  /**
@@ -6507,8 +6642,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6507
6642
  fillLayer(options = {}) {
6508
6643
  this.requireIdle("filling");
6509
6644
  const fillTarget = this.paintTarget(options.layerId, "fill");
6510
- if (_optionalChain([this, 'access', _321 => _321.doc, 'access', _322 => _322.stickers, 'optionalAccess', _323 => _323[fillTarget.id], 'optionalAccess', _324 => _324.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
6511
- if (_optionalChain([this, 'access', _325 => _325.doc, 'access', _326 => _326.liveStrokes, 'optionalAccess', _327 => _327[fillTarget.id]])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a stroke layer (its pixels are drawn from its strokes); fill another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
6645
+ if (_optionalChain([this, 'access', _322 => _322.doc, 'access', _323 => _323.stickers, 'optionalAccess', _324 => _324[fillTarget.id], 'optionalAccess', _325 => _325.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
6646
+ if (_optionalChain([this, 'access', _326 => _326.doc, 'access', _327 => _327.liveStrokes, 'optionalAccess', _328 => _328[fillTarget.id]])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a stroke layer (its pixels are drawn from its strokes); fill another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
6512
6647
  this.dryLayersFirst([_nullishCoalesce(_nullishCoalesce(options.layerId, () => ( this.doc.activeLayerId)), () => ( ""))]);
6513
6648
  const l = this.paintTarget(options.layerId, "fill");
6514
6649
  const color = options.color === void 0 ? this.color : parseColor(options.color);
@@ -6541,7 +6676,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6541
6676
  offset: l.offset
6542
6677
  };
6543
6678
  const surface = this.applyCoverage(l, coverage, rect, apply);
6544
- const lit = _optionalChain([this, 'access', _328 => _328.doc, 'access', _329 => _329.light, 'optionalAccess', _330 => _330[l.id]]);
6679
+ const lit = _optionalChain([this, 'access', _329 => _329.doc, 'access', _330 => _330.light, 'optionalAccess', _331 => _331[l.id]]);
6545
6680
  const light = lit ? withLayerLight(this.doc.light, l.id, scaleLight(lit, 1 - opacity)) : void 0;
6546
6681
  this.commit("Fill layer", this.withPaintEvent(this.withWetEvents({ ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })), ...light ? { light } : {} }), { kind: "fill", layerId: l.id, data: { color, opacity, grain: grainAmount, pressure, blend } }));
6547
6682
  return { layerId: l.id, bounds: rect };
@@ -6551,7 +6686,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6551
6686
  const tiles = new Map(base.tiles);
6552
6687
  for (const { tx, ty } of _chunk474IQG74cjs.tilesInRect.call(void 0, { x: rect.x - l.offset.x, y: rect.y - l.offset.y, width: rect.width, height: rect.height })) {
6553
6688
  const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
6554
- const src = _nullishCoalesce(_optionalChain([base, 'access', _331 => _331.tiles, 'access', _332 => _332.get, 'call', _333 => _333(key), 'optionalAccess', _334 => _334.data]), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4)));
6689
+ const src = _nullishCoalesce(_optionalChain([base, 'access', _332 => _332.tiles, 'access', _333 => _333.get, 'call', _334 => _334(key), 'optionalAccess', _335 => _335.data]), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4)));
6555
6690
  const tile = _chunk474IQG74cjs.finishTile.call(void 0, _chunkFQPUF2W2cjs.applyStrokeToTile.call(void 0, coverage, src, 4, tx, ty, apply), 4, 0);
6556
6691
  if (tile) tiles.set(key, tile);
6557
6692
  else tiles.delete(key);
@@ -6584,7 +6719,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6584
6719
  }
6585
6720
  /** The effect a layer is drawn from, or `undefined` for other layers. */
6586
6721
  getEffectLayer(layerId) {
6587
- return _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _335 => _335.doc, 'access', _336 => _336.effectLayers, 'optionalAccess', _337 => _337[layerId]]) : void 0;
6722
+ return _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _336 => _336.doc, 'access', _337 => _337.effectLayers, 'optionalAccess', _338 => _338[layerId]]) : void 0;
6588
6723
  }
6589
6724
  /** The effect paper (without its pixels), or `null`. */
6590
6725
  getPaperEffect() {
@@ -6621,8 +6756,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6621
6756
  /** A pixel layer that takes effect pixels: unlocked, visible, no sticker layer, no wet paint. */
6622
6757
  effectTarget(layerId, what) {
6623
6758
  const l = this.paintTarget(layerId, what);
6624
- if (_optionalChain([this, 'access', _338 => _338.doc, 'access', _339 => _339.stickers, 'optionalAccess', _340 => _340[l.id], 'optionalAccess', _341 => _341.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
6625
- if (_optionalChain([this, 'access', _342 => _342.doc, 'access', _343 => _343.liveStrokes, 'optionalAccess', _344 => _344[l.id]])) throw new PaintEditorError(`Layer "${l.name}" is a stroke layer (its pixels are drawn from its strokes); ${what} another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
6759
+ if (_optionalChain([this, 'access', _339 => _339.doc, 'access', _340 => _340.stickers, 'optionalAccess', _341 => _341[l.id], 'optionalAccess', _342 => _342.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
6760
+ if (_optionalChain([this, 'access', _343 => _343.doc, 'access', _344 => _344.liveStrokes, 'optionalAccess', _345 => _345[l.id]])) throw new PaintEditorError(`Layer "${l.name}" is a stroke layer (its pixels are drawn from its strokes); ${what} another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
6626
6761
  if (this.wet.wetLayerIds().includes(l.id)) throw new PaintEditorError(`Layer "${l.name}" holds wet paint; effects go on dried paint, so dry it first (dry_paint) and try again.`);
6627
6762
  return l;
6628
6763
  }
@@ -6661,8 +6796,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6661
6796
  const was = this.doc.paperEffect;
6662
6797
  const paperEffect = {
6663
6798
  ...this.sourceOf(d, values, options.time),
6664
- opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _345 => _345.opacity]))), () => ( 1)),
6665
- blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _346 => _346.blend]))), () => ( "multiply")),
6799
+ opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _346 => _346.opacity]))), () => ( 1)),
6800
+ blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _347 => _347.blend]))), () => ( "multiply")),
6666
6801
  image: { width: pixels.width, height: pixels.height, data: new Uint8ClampedArray(pixels.data) },
6667
6802
  version: nextPaperEffectVersion()
6668
6803
  };
@@ -6715,8 +6850,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6715
6850
  const above = _nullishCoalesce(options.aboveId, () => ( this.doc.activeLayerId));
6716
6851
  const loc = above ? _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, above) : null;
6717
6852
  if (options.aboveId !== void 0 && !loc) throw new PaintEditorError(`Layer "${options.aboveId}" was removed while the effect rendered.`);
6718
- const layer = { ...createPaintLayer(_optionalChain([options, 'access', _347 => _347.name, 'optionalAccess', _348 => _348.trim, 'call', _349 => _349()]) || d.name), surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
6719
- const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _350 => _350.parent, 'optionalAccess', _351 => _351.id]), () => ( null)), loc ? loc.index + 1 : void 0);
6853
+ const layer = { ...createPaintLayer(_optionalChain([options, 'access', _348 => _348.name, 'optionalAccess', _349 => _349.trim, 'call', _350 => _350()]) || d.name), surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
6854
+ const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _351 => _351.parent, 'optionalAccess', _352 => _352.id]), () => ( null)), loc ? loc.index + 1 : void 0);
6720
6855
  const source = this.sourceOf(d, values, options.time);
6721
6856
  this.commit("Add effect layer", { ...this.doc, layers, activeLayerId: layer.id, effectLayers: { ..._nullishCoalesce(this.doc.effectLayers, () => ( {})), [layer.id]: source } });
6722
6857
  return { layer: this.describeLayer(layer), source };
@@ -6869,7 +7004,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6869
7004
  /** Renders the effect paints of recorded strokes (default all of them) before a replay. */
6870
7005
  async prepareStrokeEffects(strokeIds) {
6871
7006
  const ids = strokeIds ? new Set(strokeIds) : null;
6872
- const paints2 = this.doc.strokes.filter((s) => (!ids || ids.has(s.id)) && _optionalChain([s, 'access', _352 => _352.paint, 'optionalAccess', _353 => _353.type]) === "effect").map((s) => s.paint);
7007
+ const paints2 = this.doc.strokes.filter((s) => (!ids || ids.has(s.id)) && _optionalChain([s, 'access', _353 => _353.paint, 'optionalAccess', _354 => _354.type]) === "effect").map((s) => s.paint);
6873
7008
  await this.prepareEffectPaints(paints2);
6874
7009
  }
6875
7010
  /** A small preview of the effect paint (a PNG data URL `size` px wide), or `null` without a rendered one. */
@@ -6898,7 +7033,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6898
7033
  * its pixels are not rendered.
6899
7034
  */
6900
7035
  strokeEffect(init, brush) {
6901
- if (!_chunkHS6QDWDFcjs.brushTakesPaint.call(void 0, brush)) return null;
7036
+ if (!_chunkHIMGBZAMcjs.brushTakesPaint.call(void 0, brush)) return null;
6902
7037
  let source = null;
6903
7038
  if (init.paint !== void 0) {
6904
7039
  if (!isPaintEffectPaint(init.paint)) return null;
@@ -6932,14 +7067,14 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6932
7067
  const before = _chunk474IQG74cjs.readRegion.call(void 0, l.surface, rect);
6933
7068
  const inputs = { source: { width: rect.width, height: rect.height, data: before } };
6934
7069
  const heightInput = d.inputs.find((i) => i.kind === "image" && /^(height|depth|relief)$/i.test(i.name));
6935
- const relief = _optionalChain([this, 'access', _354 => _354.doc, 'access', _355 => _355.thick, 'optionalAccess', _356 => _356[l.id]]);
7070
+ const relief = _optionalChain([this, 'access', _355 => _355.doc, 'access', _356 => _356.thick, 'optionalAccess', _357 => _357[l.id]]);
6936
7071
  if (heightInput && relief) {
6937
7072
  const h = _chunk474IQG74cjs.readRegion.call(void 0, relief.height, rect);
6938
7073
  const rgba = new Uint8ClampedArray(rect.width * rect.height * 4);
6939
7074
  for (let i = 0; i < h.length; i++) rgba.set([h[i], h[i], h[i], 255], i * 4);
6940
7075
  inputs[heightInput.name] = { width: rect.width, height: rect.height, data: rgba };
6941
7076
  }
6942
- const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _357 => _357.inputs, 'access', _358 => _358.find, 'call', _359 => _359((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _360 => _360.name])), 'optionalAccess', _361 => _361.name]), () => ( "source"));
7077
+ const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _358 => _358.inputs, 'access', _359 => _359.find, 'call', _360 => _360((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _361 => _361.name])), 'optionalAccess', _362 => _362.name]), () => ( "source"));
6943
7078
  if (sourceInput !== "source") {
6944
7079
  inputs[sourceInput] = inputs.source;
6945
7080
  delete inputs.source;
@@ -6955,11 +7090,11 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6955
7090
  return this.brushEntries.find((e) => e.brush.id === id);
6956
7091
  }
6957
7092
  findBrush(id) {
6958
- return _optionalChain([this, 'access', _362 => _362.findEntry, 'call', _363 => _363(id), 'optionalAccess', _364 => _364.brush]);
7093
+ return _optionalChain([this, 'access', _363 => _363.findEntry, 'call', _364 => _364(id), 'optionalAccess', _365 => _365.brush]);
6959
7094
  }
6960
7095
  requireEntry(id) {
6961
7096
  const e = this.findEntry(id);
6962
- if (!e) throw new PaintEditorError(`Unknown brush "${id}". ${_chunk34KLWUH4cjs.closest.call(void 0, id, this.brushEntries.map((x) => x.brush.id))}Call list_brush_presets for the ids.`);
7097
+ if (!e) throw new PaintEditorError(`Unknown brush "${id}". ${_chunkHIMGBZAMcjs.closest.call(void 0, id, this.brushEntries.map((x) => x.brush.id))}Call list_brush_presets for the ids.`);
6963
7098
  return e;
6964
7099
  }
6965
7100
  requireBrush(id) {
@@ -6985,11 +7120,11 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
6985
7120
  /** A library brush by id, as the engine paints it (`undefined` when unknown). */
6986
7121
  getBrush(id) {
6987
7122
  const b = this.findBrush(id);
6988
- return b ? _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, b, b) : void 0;
7123
+ return b ? _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, b, b) : void 0;
6989
7124
  }
6990
7125
  /** A library brush by id as stored (its facets), or without an id the active brush as edited. */
6991
7126
  getBrushSpec(id) {
6992
- const spec = id === void 0 ? this.brushSpec : _optionalChain([this, 'access', _365 => _365.findEntry, 'call', _366 => _366(id), 'optionalAccess', _367 => _367.spec]);
7127
+ const spec = id === void 0 ? this.brushSpec : _optionalChain([this, 'access', _366 => _366.findEntry, 'call', _367 => _367(id), 'optionalAccess', _368 => _368.spec]);
6993
7128
  return spec ? copyJSON(spec) : void 0;
6994
7129
  }
6995
7130
  /**
@@ -7003,7 +7138,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7003
7138
  const baseSpec = entry ? entry.spec : this.brushSpec;
7004
7139
  if (changes.paint !== void 0 && changes.paint !== null) this.readStrokePaint(changes.paint);
7005
7140
  const unchanged = !Object.keys(changes).length;
7006
- const next = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
7141
+ const next = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
7007
7142
  this.useBrush(next, unchanged ? baseSpec : brushSpecOf(next, baseSpec), unchanged && base.builtin === true);
7008
7143
  return this.brush;
7009
7144
  }
@@ -7020,7 +7155,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7020
7155
  const base = copyJSON(entry ? entry.spec : this.brushSpec);
7021
7156
  for (const k of unset) delete base[k];
7022
7157
  const spec = this.readBrushPatch(base, patch, problems);
7023
- this.useBrush(unchanged && entry ? entry.brush : _chunk34KLWUH4cjs.resolveBrush.call(void 0, spec), spec, unchanged && _optionalChain([entry, 'optionalAccess', _368 => _368.builtin]) === true);
7158
+ this.useBrush(unchanged && entry ? entry.brush : _chunkHIMGBZAMcjs.resolveBrush.call(void 0, spec), spec, unchanged && _optionalChain([entry, 'optionalAccess', _369 => _369.builtin]) === true);
7024
7159
  return { brush: this.brush, spec: copyJSON(this.brushSpec), problems };
7025
7160
  }
7026
7161
  /**
@@ -7030,15 +7165,15 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7030
7165
  */
7031
7166
  setBrushSpec(spec) {
7032
7167
  const problems = [];
7033
- const paint = _optionalChain([spec, 'access', _369 => _369.colour, 'optionalAccess', _370 => _370.default]);
7168
+ const paint = _optionalChain([spec, 'access', _370 => _370.colour, 'optionalAccess', _371 => _371.default]);
7034
7169
  if (paint && typeof paint === "object" && "type" in paint && paint.type === "gradient") this.readStrokePaint(paint);
7035
7170
  let next;
7036
7171
  try {
7037
- next = _chunk34KLWUH4cjs.normalizeBrushSpec.call(void 0, { ...spec, id: this.brush.id }, problems);
7172
+ next = _chunkHIMGBZAMcjs.normalizeBrushSpec.call(void 0, { ...spec, id: this.brush.id }, problems);
7038
7173
  } catch (e) {
7039
7174
  throw new PaintEditorError(e.message);
7040
7175
  }
7041
- this.useBrush(_chunk34KLWUH4cjs.resolveBrush.call(void 0, next), next, false);
7176
+ this.useBrush(_chunkHIMGBZAMcjs.resolveBrush.call(void 0, next), next, false);
7042
7177
  return { brush: this.brush, spec: copyJSON(this.brushSpec), problems };
7043
7178
  }
7044
7179
  /**
@@ -7047,22 +7182,22 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7047
7182
  */
7048
7183
  brushChanges(patch, from) {
7049
7184
  const entry = typeof from === "string" ? this.requireEntry(from) : null;
7050
- const base = entry ? entry.brush : typeof from === "object" ? _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, from, from) : this.brush;
7051
- const spec = entry ? entry.spec : typeof from === "object" ? _chunk34KLWUH4cjs.migrateBrushV1.call(void 0, base) : this.brushSpec;
7052
- return engineChanges(base, _chunk34KLWUH4cjs.resolveBrush.call(void 0, this.readBrushPatch(spec, patch, [])));
7185
+ const base = entry ? entry.brush : typeof from === "object" ? _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, from, from) : this.brush;
7186
+ const spec = entry ? entry.spec : typeof from === "object" ? _chunkHIMGBZAMcjs.migrateBrushV1.call(void 0, base) : this.brushSpec;
7187
+ return engineChanges(base, _chunkHIMGBZAMcjs.resolveBrush.call(void 0, this.readBrushPatch(spec, patch, [])));
7053
7188
  }
7054
7189
  readBrushPatch(base, patch, problems) {
7055
7190
  const { id: _id, name, ...rest } = patch;
7056
- const paint = _optionalChain([rest, 'access', _371 => _371.colour, 'optionalAccess', _372 => _372.default]);
7191
+ const paint = _optionalChain([rest, 'access', _372 => _372.colour, 'optionalAccess', _373 => _373.default]);
7057
7192
  if (paint && typeof paint === "object" && "type" in paint && paint.type === "gradient") this.readStrokePaint(paint);
7058
7193
  try {
7059
- return _chunk34KLWUH4cjs.normalizeBrushSpec.call(void 0, _chunk34KLWUH4cjs.mergeBrushPatch.call(void 0, base, { ...rest, ...name !== void 0 ? { name } : {} }), problems);
7194
+ return _chunkHIMGBZAMcjs.normalizeBrushSpec.call(void 0, _chunkPGPFWC35cjs.mergeBrushPatch.call(void 0, base, { ...rest, ...name !== void 0 ? { name } : {} }), problems);
7060
7195
  } catch (e) {
7061
7196
  throw new PaintEditorError(e.message);
7062
7197
  }
7063
7198
  }
7064
7199
  useBrush(next, spec, builtin) {
7065
- next = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, next, next);
7200
+ next = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, next, next);
7066
7201
  if (builtin) next.builtin = true;
7067
7202
  else delete next.builtin;
7068
7203
  this.brush = next;
@@ -7077,9 +7212,9 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7077
7212
  * saved brush.
7078
7213
  */
7079
7214
  async saveBrush(options) {
7080
- if (!_chunkHS6QDWDFcjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
7215
+ if (!_chunkHIMGBZAMcjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
7081
7216
  if (this.brushLibrary.isBuiltin(options.id)) throw new PaintEditorError(`"${options.id}" is a built-in brush; save under another id.`);
7082
- const spec = options.brush ? brushSpecOf(_chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, options.brush, this.brush), this.brushSpec) : this.brushSpec;
7217
+ const spec = options.brush ? brushSpecOf(_chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, options.brush, this.brush), this.brushSpec) : this.brushSpec;
7083
7218
  const { brush } = await libraryCall(() => this.brushLibrary.save({ ...spec, id: options.id, name: _nullishCoalesce(options.name, () => ( spec.name)) }, { overwrite: true }));
7084
7219
  await this.refreshBrushes();
7085
7220
  return this.requireBrush(brush.id);
@@ -7092,7 +7227,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7092
7227
  }
7093
7228
  /** The user's saved brushes, as the engine paints them. */
7094
7229
  getUserBrushes() {
7095
- return this.brushEntries.filter((e) => !e.builtin).map((e) => _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, e.brush, e.brush));
7230
+ return this.brushEntries.filter((e) => !e.builtin).map((e) => _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, e.brush, e.brush));
7096
7231
  }
7097
7232
  /** A brush library file (version 2) of the given brushes (default: the user's brushes). */
7098
7233
  exportBrushes(ids) {
@@ -7153,7 +7288,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7153
7288
  * brush's gradient, else the editor's gradient paint. Erasers, blenders and smudges take none.
7154
7289
  */
7155
7290
  strokeGradient(init, brush, color) {
7156
- if (!_chunkHS6QDWDFcjs.brushTakesPaint.call(void 0, brush)) return null;
7291
+ if (!_chunkHIMGBZAMcjs.brushTakesPaint.call(void 0, brush)) return null;
7157
7292
  let g = null;
7158
7293
  if (init.paint !== void 0) {
7159
7294
  if (isPaintEffectPaint(init.paint)) return null;
@@ -7230,7 +7365,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7230
7365
  // --- Strokes -------------------------------------------------------------------
7231
7366
  strokeBrush(init) {
7232
7367
  let brush = init.brushId !== void 0 ? this.requireBrush(init.brushId) : this.brush;
7233
- if (init.brush) brush = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
7368
+ if (init.brush) brush = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
7234
7369
  return brush;
7235
7370
  }
7236
7371
  /**
@@ -7263,29 +7398,30 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7263
7398
  return l;
7264
7399
  })();
7265
7400
  const brush = this.strokeBrush(init);
7401
+ if (this.previewing && _chunkHIMGBZAMcjs.isWetBrush.call(void 0, brush)) throw new PaintEditorError(`Wet paint can't be previewed; the ${brush.name} brush paints wet media. Suggest it with a dry brush.`);
7266
7402
  const effect = this.strokeEffect(init, brush);
7267
7403
  if (brush.light.amount > 0) {
7268
7404
  if (brush.engine === "sticker") throw new PaintEditorError(`The ${brush.name} brush sprays stickers, which don't take light yet; paint light with a dab or particle light brush (glow-gel, neon-marker; list_brush_presets lists them), or set light.amount to 0 (set_brush).`);
7269
7405
  }
7270
- if (_optionalChain([doc, 'access', _373 => _373.liveStrokes, 'optionalAccess', _374 => _374[layer.id]])) {
7406
+ if (_optionalChain([doc, 'access', _374 => _374.liveStrokes, 'optionalAccess', _375 => _375[layer.id]])) {
7271
7407
  const why = liveStrokeRefusal(brush);
7272
7408
  if (why) throw new PaintEditorError(`Layer "${layer.name}" is a stroke layer. ${why}`);
7273
7409
  }
7274
- if (_optionalChain([doc, 'access', _375 => _375.liveStrokes, 'optionalAccess', _376 => _376[layer.id]]) && _optionalChain([effect, 'optionalAccess', _377 => _377.source, 'access', _378 => _378.live])) {
7410
+ if (_optionalChain([doc, 'access', _376 => _376.liveStrokes, 'optionalAccess', _377 => _377[layer.id]]) && _optionalChain([effect, 'optionalAccess', _378 => _378.source, 'access', _379 => _379.live])) {
7275
7411
  const key = effectPaintKey(effect.source);
7276
7412
  const { sources } = this.liveEffects(doc);
7277
7413
  if (!sources.some((p) => effectPaintKey(p) === key) && sources.length >= MAX_LIVE_EFFECT_SOURCES) {
7278
7414
  throw new PaintEditorError(`The painting already plays ${MAX_LIVE_EFFECT_SOURCES} live effects, the most it can; paint with one of them, or set_effect_paint with live false to bake this one.`);
7279
7415
  }
7280
7416
  }
7281
- const stickerLayer = Boolean(_optionalChain([doc, 'access', _379 => _379.stickers, 'optionalAccess', _380 => _380[layer.id], 'optionalAccess', _381 => _381.length]));
7417
+ const stickerLayer = Boolean(_optionalChain([doc, 'access', _380 => _380.stickers, 'optionalAccess', _381 => _381[layer.id], 'optionalAccess', _382 => _382.length]));
7282
7418
  if (brush.engine === "sticker") {
7283
7419
  if (!stickerLayer && _chunk474IQG74cjs.contentBounds.call(void 0, layer.surface)) throw new PaintEditorError(`Layer "${layer.name}" already has paint; spray stickers onto an empty layer (add_layer) so they stay editable.`);
7284
7420
  } else if (stickerLayer) {
7285
7421
  throw new PaintEditorError(`Layer "${layer.name}" is a sticker layer (its pixels are drawn from its stickers); paint on another layer (add_layer).`);
7286
7422
  }
7287
7423
  let wet;
7288
- if (_chunkHS6QDWDFcjs.isWetBrush.call(void 0, brush)) {
7424
+ if (_chunkHIMGBZAMcjs.isWetBrush.call(void 0, brush)) {
7289
7425
  this.requireWetIdle("painting");
7290
7426
  if (layer.offset.x || layer.offset.y) {
7291
7427
  const moved = { ...layer, surface: _chunk474IQG74cjs.translateSurface.call(void 0, layer.surface, layer.offset.x, layer.offset.y), offset: { x: 0, y: 0 } };
@@ -7318,7 +7454,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7318
7454
  copies: [IDENTITY_AFFINE, ...copiesW].map(affineCopy),
7319
7455
  mask: init.maskStencils ? this.stencilSelection(init.maskStencils) : init.stencils !== false ? this.stencilSelection() : null,
7320
7456
  paint: effect ? null : wetGradient,
7321
- effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _382 => _382.pixels]), () => ( null))
7457
+ effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _383 => _383.pixels]), () => ( null))
7322
7458
  });
7323
7459
  init = { ...init, seed: seedW, load };
7324
7460
  wet = { driver, surface: () => world.display(id).surface };
@@ -7329,7 +7465,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7329
7465
  }
7330
7466
  let color = init.color === void 0 ? this.color : parseColor(init.color);
7331
7467
  const tracing = this.guides.tracing;
7332
- if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _383 => _383.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
7468
+ if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _384 => _384.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
7333
7469
  const perspective = this.guides.perspective;
7334
7470
  const snapper = init.snapToPerspective && perspective.enabled && perspective.snap ? new PerspectiveSnapper(perspective) : null;
7335
7471
  const useStencils = init.stencils !== false;
@@ -7362,9 +7498,9 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7362
7498
  mixerLoad: _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [rgba[0] / 255, rgba[1] / 255, rgba[2] / 255]))),
7363
7499
  secondary: rgbaOf(this.secondaryColor),
7364
7500
  wet,
7365
- thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _384 => _384.thick, 'optionalAccess', _385 => _385[layer.id]]), () => ( emptyThickChannels())) } : void 0,
7501
+ thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _385 => _385.thick, 'optionalAccess', _386 => _386[layer.id]]), () => ( emptyThickChannels())) } : void 0,
7366
7502
  // Light paint: a twin of the stroke paints the light channel (laying, dimming, moving light).
7367
- light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _386 => _386.light, 'optionalAccess', _387 => _387[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _388 => _388.light, 'optionalAccess', _389 => _389[layer.id]]), () => ( emptyLight())) } : null,
7503
+ light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _387 => _387.light, 'optionalAccess', _388 => _388[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _389 => _389.light, 'optionalAccess', _390 => _390[layer.id]]), () => ( emptyLight())) } : null,
7368
7504
  sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc), art: this.stickerArt.get } : void 0,
7369
7505
  paint: effect ? null : this.strokeGradient(init, brush, color),
7370
7506
  effect
@@ -7378,7 +7514,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7378
7514
  const stroke = {
7379
7515
  id: `s${this.strokeCounter++}`,
7380
7516
  layerId: session.layerId,
7381
- brush: _chunkHS6QDWDFcjs.brushToJSON.call(void 0, init.brush),
7517
+ brush: _chunkHIMGBZAMcjs.brushToJSON.call(void 0, init.brush),
7382
7518
  color: init.colorHex,
7383
7519
  points: session.points.map((p) => ({ ...p })),
7384
7520
  seed: init.seed
@@ -7403,12 +7539,12 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7403
7539
  const before = this.doc;
7404
7540
  const host = {
7405
7541
  update: (layerId, surface, rects) => {
7406
- if (_optionalChain([this, 'access', _390 => _390.session, 'optionalAccess', _391 => _391.init, 'access', _392 => _392.wet])) {
7542
+ if (_optionalChain([this, 'access', _391 => _391.session, 'optionalAccess', _392 => _392.init, 'access', _393 => _393.wet])) {
7407
7543
  this.wet.syncDisplays();
7408
7544
  return;
7409
7545
  }
7410
7546
  this.live = { layerId, surface };
7411
- const ch = _optionalChain([this, 'access', _393 => _393.session, 'optionalAccess', _394 => _394.thickChannels, 'call', _395 => _395()]);
7547
+ const ch = _optionalChain([this, 'access', _394 => _394.session, 'optionalAccess', _395 => _395.thickChannels, 'call', _396 => _396()]);
7412
7548
  this.liveThick = ch ? { layerId, channels: ch } : null;
7413
7549
  this.emit(rects);
7414
7550
  },
@@ -7420,7 +7556,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7420
7556
  const wetStroke = Boolean(s.init.wet);
7421
7557
  if (wetStroke) this.wet.driver = null;
7422
7558
  const brush = s.init.brush;
7423
- if (!cancelled && _optionalChain([s, 'access', _396 => _396.result, 'optionalAccess', _397 => _397.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
7559
+ if (!cancelled && _optionalChain([s, 'access', _397 => _397.result, 'optionalAccess', _398 => _398.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
7424
7560
  if (cancelled || !surface) {
7425
7561
  if (this.wetOp) {
7426
7562
  const snap = this.wetOp.before;
@@ -7435,7 +7571,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7435
7571
  }
7436
7572
  const stroke = this.record(s);
7437
7573
  s.result.strokeId = stroke.id;
7438
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _398 => _398.result, 'optionalAccess', _399 => _399.bounds]), () => ( null)));
7574
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _399 => _399.result, 'optionalAccess', _400 => _400.bounds]), () => ( null)));
7439
7575
  if (wetStroke && this.wet.instantDry) {
7440
7576
  this.wet.dry(s.layerId);
7441
7577
  this.logWet({ kind: "dry", layerId: s.layerId, at: this.doc.strokes.length + 1 });
@@ -7446,8 +7582,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7446
7582
  const ch = s.thickChannels();
7447
7583
  const thick = ch ? { ..._nullishCoalesce(this.doc.thick, () => ( {})), [l.id]: ch } : this.doc.thick;
7448
7584
  const sprayed = s.stickers();
7449
- const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _400 => _400.doc, 'access', _401 => _401.stickers, 'optionalAccess', _402 => _402[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
7450
- const wetLight = wetStroke && _optionalChain([this, 'access', _403 => _403.wet, 'access', _404 => _404.world, 'optionalAccess', _405 => _405.hasLane, 'call', _406 => _406(l.id)]) ? this.wet.world.lightDisplay(l.id) : null;
7585
+ const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _401 => _401.doc, 'access', _402 => _402.stickers, 'optionalAccess', _403 => _403[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
7586
+ const wetLight = wetStroke && _optionalChain([this, 'access', _404 => _404.wet, 'access', _405 => _405.world, 'optionalAccess', _406 => _406.hasLane, 'call', _407 => _407(l.id)]) ? this.wet.world.lightDisplay(l.id) : null;
7451
7587
  const light = withLayerLight(this.doc.light, l.id, _nullishCoalesce(s.lightChannel(), () => ( wetLight)));
7452
7588
  this.commit(`${brush.name} stroke`, this.withWetEvents(withLiveStroke({ ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })), strokes: [...this.doc.strokes, stroke], ...thick ? { thick } : {}, ...stickers ? { stickers } : {}, ...light ? { light } : {} }, stroke)), wetStroke ? before : this.doc);
7453
7589
  }
@@ -7477,18 +7613,18 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7477
7613
  if (cancelled || !surface) return;
7478
7614
  const stroke = this.record(s);
7479
7615
  s.result.strokeId = stroke.id;
7480
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _407 => _407.result, 'optionalAccess', _408 => _408.bounds]), () => ( null)));
7616
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _408 => _408.result, 'optionalAccess', _409 => _409.bounds]), () => ( null)));
7481
7617
  const l = _chunkDPYAO5U6cjs.findLayer.call(void 0, out.layers, s.layerId).layer;
7482
7618
  const offset = s.init.wet ? { x: 0, y: 0 } : l.offset;
7483
7619
  const ch = s.thickChannels();
7484
7620
  const sprayed = s.stickers();
7485
- const lit = _nullishCoalesce(s.lightChannel(), () => ( (s.init.wet && _optionalChain([this, 'access', _409 => _409.wet, 'access', _410 => _410.world, 'optionalAccess', _411 => _411.hasLane, 'call', _412 => _412(l.id)]) ? this.wet.world.lightDisplay(l.id) : null)));
7621
+ const lit = _nullishCoalesce(s.lightChannel(), () => ( (s.init.wet && _optionalChain([this, 'access', _410 => _410.wet, 'access', _411 => _411.world, 'optionalAccess', _412 => _412.hasLane, 'call', _413 => _413(l.id)]) ? this.wet.world.lightDisplay(l.id) : null)));
7486
7622
  out = withLiveStroke({
7487
7623
  ...out,
7488
7624
  layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, out.layers, l.id, () => ({ ...l, surface, offset })),
7489
7625
  strokes: [...out.strokes, stroke],
7490
7626
  ...ch ? { thick: { ..._nullishCoalesce(out.thick, () => ( {})), [l.id]: ch } } : {},
7491
- ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _413 => _413.stickers, 'optionalAccess', _414 => _414[l.id]]), () => ( [])), ...sprayed] } } : {},
7627
+ ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _414 => _414.stickers, 'optionalAccess', _415 => _415[l.id]]), () => ( [])), ...sprayed] } } : {},
7492
7628
  ...lit ? { light: withLayerLight(out.light, l.id, lit) } : {}
7493
7629
  }, stroke);
7494
7630
  }
@@ -7547,7 +7683,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7547
7683
  */
7548
7684
  replayStrokes(options) {
7549
7685
  this.requireIdle("replaying");
7550
- if (!_optionalChain([options, 'access', _415 => _415.strokeIds, 'optionalAccess', _416 => _416.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
7686
+ if (!_optionalChain([options, 'access', _416 => _416.strokeIds, 'optionalAccess', _417 => _417.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
7551
7687
  const strokes = options.strokeIds.map((id) => {
7552
7688
  const s = this.doc.strokes.find((x) => x.id === id);
7553
7689
  if (!s) throw new PaintEditorError(`Unknown stroke "${id}". Call list_strokes for the ids.`);
@@ -7561,7 +7697,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7561
7697
  if (options.layerId !== void 0) this.paintTarget(options.layerId, "replay onto");
7562
7698
  if (options.color === void 0) {
7563
7699
  for (const s of strokes) {
7564
- if (_optionalChain([s, 'access', _417 => _417.paint, 'optionalAccess', _418 => _418.type]) === "effect" && !this.effectPaintImage(s.paint)) {
7700
+ if (_optionalChain([s, 'access', _418 => _418.paint, 'optionalAccess', _419 => _419.type]) === "effect" && !this.effectPaintImage(s.paint)) {
7565
7701
  throw new PaintEditorError(`Stroke "${s.id}" paints with the effect "${s.paint.effect}"${s.paint.provider ? ` from provider "${s.paint.provider}"` : ""}, which is not rendered in this editor; render it first (prepareStrokeEffects; the replay_strokes tool does this) or recolour the replay with color.`);
7566
7702
  }
7567
7703
  }
@@ -7584,7 +7720,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7584
7720
  let brush = v.brush;
7585
7721
  if (options.brushId !== void 0) {
7586
7722
  const b = this.requireBrush(options.brushId);
7587
- brush = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
7723
+ brush = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
7588
7724
  }
7589
7725
  const layerId = _nullishCoalesce(options.layerId, () => ( s.layerId));
7590
7726
  if (!_chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, layerId)) throw new PaintEditorError(`Stroke "${s.id}" was painted on layer "${layerId}", which no longer exists; pass layerId to replay it elsewhere.`);
@@ -7619,7 +7755,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7619
7755
  /** A layer's light paint: whether it has any, where (document pixels), its brightest value 0..255, and its spill. */
7620
7756
  lightOf(layerId) {
7621
7757
  const l = this.wetLayer(layerId, "read the light of");
7622
- const info = lightInfo(_optionalChain([this, 'access', _419 => _419.doc, 'access', _420 => _420.light, 'optionalAccess', _421 => _421[l.id]]));
7758
+ const info = lightInfo(_optionalChain([this, 'access', _420 => _420.doc, 'access', _421 => _421.light, 'optionalAccess', _422 => _422[l.id]]));
7623
7759
  const bounds = info.bounds ? { ...info.bounds, x: info.bounds.x + l.offset.x, y: info.bounds.y + l.offset.y } : null;
7624
7760
  return { layerId: l.id, hasLight: info.peak > 0, bounds, peak: info.peak, spill: { ...this.lightSpillOf(l.id) } };
7625
7761
  }
@@ -7670,7 +7806,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7670
7806
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
7671
7807
  if (!id) return null;
7672
7808
  this.requireLayer(id);
7673
- const ch = _optionalChain([this, 'access', _422 => _422.doc, 'access', _423 => _423.thick, 'optionalAccess', _424 => _424[id]]);
7809
+ const ch = _optionalChain([this, 'access', _423 => _423.doc, 'access', _424 => _424.thick, 'optionalAccess', _425 => _425[id]]);
7674
7810
  if (!ch) return null;
7675
7811
  const r = reliefInfo(ch);
7676
7812
  return { layerId: id, bounds: r.bounds, maxHeight: r.maxHeight };
@@ -7780,7 +7916,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7780
7916
  wetState() {
7781
7917
  const st = this.getState().wet;
7782
7918
  const backend = this.wet.backend();
7783
- return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _425 => _425.message]), () => ( _chunkKBYB7OWBcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
7919
+ return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _426 => _426.message]), () => ( _chunkKBYB7OWBcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
7784
7920
  }
7785
7921
  /**
7786
7922
  * Engine B, the WebGPU accelerator for large wet areas: whether it may run, its state (`off`,
@@ -7865,7 +8001,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7865
8001
  }
7866
8002
  /** Records a settings change as a wet event (not an undo step). */
7867
8003
  recordWetSetting(e) {
7868
- this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _426 => _426.wet, 'access', _427 => _427.world, 'optionalAccess', _428 => _428.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
8004
+ this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _427 => _427.wet, 'access', _428 => _428.world, 'optionalAccess', _429 => _429.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
7869
8005
  }
7870
8006
  /** Changes a layer's wet settings (viscosity, evaporation, granulation…). Editor settings saved with the document, not an undo step. */
7871
8007
  setWetParams(layerId, update) {
@@ -7934,7 +8070,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7934
8070
  if (override) return Array.from(override).reduce((ls, [id, surface]) => _chunkDPYAO5U6cjs.mapLayer.call(void 0, ls, id, (l) => ({ ...l, surface })), this.doc.layers);
7935
8071
  const live = this.live;
7936
8072
  if (!live) return this.animatedView();
7937
- if (_optionalChain([this, 'access', _429 => _429.liveLayers, 'optionalAccess', _430 => _430.key]) === live.surface) return this.liveLayers.layers;
8073
+ if (_optionalChain([this, 'access', _430 => _430.liveLayers, 'optionalAccess', _431 => _431.key]) === live.surface) return this.liveLayers.layers;
7938
8074
  const layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, live.layerId, (l) => ({ ...l, surface: live.surface }));
7939
8075
  this.liveLayers = { key: live.surface, layers };
7940
8076
  return layers;
@@ -7957,7 +8093,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7957
8093
  tracingNode(t) {
7958
8094
  const { width, height } = this.doc.canvas;
7959
8095
  const key = this.tracingVersion * 100003 + width * 7 + height;
7960
- if (_optionalChain([this, 'access', _431 => _431.tracingCache, 'optionalAccess', _432 => _432.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
8096
+ if (_optionalChain([this, 'access', _432 => _432.tracingCache, 'optionalAccess', _433 => _433.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
7961
8097
  const src = _nullishCoalesce(this.imagePixels.get(t.src), () => ( this.decodeImage(t.src)));
7962
8098
  const image = resampleInto(src, t.rect, width, height);
7963
8099
  const node = { type: "image", id: TRACING_NODE_ID, name: "Tracing", visible: true, opacity: t.opacity, blend: "normal", image, version: key + Math.round(t.opacity * 1e3) / 1e4 };
@@ -7984,8 +8120,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
7984
8120
  let out = layers;
7985
8121
  const ids = /* @__PURE__ */ new Set([...Object.keys(_nullishCoalesce(thick, () => ( {}))), ...live ? [live.layerId] : []]);
7986
8122
  for (const id of ids) {
7987
- const ch = _optionalChain([live, 'optionalAccess', _433 => _433.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _434 => _434[id]]);
7988
- const l = ch && _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, out, id), 'optionalAccess', _435 => _435.layer]);
8123
+ const ch = _optionalChain([live, 'optionalAccess', _434 => _434.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _435 => _435[id]]);
8124
+ const l = ch && _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, out, id), 'optionalAccess', _436 => _436.layer]);
7989
8125
  if (!ch || !isPixelLayer(l)) continue;
7990
8126
  let cache = this.litCaches.get(id);
7991
8127
  if (!cache) this.litCaches.set(id, cache = new LitCache());
@@ -8005,13 +8141,13 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8005
8141
  if (!ids.size) return layers;
8006
8142
  let out = layers;
8007
8143
  for (const id of ids) {
8008
- const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, out, id), 'optionalAccess', _436 => _436.layer]);
8144
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, out, id), 'optionalAccess', _437 => _437.layer]);
8009
8145
  if (!isPixelLayer(l)) continue;
8010
8146
  let cache = this.lightCaches.get(id);
8011
8147
  if (!cache) this.lightCaches.set(id, cache = new LightCache());
8012
- const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _437 => _437.liveThick, 'optionalAccess', _438 => _438.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _439 => _439.doc, 'access', _440 => _440.thick, 'optionalAccess', _441 => _441[id]]));
8148
+ const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _438 => _438.liveThick, 'optionalAccess', _439 => _439.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _440 => _440.doc, 'access', _441 => _441.thick, 'optionalAccess', _442 => _442[id]]));
8013
8149
  if (glowed !== l.surface) out = _chunkDPYAO5U6cjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface: glowed }));
8014
- const committed = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _442 => _442.layer]);
8150
+ const committed = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _443 => _443.layer]);
8015
8151
  const spill = light[id] && isPixelLayer(committed) ? cache.spill(committed.surface, light[id], this.lightSpillOf(id)) : null;
8016
8152
  if (spill) out = insertAfter(out, id, { type: "pixel", id: `${id}${SPILL_SUFFIX}`, name: `${l.name} light`, visible: l.visible, opacity: l.opacity, blend: "linear-dodge", surface: spill, offset: { ...l.offset } });
8017
8153
  }
@@ -8023,7 +8159,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8023
8159
  if (!l.visible) continue;
8024
8160
  if (l.type === "group") this.backlitLayers(l.children, committed, opacity * l.opacity, out);
8025
8161
  else if (isPixelLayer(l)) {
8026
- const thick = !committed && _optionalChain([this, 'access', _443 => _443.liveThick, 'optionalAccess', _444 => _444.layerId]) === l.id ? this.liveThick.channels : _optionalChain([this, 'access', _445 => _445.doc, 'access', _446 => _446.thick, 'optionalAccess', _447 => _447[l.id]]);
8162
+ const thick = !committed && _optionalChain([this, 'access', _444 => _444.liveThick, 'optionalAccess', _445 => _445.layerId]) === l.id ? this.liveThick.channels : _optionalChain([this, 'access', _446 => _446.doc, 'access', _447 => _447.thick, 'optionalAccess', _448 => _448[l.id]]);
8027
8163
  out.push({ surface: l.surface, offset: l.offset, opacity: opacity * l.opacity, ...thick ? { thick } : {} });
8028
8164
  }
8029
8165
  }
@@ -8052,7 +8188,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8052
8188
  if (backlight) layers = [...layers, backlight];
8053
8189
  if (options.layerIds) {
8054
8190
  const picked = [];
8055
- for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, id), 'optionalAccess', _448 => _448.layer]), () => ( this.requireLayer(id))));
8191
+ for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, id), 'optionalAccess', _449 => _449.layer]), () => ( this.requireLayer(id))));
8056
8192
  layers = picked.map((l) => ({ ...l, visible: true }));
8057
8193
  }
8058
8194
  const under = options.paper === false ? [] : [paperNode(this.doc.paper, this.lighting)];
@@ -8068,7 +8204,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8068
8204
  */
8069
8205
  compositeTiles(rect, onTile, options = {}) {
8070
8206
  const dirty = options.dirty === "all" ? void 0 : options.dirty;
8071
- this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _449 => _449.live, 'optionalAccess', _450 => _450.layerId]), () => ( this.doc.activeLayerId)) });
8207
+ this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _450 => _450.live, 'optionalAccess', _451 => _451.layerId]), () => ( this.doc.activeLayerId)) });
8072
8208
  }
8073
8209
  /** The canvas as canvas-sized RGBA (paper included by default). */
8074
8210
  compositePixels(options = {}) {
@@ -8147,7 +8283,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8147
8283
  const spills = Object.fromEntries(Object.entries(this.lightSpills).filter(([id]) => _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)));
8148
8284
  if (Object.keys(spills).length) ext.lightSpill = spills;
8149
8285
  else delete ext.lightSpill;
8150
- const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _451 => _451.layer])));
8286
+ const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _452 => _452.layer])));
8151
8287
  if (effectLayers) ext.effectLayers = effectLayers;
8152
8288
  else delete ext.effectLayers;
8153
8289
  if (this.doc.paperEffect) ext.paperEffect = paperEffectToJSON(this.doc.paperEffect);
@@ -8183,7 +8319,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8183
8319
  if (ext.liveStrokes && typeof ext.liveStrokes === "object") {
8184
8320
  const liveStrokes = {};
8185
8321
  for (const [id, list] of Object.entries(ext.liveStrokes)) {
8186
- if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _452 => _452.layer])) || !Array.isArray(list)) continue;
8322
+ if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _453 => _453.layer])) || !Array.isArray(list)) continue;
8187
8323
  const ok = list.map(normalizeBrushStroke).filter((x) => x !== null).map((x) => ({ ...x, layerId: id }));
8188
8324
  if (ok.length !== list.length) problems.push(`Some strokes of stroke layer "${id}" could not be read; they were dropped (the layer's pixels are kept until a stroke is edited).`);
8189
8325
  liveStrokes[id] = ok;
@@ -8193,7 +8329,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8193
8329
  if (ext.effectLayers && typeof ext.effectLayers === "object") {
8194
8330
  const effectLayers = {};
8195
8331
  for (const [id, v] of Object.entries(ext.effectLayers)) {
8196
- if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _453 => _453.layer]))) continue;
8332
+ if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _454 => _454.layer]))) continue;
8197
8333
  const source = readPaintEffectSource(v);
8198
8334
  if (source) effectLayers[id] = source;
8199
8335
  else problems.push(`The effect of layer "${id}" could not be read; it loads as a plain layer.`);
@@ -8221,7 +8357,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8221
8357
  if (ext.light && typeof ext.light === "object") {
8222
8358
  const light = {};
8223
8359
  for (const [id, v] of Object.entries(ext.light)) {
8224
- if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _454 => _454.layer]))) continue;
8360
+ if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _455 => _455.layer]))) continue;
8225
8361
  try {
8226
8362
  light[id] = lightFromJSON(v);
8227
8363
  } catch (e) {
@@ -8257,7 +8393,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8257
8393
  this.readGuides(loaded.guides, loaded.state, loaded.problems);
8258
8394
  if (Array.isArray(loaded.swatches)) this.swatches = loaded.swatches.map(readSwatch).filter((x) => x !== null);
8259
8395
  for (const s of loaded.state.strokes) {
8260
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _455 => _455.exec, 'call', _456 => _456(s.id), 'optionalAccess', _457 => _457[1]]), () => ( 0)));
8396
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _456 => _456.exec, 'call', _457 => _457(s.id), 'optionalAccess', _458 => _458[1]]), () => ( 0)));
8261
8397
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
8262
8398
  }
8263
8399
  this.undoStack = [];
@@ -8265,7 +8401,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8265
8401
  this.doc = this.readThick(loaded.state, loaded.extensions, loaded.problems);
8266
8402
  for (const list of Object.values(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
8267
8403
  for (const s of list) {
8268
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _458 => _458.exec, 'call', _459 => _459(s.id), 'optionalAccess', _460 => _460[1]]), () => ( 0)));
8404
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _459 => _459.exec, 'call', _460 => _460(s.id), 'optionalAccess', _461 => _461[1]]), () => ( 0)));
8269
8405
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
8270
8406
  }
8271
8407
  }
@@ -8362,10 +8498,10 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8362
8498
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
8363
8499
  });
8364
8500
  const layers = toStandard(dried);
8365
- const result = _chunkJFHBXNR2cjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
8501
+ const result = _chunkB7V34GIHcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
8366
8502
  for (const [mode, names] of changed) {
8367
- const label = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _461 => _461.find, 'call', _462 => _462((m) => m.id === mode), 'optionalAccess', _463 => _463.label]), () => ( mode));
8368
- const std = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _464 => _464.find, 'call', _465 => _465((m) => m.id === _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _466 => _466.label]), () => ( _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)));
8503
+ const label = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _462 => _462.find, 'call', _463 => _463((m) => m.id === mode), 'optionalAccess', _464 => _464.label]), () => ( mode));
8504
+ const std = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _465 => _465.find, 'call', _466 => _466((m) => m.id === _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _467 => _467.label]), () => ( _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)));
8369
8505
  const list = names.map((n) => `"${n}"`).join(", ");
8370
8506
  const one = names.length === 1;
8371
8507
  result.warnings.push(`${label} blending has no PSD equivalent; ${list} ${one ? "was" : "were"} written as ${std}, the nearest Photoshop mode, so ${one ? "it looks" : "they look"} different in Photoshop (the merged image is exact).`);
@@ -8487,7 +8623,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8487
8623
  const { src, pixels } = this.importImage(options, "The reference image");
8488
8624
  const ref2 = {
8489
8625
  id: `ref${this.nextReferenceId++}`,
8490
- name: _optionalChain([options, 'access', _467 => _467.name, 'optionalAccess', _468 => _468.trim, 'call', _469 => _469()]) || `Reference ${this.guides.references.length + 1}`,
8626
+ name: _optionalChain([options, 'access', _468 => _468.name, 'optionalAccess', _469 => _469.trim, 'call', _470 => _470()]) || `Reference ${this.guides.references.length + 1}`,
8491
8627
  src,
8492
8628
  width: pixels.width,
8493
8629
  height: pixels.height,
@@ -8566,7 +8702,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8566
8702
  try {
8567
8703
  const px = this.decodeImage(ref2.src, `Reference "${ref2.name}"`);
8568
8704
  guides.references.push({ id: ref2.id, name: String(_nullishCoalesce(ref2.name, () => ( ref2.id))), src: ref2.src, width: px.width, height: px.height, x: Number(ref2.x) || 0, y: Number(ref2.y) || 0, displayWidth: Number(ref2.displayWidth) || 240, visible: ref2.visible !== false });
8569
- const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _470 => _470.exec, 'call', _471 => _471(ref2.id), 'optionalAccess', _472 => _472[1]]), () => ( 0)));
8705
+ const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _471 => _471.exec, 'call', _472 => _472(ref2.id), 'optionalAccess', _473 => _473[1]]), () => ( 0)));
8570
8706
  if (n >= this.nextReferenceId) this.nextReferenceId = n + 1;
8571
8707
  } catch (e) {
8572
8708
  problems.push(e.message);
@@ -8577,7 +8713,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8577
8713
  guides.stencils = [];
8578
8714
  r.stencils.forEach((raw2, i) => {
8579
8715
  try {
8580
- const id = typeof _optionalChain([raw2, 'optionalAccess', _473 => _473.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
8716
+ const id = typeof _optionalChain([raw2, 'optionalAccess', _474 => _474.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
8581
8717
  guides.stencils.push(normalizeStencil(raw2, id));
8582
8718
  const n = Number(id.slice(7));
8583
8719
  if (n >= this.nextStencilId) this.nextStencilId = n + 1;
@@ -8600,12 +8736,12 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8600
8736
  /** The next free sticker number (ids `st<n>` are unique across the document). */
8601
8737
  nextStickerNumber(doc = this.doc) {
8602
8738
  let n = 0;
8603
- for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _474 => _474.exec, 'call', _475 => _475(st.id), 'optionalAccess', _476 => _476[1]]), () => ( 0))));
8739
+ for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _475 => _475.exec, 'call', _476 => _476(st.id), 'optionalAccess', _477 => _477[1]]), () => ( 0))));
8604
8740
  return n + 1;
8605
8741
  }
8606
8742
  stickerLayer(layerId) {
8607
8743
  const l = this.wetLayer(layerId, "edit the stickers of");
8608
- const stickers = _optionalChain([this, 'access', _477 => _477.doc, 'access', _478 => _478.stickers, 'optionalAccess', _479 => _479[l.id]]);
8744
+ const stickers = _optionalChain([this, 'access', _478 => _478.doc, 'access', _479 => _479.stickers, 'optionalAccess', _480 => _480[l.id]]);
8609
8745
  if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (sticker-stars; list_brush_presets lists them).`);
8610
8746
  return { layer: l, stickers };
8611
8747
  }
@@ -8664,7 +8800,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8664
8800
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
8665
8801
  if (!id) return [];
8666
8802
  this.requireLayer(id);
8667
- return (_nullishCoalesce(_optionalChain([this, 'access', _480 => _480.doc, 'access', _481 => _481.stickers, 'optionalAccess', _482 => _482[id]]), () => ( []))).map((s) => ({ ...s }));
8803
+ return (_nullishCoalesce(_optionalChain([this, 'access', _481 => _481.doc, 'access', _482 => _482.stickers, 'optionalAccess', _483 => _483[id]]), () => ( []))).map((s) => ({ ...s }));
8668
8804
  }
8669
8805
  /**
8670
8806
  * Replaces a layer's stickers and redraws its pixels from them (one undo step). With `dirty`,
@@ -8685,7 +8821,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8685
8821
  }
8686
8822
  /** The document from before the sticker preview on screen, or `null` when none is (anything else changed the document since). */
8687
8823
  previewBase() {
8688
- return _optionalChain([this, 'access', _483 => _483.stickerPreview, 'optionalAccess', _484 => _484.shown]) === this.doc ? this.stickerPreview.base : null;
8824
+ return _optionalChain([this, 'access', _484 => _484.stickerPreview, 'optionalAccess', _485 => _485.shown]) === this.doc ? this.stickerPreview.base : null;
8689
8825
  }
8690
8826
  readStickerUpdate(update) {
8691
8827
  try {
@@ -8700,7 +8836,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8700
8836
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
8701
8837
  if (!id) return null;
8702
8838
  this.requireLayer(id);
8703
- const hit = stickerAt(_nullishCoalesce(_optionalChain([this, 'access', _485 => _485.doc, 'access', _486 => _486.stickers, 'optionalAccess', _487 => _487[id]]), () => ( [])), x, y, this.stickerArt.get);
8839
+ const hit = stickerAt(_nullishCoalesce(_optionalChain([this, 'access', _486 => _486.doc, 'access', _487 => _487.stickers, 'optionalAccess', _488 => _488[id]]), () => ( [])), x, y, this.stickerArt.get);
8704
8840
  return hit ? { ...hit } : null;
8705
8841
  }
8706
8842
  /** Picks a sticker for the panel and canvas (`null` for none). Editor state, not an undo step. */
@@ -8756,8 +8892,8 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8756
8892
  const layer = this.wetLayer(layerId, "add stickers to");
8757
8893
  if (!input.length) throw new PaintEditorError("Pass at least one sticker (ref, x, y).");
8758
8894
  if (input.length > MAX_ADD_STICKERS) throw new PaintEditorError(`At most ${MAX_ADD_STICKERS} stickers per call; split them over several calls.`);
8759
- const existing = _optionalChain([this, 'access', _488 => _488.doc, 'access', _489 => _489.stickers, 'optionalAccess', _490 => _490[layer.id]]);
8760
- if (!_optionalChain([existing, 'optionalAccess', _491 => _491.length])) {
8895
+ const existing = _optionalChain([this, 'access', _489 => _489.doc, 'access', _490 => _490.stickers, 'optionalAccess', _491 => _491[layer.id]]);
8896
+ if (!_optionalChain([existing, 'optionalAccess', _492 => _492.length])) {
8761
8897
  if (this.wet.wetLayerIds().includes(layer.id) || _chunk474IQG74cjs.contentBounds.call(void 0, layer.surface)) throw new PaintEditorError(`Layer "${layer.name}" already has paint; add stickers to an empty layer (add_layer) or a sticker layer so they stay editable.`);
8762
8898
  }
8763
8899
  let n = this.nextStickerNumber();
@@ -8774,7 +8910,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8774
8910
  const id = n++;
8775
8911
  return { id: `st${id}`, size: 48, rotation: 0, color: this.color, opacity: 1, seed: _nullishCoalesce(raw.seed, () => ( _chunk3K6HWEXZcjs.mix32.call(void 0, id * 2654435761 >>> 0) & 2147483647)), ...u };
8776
8912
  });
8777
- this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _492 => _492.length]) ? added.map(stickerRect) : void 0);
8913
+ this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _493 => _493.length]) ? added.map(stickerRect) : void 0);
8778
8914
  return added.map((s) => ({ ...s }));
8779
8915
  }
8780
8916
  /** Brings stickers to the top (`front`) or bottom of their layer (one undo step). */
@@ -8813,20 +8949,20 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8813
8949
  }
8814
8950
  liveStrokeLayer(layerId, what) {
8815
8951
  const l = this.wetLayer(layerId, what);
8816
- const strokes = _optionalChain([this, 'access', _493 => _493.doc, 'access', _494 => _494.liveStrokes, 'optionalAccess', _495 => _495[l.id]]);
8952
+ const strokes = _optionalChain([this, 'access', _494 => _494.doc, 'access', _495 => _495.liveStrokes, 'optionalAccess', _496 => _496[l.id]]);
8817
8953
  if (!strokes) throw new PaintEditorError(`Layer "${l.name}" is not a stroke layer; add one with add_layer {type: "strokes"} (or convert_to_stroke_layer on an empty layer), then paint on it.`);
8818
8954
  return { layer: l, strokes };
8819
8955
  }
8820
8956
  /** Whether a layer is a live stroke layer. */
8821
8957
  isLiveStrokeLayer(layerId) {
8822
- return Boolean(_optionalChain([this, 'access', _496 => _496.doc, 'access', _497 => _497.liveStrokes, 'optionalAccess', _498 => _498[layerId]]));
8958
+ return Boolean(_optionalChain([this, 'access', _497 => _497.doc, 'access', _498 => _498.liveStrokes, 'optionalAccess', _499 => _499[layerId]]));
8823
8959
  }
8824
8960
  /** Makes an empty pixel layer a live stroke layer (one undo step). */
8825
8961
  convertToLiveStrokes(layerId) {
8826
8962
  this.requireIdle("converting a layer");
8827
8963
  const l = this.paintTarget(layerId, "convert");
8828
- if (_optionalChain([this, 'access', _499 => _499.doc, 'access', _500 => _500.liveStrokes, 'optionalAccess', _501 => _501[l.id]])) return this.describeLayer(l);
8829
- if (_optionalChain([this, 'access', _502 => _502.doc, 'access', _503 => _503.stickers, 'optionalAccess', _504 => _504[l.id], 'optionalAccess', _505 => _505.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
8964
+ if (_optionalChain([this, 'access', _500 => _500.doc, 'access', _501 => _501.liveStrokes, 'optionalAccess', _502 => _502[l.id]])) return this.describeLayer(l);
8965
+ if (_optionalChain([this, 'access', _503 => _503.doc, 'access', _504 => _504.stickers, 'optionalAccess', _505 => _505[l.id], 'optionalAccess', _506 => _506.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
8830
8966
  if (_chunk474IQG74cjs.contentBounds.call(void 0, l.surface) || this.wet.wetLayerIds().includes(l.id)) throw new PaintEditorError(`Layer "${l.name}" already has paint, which isn't kept as strokes; convert an empty layer or add a stroke layer (add_layer {type: "strokes"}).`);
8831
8967
  this.commit("Convert to stroke layer", { ...this.doc, liveStrokes: { ..._nullishCoalesce(this.doc.liveStrokes, () => ( {})), [l.id]: [] } });
8832
8968
  return this.describeLayer(this.getLayer(l.id));
@@ -8839,7 +8975,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8839
8975
  findLiveStroke(id) {
8840
8976
  for (const [layerId, strokes] of Object.entries(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
8841
8977
  const index = strokes.findIndex((x) => x.id === id);
8842
- const layer = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _506 => _506.layer]);
8978
+ const layer = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _507 => _507.layer]);
8843
8979
  if (index >= 0 && isPixelLayer(layer)) return { layer, strokes, index };
8844
8980
  }
8845
8981
  const baked = this.doc.strokes.some((x) => x.id === id);
@@ -8859,15 +8995,15 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8859
8995
  let brush = was.brush;
8860
8996
  if (update.brushId !== void 0) {
8861
8997
  const b = this.requireBrush(update.brushId);
8862
- brush = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: was.brush.tip.size } }, b);
8998
+ brush = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: was.brush.tip.size } }, b);
8863
8999
  }
8864
9000
  if (update.brush !== void 0) {
8865
9001
  if (!update.brush || typeof update.brush !== "object") throw new PaintEditorError("brush must be an object of brush settings (as set_brush takes).");
8866
- brush = _chunkHS6QDWDFcjs.normalizePaintBrush.call(void 0, { ...update.brush, id: brush.id }, brush);
9002
+ brush = _chunkHIMGBZAMcjs.normalizePaintBrush.call(void 0, { ...update.brush, id: brush.id }, brush);
8867
9003
  }
8868
9004
  const why = liveStrokeRefusal(brush);
8869
9005
  if (why) throw new PaintEditorError(why);
8870
- const next = { ...was, brush: _chunkHS6QDWDFcjs.brushToJSON.call(void 0, brush) };
9006
+ const next = { ...was, brush: _chunkHIMGBZAMcjs.brushToJSON.call(void 0, brush) };
8871
9007
  if (update.seed !== void 0) {
8872
9008
  if (!Number.isInteger(update.seed) || update.seed < 0) throw new PaintEditorError(`seed ${update.seed} must be a whole number of 0 or more.`);
8873
9009
  next.seed = update.seed;
@@ -8934,9 +9070,9 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
8934
9070
  const layers = /* @__PURE__ */ new Map();
8935
9071
  for (const f of found) layers.set(f.layer.id, f.layer);
8936
9072
  for (const [layerId, layer] of layers) {
8937
- const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _507 => _507.liveStrokes, 'optionalAccess', _508 => _508[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
9073
+ const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _508 => _508.liveStrokes, 'optionalAccess', _509 => _509[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
8938
9074
  for (const x of gone) bounds = unionRect(bounds, this.strokeArea(x));
8939
- doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _509 => _509.liveStrokes, 'optionalAccess', _510 => _510[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
9075
+ doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _510 => _510.liveStrokes, 'optionalAccess', _511 => _511[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
8940
9076
  }
8941
9077
  this.commit(ids.length === 1 ? "Remove stroke" : "Remove strokes", doc);
8942
9078
  return { removed: [...ids], bounds };
@@ -9004,7 +9140,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
9004
9140
  }
9005
9141
  withLiveStrokes(doc, layer, list, dirty) {
9006
9142
  if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it (update_layer locks) first.`);
9007
- const current = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _511 => _511.layer]);
9143
+ const current = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _512 => _512.layer]);
9008
9144
  const surface = this.drawLiveStrokes(_nullishCoalesce(current, () => ( layer)), list, dirty);
9009
9145
  const next = { ...doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, doc.layers, layer.id, (l) => ({ ...l, surface, offset: { x: 0, y: 0 } })), liveStrokes: { ..._nullishCoalesce(doc.liveStrokes, () => ( {})), [layer.id]: [...list] } };
9010
9146
  return this.withPaintEvent(next, { kind: "live-strokes", layerId: layer.id, data: { strokes: list.map((x) => JSON.parse(JSON.stringify(x))) } });
@@ -9082,7 +9218,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
9082
9218
  if (!this.animatedLayers.size) return this.doc.layers;
9083
9219
  let layers = this.doc.layers;
9084
9220
  for (const [id, a] of this.animatedLayers) {
9085
- const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, id), 'optionalAccess', _512 => _512.layer]);
9221
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, id), 'optionalAccess', _513 => _513.layer]);
9086
9222
  if (isPixelLayer(l) && l.surface === a.base) layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, layers, id, () => ({ ...l, surface: a.surface }));
9087
9223
  }
9088
9224
  return layers;
@@ -9092,7 +9228,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
9092
9228
  const layers = [];
9093
9229
  const sources = /* @__PURE__ */ new Map();
9094
9230
  for (const [id, strokes] of Object.entries(_nullishCoalesce(doc.liveStrokes, () => ( {})))) {
9095
- const layer = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _513 => _513.layer]);
9231
+ const layer = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _514 => _514.layer]);
9096
9232
  const live = strokes.filter(isLiveEffect);
9097
9233
  if (!isPixelLayer(layer) || !live.length) continue;
9098
9234
  layers.push({ layer, strokes });
@@ -9217,13 +9353,13 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
9217
9353
  return this.withEffectTime(time, () => this.compositePixels(options));
9218
9354
  }
9219
9355
  // --- Stencils --------------------------------------------------------------------
9220
- __init174() {this.stencilCache = null}
9221
- __init175() {this.nextStencilId = 1}
9356
+ __init178() {this.stencilCache = null}
9357
+ __init179() {this.nextStencilId = 1}
9222
9358
  /** The mask stencils' coverage over the canvas (cached), or `null` when none masks. */
9223
9359
  stencilSelection(stencils = this.guides.stencils) {
9224
9360
  const { width, height } = this.doc.canvas;
9225
9361
  const size = `${width}x${height}`;
9226
- if (_optionalChain([this, 'access', _514 => _514.stencilCache, 'optionalAccess', _515 => _515.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
9362
+ if (_optionalChain([this, 'access', _515 => _515.stencilCache, 'optionalAccess', _516 => _516.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
9227
9363
  const mask = stencilMask(stencils, width, height);
9228
9364
  this.stencilCache = { key: stencils, size, mask };
9229
9365
  return mask;
@@ -9285,7 +9421,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
9285
9421
  makeSwatch(color, name) {
9286
9422
  const p = typeof color === "string" ? { type: "color", color: parseColor(color) } : this.readStrokePaint(color);
9287
9423
  const out = { color: _chunkFQPUF2W2cjs.paintSourceColor.call(void 0, p, { paint: this.color, secondary: this.secondaryColor }) };
9288
- if (_optionalChain([name, 'optionalAccess', _516 => _516.trim, 'call', _517 => _517()])) out.name = name.trim();
9424
+ if (_optionalChain([name, 'optionalAccess', _517 => _517.trim, 'call', _518 => _518()])) out.name = name.trim();
9289
9425
  if (p.type === "gradient") out.paint = p;
9290
9426
  return out;
9291
9427
  }
@@ -9337,7 +9473,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
9337
9473
  * mix becomes the paint colour. Returns the mixed colour and the pile's bounds.
9338
9474
  */
9339
9475
  mixOnPad(paints2, options = {}) {
9340
- const parsed = (_nullishCoalesce(paints2, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _518 => _518.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _519 => _519.parts]) }));
9476
+ const parsed = (_nullishCoalesce(paints2, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _519 => _519.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _520 => _520.parts]) }));
9341
9477
  let r;
9342
9478
  try {
9343
9479
  r = this.pad.mix(parsed, options);
@@ -9426,7 +9562,7 @@ var PaintEditorController = (_class19 = class _PaintEditorController {
9426
9562
  }
9427
9563
  /** A layer's tile surface (live while stroking), for thumbnails. */
9428
9564
  layerSurface(id) {
9429
- const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _520 => _520.layer]);
9565
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _521 => _521.layer]);
9430
9566
  return isPixelLayer(l) ? l.surface : null;
9431
9567
  }
9432
9568
  }, _class19.__initStatic(), _class19);
@@ -9448,7 +9584,7 @@ function insertAfter(layers, id, node) {
9448
9584
  return layers.map((l) => l.type === "group" ? { ...l, children: insertAfter(l.children, id, node) } : l);
9449
9585
  }
9450
9586
  function isLiveEffect(s) {
9451
- return _optionalChain([s, 'access', _521 => _521.paint, 'optionalAccess', _522 => _522.type]) === "effect" && s.paint.live === true;
9587
+ return _optionalChain([s, 'access', _522 => _522.paint, 'optionalAccess', _523 => _523.type]) === "effect" && s.paint.live === true;
9452
9588
  }
9453
9589
  function framePaint(p, t) {
9454
9590
  return { ...p, time: p.time + t };
@@ -9473,7 +9609,7 @@ function clipRect(r, width, height) {
9473
9609
  return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
9474
9610
  }
9475
9611
  function withLiveStroke(doc, stroke) {
9476
- const list = _optionalChain([doc, 'access', _523 => _523.liveStrokes, 'optionalAccess', _524 => _524[stroke.layerId]]);
9612
+ const list = _optionalChain([doc, 'access', _524 => _524.liveStrokes, 'optionalAccess', _525 => _525[stroke.layerId]]);
9477
9613
  return list ? { ...doc, liveStrokes: { ...doc.liveStrokes, [stroke.layerId]: [...list, stroke] } } : doc;
9478
9614
  }
9479
9615
  function shiftDocument(doc, dx, dy) {
@@ -9500,9 +9636,9 @@ function shiftDocument(doc, dx, dy) {
9500
9636
  if (doc.liveStrokes) out.liveStrokes = Object.fromEntries(Object.entries(doc.liveStrokes).map(([id, list]) => [id, list.map(moveStroke)]));
9501
9637
  if (doc.paintEvents) {
9502
9638
  out.paintEvents = doc.paintEvents.map((e) => {
9503
- const list = e.kind === "stickers" ? _optionalChain([e, 'access', _525 => _525.data, 'optionalAccess', _526 => _526.stickers]) : void 0;
9639
+ const list = e.kind === "stickers" ? _optionalChain([e, 'access', _526 => _526.data, 'optionalAccess', _527 => _527.stickers]) : void 0;
9504
9640
  if (list) return { ...e, data: { ...e.data, stickers: moveStickers(list) } };
9505
- const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _527 => _527.data, 'optionalAccess', _528 => _528.strokes]) : void 0;
9641
+ const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _528 => _528.data, 'optionalAccess', _529 => _529.strokes]) : void 0;
9506
9642
  return strokes ? { ...e, data: { ...e.data, strokes: strokes.map(moveStroke) } } : e;
9507
9643
  });
9508
9644
  }
@@ -9566,6 +9702,13 @@ function resampleInto(src, rect, width, height) {
9566
9702
  }
9567
9703
  return { width, height, data: out };
9568
9704
  }
9705
+ function clipToCanvas(rect, canvas) {
9706
+ const x0 = Math.max(0, rect.x);
9707
+ const y0 = Math.max(0, rect.y);
9708
+ const x1 = Math.min(canvas.width, rect.x + rect.width);
9709
+ const y1 = Math.min(canvas.height, rect.y + rect.height);
9710
+ return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
9711
+ }
9569
9712
 
9570
9713
  // src/paint-editor/presence.ts
9571
9714
  var PaintPresence = class extends _chunkK7ENM55Pcjs.PresenceStore {
@@ -9584,8 +9727,8 @@ function strokeSchedule(points) {
9584
9727
  return total > 0 ? acc.map((d) => d / total) : points.map(() => 1);
9585
9728
  }
9586
9729
  function strokeDuration(points, max = 1800) {
9587
- const t0 = _optionalChain([points, 'access', _529 => _529[0], 'optionalAccess', _530 => _530.t]);
9588
- const t1 = _optionalChain([points, 'access', _531 => _531[points.length - 1], 'optionalAccess', _532 => _532.t]);
9730
+ const t0 = _optionalChain([points, 'access', _530 => _530[0], 'optionalAccess', _531 => _531.t]);
9731
+ const t1 = _optionalChain([points, 'access', _532 => _532[points.length - 1], 'optionalAccess', _533 => _533.t]);
9589
9732
  let ms;
9590
9733
  if (points.every((p) => Number.isFinite(p.t)) && t1 > t0) ms = t1 - t0;
9591
9734
  else {
@@ -9639,7 +9782,7 @@ var PaintDirector = class {
9639
9782
  }
9640
9783
  where(id) {
9641
9784
  const a = this.presence.get(id);
9642
- return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _533 => _533.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _534 => _534.y]), () => ( 0)) };
9785
+ return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _534 => _534.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _535 => _535.y]), () => ( 0)) };
9643
9786
  }
9644
9787
  /** Glides to `to`; an actor that just appeared starts there instead of the corner. */
9645
9788
  async glide(id, to, ms = 380) {
@@ -9686,8 +9829,8 @@ var PaintDirector = class {
9686
9829
  }
9687
9830
  case "replay": {
9688
9831
  await this.say(id, command.note, 500);
9689
- const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _535 => _535.replay, 'access', _536 => _536.strokeIds, 'optionalAccess', _537 => _537.includes, 'call', _538 => _538(s.id)]));
9690
- const first = _optionalChain([source, 'access', _539 => _539[0], 'optionalAccess', _540 => _540.points, 'access', _541 => _541[0]]);
9832
+ const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _536 => _536.replay, 'access', _537 => _537.strokeIds, 'optionalAccess', _538 => _538.includes, 'call', _539 => _539(s.id)]));
9833
+ const first = _optionalChain([source, 'access', _540 => _540[0], 'optionalAccess', _541 => _541.points, 'access', _542 => _542[0]]);
9691
9834
  if (first) await this.glide(id, first);
9692
9835
  const result = c.replayStrokes(command.replay);
9693
9836
  if (result.bounds) await this.glide(id, centre(result.bounds), 520);
@@ -10786,8 +10929,8 @@ var POINTS = {
10786
10929
  }
10787
10930
  };
10788
10931
  function loadResult(load) {
10789
- const hex = (c) => c ? "#" + c.map((v) => Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, "0")).join("") : null;
10790
- return { reservoir: hex(load.reservoir), amount: Math.round(load.amount * 1e3) / 1e3, pickup: hex(load.pickup) };
10932
+ const hex2 = (c) => c ? "#" + c.map((v) => Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, "0")).join("") : null;
10933
+ return { reservoir: hex2(load.reservoir), amount: Math.round(load.amount * 1e3) / 1e3, pickup: hex2(load.pickup) };
10791
10934
  }
10792
10935
  function createPaintEditorToolProvider(controller, options = {}) {
10793
10936
  const c = typeof controller === "function" ? lazyController(controller) : controller;
@@ -11121,10 +11264,10 @@ function createPaintEditorToolProvider(controller, options = {}) {
11121
11264
  name: "set_brush",
11122
11265
  title: "Set the brush",
11123
11266
  description: "Chooses the active brush (id, from list_brush_presets) and / or changes it with facets laid over it (objects merge, lists and values replace, marks of another kind replace the marks; the brush library's create_brush fields); unset removes whole facets first (unset colour drops a brush's own gradient). Strokes without a brush use it. Editor state, not an undo step: the changes stay on the active brush until the library's create_brush or update_brush stores a brush. Returns the active brush as facets, the engine it paints with, and problems (values clamped or dropped).",
11124
- inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brush_presets to start from (default the active brush)." }, name: { type: "string", minLength: 1, maxLength: 80, description: "Display name." }, ..._chunk34KLWUH4cjs.BRUSH_PATCH_PROPERTIES, unset: _chunk34KLWUH4cjs.BRUSH_UNSET_PROPERTY }, additionalProperties: false },
11267
+ inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brush_presets to start from (default the active brush)." }, name: { type: "string", minLength: 1, maxLength: 80, description: "Display name." }, ..._chunkPGPFWC35cjs.BRUSH_PATCH_PROPERTIES, unset: _chunkPGPFWC35cjs.BRUSH_UNSET_PROPERTY }, additionalProperties: false },
11125
11268
  annotations: { title: "Set the brush", ...SET4 },
11126
11269
  handler: async ({ id, unset, ...patch }) => {
11127
- const stamps = _optionalChain([patch, 'access', _542 => _542.tip, 'optionalAccess', _543 => _543.stamps]);
11270
+ const stamps = _optionalChain([patch, 'access', _543 => _543.tip, 'optionalAccess', _544 => _544.stamps]);
11128
11271
  if (stamps) await c.prepareStickers(stamps);
11129
11272
  const r = c.setBrushFacets(patch, id, unset);
11130
11273
  return { brush: r.spec, engine: r.brush.engine, problems: r.problems };
@@ -11211,7 +11354,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
11211
11354
  points: POINTS,
11212
11355
  layerId: LAYER_ID4,
11213
11356
  brushId: { type: "string", description: "Brush id from list_brush_presets (default the active brush)." },
11214
- brush: { type: "object", description: "Facets to change for this stroke only, laid over brushId or the active brush (as set_brush takes them).", properties: _chunk34KLWUH4cjs.BRUSH_PATCH_PROPERTIES, additionalProperties: false },
11357
+ brush: { type: "object", description: "Facets to change for this stroke only, laid over brushId or the active brush (as set_brush takes them).", properties: _chunkPGPFWC35cjs.BRUSH_PATCH_PROPERTIES, additionalProperties: false },
11215
11358
  color: { ...COLOR3, description: "Paint colour #rrggbb (default the paint colour)." },
11216
11359
  paint: { ..._chunkFQPUF2W2cjs.PAINT_SOURCE_JSON_SCHEMA, description: "What this stroke paints with instead of the editor's paint: a colour, or gradient paint that changes colour as the stroke goes (by distance, pressure, tilt, speed, direction, time, across the tip or at random). Wins over the brush's own gradient." },
11217
11360
  seed: { type: "integer", minimum: 0, description: "Jitter seed (default a new one); the same seed and points give the same marks." },
@@ -11226,7 +11369,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
11226
11369
  await c.wetIdle();
11227
11370
  const base = a.brushId ? c.getBrush(a.brushId) : c.getState().brush;
11228
11371
  const brush = a.brush ? c.brushChanges(a.brush, a.brushId) : void 0;
11229
- if ((_nullishCoalesce(_optionalChain([brush, 'optionalAccess', _544 => _544.engine]), () => ( _optionalChain([base, 'optionalAccess', _545 => _545.engine])))) === "sticker") await c.prepareStickers(_nullishCoalesce(_nullishCoalesce(_optionalChain([brush, 'optionalAccess', _546 => _546.sticker, 'optionalAccess', _547 => _547.stamps]), () => ( _optionalChain([base, 'optionalAccess', _548 => _548.sticker, 'access', _549 => _549.stamps]))), () => ( [])));
11372
+ if ((_nullishCoalesce(_optionalChain([brush, 'optionalAccess', _545 => _545.engine]), () => ( _optionalChain([base, 'optionalAccess', _546 => _546.engine])))) === "sticker") await c.prepareStickers(_nullishCoalesce(_nullishCoalesce(_optionalChain([brush, 'optionalAccess', _547 => _547.sticker, 'optionalAccess', _548 => _548.stamps]), () => ( _optionalChain([base, 'optionalAccess', _549 => _549.sticker, 'access', _550 => _550.stamps]))), () => ( [])));
11230
11373
  const stroke = { points: a.points, layerId: a.layerId, brushId: a.brushId, brush, color: a.color, paint: a.paint, seed: a.seed, snapToPerspective: a.snapToPerspective };
11231
11374
  const r = await act({ kind: "stroke", stroke }, () => c.paintStroke(stroke));
11232
11375
  return r.mixerLoad ? { ...r, mixerLoad: loadResult(r.mixerLoad) } : r;
@@ -11258,7 +11401,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
11258
11401
  if (ids) {
11259
11402
  for (const id of ids) if (!all.some((s) => s.id === id)) throw new Error(`Unknown stroke "${id}". Call list_strokes without ids for the ids.`);
11260
11403
  }
11261
- return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _550 => _550.document, 'access', _551 => _551.liveStrokes, 'optionalAccess', _552 => _552[s.layerId], 'optionalAccess', _553 => _553.includes, 'call', _554 => _554(s)]) === true)) };
11404
+ return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _551 => _551.document, 'access', _552 => _552.liveStrokes, 'optionalAccess', _553 => _553[s.layerId], 'optionalAccess', _554 => _554.includes, 'call', _555 => _555(s)]) === true)) };
11262
11405
  }
11263
11406
  });
11264
11407
  add({
@@ -11291,7 +11434,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
11291
11434
  properties: {
11292
11435
  id: { type: "string", description: "Stroke id from list_strokes {live: true}." },
11293
11436
  brushId: { type: "string", description: "Brush id from list_brush_presets; the stroke keeps its size." },
11294
- brush: { type: "object", properties: _chunk34KLWUH4cjs.BRUSH_PATCH_PROPERTIES, additionalProperties: false, description: "Facets to change on top of brushId or the stroke\u2019s brush (as set_brush takes them); missing fields keep their values." },
11437
+ brush: { type: "object", properties: _chunkPGPFWC35cjs.BRUSH_PATCH_PROPERTIES, additionalProperties: false, description: "Facets to change on top of brushId or the stroke\u2019s brush (as set_brush takes them); missing fields keep their values." },
11295
11438
  color: { type: "string", pattern: "^#[0-9a-fA-F]{6}$", description: "New colour #rrggbb (replaces gradient paint)." },
11296
11439
  paint: { anyOf: [_chunkFQPUF2W2cjs.PAINT_SOURCE_JSON_SCHEMA, { type: "null", description: "Back to the stroke\u2019s plain colour." }], description: "A colour or gradient paint for the stroke; null drops its gradient." },
11297
11440
  seed: { type: "integer", minimum: 0, description: "Another jitter seed: particles, scatter and texture fall differently." }
@@ -11542,7 +11685,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
11542
11685
  tools.push(..._chunkKBYB7OWBcjs.createPigmentTools.call(void 0, ));
11543
11686
  tools.push(..._chunkSABJMH6Mcjs.createStickerTools.call(void 0, { provider: () => c.stickersProvider }));
11544
11687
  tools.push(
11545
- ..._chunkJFHBXNR2cjs.createLayerEffectTools.call(void 0,
11688
+ ..._chunkB7V34GIHcjs.createLayerEffectTools.call(void 0,
11546
11689
  {
11547
11690
  requireLayer: (id) => void c.getLayerEffects(id),
11548
11691
  getLayerEffects: (id) => c.getLayerEffects(id),
@@ -11567,16 +11710,16 @@ function createPaintEditorToolProvider(controller, options = {}) {
11567
11710
  }
11568
11711
  function hostTool({ coordinates, ...tool }, { origin, onChange }) {
11569
11712
  if (!origin && !onChange) return tool;
11570
- const write = !_optionalChain([tool, 'access', _555 => _555.annotations, 'optionalAccess', _556 => _556.readOnlyHint]);
11713
+ const write = !_optionalChain([tool, 'access', _556 => _556.annotations, 'optionalAccess', _557 => _557.readOnlyHint]);
11571
11714
  const done = (result) => {
11572
- if (write) _optionalChain([onChange, 'optionalCall', _557 => _557({ tool: tool.name })]);
11573
- return origin && _optionalChain([coordinates, 'optionalAccess', _558 => _558.out]) ? fromDocument(result, coordinates.out, origin) : result;
11715
+ if (write) _optionalChain([onChange, 'optionalCall', _558 => _558({ tool: tool.name })]);
11716
+ return origin && _optionalChain([coordinates, 'optionalAccess', _559 => _559.out]) ? fromDocument(result, coordinates.out, origin) : result;
11574
11717
  };
11575
11718
  return {
11576
11719
  ...tool,
11577
11720
  ...origin ? { description: hostedText(_nullishCoalesce(tool.description, () => ( ""))), inputSchema: hostedSchema(tool.inputSchema) } : {},
11578
11721
  handler: (args, context) => {
11579
- const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _559 => _559.in]) ? toDocument(args, coordinates.in, origin) : args, context);
11722
+ const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _560 => _560.in]) ? toDocument(args, coordinates.in, origin) : args, context);
11580
11723
  return r instanceof Promise ? r.then(done) : done(r);
11581
11724
  }
11582
11725
  };
@@ -11593,7 +11736,7 @@ function strokeSummary(s, withPoints, live) {
11593
11736
  color: s.color,
11594
11737
  points: withPoints ? s.points : s.points.length,
11595
11738
  seed: s.seed,
11596
- copies: _nullishCoalesce(_optionalChain([s, 'access', _560 => _560.copies, 'optionalAccess', _561 => _561.length]), () => ( 0)),
11739
+ copies: _nullishCoalesce(_optionalChain([s, 'access', _561 => _561.copies, 'optionalAccess', _562 => _562.length]), () => ( 0)),
11597
11740
  live,
11598
11741
  bounds: { x: Math.floor(Math.min(...xs) - pad), y: Math.floor(Math.min(...ys) - pad), width: Math.ceil(Math.max(...xs) - Math.min(...xs) + 2 * pad), height: Math.ceil(Math.max(...ys) - Math.min(...ys) + 2 * pad) }
11599
11742
  };
@@ -11601,11 +11744,11 @@ function strokeSummary(s, withPoints, live) {
11601
11744
 
11602
11745
  // src/paint-editor/brush-library-tools.ts
11603
11746
  function createPaintBrushLibraryToolProvider(controller, options = {}) {
11604
- return _chunk34KLWUH4cjs.createBrushLibraryToolProvider.call(void 0, controller.brushLibrary, {
11605
- profile: _chunk34KLWUH4cjs.PAINT_PROFILE,
11747
+ return _chunkPGPFWC35cjs.createBrushLibraryToolProvider.call(void 0, controller.brushLibrary, {
11748
+ profile: _chunkHIMGBZAMcjs.PAINT_PROFILE,
11606
11749
  ...options,
11607
11750
  renderPreview: (brush, { width, height, color }) => {
11608
- const t = renderBrushThumbnail(_chunk34KLWUH4cjs.resolveBrush.call(void 0, brush), { paper: controller.getState().document.paper, width, height, color: color.toLowerCase() });
11751
+ const t = renderBrushThumbnail(_chunkHIMGBZAMcjs.resolveBrush.call(void 0, brush), { paper: controller.getState().document.paper, width, height, color: color.toLowerCase() });
11609
11752
  return { data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, _chunkW5M3J7PVcjs.encodePng.call(void 0, t.width, t.height, t.data)), mimeType: "image/png" };
11610
11753
  }
11611
11754
  });
@@ -11621,20 +11764,20 @@ var PAINT_TOOLS = [
11621
11764
  { id: "rotate", label: "Rotate view", key: "r" }
11622
11765
  ];
11623
11766
  var PaintGesture = (_class20 = class {
11624
- constructor(controller, box) {;_class20.prototype.__init176.call(this);_class20.prototype.__init177.call(this);_class20.prototype.__init178.call(this);_class20.prototype.__init179.call(this);_class20.prototype.__init180.call(this);_class20.prototype.__init181.call(this);
11767
+ constructor(controller, box) {;_class20.prototype.__init180.call(this);_class20.prototype.__init181.call(this);_class20.prototype.__init182.call(this);_class20.prototype.__init183.call(this);_class20.prototype.__init184.call(this);_class20.prototype.__init185.call(this);
11625
11768
  this.controller = controller;
11626
11769
  this.box = box;
11627
11770
  }
11628
11771
 
11629
11772
 
11630
- __init176() {this.tool = "brush"}
11773
+ __init180() {this.tool = "brush"}
11631
11774
  /** The last refusal (a hidden or locked layer), for the editor to show. */
11632
- __init177() {this.error = null}
11775
+ __init181() {this.error = null}
11633
11776
  /** The predicted tail of the current stroke in document pixels (draw it as a thin preview). */
11634
- __init178() {this.predicted = []}
11635
- __init179() {this.mode = null}
11636
- __init180() {this.penAt = null}
11637
- __init181() {this.penDown = false}
11777
+ __init182() {this.predicted = []}
11778
+ __init183() {this.mode = null}
11779
+ __init184() {this.penAt = null}
11780
+ __init185() {this.penDown = false}
11638
11781
  doc(e) {
11639
11782
  const b = this.box();
11640
11783
  const s = this.controller.getState();
@@ -11690,13 +11833,13 @@ var PaintGesture = (_class20 = class {
11690
11833
  const p = this.doc(e);
11691
11834
  const s = this.controller.getState();
11692
11835
  const layerId = s.document.activeLayerId;
11693
- if (!layerId || !_optionalChain([s, 'access', _562 => _562.document, 'access', _563 => _563.liveStrokes, 'optionalAccess', _564 => _564[layerId]])) {
11836
+ if (!layerId || !_optionalChain([s, 'access', _563 => _563.document, 'access', _564 => _564.liveStrokes, 'optionalAccess', _565 => _565[layerId]])) {
11694
11837
  this.error = "Pick a stroke layer in the Layers panel (or add one) to select its strokes.";
11695
11838
  return false;
11696
11839
  }
11697
11840
  try {
11698
11841
  const hit = this.controller.liveStrokeAt(layerId, p.x, p.y);
11699
- this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _565 => _565.id]), () => ( null)));
11842
+ this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _566 => _566.id]), () => ( null)));
11700
11843
  if (!hit) return false;
11701
11844
  this.mode = { kind: "move-stroke", pointerId: e.pointerId, id: hit.id, from: p, to: p };
11702
11845
  return true;
@@ -11708,7 +11851,7 @@ var PaintGesture = (_class20 = class {
11708
11851
  /** While a stroke is dragged: how far it has moved (document pixels), to draw its outline there. */
11709
11852
  get strokeDrag() {
11710
11853
  const m = this.mode;
11711
- return _optionalChain([m, 'optionalAccess', _566 => _566.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
11854
+ return _optionalChain([m, 'optionalAccess', _567 => _567.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
11712
11855
  }
11713
11856
  /**
11714
11857
  * The Stickers tool: pressing a sticker picks it and dragging moves it (one undo step at the
@@ -11782,7 +11925,7 @@ var PaintGesture = (_class20 = class {
11782
11925
  if (!m || m.pointerId !== e.pointerId) return;
11783
11926
  this.mode = null;
11784
11927
  this.predicted = [];
11785
- if (m.kind === "stroke") _optionalChain([this, 'access', _567 => _567.controller, 'access', _568 => _568.activeStroke, 'optionalAccess', _569 => _569.end, 'call', _570 => _570()]);
11928
+ if (m.kind === "stroke") _optionalChain([this, 'access', _568 => _568.controller, 'access', _569 => _569.activeStroke, 'optionalAccess', _570 => _570.end, 'call', _571 => _571()]);
11786
11929
  if (m.kind === "move-stroke") {
11787
11930
  const dx = Math.round((this.doc(e).x - m.from.x) * 100) / 100;
11788
11931
  const dy = Math.round((this.doc(e).y - m.from.y) * 100) / 100;
@@ -11806,8 +11949,8 @@ var PaintGesture = (_class20 = class {
11806
11949
  cancel() {
11807
11950
  this.penDown = false;
11808
11951
  this.predicted = [];
11809
- if (_optionalChain([this, 'access', _571 => _571.mode, 'optionalAccess', _572 => _572.kind]) === "stroke") _optionalChain([this, 'access', _573 => _573.controller, 'access', _574 => _574.activeStroke, 'optionalAccess', _575 => _575.cancel, 'call', _576 => _576()]);
11810
- if (_optionalChain([this, 'access', _577 => _577.mode, 'optionalAccess', _578 => _578.kind]) === "sticker") this.controller.cancelStickerPreview();
11952
+ if (_optionalChain([this, 'access', _572 => _572.mode, 'optionalAccess', _573 => _573.kind]) === "stroke") _optionalChain([this, 'access', _574 => _574.controller, 'access', _575 => _575.activeStroke, 'optionalAccess', _576 => _576.cancel, 'call', _577 => _577()]);
11953
+ if (_optionalChain([this, 'access', _578 => _578.mode, 'optionalAccess', _579 => _579.kind]) === "sticker") this.controller.cancelStickerPreview();
11811
11954
  this.mode = null;
11812
11955
  }
11813
11956
  get active() {
@@ -11869,13 +12012,13 @@ function handlePaintShortcut(controller, gesture, e) {
11869
12012
  return false;
11870
12013
  }
11871
12014
  var PaintCanvasPresenter = (_class21 = class {
11872
- constructor(controller) {;_class21.prototype.__init182.call(this);_class21.prototype.__init183.call(this);_class21.prototype.__init184.call(this);
12015
+ constructor(controller) {;_class21.prototype.__init186.call(this);_class21.prototype.__init187.call(this);_class21.prototype.__init188.call(this);
11873
12016
  this.controller = controller;
11874
12017
  }
11875
12018
 
11876
- __init182() {this.uploaded = /* @__PURE__ */ new Map()}
11877
- __init183() {this.scratch = null}
11878
- __init184() {this.size = ""}
12019
+ __init186() {this.uploaded = /* @__PURE__ */ new Map()}
12020
+ __init187() {this.scratch = null}
12021
+ __init188() {this.size = ""}
11879
12022
  /** Draws what changed into `ctx` (a canvas the size of the document); returns the tiles drawn. */
11880
12023
  render(ctx) {
11881
12024
  const { width, height } = this.controller.document.canvas;
@@ -11907,7 +12050,7 @@ function guideOverlay(controller, drag) {
11907
12050
  const size = s.document.canvas;
11908
12051
  const out = [];
11909
12052
  const layerId = s.document.activeLayerId;
11910
- const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _579 => _579.document, 'access', _580 => _580.liveStrokes, 'optionalAccess', _581 => _581[layerId], 'optionalAccess', _582 => _582.some, 'call', _583 => _583((x) => x.id === s.selectedStroke)]) : false;
12053
+ const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _580 => _580.document, 'access', _581 => _581.liveStrokes, 'optionalAccess', _582 => _582[layerId], 'optionalAccess', _583 => _583.some, 'call', _584 => _584((x) => x.id === s.selectedStroke)]) : false;
11911
12054
  const area = strokePicked ? controller.liveStrokeArea(s.selectedStroke) : null;
11912
12055
  if (area) {
11913
12056
  const dx = drag && drag.id === s.selectedStroke ? drag.dx : 0;
@@ -11920,7 +12063,7 @@ function guideOverlay(controller, drag) {
11920
12063
  ];
11921
12064
  for (let i = 0; i < 4; i++) out.push({ from: box[i], to: box[(i + 1) % 4], kind: "stroke" });
11922
12065
  }
11923
- const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _584 => _584.document, 'access', _585 => _585.stickers, 'optionalAccess', _586 => _586[layerId], 'optionalAccess', _587 => _587.find, 'call', _588 => _588((x) => x.id === s.selectedSticker)]) : void 0;
12066
+ const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _585 => _585.document, 'access', _586 => _586.stickers, 'optionalAccess', _587 => _587[layerId], 'optionalAccess', _588 => _588.find, 'call', _589 => _589((x) => x.id === s.selectedSticker)]) : void 0;
11924
12067
  if (picked) {
11925
12068
  const r = picked.size / 2 + 2;
11926
12069
  const a = picked.rotation * Math.PI / 180;
@@ -11950,7 +12093,7 @@ var PAPER_SLIDERS = [
11950
12093
  ];
11951
12094
  function readPath(obj, path) {
11952
12095
  let v = obj;
11953
- for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _589 => _589[k]]);
12096
+ for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _590 => _590[k]]);
11954
12097
  return typeof v === "number" ? v : 0;
11955
12098
  }
11956
12099
  function patchPath(obj, path, value) {
@@ -12066,7 +12209,7 @@ function startWetClock(controller, frame, cancel) {
12066
12209
  id = raf(loop);
12067
12210
  return () => {
12068
12211
  stopped = true;
12069
- _optionalChain([caf, 'optionalCall', _590 => _590(id)]);
12212
+ _optionalChain([caf, 'optionalCall', _591 => _591(id)]);
12070
12213
  };
12071
12214
  }
12072
12215
  function drawWaterOverlay(controller, ctx) {
@@ -12097,7 +12240,7 @@ var DOT_ROTATION_LABELS = { follow: "Follow motion", random: "Random", fixed: "T
12097
12240
  var STAMP_LABELS = { dot: "Dot", star: "Star", heart: "Heart", leaf: "Leaf", flower: "Flower", confetti: "Confetti", splat: "Splat", sparkle: "Sparkle", ring: "Ring" };
12098
12241
  function toggleStickerRef(refs, ref2) {
12099
12242
  if (refs.includes(ref2)) return refs.length > 1 ? refs.filter((r) => r !== ref2) : [...refs];
12100
- return refs.length < _chunkHS6QDWDFcjs.MAX_STICKER_STAMPS ? [...refs, ref2] : [...refs];
12243
+ return refs.length < _chunkHIMGBZAMcjs.MAX_STICKER_STAMPS ? [...refs, ref2] : [...refs];
12101
12244
  }
12102
12245
  function stickerRefLabel(ref2) {
12103
12246
  const stamp = ref2.startsWith("editor:") ? ref2.slice(7) : null;
@@ -12110,7 +12253,7 @@ function toggleStamp(stamps, stamp) {
12110
12253
  }
12111
12254
  function toggleDotTexture(textures, stamp) {
12112
12255
  if (textures.includes(stamp)) return textures.filter((s) => s !== stamp);
12113
- return textures.length < _chunkHS6QDWDFcjs.MAX_DOT_TEXTURES ? [...textures, stamp] : [...textures];
12256
+ return textures.length < _chunkHIMGBZAMcjs.MAX_DOT_TEXTURES ? [...textures, stamp] : [...textures];
12114
12257
  }
12115
12258
  var STROKE_SLIDERS = [
12116
12259
  { path: "tip.size", label: "Size", min: 1, max: 400, step: 1 },
@@ -12406,6 +12549,396 @@ function createPaintEditorDocument(controller, options = {}) {
12406
12549
  });
12407
12550
  }
12408
12551
 
12552
+ // src/paint-editor/collaboration.ts
12553
+ var LAYER_FIELDS = ["name", "visible", "opacity", "blend"];
12554
+ function createPaintChangeFeed(controller, options = {}) {
12555
+ const now = _nullishCoalesce(options.now, () => ( (() => Date.now())));
12556
+ const listeners = /* @__PURE__ */ new Set();
12557
+ let seq = 0;
12558
+ let pending;
12559
+ const take = () => {
12560
+ const state = controller.getState();
12561
+ const doc = state.document;
12562
+ const layers = /* @__PURE__ */ new Map();
12563
+ for (const l of controller.listLayers()) layers.set(l.id, { name: l.name, visible: l.visible, opacity: l.opacity, blend: l.blend });
12564
+ return { doc, strokes: new Map(doc.strokes.map((s) => [s.id, s])), events: _nullishCoalesce(_optionalChain([doc, 'access', _592 => _592.paintEvents, 'optionalAccess', _593 => _593.length]), () => ( 0)), layers, stroking: state.stroking };
12565
+ };
12566
+ let last = take();
12567
+ const check = () => {
12568
+ const state = controller.getState();
12569
+ if (state.document === last.doc && state.stroking === last.stroking) return null;
12570
+ const next = take();
12571
+ const addedStrokes = [...next.strokes.values()].filter((s) => !last.strokes.has(s.id));
12572
+ const removedStrokes = [...last.strokes.values()].filter((s) => !next.strokes.has(s.id));
12573
+ const allEvents = _nullishCoalesce(state.document.paintEvents, () => ( []));
12574
+ const events = next.events > last.events ? allEvents.slice(last.events) : [];
12575
+ const addedLayers = [];
12576
+ const changedLayers = [];
12577
+ for (const [id, l] of next.layers) {
12578
+ const before = last.layers.get(id);
12579
+ if (!before) addedLayers.push({ id, name: String(l.name) });
12580
+ else {
12581
+ const fields = LAYER_FIELDS.filter((f) => before[f] !== l[f]);
12582
+ if (fields.length) changedLayers.push({ id, name: String(l.name), fields });
12583
+ }
12584
+ }
12585
+ const removedLayers = [...last.layers].filter(([id]) => !next.layers.has(id)).map(([id, l]) => ({ id, name: String(l.name) }));
12586
+ const gestureStarted = next.stroking && !last.stroking;
12587
+ const gestureEnded = !next.stroking && last.stroking;
12588
+ last = next;
12589
+ const edited = addedStrokes.length + removedStrokes.length + events.length + addedLayers.length + removedLayers.length + changedLayers.length > 0;
12590
+ if (!edited && !gestureStarted && !gestureEnded) return null;
12591
+ const commit = edited ? pending : void 0;
12592
+ if (edited) pending = void 0;
12593
+ const change = {
12594
+ seq: ++seq,
12595
+ origin: _nullishCoalesce(_optionalChain([commit, 'optionalAccess', _594 => _594.origin]), () => ( "user")),
12596
+ ...commit ? { commit } : {},
12597
+ addedStrokes,
12598
+ removedStrokes,
12599
+ events,
12600
+ addedLayers,
12601
+ removedLayers,
12602
+ changedLayers,
12603
+ inGesture: next.stroking,
12604
+ ...gestureStarted ? { gestureStarted: true } : {},
12605
+ ...gestureEnded ? { gestureEnded: true } : {},
12606
+ at: now()
12607
+ };
12608
+ listeners.forEach((l) => l(change));
12609
+ return change;
12610
+ };
12611
+ const offCommit = controller.onCommit((event) => {
12612
+ pending = event;
12613
+ });
12614
+ const offState = controller.subscribe(() => {
12615
+ check();
12616
+ });
12617
+ return {
12618
+ check,
12619
+ subscribe(listener) {
12620
+ listeners.add(listener);
12621
+ return () => {
12622
+ listeners.delete(listener);
12623
+ };
12624
+ },
12625
+ reset() {
12626
+ last = take();
12627
+ pending = void 0;
12628
+ },
12629
+ dispose() {
12630
+ offCommit();
12631
+ offState();
12632
+ listeners.clear();
12633
+ }
12634
+ };
12635
+ }
12636
+ var HEX4 = /^#[0-9a-f]{6}$/i;
12637
+ var DRY_ENGINES = /* @__PURE__ */ new Set(["dab", "particle", "bristle", "mixer"]);
12638
+ function suggestionBrushRefusal(brush) {
12639
+ if (!DRY_ENGINES.has(brush.engine)) return `The ${brush.name} brush (${brush.engine}) can't paint a suggestion: suggestions are dry paint on a layer of their own. Use a dab, particle, bristle or mixer brush.`;
12640
+ if (brush.behavior.pickup > 0) return `The ${brush.name} brush picks up paint, which a suggestion on its own layer can't; choose a brush without pickup.`;
12641
+ return null;
12642
+ }
12643
+ function createPaintProposals(options) {
12644
+ const { controller } = options;
12645
+ const now = _nullishCoalesce(options.now, () => ( (() => Date.now())));
12646
+ const maxPoints = _nullishCoalesce(options.maxPoints, () => ( 4e3));
12647
+ let seq = 0;
12648
+ const makeId = _nullishCoalesce(options.idGenerator, () => ( (() => `paint-proposal-${++seq}`)));
12649
+ let state = { proposals: [] };
12650
+ const listeners = /* @__PURE__ */ new Set();
12651
+ const set = (proposals) => {
12652
+ state = { proposals };
12653
+ listeners.forEach((l) => l(state));
12654
+ };
12655
+ const find = (id) => {
12656
+ const p = state.proposals.find((x) => x.id === id);
12657
+ if (!p) throw new PaintEditorError(`No pending paint proposal "${id}". Call list_paint_proposals for the ids.`);
12658
+ return p;
12659
+ };
12660
+ const strokeIds = () => new Set(controller.getStrokes().map((s) => s.id));
12661
+ const validate = (input) => {
12662
+ if (!_optionalChain([input, 'access', _595 => _595.title, 'optionalAccess', _596 => _596.trim, 'call', _597 => _597()])) throw new PaintEditorError("A proposal needs a title: what it adds, in a few words.");
12663
+ if (!Array.isArray(input.ops) || !input.ops.length) throw new PaintEditorError("A proposal needs at least one op (stroke, wash or echo).");
12664
+ const place = _nullishCoalesce(input.place, () => ( "top"));
12665
+ if (place === "above") {
12666
+ if (!input.layerId) throw new PaintEditorError('place "above" needs layerId: the layer to put the suggestion above (list_layers).');
12667
+ if (!controller.listLayers().some((l) => l.id === input.layerId)) throw new PaintEditorError(`Unknown layer "${input.layerId}". Call list_layers for the ids.`);
12668
+ }
12669
+ const known = strokeIds();
12670
+ let points = 0;
12671
+ input.ops.forEach((op, i) => {
12672
+ const at = `ops[${i}]`;
12673
+ if (op.kind === "stroke") {
12674
+ if (!_optionalChain([op, 'access', _598 => _598.points, 'optionalAccess', _599 => _599.length])) throw new PaintEditorError(`${at}: a stroke needs points in document pixels.`);
12675
+ points += op.points.length;
12676
+ if (op.color !== void 0 && !HEX4.test(op.color)) throw new PaintEditorError(`${at}: color "${op.color}" is not #rrggbb.`);
12677
+ const brush = op.brushId ? controller.getBrush(op.brushId) : controller.getState().brush;
12678
+ if (!brush) throw new PaintEditorError(`${at}: unknown brush "${op.brushId}". Call list_brush_presets for the ids.`);
12679
+ const refusal = suggestionBrushRefusal(brush);
12680
+ if (refusal) throw new PaintEditorError(`${at}: ${refusal}`);
12681
+ if (op.size !== void 0 && !(op.size > 0)) throw new PaintEditorError(`${at}: size must be above 0 (document pixels).`);
12682
+ } else if (op.kind === "wash") {
12683
+ if (!HEX4.test(_nullishCoalesce(op.color, () => ( "")))) throw new PaintEditorError(`${at}: a wash needs color as #rrggbb.`);
12684
+ if (op.opacity !== void 0 && !(op.opacity > 0 && op.opacity <= 1)) throw new PaintEditorError(`${at}: opacity must be in (0, 1].`);
12685
+ } else if (op.kind === "echo") {
12686
+ if (!_optionalChain([op, 'access', _600 => _600.strokeIds, 'optionalAccess', _601 => _601.length])) throw new PaintEditorError(`${at}: an echo needs strokeIds (list_strokes).`);
12687
+ const unknown = op.strokeIds.filter((id) => !known.has(id));
12688
+ if (unknown.length) throw new PaintEditorError(`${at}: unknown stroke ${unknown.map((u) => `"${u}"`).join(", ")}. Call list_strokes for the ids.`);
12689
+ if (op.color !== void 0 && !HEX4.test(op.color)) throw new PaintEditorError(`${at}: color "${op.color}" is not #rrggbb.`);
12690
+ if (op.repeat !== void 0 && !(Number.isInteger(op.repeat) && op.repeat >= 1 && op.repeat <= 50)) throw new PaintEditorError(`${at}: repeat must be a whole number from 1 to 50.`);
12691
+ for (const id of op.strokeIds) {
12692
+ const stroke = controller.getStrokes().find((s) => s.id === id);
12693
+ const refusal = suggestionBrushRefusal(stroke.brush);
12694
+ if (refusal) throw new PaintEditorError(`${at}: stroke "${id}": ${refusal}`);
12695
+ points += stroke.points.length * (_nullishCoalesce(op.repeat, () => ( 1)));
12696
+ }
12697
+ } else {
12698
+ throw new PaintEditorError(`${at}: unknown kind "${op.kind}"; use stroke, wash or echo.`);
12699
+ }
12700
+ });
12701
+ if (points > maxPoints) throw new PaintEditorError(`The proposal paints ${points} points; the most is ${maxPoints}. Suggest less, or echo fewer strokes.`);
12702
+ };
12703
+ const paint = (ops, layerId) => {
12704
+ const before = strokeIds();
12705
+ for (const op of ops) {
12706
+ if (op.kind === "stroke") {
12707
+ controller.paintStroke({
12708
+ layerId,
12709
+ points: op.points,
12710
+ ...op.brushId ? { brushId: op.brushId } : {},
12711
+ ...op.color ? { color: op.color } : {},
12712
+ ...op.size ? { brush: { tip: { size: op.size } } } : {},
12713
+ stencils: false
12714
+ });
12715
+ } else if (op.kind === "wash") {
12716
+ controller.fillLayer({ layerId, color: op.color, opacity: _nullishCoalesce(op.opacity, () => ( 0.35)), grain: _nullishCoalesce(op.grain, () => ( 0.4)) });
12717
+ } else {
12718
+ const { kind: _kind, strokeIds: ids, color, repeat, ...variation } = op;
12719
+ controller.replayStrokes({ strokeIds: ids, layerId, ...color ? { color } : {}, ...repeat ? { repeat } : {}, ...variation });
12720
+ }
12721
+ }
12722
+ return controller.getStrokes().map((s) => s.id).filter((id) => !before.has(id));
12723
+ };
12724
+ const missing = (id) => {
12725
+ const p = state.proposals.find((x) => x.id === id);
12726
+ if (!p) return [];
12727
+ const known = strokeIds();
12728
+ return p.anchors.filter((a) => !known.has(a));
12729
+ };
12730
+ const placementOf = (input) => ({
12731
+ place: _nullishCoalesce(input.place, () => ( "top")),
12732
+ ...input.layerId ? { layerId: input.layerId } : {},
12733
+ ...input.layerName ? { layerName: input.layerName } : {}
12734
+ });
12735
+ const topLayerId = () => _optionalChain([controller, 'access', _602 => _602.listLayers, 'call', _603 => _603(), 'access', _604 => _604.find, 'call', _605 => _605((l) => l.parentId === null), 'optionalAccess', _606 => _606.id]);
12736
+ return {
12737
+ getState: () => state,
12738
+ subscribe(listener) {
12739
+ listeners.add(listener);
12740
+ return () => {
12741
+ listeners.delete(listener);
12742
+ };
12743
+ },
12744
+ propose(input) {
12745
+ validate(input);
12746
+ const placement = placementOf(input);
12747
+ const preview = controller.previewPaint(
12748
+ (layerId) => {
12749
+ paint(input.ops, layerId);
12750
+ },
12751
+ placement.place === "bottom" ? { bottom: true } : { aboveId: placement.place === "above" ? placement.layerId : topLayerId() }
12752
+ );
12753
+ const proposal = {
12754
+ id: makeId(),
12755
+ title: input.title.trim().slice(0, 120),
12756
+ ...input.rationale ? { rationale: input.rationale } : {},
12757
+ origin: _nullishCoalesce(_nullishCoalesce(input.origin, () => ( options.origin)), () => ( "agent:anonymous")),
12758
+ ops: input.ops.map((op) => ({ ...op })),
12759
+ placement,
12760
+ bounds: preview.bounds,
12761
+ ghost: preview.composite,
12762
+ anchors: [...new Set(input.ops.flatMap((op) => op.kind === "echo" ? op.strokeIds : []))],
12763
+ createdAt: now()
12764
+ };
12765
+ set([...state.proposals, proposal]);
12766
+ return proposal;
12767
+ },
12768
+ accept(id) {
12769
+ const p = find(id);
12770
+ const gone = missing(id);
12771
+ if (gone.length) throw new PaintEditorError(`Paint proposal "${p.title}" echoes strokes that are no longer on the canvas (${gone.join(", ")}); dismiss it or propose it again.`);
12772
+ const placement = p.placement;
12773
+ if (placement.place === "above" && !controller.listLayers().some((l) => l.id === placement.layerId)) {
12774
+ throw new PaintEditorError(`Paint proposal "${p.title}" goes above layer "${placement.layerId}", which is gone; dismiss it or propose it again.`);
12775
+ }
12776
+ const active = controller.getState().document.activeLayerId;
12777
+ const result = controller.withOrigin(
12778
+ p.origin,
12779
+ () => controller.group(p.title, () => {
12780
+ const layer = controller.addLayer({ name: _nullishCoalesce(placement.layerName, () => ( p.title)), ...placement.place === "above" ? { aboveId: placement.layerId } : placement.place === "top" ? { aboveId: topLayerId() } : {} });
12781
+ if (placement.place === "bottom") controller.moveLayer(layer.id, 0, null);
12782
+ return { layerId: layer.id, strokeIds: paint(p.ops, layer.id) };
12783
+ })
12784
+ );
12785
+ if (active && controller.listLayers().some((l) => l.id === active)) controller.setActiveLayer(active);
12786
+ set(state.proposals.filter((x) => x.id !== id));
12787
+ return { proposalId: id, layerId: result.layerId, strokeIds: result.strokeIds, label: p.title };
12788
+ },
12789
+ reject(id) {
12790
+ const p = find(id);
12791
+ set(state.proposals.filter((x) => x.id !== id));
12792
+ return p;
12793
+ },
12794
+ clear(origin) {
12795
+ const dropped = state.proposals.filter((p) => !origin || p.origin === origin);
12796
+ if (dropped.length) set(state.proposals.filter((p) => !dropped.includes(p)));
12797
+ return dropped.map((p) => p.id);
12798
+ },
12799
+ get: (id) => state.proposals.find((p) => p.id === id),
12800
+ missing
12801
+ };
12802
+ }
12803
+ function paintProposalGhost(proposal) {
12804
+ const b = proposal.bounds;
12805
+ if (!b || !b.width || !b.height || proposal.ghost.length !== b.width * b.height * 4) return null;
12806
+ return { x: b.x, y: b.y, width: b.width, height: b.height, data: proposal.ghost };
12807
+ }
12808
+
12809
+ // src/paint-editor/collaboration-tools.ts
12810
+ var READ7 = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
12811
+ var WRITE6 = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
12812
+ var proposalIdArg = {
12813
+ type: "object",
12814
+ properties: { proposalId: { type: "string", minLength: 1, description: "Id of a pending paint proposal, from propose_paint or list_paint_proposals." } },
12815
+ required: ["proposalId"],
12816
+ additionalProperties: false
12817
+ };
12818
+ var hex = { type: "string", pattern: "^#[0-9a-fA-F]{6}$" };
12819
+ var opSchema = {
12820
+ type: "object",
12821
+ description: `One thing to paint. kind "stroke": a stroke along points with a dry brush. kind "wash": an even wash over the suggestion's layer (a ground, a glaze). kind "echo": strokes already on the canvas painted again, moved, turned, scaled or mirrored (grass along a horizon, rain, hatching).`,
12822
+ properties: {
12823
+ kind: { type: "string", enum: ["stroke", "wash", "echo"], description: "What this op paints (see above)." },
12824
+ points: {
12825
+ type: "array",
12826
+ minItems: 1,
12827
+ description: "stroke: pen samples in document pixels, in drawing order.",
12828
+ items: {
12829
+ type: "object",
12830
+ properties: {
12831
+ x: { type: "number", description: "Document x in pixels." },
12832
+ y: { type: "number", description: "Document y in pixels." },
12833
+ pressure: { type: "number", minimum: 0, maximum: 1, description: "Pen pressure 0..1 (default 0.5)." }
12834
+ },
12835
+ required: ["x", "y"],
12836
+ additionalProperties: false
12837
+ }
12838
+ },
12839
+ brushId: { type: "string", description: "stroke: a dry brush id from list_brush_presets (dab, particle, bristle or mixer without pickup). Default the editor brush." },
12840
+ size: { type: "number", exclusiveMinimum: 0, description: "stroke: brush size in document pixels. Default the brush's." },
12841
+ color: { ...hex, description: "stroke and echo: #rrggbb (stroke default the editor colour; echo default each stroke's colour). wash: required." },
12842
+ opacity: { type: "number", exclusiveMinimum: 0, maximum: 1, description: "wash: 0..1 (default 0.35)." },
12843
+ grain: { type: "number", minimum: 0, maximum: 1, description: "wash: how much it catches the paper grain, 0..1 (default 0.4)." },
12844
+ strokeIds: { type: "array", minItems: 1, items: { type: "string" }, description: "echo: ids of strokes on the canvas (list_strokes)." },
12845
+ dx: { type: "number", description: "echo: move right by this many document pixels (default 0)." },
12846
+ dy: { type: "number", description: "echo: move down by this many document pixels (default 0)." },
12847
+ rotate: { type: "number", description: "echo: turn this many degrees clockwise about the strokes' centre (default 0)." },
12848
+ scale: { type: "number", exclusiveMinimum: 0, description: "echo: scale about the centre; brush size scales too (default 1)." },
12849
+ flipX: { type: "boolean", description: "echo: mirror horizontally about the centre (default false)." },
12850
+ repeat: { type: "integer", minimum: 1, maximum: 50, description: "echo: repeat the move this many times, each on top of the last (default 1)." }
12851
+ },
12852
+ required: ["kind"],
12853
+ additionalProperties: false
12854
+ };
12855
+ function createPaintProposalToolProvider(proposals, options = {}) {
12856
+ const readOnlyReason = () => {
12857
+ const ro = typeof options.readOnly === "function" ? options.readOnly() : options.readOnly;
12858
+ return ro ? typeof ro === "string" ? ro : "The painting is read-only: paint proposals can be made and rejected but not accepted." : null;
12859
+ };
12860
+ const describe = (p) => ({
12861
+ id: p.id,
12862
+ title: p.title,
12863
+ ...p.rationale ? { rationale: p.rationale } : {},
12864
+ origin: p.origin,
12865
+ ops: p.ops.map((op) => op.kind),
12866
+ placement: p.placement,
12867
+ bounds: p.bounds,
12868
+ anchors: p.anchors,
12869
+ missing: proposals.missing(p.id),
12870
+ createdAt: new Date(p.createdAt).toISOString()
12871
+ });
12872
+ const proposeTool = {
12873
+ name: "propose_paint",
12874
+ title: "Propose paint",
12875
+ description: "Suggests paint without painting it: the user sees it as a ghost over the canvas and accepts or dismisses it, so use it for contributions they did not ask for. Accepted, it is painted on a new layer of its own (on top by default, at the bottom for a ground, or above a layer) as one undo step recorded as yours. Prefer what agents do well: a wash or ground, an echo of the user's strokes, a few deliberate strokes. Dry brushes only. Returns the proposal id, where the ghost sits (bounds, document pixels) and the strokes it builds on. Follow with accept_paint_proposal only when the user asked for it.",
12876
+ inputSchema: {
12877
+ type: "object",
12878
+ properties: {
12879
+ title: { type: "string", minLength: 1, maxLength: 120, description: `What the suggestion adds, in a few words, e.g. "Warm ground behind the figure". The undo step's name once accepted.` },
12880
+ rationale: { type: "string", description: "Why it fits what the user is painting, in one sentence. Shown beside the ghost." },
12881
+ ops: { type: "array", minItems: 1, items: opSchema, description: "What to paint, in order, onto the suggestion's layer." },
12882
+ place: { type: "string", enum: ["top", "bottom", "above"], description: "Where the new layer goes: top (default), bottom (behind everything: grounds and washes), or above layerId." },
12883
+ layerId: { type: "string", description: 'With place "above": the layer to put it above (list_layers).' },
12884
+ layerName: { type: "string", description: "The new layer's name (default the title)." }
12885
+ },
12886
+ required: ["title", "ops"],
12887
+ additionalProperties: false
12888
+ },
12889
+ annotations: { title: "Propose paint", ...WRITE6 },
12890
+ handler: (args, context) => {
12891
+ const origin = _optionalChain([context, 'access', _607 => _607.actor, 'optionalAccess', _608 => _608.id]) ? `agent:${context.actor.id}` : options.fallbackOrigin;
12892
+ const proposal = proposals.propose({ ...args, ...origin ? { origin } : {} });
12893
+ const { id: _id, missing: _missing, createdAt: _createdAt, ...rest } = describe(proposal);
12894
+ return { proposalId: proposal.id, ...rest };
12895
+ }
12896
+ };
12897
+ const listTool = {
12898
+ name: "list_paint_proposals",
12899
+ title: "List paint proposals",
12900
+ description: "Lists the pending paint proposals (ghost paint not yet on the canvas): id, title, rationale, who proposed it, its op kinds, where it goes, where the ghost sits, the strokes it echoes and any of those since removed (missing: it can no longer be accepted), and whether accepting is allowed. Call before accept_paint_proposal or reject_paint_proposal.",
12901
+ inputSchema: { type: "object", properties: {}, additionalProperties: false },
12902
+ annotations: { title: "List paint proposals", ...READ7 },
12903
+ handler: () => ({ proposals: proposals.getState().proposals.map(describe), readOnly: readOnlyReason() })
12904
+ };
12905
+ const acceptTool = {
12906
+ name: "accept_paint_proposal",
12907
+ title: "Accept a paint proposal",
12908
+ description: "Paints a pending proposal on a new layer as one undo step, recorded as made by whoever proposed it, and drops it from the pending list; the user's active layer stays theirs. Refuses, changing nothing, when the painting is read-only or a stroke it echoes was removed. Returns the new layer id, the stroke ids painted and the undo step name.",
12909
+ inputSchema: proposalIdArg,
12910
+ annotations: { title: "Accept a paint proposal", ...WRITE6 },
12911
+ handler: (args) => {
12912
+ const reason = readOnlyReason();
12913
+ if (reason) throw new Error(reason);
12914
+ return proposals.accept(args.proposalId);
12915
+ }
12916
+ };
12917
+ const rejectTool = {
12918
+ name: "reject_paint_proposal",
12919
+ title: "Reject a paint proposal",
12920
+ description: "Dismisses a pending paint proposal: its ghost disappears and the painting and its history are unchanged. Use it to withdraw a suggestion that no longer fits. Returns the dismissed proposal id and title.",
12921
+ inputSchema: proposalIdArg,
12922
+ annotations: { title: "Reject a paint proposal", ...WRITE6 },
12923
+ handler: (args) => {
12924
+ const p = proposals.reject(args.proposalId);
12925
+ return { proposalId: p.id, title: p.title, rejected: true };
12926
+ }
12927
+ };
12928
+ return {
12929
+ id: _nullishCoalesce(options.id, () => ( "paint-proposals")),
12930
+ ...options.namespace !== void 0 ? { namespace: options.namespace } : {},
12931
+ title: "Paint proposals",
12932
+ description: "Suggest paint as a ghost the user accepts or dismisses, and accept or reject pending suggestions.",
12933
+ skill: "pixerate-paint-editor",
12934
+ tools: [proposeTool, listTool, acceptTool, rejectTool]
12935
+ };
12936
+ }
12937
+
12938
+
12939
+
12940
+
12941
+
12409
12942
 
12410
12943
 
12411
12944
 
@@ -12753,4 +13286,4 @@ function createPaintEditorDocument(controller, options = {}) {
12753
13286
 
12754
13287
 
12755
13288
 
12756
- exports.BACKLIGHT_SPILL = BACKLIGHT_SPILL; exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunk2VX55NFMcjs.BLEND_MODES; exports.BRUSH_ID = _chunkHS6QDWDFcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkHS6QDWDFcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = _chunk34KLWUH4cjs.BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkHS6QDWDFcjs.BUILTIN_BRUSHES; exports.BristleStroke = BristleStroke; exports.DEFAULT_BACKLIGHT_COLOR = DEFAULT_BACKLIGHT_COLOR; exports.DEFAULT_BEHAVIOR = _chunkHS6QDWDFcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkHS6QDWDFcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkHS6QDWDFcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkHS6QDWDFcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkKBYB7OWBcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunkHS6QDWDFcjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHT = _chunkHS6QDWDFcjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunkHS6QDWDFcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkFQPUF2W2cjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkFQPUF2W2cjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkHS6QDWDFcjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunkHS6QDWDFcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunkHS6QDWDFcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkKBYB7OWBcjs.DEFAULT_WET_PARAMS; exports.DOT_ROTATIONS = _chunkHS6QDWDFcjs.DOT_ROTATIONS; exports.DOT_ROTATION_LABELS = DOT_ROTATION_LABELS; exports.DOT_TEXTURE_ORDERS = _chunkHS6QDWDFcjs.DOT_TEXTURE_ORDERS; exports.DOT_TEXTURE_ORDER_LABELS = DOT_TEXTURE_ORDER_LABELS; exports.DryStroke = DryStroke; exports.EFFECT_MAP_REPEATS = EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = EFFECT_STRIP_HEIGHT; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkPXDIAYB6cjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkPXDIAYB6cjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunkEUIDTZNQcjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkHS6QDWDFcjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LIVE_STROKE_ENGINES = LIVE_STROKE_ENGINES; exports.LitCache = LitCache; exports.MAX_BRUSH_SIZE = _chunkFQPUF2W2cjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_DOT_TEXTURES = _chunkHS6QDWDFcjs.MAX_DOT_TEXTURES; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; exports.MAX_STICKER_STAMPS = _chunkHS6QDWDFcjs.MAX_STICKER_STAMPS; exports.MAX_ZOOM = MAX_ZOOM; exports.MIN_CANVAS_SIDE = MIN_CANVAS_SIDE; exports.MIN_ZOOM = MIN_ZOOM; exports.MIXING_PAD_HEIGHT = MIXING_PAD_HEIGHT; exports.MIXING_PAD_WIDTH = MIXING_PAD_WIDTH; exports.MULTI_COLOR_MODES = _chunkHS6QDWDFcjs.MULTI_COLOR_MODES; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunk2VX55NFMcjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunkHS6QDWDFcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkHS6QDWDFcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkFQPUF2W2cjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkFQPUF2W2cjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkFQPUF2W2cjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkFQPUF2W2cjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkFQPUF2W2cjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkFQPUF2W2cjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TARGET = PAINT_TARGET; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = PAPER_FAMILIES; exports.PAPER_LIBRARY = PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkHS6QDWDFcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkHS6QDWDFcjs.PARTICLE_RENDERS; exports.PARTICLE_RENDER_LABELS = PARTICLE_RENDER_LABELS; exports.PaintCanvasPresenter = PaintCanvasPresenter; exports.PaintDabStroke = PaintDabStroke; exports.PaintDirector = PaintDirector; exports.PaintDocumentError = PaintDocumentError; exports.PaintEditorController = PaintEditorController; exports.PaintEditorError = PaintEditorError; exports.PaintEffectsRenderer = PaintEffectsRenderer; exports.PaintGesture = PaintGesture; exports.PaintGradientSampler = _chunkFQPUF2W2cjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkFQPUF2W2cjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkPXDIAYB6cjs.PaperGrain; exports.ParticleStroke = ParticleStroke; exports.PenDabWalker = PenDabWalker; exports.PenSmoother = PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.RIBBON_PAIRS = _chunkHS6QDWDFcjs.RIBBON_PAIRS; exports.RIBBON_PAIR_LABELS = RIBBON_PAIR_LABELS; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkJSDND7DFcjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_ART_SIZE = STICKER_ART_SIZE; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerArtCache = StickerArtCache; exports.StickerBrowser = _chunkSABJMH6Mcjs.StickerBrowser; exports.StickerSpray = StickerSpray; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunk3K6HWEXZcjs.TileableNoise; exports.WET_FLOW_KINDS = _chunkKBYB7OWBcjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunkHS6QDWDFcjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkKBYB7OWBcjs.WET_PARAM_KEYS; exports.WET_PARAM_SCHEMA = WET_PARAM_SCHEMA; exports.WET_PARAM_SLIDERS = WET_PARAM_SLIDERS; exports.WET_SPEED_SLIDER = WET_SPEED_SLIDER; exports.WET_TILT_SLIDERS = WET_TILT_SLIDERS; exports.WET_TOOLS = _chunkHS6QDWDFcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkFQPUF2W2cjs.addPaintGradientStop; exports.addPolygonArea = addPolygonArea; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.backlightOf = backlightOf; exports.brushEngineControls = _chunk34KLWUH4cjs.brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkHS6QDWDFcjs.brushTakesPaint; exports.brushToJSON = _chunkHS6QDWDFcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.contactSheet = contactSheet; exports.createPaintBrushLibraryToolProvider = createPaintBrushLibraryToolProvider; exports.createPaintCompositor = createPaintCompositor; exports.createPaintDocument = createPaintDocument; exports.createPaintEditorDocument = createPaintEditorDocument; exports.createPaintEditorToolProvider = createPaintEditorToolProvider; exports.createPaintEffectsToolProvider = createPaintEffectsToolProvider; exports.createPaintLayer = createPaintLayer; exports.createPaintReplayTools = createPaintReplayTools; exports.createPaintStickerTools = createPaintStickerTools; exports.createPaintThickTools = createPaintThickTools; exports.createPaintWetTools = createPaintWetTools; exports.decodeImageBlob = decodeImageBlob; exports.defaultGuides = defaultGuides; exports.defaultImageEncoder = defaultImageEncoder; exports.defaultStickerRasterizer = defaultStickerRasterizer; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectDabField = effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = effectPaintKey; exports.effectPaintSize = effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkPXDIAYB6cjs.grainCatch; exports.grainHeights = _chunkPXDIAYB6cjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunk3K6HWEXZcjs.hash2; exports.hexToPaintRgb = _chunkFQPUF2W2cjs.hexToPaintRgb; exports.hexToRgb8 = hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunkEUIDTZNQcjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunk2VX55NFMcjs.isBlendMode; exports.isGradientPaint = _chunkFQPUF2W2cjs.isGradientPaint; exports.isPaintEffectPaint = isPaintEffectPaint; exports.isPainterlyBlendMode = _chunk2VX55NFMcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkHS6QDWDFcjs.isWetBrush; exports.isWetCapable = _chunkHS6QDWDFcjs.isWetCapable; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.liveStrokeBounds = liveStrokeBounds; exports.liveStrokeRefusal = liveStrokeRefusal; exports.mapPenPoint = mapPenPoint; exports.mix32 = _chunk3K6HWEXZcjs.mix32; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = _chunk34KLWUH4cjs.multiColorSliders; exports.multiColorToPaint = _chunkHS6QDWDFcjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkHS6QDWDFcjs.normalizeBehavior; exports.normalizeBristle = _chunkHS6QDWDFcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkHS6QDWDFcjs.normalizeDynamics; exports.normalizeFlow = _chunkKBYB7OWBcjs.normalizeFlow; exports.normalizeHexColor = _chunkFQPUF2W2cjs.normalizeHexColor; exports.normalizeImpasto = _chunkHS6QDWDFcjs.normalizeImpasto; exports.normalizeLight = _chunkHS6QDWDFcjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunkHS6QDWDFcjs.normalizeMultiColor; exports.normalizePaintBrush = _chunkHS6QDWDFcjs.normalizePaintBrush; exports.normalizePaper = normalizePaper; exports.normalizeParticle = _chunkHS6QDWDFcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkHS6QDWDFcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunkHS6QDWDFcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkKBYB7OWBcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkFQPUF2W2cjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintSourceColor = _chunkFQPUF2W2cjs.paintSourceColor; exports.paintSourceCss = _chunkFQPUF2W2cjs.paintSourceCss; exports.paintToMultiColor = _chunkHS6QDWDFcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = paperPreset; exports.parseBrushLibrary = _chunkHS6QDWDFcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkFQPUF2W2cjs.parsePaintSource; exports.patchBrushValue = _chunk34KLWUH4cjs.patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.quickStencil = quickStencil; exports.rand01 = _chunk3K6HWEXZcjs.rand01; exports.randSigned = _chunk3K6HWEXZcjs.randSigned; exports.readEffectStrokeMap = readEffectStrokeMap; exports.readPaintEffectPaint = readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkFQPUF2W2cjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkFQPUF2W2cjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = renderPaper; exports.renderStickers = renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkFQPUF2W2cjs.resolvePaintGradient; exports.reversePaintGradient = _chunkFQPUF2W2cjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleArt = sampleArt; exports.sampleEffectAt = sampleEffectAt; exports.sampleEffectField = sampleEffectField; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkFQPUF2W2cjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunk3K6HWEXZcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkFQPUF2W2cjs.solidPaint; exports.stampCoverage = _chunkJSDND7DFcjs.stampCoverage; exports.standardBlendMode = _chunk2VX55NFMcjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = stickerAt; exports.stickerRect = stickerRect; exports.stickerRefLabel = stickerRefLabel; exports.stickerStamp = stickerStamp; exports.stickerSurface = stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokeSchedule = strokeSchedule; exports.strokeToJSON = strokeToJSON; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = toStrokePoint; exports.toggleDotTexture = toggleDotTexture; exports.toggleStamp = toggleStamp; exports.toggleStickerRef = toggleStickerRef; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkFQPUF2W2cjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkHS6QDWDFcjs.usesPaintExchange; exports.variationAffine = variationAffine; exports.varyStroke = varyStroke; exports.viewCssTransform = viewCssTransform; exports.viewMatrix = viewMatrix; exports.viewPenToDocument = viewPenToDocument; exports.wetEngineSummary = wetEngineSummary; exports.wetPaperInput = wetPaperInput; exports.wetPigmentOf = wetPigmentOf; exports.wetSupport = _chunkKBYB7OWBcjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunkEUIDTZNQcjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;
13289
+ exports.BACKLIGHT_SPILL = BACKLIGHT_SPILL; exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunk2VX55NFMcjs.BLEND_MODES; exports.BRUSH_ID = _chunkHIMGBZAMcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkHIMGBZAMcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = _chunkPGPFWC35cjs.BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkHIMGBZAMcjs.BUILTIN_BRUSHES; exports.BristleStroke = BristleStroke; exports.DEFAULT_BACKLIGHT_COLOR = DEFAULT_BACKLIGHT_COLOR; exports.DEFAULT_BEHAVIOR = _chunkHIMGBZAMcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkHIMGBZAMcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkHIMGBZAMcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkHIMGBZAMcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkKBYB7OWBcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunkHIMGBZAMcjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHT = _chunkHIMGBZAMcjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunkHIMGBZAMcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkFQPUF2W2cjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkFQPUF2W2cjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkHIMGBZAMcjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunkHIMGBZAMcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunkHIMGBZAMcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkKBYB7OWBcjs.DEFAULT_WET_PARAMS; exports.DOT_ROTATIONS = _chunkHIMGBZAMcjs.DOT_ROTATIONS; exports.DOT_ROTATION_LABELS = DOT_ROTATION_LABELS; exports.DOT_TEXTURE_ORDERS = _chunkHIMGBZAMcjs.DOT_TEXTURE_ORDERS; exports.DOT_TEXTURE_ORDER_LABELS = DOT_TEXTURE_ORDER_LABELS; exports.DryStroke = DryStroke; exports.EFFECT_MAP_REPEATS = EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = EFFECT_STRIP_HEIGHT; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkPXDIAYB6cjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkPXDIAYB6cjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunkEUIDTZNQcjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkHIMGBZAMcjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LIVE_STROKE_ENGINES = LIVE_STROKE_ENGINES; exports.LitCache = LitCache; exports.MAX_BRUSH_SIZE = _chunkFQPUF2W2cjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_DOT_TEXTURES = _chunkHIMGBZAMcjs.MAX_DOT_TEXTURES; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; exports.MAX_STICKER_STAMPS = _chunkHIMGBZAMcjs.MAX_STICKER_STAMPS; exports.MAX_ZOOM = MAX_ZOOM; exports.MIN_CANVAS_SIDE = MIN_CANVAS_SIDE; exports.MIN_ZOOM = MIN_ZOOM; exports.MIXING_PAD_HEIGHT = MIXING_PAD_HEIGHT; exports.MIXING_PAD_WIDTH = MIXING_PAD_WIDTH; exports.MULTI_COLOR_MODES = _chunkHIMGBZAMcjs.MULTI_COLOR_MODES; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunk2VX55NFMcjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunkHIMGBZAMcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkHIMGBZAMcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkFQPUF2W2cjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkFQPUF2W2cjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkFQPUF2W2cjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkFQPUF2W2cjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkFQPUF2W2cjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkFQPUF2W2cjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkFQPUF2W2cjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TARGET = PAINT_TARGET; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = PAPER_FAMILIES; exports.PAPER_LIBRARY = PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkHIMGBZAMcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkHIMGBZAMcjs.PARTICLE_RENDERS; exports.PARTICLE_RENDER_LABELS = PARTICLE_RENDER_LABELS; exports.PaintCanvasPresenter = PaintCanvasPresenter; exports.PaintDabStroke = PaintDabStroke; exports.PaintDirector = PaintDirector; exports.PaintDocumentError = PaintDocumentError; exports.PaintEditorController = PaintEditorController; exports.PaintEditorError = PaintEditorError; exports.PaintEffectsRenderer = PaintEffectsRenderer; exports.PaintGesture = PaintGesture; exports.PaintGradientSampler = _chunkFQPUF2W2cjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkFQPUF2W2cjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkPXDIAYB6cjs.PaperGrain; exports.ParticleStroke = ParticleStroke; exports.PenDabWalker = PenDabWalker; exports.PenSmoother = PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.RIBBON_PAIRS = _chunkHIMGBZAMcjs.RIBBON_PAIRS; exports.RIBBON_PAIR_LABELS = RIBBON_PAIR_LABELS; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkJSDND7DFcjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_ART_SIZE = STICKER_ART_SIZE; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerArtCache = StickerArtCache; exports.StickerBrowser = _chunkSABJMH6Mcjs.StickerBrowser; exports.StickerSpray = StickerSpray; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunk3K6HWEXZcjs.TileableNoise; exports.WET_FLOW_KINDS = _chunkKBYB7OWBcjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunkHIMGBZAMcjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkKBYB7OWBcjs.WET_PARAM_KEYS; exports.WET_PARAM_SCHEMA = WET_PARAM_SCHEMA; exports.WET_PARAM_SLIDERS = WET_PARAM_SLIDERS; exports.WET_SPEED_SLIDER = WET_SPEED_SLIDER; exports.WET_TILT_SLIDERS = WET_TILT_SLIDERS; exports.WET_TOOLS = _chunkHIMGBZAMcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkFQPUF2W2cjs.addPaintGradientStop; exports.addPolygonArea = addPolygonArea; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.backlightOf = backlightOf; exports.brushEngineControls = _chunkPGPFWC35cjs.brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkHIMGBZAMcjs.brushTakesPaint; exports.brushToJSON = _chunkHIMGBZAMcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.contactSheet = contactSheet; exports.createPaintBrushLibraryToolProvider = createPaintBrushLibraryToolProvider; exports.createPaintChangeFeed = createPaintChangeFeed; exports.createPaintCompositor = createPaintCompositor; exports.createPaintDocument = createPaintDocument; exports.createPaintEditorDocument = createPaintEditorDocument; exports.createPaintEditorToolProvider = createPaintEditorToolProvider; exports.createPaintEffectsToolProvider = createPaintEffectsToolProvider; exports.createPaintLayer = createPaintLayer; exports.createPaintProposalToolProvider = createPaintProposalToolProvider; exports.createPaintProposals = createPaintProposals; exports.createPaintReplayTools = createPaintReplayTools; exports.createPaintStickerTools = createPaintStickerTools; exports.createPaintThickTools = createPaintThickTools; exports.createPaintWetTools = createPaintWetTools; exports.decodeImageBlob = decodeImageBlob; exports.defaultGuides = defaultGuides; exports.defaultImageEncoder = defaultImageEncoder; exports.defaultStickerRasterizer = defaultStickerRasterizer; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectDabField = effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = effectPaintKey; exports.effectPaintSize = effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkPXDIAYB6cjs.grainCatch; exports.grainHeights = _chunkPXDIAYB6cjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunk3K6HWEXZcjs.hash2; exports.hexToPaintRgb = _chunkFQPUF2W2cjs.hexToPaintRgb; exports.hexToRgb8 = hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunkEUIDTZNQcjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunk2VX55NFMcjs.isBlendMode; exports.isGradientPaint = _chunkFQPUF2W2cjs.isGradientPaint; exports.isPaintEffectPaint = isPaintEffectPaint; exports.isPainterlyBlendMode = _chunk2VX55NFMcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkHIMGBZAMcjs.isWetBrush; exports.isWetCapable = _chunkHIMGBZAMcjs.isWetCapable; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.liveStrokeBounds = liveStrokeBounds; exports.liveStrokeRefusal = liveStrokeRefusal; exports.mapPenPoint = mapPenPoint; exports.mix32 = _chunk3K6HWEXZcjs.mix32; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = _chunkPGPFWC35cjs.multiColorSliders; exports.multiColorToPaint = _chunkHIMGBZAMcjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkHIMGBZAMcjs.normalizeBehavior; exports.normalizeBristle = _chunkHIMGBZAMcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkHIMGBZAMcjs.normalizeDynamics; exports.normalizeFlow = _chunkKBYB7OWBcjs.normalizeFlow; exports.normalizeHexColor = _chunkFQPUF2W2cjs.normalizeHexColor; exports.normalizeImpasto = _chunkHIMGBZAMcjs.normalizeImpasto; exports.normalizeLight = _chunkHIMGBZAMcjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunkHIMGBZAMcjs.normalizeMultiColor; exports.normalizePaintBrush = _chunkHIMGBZAMcjs.normalizePaintBrush; exports.normalizePaper = normalizePaper; exports.normalizeParticle = _chunkHIMGBZAMcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkHIMGBZAMcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunkHIMGBZAMcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkKBYB7OWBcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkFQPUF2W2cjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintProposalGhost = paintProposalGhost; exports.paintSourceColor = _chunkFQPUF2W2cjs.paintSourceColor; exports.paintSourceCss = _chunkFQPUF2W2cjs.paintSourceCss; exports.paintToMultiColor = _chunkHIMGBZAMcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = paperPreset; exports.parseBrushLibrary = _chunkHIMGBZAMcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkFQPUF2W2cjs.parsePaintSource; exports.patchBrushValue = _chunkPGPFWC35cjs.patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.quickStencil = quickStencil; exports.rand01 = _chunk3K6HWEXZcjs.rand01; exports.randSigned = _chunk3K6HWEXZcjs.randSigned; exports.readEffectStrokeMap = readEffectStrokeMap; exports.readPaintEffectPaint = readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkFQPUF2W2cjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkFQPUF2W2cjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = renderPaper; exports.renderStickers = renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkFQPUF2W2cjs.resolvePaintGradient; exports.reversePaintGradient = _chunkFQPUF2W2cjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleArt = sampleArt; exports.sampleEffectAt = sampleEffectAt; exports.sampleEffectField = sampleEffectField; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkFQPUF2W2cjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunk3K6HWEXZcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkFQPUF2W2cjs.solidPaint; exports.stampCoverage = _chunkJSDND7DFcjs.stampCoverage; exports.standardBlendMode = _chunk2VX55NFMcjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = stickerAt; exports.stickerRect = stickerRect; exports.stickerRefLabel = stickerRefLabel; exports.stickerStamp = stickerStamp; exports.stickerSurface = stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokeSchedule = strokeSchedule; exports.strokeToJSON = strokeToJSON; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = toStrokePoint; exports.toggleDotTexture = toggleDotTexture; exports.toggleStamp = toggleStamp; exports.toggleStickerRef = toggleStickerRef; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkFQPUF2W2cjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkHIMGBZAMcjs.usesPaintExchange; exports.variationAffine = variationAffine; exports.varyStroke = varyStroke; exports.viewCssTransform = viewCssTransform; exports.viewMatrix = viewMatrix; exports.viewPenToDocument = viewPenToDocument; exports.wetEngineSummary = wetEngineSummary; exports.wetPaperInput = wetPaperInput; exports.wetPigmentOf = wetPigmentOf; exports.wetSupport = _chunkKBYB7OWBcjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunkEUIDTZNQcjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;