pixel-data-js 0.26.0 → 0.28.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 (139) hide show
  1. package/README.md +12 -2
  2. package/dist/index.prod.cjs +2227 -1050
  3. package/dist/index.prod.cjs.map +1 -1
  4. package/dist/index.prod.d.ts +549 -424
  5. package/dist/index.prod.js +2171 -1028
  6. package/dist/index.prod.js.map +1 -1
  7. package/package.json +11 -11
  8. package/src/Algorithm/floodFillSelection.ts +8 -6
  9. package/src/Algorithm/forEachLinePoint.ts +6 -6
  10. package/src/{Internal/resample32.ts → Algorithm/resampleUint32Array.ts} +11 -21
  11. package/src/BlendModes/blend-modes-fast.ts +169 -0
  12. package/src/BlendModes/blend-modes-perfect.ts +207 -0
  13. package/src/BlendModes/blend-modes.ts +9 -0
  14. package/src/Canvas/CanvasFrameRenderer.ts +20 -28
  15. package/src/Canvas/CanvasPixelDataRenderer.ts +23 -0
  16. package/src/Canvas/PixelCanvas.ts +2 -7
  17. package/src/Canvas/ReusableCanvas.ts +4 -12
  18. package/src/Canvas/_canvas-types.ts +26 -0
  19. package/src/History/PixelAccumulator.ts +17 -17
  20. package/src/History/PixelEngineConfig.ts +3 -3
  21. package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +4 -3
  22. package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +4 -3
  23. package/src/History/PixelMutator/mutatorApplyMask.ts +4 -3
  24. package/src/History/PixelMutator/mutatorBlendAlphaMask.ts +6 -4
  25. package/src/History/PixelMutator/mutatorBlendBinaryMask.ts +6 -4
  26. package/src/History/PixelMutator/mutatorBlendColor.ts +2 -2
  27. package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +2 -1
  28. package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +2 -1
  29. package/src/History/PixelMutator/mutatorBlendColorPaintMask.ts +3 -1
  30. package/src/History/PixelMutator/{mutatorBlendPaintRect.ts → mutatorBlendColorPaintRect.ts} +5 -5
  31. package/src/History/PixelMutator/mutatorBlendMask.ts +6 -4
  32. package/src/History/PixelMutator/mutatorBlendPixelData.ts +5 -4
  33. package/src/History/PixelMutator/mutatorClear.ts +4 -3
  34. package/src/History/PixelMutator/mutatorFill.ts +5 -4
  35. package/src/History/PixelMutator/mutatorFillBinaryMask.ts +2 -1
  36. package/src/History/PixelMutator/mutatorInvert.ts +2 -2
  37. package/src/History/PixelMutator.ts +2 -2
  38. package/src/History/PixelPatchTiles.ts +7 -7
  39. package/src/History/PixelWriter.ts +12 -63
  40. package/src/ImageData/ImageDataLike.ts +1 -1
  41. package/src/ImageData/_ImageData-types.ts +13 -0
  42. package/src/ImageData/copyImageData.ts +1 -1
  43. package/src/ImageData/extractImageDataBuffer.ts +3 -2
  44. package/src/ImageData/imageDataToUint32Array.ts +18 -0
  45. package/src/ImageData/resampleImageData.ts +3 -3
  46. package/src/ImageData/resizeImageData.ts +1 -1
  47. package/src/ImageData/serialization.ts +1 -1
  48. package/src/ImageData/uInt32ArrayToImageData.ts +1 -1
  49. package/src/ImageData/writeImageData.ts +2 -2
  50. package/src/ImageData/writeImageDataBuffer.ts +2 -2
  51. package/src/IndexedImage/IndexedImage.ts +56 -98
  52. package/src/IndexedImage/_indexedImage-types.ts +18 -0
  53. package/src/IndexedImage/getIndexedImageColorCounts.ts +3 -3
  54. package/src/IndexedImage/indexedImageToAverageColor.ts +1 -1
  55. package/src/IndexedImage/indexedImageToImageData.ts +4 -6
  56. package/src/IndexedImage/resampleIndexedImage.ts +7 -15
  57. package/src/Input/fileToImageData.ts +1 -1
  58. package/src/Internal/_errors.ts +2 -0
  59. package/src/Internal/macros.ts +14 -0
  60. package/src/Mask/AlphaMask.ts +1 -1
  61. package/src/Mask/BinaryMask/makeBinaryMaskFromAlphaMask.ts +23 -0
  62. package/src/Mask/BinaryMask/makeBinaryMaskOutline.ts +88 -0
  63. package/src/Mask/BinaryMask/makeCircleBinaryMaskOutline.ts +104 -0
  64. package/src/Mask/BinaryMask/makeRectBinaryMaskOutline.ts +34 -0
  65. package/src/Mask/BinaryMask.ts +1 -1
  66. package/src/Mask/_mask-types.ts +73 -0
  67. package/src/Mask/applyBinaryMaskToAlphaMask.ts +2 -1
  68. package/src/Mask/copyMask.ts +1 -1
  69. package/src/Mask/extractMask.ts +2 -1
  70. package/src/Mask/extractMaskBuffer.ts +1 -1
  71. package/src/Mask/mergeAlphaMasks.ts +6 -3
  72. package/src/Mask/mergeBinaryMasks.ts +2 -1
  73. package/src/Mask/setMaskData.ts +1 -1
  74. package/src/MaskRect/merge2BinaryMaskRects.ts +2 -2
  75. package/src/MaskRect/mergeBinaryMaskRects.ts +1 -1
  76. package/src/MaskRect/subtractBinaryMaskRects.ts +1 -1
  77. package/src/Paint/AlphaMaskPaintBuffer.ts +339 -0
  78. package/src/Paint/AlphaMaskPaintBufferCanvasRenderer.ts +78 -0
  79. package/src/Paint/BinaryMaskPaintBuffer.ts +254 -0
  80. package/src/Paint/BinaryMaskPaintBufferCanvasRenderer.ts +67 -0
  81. package/src/Paint/{PaintBuffer.ts → ColorPaintBuffer.ts} +148 -77
  82. package/src/Paint/{PaintBufferCanvasRenderer.ts → ColorPaintBufferCanvasRenderer.ts} +6 -5
  83. package/src/Paint/PaintCursorRenderer.ts +117 -0
  84. package/src/Paint/_paint-types.ts +22 -0
  85. package/src/Paint/eachTileInBounds.ts +45 -0
  86. package/src/Paint/makeCirclePaintMask.ts +74 -0
  87. package/src/Paint/makePaintMask.ts +5 -2
  88. package/src/Paint/makeRectFalloffPaintAlphaMask.ts +4 -2
  89. package/src/PixelData/PixelData.ts +15 -19
  90. package/src/PixelData/ReusablePixelData.ts +36 -0
  91. package/src/PixelData/_pixelData-types.ts +17 -0
  92. package/src/PixelData/applyAlphaMaskToPixelData.ts +80 -43
  93. package/src/PixelData/applyBinaryMaskToPixelData.ts +10 -8
  94. package/src/PixelData/applyMaskToPixelData.ts +4 -9
  95. package/src/PixelData/blendColorPixelData.ts +9 -8
  96. package/src/PixelData/blendColorPixelDataAlphaMask.ts +9 -7
  97. package/src/PixelData/blendColorPixelDataBinaryMask.ts +9 -7
  98. package/src/PixelData/blendColorPixelDataMask.ts +4 -2
  99. package/src/PixelData/blendColorPixelDataPaintAlphaMask.ts +4 -2
  100. package/src/PixelData/blendColorPixelDataPaintBinaryMask.ts +4 -2
  101. package/src/PixelData/blendColorPixelDataPaintMask.ts +5 -2
  102. package/src/PixelData/blendPixel.ts +6 -5
  103. package/src/PixelData/blendPixelData.ts +14 -13
  104. package/src/PixelData/blendPixelDataAlphaMask.ts +15 -13
  105. package/src/PixelData/blendPixelDataBinaryMask.ts +15 -13
  106. package/src/PixelData/blendPixelDataMask.ts +5 -3
  107. package/src/PixelData/blendPixelDataPaintBuffer.ts +5 -4
  108. package/src/PixelData/clearPixelDataFast.ts +4 -2
  109. package/src/PixelData/copyPixelData.ts +14 -0
  110. package/src/PixelData/extractPixelData.ts +8 -7
  111. package/src/PixelData/extractPixelDataBuffer.ts +9 -8
  112. package/src/PixelData/fillPixelData.ts +16 -14
  113. package/src/PixelData/fillPixelDataBinaryMask.ts +10 -8
  114. package/src/PixelData/fillPixelDataFast.ts +16 -14
  115. package/src/PixelData/invertPixelData.ts +9 -8
  116. package/src/PixelData/pixelDataToAlphaMask.ts +9 -8
  117. package/src/PixelData/reflectPixelData.ts +9 -9
  118. package/src/PixelData/resamplePixelData.ts +20 -9
  119. package/src/PixelData/rotatePixelData.ts +8 -7
  120. package/src/PixelData/uInt32ArrayToPixelData.ts +15 -0
  121. package/src/PixelData/writePaintBufferToPixelData.ts +5 -5
  122. package/src/PixelData/writePixelDataBuffer.ts +10 -9
  123. package/src/Rect/_rect-types.ts +7 -0
  124. package/src/Rect/getRectsBounds.ts +1 -1
  125. package/src/Rect/trimMaskRectBounds.ts +2 -1
  126. package/src/Rect/trimRectBounds.ts +1 -1
  127. package/src/Tile/MaskTile.ts +40 -0
  128. package/src/Tile/PixelTile.ts +23 -0
  129. package/src/{PixelTile/PixelTilePool.ts → Tile/TilePool.ts} +9 -9
  130. package/src/Tile/_tile-types.ts +33 -0
  131. package/src/_errors.ts +1 -0
  132. package/src/_types.ts +2 -118
  133. package/src/index.ts +47 -22
  134. package/src/ImageData/imageDataToUInt32Array.ts +0 -13
  135. package/src/Internal/helpers.ts +0 -5
  136. package/src/Paint/makeCirclePaintAlphaMask.ts +0 -41
  137. package/src/Paint/makeCirclePaintBinaryMask.ts +0 -29
  138. package/src/PixelTile/PixelTile.ts +0 -21
  139. /package/src/{Internal → Rect}/resolveClipping.ts +0 -0
@@ -1,9 +1,17 @@
1
- // src/_types.ts
2
- var MaskType = /* @__PURE__ */ ((MaskType2) => {
3
- MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
4
- MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
5
- return MaskType2;
6
- })(MaskType || {});
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // src/Internal/_errors.ts
8
+ var errors_exports = {};
9
+ __export(errors_exports, {
10
+ CANVAS_CTX_FAILED: () => CANVAS_CTX_FAILED,
11
+ OFFSCREEN_CANVAS_CTX_FAILED: () => OFFSCREEN_CANVAS_CTX_FAILED
12
+ });
13
+ var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
14
+ var CANVAS_CTX_FAILED = "Failed to create Canvas context";
7
15
 
8
16
  // src/color.ts
9
17
  function packColor(r, g, b, a) {
@@ -78,7 +86,7 @@ function color32ToCssRGBA(color) {
78
86
  return `rgba(${r},${g},${b},${alpha})`;
79
87
  }
80
88
 
81
- // src/Internal/resolveClipping.ts
89
+ // src/Rect/resolveClipping.ts
82
90
  var makeClippedRect = () => ({
83
91
  x: 0,
84
92
  y: 0,
@@ -196,6 +204,13 @@ function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
196
204
  return out;
197
205
  }
198
206
 
207
+ // src/Mask/_mask-types.ts
208
+ var MaskType = /* @__PURE__ */ ((MaskType2) => {
209
+ MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
210
+ MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
211
+ return MaskType2;
212
+ })(MaskType || {});
213
+
199
214
  // src/Mask/extractMaskBuffer.ts
200
215
  function extractMaskBuffer(maskBuffer, maskWidth, xOrRect, y, w, h) {
201
216
  let finalX;
@@ -298,9 +313,9 @@ function trimMaskRectBounds(target, bounds) {
298
313
 
299
314
  // src/Algorithm/floodFillSelection.ts
300
315
  function floodFillSelection(target, startX, startY, contiguous = true, tolerance = 0, bounds, out) {
301
- const data32 = target.data32;
302
- const width = target.width;
303
- const height = target.height;
316
+ const data32 = target.data;
317
+ const width = target.w;
318
+ const height = target.h;
304
319
  const lx = bounds?.x ?? 0;
305
320
  const ly = bounds?.y ?? 0;
306
321
  const lw = bounds?.w ?? width;
@@ -414,13 +429,13 @@ function floodFillSelection(target, startX, startY, contiguous = true, tolerance
414
429
 
415
430
  // src/Algorithm/forEachLinePoint.ts
416
431
  function forEachLinePoint(x0, y0, x1, y1, callback) {
417
- const dx = x1 - x0;
418
- const dy = y1 - y0;
419
- const steps = Math.max(Math.abs(dx), Math.abs(dy));
420
- if (steps === 0) {
432
+ if (x0 === x1 && y0 === y1) {
421
433
  callback(x0, y0);
422
434
  return;
423
435
  }
436
+ const dx = x1 - x0;
437
+ const dy = y1 - y0;
438
+ const steps = Math.max(Math.abs(dx), Math.abs(dy));
424
439
  const xInc = dx / steps;
425
440
  const yInc = dy / steps;
426
441
  let curX = x0;
@@ -432,6 +447,66 @@ function forEachLinePoint(x0, y0, x1, y1, callback) {
432
447
  }
433
448
  }
434
449
 
450
+ // src/Algorithm/resampleUint32Array.ts
451
+ function resampleUint32Array(srcData32, srcW, srcH, factor, out) {
452
+ const dstW = Math.max(1, srcW * factor | 0);
453
+ const dstH = Math.max(1, srcH * factor | 0);
454
+ const dstData = new Uint32Array(dstW * dstH);
455
+ const scaleX = srcW / dstW;
456
+ const scaleY = srcH / dstH;
457
+ for (let y = 0; y < dstH; y++) {
458
+ const srcY = Math.min(srcH - 1, y * scaleY | 0);
459
+ const srcRowOffset = srcY * srcW;
460
+ const dstRowOffset = y * dstW;
461
+ for (let x = 0; x < dstW; x++) {
462
+ const srcX = Math.min(srcW - 1, x * scaleX | 0);
463
+ dstData[dstRowOffset + x] = srcData32[srcRowOffset + srcX];
464
+ }
465
+ }
466
+ out = out ?? {};
467
+ out.data = dstData;
468
+ out.w = dstW;
469
+ out.h = dstH;
470
+ return out;
471
+ }
472
+
473
+ // src/BlendModes/blend-modes.ts
474
+ var BaseBlendMode = {
475
+ overwrite: 0,
476
+ sourceOver: 1,
477
+ darken: 2,
478
+ multiply: 3,
479
+ colorBurn: 4,
480
+ linearBurn: 5,
481
+ darkerColor: 6,
482
+ lighten: 7,
483
+ screen: 8,
484
+ colorDodge: 9,
485
+ linearDodge: 10,
486
+ lighterColor: 11,
487
+ overlay: 12,
488
+ softLight: 13,
489
+ hardLight: 14,
490
+ vividLight: 15,
491
+ linearLight: 16,
492
+ pinLight: 17,
493
+ hardMix: 18,
494
+ difference: 19,
495
+ exclusion: 20,
496
+ subtract: 21,
497
+ divide: 22,
498
+ sourceIn: 23,
499
+ sourceOut: 24,
500
+ sourceAtop: 25,
501
+ destinationOver: 26,
502
+ destinationIn: 27,
503
+ destinationOut: 28,
504
+ destinationAtop: 29,
505
+ xor: 30
506
+ };
507
+ var overwriteBase = (src, _dst) => src;
508
+ overwriteBase.isOverwrite = true;
509
+
435
510
  // src/BlendModes/BlendModeRegistry.ts
436
511
  function makeBlendModeRegistry(blendModes, initialEntries, registryName = "anonymous") {
437
512
  const blendToName = /* @__PURE__ */ new Map();
@@ -471,37 +546,134 @@ function makeBlendModeRegistry(blendModes, initialEntries, registryName = "anony
471
546
  };
472
547
  }
473
548
 
474
- // src/BlendModes/blend-modes.ts
475
- var BaseBlendMode = {
476
- overwrite: 0,
477
- sourceOver: 1,
478
- darken: 2,
479
- multiply: 3,
480
- colorBurn: 4,
481
- linearBurn: 5,
482
- darkerColor: 6,
483
- lighten: 7,
484
- screen: 8,
485
- colorDodge: 9,
486
- linearDodge: 10,
487
- lighterColor: 11,
488
- overlay: 12,
489
- softLight: 13,
490
- hardLight: 14,
491
- vividLight: 15,
492
- linearLight: 16,
493
- pinLight: 17,
494
- hardMix: 18,
495
- difference: 19,
496
- exclusion: 20,
497
- subtract: 21,
498
- divide: 22
499
- };
500
- var overwriteBase = (src, _dst) => src;
501
- overwriteBase.isOverwrite = true;
502
-
503
549
  // src/BlendModes/blend-modes-fast.ts
504
550
  var overwriteFast = overwriteBase;
551
+ var sourceInFast = (src, dst) => {
552
+ const da = dst >>> 24 & 255;
553
+ if (da === 0) return 0;
554
+ if (da === 255) return src;
555
+ const sa = src >>> 24 & 255;
556
+ const sr = src & 255;
557
+ const sg = src >>> 8 & 255;
558
+ const sb = src >>> 16 & 255;
559
+ const r = sr * da >> 8;
560
+ const g = sg * da >> 8;
561
+ const b = sb * da >> 8;
562
+ const a = sa * da >> 8;
563
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
564
+ };
565
+ var sourceOutFast = (src, dst) => {
566
+ const da = dst >>> 24 & 255;
567
+ if (da === 255) return 0;
568
+ if (da === 0) return src;
569
+ const sa = src >>> 24 & 255;
570
+ const sr = src & 255;
571
+ const sg = src >>> 8 & 255;
572
+ const sb = src >>> 16 & 255;
573
+ const invDa = 255 - da;
574
+ const r = sr * invDa >> 8;
575
+ const g = sg * invDa >> 8;
576
+ const b = sb * invDa >> 8;
577
+ const a = sa * invDa >> 8;
578
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
579
+ };
580
+ var sourceAtopFast = (src, dst) => {
581
+ const sa = src >>> 24 & 255;
582
+ const da = dst >>> 24 & 255;
583
+ if (da === 0) return 0;
584
+ const sr = src & 255;
585
+ const sg = src >>> 8 & 255;
586
+ const sb = src >>> 16 & 255;
587
+ const dr = dst & 255;
588
+ const dg = dst >>> 8 & 255;
589
+ const db = dst >>> 16 & 255;
590
+ const invSa = 255 - sa;
591
+ const r = sr * da + dr * invSa >> 8;
592
+ const g = sg * da + dg * invSa >> 8;
593
+ const b = sb * da + db * invSa >> 8;
594
+ return (da << 24 | b << 16 | g << 8 | r) >>> 0;
595
+ };
596
+ var destinationOverFast = (src, dst) => {
597
+ const da = dst >>> 24 & 255;
598
+ if (da === 255) return dst;
599
+ if (da === 0) return src;
600
+ const sa = src >>> 24 & 255;
601
+ const sr = src & 255;
602
+ const sg = src >>> 8 & 255;
603
+ const sb = src >>> 16 & 255;
604
+ const dr = dst & 255;
605
+ const dg = dst >>> 8 & 255;
606
+ const db = dst >>> 16 & 255;
607
+ const invDa = 255 - da;
608
+ const r = dr * 255 + sr * invDa >> 8;
609
+ const g = dg * 255 + sg * invDa >> 8;
610
+ const b = db * 255 + sb * invDa >> 8;
611
+ const a = da * 255 + sa * invDa >> 8;
612
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
613
+ };
614
+ var destinationInFast = (src, dst) => {
615
+ const sa = src >>> 24 & 255;
616
+ if (sa === 0) return 0;
617
+ if (sa === 255) return dst;
618
+ const da = dst >>> 24 & 255;
619
+ const dr = dst & 255;
620
+ const dg = dst >>> 8 & 255;
621
+ const db = dst >>> 16 & 255;
622
+ const r = dr * sa >> 8;
623
+ const g = dg * sa >> 8;
624
+ const b = db * sa >> 8;
625
+ const a = da * sa >> 8;
626
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
627
+ };
628
+ var destinationOutFast = (src, dst) => {
629
+ const sa = src >>> 24 & 255;
630
+ if (sa === 255) return 0;
631
+ if (sa === 0) return dst;
632
+ const da = dst >>> 24 & 255;
633
+ const dr = dst & 255;
634
+ const dg = dst >>> 8 & 255;
635
+ const db = dst >>> 16 & 255;
636
+ const invSa = 255 - sa;
637
+ const r = dr * invSa >> 8;
638
+ const g = dg * invSa >> 8;
639
+ const b = db * invSa >> 8;
640
+ const a = da * invSa >> 8;
641
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
642
+ };
643
+ var destinationAtopFast = (src, dst) => {
644
+ const sa = src >>> 24 & 255;
645
+ if (sa === 0) return 0;
646
+ const da = dst >>> 24 & 255;
647
+ if (da === 0) return 0;
648
+ const sr = src & 255;
649
+ const sg = src >>> 8 & 255;
650
+ const sb = src >>> 16 & 255;
651
+ const dr = dst & 255;
652
+ const dg = dst >>> 8 & 255;
653
+ const db = dst >>> 16 & 255;
654
+ const invDa = 255 - da;
655
+ const r = dr * sa + sr * invDa >> 8;
656
+ const g = dg * sa + sg * invDa >> 8;
657
+ const b = db * sa + sb * invDa >> 8;
658
+ return (sa << 24 | b << 16 | g << 8 | r) >>> 0;
659
+ };
660
+ var xorFast = (src, dst) => {
661
+ const sa = src >>> 24 & 255;
662
+ const da = dst >>> 24 & 255;
663
+ const sr = src & 255;
664
+ const sg = src >>> 8 & 255;
665
+ const sb = src >>> 16 & 255;
666
+ const dr = dst & 255;
667
+ const dg = dst >>> 8 & 255;
668
+ const db = dst >>> 16 & 255;
669
+ const invDa = 255 - da;
670
+ const invSa = 255 - sa;
671
+ const r = sr * invDa + dr * invSa >> 8;
672
+ const g = sg * invDa + dg * invSa >> 8;
673
+ const b = sb * invDa + db * invSa >> 8;
674
+ const a = sa * invDa + da * invSa >> 8;
675
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
676
+ };
505
677
  var sourceOverFast = (src, dst) => {
506
678
  const sa = src >>> 24 & 255;
507
679
  if (sa === 255) return src;
@@ -887,6 +1059,14 @@ var divideFast = (src, dst) => {
887
1059
  };
888
1060
  var BASE_FAST_BLEND_MODE_FUNCTIONS = {
889
1061
  [BaseBlendMode.overwrite]: overwriteFast,
1062
+ [BaseBlendMode.sourceIn]: sourceInFast,
1063
+ [BaseBlendMode.sourceOut]: sourceOutFast,
1064
+ [BaseBlendMode.sourceAtop]: sourceAtopFast,
1065
+ [BaseBlendMode.destinationOver]: destinationOverFast,
1066
+ [BaseBlendMode.destinationIn]: destinationInFast,
1067
+ [BaseBlendMode.destinationOut]: destinationOutFast,
1068
+ [BaseBlendMode.destinationAtop]: destinationAtopFast,
1069
+ [BaseBlendMode.xor]: xorFast,
890
1070
  [BaseBlendMode.sourceOver]: sourceOverFast,
891
1071
  [BaseBlendMode.darken]: darkenFast,
892
1072
  [BaseBlendMode.multiply]: multiplyFast,
@@ -916,115 +1096,271 @@ function makeFastBlendModeRegistry(name = "fast") {
916
1096
 
917
1097
  // src/BlendModes/blend-modes-perfect.ts
918
1098
  var overwritePerfect = overwriteBase;
919
- var sourceOverPerfect = (src, dst) => {
920
- const sa = src >>> 24 & 255;
921
- if (sa === 255) return src;
922
- if (sa === 0) return dst;
1099
+ var sourceInPerfect = (src, dst) => {
923
1100
  const da = dst >>> 24 & 255;
924
- if (da === 0) return src;
925
- const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
926
- const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
927
- const invA = 255 - sa;
928
- const tR = sr * sa + dr * invA;
1101
+ if (da === 0) return 0;
1102
+ if (da === 255) return src;
1103
+ const sa = src >>> 24 & 255;
1104
+ const sr = src & 255;
1105
+ const sg = src >>> 8 & 255;
1106
+ const sb = src >>> 16 & 255;
1107
+ const tR = sr * da;
929
1108
  const r = tR + 1 + (tR >> 8) >> 8;
930
- const tG = sg * sa + dg * invA;
1109
+ const tG = sg * da;
931
1110
  const g = tG + 1 + (tG >> 8) >> 8;
932
- const tB = sb * sa + db * invA;
1111
+ const tB = sb * da;
933
1112
  const b = tB + 1 + (tB >> 8) >> 8;
934
- const tA = 255 * sa + da * invA;
1113
+ const tA = sa * da;
935
1114
  const a = tA + 1 + (tA >> 8) >> 8;
936
1115
  return (a << 24 | b << 16 | g << 8 | r) >>> 0;
937
1116
  };
938
- var darkenPerfect = (src, dst) => {
939
- const sa = src >>> 24 & 255;
940
- if (sa === 0) return dst;
941
- const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
942
- const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
943
- const br = sr < dr ? sr : dr;
944
- const bg = sg < dg ? sg : dg;
945
- const bb = sb < db ? sb : db;
946
- if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
947
- const invA = 255 - sa;
1117
+ var sourceOutPerfect = (src, dst) => {
948
1118
  const da = dst >>> 24 & 255;
949
- const tR = br * sa + dr * invA;
1119
+ if (da === 255) return 0;
1120
+ if (da === 0) return src;
1121
+ const sa = src >>> 24 & 255;
1122
+ const sr = src & 255;
1123
+ const sg = src >>> 8 & 255;
1124
+ const sb = src >>> 16 & 255;
1125
+ const invDa = 255 - da;
1126
+ const tR = sr * invDa;
950
1127
  const r = tR + 1 + (tR >> 8) >> 8;
951
- const tG = bg * sa + dg * invA;
1128
+ const tG = sg * invDa;
952
1129
  const g = tG + 1 + (tG >> 8) >> 8;
953
- const tB = bb * sa + db * invA;
1130
+ const tB = sb * invDa;
954
1131
  const b = tB + 1 + (tB >> 8) >> 8;
955
- const tA = 255 * sa + da * invA;
1132
+ const tA = sa * invDa;
956
1133
  const a = tA + 1 + (tA >> 8) >> 8;
957
1134
  return (a << 24 | b << 16 | g << 8 | r) >>> 0;
958
1135
  };
959
- var multiplyPerfect = (src, dst) => {
1136
+ var sourceAtopPerfect = (src, dst) => {
960
1137
  const sa = src >>> 24 & 255;
961
- if (sa === 0) return dst;
1138
+ const da = dst >>> 24 & 255;
1139
+ if (da === 0) return 0;
1140
+ const sr = src & 255;
1141
+ const sg = src >>> 8 & 255;
1142
+ const sb = src >>> 16 & 255;
962
1143
  const dr = dst & 255;
963
1144
  const dg = dst >>> 8 & 255;
964
1145
  const db = dst >>> 16 & 255;
1146
+ const invSa = 255 - sa;
1147
+ const tR = sr * da + dr * invSa;
1148
+ const r = tR + 1 + (tR >> 8) >> 8;
1149
+ const tG = sg * da + dg * invSa;
1150
+ const g = tG + 1 + (tG >> 8) >> 8;
1151
+ const tB = sb * da + db * invSa;
1152
+ const b = tB + 1 + (tB >> 8) >> 8;
1153
+ return (da << 24 | b << 16 | g << 8 | r) >>> 0;
1154
+ };
1155
+ var destinationOverPerfect = (src, dst) => {
965
1156
  const da = dst >>> 24 & 255;
1157
+ if (da === 255) return dst;
1158
+ if (da === 0) return src;
1159
+ const sa = src >>> 24 & 255;
966
1160
  const sr = src & 255;
967
1161
  const sg = src >>> 8 & 255;
968
1162
  const sb = src >>> 16 & 255;
969
- const mR = sr * dr;
970
- const br = mR + 1 + (mR >> 8) >> 8;
971
- const mG = sg * dg;
972
- const bg = mG + 1 + (mG >> 8) >> 8;
973
- const mB = sb * db;
974
- const bb = mB + 1 + (mB >> 8) >> 8;
975
- if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
976
- const invA = 255 - sa;
977
- const tR = br * sa + dr * invA;
1163
+ const dr = dst & 255;
1164
+ const dg = dst >>> 8 & 255;
1165
+ const db = dst >>> 16 & 255;
1166
+ const invDa = 255 - da;
1167
+ const tR = dr * 255 + sr * invDa;
978
1168
  const r = tR + 1 + (tR >> 8) >> 8;
979
- const tG = bg * sa + dg * invA;
1169
+ const tG = dg * 255 + sg * invDa;
980
1170
  const g = tG + 1 + (tG >> 8) >> 8;
981
- const tB = bb * sa + db * invA;
1171
+ const tB = db * 255 + sb * invDa;
982
1172
  const b = tB + 1 + (tB >> 8) >> 8;
983
- const tA = 255 * sa + da * invA;
1173
+ const tA = da * 255 + sa * invDa;
984
1174
  const a = tA + 1 + (tA >> 8) >> 8;
985
1175
  return (a << 24 | b << 16 | g << 8 | r) >>> 0;
986
1176
  };
987
- var colorBurnPerfect = (src, dst) => {
1177
+ var destinationInPerfect = (src, dst) => {
988
1178
  const sa = src >>> 24 & 255;
989
- if (sa === 0) return dst;
1179
+ if (sa === 0) return 0;
1180
+ if (sa === 255) return dst;
1181
+ const da = dst >>> 24 & 255;
990
1182
  const dr = dst & 255;
991
1183
  const dg = dst >>> 8 & 255;
992
1184
  const db = dst >>> 16 & 255;
993
- const sr = src & 255;
994
- const sg = src >>> 8 & 255;
995
- const sb = src >>> 16 & 255;
996
- const resR = dr === 255 ? 255 : sr === 0 ? 0 : 255 - ((255 - dr) * 255 / sr | 0);
997
- const br = resR < 0 ? 0 : resR;
998
- const resG = dg === 255 ? 255 : sg === 0 ? 0 : 255 - ((255 - dg) * 255 / sg | 0);
999
- const bg = resG < 0 ? 0 : resG;
1000
- const resB = db === 255 ? 255 : sb === 0 ? 0 : 255 - ((255 - db) * 255 / sb | 0);
1001
- const bb = resB < 0 ? 0 : resB;
1002
- if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
1003
- const invA = 255 - sa;
1004
- const da = dst >>> 24 & 255;
1005
- const tR = br * sa + dr * invA;
1185
+ const tR = dr * sa;
1006
1186
  const r = tR + 1 + (tR >> 8) >> 8;
1007
- const tG = bg * sa + dg * invA;
1187
+ const tG = dg * sa;
1008
1188
  const g = tG + 1 + (tG >> 8) >> 8;
1009
- const tB = bb * sa + db * invA;
1189
+ const tB = db * sa;
1010
1190
  const b = tB + 1 + (tB >> 8) >> 8;
1011
- const tA = 255 * sa + da * invA;
1191
+ const tA = da * sa;
1012
1192
  const a = tA + 1 + (tA >> 8) >> 8;
1013
1193
  return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1014
1194
  };
1015
- var linearBurnPerfect = (src, dst) => {
1195
+ var destinationOutPerfect = (src, dst) => {
1016
1196
  const sa = src >>> 24 & 255;
1197
+ if (sa === 255) return 0;
1017
1198
  if (sa === 0) return dst;
1018
- const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
1019
- const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
1020
- const brU = dr + sr - 255;
1021
- const br = brU < 0 ? 0 : brU;
1022
- const bgU = dg + sg - 255;
1023
- const bg = bgU < 0 ? 0 : bgU;
1024
- const bbU = db + sb - 255;
1025
- const bb = bbU < 0 ? 0 : bbU;
1026
- if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
1027
- const invA = 255 - sa;
1199
+ const da = dst >>> 24 & 255;
1200
+ const dr = dst & 255;
1201
+ const dg = dst >>> 8 & 255;
1202
+ const db = dst >>> 16 & 255;
1203
+ const invSa = 255 - sa;
1204
+ const tR = dr * invSa;
1205
+ const r = tR + 1 + (tR >> 8) >> 8;
1206
+ const tG = dg * invSa;
1207
+ const g = tG + 1 + (tG >> 8) >> 8;
1208
+ const tB = db * invSa;
1209
+ const b = tB + 1 + (tB >> 8) >> 8;
1210
+ const tA = da * invSa;
1211
+ const a = tA + 1 + (tA >> 8) >> 8;
1212
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1213
+ };
1214
+ var destinationAtopPerfect = (src, dst) => {
1215
+ const sa = src >>> 24 & 255;
1216
+ if (sa === 0) return 0;
1217
+ const da = dst >>> 24 & 255;
1218
+ if (da === 0) return 0;
1219
+ const sr = src & 255;
1220
+ const sg = src >>> 8 & 255;
1221
+ const sb = src >>> 16 & 255;
1222
+ const dr = dst & 255;
1223
+ const dg = dst >>> 8 & 255;
1224
+ const db = dst >>> 16 & 255;
1225
+ const invDa = 255 - da;
1226
+ const tR = dr * sa + sr * invDa;
1227
+ const r = tR + 1 + (tR >> 8) >> 8;
1228
+ const tG = dg * sa + sg * invDa;
1229
+ const g = tG + 1 + (tG >> 8) >> 8;
1230
+ const tB = db * sa + sb * invDa;
1231
+ const b = tB + 1 + (tB >> 8) >> 8;
1232
+ return (sa << 24 | b << 16 | g << 8 | r) >>> 0;
1233
+ };
1234
+ var xorPerfect = (src, dst) => {
1235
+ const sa = src >>> 24 & 255;
1236
+ const da = dst >>> 24 & 255;
1237
+ const sr = src & 255;
1238
+ const sg = src >>> 8 & 255;
1239
+ const sb = src >>> 16 & 255;
1240
+ const dr = dst & 255;
1241
+ const dg = dst >>> 8 & 255;
1242
+ const db = dst >>> 16 & 255;
1243
+ const invDa = 255 - da;
1244
+ const invSa = 255 - sa;
1245
+ const tR = sr * invDa + dr * invSa;
1246
+ const r = tR + 1 + (tR >> 8) >> 8;
1247
+ const tG = sg * invDa + dg * invSa;
1248
+ const g = tG + 1 + (tG >> 8) >> 8;
1249
+ const tB = sb * invDa + db * invSa;
1250
+ const b = tB + 1 + (tB >> 8) >> 8;
1251
+ const tA = sa * invDa + da * invSa;
1252
+ const a = tA + 1 + (tA >> 8) >> 8;
1253
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1254
+ };
1255
+ var sourceOverPerfect = (src, dst) => {
1256
+ const sa = src >>> 24 & 255;
1257
+ if (sa === 255) return src;
1258
+ if (sa === 0) return dst;
1259
+ const da = dst >>> 24 & 255;
1260
+ if (da === 0) return src;
1261
+ const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
1262
+ const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
1263
+ const invA = 255 - sa;
1264
+ const tR = sr * sa + dr * invA;
1265
+ const r = tR + 1 + (tR >> 8) >> 8;
1266
+ const tG = sg * sa + dg * invA;
1267
+ const g = tG + 1 + (tG >> 8) >> 8;
1268
+ const tB = sb * sa + db * invA;
1269
+ const b = tB + 1 + (tB >> 8) >> 8;
1270
+ const tA = 255 * sa + da * invA;
1271
+ const a = tA + 1 + (tA >> 8) >> 8;
1272
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1273
+ };
1274
+ var darkenPerfect = (src, dst) => {
1275
+ const sa = src >>> 24 & 255;
1276
+ if (sa === 0) return dst;
1277
+ const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
1278
+ const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
1279
+ const br = sr < dr ? sr : dr;
1280
+ const bg = sg < dg ? sg : dg;
1281
+ const bb = sb < db ? sb : db;
1282
+ if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
1283
+ const invA = 255 - sa;
1284
+ const da = dst >>> 24 & 255;
1285
+ const tR = br * sa + dr * invA;
1286
+ const r = tR + 1 + (tR >> 8) >> 8;
1287
+ const tG = bg * sa + dg * invA;
1288
+ const g = tG + 1 + (tG >> 8) >> 8;
1289
+ const tB = bb * sa + db * invA;
1290
+ const b = tB + 1 + (tB >> 8) >> 8;
1291
+ const tA = 255 * sa + da * invA;
1292
+ const a = tA + 1 + (tA >> 8) >> 8;
1293
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1294
+ };
1295
+ var multiplyPerfect = (src, dst) => {
1296
+ const sa = src >>> 24 & 255;
1297
+ if (sa === 0) return dst;
1298
+ const dr = dst & 255;
1299
+ const dg = dst >>> 8 & 255;
1300
+ const db = dst >>> 16 & 255;
1301
+ const da = dst >>> 24 & 255;
1302
+ const sr = src & 255;
1303
+ const sg = src >>> 8 & 255;
1304
+ const sb = src >>> 16 & 255;
1305
+ const mR = sr * dr;
1306
+ const br = mR + 1 + (mR >> 8) >> 8;
1307
+ const mG = sg * dg;
1308
+ const bg = mG + 1 + (mG >> 8) >> 8;
1309
+ const mB = sb * db;
1310
+ const bb = mB + 1 + (mB >> 8) >> 8;
1311
+ if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
1312
+ const invA = 255 - sa;
1313
+ const tR = br * sa + dr * invA;
1314
+ const r = tR + 1 + (tR >> 8) >> 8;
1315
+ const tG = bg * sa + dg * invA;
1316
+ const g = tG + 1 + (tG >> 8) >> 8;
1317
+ const tB = bb * sa + db * invA;
1318
+ const b = tB + 1 + (tB >> 8) >> 8;
1319
+ const tA = 255 * sa + da * invA;
1320
+ const a = tA + 1 + (tA >> 8) >> 8;
1321
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1322
+ };
1323
+ var colorBurnPerfect = (src, dst) => {
1324
+ const sa = src >>> 24 & 255;
1325
+ if (sa === 0) return dst;
1326
+ const dr = dst & 255;
1327
+ const dg = dst >>> 8 & 255;
1328
+ const db = dst >>> 16 & 255;
1329
+ const sr = src & 255;
1330
+ const sg = src >>> 8 & 255;
1331
+ const sb = src >>> 16 & 255;
1332
+ const resR = dr === 255 ? 255 : sr === 0 ? 0 : 255 - ((255 - dr) * 255 / sr | 0);
1333
+ const br = resR < 0 ? 0 : resR;
1334
+ const resG = dg === 255 ? 255 : sg === 0 ? 0 : 255 - ((255 - dg) * 255 / sg | 0);
1335
+ const bg = resG < 0 ? 0 : resG;
1336
+ const resB = db === 255 ? 255 : sb === 0 ? 0 : 255 - ((255 - db) * 255 / sb | 0);
1337
+ const bb = resB < 0 ? 0 : resB;
1338
+ if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
1339
+ const invA = 255 - sa;
1340
+ const da = dst >>> 24 & 255;
1341
+ const tR = br * sa + dr * invA;
1342
+ const r = tR + 1 + (tR >> 8) >> 8;
1343
+ const tG = bg * sa + dg * invA;
1344
+ const g = tG + 1 + (tG >> 8) >> 8;
1345
+ const tB = bb * sa + db * invA;
1346
+ const b = tB + 1 + (tB >> 8) >> 8;
1347
+ const tA = 255 * sa + da * invA;
1348
+ const a = tA + 1 + (tA >> 8) >> 8;
1349
+ return (a << 24 | b << 16 | g << 8 | r) >>> 0;
1350
+ };
1351
+ var linearBurnPerfect = (src, dst) => {
1352
+ const sa = src >>> 24 & 255;
1353
+ if (sa === 0) return dst;
1354
+ const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
1355
+ const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
1356
+ const brU = dr + sr - 255;
1357
+ const br = brU < 0 ? 0 : brU;
1358
+ const bgU = dg + sg - 255;
1359
+ const bg = bgU < 0 ? 0 : bgU;
1360
+ const bbU = db + sb - 255;
1361
+ const bb = bbU < 0 ? 0 : bbU;
1362
+ if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
1363
+ const invA = 255 - sa;
1028
1364
  const da = dst >>> 24 & 255;
1029
1365
  const tR = br * sa + dr * invA;
1030
1366
  const r = tR + 1 + (tR >> 8) >> 8;
@@ -1443,6 +1779,14 @@ var dividePerfect = (src, dst) => {
1443
1779
  };
1444
1780
  var BASE_PERFECT_BLEND_MODE_FUNCTIONS = {
1445
1781
  [BaseBlendMode.overwrite]: overwritePerfect,
1782
+ [BaseBlendMode.sourceIn]: sourceInPerfect,
1783
+ [BaseBlendMode.sourceOut]: sourceOutPerfect,
1784
+ [BaseBlendMode.sourceAtop]: sourceAtopPerfect,
1785
+ [BaseBlendMode.destinationOver]: destinationOverPerfect,
1786
+ [BaseBlendMode.destinationIn]: destinationInPerfect,
1787
+ [BaseBlendMode.destinationOut]: destinationOutPerfect,
1788
+ [BaseBlendMode.destinationAtop]: destinationAtopPerfect,
1789
+ [BaseBlendMode.xor]: xorPerfect,
1446
1790
  [BaseBlendMode.sourceOver]: sourceOverPerfect,
1447
1791
  [BaseBlendMode.darken]: darkenPerfect,
1448
1792
  [BaseBlendMode.multiply]: multiplyPerfect,
@@ -1505,9 +1849,23 @@ var getKeyByValue = (obj, value) => {
1505
1849
  }
1506
1850
  };
1507
1851
 
1508
- // support/error-strings.ts
1509
- var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
1510
- var CANVAS_CTX_FAILED = "Failed to create Canvas context";
1852
+ // src/Canvas/canvas-blend-modes.ts
1853
+ var CANVAS_COMPOSITE_MAP = {
1854
+ [BaseBlendMode.overwrite]: "copy",
1855
+ [BaseBlendMode.sourceOver]: "source-over",
1856
+ [BaseBlendMode.darken]: "darken",
1857
+ [BaseBlendMode.multiply]: "multiply",
1858
+ [BaseBlendMode.colorBurn]: "color-burn",
1859
+ [BaseBlendMode.lighten]: "lighten",
1860
+ [BaseBlendMode.screen]: "screen",
1861
+ [BaseBlendMode.colorDodge]: "color-dodge",
1862
+ [BaseBlendMode.linearDodge]: "lighter",
1863
+ [BaseBlendMode.overlay]: "overlay",
1864
+ [BaseBlendMode.softLight]: "soft-light",
1865
+ [BaseBlendMode.hardLight]: "hard-light",
1866
+ [BaseBlendMode.difference]: "difference",
1867
+ [BaseBlendMode.exclusion]: "exclusion"
1868
+ };
1511
1869
 
1512
1870
  // src/Canvas/ReusableCanvas.ts
1513
1871
  function makeReusableCanvas() {
@@ -1560,37 +1918,38 @@ function makeReusableCanvasMeta(factory) {
1560
1918
  }
1561
1919
 
1562
1920
  // src/Canvas/CanvasFrameRenderer.ts
1563
- var defaults = {
1564
- makeReusableCanvas
1565
- };
1566
- function makeCanvasFrameRenderer(deps = defaults) {
1567
- const {
1568
- makeReusableCanvas: makeReusableCanvas2 = defaults.makeReusableCanvas
1569
- } = deps;
1570
- const bufferCanvas = makeReusableCanvas2();
1921
+ function makeCanvasFrameRenderer(reusableCanvasFactory = makeReusableOffscreenCanvas) {
1922
+ const bufferCanvas = reusableCanvasFactory();
1571
1923
  return function renderCanvasFrame(pixelCanvas, scale, getImageData, drawPixelLayer, drawScreenLayer) {
1572
- const {
1573
- canvas,
1574
- ctx
1575
- } = pixelCanvas;
1576
- const {
1577
- ctx: pxCtx,
1578
- canvas: pxCanvas
1579
- } = bufferCanvas(canvas.width, canvas.height);
1924
+ const canvas = pixelCanvas.canvas;
1925
+ const ctx = pixelCanvas.ctx;
1926
+ const w = canvas.width;
1927
+ const h = canvas.height;
1928
+ const buffer = bufferCanvas(w, h);
1580
1929
  const img = getImageData();
1581
1930
  if (img) {
1582
- pxCtx.putImageData(img, 0, 0);
1931
+ buffer.ctx.putImageData(img, 0, 0);
1583
1932
  }
1584
- drawPixelLayer?.(pxCtx);
1933
+ drawPixelLayer?.(buffer.ctx);
1585
1934
  ctx.setTransform(1, 0, 0, 1, 0, 0);
1586
- ctx.clearRect(0, 0, canvas.width, canvas.height);
1935
+ ctx.clearRect(0, 0, w, h);
1587
1936
  ctx.setTransform(scale, 0, 0, scale, 0, 0);
1588
- ctx.drawImage(pxCanvas, 0, 0);
1937
+ ctx.drawImage(buffer.canvas, 0, 0);
1589
1938
  ctx.setTransform(1, 0, 0, 1, 0, 0);
1590
1939
  drawScreenLayer?.(ctx, scale);
1591
1940
  };
1592
1941
  }
1593
1942
 
1943
+ // src/Canvas/CanvasPixelDataRenderer.ts
1944
+ function makeCanvasPixelDataRenderer(reusableCanvasFactory = makeReusableOffscreenCanvas) {
1945
+ const bufferCanvas = reusableCanvasFactory();
1946
+ return function drawPixelData(targetCtx, pixelData, x = 0, y = 0) {
1947
+ const buffer = bufferCanvas(pixelData.w, pixelData.h);
1948
+ buffer.ctx.putImageData(pixelData.imageData, 0, 0);
1949
+ targetCtx.drawImage(buffer.canvas, x, y);
1950
+ };
1951
+ }
1952
+
1594
1953
  // src/Canvas/PixelCanvas.ts
1595
1954
  function makePixelCanvas(canvas) {
1596
1955
  const ctx = canvas.getContext("2d");
@@ -1607,24 +1966,6 @@ function makePixelCanvas(canvas) {
1607
1966
  };
1608
1967
  }
1609
1968
 
1610
- // src/Canvas/canvas-blend-modes.ts
1611
- var CANVAS_COMPOSITE_MAP = {
1612
- [BaseBlendMode.overwrite]: "copy",
1613
- [BaseBlendMode.sourceOver]: "source-over",
1614
- [BaseBlendMode.darken]: "darken",
1615
- [BaseBlendMode.multiply]: "multiply",
1616
- [BaseBlendMode.colorBurn]: "color-burn",
1617
- [BaseBlendMode.lighten]: "lighten",
1618
- [BaseBlendMode.screen]: "screen",
1619
- [BaseBlendMode.colorDodge]: "color-dodge",
1620
- [BaseBlendMode.linearDodge]: "lighter",
1621
- [BaseBlendMode.overlay]: "overlay",
1622
- [BaseBlendMode.softLight]: "soft-light",
1623
- [BaseBlendMode.hardLight]: "hard-light",
1624
- [BaseBlendMode.difference]: "difference",
1625
- [BaseBlendMode.exclusion]: "exclusion"
1626
- };
1627
-
1628
1969
  // src/ImageData/imgBlobToImageData.ts
1629
1970
  async function imgBlobToImageData(blob) {
1630
1971
  let bitmap = null;
@@ -1689,10 +2030,10 @@ function applyPatchTiles(target, tiles, tileSize) {
1689
2030
  for (let i = 0; i < tiles.length; i++) {
1690
2031
  const tile = tiles[i];
1691
2032
  if (!tile) continue;
1692
- const dst = target.data32;
1693
- const src = tile.data32;
1694
- const dstWidth = target.width;
1695
- const dstHeight = target.height;
2033
+ const dst = target.data;
2034
+ const src = tile.data;
2035
+ const dstWidth = target.w;
2036
+ const dstHeight = target.h;
1696
2037
  const startX = tile.tx * tileSize;
1697
2038
  const startY = tile.ty * tileSize;
1698
2039
  const copyWidth = Math.max(0, Math.min(tileSize, dstWidth - startX));
@@ -1787,17 +2128,17 @@ var HistoryManager = class {
1787
2128
 
1788
2129
  // src/History/PixelAccumulator.ts
1789
2130
  var PixelAccumulator = class {
1790
- constructor(config, tilePool) {
2131
+ constructor(config, pixelTilePool) {
1791
2132
  this.config = config;
1792
- this.tilePool = tilePool;
2133
+ this.pixelTilePool = pixelTilePool;
1793
2134
  this.lookup = [];
1794
2135
  this.beforeTiles = [];
1795
2136
  }
1796
2137
  lookup;
1797
2138
  beforeTiles;
1798
2139
  recyclePatch(patch) {
1799
- this.tilePool.releaseTiles(patch.beforeTiles);
1800
- this.tilePool.releaseTiles(patch.afterTiles);
2140
+ this.pixelTilePool.releaseTiles(patch.beforeTiles);
2141
+ this.pixelTilePool.releaseTiles(patch.afterTiles);
1801
2142
  }
1802
2143
  /**
1803
2144
  * @param x pixel x coordinate
@@ -1812,7 +2153,7 @@ var PixelAccumulator = class {
1812
2153
  let tile = this.lookup[id];
1813
2154
  let added = false;
1814
2155
  if (!tile) {
1815
- tile = this.tilePool.getTile(id, tx, ty);
2156
+ tile = this.pixelTilePool.getTile(id, tx, ty);
1816
2157
  this.extractState(tile);
1817
2158
  this.lookup[id] = tile;
1818
2159
  this.beforeTiles.push(tile);
@@ -1822,7 +2163,7 @@ var PixelAccumulator = class {
1822
2163
  if (!didChange && added) {
1823
2164
  this.beforeTiles.pop();
1824
2165
  this.lookup[id] = void 0;
1825
- this.tilePool.releaseTile(tile);
2166
+ this.pixelTilePool.releaseTile(tile);
1826
2167
  }
1827
2168
  return didChange;
1828
2169
  };
@@ -1846,7 +2187,7 @@ var PixelAccumulator = class {
1846
2187
  const id = ty * columns + tx;
1847
2188
  let tile = this.lookup[id];
1848
2189
  if (!tile) {
1849
- tile = this.tilePool.getTile(id, tx, ty);
2190
+ tile = this.pixelTilePool.getTile(id, tx, ty);
1850
2191
  this.extractState(tile);
1851
2192
  this.lookup[id] = tile;
1852
2193
  this.beforeTiles.push(tile);
@@ -1860,7 +2201,7 @@ var PixelAccumulator = class {
1860
2201
  let t = this.beforeTiles[i];
1861
2202
  if (t) {
1862
2203
  this.lookup[t.id] = void 0;
1863
- this.tilePool.releaseTile(t);
2204
+ this.pixelTilePool.releaseTile(t);
1864
2205
  }
1865
2206
  }
1866
2207
  this.beforeTiles.length = startIndex;
@@ -1872,7 +2213,7 @@ var PixelAccumulator = class {
1872
2213
  let tile = this.lookup[id];
1873
2214
  let added = false;
1874
2215
  if (!tile) {
1875
- tile = this.tilePool.getTile(id, tx, ty);
2216
+ tile = this.pixelTilePool.getTile(id, tx, ty);
1876
2217
  this.extractState(tile);
1877
2218
  this.lookup[id] = tile;
1878
2219
  this.beforeTiles.push(tile);
@@ -1882,7 +2223,7 @@ var PixelAccumulator = class {
1882
2223
  if (!didChange && added) {
1883
2224
  this.beforeTiles.pop();
1884
2225
  this.lookup[id] = void 0;
1885
- this.tilePool.releaseTile(tile);
2226
+ this.pixelTilePool.releaseTile(tile);
1886
2227
  }
1887
2228
  return didChange;
1888
2229
  };
@@ -1890,12 +2231,12 @@ var PixelAccumulator = class {
1890
2231
  extractState(tile) {
1891
2232
  const target = this.config.target;
1892
2233
  const TILE_SIZE = this.config.tileSize;
1893
- const dst = tile.data32;
1894
- const src = target.data32;
2234
+ const dst = tile.data;
2235
+ const src = target.data;
1895
2236
  const startX = tile.tx * TILE_SIZE;
1896
2237
  const startY = tile.ty * TILE_SIZE;
1897
- const targetWidth = target.width;
1898
- const targetHeight = target.height;
2238
+ const targetWidth = target.w;
2239
+ const targetHeight = target.h;
1899
2240
  if (startX >= targetWidth || startX + TILE_SIZE <= 0 || startY >= targetHeight || startY + TILE_SIZE <= 0) {
1900
2241
  dst.fill(0);
1901
2242
  return;
@@ -1926,7 +2267,7 @@ var PixelAccumulator = class {
1926
2267
  for (let i = 0; i < length; i++) {
1927
2268
  let beforeTile = this.beforeTiles[i];
1928
2269
  if (beforeTile) {
1929
- let afterTile = this.tilePool.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
2270
+ let afterTile = this.pixelTilePool.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
1930
2271
  this.extractState(afterTile);
1931
2272
  afterTiles.push(afterTile);
1932
2273
  }
@@ -1948,7 +2289,7 @@ var PixelAccumulator = class {
1948
2289
  let tile = this.beforeTiles[i];
1949
2290
  if (tile) {
1950
2291
  this.lookup[tile.id] = void 0;
1951
- this.tilePool.releaseTile(tile);
2292
+ this.pixelTilePool.releaseTile(tile);
1952
2293
  }
1953
2294
  }
1954
2295
  this.beforeTiles.length = 0;
@@ -1976,8 +2317,8 @@ var PixelEngineConfig = class {
1976
2317
  this.tileMask = tileSize - 1;
1977
2318
  this.tileArea = tileSize * tileSize;
1978
2319
  this.target = target;
1979
- this.targetColumns = target.width + this.tileMask >> this.tileShift;
1980
- this.targetRows = target.height + this.tileMask >> this.tileShift;
2320
+ this.targetColumns = target.w + this.tileMask >> this.tileShift;
2321
+ this.targetRows = target.h + this.tileMask >> this.tileShift;
1981
2322
  }
1982
2323
  };
1983
2324
 
@@ -1985,8 +2326,8 @@ var PixelEngineConfig = class {
1985
2326
  function applyAlphaMaskToPixelData(target, mask, opts) {
1986
2327
  const targetX = opts?.x ?? 0;
1987
2328
  const targetY = opts?.y ?? 0;
1988
- const width = opts?.w ?? target.width;
1989
- const height = opts?.h ?? target.height;
2329
+ const width = opts?.w ?? target.w;
2330
+ const height = opts?.h ?? target.h;
1990
2331
  const globalAlpha = opts?.alpha ?? 255;
1991
2332
  const mx = opts?.mx ?? 0;
1992
2333
  const my = opts?.my ?? 0;
@@ -2004,8 +2345,8 @@ function applyAlphaMaskToPixelData(target, mask, opts) {
2004
2345
  h += y;
2005
2346
  y = 0;
2006
2347
  }
2007
- w = Math.min(w, target.width - x);
2008
- h = Math.min(h, target.height - y);
2348
+ w = Math.min(w, target.w - x);
2349
+ h = Math.min(h, target.h - y);
2009
2350
  if (w <= 0) return false;
2010
2351
  if (h <= 0) return false;
2011
2352
  const mPitch = mask.w;
@@ -2022,49 +2363,82 @@ function applyAlphaMaskToPixelData(target, mask, opts) {
2022
2363
  if (finalH <= 0) return false;
2023
2364
  const xShift = sX0 - startX;
2024
2365
  const yShift = sY0 - startY;
2025
- const dst32 = target.data32;
2026
- const dw = target.width;
2366
+ const dst32 = target.data;
2367
+ const dw = target.w;
2027
2368
  const dStride = dw - finalW;
2028
2369
  const mStride = mPitch - finalW;
2029
2370
  const maskData = mask.data;
2030
2371
  let dIdx = (y + yShift) * dw + (x + xShift);
2031
2372
  let mIdx = sY0 * mPitch + sX0;
2032
2373
  let didChange = false;
2033
- for (let iy = 0; iy < h; iy++) {
2034
- for (let ix = 0; ix < w; ix++) {
2035
- const mVal = maskData[mIdx];
2036
- const effectiveM = invertMask ? 255 - mVal : mVal;
2037
- let weight = 0;
2038
- if (effectiveM === 0) {
2039
- weight = 0;
2040
- } else if (effectiveM === 255) {
2041
- weight = globalAlpha;
2042
- } else if (globalAlpha === 255) {
2043
- weight = effectiveM;
2044
- } else {
2045
- weight = effectiveM * globalAlpha + 128 >> 8;
2374
+ if (invertMask) {
2375
+ for (let iy = 0; iy < finalH; iy++) {
2376
+ for (let ix = 0; ix < finalW; ix++) {
2377
+ const effectiveM = 255 - maskData[mIdx];
2378
+ if (effectiveM === 0) {
2379
+ const current = dst32[dIdx];
2380
+ const next = (current & 16777215) >>> 0;
2381
+ if (current !== next) {
2382
+ dst32[dIdx] = next;
2383
+ didChange = true;
2384
+ }
2385
+ } else {
2386
+ const t1 = effectiveM * globalAlpha + 128;
2387
+ const weight = t1 + (t1 >> 8) >> 8;
2388
+ if (weight < 255) {
2389
+ const current = dst32[dIdx];
2390
+ const da = current >>> 24;
2391
+ if (da !== 0) {
2392
+ const t2 = da * weight + 128;
2393
+ const finalAlpha = t2 + (t2 >> 8) >> 8;
2394
+ const next = (current & 16777215 | finalAlpha << 24) >>> 0;
2395
+ if (current !== next) {
2396
+ dst32[dIdx] = next;
2397
+ didChange = true;
2398
+ }
2399
+ }
2400
+ }
2401
+ }
2402
+ dIdx++;
2403
+ mIdx++;
2046
2404
  }
2047
- if (weight === 0) {
2048
- dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
2049
- didChange = true;
2050
- } else if (weight !== 255) {
2051
- const d = dst32[dIdx];
2052
- const da = d >>> 24;
2053
- if (da !== 0) {
2054
- const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
2405
+ dIdx += dStride;
2406
+ mIdx += mStride;
2407
+ }
2408
+ } else {
2409
+ for (let iy = 0; iy < finalH; iy++) {
2410
+ for (let ix = 0; ix < finalW; ix++) {
2411
+ const effectiveM = maskData[mIdx];
2412
+ if (effectiveM === 0) {
2055
2413
  const current = dst32[dIdx];
2056
- const next = (d & 16777215 | finalAlpha << 24) >>> 0;
2414
+ const next = (current & 16777215) >>> 0;
2057
2415
  if (current !== next) {
2058
2416
  dst32[dIdx] = next;
2059
2417
  didChange = true;
2060
2418
  }
2419
+ } else {
2420
+ const t1 = effectiveM * globalAlpha + 128;
2421
+ const weight = t1 + (t1 >> 8) >> 8;
2422
+ if (weight < 255) {
2423
+ const current = dst32[dIdx];
2424
+ const da = current >>> 24;
2425
+ if (da !== 0) {
2426
+ const t2 = da * weight + 128;
2427
+ const finalAlpha = t2 + (t2 >> 8) >> 8;
2428
+ const next = (current & 16777215 | finalAlpha << 24) >>> 0;
2429
+ if (current !== next) {
2430
+ dst32[dIdx] = next;
2431
+ didChange = true;
2432
+ }
2433
+ }
2434
+ }
2061
2435
  }
2436
+ dIdx++;
2437
+ mIdx++;
2062
2438
  }
2063
- dIdx++;
2064
- mIdx++;
2439
+ dIdx += dStride;
2440
+ mIdx += mStride;
2065
2441
  }
2066
- dIdx += dStride;
2067
- mIdx += mStride;
2068
2442
  }
2069
2443
  return didChange;
2070
2444
  }
@@ -2098,338 +2472,77 @@ function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0)
2098
2472
  return result;
2099
2473
  }
2100
2474
 
2101
- // src/Rect/trimRectBounds.ts
2102
- function trimRectBounds(x, y, w, h, targetWidth, targetHeight, out) {
2103
- const res = out ?? {
2104
- x: 0,
2105
- y: 0,
2106
- w: 0,
2107
- h: 0
2475
+ // src/PixelData/PixelData.ts
2476
+ function makePixelData(imageData) {
2477
+ return {
2478
+ data: new Uint32Array(
2479
+ imageData.data.buffer,
2480
+ imageData.data.byteOffset,
2481
+ // Shift right by 2 is a fast bitwise division by 4.
2482
+ imageData.data.byteLength >> 2
2483
+ ),
2484
+ imageData,
2485
+ w: imageData.width,
2486
+ h: imageData.height
2108
2487
  };
2109
- const left = Math.max(0, x);
2110
- const top = Math.max(0, y);
2111
- const right = Math.min(targetWidth, x + w);
2112
- const bottom = Math.min(targetHeight, y + h);
2113
- res.x = left;
2114
- res.y = top;
2115
- res.w = Math.max(0, right - left);
2116
- res.h = Math.max(0, bottom - top);
2117
- return res;
2488
+ }
2489
+ function setPixelData(target, imageData) {
2490
+ ;
2491
+ target.data = new Uint32Array(
2492
+ imageData.data.buffer,
2493
+ imageData.data.byteOffset,
2494
+ // Shift right by 2 is a fast bitwise division by 4.
2495
+ imageData.data.byteLength >> 2
2496
+ );
2497
+ target.imageData = imageData;
2498
+ target.w = imageData.width;
2499
+ target.h = imageData.height;
2118
2500
  }
2119
2501
 
2120
- // src/Paint/PaintBuffer.ts
2121
- var PaintBuffer = class {
2122
- constructor(config, tilePool) {
2123
- this.config = config;
2124
- this.tilePool = tilePool;
2125
- this.lookup = [];
2126
- }
2127
- lookup;
2128
- scratchBounds = {
2129
- x: 0,
2130
- y: 0,
2131
- w: 0,
2132
- h: 0
2133
- };
2134
- eachTileInBounds(bounds, callback) {
2135
- const {
2136
- tileShift,
2137
- targetColumns,
2138
- targetRows,
2139
- tileSize
2140
- } = this.config;
2141
- const x1 = Math.max(0, bounds.x >> tileShift);
2142
- const y1 = Math.max(0, bounds.y >> tileShift);
2143
- const x2 = Math.min(targetColumns - 1, bounds.x + bounds.w - 1 >> tileShift);
2144
- const y2 = Math.min(targetRows - 1, bounds.y + bounds.h - 1 >> tileShift);
2145
- if (x1 > x2 || y1 > y2) return;
2146
- const lookup = this.lookup;
2147
- const tilePool = this.tilePool;
2148
- for (let ty = y1; ty <= y2; ty++) {
2149
- const rowOffset = ty * targetColumns;
2150
- const tileTop = ty << tileShift;
2151
- for (let tx = x1; tx <= x2; tx++) {
2152
- const id = rowOffset + tx;
2153
- const tile = lookup[id] ?? (lookup[id] = tilePool.getTile(id, tx, ty));
2154
- const tileLeft = tx << tileShift;
2155
- const startX = bounds.x > tileLeft ? bounds.x : tileLeft;
2156
- const startY = bounds.y > tileTop ? bounds.y : tileTop;
2157
- const maskEndX = bounds.x + bounds.w;
2158
- const tileEndX = tileLeft + tileSize;
2159
- const endX = maskEndX < tileEndX ? maskEndX : tileEndX;
2160
- const maskEndY = bounds.y + bounds.h;
2161
- const tileEndY = tileTop + tileSize;
2162
- const endY = maskEndY < tileEndY ? maskEndY : tileEndY;
2163
- callback(tile, startX, startY, endX - startX, endY - startY);
2164
- }
2165
- }
2166
- }
2167
- writePaintAlphaMaskStroke(color, brush, x0, y0, x1, y1) {
2168
- const cA = color >>> 24;
2169
- if (cA === 0) return false;
2170
- const {
2171
- tileShift,
2172
- tileMask,
2173
- target
2174
- } = this.config;
2175
- const {
2176
- w: bW,
2177
- h: bH,
2178
- data: bD,
2179
- centerOffsetX,
2180
- centerOffsetY
2181
- } = brush;
2182
- const cRGB = color & 16777215;
2183
- const scratch = this.scratchBounds;
2184
- let changed = false;
2185
- forEachLinePoint(x0, y0, x1, y1, (px, py) => {
2186
- const topLeftX = Math.floor(px + centerOffsetX);
2187
- const topLeftY = Math.floor(py + centerOffsetY);
2188
- trimRectBounds(topLeftX, topLeftY, bW, bH, target.width, target.height, scratch);
2189
- if (scratch.w <= 0 || scratch.h <= 0) return;
2190
- this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
2191
- const d32 = tile.data32;
2192
- let tileChanged = false;
2193
- for (let i = 0; i < bH_t; i++) {
2194
- const canvasY = bY + i;
2195
- const bOff = (canvasY - topLeftY) * bW;
2196
- const tOff = (canvasY & tileMask) << tileShift;
2197
- const dS = tOff + (bX & tileMask);
2198
- for (let j = 0; j < bW_t; j++) {
2199
- const canvasX = bX + j;
2200
- const brushA = bD[bOff + (canvasX - topLeftX)];
2201
- if (brushA === 0) continue;
2202
- const t = cA * brushA + 128;
2203
- const blendedA = t + (t >> 8) >> 8;
2204
- const idx = dS + j;
2205
- const cur = d32[idx];
2206
- if (brushA > cur >>> 24) {
2207
- const next = (cRGB | blendedA << 24) >>> 0;
2208
- if (cur !== next) {
2209
- d32[idx] = next;
2210
- tileChanged = true;
2211
- }
2212
- }
2213
- }
2214
- }
2215
- if (tileChanged) changed = true;
2216
- });
2217
- });
2218
- return changed;
2219
- }
2220
- writePaintBinaryMaskStroke(color, brush, x0, y0, x1, y1) {
2221
- const alphaIsZero = color >>> 24 === 0;
2222
- if (alphaIsZero) return false;
2223
- const {
2224
- tileShift,
2225
- tileMask,
2226
- target
2227
- } = this.config;
2228
- const {
2229
- w: bW,
2230
- h: bH,
2231
- data: bD,
2232
- centerOffsetX,
2233
- centerOffsetY
2234
- } = brush;
2235
- const scratch = this.scratchBounds;
2236
- let changed = false;
2237
- forEachLinePoint(x0, y0, x1, y1, (px, py) => {
2238
- const topLeftX = Math.floor(px + centerOffsetX);
2239
- const topLeftY = Math.floor(py + centerOffsetY);
2240
- trimRectBounds(topLeftX, topLeftY, bW, bH, target.width, target.height, scratch);
2241
- if (scratch.w <= 0 || scratch.h <= 0) return;
2242
- this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
2243
- const d32 = tile.data32;
2244
- let tileChanged = false;
2245
- for (let i = 0; i < bH_t; i++) {
2246
- const canvasY = bY + i;
2247
- const bOff = (canvasY - topLeftY) * bW;
2248
- const tOff = (canvasY & tileMask) << tileShift;
2249
- const dS = tOff + (bX & tileMask);
2250
- for (let j = 0; j < bW_t; j++) {
2251
- const canvasX = bX + j;
2252
- if (bD[bOff + (canvasX - topLeftX)]) {
2253
- const idx = dS + j;
2254
- if (d32[idx] !== color) {
2255
- d32[idx] = color;
2256
- tileChanged = true;
2257
- }
2258
- }
2259
- }
2260
- }
2261
- if (tileChanged) changed = true;
2262
- });
2263
- });
2264
- return changed;
2265
- }
2266
- writeRectStroke(color, brushWidth, brushHeight, x0, y0, x1, y1) {
2267
- const alphaIsZero = color >>> 24 === 0;
2268
- if (alphaIsZero) return false;
2269
- const config = this.config;
2270
- const tileShift = config.tileShift;
2271
- const tileMask = config.tileMask;
2272
- const target = config.target;
2273
- const scratch = this.scratchBounds;
2274
- const centerOffsetX = -(brushWidth - 1 >> 1);
2275
- const centerOffsetY = -(brushHeight - 1 >> 1);
2276
- let changed = false;
2277
- forEachLinePoint(x0, y0, x1, y1, (px, py) => {
2278
- const topLeftX = Math.floor(px + centerOffsetX);
2279
- const topLeftY = Math.floor(py + centerOffsetY);
2280
- trimRectBounds(topLeftX, topLeftY, brushWidth, brushHeight, target.width, target.height, scratch);
2281
- if (scratch.w <= 0 || scratch.h <= 0) return;
2282
- this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
2283
- const d32 = tile.data32;
2284
- let tileChanged = false;
2285
- for (let i = 0; i < bH_t; i++) {
2286
- const canvasY = bY + i;
2287
- const tOff = (canvasY & tileMask) << tileShift;
2288
- const dS = tOff + (bX & tileMask);
2289
- for (let j = 0; j < bW_t; j++) {
2290
- const idx = dS + j;
2291
- if (d32[idx] !== color) {
2292
- d32[idx] = color;
2293
- tileChanged = true;
2294
- }
2295
- }
2296
- }
2297
- if (tileChanged) {
2298
- changed = true;
2299
- }
2300
- });
2301
- });
2302
- return changed;
2303
- }
2304
- clear() {
2305
- this.tilePool.releaseTiles(this.lookup);
2306
- }
2307
- };
2502
+ // src/Tile/_tile-types.ts
2503
+ var TileType = /* @__PURE__ */ ((TileType2) => {
2504
+ TileType2[TileType2["PIXEL"] = 0] = "PIXEL";
2505
+ TileType2[TileType2["MASK"] = 1] = "MASK";
2506
+ return TileType2;
2507
+ })(TileType || {});
2308
2508
 
2309
- // src/PixelData/blendPixelData.ts
2310
- function blendPixelData(target, src, opts) {
2311
- const targetX = opts?.x ?? 0;
2312
- const targetY = opts?.y ?? 0;
2313
- const sourceX = opts?.sx ?? 0;
2314
- const sourceY = opts?.sy ?? 0;
2315
- const width = opts?.w ?? src.width;
2316
- const height = opts?.h ?? src.height;
2317
- const globalAlpha = opts?.alpha ?? 255;
2318
- const blendFn = opts?.blendFn ?? sourceOverPerfect;
2319
- if (globalAlpha === 0) return false;
2320
- let x = targetX;
2321
- let y = targetY;
2322
- let sx = sourceX;
2323
- let sy = sourceY;
2324
- let w = width;
2325
- let h = height;
2326
- if (sx < 0) {
2327
- x -= sx;
2328
- w += sx;
2329
- sx = 0;
2330
- }
2331
- if (sy < 0) {
2332
- y -= sy;
2333
- h += sy;
2334
- sy = 0;
2335
- }
2336
- w = Math.min(w, src.width - sx);
2337
- h = Math.min(h, src.height - sy);
2338
- if (x < 0) {
2339
- sx -= x;
2340
- w += x;
2341
- x = 0;
2342
- }
2343
- if (y < 0) {
2344
- sy -= y;
2345
- h += y;
2346
- y = 0;
2347
- }
2348
- const actualW = Math.min(w, target.width - x);
2349
- const actualH = Math.min(h, target.height - y);
2350
- if (actualW <= 0 || actualH <= 0) return false;
2351
- const dst32 = target.data32;
2352
- const src32 = src.data32;
2353
- const dw = target.width;
2354
- const sw = src.width;
2355
- let dIdx = y * dw + x | 0;
2356
- let sIdx = sy * sw + sx | 0;
2357
- const dStride = dw - actualW | 0;
2358
- const sStride = sw - actualW | 0;
2359
- const isOpaque = globalAlpha === 255;
2360
- const isOverwrite = blendFn.isOverwrite;
2361
- let didChange = false;
2362
- for (let iy = 0; iy < actualH; iy++) {
2363
- for (let ix = 0; ix < actualW; ix++) {
2364
- const srcCol = src32[sIdx];
2365
- const srcAlpha = srcCol >>> 24;
2366
- if (srcAlpha === 0 && !isOverwrite) {
2367
- dIdx++;
2368
- sIdx++;
2369
- continue;
2370
- }
2371
- let finalCol = srcCol;
2372
- if (!isOpaque) {
2373
- const a = srcAlpha * globalAlpha + 128 >> 8;
2374
- if (a === 0 && !isOverwrite) {
2375
- dIdx++;
2376
- sIdx++;
2377
- continue;
2378
- }
2379
- finalCol = (srcCol & 16777215 | a << 24) >>> 0;
2380
- }
2381
- const current = dst32[dIdx];
2382
- const next = blendFn(finalCol, dst32[dIdx]);
2383
- if (current !== next) {
2384
- dst32[dIdx] = next;
2385
- didChange = true;
2386
- }
2387
- dIdx++;
2388
- sIdx++;
2389
- }
2390
- dIdx += dStride;
2391
- sIdx += sStride;
2392
- }
2393
- return didChange;
2509
+ // src/Tile/PixelTile.ts
2510
+ function makePixelTile(id, tx, ty, tileSize, tileArea) {
2511
+ const data32 = new Uint32Array(tileArea);
2512
+ const data8 = new Uint8ClampedArray(data32.buffer);
2513
+ return {
2514
+ tileType: 0 /* PIXEL */,
2515
+ id,
2516
+ tx,
2517
+ ty,
2518
+ w: tileSize,
2519
+ h: tileSize,
2520
+ data: data32,
2521
+ imageData: new ImageData(data8, tileSize, tileSize)
2522
+ };
2394
2523
  }
2395
2524
 
2396
- // src/PixelTile/PixelTile.ts
2397
- var PixelTile = class {
2398
- constructor(id, tx, ty, tileSize, tileArea) {
2399
- this.id = id;
2400
- this.tx = tx;
2401
- this.ty = ty;
2402
- this.width = this.height = tileSize;
2403
- this.data32 = new Uint32Array(tileArea);
2404
- const data8 = new Uint8ClampedArray(this.data32.buffer);
2405
- this.imageData = new ImageData(data8, tileSize, tileSize);
2406
- }
2407
- data32;
2408
- width;
2409
- height;
2410
- imageData;
2411
- };
2412
-
2413
- // src/PixelTile/PixelTilePool.ts
2414
- var PixelTilePool = class {
2415
- pool;
2416
- tileSize;
2417
- tileArea;
2418
- constructor(config) {
2525
+ // src/Tile/TilePool.ts
2526
+ var TilePool = class {
2527
+ constructor(config, tileFactory) {
2528
+ this.tileFactory = tileFactory;
2419
2529
  this.pool = [];
2420
2530
  this.tileSize = config.tileSize;
2421
2531
  this.tileArea = config.tileArea;
2422
2532
  }
2533
+ pool;
2534
+ tileSize;
2535
+ tileArea;
2423
2536
  getTile(id, tx, ty) {
2424
2537
  let tile = this.pool.pop();
2425
2538
  if (tile) {
2426
2539
  tile.id = id;
2427
2540
  tile.tx = tx;
2428
2541
  tile.ty = ty;
2429
- tile.data32.fill(0);
2542
+ tile.data.fill(0);
2430
2543
  return tile;
2431
2544
  }
2432
- return new PixelTile(id, tx, ty, this.tileSize, this.tileArea);
2545
+ return this.tileFactory(id, tx, ty, this.tileSize, this.tileArea);
2433
2546
  }
2434
2547
  releaseTile(tile) {
2435
2548
  this.pool.push(tile);
@@ -2453,16 +2566,7 @@ var PixelWriter = class {
2453
2566
  historyActionFactory;
2454
2567
  config;
2455
2568
  pixelTilePool;
2456
- paintBuffer;
2457
2569
  mutator;
2458
- blendPixelDataOpts = {
2459
- alpha: 255,
2460
- blendFn: sourceOverPerfect,
2461
- x: 0,
2462
- y: 0,
2463
- w: 0,
2464
- h: 0
2465
- };
2466
2570
  _inProgress = false;
2467
2571
  constructor(target, mutatorFactory, options) {
2468
2572
  const tileSize = options?.tileSize ?? 256;
@@ -2470,10 +2574,9 @@ var PixelWriter = class {
2470
2574
  this.config = new PixelEngineConfig(tileSize, target);
2471
2575
  this.historyManager = options?.historyManager ?? new HistoryManager(maxHistorySteps);
2472
2576
  this.historyActionFactory = options?.historyActionFactory ?? makeHistoryAction;
2473
- this.pixelTilePool = options?.pixelTilePool ?? new PixelTilePool(this.config);
2577
+ this.pixelTilePool = options?.pixelTilePool ?? new TilePool(this.config, makePixelTile);
2474
2578
  this.accumulator = options?.accumulator ?? new PixelAccumulator(this.config, this.pixelTilePool);
2475
2579
  this.mutator = mutatorFactory(this);
2476
- this.paintBuffer = new PaintBuffer(this.config, this.pixelTilePool);
2477
2580
  }
2478
2581
  /**
2479
2582
  * Executes `transaction` and commits the resulting pixel changes as a single
@@ -2519,59 +2622,37 @@ var PixelWriter = class {
2519
2622
  const target = config.target;
2520
2623
  const beforeImageData = target.imageData;
2521
2624
  const afterImageData = resizeImageDataFn(beforeImageData, newWidth, newHeight, offsetX, offsetY);
2522
- target.set(afterImageData);
2625
+ setPixelData(target, afterImageData);
2523
2626
  this.historyManager.commit({
2524
2627
  undo: () => {
2525
- target.set(beforeImageData);
2628
+ setPixelData(target, beforeImageData);
2526
2629
  afterUndo?.(beforeImageData);
2527
2630
  after?.(beforeImageData);
2528
2631
  },
2529
2632
  redo: () => {
2530
- target.set(afterImageData);
2633
+ setPixelData(target, afterImageData);
2531
2634
  afterRedo?.(afterImageData);
2532
2635
  after?.(afterImageData);
2533
2636
  }
2534
2637
  });
2535
2638
  }
2536
- commitPaintBuffer(alpha = 255, blendFn = sourceOverPerfect, blendPixelDataFn = blendPixelData) {
2537
- const paintBuffer = this.paintBuffer;
2538
- const tileShift = paintBuffer.config.tileShift;
2539
- const lookup = paintBuffer.lookup;
2540
- const opts = this.blendPixelDataOpts;
2541
- opts.alpha = alpha;
2542
- opts.blendFn = blendFn;
2543
- for (let i = 0; i < lookup.length; i++) {
2544
- const tile = lookup[i];
2545
- if (tile) {
2546
- const didChange = this.accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
2547
- const dx = tile.tx << tileShift;
2548
- const dy = tile.ty << tileShift;
2549
- opts.x = dx;
2550
- opts.y = dy;
2551
- opts.w = tile.width;
2552
- opts.h = tile.height;
2553
- didChange(blendPixelDataFn(this.config.target, tile, opts));
2554
- }
2555
- }
2556
- paintBuffer.clear();
2557
- }
2558
2639
  };
2559
2640
 
2560
2641
  // src/History/PixelMutator/mutatorApplyAlphaMask.ts
2561
- var defaults2 = {
2642
+ var defaults = {
2562
2643
  applyAlphaMaskToPixelData
2563
2644
  };
2564
- var mutatorApplyAlphaMask = ((writer, deps = defaults2) => {
2645
+ var mutatorApplyAlphaMask = ((writer, deps = defaults) => {
2565
2646
  const {
2566
- applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults2.applyAlphaMaskToPixelData
2647
+ applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults.applyAlphaMaskToPixelData
2567
2648
  } = deps;
2568
2649
  return {
2569
2650
  applyAlphaMask(mask, opts) {
2570
2651
  const target = writer.config.target;
2571
2652
  const x = opts?.x ?? 0;
2572
2653
  const y = opts?.y ?? 0;
2573
- const w = opts?.w ?? target.width;
2574
- const h = opts?.h ?? target.height;
2654
+ const w = opts?.w ?? target.w;
2655
+ const h = opts?.h ?? target.h;
2575
2656
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
2576
2657
  return didChange(applyAlphaMaskToPixelData2(target, mask, opts));
2577
2658
  }
@@ -2582,8 +2663,8 @@ var mutatorApplyAlphaMask = ((writer, deps = defaults2) => {
2582
2663
  function applyBinaryMaskToPixelData(target, mask, opts) {
2583
2664
  const targetX = opts?.x ?? 0;
2584
2665
  const targetY = opts?.y ?? 0;
2585
- const width = opts?.w ?? target.width;
2586
- const height = opts?.h ?? target.height;
2666
+ const width = opts?.w ?? target.w;
2667
+ const height = opts?.h ?? target.h;
2587
2668
  const globalAlpha = opts?.alpha ?? 255;
2588
2669
  const mx = opts?.mx ?? 0;
2589
2670
  const my = opts?.my ?? 0;
@@ -2601,8 +2682,8 @@ function applyBinaryMaskToPixelData(target, mask, opts) {
2601
2682
  h += y;
2602
2683
  y = 0;
2603
2684
  }
2604
- w = Math.min(w, target.width - x);
2605
- h = Math.min(h, target.height - y);
2685
+ w = Math.min(w, target.w - x);
2686
+ h = Math.min(h, target.h - y);
2606
2687
  if (w <= 0 || h <= 0) return false;
2607
2688
  const mPitch = mask.w;
2608
2689
  if (mPitch <= 0) return false;
@@ -2619,8 +2700,8 @@ function applyBinaryMaskToPixelData(target, mask, opts) {
2619
2700
  }
2620
2701
  const xShift = sX0 - startX;
2621
2702
  const yShift = sY0 - startY;
2622
- const dst32 = target.data32;
2623
- const dw = target.width;
2703
+ const dst32 = target.data;
2704
+ const dw = target.w;
2624
2705
  const dStride = dw - finalW;
2625
2706
  const mStride = mPitch - finalW;
2626
2707
  const maskData = mask.data;
@@ -2660,20 +2741,20 @@ function applyBinaryMaskToPixelData(target, mask, opts) {
2660
2741
  }
2661
2742
 
2662
2743
  // src/History/PixelMutator/mutatorApplyBinaryMask.ts
2663
- var defaults3 = {
2744
+ var defaults2 = {
2664
2745
  applyBinaryMaskToPixelData
2665
2746
  };
2666
- var mutatorApplyBinaryMask = ((writer, deps = defaults3) => {
2747
+ var mutatorApplyBinaryMask = ((writer, deps = defaults2) => {
2667
2748
  const {
2668
- applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults3.applyBinaryMaskToPixelData
2749
+ applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults2.applyBinaryMaskToPixelData
2669
2750
  } = deps;
2670
2751
  return {
2671
2752
  applyBinaryMask(mask, opts) {
2672
2753
  const target = writer.config.target;
2673
2754
  const x = opts?.x ?? 0;
2674
2755
  const y = opts?.y ?? 0;
2675
- const w = opts?.w ?? target.width;
2676
- const h = opts?.h ?? target.height;
2756
+ const w = opts?.w ?? target.w;
2757
+ const h = opts?.h ?? target.h;
2677
2758
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
2678
2759
  return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
2679
2760
  }
@@ -2681,22 +2762,22 @@ var mutatorApplyBinaryMask = ((writer, deps = defaults3) => {
2681
2762
  });
2682
2763
 
2683
2764
  // src/History/PixelMutator/mutatorApplyMask.ts
2684
- var defaults4 = {
2765
+ var defaults3 = {
2685
2766
  applyBinaryMaskToPixelData,
2686
2767
  applyAlphaMaskToPixelData
2687
2768
  };
2688
- var mutatorApplyMask = ((writer, deps = defaults4) => {
2769
+ var mutatorApplyMask = ((writer, deps = defaults3) => {
2689
2770
  const {
2690
- applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults4.applyBinaryMaskToPixelData,
2691
- applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults4.applyAlphaMaskToPixelData
2771
+ applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults3.applyBinaryMaskToPixelData,
2772
+ applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults3.applyAlphaMaskToPixelData
2692
2773
  } = deps;
2693
2774
  return {
2694
2775
  applyMask(mask, opts) {
2695
2776
  const target = writer.config.target;
2696
2777
  const x = opts?.x ?? 0;
2697
2778
  const y = opts?.y ?? 0;
2698
- const w = opts?.w ?? target.width;
2699
- const h = opts?.h ?? target.height;
2779
+ const w = opts?.w ?? target.w;
2780
+ const h = opts?.h ?? target.h;
2700
2781
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
2701
2782
  if (mask.type === 1 /* BINARY */) {
2702
2783
  return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
@@ -2713,8 +2794,8 @@ function blendPixelDataAlphaMask(target, src, alphaMask, opts) {
2713
2794
  const targetY = opts?.y ?? 0;
2714
2795
  const sourceX = opts?.sx ?? 0;
2715
2796
  const sourceY = opts?.sy ?? 0;
2716
- const width = opts?.w ?? src.width;
2717
- const height = opts?.h ?? src.height;
2797
+ const width = opts?.w ?? src.w;
2798
+ const height = opts?.h ?? src.h;
2718
2799
  const globalAlpha = opts?.alpha ?? 255;
2719
2800
  const blendFn = opts?.blendFn ?? sourceOverPerfect;
2720
2801
  const mx = opts?.mx ?? 0;
@@ -2737,8 +2818,8 @@ function blendPixelDataAlphaMask(target, src, alphaMask, opts) {
2737
2818
  h += sy;
2738
2819
  sy = 0;
2739
2820
  }
2740
- w = Math.min(w, src.width - sx);
2741
- h = Math.min(h, src.height - sy);
2821
+ w = Math.min(w, src.w - sx);
2822
+ h = Math.min(h, src.h - sy);
2742
2823
  if (x < 0) {
2743
2824
  sx -= x;
2744
2825
  w += x;
@@ -2749,17 +2830,17 @@ function blendPixelDataAlphaMask(target, src, alphaMask, opts) {
2749
2830
  h += y;
2750
2831
  y = 0;
2751
2832
  }
2752
- const actualW = Math.min(w, target.width - x);
2753
- const actualH = Math.min(h, target.height - y);
2833
+ const actualW = Math.min(w, target.w - x);
2834
+ const actualH = Math.min(h, target.h - y);
2754
2835
  if (actualW <= 0 || actualH <= 0) return false;
2755
- const dw = target.width;
2756
- const sw = src.width;
2836
+ const dw = target.w;
2837
+ const sw = src.w;
2757
2838
  const mPitch = alphaMask.w;
2758
2839
  const maskData = alphaMask.data;
2759
2840
  const dx = x - targetX | 0;
2760
2841
  const dy = y - targetY | 0;
2761
- const dst32 = target.data32;
2762
- const src32 = src.data32;
2842
+ const dst32 = target.data;
2843
+ const src32 = src.data;
2763
2844
  let dIdx = y * dw + x | 0;
2764
2845
  let sIdx = sy * sw + sx | 0;
2765
2846
  let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
@@ -2828,19 +2909,19 @@ function blendPixelDataAlphaMask(target, src, alphaMask, opts) {
2828
2909
  }
2829
2910
 
2830
2911
  // src/History/PixelMutator/mutatorBlendAlphaMask.ts
2831
- var defaults5 = {
2912
+ var defaults4 = {
2832
2913
  blendPixelDataAlphaMask
2833
2914
  };
2834
- var mutatorBlendAlphaMask = ((writer, deps = defaults5) => {
2915
+ var mutatorBlendAlphaMask = ((writer, deps = defaults4) => {
2835
2916
  const {
2836
- blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults5.blendPixelDataAlphaMask
2917
+ blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults4.blendPixelDataAlphaMask
2837
2918
  } = deps;
2838
2919
  return {
2839
2920
  blendAlphaMask(src, mask, opts) {
2840
2921
  const x = opts?.x ?? 0;
2841
2922
  const y = opts?.y ?? 0;
2842
- const w = opts?.w ?? src.width;
2843
- const h = opts?.h ?? src.height;
2923
+ const w = opts?.w ?? src.w;
2924
+ const h = opts?.h ?? src.h;
2844
2925
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
2845
2926
  return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
2846
2927
  }
@@ -2853,8 +2934,8 @@ function blendPixelDataBinaryMask(target, src, binaryMask, opts) {
2853
2934
  const targetY = opts?.y ?? 0;
2854
2935
  const sourceX = opts?.sx ?? 0;
2855
2936
  const sourceY = opts?.sy ?? 0;
2856
- const width = opts?.w ?? src.width;
2857
- const height = opts?.h ?? src.height;
2937
+ const width = opts?.w ?? src.w;
2938
+ const height = opts?.h ?? src.h;
2858
2939
  const globalAlpha = opts?.alpha ?? 255;
2859
2940
  const blendFn = opts?.blendFn ?? sourceOverPerfect;
2860
2941
  const mx = opts?.mx ?? 0;
@@ -2877,8 +2958,8 @@ function blendPixelDataBinaryMask(target, src, binaryMask, opts) {
2877
2958
  h += sy;
2878
2959
  sy = 0;
2879
2960
  }
2880
- w = Math.min(w, src.width - sx);
2881
- h = Math.min(h, src.height - sy);
2961
+ w = Math.min(w, src.w - sx);
2962
+ h = Math.min(h, src.h - sy);
2882
2963
  if (x < 0) {
2883
2964
  sx -= x;
2884
2965
  w += x;
@@ -2889,15 +2970,15 @@ function blendPixelDataBinaryMask(target, src, binaryMask, opts) {
2889
2970
  h += y;
2890
2971
  y = 0;
2891
2972
  }
2892
- const actualW = Math.min(w, target.width - x);
2893
- const actualH = Math.min(h, target.height - y);
2973
+ const actualW = Math.min(w, target.w - x);
2974
+ const actualH = Math.min(h, target.h - y);
2894
2975
  if (actualW <= 0 || actualH <= 0) return false;
2895
2976
  const dx = x - targetX | 0;
2896
2977
  const dy = y - targetY | 0;
2897
- const dst32 = target.data32;
2898
- const src32 = src.data32;
2899
- const dw = target.width;
2900
- const sw = src.width;
2978
+ const dst32 = target.data;
2979
+ const src32 = src.data;
2980
+ const dw = target.w;
2981
+ const sw = src.w;
2901
2982
  const mPitch = binaryMask.w;
2902
2983
  const maskData = binaryMask.data;
2903
2984
  let dIdx = y * dw + x | 0;
@@ -2955,19 +3036,19 @@ function blendPixelDataBinaryMask(target, src, binaryMask, opts) {
2955
3036
  }
2956
3037
 
2957
3038
  // src/History/PixelMutator/mutatorBlendBinaryMask.ts
2958
- var defaults6 = {
3039
+ var defaults5 = {
2959
3040
  blendPixelDataBinaryMask
2960
3041
  };
2961
- var mutatorBlendBinaryMask = ((writer, deps = defaults6) => {
3042
+ var mutatorBlendBinaryMask = ((writer, deps = defaults5) => {
2962
3043
  const {
2963
- blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults6.blendPixelDataBinaryMask
3044
+ blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults5.blendPixelDataBinaryMask
2964
3045
  } = deps;
2965
3046
  return {
2966
3047
  blendBinaryMask(src, mask, opts) {
2967
3048
  const x = opts?.x ?? 0;
2968
3049
  const y = opts?.y ?? 0;
2969
- const w = opts?.w ?? src.width;
2970
- const h = opts?.h ?? src.height;
3050
+ const w = opts?.w ?? src.w;
3051
+ const h = opts?.h ?? src.h;
2971
3052
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
2972
3053
  return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
2973
3054
  }
@@ -2978,8 +3059,8 @@ var mutatorBlendBinaryMask = ((writer, deps = defaults6) => {
2978
3059
  function blendColorPixelData(target, color, opts) {
2979
3060
  const targetX = opts?.x ?? 0;
2980
3061
  const targetY = opts?.y ?? 0;
2981
- const width = opts?.w ?? target.width;
2982
- const height = opts?.h ?? target.height;
3062
+ const width = opts?.w ?? target.w;
3063
+ const height = opts?.h ?? target.h;
2983
3064
  const globalAlpha = opts?.alpha ?? 255;
2984
3065
  const blendFn = opts?.blendFn ?? sourceOverPerfect;
2985
3066
  if (globalAlpha === 0) return false;
@@ -2998,8 +3079,8 @@ function blendColorPixelData(target, color, opts) {
2998
3079
  h += y;
2999
3080
  y = 0;
3000
3081
  }
3001
- const actualW = Math.min(w, target.width - x);
3002
- const actualH = Math.min(h, target.height - y);
3082
+ const actualW = Math.min(w, target.w - x);
3083
+ const actualH = Math.min(h, target.h - y);
3003
3084
  if (actualW <= 0 || actualH <= 0) return false;
3004
3085
  let finalSrcColor = color;
3005
3086
  if (globalAlpha < 255) {
@@ -3007,8 +3088,8 @@ function blendColorPixelData(target, color, opts) {
3007
3088
  if (a === 0 && !isOverwrite) return false;
3008
3089
  finalSrcColor = (color & 16777215 | a << 24) >>> 0;
3009
3090
  }
3010
- const dst32 = target.data32;
3011
- const dw = target.width;
3091
+ const dst32 = target.data;
3092
+ const dw = target.w;
3012
3093
  let dIdx = y * dw + x | 0;
3013
3094
  const dStride = dw - actualW | 0;
3014
3095
  let didChange = false;
@@ -3028,20 +3109,20 @@ function blendColorPixelData(target, color, opts) {
3028
3109
  }
3029
3110
 
3030
3111
  // src/History/PixelMutator/mutatorBlendColor.ts
3031
- var defaults7 = {
3112
+ var defaults6 = {
3032
3113
  blendColorPixelData
3033
3114
  };
3034
- var mutatorBlendColor = ((writer, deps = defaults7) => {
3115
+ var mutatorBlendColor = ((writer, deps = defaults6) => {
3035
3116
  const {
3036
- blendColorPixelData: blendColorPixelData2 = defaults7.blendColorPixelData
3117
+ blendColorPixelData: blendColorPixelData2 = defaults6.blendColorPixelData
3037
3118
  } = deps;
3038
3119
  return {
3039
3120
  blendColor(color, opts) {
3040
3121
  const target = writer.config.target;
3041
3122
  const x = opts?.x ?? 0;
3042
3123
  const y = opts?.y ?? 0;
3043
- const w = opts?.w ?? target.width;
3044
- const h = opts?.h ?? target.height;
3124
+ const w = opts?.w ?? target.w;
3125
+ const h = opts?.h ?? target.h;
3045
3126
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3046
3127
  return didChange(blendColorPixelData2(target, color, opts));
3047
3128
  }
@@ -3075,13 +3156,13 @@ function blendColorPixelDataAlphaMask(target, color, mask, opts) {
3075
3156
  actualH += y;
3076
3157
  y = 0;
3077
3158
  }
3078
- actualW = Math.min(actualW, target.width - x);
3079
- actualH = Math.min(actualH, target.height - y);
3159
+ actualW = Math.min(actualW, target.w - x);
3160
+ actualH = Math.min(actualH, target.h - y);
3080
3161
  if (actualW <= 0 || actualH <= 0) return false;
3081
3162
  const dx = x - targetX | 0;
3082
3163
  const dy = y - targetY | 0;
3083
- const dst32 = target.data32;
3084
- const dw = target.width;
3164
+ const dst32 = target.data;
3165
+ const dw = target.w;
3085
3166
  const mPitch = mask.w;
3086
3167
  const maskData = mask.data;
3087
3168
  let dIdx = y * dw + x | 0;
@@ -3137,12 +3218,12 @@ function blendColorPixelDataAlphaMask(target, color, mask, opts) {
3137
3218
  }
3138
3219
 
3139
3220
  // src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts
3140
- var defaults8 = {
3221
+ var defaults7 = {
3141
3222
  blendColorPixelDataAlphaMask
3142
3223
  };
3143
- var mutatorBlendColorPaintAlphaMask = ((writer, deps = defaults8) => {
3224
+ var mutatorBlendColorPaintAlphaMask = ((writer, deps = defaults7) => {
3144
3225
  const {
3145
- blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults8.blendColorPixelDataAlphaMask
3226
+ blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults7.blendColorPixelDataAlphaMask
3146
3227
  } = deps;
3147
3228
  const OPTS = {
3148
3229
  x: 0,
@@ -3189,8 +3270,8 @@ function blendColorPixelDataBinaryMask(target, color, mask, opts) {
3189
3270
  h += y;
3190
3271
  y = 0;
3191
3272
  }
3192
- const actualW = Math.min(w, target.width - x);
3193
- const actualH = Math.min(h, target.height - y);
3273
+ const actualW = Math.min(w, target.w - x);
3274
+ const actualH = Math.min(h, target.h - y);
3194
3275
  if (actualW <= 0 || actualH <= 0) return false;
3195
3276
  let baseColorWithGlobalAlpha = color;
3196
3277
  if (globalAlpha < 255) {
@@ -3200,8 +3281,8 @@ function blendColorPixelDataBinaryMask(target, color, mask, opts) {
3200
3281
  }
3201
3282
  const dx = x - targetX | 0;
3202
3283
  const dy = y - targetY | 0;
3203
- const dst32 = target.data32;
3204
- const dw = target.width;
3284
+ const dst32 = target.data;
3285
+ const dw = target.w;
3205
3286
  const mPitch = mask.w;
3206
3287
  const maskData = mask.data;
3207
3288
  let dIdx = y * dw + x | 0;
@@ -3233,12 +3314,12 @@ function blendColorPixelDataBinaryMask(target, color, mask, opts) {
3233
3314
  }
3234
3315
 
3235
3316
  // src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts
3236
- var defaults9 = {
3317
+ var defaults8 = {
3237
3318
  blendColorPixelDataBinaryMask
3238
3319
  };
3239
- var mutatorBlendColorPaintBinaryMask = ((writer, deps = defaults9) => {
3320
+ var mutatorBlendColorPaintBinaryMask = ((writer, deps = defaults8) => {
3240
3321
  const {
3241
- blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults9.blendColorPixelDataBinaryMask
3322
+ blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults8.blendColorPixelDataBinaryMask
3242
3323
  } = deps;
3243
3324
  const OPTS = {
3244
3325
  x: 0,
@@ -3261,14 +3342,14 @@ var mutatorBlendColorPaintBinaryMask = ((writer, deps = defaults9) => {
3261
3342
  });
3262
3343
 
3263
3344
  // src/History/PixelMutator/mutatorBlendColorPaintMask.ts
3264
- var defaults10 = {
3345
+ var defaults9 = {
3265
3346
  blendColorPixelDataAlphaMask,
3266
3347
  blendColorPixelDataBinaryMask
3267
3348
  };
3268
- var mutatorBlendColorPaintMask = ((writer, deps = defaults10) => {
3349
+ var mutatorBlendColorPaintMask = ((writer, deps = defaults9) => {
3269
3350
  const {
3270
- blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults10.blendColorPixelDataBinaryMask,
3271
- blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults10.blendColorPixelDataAlphaMask
3351
+ blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults9.blendColorPixelDataBinaryMask,
3352
+ blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults9.blendColorPixelDataAlphaMask
3272
3353
  } = deps;
3273
3354
  const OPTS = {
3274
3355
  x: 0,
@@ -3294,39 +3375,13 @@ var mutatorBlendColorPaintMask = ((writer, deps = defaults10) => {
3294
3375
  };
3295
3376
  });
3296
3377
 
3297
- // src/History/PixelMutator/mutatorBlendMask.ts
3298
- var defaults11 = {
3299
- blendPixelDataAlphaMask,
3300
- blendPixelDataBinaryMask
3301
- };
3302
- var mutatorBlendMask = ((writer, deps = defaults11) => {
3303
- const {
3304
- blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults11.blendPixelDataAlphaMask,
3305
- blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults11.blendPixelDataBinaryMask
3306
- } = deps;
3307
- return {
3308
- blendMask(src, mask, opts) {
3309
- const x = opts?.x ?? 0;
3310
- const y = opts?.y ?? 0;
3311
- const w = opts?.w ?? src.width;
3312
- const h = opts?.h ?? src.height;
3313
- const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3314
- if (mask.type === 1 /* BINARY */) {
3315
- return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
3316
- } else {
3317
- return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
3318
- }
3319
- }
3320
- };
3321
- });
3322
-
3323
- // src/History/PixelMutator/mutatorBlendPaintRect.ts
3324
- var defaults12 = {
3378
+ // src/History/PixelMutator/mutatorBlendColorPaintRect.ts
3379
+ var defaults10 = {
3325
3380
  blendColorPixelData
3326
3381
  };
3327
- var mutatorBlendPaintRect = ((writer, deps = defaults12) => {
3382
+ var mutatorBlendColorPaintRect = ((writer, deps = defaults10) => {
3328
3383
  const {
3329
- blendColorPixelData: blendColorPixelData2 = defaults12.blendColorPixelData
3384
+ blendColorPixelData: blendColorPixelData2 = defaults10.blendColorPixelData
3330
3385
  } = deps;
3331
3386
  const OPTS = {
3332
3387
  x: 0,
@@ -3337,7 +3392,7 @@ var mutatorBlendPaintRect = ((writer, deps = defaults12) => {
3337
3392
  alpha: 255
3338
3393
  };
3339
3394
  return {
3340
- blendPaintRect(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, blendFn = sourceOverPerfect) {
3395
+ blendColorPaintRect(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, blendFn = sourceOverPerfect) {
3341
3396
  const target = writer.config.target;
3342
3397
  const topLeftX = centerX + -(brushWidth - 1 >> 1);
3343
3398
  const topLeftY = centerY + -(brushHeight - 1 >> 1);
@@ -3353,16 +3408,42 @@ var mutatorBlendPaintRect = ((writer, deps = defaults12) => {
3353
3408
  };
3354
3409
  });
3355
3410
 
3411
+ // src/History/PixelMutator/mutatorBlendMask.ts
3412
+ var defaults11 = {
3413
+ blendPixelDataAlphaMask,
3414
+ blendPixelDataBinaryMask
3415
+ };
3416
+ var mutatorBlendMask = ((writer, deps = defaults11) => {
3417
+ const {
3418
+ blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults11.blendPixelDataAlphaMask,
3419
+ blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults11.blendPixelDataBinaryMask
3420
+ } = deps;
3421
+ return {
3422
+ blendMask(src, mask, opts) {
3423
+ const x = opts?.x ?? 0;
3424
+ const y = opts?.y ?? 0;
3425
+ const w = opts?.w ?? src.w;
3426
+ const h = opts?.h ?? src.h;
3427
+ const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3428
+ if (mask.type === 1 /* BINARY */) {
3429
+ return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
3430
+ } else {
3431
+ return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
3432
+ }
3433
+ }
3434
+ };
3435
+ });
3436
+
3356
3437
  // src/PixelData/blendPixel.ts
3357
3438
  function blendPixel(target, x, y, color, alpha = 255, blendFn = sourceOverPerfect) {
3358
3439
  if (alpha === 0) return false;
3359
- let width = target.width;
3360
- let height = target.height;
3440
+ let width = target.w;
3441
+ let height = target.h;
3361
3442
  if (x < 0 || x >= width || y < 0 || y >= height) return false;
3362
3443
  let srcAlpha = color >>> 24;
3363
3444
  let isOverwrite = blendFn.isOverwrite;
3364
3445
  if (srcAlpha === 0 && !isOverwrite) return false;
3365
- let dst32 = target.data32;
3446
+ let dst32 = target.data;
3366
3447
  let index = y * width + x;
3367
3448
  let finalColor = color;
3368
3449
  if (alpha !== 255) {
@@ -3380,12 +3461,12 @@ function blendPixel(target, x, y, color, alpha = 255, blendFn = sourceOverPerfec
3380
3461
  }
3381
3462
 
3382
3463
  // src/History/PixelMutator/mutatorBlendPixel.ts
3383
- var defaults13 = {
3464
+ var defaults12 = {
3384
3465
  blendPixel
3385
3466
  };
3386
- var mutatorBlendPixel = ((writer, deps = defaults13) => {
3467
+ var mutatorBlendPixel = ((writer, deps = defaults12) => {
3387
3468
  const {
3388
- blendPixel: blendPixel2 = defaults13.blendPixel
3469
+ blendPixel: blendPixel2 = defaults12.blendPixel
3389
3470
  } = deps;
3390
3471
  return {
3391
3472
  blendPixel(x, y, color, alpha, blendFn) {
@@ -3395,20 +3476,107 @@ var mutatorBlendPixel = ((writer, deps = defaults13) => {
3395
3476
  };
3396
3477
  });
3397
3478
 
3479
+ // src/PixelData/blendPixelData.ts
3480
+ function blendPixelData(target, src, opts) {
3481
+ const targetX = opts?.x ?? 0;
3482
+ const targetY = opts?.y ?? 0;
3483
+ const sourceX = opts?.sx ?? 0;
3484
+ const sourceY = opts?.sy ?? 0;
3485
+ const width = opts?.w ?? src.w;
3486
+ const height = opts?.h ?? src.h;
3487
+ const globalAlpha = opts?.alpha ?? 255;
3488
+ const blendFn = opts?.blendFn ?? sourceOverPerfect;
3489
+ if (globalAlpha === 0) return false;
3490
+ let x = targetX;
3491
+ let y = targetY;
3492
+ let sx = sourceX;
3493
+ let sy = sourceY;
3494
+ let w = width;
3495
+ let h = height;
3496
+ if (sx < 0) {
3497
+ x -= sx;
3498
+ w += sx;
3499
+ sx = 0;
3500
+ }
3501
+ if (sy < 0) {
3502
+ y -= sy;
3503
+ h += sy;
3504
+ sy = 0;
3505
+ }
3506
+ w = Math.min(w, src.w - sx);
3507
+ h = Math.min(h, src.h - sy);
3508
+ if (x < 0) {
3509
+ sx -= x;
3510
+ w += x;
3511
+ x = 0;
3512
+ }
3513
+ if (y < 0) {
3514
+ sy -= y;
3515
+ h += y;
3516
+ y = 0;
3517
+ }
3518
+ const actualW = Math.min(w, target.w - x);
3519
+ const actualH = Math.min(h, target.h - y);
3520
+ if (actualW <= 0 || actualH <= 0) return false;
3521
+ const dst32 = target.data;
3522
+ const src32 = src.data;
3523
+ const dw = target.w;
3524
+ const sw = src.w;
3525
+ let dIdx = y * dw + x | 0;
3526
+ let sIdx = sy * sw + sx | 0;
3527
+ const dStride = dw - actualW | 0;
3528
+ const sStride = sw - actualW | 0;
3529
+ const isOpaque = globalAlpha === 255;
3530
+ const isOverwrite = blendFn.isOverwrite;
3531
+ let didChange = false;
3532
+ for (let iy = 0; iy < actualH; iy++) {
3533
+ for (let ix = 0; ix < actualW; ix++) {
3534
+ const srcCol = src32[sIdx];
3535
+ const srcAlpha = srcCol >>> 24;
3536
+ if (srcAlpha === 0 && !isOverwrite) {
3537
+ dIdx++;
3538
+ sIdx++;
3539
+ continue;
3540
+ }
3541
+ let finalCol = srcCol;
3542
+ if (!isOpaque) {
3543
+ const a = srcAlpha * globalAlpha + 128 >> 8;
3544
+ if (a === 0 && !isOverwrite) {
3545
+ dIdx++;
3546
+ sIdx++;
3547
+ continue;
3548
+ }
3549
+ finalCol = (srcCol & 16777215 | a << 24) >>> 0;
3550
+ }
3551
+ const current = dst32[dIdx];
3552
+ const next = blendFn(finalCol, dst32[dIdx]);
3553
+ if (current !== next) {
3554
+ dst32[dIdx] = next;
3555
+ didChange = true;
3556
+ }
3557
+ dIdx++;
3558
+ sIdx++;
3559
+ }
3560
+ dIdx += dStride;
3561
+ sIdx += sStride;
3562
+ }
3563
+ return didChange;
3564
+ }
3565
+
3398
3566
  // src/History/PixelMutator/mutatorBlendPixelData.ts
3399
- var defaults14 = {
3567
+ var defaults13 = {
3400
3568
  blendPixelData
3401
3569
  };
3402
- var mutatorBlendPixelData = ((writer, deps = defaults14) => {
3570
+ var mutatorBlendPixelData = ((writer, deps = defaults13) => {
3403
3571
  const {
3404
- blendPixelData: blendPixelData2 = defaults14.blendPixelData
3572
+ blendPixelData: blendPixelData2 = defaults13.blendPixelData
3405
3573
  } = deps;
3406
3574
  return {
3407
3575
  blendPixelData(src, opts) {
3408
3576
  const x = opts?.x ?? 0;
3409
3577
  const y = opts?.y ?? 0;
3410
- const w = opts?.w ?? src.width;
3411
- const h = opts?.h ?? src.height;
3578
+ const w = opts?.w ?? src.w;
3579
+ const h = opts?.h ?? src.h;
3412
3580
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3413
3581
  return didChange(blendPixelData2(writer.config.target, src, opts));
3414
3582
  }
@@ -3425,8 +3593,8 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3425
3593
  if (typeof _x === "object") {
3426
3594
  x = _x.x ?? 0;
3427
3595
  y = _x.y ?? 0;
3428
- w = _x.w ?? dst.width;
3429
- h = _x.h ?? dst.height;
3596
+ w = _x.w ?? dst.w;
3597
+ h = _x.h ?? dst.h;
3430
3598
  } else if (typeof _x === "number") {
3431
3599
  x = _x;
3432
3600
  y = _y;
@@ -3435,10 +3603,10 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3435
3603
  } else {
3436
3604
  x = 0;
3437
3605
  y = 0;
3438
- w = dst.width;
3439
- h = dst.height;
3606
+ w = dst.w;
3607
+ h = dst.h;
3440
3608
  }
3441
- const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT);
3609
+ const clip = resolveRectClipping(x, y, w, h, dst.w, dst.h, SCRATCH_RECT);
3442
3610
  if (!clip.inBounds) return false;
3443
3611
  const {
3444
3612
  x: finalX,
@@ -3446,8 +3614,8 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3446
3614
  w: actualW,
3447
3615
  h: actualH
3448
3616
  } = clip;
3449
- const dst32 = dst.data32;
3450
- const dw = dst.width;
3617
+ const dst32 = dst.data;
3618
+ const dw = dst.w;
3451
3619
  let hasChanged = false;
3452
3620
  for (let iy = 0; iy < actualH; iy++) {
3453
3621
  const rowOffset = (finalY + iy) * dw;
@@ -3464,20 +3632,20 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3464
3632
  }
3465
3633
 
3466
3634
  // src/History/PixelMutator/mutatorClear.ts
3467
- var defaults15 = {
3635
+ var defaults14 = {
3468
3636
  fillPixelData
3469
3637
  };
3470
- var mutatorClear = ((writer, deps = defaults15) => {
3638
+ var mutatorClear = ((writer, deps = defaults14) => {
3471
3639
  const {
3472
- fillPixelData: fillPixelData2 = defaults15.fillPixelData
3640
+ fillPixelData: fillPixelData2 = defaults14.fillPixelData
3473
3641
  } = deps;
3474
3642
  return {
3475
3643
  clear(rect) {
3476
3644
  const target = writer.config.target;
3477
3645
  const x = rect?.x ?? 0;
3478
3646
  const y = rect?.y ?? 0;
3479
- const w = rect?.w ?? target.width;
3480
- const h = rect?.h ?? target.height;
3647
+ const w = rect?.w ?? target.w;
3648
+ const h = rect?.h ?? target.h;
3481
3649
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3482
3650
  return didChange(fillPixelData2(target, 0, x, y, w, h));
3483
3651
  }
@@ -3485,24 +3653,24 @@ var mutatorClear = ((writer, deps = defaults15) => {
3485
3653
  });
3486
3654
 
3487
3655
  // src/History/PixelMutator/mutatorFill.ts
3488
- var defaults16 = {
3656
+ var defaults15 = {
3489
3657
  fillPixelData
3490
3658
  };
3491
- var mutatorFill = ((writer, deps = defaults16) => {
3659
+ var mutatorFill = ((writer, deps = defaults15) => {
3492
3660
  const {
3493
- fillPixelData: fillPixelData2 = defaults16.fillPixelData
3661
+ fillPixelData: fillPixelData2 = defaults15.fillPixelData
3494
3662
  } = deps;
3495
3663
  return {
3496
- fill(color, x = 0, y = 0, w = writer.config.target.width, h = writer.config.target.height) {
3664
+ fill(color, x = 0, y = 0, w = writer.config.target.w, h = writer.config.target.h) {
3497
3665
  const target = writer.config.target;
3498
3666
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3499
3667
  return didChange(fillPixelData2(target, color, x, y, w, h));
3500
3668
  }
3501
3669
  };
3502
3670
  });
3503
- var mutatorFillRect = ((writer, deps = defaults16) => {
3671
+ var mutatorFillRect = ((writer, deps = defaults15) => {
3504
3672
  const {
3505
- fillPixelData: fillPixelData2 = defaults16.fillPixelData
3673
+ fillPixelData: fillPixelData2 = defaults15.fillPixelData
3506
3674
  } = deps;
3507
3675
  return {
3508
3676
  fillRect(color, rect) {
@@ -3518,7 +3686,7 @@ var SCRATCH_RECT2 = makeClippedRect();
3518
3686
  function fillPixelDataBinaryMask(target, color, mask, x = 0, y = 0) {
3519
3687
  const maskW = mask.w;
3520
3688
  const maskH = mask.h;
3521
- const clip = resolveRectClipping(x, y, maskW, maskH, target.width, target.height, SCRATCH_RECT2);
3689
+ const clip = resolveRectClipping(x, y, maskW, maskH, target.w, target.h, SCRATCH_RECT2);
3522
3690
  if (!clip.inBounds) return false;
3523
3691
  const {
3524
3692
  x: finalX,
@@ -3527,8 +3695,8 @@ function fillPixelDataBinaryMask(target, color, mask, x = 0, y = 0) {
3527
3695
  h: actualH
3528
3696
  } = clip;
3529
3697
  const maskData = mask.data;
3530
- const dst32 = target.data32;
3531
- const dw = target.width;
3698
+ const dst32 = target.data;
3699
+ const dw = target.w;
3532
3700
  let hasChanged = false;
3533
3701
  for (let iy = 0; iy < actualH; iy++) {
3534
3702
  const currentY = finalY + iy;
@@ -3552,12 +3720,12 @@ function fillPixelDataBinaryMask(target, color, mask, x = 0, y = 0) {
3552
3720
  }
3553
3721
 
3554
3722
  // src/History/PixelMutator/mutatorFillBinaryMask.ts
3555
- var defaults17 = {
3723
+ var defaults16 = {
3556
3724
  fillPixelDataBinaryMask
3557
3725
  };
3558
- var mutatorFillBinaryMask = ((writer, deps = defaults17) => {
3726
+ var mutatorFillBinaryMask = ((writer, deps = defaults16) => {
3559
3727
  const {
3560
- fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults17.fillPixelDataBinaryMask
3728
+ fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults16.fillPixelDataBinaryMask
3561
3729
  } = deps;
3562
3730
  return {
3563
3731
  fillBinaryMask(color, mask, x = 0, y = 0) {
@@ -3575,10 +3743,10 @@ function invertPixelData(target, opts) {
3575
3743
  const targetY = opts?.y ?? 0;
3576
3744
  const mx = opts?.mx ?? 0;
3577
3745
  const my = opts?.my ?? 0;
3578
- const width = opts?.w ?? target.width;
3579
- const height = opts?.h ?? target.height;
3746
+ const width = opts?.w ?? target.w;
3747
+ const height = opts?.h ?? target.h;
3580
3748
  const invertMask = opts?.invertMask ?? false;
3581
- const clip = resolveRectClipping(targetX, targetY, width, height, target.width, target.height, SCRATCH_RECT3);
3749
+ const clip = resolveRectClipping(targetX, targetY, width, height, target.w, target.h, SCRATCH_RECT3);
3582
3750
  if (!clip.inBounds) return false;
3583
3751
  const {
3584
3752
  x,
@@ -3586,8 +3754,8 @@ function invertPixelData(target, opts) {
3586
3754
  w: actualW,
3587
3755
  h: actualH
3588
3756
  } = clip;
3589
- const dst32 = target.data32;
3590
- const dw = target.width;
3757
+ const dst32 = target.data;
3758
+ const dw = target.w;
3591
3759
  const mPitch = mask?.w ?? width;
3592
3760
  const dx = x - targetX;
3593
3761
  const dy = y - targetY;
@@ -3623,20 +3791,20 @@ function invertPixelData(target, opts) {
3623
3791
  }
3624
3792
 
3625
3793
  // src/History/PixelMutator/mutatorInvert.ts
3626
- var defaults18 = {
3794
+ var defaults17 = {
3627
3795
  invertPixelData
3628
3796
  };
3629
- var mutatorInvert = ((writer, deps = defaults18) => {
3797
+ var mutatorInvert = ((writer, deps = defaults17) => {
3630
3798
  const {
3631
- invertPixelData: invertPixelData2 = defaults18.invertPixelData
3799
+ invertPixelData: invertPixelData2 = defaults17.invertPixelData
3632
3800
  } = deps;
3633
3801
  return {
3634
3802
  invert(opts) {
3635
3803
  const target = writer.config.target;
3636
3804
  const x = opts?.x ?? 0;
3637
3805
  const y = opts?.y ?? 0;
3638
- const w = opts?.w ?? target.width;
3639
- const h = opts?.h ?? target.height;
3806
+ const w = opts?.w ?? target.w;
3807
+ const h = opts?.h ?? target.h;
3640
3808
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3641
3809
  return didChange(invertPixelData2(target, opts));
3642
3810
  }
@@ -3656,8 +3824,8 @@ function makeFullPixelMutator(writer) {
3656
3824
  ...mutatorBlendColorPaintAlphaMask(writer),
3657
3825
  ...mutatorBlendColorPaintBinaryMask(writer),
3658
3826
  ...mutatorBlendColorPaintMask(writer),
3827
+ ...mutatorBlendColorPaintRect(writer),
3659
3828
  ...mutatorBlendMask(writer),
3660
- ...mutatorBlendPaintRect(writer),
3661
3829
  ...mutatorBlendPixel(writer),
3662
3830
  ...mutatorBlendPixelData(writer),
3663
3831
  ...mutatorClear(writer),
@@ -3668,30 +3836,6 @@ function makeFullPixelMutator(writer) {
3668
3836
  };
3669
3837
  }
3670
3838
 
3671
- // src/ImageData/ImageDataLike.ts
3672
- function makeImageDataLike(width, height, data) {
3673
- const size = width * height * 4;
3674
- const buffer = data ? new Uint8ClampedArray(data.buffer, data.byteOffset, size) : new Uint8ClampedArray(size);
3675
- return {
3676
- width,
3677
- height,
3678
- data: buffer
3679
- };
3680
- }
3681
-
3682
- // src/ImageData/ReusableImageData.ts
3683
- function makeReusableImageData() {
3684
- let imageData = null;
3685
- return function getReusableImageData(width, height) {
3686
- if (imageData === null || imageData.width !== width || imageData.height !== height) {
3687
- imageData = new ImageData(width, height);
3688
- } else {
3689
- imageData.data.fill(0);
3690
- }
3691
- return imageData;
3692
- };
3693
- }
3694
-
3695
3839
  // src/ImageData/copyImageData.ts
3696
3840
  function copyImageData({
3697
3841
  data,
@@ -3712,6 +3856,17 @@ function copyImageDataLike({
3712
3856
  };
3713
3857
  }
3714
3858
 
3859
+ // src/ImageData/ImageDataLike.ts
3860
+ function makeImageDataLike(width, height, data) {
3861
+ const size = width * height * 4;
3862
+ const buffer = data ? new Uint8ClampedArray(data.buffer, data.byteOffset, size) : new Uint8ClampedArray(size);
3863
+ return {
3864
+ width,
3865
+ height,
3866
+ data: buffer
3867
+ };
3868
+ }
3869
+
3715
3870
  // src/ImageData/imageDataToAlphaMaskBuffer.ts
3716
3871
  function imageDataToAlphaMaskBuffer(imageData) {
3717
3872
  const {
@@ -3741,8 +3896,8 @@ function imageDataToDataUrl(imageData) {
3741
3896
  }
3742
3897
  imageDataToDataUrl.reset = get.reset;
3743
3898
 
3744
- // src/ImageData/imageDataToUInt32Array.ts
3745
- function imageDataToUInt32Array(imageData) {
3899
+ // src/ImageData/imageDataToUint32Array.ts
3900
+ function imageDataToUint32Array(imageData) {
3746
3901
  return new Uint32Array(
3747
3902
  imageData.data.buffer,
3748
3903
  imageData.data.byteOffset,
@@ -3763,43 +3918,29 @@ function invertImageData(imageData) {
3763
3918
  return imageData;
3764
3919
  }
3765
3920
 
3766
- // src/Internal/resample32.ts
3767
- var resample32Scratch = {
3768
- data: null,
3769
- width: 0,
3770
- height: 0
3771
- };
3772
- function resample32(srcData32, srcW, srcH, factor) {
3773
- const dstW = Math.max(1, srcW * factor | 0);
3774
- const dstH = Math.max(1, srcH * factor | 0);
3775
- const dstData = new Int32Array(dstW * dstH);
3776
- const scaleX = srcW / dstW;
3777
- const scaleY = srcH / dstH;
3778
- for (let y = 0; y < dstH; y++) {
3779
- const srcY = Math.min(srcH - 1, y * scaleY | 0);
3780
- const srcRowOffset = srcY * srcW;
3781
- const dstRowOffset = y * dstW;
3782
- for (let x = 0; x < dstW; x++) {
3783
- const srcX = Math.min(srcW - 1, x * scaleX | 0);
3784
- dstData[dstRowOffset + x] = srcData32[srcRowOffset + srcX];
3785
- }
3786
- }
3787
- resample32Scratch.data = dstData;
3788
- resample32Scratch.width = dstW;
3789
- resample32Scratch.height = dstH;
3790
- return resample32Scratch;
3791
- }
3792
-
3793
3921
  // src/ImageData/resampleImageData.ts
3794
3922
  function resampleImageData(source, factor) {
3795
3923
  const src32 = new Uint32Array(source.data.buffer);
3796
3924
  const {
3797
3925
  data,
3798
- width,
3799
- height
3800
- } = resample32(src32, source.width, source.height, factor);
3926
+ w,
3927
+ h
3928
+ } = resampleUint32Array(src32, source.width, source.height, factor);
3801
3929
  const uint8ClampedArray = new Uint8ClampedArray(data.buffer);
3802
- return new ImageData(uint8ClampedArray, width, height);
3930
+ return new ImageData(uint8ClampedArray, w, h);
3931
+ }
3932
+
3933
+ // src/ImageData/ReusableImageData.ts
3934
+ function makeReusableImageData() {
3935
+ let imageData = null;
3936
+ return function getReusableImageData(width, height) {
3937
+ if (imageData === null || imageData.width !== width || imageData.height !== height) {
3938
+ imageData = new ImageData(width, height);
3939
+ } else {
3940
+ imageData.data.fill(0);
3941
+ }
3942
+ return imageData;
3943
+ };
3803
3944
  }
3804
3945
 
3805
3946
  // src/ImageData/serialization.ts
@@ -3956,89 +4097,11 @@ function writeImageDataBuffer(target, data, _x, _y, _w, _h) {
3956
4097
  }
3957
4098
  }
3958
4099
 
3959
- // src/IndexedImage/IndexedImage.ts
3960
- var IndexedImage = class _IndexedImage {
3961
- /** The width of the image in pixels. */
3962
- width;
3963
- /** The height of the image in pixels. */
3964
- height;
3965
- /** Flat array of palette indices. Index = x + (y * width). */
3966
- data;
3967
- /** The palette of unique 32-bit colors (ABGR/RGBA packed) found in the image. */
3968
- palette;
3969
- /** The specific index in the palette reserved for fully transparent pixels. */
3970
- transparentPalletIndex;
3971
- /**
3972
- * @param width - Image width.
3973
- * @param height - Image height.
3974
- * @param data - The indexed pixel data.
3975
- * @param palette - The array of packed colors.
3976
- * @param transparentPalletIndex - The index representing alpha 0.
3977
- */
3978
- constructor(width, height, data, palette, transparentPalletIndex) {
3979
- this.width = width;
3980
- this.height = height;
3981
- this.data = data;
3982
- this.palette = palette;
3983
- this.transparentPalletIndex = transparentPalletIndex;
3984
- }
3985
- /**
3986
- * Creates an IndexedImage from standard browser ImageData.
3987
- * @param imageData - The source ImageData to convert.
3988
- * @returns A new IndexedImage instance.
3989
- */
3990
- static fromImageData(imageData) {
3991
- return _IndexedImage.fromRaw(imageData.data, imageData.width, imageData.height);
3992
- }
3993
- /**
3994
- * Creates an IndexedImage from a raw byte buffer and dimensions.
3995
- * Any pixel with an alpha channel of 0 is normalized to the transparent palette index.
3996
- * @param data - Raw RGBA byte data.
3997
- * @param width - Image width.
3998
- * @param height - Image height.
3999
- * @returns A new IndexedImage instance.
4000
- */
4001
- static fromRaw(data, width, height) {
4002
- const buffer = data.buffer;
4003
- const rawData = new Uint32Array(buffer);
4004
- const indexedData = new Int32Array(rawData.length);
4005
- const colorMap = /* @__PURE__ */ new Map();
4006
- const transparentColor = 0;
4007
- const transparentPalletIndex = 0;
4008
- colorMap.set(transparentColor, transparentPalletIndex);
4009
- for (let i = 0; i < rawData.length; i++) {
4010
- const pixel = rawData[i];
4011
- const alpha = pixel >>> 24 & 255;
4012
- const isTransparent = alpha === 0;
4013
- const colorKey = isTransparent ? transparentColor : pixel >>> 0;
4014
- let id = colorMap.get(colorKey);
4015
- if (id === void 0) {
4016
- id = colorMap.size;
4017
- colorMap.set(colorKey, id);
4018
- }
4019
- indexedData[i] = id;
4020
- }
4021
- const palette = Uint32Array.from(colorMap.keys());
4022
- return new _IndexedImage(width, height, indexedData, palette, transparentPalletIndex);
4023
- }
4024
- /**
4025
- * Retrieves the 32-bit packed color value at the given coordinates.
4026
- * @param x - X coordinate.
4027
- * @param y - Y coordinate.
4028
- * @returns The packed color from the palette.
4029
- */
4030
- getColorAt(x, y) {
4031
- const index = x + y * this.width;
4032
- const paletteIndex = this.data[index];
4033
- return this.palette[paletteIndex];
4034
- }
4035
- };
4036
-
4037
4100
  // src/IndexedImage/getIndexedImageColorCounts.ts
4038
4101
  function getIndexedImageColorCounts(indexedImage) {
4039
4102
  const data = indexedImage.data;
4040
4103
  const palette = indexedImage.palette;
4041
- const frequencies = new Int32Array(palette.length);
4104
+ const frequencies = new Uint32Array(palette.length);
4042
4105
  for (let i = 0; i < data.length; i++) {
4043
4106
  const colorIndex = data[i];
4044
4107
  frequencies[colorIndex]++;
@@ -4046,6 +4109,48 @@ function getIndexedImageColorCounts(indexedImage) {
4046
4109
  return frequencies;
4047
4110
  }
4048
4111
 
4112
+ // src/IndexedImage/IndexedImage.ts
4113
+ function makeIndexedImage(width, height, data, palette, transparentPalletIndex) {
4114
+ return {
4115
+ w: width,
4116
+ h: height,
4117
+ data,
4118
+ palette,
4119
+ transparentPalletIndex
4120
+ };
4121
+ }
4122
+ function makeIndexedImageFromImageDataRaw(data, width, height) {
4123
+ const buffer = data.buffer;
4124
+ const rawData = new Uint32Array(buffer);
4125
+ const indexedData = new Uint32Array(rawData.length);
4126
+ const colorMap = /* @__PURE__ */ new Map();
4127
+ const transparentColor = 0;
4128
+ const transparentPalletIndex = 0;
4129
+ colorMap.set(transparentColor, transparentPalletIndex);
4130
+ for (let i = 0; i < rawData.length; i++) {
4131
+ const pixel = rawData[i];
4132
+ const alpha = pixel >>> 24 & 255;
4133
+ const isTransparent = alpha === 0;
4134
+ const colorKey = isTransparent ? transparentColor : pixel >>> 0;
4135
+ let id = colorMap.get(colorKey);
4136
+ if (id === void 0) {
4137
+ id = colorMap.size;
4138
+ colorMap.set(colorKey, id);
4139
+ }
4140
+ indexedData[i] = id;
4141
+ }
4142
+ const palette = Uint32Array.from(colorMap.keys());
4143
+ return makeIndexedImage(width, height, indexedData, palette, transparentPalletIndex);
4144
+ }
4145
+ function makeIndexedImageFromImageData(imageData) {
4146
+ return makeIndexedImageFromImageDataRaw(imageData.data, imageData.width, imageData.height);
4147
+ }
4148
+ function getIndexedImageColor(target, x, y) {
4149
+ const index = x + y * target.w;
4150
+ const paletteIndex = target.data[index];
4151
+ return target.palette[paletteIndex];
4152
+ }
4153
+
4049
4154
  // src/IndexedImage/indexedImageToAverageColor.ts
4050
4155
  function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
4051
4156
  const {
@@ -4095,29 +4200,27 @@ function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
4095
4200
  // src/IndexedImage/indexedImageToImageData.ts
4096
4201
  function indexedImageToImageData(indexedImage) {
4097
4202
  const {
4098
- width,
4099
- height,
4203
+ w,
4204
+ h,
4100
4205
  data,
4101
4206
  palette
4102
4207
  } = indexedImage;
4103
- const result = new ImageData(width, height);
4208
+ const result = new ImageData(w, h);
4104
4209
  const data32 = new Uint32Array(result.data.buffer);
4105
4210
  for (let i = 0; i < data.length; i++) {
4106
4211
  const paletteIndex = data[i];
4107
- const color = palette[paletteIndex];
4108
- data32[i] = color;
4212
+ data32[i] = palette[paletteIndex];
4109
4213
  }
4110
4214
  return result;
4111
4215
  }
4112
4216
 
4113
4217
  // src/IndexedImage/resampleIndexedImage.ts
4114
4218
  function resampleIndexedImage(source, factor) {
4115
- const {
4116
- data,
4117
- width,
4118
- height
4119
- } = resample32(source.data, source.width, source.height, factor);
4120
- return new IndexedImage(width, height, data, source.palette, source.transparentPalletIndex);
4219
+ const output = {
4220
+ palette: source.palette,
4221
+ transparentPalletIndex: source.transparentPalletIndex
4222
+ };
4223
+ return resampleUint32Array(source.data, source.w, source.h, factor, output);
4121
4224
  }
4122
4225
 
4123
4226
  // src/Input/fileInputChangeToImageData.ts
@@ -4193,16 +4296,6 @@ function makeAlphaMask(w, h, data) {
4193
4296
  };
4194
4297
  }
4195
4298
 
4196
- // src/Mask/BinaryMask.ts
4197
- function makeBinaryMask(w, h, data) {
4198
- return {
4199
- type: 1 /* BINARY */,
4200
- data: data ?? new Uint8Array(w * h),
4201
- w,
4202
- h
4203
- };
4204
- }
4205
-
4206
4299
  // src/Mask/applyBinaryMaskToAlphaMask.ts
4207
4300
  function applyBinaryMaskToAlphaMask(alphaMaskDst, binaryMaskSrc, opts) {
4208
4301
  const targetX = opts?.x ?? 0;
@@ -4272,6 +4365,215 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, binaryMaskSrc, opts) {
4272
4365
  }
4273
4366
  }
4274
4367
 
4368
+ // src/Mask/BinaryMask.ts
4369
+ function makeBinaryMask(w, h, data) {
4370
+ return {
4371
+ type: 1 /* BINARY */,
4372
+ data: data ?? new Uint8Array(w * h),
4373
+ w,
4374
+ h
4375
+ };
4376
+ }
4377
+
4378
+ // src/Mask/BinaryMask/makeBinaryMaskFromAlphaMask.ts
4379
+ function makeBinaryMaskFromAlphaMask(mask, threshold, out) {
4380
+ const w = mask.w;
4381
+ const h = mask.h;
4382
+ const alphaData = mask.data;
4383
+ const area = w * h;
4384
+ const binaryData = new Uint8Array(area);
4385
+ for (let i = 0; i < area; i++) {
4386
+ if (alphaData[i] >= threshold) {
4387
+ binaryData[i] = 1;
4388
+ }
4389
+ }
4390
+ out = out ?? {
4391
+ type: 1 /* BINARY */
4392
+ };
4393
+ out.data = binaryData;
4394
+ out.w = w;
4395
+ out.h = h;
4396
+ return out;
4397
+ }
4398
+
4399
+ // src/Mask/BinaryMask/makeBinaryMaskOutline.ts
4400
+ function makeBinaryMaskOutline(mask, scale = 1) {
4401
+ const w = mask.w;
4402
+ const h = mask.h;
4403
+ const maskData = mask.data;
4404
+ const size = w * scale + 2;
4405
+ const outData = new Uint8Array(size * size);
4406
+ for (let iy = 0; iy < h; iy++) {
4407
+ for (let ix = 0; ix < w; ix++) {
4408
+ const i = iy * w + ix;
4409
+ if (maskData[i] === 0) continue;
4410
+ const lx = ix * scale + 1;
4411
+ const ly = iy * scale + 1;
4412
+ const top = iy === 0 || maskData[i - w] === 0;
4413
+ const bottom = iy === h - 1 || maskData[i + w] === 0;
4414
+ const left = ix === 0 || maskData[i - 1] === 0;
4415
+ const right = ix === w - 1 || maskData[i + 1] === 0;
4416
+ const topLeft = iy === 0 || ix === 0 || maskData[i - w - 1] === 0;
4417
+ const topRight = iy === 0 || ix === w - 1 || maskData[i - w + 1] === 0;
4418
+ const bottomLeft = iy === h - 1 || ix === 0 || maskData[i + w - 1] === 0;
4419
+ const bottomRight = iy === h - 1 || ix === w - 1 || maskData[i + w + 1] === 0;
4420
+ if (top) {
4421
+ for (let sx = 0; sx < scale; sx++) {
4422
+ const outIdx = (ly - 1) * size + (lx + sx);
4423
+ outData[outIdx] = 1;
4424
+ }
4425
+ }
4426
+ if (bottom) {
4427
+ for (let sx = 0; sx < scale; sx++) {
4428
+ const outIdx = (ly + scale) * size + (lx + sx);
4429
+ outData[outIdx] = 1;
4430
+ }
4431
+ }
4432
+ if (left) {
4433
+ for (let sy = 0; sy < scale; sy++) {
4434
+ const outIdx = (ly + sy) * size + (lx - 1);
4435
+ outData[outIdx] = 1;
4436
+ }
4437
+ }
4438
+ if (right) {
4439
+ for (let sy = 0; sy < scale; sy++) {
4440
+ const outIdx = (ly + sy) * size + (lx + scale);
4441
+ outData[outIdx] = 1;
4442
+ }
4443
+ }
4444
+ if (topLeft) {
4445
+ const outIdx = (ly - 1) * size + (lx - 1);
4446
+ outData[outIdx] = 1;
4447
+ }
4448
+ if (topRight) {
4449
+ const outIdx = (ly - 1) * size + (lx + scale);
4450
+ outData[outIdx] = 1;
4451
+ }
4452
+ if (bottomLeft) {
4453
+ const outIdx = (ly + scale) * size + (lx - 1);
4454
+ outData[outIdx] = 1;
4455
+ }
4456
+ if (bottomRight) {
4457
+ const outIdx = (ly + scale) * size + (lx + scale);
4458
+ outData[outIdx] = 1;
4459
+ }
4460
+ }
4461
+ }
4462
+ return {
4463
+ type: 1 /* BINARY */,
4464
+ w: size,
4465
+ h: size,
4466
+ data: outData
4467
+ };
4468
+ }
4469
+
4470
+ // src/Mask/BinaryMask/makeCircleBinaryMaskOutline.ts
4471
+ function makeCircleBinaryMaskOutline(size, scale) {
4472
+ const outSize = size * scale + 2;
4473
+ const outArea = outSize * outSize;
4474
+ const data = new Uint8Array(outArea);
4475
+ const radius = size / 2;
4476
+ const r2 = radius * radius;
4477
+ let prevMinX = -1;
4478
+ let prevMaxX = -1;
4479
+ let currMinX = -1;
4480
+ let currMaxX = -1;
4481
+ const initialDy = 0 - radius + 0.5;
4482
+ const initialDy2 = initialDy * initialDy;
4483
+ if (initialDy2 <= r2) {
4484
+ const dx = Math.sqrt(r2 - initialDy2);
4485
+ currMinX = Math.ceil(radius - 0.5 - dx);
4486
+ currMaxX = Math.floor(radius - 0.5 + dx);
4487
+ }
4488
+ for (let iy = 0; iy < size; iy++) {
4489
+ let nextMinX = -1;
4490
+ let nextMaxX = -1;
4491
+ if (iy + 1 < size) {
4492
+ const ny = iy + 1 - radius + 0.5;
4493
+ const ny2 = ny * ny;
4494
+ if (ny2 <= r2) {
4495
+ const dx = Math.sqrt(r2 - ny2);
4496
+ nextMinX = Math.ceil(radius - 0.5 - dx);
4497
+ nextMaxX = Math.floor(radius - 0.5 + dx);
4498
+ }
4499
+ }
4500
+ if (currMinX !== -1) {
4501
+ for (let ix = currMinX; ix <= currMaxX; ix++) {
4502
+ const sx = ix * scale + 1;
4503
+ const sy = iy * scale + 1;
4504
+ const isTop = prevMinX === -1 || ix < prevMinX || ix > prevMaxX;
4505
+ const isBottom = nextMinX === -1 || ix < nextMinX || ix > nextMaxX;
4506
+ const isLeft = ix === currMinX;
4507
+ const isRight = ix === currMaxX;
4508
+ if (isTop) {
4509
+ const leftOut = prevMinX === -1 || ix - 1 < prevMinX || ix - 1 > prevMaxX;
4510
+ const rightOut = prevMinX === -1 || ix + 1 < prevMinX || ix + 1 > prevMaxX;
4511
+ const startX = leftOut ? sx - 1 : sx;
4512
+ const endX = rightOut ? sx + scale : sx + scale - 1;
4513
+ for (let x = startX; x <= endX; x++) {
4514
+ const index = (sy - 1) * outSize + x;
4515
+ data[index] = 1;
4516
+ }
4517
+ }
4518
+ if (isBottom) {
4519
+ const leftOut = nextMinX === -1 || ix - 1 < nextMinX || ix - 1 > nextMaxX;
4520
+ const rightOut = nextMinX === -1 || ix + 1 < nextMinX || ix + 1 > nextMaxX;
4521
+ const startX = leftOut ? sx - 1 : sx;
4522
+ const endX = rightOut ? sx + scale : sx + scale - 1;
4523
+ for (let x = startX; x <= endX; x++) {
4524
+ const index = (sy + scale) * outSize + x;
4525
+ data[index] = 1;
4526
+ }
4527
+ }
4528
+ if (isLeft) {
4529
+ for (let y = sy; y < sy + scale; y++) {
4530
+ const index = y * outSize + (sx - 1);
4531
+ data[index] = 1;
4532
+ }
4533
+ }
4534
+ if (isRight) {
4535
+ for (let y = sy; y < sy + scale; y++) {
4536
+ const index = y * outSize + (sx + scale);
4537
+ data[index] = 1;
4538
+ }
4539
+ }
4540
+ }
4541
+ }
4542
+ prevMinX = currMinX;
4543
+ prevMaxX = currMaxX;
4544
+ currMinX = nextMinX;
4545
+ currMaxX = nextMaxX;
4546
+ }
4547
+ return {
4548
+ type: 1 /* BINARY */,
4549
+ w: outSize,
4550
+ h: outSize,
4551
+ data
4552
+ };
4553
+ }
4554
+
4555
+ // src/Mask/BinaryMask/makeRectBinaryMaskOutline.ts
4556
+ function makeRectBinaryMaskOutline(w, h, scale = 1) {
4557
+ const rw = w * scale;
4558
+ const rh = h * scale;
4559
+ const outW = rw + 2;
4560
+ const outH = rh + 2;
4561
+ const outData = new Uint8Array(outW * outH);
4562
+ outData.fill(1, 0, outW);
4563
+ outData.fill(1, (outH - 1) * outW, outH * outW);
4564
+ for (let iy = 1; iy < outH - 1; iy++) {
4565
+ const rowStart = iy * outW;
4566
+ outData[rowStart] = 1;
4567
+ outData[rowStart + outW - 1] = 1;
4568
+ }
4569
+ return {
4570
+ type: 1 /* BINARY */,
4571
+ w: outW,
4572
+ h: outH,
4573
+ data: outData
4574
+ };
4575
+ }
4576
+
4275
4577
  // src/Mask/copyMask.ts
4276
4578
  function copyMask(src) {
4277
4579
  return {
@@ -4379,7 +4681,8 @@ function mergeAlphaMasks(dst, src, opts) {
4379
4681
  } else if (globalAlpha === 255) {
4380
4682
  weight = effectiveM;
4381
4683
  } else {
4382
- weight = effectiveM * globalAlpha + 128 >> 8;
4684
+ const t = effectiveM * globalAlpha + 128;
4685
+ weight = t + (t >> 8) >> 8;
4383
4686
  }
4384
4687
  if (weight !== 255) {
4385
4688
  if (weight === 0) {
@@ -4389,7 +4692,8 @@ function mergeAlphaMasks(dst, src, opts) {
4389
4692
  if (da === 255) {
4390
4693
  dstData[dIdx] = weight;
4391
4694
  } else if (da !== 0) {
4392
- dstData[dIdx] = da * weight + 128 >> 8;
4695
+ const t = da * weight + 128;
4696
+ dstData[dIdx] = t + (t >> 8) >> 8;
4393
4697
  }
4394
4698
  }
4395
4699
  }
@@ -4550,92 +4854,758 @@ function merge2BinaryMaskRects(a, b) {
4550
4854
  }
4551
4855
  }
4552
4856
  }
4553
- return {
4554
- ...bounds,
4555
- data: maskData,
4556
- type: 1 /* BINARY */
4557
- };
4558
- }
4559
-
4560
- // src/MaskRect/mergeBinaryMaskRects.ts
4561
- function mergeBinaryMaskRects(current, adding) {
4562
- const rects = [...current, ...adding];
4563
- let changed = true;
4564
- while (changed) {
4565
- changed = false;
4566
- const next = [];
4567
- for (const r of rects) {
4568
- let merged = false;
4569
- for (let i = 0; i < next.length; i++) {
4570
- const n = next[i];
4571
- const overlap = r.x <= n.x + n.w && r.x + r.w >= n.x && r.y <= n.y + n.h && r.y + r.h >= n.y;
4572
- if (overlap) {
4573
- next[i] = merge2BinaryMaskRects(n, r);
4574
- merged = true;
4857
+ return {
4858
+ ...bounds,
4859
+ data: maskData,
4860
+ type: 1 /* BINARY */
4861
+ };
4862
+ }
4863
+
4864
+ // src/MaskRect/mergeBinaryMaskRects.ts
4865
+ function mergeBinaryMaskRects(current, adding) {
4866
+ const rects = [...current, ...adding];
4867
+ let changed = true;
4868
+ while (changed) {
4869
+ changed = false;
4870
+ const next = [];
4871
+ for (const r of rects) {
4872
+ let merged = false;
4873
+ for (let i = 0; i < next.length; i++) {
4874
+ const n = next[i];
4875
+ const overlap = r.x <= n.x + n.w && r.x + r.w >= n.x && r.y <= n.y + n.h && r.y + r.h >= n.y;
4876
+ if (overlap) {
4877
+ next[i] = merge2BinaryMaskRects(n, r);
4878
+ merged = true;
4879
+ changed = true;
4880
+ break;
4881
+ }
4882
+ }
4883
+ if (!merged) next.push(r);
4884
+ }
4885
+ rects.splice(0, rects.length, ...next);
4886
+ }
4887
+ return rects;
4888
+ }
4889
+
4890
+ // src/MaskRect/subtractBinaryMaskRects.ts
4891
+ function subtractBinaryMaskRects(current, subtracting) {
4892
+ let result = [...current];
4893
+ for (const sub of subtracting) {
4894
+ const next = [];
4895
+ for (const r of result) {
4896
+ const ix = Math.max(r.x, sub.x);
4897
+ const iy = Math.max(r.y, sub.y);
4898
+ const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
4899
+ const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
4900
+ if (ix >= ix2 || iy >= iy2) {
4901
+ next.push(r);
4902
+ continue;
4903
+ }
4904
+ if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
4905
+ if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
4906
+ if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
4907
+ if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
4908
+ }
4909
+ result = next;
4910
+ }
4911
+ return result;
4912
+ }
4913
+ function pushPiece(dest, r, x, y, w, h) {
4914
+ if (r.data === null || r.data === void 0) {
4915
+ dest.push({
4916
+ x,
4917
+ y,
4918
+ w,
4919
+ h,
4920
+ data: null,
4921
+ type: null
4922
+ });
4923
+ return;
4924
+ }
4925
+ const lx = x - r.x;
4926
+ const ly = y - r.y;
4927
+ const data = new Uint8Array(w * h);
4928
+ for (let row = 0; row < h; row++) {
4929
+ data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
4930
+ }
4931
+ dest.push({
4932
+ x,
4933
+ y,
4934
+ w,
4935
+ h,
4936
+ data,
4937
+ type: 1 /* BINARY */
4938
+ });
4939
+ }
4940
+
4941
+ // src/Paint/_paint-types.ts
4942
+ var PaintMaskOutline = /* @__PURE__ */ ((PaintMaskOutline2) => {
4943
+ PaintMaskOutline2[PaintMaskOutline2["MASKED"] = 0] = "MASKED";
4944
+ PaintMaskOutline2[PaintMaskOutline2["CIRCLE"] = 1] = "CIRCLE";
4945
+ PaintMaskOutline2[PaintMaskOutline2["RECT"] = 2] = "RECT";
4946
+ return PaintMaskOutline2;
4947
+ })(PaintMaskOutline || {});
4948
+
4949
+ // src/Rect/trimRectBounds.ts
4950
+ function trimRectBounds(x, y, w, h, targetWidth, targetHeight, out) {
4951
+ const res = out ?? {
4952
+ x: 0,
4953
+ y: 0,
4954
+ w: 0,
4955
+ h: 0
4956
+ };
4957
+ const left = Math.max(0, x);
4958
+ const top = Math.max(0, y);
4959
+ const right = Math.min(targetWidth, x + w);
4960
+ const bottom = Math.min(targetHeight, y + h);
4961
+ res.x = left;
4962
+ res.y = top;
4963
+ res.w = Math.max(0, right - left);
4964
+ res.h = Math.max(0, bottom - top);
4965
+ return res;
4966
+ }
4967
+
4968
+ // src/Paint/eachTileInBounds.ts
4969
+ function eachTileInBounds(config, lookup, tilePool, bounds, callback) {
4970
+ const {
4971
+ tileShift,
4972
+ targetColumns,
4973
+ targetRows,
4974
+ tileSize
4975
+ } = config;
4976
+ const x1 = Math.max(0, bounds.x >> tileShift);
4977
+ const y1 = Math.max(0, bounds.y >> tileShift);
4978
+ const x2 = Math.min(targetColumns - 1, bounds.x + bounds.w - 1 >> tileShift);
4979
+ const y2 = Math.min(targetRows - 1, bounds.y + bounds.h - 1 >> tileShift);
4980
+ if (x1 > x2 || y1 > y2) return;
4981
+ for (let ty = y1; ty <= y2; ty++) {
4982
+ const rowOffset = ty * targetColumns;
4983
+ const tileTop = ty << tileShift;
4984
+ for (let tx = x1; tx <= x2; tx++) {
4985
+ const id = rowOffset + tx;
4986
+ const tile = lookup[id] ?? (lookup[id] = tilePool.getTile(id, tx, ty));
4987
+ const tileLeft = tx << tileShift;
4988
+ const startX = bounds.x > tileLeft ? bounds.x : tileLeft;
4989
+ const startY = bounds.y > tileTop ? bounds.y : tileTop;
4990
+ const maskEndX = bounds.x + bounds.w;
4991
+ const tileEndX = tileLeft + tileSize;
4992
+ const endX = maskEndX < tileEndX ? maskEndX : tileEndX;
4993
+ const maskEndY = bounds.y + bounds.h;
4994
+ const tileEndY = tileTop + tileSize;
4995
+ const endY = maskEndY < tileEndY ? maskEndY : tileEndY;
4996
+ callback(tile, startX, startY, endX - startX, endY - startY);
4997
+ }
4998
+ }
4999
+ }
5000
+
5001
+ // src/Paint/AlphaMaskPaintBuffer.ts
5002
+ var AlphaMaskPaintBuffer = class {
5003
+ constructor(config, tilePool) {
5004
+ this.config = config;
5005
+ this.tilePool = tilePool;
5006
+ this.lookup = [];
5007
+ }
5008
+ lookup;
5009
+ scratchBounds = {
5010
+ x: 0,
5011
+ y: 0,
5012
+ w: 0,
5013
+ h: 0
5014
+ };
5015
+ blendColorPixelDataAlphaMaskFn = blendColorPixelDataAlphaMask;
5016
+ forEachLinePointFn = forEachLinePoint;
5017
+ trimRectBoundsFn = trimRectBounds;
5018
+ eachTileInBoundsFn = eachTileInBounds;
5019
+ paintAlphaMask(brush, x0, y0, x1 = x0, y1 = y0) {
5020
+ const scratch = this.scratchBounds;
5021
+ const lookup = this.lookup;
5022
+ const tilePool = this.tilePool;
5023
+ const config = this.config;
5024
+ const tileShift = config.tileShift;
5025
+ const tileMask = config.tileMask;
5026
+ const target = config.target;
5027
+ const {
5028
+ w: bW,
5029
+ h: bH,
5030
+ data: bD,
5031
+ centerOffsetX,
5032
+ centerOffsetY
5033
+ } = brush;
5034
+ let changed = false;
5035
+ const eachTileInBoundsFn = this.eachTileInBoundsFn;
5036
+ const trimRectBoundsFn = this.trimRectBoundsFn;
5037
+ this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5038
+ const topLeftX = Math.floor(px + centerOffsetX);
5039
+ const topLeftY = Math.floor(py + centerOffsetY);
5040
+ trimRectBoundsFn(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5041
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5042
+ eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5043
+ const data = tile.data;
5044
+ let tileChanged = false;
5045
+ for (let i = 0; i < bH_t; i++) {
5046
+ const canvasY = bY + i;
5047
+ const bOff = (canvasY - topLeftY) * bW;
5048
+ const tOff = (canvasY & tileMask) << tileShift;
5049
+ const dS = tOff + (bX & tileMask);
5050
+ for (let j = 0; j < bW_t; j++) {
5051
+ const canvasX = bX + j;
5052
+ const brushA = bD[bOff + (canvasX - topLeftX)];
5053
+ if (brushA === 0) continue;
5054
+ const idx = dS + j;
5055
+ if (brushA > data[idx]) {
5056
+ data[idx] = brushA;
5057
+ tileChanged = true;
5058
+ }
5059
+ }
5060
+ }
5061
+ if (tileChanged) changed = true;
5062
+ });
5063
+ });
5064
+ return changed;
5065
+ }
5066
+ paintBinaryMask(brush, alpha, x0, y0, x1 = x0, y1 = y0) {
5067
+ if (alpha === 0) return false;
5068
+ const scratch = this.scratchBounds;
5069
+ const lookup = this.lookup;
5070
+ const tilePool = this.tilePool;
5071
+ const config = this.config;
5072
+ const tileShift = config.tileShift;
5073
+ const tileMask = config.tileMask;
5074
+ const target = config.target;
5075
+ const {
5076
+ w: bW,
5077
+ h: bH,
5078
+ data: bD,
5079
+ centerOffsetX,
5080
+ centerOffsetY
5081
+ } = brush;
5082
+ let changed = false;
5083
+ const trimRectBoundsFn = this.trimRectBoundsFn;
5084
+ const eachTileInBoundsFn = this.eachTileInBoundsFn;
5085
+ this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5086
+ const topLeftX = Math.floor(px + centerOffsetX);
5087
+ const topLeftY = Math.floor(py + centerOffsetY);
5088
+ trimRectBoundsFn(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5089
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5090
+ eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5091
+ const data = tile.data;
5092
+ let tileChanged = false;
5093
+ for (let i = 0; i < bH_t; i++) {
5094
+ const canvasY = bY + i;
5095
+ const bOff = (canvasY - topLeftY) * bW;
5096
+ const tOff = (canvasY & tileMask) << tileShift;
5097
+ const dS = tOff + (bX & tileMask);
5098
+ for (let j = 0; j < bW_t; j++) {
5099
+ const canvasX = bX + j;
5100
+ if (bD[bOff + (canvasX - topLeftX)]) {
5101
+ const idx = dS + j;
5102
+ if (data[idx] < alpha) {
5103
+ data[idx] = alpha;
5104
+ tileChanged = true;
5105
+ }
5106
+ }
5107
+ }
5108
+ }
5109
+ if (tileChanged) changed = true;
5110
+ });
5111
+ });
5112
+ return changed;
5113
+ }
5114
+ paintRect(alpha, brushWidth, brushHeight, x0, y0, x1 = x0, y1 = y0) {
5115
+ const scratch = this.scratchBounds;
5116
+ const lookup = this.lookup;
5117
+ const tilePool = this.tilePool;
5118
+ const config = this.config;
5119
+ const tileShift = config.tileShift;
5120
+ const tileMask = config.tileMask;
5121
+ const target = config.target;
5122
+ const centerOffsetX = -(brushWidth - 1 >> 1);
5123
+ const centerOffsetY = -(brushHeight - 1 >> 1);
5124
+ const trimRectBoundsFn = this.trimRectBoundsFn;
5125
+ const eachTileInBoundsFn = this.eachTileInBoundsFn;
5126
+ let changed = false;
5127
+ this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5128
+ const topLeftX = Math.floor(px + centerOffsetX);
5129
+ const topLeftY = Math.floor(py + centerOffsetY);
5130
+ trimRectBoundsFn(topLeftX, topLeftY, brushWidth, brushHeight, target.w, target.h, scratch);
5131
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5132
+ eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5133
+ const data = tile.data;
5134
+ let tileChanged = false;
5135
+ for (let i = 0; i < bH_t; i++) {
5136
+ const canvasY = bY + i;
5137
+ const tOff = (canvasY & tileMask) << tileShift;
5138
+ const dS = tOff + (bX & tileMask);
5139
+ for (let j = 0; j < bW_t; j++) {
5140
+ const idx = dS + j;
5141
+ if (alpha > data[idx]) {
5142
+ data[idx] = alpha;
5143
+ tileChanged = true;
5144
+ }
5145
+ }
5146
+ }
5147
+ if (tileChanged) {
5148
+ changed = true;
5149
+ }
5150
+ });
5151
+ });
5152
+ return changed;
5153
+ }
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
+ clear() {
5185
+ this.tilePool.releaseTiles(this.lookup);
5186
+ }
5187
+ };
5188
+
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
+ // src/Paint/BinaryMaskPaintBuffer.ts
5237
+ var BinaryMaskPaintBuffer = class {
5238
+ constructor(config, tilePool) {
5239
+ this.config = config;
5240
+ this.tilePool = tilePool;
5241
+ this.lookup = [];
5242
+ }
5243
+ lookup;
5244
+ scratchBounds = {
5245
+ x: 0,
5246
+ y: 0,
5247
+ w: 0,
5248
+ h: 0
5249
+ };
5250
+ blendColorPixelDataBinaryMaskFn = blendColorPixelDataBinaryMask;
5251
+ forEachLinePointFn = forEachLinePoint;
5252
+ trimRectBoundsFn = trimRectBounds;
5253
+ eachTileInBoundsFn = eachTileInBounds;
5254
+ paintBinaryMask(brush, x0, y0, x1 = x0, y1 = y0) {
5255
+ const scratch = this.scratchBounds;
5256
+ const lookup = this.lookup;
5257
+ const tilePool = this.tilePool;
5258
+ const config = this.config;
5259
+ const tileShift = config.tileShift;
5260
+ const tileMask = config.tileMask;
5261
+ const target = config.target;
5262
+ const {
5263
+ w: bW,
5264
+ h: bH,
5265
+ data: bD,
5266
+ centerOffsetX,
5267
+ centerOffsetY
5268
+ } = brush;
5269
+ let changed = false;
5270
+ const trimRectBoundsFn = this.trimRectBoundsFn;
5271
+ const eachTileInBoundsFn = this.eachTileInBoundsFn;
5272
+ this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5273
+ const topLeftX = Math.floor(px + centerOffsetX);
5274
+ const topLeftY = Math.floor(py + centerOffsetY);
5275
+ trimRectBoundsFn(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5276
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5277
+ eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5278
+ const data = tile.data;
5279
+ let tileChanged = false;
5280
+ for (let i = 0; i < bH_t; i++) {
5281
+ const canvasY = bY + i;
5282
+ const bOff = (canvasY - topLeftY) * bW;
5283
+ const tOff = (canvasY & tileMask) << tileShift;
5284
+ const dS = tOff + (bX & tileMask);
5285
+ for (let j = 0; j < bW_t; j++) {
5286
+ const canvasX = bX + j;
5287
+ if (bD[bOff + (canvasX - topLeftX)]) {
5288
+ const idx = dS + j;
5289
+ if (data[idx] === 0) {
5290
+ data[idx] = 1;
5291
+ tileChanged = true;
5292
+ }
5293
+ }
5294
+ }
5295
+ }
5296
+ if (tileChanged) changed = true;
5297
+ });
5298
+ });
5299
+ return changed;
5300
+ }
5301
+ paintRect(brushWidth, brushHeight, x0, y0, x1 = x0, y1 = y0) {
5302
+ const scratch = this.scratchBounds;
5303
+ const lookup = this.lookup;
5304
+ const tilePool = this.tilePool;
5305
+ const config = this.config;
5306
+ const tileShift = config.tileShift;
5307
+ const tileMask = config.tileMask;
5308
+ const target = config.target;
5309
+ const centerOffsetX = -(brushWidth - 1 >> 1);
5310
+ const centerOffsetY = -(brushHeight - 1 >> 1);
5311
+ const trimRectBoundsFn = this.trimRectBoundsFn;
5312
+ const eachTileInBoundsFn = this.eachTileInBoundsFn;
5313
+ let changed = false;
5314
+ this.forEachLinePointFn(x0, y0, x1, y1, (px, py) => {
5315
+ const topLeftX = Math.floor(px + centerOffsetX);
5316
+ const topLeftY = Math.floor(py + centerOffsetY);
5317
+ trimRectBoundsFn(topLeftX, topLeftY, brushWidth, brushHeight, target.w, target.h, scratch);
5318
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5319
+ eachTileInBoundsFn(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5320
+ const data = tile.data;
5321
+ let tileChanged = false;
5322
+ for (let i = 0; i < bH_t; i++) {
5323
+ const canvasY = bY + i;
5324
+ const tOff = (canvasY & tileMask) << tileShift;
5325
+ const dS = tOff + (bX & tileMask);
5326
+ for (let j = 0; j < bW_t; j++) {
5327
+ const idx = dS + j;
5328
+ if (data[idx] === 0) {
5329
+ data[idx] = 1;
5330
+ tileChanged = true;
5331
+ }
5332
+ }
5333
+ }
5334
+ if (tileChanged) {
5335
+ changed = true;
5336
+ }
5337
+ });
5338
+ });
5339
+ return changed;
5340
+ }
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
+ clear() {
5372
+ this.tilePool.releaseTiles(this.lookup);
5373
+ }
5374
+ };
5375
+
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
+ // src/Paint/ColorPaintBuffer.ts
5417
+ var ColorPaintBuffer = class {
5418
+ constructor(config, tilePool, blendPixelDataFn = blendPixelData) {
5419
+ this.config = config;
5420
+ this.tilePool = tilePool;
5421
+ this.blendPixelDataFn = blendPixelDataFn;
5422
+ this.lookup = [];
5423
+ }
5424
+ lookup;
5425
+ scratchBounds = {
5426
+ x: 0,
5427
+ y: 0,
5428
+ w: 0,
5429
+ h: 0
5430
+ };
5431
+ paintAlphaMask(color, brush, x0, y0, x1 = x0, y1 = y0) {
5432
+ const cA = color >>> 24;
5433
+ if (cA === 0) return false;
5434
+ const scratch = this.scratchBounds;
5435
+ const lookup = this.lookup;
5436
+ const tilePool = this.tilePool;
5437
+ const config = this.config;
5438
+ const tileShift = config.tileShift;
5439
+ const tileMask = config.tileMask;
5440
+ const target = config.target;
5441
+ const {
5442
+ w: bW,
5443
+ h: bH,
5444
+ data: bD,
5445
+ centerOffsetX,
5446
+ centerOffsetY
5447
+ } = brush;
5448
+ const cRGB = color & 16777215;
5449
+ let changed = false;
5450
+ forEachLinePoint(x0, y0, x1, y1, (px, py) => {
5451
+ const topLeftX = Math.floor(px + centerOffsetX);
5452
+ const topLeftY = Math.floor(py + centerOffsetY);
5453
+ trimRectBounds(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5454
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5455
+ eachTileInBounds(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5456
+ const d32 = tile.data;
5457
+ let tileChanged = false;
5458
+ for (let i = 0; i < bH_t; i++) {
5459
+ const canvasY = bY + i;
5460
+ const bOff = (canvasY - topLeftY) * bW;
5461
+ const tOff = (canvasY & tileMask) << tileShift;
5462
+ const dS = tOff + (bX & tileMask);
5463
+ for (let j = 0; j < bW_t; j++) {
5464
+ const canvasX = bX + j;
5465
+ const brushA = bD[bOff + (canvasX - topLeftX)];
5466
+ if (brushA === 0) continue;
5467
+ const t = cA * brushA + 128;
5468
+ const blendedA = t + (t >> 8) >> 8;
5469
+ const idx = dS + j;
5470
+ const cur = d32[idx];
5471
+ if (brushA > cur >>> 24) {
5472
+ const next = (cRGB | blendedA << 24) >>> 0;
5473
+ if (cur !== next) {
5474
+ d32[idx] = next;
5475
+ tileChanged = true;
5476
+ }
5477
+ }
5478
+ }
5479
+ }
5480
+ if (tileChanged) changed = true;
5481
+ });
5482
+ });
5483
+ return changed;
5484
+ }
5485
+ paintBinaryMask(color, brush, x0, y0, x1 = x0, y1 = y0) {
5486
+ const alphaIsZero = color >>> 24 === 0;
5487
+ if (alphaIsZero) return false;
5488
+ const scratch = this.scratchBounds;
5489
+ const lookup = this.lookup;
5490
+ const tilePool = this.tilePool;
5491
+ const config = this.config;
5492
+ const tileShift = config.tileShift;
5493
+ const tileMask = config.tileMask;
5494
+ const target = config.target;
5495
+ const {
5496
+ w: bW,
5497
+ h: bH,
5498
+ data: bD,
5499
+ centerOffsetX,
5500
+ centerOffsetY
5501
+ } = brush;
5502
+ let changed = false;
5503
+ forEachLinePoint(x0, y0, x1, y1, (px, py) => {
5504
+ const topLeftX = Math.floor(px + centerOffsetX);
5505
+ const topLeftY = Math.floor(py + centerOffsetY);
5506
+ trimRectBounds(topLeftX, topLeftY, bW, bH, target.w, target.h, scratch);
5507
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5508
+ eachTileInBounds(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5509
+ const d32 = tile.data;
5510
+ let tileChanged = false;
5511
+ for (let i = 0; i < bH_t; i++) {
5512
+ const canvasY = bY + i;
5513
+ const bOff = (canvasY - topLeftY) * bW;
5514
+ const tOff = (canvasY & tileMask) << tileShift;
5515
+ const dS = tOff + (bX & tileMask);
5516
+ for (let j = 0; j < bW_t; j++) {
5517
+ const canvasX = bX + j;
5518
+ if (bD[bOff + (canvasX - topLeftX)]) {
5519
+ const idx = dS + j;
5520
+ if (d32[idx] !== color) {
5521
+ d32[idx] = color;
5522
+ tileChanged = true;
5523
+ }
5524
+ }
5525
+ }
5526
+ }
5527
+ if (tileChanged) changed = true;
5528
+ });
5529
+ });
5530
+ return changed;
5531
+ }
5532
+ paintRect(color, brushWidth, brushHeight, x0, y0, x1 = x0, y1 = y0) {
5533
+ const alphaIsZero = color >>> 24 === 0;
5534
+ if (alphaIsZero) return false;
5535
+ const scratch = this.scratchBounds;
5536
+ const lookup = this.lookup;
5537
+ const tilePool = this.tilePool;
5538
+ const config = this.config;
5539
+ const tileShift = config.tileShift;
5540
+ const tileMask = config.tileMask;
5541
+ const target = config.target;
5542
+ const centerOffsetX = -(brushWidth - 1 >> 1);
5543
+ const centerOffsetY = -(brushHeight - 1 >> 1);
5544
+ let changed = false;
5545
+ forEachLinePoint(x0, y0, x1, y1, (px, py) => {
5546
+ const topLeftX = Math.floor(px + centerOffsetX);
5547
+ const topLeftY = Math.floor(py + centerOffsetY);
5548
+ trimRectBounds(topLeftX, topLeftY, brushWidth, brushHeight, target.w, target.h, scratch);
5549
+ if (scratch.w <= 0 || scratch.h <= 0) return;
5550
+ eachTileInBounds(config, lookup, tilePool, scratch, (tile, bX, bY, bW_t, bH_t) => {
5551
+ const d32 = tile.data;
5552
+ let tileChanged = false;
5553
+ for (let i = 0; i < bH_t; i++) {
5554
+ const canvasY = bY + i;
5555
+ const tOff = (canvasY & tileMask) << tileShift;
5556
+ const dS = tOff + (bX & tileMask);
5557
+ for (let j = 0; j < bW_t; j++) {
5558
+ const idx = dS + j;
5559
+ if (d32[idx] !== color) {
5560
+ d32[idx] = color;
5561
+ tileChanged = true;
5562
+ }
5563
+ }
5564
+ }
5565
+ if (tileChanged) {
4575
5566
  changed = true;
4576
- break;
4577
5567
  }
4578
- }
4579
- if (!merged) next.push(r);
4580
- }
4581
- rects.splice(0, rects.length, ...next);
5568
+ });
5569
+ });
5570
+ return changed;
4582
5571
  }
4583
- return rects;
4584
- }
4585
-
4586
- // src/MaskRect/subtractBinaryMaskRects.ts
4587
- function subtractBinaryMaskRects(current, subtracting) {
4588
- let result = [...current];
4589
- for (const sub of subtracting) {
4590
- const next = [];
4591
- for (const r of result) {
4592
- const ix = Math.max(r.x, sub.x);
4593
- const iy = Math.max(r.y, sub.y);
4594
- const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
4595
- const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
4596
- if (ix >= ix2 || iy >= iy2) {
4597
- next.push(r);
4598
- continue;
5572
+ opts = {
5573
+ alpha: 255,
5574
+ blendFn: sourceOverPerfect,
5575
+ x: 0,
5576
+ y: 0,
5577
+ w: 0,
5578
+ h: 0
5579
+ };
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;
5587
+ for (let i = 0; i < lookup.length; i++) {
5588
+ const tile = lookup[i];
5589
+ if (tile) {
5590
+ const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
5591
+ const dx = tile.tx << tileShift;
5592
+ 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));
4599
5598
  }
4600
- if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
4601
- if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
4602
- if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
4603
- if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
4604
5599
  }
4605
- result = next;
4606
- }
4607
- return result;
4608
- }
4609
- function pushPiece(dest, r, x, y, w, h) {
4610
- if (r.data === null || r.data === void 0) {
4611
- dest.push({
4612
- x,
4613
- y,
4614
- w,
4615
- h,
4616
- data: null,
4617
- type: null
4618
- });
4619
- return;
5600
+ this.clear();
4620
5601
  }
4621
- const lx = x - r.x;
4622
- const ly = y - r.y;
4623
- const data = new Uint8Array(w * h);
4624
- for (let row = 0; row < h; row++) {
4625
- data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
5602
+ clear() {
5603
+ this.tilePool.releaseTiles(this.lookup);
4626
5604
  }
4627
- dest.push({
4628
- x,
4629
- y,
4630
- w,
4631
- h,
4632
- data,
4633
- type: 1 /* BINARY */
4634
- });
4635
- }
5605
+ };
4636
5606
 
4637
- // src/Paint/PaintBufferCanvasRenderer.ts
4638
- function makePaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
5607
+ // src/Paint/ColorPaintBufferCanvasRenderer.ts
5608
+ function makeColorPaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
4639
5609
  const config = paintBuffer.config;
4640
5610
  const tileSize = config.tileSize;
4641
5611
  const tileShift = config.tileShift;
@@ -4661,7 +5631,7 @@ function makePaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = Offsc
4661
5631
  };
4662
5632
  }
4663
5633
 
4664
- // src/Paint/makeCirclePaintAlphaMask.ts
5634
+ // src/Paint/makeCirclePaintMask.ts
4665
5635
  function makeCirclePaintAlphaMask(size, fallOff = (d) => d) {
4666
5636
  const area = size * size;
4667
5637
  const data = new Uint8Array(area);
@@ -4687,6 +5657,7 @@ function makeCirclePaintAlphaMask(size, fallOff = (d) => d) {
4687
5657
  }
4688
5658
  return {
4689
5659
  type: 0 /* ALPHA */,
5660
+ outlineType: 1 /* CIRCLE */,
4690
5661
  data,
4691
5662
  w: size,
4692
5663
  h: size,
@@ -4694,28 +5665,28 @@ function makeCirclePaintAlphaMask(size, fallOff = (d) => d) {
4694
5665
  centerOffsetY: centerOffset
4695
5666
  };
4696
5667
  }
4697
-
4698
- // src/Paint/makeCirclePaintBinaryMask.ts
4699
5668
  function makeCirclePaintBinaryMask(size) {
4700
5669
  const area = size * size;
4701
5670
  const data = new Uint8Array(area);
4702
5671
  const radius = size / 2;
4703
- const centerOffset = -Math.ceil(radius - 0.5);
5672
+ const r2 = radius * radius;
4704
5673
  for (let y = 0; y < size; y++) {
4705
5674
  for (let x = 0; x < size; x++) {
4706
5675
  const dx = x - radius + 0.5;
4707
5676
  const dy = y - radius + 0.5;
4708
5677
  const distSqr = dx * dx + dy * dy;
4709
- if (distSqr <= radius * radius) {
5678
+ if (distSqr <= r2) {
4710
5679
  data[y * size + x] = 1;
4711
5680
  }
4712
5681
  }
4713
5682
  }
5683
+ const centerOffset = -Math.ceil(radius - 0.5);
4714
5684
  return {
4715
5685
  type: 1 /* BINARY */,
4716
- data,
5686
+ outlineType: 1 /* CIRCLE */,
4717
5687
  w: size,
4718
5688
  h: size,
5689
+ data,
4719
5690
  centerOffsetX: centerOffset,
4720
5691
  centerOffsetY: centerOffset
4721
5692
  };
@@ -4725,6 +5696,7 @@ function makeCirclePaintBinaryMask(size) {
4725
5696
  function makePaintBinaryMask(mask) {
4726
5697
  return {
4727
5698
  type: 1 /* BINARY */,
5699
+ outlineType: 0 /* MASKED */,
4728
5700
  data: mask.data,
4729
5701
  w: mask.w,
4730
5702
  h: mask.h,
@@ -4735,6 +5707,7 @@ function makePaintBinaryMask(mask) {
4735
5707
  function makePaintAlphaMask(mask) {
4736
5708
  return {
4737
5709
  type: 0 /* ALPHA */,
5710
+ outlineType: 0 /* MASKED */,
4738
5711
  data: mask.data,
4739
5712
  w: mask.w,
4740
5713
  h: mask.h,
@@ -4768,6 +5741,7 @@ function makeRectFalloffPaintAlphaMask(width, height, fallOff = (d) => d) {
4768
5741
  }
4769
5742
  return {
4770
5743
  type: 0 /* ALPHA */,
5744
+ outlineType: 2 /* RECT */,
4771
5745
  data,
4772
5746
  w: width,
4773
5747
  h: height,
@@ -4776,26 +5750,110 @@ function makeRectFalloffPaintAlphaMask(width, height, fallOff = (d) => d) {
4776
5750
  };
4777
5751
  }
4778
5752
 
4779
- // src/PixelData/PixelData.ts
4780
- var PixelData = class {
4781
- data32;
4782
- imageData;
4783
- width;
4784
- height;
4785
- constructor(imageData) {
4786
- this.data32 = imageDataToUInt32Array(imageData);
4787
- this.imageData = imageData;
4788
- this.width = imageData.width;
4789
- this.height = imageData.height;
4790
- }
4791
- set(imageData) {
4792
- ;
4793
- this.imageData = imageData;
4794
- this.data32 = imageDataToUInt32Array(imageData);
4795
- this.width = imageData.width;
4796
- this.height = imageData.height;
5753
+ // src/PixelData/ReusablePixelData.ts
5754
+ function makeReusablePixelData() {
5755
+ const pixelData = {
5756
+ w: 0,
5757
+ h: 0,
5758
+ data: null,
5759
+ imageData: null
5760
+ };
5761
+ return function getReusablePixelData(width, height) {
5762
+ if (pixelData.w !== width || pixelData.h !== height) {
5763
+ setPixelData(pixelData, new ImageData(width, height));
5764
+ } else {
5765
+ pixelData.data.fill(0);
5766
+ }
5767
+ return pixelData;
5768
+ };
5769
+ }
5770
+
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;
5777
+ const getPixelData = makeReusablePixelData();
5778
+ let _color = packColor(0, 255, 255, 255);
5779
+ let _scale = 1;
5780
+ let currentMask = {
5781
+ type: 1 /* BINARY */,
5782
+ outlineType: 2 /* RECT */,
5783
+ w: 1,
5784
+ h: 1,
5785
+ centerOffsetX: -(10 - 1 >> 1),
5786
+ centerOffsetY: -(10 - 1 >> 1)
5787
+ };
5788
+ let outline;
5789
+ function update(paintMask, scale, color, alphaThreshold = 127) {
5790
+ currentMask = paintMask ?? currentMask;
5791
+ _scale = scale ?? _scale;
5792
+ _color = color ?? _color;
5793
+ canvas.width = currentMask.w * _scale + 2 * _scale;
5794
+ canvas.height = currentMask.h * _scale + 2 * _scale;
5795
+ if (currentMask.type === 1 /* BINARY */) {
5796
+ if (currentMask.outlineType === 1 /* CIRCLE */) {
5797
+ outline = makeCircleBinaryMaskOutline(currentMask.w, _scale);
5798
+ } else if (currentMask.outlineType === 2 /* RECT */) {
5799
+ outline = makeRectBinaryMaskOutline(currentMask.w, currentMask.h, _scale);
5800
+ } else if (currentMask.outlineType === 0 /* MASKED */) {
5801
+ outline = makeBinaryMaskOutline(currentMask, _scale);
5802
+ }
5803
+ } else if (currentMask.type === 0 /* ALPHA */) {
5804
+ const mask = makeBinaryMaskFromAlphaMask(currentMask, alphaThreshold);
5805
+ outline = makeBinaryMaskOutline(mask, _scale);
5806
+ }
5807
+ const pixelData = getPixelData(outline.w, outline.h);
5808
+ fillPixelDataBinaryMask(pixelData, _color, outline);
5809
+ ctx.putImageData(pixelData.imageData, 0, 0);
4797
5810
  }
4798
- };
5811
+ const boundsScratch = {
5812
+ x: 0,
5813
+ y: 0,
5814
+ w: 0,
5815
+ h: 0
5816
+ };
5817
+ function getBounds(centerX, centerY) {
5818
+ boundsScratch.x = centerX + currentMask.centerOffsetX;
5819
+ boundsScratch.y = centerY + currentMask.centerOffsetY;
5820
+ boundsScratch.w = currentMask.w;
5821
+ boundsScratch.h = currentMask.h;
5822
+ return boundsScratch;
5823
+ }
5824
+ const boundsScaledScratch = {
5825
+ x: 0,
5826
+ y: 0,
5827
+ w: 0,
5828
+ h: 0
5829
+ };
5830
+ function getOutlineBoundsScaled(centerX, centerY) {
5831
+ boundsScaledScratch.x = centerX * _scale + currentMask.centerOffsetX * _scale - 1;
5832
+ boundsScaledScratch.y = centerY * _scale + currentMask.centerOffsetY * _scale - 1;
5833
+ boundsScaledScratch.w = currentMask.w * _scale;
5834
+ boundsScaledScratch.h = currentMask.h * _scale;
5835
+ return boundsScaledScratch;
5836
+ }
5837
+ function draw(drawCtx, centerX, centerY) {
5838
+ const dx = centerX * _scale + currentMask.centerOffsetX * _scale - 1;
5839
+ const dy = centerY * _scale + currentMask.centerOffsetY * _scale - 1;
5840
+ drawCtx.drawImage(canvas, Math.floor(dx), Math.floor(dy));
5841
+ }
5842
+ function getSettings() {
5843
+ return {
5844
+ color: _color,
5845
+ scale: _scale,
5846
+ currentMask
5847
+ };
5848
+ }
5849
+ return {
5850
+ update,
5851
+ getBounds,
5852
+ getBoundsScaled: getOutlineBoundsScaled,
5853
+ draw,
5854
+ getSettings
5855
+ };
5856
+ }
4799
5857
 
4800
5858
  // src/PixelData/applyMaskToPixelData.ts
4801
5859
  function applyMaskToPixelData(dst, mask, opts) {
@@ -4913,8 +5971,8 @@ function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
4913
5971
  if (typeof _x === "object") {
4914
5972
  x = _x.x ?? 0;
4915
5973
  y = _x.y ?? 0;
4916
- w = _x.w ?? dst.width;
4917
- h = _x.h ?? dst.height;
5974
+ w = _x.w ?? dst.w;
5975
+ h = _x.h ?? dst.h;
4918
5976
  } else if (typeof _x === "number") {
4919
5977
  x = _x;
4920
5978
  y = _y;
@@ -4923,10 +5981,10 @@ function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
4923
5981
  } else {
4924
5982
  x = 0;
4925
5983
  y = 0;
4926
- w = dst.width;
4927
- h = dst.height;
5984
+ w = dst.w;
5985
+ h = dst.h;
4928
5986
  }
4929
- const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT4);
5987
+ const clip = resolveRectClipping(x, y, w, h, dst.w, dst.h, SCRATCH_RECT4);
4930
5988
  if (!clip.inBounds) return;
4931
5989
  const {
4932
5990
  x: finalX,
@@ -4934,9 +5992,9 @@ function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
4934
5992
  w: actualW,
4935
5993
  h: actualH
4936
5994
  } = clip;
4937
- const dst32 = dst.data32;
4938
- const dw = dst.width;
4939
- if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
5995
+ const dst32 = dst.data;
5996
+ const dw = dst.w;
5997
+ if (actualW === dw && actualH === dst.h && finalX === 0 && finalY === 0) {
4940
5998
  dst32.fill(color);
4941
5999
  return;
4942
6000
  }
@@ -4952,6 +6010,13 @@ function clearPixelDataFast(dst, rect) {
4952
6010
  fillPixelDataFast(dst, 0, rect);
4953
6011
  }
4954
6012
 
6013
+ // src/PixelData/copyPixelData.ts
6014
+ function copyPixelData(target) {
6015
+ const data = target.imageData.data;
6016
+ const buffer = new Uint8ClampedArray(data);
6017
+ return makePixelData(new ImageData(buffer, target.w, target.h));
6018
+ }
6019
+
4955
6020
  // src/PixelData/extractPixelDataBuffer.ts
4956
6021
  var SCRATCH_BLIT4 = makeClippedBlit();
4957
6022
  function extractPixelDataBuffer(source, _x, _y, _w, _h) {
@@ -4966,9 +6031,9 @@ function extractPixelDataBuffer(source, _x, _y, _w, _h) {
4966
6031
  w: _w,
4967
6032
  h: _h
4968
6033
  };
4969
- const srcW = source.width;
4970
- const srcH = source.height;
4971
- const srcData = source.data32;
6034
+ const srcW = source.w;
6035
+ const srcH = source.h;
6036
+ const srcData = source.data;
4972
6037
  if (w <= 0 || h <= 0) {
4973
6038
  return new Uint32Array(0);
4974
6039
  }
@@ -5005,24 +6070,24 @@ function extractPixelData(source, _x, _y, _w, _h) {
5005
6070
  w: _w,
5006
6071
  h: _h
5007
6072
  };
5008
- const result = new PixelData(new ImageData(w, h));
6073
+ const result = makePixelData(new ImageData(w, h));
5009
6074
  const buffer = extractPixelDataBuffer(source, x, y, w, h);
5010
- result.data32.set(buffer);
6075
+ result.data.set(buffer);
5011
6076
  return result;
5012
6077
  }
5013
6078
 
5014
6079
  // src/PixelData/pixelDataToAlphaMask.ts
5015
6080
  function pixelDataToAlphaMask(pixelData) {
5016
6081
  const {
5017
- data32,
5018
- width,
5019
- height
6082
+ data,
6083
+ w,
6084
+ h
5020
6085
  } = pixelData;
5021
- const len = data32.length;
5022
- const mask = makeAlphaMask(width, height);
6086
+ const len = data.length;
6087
+ const mask = makeAlphaMask(w, h);
5023
6088
  const maskData = mask.data;
5024
6089
  for (let i = 0; i < len; i++) {
5025
- const val = data32[i];
6090
+ const val = data[i];
5026
6091
  maskData[i] = val >>> 24 & 255;
5027
6092
  }
5028
6093
  return mask;
@@ -5030,9 +6095,9 @@ function pixelDataToAlphaMask(pixelData) {
5030
6095
 
5031
6096
  // src/PixelData/reflectPixelData.ts
5032
6097
  function reflectPixelDataHorizontal(pixelData) {
5033
- const width = pixelData.width;
5034
- const height = pixelData.height;
5035
- const data = pixelData.data32;
6098
+ const width = pixelData.w;
6099
+ const height = pixelData.h;
6100
+ const data = pixelData.data;
5036
6101
  const halfWidth = Math.floor(width / 2);
5037
6102
  for (let y = 0; y < height; y++) {
5038
6103
  const rowOffset = y * width;
@@ -5046,9 +6111,9 @@ function reflectPixelDataHorizontal(pixelData) {
5046
6111
  }
5047
6112
  }
5048
6113
  function reflectPixelDataVertical(pixelData) {
5049
- const width = pixelData.width;
5050
- const height = pixelData.height;
5051
- const data = pixelData.data32;
6114
+ const width = pixelData.w;
6115
+ const height = pixelData.h;
6116
+ const data = pixelData.data;
5052
6117
  const halfHeight = Math.floor(height / 2);
5053
6118
  for (let y = 0; y < halfHeight; y++) {
5054
6119
  const topRowOffset = y * width;
@@ -5065,19 +6130,21 @@ function reflectPixelDataVertical(pixelData) {
5065
6130
 
5066
6131
  // src/PixelData/resamplePixelData.ts
5067
6132
  function resamplePixelData(pixelData, factor) {
5068
- const {
5069
- data,
5070
- width,
5071
- height
5072
- } = resample32(pixelData.data32, pixelData.width, pixelData.height, factor);
5073
- return new PixelData(new ImageData(new Uint8ClampedArray(data.buffer), width, height));
6133
+ const output = {};
6134
+ const resampled = resampleUint32Array(pixelData.data, pixelData.w, pixelData.h, factor, output);
6135
+ resampled.imageData = uInt32ArrayToImageData(resampled.data, resampled.w, resampled.h);
6136
+ return resampled;
6137
+ }
6138
+ function resamplePixelDataInPlace(pixelData, factor) {
6139
+ const resampled = resampleUint32Array(pixelData.data, pixelData.w, pixelData.h, factor, pixelData);
6140
+ resampled.imageData = uInt32ArrayToImageData(resampled.data, resampled.w, resampled.h);
5074
6141
  }
5075
6142
 
5076
6143
  // src/PixelData/rotatePixelData.ts
5077
6144
  function rotatePixelData(pixelData) {
5078
- const width = pixelData.width;
5079
- const height = pixelData.height;
5080
- const data = pixelData.data32;
6145
+ const width = pixelData.w;
6146
+ const height = pixelData.h;
6147
+ const data = pixelData.data;
5081
6148
  if (width === height) {
5082
6149
  rotateSquareInPlace(pixelData);
5083
6150
  return;
@@ -5095,11 +6162,11 @@ function rotatePixelData(pixelData) {
5095
6162
  }
5096
6163
  }
5097
6164
  const newImageData = new ImageData(new Uint8ClampedArray(newData32.buffer), newWidth, newHeight);
5098
- pixelData.set(newImageData);
6165
+ setPixelData(pixelData, newImageData);
5099
6166
  }
5100
6167
  function rotateSquareInPlace(pixelData) {
5101
- const n = pixelData.width;
5102
- const data = pixelData.data32;
6168
+ const n = pixelData.w;
6169
+ const data = pixelData.data;
5103
6170
  for (let i = 0; i < n / 2; i++) {
5104
6171
  for (let j = i; j < n - i - 1; j++) {
5105
6172
  const top = i * n + j;
@@ -5115,6 +6182,16 @@ function rotateSquareInPlace(pixelData) {
5115
6182
  }
5116
6183
  }
5117
6184
 
6185
+ // src/PixelData/uInt32ArrayToPixelData.ts
6186
+ function uInt32ArrayToPixelData(data, width, height) {
6187
+ const buffer = data.buffer;
6188
+ const byteOffset = data.byteOffset;
6189
+ const byteLength = data.byteLength;
6190
+ const clampedArray = new Uint8ClampedArray(buffer, byteOffset, byteLength);
6191
+ const imageData = new ImageData(clampedArray, width, height);
6192
+ return makePixelData(imageData);
6193
+ }
6194
+
5118
6195
  // src/PixelData/writePixelDataBuffer.ts
5119
6196
  var SCRATCH_BLIT5 = makeClippedBlit();
5120
6197
  function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
@@ -5129,9 +6206,9 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
5129
6206
  w: _w,
5130
6207
  h: _h
5131
6208
  };
5132
- const dstW = target.width;
5133
- const dstH = target.height;
5134
- const dstData = target.data32;
6209
+ const dstW = target.w;
6210
+ const dstH = target.h;
6211
+ const dstData = target.data;
5135
6212
  const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT5);
5136
6213
  if (!clip.inBounds) return;
5137
6214
  const {
@@ -5158,25 +6235,53 @@ function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn
5158
6235
  if (tile) {
5159
6236
  const dx = tile.tx << tileShift;
5160
6237
  const dy = tile.ty << tileShift;
5161
- writePixelDataBufferFn(target, tile.data32, dx, dy, tile.width, tile.height);
6238
+ writePixelDataBufferFn(target, tile.data, dx, dy, tile.w, tile.h);
5162
6239
  }
5163
6240
  }
5164
6241
  }
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
+ };
5165
6268
  export {
6269
+ AlphaMaskPaintBuffer,
5166
6270
  BASE_FAST_BLEND_MODE_FUNCTIONS,
5167
6271
  BASE_PERFECT_BLEND_MODE_FUNCTIONS,
5168
6272
  BaseBlendMode,
6273
+ BinaryMaskPaintBuffer,
5169
6274
  CANVAS_COMPOSITE_MAP,
6275
+ ColorPaintBuffer,
6276
+ errors_exports as ERRORS,
5170
6277
  HistoryManager,
5171
- IndexedImage,
5172
6278
  MaskType,
5173
- PaintBuffer,
6279
+ PaintMaskOutline,
5174
6280
  PixelAccumulator,
5175
- PixelData,
5176
6281
  PixelEngineConfig,
5177
- PixelTile,
5178
- PixelTilePool,
5179
6282
  PixelWriter,
6283
+ TilePool,
6284
+ TileType,
5180
6285
  UnsupportedFormatError,
5181
6286
  applyAlphaMaskToPixelData,
5182
6287
  applyBinaryMaskToAlphaMask,
@@ -5209,6 +6314,7 @@ export {
5209
6314
  copyImageData,
5210
6315
  copyImageDataLike,
5211
6316
  copyMask,
6317
+ copyPixelData,
5212
6318
  darkenFast,
5213
6319
  darkenPerfect,
5214
6320
  darkerFast,
@@ -5216,10 +6322,19 @@ export {
5216
6322
  deserializeImageData,
5217
6323
  deserializeNullableImageData,
5218
6324
  deserializeRawImageData,
6325
+ destinationAtopFast,
6326
+ destinationAtopPerfect,
6327
+ destinationInFast,
6328
+ destinationInPerfect,
6329
+ destinationOutFast,
6330
+ destinationOutPerfect,
6331
+ destinationOverFast,
6332
+ destinationOverPerfect,
5219
6333
  differenceFast,
5220
6334
  differencePerfect,
5221
6335
  divideFast,
5222
6336
  dividePerfect,
6337
+ eachTileInBounds,
5223
6338
  exclusionFast,
5224
6339
  exclusionPerfect,
5225
6340
  extractImageDataBuffer,
@@ -5235,6 +6350,7 @@ export {
5235
6350
  floodFillSelection,
5236
6351
  forEachLinePoint,
5237
6352
  getImageDataFromClipboard,
6353
+ getIndexedImageColor,
5238
6354
  getIndexedImageColorCounts,
5239
6355
  getRectsBounds,
5240
6356
  getSupportedPixelFormats,
@@ -5245,7 +6361,7 @@ export {
5245
6361
  imageDataToAlphaMaskBuffer,
5246
6362
  imageDataToDataUrl,
5247
6363
  imageDataToImgBlob,
5248
- imageDataToUInt32Array,
6364
+ imageDataToUint32Array,
5249
6365
  imgBlobToImageData,
5250
6366
  indexedImageToAverageColor,
5251
6367
  indexedImageToImageData,
@@ -5266,26 +6382,42 @@ export {
5266
6382
  linearLightFast,
5267
6383
  linearLightPerfect,
5268
6384
  makeAlphaMask,
6385
+ makeAlphaMaskPaintBufferCanvasRenderer,
6386
+ makeAlphaMaskTile,
5269
6387
  makeBinaryMask,
6388
+ makeBinaryMaskFromAlphaMask,
6389
+ makeBinaryMaskOutline,
6390
+ makeBinaryMaskPaintBufferCanvasRenderer,
6391
+ makeBinaryMaskTile,
5270
6392
  makeBlendModeRegistry,
5271
6393
  makeCanvasFrameRenderer,
6394
+ makeCanvasPixelDataRenderer,
6395
+ makeCircleBinaryMaskOutline,
5272
6396
  makeCirclePaintAlphaMask,
5273
6397
  makeCirclePaintBinaryMask,
5274
6398
  makeClippedBlit,
5275
6399
  makeClippedRect,
6400
+ makeColorPaintBufferCanvasRenderer,
5276
6401
  makeFastBlendModeRegistry,
5277
6402
  makeFullPixelMutator,
5278
6403
  makeHistoryAction,
5279
6404
  makeImageDataLike,
6405
+ makeIndexedImage,
6406
+ makeIndexedImageFromImageData,
6407
+ makeIndexedImageFromImageDataRaw,
5280
6408
  makePaintAlphaMask,
5281
6409
  makePaintBinaryMask,
5282
- makePaintBufferCanvasRenderer,
6410
+ makePaintCursorRenderer,
5283
6411
  makePerfectBlendModeRegistry,
5284
6412
  makePixelCanvas,
6413
+ makePixelData,
6414
+ makePixelTile,
6415
+ makeRectBinaryMaskOutline,
5285
6416
  makeRectFalloffPaintAlphaMask,
5286
6417
  makeReusableCanvas,
5287
6418
  makeReusableImageData,
5288
6419
  makeReusableOffscreenCanvas,
6420
+ makeReusablePixelData,
5289
6421
  merge2BinaryMaskRects,
5290
6422
  mergeAlphaMasks,
5291
6423
  mergeBinaryMaskRects,
@@ -5301,8 +6433,8 @@ export {
5301
6433
  mutatorBlendColorPaintAlphaMask,
5302
6434
  mutatorBlendColorPaintBinaryMask,
5303
6435
  mutatorBlendColorPaintMask,
6436
+ mutatorBlendColorPaintRect,
5304
6437
  mutatorBlendMask,
5305
- mutatorBlendPaintRect,
5306
6438
  mutatorBlendPixel,
5307
6439
  mutatorBlendPixelData,
5308
6440
  mutatorClear,
@@ -5322,10 +6454,11 @@ export {
5322
6454
  pixelDataToAlphaMask,
5323
6455
  reflectPixelDataHorizontal,
5324
6456
  reflectPixelDataVertical,
5325
- resample32,
5326
6457
  resampleImageData,
5327
6458
  resampleIndexedImage,
5328
6459
  resamplePixelData,
6460
+ resamplePixelDataInPlace,
6461
+ resampleUint32Array,
5329
6462
  resizeImageData,
5330
6463
  resolveBlitClipping,
5331
6464
  resolveRectClipping,
@@ -5335,8 +6468,15 @@ export {
5335
6468
  serializeImageData,
5336
6469
  serializeNullableImageData,
5337
6470
  setMaskData,
6471
+ setPixelData,
5338
6472
  softLightFast,
5339
6473
  softLightPerfect,
6474
+ sourceAtopFast,
6475
+ sourceAtopPerfect,
6476
+ sourceInFast,
6477
+ sourceInPerfect,
6478
+ sourceOutFast,
6479
+ sourceOutPerfect,
5340
6480
  sourceOverFast,
5341
6481
  sourceOverPerfect,
5342
6482
  subtractBinaryMaskRects,
@@ -5347,6 +6487,7 @@ export {
5347
6487
  trimRectBounds,
5348
6488
  uInt32ArrayToImageData,
5349
6489
  uInt32ArrayToImageDataLike,
6490
+ uInt32ArrayToPixelData,
5350
6491
  unpackAlpha,
5351
6492
  unpackBlue,
5352
6493
  unpackColor,
@@ -5360,6 +6501,8 @@ export {
5360
6501
  writeImageDataToClipboard,
5361
6502
  writeImgBlobToClipboard,
5362
6503
  writePaintBufferToPixelData,
5363
- writePixelDataBuffer
6504
+ writePixelDataBuffer,
6505
+ xorFast,
6506
+ xorPerfect
5364
6507
  };
5365
6508
  //# sourceMappingURL=index.prod.js.map