@pixerate/editor 0.154.0 → 0.156.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 (86) hide show
  1. package/dist/animation-editor/index.cjs +60 -61
  2. package/dist/animation-editor/index.js +5 -6
  3. package/dist/{brushstrokeRender-YAZVQUXY.cjs → brushstrokeRender-5WANQIG4.cjs} +10 -10
  4. package/dist/{brushstrokeRender-EUDQTDYS.js → brushstrokeRender-Q4LI22QV.js} +3 -3
  5. package/dist/canvas/index.cjs +23 -24
  6. package/dist/canvas/index.js +3 -4
  7. package/dist/chart/index.cjs +2 -3
  8. package/dist/chart/index.js +1 -2
  9. package/dist/{chunk-AGZ47XY2.js → chunk-2N2QPO3H.js} +6 -2
  10. package/dist/{chunk-NMXPOKF3.js → chunk-45XXVHVG.js} +1 -1
  11. package/dist/{chunk-FLOGD3QB.js → chunk-6UPGM3JB.js} +2 -2
  12. package/dist/{chunk-6FUAHCVI.cjs → chunk-7NW46N7I.cjs} +16 -16
  13. package/dist/{chunk-ORDXMBD4.js → chunk-A5UCR2TO.js} +10 -3
  14. package/dist/{chunk-PI45JMP7.cjs → chunk-CD7PLU77.cjs} +81 -81
  15. package/dist/{chunk-LRRCMRSL.cjs → chunk-EBDCRTZI.cjs} +20 -16
  16. package/dist/{chunk-OLCYQLFE.js → chunk-EL5PAHNP.js} +1 -1
  17. package/dist/{chunk-PUC43JPT.cjs → chunk-EYVVIZJ3.cjs} +1 -1
  18. package/dist/{chunk-BXMIBMVG.cjs → chunk-JGKCC5OF.cjs} +65 -58
  19. package/dist/chunk-M4MIZPQI.cjs +393 -0
  20. package/dist/{chunk-LIXLD433.cjs → chunk-MHEXLG3M.cjs} +35 -35
  21. package/dist/chunk-NHLYK3AX.js +393 -0
  22. package/dist/{chunk-RHXW4TA5.cjs → chunk-QMI5HZWA.cjs} +7 -7
  23. package/dist/{chunk-XFDQEAOS.cjs → chunk-RQCMSEM5.cjs} +2 -2
  24. package/dist/{chunk-BCY22GBH.js → chunk-SDHZG5TF.js} +1 -1
  25. package/dist/{chunk-HVX35M2I.cjs → chunk-WI7QJA7A.cjs} +2 -2
  26. package/dist/{chunk-UILRJQFD.js → chunk-WNAAWLZ5.js} +1 -1
  27. package/dist/{chunk-4J4MC3F5.js → chunk-YXOW456B.js} +1 -1
  28. package/dist/{chunk-Y64YPIFT.js → chunk-ZQWLWDZI.js} +1 -1
  29. package/dist/diagram/index.cjs +2 -3
  30. package/dist/diagram/index.js +1 -2
  31. package/dist/image-editor/controller.d.cts +8 -0
  32. package/dist/image-editor/controller.d.ts +8 -0
  33. package/dist/image-editor/editorDocument.d.cts +16 -0
  34. package/dist/image-editor/editorDocument.d.ts +16 -0
  35. package/dist/image-editor/index.cjs +787 -737
  36. package/dist/image-editor/index.d.cts +1 -0
  37. package/dist/image-editor/index.d.ts +1 -0
  38. package/dist/image-editor/index.js +56 -6
  39. package/dist/index.cjs +4 -5
  40. package/dist/index.js +2 -3
  41. package/dist/paint/grain.d.cts +7 -0
  42. package/dist/paint/grain.d.ts +7 -0
  43. package/dist/paint/index.cjs +3 -3
  44. package/dist/paint/index.js +2 -2
  45. package/dist/paint-editor/controller.d.cts +38 -0
  46. package/dist/paint-editor/controller.d.ts +38 -0
  47. package/dist/paint-editor/document.d.cts +8 -0
  48. package/dist/paint-editor/document.d.ts +8 -0
  49. package/dist/paint-editor/editorDocument.d.cts +17 -0
  50. package/dist/paint-editor/editorDocument.d.ts +17 -0
  51. package/dist/paint-editor/index.cjs +476 -273
  52. package/dist/paint-editor/index.d.cts +1 -0
  53. package/dist/paint-editor/index.d.ts +1 -0
  54. package/dist/paint-editor/index.js +216 -13
  55. package/dist/paint-editor/paper.d.cts +8 -0
  56. package/dist/paint-editor/paper.d.ts +8 -0
  57. package/dist/paint-editor/stencils.d.cts +2 -0
  58. package/dist/paint-editor/stencils.d.ts +2 -0
  59. package/dist/paint-editor/wet.d.cts +1 -0
  60. package/dist/paint-editor/wet.d.ts +1 -0
  61. package/dist/parameters/index.cjs +2 -3
  62. package/dist/parameters/index.js +1 -2
  63. package/dist/persistence/assets.d.cts +51 -0
  64. package/dist/persistence/assets.d.ts +51 -0
  65. package/dist/persistence/editorDocument.d.cts +12 -0
  66. package/dist/persistence/editorDocument.d.ts +12 -0
  67. package/dist/persistence/index.cjs +32 -8
  68. package/dist/persistence/index.d.cts +1 -0
  69. package/dist/persistence/index.d.ts +1 -0
  70. package/dist/persistence/index.js +34 -10
  71. package/dist/spreadsheet/index.cjs +3 -4
  72. package/dist/spreadsheet/index.js +2 -3
  73. package/dist/tokens/index.cjs +3 -4
  74. package/dist/tokens/index.js +2 -3
  75. package/dist/vector/index.cjs +952 -953
  76. package/dist/vector/index.js +5 -6
  77. package/dist/video-editor/index.cjs +2 -3
  78. package/dist/video-editor/index.js +1 -2
  79. package/package.json +1 -1
  80. package/skills/pixerate-image-editor/SKILL.md +16 -24
  81. package/skills/pixerate-image-editor/references/smart-objects.md +28 -0
  82. package/skills/pixerate-paint-editor/SKILL.md +26 -6
  83. package/dist/chunk-5H2C3QSF.cjs +0 -134
  84. package/dist/chunk-GNV54DLO.js +0 -134
  85. package/dist/chunk-L5OWG2NA.cjs +0 -135
  86. package/dist/chunk-WHKNYFM2.js +0 -135
@@ -7,7 +7,7 @@ var _chunkVKF3PWKRcjs = require('../chunk-VKF3PWKR.cjs');
7
7
 
8
8
 
9
9
 
10
- var _chunkPI45JMP7cjs = require('../chunk-PI45JMP7.cjs');
10
+ var _chunkCD7PLU77cjs = require('../chunk-CD7PLU77.cjs');
11
11
  require('../chunk-A2IS7EHE.cjs');
12
12
 
13
13
 
@@ -54,7 +54,7 @@ var _chunkJLWLX52Lcjs = require('../chunk-JLWLX52L.cjs');
54
54
 
55
55
 
56
56
  var _chunkSWTUM32Hcjs = require('../chunk-SWTUM32H.cjs');
57
- require('../chunk-RHXW4TA5.cjs');
57
+ require('../chunk-QMI5HZWA.cjs');
58
58
 
59
59
 
60
60
 
@@ -119,7 +119,7 @@ require('../chunk-RHXW4TA5.cjs');
119
119
 
120
120
 
121
121
 
122
- var _chunkBXMIBMVGcjs = require('../chunk-BXMIBMVG.cjs');
122
+ var _chunkJGKCC5OFcjs = require('../chunk-JGKCC5OF.cjs');
123
123
  require('../chunk-CVFAAZXE.cjs');
124
124
  require('../chunk-GF2RBSDM.cjs');
125
125
  require('../chunk-NM3G4VQT.cjs');
@@ -189,7 +189,7 @@ require('../chunk-WOFXZ3XU.cjs');
189
189
 
190
190
 
191
191
 
192
- var _chunkLRRCMRSLcjs = require('../chunk-LRRCMRSL.cjs');
192
+ var _chunkEBDCRTZIcjs = require('../chunk-EBDCRTZI.cjs');
193
193
  require('../chunk-YQGCPL5X.cjs');
194
194
 
195
195
 
@@ -224,6 +224,11 @@ require('../chunk-XFM3OCHU.cjs');
224
224
  require('../chunk-NIBFDFYW.cjs');
225
225
  require('../chunk-ALNIFK5G.cjs');
226
226
  require('../chunk-UWEQ55MY.cjs');
227
+
228
+
229
+
230
+ var _chunkM4MIZPQIcjs = require('../chunk-M4MIZPQI.cjs');
231
+ require('../chunk-2BSBFBOA.cjs');
227
232
  require('../chunk-LEUZ4FRC.cjs');
228
233
  require('../chunk-A6QWKBJP.cjs');
229
234
 
@@ -265,7 +270,7 @@ function normalizeCanvas(raw) {
265
270
  function createPaintDocument(options = {}) {
266
271
  const canvas = normalizeCanvas({ width: _nullishCoalesce(options.width, () => ( 2048)), height: _nullishCoalesce(options.height, () => ( 1536)), dpi: options.dpi });
267
272
  const layer = createPaintLayer("Layer 1");
268
- return { canvas, paper: _chunkBXMIBMVGcjs.normalizePaper.call(void 0, _nullishCoalesce(options.paper, () => ( {}))), layers: [layer], activeLayerId: layer.id, strokes: [] };
273
+ return { canvas, paper: _chunkJGKCC5OFcjs.normalizePaper.call(void 0, _nullishCoalesce(options.paper, () => ( {}))), layers: [layer], activeLayerId: layer.id, strokes: [] };
269
274
  }
270
275
 
271
276
  // src/paint-editor/dab-stroke.ts
@@ -309,7 +314,7 @@ function multiColorForDab(mc, palette, index, seed, mixing) {
309
314
  const n = palette.length;
310
315
  if (mc.order === "random") {
311
316
  const run = Math.floor(index / mc.length);
312
- return [...palette[Math.min(n - 1, Math.floor(_chunkLRRCMRSLcjs.rand01.call(void 0, seed, run, 11) * n))]];
317
+ return [...palette[Math.min(n - 1, Math.floor(_chunkEBDCRTZIcjs.rand01.call(void 0, seed, run, 11) * n))]];
313
318
  }
314
319
  const f = index / mc.length % n;
315
320
  const i = Math.floor(f);
@@ -319,24 +324,24 @@ var PaintDabStroke = (_class = class {
319
324
  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);
320
325
  this.brush = brush;
321
326
  this.options = options;
322
- this.smoother = new (0, _chunkBXMIBMVGcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
323
- this.copies = _optionalChain([options, 'access', _2 => _2.copies, 'optionalAccess', _3 => _3.length]) ? options.copies : [_chunkBXMIBMVGcjs.IDENTITY_COPY];
327
+ this.smoother = new (0, _chunkJGKCC5OFcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
328
+ this.copies = _optionalChain([options, 'access', _2 => _2.copies, 'optionalAccess', _3 => _3.length]) ? options.copies : [_chunkJGKCC5OFcjs.IDENTITY_COPY];
324
329
  const exchanging = brush.engine === "mixer" || brush.engine === "dab";
325
- const rates = brush.engine === "mixer" ? _chunkLRRCMRSLcjs.mixerRates.call(void 0, brush.mixer) : _chunkLRRCMRSLcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, 1, brush.behavior.mixing);
330
+ const rates = brush.engine === "mixer" ? _chunkEBDCRTZIcjs.mixerRates.call(void 0, brush.mixer) : _chunkEBDCRTZIcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, 1, brush.behavior.mixing);
326
331
  this.mixing = brush.engine === "mixer" ? brush.mixer.mixing : brush.behavior.mixing;
327
332
  this.states = this.copies.map((c, i) => ({
328
- walker: new (0, _chunkBXMIBMVGcjs.PenDabWalker)(brush, (_nullishCoalesce(options.seed, () => ( 0))) + i * 7919 | 0, c.linear),
329
- exchange: exchanging ? new (0, _chunkLRRCMRSLcjs.PaintExchange)(rates, options.load) : null,
330
- smudge: brush.engine === "smudge" ? new (0, _chunkLRRCMRSLcjs.SmudgeTip)(brush.smudge, brush.tip.size * (1 + brush.dynamics.tiltSize * 1.5)) : null
333
+ walker: new (0, _chunkJGKCC5OFcjs.PenDabWalker)(brush, (_nullishCoalesce(options.seed, () => ( 0))) + i * 7919 | 0, c.linear),
334
+ exchange: exchanging ? new (0, _chunkEBDCRTZIcjs.PaintExchange)(rates, options.load) : null,
335
+ smudge: brush.engine === "smudge" ? new (0, _chunkEBDCRTZIcjs.SmudgeTip)(brush.smudge, brush.tip.size * (1 + brush.dynamics.tiltSize * 1.5)) : null
331
336
  }));
332
- this.medium = new (0, _chunkLRRCMRSLcjs.TileMedium)(options.target, brush.engine === "dab" ? { blend: brush.tip.blend } : {});
337
+ this.medium = new (0, _chunkEBDCRTZIcjs.TileMedium)(options.target, brush.engine === "dab" ? { blend: brush.tip.blend } : {});
333
338
  this.depth = options.grain && !options.grain.flat ? Math.min(1, Math.max(0, options.paperDepth * brush.grain)) : 0;
334
- this.coverage = brush.engine === "dab" ? new (0, _chunkLRRCMRSLcjs.CoverageMap)() : null;
335
- this.sampler = exchanging && options.paint ? new (0, _chunkLRRCMRSLcjs.PaintGradientSampler)(options.paint, _nullishCoalesce(options.seed, () => ( 0))) : null;
339
+ this.coverage = brush.engine === "dab" ? new (0, _chunkEBDCRTZIcjs.CoverageMap)() : null;
340
+ this.sampler = exchanging && options.paint ? new (0, _chunkEBDCRTZIcjs.PaintGradientSampler)(options.paint, _nullishCoalesce(options.seed, () => ( 0))) : null;
336
341
  const table = _optionalChain([this, 'access', _4 => _4.sampler, 'optionalAccess', _5 => _5.acrossTip]) ? this.sampler.tipTable(GRADIENT_STEPS) : null;
337
342
  this.gradient = table ? table.map((e) => e.rgb) : null;
338
343
  this.gradientAlpha = table && table.some((e) => e.alpha < 1) ? table.map((e) => e.alpha) : null;
339
- this.scratch = brush.engine === "blender" ? _chunkLRRCMRSLcjs.createBlenderScratch.call(void 0, ) : null;
344
+ this.scratch = brush.engine === "blender" ? _chunkEBDCRTZIcjs.createBlenderScratch.call(void 0, ) : null;
340
345
  }
341
346
 
342
347
 
@@ -395,7 +400,7 @@ var PaintDabStroke = (_class = class {
395
400
  }
396
401
  paintDabs(copy, dabs, rects) {
397
402
  for (const d of dabs) {
398
- const rect = _chunkLRRCMRSLcjs.dabRect.call(void 0, d, this.brush.tip.hardness);
403
+ const rect = _chunkEBDCRTZIcjs.dabRect.call(void 0, d, this.brush.tip.hardness);
399
404
  if (rect.width <= 0 || rect.height <= 0) continue;
400
405
  this.dab(copy, d, rect);
401
406
  rects.push(rect);
@@ -411,13 +416,13 @@ var PaintDabStroke = (_class = class {
411
416
  }
412
417
  const tip = this.tip.subarray(0, n);
413
418
  tip.fill(0);
414
- _chunkLRRCMRSLcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.tip.hardness, rect, tip);
419
+ _chunkEBDCRTZIcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.tip.hardness, rect, tip);
415
420
  if (!(this.depth > 0 && this.options.grain)) return { tip, cov: tip };
416
421
  const cov = this.cov.subarray(0, n);
417
422
  const grain = this.options.grain;
418
423
  for (let yy = 0, k = 0; yy < rect.height; yy++) {
419
424
  const y = rect.y + yy + 0.5;
420
- for (let xx = 0; xx < rect.width; xx++, k++) cov[k] = tip[k] > 0 ? tip[k] * _chunkLRRCMRSLcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure) : 0;
425
+ for (let xx = 0; xx < rect.width; xx++, k++) cov[k] = tip[k] > 0 ? tip[k] * _chunkEBDCRTZIcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure) : 0;
421
426
  }
422
427
  return { tip, cov };
423
428
  }
@@ -426,7 +431,7 @@ var PaintDabStroke = (_class = class {
426
431
  const { tip, cov } = this.rasterize(d, rect);
427
432
  const st = this.states[copy];
428
433
  if (brush.engine === "blender") {
429
- _chunkLRRCMRSLcjs.blenderDab.call(void 0, this.medium, rect, cov, d.opacity * d.alpha * brush.tip.opacity, d.radius, brush.blender, this.scratch);
434
+ _chunkEBDCRTZIcjs.blenderDab.call(void 0, this.medium, rect, cov, d.opacity * d.alpha * brush.tip.opacity, d.radius, brush.blender, this.scratch);
430
435
  return;
431
436
  }
432
437
  if (brush.engine === "smudge") {
@@ -665,19 +670,19 @@ var ThickStrokeDriver = (_class3 = class {
665
670
  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);
666
671
  this.init = init;
667
672
  const b = init.brush;
668
- this.smoother = new (0, _chunkBXMIBMVGcjs.PenSmoother)(b.tip.smoothing, b.pressureSmoothing);
669
- const copies = init.copies.length ? init.copies : [_chunkBXMIBMVGcjs.IDENTITY_COPY];
673
+ this.smoother = new (0, _chunkJGKCC5OFcjs.PenSmoother)(b.tip.smoothing, b.pressureSmoothing);
674
+ const copies = init.copies.length ? init.copies : [_chunkJGKCC5OFcjs.IDENTITY_COPY];
670
675
  this.copies = copies;
671
- const rates = _chunkLRRCMRSLcjs.exchangeRates.call(void 0, b.behavior.pickup, b.behavior.mix, 1, b.behavior.mixing);
676
+ const rates = _chunkEBDCRTZIcjs.exchangeRates.call(void 0, b.behavior.pickup, b.behavior.mix, 1, b.behavior.mixing);
672
677
  this.states = copies.map((c, i) => ({
673
- walker: new (0, _chunkBXMIBMVGcjs.PenDabWalker)(b, init.seed + i * 7919 | 0, c.linear),
674
- exchange: new (0, _chunkLRRCMRSLcjs.PaintExchange)(rates, init.load),
675
- smudge: b.impasto.tool === "knife" ? new (0, _chunkLRRCMRSLcjs.SmudgeTip)({ strength: 0.85, length: 0.6 + 0.38 * b.impasto.drag, mixing: b.behavior.mixing }, b.tip.size * 1.2) : null,
678
+ walker: new (0, _chunkJGKCC5OFcjs.PenDabWalker)(b, init.seed + i * 7919 | 0, c.linear),
679
+ exchange: new (0, _chunkEBDCRTZIcjs.PaintExchange)(rates, init.load),
680
+ smudge: b.impasto.tool === "knife" ? new (0, _chunkEBDCRTZIcjs.SmudgeTip)({ strength: 0.85, length: 0.6 + 0.38 * b.impasto.drag, mixing: b.behavior.mixing }, b.tip.size * 1.2) : null,
676
681
  carried: null,
677
682
  amount: 1
678
683
  }));
679
- this.medium = new (0, _chunkLRRCMRSLcjs.TileMedium)(init.target, {});
680
- this.sampler = init.paint ? new (0, _chunkLRRCMRSLcjs.PaintGradientSampler)(init.paint.map.by === "across-tip" ? { ...init.paint, map: { by: "distance", length: 300, repeat: "mirror" } } : init.paint, init.seed) : null;
684
+ this.medium = new (0, _chunkEBDCRTZIcjs.TileMedium)(init.target, {});
685
+ this.sampler = init.paint ? new (0, _chunkEBDCRTZIcjs.PaintGradientSampler)(init.paint.map.by === "across-tip" ? { ...init.paint, map: { by: "distance", length: 300, repeat: "mirror" } } : init.paint, init.seed) : null;
681
686
  }
682
687
 
683
688
  __init12() {this.dabCount = 0}
@@ -773,7 +778,7 @@ var ThickStrokeDriver = (_class3 = class {
773
778
  }
774
779
  applyDabs(copy, dabs, rects) {
775
780
  for (const d of dabs) {
776
- const rect = _chunkLRRCMRSLcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
781
+ const rect = _chunkEBDCRTZIcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
777
782
  if (rect.width <= 0 || rect.height <= 0) continue;
778
783
  this.dab(copy, d, rect);
779
784
  rects.push(rect);
@@ -788,7 +793,7 @@ var ThickStrokeDriver = (_class3 = class {
788
793
  const n = rect.width * rect.height;
789
794
  if (this.tip.length < n) this.tip = new Float32Array(n);
790
795
  const tip = this.tip.subarray(0, n);
791
- _chunkLRRCMRSLcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, b.tip.hardness, rect, tip);
796
+ _chunkEBDCRTZIcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, b.tip.hardness, rect, tip);
792
797
  const sel = this.init.target.selection;
793
798
  if (sel) {
794
799
  for (let yy = 0, p = 0; yy < rect.height; yy++)
@@ -842,7 +847,7 @@ var ThickStrokeDriver = (_class3 = class {
842
847
  const full = 255 * thick * k;
843
848
  switch (im.tool) {
844
849
  case "brush": {
845
- const ridge = 0.6 + 0.4 * Math.sin(u * 9 + _chunkLRRCMRSLcjs.hash2.call(void 0, Math.round(u * 6), 3, seed) * 6.28) + 0.15 * (_chunkLRRCMRSLcjs.hash2.call(void 0, lx, ly, seed) - 0.5);
850
+ const ridge = 0.6 + 0.4 * Math.sin(u * 9 + _chunkEBDCRTZIcjs.hash2.call(void 0, Math.round(u * 6), 3, seed) * 6.28) + 0.15 * (_chunkEBDCRTZIcjs.hash2.call(void 0, lx, ly, seed) - 0.5);
846
851
  const target = full * c * ridge;
847
852
  h = Math.max(h0 * (1 - 0.25 * c * im.drag), Math.min(255, h0 * 0.35 + target));
848
853
  break;
@@ -858,7 +863,7 @@ var ThickStrokeDriver = (_class3 = class {
858
863
  break;
859
864
  }
860
865
  case "roller": {
861
- const stipple = 0.75 + 0.5 * _chunkLRRCMRSLcjs.hash2.call(void 0, lx >> 1, ly >> 1, seed);
866
+ const stipple = 0.75 + 0.5 * _chunkEBDCRTZIcjs.hash2.call(void 0, lx >> 1, ly >> 1, seed);
862
867
  h = h0 + (Math.min(255, full * 0.6 * stipple) - h0) * Math.min(1, c * 1.5);
863
868
  break;
864
869
  }
@@ -968,7 +973,7 @@ var PaintStrokeSession = (_class4 = class {
968
973
  this.layerId = init.layerId;
969
974
  this.base = init.surface;
970
975
  this.live = new Map(this.base.tiles);
971
- this.copies = init.copies.length ? init.copies : [_chunkBXMIBMVGcjs.IDENTITY_COPY];
976
+ this.copies = init.copies.length ? init.copies : [_chunkJGKCC5OFcjs.IDENTITY_COPY];
972
977
  const brush = init.brush;
973
978
  if (init.wet) this.wetDriver = init.wet.driver;
974
979
  this.apply = {
@@ -983,11 +988,11 @@ var PaintStrokeSession = (_class4 = class {
983
988
  };
984
989
  if (this.wetDriver) {
985
990
  } else if (init.sticker) {
986
- this.stickerSpray = new (0, _chunkBXMIBMVGcjs.StickerSpray)({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: _nullishCoalesce(init.paint, () => ( null)) });
991
+ this.stickerSpray = new (0, _chunkJGKCC5OFcjs.StickerSpray)({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: _nullishCoalesce(init.paint, () => ( null)) });
987
992
  } else if (init.thick) {
988
993
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
989
994
  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)) });
990
- } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunkBXMIBMVGcjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
995
+ } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunkJGKCC5OFcjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
991
996
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
992
997
  this.wet = new PaintDabStroke(brush, {
993
998
  target: this.tileTarget(),
@@ -1002,7 +1007,7 @@ var PaintStrokeSession = (_class4 = class {
1002
1007
  });
1003
1008
  } else {
1004
1009
  const opts = { grain: init.grain, paperDepth: init.paperDepth, seed: init.seed, copies: this.copies, paint: _nullishCoalesce(init.paint, () => ( null)) };
1005
- this.dry = brush.engine === "particle" ? new (0, _chunkBXMIBMVGcjs.ParticleStroke)(brush, opts) : brush.engine === "bristle" ? new (0, _chunkBXMIBMVGcjs.BristleStroke)(brush, opts) : new (0, _chunkBXMIBMVGcjs.DryStroke)(brush, opts);
1010
+ this.dry = brush.engine === "particle" ? new (0, _chunkJGKCC5OFcjs.ParticleStroke)(brush, opts) : brush.engine === "bristle" ? new (0, _chunkJGKCC5OFcjs.BristleStroke)(brush, opts) : new (0, _chunkJGKCC5OFcjs.DryStroke)(brush, opts);
1006
1011
  }
1007
1012
  }
1008
1013
 
@@ -1092,7 +1097,7 @@ var PaintStrokeSession = (_class4 = class {
1092
1097
  const changed = d.dabCount > 0;
1093
1098
  this.result = { layerId: this.layerId, bounds: changed ? d.bounds : null, dabs: d.dabCount, strokeId: null, wet: true };
1094
1099
  const carried = d.load;
1095
- if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkLRRCMRSLcjs.cleanMixer.call(void 0, carried);
1100
+ if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkEBDCRTZIcjs.cleanMixer.call(void 0, carried);
1096
1101
  this.host.commit(this, changed ? this.init.wet.surface() : null, false);
1097
1102
  }
1098
1103
  update(rects) {
@@ -1118,7 +1123,7 @@ var PaintStrokeSession = (_class4 = class {
1118
1123
  const src = _nullishCoalesce(_optionalChain([this, 'access', _27 => _27.base, 'access', _28 => _28.tiles, 'access', _29 => _29.get, 'call', _30 => _30(key), 'optionalAccess', _31 => _31.data]), () => ( defaultTile(this.base)));
1119
1124
  const prev = this.touched.has(key) ? _optionalChain([this, 'access', _32 => _32.live, 'access', _33 => _33.get, 'call', _34 => _34(key), 'optionalAccess', _35 => _35.data]) : void 0;
1120
1125
  this.touched.add(key);
1121
- const data = _chunkLRRCMRSLcjs.applyStrokeToTile.call(void 0, this.dry.coverage, src, ch, tx, ty, this.apply, prev ? { into: prev, region: r } : {});
1126
+ const data = _chunkEBDCRTZIcjs.applyStrokeToTile.call(void 0, this.dry.coverage, src, ch, tx, ty, this.apply, prev ? { into: prev, region: r } : {});
1122
1127
  this.live.set(key, { data, uniform: null });
1123
1128
  }
1124
1129
  this.host.update(this.layerId, new (0, _chunkCWM3CUUXcjs.TiledSurface)(ch, new Map(this.live), this.base.defaultValue), rects);
@@ -1153,7 +1158,7 @@ var PaintStrokeSession = (_class4 = class {
1153
1158
  const dabs = this.dry ? this.dry.dabCount : this.thickDriver ? this.thickDriver.dabCount : this.stickerSpray ? this.stickerSpray.dabCount : this.wet.dabCount;
1154
1159
  this.result = { layerId: this.layerId, bounds: changed ? this.bounds : null, dabs, strokeId: null };
1155
1160
  const carried = _nullishCoalesce(_optionalChain([this, 'access', _36 => _36.wet, 'optionalAccess', _37 => _37.load]), () => ( _optionalChain([this, 'access', _38 => _38.thickDriver, 'optionalAccess', _39 => _39.load])));
1156
- if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkLRRCMRSLcjs.cleanMixer.call(void 0, carried);
1161
+ if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : _chunkEBDCRTZIcjs.cleanMixer.call(void 0, carried);
1157
1162
  this.host.commit(this, surface, false);
1158
1163
  return this.result;
1159
1164
  }
@@ -1166,15 +1171,15 @@ var PaintStrokeSession = (_class4 = class {
1166
1171
  }, _class4);
1167
1172
  function mixerLoadForStroke(brush, current, color) {
1168
1173
  if (!brush.loadsColor) return { reservoir: null, amount: 0, pickup: brush.mixer.cleanEachStroke ? null : current.pickup };
1169
- if (brush.mixer.loadEachStroke || !current.reservoir) return _chunkLRRCMRSLcjs.loadMixer.call(void 0, current, color);
1174
+ if (brush.mixer.loadEachStroke || !current.reservoir) return _chunkEBDCRTZIcjs.loadMixer.call(void 0, current, color);
1170
1175
  return current;
1171
1176
  }
1172
1177
  function brushLoadForStroke(brush, current, color) {
1173
1178
  if (brush.engine === "mixer") return mixerLoadForStroke(brush, current, color);
1174
1179
  if (brush.engine === "impasto") return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1175
- 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 } : _chunkLRRCMRSLcjs.EMPTY_MIXER_LOAD;
1176
- if (_chunkBXMIBMVGcjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1177
- return _chunkLRRCMRSLcjs.EMPTY_MIXER_LOAD;
1180
+ 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 } : _chunkEBDCRTZIcjs.EMPTY_MIXER_LOAD;
1181
+ if (_chunkJGKCC5OFcjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1182
+ return _chunkEBDCRTZIcjs.EMPTY_MIXER_LOAD;
1178
1183
  }
1179
1184
 
1180
1185
  // src/paint-editor/stencils.ts
@@ -1352,6 +1357,17 @@ function stencilMask(stencils, width, height) {
1352
1357
  }
1353
1358
  return { width, height, data };
1354
1359
  }
1360
+ function translateStencil(s, dx, dy) {
1361
+ const p = (q) => q ? { x: q.x + dx, y: q.y + dy } : void 0;
1362
+ return {
1363
+ ...s,
1364
+ ...s.from ? { from: p(s.from) } : {},
1365
+ ...s.to ? { to: p(s.to) } : {},
1366
+ ...s.center ? { center: p(s.center) } : {},
1367
+ ...s.rect ? { rect: { ...s.rect, x: s.rect.x + dx, y: s.rect.y + dy } } : {},
1368
+ ...s.points ? { points: s.points.map((q) => p(q)) } : {}
1369
+ };
1370
+ }
1355
1371
  function scaleStencil(s, k) {
1356
1372
  const p = (q) => q ? { x: q.x * k, y: q.y * k } : void 0;
1357
1373
  return {
@@ -1430,7 +1446,7 @@ function normalizeBrushStroke(raw) {
1430
1446
  const out = {
1431
1447
  id: r.id,
1432
1448
  layerId: r.layerId,
1433
- brush: _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, _nullishCoalesce(r.brush, () => ( {}))),
1449
+ brush: _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, _nullishCoalesce(r.brush, () => ( {}))),
1434
1450
  color: typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : "#000000",
1435
1451
  points,
1436
1452
  seed: finite2(r.seed) ? r.seed | 0 : 0
@@ -1449,7 +1465,7 @@ function normalizeBrushStroke(raw) {
1449
1465
  }
1450
1466
  if (st.length) out.stencils = st;
1451
1467
  }
1452
- const paint = _chunkLRRCMRSLcjs.readPaintSource.call(void 0, r.paint);
1468
+ const paint = _chunkEBDCRTZIcjs.readPaintSource.call(void 0, r.paint);
1453
1469
  if (paint && paint.type === "gradient") out.paint = paint;
1454
1470
  if (Array.isArray(r.steps) && r.steps.length === points.length && r.steps.every((v) => Number.isInteger(v) && v >= 0)) out.steps = [...r.steps];
1455
1471
  return out;
@@ -1486,9 +1502,9 @@ function varyStroke(stroke, m, v) {
1486
1502
  if (ps !== 1) q.pressure = Math.min(1, Math.max(0, (_nullishCoalesce(p.pressure, () => ( 1))) * ps));
1487
1503
  return q;
1488
1504
  });
1489
- const brush = s !== 1 ? _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
1505
+ const brush = s !== 1 ? _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
1490
1506
  const out = { ...stroke, brush, points };
1491
- if (stroke.paint && s !== 1) out.paint = _chunkLRRCMRSLcjs.scalePaintGradient.call(void 0, stroke.paint, s);
1507
+ if (stroke.paint && s !== 1) out.paint = _chunkEBDCRTZIcjs.scalePaintGradient.call(void 0, stroke.paint, s);
1492
1508
  if (_optionalChain([stroke, 'access', _57 => _57.copies, 'optionalAccess', _58 => _58.length])) {
1493
1509
  const inv = invertAffine(m);
1494
1510
  out.copies = stroke.copies.map((c) => composeAffine(m, composeAffine(c, inv)));
@@ -1502,7 +1518,7 @@ var TRACING_NODE_ID = "__tracing";
1502
1518
  var PAPER_EFFECT_NODE_ID = "__paper_effect";
1503
1519
  function paperKey(p, light) {
1504
1520
  const metal = _nullishCoalesce(p.metallic, () => ( 0));
1505
- return JSON.stringify([p.pattern, p.seed, p.color, p.scale, p.tiling, p.shading, p.dry, metal, metal > 0 && light ? [light.azimuth, light.elevation] : null]);
1521
+ return JSON.stringify([p.pattern, p.seed, p.color, p.scale, p.tiling, p.shading, p.dry, _nullishCoalesce(p.offset, () => ( null)), metal, metal > 0 && light ? [light.azimuth, light.elevation] : null]);
1506
1522
  }
1507
1523
  var paperNodes = /* @__PURE__ */ new WeakMap();
1508
1524
  function paperNode(paper, light) {
@@ -1517,10 +1533,10 @@ function paperNode(paper, light) {
1517
1533
  var grainCache = /* @__PURE__ */ new Map();
1518
1534
  var tileCache = /* @__PURE__ */ new Map();
1519
1535
  function paperGrain(paper) {
1520
- const key = JSON.stringify([paper.pattern, paper.seed, paper.scale, paper.tiling, paper.dry]);
1536
+ const key = JSON.stringify([paper.pattern, paper.seed, paper.scale, paper.tiling, paper.dry, _nullishCoalesce(paper.offset, () => ( null))]);
1521
1537
  let g = grainCache.get(key);
1522
1538
  if (!g) {
1523
- g = new (0, _chunkLRRCMRSLcjs.PaperGrain)(paper, "dry");
1539
+ g = new (0, _chunkEBDCRTZIcjs.PaperGrain)(paper, "dry");
1524
1540
  if (grainCache.size > 16) grainCache.delete(grainCache.keys().next().value);
1525
1541
  grainCache.set(key, g);
1526
1542
  }
@@ -1530,7 +1546,7 @@ function paperTile(paper, r, light) {
1530
1546
  const key = `${paperKey(paper, light)}|${r.x},${r.y},${r.width},${r.height}`;
1531
1547
  let t = tileCache.get(key);
1532
1548
  if (!t) {
1533
- t = _chunkBXMIBMVGcjs.renderPaper.call(void 0, paper, r, paperGrain(paper), light);
1549
+ t = _chunkJGKCC5OFcjs.renderPaper.call(void 0, paper, r, paperGrain(paper), light);
1534
1550
  if (tileCache.size > 512) tileCache.delete(tileCache.keys().next().value);
1535
1551
  tileCache.set(key, t);
1536
1552
  }
@@ -1607,7 +1623,7 @@ function downsampleRgba(data, width, height, tw, th) {
1607
1623
  // src/paint-editor/serialize.ts
1608
1624
  var PAINT_FORMAT = "pixerate-paint";
1609
1625
  var PAINT_SCHEMA_VERSION = 1;
1610
- var KNOWN = /* @__PURE__ */ new Set(["format", "version", "width", "height", "dpi", "paper", "layers", "assets", "activeLayerId", "strokes", "guides", "swatches", "mixingPad", "wet", "wetEvents", "paintEvents"]);
1626
+ var KNOWN = /* @__PURE__ */ new Set(["format", "version", "width", "height", "dpi", "paper", "layers", "assets", "activeLayerId", "strokes", "guides", "swatches", "mixingPad", "wet", "wetEvents", "paintEvents", "origin"]);
1611
1627
  function documentExtensions(raw) {
1612
1628
  const out = {};
1613
1629
  for (const [k, v] of Object.entries(raw)) if (!KNOWN.has(k)) out[k] = v;
@@ -1631,14 +1647,15 @@ function header(state, options) {
1631
1647
  if (options.wet !== void 0) out.wet = JSON.parse(JSON.stringify(options.wet));
1632
1648
  if (_optionalChain([state, 'access', _65 => _65.wetEvents, 'optionalAccess', _66 => _66.length])) out.wetEvents = JSON.parse(JSON.stringify(state.wetEvents));
1633
1649
  if (_optionalChain([state, 'access', _67 => _67.paintEvents, 'optionalAccess', _68 => _68.length])) out.paintEvents = JSON.parse(JSON.stringify(state.paintEvents));
1650
+ if (state.origin && (state.origin.x || state.origin.y)) out.origin = { ...state.origin };
1634
1651
  return out;
1635
1652
  }
1636
1653
  function serializePaintDocument(state, options = {}) {
1637
- const { layers, assets } = _chunkPI45JMP7cjs.serializeLayers.call(void 0, state.layers);
1654
+ const { layers, assets } = _chunkCD7PLU77cjs.serializeLayers.call(void 0, state.layers);
1638
1655
  return { ...header(state, options), layers, assets };
1639
1656
  }
1640
1657
  async function serializePaintDocumentExternal(state, store, options = {}) {
1641
- const { layers, assets } = await _chunkPI45JMP7cjs.serializeLayersExternal.call(void 0, state.layers, store);
1658
+ const { layers, assets } = await _chunkCD7PLU77cjs.serializeLayersExternal.call(void 0, state.layers, store);
1642
1659
  return { ...header(state, options), layers, assets };
1643
1660
  }
1644
1661
  function paintLayersOnly(layers, problems) {
@@ -1673,9 +1690,9 @@ function deserializePaintDocument(raw) {
1673
1690
  }
1674
1691
  const problems = [];
1675
1692
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
1676
- const paper = _chunkBXMIBMVGcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
1693
+ const paper = _chunkJGKCC5OFcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
1677
1694
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
1678
- const layers = paintLayersOnly(_chunkPI45JMP7cjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1695
+ const layers = paintLayersOnly(_chunkCD7PLU77cjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1679
1696
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
1680
1697
  const activeLayerId = wanted && _chunkHGTDMKNEcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _70 => _70.filter, 'call', _71 => _71((l) => l.type === "pixel"), 'access', _72 => _72.pop, 'call', _73 => _73(), 'optionalAccess', _74 => _74.id]), () => ( null));
1681
1698
  const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
@@ -1683,13 +1700,15 @@ function deserializePaintDocument(raw) {
1683
1700
  if (wetEvents.length) state.wetEvents = wetEvents;
1684
1701
  const paintEvents = Array.isArray(r.paintEvents) ? r.paintEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.at) && typeof e.layerId === "string" && ["fill", "clear", "flatten", "stickers"].includes(e.kind)) : [];
1685
1702
  if (paintEvents.length) state.paintEvents = paintEvents;
1703
+ const o = r.origin;
1704
+ if (o && typeof o === "object" && Number.isFinite(o.x) && Number.isFinite(o.y) && (o.x || o.y)) state.origin = { x: Math.round(o.x), y: Math.round(o.y) };
1686
1705
  return { state, extensions: documentExtensions(r), guides: r.guides, swatches: r.swatches, mixingPad: r.mixingPad, wet: r.wet, problems };
1687
1706
  }
1688
1707
  async function deserializePaintDocumentAsync(raw, store) {
1689
1708
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
1690
1709
  const r = raw;
1691
1710
  const problems = [];
1692
- const assets = await _chunkPI45JMP7cjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1711
+ const assets = await _chunkCD7PLU77cjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1693
1712
  const loaded = deserializePaintDocument({ ...r, assets });
1694
1713
  return { ...loaded, problems: [...problems, ...loaded.problems] };
1695
1714
  }
@@ -1772,7 +1791,7 @@ function pointerToPenPoint(e, x, y, view) {
1772
1791
  const p = { x, y, pressure: samplePressure(e) };
1773
1792
  if (typeof e.timeStamp === "number" && Number.isFinite(e.timeStamp)) p.t = e.timeStamp;
1774
1793
  if (e.pointerType !== "pen") return p;
1775
- const o = _chunkBXMIBMVGcjs.penOrientation.call(void 0, {
1794
+ const o = _chunkJGKCC5OFcjs.penOrientation.call(void 0, {
1776
1795
  x,
1777
1796
  y,
1778
1797
  altitude: typeof e.altitudeAngle === "number" ? e.altitudeAngle : void 0,
@@ -1845,13 +1864,13 @@ function union2(a, b) {
1845
1864
  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 };
1846
1865
  }
1847
1866
  function wetPaperInput(paper) {
1848
- const grain = new (0, _chunkLRRCMRSLcjs.PaperGrain)(paper, "wet");
1867
+ const grain = new (0, _chunkEBDCRTZIcjs.PaperGrain)(paper, "wet");
1849
1868
  const flat = grain.flat;
1850
1869
  return {
1851
1870
  absorption: paper.absorption,
1852
1871
  permeability: paper.permeability,
1853
1872
  roughness: flat ? 0 : paper.roughness,
1854
- color: _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, paper.color),
1873
+ color: _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, paper.color),
1855
1874
  heightAt: flat ? () => 0.5 : (x, y) => grain.at(x, y)
1856
1875
  };
1857
1876
  }
@@ -1859,8 +1878,8 @@ var WetStrokeDriver = (_class5 = class {
1859
1878
  constructor(init) {;_class5.prototype.__init35.call(this);_class5.prototype.__init36.call(this);_class5.prototype.__init37.call(this);_class5.prototype.__init38.call(this);_class5.prototype.__init39.call(this);_class5.prototype.__init40.call(this);_class5.prototype.__init41.call(this);_class5.prototype.__init42.call(this);_class5.prototype.__init43.call(this);_class5.prototype.__init44.call(this);_class5.prototype.__init45.call(this);_class5.prototype.__init46.call(this);
1860
1879
  this.init = init;
1861
1880
  const brush = init.brush;
1862
- this.smoother = new (0, _chunkBXMIBMVGcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
1863
- const copies = init.copies.length ? init.copies : [_chunkBXMIBMVGcjs.IDENTITY_COPY];
1881
+ this.smoother = new (0, _chunkJGKCC5OFcjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
1882
+ const copies = init.copies.length ? init.copies : [_chunkJGKCC5OFcjs.IDENTITY_COPY];
1864
1883
  const wet = brush.wet;
1865
1884
  const spacing = Math.max(0.02, brush.tip.spacing);
1866
1885
  const perDab = Math.min(1, spacing * 1.2);
@@ -1870,16 +1889,16 @@ var WetStrokeDriver = (_class5 = class {
1870
1889
  mass: STROKE_MASS * wet.pigment * (1 - 0.6 * thin) * perDab,
1871
1890
  body: wet.body * (1 - thin)
1872
1891
  });
1873
- const rates = _chunkLRRCMRSLcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
1892
+ const rates = _chunkEBDCRTZIcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
1874
1893
  this.states = copies.map((c, i) => ({
1875
- walker: new (0, _chunkBXMIBMVGcjs.PenDabWalker)(brush, init.seed + i * 7919 | 0, c.linear),
1876
- exchange: wet.tool === "paint" ? new (0, _chunkLRRCMRSLcjs.PaintExchange)(rates, init.load) : null,
1894
+ walker: new (0, _chunkJGKCC5OFcjs.PenDabWalker)(brush, init.seed + i * 7919 | 0, c.linear),
1895
+ exchange: wet.tool === "paint" ? new (0, _chunkEBDCRTZIcjs.PaintExchange)(rates, init.load) : null,
1877
1896
  last: null
1878
1897
  }));
1879
1898
  this.copies = copies;
1880
1899
  this.depth = init.grain && !init.grain.flat ? Math.min(1, Math.max(0, init.paperDepth * brush.grain)) : 0;
1881
1900
  const g = _nullishCoalesce(init.paint, () => ( null));
1882
- this.sampler = g ? new (0, _chunkLRRCMRSLcjs.PaintGradientSampler)(g.map.by === "across-tip" ? { ...g, map: { by: "distance", length: 300, repeat: "mirror" } } : g, init.seed) : null;
1901
+ this.sampler = g ? new (0, _chunkEBDCRTZIcjs.PaintGradientSampler)(g.map.by === "across-tip" ? { ...g, map: { by: "distance", length: 300, repeat: "mirror" } } : g, init.seed) : null;
1883
1902
  }
1884
1903
 
1885
1904
  __init35() {this.dabCount = 0}
@@ -1951,7 +1970,7 @@ var WetStrokeDriver = (_class5 = class {
1951
1970
  }
1952
1971
  applyDabs(copy, dabs, rects) {
1953
1972
  for (const d of dabs) {
1954
- const rect = _chunkLRRCMRSLcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
1973
+ const rect = _chunkEBDCRTZIcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
1955
1974
  if (rect.width <= 0 || rect.height <= 0) continue;
1956
1975
  this.dab(copy, d, rect);
1957
1976
  rects.push(rect);
@@ -1968,7 +1987,7 @@ var WetStrokeDriver = (_class5 = class {
1968
1987
  const tip = this.tip.subarray(0, n);
1969
1988
  const cov = this.cov.subarray(0, n);
1970
1989
  tip.fill(0);
1971
- _chunkLRRCMRSLcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.init.brush.tip.hardness, rect, tip);
1990
+ _chunkEBDCRTZIcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.init.brush.tip.hardness, rect, tip);
1972
1991
  const grain = this.depth > 0 ? this.init.grain : null;
1973
1992
  const mask = this.init.mask;
1974
1993
  for (let yy = 0, k = 0; yy < rect.height; yy++) {
@@ -1979,7 +1998,7 @@ var WetStrokeDriver = (_class5 = class {
1979
1998
  tip[k] *= mx >= 0 && my >= 0 && mx < mask.width && my < mask.height ? mask.data[my * mask.width + mx] / 255 : 0;
1980
1999
  }
1981
2000
  let v = tip[k];
1982
- if (v > 0 && grain) v *= _chunkLRRCMRSLcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, rect.y + yy + 0.5), this.depth, d.pressure);
2001
+ if (v > 0 && grain) v *= _chunkEBDCRTZIcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, rect.y + yy + 0.5), this.depth, d.pressure);
1983
2002
  tip[k] = Math.round(tip[k] * COVERAGE_STEPS) / COVERAGE_STEPS;
1984
2003
  cov[k] = Math.round(v * COVERAGE_STEPS) / COVERAGE_STEPS;
1985
2004
  }
@@ -2133,7 +2152,10 @@ var PaintWetLayers = (_class6 = class {
2133
2152
  /** The world (made on first use, at the canvas size). */
2134
2153
  ensureWorld() {
2135
2154
  const { width, height } = this.host.canvas();
2136
- if (this.world && (this.world.width !== width || this.world.height !== height)) throw new Error("The wet world is the wrong size; dry the paint before resizing the canvas.");
2155
+ if (this.world && (this.world.width !== width || this.world.height !== height)) {
2156
+ if (this.world.laneIds().length) throw new Error("The wet world is the wrong size; dry the paint before resizing the canvas.");
2157
+ this.dropWorld();
2158
+ }
2137
2159
  if (!this.world) {
2138
2160
  this.world = new (0, _chunkGNK7SESQcjs.WetWorld)(width, height, wetPaperInput(this.host.paper()), { kernel: this.options.kernel, threads: this.options.threads });
2139
2161
  this.world.setTilt(this.tilt);
@@ -2396,12 +2418,19 @@ var PaintWetLayers = (_class6 = class {
2396
2418
  if (this.world) for (const id of this.world.laneIds()) this.world.removeLane(id);
2397
2419
  return;
2398
2420
  }
2421
+ const { width, height } = this.host.canvas();
2422
+ if (this.world && (this.world.width !== width || this.world.height !== height)) this.dropWorld();
2399
2423
  this.ensureWorld().restore(snap);
2400
2424
  this.syncDisplays();
2401
2425
  }
2426
+ dropWorld() {
2427
+ _optionalChain([this, 'access', _128 => _128.world, 'optionalAccess', _129 => _129.destroy, 'call', _130 => _130()]);
2428
+ this.world = null;
2429
+ this.driver = null;
2430
+ }
2402
2431
  /** Forgets everything wet (a new canvas, a resize, opening a document). */
2403
2432
  reset() {
2404
- _optionalChain([this, 'access', _128 => _128.world, 'optionalAccess', _129 => _129.destroy, 'call', _130 => _130()]);
2433
+ _optionalChain([this, 'access', _131 => _131.world, 'optionalAccess', _132 => _132.destroy, 'call', _133 => _133()]);
2405
2434
  this.world = null;
2406
2435
  this.driver = null;
2407
2436
  this.settings.clear();
@@ -2431,14 +2460,14 @@ var PaintWetLayers = (_class6 = class {
2431
2460
  return out;
2432
2461
  }
2433
2462
  destroy() {
2434
- _optionalChain([this, 'access', _131 => _131.world, 'optionalAccess', _132 => _132.destroy, 'call', _133 => _133()]);
2463
+ _optionalChain([this, 'access', _134 => _134.world, 'optionalAccess', _135 => _135.destroy, 'call', _136 => _136()]);
2435
2464
  this.world = null;
2436
- _optionalChain([this, 'access', _134 => _134.gpu, 'optionalAccess', _135 => _135.destroy, 'call', _136 => _136()]);
2465
+ _optionalChain([this, 'access', _137 => _137.gpu, 'optionalAccess', _138 => _138.destroy, 'call', _139 => _139()]);
2437
2466
  this.gpu = null;
2438
2467
  }
2439
2468
  }, _class6);
2440
2469
  function wetPigmentOf(hex, body) {
2441
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, hex);
2470
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, hex);
2442
2471
  return Array.from(_chunkGNK7SESQcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
2443
2472
  }
2444
2473
 
@@ -2446,13 +2475,13 @@ function wetPigmentOf(hex, body) {
2446
2475
  var thumbWorld = null;
2447
2476
  function paintWetTestStroke(brush, paper, color, width, height) {
2448
2477
  if (!thumbWorld || thumbWorld.width !== width || thumbWorld.height !== height) {
2449
- _optionalChain([thumbWorld, 'optionalAccess', _137 => _137.destroy, 'call', _138 => _138()]);
2478
+ _optionalChain([thumbWorld, 'optionalAccess', _140 => _140.destroy, 'call', _141 => _141()]);
2450
2479
  thumbWorld = new (0, _chunkGNK7SESQcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: "typescript", threads: 0 });
2451
2480
  } else thumbWorld.setPaper(wetPaperInput(paper));
2452
2481
  const w = thumbWorld;
2453
2482
  if (w.hasLane("thumb")) w.removeLane("thumb");
2454
2483
  w.ensureLane("thumb");
2455
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, color);
2484
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, color);
2456
2485
  if (brush.wet.tool !== "paint" && brush.wet.tool !== "water") {
2457
2486
  const half = Math.ceil(height / 2);
2458
2487
  w.paint("thumb", { x: 0, y: 0, width, height: half }, null, 0.4, Array.from(_chunkGNK7SESQcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], 0), (v) => v * 0.05));
@@ -2463,12 +2492,12 @@ function paintWetTestStroke(brush, paper, color, width, height) {
2463
2492
  laneId: "thumb",
2464
2493
  brush,
2465
2494
  color: [r / 255, g / 255, b / 255],
2466
- load: brushLoadForStroke(brush, _chunkLRRCMRSLcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2495
+ load: brushLoadForStroke(brush, _chunkEBDCRTZIcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2467
2496
  grain: paperGrain(paper),
2468
2497
  paperDepth: paper.depth,
2469
- paperColor: _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, paper.color),
2498
+ paperColor: _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, paper.color),
2470
2499
  seed: 7,
2471
- copies: [_chunkBXMIBMVGcjs.IDENTITY_COPY]
2500
+ copies: [_chunkJGKCC5OFcjs.IDENTITY_COPY]
2472
2501
  });
2473
2502
  driver.push(thumbnailStroke(width, height));
2474
2503
  driver.finish();
@@ -2488,7 +2517,7 @@ function thumbnailStroke(width, height) {
2488
2517
  return pts;
2489
2518
  }
2490
2519
  function paintTestStroke(surface, brush, paper, color, width, height) {
2491
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, color);
2520
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, color);
2492
2521
  let result = surface;
2493
2522
  let thick = null;
2494
2523
  const session = new PaintStrokeSession(
@@ -2507,14 +2536,14 @@ function paintTestStroke(surface, brush, paper, color, width, height) {
2507
2536
  lockTransparency: false,
2508
2537
  brush,
2509
2538
  color: [r, g, b, 255],
2510
- background: [..._chunkBXMIBMVGcjs.hexToRgb8.call(void 0, paper.color), 255],
2539
+ background: [..._chunkJGKCC5OFcjs.hexToRgb8.call(void 0, paper.color), 255],
2511
2540
  grain: paperGrain(paper),
2512
2541
  paperDepth: paper.depth,
2513
2542
  seed: 7,
2514
2543
  colorHex: color,
2515
2544
  affineCopies: [],
2516
- copies: [_chunkBXMIBMVGcjs.IDENTITY_COPY],
2517
- mixerLoad: brushLoadForStroke(brush, _chunkLRRCMRSLcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2545
+ copies: [_chunkJGKCC5OFcjs.IDENTITY_COPY],
2546
+ mixerLoad: brushLoadForStroke(brush, _chunkEBDCRTZIcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2518
2547
  thick: brush.engine === "impasto" ? { channels: emptyThickChannels() } : void 0,
2519
2548
  sticker: brush.engine === "sticker" ? { nextId: 1 } : void 0
2520
2549
  }
@@ -2527,8 +2556,8 @@ function renderBrushThumbnail(brush, options) {
2527
2556
  const width = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.width, () => ( 160)))));
2528
2557
  const height = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.height, () => ( 48)))));
2529
2558
  const maxSize = height * 0.42;
2530
- const b = brush.tip.size > maxSize ? _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
2531
- const rgba = [..._chunkBXMIBMVGcjs.hexToRgb8.call(void 0, options.color), 255];
2559
+ const b = brush.tip.size > maxSize ? _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
2560
+ const rgba = [..._chunkJGKCC5OFcjs.hexToRgb8.call(void 0, options.color), 255];
2532
2561
  let surface = _chunkCWM3CUUXcjs.emptySurface.call(void 0, 4);
2533
2562
  if (b.engine === "eraser") {
2534
2563
  surface = _chunkCWM3CUUXcjs.fillRect.call(void 0, surface, { x: 0, y: 0, width, height }, rgba);
@@ -2780,12 +2809,12 @@ function colorHarmony2(base, kind, options = {}) {
2780
2809
  function readSwatch(raw) {
2781
2810
  if (!raw || typeof raw !== "object") return null;
2782
2811
  const r = raw;
2783
- const g = _chunkLRRCMRSLcjs.readPaintSource.call(void 0, r.paint);
2784
- const color = typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : _optionalChain([g, 'optionalAccess', _139 => _139.type]) === "gradient" ? _chunkLRRCMRSLcjs.paintSourceColor.call(void 0, g) : null;
2812
+ const g = _chunkEBDCRTZIcjs.readPaintSource.call(void 0, r.paint);
2813
+ const color = typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : _optionalChain([g, 'optionalAccess', _142 => _142.type]) === "gradient" ? _chunkEBDCRTZIcjs.paintSourceColor.call(void 0, g) : null;
2785
2814
  if (!color) return null;
2786
2815
  const out = { color };
2787
2816
  if (typeof r.name === "string" && r.name.trim()) out.name = r.name.trim().slice(0, 80);
2788
- if (_optionalChain([g, 'optionalAccess', _140 => _140.type]) === "gradient") out.paint = g;
2817
+ if (_optionalChain([g, 'optionalAccess', _143 => _143.type]) === "gradient") out.paint = g;
2789
2818
  return out;
2790
2819
  }
2791
2820
  var DEFAULT_SWATCHES = [
@@ -2804,7 +2833,7 @@ var DEFAULT_SWATCHES = [
2804
2833
  // src/paint-editor/mixing-pad.ts
2805
2834
  var MIXING_PAD_WIDTH = 360;
2806
2835
  var MIXING_PAD_HEIGHT = 220;
2807
- var PAD_PAINT = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, {
2836
+ var PAD_PAINT = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, {
2808
2837
  id: "pad-paint",
2809
2838
  name: "Pad paint",
2810
2839
  category: "mixer",
@@ -2812,7 +2841,7 @@ var PAD_PAINT = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, {
2812
2841
  tip: { size: 28, hardness: 0.75, spacing: 0.1, opacity: 1, flow: 0.7, pressureSize: false, pressureOpacity: false },
2813
2842
  mixer: { wet: 0.45, load: 1, mix: 0.4, loadEachStroke: true, cleanEachStroke: true, mixing: "pigment" }
2814
2843
  });
2815
- var PAD_KNIFE = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, {
2844
+ var PAD_KNIFE = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, {
2816
2845
  id: "pad-knife",
2817
2846
  name: "Palette knife",
2818
2847
  category: "smudge",
@@ -2822,7 +2851,7 @@ var PAD_KNIFE = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, {
2822
2851
  // A knife drags streaks of paint and folds them into each other, mixing them as pigment.
2823
2852
  smudge: { strength: 0.6, length: 0.8, mixing: "pigment" }
2824
2853
  });
2825
- var PAD_BLOB = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, {
2854
+ var PAD_BLOB = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, {
2826
2855
  id: "pad-blob",
2827
2856
  name: "Pad blob",
2828
2857
  category: "custom",
@@ -2844,12 +2873,12 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init65.cal
2844
2873
  }
2845
2874
  }
2846
2875
  let brush = options.tool === "knife" ? PAD_KNIFE : PAD_PAINT;
2847
- if (options.size !== void 0) brush = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
2876
+ if (options.size !== void 0) brush = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
2848
2877
  return this.run(brush, points, options.color);
2849
2878
  }
2850
2879
  /** Paints `points` with `brush` in `color` on the pad. */
2851
2880
  run(brush, points, color) {
2852
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, color);
2881
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, color);
2853
2882
  let result = null;
2854
2883
  const session = new PaintStrokeSession(
2855
2884
  { update: () => {
@@ -2867,8 +2896,8 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init65.cal
2867
2896
  seed: 1,
2868
2897
  colorHex: color,
2869
2898
  affineCopies: [],
2870
- copies: [_chunkBXMIBMVGcjs.IDENTITY_COPY],
2871
- mixerLoad: brushLoadForStroke(brush, _chunkLRRCMRSLcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255])
2899
+ copies: [_chunkJGKCC5OFcjs.IDENTITY_COPY],
2900
+ mixerLoad: brushLoadForStroke(brush, _chunkEBDCRTZIcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255])
2872
2901
  }
2873
2902
  );
2874
2903
  session.push(points);
@@ -2943,10 +2972,10 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init65.cal
2943
2972
  const off = used.length === 1 ? 0 : 0.45 * R;
2944
2973
  const x = Math.min(cx + R - r, Math.max(cx - R + r, cx + Math.cos(a) * off));
2945
2974
  const y = Math.min(cy + R - r, Math.max(cy - R + r, cy + Math.sin(a) * off));
2946
- const blob = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
2975
+ const blob = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
2947
2976
  this.run(blob, [{ x, y }], p.color.toLowerCase());
2948
2977
  });
2949
- const knife = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
2978
+ const knife = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
2950
2979
  for (let k = 0; k < passes; k++) {
2951
2980
  const stir = [];
2952
2981
  const turns = 1.6;
@@ -2958,10 +2987,10 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init65.cal
2958
2987
  this.run(knife, stir, "#000000");
2959
2988
  }
2960
2989
  const mixed = _chunkCWM3CUUXcjs.mixPigments.call(void 0,
2961
- paints.map((p) => _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, p.color).map((v) => v / 255)),
2990
+ paints.map((p) => _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, p.color).map((v) => v / 255)),
2962
2991
  paints.map((p) => p.parts)
2963
2992
  );
2964
- const core = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
2993
+ const core = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
2965
2994
  const hex = "#" + mixed.map((v) => Math.round(v * 255).toString(16).padStart(2, "0")).join("");
2966
2995
  this.run(core, [{ x: cx, y: cy }], hex);
2967
2996
  return { color: this.pick(cx, cy, 2), bounds };
@@ -2972,7 +3001,7 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init65.cal
2972
3001
  }
2973
3002
  /** Replaces the pad with a PNG (data URL or base64) of the pad's size, as `toPng` writes. */
2974
3003
  fromPng(png) {
2975
- const bytes = png.startsWith("data:") ? _optionalChain([_chunkCWM3CUUXcjs.parseDataUrl.call(void 0, png), 'optionalAccess', _141 => _141.bytes]) : _chunkCWM3CUUXcjs.base64ToBytes.call(void 0, png);
3004
+ const bytes = png.startsWith("data:") ? _optionalChain([_chunkCWM3CUUXcjs.parseDataUrl.call(void 0, png), 'optionalAccess', _144 => _144.bytes]) : _chunkCWM3CUUXcjs.base64ToBytes.call(void 0, png);
2976
3005
  if (!bytes || !_chunkCWM3CUUXcjs.isPng.call(void 0, bytes)) throw new Error("The pad image is not a PNG data URL or base64 PNG.");
2977
3006
  const img = _chunkCWM3CUUXcjs.decodePng.call(void 0, bytes);
2978
3007
  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}.`);
@@ -3026,7 +3055,7 @@ async function replayPainting(source, target, options = {}) {
3026
3055
  const n = Math.min(left, chunk);
3027
3056
  await target.advanceWet({ steps: n });
3028
3057
  left -= n;
3029
- if (Number.isFinite(chunk)) await _optionalChain([options, 'access', _142 => _142.onWetSteps, 'optionalCall', _143 => _143(target.getState().wet.clock)]);
3058
+ if (Number.isFinite(chunk)) await _optionalChain([options, 'access', _145 => _145.onWetSteps, 'optionalCall', _146 => _146(target.getState().wet.clock)]);
3030
3059
  }
3031
3060
  };
3032
3061
  const sr = (r) => ({ x: r.x * s, y: r.y * s, width: r.width * s, height: r.height * s });
@@ -3038,7 +3067,7 @@ async function replayPainting(source, target, options = {}) {
3038
3067
  if (e.kind === "fill") target.fillLayer({ layerId: e.layerId, ...e.data });
3039
3068
  else if (e.kind === "clear") target.clearLayer(e.layerId);
3040
3069
  else if (e.kind === "stickers") {
3041
- const list = (_nullishCoalesce(_optionalChain([e, 'access', _144 => _144.data, 'optionalAccess', _145 => _145.stickers]), () => ( []))).map((x) => s === 1 ? x : { ...x, x: x.x * s, y: x.y * s, size: x.size * s });
3070
+ const list = (_nullishCoalesce(_optionalChain([e, 'access', _147 => _147.data, 'optionalAccess', _148 => _148.stickers]), () => ( []))).map((x) => s === 1 ? x : { ...x, x: x.x * s, y: x.y * s, size: x.size * s });
3042
3071
  target.replaceStickers(e.layerId, list);
3043
3072
  } else target.flattenRelief(e.layerId);
3044
3073
  continue;
@@ -3051,8 +3080,8 @@ async function replayPainting(source, target, options = {}) {
3051
3080
  switch (e.kind) {
3052
3081
  case "dry": {
3053
3082
  const rect = e.data;
3054
- const ids = _optionalChain([e, 'access', _146 => _146.layerId, 'optionalAccess', _147 => _147.split, 'call', _148 => _148(","), 'access', _149 => _149.filter, 'call', _150 => _150(Boolean)]);
3055
- if (_optionalChain([ids, 'optionalAccess', _151 => _151.length])) for (const id of ids) target.dryPaint({ layerId: id, rect: rect ? sr(rect) : void 0 });
3083
+ const ids = _optionalChain([e, 'access', _149 => _149.layerId, 'optionalAccess', _150 => _150.split, 'call', _151 => _151(","), 'access', _152 => _152.filter, 'call', _153 => _153(Boolean)]);
3084
+ if (_optionalChain([ids, 'optionalAccess', _154 => _154.length])) for (const id of ids) target.dryPaint({ layerId: id, rect: rect ? sr(rect) : void 0 });
3056
3085
  else target.dryPaint({ rect: rect ? sr(rect) : void 0 });
3057
3086
  break;
3058
3087
  }
@@ -3083,7 +3112,7 @@ async function replayPainting(source, target, options = {}) {
3083
3112
  strokes++;
3084
3113
  if (!target.getLayer(st.layerId)) continue;
3085
3114
  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)) };
3086
- if (st.brush.engine === "wet" && _optionalChain([st, 'access', _152 => _152.steps, 'optionalAccess', _153 => _153.length]) === st.points.length) {
3115
+ if (st.brush.engine === "wet" && _optionalChain([st, 'access', _155 => _155.steps, 'optionalAccess', _156 => _156.length]) === st.points.length) {
3087
3116
  await target.wetIdle();
3088
3117
  await advanceTo(st.steps[0]);
3089
3118
  const session = target.beginStroke({ ...init, start: st.points[0] });
@@ -3103,7 +3132,7 @@ async function replayPainting(source, target, options = {}) {
3103
3132
  await target.wetIdle();
3104
3133
  target.paintStroke({ ...init, points: st.points });
3105
3134
  }
3106
- await _optionalChain([options, 'access', _154 => _154.onStroke, 'optionalCall', _155 => _155(strokes)]);
3135
+ await _optionalChain([options, 'access', _157 => _157.onStroke, 'optionalCall', _158 => _158(strokes)]);
3107
3136
  }
3108
3137
  void IDENTITY_AFFINE;
3109
3138
  }
@@ -3148,7 +3177,7 @@ async function buildTimeLapse(source, target, options = {}) {
3148
3177
  wetChunk: wetEvery > 0 ? wetEvery : 0,
3149
3178
  onStroke: (i) => {
3150
3179
  if (i % perFrame === 0 || i === total) shoot(i);
3151
- _optionalChain([options, 'access', _156 => _156.onProgress, 'optionalCall', _157 => _157(total ? i / total : 1)]);
3180
+ _optionalChain([options, 'access', _159 => _159.onProgress, 'optionalCall', _160 => _160(total ? i / total : 1)]);
3152
3181
  },
3153
3182
  onWetSteps: wetEvery > 0 ? () => shoot(-1) : void 0
3154
3183
  });
@@ -3318,7 +3347,7 @@ function parseColor(value, what = "color") {
3318
3347
  return value.trim().toLowerCase();
3319
3348
  }
3320
3349
  function rgbaOf(hex) {
3321
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, hex);
3350
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, hex);
3322
3351
  return [r, g, b, 255];
3323
3352
  }
3324
3353
  function rgbToHex(r, g, b) {
@@ -3331,7 +3360,7 @@ function unionRect(a, b) {
3331
3360
  const y = Math.min(a.y, b.y);
3332
3361
  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 };
3333
3362
  }
3334
- var isPixelLayer = (l) => _optionalChain([l, 'optionalAccess', _158 => _158.type]) === "pixel";
3363
+ var isPixelLayer = (l) => _optionalChain([l, 'optionalAccess', _161 => _161.type]) === "pixel";
3335
3364
  var PaintEditorController = (_class10 = class _PaintEditorController {
3336
3365
 
3337
3366
  __init72() {this.extensions = {}}
@@ -3346,7 +3375,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3346
3375
  __init76() {this.secondaryColor = "#ffffff"}
3347
3376
  /** Gradient paint chosen with `setPaint` (`null`: the paint colour). */
3348
3377
  __init77() {this.gradient = null}
3349
- __init78() {this.mixerLoad = _chunkLRRCMRSLcjs.EMPTY_MIXER_LOAD}
3378
+ __init78() {this.mixerLoad = _chunkEBDCRTZIcjs.EMPTY_MIXER_LOAD}
3350
3379
  __init79() {this.view = { ...DEFAULT_VIEW, pan: { ...DEFAULT_VIEW.pan } }}
3351
3380
 
3352
3381
 
@@ -3384,12 +3413,12 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3384
3413
  __init103() {this.effects = new (0, _chunkRUZQMYXHcjs.EffectsSlot)()}
3385
3414
  __init104() {this.effectsRenderer = new PaintEffectsRenderer()}
3386
3415
  __init105() {this.paperEffectNodeCache = null}
3387
- constructor(options = {}) {;_class10.prototype.__init72.call(this);_class10.prototype.__init73.call(this);_class10.prototype.__init74.call(this);_class10.prototype.__init75.call(this);_class10.prototype.__init76.call(this);_class10.prototype.__init77.call(this);_class10.prototype.__init78.call(this);_class10.prototype.__init79.call(this);_class10.prototype.__init80.call(this);_class10.prototype.__init81.call(this);_class10.prototype.__init82.call(this);_class10.prototype.__init83.call(this);_class10.prototype.__init84.call(this);_class10.prototype.__init85.call(this);_class10.prototype.__init86.call(this);_class10.prototype.__init87.call(this);_class10.prototype.__init88.call(this);_class10.prototype.__init89.call(this);_class10.prototype.__init90.call(this);_class10.prototype.__init91.call(this);_class10.prototype.__init92.call(this);_class10.prototype.__init93.call(this);_class10.prototype.__init94.call(this);_class10.prototype.__init95.call(this);_class10.prototype.__init96.call(this);_class10.prototype.__init97.call(this);_class10.prototype.__init98.call(this);_class10.prototype.__init99.call(this);_class10.prototype.__init100.call(this);_class10.prototype.__init101.call(this);_class10.prototype.__init102.call(this);_class10.prototype.__init103.call(this);_class10.prototype.__init104.call(this);_class10.prototype.__init105.call(this);_class10.prototype.__init106.call(this);_class10.prototype.__init107.call(this);_class10.prototype.__init108.call(this);
3416
+ constructor(options = {}) {;_class10.prototype.__init72.call(this);_class10.prototype.__init73.call(this);_class10.prototype.__init74.call(this);_class10.prototype.__init75.call(this);_class10.prototype.__init76.call(this);_class10.prototype.__init77.call(this);_class10.prototype.__init78.call(this);_class10.prototype.__init79.call(this);_class10.prototype.__init80.call(this);_class10.prototype.__init81.call(this);_class10.prototype.__init82.call(this);_class10.prototype.__init83.call(this);_class10.prototype.__init84.call(this);_class10.prototype.__init85.call(this);_class10.prototype.__init86.call(this);_class10.prototype.__init87.call(this);_class10.prototype.__init88.call(this);_class10.prototype.__init89.call(this);_class10.prototype.__init90.call(this);_class10.prototype.__init91.call(this);_class10.prototype.__init92.call(this);_class10.prototype.__init93.call(this);_class10.prototype.__init94.call(this);_class10.prototype.__init95.call(this);_class10.prototype.__init96.call(this);_class10.prototype.__init97.call(this);_class10.prototype.__init98.call(this);_class10.prototype.__init99.call(this);_class10.prototype.__init100.call(this);_class10.prototype.__init101.call(this);_class10.prototype.__init102.call(this);_class10.prototype.__init103.call(this);_class10.prototype.__init104.call(this);_class10.prototype.__init105.call(this);_class10.prototype.__init106.call(this);_class10.prototype.__init107.call(this);_class10.prototype.__init108.call(this);_class10.prototype.__init109.call(this);
3388
3417
  this.historyLimit = Math.max(1, _nullishCoalesce(options.historyLimit, () => ( 200)));
3389
3418
  this.doc = createPaintDocument({ width: options.width, height: options.height, dpi: options.dpi, paper: this.resolvePaper(options.paper) });
3390
- this.userBrushes = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
3391
- const start = _nullishCoalesce(this.findBrush(_nullishCoalesce(options.brushId, () => ( _chunkBXMIBMVGcjs.DEFAULT_BRUSH_ID))), () => ( this.findBrush(_chunkBXMIBMVGcjs.DEFAULT_BRUSH_ID)));
3392
- this.brush = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, start);
3419
+ this.userBrushes = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
3420
+ const start = _nullishCoalesce(this.findBrush(_nullishCoalesce(options.brushId, () => ( _chunkJGKCC5OFcjs.DEFAULT_BRUSH_ID))), () => ( this.findBrush(_chunkJGKCC5OFcjs.DEFAULT_BRUSH_ID)));
3421
+ this.brush = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, start);
3393
3422
  this.color = options.color ? parseColor(options.color) : "#1f2937";
3394
3423
  this.hand = options.hand === "left" ? "left" : "right";
3395
3424
  this.encodeImage = options.encodeImage;
@@ -3400,7 +3429,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3400
3429
  canvas: () => this.doc.canvas,
3401
3430
  paper: () => this.doc.paper,
3402
3431
  layerSurface: (id) => {
3403
- const l = _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _159 => _159.layer]);
3432
+ const l = _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _162 => _162.layer]);
3404
3433
  return isPixelLayer(l) ? l.surface : null;
3405
3434
  },
3406
3435
  updateSurfaces: (surfaces, rects) => {
@@ -3414,7 +3443,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3414
3443
  },
3415
3444
  options.wet
3416
3445
  );
3417
- this.wet.onDriverDone = () => _optionalChain([this, 'access', _160 => _160.session, 'optionalAccess', _161 => _161.completeWetEnd, 'call', _162 => _162()]);
3446
+ this.wet.onDriverDone = () => _optionalChain([this, 'access', _163 => _163.session, 'optionalAccess', _164 => _164.completeWetEnd, 'call', _165 => _165()]);
3418
3447
  }
3419
3448
  // --- State and events ----------------------------------------------------------
3420
3449
  subscribe(listener) {
@@ -3436,7 +3465,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3436
3465
  this.cached = {
3437
3466
  document: this.doc,
3438
3467
  brush: this.brush,
3439
- brushes: this.library ??= [..._chunkBXMIBMVGcjs.BUILTIN_BRUSHES, ...this.userBrushes],
3468
+ brushes: this.library ??= [..._chunkJGKCC5OFcjs.BUILTIN_BRUSHES, ...this.userBrushes],
3440
3469
  color: this.color,
3441
3470
  secondaryColor: this.secondaryColor,
3442
3471
  paint: _nullishCoalesce(this.gradient, () => ( { type: "color", color: this.color })),
@@ -3445,8 +3474,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3445
3474
  hand: this.hand,
3446
3475
  canUndo: this.undoStack.length > 0 && !this.session,
3447
3476
  canRedo: this.redoStack.length > 0 && !this.session,
3448
- undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _163 => _163.label]), () => ( null)),
3449
- redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _164 => _164.label]), () => ( null)),
3477
+ undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _166 => _166.label]), () => ( null)),
3478
+ redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _167 => _167.label]), () => ( null)),
3450
3479
  guides: this.guides,
3451
3480
  swatches: this.swatches,
3452
3481
  mixingPadVersion: this.pad.version,
@@ -3459,10 +3488,10 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3459
3488
  overlay: this.wet.overlay,
3460
3489
  instantDry: this.wet.instantDry,
3461
3490
  speed: this.wet.speed,
3462
- clock: _nullishCoalesce(_optionalChain([this, 'access', _165 => _165.wet, 'access', _166 => _166.world, 'optionalAccess', _167 => _167.clock]), () => ( 0)),
3491
+ clock: _nullishCoalesce(_optionalChain([this, 'access', _168 => _168.wet, 'access', _169 => _169.world, 'optionalAccess', _170 => _170.clock]), () => ( 0)),
3463
3492
  tilt: { ...this.wet.tilt },
3464
3493
  gpu: this.wet.gpuMode,
3465
- gpuActive: Boolean(_optionalChain([this, 'access', _168 => _168.wet, 'access', _169 => _169.world, 'optionalAccess', _170 => _170.gpuActive]))
3494
+ gpuActive: Boolean(_optionalChain([this, 'access', _171 => _171.wet, 'access', _172 => _172.world, 'optionalAccess', _173 => _173.gpuActive]))
3466
3495
  },
3467
3496
  version: this.version
3468
3497
  };
@@ -3481,6 +3510,20 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3481
3510
  return d;
3482
3511
  }
3483
3512
  // --- History -------------------------------------------------------------------
3513
+ __init106() {this.docRevision = 0}
3514
+ /**
3515
+ * Bumped on every change to the painting (a committed or amended step, undo, redo, opening a
3516
+ * document), not on wet-paint frames or view changes. `createPaintEditorDocument` uses it.
3517
+ */
3518
+ get documentRevision() {
3519
+ return this.docRevision;
3520
+ }
3521
+ /** Why the document cannot be replaced or stepped through right now, or `null`. */
3522
+ busyReason() {
3523
+ if (this.session) return "A stroke is in progress; end or cancel it first.";
3524
+ if (this.wet.busy) return "Wet paint is mid-step; wait a moment (wetIdle()) first.";
3525
+ return null;
3526
+ }
3484
3527
  requireIdle(what) {
3485
3528
  if (this.session) throw new PaintEditorError(`A stroke is in progress; end or cancel it before ${what}.`);
3486
3529
  }
@@ -3494,6 +3537,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3494
3537
  if (this.undoStack.length > this.historyLimit) this.undoStack.shift();
3495
3538
  this.redoStack = [];
3496
3539
  this.doc = next;
3540
+ this.docRevision++;
3497
3541
  this.trimWetHistory();
3498
3542
  this.emit();
3499
3543
  }
@@ -3510,6 +3554,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3510
3554
  last.after = next;
3511
3555
  this.redoStack = [];
3512
3556
  this.doc = next;
3557
+ this.docRevision++;
3513
3558
  this.emit();
3514
3559
  }
3515
3560
  /** Keeps the wet snapshots in history within the wet undo memory, dropping the oldest. */
@@ -3548,9 +3593,9 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3548
3593
  return wetIds;
3549
3594
  }
3550
3595
  /** Records a wet event (for replays) in the document being built. */
3551
- __init106() {this.pendingWetEvents = []}
3596
+ __init107() {this.pendingWetEvents = []}
3552
3597
  logWet(e) {
3553
- this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _171 => _171.wet, 'access', _172 => _172.world, 'optionalAccess', _173 => _173.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
3598
+ this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _174 => _174.wet, 'access', _175 => _175.world, 'optionalAccess', _176 => _176.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
3554
3599
  }
3555
3600
  /** The document with a paint event appended (for replays). */
3556
3601
  withPaintEvent(doc, e) {
@@ -3572,6 +3617,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3572
3617
  this.redoStack.push(e);
3573
3618
  const paper = this.doc.paper;
3574
3619
  this.doc = e.before;
3620
+ this.docRevision++;
3621
+ if (e.guides) this.restoreGuides(e.guides.before);
3575
3622
  if (e.wet) {
3576
3623
  if (paper !== this.doc.paper) this.wet.paperChanged();
3577
3624
  this.wet.restore(e.wet.lost ? null : e.wet.before);
@@ -3589,6 +3636,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3589
3636
  this.undoStack.push(e);
3590
3637
  const paper = this.doc.paper;
3591
3638
  this.doc = e.after;
3639
+ this.docRevision++;
3640
+ if (e.guides) this.restoreGuides(e.guides.after);
3592
3641
  if (e.wet) {
3593
3642
  this.wet.restore(e.wet.lost ? null : e.wet.after);
3594
3643
  if (paper !== this.doc.paper) this.wet.paperChanged();
@@ -3596,6 +3645,10 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3596
3645
  this.emit();
3597
3646
  return e.label;
3598
3647
  }
3648
+ restoreGuides(guides) {
3649
+ if (guides.tracing !== this.guides.tracing) this.tracingVersion++;
3650
+ this.guides = guides;
3651
+ }
3599
3652
  /** Labels of the undo steps, oldest first. */
3600
3653
  historyLabels() {
3601
3654
  return { undo: this.undoStack.map((e) => e.label), redo: this.redoStack.map((e) => e.label).reverse() };
@@ -3603,7 +3656,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3603
3656
  // --- Canvas and paper ----------------------------------------------------------
3604
3657
  resolvePaper(paper) {
3605
3658
  if (typeof paper === "string") {
3606
- const p = _chunkBXMIBMVGcjs.paperPreset.call(void 0, paper);
3659
+ const p = _chunkJGKCC5OFcjs.paperPreset.call(void 0, paper);
3607
3660
  if (!p) throw new PaintEditorError(`Unknown paper "${paper}". Call list_papers for the ids.`);
3608
3661
  return p;
3609
3662
  }
@@ -3616,7 +3669,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3616
3669
  width: _nullishCoalesce(options.width, () => ( this.doc.canvas.width)),
3617
3670
  height: _nullishCoalesce(options.height, () => ( this.doc.canvas.height)),
3618
3671
  dpi: _nullishCoalesce(options.dpi, () => ( this.doc.canvas.dpi)),
3619
- paper: options.paper === void 0 ? this.doc.paper : this.resolvePaper(options.paper)
3672
+ paper: options.paper === void 0 ? { ...this.doc.paper, offset: void 0 } : this.resolvePaper(options.paper)
3620
3673
  });
3621
3674
  this.extensions = {};
3622
3675
  this.guides = { ...this.guides, symmetry: { ...this.guides.symmetry, center: { x: next.canvas.width / 2, y: next.canvas.height / 2 } }, tracing: null };
@@ -3643,28 +3696,76 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3643
3696
  this.commit("Canvas size", this.withWetEvents({ ...this.doc, canvas }));
3644
3697
  return canvas;
3645
3698
  }
3699
+ /**
3700
+ * Grows the canvas by `left`, `top`, `right` and `bottom` pixels without moving anything
3701
+ * relative to anything else: the layers (with their masks, relief and stickers), the paper grain,
3702
+ * the effect paper, guides, stencils, the tracing image and the recorded strokes and events all
3703
+ * move by (left, top) in document pixels, `document.origin` moves by (−left, −top), and the view
3704
+ * pans so the picture stays still on screen.
3705
+ *
3706
+ * Wet paint dries first (the wet simulation is canvas-sized), as with `setCanvas`; one undo step
3707
+ * (undo brings back the old size, origin and guides, and the wet paint). Returns the new canvas,
3708
+ * where it sits in the previous document's pixels, and the origin.
3709
+ */
3710
+ extendCanvas(by) {
3711
+ this.requireIdle("extending the canvas");
3712
+ const side = (k) => {
3713
+ const v = _nullishCoalesce(by[k], () => ( 0));
3714
+ if (!Number.isInteger(v) || v < 0) throw new PaintEditorError(`${k} is ${JSON.stringify(by[k])}; use a whole number of pixels to add, 0 or more.`);
3715
+ return v;
3716
+ };
3717
+ const left = side("left");
3718
+ const top = side("top");
3719
+ const right = side("right");
3720
+ const bottom = side("bottom");
3721
+ if (!(left || top || right || bottom)) throw new PaintEditorError("Nothing to extend: give left, top, right or bottom (pixels to add on that side) above 0.");
3722
+ const was = this.doc.canvas;
3723
+ const width = was.width + left + right;
3724
+ const height = was.height + top + bottom;
3725
+ if (width > MAX_CANVAS_SIDE || height > MAX_CANVAS_SIDE) {
3726
+ throw new PaintEditorError(`The canvas would be ${width}\xD7${height}; the limit is ${MAX_CANVAS_SIDE} px per side. Extend by less (it is ${was.width}\xD7${was.height} now).`);
3727
+ }
3728
+ if (this.wet.world) {
3729
+ this.requireWetIdle("extending the canvas");
3730
+ this.dryLayersFirst(this.wet.wetLayerIds());
3731
+ const settings = [...this.wet.settings];
3732
+ this.wet.reset();
3733
+ for (const [id, s] of settings) this.wet.settings.set(id, s.flow.center ? { ...s, flow: { ...s.flow, center: { x: s.flow.center.x + left, y: s.flow.center.y + top } } } : s);
3734
+ }
3735
+ const next = { ...shiftDocument(this.withWetEvents(this.doc), left, top), canvas: { ...was, width, height } };
3736
+ const m = viewMatrix(this.view, was, { width: 0, height: 0 });
3737
+ const dx = (right - left) / 2;
3738
+ const dy = (bottom - top) / 2;
3739
+ this.view = { ...this.view, pan: { x: this.view.pan.x + m[0] * dx + m[1] * dy, y: this.view.pan.y + m[2] * dx + m[3] * dy } };
3740
+ const guidesBefore = this.guides;
3741
+ if (left || top) this.restoreGuides(shiftGuides(this.guides, left, top));
3742
+ this.commit("Extend canvas", next);
3743
+ if (this.guides !== guidesBefore) this.undoStack[this.undoStack.length - 1].guides = { before: guidesBefore, after: this.guides };
3744
+ const origin = { ..._nullishCoalesce(next.origin, () => ( { x: 0, y: 0 })) };
3745
+ return { canvas: { ...next.canvas }, rect: { x: 0 - left, y: 0 - top, width, height }, origin };
3746
+ }
3646
3747
  /** Changes the paper: a library preset (`preset`), and / or any of its settings (one undo step). */
3647
3748
  setPaper(update) {
3648
3749
  this.requireIdle("changing the paper");
3649
3750
  let base = this.doc.paper;
3650
3751
  if (update.preset !== void 0 && update.preset !== this.doc.paper.preset) {
3651
- const p = _chunkBXMIBMVGcjs.paperPreset.call(void 0, update.preset);
3752
+ const p = _chunkJGKCC5OFcjs.paperPreset.call(void 0, update.preset);
3652
3753
  if (!p) throw new PaintEditorError(`Unknown paper "${update.preset}". Call list_papers for the ids.`);
3653
3754
  base = p;
3654
3755
  }
3655
3756
  const { preset: _p, ...rest } = update;
3656
3757
  if (rest.color !== void 0) parseColor(rest.color, "paper color");
3657
- const paper = _chunkBXMIBMVGcjs.normalizePaper.call(void 0, { ...rest, preset: base.preset }, base);
3758
+ const paper = _chunkJGKCC5OFcjs.normalizePaper.call(void 0, { ...rest, preset: base.preset, offset: _nullishCoalesce(rest.offset, () => ( this.doc.paper.offset)) }, base);
3658
3759
  const changedKeys = Object.keys(rest).filter((k) => k !== "name");
3659
3760
  if (changedKeys.length && update.preset === void 0) paper.preset = base.preset;
3660
3761
  if (this.wet.world) this.beginWetOp();
3661
3762
  this.commit("Paper", { ...this.doc, paper });
3662
3763
  this.wet.paperChanged();
3663
- return _chunkBXMIBMVGcjs.clonePaper.call(void 0, paper);
3764
+ return _chunkJGKCC5OFcjs.clonePaper.call(void 0, paper);
3664
3765
  }
3665
3766
  // --- Layers --------------------------------------------------------------------
3666
3767
  getLayer(id) {
3667
- return _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _174 => _174.layer]);
3768
+ return _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _177 => _177.layer]);
3668
3769
  }
3669
3770
  /** The active pixel layer (or `undefined`). */
3670
3771
  getActiveLayer() {
@@ -3683,7 +3784,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3683
3784
  walk(this.doc.layers, null, 0);
3684
3785
  return out;
3685
3786
  }
3686
- describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _175 => _175.parent, 'optionalAccess', _176 => _176.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _177 => _177.path, 'access', _178 => _178.length]), () => ( 0))) {
3787
+ describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _178 => _178.parent, 'optionalAccess', _179 => _179.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _180 => _180.path, 'access', _181 => _181.length]), () => ( 0))) {
3687
3788
  let bounds = null;
3688
3789
  if (l.type === "pixel") {
3689
3790
  const b = _chunkCWM3CUUXcjs.contentBounds.call(void 0, l.surface);
@@ -3730,7 +3831,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3730
3831
  this.requireIdle("adding a layer");
3731
3832
  const count = _chunkHGTDMKNEcjs.flattenLayers.call(void 0, this.doc.layers).length;
3732
3833
  const type = _nullishCoalesce(options.type, () => ( "pixel"));
3733
- const name = _optionalChain([options, 'access', _179 => _179.name, 'optionalAccess', _180 => _180.trim, 'call', _181 => _181()]) || (type === "group" ? `Group ${count + 1}` : `Layer ${count + 1}`);
3834
+ const name = _optionalChain([options, 'access', _182 => _182.name, 'optionalAccess', _183 => _183.trim, 'call', _184 => _184()]) || (type === "group" ? `Group ${count + 1}` : `Layer ${count + 1}`);
3734
3835
  const layer = type === "group" ? { type: "group", id: newPaintLayerId(), name, visible: true, opacity: 1, blend: "pass-through", children: [] } : createPaintLayer(name);
3735
3836
  let parentId = null;
3736
3837
  let index;
@@ -3742,7 +3843,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3742
3843
  } else if (above) {
3743
3844
  const loc = _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, above);
3744
3845
  if (!loc) throw new PaintEditorError(`Unknown layer "${above}". Call list_layers for the ids.`);
3745
- parentId = _nullishCoalesce(_optionalChain([loc, 'access', _182 => _182.parent, 'optionalAccess', _183 => _183.id]), () => ( null));
3846
+ parentId = _nullishCoalesce(_optionalChain([loc, 'access', _185 => _185.parent, 'optionalAccess', _186 => _186.id]), () => ( null));
3746
3847
  index = loc.index + 1;
3747
3848
  }
3748
3849
  const layers = _chunkHGTDMKNEcjs.insertLayer.call(void 0, this.doc.layers, layer, parentId, index);
@@ -3782,7 +3883,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3782
3883
  }
3783
3884
  const layers = _chunkHGTDMKNEcjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
3784
3885
  let active = this.doc.activeLayerId;
3785
- if (active && !_chunkHGTDMKNEcjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _184 => _184.filter, 'call', _185 => _185((x) => x.type === "pixel"), 'access', _186 => _186.pop, 'call', _187 => _187(), 'optionalAccess', _188 => _188.id]), () => ( null));
3886
+ if (active && !_chunkHGTDMKNEcjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _187 => _187.filter, 'call', _188 => _188((x) => x.type === "pixel"), 'access', _189 => _189.pop, 'call', _190 => _190(), 'optionalAccess', _191 => _191.id]), () => ( null));
3786
3887
  this.commit("Remove layer", { ...this.doc, layers, activeLayerId: active, ...this.thickWithout(_chunkHGTDMKNEcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.stickersWithout(_chunkHGTDMKNEcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)) });
3787
3888
  return { removed: id, activeLayerId: active };
3788
3889
  }
@@ -3803,7 +3904,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3803
3904
  return l.type === "group" ? { ...l, id: id2, children: l.children.map(copy) } : { ...l, id: id2 };
3804
3905
  };
3805
3906
  const dup = { ...copy(loc.layer), name: `${loc.layer.name} copy` };
3806
- const layers = _chunkHGTDMKNEcjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _189 => _189.parent, 'optionalAccess', _190 => _190.id]), () => ( null)), loc.index + 1);
3907
+ const layers = _chunkHGTDMKNEcjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _192 => _192.parent, 'optionalAccess', _193 => _193.id]), () => ( null)), loc.index + 1);
3807
3908
  this.commit("Duplicate layer", this.withWetEvents({ ...this.doc, layers, activeLayerId: dup.id, ...this.doc.thick ? { thick } : {}, ...this.doc.stickers ? { stickers } : {} }));
3808
3909
  return this.describeLayer(dup);
3809
3910
  }
@@ -3812,7 +3913,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3812
3913
  this.requireIdle("moving a layer");
3813
3914
  const loc = _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id);
3814
3915
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
3815
- const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _191 => _191.parent, 'optionalAccess', _192 => _192.id]), () => ( null)) : parentId;
3916
+ const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _194 => _194.parent, 'optionalAccess', _195 => _195.id]), () => ( null)) : parentId;
3816
3917
  if (target) {
3817
3918
  const g = this.requireLayer(target);
3818
3919
  if (g.type !== "group") throw new PaintEditorError(`Layer "${g.name}" is not a group; pass a group id as parentId.`);
@@ -3831,7 +3932,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3831
3932
  const pre = _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id);
3832
3933
  if (pre) {
3833
3934
  const sib = pre.parent ? pre.parent.children : this.doc.layers;
3834
- this.dryLayersFirst([id, _optionalChain([sib, 'access', _193 => _193[pre.index - 1], 'optionalAccess', _194 => _194.id])].filter((x) => Boolean(x)));
3935
+ this.dryLayersFirst([id, _optionalChain([sib, 'access', _196 => _196[pre.index - 1], 'optionalAccess', _197 => _197.id])].filter((x) => Boolean(x)));
3835
3936
  }
3836
3937
  const loc = _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id);
3837
3938
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
@@ -3872,7 +3973,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3872
3973
  fillLayer(options = {}) {
3873
3974
  this.requireIdle("filling");
3874
3975
  const fillTarget = this.paintTarget(options.layerId, "fill");
3875
- if (_optionalChain([this, 'access', _195 => _195.doc, 'access', _196 => _196.stickers, 'optionalAccess', _197 => _197[fillTarget.id], 'optionalAccess', _198 => _198.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
3976
+ if (_optionalChain([this, 'access', _198 => _198.doc, 'access', _199 => _199.stickers, 'optionalAccess', _200 => _200[fillTarget.id], 'optionalAccess', _201 => _201.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
3876
3977
  this.dryLayersFirst([_nullishCoalesce(_nullishCoalesce(options.layerId, () => ( this.doc.activeLayerId)), () => ( ""))]);
3877
3978
  const l = this.paintTarget(options.layerId, "fill");
3878
3979
  const color = options.color === void 0 ? this.color : parseColor(options.color);
@@ -3885,13 +3986,13 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3885
3986
  if (!_chunkCWM3CUUXcjs.isBlendMode.call(void 0, blend)) throw new PaintEditorError(`Unknown blend mode "${blend}".`);
3886
3987
  const { width, height } = this.doc.canvas;
3887
3988
  const rect = { x: 0, y: 0, width, height };
3888
- const coverage = new (0, _chunkLRRCMRSLcjs.CoverageMap)();
3989
+ const coverage = new (0, _chunkEBDCRTZIcjs.CoverageMap)();
3889
3990
  const depth = grainAmount * this.doc.paper.depth;
3890
3991
  const grain = depth > 0 ? paperGrain(this.doc.paper) : null;
3891
3992
  for (const { tx, ty } of _chunkCWM3CUUXcjs.tilesInRect.call(void 0, rect)) {
3892
3993
  const r = { x: tx * _chunkCWM3CUUXcjs.TILE, y: ty * _chunkCWM3CUUXcjs.TILE, width: Math.min(_chunkCWM3CUUXcjs.TILE, width - tx * _chunkCWM3CUUXcjs.TILE), height: Math.min(_chunkCWM3CUUXcjs.TILE, height - ty * _chunkCWM3CUUXcjs.TILE) };
3893
3994
  const vals = new Float32Array(r.width * r.height);
3894
- for (let y = 0, k = 0; y < r.height; y++) for (let x = 0; x < r.width; x++, k++) vals[k] = grain ? _chunkLRRCMRSLcjs.grainCatch.call(void 0, grain.at(r.x + x + 0.5, r.y + y + 0.5), depth, pressure) : 1;
3995
+ for (let y = 0, k = 0; y < r.height; y++) for (let x = 0; x < r.width; x++, k++) vals[k] = grain ? _chunkEBDCRTZIcjs.grainCatch.call(void 0, grain.at(r.x + x + 0.5, r.y + y + 0.5), depth, pressure) : 1;
3895
3996
  coverage.accumulate(r, vals, 1);
3896
3997
  }
3897
3998
  const apply = {
@@ -3913,8 +4014,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3913
4014
  const tiles = new Map(base.tiles);
3914
4015
  for (const { tx, ty } of _chunkCWM3CUUXcjs.tilesInRect.call(void 0, { x: rect.x - l.offset.x, y: rect.y - l.offset.y, width: rect.width, height: rect.height })) {
3915
4016
  const key = _chunkCWM3CUUXcjs.tileKey.call(void 0, tx, ty);
3916
- const src = _nullishCoalesce(_optionalChain([base, 'access', _199 => _199.tiles, 'access', _200 => _200.get, 'call', _201 => _201(key), 'optionalAccess', _202 => _202.data]), () => ( new Uint8ClampedArray(_chunkCWM3CUUXcjs.TILE * _chunkCWM3CUUXcjs.TILE * 4)));
3917
- const tile = _chunkCWM3CUUXcjs.finishTile.call(void 0, _chunkLRRCMRSLcjs.applyStrokeToTile.call(void 0, coverage, src, 4, tx, ty, apply), 4, 0);
4017
+ const src = _nullishCoalesce(_optionalChain([base, 'access', _202 => _202.tiles, 'access', _203 => _203.get, 'call', _204 => _204(key), 'optionalAccess', _205 => _205.data]), () => ( new Uint8ClampedArray(_chunkCWM3CUUXcjs.TILE * _chunkCWM3CUUXcjs.TILE * 4)));
4018
+ const tile = _chunkCWM3CUUXcjs.finishTile.call(void 0, _chunkEBDCRTZIcjs.applyStrokeToTile.call(void 0, coverage, src, 4, tx, ty, apply), 4, 0);
3918
4019
  if (tile) tiles.set(key, tile);
3919
4020
  else tiles.delete(key);
3920
4021
  }
@@ -3946,7 +4047,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3946
4047
  }
3947
4048
  /** The effect a layer is drawn from, or `undefined` for other layers. */
3948
4049
  getEffectLayer(layerId) {
3949
- return _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _203 => _203.doc, 'access', _204 => _204.effectLayers, 'optionalAccess', _205 => _205[layerId]]) : void 0;
4050
+ return _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _206 => _206.doc, 'access', _207 => _207.effectLayers, 'optionalAccess', _208 => _208[layerId]]) : void 0;
3950
4051
  }
3951
4052
  /** The effect paper (without its pixels), or `null`. */
3952
4053
  getPaperEffect() {
@@ -3983,7 +4084,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3983
4084
  /** A pixel layer that takes effect pixels: unlocked, visible, no sticker layer, no wet paint. */
3984
4085
  effectTarget(layerId, what) {
3985
4086
  const l = this.paintTarget(layerId, what);
3986
- if (_optionalChain([this, 'access', _206 => _206.doc, 'access', _207 => _207.stickers, 'optionalAccess', _208 => _208[l.id], 'optionalAccess', _209 => _209.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
4087
+ if (_optionalChain([this, 'access', _209 => _209.doc, 'access', _210 => _210.stickers, 'optionalAccess', _211 => _211[l.id], 'optionalAccess', _212 => _212.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
3987
4088
  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.`);
3988
4089
  return l;
3989
4090
  }
@@ -4022,8 +4123,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4022
4123
  const was = this.doc.paperEffect;
4023
4124
  const paperEffect = {
4024
4125
  ...this.sourceOf(d, values, options.time),
4025
- opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _210 => _210.opacity]))), () => ( 1)),
4026
- blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _211 => _211.blend]))), () => ( "multiply")),
4126
+ opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _213 => _213.opacity]))), () => ( 1)),
4127
+ blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _214 => _214.blend]))), () => ( "multiply")),
4027
4128
  image: { width: pixels.width, height: pixels.height, data: new Uint8ClampedArray(pixels.data) },
4028
4129
  version: nextPaperEffectVersion()
4029
4130
  };
@@ -4076,8 +4177,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4076
4177
  const above = _nullishCoalesce(options.aboveId, () => ( this.doc.activeLayerId));
4077
4178
  const loc = above ? _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, above) : null;
4078
4179
  if (options.aboveId !== void 0 && !loc) throw new PaintEditorError(`Layer "${options.aboveId}" was removed while the effect rendered.`);
4079
- const layer = { ...createPaintLayer(_optionalChain([options, 'access', _212 => _212.name, 'optionalAccess', _213 => _213.trim, 'call', _214 => _214()]) || d.name), surface: _chunkCWM3CUUXcjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
4080
- const layers = _chunkHGTDMKNEcjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _215 => _215.parent, 'optionalAccess', _216 => _216.id]), () => ( null)), loc ? loc.index + 1 : void 0);
4180
+ const layer = { ...createPaintLayer(_optionalChain([options, 'access', _215 => _215.name, 'optionalAccess', _216 => _216.trim, 'call', _217 => _217()]) || d.name), surface: _chunkCWM3CUUXcjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
4181
+ const layers = _chunkHGTDMKNEcjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _218 => _218.parent, 'optionalAccess', _219 => _219.id]), () => ( null)), loc ? loc.index + 1 : void 0);
4081
4182
  const source = this.sourceOf(d, values, options.time);
4082
4183
  this.commit("Add effect layer", { ...this.doc, layers, activeLayerId: layer.id, effectLayers: { ..._nullishCoalesce(this.doc.effectLayers, () => ( {})), [layer.id]: source } });
4083
4184
  return { layer: this.describeLayer(layer), source };
@@ -4153,14 +4254,14 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4153
4254
  const before = _chunkCWM3CUUXcjs.readRegion.call(void 0, l.surface, rect);
4154
4255
  const inputs = { source: { width: rect.width, height: rect.height, data: before } };
4155
4256
  const heightInput = d.inputs.find((i) => i.kind === "image" && /^(height|depth|relief)$/i.test(i.name));
4156
- const relief = _optionalChain([this, 'access', _217 => _217.doc, 'access', _218 => _218.thick, 'optionalAccess', _219 => _219[l.id]]);
4257
+ const relief = _optionalChain([this, 'access', _220 => _220.doc, 'access', _221 => _221.thick, 'optionalAccess', _222 => _222[l.id]]);
4157
4258
  if (heightInput && relief) {
4158
4259
  const h = _chunkCWM3CUUXcjs.readRegion.call(void 0, relief.height, rect);
4159
4260
  const rgba = new Uint8ClampedArray(rect.width * rect.height * 4);
4160
4261
  for (let i = 0; i < h.length; i++) rgba.set([h[i], h[i], h[i], 255], i * 4);
4161
4262
  inputs[heightInput.name] = { width: rect.width, height: rect.height, data: rgba };
4162
4263
  }
4163
- const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _220 => _220.inputs, 'access', _221 => _221.find, 'call', _222 => _222((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _223 => _223.name])), 'optionalAccess', _224 => _224.name]), () => ( "source"));
4264
+ const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _223 => _223.inputs, 'access', _224 => _224.find, 'call', _225 => _225((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _226 => _226.name])), 'optionalAccess', _227 => _227.name]), () => ( "source"));
4164
4265
  if (sourceInput !== "source") {
4165
4266
  inputs[sourceInput] = inputs.source;
4166
4267
  delete inputs.source;
@@ -4173,12 +4274,12 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4173
4274
  }
4174
4275
  // --- Brushes -------------------------------------------------------------------
4175
4276
  findBrush(id) {
4176
- return _nullishCoalesce(_chunkBXMIBMVGcjs.BUILTIN_BRUSHES.find((b) => b.id === id), () => ( this.userBrushes.find((b) => b.id === id)));
4277
+ return _nullishCoalesce(_chunkJGKCC5OFcjs.BUILTIN_BRUSHES.find((b) => b.id === id), () => ( this.userBrushes.find((b) => b.id === id)));
4177
4278
  }
4178
4279
  /** A library brush by id (`undefined` when unknown). */
4179
4280
  getBrush(id) {
4180
4281
  const b = this.findBrush(id);
4181
- return b ? _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, b, b) : void 0;
4282
+ return b ? _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, b, b) : void 0;
4182
4283
  }
4183
4284
  requireBrush(id) {
4184
4285
  const b = this.findBrush(id);
@@ -4193,7 +4294,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4193
4294
  const { id, ...changes } = update;
4194
4295
  const base = id !== void 0 ? this.requireBrush(id) : this.brush;
4195
4296
  if (changes.paint !== void 0 && changes.paint !== null) this.readStrokePaint(changes.paint);
4196
- const next = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
4297
+ const next = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
4197
4298
  if (base.builtin && !Object.keys(changes).length) next.builtin = true;
4198
4299
  else delete next.builtin;
4199
4300
  this.brush = next;
@@ -4202,10 +4303,10 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4202
4303
  }
4203
4304
  /** Saves the active brush (or `brush`) into the user library under `id` / `name`. */
4204
4305
  saveBrush(options) {
4205
- if (!_chunkBXMIBMVGcjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
4206
- if (_chunkBXMIBMVGcjs.BUILTIN_BRUSHES.some((b) => b.id === options.id)) throw new PaintEditorError(`"${options.id}" is a built-in brush; save under another id.`);
4207
- const source = options.brush ? _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, options.brush, this.brush) : this.brush;
4208
- const saved = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { ...source, id: options.id, name: _nullishCoalesce(options.name, () => ( source.name)) });
4306
+ if (!_chunkJGKCC5OFcjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
4307
+ if (_chunkJGKCC5OFcjs.BUILTIN_BRUSHES.some((b) => b.id === options.id)) throw new PaintEditorError(`"${options.id}" is a built-in brush; save under another id.`);
4308
+ const source = options.brush ? _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, options.brush, this.brush) : this.brush;
4309
+ const saved = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { ...source, id: options.id, name: _nullishCoalesce(options.name, () => ( source.name)) });
4209
4310
  delete saved.builtin;
4210
4311
  const i = this.userBrushes.findIndex((b) => b.id === options.id);
4211
4312
  if (i >= 0) this.userBrushes[i] = saved;
@@ -4215,7 +4316,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4215
4316
  return saved;
4216
4317
  }
4217
4318
  removeBrush(id) {
4218
- if (_chunkBXMIBMVGcjs.BUILTIN_BRUSHES.some((b) => b.id === id)) throw new PaintEditorError(`"${id}" is a built-in brush and cannot be removed.`);
4319
+ if (_chunkJGKCC5OFcjs.BUILTIN_BRUSHES.some((b) => b.id === id)) throw new PaintEditorError(`"${id}" is a built-in brush and cannot be removed.`);
4219
4320
  const i = this.userBrushes.findIndex((b) => b.id === id);
4220
4321
  if (i < 0) throw new PaintEditorError(`Unknown brush "${id}". Call list_brushes for the ids.`);
4221
4322
  this.userBrushes.splice(i, 1);
@@ -4224,12 +4325,12 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4224
4325
  }
4225
4326
  /** The user's saved brushes. */
4226
4327
  getUserBrushes() {
4227
- return this.userBrushes.map((b) => _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, b, b));
4328
+ return this.userBrushes.map((b) => _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, b, b));
4228
4329
  }
4229
4330
  /** A brush library file of the given brushes (default: the user's brushes). */
4230
4331
  exportBrushes(ids) {
4231
4332
  const list = ids ? ids.map((id) => this.requireBrush(id)) : this.userBrushes;
4232
- return { format: "pixerate-brushes", version: 1, brushes: list.map(_chunkBXMIBMVGcjs.brushToJSON) };
4333
+ return { format: "pixerate-brushes", version: 1, brushes: list.map(_chunkJGKCC5OFcjs.brushToJSON) };
4233
4334
  }
4234
4335
  /**
4235
4336
  * Adds the brushes of a library file to the user library. A brush whose id is taken is skipped
@@ -4239,14 +4340,14 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4239
4340
  const problems = [];
4240
4341
  let list;
4241
4342
  try {
4242
- list = _chunkBXMIBMVGcjs.parseBrushLibrary.call(void 0, file, problems);
4343
+ list = _chunkJGKCC5OFcjs.parseBrushLibrary.call(void 0, file, problems);
4243
4344
  } catch (e) {
4244
4345
  throw new PaintEditorError(e.message);
4245
4346
  }
4246
4347
  const added = [];
4247
4348
  const skipped = [];
4248
4349
  for (const b of list) {
4249
- if (_chunkBXMIBMVGcjs.BUILTIN_BRUSHES.some((x) => x.id === b.id)) {
4350
+ if (_chunkJGKCC5OFcjs.BUILTIN_BRUSHES.some((x) => x.id === b.id)) {
4250
4351
  skipped.push(b.id);
4251
4352
  problems.push(`"${b.id}" is a built-in brush id; rename it to import it.`);
4252
4353
  continue;
@@ -4288,9 +4389,9 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4288
4389
  setPaint(paint) {
4289
4390
  let p;
4290
4391
  try {
4291
- p = _chunkLRRCMRSLcjs.parsePaintSource.call(void 0, paint);
4392
+ p = _chunkEBDCRTZIcjs.parsePaintSource.call(void 0, paint);
4292
4393
  } catch (e) {
4293
- if (e instanceof _chunkLRRCMRSLcjs.PaintSourceError) throw new PaintEditorError(e.message);
4394
+ if (e instanceof _chunkEBDCRTZIcjs.PaintSourceError) throw new PaintEditorError(e.message);
4294
4395
  throw e;
4295
4396
  }
4296
4397
  if (p.type === "color") {
@@ -4307,19 +4408,19 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4307
4408
  * brush's gradient, else the editor's gradient paint. Erasers, blenders and smudges take none.
4308
4409
  */
4309
4410
  strokeGradient(init, brush, color) {
4310
- if (!_chunkBXMIBMVGcjs.brushTakesPaint.call(void 0, brush)) return null;
4411
+ if (!_chunkJGKCC5OFcjs.brushTakesPaint.call(void 0, brush)) return null;
4311
4412
  let g = null;
4312
4413
  if (init.paint !== void 0) {
4313
4414
  const p = this.readStrokePaint(init.paint);
4314
4415
  g = p.type === "gradient" ? p : null;
4315
4416
  } else g = _nullishCoalesce(brush.paint, () => ( (init.color === void 0 ? this.gradient : null)));
4316
- return g ? _chunkLRRCMRSLcjs.resolvePaintGradient.call(void 0, g, { paint: color, secondary: this.secondaryColor }) : null;
4417
+ return g ? _chunkEBDCRTZIcjs.resolvePaintGradient.call(void 0, g, { paint: color, secondary: this.secondaryColor }) : null;
4317
4418
  }
4318
4419
  readStrokePaint(raw) {
4319
4420
  try {
4320
- return _chunkLRRCMRSLcjs.parsePaintSource.call(void 0, raw);
4421
+ return _chunkEBDCRTZIcjs.parsePaintSource.call(void 0, raw);
4321
4422
  } catch (e) {
4322
- if (e instanceof _chunkLRRCMRSLcjs.PaintSourceError) throw new PaintEditorError(e.message);
4423
+ if (e instanceof _chunkEBDCRTZIcjs.PaintSourceError) throw new PaintEditorError(e.message);
4323
4424
  throw e;
4324
4425
  }
4325
4426
  }
@@ -4353,14 +4454,14 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4353
4454
  // --- Mixer Brush ---------------------------------------------------------------
4354
4455
  /** Fills the Mixer Brush reservoir with a colour (default the editor colour). */
4355
4456
  loadMixerBrush(color) {
4356
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, color === void 0 ? this.color : parseColor(color));
4357
- this.mixerLoad = _chunkLRRCMRSLcjs.loadMixer.call(void 0, this.mixerLoad, [r / 255, g / 255, b / 255]);
4457
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, color === void 0 ? this.color : parseColor(color));
4458
+ this.mixerLoad = _chunkEBDCRTZIcjs.loadMixer.call(void 0, this.mixerLoad, [r / 255, g / 255, b / 255]);
4358
4459
  this.emit([]);
4359
4460
  return this.mixerLoad;
4360
4461
  }
4361
4462
  /** Empties the pickup well (and with `emptyReservoir` the loaded paint too). */
4362
4463
  cleanMixerBrush(emptyReservoir = false) {
4363
- this.mixerLoad = emptyReservoir ? _chunkLRRCMRSLcjs.EMPTY_MIXER_LOAD : _chunkLRRCMRSLcjs.cleanMixer.call(void 0, this.mixerLoad);
4464
+ this.mixerLoad = emptyReservoir ? _chunkEBDCRTZIcjs.EMPTY_MIXER_LOAD : _chunkEBDCRTZIcjs.cleanMixer.call(void 0, this.mixerLoad);
4364
4465
  this.emit([]);
4365
4466
  return this.mixerLoad;
4366
4467
  }
@@ -4383,7 +4484,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4383
4484
  // --- Strokes -------------------------------------------------------------------
4384
4485
  strokeBrush(init) {
4385
4486
  let brush = init.brushId !== void 0 ? this.requireBrush(init.brushId) : this.brush;
4386
- if (init.brush) brush = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
4487
+ if (init.brush) brush = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
4387
4488
  return brush;
4388
4489
  }
4389
4490
  /**
@@ -4416,14 +4517,14 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4416
4517
  return l;
4417
4518
  })();
4418
4519
  const brush = this.strokeBrush(init);
4419
- const stickerLayer = Boolean(_optionalChain([doc, 'access', _225 => _225.stickers, 'optionalAccess', _226 => _226[layer.id], 'optionalAccess', _227 => _227.length]));
4520
+ const stickerLayer = Boolean(_optionalChain([doc, 'access', _228 => _228.stickers, 'optionalAccess', _229 => _229[layer.id], 'optionalAccess', _230 => _230.length]));
4420
4521
  if (brush.engine === "sticker") {
4421
4522
  if (!stickerLayer && _chunkCWM3CUUXcjs.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.`);
4422
4523
  } else if (stickerLayer) {
4423
4524
  throw new PaintEditorError(`Layer "${layer.name}" is a sticker layer (its pixels are drawn from its stickers); paint on another layer (add_layer).`);
4424
4525
  }
4425
4526
  let wet;
4426
- if (_chunkBXMIBMVGcjs.isWetBrush.call(void 0, brush)) {
4527
+ if (_chunkJGKCC5OFcjs.isWetBrush.call(void 0, brush)) {
4427
4528
  this.requireWetIdle("painting");
4428
4529
  if (layer.offset.x || layer.offset.y) {
4429
4530
  const moved = { ...layer, surface: _chunkCWM3CUUXcjs.translateSurface.call(void 0, layer.surface, layer.offset.x, layer.offset.y), offset: { x: 0, y: 0 } };
@@ -4438,10 +4539,10 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4438
4539
  const world = this.wet.ensureLane(layer.id, brush.wet.medium);
4439
4540
  const id = layer.id;
4440
4541
  const wetColor = init.color === void 0 ? this.color : parseColor(init.color);
4441
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, wetColor);
4542
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, wetColor);
4442
4543
  const wetGradient = this.strokeGradient(init, brush, wetColor);
4443
4544
  const load = _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [r / 255, g / 255, b / 255])));
4444
- const seedW = _nullishCoalesce(init.seed, () => ( _chunkLRRCMRSLcjs.mix32.call(void 0, this.seedCounter * 2654435761 >>> 0) & 2147483647));
4545
+ const seedW = _nullishCoalesce(init.seed, () => ( _chunkEBDCRTZIcjs.mix32.call(void 0, this.seedCounter * 2654435761 >>> 0) & 2147483647));
4445
4546
  const copiesW = (_nullishCoalesce(init.copies, () => ( this.strokeCopies()))).filter((m) => m.some((v, i) => v !== IDENTITY_AFFINE[i]));
4446
4547
  const driver = new WetStrokeDriver({
4447
4548
  world,
@@ -4451,7 +4552,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4451
4552
  load,
4452
4553
  grain: paperGrain(doc.paper),
4453
4554
  paperDepth: doc.paper.depth,
4454
- paperColor: _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, doc.paper.color),
4555
+ paperColor: _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, doc.paper.color),
4455
4556
  seed: seedW,
4456
4557
  copies: [IDENTITY_AFFINE, ...copiesW].map(affineCopy),
4457
4558
  mask: init.maskStencils ? this.stencilSelection(init.maskStencils) : init.stencils !== false ? this.stencilSelection() : null,
@@ -4466,7 +4567,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4466
4567
  }
4467
4568
  let color = init.color === void 0 ? this.color : parseColor(init.color);
4468
4569
  const tracing = this.guides.tracing;
4469
- if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _228 => _228.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
4570
+ if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _231 => _231.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
4470
4571
  const perspective = this.guides.perspective;
4471
4572
  const snapper = init.snapToPerspective && perspective.enabled && perspective.snap ? new PerspectiveSnapper(perspective) : null;
4472
4573
  const useStencils = init.stencils !== false;
@@ -4474,7 +4575,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4474
4575
  const selection = init.maskStencils ? this.stencilSelection(init.maskStencils) : useStencils ? this.stencilSelection() : null;
4475
4576
  const inputFilter = snapper || stencilSnapper ? (p) => stencilSnapper ? stencilSnapper.snap(snapper ? snapper.snap(p) : p) : snapper.snap(p) : void 0;
4476
4577
  const rgba = rgbaOf(color);
4477
- const seed = _nullishCoalesce(init.seed, () => ( _chunkLRRCMRSLcjs.mix32.call(void 0, this.seedCounter++ * 2654435761 >>> 0) & 2147483647));
4578
+ const seed = _nullishCoalesce(init.seed, () => ( _chunkEBDCRTZIcjs.mix32.call(void 0, this.seedCounter++ * 2654435761 >>> 0) & 2147483647));
4478
4579
  const copies = (_nullishCoalesce(init.copies, () => ( this.strokeCopies()))).filter((m) => m.some((v, i) => v !== IDENTITY_AFFINE[i]));
4479
4580
  const session = new PaintStrokeSession(host, {
4480
4581
  layerId: layer.id,
@@ -4495,7 +4596,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4495
4596
  mixerLoad: _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [rgba[0] / 255, rgba[1] / 255, rgba[2] / 255]))),
4496
4597
  secondary: rgbaOf(this.secondaryColor),
4497
4598
  wet,
4498
- thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _229 => _229.thick, 'optionalAccess', _230 => _230[layer.id]]), () => ( emptyThickChannels())) } : void 0,
4599
+ thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _232 => _232.thick, 'optionalAccess', _233 => _233[layer.id]]), () => ( emptyThickChannels())) } : void 0,
4499
4600
  sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc) } : void 0,
4500
4601
  paint: this.strokeGradient(init, brush, color)
4501
4602
  });
@@ -4508,7 +4609,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4508
4609
  const stroke = {
4509
4610
  id: `s${this.strokeCounter++}`,
4510
4611
  layerId: session.layerId,
4511
- brush: _chunkBXMIBMVGcjs.brushToJSON.call(void 0, init.brush),
4612
+ brush: _chunkJGKCC5OFcjs.brushToJSON.call(void 0, init.brush),
4512
4613
  color: init.colorHex,
4513
4614
  points: session.points.map((p) => ({ ...p })),
4514
4615
  seed: init.seed
@@ -4532,12 +4633,12 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4532
4633
  const before = this.doc;
4533
4634
  const host = {
4534
4635
  update: (layerId, surface, rects) => {
4535
- if (_optionalChain([this, 'access', _231 => _231.session, 'optionalAccess', _232 => _232.init, 'access', _233 => _233.wet])) {
4636
+ if (_optionalChain([this, 'access', _234 => _234.session, 'optionalAccess', _235 => _235.init, 'access', _236 => _236.wet])) {
4536
4637
  this.wet.syncDisplays();
4537
4638
  return;
4538
4639
  }
4539
4640
  this.live = { layerId, surface };
4540
- const ch = _optionalChain([this, 'access', _234 => _234.session, 'optionalAccess', _235 => _235.thickChannels, 'call', _236 => _236()]);
4641
+ const ch = _optionalChain([this, 'access', _237 => _237.session, 'optionalAccess', _238 => _238.thickChannels, 'call', _239 => _239()]);
4541
4642
  this.liveThick = ch ? { layerId, channels: ch } : null;
4542
4643
  this.emit(rects);
4543
4644
  },
@@ -4549,7 +4650,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4549
4650
  const wetStroke = Boolean(s.init.wet);
4550
4651
  if (wetStroke) this.wet.driver = null;
4551
4652
  const brush = s.init.brush;
4552
- if (!cancelled && _optionalChain([s, 'access', _237 => _237.result, 'optionalAccess', _238 => _238.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
4653
+ if (!cancelled && _optionalChain([s, 'access', _240 => _240.result, 'optionalAccess', _241 => _241.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
4553
4654
  if (cancelled || !surface) {
4554
4655
  if (this.wetOp) {
4555
4656
  const snap = this.wetOp.before;
@@ -4574,7 +4675,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4574
4675
  const ch = s.thickChannels();
4575
4676
  const thick = ch ? { ..._nullishCoalesce(this.doc.thick, () => ( {})), [l.id]: ch } : this.doc.thick;
4576
4677
  const sprayed = s.stickers();
4577
- const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _239 => _239.doc, 'access', _240 => _240.stickers, 'optionalAccess', _241 => _241[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
4678
+ const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _242 => _242.doc, 'access', _243 => _243.stickers, 'optionalAccess', _244 => _244[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
4578
4679
  this.commit(`${brush.name} stroke`, this.withWetEvents({ ...this.doc, layers: _chunkHGTDMKNEcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })), strokes: [...this.doc.strokes, stroke], ...thick ? { thick } : {}, ...stickers ? { stickers } : {} }), wetStroke ? before : this.doc);
4579
4680
  }
4580
4681
  };
@@ -4612,7 +4713,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4612
4713
  layers: _chunkHGTDMKNEcjs.mapLayer.call(void 0, out.layers, l.id, () => ({ ...l, surface, offset })),
4613
4714
  strokes: [...out.strokes, stroke],
4614
4715
  ...ch ? { thick: { ..._nullishCoalesce(out.thick, () => ( {})), [l.id]: ch } } : {},
4615
- ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _242 => _242.stickers, 'optionalAccess', _243 => _243[l.id]]), () => ( [])), ...sprayed] } } : {}
4716
+ ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _245 => _245.stickers, 'optionalAccess', _246 => _246[l.id]]), () => ( [])), ...sprayed] } } : {}
4616
4717
  };
4617
4718
  }
4618
4719
  };
@@ -4670,7 +4771,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4670
4771
  */
4671
4772
  replayStrokes(options) {
4672
4773
  this.requireIdle("replaying");
4673
- if (!_optionalChain([options, 'access', _244 => _244.strokeIds, 'optionalAccess', _245 => _245.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
4774
+ if (!_optionalChain([options, 'access', _247 => _247.strokeIds, 'optionalAccess', _248 => _248.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
4674
4775
  const strokes = options.strokeIds.map((id) => {
4675
4776
  const s = this.doc.strokes.find((x) => x.id === id);
4676
4777
  if (!s) throw new PaintEditorError(`Unknown stroke "${id}". Call list_strokes for the ids.`);
@@ -4700,13 +4801,13 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4700
4801
  let brush = v.brush;
4701
4802
  if (options.brushId !== void 0) {
4702
4803
  const b = this.requireBrush(options.brushId);
4703
- brush = _chunkBXMIBMVGcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
4804
+ brush = _chunkJGKCC5OFcjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
4704
4805
  }
4705
4806
  const layerId = _nullishCoalesce(options.layerId, () => ( s.layerId));
4706
4807
  if (!_chunkHGTDMKNEcjs.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.`);
4707
4808
  let load = s.load;
4708
4809
  if (load && options.color !== void 0 && load.reservoir) {
4709
- const [r, g, b] = _chunkBXMIBMVGcjs.hexToRgb8.call(void 0, options.color);
4810
+ const [r, g, b] = _chunkJGKCC5OFcjs.hexToRgb8.call(void 0, options.color);
4710
4811
  load = { ...load, reservoir: [r / 255, g / 255, b / 255] };
4711
4812
  }
4712
4813
  const paint = v.paint && options.color === void 0 ? { paint: v.paint } : {};
@@ -4746,7 +4847,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4746
4847
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
4747
4848
  if (!id) return null;
4748
4849
  this.requireLayer(id);
4749
- const ch = _optionalChain([this, 'access', _246 => _246.doc, 'access', _247 => _247.thick, 'optionalAccess', _248 => _248[id]]);
4850
+ const ch = _optionalChain([this, 'access', _249 => _249.doc, 'access', _250 => _250.thick, 'optionalAccess', _251 => _251[id]]);
4750
4851
  if (!ch) return null;
4751
4852
  const r = reliefInfo(ch);
4752
4853
  return { layerId: id, bounds: r.bounds, maxHeight: r.maxHeight };
@@ -4851,7 +4952,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4851
4952
  wetState() {
4852
4953
  const st = this.getState().wet;
4853
4954
  const backend = this.wet.backend();
4854
- return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _249 => _249.message]), () => ( _chunkGNK7SESQcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
4955
+ return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _252 => _252.message]), () => ( _chunkGNK7SESQcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
4855
4956
  }
4856
4957
  /**
4857
4958
  * Engine B, the WebGPU accelerator for large wet areas: whether it may run, its state (`off`,
@@ -4936,7 +5037,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4936
5037
  }
4937
5038
  /** Records a settings change as a wet event (not an undo step). */
4938
5039
  recordWetSetting(e) {
4939
- this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _250 => _250.wet, 'access', _251 => _251.world, 'optionalAccess', _252 => _252.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
5040
+ this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _253 => _253.wet, 'access', _254 => _254.world, 'optionalAccess', _255 => _255.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
4940
5041
  }
4941
5042
  /** Changes a layer's wet settings (viscosity, evaporation, granulation…). Editor settings saved with the document, not an undo step. */
4942
5043
  setWetParams(layerId, update) {
@@ -5003,7 +5104,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5003
5104
  currentLayers() {
5004
5105
  const live = this.live;
5005
5106
  if (!live) return this.doc.layers;
5006
- if (_optionalChain([this, 'access', _253 => _253.liveLayers, 'optionalAccess', _254 => _254.key]) === live.surface) return this.liveLayers.layers;
5107
+ if (_optionalChain([this, 'access', _256 => _256.liveLayers, 'optionalAccess', _257 => _257.key]) === live.surface) return this.liveLayers.layers;
5007
5108
  const layers = _chunkHGTDMKNEcjs.mapLayer.call(void 0, this.doc.layers, live.layerId, (l) => ({ ...l, surface: live.surface }));
5008
5109
  this.liveLayers = { key: live.surface, layers };
5009
5110
  return layers;
@@ -5026,7 +5127,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5026
5127
  tracingNode(t) {
5027
5128
  const { width, height } = this.doc.canvas;
5028
5129
  const key = this.tracingVersion * 100003 + width * 7 + height;
5029
- if (_optionalChain([this, 'access', _255 => _255.tracingCache, 'optionalAccess', _256 => _256.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
5130
+ if (_optionalChain([this, 'access', _258 => _258.tracingCache, 'optionalAccess', _259 => _259.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
5030
5131
  const src = _nullishCoalesce(this.imagePixels.get(t.src), () => ( this.decodeImage(t.src)));
5031
5132
  const image = resampleInto(src, t.rect, width, height);
5032
5133
  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 };
@@ -5053,8 +5154,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5053
5154
  let out = layers;
5054
5155
  const ids = /* @__PURE__ */ new Set([...Object.keys(_nullishCoalesce(thick, () => ( {}))), ...live ? [live.layerId] : []]);
5055
5156
  for (const id of ids) {
5056
- const ch = _optionalChain([live, 'optionalAccess', _257 => _257.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _258 => _258[id]]);
5057
- const l = ch && _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, out, id), 'optionalAccess', _259 => _259.layer]);
5157
+ const ch = _optionalChain([live, 'optionalAccess', _260 => _260.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _261 => _261[id]]);
5158
+ const l = ch && _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, out, id), 'optionalAccess', _262 => _262.layer]);
5058
5159
  if (!ch || !isPixelLayer(l)) continue;
5059
5160
  let cache = this.litCaches.get(id);
5060
5161
  if (!cache) this.litCaches.set(id, cache = new LitCache());
@@ -5067,7 +5168,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5067
5168
  let layers = this.litLayers((_nullishCoalesce(options.wet, () => ( "display"))) === "dried" ? this.driedLayers() : this.currentLayers());
5068
5169
  if (options.layerIds) {
5069
5170
  const picked = [];
5070
- for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _260 => _260.layer]), () => ( this.requireLayer(id))));
5171
+ for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _263 => _263.layer]), () => ( this.requireLayer(id))));
5071
5172
  layers = picked.map((l) => ({ ...l, visible: true }));
5072
5173
  }
5073
5174
  const under = options.paper === false ? [] : [paperNode(this.doc.paper, this.lighting)];
@@ -5083,7 +5184,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5083
5184
  */
5084
5185
  compositeTiles(rect, onTile, options = {}) {
5085
5186
  const dirty = options.dirty === "all" ? void 0 : options.dirty;
5086
- this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _261 => _261.live, 'optionalAccess', _262 => _262.layerId]), () => ( this.doc.activeLayerId)) });
5187
+ this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _264 => _264.live, 'optionalAccess', _265 => _265.layerId]), () => ( this.doc.activeLayerId)) });
5087
5188
  }
5088
5189
  /** The canvas as canvas-sized RGBA (paper included by default). */
5089
5190
  compositePixels(options = {}) {
@@ -5147,7 +5248,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5147
5248
  for (const [id, list] of Object.entries(_nullishCoalesce(this.doc.stickers, () => ( {})))) if (list.length && _chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id)) stickers[id] = list.map((x) => ({ ...x }));
5148
5249
  if (Object.keys(stickers).length) ext.stickers = stickers;
5149
5250
  else delete ext.stickers;
5150
- const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _263 => _263.layer])));
5251
+ const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _266 => _266.layer])));
5151
5252
  if (effectLayers) ext.effectLayers = effectLayers;
5152
5253
  else delete ext.effectLayers;
5153
5254
  if (this.doc.paperEffect) ext.paperEffect = paperEffectToJSON(this.doc.paperEffect);
@@ -5164,7 +5265,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5164
5265
  const stickers = {};
5165
5266
  for (const [id, list] of Object.entries(ext.stickers)) {
5166
5267
  if (!_chunkHGTDMKNEcjs.findLayer.call(void 0, state.layers, id) || !Array.isArray(list)) continue;
5167
- const ok = list.filter((x) => x && typeof x.id === "string" && _chunkBXMIBMVGcjs.STAMP_KINDS.includes(x.stamp) && Number.isFinite(x.x) && Number.isFinite(x.y) && x.size > 0);
5268
+ const ok = list.filter((x) => x && typeof x.id === "string" && _chunkJGKCC5OFcjs.STAMP_KINDS.includes(x.stamp) && Number.isFinite(x.x) && Number.isFinite(x.y) && x.size > 0);
5168
5269
  if (ok.length !== list.length) problems.push(`Some stickers of layer "${id}" could not be read; they were dropped.`);
5169
5270
  stickers[id] = ok.map((x) => ({ ...x }));
5170
5271
  }
@@ -5173,7 +5274,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5173
5274
  if (ext.effectLayers && typeof ext.effectLayers === "object") {
5174
5275
  const effectLayers = {};
5175
5276
  for (const [id, v] of Object.entries(ext.effectLayers)) {
5176
- if (!isPixelLayer(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _264 => _264.layer]))) continue;
5277
+ if (!isPixelLayer(_optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _267 => _267.layer]))) continue;
5177
5278
  const source = readPaintEffectSource(v);
5178
5279
  if (source) effectLayers[id] = source;
5179
5280
  else problems.push(`The effect of layer "${id}" could not be read; it loads as a plain layer.`);
@@ -5214,12 +5315,13 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5214
5315
  this.readGuides(loaded.guides, loaded.state, loaded.problems);
5215
5316
  if (Array.isArray(loaded.swatches)) this.swatches = loaded.swatches.map(readSwatch).filter((x) => x !== null);
5216
5317
  for (const s of loaded.state.strokes) {
5217
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _265 => _265.exec, 'call', _266 => _266(s.id), 'optionalAccess', _267 => _267[1]]), () => ( 0)));
5318
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _268 => _268.exec, 'call', _269 => _269(s.id), 'optionalAccess', _270 => _270[1]]), () => ( 0)));
5218
5319
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
5219
5320
  }
5220
5321
  this.undoStack = [];
5221
5322
  this.redoStack = [];
5222
5323
  this.doc = this.readThick(loaded.state, loaded.extensions, loaded.problems);
5324
+ this.docRevision++;
5223
5325
  delete this.extensions.layerChannels;
5224
5326
  delete this.extensions.lighting;
5225
5327
  delete this.extensions.stickers;
@@ -5305,10 +5407,10 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5305
5407
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
5306
5408
  });
5307
5409
  const layers = toStandard(dried);
5308
- const result = _chunkPI45JMP7cjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5410
+ const result = _chunkCD7PLU77cjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5309
5411
  for (const [mode, names] of changed) {
5310
- const label = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _268 => _268.find, 'call', _269 => _269((m) => m.id === mode), 'optionalAccess', _270 => _270.label]), () => ( mode));
5311
- const std = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _271 => _271.find, 'call', _272 => _272((m) => m.id === _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _273 => _273.label]), () => ( _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)));
5412
+ const label = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _271 => _271.find, 'call', _272 => _272((m) => m.id === mode), 'optionalAccess', _273 => _273.label]), () => ( mode));
5413
+ const std = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _274 => _274.find, 'call', _275 => _275((m) => m.id === _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _276 => _276.label]), () => ( _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)));
5312
5414
  const list = names.map((n) => `"${n}"`).join(", ");
5313
5415
  const one = names.length === 1;
5314
5416
  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).`);
@@ -5424,7 +5526,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5424
5526
  const { src, pixels } = this.importImage(options, "The reference image");
5425
5527
  const ref2 = {
5426
5528
  id: `ref${this.nextReferenceId++}`,
5427
- name: _optionalChain([options, 'access', _274 => _274.name, 'optionalAccess', _275 => _275.trim, 'call', _276 => _276()]) || `Reference ${this.guides.references.length + 1}`,
5529
+ name: _optionalChain([options, 'access', _277 => _277.name, 'optionalAccess', _278 => _278.trim, 'call', _279 => _279()]) || `Reference ${this.guides.references.length + 1}`,
5428
5530
  src,
5429
5531
  width: pixels.width,
5430
5532
  height: pixels.height,
@@ -5503,7 +5605,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5503
5605
  try {
5504
5606
  const px = this.decodeImage(ref2.src, `Reference "${ref2.name}"`);
5505
5607
  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 });
5506
- const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _277 => _277.exec, 'call', _278 => _278(ref2.id), 'optionalAccess', _279 => _279[1]]), () => ( 0)));
5608
+ const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _280 => _280.exec, 'call', _281 => _281(ref2.id), 'optionalAccess', _282 => _282[1]]), () => ( 0)));
5507
5609
  if (n >= this.nextReferenceId) this.nextReferenceId = n + 1;
5508
5610
  } catch (e) {
5509
5611
  problems.push(e.message);
@@ -5514,7 +5616,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5514
5616
  guides.stencils = [];
5515
5617
  r.stencils.forEach((raw2, i) => {
5516
5618
  try {
5517
- const id = typeof _optionalChain([raw2, 'optionalAccess', _280 => _280.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
5619
+ const id = typeof _optionalChain([raw2, 'optionalAccess', _283 => _283.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
5518
5620
  guides.stencils.push(normalizeStencil(raw2, id));
5519
5621
  const n = Number(id.slice(7));
5520
5622
  if (n >= this.nextStencilId) this.nextStencilId = n + 1;
@@ -5537,12 +5639,12 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5537
5639
  /** The next free sticker number (ids `st<n>` are unique across the document). */
5538
5640
  nextStickerNumber(doc = this.doc) {
5539
5641
  let n = 0;
5540
- for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _281 => _281.exec, 'call', _282 => _282(st.id), 'optionalAccess', _283 => _283[1]]), () => ( 0))));
5642
+ for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _284 => _284.exec, 'call', _285 => _285(st.id), 'optionalAccess', _286 => _286[1]]), () => ( 0))));
5541
5643
  return n + 1;
5542
5644
  }
5543
5645
  stickerLayer(layerId) {
5544
5646
  const l = this.wetLayer(layerId, "edit the stickers of");
5545
- const stickers = _optionalChain([this, 'access', _284 => _284.doc, 'access', _285 => _285.stickers, 'optionalAccess', _286 => _286[l.id]]);
5647
+ const stickers = _optionalChain([this, 'access', _287 => _287.doc, 'access', _288 => _288.stickers, 'optionalAccess', _289 => _289[l.id]]);
5546
5648
  if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (list_brushes category sticker).`);
5547
5649
  return { layer: l, stickers };
5548
5650
  }
@@ -5551,12 +5653,12 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5551
5653
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
5552
5654
  if (!id) return [];
5553
5655
  this.requireLayer(id);
5554
- return (_nullishCoalesce(_optionalChain([this, 'access', _287 => _287.doc, 'access', _288 => _288.stickers, 'optionalAccess', _289 => _289[id]]), () => ( []))).map((s) => ({ ...s }));
5656
+ return (_nullishCoalesce(_optionalChain([this, 'access', _290 => _290.doc, 'access', _291 => _291.stickers, 'optionalAccess', _292 => _292[id]]), () => ( []))).map((s) => ({ ...s }));
5555
5657
  }
5556
5658
  /** Replaces a layer's stickers and redraws its pixels from them (one undo step). */
5557
5659
  commitStickers(label, layer, stickers) {
5558
5660
  if (_chunkHGTDMKNEcjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
5559
- const surface = _chunkBXMIBMVGcjs.stickerSurface.call(void 0, stickers);
5661
+ const surface = _chunkJGKCC5OFcjs.stickerSurface.call(void 0, stickers);
5560
5662
  const doc = { ...this.doc, layers: _chunkHGTDMKNEcjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => ({ ...layer, surface, offset: { x: 0, y: 0 } })), stickers: { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [layer.id]: stickers } };
5561
5663
  this.commit(label, this.withPaintEvent(doc, { kind: "stickers", layerId: layer.id, data: { stickers: stickers.map((s) => ({ ...s })) } }));
5562
5664
  }
@@ -5567,7 +5669,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5567
5669
  if (i < 0) throw new PaintEditorError(`Layer "${layer.name}" has no sticker "${id}". Call list_stickers for the ids.`);
5568
5670
  let u;
5569
5671
  try {
5570
- u = _chunkBXMIBMVGcjs.normalizeStickerUpdate.call(void 0, update);
5672
+ u = _chunkJGKCC5OFcjs.normalizeStickerUpdate.call(void 0, update);
5571
5673
  } catch (e) {
5572
5674
  throw new PaintEditorError(e.message);
5573
5675
  }
@@ -5601,13 +5703,13 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5601
5703
  this.commitStickers("Stickers", l, stickers.map((s) => ({ ...s })));
5602
5704
  }
5603
5705
  // --- Stencils --------------------------------------------------------------------
5604
- __init107() {this.stencilCache = null}
5605
- __init108() {this.nextStencilId = 1}
5706
+ __init108() {this.stencilCache = null}
5707
+ __init109() {this.nextStencilId = 1}
5606
5708
  /** The mask stencils' coverage over the canvas (cached), or `null` when none masks. */
5607
5709
  stencilSelection(stencils = this.guides.stencils) {
5608
5710
  const { width, height } = this.doc.canvas;
5609
5711
  const size = `${width}x${height}`;
5610
- if (_optionalChain([this, 'access', _290 => _290.stencilCache, 'optionalAccess', _291 => _291.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
5712
+ if (_optionalChain([this, 'access', _293 => _293.stencilCache, 'optionalAccess', _294 => _294.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
5611
5713
  const mask = stencilMask(stencils, width, height);
5612
5714
  this.stencilCache = { key: stencils, size, mask };
5613
5715
  return mask;
@@ -5668,8 +5770,8 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5668
5770
  }
5669
5771
  makeSwatch(color, name) {
5670
5772
  const p = typeof color === "string" ? { type: "color", color: parseColor(color) } : this.readStrokePaint(color);
5671
- const out = { color: _chunkLRRCMRSLcjs.paintSourceColor.call(void 0, p, { paint: this.color, secondary: this.secondaryColor }) };
5672
- if (_optionalChain([name, 'optionalAccess', _292 => _292.trim, 'call', _293 => _293()])) out.name = name.trim();
5773
+ const out = { color: _chunkEBDCRTZIcjs.paintSourceColor.call(void 0, p, { paint: this.color, secondary: this.secondaryColor }) };
5774
+ if (_optionalChain([name, 'optionalAccess', _295 => _295.trim, 'call', _296 => _296()])) out.name = name.trim();
5673
5775
  if (p.type === "gradient") out.paint = p;
5674
5776
  return out;
5675
5777
  }
@@ -5721,7 +5823,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5721
5823
  * mix becomes the paint colour. Returns the mixed colour and the pile's bounds.
5722
5824
  */
5723
5825
  mixOnPad(paints, options = {}) {
5724
- const parsed = (_nullishCoalesce(paints, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _294 => _294.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _295 => _295.parts]) }));
5826
+ const parsed = (_nullishCoalesce(paints, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _297 => _297.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _298 => _298.parts]) }));
5725
5827
  let r;
5726
5828
  try {
5727
5829
  r = this.pad.mix(parsed, options);
@@ -5810,11 +5912,65 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5810
5912
  }
5811
5913
  /** A layer's tile surface (live while stroking), for thumbnails. */
5812
5914
  layerSurface(id) {
5813
- const l = _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _296 => _296.layer]);
5915
+ const l = _optionalChain([_chunkHGTDMKNEcjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _299 => _299.layer]);
5814
5916
  return isPixelLayer(l) ? l.surface : null;
5815
5917
  }
5816
5918
  }, _class10);
5817
5919
  var MAX_IMAGE_SIDE = 8192;
5920
+ var movePoint = (p, dx, dy) => ({ x: p.x + dx, y: p.y + dy });
5921
+ var moveRect = (r, dx, dy) => ({ ...r, x: r.x + dx, y: r.y + dy });
5922
+ function shiftDocument(doc, dx, dy) {
5923
+ if (!dx && !dy) return doc;
5924
+ let layers = doc.layers;
5925
+ for (const l of _chunkHGTDMKNEcjs.flattenLayers.call(void 0, doc.layers)) if (l.type === "pixel") layers = _chunkHGTDMKNEcjs.mapLayer.call(void 0, layers, l.id, () => ({ ...l, offset: movePoint(l.offset, dx, dy) }));
5926
+ const m = [1, 0, 0, 1, dx, dy];
5927
+ const moveStickers = (list) => list.map((s) => ({ ...s, x: Math.round((s.x + dx) * 100) / 100, y: Math.round((s.y + dy) * 100) / 100 }));
5928
+ const out = {
5929
+ ...doc,
5930
+ layers,
5931
+ paper: { ...doc.paper, offset: movePoint(_nullishCoalesce(doc.paper.offset, () => ( { x: 0, y: 0 })), dx, dy) },
5932
+ origin: movePoint(_nullishCoalesce(doc.origin, () => ( { x: 0, y: 0 })), -dx, -dy),
5933
+ strokes: doc.strokes.map((s) => {
5934
+ const moved = varyStroke(s, m, {});
5935
+ return s.stencils ? { ...moved, stencils: s.stencils.map((x) => translateStencil(x, dx, dy)) } : moved;
5936
+ })
5937
+ };
5938
+ if (doc.stickers) out.stickers = Object.fromEntries(Object.entries(doc.stickers).map(([id, list]) => [id, moveStickers(list)]));
5939
+ if (doc.paintEvents) {
5940
+ out.paintEvents = doc.paintEvents.map((e) => {
5941
+ const list = e.kind === "stickers" ? _optionalChain([e, 'access', _300 => _300.data, 'optionalAccess', _301 => _301.stickers]) : void 0;
5942
+ return list ? { ...e, data: { ...e.data, stickers: moveStickers(list) } } : e;
5943
+ });
5944
+ }
5945
+ if (doc.wetEvents) {
5946
+ out.wetEvents = doc.wetEvents.map((e) => {
5947
+ const d = e.data;
5948
+ if (!d) return e;
5949
+ if (e.kind === "dry" && typeof d.x === "number") return { ...e, data: moveRect(d, dx, dy) };
5950
+ if (e.kind === "wet-paper" && d.rect) return { ...e, data: { ...d, rect: moveRect(d.rect, dx, dy) } };
5951
+ if (e.kind === "flow" && d.center) return { ...e, data: { ...d, center: movePoint(d.center, dx, dy) } };
5952
+ return e;
5953
+ });
5954
+ }
5955
+ if (doc.paperEffect) {
5956
+ const src = doc.paperEffect.image;
5957
+ const width = src.width + dx;
5958
+ const height = src.height + dy;
5959
+ const data = new Uint8ClampedArray(width * height * 4);
5960
+ for (let y = 0; y < src.height; y++) data.set(src.data.subarray(y * src.width * 4, (y + 1) * src.width * 4), ((y + dy) * width + dx) * 4);
5961
+ out.paperEffect = { ...doc.paperEffect, image: { width, height, data }, version: nextPaperEffectVersion() };
5962
+ }
5963
+ return out;
5964
+ }
5965
+ function shiftGuides(g, dx, dy) {
5966
+ return {
5967
+ ...g,
5968
+ symmetry: { ...g.symmetry, center: movePoint(g.symmetry.center, dx, dy) },
5969
+ perspective: { ...g.perspective, points: g.perspective.points.map((p) => movePoint(p, dx, dy)) },
5970
+ tracing: g.tracing ? { ...g.tracing, rect: moveRect(g.tracing.rect, dx, dy) } : null,
5971
+ stencils: g.stencils.map((s) => translateStencil(s, dx, dy))
5972
+ };
5973
+ }
5818
5974
  function resampleInto(src, rect, width, height) {
5819
5975
  const out = new Uint8ClampedArray(width * height * 4);
5820
5976
  const x0 = Math.max(0, Math.floor(rect.x));
@@ -5864,8 +6020,8 @@ function strokeSchedule(points) {
5864
6020
  return total > 0 ? acc.map((d) => d / total) : points.map(() => 1);
5865
6021
  }
5866
6022
  function strokeDuration(points, max = 1800) {
5867
- const t0 = _optionalChain([points, 'access', _297 => _297[0], 'optionalAccess', _298 => _298.t]);
5868
- const t1 = _optionalChain([points, 'access', _299 => _299[points.length - 1], 'optionalAccess', _300 => _300.t]);
6023
+ const t0 = _optionalChain([points, 'access', _302 => _302[0], 'optionalAccess', _303 => _303.t]);
6024
+ const t1 = _optionalChain([points, 'access', _304 => _304[points.length - 1], 'optionalAccess', _305 => _305.t]);
5869
6025
  let ms;
5870
6026
  if (points.every((p) => Number.isFinite(p.t)) && t1 > t0) ms = t1 - t0;
5871
6027
  else {
@@ -5919,7 +6075,7 @@ var PaintDirector = class {
5919
6075
  }
5920
6076
  where(id) {
5921
6077
  const a = this.presence.get(id);
5922
- return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _301 => _301.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _302 => _302.y]), () => ( 0)) };
6078
+ return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _306 => _306.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _307 => _307.y]), () => ( 0)) };
5923
6079
  }
5924
6080
  /** Glides to `to`; an actor that just appeared starts there instead of the corner. */
5925
6081
  async glide(id, to, ms = 380) {
@@ -5966,8 +6122,8 @@ var PaintDirector = class {
5966
6122
  }
5967
6123
  case "replay": {
5968
6124
  await this.say(id, command.note, 500);
5969
- const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _303 => _303.replay, 'access', _304 => _304.strokeIds, 'optionalAccess', _305 => _305.includes, 'call', _306 => _306(s.id)]));
5970
- const first = _optionalChain([source, 'access', _307 => _307[0], 'optionalAccess', _308 => _308.points, 'access', _309 => _309[0]]);
6125
+ const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _308 => _308.replay, 'access', _309 => _309.strokeIds, 'optionalAccess', _310 => _310.includes, 'call', _311 => _311(s.id)]));
6126
+ const first = _optionalChain([source, 'access', _312 => _312[0], 'optionalAccess', _313 => _313.points, 'access', _314 => _314[0]]);
5971
6127
  if (first) await this.glide(id, first);
5972
6128
  const result = c.replayStrokes(command.replay);
5973
6129
  if (result.bounds) await this.glide(id, centre(result.bounds), 520);
@@ -6079,7 +6235,7 @@ function createPaintStickerTools(c) {
6079
6235
  properties: {
6080
6236
  layerId: LAYER_ID,
6081
6237
  id: { type: "string", description: "Sticker id from list_stickers." },
6082
- stamp: { type: "string", enum: [..._chunkBXMIBMVGcjs.STAMP_KINDS], description: "Another stamp." },
6238
+ stamp: { type: "string", enum: [..._chunkJGKCC5OFcjs.STAMP_KINDS], description: "Another stamp." },
6083
6239
  x: { type: "number", description: "Centre x in document pixels." },
6084
6240
  y: { type: "number", description: "Centre y in document pixels." },
6085
6241
  size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels." },
@@ -6376,7 +6532,7 @@ function createPaintGuideTools(c) {
6376
6532
  type: "object",
6377
6533
  properties: {
6378
6534
  color: { ...COLOR2, description: "A colour #rrggbb." },
6379
- paint: { ..._chunkLRRCMRSLcjs.PAINT_SOURCE_JSON_SCHEMA, description: "Gradient paint (or a colour) for the swatch, instead of color." },
6535
+ paint: { ..._chunkEBDCRTZIcjs.PAINT_SOURCE_JSON_SCHEMA, description: "Gradient paint (or a colour) for the swatch, instead of color." },
6380
6536
  name: { type: "string", minLength: 1, description: "Optional name." }
6381
6537
  },
6382
6538
  additionalProperties: false
@@ -6881,7 +7037,7 @@ var TIP = {
6881
7037
  type: "object",
6882
7038
  description: "The tip (the shared brush engine). Missing fields keep their current values.",
6883
7039
  properties: {
6884
- size: { type: "number", minimum: 1, maximum: _chunkLRRCMRSLcjs.MAX_BRUSH_SIZE, description: "Diameter in document pixels." },
7040
+ size: { type: "number", minimum: 1, maximum: _chunkEBDCRTZIcjs.MAX_BRUSH_SIZE, description: "Diameter in document pixels." },
6885
7041
  hardness: { type: "number", minimum: 0, maximum: 1, description: "Edge hardness, 0 (soft) .. 1 (hard)." },
6886
7042
  spacing: { type: "number", minimum: 0.01, maximum: 10, description: "Dab spacing as a fraction of the diameter (0.05 is smooth, 1 is dotted)." },
6887
7043
  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." },
@@ -6926,11 +7082,11 @@ var MIXER = {
6926
7082
  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." },
6927
7083
  loadEachStroke: { type: "boolean", description: "Refill the reservoir with the colour before each stroke." },
6928
7084
  cleanEachStroke: { type: "boolean", description: "Empty the pickup well after each stroke." },
6929
- mixing: { type: "string", enum: [..._chunkLRRCMRSLcjs.MIXING_MODELS], description: "rgb: RGB averages. pigment: mixes like paint (Kubelka-Munk)." }
7085
+ mixing: { type: "string", enum: [..._chunkEBDCRTZIcjs.MIXING_MODELS], description: "rgb: RGB averages. pigment: mixes like paint (Kubelka-Munk)." }
6930
7086
  },
6931
7087
  additionalProperties: false
6932
7088
  };
6933
- var MIXING = { type: "string", enum: [..._chunkLRRCMRSLcjs.MIXING_MODELS], description: "pigment: mixes like paint (Kubelka-Munk, blue and yellow make green); rgb: straight RGB averages." };
7089
+ var MIXING = { type: "string", enum: [..._chunkEBDCRTZIcjs.MIXING_MODELS], description: "pigment: mixes like paint (Kubelka-Munk, blue and yellow make green); rgb: straight RGB averages." };
6934
7090
  var BEHAVIOR = {
6935
7091
  type: "object",
6936
7092
  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.",
@@ -6943,7 +7099,7 @@ var BEHAVIOR = {
6943
7099
  type: "object",
6944
7100
  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.",
6945
7101
  properties: {
6946
- mode: { type: "string", enum: [..._chunkBXMIBMVGcjs.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." },
7102
+ mode: { type: "string", enum: [..._chunkJGKCC5OFcjs.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." },
6947
7103
  colors: { type: "array", maxItems: 8, items: { ...COLOR3 }, description: "2..8 colours #rrggbb; fewer than 2 uses the paint colour and the secondary colour." },
6948
7104
  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)." },
6949
7105
  length: { type: "integer", minimum: 1, maximum: 500, description: "dab mode: dabs per colour (default 12)." },
@@ -6956,7 +7112,7 @@ var BEHAVIOR = {
6956
7112
  };
6957
7113
  var BRUSH_PAINT = {
6958
7114
  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.`,
6959
- anyOf: [_chunkLRRCMRSLcjs.PAINT_GRADIENT_JSON_SCHEMA, { type: "null", description: "No gradient of its own: the editor's paint." }]
7115
+ anyOf: [_chunkEBDCRTZIcjs.PAINT_GRADIENT_JSON_SCHEMA, { type: "null", description: "No gradient of its own: the editor's paint." }]
6960
7116
  };
6961
7117
  var BLENDER = {
6962
7118
  type: "object",
@@ -6984,10 +7140,10 @@ var WET_BRUSH = {
6984
7140
  properties: {
6985
7141
  tool: {
6986
7142
  type: "string",
6987
- enum: [..._chunkBXMIBMVGcjs.WET_TOOLS],
7143
+ enum: [..._chunkJGKCC5OFcjs.WET_TOOLS],
6988
7144
  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)."
6989
7145
  },
6990
- medium: { type: "string", enum: [..._chunkBXMIBMVGcjs.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)." },
7146
+ medium: { type: "string", enum: [..._chunkJGKCC5OFcjs.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)." },
6991
7147
  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)." },
6992
7148
  thinner: { type: "number", minimum: 0, maximum: 1, description: "Thinner (water or solvent): more transparent, runnier paint." },
6993
7149
  water: { type: "number", minimum: 0, maximum: 1, description: "Wetness: water laid per stroke, 0.2 a damp brush .. 1 a dripping one." },
@@ -7004,7 +7160,7 @@ var IMPASTO_BRUSH = {
7004
7160
  properties: {
7005
7161
  tool: {
7006
7162
  type: "string",
7007
- enum: [..._chunkBXMIBMVGcjs.IMPASTO_TOOLS],
7163
+ enum: [..._chunkJGKCC5OFcjs.IMPASTO_TOOLS],
7008
7164
  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."
7009
7165
  },
7010
7166
  thickness: { type: "number", minimum: 0, maximum: 1, description: "How far the paint stands up." },
@@ -7020,8 +7176,8 @@ var PARTICLE_BRUSH = {
7020
7176
  type: "object",
7021
7177
  description: "Particle engine settings (procedural brushes). Missing fields keep their current values.",
7022
7178
  properties: {
7023
- kind: { type: "string", enum: [..._chunkBXMIBMVGcjs.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." },
7024
- render: { type: "string", enum: [..._chunkBXMIBMVGcjs.PARTICLE_RENDERS], description: "dot: a mark at each step; line: each particle draws a continuous line; sequence: beads spaced along each path." },
7179
+ kind: { type: "string", enum: [..._chunkJGKCC5OFcjs.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." },
7180
+ render: { type: "string", enum: [..._chunkJGKCC5OFcjs.PARTICLE_RENDERS], description: "dot: a mark at each step; line: each particle draws a continuous line; sequence: beads spaced along each path." },
7025
7181
  count: { type: "integer", minimum: 1, maximum: 64, description: "Particles (flow: how many are thrown per tip of travel)." },
7026
7182
  size: { type: "number", minimum: 0, maximum: 1, description: "Mark size as a fraction of the tip size." },
7027
7183
  spread: { type: "number", minimum: 0, maximum: 1, description: "How far apart the particles start, as a fraction of the tip size." },
@@ -7051,7 +7207,7 @@ var STICKER_BRUSH = {
7051
7207
  type: "object",
7052
7208
  description: "Sticker engine settings: stamps sprayed along the stroke as editable stickers. Missing fields keep their current values.",
7053
7209
  properties: {
7054
- stamps: { type: "array", minItems: 1, maxItems: 9, items: { type: "string", enum: [..._chunkBXMIBMVGcjs.STAMP_KINDS], description: "A stamp." }, description: "The stamps to spray (one picked at random per sticker)." },
7210
+ stamps: { type: "array", minItems: 1, maxItems: 9, items: { type: "string", enum: [..._chunkJGKCC5OFcjs.STAMP_KINDS], description: "A stamp." }, description: "The stamps to spray (one picked at random per sticker)." },
7055
7211
  density: { type: "number", minimum: 0, maximum: 1, description: "Stickers per distance travelled." },
7056
7212
  sizeJitter: { type: "number", minimum: 0, maximum: 1, description: "Random size change." },
7057
7213
  rotationJitter: { type: "number", minimum: 0, maximum: 1, description: "Random turn as a fraction of \xB1180\xB0." },
@@ -7062,16 +7218,16 @@ var STICKER_BRUSH = {
7062
7218
  };
7063
7219
  var BRUSH_FIELDS = {
7064
7220
  name: { type: "string", minLength: 1, maxLength: 80, description: "Display name." },
7065
- category: { type: "string", enum: [..._chunkBXMIBMVGcjs.PAINT_BRUSH_CATEGORIES], description: "Library category." },
7221
+ category: { type: "string", enum: [..._chunkJGKCC5OFcjs.PAINT_BRUSH_CATEGORIES], description: "Library category." },
7066
7222
  engine: {
7067
7223
  type: "string",
7068
- enum: [..._chunkBXMIBMVGcjs.PAINT_BRUSH_ENGINES],
7224
+ enum: [..._chunkJGKCC5OFcjs.PAINT_BRUSH_ENGINES],
7069
7225
  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)."
7070
7226
  },
7071
7227
  tip: TIP,
7072
7228
  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." },
7073
7229
  pressureSmoothing: { type: "number", minimum: 0, maximum: 0.95, description: "Pressure smoothing, separate from the tip position smoothing." },
7074
- rotation: { type: "string", enum: [..._chunkBXMIBMVGcjs.BRUSH_ROTATIONS], description: "What turns the tip: fixed (tip.angle), stroke (follows the direction of travel) or barrel (the pen barrel rotation, twist)." },
7230
+ rotation: { type: "string", enum: [..._chunkJGKCC5OFcjs.BRUSH_ROTATIONS], description: "What turns the tip: fixed (tip.angle), stroke (follows the direction of travel) or barrel (the pen barrel rotation, twist)." },
7075
7231
  dynamics: DYNAMICS,
7076
7232
  mixer: MIXER,
7077
7233
  loadsColor: { type: "boolean", description: "Mixer engine: load the colour each stroke (false for a mixer that only moves paint)." },
@@ -7121,7 +7277,7 @@ function brushSummary(b) {
7121
7277
  size: b.tip.size,
7122
7278
  grain: b.grain,
7123
7279
  rotation: b.rotation,
7124
- wetCapable: _chunkBXMIBMVGcjs.isWetCapable.call(void 0, b),
7280
+ wetCapable: _chunkJGKCC5OFcjs.isWetCapable.call(void 0, b),
7125
7281
  pickup: b.behavior.pickup,
7126
7282
  dirty: b.behavior.dirty,
7127
7283
  multicolor: b.behavior.multicolor.mode,
@@ -7143,7 +7299,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7143
7299
  add({
7144
7300
  name: "get_canvas_info",
7145
7301
  title: "Get the canvas",
7146
- description: "Reads the canvas: size in pixels and dpi, the paper (preset, colour, grain depth), the active layer, the active brush id, the paint colour, the view (zoom, rotation, mirror), the hand, how many strokes are recorded, the undo / redo labels, and the blend modes. Call it first.",
7302
+ description: "Reads the canvas: size in pixels and dpi, its origin (where (0, 0) is relative to the canvas it was extended from), the paper (preset, colour, grain depth), the active layer, the active brush id, the paint colour, the view (zoom, rotation, mirror), the hand, how many strokes are recorded, the undo / redo labels, and the blend modes. Call it first.",
7147
7303
  inputSchema: EMPTY3,
7148
7304
  annotations: { title: "Get the canvas", ...READ6 },
7149
7305
  handler: () => {
@@ -7153,6 +7309,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7153
7309
  width: d.canvas.width,
7154
7310
  height: d.canvas.height,
7155
7311
  dpi: d.canvas.dpi,
7312
+ origin: { ..._nullishCoalesce(d.origin, () => ( { x: 0, y: 0 })) },
7156
7313
  paper: { preset: d.paper.preset, name: d.paper.name, color: d.paper.color, depth: d.paper.depth },
7157
7314
  activeLayerId: d.activeLayerId,
7158
7315
  layerCount: c.listLayers().length,
@@ -7206,6 +7363,19 @@ function createPaintEditorToolProvider(controller, options = {}) {
7206
7363
  annotations: { title: "Resize the canvas", ...SET4 },
7207
7364
  handler: (a) => c.setCanvas({ width: a.width, height: a.height, dpi: a.dpi })
7208
7365
  });
7366
+ const EXTEND_SIDE = (side) => ({ type: "integer", minimum: 0, maximum: MAX_CANVAS_SIDE - 1, description: `Pixels to add on the ${side} (default 0).` });
7367
+ add({
7368
+ name: "extend_canvas",
7369
+ title: "Extend the canvas",
7370
+ description: "Grows the canvas by adding pixels on any side, keeping everything painted. Adding on the left or top moves the whole picture (layers, paper grain, guides, stencils, recorded strokes) right or down by that much in document pixels, so coordinates you read before change by (+left, +top). Wet paint dries first. One undo step. Returns the canvas, rect (the new canvas in the previous coordinates: x -left, y -top) and origin.",
7371
+ inputSchema: {
7372
+ type: "object",
7373
+ properties: { left: EXTEND_SIDE("left"), top: EXTEND_SIDE("top"), right: EXTEND_SIDE("right"), bottom: EXTEND_SIDE("bottom") },
7374
+ additionalProperties: false
7375
+ },
7376
+ annotations: { title: "Extend the canvas", ...WRITE5 },
7377
+ handler: (a) => c.extendCanvas({ left: a.left, top: a.top, right: a.right, bottom: a.bottom })
7378
+ });
7209
7379
  add({
7210
7380
  name: "list_papers",
7211
7381
  title: "List papers",
@@ -7213,9 +7383,9 @@ function createPaintEditorToolProvider(controller, options = {}) {
7213
7383
  inputSchema: EMPTY3,
7214
7384
  annotations: { title: "List papers", ...READ6 },
7215
7385
  handler: () => ({
7216
- papers: _chunkBXMIBMVGcjs.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 })),
7217
- families: [..._chunkBXMIBMVGcjs.PAPER_FAMILIES],
7218
- patterns: [..._chunkLRRCMRSLcjs.GRAIN_PATTERNS]
7386
+ papers: _chunkJGKCC5OFcjs.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 })),
7387
+ families: [..._chunkJGKCC5OFcjs.PAPER_FAMILIES],
7388
+ patterns: [..._chunkEBDCRTZIcjs.GRAIN_PATTERNS]
7219
7389
  })
7220
7390
  });
7221
7391
  add({
@@ -7246,7 +7416,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7246
7416
  depth: { type: "number", minimum: 0, maximum: 1, description: "Grain depth 0..1 (0: brushes ignore the grain)." },
7247
7417
  scale: { type: "number", minimum: 0.25, maximum: 8, description: "Grain scale: 1 natural, 2 twice as coarse." },
7248
7418
  seed: { type: "integer", minimum: 0, description: "Grain seed: another sheet of the same paper." },
7249
- pattern: { type: "string", enum: [..._chunkLRRCMRSLcjs.GRAIN_PATTERNS], description: "Grain pattern." },
7419
+ pattern: { type: "string", enum: [..._chunkEBDCRTZIcjs.GRAIN_PATTERNS], description: "Grain pattern." },
7250
7420
  tiling: { type: "string", enum: ["repeat", "mirror"], description: "How the grain tile repeats (mirror hides seams)." },
7251
7421
  shading: { type: "number", minimum: 0, maximum: 1, description: "How much the grain shades the paper colour." },
7252
7422
  dry: { ...tuning, description: "Height map tuning for dry media." },
@@ -7425,7 +7595,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7425
7595
  annotations: { title: "List brushes", ...READ6 },
7426
7596
  handler: () => {
7427
7597
  const s = c.getState();
7428
- return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access', _310 => _310.getBrush, 'call', _311 => _311(s.brush.id), 'optionalAccess', _312 => _312.builtin])), brushes: s.brushes.map(brushSummary) };
7598
+ return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access', _315 => _315.getBrush, 'call', _316 => _316(s.brush.id), 'optionalAccess', _317 => _317.builtin])), brushes: s.brushes.map(brushSummary) };
7429
7599
  }
7430
7600
  });
7431
7601
  add({
@@ -7436,10 +7606,10 @@ function createPaintEditorToolProvider(controller, options = {}) {
7436
7606
  annotations: { title: "Get a brush", ...READ6 },
7437
7607
  handler: ({ id }) => {
7438
7608
  const st = c.getState();
7439
- if (id === void 0) return { ..._chunkBXMIBMVGcjs.brushToJSON.call(void 0, st.brush), strokePaint: _nullishCoalesce(st.brush.paint, () => ( st.paint)) };
7609
+ if (id === void 0) return { ..._chunkJGKCC5OFcjs.brushToJSON.call(void 0, st.brush), strokePaint: _nullishCoalesce(st.brush.paint, () => ( st.paint)) };
7440
7610
  const b = c.getBrush(id);
7441
7611
  if (!b) throw new Error(`Unknown brush "${id}". Call list_brushes for the ids.`);
7442
- return { ..._chunkBXMIBMVGcjs.brushToJSON.call(void 0, b), builtin: Boolean(b.builtin), strokePaint: _nullishCoalesce(b.paint, () => ( st.paint)) };
7612
+ return { ..._chunkJGKCC5OFcjs.brushToJSON.call(void 0, b), builtin: Boolean(b.builtin), strokePaint: _nullishCoalesce(b.paint, () => ( st.paint)) };
7443
7613
  }
7444
7614
  });
7445
7615
  add({
@@ -7448,7 +7618,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7448
7618
  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.",
7449
7619
  inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brushes to start from." }, ...BRUSH_FIELDS }, additionalProperties: false },
7450
7620
  annotations: { title: "Set the brush", ...SET4 },
7451
- handler: (a) => _chunkBXMIBMVGcjs.brushToJSON.call(void 0, c.setBrush(a))
7621
+ handler: (a) => _chunkJGKCC5OFcjs.brushToJSON.call(void 0, c.setBrush(a))
7452
7622
  });
7453
7623
  add({
7454
7624
  name: "save_brush",
@@ -7464,7 +7634,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7464
7634
  additionalProperties: false
7465
7635
  },
7466
7636
  annotations: { title: "Save a brush", ...SET4 },
7467
- handler: ({ id, name }) => _chunkBXMIBMVGcjs.brushToJSON.call(void 0, c.saveBrush({ id, name }))
7637
+ handler: ({ id, name }) => _chunkJGKCC5OFcjs.brushToJSON.call(void 0, c.saveBrush({ id, name }))
7468
7638
  });
7469
7639
  add({
7470
7640
  name: "remove_brush",
@@ -7551,7 +7721,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7551
7721
  name: "set_paint",
7552
7722
  title: "Set the paint (colour or gradient)",
7553
7723
  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. set_color goes back to one colour. Editor state, not an undo step. Returns paint, color and secondaryColor.',
7554
- inputSchema: { type: "object", properties: { paint: _chunkLRRCMRSLcjs.PAINT_SOURCE_JSON_SCHEMA }, required: ["paint"], additionalProperties: false },
7724
+ inputSchema: { type: "object", properties: { paint: _chunkEBDCRTZIcjs.PAINT_SOURCE_JSON_SCHEMA }, required: ["paint"], additionalProperties: false },
7555
7725
  annotations: { title: "Set the paint (colour or gradient)", ...SET4 },
7556
7726
  handler: ({ paint }) => {
7557
7727
  const p = c.setPaint(paint);
@@ -7612,7 +7782,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7612
7782
  brushId: { type: "string", description: "Brush id from list_brushes (default the active brush)." },
7613
7783
  brush: { type: "object", description: "Brush changes for this stroke only.", properties: BRUSH_FIELDS, additionalProperties: false },
7614
7784
  color: { ...COLOR3, description: "Paint colour #rrggbb (default the paint colour)." },
7615
- paint: { ..._chunkLRRCMRSLcjs.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." },
7785
+ paint: { ..._chunkEBDCRTZIcjs.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." },
7616
7786
  seed: { type: "integer", minimum: 0, description: "Jitter seed (default a new one); the same seed and points give the same marks." },
7617
7787
  snapToPerspective: { type: "boolean", description: "Snap the points to the perspective guide, as a pen stroke would (default false)." }
7618
7788
  },
@@ -7660,7 +7830,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7660
7830
  color: s.color,
7661
7831
  points: ids ? s.points : s.points.length,
7662
7832
  seed: s.seed,
7663
- copies: _nullishCoalesce(_optionalChain([s, 'access', _313 => _313.copies, 'optionalAccess', _314 => _314.length]), () => ( 0)),
7833
+ copies: _nullishCoalesce(_optionalChain([s, 'access', _318 => _318.copies, 'optionalAccess', _319 => _319.length]), () => ( 0)),
7664
7834
  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) }
7665
7835
  };
7666
7836
  })
@@ -7810,7 +7980,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7810
7980
  add({
7811
7981
  name: "save_document",
7812
7982
  title: "Save the document",
7813
- description: "Returns the document as JSON (format pixerate-paint, version 1): canvas, paper, layers with PNG data URLs, and the recorded strokes unless strokes is false. Changes nothing.",
7983
+ description: "Deprecated (kept for one minor version): use get_paint_document, which returns the painting with images as asset references, or save_paint_document to store it. Returns the document as JSON (format pixerate-paint, version 1): canvas, paper, layers with PNG data URLs, and the recorded strokes unless strokes is false. Changes nothing.",
7814
7984
  inputSchema: { type: "object", properties: { strokes: { type: "boolean", description: "Include the recorded strokes (default true)." } }, additionalProperties: false },
7815
7985
  annotations: { title: "Save the document", ...READ6 },
7816
7986
  handler: ({ strokes }) => c.toJSON({ strokes })
@@ -7818,7 +7988,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
7818
7988
  add({
7819
7989
  name: "open_document",
7820
7990
  title: "Open a document",
7821
- description: "Opens a saved paint document (as save_document returns), replacing the painting and clearing the undo history. Returns the canvas, the layers and anything that could not be read.",
7991
+ description: "Deprecated (kept for one minor version): use load_paint_document or open_saved_paint_document. Opens a saved paint document (as save_document returns), replacing the painting and clearing the undo history. Returns the canvas, the layers and anything that could not be read.",
7822
7992
  inputSchema: { type: "object", properties: { document: { type: "object", description: "The saved document JSON." } }, required: ["document"], additionalProperties: false },
7823
7993
  annotations: { title: "Open a document", ...DESTRUCTIVE3 },
7824
7994
  handler: ({ document }) => {
@@ -7851,20 +8021,20 @@ var PAINT_TOOLS = [
7851
8021
  { id: "rotate", label: "Rotate view", key: "r" }
7852
8022
  ];
7853
8023
  var PaintGesture = (_class11 = class {
7854
- constructor(controller, box) {;_class11.prototype.__init109.call(this);_class11.prototype.__init110.call(this);_class11.prototype.__init111.call(this);_class11.prototype.__init112.call(this);_class11.prototype.__init113.call(this);_class11.prototype.__init114.call(this);
8024
+ constructor(controller, box) {;_class11.prototype.__init110.call(this);_class11.prototype.__init111.call(this);_class11.prototype.__init112.call(this);_class11.prototype.__init113.call(this);_class11.prototype.__init114.call(this);_class11.prototype.__init115.call(this);
7855
8025
  this.controller = controller;
7856
8026
  this.box = box;
7857
8027
  }
7858
8028
 
7859
8029
 
7860
- __init109() {this.tool = "brush"}
8030
+ __init110() {this.tool = "brush"}
7861
8031
  /** The last refusal (a hidden or locked layer), for the editor to show. */
7862
- __init110() {this.error = null}
8032
+ __init111() {this.error = null}
7863
8033
  /** The predicted tail of the current stroke in document pixels (draw it as a thin preview). */
7864
- __init111() {this.predicted = []}
7865
- __init112() {this.mode = null}
7866
- __init113() {this.penAt = null}
7867
- __init114() {this.penDown = false}
8034
+ __init112() {this.predicted = []}
8035
+ __init113() {this.mode = null}
8036
+ __init114() {this.penAt = null}
8037
+ __init115() {this.penDown = false}
7868
8038
  doc(e) {
7869
8039
  const b = this.box();
7870
8040
  const s = this.controller.getState();
@@ -7945,12 +8115,12 @@ var PaintGesture = (_class11 = class {
7945
8115
  if (!m || m.pointerId !== e.pointerId) return;
7946
8116
  this.mode = null;
7947
8117
  this.predicted = [];
7948
- if (m.kind === "stroke") _optionalChain([this, 'access', _315 => _315.controller, 'access', _316 => _316.activeStroke, 'optionalAccess', _317 => _317.end, 'call', _318 => _318()]);
8118
+ if (m.kind === "stroke") _optionalChain([this, 'access', _320 => _320.controller, 'access', _321 => _321.activeStroke, 'optionalAccess', _322 => _322.end, 'call', _323 => _323()]);
7949
8119
  }
7950
8120
  cancel() {
7951
8121
  this.penDown = false;
7952
8122
  this.predicted = [];
7953
- if (_optionalChain([this, 'access', _319 => _319.mode, 'optionalAccess', _320 => _320.kind]) === "stroke") _optionalChain([this, 'access', _321 => _321.controller, 'access', _322 => _322.activeStroke, 'optionalAccess', _323 => _323.cancel, 'call', _324 => _324()]);
8123
+ if (_optionalChain([this, 'access', _324 => _324.mode, 'optionalAccess', _325 => _325.kind]) === "stroke") _optionalChain([this, 'access', _326 => _326.controller, 'access', _327 => _327.activeStroke, 'optionalAccess', _328 => _328.cancel, 'call', _329 => _329()]);
7954
8124
  this.mode = null;
7955
8125
  }
7956
8126
  get active() {
@@ -8011,13 +8181,13 @@ function handlePaintShortcut(controller, gesture, e) {
8011
8181
  return false;
8012
8182
  }
8013
8183
  var PaintCanvasPresenter = (_class12 = class {
8014
- constructor(controller) {;_class12.prototype.__init115.call(this);_class12.prototype.__init116.call(this);_class12.prototype.__init117.call(this);
8184
+ constructor(controller) {;_class12.prototype.__init116.call(this);_class12.prototype.__init117.call(this);_class12.prototype.__init118.call(this);
8015
8185
  this.controller = controller;
8016
8186
  }
8017
8187
 
8018
- __init115() {this.uploaded = /* @__PURE__ */ new Map()}
8019
- __init116() {this.scratch = null}
8020
- __init117() {this.size = ""}
8188
+ __init116() {this.uploaded = /* @__PURE__ */ new Map()}
8189
+ __init117() {this.scratch = null}
8190
+ __init118() {this.size = ""}
8021
8191
  /** Draws what changed into `ctx` (a canvas the size of the document); returns the tiles drawn. */
8022
8192
  render(ctx) {
8023
8193
  const { width, height } = this.controller.document.canvas;
@@ -8084,7 +8254,7 @@ var PAPER_SLIDERS = [
8084
8254
  ];
8085
8255
  function readPath(obj, path) {
8086
8256
  let v = obj;
8087
- for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _325 => _325[k]]);
8257
+ for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _330 => _330[k]]);
8088
8258
  return typeof v === "number" ? v : 0;
8089
8259
  }
8090
8260
  function patchPath(obj, path, value) {
@@ -8206,7 +8376,7 @@ function brushEngineControls(brush) {
8206
8376
  impastoTool: true
8207
8377
  };
8208
8378
  case "wet": {
8209
- const tool = _nullishCoalesce(_optionalChain([brush, 'access', _326 => _326.wet, 'optionalAccess', _327 => _327.tool]), () => ( "paint"));
8379
+ const tool = _nullishCoalesce(_optionalChain([brush, 'access', _331 => _331.wet, 'optionalAccess', _332 => _332.tool]), () => ( "paint"));
8210
8380
  const sliders = tool === "paint" ? [
8211
8381
  { path: "wet.water", label: "Water", min: 0, max: 1, step: 0.01 },
8212
8382
  { path: "wet.pigment", label: "Pigment", min: 0, max: 1, step: 0.01 },
@@ -8339,7 +8509,7 @@ function startWetClock(controller, frame, cancel) {
8339
8509
  id = raf(loop);
8340
8510
  return () => {
8341
8511
  stopped = true;
8342
- _optionalChain([caf, 'optionalCall', _328 => _328(id)]);
8512
+ _optionalChain([caf, 'optionalCall', _333 => _333(id)]);
8343
8513
  };
8344
8514
  }
8345
8515
  function drawWaterOverlay(controller, ctx) {
@@ -8561,6 +8731,39 @@ function createPaintEffectsToolProvider(controller, options = {}) {
8561
8731
  }), { director: false, surface: options.playbackSurface });
8562
8732
  }
8563
8733
 
8734
+ // src/paint-editor/editorDocument.ts
8735
+ function createPaintEditorDocument(controller, options = {}) {
8736
+ return _chunkM4MIZPQIcjs.defineEditorDocument.call(void 0, {
8737
+ kind: "paint",
8738
+ recordsLoads: false,
8739
+ assets: _nullishCoalesce(options.assets, () => ( _chunkM4MIZPQIcjs.createEditorAssetRegistry.call(void 0, ))),
8740
+ get: () => controller.toJSON({ strokes: _nullishCoalesce(options.strokes, () => ( true)) }),
8741
+ load: (document) => {
8742
+ const problems = controller.loadJSON(document);
8743
+ return { problems: problems.map((message) => ({ section: "painting", message })) };
8744
+ },
8745
+ subscribe: (listener) => {
8746
+ let revision = controller.documentRevision;
8747
+ return controller.subscribe(() => {
8748
+ if (controller.documentRevision === revision) return;
8749
+ revision = controller.documentRevision;
8750
+ listener();
8751
+ });
8752
+ },
8753
+ history: {
8754
+ undo: () => controller.undo() !== null,
8755
+ redo: () => controller.redo() !== null,
8756
+ getState: () => {
8757
+ const s = controller.getState();
8758
+ return { canUndo: s.canUndo, canRedo: s.canRedo, ...s.undoLabel ? { undoName: s.undoLabel } : {}, ...s.redoLabel ? { redoName: s.redoLabel } : {} };
8759
+ }
8760
+ },
8761
+ readOnly: () => _nullishCoalesce(controller.busyReason(), () => ( false))
8762
+ });
8763
+ }
8764
+
8765
+
8766
+
8564
8767
 
8565
8768
 
8566
8769
 
@@ -8864,4 +9067,4 @@ function createPaintEffectsToolProvider(controller, options = {}) {
8864
9067
 
8865
9068
 
8866
9069
 
8867
- exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunkCWM3CUUXcjs.BLEND_MODES; exports.BRUSH_ID = _chunkBXMIBMVGcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkBXMIBMVGcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkBXMIBMVGcjs.BUILTIN_BRUSHES; exports.BristleStroke = _chunkBXMIBMVGcjs.BristleStroke; exports.DEFAULT_BEHAVIOR = _chunkBXMIBMVGcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkBXMIBMVGcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkBXMIBMVGcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkBXMIBMVGcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkGNK7SESQcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunkBXMIBMVGcjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunkBXMIBMVGcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkLRRCMRSLcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkLRRCMRSLcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunkBXMIBMVGcjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkBXMIBMVGcjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunkBXMIBMVGcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunkBXMIBMVGcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkGNK7SESQcjs.DEFAULT_WET_PARAMS; exports.DryStroke = _chunkBXMIBMVGcjs.DryStroke; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkLRRCMRSLcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkLRRCMRSLcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunkUKCJ43YLcjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunkBXMIBMVGcjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkBXMIBMVGcjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LitCache = LitCache; exports.MAX_BRUSH_SIZE = _chunkLRRCMRSLcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; 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 = _chunkBXMIBMVGcjs.MULTI_COLOR_MODES; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunkCWM3CUUXcjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunkBXMIBMVGcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkBXMIBMVGcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkLRRCMRSLcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkLRRCMRSLcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkLRRCMRSLcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkLRRCMRSLcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkLRRCMRSLcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkLRRCMRSLcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkLRRCMRSLcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkLRRCMRSLcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkLRRCMRSLcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkLRRCMRSLcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkLRRCMRSLcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkLRRCMRSLcjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = _chunkBXMIBMVGcjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunkBXMIBMVGcjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkBXMIBMVGcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkBXMIBMVGcjs.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 = _chunkLRRCMRSLcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkLRRCMRSLcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkLRRCMRSLcjs.PaperGrain; exports.ParticleStroke = _chunkBXMIBMVGcjs.ParticleStroke; exports.PenDabWalker = _chunkBXMIBMVGcjs.PenDabWalker; exports.PenSmoother = _chunkBXMIBMVGcjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkBXMIBMVGcjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerSpray = _chunkBXMIBMVGcjs.StickerSpray; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunkLRRCMRSLcjs.TileableNoise; exports.WET_FLOW_KINDS = _chunkGNK7SESQcjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunkBXMIBMVGcjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkGNK7SESQcjs.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 = _chunkBXMIBMVGcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkLRRCMRSLcjs.addPaintGradientStop; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.brushEngineControls = brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkBXMIBMVGcjs.brushTakesPaint; exports.brushToJSON = _chunkBXMIBMVGcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = _chunkBXMIBMVGcjs.clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.contactSheet = contactSheet; exports.createPaintCompositor = createPaintCompositor; exports.createPaintDocument = createPaintDocument; 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 = _chunkBXMIBMVGcjs.drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectLayersToJSON = effectLayersToJSON; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkLRRCMRSLcjs.grainCatch; exports.grainHeights = _chunkLRRCMRSLcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunkLRRCMRSLcjs.hash2; exports.hexToPaintRgb = _chunkLRRCMRSLcjs.hexToPaintRgb; exports.hexToRgb8 = _chunkBXMIBMVGcjs.hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunkUKCJ43YLcjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunkCWM3CUUXcjs.isBlendMode; exports.isGradientPaint = _chunkLRRCMRSLcjs.isGradientPaint; exports.isPainterlyBlendMode = _chunkCWM3CUUXcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkBXMIBMVGcjs.isWetBrush; exports.isWetCapable = _chunkBXMIBMVGcjs.isWetCapable; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.mapPenPoint = mapPenPoint; exports.mix32 = _chunkLRRCMRSLcjs.mix32; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = _chunkBXMIBMVGcjs.mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = multiColorSliders; exports.multiColorToPaint = _chunkBXMIBMVGcjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkBXMIBMVGcjs.normalizeBehavior; exports.normalizeBristle = _chunkBXMIBMVGcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkBXMIBMVGcjs.normalizeDynamics; exports.normalizeFlow = _chunkGNK7SESQcjs.normalizeFlow; exports.normalizeHexColor = _chunkLRRCMRSLcjs.normalizeHexColor; exports.normalizeImpasto = _chunkBXMIBMVGcjs.normalizeImpasto; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunkBXMIBMVGcjs.normalizeMultiColor; exports.normalizePaintBrush = _chunkBXMIBMVGcjs.normalizePaintBrush; exports.normalizePaper = _chunkBXMIBMVGcjs.normalizePaper; exports.normalizeParticle = _chunkBXMIBMVGcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkBXMIBMVGcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = _chunkBXMIBMVGcjs.normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunkBXMIBMVGcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkGNK7SESQcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkLRRCMRSLcjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintSourceColor = _chunkLRRCMRSLcjs.paintSourceColor; exports.paintSourceCss = _chunkLRRCMRSLcjs.paintSourceCss; exports.paintToMultiColor = _chunkBXMIBMVGcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunkBXMIBMVGcjs.paperPreset; exports.parseBrushLibrary = _chunkBXMIBMVGcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkLRRCMRSLcjs.parsePaintSource; exports.patchBrushValue = patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunkBXMIBMVGcjs.penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.quickStencil = quickStencil; exports.rand01 = _chunkLRRCMRSLcjs.rand01; exports.randSigned = _chunkLRRCMRSLcjs.randSigned; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkLRRCMRSLcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkLRRCMRSLcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunkBXMIBMVGcjs.renderPaper; exports.renderStickers = _chunkBXMIBMVGcjs.renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkLRRCMRSLcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkLRRCMRSLcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkLRRCMRSLcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunkLRRCMRSLcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkLRRCMRSLcjs.solidPaint; exports.stampCoverage = _chunkBXMIBMVGcjs.stampCoverage; exports.standardBlendMode = _chunkCWM3CUUXcjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerRect = _chunkBXMIBMVGcjs.stickerRect; exports.stickerSurface = _chunkBXMIBMVGcjs.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 = _chunkBXMIBMVGcjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunkBXMIBMVGcjs.toStrokePoint; exports.toggleStamp = toggleStamp; exports.updatePaintGradientStop = _chunkLRRCMRSLcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkBXMIBMVGcjs.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 = _chunkGNK7SESQcjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunkUKCJ43YLcjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;
9070
+ exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunkCWM3CUUXcjs.BLEND_MODES; exports.BRUSH_ID = _chunkJGKCC5OFcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkJGKCC5OFcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkJGKCC5OFcjs.BUILTIN_BRUSHES; exports.BristleStroke = _chunkJGKCC5OFcjs.BristleStroke; exports.DEFAULT_BEHAVIOR = _chunkJGKCC5OFcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkJGKCC5OFcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkJGKCC5OFcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkJGKCC5OFcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkGNK7SESQcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunkJGKCC5OFcjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunkJGKCC5OFcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkEBDCRTZIcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkEBDCRTZIcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunkJGKCC5OFcjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkJGKCC5OFcjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunkJGKCC5OFcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunkJGKCC5OFcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkGNK7SESQcjs.DEFAULT_WET_PARAMS; exports.DryStroke = _chunkJGKCC5OFcjs.DryStroke; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkEBDCRTZIcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkEBDCRTZIcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunkUKCJ43YLcjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunkJGKCC5OFcjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkJGKCC5OFcjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LitCache = LitCache; exports.MAX_BRUSH_SIZE = _chunkEBDCRTZIcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; 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 = _chunkJGKCC5OFcjs.MULTI_COLOR_MODES; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunkCWM3CUUXcjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunkJGKCC5OFcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkJGKCC5OFcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkEBDCRTZIcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkEBDCRTZIcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkEBDCRTZIcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkEBDCRTZIcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkEBDCRTZIcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkEBDCRTZIcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkEBDCRTZIcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkEBDCRTZIcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkEBDCRTZIcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkEBDCRTZIcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkEBDCRTZIcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkEBDCRTZIcjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = _chunkJGKCC5OFcjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunkJGKCC5OFcjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkJGKCC5OFcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkJGKCC5OFcjs.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 = _chunkEBDCRTZIcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkEBDCRTZIcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkEBDCRTZIcjs.PaperGrain; exports.ParticleStroke = _chunkJGKCC5OFcjs.ParticleStroke; exports.PenDabWalker = _chunkJGKCC5OFcjs.PenDabWalker; exports.PenSmoother = _chunkJGKCC5OFcjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkJGKCC5OFcjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerSpray = _chunkJGKCC5OFcjs.StickerSpray; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunkEBDCRTZIcjs.TileableNoise; exports.WET_FLOW_KINDS = _chunkGNK7SESQcjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunkJGKCC5OFcjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkGNK7SESQcjs.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 = _chunkJGKCC5OFcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkEBDCRTZIcjs.addPaintGradientStop; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.brushEngineControls = brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkJGKCC5OFcjs.brushTakesPaint; exports.brushToJSON = _chunkJGKCC5OFcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = _chunkJGKCC5OFcjs.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 = _chunkJGKCC5OFcjs.drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectLayersToJSON = effectLayersToJSON; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkEBDCRTZIcjs.grainCatch; exports.grainHeights = _chunkEBDCRTZIcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunkEBDCRTZIcjs.hash2; exports.hexToPaintRgb = _chunkEBDCRTZIcjs.hexToPaintRgb; exports.hexToRgb8 = _chunkJGKCC5OFcjs.hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunkUKCJ43YLcjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunkCWM3CUUXcjs.isBlendMode; exports.isGradientPaint = _chunkEBDCRTZIcjs.isGradientPaint; exports.isPainterlyBlendMode = _chunkCWM3CUUXcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkJGKCC5OFcjs.isWetBrush; exports.isWetCapable = _chunkJGKCC5OFcjs.isWetCapable; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.mapPenPoint = mapPenPoint; exports.mix32 = _chunkEBDCRTZIcjs.mix32; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = _chunkJGKCC5OFcjs.mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = multiColorSliders; exports.multiColorToPaint = _chunkJGKCC5OFcjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkJGKCC5OFcjs.normalizeBehavior; exports.normalizeBristle = _chunkJGKCC5OFcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkJGKCC5OFcjs.normalizeDynamics; exports.normalizeFlow = _chunkGNK7SESQcjs.normalizeFlow; exports.normalizeHexColor = _chunkEBDCRTZIcjs.normalizeHexColor; exports.normalizeImpasto = _chunkJGKCC5OFcjs.normalizeImpasto; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunkJGKCC5OFcjs.normalizeMultiColor; exports.normalizePaintBrush = _chunkJGKCC5OFcjs.normalizePaintBrush; exports.normalizePaper = _chunkJGKCC5OFcjs.normalizePaper; exports.normalizeParticle = _chunkJGKCC5OFcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkJGKCC5OFcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = _chunkJGKCC5OFcjs.normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunkJGKCC5OFcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkGNK7SESQcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkEBDCRTZIcjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintSourceColor = _chunkEBDCRTZIcjs.paintSourceColor; exports.paintSourceCss = _chunkEBDCRTZIcjs.paintSourceCss; exports.paintToMultiColor = _chunkJGKCC5OFcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunkJGKCC5OFcjs.paperPreset; exports.parseBrushLibrary = _chunkJGKCC5OFcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkEBDCRTZIcjs.parsePaintSource; exports.patchBrushValue = patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunkJGKCC5OFcjs.penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.quickStencil = quickStencil; exports.rand01 = _chunkEBDCRTZIcjs.rand01; exports.randSigned = _chunkEBDCRTZIcjs.randSigned; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkEBDCRTZIcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkEBDCRTZIcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunkJGKCC5OFcjs.renderPaper; exports.renderStickers = _chunkJGKCC5OFcjs.renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkEBDCRTZIcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkEBDCRTZIcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkEBDCRTZIcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunkEBDCRTZIcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkEBDCRTZIcjs.solidPaint; exports.stampCoverage = _chunkJGKCC5OFcjs.stampCoverage; exports.standardBlendMode = _chunkCWM3CUUXcjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerRect = _chunkJGKCC5OFcjs.stickerRect; exports.stickerSurface = _chunkJGKCC5OFcjs.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 = _chunkJGKCC5OFcjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunkJGKCC5OFcjs.toStrokePoint; exports.toggleStamp = toggleStamp; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkEBDCRTZIcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkJGKCC5OFcjs.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 = _chunkGNK7SESQcjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunkUKCJ43YLcjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;