pixel-data-js 0.24.0 → 0.25.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 +1431 -1845
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1297 -1702
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1305 -1719
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +220 -328
- package/dist/index.prod.js +1423 -1828
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/Algorithm/floodFillSelection.ts +2 -2
- package/src/Canvas/canvas-blend-modes.ts +28 -0
- package/src/History/PixelAccumulator.ts +52 -29
- package/src/History/PixelEngineConfig.ts +7 -9
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts +2 -2
- package/src/History/PixelMutator.ts +0 -20
- package/src/History/PixelPatchTiles.ts +2 -2
- package/src/History/PixelWriter.ts +132 -9
- package/src/Internal/helpers.ts +2 -0
- package/src/Paint/PaintBuffer.ts +269 -0
- package/src/{PixelTile/PaintBufferRenderer.ts → Paint/PaintBufferCanvasRenderer.ts} +13 -5
- package/src/Paint/makeCirclePaintAlphaMask.ts +41 -0
- package/src/{Mask/CircleBinaryMask.ts → Paint/makeCirclePaintBinaryMask.ts} +5 -6
- package/src/Paint/makePaintMask.ts +28 -0
- package/src/Paint/makeRectFalloffPaintAlphaMask.ts +47 -0
- package/src/PixelData/PixelBuffer32.ts +2 -2
- package/src/PixelData/PixelData.ts +1 -1
- package/src/PixelData/applyAlphaMaskToPixelData.ts +2 -2
- package/src/PixelData/applyBinaryMaskToPixelData.ts +2 -2
- package/src/PixelData/blendColorPixelData.ts +2 -2
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +3 -3
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/blendPixel.ts +2 -2
- package/src/PixelData/blendPixelData.ts +3 -3
- package/src/PixelData/blendPixelDataAlphaMask.ts +3 -3
- package/src/PixelData/blendPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/blendPixelDataPaintBuffer.ts +3 -3
- package/src/PixelData/clearPixelData.ts +2 -2
- package/src/PixelData/extractPixelData.ts +4 -4
- package/src/PixelData/extractPixelDataBuffer.ts +4 -4
- package/src/PixelData/fillPixelData.ts +5 -5
- package/src/PixelData/fillPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/fillPixelDataFast.ts +5 -5
- package/src/PixelData/invertPixelData.ts +2 -2
- package/src/PixelData/pixelDataToAlphaMask.ts +2 -2
- package/src/PixelData/reflectPixelData.ts +3 -3
- package/src/PixelData/resamplePixelData.ts +2 -2
- package/src/PixelData/writePaintBufferToPixelData.ts +26 -0
- package/src/PixelData/writePixelDataBuffer.ts +5 -5
- package/src/Rect/trimMaskRectBounds.ts +121 -0
- package/src/Rect/trimRectBounds.ts +25 -116
- package/src/_types.ts +16 -15
- package/src/index.ts +9 -24
- package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +0 -182
- package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +0 -59
- package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +0 -172
- package/src/History/PixelMutator/mutatorApplyRectBrush.ts +0 -64
- package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +0 -184
- package/src/History/PixelMutator/mutatorApplyRectPencil.ts +0 -65
- package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +0 -166
- package/src/History/PixelMutator/mutatorBlendColorCircleMask.ts +0 -71
- package/src/Mask/CircleAlphaMask.ts +0 -32
- package/src/PixelData/applyRectBrushToPixelData.ts +0 -98
- package/src/PixelData/blendColorPixelDataCircleMask.ts +0 -92
- package/src/PixelTile/PaintBuffer.ts +0 -122
- package/src/Rect/getCircleBrushOrPencilBounds.ts +0 -43
- package/src/Rect/getCircleBrushOrPencilStrokeBounds.ts +0 -24
- package/src/Rect/getRectBrushOrPencilBounds.ts +0 -38
- package/src/Rect/getRectBrushOrPencilStrokeBounds.ts +0 -26
package/dist/index.dev.js
CHANGED
|
@@ -232,8 +232,8 @@ function extractMaskBuffer(maskBuffer, maskWidth, xOrRect, y, w, h) {
|
|
|
232
232
|
return out;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
// src/Rect/
|
|
236
|
-
function
|
|
235
|
+
// src/Rect/trimMaskRectBounds.ts
|
|
236
|
+
function trimMaskRectBounds(target, bounds) {
|
|
237
237
|
const originalX = target.x;
|
|
238
238
|
const originalY = target.y;
|
|
239
239
|
const originalW = target.w;
|
|
@@ -421,7 +421,7 @@ function floodFillSelection(img, startX, startY, {
|
|
|
421
421
|
finalMask[my * sw + mx] = 1;
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
|
-
|
|
424
|
+
trimMaskRectBounds(selectionRect, {
|
|
425
425
|
x: 0,
|
|
426
426
|
y: 0,
|
|
427
427
|
w: width,
|
|
@@ -1811,11 +1811,11 @@ var PixelAccumulator = class {
|
|
|
1811
1811
|
* @param y pixel y coordinate
|
|
1812
1812
|
*/
|
|
1813
1813
|
storePixelBeforeState(x, y) {
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1814
|
+
const shift = this.config.tileShift;
|
|
1815
|
+
const columns = this.config.targetColumns;
|
|
1816
|
+
const tx = x >> shift;
|
|
1817
|
+
const ty = y >> shift;
|
|
1818
|
+
const id = ty * columns + tx;
|
|
1819
1819
|
let tile = this.lookup[id];
|
|
1820
1820
|
let added = false;
|
|
1821
1821
|
if (!tile) {
|
|
@@ -1841,16 +1841,16 @@ var PixelAccumulator = class {
|
|
|
1841
1841
|
* @param h pixel height
|
|
1842
1842
|
*/
|
|
1843
1843
|
storeRegionBeforeState(x, y, w, h) {
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1844
|
+
const shift = this.config.tileShift;
|
|
1845
|
+
const columns = this.config.targetColumns;
|
|
1846
|
+
const startX = x >> shift;
|
|
1847
|
+
const startY = y >> shift;
|
|
1848
|
+
const endX = x + w - 1 >> shift;
|
|
1849
|
+
const endY = y + h - 1 >> shift;
|
|
1850
|
+
const startIndex = this.beforeTiles.length;
|
|
1851
1851
|
for (let ty = startY; ty <= endY; ty++) {
|
|
1852
1852
|
for (let tx = startX; tx <= endX; tx++) {
|
|
1853
|
-
|
|
1853
|
+
const id = ty * columns + tx;
|
|
1854
1854
|
let tile = this.lookup[id];
|
|
1855
1855
|
if (!tile) {
|
|
1856
1856
|
tile = this.tilePool.getTile(id, tx, ty);
|
|
@@ -1862,7 +1862,7 @@ var PixelAccumulator = class {
|
|
|
1862
1862
|
}
|
|
1863
1863
|
return (didChange) => {
|
|
1864
1864
|
if (!didChange) {
|
|
1865
|
-
|
|
1865
|
+
const length = this.beforeTiles.length;
|
|
1866
1866
|
for (let i = startIndex; i < length; i++) {
|
|
1867
1867
|
let t = this.beforeTiles[i];
|
|
1868
1868
|
if (t) {
|
|
@@ -1875,15 +1875,34 @@ var PixelAccumulator = class {
|
|
|
1875
1875
|
return didChange;
|
|
1876
1876
|
};
|
|
1877
1877
|
}
|
|
1878
|
+
storeTileBeforeState(id, tx, ty) {
|
|
1879
|
+
let tile = this.lookup[id];
|
|
1880
|
+
let added = false;
|
|
1881
|
+
if (!tile) {
|
|
1882
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
1883
|
+
this.extractState(tile);
|
|
1884
|
+
this.lookup[id] = tile;
|
|
1885
|
+
this.beforeTiles.push(tile);
|
|
1886
|
+
added = true;
|
|
1887
|
+
}
|
|
1888
|
+
return (didChange) => {
|
|
1889
|
+
if (!didChange && added) {
|
|
1890
|
+
this.beforeTiles.pop();
|
|
1891
|
+
this.lookup[id] = void 0;
|
|
1892
|
+
this.tilePool.releaseTile(tile);
|
|
1893
|
+
}
|
|
1894
|
+
return didChange;
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1878
1897
|
extractState(tile) {
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1898
|
+
const target = this.config.target;
|
|
1899
|
+
const TILE_SIZE = this.config.tileSize;
|
|
1900
|
+
const dst = tile.data32;
|
|
1901
|
+
const src = target.data32;
|
|
1902
|
+
const startX = tile.tx * TILE_SIZE;
|
|
1903
|
+
const startY = tile.ty * TILE_SIZE;
|
|
1904
|
+
const targetWidth = target.width;
|
|
1905
|
+
const targetHeight = target.height;
|
|
1887
1906
|
if (startX >= targetWidth || startX + TILE_SIZE <= 0 || startY >= targetHeight || startY + TILE_SIZE <= 0) {
|
|
1888
1907
|
dst.fill(0);
|
|
1889
1908
|
return;
|
|
@@ -1909,8 +1928,8 @@ var PixelAccumulator = class {
|
|
|
1909
1928
|
}
|
|
1910
1929
|
}
|
|
1911
1930
|
extractPatch() {
|
|
1912
|
-
|
|
1913
|
-
|
|
1931
|
+
const afterTiles = [];
|
|
1932
|
+
const length = this.beforeTiles.length;
|
|
1914
1933
|
for (let i = 0; i < length; i++) {
|
|
1915
1934
|
let beforeTile = this.beforeTiles[i];
|
|
1916
1935
|
if (beforeTile) {
|
|
@@ -1919,7 +1938,7 @@ var PixelAccumulator = class {
|
|
|
1919
1938
|
afterTiles.push(afterTile);
|
|
1920
1939
|
}
|
|
1921
1940
|
}
|
|
1922
|
-
|
|
1941
|
+
const beforeTiles = this.beforeTiles;
|
|
1923
1942
|
this.beforeTiles = [];
|
|
1924
1943
|
this.lookup.length = 0;
|
|
1925
1944
|
return {
|
|
@@ -1927,10 +1946,10 @@ var PixelAccumulator = class {
|
|
|
1927
1946
|
afterTiles
|
|
1928
1947
|
};
|
|
1929
1948
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1949
|
+
rollbackAfterError() {
|
|
1950
|
+
const target = this.config.target;
|
|
1951
|
+
const tileSize = this.config.tileSize;
|
|
1952
|
+
const length = this.beforeTiles.length;
|
|
1934
1953
|
applyPatchTiles(target, this.beforeTiles, tileSize);
|
|
1935
1954
|
for (let i = 0; i < length; i++) {
|
|
1936
1955
|
let tile = this.beforeTiles[i];
|
|
@@ -1954,6 +1973,7 @@ var PixelEngineConfig = class {
|
|
|
1954
1973
|
tileArea;
|
|
1955
1974
|
target;
|
|
1956
1975
|
targetColumns = 0;
|
|
1976
|
+
targetRows = 0;
|
|
1957
1977
|
constructor(tileSize, target) {
|
|
1958
1978
|
if ((tileSize & tileSize - 1) !== 0) {
|
|
1959
1979
|
throw new Error("tileSize must be a power of 2");
|
|
@@ -1962,28 +1982,26 @@ var PixelEngineConfig = class {
|
|
|
1962
1982
|
this.tileShift = 31 - Math.clz32(tileSize);
|
|
1963
1983
|
this.tileMask = tileSize - 1;
|
|
1964
1984
|
this.tileArea = tileSize * tileSize;
|
|
1965
|
-
this.setTarget(target);
|
|
1966
|
-
}
|
|
1967
|
-
setTarget(target) {
|
|
1968
|
-
;
|
|
1969
1985
|
this.target = target;
|
|
1970
1986
|
this.targetColumns = target.width + this.tileMask >> this.tileShift;
|
|
1987
|
+
this.targetRows = target.height + this.tileMask >> this.tileShift;
|
|
1971
1988
|
}
|
|
1972
1989
|
};
|
|
1973
1990
|
|
|
1974
|
-
// src/PixelData/
|
|
1975
|
-
function
|
|
1991
|
+
// src/PixelData/blendColorPixelData.ts
|
|
1992
|
+
function blendColorPixelData(dst, color, opts = {}) {
|
|
1976
1993
|
const {
|
|
1977
1994
|
x: targetX = 0,
|
|
1978
1995
|
y: targetY = 0,
|
|
1979
1996
|
w: width = dst.width,
|
|
1980
1997
|
h: height = dst.height,
|
|
1981
1998
|
alpha: globalAlpha = 255,
|
|
1982
|
-
|
|
1983
|
-
my = 0,
|
|
1984
|
-
invertMask = false
|
|
1999
|
+
blendFn = sourceOverPerfect
|
|
1985
2000
|
} = opts;
|
|
1986
2001
|
if (globalAlpha === 0) return false;
|
|
2002
|
+
const baseSrcAlpha = color >>> 24;
|
|
2003
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2004
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
1987
2005
|
let x = targetX;
|
|
1988
2006
|
let y = targetY;
|
|
1989
2007
|
let w = width;
|
|
@@ -1996,82 +2014,46 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1996
2014
|
h += y;
|
|
1997
2015
|
y = 0;
|
|
1998
2016
|
}
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
if (
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
const sY0 = Math.max(0, startY);
|
|
2009
|
-
const sX1 = Math.min(mPitch, startX + w);
|
|
2010
|
-
const sY1 = Math.min(mask.h, startY + h);
|
|
2011
|
-
const finalW = sX1 - sX0;
|
|
2012
|
-
const finalH = sY1 - sY0;
|
|
2013
|
-
if (finalW <= 0) return false;
|
|
2014
|
-
if (finalH <= 0) return false;
|
|
2015
|
-
const xShift = sX0 - startX;
|
|
2016
|
-
const yShift = sY0 - startY;
|
|
2017
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2018
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2019
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2020
|
+
let finalSrcColor = color;
|
|
2021
|
+
if (globalAlpha < 255) {
|
|
2022
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2023
|
+
if (a === 0 && !isOverwrite) return false;
|
|
2024
|
+
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
2025
|
+
}
|
|
2017
2026
|
const dst32 = dst.data32;
|
|
2018
2027
|
const dw = dst.width;
|
|
2019
|
-
|
|
2020
|
-
const
|
|
2021
|
-
const maskData = mask.data;
|
|
2022
|
-
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2023
|
-
let mIdx = sY0 * mPitch + sX0;
|
|
2028
|
+
let dIdx = y * dw + x | 0;
|
|
2029
|
+
const dStride = dw - actualW | 0;
|
|
2024
2030
|
let didChange = false;
|
|
2025
|
-
for (let iy = 0; iy <
|
|
2026
|
-
for (let ix = 0; ix <
|
|
2027
|
-
const
|
|
2028
|
-
const
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
weight = 0;
|
|
2032
|
-
} else if (effectiveM === 255) {
|
|
2033
|
-
weight = globalAlpha;
|
|
2034
|
-
} else if (globalAlpha === 255) {
|
|
2035
|
-
weight = effectiveM;
|
|
2036
|
-
} else {
|
|
2037
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2038
|
-
}
|
|
2039
|
-
if (weight === 0) {
|
|
2040
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2031
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2032
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2033
|
+
const current = dst32[dIdx];
|
|
2034
|
+
const next = blendFn(finalSrcColor, current);
|
|
2035
|
+
if (current !== next) {
|
|
2036
|
+
dst32[dIdx] = next;
|
|
2041
2037
|
didChange = true;
|
|
2042
|
-
} else if (weight !== 255) {
|
|
2043
|
-
const d = dst32[dIdx];
|
|
2044
|
-
const da = d >>> 24;
|
|
2045
|
-
if (da !== 0) {
|
|
2046
|
-
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
2047
|
-
const current = dst32[dIdx];
|
|
2048
|
-
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2049
|
-
if (current !== next) {
|
|
2050
|
-
dst32[dIdx] = next;
|
|
2051
|
-
didChange = true;
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
2038
|
}
|
|
2055
2039
|
dIdx++;
|
|
2056
|
-
mIdx++;
|
|
2057
2040
|
}
|
|
2058
2041
|
dIdx += dStride;
|
|
2059
|
-
mIdx += mStride;
|
|
2060
2042
|
}
|
|
2061
2043
|
return didChange;
|
|
2062
2044
|
}
|
|
2063
2045
|
|
|
2064
|
-
// src/History/PixelMutator/
|
|
2046
|
+
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2065
2047
|
var defaults2 = {
|
|
2066
|
-
|
|
2048
|
+
blendColorPixelData
|
|
2067
2049
|
};
|
|
2068
|
-
var
|
|
2050
|
+
var mutatorBlendColor = ((writer, deps = defaults2) => {
|
|
2069
2051
|
const {
|
|
2070
|
-
|
|
2052
|
+
blendColorPixelData: blendColorPixelData2 = defaults2.blendColorPixelData
|
|
2071
2053
|
} = deps;
|
|
2072
2054
|
return {
|
|
2073
|
-
|
|
2074
|
-
|
|
2055
|
+
blendColor(color, opts = {}) {
|
|
2056
|
+
const target = writer.config.target;
|
|
2075
2057
|
const {
|
|
2076
2058
|
x = 0,
|
|
2077
2059
|
y = 0,
|
|
@@ -2079,159 +2061,227 @@ var mutatorApplyAlphaMask = ((writer, deps = defaults2) => {
|
|
|
2079
2061
|
h = target.height
|
|
2080
2062
|
} = opts;
|
|
2081
2063
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2082
|
-
return didChange(
|
|
2064
|
+
return didChange(blendColorPixelData2(target, color, opts));
|
|
2083
2065
|
}
|
|
2084
2066
|
};
|
|
2085
2067
|
});
|
|
2086
2068
|
|
|
2087
|
-
// src/PixelData/
|
|
2088
|
-
function
|
|
2069
|
+
// src/PixelData/blendPixel.ts
|
|
2070
|
+
function blendPixel(target, x, y, color, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2071
|
+
if (alpha === 0) return false;
|
|
2072
|
+
let width = target.width;
|
|
2073
|
+
let height = target.height;
|
|
2074
|
+
if (x < 0 || x >= width || y < 0 || y >= height) return false;
|
|
2075
|
+
let srcAlpha = color >>> 24;
|
|
2076
|
+
let isOverwrite = blendFn.isOverwrite;
|
|
2077
|
+
if (srcAlpha === 0 && !isOverwrite) return false;
|
|
2078
|
+
let dst32 = target.data32;
|
|
2079
|
+
let index = y * width + x;
|
|
2080
|
+
let finalColor = color;
|
|
2081
|
+
if (alpha !== 255) {
|
|
2082
|
+
let finalAlpha = srcAlpha * alpha + 128 >> 8;
|
|
2083
|
+
if (finalAlpha === 0 && !isOverwrite) return false;
|
|
2084
|
+
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
2085
|
+
}
|
|
2086
|
+
let current = dst32[index];
|
|
2087
|
+
let next = blendFn(finalColor, current);
|
|
2088
|
+
if (current !== next) {
|
|
2089
|
+
dst32[index] = next;
|
|
2090
|
+
return true;
|
|
2091
|
+
}
|
|
2092
|
+
return false;
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2096
|
+
var defaults3 = {
|
|
2097
|
+
blendPixel
|
|
2098
|
+
};
|
|
2099
|
+
var mutatorBlendPixel = ((writer, deps = defaults3) => {
|
|
2100
|
+
const {
|
|
2101
|
+
blendPixel: blendPixel2 = defaults3.blendPixel
|
|
2102
|
+
} = deps;
|
|
2103
|
+
return {
|
|
2104
|
+
blendPixel(x, y, color, alpha, blendFn) {
|
|
2105
|
+
const didChange = writer.accumulator.storePixelBeforeState(x, y);
|
|
2106
|
+
return didChange(blendPixel2(writer.config.target, x, y, color, alpha, blendFn));
|
|
2107
|
+
}
|
|
2108
|
+
};
|
|
2109
|
+
});
|
|
2110
|
+
|
|
2111
|
+
// src/PixelData/blendPixelData.ts
|
|
2112
|
+
function blendPixelData(dst, src, opts = {}) {
|
|
2089
2113
|
const {
|
|
2090
2114
|
x: targetX = 0,
|
|
2091
2115
|
y: targetY = 0,
|
|
2092
|
-
|
|
2093
|
-
|
|
2116
|
+
sx: sourceX = 0,
|
|
2117
|
+
sy: sourceY = 0,
|
|
2118
|
+
w: width = src.width,
|
|
2119
|
+
h: height = src.height,
|
|
2094
2120
|
alpha: globalAlpha = 255,
|
|
2095
|
-
|
|
2096
|
-
my = 0,
|
|
2097
|
-
invertMask = false
|
|
2121
|
+
blendFn = sourceOverPerfect
|
|
2098
2122
|
} = opts;
|
|
2099
2123
|
if (globalAlpha === 0) return false;
|
|
2100
2124
|
let x = targetX;
|
|
2101
2125
|
let y = targetY;
|
|
2126
|
+
let sx = sourceX;
|
|
2127
|
+
let sy = sourceY;
|
|
2102
2128
|
let w = width;
|
|
2103
2129
|
let h = height;
|
|
2130
|
+
if (sx < 0) {
|
|
2131
|
+
x -= sx;
|
|
2132
|
+
w += sx;
|
|
2133
|
+
sx = 0;
|
|
2134
|
+
}
|
|
2135
|
+
if (sy < 0) {
|
|
2136
|
+
y -= sy;
|
|
2137
|
+
h += sy;
|
|
2138
|
+
sy = 0;
|
|
2139
|
+
}
|
|
2140
|
+
w = Math.min(w, src.width - sx);
|
|
2141
|
+
h = Math.min(h, src.height - sy);
|
|
2104
2142
|
if (x < 0) {
|
|
2143
|
+
sx -= x;
|
|
2105
2144
|
w += x;
|
|
2106
2145
|
x = 0;
|
|
2107
2146
|
}
|
|
2108
2147
|
if (y < 0) {
|
|
2148
|
+
sy -= y;
|
|
2109
2149
|
h += y;
|
|
2110
2150
|
y = 0;
|
|
2111
2151
|
}
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
if (
|
|
2115
|
-
const mPitch = mask.w;
|
|
2116
|
-
if (mPitch <= 0) return false;
|
|
2117
|
-
const startX = mx + (x - targetX);
|
|
2118
|
-
const startY = my + (y - targetY);
|
|
2119
|
-
const sX0 = Math.max(0, startX);
|
|
2120
|
-
const sY0 = Math.max(0, startY);
|
|
2121
|
-
const sX1 = Math.min(mPitch, startX + w);
|
|
2122
|
-
const sY1 = Math.min(mask.h, startY + h);
|
|
2123
|
-
const finalW = sX1 - sX0;
|
|
2124
|
-
const finalH = sY1 - sY0;
|
|
2125
|
-
if (finalW <= 0 || finalH <= 0) {
|
|
2126
|
-
return false;
|
|
2127
|
-
}
|
|
2128
|
-
const xShift = sX0 - startX;
|
|
2129
|
-
const yShift = sY0 - startY;
|
|
2152
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2153
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2154
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2130
2155
|
const dst32 = dst.data32;
|
|
2156
|
+
const src32 = src.data32;
|
|
2131
2157
|
const dw = dst.width;
|
|
2132
|
-
const
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2158
|
+
const sw = src.width;
|
|
2159
|
+
let dIdx = y * dw + x | 0;
|
|
2160
|
+
let sIdx = sy * sw + sx | 0;
|
|
2161
|
+
const dStride = dw - actualW | 0;
|
|
2162
|
+
const sStride = sw - actualW | 0;
|
|
2163
|
+
const isOpaque = globalAlpha === 255;
|
|
2164
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2137
2165
|
let didChange = false;
|
|
2138
|
-
for (let iy = 0; iy <
|
|
2139
|
-
for (let ix = 0; ix <
|
|
2140
|
-
const
|
|
2141
|
-
const
|
|
2142
|
-
if (
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2155
|
-
if (d !== next) {
|
|
2156
|
-
dst32[dIdx] = next;
|
|
2157
|
-
didChange = true;
|
|
2158
|
-
}
|
|
2166
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2167
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2168
|
+
const srcCol = src32[sIdx];
|
|
2169
|
+
const srcAlpha = srcCol >>> 24;
|
|
2170
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2171
|
+
dIdx++;
|
|
2172
|
+
sIdx++;
|
|
2173
|
+
continue;
|
|
2174
|
+
}
|
|
2175
|
+
let finalCol = srcCol;
|
|
2176
|
+
if (!isOpaque) {
|
|
2177
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
2178
|
+
if (a === 0 && !isOverwrite) {
|
|
2179
|
+
dIdx++;
|
|
2180
|
+
sIdx++;
|
|
2181
|
+
continue;
|
|
2159
2182
|
}
|
|
2183
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2160
2184
|
}
|
|
2161
|
-
dIdx
|
|
2162
|
-
|
|
2185
|
+
const current = dst32[dIdx];
|
|
2186
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
2187
|
+
if (current !== next) {
|
|
2188
|
+
dst32[dIdx] = next;
|
|
2189
|
+
didChange = true;
|
|
2190
|
+
}
|
|
2191
|
+
dIdx++;
|
|
2192
|
+
sIdx++;
|
|
2163
2193
|
}
|
|
2164
2194
|
dIdx += dStride;
|
|
2165
|
-
|
|
2195
|
+
sIdx += sStride;
|
|
2166
2196
|
}
|
|
2167
2197
|
return didChange;
|
|
2168
2198
|
}
|
|
2169
2199
|
|
|
2170
|
-
// src/History/PixelMutator/
|
|
2171
|
-
var
|
|
2172
|
-
|
|
2200
|
+
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
2201
|
+
var defaults4 = {
|
|
2202
|
+
blendPixelData
|
|
2173
2203
|
};
|
|
2174
|
-
var
|
|
2204
|
+
var mutatorBlendPixelData = ((writer, deps = defaults4) => {
|
|
2175
2205
|
const {
|
|
2176
|
-
|
|
2206
|
+
blendPixelData: blendPixelData2 = defaults4.blendPixelData
|
|
2177
2207
|
} = deps;
|
|
2178
2208
|
return {
|
|
2179
|
-
|
|
2180
|
-
let target = writer.config.target;
|
|
2209
|
+
blendPixelData(src, opts = {}) {
|
|
2181
2210
|
const {
|
|
2182
2211
|
x = 0,
|
|
2183
2212
|
y = 0,
|
|
2184
|
-
w =
|
|
2185
|
-
h =
|
|
2213
|
+
w = src.width,
|
|
2214
|
+
h = src.height
|
|
2186
2215
|
} = opts;
|
|
2187
2216
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2188
|
-
return didChange(
|
|
2217
|
+
return didChange(blendPixelData2(writer.config.target, src, opts));
|
|
2189
2218
|
}
|
|
2190
2219
|
};
|
|
2191
2220
|
});
|
|
2192
2221
|
|
|
2193
|
-
// src/PixelData/
|
|
2194
|
-
function
|
|
2195
|
-
const
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2222
|
+
// src/PixelData/blendPixelDataAlphaMask.ts
|
|
2223
|
+
function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
2224
|
+
const {
|
|
2225
|
+
x: targetX = 0,
|
|
2226
|
+
y: targetY = 0,
|
|
2227
|
+
sx: sourceX = 0,
|
|
2228
|
+
sy: sourceY = 0,
|
|
2229
|
+
w: width = src.width,
|
|
2230
|
+
h: height = src.height,
|
|
2231
|
+
alpha: globalAlpha = 255,
|
|
2232
|
+
blendFn = sourceOverPerfect,
|
|
2233
|
+
mx = 0,
|
|
2234
|
+
my = 0,
|
|
2235
|
+
invertMask = false
|
|
2236
|
+
} = opts;
|
|
2204
2237
|
if (globalAlpha === 0) return false;
|
|
2205
|
-
const baseSrcAlpha = color >>> 24;
|
|
2206
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
2207
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2208
2238
|
let x = targetX;
|
|
2209
2239
|
let y = targetY;
|
|
2210
|
-
let
|
|
2211
|
-
let
|
|
2240
|
+
let sx = sourceX;
|
|
2241
|
+
let sy = sourceY;
|
|
2242
|
+
let w = width;
|
|
2243
|
+
let h = height;
|
|
2244
|
+
if (sx < 0) {
|
|
2245
|
+
x -= sx;
|
|
2246
|
+
w += sx;
|
|
2247
|
+
sx = 0;
|
|
2248
|
+
}
|
|
2249
|
+
if (sy < 0) {
|
|
2250
|
+
y -= sy;
|
|
2251
|
+
h += sy;
|
|
2252
|
+
sy = 0;
|
|
2253
|
+
}
|
|
2254
|
+
w = Math.min(w, src.width - sx);
|
|
2255
|
+
h = Math.min(h, src.height - sy);
|
|
2212
2256
|
if (x < 0) {
|
|
2213
|
-
|
|
2257
|
+
sx -= x;
|
|
2258
|
+
w += x;
|
|
2214
2259
|
x = 0;
|
|
2215
2260
|
}
|
|
2216
2261
|
if (y < 0) {
|
|
2217
|
-
|
|
2262
|
+
sy -= y;
|
|
2263
|
+
h += y;
|
|
2218
2264
|
y = 0;
|
|
2219
2265
|
}
|
|
2220
|
-
actualW = Math.min(
|
|
2221
|
-
actualH = Math.min(
|
|
2266
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2267
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2222
2268
|
if (actualW <= 0 || actualH <= 0) return false;
|
|
2269
|
+
const dw = dst.width;
|
|
2270
|
+
const sw = src.width;
|
|
2271
|
+
const mPitch = alphaMask.w;
|
|
2272
|
+
const maskData = alphaMask.data;
|
|
2223
2273
|
const dx = x - targetX | 0;
|
|
2224
2274
|
const dy = y - targetY | 0;
|
|
2225
2275
|
const dst32 = dst.data32;
|
|
2226
|
-
const
|
|
2227
|
-
const mPitch = mask.w;
|
|
2228
|
-
const maskData = mask.data;
|
|
2276
|
+
const src32 = src.data32;
|
|
2229
2277
|
let dIdx = y * dw + x | 0;
|
|
2278
|
+
let sIdx = sy * sw + sx | 0;
|
|
2230
2279
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2231
2280
|
const dStride = dw - actualW | 0;
|
|
2281
|
+
const sStride = sw - actualW | 0;
|
|
2232
2282
|
const mStride = mPitch - actualW | 0;
|
|
2233
2283
|
const isOpaque = globalAlpha === 255;
|
|
2234
|
-
const
|
|
2284
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2235
2285
|
let didChange = false;
|
|
2236
2286
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2237
2287
|
for (let ix = 0; ix < actualW; ix++) {
|
|
@@ -2239,6 +2289,15 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2239
2289
|
const effM = invertMask ? 255 - mVal : mVal;
|
|
2240
2290
|
if (effM === 0) {
|
|
2241
2291
|
dIdx++;
|
|
2292
|
+
sIdx++;
|
|
2293
|
+
mIdx++;
|
|
2294
|
+
continue;
|
|
2295
|
+
}
|
|
2296
|
+
const srcCol = src32[sIdx];
|
|
2297
|
+
const srcAlpha = srcCol >>> 24;
|
|
2298
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2299
|
+
dIdx++;
|
|
2300
|
+
sIdx++;
|
|
2242
2301
|
mIdx++;
|
|
2243
2302
|
continue;
|
|
2244
2303
|
}
|
|
@@ -2250,1268 +2309,174 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2250
2309
|
}
|
|
2251
2310
|
if (weight === 0) {
|
|
2252
2311
|
dIdx++;
|
|
2312
|
+
sIdx++;
|
|
2253
2313
|
mIdx++;
|
|
2254
2314
|
continue;
|
|
2255
2315
|
}
|
|
2256
|
-
let finalCol =
|
|
2316
|
+
let finalCol = srcCol;
|
|
2257
2317
|
if (weight < 255) {
|
|
2258
|
-
const a =
|
|
2318
|
+
const a = srcAlpha * weight + 128 >> 8;
|
|
2259
2319
|
if (a === 0 && !isOverwrite) {
|
|
2260
2320
|
dIdx++;
|
|
2321
|
+
sIdx++;
|
|
2261
2322
|
mIdx++;
|
|
2262
2323
|
continue;
|
|
2263
2324
|
}
|
|
2264
|
-
finalCol = (
|
|
2325
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2265
2326
|
}
|
|
2266
2327
|
const current = dst32[dIdx];
|
|
2267
|
-
const next = blendFn(finalCol,
|
|
2328
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
2268
2329
|
if (current !== next) {
|
|
2269
2330
|
dst32[dIdx] = next;
|
|
2270
2331
|
didChange = true;
|
|
2271
2332
|
}
|
|
2272
2333
|
dIdx++;
|
|
2334
|
+
sIdx++;
|
|
2273
2335
|
mIdx++;
|
|
2274
2336
|
}
|
|
2275
2337
|
dIdx += dStride;
|
|
2338
|
+
sIdx += sStride;
|
|
2276
2339
|
mIdx += mStride;
|
|
2277
2340
|
}
|
|
2278
2341
|
return didChange;
|
|
2279
2342
|
}
|
|
2280
2343
|
|
|
2281
|
-
// src/
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
const minOffset = -Math.ceil(r - 0.5);
|
|
2285
|
-
const maxOffset = Math.floor(r - 0.5);
|
|
2286
|
-
const startX = Math.floor(centerX + minOffset);
|
|
2287
|
-
const startY = Math.floor(centerY + minOffset);
|
|
2288
|
-
const endX = Math.floor(centerX + maxOffset) + 1;
|
|
2289
|
-
const endY = Math.floor(centerY + maxOffset) + 1;
|
|
2290
|
-
const res = out ?? {
|
|
2291
|
-
x: 0,
|
|
2292
|
-
y: 0,
|
|
2293
|
-
w: 0,
|
|
2294
|
-
h: 0
|
|
2295
|
-
};
|
|
2296
|
-
const cStartX = Math.max(0, startX);
|
|
2297
|
-
const cStartY = Math.max(0, startY);
|
|
2298
|
-
const cEndX = Math.min(targetWidth, endX);
|
|
2299
|
-
const cEndY = Math.min(targetHeight, endY);
|
|
2300
|
-
const w = cEndX - cStartX;
|
|
2301
|
-
const h = cEndY - cStartY;
|
|
2302
|
-
res.x = cStartX;
|
|
2303
|
-
res.y = cStartY;
|
|
2304
|
-
res.w = w < 0 ? 0 : w;
|
|
2305
|
-
res.h = h < 0 ? 0 : h;
|
|
2306
|
-
return res;
|
|
2307
|
-
}
|
|
2308
|
-
|
|
2309
|
-
// src/Rect/getCircleBrushOrPencilStrokeBounds.ts
|
|
2310
|
-
function getCircleBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushSize, result) {
|
|
2311
|
-
const r = Math.ceil(brushSize / 2);
|
|
2312
|
-
const minX = Math.min(x0, x1) - r;
|
|
2313
|
-
const minY = Math.min(y0, y1) - r;
|
|
2314
|
-
const maxX = Math.max(x0, x1) + r;
|
|
2315
|
-
const maxY = Math.max(x0, y1) + r;
|
|
2316
|
-
result.x = Math.floor(minX);
|
|
2317
|
-
result.y = Math.floor(minY);
|
|
2318
|
-
result.w = Math.ceil(maxX - minX);
|
|
2319
|
-
result.h = Math.ceil(maxY - minY);
|
|
2320
|
-
return result;
|
|
2321
|
-
}
|
|
2322
|
-
|
|
2323
|
-
// src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts
|
|
2324
|
-
var defaults4 = {
|
|
2325
|
-
forEachLinePoint,
|
|
2326
|
-
blendColorPixelDataAlphaMask,
|
|
2327
|
-
getCircleBrushOrPencilBounds,
|
|
2328
|
-
getCircleBrushOrPencilStrokeBounds
|
|
2344
|
+
// src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts
|
|
2345
|
+
var defaults5 = {
|
|
2346
|
+
blendPixelDataAlphaMask
|
|
2329
2347
|
};
|
|
2330
|
-
var
|
|
2348
|
+
var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults5) => {
|
|
2331
2349
|
const {
|
|
2332
|
-
|
|
2333
|
-
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults4.blendColorPixelDataAlphaMask,
|
|
2334
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults4.getCircleBrushOrPencilBounds,
|
|
2335
|
-
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults4.getCircleBrushOrPencilStrokeBounds
|
|
2350
|
+
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults5.blendPixelDataAlphaMask
|
|
2336
2351
|
} = deps;
|
|
2337
|
-
const strokeBoundsOut = {
|
|
2338
|
-
x: 0,
|
|
2339
|
-
y: 0,
|
|
2340
|
-
w: 0,
|
|
2341
|
-
h: 0
|
|
2342
|
-
};
|
|
2343
|
-
const circleBrushBounds = {
|
|
2344
|
-
x: 0,
|
|
2345
|
-
y: 0,
|
|
2346
|
-
w: 0,
|
|
2347
|
-
h: 0
|
|
2348
|
-
};
|
|
2349
|
-
const blendColorPixelOptions = {
|
|
2350
|
-
alpha: 255,
|
|
2351
|
-
blendFn: sourceOverPerfect,
|
|
2352
|
-
x: 0,
|
|
2353
|
-
y: 0,
|
|
2354
|
-
w: 0,
|
|
2355
|
-
h: 0
|
|
2356
|
-
};
|
|
2357
|
-
const mask = {
|
|
2358
|
-
type: 0 /* ALPHA */,
|
|
2359
|
-
data: null,
|
|
2360
|
-
w: 0,
|
|
2361
|
-
h: 0
|
|
2362
|
-
};
|
|
2363
2352
|
return {
|
|
2364
|
-
|
|
2365
|
-
const
|
|
2366
|
-
const
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
|
|
2372
|
-
if (bw <= 0 || bh <= 0) return;
|
|
2373
|
-
mask.data = new Uint8Array(bw * bh);
|
|
2374
|
-
mask.w = bw;
|
|
2375
|
-
mask.h = bh;
|
|
2376
|
-
const maskData = mask.data;
|
|
2377
|
-
const brushData = brush.data;
|
|
2378
|
-
const minOffset = brush.minOffset;
|
|
2379
|
-
const target = writer.config.target;
|
|
2380
|
-
const targetWidth = target.width;
|
|
2381
|
-
const targetHeight = target.height;
|
|
2382
|
-
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2383
|
-
const {
|
|
2384
|
-
x: cbx,
|
|
2385
|
-
y: cby,
|
|
2386
|
-
w: cbw,
|
|
2387
|
-
h: cbh
|
|
2388
|
-
} = getCircleBrushOrPencilBounds2(px, py, brushSize, targetWidth, targetHeight, circleBrushBounds);
|
|
2389
|
-
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2390
|
-
const startX = Math.max(bx, cbx);
|
|
2391
|
-
const startY = Math.max(by, cby);
|
|
2392
|
-
const endX = Math.min(bx + bw, cbx + cbw);
|
|
2393
|
-
const endY = Math.min(by + bh, cby + cbh);
|
|
2394
|
-
const unclippedStartX = Math.floor(px + minOffset);
|
|
2395
|
-
const unclippedStartY = Math.floor(py + minOffset);
|
|
2396
|
-
for (let my = startY; my < endY; my++) {
|
|
2397
|
-
const strokeMaskY = my - by;
|
|
2398
|
-
const strokeMaskRowOffset = strokeMaskY * bw;
|
|
2399
|
-
const brushY = my - unclippedStartY;
|
|
2400
|
-
const brushRowOffset = brushY * brushSize;
|
|
2401
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
2402
|
-
const brushX = mx - unclippedStartX;
|
|
2403
|
-
const brushVal = brushData[brushRowOffset + brushX];
|
|
2404
|
-
if (brushVal > 0) {
|
|
2405
|
-
const strokeMaskIdx = strokeMaskRowOffset + (mx - bx);
|
|
2406
|
-
if (brushVal > maskData[strokeMaskIdx]) {
|
|
2407
|
-
maskData[strokeMaskIdx] = brushVal;
|
|
2408
|
-
}
|
|
2409
|
-
}
|
|
2410
|
-
}
|
|
2411
|
-
}
|
|
2412
|
-
});
|
|
2413
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
2414
|
-
blendColorPixelOptions.alpha = alpha;
|
|
2415
|
-
blendColorPixelOptions.x = bx;
|
|
2416
|
-
blendColorPixelOptions.y = by;
|
|
2417
|
-
blendColorPixelOptions.w = bw;
|
|
2418
|
-
blendColorPixelOptions.h = bh;
|
|
2419
|
-
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2353
|
+
blendPixelDataAlphaMask(src, mask, opts = {}) {
|
|
2354
|
+
const x = opts.x ?? 0;
|
|
2355
|
+
const y = opts.y ?? 0;
|
|
2356
|
+
const w = opts.w ?? src.width;
|
|
2357
|
+
const h = opts.h ?? src.height;
|
|
2358
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2359
|
+
return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
|
|
2420
2360
|
}
|
|
2421
2361
|
};
|
|
2422
2362
|
});
|
|
2423
2363
|
|
|
2424
|
-
// src/PixelData/
|
|
2425
|
-
function
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2364
|
+
// src/PixelData/blendPixelDataBinaryMask.ts
|
|
2365
|
+
function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
2366
|
+
const {
|
|
2367
|
+
x: targetX = 0,
|
|
2368
|
+
y: targetY = 0,
|
|
2369
|
+
sx: sourceX = 0,
|
|
2370
|
+
sy: sourceY = 0,
|
|
2371
|
+
w: width = src.width,
|
|
2372
|
+
h: height = src.height,
|
|
2373
|
+
alpha: globalAlpha = 255,
|
|
2374
|
+
blendFn = sourceOverPerfect,
|
|
2375
|
+
mx = 0,
|
|
2376
|
+
my = 0,
|
|
2377
|
+
invertMask = false
|
|
2378
|
+
} = opts;
|
|
2435
2379
|
if (globalAlpha === 0) return false;
|
|
2436
|
-
const baseSrcAlpha = color >>> 24;
|
|
2437
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
2438
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2439
2380
|
let x = targetX;
|
|
2440
2381
|
let y = targetY;
|
|
2382
|
+
let sx = sourceX;
|
|
2383
|
+
let sy = sourceY;
|
|
2384
|
+
let w = width;
|
|
2385
|
+
let h = height;
|
|
2386
|
+
if (sx < 0) {
|
|
2387
|
+
x -= sx;
|
|
2388
|
+
w += sx;
|
|
2389
|
+
sx = 0;
|
|
2390
|
+
}
|
|
2391
|
+
if (sy < 0) {
|
|
2392
|
+
y -= sy;
|
|
2393
|
+
h += sy;
|
|
2394
|
+
sy = 0;
|
|
2395
|
+
}
|
|
2396
|
+
w = Math.min(w, src.width - sx);
|
|
2397
|
+
h = Math.min(h, src.height - sy);
|
|
2441
2398
|
if (x < 0) {
|
|
2399
|
+
sx -= x;
|
|
2442
2400
|
w += x;
|
|
2443
2401
|
x = 0;
|
|
2444
2402
|
}
|
|
2445
2403
|
if (y < 0) {
|
|
2404
|
+
sy -= y;
|
|
2446
2405
|
h += y;
|
|
2447
2406
|
y = 0;
|
|
2448
2407
|
}
|
|
2449
2408
|
const actualW = Math.min(w, dst.width - x);
|
|
2450
2409
|
const actualH = Math.min(h, dst.height - y);
|
|
2451
2410
|
if (actualW <= 0 || actualH <= 0) return false;
|
|
2452
|
-
let baseColorWithGlobalAlpha = color;
|
|
2453
|
-
if (globalAlpha < 255) {
|
|
2454
|
-
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2455
|
-
if (a === 0 && !isOverwrite) return false;
|
|
2456
|
-
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2457
|
-
}
|
|
2458
2411
|
const dx = x - targetX | 0;
|
|
2459
2412
|
const dy = y - targetY | 0;
|
|
2460
2413
|
const dst32 = dst.data32;
|
|
2414
|
+
const src32 = src.data32;
|
|
2461
2415
|
const dw = dst.width;
|
|
2462
|
-
const
|
|
2463
|
-
const
|
|
2416
|
+
const sw = src.width;
|
|
2417
|
+
const mPitch = binaryMask.w;
|
|
2418
|
+
const maskData = binaryMask.data;
|
|
2464
2419
|
let dIdx = y * dw + x | 0;
|
|
2420
|
+
let sIdx = sy * sw + sx | 0;
|
|
2465
2421
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2466
2422
|
const dStride = dw - actualW | 0;
|
|
2423
|
+
const sStride = sw - actualW | 0;
|
|
2467
2424
|
const mStride = mPitch - actualW | 0;
|
|
2468
2425
|
const skipVal = invertMask ? 1 : 0;
|
|
2426
|
+
const isOpaque = globalAlpha === 255;
|
|
2427
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2469
2428
|
let didChange = false;
|
|
2470
2429
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2471
2430
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2472
2431
|
if (maskData[mIdx] === skipVal) {
|
|
2473
2432
|
dIdx++;
|
|
2433
|
+
sIdx++;
|
|
2434
|
+
mIdx++;
|
|
2435
|
+
continue;
|
|
2436
|
+
}
|
|
2437
|
+
const srcCol = src32[sIdx];
|
|
2438
|
+
const srcAlpha = srcCol >>> 24;
|
|
2439
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2440
|
+
dIdx++;
|
|
2441
|
+
sIdx++;
|
|
2474
2442
|
mIdx++;
|
|
2475
2443
|
continue;
|
|
2476
2444
|
}
|
|
2445
|
+
let finalCol = srcCol;
|
|
2446
|
+
if (!isOpaque) {
|
|
2447
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
2448
|
+
if (a === 0 && !isOverwrite) {
|
|
2449
|
+
dIdx++;
|
|
2450
|
+
sIdx++;
|
|
2451
|
+
mIdx++;
|
|
2452
|
+
continue;
|
|
2453
|
+
}
|
|
2454
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2455
|
+
}
|
|
2477
2456
|
const current = dst32[dIdx];
|
|
2478
|
-
const next = blendFn(
|
|
2457
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
2479
2458
|
if (current !== next) {
|
|
2480
2459
|
dst32[dIdx] = next;
|
|
2481
2460
|
didChange = true;
|
|
2482
2461
|
}
|
|
2483
2462
|
dIdx++;
|
|
2463
|
+
sIdx++;
|
|
2484
2464
|
mIdx++;
|
|
2485
2465
|
}
|
|
2486
2466
|
dIdx += dStride;
|
|
2487
|
-
|
|
2488
|
-
}
|
|
2489
|
-
return didChange;
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
|
-
// src/PixelData/blendColorPixelDataCircleMask.ts
|
|
2493
|
-
function blendColorPixelDataCircleMask(target, color, centerX, centerY, brush, alpha = 255, blendFn = sourceOverPerfect, scratchOptions = {}, bounds) {
|
|
2494
|
-
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brush.size, target.width, target.height);
|
|
2495
|
-
if (b.w <= 0 || b.h <= 0) return false;
|
|
2496
|
-
const unclippedStartX = Math.floor(centerX + brush.minOffset);
|
|
2497
|
-
const unclippedStartY = Math.floor(centerY + brush.minOffset);
|
|
2498
|
-
const ix = Math.max(unclippedStartX, b.x);
|
|
2499
|
-
const iy = Math.max(unclippedStartY, b.y);
|
|
2500
|
-
const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
|
|
2501
|
-
const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
|
|
2502
|
-
const iw = ir - ix;
|
|
2503
|
-
const ih = ib - iy;
|
|
2504
|
-
if (iw <= 0 || ih <= 0) return false;
|
|
2505
|
-
scratchOptions.x = ix;
|
|
2506
|
-
scratchOptions.y = iy;
|
|
2507
|
-
scratchOptions.w = iw;
|
|
2508
|
-
scratchOptions.h = ih;
|
|
2509
|
-
scratchOptions.mx = ix - unclippedStartX;
|
|
2510
|
-
scratchOptions.my = iy - unclippedStartY;
|
|
2511
|
-
scratchOptions.alpha = alpha;
|
|
2512
|
-
scratchOptions.blendFn = blendFn;
|
|
2513
|
-
if (brush.type === 0 /* ALPHA */) {
|
|
2514
|
-
return blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
|
|
2515
|
-
}
|
|
2516
|
-
if (brush.type === 1 /* BINARY */) {
|
|
2517
|
-
return blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
|
|
2518
|
-
}
|
|
2519
|
-
return false;
|
|
2520
|
-
}
|
|
2521
|
-
|
|
2522
|
-
// src/History/PixelMutator/mutatorBlendColorCircleMask.ts
|
|
2523
|
-
var defaults5 = {
|
|
2524
|
-
blendColorPixelDataCircleMask,
|
|
2525
|
-
getCircleBrushOrPencilBounds
|
|
2526
|
-
};
|
|
2527
|
-
var mutatorBlendColorCircleMask = ((writer, deps = defaults5) => {
|
|
2528
|
-
const {
|
|
2529
|
-
blendColorPixelDataCircleMask: blendColorPixelDataCircleMask2 = defaults5.blendColorPixelDataCircleMask,
|
|
2530
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
|
|
2531
|
-
} = deps;
|
|
2532
|
-
const boundsOut = {
|
|
2533
|
-
x: 0,
|
|
2534
|
-
y: 0,
|
|
2535
|
-
w: 0,
|
|
2536
|
-
h: 0
|
|
2537
|
-
};
|
|
2538
|
-
const blendColorPixelOptions = {
|
|
2539
|
-
alpha: 255,
|
|
2540
|
-
blendFn: sourceOverPerfect,
|
|
2541
|
-
x: 0,
|
|
2542
|
-
y: 0,
|
|
2543
|
-
w: 0,
|
|
2544
|
-
h: 0
|
|
2545
|
-
};
|
|
2546
|
-
return {
|
|
2547
|
-
applyCircleMask(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
2548
|
-
const target = writer.config.target;
|
|
2549
|
-
const b = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, target.width, target.height, boundsOut);
|
|
2550
|
-
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2551
|
-
return didChange(blendColorPixelDataCircleMask2(target, color, centerX, centerY, brush, alpha, blendFn, blendColorPixelOptions, b));
|
|
2552
|
-
}
|
|
2553
|
-
};
|
|
2554
|
-
});
|
|
2555
|
-
|
|
2556
|
-
// src/History/PixelMutator/mutatorApplyCirclePencil.ts
|
|
2557
|
-
var defaults6 = {
|
|
2558
|
-
applyCircleMaskToPixelData: blendColorPixelDataCircleMask,
|
|
2559
|
-
getCircleBrushOrPencilBounds
|
|
2560
|
-
};
|
|
2561
|
-
var mutatorApplyCirclePencil = ((writer, deps = defaults6) => {
|
|
2562
|
-
const {
|
|
2563
|
-
applyCircleMaskToPixelData = defaults6.applyCircleMaskToPixelData,
|
|
2564
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults6.getCircleBrushOrPencilBounds
|
|
2565
|
-
} = deps;
|
|
2566
|
-
const boundsOut = {
|
|
2567
|
-
x: 0,
|
|
2568
|
-
y: 0,
|
|
2569
|
-
w: 0,
|
|
2570
|
-
h: 0
|
|
2571
|
-
};
|
|
2572
|
-
return {
|
|
2573
|
-
applyCirclePencil(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
2574
|
-
const target = writer.config.target;
|
|
2575
|
-
const b = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, target.width, target.height, boundsOut);
|
|
2576
|
-
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2577
|
-
return didChange(applyCircleMaskToPixelData(target, color, centerX, centerY, brush, alpha, blendFn, b));
|
|
2578
|
-
}
|
|
2579
|
-
};
|
|
2580
|
-
});
|
|
2581
|
-
|
|
2582
|
-
// src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
|
|
2583
|
-
var defaults7 = {
|
|
2584
|
-
forEachLinePoint,
|
|
2585
|
-
blendColorPixelDataBinaryMask,
|
|
2586
|
-
getCircleBrushOrPencilBounds,
|
|
2587
|
-
getCircleBrushOrPencilStrokeBounds
|
|
2588
|
-
};
|
|
2589
|
-
var mutatorApplyCirclePencilStroke = ((writer, deps = defaults7) => {
|
|
2590
|
-
const {
|
|
2591
|
-
forEachLinePoint: forEachLinePoint2 = defaults7.forEachLinePoint,
|
|
2592
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults7.blendColorPixelDataBinaryMask,
|
|
2593
|
-
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults7.getCircleBrushOrPencilStrokeBounds,
|
|
2594
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults7.getCircleBrushOrPencilBounds
|
|
2595
|
-
} = deps;
|
|
2596
|
-
const strokeBoundsOut = {
|
|
2597
|
-
x: 0,
|
|
2598
|
-
y: 0,
|
|
2599
|
-
w: 0,
|
|
2600
|
-
h: 0
|
|
2601
|
-
};
|
|
2602
|
-
const circlePencilBounds = {
|
|
2603
|
-
x: 0,
|
|
2604
|
-
y: 0,
|
|
2605
|
-
w: 0,
|
|
2606
|
-
h: 0
|
|
2607
|
-
};
|
|
2608
|
-
const blendColorPixelOptions = {
|
|
2609
|
-
alpha: 255,
|
|
2610
|
-
blendFn: sourceOverPerfect,
|
|
2611
|
-
x: 0,
|
|
2612
|
-
y: 0,
|
|
2613
|
-
w: 0,
|
|
2614
|
-
h: 0
|
|
2615
|
-
};
|
|
2616
|
-
const mask = {
|
|
2617
|
-
type: 1 /* BINARY */,
|
|
2618
|
-
data: null,
|
|
2619
|
-
w: 0,
|
|
2620
|
-
h: 0
|
|
2621
|
-
};
|
|
2622
|
-
return {
|
|
2623
|
-
applyCirclePencilStroke(color, x0, y0, x1, y1, brush, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2624
|
-
const {
|
|
2625
|
-
x: bx,
|
|
2626
|
-
y: by,
|
|
2627
|
-
w: bw,
|
|
2628
|
-
h: bh
|
|
2629
|
-
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brush.size, strokeBoundsOut);
|
|
2630
|
-
if (bw <= 0 || bh <= 0) return;
|
|
2631
|
-
mask.data = new Uint8Array(bw * bh);
|
|
2632
|
-
mask.w = bw;
|
|
2633
|
-
mask.h = bh;
|
|
2634
|
-
const maskData = mask.data;
|
|
2635
|
-
const target = writer.config.target;
|
|
2636
|
-
const targetWidth = target.width;
|
|
2637
|
-
const targetHeight = target.height;
|
|
2638
|
-
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2639
|
-
const {
|
|
2640
|
-
x: cbx,
|
|
2641
|
-
y: cby,
|
|
2642
|
-
w: cbw,
|
|
2643
|
-
h: cbh
|
|
2644
|
-
} = getCircleBrushOrPencilBounds2(px, py, brush.size, targetWidth, targetHeight, circlePencilBounds);
|
|
2645
|
-
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2646
|
-
const unclippedStartX = Math.floor(px + brush.minOffset);
|
|
2647
|
-
const unclippedStartY = Math.floor(py + brush.minOffset);
|
|
2648
|
-
const startX = Math.max(bx, unclippedStartX);
|
|
2649
|
-
const startY = Math.max(by, unclippedStartY);
|
|
2650
|
-
const endX = Math.min(bx + bw, unclippedStartX + brush.w);
|
|
2651
|
-
const endY = Math.min(by + bh, unclippedStartY + brush.h);
|
|
2652
|
-
for (let my = startY; my < endY; my++) {
|
|
2653
|
-
const brushY = my - unclippedStartY;
|
|
2654
|
-
const maskRowOffset = (my - by) * bw;
|
|
2655
|
-
const brushRowOffset = brushY * brush.w;
|
|
2656
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
2657
|
-
const brushX = mx - unclippedStartX;
|
|
2658
|
-
const brushAlpha = brush.data[brushRowOffset + brushX];
|
|
2659
|
-
if (brushAlpha > 0) {
|
|
2660
|
-
const maskIdx = maskRowOffset + (mx - bx);
|
|
2661
|
-
maskData[maskIdx] = brushAlpha;
|
|
2662
|
-
}
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
});
|
|
2666
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
2667
|
-
blendColorPixelOptions.alpha = alpha;
|
|
2668
|
-
blendColorPixelOptions.x = bx;
|
|
2669
|
-
blendColorPixelOptions.y = by;
|
|
2670
|
-
blendColorPixelOptions.w = bw;
|
|
2671
|
-
blendColorPixelOptions.h = bh;
|
|
2672
|
-
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
2673
|
-
}
|
|
2674
|
-
};
|
|
2675
|
-
});
|
|
2676
|
-
|
|
2677
|
-
// src/Rect/getRectBrushOrPencilBounds.ts
|
|
2678
|
-
function getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight, out) {
|
|
2679
|
-
const startX = Math.floor(centerX - brushWidth / 2);
|
|
2680
|
-
const startY = Math.floor(centerY - brushHeight / 2);
|
|
2681
|
-
const endX = startX + brushWidth;
|
|
2682
|
-
const endY = startY + brushHeight;
|
|
2683
|
-
const res = out ?? {
|
|
2684
|
-
x: 0,
|
|
2685
|
-
y: 0,
|
|
2686
|
-
w: 0,
|
|
2687
|
-
h: 0
|
|
2688
|
-
};
|
|
2689
|
-
const cStartX = Math.max(0, startX);
|
|
2690
|
-
const cStartY = Math.max(0, startY);
|
|
2691
|
-
const cEndX = Math.min(targetWidth, endX);
|
|
2692
|
-
const cEndY = Math.min(targetHeight, endY);
|
|
2693
|
-
const w = cEndX - cStartX;
|
|
2694
|
-
const h = cEndY - cStartY;
|
|
2695
|
-
res.x = cStartX;
|
|
2696
|
-
res.y = cStartY;
|
|
2697
|
-
res.w = w < 0 ? 0 : w;
|
|
2698
|
-
res.h = h < 0 ? 0 : h;
|
|
2699
|
-
return res;
|
|
2700
|
-
}
|
|
2701
|
-
|
|
2702
|
-
// src/PixelData/applyRectBrushToPixelData.ts
|
|
2703
|
-
function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2704
|
-
const targetWidth = target.width;
|
|
2705
|
-
const targetHeight = target.height;
|
|
2706
|
-
const b = bounds ?? getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight);
|
|
2707
|
-
if (b.w <= 0 || b.h <= 0) {
|
|
2708
|
-
return false;
|
|
2709
|
-
}
|
|
2710
|
-
const data32 = target.data32;
|
|
2711
|
-
const baseColor = color & 16777215;
|
|
2712
|
-
const baseSrcAlpha = color >>> 24;
|
|
2713
|
-
const isOpaque = alpha === 255;
|
|
2714
|
-
const invHalfW = 1 / (brushWidth / 2);
|
|
2715
|
-
const invHalfH = 1 / (brushHeight / 2);
|
|
2716
|
-
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2717
|
-
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2718
|
-
const fCenterX = Math.floor(centerX);
|
|
2719
|
-
const fCenterY = Math.floor(centerY);
|
|
2720
|
-
const endX = b.x + b.w;
|
|
2721
|
-
const endY = b.y + b.h;
|
|
2722
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
2723
|
-
let didChange = false;
|
|
2724
|
-
for (let py = b.y; py < endY; py++) {
|
|
2725
|
-
const rowOffset = py * targetWidth;
|
|
2726
|
-
const dy = Math.abs(py - fCenterY + centerOffsetY) * invHalfH;
|
|
2727
|
-
for (let px = b.x; px < endX; px++) {
|
|
2728
|
-
const idx = rowOffset + px;
|
|
2729
|
-
const dx = Math.abs(px - fCenterX + centerOffsetX) * invHalfW;
|
|
2730
|
-
const dist = dx > dy ? dx : dy;
|
|
2731
|
-
const strength = fallOff(dist);
|
|
2732
|
-
const maskVal = strength * 255 | 0;
|
|
2733
|
-
if (maskVal <= 0) continue;
|
|
2734
|
-
let weight = alpha;
|
|
2735
|
-
if (isOpaque) {
|
|
2736
|
-
weight = maskVal;
|
|
2737
|
-
} else if (maskVal !== 255) {
|
|
2738
|
-
weight = maskVal * alpha + 128 >> 8;
|
|
2739
|
-
}
|
|
2740
|
-
let finalCol = color;
|
|
2741
|
-
if (weight < 255) {
|
|
2742
|
-
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2743
|
-
if (a === 0 && !isOverwrite) continue;
|
|
2744
|
-
finalCol = (a << 24 | baseColor) >>> 0;
|
|
2745
|
-
}
|
|
2746
|
-
const current = data32[idx];
|
|
2747
|
-
const next = blendFn(finalCol, current);
|
|
2748
|
-
if (current !== next) {
|
|
2749
|
-
data32[idx] = next;
|
|
2750
|
-
didChange = true;
|
|
2751
|
-
}
|
|
2752
|
-
}
|
|
2753
|
-
}
|
|
2754
|
-
return didChange;
|
|
2755
|
-
}
|
|
2756
|
-
|
|
2757
|
-
// src/History/PixelMutator/mutatorApplyRectBrush.ts
|
|
2758
|
-
var defaults8 = {
|
|
2759
|
-
applyRectBrushToPixelData,
|
|
2760
|
-
getRectBrushOrPencilBounds
|
|
2761
|
-
};
|
|
2762
|
-
var mutatorApplyRectBrush = ((writer, deps = defaults8) => {
|
|
2763
|
-
const {
|
|
2764
|
-
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults8.applyRectBrushToPixelData,
|
|
2765
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds
|
|
2766
|
-
} = deps;
|
|
2767
|
-
const boundsOut = {
|
|
2768
|
-
x: 0,
|
|
2769
|
-
y: 0,
|
|
2770
|
-
w: 0,
|
|
2771
|
-
h: 0
|
|
2772
|
-
};
|
|
2773
|
-
return {
|
|
2774
|
-
applyRectBrush(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn) {
|
|
2775
|
-
const target = writer.config.target;
|
|
2776
|
-
const b = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, target.width, target.height, boundsOut);
|
|
2777
|
-
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2778
|
-
return didChange(applyRectBrushToPixelData2(target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, b));
|
|
2779
|
-
}
|
|
2780
|
-
};
|
|
2781
|
-
});
|
|
2782
|
-
|
|
2783
|
-
// src/Rect/getRectBrushOrPencilStrokeBounds.ts
|
|
2784
|
-
function getRectBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushWidth, brushHeight, result) {
|
|
2785
|
-
const halfW = brushWidth / 2;
|
|
2786
|
-
const halfH = brushHeight / 2;
|
|
2787
|
-
const minX = Math.min(x0, x1) - halfW;
|
|
2788
|
-
const minY = Math.min(y0, y1) - halfH;
|
|
2789
|
-
const maxX = Math.max(x0, x1) + halfW;
|
|
2790
|
-
const maxY = Math.max(y0, y1) + halfH;
|
|
2791
|
-
result.x = Math.floor(minX);
|
|
2792
|
-
result.y = Math.floor(minY);
|
|
2793
|
-
result.w = Math.ceil(maxX - minX);
|
|
2794
|
-
result.h = Math.ceil(maxY - minY);
|
|
2795
|
-
return result;
|
|
2796
|
-
}
|
|
2797
|
-
|
|
2798
|
-
// src/History/PixelMutator/mutatorApplyRectBrushStroke.ts
|
|
2799
|
-
var defaults9 = {
|
|
2800
|
-
forEachLinePoint,
|
|
2801
|
-
blendColorPixelDataAlphaMask,
|
|
2802
|
-
getRectBrushOrPencilBounds,
|
|
2803
|
-
getRectBrushOrPencilStrokeBounds
|
|
2804
|
-
};
|
|
2805
|
-
var mutatorApplyRectBrushStroke = ((writer, deps = defaults9) => {
|
|
2806
|
-
const {
|
|
2807
|
-
forEachLinePoint: forEachLinePoint2 = defaults9.forEachLinePoint,
|
|
2808
|
-
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults9.blendColorPixelDataAlphaMask,
|
|
2809
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
|
|
2810
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults9.getRectBrushOrPencilStrokeBounds
|
|
2811
|
-
} = deps;
|
|
2812
|
-
const strokeBoundsOut = {
|
|
2813
|
-
x: 0,
|
|
2814
|
-
y: 0,
|
|
2815
|
-
w: 0,
|
|
2816
|
-
h: 0
|
|
2817
|
-
};
|
|
2818
|
-
const rectBrushBounds = {
|
|
2819
|
-
x: 0,
|
|
2820
|
-
y: 0,
|
|
2821
|
-
w: 0,
|
|
2822
|
-
h: 0
|
|
2823
|
-
};
|
|
2824
|
-
const blendColorPixelOptions = {
|
|
2825
|
-
alpha: 255,
|
|
2826
|
-
blendFn: sourceOverPerfect,
|
|
2827
|
-
x: 0,
|
|
2828
|
-
y: 0,
|
|
2829
|
-
w: 0,
|
|
2830
|
-
h: 0
|
|
2831
|
-
};
|
|
2832
|
-
const mask = {
|
|
2833
|
-
type: 0 /* ALPHA */,
|
|
2834
|
-
data: null,
|
|
2835
|
-
w: 0,
|
|
2836
|
-
h: 0
|
|
2837
|
-
};
|
|
2838
|
-
return {
|
|
2839
|
-
applyRectBrushStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
2840
|
-
const {
|
|
2841
|
-
x: bx,
|
|
2842
|
-
y: by,
|
|
2843
|
-
w: bw,
|
|
2844
|
-
h: bh
|
|
2845
|
-
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
2846
|
-
if (bw <= 0 || bh <= 0) return;
|
|
2847
|
-
mask.data = new Uint8Array(bw * bh);
|
|
2848
|
-
mask.w = bw;
|
|
2849
|
-
mask.h = bh;
|
|
2850
|
-
const maskData = mask.data;
|
|
2851
|
-
const halfW = brushWidth / 2;
|
|
2852
|
-
const halfH = brushHeight / 2;
|
|
2853
|
-
const invHalfW = 1 / halfW;
|
|
2854
|
-
const invHalfH = 1 / halfH;
|
|
2855
|
-
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2856
|
-
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2857
|
-
const target = writer.config.target;
|
|
2858
|
-
const targetWidth = target.width;
|
|
2859
|
-
const targetHeight = target.height;
|
|
2860
|
-
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2861
|
-
const {
|
|
2862
|
-
x: rbx,
|
|
2863
|
-
y: rby,
|
|
2864
|
-
w: rbw,
|
|
2865
|
-
h: rbh
|
|
2866
|
-
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectBrushBounds);
|
|
2867
|
-
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
2868
|
-
const startX = Math.max(bx, rbx);
|
|
2869
|
-
const startY = Math.max(by, rby);
|
|
2870
|
-
const endX = Math.min(bx + bw, rbx + rbw);
|
|
2871
|
-
const endY = Math.min(by + bh, rby + rbh);
|
|
2872
|
-
const fPx = Math.floor(px);
|
|
2873
|
-
const fPy = Math.floor(py);
|
|
2874
|
-
for (let my = startY; my < endY; my++) {
|
|
2875
|
-
const dy = Math.abs(my - fPy + centerOffsetY) * invHalfH;
|
|
2876
|
-
const maskRowOffset = (my - by) * bw;
|
|
2877
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
2878
|
-
const dx = Math.abs(mx - fPx + centerOffsetX) * invHalfW;
|
|
2879
|
-
const maskIdx = maskRowOffset + (mx - bx);
|
|
2880
|
-
const dist = dx > dy ? dx : dy;
|
|
2881
|
-
const strength = fallOff(dist);
|
|
2882
|
-
if (strength > 0) {
|
|
2883
|
-
const intensity = strength * 255 | 0;
|
|
2884
|
-
if (intensity > maskData[maskIdx]) {
|
|
2885
|
-
maskData[maskIdx] = intensity;
|
|
2886
|
-
}
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
|
-
}
|
|
2890
|
-
});
|
|
2891
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
2892
|
-
blendColorPixelOptions.alpha = alpha;
|
|
2893
|
-
blendColorPixelOptions.x = bx;
|
|
2894
|
-
blendColorPixelOptions.y = by;
|
|
2895
|
-
blendColorPixelOptions.w = bw;
|
|
2896
|
-
blendColorPixelOptions.h = bh;
|
|
2897
|
-
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2898
|
-
}
|
|
2899
|
-
};
|
|
2900
|
-
});
|
|
2901
|
-
|
|
2902
|
-
// src/History/PixelMutator/mutatorApplyRectPencil.ts
|
|
2903
|
-
var defaults10 = {
|
|
2904
|
-
applyRectBrushToPixelData,
|
|
2905
|
-
getRectBrushOrPencilBounds,
|
|
2906
|
-
fallOff: () => 1
|
|
2907
|
-
};
|
|
2908
|
-
var mutatorApplyRectPencil = ((writer, deps = defaults10) => {
|
|
2909
|
-
const {
|
|
2910
|
-
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults10.applyRectBrushToPixelData,
|
|
2911
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults10.getRectBrushOrPencilBounds,
|
|
2912
|
-
fallOff = defaults10.fallOff
|
|
2913
|
-
} = deps;
|
|
2914
|
-
const boundsOut = {
|
|
2915
|
-
x: 0,
|
|
2916
|
-
y: 0,
|
|
2917
|
-
w: 0,
|
|
2918
|
-
h: 0
|
|
2919
|
-
};
|
|
2920
|
-
return {
|
|
2921
|
-
applyRectPencil(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, blendFn) {
|
|
2922
|
-
const target = writer.config.target;
|
|
2923
|
-
const b = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, target.width, target.height, boundsOut);
|
|
2924
|
-
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2925
|
-
return didChange(applyRectBrushToPixelData2(target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, b));
|
|
2926
|
-
}
|
|
2927
|
-
};
|
|
2928
|
-
});
|
|
2929
|
-
|
|
2930
|
-
// src/History/PixelMutator/mutatorApplyRectPencilStroke.ts
|
|
2931
|
-
var defaults11 = {
|
|
2932
|
-
forEachLinePoint,
|
|
2933
|
-
getRectBrushOrPencilBounds,
|
|
2934
|
-
getRectBrushOrPencilStrokeBounds,
|
|
2935
|
-
blendColorPixelDataBinaryMask
|
|
2936
|
-
};
|
|
2937
|
-
var mutatorApplyRectPencilStroke = ((writer, deps = defaults11) => {
|
|
2938
|
-
const {
|
|
2939
|
-
forEachLinePoint: forEachLinePoint2 = defaults11.forEachLinePoint,
|
|
2940
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults11.blendColorPixelDataBinaryMask,
|
|
2941
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults11.getRectBrushOrPencilBounds,
|
|
2942
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults11.getRectBrushOrPencilStrokeBounds
|
|
2943
|
-
} = deps;
|
|
2944
|
-
const strokeBoundsOut = {
|
|
2945
|
-
x: 0,
|
|
2946
|
-
y: 0,
|
|
2947
|
-
w: 0,
|
|
2948
|
-
h: 0
|
|
2949
|
-
};
|
|
2950
|
-
const rectPencilBounds = {
|
|
2951
|
-
x: 0,
|
|
2952
|
-
y: 0,
|
|
2953
|
-
w: 0,
|
|
2954
|
-
h: 0
|
|
2955
|
-
};
|
|
2956
|
-
const blendColorPixelOptions = {
|
|
2957
|
-
alpha: 255,
|
|
2958
|
-
blendFn: sourceOverPerfect,
|
|
2959
|
-
x: 0,
|
|
2960
|
-
y: 0,
|
|
2961
|
-
w: 0,
|
|
2962
|
-
h: 0
|
|
2963
|
-
};
|
|
2964
|
-
const mask = {
|
|
2965
|
-
type: 1 /* BINARY */,
|
|
2966
|
-
data: null,
|
|
2967
|
-
w: 0,
|
|
2968
|
-
h: 0
|
|
2969
|
-
};
|
|
2970
|
-
return {
|
|
2971
|
-
applyRectPencilStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2972
|
-
const {
|
|
2973
|
-
x: bx,
|
|
2974
|
-
y: by,
|
|
2975
|
-
w: bw,
|
|
2976
|
-
h: bh
|
|
2977
|
-
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
2978
|
-
if (bw <= 0 || bh <= 0) return;
|
|
2979
|
-
mask.data = new Uint8Array(bw * bh);
|
|
2980
|
-
mask.w = bw;
|
|
2981
|
-
mask.h = bh;
|
|
2982
|
-
const maskData = mask.data;
|
|
2983
|
-
const halfW = brushWidth / 2;
|
|
2984
|
-
const halfH = brushHeight / 2;
|
|
2985
|
-
const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2986
|
-
const target = writer.config.target;
|
|
2987
|
-
const targetWidth = target.width;
|
|
2988
|
-
const targetHeight = target.height;
|
|
2989
|
-
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2990
|
-
const {
|
|
2991
|
-
x: rbx,
|
|
2992
|
-
y: rby,
|
|
2993
|
-
w: rbw,
|
|
2994
|
-
h: rbh
|
|
2995
|
-
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectPencilBounds);
|
|
2996
|
-
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
2997
|
-
const startX = Math.max(bx, rbx);
|
|
2998
|
-
const startY = Math.max(by, rby);
|
|
2999
|
-
const endX = Math.min(bx + bw, rbx + rbw);
|
|
3000
|
-
const endY = Math.min(by + bh, rby + rbh);
|
|
3001
|
-
const fPx = Math.floor(px);
|
|
3002
|
-
const fPy = Math.floor(py);
|
|
3003
|
-
for (let my = startY; my < endY; my++) {
|
|
3004
|
-
const dy = Math.abs(my - fPy + centerOffset);
|
|
3005
|
-
const maskRowOffset = (my - by) * bw;
|
|
3006
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
3007
|
-
const dx = Math.abs(mx - fPx + centerOffset);
|
|
3008
|
-
const maskIdx = maskRowOffset + (mx - bx);
|
|
3009
|
-
if (dx <= halfW && dy <= halfH) {
|
|
3010
|
-
maskData[maskIdx] = 1;
|
|
3011
|
-
}
|
|
3012
|
-
}
|
|
3013
|
-
}
|
|
3014
|
-
});
|
|
3015
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
3016
|
-
blendColorPixelOptions.alpha = alpha;
|
|
3017
|
-
blendColorPixelOptions.x = bx;
|
|
3018
|
-
blendColorPixelOptions.y = by;
|
|
3019
|
-
blendColorPixelOptions.w = bw;
|
|
3020
|
-
blendColorPixelOptions.h = bh;
|
|
3021
|
-
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
3022
|
-
}
|
|
3023
|
-
};
|
|
3024
|
-
});
|
|
3025
|
-
|
|
3026
|
-
// src/PixelData/blendColorPixelData.ts
|
|
3027
|
-
function blendColorPixelData(dst, color, opts = {}) {
|
|
3028
|
-
const {
|
|
3029
|
-
x: targetX = 0,
|
|
3030
|
-
y: targetY = 0,
|
|
3031
|
-
w: width = dst.width,
|
|
3032
|
-
h: height = dst.height,
|
|
3033
|
-
alpha: globalAlpha = 255,
|
|
3034
|
-
blendFn = sourceOverPerfect
|
|
3035
|
-
} = opts;
|
|
3036
|
-
if (globalAlpha === 0) return false;
|
|
3037
|
-
const baseSrcAlpha = color >>> 24;
|
|
3038
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
3039
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
3040
|
-
let x = targetX;
|
|
3041
|
-
let y = targetY;
|
|
3042
|
-
let w = width;
|
|
3043
|
-
let h = height;
|
|
3044
|
-
if (x < 0) {
|
|
3045
|
-
w += x;
|
|
3046
|
-
x = 0;
|
|
3047
|
-
}
|
|
3048
|
-
if (y < 0) {
|
|
3049
|
-
h += y;
|
|
3050
|
-
y = 0;
|
|
3051
|
-
}
|
|
3052
|
-
const actualW = Math.min(w, dst.width - x);
|
|
3053
|
-
const actualH = Math.min(h, dst.height - y);
|
|
3054
|
-
if (actualW <= 0 || actualH <= 0) return false;
|
|
3055
|
-
let finalSrcColor = color;
|
|
3056
|
-
if (globalAlpha < 255) {
|
|
3057
|
-
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
3058
|
-
if (a === 0 && !isOverwrite) return false;
|
|
3059
|
-
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
3060
|
-
}
|
|
3061
|
-
const dst32 = dst.data32;
|
|
3062
|
-
const dw = dst.width;
|
|
3063
|
-
let dIdx = y * dw + x | 0;
|
|
3064
|
-
const dStride = dw - actualW | 0;
|
|
3065
|
-
let didChange = false;
|
|
3066
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3067
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3068
|
-
const current = dst32[dIdx];
|
|
3069
|
-
const next = blendFn(finalSrcColor, current);
|
|
3070
|
-
if (current !== next) {
|
|
3071
|
-
dst32[dIdx] = next;
|
|
3072
|
-
didChange = true;
|
|
3073
|
-
}
|
|
3074
|
-
dIdx++;
|
|
3075
|
-
}
|
|
3076
|
-
dIdx += dStride;
|
|
3077
|
-
}
|
|
3078
|
-
return didChange;
|
|
3079
|
-
}
|
|
3080
|
-
|
|
3081
|
-
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
3082
|
-
var defaults12 = {
|
|
3083
|
-
blendColorPixelData
|
|
3084
|
-
};
|
|
3085
|
-
var mutatorBlendColor = ((writer, deps = defaults12) => {
|
|
3086
|
-
const {
|
|
3087
|
-
blendColorPixelData: blendColorPixelData2 = defaults12.blendColorPixelData
|
|
3088
|
-
} = deps;
|
|
3089
|
-
return {
|
|
3090
|
-
blendColor(color, opts = {}) {
|
|
3091
|
-
const target = writer.config.target;
|
|
3092
|
-
const {
|
|
3093
|
-
x = 0,
|
|
3094
|
-
y = 0,
|
|
3095
|
-
w = target.width,
|
|
3096
|
-
h = target.height
|
|
3097
|
-
} = opts;
|
|
3098
|
-
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3099
|
-
return didChange(blendColorPixelData2(target, color, opts));
|
|
3100
|
-
}
|
|
3101
|
-
};
|
|
3102
|
-
});
|
|
3103
|
-
|
|
3104
|
-
// src/PixelData/blendPixel.ts
|
|
3105
|
-
function blendPixel(target, x, y, color, alpha = 255, blendFn = sourceOverPerfect) {
|
|
3106
|
-
if (alpha === 0) return false;
|
|
3107
|
-
let width = target.width;
|
|
3108
|
-
let height = target.height;
|
|
3109
|
-
if (x < 0 || x >= width || y < 0 || y >= height) return false;
|
|
3110
|
-
let srcAlpha = color >>> 24;
|
|
3111
|
-
let isOverwrite = blendFn.isOverwrite;
|
|
3112
|
-
if (srcAlpha === 0 && !isOverwrite) return false;
|
|
3113
|
-
let dst32 = target.data32;
|
|
3114
|
-
let index = y * width + x;
|
|
3115
|
-
let finalColor = color;
|
|
3116
|
-
if (alpha !== 255) {
|
|
3117
|
-
let finalAlpha = srcAlpha * alpha + 128 >> 8;
|
|
3118
|
-
if (finalAlpha === 0 && !isOverwrite) return false;
|
|
3119
|
-
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
3120
|
-
}
|
|
3121
|
-
let current = dst32[index];
|
|
3122
|
-
let next = blendFn(finalColor, current);
|
|
3123
|
-
if (current !== next) {
|
|
3124
|
-
dst32[index] = next;
|
|
3125
|
-
return true;
|
|
3126
|
-
}
|
|
3127
|
-
return false;
|
|
3128
|
-
}
|
|
3129
|
-
|
|
3130
|
-
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
3131
|
-
var defaults13 = {
|
|
3132
|
-
blendPixel
|
|
3133
|
-
};
|
|
3134
|
-
var mutatorBlendPixel = ((writer, deps = defaults13) => {
|
|
3135
|
-
const {
|
|
3136
|
-
blendPixel: blendPixel2 = defaults13.blendPixel
|
|
3137
|
-
} = deps;
|
|
3138
|
-
return {
|
|
3139
|
-
blendPixel(x, y, color, alpha, blendFn) {
|
|
3140
|
-
const didChange = writer.accumulator.storePixelBeforeState(x, y);
|
|
3141
|
-
return didChange(blendPixel2(writer.config.target, x, y, color, alpha, blendFn));
|
|
3142
|
-
}
|
|
3143
|
-
};
|
|
3144
|
-
});
|
|
3145
|
-
|
|
3146
|
-
// src/PixelData/blendPixelData.ts
|
|
3147
|
-
function blendPixelData(dst, src, opts = {}) {
|
|
3148
|
-
const {
|
|
3149
|
-
x: targetX = 0,
|
|
3150
|
-
y: targetY = 0,
|
|
3151
|
-
sx: sourceX = 0,
|
|
3152
|
-
sy: sourceY = 0,
|
|
3153
|
-
w: width = src.width,
|
|
3154
|
-
h: height = src.height,
|
|
3155
|
-
alpha: globalAlpha = 255,
|
|
3156
|
-
blendFn = sourceOverPerfect
|
|
3157
|
-
} = opts;
|
|
3158
|
-
if (globalAlpha === 0) return false;
|
|
3159
|
-
let x = targetX;
|
|
3160
|
-
let y = targetY;
|
|
3161
|
-
let sx = sourceX;
|
|
3162
|
-
let sy = sourceY;
|
|
3163
|
-
let w = width;
|
|
3164
|
-
let h = height;
|
|
3165
|
-
if (sx < 0) {
|
|
3166
|
-
x -= sx;
|
|
3167
|
-
w += sx;
|
|
3168
|
-
sx = 0;
|
|
3169
|
-
}
|
|
3170
|
-
if (sy < 0) {
|
|
3171
|
-
y -= sy;
|
|
3172
|
-
h += sy;
|
|
3173
|
-
sy = 0;
|
|
3174
|
-
}
|
|
3175
|
-
w = Math.min(w, src.width - sx);
|
|
3176
|
-
h = Math.min(h, src.height - sy);
|
|
3177
|
-
if (x < 0) {
|
|
3178
|
-
sx -= x;
|
|
3179
|
-
w += x;
|
|
3180
|
-
x = 0;
|
|
3181
|
-
}
|
|
3182
|
-
if (y < 0) {
|
|
3183
|
-
sy -= y;
|
|
3184
|
-
h += y;
|
|
3185
|
-
y = 0;
|
|
3186
|
-
}
|
|
3187
|
-
const actualW = Math.min(w, dst.width - x);
|
|
3188
|
-
const actualH = Math.min(h, dst.height - y);
|
|
3189
|
-
if (actualW <= 0 || actualH <= 0) return false;
|
|
3190
|
-
const dst32 = dst.data32;
|
|
3191
|
-
const src32 = src.data32;
|
|
3192
|
-
const dw = dst.width;
|
|
3193
|
-
const sw = src.width;
|
|
3194
|
-
let dIdx = y * dw + x | 0;
|
|
3195
|
-
let sIdx = sy * sw + sx | 0;
|
|
3196
|
-
const dStride = dw - actualW | 0;
|
|
3197
|
-
const sStride = sw - actualW | 0;
|
|
3198
|
-
const isOpaque = globalAlpha === 255;
|
|
3199
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
3200
|
-
let didChange = false;
|
|
3201
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3202
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3203
|
-
const srcCol = src32[sIdx];
|
|
3204
|
-
const srcAlpha = srcCol >>> 24;
|
|
3205
|
-
if (srcAlpha === 0 && !isOverwrite) {
|
|
3206
|
-
dIdx++;
|
|
3207
|
-
sIdx++;
|
|
3208
|
-
continue;
|
|
3209
|
-
}
|
|
3210
|
-
let finalCol = srcCol;
|
|
3211
|
-
if (!isOpaque) {
|
|
3212
|
-
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
3213
|
-
if (a === 0 && !isOverwrite) {
|
|
3214
|
-
dIdx++;
|
|
3215
|
-
sIdx++;
|
|
3216
|
-
continue;
|
|
3217
|
-
}
|
|
3218
|
-
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3219
|
-
}
|
|
3220
|
-
const current = dst32[dIdx];
|
|
3221
|
-
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3222
|
-
if (current !== next) {
|
|
3223
|
-
dst32[dIdx] = next;
|
|
3224
|
-
didChange = true;
|
|
3225
|
-
}
|
|
3226
|
-
dIdx++;
|
|
3227
|
-
sIdx++;
|
|
3228
|
-
}
|
|
3229
|
-
dIdx += dStride;
|
|
3230
|
-
sIdx += sStride;
|
|
3231
|
-
}
|
|
3232
|
-
return didChange;
|
|
3233
|
-
}
|
|
3234
|
-
|
|
3235
|
-
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
3236
|
-
var defaults14 = {
|
|
3237
|
-
blendPixelData
|
|
3238
|
-
};
|
|
3239
|
-
var mutatorBlendPixelData = ((writer, deps = defaults14) => {
|
|
3240
|
-
const {
|
|
3241
|
-
blendPixelData: blendPixelData2 = defaults14.blendPixelData
|
|
3242
|
-
} = deps;
|
|
3243
|
-
return {
|
|
3244
|
-
blendPixelData(src, opts = {}) {
|
|
3245
|
-
const {
|
|
3246
|
-
x = 0,
|
|
3247
|
-
y = 0,
|
|
3248
|
-
w = src.width,
|
|
3249
|
-
h = src.height
|
|
3250
|
-
} = opts;
|
|
3251
|
-
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3252
|
-
return didChange(blendPixelData2(writer.config.target, src, opts));
|
|
3253
|
-
}
|
|
3254
|
-
};
|
|
3255
|
-
});
|
|
3256
|
-
|
|
3257
|
-
// src/PixelData/blendPixelDataAlphaMask.ts
|
|
3258
|
-
function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
3259
|
-
const {
|
|
3260
|
-
x: targetX = 0,
|
|
3261
|
-
y: targetY = 0,
|
|
3262
|
-
sx: sourceX = 0,
|
|
3263
|
-
sy: sourceY = 0,
|
|
3264
|
-
w: width = src.width,
|
|
3265
|
-
h: height = src.height,
|
|
3266
|
-
alpha: globalAlpha = 255,
|
|
3267
|
-
blendFn = sourceOverPerfect,
|
|
3268
|
-
mx = 0,
|
|
3269
|
-
my = 0,
|
|
3270
|
-
invertMask = false
|
|
3271
|
-
} = opts;
|
|
3272
|
-
if (globalAlpha === 0) return false;
|
|
3273
|
-
let x = targetX;
|
|
3274
|
-
let y = targetY;
|
|
3275
|
-
let sx = sourceX;
|
|
3276
|
-
let sy = sourceY;
|
|
3277
|
-
let w = width;
|
|
3278
|
-
let h = height;
|
|
3279
|
-
if (sx < 0) {
|
|
3280
|
-
x -= sx;
|
|
3281
|
-
w += sx;
|
|
3282
|
-
sx = 0;
|
|
3283
|
-
}
|
|
3284
|
-
if (sy < 0) {
|
|
3285
|
-
y -= sy;
|
|
3286
|
-
h += sy;
|
|
3287
|
-
sy = 0;
|
|
3288
|
-
}
|
|
3289
|
-
w = Math.min(w, src.width - sx);
|
|
3290
|
-
h = Math.min(h, src.height - sy);
|
|
3291
|
-
if (x < 0) {
|
|
3292
|
-
sx -= x;
|
|
3293
|
-
w += x;
|
|
3294
|
-
x = 0;
|
|
3295
|
-
}
|
|
3296
|
-
if (y < 0) {
|
|
3297
|
-
sy -= y;
|
|
3298
|
-
h += y;
|
|
3299
|
-
y = 0;
|
|
3300
|
-
}
|
|
3301
|
-
const actualW = Math.min(w, dst.width - x);
|
|
3302
|
-
const actualH = Math.min(h, dst.height - y);
|
|
3303
|
-
if (actualW <= 0 || actualH <= 0) return false;
|
|
3304
|
-
const dw = dst.width;
|
|
3305
|
-
const sw = src.width;
|
|
3306
|
-
const mPitch = alphaMask.w;
|
|
3307
|
-
const maskData = alphaMask.data;
|
|
3308
|
-
const dx = x - targetX | 0;
|
|
3309
|
-
const dy = y - targetY | 0;
|
|
3310
|
-
const dst32 = dst.data32;
|
|
3311
|
-
const src32 = src.data32;
|
|
3312
|
-
let dIdx = y * dw + x | 0;
|
|
3313
|
-
let sIdx = sy * sw + sx | 0;
|
|
3314
|
-
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
3315
|
-
const dStride = dw - actualW | 0;
|
|
3316
|
-
const sStride = sw - actualW | 0;
|
|
3317
|
-
const mStride = mPitch - actualW | 0;
|
|
3318
|
-
const isOpaque = globalAlpha === 255;
|
|
3319
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
3320
|
-
let didChange = false;
|
|
3321
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3322
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3323
|
-
const mVal = maskData[mIdx];
|
|
3324
|
-
const effM = invertMask ? 255 - mVal : mVal;
|
|
3325
|
-
if (effM === 0) {
|
|
3326
|
-
dIdx++;
|
|
3327
|
-
sIdx++;
|
|
3328
|
-
mIdx++;
|
|
3329
|
-
continue;
|
|
3330
|
-
}
|
|
3331
|
-
const srcCol = src32[sIdx];
|
|
3332
|
-
const srcAlpha = srcCol >>> 24;
|
|
3333
|
-
if (srcAlpha === 0 && !isOverwrite) {
|
|
3334
|
-
dIdx++;
|
|
3335
|
-
sIdx++;
|
|
3336
|
-
mIdx++;
|
|
3337
|
-
continue;
|
|
3338
|
-
}
|
|
3339
|
-
let weight = globalAlpha;
|
|
3340
|
-
if (isOpaque) {
|
|
3341
|
-
weight = effM;
|
|
3342
|
-
} else if (effM !== 255) {
|
|
3343
|
-
weight = effM * globalAlpha + 128 >> 8;
|
|
3344
|
-
}
|
|
3345
|
-
if (weight === 0) {
|
|
3346
|
-
dIdx++;
|
|
3347
|
-
sIdx++;
|
|
3348
|
-
mIdx++;
|
|
3349
|
-
continue;
|
|
3350
|
-
}
|
|
3351
|
-
let finalCol = srcCol;
|
|
3352
|
-
if (weight < 255) {
|
|
3353
|
-
const a = srcAlpha * weight + 128 >> 8;
|
|
3354
|
-
if (a === 0 && !isOverwrite) {
|
|
3355
|
-
dIdx++;
|
|
3356
|
-
sIdx++;
|
|
3357
|
-
mIdx++;
|
|
3358
|
-
continue;
|
|
3359
|
-
}
|
|
3360
|
-
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3361
|
-
}
|
|
3362
|
-
const current = dst32[dIdx];
|
|
3363
|
-
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3364
|
-
if (current !== next) {
|
|
3365
|
-
dst32[dIdx] = next;
|
|
3366
|
-
didChange = true;
|
|
3367
|
-
}
|
|
3368
|
-
dIdx++;
|
|
3369
|
-
sIdx++;
|
|
3370
|
-
mIdx++;
|
|
3371
|
-
}
|
|
3372
|
-
dIdx += dStride;
|
|
3373
|
-
sIdx += sStride;
|
|
3374
|
-
mIdx += mStride;
|
|
3375
|
-
}
|
|
3376
|
-
return didChange;
|
|
3377
|
-
}
|
|
3378
|
-
|
|
3379
|
-
// src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts
|
|
3380
|
-
var defaults15 = {
|
|
3381
|
-
blendPixelDataAlphaMask
|
|
3382
|
-
};
|
|
3383
|
-
var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults15) => {
|
|
3384
|
-
const {
|
|
3385
|
-
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults15.blendPixelDataAlphaMask
|
|
3386
|
-
} = deps;
|
|
3387
|
-
return {
|
|
3388
|
-
blendPixelDataAlphaMask(src, mask, opts = {}) {
|
|
3389
|
-
const x = opts.x ?? 0;
|
|
3390
|
-
const y = opts.y ?? 0;
|
|
3391
|
-
const w = opts.w ?? src.width;
|
|
3392
|
-
const h = opts.h ?? src.height;
|
|
3393
|
-
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3394
|
-
return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
|
|
3395
|
-
}
|
|
3396
|
-
};
|
|
3397
|
-
});
|
|
3398
|
-
|
|
3399
|
-
// src/PixelData/blendPixelDataBinaryMask.ts
|
|
3400
|
-
function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
3401
|
-
const {
|
|
3402
|
-
x: targetX = 0,
|
|
3403
|
-
y: targetY = 0,
|
|
3404
|
-
sx: sourceX = 0,
|
|
3405
|
-
sy: sourceY = 0,
|
|
3406
|
-
w: width = src.width,
|
|
3407
|
-
h: height = src.height,
|
|
3408
|
-
alpha: globalAlpha = 255,
|
|
3409
|
-
blendFn = sourceOverPerfect,
|
|
3410
|
-
mx = 0,
|
|
3411
|
-
my = 0,
|
|
3412
|
-
invertMask = false
|
|
3413
|
-
} = opts;
|
|
3414
|
-
if (globalAlpha === 0) return false;
|
|
3415
|
-
let x = targetX;
|
|
3416
|
-
let y = targetY;
|
|
3417
|
-
let sx = sourceX;
|
|
3418
|
-
let sy = sourceY;
|
|
3419
|
-
let w = width;
|
|
3420
|
-
let h = height;
|
|
3421
|
-
if (sx < 0) {
|
|
3422
|
-
x -= sx;
|
|
3423
|
-
w += sx;
|
|
3424
|
-
sx = 0;
|
|
3425
|
-
}
|
|
3426
|
-
if (sy < 0) {
|
|
3427
|
-
y -= sy;
|
|
3428
|
-
h += sy;
|
|
3429
|
-
sy = 0;
|
|
3430
|
-
}
|
|
3431
|
-
w = Math.min(w, src.width - sx);
|
|
3432
|
-
h = Math.min(h, src.height - sy);
|
|
3433
|
-
if (x < 0) {
|
|
3434
|
-
sx -= x;
|
|
3435
|
-
w += x;
|
|
3436
|
-
x = 0;
|
|
3437
|
-
}
|
|
3438
|
-
if (y < 0) {
|
|
3439
|
-
sy -= y;
|
|
3440
|
-
h += y;
|
|
3441
|
-
y = 0;
|
|
3442
|
-
}
|
|
3443
|
-
const actualW = Math.min(w, dst.width - x);
|
|
3444
|
-
const actualH = Math.min(h, dst.height - y);
|
|
3445
|
-
if (actualW <= 0 || actualH <= 0) return false;
|
|
3446
|
-
const dx = x - targetX | 0;
|
|
3447
|
-
const dy = y - targetY | 0;
|
|
3448
|
-
const dst32 = dst.data32;
|
|
3449
|
-
const src32 = src.data32;
|
|
3450
|
-
const dw = dst.width;
|
|
3451
|
-
const sw = src.width;
|
|
3452
|
-
const mPitch = binaryMask.w;
|
|
3453
|
-
const maskData = binaryMask.data;
|
|
3454
|
-
let dIdx = y * dw + x | 0;
|
|
3455
|
-
let sIdx = sy * sw + sx | 0;
|
|
3456
|
-
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
3457
|
-
const dStride = dw - actualW | 0;
|
|
3458
|
-
const sStride = sw - actualW | 0;
|
|
3459
|
-
const mStride = mPitch - actualW | 0;
|
|
3460
|
-
const skipVal = invertMask ? 1 : 0;
|
|
3461
|
-
const isOpaque = globalAlpha === 255;
|
|
3462
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
3463
|
-
let didChange = false;
|
|
3464
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3465
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3466
|
-
if (maskData[mIdx] === skipVal) {
|
|
3467
|
-
dIdx++;
|
|
3468
|
-
sIdx++;
|
|
3469
|
-
mIdx++;
|
|
3470
|
-
continue;
|
|
3471
|
-
}
|
|
3472
|
-
const srcCol = src32[sIdx];
|
|
3473
|
-
const srcAlpha = srcCol >>> 24;
|
|
3474
|
-
if (srcAlpha === 0 && !isOverwrite) {
|
|
3475
|
-
dIdx++;
|
|
3476
|
-
sIdx++;
|
|
3477
|
-
mIdx++;
|
|
3478
|
-
continue;
|
|
3479
|
-
}
|
|
3480
|
-
let finalCol = srcCol;
|
|
3481
|
-
if (!isOpaque) {
|
|
3482
|
-
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
3483
|
-
if (a === 0 && !isOverwrite) {
|
|
3484
|
-
dIdx++;
|
|
3485
|
-
sIdx++;
|
|
3486
|
-
mIdx++;
|
|
3487
|
-
continue;
|
|
3488
|
-
}
|
|
3489
|
-
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3490
|
-
}
|
|
3491
|
-
const current = dst32[dIdx];
|
|
3492
|
-
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3493
|
-
if (current !== next) {
|
|
3494
|
-
dst32[dIdx] = next;
|
|
3495
|
-
didChange = true;
|
|
3496
|
-
}
|
|
3497
|
-
dIdx++;
|
|
3498
|
-
sIdx++;
|
|
3499
|
-
mIdx++;
|
|
3500
|
-
}
|
|
3501
|
-
dIdx += dStride;
|
|
3502
|
-
sIdx += sStride;
|
|
2467
|
+
sIdx += sStride;
|
|
3503
2468
|
mIdx += mStride;
|
|
3504
2469
|
}
|
|
3505
2470
|
return didChange;
|
|
3506
2471
|
}
|
|
3507
2472
|
|
|
3508
2473
|
// src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts
|
|
3509
|
-
var
|
|
2474
|
+
var defaults6 = {
|
|
3510
2475
|
blendPixelDataBinaryMask
|
|
3511
2476
|
};
|
|
3512
|
-
var mutatorBlendPixelDataBinaryMask = ((writer, deps =
|
|
2477
|
+
var mutatorBlendPixelDataBinaryMask = ((writer, deps = defaults6) => {
|
|
3513
2478
|
const {
|
|
3514
|
-
blendPixelDataBinaryMask: blendPixelDataBinaryMask2 =
|
|
2479
|
+
blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults6.blendPixelDataBinaryMask
|
|
3515
2480
|
} = deps;
|
|
3516
2481
|
return {
|
|
3517
2482
|
blendPixelDataBinaryMask(src, mask, opts = {}) {
|
|
@@ -3570,12 +2535,12 @@ function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
|
|
|
3570
2535
|
}
|
|
3571
2536
|
|
|
3572
2537
|
// src/History/PixelMutator/mutatorClear.ts
|
|
3573
|
-
var
|
|
2538
|
+
var defaults7 = {
|
|
3574
2539
|
fillPixelData: fillPixelDataFast
|
|
3575
2540
|
};
|
|
3576
|
-
var mutatorClear = ((writer, deps =
|
|
2541
|
+
var mutatorClear = ((writer, deps = defaults7) => {
|
|
3577
2542
|
const {
|
|
3578
|
-
fillPixelData: fillPixelData2 =
|
|
2543
|
+
fillPixelData: fillPixelData2 = defaults7.fillPixelData
|
|
3579
2544
|
} = deps;
|
|
3580
2545
|
return {
|
|
3581
2546
|
clear(rect = {}) {
|
|
@@ -3639,12 +2604,12 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
|
3639
2604
|
}
|
|
3640
2605
|
|
|
3641
2606
|
// src/History/PixelMutator/mutatorFill.ts
|
|
3642
|
-
var
|
|
2607
|
+
var defaults8 = {
|
|
3643
2608
|
fillPixelData
|
|
3644
2609
|
};
|
|
3645
|
-
var mutatorFill = ((writer, deps =
|
|
2610
|
+
var mutatorFill = ((writer, deps = defaults8) => {
|
|
3646
2611
|
const {
|
|
3647
|
-
fillPixelData: fillPixelData2 =
|
|
2612
|
+
fillPixelData: fillPixelData2 = defaults8.fillPixelData
|
|
3648
2613
|
} = deps;
|
|
3649
2614
|
return {
|
|
3650
2615
|
fill(color, x = 0, y = 0, w = writer.config.target.width, h = writer.config.target.height) {
|
|
@@ -3654,9 +2619,9 @@ var mutatorFill = ((writer, deps = defaults18) => {
|
|
|
3654
2619
|
}
|
|
3655
2620
|
};
|
|
3656
2621
|
});
|
|
3657
|
-
var mutatorFillRect = ((writer, deps =
|
|
2622
|
+
var mutatorFillRect = ((writer, deps = defaults8) => {
|
|
3658
2623
|
const {
|
|
3659
|
-
fillPixelData: fillPixelData2 =
|
|
2624
|
+
fillPixelData: fillPixelData2 = defaults8.fillPixelData
|
|
3660
2625
|
} = deps;
|
|
3661
2626
|
return {
|
|
3662
2627
|
fillRect(color, rect) {
|
|
@@ -3714,12 +2679,12 @@ function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
|
3714
2679
|
}
|
|
3715
2680
|
|
|
3716
2681
|
// src/History/PixelMutator/mutatorFillBinaryMask.ts
|
|
3717
|
-
var
|
|
2682
|
+
var defaults9 = {
|
|
3718
2683
|
fillPixelDataBinaryMask
|
|
3719
2684
|
};
|
|
3720
|
-
var mutatorFillBinaryMask = ((writer, deps =
|
|
2685
|
+
var mutatorFillBinaryMask = ((writer, deps = defaults9) => {
|
|
3721
2686
|
const {
|
|
3722
|
-
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 =
|
|
2687
|
+
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults9.fillPixelDataBinaryMask
|
|
3723
2688
|
} = deps;
|
|
3724
2689
|
return {
|
|
3725
2690
|
fillBinaryMask(color, mask, alpha = 255, x = 0, y = 0) {
|
|
@@ -3784,58 +2749,285 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3784
2749
|
dIdx += dStride;
|
|
3785
2750
|
}
|
|
3786
2751
|
}
|
|
3787
|
-
return true;
|
|
3788
|
-
}
|
|
3789
|
-
|
|
3790
|
-
// src/History/PixelMutator/mutatorInvert.ts
|
|
3791
|
-
var
|
|
3792
|
-
invertPixelData
|
|
2752
|
+
return true;
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
// src/History/PixelMutator/mutatorInvert.ts
|
|
2756
|
+
var defaults10 = {
|
|
2757
|
+
invertPixelData
|
|
2758
|
+
};
|
|
2759
|
+
var mutatorInvert = ((writer, deps = defaults10) => {
|
|
2760
|
+
const {
|
|
2761
|
+
invertPixelData: invertPixelData2 = defaults10.invertPixelData
|
|
2762
|
+
} = deps;
|
|
2763
|
+
return {
|
|
2764
|
+
invert(opts = {}) {
|
|
2765
|
+
const target = writer.config.target;
|
|
2766
|
+
const {
|
|
2767
|
+
x = 0,
|
|
2768
|
+
y = 0,
|
|
2769
|
+
w = target.width,
|
|
2770
|
+
h = target.height
|
|
2771
|
+
} = opts;
|
|
2772
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2773
|
+
return didChange(invertPixelData2(target, opts));
|
|
2774
|
+
}
|
|
2775
|
+
};
|
|
2776
|
+
});
|
|
2777
|
+
|
|
2778
|
+
// src/History/PixelMutator.ts
|
|
2779
|
+
function makeFullPixelMutator(writer) {
|
|
2780
|
+
return {
|
|
2781
|
+
// @sort
|
|
2782
|
+
...mutatorBlendColor(writer),
|
|
2783
|
+
...mutatorBlendPixel(writer),
|
|
2784
|
+
...mutatorBlendPixelData(writer),
|
|
2785
|
+
...mutatorBlendPixelDataAlphaMask(writer),
|
|
2786
|
+
...mutatorBlendPixelDataBinaryMask(writer),
|
|
2787
|
+
...mutatorClear(writer),
|
|
2788
|
+
...mutatorFill(writer),
|
|
2789
|
+
...mutatorFillBinaryMask(writer),
|
|
2790
|
+
...mutatorFillRect(writer),
|
|
2791
|
+
...mutatorInvert(writer)
|
|
2792
|
+
};
|
|
2793
|
+
}
|
|
2794
|
+
|
|
2795
|
+
// src/ImageData/resizeImageData.ts
|
|
2796
|
+
function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
2797
|
+
const result = new ImageData(newWidth, newHeight);
|
|
2798
|
+
const {
|
|
2799
|
+
width: oldW,
|
|
2800
|
+
height: oldH,
|
|
2801
|
+
data: oldData
|
|
2802
|
+
} = target;
|
|
2803
|
+
const newData = result.data;
|
|
2804
|
+
const x0 = Math.max(0, offsetX);
|
|
2805
|
+
const y0 = Math.max(0, offsetY);
|
|
2806
|
+
const x1 = Math.min(newWidth, offsetX + oldW);
|
|
2807
|
+
const y1 = Math.min(newHeight, offsetY + oldH);
|
|
2808
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
2809
|
+
return result;
|
|
2810
|
+
}
|
|
2811
|
+
const rowCount = y1 - y0;
|
|
2812
|
+
const rowLen = (x1 - x0) * 4;
|
|
2813
|
+
for (let row = 0; row < rowCount; row++) {
|
|
2814
|
+
const dstY = y0 + row;
|
|
2815
|
+
const srcY = dstY - offsetY;
|
|
2816
|
+
const srcX = x0 - offsetX;
|
|
2817
|
+
const dstStart = (dstY * newWidth + x0) * 4;
|
|
2818
|
+
const srcStart = (srcY * oldW + srcX) * 4;
|
|
2819
|
+
newData.set(oldData.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
2820
|
+
}
|
|
2821
|
+
return result;
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
// src/Rect/trimRectBounds.ts
|
|
2825
|
+
function trimRectBounds(x, y, w, h, targetWidth, targetHeight, out) {
|
|
2826
|
+
const res = out ?? {
|
|
2827
|
+
x: 0,
|
|
2828
|
+
y: 0,
|
|
2829
|
+
w: 0,
|
|
2830
|
+
h: 0
|
|
2831
|
+
};
|
|
2832
|
+
const left = Math.max(0, x);
|
|
2833
|
+
const top = Math.max(0, y);
|
|
2834
|
+
const right = Math.min(targetWidth, x + w);
|
|
2835
|
+
const bottom = Math.min(targetHeight, y + h);
|
|
2836
|
+
res.x = left;
|
|
2837
|
+
res.y = top;
|
|
2838
|
+
res.w = Math.max(0, right - left);
|
|
2839
|
+
res.h = Math.max(0, bottom - top);
|
|
2840
|
+
return res;
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
// src/Paint/PaintBuffer.ts
|
|
2844
|
+
var PaintBuffer = class {
|
|
2845
|
+
constructor(config, tilePool) {
|
|
2846
|
+
this.config = config;
|
|
2847
|
+
this.tilePool = tilePool;
|
|
2848
|
+
this.lookup = [];
|
|
2849
|
+
}
|
|
2850
|
+
lookup;
|
|
2851
|
+
scratchBounds = {
|
|
2852
|
+
x: 0,
|
|
2853
|
+
y: 0,
|
|
2854
|
+
w: 0,
|
|
2855
|
+
h: 0
|
|
2856
|
+
};
|
|
2857
|
+
eachTileInBounds(bounds, callback) {
|
|
2858
|
+
const {
|
|
2859
|
+
tileShift,
|
|
2860
|
+
targetColumns,
|
|
2861
|
+
targetRows,
|
|
2862
|
+
tileSize
|
|
2863
|
+
} = this.config;
|
|
2864
|
+
const x1 = Math.max(0, bounds.x >> tileShift);
|
|
2865
|
+
const y1 = Math.max(0, bounds.y >> tileShift);
|
|
2866
|
+
const x2 = Math.min(targetColumns - 1, bounds.x + bounds.w - 1 >> tileShift);
|
|
2867
|
+
const y2 = Math.min(targetRows - 1, bounds.y + bounds.h - 1 >> tileShift);
|
|
2868
|
+
if (x1 > x2 || y1 > y2) return;
|
|
2869
|
+
const lookup = this.lookup;
|
|
2870
|
+
const tilePool = this.tilePool;
|
|
2871
|
+
for (let ty = y1; ty <= y2; ty++) {
|
|
2872
|
+
const rowOffset = ty * targetColumns;
|
|
2873
|
+
const tileTop = ty << tileShift;
|
|
2874
|
+
for (let tx = x1; tx <= x2; tx++) {
|
|
2875
|
+
const id = rowOffset + tx;
|
|
2876
|
+
const tile = lookup[id] ?? (lookup[id] = tilePool.getTile(id, tx, ty));
|
|
2877
|
+
const tileLeft = tx << tileShift;
|
|
2878
|
+
const startX = bounds.x > tileLeft ? bounds.x : tileLeft;
|
|
2879
|
+
const startY = bounds.y > tileTop ? bounds.y : tileTop;
|
|
2880
|
+
const maskEndX = bounds.x + bounds.w;
|
|
2881
|
+
const tileEndX = tileLeft + tileSize;
|
|
2882
|
+
const endX = maskEndX < tileEndX ? maskEndX : tileEndX;
|
|
2883
|
+
const maskEndY = bounds.y + bounds.h;
|
|
2884
|
+
const tileEndY = tileTop + tileSize;
|
|
2885
|
+
const endY = maskEndY < tileEndY ? maskEndY : tileEndY;
|
|
2886
|
+
callback(tile, startX, startY, endX - startX, endY - startY);
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
writePaintAlphaMaskStroke(color, brush, x0, y0, x1, y1) {
|
|
2891
|
+
const cA = color >>> 24;
|
|
2892
|
+
if (cA === 0) return false;
|
|
2893
|
+
const {
|
|
2894
|
+
tileShift,
|
|
2895
|
+
tileMask,
|
|
2896
|
+
target
|
|
2897
|
+
} = this.config;
|
|
2898
|
+
const {
|
|
2899
|
+
w: bW,
|
|
2900
|
+
h: bH,
|
|
2901
|
+
data: bD,
|
|
2902
|
+
centerOffsetX,
|
|
2903
|
+
centerOffsetY
|
|
2904
|
+
} = brush;
|
|
2905
|
+
const cRGB = color & 16777215;
|
|
2906
|
+
const scratch = this.scratchBounds;
|
|
2907
|
+
let changed = false;
|
|
2908
|
+
forEachLinePoint(x0, y0, x1, y1, (px, py) => {
|
|
2909
|
+
const topLeftX = Math.floor(px + centerOffsetX);
|
|
2910
|
+
const topLeftY = Math.floor(py + centerOffsetY);
|
|
2911
|
+
trimRectBounds(topLeftX, topLeftY, bW, bH, target.width, target.height, scratch);
|
|
2912
|
+
if (scratch.w <= 0 || scratch.h <= 0) return;
|
|
2913
|
+
this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
|
|
2914
|
+
const d32 = tile.data32;
|
|
2915
|
+
let tileChanged = false;
|
|
2916
|
+
for (let i = 0; i < bH_t; i++) {
|
|
2917
|
+
const canvasY = bY + i;
|
|
2918
|
+
const bOff = (canvasY - topLeftY) * bW;
|
|
2919
|
+
const tOff = (canvasY & tileMask) << tileShift;
|
|
2920
|
+
const dS = tOff + (bX & tileMask);
|
|
2921
|
+
for (let j = 0; j < bW_t; j++) {
|
|
2922
|
+
const canvasX = bX + j;
|
|
2923
|
+
const brushA = bD[bOff + (canvasX - topLeftX)];
|
|
2924
|
+
if (brushA === 0) continue;
|
|
2925
|
+
const t = cA * brushA + 128;
|
|
2926
|
+
const blendedA = t + (t >> 8) >> 8;
|
|
2927
|
+
const idx = dS + j;
|
|
2928
|
+
const cur = d32[idx];
|
|
2929
|
+
if (brushA > cur >>> 24) {
|
|
2930
|
+
const next = (cRGB | blendedA << 24) >>> 0;
|
|
2931
|
+
if (cur !== next) {
|
|
2932
|
+
d32[idx] = next;
|
|
2933
|
+
tileChanged = true;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
if (tileChanged) changed = true;
|
|
2939
|
+
});
|
|
2940
|
+
});
|
|
2941
|
+
return changed;
|
|
2942
|
+
}
|
|
2943
|
+
writePaintBinaryMaskStroke(color, brush, x0, y0, x1, y1) {
|
|
2944
|
+
const alphaIsZero = color >>> 24 === 0;
|
|
2945
|
+
if (alphaIsZero) return false;
|
|
2946
|
+
const {
|
|
2947
|
+
tileShift,
|
|
2948
|
+
tileMask,
|
|
2949
|
+
target
|
|
2950
|
+
} = this.config;
|
|
2951
|
+
const {
|
|
2952
|
+
w: bW,
|
|
2953
|
+
h: bH,
|
|
2954
|
+
data: bD,
|
|
2955
|
+
centerOffsetX,
|
|
2956
|
+
centerOffsetY
|
|
2957
|
+
} = brush;
|
|
2958
|
+
const scratch = this.scratchBounds;
|
|
2959
|
+
let changed = false;
|
|
2960
|
+
forEachLinePoint(x0, y0, x1, y1, (px, py) => {
|
|
2961
|
+
const topLeftX = Math.floor(px + centerOffsetX);
|
|
2962
|
+
const topLeftY = Math.floor(py + centerOffsetY);
|
|
2963
|
+
trimRectBounds(topLeftX, topLeftY, bW, bH, target.width, target.height, scratch);
|
|
2964
|
+
if (scratch.w <= 0 || scratch.h <= 0) return;
|
|
2965
|
+
this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
|
|
2966
|
+
const d32 = tile.data32;
|
|
2967
|
+
let tileChanged = false;
|
|
2968
|
+
for (let i = 0; i < bH_t; i++) {
|
|
2969
|
+
const canvasY = bY + i;
|
|
2970
|
+
const bOff = (canvasY - topLeftY) * bW;
|
|
2971
|
+
const tOff = (canvasY & tileMask) << tileShift;
|
|
2972
|
+
const dS = tOff + (bX & tileMask);
|
|
2973
|
+
for (let j = 0; j < bW_t; j++) {
|
|
2974
|
+
const canvasX = bX + j;
|
|
2975
|
+
if (bD[bOff + (canvasX - topLeftX)]) {
|
|
2976
|
+
const idx = dS + j;
|
|
2977
|
+
if (d32[idx] !== color) {
|
|
2978
|
+
d32[idx] = color;
|
|
2979
|
+
tileChanged = true;
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
if (tileChanged) changed = true;
|
|
2985
|
+
});
|
|
2986
|
+
});
|
|
2987
|
+
return changed;
|
|
2988
|
+
}
|
|
2989
|
+
writeRectStroke(color, brushWidth, brushHeight, x0, y0, x1, y1) {
|
|
2990
|
+
const alphaIsZero = color >>> 24 === 0;
|
|
2991
|
+
if (alphaIsZero) return false;
|
|
2992
|
+
const config = this.config;
|
|
2993
|
+
const tileShift = config.tileShift;
|
|
2994
|
+
const tileMask = config.tileMask;
|
|
2995
|
+
const target = config.target;
|
|
2996
|
+
const scratch = this.scratchBounds;
|
|
2997
|
+
const centerOffsetX = brushWidth - 1 >> 1;
|
|
2998
|
+
const centerOffsetY = brushHeight - 1 >> 1;
|
|
2999
|
+
let changed = false;
|
|
3000
|
+
forEachLinePoint(x0, y0, x1, y1, (px, py) => {
|
|
3001
|
+
const topLeftX = Math.floor(px + centerOffsetX);
|
|
3002
|
+
const topLeftY = Math.floor(py + centerOffsetY);
|
|
3003
|
+
trimRectBounds(topLeftX, topLeftY, brushWidth, brushHeight, target.width, target.height, scratch);
|
|
3004
|
+
if (scratch.w <= 0 || scratch.h <= 0) return;
|
|
3005
|
+
this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
|
|
3006
|
+
const d32 = tile.data32;
|
|
3007
|
+
let tileChanged = false;
|
|
3008
|
+
for (let i = 0; i < bH_t; i++) {
|
|
3009
|
+
const canvasY = bY + i;
|
|
3010
|
+
const tOff = (canvasY & tileMask) << tileShift;
|
|
3011
|
+
const dS = tOff + (bX & tileMask);
|
|
3012
|
+
for (let j = 0; j < bW_t; j++) {
|
|
3013
|
+
const idx = dS + j;
|
|
3014
|
+
if (d32[idx] !== color) {
|
|
3015
|
+
d32[idx] = color;
|
|
3016
|
+
tileChanged = true;
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
if (tileChanged) {
|
|
3021
|
+
changed = true;
|
|
3022
|
+
}
|
|
3023
|
+
});
|
|
3024
|
+
});
|
|
3025
|
+
return changed;
|
|
3026
|
+
}
|
|
3027
|
+
clear() {
|
|
3028
|
+
this.tilePool.releaseTiles(this.lookup);
|
|
3029
|
+
}
|
|
3793
3030
|
};
|
|
3794
|
-
var mutatorInvert = ((writer, deps = defaults20) => {
|
|
3795
|
-
const {
|
|
3796
|
-
invertPixelData: invertPixelData2 = defaults20.invertPixelData
|
|
3797
|
-
} = deps;
|
|
3798
|
-
return {
|
|
3799
|
-
invert(opts = {}) {
|
|
3800
|
-
const target = writer.config.target;
|
|
3801
|
-
const {
|
|
3802
|
-
x = 0,
|
|
3803
|
-
y = 0,
|
|
3804
|
-
w = target.width,
|
|
3805
|
-
h = target.height
|
|
3806
|
-
} = opts;
|
|
3807
|
-
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3808
|
-
return didChange(invertPixelData2(target, opts));
|
|
3809
|
-
}
|
|
3810
|
-
};
|
|
3811
|
-
});
|
|
3812
|
-
|
|
3813
|
-
// src/History/PixelMutator.ts
|
|
3814
|
-
function makeFullPixelMutator(writer) {
|
|
3815
|
-
return {
|
|
3816
|
-
// @sort
|
|
3817
|
-
...mutatorApplyAlphaMask(writer),
|
|
3818
|
-
...mutatorApplyBinaryMask(writer),
|
|
3819
|
-
...mutatorApplyCircleBrushStroke(writer),
|
|
3820
|
-
...mutatorApplyCirclePencil(writer),
|
|
3821
|
-
...mutatorApplyCirclePencilStroke(writer),
|
|
3822
|
-
...mutatorApplyRectBrush(writer),
|
|
3823
|
-
...mutatorApplyRectBrushStroke(writer),
|
|
3824
|
-
...mutatorApplyRectPencil(writer),
|
|
3825
|
-
...mutatorApplyRectPencilStroke(writer),
|
|
3826
|
-
...mutatorBlendColor(writer),
|
|
3827
|
-
...mutatorBlendColorCircleMask(writer),
|
|
3828
|
-
...mutatorBlendPixel(writer),
|
|
3829
|
-
...mutatorBlendPixelData(writer),
|
|
3830
|
-
...mutatorBlendPixelDataAlphaMask(writer),
|
|
3831
|
-
...mutatorBlendPixelDataBinaryMask(writer),
|
|
3832
|
-
...mutatorClear(writer),
|
|
3833
|
-
...mutatorFill(writer),
|
|
3834
|
-
...mutatorFillBinaryMask(writer),
|
|
3835
|
-
...mutatorFillRect(writer),
|
|
3836
|
-
...mutatorInvert(writer)
|
|
3837
|
-
};
|
|
3838
|
-
}
|
|
3839
3031
|
|
|
3840
3032
|
// src/PixelTile/PixelTile.ts
|
|
3841
3033
|
var PixelTile = class {
|
|
@@ -3896,34 +3088,334 @@ var PixelWriter = class {
|
|
|
3896
3088
|
accumulator;
|
|
3897
3089
|
historyActionFactory;
|
|
3898
3090
|
config;
|
|
3091
|
+
pixelTilePool;
|
|
3092
|
+
paintBuffer;
|
|
3899
3093
|
mutator;
|
|
3094
|
+
blendPixelDataOpts = {
|
|
3095
|
+
alpha: 255,
|
|
3096
|
+
blendFn: sourceOverPerfect,
|
|
3097
|
+
x: 0,
|
|
3098
|
+
y: 0,
|
|
3099
|
+
w: 0,
|
|
3100
|
+
h: 0
|
|
3101
|
+
};
|
|
3102
|
+
_inProgress = false;
|
|
3900
3103
|
constructor(target, mutatorFactory, {
|
|
3901
3104
|
tileSize = 256,
|
|
3902
3105
|
maxHistorySteps = 50,
|
|
3903
3106
|
historyManager = new HistoryManager(maxHistorySteps),
|
|
3904
3107
|
historyActionFactory = makeHistoryAction,
|
|
3905
|
-
pixelTilePool
|
|
3108
|
+
pixelTilePool,
|
|
3109
|
+
accumulator
|
|
3906
3110
|
} = {}) {
|
|
3907
3111
|
this.config = new PixelEngineConfig(tileSize, target);
|
|
3908
3112
|
this.historyManager = historyManager;
|
|
3909
|
-
pixelTilePool
|
|
3910
|
-
this.accumulator = new PixelAccumulator(this.config, pixelTilePool);
|
|
3113
|
+
this.pixelTilePool = pixelTilePool ?? new PixelTilePool(this.config);
|
|
3114
|
+
this.accumulator = accumulator ?? new PixelAccumulator(this.config, this.pixelTilePool);
|
|
3911
3115
|
this.historyActionFactory = historyActionFactory;
|
|
3912
3116
|
this.mutator = mutatorFactory(this);
|
|
3117
|
+
this.paintBuffer = new PaintBuffer(this.config, this.pixelTilePool);
|
|
3913
3118
|
}
|
|
3914
|
-
|
|
3119
|
+
/**
|
|
3120
|
+
* Executes `transaction` and commits the resulting pixel changes as a single
|
|
3121
|
+
* undoable history action.
|
|
3122
|
+
*
|
|
3123
|
+
* - If `transaction` throws, all accumulated changes are rolled back and the error
|
|
3124
|
+
* is re-thrown. No action is committed.
|
|
3125
|
+
* - If `transaction` completes without modifying any pixels, no action is committed.
|
|
3126
|
+
* - `withHistory` is not re-entrant. Calling it again from inside `transaction` will
|
|
3127
|
+
* throw immediately to prevent silent data loss from a nested extractPatch.
|
|
3128
|
+
*
|
|
3129
|
+
* @param transaction Callback to be executed inside the transaction.
|
|
3130
|
+
* @param after Called after both undo and redo — use for generic change notifications.
|
|
3131
|
+
* @param afterUndo Called after undo only — use for dimension or state changes specific to undo.
|
|
3132
|
+
* @param afterRedo Called after redo only.
|
|
3133
|
+
*/
|
|
3134
|
+
withHistory(transaction, after, afterUndo, afterRedo) {
|
|
3135
|
+
if (this._inProgress) {
|
|
3136
|
+
throw new Error("withHistory is not re-entrant \u2014 commit or rollback the current operation first");
|
|
3137
|
+
}
|
|
3138
|
+
this._inProgress = true;
|
|
3915
3139
|
try {
|
|
3916
|
-
|
|
3140
|
+
transaction(this.mutator);
|
|
3917
3141
|
} catch (e) {
|
|
3918
|
-
this.accumulator.
|
|
3142
|
+
this.accumulator.rollbackAfterError();
|
|
3919
3143
|
throw e;
|
|
3144
|
+
} finally {
|
|
3145
|
+
this._inProgress = false;
|
|
3146
|
+
}
|
|
3147
|
+
if (this.accumulator.beforeTiles.length === 0) return;
|
|
3148
|
+
const patch = this.accumulator.extractPatch();
|
|
3149
|
+
const action = this.historyActionFactory(this, patch, after, afterUndo, afterRedo);
|
|
3150
|
+
this.historyManager.commit(action);
|
|
3151
|
+
}
|
|
3152
|
+
resize(newWidth, newHeight, offsetX = 0, offsetY = 0, after, afterUndo, afterRedo, resizeImageDataFn = resizeImageData) {
|
|
3153
|
+
if (this._inProgress) {
|
|
3154
|
+
throw new Error("Cannot resize inside a withHistory callback");
|
|
3155
|
+
}
|
|
3156
|
+
if (this.accumulator.beforeTiles.length > 0) {
|
|
3157
|
+
throw new Error("Cannot resize with an open accumulator \u2014 commit or rollback first");
|
|
3158
|
+
}
|
|
3159
|
+
const config = this.config;
|
|
3160
|
+
const target = config.target;
|
|
3161
|
+
const beforeImageData = target.imageData;
|
|
3162
|
+
const afterImageData = resizeImageDataFn(beforeImageData, newWidth, newHeight, offsetX, offsetY);
|
|
3163
|
+
target.set(afterImageData);
|
|
3164
|
+
this.historyManager.commit({
|
|
3165
|
+
undo: () => {
|
|
3166
|
+
target.set(beforeImageData);
|
|
3167
|
+
afterUndo?.(beforeImageData);
|
|
3168
|
+
after?.(beforeImageData);
|
|
3169
|
+
},
|
|
3170
|
+
redo: () => {
|
|
3171
|
+
target.set(afterImageData);
|
|
3172
|
+
afterRedo?.(afterImageData);
|
|
3173
|
+
after?.(afterImageData);
|
|
3174
|
+
}
|
|
3175
|
+
});
|
|
3176
|
+
}
|
|
3177
|
+
commitPaintBuffer(alpha = 255, blendFn = sourceOverPerfect, blendPixelDataFn = blendPixelData) {
|
|
3178
|
+
const paintBuffer = this.paintBuffer;
|
|
3179
|
+
const tileShift = paintBuffer.config.tileShift;
|
|
3180
|
+
const lookup = paintBuffer.lookup;
|
|
3181
|
+
const opts = this.blendPixelDataOpts;
|
|
3182
|
+
opts.alpha = alpha;
|
|
3183
|
+
opts.blendFn = blendFn;
|
|
3184
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
3185
|
+
const tile = lookup[i];
|
|
3186
|
+
if (tile) {
|
|
3187
|
+
const didChange = this.accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
|
|
3188
|
+
const dx = tile.tx << tileShift;
|
|
3189
|
+
const dy = tile.ty << tileShift;
|
|
3190
|
+
opts.x = dx;
|
|
3191
|
+
opts.y = dy;
|
|
3192
|
+
opts.w = tile.width;
|
|
3193
|
+
opts.h = tile.height;
|
|
3194
|
+
didChange(blendPixelDataFn(this.config.target, tile, opts));
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
paintBuffer.clear();
|
|
3198
|
+
}
|
|
3199
|
+
};
|
|
3200
|
+
|
|
3201
|
+
// src/PixelData/applyAlphaMaskToPixelData.ts
|
|
3202
|
+
function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
3203
|
+
const {
|
|
3204
|
+
x: targetX = 0,
|
|
3205
|
+
y: targetY = 0,
|
|
3206
|
+
w: width = dst.width,
|
|
3207
|
+
h: height = dst.height,
|
|
3208
|
+
alpha: globalAlpha = 255,
|
|
3209
|
+
mx = 0,
|
|
3210
|
+
my = 0,
|
|
3211
|
+
invertMask = false
|
|
3212
|
+
} = opts;
|
|
3213
|
+
if (globalAlpha === 0) return false;
|
|
3214
|
+
let x = targetX;
|
|
3215
|
+
let y = targetY;
|
|
3216
|
+
let w = width;
|
|
3217
|
+
let h = height;
|
|
3218
|
+
if (x < 0) {
|
|
3219
|
+
w += x;
|
|
3220
|
+
x = 0;
|
|
3221
|
+
}
|
|
3222
|
+
if (y < 0) {
|
|
3223
|
+
h += y;
|
|
3224
|
+
y = 0;
|
|
3225
|
+
}
|
|
3226
|
+
w = Math.min(w, dst.width - x);
|
|
3227
|
+
h = Math.min(h, dst.height - y);
|
|
3228
|
+
if (w <= 0) return false;
|
|
3229
|
+
if (h <= 0) return false;
|
|
3230
|
+
const mPitch = mask.w;
|
|
3231
|
+
if (mPitch <= 0) return false;
|
|
3232
|
+
const startX = mx + (x - targetX);
|
|
3233
|
+
const startY = my + (y - targetY);
|
|
3234
|
+
const sX0 = Math.max(0, startX);
|
|
3235
|
+
const sY0 = Math.max(0, startY);
|
|
3236
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
3237
|
+
const sY1 = Math.min(mask.h, startY + h);
|
|
3238
|
+
const finalW = sX1 - sX0;
|
|
3239
|
+
const finalH = sY1 - sY0;
|
|
3240
|
+
if (finalW <= 0) return false;
|
|
3241
|
+
if (finalH <= 0) return false;
|
|
3242
|
+
const xShift = sX0 - startX;
|
|
3243
|
+
const yShift = sY0 - startY;
|
|
3244
|
+
const dst32 = dst.data32;
|
|
3245
|
+
const dw = dst.width;
|
|
3246
|
+
const dStride = dw - finalW;
|
|
3247
|
+
const mStride = mPitch - finalW;
|
|
3248
|
+
const maskData = mask.data;
|
|
3249
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
3250
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
3251
|
+
let didChange = false;
|
|
3252
|
+
for (let iy = 0; iy < h; iy++) {
|
|
3253
|
+
for (let ix = 0; ix < w; ix++) {
|
|
3254
|
+
const mVal = maskData[mIdx];
|
|
3255
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
3256
|
+
let weight = 0;
|
|
3257
|
+
if (effectiveM === 0) {
|
|
3258
|
+
weight = 0;
|
|
3259
|
+
} else if (effectiveM === 255) {
|
|
3260
|
+
weight = globalAlpha;
|
|
3261
|
+
} else if (globalAlpha === 255) {
|
|
3262
|
+
weight = effectiveM;
|
|
3263
|
+
} else {
|
|
3264
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
3265
|
+
}
|
|
3266
|
+
if (weight === 0) {
|
|
3267
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
3268
|
+
didChange = true;
|
|
3269
|
+
} else if (weight !== 255) {
|
|
3270
|
+
const d = dst32[dIdx];
|
|
3271
|
+
const da = d >>> 24;
|
|
3272
|
+
if (da !== 0) {
|
|
3273
|
+
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
3274
|
+
const current = dst32[dIdx];
|
|
3275
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
3276
|
+
if (current !== next) {
|
|
3277
|
+
dst32[dIdx] = next;
|
|
3278
|
+
didChange = true;
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
dIdx++;
|
|
3283
|
+
mIdx++;
|
|
3284
|
+
}
|
|
3285
|
+
dIdx += dStride;
|
|
3286
|
+
mIdx += mStride;
|
|
3287
|
+
}
|
|
3288
|
+
return didChange;
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
// src/History/PixelMutator/mutatorApplyAlphaMask.ts
|
|
3292
|
+
var defaults11 = {
|
|
3293
|
+
applyAlphaMaskToPixelData
|
|
3294
|
+
};
|
|
3295
|
+
var mutatorApplyAlphaMask = ((writer, deps = defaults11) => {
|
|
3296
|
+
const {
|
|
3297
|
+
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults11.applyAlphaMaskToPixelData
|
|
3298
|
+
} = deps;
|
|
3299
|
+
return {
|
|
3300
|
+
applyAlphaMask(mask, opts = {}) {
|
|
3301
|
+
let target = writer.config.target;
|
|
3302
|
+
const {
|
|
3303
|
+
x = 0,
|
|
3304
|
+
y = 0,
|
|
3305
|
+
w = target.width,
|
|
3306
|
+
h = target.height
|
|
3307
|
+
} = opts;
|
|
3308
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3309
|
+
return didChange(applyAlphaMaskToPixelData2(target, mask, opts));
|
|
3310
|
+
}
|
|
3311
|
+
};
|
|
3312
|
+
});
|
|
3313
|
+
|
|
3314
|
+
// src/PixelData/applyBinaryMaskToPixelData.ts
|
|
3315
|
+
function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
3316
|
+
const {
|
|
3317
|
+
x: targetX = 0,
|
|
3318
|
+
y: targetY = 0,
|
|
3319
|
+
w: width = dst.width,
|
|
3320
|
+
h: height = dst.height,
|
|
3321
|
+
alpha: globalAlpha = 255,
|
|
3322
|
+
mx = 0,
|
|
3323
|
+
my = 0,
|
|
3324
|
+
invertMask = false
|
|
3325
|
+
} = opts;
|
|
3326
|
+
if (globalAlpha === 0) return false;
|
|
3327
|
+
let x = targetX;
|
|
3328
|
+
let y = targetY;
|
|
3329
|
+
let w = width;
|
|
3330
|
+
let h = height;
|
|
3331
|
+
if (x < 0) {
|
|
3332
|
+
w += x;
|
|
3333
|
+
x = 0;
|
|
3334
|
+
}
|
|
3335
|
+
if (y < 0) {
|
|
3336
|
+
h += y;
|
|
3337
|
+
y = 0;
|
|
3338
|
+
}
|
|
3339
|
+
w = Math.min(w, dst.width - x);
|
|
3340
|
+
h = Math.min(h, dst.height - y);
|
|
3341
|
+
if (w <= 0 || h <= 0) return false;
|
|
3342
|
+
const mPitch = mask.w;
|
|
3343
|
+
if (mPitch <= 0) return false;
|
|
3344
|
+
const startX = mx + (x - targetX);
|
|
3345
|
+
const startY = my + (y - targetY);
|
|
3346
|
+
const sX0 = Math.max(0, startX);
|
|
3347
|
+
const sY0 = Math.max(0, startY);
|
|
3348
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
3349
|
+
const sY1 = Math.min(mask.h, startY + h);
|
|
3350
|
+
const finalW = sX1 - sX0;
|
|
3351
|
+
const finalH = sY1 - sY0;
|
|
3352
|
+
if (finalW <= 0 || finalH <= 0) {
|
|
3353
|
+
return false;
|
|
3354
|
+
}
|
|
3355
|
+
const xShift = sX0 - startX;
|
|
3356
|
+
const yShift = sY0 - startY;
|
|
3357
|
+
const dst32 = dst.data32;
|
|
3358
|
+
const dw = dst.width;
|
|
3359
|
+
const dStride = dw - finalW;
|
|
3360
|
+
const mStride = mPitch - finalW;
|
|
3361
|
+
const maskData = mask.data;
|
|
3362
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
3363
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
3364
|
+
let didChange = false;
|
|
3365
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
3366
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
3367
|
+
const mVal = maskData[mIdx];
|
|
3368
|
+
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
3369
|
+
if (isMaskedOut) {
|
|
3370
|
+
const current = dst32[dIdx];
|
|
3371
|
+
const next = (current & 16777215) >>> 0;
|
|
3372
|
+
if (current !== next) {
|
|
3373
|
+
dst32[dIdx] = next;
|
|
3374
|
+
didChange = true;
|
|
3375
|
+
}
|
|
3376
|
+
} else if (globalAlpha !== 255) {
|
|
3377
|
+
const d = dst32[dIdx];
|
|
3378
|
+
const da = d >>> 24;
|
|
3379
|
+
if (da !== 0) {
|
|
3380
|
+
const finalAlpha = da === 255 ? globalAlpha : da * globalAlpha + 128 >> 8;
|
|
3381
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
3382
|
+
if (d !== next) {
|
|
3383
|
+
dst32[dIdx] = next;
|
|
3384
|
+
didChange = true;
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
dIdx++;
|
|
3389
|
+
mIdx++;
|
|
3920
3390
|
}
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
const action = this.historyActionFactory(this, patch, after, afterUndo, afterRedo);
|
|
3924
|
-
this.historyManager.commit(action);
|
|
3391
|
+
dIdx += dStride;
|
|
3392
|
+
mIdx += mStride;
|
|
3925
3393
|
}
|
|
3394
|
+
return didChange;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
// src/History/PixelMutator/mutatorApplyBinaryMask.ts
|
|
3398
|
+
var defaults12 = {
|
|
3399
|
+
applyBinaryMaskToPixelData
|
|
3926
3400
|
};
|
|
3401
|
+
var mutatorApplyBinaryMask = ((writer, deps = defaults12) => {
|
|
3402
|
+
const {
|
|
3403
|
+
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults12.applyBinaryMaskToPixelData
|
|
3404
|
+
} = deps;
|
|
3405
|
+
return {
|
|
3406
|
+
applyBinaryMask(mask, opts = {}) {
|
|
3407
|
+
let target = writer.config.target;
|
|
3408
|
+
const {
|
|
3409
|
+
x = 0,
|
|
3410
|
+
y = 0,
|
|
3411
|
+
w = target.width,
|
|
3412
|
+
h = target.height
|
|
3413
|
+
} = opts;
|
|
3414
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3415
|
+
return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
|
|
3416
|
+
}
|
|
3417
|
+
};
|
|
3418
|
+
});
|
|
3927
3419
|
|
|
3928
3420
|
// src/ImageData/copyImageData.ts
|
|
3929
3421
|
function copyImageData({
|
|
@@ -4046,35 +3538,6 @@ function resampleImageData(source, factor) {
|
|
|
4046
3538
|
return new ImageData(uint8ClampedArray, width, height);
|
|
4047
3539
|
}
|
|
4048
3540
|
|
|
4049
|
-
// src/ImageData/resizeImageData.ts
|
|
4050
|
-
function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
4051
|
-
const result = new ImageData(newWidth, newHeight);
|
|
4052
|
-
const {
|
|
4053
|
-
width: oldW,
|
|
4054
|
-
height: oldH,
|
|
4055
|
-
data: oldData
|
|
4056
|
-
} = target;
|
|
4057
|
-
const newData = result.data;
|
|
4058
|
-
const x0 = Math.max(0, offsetX);
|
|
4059
|
-
const y0 = Math.max(0, offsetY);
|
|
4060
|
-
const x1 = Math.min(newWidth, offsetX + oldW);
|
|
4061
|
-
const y1 = Math.min(newHeight, offsetY + oldH);
|
|
4062
|
-
if (x1 <= x0 || y1 <= y0) {
|
|
4063
|
-
return result;
|
|
4064
|
-
}
|
|
4065
|
-
const rowCount = y1 - y0;
|
|
4066
|
-
const rowLen = (x1 - x0) * 4;
|
|
4067
|
-
for (let row = 0; row < rowCount; row++) {
|
|
4068
|
-
const dstY = y0 + row;
|
|
4069
|
-
const srcY = dstY - offsetY;
|
|
4070
|
-
const srcX = x0 - offsetX;
|
|
4071
|
-
const dstStart = (dstY * newWidth + x0) * 4;
|
|
4072
|
-
const srcStart = (srcY * oldW + srcX) * 4;
|
|
4073
|
-
newData.set(oldData.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
4074
|
-
}
|
|
4075
|
-
return result;
|
|
4076
|
-
}
|
|
4077
|
-
|
|
4078
3541
|
// src/ImageData/ReusableImageData.ts
|
|
4079
3542
|
function makeReusableImageData() {
|
|
4080
3543
|
let imageData = null;
|
|
@@ -4489,62 +3952,6 @@ function makeBinaryMask(w, h, data) {
|
|
|
4489
3952
|
};
|
|
4490
3953
|
}
|
|
4491
3954
|
|
|
4492
|
-
// src/Mask/CircleAlphaMask.ts
|
|
4493
|
-
function makeCircleAlphaMask(size, fallOff = () => 1) {
|
|
4494
|
-
const area = size * size;
|
|
4495
|
-
const data = new Uint8Array(area);
|
|
4496
|
-
const radius = size / 2;
|
|
4497
|
-
const invR = 1 / radius;
|
|
4498
|
-
const minOffset = -Math.ceil(radius - 0.5);
|
|
4499
|
-
for (let y = 0; y < size; y++) {
|
|
4500
|
-
for (let x = 0; x < size; x++) {
|
|
4501
|
-
const dx = x - radius + 0.5;
|
|
4502
|
-
const dy = y - radius + 0.5;
|
|
4503
|
-
const distSqr = dx * dx + dy * dy;
|
|
4504
|
-
if (distSqr <= radius * radius) {
|
|
4505
|
-
const dist = Math.sqrt(distSqr);
|
|
4506
|
-
data[y * size + x] = fallOff(1 - dist * invR) * 255 | 0;
|
|
4507
|
-
}
|
|
4508
|
-
}
|
|
4509
|
-
}
|
|
4510
|
-
return {
|
|
4511
|
-
type: 0 /* ALPHA */,
|
|
4512
|
-
data,
|
|
4513
|
-
w: size,
|
|
4514
|
-
h: size,
|
|
4515
|
-
radius,
|
|
4516
|
-
size,
|
|
4517
|
-
minOffset
|
|
4518
|
-
};
|
|
4519
|
-
}
|
|
4520
|
-
|
|
4521
|
-
// src/Mask/CircleBinaryMask.ts
|
|
4522
|
-
function makeCircleBinaryMask(size) {
|
|
4523
|
-
const area = size * size;
|
|
4524
|
-
const data = new Uint8Array(area);
|
|
4525
|
-
const radius = size / 2;
|
|
4526
|
-
const minOffset = -Math.ceil(radius - 0.5);
|
|
4527
|
-
for (let y = 0; y < size; y++) {
|
|
4528
|
-
for (let x = 0; x < size; x++) {
|
|
4529
|
-
const dx = x - radius + 0.5;
|
|
4530
|
-
const dy = y - radius + 0.5;
|
|
4531
|
-
const distSqr = dx * dx + dy * dy;
|
|
4532
|
-
if (distSqr <= radius * radius) {
|
|
4533
|
-
data[y * size + x] = 1;
|
|
4534
|
-
}
|
|
4535
|
-
}
|
|
4536
|
-
}
|
|
4537
|
-
return {
|
|
4538
|
-
type: 1 /* BINARY */,
|
|
4539
|
-
data,
|
|
4540
|
-
w: size,
|
|
4541
|
-
h: size,
|
|
4542
|
-
radius,
|
|
4543
|
-
size,
|
|
4544
|
-
minOffset
|
|
4545
|
-
};
|
|
4546
|
-
}
|
|
4547
|
-
|
|
4548
3955
|
// src/Mask/applyBinaryMaskToAlphaMask.ts
|
|
4549
3956
|
function applyBinaryMaskToAlphaMask(alphaMaskDst, binaryMaskSrc, opts = {}) {
|
|
4550
3957
|
const {
|
|
@@ -4920,85 +4327,241 @@ function mergeBinaryMaskRects(current, adding) {
|
|
|
4920
4327
|
break;
|
|
4921
4328
|
}
|
|
4922
4329
|
}
|
|
4923
|
-
if (!merged) next.push(r);
|
|
4330
|
+
if (!merged) next.push(r);
|
|
4331
|
+
}
|
|
4332
|
+
rects.splice(0, rects.length, ...next);
|
|
4333
|
+
}
|
|
4334
|
+
return rects;
|
|
4335
|
+
}
|
|
4336
|
+
|
|
4337
|
+
// src/MaskRect/subtractBinaryMaskRects.ts
|
|
4338
|
+
function subtractBinaryMaskRects(current, subtracting) {
|
|
4339
|
+
let result = [...current];
|
|
4340
|
+
for (const sub of subtracting) {
|
|
4341
|
+
const next = [];
|
|
4342
|
+
for (const r of result) {
|
|
4343
|
+
const ix = Math.max(r.x, sub.x);
|
|
4344
|
+
const iy = Math.max(r.y, sub.y);
|
|
4345
|
+
const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
|
|
4346
|
+
const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
|
|
4347
|
+
if (ix >= ix2 || iy >= iy2) {
|
|
4348
|
+
next.push(r);
|
|
4349
|
+
continue;
|
|
4350
|
+
}
|
|
4351
|
+
if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
|
|
4352
|
+
if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
|
|
4353
|
+
if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
|
|
4354
|
+
if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
|
|
4355
|
+
}
|
|
4356
|
+
result = next;
|
|
4357
|
+
}
|
|
4358
|
+
return result;
|
|
4359
|
+
}
|
|
4360
|
+
function pushPiece(dest, r, x, y, w, h) {
|
|
4361
|
+
if (r.data === null || r.data === void 0) {
|
|
4362
|
+
dest.push({
|
|
4363
|
+
x,
|
|
4364
|
+
y,
|
|
4365
|
+
w,
|
|
4366
|
+
h,
|
|
4367
|
+
data: null,
|
|
4368
|
+
type: null
|
|
4369
|
+
});
|
|
4370
|
+
return;
|
|
4371
|
+
}
|
|
4372
|
+
const lx = x - r.x;
|
|
4373
|
+
const ly = y - r.y;
|
|
4374
|
+
const data = new Uint8Array(w * h);
|
|
4375
|
+
for (let row = 0; row < h; row++) {
|
|
4376
|
+
data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
|
|
4377
|
+
}
|
|
4378
|
+
dest.push({
|
|
4379
|
+
x,
|
|
4380
|
+
y,
|
|
4381
|
+
w,
|
|
4382
|
+
h,
|
|
4383
|
+
data,
|
|
4384
|
+
type: 1 /* BINARY */
|
|
4385
|
+
});
|
|
4386
|
+
}
|
|
4387
|
+
|
|
4388
|
+
// src/PixelData/PixelData.ts
|
|
4389
|
+
var PixelData = class {
|
|
4390
|
+
data32;
|
|
4391
|
+
imageData;
|
|
4392
|
+
width;
|
|
4393
|
+
height;
|
|
4394
|
+
constructor(imageData) {
|
|
4395
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
4396
|
+
this.imageData = imageData;
|
|
4397
|
+
this.width = imageData.width;
|
|
4398
|
+
this.height = imageData.height;
|
|
4399
|
+
}
|
|
4400
|
+
set(imageData) {
|
|
4401
|
+
;
|
|
4402
|
+
this.imageData = imageData;
|
|
4403
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
4404
|
+
this.width = imageData.width;
|
|
4405
|
+
this.height = imageData.height;
|
|
4406
|
+
}
|
|
4407
|
+
};
|
|
4408
|
+
|
|
4409
|
+
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
4410
|
+
function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
4411
|
+
const targetX = opts.x ?? 0;
|
|
4412
|
+
const targetY = opts.y ?? 0;
|
|
4413
|
+
const w = opts.w ?? mask.w;
|
|
4414
|
+
const h = opts.h ?? mask.h;
|
|
4415
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
4416
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
4417
|
+
const mx = opts.mx ?? 0;
|
|
4418
|
+
const my = opts.my ?? 0;
|
|
4419
|
+
const invertMask = opts.invertMask ?? false;
|
|
4420
|
+
if (globalAlpha === 0) return false;
|
|
4421
|
+
const baseSrcAlpha = color >>> 24;
|
|
4422
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
4423
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
4424
|
+
let x = targetX;
|
|
4425
|
+
let y = targetY;
|
|
4426
|
+
let actualW = w;
|
|
4427
|
+
let actualH = h;
|
|
4428
|
+
if (x < 0) {
|
|
4429
|
+
actualW += x;
|
|
4430
|
+
x = 0;
|
|
4431
|
+
}
|
|
4432
|
+
if (y < 0) {
|
|
4433
|
+
actualH += y;
|
|
4434
|
+
y = 0;
|
|
4435
|
+
}
|
|
4436
|
+
actualW = Math.min(actualW, dst.width - x);
|
|
4437
|
+
actualH = Math.min(actualH, dst.height - y);
|
|
4438
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
4439
|
+
const dx = x - targetX | 0;
|
|
4440
|
+
const dy = y - targetY | 0;
|
|
4441
|
+
const dst32 = dst.data32;
|
|
4442
|
+
const dw = dst.width;
|
|
4443
|
+
const mPitch = mask.w;
|
|
4444
|
+
const maskData = mask.data;
|
|
4445
|
+
let dIdx = y * dw + x | 0;
|
|
4446
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
4447
|
+
const dStride = dw - actualW | 0;
|
|
4448
|
+
const mStride = mPitch - actualW | 0;
|
|
4449
|
+
const isOpaque = globalAlpha === 255;
|
|
4450
|
+
const colorRGB = color & 16777215;
|
|
4451
|
+
let didChange = false;
|
|
4452
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
4453
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
4454
|
+
const mVal = maskData[mIdx];
|
|
4455
|
+
const effM = invertMask ? 255 - mVal : mVal;
|
|
4456
|
+
if (effM === 0) {
|
|
4457
|
+
dIdx++;
|
|
4458
|
+
mIdx++;
|
|
4459
|
+
continue;
|
|
4460
|
+
}
|
|
4461
|
+
let weight = globalAlpha;
|
|
4462
|
+
if (isOpaque) {
|
|
4463
|
+
weight = effM;
|
|
4464
|
+
} else if (effM !== 255) {
|
|
4465
|
+
weight = effM * globalAlpha + 128 >> 8;
|
|
4466
|
+
}
|
|
4467
|
+
if (weight === 0) {
|
|
4468
|
+
dIdx++;
|
|
4469
|
+
mIdx++;
|
|
4470
|
+
continue;
|
|
4471
|
+
}
|
|
4472
|
+
let finalCol = color;
|
|
4473
|
+
if (weight < 255) {
|
|
4474
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
4475
|
+
if (a === 0 && !isOverwrite) {
|
|
4476
|
+
dIdx++;
|
|
4477
|
+
mIdx++;
|
|
4478
|
+
continue;
|
|
4479
|
+
}
|
|
4480
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
4481
|
+
}
|
|
4482
|
+
const current = dst32[dIdx];
|
|
4483
|
+
const next = blendFn(finalCol, current);
|
|
4484
|
+
if (current !== next) {
|
|
4485
|
+
dst32[dIdx] = next;
|
|
4486
|
+
didChange = true;
|
|
4487
|
+
}
|
|
4488
|
+
dIdx++;
|
|
4489
|
+
mIdx++;
|
|
4924
4490
|
}
|
|
4925
|
-
|
|
4491
|
+
dIdx += dStride;
|
|
4492
|
+
mIdx += mStride;
|
|
4926
4493
|
}
|
|
4927
|
-
return
|
|
4494
|
+
return didChange;
|
|
4928
4495
|
}
|
|
4929
4496
|
|
|
4930
|
-
// src/
|
|
4931
|
-
function
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4497
|
+
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
4498
|
+
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
4499
|
+
const targetX = opts.x ?? 0;
|
|
4500
|
+
const targetY = opts.y ?? 0;
|
|
4501
|
+
let w = opts.w ?? mask.w;
|
|
4502
|
+
let h = opts.h ?? mask.h;
|
|
4503
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
4504
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
4505
|
+
const mx = opts.mx ?? 0;
|
|
4506
|
+
const my = opts.my ?? 0;
|
|
4507
|
+
const invertMask = opts.invertMask ?? false;
|
|
4508
|
+
if (globalAlpha === 0) return false;
|
|
4509
|
+
const baseSrcAlpha = color >>> 24;
|
|
4510
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
4511
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
4512
|
+
let x = targetX;
|
|
4513
|
+
let y = targetY;
|
|
4514
|
+
if (x < 0) {
|
|
4515
|
+
w += x;
|
|
4516
|
+
x = 0;
|
|
4517
|
+
}
|
|
4518
|
+
if (y < 0) {
|
|
4519
|
+
h += y;
|
|
4520
|
+
y = 0;
|
|
4521
|
+
}
|
|
4522
|
+
const actualW = Math.min(w, dst.width - x);
|
|
4523
|
+
const actualH = Math.min(h, dst.height - y);
|
|
4524
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
4525
|
+
let baseColorWithGlobalAlpha = color;
|
|
4526
|
+
if (globalAlpha < 255) {
|
|
4527
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
4528
|
+
if (a === 0 && !isOverwrite) return false;
|
|
4529
|
+
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
4530
|
+
}
|
|
4531
|
+
const dx = x - targetX | 0;
|
|
4532
|
+
const dy = y - targetY | 0;
|
|
4533
|
+
const dst32 = dst.data32;
|
|
4534
|
+
const dw = dst.width;
|
|
4535
|
+
const mPitch = mask.w;
|
|
4536
|
+
const maskData = mask.data;
|
|
4537
|
+
let dIdx = y * dw + x | 0;
|
|
4538
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
4539
|
+
const dStride = dw - actualW | 0;
|
|
4540
|
+
const mStride = mPitch - actualW | 0;
|
|
4541
|
+
const skipVal = invertMask ? 1 : 0;
|
|
4542
|
+
let didChange = false;
|
|
4543
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
4544
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
4545
|
+
if (maskData[mIdx] === skipVal) {
|
|
4546
|
+
dIdx++;
|
|
4547
|
+
mIdx++;
|
|
4942
4548
|
continue;
|
|
4943
4549
|
}
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
if (
|
|
4947
|
-
|
|
4550
|
+
const current = dst32[dIdx];
|
|
4551
|
+
const next = blendFn(baseColorWithGlobalAlpha, current);
|
|
4552
|
+
if (current !== next) {
|
|
4553
|
+
dst32[dIdx] = next;
|
|
4554
|
+
didChange = true;
|
|
4555
|
+
}
|
|
4556
|
+
dIdx++;
|
|
4557
|
+
mIdx++;
|
|
4948
4558
|
}
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
return result;
|
|
4952
|
-
}
|
|
4953
|
-
function pushPiece(dest, r, x, y, w, h) {
|
|
4954
|
-
if (r.data === null || r.data === void 0) {
|
|
4955
|
-
dest.push({
|
|
4956
|
-
x,
|
|
4957
|
-
y,
|
|
4958
|
-
w,
|
|
4959
|
-
h,
|
|
4960
|
-
data: null,
|
|
4961
|
-
type: null
|
|
4962
|
-
});
|
|
4963
|
-
return;
|
|
4964
|
-
}
|
|
4965
|
-
const lx = x - r.x;
|
|
4966
|
-
const ly = y - r.y;
|
|
4967
|
-
const data = new Uint8Array(w * h);
|
|
4968
|
-
for (let row = 0; row < h; row++) {
|
|
4969
|
-
data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
|
|
4559
|
+
dIdx += dStride;
|
|
4560
|
+
mIdx += mStride;
|
|
4970
4561
|
}
|
|
4971
|
-
|
|
4972
|
-
x,
|
|
4973
|
-
y,
|
|
4974
|
-
w,
|
|
4975
|
-
h,
|
|
4976
|
-
data,
|
|
4977
|
-
type: 1 /* BINARY */
|
|
4978
|
-
});
|
|
4562
|
+
return didChange;
|
|
4979
4563
|
}
|
|
4980
4564
|
|
|
4981
|
-
// src/PixelData/PixelData.ts
|
|
4982
|
-
var PixelData = class {
|
|
4983
|
-
data32;
|
|
4984
|
-
imageData;
|
|
4985
|
-
width;
|
|
4986
|
-
height;
|
|
4987
|
-
constructor(imageData) {
|
|
4988
|
-
this.data32 = imageDataToUInt32Array(imageData);
|
|
4989
|
-
this.imageData = imageData;
|
|
4990
|
-
this.width = imageData.width;
|
|
4991
|
-
this.height = imageData.height;
|
|
4992
|
-
}
|
|
4993
|
-
set(imageData) {
|
|
4994
|
-
;
|
|
4995
|
-
this.imageData = imageData;
|
|
4996
|
-
this.data32 = imageDataToUInt32Array(imageData);
|
|
4997
|
-
this.width = imageData.width;
|
|
4998
|
-
this.height = imageData.height;
|
|
4999
|
-
}
|
|
5000
|
-
};
|
|
5001
|
-
|
|
5002
4565
|
// src/PixelData/blendPixelDataPaintBuffer.ts
|
|
5003
4566
|
var SCRATCH_OPTS = {
|
|
5004
4567
|
x: 0,
|
|
@@ -5245,103 +4808,140 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5245
4808
|
}
|
|
5246
4809
|
}
|
|
5247
4810
|
|
|
5248
|
-
// src/
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
4811
|
+
// src/PixelData/writePaintBufferToPixelData.ts
|
|
4812
|
+
function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn = writePixelDataBuffer) {
|
|
4813
|
+
const tileShift = paintBuffer.config.tileShift;
|
|
4814
|
+
const lookup = paintBuffer.lookup;
|
|
4815
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
4816
|
+
const tile = lookup[i];
|
|
4817
|
+
if (tile) {
|
|
4818
|
+
const dx = tile.tx << tileShift;
|
|
4819
|
+
const dy = tile.ty << tileShift;
|
|
4820
|
+
writePixelDataBufferFn(target, tile.data32, dx, dy, tile.width, tile.height);
|
|
4821
|
+
}
|
|
5254
4822
|
}
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
4823
|
+
}
|
|
4824
|
+
|
|
4825
|
+
// src/Paint/makeCirclePaintAlphaMask.ts
|
|
4826
|
+
function makeCirclePaintAlphaMask(size, fallOff = (d) => d) {
|
|
4827
|
+
const area = size * size;
|
|
4828
|
+
const data = new Uint8Array(area);
|
|
4829
|
+
const radius = size / 2;
|
|
4830
|
+
const invR = 1 / radius;
|
|
4831
|
+
const centerOffset = -Math.ceil(radius - 0.5);
|
|
4832
|
+
for (let y = 0; y < size; y++) {
|
|
4833
|
+
const rowOffset = y * size;
|
|
4834
|
+
const dy = y - radius + 0.5;
|
|
4835
|
+
const dy2 = dy * dy;
|
|
4836
|
+
for (let x = 0; x < size; x++) {
|
|
4837
|
+
const dx = x - radius + 0.5;
|
|
4838
|
+
const distSqr = dx * dx + dy2;
|
|
4839
|
+
if (distSqr <= radius * radius) {
|
|
4840
|
+
const dist = Math.sqrt(distSqr) * invR;
|
|
4841
|
+
const strength = fallOff(1 - dist);
|
|
4842
|
+
if (strength > 0) {
|
|
4843
|
+
const intensity = strength * 255 | 0;
|
|
4844
|
+
data[rowOffset + x] = Math.max(0, Math.min(255, intensity));
|
|
5274
4845
|
}
|
|
5275
|
-
const tileLeft = tx << tileShift;
|
|
5276
|
-
const startX = Math.max(mask.x, tileLeft);
|
|
5277
|
-
const endX = Math.min(mask.x + mask.w, tileLeft + this.config.tileSize);
|
|
5278
|
-
const startY = Math.max(mask.y, tileTop);
|
|
5279
|
-
const endY = Math.min(mask.y + mask.h, tileTop + this.config.tileSize);
|
|
5280
|
-
callback(tile, startX, startY, endX - startX, endY - startY, startX - mask.x, startY - mask.y);
|
|
5281
4846
|
}
|
|
5282
4847
|
}
|
|
5283
4848
|
}
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
4849
|
+
return {
|
|
4850
|
+
type: 0 /* ALPHA */,
|
|
4851
|
+
data,
|
|
4852
|
+
w: size,
|
|
4853
|
+
h: size,
|
|
4854
|
+
centerOffsetX: centerOffset,
|
|
4855
|
+
centerOffsetY: centerOffset
|
|
4856
|
+
};
|
|
4857
|
+
}
|
|
4858
|
+
|
|
4859
|
+
// src/Paint/makeCirclePaintBinaryMask.ts
|
|
4860
|
+
function makeCirclePaintBinaryMask(size) {
|
|
4861
|
+
const area = size * size;
|
|
4862
|
+
const data = new Uint8Array(area);
|
|
4863
|
+
const radius = size / 2;
|
|
4864
|
+
const centerOffset = -Math.ceil(radius - 0.5);
|
|
4865
|
+
for (let y = 0; y < size; y++) {
|
|
4866
|
+
for (let x = 0; x < size; x++) {
|
|
4867
|
+
const dx = x - radius + 0.5;
|
|
4868
|
+
const dy = y - radius + 0.5;
|
|
4869
|
+
const distSqr = dx * dx + dy * dy;
|
|
4870
|
+
if (distSqr <= radius * radius) {
|
|
4871
|
+
data[y * size + x] = 1;
|
|
5306
4872
|
}
|
|
5307
|
-
}
|
|
4873
|
+
}
|
|
5308
4874
|
}
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
4875
|
+
return {
|
|
4876
|
+
type: 1 /* BINARY */,
|
|
4877
|
+
data,
|
|
4878
|
+
w: size,
|
|
4879
|
+
h: size,
|
|
4880
|
+
centerOffsetX: centerOffset,
|
|
4881
|
+
centerOffsetY: centerOffset
|
|
4882
|
+
};
|
|
4883
|
+
}
|
|
4884
|
+
|
|
4885
|
+
// src/Paint/makePaintMask.ts
|
|
4886
|
+
function makePaintBinaryMask(mask) {
|
|
4887
|
+
return {
|
|
4888
|
+
type: 1 /* BINARY */,
|
|
4889
|
+
data: mask.data,
|
|
4890
|
+
w: mask.w,
|
|
4891
|
+
h: mask.h,
|
|
4892
|
+
centerOffsetX: -(mask.w >> 1),
|
|
4893
|
+
centerOffsetY: -(mask.h >> 1)
|
|
4894
|
+
};
|
|
4895
|
+
}
|
|
4896
|
+
function makePaintAlphaMask(mask) {
|
|
4897
|
+
return {
|
|
4898
|
+
type: 0 /* ALPHA */,
|
|
4899
|
+
data: mask.data,
|
|
4900
|
+
w: mask.w,
|
|
4901
|
+
h: mask.h,
|
|
4902
|
+
centerOffsetX: -(mask.w >> 1),
|
|
4903
|
+
centerOffsetY: -(mask.h >> 1)
|
|
4904
|
+
};
|
|
4905
|
+
}
|
|
4906
|
+
|
|
4907
|
+
// src/Internal/helpers.ts
|
|
4908
|
+
var macro_halfAndFloor = (value) => value >> 1;
|
|
4909
|
+
|
|
4910
|
+
// src/Paint/makeRectFalloffPaintAlphaMask.ts
|
|
4911
|
+
function makeRectFalloffPaintAlphaMask(width, height, fallOff = (d) => d) {
|
|
4912
|
+
const fPx = Math.floor(width / 2);
|
|
4913
|
+
const fPy = Math.floor(height / 2);
|
|
4914
|
+
const invHalfW = 2 / width;
|
|
4915
|
+
const invHalfH = 2 / height;
|
|
4916
|
+
const offX = width % 2 === 0 ? 0.5 : 0;
|
|
4917
|
+
const offY = height % 2 === 0 ? 0.5 : 0;
|
|
4918
|
+
const area = width * height;
|
|
4919
|
+
const data = new Uint8Array(area);
|
|
4920
|
+
for (let y = 0; y < height; y++) {
|
|
4921
|
+
const dy = Math.abs(y - fPy + offY) * invHalfH;
|
|
4922
|
+
const rowOffset = y * width;
|
|
4923
|
+
for (let x = 0; x < width; x++) {
|
|
4924
|
+
const dx = Math.abs(x - fPx + offX) * invHalfW;
|
|
4925
|
+
const dist = dx > dy ? dx : dy;
|
|
4926
|
+
const strength = fallOff(1 - dist);
|
|
4927
|
+
if (strength > 0) {
|
|
4928
|
+
const intensity = strength * 255 | 0;
|
|
4929
|
+
data[rowOffset + x] = Math.max(0, Math.min(255, intensity));
|
|
5335
4930
|
}
|
|
5336
|
-
}
|
|
5337
|
-
}
|
|
5338
|
-
clear() {
|
|
5339
|
-
this.tilePool.releaseTiles(this.lookup);
|
|
4931
|
+
}
|
|
5340
4932
|
}
|
|
5341
|
-
|
|
4933
|
+
return {
|
|
4934
|
+
type: 0 /* ALPHA */,
|
|
4935
|
+
data,
|
|
4936
|
+
w: width,
|
|
4937
|
+
h: height,
|
|
4938
|
+
centerOffsetX: -macro_halfAndFloor(width),
|
|
4939
|
+
centerOffsetY: -macro_halfAndFloor(height)
|
|
4940
|
+
};
|
|
4941
|
+
}
|
|
5342
4942
|
|
|
5343
|
-
// src/
|
|
5344
|
-
function
|
|
4943
|
+
// src/Paint/PaintBufferCanvasRenderer.ts
|
|
4944
|
+
function makePaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
|
|
5345
4945
|
const config = paintBuffer.config;
|
|
5346
4946
|
const tileSize = config.tileSize;
|
|
5347
4947
|
const tileShift = config.tileShift;
|
|
@@ -5350,16 +4950,20 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5350
4950
|
const ctx = canvas.getContext("2d");
|
|
5351
4951
|
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
5352
4952
|
ctx.imageSmoothingEnabled = false;
|
|
5353
|
-
return function drawPaintBuffer(
|
|
4953
|
+
return function drawPaintBuffer(targetCtx, alpha = 255, compOperation = "source-over") {
|
|
4954
|
+
targetCtx.globalAlpha = alpha / 255;
|
|
4955
|
+
targetCtx.globalCompositeOperation = compOperation;
|
|
5354
4956
|
for (let i = 0; i < lookup.length; i++) {
|
|
5355
4957
|
const tile = lookup[i];
|
|
5356
4958
|
if (tile) {
|
|
5357
4959
|
const dx = tile.tx << tileShift;
|
|
5358
4960
|
const dy = tile.ty << tileShift;
|
|
5359
4961
|
ctx.putImageData(tile.imageData, 0, 0);
|
|
5360
|
-
|
|
4962
|
+
targetCtx.drawImage(canvas, dx, dy);
|
|
5361
4963
|
}
|
|
5362
4964
|
}
|
|
4965
|
+
targetCtx.globalAlpha = 1;
|
|
4966
|
+
targetCtx.globalCompositeOperation = "source-over";
|
|
5363
4967
|
};
|
|
5364
4968
|
}
|
|
5365
4969
|
export {
|
|
@@ -5384,13 +4988,11 @@ export {
|
|
|
5384
4988
|
applyBinaryMaskToAlphaMask,
|
|
5385
4989
|
applyBinaryMaskToPixelData,
|
|
5386
4990
|
applyPatchTiles,
|
|
5387
|
-
applyRectBrushToPixelData,
|
|
5388
4991
|
base64DecodeArrayBuffer,
|
|
5389
4992
|
base64EncodeArrayBuffer,
|
|
5390
4993
|
blendColorPixelData,
|
|
5391
4994
|
blendColorPixelDataAlphaMask,
|
|
5392
4995
|
blendColorPixelDataBinaryMask,
|
|
5393
|
-
blendColorPixelDataCircleMask,
|
|
5394
4996
|
blendPixel,
|
|
5395
4997
|
blendPixelData,
|
|
5396
4998
|
blendPixelDataAlphaMask,
|
|
@@ -5432,12 +5034,8 @@ export {
|
|
|
5432
5034
|
fillPixelDataFast,
|
|
5433
5035
|
floodFillSelection,
|
|
5434
5036
|
forEachLinePoint,
|
|
5435
|
-
getCircleBrushOrPencilBounds,
|
|
5436
|
-
getCircleBrushOrPencilStrokeBounds,
|
|
5437
5037
|
getImageDataFromClipboard,
|
|
5438
5038
|
getIndexedImageColorCounts,
|
|
5439
|
-
getRectBrushOrPencilBounds,
|
|
5440
|
-
getRectBrushOrPencilStrokeBounds,
|
|
5441
5039
|
getRectsBounds,
|
|
5442
5040
|
getSupportedPixelFormats,
|
|
5443
5041
|
hardLightFast,
|
|
@@ -5471,15 +5069,18 @@ export {
|
|
|
5471
5069
|
makeBinaryMask,
|
|
5472
5070
|
makeBlendModeRegistry,
|
|
5473
5071
|
makeCanvasFrameRenderer,
|
|
5474
|
-
|
|
5475
|
-
|
|
5072
|
+
makeCirclePaintAlphaMask,
|
|
5073
|
+
makeCirclePaintBinaryMask,
|
|
5476
5074
|
makeFastBlendModeRegistry,
|
|
5477
5075
|
makeFullPixelMutator,
|
|
5478
5076
|
makeHistoryAction,
|
|
5479
5077
|
makeImageDataLike,
|
|
5480
|
-
|
|
5078
|
+
makePaintAlphaMask,
|
|
5079
|
+
makePaintBinaryMask,
|
|
5080
|
+
makePaintBufferCanvasRenderer,
|
|
5481
5081
|
makePerfectBlendModeRegistry,
|
|
5482
5082
|
makePixelCanvas,
|
|
5083
|
+
makeRectFalloffPaintAlphaMask,
|
|
5483
5084
|
makeReusableCanvas,
|
|
5484
5085
|
makeReusableImageData,
|
|
5485
5086
|
makeReusableOffscreenCanvas,
|
|
@@ -5491,15 +5092,7 @@ export {
|
|
|
5491
5092
|
multiplyPerfect,
|
|
5492
5093
|
mutatorApplyAlphaMask,
|
|
5493
5094
|
mutatorApplyBinaryMask,
|
|
5494
|
-
mutatorApplyCircleBrushStroke,
|
|
5495
|
-
mutatorApplyCirclePencil,
|
|
5496
|
-
mutatorApplyCirclePencilStroke,
|
|
5497
|
-
mutatorApplyRectBrush,
|
|
5498
|
-
mutatorApplyRectBrushStroke,
|
|
5499
|
-
mutatorApplyRectPencil,
|
|
5500
|
-
mutatorApplyRectPencilStroke,
|
|
5501
5095
|
mutatorBlendColor,
|
|
5502
|
-
mutatorBlendColorCircleMask,
|
|
5503
5096
|
mutatorBlendPixel,
|
|
5504
5097
|
mutatorBlendPixelData,
|
|
5505
5098
|
mutatorBlendPixelDataAlphaMask,
|
|
@@ -5539,6 +5132,7 @@ export {
|
|
|
5539
5132
|
subtractFast,
|
|
5540
5133
|
subtractPerfect,
|
|
5541
5134
|
toBlendModeIndexAndName,
|
|
5135
|
+
trimMaskRectBounds,
|
|
5542
5136
|
trimRectBounds,
|
|
5543
5137
|
uInt32ArrayToImageData,
|
|
5544
5138
|
uInt32ArrayToImageDataLike,
|
|
@@ -5554,6 +5148,7 @@ export {
|
|
|
5554
5148
|
writeImageDataBuffer,
|
|
5555
5149
|
writeImageDataToClipboard,
|
|
5556
5150
|
writeImgBlobToClipboard,
|
|
5151
|
+
writePaintBufferToPixelData,
|
|
5557
5152
|
writePixelDataBuffer
|
|
5558
5153
|
};
|
|
5559
5154
|
//# sourceMappingURL=index.dev.js.map
|