pixel-data-js 0.28.0 → 0.30.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.
@@ -65,6 +65,8 @@ __export(src_exports, {
65
65
  colorDistance: () => colorDistance,
66
66
  colorDodgeFast: () => colorDodgeFast,
67
67
  colorDodgePerfect: () => colorDodgePerfect,
68
+ commitColorPaintBuffer: () => commitColorPaintBuffer,
69
+ commitMaskPaintBuffer: () => commitMaskPaintBuffer,
68
70
  copyImageData: () => copyImageData,
69
71
  copyImageDataLike: () => copyImageDataLike,
70
72
  copyMask: () => copyMask,
@@ -137,11 +139,15 @@ __export(src_exports, {
137
139
  linearLightPerfect: () => linearLightPerfect,
138
140
  makeAlphaMask: () => makeAlphaMask,
139
141
  makeAlphaMaskPaintBufferCanvasRenderer: () => makeAlphaMaskPaintBufferCanvasRenderer,
142
+ makeAlphaMaskPaintBufferCommitter: () => makeAlphaMaskPaintBufferCommitter,
143
+ makeAlphaMaskPaintBufferManager: () => makeAlphaMaskPaintBufferManager,
140
144
  makeAlphaMaskTile: () => makeAlphaMaskTile,
141
145
  makeBinaryMask: () => makeBinaryMask,
142
146
  makeBinaryMaskFromAlphaMask: () => makeBinaryMaskFromAlphaMask,
143
147
  makeBinaryMaskOutline: () => makeBinaryMaskOutline,
144
148
  makeBinaryMaskPaintBufferCanvasRenderer: () => makeBinaryMaskPaintBufferCanvasRenderer,
149
+ makeBinaryMaskPaintBufferCommitter: () => makeBinaryMaskPaintBufferCommitter,
150
+ makeBinaryMaskPaintBufferManager: () => makeBinaryMaskPaintBufferManager,
145
151
  makeBinaryMaskTile: () => makeBinaryMaskTile,
146
152
  makeBlendModeRegistry: () => makeBlendModeRegistry,
147
153
  makeCanvasFrameRenderer: () => makeCanvasFrameRenderer,
@@ -152,6 +158,8 @@ __export(src_exports, {
152
158
  makeClippedBlit: () => makeClippedBlit,
153
159
  makeClippedRect: () => makeClippedRect,
154
160
  makeColorPaintBufferCanvasRenderer: () => makeColorPaintBufferCanvasRenderer,
161
+ makeColorPaintBufferCommitter: () => makeColorPaintBufferCommitter,
162
+ makeColorPaintBufferManager: () => makeColorPaintBufferManager,
155
163
  makeFastBlendModeRegistry: () => makeFastBlendModeRegistry,
156
164
  makeFullPixelMutator: () => makeFullPixelMutator,
157
165
  makeHistoryAction: () => makeHistoryAction,
@@ -2176,13 +2184,13 @@ function makeReusableCanvasMeta(factory) {
2176
2184
 
2177
2185
  // src/Canvas/CanvasFrameRenderer.ts
2178
2186
  function makeCanvasFrameRenderer(reusableCanvasFactory = makeReusableOffscreenCanvas) {
2179
- const bufferCanvas = reusableCanvasFactory();
2187
+ const getBuffer = reusableCanvasFactory();
2180
2188
  return function renderCanvasFrame(pixelCanvas, scale, getImageData, drawPixelLayer, drawScreenLayer) {
2181
2189
  const canvas = pixelCanvas.canvas;
2182
2190
  const ctx = pixelCanvas.ctx;
2183
2191
  const w = canvas.width;
2184
2192
  const h = canvas.height;
2185
- const buffer = bufferCanvas(w, h);
2193
+ const buffer = getBuffer(w, h);
2186
2194
  const img = getImageData();
2187
2195
  if (img) {
2188
2196
  buffer.ctx.putImageData(img, 0, 0);
@@ -2307,19 +2315,17 @@ function applyPatchTiles(target, tiles, tileSize) {
2307
2315
  }
2308
2316
 
2309
2317
  // src/History/HistoryAction.ts
2310
- function makeHistoryAction(config, accumulator, patch, after, afterUndo, afterRedo, applyPatchTilesFn = applyPatchTiles) {
2318
+ function makeHistoryAction(config, accumulator, patch, afterUndo, afterRedo, applyPatchTilesFn = applyPatchTiles) {
2311
2319
  const target = config.target;
2312
2320
  const tileSize = config.tileSize;
2313
2321
  return {
2314
2322
  undo: () => {
2315
2323
  applyPatchTilesFn(target, patch.beforeTiles, tileSize);
2316
- afterUndo?.();
2317
- after?.();
2324
+ afterUndo?.(patch);
2318
2325
  },
2319
2326
  redo: () => {
2320
2327
  applyPatchTilesFn(target, patch.afterTiles, tileSize);
2321
- afterRedo?.();
2322
- after?.();
2328
+ afterRedo?.(patch);
2323
2329
  },
2324
2330
  dispose: () => accumulator.recyclePatch(patch)
2325
2331
  };
@@ -5269,7 +5275,6 @@ var AlphaMaskPaintBuffer = class {
5269
5275
  w: 0,
5270
5276
  h: 0
5271
5277
  };
5272
- blendColorPixelDataAlphaMaskFn = blendColorPixelDataAlphaMask;
5273
5278
  forEachLinePointFn = forEachLinePoint;
5274
5279
  trimRectBoundsFn = trimRectBounds;
5275
5280
  eachTileInBoundsFn = eachTileInBounds;
@@ -5408,88 +5413,11 @@ var AlphaMaskPaintBuffer = class {
5408
5413
  });
5409
5414
  return changed;
5410
5415
  }
5411
- opts = {
5412
- alpha: 255,
5413
- blendFn: sourceOverPerfect,
5414
- x: 0,
5415
- y: 0,
5416
- w: 0,
5417
- h: 0
5418
- };
5419
- commit(accumulator, color, alpha = 255, blendFn = sourceOverPerfect) {
5420
- const blendColorPixelDataAlphaMaskFn = this.blendColorPixelDataAlphaMaskFn;
5421
- const tileShift = this.config.tileShift;
5422
- const lookup = this.lookup;
5423
- const opts = this.opts;
5424
- opts.alpha = alpha;
5425
- opts.blendFn = blendFn;
5426
- for (let i = 0; i < lookup.length; i++) {
5427
- const tile = lookup[i];
5428
- if (tile) {
5429
- const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5430
- const dx = tile.tx << tileShift;
5431
- const dy = tile.ty << tileShift;
5432
- opts.x = dx;
5433
- opts.y = dy;
5434
- opts.w = tile.w;
5435
- opts.h = tile.h;
5436
- didChange(blendColorPixelDataAlphaMaskFn(this.config.target, color, tile, opts));
5437
- }
5438
- }
5439
- this.clear();
5440
- }
5441
5416
  clear() {
5442
5417
  this.tilePool.releaseTiles(this.lookup);
5443
5418
  }
5444
5419
  };
5445
5420
 
5446
- // src/Paint/AlphaMaskPaintBufferCanvasRenderer.ts
5447
- function makeAlphaMaskPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
5448
- const config = paintBuffer.config;
5449
- const tileSize = config.tileSize;
5450
- const tileShift = config.tileShift;
5451
- const tileArea = config.tileArea;
5452
- const lookup = paintBuffer.lookup;
5453
- const canvas = new offscreenCanvasClass(tileSize, tileSize);
5454
- const ctx = canvas.getContext("2d");
5455
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5456
- ctx.imageSmoothingEnabled = false;
5457
- const bridge = makePixelData(new ImageData(tileSize, tileSize));
5458
- const view32 = bridge.data;
5459
- return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5460
- if (alpha === 0) return;
5461
- const baseSrcAlpha = color >>> 24;
5462
- const colorRGB = color & 16777215;
5463
- if (baseSrcAlpha === 0) return;
5464
- targetCtx.globalAlpha = alpha / 255;
5465
- targetCtx.globalCompositeOperation = compOperation;
5466
- for (let i = 0; i < lookup.length; i++) {
5467
- const tile = lookup[i];
5468
- if (tile) {
5469
- const data8 = tile.data;
5470
- view32.fill(0);
5471
- for (let p = 0; p < tileArea; p++) {
5472
- const maskA = data8[p];
5473
- if (maskA === 0) continue;
5474
- if (maskA === 255) {
5475
- view32[p] = color;
5476
- } else {
5477
- const t = baseSrcAlpha * maskA + 128;
5478
- const finalA = t + (t >> 8) >> 8;
5479
- view32[p] = (colorRGB | finalA << 24) >>> 0;
5480
- }
5481
- }
5482
- const dx = tile.tx << tileShift;
5483
- const dy = tile.ty << tileShift;
5484
- ctx.putImageData(bridge.imageData, 0, 0);
5485
- targetCtx.drawImage(canvas, dx, dy);
5486
- }
5487
- }
5488
- targetCtx.globalAlpha = 1;
5489
- targetCtx.globalCompositeOperation = "source-over";
5490
- };
5491
- }
5492
-
5493
5421
  // src/Paint/BinaryMaskPaintBuffer.ts
5494
5422
  var BinaryMaskPaintBuffer = class {
5495
5423
  constructor(config, tilePool) {
@@ -5504,7 +5432,6 @@ var BinaryMaskPaintBuffer = class {
5504
5432
  w: 0,
5505
5433
  h: 0
5506
5434
  };
5507
- blendColorPixelDataBinaryMaskFn = blendColorPixelDataBinaryMask;
5508
5435
  forEachLinePointFn = forEachLinePoint;
5509
5436
  trimRectBoundsFn = trimRectBounds;
5510
5437
  eachTileInBoundsFn = eachTileInBounds;
@@ -5595,87 +5522,16 @@ var BinaryMaskPaintBuffer = class {
5595
5522
  });
5596
5523
  return changed;
5597
5524
  }
5598
- opts = {
5599
- alpha: 255,
5600
- blendFn: sourceOverPerfect,
5601
- x: 0,
5602
- y: 0,
5603
- w: 0,
5604
- h: 0
5605
- };
5606
- commit(accumulator, color, alpha = 255, blendFn = sourceOverPerfect) {
5607
- const blendColorPixelDataBinaryMaskFn = this.blendColorPixelDataBinaryMaskFn;
5608
- const tileShift = this.config.tileShift;
5609
- const lookup = this.lookup;
5610
- const opts = this.opts;
5611
- opts.alpha = alpha;
5612
- opts.blendFn = blendFn;
5613
- for (let i = 0; i < lookup.length; i++) {
5614
- const tile = lookup[i];
5615
- if (tile) {
5616
- const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5617
- const dx = tile.tx << tileShift;
5618
- const dy = tile.ty << tileShift;
5619
- opts.x = dx;
5620
- opts.y = dy;
5621
- opts.w = tile.w;
5622
- opts.h = tile.h;
5623
- didChange(blendColorPixelDataBinaryMaskFn(this.config.target, color, tile, opts));
5624
- }
5625
- }
5626
- this.clear();
5627
- }
5628
5525
  clear() {
5629
5526
  this.tilePool.releaseTiles(this.lookup);
5630
5527
  }
5631
5528
  };
5632
5529
 
5633
- // src/Paint/BinaryMaskPaintBufferCanvasRenderer.ts
5634
- function makeBinaryMaskPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
5635
- const config = paintBuffer.config;
5636
- const tileSize = config.tileSize;
5637
- const tileShift = config.tileShift;
5638
- const tileArea = config.tileArea;
5639
- const lookup = paintBuffer.lookup;
5640
- const canvas = new offscreenCanvasClass(tileSize, tileSize);
5641
- const ctx = canvas.getContext("2d");
5642
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5643
- ctx.imageSmoothingEnabled = false;
5644
- const bridge = makePixelData(new ImageData(tileSize, tileSize));
5645
- const view32 = bridge.data;
5646
- return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5647
- if (alpha === 0) return;
5648
- const baseSrcAlpha = color >>> 24;
5649
- if (baseSrcAlpha === 0) return;
5650
- targetCtx.globalAlpha = alpha / 255;
5651
- targetCtx.globalCompositeOperation = compOperation;
5652
- for (let i = 0; i < lookup.length; i++) {
5653
- const tile = lookup[i];
5654
- if (tile) {
5655
- const data8 = tile.data;
5656
- view32.fill(0);
5657
- for (let p = 0; p < tileArea; p++) {
5658
- if (data8[p] === 1) {
5659
- view32[p] = color;
5660
- }
5661
- }
5662
- const dx = tile.tx << tileShift;
5663
- const dy = tile.ty << tileShift;
5664
- ctx.putImageData(bridge.imageData, 0, 0);
5665
- targetCtx.drawImage(canvas, dx, dy);
5666
- }
5667
- }
5668
- targetCtx.globalAlpha = 1;
5669
- targetCtx.globalCompositeOperation = "source-over";
5670
- };
5671
- }
5672
-
5673
5530
  // src/Paint/ColorPaintBuffer.ts
5674
5531
  var ColorPaintBuffer = class {
5675
- constructor(config, tilePool, blendPixelDataFn = blendPixelData) {
5532
+ constructor(config, tilePool) {
5676
5533
  this.config = config;
5677
5534
  this.tilePool = tilePool;
5678
- this.blendPixelDataFn = blendPixelDataFn;
5679
5535
  this.lookup = [];
5680
5536
  }
5681
5537
  lookup;
@@ -5826,48 +5682,246 @@ var ColorPaintBuffer = class {
5826
5682
  });
5827
5683
  return changed;
5828
5684
  }
5829
- opts = {
5830
- alpha: 255,
5831
- blendFn: sourceOverPerfect,
5832
- x: 0,
5833
- y: 0,
5834
- w: 0,
5835
- h: 0
5685
+ clear() {
5686
+ this.tilePool.releaseTiles(this.lookup);
5687
+ }
5688
+ };
5689
+
5690
+ // src/Paint/Commit/commitMaskPaintBuffer.ts
5691
+ var SCRATCH_OPTS = {
5692
+ alpha: 255,
5693
+ blendFn: sourceOverPerfect,
5694
+ x: 0,
5695
+ y: 0,
5696
+ w: 0,
5697
+ h: 0
5698
+ };
5699
+ function commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha = 255, blendFn = sourceOverPerfect, blendColorPixelDataMaskFn) {
5700
+ const config = accumulator.config;
5701
+ const tileShift = config.tileShift;
5702
+ const lookup = paintBuffer.lookup;
5703
+ SCRATCH_OPTS.alpha = alpha;
5704
+ SCRATCH_OPTS.blendFn = blendFn;
5705
+ for (let i = 0; i < lookup.length; i++) {
5706
+ const tile = lookup[i];
5707
+ if (tile) {
5708
+ const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5709
+ const dx = tile.tx << tileShift;
5710
+ const dy = tile.ty << tileShift;
5711
+ SCRATCH_OPTS.x = dx;
5712
+ SCRATCH_OPTS.y = dy;
5713
+ SCRATCH_OPTS.w = tile.w;
5714
+ SCRATCH_OPTS.h = tile.h;
5715
+ didChange(blendColorPixelDataMaskFn(config.target, color, tile, SCRATCH_OPTS));
5716
+ }
5717
+ }
5718
+ paintBuffer.clear();
5719
+ }
5720
+
5721
+ // src/Paint/Commit/AlphaMaskPaintBufferCommitter.ts
5722
+ function makeAlphaMaskPaintBufferCommitter(accumulator, paintBuffer) {
5723
+ return function commitAlphaMaskPaintBufferToAccumulator(color, alpha = 255, blendFn = sourceOverPerfect) {
5724
+ return commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha, blendFn, blendColorPixelDataAlphaMask);
5836
5725
  };
5837
- commit(accumulator, alpha = 255, blendFn = sourceOverPerfect) {
5838
- const tileShift = this.config.tileShift;
5839
- const lookup = this.lookup;
5840
- const opts = this.opts;
5841
- const blendPixelDataFn = this.blendPixelDataFn;
5842
- opts.alpha = alpha;
5843
- opts.blendFn = blendFn;
5726
+ }
5727
+
5728
+ // src/Internal/_constants.ts
5729
+ var DEFAULT_CANVAS_FACTORY = (w, h) => new OffscreenCanvas(w, h);
5730
+
5731
+ // src/Tile/MaskTile.ts
5732
+ var makeAlphaMaskTile = (id, tx, ty, tileSize, tileArea) => {
5733
+ return {
5734
+ tileType: 1 /* MASK */,
5735
+ type: 0 /* ALPHA */,
5736
+ data: new Uint8Array(tileArea),
5737
+ w: tileSize,
5738
+ h: tileSize,
5739
+ id,
5740
+ tx,
5741
+ ty
5742
+ };
5743
+ };
5744
+ var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
5745
+ return {
5746
+ tileType: 1 /* MASK */,
5747
+ type: 1 /* BINARY */,
5748
+ data: new Uint8Array(tileArea),
5749
+ w: tileSize,
5750
+ h: tileSize,
5751
+ id,
5752
+ tx,
5753
+ ty
5754
+ };
5755
+ };
5756
+
5757
+ // src/Paint/Render/AlphaMaskPaintBufferCanvasRenderer.ts
5758
+ function makeAlphaMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5759
+ const config = paintBuffer.config;
5760
+ const tileSize = config.tileSize;
5761
+ const tileShift = config.tileShift;
5762
+ const tileArea = config.tileArea;
5763
+ const lookup = paintBuffer.lookup;
5764
+ const canvas = canvasFactory(tileSize, tileSize);
5765
+ const ctx = canvas.getContext("2d");
5766
+ if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5767
+ ctx.imageSmoothingEnabled = false;
5768
+ const bridge = makePixelData(new ImageData(tileSize, tileSize));
5769
+ const view32 = bridge.data;
5770
+ return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5771
+ if (alpha === 0) return;
5772
+ const baseSrcAlpha = color >>> 24;
5773
+ const colorRGB = color & 16777215;
5774
+ if (baseSrcAlpha === 0) return;
5775
+ targetCtx.globalAlpha = alpha / 255;
5776
+ targetCtx.globalCompositeOperation = compOperation;
5844
5777
  for (let i = 0; i < lookup.length; i++) {
5845
5778
  const tile = lookup[i];
5846
5779
  if (tile) {
5847
- const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5780
+ const data8 = tile.data;
5781
+ view32.fill(0);
5782
+ for (let p = 0; p < tileArea; p++) {
5783
+ const maskA = data8[p];
5784
+ if (maskA === 0) continue;
5785
+ if (maskA === 255) {
5786
+ view32[p] = color;
5787
+ } else {
5788
+ const t = baseSrcAlpha * maskA + 128;
5789
+ const finalA = t + (t >> 8) >> 8;
5790
+ view32[p] = (colorRGB | finalA << 24) >>> 0;
5791
+ }
5792
+ }
5848
5793
  const dx = tile.tx << tileShift;
5849
5794
  const dy = tile.ty << tileShift;
5850
- opts.x = dx;
5851
- opts.y = dy;
5852
- opts.w = tile.w;
5853
- opts.h = tile.h;
5854
- didChange(blendPixelDataFn(this.config.target, tile, opts));
5795
+ ctx.putImageData(bridge.imageData, 0, 0);
5796
+ targetCtx.drawImage(canvas, dx, dy);
5855
5797
  }
5856
5798
  }
5857
- this.clear();
5858
- }
5859
- clear() {
5860
- this.tilePool.releaseTiles(this.lookup);
5861
- }
5799
+ targetCtx.globalAlpha = 1;
5800
+ targetCtx.globalCompositeOperation = "source-over";
5801
+ };
5802
+ }
5803
+
5804
+ // src/Paint/Commit/AlphaMaskPaintBufferManager.ts
5805
+ function makeAlphaMaskPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5806
+ const pool = new TilePool(writer.config, makeAlphaMaskTile);
5807
+ const buffer = new AlphaMaskPaintBuffer(writer.config, pool);
5808
+ const draw = makeAlphaMaskPaintBufferCanvasRenderer(buffer, canvasFactory);
5809
+ return {
5810
+ clear: buffer.clear.bind(buffer),
5811
+ paintRect: buffer.paintRect.bind(buffer),
5812
+ paintAlphaMask: buffer.paintAlphaMask.bind(buffer),
5813
+ paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5814
+ commit: makeAlphaMaskPaintBufferCommitter(writer.accumulator, buffer),
5815
+ draw
5816
+ };
5817
+ }
5818
+
5819
+ // src/Paint/Commit/BinaryMaskPaintBufferCommitter.ts
5820
+ function makeBinaryMaskPaintBufferCommitter(accumulator, paintBuffer) {
5821
+ return function commitBinaryMaskPaintBufferToAccumulator(color, alpha = 255, blendFn = sourceOverPerfect) {
5822
+ return commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha, blendFn, blendColorPixelDataBinaryMask);
5823
+ };
5824
+ }
5825
+
5826
+ // src/Paint/Render/BinaryMaskPaintBufferCanvasRenderer.ts
5827
+ function makeBinaryMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5828
+ const config = paintBuffer.config;
5829
+ const tileSize = config.tileSize;
5830
+ const tileShift = config.tileShift;
5831
+ const tileArea = config.tileArea;
5832
+ const lookup = paintBuffer.lookup;
5833
+ const canvas = canvasFactory(tileSize, tileSize);
5834
+ const ctx = canvas.getContext("2d");
5835
+ if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5836
+ ctx.imageSmoothingEnabled = false;
5837
+ const bridge = makePixelData(new ImageData(tileSize, tileSize));
5838
+ const view32 = bridge.data;
5839
+ return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5840
+ if (alpha === 0) return;
5841
+ const baseSrcAlpha = color >>> 24;
5842
+ if (baseSrcAlpha === 0) return;
5843
+ targetCtx.globalAlpha = alpha / 255;
5844
+ targetCtx.globalCompositeOperation = compOperation;
5845
+ for (let i = 0; i < lookup.length; i++) {
5846
+ const tile = lookup[i];
5847
+ if (tile) {
5848
+ const data8 = tile.data;
5849
+ view32.fill(0);
5850
+ for (let p = 0; p < tileArea; p++) {
5851
+ if (data8[p] === 1) {
5852
+ view32[p] = color;
5853
+ }
5854
+ }
5855
+ const dx = tile.tx << tileShift;
5856
+ const dy = tile.ty << tileShift;
5857
+ ctx.putImageData(bridge.imageData, 0, 0);
5858
+ targetCtx.drawImage(canvas, dx, dy);
5859
+ }
5860
+ }
5861
+ targetCtx.globalAlpha = 1;
5862
+ targetCtx.globalCompositeOperation = "source-over";
5863
+ };
5864
+ }
5865
+
5866
+ // src/Paint/Commit/BinaryMaskPaintBufferManager.ts
5867
+ function makeBinaryMaskPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5868
+ const pool = new TilePool(writer.config, makeBinaryMaskTile);
5869
+ const buffer = new BinaryMaskPaintBuffer(writer.config, pool);
5870
+ const draw = makeBinaryMaskPaintBufferCanvasRenderer(buffer, canvasFactory);
5871
+ return {
5872
+ clear: buffer.clear.bind(buffer),
5873
+ paintRect: buffer.paintRect.bind(buffer),
5874
+ paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5875
+ commit: makeBinaryMaskPaintBufferCommitter(writer.accumulator, buffer),
5876
+ draw
5877
+ };
5878
+ }
5879
+
5880
+ // src/Paint/Commit/commitColorPaintBuffer.ts
5881
+ var SCRATCH_OPTS2 = {
5882
+ alpha: 255,
5883
+ blendFn: sourceOverPerfect,
5884
+ x: 0,
5885
+ y: 0,
5886
+ w: 0,
5887
+ h: 0
5862
5888
  };
5889
+ function commitColorPaintBuffer(accumulator, paintBuffer, alpha = 255, blendFn = sourceOverPerfect, blendPixelDataFn = blendPixelData) {
5890
+ const config = accumulator.config;
5891
+ const tileShift = config.tileShift;
5892
+ const lookup = paintBuffer.lookup;
5893
+ SCRATCH_OPTS2.alpha = alpha;
5894
+ SCRATCH_OPTS2.blendFn = blendFn;
5895
+ for (let i = 0; i < lookup.length; i++) {
5896
+ const tile = lookup[i];
5897
+ if (tile) {
5898
+ const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5899
+ const dx = tile.tx << tileShift;
5900
+ const dy = tile.ty << tileShift;
5901
+ SCRATCH_OPTS2.x = dx;
5902
+ SCRATCH_OPTS2.y = dy;
5903
+ SCRATCH_OPTS2.w = tile.w;
5904
+ SCRATCH_OPTS2.h = tile.h;
5905
+ didChange(blendPixelDataFn(config.target, tile, SCRATCH_OPTS2));
5906
+ }
5907
+ }
5908
+ paintBuffer.clear();
5909
+ }
5863
5910
 
5864
- // src/Paint/ColorPaintBufferCanvasRenderer.ts
5865
- function makeColorPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
5911
+ // src/Paint/Commit/ColorPaintBufferCommitter.ts
5912
+ function makeColorPaintBufferCommitter(accumulator, paintBuffer) {
5913
+ return function commitColorPaintBufferToAccumulator(alpha = 255, blendFn = sourceOverPerfect) {
5914
+ return commitColorPaintBuffer(accumulator, paintBuffer, alpha, blendFn, blendPixelData);
5915
+ };
5916
+ }
5917
+
5918
+ // src/Paint/Render/ColorPaintBufferCanvasRenderer.ts
5919
+ function makeColorPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5866
5920
  const config = paintBuffer.config;
5867
5921
  const tileSize = config.tileSize;
5868
5922
  const tileShift = config.tileShift;
5869
5923
  const lookup = paintBuffer.lookup;
5870
- const canvas = new offscreenCanvasClass(tileSize, tileSize);
5924
+ const canvas = canvasFactory(tileSize, tileSize);
5871
5925
  const ctx = canvas.getContext("2d");
5872
5926
  if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5873
5927
  ctx.imageSmoothingEnabled = false;
@@ -5888,6 +5942,21 @@ function makeColorPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass =
5888
5942
  };
5889
5943
  }
5890
5944
 
5945
+ // src/Paint/Commit/ColorPaintBufferManager.ts
5946
+ function makeColorPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5947
+ const pool = new TilePool(writer.config, makePixelTile);
5948
+ const buffer = new ColorPaintBuffer(writer.config, pool);
5949
+ const draw = makeColorPaintBufferCanvasRenderer(buffer, canvasFactory);
5950
+ return {
5951
+ clear: buffer.clear.bind(buffer),
5952
+ paintRect: buffer.paintRect.bind(buffer),
5953
+ paintAlphaMask: buffer.paintAlphaMask.bind(buffer),
5954
+ paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5955
+ commit: makeColorPaintBufferCommitter(writer.accumulator, buffer),
5956
+ draw
5957
+ };
5958
+ }
5959
+
5891
5960
  // src/Paint/makeCirclePaintMask.ts
5892
5961
  function makeCirclePaintAlphaMask(size, fallOff = (d) => d) {
5893
5962
  const area = size * size;
@@ -6025,12 +6094,14 @@ function makeReusablePixelData() {
6025
6094
  };
6026
6095
  }
6027
6096
 
6028
- // src/Paint/PaintCursorRenderer.ts
6029
- function makePaintCursorRenderer(factory = (w, h) => new OffscreenCanvas(w, h)) {
6030
- const canvas = factory(1, 1);
6031
- const ctx = canvas.getContext("2d");
6032
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
6033
- ctx.imageSmoothingEnabled = false;
6097
+ // src/Paint/Render/PaintCursorRenderer.ts
6098
+ function makePaintCursorRenderer(reusableCanvasFactory) {
6099
+ const factory = reusableCanvasFactory ?? makeReusableOffscreenCanvas;
6100
+ const updateBuffer = factory();
6101
+ const {
6102
+ canvas,
6103
+ ctx
6104
+ } = updateBuffer(1, 1);
6034
6105
  const getPixelData = makeReusablePixelData();
6035
6106
  let _color = packColor(0, 255, 255, 255);
6036
6107
  let _scale = 1;
@@ -6047,8 +6118,7 @@ function makePaintCursorRenderer(factory = (w, h) => new OffscreenCanvas(w, h))
6047
6118
  currentMask = paintMask ?? currentMask;
6048
6119
  _scale = scale ?? _scale;
6049
6120
  _color = color ?? _color;
6050
- canvas.width = currentMask.w * _scale + 2 * _scale;
6051
- canvas.height = currentMask.h * _scale + 2 * _scale;
6121
+ updateBuffer(currentMask.w * _scale + 2 * _scale, currentMask.h * _scale + 2 * _scale);
6052
6122
  if (currentMask.type === 1 /* BINARY */) {
6053
6123
  if (currentMask.outlineType === 1 /* CIRCLE */) {
6054
6124
  outline = makeCircleBinaryMaskOutline(currentMask.w, _scale);
@@ -6131,7 +6201,7 @@ function blendColorPixelDataMask(dst, color, mask, opts) {
6131
6201
  }
6132
6202
 
6133
6203
  // src/PixelData/blendColorPixelDataPaintAlphaMask.ts
6134
- var SCRATCH_OPTS = {
6204
+ var SCRATCH_OPTS3 = {
6135
6205
  x: 0,
6136
6206
  y: 0,
6137
6207
  alpha: 255,
@@ -6140,15 +6210,15 @@ var SCRATCH_OPTS = {
6140
6210
  function blendColorPixelDataPaintAlphaMask(dst, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
6141
6211
  const tx = x + mask.centerOffsetX;
6142
6212
  const ty = y + mask.centerOffsetY;
6143
- SCRATCH_OPTS.x = tx;
6144
- SCRATCH_OPTS.y = ty;
6145
- SCRATCH_OPTS.alpha = alpha;
6146
- SCRATCH_OPTS.blendFn = blendFn;
6147
- return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS);
6213
+ SCRATCH_OPTS3.x = tx;
6214
+ SCRATCH_OPTS3.y = ty;
6215
+ SCRATCH_OPTS3.alpha = alpha;
6216
+ SCRATCH_OPTS3.blendFn = blendFn;
6217
+ return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS3);
6148
6218
  }
6149
6219
 
6150
6220
  // src/PixelData/blendColorPixelDataPaintBinaryMask.ts
6151
- var SCRATCH_OPTS2 = {
6221
+ var SCRATCH_OPTS4 = {
6152
6222
  x: 0,
6153
6223
  y: 0,
6154
6224
  alpha: 255,
@@ -6157,15 +6227,15 @@ var SCRATCH_OPTS2 = {
6157
6227
  function blendColorPixelDataPaintBinaryMask(dst, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
6158
6228
  const tx = x + mask.centerOffsetX;
6159
6229
  const ty = y + mask.centerOffsetY;
6160
- SCRATCH_OPTS2.x = tx;
6161
- SCRATCH_OPTS2.y = ty;
6162
- SCRATCH_OPTS2.alpha = alpha;
6163
- SCRATCH_OPTS2.blendFn = blendFn;
6164
- return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS2);
6230
+ SCRATCH_OPTS4.x = tx;
6231
+ SCRATCH_OPTS4.y = ty;
6232
+ SCRATCH_OPTS4.alpha = alpha;
6233
+ SCRATCH_OPTS4.blendFn = blendFn;
6234
+ return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS4);
6165
6235
  }
6166
6236
 
6167
6237
  // src/PixelData/blendColorPixelDataPaintMask.ts
6168
- var SCRATCH_OPTS3 = {
6238
+ var SCRATCH_OPTS5 = {
6169
6239
  x: 0,
6170
6240
  y: 0,
6171
6241
  alpha: 255,
@@ -6174,14 +6244,14 @@ var SCRATCH_OPTS3 = {
6174
6244
  function blendColorPixelDataPaintMask(dst, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
6175
6245
  const tx = x + mask.centerOffsetX;
6176
6246
  const ty = y + mask.centerOffsetY;
6177
- SCRATCH_OPTS3.x = tx;
6178
- SCRATCH_OPTS3.y = ty;
6179
- SCRATCH_OPTS3.alpha = alpha;
6180
- SCRATCH_OPTS3.blendFn = blendFn;
6247
+ SCRATCH_OPTS5.x = tx;
6248
+ SCRATCH_OPTS5.y = ty;
6249
+ SCRATCH_OPTS5.alpha = alpha;
6250
+ SCRATCH_OPTS5.blendFn = blendFn;
6181
6251
  if (mask.type === 1 /* BINARY */) {
6182
- return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS3);
6252
+ return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS5);
6183
6253
  } else {
6184
- return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS3);
6254
+ return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS5);
6185
6255
  }
6186
6256
  }
6187
6257
 
@@ -6195,7 +6265,7 @@ function blendPixelDataMask(target, src, mask, opts) {
6195
6265
  }
6196
6266
 
6197
6267
  // src/PixelData/blendPixelDataPaintBuffer.ts
6198
- var SCRATCH_OPTS4 = {
6268
+ var SCRATCH_OPTS6 = {
6199
6269
  x: 0,
6200
6270
  y: 0,
6201
6271
  alpha: 255,
@@ -6209,11 +6279,11 @@ function blendPixelDataPaintBuffer(target, paintBuffer, alpha = 255, blendFn, bl
6209
6279
  if (tile) {
6210
6280
  const x = tile.tx << tileShift;
6211
6281
  const y = tile.ty << tileShift;
6212
- SCRATCH_OPTS4.x = x;
6213
- SCRATCH_OPTS4.y = y;
6214
- SCRATCH_OPTS4.alpha = alpha;
6215
- SCRATCH_OPTS4.blendFn = blendFn;
6216
- blendPixelDataFn(target, tile, SCRATCH_OPTS4);
6282
+ SCRATCH_OPTS6.x = x;
6283
+ SCRATCH_OPTS6.y = y;
6284
+ SCRATCH_OPTS6.alpha = alpha;
6285
+ SCRATCH_OPTS6.blendFn = blendFn;
6286
+ blendPixelDataFn(target, tile, SCRATCH_OPTS6);
6217
6287
  }
6218
6288
  }
6219
6289
  }
@@ -6496,32 +6566,6 @@ function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn
6496
6566
  }
6497
6567
  }
6498
6568
  }
6499
-
6500
- // src/Tile/MaskTile.ts
6501
- var makeAlphaMaskTile = (id, tx, ty, tileSize, tileArea) => {
6502
- return {
6503
- tileType: 1 /* MASK */,
6504
- type: 0 /* ALPHA */,
6505
- data: new Uint8Array(tileArea),
6506
- w: tileSize,
6507
- h: tileSize,
6508
- id,
6509
- tx,
6510
- ty
6511
- };
6512
- };
6513
- var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
6514
- return {
6515
- tileType: 1 /* MASK */,
6516
- type: 1 /* BINARY */,
6517
- data: new Uint8Array(tileArea),
6518
- w: tileSize,
6519
- h: tileSize,
6520
- id,
6521
- tx,
6522
- ty
6523
- };
6524
- };
6525
6569
  // Annotate the CommonJS export names for ESM import in node:
6526
6570
  0 && (module.exports = {
6527
6571
  AlphaMaskPaintBuffer,
@@ -6569,6 +6613,8 @@ var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
6569
6613
  colorDistance,
6570
6614
  colorDodgeFast,
6571
6615
  colorDodgePerfect,
6616
+ commitColorPaintBuffer,
6617
+ commitMaskPaintBuffer,
6572
6618
  copyImageData,
6573
6619
  copyImageDataLike,
6574
6620
  copyMask,
@@ -6641,11 +6687,15 @@ var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
6641
6687
  linearLightPerfect,
6642
6688
  makeAlphaMask,
6643
6689
  makeAlphaMaskPaintBufferCanvasRenderer,
6690
+ makeAlphaMaskPaintBufferCommitter,
6691
+ makeAlphaMaskPaintBufferManager,
6644
6692
  makeAlphaMaskTile,
6645
6693
  makeBinaryMask,
6646
6694
  makeBinaryMaskFromAlphaMask,
6647
6695
  makeBinaryMaskOutline,
6648
6696
  makeBinaryMaskPaintBufferCanvasRenderer,
6697
+ makeBinaryMaskPaintBufferCommitter,
6698
+ makeBinaryMaskPaintBufferManager,
6649
6699
  makeBinaryMaskTile,
6650
6700
  makeBlendModeRegistry,
6651
6701
  makeCanvasFrameRenderer,
@@ -6656,6 +6706,8 @@ var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
6656
6706
  makeClippedBlit,
6657
6707
  makeClippedRect,
6658
6708
  makeColorPaintBufferCanvasRenderer,
6709
+ makeColorPaintBufferCommitter,
6710
+ makeColorPaintBufferManager,
6659
6711
  makeFastBlendModeRegistry,
6660
6712
  makeFullPixelMutator,
6661
6713
  makeHistoryAction,