@pixerate/editor 0.246.0 → 0.249.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 (105) hide show
  1. package/README.md +1 -0
  2. package/dist/animation-editor/index.cjs +64 -61
  3. package/dist/animation-editor/index.js +8 -5
  4. package/dist/{brushstrokeRender-ZDHMXJAE.cjs → brushstrokeRender-GCKK7V2I.cjs} +14 -11
  5. package/dist/{brushstrokeRender-AKUI3SEJ.js → brushstrokeRender-T3JZST44.js} +7 -4
  6. package/dist/canvas/index.cjs +8 -8
  7. package/dist/canvas/index.js +1 -1
  8. package/dist/{chunk-UVPD55UZ.cjs → chunk-2SMMZDMG.cjs} +35 -35
  9. package/dist/chunk-2VJAVXLI.js +192 -0
  10. package/dist/{chunk-OLNIPTB3.cjs → chunk-2VX55NFM.cjs} +1 -320
  11. package/dist/chunk-3K6HWEXZ.cjs +92 -0
  12. package/dist/{chunk-UOOK7HTX.js → chunk-3PPJRMIG.js} +1 -1
  13. package/dist/chunk-4D6KP5BV.js +92 -0
  14. package/dist/chunk-5RH3VXAK.js +269 -0
  15. package/dist/{chunk-LDPLEZ5T.js → chunk-6BIDVPED.js} +1 -1
  16. package/dist/{chunk-2ONK3ERD.cjs → chunk-75K3W4D6.cjs} +20 -20
  17. package/dist/chunk-BOHDJJ2O.cjs +192 -0
  18. package/dist/{chunk-2PBZBRP5.js → chunk-D5KGAO4Z.js} +10 -92
  19. package/dist/{chunk-DQWPMGH2.js → chunk-DOIU7VJG.js} +1 -1
  20. package/dist/{chunk-HB4ICNNA.cjs → chunk-DPYAO5U6.cjs} +42 -42
  21. package/dist/chunk-EJLRBS5Q.js +301 -0
  22. package/dist/{chunk-Q2UYUWAZ.cjs → chunk-H4AOUUBE.cjs} +679 -164
  23. package/dist/{chunk-PQ3H2AAN.cjs → chunk-I7NJPHWV.cjs} +122 -204
  24. package/dist/{chunk-FK5LTDOO.cjs → chunk-IOFVM3L3.cjs} +7 -7
  25. package/dist/{chunk-42TWUPNJ.js → chunk-IRSTHLQQ.js} +1 -320
  26. package/dist/{chunk-VDAWA546.js → chunk-J7T5QZ45.js} +614 -99
  27. package/dist/{chunk-VMROIWLL.cjs → chunk-KBYB7OWB.cjs} +3 -3
  28. package/dist/{chunk-5MFDD7SP.cjs → chunk-KYX7NZ5V.cjs} +1 -1
  29. package/dist/chunk-LJRCU3BJ.cjs +301 -0
  30. package/dist/{chunk-XTWXBQD4.cjs → chunk-LP2MCSBE.cjs} +593 -236
  31. package/dist/{chunk-A23PSOBB.js → chunk-O75V4ZS3.js} +1 -1
  32. package/dist/chunk-OTTT5N3K.js +322 -0
  33. package/dist/{chunk-N6WUB3Y5.js → chunk-PZP2SZIZ.js} +2 -2
  34. package/dist/{chunk-4PMCMWQS.js → chunk-UBRJOIR5.js} +367 -10
  35. package/dist/chunk-W5M3J7PV.cjs +322 -0
  36. package/dist/{chunk-4P6H35HU.js → chunk-WA44NKPF.js} +2 -2
  37. package/dist/{chunk-CEPKXLBS.cjs → chunk-WLJZZHUZ.cjs} +23 -23
  38. package/dist/{chunk-P3NIPIKS.js → chunk-WQCNC4DK.js} +1 -1
  39. package/dist/chunk-ZEYMKDYS.cjs +269 -0
  40. package/dist/image-editor/effect-tools.d.cts +37 -4
  41. package/dist/image-editor/effect-tools.d.ts +37 -4
  42. package/dist/image-editor/index.cjs +1340 -1828
  43. package/dist/image-editor/index.d.cts +1 -1
  44. package/dist/image-editor/index.d.ts +1 -1
  45. package/dist/image-editor/index.js +298 -786
  46. package/dist/paint/index.cjs +8 -5
  47. package/dist/paint/index.js +13 -10
  48. package/dist/paint-editor/controller.d.cts +71 -2
  49. package/dist/paint-editor/controller.d.ts +71 -2
  50. package/dist/paint-editor/index.cjs +901 -589
  51. package/dist/paint-editor/index.d.cts +3 -0
  52. package/dist/paint-editor/index.d.ts +3 -0
  53. package/dist/paint-editor/index.js +365 -53
  54. package/dist/paint-editor/procedural.d.cts +82 -5
  55. package/dist/paint-editor/procedural.d.ts +82 -5
  56. package/dist/paint-editor/sticker-art.d.cts +55 -0
  57. package/dist/paint-editor/sticker-art.d.ts +55 -0
  58. package/dist/paint-editor/stickers.d.cts +30 -17
  59. package/dist/paint-editor/stickers.d.ts +30 -17
  60. package/dist/paint-editor/stroke.d.cts +4 -0
  61. package/dist/paint-editor/stroke.d.ts +4 -0
  62. package/dist/paint-editor/tools.d.cts +1 -1
  63. package/dist/paint-editor/tools.d.ts +1 -1
  64. package/dist/paint-editor/ui.d.cts +25 -4
  65. package/dist/paint-editor/ui.d.ts +25 -4
  66. package/dist/{image-editor/layers/effects-ui.d.cts → raster/effects/ui.d.cts} +32 -5
  67. package/dist/{image-editor/layers/effects-ui.d.ts → raster/effects/ui.d.ts} +32 -5
  68. package/dist/raster/index.cjs +17 -3
  69. package/dist/raster/index.d.cts +1 -0
  70. package/dist/raster/index.d.ts +1 -0
  71. package/dist/raster/index.js +23 -9
  72. package/dist/stickers/browser.d.cts +48 -0
  73. package/dist/stickers/browser.d.ts +48 -0
  74. package/dist/stickers/combine.d.cts +10 -0
  75. package/dist/stickers/combine.d.ts +10 -0
  76. package/dist/stickers/conformance.d.cts +18 -0
  77. package/dist/stickers/conformance.d.ts +18 -0
  78. package/dist/stickers/editor.d.cts +14 -0
  79. package/dist/stickers/editor.d.ts +14 -0
  80. package/dist/stickers/errors.d.cts +6 -0
  81. package/dist/stickers/errors.d.ts +6 -0
  82. package/dist/stickers/fake.d.cts +16 -0
  83. package/dist/stickers/fake.d.ts +16 -0
  84. package/dist/stickers/helpers.d.cts +51 -0
  85. package/dist/stickers/helpers.d.ts +51 -0
  86. package/dist/stickers/index.cjs +331 -0
  87. package/dist/stickers/index.d.cts +16 -0
  88. package/dist/stickers/index.d.ts +16 -0
  89. package/dist/stickers/index.js +331 -0
  90. package/dist/stickers/stamps.d.cts +13 -0
  91. package/dist/stickers/stamps.d.ts +13 -0
  92. package/dist/stickers/tools.d.cts +25 -0
  93. package/dist/stickers/tools.d.ts +25 -0
  94. package/dist/stickers/types.d.cts +123 -0
  95. package/dist/stickers/types.d.ts +123 -0
  96. package/dist/vector/index.cjs +978 -975
  97. package/dist/vector/index.js +9 -6
  98. package/package.json +11 -1
  99. package/skills/README.md +1 -0
  100. package/skills/pixerate-paint-editor/SKILL.md +26 -32
  101. package/skills/pixerate-paint-editor/references/gradient-paint.md +23 -0
  102. package/skills/pixerate-paint-editor/references/layer-effects.md +28 -0
  103. package/skills/pixerate-paint-editor/references/light-paint.md +10 -2
  104. package/skills/pixerate-paint-editor/references/particle-brushes.md +66 -0
  105. package/skills/pixerate-stickers/SKILL.md +45 -0
@@ -1,5 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14;
2
2
 
3
+
4
+ var _chunkLJRCU3BJcjs = require('../chunk-LJRCU3BJ.cjs');
5
+
6
+
3
7
  var _chunkXNZFVYC2cjs = require('../chunk-XNZFVYC2.cjs');
4
8
 
5
9
 
@@ -7,7 +11,8 @@ var _chunkXNZFVYC2cjs = require('../chunk-XNZFVYC2.cjs');
7
11
 
8
12
 
9
13
 
10
- var _chunkXTWXBQD4cjs = require('../chunk-XTWXBQD4.cjs');
14
+
15
+ var _chunkLP2MCSBEcjs = require('../chunk-LP2MCSBE.cjs');
11
16
  require('../chunk-A2IS7EHE.cjs');
12
17
  require('../chunk-SS53NNZO.cjs');
13
18
 
@@ -17,7 +22,15 @@ require('../chunk-SS53NNZO.cjs');
17
22
 
18
23
 
19
24
 
20
- var _chunkHB4ICNNAcjs = require('../chunk-HB4ICNNA.cjs');
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+ var _chunkDPYAO5U6cjs = require('../chunk-DPYAO5U6.cjs');
21
34
  require('../chunk-QT26RHKK.cjs');
22
35
  require('../chunk-K6PXS6DO.cjs');
23
36
 
@@ -44,7 +57,7 @@ require('../chunk-K6PXS6DO.cjs');
44
57
 
45
58
 
46
59
 
47
- var _chunkVMROIWLLcjs = require('../chunk-VMROIWLL.cjs');
60
+ var _chunkKBYB7OWBcjs = require('../chunk-KBYB7OWB.cjs');
48
61
  require('../chunk-BROJYMWU.cjs');
49
62
 
50
63
 
@@ -55,7 +68,22 @@ var _chunkJLWLX52Lcjs = require('../chunk-JLWLX52L.cjs');
55
68
 
56
69
 
57
70
  var _chunkK7ENM55Pcjs = require('../chunk-K7ENM55P.cjs');
58
- require('../chunk-FK5LTDOO.cjs');
71
+ require('../chunk-IOFVM3L3.cjs');
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
59
87
 
60
88
 
61
89
 
@@ -127,13 +155,15 @@ require('../chunk-FK5LTDOO.cjs');
127
155
 
128
156
 
129
157
 
158
+ var _chunkH4AOUUBEcjs = require('../chunk-H4AOUUBE.cjs');
130
159
 
131
160
 
132
161
 
133
162
 
134
163
 
135
164
 
136
- var _chunkQ2UYUWAZcjs = require('../chunk-Q2UYUWAZ.cjs');
165
+
166
+ var _chunkZEYMKDYScjs = require('../chunk-ZEYMKDYS.cjs');
137
167
  require('../chunk-CVFAAZXE.cjs');
138
168
  require('../chunk-GF2RBSDM.cjs');
139
169
  require('../chunk-NM3G4VQT.cjs');
@@ -199,6 +229,8 @@ require('../chunk-WOFXZ3XU.cjs');
199
229
 
200
230
 
201
231
 
232
+
233
+ var _chunkI7NJPHWVcjs = require('../chunk-I7NJPHWV.cjs');
202
234
 
203
235
 
204
236
 
@@ -206,7 +238,7 @@ require('../chunk-WOFXZ3XU.cjs');
206
238
 
207
239
 
208
240
 
209
- var _chunkPQ3H2AANcjs = require('../chunk-PQ3H2AAN.cjs');
241
+ var _chunk3K6HWEXZcjs = require('../chunk-3K6HWEXZ.cjs');
210
242
  require('../chunk-YQGCPL5X.cjs');
211
243
 
212
244
 
@@ -216,6 +248,7 @@ require('../chunk-YQGCPL5X.cjs');
216
248
 
217
249
 
218
250
 
251
+ var _chunk2VX55NFMcjs = require('../chunk-2VX55NFM.cjs');
219
252
 
220
253
 
221
254
 
@@ -223,7 +256,8 @@ require('../chunk-YQGCPL5X.cjs');
223
256
 
224
257
 
225
258
 
226
- var _chunkOLNIPTB3cjs = require('../chunk-OLNIPTB3.cjs');
259
+
260
+ var _chunkW5M3J7PVcjs = require('../chunk-W5M3J7PV.cjs');
227
261
 
228
262
 
229
263
 
@@ -295,7 +329,7 @@ function normalizeCanvas(raw) {
295
329
  function createPaintDocument(options = {}) {
296
330
  const canvas = normalizeCanvas({ width: _nullishCoalesce(options.width, () => ( 2048)), height: _nullishCoalesce(options.height, () => ( 1536)), dpi: options.dpi });
297
331
  const layer = createPaintLayer("Layer 1");
298
- return { canvas, paper: _chunkQ2UYUWAZcjs.normalizePaper.call(void 0, _nullishCoalesce(options.paper, () => ( {}))), layers: [layer], activeLayerId: layer.id, strokes: [] };
332
+ return { canvas, paper: _chunkH4AOUUBEcjs.normalizePaper.call(void 0, _nullishCoalesce(options.paper, () => ( {}))), layers: [layer], activeLayerId: layer.id, strokes: [] };
299
333
  }
300
334
 
301
335
  // src/paint-editor/dab-stroke.ts
@@ -320,7 +354,7 @@ function mixRgb(a, b, t, mixing) {
320
354
  if (mixing === "pigment") {
321
355
  const o = [0, 0, 0];
322
356
  const q = (v) => Math.round(Math.min(1, Math.max(0, v)) * 255);
323
- _chunkOLNIPTB3cjs.mixPigment8.call(void 0, q(a[0]), q(a[1]), q(a[2]), q(b[0]), q(b[1]), q(b[2]), t, o);
357
+ _chunk2VX55NFMcjs.mixPigment8.call(void 0, q(a[0]), q(a[1]), q(a[2]), q(b[0]), q(b[1]), q(b[2]), t, o);
324
358
  return [o[0], o[1], o[2]];
325
359
  }
326
360
  return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
@@ -339,7 +373,7 @@ function multiColorForDab(mc, palette, index, seed, mixing) {
339
373
  const n = palette.length;
340
374
  if (mc.order === "random") {
341
375
  const run = Math.floor(index / mc.length);
342
- return [...palette[Math.min(n - 1, Math.floor(_chunkPQ3H2AANcjs.rand01.call(void 0, seed, run, 11) * n))]];
376
+ return [...palette[Math.min(n - 1, Math.floor(_chunk3K6HWEXZcjs.rand01.call(void 0, seed, run, 11) * n))]];
343
377
  }
344
378
  const f = index / mc.length % n;
345
379
  const i = Math.floor(f);
@@ -349,24 +383,24 @@ var PaintDabStroke = (_class = class {
349
383
  constructor(brush, options) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);
350
384
  this.brush = brush;
351
385
  this.options = options;
352
- this.smoother = new (0, _chunkQ2UYUWAZcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
353
- this.copies = _optionalChain([options, 'access', _2 => _2.copies, 'optionalAccess', _3 => _3.length]) ? options.copies : [_chunkQ2UYUWAZcjs.IDENTITY_COPY];
386
+ this.smoother = new (0, _chunkH4AOUUBEcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
387
+ this.copies = _optionalChain([options, 'access', _2 => _2.copies, 'optionalAccess', _3 => _3.length]) ? options.copies : [_chunkH4AOUUBEcjs.IDENTITY_COPY];
354
388
  const exchanging = brush.engine === "mixer" || brush.engine === "dab";
355
- const rates = brush.engine === "mixer" ? _chunkPQ3H2AANcjs.mixerRates.call(void 0, brush.mixer) : _chunkPQ3H2AANcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, 1, brush.behavior.mixing);
389
+ const rates = brush.engine === "mixer" ? _chunkI7NJPHWVcjs.mixerRates.call(void 0, brush.mixer) : _chunkI7NJPHWVcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, 1, brush.behavior.mixing);
356
390
  this.mixing = brush.engine === "mixer" ? brush.mixer.mixing : brush.behavior.mixing;
357
391
  this.states = this.copies.map((c, i) => ({
358
- walker: new (0, _chunkQ2UYUWAZcjs.PenDabWalker)(brush, (_nullishCoalesce(options.seed, () => ( 0))) + i * 7919 | 0, c.linear),
359
- exchange: exchanging ? new (0, _chunkPQ3H2AANcjs.PaintExchange)(rates, options.load) : null,
360
- smudge: brush.engine === "smudge" ? new (0, _chunkPQ3H2AANcjs.SmudgeTip)(brush.smudge, brush.tip.size * (1 + brush.dynamics.tiltSize * 1.5)) : null
392
+ walker: new (0, _chunkH4AOUUBEcjs.PenDabWalker)(brush, (_nullishCoalesce(options.seed, () => ( 0))) + i * 7919 | 0, c.linear),
393
+ exchange: exchanging ? new (0, _chunkI7NJPHWVcjs.PaintExchange)(rates, options.load) : null,
394
+ smudge: brush.engine === "smudge" ? new (0, _chunkI7NJPHWVcjs.SmudgeTip)(brush.smudge, brush.tip.size * (1 + brush.dynamics.tiltSize * 1.5)) : null
361
395
  }));
362
- this.medium = new (0, _chunkPQ3H2AANcjs.TileMedium)(options.target, brush.engine === "dab" ? { blend: brush.tip.blend } : {});
396
+ this.medium = new (0, _chunkI7NJPHWVcjs.TileMedium)(options.target, brush.engine === "dab" ? { blend: brush.tip.blend } : {});
363
397
  this.depth = options.grain && !options.grain.flat ? Math.min(1, Math.max(0, options.paperDepth * brush.grain)) : 0;
364
- this.coverage = brush.engine === "dab" ? new (0, _chunkPQ3H2AANcjs.CoverageMap)() : null;
365
- this.sampler = exchanging && options.paint ? new (0, _chunkPQ3H2AANcjs.PaintGradientSampler)(options.paint, _nullishCoalesce(options.seed, () => ( 0))) : null;
398
+ this.coverage = brush.engine === "dab" ? new (0, _chunkI7NJPHWVcjs.CoverageMap)() : null;
399
+ this.sampler = exchanging && options.paint ? new (0, _chunkI7NJPHWVcjs.PaintGradientSampler)(options.paint, _nullishCoalesce(options.seed, () => ( 0))) : null;
366
400
  const table = _optionalChain([this, 'access', _4 => _4.sampler, 'optionalAccess', _5 => _5.acrossTip]) ? this.sampler.tipTable(GRADIENT_STEPS) : null;
367
401
  this.gradient = table ? table.map((e) => e.rgb) : null;
368
402
  this.gradientAlpha = table && table.some((e) => e.alpha < 1) ? table.map((e) => e.alpha) : null;
369
- this.scratch = brush.engine === "blender" ? _chunkPQ3H2AANcjs.createBlenderScratch.call(void 0, ) : null;
403
+ this.scratch = brush.engine === "blender" ? _chunkI7NJPHWVcjs.createBlenderScratch.call(void 0, ) : null;
370
404
  }
371
405
 
372
406
 
@@ -425,7 +459,7 @@ var PaintDabStroke = (_class = class {
425
459
  }
426
460
  paintDabs(copy, dabs, rects) {
427
461
  for (const d of dabs) {
428
- const rect = _chunkPQ3H2AANcjs.dabRect.call(void 0, d, this.brush.tip.hardness);
462
+ const rect = _chunkI7NJPHWVcjs.dabRect.call(void 0, d, this.brush.tip.hardness);
429
463
  if (rect.width <= 0 || rect.height <= 0) continue;
430
464
  this.dab(copy, d, rect);
431
465
  rects.push(rect);
@@ -441,13 +475,13 @@ var PaintDabStroke = (_class = class {
441
475
  }
442
476
  const tip = this.tip.subarray(0, n);
443
477
  tip.fill(0);
444
- _chunkPQ3H2AANcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.tip.hardness, rect, tip);
478
+ _chunkI7NJPHWVcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.tip.hardness, rect, tip);
445
479
  if (!(this.depth > 0 && this.options.grain)) return { tip, cov: tip };
446
480
  const cov = this.cov.subarray(0, n);
447
481
  const grain = this.options.grain;
448
482
  for (let yy = 0, k = 0; yy < rect.height; yy++) {
449
483
  const y = rect.y + yy + 0.5;
450
- for (let xx = 0; xx < rect.width; xx++, k++) cov[k] = tip[k] > 0 ? tip[k] * _chunkPQ3H2AANcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure) : 0;
484
+ for (let xx = 0; xx < rect.width; xx++, k++) cov[k] = tip[k] > 0 ? tip[k] * _chunkI7NJPHWVcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure) : 0;
451
485
  }
452
486
  return { tip, cov };
453
487
  }
@@ -456,7 +490,7 @@ var PaintDabStroke = (_class = class {
456
490
  const { tip, cov } = this.rasterize(d, rect);
457
491
  const st = this.states[copy];
458
492
  if (brush.engine === "blender") {
459
- _chunkPQ3H2AANcjs.blenderDab.call(void 0, this.medium, rect, cov, d.opacity * d.alpha * brush.tip.opacity, d.radius, brush.blender, this.scratch);
493
+ _chunkI7NJPHWVcjs.blenderDab.call(void 0, this.medium, rect, cov, d.opacity * d.alpha * brush.tip.opacity, d.radius, brush.blender, this.scratch);
460
494
  return;
461
495
  }
462
496
  if (brush.engine === "smudge") {
@@ -468,7 +502,7 @@ var PaintDabStroke = (_class = class {
468
502
  let flow = 1;
469
503
  if (this.options.effect) {
470
504
  const rgb = [0, 0, 0];
471
- flow = _chunkQ2UYUWAZcjs.sampleEffectAt.call(void 0, this.options.effect, d.x, d.y, rgb, d);
505
+ flow = _chunkH4AOUUBEcjs.sampleEffectAt.call(void 0, this.options.effect, d.x, d.y, rgb, d);
472
506
  ex.setReservoirColor(rgb[0], rgb[1], rgb[2]);
473
507
  } else if (this.sampler && !this.gradient) {
474
508
  const g = this.sampler.dab(d, this.sample);
@@ -636,10 +670,10 @@ function lightTile(color, height, heightAround, material, light) {
636
670
  const nh = Math.max(0, nx * hx + ny * hy + nz * hz);
637
671
  const spec = Math.max(0, Math.pow(nh, shininess) - Math.pow(hz, shininess)) * (0.25 + 0.75 * gloss) * light.relief;
638
672
  for (let c = 0; c < 3; c++) {
639
- const a = _chunkVMROIWLLcjs.SRGB_TO_LINEAR[color[i + c]];
673
+ const a = _chunkKBYB7OWBcjs.SRGB_TO_LINEAR[color[i + c]];
640
674
  const tint = metal * a + (1 - metal);
641
675
  const v = a * shade * (1 - 0.35 * metal) + spec * tint * (1 + metal);
642
- out[i + c] = _chunkVMROIWLLcjs.linearToSrgb8.call(void 0, v);
676
+ out[i + c] = _chunkKBYB7OWBcjs.linearToSrgb8.call(void 0, v);
643
677
  }
644
678
  }
645
679
  }
@@ -699,19 +733,19 @@ var ThickStrokeDriver = (_class3 = class {
699
733
  constructor(init) {;_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);
700
734
  this.init = init;
701
735
  const b = init.brush;
702
- this.smoother = new (0, _chunkQ2UYUWAZcjs.PenSmoother)(b.tip.smoothing, b.pressureSmoothing);
703
- const copies = init.copies.length ? init.copies : [_chunkQ2UYUWAZcjs.IDENTITY_COPY];
736
+ this.smoother = new (0, _chunkH4AOUUBEcjs.PenSmoother)(b.tip.smoothing, b.pressureSmoothing);
737
+ const copies = init.copies.length ? init.copies : [_chunkH4AOUUBEcjs.IDENTITY_COPY];
704
738
  this.copies = copies;
705
- const rates = _chunkPQ3H2AANcjs.exchangeRates.call(void 0, b.behavior.pickup, b.behavior.mix, 1, b.behavior.mixing);
739
+ const rates = _chunkI7NJPHWVcjs.exchangeRates.call(void 0, b.behavior.pickup, b.behavior.mix, 1, b.behavior.mixing);
706
740
  this.states = copies.map((c, i) => ({
707
- walker: new (0, _chunkQ2UYUWAZcjs.PenDabWalker)(b, init.seed + i * 7919 | 0, c.linear),
708
- exchange: new (0, _chunkPQ3H2AANcjs.PaintExchange)(rates, init.load),
709
- smudge: b.impasto.tool === "knife" ? new (0, _chunkPQ3H2AANcjs.SmudgeTip)({ strength: 0.85, length: 0.6 + 0.38 * b.impasto.drag, mixing: b.behavior.mixing }, b.tip.size * 1.2) : null,
741
+ walker: new (0, _chunkH4AOUUBEcjs.PenDabWalker)(b, init.seed + i * 7919 | 0, c.linear),
742
+ exchange: new (0, _chunkI7NJPHWVcjs.PaintExchange)(rates, init.load),
743
+ smudge: b.impasto.tool === "knife" ? new (0, _chunkI7NJPHWVcjs.SmudgeTip)({ strength: 0.85, length: 0.6 + 0.38 * b.impasto.drag, mixing: b.behavior.mixing }, b.tip.size * 1.2) : null,
710
744
  carried: null,
711
745
  amount: 1
712
746
  }));
713
- this.medium = new (0, _chunkPQ3H2AANcjs.TileMedium)(init.target, {});
714
- this.sampler = init.paint ? new (0, _chunkPQ3H2AANcjs.PaintGradientSampler)(init.paint.map.by === "across-tip" ? { ...init.paint, map: { by: "distance", length: 300, repeat: "mirror" } } : init.paint, init.seed) : null;
747
+ this.medium = new (0, _chunkI7NJPHWVcjs.TileMedium)(init.target, {});
748
+ this.sampler = init.paint ? new (0, _chunkI7NJPHWVcjs.PaintGradientSampler)(init.paint.map.by === "across-tip" ? { ...init.paint, map: { by: "distance", length: 300, repeat: "mirror" } } : init.paint, init.seed) : null;
715
749
  }
716
750
 
717
751
  __init12() {this.dabCount = 0}
@@ -808,7 +842,7 @@ var ThickStrokeDriver = (_class3 = class {
808
842
  }
809
843
  applyDabs(copy, dabs, rects) {
810
844
  for (const d of dabs) {
811
- const rect = _chunkPQ3H2AANcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
845
+ const rect = _chunkI7NJPHWVcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
812
846
  if (rect.width <= 0 || rect.height <= 0) continue;
813
847
  this.dab(copy, d, rect);
814
848
  rects.push(rect);
@@ -823,7 +857,7 @@ var ThickStrokeDriver = (_class3 = class {
823
857
  const n = rect.width * rect.height;
824
858
  if (this.tip.length < n) this.tip = new Float32Array(n);
825
859
  const tip = this.tip.subarray(0, n);
826
- _chunkPQ3H2AANcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, b.tip.hardness, rect, tip);
860
+ _chunkI7NJPHWVcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, b.tip.hardness, rect, tip);
827
861
  const sel = this.init.target.selection;
828
862
  if (sel) {
829
863
  for (let yy = 0, p = 0; yy < rect.height; yy++)
@@ -850,7 +884,7 @@ var ThickStrokeDriver = (_class3 = class {
850
884
  let flow = 1;
851
885
  const effect = this.init.effect;
852
886
  if (effect) {
853
- _chunkQ2UYUWAZcjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
887
+ _chunkH4AOUUBEcjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
854
888
  ex.setReservoirColor(this.centre[0], this.centre[1], this.centre[2]);
855
889
  } else if (this.sampler) {
856
890
  const g = this.sampler.dab(d, this.sample);
@@ -867,7 +901,7 @@ var ThickStrokeDriver = (_class3 = class {
867
901
  let field = null;
868
902
  if (effect) {
869
903
  field = new Float32Array(n * 3);
870
- _chunkQ2UYUWAZcjs.effectDabField.call(void 0, effect, rect, cov, this.centre, this.paint, field, 0, d);
904
+ _chunkH4AOUUBEcjs.effectDabField.call(void 0, effect, rect, cov, this.centre, this.paint, field, 0, d);
871
905
  }
872
906
  this.medium.deposit(rect, cov, dep, this.paint, ex.paintPigment, field);
873
907
  }
@@ -886,7 +920,7 @@ var ThickStrokeDriver = (_class3 = class {
886
920
  const full2 = 255 * thick * k;
887
921
  switch (im.tool) {
888
922
  case "brush": {
889
- const ridge = 0.6 + 0.4 * Math.sin(u * 9 + _chunkPQ3H2AANcjs.hash2.call(void 0, Math.round(u * 6), 3, seed) * 6.28) + 0.15 * (_chunkPQ3H2AANcjs.hash2.call(void 0, lx, ly, seed) - 0.5);
923
+ const ridge = 0.6 + 0.4 * Math.sin(u * 9 + _chunk3K6HWEXZcjs.hash2.call(void 0, Math.round(u * 6), 3, seed) * 6.28) + 0.15 * (_chunk3K6HWEXZcjs.hash2.call(void 0, lx, ly, seed) - 0.5);
890
924
  const target = full2 * c * ridge;
891
925
  h = Math.max(h0 * (1 - 0.25 * c * im.drag), Math.min(255, h0 * 0.35 + target));
892
926
  break;
@@ -902,7 +936,7 @@ var ThickStrokeDriver = (_class3 = class {
902
936
  break;
903
937
  }
904
938
  case "roller": {
905
- const stipple = 0.75 + 0.5 * _chunkPQ3H2AANcjs.hash2.call(void 0, lx >> 1, ly >> 1, seed);
939
+ const stipple = 0.75 + 0.5 * _chunk3K6HWEXZcjs.hash2.call(void 0, lx >> 1, ly >> 1, seed);
906
940
  h = h0 + (Math.min(255, full2 * 0.6 * stipple) - h0) * Math.min(1, c * 1.5);
907
941
  break;
908
942
  }
@@ -974,15 +1008,15 @@ function reliefInfo(ch) {
974
1008
  function thickToJSON(ch) {
975
1009
  const b = ch.height.bounds;
976
1010
  if (!b) return null;
977
- return { rect: { ...b }, height: _chunkOLNIPTB3cjs.pngDataUrl.call(void 0, b.width, b.height, _chunk474IQG74cjs.readRegion.call(void 0, ch.height, b), 1), material: _chunkOLNIPTB3cjs.pngDataUrl.call(void 0, b.width, b.height, _chunk474IQG74cjs.readRegion.call(void 0, ch.material, b), 4) };
1011
+ return { rect: { ...b }, height: _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, b.width, b.height, _chunk474IQG74cjs.readRegion.call(void 0, ch.height, b), 1), material: _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, b.width, b.height, _chunk474IQG74cjs.readRegion.call(void 0, ch.material, b), 4) };
978
1012
  }
979
1013
  function thickFromJSON(raw) {
980
1014
  const r = raw;
981
1015
  if (!r || typeof r !== "object" || !r.rect || typeof r.height !== "string" || typeof r.material !== "string") throw new Error("not saved thick-paint channels");
982
1016
  const decode = (url, gray) => {
983
- const parsed = _chunkOLNIPTB3cjs.parseDataUrl.call(void 0, url);
1017
+ const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, url);
984
1018
  if (!parsed) throw new Error("a channel is not a PNG data URL");
985
- return _chunkOLNIPTB3cjs.decodePng.call(void 0, parsed.bytes, { keepGray: gray });
1019
+ return _chunkW5M3J7PVcjs.decodePng.call(void 0, parsed.bytes, { keepGray: gray });
986
1020
  };
987
1021
  const h = decode(r.height, true);
988
1022
  const m = decode(r.material, false);
@@ -1044,7 +1078,7 @@ function shadowToLight(shadow) {
1044
1078
  return new (0, _chunk474IQG74cjs.TiledSurface)(1, tiles, 0);
1045
1079
  }
1046
1080
  function lightTwinBrush(brush) {
1047
- return _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0,
1081
+ return _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0,
1048
1082
  {
1049
1083
  tip: { ...brush.tip, blend: "normal", pressureOpacity: brush.tip.pressureOpacity || brush.light.pressure },
1050
1084
  behavior: { ...brush.behavior, mixing: "rgb" },
@@ -1236,14 +1270,14 @@ function boxBlur(p, w, h, r) {
1236
1270
  function lightToJSON(light) {
1237
1271
  const b = lightInfo(light).bounds;
1238
1272
  if (!b) return null;
1239
- return { rect: { ...b }, light: _chunkOLNIPTB3cjs.pngDataUrl.call(void 0, b.width, b.height, _chunk474IQG74cjs.readRegion.call(void 0, light, b), 1) };
1273
+ return { rect: { ...b }, light: _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, b.width, b.height, _chunk474IQG74cjs.readRegion.call(void 0, light, b), 1) };
1240
1274
  }
1241
1275
  function lightFromJSON(raw) {
1242
1276
  const r = raw;
1243
1277
  if (!r || typeof r !== "object" || !r.rect || typeof r.light !== "string") throw new Error("not a saved light channel");
1244
- const parsed = _chunkOLNIPTB3cjs.parseDataUrl.call(void 0, r.light);
1278
+ const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, r.light);
1245
1279
  if (!parsed) throw new Error("the light is not a PNG data URL");
1246
- const img = _chunkOLNIPTB3cjs.decodePng.call(void 0, parsed.bytes, { keepGray: true });
1280
+ const img = _chunkW5M3J7PVcjs.decodePng.call(void 0, parsed.bytes, { keepGray: true });
1247
1281
  const data = img.channels === 1 ? img.data : Uint8ClampedArray.from({ length: img.width * img.height }, (_, i) => img.data[i * 4]);
1248
1282
  return _chunk474IQG74cjs.surfaceFromPixels.call(void 0, { width: img.width, height: img.height, data }, 1, r.rect.x, r.rect.y);
1249
1283
  }
@@ -1274,7 +1308,7 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1274
1308
  this.layerId = init.layerId;
1275
1309
  this.base = init.surface;
1276
1310
  this.live = new Map(this.base.tiles);
1277
- this.copies = init.copies.length ? init.copies : [_chunkQ2UYUWAZcjs.IDENTITY_COPY];
1311
+ this.copies = init.copies.length ? init.copies : [_chunkH4AOUUBEcjs.IDENTITY_COPY];
1278
1312
  const brush = init.brush;
1279
1313
  if (init.wet) this.wetDriver = init.wet.driver;
1280
1314
  if (init.light && !init.wet && !init.sticker) this.lightTwin = this.makeLightTwin(init.light.surface);
@@ -1291,11 +1325,11 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1291
1325
  };
1292
1326
  if (this.wetDriver) {
1293
1327
  } else if (init.sticker) {
1294
- this.stickerSpray = new (0, _chunkQ2UYUWAZcjs.StickerSpray)({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: _nullishCoalesce(init.paint, () => ( null)), effect });
1328
+ this.stickerSpray = new (0, _chunkH4AOUUBEcjs.StickerSpray)({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: _nullishCoalesce(init.paint, () => ( null)), effect, art: init.sticker.art });
1295
1329
  } else if (init.thick) {
1296
1330
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
1297
1331
  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 });
1298
- } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunkQ2UYUWAZcjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
1332
+ } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunkH4AOUUBEcjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
1299
1333
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
1300
1334
  this.wet = new PaintDabStroke(brush, {
1301
1335
  target: this.tileTarget(),
@@ -1311,7 +1345,7 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1311
1345
  });
1312
1346
  } else {
1313
1347
  const opts = { grain: init.grain, paperDepth: init.paperDepth, seed: init.seed, copies: this.copies, paint: _nullishCoalesce(init.paint, () => ( null)), effect };
1314
- this.dry = brush.engine === "particle" ? new (0, _chunkQ2UYUWAZcjs.ParticleStroke)(brush, opts) : brush.engine === "bristle" ? new (0, _chunkQ2UYUWAZcjs.BristleStroke)(brush, opts) : new (0, _chunkQ2UYUWAZcjs.DryStroke)(brush, opts);
1348
+ this.dry = brush.engine === "particle" ? new (0, _chunkH4AOUUBEcjs.ParticleStroke)(brush, opts) : brush.engine === "bristle" ? new (0, _chunkH4AOUUBEcjs.BristleStroke)(brush, opts) : new (0, _chunkH4AOUUBEcjs.DryStroke)(brush, opts);
1315
1349
  }
1316
1350
  }
1317
1351
 
@@ -1440,7 +1474,7 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1440
1474
  const changed = d.dabCount > 0;
1441
1475
  this.result = { layerId: this.layerId, bounds: changed ? d.bounds : null, dabs: d.dabCount, strokeId: null, wet: true };
1442
1476
  const carried = d.load;
1443
- if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkPQ3H2AANcjs.cleanMixer.call(void 0, carried);
1477
+ if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkI7NJPHWVcjs.cleanMixer.call(void 0, carried);
1444
1478
  this.host.commit(this, changed ? this.init.wet.surface() : null, false);
1445
1479
  }
1446
1480
  update(rects) {
@@ -1466,7 +1500,7 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1466
1500
  const src = _nullishCoalesce(_optionalChain([this, 'access', _53 => _53.base, 'access', _54 => _54.tiles, 'access', _55 => _55.get, 'call', _56 => _56(key), 'optionalAccess', _57 => _57.data]), () => ( defaultTile(this.base)));
1467
1501
  const prev = this.touched.has(key) ? _optionalChain([this, 'access', _58 => _58.live, 'access', _59 => _59.get, 'call', _60 => _60(key), 'optionalAccess', _61 => _61.data]) : void 0;
1468
1502
  this.touched.add(key);
1469
- const data = _chunkPQ3H2AANcjs.applyStrokeToTile.call(void 0, this.dry.coverage, src, ch, tx, ty, this.apply, prev ? { into: prev, region: r } : {});
1503
+ const data = _chunkI7NJPHWVcjs.applyStrokeToTile.call(void 0, this.dry.coverage, src, ch, tx, ty, this.apply, prev ? { into: prev, region: r } : {});
1470
1504
  this.live.set(key, { data, uniform: null });
1471
1505
  }
1472
1506
  this.host.update(this.layerId, new (0, _chunk474IQG74cjs.TiledSurface)(ch, new Map(this.live), this.base.defaultValue), rects);
@@ -1501,8 +1535,9 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1501
1535
  const surface = changed ? new (0, _chunk474IQG74cjs.TiledSurface)(ch, tiles, this.base.defaultValue) : null;
1502
1536
  const dabs = this.dry ? this.dry.dabCount : this.thickDriver ? this.thickDriver.dabCount : this.stickerSpray ? this.stickerSpray.dabCount : this.wet.dabCount;
1503
1537
  this.result = { layerId: this.layerId, bounds: changed ? this.bounds : null, dabs, strokeId: null };
1504
- const carried = _nullishCoalesce(_optionalChain([this, 'access', _64 => _64.wet, 'optionalAccess', _65 => _65.load]), () => ( _optionalChain([this, 'access', _66 => _66.thickDriver, 'optionalAccess', _67 => _67.load])));
1505
- if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkPQ3H2AANcjs.cleanMixer.call(void 0, carried);
1538
+ if (_optionalChain([this, 'access', _64 => _64.stickerSpray, 'optionalAccess', _65 => _65.skipped, 'access', _66 => _66.size])) this.result.skippedStickers = [...this.stickerSpray.skipped];
1539
+ const carried = _nullishCoalesce(_optionalChain([this, 'access', _67 => _67.wet, 'optionalAccess', _68 => _68.load]), () => ( _optionalChain([this, 'access', _69 => _69.thickDriver, 'optionalAccess', _70 => _70.load])));
1540
+ if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkI7NJPHWVcjs.cleanMixer.call(void 0, carried);
1506
1541
  this.host.commit(this, surface, false);
1507
1542
  return this.result;
1508
1543
  }
@@ -1510,7 +1545,7 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1510
1545
  cancel() {
1511
1546
  if (this.closed) return;
1512
1547
  this.closed = true;
1513
- if (_optionalChain([this, 'access', _68 => _68.lightTwin, 'optionalAccess', _69 => _69.open])) this.lightTwin.cancel();
1548
+ if (_optionalChain([this, 'access', _71 => _71.lightTwin, 'optionalAccess', _72 => _72.open])) this.lightTwin.cancel();
1514
1549
  this.lightResult = null;
1515
1550
  this.host.commit(this, null, true);
1516
1551
  }
@@ -1525,15 +1560,15 @@ function greyPixels(data, grey) {
1525
1560
  }
1526
1561
  function mixerLoadForStroke(brush, current, color) {
1527
1562
  if (!brush.loadsColor) return { reservoir: null, amount: 0, pickup: brush.mixer.cleanEachStroke ? null : current.pickup };
1528
- if (brush.mixer.loadEachStroke || !current.reservoir) return _chunkPQ3H2AANcjs.loadMixer.call(void 0, current, color);
1563
+ if (brush.mixer.loadEachStroke || !current.reservoir) return _chunkI7NJPHWVcjs.loadMixer.call(void 0, current, color);
1529
1564
  return current;
1530
1565
  }
1531
1566
  function brushLoadForStroke(brush, current, color) {
1532
1567
  if (brush.engine === "mixer") return mixerLoadForStroke(brush, current, color);
1533
1568
  if (brush.engine === "impasto") return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1534
- 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 } : _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD;
1535
- if (_chunkQ2UYUWAZcjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1536
- return _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD;
1569
+ 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 } : _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD;
1570
+ if (_chunkH4AOUUBEcjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1571
+ return _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD;
1537
1572
  }
1538
1573
 
1539
1574
  // src/paint-editor/stencils.ts
@@ -1542,36 +1577,36 @@ var STENCIL_SHAPES = ["rect", "ellipse", "polygon"];
1542
1577
  var finite = (v) => typeof v === "number" && Number.isFinite(v);
1543
1578
  var pt = (p) => p && finite(p.x) && finite(p.y) ? { x: p.x, y: p.y } : void 0;
1544
1579
  function normalizeStencil(raw, id, base) {
1545
- const kind = STENCIL_KINDS.includes(raw.kind) ? raw.kind : _optionalChain([base, 'optionalAccess', _70 => _70.kind]);
1580
+ const kind = STENCIL_KINDS.includes(raw.kind) ? raw.kind : _optionalChain([base, 'optionalAccess', _73 => _73.kind]);
1546
1581
  if (!kind) throw new Error(`kind ${JSON.stringify(raw.kind)} is not a stencil; use ${STENCIL_KINDS.join(", ")}.`);
1547
1582
  const s = {
1548
1583
  id,
1549
1584
  kind,
1550
- mode: raw.mode === "guide" || raw.mode === "mask" ? raw.mode : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _71 => _71.mode]), () => ( (kind === "ruler" || kind === "arc" ? "guide" : "mask"))),
1551
- enabled: typeof raw.enabled === "boolean" ? raw.enabled : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _72 => _72.enabled]), () => ( true)),
1552
- invert: typeof raw.invert === "boolean" ? raw.invert : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _73 => _73.invert]), () => ( false)),
1553
- snap: finite(raw.snap) ? Math.min(400, Math.max(1, raw.snap)) : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _74 => _74.snap]), () => ( 40)),
1554
- feather: finite(raw.feather) ? Math.min(100, Math.max(0, raw.feather)) : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _75 => _75.feather]), () => ( 1))
1585
+ mode: raw.mode === "guide" || raw.mode === "mask" ? raw.mode : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _74 => _74.mode]), () => ( (kind === "ruler" || kind === "arc" ? "guide" : "mask"))),
1586
+ enabled: typeof raw.enabled === "boolean" ? raw.enabled : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _75 => _75.enabled]), () => ( true)),
1587
+ invert: typeof raw.invert === "boolean" ? raw.invert : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _76 => _76.invert]), () => ( false)),
1588
+ snap: finite(raw.snap) ? Math.min(400, Math.max(1, raw.snap)) : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _77 => _77.snap]), () => ( 40)),
1589
+ feather: finite(raw.feather) ? Math.min(100, Math.max(0, raw.feather)) : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _78 => _78.feather]), () => ( 1))
1555
1590
  };
1556
1591
  if (kind === "ruler" || kind === "line") {
1557
- s.from = _nullishCoalesce(pt(raw.from), () => ( _optionalChain([base, 'optionalAccess', _76 => _76.from])));
1558
- s.to = _nullishCoalesce(pt(raw.to), () => ( _optionalChain([base, 'optionalAccess', _77 => _77.to])));
1592
+ s.from = _nullishCoalesce(pt(raw.from), () => ( _optionalChain([base, 'optionalAccess', _79 => _79.from])));
1593
+ s.to = _nullishCoalesce(pt(raw.to), () => ( _optionalChain([base, 'optionalAccess', _80 => _80.to])));
1559
1594
  if (!s.from || !s.to) throw new Error(`A ${kind} needs from and to points ({x, y} in document pixels).`);
1560
1595
  if (Math.hypot(s.to.x - s.from.x, s.to.y - s.from.y) < 1) throw new Error(`A ${kind}'s from and to must be at least 1 px apart.`);
1561
1596
  } else if (kind === "arc") {
1562
- s.center = _nullishCoalesce(pt(raw.center), () => ( _optionalChain([base, 'optionalAccess', _78 => _78.center])));
1563
- s.radius = finite(raw.radius) ? raw.radius : _optionalChain([base, 'optionalAccess', _79 => _79.radius]);
1597
+ s.center = _nullishCoalesce(pt(raw.center), () => ( _optionalChain([base, 'optionalAccess', _81 => _81.center])));
1598
+ s.radius = finite(raw.radius) ? raw.radius : _optionalChain([base, 'optionalAccess', _82 => _82.radius]);
1564
1599
  if (!s.center || !(s.radius > 0)) throw new Error("An arc needs a center ({x, y}) and a radius above 0.");
1565
- s.startAngle = finite(raw.startAngle) ? raw.startAngle : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _80 => _80.startAngle]), () => ( 0));
1566
- s.endAngle = finite(raw.endAngle) ? raw.endAngle : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _81 => _81.endAngle]), () => ( 360));
1600
+ s.startAngle = finite(raw.startAngle) ? raw.startAngle : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _83 => _83.startAngle]), () => ( 0));
1601
+ s.endAngle = finite(raw.endAngle) ? raw.endAngle : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _84 => _84.endAngle]), () => ( 360));
1567
1602
  } else {
1568
- s.shape = STENCIL_SHAPES.includes(raw.shape) ? raw.shape : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _82 => _82.shape]), () => ( "rect"));
1603
+ s.shape = STENCIL_SHAPES.includes(raw.shape) ? raw.shape : _nullishCoalesce(_optionalChain([base, 'optionalAccess', _85 => _85.shape]), () => ( "rect"));
1569
1604
  if (s.shape === "polygon") {
1570
- const pts = Array.isArray(raw.points) ? raw.points.map(pt).filter((p) => Boolean(p)) : _optionalChain([base, 'optionalAccess', _83 => _83.points]);
1605
+ const pts = Array.isArray(raw.points) ? raw.points.map(pt).filter((p) => Boolean(p)) : _optionalChain([base, 'optionalAccess', _86 => _86.points]);
1571
1606
  if (!pts || pts.length < 3) throw new Error("A polygon stencil needs at least 3 points.");
1572
1607
  s.points = pts;
1573
1608
  } else {
1574
- const r = _nullishCoalesce(raw.rect, () => ( _optionalChain([base, 'optionalAccess', _84 => _84.rect])));
1609
+ const r = _nullishCoalesce(raw.rect, () => ( _optionalChain([base, 'optionalAccess', _87 => _87.rect])));
1575
1610
  if (!r || !finite(r.x) || !finite(r.y) || !(r.width > 0) || !(r.height > 0)) throw new Error(`A ${s.shape} stencil needs rect {x, y, width, height} with a width and height above 0.`);
1576
1611
  s.rect = { x: r.x, y: r.y, width: r.width, height: r.height };
1577
1612
  }
@@ -1653,7 +1688,7 @@ var StencilSnapper = class {
1653
1688
  const { distance } = nearestOnStencil(s, p);
1654
1689
  if (distance <= s.snap && (!best || distance < best.d)) best = { s, d: distance };
1655
1690
  }
1656
- this.guide = _nullishCoalesce(_optionalChain([best, 'optionalAccess', _85 => _85.s]), () => ( null));
1691
+ this.guide = _nullishCoalesce(_optionalChain([best, 'optionalAccess', _88 => _88.s]), () => ( null));
1657
1692
  }
1658
1693
  if (!this.guide) return p;
1659
1694
  const q = nearestOnStencil(this.guide, p).point;
@@ -1800,7 +1835,7 @@ function normalizeBrushStroke(raw) {
1800
1835
  const out = {
1801
1836
  id: r.id,
1802
1837
  layerId: r.layerId,
1803
- brush: _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, _nullishCoalesce(r.brush, () => ( {}))),
1838
+ brush: _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, _nullishCoalesce(r.brush, () => ( {}))),
1804
1839
  color: typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : "#000000",
1805
1840
  points,
1806
1841
  seed: finite2(r.seed) ? r.seed | 0 : 0
@@ -1813,14 +1848,14 @@ function normalizeBrushStroke(raw) {
1813
1848
  const st = [];
1814
1849
  for (const raw2 of r.stencils) {
1815
1850
  try {
1816
- st.push(normalizeStencil(raw2, typeof _optionalChain([raw2, 'optionalAccess', _86 => _86.id]) === "string" ? raw2.id : "stencil"));
1851
+ st.push(normalizeStencil(raw2, typeof _optionalChain([raw2, 'optionalAccess', _89 => _89.id]) === "string" ? raw2.id : "stencil"));
1817
1852
  } catch (e2) {
1818
1853
  }
1819
1854
  }
1820
1855
  if (st.length) out.stencils = st;
1821
1856
  }
1822
- const effect = _chunkQ2UYUWAZcjs.readPaintEffectPaint.call(void 0, r.paint);
1823
- const paint = effect ? null : _chunkPQ3H2AANcjs.readPaintSource.call(void 0, r.paint);
1857
+ const effect = _chunkH4AOUUBEcjs.readPaintEffectPaint.call(void 0, r.paint);
1858
+ const paint = effect ? null : _chunkI7NJPHWVcjs.readPaintSource.call(void 0, r.paint);
1824
1859
  if (effect) out.paint = effect;
1825
1860
  else if (paint && paint.type === "gradient") out.paint = paint;
1826
1861
  if (Array.isArray(r.steps) && r.steps.length === points.length && r.steps.every((v) => Number.isInteger(v) && v >= 0)) out.steps = [...r.steps];
@@ -1859,11 +1894,11 @@ function varyStroke(stroke, m, v) {
1859
1894
  if (ps !== 1) q.pressure = Math.min(1, Math.max(0, (_nullishCoalesce(p.pressure, () => ( 1))) * ps));
1860
1895
  return q;
1861
1896
  });
1862
- const brush = s !== 1 ? _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
1897
+ const brush = s !== 1 ? _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
1863
1898
  const out = { ...stroke, brush, points };
1864
- if (_optionalChain([stroke, 'access', _87 => _87.paint, 'optionalAccess', _88 => _88.type]) === "gradient" && s !== 1) out.paint = _chunkPQ3H2AANcjs.scalePaintGradient.call(void 0, stroke.paint, s);
1865
- if (_optionalChain([stroke, 'access', _89 => _89.paint, 'optionalAccess', _90 => _90.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))) } };
1866
- if (_optionalChain([stroke, 'access', _91 => _91.copies, 'optionalAccess', _92 => _92.length])) {
1899
+ if (_optionalChain([stroke, 'access', _90 => _90.paint, 'optionalAccess', _91 => _91.type]) === "gradient" && s !== 1) out.paint = _chunkI7NJPHWVcjs.scalePaintGradient.call(void 0, stroke.paint, s);
1900
+ if (_optionalChain([stroke, 'access', _92 => _92.paint, 'optionalAccess', _93 => _93.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))) } };
1901
+ if (_optionalChain([stroke, 'access', _94 => _94.copies, 'optionalAccess', _95 => _95.length])) {
1867
1902
  const inv = invertAffine(m);
1868
1903
  out.copies = stroke.copies.map((c) => composeAffine(m, composeAffine(c, inv)));
1869
1904
  }
@@ -1882,7 +1917,7 @@ var paperNodes = /* @__PURE__ */ new WeakMap();
1882
1917
  function paperNode(paper, light) {
1883
1918
  let n = paperNodes.get(paper);
1884
1919
  const metal = (_nullishCoalesce(paper.metallic, () => ( 0))) > 0;
1885
- if (!n || metal && (_optionalChain([n, 'access', _93 => _93.light, 'optionalAccess', _94 => _94.azimuth]) !== _optionalChain([light, 'optionalAccess', _95 => _95.azimuth]) || _optionalChain([n, 'access', _96 => _96.light, 'optionalAccess', _97 => _97.elevation]) !== _optionalChain([light, 'optionalAccess', _98 => _98.elevation]))) {
1920
+ if (!n || metal && (_optionalChain([n, 'access', _96 => _96.light, 'optionalAccess', _97 => _97.azimuth]) !== _optionalChain([light, 'optionalAccess', _98 => _98.azimuth]) || _optionalChain([n, 'access', _99 => _99.light, 'optionalAccess', _100 => _100.elevation]) !== _optionalChain([light, 'optionalAccess', _101 => _101.elevation]))) {
1886
1921
  n = { type: "paper", id: PAPER_NODE_ID, name: "Paper", visible: true, opacity: 1, blend: "normal", paper, ...metal && light ? { light: { azimuth: light.azimuth, elevation: light.elevation } } : {} };
1887
1922
  paperNodes.set(paper, n);
1888
1923
  }
@@ -1894,7 +1929,7 @@ function paperGrain(paper) {
1894
1929
  const key = JSON.stringify([paper.pattern, paper.seed, paper.scale, paper.tiling, paper.dry, _nullishCoalesce(paper.offset, () => ( null))]);
1895
1930
  let g = grainCache.get(key);
1896
1931
  if (!g) {
1897
- g = new (0, _chunkPQ3H2AANcjs.PaperGrain)(paper, "dry");
1932
+ g = new (0, _chunkI7NJPHWVcjs.PaperGrain)(paper, "dry");
1898
1933
  if (grainCache.size > 16) grainCache.delete(grainCache.keys().next().value);
1899
1934
  grainCache.set(key, g);
1900
1935
  }
@@ -1904,7 +1939,7 @@ function paperTile(paper, r, light) {
1904
1939
  const key = `${paperKey(paper, light)}|${r.x},${r.y},${r.width},${r.height}`;
1905
1940
  let t = tileCache.get(key);
1906
1941
  if (!t) {
1907
- t = _chunkQ2UYUWAZcjs.renderPaper.call(void 0, paper, r, paperGrain(paper), light);
1942
+ t = _chunkH4AOUUBEcjs.renderPaper.call(void 0, paper, r, paperGrain(paper), light);
1908
1943
  if (tileCache.size > 512) tileCache.delete(tileCache.keys().next().value);
1909
1944
  tileCache.set(key, t);
1910
1945
  }
@@ -1933,7 +1968,7 @@ var PROFILE = {
1933
1968
  }
1934
1969
  };
1935
1970
  function createPaintCompositor() {
1936
- return new (0, _chunkHB4ICNNAcjs.RasterCompositor)(PROFILE);
1971
+ return new (0, _chunkDPYAO5U6cjs.RasterCompositor)(PROFILE);
1937
1972
  }
1938
1973
  function downsampleRgba(data, width, height, tw, th) {
1939
1974
  tw = Math.max(1, Math.round(tw));
@@ -2003,17 +2038,17 @@ function header(state, options) {
2003
2038
  if (options.swatches !== void 0) out.swatches = JSON.parse(JSON.stringify(options.swatches));
2004
2039
  if (options.mixingPad !== void 0) out.mixingPad = JSON.parse(JSON.stringify(options.mixingPad));
2005
2040
  if (options.wet !== void 0) out.wet = JSON.parse(JSON.stringify(options.wet));
2006
- if (_optionalChain([state, 'access', _99 => _99.wetEvents, 'optionalAccess', _100 => _100.length])) out.wetEvents = JSON.parse(JSON.stringify(state.wetEvents));
2007
- if (_optionalChain([state, 'access', _101 => _101.paintEvents, 'optionalAccess', _102 => _102.length])) out.paintEvents = JSON.parse(JSON.stringify(state.paintEvents));
2041
+ if (_optionalChain([state, 'access', _102 => _102.wetEvents, 'optionalAccess', _103 => _103.length])) out.wetEvents = JSON.parse(JSON.stringify(state.wetEvents));
2042
+ if (_optionalChain([state, 'access', _104 => _104.paintEvents, 'optionalAccess', _105 => _105.length])) out.paintEvents = JSON.parse(JSON.stringify(state.paintEvents));
2008
2043
  if (state.origin && (state.origin.x || state.origin.y)) out.origin = { ...state.origin };
2009
2044
  return out;
2010
2045
  }
2011
2046
  function serializePaintDocument(state, options = {}) {
2012
- const { layers, assets } = _chunkXTWXBQD4cjs.serializeLayers.call(void 0, state.layers);
2047
+ const { layers, assets } = _chunkLP2MCSBEcjs.serializeLayers.call(void 0, state.layers);
2013
2048
  return { ...header(state, options), layers, assets };
2014
2049
  }
2015
2050
  async function serializePaintDocumentExternal(state, store, options = {}) {
2016
- const { layers, assets } = await _chunkXTWXBQD4cjs.serializeLayersExternal.call(void 0, state.layers, store);
2051
+ const { layers, assets } = await _chunkLP2MCSBEcjs.serializeLayersExternal.call(void 0, state.layers, store);
2017
2052
  return { ...header(state, options), layers, assets };
2018
2053
  }
2019
2054
  function paintLayersOnly(layers, problems) {
@@ -2021,7 +2056,7 @@ function paintLayersOnly(layers, problems) {
2021
2056
  for (const l of layers) {
2022
2057
  if (l.type === "pixel") {
2023
2058
  const { filters, source, ...rest } = l;
2024
- if (_optionalChain([filters, 'optionalAccess', _103 => _103.length])) problems.push(`Layer "${l.name}": its filters are an image editor feature and were dropped.`);
2059
+ if (_optionalChain([filters, 'optionalAccess', _106 => _106.length])) problems.push(`Layer "${l.name}": its filters are an image editor feature and were dropped.`);
2025
2060
  if (source) problems.push(`Layer "${l.name}" refers to an image editor source image; it loads empty.`);
2026
2061
  out.push(rest);
2027
2062
  } else if (l.type === "group") out.push({ ...l, children: paintLayersOnly(l.children, problems) });
@@ -2048,11 +2083,11 @@ function deserializePaintDocument(raw) {
2048
2083
  }
2049
2084
  const problems = [];
2050
2085
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
2051
- const paper = _chunkQ2UYUWAZcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
2086
+ const paper = _chunkH4AOUUBEcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
2052
2087
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
2053
- const layers = paintLayersOnly(_chunkXTWXBQD4cjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
2088
+ const layers = paintLayersOnly(_chunkLP2MCSBEcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
2054
2089
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
2055
- const activeLayerId = wanted && _chunkHB4ICNNAcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.flattenLayers.call(void 0, layers), 'access', _104 => _104.filter, 'call', _105 => _105((l) => l.type === "pixel"), 'access', _106 => _106.pop, 'call', _107 => _107(), 'optionalAccess', _108 => _108.id]), () => ( null));
2090
+ const activeLayerId = wanted && _chunkDPYAO5U6cjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.flattenLayers.call(void 0, layers), 'access', _107 => _107.filter, 'call', _108 => _108((l) => l.type === "pixel"), 'access', _109 => _109.pop, 'call', _110 => _110(), 'optionalAccess', _111 => _111.id]), () => ( null));
2056
2091
  const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
2057
2092
  const state = { canvas, paper, layers, activeLayerId, strokes: readStrokes(r.strokes, problems) };
2058
2093
  if (wetEvents.length) state.wetEvents = wetEvents;
@@ -2066,7 +2101,7 @@ async function deserializePaintDocumentAsync(raw, store) {
2066
2101
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
2067
2102
  const r = raw;
2068
2103
  const problems = [];
2069
- const assets = await _chunkXTWXBQD4cjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
2104
+ const assets = await _chunkLP2MCSBEcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
2070
2105
  const loaded = deserializePaintDocument({ ...r, assets });
2071
2106
  return { ...loaded, problems: [...problems, ...loaded.problems] };
2072
2107
  }
@@ -2143,13 +2178,13 @@ function viewPenToDocument(view, p) {
2143
2178
 
2144
2179
  // src/paint-editor/input.ts
2145
2180
  function samplePressure(e) {
2146
- return _chunkVMROIWLLcjs.pointerPressure.call(void 0, e);
2181
+ return _chunkKBYB7OWBcjs.pointerPressure.call(void 0, e);
2147
2182
  }
2148
2183
  function pointerToPenPoint(e, x, y, view) {
2149
2184
  const p = { x, y, pressure: samplePressure(e) };
2150
2185
  if (typeof e.timeStamp === "number" && Number.isFinite(e.timeStamp)) p.t = e.timeStamp;
2151
2186
  if (e.pointerType !== "pen") return p;
2152
- const o = _chunkQ2UYUWAZcjs.penOrientation.call(void 0, {
2187
+ const o = _chunkH4AOUUBEcjs.penOrientation.call(void 0, {
2153
2188
  x,
2154
2189
  y,
2155
2190
  altitude: typeof e.altitudeAngle === "number" ? e.altitudeAngle : void 0,
@@ -2197,7 +2232,7 @@ async function decodeImageBlob(blob) {
2197
2232
  if (!ctx) throw new Error("No 2D context to decode with.");
2198
2233
  ctx.drawImage(bitmap, 0, 0);
2199
2234
  const data = new Uint8ClampedArray(ctx.getImageData(0, 0, bitmap.width, bitmap.height).data);
2200
- _optionalChain([bitmap, 'access', _109 => _109.close, 'optionalCall', _110 => _110()]);
2235
+ _optionalChain([bitmap, 'access', _112 => _112.close, 'optionalCall', _113 => _113()]);
2201
2236
  return { width: bitmap.width, height: bitmap.height, data };
2202
2237
  }
2203
2238
  function downloadBytes(bytes, fileName, mimeType) {
@@ -2213,7 +2248,7 @@ function downloadBytes(bytes, fileName, mimeType) {
2213
2248
 
2214
2249
  // src/paint-editor/wet.ts
2215
2250
  var STROKE_WATER = 0.9;
2216
- var STROKE_MASS = _chunkVMROIWLLcjs.PIGMENT_UNIT * 2.5;
2251
+ var STROKE_MASS = _chunkKBYB7OWBcjs.PIGMENT_UNIT * 2.5;
2217
2252
  var STROKE_LIGHT = 1.5;
2218
2253
  var COVERAGE_STEPS = 4096;
2219
2254
  function union2(a, b) {
@@ -2223,13 +2258,13 @@ function union2(a, b) {
2223
2258
  return { x, y, width: Math.max(a.x + a.width, b.x + b.width) - x, height: Math.max(a.y + a.height, b.y + b.height) - y };
2224
2259
  }
2225
2260
  function wetPaperInput(paper) {
2226
- const grain = new (0, _chunkPQ3H2AANcjs.PaperGrain)(paper, "wet");
2261
+ const grain = new (0, _chunkI7NJPHWVcjs.PaperGrain)(paper, "wet");
2227
2262
  const flat = grain.flat;
2228
2263
  return {
2229
2264
  absorption: paper.absorption,
2230
2265
  permeability: paper.permeability,
2231
2266
  roughness: flat ? 0 : paper.roughness,
2232
- color: _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, paper.color),
2267
+ color: _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, paper.color),
2233
2268
  heightAt: flat ? () => 0.5 : (x, y) => grain.at(x, y)
2234
2269
  };
2235
2270
  }
@@ -2237,29 +2272,29 @@ var WetStrokeDriver = (_class6 = class {
2237
2272
  constructor(init) {;_class6.prototype.__init40.call(this);_class6.prototype.__init41.call(this);_class6.prototype.__init42.call(this);_class6.prototype.__init43.call(this);_class6.prototype.__init44.call(this);_class6.prototype.__init45.call(this);_class6.prototype.__init46.call(this);_class6.prototype.__init47.call(this);_class6.prototype.__init48.call(this);_class6.prototype.__init49.call(this);_class6.prototype.__init50.call(this);_class6.prototype.__init51.call(this);_class6.prototype.__init52.call(this);
2238
2273
  this.init = init;
2239
2274
  const brush = init.brush;
2240
- this.smoother = new (0, _chunkQ2UYUWAZcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
2241
- const copies = init.copies.length ? init.copies : [_chunkQ2UYUWAZcjs.IDENTITY_COPY];
2275
+ this.smoother = new (0, _chunkH4AOUUBEcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
2276
+ const copies = init.copies.length ? init.copies : [_chunkH4AOUUBEcjs.IDENTITY_COPY];
2242
2277
  const wet = brush.wet;
2243
2278
  const spacing = Math.max(0.02, brush.tip.spacing);
2244
2279
  const perDab = Math.min(1, spacing * 1.2);
2245
2280
  const thin = wet.thinner;
2246
- this.medium = new (0, _chunkVMROIWLLcjs.WetMedium)(init.world, init.laneId, {
2281
+ this.medium = new (0, _chunkKBYB7OWBcjs.WetMedium)(init.world, init.laneId, {
2247
2282
  water: STROKE_WATER * Math.min(1, wet.water * (1 + thin)) * perDab,
2248
2283
  mass: STROKE_MASS * wet.pigment * (1 - 0.6 * thin) * perDab,
2249
2284
  body: wet.body * (1 - thin),
2250
2285
  light: 0
2251
2286
  });
2252
2287
  this.lightBase = wet.tool === "paint" ? STROKE_LIGHT * brush.light.amount * (1 - 0.6 * thin) * perDab : 0;
2253
- const rates = _chunkPQ3H2AANcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
2288
+ const rates = _chunkI7NJPHWVcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
2254
2289
  this.states = copies.map((c, i) => ({
2255
- walker: new (0, _chunkQ2UYUWAZcjs.PenDabWalker)(brush, init.seed + i * 7919 | 0, c.linear),
2256
- exchange: wet.tool === "paint" ? new (0, _chunkPQ3H2AANcjs.PaintExchange)(rates, init.load) : null,
2290
+ walker: new (0, _chunkH4AOUUBEcjs.PenDabWalker)(brush, init.seed + i * 7919 | 0, c.linear),
2291
+ exchange: wet.tool === "paint" ? new (0, _chunkI7NJPHWVcjs.PaintExchange)(rates, init.load) : null,
2257
2292
  last: null
2258
2293
  }));
2259
2294
  this.copies = copies;
2260
2295
  this.depth = init.grain && !init.grain.flat ? Math.min(1, Math.max(0, init.paperDepth * brush.grain)) : 0;
2261
2296
  const g = _nullishCoalesce(init.paint, () => ( null));
2262
- this.sampler = g ? new (0, _chunkPQ3H2AANcjs.PaintGradientSampler)(g.map.by === "across-tip" ? { ...g, map: { by: "distance", length: 300, repeat: "mirror" } } : g, init.seed) : null;
2297
+ this.sampler = g ? new (0, _chunkI7NJPHWVcjs.PaintGradientSampler)(g.map.by === "across-tip" ? { ...g, map: { by: "distance", length: 300, repeat: "mirror" } } : g, init.seed) : null;
2263
2298
  }
2264
2299
 
2265
2300
  __init40() {this.dabCount = 0}
@@ -2285,7 +2320,7 @@ var WetStrokeDriver = (_class6 = class {
2285
2320
 
2286
2321
  /** What copy 0's brush carries after the dabs so far. */
2287
2322
  get load() {
2288
- return _nullishCoalesce(_optionalChain([this, 'access', _111 => _111.states, 'access', _112 => _112[0], 'access', _113 => _113.exchange, 'optionalAccess', _114 => _114.load]), () => ( null));
2323
+ return _nullishCoalesce(_optionalChain([this, 'access', _114 => _114.states, 'access', _115 => _115[0], 'access', _116 => _116.exchange, 'optionalAccess', _117 => _117.load]), () => ( null));
2289
2324
  }
2290
2325
  /** Whether every point (and the end) has been applied. */
2291
2326
  get done() {
@@ -2333,7 +2368,7 @@ var WetStrokeDriver = (_class6 = class {
2333
2368
  }
2334
2369
  applyDabs(copy, dabs, rects) {
2335
2370
  for (const d of dabs) {
2336
- const rect = _chunkPQ3H2AANcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
2371
+ const rect = _chunkI7NJPHWVcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
2337
2372
  if (rect.width <= 0 || rect.height <= 0) continue;
2338
2373
  this.dab(copy, d, rect);
2339
2374
  rects.push(rect);
@@ -2350,7 +2385,7 @@ var WetStrokeDriver = (_class6 = class {
2350
2385
  const tip = this.tip.subarray(0, n);
2351
2386
  const cov = this.cov.subarray(0, n);
2352
2387
  tip.fill(0);
2353
- _chunkPQ3H2AANcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.init.brush.tip.hardness, rect, tip);
2388
+ _chunkI7NJPHWVcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.init.brush.tip.hardness, rect, tip);
2354
2389
  const grain = this.depth > 0 ? this.init.grain : null;
2355
2390
  const mask = this.init.mask;
2356
2391
  for (let yy = 0, k = 0; yy < rect.height; yy++) {
@@ -2361,7 +2396,7 @@ var WetStrokeDriver = (_class6 = class {
2361
2396
  tip[k] *= mx >= 0 && my >= 0 && mx < mask.width && my < mask.height ? mask.data[my * mask.width + mx] / 255 : 0;
2362
2397
  }
2363
2398
  let v = tip[k];
2364
- if (v > 0 && grain) v *= _chunkPQ3H2AANcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, rect.y + yy + 0.5), this.depth, d.pressure);
2399
+ if (v > 0 && grain) v *= _chunkI7NJPHWVcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, rect.y + yy + 0.5), this.depth, d.pressure);
2365
2400
  tip[k] = Math.round(tip[k] * COVERAGE_STEPS) / COVERAGE_STEPS;
2366
2401
  cov[k] = Math.round(v * COVERAGE_STEPS) / COVERAGE_STEPS;
2367
2402
  }
@@ -2382,7 +2417,7 @@ var WetStrokeDriver = (_class6 = class {
2382
2417
  let flow = 1;
2383
2418
  const effect = this.init.effect;
2384
2419
  if (effect) {
2385
- _chunkQ2UYUWAZcjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
2420
+ _chunkH4AOUUBEcjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
2386
2421
  ex.setReservoirColor(this.centre[0], this.centre[1], this.centre[2]);
2387
2422
  } else if (this.sampler) {
2388
2423
  const g = this.sampler.dab(d, this.sample);
@@ -2394,7 +2429,7 @@ var WetStrokeDriver = (_class6 = class {
2394
2429
  if (total > 0 && flow > 0 && effect) {
2395
2430
  const ec = cov.slice();
2396
2431
  const field = new Float32Array(ec.length * 3);
2397
- _chunkQ2UYUWAZcjs.effectDabField.call(void 0, effect, rect, ec, this.centre, this.paint, field, COVERAGE_STEPS, d);
2432
+ _chunkH4AOUUBEcjs.effectDabField.call(void 0, effect, rect, ec, this.centre, this.paint, field, COVERAGE_STEPS, d);
2398
2433
  this.medium.deposit(rect, ec, Math.min(1, total) * k, this.paint, null, field);
2399
2434
  } else if (total > 0 && flow > 0) this.medium.deposit(rect, cov, Math.min(1, total) * k * flow, this.paint, null);
2400
2435
  else world.paint(laneId, rect, cov, this.medium.options.water * k, null);
@@ -2449,7 +2484,7 @@ var PaintWetLayers = (_class7 = class {
2449
2484
 
2450
2485
 
2451
2486
  __init53() {this.world = null}
2452
- __init54() {this.tilt = { ..._chunkVMROIWLLcjs.FLAT }}
2487
+ __init54() {this.tilt = { ..._chunkKBYB7OWBcjs.FLAT }}
2453
2488
  __init55() {this.settings = /* @__PURE__ */ new Map()}
2454
2489
  __init56() {this.paused = false}
2455
2490
  /** Wet strokes dry as soon as they end (one undo step with the stroke). */
@@ -2473,8 +2508,8 @@ var PaintWetLayers = (_class7 = class {
2473
2508
  /** Starts the GPU engine for the world (once; it may turn out unavailable). */
2474
2509
  startGpu() {
2475
2510
  if (this.gpuMode === "off" || this.gpu || this.gpuStarting || this.gpuSupport) return;
2476
- const provider = this.options.gpuProvider === void 0 ? _chunkVMROIWLLcjs.findWebGpu.call(void 0, ) : this.options.gpuProvider;
2477
- this.gpuStarting = _chunkVMROIWLLcjs.createWetGpuEngine.call(void 0, provider).then(({ engine, support }) => {
2511
+ const provider = this.options.gpuProvider === void 0 ? _chunkKBYB7OWBcjs.findWebGpu.call(void 0, ) : this.options.gpuProvider;
2512
+ this.gpuStarting = _chunkKBYB7OWBcjs.createWetGpuEngine.call(void 0, provider).then(({ engine, support }) => {
2478
2513
  this.gpuSupport = support;
2479
2514
  if (!engine) return;
2480
2515
  if (this.gpuMode === "off" || !this.world) {
@@ -2504,8 +2539,8 @@ var PaintWetLayers = (_class7 = class {
2504
2539
  if (mode === this.gpuMode) return this.engineInfo();
2505
2540
  this.gpuMode = mode;
2506
2541
  if (mode === "off") {
2507
- _optionalChain([this, 'access', _115 => _115.world, 'optionalAccess', _116 => _116.attachGpu, 'call', _117 => _117(null)]);
2508
- _optionalChain([this, 'access', _118 => _118.gpu, 'optionalAccess', _119 => _119.destroy, 'call', _120 => _120()]);
2542
+ _optionalChain([this, 'access', _118 => _118.world, 'optionalAccess', _119 => _119.attachGpu, 'call', _120 => _120(null)]);
2543
+ _optionalChain([this, 'access', _121 => _121.gpu, 'optionalAccess', _122 => _122.destroy, 'call', _123 => _123()]);
2509
2544
  this.gpu = null;
2510
2545
  this.gpuSupport = null;
2511
2546
  } else if (this.world) this.startGpu();
@@ -2513,13 +2548,13 @@ var PaintWetLayers = (_class7 = class {
2513
2548
  }
2514
2549
  engineInfo() {
2515
2550
  const w = this.world;
2516
- const base = { mode: this.gpuMode, adapter: _nullishCoalesce(_optionalChain([this, 'access', _121 => _121.gpuSupport, 'optionalAccess', _122 => _122.adapter]), () => ( null)), maxTiles: _nullishCoalesce(_optionalChain([this, 'access', _123 => _123.gpuSupport, 'optionalAccess', _124 => _124.maxSlots]), () => ( 0)), minTiles: this.gpuMinTiles, activeTiles: _nullishCoalesce(_optionalChain([w, 'optionalAccess', _125 => _125.activeTiles, 'call', _126 => _126()]), () => ( 0)), cpu: this.backend() };
2551
+ const base = { mode: this.gpuMode, adapter: _nullishCoalesce(_optionalChain([this, 'access', _124 => _124.gpuSupport, 'optionalAccess', _125 => _125.adapter]), () => ( null)), maxTiles: _nullishCoalesce(_optionalChain([this, 'access', _126 => _126.gpuSupport, 'optionalAccess', _127 => _127.maxSlots]), () => ( 0)), minTiles: this.gpuMinTiles, activeTiles: _nullishCoalesce(_optionalChain([w, 'optionalAccess', _128 => _128.activeTiles, 'call', _129 => _129()]), () => ( 0)), cpu: this.backend() };
2517
2552
  if (this.gpuMode === "off") return { ...base, state: "off", reason: "Forced to the CPU." };
2518
2553
  if (this.gpuStarting) return { ...base, state: "starting", reason: null };
2519
- if (_optionalChain([w, 'optionalAccess', _127 => _127.gpuError])) return { ...base, state: "failed", reason: w.gpuError };
2554
+ if (_optionalChain([w, 'optionalAccess', _130 => _130.gpuError])) return { ...base, state: "failed", reason: w.gpuError };
2520
2555
  if (this.gpuSupport && !this.gpuSupport.supported) return { ...base, state: "unavailable", reason: this.gpuSupport.reason };
2521
2556
  if (!this.gpu) return { ...base, state: "not-started", reason: "Starts with the first wet stroke." };
2522
- if (_optionalChain([w, 'optionalAccess', _128 => _128.gpuActive])) return { ...base, state: "active", reason: null };
2557
+ if (_optionalChain([w, 'optionalAccess', _131 => _131.gpuActive])) return { ...base, state: "active", reason: null };
2523
2558
  return { ...base, state: "standby", reason: `The GPU takes over at ${this.gpuMinTiles} wet tiles (256 px).` };
2524
2559
  }
2525
2560
  /** The world (made on first use, at the canvas size). */
@@ -2533,7 +2568,7 @@ var PaintWetLayers = (_class7 = class {
2533
2568
  return this.world;
2534
2569
  }
2535
2570
  makeWorld(width, height, paper) {
2536
- const world = new (0, _chunkVMROIWLLcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: this.options.kernel, threads: this.options.threads });
2571
+ const world = new (0, _chunkKBYB7OWBcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: this.options.kernel, threads: this.options.threads });
2537
2572
  world.setTilt(this.tilt);
2538
2573
  world.gpuMinTiles = this.gpuMinTiles;
2539
2574
  if (this.gpu) world.attachGpu(this.gpu);
@@ -2545,7 +2580,7 @@ var PaintWetLayers = (_class7 = class {
2545
2580
  * sides: the shift has to be whole wet tiles (256 px), and no wet stroke may be live.
2546
2581
  */
2547
2582
  canExtend(left, top) {
2548
- return left % _chunkVMROIWLLcjs.WET_TILE === 0 && top % _chunkVMROIWLLcjs.WET_TILE === 0 && !this.driver;
2583
+ return left % _chunkKBYB7OWBcjs.WET_TILE === 0 && top % _chunkKBYB7OWBcjs.WET_TILE === 0 && !this.driver;
2549
2584
  }
2550
2585
  /**
2551
2586
  * Keeps the wet paint while the canvas grows to `width`×`height` by `left` / `top` on those
@@ -2558,17 +2593,17 @@ var PaintWetLayers = (_class7 = class {
2558
2593
  if (!this.canExtend(left, top)) throw new Error("Wet paint only moves by whole 256 px tiles, between strokes.");
2559
2594
  for (const [id, s] of this.settings) if (s.flow.center) this.settings.set(id, { ...s, flow: { ...s.flow, center: { x: s.flow.center.x + left, y: s.flow.center.y + top } } });
2560
2595
  const old = this.world;
2561
- const snap = _optionalChain([old, 'optionalAccess', _129 => _129.laneIds, 'call', _130 => _130(), 'access', _131 => _131.length]) ? old.snapshot() : null;
2596
+ const snap = _optionalChain([old, 'optionalAccess', _132 => _132.laneIds, 'call', _133 => _133(), 'access', _134 => _134.length]) ? old.snapshot() : null;
2562
2597
  this.dropWorld();
2563
2598
  this.lastTick = null;
2564
2599
  this.stepsOwed = 0;
2565
2600
  if (!old || !snap) return;
2566
- const moved = _chunkVMROIWLLcjs.moveWetSnapshot.call(void 0, snap, old, { width, height }, left, top, (l) => {
2567
- const flow = _optionalChain([this, 'access', _132 => _132.settings, 'access', _133 => _133.get, 'call', _134 => _134(l.id), 'optionalAccess', _135 => _135.flow]);
2601
+ const moved = _chunkKBYB7OWBcjs.moveWetSnapshot.call(void 0, snap, old, { width, height }, left, top, (l) => {
2602
+ const flow = _optionalChain([this, 'access', _135 => _135.settings, 'access', _136 => _136.get, 'call', _137 => _137(l.id), 'optionalAccess', _138 => _138.flow]);
2568
2603
  return {
2569
2604
  base: _chunk474IQG74cjs.translateSurface.call(void 0, l.base, left, top),
2570
2605
  ...l.light ? { light: _chunk474IQG74cjs.translateSurface.call(void 0, l.light, left, top) } : {},
2571
- flow: l.flow && flow && flow.kind !== "none" ? _chunkVMROIWLLcjs.flowField.call(void 0, flow, width, height) : l.flow
2606
+ flow: l.flow && flow && flow.kind !== "none" ? _chunkKBYB7OWBcjs.flowField.call(void 0, flow, width, height) : l.flow
2572
2607
  };
2573
2608
  });
2574
2609
  this.world = this.makeWorld(width, height, paper);
@@ -2583,11 +2618,11 @@ var PaintWetLayers = (_class7 = class {
2583
2618
  }
2584
2619
  /** Layers holding a wet layer (wet or drying). */
2585
2620
  wetLayerIds() {
2586
- return _nullishCoalesce(_optionalChain([this, 'access', _136 => _136.world, 'optionalAccess', _137 => _137.laneIds, 'call', _138 => _138()]), () => ( []));
2621
+ return _nullishCoalesce(_optionalChain([this, 'access', _139 => _139.world, 'optionalAccess', _140 => _140.laneIds, 'call', _141 => _141()]), () => ( []));
2587
2622
  }
2588
2623
  /** Whether a batch is running (edits wait). */
2589
2624
  get busy() {
2590
- return Boolean(_optionalChain([this, 'access', _139 => _139.world, 'optionalAccess', _140 => _140.busy]));
2625
+ return Boolean(_optionalChain([this, 'access', _142 => _142.world, 'optionalAccess', _143 => _143.busy]));
2591
2626
  }
2592
2627
  /** Resolves when no batch is running. */
2593
2628
  async idle() {
@@ -2596,7 +2631,7 @@ var PaintWetLayers = (_class7 = class {
2596
2631
  settingsOf(layerId, medium = "watercolor") {
2597
2632
  let s = this.settings.get(layerId);
2598
2633
  if (!s) {
2599
- s = { params: _chunkVMROIWLLcjs.normalizeWetParams.call(void 0, WET_MEDIUM_PARAMS[medium], _chunkVMROIWLLcjs.DEFAULT_WET_PARAMS), flow: { ..._chunkVMROIWLLcjs.DEFAULT_FLOW } };
2634
+ s = { params: _chunkKBYB7OWBcjs.normalizeWetParams.call(void 0, WET_MEDIUM_PARAMS[medium], _chunkKBYB7OWBcjs.DEFAULT_WET_PARAMS), flow: { ..._chunkKBYB7OWBcjs.DEFAULT_FLOW } };
2600
2635
  this.settings.set(layerId, s);
2601
2636
  }
2602
2637
  return s;
@@ -2609,50 +2644,50 @@ var PaintWetLayers = (_class7 = class {
2609
2644
  const s = this.settingsOf(layerId, medium);
2610
2645
  w.ensureLane(layerId, { params: s.params, base, light: this.host.layerLight(layerId) });
2611
2646
  const { width, height } = this.host.canvas();
2612
- if (s.flow.kind !== "none") w.setFlow(layerId, _chunkVMROIWLLcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2647
+ if (s.flow.kind !== "none") w.setFlow(layerId, _chunkKBYB7OWBcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2613
2648
  }
2614
2649
  return w;
2615
2650
  }
2616
2651
  setParams(layerId, update) {
2617
2652
  const s = this.settingsOf(layerId);
2618
- s.params = _chunkVMROIWLLcjs.normalizeWetParams.call(void 0, update, s.params);
2619
- if (_optionalChain([this, 'access', _141 => _141.world, 'optionalAccess', _142 => _142.hasLane, 'call', _143 => _143(layerId)])) this.world.setParams(layerId, s.params);
2653
+ s.params = _chunkKBYB7OWBcjs.normalizeWetParams.call(void 0, update, s.params);
2654
+ if (_optionalChain([this, 'access', _144 => _144.world, 'optionalAccess', _145 => _145.hasLane, 'call', _146 => _146(layerId)])) this.world.setParams(layerId, s.params);
2620
2655
  return { ...s.params };
2621
2656
  }
2622
2657
  setFlow(layerId, update) {
2623
2658
  const s = this.settingsOf(layerId);
2624
- s.flow = _chunkVMROIWLLcjs.normalizeFlow.call(void 0, update, s.flow);
2625
- if (_optionalChain([this, 'access', _144 => _144.world, 'optionalAccess', _145 => _145.hasLane, 'call', _146 => _146(layerId)])) {
2659
+ s.flow = _chunkKBYB7OWBcjs.normalizeFlow.call(void 0, update, s.flow);
2660
+ if (_optionalChain([this, 'access', _147 => _147.world, 'optionalAccess', _148 => _148.hasLane, 'call', _149 => _149(layerId)])) {
2626
2661
  const { width, height } = this.host.canvas();
2627
- this.world.setFlow(layerId, _chunkVMROIWLLcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2662
+ this.world.setFlow(layerId, _chunkKBYB7OWBcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2628
2663
  }
2629
2664
  return { ...s.flow };
2630
2665
  }
2631
2666
  setTilt(update) {
2632
- this.tilt = _chunkVMROIWLLcjs.normalizeTilt.call(void 0, update, this.tilt);
2633
- _optionalChain([this, 'access', _147 => _147.world, 'optionalAccess', _148 => _148.setTilt, 'call', _149 => _149(this.tilt)]);
2667
+ this.tilt = _chunkKBYB7OWBcjs.normalizeTilt.call(void 0, update, this.tilt);
2668
+ _optionalChain([this, 'access', _150 => _150.world, 'optionalAccess', _151 => _151.setTilt, 'call', _152 => _152(this.tilt)]);
2634
2669
  return { ...this.tilt };
2635
2670
  }
2636
2671
  /** The paper changed. */
2637
2672
  paperChanged() {
2638
- _optionalChain([this, 'access', _150 => _150.world, 'optionalAccess', _151 => _151.setPaper, 'call', _152 => _152(wetPaperInput(this.host.paper()))]);
2673
+ _optionalChain([this, 'access', _153 => _153.world, 'optionalAccess', _154 => _154.setPaper, 'call', _155 => _155(wetPaperInput(this.host.paper()))]);
2639
2674
  }
2640
2675
  /** A layer as tools describe it. */
2641
2676
  info(layerId) {
2642
2677
  const s = this.settingsOf(layerId);
2643
- const st = _optionalChain([this, 'access', _153 => _153.world, 'optionalAccess', _154 => _154.hasLane, 'call', _155 => _155(layerId)]) ? this.world.stats(layerId) : null;
2678
+ const st = _optionalChain([this, 'access', _156 => _156.world, 'optionalAccess', _157 => _157.hasLane, 'call', _158 => _158(layerId)]) ? this.world.stats(layerId) : null;
2644
2679
  return {
2645
2680
  layerId,
2646
2681
  wet: Boolean(st && st.wetCells > 0),
2647
- wetCells: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _156 => _156.wetCells]), () => ( 0)),
2648
- wetBounds: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _157 => _157.wetBounds]), () => ( null)),
2649
- activeTiles: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _158 => _158.activeTiles]), () => ( 0)),
2682
+ wetCells: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _159 => _159.wetCells]), () => ( 0)),
2683
+ wetBounds: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _160 => _160.wetBounds]), () => ( null)),
2684
+ activeTiles: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _161 => _161.activeTiles]), () => ( 0)),
2650
2685
  params: { ...s.params },
2651
2686
  flow: { ...s.flow }
2652
2687
  };
2653
2688
  }
2654
2689
  backend() {
2655
- return _nullishCoalesce(_optionalChain([this, 'access', _159 => _159.world, 'optionalAccess', _160 => _160.backend, 'call', _161 => _161()]), () => ( null));
2690
+ return _nullishCoalesce(_optionalChain([this, 'access', _162 => _162.world, 'optionalAccess', _163 => _163.backend, 'call', _164 => _164()]), () => ( null));
2656
2691
  }
2657
2692
  /** Shows the current wet pixels (at most `maxTiles` reshaded per layer). */
2658
2693
  syncDisplays(maxTiles = Infinity) {
@@ -2701,7 +2736,7 @@ var PaintWetLayers = (_class7 = class {
2701
2736
  const w = this.world;
2702
2737
  if (!w) return;
2703
2738
  for (const id of w.laneIds()) {
2704
- if (w.isActive(id) || _optionalChain([this, 'access', _162 => _162.driver, 'optionalAccess', _163 => _163.init, 'access', _164 => _164.laneId]) === id) continue;
2739
+ if (w.isActive(id) || _optionalChain([this, 'access', _165 => _165.driver, 'optionalAccess', _166 => _166.init, 'access', _167 => _167.laneId]) === id) continue;
2705
2740
  const base = w.getBase(id);
2706
2741
  const light = w.isLit(id) ? w.getLight(id) : null;
2707
2742
  w.removeLane(id);
@@ -2783,7 +2818,7 @@ var PaintWetLayers = (_class7 = class {
2783
2818
  if (!d || !this.world) return;
2784
2819
  const rects = d.flush();
2785
2820
  if (rects.length) this.syncDisplays(DISPLAY_TILES_PER_TICK);
2786
- if (d.done) _optionalChain([this, 'access', _165 => _165.onDriverDone, 'optionalCall', _166 => _166(d)]);
2821
+ if (d.done) _optionalChain([this, 'access', _168 => _168.onDriverDone, 'optionalCall', _169 => _169(d)]);
2787
2822
  }
2788
2823
  /** Called when a live stroke that ended mid-batch has finished applying. */
2789
2824
  __init68() {this.onDriverDone = null}
@@ -2827,13 +2862,13 @@ var PaintWetLayers = (_class7 = class {
2827
2862
  /** The layer's light paint with all its wet paint dried (`null` without a wet layer or light), without changing anything. */
2828
2863
  bakedLight(layerId) {
2829
2864
  const w = this.world;
2830
- if (!_optionalChain([w, 'optionalAccess', _167 => _167.hasLane, 'call', _168 => _168(layerId)]) || !w.isLit(layerId)) return null;
2865
+ if (!_optionalChain([w, 'optionalAccess', _170 => _170.hasLane, 'call', _171 => _171(layerId)]) || !w.isLit(layerId)) return null;
2831
2866
  return w.bakedLight(layerId);
2832
2867
  }
2833
2868
  /** The layer's pixels with all its wet paint dried (deterministic), without changing anything. */
2834
2869
  bakedSurface(layerId) {
2835
2870
  const w = this.world;
2836
- if (!_optionalChain([w, 'optionalAccess', _169 => _169.hasLane, 'call', _170 => _170(layerId)])) return null;
2871
+ if (!_optionalChain([w, 'optionalAccess', _172 => _172.hasLane, 'call', _173 => _173(layerId)])) return null;
2837
2872
  return w.bakedSurface(layerId);
2838
2873
  }
2839
2874
  /** A snapshot of the world for undo (`null` when there is none). */
@@ -2854,13 +2889,13 @@ var PaintWetLayers = (_class7 = class {
2854
2889
  this.syncDisplays();
2855
2890
  }
2856
2891
  dropWorld() {
2857
- _optionalChain([this, 'access', _171 => _171.world, 'optionalAccess', _172 => _172.destroy, 'call', _173 => _173()]);
2892
+ _optionalChain([this, 'access', _174 => _174.world, 'optionalAccess', _175 => _175.destroy, 'call', _176 => _176()]);
2858
2893
  this.world = null;
2859
2894
  this.driver = null;
2860
2895
  }
2861
2896
  /** Forgets everything wet (a new canvas, a resize, opening a document). */
2862
2897
  reset() {
2863
- _optionalChain([this, 'access', _174 => _174.world, 'optionalAccess', _175 => _175.destroy, 'call', _176 => _176()]);
2898
+ _optionalChain([this, 'access', _177 => _177.world, 'optionalAccess', _178 => _178.destroy, 'call', _179 => _179()]);
2864
2899
  this.world = null;
2865
2900
  this.driver = null;
2866
2901
  this.settings.clear();
@@ -2890,44 +2925,44 @@ var PaintWetLayers = (_class7 = class {
2890
2925
  return out;
2891
2926
  }
2892
2927
  destroy() {
2893
- _optionalChain([this, 'access', _177 => _177.world, 'optionalAccess', _178 => _178.destroy, 'call', _179 => _179()]);
2928
+ _optionalChain([this, 'access', _180 => _180.world, 'optionalAccess', _181 => _181.destroy, 'call', _182 => _182()]);
2894
2929
  this.world = null;
2895
- _optionalChain([this, 'access', _180 => _180.gpu, 'optionalAccess', _181 => _181.destroy, 'call', _182 => _182()]);
2930
+ _optionalChain([this, 'access', _183 => _183.gpu, 'optionalAccess', _184 => _184.destroy, 'call', _185 => _185()]);
2896
2931
  this.gpu = null;
2897
2932
  }
2898
2933
  }, _class7);
2899
2934
  function wetPigmentOf(hex, body) {
2900
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, hex);
2901
- return Array.from(_chunkVMROIWLLcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
2935
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, hex);
2936
+ return Array.from(_chunkKBYB7OWBcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
2902
2937
  }
2903
2938
 
2904
2939
  // src/paint-editor/thumbnails.ts
2905
2940
  var thumbWorld = null;
2906
2941
  function paintWetTestStroke(brush, paper, color, width, height) {
2907
2942
  if (!thumbWorld || thumbWorld.width !== width || thumbWorld.height !== height) {
2908
- _optionalChain([thumbWorld, 'optionalAccess', _183 => _183.destroy, 'call', _184 => _184()]);
2909
- thumbWorld = new (0, _chunkVMROIWLLcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: "typescript", threads: 0 });
2943
+ _optionalChain([thumbWorld, 'optionalAccess', _186 => _186.destroy, 'call', _187 => _187()]);
2944
+ thumbWorld = new (0, _chunkKBYB7OWBcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: "typescript", threads: 0 });
2910
2945
  } else thumbWorld.setPaper(wetPaperInput(paper));
2911
2946
  const w = thumbWorld;
2912
2947
  if (w.hasLane("thumb")) w.removeLane("thumb");
2913
2948
  w.ensureLane("thumb");
2914
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, color);
2949
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, color);
2915
2950
  if (brush.wet.tool !== "paint" && brush.wet.tool !== "water") {
2916
2951
  const half = Math.ceil(height / 2);
2917
- w.paint("thumb", { x: 0, y: 0, width, height: half }, null, 0.4, Array.from(_chunkVMROIWLLcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], 0), (v) => v * 0.05));
2918
- w.paint("thumb", { x: 0, y: half, width, height: height - half }, null, 0.4, Array.from(_chunkVMROIWLLcjs.pigmentOf.call(void 0, [232 / 255, 196 / 255, 64 / 255], 0), (v) => v * 0.05));
2952
+ w.paint("thumb", { x: 0, y: 0, width, height: half }, null, 0.4, Array.from(_chunkKBYB7OWBcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], 0), (v) => v * 0.05));
2953
+ w.paint("thumb", { x: 0, y: half, width, height: height - half }, null, 0.4, Array.from(_chunkKBYB7OWBcjs.pigmentOf.call(void 0, [232 / 255, 196 / 255, 64 / 255], 0), (v) => v * 0.05));
2919
2954
  }
2920
2955
  const driver = new WetStrokeDriver({
2921
2956
  world: w,
2922
2957
  laneId: "thumb",
2923
2958
  brush,
2924
2959
  color: [r / 255, g / 255, b / 255],
2925
- load: brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2960
+ load: brushLoadForStroke(brush, _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2926
2961
  grain: paperGrain(paper),
2927
2962
  paperDepth: paper.depth,
2928
- paperColor: _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, paper.color),
2963
+ paperColor: _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, paper.color),
2929
2964
  seed: 7,
2930
- copies: [_chunkQ2UYUWAZcjs.IDENTITY_COPY]
2965
+ copies: [_chunkH4AOUUBEcjs.IDENTITY_COPY]
2931
2966
  });
2932
2967
  driver.push(thumbnailStroke(width, height));
2933
2968
  driver.finish();
@@ -2947,7 +2982,7 @@ function thumbnailStroke(width, height) {
2947
2982
  return pts;
2948
2983
  }
2949
2984
  function paintTestStroke(surface, brush, paper, color, width, height) {
2950
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, color);
2985
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, color);
2951
2986
  let result = surface;
2952
2987
  let thick = null;
2953
2988
  let light = null;
@@ -2968,14 +3003,14 @@ function paintTestStroke(surface, brush, paper, color, width, height) {
2968
3003
  lockTransparency: false,
2969
3004
  brush,
2970
3005
  color: [r, g, b, 255],
2971
- background: [..._chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, paper.color), 255],
3006
+ background: [..._chunkH4AOUUBEcjs.hexToRgb8.call(void 0, paper.color), 255],
2972
3007
  grain: paperGrain(paper),
2973
3008
  paperDepth: paper.depth,
2974
3009
  seed: 7,
2975
3010
  colorHex: color,
2976
3011
  affineCopies: [],
2977
- copies: [_chunkQ2UYUWAZcjs.IDENTITY_COPY],
2978
- mixerLoad: brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
3012
+ copies: [_chunkH4AOUUBEcjs.IDENTITY_COPY],
3013
+ mixerLoad: brushLoadForStroke(brush, _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2979
3014
  thick: brush.engine === "impasto" ? { channels: emptyThickChannels() } : void 0,
2980
3015
  sticker: brush.engine === "sticker" ? { nextId: 1 } : void 0,
2981
3016
  light: brush.light.amount > 0 && brush.engine !== "wet" && brush.engine !== "sticker" ? { surface: emptyLight() } : null
@@ -2990,8 +3025,8 @@ function renderBrushThumbnail(brush, options) {
2990
3025
  const width = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.width, () => ( 160)))));
2991
3026
  const height = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.height, () => ( 48)))));
2992
3027
  const maxSize = height * 0.42;
2993
- const b = brush.tip.size > maxSize ? _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
2994
- const rgba = [..._chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, options.color), 255];
3028
+ const b = brush.tip.size > maxSize ? _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
3029
+ const rgba = [..._chunkH4AOUUBEcjs.hexToRgb8.call(void 0, options.color), 255];
2995
3030
  let surface = _chunk474IQG74cjs.emptySurface.call(void 0, 4);
2996
3031
  if (b.engine === "eraser") {
2997
3032
  surface = _chunk474IQG74cjs.fillRect.call(void 0, surface, { x: 0, y: 0, width, height }, rgba);
@@ -3249,12 +3284,12 @@ function colorHarmony2(base, kind, options = {}) {
3249
3284
  function readSwatch(raw) {
3250
3285
  if (!raw || typeof raw !== "object") return null;
3251
3286
  const r = raw;
3252
- const g = _chunkPQ3H2AANcjs.readPaintSource.call(void 0, r.paint);
3253
- const color = typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : _optionalChain([g, 'optionalAccess', _185 => _185.type]) === "gradient" ? _chunkPQ3H2AANcjs.paintSourceColor.call(void 0, g) : null;
3287
+ const g = _chunkI7NJPHWVcjs.readPaintSource.call(void 0, r.paint);
3288
+ const color = typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : _optionalChain([g, 'optionalAccess', _188 => _188.type]) === "gradient" ? _chunkI7NJPHWVcjs.paintSourceColor.call(void 0, g) : null;
3254
3289
  if (!color) return null;
3255
3290
  const out = { color };
3256
3291
  if (typeof r.name === "string" && r.name.trim()) out.name = r.name.trim().slice(0, 80);
3257
- if (_optionalChain([g, 'optionalAccess', _186 => _186.type]) === "gradient") out.paint = g;
3292
+ if (_optionalChain([g, 'optionalAccess', _189 => _189.type]) === "gradient") out.paint = g;
3258
3293
  return out;
3259
3294
  }
3260
3295
  var DEFAULT_SWATCHES = [
@@ -3273,7 +3308,7 @@ var DEFAULT_SWATCHES = [
3273
3308
  // src/paint-editor/mixing-pad.ts
3274
3309
  var MIXING_PAD_WIDTH = 360;
3275
3310
  var MIXING_PAD_HEIGHT = 220;
3276
- var PAD_PAINT = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, {
3311
+ var PAD_PAINT = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, {
3277
3312
  id: "pad-paint",
3278
3313
  name: "Pad paint",
3279
3314
  category: "mixer",
@@ -3281,7 +3316,7 @@ var PAD_PAINT = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, {
3281
3316
  tip: { size: 28, hardness: 0.75, spacing: 0.1, opacity: 1, flow: 0.7, pressureSize: false, pressureOpacity: false },
3282
3317
  mixer: { wet: 0.45, load: 1, mix: 0.4, loadEachStroke: true, cleanEachStroke: true, mixing: "pigment" }
3283
3318
  });
3284
- var PAD_KNIFE = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, {
3319
+ var PAD_KNIFE = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, {
3285
3320
  id: "pad-knife",
3286
3321
  name: "Palette knife",
3287
3322
  category: "smudge",
@@ -3291,7 +3326,7 @@ var PAD_KNIFE = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, {
3291
3326
  // A knife drags streaks of paint and folds them into each other, mixing them as pigment.
3292
3327
  smudge: { strength: 0.6, length: 0.8, mixing: "pigment" }
3293
3328
  });
3294
- var PAD_BLOB = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, {
3329
+ var PAD_BLOB = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, {
3295
3330
  id: "pad-blob",
3296
3331
  name: "Pad blob",
3297
3332
  category: "custom",
@@ -3313,12 +3348,12 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3313
3348
  }
3314
3349
  }
3315
3350
  let brush = options.tool === "knife" ? PAD_KNIFE : PAD_PAINT;
3316
- if (options.size !== void 0) brush = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
3351
+ if (options.size !== void 0) brush = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
3317
3352
  return this.run(brush, points, options.color);
3318
3353
  }
3319
3354
  /** Paints `points` with `brush` in `color` on the pad. */
3320
3355
  run(brush, points, color) {
3321
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, color);
3356
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, color);
3322
3357
  let result = null;
3323
3358
  const session = new PaintStrokeSession(
3324
3359
  { update: () => {
@@ -3336,8 +3371,8 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3336
3371
  seed: 1,
3337
3372
  colorHex: color,
3338
3373
  affineCopies: [],
3339
- copies: [_chunkQ2UYUWAZcjs.IDENTITY_COPY],
3340
- mixerLoad: brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255])
3374
+ copies: [_chunkH4AOUUBEcjs.IDENTITY_COPY],
3375
+ mixerLoad: brushLoadForStroke(brush, _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255])
3341
3376
  }
3342
3377
  );
3343
3378
  session.push(points);
@@ -3412,10 +3447,10 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3412
3447
  const off = used.length === 1 ? 0 : 0.45 * R;
3413
3448
  const x = Math.min(cx + R - r, Math.max(cx - R + r, cx + Math.cos(a) * off));
3414
3449
  const y = Math.min(cy + R - r, Math.max(cy - R + r, cy + Math.sin(a) * off));
3415
- const blob = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
3450
+ const blob = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
3416
3451
  this.run(blob, [{ x, y }], p.color.toLowerCase());
3417
3452
  });
3418
- const knife = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
3453
+ const knife = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
3419
3454
  for (let k = 0; k < passes; k++) {
3420
3455
  const stir = [];
3421
3456
  const turns = 1.6;
@@ -3426,24 +3461,24 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3426
3461
  }
3427
3462
  this.run(knife, stir, "#000000");
3428
3463
  }
3429
- const mixed = _chunkOLNIPTB3cjs.mixPigments.call(void 0,
3430
- paints.map((p) => _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, p.color).map((v) => v / 255)),
3464
+ const mixed = _chunk2VX55NFMcjs.mixPigments.call(void 0,
3465
+ paints.map((p) => _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, p.color).map((v) => v / 255)),
3431
3466
  paints.map((p) => p.parts)
3432
3467
  );
3433
- const core = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
3468
+ const core = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
3434
3469
  const hex = "#" + mixed.map((v) => Math.round(v * 255).toString(16).padStart(2, "0")).join("");
3435
3470
  this.run(core, [{ x: cx, y: cy }], hex);
3436
3471
  return { color: this.pick(cx, cy, 2), bounds };
3437
3472
  }
3438
3473
  /** The pad's pixels as a PNG data URL (with alpha), for saving. */
3439
3474
  toPng() {
3440
- return _chunkOLNIPTB3cjs.pngDataUrl.call(void 0, this.width, this.height, _chunk474IQG74cjs.readRegion.call(void 0, this.surface, { x: 0, y: 0, width: this.width, height: this.height }));
3475
+ return _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, this.width, this.height, _chunk474IQG74cjs.readRegion.call(void 0, this.surface, { x: 0, y: 0, width: this.width, height: this.height }));
3441
3476
  }
3442
3477
  /** Replaces the pad with a PNG (data URL or base64) of the pad's size, as `toPng` writes. */
3443
3478
  fromPng(png) {
3444
- const bytes = png.startsWith("data:") ? _optionalChain([_chunkOLNIPTB3cjs.parseDataUrl.call(void 0, png), 'optionalAccess', _187 => _187.bytes]) : _chunkOLNIPTB3cjs.base64ToBytes.call(void 0, png);
3445
- if (!bytes || !_chunkOLNIPTB3cjs.isPng.call(void 0, bytes)) throw new Error("The pad image is not a PNG data URL or base64 PNG.");
3446
- const img = _chunkOLNIPTB3cjs.decodePng.call(void 0, bytes);
3479
+ const bytes = png.startsWith("data:") ? _optionalChain([_chunkW5M3J7PVcjs.parseDataUrl.call(void 0, png), 'optionalAccess', _190 => _190.bytes]) : _chunkW5M3J7PVcjs.base64ToBytes.call(void 0, png);
3480
+ if (!bytes || !_chunkW5M3J7PVcjs.isPng.call(void 0, bytes)) throw new Error("The pad image is not a PNG data URL or base64 PNG.");
3481
+ const img = _chunkW5M3J7PVcjs.decodePng.call(void 0, bytes);
3447
3482
  if (img.width !== this.width || img.height !== this.height) throw new Error(`The pad image is ${img.width}\xD7${img.height}; a mixing pad is ${this.width}\xD7${this.height}.`);
3448
3483
  this.surface = _chunk474IQG74cjs.surfaceFromPixels.call(void 0, { width: img.width, height: img.height, data: img.data }, 4);
3449
3484
  this.version++;
@@ -3500,7 +3535,9 @@ function liveStrokeBounds(stroke) {
3500
3535
  if (q.y > y1) y1 = q.y;
3501
3536
  }
3502
3537
  }
3503
- const pad = stroke.brush.tip.size * (stroke.brush.engine === "particle" ? 2 : 1) + 2;
3538
+ const particle = stroke.brush.engine === "particle" ? stroke.brush.particle : null;
3539
+ const wave = particle ? Math.max(_nullishCoalesce(particle.waveAmplitude, () => ( 0)), particle.kind === "fuzzy" ? 0.12 : 0) : 0;
3540
+ const pad = stroke.brush.tip.size * (particle ? 2 + wave : 1) + 2;
3504
3541
  return { x: Math.floor(x0 - pad), y: Math.floor(y0 - pad), width: Math.ceil(x1 - x0 + 2 * pad), height: Math.ceil(y1 - y0 + 2 * pad) };
3505
3542
  }
3506
3543
 
@@ -3561,8 +3598,8 @@ var BacklightCache = (_class10 = class {constructor() { _class10.prototype.__ini
3561
3598
  refs.length = 0;
3562
3599
  for (const l of layers) {
3563
3600
  tilesUnder(l.surface, rect, l.offset, refs);
3564
- tilesUnder(_optionalChain([l, 'access', _188 => _188.thick, 'optionalAccess', _189 => _189.height]), rect, l.offset, refs);
3565
- tilesUnder(_optionalChain([l, 'access', _190 => _190.thick, 'optionalAccess', _191 => _191.material]), rect, l.offset, refs);
3601
+ tilesUnder(_optionalChain([l, 'access', _191 => _191.thick, 'optionalAccess', _192 => _192.height]), rect, l.offset, refs);
3602
+ tilesUnder(_optionalChain([l, 'access', _193 => _193.thick, 'optionalAccess', _194 => _194.material]), rect, l.offset, refs);
3566
3603
  }
3567
3604
  const k = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
3568
3605
  let r = this.tiles.get(k);
@@ -3634,10 +3671,10 @@ function addTiles(a, b) {
3634
3671
  }
3635
3672
  function computeTile(paper, grain, amount, rect, layers) {
3636
3673
  const n = rect.width * rect.height;
3637
- const [p0, p1, p2] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, paper.color);
3674
+ const [p0, p1, p2] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, paper.color);
3638
3675
  const pb = [p0, p1, p2];
3639
3676
  const pl = [Math.max(1e-4, LIN[p0]), Math.max(1e-4, LIN[p1]), Math.max(1e-4, LIN[p2])];
3640
- const [c0, c1, c2] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, _nullishCoalesce(paper.backlightColor, () => ( DEFAULT_BACKLIGHT_COLOR)));
3677
+ const [c0, c1, c2] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, _nullishCoalesce(paper.backlightColor, () => ( DEFAULT_BACKLIGHT_COLOR)));
3641
3678
  const t0 = new Float32Array(n).fill(amount * LIN[c0]);
3642
3679
  const t1 = new Float32Array(n).fill(amount * LIN[c1]);
3643
3680
  const t2 = new Float32Array(n).fill(amount * LIN[c2]);
@@ -3656,8 +3693,8 @@ function computeTile(paper, grain, amount, rect, layers) {
3656
3693
  const lr = { x: rect.x - l.offset.x, y: rect.y - l.offset.y, width: rect.width, height: rect.height };
3657
3694
  if (!l.surface.tiles.size) continue;
3658
3695
  const px = _chunk474IQG74cjs.readRegion.call(void 0, l.surface, lr);
3659
- const h = _optionalChain([l, 'access', _192 => _192.thick, 'optionalAccess', _193 => _193.height, 'access', _194 => _194.tiles, 'access', _195 => _195.size]) ? _chunk474IQG74cjs.readRegion.call(void 0, l.thick.height, lr) : null;
3660
- const m = h && _optionalChain([l, 'access', _196 => _196.thick, 'optionalAccess', _197 => _197.material, 'access', _198 => _198.tiles, 'access', _199 => _199.size]) ? _chunk474IQG74cjs.readRegion.call(void 0, l.thick.material, lr) : null;
3696
+ const h = _optionalChain([l, 'access', _195 => _195.thick, 'optionalAccess', _196 => _196.height, 'access', _197 => _197.tiles, 'access', _198 => _198.size]) ? _chunk474IQG74cjs.readRegion.call(void 0, l.thick.height, lr) : null;
3697
+ const m = h && _optionalChain([l, 'access', _199 => _199.thick, 'optionalAccess', _200 => _200.material, 'access', _201 => _201.tiles, 'access', _202 => _202.size]) ? _chunk474IQG74cjs.readRegion.call(void 0, l.thick.material, lr) : null;
3661
3698
  const op = l.opacity;
3662
3699
  for (let i = 0; i < n; i++) {
3663
3700
  const a8 = px[i * 4 + 3];
@@ -3722,7 +3759,7 @@ function replayItems(doc) {
3722
3759
  }
3723
3760
  function emptiedLayers(layers) {
3724
3761
  let out = [...layers];
3725
- for (const l of _chunkHB4ICNNAcjs.flattenLayers.call(void 0, layers)) if (l.type === "pixel") out = _chunkHB4ICNNAcjs.mapLayer.call(void 0, out, l.id, () => ({ ...l, surface: _chunk474IQG74cjs.emptySurface.call(void 0, 4), offset: { x: 0, y: 0 } }));
3762
+ for (const l of _chunkDPYAO5U6cjs.flattenLayers.call(void 0, layers)) if (l.type === "pixel") out = _chunkDPYAO5U6cjs.mapLayer.call(void 0, out, l.id, () => ({ ...l, surface: _chunk474IQG74cjs.emptySurface.call(void 0, 4), offset: { x: 0, y: 0 } }));
3726
3763
  return out;
3727
3764
  }
3728
3765
  async function replayPainting(source, target, options = {}) {
@@ -3732,7 +3769,7 @@ async function replayPainting(source, target, options = {}) {
3732
3769
  const maxStrokes = _nullishCoalesce(options.strokes, () => ( source.strokes.length));
3733
3770
  const chunk = Math.max(1, _nullishCoalesce(options.wetChunk, () => ( 0))) || Infinity;
3734
3771
  let strokes = 0;
3735
- await target.prepareEffectPaints(source.strokes.slice(0, maxStrokes).flatMap((st) => _optionalChain([st, 'access', _200 => _200.paint, 'optionalAccess', _201 => _201.type]) === "effect" ? [st.paint] : []));
3772
+ await target.prepareEffectPaints(source.strokes.slice(0, maxStrokes).flatMap((st) => _optionalChain([st, 'access', _203 => _203.paint, 'optionalAccess', _204 => _204.type]) === "effect" ? [st.paint] : []));
3736
3773
  const advanceTo = async (clock) => {
3737
3774
  const now = target.getState().wet.clock;
3738
3775
  let left = clock - now;
@@ -3740,7 +3777,7 @@ async function replayPainting(source, target, options = {}) {
3740
3777
  const n = Math.min(left, chunk);
3741
3778
  await target.advanceWet({ steps: n });
3742
3779
  left -= n;
3743
- if (Number.isFinite(chunk)) await _optionalChain([options, 'access', _202 => _202.onWetSteps, 'optionalCall', _203 => _203(target.getState().wet.clock)]);
3780
+ if (Number.isFinite(chunk)) await _optionalChain([options, 'access', _205 => _205.onWetSteps, 'optionalCall', _206 => _206(target.getState().wet.clock)]);
3744
3781
  }
3745
3782
  };
3746
3783
  const sr = (r) => ({ x: r.x * s, y: r.y * s, width: r.width * s, height: r.height * s });
@@ -3753,14 +3790,14 @@ async function replayPainting(source, target, options = {}) {
3753
3790
  else if (e.kind === "clear") target.clearLayer(e.layerId);
3754
3791
  else if (e.kind === "live-strokes") {
3755
3792
  const d = e.data;
3756
- if (_optionalChain([d, 'optionalAccess', _204 => _204.rasterized])) target.replaceLiveStrokes(e.layerId, null);
3793
+ if (_optionalChain([d, 'optionalAccess', _207 => _207.rasterized])) target.replaceLiveStrokes(e.layerId, null);
3757
3794
  else {
3758
- const list = (_nullishCoalesce(_optionalChain([d, 'optionalAccess', _205 => _205.strokes]), () => ( []))).map((st2) => s === 1 ? st2 : { ...varyStroke(st2, scaleM, { scale: s }), ...st2.stencils ? { stencils: st2.stencils.map((x) => scaleStencil(x, s)) } : {} });
3759
- await target.prepareEffectPaints(list.flatMap((st2) => _optionalChain([st2, 'access', _206 => _206.paint, 'optionalAccess', _207 => _207.type]) === "effect" ? [st2.paint] : []));
3795
+ const list = (_nullishCoalesce(_optionalChain([d, 'optionalAccess', _208 => _208.strokes]), () => ( []))).map((st2) => s === 1 ? st2 : { ...varyStroke(st2, scaleM, { scale: s }), ...st2.stencils ? { stencils: st2.stencils.map((x) => scaleStencil(x, s)) } : {} });
3796
+ await target.prepareEffectPaints(list.flatMap((st2) => _optionalChain([st2, 'access', _209 => _209.paint, 'optionalAccess', _210 => _210.type]) === "effect" ? [st2.paint] : []));
3760
3797
  target.replaceLiveStrokes(e.layerId, list);
3761
3798
  }
3762
3799
  } else if (e.kind === "stickers") {
3763
- const list = (_nullishCoalesce(_optionalChain([e, 'access', _208 => _208.data, 'optionalAccess', _209 => _209.stickers]), () => ( []))).map((x) => s === 1 ? x : { ...x, x: x.x * s, y: x.y * s, size: x.size * s });
3800
+ const list = (_nullishCoalesce(_optionalChain([e, 'access', _211 => _211.data, 'optionalAccess', _212 => _212.stickers]), () => ( []))).map((x) => s === 1 ? x : { ...x, x: x.x * s, y: x.y * s, size: x.size * s });
3764
3801
  target.replaceStickers(e.layerId, list);
3765
3802
  } else target.flattenRelief(e.layerId);
3766
3803
  continue;
@@ -3773,8 +3810,8 @@ async function replayPainting(source, target, options = {}) {
3773
3810
  switch (e.kind) {
3774
3811
  case "dry": {
3775
3812
  const rect = e.data;
3776
- const ids = _optionalChain([e, 'access', _210 => _210.layerId, 'optionalAccess', _211 => _211.split, 'call', _212 => _212(","), 'access', _213 => _213.filter, 'call', _214 => _214(Boolean)]);
3777
- if (_optionalChain([ids, 'optionalAccess', _215 => _215.length])) for (const id of ids) target.dryPaint({ layerId: id, rect: rect ? sr(rect) : void 0 });
3813
+ const ids = _optionalChain([e, 'access', _213 => _213.layerId, 'optionalAccess', _214 => _214.split, 'call', _215 => _215(","), 'access', _216 => _216.filter, 'call', _217 => _217(Boolean)]);
3814
+ if (_optionalChain([ids, 'optionalAccess', _218 => _218.length])) for (const id of ids) target.dryPaint({ layerId: id, rect: rect ? sr(rect) : void 0 });
3778
3815
  else target.dryPaint({ rect: rect ? sr(rect) : void 0 });
3779
3816
  break;
3780
3817
  }
@@ -3805,7 +3842,7 @@ async function replayPainting(source, target, options = {}) {
3805
3842
  strokes++;
3806
3843
  if (!target.getLayer(st.layerId)) continue;
3807
3844
  const init = { layerId: st.layerId, color: st.color, brush: st.brush, seed: st.seed, copies: _nullishCoalesce(st.copies, () => ( [])), ...st.load ? { load: st.load } : {}, ...st.paint ? { paint: st.paint } : {}, snapToPerspective: false, stencils: false, maskStencils: (_nullishCoalesce(st.stencils, () => ( []))).map((x) => s === 1 ? x : scaleStencil(x, s)) };
3808
- if (st.brush.engine === "wet" && _optionalChain([st, 'access', _216 => _216.steps, 'optionalAccess', _217 => _217.length]) === st.points.length) {
3845
+ if (st.brush.engine === "wet" && _optionalChain([st, 'access', _219 => _219.steps, 'optionalAccess', _220 => _220.length]) === st.points.length) {
3809
3846
  await target.wetIdle();
3810
3847
  await advanceTo(st.steps[0]);
3811
3848
  const session = target.beginStroke({ ...init, start: st.points[0] });
@@ -3825,7 +3862,7 @@ async function replayPainting(source, target, options = {}) {
3825
3862
  await target.wetIdle();
3826
3863
  target.paintStroke({ ...init, points: st.points });
3827
3864
  }
3828
- await _optionalChain([options, 'access', _218 => _218.onStroke, 'optionalCall', _219 => _219(strokes)]);
3865
+ await _optionalChain([options, 'access', _221 => _221.onStroke, 'optionalCall', _222 => _222(strokes)]);
3829
3866
  }
3830
3867
  void IDENTITY_AFFINE;
3831
3868
  }
@@ -3863,14 +3900,14 @@ async function buildTimeLapse(source, target, options = {}) {
3863
3900
  const f = replayFrame(target, maxSide, stroke);
3864
3901
  width = f.width;
3865
3902
  height = f.height;
3866
- frames.push(_chunkOLNIPTB3cjs.encodePng.call(void 0, f.width, f.height, f.data));
3903
+ frames.push(_chunkW5M3J7PVcjs.encodePng.call(void 0, f.width, f.height, f.data));
3867
3904
  };
3868
3905
  shoot(0);
3869
3906
  await replayPainting(source, target, {
3870
3907
  wetChunk: wetEvery > 0 ? wetEvery : 0,
3871
3908
  onStroke: (i) => {
3872
3909
  if (i % perFrame === 0 || i === total) shoot(i);
3873
- _optionalChain([options, 'access', _220 => _220.onProgress, 'optionalCall', _221 => _221(total ? i / total : 1)]);
3910
+ _optionalChain([options, 'access', _223 => _223.onProgress, 'optionalCall', _224 => _224(total ? i / total : 1)]);
3874
3911
  },
3875
3912
  onWetSteps: wetEvery > 0 ? () => shoot(-1) : void 0
3876
3913
  });
@@ -4011,15 +4048,15 @@ function readPaintEffectSource(raw) {
4011
4048
  };
4012
4049
  }
4013
4050
  function paperEffectToJSON(p) {
4014
- return { ...sourceOut(p), opacity: p.opacity, blend: p.blend, png: _chunkOLNIPTB3cjs.pngDataUrl.call(void 0, p.image.width, p.image.height, p.image.data) };
4051
+ return { ...sourceOut(p), opacity: p.opacity, blend: p.blend, png: _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, p.image.width, p.image.height, p.image.data) };
4015
4052
  }
4016
4053
  function paperEffectFromJSON(raw, width, height) {
4017
4054
  const source = readPaintEffectSource(raw);
4018
4055
  if (!source) throw new Error("it is not an effect (effect id and values)");
4019
4056
  const r = raw;
4020
- const parsed = typeof r.png === "string" ? _chunkOLNIPTB3cjs.parseDataUrl.call(void 0, r.png) : null;
4057
+ const parsed = typeof r.png === "string" ? _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, r.png) : null;
4021
4058
  if (!parsed) throw new Error("its pixels are missing");
4022
- const image = _chunkOLNIPTB3cjs.decodePng.call(void 0, parsed.bytes);
4059
+ const image = _chunkW5M3J7PVcjs.decodePng.call(void 0, parsed.bytes);
4023
4060
  if (image.width !== width || image.height !== height) throw new Error(`its pixels are ${image.width}\xD7${image.height}, not the canvas size ${width}\xD7${height}`);
4024
4061
  const opacity = typeof r.opacity === "number" && r.opacity >= 0 && r.opacity <= 1 ? r.opacity : 1;
4025
4062
  const blend = PAPER_EFFECT_BLENDS.includes(r.blend) ? r.blend : "multiply";
@@ -4032,6 +4069,14 @@ function effectLayersToJSON(map, keep) {
4032
4069
  }
4033
4070
 
4034
4071
  // src/paint-editor/controller.ts
4072
+ function effectGuard(fn) {
4073
+ try {
4074
+ return fn();
4075
+ } catch (e) {
4076
+ if (e instanceof _chunkDPYAO5U6cjs.LayerEffectError) throw new PaintEditorError(e.message);
4077
+ throw e;
4078
+ }
4079
+ }
4035
4080
  var PaintEditorError = class extends Error {
4036
4081
  constructor(message) {
4037
4082
  super(message);
@@ -4045,7 +4090,7 @@ function parseColor(value, what = "color") {
4045
4090
  return value.trim().toLowerCase();
4046
4091
  }
4047
4092
  function rgbaOf(hex) {
4048
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, hex);
4093
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, hex);
4049
4094
  return [r, g, b, 255];
4050
4095
  }
4051
4096
  function rgbToHex(r, g, b) {
@@ -4058,7 +4103,7 @@ function unionRect(a, b) {
4058
4103
  const y = Math.min(a.y, b.y);
4059
4104
  return { x, y, width: Math.max(a.x + a.width, b.x + b.width) - x, height: Math.max(a.y + a.height, b.y + b.height) - y };
4060
4105
  }
4061
- var isPixelLayer = (l) => _optionalChain([l, 'optionalAccess', _222 => _222.type]) === "pixel";
4106
+ var isPixelLayer = (l) => _optionalChain([l, 'optionalAccess', _225 => _225.type]) === "pixel";
4062
4107
  var PaintEditorController = (_class12 = class _PaintEditorController {
4063
4108
 
4064
4109
  __init82() {this.extensions = {}}
@@ -4080,7 +4125,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4080
4125
  __init90() {this.paintEpoch = 0}
4081
4126
  /** Rendered effect paints by `effectPaintKey` (most recently used last). */
4082
4127
  __init91() {this.effectPaintPixels = /* @__PURE__ */ new Map()}
4083
- __init92() {this.mixerLoad = _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD}
4128
+ __init92() {this.mixerLoad = _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD}
4084
4129
  __init93() {this.view = { ...DEFAULT_VIEW, pan: { ...DEFAULT_VIEW.pan } }}
4085
4130
 
4086
4131
  __init94() {this.selectedStroke = null}
@@ -4137,14 +4182,20 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4137
4182
  __init129() {this.wetOp = null}
4138
4183
  /** The effects provider slot (see `setEffectsProvider`). */
4139
4184
  __init130() {this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)()}
4140
- __init131() {this.effectsRenderer = new PaintEffectsRenderer()}
4141
- __init132() {this.paperEffectNodeCache = null}
4142
- constructor(options = {}) {;_class12.prototype.__init82.call(this);_class12.prototype.__init83.call(this);_class12.prototype.__init84.call(this);_class12.prototype.__init85.call(this);_class12.prototype.__init86.call(this);_class12.prototype.__init87.call(this);_class12.prototype.__init88.call(this);_class12.prototype.__init89.call(this);_class12.prototype.__init90.call(this);_class12.prototype.__init91.call(this);_class12.prototype.__init92.call(this);_class12.prototype.__init93.call(this);_class12.prototype.__init94.call(this);_class12.prototype.__init95.call(this);_class12.prototype.__init96.call(this);_class12.prototype.__init97.call(this);_class12.prototype.__init98.call(this);_class12.prototype.__init99.call(this);_class12.prototype.__init100.call(this);_class12.prototype.__init101.call(this);_class12.prototype.__init102.call(this);_class12.prototype.__init103.call(this);_class12.prototype.__init104.call(this);_class12.prototype.__init105.call(this);_class12.prototype.__init106.call(this);_class12.prototype.__init107.call(this);_class12.prototype.__init108.call(this);_class12.prototype.__init109.call(this);_class12.prototype.__init110.call(this);_class12.prototype.__init111.call(this);_class12.prototype.__init112.call(this);_class12.prototype.__init113.call(this);_class12.prototype.__init114.call(this);_class12.prototype.__init115.call(this);_class12.prototype.__init116.call(this);_class12.prototype.__init117.call(this);_class12.prototype.__init118.call(this);_class12.prototype.__init119.call(this);_class12.prototype.__init120.call(this);_class12.prototype.__init121.call(this);_class12.prototype.__init122.call(this);_class12.prototype.__init123.call(this);_class12.prototype.__init124.call(this);_class12.prototype.__init125.call(this);_class12.prototype.__init126.call(this);_class12.prototype.__init127.call(this);_class12.prototype.__init128.call(this);_class12.prototype.__init129.call(this);_class12.prototype.__init130.call(this);_class12.prototype.__init131.call(this);_class12.prototype.__init132.call(this);_class12.prototype.__init133.call(this);_class12.prototype.__init134.call(this);_class12.prototype.__init135.call(this);_class12.prototype.__init136.call(this);
4185
+ /** The sticker library slot (see `setStickersProvider`). */
4186
+ __init131() {this.stickers = new (0, _chunkZEYMKDYScjs.StickersSlot)(_chunkLJRCU3BJcjs.editorStickers.call(void 0, ))}
4187
+ __init132() {this.stickerArt = new (0, _chunkH4AOUUBEcjs.StickerArtCache)()}
4188
+
4189
+ __init133() {this.effectsRenderer = new PaintEffectsRenderer()}
4190
+ __init134() {this.paperEffectNodeCache = null}
4191
+ constructor(options = {}) {;_class12.prototype.__init82.call(this);_class12.prototype.__init83.call(this);_class12.prototype.__init84.call(this);_class12.prototype.__init85.call(this);_class12.prototype.__init86.call(this);_class12.prototype.__init87.call(this);_class12.prototype.__init88.call(this);_class12.prototype.__init89.call(this);_class12.prototype.__init90.call(this);_class12.prototype.__init91.call(this);_class12.prototype.__init92.call(this);_class12.prototype.__init93.call(this);_class12.prototype.__init94.call(this);_class12.prototype.__init95.call(this);_class12.prototype.__init96.call(this);_class12.prototype.__init97.call(this);_class12.prototype.__init98.call(this);_class12.prototype.__init99.call(this);_class12.prototype.__init100.call(this);_class12.prototype.__init101.call(this);_class12.prototype.__init102.call(this);_class12.prototype.__init103.call(this);_class12.prototype.__init104.call(this);_class12.prototype.__init105.call(this);_class12.prototype.__init106.call(this);_class12.prototype.__init107.call(this);_class12.prototype.__init108.call(this);_class12.prototype.__init109.call(this);_class12.prototype.__init110.call(this);_class12.prototype.__init111.call(this);_class12.prototype.__init112.call(this);_class12.prototype.__init113.call(this);_class12.prototype.__init114.call(this);_class12.prototype.__init115.call(this);_class12.prototype.__init116.call(this);_class12.prototype.__init117.call(this);_class12.prototype.__init118.call(this);_class12.prototype.__init119.call(this);_class12.prototype.__init120.call(this);_class12.prototype.__init121.call(this);_class12.prototype.__init122.call(this);_class12.prototype.__init123.call(this);_class12.prototype.__init124.call(this);_class12.prototype.__init125.call(this);_class12.prototype.__init126.call(this);_class12.prototype.__init127.call(this);_class12.prototype.__init128.call(this);_class12.prototype.__init129.call(this);_class12.prototype.__init130.call(this);_class12.prototype.__init131.call(this);_class12.prototype.__init132.call(this);_class12.prototype.__init133.call(this);_class12.prototype.__init134.call(this);_class12.prototype.__init135.call(this);_class12.prototype.__init136.call(this);_class12.prototype.__init137.call(this);_class12.prototype.__init138.call(this);
4143
4192
  this.historyLimit = Math.max(1, _nullishCoalesce(options.historyLimit, () => ( 200)));
4193
+ this.rasterizeSticker = _nullishCoalesce(options.rasterizeSticker, () => ( _chunkH4AOUUBEcjs.defaultStickerRasterizer));
4194
+ if (options.stickers) this.stickers.set(options.stickers);
4144
4195
  this.doc = createPaintDocument({ width: options.width, height: options.height, dpi: options.dpi, paper: this.resolvePaper(options.paper) });
4145
- this.userBrushes = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
4146
- const start = _nullishCoalesce(this.findBrush(_nullishCoalesce(options.brushId, () => ( _chunkQ2UYUWAZcjs.DEFAULT_BRUSH_ID))), () => ( this.findBrush(_chunkQ2UYUWAZcjs.DEFAULT_BRUSH_ID)));
4147
- this.brush = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, start);
4196
+ this.userBrushes = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
4197
+ const start = _nullishCoalesce(this.findBrush(_nullishCoalesce(options.brushId, () => ( _chunkH4AOUUBEcjs.DEFAULT_BRUSH_ID))), () => ( this.findBrush(_chunkH4AOUUBEcjs.DEFAULT_BRUSH_ID)));
4198
+ this.brush = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, start);
4148
4199
  this.color = options.color ? parseColor(options.color) : "#1f2937";
4149
4200
  this.hand = options.hand === "left" ? "left" : "right";
4150
4201
  this.encodeImage = options.encodeImage;
@@ -4155,19 +4206,19 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4155
4206
  canvas: () => this.doc.canvas,
4156
4207
  paper: () => this.doc.paper,
4157
4208
  layerSurface: (id) => {
4158
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _223 => _223.layer]);
4209
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _226 => _226.layer]);
4159
4210
  return isPixelLayer(l) ? l.surface : null;
4160
4211
  },
4161
4212
  updateSurfaces: (surfaces, rects) => {
4162
4213
  let layers = this.doc.layers;
4163
- for (const [id, surface] of surfaces) if (_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, id)) layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, layers, id, (l) => ({ ...l, surface }));
4214
+ for (const [id, surface] of surfaces) if (_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, id)) layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, layers, id, (l) => ({ ...l, surface }));
4164
4215
  this.doc = { ...this.doc, layers };
4165
4216
  this.emit(rects.length ? rects : "all");
4166
4217
  },
4167
- layerLight: (id) => _nullishCoalesce(_optionalChain([this, 'access', _224 => _224.doc, 'access', _225 => _225.light, 'optionalAccess', _226 => _226[id]]), () => ( null)),
4218
+ layerLight: (id) => _nullishCoalesce(_optionalChain([this, 'access', _227 => _227.doc, 'access', _228 => _228.light, 'optionalAccess', _229 => _229[id]]), () => ( null)),
4168
4219
  updateLights: (lights) => {
4169
4220
  let light = this.doc.light;
4170
- for (const [id, surface] of lights) if (_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) light = withLayerLight(light, id, surface);
4221
+ for (const [id, surface] of lights) if (_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)) light = withLayerLight(light, id, surface);
4171
4222
  this.doc = { ...this.doc, ...light ? { light } : {} };
4172
4223
  },
4173
4224
  changed: () => {
@@ -4175,7 +4226,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4175
4226
  },
4176
4227
  options.wet
4177
4228
  );
4178
- this.wet.onDriverDone = () => _optionalChain([this, 'access', _227 => _227.session, 'optionalAccess', _228 => _228.completeWetEnd, 'call', _229 => _229()]);
4229
+ this.wet.onDriverDone = () => _optionalChain([this, 'access', _230 => _230.session, 'optionalAccess', _231 => _231.completeWetEnd, 'call', _232 => _232()]);
4179
4230
  }
4180
4231
  // --- State and events ----------------------------------------------------------
4181
4232
  subscribe(listener) {
@@ -4197,7 +4248,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4197
4248
  this.cached = {
4198
4249
  document: this.doc,
4199
4250
  brush: this.brush,
4200
- brushes: this.library ??= [..._chunkQ2UYUWAZcjs.BUILTIN_BRUSHES, ...this.userBrushes],
4251
+ brushes: this.library ??= [..._chunkH4AOUUBEcjs.BUILTIN_BRUSHES, ...this.userBrushes],
4201
4252
  color: this.color,
4202
4253
  secondaryColor: this.secondaryColor,
4203
4254
  paint: _nullishCoalesce(this.gradient, () => ( { type: "color", color: this.color })),
@@ -4211,8 +4262,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4211
4262
  selectedSticker: this.selectedSticker,
4212
4263
  canUndo: this.undoStack.length > 0 && !this.session,
4213
4264
  canRedo: this.redoStack.length > 0 && !this.session,
4214
- undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _230 => _230.label]), () => ( null)),
4215
- redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _231 => _231.label]), () => ( null)),
4265
+ undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _233 => _233.label]), () => ( null)),
4266
+ redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _234 => _234.label]), () => ( null)),
4216
4267
  guides: this.guides,
4217
4268
  swatches: this.swatches,
4218
4269
  mixingPadVersion: this.pad.version,
@@ -4225,10 +4276,10 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4225
4276
  overlay: this.wet.overlay,
4226
4277
  instantDry: this.wet.instantDry,
4227
4278
  speed: this.wet.speed,
4228
- clock: _nullishCoalesce(_optionalChain([this, 'access', _232 => _232.wet, 'access', _233 => _233.world, 'optionalAccess', _234 => _234.clock]), () => ( 0)),
4279
+ clock: _nullishCoalesce(_optionalChain([this, 'access', _235 => _235.wet, 'access', _236 => _236.world, 'optionalAccess', _237 => _237.clock]), () => ( 0)),
4229
4280
  tilt: { ...this.wet.tilt },
4230
4281
  gpu: this.wet.gpuMode,
4231
- gpuActive: Boolean(_optionalChain([this, 'access', _235 => _235.wet, 'access', _236 => _236.world, 'optionalAccess', _237 => _237.gpuActive]))
4282
+ gpuActive: Boolean(_optionalChain([this, 'access', _238 => _238.wet, 'access', _239 => _239.world, 'optionalAccess', _240 => _240.gpuActive]))
4232
4283
  },
4233
4284
  version: this.version
4234
4285
  };
@@ -4247,7 +4298,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4247
4298
  return d;
4248
4299
  }
4249
4300
  // --- History -------------------------------------------------------------------
4250
- __init133() {this.docRevision = 0}
4301
+ __init135() {this.docRevision = 0}
4251
4302
  /**
4252
4303
  * Bumped on every change to the painting (a committed or amended step, undo, redo, opening a
4253
4304
  * document), not on wet-paint frames or view changes. `createPaintEditorDocument` uses it.
@@ -4330,9 +4381,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4330
4381
  return wetIds;
4331
4382
  }
4332
4383
  /** Records a wet event (for replays) in the document being built. */
4333
- __init134() {this.pendingWetEvents = []}
4384
+ __init136() {this.pendingWetEvents = []}
4334
4385
  logWet(e) {
4335
- this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _238 => _238.wet, 'access', _239 => _239.world, 'optionalAccess', _240 => _240.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
4386
+ this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _241 => _241.wet, 'access', _242 => _242.world, 'optionalAccess', _243 => _243.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
4336
4387
  }
4337
4388
  /** The document with a paint event appended (for replays). */
4338
4389
  withPaintEvent(doc, e) {
@@ -4393,7 +4444,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4393
4444
  // --- Canvas and paper ----------------------------------------------------------
4394
4445
  resolvePaper(paper) {
4395
4446
  if (typeof paper === "string") {
4396
- const p = _chunkQ2UYUWAZcjs.paperPreset.call(void 0, paper);
4447
+ const p = _chunkH4AOUUBEcjs.paperPreset.call(void 0, paper);
4397
4448
  if (!p) throw new PaintEditorError(`Unknown paper "${paper}". Call list_papers for the ids.`);
4398
4449
  return p;
4399
4450
  }
@@ -4476,8 +4527,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4476
4527
  }
4477
4528
  let next = { ...shiftDocument(this.withWetEvents(this.doc), left, top), canvas: { ...was, width, height } };
4478
4529
  for (const id of keptWet) {
4479
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, next.layers, id), 'optionalAccess', _241 => _241.layer]);
4480
- if (isPixelLayer(l)) next = { ...next, layers: _chunkHB4ICNNAcjs.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 } })) };
4530
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, next.layers, id), 'optionalAccess', _244 => _244.layer]);
4531
+ 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 } })) };
4481
4532
  }
4482
4533
  if (this.wet.world) {
4483
4534
  if (keptWet.length) this.wet.extend(width, height, left, top, next.paper);
@@ -4504,23 +4555,23 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4504
4555
  this.requireIdle("changing the paper");
4505
4556
  let base = this.doc.paper;
4506
4557
  if (update.preset !== void 0 && update.preset !== this.doc.paper.preset) {
4507
- const p = _chunkQ2UYUWAZcjs.paperPreset.call(void 0, update.preset);
4558
+ const p = _chunkH4AOUUBEcjs.paperPreset.call(void 0, update.preset);
4508
4559
  if (!p) throw new PaintEditorError(`Unknown paper "${update.preset}". Call list_papers for the ids.`);
4509
4560
  base = p;
4510
4561
  }
4511
4562
  const { preset: _p, ...rest } = update;
4512
4563
  if (rest.color !== void 0) parseColor(rest.color, "paper color");
4513
- const paper = _chunkQ2UYUWAZcjs.normalizePaper.call(void 0, { ...rest, preset: base.preset, offset: _nullishCoalesce(rest.offset, () => ( this.doc.paper.offset)) }, base);
4564
+ const paper = _chunkH4AOUUBEcjs.normalizePaper.call(void 0, { ...rest, preset: base.preset, offset: _nullishCoalesce(rest.offset, () => ( this.doc.paper.offset)) }, base);
4514
4565
  const changedKeys = Object.keys(rest).filter((k) => k !== "name");
4515
4566
  if (changedKeys.length && update.preset === void 0) paper.preset = base.preset;
4516
4567
  if (this.wet.world) this.beginWetOp();
4517
4568
  this.commit("Paper", { ...this.doc, paper });
4518
4569
  this.wet.paperChanged();
4519
- return _chunkQ2UYUWAZcjs.clonePaper.call(void 0, paper);
4570
+ return _chunkH4AOUUBEcjs.clonePaper.call(void 0, paper);
4520
4571
  }
4521
4572
  // --- Layers --------------------------------------------------------------------
4522
4573
  getLayer(id) {
4523
- return _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _242 => _242.layer]);
4574
+ return _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _245 => _245.layer]);
4524
4575
  }
4525
4576
  /** The active pixel layer (or `undefined`). */
4526
4577
  getActiveLayer() {
@@ -4539,12 +4590,12 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4539
4590
  walk(this.doc.layers, null, 0);
4540
4591
  return out;
4541
4592
  }
4542
- describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _243 => _243.parent, 'optionalAccess', _244 => _244.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _245 => _245.path, 'access', _246 => _246.length]), () => ( 0))) {
4593
+ describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _246 => _246.parent, 'optionalAccess', _247 => _247.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _248 => _248.path, 'access', _249 => _249.length]), () => ( 0))) {
4543
4594
  let bounds = null;
4544
4595
  if (l.type === "pixel") {
4545
4596
  const b = _chunk474IQG74cjs.contentBounds.call(void 0, l.surface);
4546
4597
  bounds = b ? { ...b, x: b.x + l.offset.x, y: b.y + l.offset.y } : null;
4547
- } else for (const c of _chunkHB4ICNNAcjs.flattenLayers.call(void 0, l.children)) if (c.type === "pixel") bounds = unionRect(bounds, this.describeLayer(c, l.id, depth + 1).bounds);
4598
+ } else for (const c of _chunkDPYAO5U6cjs.flattenLayers.call(void 0, l.children)) if (c.type === "pixel") bounds = unionRect(bounds, this.describeLayer(c, l.id, depth + 1).bounds);
4548
4599
  return {
4549
4600
  id: l.id,
4550
4601
  name: l.name,
@@ -4556,7 +4607,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4556
4607
  locks: { ..._nullishCoalesce(l.locks, () => ( {})) },
4557
4608
  active: l.id === this.doc.activeLayerId,
4558
4609
  bounds,
4559
- ..._optionalChain([this, 'access', _247 => _247.doc, 'access', _248 => _248.liveStrokes, 'optionalAccess', _249 => _249[l.id]]) ? { liveStrokes: this.doc.liveStrokes[l.id].length } : {},
4610
+ ..._optionalChain([this, 'access', _250 => _250.doc, 'access', _251 => _251.liveStrokes, 'optionalAccess', _252 => _252[l.id]]) ? { liveStrokes: this.doc.liveStrokes[l.id].length } : {},
4611
+ ..._optionalChain([l, 'access', _253 => _253.effects, 'optionalAccess', _254 => _254.items, 'access', _255 => _255.length]) ? { effects: l.effects.items.length } : {},
4560
4612
  parentId,
4561
4613
  depth
4562
4614
  };
@@ -4572,7 +4624,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4572
4624
  if (!id) throw new PaintEditorError(`There is no active layer to ${what}; add one with add_layer.`);
4573
4625
  const l = this.requireLayer(id);
4574
4626
  if (!isPixelLayer(l)) throw new PaintEditorError(`Layer "${l.name}" is a group; ${what} a pixel layer inside it.`);
4575
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it (update_layer locks) before you ${what} it.`);
4627
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it (update_layer locks) before you ${what} it.`);
4576
4628
  if (!l.visible) throw new PaintEditorError(`Layer "${l.name}" is hidden; show it (update_layer visible true) before you ${what} it.`);
4577
4629
  return l;
4578
4630
  }
@@ -4586,9 +4638,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4586
4638
  /** Adds a layer above the active one: `pixel` (default), `group`, or `strokes`, a live stroke layer whose strokes stay editable. */
4587
4639
  addLayer(options = {}) {
4588
4640
  this.requireIdle("adding a layer");
4589
- const count = _chunkHB4ICNNAcjs.flattenLayers.call(void 0, this.doc.layers).length;
4641
+ const count = _chunkDPYAO5U6cjs.flattenLayers.call(void 0, this.doc.layers).length;
4590
4642
  const type = _nullishCoalesce(options.type, () => ( "pixel"));
4591
- const name = _optionalChain([options, 'access', _250 => _250.name, 'optionalAccess', _251 => _251.trim, 'call', _252 => _252()]) || (type === "group" ? `Group ${count + 1}` : type === "strokes" ? `Strokes ${count + 1}` : `Layer ${count + 1}`);
4643
+ const name = _optionalChain([options, 'access', _256 => _256.name, 'optionalAccess', _257 => _257.trim, 'call', _258 => _258()]) || (type === "group" ? `Group ${count + 1}` : type === "strokes" ? `Strokes ${count + 1}` : `Layer ${count + 1}`);
4592
4644
  const layer = type === "group" ? { type: "group", id: newPaintLayerId(), name, visible: true, opacity: 1, blend: "pass-through", children: [] } : createPaintLayer(name);
4593
4645
  let parentId = null;
4594
4646
  let index;
@@ -4598,12 +4650,12 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4598
4650
  if (g.type !== "group") throw new PaintEditorError(`Layer "${g.name}" is not a group; pass a group id as parentId.`);
4599
4651
  parentId = g.id;
4600
4652
  } else if (above) {
4601
- const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, above);
4653
+ const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, above);
4602
4654
  if (!loc) throw new PaintEditorError(`Unknown layer "${above}". Call list_layers for the ids.`);
4603
- parentId = _nullishCoalesce(_optionalChain([loc, 'access', _253 => _253.parent, 'optionalAccess', _254 => _254.id]), () => ( null));
4655
+ parentId = _nullishCoalesce(_optionalChain([loc, 'access', _259 => _259.parent, 'optionalAccess', _260 => _260.id]), () => ( null));
4604
4656
  index = loc.index + 1;
4605
4657
  }
4606
- const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, layer, parentId, index);
4658
+ const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, layer, parentId, index);
4607
4659
  const live = type === "strokes" ? { liveStrokes: { ..._nullishCoalesce(this.doc.liveStrokes, () => ( {})), [layer.id]: [] } } : {};
4608
4660
  this.commit(type === "group" ? "Add group" : type === "strokes" ? "Add stroke layer" : "Add layer", { ...this.doc, layers, activeLayerId: layer.id, ...live });
4609
4661
  return this.describeLayer(layer);
@@ -4611,9 +4663,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4611
4663
  updateLayer(id, update) {
4612
4664
  this.requireIdle("changing a layer");
4613
4665
  const l = this.requireLayer(id);
4614
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, l, "all") && Object.keys(update).some((k) => k !== "locks")) throw new PaintEditorError(`Layer "${l.name}" is fully locked; unlock it first (locks {all: false}).`);
4666
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, l, "all") && Object.keys(update).some((k) => k !== "locks")) throw new PaintEditorError(`Layer "${l.name}" is fully locked; unlock it first (locks {all: false}).`);
4615
4667
  if (update.opacity !== void 0 && !(update.opacity >= 0 && update.opacity <= 1)) throw new PaintEditorError(`opacity ${update.opacity} is out of range; use 0..1.`);
4616
- if (update.blend !== void 0 && !_chunkOLNIPTB3cjs.isBlendMode.call(void 0, update.blend) && !(l.type === "group" && update.blend === "pass-through")) {
4668
+ if (update.blend !== void 0 && !_chunk2VX55NFMcjs.isBlendMode.call(void 0, update.blend) && !(l.type === "group" && update.blend === "pass-through")) {
4617
4669
  throw new PaintEditorError(`Unknown blend mode "${update.blend}". Call get_canvas_info for the blend modes.`);
4618
4670
  }
4619
4671
  if (update.name !== void 0 && !update.name.trim()) throw new PaintEditorError("name is empty; give the layer a name.");
@@ -4627,31 +4679,119 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4627
4679
  const locks = { ..._nullishCoalesce(l.locks, () => ( {})), ...update.locks };
4628
4680
  next.locks = Object.values(locks).some(Boolean) ? locks : void 0;
4629
4681
  }
4630
- this.commit("Layer properties", { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, id, () => next) });
4682
+ this.commit("Layer properties", { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, id, () => next) });
4631
4683
  return this.describeLayer(next);
4632
4684
  }
4685
+ // --- Layer effects (layer styles) ---------------------------------------------
4686
+ /** A layer's live effects (an empty, enabled list when it has none). */
4687
+ getLayerEffects(id) {
4688
+ return _nullishCoalesce(this.requireLayer(id).effects, () => ( { enabled: true, items: [] }));
4689
+ }
4690
+ /**
4691
+ * Adds a live effect of `kind` (outer and inner glow, drop and inner shadow, stroke, bevel &
4692
+ * emboss, satin, colour / gradient / pattern overlay) with Photoshop's defaults and `settings`
4693
+ * applied, at `index` in the layer's list (default the end). The effect is drawn from the
4694
+ * layer's pixels when it is composited, so it follows later painting. One undo step.
4695
+ */
4696
+ addLayerEffect(id, kind, settings = {}, index) {
4697
+ if (!_chunkDPYAO5U6cjs.isLayerEffectKind.call(void 0, kind)) throw new PaintEditorError(`Unknown effect kind "${String(kind)}". Kinds: ${_chunkDPYAO5U6cjs.LAYER_EFFECT_KINDS.join(", ")}.`);
4698
+ const current = _nullishCoalesce(this.effectsLayer(id, "add effects").effects, () => ( { enabled: true, items: [] }));
4699
+ const ids = new Set(current.items.map((e) => e.id));
4700
+ let effectId = _chunkDPYAO5U6cjs.newEffectId.call(void 0, );
4701
+ while (ids.has(effectId)) effectId = _chunkDPYAO5U6cjs.newEffectId.call(void 0, );
4702
+ const { id: _id, kind: _kind, ...rest } = settings;
4703
+ const effect = effectGuard(() => _chunkDPYAO5U6cjs.mergeLayerEffect.call(void 0, _chunkDPYAO5U6cjs.defaultLayerEffect.call(void 0, kind, effectId), rest));
4704
+ const items = [...current.items];
4705
+ const at = index === void 0 ? items.length : Math.max(0, Math.min(items.length, Math.floor(index)));
4706
+ items.splice(at, 0, effect);
4707
+ this.writeLayerEffects(id, { ...current, items }, `Add ${_chunkDPYAO5U6cjs.layerEffectLabel.call(void 0, kind)}`, true);
4708
+ return { effect, effects: this.getLayerEffects(id) };
4709
+ }
4710
+ /**
4711
+ * Changes one effect: only the given settings (nested objects replace whole; `null` removes an
4712
+ * optional contour or texture). One undo step, or with `commitToHistory` false folded into the
4713
+ * last change of this effect (a slider drag). Returns the layer's effects.
4714
+ */
4715
+ updateLayerEffect(id, effectId, changes, commitToHistory = true) {
4716
+ const current = this.effectsLayer(id, "change its effects").effects;
4717
+ const i = this.requireEffect(id, effectId);
4718
+ const items = [...current.items];
4719
+ items[i] = effectGuard(() => _chunkDPYAO5U6cjs.mergeLayerEffect.call(void 0, items[i], changes));
4720
+ this.writeLayerEffects(id, { ...current, items }, `Change ${_chunkDPYAO5U6cjs.layerEffectLabel.call(void 0, items[i].kind)}`, commitToHistory);
4721
+ return this.getLayerEffects(id);
4722
+ }
4723
+ /** Removes one effect (one undo step). Returns the layer's remaining effects. */
4724
+ removeLayerEffect(id, effectId) {
4725
+ const current = this.effectsLayer(id, "change its effects").effects;
4726
+ const i = this.requireEffect(id, effectId);
4727
+ this.writeLayerEffects(id, { ...current, items: current.items.filter((e) => e.id !== effectId) }, `Remove ${_chunkDPYAO5U6cjs.layerEffectLabel.call(void 0, current.items[i].kind)}`, true);
4728
+ return this.getLayerEffects(id);
4729
+ }
4730
+ /** Turns all of a layer's effects on or off and, when given, sets Scale Effects (0.01..10). One undo step. */
4731
+ setLayerEffectsEnabled(id, enabled, scale, commitToHistory = true) {
4732
+ const current = _nullishCoalesce(this.effectsLayer(id, "change its effects").effects, () => ( { enabled: true, items: [] }));
4733
+ if (scale !== void 0 && !(Number.isFinite(scale) && scale >= 0.01 && scale <= 10)) throw new PaintEditorError(`scale must be from 0.01 to 10 (1 = 100 %), got ${scale}.`);
4734
+ const next = { ...current, enabled };
4735
+ if (scale !== void 0) {
4736
+ if (scale === 1) delete next.scale;
4737
+ else next.scale = scale;
4738
+ }
4739
+ this.writeLayerEffects(id, next, "Layer effects", commitToHistory);
4740
+ return this.getLayerEffects(id);
4741
+ }
4742
+ /** Replaces a layer's effects, validated (`null` removes them). One undo step. Returns the effects. */
4743
+ setLayerEffects(id, effects, commitToHistory = true) {
4744
+ this.effectsLayer(id, "change its effects");
4745
+ if (effects) effectGuard(() => _chunkDPYAO5U6cjs.validateLayerEffects.call(void 0, effects));
4746
+ this.writeLayerEffects(id, effects, "Layer effects", commitToHistory);
4747
+ return this.getLayerEffects(id);
4748
+ }
4749
+ /** Document patterns for pattern effects besides the built-in ones: none (paint documents bring none). */
4750
+ getDocumentPatterns() {
4751
+ return [];
4752
+ }
4753
+ effectsLayer(id, action) {
4754
+ this.requireIdle("changing layer effects");
4755
+ const l = this.requireLayer(id);
4756
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, l, "all")) throw new PaintEditorError(`Layer "${l.name}" is fully locked, so it can't ${action}; unlock it first (locks {all: false}).`);
4757
+ return l;
4758
+ }
4759
+ requireEffect(id, effectId) {
4760
+ const l = this.requireLayer(id);
4761
+ const items = _nullishCoalesce(_optionalChain([l, 'access', _261 => _261.effects, 'optionalAccess', _262 => _262.items]), () => ( []));
4762
+ const i = items.findIndex((e) => e.id === effectId);
4763
+ 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.`);
4764
+ return i;
4765
+ }
4766
+ /** Writes a layer's effects (dropped when empty, enabled and unscaled), as an undo step or folded into the last one. */
4767
+ writeLayerEffects(id, effects, label, commitToHistory) {
4768
+ const next = { ...this.requireLayer(id) };
4769
+ if (effects && (effects.items.length || effects.psd || effects.scale !== void 0 || !effects.enabled)) next.effects = effects;
4770
+ else delete next.effects;
4771
+ this.commitOrAmend(label, { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, id, () => next) }, commitToHistory);
4772
+ }
4633
4773
  removeLayer(id) {
4634
4774
  this.requireIdle("removing a layer");
4635
4775
  const l = this.requireLayer(id);
4636
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, l, "all")) throw new PaintEditorError(`Layer "${l.name}" is fully locked; unlock it before removing it.`);
4637
- const wetIds = this.wet.wetLayerIds().filter((x) => x === id || l.type === "group" && _chunkHB4ICNNAcjs.findLayer.call(void 0, l.children, x));
4776
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, l, "all")) throw new PaintEditorError(`Layer "${l.name}" is fully locked; unlock it before removing it.`);
4777
+ const wetIds = this.wet.wetLayerIds().filter((x) => x === id || l.type === "group" && _chunkDPYAO5U6cjs.findLayer.call(void 0, l.children, x));
4638
4778
  if (wetIds.length) {
4639
4779
  this.beginWetOp();
4640
4780
  for (const x of wetIds) this.wet.world.removeLane(x);
4641
4781
  }
4642
- const layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
4782
+ const layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
4643
4783
  let active = this.doc.activeLayerId;
4644
- if (active && !_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.flattenLayers.call(void 0, layers), 'access', _255 => _255.filter, 'call', _256 => _256((x) => x.type === "pixel"), 'access', _257 => _257.pop, 'call', _258 => _258(), 'optionalAccess', _259 => _259.id]), () => ( null));
4645
- this.commit("Remove layer", { ...this.doc, layers, activeLayerId: active, ...this.thickWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.stickersWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.liveStrokesWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.lightWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)) });
4784
+ if (active && !_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.flattenLayers.call(void 0, layers), 'access', _263 => _263.filter, 'call', _264 => _264((x) => x.type === "pixel"), 'access', _265 => _265.pop, 'call', _266 => _266(), 'optionalAccess', _267 => _267.id]), () => ( null));
4785
+ 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)) });
4646
4786
  return { removed: id, activeLayerId: active };
4647
4787
  }
4648
4788
  duplicateLayer(id) {
4649
4789
  this.requireIdle("duplicating a layer");
4650
- if (_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) {
4790
+ if (_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)) {
4651
4791
  const inside = (l) => l.type === "group" ? l.children.flatMap(inside) : [l.id];
4652
- this.dryLayersFirst(inside(_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id).layer));
4792
+ this.dryLayersFirst(inside(_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id).layer));
4653
4793
  }
4654
- const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id);
4794
+ const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id);
4655
4795
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
4656
4796
  const thick = { ..._nullishCoalesce(this.doc.thick, () => ( {})) };
4657
4797
  const stickers = { ..._nullishCoalesce(this.doc.stickers, () => ( {})) };
@@ -4667,43 +4807,43 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4667
4807
  return l.type === "group" ? { ...l, id: id2, children: l.children.map(copy) } : { ...l, id: id2 };
4668
4808
  };
4669
4809
  const dup = { ...copy(loc.layer), name: `${loc.layer.name} copy` };
4670
- const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _260 => _260.parent, 'optionalAccess', _261 => _261.id]), () => ( null)), loc.index + 1);
4810
+ const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _268 => _268.parent, 'optionalAccess', _269 => _269.id]), () => ( null)), loc.index + 1);
4671
4811
  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 } : {} }));
4672
4812
  return this.describeLayer(dup);
4673
4813
  }
4674
4814
  /** Moves a layer to `index` (0 = bottom) within `parentId` (default its own parent; `null` = top level). */
4675
4815
  moveLayer(id, index, parentId) {
4676
4816
  this.requireIdle("moving a layer");
4677
- const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id);
4817
+ const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id);
4678
4818
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
4679
- const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _262 => _262.parent, 'optionalAccess', _263 => _263.id]), () => ( null)) : parentId;
4819
+ const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _270 => _270.parent, 'optionalAccess', _271 => _271.id]), () => ( null)) : parentId;
4680
4820
  if (target) {
4681
4821
  const g = this.requireLayer(target);
4682
4822
  if (g.type !== "group") throw new PaintEditorError(`Layer "${g.name}" is not a group; pass a group id as parentId.`);
4683
- if (target === id || loc.layer.type === "group" && _chunkHB4ICNNAcjs.findLayer.call(void 0, loc.layer.children, target)) throw new PaintEditorError("A group cannot move into itself.");
4823
+ if (target === id || loc.layer.type === "group" && _chunkDPYAO5U6cjs.findLayer.call(void 0, loc.layer.children, target)) throw new PaintEditorError("A group cannot move into itself.");
4684
4824
  }
4685
- const without = _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
4686
- const siblings = target ? _chunkHB4ICNNAcjs.findLayer.call(void 0, without, target).layer.children : without;
4825
+ const without = _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
4826
+ const siblings = target ? _chunkDPYAO5U6cjs.findLayer.call(void 0, without, target).layer.children : without;
4687
4827
  if (!Number.isInteger(index) || index < 0 || index > siblings.length) throw new PaintEditorError(`index ${index} is out of range; use 0..${siblings.length} (0 is the bottom).`);
4688
- const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, without, loc.layer, target, index);
4828
+ const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, without, loc.layer, target, index);
4689
4829
  this.commit("Move layer", { ...this.doc, layers });
4690
4830
  return this.describeLayer(loc.layer);
4691
4831
  }
4692
4832
  /** Merges a pixel layer into the pixel layer below it (keeping the lower one's settings). */
4693
4833
  mergeDown(id) {
4694
4834
  this.requireIdle("merging");
4695
- const pre = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id);
4835
+ const pre = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id);
4696
4836
  if (pre) {
4697
4837
  const sib = pre.parent ? pre.parent.children : this.doc.layers;
4698
- this.dryLayersFirst([id, _optionalChain([sib, 'access', _264 => _264[pre.index - 1], 'optionalAccess', _265 => _265.id])].filter((x) => Boolean(x)));
4838
+ this.dryLayersFirst([id, _optionalChain([sib, 'access', _272 => _272[pre.index - 1], 'optionalAccess', _273 => _273.id])].filter((x) => Boolean(x)));
4699
4839
  }
4700
- const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id);
4840
+ const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id);
4701
4841
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
4702
4842
  const siblings = loc.parent ? loc.parent.children : this.doc.layers;
4703
4843
  const below = siblings[loc.index - 1];
4704
4844
  const upper = loc.layer;
4705
4845
  if (!isPixelLayer(upper) || !isPixelLayer(below)) throw new PaintEditorError("Merge down needs a pixel layer directly above another pixel layer in the same group.");
4706
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, below, "pixels")) throw new PaintEditorError(`Layer "${below.name}" has its pixels locked; unlock it to merge into it.`);
4846
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, below, "pixels")) throw new PaintEditorError(`Layer "${below.name}" has its pixels locked; unlock it to merge into it.`);
4707
4847
  const rect = unionRect(this.describeLayer(below).bounds, this.describeLayer(upper).bounds);
4708
4848
  let surface = _chunk474IQG74cjs.emptySurface.call(void 0, 4);
4709
4849
  if (rect) {
@@ -4713,9 +4853,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4713
4853
  surface = _chunk474IQG74cjs.surfaceFromPixels.call(void 0, { width: rect.width, height: rect.height, data: px }, 4, rect.x, rect.y);
4714
4854
  }
4715
4855
  const merged = { ...below, surface, offset: { x: 0, y: 0 } };
4716
- const layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, upper.id, () => null), below.id, () => merged);
4856
+ const layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, upper.id, () => null), below.id, () => merged);
4717
4857
  const toDoc = (t, l) => t ? _chunk474IQG74cjs.translateSurface.call(void 0, t, l.offset.x, l.offset.y) : void 0;
4718
- const mergedLight = _optionalChain([this, 'access', _266 => _266.doc, 'access', _267 => _267.light, 'optionalAccess', _268 => _268[upper.id]]) || _optionalChain([this, 'access', _269 => _269.doc, 'access', _270 => _270.light, 'optionalAccess', _271 => _271[below.id]]) ? mergeLight(toDoc(_optionalChain([this, 'access', _272 => _272.doc, 'access', _273 => _273.light, 'optionalAccess', _274 => _274[below.id]]), below), upper.visible ? toDoc(_optionalChain([this, 'access', _275 => _275.doc, 'access', _276 => _276.light, 'optionalAccess', _277 => _277[upper.id]]), upper) : void 0, _chunk474IQG74cjs.translateSurface.call(void 0, upper.surface, upper.offset.x, upper.offset.y)) : void 0;
4858
+ const mergedLight = _optionalChain([this, 'access', _274 => _274.doc, 'access', _275 => _275.light, 'optionalAccess', _276 => _276[upper.id]]) || _optionalChain([this, 'access', _277 => _277.doc, 'access', _278 => _278.light, 'optionalAccess', _279 => _279[below.id]]) ? mergeLight(toDoc(_optionalChain([this, 'access', _280 => _280.doc, 'access', _281 => _281.light, 'optionalAccess', _282 => _282[below.id]]), below), upper.visible ? toDoc(_optionalChain([this, 'access', _283 => _283.doc, 'access', _284 => _284.light, 'optionalAccess', _285 => _285[upper.id]]), upper) : void 0, _chunk474IQG74cjs.translateSurface.call(void 0, upper.surface, upper.offset.x, upper.offset.y)) : void 0;
4719
4859
  const lightAfter = _nullishCoalesce(this.lightWithout([upper.id, below.id]).light, () => ( (this.doc.light ? { ...this.doc.light } : void 0)));
4720
4860
  const light = mergedLight ? { ..._nullishCoalesce(lightAfter, () => ( {})), [below.id]: mergedLight } : lightAfter;
4721
4861
  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 } : {} }));
@@ -4730,7 +4870,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4730
4870
  this.wet.world.removeLane(l.id);
4731
4871
  }
4732
4872
  const bounds = this.describeLayer(l).bounds;
4733
- this.commit("Clear layer", this.withPaintEvent({ ...this.doc, layers: _chunkHB4ICNNAcjs.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', _278 => _278.doc, 'access', _279 => _279.liveStrokes, 'optionalAccess', _280 => _280[l.id]]) ? { liveStrokes: { ...this.doc.liveStrokes, [l.id]: [] } } : {}, ...this.lightWithout([l.id]) }, { kind: "clear", layerId: l.id }));
4873
+ 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', _286 => _286.doc, 'access', _287 => _287.liveStrokes, 'optionalAccess', _288 => _288[l.id]]) ? { liveStrokes: { ...this.doc.liveStrokes, [l.id]: [] } } : {}, ...this.lightWithout([l.id]) }, { kind: "clear", layerId: l.id }));
4734
4874
  return { layerId: l.id, bounds };
4735
4875
  }
4736
4876
  /**
@@ -4740,8 +4880,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4740
4880
  fillLayer(options = {}) {
4741
4881
  this.requireIdle("filling");
4742
4882
  const fillTarget = this.paintTarget(options.layerId, "fill");
4743
- if (_optionalChain([this, 'access', _281 => _281.doc, 'access', _282 => _282.stickers, 'optionalAccess', _283 => _283[fillTarget.id], 'optionalAccess', _284 => _284.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
4744
- if (_optionalChain([this, 'access', _285 => _285.doc, 'access', _286 => _286.liveStrokes, 'optionalAccess', _287 => _287[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).`);
4883
+ if (_optionalChain([this, 'access', _289 => _289.doc, 'access', _290 => _290.stickers, 'optionalAccess', _291 => _291[fillTarget.id], 'optionalAccess', _292 => _292.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
4884
+ if (_optionalChain([this, 'access', _293 => _293.doc, 'access', _294 => _294.liveStrokes, 'optionalAccess', _295 => _295[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).`);
4745
4885
  this.dryLayersFirst([_nullishCoalesce(_nullishCoalesce(options.layerId, () => ( this.doc.activeLayerId)), () => ( ""))]);
4746
4886
  const l = this.paintTarget(options.layerId, "fill");
4747
4887
  const color = options.color === void 0 ? this.color : parseColor(options.color);
@@ -4751,16 +4891,16 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4751
4891
  if (!(grainAmount >= 0 && grainAmount <= 1)) throw new PaintEditorError(`grain ${grainAmount} is out of range; use 0..1.`);
4752
4892
  const pressure = _nullishCoalesce(options.pressure, () => ( 0.5));
4753
4893
  const blend = _nullishCoalesce(options.blend, () => ( "normal"));
4754
- if (!_chunkOLNIPTB3cjs.isBlendMode.call(void 0, blend)) throw new PaintEditorError(`Unknown blend mode "${blend}".`);
4894
+ if (!_chunk2VX55NFMcjs.isBlendMode.call(void 0, blend)) throw new PaintEditorError(`Unknown blend mode "${blend}".`);
4755
4895
  const { width, height } = this.doc.canvas;
4756
4896
  const rect = { x: 0, y: 0, width, height };
4757
- const coverage = new (0, _chunkPQ3H2AANcjs.CoverageMap)();
4897
+ const coverage = new (0, _chunkI7NJPHWVcjs.CoverageMap)();
4758
4898
  const depth = grainAmount * this.doc.paper.depth;
4759
4899
  const grain = depth > 0 ? paperGrain(this.doc.paper) : null;
4760
4900
  for (const { tx, ty } of _chunk474IQG74cjs.tilesInRect.call(void 0, rect)) {
4761
4901
  const r = { x: tx * _chunk474IQG74cjs.TILE, y: ty * _chunk474IQG74cjs.TILE, width: Math.min(_chunk474IQG74cjs.TILE, width - tx * _chunk474IQG74cjs.TILE), height: Math.min(_chunk474IQG74cjs.TILE, height - ty * _chunk474IQG74cjs.TILE) };
4762
4902
  const vals = new Float32Array(r.width * r.height);
4763
- for (let y = 0, k = 0; y < r.height; y++) for (let x = 0; x < r.width; x++, k++) vals[k] = grain ? _chunkPQ3H2AANcjs.grainCatch.call(void 0, grain.at(r.x + x + 0.5, r.y + y + 0.5), depth, pressure) : 1;
4903
+ for (let y = 0, k = 0; y < r.height; y++) for (let x = 0; x < r.width; x++, k++) vals[k] = grain ? _chunkI7NJPHWVcjs.grainCatch.call(void 0, grain.at(r.x + x + 0.5, r.y + y + 0.5), depth, pressure) : 1;
4764
4904
  coverage.accumulate(r, vals, 1);
4765
4905
  }
4766
4906
  const apply = {
@@ -4769,14 +4909,14 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4769
4909
  background: rgbaOf(this.doc.paper.color),
4770
4910
  opacity,
4771
4911
  blend,
4772
- lockTransparency: _chunkHB4ICNNAcjs.isLayerLocked.call(void 0, l, "transparency"),
4912
+ lockTransparency: _chunkDPYAO5U6cjs.isLayerLocked.call(void 0, l, "transparency"),
4773
4913
  selection: null,
4774
4914
  offset: l.offset
4775
4915
  };
4776
4916
  const surface = this.applyCoverage(l, coverage, rect, apply);
4777
- const lit = _optionalChain([this, 'access', _288 => _288.doc, 'access', _289 => _289.light, 'optionalAccess', _290 => _290[l.id]]);
4917
+ const lit = _optionalChain([this, 'access', _296 => _296.doc, 'access', _297 => _297.light, 'optionalAccess', _298 => _298[l.id]]);
4778
4918
  const light = lit ? withLayerLight(this.doc.light, l.id, scaleLight(lit, 1 - opacity)) : void 0;
4779
- this.commit("Fill layer", this.withPaintEvent(this.withWetEvents({ ...this.doc, layers: _chunkHB4ICNNAcjs.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 } }));
4919
+ 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 } }));
4780
4920
  return { layerId: l.id, bounds: rect };
4781
4921
  }
4782
4922
  applyCoverage(l, coverage, rect, apply) {
@@ -4784,8 +4924,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4784
4924
  const tiles = new Map(base.tiles);
4785
4925
  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 })) {
4786
4926
  const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
4787
- const src = _nullishCoalesce(_optionalChain([base, 'access', _291 => _291.tiles, 'access', _292 => _292.get, 'call', _293 => _293(key), 'optionalAccess', _294 => _294.data]), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4)));
4788
- const tile = _chunk474IQG74cjs.finishTile.call(void 0, _chunkPQ3H2AANcjs.applyStrokeToTile.call(void 0, coverage, src, 4, tx, ty, apply), 4, 0);
4927
+ const src = _nullishCoalesce(_optionalChain([base, 'access', _299 => _299.tiles, 'access', _300 => _300.get, 'call', _301 => _301(key), 'optionalAccess', _302 => _302.data]), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4)));
4928
+ const tile = _chunk474IQG74cjs.finishTile.call(void 0, _chunkI7NJPHWVcjs.applyStrokeToTile.call(void 0, coverage, src, 4, tx, ty, apply), 4, 0);
4789
4929
  if (tile) tiles.set(key, tile);
4790
4930
  else tiles.delete(key);
4791
4931
  }
@@ -4817,7 +4957,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4817
4957
  }
4818
4958
  /** The effect a layer is drawn from, or `undefined` for other layers. */
4819
4959
  getEffectLayer(layerId) {
4820
- return _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _295 => _295.doc, 'access', _296 => _296.effectLayers, 'optionalAccess', _297 => _297[layerId]]) : void 0;
4960
+ return _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _303 => _303.doc, 'access', _304 => _304.effectLayers, 'optionalAccess', _305 => _305[layerId]]) : void 0;
4821
4961
  }
4822
4962
  /** The effect paper (without its pixels), or `null`. */
4823
4963
  getPaperEffect() {
@@ -4854,8 +4994,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4854
4994
  /** A pixel layer that takes effect pixels: unlocked, visible, no sticker layer, no wet paint. */
4855
4995
  effectTarget(layerId, what) {
4856
4996
  const l = this.paintTarget(layerId, what);
4857
- if (_optionalChain([this, 'access', _298 => _298.doc, 'access', _299 => _299.stickers, 'optionalAccess', _300 => _300[l.id], 'optionalAccess', _301 => _301.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
4858
- if (_optionalChain([this, 'access', _302 => _302.doc, 'access', _303 => _303.liveStrokes, 'optionalAccess', _304 => _304[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).`);
4997
+ if (_optionalChain([this, 'access', _306 => _306.doc, 'access', _307 => _307.stickers, 'optionalAccess', _308 => _308[l.id], 'optionalAccess', _309 => _309.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
4998
+ if (_optionalChain([this, 'access', _310 => _310.doc, 'access', _311 => _311.liveStrokes, 'optionalAccess', _312 => _312[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).`);
4859
4999
  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.`);
4860
5000
  return l;
4861
5001
  }
@@ -4894,8 +5034,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4894
5034
  const was = this.doc.paperEffect;
4895
5035
  const paperEffect = {
4896
5036
  ...this.sourceOf(d, values, options.time),
4897
- opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _305 => _305.opacity]))), () => ( 1)),
4898
- blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _306 => _306.blend]))), () => ( "multiply")),
5037
+ opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _313 => _313.opacity]))), () => ( 1)),
5038
+ blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _314 => _314.blend]))), () => ( "multiply")),
4899
5039
  image: { width: pixels.width, height: pixels.height, data: new Uint8ClampedArray(pixels.data) },
4900
5040
  version: nextPaperEffectVersion()
4901
5041
  };
@@ -4939,17 +5079,17 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4939
5079
  this.requireIdle("adding a layer");
4940
5080
  this.checkOpacity(options.opacity);
4941
5081
  this.checkTime(options.time);
4942
- if (options.blend !== void 0 && !_chunkOLNIPTB3cjs.isBlendMode.call(void 0, options.blend)) throw new PaintEditorError(`Unknown blend mode "${options.blend}". Call get_canvas_info for the blend modes.`);
5082
+ if (options.blend !== void 0 && !_chunk2VX55NFMcjs.isBlendMode.call(void 0, options.blend)) throw new PaintEditorError(`Unknown blend mode "${options.blend}". Call get_canvas_info for the blend modes.`);
4943
5083
  if (options.aboveId !== void 0) this.requireLayer(options.aboveId);
4944
5084
  const d = await this.describeEffect(effect, "layer");
4945
5085
  const values = this.effectValues(d, { ...d.defaults }, options.values);
4946
5086
  const pixels = await this.renderEffectCanvas(d, values, options.time);
4947
5087
  this.requireIdle("adding a layer");
4948
5088
  const above = _nullishCoalesce(options.aboveId, () => ( this.doc.activeLayerId));
4949
- const loc = above ? _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, above) : null;
5089
+ const loc = above ? _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, above) : null;
4950
5090
  if (options.aboveId !== void 0 && !loc) throw new PaintEditorError(`Layer "${options.aboveId}" was removed while the effect rendered.`);
4951
- const layer = { ...createPaintLayer(_optionalChain([options, 'access', _307 => _307.name, 'optionalAccess', _308 => _308.trim, 'call', _309 => _309()]) || d.name), surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
4952
- const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _310 => _310.parent, 'optionalAccess', _311 => _311.id]), () => ( null)), loc ? loc.index + 1 : void 0);
5091
+ const layer = { ...createPaintLayer(_optionalChain([options, 'access', _315 => _315.name, 'optionalAccess', _316 => _316.trim, 'call', _317 => _317()]) || d.name), surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
5092
+ const layers = _chunkDPYAO5U6cjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _318 => _318.parent, 'optionalAccess', _319 => _319.id]), () => ( null)), loc ? loc.index + 1 : void 0);
4953
5093
  const source = this.sourceOf(d, values, options.time);
4954
5094
  this.commit("Add effect layer", { ...this.doc, layers, activeLayerId: layer.id, effectLayers: { ..._nullishCoalesce(this.doc.effectLayers, () => ( {})), [layer.id]: source } });
4955
5095
  return { layer: this.describeLayer(layer), source };
@@ -4973,7 +5113,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
4973
5113
  this.requireIdle("changing an effect layer");
4974
5114
  if (!isPixelLayer(now)) throw new PaintEditorError(`Layer "${l.name}" was removed while the effect rendered.`);
4975
5115
  const source = this.sourceOf(d, values, time);
4976
- this.commitOrAmend("Effect layer", { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...now, surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), offset: { x: 0, y: 0 } })), effectLayers: { ..._nullishCoalesce(this.doc.effectLayers, () => ( {})), [l.id]: source } }, commitToHistory);
5116
+ this.commitOrAmend("Effect layer", { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...now, surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), offset: { x: 0, y: 0 } })), effectLayers: { ..._nullishCoalesce(this.doc.effectLayers, () => ( {})), [l.id]: source } }, commitToHistory);
4977
5117
  return source;
4978
5118
  }
4979
5119
  /** Turns an effect layer into a plain pixel layer, keeping its pixels (one undo step). */
@@ -5001,9 +5141,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5001
5141
  const rect = this.canvasRectOf(now);
5002
5142
  const before = _chunk474IQG74cjs.readRegion.call(void 0, now.surface, rect);
5003
5143
  let after = overPixels(before, pixels.data, _nullishCoalesce(options.opacity, () => ( 1)));
5004
- if (options.lockTransparency || _chunkHB4ICNNAcjs.isLayerLocked.call(void 0, now, "transparency")) after = mixPixels(before, after, 1);
5144
+ if (options.lockTransparency || _chunkDPYAO5U6cjs.isLayerLocked.call(void 0, now, "transparency")) after = mixPixels(before, after, 1);
5005
5145
  const surface = _chunk474IQG74cjs.writeRegion.call(void 0, now.surface, rect, after);
5006
- this.commit("Effect fill", { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, now.id, () => ({ ...now, surface })) });
5146
+ this.commit("Effect fill", { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, now.id, () => ({ ...now, surface })) });
5007
5147
  return { layerId: now.id, source: this.sourceOf(d, values, options.time) };
5008
5148
  }
5009
5149
  // --- Effect paint ----------------------------------------------------------------
@@ -5027,7 +5167,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5027
5167
  this.checkTime(source.time);
5028
5168
  let map;
5029
5169
  try {
5030
- map = _chunkQ2UYUWAZcjs.readEffectStrokeMap.call(void 0, source.map);
5170
+ map = _chunkH4AOUUBEcjs.readEffectStrokeMap.call(void 0, source.map);
5031
5171
  } catch (e) {
5032
5172
  throw new PaintEditorError(e.message);
5033
5173
  }
@@ -5058,9 +5198,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5058
5198
  }
5059
5199
  /** The rendered pixels of an effect paint at the current canvas size, or `null` when it has not been rendered. */
5060
5200
  effectPaintImage(p) {
5061
- const key = _chunkQ2UYUWAZcjs.effectPaintKey.call(void 0, p);
5201
+ const key = _chunkH4AOUUBEcjs.effectPaintKey.call(void 0, p);
5062
5202
  const img = this.effectPaintPixels.get(key);
5063
- const size = _chunkQ2UYUWAZcjs.effectPaintSize.call(void 0, p, this.doc.canvas);
5203
+ const size = _chunkH4AOUUBEcjs.effectPaintSize.call(void 0, p, this.doc.canvas);
5064
5204
  if (!img || img.width !== size.width || img.height !== size.height) return null;
5065
5205
  this.effectPaintPixels.delete(key);
5066
5206
  this.effectPaintPixels.set(key, img);
@@ -5074,7 +5214,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5074
5214
  const what = `the effect "${p.effect}"${p.provider ? ` from provider "${p.provider}"` : ""}`;
5075
5215
  if (!provider) throw new PaintEditorError(`Effect paint needs ${what}, but no effects provider is registered; register it (setEffectsProvider) and try again.`);
5076
5216
  if (p.provider && provider.id !== p.provider) throw new PaintEditorError(`Effect paint needs ${what}, but the registered provider is "${provider.id}"; register "${p.provider}" (setEffectsProvider) and try again.`);
5077
- const { width, height } = _chunkQ2UYUWAZcjs.effectPaintSize.call(void 0, p, this.doc.canvas);
5217
+ const { width, height } = _chunkH4AOUUBEcjs.effectPaintSize.call(void 0, p, this.doc.canvas);
5078
5218
  let pixels;
5079
5219
  try {
5080
5220
  pixels = await this.effectsRenderer.render(provider, p.effect, { width, height }, { time: p.time, values: p.values });
@@ -5082,7 +5222,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5082
5222
  throw new PaintEditorError(`Effect paint could not render ${what}: ${e instanceof Error ? e.message : String(e)}`);
5083
5223
  }
5084
5224
  const img = { width, height, data: new Uint8ClampedArray(pixels.data), ...p.map ? { map: p.map } : {} };
5085
- this.effectPaintPixels.set(_chunkQ2UYUWAZcjs.effectPaintKey.call(void 0, p), img);
5225
+ this.effectPaintPixels.set(_chunkH4AOUUBEcjs.effectPaintKey.call(void 0, p), img);
5086
5226
  while (this.effectPaintPixels.size > _PaintEditorController.EFFECT_PAINT_CACHE) this.effectPaintPixels.delete(this.effectPaintPixels.keys().next().value);
5087
5227
  return img;
5088
5228
  }
@@ -5093,7 +5233,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5093
5233
  async prepareEffectPaints(paints) {
5094
5234
  const seen = /* @__PURE__ */ new Set();
5095
5235
  for (const p of paints) {
5096
- const key = _chunkQ2UYUWAZcjs.effectPaintKey.call(void 0, p);
5236
+ const key = _chunkH4AOUUBEcjs.effectPaintKey.call(void 0, p);
5097
5237
  if (seen.has(key)) continue;
5098
5238
  seen.add(key);
5099
5239
  await this.renderEffectPaint(p);
@@ -5102,7 +5242,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5102
5242
  /** Renders the effect paints of recorded strokes (default all of them) before a replay. */
5103
5243
  async prepareStrokeEffects(strokeIds) {
5104
5244
  const ids = strokeIds ? new Set(strokeIds) : null;
5105
- const paints = this.doc.strokes.filter((s) => (!ids || ids.has(s.id)) && _optionalChain([s, 'access', _312 => _312.paint, 'optionalAccess', _313 => _313.type]) === "effect").map((s) => s.paint);
5245
+ const paints = this.doc.strokes.filter((s) => (!ids || ids.has(s.id)) && _optionalChain([s, 'access', _320 => _320.paint, 'optionalAccess', _321 => _321.type]) === "effect").map((s) => s.paint);
5106
5246
  await this.prepareEffectPaints(paints);
5107
5247
  }
5108
5248
  /** A small preview of the effect paint (a PNG data URL `size` px wide), or `null` without a rendered one. */
@@ -5122,7 +5262,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5122
5262
  for (let c = 0; c < 4; c++) out[o + c] = img.data[i + c];
5123
5263
  }
5124
5264
  }
5125
- return _chunkOLNIPTB3cjs.pngDataUrl.call(void 0, w, h, out);
5265
+ return _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, w, h, out);
5126
5266
  }
5127
5267
  /**
5128
5268
  * The effect paint a stroke paints with and its pixels, or `null`: the stroke's own effect
@@ -5131,11 +5271,11 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5131
5271
  * its pixels are not rendered.
5132
5272
  */
5133
5273
  strokeEffect(init, brush) {
5134
- if (!_chunkQ2UYUWAZcjs.brushTakesPaint.call(void 0, brush)) return null;
5274
+ if (!_chunkH4AOUUBEcjs.brushTakesPaint.call(void 0, brush)) return null;
5135
5275
  let source = null;
5136
5276
  if (init.paint !== void 0) {
5137
- if (!_chunkQ2UYUWAZcjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
5138
- source = _chunkQ2UYUWAZcjs.readPaintEffectPaint.call(void 0, init.paint);
5277
+ if (!_chunkH4AOUUBEcjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
5278
+ source = _chunkH4AOUUBEcjs.readPaintEffectPaint.call(void 0, init.paint);
5139
5279
  if (!source) throw new PaintEditorError("The stroke's effect paint needs an effect id and values (getEffectPaint returns one).");
5140
5280
  } else if (init.color === void 0 && !brush.paint) {
5141
5281
  if (this.effectPaintPending) throw new PaintEditorError(`The effect paint "${this.effectPaintPending.effect}" is still rendering; wait for set_effect_paint to finish, then paint.`);
@@ -5165,14 +5305,14 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5165
5305
  const before = _chunk474IQG74cjs.readRegion.call(void 0, l.surface, rect);
5166
5306
  const inputs = { source: { width: rect.width, height: rect.height, data: before } };
5167
5307
  const heightInput = d.inputs.find((i) => i.kind === "image" && /^(height|depth|relief)$/i.test(i.name));
5168
- const relief = _optionalChain([this, 'access', _314 => _314.doc, 'access', _315 => _315.thick, 'optionalAccess', _316 => _316[l.id]]);
5308
+ const relief = _optionalChain([this, 'access', _322 => _322.doc, 'access', _323 => _323.thick, 'optionalAccess', _324 => _324[l.id]]);
5169
5309
  if (heightInput && relief) {
5170
5310
  const h = _chunk474IQG74cjs.readRegion.call(void 0, relief.height, rect);
5171
5311
  const rgba = new Uint8ClampedArray(rect.width * rect.height * 4);
5172
5312
  for (let i = 0; i < h.length; i++) rgba.set([h[i], h[i], h[i], 255], i * 4);
5173
5313
  inputs[heightInput.name] = { width: rect.width, height: rect.height, data: rgba };
5174
5314
  }
5175
- const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _317 => _317.inputs, 'access', _318 => _318.find, 'call', _319 => _319((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _320 => _320.name])), 'optionalAccess', _321 => _321.name]), () => ( "source"));
5315
+ const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _325 => _325.inputs, 'access', _326 => _326.find, 'call', _327 => _327((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _328 => _328.name])), 'optionalAccess', _329 => _329.name]), () => ( "source"));
5176
5316
  if (sourceInput !== "source") {
5177
5317
  inputs[sourceInput] = inputs.source;
5178
5318
  delete inputs.source;
@@ -5180,17 +5320,17 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5180
5320
  const out = await this.effectsRenderer.render(this.effects.require(), d.id, { width: rect.width, height: rect.height }, { time: _nullishCoalesce(options.time, () => ( 0)), values, inputs });
5181
5321
  const now = this.sameLayerAfterRender(l);
5182
5322
  const surface = _chunk474IQG74cjs.writeRegion.call(void 0, now.surface, rect, mixPixels(before, out.data, amount));
5183
- this.commit("Light effect", { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, now.id, () => ({ ...now, surface })) });
5323
+ this.commit("Light effect", { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, now.id, () => ({ ...now, surface })) });
5184
5324
  return { layerId: now.id, source: this.sourceOf(d, values, options.time), amount };
5185
5325
  }
5186
5326
  // --- Brushes -------------------------------------------------------------------
5187
5327
  findBrush(id) {
5188
- return _nullishCoalesce(_chunkQ2UYUWAZcjs.BUILTIN_BRUSHES.find((b) => b.id === id), () => ( this.userBrushes.find((b) => b.id === id)));
5328
+ return _nullishCoalesce(_chunkH4AOUUBEcjs.BUILTIN_BRUSHES.find((b) => b.id === id), () => ( this.userBrushes.find((b) => b.id === id)));
5189
5329
  }
5190
5330
  /** A library brush by id (`undefined` when unknown). */
5191
5331
  getBrush(id) {
5192
5332
  const b = this.findBrush(id);
5193
- return b ? _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, b, b) : void 0;
5333
+ return b ? _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, b, b) : void 0;
5194
5334
  }
5195
5335
  requireBrush(id) {
5196
5336
  const b = this.findBrush(id);
@@ -5205,19 +5345,20 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5205
5345
  const { id, ...changes } = update;
5206
5346
  const base = id !== void 0 ? this.requireBrush(id) : this.brush;
5207
5347
  if (changes.paint !== void 0 && changes.paint !== null) this.readStrokePaint(changes.paint);
5208
- const next = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
5348
+ const next = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
5209
5349
  if (base.builtin && !Object.keys(changes).length) next.builtin = true;
5210
5350
  else delete next.builtin;
5211
5351
  this.brush = next;
5212
5352
  this.emit([]);
5353
+ if (next.engine === "sticker" && next.sticker.stamps.some((r) => !_chunkZEYMKDYScjs.editorStampOf.call(void 0, r))) void this.prepareStickers(next.sticker.stamps).catch(() => this.emit([]));
5213
5354
  return this.brush;
5214
5355
  }
5215
5356
  /** Saves the active brush (or `brush`) into the user library under `id` / `name`. */
5216
5357
  saveBrush(options) {
5217
- if (!_chunkQ2UYUWAZcjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
5218
- if (_chunkQ2UYUWAZcjs.BUILTIN_BRUSHES.some((b) => b.id === options.id)) throw new PaintEditorError(`"${options.id}" is a built-in brush; save under another id.`);
5219
- const source = options.brush ? _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, options.brush, this.brush) : this.brush;
5220
- const saved = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { ...source, id: options.id, name: _nullishCoalesce(options.name, () => ( source.name)) });
5358
+ if (!_chunkH4AOUUBEcjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
5359
+ if (_chunkH4AOUUBEcjs.BUILTIN_BRUSHES.some((b) => b.id === options.id)) throw new PaintEditorError(`"${options.id}" is a built-in brush; save under another id.`);
5360
+ const source = options.brush ? _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, options.brush, this.brush) : this.brush;
5361
+ const saved = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { ...source, id: options.id, name: _nullishCoalesce(options.name, () => ( source.name)) });
5221
5362
  delete saved.builtin;
5222
5363
  const i = this.userBrushes.findIndex((b) => b.id === options.id);
5223
5364
  if (i >= 0) this.userBrushes[i] = saved;
@@ -5227,7 +5368,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5227
5368
  return saved;
5228
5369
  }
5229
5370
  removeBrush(id) {
5230
- if (_chunkQ2UYUWAZcjs.BUILTIN_BRUSHES.some((b) => b.id === id)) throw new PaintEditorError(`"${id}" is a built-in brush and cannot be removed.`);
5371
+ if (_chunkH4AOUUBEcjs.BUILTIN_BRUSHES.some((b) => b.id === id)) throw new PaintEditorError(`"${id}" is a built-in brush and cannot be removed.`);
5231
5372
  const i = this.userBrushes.findIndex((b) => b.id === id);
5232
5373
  if (i < 0) throw new PaintEditorError(`Unknown brush "${id}". Call list_brushes for the ids.`);
5233
5374
  this.userBrushes.splice(i, 1);
@@ -5236,12 +5377,12 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5236
5377
  }
5237
5378
  /** The user's saved brushes. */
5238
5379
  getUserBrushes() {
5239
- return this.userBrushes.map((b) => _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, b, b));
5380
+ return this.userBrushes.map((b) => _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, b, b));
5240
5381
  }
5241
5382
  /** A brush library file of the given brushes (default: the user's brushes). */
5242
5383
  exportBrushes(ids) {
5243
5384
  const list = ids ? ids.map((id) => this.requireBrush(id)) : this.userBrushes;
5244
- return { format: "pixerate-brushes", version: 1, brushes: list.map(_chunkQ2UYUWAZcjs.brushToJSON) };
5385
+ return { format: "pixerate-brushes", version: 1, brushes: list.map(_chunkH4AOUUBEcjs.brushToJSON) };
5245
5386
  }
5246
5387
  /**
5247
5388
  * Adds the brushes of a library file to the user library. A brush whose id is taken is skipped
@@ -5251,14 +5392,14 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5251
5392
  const problems = [];
5252
5393
  let list;
5253
5394
  try {
5254
- list = _chunkQ2UYUWAZcjs.parseBrushLibrary.call(void 0, file, problems);
5395
+ list = _chunkH4AOUUBEcjs.parseBrushLibrary.call(void 0, file, problems);
5255
5396
  } catch (e) {
5256
5397
  throw new PaintEditorError(e.message);
5257
5398
  }
5258
5399
  const added = [];
5259
5400
  const skipped = [];
5260
5401
  for (const b of list) {
5261
- if (_chunkQ2UYUWAZcjs.BUILTIN_BRUSHES.some((x) => x.id === b.id)) {
5402
+ if (_chunkH4AOUUBEcjs.BUILTIN_BRUSHES.some((x) => x.id === b.id)) {
5262
5403
  skipped.push(b.id);
5263
5404
  problems.push(`"${b.id}" is a built-in brush id; rename it to import it.`);
5264
5405
  continue;
@@ -5302,9 +5443,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5302
5443
  setPaint(paint) {
5303
5444
  let p;
5304
5445
  try {
5305
- p = _chunkPQ3H2AANcjs.parsePaintSource.call(void 0, paint);
5446
+ p = _chunkI7NJPHWVcjs.parsePaintSource.call(void 0, paint);
5306
5447
  } catch (e) {
5307
- if (e instanceof _chunkPQ3H2AANcjs.PaintSourceError) throw new PaintEditorError(e.message);
5448
+ if (e instanceof _chunkI7NJPHWVcjs.PaintSourceError) throw new PaintEditorError(e.message);
5308
5449
  throw e;
5309
5450
  }
5310
5451
  if (p.type === "color") {
@@ -5323,20 +5464,20 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5323
5464
  * brush's gradient, else the editor's gradient paint. Erasers, blenders and smudges take none.
5324
5465
  */
5325
5466
  strokeGradient(init, brush, color) {
5326
- if (!_chunkQ2UYUWAZcjs.brushTakesPaint.call(void 0, brush)) return null;
5467
+ if (!_chunkH4AOUUBEcjs.brushTakesPaint.call(void 0, brush)) return null;
5327
5468
  let g = null;
5328
5469
  if (init.paint !== void 0) {
5329
- if (_chunkQ2UYUWAZcjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
5470
+ if (_chunkH4AOUUBEcjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
5330
5471
  const p = this.readStrokePaint(init.paint);
5331
5472
  g = p.type === "gradient" ? p : null;
5332
5473
  } else g = _nullishCoalesce(brush.paint, () => ( (init.color === void 0 ? this.gradient : null)));
5333
- return g ? _chunkPQ3H2AANcjs.resolvePaintGradient.call(void 0, g, { paint: color, secondary: this.secondaryColor }) : null;
5474
+ return g ? _chunkI7NJPHWVcjs.resolvePaintGradient.call(void 0, g, { paint: color, secondary: this.secondaryColor }) : null;
5334
5475
  }
5335
5476
  readStrokePaint(raw) {
5336
5477
  try {
5337
- return _chunkPQ3H2AANcjs.parsePaintSource.call(void 0, raw);
5478
+ return _chunkI7NJPHWVcjs.parsePaintSource.call(void 0, raw);
5338
5479
  } catch (e) {
5339
- if (e instanceof _chunkPQ3H2AANcjs.PaintSourceError) throw new PaintEditorError(e.message);
5480
+ if (e instanceof _chunkI7NJPHWVcjs.PaintSourceError) throw new PaintEditorError(e.message);
5340
5481
  throw e;
5341
5482
  }
5342
5483
  }
@@ -5370,14 +5511,14 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5370
5511
  // --- Mixer Brush ---------------------------------------------------------------
5371
5512
  /** Fills the Mixer Brush reservoir with a colour (default the editor colour). */
5372
5513
  loadMixerBrush(color) {
5373
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, color === void 0 ? this.color : parseColor(color));
5374
- this.mixerLoad = _chunkPQ3H2AANcjs.loadMixer.call(void 0, this.mixerLoad, [r / 255, g / 255, b / 255]);
5514
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, color === void 0 ? this.color : parseColor(color));
5515
+ this.mixerLoad = _chunkI7NJPHWVcjs.loadMixer.call(void 0, this.mixerLoad, [r / 255, g / 255, b / 255]);
5375
5516
  this.emit([]);
5376
5517
  return this.mixerLoad;
5377
5518
  }
5378
5519
  /** Empties the pickup well (and with `emptyReservoir` the loaded paint too). */
5379
5520
  cleanMixerBrush(emptyReservoir = false) {
5380
- this.mixerLoad = emptyReservoir ? _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD : _chunkPQ3H2AANcjs.cleanMixer.call(void 0, this.mixerLoad);
5521
+ this.mixerLoad = emptyReservoir ? _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD : _chunkI7NJPHWVcjs.cleanMixer.call(void 0, this.mixerLoad);
5381
5522
  this.emit([]);
5382
5523
  return this.mixerLoad;
5383
5524
  }
@@ -5400,7 +5541,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5400
5541
  // --- Strokes -------------------------------------------------------------------
5401
5542
  strokeBrush(init) {
5402
5543
  let brush = init.brushId !== void 0 ? this.requireBrush(init.brushId) : this.brush;
5403
- if (init.brush) brush = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
5544
+ if (init.brush) brush = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
5404
5545
  return brush;
5405
5546
  }
5406
5547
  /**
@@ -5416,7 +5557,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5416
5557
  return symmetryCopies(this.guides.symmetry);
5417
5558
  }
5418
5559
  sessionFor(doc, init, host) {
5419
- if (init.paint !== void 0 && !_chunkQ2UYUWAZcjs.isPaintEffectPaint.call(void 0, init.paint)) {
5560
+ if (init.paint !== void 0 && !_chunkH4AOUUBEcjs.isPaintEffectPaint.call(void 0, init.paint)) {
5420
5561
  const p = this.readStrokePaint(init.paint);
5421
5562
  if (p.type === "color") init = { ...init, color: p.color, paint: void 0 };
5422
5563
  else init = { ...init, paint: p };
@@ -5424,11 +5565,11 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5424
5565
  let layer = (() => {
5425
5566
  const id = _nullishCoalesce(init.layerId, () => ( doc.activeLayerId));
5426
5567
  if (!id) throw new PaintEditorError("There is no active layer to paint on; add one with add_layer.");
5427
- const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, id);
5568
+ const loc = _chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, id);
5428
5569
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
5429
5570
  const l = loc.layer;
5430
5571
  if (!isPixelLayer(l)) throw new PaintEditorError(`Layer "${l.name}" is a group; paint on a pixel layer inside it.`);
5431
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it (update_layer locks) to paint on it.`);
5572
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it (update_layer locks) to paint on it.`);
5432
5573
  if (!l.visible) throw new PaintEditorError(`Layer "${l.name}" is hidden; show it (update_layer visible true) to paint on it.`);
5433
5574
  return l;
5434
5575
  })();
@@ -5437,43 +5578,43 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5437
5578
  if (brush.light.amount > 0) {
5438
5579
  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 (list_brushes category light), or set light.amount to 0 (set_brush).`);
5439
5580
  }
5440
- if (_optionalChain([doc, 'access', _322 => _322.liveStrokes, 'optionalAccess', _323 => _323[layer.id]])) {
5581
+ if (_optionalChain([doc, 'access', _330 => _330.liveStrokes, 'optionalAccess', _331 => _331[layer.id]])) {
5441
5582
  const why = liveStrokeRefusal(brush);
5442
5583
  if (why) throw new PaintEditorError(`Layer "${layer.name}" is a stroke layer. ${why}`);
5443
5584
  }
5444
- if (_optionalChain([doc, 'access', _324 => _324.liveStrokes, 'optionalAccess', _325 => _325[layer.id]]) && _optionalChain([effect, 'optionalAccess', _326 => _326.source, 'access', _327 => _327.live])) {
5445
- const key = _chunkQ2UYUWAZcjs.effectPaintKey.call(void 0, effect.source);
5585
+ if (_optionalChain([doc, 'access', _332 => _332.liveStrokes, 'optionalAccess', _333 => _333[layer.id]]) && _optionalChain([effect, 'optionalAccess', _334 => _334.source, 'access', _335 => _335.live])) {
5586
+ const key = _chunkH4AOUUBEcjs.effectPaintKey.call(void 0, effect.source);
5446
5587
  const { sources } = this.liveEffects(doc);
5447
- if (!sources.some((p) => _chunkQ2UYUWAZcjs.effectPaintKey.call(void 0, p) === key) && sources.length >= MAX_LIVE_EFFECT_SOURCES) {
5588
+ if (!sources.some((p) => _chunkH4AOUUBEcjs.effectPaintKey.call(void 0, p) === key) && sources.length >= MAX_LIVE_EFFECT_SOURCES) {
5448
5589
  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.`);
5449
5590
  }
5450
5591
  }
5451
- const stickerLayer = Boolean(_optionalChain([doc, 'access', _328 => _328.stickers, 'optionalAccess', _329 => _329[layer.id], 'optionalAccess', _330 => _330.length]));
5592
+ const stickerLayer = Boolean(_optionalChain([doc, 'access', _336 => _336.stickers, 'optionalAccess', _337 => _337[layer.id], 'optionalAccess', _338 => _338.length]));
5452
5593
  if (brush.engine === "sticker") {
5453
5594
  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.`);
5454
5595
  } else if (stickerLayer) {
5455
5596
  throw new PaintEditorError(`Layer "${layer.name}" is a sticker layer (its pixels are drawn from its stickers); paint on another layer (add_layer).`);
5456
5597
  }
5457
5598
  let wet;
5458
- if (_chunkQ2UYUWAZcjs.isWetBrush.call(void 0, brush)) {
5599
+ if (_chunkH4AOUUBEcjs.isWetBrush.call(void 0, brush)) {
5459
5600
  this.requireWetIdle("painting");
5460
5601
  if (layer.offset.x || layer.offset.y) {
5461
5602
  const moved = { ...layer, surface: _chunk474IQG74cjs.translateSurface.call(void 0, layer.surface, layer.offset.x, layer.offset.y), offset: { x: 0, y: 0 } };
5462
- this.doc = { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => moved) };
5463
- if (doc !== this.doc) doc = { ...doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, doc.layers, layer.id, () => moved) };
5603
+ this.doc = { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => moved) };
5604
+ if (doc !== this.doc) doc = { ...doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, doc.layers, layer.id, () => moved) };
5464
5605
  layer = moved;
5465
5606
  }
5466
- if (!this.wet.wetLayerIds().includes(layer.id) && this.wet.wetLayerIds().length >= _chunkVMROIWLLcjs.MAX_WET_LANES) {
5467
- throw new PaintEditorError(`At most ${_chunkVMROIWLLcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
5607
+ if (!this.wet.wetLayerIds().includes(layer.id) && this.wet.wetLayerIds().length >= _chunkKBYB7OWBcjs.MAX_WET_LANES) {
5608
+ throw new PaintEditorError(`At most ${_chunkKBYB7OWBcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
5468
5609
  }
5469
5610
  this.beginWetOp();
5470
5611
  const world = this.wet.ensureLane(layer.id, brush.wet.medium);
5471
5612
  const id = layer.id;
5472
5613
  const wetColor = init.color === void 0 ? this.color : parseColor(init.color);
5473
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, wetColor);
5614
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, wetColor);
5474
5615
  const wetGradient = this.strokeGradient(init, brush, wetColor);
5475
5616
  const load = _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [r / 255, g / 255, b / 255])));
5476
- const seedW = _nullishCoalesce(init.seed, () => ( _chunkPQ3H2AANcjs.mix32.call(void 0, this.seedCounter * 2654435761 >>> 0) & 2147483647));
5617
+ const seedW = _nullishCoalesce(init.seed, () => ( _chunk3K6HWEXZcjs.mix32.call(void 0, this.seedCounter * 2654435761 >>> 0) & 2147483647));
5477
5618
  const copiesW = (_nullishCoalesce(init.copies, () => ( this.strokeCopies()))).filter((m) => m.some((v, i) => v !== IDENTITY_AFFINE[i]));
5478
5619
  const driver = new WetStrokeDriver({
5479
5620
  world,
@@ -5483,23 +5624,23 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5483
5624
  load,
5484
5625
  grain: paperGrain(doc.paper),
5485
5626
  paperDepth: doc.paper.depth,
5486
- paperColor: _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, doc.paper.color),
5627
+ paperColor: _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, doc.paper.color),
5487
5628
  seed: seedW,
5488
5629
  copies: [IDENTITY_AFFINE, ...copiesW].map(affineCopy),
5489
5630
  mask: init.maskStencils ? this.stencilSelection(init.maskStencils) : init.stencils !== false ? this.stencilSelection() : null,
5490
5631
  paint: effect ? null : wetGradient,
5491
- effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _331 => _331.pixels]), () => ( null))
5632
+ effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _339 => _339.pixels]), () => ( null))
5492
5633
  });
5493
5634
  init = { ...init, seed: seedW, load };
5494
5635
  wet = { driver, surface: () => world.display(id).surface };
5495
5636
  } else if (this.wet.wetLayerIds().includes(layer.id)) {
5496
5637
  this.dryLayersFirst([layer.id]);
5497
- const dried = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, layer.id).layer;
5638
+ const dried = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layer.id).layer;
5498
5639
  layer = dried;
5499
5640
  }
5500
5641
  let color = init.color === void 0 ? this.color : parseColor(init.color);
5501
5642
  const tracing = this.guides.tracing;
5502
- if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _332 => _332.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
5643
+ if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _340 => _340.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
5503
5644
  const perspective = this.guides.perspective;
5504
5645
  const snapper = init.snapToPerspective && perspective.enabled && perspective.snap ? new PerspectiveSnapper(perspective) : null;
5505
5646
  const useStencils = init.stencils !== false;
@@ -5511,13 +5652,13 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5511
5652
  const selection = brush.engine === "sticker" ? null : init.maskStencils ? this.stencilSelection(init.maskStencils) : useStencils ? this.stencilSelection() : null;
5512
5653
  const inputFilter = snapper || stencilSnapper ? (p) => stencilSnapper ? stencilSnapper.snap(snapper ? snapper.snap(p) : p) : snapper.snap(p) : void 0;
5513
5654
  const rgba = rgbaOf(color);
5514
- const seed = _nullishCoalesce(init.seed, () => ( _chunkPQ3H2AANcjs.mix32.call(void 0, this.seedCounter++ * 2654435761 >>> 0) & 2147483647));
5655
+ const seed = _nullishCoalesce(init.seed, () => ( _chunk3K6HWEXZcjs.mix32.call(void 0, this.seedCounter++ * 2654435761 >>> 0) & 2147483647));
5515
5656
  const copies = (_nullishCoalesce(init.copies, () => ( this.strokeCopies()))).filter((m) => m.some((v, i) => v !== IDENTITY_AFFINE[i]));
5516
5657
  const session = new PaintStrokeSession(host, {
5517
5658
  layerId: layer.id,
5518
5659
  surface: layer.surface,
5519
5660
  offset: layer.offset,
5520
- lockTransparency: _chunkHB4ICNNAcjs.isLayerLocked.call(void 0, layer, "transparency"),
5661
+ lockTransparency: _chunkDPYAO5U6cjs.isLayerLocked.call(void 0, layer, "transparency"),
5521
5662
  brush,
5522
5663
  color: rgba,
5523
5664
  background: rgbaOf(doc.paper.color),
@@ -5532,10 +5673,10 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5532
5673
  mixerLoad: _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [rgba[0] / 255, rgba[1] / 255, rgba[2] / 255]))),
5533
5674
  secondary: rgbaOf(this.secondaryColor),
5534
5675
  wet,
5535
- thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _333 => _333.thick, 'optionalAccess', _334 => _334[layer.id]]), () => ( emptyThickChannels())) } : void 0,
5676
+ thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _341 => _341.thick, 'optionalAccess', _342 => _342[layer.id]]), () => ( emptyThickChannels())) } : void 0,
5536
5677
  // Light paint: a twin of the stroke paints the light channel (laying, dimming, moving light).
5537
- light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _335 => _335.light, 'optionalAccess', _336 => _336[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _337 => _337.light, 'optionalAccess', _338 => _338[layer.id]]), () => ( emptyLight())) } : null,
5538
- sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc) } : void 0,
5678
+ light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _343 => _343.light, 'optionalAccess', _344 => _344[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _345 => _345.light, 'optionalAccess', _346 => _346[layer.id]]), () => ( emptyLight())) } : null,
5679
+ sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc), art: this.stickerArt.get } : void 0,
5539
5680
  paint: effect ? null : this.strokeGradient(init, brush, color),
5540
5681
  effect
5541
5682
  });
@@ -5548,7 +5689,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5548
5689
  const stroke = {
5549
5690
  id: `s${this.strokeCounter++}`,
5550
5691
  layerId: session.layerId,
5551
- brush: _chunkQ2UYUWAZcjs.brushToJSON.call(void 0, init.brush),
5692
+ brush: _chunkH4AOUUBEcjs.brushToJSON.call(void 0, init.brush),
5552
5693
  color: init.colorHex,
5553
5694
  points: session.points.map((p) => ({ ...p })),
5554
5695
  seed: init.seed
@@ -5573,12 +5714,12 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5573
5714
  const before = this.doc;
5574
5715
  const host = {
5575
5716
  update: (layerId, surface, rects) => {
5576
- if (_optionalChain([this, 'access', _339 => _339.session, 'optionalAccess', _340 => _340.init, 'access', _341 => _341.wet])) {
5717
+ if (_optionalChain([this, 'access', _347 => _347.session, 'optionalAccess', _348 => _348.init, 'access', _349 => _349.wet])) {
5577
5718
  this.wet.syncDisplays();
5578
5719
  return;
5579
5720
  }
5580
5721
  this.live = { layerId, surface };
5581
- const ch = _optionalChain([this, 'access', _342 => _342.session, 'optionalAccess', _343 => _343.thickChannels, 'call', _344 => _344()]);
5722
+ const ch = _optionalChain([this, 'access', _350 => _350.session, 'optionalAccess', _351 => _351.thickChannels, 'call', _352 => _352()]);
5582
5723
  this.liveThick = ch ? { layerId, channels: ch } : null;
5583
5724
  this.emit(rects);
5584
5725
  },
@@ -5590,7 +5731,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5590
5731
  const wetStroke = Boolean(s.init.wet);
5591
5732
  if (wetStroke) this.wet.driver = null;
5592
5733
  const brush = s.init.brush;
5593
- if (!cancelled && _optionalChain([s, 'access', _345 => _345.result, 'optionalAccess', _346 => _346.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
5734
+ if (!cancelled && _optionalChain([s, 'access', _353 => _353.result, 'optionalAccess', _354 => _354.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
5594
5735
  if (cancelled || !surface) {
5595
5736
  if (this.wetOp) {
5596
5737
  const snap = this.wetOp.before;
@@ -5605,7 +5746,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5605
5746
  }
5606
5747
  const stroke = this.record(s);
5607
5748
  s.result.strokeId = stroke.id;
5608
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _347 => _347.result, 'optionalAccess', _348 => _348.bounds]), () => ( null)));
5749
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _355 => _355.result, 'optionalAccess', _356 => _356.bounds]), () => ( null)));
5609
5750
  if (wetStroke && this.wet.instantDry) {
5610
5751
  this.wet.dry(s.layerId);
5611
5752
  this.logWet({ kind: "dry", layerId: s.layerId, at: this.doc.strokes.length + 1 });
@@ -5616,10 +5757,10 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5616
5757
  const ch = s.thickChannels();
5617
5758
  const thick = ch ? { ..._nullishCoalesce(this.doc.thick, () => ( {})), [l.id]: ch } : this.doc.thick;
5618
5759
  const sprayed = s.stickers();
5619
- const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _349 => _349.doc, 'access', _350 => _350.stickers, 'optionalAccess', _351 => _351[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
5620
- const wetLight = wetStroke && _optionalChain([this, 'access', _352 => _352.wet, 'access', _353 => _353.world, 'optionalAccess', _354 => _354.hasLane, 'call', _355 => _355(l.id)]) ? this.wet.world.lightDisplay(l.id) : null;
5760
+ const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _357 => _357.doc, 'access', _358 => _358.stickers, 'optionalAccess', _359 => _359[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
5761
+ const wetLight = wetStroke && _optionalChain([this, 'access', _360 => _360.wet, 'access', _361 => _361.world, 'optionalAccess', _362 => _362.hasLane, 'call', _363 => _363(l.id)]) ? this.wet.world.lightDisplay(l.id) : null;
5621
5762
  const light = withLayerLight(this.doc.light, l.id, _nullishCoalesce(s.lightChannel(), () => ( wetLight)));
5622
- this.commit(`${brush.name} stroke`, this.withWetEvents(withLiveStroke({ ...this.doc, layers: _chunkHB4ICNNAcjs.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);
5763
+ 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);
5623
5764
  }
5624
5765
  };
5625
5766
  let session;
@@ -5647,18 +5788,18 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5647
5788
  if (cancelled || !surface) return;
5648
5789
  const stroke = this.record(s);
5649
5790
  s.result.strokeId = stroke.id;
5650
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _356 => _356.result, 'optionalAccess', _357 => _357.bounds]), () => ( null)));
5651
- const l = _chunkHB4ICNNAcjs.findLayer.call(void 0, out.layers, s.layerId).layer;
5791
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _364 => _364.result, 'optionalAccess', _365 => _365.bounds]), () => ( null)));
5792
+ const l = _chunkDPYAO5U6cjs.findLayer.call(void 0, out.layers, s.layerId).layer;
5652
5793
  const offset = s.init.wet ? { x: 0, y: 0 } : l.offset;
5653
5794
  const ch = s.thickChannels();
5654
5795
  const sprayed = s.stickers();
5655
- const lit = _nullishCoalesce(s.lightChannel(), () => ( (s.init.wet && _optionalChain([this, 'access', _358 => _358.wet, 'access', _359 => _359.world, 'optionalAccess', _360 => _360.hasLane, 'call', _361 => _361(l.id)]) ? this.wet.world.lightDisplay(l.id) : null)));
5796
+ const lit = _nullishCoalesce(s.lightChannel(), () => ( (s.init.wet && _optionalChain([this, 'access', _366 => _366.wet, 'access', _367 => _367.world, 'optionalAccess', _368 => _368.hasLane, 'call', _369 => _369(l.id)]) ? this.wet.world.lightDisplay(l.id) : null)));
5656
5797
  out = withLiveStroke({
5657
5798
  ...out,
5658
- layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, out.layers, l.id, () => ({ ...l, surface, offset })),
5799
+ layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, out.layers, l.id, () => ({ ...l, surface, offset })),
5659
5800
  strokes: [...out.strokes, stroke],
5660
5801
  ...ch ? { thick: { ..._nullishCoalesce(out.thick, () => ( {})), [l.id]: ch } } : {},
5661
- ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _362 => _362.stickers, 'optionalAccess', _363 => _363[l.id]]), () => ( [])), ...sprayed] } } : {},
5802
+ ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _370 => _370.stickers, 'optionalAccess', _371 => _371[l.id]]), () => ( [])), ...sprayed] } } : {},
5662
5803
  ...lit ? { light: withLayerLight(out.light, l.id, lit) } : {}
5663
5804
  }, stroke);
5664
5805
  }
@@ -5671,8 +5812,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5671
5812
  if (this.wet.instantDry && result.strokeId) {
5672
5813
  this.wet.dry(session.layerId);
5673
5814
  this.logWet({ kind: "dry", layerId: session.layerId, at: out.strokes.length });
5674
- const dried = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, session.layerId).layer.surface;
5675
- out = { ...out, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, out.layers, session.layerId, (l) => ({ ...l, surface: dried })) };
5815
+ const dried = _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, session.layerId).layer.surface;
5816
+ out = { ...out, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, out.layers, session.layerId, (l) => ({ ...l, surface: dried })) };
5676
5817
  }
5677
5818
  result.wet = this.wet.isWet(session.layerId);
5678
5819
  }
@@ -5717,7 +5858,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5717
5858
  */
5718
5859
  replayStrokes(options) {
5719
5860
  this.requireIdle("replaying");
5720
- if (!_optionalChain([options, 'access', _364 => _364.strokeIds, 'optionalAccess', _365 => _365.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
5861
+ if (!_optionalChain([options, 'access', _372 => _372.strokeIds, 'optionalAccess', _373 => _373.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
5721
5862
  const strokes = options.strokeIds.map((id) => {
5722
5863
  const s = this.doc.strokes.find((x) => x.id === id);
5723
5864
  if (!s) throw new PaintEditorError(`Unknown stroke "${id}". Call list_strokes for the ids.`);
@@ -5731,7 +5872,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5731
5872
  if (options.layerId !== void 0) this.paintTarget(options.layerId, "replay onto");
5732
5873
  if (options.color === void 0) {
5733
5874
  for (const s of strokes) {
5734
- if (_optionalChain([s, 'access', _366 => _366.paint, 'optionalAccess', _367 => _367.type]) === "effect" && !this.effectPaintImage(s.paint)) {
5875
+ if (_optionalChain([s, 'access', _374 => _374.paint, 'optionalAccess', _375 => _375.type]) === "effect" && !this.effectPaintImage(s.paint)) {
5735
5876
  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.`);
5736
5877
  }
5737
5878
  }
@@ -5754,13 +5895,13 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5754
5895
  let brush = v.brush;
5755
5896
  if (options.brushId !== void 0) {
5756
5897
  const b = this.requireBrush(options.brushId);
5757
- brush = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
5898
+ brush = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
5758
5899
  }
5759
5900
  const layerId = _nullishCoalesce(options.layerId, () => ( s.layerId));
5760
- if (!_chunkHB4ICNNAcjs.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.`);
5901
+ 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.`);
5761
5902
  let load = s.load;
5762
5903
  if (load && options.color !== void 0 && load.reservoir) {
5763
- const [r, g, b] = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, options.color);
5904
+ const [r, g, b] = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, options.color);
5764
5905
  load = { ...load, reservoir: [r / 255, g / 255, b / 255] };
5765
5906
  }
5766
5907
  const paint = v.paint && options.color === void 0 ? { paint: v.paint } : {};
@@ -5789,7 +5930,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5789
5930
  /** A layer's light paint: whether it has any, where (document pixels), its brightest value 0..255, and its spill. */
5790
5931
  lightOf(layerId) {
5791
5932
  const l = this.wetLayer(layerId, "read the light of");
5792
- const info = lightInfo(_optionalChain([this, 'access', _368 => _368.doc, 'access', _369 => _369.light, 'optionalAccess', _370 => _370[l.id]]));
5933
+ const info = lightInfo(_optionalChain([this, 'access', _376 => _376.doc, 'access', _377 => _377.light, 'optionalAccess', _378 => _378[l.id]]));
5793
5934
  const bounds = info.bounds ? { ...info.bounds, x: info.bounds.x + l.offset.x, y: info.bounds.y + l.offset.y } : null;
5794
5935
  return { layerId: l.id, hasLight: info.peak > 0, bounds, peak: info.peak, spill: { ...this.lightSpillOf(l.id) } };
5795
5936
  }
@@ -5840,7 +5981,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5840
5981
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
5841
5982
  if (!id) return null;
5842
5983
  this.requireLayer(id);
5843
- const ch = _optionalChain([this, 'access', _371 => _371.doc, 'access', _372 => _372.thick, 'optionalAccess', _373 => _373[id]]);
5984
+ const ch = _optionalChain([this, 'access', _379 => _379.doc, 'access', _380 => _380.thick, 'optionalAccess', _381 => _381[id]]);
5844
5985
  if (!ch) return null;
5845
5986
  const r = reliefInfo(ch);
5846
5987
  return { layerId: id, bounds: r.bounds, maxHeight: r.maxHeight };
@@ -5895,7 +6036,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5895
6036
  /** `renderHighRes` as PNG bytes. */
5896
6037
  async exportHighResPng(options) {
5897
6038
  const img = await this.renderHighRes(options);
5898
- return _chunkOLNIPTB3cjs.encodePng.call(void 0, img.width, img.height, img.data);
6039
+ return _chunkW5M3J7PVcjs.encodePng.call(void 0, img.width, img.height, img.data);
5899
6040
  }
5900
6041
  async renderHighRes(options) {
5901
6042
  const target = this.createReplayTarget(options.scale);
@@ -5948,7 +6089,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
5948
6089
  wetState() {
5949
6090
  const st = this.getState().wet;
5950
6091
  const backend = this.wet.backend();
5951
- return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _374 => _374.message]), () => ( _chunkVMROIWLLcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
6092
+ return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _382 => _382.message]), () => ( _chunkKBYB7OWBcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
5952
6093
  }
5953
6094
  /**
5954
6095
  * Engine B, the WebGPU accelerator for large wet areas: whether it may run, its state (`off`,
@@ -6017,11 +6158,11 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6017
6158
  wetPaper(options = {}) {
6018
6159
  this.requireIdle("wetting the paper");
6019
6160
  const l = this.wetLayer(options.layerId, "wet the paper of");
6020
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it first.`);
6161
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it first.`);
6021
6162
  const amount = _nullishCoalesce(options.amount, () => ( 1));
6022
6163
  if (!(amount > 0 && amount <= 1)) throw new PaintEditorError(`amount ${amount} is out of range; use above 0 up to 1.`);
6023
6164
  const rect = _nullishCoalesce(this.checkRect(options.rect), () => ( { x: 0, y: 0, width: this.doc.canvas.width, height: this.doc.canvas.height }));
6024
- if (!this.wet.wetLayerIds().includes(l.id) && this.wet.wetLayerIds().length >= _chunkVMROIWLLcjs.MAX_WET_LANES) throw new PaintEditorError(`At most ${_chunkVMROIWLLcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
6165
+ if (!this.wet.wetLayerIds().includes(l.id) && this.wet.wetLayerIds().length >= _chunkKBYB7OWBcjs.MAX_WET_LANES) throw new PaintEditorError(`At most ${_chunkKBYB7OWBcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
6025
6166
  const before = this.doc;
6026
6167
  this.beginWetOp();
6027
6168
  const world = this.wet.ensureLane(l.id);
@@ -6033,7 +6174,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6033
6174
  }
6034
6175
  /** Records a settings change as a wet event (not an undo step). */
6035
6176
  recordWetSetting(e) {
6036
- this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _375 => _375.wet, 'access', _376 => _376.world, 'optionalAccess', _377 => _377.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
6177
+ this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _383 => _383.wet, 'access', _384 => _384.world, 'optionalAccess', _385 => _385.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
6037
6178
  }
6038
6179
  /** Changes a layer's wet settings (viscosity, evaporation, granulation…). Editor settings saved with the document, not an undo step. */
6039
6180
  setWetParams(layerId, update) {
@@ -6099,11 +6240,11 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6099
6240
  /** The layers with the live stroke's surface in place. */
6100
6241
  currentLayers() {
6101
6242
  const override = this.frameOverride;
6102
- if (override) return Array.from(override).reduce((ls, [id, surface]) => _chunkHB4ICNNAcjs.mapLayer.call(void 0, ls, id, (l) => ({ ...l, surface })), this.doc.layers);
6243
+ if (override) return Array.from(override).reduce((ls, [id, surface]) => _chunkDPYAO5U6cjs.mapLayer.call(void 0, ls, id, (l) => ({ ...l, surface })), this.doc.layers);
6103
6244
  const live = this.live;
6104
6245
  if (!live) return this.animatedView();
6105
- if (_optionalChain([this, 'access', _378 => _378.liveLayers, 'optionalAccess', _379 => _379.key]) === live.surface) return this.liveLayers.layers;
6106
- const layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, live.layerId, (l) => ({ ...l, surface: live.surface }));
6246
+ if (_optionalChain([this, 'access', _386 => _386.liveLayers, 'optionalAccess', _387 => _387.key]) === live.surface) return this.liveLayers.layers;
6247
+ const layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, live.layerId, (l) => ({ ...l, surface: live.surface }));
6107
6248
  this.liveLayers = { key: live.surface, layers };
6108
6249
  return layers;
6109
6250
  }
@@ -6125,7 +6266,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6125
6266
  tracingNode(t) {
6126
6267
  const { width, height } = this.doc.canvas;
6127
6268
  const key = this.tracingVersion * 100003 + width * 7 + height;
6128
- if (_optionalChain([this, 'access', _380 => _380.tracingCache, 'optionalAccess', _381 => _381.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
6269
+ if (_optionalChain([this, 'access', _388 => _388.tracingCache, 'optionalAccess', _389 => _389.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
6129
6270
  const src = _nullishCoalesce(this.imagePixels.get(t.src), () => ( this.decodeImage(t.src)));
6130
6271
  const image = resampleInto(src, t.rect, width, height);
6131
6272
  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 };
@@ -6140,7 +6281,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6140
6281
  let out = layers;
6141
6282
  for (const id of ids) {
6142
6283
  const baked = this.wet.bakedSurface(id);
6143
- if (baked && _chunkHB4ICNNAcjs.findLayer.call(void 0, out, id)) out = _chunkHB4ICNNAcjs.mapLayer.call(void 0, out, id, (l) => ({ ...l, surface: baked }));
6284
+ if (baked && _chunkDPYAO5U6cjs.findLayer.call(void 0, out, id)) out = _chunkDPYAO5U6cjs.mapLayer.call(void 0, out, id, (l) => ({ ...l, surface: baked }));
6144
6285
  }
6145
6286
  return out;
6146
6287
  }
@@ -6152,13 +6293,13 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6152
6293
  let out = layers;
6153
6294
  const ids = /* @__PURE__ */ new Set([...Object.keys(_nullishCoalesce(thick, () => ( {}))), ...live ? [live.layerId] : []]);
6154
6295
  for (const id of ids) {
6155
- const ch = _optionalChain([live, 'optionalAccess', _382 => _382.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _383 => _383[id]]);
6156
- const l = ch && _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, out, id), 'optionalAccess', _384 => _384.layer]);
6296
+ const ch = _optionalChain([live, 'optionalAccess', _390 => _390.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _391 => _391[id]]);
6297
+ const l = ch && _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, out, id), 'optionalAccess', _392 => _392.layer]);
6157
6298
  if (!ch || !isPixelLayer(l)) continue;
6158
6299
  let cache = this.litCaches.get(id);
6159
6300
  if (!cache) this.litCaches.set(id, cache = new LitCache());
6160
6301
  const lit = cache.lit(l.surface, ch, this.lighting);
6161
- if (lit !== l.surface) out = _chunkHB4ICNNAcjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface: lit }));
6302
+ if (lit !== l.surface) out = _chunkDPYAO5U6cjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface: lit }));
6162
6303
  }
6163
6304
  return out;
6164
6305
  }
@@ -6173,13 +6314,13 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6173
6314
  if (!ids.size) return layers;
6174
6315
  let out = layers;
6175
6316
  for (const id of ids) {
6176
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, out, id), 'optionalAccess', _385 => _385.layer]);
6317
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, out, id), 'optionalAccess', _393 => _393.layer]);
6177
6318
  if (!isPixelLayer(l)) continue;
6178
6319
  let cache = this.lightCaches.get(id);
6179
6320
  if (!cache) this.lightCaches.set(id, cache = new LightCache());
6180
- const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _386 => _386.liveThick, 'optionalAccess', _387 => _387.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _388 => _388.doc, 'access', _389 => _389.thick, 'optionalAccess', _390 => _390[id]]));
6181
- if (glowed !== l.surface) out = _chunkHB4ICNNAcjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface: glowed }));
6182
- const committed = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _391 => _391.layer]);
6321
+ const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _394 => _394.liveThick, 'optionalAccess', _395 => _395.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _396 => _396.doc, 'access', _397 => _397.thick, 'optionalAccess', _398 => _398[id]]));
6322
+ if (glowed !== l.surface) out = _chunkDPYAO5U6cjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface: glowed }));
6323
+ const committed = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _399 => _399.layer]);
6183
6324
  const spill = light[id] && isPixelLayer(committed) ? cache.spill(committed.surface, light[id], this.lightSpillOf(id)) : null;
6184
6325
  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 } });
6185
6326
  }
@@ -6191,7 +6332,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6191
6332
  if (!l.visible) continue;
6192
6333
  if (l.type === "group") this.backlitLayers(l.children, committed, opacity * l.opacity, out);
6193
6334
  else if (isPixelLayer(l)) {
6194
- const thick = !committed && _optionalChain([this, 'access', _392 => _392.liveThick, 'optionalAccess', _393 => _393.layerId]) === l.id ? this.liveThick.channels : _optionalChain([this, 'access', _394 => _394.doc, 'access', _395 => _395.thick, 'optionalAccess', _396 => _396[l.id]]);
6335
+ const thick = !committed && _optionalChain([this, 'access', _400 => _400.liveThick, 'optionalAccess', _401 => _401.layerId]) === l.id ? this.liveThick.channels : _optionalChain([this, 'access', _402 => _402.doc, 'access', _403 => _403.thick, 'optionalAccess', _404 => _404[l.id]]);
6195
6336
  out.push({ surface: l.surface, offset: l.offset, opacity: opacity * l.opacity, ...thick ? { thick } : {} });
6196
6337
  }
6197
6338
  }
@@ -6220,7 +6361,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6220
6361
  if (backlight) layers = [...layers, backlight];
6221
6362
  if (options.layerIds) {
6222
6363
  const picked = [];
6223
- for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _397 => _397.layer]), () => ( this.requireLayer(id))));
6364
+ for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, id), 'optionalAccess', _405 => _405.layer]), () => ( this.requireLayer(id))));
6224
6365
  layers = picked.map((l) => ({ ...l, visible: true }));
6225
6366
  }
6226
6367
  const under = options.paper === false ? [] : [paperNode(this.doc.paper, this.lighting)];
@@ -6236,7 +6377,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6236
6377
  */
6237
6378
  compositeTiles(rect, onTile, options = {}) {
6238
6379
  const dirty = options.dirty === "all" ? void 0 : options.dirty;
6239
- this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _398 => _398.live, 'optionalAccess', _399 => _399.layerId]), () => ( this.doc.activeLayerId)) });
6380
+ this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _406 => _406.live, 'optionalAccess', _407 => _407.layerId]), () => ( this.doc.activeLayerId)) });
6240
6381
  }
6241
6382
  /** The canvas as canvas-sized RGBA (paper included by default). */
6242
6383
  compositePixels(options = {}) {
@@ -6264,7 +6405,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6264
6405
  /** Wet settings saved with the document (`null` when they are all defaults). */
6265
6406
  wetJSON() {
6266
6407
  const layers = {};
6267
- for (const [id, set] of this.wet.settings) if (_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) layers[id] = { params: { ...set.params }, flow: { ...set.flow } };
6408
+ for (const [id, set] of this.wet.settings) if (_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)) layers[id] = { params: { ...set.params }, flow: { ...set.flow } };
6268
6409
  const flat = this.wet.tilt.angle === 0;
6269
6410
  if (!Object.keys(layers).length && flat) return void 0;
6270
6411
  return { tilt: { ...this.wet.tilt }, layers };
@@ -6273,7 +6414,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6273
6414
  this.wet.reset();
6274
6415
  if (!raw || typeof raw !== "object") return;
6275
6416
  const r = raw;
6276
- this.wet.setTilt(_chunkVMROIWLLcjs.normalizeTilt.call(void 0, _nullishCoalesce(r.tilt, () => ( {}))));
6417
+ this.wet.setTilt(_chunkKBYB7OWBcjs.normalizeTilt.call(void 0, _nullishCoalesce(r.tilt, () => ( {}))));
6277
6418
  if (r.layers && typeof r.layers === "object") {
6278
6419
  for (const [id, v] of Object.entries(r.layers)) {
6279
6420
  if (!v || typeof v !== "object") {
@@ -6281,7 +6422,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6281
6422
  continue;
6282
6423
  }
6283
6424
  const x = v;
6284
- this.wet.settings.set(id, { params: _chunkVMROIWLLcjs.normalizeWetParams.call(void 0, _nullishCoalesce(x.params, () => ( {}))), flow: _chunkVMROIWLLcjs.normalizeFlow.call(void 0, _nullishCoalesce(x.flow, () => ( {}))) });
6425
+ this.wet.settings.set(id, { params: _chunkKBYB7OWBcjs.normalizeWetParams.call(void 0, _nullishCoalesce(x.params, () => ( {}))), flow: _chunkKBYB7OWBcjs.normalizeFlow.call(void 0, _nullishCoalesce(x.flow, () => ( {}))) });
6285
6426
  }
6286
6427
  }
6287
6428
  }
@@ -6290,32 +6431,32 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6290
6431
  const ext = { ...this.extensions };
6291
6432
  const channels = {};
6292
6433
  for (const [id, ch] of Object.entries(_nullishCoalesce(this.doc.thick, () => ( {})))) {
6293
- if (!_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) continue;
6434
+ if (!_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)) continue;
6294
6435
  const saved = thickToJSON(ch);
6295
6436
  if (saved) channels[id] = saved;
6296
6437
  }
6297
6438
  if (Object.keys(channels).length) ext.layerChannels = channels;
6298
6439
  else delete ext.layerChannels;
6299
6440
  const stickers = {};
6300
- for (const [id, list] of Object.entries(_nullishCoalesce(this.doc.stickers, () => ( {})))) if (list.length && _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) stickers[id] = list.map((x) => ({ ...x }));
6441
+ for (const [id, list] of Object.entries(_nullishCoalesce(this.doc.stickers, () => ( {})))) if (list.length && _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)) stickers[id] = list.map((x) => ({ ...x }));
6301
6442
  if (Object.keys(stickers).length) ext.stickers = stickers;
6302
6443
  else delete ext.stickers;
6303
6444
  const liveStrokes = {};
6304
- for (const [id, list] of Object.entries(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) if (_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) liveStrokes[id] = list.map((x) => JSON.parse(JSON.stringify(x)));
6445
+ for (const [id, list] of Object.entries(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) if (_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)) liveStrokes[id] = list.map((x) => JSON.parse(JSON.stringify(x)));
6305
6446
  if (Object.keys(liveStrokes).length) ext.liveStrokes = liveStrokes;
6306
6447
  else delete ext.liveStrokes;
6307
6448
  const light = {};
6308
6449
  for (const [id, t] of Object.entries(_nullishCoalesce(this.doc.light, () => ( {})))) {
6309
- if (!_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) continue;
6450
+ if (!_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)) continue;
6310
6451
  const saved = lightToJSON(_nullishCoalesce(this.wet.bakedLight(id), () => ( t)));
6311
6452
  if (saved) light[id] = saved;
6312
6453
  }
6313
6454
  if (Object.keys(light).length) ext.light = light;
6314
6455
  else delete ext.light;
6315
- const spills = Object.fromEntries(Object.entries(this.lightSpills).filter(([id]) => _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)));
6456
+ const spills = Object.fromEntries(Object.entries(this.lightSpills).filter(([id]) => _chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id)));
6316
6457
  if (Object.keys(spills).length) ext.lightSpill = spills;
6317
6458
  else delete ext.lightSpill;
6318
- const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _400 => _400.layer])));
6459
+ const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _408 => _408.layer])));
6319
6460
  if (effectLayers) ext.effectLayers = effectLayers;
6320
6461
  else delete ext.effectLayers;
6321
6462
  if (this.doc.paperEffect) ext.paperEffect = paperEffectToJSON(this.doc.paperEffect);
@@ -6331,17 +6472,27 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6331
6472
  if (ext.stickers && typeof ext.stickers === "object") {
6332
6473
  const stickers = {};
6333
6474
  for (const [id, list] of Object.entries(ext.stickers)) {
6334
- if (!_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id) || !Array.isArray(list)) continue;
6335
- const ok = list.filter((x) => x && typeof x.id === "string" && _chunkQ2UYUWAZcjs.STAMP_KINDS.includes(x.stamp) && Number.isFinite(x.x) && Number.isFinite(x.y) && x.size > 0);
6475
+ if (!_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id) || !Array.isArray(list)) continue;
6476
+ const ok = list.flatMap((x) => {
6477
+ if (!x || typeof x.id !== "string" || !Number.isFinite(x.x) || !Number.isFinite(x.y) || !(x.size > 0)) return [];
6478
+ try {
6479
+ const ref2 = _chunkZEYMKDYScjs.normalizeStickerRef.call(void 0, _nullishCoalesce(x.ref, () => ( x.stamp)));
6480
+ const stamp = _chunkZEYMKDYScjs.editorStampOf.call(void 0, ref2);
6481
+ const { stamp: _old, ...rest } = x;
6482
+ return [{ ...rest, ref: ref2, ...stamp ? { stamp } : {} }];
6483
+ } catch (e4) {
6484
+ return [];
6485
+ }
6486
+ });
6336
6487
  if (ok.length !== list.length) problems.push(`Some stickers of layer "${id}" could not be read; they were dropped.`);
6337
- stickers[id] = ok.map((x) => ({ ...x }));
6488
+ stickers[id] = ok;
6338
6489
  }
6339
6490
  if (Object.keys(stickers).length) state = { ...state, stickers };
6340
6491
  }
6341
6492
  if (ext.liveStrokes && typeof ext.liveStrokes === "object") {
6342
6493
  const liveStrokes = {};
6343
6494
  for (const [id, list] of Object.entries(ext.liveStrokes)) {
6344
- if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _401 => _401.layer])) || !Array.isArray(list)) continue;
6495
+ if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _409 => _409.layer])) || !Array.isArray(list)) continue;
6345
6496
  const ok = list.map(normalizeBrushStroke).filter((x) => x !== null).map((x) => ({ ...x, layerId: id }));
6346
6497
  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).`);
6347
6498
  liveStrokes[id] = ok;
@@ -6351,7 +6502,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6351
6502
  if (ext.effectLayers && typeof ext.effectLayers === "object") {
6352
6503
  const effectLayers = {};
6353
6504
  for (const [id, v] of Object.entries(ext.effectLayers)) {
6354
- if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _402 => _402.layer]))) continue;
6505
+ if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _410 => _410.layer]))) continue;
6355
6506
  const source = readPaintEffectSource(v);
6356
6507
  if (source) effectLayers[id] = source;
6357
6508
  else problems.push(`The effect of layer "${id}" could not be read; it loads as a plain layer.`);
@@ -6370,8 +6521,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6370
6521
  if (ext.lightSpill && typeof ext.lightSpill === "object") {
6371
6522
  for (const [id, v] of Object.entries(ext.lightSpill)) {
6372
6523
  try {
6373
- if (_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id)) this.lightSpills[id] = normalizeLightSpill(_nullishCoalesce(v, () => ( {})));
6374
- } catch (e4) {
6524
+ if (_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id)) this.lightSpills[id] = normalizeLightSpill(_nullishCoalesce(v, () => ( {})));
6525
+ } catch (e5) {
6375
6526
  problems.push(`The light spill of layer "${id}" could not be read; it takes the defaults.`);
6376
6527
  }
6377
6528
  }
@@ -6379,7 +6530,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6379
6530
  if (ext.light && typeof ext.light === "object") {
6380
6531
  const light = {};
6381
6532
  for (const [id, v] of Object.entries(ext.light)) {
6382
- if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _403 => _403.layer]))) continue;
6533
+ if (!isPixelLayer(_optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _411 => _411.layer]))) continue;
6383
6534
  try {
6384
6535
  light[id] = lightFromJSON(v);
6385
6536
  } catch (e) {
@@ -6392,7 +6543,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6392
6543
  if (!raw || typeof raw !== "object") return state;
6393
6544
  const thick = {};
6394
6545
  for (const [id, v] of Object.entries(raw)) {
6395
- if (!_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id)) continue;
6546
+ if (!_chunkDPYAO5U6cjs.findLayer.call(void 0, state.layers, id)) continue;
6396
6547
  try {
6397
6548
  thick[id] = thickFromJSON(v);
6398
6549
  } catch (e) {
@@ -6415,7 +6566,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6415
6566
  this.readGuides(loaded.guides, loaded.state, loaded.problems);
6416
6567
  if (Array.isArray(loaded.swatches)) this.swatches = loaded.swatches.map(readSwatch).filter((x) => x !== null);
6417
6568
  for (const s of loaded.state.strokes) {
6418
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _404 => _404.exec, 'call', _405 => _405(s.id), 'optionalAccess', _406 => _406[1]]), () => ( 0)));
6569
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _412 => _412.exec, 'call', _413 => _413(s.id), 'optionalAccess', _414 => _414[1]]), () => ( 0)));
6419
6570
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
6420
6571
  }
6421
6572
  this.undoStack = [];
@@ -6423,7 +6574,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6423
6574
  this.doc = this.readThick(loaded.state, loaded.extensions, loaded.problems);
6424
6575
  for (const list of Object.values(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
6425
6576
  for (const s of list) {
6426
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _407 => _407.exec, 'call', _408 => _408(s.id), 'optionalAccess', _409 => _409[1]]), () => ( 0)));
6577
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _415 => _415.exec, 'call', _416 => _416(s.id), 'optionalAccess', _417 => _417[1]]), () => ( 0)));
6427
6578
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
6428
6579
  }
6429
6580
  }
@@ -6438,6 +6589,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6438
6589
  delete this.extensions.paperEffect;
6439
6590
  this.viewCompositor.clear();
6440
6591
  this.emit();
6592
+ const refs = Object.values(_nullishCoalesce(this.doc.stickers, () => ( {}))).flatMap((list) => list.map((x) => x.ref));
6593
+ if (refs.some((r) => !_chunkZEYMKDYScjs.editorStampOf.call(void 0, r))) void this.prepareStickers(refs).catch(() => this.emit([]));
6441
6594
  return loaded.problems;
6442
6595
  }
6443
6596
  /** Opens a saved document (clears the history). Returns what could not be read. */
@@ -6461,7 +6614,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6461
6614
  /** The canvas as PNG bytes (paper included by default; `scale` below 1 shrinks it). */
6462
6615
  exportPng(options = {}) {
6463
6616
  const img = this.scaled(options);
6464
- return _chunkOLNIPTB3cjs.encodePng.call(void 0, img.width, img.height, img.data);
6617
+ return _chunkW5M3J7PVcjs.encodePng.call(void 0, img.width, img.height, img.data);
6465
6618
  }
6466
6619
  scaled(options) {
6467
6620
  const full2 = this.compositePixels(options);
@@ -6512,16 +6665,16 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6512
6665
  const merged = this.compositePixels({ paper: true }).data;
6513
6666
  const changed = /* @__PURE__ */ new Map();
6514
6667
  const toStandard = (layers2) => layers2.map((l) => {
6515
- const blend = l.blend === "pass-through" ? l.blend : _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, l.blend);
6668
+ const blend = l.blend === "pass-through" ? l.blend : _chunk2VX55NFMcjs.standardBlendMode.call(void 0, l.blend);
6516
6669
  if (blend !== l.blend) changed.set(l.blend, [..._nullishCoalesce(changed.get(l.blend), () => ( [])), l.name]);
6517
6670
  const next = blend === l.blend ? l : { ...l, blend };
6518
6671
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
6519
6672
  });
6520
6673
  const layers = toStandard(dried);
6521
- const result = _chunkXTWXBQD4cjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
6674
+ const result = _chunkLP2MCSBEcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
6522
6675
  for (const [mode, names] of changed) {
6523
- const label = _nullishCoalesce(_optionalChain([_chunkOLNIPTB3cjs.BLEND_MODES, 'access', _410 => _410.find, 'call', _411 => _411((m) => m.id === mode), 'optionalAccess', _412 => _412.label]), () => ( mode));
6524
- const std = _nullishCoalesce(_optionalChain([_chunkOLNIPTB3cjs.BLEND_MODES, 'access', _413 => _413.find, 'call', _414 => _414((m) => m.id === _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _415 => _415.label]), () => ( _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, mode)));
6676
+ const label = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _418 => _418.find, 'call', _419 => _419((m) => m.id === mode), 'optionalAccess', _420 => _420.label]), () => ( mode));
6677
+ const std = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _421 => _421.find, 'call', _422 => _422((m) => m.id === _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _423 => _423.label]), () => ( _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)));
6525
6678
  const list = names.map((n) => `"${n}"`).join(", ");
6526
6679
  const one = names.length === 1;
6527
6680
  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).`);
@@ -6537,7 +6690,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6537
6690
  /** `render_preview` as a base64 PNG. */
6538
6691
  previewPngBase64(options = {}) {
6539
6692
  const img = this.renderPreview(options);
6540
- return { data: _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, _chunkOLNIPTB3cjs.encodePng.call(void 0, img.width, img.height, img.data)), width: img.width, height: img.height };
6693
+ return { data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, _chunkW5M3J7PVcjs.encodePng.call(void 0, img.width, img.height, img.data)), width: img.width, height: img.height };
6541
6694
  }
6542
6695
  // --- Guides --------------------------------------------------------------------
6543
6696
  setGuides(next) {
@@ -6575,17 +6728,17 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6575
6728
  pixels = this.decodeImage(input.png.trim().startsWith("data:") ? input.png.trim() : `data:image/png;base64,${input.png.trim()}`, what);
6576
6729
  } else throw new PaintEditorError(`${what}: pass png (a PNG as base64 or a data URL) or pixels.`);
6577
6730
  if (pixels.width > MAX_IMAGE_SIDE || pixels.height > MAX_IMAGE_SIDE) throw new PaintEditorError(`${what} is ${pixels.width}\xD7${pixels.height}; the limit is ${MAX_IMAGE_SIDE} px per side.`);
6578
- const src = _chunkOLNIPTB3cjs.pngDataUrl.call(void 0, pixels.width, pixels.height, pixels.data);
6731
+ const src = _chunkW5M3J7PVcjs.pngDataUrl.call(void 0, pixels.width, pixels.height, pixels.data);
6579
6732
  this.imagePixels.set(src, pixels);
6580
6733
  return { src, pixels };
6581
6734
  }
6582
6735
  decodeImage(src, what = "Image") {
6583
6736
  const cached = this.imagePixels.get(src);
6584
6737
  if (cached) return cached;
6585
- const parsed = _chunkOLNIPTB3cjs.parseDataUrl.call(void 0, src);
6738
+ const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, src);
6586
6739
  if (!parsed) throw new PaintEditorError(`${what} is not a data URL or base64 PNG.`);
6587
6740
  try {
6588
- const png = _chunkOLNIPTB3cjs.decodePng.call(void 0, parsed.bytes);
6741
+ const png = _chunkW5M3J7PVcjs.decodePng.call(void 0, parsed.bytes);
6589
6742
  const px = { width: png.width, height: png.height, data: png.data };
6590
6743
  this.imagePixels.set(src, px);
6591
6744
  return px;
@@ -6643,7 +6796,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6643
6796
  const { src, pixels } = this.importImage(options, "The reference image");
6644
6797
  const ref2 = {
6645
6798
  id: `ref${this.nextReferenceId++}`,
6646
- name: _optionalChain([options, 'access', _416 => _416.name, 'optionalAccess', _417 => _417.trim, 'call', _418 => _418()]) || `Reference ${this.guides.references.length + 1}`,
6799
+ name: _optionalChain([options, 'access', _424 => _424.name, 'optionalAccess', _425 => _425.trim, 'call', _426 => _426()]) || `Reference ${this.guides.references.length + 1}`,
6647
6800
  src,
6648
6801
  width: pixels.width,
6649
6802
  height: pixels.height,
@@ -6722,7 +6875,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6722
6875
  try {
6723
6876
  const px = this.decodeImage(ref2.src, `Reference "${ref2.name}"`);
6724
6877
  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 });
6725
- const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _419 => _419.exec, 'call', _420 => _420(ref2.id), 'optionalAccess', _421 => _421[1]]), () => ( 0)));
6878
+ const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _427 => _427.exec, 'call', _428 => _428(ref2.id), 'optionalAccess', _429 => _429[1]]), () => ( 0)));
6726
6879
  if (n >= this.nextReferenceId) this.nextReferenceId = n + 1;
6727
6880
  } catch (e) {
6728
6881
  problems.push(e.message);
@@ -6733,7 +6886,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6733
6886
  guides.stencils = [];
6734
6887
  r.stencils.forEach((raw2, i) => {
6735
6888
  try {
6736
- const id = typeof _optionalChain([raw2, 'optionalAccess', _422 => _422.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
6889
+ const id = typeof _optionalChain([raw2, 'optionalAccess', _430 => _430.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
6737
6890
  guides.stencils.push(normalizeStencil(raw2, id));
6738
6891
  const n = Number(id.slice(7));
6739
6892
  if (n >= this.nextStencilId) this.nextStencilId = n + 1;
@@ -6756,45 +6909,96 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6756
6909
  /** The next free sticker number (ids `st<n>` are unique across the document). */
6757
6910
  nextStickerNumber(doc = this.doc) {
6758
6911
  let n = 0;
6759
- for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _423 => _423.exec, 'call', _424 => _424(st.id), 'optionalAccess', _425 => _425[1]]), () => ( 0))));
6912
+ for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _431 => _431.exec, 'call', _432 => _432(st.id), 'optionalAccess', _433 => _433[1]]), () => ( 0))));
6760
6913
  return n + 1;
6761
6914
  }
6762
6915
  stickerLayer(layerId) {
6763
6916
  const l = this.wetLayer(layerId, "edit the stickers of");
6764
- const stickers = _optionalChain([this, 'access', _426 => _426.doc, 'access', _427 => _427.stickers, 'optionalAccess', _428 => _428[l.id]]);
6917
+ const stickers = _optionalChain([this, 'access', _434 => _434.doc, 'access', _435 => _435.stickers, 'optionalAccess', _436 => _436[l.id]]);
6765
6918
  if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (list_brushes category sticker).`);
6766
6919
  return { layer: l, stickers };
6767
6920
  }
6921
+ // --- The sticker library ---------------------------------------------------------
6922
+ /** The sticker library: the editor's own stamps unless a host set its own. */
6923
+ get stickersProvider() {
6924
+ return this.stickers.provider;
6925
+ }
6926
+ /**
6927
+ * Sets the sticker library (`null` goes back to the editor's own stamps, `editorStickers()`);
6928
+ * to offer both, pass `combineStickerProviders([editorStickers(), yours])`. Loaded art is
6929
+ * forgotten. Not an edit: no undo step.
6930
+ */
6931
+ setStickersProvider(provider) {
6932
+ if ((_nullishCoalesce(provider, () => ( this.stickers.fallback))) === this.stickers.provider) return;
6933
+ this.stickers.set(provider);
6934
+ this.stickerArt.clear();
6935
+ this.emit([]);
6936
+ }
6937
+ /**
6938
+ * Loads the art of `refs` (provider stickers; editor stamps need none) so sprays and placements
6939
+ * can draw them. Rejects with a `PaintEditorError` naming an unknown ref and the closest known
6940
+ * ones, or a sticker whose art failed. Emits when art arrives, so views redraw.
6941
+ */
6942
+ async prepareStickers(refs) {
6943
+ const list = [...new Set(refs.map((r) => this.readStickerRef(r)))].filter((r) => !_chunkZEYMKDYScjs.editorStampOf.call(void 0, r));
6944
+ try {
6945
+ await Promise.all(list.map((r) => this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker)));
6946
+ } catch (e) {
6947
+ throw new PaintEditorError(e instanceof Error ? e.message : String(e));
6948
+ } finally {
6949
+ if (list.length) this.emit([]);
6950
+ }
6951
+ }
6952
+ /** Whether a sticker's art is ready to draw: `ready` (always for editor stamps), `loading`, `failed` (with why) or `none`. */
6953
+ stickerArtStatus(ref2) {
6954
+ return this.stickerArt.status(this.readStickerRef(ref2));
6955
+ }
6956
+ readStickerRef(ref2) {
6957
+ try {
6958
+ return _chunkZEYMKDYScjs.normalizeStickerRef.call(void 0, ref2);
6959
+ } catch (e) {
6960
+ throw new PaintEditorError(e.message);
6961
+ }
6962
+ }
6963
+ /** Refuses to redraw stickers whose art has not loaded (they would vanish), naming them and what to call. */
6964
+ requireStickerArt(stickers) {
6965
+ const missing = [...new Set(stickers.filter((s) => !_chunkH4AOUUBEcjs.stickerStamp.call(void 0, s) && !this.stickerArt.get(s.ref)).map((s) => s.ref))];
6966
+ if (missing.length) {
6967
+ for (const r of missing) void this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker).then(() => this.emit([]), () => this.emit([]));
6968
+ throw new PaintEditorError(`The art for ${missing.map((r) => `"${r}"`).join(", ")} has not loaded yet; it is loading now (prepareStickers), so try again when it has.`);
6969
+ }
6970
+ }
6768
6971
  /** A layer's stickers, bottom first. */
6769
6972
  listStickers(layerId) {
6770
6973
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
6771
6974
  if (!id) return [];
6772
6975
  this.requireLayer(id);
6773
- return (_nullishCoalesce(_optionalChain([this, 'access', _429 => _429.doc, 'access', _430 => _430.stickers, 'optionalAccess', _431 => _431[id]]), () => ( []))).map((s) => ({ ...s }));
6976
+ return (_nullishCoalesce(_optionalChain([this, 'access', _437 => _437.doc, 'access', _438 => _438.stickers, 'optionalAccess', _439 => _439[id]]), () => ( []))).map((s) => ({ ...s }));
6774
6977
  }
6775
6978
  /**
6776
6979
  * Replaces a layer's stickers and redraws its pixels from them (one undo step). With `dirty`,
6777
6980
  * only the tiles under those rects are redrawn.
6778
6981
  */
6779
6982
  commitStickers(label, layer, stickers, dirty) {
6780
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
6983
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
6984
+ this.requireStickerArt(stickers);
6781
6985
  const before = _nullishCoalesce(this.previewBase(), () => ( this.doc));
6782
6986
  this.stickerPreview = null;
6783
6987
  const surface = this.redrawStickers(layer, stickers, dirty);
6784
- const doc = { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => ({ ...layer, surface, offset: { x: 0, y: 0 } })), stickers: { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [layer.id]: stickers } };
6988
+ const doc = { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => ({ ...layer, surface, offset: { x: 0, y: 0 } })), stickers: { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [layer.id]: stickers } };
6785
6989
  this.commit(label, this.withPaintEvent(doc, { kind: "stickers", layerId: layer.id, data: { stickers: stickers.map((s) => ({ ...s })) } }), before);
6786
6990
  }
6787
6991
  redrawStickers(layer, stickers, dirty) {
6788
6992
  const partial = dirty && !layer.offset.x && !layer.offset.y;
6789
- return partial ? _chunkQ2UYUWAZcjs.stickerSurface.call(void 0, stickers, layer.surface, dirty) : _chunkQ2UYUWAZcjs.stickerSurface.call(void 0, stickers);
6993
+ return partial ? _chunkH4AOUUBEcjs.stickerSurface.call(void 0, stickers, layer.surface, dirty, this.stickerArt.get) : _chunkH4AOUUBEcjs.stickerSurface.call(void 0, stickers, void 0, void 0, this.stickerArt.get);
6790
6994
  }
6791
6995
  /** The document from before the sticker preview on screen, or `null` when none is (anything else changed the document since). */
6792
6996
  previewBase() {
6793
- return _optionalChain([this, 'access', _432 => _432.stickerPreview, 'optionalAccess', _433 => _433.shown]) === this.doc ? this.stickerPreview.base : null;
6997
+ return _optionalChain([this, 'access', _440 => _440.stickerPreview, 'optionalAccess', _441 => _441.shown]) === this.doc ? this.stickerPreview.base : null;
6794
6998
  }
6795
6999
  readStickerUpdate(update) {
6796
7000
  try {
6797
- return _chunkQ2UYUWAZcjs.normalizeStickerUpdate.call(void 0, update);
7001
+ return _chunkH4AOUUBEcjs.normalizeStickerUpdate.call(void 0, update);
6798
7002
  } catch (e) {
6799
7003
  throw new PaintEditorError(e.message);
6800
7004
  }
@@ -6805,7 +7009,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6805
7009
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
6806
7010
  if (!id) return null;
6807
7011
  this.requireLayer(id);
6808
- const hit = _chunkQ2UYUWAZcjs.stickerAt.call(void 0, _nullishCoalesce(_optionalChain([this, 'access', _434 => _434.doc, 'access', _435 => _435.stickers, 'optionalAccess', _436 => _436[id]]), () => ( [])), x, y);
7012
+ const hit = _chunkH4AOUUBEcjs.stickerAt.call(void 0, _nullishCoalesce(_optionalChain([this, 'access', _442 => _442.doc, 'access', _443 => _443.stickers, 'optionalAccess', _444 => _444[id]]), () => ( [])), x, y, this.stickerArt.get);
6809
7013
  return hit ? { ...hit } : null;
6810
7014
  }
6811
7015
  /** Picks a sticker for the panel and canvas (`null` for none). Editor state, not an undo step. */
@@ -6821,15 +7025,15 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6821
7025
  */
6822
7026
  previewSticker(layerId, id, update) {
6823
7027
  const { layer, stickers } = this.stickerLayer(layerId);
6824
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
7028
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
6825
7029
  const i = stickers.findIndex((s) => s.id === id);
6826
7030
  if (i < 0) throw new PaintEditorError(`Layer "${layer.name}" has no sticker "${id}". Call list_stickers for the ids.`);
6827
7031
  const next = { ...stickers[i], ...this.readStickerUpdate(update) };
6828
7032
  const list = stickers.map((s, j) => j === i ? next : s);
6829
- const dirty = [_chunkQ2UYUWAZcjs.stickerRect.call(void 0, stickers[i]), _chunkQ2UYUWAZcjs.stickerRect.call(void 0, next)];
7033
+ const dirty = [_chunkH4AOUUBEcjs.stickerRect.call(void 0, stickers[i]), _chunkH4AOUUBEcjs.stickerRect.call(void 0, next)];
6830
7034
  const base = _nullishCoalesce(this.previewBase(), () => ( this.doc));
6831
7035
  const surface = this.redrawStickers(layer, list, dirty);
6832
- this.doc = { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => ({ ...layer, surface, offset: { x: 0, y: 0 } })), stickers: { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [layer.id]: list } };
7036
+ this.doc = { ...this.doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => ({ ...layer, surface, offset: { x: 0, y: 0 } })), stickers: { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [layer.id]: list } };
6833
7037
  this.stickerPreview = { base, shown: this.doc };
6834
7038
  this.emit(dirty);
6835
7039
  return { ...next };
@@ -6849,7 +7053,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6849
7053
  if (i < 0) throw new PaintEditorError(`Layer "${layer.name}" has no sticker "${id}". Call list_stickers for the ids.`);
6850
7054
  const u = this.readStickerUpdate(update);
6851
7055
  const next = { ...stickers[i], ...u };
6852
- this.commitStickers("Edit sticker", layer, stickers.map((s, j) => j === i ? next : s), [_chunkQ2UYUWAZcjs.stickerRect.call(void 0, stickers[i]), _chunkQ2UYUWAZcjs.stickerRect.call(void 0, next)]);
7056
+ this.commitStickers("Edit sticker", layer, stickers.map((s, j) => j === i ? next : s), [_chunkH4AOUUBEcjs.stickerRect.call(void 0, stickers[i]), _chunkH4AOUUBEcjs.stickerRect.call(void 0, next)]);
6853
7057
  return { ...next };
6854
7058
  }
6855
7059
  /**
@@ -6859,15 +7063,16 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6859
7063
  */
6860
7064
  addStickers(layerId, input) {
6861
7065
  const layer = this.wetLayer(layerId, "add stickers to");
6862
- if (!input.length) throw new PaintEditorError("Pass at least one sticker (stamp, x, y).");
7066
+ if (!input.length) throw new PaintEditorError("Pass at least one sticker (ref, x, y).");
6863
7067
  if (input.length > MAX_ADD_STICKERS) throw new PaintEditorError(`At most ${MAX_ADD_STICKERS} stickers per call; split them over several calls.`);
6864
- const existing = _optionalChain([this, 'access', _437 => _437.doc, 'access', _438 => _438.stickers, 'optionalAccess', _439 => _439[layer.id]]);
6865
- if (!_optionalChain([existing, 'optionalAccess', _440 => _440.length])) {
7068
+ const existing = _optionalChain([this, 'access', _445 => _445.doc, 'access', _446 => _446.stickers, 'optionalAccess', _447 => _447[layer.id]]);
7069
+ if (!_optionalChain([existing, 'optionalAccess', _448 => _448.length])) {
6866
7070
  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.`);
6867
7071
  }
6868
7072
  let n = this.nextStickerNumber();
6869
7073
  const added = input.map((raw, i) => {
6870
- for (const k of ["stamp", "x", "y"]) if (raw[k] === void 0) throw new PaintEditorError(`Sticker ${i} needs ${k}.`);
7074
+ if (raw.ref === void 0 && raw.stamp === void 0) throw new PaintEditorError(`Sticker ${i} needs ref (a sticker ref from find_stickers, e.g. "editor:star").`);
7075
+ for (const k of ["x", "y"]) if (raw[k] === void 0) throw new PaintEditorError(`Sticker ${i} needs ${k}.`);
6871
7076
  let u;
6872
7077
  try {
6873
7078
  u = this.readStickerUpdate(raw);
@@ -6876,9 +7081,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6876
7081
  }
6877
7082
  if (raw.seed !== void 0 && !Number.isInteger(raw.seed)) throw new PaintEditorError(`Sticker ${i}: seed must be a whole number.`);
6878
7083
  const id = n++;
6879
- return { id: `st${id}`, size: 48, rotation: 0, color: this.color, opacity: 1, seed: _nullishCoalesce(raw.seed, () => ( _chunkPQ3H2AANcjs.mix32.call(void 0, id * 2654435761 >>> 0) & 2147483647)), ...u };
7084
+ 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 };
6880
7085
  });
6881
- this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _441 => _441.length]) ? added.map(_chunkQ2UYUWAZcjs.stickerRect) : void 0);
7086
+ this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _449 => _449.length]) ? added.map(_chunkH4AOUUBEcjs.stickerRect) : void 0);
6882
7087
  return added.map((s) => ({ ...s }));
6883
7088
  }
6884
7089
  /** Brings stickers to the top (`front`) or bottom of their layer (one undo step). */
@@ -6888,7 +7093,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6888
7093
  const picked = stickers.filter((s) => ids.includes(s.id));
6889
7094
  const rest = stickers.filter((s) => !ids.includes(s.id));
6890
7095
  const next = to === "front" ? [...rest, ...picked] : [...picked, ...rest];
6891
- this.commitStickers("Arrange stickers", layer, next, picked.map(_chunkQ2UYUWAZcjs.stickerRect));
7096
+ this.commitStickers("Arrange stickers", layer, next, picked.map(_chunkH4AOUUBEcjs.stickerRect));
6892
7097
  return next.map((s) => s.id);
6893
7098
  }
6894
7099
  /** Deletes stickers (`ids`, or all of them on the layer) (one undo step). Returns the ids removed. */
@@ -6898,7 +7103,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6898
7103
  for (const id of ids) if (!stickers.some((s) => s.id === id)) throw new PaintEditorError(`Layer "${layer.name}" has no sticker "${id}". Call list_stickers for the ids.`);
6899
7104
  }
6900
7105
  const removed = ids ? [...ids] : stickers.map((s) => s.id);
6901
- this.commitStickers("Remove stickers", layer, stickers.filter((s) => !removed.includes(s.id)), ids ? stickers.filter((s) => removed.includes(s.id)).map(_chunkQ2UYUWAZcjs.stickerRect) : void 0);
7106
+ this.commitStickers("Remove stickers", layer, stickers.filter((s) => !removed.includes(s.id)), ids ? stickers.filter((s) => removed.includes(s.id)).map(_chunkH4AOUUBEcjs.stickerRect) : void 0);
6902
7107
  return removed;
6903
7108
  }
6904
7109
  /** Sets a layer's stickers (replays). */
@@ -6917,20 +7122,20 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6917
7122
  }
6918
7123
  liveStrokeLayer(layerId, what) {
6919
7124
  const l = this.wetLayer(layerId, what);
6920
- const strokes = _optionalChain([this, 'access', _442 => _442.doc, 'access', _443 => _443.liveStrokes, 'optionalAccess', _444 => _444[l.id]]);
7125
+ const strokes = _optionalChain([this, 'access', _450 => _450.doc, 'access', _451 => _451.liveStrokes, 'optionalAccess', _452 => _452[l.id]]);
6921
7126
  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.`);
6922
7127
  return { layer: l, strokes };
6923
7128
  }
6924
7129
  /** Whether a layer is a live stroke layer. */
6925
7130
  isLiveStrokeLayer(layerId) {
6926
- return Boolean(_optionalChain([this, 'access', _445 => _445.doc, 'access', _446 => _446.liveStrokes, 'optionalAccess', _447 => _447[layerId]]));
7131
+ return Boolean(_optionalChain([this, 'access', _453 => _453.doc, 'access', _454 => _454.liveStrokes, 'optionalAccess', _455 => _455[layerId]]));
6927
7132
  }
6928
7133
  /** Makes an empty pixel layer a live stroke layer (one undo step). */
6929
7134
  convertToLiveStrokes(layerId) {
6930
7135
  this.requireIdle("converting a layer");
6931
7136
  const l = this.paintTarget(layerId, "convert");
6932
- if (_optionalChain([this, 'access', _448 => _448.doc, 'access', _449 => _449.liveStrokes, 'optionalAccess', _450 => _450[l.id]])) return this.describeLayer(l);
6933
- if (_optionalChain([this, 'access', _451 => _451.doc, 'access', _452 => _452.stickers, 'optionalAccess', _453 => _453[l.id], 'optionalAccess', _454 => _454.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
7137
+ if (_optionalChain([this, 'access', _456 => _456.doc, 'access', _457 => _457.liveStrokes, 'optionalAccess', _458 => _458[l.id]])) return this.describeLayer(l);
7138
+ if (_optionalChain([this, 'access', _459 => _459.doc, 'access', _460 => _460.stickers, 'optionalAccess', _461 => _461[l.id], 'optionalAccess', _462 => _462.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
6934
7139
  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"}).`);
6935
7140
  this.commit("Convert to stroke layer", { ...this.doc, liveStrokes: { ..._nullishCoalesce(this.doc.liveStrokes, () => ( {})), [l.id]: [] } });
6936
7141
  return this.describeLayer(this.getLayer(l.id));
@@ -6943,7 +7148,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6943
7148
  findLiveStroke(id) {
6944
7149
  for (const [layerId, strokes] of Object.entries(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
6945
7150
  const index = strokes.findIndex((x) => x.id === id);
6946
- const layer = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _455 => _455.layer]);
7151
+ const layer = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _463 => _463.layer]);
6947
7152
  if (index >= 0 && isPixelLayer(layer)) return { layer, strokes, index };
6948
7153
  }
6949
7154
  const baked = this.doc.strokes.some((x) => x.id === id);
@@ -6963,15 +7168,15 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6963
7168
  let brush = was.brush;
6964
7169
  if (update.brushId !== void 0) {
6965
7170
  const b = this.requireBrush(update.brushId);
6966
- brush = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: was.brush.tip.size } }, b);
7171
+ brush = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: was.brush.tip.size } }, b);
6967
7172
  }
6968
7173
  if (update.brush !== void 0) {
6969
7174
  if (!update.brush || typeof update.brush !== "object") throw new PaintEditorError("brush must be an object of brush settings (as set_brush takes).");
6970
- brush = _chunkQ2UYUWAZcjs.normalizePaintBrush.call(void 0, { ...update.brush, id: brush.id }, brush);
7175
+ brush = _chunkH4AOUUBEcjs.normalizePaintBrush.call(void 0, { ...update.brush, id: brush.id }, brush);
6971
7176
  }
6972
7177
  const why = liveStrokeRefusal(brush);
6973
7178
  if (why) throw new PaintEditorError(why);
6974
- const next = { ...was, brush: _chunkQ2UYUWAZcjs.brushToJSON.call(void 0, brush) };
7179
+ const next = { ...was, brush: _chunkH4AOUUBEcjs.brushToJSON.call(void 0, brush) };
6975
7180
  if (update.seed !== void 0) {
6976
7181
  if (!Number.isInteger(update.seed) || update.seed < 0) throw new PaintEditorError(`seed ${update.seed} must be a whole number of 0 or more.`);
6977
7182
  next.seed = update.seed;
@@ -6982,7 +7187,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6982
7187
  }
6983
7188
  if (update.paint !== void 0) {
6984
7189
  if (update.paint === null) delete next.paint;
6985
- else if (_chunkQ2UYUWAZcjs.isPaintEffectPaint.call(void 0, update.paint)) {
7190
+ else if (_chunkH4AOUUBEcjs.isPaintEffectPaint.call(void 0, update.paint)) {
6986
7191
  if (!this.effectPaintImage(update.paint)) throw new PaintEditorError(`The effect "${update.paint.effect}" is not rendered yet; render it first (prepareEffectPaints; the update_stroke tool does this).`);
6987
7192
  next.paint = JSON.parse(JSON.stringify(update.paint));
6988
7193
  } else {
@@ -6993,8 +7198,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
6993
7198
  } else next.paint = JSON.parse(JSON.stringify(p));
6994
7199
  }
6995
7200
  }
6996
- const rgb = _chunkQ2UYUWAZcjs.hexToRgb8.call(void 0, next.color).map((v) => v / 255);
6997
- const load = brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, rgb);
7201
+ const rgb = _chunkH4AOUUBEcjs.hexToRgb8.call(void 0, next.color).map((v) => v / 255);
7202
+ const load = brushLoadForStroke(brush, _chunkI7NJPHWVcjs.EMPTY_MIXER_LOAD, rgb);
6998
7203
  if (load.reservoir || load.pickup) next.load = load;
6999
7204
  else delete next.load;
7000
7205
  const list = strokes.map((x, i) => i === index ? next : x);
@@ -7038,9 +7243,9 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7038
7243
  const layers = /* @__PURE__ */ new Map();
7039
7244
  for (const f of found) layers.set(f.layer.id, f.layer);
7040
7245
  for (const [layerId, layer] of layers) {
7041
- const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _456 => _456.liveStrokes, 'optionalAccess', _457 => _457[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
7246
+ const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _464 => _464.liveStrokes, 'optionalAccess', _465 => _465[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
7042
7247
  for (const x of gone) bounds = unionRect(bounds, this.strokeArea(x));
7043
- doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _458 => _458.liveStrokes, 'optionalAccess', _459 => _459[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
7248
+ doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _466 => _466.liveStrokes, 'optionalAccess', _467 => _467[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
7044
7249
  }
7045
7250
  this.commit(ids.length === 1 ? "Remove stroke" : "Remove strokes", doc);
7046
7251
  return { removed: [...ids], bounds };
@@ -7107,10 +7312,10 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7107
7312
  this.commit(label, this.withLiveStrokes(this.doc, layer, list, dirty));
7108
7313
  }
7109
7314
  withLiveStrokes(doc, layer, list, dirty) {
7110
- if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it (update_layer locks) first.`);
7111
- const current = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _460 => _460.layer]);
7315
+ if (_chunkDPYAO5U6cjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it (update_layer locks) first.`);
7316
+ const current = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _468 => _468.layer]);
7112
7317
  const surface = this.drawLiveStrokes(_nullishCoalesce(current, () => ( layer)), list, dirty);
7113
- const next = { ...doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, doc.layers, layer.id, (l) => ({ ...l, surface, offset: { x: 0, y: 0 } })), liveStrokes: { ..._nullishCoalesce(doc.liveStrokes, () => ( {})), [layer.id]: [...list] } };
7318
+ 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] } };
7114
7319
  return this.withPaintEvent(next, { kind: "live-strokes", layerId: layer.id, data: { strokes: list.map((x) => JSON.parse(JSON.stringify(x))) } });
7115
7320
  }
7116
7321
  /** Where a stroke painted (document pixels): as learnt when it was painted or drawn, else an estimate from its points and brush. */
@@ -7139,7 +7344,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7139
7344
  };
7140
7345
  const paint = st.paint && this.liveEffectAt !== null && isLiveEffect(st) ? framePaint(st.paint, this.liveEffectAt) : st.paint;
7141
7346
  const init = { layerId: plain.id, color: st.color, brush: st.brush, seed: st.seed, copies: _nullishCoalesce(st.copies, () => ( [])), ...st.load ? { load: st.load } : {}, ...paint ? { paint } : {}, snapToPerspective: false, stencils: false, maskStencils: _nullishCoalesce(st.stencils, () => ( [])) };
7142
- const session = this.sessionFor({ ...doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, doc.layers, plain.id, () => ({ ...plain, surface })) }, init, host);
7347
+ const session = this.sessionFor({ ...doc, layers: _chunkDPYAO5U6cjs.mapLayer.call(void 0, doc.layers, plain.id, () => ({ ...plain, surface })) }, init, host);
7143
7348
  session.push(st.points);
7144
7349
  const result = session.end();
7145
7350
  const had = this.paintedBounds.get(st);
@@ -7186,8 +7391,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7186
7391
  if (!this.animatedLayers.size) return this.doc.layers;
7187
7392
  let layers = this.doc.layers;
7188
7393
  for (const [id, a] of this.animatedLayers) {
7189
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _461 => _461.layer]);
7190
- if (isPixelLayer(l) && l.surface === a.base) layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, layers, id, () => ({ ...l, surface: a.surface }));
7394
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, layers, id), 'optionalAccess', _469 => _469.layer]);
7395
+ if (isPixelLayer(l) && l.surface === a.base) layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, layers, id, () => ({ ...l, surface: a.surface }));
7191
7396
  }
7192
7397
  return layers;
7193
7398
  }
@@ -7196,11 +7401,11 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7196
7401
  const layers = [];
7197
7402
  const sources = /* @__PURE__ */ new Map();
7198
7403
  for (const [id, strokes] of Object.entries(_nullishCoalesce(doc.liveStrokes, () => ( {})))) {
7199
- const layer = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _462 => _462.layer]);
7404
+ const layer = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _470 => _470.layer]);
7200
7405
  const live = strokes.filter(isLiveEffect);
7201
7406
  if (!isPixelLayer(layer) || !live.length) continue;
7202
7407
  layers.push({ layer, strokes });
7203
- for (const st of live) sources.set(_chunkQ2UYUWAZcjs.effectPaintKey.call(void 0, st.paint), st.paint);
7408
+ for (const st of live) sources.set(_chunkH4AOUUBEcjs.effectPaintKey.call(void 0, st.paint), st.paint);
7204
7409
  }
7205
7410
  return { layers, sources: [...sources.values()] };
7206
7411
  }
@@ -7321,13 +7526,13 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7321
7526
  return this.withEffectTime(time, () => this.compositePixels(options));
7322
7527
  }
7323
7528
  // --- Stencils --------------------------------------------------------------------
7324
- __init135() {this.stencilCache = null}
7325
- __init136() {this.nextStencilId = 1}
7529
+ __init137() {this.stencilCache = null}
7530
+ __init138() {this.nextStencilId = 1}
7326
7531
  /** The mask stencils' coverage over the canvas (cached), or `null` when none masks. */
7327
7532
  stencilSelection(stencils = this.guides.stencils) {
7328
7533
  const { width, height } = this.doc.canvas;
7329
7534
  const size = `${width}x${height}`;
7330
- if (_optionalChain([this, 'access', _463 => _463.stencilCache, 'optionalAccess', _464 => _464.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
7535
+ if (_optionalChain([this, 'access', _471 => _471.stencilCache, 'optionalAccess', _472 => _472.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
7331
7536
  const mask = stencilMask(stencils, width, height);
7332
7537
  this.stencilCache = { key: stencils, size, mask };
7333
7538
  return mask;
@@ -7388,8 +7593,8 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7388
7593
  }
7389
7594
  makeSwatch(color, name) {
7390
7595
  const p = typeof color === "string" ? { type: "color", color: parseColor(color) } : this.readStrokePaint(color);
7391
- const out = { color: _chunkPQ3H2AANcjs.paintSourceColor.call(void 0, p, { paint: this.color, secondary: this.secondaryColor }) };
7392
- if (_optionalChain([name, 'optionalAccess', _465 => _465.trim, 'call', _466 => _466()])) out.name = name.trim();
7596
+ const out = { color: _chunkI7NJPHWVcjs.paintSourceColor.call(void 0, p, { paint: this.color, secondary: this.secondaryColor }) };
7597
+ if (_optionalChain([name, 'optionalAccess', _473 => _473.trim, 'call', _474 => _474()])) out.name = name.trim();
7393
7598
  if (p.type === "gradient") out.paint = p;
7394
7599
  return out;
7395
7600
  }
@@ -7441,7 +7646,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7441
7646
  * mix becomes the paint colour. Returns the mixed colour and the pile's bounds.
7442
7647
  */
7443
7648
  mixOnPad(paints, options = {}) {
7444
- const parsed = (_nullishCoalesce(paints, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _467 => _467.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _468 => _468.parts]) }));
7649
+ const parsed = (_nullishCoalesce(paints, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _475 => _475.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _476 => _476.parts]) }));
7445
7650
  let r;
7446
7651
  try {
7447
7652
  r = this.pad.mix(parsed, options);
@@ -7530,7 +7735,7 @@ var PaintEditorController = (_class12 = class _PaintEditorController {
7530
7735
  }
7531
7736
  /** A layer's tile surface (live while stroking), for thumbnails. */
7532
7737
  layerSurface(id) {
7533
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _469 => _469.layer]);
7738
+ const l = _optionalChain([_chunkDPYAO5U6cjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _477 => _477.layer]);
7534
7739
  return isPixelLayer(l) ? l.surface : null;
7535
7740
  }
7536
7741
  }, _class12.__initStatic(), _class12);
@@ -7552,7 +7757,7 @@ function insertAfter(layers, id, node) {
7552
7757
  return layers.map((l) => l.type === "group" ? { ...l, children: insertAfter(l.children, id, node) } : l);
7553
7758
  }
7554
7759
  function isLiveEffect(s) {
7555
- return _optionalChain([s, 'access', _470 => _470.paint, 'optionalAccess', _471 => _471.type]) === "effect" && s.paint.live === true;
7760
+ return _optionalChain([s, 'access', _478 => _478.paint, 'optionalAccess', _479 => _479.type]) === "effect" && s.paint.live === true;
7556
7761
  }
7557
7762
  function framePaint(p, t) {
7558
7763
  return { ...p, time: p.time + t };
@@ -7577,13 +7782,13 @@ function clipRect(r, width, height) {
7577
7782
  return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
7578
7783
  }
7579
7784
  function withLiveStroke(doc, stroke) {
7580
- const list = _optionalChain([doc, 'access', _472 => _472.liveStrokes, 'optionalAccess', _473 => _473[stroke.layerId]]);
7785
+ const list = _optionalChain([doc, 'access', _480 => _480.liveStrokes, 'optionalAccess', _481 => _481[stroke.layerId]]);
7581
7786
  return list ? { ...doc, liveStrokes: { ...doc.liveStrokes, [stroke.layerId]: [...list, stroke] } } : doc;
7582
7787
  }
7583
7788
  function shiftDocument(doc, dx, dy) {
7584
7789
  if (!dx && !dy) return doc;
7585
7790
  let layers = doc.layers;
7586
- for (const l of _chunkHB4ICNNAcjs.flattenLayers.call(void 0, doc.layers)) if (l.type === "pixel") layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, layers, l.id, () => ({ ...l, offset: movePoint(l.offset, dx, dy) }));
7791
+ for (const l of _chunkDPYAO5U6cjs.flattenLayers.call(void 0, doc.layers)) if (l.type === "pixel") layers = _chunkDPYAO5U6cjs.mapLayer.call(void 0, layers, l.id, () => ({ ...l, offset: movePoint(l.offset, dx, dy) }));
7587
7792
  const m = [1, 0, 0, 1, dx, dy];
7588
7793
  const moveStickers = (list) => list.map((s) => ({ ...s, x: Math.round((s.x + dx) * 100) / 100, y: Math.round((s.y + dy) * 100) / 100 }));
7589
7794
  const out = {
@@ -7604,9 +7809,9 @@ function shiftDocument(doc, dx, dy) {
7604
7809
  if (doc.liveStrokes) out.liveStrokes = Object.fromEntries(Object.entries(doc.liveStrokes).map(([id, list]) => [id, list.map(moveStroke)]));
7605
7810
  if (doc.paintEvents) {
7606
7811
  out.paintEvents = doc.paintEvents.map((e) => {
7607
- const list = e.kind === "stickers" ? _optionalChain([e, 'access', _474 => _474.data, 'optionalAccess', _475 => _475.stickers]) : void 0;
7812
+ const list = e.kind === "stickers" ? _optionalChain([e, 'access', _482 => _482.data, 'optionalAccess', _483 => _483.stickers]) : void 0;
7608
7813
  if (list) return { ...e, data: { ...e.data, stickers: moveStickers(list) } };
7609
- const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _476 => _476.data, 'optionalAccess', _477 => _477.strokes]) : void 0;
7814
+ const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _484 => _484.data, 'optionalAccess', _485 => _485.strokes]) : void 0;
7610
7815
  return strokes ? { ...e, data: { ...e.data, strokes: strokes.map(moveStroke) } } : e;
7611
7816
  });
7612
7817
  }
@@ -7688,8 +7893,8 @@ function strokeSchedule(points) {
7688
7893
  return total > 0 ? acc.map((d) => d / total) : points.map(() => 1);
7689
7894
  }
7690
7895
  function strokeDuration(points, max = 1800) {
7691
- const t0 = _optionalChain([points, 'access', _478 => _478[0], 'optionalAccess', _479 => _479.t]);
7692
- const t1 = _optionalChain([points, 'access', _480 => _480[points.length - 1], 'optionalAccess', _481 => _481.t]);
7896
+ const t0 = _optionalChain([points, 'access', _486 => _486[0], 'optionalAccess', _487 => _487.t]);
7897
+ const t1 = _optionalChain([points, 'access', _488 => _488[points.length - 1], 'optionalAccess', _489 => _489.t]);
7693
7898
  let ms;
7694
7899
  if (points.every((p) => Number.isFinite(p.t)) && t1 > t0) ms = t1 - t0;
7695
7900
  else {
@@ -7743,7 +7948,7 @@ var PaintDirector = class {
7743
7948
  }
7744
7949
  where(id) {
7745
7950
  const a = this.presence.get(id);
7746
- return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _482 => _482.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _483 => _483.y]), () => ( 0)) };
7951
+ return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _490 => _490.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _491 => _491.y]), () => ( 0)) };
7747
7952
  }
7748
7953
  /** Glides to `to`; an actor that just appeared starts there instead of the corner. */
7749
7954
  async glide(id, to, ms = 380) {
@@ -7790,8 +7995,8 @@ var PaintDirector = class {
7790
7995
  }
7791
7996
  case "replay": {
7792
7997
  await this.say(id, command.note, 500);
7793
- const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _484 => _484.replay, 'access', _485 => _485.strokeIds, 'optionalAccess', _486 => _486.includes, 'call', _487 => _487(s.id)]));
7794
- const first = _optionalChain([source, 'access', _488 => _488[0], 'optionalAccess', _489 => _489.points, 'access', _490 => _490[0]]);
7998
+ const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _492 => _492.replay, 'access', _493 => _493.strokeIds, 'optionalAccess', _494 => _494.includes, 'call', _495 => _495(s.id)]));
7999
+ const first = _optionalChain([source, 'access', _496 => _496[0], 'optionalAccess', _497 => _497.points, 'access', _498 => _498[0]]);
7795
8000
  if (first) await this.glide(id, first);
7796
8001
  const result = c.replayStrokes(command.replay);
7797
8002
  if (result.bounds) await this.glide(id, centre(result.bounds), 520);
@@ -7932,7 +8137,7 @@ function createPaintStickerTools(c) {
7932
8137
  {
7933
8138
  name: "list_stickers",
7934
8139
  title: "List stickers",
7935
- description: "Lists a layer\u2019s stickers bottom first: id, stamp, x, y (centre, document pixels), size (diameter px), rotation (degrees clockwise), color, opacity. Empty for a layer without stickers. Changes nothing.",
8140
+ description: "Lists a layer\u2019s stickers bottom first: id, ref (provider:id; stamp too for the editor\u2019s own), x, y (centre, document pixels), size (diameter px), rotation (degrees clockwise), color, opacity. Empty for a layer without stickers. Changes nothing.",
7936
8141
  inputSchema: { type: "object", properties: { layerId: LAYER_ID }, additionalProperties: false },
7937
8142
  annotations: { title: "List stickers", ...READ },
7938
8143
  coordinates: { out: ["stickers[]"] },
@@ -7959,7 +8164,7 @@ function createPaintStickerTools(c) {
7959
8164
  {
7960
8165
  name: "add_stickers",
7961
8166
  title: "Place stickers",
7962
- description: "Places stickers exactly where you say, on top of a sticker layer or onto an empty layer (which becomes a sticker layer). Use it for deliberate placement; spray with paint_stroke and a sticker brush for a random scatter. One undo step. Returns the new stickers with their ids, for update_sticker, arrange_stickers and remove_stickers.",
8167
+ description: "Places stickers exactly where you say, on top of a sticker layer or onto an empty layer (which becomes a sticker layer): any sticker from the sticker library by ref (find_stickers), its art loaded first; tintable ones take color. Use it for deliberate placement; spray with paint_stroke and a sticker brush for a random scatter. An unknown ref is refused with the closest ones. One undo step. Returns the new stickers with their ids, for update_sticker, arrange_stickers and remove_stickers.",
7963
8168
  inputSchema: {
7964
8169
  type: "object",
7965
8170
  properties: {
@@ -7972,7 +8177,8 @@ function createPaintStickerTools(c) {
7972
8177
  items: {
7973
8178
  type: "object",
7974
8179
  properties: {
7975
- stamp: { type: "string", enum: [..._chunkQ2UYUWAZcjs.STAMP_KINDS], description: "The stamp." },
8180
+ ref: { type: "string", minLength: 1, description: "The sticker: a ref provider:id from find_stickers (e.g. editor:star). Give ref or stamp." },
8181
+ stamp: { type: "string", enum: [..._chunkZEYMKDYScjs.STAMP_KINDS], description: "Older form: an editor stamp (same as ref editor:<stamp>)." },
7976
8182
  x: { type: "number", description: "Centre x in document pixels." },
7977
8183
  y: { type: "number", description: "Centre y in document pixels." },
7978
8184
  size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels (default 48)." },
@@ -7981,7 +8187,7 @@ function createPaintStickerTools(c) {
7981
8187
  opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0..1 (default 1)." },
7982
8188
  seed: { type: "integer", minimum: 0, description: "Texture seed (default from the new id); splat and confetti shapes vary with it." }
7983
8189
  },
7984
- required: ["stamp", "x", "y"],
8190
+ required: ["x", "y"],
7985
8191
  additionalProperties: false
7986
8192
  }
7987
8193
  }
@@ -7991,7 +8197,14 @@ function createPaintStickerTools(c) {
7991
8197
  },
7992
8198
  annotations: { title: "Place stickers", ...WRITE },
7993
8199
  coordinates: { in: ["stickers[]"], out: ["stickers[]"] },
7994
- handler: ({ layerId, stickers }) => ({ layerId: _nullishCoalesce(layerId, () => ( c.document.activeLayerId)), stickers: c.addStickers(layerId, stickers) })
8200
+ handler: async ({ layerId, stickers }) => {
8201
+ const list = stickers;
8202
+ list.forEach((x, i) => {
8203
+ if (x.ref === void 0 && x.stamp === void 0) throw new Error(`Sticker ${i} needs ref (a sticker ref from find_stickers, e.g. "editor:star").`);
8204
+ });
8205
+ await c.prepareStickers(list.map((x) => _nullishCoalesce(x.ref, () => ( `editor:${x.stamp}`))));
8206
+ return { layerId: _nullishCoalesce(layerId, () => ( c.document.activeLayerId)), stickers: c.addStickers(layerId, list) };
8207
+ }
7995
8208
  },
7996
8209
  {
7997
8210
  name: "update_sticker",
@@ -8002,7 +8215,8 @@ function createPaintStickerTools(c) {
8002
8215
  properties: {
8003
8216
  layerId: LAYER_ID,
8004
8217
  id: { type: "string", description: "Sticker id from list_stickers." },
8005
- stamp: { type: "string", enum: [..._chunkQ2UYUWAZcjs.STAMP_KINDS], description: "Another stamp." },
8218
+ ref: { type: "string", minLength: 1, description: "Another sticker: a ref provider:id from find_stickers." },
8219
+ stamp: { type: "string", enum: [..._chunkZEYMKDYScjs.STAMP_KINDS], description: "Older form: another editor stamp (same as ref editor:<stamp>)." },
8006
8220
  x: { type: "number", description: "Centre x in document pixels." },
8007
8221
  y: { type: "number", description: "Centre y in document pixels." },
8008
8222
  size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels." },
@@ -8015,7 +8229,11 @@ function createPaintStickerTools(c) {
8015
8229
  },
8016
8230
  annotations: { title: "Change a sticker", ...WRITE },
8017
8231
  coordinates: { in: [""], out: [""] },
8018
- handler: ({ layerId, id, ...update }) => c.updateSticker(layerId, id, update)
8232
+ handler: async ({ layerId, id, ...update }) => {
8233
+ const refs = c.listStickers(layerId).map((s) => s.ref);
8234
+ await c.prepareStickers(update.ref ? [...refs, update.ref] : refs);
8235
+ return c.updateSticker(layerId, id, update);
8236
+ }
8019
8237
  },
8020
8238
  {
8021
8239
  name: "arrange_stickers",
@@ -8032,7 +8250,10 @@ function createPaintStickerTools(c) {
8032
8250
  additionalProperties: false
8033
8251
  },
8034
8252
  annotations: { title: "Bring stickers forward or back", ...WRITE },
8035
- handler: ({ layerId, ids, to }) => ({ order: c.arrangeStickers(layerId, ids, to) })
8253
+ handler: async ({ layerId, ids, to }) => {
8254
+ await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
8255
+ return { order: c.arrangeStickers(layerId, ids, to) };
8256
+ }
8036
8257
  },
8037
8258
  {
8038
8259
  name: "remove_stickers",
@@ -8040,7 +8261,10 @@ function createPaintStickerTools(c) {
8040
8261
  description: "Deletes stickers by id, or every sticker on the layer when ids is missing. One undo step. Returns the ids removed.",
8041
8262
  inputSchema: { type: "object", properties: { layerId: LAYER_ID, ids: { type: "array", items: { type: "string", description: "Sticker id." }, description: "Sticker ids (default all)." } }, additionalProperties: false },
8042
8263
  annotations: { title: "Delete stickers", ...DESTRUCTIVE },
8043
- handler: ({ layerId, ids }) => ({ removed: c.removeStickers(layerId, ids) })
8264
+ handler: async ({ layerId, ids }) => {
8265
+ await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
8266
+ return { removed: c.removeStickers(layerId, ids) };
8267
+ }
8044
8268
  }
8045
8269
  ];
8046
8270
  }
@@ -8306,7 +8530,7 @@ function createPaintGuideTools(c) {
8306
8530
  type: "object",
8307
8531
  properties: {
8308
8532
  color: { ...COLOR2, description: "A colour #rrggbb." },
8309
- paint: { ..._chunkPQ3H2AANcjs.PAINT_SOURCE_JSON_SCHEMA, description: "Gradient paint (or a colour) for the swatch, instead of color." },
8533
+ paint: { ..._chunkI7NJPHWVcjs.PAINT_SOURCE_JSON_SCHEMA, description: "Gradient paint (or a colour) for the swatch, instead of color." },
8310
8534
  name: { type: "string", minLength: 1, description: "Optional name." }
8311
8535
  },
8312
8536
  additionalProperties: false
@@ -8460,7 +8684,7 @@ function createPaintGuideTools(c) {
8460
8684
  const pad = c.mixingPad;
8461
8685
  return {
8462
8686
  content: [
8463
- { type: "image", data: _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, _chunkOLNIPTB3cjs.encodePng.call(void 0, pad.width, pad.height, pad.pixels())), mimeType: "image/png" },
8687
+ { type: "image", data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, _chunkW5M3J7PVcjs.encodePng.call(void 0, pad.width, pad.height, pad.pixels())), mimeType: "image/png" },
8464
8688
  { type: "text", text: `Mixing pad ${pad.width}\xD7${pad.height}` }
8465
8689
  ]
8466
8690
  };
@@ -8602,7 +8826,7 @@ function createPaintWetTools(c) {
8602
8826
  type: "object",
8603
8827
  properties: {
8604
8828
  layerId: LAYER_ID2,
8605
- kind: { type: "string", enum: [..._chunkVMROIWLLcjs.WET_FLOW_KINDS], description: "none, linear, swirl, radial or turbulent." },
8829
+ kind: { type: "string", enum: [..._chunkKBYB7OWBcjs.WET_FLOW_KINDS], description: "none, linear, swirl, radial or turbulent." },
8606
8830
  strength: UNIT("How hard it pushes, 0..1 (1 is about a 25\xB0 tilt; default 0.5)."),
8607
8831
  angle: { type: "number", minimum: -360, maximum: 360, description: "linear: direction in degrees clockwise from canvas down (default 0)." },
8608
8832
  center: {
@@ -8801,7 +9025,7 @@ function createPaintReplayTools(c) {
8801
9025
  await c.wetIdle();
8802
9026
  const tl = await c.timeLapse({ frames: a.frames, fps: a.fps, maxSide: a.maxSide, wetStepsPerFrame: a.wetStepsPerFrame, holdMs: a.holdMs });
8803
9027
  const pick = [0, Math.floor(tl.frames.length / 3), Math.floor(2 * tl.frames.length / 3), tl.frames.length - 1].filter((v, i, arr) => arr.indexOf(v) === i);
8804
- const sheet = contactSheet(pick.map((i) => _chunkOLNIPTB3cjs.decodePng.call(void 0, tl.frames[i])), pick.length, 160);
9028
+ const sheet = contactSheet(pick.map((i) => _chunkW5M3J7PVcjs.decodePng.call(void 0, tl.frames[i])), pick.length, 160);
8805
9029
  const info = {
8806
9030
  frames: tl.frames.length,
8807
9031
  fps: tl.fps,
@@ -8810,9 +9034,9 @@ function createPaintReplayTools(c) {
8810
9034
  durationMs: tl.durationMs,
8811
9035
  ffmpeg: tl.ffmpeg.command,
8812
9036
  video: tl.video,
8813
- ...a.includeFrames ? { framesPng: tl.frames.map((f) => _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, f)) } : {}
9037
+ ...a.includeFrames ? { framesPng: tl.frames.map((f) => _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, f)) } : {}
8814
9038
  };
8815
- return { content: [{ type: "image", data: _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, _chunkOLNIPTB3cjs.encodePng.call(void 0, sheet.width, sheet.height, sheet.data)), mimeType: "image/png" }, { type: "text", text: JSON.stringify(info) }] };
9039
+ return { content: [{ type: "image", data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, _chunkW5M3J7PVcjs.encodePng.call(void 0, sheet.width, sheet.height, sheet.data)), mimeType: "image/png" }, { type: "text", text: JSON.stringify(info) }] };
8816
9040
  }
8817
9041
  },
8818
9042
  {
@@ -8832,8 +9056,8 @@ function createPaintReplayTools(c) {
8832
9056
  handler: async ({ scale, paper }) => {
8833
9057
  await c.wetIdle();
8834
9058
  const img = await c.renderHighRes({ scale, paper });
8835
- const bytes = _chunkOLNIPTB3cjs.encodePng.call(void 0, img.width, img.height, img.data);
8836
- return { mimeType: "image/png", width: img.width, height: img.height, bytes: bytes.length, data: _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, bytes) };
9059
+ const bytes = _chunkW5M3J7PVcjs.encodePng.call(void 0, img.width, img.height, img.data);
9060
+ return { mimeType: "image/png", width: img.width, height: img.height, bytes: bytes.length, data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, bytes) };
8837
9061
  }
8838
9062
  }
8839
9063
  ];
@@ -8851,7 +9075,7 @@ var TIP = {
8851
9075
  type: "object",
8852
9076
  description: "The tip (the shared brush engine). Missing fields keep their current values.",
8853
9077
  properties: {
8854
- size: { type: "number", minimum: 1, maximum: _chunkPQ3H2AANcjs.MAX_BRUSH_SIZE, description: "Diameter in pixels." },
9078
+ size: { type: "number", minimum: 1, maximum: _chunkI7NJPHWVcjs.MAX_BRUSH_SIZE, description: "Diameter in pixels." },
8855
9079
  hardness: { type: "number", minimum: 0, maximum: 1, description: "Edge hardness, 0 (soft) .. 1 (hard)." },
8856
9080
  spacing: { type: "number", minimum: 0.01, maximum: 10, description: "Dab spacing as a fraction of the diameter (0.05 is smooth, 1 is dotted)." },
8857
9081
  angle: { type: "number", minimum: -360, maximum: 360, description: "Tip angle in degrees, counter-clockwise; with rotation stroke or barrel it is added to the stroke direction or pen rotation." },
@@ -8863,7 +9087,7 @@ var TIP = {
8863
9087
  pressureOpacity: { type: "boolean", description: "Pressure scales the opacity." },
8864
9088
  blend: {
8865
9089
  type: "string",
8866
- enum: _chunkOLNIPTB3cjs.BLEND_MODES.map((m) => m.id),
9090
+ enum: _chunk2VX55NFMcjs.BLEND_MODES.map((m) => m.id),
8867
9091
  description: "How paint combines with the layer. pigment mixes it in like real paint (blue into yellow gives green); multiply darkens like marker ink; watercolor glazes like a transparent wash; tint, highlight and shadow recolour, light and shade (see list_blend_modes)."
8868
9092
  }
8869
9093
  },
@@ -8896,11 +9120,11 @@ var MIXER = {
8896
9120
  mix: { type: "number", minimum: 0, maximum: 1, description: "Mix ratio: how far each dab's paint moves from the reservoir towards the picked-up colour." },
8897
9121
  loadEachStroke: { type: "boolean", description: "Refill the reservoir with the colour before each stroke." },
8898
9122
  cleanEachStroke: { type: "boolean", description: "Empty the pickup well after each stroke." },
8899
- mixing: { type: "string", enum: [..._chunkPQ3H2AANcjs.MIXING_MODELS], description: "rgb: RGB averages. pigment: mixes like paint (Kubelka-Munk)." }
9123
+ mixing: { type: "string", enum: [..._chunkI7NJPHWVcjs.MIXING_MODELS], description: "rgb: RGB averages. pigment: mixes like paint (Kubelka-Munk)." }
8900
9124
  },
8901
9125
  additionalProperties: false
8902
9126
  };
8903
- var MIXING = { type: "string", enum: [..._chunkPQ3H2AANcjs.MIXING_MODELS], description: "pigment: mixes like paint (Kubelka-Munk, blue and yellow make green); rgb: straight RGB averages." };
9127
+ var MIXING = { type: "string", enum: [..._chunkI7NJPHWVcjs.MIXING_MODELS], description: "pigment: mixes like paint (Kubelka-Munk, blue and yellow make green); rgb: straight RGB averages." };
8904
9128
  var BEHAVIOR = {
8905
9129
  type: "object",
8906
9130
  description: "How the brush handles paint on the canvas (dab and mixer engines; on a mixer brush pickup, mix, dirty and mixing are its mixer wet, mix, !cleanEachStroke and mixing). Missing fields keep their current values.",
@@ -8913,7 +9137,7 @@ var BEHAVIOR = {
8913
9137
  type: "object",
8914
9138
  description: "Multi-coloured brush (the older form of paint, the brush's own gradient: tip is across-tip, dab is distance in dabs or random). Read back from paint when it has a multi-colour equivalent. Missing fields keep their current values.",
8915
9139
  properties: {
8916
- mode: { type: "string", enum: [..._chunkQ2UYUWAZcjs.MULTI_COLOR_MODES], description: "off; tip: the colours lie side by side across the tip (stripes along the stroke, like a brush loaded with several paints); dab: the colour changes along the stroke." },
9140
+ mode: { type: "string", enum: [..._chunkH4AOUUBEcjs.MULTI_COLOR_MODES], description: "off; tip: the colours lie side by side across the tip (stripes along the stroke, like a brush loaded with several paints); dab: the colour changes along the stroke." },
8917
9141
  colors: { type: "array", maxItems: 8, items: { ...COLOR3 }, description: "2..8 colours #rrggbb; fewer than 2 uses the paint colour and the secondary colour." },
8918
9142
  order: { type: "string", enum: ["sequence", "random"], description: "dab mode: sequence runs through the colours in order, blending between them; random picks one per run of dabs (seeded)." },
8919
9143
  length: { type: "integer", minimum: 1, maximum: 500, description: "dab mode: dabs per colour (default 12)." },
@@ -8926,7 +9150,7 @@ var BEHAVIOR = {
8926
9150
  };
8927
9151
  var BRUSH_PAINT = {
8928
9152
  description: `The brush's own gradient paint, used instead of the editor's paint (null: the editor's paint). It is what the multi-colour settings became; stops may be "paint" / "secondary" for the editor's two colours.`,
8929
- anyOf: [_chunkPQ3H2AANcjs.PAINT_GRADIENT_JSON_SCHEMA, { type: "null", description: "No gradient of its own: the editor's paint." }]
9153
+ anyOf: [_chunkI7NJPHWVcjs.PAINT_GRADIENT_JSON_SCHEMA, { type: "null", description: "No gradient of its own: the editor's paint." }]
8930
9154
  };
8931
9155
  var BLENDER = {
8932
9156
  type: "object",
@@ -8954,10 +9178,10 @@ var WET_BRUSH = {
8954
9178
  properties: {
8955
9179
  tool: {
8956
9180
  type: "string",
8957
- enum: [..._chunkQ2UYUWAZcjs.WET_TOOLS],
9181
+ enum: [..._chunkH4AOUUBEcjs.WET_TOOLS],
8958
9182
  description: "paint: water and pigment (picks up and mixes wet paint by behavior.pickup / mix); water: clear water (with rewet it lifts dried paint); dry: a hair dryer, takes water; blow: pushes the water along the stroke; blend: evens out wet pigment; smudge: drags wet paint; blot: a tissue, takes wet paint up (erase wet)."
8959
9183
  },
8960
- medium: { type: "string", enum: [..._chunkQ2UYUWAZcjs.WET_MEDIA], description: "The medium: watercolor, gouache or oil. A layer takes the medium's wet settings the first time it holds wet paint (oil: thick, barely flows, stays wet long and blends into the wet paint it meets)." },
9184
+ medium: { type: "string", enum: [..._chunkH4AOUUBEcjs.WET_MEDIA], description: "The medium: watercolor, gouache or oil. A layer takes the medium's wet settings the first time it holds wet paint (oil: thick, barely flows, stays wet long and blends into the wet paint it meets)." },
8961
9185
  load: { type: "number", minimum: 0, maximum: 1, description: "Paint loading: 1 never runs out; lower, the brush runs dry along a long stroke (each stroke reloads)." },
8962
9186
  thinner: { type: "number", minimum: 0, maximum: 1, description: "Thinner (water or solvent): more transparent, runnier paint." },
8963
9187
  water: { type: "number", minimum: 0, maximum: 1, description: "Wetness: water laid per stroke, 0.2 a damp brush .. 1 a dripping one." },
@@ -8974,7 +9198,7 @@ var IMPASTO_BRUSH = {
8974
9198
  properties: {
8975
9199
  tool: {
8976
9200
  type: "string",
8977
- enum: [..._chunkQ2UYUWAZcjs.IMPASTO_TOOLS],
9201
+ enum: [..._chunkH4AOUUBEcjs.IMPASTO_TOOLS],
8978
9202
  description: "brush: thick paint with bristle ridges along the stroke; tube: blobs squeezed from the tube; knife: a palette knife that scrapes the relief flat and smears the paint; roller: a flat stippled band; gloop: a thick, glossy, rounded bead."
8979
9203
  },
8980
9204
  thickness: { type: "number", minimum: 0, maximum: 1, description: "How far the paint stands up." },
@@ -9001,17 +9225,39 @@ var PARTICLE_BRUSH = {
9001
9225
  type: "object",
9002
9226
  description: "Particle engine settings (procedural brushes). Missing fields keep their current values.",
9003
9227
  properties: {
9004
- kind: { type: "string", enum: [..._chunkQ2UYUWAZcjs.PARTICLE_KINDS], description: "string: strands of masses on springs dragged behind the pen (hair, fur, wet string); spring: particles on springs to the pen, overshooting and wobbling; orbit: particles circling the pen (curls); flow: particles thrown off the pen into a swirling flow until they fade." },
9005
- render: { type: "string", enum: [..._chunkQ2UYUWAZcjs.PARTICLE_RENDERS], description: "dot: a mark at each step; line: each particle draws a continuous line; sequence: beads spaced along each path." },
9228
+ kind: {
9229
+ type: "string",
9230
+ enum: [..._chunkH4AOUUBEcjs.PARTICLE_KINDS],
9231
+ description: "string: strands of masses on springs dragged behind the pen (hair, fur, wet string); spring: particles on springs to the pen, overshooting and wobbling; orbit: particles circling the pen (curls); flow: particles thrown off the pen into a swirling flow until they fade; elastic: strands whose links keep a rest length, stretching when the pen is fast and snapping back; fuzzy: winding strings, each strand waving out of step with the others (always waves by at least 0.12 of the tip size)."
9232
+ },
9233
+ render: {
9234
+ type: "string",
9235
+ enum: [..._chunkH4AOUUBEcjs.PARTICLE_RENDERS],
9236
+ description: "dot: a mark at each step (round, or dotTextures); line: each particle draws a continuous line; sequence: beads spaced along each path (round, or dotTextures); ribbon: the band between neighbouring particles' paths filled (ribbonFill), with the paths drawn as its edges at the mark size (flame, silk, smoke)."
9237
+ },
9006
9238
  count: { type: "integer", minimum: 1, maximum: 64, description: "Particles (flow: how many are thrown per tip of travel)." },
9007
- size: { type: "number", minimum: 0, maximum: 1, description: "Mark size as a fraction of the tip size." },
9008
- spread: { type: "number", minimum: 0, maximum: 1, description: "How far apart the particles start, as a fraction of the tip size." },
9009
- stiffness: { type: "number", minimum: 0, maximum: 1, description: "Spring and string stiffness: stiff follows closely, soft swings wide." },
9239
+ size: { type: "number", minimum: 0, maximum: 1, description: "Mark size as a fraction of the tip size (ribbon: the width of its edges)." },
9240
+ spread: { type: "number", minimum: 0, maximum: 1, description: "How far apart the particles start, as a fraction of the tip size (ribbon: how wide it is)." },
9241
+ stiffness: { type: "number", minimum: 0, maximum: 1, description: "Spring, string and elastic stiffness: stiff follows closely (elastic: snaps back faster), soft swings wide." },
9010
9242
  damping: { type: "number", minimum: 0, maximum: 1, description: "How quickly motion dies down." },
9011
9243
  speed: { type: "number", minimum: 0, maximum: 1, description: "Orbit and flow speed." },
9012
9244
  gravity: { type: "number", minimum: -1, maximum: 1, description: "Pull downwards (negative: upwards)." },
9013
9245
  life: { type: "number", minimum: 0, maximum: 1, description: "Flow particles: how long they live." },
9014
- interval: { type: "number", minimum: 0, maximum: 1, description: "Sequence: spacing of the beads." }
9246
+ interval: { type: "number", minimum: 0, maximum: 1, description: "Sequence: spacing of the beads." },
9247
+ ribbonFill: { type: "number", minimum: 0, maximum: 1, description: "Ribbon: opacity of the fill between the paths, relative to their edges (default 0.5; 0 draws only the edges)." },
9248
+ ribbonPairs: { type: "string", enum: [..._chunkH4AOUUBEcjs.RIBBON_PAIRS], description: "Ribbon: adjacent (default) joins each particle to its neighbour around the pen; first-last makes one band between the outermost two." },
9249
+ waveAmplitude: { type: "number", minimum: 0, maximum: 1, description: "Wave: how far each particle's drawn place swings sideways to the stroke, as a fraction of the tip size (default 0: no wave). Works with every kind and render." },
9250
+ waveLength: { type: "number", minimum: 4, maximum: 2e3, description: "Wave: wavelength in px of pen travel (default 60)." },
9251
+ waveSpeed: { type: "number", minimum: 0, maximum: 1, description: "Wave: how fast the waves run, by stroke time (0 default: they stand still on the path; 1: about four a second, so slow strokes wave more). Strokes without times run at a nominal 0.5 px/ms." },
9252
+ wavePhaseJitter: { type: "number", minimum: 0, maximum: 1, description: "Wave: how far out of step the particles' waves are (default 0: all in step, a wavy band; 1: random phases, tangled strands)." },
9253
+ dotTextures: {
9254
+ type: "array",
9255
+ maxItems: _chunkH4AOUUBEcjs.MAX_DOT_TEXTURES,
9256
+ items: { type: "string", enum: [..._chunkZEYMKDYScjs.STAMP_KINDS], description: "A stamp." },
9257
+ description: `Dot and sequence renders: up to ${_chunkH4AOUUBEcjs.MAX_DOT_TEXTURES} sticker stamps (list_stickers) drawn instead of round marks; repeats are allowed (they weight the order). Empty (default): round marks.`
9258
+ },
9259
+ dotTextureOrder: { type: "string", enum: [..._chunkH4AOUUBEcjs.DOT_TEXTURE_ORDERS], description: "Textured dots: sequence (default) uses the stamps in turn; random picks one per dot (seeded, so replays are exact)." },
9260
+ dotRotation: { type: "string", enum: [..._chunkH4AOUUBEcjs.DOT_ROTATIONS], description: "Textured dots: follow turns each with its particle's motion; random (default) turns each at random; fixed uses the tip angle." }
9015
9261
  },
9016
9262
  additionalProperties: false
9017
9263
  };
@@ -9032,7 +9278,13 @@ var STICKER_BRUSH = {
9032
9278
  type: "object",
9033
9279
  description: "Sticker engine settings: stamps sprayed along the stroke as editable stickers. Missing fields keep their current values.",
9034
9280
  properties: {
9035
- stamps: { type: "array", minItems: 1, maxItems: 9, items: { type: "string", enum: [..._chunkQ2UYUWAZcjs.STAMP_KINDS], description: "A stamp." }, description: "The stamps to spray (one picked at random per sticker)." },
9281
+ stamps: {
9282
+ type: "array",
9283
+ minItems: 1,
9284
+ maxItems: _chunkH4AOUUBEcjs.MAX_STICKER_STAMPS,
9285
+ items: { type: "string", minLength: 1, description: "A sticker ref provider:id from find_stickers (e.g. editor:star); a bare editor stamp (star) means editor:star." },
9286
+ description: `The stickers to spray, one picked at random per sticker: refs from find_stickers (the editor's own: ${_chunkZEYMKDYScjs.STAMP_KINDS.map((k) => `editor:${k}`).join(", ")}). Each is checked against the sticker library and an unknown ref is refused with the closest ones. A provider's sticker is drawn from its art (tinted to the paint colour when tintable), loaded before the stroke.`
9287
+ },
9036
9288
  density: { type: "number", minimum: 0, maximum: 1, description: "How closely stickers follow each other: about density \xD7 4 stickers per tip diameter of travel (0.25 \u2248 one per diameter, 1 \u2248 four). Default 0.4." },
9037
9289
  sizeJitter: { type: "number", minimum: 0, maximum: 1, description: "Random size change." },
9038
9290
  rotationJitter: { type: "number", minimum: 0, maximum: 1, description: "Random turn as a fraction of \xB1180\xB0." },
@@ -9043,16 +9295,16 @@ var STICKER_BRUSH = {
9043
9295
  };
9044
9296
  var BRUSH_FIELDS = {
9045
9297
  name: { type: "string", minLength: 1, maxLength: 80, description: "Display name." },
9046
- category: { type: "string", enum: [..._chunkQ2UYUWAZcjs.PAINT_BRUSH_CATEGORIES], description: "Library category." },
9298
+ category: { type: "string", enum: [..._chunkH4AOUUBEcjs.PAINT_BRUSH_CATEGORIES], description: "Library category." },
9047
9299
  engine: {
9048
9300
  type: "string",
9049
- enum: [..._chunkQ2UYUWAZcjs.PAINT_BRUSH_ENGINES],
9301
+ enum: [..._chunkH4AOUUBEcjs.PAINT_BRUSH_ENGINES],
9050
9302
  description: "dab: paints dabs (with behavior.pickup or gradient paint it paints dab by dab, lifting and mixing paint); eraser: removes paint; mixer: the Mixer Brush (a reservoir plus picked-up paint); blender: mixes the colours under and near the tip; smudge: drags paint along the stroke; wet: watercolour, gouache, oil and the wet tools on a simulated wet layer (see wet); impasto: thick paint with relief (see impasto); particle: procedural particle brushes (see particle); bristle: a tuft of bristles that bend and splay (see bristle); sticker: sprays editable sticker stamps (see sticker)."
9051
9303
  },
9052
9304
  tip: TIP,
9053
9305
  grain: { type: "number", minimum: 0, maximum: 1, description: "Paper grain response: 0 ignores the grain, 1 catches only its peaks at light pressure (pencil, pastel, charcoal). Multiplied by the paper depth." },
9054
9306
  pressureSmoothing: { type: "number", minimum: 0, maximum: 0.95, description: "Pressure smoothing, separate from the tip position smoothing." },
9055
- rotation: { type: "string", enum: [..._chunkQ2UYUWAZcjs.BRUSH_ROTATIONS], description: "What turns the tip: fixed (tip.angle), stroke (follows the direction of travel) or barrel (the pen barrel rotation, twist)." },
9307
+ rotation: { type: "string", enum: [..._chunkH4AOUUBEcjs.BRUSH_ROTATIONS], description: "What turns the tip: fixed (tip.angle), stroke (follows the direction of travel) or barrel (the pen barrel rotation, twist)." },
9056
9308
  dynamics: DYNAMICS,
9057
9309
  mixer: MIXER,
9058
9310
  loadsColor: { type: "boolean", description: "Mixer engine: load the colour each stroke (false for a mixer that only moves paint)." },
@@ -9104,7 +9356,7 @@ function brushSummary(b) {
9104
9356
  size: b.tip.size,
9105
9357
  grain: b.grain,
9106
9358
  rotation: b.rotation,
9107
- wetCapable: _chunkQ2UYUWAZcjs.isWetCapable.call(void 0, b),
9359
+ wetCapable: _chunkH4AOUUBEcjs.isWetCapable.call(void 0, b),
9108
9360
  pickup: b.behavior.pickup,
9109
9361
  dirty: b.behavior.dirty,
9110
9362
  multicolor: b.behavior.multicolor.mode,
@@ -9151,7 +9403,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9151
9403
  strokes: d.strokes.length,
9152
9404
  undo: s.undoLabel,
9153
9405
  redo: s.redoLabel,
9154
- blendModes: _chunkOLNIPTB3cjs.BLEND_MODES.map((m) => m.id),
9406
+ blendModes: _chunk2VX55NFMcjs.BLEND_MODES.map((m) => m.id),
9155
9407
  wet: s.wet.wet,
9156
9408
  lighting: c.getLighting()
9157
9409
  };
@@ -9213,9 +9465,9 @@ function createPaintEditorToolProvider(controller, options = {}) {
9213
9465
  inputSchema: EMPTY3,
9214
9466
  annotations: { title: "List papers", ...READ6 },
9215
9467
  handler: () => ({
9216
- papers: _chunkQ2UYUWAZcjs.PAPER_LIBRARY.map((p) => ({ id: p.preset, name: p.name, family: p.family, pattern: p.pattern, color: p.color, depth: p.depth, absorption: p.absorption, permeability: p.permeability, roughness: p.roughness })),
9217
- families: [..._chunkQ2UYUWAZcjs.PAPER_FAMILIES],
9218
- patterns: [..._chunkPQ3H2AANcjs.GRAIN_PATTERNS]
9468
+ papers: _chunkH4AOUUBEcjs.PAPER_LIBRARY.map((p) => ({ id: p.preset, name: p.name, family: p.family, pattern: p.pattern, color: p.color, depth: p.depth, absorption: p.absorption, permeability: p.permeability, roughness: p.roughness })),
9469
+ families: [..._chunkH4AOUUBEcjs.PAPER_FAMILIES],
9470
+ patterns: [..._chunkI7NJPHWVcjs.GRAIN_PATTERNS]
9219
9471
  })
9220
9472
  });
9221
9473
  add({
@@ -9246,7 +9498,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9246
9498
  depth: { type: "number", minimum: 0, maximum: 1, description: "Grain depth 0..1 (0: brushes ignore the grain)." },
9247
9499
  scale: { type: "number", minimum: 0.25, maximum: 8, description: "Grain scale: 1 natural, 2 twice as coarse." },
9248
9500
  seed: { type: "integer", minimum: 0, description: "Grain seed: another sheet of the same paper." },
9249
- pattern: { type: "string", enum: [..._chunkPQ3H2AANcjs.GRAIN_PATTERNS], description: "Grain pattern." },
9501
+ pattern: { type: "string", enum: [..._chunkI7NJPHWVcjs.GRAIN_PATTERNS], description: "Grain pattern." },
9250
9502
  tiling: { type: "string", enum: ["repeat", "mirror"], description: "How the grain tile repeats (mirror hides seams)." },
9251
9503
  shading: { type: "number", minimum: 0, maximum: 1, description: "How much the grain shades the paper colour." },
9252
9504
  dry: { ...tuning, description: "Height map tuning for dry media." },
@@ -9304,7 +9556,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9304
9556
  opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0..1." },
9305
9557
  blend: {
9306
9558
  type: "string",
9307
- enum: [..._chunkOLNIPTB3cjs.BLEND_MODES.map((m) => m.id), "pass-through"],
9559
+ enum: [..._chunk2VX55NFMcjs.BLEND_MODES.map((m) => m.id), "pass-through"],
9308
9560
  description: "Blend mode (pass-through for groups only). Painterly modes: watercolor (the layer glazes like a transparent wash), tint (recolours keeping lightness), highlight (adds soft coloured light), shadow (shades with ambient fill); see list_blend_modes."
9309
9561
  },
9310
9562
  clipped: { type: "boolean", description: "Clip to the layer below (paint only shows where it has paint)." },
@@ -9334,12 +9586,12 @@ function createPaintEditorToolProvider(controller, options = {}) {
9334
9586
  inputSchema: EMPTY3,
9335
9587
  annotations: { title: "List blend modes", ...READ6 },
9336
9588
  handler: () => ({
9337
- modes: _chunkOLNIPTB3cjs.BLEND_MODES.map((m) => ({
9589
+ modes: _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({
9338
9590
  id: m.id,
9339
9591
  label: m.label,
9340
9592
  group: m.painterly ? "painterly" : m.id === "pigment" ? "pigment" : "standard",
9341
9593
  ...m.description ? { description: m.description } : {},
9342
- psd: _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, m.id)
9594
+ psd: _chunk2VX55NFMcjs.standardBlendMode.call(void 0, m.id)
9343
9595
  }))
9344
9596
  })
9345
9597
  });
@@ -9411,7 +9663,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9411
9663
  opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0..1 (default 1)." },
9412
9664
  grain: { type: "number", minimum: 0, maximum: 1, description: "Paper grain response 0..1 (default 0: flat)." },
9413
9665
  pressure: { type: "number", minimum: 0, maximum: 1, description: "With grain: how far into the valleys, 0..1 (default 0.5)." },
9414
- blend: { type: "string", enum: _chunkOLNIPTB3cjs.BLEND_MODES.map((m) => m.id), description: "Blend mode (default normal; pigment mixes like paint, watercolor glazes; see list_blend_modes)." }
9666
+ blend: { type: "string", enum: _chunk2VX55NFMcjs.BLEND_MODES.map((m) => m.id), description: "Blend mode (default normal; pigment mixes like paint, watercolor glazes; see list_blend_modes)." }
9415
9667
  },
9416
9668
  additionalProperties: false
9417
9669
  },
@@ -9431,12 +9683,12 @@ function createPaintEditorToolProvider(controller, options = {}) {
9431
9683
  add({
9432
9684
  name: "list_brushes",
9433
9685
  title: "List brushes",
9434
- description: "Lists the brush library: built-in dry media (pencils, pastels, charcoal, airbrush, marker, ink, erasers), paint brushes (dirty round, multi-colour flat, palette dabber), blending tools (blender, smudge, pigment smudge, Mixer Brush), light paint (category light: glow gel, neon marker, light airbrush, spark trail, glow wash, highlighter; light is the amount they lay) and saved user brushes, with id, name, category, engine, size, grain response, rotation mode, whether it can pick up paint (wetCapable), its pick-up ratio, dirty and multi-colour mode, plus the active brush id.",
9686
+ description: "Lists the brush library: built-in dry media (pencils, pastels, charcoal, airbrush, marker, ink, erasers), paint brushes (dirty round, multi-colour flat, palette dabber), blending tools (blender, smudge, pigment smudge, Mixer Brush), light paint (category light: glow gel, neon marker, light airbrush, spark trail, light ribbon, flame ribbon, neon strand, smoke ribbon, bokeh dots, twinkle sparks, glow wash, highlighter; light is the amount they lay) and saved user brushes, with id, name, category, engine, size, grain response, rotation mode, whether it can pick up paint (wetCapable), its pick-up ratio, dirty and multi-colour mode, plus the active brush id.",
9435
9687
  inputSchema: EMPTY3,
9436
9688
  annotations: { title: "List brushes", ...READ6 },
9437
9689
  handler: () => {
9438
9690
  const s = c.getState();
9439
- return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access', _491 => _491.getBrush, 'call', _492 => _492(s.brush.id), 'optionalAccess', _493 => _493.builtin])), brushes: s.brushes.map(brushSummary) };
9691
+ return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access', _499 => _499.getBrush, 'call', _500 => _500(s.brush.id), 'optionalAccess', _501 => _501.builtin])), brushes: s.brushes.map(brushSummary) };
9440
9692
  }
9441
9693
  });
9442
9694
  add({
@@ -9447,10 +9699,10 @@ function createPaintEditorToolProvider(controller, options = {}) {
9447
9699
  annotations: { title: "Get a brush", ...READ6 },
9448
9700
  handler: ({ id }) => {
9449
9701
  const st = c.getState();
9450
- if (id === void 0) return { ..._chunkQ2UYUWAZcjs.brushToJSON.call(void 0, st.brush), strokePaint: _nullishCoalesce(st.brush.paint, () => ( st.paint)) };
9702
+ if (id === void 0) return { ..._chunkH4AOUUBEcjs.brushToJSON.call(void 0, st.brush), strokePaint: _nullishCoalesce(st.brush.paint, () => ( st.paint)) };
9451
9703
  const b = c.getBrush(id);
9452
9704
  if (!b) throw new Error(`Unknown brush "${id}". Call list_brushes for the ids.`);
9453
- return { ..._chunkQ2UYUWAZcjs.brushToJSON.call(void 0, b), builtin: Boolean(b.builtin), strokePaint: _nullishCoalesce(b.paint, () => ( st.paint)) };
9705
+ return { ..._chunkH4AOUUBEcjs.brushToJSON.call(void 0, b), builtin: Boolean(b.builtin), strokePaint: _nullishCoalesce(b.paint, () => ( st.paint)) };
9454
9706
  }
9455
9707
  });
9456
9708
  add({
@@ -9459,7 +9711,11 @@ function createPaintEditorToolProvider(controller, options = {}) {
9459
9711
  description: "Chooses the active brush (id) and / or changes its settings; strokes without a brush use it. Editor state, not an undo step. Changes stay on the active brush until save_brush stores them. Returns the active brush.",
9460
9712
  inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brushes to start from." }, ...BRUSH_FIELDS }, additionalProperties: false },
9461
9713
  annotations: { title: "Set the brush", ...SET4 },
9462
- handler: (a) => _chunkQ2UYUWAZcjs.brushToJSON.call(void 0, c.setBrush(a))
9714
+ handler: async (a) => {
9715
+ const stamps = _optionalChain([a, 'access', _502 => _502.sticker, 'optionalAccess', _503 => _503.stamps]);
9716
+ if (stamps) await c.prepareStickers(stamps);
9717
+ return _chunkH4AOUUBEcjs.brushToJSON.call(void 0, c.setBrush(a));
9718
+ }
9463
9719
  });
9464
9720
  add({
9465
9721
  name: "save_brush",
@@ -9475,7 +9731,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9475
9731
  additionalProperties: false
9476
9732
  },
9477
9733
  annotations: { title: "Save a brush", ...SET4 },
9478
- handler: ({ id, name }) => _chunkQ2UYUWAZcjs.brushToJSON.call(void 0, c.saveBrush({ id, name }))
9734
+ handler: ({ id, name }) => _chunkH4AOUUBEcjs.brushToJSON.call(void 0, c.saveBrush({ id, name }))
9479
9735
  });
9480
9736
  add({
9481
9737
  name: "remove_brush",
@@ -9535,7 +9791,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9535
9791
  const t = c.brushThumbnail(_nullishCoalesce(id, () => ( c.getState().brush.id)), { width, height, color });
9536
9792
  return {
9537
9793
  content: [
9538
- { type: "image", data: _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, _chunkOLNIPTB3cjs.encodePng.call(void 0, t.width, t.height, t.data)), mimeType: "image/png" },
9794
+ { type: "image", data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, _chunkW5M3J7PVcjs.encodePng.call(void 0, t.width, t.height, t.data)), mimeType: "image/png" },
9539
9795
  { type: "text", text: `Brush ${_nullishCoalesce(id, () => ( c.getState().brush.id))} ${t.width}\xD7${t.height}` }
9540
9796
  ]
9541
9797
  };
@@ -9562,7 +9818,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9562
9818
  name: "set_paint",
9563
9819
  title: "Set the paint (colour or gradient)",
9564
9820
  description: 'Sets what strokes paint with: one colour, or gradient paint that changes colour as the stroke goes. Gradient paint: 2..16 stops sorted by offset (#rrggbb, or "paint" / "secondary" for the two editor colours), space pigment (default: mixes like paint) / oklab / srgb, and map: distance (default: the colour changes as the stroke is dragged out, 300 px then mirrored back), pressure, tilt, velocity, direction, time, across-tip or random. Every stroking brush samples it per dab (dab, mixer, watercolour and gouache, oil and impasto, particle, bristle, sticker); erasers, blenders and smudges ignore it, and a brush with its own gradient (get_brush paint) paints that instead. It also ends effect paint (set_effect_paint); set_color goes back to one colour. Editor state, not an undo step. Returns paint, color and secondaryColor.',
9565
- inputSchema: { type: "object", properties: { paint: _chunkPQ3H2AANcjs.PAINT_SOURCE_JSON_SCHEMA }, required: ["paint"], additionalProperties: false },
9821
+ inputSchema: { type: "object", properties: { paint: _chunkI7NJPHWVcjs.PAINT_SOURCE_JSON_SCHEMA }, required: ["paint"], additionalProperties: false },
9566
9822
  annotations: { title: "Set the paint (colour or gradient)", ...SET4 },
9567
9823
  handler: ({ paint }) => {
9568
9824
  const p = c.setPaint(paint);
@@ -9624,7 +9880,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9624
9880
  brushId: { type: "string", description: "Brush id from list_brushes (default the active brush)." },
9625
9881
  brush: { type: "object", description: "Brush changes for this stroke only.", properties: BRUSH_FIELDS, additionalProperties: false },
9626
9882
  color: { ...COLOR3, description: "Paint colour #rrggbb (default the paint colour)." },
9627
- paint: { ..._chunkPQ3H2AANcjs.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." },
9883
+ paint: { ..._chunkI7NJPHWVcjs.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." },
9628
9884
  seed: { type: "integer", minimum: 0, description: "Jitter seed (default a new one); the same seed and points give the same marks." },
9629
9885
  snapToPerspective: { type: "boolean", description: "Snap the points to the perspective guide, as a pen stroke would (default false)." }
9630
9886
  },
@@ -9635,6 +9891,9 @@ function createPaintEditorToolProvider(controller, options = {}) {
9635
9891
  coordinates: { in: ["points[]"], out: ["bounds"] },
9636
9892
  handler: async (a) => {
9637
9893
  await c.wetIdle();
9894
+ const base = a.brushId ? c.getBrush(a.brushId) : c.getState().brush;
9895
+ const over = a.brush;
9896
+ if ((_nullishCoalesce(_optionalChain([over, 'optionalAccess', _504 => _504.engine]), () => ( _optionalChain([base, 'optionalAccess', _505 => _505.engine])))) === "sticker") await c.prepareStickers(_nullishCoalesce(_nullishCoalesce(_optionalChain([over, 'optionalAccess', _506 => _506.sticker, 'optionalAccess', _507 => _507.stamps]), () => ( _optionalChain([base, 'optionalAccess', _508 => _508.sticker, 'access', _509 => _509.stamps]))), () => ( [])));
9638
9897
  const stroke = { points: a.points, layerId: a.layerId, brushId: a.brushId, brush: a.brush, color: a.color, paint: a.paint, seed: a.seed, snapToPerspective: a.snapToPerspective };
9639
9898
  const r = await act({ kind: "stroke", stroke }, () => c.paintStroke(stroke));
9640
9899
  return r.mixerLoad ? { ...r, mixerLoad: loadResult(r.mixerLoad) } : r;
@@ -9666,7 +9925,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9666
9925
  if (ids) {
9667
9926
  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.`);
9668
9927
  }
9669
- return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _494 => _494.document, 'access', _495 => _495.liveStrokes, 'optionalAccess', _496 => _496[s.layerId], 'optionalAccess', _497 => _497.includes, 'call', _498 => _498(s)]) === true)) };
9928
+ return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _510 => _510.document, 'access', _511 => _511.liveStrokes, 'optionalAccess', _512 => _512[s.layerId], 'optionalAccess', _513 => _513.includes, 'call', _514 => _514(s)]) === true)) };
9670
9929
  }
9671
9930
  });
9672
9931
  add({
@@ -9701,7 +9960,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9701
9960
  brushId: { type: "string", description: "Brush preset id from list_brushes; the stroke keeps its size." },
9702
9961
  brush: { type: "object", properties: BRUSH_FIELDS, additionalProperties: false, description: "Brush settings to change on top of brushId or the stroke\u2019s brush; missing fields keep their values." },
9703
9962
  color: { type: "string", pattern: "^#[0-9a-fA-F]{6}$", description: "New colour #rrggbb (replaces gradient paint)." },
9704
- paint: { anyOf: [_chunkPQ3H2AANcjs.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." },
9963
+ paint: { anyOf: [_chunkI7NJPHWVcjs.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." },
9705
9964
  seed: { type: "integer", minimum: 0, description: "Another jitter seed: particles, scatter and texture fall differently." }
9706
9965
  },
9707
9966
  required: ["id"],
@@ -9923,7 +10182,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9923
10182
  handler: async ({ format, quality, scale, paper, time }) => {
9924
10183
  const run = () => c.exportImage({ format, quality, scale, paper });
9925
10184
  const bytes = time === void 0 ? await run() : await c.withEffectTime(time, run);
9926
- return { mimeType: _nullishCoalesce(format, () => ( "image/png")), bytes: bytes.length, data: _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, bytes) };
10185
+ return { mimeType: _nullishCoalesce(format, () => ( "image/png")), bytes: bytes.length, data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, bytes) };
9927
10186
  }
9928
10187
  });
9929
10188
  add({
@@ -9934,7 +10193,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9934
10193
  annotations: { title: "Export as PSD", ...READ6 },
9935
10194
  handler: async ({ time }) => {
9936
10195
  const r = time === void 0 ? c.exportPsd() : await c.withEffectTime(time, () => c.exportPsd());
9937
- return { data: _chunkOLNIPTB3cjs.bytesToBase64.call(void 0, r.bytes), bytes: r.bytes.length, psb: r.psb, warnings: r.warnings };
10196
+ return { data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, r.bytes), bytes: r.bytes.length, psb: r.psb, warnings: r.warnings };
9938
10197
  }
9939
10198
  });
9940
10199
  tools.push(...createPaintGuideTools(c));
@@ -9942,7 +10201,21 @@ function createPaintEditorToolProvider(controller, options = {}) {
9942
10201
  tools.push(...createPaintThickTools(c));
9943
10202
  tools.push(...createPaintReplayTools(c));
9944
10203
  tools.push(...createPaintStickerTools(c));
9945
- tools.push(..._chunkVMROIWLLcjs.createPigmentTools.call(void 0, ));
10204
+ tools.push(..._chunkKBYB7OWBcjs.createPigmentTools.call(void 0, ));
10205
+ tools.push(..._chunkZEYMKDYScjs.createStickerTools.call(void 0, { provider: () => c.stickersProvider }));
10206
+ tools.push(
10207
+ ..._chunkLP2MCSBEcjs.createLayerEffectTools.call(void 0,
10208
+ {
10209
+ requireLayer: (id) => void c.getLayerEffects(id),
10210
+ getLayerEffects: (id) => c.getLayerEffects(id),
10211
+ addLayerEffect: (id, kind, settings, index) => c.addLayerEffect(id, kind, settings, index),
10212
+ updateLayerEffect: (id, effectId, changes) => c.updateLayerEffect(id, effectId, changes),
10213
+ removeLayerEffect: (id, effectId) => c.removeLayerEffect(id, effectId),
10214
+ setLayerEffectsEnabled: (id, enabled, scale) => c.setLayerEffectsEnabled(id, enabled, scale)
10215
+ },
10216
+ { layers: "a pixel, stroke, sticker or group layer", error: (m) => new PaintEditorError(m) }
10217
+ )
10218
+ );
9946
10219
  const exclude = new Set(_nullishCoalesce(options.exclude, () => ( [])));
9947
10220
  const description = "Natural-media painting: paper and grain, dry and wet brushes, the brush library, strokes as data, pigment mixing, stencils, guides, layers and export.";
9948
10221
  return withPaintPlayback({
@@ -9956,16 +10229,16 @@ function createPaintEditorToolProvider(controller, options = {}) {
9956
10229
  }
9957
10230
  function hostTool({ coordinates, ...tool }, { origin, onChange }) {
9958
10231
  if (!origin && !onChange) return tool;
9959
- const write = !_optionalChain([tool, 'access', _499 => _499.annotations, 'optionalAccess', _500 => _500.readOnlyHint]);
10232
+ const write = !_optionalChain([tool, 'access', _515 => _515.annotations, 'optionalAccess', _516 => _516.readOnlyHint]);
9960
10233
  const done = (result) => {
9961
- if (write) _optionalChain([onChange, 'optionalCall', _501 => _501({ tool: tool.name })]);
9962
- return origin && _optionalChain([coordinates, 'optionalAccess', _502 => _502.out]) ? fromDocument(result, coordinates.out, origin) : result;
10234
+ if (write) _optionalChain([onChange, 'optionalCall', _517 => _517({ tool: tool.name })]);
10235
+ return origin && _optionalChain([coordinates, 'optionalAccess', _518 => _518.out]) ? fromDocument(result, coordinates.out, origin) : result;
9963
10236
  };
9964
10237
  return {
9965
10238
  ...tool,
9966
10239
  ...origin ? { description: hostedText(_nullishCoalesce(tool.description, () => ( ""))), inputSchema: hostedSchema(tool.inputSchema) } : {},
9967
10240
  handler: (args, context) => {
9968
- const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _503 => _503.in]) ? toDocument(args, coordinates.in, origin) : args, context);
10241
+ const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _519 => _519.in]) ? toDocument(args, coordinates.in, origin) : args, context);
9969
10242
  return r instanceof Promise ? r.then(done) : done(r);
9970
10243
  }
9971
10244
  };
@@ -9982,7 +10255,7 @@ function strokeSummary(s, withPoints, live) {
9982
10255
  color: s.color,
9983
10256
  points: withPoints ? s.points : s.points.length,
9984
10257
  seed: s.seed,
9985
- copies: _nullishCoalesce(_optionalChain([s, 'access', _504 => _504.copies, 'optionalAccess', _505 => _505.length]), () => ( 0)),
10258
+ copies: _nullishCoalesce(_optionalChain([s, 'access', _520 => _520.copies, 'optionalAccess', _521 => _521.length]), () => ( 0)),
9986
10259
  live,
9987
10260
  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) }
9988
10261
  };
@@ -9998,20 +10271,20 @@ var PAINT_TOOLS = [
9998
10271
  { id: "rotate", label: "Rotate view", key: "r" }
9999
10272
  ];
10000
10273
  var PaintGesture = (_class13 = class {
10001
- constructor(controller, box) {;_class13.prototype.__init137.call(this);_class13.prototype.__init138.call(this);_class13.prototype.__init139.call(this);_class13.prototype.__init140.call(this);_class13.prototype.__init141.call(this);_class13.prototype.__init142.call(this);
10274
+ constructor(controller, box) {;_class13.prototype.__init139.call(this);_class13.prototype.__init140.call(this);_class13.prototype.__init141.call(this);_class13.prototype.__init142.call(this);_class13.prototype.__init143.call(this);_class13.prototype.__init144.call(this);
10002
10275
  this.controller = controller;
10003
10276
  this.box = box;
10004
10277
  }
10005
10278
 
10006
10279
 
10007
- __init137() {this.tool = "brush"}
10280
+ __init139() {this.tool = "brush"}
10008
10281
  /** The last refusal (a hidden or locked layer), for the editor to show. */
10009
- __init138() {this.error = null}
10282
+ __init140() {this.error = null}
10010
10283
  /** The predicted tail of the current stroke in document pixels (draw it as a thin preview). */
10011
- __init139() {this.predicted = []}
10012
- __init140() {this.mode = null}
10013
- __init141() {this.penAt = null}
10014
- __init142() {this.penDown = false}
10284
+ __init141() {this.predicted = []}
10285
+ __init142() {this.mode = null}
10286
+ __init143() {this.penAt = null}
10287
+ __init144() {this.penDown = false}
10015
10288
  doc(e) {
10016
10289
  const b = this.box();
10017
10290
  const s = this.controller.getState();
@@ -10067,13 +10340,13 @@ var PaintGesture = (_class13 = class {
10067
10340
  const p = this.doc(e);
10068
10341
  const s = this.controller.getState();
10069
10342
  const layerId = s.document.activeLayerId;
10070
- if (!layerId || !_optionalChain([s, 'access', _506 => _506.document, 'access', _507 => _507.liveStrokes, 'optionalAccess', _508 => _508[layerId]])) {
10343
+ if (!layerId || !_optionalChain([s, 'access', _522 => _522.document, 'access', _523 => _523.liveStrokes, 'optionalAccess', _524 => _524[layerId]])) {
10071
10344
  this.error = "Pick a stroke layer in the Layers panel (or add one) to select its strokes.";
10072
10345
  return false;
10073
10346
  }
10074
10347
  try {
10075
10348
  const hit = this.controller.liveStrokeAt(layerId, p.x, p.y);
10076
- this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _509 => _509.id]), () => ( null)));
10349
+ this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _525 => _525.id]), () => ( null)));
10077
10350
  if (!hit) return false;
10078
10351
  this.mode = { kind: "move-stroke", pointerId: e.pointerId, id: hit.id, from: p, to: p };
10079
10352
  return true;
@@ -10085,7 +10358,7 @@ var PaintGesture = (_class13 = class {
10085
10358
  /** While a stroke is dragged: how far it has moved (document pixels), to draw its outline there. */
10086
10359
  get strokeDrag() {
10087
10360
  const m = this.mode;
10088
- return _optionalChain([m, 'optionalAccess', _510 => _510.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
10361
+ return _optionalChain([m, 'optionalAccess', _526 => _526.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
10089
10362
  }
10090
10363
  /**
10091
10364
  * The Stickers tool: pressing a sticker picks it and dragging moves it (one undo step at the
@@ -10103,7 +10376,7 @@ var PaintGesture = (_class13 = class {
10103
10376
  }
10104
10377
  const brush = this.controller.getState().brush;
10105
10378
  const size = Math.min(2048, Math.max(2, Math.round(brush.tip.size)));
10106
- const [added] = this.controller.addStickers(void 0, [{ stamp: _nullishCoalesce(brush.sticker.stamps[0], () => ( "star")), x: round2(p.x), y: round2(p.y), size }]);
10379
+ const [added] = this.controller.addStickers(void 0, [{ ref: _nullishCoalesce(brush.sticker.stamps[0], () => ( "editor:star")), x: round2(p.x), y: round2(p.y), size }]);
10107
10380
  this.controller.selectSticker(added.id);
10108
10381
  } catch (err) {
10109
10382
  this.error = err instanceof Error ? err.message : String(err);
@@ -10159,7 +10432,7 @@ var PaintGesture = (_class13 = class {
10159
10432
  if (!m || m.pointerId !== e.pointerId) return;
10160
10433
  this.mode = null;
10161
10434
  this.predicted = [];
10162
- if (m.kind === "stroke") _optionalChain([this, 'access', _511 => _511.controller, 'access', _512 => _512.activeStroke, 'optionalAccess', _513 => _513.end, 'call', _514 => _514()]);
10435
+ if (m.kind === "stroke") _optionalChain([this, 'access', _527 => _527.controller, 'access', _528 => _528.activeStroke, 'optionalAccess', _529 => _529.end, 'call', _530 => _530()]);
10163
10436
  if (m.kind === "move-stroke") {
10164
10437
  const dx = Math.round((this.doc(e).x - m.from.x) * 100) / 100;
10165
10438
  const dy = Math.round((this.doc(e).y - m.from.y) * 100) / 100;
@@ -10183,8 +10456,8 @@ var PaintGesture = (_class13 = class {
10183
10456
  cancel() {
10184
10457
  this.penDown = false;
10185
10458
  this.predicted = [];
10186
- if (_optionalChain([this, 'access', _515 => _515.mode, 'optionalAccess', _516 => _516.kind]) === "stroke") _optionalChain([this, 'access', _517 => _517.controller, 'access', _518 => _518.activeStroke, 'optionalAccess', _519 => _519.cancel, 'call', _520 => _520()]);
10187
- if (_optionalChain([this, 'access', _521 => _521.mode, 'optionalAccess', _522 => _522.kind]) === "sticker") this.controller.cancelStickerPreview();
10459
+ if (_optionalChain([this, 'access', _531 => _531.mode, 'optionalAccess', _532 => _532.kind]) === "stroke") _optionalChain([this, 'access', _533 => _533.controller, 'access', _534 => _534.activeStroke, 'optionalAccess', _535 => _535.cancel, 'call', _536 => _536()]);
10460
+ if (_optionalChain([this, 'access', _537 => _537.mode, 'optionalAccess', _538 => _538.kind]) === "sticker") this.controller.cancelStickerPreview();
10188
10461
  this.mode = null;
10189
10462
  }
10190
10463
  get active() {
@@ -10246,13 +10519,13 @@ function handlePaintShortcut(controller, gesture, e) {
10246
10519
  return false;
10247
10520
  }
10248
10521
  var PaintCanvasPresenter = (_class14 = class {
10249
- constructor(controller) {;_class14.prototype.__init143.call(this);_class14.prototype.__init144.call(this);_class14.prototype.__init145.call(this);
10522
+ constructor(controller) {;_class14.prototype.__init145.call(this);_class14.prototype.__init146.call(this);_class14.prototype.__init147.call(this);
10250
10523
  this.controller = controller;
10251
10524
  }
10252
10525
 
10253
- __init143() {this.uploaded = /* @__PURE__ */ new Map()}
10254
- __init144() {this.scratch = null}
10255
- __init145() {this.size = ""}
10526
+ __init145() {this.uploaded = /* @__PURE__ */ new Map()}
10527
+ __init146() {this.scratch = null}
10528
+ __init147() {this.size = ""}
10256
10529
  /** Draws what changed into `ctx` (a canvas the size of the document); returns the tiles drawn. */
10257
10530
  render(ctx) {
10258
10531
  const { width, height } = this.controller.document.canvas;
@@ -10284,7 +10557,7 @@ function guideOverlay(controller, drag) {
10284
10557
  const size = s.document.canvas;
10285
10558
  const out = [];
10286
10559
  const layerId = s.document.activeLayerId;
10287
- const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _523 => _523.document, 'access', _524 => _524.liveStrokes, 'optionalAccess', _525 => _525[layerId], 'optionalAccess', _526 => _526.some, 'call', _527 => _527((x) => x.id === s.selectedStroke)]) : false;
10560
+ const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _539 => _539.document, 'access', _540 => _540.liveStrokes, 'optionalAccess', _541 => _541[layerId], 'optionalAccess', _542 => _542.some, 'call', _543 => _543((x) => x.id === s.selectedStroke)]) : false;
10288
10561
  const area = strokePicked ? controller.liveStrokeArea(s.selectedStroke) : null;
10289
10562
  if (area) {
10290
10563
  const dx = drag && drag.id === s.selectedStroke ? drag.dx : 0;
@@ -10297,7 +10570,7 @@ function guideOverlay(controller, drag) {
10297
10570
  ];
10298
10571
  for (let i = 0; i < 4; i++) out.push({ from: box[i], to: box[(i + 1) % 4], kind: "stroke" });
10299
10572
  }
10300
- const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _528 => _528.document, 'access', _529 => _529.stickers, 'optionalAccess', _530 => _530[layerId], 'optionalAccess', _531 => _531.find, 'call', _532 => _532((x) => x.id === s.selectedSticker)]) : void 0;
10573
+ const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _544 => _544.document, 'access', _545 => _545.stickers, 'optionalAccess', _546 => _546[layerId], 'optionalAccess', _547 => _547.find, 'call', _548 => _548((x) => x.id === s.selectedSticker)]) : void 0;
10301
10574
  if (picked) {
10302
10575
  const r = picked.size / 2 + 2;
10303
10576
  const a = picked.rotation * Math.PI / 180;
@@ -10342,7 +10615,7 @@ var PAPER_SLIDERS = [
10342
10615
  ];
10343
10616
  function readPath(obj, path) {
10344
10617
  let v = obj;
10345
- for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _533 => _533[k]]);
10618
+ for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _549 => _549[k]]);
10346
10619
  return typeof v === "number" ? v : 0;
10347
10620
  }
10348
10621
  function patchPath(obj, path, value) {
@@ -10384,8 +10657,8 @@ function wheelPick(dx, dy, wheel, color) {
10384
10657
  return rgbToHexColor(nr, ng, nb);
10385
10658
  }
10386
10659
  var BLEND_MENU_GROUPS = [
10387
- { label: "Standard", modes: _chunkOLNIPTB3cjs.BLEND_MODES.filter((m) => !m.painterly && m.id !== "pigment") },
10388
- { label: "Paint", modes: _chunkOLNIPTB3cjs.BLEND_MODES.filter((m) => m.painterly || m.id === "pigment") }
10660
+ { label: "Standard", modes: _chunk2VX55NFMcjs.BLEND_MODES.filter((m) => !m.painterly && m.id !== "pigment") },
10661
+ { label: "Paint", modes: _chunk2VX55NFMcjs.BLEND_MODES.filter((m) => m.painterly || m.id === "pigment") }
10389
10662
  ];
10390
10663
  var LIGHT_SLIDER = { path: "light.amount", label: "Light", min: 0, max: 1, step: 0.01 };
10391
10664
  var PICKUP_SLIDERS = [
@@ -10394,7 +10667,7 @@ var PICKUP_SLIDERS = [
10394
10667
  ];
10395
10668
  function brushEngineControls(brush) {
10396
10669
  const c = engineControls(brush);
10397
- const wetPaint = brush.engine === "wet" && _optionalChain([brush, 'access', _534 => _534.wet, 'optionalAccess', _535 => _535.tool]) === "paint";
10670
+ const wetPaint = brush.engine === "wet" && _optionalChain([brush, 'access', _550 => _550.wet, 'optionalAccess', _551 => _551.tool]) === "paint";
10398
10671
  if (!c || !(wetPaint || ["dab", "mixer", "particle", "bristle", "impasto"].includes(brush.engine))) return c;
10399
10672
  const extra = brush.engine === "impasto" ? [{ path: "impasto.rim", label: "Rim", min: 0, max: 1, step: 0.01 }, { path: "impasto.clarity", label: "Clarity", min: 0, max: 1, step: 0.01 }] : [];
10400
10673
  return { ...c, sliders: [...c.sliders, LIGHT_SLIDER, ...extra], light: true };
@@ -10413,7 +10686,12 @@ function engineControls(brush) {
10413
10686
  { path: "particle.speed", label: "Speed", min: 0, max: 1, step: 0.01 },
10414
10687
  { path: "particle.gravity", label: "Gravity", min: -1, max: 1, step: 0.01 },
10415
10688
  { path: "particle.life", label: "Life", min: 0, max: 1, step: 0.01 },
10416
- { path: "particle.interval", label: "Bead spacing", min: 0, max: 1, step: 0.01 }
10689
+ { path: "particle.interval", label: "Bead spacing", min: 0, max: 1, step: 0.01 },
10690
+ { path: "particle.ribbonFill", label: "Ribbon fill", min: 0, max: 1, step: 0.01 },
10691
+ { path: "particle.waveAmplitude", label: "Wave", min: 0, max: 1, step: 0.01 },
10692
+ { path: "particle.waveLength", label: "Wavelength", min: 4, max: 400, step: 1 },
10693
+ { path: "particle.waveSpeed", label: "Wave speed", min: 0, max: 1, step: 0.01 },
10694
+ { path: "particle.wavePhaseJitter", label: "Wave scatter", min: 0, max: 1, step: 0.01 }
10417
10695
  ],
10418
10696
  mixingPath: null,
10419
10697
  dirty: false,
@@ -10472,7 +10750,7 @@ function engineControls(brush) {
10472
10750
  impastoTool: true
10473
10751
  };
10474
10752
  case "wet": {
10475
- const tool = _nullishCoalesce(_optionalChain([brush, 'access', _536 => _536.wet, 'optionalAccess', _537 => _537.tool]), () => ( "paint"));
10753
+ const tool = _nullishCoalesce(_optionalChain([brush, 'access', _552 => _552.wet, 'optionalAccess', _553 => _553.tool]), () => ( "paint"));
10476
10754
  const sliders = tool === "paint" ? [
10477
10755
  { path: "wet.water", label: "Water", min: 0, max: 1, step: 0.01 },
10478
10756
  { path: "wet.pigment", label: "Pigment", min: 0, max: 1, step: 0.01 },
@@ -10605,7 +10883,7 @@ function startWetClock(controller, frame, cancel) {
10605
10883
  id = raf(loop);
10606
10884
  return () => {
10607
10885
  stopped = true;
10608
- _optionalChain([caf, 'optionalCall', _538 => _538(id)]);
10886
+ _optionalChain([caf, 'optionalCall', _554 => _554(id)]);
10609
10887
  };
10610
10888
  }
10611
10889
  function drawWaterOverlay(controller, ctx) {
@@ -10628,13 +10906,29 @@ var LIGHT_SLIDERS = [
10628
10906
  { path: "elevation", label: "Light height", min: 5, max: 90, step: 1 },
10629
10907
  { path: "relief", label: "Relief", min: 0, max: 1, step: 0.01 }
10630
10908
  ];
10631
- var PARTICLE_KIND_LABELS = { string: "Strings", spring: "Springs", orbit: "Orbits", flow: "Flow" };
10632
- var PARTICLE_RENDER_LABELS = { dot: "Dots", line: "Lines", sequence: "Beads" };
10909
+ var PARTICLE_KIND_LABELS = { string: "Strings", spring: "Springs", orbit: "Orbits", flow: "Flow", elastic: "Elastic", fuzzy: "Fuzzy" };
10910
+ var PARTICLE_RENDER_LABELS = { dot: "Dots", line: "Lines", sequence: "Beads", ribbon: "Ribbon" };
10911
+ var RIBBON_PAIR_LABELS = { adjacent: "Neighbours", "first-last": "Outermost" };
10912
+ var DOT_TEXTURE_ORDER_LABELS = { sequence: "In turn", random: "Random" };
10913
+ var DOT_ROTATION_LABELS = { follow: "Follow motion", random: "Random", fixed: "Tip angle" };
10633
10914
  var STAMP_LABELS = { dot: "Dot", star: "Star", heart: "Heart", leaf: "Leaf", flower: "Flower", confetti: "Confetti", splat: "Splat", sparkle: "Sparkle", ring: "Ring" };
10915
+ function toggleStickerRef(refs, ref2) {
10916
+ if (refs.includes(ref2)) return refs.length > 1 ? refs.filter((r) => r !== ref2) : [...refs];
10917
+ return refs.length < _chunkH4AOUUBEcjs.MAX_STICKER_STAMPS ? [...refs, ref2] : [...refs];
10918
+ }
10919
+ function stickerRefLabel(ref2) {
10920
+ const stamp = ref2.startsWith("editor:") ? ref2.slice(7) : null;
10921
+ if (stamp && STAMP_LABELS[stamp]) return STAMP_LABELS[stamp];
10922
+ return ref2.slice(ref2.indexOf(":") + 1);
10923
+ }
10634
10924
  function toggleStamp(stamps, stamp) {
10635
10925
  const next = stamps.includes(stamp) ? stamps.filter((s) => s !== stamp) : [...stamps, stamp];
10636
10926
  return next.length ? next : [stamp];
10637
10927
  }
10928
+ function toggleDotTexture(textures, stamp) {
10929
+ if (textures.includes(stamp)) return textures.filter((s) => s !== stamp);
10930
+ return textures.length < _chunkH4AOUUBEcjs.MAX_DOT_TEXTURES ? [...textures, stamp] : [...textures];
10931
+ }
10638
10932
  var STROKE_SLIDERS = [
10639
10933
  { path: "tip.size", label: "Size", min: 1, max: 400, step: 1 },
10640
10934
  { path: "tip.opacity", label: "Opacity", min: 0, max: 1, step: 0.01 },
@@ -10858,7 +11152,7 @@ function createPaintEffectsToolProvider(controller, options = {}) {
10858
11152
  name: { type: "string", minLength: 1, description: "The layer name (default: the effect's name)." },
10859
11153
  aboveId: { type: "string", minLength: 1, description: "Put it directly above this layer (default: above the active layer, else on top)." },
10860
11154
  opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0\u20131 (default 1)." },
10861
- blend: { type: "string", enum: _chunkOLNIPTB3cjs.BLEND_MODES.map((m) => m.id), description: "Layer blend mode (default normal); screen or linear-dodge for light, multiply for textures." },
11155
+ blend: { type: "string", enum: _chunk2VX55NFMcjs.BLEND_MODES.map((m) => m.id), description: "Layer blend mode (default normal); screen or linear-dodge for light, multiply for textures." },
10862
11156
  time: { type: "number", minimum: 0, description: "Which moment of an animated effect to draw, in ms (default 0)." }
10863
11157
  },
10864
11158
  required: ["effect"],
@@ -11256,4 +11550,22 @@ function createPaintEditorDocument(controller, options = {}) {
11256
11550
 
11257
11551
 
11258
11552
 
11259
- exports.BACKLIGHT_SPILL = BACKLIGHT_SPILL; exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunkOLNIPTB3cjs.BLEND_MODES; exports.BRUSH_ID = _chunkQ2UYUWAZcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkQ2UYUWAZcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkQ2UYUWAZcjs.BUILTIN_BRUSHES; exports.BristleStroke = _chunkQ2UYUWAZcjs.BristleStroke; exports.DEFAULT_BACKLIGHT_COLOR = DEFAULT_BACKLIGHT_COLOR; exports.DEFAULT_BEHAVIOR = _chunkQ2UYUWAZcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkQ2UYUWAZcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkQ2UYUWAZcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkQ2UYUWAZcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkVMROIWLLcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunkQ2UYUWAZcjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHT = _chunkQ2UYUWAZcjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunkQ2UYUWAZcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkPQ3H2AANcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkPQ3H2AANcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunkQ2UYUWAZcjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkQ2UYUWAZcjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunkQ2UYUWAZcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunkQ2UYUWAZcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkVMROIWLLcjs.DEFAULT_WET_PARAMS; exports.DryStroke = _chunkQ2UYUWAZcjs.DryStroke; exports.EFFECT_MAP_REPEATS = _chunkQ2UYUWAZcjs.EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = _chunkQ2UYUWAZcjs.EFFECT_STRIP_HEIGHT; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkPQ3H2AANcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkPQ3H2AANcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunk7PT4RJL5cjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunkQ2UYUWAZcjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkQ2UYUWAZcjs.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 = _chunkPQ3H2AANcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; 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 = _chunkQ2UYUWAZcjs.MULTI_COLOR_MODES; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunkOLNIPTB3cjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunkQ2UYUWAZcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkQ2UYUWAZcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkPQ3H2AANcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkPQ3H2AANcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkPQ3H2AANcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkPQ3H2AANcjs.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 = _chunkQ2UYUWAZcjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunkQ2UYUWAZcjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkQ2UYUWAZcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkQ2UYUWAZcjs.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 = _chunkPQ3H2AANcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkPQ3H2AANcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkPQ3H2AANcjs.PaperGrain; exports.ParticleStroke = _chunkQ2UYUWAZcjs.ParticleStroke; exports.PenDabWalker = _chunkQ2UYUWAZcjs.PenDabWalker; exports.PenSmoother = _chunkQ2UYUWAZcjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkQ2UYUWAZcjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerSpray = _chunkQ2UYUWAZcjs.StickerSpray; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunkPQ3H2AANcjs.TileableNoise; exports.WET_FLOW_KINDS = _chunkVMROIWLLcjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunkQ2UYUWAZcjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkVMROIWLLcjs.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 = _chunkQ2UYUWAZcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkPQ3H2AANcjs.addPaintGradientStop; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.backlightOf = backlightOf; exports.brushEngineControls = brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkQ2UYUWAZcjs.brushTakesPaint; exports.brushToJSON = _chunkQ2UYUWAZcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = _chunkQ2UYUWAZcjs.clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.contactSheet = contactSheet; 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.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = _chunkQ2UYUWAZcjs.drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectDabField = _chunkQ2UYUWAZcjs.effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = _chunkQ2UYUWAZcjs.effectPaintKey; exports.effectPaintSize = _chunkQ2UYUWAZcjs.effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkPQ3H2AANcjs.grainCatch; exports.grainHeights = _chunkPQ3H2AANcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunkPQ3H2AANcjs.hash2; exports.hexToPaintRgb = _chunkPQ3H2AANcjs.hexToPaintRgb; exports.hexToRgb8 = _chunkQ2UYUWAZcjs.hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunk7PT4RJL5cjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunkOLNIPTB3cjs.isBlendMode; exports.isGradientPaint = _chunkPQ3H2AANcjs.isGradientPaint; exports.isPaintEffectPaint = _chunkQ2UYUWAZcjs.isPaintEffectPaint; exports.isPainterlyBlendMode = _chunkOLNIPTB3cjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkQ2UYUWAZcjs.isWetBrush; exports.isWetCapable = _chunkQ2UYUWAZcjs.isWetCapable; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.liveStrokeBounds = liveStrokeBounds; exports.liveStrokeRefusal = liveStrokeRefusal; exports.mapPenPoint = mapPenPoint; exports.mix32 = _chunkPQ3H2AANcjs.mix32; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = _chunkQ2UYUWAZcjs.mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = multiColorSliders; exports.multiColorToPaint = _chunkQ2UYUWAZcjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkQ2UYUWAZcjs.normalizeBehavior; exports.normalizeBristle = _chunkQ2UYUWAZcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkQ2UYUWAZcjs.normalizeDynamics; exports.normalizeFlow = _chunkVMROIWLLcjs.normalizeFlow; exports.normalizeHexColor = _chunkPQ3H2AANcjs.normalizeHexColor; exports.normalizeImpasto = _chunkQ2UYUWAZcjs.normalizeImpasto; exports.normalizeLight = _chunkQ2UYUWAZcjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunkQ2UYUWAZcjs.normalizeMultiColor; exports.normalizePaintBrush = _chunkQ2UYUWAZcjs.normalizePaintBrush; exports.normalizePaper = _chunkQ2UYUWAZcjs.normalizePaper; exports.normalizeParticle = _chunkQ2UYUWAZcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkQ2UYUWAZcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = _chunkQ2UYUWAZcjs.normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunkQ2UYUWAZcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkVMROIWLLcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkPQ3H2AANcjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintSourceColor = _chunkPQ3H2AANcjs.paintSourceColor; exports.paintSourceCss = _chunkPQ3H2AANcjs.paintSourceCss; exports.paintToMultiColor = _chunkQ2UYUWAZcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunkQ2UYUWAZcjs.paperPreset; exports.parseBrushLibrary = _chunkQ2UYUWAZcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkPQ3H2AANcjs.parsePaintSource; exports.patchBrushValue = patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunkQ2UYUWAZcjs.penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.quickStencil = quickStencil; exports.rand01 = _chunkPQ3H2AANcjs.rand01; exports.randSigned = _chunkPQ3H2AANcjs.randSigned; exports.readEffectStrokeMap = _chunkQ2UYUWAZcjs.readEffectStrokeMap; exports.readPaintEffectPaint = _chunkQ2UYUWAZcjs.readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkPQ3H2AANcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkPQ3H2AANcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunkQ2UYUWAZcjs.renderPaper; exports.renderStickers = _chunkQ2UYUWAZcjs.renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkPQ3H2AANcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkPQ3H2AANcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleEffectAt = _chunkQ2UYUWAZcjs.sampleEffectAt; exports.sampleEffectField = _chunkQ2UYUWAZcjs.sampleEffectField; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkPQ3H2AANcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunkPQ3H2AANcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkPQ3H2AANcjs.solidPaint; exports.stampCoverage = _chunkQ2UYUWAZcjs.stampCoverage; exports.standardBlendMode = _chunkOLNIPTB3cjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = _chunkQ2UYUWAZcjs.stickerAt; exports.stickerRect = _chunkQ2UYUWAZcjs.stickerRect; exports.stickerSurface = _chunkQ2UYUWAZcjs.stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokeSchedule = strokeSchedule; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = _chunkQ2UYUWAZcjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunkQ2UYUWAZcjs.toStrokePoint; exports.toggleStamp = toggleStamp; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkPQ3H2AANcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkQ2UYUWAZcjs.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 = _chunkVMROIWLLcjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunk7PT4RJL5cjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;
11553
+
11554
+
11555
+
11556
+
11557
+
11558
+
11559
+
11560
+
11561
+
11562
+
11563
+
11564
+
11565
+
11566
+
11567
+
11568
+
11569
+
11570
+
11571
+ exports.BACKLIGHT_SPILL = BACKLIGHT_SPILL; exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunk2VX55NFMcjs.BLEND_MODES; exports.BRUSH_ID = _chunkH4AOUUBEcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkH4AOUUBEcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkH4AOUUBEcjs.BUILTIN_BRUSHES; exports.BristleStroke = _chunkH4AOUUBEcjs.BristleStroke; exports.DEFAULT_BACKLIGHT_COLOR = DEFAULT_BACKLIGHT_COLOR; exports.DEFAULT_BEHAVIOR = _chunkH4AOUUBEcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkH4AOUUBEcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkH4AOUUBEcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkH4AOUUBEcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkKBYB7OWBcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunkH4AOUUBEcjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHT = _chunkH4AOUUBEcjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunkH4AOUUBEcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkI7NJPHWVcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkI7NJPHWVcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunkH4AOUUBEcjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkH4AOUUBEcjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunkH4AOUUBEcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunkH4AOUUBEcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkKBYB7OWBcjs.DEFAULT_WET_PARAMS; exports.DOT_ROTATIONS = _chunkH4AOUUBEcjs.DOT_ROTATIONS; exports.DOT_ROTATION_LABELS = DOT_ROTATION_LABELS; exports.DOT_TEXTURE_ORDERS = _chunkH4AOUUBEcjs.DOT_TEXTURE_ORDERS; exports.DOT_TEXTURE_ORDER_LABELS = DOT_TEXTURE_ORDER_LABELS; exports.DryStroke = _chunkH4AOUUBEcjs.DryStroke; exports.EFFECT_MAP_REPEATS = _chunkH4AOUUBEcjs.EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = _chunkH4AOUUBEcjs.EFFECT_STRIP_HEIGHT; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkI7NJPHWVcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkI7NJPHWVcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunk7PT4RJL5cjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunkH4AOUUBEcjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkH4AOUUBEcjs.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 = _chunkI7NJPHWVcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_DOT_TEXTURES = _chunkH4AOUUBEcjs.MAX_DOT_TEXTURES; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; exports.MAX_STICKER_STAMPS = _chunkH4AOUUBEcjs.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 = _chunkH4AOUUBEcjs.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 = _chunkH4AOUUBEcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkH4AOUUBEcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkI7NJPHWVcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkI7NJPHWVcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkI7NJPHWVcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkI7NJPHWVcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkI7NJPHWVcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkI7NJPHWVcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkI7NJPHWVcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkI7NJPHWVcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkI7NJPHWVcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkI7NJPHWVcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkI7NJPHWVcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkI7NJPHWVcjs.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 = _chunkH4AOUUBEcjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunkH4AOUUBEcjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkH4AOUUBEcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkH4AOUUBEcjs.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 = _chunkI7NJPHWVcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkI7NJPHWVcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkI7NJPHWVcjs.PaperGrain; exports.ParticleStroke = _chunkH4AOUUBEcjs.ParticleStroke; exports.PenDabWalker = _chunkH4AOUUBEcjs.PenDabWalker; exports.PenSmoother = _chunkH4AOUUBEcjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.RIBBON_PAIRS = _chunkH4AOUUBEcjs.RIBBON_PAIRS; exports.RIBBON_PAIR_LABELS = RIBBON_PAIR_LABELS; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkZEYMKDYScjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_ART_SIZE = _chunkH4AOUUBEcjs.STICKER_ART_SIZE; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerArtCache = _chunkH4AOUUBEcjs.StickerArtCache; exports.StickerBrowser = _chunkLJRCU3BJcjs.StickerBrowser; exports.StickerSpray = _chunkH4AOUUBEcjs.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 = _chunkH4AOUUBEcjs.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 = _chunkH4AOUUBEcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkI7NJPHWVcjs.addPaintGradientStop; exports.addPolygonArea = _chunkH4AOUUBEcjs.addPolygonArea; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.backlightOf = backlightOf; exports.brushEngineControls = brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkH4AOUUBEcjs.brushTakesPaint; exports.brushToJSON = _chunkH4AOUUBEcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = _chunkH4AOUUBEcjs.clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.contactSheet = contactSheet; 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 = _chunkH4AOUUBEcjs.defaultStickerRasterizer; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = _chunkH4AOUUBEcjs.drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectDabField = _chunkH4AOUUBEcjs.effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = _chunkH4AOUUBEcjs.effectPaintKey; exports.effectPaintSize = _chunkH4AOUUBEcjs.effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkI7NJPHWVcjs.grainCatch; exports.grainHeights = _chunkI7NJPHWVcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunk3K6HWEXZcjs.hash2; exports.hexToPaintRgb = _chunkI7NJPHWVcjs.hexToPaintRgb; exports.hexToRgb8 = _chunkH4AOUUBEcjs.hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunk7PT4RJL5cjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunk2VX55NFMcjs.isBlendMode; exports.isGradientPaint = _chunkI7NJPHWVcjs.isGradientPaint; exports.isPaintEffectPaint = _chunkH4AOUUBEcjs.isPaintEffectPaint; exports.isPainterlyBlendMode = _chunk2VX55NFMcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkH4AOUUBEcjs.isWetBrush; exports.isWetCapable = _chunkH4AOUUBEcjs.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 = _chunkH4AOUUBEcjs.mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = multiColorSliders; exports.multiColorToPaint = _chunkH4AOUUBEcjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkH4AOUUBEcjs.normalizeBehavior; exports.normalizeBristle = _chunkH4AOUUBEcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkH4AOUUBEcjs.normalizeDynamics; exports.normalizeFlow = _chunkKBYB7OWBcjs.normalizeFlow; exports.normalizeHexColor = _chunkI7NJPHWVcjs.normalizeHexColor; exports.normalizeImpasto = _chunkH4AOUUBEcjs.normalizeImpasto; exports.normalizeLight = _chunkH4AOUUBEcjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunkH4AOUUBEcjs.normalizeMultiColor; exports.normalizePaintBrush = _chunkH4AOUUBEcjs.normalizePaintBrush; exports.normalizePaper = _chunkH4AOUUBEcjs.normalizePaper; exports.normalizeParticle = _chunkH4AOUUBEcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkH4AOUUBEcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = _chunkH4AOUUBEcjs.normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunkH4AOUUBEcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkKBYB7OWBcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkI7NJPHWVcjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintSourceColor = _chunkI7NJPHWVcjs.paintSourceColor; exports.paintSourceCss = _chunkI7NJPHWVcjs.paintSourceCss; exports.paintToMultiColor = _chunkH4AOUUBEcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunkH4AOUUBEcjs.paperPreset; exports.parseBrushLibrary = _chunkH4AOUUBEcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkI7NJPHWVcjs.parsePaintSource; exports.patchBrushValue = patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunkH4AOUUBEcjs.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 = _chunkH4AOUUBEcjs.readEffectStrokeMap; exports.readPaintEffectPaint = _chunkH4AOUUBEcjs.readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkI7NJPHWVcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkI7NJPHWVcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunkH4AOUUBEcjs.renderPaper; exports.renderStickers = _chunkH4AOUUBEcjs.renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkI7NJPHWVcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkI7NJPHWVcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleArt = _chunkH4AOUUBEcjs.sampleArt; exports.sampleEffectAt = _chunkH4AOUUBEcjs.sampleEffectAt; exports.sampleEffectField = _chunkH4AOUUBEcjs.sampleEffectField; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkI7NJPHWVcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunk3K6HWEXZcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkI7NJPHWVcjs.solidPaint; exports.stampCoverage = _chunkZEYMKDYScjs.stampCoverage; exports.standardBlendMode = _chunk2VX55NFMcjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = _chunkH4AOUUBEcjs.stickerAt; exports.stickerRect = _chunkH4AOUUBEcjs.stickerRect; exports.stickerRefLabel = stickerRefLabel; exports.stickerStamp = _chunkH4AOUUBEcjs.stickerStamp; exports.stickerSurface = _chunkH4AOUUBEcjs.stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokeSchedule = strokeSchedule; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = _chunkH4AOUUBEcjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunkH4AOUUBEcjs.toStrokePoint; exports.toggleDotTexture = toggleDotTexture; exports.toggleStamp = toggleStamp; exports.toggleStickerRef = toggleStickerRef; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkI7NJPHWVcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkH4AOUUBEcjs.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 = _chunk7PT4RJL5cjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;