pixel-data-js 0.23.1 → 0.24.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.
- package/dist/index.dev.cjs +1024 -596
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1010 -592
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1024 -596
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +280 -165
- package/dist/index.prod.js +1010 -592
- package/dist/index.prod.js.map +1 -1
- package/package.json +3 -2
- package/src/Canvas/CanvasFrameRenderer.ts +57 -0
- package/src/Canvas/ReusableCanvas.ts +60 -11
- package/src/History/HistoryAction.ts +38 -0
- package/src/History/HistoryManager.ts +4 -8
- package/src/History/PixelAccumulator.ts +95 -80
- package/src/History/PixelEngineConfig.ts +18 -6
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +6 -6
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +6 -6
- package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +6 -5
- package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +22 -22
- package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +6 -5
- package/src/History/PixelMutator/mutatorApplyRectBrush.ts +19 -19
- package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +6 -4
- package/src/History/PixelMutator/mutatorApplyRectPencil.ts +20 -20
- package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +6 -4
- package/src/History/PixelMutator/mutatorBlendColor.ts +8 -5
- package/src/History/PixelMutator/mutatorBlendColorCircleMask.ts +71 -0
- package/src/History/PixelMutator/mutatorBlendPixel.ts +22 -26
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +5 -3
- package/src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts +5 -3
- package/src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts +5 -3
- package/src/History/PixelMutator/mutatorClear.ts +6 -5
- package/src/History/PixelMutator/mutatorFill.ts +34 -9
- package/src/History/PixelMutator/mutatorFillBinaryMask.ts +4 -2
- package/src/History/PixelMutator/mutatorInvert.ts +8 -4
- package/src/History/PixelMutator.ts +4 -3
- package/src/History/PixelPatchTiles.ts +3 -15
- package/src/History/PixelWriter.ts +29 -33
- package/src/ImageData/ReusableImageData.ts +3 -5
- package/src/Mask/{CircleBrushAlphaMask.ts → CircleAlphaMask.ts} +2 -2
- package/src/Mask/{CircleBrushBinaryMask.ts → CircleBinaryMask.ts} +2 -2
- package/src/PixelData/PixelData.ts +1 -27
- package/src/PixelData/applyAlphaMaskToPixelData.ts +19 -9
- package/src/PixelData/applyBinaryMaskToPixelData.ts +24 -17
- package/src/PixelData/applyRectBrushToPixelData.ts +18 -5
- package/src/PixelData/blendColorPixelData.ts +31 -7
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +16 -6
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +16 -7
- package/src/PixelData/{applyCircleBrushToPixelData.ts → blendColorPixelDataCircleMask.ts} +11 -10
- package/src/PixelData/blendPixel.ts +47 -0
- package/src/PixelData/blendPixelData.ts +14 -4
- package/src/PixelData/blendPixelDataAlphaMask.ts +12 -4
- package/src/PixelData/blendPixelDataBinaryMask.ts +13 -4
- package/src/PixelData/blendPixelDataPaintBuffer.ts +37 -0
- package/src/PixelData/clearPixelData.ts +2 -2
- package/src/PixelData/fillPixelData.ts +26 -16
- package/src/PixelData/fillPixelDataBinaryMask.ts +12 -4
- package/src/PixelData/fillPixelDataFast.ts +94 -0
- package/src/PixelData/invertPixelData.ts +4 -2
- package/src/PixelTile/PaintBuffer.ts +122 -0
- package/src/PixelTile/PaintBufferRenderer.ts +40 -0
- package/src/PixelTile/PixelTile.ts +21 -0
- package/src/PixelTile/PixelTilePool.ts +63 -0
- package/src/_types.ts +9 -9
- package/src/index.ts +16 -6
- package/src/History/PixelMutator/mutatorApplyCircleBrush.ts +0 -78
package/dist/index.dev.cjs
CHANGED
|
@@ -28,17 +28,18 @@ __export(src_exports, {
|
|
|
28
28
|
IndexedImage: () => IndexedImage,
|
|
29
29
|
MaskType: () => MaskType,
|
|
30
30
|
OFFSCREEN_CANVAS_CTX_FAILED: () => OFFSCREEN_CANVAS_CTX_FAILED,
|
|
31
|
+
PaintBuffer: () => PaintBuffer,
|
|
31
32
|
PixelAccumulator: () => PixelAccumulator,
|
|
32
33
|
PixelBuffer32: () => PixelBuffer32,
|
|
33
34
|
PixelData: () => PixelData,
|
|
34
35
|
PixelEngineConfig: () => PixelEngineConfig,
|
|
35
36
|
PixelTile: () => PixelTile,
|
|
37
|
+
PixelTilePool: () => PixelTilePool,
|
|
36
38
|
PixelWriter: () => PixelWriter,
|
|
37
39
|
UnsupportedFormatError: () => UnsupportedFormatError,
|
|
38
40
|
applyAlphaMaskToPixelData: () => applyAlphaMaskToPixelData,
|
|
39
41
|
applyBinaryMaskToAlphaMask: () => applyBinaryMaskToAlphaMask,
|
|
40
42
|
applyBinaryMaskToPixelData: () => applyBinaryMaskToPixelData,
|
|
41
|
-
applyCircleBrushToPixelData: () => applyCircleBrushToPixelData,
|
|
42
43
|
applyPatchTiles: () => applyPatchTiles,
|
|
43
44
|
applyRectBrushToPixelData: () => applyRectBrushToPixelData,
|
|
44
45
|
base64DecodeArrayBuffer: () => base64DecodeArrayBuffer,
|
|
@@ -46,9 +47,12 @@ __export(src_exports, {
|
|
|
46
47
|
blendColorPixelData: () => blendColorPixelData,
|
|
47
48
|
blendColorPixelDataAlphaMask: () => blendColorPixelDataAlphaMask,
|
|
48
49
|
blendColorPixelDataBinaryMask: () => blendColorPixelDataBinaryMask,
|
|
50
|
+
blendColorPixelDataCircleMask: () => blendColorPixelDataCircleMask,
|
|
51
|
+
blendPixel: () => blendPixel,
|
|
49
52
|
blendPixelData: () => blendPixelData,
|
|
50
53
|
blendPixelDataAlphaMask: () => blendPixelDataAlphaMask,
|
|
51
54
|
blendPixelDataBinaryMask: () => blendPixelDataBinaryMask,
|
|
55
|
+
blendPixelDataPaintBuffer: () => blendPixelDataPaintBuffer,
|
|
52
56
|
clearPixelData: () => clearPixelData,
|
|
53
57
|
color32ToCssRGBA: () => color32ToCssRGBA,
|
|
54
58
|
color32ToHex: () => color32ToHex,
|
|
@@ -82,6 +86,7 @@ __export(src_exports, {
|
|
|
82
86
|
fileToImageData: () => fileToImageData,
|
|
83
87
|
fillPixelData: () => fillPixelData,
|
|
84
88
|
fillPixelDataBinaryMask: () => fillPixelDataBinaryMask,
|
|
89
|
+
fillPixelDataFast: () => fillPixelDataFast,
|
|
85
90
|
floodFillSelection: () => floodFillSelection,
|
|
86
91
|
forEachLinePoint: () => forEachLinePoint,
|
|
87
92
|
getCircleBrushOrPencilBounds: () => getCircleBrushOrPencilBounds,
|
|
@@ -122,15 +127,19 @@ __export(src_exports, {
|
|
|
122
127
|
makeAlphaMask: () => makeAlphaMask,
|
|
123
128
|
makeBinaryMask: () => makeBinaryMask,
|
|
124
129
|
makeBlendModeRegistry: () => makeBlendModeRegistry,
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
makeCanvasFrameRenderer: () => makeCanvasFrameRenderer,
|
|
131
|
+
makeCircleAlphaMask: () => makeCircleAlphaMask,
|
|
132
|
+
makeCircleBinaryMask: () => makeCircleBinaryMask,
|
|
127
133
|
makeFastBlendModeRegistry: () => makeFastBlendModeRegistry,
|
|
128
134
|
makeFullPixelMutator: () => makeFullPixelMutator,
|
|
135
|
+
makeHistoryAction: () => makeHistoryAction,
|
|
129
136
|
makeImageDataLike: () => makeImageDataLike,
|
|
137
|
+
makePaintBufferRenderer: () => makePaintBufferRenderer,
|
|
130
138
|
makePerfectBlendModeRegistry: () => makePerfectBlendModeRegistry,
|
|
131
139
|
makePixelCanvas: () => makePixelCanvas,
|
|
132
140
|
makeReusableCanvas: () => makeReusableCanvas,
|
|
133
141
|
makeReusableImageData: () => makeReusableImageData,
|
|
142
|
+
makeReusableOffscreenCanvas: () => makeReusableOffscreenCanvas,
|
|
134
143
|
merge2BinaryMaskRects: () => merge2BinaryMaskRects,
|
|
135
144
|
mergeAlphaMasks: () => mergeAlphaMasks,
|
|
136
145
|
mergeBinaryMaskRects: () => mergeBinaryMaskRects,
|
|
@@ -139,7 +148,6 @@ __export(src_exports, {
|
|
|
139
148
|
multiplyPerfect: () => multiplyPerfect,
|
|
140
149
|
mutatorApplyAlphaMask: () => mutatorApplyAlphaMask,
|
|
141
150
|
mutatorApplyBinaryMask: () => mutatorApplyBinaryMask,
|
|
142
|
-
mutatorApplyCircleBrush: () => mutatorApplyCircleBrush,
|
|
143
151
|
mutatorApplyCircleBrushStroke: () => mutatorApplyCircleBrushStroke,
|
|
144
152
|
mutatorApplyCirclePencil: () => mutatorApplyCirclePencil,
|
|
145
153
|
mutatorApplyCirclePencilStroke: () => mutatorApplyCirclePencilStroke,
|
|
@@ -148,6 +156,7 @@ __export(src_exports, {
|
|
|
148
156
|
mutatorApplyRectPencil: () => mutatorApplyRectPencil,
|
|
149
157
|
mutatorApplyRectPencilStroke: () => mutatorApplyRectPencilStroke,
|
|
150
158
|
mutatorBlendColor: () => mutatorBlendColor,
|
|
159
|
+
mutatorBlendColorCircleMask: () => mutatorBlendColorCircleMask,
|
|
151
160
|
mutatorBlendPixel: () => mutatorBlendPixel,
|
|
152
161
|
mutatorBlendPixelData: () => mutatorBlendPixelData,
|
|
153
162
|
mutatorBlendPixelDataAlphaMask: () => mutatorBlendPixelDataAlphaMask,
|
|
@@ -155,6 +164,7 @@ __export(src_exports, {
|
|
|
155
164
|
mutatorClear: () => mutatorClear,
|
|
156
165
|
mutatorFill: () => mutatorFill,
|
|
157
166
|
mutatorFillBinaryMask: () => mutatorFillBinaryMask,
|
|
167
|
+
mutatorFillRect: () => mutatorFillRect,
|
|
158
168
|
mutatorInvert: () => mutatorInvert,
|
|
159
169
|
overlayFast: () => overlayFast,
|
|
160
170
|
overlayPerfect: () => overlayPerfect,
|
|
@@ -643,6 +653,26 @@ function floodFillSelection(img, startX, startY, {
|
|
|
643
653
|
};
|
|
644
654
|
}
|
|
645
655
|
|
|
656
|
+
// src/Algorithm/forEachLinePoint.ts
|
|
657
|
+
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
658
|
+
const dx = x1 - x0;
|
|
659
|
+
const dy = y1 - y0;
|
|
660
|
+
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
661
|
+
if (steps === 0) {
|
|
662
|
+
callback(x0, y0);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
const xInc = dx / steps;
|
|
666
|
+
const yInc = dy / steps;
|
|
667
|
+
let curX = x0;
|
|
668
|
+
let curY = y0;
|
|
669
|
+
for (let i = 0; i <= steps; i++) {
|
|
670
|
+
callback(curX, curY);
|
|
671
|
+
curX += xInc;
|
|
672
|
+
curY += yInc;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
646
676
|
// src/BlendModes/blend-modes.ts
|
|
647
677
|
var BaseBlendMode = {
|
|
648
678
|
overwrite: 0,
|
|
@@ -1720,51 +1750,104 @@ var getKeyByValue = (obj, value) => {
|
|
|
1720
1750
|
var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
|
|
1721
1751
|
var CANVAS_CTX_FAILED = "Failed to create Canvas context";
|
|
1722
1752
|
|
|
1723
|
-
// src/Canvas/PixelCanvas.ts
|
|
1724
|
-
function makePixelCanvas(canvas) {
|
|
1725
|
-
const ctx = canvas.getContext("2d");
|
|
1726
|
-
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
1727
|
-
ctx.imageSmoothingEnabled = false;
|
|
1728
|
-
return {
|
|
1729
|
-
canvas,
|
|
1730
|
-
ctx,
|
|
1731
|
-
resize(w, h) {
|
|
1732
|
-
canvas.width = w;
|
|
1733
|
-
canvas.height = h;
|
|
1734
|
-
ctx.imageSmoothingEnabled = false;
|
|
1735
|
-
}
|
|
1736
|
-
};
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
1753
|
// src/Canvas/ReusableCanvas.ts
|
|
1740
1754
|
function makeReusableCanvas() {
|
|
1755
|
+
return makeReusableCanvasMeta((w, h) => {
|
|
1756
|
+
const canvas = document.createElement("canvas");
|
|
1757
|
+
canvas.width = w;
|
|
1758
|
+
canvas.height = h;
|
|
1759
|
+
return canvas;
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
function makeReusableOffscreenCanvas() {
|
|
1763
|
+
return makeReusableCanvasMeta((w, h) => new OffscreenCanvas(w, h));
|
|
1764
|
+
}
|
|
1765
|
+
function makeReusableCanvasMeta(factory) {
|
|
1741
1766
|
let canvas = null;
|
|
1742
1767
|
let ctx = null;
|
|
1768
|
+
const result = {
|
|
1769
|
+
canvas: null,
|
|
1770
|
+
ctx: null
|
|
1771
|
+
};
|
|
1743
1772
|
function get2(width, height) {
|
|
1744
1773
|
if (canvas === null) {
|
|
1745
|
-
canvas =
|
|
1774
|
+
canvas = factory(width, height);
|
|
1746
1775
|
ctx = canvas.getContext("2d");
|
|
1747
|
-
if (!ctx)
|
|
1776
|
+
if (!ctx) {
|
|
1777
|
+
throw new Error(CANVAS_CTX_FAILED);
|
|
1778
|
+
}
|
|
1779
|
+
ctx.imageSmoothingEnabled = false;
|
|
1780
|
+
result.canvas = canvas;
|
|
1781
|
+
result.ctx = ctx;
|
|
1782
|
+
return result;
|
|
1748
1783
|
}
|
|
1749
1784
|
if (canvas.width !== width || canvas.height !== height) {
|
|
1750
1785
|
canvas.width = width;
|
|
1751
1786
|
canvas.height = height;
|
|
1752
1787
|
ctx.imageSmoothingEnabled = false;
|
|
1753
1788
|
} else {
|
|
1789
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
1754
1790
|
ctx.clearRect(0, 0, width, height);
|
|
1755
1791
|
}
|
|
1756
|
-
return
|
|
1757
|
-
canvas,
|
|
1758
|
-
ctx
|
|
1759
|
-
};
|
|
1792
|
+
return result;
|
|
1760
1793
|
}
|
|
1761
1794
|
get2.reset = () => {
|
|
1762
1795
|
canvas = null;
|
|
1763
1796
|
ctx = null;
|
|
1797
|
+
result.canvas = null;
|
|
1798
|
+
result.ctx = null;
|
|
1764
1799
|
};
|
|
1765
1800
|
return get2;
|
|
1766
1801
|
}
|
|
1767
1802
|
|
|
1803
|
+
// src/Canvas/CanvasFrameRenderer.ts
|
|
1804
|
+
var defaults = {
|
|
1805
|
+
makeReusableCanvas
|
|
1806
|
+
};
|
|
1807
|
+
function makeCanvasFrameRenderer(deps = defaults) {
|
|
1808
|
+
const {
|
|
1809
|
+
makeReusableCanvas: makeReusableCanvas2 = defaults.makeReusableCanvas
|
|
1810
|
+
} = deps;
|
|
1811
|
+
const bufferCanvas = makeReusableCanvas2();
|
|
1812
|
+
return function renderCanvasFrame(pixelCanvas, scale, getImageData, drawPixelLayer, drawScreenLayer) {
|
|
1813
|
+
const {
|
|
1814
|
+
canvas,
|
|
1815
|
+
ctx
|
|
1816
|
+
} = pixelCanvas;
|
|
1817
|
+
const {
|
|
1818
|
+
ctx: pxCtx,
|
|
1819
|
+
canvas: pxCanvas
|
|
1820
|
+
} = bufferCanvas(canvas.width, canvas.height);
|
|
1821
|
+
const img = getImageData();
|
|
1822
|
+
if (img) {
|
|
1823
|
+
pxCtx.putImageData(img, 0, 0);
|
|
1824
|
+
}
|
|
1825
|
+
drawPixelLayer?.(pxCtx);
|
|
1826
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
1827
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1828
|
+
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
|
1829
|
+
ctx.drawImage(pxCanvas, 0, 0);
|
|
1830
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
1831
|
+
drawScreenLayer?.(ctx, scale);
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
// src/Canvas/PixelCanvas.ts
|
|
1836
|
+
function makePixelCanvas(canvas) {
|
|
1837
|
+
const ctx = canvas.getContext("2d");
|
|
1838
|
+
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
1839
|
+
ctx.imageSmoothingEnabled = false;
|
|
1840
|
+
return {
|
|
1841
|
+
canvas,
|
|
1842
|
+
ctx,
|
|
1843
|
+
resize(w, h) {
|
|
1844
|
+
canvas.width = w;
|
|
1845
|
+
canvas.height = h;
|
|
1846
|
+
ctx.imageSmoothingEnabled = false;
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1768
1851
|
// src/ImageData/imgBlobToImageData.ts
|
|
1769
1852
|
async function imgBlobToImageData(blob) {
|
|
1770
1853
|
let bitmap = null;
|
|
@@ -1824,6 +1907,50 @@ async function writeImageDataToClipboard(imageData) {
|
|
|
1824
1907
|
return writeImgBlobToClipboard(blob);
|
|
1825
1908
|
}
|
|
1826
1909
|
|
|
1910
|
+
// src/History/PixelPatchTiles.ts
|
|
1911
|
+
function applyPatchTiles(target, tiles, tileSize) {
|
|
1912
|
+
for (let i = 0; i < tiles.length; i++) {
|
|
1913
|
+
const tile = tiles[i];
|
|
1914
|
+
if (!tile) continue;
|
|
1915
|
+
const dst = target.data32;
|
|
1916
|
+
const src = tile.data32;
|
|
1917
|
+
const dstWidth = target.width;
|
|
1918
|
+
const dstHeight = target.height;
|
|
1919
|
+
const startX = tile.tx * tileSize;
|
|
1920
|
+
const startY = tile.ty * tileSize;
|
|
1921
|
+
const copyWidth = Math.max(0, Math.min(tileSize, dstWidth - startX));
|
|
1922
|
+
if (copyWidth <= 0) continue;
|
|
1923
|
+
for (let ly = 0; ly < tileSize; ly++) {
|
|
1924
|
+
const globalY = startY + ly;
|
|
1925
|
+
if (globalY >= dstHeight) break;
|
|
1926
|
+
const dstIndex = globalY * dstWidth + startX;
|
|
1927
|
+
const srcIndex = ly * tileSize;
|
|
1928
|
+
const rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1929
|
+
dst.set(rowData, dstIndex);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
// src/History/HistoryAction.ts
|
|
1935
|
+
function makeHistoryAction(writer, patch, after, afterUndo, afterRedo, applyPatchTilesFn = applyPatchTiles) {
|
|
1936
|
+
const target = writer.config.target;
|
|
1937
|
+
const tileSize = writer.config.tileSize;
|
|
1938
|
+
const accumulator = writer.accumulator;
|
|
1939
|
+
return {
|
|
1940
|
+
undo: () => {
|
|
1941
|
+
applyPatchTilesFn(target, patch.beforeTiles, tileSize);
|
|
1942
|
+
afterUndo?.();
|
|
1943
|
+
after?.();
|
|
1944
|
+
},
|
|
1945
|
+
redo: () => {
|
|
1946
|
+
applyPatchTilesFn(target, patch.afterTiles, tileSize);
|
|
1947
|
+
afterRedo?.();
|
|
1948
|
+
after?.();
|
|
1949
|
+
},
|
|
1950
|
+
dispose: () => accumulator.recyclePatch(patch)
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1827
1954
|
// src/History/HistoryManager.ts
|
|
1828
1955
|
var HistoryManager = class {
|
|
1829
1956
|
constructor(maxSteps = 50) {
|
|
@@ -1882,126 +2009,91 @@ var HistoryManager = class {
|
|
|
1882
2009
|
}
|
|
1883
2010
|
};
|
|
1884
2011
|
|
|
1885
|
-
// src/History/PixelPatchTiles.ts
|
|
1886
|
-
var PixelTile = class {
|
|
1887
|
-
constructor(id, tx, ty, tileArea) {
|
|
1888
|
-
this.id = id;
|
|
1889
|
-
this.tx = tx;
|
|
1890
|
-
this.ty = ty;
|
|
1891
|
-
this.data32 = new Uint32Array(tileArea);
|
|
1892
|
-
}
|
|
1893
|
-
data32;
|
|
1894
|
-
};
|
|
1895
|
-
function applyPatchTiles(target, tiles, tileSize = 256) {
|
|
1896
|
-
for (let i = 0; i < tiles.length; i++) {
|
|
1897
|
-
const tile = tiles[i];
|
|
1898
|
-
if (!tile) continue;
|
|
1899
|
-
const dst = target.data32;
|
|
1900
|
-
const src = tile.data32;
|
|
1901
|
-
const dstWidth = target.width;
|
|
1902
|
-
const dstHeight = target.height;
|
|
1903
|
-
const startX = tile.tx * tileSize;
|
|
1904
|
-
const startY = tile.ty * tileSize;
|
|
1905
|
-
const copyWidth = Math.max(0, Math.min(tileSize, dstWidth - startX));
|
|
1906
|
-
if (copyWidth <= 0) return;
|
|
1907
|
-
for (let ly = 0; ly < tileSize; ly++) {
|
|
1908
|
-
const globalY = startY + ly;
|
|
1909
|
-
if (globalY >= dstHeight) break;
|
|
1910
|
-
const dstIndex = globalY * dstWidth + startX;
|
|
1911
|
-
const srcIndex = ly * tileSize;
|
|
1912
|
-
const rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1913
|
-
dst.set(rowData, dstIndex);
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
2012
|
// src/History/PixelAccumulator.ts
|
|
1919
2013
|
var PixelAccumulator = class {
|
|
1920
|
-
constructor(
|
|
1921
|
-
this.target = target;
|
|
2014
|
+
constructor(config, tilePool) {
|
|
1922
2015
|
this.config = config;
|
|
2016
|
+
this.tilePool = tilePool;
|
|
1923
2017
|
this.lookup = [];
|
|
1924
2018
|
this.beforeTiles = [];
|
|
1925
|
-
this.pool = [];
|
|
1926
2019
|
}
|
|
1927
2020
|
lookup;
|
|
1928
2021
|
beforeTiles;
|
|
1929
|
-
pool;
|
|
1930
|
-
getTile(id, tx, ty) {
|
|
1931
|
-
let tile = this.pool.pop();
|
|
1932
|
-
if (tile) {
|
|
1933
|
-
tile.id = id;
|
|
1934
|
-
tile.tx = tx;
|
|
1935
|
-
tile.ty = ty;
|
|
1936
|
-
return tile;
|
|
1937
|
-
}
|
|
1938
|
-
return new PixelTile(id, tx, ty, this.config.tileArea);
|
|
1939
|
-
}
|
|
1940
2022
|
recyclePatch(patch) {
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
let tile = before[i];
|
|
1944
|
-
if (tile) {
|
|
1945
|
-
this.pool.push(tile);
|
|
1946
|
-
}
|
|
1947
|
-
}
|
|
1948
|
-
const after = patch.afterTiles;
|
|
1949
|
-
for (let i = 0; i < after.length; i++) {
|
|
1950
|
-
let tile = after[i];
|
|
1951
|
-
if (tile) {
|
|
1952
|
-
this.pool.push(tile);
|
|
1953
|
-
}
|
|
1954
|
-
}
|
|
2023
|
+
this.tilePool.releaseTiles(patch.beforeTiles);
|
|
2024
|
+
this.tilePool.releaseTiles(patch.afterTiles);
|
|
1955
2025
|
}
|
|
1956
2026
|
/**
|
|
1957
2027
|
* @param x pixel x coordinate
|
|
1958
2028
|
* @param y pixel y coordinate
|
|
1959
2029
|
*/
|
|
1960
|
-
|
|
1961
|
-
let target = this.target;
|
|
2030
|
+
storePixelBeforeState(x, y) {
|
|
1962
2031
|
let shift = this.config.tileShift;
|
|
1963
|
-
let columns =
|
|
2032
|
+
let columns = this.config.targetColumns;
|
|
1964
2033
|
let tx = x >> shift;
|
|
1965
2034
|
let ty = y >> shift;
|
|
1966
2035
|
let id = ty * columns + tx;
|
|
1967
2036
|
let tile = this.lookup[id];
|
|
2037
|
+
let added = false;
|
|
1968
2038
|
if (!tile) {
|
|
1969
|
-
tile = this.getTile(id, tx, ty);
|
|
2039
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
1970
2040
|
this.extractState(tile);
|
|
1971
2041
|
this.lookup[id] = tile;
|
|
1972
2042
|
this.beforeTiles.push(tile);
|
|
2043
|
+
added = true;
|
|
1973
2044
|
}
|
|
2045
|
+
return (didChange) => {
|
|
2046
|
+
if (!didChange && added) {
|
|
2047
|
+
this.beforeTiles.pop();
|
|
2048
|
+
this.lookup[id] = void 0;
|
|
2049
|
+
this.tilePool.releaseTile(tile);
|
|
2050
|
+
}
|
|
2051
|
+
return didChange;
|
|
2052
|
+
};
|
|
1974
2053
|
}
|
|
1975
2054
|
/**
|
|
1976
|
-
*
|
|
1977
2055
|
* @param x pixel x coordinate
|
|
1978
2056
|
* @param y pixel y coordinate
|
|
1979
2057
|
* @param w pixel width
|
|
1980
2058
|
* @param h pixel height
|
|
1981
2059
|
*/
|
|
1982
2060
|
storeRegionBeforeState(x, y, w, h) {
|
|
1983
|
-
let target = this.target;
|
|
1984
2061
|
let shift = this.config.tileShift;
|
|
1985
|
-
let columns =
|
|
2062
|
+
let columns = this.config.targetColumns;
|
|
1986
2063
|
let startX = x >> shift;
|
|
1987
2064
|
let startY = y >> shift;
|
|
1988
2065
|
let endX = x + w - 1 >> shift;
|
|
1989
2066
|
let endY = y + h - 1 >> shift;
|
|
2067
|
+
let startIndex = this.beforeTiles.length;
|
|
1990
2068
|
for (let ty = startY; ty <= endY; ty++) {
|
|
1991
2069
|
for (let tx = startX; tx <= endX; tx++) {
|
|
1992
2070
|
let id = ty * columns + tx;
|
|
1993
2071
|
let tile = this.lookup[id];
|
|
1994
2072
|
if (!tile) {
|
|
1995
|
-
tile = this.getTile(id, tx, ty);
|
|
2073
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
1996
2074
|
this.extractState(tile);
|
|
1997
2075
|
this.lookup[id] = tile;
|
|
1998
2076
|
this.beforeTiles.push(tile);
|
|
1999
2077
|
}
|
|
2000
2078
|
}
|
|
2001
2079
|
}
|
|
2080
|
+
return (didChange) => {
|
|
2081
|
+
if (!didChange) {
|
|
2082
|
+
let length = this.beforeTiles.length;
|
|
2083
|
+
for (let i = startIndex; i < length; i++) {
|
|
2084
|
+
let t = this.beforeTiles[i];
|
|
2085
|
+
if (t) {
|
|
2086
|
+
this.lookup[t.id] = void 0;
|
|
2087
|
+
this.tilePool.releaseTile(t);
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
this.beforeTiles.length = startIndex;
|
|
2091
|
+
}
|
|
2092
|
+
return didChange;
|
|
2093
|
+
};
|
|
2002
2094
|
}
|
|
2003
2095
|
extractState(tile) {
|
|
2004
|
-
let target = this.target;
|
|
2096
|
+
let target = this.config.target;
|
|
2005
2097
|
let TILE_SIZE = this.config.tileSize;
|
|
2006
2098
|
let dst = tile.data32;
|
|
2007
2099
|
let src = target.data32;
|
|
@@ -2009,7 +2101,12 @@ var PixelAccumulator = class {
|
|
|
2009
2101
|
let startY = tile.ty * TILE_SIZE;
|
|
2010
2102
|
let targetWidth = target.width;
|
|
2011
2103
|
let targetHeight = target.height;
|
|
2012
|
-
|
|
2104
|
+
if (startX >= targetWidth || startX + TILE_SIZE <= 0 || startY >= targetHeight || startY + TILE_SIZE <= 0) {
|
|
2105
|
+
dst.fill(0);
|
|
2106
|
+
return;
|
|
2107
|
+
}
|
|
2108
|
+
let srcOffsetX = Math.max(0, -startX);
|
|
2109
|
+
let copyWidth = Math.max(0, Math.min(TILE_SIZE - srcOffsetX, targetWidth - Math.max(0, startX)));
|
|
2013
2110
|
for (let ly = 0; ly < TILE_SIZE; ly++) {
|
|
2014
2111
|
let globalY = startY + ly;
|
|
2015
2112
|
let dstIndex = ly * TILE_SIZE;
|
|
@@ -2017,47 +2114,77 @@ var PixelAccumulator = class {
|
|
|
2017
2114
|
dst.fill(0, dstIndex, dstIndex + TILE_SIZE);
|
|
2018
2115
|
continue;
|
|
2019
2116
|
}
|
|
2020
|
-
let srcIndex = globalY * targetWidth + startX;
|
|
2117
|
+
let srcIndex = globalY * targetWidth + Math.max(0, startX);
|
|
2021
2118
|
let rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
2022
|
-
dst.set(rowData, dstIndex);
|
|
2023
|
-
if (
|
|
2024
|
-
dst.fill(0, dstIndex
|
|
2119
|
+
dst.set(rowData, dstIndex + srcOffsetX);
|
|
2120
|
+
if (srcOffsetX > 0) {
|
|
2121
|
+
dst.fill(0, dstIndex, dstIndex + srcOffsetX);
|
|
2122
|
+
}
|
|
2123
|
+
if (srcOffsetX + copyWidth < TILE_SIZE) {
|
|
2124
|
+
dst.fill(0, dstIndex + srcOffsetX + copyWidth, dstIndex + TILE_SIZE);
|
|
2025
2125
|
}
|
|
2026
2126
|
}
|
|
2027
2127
|
}
|
|
2028
|
-
|
|
2128
|
+
extractPatch() {
|
|
2029
2129
|
let afterTiles = [];
|
|
2030
2130
|
let length = this.beforeTiles.length;
|
|
2031
2131
|
for (let i = 0; i < length; i++) {
|
|
2032
2132
|
let beforeTile = this.beforeTiles[i];
|
|
2033
2133
|
if (beforeTile) {
|
|
2034
|
-
let afterTile = this.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
|
|
2134
|
+
let afterTile = this.tilePool.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
|
|
2035
2135
|
this.extractState(afterTile);
|
|
2036
2136
|
afterTiles.push(afterTile);
|
|
2037
2137
|
}
|
|
2038
2138
|
}
|
|
2039
|
-
|
|
2040
|
-
}
|
|
2041
|
-
reset() {
|
|
2042
|
-
this.lookup = [];
|
|
2139
|
+
let beforeTiles = this.beforeTiles;
|
|
2043
2140
|
this.beforeTiles = [];
|
|
2141
|
+
this.lookup.length = 0;
|
|
2142
|
+
return {
|
|
2143
|
+
beforeTiles,
|
|
2144
|
+
afterTiles
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
rollback() {
|
|
2148
|
+
let target = this.config.target;
|
|
2149
|
+
let tileSize = this.config.tileSize;
|
|
2150
|
+
let length = this.beforeTiles.length;
|
|
2151
|
+
applyPatchTiles(target, this.beforeTiles, tileSize);
|
|
2152
|
+
for (let i = 0; i < length; i++) {
|
|
2153
|
+
let tile = this.beforeTiles[i];
|
|
2154
|
+
if (tile) {
|
|
2155
|
+
this.lookup[tile.id] = void 0;
|
|
2156
|
+
this.tilePool.releaseTile(tile);
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
this.beforeTiles.length = 0;
|
|
2160
|
+
this.lookup.length = 0;
|
|
2044
2161
|
}
|
|
2045
2162
|
};
|
|
2046
2163
|
|
|
2047
2164
|
// src/History/PixelEngineConfig.ts
|
|
2048
2165
|
var PixelEngineConfig = class {
|
|
2049
2166
|
tileSize;
|
|
2167
|
+
// pixelX = tileX << tileShift
|
|
2168
|
+
// pixelY = tileY << tileShift
|
|
2050
2169
|
tileShift;
|
|
2051
2170
|
tileMask;
|
|
2052
2171
|
tileArea;
|
|
2053
|
-
|
|
2172
|
+
target;
|
|
2173
|
+
targetColumns = 0;
|
|
2174
|
+
constructor(tileSize, target) {
|
|
2054
2175
|
if ((tileSize & tileSize - 1) !== 0) {
|
|
2055
2176
|
throw new Error("tileSize must be a power of 2");
|
|
2056
2177
|
}
|
|
2057
2178
|
this.tileSize = tileSize;
|
|
2058
|
-
this.tileShift = Math.
|
|
2179
|
+
this.tileShift = 31 - Math.clz32(tileSize);
|
|
2059
2180
|
this.tileMask = tileSize - 1;
|
|
2060
2181
|
this.tileArea = tileSize * tileSize;
|
|
2182
|
+
this.setTarget(target);
|
|
2183
|
+
}
|
|
2184
|
+
setTarget(target) {
|
|
2185
|
+
;
|
|
2186
|
+
this.target = target;
|
|
2187
|
+
this.targetColumns = target.width + this.tileMask >> this.tileShift;
|
|
2061
2188
|
}
|
|
2062
2189
|
};
|
|
2063
2190
|
|
|
@@ -2073,7 +2200,7 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2073
2200
|
my = 0,
|
|
2074
2201
|
invertMask = false
|
|
2075
2202
|
} = opts;
|
|
2076
|
-
if (globalAlpha === 0) return;
|
|
2203
|
+
if (globalAlpha === 0) return false;
|
|
2077
2204
|
let x = targetX;
|
|
2078
2205
|
let y = targetY;
|
|
2079
2206
|
let w = width;
|
|
@@ -2088,10 +2215,10 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2088
2215
|
}
|
|
2089
2216
|
w = Math.min(w, dst.width - x);
|
|
2090
2217
|
h = Math.min(h, dst.height - y);
|
|
2091
|
-
if (w <= 0) return;
|
|
2092
|
-
if (h <= 0) return;
|
|
2218
|
+
if (w <= 0) return false;
|
|
2219
|
+
if (h <= 0) return false;
|
|
2093
2220
|
const mPitch = mask.w;
|
|
2094
|
-
if (mPitch <= 0) return;
|
|
2221
|
+
if (mPitch <= 0) return false;
|
|
2095
2222
|
const startX = mx + (x - targetX);
|
|
2096
2223
|
const startY = my + (y - targetY);
|
|
2097
2224
|
const sX0 = Math.max(0, startX);
|
|
@@ -2100,8 +2227,8 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2100
2227
|
const sY1 = Math.min(mask.h, startY + h);
|
|
2101
2228
|
const finalW = sX1 - sX0;
|
|
2102
2229
|
const finalH = sY1 - sY0;
|
|
2103
|
-
if (finalW <= 0) return;
|
|
2104
|
-
if (finalH <= 0) return;
|
|
2230
|
+
if (finalW <= 0) return false;
|
|
2231
|
+
if (finalH <= 0) return false;
|
|
2105
2232
|
const xShift = sX0 - startX;
|
|
2106
2233
|
const yShift = sY0 - startY;
|
|
2107
2234
|
const dst32 = dst.data32;
|
|
@@ -2111,6 +2238,7 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2111
2238
|
const maskData = mask.data;
|
|
2112
2239
|
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2113
2240
|
let mIdx = sY0 * mPitch + sX0;
|
|
2241
|
+
let didChange = false;
|
|
2114
2242
|
for (let iy = 0; iy < h; iy++) {
|
|
2115
2243
|
for (let ix = 0; ix < w; ix++) {
|
|
2116
2244
|
const mVal = maskData[mIdx];
|
|
@@ -2127,12 +2255,18 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2127
2255
|
}
|
|
2128
2256
|
if (weight === 0) {
|
|
2129
2257
|
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2258
|
+
didChange = true;
|
|
2130
2259
|
} else if (weight !== 255) {
|
|
2131
2260
|
const d = dst32[dIdx];
|
|
2132
2261
|
const da = d >>> 24;
|
|
2133
2262
|
if (da !== 0) {
|
|
2134
2263
|
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
2135
|
-
dst32[dIdx]
|
|
2264
|
+
const current = dst32[dIdx];
|
|
2265
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2266
|
+
if (current !== next) {
|
|
2267
|
+
dst32[dIdx] = next;
|
|
2268
|
+
didChange = true;
|
|
2269
|
+
}
|
|
2136
2270
|
}
|
|
2137
2271
|
}
|
|
2138
2272
|
dIdx++;
|
|
@@ -2141,27 +2275,28 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2141
2275
|
dIdx += dStride;
|
|
2142
2276
|
mIdx += mStride;
|
|
2143
2277
|
}
|
|
2278
|
+
return didChange;
|
|
2144
2279
|
}
|
|
2145
2280
|
|
|
2146
2281
|
// src/History/PixelMutator/mutatorApplyAlphaMask.ts
|
|
2147
|
-
var
|
|
2282
|
+
var defaults2 = {
|
|
2148
2283
|
applyAlphaMaskToPixelData
|
|
2149
2284
|
};
|
|
2150
|
-
var mutatorApplyAlphaMask = ((writer, deps =
|
|
2285
|
+
var mutatorApplyAlphaMask = ((writer, deps = defaults2) => {
|
|
2151
2286
|
const {
|
|
2152
|
-
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 =
|
|
2287
|
+
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults2.applyAlphaMaskToPixelData
|
|
2153
2288
|
} = deps;
|
|
2154
2289
|
return {
|
|
2155
|
-
applyAlphaMask
|
|
2156
|
-
let target = writer.target;
|
|
2290
|
+
applyAlphaMask(mask, opts = {}) {
|
|
2291
|
+
let target = writer.config.target;
|
|
2157
2292
|
const {
|
|
2158
2293
|
x = 0,
|
|
2159
2294
|
y = 0,
|
|
2160
|
-
w =
|
|
2161
|
-
h =
|
|
2295
|
+
w = target.width,
|
|
2296
|
+
h = target.height
|
|
2162
2297
|
} = opts;
|
|
2163
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2164
|
-
applyAlphaMaskToPixelData2(target, mask, opts);
|
|
2298
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2299
|
+
return didChange(applyAlphaMaskToPixelData2(target, mask, opts));
|
|
2165
2300
|
}
|
|
2166
2301
|
};
|
|
2167
2302
|
});
|
|
@@ -2178,7 +2313,7 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2178
2313
|
my = 0,
|
|
2179
2314
|
invertMask = false
|
|
2180
2315
|
} = opts;
|
|
2181
|
-
if (globalAlpha === 0) return;
|
|
2316
|
+
if (globalAlpha === 0) return false;
|
|
2182
2317
|
let x = targetX;
|
|
2183
2318
|
let y = targetY;
|
|
2184
2319
|
let w = width;
|
|
@@ -2193,10 +2328,9 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2193
2328
|
}
|
|
2194
2329
|
w = Math.min(w, dst.width - x);
|
|
2195
2330
|
h = Math.min(h, dst.height - y);
|
|
2196
|
-
if (w <= 0) return;
|
|
2197
|
-
if (h <= 0) return;
|
|
2331
|
+
if (w <= 0 || h <= 0) return false;
|
|
2198
2332
|
const mPitch = mask.w;
|
|
2199
|
-
if (mPitch <= 0) return;
|
|
2333
|
+
if (mPitch <= 0) return false;
|
|
2200
2334
|
const startX = mx + (x - targetX);
|
|
2201
2335
|
const startY = my + (y - targetY);
|
|
2202
2336
|
const sX0 = Math.max(0, startX);
|
|
@@ -2205,8 +2339,9 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2205
2339
|
const sY1 = Math.min(mask.h, startY + h);
|
|
2206
2340
|
const finalW = sX1 - sX0;
|
|
2207
2341
|
const finalH = sY1 - sY0;
|
|
2208
|
-
if (finalW <= 0)
|
|
2209
|
-
|
|
2342
|
+
if (finalW <= 0 || finalH <= 0) {
|
|
2343
|
+
return false;
|
|
2344
|
+
}
|
|
2210
2345
|
const xShift = sX0 - startX;
|
|
2211
2346
|
const yShift = sY0 - startY;
|
|
2212
2347
|
const dst32 = dst.data32;
|
|
@@ -2216,18 +2351,28 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2216
2351
|
const maskData = mask.data;
|
|
2217
2352
|
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2218
2353
|
let mIdx = sY0 * mPitch + sX0;
|
|
2219
|
-
|
|
2220
|
-
|
|
2354
|
+
let didChange = false;
|
|
2355
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
2356
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
2221
2357
|
const mVal = maskData[mIdx];
|
|
2222
2358
|
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
2223
2359
|
if (isMaskedOut) {
|
|
2224
|
-
|
|
2360
|
+
const current = dst32[dIdx];
|
|
2361
|
+
const next = (current & 16777215) >>> 0;
|
|
2362
|
+
if (current !== next) {
|
|
2363
|
+
dst32[dIdx] = next;
|
|
2364
|
+
didChange = true;
|
|
2365
|
+
}
|
|
2225
2366
|
} else if (globalAlpha !== 255) {
|
|
2226
2367
|
const d = dst32[dIdx];
|
|
2227
2368
|
const da = d >>> 24;
|
|
2228
2369
|
if (da !== 0) {
|
|
2229
2370
|
const finalAlpha = da === 255 ? globalAlpha : da * globalAlpha + 128 >> 8;
|
|
2230
|
-
|
|
2371
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2372
|
+
if (d !== next) {
|
|
2373
|
+
dst32[dIdx] = next;
|
|
2374
|
+
didChange = true;
|
|
2375
|
+
}
|
|
2231
2376
|
}
|
|
2232
2377
|
}
|
|
2233
2378
|
dIdx++;
|
|
@@ -2236,59 +2381,32 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2236
2381
|
dIdx += dStride;
|
|
2237
2382
|
mIdx += mStride;
|
|
2238
2383
|
}
|
|
2384
|
+
return didChange;
|
|
2239
2385
|
}
|
|
2240
2386
|
|
|
2241
2387
|
// src/History/PixelMutator/mutatorApplyBinaryMask.ts
|
|
2242
|
-
var
|
|
2388
|
+
var defaults3 = {
|
|
2243
2389
|
applyBinaryMaskToPixelData
|
|
2244
2390
|
};
|
|
2245
|
-
var mutatorApplyBinaryMask = ((writer, deps =
|
|
2391
|
+
var mutatorApplyBinaryMask = ((writer, deps = defaults3) => {
|
|
2246
2392
|
const {
|
|
2247
|
-
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 =
|
|
2393
|
+
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults3.applyBinaryMaskToPixelData
|
|
2248
2394
|
} = deps;
|
|
2249
2395
|
return {
|
|
2250
|
-
applyBinaryMask
|
|
2251
|
-
let target = writer.target;
|
|
2396
|
+
applyBinaryMask(mask, opts = {}) {
|
|
2397
|
+
let target = writer.config.target;
|
|
2252
2398
|
const {
|
|
2253
2399
|
x = 0,
|
|
2254
2400
|
y = 0,
|
|
2255
|
-
w =
|
|
2256
|
-
h =
|
|
2401
|
+
w = target.width,
|
|
2402
|
+
h = target.height
|
|
2257
2403
|
} = opts;
|
|
2258
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2259
|
-
applyBinaryMaskToPixelData2(target, mask, opts);
|
|
2404
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2405
|
+
return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
|
|
2260
2406
|
}
|
|
2261
2407
|
};
|
|
2262
2408
|
});
|
|
2263
2409
|
|
|
2264
|
-
// src/Rect/getCircleBrushOrPencilBounds.ts
|
|
2265
|
-
function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight, out) {
|
|
2266
|
-
const r = brushSize / 2;
|
|
2267
|
-
const minOffset = -Math.ceil(r - 0.5);
|
|
2268
|
-
const maxOffset = Math.floor(r - 0.5);
|
|
2269
|
-
const startX = Math.floor(centerX + minOffset);
|
|
2270
|
-
const startY = Math.floor(centerY + minOffset);
|
|
2271
|
-
const endX = Math.floor(centerX + maxOffset) + 1;
|
|
2272
|
-
const endY = Math.floor(centerY + maxOffset) + 1;
|
|
2273
|
-
const res = out ?? {
|
|
2274
|
-
x: 0,
|
|
2275
|
-
y: 0,
|
|
2276
|
-
w: 0,
|
|
2277
|
-
h: 0
|
|
2278
|
-
};
|
|
2279
|
-
const cStartX = Math.max(0, startX);
|
|
2280
|
-
const cStartY = Math.max(0, startY);
|
|
2281
|
-
const cEndX = Math.min(targetWidth, endX);
|
|
2282
|
-
const cEndY = Math.min(targetHeight, endY);
|
|
2283
|
-
const w = cEndX - cStartX;
|
|
2284
|
-
const h = cEndY - cStartY;
|
|
2285
|
-
res.x = cStartX;
|
|
2286
|
-
res.y = cStartY;
|
|
2287
|
-
res.w = w < 0 ? 0 : w;
|
|
2288
|
-
res.h = h < 0 ? 0 : h;
|
|
2289
|
-
return res;
|
|
2290
|
-
}
|
|
2291
|
-
|
|
2292
2410
|
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
2293
2411
|
function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
2294
2412
|
const targetX = opts.x ?? 0;
|
|
@@ -2300,10 +2418,10 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2300
2418
|
const mx = opts.mx ?? 0;
|
|
2301
2419
|
const my = opts.my ?? 0;
|
|
2302
2420
|
const invertMask = opts.invertMask ?? false;
|
|
2303
|
-
if (globalAlpha === 0) return;
|
|
2421
|
+
if (globalAlpha === 0) return false;
|
|
2304
2422
|
const baseSrcAlpha = color >>> 24;
|
|
2305
2423
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
2306
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2424
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2307
2425
|
let x = targetX;
|
|
2308
2426
|
let y = targetY;
|
|
2309
2427
|
let actualW = w;
|
|
@@ -2318,7 +2436,7 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2318
2436
|
}
|
|
2319
2437
|
actualW = Math.min(actualW, dst.width - x);
|
|
2320
2438
|
actualH = Math.min(actualH, dst.height - y);
|
|
2321
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
2439
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2322
2440
|
const dx = x - targetX | 0;
|
|
2323
2441
|
const dy = y - targetY | 0;
|
|
2324
2442
|
const dst32 = dst.data32;
|
|
@@ -2328,9 +2446,10 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2328
2446
|
let dIdx = y * dw + x | 0;
|
|
2329
2447
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2330
2448
|
const dStride = dw - actualW | 0;
|
|
2331
|
-
|
|
2449
|
+
const mStride = mPitch - actualW | 0;
|
|
2332
2450
|
const isOpaque = globalAlpha === 255;
|
|
2333
2451
|
const colorRGB = color & 16777215;
|
|
2452
|
+
let didChange = false;
|
|
2334
2453
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2335
2454
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2336
2455
|
const mVal = maskData[mIdx];
|
|
@@ -2361,162 +2480,47 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2361
2480
|
}
|
|
2362
2481
|
finalCol = (colorRGB | a << 24) >>> 0;
|
|
2363
2482
|
}
|
|
2364
|
-
|
|
2483
|
+
const current = dst32[dIdx];
|
|
2484
|
+
const next = blendFn(finalCol, current);
|
|
2485
|
+
if (current !== next) {
|
|
2486
|
+
dst32[dIdx] = next;
|
|
2487
|
+
didChange = true;
|
|
2488
|
+
}
|
|
2365
2489
|
dIdx++;
|
|
2366
2490
|
mIdx++;
|
|
2367
2491
|
}
|
|
2368
2492
|
dIdx += dStride;
|
|
2369
2493
|
mIdx += mStride;
|
|
2370
2494
|
}
|
|
2495
|
+
return didChange;
|
|
2371
2496
|
}
|
|
2372
2497
|
|
|
2373
|
-
// src/
|
|
2374
|
-
function
|
|
2375
|
-
const
|
|
2376
|
-
const
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
const
|
|
2380
|
-
const
|
|
2381
|
-
const
|
|
2382
|
-
const
|
|
2383
|
-
const invertMask = opts.invertMask ?? false;
|
|
2384
|
-
if (globalAlpha === 0) return;
|
|
2385
|
-
const baseSrcAlpha = color >>> 24;
|
|
2386
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
2387
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2388
|
-
let x = targetX;
|
|
2389
|
-
let y = targetY;
|
|
2390
|
-
if (x < 0) {
|
|
2391
|
-
w += x;
|
|
2392
|
-
x = 0;
|
|
2393
|
-
}
|
|
2394
|
-
if (y < 0) {
|
|
2395
|
-
h += y;
|
|
2396
|
-
y = 0;
|
|
2397
|
-
}
|
|
2398
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2399
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2400
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
2401
|
-
let baseColorWithGlobalAlpha = color;
|
|
2402
|
-
if (globalAlpha < 255) {
|
|
2403
|
-
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2404
|
-
if (a === 0 && !isOverwrite) return;
|
|
2405
|
-
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2406
|
-
}
|
|
2407
|
-
const dx = x - targetX | 0;
|
|
2408
|
-
const dy = y - targetY | 0;
|
|
2409
|
-
const dst32 = dst.data32;
|
|
2410
|
-
const dw = dst.width;
|
|
2411
|
-
const mPitch = mask.w;
|
|
2412
|
-
const maskData = mask.data;
|
|
2413
|
-
let dIdx = y * dw + x | 0;
|
|
2414
|
-
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2415
|
-
const dStride = dw - actualW | 0;
|
|
2416
|
-
const mStride = mPitch - actualW | 0;
|
|
2417
|
-
const skipVal = invertMask ? 1 : 0;
|
|
2418
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
2419
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2420
|
-
if (maskData[mIdx] === skipVal) {
|
|
2421
|
-
dIdx++;
|
|
2422
|
-
mIdx++;
|
|
2423
|
-
continue;
|
|
2424
|
-
}
|
|
2425
|
-
dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
|
|
2426
|
-
dIdx++;
|
|
2427
|
-
mIdx++;
|
|
2428
|
-
}
|
|
2429
|
-
dIdx += dStride;
|
|
2430
|
-
mIdx += mStride;
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
|
-
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
2435
|
-
function applyCircleBrushToPixelData(target, color, centerX, centerY, brush, alpha = 255, blendFn = sourceOverPerfect, scratchOptions = {}, bounds) {
|
|
2436
|
-
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brush.size, target.width, target.height);
|
|
2437
|
-
if (b.w <= 0 || b.h <= 0) return;
|
|
2438
|
-
const unclippedStartX = Math.floor(centerX + brush.minOffset);
|
|
2439
|
-
const unclippedStartY = Math.floor(centerY + brush.minOffset);
|
|
2440
|
-
const ix = Math.max(unclippedStartX, b.x);
|
|
2441
|
-
const iy = Math.max(unclippedStartY, b.y);
|
|
2442
|
-
const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
|
|
2443
|
-
const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
|
|
2444
|
-
const iw = ir - ix;
|
|
2445
|
-
const ih = ib - iy;
|
|
2446
|
-
if (iw <= 0 || ih <= 0) return;
|
|
2447
|
-
scratchOptions.x = ix;
|
|
2448
|
-
scratchOptions.y = iy;
|
|
2449
|
-
scratchOptions.w = iw;
|
|
2450
|
-
scratchOptions.h = ih;
|
|
2451
|
-
scratchOptions.mx = ix - unclippedStartX;
|
|
2452
|
-
scratchOptions.my = iy - unclippedStartY;
|
|
2453
|
-
scratchOptions.alpha = alpha;
|
|
2454
|
-
scratchOptions.blendFn = blendFn;
|
|
2455
|
-
if (brush.type === 0 /* ALPHA */) {
|
|
2456
|
-
blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
|
|
2457
|
-
}
|
|
2458
|
-
if (brush.type === 1 /* BINARY */) {
|
|
2459
|
-
blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
|
|
2463
|
-
// src/History/PixelMutator/mutatorApplyCircleBrush.ts
|
|
2464
|
-
var defaults3 = {
|
|
2465
|
-
applyCircleBrushToPixelData,
|
|
2466
|
-
getCircleBrushOrPencilBounds
|
|
2467
|
-
};
|
|
2468
|
-
var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
|
|
2469
|
-
const {
|
|
2470
|
-
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
|
|
2471
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
|
|
2472
|
-
} = deps;
|
|
2473
|
-
const boundsOut = {
|
|
2474
|
-
x: 0,
|
|
2475
|
-
y: 0,
|
|
2476
|
-
w: 0,
|
|
2477
|
-
h: 0
|
|
2478
|
-
};
|
|
2479
|
-
const blendColorPixelOptions = {
|
|
2480
|
-
alpha: 255,
|
|
2481
|
-
blendFn: sourceOverPerfect,
|
|
2498
|
+
// src/Rect/getCircleBrushOrPencilBounds.ts
|
|
2499
|
+
function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight, out) {
|
|
2500
|
+
const r = brushSize / 2;
|
|
2501
|
+
const minOffset = -Math.ceil(r - 0.5);
|
|
2502
|
+
const maxOffset = Math.floor(r - 0.5);
|
|
2503
|
+
const startX = Math.floor(centerX + minOffset);
|
|
2504
|
+
const startY = Math.floor(centerY + minOffset);
|
|
2505
|
+
const endX = Math.floor(centerX + maxOffset) + 1;
|
|
2506
|
+
const endY = Math.floor(centerY + maxOffset) + 1;
|
|
2507
|
+
const res = out ?? {
|
|
2482
2508
|
x: 0,
|
|
2483
2509
|
y: 0,
|
|
2484
2510
|
w: 0,
|
|
2485
2511
|
h: 0
|
|
2486
2512
|
};
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
}
|
|
2499
|
-
};
|
|
2500
|
-
});
|
|
2501
|
-
|
|
2502
|
-
// src/Algorithm/forEachLinePoint.ts
|
|
2503
|
-
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
2504
|
-
const dx = x1 - x0;
|
|
2505
|
-
const dy = y1 - y0;
|
|
2506
|
-
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
2507
|
-
if (steps === 0) {
|
|
2508
|
-
callback(x0, y0);
|
|
2509
|
-
return;
|
|
2510
|
-
}
|
|
2511
|
-
const xInc = dx / steps;
|
|
2512
|
-
const yInc = dy / steps;
|
|
2513
|
-
let curX = x0;
|
|
2514
|
-
let curY = y0;
|
|
2515
|
-
for (let i = 0; i <= steps; i++) {
|
|
2516
|
-
callback(curX, curY);
|
|
2517
|
-
curX += xInc;
|
|
2518
|
-
curY += yInc;
|
|
2519
|
-
}
|
|
2513
|
+
const cStartX = Math.max(0, startX);
|
|
2514
|
+
const cStartY = Math.max(0, startY);
|
|
2515
|
+
const cEndX = Math.min(targetWidth, endX);
|
|
2516
|
+
const cEndY = Math.min(targetHeight, endY);
|
|
2517
|
+
const w = cEndX - cStartX;
|
|
2518
|
+
const h = cEndY - cStartY;
|
|
2519
|
+
res.x = cStartX;
|
|
2520
|
+
res.y = cStartY;
|
|
2521
|
+
res.w = w < 0 ? 0 : w;
|
|
2522
|
+
res.h = h < 0 ? 0 : h;
|
|
2523
|
+
return res;
|
|
2520
2524
|
}
|
|
2521
2525
|
|
|
2522
2526
|
// src/Rect/getCircleBrushOrPencilStrokeBounds.ts
|
|
@@ -2589,8 +2593,9 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2589
2593
|
const maskData = mask.data;
|
|
2590
2594
|
const brushData = brush.data;
|
|
2591
2595
|
const minOffset = brush.minOffset;
|
|
2592
|
-
const
|
|
2593
|
-
const
|
|
2596
|
+
const target = writer.config.target;
|
|
2597
|
+
const targetWidth = target.width;
|
|
2598
|
+
const targetHeight = target.height;
|
|
2594
2599
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2595
2600
|
const {
|
|
2596
2601
|
x: cbx,
|
|
@@ -2628,19 +2633,117 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2628
2633
|
blendColorPixelOptions.y = by;
|
|
2629
2634
|
blendColorPixelOptions.w = bw;
|
|
2630
2635
|
blendColorPixelOptions.h = bh;
|
|
2631
|
-
blendColorPixelDataAlphaMask2(
|
|
2636
|
+
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2632
2637
|
}
|
|
2633
2638
|
};
|
|
2634
2639
|
});
|
|
2635
2640
|
|
|
2636
|
-
// src/
|
|
2641
|
+
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
2642
|
+
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
2643
|
+
const targetX = opts.x ?? 0;
|
|
2644
|
+
const targetY = opts.y ?? 0;
|
|
2645
|
+
let w = opts.w ?? mask.w;
|
|
2646
|
+
let h = opts.h ?? mask.h;
|
|
2647
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
2648
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
2649
|
+
const mx = opts.mx ?? 0;
|
|
2650
|
+
const my = opts.my ?? 0;
|
|
2651
|
+
const invertMask = opts.invertMask ?? false;
|
|
2652
|
+
if (globalAlpha === 0) return false;
|
|
2653
|
+
const baseSrcAlpha = color >>> 24;
|
|
2654
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2655
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2656
|
+
let x = targetX;
|
|
2657
|
+
let y = targetY;
|
|
2658
|
+
if (x < 0) {
|
|
2659
|
+
w += x;
|
|
2660
|
+
x = 0;
|
|
2661
|
+
}
|
|
2662
|
+
if (y < 0) {
|
|
2663
|
+
h += y;
|
|
2664
|
+
y = 0;
|
|
2665
|
+
}
|
|
2666
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2667
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2668
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2669
|
+
let baseColorWithGlobalAlpha = color;
|
|
2670
|
+
if (globalAlpha < 255) {
|
|
2671
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2672
|
+
if (a === 0 && !isOverwrite) return false;
|
|
2673
|
+
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2674
|
+
}
|
|
2675
|
+
const dx = x - targetX | 0;
|
|
2676
|
+
const dy = y - targetY | 0;
|
|
2677
|
+
const dst32 = dst.data32;
|
|
2678
|
+
const dw = dst.width;
|
|
2679
|
+
const mPitch = mask.w;
|
|
2680
|
+
const maskData = mask.data;
|
|
2681
|
+
let dIdx = y * dw + x | 0;
|
|
2682
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2683
|
+
const dStride = dw - actualW | 0;
|
|
2684
|
+
const mStride = mPitch - actualW | 0;
|
|
2685
|
+
const skipVal = invertMask ? 1 : 0;
|
|
2686
|
+
let didChange = false;
|
|
2687
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2688
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2689
|
+
if (maskData[mIdx] === skipVal) {
|
|
2690
|
+
dIdx++;
|
|
2691
|
+
mIdx++;
|
|
2692
|
+
continue;
|
|
2693
|
+
}
|
|
2694
|
+
const current = dst32[dIdx];
|
|
2695
|
+
const next = blendFn(baseColorWithGlobalAlpha, current);
|
|
2696
|
+
if (current !== next) {
|
|
2697
|
+
dst32[dIdx] = next;
|
|
2698
|
+
didChange = true;
|
|
2699
|
+
}
|
|
2700
|
+
dIdx++;
|
|
2701
|
+
mIdx++;
|
|
2702
|
+
}
|
|
2703
|
+
dIdx += dStride;
|
|
2704
|
+
mIdx += mStride;
|
|
2705
|
+
}
|
|
2706
|
+
return didChange;
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
// src/PixelData/blendColorPixelDataCircleMask.ts
|
|
2710
|
+
function blendColorPixelDataCircleMask(target, color, centerX, centerY, brush, alpha = 255, blendFn = sourceOverPerfect, scratchOptions = {}, bounds) {
|
|
2711
|
+
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brush.size, target.width, target.height);
|
|
2712
|
+
if (b.w <= 0 || b.h <= 0) return false;
|
|
2713
|
+
const unclippedStartX = Math.floor(centerX + brush.minOffset);
|
|
2714
|
+
const unclippedStartY = Math.floor(centerY + brush.minOffset);
|
|
2715
|
+
const ix = Math.max(unclippedStartX, b.x);
|
|
2716
|
+
const iy = Math.max(unclippedStartY, b.y);
|
|
2717
|
+
const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
|
|
2718
|
+
const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
|
|
2719
|
+
const iw = ir - ix;
|
|
2720
|
+
const ih = ib - iy;
|
|
2721
|
+
if (iw <= 0 || ih <= 0) return false;
|
|
2722
|
+
scratchOptions.x = ix;
|
|
2723
|
+
scratchOptions.y = iy;
|
|
2724
|
+
scratchOptions.w = iw;
|
|
2725
|
+
scratchOptions.h = ih;
|
|
2726
|
+
scratchOptions.mx = ix - unclippedStartX;
|
|
2727
|
+
scratchOptions.my = iy - unclippedStartY;
|
|
2728
|
+
scratchOptions.alpha = alpha;
|
|
2729
|
+
scratchOptions.blendFn = blendFn;
|
|
2730
|
+
if (brush.type === 0 /* ALPHA */) {
|
|
2731
|
+
return blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
|
|
2732
|
+
}
|
|
2733
|
+
if (brush.type === 1 /* BINARY */) {
|
|
2734
|
+
return blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
|
|
2735
|
+
}
|
|
2736
|
+
return false;
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
// src/History/PixelMutator/mutatorBlendColorCircleMask.ts
|
|
2637
2740
|
var defaults5 = {
|
|
2638
|
-
|
|
2741
|
+
blendColorPixelDataCircleMask,
|
|
2639
2742
|
getCircleBrushOrPencilBounds
|
|
2640
2743
|
};
|
|
2641
|
-
var
|
|
2744
|
+
var mutatorBlendColorCircleMask = ((writer, deps = defaults5) => {
|
|
2642
2745
|
const {
|
|
2643
|
-
|
|
2746
|
+
blendColorPixelDataCircleMask: blendColorPixelDataCircleMask2 = defaults5.blendColorPixelDataCircleMask,
|
|
2644
2747
|
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
|
|
2645
2748
|
} = deps;
|
|
2646
2749
|
const boundsOut = {
|
|
@@ -2649,34 +2752,63 @@ var mutatorApplyCirclePencil = ((writer, deps = defaults5) => {
|
|
|
2649
2752
|
w: 0,
|
|
2650
2753
|
h: 0
|
|
2651
2754
|
};
|
|
2755
|
+
const blendColorPixelOptions = {
|
|
2756
|
+
alpha: 255,
|
|
2757
|
+
blendFn: sourceOverPerfect,
|
|
2758
|
+
x: 0,
|
|
2759
|
+
y: 0,
|
|
2760
|
+
w: 0,
|
|
2761
|
+
h: 0
|
|
2762
|
+
};
|
|
2763
|
+
return {
|
|
2764
|
+
applyCircleMask(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
2765
|
+
const target = writer.config.target;
|
|
2766
|
+
const b = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, target.width, target.height, boundsOut);
|
|
2767
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2768
|
+
return didChange(blendColorPixelDataCircleMask2(target, color, centerX, centerY, brush, alpha, blendFn, blendColorPixelOptions, b));
|
|
2769
|
+
}
|
|
2770
|
+
};
|
|
2771
|
+
});
|
|
2772
|
+
|
|
2773
|
+
// src/History/PixelMutator/mutatorApplyCirclePencil.ts
|
|
2774
|
+
var defaults6 = {
|
|
2775
|
+
applyCircleMaskToPixelData: blendColorPixelDataCircleMask,
|
|
2776
|
+
getCircleBrushOrPencilBounds
|
|
2777
|
+
};
|
|
2778
|
+
var mutatorApplyCirclePencil = ((writer, deps = defaults6) => {
|
|
2779
|
+
const {
|
|
2780
|
+
applyCircleMaskToPixelData = defaults6.applyCircleMaskToPixelData,
|
|
2781
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults6.getCircleBrushOrPencilBounds
|
|
2782
|
+
} = deps;
|
|
2783
|
+
const boundsOut = {
|
|
2784
|
+
x: 0,
|
|
2785
|
+
y: 0,
|
|
2786
|
+
w: 0,
|
|
2787
|
+
h: 0
|
|
2788
|
+
};
|
|
2652
2789
|
return {
|
|
2653
2790
|
applyCirclePencil(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
2654
|
-
const
|
|
2655
|
-
const
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
w,
|
|
2659
|
-
h
|
|
2660
|
-
} = bounds;
|
|
2661
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2662
|
-
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brush, alpha, blendFn, bounds);
|
|
2791
|
+
const target = writer.config.target;
|
|
2792
|
+
const b = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, target.width, target.height, boundsOut);
|
|
2793
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2794
|
+
return didChange(applyCircleMaskToPixelData(target, color, centerX, centerY, brush, alpha, blendFn, b));
|
|
2663
2795
|
}
|
|
2664
2796
|
};
|
|
2665
2797
|
});
|
|
2666
2798
|
|
|
2667
2799
|
// src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
|
|
2668
|
-
var
|
|
2800
|
+
var defaults7 = {
|
|
2669
2801
|
forEachLinePoint,
|
|
2670
2802
|
blendColorPixelDataBinaryMask,
|
|
2671
2803
|
getCircleBrushOrPencilBounds,
|
|
2672
2804
|
getCircleBrushOrPencilStrokeBounds
|
|
2673
2805
|
};
|
|
2674
|
-
var mutatorApplyCirclePencilStroke = ((writer, deps =
|
|
2806
|
+
var mutatorApplyCirclePencilStroke = ((writer, deps = defaults7) => {
|
|
2675
2807
|
const {
|
|
2676
|
-
forEachLinePoint: forEachLinePoint2 =
|
|
2677
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 =
|
|
2678
|
-
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 =
|
|
2679
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 =
|
|
2808
|
+
forEachLinePoint: forEachLinePoint2 = defaults7.forEachLinePoint,
|
|
2809
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults7.blendColorPixelDataBinaryMask,
|
|
2810
|
+
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults7.getCircleBrushOrPencilStrokeBounds,
|
|
2811
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults7.getCircleBrushOrPencilBounds
|
|
2680
2812
|
} = deps;
|
|
2681
2813
|
const strokeBoundsOut = {
|
|
2682
2814
|
x: 0,
|
|
@@ -2717,8 +2849,9 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults6) => {
|
|
|
2717
2849
|
mask.w = bw;
|
|
2718
2850
|
mask.h = bh;
|
|
2719
2851
|
const maskData = mask.data;
|
|
2720
|
-
const
|
|
2721
|
-
const
|
|
2852
|
+
const target = writer.config.target;
|
|
2853
|
+
const targetWidth = target.width;
|
|
2854
|
+
const targetHeight = target.height;
|
|
2722
2855
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2723
2856
|
const {
|
|
2724
2857
|
x: cbx,
|
|
@@ -2753,7 +2886,7 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults6) => {
|
|
|
2753
2886
|
blendColorPixelOptions.y = by;
|
|
2754
2887
|
blendColorPixelOptions.w = bw;
|
|
2755
2888
|
blendColorPixelOptions.h = bh;
|
|
2756
|
-
blendColorPixelDataBinaryMask2(
|
|
2889
|
+
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
2757
2890
|
}
|
|
2758
2891
|
};
|
|
2759
2892
|
});
|
|
@@ -2788,7 +2921,9 @@ function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth,
|
|
|
2788
2921
|
const targetWidth = target.width;
|
|
2789
2922
|
const targetHeight = target.height;
|
|
2790
2923
|
const b = bounds ?? getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight);
|
|
2791
|
-
if (b.w <= 0 || b.h <= 0)
|
|
2924
|
+
if (b.w <= 0 || b.h <= 0) {
|
|
2925
|
+
return false;
|
|
2926
|
+
}
|
|
2792
2927
|
const data32 = target.data32;
|
|
2793
2928
|
const baseColor = color & 16777215;
|
|
2794
2929
|
const baseSrcAlpha = color >>> 24;
|
|
@@ -2802,6 +2937,7 @@ function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth,
|
|
|
2802
2937
|
const endX = b.x + b.w;
|
|
2803
2938
|
const endY = b.y + b.h;
|
|
2804
2939
|
const isOverwrite = blendFn.isOverwrite;
|
|
2940
|
+
let didChange = false;
|
|
2805
2941
|
for (let py = b.y; py < endY; py++) {
|
|
2806
2942
|
const rowOffset = py * targetWidth;
|
|
2807
2943
|
const dy = Math.abs(py - fCenterY + centerOffsetY) * invHalfH;
|
|
@@ -2824,20 +2960,26 @@ function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth,
|
|
|
2824
2960
|
if (a === 0 && !isOverwrite) continue;
|
|
2825
2961
|
finalCol = (a << 24 | baseColor) >>> 0;
|
|
2826
2962
|
}
|
|
2827
|
-
|
|
2963
|
+
const current = data32[idx];
|
|
2964
|
+
const next = blendFn(finalCol, current);
|
|
2965
|
+
if (current !== next) {
|
|
2966
|
+
data32[idx] = next;
|
|
2967
|
+
didChange = true;
|
|
2968
|
+
}
|
|
2828
2969
|
}
|
|
2829
2970
|
}
|
|
2971
|
+
return didChange;
|
|
2830
2972
|
}
|
|
2831
2973
|
|
|
2832
2974
|
// src/History/PixelMutator/mutatorApplyRectBrush.ts
|
|
2833
|
-
var
|
|
2975
|
+
var defaults8 = {
|
|
2834
2976
|
applyRectBrushToPixelData,
|
|
2835
2977
|
getRectBrushOrPencilBounds
|
|
2836
2978
|
};
|
|
2837
|
-
var mutatorApplyRectBrush = ((writer, deps =
|
|
2979
|
+
var mutatorApplyRectBrush = ((writer, deps = defaults8) => {
|
|
2838
2980
|
const {
|
|
2839
|
-
applyRectBrushToPixelData: applyRectBrushToPixelData2 =
|
|
2840
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
2981
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults8.applyRectBrushToPixelData,
|
|
2982
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds
|
|
2841
2983
|
} = deps;
|
|
2842
2984
|
const boundsOut = {
|
|
2843
2985
|
x: 0,
|
|
@@ -2847,15 +2989,10 @@ var mutatorApplyRectBrush = ((writer, deps = defaults7) => {
|
|
|
2847
2989
|
};
|
|
2848
2990
|
return {
|
|
2849
2991
|
applyRectBrush(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn) {
|
|
2850
|
-
const
|
|
2851
|
-
const
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
w,
|
|
2855
|
-
h
|
|
2856
|
-
} = bounds;
|
|
2857
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2858
|
-
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2992
|
+
const target = writer.config.target;
|
|
2993
|
+
const b = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, target.width, target.height, boundsOut);
|
|
2994
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2995
|
+
return didChange(applyRectBrushToPixelData2(target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, b));
|
|
2859
2996
|
}
|
|
2860
2997
|
};
|
|
2861
2998
|
});
|
|
@@ -2876,18 +3013,18 @@ function getRectBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushWidth, brushHeigh
|
|
|
2876
3013
|
}
|
|
2877
3014
|
|
|
2878
3015
|
// src/History/PixelMutator/mutatorApplyRectBrushStroke.ts
|
|
2879
|
-
var
|
|
3016
|
+
var defaults9 = {
|
|
2880
3017
|
forEachLinePoint,
|
|
2881
3018
|
blendColorPixelDataAlphaMask,
|
|
2882
3019
|
getRectBrushOrPencilBounds,
|
|
2883
3020
|
getRectBrushOrPencilStrokeBounds
|
|
2884
3021
|
};
|
|
2885
|
-
var mutatorApplyRectBrushStroke = ((writer, deps =
|
|
3022
|
+
var mutatorApplyRectBrushStroke = ((writer, deps = defaults9) => {
|
|
2886
3023
|
const {
|
|
2887
|
-
forEachLinePoint: forEachLinePoint2 =
|
|
2888
|
-
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 =
|
|
2889
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
2890
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 =
|
|
3024
|
+
forEachLinePoint: forEachLinePoint2 = defaults9.forEachLinePoint,
|
|
3025
|
+
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults9.blendColorPixelDataAlphaMask,
|
|
3026
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
|
|
3027
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults9.getRectBrushOrPencilStrokeBounds
|
|
2891
3028
|
} = deps;
|
|
2892
3029
|
const strokeBoundsOut = {
|
|
2893
3030
|
x: 0,
|
|
@@ -2934,8 +3071,9 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults8) => {
|
|
|
2934
3071
|
const invHalfH = 1 / halfH;
|
|
2935
3072
|
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2936
3073
|
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2937
|
-
const
|
|
2938
|
-
const
|
|
3074
|
+
const target = writer.config.target;
|
|
3075
|
+
const targetWidth = target.width;
|
|
3076
|
+
const targetHeight = target.height;
|
|
2939
3077
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2940
3078
|
const {
|
|
2941
3079
|
x: rbx,
|
|
@@ -2973,22 +3111,22 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults8) => {
|
|
|
2973
3111
|
blendColorPixelOptions.y = by;
|
|
2974
3112
|
blendColorPixelOptions.w = bw;
|
|
2975
3113
|
blendColorPixelOptions.h = bh;
|
|
2976
|
-
blendColorPixelDataAlphaMask2(
|
|
3114
|
+
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2977
3115
|
}
|
|
2978
3116
|
};
|
|
2979
3117
|
});
|
|
2980
3118
|
|
|
2981
3119
|
// src/History/PixelMutator/mutatorApplyRectPencil.ts
|
|
2982
|
-
var
|
|
3120
|
+
var defaults10 = {
|
|
2983
3121
|
applyRectBrushToPixelData,
|
|
2984
3122
|
getRectBrushOrPencilBounds,
|
|
2985
3123
|
fallOff: () => 1
|
|
2986
3124
|
};
|
|
2987
|
-
var mutatorApplyRectPencil = ((writer, deps =
|
|
3125
|
+
var mutatorApplyRectPencil = ((writer, deps = defaults10) => {
|
|
2988
3126
|
const {
|
|
2989
|
-
applyRectBrushToPixelData: applyRectBrushToPixelData2 =
|
|
2990
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
2991
|
-
fallOff =
|
|
3127
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults10.applyRectBrushToPixelData,
|
|
3128
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults10.getRectBrushOrPencilBounds,
|
|
3129
|
+
fallOff = defaults10.fallOff
|
|
2992
3130
|
} = deps;
|
|
2993
3131
|
const boundsOut = {
|
|
2994
3132
|
x: 0,
|
|
@@ -2998,32 +3136,27 @@ var mutatorApplyRectPencil = ((writer, deps = defaults9) => {
|
|
|
2998
3136
|
};
|
|
2999
3137
|
return {
|
|
3000
3138
|
applyRectPencil(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, blendFn) {
|
|
3001
|
-
const
|
|
3002
|
-
const
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
w,
|
|
3006
|
-
h
|
|
3007
|
-
} = bounds;
|
|
3008
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3009
|
-
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
3139
|
+
const target = writer.config.target;
|
|
3140
|
+
const b = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, target.width, target.height, boundsOut);
|
|
3141
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
3142
|
+
return didChange(applyRectBrushToPixelData2(target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, b));
|
|
3010
3143
|
}
|
|
3011
3144
|
};
|
|
3012
3145
|
});
|
|
3013
3146
|
|
|
3014
3147
|
// src/History/PixelMutator/mutatorApplyRectPencilStroke.ts
|
|
3015
|
-
var
|
|
3148
|
+
var defaults11 = {
|
|
3016
3149
|
forEachLinePoint,
|
|
3017
3150
|
getRectBrushOrPencilBounds,
|
|
3018
3151
|
getRectBrushOrPencilStrokeBounds,
|
|
3019
3152
|
blendColorPixelDataBinaryMask
|
|
3020
3153
|
};
|
|
3021
|
-
var mutatorApplyRectPencilStroke = ((writer, deps =
|
|
3154
|
+
var mutatorApplyRectPencilStroke = ((writer, deps = defaults11) => {
|
|
3022
3155
|
const {
|
|
3023
|
-
forEachLinePoint: forEachLinePoint2 =
|
|
3024
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 =
|
|
3025
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
3026
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 =
|
|
3156
|
+
forEachLinePoint: forEachLinePoint2 = defaults11.forEachLinePoint,
|
|
3157
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults11.blendColorPixelDataBinaryMask,
|
|
3158
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults11.getRectBrushOrPencilBounds,
|
|
3159
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults11.getRectBrushOrPencilStrokeBounds
|
|
3027
3160
|
} = deps;
|
|
3028
3161
|
const strokeBoundsOut = {
|
|
3029
3162
|
x: 0,
|
|
@@ -3067,8 +3200,9 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults10) => {
|
|
|
3067
3200
|
const halfW = brushWidth / 2;
|
|
3068
3201
|
const halfH = brushHeight / 2;
|
|
3069
3202
|
const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
3070
|
-
const
|
|
3071
|
-
const
|
|
3203
|
+
const target = writer.config.target;
|
|
3204
|
+
const targetWidth = target.width;
|
|
3205
|
+
const targetHeight = target.height;
|
|
3072
3206
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
3073
3207
|
const {
|
|
3074
3208
|
x: rbx,
|
|
@@ -3101,7 +3235,7 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults10) => {
|
|
|
3101
3235
|
blendColorPixelOptions.y = by;
|
|
3102
3236
|
blendColorPixelOptions.w = bw;
|
|
3103
3237
|
blendColorPixelOptions.h = bh;
|
|
3104
|
-
blendColorPixelDataBinaryMask2(
|
|
3238
|
+
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
3105
3239
|
}
|
|
3106
3240
|
};
|
|
3107
3241
|
});
|
|
@@ -3116,11 +3250,14 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
3116
3250
|
alpha: globalAlpha = 255,
|
|
3117
3251
|
blendFn = sourceOverPerfect
|
|
3118
3252
|
} = opts;
|
|
3119
|
-
if (globalAlpha === 0) return;
|
|
3253
|
+
if (globalAlpha === 0) return false;
|
|
3120
3254
|
const baseSrcAlpha = color >>> 24;
|
|
3121
3255
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
3122
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
3123
|
-
let x = targetX
|
|
3256
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
3257
|
+
let x = targetX;
|
|
3258
|
+
let y = targetY;
|
|
3259
|
+
let w = width;
|
|
3260
|
+
let h = height;
|
|
3124
3261
|
if (x < 0) {
|
|
3125
3262
|
w += x;
|
|
3126
3263
|
x = 0;
|
|
@@ -3131,69 +3268,97 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
3131
3268
|
}
|
|
3132
3269
|
const actualW = Math.min(w, dst.width - x);
|
|
3133
3270
|
const actualH = Math.min(h, dst.height - y);
|
|
3134
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3271
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3135
3272
|
let finalSrcColor = color;
|
|
3136
3273
|
if (globalAlpha < 255) {
|
|
3137
3274
|
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
3138
|
-
if (a === 0 && !isOverwrite) return;
|
|
3275
|
+
if (a === 0 && !isOverwrite) return false;
|
|
3139
3276
|
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
3140
3277
|
}
|
|
3141
3278
|
const dst32 = dst.data32;
|
|
3142
3279
|
const dw = dst.width;
|
|
3143
3280
|
let dIdx = y * dw + x | 0;
|
|
3144
3281
|
const dStride = dw - actualW | 0;
|
|
3282
|
+
let didChange = false;
|
|
3145
3283
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3146
3284
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3147
|
-
|
|
3285
|
+
const current = dst32[dIdx];
|
|
3286
|
+
const next = blendFn(finalSrcColor, current);
|
|
3287
|
+
if (current !== next) {
|
|
3288
|
+
dst32[dIdx] = next;
|
|
3289
|
+
didChange = true;
|
|
3290
|
+
}
|
|
3148
3291
|
dIdx++;
|
|
3149
3292
|
}
|
|
3150
3293
|
dIdx += dStride;
|
|
3151
3294
|
}
|
|
3295
|
+
return didChange;
|
|
3152
3296
|
}
|
|
3153
3297
|
|
|
3154
3298
|
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
3155
|
-
var
|
|
3299
|
+
var defaults12 = {
|
|
3156
3300
|
blendColorPixelData
|
|
3157
3301
|
};
|
|
3158
|
-
var mutatorBlendColor = ((writer, deps =
|
|
3302
|
+
var mutatorBlendColor = ((writer, deps = defaults12) => {
|
|
3159
3303
|
const {
|
|
3160
|
-
blendColorPixelData: blendColorPixelData2 =
|
|
3304
|
+
blendColorPixelData: blendColorPixelData2 = defaults12.blendColorPixelData
|
|
3161
3305
|
} = deps;
|
|
3162
3306
|
return {
|
|
3163
3307
|
blendColor(color, opts = {}) {
|
|
3308
|
+
const target = writer.config.target;
|
|
3164
3309
|
const {
|
|
3165
3310
|
x = 0,
|
|
3166
3311
|
y = 0,
|
|
3167
|
-
w =
|
|
3168
|
-
h =
|
|
3312
|
+
w = target.width,
|
|
3313
|
+
h = target.height
|
|
3169
3314
|
} = opts;
|
|
3170
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3171
|
-
blendColorPixelData2(
|
|
3315
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3316
|
+
return didChange(blendColorPixelData2(target, color, opts));
|
|
3172
3317
|
}
|
|
3173
3318
|
};
|
|
3174
3319
|
});
|
|
3175
3320
|
|
|
3321
|
+
// src/PixelData/blendPixel.ts
|
|
3322
|
+
function blendPixel(target, x, y, color, alpha = 255, blendFn = sourceOverPerfect) {
|
|
3323
|
+
if (alpha === 0) return false;
|
|
3324
|
+
let width = target.width;
|
|
3325
|
+
let height = target.height;
|
|
3326
|
+
if (x < 0 || x >= width || y < 0 || y >= height) return false;
|
|
3327
|
+
let srcAlpha = color >>> 24;
|
|
3328
|
+
let isOverwrite = blendFn.isOverwrite;
|
|
3329
|
+
if (srcAlpha === 0 && !isOverwrite) return false;
|
|
3330
|
+
let dst32 = target.data32;
|
|
3331
|
+
let index = y * width + x;
|
|
3332
|
+
let finalColor = color;
|
|
3333
|
+
if (alpha !== 255) {
|
|
3334
|
+
let finalAlpha = srcAlpha * alpha + 128 >> 8;
|
|
3335
|
+
if (finalAlpha === 0 && !isOverwrite) return false;
|
|
3336
|
+
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
3337
|
+
}
|
|
3338
|
+
let current = dst32[index];
|
|
3339
|
+
let next = blendFn(finalColor, current);
|
|
3340
|
+
if (current !== next) {
|
|
3341
|
+
dst32[index] = next;
|
|
3342
|
+
return true;
|
|
3343
|
+
}
|
|
3344
|
+
return false;
|
|
3345
|
+
}
|
|
3346
|
+
|
|
3176
3347
|
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
3177
|
-
|
|
3348
|
+
var defaults13 = {
|
|
3349
|
+
blendPixel
|
|
3350
|
+
};
|
|
3351
|
+
var mutatorBlendPixel = ((writer, deps = defaults13) => {
|
|
3352
|
+
const {
|
|
3353
|
+
blendPixel: blendPixel2 = defaults13.blendPixel
|
|
3354
|
+
} = deps;
|
|
3178
3355
|
return {
|
|
3179
|
-
blendPixel(x, y, color, alpha
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
let height = target.height;
|
|
3183
|
-
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
3184
|
-
writer.accumulator.storeTileBeforeState(x, y);
|
|
3185
|
-
let index = y * width + x;
|
|
3186
|
-
let bg = target.data32[index];
|
|
3187
|
-
let finalColor = color;
|
|
3188
|
-
if (alpha < 255) {
|
|
3189
|
-
let baseSrcAlpha = color >>> 24;
|
|
3190
|
-
let finalAlpha = baseSrcAlpha * alpha + 128 >> 8;
|
|
3191
|
-
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
3192
|
-
}
|
|
3193
|
-
target.data32[index] = blendFn(finalColor, bg);
|
|
3356
|
+
blendPixel(x, y, color, alpha, blendFn) {
|
|
3357
|
+
const didChange = writer.accumulator.storePixelBeforeState(x, y);
|
|
3358
|
+
return didChange(blendPixel2(writer.config.target, x, y, color, alpha, blendFn));
|
|
3194
3359
|
}
|
|
3195
3360
|
};
|
|
3196
|
-
}
|
|
3361
|
+
});
|
|
3197
3362
|
|
|
3198
3363
|
// src/PixelData/blendPixelData.ts
|
|
3199
3364
|
function blendPixelData(dst, src, opts = {}) {
|
|
@@ -3207,7 +3372,7 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3207
3372
|
alpha: globalAlpha = 255,
|
|
3208
3373
|
blendFn = sourceOverPerfect
|
|
3209
3374
|
} = opts;
|
|
3210
|
-
if (globalAlpha === 0) return;
|
|
3375
|
+
if (globalAlpha === 0) return false;
|
|
3211
3376
|
let x = targetX;
|
|
3212
3377
|
let y = targetY;
|
|
3213
3378
|
let sx = sourceX;
|
|
@@ -3238,7 +3403,7 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3238
3403
|
}
|
|
3239
3404
|
const actualW = Math.min(w, dst.width - x);
|
|
3240
3405
|
const actualH = Math.min(h, dst.height - y);
|
|
3241
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3406
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3242
3407
|
const dst32 = dst.data32;
|
|
3243
3408
|
const src32 = src.data32;
|
|
3244
3409
|
const dw = dst.width;
|
|
@@ -3249,6 +3414,7 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3249
3414
|
const sStride = sw - actualW | 0;
|
|
3250
3415
|
const isOpaque = globalAlpha === 255;
|
|
3251
3416
|
const isOverwrite = blendFn.isOverwrite;
|
|
3417
|
+
let didChange = false;
|
|
3252
3418
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3253
3419
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3254
3420
|
const srcCol = src32[sIdx];
|
|
@@ -3268,22 +3434,28 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3268
3434
|
}
|
|
3269
3435
|
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3270
3436
|
}
|
|
3271
|
-
|
|
3437
|
+
const current = dst32[dIdx];
|
|
3438
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3439
|
+
if (current !== next) {
|
|
3440
|
+
dst32[dIdx] = next;
|
|
3441
|
+
didChange = true;
|
|
3442
|
+
}
|
|
3272
3443
|
dIdx++;
|
|
3273
3444
|
sIdx++;
|
|
3274
3445
|
}
|
|
3275
3446
|
dIdx += dStride;
|
|
3276
3447
|
sIdx += sStride;
|
|
3277
3448
|
}
|
|
3449
|
+
return didChange;
|
|
3278
3450
|
}
|
|
3279
3451
|
|
|
3280
3452
|
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
3281
|
-
var
|
|
3453
|
+
var defaults14 = {
|
|
3282
3454
|
blendPixelData
|
|
3283
3455
|
};
|
|
3284
|
-
var mutatorBlendPixelData = ((writer, deps =
|
|
3456
|
+
var mutatorBlendPixelData = ((writer, deps = defaults14) => {
|
|
3285
3457
|
const {
|
|
3286
|
-
blendPixelData: blendPixelData2 =
|
|
3458
|
+
blendPixelData: blendPixelData2 = defaults14.blendPixelData
|
|
3287
3459
|
} = deps;
|
|
3288
3460
|
return {
|
|
3289
3461
|
blendPixelData(src, opts = {}) {
|
|
@@ -3293,8 +3465,8 @@ var mutatorBlendPixelData = ((writer, deps = defaults12) => {
|
|
|
3293
3465
|
w = src.width,
|
|
3294
3466
|
h = src.height
|
|
3295
3467
|
} = opts;
|
|
3296
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3297
|
-
blendPixelData2(writer.target, src, opts);
|
|
3468
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3469
|
+
return didChange(blendPixelData2(writer.config.target, src, opts));
|
|
3298
3470
|
}
|
|
3299
3471
|
};
|
|
3300
3472
|
});
|
|
@@ -3314,7 +3486,7 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3314
3486
|
my = 0,
|
|
3315
3487
|
invertMask = false
|
|
3316
3488
|
} = opts;
|
|
3317
|
-
if (globalAlpha === 0) return;
|
|
3489
|
+
if (globalAlpha === 0) return false;
|
|
3318
3490
|
let x = targetX;
|
|
3319
3491
|
let y = targetY;
|
|
3320
3492
|
let sx = sourceX;
|
|
@@ -3345,7 +3517,7 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3345
3517
|
}
|
|
3346
3518
|
const actualW = Math.min(w, dst.width - x);
|
|
3347
3519
|
const actualH = Math.min(h, dst.height - y);
|
|
3348
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3520
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3349
3521
|
const dw = dst.width;
|
|
3350
3522
|
const sw = src.width;
|
|
3351
3523
|
const mPitch = alphaMask.w;
|
|
@@ -3362,6 +3534,7 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3362
3534
|
const mStride = mPitch - actualW | 0;
|
|
3363
3535
|
const isOpaque = globalAlpha === 255;
|
|
3364
3536
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
3537
|
+
let didChange = false;
|
|
3365
3538
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3366
3539
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3367
3540
|
const mVal = maskData[mIdx];
|
|
@@ -3403,7 +3576,12 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3403
3576
|
}
|
|
3404
3577
|
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3405
3578
|
}
|
|
3406
|
-
|
|
3579
|
+
const current = dst32[dIdx];
|
|
3580
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3581
|
+
if (current !== next) {
|
|
3582
|
+
dst32[dIdx] = next;
|
|
3583
|
+
didChange = true;
|
|
3584
|
+
}
|
|
3407
3585
|
dIdx++;
|
|
3408
3586
|
sIdx++;
|
|
3409
3587
|
mIdx++;
|
|
@@ -3412,15 +3590,16 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3412
3590
|
sIdx += sStride;
|
|
3413
3591
|
mIdx += mStride;
|
|
3414
3592
|
}
|
|
3593
|
+
return didChange;
|
|
3415
3594
|
}
|
|
3416
3595
|
|
|
3417
3596
|
// src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts
|
|
3418
|
-
var
|
|
3597
|
+
var defaults15 = {
|
|
3419
3598
|
blendPixelDataAlphaMask
|
|
3420
3599
|
};
|
|
3421
|
-
var mutatorBlendPixelDataAlphaMask = ((writer, deps =
|
|
3600
|
+
var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults15) => {
|
|
3422
3601
|
const {
|
|
3423
|
-
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 =
|
|
3602
|
+
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults15.blendPixelDataAlphaMask
|
|
3424
3603
|
} = deps;
|
|
3425
3604
|
return {
|
|
3426
3605
|
blendPixelDataAlphaMask(src, mask, opts = {}) {
|
|
@@ -3428,8 +3607,8 @@ var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults13) => {
|
|
|
3428
3607
|
const y = opts.y ?? 0;
|
|
3429
3608
|
const w = opts.w ?? src.width;
|
|
3430
3609
|
const h = opts.h ?? src.height;
|
|
3431
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3432
|
-
blendPixelDataAlphaMask2(writer.target, src, mask, opts);
|
|
3610
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3611
|
+
return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
|
|
3433
3612
|
}
|
|
3434
3613
|
};
|
|
3435
3614
|
});
|
|
@@ -3449,7 +3628,7 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3449
3628
|
my = 0,
|
|
3450
3629
|
invertMask = false
|
|
3451
3630
|
} = opts;
|
|
3452
|
-
if (globalAlpha === 0) return;
|
|
3631
|
+
if (globalAlpha === 0) return false;
|
|
3453
3632
|
let x = targetX;
|
|
3454
3633
|
let y = targetY;
|
|
3455
3634
|
let sx = sourceX;
|
|
@@ -3480,7 +3659,7 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3480
3659
|
}
|
|
3481
3660
|
const actualW = Math.min(w, dst.width - x);
|
|
3482
3661
|
const actualH = Math.min(h, dst.height - y);
|
|
3483
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3662
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3484
3663
|
const dx = x - targetX | 0;
|
|
3485
3664
|
const dy = y - targetY | 0;
|
|
3486
3665
|
const dst32 = dst.data32;
|
|
@@ -3498,6 +3677,7 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3498
3677
|
const skipVal = invertMask ? 1 : 0;
|
|
3499
3678
|
const isOpaque = globalAlpha === 255;
|
|
3500
3679
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
3680
|
+
let didChange = false;
|
|
3501
3681
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3502
3682
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3503
3683
|
if (maskData[mIdx] === skipVal) {
|
|
@@ -3525,7 +3705,12 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3525
3705
|
}
|
|
3526
3706
|
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3527
3707
|
}
|
|
3528
|
-
|
|
3708
|
+
const current = dst32[dIdx];
|
|
3709
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3710
|
+
if (current !== next) {
|
|
3711
|
+
dst32[dIdx] = next;
|
|
3712
|
+
didChange = true;
|
|
3713
|
+
}
|
|
3529
3714
|
dIdx++;
|
|
3530
3715
|
sIdx++;
|
|
3531
3716
|
mIdx++;
|
|
@@ -3534,15 +3719,16 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3534
3719
|
sIdx += sStride;
|
|
3535
3720
|
mIdx += mStride;
|
|
3536
3721
|
}
|
|
3722
|
+
return didChange;
|
|
3537
3723
|
}
|
|
3538
3724
|
|
|
3539
3725
|
// src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts
|
|
3540
|
-
var
|
|
3726
|
+
var defaults16 = {
|
|
3541
3727
|
blendPixelDataBinaryMask
|
|
3542
3728
|
};
|
|
3543
|
-
var mutatorBlendPixelDataBinaryMask = ((writer, deps =
|
|
3729
|
+
var mutatorBlendPixelDataBinaryMask = ((writer, deps = defaults16) => {
|
|
3544
3730
|
const {
|
|
3545
|
-
blendPixelDataBinaryMask: blendPixelDataBinaryMask2 =
|
|
3731
|
+
blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults16.blendPixelDataBinaryMask
|
|
3546
3732
|
} = deps;
|
|
3547
3733
|
return {
|
|
3548
3734
|
blendPixelDataBinaryMask(src, mask, opts = {}) {
|
|
@@ -3550,15 +3736,15 @@ var mutatorBlendPixelDataBinaryMask = ((writer, deps = defaults14) => {
|
|
|
3550
3736
|
const y = opts.y ?? 0;
|
|
3551
3737
|
const w = opts.w ?? src.width;
|
|
3552
3738
|
const h = opts.h ?? src.height;
|
|
3553
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3554
|
-
blendPixelDataBinaryMask2(writer.target, src, mask, opts);
|
|
3739
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3740
|
+
return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
|
|
3555
3741
|
}
|
|
3556
3742
|
};
|
|
3557
3743
|
});
|
|
3558
3744
|
|
|
3559
|
-
// src/PixelData/
|
|
3745
|
+
// src/PixelData/fillPixelDataFast.ts
|
|
3560
3746
|
var SCRATCH_RECT = makeClippedRect();
|
|
3561
|
-
function
|
|
3747
|
+
function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
|
|
3562
3748
|
let x;
|
|
3563
3749
|
let y;
|
|
3564
3750
|
let w;
|
|
@@ -3601,55 +3787,111 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
|
3601
3787
|
}
|
|
3602
3788
|
|
|
3603
3789
|
// src/History/PixelMutator/mutatorClear.ts
|
|
3604
|
-
var
|
|
3605
|
-
fillPixelData
|
|
3790
|
+
var defaults17 = {
|
|
3791
|
+
fillPixelData: fillPixelDataFast
|
|
3606
3792
|
};
|
|
3607
|
-
var mutatorClear = ((writer, deps =
|
|
3793
|
+
var mutatorClear = ((writer, deps = defaults17) => {
|
|
3608
3794
|
const {
|
|
3609
|
-
fillPixelData: fillPixelData2 =
|
|
3795
|
+
fillPixelData: fillPixelData2 = defaults17.fillPixelData
|
|
3610
3796
|
} = deps;
|
|
3611
3797
|
return {
|
|
3612
3798
|
clear(rect = {}) {
|
|
3799
|
+
const target = writer.config.target;
|
|
3613
3800
|
const x = rect.x ?? 0;
|
|
3614
3801
|
const y = rect.y ?? 0;
|
|
3615
|
-
const w = rect.w ??
|
|
3616
|
-
const h = rect.h ??
|
|
3802
|
+
const w = rect.w ?? target.width;
|
|
3803
|
+
const h = rect.h ?? target.height;
|
|
3617
3804
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3618
|
-
fillPixelData2(
|
|
3805
|
+
fillPixelData2(target, 0, x, y, w, h);
|
|
3619
3806
|
}
|
|
3620
3807
|
};
|
|
3621
3808
|
});
|
|
3622
3809
|
|
|
3810
|
+
// src/PixelData/fillPixelData.ts
|
|
3811
|
+
var SCRATCH_RECT2 = makeClippedRect();
|
|
3812
|
+
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
3813
|
+
let x;
|
|
3814
|
+
let y;
|
|
3815
|
+
let w;
|
|
3816
|
+
let h;
|
|
3817
|
+
if (typeof _x === "object") {
|
|
3818
|
+
x = _x.x ?? 0;
|
|
3819
|
+
y = _x.y ?? 0;
|
|
3820
|
+
w = _x.w ?? dst.width;
|
|
3821
|
+
h = _x.h ?? dst.height;
|
|
3822
|
+
} else if (typeof _x === "number") {
|
|
3823
|
+
x = _x;
|
|
3824
|
+
y = _y;
|
|
3825
|
+
w = _w;
|
|
3826
|
+
h = _h;
|
|
3827
|
+
} else {
|
|
3828
|
+
x = 0;
|
|
3829
|
+
y = 0;
|
|
3830
|
+
w = dst.width;
|
|
3831
|
+
h = dst.height;
|
|
3832
|
+
}
|
|
3833
|
+
const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT2);
|
|
3834
|
+
if (!clip.inBounds) return false;
|
|
3835
|
+
const {
|
|
3836
|
+
x: finalX,
|
|
3837
|
+
y: finalY,
|
|
3838
|
+
w: actualW,
|
|
3839
|
+
h: actualH
|
|
3840
|
+
} = clip;
|
|
3841
|
+
const dst32 = dst.data32;
|
|
3842
|
+
const dw = dst.width;
|
|
3843
|
+
let hasChanged = false;
|
|
3844
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
3845
|
+
const rowOffset = (finalY + iy) * dw;
|
|
3846
|
+
const start = rowOffset + finalX;
|
|
3847
|
+
const end = start + actualW;
|
|
3848
|
+
for (let i = start; i < end; i++) {
|
|
3849
|
+
if (dst32[i] !== color) {
|
|
3850
|
+
dst32[i] = color;
|
|
3851
|
+
hasChanged = true;
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
return hasChanged;
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3623
3858
|
// src/History/PixelMutator/mutatorFill.ts
|
|
3624
|
-
var
|
|
3859
|
+
var defaults18 = {
|
|
3625
3860
|
fillPixelData
|
|
3626
3861
|
};
|
|
3627
|
-
var mutatorFill = ((writer, deps =
|
|
3862
|
+
var mutatorFill = ((writer, deps = defaults18) => {
|
|
3628
3863
|
const {
|
|
3629
|
-
fillPixelData: fillPixelData2 =
|
|
3864
|
+
fillPixelData: fillPixelData2 = defaults18.fillPixelData
|
|
3630
3865
|
} = deps;
|
|
3631
3866
|
return {
|
|
3632
|
-
fill(color,
|
|
3633
|
-
const
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3867
|
+
fill(color, x = 0, y = 0, w = writer.config.target.width, h = writer.config.target.height) {
|
|
3868
|
+
const target = writer.config.target;
|
|
3869
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3870
|
+
return didChange(fillPixelData2(target, color, x, y, w, h));
|
|
3871
|
+
}
|
|
3872
|
+
};
|
|
3873
|
+
});
|
|
3874
|
+
var mutatorFillRect = ((writer, deps = defaults18) => {
|
|
3875
|
+
const {
|
|
3876
|
+
fillPixelData: fillPixelData2 = defaults18.fillPixelData
|
|
3877
|
+
} = deps;
|
|
3878
|
+
return {
|
|
3879
|
+
fillRect(color, rect) {
|
|
3880
|
+
const target = writer.config.target;
|
|
3881
|
+
const didChange = writer.accumulator.storeRegionBeforeState(rect.x, rect.y, rect.w, rect.h);
|
|
3882
|
+
return didChange(fillPixelData2(target, color, rect.x, rect.y, rect.w, rect.h));
|
|
3641
3883
|
}
|
|
3642
3884
|
};
|
|
3643
3885
|
});
|
|
3644
3886
|
|
|
3645
3887
|
// src/PixelData/fillPixelDataBinaryMask.ts
|
|
3646
|
-
var
|
|
3888
|
+
var SCRATCH_RECT3 = makeClippedRect();
|
|
3647
3889
|
function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
3648
|
-
if (alpha === 0) return;
|
|
3890
|
+
if (alpha === 0) return false;
|
|
3649
3891
|
const maskW = mask.w;
|
|
3650
3892
|
const maskH = mask.h;
|
|
3651
|
-
const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height,
|
|
3652
|
-
if (!clip.inBounds) return;
|
|
3893
|
+
const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height, SCRATCH_RECT3);
|
|
3894
|
+
if (!clip.inBounds) return false;
|
|
3653
3895
|
const {
|
|
3654
3896
|
x: finalX,
|
|
3655
3897
|
y: finalY,
|
|
@@ -3666,6 +3908,7 @@ function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
|
3666
3908
|
const a = baseSrcAlpha * alpha + 128 >> 8;
|
|
3667
3909
|
finalCol = (colorRGB | a << 24) >>> 0;
|
|
3668
3910
|
}
|
|
3911
|
+
let hasChanged = false;
|
|
3669
3912
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3670
3913
|
const currentY = finalY + iy;
|
|
3671
3914
|
const maskY = currentY - y;
|
|
@@ -3676,30 +3919,35 @@ function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
|
3676
3919
|
const maskX = currentX - x;
|
|
3677
3920
|
const maskIndex = maskOffset + maskX;
|
|
3678
3921
|
if (maskData[maskIndex]) {
|
|
3679
|
-
dst32[dstRowOffset + currentX]
|
|
3922
|
+
const current = dst32[dstRowOffset + currentX];
|
|
3923
|
+
if (current !== finalCol) {
|
|
3924
|
+
dst32[dstRowOffset + currentX] = finalCol;
|
|
3925
|
+
hasChanged = true;
|
|
3926
|
+
}
|
|
3680
3927
|
}
|
|
3681
3928
|
}
|
|
3682
3929
|
}
|
|
3930
|
+
return hasChanged;
|
|
3683
3931
|
}
|
|
3684
3932
|
|
|
3685
3933
|
// src/History/PixelMutator/mutatorFillBinaryMask.ts
|
|
3686
|
-
var
|
|
3934
|
+
var defaults19 = {
|
|
3687
3935
|
fillPixelDataBinaryMask
|
|
3688
3936
|
};
|
|
3689
|
-
var mutatorFillBinaryMask = ((writer, deps =
|
|
3937
|
+
var mutatorFillBinaryMask = ((writer, deps = defaults19) => {
|
|
3690
3938
|
const {
|
|
3691
|
-
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 =
|
|
3939
|
+
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults19.fillPixelDataBinaryMask
|
|
3692
3940
|
} = deps;
|
|
3693
3941
|
return {
|
|
3694
3942
|
fillBinaryMask(color, mask, alpha = 255, x = 0, y = 0) {
|
|
3695
|
-
writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
|
|
3696
|
-
fillPixelDataBinaryMask2(writer.target, color, mask, alpha, x, y);
|
|
3943
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
|
|
3944
|
+
return didChange(fillPixelDataBinaryMask2(writer.config.target, color, mask, alpha, x, y));
|
|
3697
3945
|
}
|
|
3698
3946
|
};
|
|
3699
3947
|
});
|
|
3700
3948
|
|
|
3701
3949
|
// src/PixelData/invertPixelData.ts
|
|
3702
|
-
var
|
|
3950
|
+
var SCRATCH_RECT4 = makeClippedRect();
|
|
3703
3951
|
function invertPixelData(pixelData, opts = {}) {
|
|
3704
3952
|
const dst = pixelData;
|
|
3705
3953
|
const {
|
|
@@ -3712,8 +3960,8 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3712
3960
|
my = 0,
|
|
3713
3961
|
invertMask = false
|
|
3714
3962
|
} = opts;
|
|
3715
|
-
const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height,
|
|
3716
|
-
if (!clip.inBounds) return;
|
|
3963
|
+
const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT4);
|
|
3964
|
+
if (!clip.inBounds) return false;
|
|
3717
3965
|
const {
|
|
3718
3966
|
x,
|
|
3719
3967
|
y,
|
|
@@ -3753,26 +4001,28 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3753
4001
|
dIdx += dStride;
|
|
3754
4002
|
}
|
|
3755
4003
|
}
|
|
4004
|
+
return true;
|
|
3756
4005
|
}
|
|
3757
4006
|
|
|
3758
4007
|
// src/History/PixelMutator/mutatorInvert.ts
|
|
3759
|
-
var
|
|
4008
|
+
var defaults20 = {
|
|
3760
4009
|
invertPixelData
|
|
3761
4010
|
};
|
|
3762
|
-
var mutatorInvert = ((writer, deps =
|
|
4011
|
+
var mutatorInvert = ((writer, deps = defaults20) => {
|
|
3763
4012
|
const {
|
|
3764
|
-
invertPixelData: invertPixelData2 =
|
|
4013
|
+
invertPixelData: invertPixelData2 = defaults20.invertPixelData
|
|
3765
4014
|
} = deps;
|
|
3766
4015
|
return {
|
|
3767
4016
|
invert(opts = {}) {
|
|
4017
|
+
const target = writer.config.target;
|
|
3768
4018
|
const {
|
|
3769
4019
|
x = 0,
|
|
3770
4020
|
y = 0,
|
|
3771
|
-
w =
|
|
3772
|
-
h =
|
|
4021
|
+
w = target.width,
|
|
4022
|
+
h = target.height
|
|
3773
4023
|
} = opts;
|
|
3774
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3775
|
-
invertPixelData2(
|
|
4024
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
4025
|
+
return didChange(invertPixelData2(target, opts));
|
|
3776
4026
|
}
|
|
3777
4027
|
};
|
|
3778
4028
|
});
|
|
@@ -3783,7 +4033,6 @@ function makeFullPixelMutator(writer) {
|
|
|
3783
4033
|
// @sort
|
|
3784
4034
|
...mutatorApplyAlphaMask(writer),
|
|
3785
4035
|
...mutatorApplyBinaryMask(writer),
|
|
3786
|
-
...mutatorApplyCircleBrush(writer),
|
|
3787
4036
|
...mutatorApplyCircleBrushStroke(writer),
|
|
3788
4037
|
...mutatorApplyCirclePencil(writer),
|
|
3789
4038
|
...mutatorApplyCirclePencilStroke(writer),
|
|
@@ -3792,6 +4041,7 @@ function makeFullPixelMutator(writer) {
|
|
|
3792
4041
|
...mutatorApplyRectPencil(writer),
|
|
3793
4042
|
...mutatorApplyRectPencilStroke(writer),
|
|
3794
4043
|
...mutatorBlendColor(writer),
|
|
4044
|
+
...mutatorBlendColorCircleMask(writer),
|
|
3795
4045
|
...mutatorBlendPixel(writer),
|
|
3796
4046
|
...mutatorBlendPixelData(writer),
|
|
3797
4047
|
...mutatorBlendPixelDataAlphaMask(writer),
|
|
@@ -3799,50 +4049,96 @@ function makeFullPixelMutator(writer) {
|
|
|
3799
4049
|
...mutatorClear(writer),
|
|
3800
4050
|
...mutatorFill(writer),
|
|
3801
4051
|
...mutatorFillBinaryMask(writer),
|
|
4052
|
+
...mutatorFillRect(writer),
|
|
3802
4053
|
...mutatorInvert(writer)
|
|
3803
4054
|
};
|
|
3804
4055
|
}
|
|
3805
4056
|
|
|
4057
|
+
// src/PixelTile/PixelTile.ts
|
|
4058
|
+
var PixelTile = class {
|
|
4059
|
+
constructor(id, tx, ty, tileSize, tileArea) {
|
|
4060
|
+
this.id = id;
|
|
4061
|
+
this.tx = tx;
|
|
4062
|
+
this.ty = ty;
|
|
4063
|
+
this.width = this.height = tileSize;
|
|
4064
|
+
this.data32 = new Uint32Array(tileArea);
|
|
4065
|
+
const data8 = new Uint8ClampedArray(this.data32.buffer);
|
|
4066
|
+
this.imageData = new ImageData(data8, tileSize, tileSize);
|
|
4067
|
+
}
|
|
4068
|
+
data32;
|
|
4069
|
+
width;
|
|
4070
|
+
height;
|
|
4071
|
+
imageData;
|
|
4072
|
+
};
|
|
4073
|
+
|
|
4074
|
+
// src/PixelTile/PixelTilePool.ts
|
|
4075
|
+
var PixelTilePool = class {
|
|
4076
|
+
pool;
|
|
4077
|
+
tileSize;
|
|
4078
|
+
tileArea;
|
|
4079
|
+
constructor(config) {
|
|
4080
|
+
this.pool = [];
|
|
4081
|
+
this.tileSize = config.tileSize;
|
|
4082
|
+
this.tileArea = config.tileArea;
|
|
4083
|
+
}
|
|
4084
|
+
getTile(id, tx, ty) {
|
|
4085
|
+
let tile = this.pool.pop();
|
|
4086
|
+
if (tile) {
|
|
4087
|
+
tile.id = id;
|
|
4088
|
+
tile.tx = tx;
|
|
4089
|
+
tile.ty = ty;
|
|
4090
|
+
tile.data32.fill(0);
|
|
4091
|
+
return tile;
|
|
4092
|
+
}
|
|
4093
|
+
return new PixelTile(id, tx, ty, this.tileSize, this.tileArea);
|
|
4094
|
+
}
|
|
4095
|
+
releaseTile(tile) {
|
|
4096
|
+
this.pool.push(tile);
|
|
4097
|
+
}
|
|
4098
|
+
releaseTiles(tiles) {
|
|
4099
|
+
let length = tiles.length;
|
|
4100
|
+
for (let i = 0; i < length; i++) {
|
|
4101
|
+
let tile = tiles[i];
|
|
4102
|
+
if (tile) {
|
|
4103
|
+
this.pool.push(tile);
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
tiles.length = 0;
|
|
4107
|
+
}
|
|
4108
|
+
};
|
|
4109
|
+
|
|
3806
4110
|
// src/History/PixelWriter.ts
|
|
3807
4111
|
var PixelWriter = class {
|
|
3808
|
-
target;
|
|
3809
4112
|
historyManager;
|
|
3810
4113
|
accumulator;
|
|
4114
|
+
historyActionFactory;
|
|
3811
4115
|
config;
|
|
3812
4116
|
mutator;
|
|
3813
4117
|
constructor(target, mutatorFactory, {
|
|
3814
4118
|
tileSize = 256,
|
|
3815
4119
|
maxHistorySteps = 50,
|
|
3816
|
-
historyManager = new HistoryManager(maxHistorySteps)
|
|
4120
|
+
historyManager = new HistoryManager(maxHistorySteps),
|
|
4121
|
+
historyActionFactory = makeHistoryAction,
|
|
4122
|
+
pixelTilePool
|
|
3817
4123
|
} = {}) {
|
|
3818
|
-
this.
|
|
3819
|
-
this.config = new PixelEngineConfig(tileSize);
|
|
4124
|
+
this.config = new PixelEngineConfig(tileSize, target);
|
|
3820
4125
|
this.historyManager = historyManager;
|
|
3821
|
-
|
|
4126
|
+
pixelTilePool ??= new PixelTilePool(this.config);
|
|
4127
|
+
this.accumulator = new PixelAccumulator(this.config, pixelTilePool);
|
|
4128
|
+
this.historyActionFactory = historyActionFactory;
|
|
3822
4129
|
this.mutator = mutatorFactory(this);
|
|
3823
4130
|
}
|
|
3824
|
-
withHistory(cb) {
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
const patch =
|
|
3833
|
-
|
|
3834
|
-
afterTiles
|
|
3835
|
-
};
|
|
3836
|
-
const target = this.target;
|
|
3837
|
-
const tileSize = this.config.tileSize;
|
|
3838
|
-
const accumulator = this.accumulator;
|
|
3839
|
-
const action = {
|
|
3840
|
-
undo: () => applyPatchTiles(target, patch.beforeTiles, tileSize),
|
|
3841
|
-
redo: () => applyPatchTiles(target, patch.afterTiles, tileSize),
|
|
3842
|
-
dispose: () => accumulator.recyclePatch(patch)
|
|
3843
|
-
};
|
|
4131
|
+
withHistory(cb, after, afterUndo, afterRedo) {
|
|
4132
|
+
try {
|
|
4133
|
+
cb(this.mutator);
|
|
4134
|
+
} catch (e) {
|
|
4135
|
+
this.accumulator.rollback();
|
|
4136
|
+
throw e;
|
|
4137
|
+
}
|
|
4138
|
+
if (this.accumulator.beforeTiles.length === 0) return;
|
|
4139
|
+
const patch = this.accumulator.extractPatch();
|
|
4140
|
+
const action = this.historyActionFactory(this, patch, after, afterUndo, afterRedo);
|
|
3844
4141
|
this.historyManager.commit(action);
|
|
3845
|
-
this.accumulator.reset();
|
|
3846
4142
|
}
|
|
3847
4143
|
};
|
|
3848
4144
|
|
|
@@ -4000,11 +4296,10 @@ function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0)
|
|
|
4000
4296
|
function makeReusableImageData() {
|
|
4001
4297
|
let imageData = null;
|
|
4002
4298
|
return function getReusableImageData(width, height) {
|
|
4003
|
-
|
|
4004
|
-
const widthMatches = hasInstance && imageData.width === width;
|
|
4005
|
-
const heightMatches = hasInstance && imageData.height === height;
|
|
4006
|
-
if (!widthMatches || !heightMatches) {
|
|
4299
|
+
if (imageData === null || imageData.width !== width || imageData.height !== height) {
|
|
4007
4300
|
imageData = new ImageData(width, height);
|
|
4301
|
+
} else {
|
|
4302
|
+
imageData.data.fill(0);
|
|
4008
4303
|
}
|
|
4009
4304
|
return imageData;
|
|
4010
4305
|
};
|
|
@@ -4411,8 +4706,8 @@ function makeBinaryMask(w, h, data) {
|
|
|
4411
4706
|
};
|
|
4412
4707
|
}
|
|
4413
4708
|
|
|
4414
|
-
// src/Mask/
|
|
4415
|
-
function
|
|
4709
|
+
// src/Mask/CircleAlphaMask.ts
|
|
4710
|
+
function makeCircleAlphaMask(size, fallOff = () => 1) {
|
|
4416
4711
|
const area = size * size;
|
|
4417
4712
|
const data = new Uint8Array(area);
|
|
4418
4713
|
const radius = size / 2;
|
|
@@ -4440,8 +4735,8 @@ function makeCircleBrushAlphaMask(size, fallOff = () => 1) {
|
|
|
4440
4735
|
};
|
|
4441
4736
|
}
|
|
4442
4737
|
|
|
4443
|
-
// src/Mask/
|
|
4444
|
-
function
|
|
4738
|
+
// src/Mask/CircleBinaryMask.ts
|
|
4739
|
+
function makeCircleBinaryMask(size) {
|
|
4445
4740
|
const area = size * size;
|
|
4446
4741
|
const data = new Uint8Array(area);
|
|
4447
4742
|
const radius = size / 2;
|
|
@@ -4737,57 +5032,6 @@ function setMaskData(mask, width, height, data) {
|
|
|
4737
5032
|
mask.data = data;
|
|
4738
5033
|
}
|
|
4739
5034
|
|
|
4740
|
-
// src/MaskRect/subtractBinaryMaskRects.ts
|
|
4741
|
-
function subtractBinaryMaskRects(current, subtracting) {
|
|
4742
|
-
let result = [...current];
|
|
4743
|
-
for (const sub of subtracting) {
|
|
4744
|
-
const next = [];
|
|
4745
|
-
for (const r of result) {
|
|
4746
|
-
const ix = Math.max(r.x, sub.x);
|
|
4747
|
-
const iy = Math.max(r.y, sub.y);
|
|
4748
|
-
const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
|
|
4749
|
-
const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
|
|
4750
|
-
if (ix >= ix2 || iy >= iy2) {
|
|
4751
|
-
next.push(r);
|
|
4752
|
-
continue;
|
|
4753
|
-
}
|
|
4754
|
-
if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
|
|
4755
|
-
if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
|
|
4756
|
-
if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
|
|
4757
|
-
if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
|
|
4758
|
-
}
|
|
4759
|
-
result = next;
|
|
4760
|
-
}
|
|
4761
|
-
return result;
|
|
4762
|
-
}
|
|
4763
|
-
function pushPiece(dest, r, x, y, w, h) {
|
|
4764
|
-
if (r.data === null || r.data === void 0) {
|
|
4765
|
-
dest.push({
|
|
4766
|
-
x,
|
|
4767
|
-
y,
|
|
4768
|
-
w,
|
|
4769
|
-
h,
|
|
4770
|
-
data: null,
|
|
4771
|
-
type: null
|
|
4772
|
-
});
|
|
4773
|
-
return;
|
|
4774
|
-
}
|
|
4775
|
-
const lx = x - r.x;
|
|
4776
|
-
const ly = y - r.y;
|
|
4777
|
-
const data = new Uint8Array(w * h);
|
|
4778
|
-
for (let row = 0; row < h; row++) {
|
|
4779
|
-
data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
|
|
4780
|
-
}
|
|
4781
|
-
dest.push({
|
|
4782
|
-
x,
|
|
4783
|
-
y,
|
|
4784
|
-
w,
|
|
4785
|
-
h,
|
|
4786
|
-
data,
|
|
4787
|
-
type: 1 /* BINARY */
|
|
4788
|
-
});
|
|
4789
|
-
}
|
|
4790
|
-
|
|
4791
5035
|
// src/Rect/getRectsBounds.ts
|
|
4792
5036
|
function getRectsBounds(rects) {
|
|
4793
5037
|
if (rects.length === 1) return {
|
|
@@ -4900,8 +5144,59 @@ function mergeBinaryMaskRects(current, adding) {
|
|
|
4900
5144
|
return rects;
|
|
4901
5145
|
}
|
|
4902
5146
|
|
|
5147
|
+
// src/MaskRect/subtractBinaryMaskRects.ts
|
|
5148
|
+
function subtractBinaryMaskRects(current, subtracting) {
|
|
5149
|
+
let result = [...current];
|
|
5150
|
+
for (const sub of subtracting) {
|
|
5151
|
+
const next = [];
|
|
5152
|
+
for (const r of result) {
|
|
5153
|
+
const ix = Math.max(r.x, sub.x);
|
|
5154
|
+
const iy = Math.max(r.y, sub.y);
|
|
5155
|
+
const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
|
|
5156
|
+
const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
|
|
5157
|
+
if (ix >= ix2 || iy >= iy2) {
|
|
5158
|
+
next.push(r);
|
|
5159
|
+
continue;
|
|
5160
|
+
}
|
|
5161
|
+
if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
|
|
5162
|
+
if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
|
|
5163
|
+
if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
|
|
5164
|
+
if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
|
|
5165
|
+
}
|
|
5166
|
+
result = next;
|
|
5167
|
+
}
|
|
5168
|
+
return result;
|
|
5169
|
+
}
|
|
5170
|
+
function pushPiece(dest, r, x, y, w, h) {
|
|
5171
|
+
if (r.data === null || r.data === void 0) {
|
|
5172
|
+
dest.push({
|
|
5173
|
+
x,
|
|
5174
|
+
y,
|
|
5175
|
+
w,
|
|
5176
|
+
h,
|
|
5177
|
+
data: null,
|
|
5178
|
+
type: null
|
|
5179
|
+
});
|
|
5180
|
+
return;
|
|
5181
|
+
}
|
|
5182
|
+
const lx = x - r.x;
|
|
5183
|
+
const ly = y - r.y;
|
|
5184
|
+
const data = new Uint8Array(w * h);
|
|
5185
|
+
for (let row = 0; row < h; row++) {
|
|
5186
|
+
data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
|
|
5187
|
+
}
|
|
5188
|
+
dest.push({
|
|
5189
|
+
x,
|
|
5190
|
+
y,
|
|
5191
|
+
w,
|
|
5192
|
+
h,
|
|
5193
|
+
data,
|
|
5194
|
+
type: 1 /* BINARY */
|
|
5195
|
+
});
|
|
5196
|
+
}
|
|
5197
|
+
|
|
4903
5198
|
// src/PixelData/PixelData.ts
|
|
4904
|
-
var PixelData = class
|
|
5199
|
+
var PixelData = class {
|
|
4905
5200
|
data32;
|
|
4906
5201
|
imageData;
|
|
4907
5202
|
width;
|
|
@@ -4919,30 +5214,35 @@ var PixelData = class _PixelData {
|
|
|
4919
5214
|
this.width = imageData.width;
|
|
4920
5215
|
this.height = imageData.height;
|
|
4921
5216
|
}
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
5217
|
+
};
|
|
5218
|
+
|
|
5219
|
+
// src/PixelData/blendPixelDataPaintBuffer.ts
|
|
5220
|
+
var SCRATCH_OPTS = {
|
|
5221
|
+
x: 0,
|
|
5222
|
+
y: 0,
|
|
5223
|
+
alpha: 255,
|
|
5224
|
+
blendFn: void 0
|
|
5225
|
+
};
|
|
5226
|
+
function blendPixelDataPaintBuffer(paintBuffer, target, alpha = 255, blendFn, blendPixelDataFn = blendPixelData) {
|
|
5227
|
+
const tileShift = paintBuffer.config.tileShift;
|
|
5228
|
+
const lookup = paintBuffer.lookup;
|
|
5229
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
5230
|
+
const tile = lookup[i];
|
|
5231
|
+
if (tile) {
|
|
5232
|
+
const x = tile.tx << tileShift;
|
|
5233
|
+
const y = tile.ty << tileShift;
|
|
5234
|
+
SCRATCH_OPTS.x = x;
|
|
5235
|
+
SCRATCH_OPTS.y = y;
|
|
5236
|
+
SCRATCH_OPTS.alpha = alpha;
|
|
5237
|
+
SCRATCH_OPTS.blendFn = blendFn;
|
|
5238
|
+
blendPixelDataFn(target, tile, SCRATCH_OPTS);
|
|
4938
5239
|
}
|
|
4939
|
-
return new _PixelData(newImageData);
|
|
4940
5240
|
}
|
|
4941
|
-
}
|
|
5241
|
+
}
|
|
4942
5242
|
|
|
4943
5243
|
// src/PixelData/clearPixelData.ts
|
|
4944
5244
|
function clearPixelData(dst, rect) {
|
|
4945
|
-
|
|
5245
|
+
fillPixelDataFast(dst, 0, rect);
|
|
4946
5246
|
}
|
|
4947
5247
|
|
|
4948
5248
|
// src/PixelData/extractPixelDataBuffer.ts
|
|
@@ -5161,6 +5461,124 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5161
5461
|
dstData.set(data.subarray(srcStart, srcStart + copyW), dstStart);
|
|
5162
5462
|
}
|
|
5163
5463
|
}
|
|
5464
|
+
|
|
5465
|
+
// src/PixelTile/PaintBuffer.ts
|
|
5466
|
+
var PaintBuffer = class {
|
|
5467
|
+
constructor(config, tilePool) {
|
|
5468
|
+
this.config = config;
|
|
5469
|
+
this.tilePool = tilePool;
|
|
5470
|
+
this.lookup = [];
|
|
5471
|
+
}
|
|
5472
|
+
lookup;
|
|
5473
|
+
processMaskTiles(mask, callback) {
|
|
5474
|
+
const {
|
|
5475
|
+
tileShift,
|
|
5476
|
+
targetColumns
|
|
5477
|
+
} = this.config;
|
|
5478
|
+
const x1 = mask.x >> tileShift;
|
|
5479
|
+
const y1 = mask.y >> tileShift;
|
|
5480
|
+
const x2 = mask.x + mask.w - 1 >> tileShift;
|
|
5481
|
+
const y2 = mask.y + mask.h - 1 >> tileShift;
|
|
5482
|
+
for (let ty = y1; ty <= y2; ty++) {
|
|
5483
|
+
const tileRowIndex = ty * targetColumns;
|
|
5484
|
+
const tileTop = ty << tileShift;
|
|
5485
|
+
for (let tx = x1; tx <= x2; tx++) {
|
|
5486
|
+
const id = tileRowIndex + tx;
|
|
5487
|
+
let tile = this.lookup[id];
|
|
5488
|
+
if (!tile) {
|
|
5489
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
5490
|
+
this.lookup[id] = tile;
|
|
5491
|
+
}
|
|
5492
|
+
const tileLeft = tx << tileShift;
|
|
5493
|
+
const startX = Math.max(mask.x, tileLeft);
|
|
5494
|
+
const endX = Math.min(mask.x + mask.w, tileLeft + this.config.tileSize);
|
|
5495
|
+
const startY = Math.max(mask.y, tileTop);
|
|
5496
|
+
const endY = Math.min(mask.y + mask.h, tileTop + this.config.tileSize);
|
|
5497
|
+
callback(tile, startX, startY, endX - startX, endY - startY, startX - mask.x, startY - mask.y);
|
|
5498
|
+
}
|
|
5499
|
+
}
|
|
5500
|
+
}
|
|
5501
|
+
writeColorBinaryMaskRect(color, mask) {
|
|
5502
|
+
const {
|
|
5503
|
+
tileShift,
|
|
5504
|
+
tileMask
|
|
5505
|
+
} = this.config;
|
|
5506
|
+
const maskData = mask.data;
|
|
5507
|
+
const maskW = mask.w;
|
|
5508
|
+
this.processMaskTiles(mask, (tile, bX, bY, bW, bH, mX, mY) => {
|
|
5509
|
+
const data32 = tile.data32;
|
|
5510
|
+
const startTileX = bX & tileMask;
|
|
5511
|
+
for (let i = 0; i < bH; i++) {
|
|
5512
|
+
const tileY = bY + i & tileMask;
|
|
5513
|
+
const maskY = mY + i;
|
|
5514
|
+
const tileRowOffset = tileY << tileShift;
|
|
5515
|
+
const maskRowOffset = maskY * maskW;
|
|
5516
|
+
const destStart = tileRowOffset + startTileX;
|
|
5517
|
+
const maskStart = maskRowOffset + mX;
|
|
5518
|
+
for (let j = 0; j < bW; j++) {
|
|
5519
|
+
if (maskData[maskStart + j]) {
|
|
5520
|
+
data32[destStart + j] = color;
|
|
5521
|
+
}
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
5524
|
+
});
|
|
5525
|
+
}
|
|
5526
|
+
writeColorAlphaMaskRect(color, mask) {
|
|
5527
|
+
const {
|
|
5528
|
+
tileShift,
|
|
5529
|
+
tileMask
|
|
5530
|
+
} = this.config;
|
|
5531
|
+
const maskData = mask.data;
|
|
5532
|
+
const maskW = mask.w;
|
|
5533
|
+
const colorRGB = color & 16777215;
|
|
5534
|
+
const colorA = color >>> 24;
|
|
5535
|
+
this.processMaskTiles(mask, (tile, bX, bY, bW, bH, mX, mY) => {
|
|
5536
|
+
const data32 = tile.data32;
|
|
5537
|
+
const startTileX = bX & tileMask;
|
|
5538
|
+
for (let i = 0; i < bH; i++) {
|
|
5539
|
+
const tileY = bY + i & tileMask;
|
|
5540
|
+
const maskY = mY + i;
|
|
5541
|
+
const tileRowOffset = tileY << tileShift;
|
|
5542
|
+
const maskRowOffset = maskY * maskW;
|
|
5543
|
+
const destStart = tileRowOffset + startTileX;
|
|
5544
|
+
const maskStart = maskRowOffset + mX;
|
|
5545
|
+
for (let j = 0; j < bW; j++) {
|
|
5546
|
+
const maskA = maskData[maskStart + j];
|
|
5547
|
+
if (maskA > 0) {
|
|
5548
|
+
const finalA = colorA * maskA + 128 >> 8;
|
|
5549
|
+
data32[destStart + j] = (colorRGB | finalA << 24) >>> 0;
|
|
5550
|
+
}
|
|
5551
|
+
}
|
|
5552
|
+
}
|
|
5553
|
+
});
|
|
5554
|
+
}
|
|
5555
|
+
clear() {
|
|
5556
|
+
this.tilePool.releaseTiles(this.lookup);
|
|
5557
|
+
}
|
|
5558
|
+
};
|
|
5559
|
+
|
|
5560
|
+
// src/PixelTile/PaintBufferRenderer.ts
|
|
5561
|
+
function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
|
|
5562
|
+
const config = paintBuffer.config;
|
|
5563
|
+
const tileSize = config.tileSize;
|
|
5564
|
+
const tileShift = config.tileShift;
|
|
5565
|
+
const lookup = paintBuffer.lookup;
|
|
5566
|
+
const canvas = new offscreenCanvasClass(tileSize, tileSize);
|
|
5567
|
+
const ctx = canvas.getContext("2d");
|
|
5568
|
+
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
5569
|
+
ctx.imageSmoothingEnabled = false;
|
|
5570
|
+
return function drawPaintBuffer(target) {
|
|
5571
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
5572
|
+
const tile = lookup[i];
|
|
5573
|
+
if (tile) {
|
|
5574
|
+
const dx = tile.tx << tileShift;
|
|
5575
|
+
const dy = tile.ty << tileShift;
|
|
5576
|
+
ctx.putImageData(tile.imageData, 0, 0);
|
|
5577
|
+
target.drawImage(canvas, dx, dy);
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5580
|
+
};
|
|
5581
|
+
}
|
|
5164
5582
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5165
5583
|
0 && (module.exports = {
|
|
5166
5584
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
@@ -5171,17 +5589,18 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5171
5589
|
IndexedImage,
|
|
5172
5590
|
MaskType,
|
|
5173
5591
|
OFFSCREEN_CANVAS_CTX_FAILED,
|
|
5592
|
+
PaintBuffer,
|
|
5174
5593
|
PixelAccumulator,
|
|
5175
5594
|
PixelBuffer32,
|
|
5176
5595
|
PixelData,
|
|
5177
5596
|
PixelEngineConfig,
|
|
5178
5597
|
PixelTile,
|
|
5598
|
+
PixelTilePool,
|
|
5179
5599
|
PixelWriter,
|
|
5180
5600
|
UnsupportedFormatError,
|
|
5181
5601
|
applyAlphaMaskToPixelData,
|
|
5182
5602
|
applyBinaryMaskToAlphaMask,
|
|
5183
5603
|
applyBinaryMaskToPixelData,
|
|
5184
|
-
applyCircleBrushToPixelData,
|
|
5185
5604
|
applyPatchTiles,
|
|
5186
5605
|
applyRectBrushToPixelData,
|
|
5187
5606
|
base64DecodeArrayBuffer,
|
|
@@ -5189,9 +5608,12 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5189
5608
|
blendColorPixelData,
|
|
5190
5609
|
blendColorPixelDataAlphaMask,
|
|
5191
5610
|
blendColorPixelDataBinaryMask,
|
|
5611
|
+
blendColorPixelDataCircleMask,
|
|
5612
|
+
blendPixel,
|
|
5192
5613
|
blendPixelData,
|
|
5193
5614
|
blendPixelDataAlphaMask,
|
|
5194
5615
|
blendPixelDataBinaryMask,
|
|
5616
|
+
blendPixelDataPaintBuffer,
|
|
5195
5617
|
clearPixelData,
|
|
5196
5618
|
color32ToCssRGBA,
|
|
5197
5619
|
color32ToHex,
|
|
@@ -5225,6 +5647,7 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5225
5647
|
fileToImageData,
|
|
5226
5648
|
fillPixelData,
|
|
5227
5649
|
fillPixelDataBinaryMask,
|
|
5650
|
+
fillPixelDataFast,
|
|
5228
5651
|
floodFillSelection,
|
|
5229
5652
|
forEachLinePoint,
|
|
5230
5653
|
getCircleBrushOrPencilBounds,
|
|
@@ -5265,15 +5688,19 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5265
5688
|
makeAlphaMask,
|
|
5266
5689
|
makeBinaryMask,
|
|
5267
5690
|
makeBlendModeRegistry,
|
|
5268
|
-
|
|
5269
|
-
|
|
5691
|
+
makeCanvasFrameRenderer,
|
|
5692
|
+
makeCircleAlphaMask,
|
|
5693
|
+
makeCircleBinaryMask,
|
|
5270
5694
|
makeFastBlendModeRegistry,
|
|
5271
5695
|
makeFullPixelMutator,
|
|
5696
|
+
makeHistoryAction,
|
|
5272
5697
|
makeImageDataLike,
|
|
5698
|
+
makePaintBufferRenderer,
|
|
5273
5699
|
makePerfectBlendModeRegistry,
|
|
5274
5700
|
makePixelCanvas,
|
|
5275
5701
|
makeReusableCanvas,
|
|
5276
5702
|
makeReusableImageData,
|
|
5703
|
+
makeReusableOffscreenCanvas,
|
|
5277
5704
|
merge2BinaryMaskRects,
|
|
5278
5705
|
mergeAlphaMasks,
|
|
5279
5706
|
mergeBinaryMaskRects,
|
|
@@ -5282,7 +5709,6 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5282
5709
|
multiplyPerfect,
|
|
5283
5710
|
mutatorApplyAlphaMask,
|
|
5284
5711
|
mutatorApplyBinaryMask,
|
|
5285
|
-
mutatorApplyCircleBrush,
|
|
5286
5712
|
mutatorApplyCircleBrushStroke,
|
|
5287
5713
|
mutatorApplyCirclePencil,
|
|
5288
5714
|
mutatorApplyCirclePencilStroke,
|
|
@@ -5291,6 +5717,7 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5291
5717
|
mutatorApplyRectPencil,
|
|
5292
5718
|
mutatorApplyRectPencilStroke,
|
|
5293
5719
|
mutatorBlendColor,
|
|
5720
|
+
mutatorBlendColorCircleMask,
|
|
5294
5721
|
mutatorBlendPixel,
|
|
5295
5722
|
mutatorBlendPixelData,
|
|
5296
5723
|
mutatorBlendPixelDataAlphaMask,
|
|
@@ -5298,6 +5725,7 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5298
5725
|
mutatorClear,
|
|
5299
5726
|
mutatorFill,
|
|
5300
5727
|
mutatorFillBinaryMask,
|
|
5728
|
+
mutatorFillRect,
|
|
5301
5729
|
mutatorInvert,
|
|
5302
5730
|
overlayFast,
|
|
5303
5731
|
overlayPerfect,
|