pixel-data-js 0.36.0 → 0.37.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 (72) hide show
  1. package/dist/index.prod.cjs +372 -303
  2. package/dist/index.prod.cjs.map +1 -1
  3. package/dist/index.prod.d.ts +109 -67
  4. package/dist/index.prod.js +368 -302
  5. package/dist/index.prod.js.map +1 -1
  6. package/package.json +2 -2
  7. package/src/Algorithm/floodFillSelection.ts +3 -2
  8. package/src/BlendModes/blend-modes-fast.ts +2 -1
  9. package/src/BlendModes/blend-modes-perfect.ts +2 -1
  10. package/src/Canvas/ReusableCanvas.ts +0 -5
  11. package/src/Color/_color-types.ts +8 -0
  12. package/src/Color/colorDistance.ts +9 -0
  13. package/src/Color/convert-color.ts +43 -0
  14. package/src/Color/lerpColor32.ts +44 -0
  15. package/src/Color/pack-color.ts +38 -0
  16. package/src/History/HistoryAction.ts +2 -2
  17. package/src/History/PixelAccumulator.ts +13 -15
  18. package/src/History/PixelMutator/mutatorBlendColor.ts +2 -1
  19. package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +1 -1
  20. package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +1 -1
  21. package/src/History/PixelMutator/mutatorBlendColorPaintMask.ts +23 -8
  22. package/src/History/PixelMutator/mutatorBlendColorPaintRect.ts +2 -1
  23. package/src/History/PixelMutator/mutatorBlendPixel.ts +2 -1
  24. package/src/History/PixelMutator/mutatorClear.ts +1 -1
  25. package/src/History/PixelMutator/mutatorFill.ts +1 -1
  26. package/src/History/PixelMutator/mutatorFillBinaryMask.ts +1 -1
  27. package/src/History/PixelWriter.ts +5 -5
  28. package/src/IndexedImage/IndexedImage.ts +1 -1
  29. package/src/IndexedImage/indexedImageToAverageColor.ts +3 -2
  30. package/src/Mask/_mask-types.ts +9 -0
  31. package/src/Paint/AlphaMaskPaintBuffer.ts +26 -26
  32. package/src/Paint/BinaryMaskPaintBuffer.ts +19 -19
  33. package/src/Paint/ColorPaintBuffer.ts +40 -42
  34. package/src/Paint/Commit/AlphaMaskPaintBufferCommitter.ts +1 -1
  35. package/src/Paint/Commit/AlphaMaskPaintBufferManager.ts +6 -7
  36. package/src/Paint/Commit/BinaryMaskPaintBufferCommitter.ts +1 -1
  37. package/src/Paint/Commit/BinaryMaskPaintBufferManager.ts +6 -7
  38. package/src/Paint/Commit/ColorPaintBufferManager.ts +6 -7
  39. package/src/Paint/Commit/commitColorPaintBuffer.ts +2 -6
  40. package/src/Paint/Commit/commitMaskPaintBuffer.ts +3 -7
  41. package/src/Paint/Render/AlphaMaskPaintBufferCanvasRenderer.ts +42 -25
  42. package/src/Paint/Render/BinaryMaskPaintBufferCanvasRenderer.ts +40 -24
  43. package/src/Paint/Render/ColorPaintBufferCanvasRenderer.ts +21 -21
  44. package/src/Paint/Render/PaintCursorRenderer.ts +3 -2
  45. package/src/Paint/eachTileInBounds.ts +9 -10
  46. package/src/PixelData/blendColorPixelData.ts +2 -1
  47. package/src/PixelData/blendColorPixelDataAlphaMask.ts +2 -1
  48. package/src/PixelData/blendColorPixelDataBinaryMask.ts +2 -1
  49. package/src/PixelData/blendColorPixelDataMask.ts +2 -1
  50. package/src/PixelData/blendColorPixelDataPaintAlphaMask.ts +1 -1
  51. package/src/PixelData/blendColorPixelDataPaintBinaryMask.ts +1 -1
  52. package/src/PixelData/blendColorPixelDataPaintMask.ts +19 -8
  53. package/src/PixelData/blendPixel.ts +2 -1
  54. package/src/PixelData/blendPixelData.ts +2 -1
  55. package/src/PixelData/blendPixelDataAlphaMask.ts +2 -1
  56. package/src/PixelData/blendPixelDataBinaryMask.ts +2 -1
  57. package/src/PixelData/blendPixelDataPaintBuffer.ts +2 -3
  58. package/src/PixelData/clearPixelDataFast.ts +1 -1
  59. package/src/PixelData/fillPixelData.ts +1 -1
  60. package/src/PixelData/fillPixelDataBinaryMask.ts +1 -1
  61. package/src/PixelData/fillPixelDataFast.ts +1 -1
  62. package/src/PixelData/writePaintBufferToPixelData.ts +1 -5
  63. package/src/Tile/MaskTile.ts +4 -0
  64. package/src/Tile/PixelTile.ts +2 -0
  65. package/src/Tile/TilePool.ts +9 -8
  66. package/src/Tile/TileTargetConfig.ts +27 -0
  67. package/src/Tile/_tile-types.ts +16 -0
  68. package/src/_types.ts +1 -6
  69. package/src/index.ts +7 -3
  70. package/src/History/PixelEngineConfig.ts +0 -28
  71. package/src/Internal/_constants.ts +0 -3
  72. package/src/color.ts +0 -112
@@ -13,43 +13,7 @@ __export(errors_exports, {
13
13
  var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
14
14
  var CANVAS_CTX_FAILED = "Failed to create Canvas context";
15
15
 
16
- // src/color.ts
17
- function packColor(r, g, b, a) {
18
- return (a << 24 | b << 16 | g << 8 | r) >>> 0;
19
- }
20
- function packRGBA({
21
- r,
22
- g,
23
- b,
24
- a
25
- }) {
26
- return (a << 24 | b << 16 | g << 8 | r) >>> 0;
27
- }
28
- var unpackRed = (packed) => packed >>> 0 & 255;
29
- var unpackGreen = (packed) => packed >>> 8 & 255;
30
- var unpackBlue = (packed) => packed >>> 16 & 255;
31
- var unpackAlpha = (packed) => packed >>> 24 & 255;
32
- function unpackColor(packed) {
33
- return {
34
- r: packed >>> 0 & 255,
35
- g: packed >>> 8 & 255,
36
- b: packed >>> 16 & 255,
37
- a: packed >>> 24 & 255
38
- };
39
- }
40
- var SCRATCH_RGBA = {
41
- r: 0,
42
- g: 0,
43
- b: 0,
44
- a: 0
45
- };
46
- function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
47
- scratch.r = packed >>> 0 & 255;
48
- scratch.g = packed >>> 8 & 255;
49
- scratch.b = packed >>> 16 & 255;
50
- scratch.a = packed >>> 24 & 255;
51
- return scratch;
52
- }
16
+ // src/Color/colorDistance.ts
53
17
  function colorDistance(a, b) {
54
18
  const dr = (a & 255) - (b & 255);
55
19
  const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
@@ -57,34 +21,6 @@ function colorDistance(a, b) {
57
21
  const da = (a >>> 24 & 255) - (b >>> 24 & 255);
58
22
  return dr * dr + dg * dg + db * db + da * da;
59
23
  }
60
- function lerpColor32(a, b, t) {
61
- const r = (a & 255) + t * ((b & 255) - (a & 255));
62
- const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
63
- const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
64
- const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
65
- return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
66
- }
67
- function lerpColor32Fast(src, dst, w) {
68
- const invA = 255 - w;
69
- const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
70
- const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
71
- return (rb | ga << 8) >>> 0;
72
- }
73
- function color32ToHex(color) {
74
- const r = (color & 255).toString(16).padStart(2, "0");
75
- const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
76
- const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
77
- const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
78
- return `#${r}${g}${b}${a}`;
79
- }
80
- function color32ToCssRGBA(color) {
81
- const r = color & 255;
82
- const g = color >>> 8 & 255;
83
- const b = color >>> 16 & 255;
84
- const a = color >>> 24 & 255;
85
- const alpha = Number((a / 255).toFixed(3));
86
- return `rgba(${r},${g},${b},${alpha})`;
87
- }
88
24
 
89
25
  // src/ImageData/extractImageDataBuffer.ts
90
26
  function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
@@ -1845,9 +1781,6 @@ function makeReusableCanvasMeta(factory) {
1845
1781
  canvas.width = width;
1846
1782
  canvas.height = height;
1847
1783
  ctx.imageSmoothingEnabled = false;
1848
- } else {
1849
- ctx.setTransform(1, 0, 0, 1, 0, 0);
1850
- ctx.clearRect(0, 0, width, height);
1851
1784
  }
1852
1785
  return result;
1853
1786
  }
@@ -1968,6 +1901,96 @@ async function writeImageDataToClipboard(imageData) {
1968
1901
  return writeImgBlobToClipboard(blob);
1969
1902
  }
1970
1903
 
1904
+ // src/Color/lerpColor32.ts
1905
+ function lerpColor32(a, b, t) {
1906
+ const r = (a & 255) + t * ((b & 255) - (a & 255));
1907
+ const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
1908
+ const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
1909
+ const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
1910
+ return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
1911
+ }
1912
+ function lerpColor32Fast(src, dst, w) {
1913
+ const invA = 255 - w;
1914
+ const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
1915
+ const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
1916
+ return (rb | ga << 8) >>> 0;
1917
+ }
1918
+
1919
+ // src/Color/convert-color.ts
1920
+ function color32ToHex(color) {
1921
+ const r = (color & 255).toString(16).padStart(2, "0");
1922
+ const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
1923
+ const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
1924
+ const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
1925
+ return `#${r}${g}${b}${a}`;
1926
+ }
1927
+ function color32ToCssRGBAString(color) {
1928
+ const r = color & 255;
1929
+ const g = color >>> 8 & 255;
1930
+ const b = color >>> 16 & 255;
1931
+ const a = color >>> 24 & 255;
1932
+ const alpha = Number((a / 255).toFixed(3));
1933
+ return `rgba(${r},${g},${b},${alpha})`;
1934
+ }
1935
+ function color32ToCssRGBA(color) {
1936
+ const r = color & 255;
1937
+ const g = color >>> 8 & 255;
1938
+ const b = color >>> 16 & 255;
1939
+ const a = color >>> 24 & 255;
1940
+ return {
1941
+ r,
1942
+ g,
1943
+ b,
1944
+ a: a / 255
1945
+ };
1946
+ }
1947
+ function cssRGBAToColor32({
1948
+ r,
1949
+ g,
1950
+ b,
1951
+ a
1952
+ }) {
1953
+ return (a * 255 << 24 | b << 16 | g << 8 | r) >>> 0;
1954
+ }
1955
+
1956
+ // src/Color/pack-color.ts
1957
+ function packColor(r, g, b, a) {
1958
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1959
+ }
1960
+ function packRGBA({
1961
+ r,
1962
+ g,
1963
+ b,
1964
+ a
1965
+ }) {
1966
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1967
+ }
1968
+ var unpackRed = (packed) => packed >>> 0 & 255;
1969
+ var unpackGreen = (packed) => packed >>> 8 & 255;
1970
+ var unpackBlue = (packed) => packed >>> 16 & 255;
1971
+ var unpackAlpha = (packed) => packed >>> 24 & 255;
1972
+ function unpackColor(packed) {
1973
+ return {
1974
+ r: packed >>> 0 & 255,
1975
+ g: packed >>> 8 & 255,
1976
+ b: packed >>> 16 & 255,
1977
+ a: packed >>> 24 & 255
1978
+ };
1979
+ }
1980
+ var SCRATCH_RGBA = {
1981
+ r: 0,
1982
+ g: 0,
1983
+ b: 0,
1984
+ a: 0
1985
+ };
1986
+ function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
1987
+ scratch.r = packed >>> 0 & 255;
1988
+ scratch.g = packed >>> 8 & 255;
1989
+ scratch.b = packed >>> 16 & 255;
1990
+ scratch.a = packed >>> 24 & 255;
1991
+ return scratch;
1992
+ }
1993
+
1971
1994
  // src/Control/BatchedQueue.ts
1972
1995
  function makeBatchedQueue(processor, queue) {
1973
1996
  let activeSet = /* @__PURE__ */ new Set();
@@ -2147,15 +2170,14 @@ var PixelAccumulator = class {
2147
2170
  * @param y pixel y coordinate
2148
2171
  */
2149
2172
  storePixelBeforeState(x, y) {
2150
- const shift = this.config.tileShift;
2151
2173
  const columns = this.config.targetColumns;
2152
- const targetWidth = this.config.target.w;
2153
- const targetHeight = this.config.target.h;
2174
+ const targetWidth = this.config.targetWidth;
2175
+ const targetHeight = this.config.targetHeight;
2154
2176
  if (x < 0 || x >= targetWidth || y < 0 || y >= targetHeight) {
2155
2177
  return null;
2156
2178
  }
2157
- const tx = x >> shift;
2158
- const ty = y >> shift;
2179
+ const tx = x * this.config.invTileSize | 0;
2180
+ const ty = y * this.config.invTileSize | 0;
2159
2181
  const id = ty * columns + tx;
2160
2182
  let tile = this.lookup[id];
2161
2183
  let added = false;
@@ -2182,10 +2204,10 @@ var PixelAccumulator = class {
2182
2204
  * @param h pixel height
2183
2205
  */
2184
2206
  storeRegionBeforeState(x, y, w, h) {
2185
- const shift = this.config.tileShift;
2186
2207
  const columns = this.config.targetColumns;
2187
- const targetWidth = this.config.target.w;
2188
- const targetHeight = this.config.target.h;
2208
+ const targetWidth = this.config.targetWidth;
2209
+ const targetHeight = this.config.targetHeight;
2210
+ const invTileSize = this.config.invTileSize;
2189
2211
  const clipX1 = Math.max(0, x);
2190
2212
  const clipY1 = Math.max(0, y);
2191
2213
  const clipX2 = Math.min(targetWidth - 1, x + w - 1);
@@ -2193,10 +2215,10 @@ var PixelAccumulator = class {
2193
2215
  if (clipX2 < clipX1 || clipY2 < clipY1) {
2194
2216
  return null;
2195
2217
  }
2196
- const startX = clipX1 >> shift;
2197
- const startY = clipY1 >> shift;
2198
- const endX = clipX2 >> shift;
2199
- const endY = clipY2 >> shift;
2218
+ const startX = clipX1 * invTileSize | 0;
2219
+ const startY = clipY1 * invTileSize | 0;
2220
+ const endX = clipX2 * invTileSize | 0;
2221
+ const endY = clipY2 * invTileSize | 0;
2200
2222
  const startIndex = this.beforeTiles.length;
2201
2223
  for (let ty = startY; ty <= endY; ty++) {
2202
2224
  for (let tx = startX; tx <= endX; tx++) {
@@ -2313,31 +2335,6 @@ var PixelAccumulator = class {
2313
2335
  }
2314
2336
  };
2315
2337
 
2316
- // src/History/PixelEngineConfig.ts
2317
- var PixelEngineConfig = class {
2318
- tileSize;
2319
- // pixelX = tileX << tileShift
2320
- // pixelY = tileY << tileShift
2321
- tileShift;
2322
- tileMask;
2323
- tileArea;
2324
- target;
2325
- targetColumns = 0;
2326
- targetRows = 0;
2327
- constructor(tileSize, target) {
2328
- if ((tileSize & tileSize - 1) !== 0) {
2329
- throw new Error("tileSize must be a power of 2");
2330
- }
2331
- this.tileSize = tileSize;
2332
- this.tileShift = 31 - Math.clz32(tileSize);
2333
- this.tileMask = tileSize - 1;
2334
- this.tileArea = tileSize * tileSize;
2335
- this.target = target;
2336
- this.targetColumns = target.w + this.tileMask >> this.tileShift;
2337
- this.targetRows = target.h + this.tileMask >> this.tileShift;
2338
- }
2339
- };
2340
-
2341
2338
  // src/PixelData/applyAlphaMaskToPixelData.ts
2342
2339
  function applyAlphaMaskToPixelData(target, mask, opts) {
2343
2340
  const targetX = opts?.x ?? 0;
@@ -2531,6 +2528,8 @@ function makePixelTile(id, tx, ty, tileSize, tileArea) {
2531
2528
  id,
2532
2529
  tx,
2533
2530
  ty,
2531
+ x: tx * tileSize,
2532
+ y: ty * tileSize,
2534
2533
  w: tileSize,
2535
2534
  h: tileSize,
2536
2535
  data: data32,
@@ -2540,25 +2539,28 @@ function makePixelTile(id, tx, ty, tileSize, tileArea) {
2540
2539
 
2541
2540
  // src/Tile/TilePool.ts
2542
2541
  var TilePool = class {
2543
- constructor(config, tileFactory) {
2542
+ constructor(tileSize, tileFactory) {
2543
+ this.tileSize = tileSize;
2544
2544
  this.tileFactory = tileFactory;
2545
2545
  this.pool = [];
2546
- this.tileSize = config.tileSize;
2547
- this.tileArea = config.tileArea;
2546
+ this.tileSize = tileSize;
2547
+ this.tileArea = tileSize * tileSize;
2548
2548
  }
2549
2549
  pool;
2550
- tileSize;
2551
2550
  tileArea;
2552
2551
  getTile(id, tx, ty) {
2553
2552
  let tile = this.pool.pop();
2553
+ const tileSize = this.tileSize;
2554
2554
  if (tile) {
2555
2555
  tile.id = id;
2556
2556
  tile.tx = tx;
2557
2557
  tile.ty = ty;
2558
+ tile.x = tx * tileSize;
2559
+ tile.y = ty * tileSize;
2558
2560
  tile.data.fill(0);
2559
2561
  return tile;
2560
2562
  }
2561
- return this.tileFactory(id, tx, ty, this.tileSize, this.tileArea);
2563
+ return this.tileFactory(id, tx, ty, tileSize, this.tileArea);
2562
2564
  }
2563
2565
  releaseTile(tile) {
2564
2566
  this.pool.push(tile);
@@ -2575,6 +2577,25 @@ var TilePool = class {
2575
2577
  }
2576
2578
  };
2577
2579
 
2580
+ // src/Tile/TileTargetConfig.ts
2581
+ function makeTileTargetConfig(tileSize, target) {
2582
+ return {
2583
+ target,
2584
+ ...makeTileTargetMeta(tileSize, target)
2585
+ };
2586
+ }
2587
+ function makeTileTargetMeta(tileSize, target) {
2588
+ return {
2589
+ targetWidth: target.w,
2590
+ targetHeight: target.h,
2591
+ tileSize,
2592
+ invTileSize: 1 / tileSize,
2593
+ tileArea: tileSize * tileSize,
2594
+ targetColumns: Math.ceil(target.w / tileSize),
2595
+ targetRows: Math.ceil(target.h / tileSize)
2596
+ };
2597
+ }
2598
+
2578
2599
  // src/History/PixelWriter.ts
2579
2600
  var PixelWriter = class {
2580
2601
  historyManager;
@@ -2587,10 +2608,10 @@ var PixelWriter = class {
2587
2608
  constructor(target, mutatorFactory, options) {
2588
2609
  const tileSize = options?.tileSize ?? 256;
2589
2610
  const maxHistorySteps = options?.maxHistorySteps ?? 50;
2590
- this.config = new PixelEngineConfig(tileSize, target);
2611
+ this.config = makeTileTargetConfig(tileSize, target);
2591
2612
  this.historyManager = options?.historyManager ?? new HistoryManager(maxHistorySteps);
2592
2613
  this.historyActionFactory = options?.historyActionFactory ?? makeHistoryAction;
2593
- this.pixelTilePool = options?.pixelTilePool ?? new TilePool(this.config, makePixelTile);
2614
+ this.pixelTilePool = options?.pixelTilePool ?? new TilePool(this.config.tileSize, makePixelTile);
2594
2615
  this.accumulator = options?.accumulator ?? new PixelAccumulator(this.config, this.pixelTilePool);
2595
2616
  this.mutator = mutatorFactory(this);
2596
2617
  }
@@ -3369,18 +3390,22 @@ var mutatorBlendColorPaintBinaryMask = ((writer, deps = defaults8) => {
3369
3390
  // src/History/PixelMutator/mutatorBlendColorPaintMask.ts
3370
3391
  var defaults9 = {
3371
3392
  blendColorPixelDataAlphaMask,
3372
- blendColorPixelDataBinaryMask
3393
+ blendColorPixelDataBinaryMask,
3394
+ blendColorPixelData
3373
3395
  };
3374
3396
  var mutatorBlendColorPaintMask = ((writer, deps = defaults9) => {
3375
3397
  const {
3376
3398
  blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults9.blendColorPixelDataBinaryMask,
3377
- blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults9.blendColorPixelDataAlphaMask
3399
+ blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults9.blendColorPixelDataAlphaMask,
3400
+ blendColorPixelData: blendColorPixelData2 = defaults9.blendColorPixelData
3378
3401
  } = deps;
3379
3402
  const OPTS = {
3380
3403
  x: 0,
3381
3404
  y: 0,
3382
3405
  blendFn: sourceOverPerfect,
3383
- alpha: 255
3406
+ alpha: 255,
3407
+ w: void 0,
3408
+ h: void 0
3384
3409
  };
3385
3410
  return {
3386
3411
  blendColorPaintMask(color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
@@ -3392,11 +3417,17 @@ var mutatorBlendColorPaintMask = ((writer, deps = defaults9) => {
3392
3417
  OPTS.y = ty;
3393
3418
  OPTS.alpha = alpha;
3394
3419
  OPTS.blendFn = blendFn;
3395
- if (mask.type === 1 /* BINARY */) {
3396
- return didChange(blendColorPixelDataBinaryMask2(writer.config.target, color, mask, OPTS));
3397
- } else {
3420
+ OPTS.w = void 0;
3421
+ OPTS.h = void 0;
3422
+ if (mask.data) {
3423
+ if (mask.type === 1 /* BINARY */) {
3424
+ return didChange(blendColorPixelDataBinaryMask2(writer.config.target, color, mask, OPTS));
3425
+ }
3398
3426
  return didChange(blendColorPixelDataAlphaMask2(writer.config.target, color, mask, OPTS));
3399
3427
  }
3428
+ OPTS.w = mask.w;
3429
+ OPTS.h = mask.h;
3430
+ return didChange(blendColorPixelData2(writer.config.target, color, OPTS));
3400
3431
  }
3401
3432
  };
3402
3433
  });
@@ -5085,26 +5116,55 @@ function trimRectBounds(x, y, w, h, targetWidth, targetHeight, out) {
5085
5116
  return res;
5086
5117
  }
5087
5118
 
5119
+ // src/Tile/MaskTile.ts
5120
+ var makeAlphaMaskTile = (id, tx, ty, tileSize, tileArea) => {
5121
+ return {
5122
+ tileType: 1 /* MASK */,
5123
+ type: 0 /* ALPHA */,
5124
+ data: new Uint8Array(tileArea),
5125
+ w: tileSize,
5126
+ h: tileSize,
5127
+ x: tx * tileSize,
5128
+ y: ty * tileSize,
5129
+ id,
5130
+ tx,
5131
+ ty
5132
+ };
5133
+ };
5134
+ var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
5135
+ return {
5136
+ tileType: 1 /* MASK */,
5137
+ type: 1 /* BINARY */,
5138
+ data: new Uint8Array(tileArea),
5139
+ w: tileSize,
5140
+ h: tileSize,
5141
+ x: tx * tileSize,
5142
+ y: ty * tileSize,
5143
+ id,
5144
+ tx,
5145
+ ty
5146
+ };
5147
+ };
5148
+
5088
5149
  // src/Paint/eachTileInBounds.ts
5089
5150
  function eachTileInBounds(config, lookup, tilePool, bounds, callback) {
5090
5151
  const {
5091
- tileShift,
5092
- targetColumns,
5093
5152
  targetRows,
5153
+ targetColumns,
5094
5154
  tileSize
5095
5155
  } = config;
5096
- const x1 = Math.max(0, bounds.x >> tileShift);
5097
- const y1 = Math.max(0, bounds.y >> tileShift);
5098
- const x2 = Math.min(targetColumns - 1, bounds.x + bounds.w - 1 >> tileShift);
5099
- const y2 = Math.min(targetRows - 1, bounds.y + bounds.h - 1 >> tileShift);
5156
+ const x1 = Math.max(0, Math.floor(bounds.x / tileSize));
5157
+ const y1 = Math.max(0, Math.floor(bounds.y / tileSize));
5158
+ const x2 = Math.min(targetColumns - 1, Math.floor((bounds.x + bounds.w - 1) / tileSize));
5159
+ const y2 = Math.min(targetRows - 1, Math.floor((bounds.y + bounds.h - 1) / tileSize));
5100
5160
  if (x1 > x2 || y1 > y2) return;
5101
5161
  for (let ty = y1; ty <= y2; ty++) {
5102
5162
  const rowOffset = ty * targetColumns;
5103
- const tileTop = ty << tileShift;
5163
+ const tileTop = ty * tileSize;
5104
5164
  for (let tx = x1; tx <= x2; tx++) {
5105
5165
  const id = rowOffset + tx;
5106
5166
  const tile = lookup[id] ?? (lookup[id] = tilePool.getTile(id, tx, ty));
5107
- const tileLeft = tx << tileShift;
5167
+ const tileLeft = tx * tileSize;
5108
5168
  const startX = bounds.x > tileLeft ? bounds.x : tileLeft;
5109
5169
  const startY = bounds.y > tileTop ? bounds.y : tileTop;
5110
5170
  const maskEndX = bounds.x + bounds.w;
@@ -5120,7 +5180,7 @@ function eachTileInBounds(config, lookup, tilePool, bounds, callback) {
5120
5180
 
5121
5181
  // src/Paint/AlphaMaskPaintBuffer.ts
5122
5182
  var AlphaMaskPaintBuffer = class {
5123
- constructor(config, tilePool) {
5183
+ constructor(config, tilePool = new TilePool(config.tileSize, makeAlphaMaskTile)) {
5124
5184
  this.config = config;
5125
5185
  this.tilePool = tilePool;
5126
5186
  this.lookup = [];
@@ -5140,9 +5200,9 @@ var AlphaMaskPaintBuffer = class {
5140
5200
  const lookup = this.lookup;
5141
5201
  const tilePool = this.tilePool;
5142
5202
  const config = this.config;
5143
- const tileShift = config.tileShift;
5144
- const tileMask = config.tileMask;
5145
- const target = config.target;
5203
+ const targetW = config.targetWidth;
5204
+ const targetH = config.targetHeight;
5205
+ const tileSize = config.tileSize;
5146
5206
  const {
5147
5207
  w: bW,
5148
5208
  h: bH,
@@ -5156,7 +5216,7 @@ var AlphaMaskPaintBuffer = class {
5156
5216
  this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5157
5217
  const topLeftX = Math.floor(px + centerOffsetX);
5158
5218
  const topLeftY = Math.floor(py + centerOffsetY);
5159
- trimRectBoundsFn(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5219
+ trimRectBoundsFn(topLeftX, topLeftY, bW, bH, targetW, targetH, scratch);
5160
5220
  if (scratch.w <= 0 || scratch.h <= 0) return;
5161
5221
  eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5162
5222
  const data = tile.data;
@@ -5164,8 +5224,8 @@ var AlphaMaskPaintBuffer = class {
5164
5224
  for (let i = 0; i < bH_t; i++) {
5165
5225
  const canvasY = bY + i;
5166
5226
  const bOff = (canvasY - topLeftY) * bW;
5167
- const tOff = (canvasY & tileMask) << tileShift;
5168
- const dS = tOff + (bX & tileMask);
5227
+ const tOff = (canvasY - tile.y) * tileSize;
5228
+ const dS = tOff + (bX - tile.x);
5169
5229
  for (let j = 0; j < bW_t; j++) {
5170
5230
  const canvasX = bX + j;
5171
5231
  const brushA = bD[bOff + (canvasX - topLeftX)];
@@ -5188,9 +5248,9 @@ var AlphaMaskPaintBuffer = class {
5188
5248
  const lookup = this.lookup;
5189
5249
  const tilePool = this.tilePool;
5190
5250
  const config = this.config;
5191
- const tileShift = config.tileShift;
5192
- const tileMask = config.tileMask;
5193
- const target = config.target;
5251
+ const targetW = config.targetWidth;
5252
+ const targetH = config.targetHeight;
5253
+ const tileSize = config.tileSize;
5194
5254
  const {
5195
5255
  w: bW,
5196
5256
  h: bH,
@@ -5204,7 +5264,7 @@ var AlphaMaskPaintBuffer = class {
5204
5264
  this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5205
5265
  const topLeftX = Math.floor(px + centerOffsetX);
5206
5266
  const topLeftY = Math.floor(py + centerOffsetY);
5207
- trimRectBoundsFn(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5267
+ trimRectBoundsFn(topLeftX, topLeftY, bW, bH, targetW, targetH, scratch);
5208
5268
  if (scratch.w <= 0 || scratch.h <= 0) return;
5209
5269
  eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5210
5270
  const data = tile.data;
@@ -5212,8 +5272,8 @@ var AlphaMaskPaintBuffer = class {
5212
5272
  for (let i = 0; i < bH_t; i++) {
5213
5273
  const canvasY = bY + i;
5214
5274
  const bOff = (canvasY - topLeftY) * bW;
5215
- const tOff = (canvasY & tileMask) << tileShift;
5216
- const dS = tOff + (bX & tileMask);
5275
+ const tOff = (canvasY - tile.y) * tileSize;
5276
+ const dS = tOff + (bX - tile.x);
5217
5277
  for (let j = 0; j < bW_t; j++) {
5218
5278
  const canvasX = bX + j;
5219
5279
  if (bD[bOff + (canvasX - topLeftX)]) {
@@ -5235,9 +5295,9 @@ var AlphaMaskPaintBuffer = class {
5235
5295
  const lookup = this.lookup;
5236
5296
  const tilePool = this.tilePool;
5237
5297
  const config = this.config;
5238
- const tileShift = config.tileShift;
5239
- const tileMask = config.tileMask;
5240
- const target = config.target;
5298
+ const targetW = config.targetWidth;
5299
+ const targetH = config.targetHeight;
5300
+ const tileSize = config.tileSize;
5241
5301
  const brushWidth = brush.w;
5242
5302
  const brushHeight = brush.h;
5243
5303
  const centerOffsetX = brush.centerOffsetX;
@@ -5248,15 +5308,15 @@ var AlphaMaskPaintBuffer = class {
5248
5308
  this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5249
5309
  const topLeftX = Math.floor(px + centerOffsetX);
5250
5310
  const topLeftY = Math.floor(py + centerOffsetY);
5251
- trimRectBoundsFn(topLeftX, topLeftY, brushWidth, brushHeight, target.w, target.h, scratch);
5311
+ trimRectBoundsFn(topLeftX, topLeftY, brushWidth, brushHeight, targetW, targetH, scratch);
5252
5312
  if (scratch.w <= 0 || scratch.h <= 0) return;
5253
5313
  eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5254
5314
  const data = tile.data;
5255
5315
  let tileChanged = false;
5256
5316
  for (let i = 0; i < bH_t; i++) {
5257
5317
  const canvasY = bY + i;
5258
- const tOff = (canvasY & tileMask) << tileShift;
5259
- const dS = tOff + (bX & tileMask);
5318
+ const tOff = (canvasY - tile.y) * tileSize;
5319
+ const dS = tOff + (bX - tile.x);
5260
5320
  for (let j = 0; j < bW_t; j++) {
5261
5321
  const idx = dS + j;
5262
5322
  if (alpha > data[idx]) {
@@ -5279,7 +5339,7 @@ var AlphaMaskPaintBuffer = class {
5279
5339
 
5280
5340
  // src/Paint/BinaryMaskPaintBuffer.ts
5281
5341
  var BinaryMaskPaintBuffer = class {
5282
- constructor(config, tilePool) {
5342
+ constructor(config, tilePool = new TilePool(config.tileSize, makeBinaryMaskTile)) {
5283
5343
  this.config = config;
5284
5344
  this.tilePool = tilePool;
5285
5345
  this.lookup = [];
@@ -5299,9 +5359,9 @@ var BinaryMaskPaintBuffer = class {
5299
5359
  const lookup = this.lookup;
5300
5360
  const tilePool = this.tilePool;
5301
5361
  const config = this.config;
5302
- const tileShift = config.tileShift;
5303
- const tileMask = config.tileMask;
5304
- const target = config.target;
5362
+ const targetW = config.targetWidth;
5363
+ const targetH = config.targetHeight;
5364
+ const tileSize = config.tileSize;
5305
5365
  const {
5306
5366
  w: bW,
5307
5367
  h: bH,
@@ -5315,7 +5375,7 @@ var BinaryMaskPaintBuffer = class {
5315
5375
  this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5316
5376
  const topLeftX = Math.floor(px + centerOffsetX);
5317
5377
  const topLeftY = Math.floor(py + centerOffsetY);
5318
- trimRectBoundsFn(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5378
+ trimRectBoundsFn(topLeftX, topLeftY, bW, bH, targetW, targetH, scratch);
5319
5379
  if (scratch.w <= 0 || scratch.h <= 0) return;
5320
5380
  eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5321
5381
  const data = tile.data;
@@ -5323,8 +5383,8 @@ var BinaryMaskPaintBuffer = class {
5323
5383
  for (let i = 0; i < bH_t; i++) {
5324
5384
  const canvasY = bY + i;
5325
5385
  const bOff = (canvasY - topLeftY) * bW;
5326
- const tOff = (canvasY & tileMask) << tileShift;
5327
- const dS = tOff + (bX & tileMask);
5386
+ const tOff = (canvasY - tile.y) * tileSize;
5387
+ const dS = tOff + (bX - tile.x);
5328
5388
  for (let j = 0; j < bW_t; j++) {
5329
5389
  const canvasX = bX + j;
5330
5390
  if (bD[bOff + (canvasX - topLeftX)]) {
@@ -5346,9 +5406,9 @@ var BinaryMaskPaintBuffer = class {
5346
5406
  const lookup = this.lookup;
5347
5407
  const tilePool = this.tilePool;
5348
5408
  const config = this.config;
5349
- const tileShift = config.tileShift;
5350
- const tileMask = config.tileMask;
5351
- const target = config.target;
5409
+ const targetW = config.targetWidth;
5410
+ const targetH = config.targetHeight;
5411
+ const tileSize = config.tileSize;
5352
5412
  const brushWidth = brush.w;
5353
5413
  const brushHeight = brush.h;
5354
5414
  const centerOffsetX = brush.centerOffsetX;
@@ -5359,15 +5419,15 @@ var BinaryMaskPaintBuffer = class {
5359
5419
  this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5360
5420
  const topLeftX = Math.floor(px + centerOffsetX);
5361
5421
  const topLeftY = Math.floor(py + centerOffsetY);
5362
- trimRectBoundsFn(topLeftX, topLeftY, brushWidth, brushHeight, target.w, target.h, scratch);
5422
+ trimRectBoundsFn(topLeftX, topLeftY, brushWidth, brushHeight, targetW, targetH, scratch);
5363
5423
  if (scratch.w <= 0 || scratch.h <= 0) return;
5364
5424
  eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5365
5425
  const data = tile.data;
5366
5426
  let tileChanged = false;
5367
5427
  for (let i = 0; i < bH_t; i++) {
5368
5428
  const canvasY = bY + i;
5369
- const tOff = (canvasY & tileMask) << tileShift;
5370
- const dS = tOff + (bX & tileMask);
5429
+ const tOff = (canvasY - tile.y) * tileSize;
5430
+ const dS = tOff + (bX - tile.x);
5371
5431
  for (let j = 0; j < bW_t; j++) {
5372
5432
  const idx = dS + j;
5373
5433
  if (data[idx] === 0) {
@@ -5409,9 +5469,9 @@ var ColorPaintBuffer = class {
5409
5469
  const lookup = this.lookup;
5410
5470
  const tilePool = this.tilePool;
5411
5471
  const config = this.config;
5412
- const tileShift = config.tileShift;
5413
- const tileMask = config.tileMask;
5414
- const target = config.target;
5472
+ const tileSize = config.tileSize;
5473
+ const targetW = config.targetWidth;
5474
+ const targetH = config.targetHeight;
5415
5475
  const {
5416
5476
  w: bW,
5417
5477
  h: bH,
@@ -5424,7 +5484,7 @@ var ColorPaintBuffer = class {
5424
5484
  forEachLinePoint(x0, y0, x1, y1, (px, py) => {
5425
5485
  const topLeftX = Math.floor(px + centerOffsetX);
5426
5486
  const topLeftY = Math.floor(py + centerOffsetY);
5427
- trimRectBounds(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5487
+ trimRectBounds(topLeftX, topLeftY, bW, bH, targetW, targetH, scratch);
5428
5488
  if (scratch.w <= 0 || scratch.h <= 0) return;
5429
5489
  eachTileInBounds(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5430
5490
  const d32 = tile.data;
@@ -5432,8 +5492,8 @@ var ColorPaintBuffer = class {
5432
5492
  for (let i = 0; i < bH_t; i++) {
5433
5493
  const canvasY = bY + i;
5434
5494
  const bOff = (canvasY - topLeftY) * bW;
5435
- const tOff = (canvasY & tileMask) << tileShift;
5436
- const dS = tOff + (bX & tileMask);
5495
+ const tOff = (canvasY - tile.y) * tileSize;
5496
+ const dS = tOff + (bX - tile.x);
5437
5497
  for (let j = 0; j < bW_t; j++) {
5438
5498
  const canvasX = bX + j;
5439
5499
  const brushA = bD[bOff + (canvasX - topLeftX)];
@@ -5463,9 +5523,9 @@ var ColorPaintBuffer = class {
5463
5523
  const lookup = this.lookup;
5464
5524
  const tilePool = this.tilePool;
5465
5525
  const config = this.config;
5466
- const tileShift = config.tileShift;
5467
- const tileMask = config.tileMask;
5468
- const target = config.target;
5526
+ const tileSize = config.tileSize;
5527
+ const targetW = config.targetWidth;
5528
+ const targetH = config.targetHeight;
5469
5529
  const {
5470
5530
  w: bW,
5471
5531
  h: bH,
@@ -5477,7 +5537,7 @@ var ColorPaintBuffer = class {
5477
5537
  forEachLinePoint(x0, y0, x1, y1, (px, py) => {
5478
5538
  const topLeftX = Math.floor(px + centerOffsetX);
5479
5539
  const topLeftY = Math.floor(py + centerOffsetY);
5480
- trimRectBounds(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5540
+ trimRectBounds(topLeftX, topLeftY, bW, bH, targetW, targetH, scratch);
5481
5541
  if (scratch.w <= 0 || scratch.h <= 0) return;
5482
5542
  eachTileInBounds(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5483
5543
  const d32 = tile.data;
@@ -5485,8 +5545,8 @@ var ColorPaintBuffer = class {
5485
5545
  for (let i = 0; i < bH_t; i++) {
5486
5546
  const canvasY = bY + i;
5487
5547
  const bOff = (canvasY - topLeftY) * bW;
5488
- const tOff = (canvasY & tileMask) << tileShift;
5489
- const dS = tOff + (bX & tileMask);
5548
+ const tOff = (canvasY - tile.y) * tileSize;
5549
+ const dS = tOff + (bX - tile.x);
5490
5550
  for (let j = 0; j < bW_t; j++) {
5491
5551
  const canvasX = bX + j;
5492
5552
  if (bD[bOff + (canvasX - topLeftX)]) {
@@ -5510,9 +5570,9 @@ var ColorPaintBuffer = class {
5510
5570
  const lookup = this.lookup;
5511
5571
  const tilePool = this.tilePool;
5512
5572
  const config = this.config;
5513
- const tileShift = config.tileShift;
5514
- const tileMask = config.tileMask;
5515
- const target = config.target;
5573
+ const targetW = config.targetWidth;
5574
+ const targetH = config.targetHeight;
5575
+ const tileSize = config.tileSize;
5516
5576
  const brushWidth = brush.w;
5517
5577
  const brushHeight = brush.h;
5518
5578
  const centerOffsetX = brush.centerOffsetX;
@@ -5521,15 +5581,15 @@ var ColorPaintBuffer = class {
5521
5581
  forEachLinePoint(x0, y0, x1, y1, (px, py) => {
5522
5582
  const topLeftX = Math.floor(px + centerOffsetX);
5523
5583
  const topLeftY = Math.floor(py + centerOffsetY);
5524
- trimRectBounds(topLeftX, topLeftY, brushWidth, brushHeight, target.w, target.h, scratch);
5584
+ trimRectBounds(topLeftX, topLeftY, brushWidth, brushHeight, targetW, targetH, scratch);
5525
5585
  if (scratch.w <= 0 || scratch.h <= 0) return;
5526
5586
  eachTileInBounds(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5527
5587
  const d32 = tile.data;
5528
5588
  let tileChanged = false;
5529
5589
  for (let i = 0; i < bH_t; i++) {
5530
5590
  const canvasY = bY + i;
5531
- const tOff = (canvasY & tileMask) << tileShift;
5532
- const dS = tOff + (bX & tileMask);
5591
+ const tOff = (canvasY - tile.y) * tileSize;
5592
+ const dS = tOff + (bX - tile.x);
5533
5593
  for (let j = 0; j < bW_t; j++) {
5534
5594
  const idx = dS + j;
5535
5595
  if (d32[idx] !== color) {
@@ -5561,7 +5621,6 @@ var SCRATCH_OPTS = {
5561
5621
  };
5562
5622
  function commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha = 255, blendFn = sourceOverPerfect, blendColorPixelDataMaskFn) {
5563
5623
  const config = accumulator.config;
5564
- const tileShift = config.tileShift;
5565
5624
  const lookup = paintBuffer.lookup;
5566
5625
  SCRATCH_OPTS.alpha = alpha;
5567
5626
  SCRATCH_OPTS.blendFn = blendFn;
@@ -5569,10 +5628,8 @@ function commitMaskPaintBuffer(accumulator, paintBuffer, color, alpha = 255, ble
5569
5628
  const tile = lookup[i];
5570
5629
  if (tile) {
5571
5630
  const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5572
- const dx = tile.tx << tileShift;
5573
- const dy = tile.ty << tileShift;
5574
- SCRATCH_OPTS.x = dx;
5575
- SCRATCH_OPTS.y = dy;
5631
+ SCRATCH_OPTS.x = tile.x;
5632
+ SCRATCH_OPTS.y = tile.y;
5576
5633
  SCRATCH_OPTS.w = tile.w;
5577
5634
  SCRATCH_OPTS.h = tile.h;
5578
5635
  didChange(blendColorPixelDataMaskFn(config.target, color, tile, SCRATCH_OPTS));
@@ -5588,49 +5645,51 @@ function makeAlphaMaskPaintBufferCommitter(accumulator, paintBuffer) {
5588
5645
  };
5589
5646
  }
5590
5647
 
5591
- // src/Internal/_constants.ts
5592
- var DEFAULT_CANVAS_FACTORY = (w, h) => new OffscreenCanvas(w, h);
5593
-
5594
- // src/Tile/MaskTile.ts
5595
- var makeAlphaMaskTile = (id, tx, ty, tileSize, tileArea) => {
5596
- return {
5597
- tileType: 1 /* MASK */,
5598
- type: 0 /* ALPHA */,
5599
- data: new Uint8Array(tileArea),
5600
- w: tileSize,
5601
- h: tileSize,
5602
- id,
5603
- tx,
5604
- ty
5648
+ // src/PixelData/ReusablePixelData.ts
5649
+ function makeReusablePixelData() {
5650
+ const pixelData = {
5651
+ w: 0,
5652
+ h: 0,
5653
+ data: null,
5654
+ imageData: null
5605
5655
  };
5606
- };
5607
- var makeBinaryMaskTile = (id, tx, ty, tileSize, tileArea) => {
5608
- return {
5609
- tileType: 1 /* MASK */,
5610
- type: 1 /* BINARY */,
5611
- data: new Uint8Array(tileArea),
5612
- w: tileSize,
5613
- h: tileSize,
5614
- id,
5615
- tx,
5616
- ty
5656
+ return function getReusablePixelData(width, height) {
5657
+ if (pixelData.w !== width || pixelData.h !== height) {
5658
+ setPixelData(pixelData, new ImageData(width, height));
5659
+ } else {
5660
+ pixelData.data.fill(0);
5661
+ }
5662
+ return pixelData;
5617
5663
  };
5618
- };
5664
+ }
5619
5665
 
5620
5666
  // src/Paint/Render/AlphaMaskPaintBufferCanvasRenderer.ts
5621
- function makeAlphaMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5622
- const config = paintBuffer.config;
5623
- const tileSize = config.tileSize;
5624
- const tileShift = config.tileShift;
5625
- const tileArea = config.tileArea;
5626
- const lookup = paintBuffer.lookup;
5627
- const canvas = canvasFactory(tileSize, tileSize);
5628
- const ctx = canvas.getContext("2d");
5629
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5630
- ctx.imageSmoothingEnabled = false;
5631
- const bridge = makePixelData(new ImageData(tileSize, tileSize));
5632
- const view32 = bridge.data;
5633
- return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5667
+ function makeAlphaMaskPaintBufferCanvasRenderer(paintBuffer, reusableCanvasFactory) {
5668
+ const factory = reusableCanvasFactory ?? makeReusableOffscreenCanvas;
5669
+ const getBuffer = factory();
5670
+ const getBridge = makeReusablePixelData();
5671
+ let config;
5672
+ let tileSize;
5673
+ let tileArea;
5674
+ let lookup;
5675
+ let view32;
5676
+ let bridge;
5677
+ let canvas;
5678
+ let ctx;
5679
+ setBuffer(paintBuffer);
5680
+ function setBuffer(value) {
5681
+ paintBuffer = value;
5682
+ config = paintBuffer.config;
5683
+ tileSize = config.tileSize;
5684
+ tileArea = config.tileArea;
5685
+ lookup = paintBuffer.lookup;
5686
+ bridge = getBridge(tileSize, tileSize);
5687
+ view32 = bridge.data;
5688
+ const buff = getBuffer(tileSize, tileSize);
5689
+ canvas = buff.canvas;
5690
+ ctx = buff.ctx;
5691
+ }
5692
+ function draw(targetCtx, color, alpha = 255, compOperation = "source-over") {
5634
5693
  if (alpha === 0) return;
5635
5694
  const baseSrcAlpha = color >>> 24;
5636
5695
  const colorRGB = color & 16777215;
@@ -5653,29 +5712,31 @@ function makeAlphaMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEF
5653
5712
  view32[p] = (colorRGB | finalA << 24) >>> 0;
5654
5713
  }
5655
5714
  }
5656
- const dx = tile.tx << tileShift;
5657
- const dy = tile.ty << tileShift;
5658
5715
  ctx.putImageData(bridge.imageData, 0, 0);
5659
- targetCtx.drawImage(canvas, dx, dy);
5716
+ targetCtx.drawImage(canvas, tile.x, tile.y);
5660
5717
  }
5661
5718
  }
5662
5719
  targetCtx.globalAlpha = 1;
5663
5720
  targetCtx.globalCompositeOperation = "source-over";
5721
+ }
5722
+ return {
5723
+ draw,
5724
+ setBuffer
5664
5725
  };
5665
5726
  }
5666
5727
 
5667
5728
  // src/Paint/Commit/AlphaMaskPaintBufferManager.ts
5668
- function makeAlphaMaskPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5669
- const pool = new TilePool(writer.config, makeAlphaMaskTile);
5729
+ function makeAlphaMaskPaintBufferManager(writer, reusableCanvasFactory) {
5730
+ const pool = new TilePool(writer.config.tileSize, makeAlphaMaskTile);
5670
5731
  const buffer = new AlphaMaskPaintBuffer(writer.config, pool);
5671
- const draw = makeAlphaMaskPaintBufferCanvasRenderer(buffer, canvasFactory);
5732
+ const renderer = makeAlphaMaskPaintBufferCanvasRenderer(buffer, reusableCanvasFactory);
5672
5733
  return {
5673
5734
  clear: buffer.clear.bind(buffer),
5674
5735
  paintRect: buffer.paintRect.bind(buffer),
5675
5736
  paintAlphaMask: buffer.paintAlphaMask.bind(buffer),
5676
5737
  paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5677
5738
  commit: makeAlphaMaskPaintBufferCommitter(writer.accumulator, buffer),
5678
- draw
5739
+ renderer
5679
5740
  };
5680
5741
  }
5681
5742
 
@@ -5687,19 +5748,32 @@ function makeBinaryMaskPaintBufferCommitter(accumulator, paintBuffer) {
5687
5748
  }
5688
5749
 
5689
5750
  // src/Paint/Render/BinaryMaskPaintBufferCanvasRenderer.ts
5690
- function makeBinaryMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5691
- const config = paintBuffer.config;
5692
- const tileSize = config.tileSize;
5693
- const tileShift = config.tileShift;
5694
- const tileArea = config.tileArea;
5695
- const lookup = paintBuffer.lookup;
5696
- const canvas = canvasFactory(tileSize, tileSize);
5697
- const ctx = canvas.getContext("2d");
5698
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5699
- ctx.imageSmoothingEnabled = false;
5700
- const bridge = makePixelData(new ImageData(tileSize, tileSize));
5701
- const view32 = bridge.data;
5702
- return function drawPaintBuffer(targetCtx, color, alpha = 255, compOperation = "source-over") {
5751
+ function makeBinaryMaskPaintBufferCanvasRenderer(paintBuffer, reusableCanvasFactory) {
5752
+ const factory = reusableCanvasFactory ?? makeReusableOffscreenCanvas;
5753
+ const getBuffer = factory();
5754
+ const getBridge = makeReusablePixelData();
5755
+ let config;
5756
+ let tileSize;
5757
+ let tileArea;
5758
+ let lookup;
5759
+ let view32;
5760
+ let bridge;
5761
+ let canvas;
5762
+ let ctx;
5763
+ setBuffer(paintBuffer);
5764
+ function setBuffer(value) {
5765
+ paintBuffer = value;
5766
+ config = paintBuffer.config;
5767
+ tileSize = config.tileSize;
5768
+ tileArea = config.tileArea;
5769
+ lookup = paintBuffer.lookup;
5770
+ bridge = getBridge(tileSize, tileSize);
5771
+ view32 = bridge.data;
5772
+ const buff = getBuffer(tileSize, tileSize);
5773
+ canvas = buff.canvas;
5774
+ ctx = buff.ctx;
5775
+ }
5776
+ function draw(targetCtx, color, alpha = 255, compOperation = "source-over") {
5703
5777
  if (alpha === 0) return;
5704
5778
  const baseSrcAlpha = color >>> 24;
5705
5779
  if (baseSrcAlpha === 0) return;
@@ -5715,28 +5789,30 @@ function makeBinaryMaskPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DE
5715
5789
  view32[p] = color;
5716
5790
  }
5717
5791
  }
5718
- const dx = tile.tx << tileShift;
5719
- const dy = tile.ty << tileShift;
5720
5792
  ctx.putImageData(bridge.imageData, 0, 0);
5721
- targetCtx.drawImage(canvas, dx, dy);
5793
+ targetCtx.drawImage(canvas, tile.x, tile.y);
5722
5794
  }
5723
5795
  }
5724
5796
  targetCtx.globalAlpha = 1;
5725
5797
  targetCtx.globalCompositeOperation = "source-over";
5798
+ }
5799
+ return {
5800
+ draw,
5801
+ setBuffer
5726
5802
  };
5727
5803
  }
5728
5804
 
5729
5805
  // src/Paint/Commit/BinaryMaskPaintBufferManager.ts
5730
- function makeBinaryMaskPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5731
- const pool = new TilePool(writer.config, makeBinaryMaskTile);
5806
+ function makeBinaryMaskPaintBufferManager(writer, reusableCanvasFactory) {
5807
+ const pool = new TilePool(writer.config.tileSize, makeBinaryMaskTile);
5732
5808
  const buffer = new BinaryMaskPaintBuffer(writer.config, pool);
5733
- const draw = makeBinaryMaskPaintBufferCanvasRenderer(buffer, canvasFactory);
5809
+ const renderer = makeBinaryMaskPaintBufferCanvasRenderer(buffer, reusableCanvasFactory);
5734
5810
  return {
5735
5811
  clear: buffer.clear.bind(buffer),
5736
5812
  paintRect: buffer.paintRect.bind(buffer),
5737
5813
  paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5738
5814
  commit: makeBinaryMaskPaintBufferCommitter(writer.accumulator, buffer),
5739
- draw
5815
+ renderer
5740
5816
  };
5741
5817
  }
5742
5818
 
@@ -5751,7 +5827,6 @@ var SCRATCH_OPTS2 = {
5751
5827
  };
5752
5828
  function commitColorPaintBuffer(accumulator, paintBuffer, alpha = 255, blendFn = sourceOverPerfect, blendPixelDataFn = blendPixelData) {
5753
5829
  const config = accumulator.config;
5754
- const tileShift = config.tileShift;
5755
5830
  const lookup = paintBuffer.lookup;
5756
5831
  SCRATCH_OPTS2.alpha = alpha;
5757
5832
  SCRATCH_OPTS2.blendFn = blendFn;
@@ -5759,10 +5834,8 @@ function commitColorPaintBuffer(accumulator, paintBuffer, alpha = 255, blendFn =
5759
5834
  const tile = lookup[i];
5760
5835
  if (tile) {
5761
5836
  const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5762
- const dx = tile.tx << tileShift;
5763
- const dy = tile.ty << tileShift;
5764
- SCRATCH_OPTS2.x = dx;
5765
- SCRATCH_OPTS2.y = dy;
5837
+ SCRATCH_OPTS2.x = tile.x;
5838
+ SCRATCH_OPTS2.y = tile.y;
5766
5839
  SCRATCH_OPTS2.w = tile.w;
5767
5840
  SCRATCH_OPTS2.h = tile.h;
5768
5841
  didChange(blendPixelDataFn(config.target, tile, SCRATCH_OPTS2));
@@ -5779,44 +5852,47 @@ function makeColorPaintBufferCommitter(accumulator, paintBuffer) {
5779
5852
  }
5780
5853
 
5781
5854
  // src/Paint/Render/ColorPaintBufferCanvasRenderer.ts
5782
- function makeColorPaintBufferCanvasRenderer(paintBuffer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5783
- const config = paintBuffer.config;
5784
- const tileSize = config.tileSize;
5785
- const tileShift = config.tileShift;
5786
- const lookup = paintBuffer.lookup;
5787
- const canvas = canvasFactory(tileSize, tileSize);
5788
- const ctx = canvas.getContext("2d");
5789
- if (!ctx) throw new Error(CANVAS_CTX_FAILED);
5790
- ctx.imageSmoothingEnabled = false;
5791
- return function drawPaintBuffer(targetCtx, alpha = 255, compOperation = "source-over") {
5855
+ function makeColorPaintBufferCanvasRenderer(paintBuffer, reusableCanvasFactory) {
5856
+ const factory = reusableCanvasFactory ?? makeReusableOffscreenCanvas;
5857
+ const getBuffer = factory();
5858
+ function draw(targetCtx, alpha = 255, compOperation = "source-over") {
5859
+ const buff = getBuffer(paintBuffer.config.tileSize, paintBuffer.config.tileSize);
5860
+ const lookup = paintBuffer.lookup;
5861
+ const length = lookup.length;
5862
+ const ctx = buff.ctx;
5863
+ const canvas = buff.canvas;
5792
5864
  targetCtx.globalAlpha = alpha / 255;
5793
5865
  targetCtx.globalCompositeOperation = compOperation;
5794
- for (let i = 0; i < lookup.length; i++) {
5866
+ for (let i = 0; i < length; i++) {
5795
5867
  const tile = lookup[i];
5796
5868
  if (tile) {
5797
- const dx = tile.tx << tileShift;
5798
- const dy = tile.ty << tileShift;
5799
5869
  ctx.putImageData(tile.imageData, 0, 0);
5800
- targetCtx.drawImage(canvas, dx, dy);
5870
+ targetCtx.drawImage(canvas, tile.x, tile.y);
5801
5871
  }
5802
5872
  }
5803
5873
  targetCtx.globalAlpha = 1;
5804
5874
  targetCtx.globalCompositeOperation = "source-over";
5875
+ }
5876
+ return {
5877
+ draw,
5878
+ setBuffer(value) {
5879
+ paintBuffer = value;
5880
+ }
5805
5881
  };
5806
5882
  }
5807
5883
 
5808
5884
  // src/Paint/Commit/ColorPaintBufferManager.ts
5809
- function makeColorPaintBufferManager(writer, canvasFactory = DEFAULT_CANVAS_FACTORY) {
5810
- const pool = new TilePool(writer.config, makePixelTile);
5885
+ function makeColorPaintBufferManager(writer, reusableCanvasFactory) {
5886
+ const pool = new TilePool(writer.config.tileSize, makePixelTile);
5811
5887
  const buffer = new ColorPaintBuffer(writer.config, pool);
5812
- const draw = makeColorPaintBufferCanvasRenderer(buffer, canvasFactory);
5888
+ const renderer = makeColorPaintBufferCanvasRenderer(buffer, reusableCanvasFactory);
5813
5889
  return {
5814
5890
  clear: buffer.clear.bind(buffer),
5815
5891
  paintRect: buffer.paintRect.bind(buffer),
5816
5892
  paintAlphaMask: buffer.paintAlphaMask.bind(buffer),
5817
5893
  paintBinaryMask: buffer.paintBinaryMask.bind(buffer),
5818
5894
  commit: makeColorPaintBufferCommitter(writer.accumulator, buffer),
5819
- draw
5895
+ renderer
5820
5896
  };
5821
5897
  }
5822
5898
 
@@ -5952,24 +6028,6 @@ function makePaintRect(w, h) {
5952
6028
  };
5953
6029
  }
5954
6030
 
5955
- // src/PixelData/ReusablePixelData.ts
5956
- function makeReusablePixelData() {
5957
- const pixelData = {
5958
- w: 0,
5959
- h: 0,
5960
- data: null,
5961
- imageData: null
5962
- };
5963
- return function getReusablePixelData(width, height) {
5964
- if (pixelData.w !== width || pixelData.h !== height) {
5965
- setPixelData(pixelData, new ImageData(width, height));
5966
- } else {
5967
- pixelData.data.fill(0);
5968
- }
5969
- return pixelData;
5970
- };
5971
- }
5972
-
5973
6031
  // src/Paint/Render/PaintCursorRenderer.ts
5974
6032
  function makePaintCursorRenderer(reusableCanvasFactory) {
5975
6033
  const factory = reusableCanvasFactory ?? makeReusableOffscreenCanvas;
@@ -6122,20 +6180,29 @@ var SCRATCH_OPTS5 = {
6122
6180
  x: 0,
6123
6181
  y: 0,
6124
6182
  alpha: 255,
6125
- blendFn: sourceOverPerfect
6183
+ blendFn: sourceOverPerfect,
6184
+ w: void 0,
6185
+ h: void 0
6126
6186
  };
6127
- function blendColorPixelDataPaintMask(dst, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
6187
+ function blendColorPixelDataPaintMask(target, color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
6128
6188
  const tx = x + mask.centerOffsetX;
6129
6189
  const ty = y + mask.centerOffsetY;
6130
6190
  SCRATCH_OPTS5.x = tx;
6131
6191
  SCRATCH_OPTS5.y = ty;
6132
6192
  SCRATCH_OPTS5.alpha = alpha;
6133
6193
  SCRATCH_OPTS5.blendFn = blendFn;
6134
- if (mask.type === 1 /* BINARY */) {
6135
- return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS5);
6136
- } else {
6137
- return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS5);
6194
+ SCRATCH_OPTS5.w = void 0;
6195
+ SCRATCH_OPTS5.h = void 0;
6196
+ if (mask.data) {
6197
+ if (mask.type === 1 /* BINARY */) {
6198
+ return blendColorPixelDataBinaryMask(target, color, mask, SCRATCH_OPTS5);
6199
+ } else {
6200
+ return blendColorPixelDataAlphaMask(target, color, mask, SCRATCH_OPTS5);
6201
+ }
6138
6202
  }
6203
+ SCRATCH_OPTS5.w = mask.w;
6204
+ SCRATCH_OPTS5.h = mask.h;
6205
+ return blendColorPixelData(target, color, SCRATCH_OPTS5);
6139
6206
  }
6140
6207
 
6141
6208
  // src/PixelData/blendPixelDataMask.ts
@@ -6155,13 +6222,12 @@ var SCRATCH_OPTS6 = {
6155
6222
  blendFn: void 0
6156
6223
  };
6157
6224
  function blendPixelDataPaintBuffer(target, paintBuffer, alpha = 255, blendFn, blendPixelDataFn = blendPixelData) {
6158
- const tileShift = paintBuffer.config.tileShift;
6159
6225
  const lookup = paintBuffer.lookup;
6160
6226
  for (let i = 0; i < lookup.length; i++) {
6161
6227
  const tile = lookup[i];
6162
6228
  if (tile) {
6163
- const x = tile.tx << tileShift;
6164
- const y = tile.ty << tileShift;
6229
+ const x = tile.x;
6230
+ const y = tile.y;
6165
6231
  SCRATCH_OPTS6.x = x;
6166
6232
  SCRATCH_OPTS6.y = y;
6167
6233
  SCRATCH_OPTS6.alpha = alpha;
@@ -6580,14 +6646,11 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
6580
6646
 
6581
6647
  // src/PixelData/writePaintBufferToPixelData.ts
6582
6648
  function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn = writePixelDataBuffer) {
6583
- const tileShift = paintBuffer.config.tileShift;
6584
6649
  const lookup = paintBuffer.lookup;
6585
6650
  for (let i = 0; i < lookup.length; i++) {
6586
6651
  const tile = lookup[i];
6587
6652
  if (tile) {
6588
- const dx = tile.tx << tileShift;
6589
- const dy = tile.ty << tileShift;
6590
- writePixelDataBufferFn(target, tile.data, dx, dy, tile.w, tile.h);
6653
+ writePixelDataBufferFn(target, tile.data, tile.x, tile.y, tile.w, tile.h);
6591
6654
  }
6592
6655
  }
6593
6656
  }
@@ -6639,7 +6702,6 @@ export {
6639
6702
  MaskType,
6640
6703
  PaintMaskOutline,
6641
6704
  PixelAccumulator,
6642
- PixelEngineConfig,
6643
6705
  PixelWriter,
6644
6706
  TilePool,
6645
6707
  TileType,
@@ -6666,6 +6728,7 @@ export {
6666
6728
  blendPixelDataPaintBuffer,
6667
6729
  clearPixelDataFast,
6668
6730
  color32ToCssRGBA,
6731
+ color32ToCssRGBAString,
6669
6732
  color32ToHex,
6670
6733
  colorBurnFast,
6671
6734
  colorBurnPerfect,
@@ -6679,6 +6742,7 @@ export {
6679
6742
  copyMask,
6680
6743
  copyPixelData,
6681
6744
  cropPixelData,
6745
+ cssRGBAToColor32,
6682
6746
  darkenFast,
6683
6747
  darkenPerfect,
6684
6748
  darkerFast,
@@ -6791,6 +6855,8 @@ export {
6791
6855
  makeReusableImageData,
6792
6856
  makeReusableOffscreenCanvas,
6793
6857
  makeReusablePixelData,
6858
+ makeTileTargetConfig,
6859
+ makeTileTargetMeta,
6794
6860
  merge2BinaryMaskRects,
6795
6861
  mergeAlphaMasks,
6796
6862
  mergeBinaryMaskRects,