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.
@@ -1919,13 +1919,13 @@ function makeReusableCanvasMeta(factory) {
1919
1919
 
1920
1920
  // src/Canvas/CanvasFrameRenderer.ts
1921
1921
  function makeCanvasFrameRenderer(reusableCanvasFactory = makeReusableOffscreenCanvas) {
1922
- const bufferCanvas = reusableCanvasFactory();
1922
+ const getBuffer = reusableCanvasFactory();
1923
1923
  return function renderCanvasFrame(pixelCanvas, scale, getImageData, drawPixelLayer, drawScreenLayer) {
1924
1924
  const canvas = pixelCanvas.canvas;
1925
1925
  const ctx = pixelCanvas.ctx;
1926
1926
  const w = canvas.width;
1927
1927
  const h = canvas.height;
1928
- const buffer = bufferCanvas(w, h);
1928
+ const buffer = getBuffer(w, h);
1929
1929
  const img = getImageData();
1930
1930
  if (img) {
1931
1931
  buffer.ctx.putImageData(img, 0, 0);
@@ -2050,19 +2050,17 @@ function applyPatchTiles(target, tiles, tileSize) {
2050
2050
  }
2051
2051
 
2052
2052
  // src/History/HistoryAction.ts
2053
- function makeHistoryAction(config, accumulator, patch, after, afterUndo, afterRedo, applyPatchTilesFn = applyPatchTiles) {
2053
+ function makeHistoryAction(config, accumulator, patch, afterUndo, afterRedo, applyPatchTilesFn = applyPatchTiles) {
2054
2054
  const target = config.target;
2055
2055
  const tileSize = config.tileSize;
2056
2056
  return {
2057
2057
  undo: () => {
2058
2058
  applyPatchTilesFn(target, patch.beforeTiles, tileSize);
2059
- afterUndo?.();
2060
- after?.();
2059
+ afterUndo?.(patch);
2061
2060
  },
2062
2061
  redo: () => {
2063
2062
  applyPatchTilesFn(target, patch.afterTiles, tileSize);
2064
- afterRedo?.();
2065
- after?.();
2063
+ afterRedo?.(patch);
2066
2064
  },
2067
2065
  dispose: () => accumulator.recyclePatch(patch)
2068
2066
  };
@@ -5012,7 +5010,6 @@ var AlphaMaskPaintBuffer = class {
5012
5010
  w: 0,
5013
5011
  h: 0
5014
5012
  };
5015
- blendColorPixelDataAlphaMaskFn = blendColorPixelDataAlphaMask;
5016
5013
  forEachLinePointFn = forEachLinePoint;
5017
5014
  trimRectBoundsFn = trimRectBounds;
5018
5015
  eachTileInBoundsFn = eachTileInBounds;
@@ -5151,88 +5148,11 @@ var AlphaMaskPaintBuffer = class {
5151
5148
  });
5152
5149
  return changed;
5153
5150
  }
5154
- opts = {
5155
- alpha: 255,
5156
- blendFn: sourceOverPerfect,
5157
- x: 0,
5158
- y: 0,
5159
- w: 0,
5160
- h: 0
5161
- };
5162
- commit(accumulator, color, alpha = 255, blendFn = sourceOverPerfect) {
5163
- const blendColorPixelDataAlphaMaskFn = this.blendColorPixelDataAlphaMaskFn;
5164
- const tileShift = this.config.tileShift;
5165
- const lookup = this.lookup;
5166
- const opts = this.opts;
5167
- opts.alpha = alpha;
5168
- opts.blendFn = blendFn;
5169
- for (let i = 0; i < lookup.length; i++) {
5170
- const tile = lookup[i];
5171
- if (tile) {
5172
- const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5173
- const dx = tile.tx << tileShift;
5174
- const dy = tile.ty << tileShift;
5175
- opts.x = dx;
5176
- opts.y = dy;
5177
- opts.w = tile.w;
5178
- opts.h = tile.h;
5179
- didChange(blendColorPixelDataAlphaMaskFn(this.config.target, color, tile, opts));
5180
- }
5181
- }
5182
- this.clear();
5183
- }
5184
5151
  clear() {
5185
5152
  this.tilePool.releaseTiles(this.lookup);
5186
5153
  }
5187
5154
  };
5188
5155
 
5189
- // src/Paint/AlphaMaskPaintBufferCanvasRenderer.ts
5190
- function makeAlphaMaskPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
5191
- const config = paintBuffer.config;
5192
- const tileSize = config.tileSize;
5193
- const tileShift = config.tileShift;
5194
- const tileArea = config.tileArea;
5195
- const lookup = paintBuffer.lookup;
5196
- const canvas = new offscreenCanvasClass(tileSize, tileSize);
5197
- const ctx = canvas.getContext("2d");
5198
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5199
- ctx.imageSmoothingEnabled = false;
5200
- const bridge = makePixelData(new ImageData(tileSize, tileSize));
5201
- const view32 = bridge.data;
5202
- return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5203
- if (alpha === 0) return;
5204
- const baseSrcAlpha = color >>> 24;
5205
- const colorRGB = color & 16777215;
5206
- if (baseSrcAlpha === 0) return;
5207
- targetCtx.globalAlpha = alpha / 255;
5208
- targetCtx.globalCompositeOperation = compOperation;
5209
- for (let i = 0; i < lookup.length; i++) {
5210
- const tile = lookup[i];
5211
- if (tile) {
5212
- const data8 = tile.data;
5213
- view32.fill(0);
5214
- for (let p = 0; p < tileArea; p++) {
5215
- const maskA = data8[p];
5216
- if (maskA === 0) continue;
5217
- if (maskA === 255) {
5218
- view32[p] = color;
5219
- } else {
5220
- const t = baseSrcAlpha * maskA + 128;
5221
- const finalA = t + (t >> 8) >> 8;
5222
- view32[p] = (colorRGB | finalA << 24) >>> 0;
5223
- }
5224
- }
5225
- const dx = tile.tx << tileShift;
5226
- const dy = tile.ty << tileShift;
5227
- ctx.putImageData(bridge.imageData, 0, 0);
5228
- targetCtx.drawImage(canvas, dx, dy);
5229
- }
5230
- }
5231
- targetCtx.globalAlpha = 1;
5232
- targetCtx.globalCompositeOperation = "source-over";
5233
- };
5234
- }
5235
-
5236
5156
  // src/Paint/BinaryMaskPaintBuffer.ts
5237
5157
  var BinaryMaskPaintBuffer = class {
5238
5158
  constructor(config, tilePool) {
@@ -5247,7 +5167,6 @@ var BinaryMaskPaintBuffer = class {
5247
5167
  w: 0,
5248
5168
  h: 0
5249
5169
  };
5250
- blendColorPixelDataBinaryMaskFn = blendColorPixelDataBinaryMask;
5251
5170
  forEachLinePointFn = forEachLinePoint;
5252
5171
  trimRectBoundsFn = trimRectBounds;
5253
5172
  eachTileInBoundsFn = eachTileInBounds;
@@ -5338,87 +5257,16 @@ var BinaryMaskPaintBuffer = class {
5338
5257
  });
5339
5258
  return changed;
5340
5259
  }
5341
- opts = {
5342
- alpha: 255,
5343
- blendFn: sourceOverPerfect,
5344
- x: 0,
5345
- y: 0,
5346
- w: 0,
5347
- h: 0
5348
- };
5349
- commit(accumulator, color, alpha = 255, blendFn = sourceOverPerfect) {
5350
- const blendColorPixelDataBinaryMaskFn = this.blendColorPixelDataBinaryMaskFn;
5351
- const tileShift = this.config.tileShift;
5352
- const lookup = this.lookup;
5353
- const opts = this.opts;
5354
- opts.alpha = alpha;
5355
- opts.blendFn = blendFn;
5356
- for (let i = 0; i < lookup.length; i++) {
5357
- const tile = lookup[i];
5358
- if (tile) {
5359
- const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5360
- const dx = tile.tx << tileShift;
5361
- const dy = tile.ty << tileShift;
5362
- opts.x = dx;
5363
- opts.y = dy;
5364
- opts.w = tile.w;
5365
- opts.h = tile.h;
5366
- didChange(blendColorPixelDataBinaryMaskFn(this.config.target, color, tile, opts));
5367
- }
5368
- }
5369
- this.clear();
5370
- }
5371
5260
  clear() {
5372
5261
  this.tilePool.releaseTiles(this.lookup);
5373
5262
  }
5374
5263
  };
5375
5264
 
5376
- // src/Paint/BinaryMaskPaintBufferCanvasRenderer.ts
5377
- function makeBinaryMaskPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
5378
- const config = paintBuffer.config;
5379
- const tileSize = config.tileSize;
5380
- const tileShift = config.tileShift;
5381
- const tileArea = config.tileArea;
5382
- const lookup = paintBuffer.lookup;
5383
- const canvas = new offscreenCanvasClass(tileSize, tileSize);
5384
- const ctx = canvas.getContext("2d");
5385
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5386
- ctx.imageSmoothingEnabled = false;
5387
- const bridge = makePixelData(new ImageData(tileSize, tileSize));
5388
- const view32 = bridge.data;
5389
- return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5390
- if (alpha === 0) return;
5391
- const baseSrcAlpha = color >>> 24;
5392
- if (baseSrcAlpha === 0) return;
5393
- targetCtx.globalAlpha = alpha / 255;
5394
- targetCtx.globalCompositeOperation = compOperation;
5395
- for (let i = 0; i < lookup.length; i++) {
5396
- const tile = lookup[i];
5397
- if (tile) {
5398
- const data8 = tile.data;
5399
- view32.fill(0);
5400
- for (let p = 0; p < tileArea; p++) {
5401
- if (data8[p] === 1) {
5402
- view32[p] = color;
5403
- }
5404
- }
5405
- const dx = tile.tx << tileShift;
5406
- const dy = tile.ty << tileShift;
5407
- ctx.putImageData(bridge.imageData, 0, 0);
5408
- targetCtx.drawImage(canvas, dx, dy);
5409
- }
5410
- }
5411
- targetCtx.globalAlpha = 1;
5412
- targetCtx.globalCompositeOperation = "source-over";
5413
- };
5414
- }
5415
-
5416
5265
  // src/Paint/ColorPaintBuffer.ts
5417
5266
  var ColorPaintBuffer = class {
5418
- constructor(config, tilePool, blendPixelDataFn = blendPixelData) {
5267
+ constructor(config, tilePool) {
5419
5268
  this.config = config;
5420
5269
  this.tilePool = tilePool;
5421
- this.blendPixelDataFn = blendPixelDataFn;
5422
5270
  this.lookup = [];
5423
5271
  }
5424
5272
  lookup;
@@ -5569,48 +5417,246 @@ var ColorPaintBuffer = class {
5569
5417
  });
5570
5418
  return changed;
5571
5419
  }
5572
- opts = {
5573
- alpha: 255,
5574
- blendFn: sourceOverPerfect,
5575
- x: 0,
5576
- y: 0,
5577
- w: 0,
5578
- h: 0
5420
+ clear() {
5421
+ this.tilePool.releaseTiles(this.lookup);
5422
+ }
5423
+ };
5424
+
5425
+ // src/Paint/Commit/commitMaskPaintBuffer.ts
5426
+ var SCRATCH_OPTS = {
5427
+ alpha: 255,
5428
+ blendFn: sourceOverPerfect,
5429
+ x: 0,
5430
+ y: 0,
5431
+ w: 0,
5432
+ h: 0
5433
+ };
5434
+ function commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha = 255, blendFn = sourceOverPerfect, blendColorPixelDataMaskFn) {
5435
+ const config = accumulator.config;
5436
+ const tileShift = config.tileShift;
5437
+ const lookup = paintBuffer.lookup;
5438
+ SCRATCH_OPTS.alpha = alpha;
5439
+ SCRATCH_OPTS.blendFn = blendFn;
5440
+ for (let i = 0; i < lookup.length; i++) {
5441
+ const tile = lookup[i];
5442
+ if (tile) {
5443
+ const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5444
+ const dx = tile.tx << tileShift;
5445
+ const dy = tile.ty << tileShift;
5446
+ SCRATCH_OPTS.x = dx;
5447
+ SCRATCH_OPTS.y = dy;
5448
+ SCRATCH_OPTS.w = tile.w;
5449
+ SCRATCH_OPTS.h = tile.h;
5450
+ didChange(blendColorPixelDataMaskFn(config.target, color, tile, SCRATCH_OPTS));
5451
+ }
5452
+ }
5453
+ paintBuffer.clear();
5454
+ }
5455
+
5456
+ // src/Paint/Commit/AlphaMaskPaintBufferCommitter.ts
5457
+ function makeAlphaMaskPaintBufferCommitter(accumulator, paintBuffer) {
5458
+ return function commitAlphaMaskPaintBufferToAccumulator(color, alpha = 255, blendFn = sourceOverPerfect) {
5459
+ return commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha, blendFn, blendColorPixelDataAlphaMask);
5579
5460
  };
5580
- commit(accumulator, alpha = 255, blendFn = sourceOverPerfect) {
5581
- const tileShift = this.config.tileShift;
5582
- const lookup = this.lookup;
5583
- const opts = this.opts;
5584
- const blendPixelDataFn = this.blendPixelDataFn;
5585
- opts.alpha = alpha;
5586
- opts.blendFn = blendFn;
5461
+ }
5462
+
5463
+ // src/Internal/_constants.ts
5464
+ var DEFAULT_CANVAS_FACTORY = (w, h) => new OffscreenCanvas(w, h);
5465
+
5466
+ // src/Tile/MaskTile.ts
5467
+ var makeAlphaMaskTile = (id, tx, ty, tileSize, tileArea) => {
5468
+ return {
5469
+ tileType: 1 /* MASK */,
5470
+ type: 0 /* ALPHA */,
5471
+ data: new Uint8Array(tileArea),
5472
+ w: tileSize,
5473
+ h: tileSize,
5474
+ id,
5475
+ tx,
5476
+ ty
5477
+ };
5478
+ };
5479
+ var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
5480
+ return {
5481
+ tileType: 1 /* MASK */,
5482
+ type: 1 /* BINARY */,
5483
+ data: new Uint8Array(tileArea),
5484
+ w: tileSize,
5485
+ h: tileSize,
5486
+ id,
5487
+ tx,
5488
+ ty
5489
+ };
5490
+ };
5491
+
5492
+ // src/Paint/Render/AlphaMaskPaintBufferCanvasRenderer.ts
5493
+ function makeAlphaMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5494
+ const config = paintBuffer.config;
5495
+ const tileSize = config.tileSize;
5496
+ const tileShift = config.tileShift;
5497
+ const tileArea = config.tileArea;
5498
+ const lookup = paintBuffer.lookup;
5499
+ const canvas = canvasFactory(tileSize, tileSize);
5500
+ const ctx = canvas.getContext("2d");
5501
+ if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5502
+ ctx.imageSmoothingEnabled = false;
5503
+ const bridge = makePixelData(new ImageData(tileSize, tileSize));
5504
+ const view32 = bridge.data;
5505
+ return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5506
+ if (alpha === 0) return;
5507
+ const baseSrcAlpha = color >>> 24;
5508
+ const colorRGB = color & 16777215;
5509
+ if (baseSrcAlpha === 0) return;
5510
+ targetCtx.globalAlpha = alpha / 255;
5511
+ targetCtx.globalCompositeOperation = compOperation;
5587
5512
  for (let i = 0; i < lookup.length; i++) {
5588
5513
  const tile = lookup[i];
5589
5514
  if (tile) {
5590
- const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5515
+ const data8 = tile.data;
5516
+ view32.fill(0);
5517
+ for (let p = 0; p < tileArea; p++) {
5518
+ const maskA = data8[p];
5519
+ if (maskA === 0) continue;
5520
+ if (maskA === 255) {
5521
+ view32[p] = color;
5522
+ } else {
5523
+ const t = baseSrcAlpha * maskA + 128;
5524
+ const finalA = t + (t >> 8) >> 8;
5525
+ view32[p] = (colorRGB | finalA << 24) >>> 0;
5526
+ }
5527
+ }
5591
5528
  const dx = tile.tx << tileShift;
5592
5529
  const dy = tile.ty << tileShift;
5593
- opts.x = dx;
5594
- opts.y = dy;
5595
- opts.w = tile.w;
5596
- opts.h = tile.h;
5597
- didChange(blendPixelDataFn(this.config.target, tile, opts));
5530
+ ctx.putImageData(bridge.imageData, 0, 0);
5531
+ targetCtx.drawImage(canvas, dx, dy);
5598
5532
  }
5599
5533
  }
5600
- this.clear();
5601
- }
5602
- clear() {
5603
- this.tilePool.releaseTiles(this.lookup);
5604
- }
5534
+ targetCtx.globalAlpha = 1;
5535
+ targetCtx.globalCompositeOperation = "source-over";
5536
+ };
5537
+ }
5538
+
5539
+ // src/Paint/Commit/AlphaMaskPaintBufferManager.ts
5540
+ function makeAlphaMaskPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5541
+ const pool = new TilePool(writer.config, makeAlphaMaskTile);
5542
+ const buffer = new AlphaMaskPaintBuffer(writer.config, pool);
5543
+ const draw = makeAlphaMaskPaintBufferCanvasRenderer(buffer, canvasFactory);
5544
+ return {
5545
+ clear: buffer.clear.bind(buffer),
5546
+ paintRect: buffer.paintRect.bind(buffer),
5547
+ paintAlphaMask: buffer.paintAlphaMask.bind(buffer),
5548
+ paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5549
+ commit: makeAlphaMaskPaintBufferCommitter(writer.accumulator, buffer),
5550
+ draw
5551
+ };
5552
+ }
5553
+
5554
+ // src/Paint/Commit/BinaryMaskPaintBufferCommitter.ts
5555
+ function makeBinaryMaskPaintBufferCommitter(accumulator, paintBuffer) {
5556
+ return function commitBinaryMaskPaintBufferToAccumulator(color, alpha = 255, blendFn = sourceOverPerfect) {
5557
+ return commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha, blendFn, blendColorPixelDataBinaryMask);
5558
+ };
5559
+ }
5560
+
5561
+ // src/Paint/Render/BinaryMaskPaintBufferCanvasRenderer.ts
5562
+ function makeBinaryMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5563
+ const config = paintBuffer.config;
5564
+ const tileSize = config.tileSize;
5565
+ const tileShift = config.tileShift;
5566
+ const tileArea = config.tileArea;
5567
+ const lookup = paintBuffer.lookup;
5568
+ const canvas = canvasFactory(tileSize, tileSize);
5569
+ const ctx = canvas.getContext("2d");
5570
+ if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5571
+ ctx.imageSmoothingEnabled = false;
5572
+ const bridge = makePixelData(new ImageData(tileSize, tileSize));
5573
+ const view32 = bridge.data;
5574
+ return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5575
+ if (alpha === 0) return;
5576
+ const baseSrcAlpha = color >>> 24;
5577
+ if (baseSrcAlpha === 0) return;
5578
+ targetCtx.globalAlpha = alpha / 255;
5579
+ targetCtx.globalCompositeOperation = compOperation;
5580
+ for (let i = 0; i < lookup.length; i++) {
5581
+ const tile = lookup[i];
5582
+ if (tile) {
5583
+ const data8 = tile.data;
5584
+ view32.fill(0);
5585
+ for (let p = 0; p < tileArea; p++) {
5586
+ if (data8[p] === 1) {
5587
+ view32[p] = color;
5588
+ }
5589
+ }
5590
+ const dx = tile.tx << tileShift;
5591
+ const dy = tile.ty << tileShift;
5592
+ ctx.putImageData(bridge.imageData, 0, 0);
5593
+ targetCtx.drawImage(canvas, dx, dy);
5594
+ }
5595
+ }
5596
+ targetCtx.globalAlpha = 1;
5597
+ targetCtx.globalCompositeOperation = "source-over";
5598
+ };
5599
+ }
5600
+
5601
+ // src/Paint/Commit/BinaryMaskPaintBufferManager.ts
5602
+ function makeBinaryMaskPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5603
+ const pool = new TilePool(writer.config, makeBinaryMaskTile);
5604
+ const buffer = new BinaryMaskPaintBuffer(writer.config, pool);
5605
+ const draw = makeBinaryMaskPaintBufferCanvasRenderer(buffer, canvasFactory);
5606
+ return {
5607
+ clear: buffer.clear.bind(buffer),
5608
+ paintRect: buffer.paintRect.bind(buffer),
5609
+ paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5610
+ commit: makeBinaryMaskPaintBufferCommitter(writer.accumulator, buffer),
5611
+ draw
5612
+ };
5613
+ }
5614
+
5615
+ // src/Paint/Commit/commitColorPaintBuffer.ts
5616
+ var SCRATCH_OPTS2 = {
5617
+ alpha: 255,
5618
+ blendFn: sourceOverPerfect,
5619
+ x: 0,
5620
+ y: 0,
5621
+ w: 0,
5622
+ h: 0
5605
5623
  };
5624
+ function commitColorPaintBuffer(accumulator, paintBuffer, alpha = 255, blendFn = sourceOverPerfect, blendPixelDataFn = blendPixelData) {
5625
+ const config = accumulator.config;
5626
+ const tileShift = config.tileShift;
5627
+ const lookup = paintBuffer.lookup;
5628
+ SCRATCH_OPTS2.alpha = alpha;
5629
+ SCRATCH_OPTS2.blendFn = blendFn;
5630
+ for (let i = 0; i < lookup.length; i++) {
5631
+ const tile = lookup[i];
5632
+ if (tile) {
5633
+ const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5634
+ const dx = tile.tx << tileShift;
5635
+ const dy = tile.ty << tileShift;
5636
+ SCRATCH_OPTS2.x = dx;
5637
+ SCRATCH_OPTS2.y = dy;
5638
+ SCRATCH_OPTS2.w = tile.w;
5639
+ SCRATCH_OPTS2.h = tile.h;
5640
+ didChange(blendPixelDataFn(config.target, tile, SCRATCH_OPTS2));
5641
+ }
5642
+ }
5643
+ paintBuffer.clear();
5644
+ }
5606
5645
 
5607
- // src/Paint/ColorPaintBufferCanvasRenderer.ts
5608
- function makeColorPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
5646
+ // src/Paint/Commit/ColorPaintBufferCommitter.ts
5647
+ function makeColorPaintBufferCommitter(accumulator, paintBuffer) {
5648
+ return function commitColorPaintBufferToAccumulator(alpha = 255, blendFn = sourceOverPerfect) {
5649
+ return commitColorPaintBuffer(accumulator, paintBuffer, alpha, blendFn, blendPixelData);
5650
+ };
5651
+ }
5652
+
5653
+ // src/Paint/Render/ColorPaintBufferCanvasRenderer.ts
5654
+ function makeColorPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5609
5655
  const config = paintBuffer.config;
5610
5656
  const tileSize = config.tileSize;
5611
5657
  const tileShift = config.tileShift;
5612
5658
  const lookup = paintBuffer.lookup;
5613
- const canvas = new offscreenCanvasClass(tileSize, tileSize);
5659
+ const canvas = canvasFactory(tileSize, tileSize);
5614
5660
  const ctx = canvas.getContext("2d");
5615
5661
  if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5616
5662
  ctx.imageSmoothingEnabled = false;
@@ -5631,6 +5677,21 @@ function makeColorPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass =
5631
5677
  };
5632
5678
  }
5633
5679
 
5680
+ // src/Paint/Commit/ColorPaintBufferManager.ts
5681
+ function makeColorPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5682
+ const pool = new TilePool(writer.config, makePixelTile);
5683
+ const buffer = new ColorPaintBuffer(writer.config, pool);
5684
+ const draw = makeColorPaintBufferCanvasRenderer(buffer, canvasFactory);
5685
+ return {
5686
+ clear: buffer.clear.bind(buffer),
5687
+ paintRect: buffer.paintRect.bind(buffer),
5688
+ paintAlphaMask: buffer.paintAlphaMask.bind(buffer),
5689
+ paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5690
+ commit: makeColorPaintBufferCommitter(writer.accumulator, buffer),
5691
+ draw
5692
+ };
5693
+ }
5694
+
5634
5695
  // src/Paint/makeCirclePaintMask.ts
5635
5696
  function makeCirclePaintAlphaMask(size, fallOff = (d) => d) {
5636
5697
  const area = size * size;
@@ -5768,12 +5829,14 @@ function makeReusablePixelData() {
5768
5829
  };
5769
5830
  }
5770
5831
 
5771
- // src/Paint/PaintCursorRenderer.ts
5772
- function makePaintCursorRenderer(factory = (w, h) => new OffscreenCanvas(w, h)) {
5773
- const canvas = factory(1, 1);
5774
- const ctx = canvas.getContext("2d");
5775
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5776
- ctx.imageSmoothingEnabled = false;
5832
+ // src/Paint/Render/PaintCursorRenderer.ts
5833
+ function makePaintCursorRenderer(reusableCanvasFactory) {
5834
+ const factory = reusableCanvasFactory ?? makeReusableOffscreenCanvas;
5835
+ const updateBuffer = factory();
5836
+ const {
5837
+ canvas,
5838
+ ctx
5839
+ } = updateBuffer(1, 1);
5777
5840
  const getPixelData = makeReusablePixelData();
5778
5841
  let _color = packColor(0, 255, 255, 255);
5779
5842
  let _scale = 1;
@@ -5790,8 +5853,7 @@ function makePaintCursorRenderer(factory = (w, h) => new OffscreenCanvas(w, h))
5790
5853
  currentMask = paintMask ?? currentMask;
5791
5854
  _scale = scale ?? _scale;
5792
5855
  _color = color ?? _color;
5793
- canvas.width = currentMask.w * _scale + 2 * _scale;
5794
- canvas.height = currentMask.h * _scale + 2 * _scale;
5856
+ updateBuffer(currentMask.w * _scale + 2 * _scale, currentMask.h * _scale + 2 * _scale);
5795
5857
  if (currentMask.type === 1 /* BINARY */) {
5796
5858
  if (currentMask.outlineType === 1 /* CIRCLE */) {
5797
5859
  outline = makeCircleBinaryMaskOutline(currentMask.w, _scale);
@@ -5874,7 +5936,7 @@ function blendColorPixelDataMask(dst, color, mask, opts) {
5874
5936
  }
5875
5937
 
5876
5938
  // src/PixelData/blendColorPixelDataPaintAlphaMask.ts
5877
- var SCRATCH_OPTS = {
5939
+ var SCRATCH_OPTS3 = {
5878
5940
  x: 0,
5879
5941
  y: 0,
5880
5942
  alpha: 255,
@@ -5883,15 +5945,15 @@ var SCRATCH_OPTS = {
5883
5945
  function blendColorPixelDataPaintAlphaMask(dst, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
5884
5946
  const tx = x + mask.centerOffsetX;
5885
5947
  const ty = y + mask.centerOffsetY;
5886
- SCRATCH_OPTS.x = tx;
5887
- SCRATCH_OPTS.y = ty;
5888
- SCRATCH_OPTS.alpha = alpha;
5889
- SCRATCH_OPTS.blendFn = blendFn;
5890
- return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS);
5948
+ SCRATCH_OPTS3.x = tx;
5949
+ SCRATCH_OPTS3.y = ty;
5950
+ SCRATCH_OPTS3.alpha = alpha;
5951
+ SCRATCH_OPTS3.blendFn = blendFn;
5952
+ return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS3);
5891
5953
  }
5892
5954
 
5893
5955
  // src/PixelData/blendColorPixelDataPaintBinaryMask.ts
5894
- var SCRATCH_OPTS2 = {
5956
+ var SCRATCH_OPTS4 = {
5895
5957
  x: 0,
5896
5958
  y: 0,
5897
5959
  alpha: 255,
@@ -5900,15 +5962,15 @@ var SCRATCH_OPTS2 = {
5900
5962
  function blendColorPixelDataPaintBinaryMask(dst, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
5901
5963
  const tx = x + mask.centerOffsetX;
5902
5964
  const ty = y + mask.centerOffsetY;
5903
- SCRATCH_OPTS2.x = tx;
5904
- SCRATCH_OPTS2.y = ty;
5905
- SCRATCH_OPTS2.alpha = alpha;
5906
- SCRATCH_OPTS2.blendFn = blendFn;
5907
- return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS2);
5965
+ SCRATCH_OPTS4.x = tx;
5966
+ SCRATCH_OPTS4.y = ty;
5967
+ SCRATCH_OPTS4.alpha = alpha;
5968
+ SCRATCH_OPTS4.blendFn = blendFn;
5969
+ return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS4);
5908
5970
  }
5909
5971
 
5910
5972
  // src/PixelData/blendColorPixelDataPaintMask.ts
5911
- var SCRATCH_OPTS3 = {
5973
+ var SCRATCH_OPTS5 = {
5912
5974
  x: 0,
5913
5975
  y: 0,
5914
5976
  alpha: 255,
@@ -5917,14 +5979,14 @@ var SCRATCH_OPTS3 = {
5917
5979
  function blendColorPixelDataPaintMask(dst, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
5918
5980
  const tx = x + mask.centerOffsetX;
5919
5981
  const ty = y + mask.centerOffsetY;
5920
- SCRATCH_OPTS3.x = tx;
5921
- SCRATCH_OPTS3.y = ty;
5922
- SCRATCH_OPTS3.alpha = alpha;
5923
- SCRATCH_OPTS3.blendFn = blendFn;
5982
+ SCRATCH_OPTS5.x = tx;
5983
+ SCRATCH_OPTS5.y = ty;
5984
+ SCRATCH_OPTS5.alpha = alpha;
5985
+ SCRATCH_OPTS5.blendFn = blendFn;
5924
5986
  if (mask.type === 1 /* BINARY */) {
5925
- return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS3);
5987
+ return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS5);
5926
5988
  } else {
5927
- return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS3);
5989
+ return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS5);
5928
5990
  }
5929
5991
  }
5930
5992
 
@@ -5938,7 +6000,7 @@ function blendPixelDataMask(target, src, mask, opts) {
5938
6000
  }
5939
6001
 
5940
6002
  // src/PixelData/blendPixelDataPaintBuffer.ts
5941
- var SCRATCH_OPTS4 = {
6003
+ var SCRATCH_OPTS6 = {
5942
6004
  x: 0,
5943
6005
  y: 0,
5944
6006
  alpha: 255,
@@ -5952,11 +6014,11 @@ function blendPixelDataPaintBuffer(target, paintBuffer, alpha = 255, blendFn, bl
5952
6014
  if (tile) {
5953
6015
  const x = tile.tx << tileShift;
5954
6016
  const y = tile.ty << tileShift;
5955
- SCRATCH_OPTS4.x = x;
5956
- SCRATCH_OPTS4.y = y;
5957
- SCRATCH_OPTS4.alpha = alpha;
5958
- SCRATCH_OPTS4.blendFn = blendFn;
5959
- blendPixelDataFn(target, tile, SCRATCH_OPTS4);
6017
+ SCRATCH_OPTS6.x = x;
6018
+ SCRATCH_OPTS6.y = y;
6019
+ SCRATCH_OPTS6.alpha = alpha;
6020
+ SCRATCH_OPTS6.blendFn = blendFn;
6021
+ blendPixelDataFn(target, tile, SCRATCH_OPTS6);
5960
6022
  }
5961
6023
  }
5962
6024
  }
@@ -6239,32 +6301,6 @@ function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn
6239
6301
  }
6240
6302
  }
6241
6303
  }
6242
-
6243
- // src/Tile/MaskTile.ts
6244
- var makeAlphaMaskTile = (id, tx, ty, tileSize, tileArea) => {
6245
- return {
6246
- tileType: 1 /* MASK */,
6247
- type: 0 /* ALPHA */,
6248
- data: new Uint8Array(tileArea),
6249
- w: tileSize,
6250
- h: tileSize,
6251
- id,
6252
- tx,
6253
- ty
6254
- };
6255
- };
6256
- var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
6257
- return {
6258
- tileType: 1 /* MASK */,
6259
- type: 1 /* BINARY */,
6260
- data: new Uint8Array(tileArea),
6261
- w: tileSize,
6262
- h: tileSize,
6263
- id,
6264
- tx,
6265
- ty
6266
- };
6267
- };
6268
6304
  export {
6269
6305
  AlphaMaskPaintBuffer,
6270
6306
  BASE_FAST_BLEND_MODE_FUNCTIONS,
@@ -6311,6 +6347,8 @@ export {
6311
6347
  colorDistance,
6312
6348
  colorDodgeFast,
6313
6349
  colorDodgePerfect,
6350
+ commitColorPaintBuffer,
6351
+ commitMaskPaintBuffer,
6314
6352
  copyImageData,
6315
6353
  copyImageDataLike,
6316
6354
  copyMask,
@@ -6383,11 +6421,15 @@ export {
6383
6421
  linearLightPerfect,
6384
6422
  makeAlphaMask,
6385
6423
  makeAlphaMaskPaintBufferCanvasRenderer,
6424
+ makeAlphaMaskPaintBufferCommitter,
6425
+ makeAlphaMaskPaintBufferManager,
6386
6426
  makeAlphaMaskTile,
6387
6427
  makeBinaryMask,
6388
6428
  makeBinaryMaskFromAlphaMask,
6389
6429
  makeBinaryMaskOutline,
6390
6430
  makeBinaryMaskPaintBufferCanvasRenderer,
6431
+ makeBinaryMaskPaintBufferCommitter,
6432
+ makeBinaryMaskPaintBufferManager,
6391
6433
  makeBinaryMaskTile,
6392
6434
  makeBlendModeRegistry,
6393
6435
  makeCanvasFrameRenderer,
@@ -6398,6 +6440,8 @@ export {
6398
6440
  makeClippedBlit,
6399
6441
  makeClippedRect,
6400
6442
  makeColorPaintBufferCanvasRenderer,
6443
+ makeColorPaintBufferCommitter,
6444
+ makeColorPaintBufferManager,
6401
6445
  makeFastBlendModeRegistry,
6402
6446
  makeFullPixelMutator,
6403
6447
  makeHistoryAction,