pixel-data-js 0.24.0 → 0.25.2
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 +1476 -1834
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1465 -1816
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1475 -1833
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +233 -310
- package/dist/index.prod.js +1465 -1816
- 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/mutatorBlendPaintMask.ts +60 -0
- 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 +11 -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.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(src_exports, {
|
|
|
23
23
|
BASE_FAST_BLEND_MODE_FUNCTIONS: () => BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
24
24
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS: () => BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
25
25
|
BaseBlendMode: () => BaseBlendMode,
|
|
26
|
+
CANVAS_COMPOSITE_MAP: () => CANVAS_COMPOSITE_MAP,
|
|
26
27
|
CANVAS_CTX_FAILED: () => CANVAS_CTX_FAILED,
|
|
27
28
|
HistoryManager: () => HistoryManager,
|
|
28
29
|
IndexedImage: () => IndexedImage,
|
|
@@ -41,13 +42,11 @@ __export(src_exports, {
|
|
|
41
42
|
applyBinaryMaskToAlphaMask: () => applyBinaryMaskToAlphaMask,
|
|
42
43
|
applyBinaryMaskToPixelData: () => applyBinaryMaskToPixelData,
|
|
43
44
|
applyPatchTiles: () => applyPatchTiles,
|
|
44
|
-
applyRectBrushToPixelData: () => applyRectBrushToPixelData,
|
|
45
45
|
base64DecodeArrayBuffer: () => base64DecodeArrayBuffer,
|
|
46
46
|
base64EncodeArrayBuffer: () => base64EncodeArrayBuffer,
|
|
47
47
|
blendColorPixelData: () => blendColorPixelData,
|
|
48
48
|
blendColorPixelDataAlphaMask: () => blendColorPixelDataAlphaMask,
|
|
49
49
|
blendColorPixelDataBinaryMask: () => blendColorPixelDataBinaryMask,
|
|
50
|
-
blendColorPixelDataCircleMask: () => blendColorPixelDataCircleMask,
|
|
51
50
|
blendPixel: () => blendPixel,
|
|
52
51
|
blendPixelData: () => blendPixelData,
|
|
53
52
|
blendPixelDataAlphaMask: () => blendPixelDataAlphaMask,
|
|
@@ -89,12 +88,8 @@ __export(src_exports, {
|
|
|
89
88
|
fillPixelDataFast: () => fillPixelDataFast,
|
|
90
89
|
floodFillSelection: () => floodFillSelection,
|
|
91
90
|
forEachLinePoint: () => forEachLinePoint,
|
|
92
|
-
getCircleBrushOrPencilBounds: () => getCircleBrushOrPencilBounds,
|
|
93
|
-
getCircleBrushOrPencilStrokeBounds: () => getCircleBrushOrPencilStrokeBounds,
|
|
94
91
|
getImageDataFromClipboard: () => getImageDataFromClipboard,
|
|
95
92
|
getIndexedImageColorCounts: () => getIndexedImageColorCounts,
|
|
96
|
-
getRectBrushOrPencilBounds: () => getRectBrushOrPencilBounds,
|
|
97
|
-
getRectBrushOrPencilStrokeBounds: () => getRectBrushOrPencilStrokeBounds,
|
|
98
93
|
getRectsBounds: () => getRectsBounds,
|
|
99
94
|
getSupportedPixelFormats: () => getSupportedPixelFormats,
|
|
100
95
|
hardLightFast: () => hardLightFast,
|
|
@@ -128,15 +123,18 @@ __export(src_exports, {
|
|
|
128
123
|
makeBinaryMask: () => makeBinaryMask,
|
|
129
124
|
makeBlendModeRegistry: () => makeBlendModeRegistry,
|
|
130
125
|
makeCanvasFrameRenderer: () => makeCanvasFrameRenderer,
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
makeCirclePaintAlphaMask: () => makeCirclePaintAlphaMask,
|
|
127
|
+
makeCirclePaintBinaryMask: () => makeCirclePaintBinaryMask,
|
|
133
128
|
makeFastBlendModeRegistry: () => makeFastBlendModeRegistry,
|
|
134
129
|
makeFullPixelMutator: () => makeFullPixelMutator,
|
|
135
130
|
makeHistoryAction: () => makeHistoryAction,
|
|
136
131
|
makeImageDataLike: () => makeImageDataLike,
|
|
137
|
-
|
|
132
|
+
makePaintAlphaMask: () => makePaintAlphaMask,
|
|
133
|
+
makePaintBinaryMask: () => makePaintBinaryMask,
|
|
134
|
+
makePaintBufferCanvasRenderer: () => makePaintBufferCanvasRenderer,
|
|
138
135
|
makePerfectBlendModeRegistry: () => makePerfectBlendModeRegistry,
|
|
139
136
|
makePixelCanvas: () => makePixelCanvas,
|
|
137
|
+
makeRectFalloffPaintAlphaMask: () => makeRectFalloffPaintAlphaMask,
|
|
140
138
|
makeReusableCanvas: () => makeReusableCanvas,
|
|
141
139
|
makeReusableImageData: () => makeReusableImageData,
|
|
142
140
|
makeReusableOffscreenCanvas: () => makeReusableOffscreenCanvas,
|
|
@@ -148,15 +146,8 @@ __export(src_exports, {
|
|
|
148
146
|
multiplyPerfect: () => multiplyPerfect,
|
|
149
147
|
mutatorApplyAlphaMask: () => mutatorApplyAlphaMask,
|
|
150
148
|
mutatorApplyBinaryMask: () => mutatorApplyBinaryMask,
|
|
151
|
-
mutatorApplyCircleBrushStroke: () => mutatorApplyCircleBrushStroke,
|
|
152
|
-
mutatorApplyCirclePencil: () => mutatorApplyCirclePencil,
|
|
153
|
-
mutatorApplyCirclePencilStroke: () => mutatorApplyCirclePencilStroke,
|
|
154
|
-
mutatorApplyRectBrush: () => mutatorApplyRectBrush,
|
|
155
|
-
mutatorApplyRectBrushStroke: () => mutatorApplyRectBrushStroke,
|
|
156
|
-
mutatorApplyRectPencil: () => mutatorApplyRectPencil,
|
|
157
|
-
mutatorApplyRectPencilStroke: () => mutatorApplyRectPencilStroke,
|
|
158
149
|
mutatorBlendColor: () => mutatorBlendColor,
|
|
159
|
-
|
|
150
|
+
mutatorBlendPaintMask: () => mutatorBlendPaintMask,
|
|
160
151
|
mutatorBlendPixel: () => mutatorBlendPixel,
|
|
161
152
|
mutatorBlendPixelData: () => mutatorBlendPixelData,
|
|
162
153
|
mutatorBlendPixelDataAlphaMask: () => mutatorBlendPixelDataAlphaMask,
|
|
@@ -196,6 +187,7 @@ __export(src_exports, {
|
|
|
196
187
|
subtractFast: () => subtractFast,
|
|
197
188
|
subtractPerfect: () => subtractPerfect,
|
|
198
189
|
toBlendModeIndexAndName: () => toBlendModeIndexAndName,
|
|
190
|
+
trimMaskRectBounds: () => trimMaskRectBounds,
|
|
199
191
|
trimRectBounds: () => trimRectBounds,
|
|
200
192
|
uInt32ArrayToImageData: () => uInt32ArrayToImageData,
|
|
201
193
|
uInt32ArrayToImageDataLike: () => uInt32ArrayToImageDataLike,
|
|
@@ -211,6 +203,7 @@ __export(src_exports, {
|
|
|
211
203
|
writeImageDataBuffer: () => writeImageDataBuffer,
|
|
212
204
|
writeImageDataToClipboard: () => writeImageDataToClipboard,
|
|
213
205
|
writeImgBlobToClipboard: () => writeImgBlobToClipboard,
|
|
206
|
+
writePaintBufferToPixelData: () => writePaintBufferToPixelData,
|
|
214
207
|
writePixelDataBuffer: () => writePixelDataBuffer
|
|
215
208
|
});
|
|
216
209
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -449,8 +442,8 @@ function extractMaskBuffer(maskBuffer, maskWidth, xOrRect, y, w, h) {
|
|
|
449
442
|
return out;
|
|
450
443
|
}
|
|
451
444
|
|
|
452
|
-
// src/Rect/
|
|
453
|
-
function
|
|
445
|
+
// src/Rect/trimMaskRectBounds.ts
|
|
446
|
+
function trimMaskRectBounds(target, bounds) {
|
|
454
447
|
const originalX = target.x;
|
|
455
448
|
const originalY = target.y;
|
|
456
449
|
const originalW = target.w;
|
|
@@ -638,7 +631,7 @@ function floodFillSelection(img, startX, startY, {
|
|
|
638
631
|
finalMask[my * sw + mx] = 1;
|
|
639
632
|
}
|
|
640
633
|
}
|
|
641
|
-
|
|
634
|
+
trimMaskRectBounds(selectionRect, {
|
|
642
635
|
x: 0,
|
|
643
636
|
y: 0,
|
|
644
637
|
w: width,
|
|
@@ -1750,6 +1743,24 @@ var getKeyByValue = (obj, value) => {
|
|
|
1750
1743
|
var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
|
|
1751
1744
|
var CANVAS_CTX_FAILED = "Failed to create Canvas context";
|
|
1752
1745
|
|
|
1746
|
+
// src/Canvas/canvas-blend-modes.ts
|
|
1747
|
+
var CANVAS_COMPOSITE_MAP = {
|
|
1748
|
+
[BaseBlendMode.overwrite]: "copy",
|
|
1749
|
+
[BaseBlendMode.sourceOver]: "source-over",
|
|
1750
|
+
[BaseBlendMode.darken]: "darken",
|
|
1751
|
+
[BaseBlendMode.multiply]: "multiply",
|
|
1752
|
+
[BaseBlendMode.colorBurn]: "color-burn",
|
|
1753
|
+
[BaseBlendMode.lighten]: "lighten",
|
|
1754
|
+
[BaseBlendMode.screen]: "screen",
|
|
1755
|
+
[BaseBlendMode.colorDodge]: "color-dodge",
|
|
1756
|
+
[BaseBlendMode.linearDodge]: "lighter",
|
|
1757
|
+
[BaseBlendMode.overlay]: "overlay",
|
|
1758
|
+
[BaseBlendMode.softLight]: "soft-light",
|
|
1759
|
+
[BaseBlendMode.hardLight]: "hard-light",
|
|
1760
|
+
[BaseBlendMode.difference]: "difference",
|
|
1761
|
+
[BaseBlendMode.exclusion]: "exclusion"
|
|
1762
|
+
};
|
|
1763
|
+
|
|
1753
1764
|
// src/Canvas/ReusableCanvas.ts
|
|
1754
1765
|
function makeReusableCanvas() {
|
|
1755
1766
|
return makeReusableCanvasMeta((w, h) => {
|
|
@@ -2028,11 +2039,11 @@ var PixelAccumulator = class {
|
|
|
2028
2039
|
* @param y pixel y coordinate
|
|
2029
2040
|
*/
|
|
2030
2041
|
storePixelBeforeState(x, y) {
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2042
|
+
const shift = this.config.tileShift;
|
|
2043
|
+
const columns = this.config.targetColumns;
|
|
2044
|
+
const tx = x >> shift;
|
|
2045
|
+
const ty = y >> shift;
|
|
2046
|
+
const id = ty * columns + tx;
|
|
2036
2047
|
let tile = this.lookup[id];
|
|
2037
2048
|
let added = false;
|
|
2038
2049
|
if (!tile) {
|
|
@@ -2058,16 +2069,16 @@ var PixelAccumulator = class {
|
|
|
2058
2069
|
* @param h pixel height
|
|
2059
2070
|
*/
|
|
2060
2071
|
storeRegionBeforeState(x, y, w, h) {
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2072
|
+
const shift = this.config.tileShift;
|
|
2073
|
+
const columns = this.config.targetColumns;
|
|
2074
|
+
const startX = x >> shift;
|
|
2075
|
+
const startY = y >> shift;
|
|
2076
|
+
const endX = x + w - 1 >> shift;
|
|
2077
|
+
const endY = y + h - 1 >> shift;
|
|
2078
|
+
const startIndex = this.beforeTiles.length;
|
|
2068
2079
|
for (let ty = startY; ty <= endY; ty++) {
|
|
2069
2080
|
for (let tx = startX; tx <= endX; tx++) {
|
|
2070
|
-
|
|
2081
|
+
const id = ty * columns + tx;
|
|
2071
2082
|
let tile = this.lookup[id];
|
|
2072
2083
|
if (!tile) {
|
|
2073
2084
|
tile = this.tilePool.getTile(id, tx, ty);
|
|
@@ -2079,7 +2090,7 @@ var PixelAccumulator = class {
|
|
|
2079
2090
|
}
|
|
2080
2091
|
return (didChange) => {
|
|
2081
2092
|
if (!didChange) {
|
|
2082
|
-
|
|
2093
|
+
const length = this.beforeTiles.length;
|
|
2083
2094
|
for (let i = startIndex; i < length; i++) {
|
|
2084
2095
|
let t = this.beforeTiles[i];
|
|
2085
2096
|
if (t) {
|
|
@@ -2092,15 +2103,34 @@ var PixelAccumulator = class {
|
|
|
2092
2103
|
return didChange;
|
|
2093
2104
|
};
|
|
2094
2105
|
}
|
|
2106
|
+
storeTileBeforeState(id, tx, ty) {
|
|
2107
|
+
let tile = this.lookup[id];
|
|
2108
|
+
let added = false;
|
|
2109
|
+
if (!tile) {
|
|
2110
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
2111
|
+
this.extractState(tile);
|
|
2112
|
+
this.lookup[id] = tile;
|
|
2113
|
+
this.beforeTiles.push(tile);
|
|
2114
|
+
added = true;
|
|
2115
|
+
}
|
|
2116
|
+
return (didChange) => {
|
|
2117
|
+
if (!didChange && added) {
|
|
2118
|
+
this.beforeTiles.pop();
|
|
2119
|
+
this.lookup[id] = void 0;
|
|
2120
|
+
this.tilePool.releaseTile(tile);
|
|
2121
|
+
}
|
|
2122
|
+
return didChange;
|
|
2123
|
+
};
|
|
2124
|
+
}
|
|
2095
2125
|
extractState(tile) {
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2126
|
+
const target = this.config.target;
|
|
2127
|
+
const TILE_SIZE = this.config.tileSize;
|
|
2128
|
+
const dst = tile.data32;
|
|
2129
|
+
const src = target.data32;
|
|
2130
|
+
const startX = tile.tx * TILE_SIZE;
|
|
2131
|
+
const startY = tile.ty * TILE_SIZE;
|
|
2132
|
+
const targetWidth = target.width;
|
|
2133
|
+
const targetHeight = target.height;
|
|
2104
2134
|
if (startX >= targetWidth || startX + TILE_SIZE <= 0 || startY >= targetHeight || startY + TILE_SIZE <= 0) {
|
|
2105
2135
|
dst.fill(0);
|
|
2106
2136
|
return;
|
|
@@ -2126,8 +2156,8 @@ var PixelAccumulator = class {
|
|
|
2126
2156
|
}
|
|
2127
2157
|
}
|
|
2128
2158
|
extractPatch() {
|
|
2129
|
-
|
|
2130
|
-
|
|
2159
|
+
const afterTiles = [];
|
|
2160
|
+
const length = this.beforeTiles.length;
|
|
2131
2161
|
for (let i = 0; i < length; i++) {
|
|
2132
2162
|
let beforeTile = this.beforeTiles[i];
|
|
2133
2163
|
if (beforeTile) {
|
|
@@ -2136,7 +2166,7 @@ var PixelAccumulator = class {
|
|
|
2136
2166
|
afterTiles.push(afterTile);
|
|
2137
2167
|
}
|
|
2138
2168
|
}
|
|
2139
|
-
|
|
2169
|
+
const beforeTiles = this.beforeTiles;
|
|
2140
2170
|
this.beforeTiles = [];
|
|
2141
2171
|
this.lookup.length = 0;
|
|
2142
2172
|
return {
|
|
@@ -2144,10 +2174,10 @@ var PixelAccumulator = class {
|
|
|
2144
2174
|
afterTiles
|
|
2145
2175
|
};
|
|
2146
2176
|
}
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2177
|
+
rollbackAfterError() {
|
|
2178
|
+
const target = this.config.target;
|
|
2179
|
+
const tileSize = this.config.tileSize;
|
|
2180
|
+
const length = this.beforeTiles.length;
|
|
2151
2181
|
applyPatchTiles(target, this.beforeTiles, tileSize);
|
|
2152
2182
|
for (let i = 0; i < length; i++) {
|
|
2153
2183
|
let tile = this.beforeTiles[i];
|
|
@@ -2171,6 +2201,7 @@ var PixelEngineConfig = class {
|
|
|
2171
2201
|
tileArea;
|
|
2172
2202
|
target;
|
|
2173
2203
|
targetColumns = 0;
|
|
2204
|
+
targetRows = 0;
|
|
2174
2205
|
constructor(tileSize, target) {
|
|
2175
2206
|
if ((tileSize & tileSize - 1) !== 0) {
|
|
2176
2207
|
throw new Error("tileSize must be a power of 2");
|
|
@@ -2179,28 +2210,26 @@ var PixelEngineConfig = class {
|
|
|
2179
2210
|
this.tileShift = 31 - Math.clz32(tileSize);
|
|
2180
2211
|
this.tileMask = tileSize - 1;
|
|
2181
2212
|
this.tileArea = tileSize * tileSize;
|
|
2182
|
-
this.setTarget(target);
|
|
2183
|
-
}
|
|
2184
|
-
setTarget(target) {
|
|
2185
|
-
;
|
|
2186
2213
|
this.target = target;
|
|
2187
2214
|
this.targetColumns = target.width + this.tileMask >> this.tileShift;
|
|
2215
|
+
this.targetRows = target.height + this.tileMask >> this.tileShift;
|
|
2188
2216
|
}
|
|
2189
2217
|
};
|
|
2190
2218
|
|
|
2191
|
-
// src/PixelData/
|
|
2192
|
-
function
|
|
2219
|
+
// src/PixelData/blendColorPixelData.ts
|
|
2220
|
+
function blendColorPixelData(dst, color, opts = {}) {
|
|
2193
2221
|
const {
|
|
2194
2222
|
x: targetX = 0,
|
|
2195
2223
|
y: targetY = 0,
|
|
2196
2224
|
w: width = dst.width,
|
|
2197
2225
|
h: height = dst.height,
|
|
2198
2226
|
alpha: globalAlpha = 255,
|
|
2199
|
-
|
|
2200
|
-
my = 0,
|
|
2201
|
-
invertMask = false
|
|
2227
|
+
blendFn = sourceOverPerfect
|
|
2202
2228
|
} = opts;
|
|
2203
2229
|
if (globalAlpha === 0) return false;
|
|
2230
|
+
const baseSrcAlpha = color >>> 24;
|
|
2231
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2232
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2204
2233
|
let x = targetX;
|
|
2205
2234
|
let y = targetY;
|
|
2206
2235
|
let w = width;
|
|
@@ -2213,82 +2242,46 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2213
2242
|
h += y;
|
|
2214
2243
|
y = 0;
|
|
2215
2244
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
if (
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
const sY0 = Math.max(0, startY);
|
|
2226
|
-
const sX1 = Math.min(mPitch, startX + w);
|
|
2227
|
-
const sY1 = Math.min(mask.h, startY + h);
|
|
2228
|
-
const finalW = sX1 - sX0;
|
|
2229
|
-
const finalH = sY1 - sY0;
|
|
2230
|
-
if (finalW <= 0) return false;
|
|
2231
|
-
if (finalH <= 0) return false;
|
|
2232
|
-
const xShift = sX0 - startX;
|
|
2233
|
-
const yShift = sY0 - startY;
|
|
2245
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2246
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2247
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2248
|
+
let finalSrcColor = color;
|
|
2249
|
+
if (globalAlpha < 255) {
|
|
2250
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2251
|
+
if (a === 0 && !isOverwrite) return false;
|
|
2252
|
+
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
2253
|
+
}
|
|
2234
2254
|
const dst32 = dst.data32;
|
|
2235
2255
|
const dw = dst.width;
|
|
2236
|
-
|
|
2237
|
-
const
|
|
2238
|
-
const maskData = mask.data;
|
|
2239
|
-
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2240
|
-
let mIdx = sY0 * mPitch + sX0;
|
|
2256
|
+
let dIdx = y * dw + x | 0;
|
|
2257
|
+
const dStride = dw - actualW | 0;
|
|
2241
2258
|
let didChange = false;
|
|
2242
|
-
for (let iy = 0; iy <
|
|
2243
|
-
for (let ix = 0; ix <
|
|
2244
|
-
const
|
|
2245
|
-
const
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
weight = 0;
|
|
2249
|
-
} else if (effectiveM === 255) {
|
|
2250
|
-
weight = globalAlpha;
|
|
2251
|
-
} else if (globalAlpha === 255) {
|
|
2252
|
-
weight = effectiveM;
|
|
2253
|
-
} else {
|
|
2254
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2255
|
-
}
|
|
2256
|
-
if (weight === 0) {
|
|
2257
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2259
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2260
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2261
|
+
const current = dst32[dIdx];
|
|
2262
|
+
const next = blendFn(finalSrcColor, current);
|
|
2263
|
+
if (current !== next) {
|
|
2264
|
+
dst32[dIdx] = next;
|
|
2258
2265
|
didChange = true;
|
|
2259
|
-
} else if (weight !== 255) {
|
|
2260
|
-
const d = dst32[dIdx];
|
|
2261
|
-
const da = d >>> 24;
|
|
2262
|
-
if (da !== 0) {
|
|
2263
|
-
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
2264
|
-
const current = dst32[dIdx];
|
|
2265
|
-
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2266
|
-
if (current !== next) {
|
|
2267
|
-
dst32[dIdx] = next;
|
|
2268
|
-
didChange = true;
|
|
2269
|
-
}
|
|
2270
|
-
}
|
|
2271
2266
|
}
|
|
2272
2267
|
dIdx++;
|
|
2273
|
-
mIdx++;
|
|
2274
2268
|
}
|
|
2275
2269
|
dIdx += dStride;
|
|
2276
|
-
mIdx += mStride;
|
|
2277
2270
|
}
|
|
2278
2271
|
return didChange;
|
|
2279
2272
|
}
|
|
2280
2273
|
|
|
2281
|
-
// src/History/PixelMutator/
|
|
2274
|
+
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2282
2275
|
var defaults2 = {
|
|
2283
|
-
|
|
2276
|
+
blendColorPixelData
|
|
2284
2277
|
};
|
|
2285
|
-
var
|
|
2278
|
+
var mutatorBlendColor = ((writer, deps = defaults2) => {
|
|
2286
2279
|
const {
|
|
2287
|
-
|
|
2280
|
+
blendColorPixelData: blendColorPixelData2 = defaults2.blendColorPixelData
|
|
2288
2281
|
} = deps;
|
|
2289
2282
|
return {
|
|
2290
|
-
|
|
2291
|
-
|
|
2283
|
+
blendColor(color, opts = {}) {
|
|
2284
|
+
const target = writer.config.target;
|
|
2292
2285
|
const {
|
|
2293
2286
|
x = 0,
|
|
2294
2287
|
y = 0,
|
|
@@ -2296,159 +2289,227 @@ var mutatorApplyAlphaMask = ((writer, deps = defaults2) => {
|
|
|
2296
2289
|
h = target.height
|
|
2297
2290
|
} = opts;
|
|
2298
2291
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2299
|
-
return didChange(
|
|
2292
|
+
return didChange(blendColorPixelData2(target, color, opts));
|
|
2300
2293
|
}
|
|
2301
2294
|
};
|
|
2302
2295
|
});
|
|
2303
2296
|
|
|
2304
|
-
// src/PixelData/
|
|
2305
|
-
function
|
|
2297
|
+
// src/PixelData/blendPixel.ts
|
|
2298
|
+
function blendPixel(target, x, y, color, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2299
|
+
if (alpha === 0) return false;
|
|
2300
|
+
let width = target.width;
|
|
2301
|
+
let height = target.height;
|
|
2302
|
+
if (x < 0 || x >= width || y < 0 || y >= height) return false;
|
|
2303
|
+
let srcAlpha = color >>> 24;
|
|
2304
|
+
let isOverwrite = blendFn.isOverwrite;
|
|
2305
|
+
if (srcAlpha === 0 && !isOverwrite) return false;
|
|
2306
|
+
let dst32 = target.data32;
|
|
2307
|
+
let index = y * width + x;
|
|
2308
|
+
let finalColor = color;
|
|
2309
|
+
if (alpha !== 255) {
|
|
2310
|
+
let finalAlpha = srcAlpha * alpha + 128 >> 8;
|
|
2311
|
+
if (finalAlpha === 0 && !isOverwrite) return false;
|
|
2312
|
+
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
2313
|
+
}
|
|
2314
|
+
let current = dst32[index];
|
|
2315
|
+
let next = blendFn(finalColor, current);
|
|
2316
|
+
if (current !== next) {
|
|
2317
|
+
dst32[index] = next;
|
|
2318
|
+
return true;
|
|
2319
|
+
}
|
|
2320
|
+
return false;
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2324
|
+
var defaults3 = {
|
|
2325
|
+
blendPixel
|
|
2326
|
+
};
|
|
2327
|
+
var mutatorBlendPixel = ((writer, deps = defaults3) => {
|
|
2328
|
+
const {
|
|
2329
|
+
blendPixel: blendPixel2 = defaults3.blendPixel
|
|
2330
|
+
} = deps;
|
|
2331
|
+
return {
|
|
2332
|
+
blendPixel(x, y, color, alpha, blendFn) {
|
|
2333
|
+
const didChange = writer.accumulator.storePixelBeforeState(x, y);
|
|
2334
|
+
return didChange(blendPixel2(writer.config.target, x, y, color, alpha, blendFn));
|
|
2335
|
+
}
|
|
2336
|
+
};
|
|
2337
|
+
});
|
|
2338
|
+
|
|
2339
|
+
// src/PixelData/blendPixelData.ts
|
|
2340
|
+
function blendPixelData(dst, src, opts = {}) {
|
|
2306
2341
|
const {
|
|
2307
2342
|
x: targetX = 0,
|
|
2308
2343
|
y: targetY = 0,
|
|
2309
|
-
|
|
2310
|
-
|
|
2344
|
+
sx: sourceX = 0,
|
|
2345
|
+
sy: sourceY = 0,
|
|
2346
|
+
w: width = src.width,
|
|
2347
|
+
h: height = src.height,
|
|
2311
2348
|
alpha: globalAlpha = 255,
|
|
2312
|
-
|
|
2313
|
-
my = 0,
|
|
2314
|
-
invertMask = false
|
|
2349
|
+
blendFn = sourceOverPerfect
|
|
2315
2350
|
} = opts;
|
|
2316
2351
|
if (globalAlpha === 0) return false;
|
|
2317
2352
|
let x = targetX;
|
|
2318
2353
|
let y = targetY;
|
|
2354
|
+
let sx = sourceX;
|
|
2355
|
+
let sy = sourceY;
|
|
2319
2356
|
let w = width;
|
|
2320
2357
|
let h = height;
|
|
2358
|
+
if (sx < 0) {
|
|
2359
|
+
x -= sx;
|
|
2360
|
+
w += sx;
|
|
2361
|
+
sx = 0;
|
|
2362
|
+
}
|
|
2363
|
+
if (sy < 0) {
|
|
2364
|
+
y -= sy;
|
|
2365
|
+
h += sy;
|
|
2366
|
+
sy = 0;
|
|
2367
|
+
}
|
|
2368
|
+
w = Math.min(w, src.width - sx);
|
|
2369
|
+
h = Math.min(h, src.height - sy);
|
|
2321
2370
|
if (x < 0) {
|
|
2371
|
+
sx -= x;
|
|
2322
2372
|
w += x;
|
|
2323
2373
|
x = 0;
|
|
2324
2374
|
}
|
|
2325
2375
|
if (y < 0) {
|
|
2376
|
+
sy -= y;
|
|
2326
2377
|
h += y;
|
|
2327
2378
|
y = 0;
|
|
2328
2379
|
}
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
if (
|
|
2332
|
-
const mPitch = mask.w;
|
|
2333
|
-
if (mPitch <= 0) return false;
|
|
2334
|
-
const startX = mx + (x - targetX);
|
|
2335
|
-
const startY = my + (y - targetY);
|
|
2336
|
-
const sX0 = Math.max(0, startX);
|
|
2337
|
-
const sY0 = Math.max(0, startY);
|
|
2338
|
-
const sX1 = Math.min(mPitch, startX + w);
|
|
2339
|
-
const sY1 = Math.min(mask.h, startY + h);
|
|
2340
|
-
const finalW = sX1 - sX0;
|
|
2341
|
-
const finalH = sY1 - sY0;
|
|
2342
|
-
if (finalW <= 0 || finalH <= 0) {
|
|
2343
|
-
return false;
|
|
2344
|
-
}
|
|
2345
|
-
const xShift = sX0 - startX;
|
|
2346
|
-
const yShift = sY0 - startY;
|
|
2380
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2381
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2382
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2347
2383
|
const dst32 = dst.data32;
|
|
2384
|
+
const src32 = src.data32;
|
|
2348
2385
|
const dw = dst.width;
|
|
2349
|
-
const
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2386
|
+
const sw = src.width;
|
|
2387
|
+
let dIdx = y * dw + x | 0;
|
|
2388
|
+
let sIdx = sy * sw + sx | 0;
|
|
2389
|
+
const dStride = dw - actualW | 0;
|
|
2390
|
+
const sStride = sw - actualW | 0;
|
|
2391
|
+
const isOpaque = globalAlpha === 255;
|
|
2392
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2354
2393
|
let didChange = false;
|
|
2355
|
-
for (let iy = 0; iy <
|
|
2356
|
-
for (let ix = 0; ix <
|
|
2357
|
-
const
|
|
2358
|
-
const
|
|
2359
|
-
if (
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2372
|
-
if (d !== next) {
|
|
2373
|
-
dst32[dIdx] = next;
|
|
2374
|
-
didChange = true;
|
|
2375
|
-
}
|
|
2394
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2395
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2396
|
+
const srcCol = src32[sIdx];
|
|
2397
|
+
const srcAlpha = srcCol >>> 24;
|
|
2398
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2399
|
+
dIdx++;
|
|
2400
|
+
sIdx++;
|
|
2401
|
+
continue;
|
|
2402
|
+
}
|
|
2403
|
+
let finalCol = srcCol;
|
|
2404
|
+
if (!isOpaque) {
|
|
2405
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
2406
|
+
if (a === 0 && !isOverwrite) {
|
|
2407
|
+
dIdx++;
|
|
2408
|
+
sIdx++;
|
|
2409
|
+
continue;
|
|
2376
2410
|
}
|
|
2411
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2412
|
+
}
|
|
2413
|
+
const current = dst32[dIdx];
|
|
2414
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
2415
|
+
if (current !== next) {
|
|
2416
|
+
dst32[dIdx] = next;
|
|
2417
|
+
didChange = true;
|
|
2377
2418
|
}
|
|
2378
2419
|
dIdx++;
|
|
2379
|
-
|
|
2420
|
+
sIdx++;
|
|
2380
2421
|
}
|
|
2381
2422
|
dIdx += dStride;
|
|
2382
|
-
|
|
2423
|
+
sIdx += sStride;
|
|
2383
2424
|
}
|
|
2384
2425
|
return didChange;
|
|
2385
2426
|
}
|
|
2386
2427
|
|
|
2387
|
-
// src/History/PixelMutator/
|
|
2388
|
-
var
|
|
2389
|
-
|
|
2428
|
+
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
2429
|
+
var defaults4 = {
|
|
2430
|
+
blendPixelData
|
|
2390
2431
|
};
|
|
2391
|
-
var
|
|
2432
|
+
var mutatorBlendPixelData = ((writer, deps = defaults4) => {
|
|
2392
2433
|
const {
|
|
2393
|
-
|
|
2434
|
+
blendPixelData: blendPixelData2 = defaults4.blendPixelData
|
|
2394
2435
|
} = deps;
|
|
2395
2436
|
return {
|
|
2396
|
-
|
|
2397
|
-
let target = writer.config.target;
|
|
2437
|
+
blendPixelData(src, opts = {}) {
|
|
2398
2438
|
const {
|
|
2399
2439
|
x = 0,
|
|
2400
2440
|
y = 0,
|
|
2401
|
-
w =
|
|
2402
|
-
h =
|
|
2441
|
+
w = src.width,
|
|
2442
|
+
h = src.height
|
|
2403
2443
|
} = opts;
|
|
2404
2444
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2405
|
-
return didChange(
|
|
2445
|
+
return didChange(blendPixelData2(writer.config.target, src, opts));
|
|
2406
2446
|
}
|
|
2407
2447
|
};
|
|
2408
2448
|
});
|
|
2409
2449
|
|
|
2410
|
-
// src/PixelData/
|
|
2411
|
-
function
|
|
2412
|
-
const
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2450
|
+
// src/PixelData/blendPixelDataAlphaMask.ts
|
|
2451
|
+
function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
2452
|
+
const {
|
|
2453
|
+
x: targetX = 0,
|
|
2454
|
+
y: targetY = 0,
|
|
2455
|
+
sx: sourceX = 0,
|
|
2456
|
+
sy: sourceY = 0,
|
|
2457
|
+
w: width = src.width,
|
|
2458
|
+
h: height = src.height,
|
|
2459
|
+
alpha: globalAlpha = 255,
|
|
2460
|
+
blendFn = sourceOverPerfect,
|
|
2461
|
+
mx = 0,
|
|
2462
|
+
my = 0,
|
|
2463
|
+
invertMask = false
|
|
2464
|
+
} = opts;
|
|
2421
2465
|
if (globalAlpha === 0) return false;
|
|
2422
|
-
const baseSrcAlpha = color >>> 24;
|
|
2423
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
2424
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2425
2466
|
let x = targetX;
|
|
2426
2467
|
let y = targetY;
|
|
2427
|
-
let
|
|
2428
|
-
let
|
|
2468
|
+
let sx = sourceX;
|
|
2469
|
+
let sy = sourceY;
|
|
2470
|
+
let w = width;
|
|
2471
|
+
let h = height;
|
|
2472
|
+
if (sx < 0) {
|
|
2473
|
+
x -= sx;
|
|
2474
|
+
w += sx;
|
|
2475
|
+
sx = 0;
|
|
2476
|
+
}
|
|
2477
|
+
if (sy < 0) {
|
|
2478
|
+
y -= sy;
|
|
2479
|
+
h += sy;
|
|
2480
|
+
sy = 0;
|
|
2481
|
+
}
|
|
2482
|
+
w = Math.min(w, src.width - sx);
|
|
2483
|
+
h = Math.min(h, src.height - sy);
|
|
2429
2484
|
if (x < 0) {
|
|
2430
|
-
|
|
2485
|
+
sx -= x;
|
|
2486
|
+
w += x;
|
|
2431
2487
|
x = 0;
|
|
2432
2488
|
}
|
|
2433
2489
|
if (y < 0) {
|
|
2434
|
-
|
|
2490
|
+
sy -= y;
|
|
2491
|
+
h += y;
|
|
2435
2492
|
y = 0;
|
|
2436
2493
|
}
|
|
2437
|
-
actualW = Math.min(
|
|
2438
|
-
actualH = Math.min(
|
|
2494
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2495
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2439
2496
|
if (actualW <= 0 || actualH <= 0) return false;
|
|
2497
|
+
const dw = dst.width;
|
|
2498
|
+
const sw = src.width;
|
|
2499
|
+
const mPitch = alphaMask.w;
|
|
2500
|
+
const maskData = alphaMask.data;
|
|
2440
2501
|
const dx = x - targetX | 0;
|
|
2441
2502
|
const dy = y - targetY | 0;
|
|
2442
2503
|
const dst32 = dst.data32;
|
|
2443
|
-
const
|
|
2444
|
-
const mPitch = mask.w;
|
|
2445
|
-
const maskData = mask.data;
|
|
2504
|
+
const src32 = src.data32;
|
|
2446
2505
|
let dIdx = y * dw + x | 0;
|
|
2506
|
+
let sIdx = sy * sw + sx | 0;
|
|
2447
2507
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2448
2508
|
const dStride = dw - actualW | 0;
|
|
2509
|
+
const sStride = sw - actualW | 0;
|
|
2449
2510
|
const mStride = mPitch - actualW | 0;
|
|
2450
2511
|
const isOpaque = globalAlpha === 255;
|
|
2451
|
-
const
|
|
2512
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2452
2513
|
let didChange = false;
|
|
2453
2514
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2454
2515
|
for (let ix = 0; ix < actualW; ix++) {
|
|
@@ -2456,6 +2517,15 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2456
2517
|
const effM = invertMask ? 255 - mVal : mVal;
|
|
2457
2518
|
if (effM === 0) {
|
|
2458
2519
|
dIdx++;
|
|
2520
|
+
sIdx++;
|
|
2521
|
+
mIdx++;
|
|
2522
|
+
continue;
|
|
2523
|
+
}
|
|
2524
|
+
const srcCol = src32[sIdx];
|
|
2525
|
+
const srcAlpha = srcCol >>> 24;
|
|
2526
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2527
|
+
dIdx++;
|
|
2528
|
+
sIdx++;
|
|
2459
2529
|
mIdx++;
|
|
2460
2530
|
continue;
|
|
2461
2531
|
}
|
|
@@ -2467,844 +2537,459 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2467
2537
|
}
|
|
2468
2538
|
if (weight === 0) {
|
|
2469
2539
|
dIdx++;
|
|
2540
|
+
sIdx++;
|
|
2470
2541
|
mIdx++;
|
|
2471
2542
|
continue;
|
|
2472
2543
|
}
|
|
2473
|
-
let finalCol =
|
|
2544
|
+
let finalCol = srcCol;
|
|
2474
2545
|
if (weight < 255) {
|
|
2475
|
-
const a =
|
|
2546
|
+
const a = srcAlpha * weight + 128 >> 8;
|
|
2476
2547
|
if (a === 0 && !isOverwrite) {
|
|
2477
2548
|
dIdx++;
|
|
2549
|
+
sIdx++;
|
|
2478
2550
|
mIdx++;
|
|
2479
2551
|
continue;
|
|
2480
2552
|
}
|
|
2481
|
-
finalCol = (
|
|
2553
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2482
2554
|
}
|
|
2483
2555
|
const current = dst32[dIdx];
|
|
2484
|
-
const next = blendFn(finalCol,
|
|
2556
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
2485
2557
|
if (current !== next) {
|
|
2486
2558
|
dst32[dIdx] = next;
|
|
2487
2559
|
didChange = true;
|
|
2488
2560
|
}
|
|
2489
2561
|
dIdx++;
|
|
2562
|
+
sIdx++;
|
|
2490
2563
|
mIdx++;
|
|
2491
2564
|
}
|
|
2492
2565
|
dIdx += dStride;
|
|
2566
|
+
sIdx += sStride;
|
|
2493
2567
|
mIdx += mStride;
|
|
2494
2568
|
}
|
|
2495
2569
|
return didChange;
|
|
2496
2570
|
}
|
|
2497
2571
|
|
|
2498
|
-
// src/
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
const minOffset = -Math.ceil(r - 0.5);
|
|
2502
|
-
const maxOffset = Math.floor(r - 0.5);
|
|
2503
|
-
const startX = Math.floor(centerX + minOffset);
|
|
2504
|
-
const startY = Math.floor(centerY + minOffset);
|
|
2505
|
-
const endX = Math.floor(centerX + maxOffset) + 1;
|
|
2506
|
-
const endY = Math.floor(centerY + maxOffset) + 1;
|
|
2507
|
-
const res = out ?? {
|
|
2508
|
-
x: 0,
|
|
2509
|
-
y: 0,
|
|
2510
|
-
w: 0,
|
|
2511
|
-
h: 0
|
|
2512
|
-
};
|
|
2513
|
-
const cStartX = Math.max(0, startX);
|
|
2514
|
-
const cStartY = Math.max(0, startY);
|
|
2515
|
-
const cEndX = Math.min(targetWidth, endX);
|
|
2516
|
-
const cEndY = Math.min(targetHeight, endY);
|
|
2517
|
-
const w = cEndX - cStartX;
|
|
2518
|
-
const h = cEndY - cStartY;
|
|
2519
|
-
res.x = cStartX;
|
|
2520
|
-
res.y = cStartY;
|
|
2521
|
-
res.w = w < 0 ? 0 : w;
|
|
2522
|
-
res.h = h < 0 ? 0 : h;
|
|
2523
|
-
return res;
|
|
2524
|
-
}
|
|
2525
|
-
|
|
2526
|
-
// src/Rect/getCircleBrushOrPencilStrokeBounds.ts
|
|
2527
|
-
function getCircleBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushSize, result) {
|
|
2528
|
-
const r = Math.ceil(brushSize / 2);
|
|
2529
|
-
const minX = Math.min(x0, x1) - r;
|
|
2530
|
-
const minY = Math.min(y0, y1) - r;
|
|
2531
|
-
const maxX = Math.max(x0, x1) + r;
|
|
2532
|
-
const maxY = Math.max(x0, y1) + r;
|
|
2533
|
-
result.x = Math.floor(minX);
|
|
2534
|
-
result.y = Math.floor(minY);
|
|
2535
|
-
result.w = Math.ceil(maxX - minX);
|
|
2536
|
-
result.h = Math.ceil(maxY - minY);
|
|
2537
|
-
return result;
|
|
2538
|
-
}
|
|
2539
|
-
|
|
2540
|
-
// src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts
|
|
2541
|
-
var defaults4 = {
|
|
2542
|
-
forEachLinePoint,
|
|
2543
|
-
blendColorPixelDataAlphaMask,
|
|
2544
|
-
getCircleBrushOrPencilBounds,
|
|
2545
|
-
getCircleBrushOrPencilStrokeBounds
|
|
2572
|
+
// src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts
|
|
2573
|
+
var defaults5 = {
|
|
2574
|
+
blendPixelDataAlphaMask
|
|
2546
2575
|
};
|
|
2547
|
-
var
|
|
2576
|
+
var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults5) => {
|
|
2548
2577
|
const {
|
|
2549
|
-
|
|
2550
|
-
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults4.blendColorPixelDataAlphaMask,
|
|
2551
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults4.getCircleBrushOrPencilBounds,
|
|
2552
|
-
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults4.getCircleBrushOrPencilStrokeBounds
|
|
2578
|
+
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults5.blendPixelDataAlphaMask
|
|
2553
2579
|
} = deps;
|
|
2554
|
-
const strokeBoundsOut = {
|
|
2555
|
-
x: 0,
|
|
2556
|
-
y: 0,
|
|
2557
|
-
w: 0,
|
|
2558
|
-
h: 0
|
|
2559
|
-
};
|
|
2560
|
-
const circleBrushBounds = {
|
|
2561
|
-
x: 0,
|
|
2562
|
-
y: 0,
|
|
2563
|
-
w: 0,
|
|
2564
|
-
h: 0
|
|
2565
|
-
};
|
|
2566
|
-
const blendColorPixelOptions = {
|
|
2567
|
-
alpha: 255,
|
|
2568
|
-
blendFn: sourceOverPerfect,
|
|
2569
|
-
x: 0,
|
|
2570
|
-
y: 0,
|
|
2571
|
-
w: 0,
|
|
2572
|
-
h: 0
|
|
2573
|
-
};
|
|
2574
|
-
const mask = {
|
|
2575
|
-
type: 0 /* ALPHA */,
|
|
2576
|
-
data: null,
|
|
2577
|
-
w: 0,
|
|
2578
|
-
h: 0
|
|
2579
|
-
};
|
|
2580
2580
|
return {
|
|
2581
|
-
|
|
2582
|
-
const
|
|
2583
|
-
const
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
|
|
2589
|
-
if (bw <= 0 || bh <= 0) return;
|
|
2590
|
-
mask.data = new Uint8Array(bw * bh);
|
|
2591
|
-
mask.w = bw;
|
|
2592
|
-
mask.h = bh;
|
|
2593
|
-
const maskData = mask.data;
|
|
2594
|
-
const brushData = brush.data;
|
|
2595
|
-
const minOffset = brush.minOffset;
|
|
2596
|
-
const target = writer.config.target;
|
|
2597
|
-
const targetWidth = target.width;
|
|
2598
|
-
const targetHeight = target.height;
|
|
2599
|
-
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2600
|
-
const {
|
|
2601
|
-
x: cbx,
|
|
2602
|
-
y: cby,
|
|
2603
|
-
w: cbw,
|
|
2604
|
-
h: cbh
|
|
2605
|
-
} = getCircleBrushOrPencilBounds2(px, py, brushSize, targetWidth, targetHeight, circleBrushBounds);
|
|
2606
|
-
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2607
|
-
const startX = Math.max(bx, cbx);
|
|
2608
|
-
const startY = Math.max(by, cby);
|
|
2609
|
-
const endX = Math.min(bx + bw, cbx + cbw);
|
|
2610
|
-
const endY = Math.min(by + bh, cby + cbh);
|
|
2611
|
-
const unclippedStartX = Math.floor(px + minOffset);
|
|
2612
|
-
const unclippedStartY = Math.floor(py + minOffset);
|
|
2613
|
-
for (let my = startY; my < endY; my++) {
|
|
2614
|
-
const strokeMaskY = my - by;
|
|
2615
|
-
const strokeMaskRowOffset = strokeMaskY * bw;
|
|
2616
|
-
const brushY = my - unclippedStartY;
|
|
2617
|
-
const brushRowOffset = brushY * brushSize;
|
|
2618
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
2619
|
-
const brushX = mx - unclippedStartX;
|
|
2620
|
-
const brushVal = brushData[brushRowOffset + brushX];
|
|
2621
|
-
if (brushVal > 0) {
|
|
2622
|
-
const strokeMaskIdx = strokeMaskRowOffset + (mx - bx);
|
|
2623
|
-
if (brushVal > maskData[strokeMaskIdx]) {
|
|
2624
|
-
maskData[strokeMaskIdx] = brushVal;
|
|
2625
|
-
}
|
|
2626
|
-
}
|
|
2627
|
-
}
|
|
2628
|
-
}
|
|
2629
|
-
});
|
|
2630
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
2631
|
-
blendColorPixelOptions.alpha = alpha;
|
|
2632
|
-
blendColorPixelOptions.x = bx;
|
|
2633
|
-
blendColorPixelOptions.y = by;
|
|
2634
|
-
blendColorPixelOptions.w = bw;
|
|
2635
|
-
blendColorPixelOptions.h = bh;
|
|
2636
|
-
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2581
|
+
blendPixelDataAlphaMask(src, mask, opts = {}) {
|
|
2582
|
+
const x = opts.x ?? 0;
|
|
2583
|
+
const y = opts.y ?? 0;
|
|
2584
|
+
const w = opts.w ?? src.width;
|
|
2585
|
+
const h = opts.h ?? src.height;
|
|
2586
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2587
|
+
return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
|
|
2637
2588
|
}
|
|
2638
2589
|
};
|
|
2639
2590
|
});
|
|
2640
2591
|
|
|
2641
|
-
// src/PixelData/
|
|
2642
|
-
function
|
|
2643
|
-
const
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2592
|
+
// src/PixelData/blendPixelDataBinaryMask.ts
|
|
2593
|
+
function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
2594
|
+
const {
|
|
2595
|
+
x: targetX = 0,
|
|
2596
|
+
y: targetY = 0,
|
|
2597
|
+
sx: sourceX = 0,
|
|
2598
|
+
sy: sourceY = 0,
|
|
2599
|
+
w: width = src.width,
|
|
2600
|
+
h: height = src.height,
|
|
2601
|
+
alpha: globalAlpha = 255,
|
|
2602
|
+
blendFn = sourceOverPerfect,
|
|
2603
|
+
mx = 0,
|
|
2604
|
+
my = 0,
|
|
2605
|
+
invertMask = false
|
|
2606
|
+
} = opts;
|
|
2652
2607
|
if (globalAlpha === 0) return false;
|
|
2653
|
-
const baseSrcAlpha = color >>> 24;
|
|
2654
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
2655
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2656
2608
|
let x = targetX;
|
|
2657
2609
|
let y = targetY;
|
|
2610
|
+
let sx = sourceX;
|
|
2611
|
+
let sy = sourceY;
|
|
2612
|
+
let w = width;
|
|
2613
|
+
let h = height;
|
|
2614
|
+
if (sx < 0) {
|
|
2615
|
+
x -= sx;
|
|
2616
|
+
w += sx;
|
|
2617
|
+
sx = 0;
|
|
2618
|
+
}
|
|
2619
|
+
if (sy < 0) {
|
|
2620
|
+
y -= sy;
|
|
2621
|
+
h += sy;
|
|
2622
|
+
sy = 0;
|
|
2623
|
+
}
|
|
2624
|
+
w = Math.min(w, src.width - sx);
|
|
2625
|
+
h = Math.min(h, src.height - sy);
|
|
2658
2626
|
if (x < 0) {
|
|
2627
|
+
sx -= x;
|
|
2659
2628
|
w += x;
|
|
2660
2629
|
x = 0;
|
|
2661
2630
|
}
|
|
2662
2631
|
if (y < 0) {
|
|
2632
|
+
sy -= y;
|
|
2663
2633
|
h += y;
|
|
2664
2634
|
y = 0;
|
|
2665
2635
|
}
|
|
2666
2636
|
const actualW = Math.min(w, dst.width - x);
|
|
2667
2637
|
const actualH = Math.min(h, dst.height - y);
|
|
2668
2638
|
if (actualW <= 0 || actualH <= 0) return false;
|
|
2669
|
-
let baseColorWithGlobalAlpha = color;
|
|
2670
|
-
if (globalAlpha < 255) {
|
|
2671
|
-
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2672
|
-
if (a === 0 && !isOverwrite) return false;
|
|
2673
|
-
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2674
|
-
}
|
|
2675
2639
|
const dx = x - targetX | 0;
|
|
2676
2640
|
const dy = y - targetY | 0;
|
|
2677
2641
|
const dst32 = dst.data32;
|
|
2642
|
+
const src32 = src.data32;
|
|
2678
2643
|
const dw = dst.width;
|
|
2679
|
-
const
|
|
2680
|
-
const
|
|
2644
|
+
const sw = src.width;
|
|
2645
|
+
const mPitch = binaryMask.w;
|
|
2646
|
+
const maskData = binaryMask.data;
|
|
2681
2647
|
let dIdx = y * dw + x | 0;
|
|
2648
|
+
let sIdx = sy * sw + sx | 0;
|
|
2682
2649
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2683
2650
|
const dStride = dw - actualW | 0;
|
|
2651
|
+
const sStride = sw - actualW | 0;
|
|
2684
2652
|
const mStride = mPitch - actualW | 0;
|
|
2685
2653
|
const skipVal = invertMask ? 1 : 0;
|
|
2654
|
+
const isOpaque = globalAlpha === 255;
|
|
2655
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2686
2656
|
let didChange = false;
|
|
2687
2657
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2688
2658
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2689
2659
|
if (maskData[mIdx] === skipVal) {
|
|
2690
2660
|
dIdx++;
|
|
2661
|
+
sIdx++;
|
|
2662
|
+
mIdx++;
|
|
2663
|
+
continue;
|
|
2664
|
+
}
|
|
2665
|
+
const srcCol = src32[sIdx];
|
|
2666
|
+
const srcAlpha = srcCol >>> 24;
|
|
2667
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2668
|
+
dIdx++;
|
|
2669
|
+
sIdx++;
|
|
2691
2670
|
mIdx++;
|
|
2692
2671
|
continue;
|
|
2693
2672
|
}
|
|
2673
|
+
let finalCol = srcCol;
|
|
2674
|
+
if (!isOpaque) {
|
|
2675
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
2676
|
+
if (a === 0 && !isOverwrite) {
|
|
2677
|
+
dIdx++;
|
|
2678
|
+
sIdx++;
|
|
2679
|
+
mIdx++;
|
|
2680
|
+
continue;
|
|
2681
|
+
}
|
|
2682
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2683
|
+
}
|
|
2694
2684
|
const current = dst32[dIdx];
|
|
2695
|
-
const next = blendFn(
|
|
2685
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
2696
2686
|
if (current !== next) {
|
|
2697
2687
|
dst32[dIdx] = next;
|
|
2698
2688
|
didChange = true;
|
|
2699
2689
|
}
|
|
2700
2690
|
dIdx++;
|
|
2691
|
+
sIdx++;
|
|
2701
2692
|
mIdx++;
|
|
2702
2693
|
}
|
|
2703
2694
|
dIdx += dStride;
|
|
2695
|
+
sIdx += sStride;
|
|
2704
2696
|
mIdx += mStride;
|
|
2705
2697
|
}
|
|
2706
2698
|
return didChange;
|
|
2707
2699
|
}
|
|
2708
2700
|
|
|
2709
|
-
// src/
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
if (b.w <= 0 || b.h <= 0) return false;
|
|
2713
|
-
const unclippedStartX = Math.floor(centerX + brush.minOffset);
|
|
2714
|
-
const unclippedStartY = Math.floor(centerY + brush.minOffset);
|
|
2715
|
-
const ix = Math.max(unclippedStartX, b.x);
|
|
2716
|
-
const iy = Math.max(unclippedStartY, b.y);
|
|
2717
|
-
const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
|
|
2718
|
-
const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
|
|
2719
|
-
const iw = ir - ix;
|
|
2720
|
-
const ih = ib - iy;
|
|
2721
|
-
if (iw <= 0 || ih <= 0) return false;
|
|
2722
|
-
scratchOptions.x = ix;
|
|
2723
|
-
scratchOptions.y = iy;
|
|
2724
|
-
scratchOptions.w = iw;
|
|
2725
|
-
scratchOptions.h = ih;
|
|
2726
|
-
scratchOptions.mx = ix - unclippedStartX;
|
|
2727
|
-
scratchOptions.my = iy - unclippedStartY;
|
|
2728
|
-
scratchOptions.alpha = alpha;
|
|
2729
|
-
scratchOptions.blendFn = blendFn;
|
|
2730
|
-
if (brush.type === 0 /* ALPHA */) {
|
|
2731
|
-
return blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
|
|
2732
|
-
}
|
|
2733
|
-
if (brush.type === 1 /* BINARY */) {
|
|
2734
|
-
return blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
|
|
2735
|
-
}
|
|
2736
|
-
return false;
|
|
2737
|
-
}
|
|
2738
|
-
|
|
2739
|
-
// src/History/PixelMutator/mutatorBlendColorCircleMask.ts
|
|
2740
|
-
var defaults5 = {
|
|
2741
|
-
blendColorPixelDataCircleMask,
|
|
2742
|
-
getCircleBrushOrPencilBounds
|
|
2701
|
+
// src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts
|
|
2702
|
+
var defaults6 = {
|
|
2703
|
+
blendPixelDataBinaryMask
|
|
2743
2704
|
};
|
|
2744
|
-
var
|
|
2705
|
+
var mutatorBlendPixelDataBinaryMask = ((writer, deps = defaults6) => {
|
|
2745
2706
|
const {
|
|
2746
|
-
|
|
2747
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
|
|
2707
|
+
blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults6.blendPixelDataBinaryMask
|
|
2748
2708
|
} = deps;
|
|
2749
|
-
const boundsOut = {
|
|
2750
|
-
x: 0,
|
|
2751
|
-
y: 0,
|
|
2752
|
-
w: 0,
|
|
2753
|
-
h: 0
|
|
2754
|
-
};
|
|
2755
|
-
const blendColorPixelOptions = {
|
|
2756
|
-
alpha: 255,
|
|
2757
|
-
blendFn: sourceOverPerfect,
|
|
2758
|
-
x: 0,
|
|
2759
|
-
y: 0,
|
|
2760
|
-
w: 0,
|
|
2761
|
-
h: 0
|
|
2762
|
-
};
|
|
2763
2709
|
return {
|
|
2764
|
-
|
|
2765
|
-
const
|
|
2766
|
-
const
|
|
2767
|
-
const
|
|
2768
|
-
|
|
2710
|
+
blendPixelDataBinaryMask(src, mask, opts = {}) {
|
|
2711
|
+
const x = opts.x ?? 0;
|
|
2712
|
+
const y = opts.y ?? 0;
|
|
2713
|
+
const w = opts.w ?? src.width;
|
|
2714
|
+
const h = opts.h ?? src.height;
|
|
2715
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2716
|
+
return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
|
|
2769
2717
|
}
|
|
2770
2718
|
};
|
|
2771
2719
|
});
|
|
2772
2720
|
|
|
2773
|
-
// src/
|
|
2774
|
-
var
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2721
|
+
// src/PixelData/fillPixelDataFast.ts
|
|
2722
|
+
var SCRATCH_RECT = makeClippedRect();
|
|
2723
|
+
function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
|
|
2724
|
+
let x;
|
|
2725
|
+
let y;
|
|
2726
|
+
let w;
|
|
2727
|
+
let h;
|
|
2728
|
+
if (typeof _x === "object") {
|
|
2729
|
+
x = _x.x ?? 0;
|
|
2730
|
+
y = _x.y ?? 0;
|
|
2731
|
+
w = _x.w ?? dst.width;
|
|
2732
|
+
h = _x.h ?? dst.height;
|
|
2733
|
+
} else if (typeof _x === "number") {
|
|
2734
|
+
x = _x;
|
|
2735
|
+
y = _y;
|
|
2736
|
+
w = _w;
|
|
2737
|
+
h = _h;
|
|
2738
|
+
} else {
|
|
2739
|
+
x = 0;
|
|
2740
|
+
y = 0;
|
|
2741
|
+
w = dst.width;
|
|
2742
|
+
h = dst.height;
|
|
2743
|
+
}
|
|
2744
|
+
const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT);
|
|
2745
|
+
if (!clip.inBounds) return;
|
|
2779
2746
|
const {
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
});
|
|
2747
|
+
x: finalX,
|
|
2748
|
+
y: finalY,
|
|
2749
|
+
w: actualW,
|
|
2750
|
+
h: actualH
|
|
2751
|
+
} = clip;
|
|
2752
|
+
const dst32 = dst.data32;
|
|
2753
|
+
const dw = dst.width;
|
|
2754
|
+
if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
|
|
2755
|
+
dst32.fill(color);
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2759
|
+
const start = (finalY + iy) * dw + finalX;
|
|
2760
|
+
const end = start + actualW;
|
|
2761
|
+
dst32.fill(color, start, end);
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2798
2764
|
|
|
2799
|
-
// src/History/PixelMutator/
|
|
2765
|
+
// src/History/PixelMutator/mutatorClear.ts
|
|
2800
2766
|
var defaults7 = {
|
|
2801
|
-
|
|
2802
|
-
blendColorPixelDataBinaryMask,
|
|
2803
|
-
getCircleBrushOrPencilBounds,
|
|
2804
|
-
getCircleBrushOrPencilStrokeBounds
|
|
2767
|
+
fillPixelData: fillPixelDataFast
|
|
2805
2768
|
};
|
|
2806
|
-
var
|
|
2769
|
+
var mutatorClear = ((writer, deps = defaults7) => {
|
|
2807
2770
|
const {
|
|
2808
|
-
|
|
2809
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults7.blendColorPixelDataBinaryMask,
|
|
2810
|
-
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults7.getCircleBrushOrPencilStrokeBounds,
|
|
2811
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults7.getCircleBrushOrPencilBounds
|
|
2771
|
+
fillPixelData: fillPixelData2 = defaults7.fillPixelData
|
|
2812
2772
|
} = deps;
|
|
2813
|
-
const strokeBoundsOut = {
|
|
2814
|
-
x: 0,
|
|
2815
|
-
y: 0,
|
|
2816
|
-
w: 0,
|
|
2817
|
-
h: 0
|
|
2818
|
-
};
|
|
2819
|
-
const circlePencilBounds = {
|
|
2820
|
-
x: 0,
|
|
2821
|
-
y: 0,
|
|
2822
|
-
w: 0,
|
|
2823
|
-
h: 0
|
|
2824
|
-
};
|
|
2825
|
-
const blendColorPixelOptions = {
|
|
2826
|
-
alpha: 255,
|
|
2827
|
-
blendFn: sourceOverPerfect,
|
|
2828
|
-
x: 0,
|
|
2829
|
-
y: 0,
|
|
2830
|
-
w: 0,
|
|
2831
|
-
h: 0
|
|
2832
|
-
};
|
|
2833
|
-
const mask = {
|
|
2834
|
-
type: 1 /* BINARY */,
|
|
2835
|
-
data: null,
|
|
2836
|
-
w: 0,
|
|
2837
|
-
h: 0
|
|
2838
|
-
};
|
|
2839
2773
|
return {
|
|
2840
|
-
|
|
2841
|
-
const {
|
|
2842
|
-
x: bx,
|
|
2843
|
-
y: by,
|
|
2844
|
-
w: bw,
|
|
2845
|
-
h: bh
|
|
2846
|
-
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brush.size, strokeBoundsOut);
|
|
2847
|
-
if (bw <= 0 || bh <= 0) return;
|
|
2848
|
-
mask.data = new Uint8Array(bw * bh);
|
|
2849
|
-
mask.w = bw;
|
|
2850
|
-
mask.h = bh;
|
|
2851
|
-
const maskData = mask.data;
|
|
2774
|
+
clear(rect = {}) {
|
|
2852
2775
|
const target = writer.config.target;
|
|
2853
|
-
const
|
|
2854
|
-
const
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
w: cbw,
|
|
2860
|
-
h: cbh
|
|
2861
|
-
} = getCircleBrushOrPencilBounds2(px, py, brush.size, targetWidth, targetHeight, circlePencilBounds);
|
|
2862
|
-
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2863
|
-
const unclippedStartX = Math.floor(px + brush.minOffset);
|
|
2864
|
-
const unclippedStartY = Math.floor(py + brush.minOffset);
|
|
2865
|
-
const startX = Math.max(bx, unclippedStartX);
|
|
2866
|
-
const startY = Math.max(by, unclippedStartY);
|
|
2867
|
-
const endX = Math.min(bx + bw, unclippedStartX + brush.w);
|
|
2868
|
-
const endY = Math.min(by + bh, unclippedStartY + brush.h);
|
|
2869
|
-
for (let my = startY; my < endY; my++) {
|
|
2870
|
-
const brushY = my - unclippedStartY;
|
|
2871
|
-
const maskRowOffset = (my - by) * bw;
|
|
2872
|
-
const brushRowOffset = brushY * brush.w;
|
|
2873
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
2874
|
-
const brushX = mx - unclippedStartX;
|
|
2875
|
-
const brushAlpha = brush.data[brushRowOffset + brushX];
|
|
2876
|
-
if (brushAlpha > 0) {
|
|
2877
|
-
const maskIdx = maskRowOffset + (mx - bx);
|
|
2878
|
-
maskData[maskIdx] = brushAlpha;
|
|
2879
|
-
}
|
|
2880
|
-
}
|
|
2881
|
-
}
|
|
2882
|
-
});
|
|
2883
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
2884
|
-
blendColorPixelOptions.alpha = alpha;
|
|
2885
|
-
blendColorPixelOptions.x = bx;
|
|
2886
|
-
blendColorPixelOptions.y = by;
|
|
2887
|
-
blendColorPixelOptions.w = bw;
|
|
2888
|
-
blendColorPixelOptions.h = bh;
|
|
2889
|
-
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
2776
|
+
const x = rect.x ?? 0;
|
|
2777
|
+
const y = rect.y ?? 0;
|
|
2778
|
+
const w = rect.w ?? target.width;
|
|
2779
|
+
const h = rect.h ?? target.height;
|
|
2780
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2781
|
+
fillPixelData2(target, 0, x, y, w, h);
|
|
2890
2782
|
}
|
|
2891
2783
|
};
|
|
2892
2784
|
});
|
|
2893
2785
|
|
|
2894
|
-
// src/
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
return res;
|
|
2917
|
-
}
|
|
2918
|
-
|
|
2919
|
-
// src/PixelData/applyRectBrushToPixelData.ts
|
|
2920
|
-
function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2921
|
-
const targetWidth = target.width;
|
|
2922
|
-
const targetHeight = target.height;
|
|
2923
|
-
const b = bounds ?? getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight);
|
|
2924
|
-
if (b.w <= 0 || b.h <= 0) {
|
|
2925
|
-
return false;
|
|
2786
|
+
// src/PixelData/fillPixelData.ts
|
|
2787
|
+
var SCRATCH_RECT2 = makeClippedRect();
|
|
2788
|
+
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
2789
|
+
let x;
|
|
2790
|
+
let y;
|
|
2791
|
+
let w;
|
|
2792
|
+
let h;
|
|
2793
|
+
if (typeof _x === "object") {
|
|
2794
|
+
x = _x.x ?? 0;
|
|
2795
|
+
y = _x.y ?? 0;
|
|
2796
|
+
w = _x.w ?? dst.width;
|
|
2797
|
+
h = _x.h ?? dst.height;
|
|
2798
|
+
} else if (typeof _x === "number") {
|
|
2799
|
+
x = _x;
|
|
2800
|
+
y = _y;
|
|
2801
|
+
w = _w;
|
|
2802
|
+
h = _h;
|
|
2803
|
+
} else {
|
|
2804
|
+
x = 0;
|
|
2805
|
+
y = 0;
|
|
2806
|
+
w = dst.width;
|
|
2807
|
+
h = dst.height;
|
|
2926
2808
|
}
|
|
2927
|
-
const
|
|
2928
|
-
|
|
2929
|
-
const
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
const
|
|
2936
|
-
const
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
const dx = Math.abs(px - fCenterX + centerOffsetX) * invHalfW;
|
|
2947
|
-
const dist = dx > dy ? dx : dy;
|
|
2948
|
-
const strength = fallOff(dist);
|
|
2949
|
-
const maskVal = strength * 255 | 0;
|
|
2950
|
-
if (maskVal <= 0) continue;
|
|
2951
|
-
let weight = alpha;
|
|
2952
|
-
if (isOpaque) {
|
|
2953
|
-
weight = maskVal;
|
|
2954
|
-
} else if (maskVal !== 255) {
|
|
2955
|
-
weight = maskVal * alpha + 128 >> 8;
|
|
2956
|
-
}
|
|
2957
|
-
let finalCol = color;
|
|
2958
|
-
if (weight < 255) {
|
|
2959
|
-
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2960
|
-
if (a === 0 && !isOverwrite) continue;
|
|
2961
|
-
finalCol = (a << 24 | baseColor) >>> 0;
|
|
2962
|
-
}
|
|
2963
|
-
const current = data32[idx];
|
|
2964
|
-
const next = blendFn(finalCol, current);
|
|
2965
|
-
if (current !== next) {
|
|
2966
|
-
data32[idx] = next;
|
|
2967
|
-
didChange = true;
|
|
2809
|
+
const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT2);
|
|
2810
|
+
if (!clip.inBounds) return false;
|
|
2811
|
+
const {
|
|
2812
|
+
x: finalX,
|
|
2813
|
+
y: finalY,
|
|
2814
|
+
w: actualW,
|
|
2815
|
+
h: actualH
|
|
2816
|
+
} = clip;
|
|
2817
|
+
const dst32 = dst.data32;
|
|
2818
|
+
const dw = dst.width;
|
|
2819
|
+
let hasChanged = false;
|
|
2820
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2821
|
+
const rowOffset = (finalY + iy) * dw;
|
|
2822
|
+
const start = rowOffset + finalX;
|
|
2823
|
+
const end = start + actualW;
|
|
2824
|
+
for (let i = start; i < end; i++) {
|
|
2825
|
+
if (dst32[i] !== color) {
|
|
2826
|
+
dst32[i] = color;
|
|
2827
|
+
hasChanged = true;
|
|
2968
2828
|
}
|
|
2969
2829
|
}
|
|
2970
2830
|
}
|
|
2971
|
-
return
|
|
2831
|
+
return hasChanged;
|
|
2972
2832
|
}
|
|
2973
2833
|
|
|
2974
|
-
// src/History/PixelMutator/
|
|
2834
|
+
// src/History/PixelMutator/mutatorFill.ts
|
|
2975
2835
|
var defaults8 = {
|
|
2976
|
-
|
|
2977
|
-
getRectBrushOrPencilBounds
|
|
2836
|
+
fillPixelData
|
|
2978
2837
|
};
|
|
2979
|
-
var
|
|
2838
|
+
var mutatorFill = ((writer, deps = defaults8) => {
|
|
2980
2839
|
const {
|
|
2981
|
-
|
|
2982
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds
|
|
2840
|
+
fillPixelData: fillPixelData2 = defaults8.fillPixelData
|
|
2983
2841
|
} = deps;
|
|
2984
|
-
const boundsOut = {
|
|
2985
|
-
x: 0,
|
|
2986
|
-
y: 0,
|
|
2987
|
-
w: 0,
|
|
2988
|
-
h: 0
|
|
2989
|
-
};
|
|
2990
2842
|
return {
|
|
2991
|
-
|
|
2843
|
+
fill(color, x = 0, y = 0, w = writer.config.target.width, h = writer.config.target.height) {
|
|
2992
2844
|
const target = writer.config.target;
|
|
2993
|
-
const
|
|
2994
|
-
|
|
2995
|
-
return didChange(applyRectBrushToPixelData2(target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, b));
|
|
2845
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2846
|
+
return didChange(fillPixelData2(target, color, x, y, w, h));
|
|
2996
2847
|
}
|
|
2997
2848
|
};
|
|
2998
2849
|
});
|
|
2999
|
-
|
|
3000
|
-
// src/Rect/getRectBrushOrPencilStrokeBounds.ts
|
|
3001
|
-
function getRectBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushWidth, brushHeight, result) {
|
|
3002
|
-
const halfW = brushWidth / 2;
|
|
3003
|
-
const halfH = brushHeight / 2;
|
|
3004
|
-
const minX = Math.min(x0, x1) - halfW;
|
|
3005
|
-
const minY = Math.min(y0, y1) - halfH;
|
|
3006
|
-
const maxX = Math.max(x0, x1) + halfW;
|
|
3007
|
-
const maxY = Math.max(y0, y1) + halfH;
|
|
3008
|
-
result.x = Math.floor(minX);
|
|
3009
|
-
result.y = Math.floor(minY);
|
|
3010
|
-
result.w = Math.ceil(maxX - minX);
|
|
3011
|
-
result.h = Math.ceil(maxY - minY);
|
|
3012
|
-
return result;
|
|
3013
|
-
}
|
|
3014
|
-
|
|
3015
|
-
// src/History/PixelMutator/mutatorApplyRectBrushStroke.ts
|
|
3016
|
-
var defaults9 = {
|
|
3017
|
-
forEachLinePoint,
|
|
3018
|
-
blendColorPixelDataAlphaMask,
|
|
3019
|
-
getRectBrushOrPencilBounds,
|
|
3020
|
-
getRectBrushOrPencilStrokeBounds
|
|
3021
|
-
};
|
|
3022
|
-
var mutatorApplyRectBrushStroke = ((writer, deps = defaults9) => {
|
|
2850
|
+
var mutatorFillRect = ((writer, deps = defaults8) => {
|
|
3023
2851
|
const {
|
|
3024
|
-
|
|
3025
|
-
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults9.blendColorPixelDataAlphaMask,
|
|
3026
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
|
|
3027
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults9.getRectBrushOrPencilStrokeBounds
|
|
2852
|
+
fillPixelData: fillPixelData2 = defaults8.fillPixelData
|
|
3028
2853
|
} = deps;
|
|
3029
|
-
const strokeBoundsOut = {
|
|
3030
|
-
x: 0,
|
|
3031
|
-
y: 0,
|
|
3032
|
-
w: 0,
|
|
3033
|
-
h: 0
|
|
3034
|
-
};
|
|
3035
|
-
const rectBrushBounds = {
|
|
3036
|
-
x: 0,
|
|
3037
|
-
y: 0,
|
|
3038
|
-
w: 0,
|
|
3039
|
-
h: 0
|
|
3040
|
-
};
|
|
3041
|
-
const blendColorPixelOptions = {
|
|
3042
|
-
alpha: 255,
|
|
3043
|
-
blendFn: sourceOverPerfect,
|
|
3044
|
-
x: 0,
|
|
3045
|
-
y: 0,
|
|
3046
|
-
w: 0,
|
|
3047
|
-
h: 0
|
|
3048
|
-
};
|
|
3049
|
-
const mask = {
|
|
3050
|
-
type: 0 /* ALPHA */,
|
|
3051
|
-
data: null,
|
|
3052
|
-
w: 0,
|
|
3053
|
-
h: 0
|
|
3054
|
-
};
|
|
3055
2854
|
return {
|
|
3056
|
-
|
|
3057
|
-
const {
|
|
3058
|
-
x: bx,
|
|
3059
|
-
y: by,
|
|
3060
|
-
w: bw,
|
|
3061
|
-
h: bh
|
|
3062
|
-
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
3063
|
-
if (bw <= 0 || bh <= 0) return;
|
|
3064
|
-
mask.data = new Uint8Array(bw * bh);
|
|
3065
|
-
mask.w = bw;
|
|
3066
|
-
mask.h = bh;
|
|
3067
|
-
const maskData = mask.data;
|
|
3068
|
-
const halfW = brushWidth / 2;
|
|
3069
|
-
const halfH = brushHeight / 2;
|
|
3070
|
-
const invHalfW = 1 / halfW;
|
|
3071
|
-
const invHalfH = 1 / halfH;
|
|
3072
|
-
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
3073
|
-
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2855
|
+
fillRect(color, rect) {
|
|
3074
2856
|
const target = writer.config.target;
|
|
3075
|
-
const
|
|
3076
|
-
|
|
3077
|
-
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
3078
|
-
const {
|
|
3079
|
-
x: rbx,
|
|
3080
|
-
y: rby,
|
|
3081
|
-
w: rbw,
|
|
3082
|
-
h: rbh
|
|
3083
|
-
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectBrushBounds);
|
|
3084
|
-
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
3085
|
-
const startX = Math.max(bx, rbx);
|
|
3086
|
-
const startY = Math.max(by, rby);
|
|
3087
|
-
const endX = Math.min(bx + bw, rbx + rbw);
|
|
3088
|
-
const endY = Math.min(by + bh, rby + rbh);
|
|
3089
|
-
const fPx = Math.floor(px);
|
|
3090
|
-
const fPy = Math.floor(py);
|
|
3091
|
-
for (let my = startY; my < endY; my++) {
|
|
3092
|
-
const dy = Math.abs(my - fPy + centerOffsetY) * invHalfH;
|
|
3093
|
-
const maskRowOffset = (my - by) * bw;
|
|
3094
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
3095
|
-
const dx = Math.abs(mx - fPx + centerOffsetX) * invHalfW;
|
|
3096
|
-
const maskIdx = maskRowOffset + (mx - bx);
|
|
3097
|
-
const dist = dx > dy ? dx : dy;
|
|
3098
|
-
const strength = fallOff(dist);
|
|
3099
|
-
if (strength > 0) {
|
|
3100
|
-
const intensity = strength * 255 | 0;
|
|
3101
|
-
if (intensity > maskData[maskIdx]) {
|
|
3102
|
-
maskData[maskIdx] = intensity;
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
}
|
|
3106
|
-
}
|
|
3107
|
-
});
|
|
3108
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
3109
|
-
blendColorPixelOptions.alpha = alpha;
|
|
3110
|
-
blendColorPixelOptions.x = bx;
|
|
3111
|
-
blendColorPixelOptions.y = by;
|
|
3112
|
-
blendColorPixelOptions.w = bw;
|
|
3113
|
-
blendColorPixelOptions.h = bh;
|
|
3114
|
-
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2857
|
+
const didChange = writer.accumulator.storeRegionBeforeState(rect.x, rect.y, rect.w, rect.h);
|
|
2858
|
+
return didChange(fillPixelData2(target, color, rect.x, rect.y, rect.w, rect.h));
|
|
3115
2859
|
}
|
|
3116
2860
|
};
|
|
3117
2861
|
});
|
|
3118
2862
|
|
|
3119
|
-
// src/
|
|
3120
|
-
var
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
2863
|
+
// src/PixelData/fillPixelDataBinaryMask.ts
|
|
2864
|
+
var SCRATCH_RECT3 = makeClippedRect();
|
|
2865
|
+
function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
2866
|
+
if (alpha === 0) return false;
|
|
2867
|
+
const maskW = mask.w;
|
|
2868
|
+
const maskH = mask.h;
|
|
2869
|
+
const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height, SCRATCH_RECT3);
|
|
2870
|
+
if (!clip.inBounds) return false;
|
|
3126
2871
|
const {
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
2872
|
+
x: finalX,
|
|
2873
|
+
y: finalY,
|
|
2874
|
+
w: actualW,
|
|
2875
|
+
h: actualH
|
|
2876
|
+
} = clip;
|
|
2877
|
+
const maskData = mask.data;
|
|
2878
|
+
const dst32 = dst.data32;
|
|
2879
|
+
const dw = dst.width;
|
|
2880
|
+
let finalCol = color;
|
|
2881
|
+
if (alpha < 255) {
|
|
2882
|
+
const baseSrcAlpha = color >>> 24;
|
|
2883
|
+
const colorRGB = color & 16777215;
|
|
2884
|
+
const a = baseSrcAlpha * alpha + 128 >> 8;
|
|
2885
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
2886
|
+
}
|
|
2887
|
+
let hasChanged = false;
|
|
2888
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2889
|
+
const currentY = finalY + iy;
|
|
2890
|
+
const maskY = currentY - y;
|
|
2891
|
+
const maskOffset = maskY * maskW;
|
|
2892
|
+
const dstRowOffset = currentY * dw;
|
|
2893
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2894
|
+
const currentX = finalX + ix;
|
|
2895
|
+
const maskX = currentX - x;
|
|
2896
|
+
const maskIndex = maskOffset + maskX;
|
|
2897
|
+
if (maskData[maskIndex]) {
|
|
2898
|
+
const current = dst32[dstRowOffset + currentX];
|
|
2899
|
+
if (current !== finalCol) {
|
|
2900
|
+
dst32[dstRowOffset + currentX] = finalCol;
|
|
2901
|
+
hasChanged = true;
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
return hasChanged;
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
// src/History/PixelMutator/mutatorFillBinaryMask.ts
|
|
2910
|
+
var defaults9 = {
|
|
2911
|
+
fillPixelDataBinaryMask
|
|
3153
2912
|
};
|
|
3154
|
-
var
|
|
2913
|
+
var mutatorFillBinaryMask = ((writer, deps = defaults9) => {
|
|
3155
2914
|
const {
|
|
3156
|
-
|
|
3157
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults11.blendColorPixelDataBinaryMask,
|
|
3158
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults11.getRectBrushOrPencilBounds,
|
|
3159
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults11.getRectBrushOrPencilStrokeBounds
|
|
2915
|
+
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults9.fillPixelDataBinaryMask
|
|
3160
2916
|
} = deps;
|
|
3161
|
-
const strokeBoundsOut = {
|
|
3162
|
-
x: 0,
|
|
3163
|
-
y: 0,
|
|
3164
|
-
w: 0,
|
|
3165
|
-
h: 0
|
|
3166
|
-
};
|
|
3167
|
-
const rectPencilBounds = {
|
|
3168
|
-
x: 0,
|
|
3169
|
-
y: 0,
|
|
3170
|
-
w: 0,
|
|
3171
|
-
h: 0
|
|
3172
|
-
};
|
|
3173
|
-
const blendColorPixelOptions = {
|
|
3174
|
-
alpha: 255,
|
|
3175
|
-
blendFn: sourceOverPerfect,
|
|
3176
|
-
x: 0,
|
|
3177
|
-
y: 0,
|
|
3178
|
-
w: 0,
|
|
3179
|
-
h: 0
|
|
3180
|
-
};
|
|
3181
|
-
const mask = {
|
|
3182
|
-
type: 1 /* BINARY */,
|
|
3183
|
-
data: null,
|
|
3184
|
-
w: 0,
|
|
3185
|
-
h: 0
|
|
3186
|
-
};
|
|
3187
2917
|
return {
|
|
3188
|
-
|
|
3189
|
-
const
|
|
3190
|
-
|
|
3191
|
-
y: by,
|
|
3192
|
-
w: bw,
|
|
3193
|
-
h: bh
|
|
3194
|
-
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
3195
|
-
if (bw <= 0 || bh <= 0) return;
|
|
3196
|
-
mask.data = new Uint8Array(bw * bh);
|
|
3197
|
-
mask.w = bw;
|
|
3198
|
-
mask.h = bh;
|
|
3199
|
-
const maskData = mask.data;
|
|
3200
|
-
const halfW = brushWidth / 2;
|
|
3201
|
-
const halfH = brushHeight / 2;
|
|
3202
|
-
const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
3203
|
-
const target = writer.config.target;
|
|
3204
|
-
const targetWidth = target.width;
|
|
3205
|
-
const targetHeight = target.height;
|
|
3206
|
-
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
3207
|
-
const {
|
|
3208
|
-
x: rbx,
|
|
3209
|
-
y: rby,
|
|
3210
|
-
w: rbw,
|
|
3211
|
-
h: rbh
|
|
3212
|
-
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectPencilBounds);
|
|
3213
|
-
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
3214
|
-
const startX = Math.max(bx, rbx);
|
|
3215
|
-
const startY = Math.max(by, rby);
|
|
3216
|
-
const endX = Math.min(bx + bw, rbx + rbw);
|
|
3217
|
-
const endY = Math.min(by + bh, rby + rbh);
|
|
3218
|
-
const fPx = Math.floor(px);
|
|
3219
|
-
const fPy = Math.floor(py);
|
|
3220
|
-
for (let my = startY; my < endY; my++) {
|
|
3221
|
-
const dy = Math.abs(my - fPy + centerOffset);
|
|
3222
|
-
const maskRowOffset = (my - by) * bw;
|
|
3223
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
3224
|
-
const dx = Math.abs(mx - fPx + centerOffset);
|
|
3225
|
-
const maskIdx = maskRowOffset + (mx - bx);
|
|
3226
|
-
if (dx <= halfW && dy <= halfH) {
|
|
3227
|
-
maskData[maskIdx] = 1;
|
|
3228
|
-
}
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
});
|
|
3232
|
-
blendColorPixelOptions.blendFn = blendFn;
|
|
3233
|
-
blendColorPixelOptions.alpha = alpha;
|
|
3234
|
-
blendColorPixelOptions.x = bx;
|
|
3235
|
-
blendColorPixelOptions.y = by;
|
|
3236
|
-
blendColorPixelOptions.w = bw;
|
|
3237
|
-
blendColorPixelOptions.h = bh;
|
|
3238
|
-
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
2918
|
+
fillBinaryMask(color, mask, alpha = 255, x = 0, y = 0) {
|
|
2919
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
|
|
2920
|
+
return didChange(fillPixelDataBinaryMask2(writer.config.target, color, mask, alpha, x, y));
|
|
3239
2921
|
}
|
|
3240
2922
|
};
|
|
3241
2923
|
});
|
|
3242
2924
|
|
|
3243
|
-
// src/PixelData/
|
|
3244
|
-
|
|
2925
|
+
// src/PixelData/invertPixelData.ts
|
|
2926
|
+
var SCRATCH_RECT4 = makeClippedRect();
|
|
2927
|
+
function invertPixelData(pixelData, opts = {}) {
|
|
2928
|
+
const dst = pixelData;
|
|
3245
2929
|
const {
|
|
3246
2930
|
x: targetX = 0,
|
|
3247
2931
|
y: targetY = 0,
|
|
3248
|
-
w: width =
|
|
3249
|
-
h: height =
|
|
3250
|
-
|
|
3251
|
-
|
|
2932
|
+
w: width = pixelData.width,
|
|
2933
|
+
h: height = pixelData.height,
|
|
2934
|
+
mask,
|
|
2935
|
+
mx = 0,
|
|
2936
|
+
my = 0,
|
|
2937
|
+
invertMask = false
|
|
3252
2938
|
} = opts;
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
const
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
if (x < 0) {
|
|
3262
|
-
w += x;
|
|
3263
|
-
x = 0;
|
|
3264
|
-
}
|
|
3265
|
-
if (y < 0) {
|
|
3266
|
-
h += y;
|
|
3267
|
-
y = 0;
|
|
3268
|
-
}
|
|
3269
|
-
const actualW = Math.min(w, dst.width - x);
|
|
3270
|
-
const actualH = Math.min(h, dst.height - y);
|
|
3271
|
-
if (actualW <= 0 || actualH <= 0) return false;
|
|
3272
|
-
let finalSrcColor = color;
|
|
3273
|
-
if (globalAlpha < 255) {
|
|
3274
|
-
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
3275
|
-
if (a === 0 && !isOverwrite) return false;
|
|
3276
|
-
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
3277
|
-
}
|
|
2939
|
+
const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT4);
|
|
2940
|
+
if (!clip.inBounds) return false;
|
|
2941
|
+
const {
|
|
2942
|
+
x,
|
|
2943
|
+
y,
|
|
2944
|
+
w: actualW,
|
|
2945
|
+
h: actualH
|
|
2946
|
+
} = clip;
|
|
3278
2947
|
const dst32 = dst.data32;
|
|
3279
2948
|
const dw = dst.width;
|
|
3280
|
-
|
|
3281
|
-
const
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
2949
|
+
const mPitch = mask?.w ?? width;
|
|
2950
|
+
const dx = x - targetX;
|
|
2951
|
+
const dy = y - targetY;
|
|
2952
|
+
let dIdx = y * dw + x;
|
|
2953
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2954
|
+
const dStride = dw - actualW;
|
|
2955
|
+
const mStride = mPitch - actualW;
|
|
2956
|
+
if (mask) {
|
|
2957
|
+
const maskData = mask.data;
|
|
2958
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2959
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2960
|
+
const mVal = maskData[mIdx];
|
|
2961
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2962
|
+
if (isHit) {
|
|
2963
|
+
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
2964
|
+
}
|
|
2965
|
+
dIdx++;
|
|
2966
|
+
mIdx++;
|
|
3290
2967
|
}
|
|
3291
|
-
dIdx
|
|
2968
|
+
dIdx += dStride;
|
|
2969
|
+
mIdx += mStride;
|
|
2970
|
+
}
|
|
2971
|
+
} else {
|
|
2972
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2973
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2974
|
+
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
2975
|
+
dIdx++;
|
|
2976
|
+
}
|
|
2977
|
+
dIdx += dStride;
|
|
3292
2978
|
}
|
|
3293
|
-
dIdx += dStride;
|
|
3294
2979
|
}
|
|
3295
|
-
return
|
|
2980
|
+
return true;
|
|
3296
2981
|
}
|
|
3297
2982
|
|
|
3298
|
-
// src/History/PixelMutator/
|
|
3299
|
-
var
|
|
3300
|
-
|
|
2983
|
+
// src/History/PixelMutator/mutatorInvert.ts
|
|
2984
|
+
var defaults10 = {
|
|
2985
|
+
invertPixelData
|
|
3301
2986
|
};
|
|
3302
|
-
var
|
|
2987
|
+
var mutatorInvert = ((writer, deps = defaults10) => {
|
|
3303
2988
|
const {
|
|
3304
|
-
|
|
2989
|
+
invertPixelData: invertPixelData2 = defaults10.invertPixelData
|
|
3305
2990
|
} = deps;
|
|
3306
2991
|
return {
|
|
3307
|
-
|
|
2992
|
+
invert(opts = {}) {
|
|
3308
2993
|
const target = writer.config.target;
|
|
3309
2994
|
const {
|
|
3310
2995
|
x = 0,
|
|
@@ -3313,708 +2998,641 @@ var mutatorBlendColor = ((writer, deps = defaults12) => {
|
|
|
3313
2998
|
h = target.height
|
|
3314
2999
|
} = opts;
|
|
3315
3000
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3316
|
-
return didChange(
|
|
3001
|
+
return didChange(invertPixelData2(target, opts));
|
|
3317
3002
|
}
|
|
3318
3003
|
};
|
|
3319
3004
|
});
|
|
3320
3005
|
|
|
3321
|
-
// src/
|
|
3322
|
-
function
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3006
|
+
// src/History/PixelMutator.ts
|
|
3007
|
+
function makeFullPixelMutator(writer) {
|
|
3008
|
+
return {
|
|
3009
|
+
// @sort
|
|
3010
|
+
...mutatorBlendColor(writer),
|
|
3011
|
+
...mutatorBlendPixel(writer),
|
|
3012
|
+
...mutatorBlendPixelData(writer),
|
|
3013
|
+
...mutatorBlendPixelDataAlphaMask(writer),
|
|
3014
|
+
...mutatorBlendPixelDataBinaryMask(writer),
|
|
3015
|
+
...mutatorClear(writer),
|
|
3016
|
+
...mutatorFill(writer),
|
|
3017
|
+
...mutatorFillBinaryMask(writer),
|
|
3018
|
+
...mutatorFillRect(writer),
|
|
3019
|
+
...mutatorInvert(writer)
|
|
3020
|
+
};
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
// src/ImageData/resizeImageData.ts
|
|
3024
|
+
function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
3025
|
+
const result = new ImageData(newWidth, newHeight);
|
|
3026
|
+
const {
|
|
3027
|
+
width: oldW,
|
|
3028
|
+
height: oldH,
|
|
3029
|
+
data: oldData
|
|
3030
|
+
} = target;
|
|
3031
|
+
const newData = result.data;
|
|
3032
|
+
const x0 = Math.max(0, offsetX);
|
|
3033
|
+
const y0 = Math.max(0, offsetY);
|
|
3034
|
+
const x1 = Math.min(newWidth, offsetX + oldW);
|
|
3035
|
+
const y1 = Math.min(newHeight, offsetY + oldH);
|
|
3036
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
3037
|
+
return result;
|
|
3337
3038
|
}
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3039
|
+
const rowCount = y1 - y0;
|
|
3040
|
+
const rowLen = (x1 - x0) * 4;
|
|
3041
|
+
for (let row = 0; row < rowCount; row++) {
|
|
3042
|
+
const dstY = y0 + row;
|
|
3043
|
+
const srcY = dstY - offsetY;
|
|
3044
|
+
const srcX = x0 - offsetX;
|
|
3045
|
+
const dstStart = (dstY * newWidth + x0) * 4;
|
|
3046
|
+
const srcStart = (srcY * oldW + srcX) * 4;
|
|
3047
|
+
newData.set(oldData.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
3343
3048
|
}
|
|
3344
|
-
return
|
|
3049
|
+
return result;
|
|
3345
3050
|
}
|
|
3346
3051
|
|
|
3347
|
-
// src/
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
} = deps;
|
|
3355
|
-
return {
|
|
3356
|
-
blendPixel(x, y, color, alpha, blendFn) {
|
|
3357
|
-
const didChange = writer.accumulator.storePixelBeforeState(x, y);
|
|
3358
|
-
return didChange(blendPixel2(writer.config.target, x, y, color, alpha, blendFn));
|
|
3359
|
-
}
|
|
3052
|
+
// src/Rect/trimRectBounds.ts
|
|
3053
|
+
function trimRectBounds(x, y, w, h, targetWidth, targetHeight, out) {
|
|
3054
|
+
const res = out ?? {
|
|
3055
|
+
x: 0,
|
|
3056
|
+
y: 0,
|
|
3057
|
+
w: 0,
|
|
3058
|
+
h: 0
|
|
3360
3059
|
};
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
let sx = sourceX;
|
|
3379
|
-
let sy = sourceY;
|
|
3380
|
-
let w = width;
|
|
3381
|
-
let h = height;
|
|
3382
|
-
if (sx < 0) {
|
|
3383
|
-
x -= sx;
|
|
3384
|
-
w += sx;
|
|
3385
|
-
sx = 0;
|
|
3386
|
-
}
|
|
3387
|
-
if (sy < 0) {
|
|
3388
|
-
y -= sy;
|
|
3389
|
-
h += sy;
|
|
3390
|
-
sy = 0;
|
|
3391
|
-
}
|
|
3392
|
-
w = Math.min(w, src.width - sx);
|
|
3393
|
-
h = Math.min(h, src.height - sy);
|
|
3394
|
-
if (x < 0) {
|
|
3395
|
-
sx -= x;
|
|
3396
|
-
w += x;
|
|
3397
|
-
x = 0;
|
|
3398
|
-
}
|
|
3399
|
-
if (y < 0) {
|
|
3400
|
-
sy -= y;
|
|
3401
|
-
h += y;
|
|
3402
|
-
y = 0;
|
|
3403
|
-
}
|
|
3404
|
-
const actualW = Math.min(w, dst.width - x);
|
|
3405
|
-
const actualH = Math.min(h, dst.height - y);
|
|
3406
|
-
if (actualW <= 0 || actualH <= 0) return false;
|
|
3407
|
-
const dst32 = dst.data32;
|
|
3408
|
-
const src32 = src.data32;
|
|
3409
|
-
const dw = dst.width;
|
|
3410
|
-
const sw = src.width;
|
|
3411
|
-
let dIdx = y * dw + x | 0;
|
|
3412
|
-
let sIdx = sy * sw + sx | 0;
|
|
3413
|
-
const dStride = dw - actualW | 0;
|
|
3414
|
-
const sStride = sw - actualW | 0;
|
|
3415
|
-
const isOpaque = globalAlpha === 255;
|
|
3416
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
3417
|
-
let didChange = false;
|
|
3418
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3419
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3420
|
-
const srcCol = src32[sIdx];
|
|
3421
|
-
const srcAlpha = srcCol >>> 24;
|
|
3422
|
-
if (srcAlpha === 0 && !isOverwrite) {
|
|
3423
|
-
dIdx++;
|
|
3424
|
-
sIdx++;
|
|
3425
|
-
continue;
|
|
3426
|
-
}
|
|
3427
|
-
let finalCol = srcCol;
|
|
3428
|
-
if (!isOpaque) {
|
|
3429
|
-
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
3430
|
-
if (a === 0 && !isOverwrite) {
|
|
3431
|
-
dIdx++;
|
|
3432
|
-
sIdx++;
|
|
3433
|
-
continue;
|
|
3434
|
-
}
|
|
3435
|
-
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3436
|
-
}
|
|
3437
|
-
const current = dst32[dIdx];
|
|
3438
|
-
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3439
|
-
if (current !== next) {
|
|
3440
|
-
dst32[dIdx] = next;
|
|
3441
|
-
didChange = true;
|
|
3442
|
-
}
|
|
3443
|
-
dIdx++;
|
|
3444
|
-
sIdx++;
|
|
3445
|
-
}
|
|
3446
|
-
dIdx += dStride;
|
|
3447
|
-
sIdx += sStride;
|
|
3448
|
-
}
|
|
3449
|
-
return didChange;
|
|
3450
|
-
}
|
|
3451
|
-
|
|
3452
|
-
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
3453
|
-
var defaults14 = {
|
|
3454
|
-
blendPixelData
|
|
3455
|
-
};
|
|
3456
|
-
var mutatorBlendPixelData = ((writer, deps = defaults14) => {
|
|
3457
|
-
const {
|
|
3458
|
-
blendPixelData: blendPixelData2 = defaults14.blendPixelData
|
|
3459
|
-
} = deps;
|
|
3460
|
-
return {
|
|
3461
|
-
blendPixelData(src, opts = {}) {
|
|
3462
|
-
const {
|
|
3463
|
-
x = 0,
|
|
3464
|
-
y = 0,
|
|
3465
|
-
w = src.width,
|
|
3466
|
-
h = src.height
|
|
3467
|
-
} = opts;
|
|
3468
|
-
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3469
|
-
return didChange(blendPixelData2(writer.config.target, src, opts));
|
|
3470
|
-
}
|
|
3471
|
-
};
|
|
3472
|
-
});
|
|
3473
|
-
|
|
3474
|
-
// src/PixelData/blendPixelDataAlphaMask.ts
|
|
3475
|
-
function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
3476
|
-
const {
|
|
3477
|
-
x: targetX = 0,
|
|
3478
|
-
y: targetY = 0,
|
|
3479
|
-
sx: sourceX = 0,
|
|
3480
|
-
sy: sourceY = 0,
|
|
3481
|
-
w: width = src.width,
|
|
3482
|
-
h: height = src.height,
|
|
3483
|
-
alpha: globalAlpha = 255,
|
|
3484
|
-
blendFn = sourceOverPerfect,
|
|
3485
|
-
mx = 0,
|
|
3486
|
-
my = 0,
|
|
3487
|
-
invertMask = false
|
|
3488
|
-
} = opts;
|
|
3489
|
-
if (globalAlpha === 0) return false;
|
|
3490
|
-
let x = targetX;
|
|
3491
|
-
let y = targetY;
|
|
3492
|
-
let sx = sourceX;
|
|
3493
|
-
let sy = sourceY;
|
|
3494
|
-
let w = width;
|
|
3495
|
-
let h = height;
|
|
3496
|
-
if (sx < 0) {
|
|
3497
|
-
x -= sx;
|
|
3498
|
-
w += sx;
|
|
3499
|
-
sx = 0;
|
|
3500
|
-
}
|
|
3501
|
-
if (sy < 0) {
|
|
3502
|
-
y -= sy;
|
|
3503
|
-
h += sy;
|
|
3504
|
-
sy = 0;
|
|
3505
|
-
}
|
|
3506
|
-
w = Math.min(w, src.width - sx);
|
|
3507
|
-
h = Math.min(h, src.height - sy);
|
|
3508
|
-
if (x < 0) {
|
|
3509
|
-
sx -= x;
|
|
3510
|
-
w += x;
|
|
3511
|
-
x = 0;
|
|
3512
|
-
}
|
|
3513
|
-
if (y < 0) {
|
|
3514
|
-
sy -= y;
|
|
3515
|
-
h += y;
|
|
3516
|
-
y = 0;
|
|
3517
|
-
}
|
|
3518
|
-
const actualW = Math.min(w, dst.width - x);
|
|
3519
|
-
const actualH = Math.min(h, dst.height - y);
|
|
3520
|
-
if (actualW <= 0 || actualH <= 0) return false;
|
|
3521
|
-
const dw = dst.width;
|
|
3522
|
-
const sw = src.width;
|
|
3523
|
-
const mPitch = alphaMask.w;
|
|
3524
|
-
const maskData = alphaMask.data;
|
|
3525
|
-
const dx = x - targetX | 0;
|
|
3526
|
-
const dy = y - targetY | 0;
|
|
3527
|
-
const dst32 = dst.data32;
|
|
3528
|
-
const src32 = src.data32;
|
|
3529
|
-
let dIdx = y * dw + x | 0;
|
|
3530
|
-
let sIdx = sy * sw + sx | 0;
|
|
3531
|
-
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
3532
|
-
const dStride = dw - actualW | 0;
|
|
3533
|
-
const sStride = sw - actualW | 0;
|
|
3534
|
-
const mStride = mPitch - actualW | 0;
|
|
3535
|
-
const isOpaque = globalAlpha === 255;
|
|
3536
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
3537
|
-
let didChange = false;
|
|
3538
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3539
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3540
|
-
const mVal = maskData[mIdx];
|
|
3541
|
-
const effM = invertMask ? 255 - mVal : mVal;
|
|
3542
|
-
if (effM === 0) {
|
|
3543
|
-
dIdx++;
|
|
3544
|
-
sIdx++;
|
|
3545
|
-
mIdx++;
|
|
3546
|
-
continue;
|
|
3547
|
-
}
|
|
3548
|
-
const srcCol = src32[sIdx];
|
|
3549
|
-
const srcAlpha = srcCol >>> 24;
|
|
3550
|
-
if (srcAlpha === 0 && !isOverwrite) {
|
|
3551
|
-
dIdx++;
|
|
3552
|
-
sIdx++;
|
|
3553
|
-
mIdx++;
|
|
3554
|
-
continue;
|
|
3555
|
-
}
|
|
3556
|
-
let weight = globalAlpha;
|
|
3557
|
-
if (isOpaque) {
|
|
3558
|
-
weight = effM;
|
|
3559
|
-
} else if (effM !== 255) {
|
|
3560
|
-
weight = effM * globalAlpha + 128 >> 8;
|
|
3561
|
-
}
|
|
3562
|
-
if (weight === 0) {
|
|
3563
|
-
dIdx++;
|
|
3564
|
-
sIdx++;
|
|
3565
|
-
mIdx++;
|
|
3566
|
-
continue;
|
|
3567
|
-
}
|
|
3568
|
-
let finalCol = srcCol;
|
|
3569
|
-
if (weight < 255) {
|
|
3570
|
-
const a = srcAlpha * weight + 128 >> 8;
|
|
3571
|
-
if (a === 0 && !isOverwrite) {
|
|
3572
|
-
dIdx++;
|
|
3573
|
-
sIdx++;
|
|
3574
|
-
mIdx++;
|
|
3575
|
-
continue;
|
|
3576
|
-
}
|
|
3577
|
-
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3578
|
-
}
|
|
3579
|
-
const current = dst32[dIdx];
|
|
3580
|
-
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3581
|
-
if (current !== next) {
|
|
3582
|
-
dst32[dIdx] = next;
|
|
3583
|
-
didChange = true;
|
|
3584
|
-
}
|
|
3585
|
-
dIdx++;
|
|
3586
|
-
sIdx++;
|
|
3587
|
-
mIdx++;
|
|
3588
|
-
}
|
|
3589
|
-
dIdx += dStride;
|
|
3590
|
-
sIdx += sStride;
|
|
3591
|
-
mIdx += mStride;
|
|
3592
|
-
}
|
|
3593
|
-
return didChange;
|
|
3594
|
-
}
|
|
3595
|
-
|
|
3596
|
-
// src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts
|
|
3597
|
-
var defaults15 = {
|
|
3598
|
-
blendPixelDataAlphaMask
|
|
3599
|
-
};
|
|
3600
|
-
var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults15) => {
|
|
3601
|
-
const {
|
|
3602
|
-
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults15.blendPixelDataAlphaMask
|
|
3603
|
-
} = deps;
|
|
3604
|
-
return {
|
|
3605
|
-
blendPixelDataAlphaMask(src, mask, opts = {}) {
|
|
3606
|
-
const x = opts.x ?? 0;
|
|
3607
|
-
const y = opts.y ?? 0;
|
|
3608
|
-
const w = opts.w ?? src.width;
|
|
3609
|
-
const h = opts.h ?? src.height;
|
|
3610
|
-
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3611
|
-
return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
|
|
3612
|
-
}
|
|
3613
|
-
};
|
|
3614
|
-
});
|
|
3615
|
-
|
|
3616
|
-
// src/PixelData/blendPixelDataBinaryMask.ts
|
|
3617
|
-
function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
3618
|
-
const {
|
|
3619
|
-
x: targetX = 0,
|
|
3620
|
-
y: targetY = 0,
|
|
3621
|
-
sx: sourceX = 0,
|
|
3622
|
-
sy: sourceY = 0,
|
|
3623
|
-
w: width = src.width,
|
|
3624
|
-
h: height = src.height,
|
|
3625
|
-
alpha: globalAlpha = 255,
|
|
3626
|
-
blendFn = sourceOverPerfect,
|
|
3627
|
-
mx = 0,
|
|
3628
|
-
my = 0,
|
|
3629
|
-
invertMask = false
|
|
3630
|
-
} = opts;
|
|
3631
|
-
if (globalAlpha === 0) return false;
|
|
3632
|
-
let x = targetX;
|
|
3633
|
-
let y = targetY;
|
|
3634
|
-
let sx = sourceX;
|
|
3635
|
-
let sy = sourceY;
|
|
3636
|
-
let w = width;
|
|
3637
|
-
let h = height;
|
|
3638
|
-
if (sx < 0) {
|
|
3639
|
-
x -= sx;
|
|
3640
|
-
w += sx;
|
|
3641
|
-
sx = 0;
|
|
3642
|
-
}
|
|
3643
|
-
if (sy < 0) {
|
|
3644
|
-
y -= sy;
|
|
3645
|
-
h += sy;
|
|
3646
|
-
sy = 0;
|
|
3647
|
-
}
|
|
3648
|
-
w = Math.min(w, src.width - sx);
|
|
3649
|
-
h = Math.min(h, src.height - sy);
|
|
3650
|
-
if (x < 0) {
|
|
3651
|
-
sx -= x;
|
|
3652
|
-
w += x;
|
|
3653
|
-
x = 0;
|
|
3654
|
-
}
|
|
3655
|
-
if (y < 0) {
|
|
3656
|
-
sy -= y;
|
|
3657
|
-
h += y;
|
|
3658
|
-
y = 0;
|
|
3060
|
+
const left = Math.max(0, x);
|
|
3061
|
+
const top = Math.max(0, y);
|
|
3062
|
+
const right = Math.min(targetWidth, x + w);
|
|
3063
|
+
const bottom = Math.min(targetHeight, y + h);
|
|
3064
|
+
res.x = left;
|
|
3065
|
+
res.y = top;
|
|
3066
|
+
res.w = Math.max(0, right - left);
|
|
3067
|
+
res.h = Math.max(0, bottom - top);
|
|
3068
|
+
return res;
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
// src/Paint/PaintBuffer.ts
|
|
3072
|
+
var PaintBuffer = class {
|
|
3073
|
+
constructor(config, tilePool) {
|
|
3074
|
+
this.config = config;
|
|
3075
|
+
this.tilePool = tilePool;
|
|
3076
|
+
this.lookup = [];
|
|
3659
3077
|
}
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
let finalCol = srcCol;
|
|
3698
|
-
if (!isOpaque) {
|
|
3699
|
-
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
3700
|
-
if (a === 0 && !isOverwrite) {
|
|
3701
|
-
dIdx++;
|
|
3702
|
-
sIdx++;
|
|
3703
|
-
mIdx++;
|
|
3704
|
-
continue;
|
|
3705
|
-
}
|
|
3706
|
-
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3707
|
-
}
|
|
3708
|
-
const current = dst32[dIdx];
|
|
3709
|
-
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3710
|
-
if (current !== next) {
|
|
3711
|
-
dst32[dIdx] = next;
|
|
3712
|
-
didChange = true;
|
|
3078
|
+
lookup;
|
|
3079
|
+
scratchBounds = {
|
|
3080
|
+
x: 0,
|
|
3081
|
+
y: 0,
|
|
3082
|
+
w: 0,
|
|
3083
|
+
h: 0
|
|
3084
|
+
};
|
|
3085
|
+
eachTileInBounds(bounds, callback) {
|
|
3086
|
+
const {
|
|
3087
|
+
tileShift,
|
|
3088
|
+
targetColumns,
|
|
3089
|
+
targetRows,
|
|
3090
|
+
tileSize
|
|
3091
|
+
} = this.config;
|
|
3092
|
+
const x1 = Math.max(0, bounds.x >> tileShift);
|
|
3093
|
+
const y1 = Math.max(0, bounds.y >> tileShift);
|
|
3094
|
+
const x2 = Math.min(targetColumns - 1, bounds.x + bounds.w - 1 >> tileShift);
|
|
3095
|
+
const y2 = Math.min(targetRows - 1, bounds.y + bounds.h - 1 >> tileShift);
|
|
3096
|
+
if (x1 > x2 || y1 > y2) return;
|
|
3097
|
+
const lookup = this.lookup;
|
|
3098
|
+
const tilePool = this.tilePool;
|
|
3099
|
+
for (let ty = y1; ty <= y2; ty++) {
|
|
3100
|
+
const rowOffset = ty * targetColumns;
|
|
3101
|
+
const tileTop = ty << tileShift;
|
|
3102
|
+
for (let tx = x1; tx <= x2; tx++) {
|
|
3103
|
+
const id = rowOffset + tx;
|
|
3104
|
+
const tile = lookup[id] ?? (lookup[id] = tilePool.getTile(id, tx, ty));
|
|
3105
|
+
const tileLeft = tx << tileShift;
|
|
3106
|
+
const startX = bounds.x > tileLeft ? bounds.x : tileLeft;
|
|
3107
|
+
const startY = bounds.y > tileTop ? bounds.y : tileTop;
|
|
3108
|
+
const maskEndX = bounds.x + bounds.w;
|
|
3109
|
+
const tileEndX = tileLeft + tileSize;
|
|
3110
|
+
const endX = maskEndX < tileEndX ? maskEndX : tileEndX;
|
|
3111
|
+
const maskEndY = bounds.y + bounds.h;
|
|
3112
|
+
const tileEndY = tileTop + tileSize;
|
|
3113
|
+
const endY = maskEndY < tileEndY ? maskEndY : tileEndY;
|
|
3114
|
+
callback(tile, startX, startY, endX - startX, endY - startY);
|
|
3713
3115
|
}
|
|
3714
|
-
dIdx++;
|
|
3715
|
-
sIdx++;
|
|
3716
|
-
mIdx++;
|
|
3717
3116
|
}
|
|
3718
|
-
dIdx += dStride;
|
|
3719
|
-
sIdx += sStride;
|
|
3720
|
-
mIdx += mStride;
|
|
3721
3117
|
}
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3118
|
+
writePaintAlphaMaskStroke(color, brush, x0, y0, x1, y1) {
|
|
3119
|
+
const cA = color >>> 24;
|
|
3120
|
+
if (cA === 0) return false;
|
|
3121
|
+
const {
|
|
3122
|
+
tileShift,
|
|
3123
|
+
tileMask,
|
|
3124
|
+
target
|
|
3125
|
+
} = this.config;
|
|
3126
|
+
const {
|
|
3127
|
+
w: bW,
|
|
3128
|
+
h: bH,
|
|
3129
|
+
data: bD,
|
|
3130
|
+
centerOffsetX,
|
|
3131
|
+
centerOffsetY
|
|
3132
|
+
} = brush;
|
|
3133
|
+
const cRGB = color & 16777215;
|
|
3134
|
+
const scratch = this.scratchBounds;
|
|
3135
|
+
let changed = false;
|
|
3136
|
+
forEachLinePoint(x0, y0, x1, y1, (px, py) => {
|
|
3137
|
+
const topLeftX = Math.floor(px + centerOffsetX);
|
|
3138
|
+
const topLeftY = Math.floor(py + centerOffsetY);
|
|
3139
|
+
trimRectBounds(topLeftX, topLeftY, bW, bH, target.width, target.height, scratch);
|
|
3140
|
+
if (scratch.w <= 0 || scratch.h <= 0) return;
|
|
3141
|
+
this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
|
|
3142
|
+
const d32 = tile.data32;
|
|
3143
|
+
let tileChanged = false;
|
|
3144
|
+
for (let i = 0; i < bH_t; i++) {
|
|
3145
|
+
const canvasY = bY + i;
|
|
3146
|
+
const bOff = (canvasY - topLeftY) * bW;
|
|
3147
|
+
const tOff = (canvasY & tileMask) << tileShift;
|
|
3148
|
+
const dS = tOff + (bX & tileMask);
|
|
3149
|
+
for (let j = 0; j < bW_t; j++) {
|
|
3150
|
+
const canvasX = bX + j;
|
|
3151
|
+
const brushA = bD[bOff + (canvasX - topLeftX)];
|
|
3152
|
+
if (brushA === 0) continue;
|
|
3153
|
+
const t = cA * brushA + 128;
|
|
3154
|
+
const blendedA = t + (t >> 8) >> 8;
|
|
3155
|
+
const idx = dS + j;
|
|
3156
|
+
const cur = d32[idx];
|
|
3157
|
+
if (brushA > cur >>> 24) {
|
|
3158
|
+
const next = (cRGB | blendedA << 24) >>> 0;
|
|
3159
|
+
if (cur !== next) {
|
|
3160
|
+
d32[idx] = next;
|
|
3161
|
+
tileChanged = true;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
if (tileChanged) changed = true;
|
|
3167
|
+
});
|
|
3168
|
+
});
|
|
3169
|
+
return changed;
|
|
3767
3170
|
}
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3171
|
+
writePaintBinaryMaskStroke(color, brush, x0, y0, x1, y1) {
|
|
3172
|
+
const alphaIsZero = color >>> 24 === 0;
|
|
3173
|
+
if (alphaIsZero) return false;
|
|
3174
|
+
const {
|
|
3175
|
+
tileShift,
|
|
3176
|
+
tileMask,
|
|
3177
|
+
target
|
|
3178
|
+
} = this.config;
|
|
3179
|
+
const {
|
|
3180
|
+
w: bW,
|
|
3181
|
+
h: bH,
|
|
3182
|
+
data: bD,
|
|
3183
|
+
centerOffsetX,
|
|
3184
|
+
centerOffsetY
|
|
3185
|
+
} = brush;
|
|
3186
|
+
const scratch = this.scratchBounds;
|
|
3187
|
+
let changed = false;
|
|
3188
|
+
forEachLinePoint(x0, y0, x1, y1, (px, py) => {
|
|
3189
|
+
const topLeftX = Math.floor(px + centerOffsetX);
|
|
3190
|
+
const topLeftY = Math.floor(py + centerOffsetY);
|
|
3191
|
+
trimRectBounds(topLeftX, topLeftY, bW, bH, target.width, target.height, scratch);
|
|
3192
|
+
if (scratch.w <= 0 || scratch.h <= 0) return;
|
|
3193
|
+
this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
|
|
3194
|
+
const d32 = tile.data32;
|
|
3195
|
+
let tileChanged = false;
|
|
3196
|
+
for (let i = 0; i < bH_t; i++) {
|
|
3197
|
+
const canvasY = bY + i;
|
|
3198
|
+
const bOff = (canvasY - topLeftY) * bW;
|
|
3199
|
+
const tOff = (canvasY & tileMask) << tileShift;
|
|
3200
|
+
const dS = tOff + (bX & tileMask);
|
|
3201
|
+
for (let j = 0; j < bW_t; j++) {
|
|
3202
|
+
const canvasX = bX + j;
|
|
3203
|
+
if (bD[bOff + (canvasX - topLeftX)]) {
|
|
3204
|
+
const idx = dS + j;
|
|
3205
|
+
if (d32[idx] !== color) {
|
|
3206
|
+
d32[idx] = color;
|
|
3207
|
+
tileChanged = true;
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
if (tileChanged) changed = true;
|
|
3213
|
+
});
|
|
3214
|
+
});
|
|
3215
|
+
return changed;
|
|
3216
|
+
}
|
|
3217
|
+
writeRectStroke(color, brushWidth, brushHeight, x0, y0, x1, y1) {
|
|
3218
|
+
const alphaIsZero = color >>> 24 === 0;
|
|
3219
|
+
if (alphaIsZero) return false;
|
|
3220
|
+
const config = this.config;
|
|
3221
|
+
const tileShift = config.tileShift;
|
|
3222
|
+
const tileMask = config.tileMask;
|
|
3223
|
+
const target = config.target;
|
|
3224
|
+
const scratch = this.scratchBounds;
|
|
3225
|
+
const centerOffsetX = brushWidth - 1 >> 1;
|
|
3226
|
+
const centerOffsetY = brushHeight - 1 >> 1;
|
|
3227
|
+
let changed = false;
|
|
3228
|
+
forEachLinePoint(x0, y0, x1, y1, (px, py) => {
|
|
3229
|
+
const topLeftX = Math.floor(px + centerOffsetX);
|
|
3230
|
+
const topLeftY = Math.floor(py + centerOffsetY);
|
|
3231
|
+
trimRectBounds(topLeftX, topLeftY, brushWidth, brushHeight, target.width, target.height, scratch);
|
|
3232
|
+
if (scratch.w <= 0 || scratch.h <= 0) return;
|
|
3233
|
+
this.eachTileInBounds(scratch, (tile, bX, bY, bW_t, bH_t) => {
|
|
3234
|
+
const d32 = tile.data32;
|
|
3235
|
+
let tileChanged = false;
|
|
3236
|
+
for (let i = 0; i < bH_t; i++) {
|
|
3237
|
+
const canvasY = bY + i;
|
|
3238
|
+
const tOff = (canvasY & tileMask) << tileShift;
|
|
3239
|
+
const dS = tOff + (bX & tileMask);
|
|
3240
|
+
for (let j = 0; j < bW_t; j++) {
|
|
3241
|
+
const idx = dS + j;
|
|
3242
|
+
if (d32[idx] !== color) {
|
|
3243
|
+
d32[idx] = color;
|
|
3244
|
+
tileChanged = true;
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
if (tileChanged) {
|
|
3249
|
+
changed = true;
|
|
3250
|
+
}
|
|
3251
|
+
});
|
|
3252
|
+
});
|
|
3253
|
+
return changed;
|
|
3781
3254
|
}
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
const end = start + actualW;
|
|
3785
|
-
dst32.fill(color, start, end);
|
|
3255
|
+
clear() {
|
|
3256
|
+
this.tilePool.releaseTiles(this.lookup);
|
|
3786
3257
|
}
|
|
3787
|
-
}
|
|
3258
|
+
};
|
|
3788
3259
|
|
|
3789
|
-
// src/
|
|
3790
|
-
var
|
|
3791
|
-
|
|
3260
|
+
// src/PixelTile/PixelTile.ts
|
|
3261
|
+
var PixelTile = class {
|
|
3262
|
+
constructor(id, tx, ty, tileSize, tileArea) {
|
|
3263
|
+
this.id = id;
|
|
3264
|
+
this.tx = tx;
|
|
3265
|
+
this.ty = ty;
|
|
3266
|
+
this.width = this.height = tileSize;
|
|
3267
|
+
this.data32 = new Uint32Array(tileArea);
|
|
3268
|
+
const data8 = new Uint8ClampedArray(this.data32.buffer);
|
|
3269
|
+
this.imageData = new ImageData(data8, tileSize, tileSize);
|
|
3270
|
+
}
|
|
3271
|
+
data32;
|
|
3272
|
+
width;
|
|
3273
|
+
height;
|
|
3274
|
+
imageData;
|
|
3792
3275
|
};
|
|
3793
|
-
var mutatorClear = ((writer, deps = defaults17) => {
|
|
3794
|
-
const {
|
|
3795
|
-
fillPixelData: fillPixelData2 = defaults17.fillPixelData
|
|
3796
|
-
} = deps;
|
|
3797
|
-
return {
|
|
3798
|
-
clear(rect = {}) {
|
|
3799
|
-
const target = writer.config.target;
|
|
3800
|
-
const x = rect.x ?? 0;
|
|
3801
|
-
const y = rect.y ?? 0;
|
|
3802
|
-
const w = rect.w ?? target.width;
|
|
3803
|
-
const h = rect.h ?? target.height;
|
|
3804
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3805
|
-
fillPixelData2(target, 0, x, y, w, h);
|
|
3806
|
-
}
|
|
3807
|
-
};
|
|
3808
|
-
});
|
|
3809
3276
|
|
|
3810
|
-
// src/
|
|
3811
|
-
var
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
y = _x.y ?? 0;
|
|
3820
|
-
w = _x.w ?? dst.width;
|
|
3821
|
-
h = _x.h ?? dst.height;
|
|
3822
|
-
} else if (typeof _x === "number") {
|
|
3823
|
-
x = _x;
|
|
3824
|
-
y = _y;
|
|
3825
|
-
w = _w;
|
|
3826
|
-
h = _h;
|
|
3827
|
-
} else {
|
|
3828
|
-
x = 0;
|
|
3829
|
-
y = 0;
|
|
3830
|
-
w = dst.width;
|
|
3831
|
-
h = dst.height;
|
|
3277
|
+
// src/PixelTile/PixelTilePool.ts
|
|
3278
|
+
var PixelTilePool = class {
|
|
3279
|
+
pool;
|
|
3280
|
+
tileSize;
|
|
3281
|
+
tileArea;
|
|
3282
|
+
constructor(config) {
|
|
3283
|
+
this.pool = [];
|
|
3284
|
+
this.tileSize = config.tileSize;
|
|
3285
|
+
this.tileArea = config.tileArea;
|
|
3832
3286
|
}
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3287
|
+
getTile(id, tx, ty) {
|
|
3288
|
+
let tile = this.pool.pop();
|
|
3289
|
+
if (tile) {
|
|
3290
|
+
tile.id = id;
|
|
3291
|
+
tile.tx = tx;
|
|
3292
|
+
tile.ty = ty;
|
|
3293
|
+
tile.data32.fill(0);
|
|
3294
|
+
return tile;
|
|
3295
|
+
}
|
|
3296
|
+
return new PixelTile(id, tx, ty, this.tileSize, this.tileArea);
|
|
3297
|
+
}
|
|
3298
|
+
releaseTile(tile) {
|
|
3299
|
+
this.pool.push(tile);
|
|
3300
|
+
}
|
|
3301
|
+
releaseTiles(tiles) {
|
|
3302
|
+
let length = tiles.length;
|
|
3303
|
+
for (let i = 0; i < length; i++) {
|
|
3304
|
+
let tile = tiles[i];
|
|
3305
|
+
if (tile) {
|
|
3306
|
+
this.pool.push(tile);
|
|
3852
3307
|
}
|
|
3853
3308
|
}
|
|
3309
|
+
tiles.length = 0;
|
|
3854
3310
|
}
|
|
3855
|
-
return hasChanged;
|
|
3856
|
-
}
|
|
3857
|
-
|
|
3858
|
-
// src/History/PixelMutator/mutatorFill.ts
|
|
3859
|
-
var defaults18 = {
|
|
3860
|
-
fillPixelData
|
|
3861
3311
|
};
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3312
|
+
|
|
3313
|
+
// src/History/PixelWriter.ts
|
|
3314
|
+
var PixelWriter = class {
|
|
3315
|
+
historyManager;
|
|
3316
|
+
accumulator;
|
|
3317
|
+
historyActionFactory;
|
|
3318
|
+
config;
|
|
3319
|
+
pixelTilePool;
|
|
3320
|
+
paintBuffer;
|
|
3321
|
+
mutator;
|
|
3322
|
+
blendPixelDataOpts = {
|
|
3323
|
+
alpha: 255,
|
|
3324
|
+
blendFn: sourceOverPerfect,
|
|
3325
|
+
x: 0,
|
|
3326
|
+
y: 0,
|
|
3327
|
+
w: 0,
|
|
3328
|
+
h: 0
|
|
3872
3329
|
};
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3330
|
+
_inProgress = false;
|
|
3331
|
+
constructor(target, mutatorFactory, {
|
|
3332
|
+
tileSize = 256,
|
|
3333
|
+
maxHistorySteps = 50,
|
|
3334
|
+
historyManager = new HistoryManager(maxHistorySteps),
|
|
3335
|
+
historyActionFactory = makeHistoryAction,
|
|
3336
|
+
pixelTilePool,
|
|
3337
|
+
accumulator
|
|
3338
|
+
} = {}) {
|
|
3339
|
+
this.config = new PixelEngineConfig(tileSize, target);
|
|
3340
|
+
this.historyManager = historyManager;
|
|
3341
|
+
this.pixelTilePool = pixelTilePool ?? new PixelTilePool(this.config);
|
|
3342
|
+
this.accumulator = accumulator ?? new PixelAccumulator(this.config, this.pixelTilePool);
|
|
3343
|
+
this.historyActionFactory = historyActionFactory;
|
|
3344
|
+
this.mutator = mutatorFactory(this);
|
|
3345
|
+
this.paintBuffer = new PaintBuffer(this.config, this.pixelTilePool);
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* Executes `transaction` and commits the resulting pixel changes as a single
|
|
3349
|
+
* undoable history action.
|
|
3350
|
+
*
|
|
3351
|
+
* - If `transaction` throws, all accumulated changes are rolled back and the error
|
|
3352
|
+
* is re-thrown. No action is committed.
|
|
3353
|
+
* - If `transaction` completes without modifying any pixels, no action is committed.
|
|
3354
|
+
* - `withHistory` is not re-entrant. Calling it again from inside `transaction` will
|
|
3355
|
+
* throw immediately to prevent silent data loss from a nested extractPatch.
|
|
3356
|
+
*
|
|
3357
|
+
* @param transaction Callback to be executed inside the transaction.
|
|
3358
|
+
* @param after Called after both undo and redo — use for generic change notifications.
|
|
3359
|
+
* @param afterUndo Called after undo only — use for dimension or state changes specific to undo.
|
|
3360
|
+
* @param afterRedo Called after redo only.
|
|
3361
|
+
*/
|
|
3362
|
+
withHistory(transaction, after, afterUndo, afterRedo) {
|
|
3363
|
+
if (this._inProgress) {
|
|
3364
|
+
throw new Error("withHistory is not re-entrant \u2014 commit or rollback the current operation first");
|
|
3883
3365
|
}
|
|
3884
|
-
|
|
3885
|
-
|
|
3366
|
+
this._inProgress = true;
|
|
3367
|
+
try {
|
|
3368
|
+
transaction(this.mutator);
|
|
3369
|
+
} catch (e) {
|
|
3370
|
+
this.accumulator.rollbackAfterError();
|
|
3371
|
+
throw e;
|
|
3372
|
+
} finally {
|
|
3373
|
+
this._inProgress = false;
|
|
3374
|
+
}
|
|
3375
|
+
if (this.accumulator.beforeTiles.length === 0) return;
|
|
3376
|
+
const patch = this.accumulator.extractPatch();
|
|
3377
|
+
const action = this.historyActionFactory(this, patch, after, afterUndo, afterRedo);
|
|
3378
|
+
this.historyManager.commit(action);
|
|
3379
|
+
}
|
|
3380
|
+
resize(newWidth, newHeight, offsetX = 0, offsetY = 0, after, afterUndo, afterRedo, resizeImageDataFn = resizeImageData) {
|
|
3381
|
+
if (this._inProgress) {
|
|
3382
|
+
throw new Error("Cannot resize inside a withHistory callback");
|
|
3383
|
+
}
|
|
3384
|
+
if (this.accumulator.beforeTiles.length > 0) {
|
|
3385
|
+
throw new Error("Cannot resize with an open accumulator \u2014 commit or rollback first");
|
|
3386
|
+
}
|
|
3387
|
+
const config = this.config;
|
|
3388
|
+
const target = config.target;
|
|
3389
|
+
const beforeImageData = target.imageData;
|
|
3390
|
+
const afterImageData = resizeImageDataFn(beforeImageData, newWidth, newHeight, offsetX, offsetY);
|
|
3391
|
+
target.set(afterImageData);
|
|
3392
|
+
this.historyManager.commit({
|
|
3393
|
+
undo: () => {
|
|
3394
|
+
target.set(beforeImageData);
|
|
3395
|
+
afterUndo?.(beforeImageData);
|
|
3396
|
+
after?.(beforeImageData);
|
|
3397
|
+
},
|
|
3398
|
+
redo: () => {
|
|
3399
|
+
target.set(afterImageData);
|
|
3400
|
+
afterRedo?.(afterImageData);
|
|
3401
|
+
after?.(afterImageData);
|
|
3402
|
+
}
|
|
3403
|
+
});
|
|
3404
|
+
}
|
|
3405
|
+
commitPaintBuffer(alpha = 255, blendFn = sourceOverPerfect, blendPixelDataFn = blendPixelData) {
|
|
3406
|
+
const paintBuffer = this.paintBuffer;
|
|
3407
|
+
const tileShift = paintBuffer.config.tileShift;
|
|
3408
|
+
const lookup = paintBuffer.lookup;
|
|
3409
|
+
const opts = this.blendPixelDataOpts;
|
|
3410
|
+
opts.alpha = alpha;
|
|
3411
|
+
opts.blendFn = blendFn;
|
|
3412
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
3413
|
+
const tile = lookup[i];
|
|
3414
|
+
if (tile) {
|
|
3415
|
+
const didChange = this.accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty);
|
|
3416
|
+
const dx = tile.tx << tileShift;
|
|
3417
|
+
const dy = tile.ty << tileShift;
|
|
3418
|
+
opts.x = dx;
|
|
3419
|
+
opts.y = dy;
|
|
3420
|
+
opts.w = tile.width;
|
|
3421
|
+
opts.h = tile.height;
|
|
3422
|
+
didChange(blendPixelDataFn(this.config.target, tile, opts));
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
paintBuffer.clear();
|
|
3426
|
+
}
|
|
3427
|
+
};
|
|
3886
3428
|
|
|
3887
|
-
// src/PixelData/
|
|
3888
|
-
|
|
3889
|
-
function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
3890
|
-
if (alpha === 0) return false;
|
|
3891
|
-
const maskW = mask.w;
|
|
3892
|
-
const maskH = mask.h;
|
|
3893
|
-
const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height, SCRATCH_RECT3);
|
|
3894
|
-
if (!clip.inBounds) return false;
|
|
3429
|
+
// src/PixelData/applyAlphaMaskToPixelData.ts
|
|
3430
|
+
function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
3895
3431
|
const {
|
|
3896
|
-
x:
|
|
3897
|
-
y:
|
|
3898
|
-
w:
|
|
3899
|
-
h:
|
|
3900
|
-
|
|
3901
|
-
|
|
3432
|
+
x: targetX = 0,
|
|
3433
|
+
y: targetY = 0,
|
|
3434
|
+
w: width = dst.width,
|
|
3435
|
+
h: height = dst.height,
|
|
3436
|
+
alpha: globalAlpha = 255,
|
|
3437
|
+
mx = 0,
|
|
3438
|
+
my = 0,
|
|
3439
|
+
invertMask = false
|
|
3440
|
+
} = opts;
|
|
3441
|
+
if (globalAlpha === 0) return false;
|
|
3442
|
+
let x = targetX;
|
|
3443
|
+
let y = targetY;
|
|
3444
|
+
let w = width;
|
|
3445
|
+
let h = height;
|
|
3446
|
+
if (x < 0) {
|
|
3447
|
+
w += x;
|
|
3448
|
+
x = 0;
|
|
3449
|
+
}
|
|
3450
|
+
if (y < 0) {
|
|
3451
|
+
h += y;
|
|
3452
|
+
y = 0;
|
|
3453
|
+
}
|
|
3454
|
+
w = Math.min(w, dst.width - x);
|
|
3455
|
+
h = Math.min(h, dst.height - y);
|
|
3456
|
+
if (w <= 0) return false;
|
|
3457
|
+
if (h <= 0) return false;
|
|
3458
|
+
const mPitch = mask.w;
|
|
3459
|
+
if (mPitch <= 0) return false;
|
|
3460
|
+
const startX = mx + (x - targetX);
|
|
3461
|
+
const startY = my + (y - targetY);
|
|
3462
|
+
const sX0 = Math.max(0, startX);
|
|
3463
|
+
const sY0 = Math.max(0, startY);
|
|
3464
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
3465
|
+
const sY1 = Math.min(mask.h, startY + h);
|
|
3466
|
+
const finalW = sX1 - sX0;
|
|
3467
|
+
const finalH = sY1 - sY0;
|
|
3468
|
+
if (finalW <= 0) return false;
|
|
3469
|
+
if (finalH <= 0) return false;
|
|
3470
|
+
const xShift = sX0 - startX;
|
|
3471
|
+
const yShift = sY0 - startY;
|
|
3902
3472
|
const dst32 = dst.data32;
|
|
3903
3473
|
const dw = dst.width;
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3474
|
+
const dStride = dw - finalW;
|
|
3475
|
+
const mStride = mPitch - finalW;
|
|
3476
|
+
const maskData = mask.data;
|
|
3477
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
3478
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
3479
|
+
let didChange = false;
|
|
3480
|
+
for (let iy = 0; iy < h; iy++) {
|
|
3481
|
+
for (let ix = 0; ix < w; ix++) {
|
|
3482
|
+
const mVal = maskData[mIdx];
|
|
3483
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
3484
|
+
let weight = 0;
|
|
3485
|
+
if (effectiveM === 0) {
|
|
3486
|
+
weight = 0;
|
|
3487
|
+
} else if (effectiveM === 255) {
|
|
3488
|
+
weight = globalAlpha;
|
|
3489
|
+
} else if (globalAlpha === 255) {
|
|
3490
|
+
weight = effectiveM;
|
|
3491
|
+
} else {
|
|
3492
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
3493
|
+
}
|
|
3494
|
+
if (weight === 0) {
|
|
3495
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
3496
|
+
didChange = true;
|
|
3497
|
+
} else if (weight !== 255) {
|
|
3498
|
+
const d = dst32[dIdx];
|
|
3499
|
+
const da = d >>> 24;
|
|
3500
|
+
if (da !== 0) {
|
|
3501
|
+
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
3502
|
+
const current = dst32[dIdx];
|
|
3503
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
3504
|
+
if (current !== next) {
|
|
3505
|
+
dst32[dIdx] = next;
|
|
3506
|
+
didChange = true;
|
|
3507
|
+
}
|
|
3926
3508
|
}
|
|
3927
3509
|
}
|
|
3510
|
+
dIdx++;
|
|
3511
|
+
mIdx++;
|
|
3928
3512
|
}
|
|
3513
|
+
dIdx += dStride;
|
|
3514
|
+
mIdx += mStride;
|
|
3929
3515
|
}
|
|
3930
|
-
return
|
|
3516
|
+
return didChange;
|
|
3931
3517
|
}
|
|
3932
3518
|
|
|
3933
|
-
// src/History/PixelMutator/
|
|
3934
|
-
var
|
|
3935
|
-
|
|
3519
|
+
// src/History/PixelMutator/mutatorApplyAlphaMask.ts
|
|
3520
|
+
var defaults11 = {
|
|
3521
|
+
applyAlphaMaskToPixelData
|
|
3936
3522
|
};
|
|
3937
|
-
var
|
|
3523
|
+
var mutatorApplyAlphaMask = ((writer, deps = defaults11) => {
|
|
3938
3524
|
const {
|
|
3939
|
-
|
|
3525
|
+
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults11.applyAlphaMaskToPixelData
|
|
3940
3526
|
} = deps;
|
|
3941
3527
|
return {
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3528
|
+
applyAlphaMask(mask, opts = {}) {
|
|
3529
|
+
let target = writer.config.target;
|
|
3530
|
+
const {
|
|
3531
|
+
x = 0,
|
|
3532
|
+
y = 0,
|
|
3533
|
+
w = target.width,
|
|
3534
|
+
h = target.height
|
|
3535
|
+
} = opts;
|
|
3536
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3537
|
+
return didChange(applyAlphaMaskToPixelData2(target, mask, opts));
|
|
3945
3538
|
}
|
|
3946
3539
|
};
|
|
3947
3540
|
});
|
|
3948
3541
|
|
|
3949
|
-
// src/PixelData/
|
|
3950
|
-
|
|
3951
|
-
function invertPixelData(pixelData, opts = {}) {
|
|
3952
|
-
const dst = pixelData;
|
|
3542
|
+
// src/PixelData/applyBinaryMaskToPixelData.ts
|
|
3543
|
+
function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
3953
3544
|
const {
|
|
3954
3545
|
x: targetX = 0,
|
|
3955
3546
|
y: targetY = 0,
|
|
3956
|
-
w: width =
|
|
3957
|
-
h: height =
|
|
3958
|
-
|
|
3547
|
+
w: width = dst.width,
|
|
3548
|
+
h: height = dst.height,
|
|
3549
|
+
alpha: globalAlpha = 255,
|
|
3959
3550
|
mx = 0,
|
|
3960
3551
|
my = 0,
|
|
3961
3552
|
invertMask = false
|
|
3962
3553
|
} = opts;
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3554
|
+
if (globalAlpha === 0) return false;
|
|
3555
|
+
let x = targetX;
|
|
3556
|
+
let y = targetY;
|
|
3557
|
+
let w = width;
|
|
3558
|
+
let h = height;
|
|
3559
|
+
if (x < 0) {
|
|
3560
|
+
w += x;
|
|
3561
|
+
x = 0;
|
|
3562
|
+
}
|
|
3563
|
+
if (y < 0) {
|
|
3564
|
+
h += y;
|
|
3565
|
+
y = 0;
|
|
3566
|
+
}
|
|
3567
|
+
w = Math.min(w, dst.width - x);
|
|
3568
|
+
h = Math.min(h, dst.height - y);
|
|
3569
|
+
if (w <= 0 || h <= 0) return false;
|
|
3570
|
+
const mPitch = mask.w;
|
|
3571
|
+
if (mPitch <= 0) return false;
|
|
3572
|
+
const startX = mx + (x - targetX);
|
|
3573
|
+
const startY = my + (y - targetY);
|
|
3574
|
+
const sX0 = Math.max(0, startX);
|
|
3575
|
+
const sY0 = Math.max(0, startY);
|
|
3576
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
3577
|
+
const sY1 = Math.min(mask.h, startY + h);
|
|
3578
|
+
const finalW = sX1 - sX0;
|
|
3579
|
+
const finalH = sY1 - sY0;
|
|
3580
|
+
if (finalW <= 0 || finalH <= 0) {
|
|
3581
|
+
return false;
|
|
3582
|
+
}
|
|
3583
|
+
const xShift = sX0 - startX;
|
|
3584
|
+
const yShift = sY0 - startY;
|
|
3971
3585
|
const dst32 = dst.data32;
|
|
3972
3586
|
const dw = dst.width;
|
|
3973
|
-
const
|
|
3974
|
-
const
|
|
3975
|
-
const
|
|
3976
|
-
let dIdx = y * dw + x;
|
|
3977
|
-
let mIdx =
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
const
|
|
3985
|
-
const
|
|
3986
|
-
if (
|
|
3987
|
-
dst32[dIdx] =
|
|
3587
|
+
const dStride = dw - finalW;
|
|
3588
|
+
const mStride = mPitch - finalW;
|
|
3589
|
+
const maskData = mask.data;
|
|
3590
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
3591
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
3592
|
+
let didChange = false;
|
|
3593
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
3594
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
3595
|
+
const mVal = maskData[mIdx];
|
|
3596
|
+
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
3597
|
+
if (isMaskedOut) {
|
|
3598
|
+
const current = dst32[dIdx];
|
|
3599
|
+
const next = (current & 16777215) >>> 0;
|
|
3600
|
+
if (current !== next) {
|
|
3601
|
+
dst32[dIdx] = next;
|
|
3602
|
+
didChange = true;
|
|
3603
|
+
}
|
|
3604
|
+
} else if (globalAlpha !== 255) {
|
|
3605
|
+
const d = dst32[dIdx];
|
|
3606
|
+
const da = d >>> 24;
|
|
3607
|
+
if (da !== 0) {
|
|
3608
|
+
const finalAlpha = da === 255 ? globalAlpha : da * globalAlpha + 128 >> 8;
|
|
3609
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
3610
|
+
if (d !== next) {
|
|
3611
|
+
dst32[dIdx] = next;
|
|
3612
|
+
didChange = true;
|
|
3613
|
+
}
|
|
3988
3614
|
}
|
|
3989
|
-
dIdx++;
|
|
3990
|
-
mIdx++;
|
|
3991
|
-
}
|
|
3992
|
-
dIdx += dStride;
|
|
3993
|
-
mIdx += mStride;
|
|
3994
|
-
}
|
|
3995
|
-
} else {
|
|
3996
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3997
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3998
|
-
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
3999
|
-
dIdx++;
|
|
4000
3615
|
}
|
|
4001
|
-
dIdx
|
|
3616
|
+
dIdx++;
|
|
3617
|
+
mIdx++;
|
|
4002
3618
|
}
|
|
3619
|
+
dIdx += dStride;
|
|
3620
|
+
mIdx += mStride;
|
|
4003
3621
|
}
|
|
4004
|
-
return
|
|
3622
|
+
return didChange;
|
|
4005
3623
|
}
|
|
4006
3624
|
|
|
4007
|
-
// src/History/PixelMutator/
|
|
4008
|
-
var
|
|
4009
|
-
|
|
3625
|
+
// src/History/PixelMutator/mutatorApplyBinaryMask.ts
|
|
3626
|
+
var defaults12 = {
|
|
3627
|
+
applyBinaryMaskToPixelData
|
|
4010
3628
|
};
|
|
4011
|
-
var
|
|
3629
|
+
var mutatorApplyBinaryMask = ((writer, deps = defaults12) => {
|
|
4012
3630
|
const {
|
|
4013
|
-
|
|
3631
|
+
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults12.applyBinaryMaskToPixelData
|
|
4014
3632
|
} = deps;
|
|
4015
3633
|
return {
|
|
4016
|
-
|
|
4017
|
-
|
|
3634
|
+
applyBinaryMask(mask, opts = {}) {
|
|
3635
|
+
let target = writer.config.target;
|
|
4018
3636
|
const {
|
|
4019
3637
|
x = 0,
|
|
4020
3638
|
y = 0,
|
|
@@ -4022,125 +3640,200 @@ var mutatorInvert = ((writer, deps = defaults20) => {
|
|
|
4022
3640
|
h = target.height
|
|
4023
3641
|
} = opts;
|
|
4024
3642
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
4025
|
-
return didChange(
|
|
3643
|
+
return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
|
|
4026
3644
|
}
|
|
4027
3645
|
};
|
|
4028
3646
|
});
|
|
4029
3647
|
|
|
4030
|
-
// src/
|
|
4031
|
-
function
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
...mutatorFillRect(writer),
|
|
4053
|
-
...mutatorInvert(writer)
|
|
4054
|
-
};
|
|
4055
|
-
}
|
|
4056
|
-
|
|
4057
|
-
// src/PixelTile/PixelTile.ts
|
|
4058
|
-
var PixelTile = class {
|
|
4059
|
-
constructor(id, tx, ty, tileSize, tileArea) {
|
|
4060
|
-
this.id = id;
|
|
4061
|
-
this.tx = tx;
|
|
4062
|
-
this.ty = ty;
|
|
4063
|
-
this.width = this.height = tileSize;
|
|
4064
|
-
this.data32 = new Uint32Array(tileArea);
|
|
4065
|
-
const data8 = new Uint8ClampedArray(this.data32.buffer);
|
|
4066
|
-
this.imageData = new ImageData(data8, tileSize, tileSize);
|
|
3648
|
+
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
3649
|
+
function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
3650
|
+
const targetX = opts.x ?? 0;
|
|
3651
|
+
const targetY = opts.y ?? 0;
|
|
3652
|
+
const w = opts.w ?? mask.w;
|
|
3653
|
+
const h = opts.h ?? mask.h;
|
|
3654
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
3655
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
3656
|
+
const mx = opts.mx ?? 0;
|
|
3657
|
+
const my = opts.my ?? 0;
|
|
3658
|
+
const invertMask = opts.invertMask ?? false;
|
|
3659
|
+
if (globalAlpha === 0) return false;
|
|
3660
|
+
const baseSrcAlpha = color >>> 24;
|
|
3661
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
3662
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
3663
|
+
let x = targetX;
|
|
3664
|
+
let y = targetY;
|
|
3665
|
+
let actualW = w;
|
|
3666
|
+
let actualH = h;
|
|
3667
|
+
if (x < 0) {
|
|
3668
|
+
actualW += x;
|
|
3669
|
+
x = 0;
|
|
4067
3670
|
}
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
imageData;
|
|
4072
|
-
};
|
|
4073
|
-
|
|
4074
|
-
// src/PixelTile/PixelTilePool.ts
|
|
4075
|
-
var PixelTilePool = class {
|
|
4076
|
-
pool;
|
|
4077
|
-
tileSize;
|
|
4078
|
-
tileArea;
|
|
4079
|
-
constructor(config) {
|
|
4080
|
-
this.pool = [];
|
|
4081
|
-
this.tileSize = config.tileSize;
|
|
4082
|
-
this.tileArea = config.tileArea;
|
|
3671
|
+
if (y < 0) {
|
|
3672
|
+
actualH += y;
|
|
3673
|
+
y = 0;
|
|
4083
3674
|
}
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
3675
|
+
actualW = Math.min(actualW, dst.width - x);
|
|
3676
|
+
actualH = Math.min(actualH, dst.height - y);
|
|
3677
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3678
|
+
const dx = x - targetX | 0;
|
|
3679
|
+
const dy = y - targetY | 0;
|
|
3680
|
+
const dst32 = dst.data32;
|
|
3681
|
+
const dw = dst.width;
|
|
3682
|
+
const mPitch = mask.w;
|
|
3683
|
+
const maskData = mask.data;
|
|
3684
|
+
let dIdx = y * dw + x | 0;
|
|
3685
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
3686
|
+
const dStride = dw - actualW | 0;
|
|
3687
|
+
const mStride = mPitch - actualW | 0;
|
|
3688
|
+
const isOpaque = globalAlpha === 255;
|
|
3689
|
+
const colorRGB = color & 16777215;
|
|
3690
|
+
let didChange = false;
|
|
3691
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
3692
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
3693
|
+
const mVal = maskData[mIdx];
|
|
3694
|
+
const effM = invertMask ? 255 - mVal : mVal;
|
|
3695
|
+
if (effM === 0) {
|
|
3696
|
+
dIdx++;
|
|
3697
|
+
mIdx++;
|
|
3698
|
+
continue;
|
|
3699
|
+
}
|
|
3700
|
+
let weight = globalAlpha;
|
|
3701
|
+
if (isOpaque) {
|
|
3702
|
+
weight = effM;
|
|
3703
|
+
} else if (effM !== 255) {
|
|
3704
|
+
weight = effM * globalAlpha + 128 >> 8;
|
|
3705
|
+
}
|
|
3706
|
+
if (weight === 0) {
|
|
3707
|
+
dIdx++;
|
|
3708
|
+
mIdx++;
|
|
3709
|
+
continue;
|
|
3710
|
+
}
|
|
3711
|
+
let finalCol = color;
|
|
3712
|
+
if (weight < 255) {
|
|
3713
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
3714
|
+
if (a === 0 && !isOverwrite) {
|
|
3715
|
+
dIdx++;
|
|
3716
|
+
mIdx++;
|
|
3717
|
+
continue;
|
|
3718
|
+
}
|
|
3719
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
3720
|
+
}
|
|
3721
|
+
const current = dst32[dIdx];
|
|
3722
|
+
const next = blendFn(finalCol, current);
|
|
3723
|
+
if (current !== next) {
|
|
3724
|
+
dst32[dIdx] = next;
|
|
3725
|
+
didChange = true;
|
|
3726
|
+
}
|
|
3727
|
+
dIdx++;
|
|
3728
|
+
mIdx++;
|
|
4092
3729
|
}
|
|
4093
|
-
|
|
3730
|
+
dIdx += dStride;
|
|
3731
|
+
mIdx += mStride;
|
|
4094
3732
|
}
|
|
4095
|
-
|
|
4096
|
-
|
|
3733
|
+
return didChange;
|
|
3734
|
+
}
|
|
3735
|
+
|
|
3736
|
+
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
3737
|
+
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
3738
|
+
const targetX = opts.x ?? 0;
|
|
3739
|
+
const targetY = opts.y ?? 0;
|
|
3740
|
+
let w = opts.w ?? mask.w;
|
|
3741
|
+
let h = opts.h ?? mask.h;
|
|
3742
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
3743
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
3744
|
+
const mx = opts.mx ?? 0;
|
|
3745
|
+
const my = opts.my ?? 0;
|
|
3746
|
+
const invertMask = opts.invertMask ?? false;
|
|
3747
|
+
if (globalAlpha === 0) return false;
|
|
3748
|
+
const baseSrcAlpha = color >>> 24;
|
|
3749
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
3750
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
3751
|
+
let x = targetX;
|
|
3752
|
+
let y = targetY;
|
|
3753
|
+
if (x < 0) {
|
|
3754
|
+
w += x;
|
|
3755
|
+
x = 0;
|
|
3756
|
+
}
|
|
3757
|
+
if (y < 0) {
|
|
3758
|
+
h += y;
|
|
3759
|
+
y = 0;
|
|
3760
|
+
}
|
|
3761
|
+
const actualW = Math.min(w, dst.width - x);
|
|
3762
|
+
const actualH = Math.min(h, dst.height - y);
|
|
3763
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3764
|
+
let baseColorWithGlobalAlpha = color;
|
|
3765
|
+
if (globalAlpha < 255) {
|
|
3766
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
3767
|
+
if (a === 0 && !isOverwrite) return false;
|
|
3768
|
+
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
4097
3769
|
}
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
3770
|
+
const dx = x - targetX | 0;
|
|
3771
|
+
const dy = y - targetY | 0;
|
|
3772
|
+
const dst32 = dst.data32;
|
|
3773
|
+
const dw = dst.width;
|
|
3774
|
+
const mPitch = mask.w;
|
|
3775
|
+
const maskData = mask.data;
|
|
3776
|
+
let dIdx = y * dw + x | 0;
|
|
3777
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
3778
|
+
const dStride = dw - actualW | 0;
|
|
3779
|
+
const mStride = mPitch - actualW | 0;
|
|
3780
|
+
const skipVal = invertMask ? 1 : 0;
|
|
3781
|
+
let didChange = false;
|
|
3782
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
3783
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
3784
|
+
if (maskData[mIdx] === skipVal) {
|
|
3785
|
+
dIdx++;
|
|
3786
|
+
mIdx++;
|
|
3787
|
+
continue;
|
|
3788
|
+
}
|
|
3789
|
+
const current = dst32[dIdx];
|
|
3790
|
+
const next = blendFn(baseColorWithGlobalAlpha, current);
|
|
3791
|
+
if (current !== next) {
|
|
3792
|
+
dst32[dIdx] = next;
|
|
3793
|
+
didChange = true;
|
|
4104
3794
|
}
|
|
3795
|
+
dIdx++;
|
|
3796
|
+
mIdx++;
|
|
4105
3797
|
}
|
|
4106
|
-
|
|
3798
|
+
dIdx += dStride;
|
|
3799
|
+
mIdx += mStride;
|
|
4107
3800
|
}
|
|
4108
|
-
|
|
3801
|
+
return didChange;
|
|
3802
|
+
}
|
|
4109
3803
|
|
|
4110
|
-
// src/History/
|
|
4111
|
-
var
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
historyActionFactory;
|
|
4115
|
-
config;
|
|
4116
|
-
mutator;
|
|
4117
|
-
constructor(target, mutatorFactory, {
|
|
4118
|
-
tileSize = 256,
|
|
4119
|
-
maxHistorySteps = 50,
|
|
4120
|
-
historyManager = new HistoryManager(maxHistorySteps),
|
|
4121
|
-
historyActionFactory = makeHistoryAction,
|
|
4122
|
-
pixelTilePool
|
|
4123
|
-
} = {}) {
|
|
4124
|
-
this.config = new PixelEngineConfig(tileSize, target);
|
|
4125
|
-
this.historyManager = historyManager;
|
|
4126
|
-
pixelTilePool ??= new PixelTilePool(this.config);
|
|
4127
|
-
this.accumulator = new PixelAccumulator(this.config, pixelTilePool);
|
|
4128
|
-
this.historyActionFactory = historyActionFactory;
|
|
4129
|
-
this.mutator = mutatorFactory(this);
|
|
4130
|
-
}
|
|
4131
|
-
withHistory(cb, after, afterUndo, afterRedo) {
|
|
4132
|
-
try {
|
|
4133
|
-
cb(this.mutator);
|
|
4134
|
-
} catch (e) {
|
|
4135
|
-
this.accumulator.rollback();
|
|
4136
|
-
throw e;
|
|
4137
|
-
}
|
|
4138
|
-
if (this.accumulator.beforeTiles.length === 0) return;
|
|
4139
|
-
const patch = this.accumulator.extractPatch();
|
|
4140
|
-
const action = this.historyActionFactory(this, patch, after, afterUndo, afterRedo);
|
|
4141
|
-
this.historyManager.commit(action);
|
|
4142
|
-
}
|
|
3804
|
+
// src/History/PixelMutator/mutatorBlendPaintMask.ts
|
|
3805
|
+
var defaults13 = {
|
|
3806
|
+
blendColorPixelDataAlphaMask,
|
|
3807
|
+
blendColorPixelDataBinaryMask
|
|
4143
3808
|
};
|
|
3809
|
+
var mutatorBlendPaintMask = ((writer, deps = defaults13) => {
|
|
3810
|
+
const {
|
|
3811
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults13.blendColorPixelDataBinaryMask,
|
|
3812
|
+
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults13.blendColorPixelDataAlphaMask
|
|
3813
|
+
} = deps;
|
|
3814
|
+
const OPTS = {
|
|
3815
|
+
x: 0,
|
|
3816
|
+
y: 0,
|
|
3817
|
+
blendFn: sourceOverPerfect,
|
|
3818
|
+
alpha: 255
|
|
3819
|
+
};
|
|
3820
|
+
return {
|
|
3821
|
+
blendColorPaintMask(color, mask, x, y, alpha = 255, blendFn = sourceOverPerfect) {
|
|
3822
|
+
const tx = x + mask.centerOffsetX;
|
|
3823
|
+
const ty = y + mask.centerOffsetY;
|
|
3824
|
+
const didChange = writer.accumulator.storeRegionBeforeState(tx, ty, mask.w, mask.h);
|
|
3825
|
+
OPTS.x = tx;
|
|
3826
|
+
OPTS.y = ty;
|
|
3827
|
+
OPTS.alpha = alpha;
|
|
3828
|
+
OPTS.blendFn = blendFn;
|
|
3829
|
+
if (mask.type === 1 /* BINARY */) {
|
|
3830
|
+
return didChange(blendColorPixelDataBinaryMask2(writer.config.target, color, mask, OPTS));
|
|
3831
|
+
} else {
|
|
3832
|
+
return didChange(blendColorPixelDataAlphaMask2(writer.config.target, color, mask, OPTS));
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
};
|
|
3836
|
+
});
|
|
4144
3837
|
|
|
4145
3838
|
// src/ImageData/copyImageData.ts
|
|
4146
3839
|
function copyImageData({
|
|
@@ -4263,35 +3956,6 @@ function resampleImageData(source, factor) {
|
|
|
4263
3956
|
return new ImageData(uint8ClampedArray, width, height);
|
|
4264
3957
|
}
|
|
4265
3958
|
|
|
4266
|
-
// src/ImageData/resizeImageData.ts
|
|
4267
|
-
function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
4268
|
-
const result = new ImageData(newWidth, newHeight);
|
|
4269
|
-
const {
|
|
4270
|
-
width: oldW,
|
|
4271
|
-
height: oldH,
|
|
4272
|
-
data: oldData
|
|
4273
|
-
} = target;
|
|
4274
|
-
const newData = result.data;
|
|
4275
|
-
const x0 = Math.max(0, offsetX);
|
|
4276
|
-
const y0 = Math.max(0, offsetY);
|
|
4277
|
-
const x1 = Math.min(newWidth, offsetX + oldW);
|
|
4278
|
-
const y1 = Math.min(newHeight, offsetY + oldH);
|
|
4279
|
-
if (x1 <= x0 || y1 <= y0) {
|
|
4280
|
-
return result;
|
|
4281
|
-
}
|
|
4282
|
-
const rowCount = y1 - y0;
|
|
4283
|
-
const rowLen = (x1 - x0) * 4;
|
|
4284
|
-
for (let row = 0; row < rowCount; row++) {
|
|
4285
|
-
const dstY = y0 + row;
|
|
4286
|
-
const srcY = dstY - offsetY;
|
|
4287
|
-
const srcX = x0 - offsetX;
|
|
4288
|
-
const dstStart = (dstY * newWidth + x0) * 4;
|
|
4289
|
-
const srcStart = (srcY * oldW + srcX) * 4;
|
|
4290
|
-
newData.set(oldData.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
4291
|
-
}
|
|
4292
|
-
return result;
|
|
4293
|
-
}
|
|
4294
|
-
|
|
4295
3959
|
// src/ImageData/ReusableImageData.ts
|
|
4296
3960
|
function makeReusableImageData() {
|
|
4297
3961
|
let imageData = null;
|
|
@@ -4706,62 +4370,6 @@ function makeBinaryMask(w, h, data) {
|
|
|
4706
4370
|
};
|
|
4707
4371
|
}
|
|
4708
4372
|
|
|
4709
|
-
// src/Mask/CircleAlphaMask.ts
|
|
4710
|
-
function makeCircleAlphaMask(size, fallOff = () => 1) {
|
|
4711
|
-
const area = size * size;
|
|
4712
|
-
const data = new Uint8Array(area);
|
|
4713
|
-
const radius = size / 2;
|
|
4714
|
-
const invR = 1 / radius;
|
|
4715
|
-
const minOffset = -Math.ceil(radius - 0.5);
|
|
4716
|
-
for (let y = 0; y < size; y++) {
|
|
4717
|
-
for (let x = 0; x < size; x++) {
|
|
4718
|
-
const dx = x - radius + 0.5;
|
|
4719
|
-
const dy = y - radius + 0.5;
|
|
4720
|
-
const distSqr = dx * dx + dy * dy;
|
|
4721
|
-
if (distSqr <= radius * radius) {
|
|
4722
|
-
const dist = Math.sqrt(distSqr);
|
|
4723
|
-
data[y * size + x] = fallOff(1 - dist * invR) * 255 | 0;
|
|
4724
|
-
}
|
|
4725
|
-
}
|
|
4726
|
-
}
|
|
4727
|
-
return {
|
|
4728
|
-
type: 0 /* ALPHA */,
|
|
4729
|
-
data,
|
|
4730
|
-
w: size,
|
|
4731
|
-
h: size,
|
|
4732
|
-
radius,
|
|
4733
|
-
size,
|
|
4734
|
-
minOffset
|
|
4735
|
-
};
|
|
4736
|
-
}
|
|
4737
|
-
|
|
4738
|
-
// src/Mask/CircleBinaryMask.ts
|
|
4739
|
-
function makeCircleBinaryMask(size) {
|
|
4740
|
-
const area = size * size;
|
|
4741
|
-
const data = new Uint8Array(area);
|
|
4742
|
-
const radius = size / 2;
|
|
4743
|
-
const minOffset = -Math.ceil(radius - 0.5);
|
|
4744
|
-
for (let y = 0; y < size; y++) {
|
|
4745
|
-
for (let x = 0; x < size; x++) {
|
|
4746
|
-
const dx = x - radius + 0.5;
|
|
4747
|
-
const dy = y - radius + 0.5;
|
|
4748
|
-
const distSqr = dx * dx + dy * dy;
|
|
4749
|
-
if (distSqr <= radius * radius) {
|
|
4750
|
-
data[y * size + x] = 1;
|
|
4751
|
-
}
|
|
4752
|
-
}
|
|
4753
|
-
}
|
|
4754
|
-
return {
|
|
4755
|
-
type: 1 /* BINARY */,
|
|
4756
|
-
data,
|
|
4757
|
-
w: size,
|
|
4758
|
-
h: size,
|
|
4759
|
-
radius,
|
|
4760
|
-
size,
|
|
4761
|
-
minOffset
|
|
4762
|
-
};
|
|
4763
|
-
}
|
|
4764
|
-
|
|
4765
4373
|
// src/Mask/applyBinaryMaskToAlphaMask.ts
|
|
4766
4374
|
function applyBinaryMaskToAlphaMask(alphaMaskDst, binaryMaskSrc, opts = {}) {
|
|
4767
4375
|
const {
|
|
@@ -5462,103 +5070,140 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
5462
5070
|
}
|
|
5463
5071
|
}
|
|
5464
5072
|
|
|
5465
|
-
// src/
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5073
|
+
// src/PixelData/writePaintBufferToPixelData.ts
|
|
5074
|
+
function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn = writePixelDataBuffer) {
|
|
5075
|
+
const tileShift = paintBuffer.config.tileShift;
|
|
5076
|
+
const lookup = paintBuffer.lookup;
|
|
5077
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
5078
|
+
const tile = lookup[i];
|
|
5079
|
+
if (tile) {
|
|
5080
|
+
const dx = tile.tx << tileShift;
|
|
5081
|
+
const dy = tile.ty << tileShift;
|
|
5082
|
+
writePixelDataBufferFn(target, tile.data32, dx, dy, tile.width, tile.height);
|
|
5083
|
+
}
|
|
5471
5084
|
}
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5085
|
+
}
|
|
5086
|
+
|
|
5087
|
+
// src/Paint/makeCirclePaintAlphaMask.ts
|
|
5088
|
+
function makeCirclePaintAlphaMask(size, fallOff = (d) => d) {
|
|
5089
|
+
const area = size * size;
|
|
5090
|
+
const data = new Uint8Array(area);
|
|
5091
|
+
const radius = size / 2;
|
|
5092
|
+
const invR = 1 / radius;
|
|
5093
|
+
const centerOffset = -Math.ceil(radius - 0.5);
|
|
5094
|
+
for (let y = 0; y < size; y++) {
|
|
5095
|
+
const rowOffset = y * size;
|
|
5096
|
+
const dy = y - radius + 0.5;
|
|
5097
|
+
const dy2 = dy * dy;
|
|
5098
|
+
for (let x = 0; x < size; x++) {
|
|
5099
|
+
const dx = x - radius + 0.5;
|
|
5100
|
+
const distSqr = dx * dx + dy2;
|
|
5101
|
+
if (distSqr <= radius * radius) {
|
|
5102
|
+
const dist = Math.sqrt(distSqr) * invR;
|
|
5103
|
+
const strength = fallOff(1 - dist);
|
|
5104
|
+
if (strength > 0) {
|
|
5105
|
+
const intensity = strength * 255 | 0;
|
|
5106
|
+
data[rowOffset + x] = Math.max(0, Math.min(255, intensity));
|
|
5491
5107
|
}
|
|
5492
|
-
const tileLeft = tx << tileShift;
|
|
5493
|
-
const startX = Math.max(mask.x, tileLeft);
|
|
5494
|
-
const endX = Math.min(mask.x + mask.w, tileLeft + this.config.tileSize);
|
|
5495
|
-
const startY = Math.max(mask.y, tileTop);
|
|
5496
|
-
const endY = Math.min(mask.y + mask.h, tileTop + this.config.tileSize);
|
|
5497
|
-
callback(tile, startX, startY, endX - startX, endY - startY, startX - mask.x, startY - mask.y);
|
|
5498
5108
|
}
|
|
5499
5109
|
}
|
|
5500
5110
|
}
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5111
|
+
return {
|
|
5112
|
+
type: 0 /* ALPHA */,
|
|
5113
|
+
data,
|
|
5114
|
+
w: size,
|
|
5115
|
+
h: size,
|
|
5116
|
+
centerOffsetX: centerOffset,
|
|
5117
|
+
centerOffsetY: centerOffset
|
|
5118
|
+
};
|
|
5119
|
+
}
|
|
5120
|
+
|
|
5121
|
+
// src/Paint/makeCirclePaintBinaryMask.ts
|
|
5122
|
+
function makeCirclePaintBinaryMask(size) {
|
|
5123
|
+
const area = size * size;
|
|
5124
|
+
const data = new Uint8Array(area);
|
|
5125
|
+
const radius = size / 2;
|
|
5126
|
+
const centerOffset = -Math.ceil(radius - 0.5);
|
|
5127
|
+
for (let y = 0; y < size; y++) {
|
|
5128
|
+
for (let x = 0; x < size; x++) {
|
|
5129
|
+
const dx = x - radius + 0.5;
|
|
5130
|
+
const dy = y - radius + 0.5;
|
|
5131
|
+
const distSqr = dx * dx + dy * dy;
|
|
5132
|
+
if (distSqr <= radius * radius) {
|
|
5133
|
+
data[y * size + x] = 1;
|
|
5523
5134
|
}
|
|
5524
|
-
}
|
|
5135
|
+
}
|
|
5525
5136
|
}
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5137
|
+
return {
|
|
5138
|
+
type: 1 /* BINARY */,
|
|
5139
|
+
data,
|
|
5140
|
+
w: size,
|
|
5141
|
+
h: size,
|
|
5142
|
+
centerOffsetX: centerOffset,
|
|
5143
|
+
centerOffsetY: centerOffset
|
|
5144
|
+
};
|
|
5145
|
+
}
|
|
5146
|
+
|
|
5147
|
+
// src/Internal/helpers.ts
|
|
5148
|
+
var macro_halfAndFloor = (value) => value >> 1;
|
|
5149
|
+
|
|
5150
|
+
// src/Paint/makePaintMask.ts
|
|
5151
|
+
function makePaintBinaryMask(mask) {
|
|
5152
|
+
return {
|
|
5153
|
+
type: 1 /* BINARY */,
|
|
5154
|
+
data: mask.data,
|
|
5155
|
+
w: mask.w,
|
|
5156
|
+
h: mask.h,
|
|
5157
|
+
centerOffsetX: -macro_halfAndFloor(mask.w),
|
|
5158
|
+
centerOffsetY: -macro_halfAndFloor(mask.h)
|
|
5159
|
+
};
|
|
5160
|
+
}
|
|
5161
|
+
function makePaintAlphaMask(mask) {
|
|
5162
|
+
return {
|
|
5163
|
+
type: 0 /* ALPHA */,
|
|
5164
|
+
data: mask.data,
|
|
5165
|
+
w: mask.w,
|
|
5166
|
+
h: mask.h,
|
|
5167
|
+
centerOffsetX: -macro_halfAndFloor(mask.w),
|
|
5168
|
+
centerOffsetY: -macro_halfAndFloor(mask.h)
|
|
5169
|
+
};
|
|
5170
|
+
}
|
|
5171
|
+
|
|
5172
|
+
// src/Paint/makeRectFalloffPaintAlphaMask.ts
|
|
5173
|
+
function makeRectFalloffPaintAlphaMask(width, height, fallOff = (d) => d) {
|
|
5174
|
+
const fPx = Math.floor(width / 2);
|
|
5175
|
+
const fPy = Math.floor(height / 2);
|
|
5176
|
+
const invHalfW = 2 / width;
|
|
5177
|
+
const invHalfH = 2 / height;
|
|
5178
|
+
const offX = width % 2 === 0 ? 0.5 : 0;
|
|
5179
|
+
const offY = height % 2 === 0 ? 0.5 : 0;
|
|
5180
|
+
const area = width * height;
|
|
5181
|
+
const data = new Uint8Array(area);
|
|
5182
|
+
for (let y = 0; y < height; y++) {
|
|
5183
|
+
const dy = Math.abs(y - fPy + offY) * invHalfH;
|
|
5184
|
+
const rowOffset = y * width;
|
|
5185
|
+
for (let x = 0; x < width; x++) {
|
|
5186
|
+
const dx = Math.abs(x - fPx + offX) * invHalfW;
|
|
5187
|
+
const dist = dx > dy ? dx : dy;
|
|
5188
|
+
const strength = fallOff(1 - dist);
|
|
5189
|
+
if (strength > 0) {
|
|
5190
|
+
const intensity = strength * 255 | 0;
|
|
5191
|
+
data[rowOffset + x] = Math.max(0, Math.min(255, intensity));
|
|
5552
5192
|
}
|
|
5553
|
-
}
|
|
5554
|
-
}
|
|
5555
|
-
clear() {
|
|
5556
|
-
this.tilePool.releaseTiles(this.lookup);
|
|
5193
|
+
}
|
|
5557
5194
|
}
|
|
5558
|
-
|
|
5195
|
+
return {
|
|
5196
|
+
type: 0 /* ALPHA */,
|
|
5197
|
+
data,
|
|
5198
|
+
w: width,
|
|
5199
|
+
h: height,
|
|
5200
|
+
centerOffsetX: -macro_halfAndFloor(width),
|
|
5201
|
+
centerOffsetY: -macro_halfAndFloor(height)
|
|
5202
|
+
};
|
|
5203
|
+
}
|
|
5559
5204
|
|
|
5560
|
-
// src/
|
|
5561
|
-
function
|
|
5205
|
+
// src/Paint/PaintBufferCanvasRenderer.ts
|
|
5206
|
+
function makePaintBufferCanvasRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
|
|
5562
5207
|
const config = paintBuffer.config;
|
|
5563
5208
|
const tileSize = config.tileSize;
|
|
5564
5209
|
const tileShift = config.tileShift;
|
|
@@ -5567,16 +5212,20 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5567
5212
|
const ctx = canvas.getContext("2d");
|
|
5568
5213
|
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
5569
5214
|
ctx.imageSmoothingEnabled = false;
|
|
5570
|
-
return function drawPaintBuffer(
|
|
5215
|
+
return function drawPaintBuffer(targetCtx, alpha = 255, compOperation = "source-over") {
|
|
5216
|
+
targetCtx.globalAlpha = alpha / 255;
|
|
5217
|
+
targetCtx.globalCompositeOperation = compOperation;
|
|
5571
5218
|
for (let i = 0; i < lookup.length; i++) {
|
|
5572
5219
|
const tile = lookup[i];
|
|
5573
5220
|
if (tile) {
|
|
5574
5221
|
const dx = tile.tx << tileShift;
|
|
5575
5222
|
const dy = tile.ty << tileShift;
|
|
5576
5223
|
ctx.putImageData(tile.imageData, 0, 0);
|
|
5577
|
-
|
|
5224
|
+
targetCtx.drawImage(canvas, dx, dy);
|
|
5578
5225
|
}
|
|
5579
5226
|
}
|
|
5227
|
+
targetCtx.globalAlpha = 1;
|
|
5228
|
+
targetCtx.globalCompositeOperation = "source-over";
|
|
5580
5229
|
};
|
|
5581
5230
|
}
|
|
5582
5231
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -5584,6 +5233,7 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5584
5233
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
5585
5234
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
5586
5235
|
BaseBlendMode,
|
|
5236
|
+
CANVAS_COMPOSITE_MAP,
|
|
5587
5237
|
CANVAS_CTX_FAILED,
|
|
5588
5238
|
HistoryManager,
|
|
5589
5239
|
IndexedImage,
|
|
@@ -5602,13 +5252,11 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5602
5252
|
applyBinaryMaskToAlphaMask,
|
|
5603
5253
|
applyBinaryMaskToPixelData,
|
|
5604
5254
|
applyPatchTiles,
|
|
5605
|
-
applyRectBrushToPixelData,
|
|
5606
5255
|
base64DecodeArrayBuffer,
|
|
5607
5256
|
base64EncodeArrayBuffer,
|
|
5608
5257
|
blendColorPixelData,
|
|
5609
5258
|
blendColorPixelDataAlphaMask,
|
|
5610
5259
|
blendColorPixelDataBinaryMask,
|
|
5611
|
-
blendColorPixelDataCircleMask,
|
|
5612
5260
|
blendPixel,
|
|
5613
5261
|
blendPixelData,
|
|
5614
5262
|
blendPixelDataAlphaMask,
|
|
@@ -5650,12 +5298,8 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5650
5298
|
fillPixelDataFast,
|
|
5651
5299
|
floodFillSelection,
|
|
5652
5300
|
forEachLinePoint,
|
|
5653
|
-
getCircleBrushOrPencilBounds,
|
|
5654
|
-
getCircleBrushOrPencilStrokeBounds,
|
|
5655
5301
|
getImageDataFromClipboard,
|
|
5656
5302
|
getIndexedImageColorCounts,
|
|
5657
|
-
getRectBrushOrPencilBounds,
|
|
5658
|
-
getRectBrushOrPencilStrokeBounds,
|
|
5659
5303
|
getRectsBounds,
|
|
5660
5304
|
getSupportedPixelFormats,
|
|
5661
5305
|
hardLightFast,
|
|
@@ -5689,15 +5333,18 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5689
5333
|
makeBinaryMask,
|
|
5690
5334
|
makeBlendModeRegistry,
|
|
5691
5335
|
makeCanvasFrameRenderer,
|
|
5692
|
-
|
|
5693
|
-
|
|
5336
|
+
makeCirclePaintAlphaMask,
|
|
5337
|
+
makeCirclePaintBinaryMask,
|
|
5694
5338
|
makeFastBlendModeRegistry,
|
|
5695
5339
|
makeFullPixelMutator,
|
|
5696
5340
|
makeHistoryAction,
|
|
5697
5341
|
makeImageDataLike,
|
|
5698
|
-
|
|
5342
|
+
makePaintAlphaMask,
|
|
5343
|
+
makePaintBinaryMask,
|
|
5344
|
+
makePaintBufferCanvasRenderer,
|
|
5699
5345
|
makePerfectBlendModeRegistry,
|
|
5700
5346
|
makePixelCanvas,
|
|
5347
|
+
makeRectFalloffPaintAlphaMask,
|
|
5701
5348
|
makeReusableCanvas,
|
|
5702
5349
|
makeReusableImageData,
|
|
5703
5350
|
makeReusableOffscreenCanvas,
|
|
@@ -5709,15 +5356,8 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5709
5356
|
multiplyPerfect,
|
|
5710
5357
|
mutatorApplyAlphaMask,
|
|
5711
5358
|
mutatorApplyBinaryMask,
|
|
5712
|
-
mutatorApplyCircleBrushStroke,
|
|
5713
|
-
mutatorApplyCirclePencil,
|
|
5714
|
-
mutatorApplyCirclePencilStroke,
|
|
5715
|
-
mutatorApplyRectBrush,
|
|
5716
|
-
mutatorApplyRectBrushStroke,
|
|
5717
|
-
mutatorApplyRectPencil,
|
|
5718
|
-
mutatorApplyRectPencilStroke,
|
|
5719
5359
|
mutatorBlendColor,
|
|
5720
|
-
|
|
5360
|
+
mutatorBlendPaintMask,
|
|
5721
5361
|
mutatorBlendPixel,
|
|
5722
5362
|
mutatorBlendPixelData,
|
|
5723
5363
|
mutatorBlendPixelDataAlphaMask,
|
|
@@ -5757,6 +5397,7 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5757
5397
|
subtractFast,
|
|
5758
5398
|
subtractPerfect,
|
|
5759
5399
|
toBlendModeIndexAndName,
|
|
5400
|
+
trimMaskRectBounds,
|
|
5760
5401
|
trimRectBounds,
|
|
5761
5402
|
uInt32ArrayToImageData,
|
|
5762
5403
|
uInt32ArrayToImageDataLike,
|
|
@@ -5772,6 +5413,7 @@ function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCa
|
|
|
5772
5413
|
writeImageDataBuffer,
|
|
5773
5414
|
writeImageDataToClipboard,
|
|
5774
5415
|
writeImgBlobToClipboard,
|
|
5416
|
+
writePaintBufferToPixelData,
|
|
5775
5417
|
writePixelDataBuffer
|
|
5776
5418
|
});
|
|
5777
5419
|
//# sourceMappingURL=index.dev.cjs.map
|