pixel-data-js 0.17.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/index.dev.cjs +2747 -1397
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +2725 -1403
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +2747 -1397
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +401 -241
- package/dist/index.prod.js +2725 -1403
- package/dist/index.prod.js.map +1 -1
- package/package.json +21 -6
- package/src/Algorithm/forEachLinePoint.ts +36 -0
- package/src/BlendModes/BlendModeRegistry.ts +2 -0
- package/src/BlendModes/blend-modes-fast.ts +2 -2
- package/src/BlendModes/blend-modes-perfect.ts +5 -4
- package/src/BlendModes/toBlendModeIndexAndName.ts +41 -0
- package/src/History/PixelAccumulator.ts +2 -2
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +30 -0
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +30 -0
- package/src/History/PixelMutator/mutatorApplyCircleBrush.ts +59 -0
- package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +138 -0
- package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +59 -0
- package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +131 -0
- package/src/History/PixelMutator/mutatorApplyRectBrush.ts +61 -0
- package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +169 -0
- package/src/History/PixelMutator/mutatorApplyRectPencil.ts +62 -0
- package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +149 -0
- package/src/History/PixelMutator/mutatorBlendColor.ts +9 -4
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +10 -5
- package/src/History/PixelMutator/mutatorClear.ts +27 -0
- package/src/History/PixelMutator/{mutatorFillPixelData.ts → mutatorFill.ts} +9 -3
- package/src/History/PixelMutator/mutatorInvert.ts +10 -3
- package/src/History/PixelMutator.ts +27 -3
- package/src/History/PixelPatchTiles.ts +2 -2
- package/src/History/PixelWriter.ts +7 -3
- package/src/ImageData/ImageDataLike.ts +13 -0
- package/src/ImageData/ReusableImageData.ts +1 -4
- package/src/ImageData/extractImageDataBuffer.ts +22 -15
- package/src/ImageData/serialization.ts +4 -4
- package/src/ImageData/uInt32ArrayToImageData.ts +29 -0
- package/src/ImageData/writeImageData.ts +26 -18
- package/src/ImageData/writeImageDataBuffer.ts +30 -18
- package/src/IndexedImage/indexedImageToAverageColor.ts +1 -1
- package/src/Internal/resolveClipping.ts +140 -0
- package/src/Mask/applyBinaryMaskToAlphaMask.ts +89 -0
- package/src/Mask/copyMask.ts +1 -3
- package/src/Mask/mergeAlphaMasks.ts +81 -0
- package/src/Mask/mergeBinaryMasks.ts +89 -0
- package/src/PixelData/PixelBuffer32.ts +28 -0
- package/src/PixelData/PixelData.ts +38 -33
- package/src/PixelData/applyAlphaMaskToPixelData.ts +119 -0
- package/src/PixelData/applyBinaryMaskToPixelData.ts +111 -0
- package/src/PixelData/applyCircleBrushToPixelData.ts +58 -28
- package/src/PixelData/applyRectBrushToPixelData.ts +56 -73
- package/src/PixelData/blendColorPixelData.ts +18 -111
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +111 -0
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +89 -0
- package/src/PixelData/blendPixelData.ts +19 -107
- package/src/PixelData/blendPixelDataAlphaMask.ts +149 -0
- package/src/PixelData/blendPixelDataBinaryMask.ts +133 -0
- package/src/PixelData/clearPixelData.ts +2 -3
- package/src/PixelData/extractPixelData.ts +4 -4
- package/src/PixelData/extractPixelDataBuffer.ts +38 -26
- package/src/PixelData/fillPixelData.ts +18 -20
- package/src/PixelData/invertPixelData.ts +13 -21
- package/src/PixelData/pixelDataToAlphaMask.ts +2 -3
- package/src/PixelData/reflectPixelData.ts +3 -3
- package/src/PixelData/resamplePixelData.ts +2 -6
- package/src/PixelData/writePixelDataBuffer.ts +34 -20
- package/src/Rect/getCircleBrushOrPencilBounds.ts +43 -0
- package/src/Rect/getCircleBrushOrPencilStrokeBounds.ts +24 -0
- package/src/Rect/getRectBrushOrPencilBounds.ts +38 -0
- package/src/Rect/getRectBrushOrPencilStrokeBounds.ts +26 -0
- package/src/_types.ts +49 -33
- package/src/index.ts +47 -11
- package/src/History/PixelMutator/mutatorApplyMask.ts +0 -20
- package/src/Mask/mergeMasks.ts +0 -100
- package/src/PixelData/applyMaskToPixelData.ts +0 -129
package/dist/index.dev.cjs
CHANGED
|
@@ -23,23 +23,32 @@ __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_CTX_FAILED: () => CANVAS_CTX_FAILED,
|
|
26
27
|
HistoryManager: () => HistoryManager,
|
|
27
28
|
IndexedImage: () => IndexedImage,
|
|
28
29
|
MaskType: () => MaskType,
|
|
30
|
+
OFFSCREEN_CANVAS_CTX_FAILED: () => OFFSCREEN_CANVAS_CTX_FAILED,
|
|
29
31
|
PixelAccumulator: () => PixelAccumulator,
|
|
32
|
+
PixelBuffer32: () => PixelBuffer32,
|
|
30
33
|
PixelData: () => PixelData,
|
|
31
34
|
PixelEngineConfig: () => PixelEngineConfig,
|
|
32
35
|
PixelTile: () => PixelTile,
|
|
33
36
|
PixelWriter: () => PixelWriter,
|
|
34
37
|
UnsupportedFormatError: () => UnsupportedFormatError,
|
|
38
|
+
applyAlphaMaskToPixelData: () => applyAlphaMaskToPixelData,
|
|
39
|
+
applyBinaryMaskToAlphaMask: () => applyBinaryMaskToAlphaMask,
|
|
40
|
+
applyBinaryMaskToPixelData: () => applyBinaryMaskToPixelData,
|
|
35
41
|
applyCircleBrushToPixelData: () => applyCircleBrushToPixelData,
|
|
36
|
-
applyMaskToPixelData: () => applyMaskToPixelData,
|
|
37
42
|
applyPatchTiles: () => applyPatchTiles,
|
|
38
43
|
applyRectBrushToPixelData: () => applyRectBrushToPixelData,
|
|
39
44
|
base64DecodeArrayBuffer: () => base64DecodeArrayBuffer,
|
|
40
45
|
base64EncodeArrayBuffer: () => base64EncodeArrayBuffer,
|
|
41
46
|
blendColorPixelData: () => blendColorPixelData,
|
|
47
|
+
blendColorPixelDataAlphaMask: () => blendColorPixelDataAlphaMask,
|
|
48
|
+
blendColorPixelDataBinaryMask: () => blendColorPixelDataBinaryMask,
|
|
42
49
|
blendPixelData: () => blendPixelData,
|
|
50
|
+
blendPixelDataAlphaMask: () => blendPixelDataAlphaMask,
|
|
51
|
+
blendPixelDataBinaryMask: () => blendPixelDataBinaryMask,
|
|
43
52
|
clearPixelData: () => clearPixelData,
|
|
44
53
|
color32ToCssRGBA: () => color32ToCssRGBA,
|
|
45
54
|
color32ToHex: () => color32ToHex,
|
|
@@ -72,9 +81,13 @@ __export(src_exports, {
|
|
|
72
81
|
fileToImageData: () => fileToImageData,
|
|
73
82
|
fillPixelData: () => fillPixelData,
|
|
74
83
|
floodFillSelection: () => floodFillSelection,
|
|
84
|
+
forEachLinePoint: () => forEachLinePoint,
|
|
85
|
+
getCircleBrushOrPencilBounds: () => getCircleBrushOrPencilBounds,
|
|
86
|
+
getCircleBrushOrPencilStrokeBounds: () => getCircleBrushOrPencilStrokeBounds,
|
|
75
87
|
getImageDataFromClipboard: () => getImageDataFromClipboard,
|
|
76
88
|
getIndexedImageColorCounts: () => getIndexedImageColorCounts,
|
|
77
|
-
|
|
89
|
+
getRectBrushOrPencilBounds: () => getRectBrushOrPencilBounds,
|
|
90
|
+
getRectBrushOrPencilStrokeBounds: () => getRectBrushOrPencilStrokeBounds,
|
|
78
91
|
getSupportedPixelFormats: () => getSupportedPixelFormats,
|
|
79
92
|
hardLightFast: () => hardLightFast,
|
|
80
93
|
hardLightPerfect: () => hardLightPerfect,
|
|
@@ -106,17 +119,29 @@ __export(src_exports, {
|
|
|
106
119
|
makeBlendModeRegistry: () => makeBlendModeRegistry,
|
|
107
120
|
makeFastBlendModeRegistry: () => makeFastBlendModeRegistry,
|
|
108
121
|
makeFullPixelMutator: () => makeFullPixelMutator,
|
|
122
|
+
makeImageDataLike: () => makeImageDataLike,
|
|
109
123
|
makePerfectBlendModeRegistry: () => makePerfectBlendModeRegistry,
|
|
110
124
|
makePixelCanvas: () => makePixelCanvas,
|
|
111
125
|
makeReusableCanvas: () => makeReusableCanvas,
|
|
112
126
|
makeReusableImageData: () => makeReusableImageData,
|
|
113
|
-
|
|
127
|
+
mergeAlphaMasks: () => mergeAlphaMasks,
|
|
128
|
+
mergeBinaryMasks: () => mergeBinaryMasks,
|
|
114
129
|
multiplyFast: () => multiplyFast,
|
|
115
130
|
multiplyPerfect: () => multiplyPerfect,
|
|
116
|
-
|
|
131
|
+
mutatorApplyAlphaMask: () => mutatorApplyAlphaMask,
|
|
132
|
+
mutatorApplyBinaryMask: () => mutatorApplyBinaryMask,
|
|
133
|
+
mutatorApplyCircleBrush: () => mutatorApplyCircleBrush,
|
|
134
|
+
mutatorApplyCircleBrushStroke: () => mutatorApplyCircleBrushStroke,
|
|
135
|
+
mutatorApplyCirclePencil: () => mutatorApplyCirclePencil,
|
|
136
|
+
mutatorApplyCirclePencilStroke: () => mutatorApplyCirclePencilStroke,
|
|
137
|
+
mutatorApplyRectBrush: () => mutatorApplyRectBrush,
|
|
138
|
+
mutatorApplyRectBrushStroke: () => mutatorApplyRectBrushStroke,
|
|
139
|
+
mutatorApplyRectPencil: () => mutatorApplyRectPencil,
|
|
140
|
+
mutatorApplyRectPencilStroke: () => mutatorApplyRectPencilStroke,
|
|
117
141
|
mutatorBlendColor: () => mutatorBlendColor,
|
|
118
142
|
mutatorBlendPixel: () => mutatorBlendPixel,
|
|
119
143
|
mutatorBlendPixelData: () => mutatorBlendPixelData,
|
|
144
|
+
mutatorClear: () => mutatorClear,
|
|
120
145
|
mutatorFill: () => mutatorFill,
|
|
121
146
|
mutatorInvert: () => mutatorInvert,
|
|
122
147
|
overlayFast: () => overlayFast,
|
|
@@ -146,7 +171,10 @@ __export(src_exports, {
|
|
|
146
171
|
sourceOverPerfect: () => sourceOverPerfect,
|
|
147
172
|
subtractFast: () => subtractFast,
|
|
148
173
|
subtractPerfect: () => subtractPerfect,
|
|
174
|
+
toBlendModeIndexAndName: () => toBlendModeIndexAndName,
|
|
149
175
|
trimRectBounds: () => trimRectBounds,
|
|
176
|
+
uInt32ArrayToImageData: () => uInt32ArrayToImageData,
|
|
177
|
+
uInt32ArrayToImageDataLike: () => uInt32ArrayToImageDataLike,
|
|
150
178
|
unpackAlpha: () => unpackAlpha,
|
|
151
179
|
unpackBlue: () => unpackBlue,
|
|
152
180
|
unpackColor: () => unpackColor,
|
|
@@ -163,617 +191,238 @@ __export(src_exports, {
|
|
|
163
191
|
});
|
|
164
192
|
module.exports = __toCommonJS(src_exports);
|
|
165
193
|
|
|
166
|
-
// src/
|
|
167
|
-
var
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
194
|
+
// src/_types.ts
|
|
195
|
+
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
196
|
+
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
197
|
+
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
198
|
+
return MaskType2;
|
|
199
|
+
})(MaskType || {});
|
|
200
|
+
|
|
201
|
+
// src/color.ts
|
|
202
|
+
function packColor(r, g, b, a) {
|
|
203
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
204
|
+
}
|
|
205
|
+
function packRGBA({
|
|
206
|
+
r,
|
|
207
|
+
g,
|
|
208
|
+
b,
|
|
209
|
+
a
|
|
210
|
+
}) {
|
|
211
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
212
|
+
}
|
|
213
|
+
var unpackRed = (packed) => packed >>> 0 & 255;
|
|
214
|
+
var unpackGreen = (packed) => packed >>> 8 & 255;
|
|
215
|
+
var unpackBlue = (packed) => packed >>> 16 & 255;
|
|
216
|
+
var unpackAlpha = (packed) => packed >>> 24 & 255;
|
|
217
|
+
function unpackColor(packed) {
|
|
218
|
+
return {
|
|
219
|
+
r: packed >>> 0 & 255,
|
|
220
|
+
g: packed >>> 8 & 255,
|
|
221
|
+
b: packed >>> 16 & 255,
|
|
222
|
+
a: packed >>> 24 & 255
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
var SCRATCH_RGBA = {
|
|
226
|
+
r: 0,
|
|
227
|
+
g: 0,
|
|
228
|
+
b: 0,
|
|
229
|
+
a: 0
|
|
191
230
|
};
|
|
192
|
-
|
|
193
|
-
|
|
231
|
+
function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
|
|
232
|
+
scratch.r = packed >>> 0 & 255;
|
|
233
|
+
scratch.g = packed >>> 8 & 255;
|
|
234
|
+
scratch.b = packed >>> 16 & 255;
|
|
235
|
+
scratch.a = packed >>> 24 & 255;
|
|
236
|
+
return scratch;
|
|
237
|
+
}
|
|
238
|
+
function colorDistance(a, b) {
|
|
239
|
+
const dr = (a & 255) - (b & 255);
|
|
240
|
+
const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
|
|
241
|
+
const db = (a >>> 16 & 255) - (b >>> 16 & 255);
|
|
242
|
+
const da = (a >>> 24 & 255) - (b >>> 24 & 255);
|
|
243
|
+
return dr * dr + dg * dg + db * db + da * da;
|
|
244
|
+
}
|
|
245
|
+
function lerpColor32(a, b, t) {
|
|
246
|
+
const r = (a & 255) + t * ((b & 255) - (a & 255));
|
|
247
|
+
const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
|
|
248
|
+
const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
|
|
249
|
+
const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
|
|
250
|
+
return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
|
|
251
|
+
}
|
|
252
|
+
function lerpColor32Fast(src, dst, w) {
|
|
253
|
+
const invA = 255 - w;
|
|
254
|
+
const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
|
|
255
|
+
const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
|
|
256
|
+
return (rb | ga << 8) >>> 0;
|
|
257
|
+
}
|
|
258
|
+
function color32ToHex(color) {
|
|
259
|
+
const r = (color & 255).toString(16).padStart(2, "0");
|
|
260
|
+
const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
|
|
261
|
+
const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
|
|
262
|
+
const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
|
|
263
|
+
return `#${r}${g}${b}${a}`;
|
|
264
|
+
}
|
|
265
|
+
function color32ToCssRGBA(color) {
|
|
266
|
+
const r = color & 255;
|
|
267
|
+
const g = color >>> 8 & 255;
|
|
268
|
+
const b = color >>> 16 & 255;
|
|
269
|
+
const a = color >>> 24 & 255;
|
|
270
|
+
const alpha = Number((a / 255).toFixed(3));
|
|
271
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
272
|
+
}
|
|
194
273
|
|
|
195
|
-
// src/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
274
|
+
// src/Internal/resolveClipping.ts
|
|
275
|
+
var makeClippedRect = () => ({
|
|
276
|
+
x: 0,
|
|
277
|
+
y: 0,
|
|
278
|
+
w: 0,
|
|
279
|
+
h: 0,
|
|
280
|
+
inBounds: false
|
|
281
|
+
});
|
|
282
|
+
var makeClippedBlit = () => ({
|
|
283
|
+
x: 0,
|
|
284
|
+
y: 0,
|
|
285
|
+
sx: 0,
|
|
286
|
+
sy: 0,
|
|
287
|
+
w: 0,
|
|
288
|
+
h: 0,
|
|
289
|
+
inBounds: false
|
|
290
|
+
});
|
|
291
|
+
function resolveRectClipping(x, y, w, h, boundaryW, boundaryH, out) {
|
|
292
|
+
if (x < 0) {
|
|
293
|
+
w += x;
|
|
294
|
+
x = 0;
|
|
295
|
+
}
|
|
296
|
+
if (y < 0) {
|
|
297
|
+
h += y;
|
|
298
|
+
y = 0;
|
|
299
|
+
}
|
|
300
|
+
const actualW = Math.min(w, boundaryW - x);
|
|
301
|
+
const actualH = Math.min(h, boundaryH - y);
|
|
302
|
+
if (actualW <= 0 || actualH <= 0) {
|
|
303
|
+
out.inBounds = false;
|
|
304
|
+
return out;
|
|
305
|
+
}
|
|
306
|
+
out.x = x;
|
|
307
|
+
out.y = y;
|
|
308
|
+
out.w = actualW;
|
|
309
|
+
out.h = actualH;
|
|
310
|
+
out.inBounds = true;
|
|
311
|
+
return out;
|
|
312
|
+
}
|
|
313
|
+
function resolveBlitClipping(x, y, sx, sy, w, h, dstW, dstH, srcW, srcH, out) {
|
|
314
|
+
if (sx < 0) {
|
|
315
|
+
x -= sx;
|
|
316
|
+
w += sx;
|
|
317
|
+
sx = 0;
|
|
318
|
+
}
|
|
319
|
+
if (sy < 0) {
|
|
320
|
+
y -= sy;
|
|
321
|
+
h += sy;
|
|
322
|
+
sy = 0;
|
|
323
|
+
}
|
|
324
|
+
w = Math.min(w, srcW - sx);
|
|
325
|
+
h = Math.min(h, srcH - sy);
|
|
326
|
+
if (x < 0) {
|
|
327
|
+
sx -= x;
|
|
328
|
+
w += x;
|
|
329
|
+
x = 0;
|
|
330
|
+
}
|
|
331
|
+
if (y < 0) {
|
|
332
|
+
sy -= y;
|
|
333
|
+
h += y;
|
|
334
|
+
y = 0;
|
|
335
|
+
}
|
|
336
|
+
const actualW = Math.min(w, dstW - x);
|
|
337
|
+
const actualH = Math.min(h, dstH - y);
|
|
338
|
+
if (actualW <= 0 || actualH <= 0) {
|
|
339
|
+
out.inBounds = false;
|
|
340
|
+
return out;
|
|
341
|
+
}
|
|
342
|
+
out.x = x;
|
|
343
|
+
out.y = y;
|
|
344
|
+
out.sx = sx;
|
|
345
|
+
out.sy = sy;
|
|
346
|
+
out.w = actualW;
|
|
347
|
+
out.h = actualH;
|
|
348
|
+
out.inBounds = true;
|
|
349
|
+
return out;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/ImageData/extractImageDataBuffer.ts
|
|
353
|
+
var SCRATCH_BLIT = makeClippedBlit();
|
|
354
|
+
function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
|
|
355
|
+
const {
|
|
356
|
+
x,
|
|
357
|
+
y,
|
|
358
|
+
w,
|
|
359
|
+
h
|
|
360
|
+
} = typeof _x === "object" ? _x : {
|
|
361
|
+
x: _x,
|
|
362
|
+
y: _y,
|
|
363
|
+
w: _w,
|
|
364
|
+
h: _h
|
|
365
|
+
};
|
|
366
|
+
const {
|
|
367
|
+
width: srcW,
|
|
368
|
+
height: srcH,
|
|
369
|
+
data: src
|
|
370
|
+
} = imageData;
|
|
371
|
+
if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
|
|
372
|
+
const out = new Uint8ClampedArray(w * h * 4);
|
|
373
|
+
const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT);
|
|
374
|
+
if (!clip.inBounds) return out;
|
|
375
|
+
const {
|
|
376
|
+
x: dstX,
|
|
377
|
+
y: dstY,
|
|
378
|
+
sx: srcX,
|
|
379
|
+
sy: srcY,
|
|
380
|
+
w: copyW,
|
|
381
|
+
h: copyH
|
|
382
|
+
} = clip;
|
|
383
|
+
const rowLen = copyW * 4;
|
|
384
|
+
for (let row = 0; row < copyH; row++) {
|
|
385
|
+
const srcStart = ((srcY + row) * srcW + srcX) * 4;
|
|
386
|
+
const dstStart = ((dstY + row) * w + dstX) * 4;
|
|
387
|
+
out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
388
|
+
}
|
|
389
|
+
return out;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/Mask/extractMask.ts
|
|
393
|
+
function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
394
|
+
let finalX;
|
|
395
|
+
let finalY;
|
|
396
|
+
let finalW;
|
|
397
|
+
let finalH;
|
|
398
|
+
if (typeof xOrRect === "object") {
|
|
399
|
+
finalX = xOrRect.x;
|
|
400
|
+
finalY = xOrRect.y;
|
|
401
|
+
finalW = xOrRect.w;
|
|
402
|
+
finalH = xOrRect.h;
|
|
403
|
+
} else {
|
|
404
|
+
finalX = xOrRect;
|
|
405
|
+
finalY = y;
|
|
406
|
+
finalW = w;
|
|
407
|
+
finalH = h;
|
|
408
|
+
}
|
|
409
|
+
const out = new Uint8Array(finalW * finalH);
|
|
410
|
+
const srcH = mask.length / maskWidth;
|
|
411
|
+
for (let row = 0; row < finalH; row++) {
|
|
412
|
+
const currentSrcY = finalY + row;
|
|
413
|
+
if (currentSrcY < 0 || currentSrcY >= srcH) {
|
|
414
|
+
continue;
|
|
206
415
|
}
|
|
207
|
-
|
|
208
|
-
|
|
416
|
+
const start = Math.max(0, finalX);
|
|
417
|
+
const end = Math.min(maskWidth, finalX + finalW);
|
|
418
|
+
if (start < end) {
|
|
419
|
+
const srcOffset = currentSrcY * maskWidth + start;
|
|
420
|
+
const dstOffset = row * finalW + (start - finalX);
|
|
421
|
+
const count = end - start;
|
|
422
|
+
out.set(mask.subarray(srcOffset, srcOffset + count), dstOffset);
|
|
209
423
|
}
|
|
210
|
-
indexToName[index] = name;
|
|
211
|
-
indexToBlend[index] = blendFn;
|
|
212
|
-
blendToIndex.set(blendFn, index);
|
|
213
|
-
blendToName.set(blendFn, name);
|
|
214
|
-
nameToBlend[name] = blendFn;
|
|
215
|
-
nameToIndex[name] = index;
|
|
216
|
-
};
|
|
217
|
-
for (const [name, index] of Object.entries(blendModes)) {
|
|
218
|
-
const blend = initialEntries[index];
|
|
219
|
-
add(name, index, blend);
|
|
220
424
|
}
|
|
221
|
-
return
|
|
222
|
-
nameToBlend,
|
|
223
|
-
nameToIndex,
|
|
224
|
-
blendToIndex,
|
|
225
|
-
blendToName,
|
|
226
|
-
indexToBlend,
|
|
227
|
-
indexToName,
|
|
228
|
-
indexType: null,
|
|
229
|
-
nameType: null
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// src/BlendModes/blend-modes-fast.ts
|
|
234
|
-
var overwriteFast = overwriteBase;
|
|
235
|
-
var sourceOverFast = (src, dst) => {
|
|
236
|
-
const sa = src >>> 24 & 255;
|
|
237
|
-
if (sa === 255) return src;
|
|
238
|
-
if (sa === 0) return dst;
|
|
239
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
240
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
241
|
-
const da = dst >>> 24 & 255;
|
|
242
|
-
const invA = 255 - sa;
|
|
243
|
-
const r = sr * sa + dr * invA >> 8;
|
|
244
|
-
const g = sg * sa + dg * invA >> 8;
|
|
245
|
-
const b = sb * sa + db * invA >> 8;
|
|
246
|
-
const a = 255 * sa + da * invA >> 8;
|
|
247
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
248
|
-
};
|
|
249
|
-
var darkenFast = (src, dst) => {
|
|
250
|
-
const sa = src >>> 24 & 255;
|
|
251
|
-
if (sa === 0) return dst;
|
|
252
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
253
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
254
|
-
const br = sr < dr ? sr : dr;
|
|
255
|
-
const bg = sg < dg ? sg : dg;
|
|
256
|
-
const bb = sb < db ? sb : db;
|
|
257
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
258
|
-
const invA = 255 - sa;
|
|
259
|
-
const r = br * sa + dr * invA >> 8;
|
|
260
|
-
const g = bg * sa + dg * invA >> 8;
|
|
261
|
-
const b = bb * sa + db * invA >> 8;
|
|
262
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
263
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
264
|
-
};
|
|
265
|
-
var multiplyFast = (src, dst) => {
|
|
266
|
-
const sa = src >>> 24 & 255;
|
|
267
|
-
if (sa === 0) return dst;
|
|
268
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
269
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
270
|
-
const br = sr * dr >> 8;
|
|
271
|
-
const bg = sg * dg >> 8;
|
|
272
|
-
const bb = sb * db >> 8;
|
|
273
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
274
|
-
const invA = 255 - sa;
|
|
275
|
-
const da = dst >>> 24 & 255;
|
|
276
|
-
const r = br * sa + dr * invA >> 8;
|
|
277
|
-
const g = bg * sa + dg * invA >> 8;
|
|
278
|
-
const b = bb * sa + db * invA >> 8;
|
|
279
|
-
const a = 255 * sa + da * invA >> 8;
|
|
280
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
281
|
-
};
|
|
282
|
-
var colorBurnFast = (src, dst) => {
|
|
283
|
-
const sa = src >>> 24 & 255;
|
|
284
|
-
if (sa === 0) return dst;
|
|
285
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
286
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
287
|
-
const br = dr === 255 ? 255 : sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / sr | 0);
|
|
288
|
-
const bg = dg === 255 ? 255 : sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / sg | 0);
|
|
289
|
-
const bb = db === 255 ? 255 : sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / sb | 0);
|
|
290
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
291
|
-
const invA = 255 - sa;
|
|
292
|
-
const da = dst >>> 24 & 255;
|
|
293
|
-
const r = br * sa + dr * invA >> 8;
|
|
294
|
-
const g = bg * sa + dg * invA >> 8;
|
|
295
|
-
const b = bb * sa + db * invA >> 8;
|
|
296
|
-
const a = 255 * sa + da * invA >> 8;
|
|
297
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
298
|
-
};
|
|
299
|
-
var linearBurnFast = (src, dst) => {
|
|
300
|
-
const sa = src >>> 24 & 255;
|
|
301
|
-
if (sa === 0) return dst;
|
|
302
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
303
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
304
|
-
const brU = dr + sr - 255;
|
|
305
|
-
const bgU = dg + sg - 255;
|
|
306
|
-
const bbU = db + sb - 255;
|
|
307
|
-
const br = brU < 0 ? 0 : brU;
|
|
308
|
-
const bg = bgU < 0 ? 0 : bgU;
|
|
309
|
-
const bb = bbU < 0 ? 0 : bbU;
|
|
310
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
311
|
-
const invA = 255 - sa;
|
|
312
|
-
const r = br * sa + dr * invA >> 8;
|
|
313
|
-
const g = bg * sa + dg * invA >> 8;
|
|
314
|
-
const b = bb * sa + db * invA >> 8;
|
|
315
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
316
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
317
|
-
};
|
|
318
|
-
var darkerFast = (src, dst) => {
|
|
319
|
-
const sa = src >>> 24 & 255;
|
|
320
|
-
if (sa === 0) return dst;
|
|
321
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
322
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
323
|
-
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
324
|
-
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
325
|
-
let br, bg, bb;
|
|
326
|
-
if (lumSrc < lumDst) {
|
|
327
|
-
br = sr;
|
|
328
|
-
bg = sg;
|
|
329
|
-
bb = sb;
|
|
330
|
-
} else {
|
|
331
|
-
br = dr;
|
|
332
|
-
bg = dg;
|
|
333
|
-
bb = db;
|
|
334
|
-
}
|
|
335
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
336
|
-
const invA = 255 - sa;
|
|
337
|
-
const r = br * sa + dr * invA >> 8;
|
|
338
|
-
const g = bg * sa + dg * invA >> 8;
|
|
339
|
-
const b = bb * sa + db * invA >> 8;
|
|
340
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
341
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
342
|
-
};
|
|
343
|
-
var lightenFast = (src, dst) => {
|
|
344
|
-
const sa = src >>> 24 & 255;
|
|
345
|
-
if (sa === 0) return dst;
|
|
346
|
-
const br = Math.max(src & 255, dst & 255);
|
|
347
|
-
const bg = Math.max(src >> 8 & 255, dst >> 8 & 255);
|
|
348
|
-
const bb = Math.max(src >> 16 & 255, dst >> 16 & 255);
|
|
349
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
350
|
-
const dr = dst & 255;
|
|
351
|
-
const dg = dst >> 8 & 255;
|
|
352
|
-
const db = dst >> 16 & 255;
|
|
353
|
-
const invA = 255 - sa;
|
|
354
|
-
const r = br * sa + dr * invA >> 8;
|
|
355
|
-
const g = bg * sa + dg * invA >> 8;
|
|
356
|
-
const b = bb * sa + db * invA >> 8;
|
|
357
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
358
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
359
|
-
};
|
|
360
|
-
var screenFast = (src, dst) => {
|
|
361
|
-
const sa = src >>> 24 & 255;
|
|
362
|
-
if (sa === 0) return dst;
|
|
363
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
364
|
-
const br = 255 - ((255 - (src & 255)) * (255 - dr) >> 8);
|
|
365
|
-
const bg = 255 - ((255 - (src >>> 8 & 255)) * (255 - dg) >> 8);
|
|
366
|
-
const bb = 255 - ((255 - (src >>> 16 & 255)) * (255 - db) >> 8);
|
|
367
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
368
|
-
const invA = 255 - sa;
|
|
369
|
-
const r = br * sa + dr * invA >> 8;
|
|
370
|
-
const g = bg * sa + dg * invA >> 8;
|
|
371
|
-
const b = bb * sa + db * invA >> 8;
|
|
372
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
373
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
374
|
-
};
|
|
375
|
-
var colorDodgeFast = (src, dst) => {
|
|
376
|
-
const sa = src >>> 24 & 255;
|
|
377
|
-
if (sa === 0) return dst;
|
|
378
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
379
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
380
|
-
const br = sr === 255 ? 255 : Math.min(255, (dr << 8) / (255 - sr) | 0);
|
|
381
|
-
const bg = sg === 255 ? 255 : Math.min(255, (dg << 8) / (255 - sg) | 0);
|
|
382
|
-
const bb = sb === 255 ? 255 : Math.min(255, (db << 8) / (255 - sb) | 0);
|
|
383
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
384
|
-
const invA = 255 - sa;
|
|
385
|
-
const r = br * sa + dr * invA >> 8;
|
|
386
|
-
const g = bg * sa + dg * invA >> 8;
|
|
387
|
-
const b = bb * sa + db * invA >> 8;
|
|
388
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
389
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
390
|
-
};
|
|
391
|
-
var linearDodgeFast = (src, dst) => {
|
|
392
|
-
const sa = src >>> 24 & 255;
|
|
393
|
-
if (sa === 0) return dst;
|
|
394
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
395
|
-
const brU = (src & 255) + dr;
|
|
396
|
-
const bgU = (src >>> 8 & 255) + dg;
|
|
397
|
-
const bbU = (src >>> 16 & 255) + db;
|
|
398
|
-
const br = brU > 255 ? 255 : brU;
|
|
399
|
-
const bg = bgU > 255 ? 255 : bgU;
|
|
400
|
-
const bb = bbU > 255 ? 255 : bbU;
|
|
401
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
402
|
-
const invA = 255 - sa;
|
|
403
|
-
const r = br * sa + dr * invA >> 8;
|
|
404
|
-
const g = bg * sa + dg * invA >> 8;
|
|
405
|
-
const b = bb * sa + db * invA >> 8;
|
|
406
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
407
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
408
|
-
};
|
|
409
|
-
var lighterFast = (src, dst) => {
|
|
410
|
-
const sa = src >>> 24 & 255;
|
|
411
|
-
if (sa === 0) return dst;
|
|
412
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
413
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
414
|
-
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
415
|
-
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
416
|
-
let br, bg, bb;
|
|
417
|
-
if (lumSrc > lumDst) {
|
|
418
|
-
br = sr;
|
|
419
|
-
bg = sg;
|
|
420
|
-
bb = sb;
|
|
421
|
-
} else {
|
|
422
|
-
br = dr;
|
|
423
|
-
bg = dg;
|
|
424
|
-
bb = db;
|
|
425
|
-
}
|
|
426
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
427
|
-
const invA = 255 - sa;
|
|
428
|
-
const r = br * sa + dr * invA >> 8;
|
|
429
|
-
const g = bg * sa + dg * invA >> 8;
|
|
430
|
-
const b = bb * sa + db * invA >> 8;
|
|
431
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
432
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
433
|
-
};
|
|
434
|
-
var overlayFast = (src, dst) => {
|
|
435
|
-
const sa = src >>> 24 & 255;
|
|
436
|
-
if (sa === 0) return dst;
|
|
437
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
438
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
439
|
-
const br = dr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
440
|
-
const bg = dg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
441
|
-
const bb = db < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
442
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
443
|
-
const invA = 255 - sa;
|
|
444
|
-
const r = br * sa + dr * invA >> 8;
|
|
445
|
-
const g = bg * sa + dg * invA >> 8;
|
|
446
|
-
const b = bb * sa + db * invA >> 8;
|
|
447
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
448
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
449
|
-
};
|
|
450
|
-
var softLightFast = (src, dst) => {
|
|
451
|
-
const sa = src >>> 24 & 255;
|
|
452
|
-
if (sa === 0) return dst;
|
|
453
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
454
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
455
|
-
const br = (255 - dr) * (sr * dr >> 8) + dr * (255 - ((255 - sr) * (255 - dr) >> 8)) >> 8;
|
|
456
|
-
const bg = (255 - dg) * (sg * dg >> 8) + dg * (255 - ((255 - sg) * (255 - dg) >> 8)) >> 8;
|
|
457
|
-
const bb = (255 - db) * (sb * db >> 8) + db * (255 - ((255 - sb) * (255 - db) >> 8)) >> 8;
|
|
458
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
459
|
-
const invA = 255 - sa;
|
|
460
|
-
const r = br * sa + dr * invA >> 8;
|
|
461
|
-
const g = bg * sa + dg * invA >> 8;
|
|
462
|
-
const b = bb * sa + db * invA >> 8;
|
|
463
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
464
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
465
|
-
};
|
|
466
|
-
var hardLightFast = (src, dst) => {
|
|
467
|
-
const sa = src >>> 24 & 255;
|
|
468
|
-
if (sa === 0) return dst;
|
|
469
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
470
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
471
|
-
const br = sr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
472
|
-
const bg = sg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
473
|
-
const bb = sb < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
474
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
475
|
-
const invA = 255 - sa;
|
|
476
|
-
const r = br * sa + dr * invA >> 8;
|
|
477
|
-
const g = bg * sa + dg * invA >> 8;
|
|
478
|
-
const b = bb * sa + db * invA >> 8;
|
|
479
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
480
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
481
|
-
};
|
|
482
|
-
var vividLightFast = (src, dst) => {
|
|
483
|
-
const sa = src >>> 24 & 255;
|
|
484
|
-
if (sa === 0) return dst;
|
|
485
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
486
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
487
|
-
const br = sr < 128 ? sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / (2 * sr) | 0) : sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr)) | 0);
|
|
488
|
-
const bg = sg < 128 ? sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / (2 * sg) | 0) : sg === 255 ? 255 : Math.min(255, (dg << 8) / (2 * (255 - sg)) | 0);
|
|
489
|
-
const bb = sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / (2 * sb) | 0) : sb === 255 ? 255 : Math.min(255, (db << 8) / (2 * (255 - sb)) | 0);
|
|
490
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
491
|
-
const invA = 255 - sa;
|
|
492
|
-
const r = br * sa + dr * invA >> 8;
|
|
493
|
-
const g = bg * sa + dg * invA >> 8;
|
|
494
|
-
const b = bb * sa + db * invA >> 8;
|
|
495
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
496
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
497
|
-
};
|
|
498
|
-
var linearLightFast = (src, dst) => {
|
|
499
|
-
const sa = src >>> 24 & 255;
|
|
500
|
-
if (sa === 0) return dst;
|
|
501
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
502
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
503
|
-
const brU = dr + 2 * sr - 255;
|
|
504
|
-
const bgU = dg + 2 * sg - 255;
|
|
505
|
-
const bbU = db + 2 * sb - 255;
|
|
506
|
-
const br = brU < 0 ? 0 : brU > 255 ? 255 : brU;
|
|
507
|
-
const bg = bgU < 0 ? 0 : bgU > 255 ? 255 : bgU;
|
|
508
|
-
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU;
|
|
509
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
510
|
-
const invA = 255 - sa;
|
|
511
|
-
const r = br * sa + dr * invA >> 8;
|
|
512
|
-
const g = bg * sa + dg * invA >> 8;
|
|
513
|
-
const b = bb * sa + db * invA >> 8;
|
|
514
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
515
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
516
|
-
};
|
|
517
|
-
var pinLightFast = (src, dst) => {
|
|
518
|
-
const sa = src >>> 24 & 255;
|
|
519
|
-
if (sa === 0) return dst;
|
|
520
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
521
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
522
|
-
const br = sr < 128 ? dr < 2 * sr ? dr : 2 * sr : dr > 2 * sr - 256 ? dr : 2 * sr - 256;
|
|
523
|
-
const bg = sg < 128 ? dg < 2 * sg ? dg : 2 * sg : dg > 2 * sg - 256 ? dg : 2 * sg - 256;
|
|
524
|
-
const bb = sb < 128 ? db < 2 * sb ? db : 2 * sb : db > 2 * sb - 256 ? db : 2 * sb - 256;
|
|
525
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
526
|
-
const invA = 255 - sa;
|
|
527
|
-
const r = br * sa + dr * invA >> 8;
|
|
528
|
-
const g = bg * sa + dg * invA >> 8;
|
|
529
|
-
const b = bb * sa + db * invA >> 8;
|
|
530
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
531
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
532
|
-
};
|
|
533
|
-
var hardMixFast = (src, dst) => {
|
|
534
|
-
const sa = src >>> 24 & 255;
|
|
535
|
-
if (sa === 0) return dst;
|
|
536
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
537
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
538
|
-
const br = (sr < 128 ? sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / (2 * sr) | 0) : sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr)) | 0)) < 128 ? 0 : 255;
|
|
539
|
-
const bg = (sg < 128 ? sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / (2 * sg) | 0) : sg === 255 ? 255 : Math.min(255, (dg << 8) / (2 * (255 - sg)) | 0)) < 128 ? 0 : 255;
|
|
540
|
-
const bb = (sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / (2 * sb) | 0) : sb === 255 ? 255 : Math.min(255, (db << 8) / (2 * (255 - sb)) | 0)) < 128 ? 0 : 255;
|
|
541
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
542
|
-
const invA = 255 - sa;
|
|
543
|
-
const r = br * sa + dr * invA >> 8;
|
|
544
|
-
const g = bg * sa + dg * invA >> 8;
|
|
545
|
-
const b = bb * sa + db * invA >> 8;
|
|
546
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
547
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
548
|
-
};
|
|
549
|
-
var differenceFast = (src, dst) => {
|
|
550
|
-
const sa = src >>> 24 & 255;
|
|
551
|
-
if (sa === 0) return dst;
|
|
552
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
553
|
-
const brD = (src & 255) - dr;
|
|
554
|
-
const bgD = (src >>> 8 & 255) - dg;
|
|
555
|
-
const bbD = (src >>> 16 & 255) - db;
|
|
556
|
-
const br = brD < 0 ? -brD : brD;
|
|
557
|
-
const bg = bgD < 0 ? -bgD : bgD;
|
|
558
|
-
const bb = bbD < 0 ? -bbD : bbD;
|
|
559
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
560
|
-
const invA = 255 - sa;
|
|
561
|
-
const r = br * sa + dr * invA >> 8;
|
|
562
|
-
const g = bg * sa + dg * invA >> 8;
|
|
563
|
-
const b = bb * sa + db * invA >> 8;
|
|
564
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
565
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
566
|
-
};
|
|
567
|
-
var exclusionFast = (src, dst) => {
|
|
568
|
-
const sa = src >>> 24 & 255;
|
|
569
|
-
if (sa === 0) return dst;
|
|
570
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
571
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
572
|
-
const br = dr + sr - (dr * sr >> 7);
|
|
573
|
-
const bg = dg + sg - (dg * sg >> 7);
|
|
574
|
-
const bb = db + sb - (db * sb >> 7);
|
|
575
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
576
|
-
const invA = 255 - sa;
|
|
577
|
-
const r = br * sa + dr * invA >> 8;
|
|
578
|
-
const g = bg * sa + dg * invA >> 8;
|
|
579
|
-
const b = bb * sa + db * invA >> 8;
|
|
580
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
581
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
582
|
-
};
|
|
583
|
-
var subtractFast = (src, dst) => {
|
|
584
|
-
const sa = src >>> 24 & 255;
|
|
585
|
-
if (sa === 0) return dst;
|
|
586
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
587
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
588
|
-
const brU = dr - sr;
|
|
589
|
-
const bgU = dg - sg;
|
|
590
|
-
const bbU = db - sb;
|
|
591
|
-
const br = brU < 0 ? 0 : brU;
|
|
592
|
-
const bg = bgU < 0 ? 0 : bgU;
|
|
593
|
-
const bb = bbU < 0 ? 0 : bbU;
|
|
594
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
595
|
-
const invA = 255 - sa;
|
|
596
|
-
const r = br * sa + dr * invA >> 8;
|
|
597
|
-
const g = bg * sa + dg * invA >> 8;
|
|
598
|
-
const b = bb * sa + db * invA >> 8;
|
|
599
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
600
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
601
|
-
};
|
|
602
|
-
var divideFast = (src, dst) => {
|
|
603
|
-
const sa = src >>> 24 & 255;
|
|
604
|
-
if (sa === 0) return dst;
|
|
605
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
606
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
607
|
-
const br = sr === 0 ? 255 : Math.min(255, (dr << 8) / sr | 0);
|
|
608
|
-
const bg = sg === 0 ? 255 : Math.min(255, (dg << 8) / sg | 0);
|
|
609
|
-
const bb = sb === 0 ? 255 : Math.min(255, (db << 8) / sb | 0);
|
|
610
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
611
|
-
const invA = 255 - sa;
|
|
612
|
-
const r = br * sa + dr * invA >> 8;
|
|
613
|
-
const g = bg * sa + dg * invA >> 8;
|
|
614
|
-
const b = bb * sa + db * invA >> 8;
|
|
615
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
616
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
617
|
-
};
|
|
618
|
-
var BASE_FAST_BLEND_MODE_FUNCTIONS = {
|
|
619
|
-
[BaseBlendMode.overwrite]: overwriteFast,
|
|
620
|
-
[BaseBlendMode.sourceOver]: sourceOverFast,
|
|
621
|
-
[BaseBlendMode.darken]: darkenFast,
|
|
622
|
-
[BaseBlendMode.multiply]: multiplyFast,
|
|
623
|
-
[BaseBlendMode.colorBurn]: colorBurnFast,
|
|
624
|
-
[BaseBlendMode.linearBurn]: linearBurnFast,
|
|
625
|
-
[BaseBlendMode.darkerColor]: darkerFast,
|
|
626
|
-
[BaseBlendMode.lighten]: lightenFast,
|
|
627
|
-
[BaseBlendMode.screen]: screenFast,
|
|
628
|
-
[BaseBlendMode.colorDodge]: colorDodgeFast,
|
|
629
|
-
[BaseBlendMode.linearDodge]: linearDodgeFast,
|
|
630
|
-
[BaseBlendMode.lighterColor]: lighterFast,
|
|
631
|
-
[BaseBlendMode.overlay]: overlayFast,
|
|
632
|
-
[BaseBlendMode.softLight]: softLightFast,
|
|
633
|
-
[BaseBlendMode.hardLight]: hardLightFast,
|
|
634
|
-
[BaseBlendMode.vividLight]: vividLightFast,
|
|
635
|
-
[BaseBlendMode.linearLight]: linearLightFast,
|
|
636
|
-
[BaseBlendMode.pinLight]: pinLightFast,
|
|
637
|
-
[BaseBlendMode.hardMix]: hardMixFast,
|
|
638
|
-
[BaseBlendMode.difference]: differenceFast,
|
|
639
|
-
[BaseBlendMode.exclusion]: exclusionFast,
|
|
640
|
-
[BaseBlendMode.subtract]: subtractFast,
|
|
641
|
-
[BaseBlendMode.divide]: divideFast
|
|
642
|
-
};
|
|
643
|
-
function makeFastBlendModeRegistry() {
|
|
644
|
-
return makeBlendModeRegistry(BaseBlendMode, BASE_FAST_BLEND_MODE_FUNCTIONS);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// src/_types.ts
|
|
648
|
-
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
649
|
-
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
650
|
-
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
651
|
-
return MaskType2;
|
|
652
|
-
})(MaskType || {});
|
|
653
|
-
|
|
654
|
-
// src/color.ts
|
|
655
|
-
function packColor(r, g, b, a) {
|
|
656
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
657
|
-
}
|
|
658
|
-
function packRGBA({ r, g, b, a }) {
|
|
659
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
660
|
-
}
|
|
661
|
-
var unpackRed = (packed) => packed >>> 0 & 255;
|
|
662
|
-
var unpackGreen = (packed) => packed >>> 8 & 255;
|
|
663
|
-
var unpackBlue = (packed) => packed >>> 16 & 255;
|
|
664
|
-
var unpackAlpha = (packed) => packed >>> 24 & 255;
|
|
665
|
-
function unpackColor(packed) {
|
|
666
|
-
return {
|
|
667
|
-
r: packed >>> 0 & 255,
|
|
668
|
-
g: packed >>> 8 & 255,
|
|
669
|
-
b: packed >>> 16 & 255,
|
|
670
|
-
a: packed >>> 24 & 255
|
|
671
|
-
};
|
|
672
|
-
}
|
|
673
|
-
var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
|
|
674
|
-
function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
|
|
675
|
-
scratch.r = packed >>> 0 & 255;
|
|
676
|
-
scratch.g = packed >>> 8 & 255;
|
|
677
|
-
scratch.b = packed >>> 16 & 255;
|
|
678
|
-
scratch.a = packed >>> 24 & 255;
|
|
679
|
-
return scratch;
|
|
680
|
-
}
|
|
681
|
-
function colorDistance(a, b) {
|
|
682
|
-
const dr = (a & 255) - (b & 255);
|
|
683
|
-
const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
|
|
684
|
-
const db = (a >>> 16 & 255) - (b >>> 16 & 255);
|
|
685
|
-
const da = (a >>> 24 & 255) - (b >>> 24 & 255);
|
|
686
|
-
return dr * dr + dg * dg + db * db + da * da;
|
|
687
|
-
}
|
|
688
|
-
function lerpColor32(a, b, t) {
|
|
689
|
-
const r = (a & 255) + t * ((b & 255) - (a & 255));
|
|
690
|
-
const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
|
|
691
|
-
const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
|
|
692
|
-
const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
|
|
693
|
-
return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
|
|
694
|
-
}
|
|
695
|
-
function lerpColor32Fast(src, dst, w) {
|
|
696
|
-
const invA = 255 - w;
|
|
697
|
-
const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
|
|
698
|
-
const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
|
|
699
|
-
return (rb | ga << 8) >>> 0;
|
|
700
|
-
}
|
|
701
|
-
function color32ToHex(color) {
|
|
702
|
-
const r = (color & 255).toString(16).padStart(2, "0");
|
|
703
|
-
const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
|
|
704
|
-
const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
|
|
705
|
-
const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
|
|
706
|
-
return `#${r}${g}${b}${a}`;
|
|
707
|
-
}
|
|
708
|
-
function color32ToCssRGBA(color) {
|
|
709
|
-
const r = color & 255;
|
|
710
|
-
const g = color >>> 8 & 255;
|
|
711
|
-
const b = color >>> 16 & 255;
|
|
712
|
-
const a = color >>> 24 & 255;
|
|
713
|
-
const alpha = Number((a / 255).toFixed(3));
|
|
714
|
-
return `rgba(${r},${g},${b},${alpha})`;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// src/ImageData/extractImageDataBuffer.ts
|
|
718
|
-
function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
|
|
719
|
-
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
720
|
-
const { width: srcW, height: srcH, data: src } = imageData;
|
|
721
|
-
if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
|
|
722
|
-
const out = new Uint8ClampedArray(w * h * 4);
|
|
723
|
-
const x0 = Math.max(0, x);
|
|
724
|
-
const y0 = Math.max(0, y);
|
|
725
|
-
const x1 = Math.min(srcW, x + w);
|
|
726
|
-
const y1 = Math.min(srcH, y + h);
|
|
727
|
-
if (x1 <= x0 || y1 <= y0) return out;
|
|
728
|
-
for (let row = 0; row < y1 - y0; row++) {
|
|
729
|
-
const srcRow = y0 + row;
|
|
730
|
-
const srcStart = (srcRow * srcW + x0) * 4;
|
|
731
|
-
const rowLen = (x1 - x0) * 4;
|
|
732
|
-
const dstRow = y0 - y + row;
|
|
733
|
-
const dstCol = x0 - x;
|
|
734
|
-
const dstStart = (dstRow * w + dstCol) * 4;
|
|
735
|
-
out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
736
|
-
}
|
|
737
|
-
return out;
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// src/Mask/extractMask.ts
|
|
741
|
-
function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
742
|
-
let finalX;
|
|
743
|
-
let finalY;
|
|
744
|
-
let finalW;
|
|
745
|
-
let finalH;
|
|
746
|
-
if (typeof xOrRect === "object") {
|
|
747
|
-
finalX = xOrRect.x;
|
|
748
|
-
finalY = xOrRect.y;
|
|
749
|
-
finalW = xOrRect.w;
|
|
750
|
-
finalH = xOrRect.h;
|
|
751
|
-
} else {
|
|
752
|
-
finalX = xOrRect;
|
|
753
|
-
finalY = y;
|
|
754
|
-
finalW = w;
|
|
755
|
-
finalH = h;
|
|
756
|
-
}
|
|
757
|
-
const out = new Uint8Array(finalW * finalH);
|
|
758
|
-
const srcH = mask.length / maskWidth;
|
|
759
|
-
for (let row = 0; row < finalH; row++) {
|
|
760
|
-
const currentSrcY = finalY + row;
|
|
761
|
-
if (currentSrcY < 0 || currentSrcY >= srcH) {
|
|
762
|
-
continue;
|
|
763
|
-
}
|
|
764
|
-
const start = Math.max(0, finalX);
|
|
765
|
-
const end = Math.min(maskWidth, finalX + finalW);
|
|
766
|
-
if (start < end) {
|
|
767
|
-
const srcOffset = currentSrcY * maskWidth + start;
|
|
768
|
-
const dstOffset = row * finalW + (start - finalX);
|
|
769
|
-
const count = end - start;
|
|
770
|
-
out.set(
|
|
771
|
-
mask.subarray(srcOffset, srcOffset + count),
|
|
772
|
-
dstOffset
|
|
773
|
-
);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
return out;
|
|
425
|
+
return out;
|
|
777
426
|
}
|
|
778
427
|
|
|
779
428
|
// src/Rect/trimRectBounds.ts
|
|
@@ -783,14 +432,8 @@ function trimRectBounds(target, bounds) {
|
|
|
783
432
|
const originalW = target.w;
|
|
784
433
|
const intersectedX = Math.max(target.x, bounds.x);
|
|
785
434
|
const intersectedY = Math.max(target.y, bounds.y);
|
|
786
|
-
const intersectedMaxX = Math.min(
|
|
787
|
-
|
|
788
|
-
bounds.x + bounds.w
|
|
789
|
-
);
|
|
790
|
-
const intersectedMaxY = Math.min(
|
|
791
|
-
target.y + target.h,
|
|
792
|
-
bounds.y + bounds.h
|
|
793
|
-
);
|
|
435
|
+
const intersectedMaxX = Math.min(target.x + target.w, bounds.x + bounds.w);
|
|
436
|
+
const intersectedMaxY = Math.min(target.y + target.h, bounds.y + bounds.h);
|
|
794
437
|
if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
|
|
795
438
|
target.w = 0;
|
|
796
439
|
target.h = 0;
|
|
@@ -808,14 +451,7 @@ function trimRectBounds(target, bounds) {
|
|
|
808
451
|
target.w = intersectedW;
|
|
809
452
|
target.h = intersectedH;
|
|
810
453
|
if ("mask" in target && target.mask) {
|
|
811
|
-
const currentMask = extractMask(
|
|
812
|
-
target.mask,
|
|
813
|
-
originalW,
|
|
814
|
-
offsetX,
|
|
815
|
-
offsetY,
|
|
816
|
-
intersectedW,
|
|
817
|
-
intersectedH
|
|
818
|
-
);
|
|
454
|
+
const currentMask = extractMask(target.mask, originalW, offsetX, offsetY, intersectedW, intersectedH);
|
|
819
455
|
let minX = intersectedW;
|
|
820
456
|
let maxX = -1;
|
|
821
457
|
let minY = intersectedH;
|
|
@@ -839,14 +475,7 @@ function trimRectBounds(target, bounds) {
|
|
|
839
475
|
const finalW = maxX - minX + 1;
|
|
840
476
|
const finalH = maxY - minY + 1;
|
|
841
477
|
if (finalW !== intersectedW || finalH !== intersectedH) {
|
|
842
|
-
target.mask = extractMask(
|
|
843
|
-
currentMask,
|
|
844
|
-
intersectedW,
|
|
845
|
-
minX,
|
|
846
|
-
minY,
|
|
847
|
-
finalW,
|
|
848
|
-
finalH
|
|
849
|
-
);
|
|
478
|
+
target.mask = extractMask(currentMask, intersectedW, minX, minY, finalW, finalH);
|
|
850
479
|
target.x += minX;
|
|
851
480
|
target.y += minY;
|
|
852
481
|
target.w = finalW;
|
|
@@ -869,11 +498,7 @@ function floodFillSelection(img, startX, startY, {
|
|
|
869
498
|
data32 = img.data32;
|
|
870
499
|
imageData = img.imageData;
|
|
871
500
|
} else {
|
|
872
|
-
data32 = new Uint32Array(
|
|
873
|
-
img.data.buffer,
|
|
874
|
-
img.data.byteOffset,
|
|
875
|
-
img.data.byteLength >> 2
|
|
876
|
-
);
|
|
501
|
+
data32 = new Uint32Array(img.data.buffer, img.data.byteOffset, img.data.byteLength >> 2);
|
|
877
502
|
imageData = img;
|
|
878
503
|
}
|
|
879
504
|
const {
|
|
@@ -948,59 +573,537 @@ function floodFillSelection(img, startX, startY, {
|
|
|
948
573
|
}
|
|
949
574
|
}
|
|
950
575
|
} else {
|
|
951
|
-
for (let y = yMin; y <= yMax; y++) {
|
|
952
|
-
for (let x = xMin; x <= xMax; x++) {
|
|
953
|
-
const color = data32[y * width + x];
|
|
954
|
-
if (colorDistance(color, baseColor) <= tolerance) {
|
|
955
|
-
matchX[matchCount] = x;
|
|
956
|
-
matchY[matchCount] = y;
|
|
957
|
-
matchCount++;
|
|
958
|
-
if (x < minX) minX = x;
|
|
959
|
-
if (x > maxX) maxX = x;
|
|
960
|
-
if (y < minY) minY = y;
|
|
961
|
-
if (y > maxY) maxY = y;
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
if (matchCount === 0) {
|
|
967
|
-
return null;
|
|
576
|
+
for (let y = yMin; y <= yMax; y++) {
|
|
577
|
+
for (let x = xMin; x <= xMax; x++) {
|
|
578
|
+
const color = data32[y * width + x];
|
|
579
|
+
if (colorDistance(color, baseColor) <= tolerance) {
|
|
580
|
+
matchX[matchCount] = x;
|
|
581
|
+
matchY[matchCount] = y;
|
|
582
|
+
matchCount++;
|
|
583
|
+
if (x < minX) minX = x;
|
|
584
|
+
if (x > maxX) maxX = x;
|
|
585
|
+
if (y < minY) minY = y;
|
|
586
|
+
if (y > maxY) maxY = y;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (matchCount === 0) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
const selectionRect = {
|
|
595
|
+
x: minX,
|
|
596
|
+
y: minY,
|
|
597
|
+
w: maxX - minX + 1,
|
|
598
|
+
h: maxY - minY + 1,
|
|
599
|
+
mask: new Uint8Array((maxX - minX + 1) * (maxY - minY + 1)),
|
|
600
|
+
maskType: 1 /* BINARY */
|
|
601
|
+
};
|
|
602
|
+
const sw = selectionRect.w;
|
|
603
|
+
const sh = selectionRect.h;
|
|
604
|
+
const finalMask = selectionRect.mask;
|
|
605
|
+
for (let i = 0; i < matchCount; i++) {
|
|
606
|
+
const mx = matchX[i] - selectionRect.x;
|
|
607
|
+
const my = matchY[i] - selectionRect.y;
|
|
608
|
+
if (mx >= 0 && mx < sw && my >= 0 && my < sh) {
|
|
609
|
+
finalMask[my * sw + mx] = 1;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
trimRectBounds(selectionRect, {
|
|
613
|
+
x: 0,
|
|
614
|
+
y: 0,
|
|
615
|
+
w: width,
|
|
616
|
+
h: height
|
|
617
|
+
});
|
|
618
|
+
const extracted = extractImageDataBuffer(imageData, selectionRect.x, selectionRect.y, selectionRect.w, selectionRect.h);
|
|
619
|
+
return {
|
|
620
|
+
startX,
|
|
621
|
+
startY,
|
|
622
|
+
selectionRect,
|
|
623
|
+
pixels: extracted
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// src/BlendModes/blend-modes.ts
|
|
628
|
+
var BaseBlendMode = {
|
|
629
|
+
overwrite: 0,
|
|
630
|
+
sourceOver: 1,
|
|
631
|
+
darken: 2,
|
|
632
|
+
multiply: 3,
|
|
633
|
+
colorBurn: 4,
|
|
634
|
+
linearBurn: 5,
|
|
635
|
+
darkerColor: 6,
|
|
636
|
+
lighten: 7,
|
|
637
|
+
screen: 8,
|
|
638
|
+
colorDodge: 9,
|
|
639
|
+
linearDodge: 10,
|
|
640
|
+
lighterColor: 11,
|
|
641
|
+
overlay: 12,
|
|
642
|
+
softLight: 13,
|
|
643
|
+
hardLight: 14,
|
|
644
|
+
vividLight: 15,
|
|
645
|
+
linearLight: 16,
|
|
646
|
+
pinLight: 17,
|
|
647
|
+
hardMix: 18,
|
|
648
|
+
difference: 19,
|
|
649
|
+
exclusion: 20,
|
|
650
|
+
subtract: 21,
|
|
651
|
+
divide: 22
|
|
652
|
+
};
|
|
653
|
+
var overwriteBase = (src, _dst) => src;
|
|
654
|
+
overwriteBase.isOverwrite = true;
|
|
655
|
+
|
|
656
|
+
// src/BlendModes/BlendModeRegistry.ts
|
|
657
|
+
function makeBlendModeRegistry(blendModes, initialEntries, registryName = "anonymous") {
|
|
658
|
+
const blendToName = /* @__PURE__ */ new Map();
|
|
659
|
+
const blendToIndex = /* @__PURE__ */ new Map();
|
|
660
|
+
const indexToName = [];
|
|
661
|
+
const indexToBlend = [];
|
|
662
|
+
const nameToBlend = {};
|
|
663
|
+
const nameToIndex = {};
|
|
664
|
+
const add = (name, index, blendFn) => {
|
|
665
|
+
if (!Number.isFinite(index)) {
|
|
666
|
+
throw new Error(`Index "${index}" is not a number. Attempting to add name: "${name}", index: "${index}"`);
|
|
667
|
+
}
|
|
668
|
+
if (indexToBlend[index]) {
|
|
669
|
+
throw new Error(`Blend Mode index: ${index} is already used. Attempting to add name: "${name}", index: "${index}"`);
|
|
670
|
+
}
|
|
671
|
+
indexToName[index] = name;
|
|
672
|
+
indexToBlend[index] = blendFn;
|
|
673
|
+
blendToIndex.set(blendFn, index);
|
|
674
|
+
blendToName.set(blendFn, name);
|
|
675
|
+
nameToBlend[name] = blendFn;
|
|
676
|
+
nameToIndex[name] = index;
|
|
677
|
+
};
|
|
678
|
+
for (const [name, index] of Object.entries(blendModes)) {
|
|
679
|
+
const blend = initialEntries[index];
|
|
680
|
+
add(name, index, blend);
|
|
681
|
+
}
|
|
682
|
+
return {
|
|
683
|
+
registryName,
|
|
684
|
+
nameToBlend,
|
|
685
|
+
nameToIndex,
|
|
686
|
+
blendToIndex,
|
|
687
|
+
blendToName,
|
|
688
|
+
indexToBlend,
|
|
689
|
+
indexToName,
|
|
690
|
+
indexType: null,
|
|
691
|
+
nameType: null
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// src/BlendModes/blend-modes-fast.ts
|
|
696
|
+
var overwriteFast = overwriteBase;
|
|
697
|
+
var sourceOverFast = (src, dst) => {
|
|
698
|
+
const sa = src >>> 24 & 255;
|
|
699
|
+
if (sa === 255) return src;
|
|
700
|
+
if (sa === 0) return dst;
|
|
701
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
702
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
703
|
+
const da = dst >>> 24 & 255;
|
|
704
|
+
const invA = 255 - sa;
|
|
705
|
+
const r = sr * sa + dr * invA >> 8;
|
|
706
|
+
const g = sg * sa + dg * invA >> 8;
|
|
707
|
+
const b = sb * sa + db * invA >> 8;
|
|
708
|
+
const a = 255 * sa + da * invA >> 8;
|
|
709
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
710
|
+
};
|
|
711
|
+
var darkenFast = (src, dst) => {
|
|
712
|
+
const sa = src >>> 24 & 255;
|
|
713
|
+
if (sa === 0) return dst;
|
|
714
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
715
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
716
|
+
const br = sr < dr ? sr : dr;
|
|
717
|
+
const bg = sg < dg ? sg : dg;
|
|
718
|
+
const bb = sb < db ? sb : db;
|
|
719
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
720
|
+
const invA = 255 - sa;
|
|
721
|
+
const r = br * sa + dr * invA >> 8;
|
|
722
|
+
const g = bg * sa + dg * invA >> 8;
|
|
723
|
+
const b = bb * sa + db * invA >> 8;
|
|
724
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
725
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
726
|
+
};
|
|
727
|
+
var multiplyFast = (src, dst) => {
|
|
728
|
+
const sa = src >>> 24 & 255;
|
|
729
|
+
if (sa === 0) return dst;
|
|
730
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
731
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
732
|
+
const br = sr * dr >> 8;
|
|
733
|
+
const bg = sg * dg >> 8;
|
|
734
|
+
const bb = sb * db >> 8;
|
|
735
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
736
|
+
const invA = 255 - sa;
|
|
737
|
+
const da = dst >>> 24 & 255;
|
|
738
|
+
const r = br * sa + dr * invA >> 8;
|
|
739
|
+
const g = bg * sa + dg * invA >> 8;
|
|
740
|
+
const b = bb * sa + db * invA >> 8;
|
|
741
|
+
const a = 255 * sa + da * invA >> 8;
|
|
742
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
743
|
+
};
|
|
744
|
+
var colorBurnFast = (src, dst) => {
|
|
745
|
+
const sa = src >>> 24 & 255;
|
|
746
|
+
if (sa === 0) return dst;
|
|
747
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
748
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
749
|
+
const br = dr === 255 ? 255 : sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / sr | 0);
|
|
750
|
+
const bg = dg === 255 ? 255 : sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / sg | 0);
|
|
751
|
+
const bb = db === 255 ? 255 : sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / sb | 0);
|
|
752
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
753
|
+
const invA = 255 - sa;
|
|
754
|
+
const da = dst >>> 24 & 255;
|
|
755
|
+
const r = br * sa + dr * invA >> 8;
|
|
756
|
+
const g = bg * sa + dg * invA >> 8;
|
|
757
|
+
const b = bb * sa + db * invA >> 8;
|
|
758
|
+
const a = 255 * sa + da * invA >> 8;
|
|
759
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
760
|
+
};
|
|
761
|
+
var linearBurnFast = (src, dst) => {
|
|
762
|
+
const sa = src >>> 24 & 255;
|
|
763
|
+
if (sa === 0) return dst;
|
|
764
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
765
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
766
|
+
const brU = dr + sr - 255;
|
|
767
|
+
const bgU = dg + sg - 255;
|
|
768
|
+
const bbU = db + sb - 255;
|
|
769
|
+
const br = brU < 0 ? 0 : brU;
|
|
770
|
+
const bg = bgU < 0 ? 0 : bgU;
|
|
771
|
+
const bb = bbU < 0 ? 0 : bbU;
|
|
772
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
773
|
+
const invA = 255 - sa;
|
|
774
|
+
const r = br * sa + dr * invA >> 8;
|
|
775
|
+
const g = bg * sa + dg * invA >> 8;
|
|
776
|
+
const b = bb * sa + db * invA >> 8;
|
|
777
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
778
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
779
|
+
};
|
|
780
|
+
var darkerFast = (src, dst) => {
|
|
781
|
+
const sa = src >>> 24 & 255;
|
|
782
|
+
if (sa === 0) return dst;
|
|
783
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
784
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
785
|
+
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
786
|
+
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
787
|
+
let br, bg, bb;
|
|
788
|
+
if (lumSrc < lumDst) {
|
|
789
|
+
br = sr;
|
|
790
|
+
bg = sg;
|
|
791
|
+
bb = sb;
|
|
792
|
+
} else {
|
|
793
|
+
br = dr;
|
|
794
|
+
bg = dg;
|
|
795
|
+
bb = db;
|
|
968
796
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
const
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
797
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
798
|
+
const invA = 255 - sa;
|
|
799
|
+
const r = br * sa + dr * invA >> 8;
|
|
800
|
+
const g = bg * sa + dg * invA >> 8;
|
|
801
|
+
const b = bb * sa + db * invA >> 8;
|
|
802
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
803
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
804
|
+
};
|
|
805
|
+
var lightenFast = (src, dst) => {
|
|
806
|
+
const sa = src >>> 24 & 255;
|
|
807
|
+
if (sa === 0) return dst;
|
|
808
|
+
const br = Math.max(src & 255, dst & 255);
|
|
809
|
+
const bg = Math.max(src >> 8 & 255, dst >> 8 & 255);
|
|
810
|
+
const bb = Math.max(src >> 16 & 255, dst >> 16 & 255);
|
|
811
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
812
|
+
const dr = dst & 255;
|
|
813
|
+
const dg = dst >> 8 & 255;
|
|
814
|
+
const db = dst >> 16 & 255;
|
|
815
|
+
const invA = 255 - sa;
|
|
816
|
+
const r = br * sa + dr * invA >> 8;
|
|
817
|
+
const g = bg * sa + dg * invA >> 8;
|
|
818
|
+
const b = bb * sa + db * invA >> 8;
|
|
819
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
820
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
821
|
+
};
|
|
822
|
+
var screenFast = (src, dst) => {
|
|
823
|
+
const sa = src >>> 24 & 255;
|
|
824
|
+
if (sa === 0) return dst;
|
|
825
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
826
|
+
const br = 255 - ((255 - (src & 255)) * (255 - dr) >> 8);
|
|
827
|
+
const bg = 255 - ((255 - (src >>> 8 & 255)) * (255 - dg) >> 8);
|
|
828
|
+
const bb = 255 - ((255 - (src >>> 16 & 255)) * (255 - db) >> 8);
|
|
829
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
830
|
+
const invA = 255 - sa;
|
|
831
|
+
const r = br * sa + dr * invA >> 8;
|
|
832
|
+
const g = bg * sa + dg * invA >> 8;
|
|
833
|
+
const b = bb * sa + db * invA >> 8;
|
|
834
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
835
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
836
|
+
};
|
|
837
|
+
var colorDodgeFast = (src, dst) => {
|
|
838
|
+
const sa = src >>> 24 & 255;
|
|
839
|
+
if (sa === 0) return dst;
|
|
840
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
841
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
842
|
+
const br = sr === 255 ? 255 : Math.min(255, (dr << 8) / (255 - sr) | 0);
|
|
843
|
+
const bg = sg === 255 ? 255 : Math.min(255, (dg << 8) / (255 - sg) | 0);
|
|
844
|
+
const bb = sb === 255 ? 255 : Math.min(255, (db << 8) / (255 - sb) | 0);
|
|
845
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
846
|
+
const invA = 255 - sa;
|
|
847
|
+
const r = br * sa + dr * invA >> 8;
|
|
848
|
+
const g = bg * sa + dg * invA >> 8;
|
|
849
|
+
const b = bb * sa + db * invA >> 8;
|
|
850
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
851
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
852
|
+
};
|
|
853
|
+
var linearDodgeFast = (src, dst) => {
|
|
854
|
+
const sa = src >>> 24 & 255;
|
|
855
|
+
if (sa === 0) return dst;
|
|
856
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
857
|
+
const brU = (src & 255) + dr;
|
|
858
|
+
const bgU = (src >>> 8 & 255) + dg;
|
|
859
|
+
const bbU = (src >>> 16 & 255) + db;
|
|
860
|
+
const br = brU > 255 ? 255 : brU;
|
|
861
|
+
const bg = bgU > 255 ? 255 : bgU;
|
|
862
|
+
const bb = bbU > 255 ? 255 : bbU;
|
|
863
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
864
|
+
const invA = 255 - sa;
|
|
865
|
+
const r = br * sa + dr * invA >> 8;
|
|
866
|
+
const g = bg * sa + dg * invA >> 8;
|
|
867
|
+
const b = bb * sa + db * invA >> 8;
|
|
868
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
869
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
870
|
+
};
|
|
871
|
+
var lighterFast = (src, dst) => {
|
|
872
|
+
const sa = src >>> 24 & 255;
|
|
873
|
+
if (sa === 0) return dst;
|
|
874
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
875
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
876
|
+
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
877
|
+
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
878
|
+
let br, bg, bb;
|
|
879
|
+
if (lumSrc > lumDst) {
|
|
880
|
+
br = sr;
|
|
881
|
+
bg = sg;
|
|
882
|
+
bb = sb;
|
|
883
|
+
} else {
|
|
884
|
+
br = dr;
|
|
885
|
+
bg = dg;
|
|
886
|
+
bb = db;
|
|
986
887
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
const
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
);
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
888
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
889
|
+
const invA = 255 - sa;
|
|
890
|
+
const r = br * sa + dr * invA >> 8;
|
|
891
|
+
const g = bg * sa + dg * invA >> 8;
|
|
892
|
+
const b = bb * sa + db * invA >> 8;
|
|
893
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
894
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
895
|
+
};
|
|
896
|
+
var overlayFast = (src, dst) => {
|
|
897
|
+
const sa = src >>> 24 & 255;
|
|
898
|
+
if (sa === 0) return dst;
|
|
899
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
900
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
901
|
+
const br = dr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
902
|
+
const bg = dg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
903
|
+
const bb = db < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
904
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
905
|
+
const invA = 255 - sa;
|
|
906
|
+
const r = br * sa + dr * invA >> 8;
|
|
907
|
+
const g = bg * sa + dg * invA >> 8;
|
|
908
|
+
const b = bb * sa + db * invA >> 8;
|
|
909
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
910
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
911
|
+
};
|
|
912
|
+
var softLightFast = (src, dst) => {
|
|
913
|
+
const sa = src >>> 24 & 255;
|
|
914
|
+
if (sa === 0) return dst;
|
|
915
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
916
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
917
|
+
const br = (255 - dr) * (sr * dr >> 8) + dr * (255 - ((255 - sr) * (255 - dr) >> 8)) >> 8;
|
|
918
|
+
const bg = (255 - dg) * (sg * dg >> 8) + dg * (255 - ((255 - sg) * (255 - dg) >> 8)) >> 8;
|
|
919
|
+
const bb = (255 - db) * (sb * db >> 8) + db * (255 - ((255 - sb) * (255 - db) >> 8)) >> 8;
|
|
920
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
921
|
+
const invA = 255 - sa;
|
|
922
|
+
const r = br * sa + dr * invA >> 8;
|
|
923
|
+
const g = bg * sa + dg * invA >> 8;
|
|
924
|
+
const b = bb * sa + db * invA >> 8;
|
|
925
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
926
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
927
|
+
};
|
|
928
|
+
var hardLightFast = (src, dst) => {
|
|
929
|
+
const sa = src >>> 24 & 255;
|
|
930
|
+
if (sa === 0) return dst;
|
|
931
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
932
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
933
|
+
const br = sr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
934
|
+
const bg = sg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
935
|
+
const bb = sb < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
936
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
937
|
+
const invA = 255 - sa;
|
|
938
|
+
const r = br * sa + dr * invA >> 8;
|
|
939
|
+
const g = bg * sa + dg * invA >> 8;
|
|
940
|
+
const b = bb * sa + db * invA >> 8;
|
|
941
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
942
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
943
|
+
};
|
|
944
|
+
var vividLightFast = (src, dst) => {
|
|
945
|
+
const sa = src >>> 24 & 255;
|
|
946
|
+
if (sa === 0) return dst;
|
|
947
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
948
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
949
|
+
const br = sr < 128 ? sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / (2 * sr) | 0) : sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr)) | 0);
|
|
950
|
+
const bg = sg < 128 ? sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / (2 * sg) | 0) : sg === 255 ? 255 : Math.min(255, (dg << 8) / (2 * (255 - sg)) | 0);
|
|
951
|
+
const bb = sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / (2 * sb) | 0) : sb === 255 ? 255 : Math.min(255, (db << 8) / (2 * (255 - sb)) | 0);
|
|
952
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
953
|
+
const invA = 255 - sa;
|
|
954
|
+
const r = br * sa + dr * invA >> 8;
|
|
955
|
+
const g = bg * sa + dg * invA >> 8;
|
|
956
|
+
const b = bb * sa + db * invA >> 8;
|
|
957
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
958
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
959
|
+
};
|
|
960
|
+
var linearLightFast = (src, dst) => {
|
|
961
|
+
const sa = src >>> 24 & 255;
|
|
962
|
+
if (sa === 0) return dst;
|
|
963
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
964
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
965
|
+
const brU = dr + 2 * sr - 255;
|
|
966
|
+
const bgU = dg + 2 * sg - 255;
|
|
967
|
+
const bbU = db + 2 * sb - 255;
|
|
968
|
+
const br = brU < 0 ? 0 : brU > 255 ? 255 : brU;
|
|
969
|
+
const bg = bgU < 0 ? 0 : bgU > 255 ? 255 : bgU;
|
|
970
|
+
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU;
|
|
971
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
972
|
+
const invA = 255 - sa;
|
|
973
|
+
const r = br * sa + dr * invA >> 8;
|
|
974
|
+
const g = bg * sa + dg * invA >> 8;
|
|
975
|
+
const b = bb * sa + db * invA >> 8;
|
|
976
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
977
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
978
|
+
};
|
|
979
|
+
var pinLightFast = (src, dst) => {
|
|
980
|
+
const sa = src >>> 24 & 255;
|
|
981
|
+
if (sa === 0) return dst;
|
|
982
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
983
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
984
|
+
const br = sr < 128 ? dr < 2 * sr ? dr : 2 * sr : dr > 2 * sr - 256 ? dr : 2 * sr - 256;
|
|
985
|
+
const bg = sg < 128 ? dg < 2 * sg ? dg : 2 * sg : dg > 2 * sg - 256 ? dg : 2 * sg - 256;
|
|
986
|
+
const bb = sb < 128 ? db < 2 * sb ? db : 2 * sb : db > 2 * sb - 256 ? db : 2 * sb - 256;
|
|
987
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
988
|
+
const invA = 255 - sa;
|
|
989
|
+
const r = br * sa + dr * invA >> 8;
|
|
990
|
+
const g = bg * sa + dg * invA >> 8;
|
|
991
|
+
const b = bb * sa + db * invA >> 8;
|
|
992
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
993
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
994
|
+
};
|
|
995
|
+
var hardMixFast = (src, dst) => {
|
|
996
|
+
const sa = src >>> 24 & 255;
|
|
997
|
+
if (sa === 0) return dst;
|
|
998
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
999
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1000
|
+
const br = (sr < 128 ? sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / (2 * sr) | 0) : sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr)) | 0)) < 128 ? 0 : 255;
|
|
1001
|
+
const bg = (sg < 128 ? sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / (2 * sg) | 0) : sg === 255 ? 255 : Math.min(255, (dg << 8) / (2 * (255 - sg)) | 0)) < 128 ? 0 : 255;
|
|
1002
|
+
const bb = (sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / (2 * sb) | 0) : sb === 255 ? 255 : Math.min(255, (db << 8) / (2 * (255 - sb)) | 0)) < 128 ? 0 : 255;
|
|
1003
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1004
|
+
const invA = 255 - sa;
|
|
1005
|
+
const r = br * sa + dr * invA >> 8;
|
|
1006
|
+
const g = bg * sa + dg * invA >> 8;
|
|
1007
|
+
const b = bb * sa + db * invA >> 8;
|
|
1008
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
1009
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1010
|
+
};
|
|
1011
|
+
var differenceFast = (src, dst) => {
|
|
1012
|
+
const sa = src >>> 24 & 255;
|
|
1013
|
+
if (sa === 0) return dst;
|
|
1014
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1015
|
+
const brD = (src & 255) - dr;
|
|
1016
|
+
const bgD = (src >>> 8 & 255) - dg;
|
|
1017
|
+
const bbD = (src >>> 16 & 255) - db;
|
|
1018
|
+
const br = brD < 0 ? -brD : brD;
|
|
1019
|
+
const bg = bgD < 0 ? -bgD : bgD;
|
|
1020
|
+
const bb = bbD < 0 ? -bbD : bbD;
|
|
1021
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1022
|
+
const invA = 255 - sa;
|
|
1023
|
+
const r = br * sa + dr * invA >> 8;
|
|
1024
|
+
const g = bg * sa + dg * invA >> 8;
|
|
1025
|
+
const b = bb * sa + db * invA >> 8;
|
|
1026
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
1027
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1028
|
+
};
|
|
1029
|
+
var exclusionFast = (src, dst) => {
|
|
1030
|
+
const sa = src >>> 24 & 255;
|
|
1031
|
+
if (sa === 0) return dst;
|
|
1032
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1033
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1034
|
+
const br = dr + sr - (dr * sr >> 7);
|
|
1035
|
+
const bg = dg + sg - (dg * sg >> 7);
|
|
1036
|
+
const bb = db + sb - (db * sb >> 7);
|
|
1037
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1038
|
+
const invA = 255 - sa;
|
|
1039
|
+
const r = br * sa + dr * invA >> 8;
|
|
1040
|
+
const g = bg * sa + dg * invA >> 8;
|
|
1041
|
+
const b = bb * sa + db * invA >> 8;
|
|
1042
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
1043
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1044
|
+
};
|
|
1045
|
+
var subtractFast = (src, dst) => {
|
|
1046
|
+
const sa = src >>> 24 & 255;
|
|
1047
|
+
if (sa === 0) return dst;
|
|
1048
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1049
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1050
|
+
const brU = dr - sr;
|
|
1051
|
+
const bgU = dg - sg;
|
|
1052
|
+
const bbU = db - sb;
|
|
1053
|
+
const br = brU < 0 ? 0 : brU;
|
|
1054
|
+
const bg = bgU < 0 ? 0 : bgU;
|
|
1055
|
+
const bb = bbU < 0 ? 0 : bbU;
|
|
1056
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1057
|
+
const invA = 255 - sa;
|
|
1058
|
+
const r = br * sa + dr * invA >> 8;
|
|
1059
|
+
const g = bg * sa + dg * invA >> 8;
|
|
1060
|
+
const b = bb * sa + db * invA >> 8;
|
|
1061
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
1062
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1063
|
+
};
|
|
1064
|
+
var divideFast = (src, dst) => {
|
|
1065
|
+
const sa = src >>> 24 & 255;
|
|
1066
|
+
if (sa === 0) return dst;
|
|
1067
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1068
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1069
|
+
const br = sr === 0 ? 255 : Math.min(255, (dr << 8) / sr | 0);
|
|
1070
|
+
const bg = sg === 0 ? 255 : Math.min(255, (dg << 8) / sg | 0);
|
|
1071
|
+
const bb = sb === 0 ? 255 : Math.min(255, (db << 8) / sb | 0);
|
|
1072
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1073
|
+
const invA = 255 - sa;
|
|
1074
|
+
const r = br * sa + dr * invA >> 8;
|
|
1075
|
+
const g = bg * sa + dg * invA >> 8;
|
|
1076
|
+
const b = bb * sa + db * invA >> 8;
|
|
1077
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
1078
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1079
|
+
};
|
|
1080
|
+
var BASE_FAST_BLEND_MODE_FUNCTIONS = {
|
|
1081
|
+
[BaseBlendMode.overwrite]: overwriteFast,
|
|
1082
|
+
[BaseBlendMode.sourceOver]: sourceOverFast,
|
|
1083
|
+
[BaseBlendMode.darken]: darkenFast,
|
|
1084
|
+
[BaseBlendMode.multiply]: multiplyFast,
|
|
1085
|
+
[BaseBlendMode.colorBurn]: colorBurnFast,
|
|
1086
|
+
[BaseBlendMode.linearBurn]: linearBurnFast,
|
|
1087
|
+
[BaseBlendMode.darkerColor]: darkerFast,
|
|
1088
|
+
[BaseBlendMode.lighten]: lightenFast,
|
|
1089
|
+
[BaseBlendMode.screen]: screenFast,
|
|
1090
|
+
[BaseBlendMode.colorDodge]: colorDodgeFast,
|
|
1091
|
+
[BaseBlendMode.linearDodge]: linearDodgeFast,
|
|
1092
|
+
[BaseBlendMode.lighterColor]: lighterFast,
|
|
1093
|
+
[BaseBlendMode.overlay]: overlayFast,
|
|
1094
|
+
[BaseBlendMode.softLight]: softLightFast,
|
|
1095
|
+
[BaseBlendMode.hardLight]: hardLightFast,
|
|
1096
|
+
[BaseBlendMode.vividLight]: vividLightFast,
|
|
1097
|
+
[BaseBlendMode.linearLight]: linearLightFast,
|
|
1098
|
+
[BaseBlendMode.pinLight]: pinLightFast,
|
|
1099
|
+
[BaseBlendMode.hardMix]: hardMixFast,
|
|
1100
|
+
[BaseBlendMode.difference]: differenceFast,
|
|
1101
|
+
[BaseBlendMode.exclusion]: exclusionFast,
|
|
1102
|
+
[BaseBlendMode.subtract]: subtractFast,
|
|
1103
|
+
[BaseBlendMode.divide]: divideFast
|
|
1104
|
+
};
|
|
1105
|
+
function makeFastBlendModeRegistry(name = "fast") {
|
|
1106
|
+
return makeBlendModeRegistry(BaseBlendMode, BASE_FAST_BLEND_MODE_FUNCTIONS, name);
|
|
1004
1107
|
}
|
|
1005
1108
|
|
|
1006
1109
|
// src/BlendModes/blend-modes-perfect.ts
|
|
@@ -1009,10 +1112,11 @@ var sourceOverPerfect = (src, dst) => {
|
|
|
1009
1112
|
const sa = src >>> 24 & 255;
|
|
1010
1113
|
if (sa === 255) return src;
|
|
1011
1114
|
if (sa === 0) return dst;
|
|
1012
|
-
const
|
|
1115
|
+
const da = dst >>> 24 & 255;
|
|
1116
|
+
if (da === 0) return src;
|
|
1013
1117
|
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1014
1118
|
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1015
|
-
const
|
|
1119
|
+
const invA = 255 - sa;
|
|
1016
1120
|
const tR = sr * sa + dr * invA;
|
|
1017
1121
|
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1018
1122
|
const tG = sg * sa + dg * invA;
|
|
@@ -1554,9 +1658,53 @@ var BASE_PERFECT_BLEND_MODE_FUNCTIONS = {
|
|
|
1554
1658
|
[BaseBlendMode.subtract]: subtractPerfect,
|
|
1555
1659
|
[BaseBlendMode.divide]: dividePerfect
|
|
1556
1660
|
};
|
|
1557
|
-
function makePerfectBlendModeRegistry() {
|
|
1558
|
-
return makeBlendModeRegistry(BaseBlendMode, BASE_PERFECT_BLEND_MODE_FUNCTIONS);
|
|
1661
|
+
function makePerfectBlendModeRegistry(name = "perfect") {
|
|
1662
|
+
return makeBlendModeRegistry(BaseBlendMode, BASE_PERFECT_BLEND_MODE_FUNCTIONS, name);
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// src/BlendModes/toBlendModeIndexAndName.ts
|
|
1666
|
+
function toBlendModeIndexAndName(input) {
|
|
1667
|
+
if (typeof input === "number") {
|
|
1668
|
+
const name = getKeyByValue(BaseBlendMode, input);
|
|
1669
|
+
if (name === void 0) throw new Error(`Invalid index: ${input}`);
|
|
1670
|
+
return {
|
|
1671
|
+
blendIndex: input,
|
|
1672
|
+
blendName: name
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
const trimmed = input.trim();
|
|
1676
|
+
const num = Number(trimmed);
|
|
1677
|
+
const isNumeric = trimmed !== "" && !Number.isNaN(num);
|
|
1678
|
+
if (isNumeric && Number.isInteger(num)) {
|
|
1679
|
+
console.log({
|
|
1680
|
+
trimmed,
|
|
1681
|
+
num,
|
|
1682
|
+
isNumeric,
|
|
1683
|
+
isInt: Number.isInteger(num)
|
|
1684
|
+
});
|
|
1685
|
+
const name = getKeyByValue(BaseBlendMode, num);
|
|
1686
|
+
console.log({
|
|
1687
|
+
name
|
|
1688
|
+
});
|
|
1689
|
+
if (name === void 0) throw new Error(`Invalid index: ${num}`);
|
|
1690
|
+
return {
|
|
1691
|
+
blendIndex: num,
|
|
1692
|
+
blendName: name
|
|
1693
|
+
};
|
|
1694
|
+
}
|
|
1695
|
+
if (trimmed in BaseBlendMode) {
|
|
1696
|
+
return {
|
|
1697
|
+
blendIndex: BaseBlendMode[trimmed],
|
|
1698
|
+
blendName: trimmed
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
throw new Error(`Invalid blend mode: ${JSON.stringify(input)}`);
|
|
1559
1702
|
}
|
|
1703
|
+
var getKeyByValue = (obj, value) => {
|
|
1704
|
+
for (const key in obj) {
|
|
1705
|
+
if (obj[key] === value) return key;
|
|
1706
|
+
}
|
|
1707
|
+
};
|
|
1560
1708
|
|
|
1561
1709
|
// src/Canvas/_constants.ts
|
|
1562
1710
|
var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
|
|
@@ -1595,7 +1743,10 @@ function makeReusableCanvas() {
|
|
|
1595
1743
|
} else {
|
|
1596
1744
|
ctx.clearRect(0, 0, width, height);
|
|
1597
1745
|
}
|
|
1598
|
-
return {
|
|
1746
|
+
return {
|
|
1747
|
+
canvas,
|
|
1748
|
+
ctx
|
|
1749
|
+
};
|
|
1599
1750
|
}
|
|
1600
1751
|
get2.reset = () => {
|
|
1601
1752
|
canvas = null;
|
|
@@ -1609,21 +1760,13 @@ async function imgBlobToImageData(blob) {
|
|
|
1609
1760
|
let bitmap = null;
|
|
1610
1761
|
try {
|
|
1611
1762
|
bitmap = await createImageBitmap(blob);
|
|
1612
|
-
const canvas = new OffscreenCanvas(
|
|
1613
|
-
bitmap.width,
|
|
1614
|
-
bitmap.height
|
|
1615
|
-
);
|
|
1763
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
1616
1764
|
const ctx = canvas.getContext("2d");
|
|
1617
1765
|
if (!ctx) {
|
|
1618
1766
|
throw new Error("Failed to get 2D context");
|
|
1619
1767
|
}
|
|
1620
1768
|
ctx.drawImage(bitmap, 0, 0);
|
|
1621
|
-
return ctx.getImageData(
|
|
1622
|
-
0,
|
|
1623
|
-
0,
|
|
1624
|
-
bitmap.width,
|
|
1625
|
-
bitmap.height
|
|
1626
|
-
);
|
|
1769
|
+
return ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
1627
1770
|
} finally {
|
|
1628
1771
|
bitmap?.close();
|
|
1629
1772
|
}
|
|
@@ -1671,6 +1814,64 @@ async function writeImageDataToClipboard(imageData) {
|
|
|
1671
1814
|
return writeImgBlobToClipboard(blob);
|
|
1672
1815
|
}
|
|
1673
1816
|
|
|
1817
|
+
// src/History/HistoryManager.ts
|
|
1818
|
+
var HistoryManager = class {
|
|
1819
|
+
constructor(maxSteps = 50) {
|
|
1820
|
+
this.maxSteps = maxSteps;
|
|
1821
|
+
this.undoStack = [];
|
|
1822
|
+
this.redoStack = [];
|
|
1823
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
1824
|
+
}
|
|
1825
|
+
undoStack;
|
|
1826
|
+
redoStack;
|
|
1827
|
+
listeners;
|
|
1828
|
+
get canUndo() {
|
|
1829
|
+
return this.undoStack.length > 0;
|
|
1830
|
+
}
|
|
1831
|
+
get canRedo() {
|
|
1832
|
+
return this.redoStack.length > 0;
|
|
1833
|
+
}
|
|
1834
|
+
subscribe(fn) {
|
|
1835
|
+
this.listeners.add(fn);
|
|
1836
|
+
return () => this.listeners.delete(fn);
|
|
1837
|
+
}
|
|
1838
|
+
notify() {
|
|
1839
|
+
this.listeners.forEach((fn) => fn());
|
|
1840
|
+
}
|
|
1841
|
+
commit(action) {
|
|
1842
|
+
this.undoStack.push(action);
|
|
1843
|
+
this.clearRedoStack();
|
|
1844
|
+
if (this.undoStack.length > this.maxSteps) {
|
|
1845
|
+
this.undoStack.shift()?.dispose?.();
|
|
1846
|
+
}
|
|
1847
|
+
this.notify();
|
|
1848
|
+
}
|
|
1849
|
+
undo() {
|
|
1850
|
+
let action = this.undoStack.pop();
|
|
1851
|
+
if (!action) return;
|
|
1852
|
+
this.redoStack.push(action);
|
|
1853
|
+
action.undo();
|
|
1854
|
+
this.notify();
|
|
1855
|
+
}
|
|
1856
|
+
redo() {
|
|
1857
|
+
let action = this.redoStack.pop();
|
|
1858
|
+
if (!action) return;
|
|
1859
|
+
this.undoStack.push(action);
|
|
1860
|
+
action.redo();
|
|
1861
|
+
this.notify();
|
|
1862
|
+
}
|
|
1863
|
+
clearRedoStack() {
|
|
1864
|
+
let length = this.redoStack.length;
|
|
1865
|
+
for (let i = 0; i < length; i++) {
|
|
1866
|
+
let action = this.redoStack[i];
|
|
1867
|
+
if (action) {
|
|
1868
|
+
action.dispose?.();
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
this.redoStack.length = 0;
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
|
|
1674
1875
|
// src/History/PixelPatchTiles.ts
|
|
1675
1876
|
var PixelTile = class {
|
|
1676
1877
|
constructor(id, tx, ty, tileArea) {
|
|
@@ -1724,12 +1925,7 @@ var PixelAccumulator = class {
|
|
|
1724
1925
|
tile.ty = ty;
|
|
1725
1926
|
return tile;
|
|
1726
1927
|
}
|
|
1727
|
-
return new PixelTile(
|
|
1728
|
-
id,
|
|
1729
|
-
tx,
|
|
1730
|
-
ty,
|
|
1731
|
-
this.config.tileArea
|
|
1732
|
-
);
|
|
1928
|
+
return new PixelTile(id, tx, ty, this.config.tileArea);
|
|
1733
1929
|
}
|
|
1734
1930
|
recyclePatch(patch) {
|
|
1735
1931
|
const before = patch.beforeTiles;
|
|
@@ -1760,11 +1956,7 @@ var PixelAccumulator = class {
|
|
|
1760
1956
|
let id = ty * columns + tx;
|
|
1761
1957
|
let tile = this.lookup[id];
|
|
1762
1958
|
if (!tile) {
|
|
1763
|
-
tile = this.getTile(
|
|
1764
|
-
id,
|
|
1765
|
-
tx,
|
|
1766
|
-
ty
|
|
1767
|
-
);
|
|
1959
|
+
tile = this.getTile(id, tx, ty);
|
|
1768
1960
|
this.extractState(tile);
|
|
1769
1961
|
this.lookup[id] = tile;
|
|
1770
1962
|
this.beforeTiles.push(tile);
|
|
@@ -1790,11 +1982,7 @@ var PixelAccumulator = class {
|
|
|
1790
1982
|
let id = ty * columns + tx;
|
|
1791
1983
|
let tile = this.lookup[id];
|
|
1792
1984
|
if (!tile) {
|
|
1793
|
-
tile = this.getTile(
|
|
1794
|
-
id,
|
|
1795
|
-
tx,
|
|
1796
|
-
ty
|
|
1797
|
-
);
|
|
1985
|
+
tile = this.getTile(id, tx, ty);
|
|
1798
1986
|
this.extractState(tile);
|
|
1799
1987
|
this.lookup[id] = tile;
|
|
1800
1988
|
this.beforeTiles.push(tile);
|
|
@@ -1833,78 +2021,16 @@ var PixelAccumulator = class {
|
|
|
1833
2021
|
for (let i = 0; i < length; i++) {
|
|
1834
2022
|
let beforeTile = this.beforeTiles[i];
|
|
1835
2023
|
if (beforeTile) {
|
|
1836
|
-
let afterTile = this.getTile(
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
beforeTile.ty
|
|
1840
|
-
);
|
|
1841
|
-
this.extractState(afterTile);
|
|
1842
|
-
afterTiles.push(afterTile);
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
return afterTiles;
|
|
1846
|
-
}
|
|
1847
|
-
reset() {
|
|
1848
|
-
this.lookup = [];
|
|
1849
|
-
this.beforeTiles = [];
|
|
1850
|
-
}
|
|
1851
|
-
};
|
|
1852
|
-
|
|
1853
|
-
// src/History/HistoryManager.ts
|
|
1854
|
-
var HistoryManager = class {
|
|
1855
|
-
constructor(maxSteps = 50) {
|
|
1856
|
-
this.maxSteps = maxSteps;
|
|
1857
|
-
this.undoStack = [];
|
|
1858
|
-
this.redoStack = [];
|
|
1859
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
1860
|
-
}
|
|
1861
|
-
undoStack;
|
|
1862
|
-
redoStack;
|
|
1863
|
-
listeners;
|
|
1864
|
-
get canUndo() {
|
|
1865
|
-
return this.undoStack.length > 0;
|
|
1866
|
-
}
|
|
1867
|
-
get canRedo() {
|
|
1868
|
-
return this.redoStack.length > 0;
|
|
1869
|
-
}
|
|
1870
|
-
subscribe(fn) {
|
|
1871
|
-
this.listeners.add(fn);
|
|
1872
|
-
return () => this.listeners.delete(fn);
|
|
1873
|
-
}
|
|
1874
|
-
notify() {
|
|
1875
|
-
this.listeners.forEach((fn) => fn());
|
|
1876
|
-
}
|
|
1877
|
-
commit(action) {
|
|
1878
|
-
this.undoStack.push(action);
|
|
1879
|
-
this.clearRedoStack();
|
|
1880
|
-
if (this.undoStack.length > this.maxSteps) {
|
|
1881
|
-
this.undoStack.shift()?.dispose?.();
|
|
1882
|
-
}
|
|
1883
|
-
this.notify();
|
|
1884
|
-
}
|
|
1885
|
-
undo() {
|
|
1886
|
-
let action = this.undoStack.pop();
|
|
1887
|
-
if (!action) return;
|
|
1888
|
-
this.redoStack.push(action);
|
|
1889
|
-
action.undo();
|
|
1890
|
-
this.notify();
|
|
1891
|
-
}
|
|
1892
|
-
redo() {
|
|
1893
|
-
let action = this.redoStack.pop();
|
|
1894
|
-
if (!action) return;
|
|
1895
|
-
this.undoStack.push(action);
|
|
1896
|
-
action.redo();
|
|
1897
|
-
this.notify();
|
|
1898
|
-
}
|
|
1899
|
-
clearRedoStack() {
|
|
1900
|
-
let length = this.redoStack.length;
|
|
1901
|
-
for (let i = 0; i < length; i++) {
|
|
1902
|
-
let action = this.redoStack[i];
|
|
1903
|
-
if (action) {
|
|
1904
|
-
action.dispose?.();
|
|
2024
|
+
let afterTile = this.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
|
|
2025
|
+
this.extractState(afterTile);
|
|
2026
|
+
afterTiles.push(afterTile);
|
|
1905
2027
|
}
|
|
1906
2028
|
}
|
|
1907
|
-
|
|
2029
|
+
return afterTiles;
|
|
2030
|
+
}
|
|
2031
|
+
reset() {
|
|
2032
|
+
this.lookup = [];
|
|
2033
|
+
this.beforeTiles = [];
|
|
1908
2034
|
}
|
|
1909
2035
|
};
|
|
1910
2036
|
|
|
@@ -1925,20 +2051,20 @@ var PixelEngineConfig = class {
|
|
|
1925
2051
|
}
|
|
1926
2052
|
};
|
|
1927
2053
|
|
|
1928
|
-
// src/PixelData/
|
|
1929
|
-
function
|
|
2054
|
+
// src/PixelData/applyAlphaMaskToPixelData.ts
|
|
2055
|
+
function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
1930
2056
|
const {
|
|
1931
2057
|
x: targetX = 0,
|
|
1932
2058
|
y: targetY = 0,
|
|
1933
2059
|
w: width = dst.width,
|
|
1934
2060
|
h: height = dst.height,
|
|
1935
2061
|
alpha: globalAlpha = 255,
|
|
1936
|
-
maskType = 0 /* ALPHA */,
|
|
1937
2062
|
mw,
|
|
1938
2063
|
mx = 0,
|
|
1939
2064
|
my = 0,
|
|
1940
2065
|
invertMask = false
|
|
1941
2066
|
} = opts;
|
|
2067
|
+
if (globalAlpha === 0) return;
|
|
1942
2068
|
let x = targetX;
|
|
1943
2069
|
let y = targetY;
|
|
1944
2070
|
let w = width;
|
|
@@ -1951,59 +2077,557 @@ function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1951
2077
|
h += y;
|
|
1952
2078
|
y = 0;
|
|
1953
2079
|
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
if (
|
|
2080
|
+
w = Math.min(w, dst.width - x);
|
|
2081
|
+
h = Math.min(h, dst.height - y);
|
|
2082
|
+
if (w <= 0) return;
|
|
2083
|
+
if (h <= 0) return;
|
|
2084
|
+
const mPitch = mw ?? width;
|
|
2085
|
+
if (mPitch <= 0) return;
|
|
2086
|
+
const maskHeight = mask.length / mPitch | 0;
|
|
2087
|
+
const startX = mx + (x - targetX);
|
|
2088
|
+
const startY = my + (y - targetY);
|
|
2089
|
+
const sX0 = Math.max(0, startX);
|
|
2090
|
+
const sY0 = Math.max(0, startY);
|
|
2091
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
2092
|
+
const sY1 = Math.min(maskHeight, startY + h);
|
|
2093
|
+
const finalW = sX1 - sX0;
|
|
2094
|
+
const finalH = sY1 - sY0;
|
|
2095
|
+
if (finalW <= 0) return;
|
|
2096
|
+
if (finalH <= 0) return;
|
|
2097
|
+
const xShift = sX0 - startX;
|
|
2098
|
+
const yShift = sY0 - startY;
|
|
2099
|
+
const dst32 = dst.data32;
|
|
2100
|
+
const dw = dst.width;
|
|
2101
|
+
const dStride = dw - finalW;
|
|
2102
|
+
const mStride = mPitch - finalW;
|
|
2103
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2104
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
2105
|
+
for (let iy = 0; iy < h; iy++) {
|
|
2106
|
+
for (let ix = 0; ix < w; ix++) {
|
|
2107
|
+
const mVal = mask[mIdx];
|
|
2108
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2109
|
+
let weight = 0;
|
|
2110
|
+
if (effectiveM === 0) {
|
|
2111
|
+
weight = 0;
|
|
2112
|
+
} else if (effectiveM === 255) {
|
|
2113
|
+
weight = globalAlpha;
|
|
2114
|
+
} else if (globalAlpha === 255) {
|
|
2115
|
+
weight = effectiveM;
|
|
2116
|
+
} else {
|
|
2117
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2118
|
+
}
|
|
2119
|
+
if (weight === 0) {
|
|
2120
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2121
|
+
} else if (weight !== 255) {
|
|
2122
|
+
const d = dst32[dIdx];
|
|
2123
|
+
const da = d >>> 24;
|
|
2124
|
+
if (da !== 0) {
|
|
2125
|
+
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
2126
|
+
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
dIdx++;
|
|
2130
|
+
mIdx++;
|
|
2131
|
+
}
|
|
2132
|
+
dIdx += dStride;
|
|
2133
|
+
mIdx += mStride;
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
// src/History/PixelMutator/mutatorApplyAlphaMask.ts
|
|
2138
|
+
var defaults = {
|
|
2139
|
+
applyAlphaMaskToPixelData
|
|
2140
|
+
};
|
|
2141
|
+
var mutatorApplyAlphaMask = ((writer, deps = defaults) => {
|
|
2142
|
+
const {
|
|
2143
|
+
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults.applyAlphaMaskToPixelData
|
|
2144
|
+
} = deps;
|
|
2145
|
+
return {
|
|
2146
|
+
applyAlphaMask: (mask, opts = {}) => {
|
|
2147
|
+
let target = writer.target;
|
|
2148
|
+
const {
|
|
2149
|
+
x = 0,
|
|
2150
|
+
y = 0,
|
|
2151
|
+
w = writer.target.width,
|
|
2152
|
+
h = writer.target.height
|
|
2153
|
+
} = opts;
|
|
2154
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2155
|
+
applyAlphaMaskToPixelData2(target, mask, opts);
|
|
2156
|
+
}
|
|
2157
|
+
};
|
|
2158
|
+
});
|
|
2159
|
+
|
|
2160
|
+
// src/PixelData/applyBinaryMaskToPixelData.ts
|
|
2161
|
+
function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
2162
|
+
const {
|
|
2163
|
+
x: targetX = 0,
|
|
2164
|
+
y: targetY = 0,
|
|
2165
|
+
w: width = dst.width,
|
|
2166
|
+
h: height = dst.height,
|
|
2167
|
+
alpha = 255,
|
|
2168
|
+
mw,
|
|
2169
|
+
mx = 0,
|
|
2170
|
+
my = 0,
|
|
2171
|
+
invertMask = false
|
|
2172
|
+
} = opts;
|
|
2173
|
+
if (alpha === 0) return;
|
|
2174
|
+
let x = targetX;
|
|
2175
|
+
let y = targetY;
|
|
2176
|
+
let w = width;
|
|
2177
|
+
let h = height;
|
|
2178
|
+
if (x < 0) {
|
|
2179
|
+
w += x;
|
|
2180
|
+
x = 0;
|
|
2181
|
+
}
|
|
2182
|
+
if (y < 0) {
|
|
2183
|
+
h += y;
|
|
2184
|
+
y = 0;
|
|
2185
|
+
}
|
|
2186
|
+
w = Math.min(w, dst.width - x);
|
|
2187
|
+
h = Math.min(h, dst.height - y);
|
|
2188
|
+
if (w <= 0) return;
|
|
2189
|
+
if (h <= 0) return;
|
|
2190
|
+
const mPitch = mw ?? width;
|
|
2191
|
+
if (mPitch <= 0) return;
|
|
2192
|
+
const maskHeight = mask.length / mPitch | 0;
|
|
2193
|
+
const startX = mx + (x - targetX);
|
|
2194
|
+
const startY = my + (y - targetY);
|
|
2195
|
+
const sX0 = Math.max(0, startX);
|
|
2196
|
+
const sY0 = Math.max(0, startY);
|
|
2197
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
2198
|
+
const sY1 = Math.min(maskHeight, startY + h);
|
|
2199
|
+
const finalW = sX1 - sX0;
|
|
2200
|
+
const finalH = sY1 - sY0;
|
|
2201
|
+
if (finalW <= 0) return;
|
|
2202
|
+
if (finalH <= 0) return;
|
|
2203
|
+
const xShift = sX0 - startX;
|
|
2204
|
+
const yShift = sY0 - startY;
|
|
2205
|
+
const dst32 = dst.data32;
|
|
2206
|
+
const dw = dst.width;
|
|
2207
|
+
const dStride = dw - finalW;
|
|
2208
|
+
const mStride = mPitch - finalW;
|
|
2209
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2210
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
2211
|
+
for (let iy = 0; iy < h; iy++) {
|
|
2212
|
+
for (let ix = 0; ix < w; ix++) {
|
|
2213
|
+
const mVal = mask[mIdx];
|
|
2214
|
+
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
2215
|
+
if (isMaskedOut) {
|
|
2216
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2217
|
+
} else if (alpha !== 255) {
|
|
2218
|
+
const d = dst32[dIdx];
|
|
2219
|
+
const da = d >>> 24;
|
|
2220
|
+
if (da !== 0) {
|
|
2221
|
+
const finalAlpha = da === 255 ? alpha : da * alpha + 128 >> 8;
|
|
2222
|
+
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
dIdx++;
|
|
2226
|
+
mIdx++;
|
|
2227
|
+
}
|
|
2228
|
+
dIdx += dStride;
|
|
2229
|
+
mIdx += mStride;
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
// src/History/PixelMutator/mutatorApplyBinaryMask.ts
|
|
2234
|
+
var defaults2 = {
|
|
2235
|
+
applyBinaryMaskToPixelData
|
|
2236
|
+
};
|
|
2237
|
+
var mutatorApplyBinaryMask = ((writer, deps = defaults2) => {
|
|
2238
|
+
const {
|
|
2239
|
+
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults2.applyBinaryMaskToPixelData
|
|
2240
|
+
} = deps;
|
|
2241
|
+
return {
|
|
2242
|
+
applyBinaryMask: (mask, opts = {}) => {
|
|
2243
|
+
let target = writer.target;
|
|
2244
|
+
const {
|
|
2245
|
+
x = 0,
|
|
2246
|
+
y = 0,
|
|
2247
|
+
w = writer.target.width,
|
|
2248
|
+
h = writer.target.height
|
|
2249
|
+
} = opts;
|
|
2250
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2251
|
+
applyBinaryMaskToPixelData2(target, mask, opts);
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
});
|
|
2255
|
+
|
|
2256
|
+
// src/Rect/getCircleBrushOrPencilBounds.ts
|
|
2257
|
+
function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight, out) {
|
|
2258
|
+
const r = brushSize / 2;
|
|
2259
|
+
const minOffset = -Math.ceil(r - 0.5);
|
|
2260
|
+
const maxOffset = Math.floor(r - 0.5);
|
|
2261
|
+
const startX = Math.floor(centerX + minOffset);
|
|
2262
|
+
const startY = Math.floor(centerY + minOffset);
|
|
2263
|
+
const endX = Math.floor(centerX + maxOffset) + 1;
|
|
2264
|
+
const endY = Math.floor(centerY + maxOffset) + 1;
|
|
2265
|
+
const res = out ?? {
|
|
2266
|
+
x: 0,
|
|
2267
|
+
y: 0,
|
|
2268
|
+
w: 0,
|
|
2269
|
+
h: 0
|
|
2270
|
+
};
|
|
2271
|
+
const cStartX = Math.max(0, startX);
|
|
2272
|
+
const cStartY = Math.max(0, startY);
|
|
2273
|
+
const cEndX = Math.min(targetWidth, endX);
|
|
2274
|
+
const cEndY = Math.min(targetHeight, endY);
|
|
2275
|
+
const w = cEndX - cStartX;
|
|
2276
|
+
const h = cEndY - cStartY;
|
|
2277
|
+
res.x = cStartX;
|
|
2278
|
+
res.y = cStartY;
|
|
2279
|
+
res.w = w < 0 ? 0 : w;
|
|
2280
|
+
res.h = h < 0 ? 0 : h;
|
|
2281
|
+
return res;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
2285
|
+
function applyCircleBrushToPixelData(target, color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2286
|
+
const targetWidth = target.width;
|
|
2287
|
+
const targetHeight = target.height;
|
|
2288
|
+
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight);
|
|
2289
|
+
if (b.w <= 0 || b.h <= 0) return;
|
|
2290
|
+
const data32 = target.data32;
|
|
2291
|
+
const r = brushSize / 2;
|
|
2292
|
+
const rSqr = r * r;
|
|
2293
|
+
const invR = 1 / r;
|
|
2294
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
2295
|
+
const endX = b.x + b.w;
|
|
2296
|
+
const endY = b.y + b.h;
|
|
2297
|
+
const fCenterX = Math.floor(centerX);
|
|
2298
|
+
const fCenterY = Math.floor(centerY);
|
|
2299
|
+
const baseSrcAlpha = color >>> 24;
|
|
2300
|
+
const colorRGB = color & 16777215;
|
|
2301
|
+
const isOpaque = alpha === 255;
|
|
2302
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2303
|
+
for (let cy = b.y; cy < endY; cy++) {
|
|
2304
|
+
const relY = cy - fCenterY + centerOffset;
|
|
2305
|
+
const dySqr = relY * relY;
|
|
2306
|
+
const rowOffset = cy * targetWidth;
|
|
2307
|
+
for (let cx = b.x; cx < endX; cx++) {
|
|
2308
|
+
const relX = cx - fCenterX + centerOffset;
|
|
2309
|
+
const dSqr = relX * relX + dySqr;
|
|
2310
|
+
if (dSqr <= rSqr) {
|
|
2311
|
+
const idx = rowOffset + cx;
|
|
2312
|
+
let weight = alpha;
|
|
2313
|
+
const strength = fallOff(1 - Math.sqrt(dSqr) * invR);
|
|
2314
|
+
const maskVal = strength * 255 | 0;
|
|
2315
|
+
if (maskVal === 0) continue;
|
|
2316
|
+
if (isOpaque) {
|
|
2317
|
+
weight = maskVal;
|
|
2318
|
+
} else if (maskVal !== 255) {
|
|
2319
|
+
weight = maskVal * alpha + 128 >> 8;
|
|
2320
|
+
}
|
|
2321
|
+
let finalCol = color;
|
|
2322
|
+
if (weight < 255) {
|
|
2323
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2324
|
+
if (a === 0 && !isOverwrite) continue;
|
|
2325
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
2326
|
+
}
|
|
2327
|
+
data32[idx] = blendFn(finalCol, data32[idx]);
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
// src/History/PixelMutator/mutatorApplyCircleBrush.ts
|
|
2334
|
+
var defaults3 = {
|
|
2335
|
+
applyCircleBrushToPixelData,
|
|
2336
|
+
getCircleBrushOrPencilBounds
|
|
2337
|
+
};
|
|
2338
|
+
var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
|
|
2339
|
+
const {
|
|
2340
|
+
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
|
|
2341
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
|
|
2342
|
+
} = deps;
|
|
2343
|
+
const boundsOut = {
|
|
2344
|
+
x: 0,
|
|
2345
|
+
y: 0,
|
|
2346
|
+
w: 0,
|
|
2347
|
+
h: 0
|
|
2348
|
+
};
|
|
2349
|
+
return {
|
|
2350
|
+
applyCircleBrush(color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn) {
|
|
2351
|
+
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
|
|
2352
|
+
const {
|
|
2353
|
+
x,
|
|
2354
|
+
y,
|
|
2355
|
+
w,
|
|
2356
|
+
h
|
|
2357
|
+
} = bounds;
|
|
2358
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2359
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2362
|
+
});
|
|
2363
|
+
|
|
2364
|
+
// src/Algorithm/forEachLinePoint.ts
|
|
2365
|
+
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
2366
|
+
const dx = x1 - x0;
|
|
2367
|
+
const dy = y1 - y0;
|
|
2368
|
+
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
2369
|
+
if (steps === 0) {
|
|
2370
|
+
callback(x0, y0);
|
|
1957
2371
|
return;
|
|
1958
2372
|
}
|
|
2373
|
+
const xInc = dx / steps;
|
|
2374
|
+
const yInc = dy / steps;
|
|
2375
|
+
let curX = x0;
|
|
2376
|
+
let curY = y0;
|
|
2377
|
+
for (let i = 0; i <= steps; i++) {
|
|
2378
|
+
callback(curX, curY);
|
|
2379
|
+
curX += xInc;
|
|
2380
|
+
curY += yInc;
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
2385
|
+
function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
|
|
2386
|
+
const {
|
|
2387
|
+
x: targetX = 0,
|
|
2388
|
+
y: targetY = 0,
|
|
2389
|
+
w: width = dst.width,
|
|
2390
|
+
h: height = dst.height,
|
|
2391
|
+
alpha: globalAlpha = 255,
|
|
2392
|
+
blendFn = sourceOverPerfect,
|
|
2393
|
+
mw = width,
|
|
2394
|
+
mx = 0,
|
|
2395
|
+
my = 0,
|
|
2396
|
+
invertMask = false
|
|
2397
|
+
} = opts;
|
|
2398
|
+
if (globalAlpha === 0 || !mask) return;
|
|
2399
|
+
const baseSrcAlpha = color >>> 24;
|
|
2400
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2401
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2402
|
+
let x = targetX;
|
|
2403
|
+
let y = targetY;
|
|
2404
|
+
let w = width;
|
|
2405
|
+
let h = height;
|
|
2406
|
+
if (x < 0) {
|
|
2407
|
+
w += x;
|
|
2408
|
+
x = 0;
|
|
2409
|
+
}
|
|
2410
|
+
if (y < 0) {
|
|
2411
|
+
h += y;
|
|
2412
|
+
y = 0;
|
|
2413
|
+
}
|
|
2414
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2415
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2416
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2417
|
+
const dx = x - targetX | 0;
|
|
2418
|
+
const dy = y - targetY | 0;
|
|
1959
2419
|
const dst32 = dst.data32;
|
|
1960
2420
|
const dw = dst.width;
|
|
1961
|
-
const mPitch = mw
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
const
|
|
1965
|
-
let
|
|
1966
|
-
|
|
1967
|
-
const
|
|
1968
|
-
const mStride = mPitch - actualW;
|
|
2421
|
+
const mPitch = mw;
|
|
2422
|
+
let dIdx = y * dw + x | 0;
|
|
2423
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2424
|
+
const dStride = dw - actualW | 0;
|
|
2425
|
+
let mStride = mPitch - actualW | 0;
|
|
2426
|
+
const isOpaque = globalAlpha === 255;
|
|
2427
|
+
const colorRGB = color & 16777215;
|
|
1969
2428
|
for (let iy = 0; iy < actualH; iy++) {
|
|
1970
2429
|
for (let ix = 0; ix < actualW; ix++) {
|
|
1971
2430
|
const mVal = mask[mIdx];
|
|
2431
|
+
const effM = invertMask ? 255 - mVal : mVal;
|
|
2432
|
+
if (effM === 0) {
|
|
2433
|
+
dIdx++;
|
|
2434
|
+
mIdx++;
|
|
2435
|
+
continue;
|
|
2436
|
+
}
|
|
1972
2437
|
let weight = globalAlpha;
|
|
1973
|
-
if (
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
2438
|
+
if (isOpaque) {
|
|
2439
|
+
weight = effM;
|
|
2440
|
+
} else if (effM !== 255) {
|
|
2441
|
+
weight = effM * globalAlpha + 128 >> 8;
|
|
2442
|
+
}
|
|
2443
|
+
if (weight === 0) {
|
|
2444
|
+
dIdx++;
|
|
2445
|
+
mIdx++;
|
|
2446
|
+
continue;
|
|
2447
|
+
}
|
|
2448
|
+
let finalCol = color;
|
|
2449
|
+
if (weight < 255) {
|
|
2450
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2451
|
+
if (a === 0 && !isOverwrite) {
|
|
1986
2452
|
dIdx++;
|
|
1987
2453
|
mIdx++;
|
|
1988
2454
|
continue;
|
|
1989
2455
|
}
|
|
1990
|
-
|
|
2456
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
1991
2457
|
}
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2458
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
2459
|
+
dIdx++;
|
|
2460
|
+
mIdx++;
|
|
2461
|
+
}
|
|
2462
|
+
dIdx += dStride;
|
|
2463
|
+
mIdx += mStride;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
// src/Rect/getCircleBrushOrPencilStrokeBounds.ts
|
|
2468
|
+
function getCircleBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushSize, result) {
|
|
2469
|
+
const r = Math.ceil(brushSize / 2);
|
|
2470
|
+
const minX = Math.min(x0, x1) - r;
|
|
2471
|
+
const minY = Math.min(y0, y1) - r;
|
|
2472
|
+
const maxX = Math.max(x0, x1) + r;
|
|
2473
|
+
const maxY = Math.max(x0, y1) + r;
|
|
2474
|
+
result.x = Math.floor(minX);
|
|
2475
|
+
result.y = Math.floor(minY);
|
|
2476
|
+
result.w = Math.ceil(maxX - minX);
|
|
2477
|
+
result.h = Math.ceil(maxY - minY);
|
|
2478
|
+
return result;
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
// src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts
|
|
2482
|
+
var defaults4 = {
|
|
2483
|
+
forEachLinePoint,
|
|
2484
|
+
blendColorPixelDataAlphaMask,
|
|
2485
|
+
getCircleBrushOrPencilBounds,
|
|
2486
|
+
getCircleBrushOrPencilStrokeBounds
|
|
2487
|
+
};
|
|
2488
|
+
var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
2489
|
+
const {
|
|
2490
|
+
forEachLinePoint: forEachLinePoint2 = defaults4.forEachLinePoint,
|
|
2491
|
+
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults4.blendColorPixelDataAlphaMask,
|
|
2492
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults4.getCircleBrushOrPencilBounds,
|
|
2493
|
+
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults4.getCircleBrushOrPencilStrokeBounds
|
|
2494
|
+
} = deps;
|
|
2495
|
+
const strokeBoundsOut = {
|
|
2496
|
+
x: 0,
|
|
2497
|
+
y: 0,
|
|
2498
|
+
w: 0,
|
|
2499
|
+
h: 0
|
|
2500
|
+
};
|
|
2501
|
+
const circleBrushBounds = {
|
|
2502
|
+
x: 0,
|
|
2503
|
+
y: 0,
|
|
2504
|
+
w: 0,
|
|
2505
|
+
h: 0
|
|
2506
|
+
};
|
|
2507
|
+
const blendColorPixelOptions = {
|
|
2508
|
+
alpha: 255,
|
|
2509
|
+
blendFn: sourceOverPerfect,
|
|
2510
|
+
x: 0,
|
|
2511
|
+
y: 0,
|
|
2512
|
+
w: 0,
|
|
2513
|
+
h: 0
|
|
2514
|
+
};
|
|
2515
|
+
return {
|
|
2516
|
+
applyCircleBrushStroke(color, x0, y0, x1, y1, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
2517
|
+
const {
|
|
2518
|
+
x: bx,
|
|
2519
|
+
y: by,
|
|
2520
|
+
w: bw,
|
|
2521
|
+
h: bh
|
|
2522
|
+
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
|
|
2523
|
+
if (bw <= 0 || bh <= 0) return;
|
|
2524
|
+
const mask = new Uint8Array(bw * bh);
|
|
2525
|
+
const r = brushSize / 2;
|
|
2526
|
+
const rSqr = r * r;
|
|
2527
|
+
const invR = 1 / r;
|
|
2528
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
2529
|
+
const targetWidth = writer.target.width;
|
|
2530
|
+
const targetHeight = writer.target.height;
|
|
2531
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2532
|
+
const {
|
|
2533
|
+
x: cbx,
|
|
2534
|
+
y: cby,
|
|
2535
|
+
w: cbw,
|
|
2536
|
+
h: cbh
|
|
2537
|
+
} = getCircleBrushOrPencilBounds2(px, py, brushSize, targetWidth, targetHeight, circleBrushBounds);
|
|
2538
|
+
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2539
|
+
const startX = Math.max(bx, cbx);
|
|
2540
|
+
const startY = Math.max(by, cby);
|
|
2541
|
+
const endX = Math.min(bx + bw, cbx + cbw);
|
|
2542
|
+
const endY = Math.min(by + bh, cby + cbh);
|
|
2543
|
+
const fPx = Math.floor(px);
|
|
2544
|
+
const fPy = Math.floor(py);
|
|
2545
|
+
for (let my = startY; my < endY; my++) {
|
|
2546
|
+
const dy = my - fPy + centerOffset;
|
|
2547
|
+
const dySqr = dy * dy;
|
|
2548
|
+
const maskRowOffset = (my - by) * bw;
|
|
2549
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
2550
|
+
const dx = mx - fPx + centerOffset;
|
|
2551
|
+
const dSqr = dx * dx + dySqr;
|
|
2552
|
+
if (dSqr <= rSqr) {
|
|
2553
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
2554
|
+
const dist = Math.sqrt(dSqr) * invR;
|
|
2555
|
+
const intensity = fallOff(1 - dist) * 255 | 0;
|
|
2556
|
+
if (intensity > mask[maskIdx]) {
|
|
2557
|
+
mask[maskIdx] = intensity;
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2004
2561
|
}
|
|
2005
|
-
|
|
2562
|
+
});
|
|
2563
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
2564
|
+
blendColorPixelOptions.alpha = alpha;
|
|
2565
|
+
blendColorPixelOptions.x = bx;
|
|
2566
|
+
blendColorPixelOptions.y = by;
|
|
2567
|
+
blendColorPixelOptions.w = bw;
|
|
2568
|
+
blendColorPixelOptions.h = bh;
|
|
2569
|
+
blendColorPixelDataAlphaMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
2570
|
+
}
|
|
2571
|
+
};
|
|
2572
|
+
});
|
|
2573
|
+
|
|
2574
|
+
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
2575
|
+
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
2576
|
+
const {
|
|
2577
|
+
x: targetX = 0,
|
|
2578
|
+
y: targetY = 0,
|
|
2579
|
+
w: width = dst.width,
|
|
2580
|
+
h: height = dst.height,
|
|
2581
|
+
alpha: globalAlpha = 255,
|
|
2582
|
+
blendFn = sourceOverPerfect,
|
|
2583
|
+
mw = width,
|
|
2584
|
+
mx = 0,
|
|
2585
|
+
my = 0,
|
|
2586
|
+
invertMask = false
|
|
2587
|
+
} = opts;
|
|
2588
|
+
if (globalAlpha === 0 || !mask) return;
|
|
2589
|
+
const baseSrcAlpha = color >>> 24;
|
|
2590
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2591
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2592
|
+
let x = targetX;
|
|
2593
|
+
let y = targetY;
|
|
2594
|
+
let w = width;
|
|
2595
|
+
let h = height;
|
|
2596
|
+
if (x < 0) {
|
|
2597
|
+
w += x;
|
|
2598
|
+
x = 0;
|
|
2599
|
+
}
|
|
2600
|
+
if (y < 0) {
|
|
2601
|
+
h += y;
|
|
2602
|
+
y = 0;
|
|
2603
|
+
}
|
|
2604
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2605
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2606
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2607
|
+
let baseColorWithGlobalAlpha = color;
|
|
2608
|
+
if (globalAlpha < 255) {
|
|
2609
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2610
|
+
if (a === 0 && !isOverwrite) return;
|
|
2611
|
+
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2612
|
+
}
|
|
2613
|
+
const dx = x - targetX | 0;
|
|
2614
|
+
const dy = y - targetY | 0;
|
|
2615
|
+
const dst32 = dst.data32;
|
|
2616
|
+
const dw = dst.width;
|
|
2617
|
+
const mPitch = mw;
|
|
2618
|
+
let dIdx = y * dw + x | 0;
|
|
2619
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2620
|
+
const dStride = dw - actualW | 0;
|
|
2621
|
+
const mStride = mPitch - actualW | 0;
|
|
2622
|
+
const skipVal = invertMask ? 1 : 0;
|
|
2623
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2624
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2625
|
+
if (mask[mIdx] === skipVal) {
|
|
2626
|
+
dIdx++;
|
|
2627
|
+
mIdx++;
|
|
2628
|
+
continue;
|
|
2006
2629
|
}
|
|
2630
|
+
dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
|
|
2007
2631
|
dIdx++;
|
|
2008
2632
|
mIdx++;
|
|
2009
2633
|
}
|
|
@@ -2012,63 +2636,424 @@ function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2012
2636
|
}
|
|
2013
2637
|
}
|
|
2014
2638
|
|
|
2015
|
-
// src/History/
|
|
2016
|
-
var
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
mutator;
|
|
2022
|
-
constructor(target, mutatorFactory, {
|
|
2023
|
-
tileSize = 256,
|
|
2024
|
-
maxHistorySteps = 50,
|
|
2025
|
-
historyManager = new HistoryManager(maxHistorySteps)
|
|
2026
|
-
} = {}) {
|
|
2027
|
-
this.target = target;
|
|
2028
|
-
this.config = new PixelEngineConfig(tileSize);
|
|
2029
|
-
this.historyManager = historyManager;
|
|
2030
|
-
this.accumulator = new PixelAccumulator(target, this.config);
|
|
2031
|
-
this.mutator = mutatorFactory(this);
|
|
2032
|
-
}
|
|
2033
|
-
withHistory(cb) {
|
|
2034
|
-
cb(this.mutator);
|
|
2035
|
-
const beforeTiles = this.accumulator.beforeTiles;
|
|
2036
|
-
if (beforeTiles.length === 0) return;
|
|
2037
|
-
const afterTiles = this.accumulator.extractAfterTiles();
|
|
2038
|
-
const patch = {
|
|
2039
|
-
beforeTiles,
|
|
2040
|
-
afterTiles
|
|
2041
|
-
};
|
|
2042
|
-
const target = this.target;
|
|
2043
|
-
const tileSize = this.config.tileSize;
|
|
2044
|
-
const accumulator = this.accumulator;
|
|
2045
|
-
const action = {
|
|
2046
|
-
undo: () => applyPatchTiles(target, patch.beforeTiles, tileSize),
|
|
2047
|
-
redo: () => applyPatchTiles(target, patch.afterTiles, tileSize),
|
|
2048
|
-
dispose: () => accumulator.recyclePatch(patch)
|
|
2049
|
-
};
|
|
2050
|
-
this.historyManager.commit(action);
|
|
2051
|
-
this.accumulator.reset();
|
|
2052
|
-
}
|
|
2639
|
+
// src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
|
|
2640
|
+
var defaults5 = {
|
|
2641
|
+
forEachLinePoint,
|
|
2642
|
+
blendColorPixelDataBinaryMask,
|
|
2643
|
+
getCircleBrushOrPencilBounds,
|
|
2644
|
+
getCircleBrushOrPencilStrokeBounds
|
|
2053
2645
|
};
|
|
2646
|
+
var mutatorApplyCirclePencilStroke = ((writer, deps = defaults5) => {
|
|
2647
|
+
const {
|
|
2648
|
+
forEachLinePoint: forEachLinePoint2 = defaults5.forEachLinePoint,
|
|
2649
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults5.blendColorPixelDataBinaryMask,
|
|
2650
|
+
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults5.getCircleBrushOrPencilStrokeBounds,
|
|
2651
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
|
|
2652
|
+
} = deps;
|
|
2653
|
+
const strokeBoundsOut = {
|
|
2654
|
+
x: 0,
|
|
2655
|
+
y: 0,
|
|
2656
|
+
w: 0,
|
|
2657
|
+
h: 0
|
|
2658
|
+
};
|
|
2659
|
+
const circlePencilBounds = {
|
|
2660
|
+
x: 0,
|
|
2661
|
+
y: 0,
|
|
2662
|
+
w: 0,
|
|
2663
|
+
h: 0
|
|
2664
|
+
};
|
|
2665
|
+
const blendColorPixelOptions = {
|
|
2666
|
+
alpha: 255,
|
|
2667
|
+
blendFn: sourceOverPerfect,
|
|
2668
|
+
x: 0,
|
|
2669
|
+
y: 0,
|
|
2670
|
+
w: 0,
|
|
2671
|
+
h: 0
|
|
2672
|
+
};
|
|
2673
|
+
return {
|
|
2674
|
+
applyCirclePencilStroke(color, x0, y0, x1, y1, brushSize, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2675
|
+
const {
|
|
2676
|
+
x: bx,
|
|
2677
|
+
y: by,
|
|
2678
|
+
w: bw,
|
|
2679
|
+
h: bh
|
|
2680
|
+
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
|
|
2681
|
+
if (bw <= 0 || bh <= 0) return;
|
|
2682
|
+
const mask = new Uint8Array(bw * bh);
|
|
2683
|
+
const r = brushSize / 2;
|
|
2684
|
+
const rSqr = r * r;
|
|
2685
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
2686
|
+
const targetWidth = writer.target.width;
|
|
2687
|
+
const targetHeight = writer.target.height;
|
|
2688
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2689
|
+
const {
|
|
2690
|
+
x: cbx,
|
|
2691
|
+
y: cby,
|
|
2692
|
+
w: cbw,
|
|
2693
|
+
h: cbh
|
|
2694
|
+
} = getCircleBrushOrPencilBounds2(px, py, brushSize, targetWidth, targetHeight, circlePencilBounds);
|
|
2695
|
+
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2696
|
+
const startX = Math.max(bx, cbx);
|
|
2697
|
+
const startY = Math.max(by, cby);
|
|
2698
|
+
const endX = Math.min(bx + bw, cbx + cbw);
|
|
2699
|
+
const endY = Math.min(by + bh, cby + cbh);
|
|
2700
|
+
const fPx = Math.floor(px);
|
|
2701
|
+
const fPy = Math.floor(py);
|
|
2702
|
+
for (let my = startY; my < endY; my++) {
|
|
2703
|
+
const dy = my - fPy + centerOffset;
|
|
2704
|
+
const dySqr = dy * dy;
|
|
2705
|
+
const maskRowOffset = (my - by) * bw;
|
|
2706
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
2707
|
+
const dx = mx - fPx + centerOffset;
|
|
2708
|
+
const dSqr = dx * dx + dySqr;
|
|
2709
|
+
if (dSqr <= rSqr) {
|
|
2710
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
2711
|
+
mask[maskIdx] = 1;
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
});
|
|
2716
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
2717
|
+
blendColorPixelOptions.alpha = alpha;
|
|
2718
|
+
blendColorPixelOptions.x = bx;
|
|
2719
|
+
blendColorPixelOptions.y = by;
|
|
2720
|
+
blendColorPixelOptions.w = bw;
|
|
2721
|
+
blendColorPixelOptions.h = bh;
|
|
2722
|
+
blendColorPixelDataBinaryMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
2723
|
+
}
|
|
2724
|
+
};
|
|
2725
|
+
});
|
|
2054
2726
|
|
|
2055
|
-
// src/
|
|
2056
|
-
function
|
|
2727
|
+
// src/Rect/getRectBrushOrPencilBounds.ts
|
|
2728
|
+
function getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight, out) {
|
|
2729
|
+
const startX = Math.floor(centerX - brushWidth / 2);
|
|
2730
|
+
const startY = Math.floor(centerY - brushHeight / 2);
|
|
2731
|
+
const endX = startX + brushWidth;
|
|
2732
|
+
const endY = startY + brushHeight;
|
|
2733
|
+
const res = out ?? {
|
|
2734
|
+
x: 0,
|
|
2735
|
+
y: 0,
|
|
2736
|
+
w: 0,
|
|
2737
|
+
h: 0
|
|
2738
|
+
};
|
|
2739
|
+
const cStartX = Math.max(0, startX);
|
|
2740
|
+
const cStartY = Math.max(0, startY);
|
|
2741
|
+
const cEndX = Math.min(targetWidth, endX);
|
|
2742
|
+
const cEndY = Math.min(targetHeight, endY);
|
|
2743
|
+
const w = cEndX - cStartX;
|
|
2744
|
+
const h = cEndY - cStartY;
|
|
2745
|
+
res.x = cStartX;
|
|
2746
|
+
res.y = cStartY;
|
|
2747
|
+
res.w = w < 0 ? 0 : w;
|
|
2748
|
+
res.h = h < 0 ? 0 : h;
|
|
2749
|
+
return res;
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2752
|
+
// src/PixelData/applyRectBrushToPixelData.ts
|
|
2753
|
+
function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2754
|
+
const targetWidth = target.width;
|
|
2755
|
+
const targetHeight = target.height;
|
|
2756
|
+
const b = bounds ?? getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight);
|
|
2757
|
+
if (b.w <= 0 || b.h <= 0) return;
|
|
2758
|
+
const data32 = target.data32;
|
|
2759
|
+
const baseColor = color & 16777215;
|
|
2760
|
+
const baseSrcAlpha = color >>> 24;
|
|
2761
|
+
const isOpaque = alpha === 255;
|
|
2762
|
+
const invHalfW = 1 / (brushWidth / 2);
|
|
2763
|
+
const invHalfH = 1 / (brushHeight / 2);
|
|
2764
|
+
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2765
|
+
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2766
|
+
const fCenterX = Math.floor(centerX);
|
|
2767
|
+
const fCenterY = Math.floor(centerY);
|
|
2768
|
+
const endX = b.x + b.w;
|
|
2769
|
+
const endY = b.y + b.h;
|
|
2770
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2771
|
+
for (let py = b.y; py < endY; py++) {
|
|
2772
|
+
const rowOffset = py * targetWidth;
|
|
2773
|
+
const dy = Math.abs(py - fCenterY + centerOffsetY) * invHalfH;
|
|
2774
|
+
for (let px = b.x; px < endX; px++) {
|
|
2775
|
+
const idx = rowOffset + px;
|
|
2776
|
+
const dx = Math.abs(px - fCenterX + centerOffsetX) * invHalfW;
|
|
2777
|
+
const dist = dx > dy ? dx : dy;
|
|
2778
|
+
const strength = fallOff(dist);
|
|
2779
|
+
const maskVal = strength * 255 | 0;
|
|
2780
|
+
if (maskVal <= 0) continue;
|
|
2781
|
+
let weight = alpha;
|
|
2782
|
+
if (isOpaque) {
|
|
2783
|
+
weight = maskVal;
|
|
2784
|
+
} else if (maskVal !== 255) {
|
|
2785
|
+
weight = maskVal * alpha + 128 >> 8;
|
|
2786
|
+
}
|
|
2787
|
+
let finalCol = color;
|
|
2788
|
+
if (weight < 255) {
|
|
2789
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2790
|
+
if (a === 0 && !isOverwrite) continue;
|
|
2791
|
+
finalCol = (a << 24 | baseColor) >>> 0;
|
|
2792
|
+
}
|
|
2793
|
+
data32[idx] = blendFn(finalCol, data32[idx]);
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
// src/History/PixelMutator/mutatorApplyRectBrush.ts
|
|
2799
|
+
var defaults6 = {
|
|
2800
|
+
applyRectBrushToPixelData,
|
|
2801
|
+
getRectBrushOrPencilBounds
|
|
2802
|
+
};
|
|
2803
|
+
var mutatorApplyRectBrush = ((writer, deps = defaults6) => {
|
|
2804
|
+
const {
|
|
2805
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults6.applyRectBrushToPixelData,
|
|
2806
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults6.getRectBrushOrPencilBounds
|
|
2807
|
+
} = deps;
|
|
2808
|
+
const boundsOut = {
|
|
2809
|
+
x: 0,
|
|
2810
|
+
y: 0,
|
|
2811
|
+
w: 0,
|
|
2812
|
+
h: 0
|
|
2813
|
+
};
|
|
2057
2814
|
return {
|
|
2058
|
-
|
|
2059
|
-
|
|
2815
|
+
applyRectBrush(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn) {
|
|
2816
|
+
const bounds = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, writer.target.width, writer.target.height, boundsOut);
|
|
2060
2817
|
const {
|
|
2061
|
-
x
|
|
2062
|
-
y
|
|
2063
|
-
w
|
|
2064
|
-
h
|
|
2065
|
-
} =
|
|
2818
|
+
x,
|
|
2819
|
+
y,
|
|
2820
|
+
w,
|
|
2821
|
+
h
|
|
2822
|
+
} = bounds;
|
|
2066
2823
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2067
|
-
|
|
2824
|
+
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2068
2825
|
}
|
|
2069
2826
|
};
|
|
2827
|
+
});
|
|
2828
|
+
|
|
2829
|
+
// src/Rect/getRectBrushOrPencilStrokeBounds.ts
|
|
2830
|
+
function getRectBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushWidth, brushHeight, result) {
|
|
2831
|
+
const halfW = brushWidth / 2;
|
|
2832
|
+
const halfH = brushHeight / 2;
|
|
2833
|
+
const minX = Math.min(x0, x1) - halfW;
|
|
2834
|
+
const minY = Math.min(y0, y1) - halfH;
|
|
2835
|
+
const maxX = Math.max(x0, x1) + halfW;
|
|
2836
|
+
const maxY = Math.max(y0, y1) + halfH;
|
|
2837
|
+
result.x = Math.floor(minX);
|
|
2838
|
+
result.y = Math.floor(minY);
|
|
2839
|
+
result.w = Math.ceil(maxX - minX);
|
|
2840
|
+
result.h = Math.ceil(maxY - minY);
|
|
2841
|
+
return result;
|
|
2070
2842
|
}
|
|
2071
2843
|
|
|
2844
|
+
// src/History/PixelMutator/mutatorApplyRectBrushStroke.ts
|
|
2845
|
+
var defaults7 = {
|
|
2846
|
+
forEachLinePoint,
|
|
2847
|
+
blendColorPixelDataAlphaMask,
|
|
2848
|
+
getRectBrushOrPencilBounds,
|
|
2849
|
+
getRectBrushOrPencilStrokeBounds
|
|
2850
|
+
};
|
|
2851
|
+
var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
|
|
2852
|
+
const {
|
|
2853
|
+
forEachLinePoint: forEachLinePoint2 = defaults7.forEachLinePoint,
|
|
2854
|
+
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults7.blendColorPixelDataAlphaMask,
|
|
2855
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults7.getRectBrushOrPencilBounds,
|
|
2856
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults7.getRectBrushOrPencilStrokeBounds
|
|
2857
|
+
} = deps;
|
|
2858
|
+
const strokeBoundsOut = {
|
|
2859
|
+
x: 0,
|
|
2860
|
+
y: 0,
|
|
2861
|
+
w: 0,
|
|
2862
|
+
h: 0
|
|
2863
|
+
};
|
|
2864
|
+
const rectBrushBounds = {
|
|
2865
|
+
x: 0,
|
|
2866
|
+
y: 0,
|
|
2867
|
+
w: 0,
|
|
2868
|
+
h: 0
|
|
2869
|
+
};
|
|
2870
|
+
const blendColorPixelOptions = {
|
|
2871
|
+
alpha: 255,
|
|
2872
|
+
blendFn: sourceOverPerfect,
|
|
2873
|
+
x: 0,
|
|
2874
|
+
y: 0,
|
|
2875
|
+
w: 0,
|
|
2876
|
+
h: 0
|
|
2877
|
+
};
|
|
2878
|
+
return {
|
|
2879
|
+
applyRectBrushStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
2880
|
+
const {
|
|
2881
|
+
x: bx,
|
|
2882
|
+
y: by,
|
|
2883
|
+
w: bw,
|
|
2884
|
+
h: bh
|
|
2885
|
+
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
2886
|
+
if (bw <= 0 || bh <= 0) return;
|
|
2887
|
+
const mask = new Uint8Array(bw * bh);
|
|
2888
|
+
const halfW = brushWidth / 2;
|
|
2889
|
+
const halfH = brushHeight / 2;
|
|
2890
|
+
const invHalfW = 1 / halfW;
|
|
2891
|
+
const invHalfH = 1 / halfH;
|
|
2892
|
+
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2893
|
+
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2894
|
+
const targetWidth = writer.target.width;
|
|
2895
|
+
const targetHeight = writer.target.height;
|
|
2896
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2897
|
+
const {
|
|
2898
|
+
x: rbx,
|
|
2899
|
+
y: rby,
|
|
2900
|
+
w: rbw,
|
|
2901
|
+
h: rbh
|
|
2902
|
+
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectBrushBounds);
|
|
2903
|
+
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
2904
|
+
const startX = Math.max(bx, rbx);
|
|
2905
|
+
const startY = Math.max(by, rby);
|
|
2906
|
+
const endX = Math.min(bx + bw, rbx + rbw);
|
|
2907
|
+
const endY = Math.min(by + bh, rby + rbh);
|
|
2908
|
+
const fPx = Math.floor(px);
|
|
2909
|
+
const fPy = Math.floor(py);
|
|
2910
|
+
for (let my = startY; my < endY; my++) {
|
|
2911
|
+
const dy = Math.abs(my - fPy + centerOffsetY) * invHalfH;
|
|
2912
|
+
const maskRowOffset = (my - by) * bw;
|
|
2913
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
2914
|
+
const dx = Math.abs(mx - fPx + centerOffsetX) * invHalfW;
|
|
2915
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
2916
|
+
const dist = dx > dy ? dx : dy;
|
|
2917
|
+
const strength = fallOff(dist);
|
|
2918
|
+
if (strength > 0) {
|
|
2919
|
+
const intensity = strength * 255 | 0;
|
|
2920
|
+
if (intensity > mask[maskIdx]) {
|
|
2921
|
+
mask[maskIdx] = intensity;
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
});
|
|
2927
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
2928
|
+
blendColorPixelOptions.alpha = alpha;
|
|
2929
|
+
blendColorPixelOptions.x = bx;
|
|
2930
|
+
blendColorPixelOptions.y = by;
|
|
2931
|
+
blendColorPixelOptions.w = bw;
|
|
2932
|
+
blendColorPixelOptions.h = bh;
|
|
2933
|
+
blendColorPixelDataAlphaMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
2934
|
+
}
|
|
2935
|
+
};
|
|
2936
|
+
});
|
|
2937
|
+
|
|
2938
|
+
// src/History/PixelMutator/mutatorApplyRectPencil.ts
|
|
2939
|
+
var defaults8 = {
|
|
2940
|
+
applyRectBrushToPixelData,
|
|
2941
|
+
getRectBrushOrPencilBounds,
|
|
2942
|
+
fallOff: () => 1
|
|
2943
|
+
};
|
|
2944
|
+
var mutatorApplyRectPencil = ((writer, deps = defaults8) => {
|
|
2945
|
+
const {
|
|
2946
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults8.applyRectBrushToPixelData,
|
|
2947
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds,
|
|
2948
|
+
fallOff = defaults8.fallOff
|
|
2949
|
+
} = deps;
|
|
2950
|
+
const boundsOut = {
|
|
2951
|
+
x: 0,
|
|
2952
|
+
y: 0,
|
|
2953
|
+
w: 0,
|
|
2954
|
+
h: 0
|
|
2955
|
+
};
|
|
2956
|
+
return {
|
|
2957
|
+
applyRectPencil(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, blendFn) {
|
|
2958
|
+
const bounds = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, writer.target.width, writer.target.height, boundsOut);
|
|
2959
|
+
const {
|
|
2960
|
+
x,
|
|
2961
|
+
y,
|
|
2962
|
+
w,
|
|
2963
|
+
h
|
|
2964
|
+
} = bounds;
|
|
2965
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2966
|
+
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2967
|
+
}
|
|
2968
|
+
};
|
|
2969
|
+
});
|
|
2970
|
+
|
|
2971
|
+
// src/History/PixelMutator/mutatorApplyRectPencilStroke.ts
|
|
2972
|
+
var defaults9 = {
|
|
2973
|
+
forEachLinePoint,
|
|
2974
|
+
getRectBrushOrPencilBounds,
|
|
2975
|
+
getRectBrushOrPencilStrokeBounds,
|
|
2976
|
+
blendColorPixelDataBinaryMask
|
|
2977
|
+
};
|
|
2978
|
+
var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
|
|
2979
|
+
const {
|
|
2980
|
+
forEachLinePoint: forEachLinePoint2 = defaults9.forEachLinePoint,
|
|
2981
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults9.blendColorPixelDataBinaryMask,
|
|
2982
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
|
|
2983
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults9.getRectBrushOrPencilStrokeBounds
|
|
2984
|
+
} = deps;
|
|
2985
|
+
const strokeBoundsOut = {
|
|
2986
|
+
x: 0,
|
|
2987
|
+
y: 0,
|
|
2988
|
+
w: 0,
|
|
2989
|
+
h: 0
|
|
2990
|
+
};
|
|
2991
|
+
const rectPencilBounds = {
|
|
2992
|
+
x: 0,
|
|
2993
|
+
y: 0,
|
|
2994
|
+
w: 0,
|
|
2995
|
+
h: 0
|
|
2996
|
+
};
|
|
2997
|
+
const blendColorPixelOptions = {
|
|
2998
|
+
alpha: 255,
|
|
2999
|
+
blendFn: sourceOverPerfect,
|
|
3000
|
+
x: 0,
|
|
3001
|
+
y: 0,
|
|
3002
|
+
w: 0,
|
|
3003
|
+
h: 0
|
|
3004
|
+
};
|
|
3005
|
+
return {
|
|
3006
|
+
applyRectPencilStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, blendFn = sourceOverPerfect) {
|
|
3007
|
+
const {
|
|
3008
|
+
x: bx,
|
|
3009
|
+
y: by,
|
|
3010
|
+
w: bw,
|
|
3011
|
+
h: bh
|
|
3012
|
+
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
3013
|
+
if (bw <= 0 || bh <= 0) return;
|
|
3014
|
+
const mask = new Uint8Array(bw * bh);
|
|
3015
|
+
const halfW = brushWidth / 2;
|
|
3016
|
+
const halfH = brushHeight / 2;
|
|
3017
|
+
const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
3018
|
+
const targetWidth = writer.target.width;
|
|
3019
|
+
const targetHeight = writer.target.height;
|
|
3020
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
3021
|
+
const {
|
|
3022
|
+
x: rbx,
|
|
3023
|
+
y: rby,
|
|
3024
|
+
w: rbw,
|
|
3025
|
+
h: rbh
|
|
3026
|
+
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectPencilBounds);
|
|
3027
|
+
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
3028
|
+
const startX = Math.max(bx, rbx);
|
|
3029
|
+
const startY = Math.max(by, rby);
|
|
3030
|
+
const endX = Math.min(bx + bw, rbx + rbw);
|
|
3031
|
+
const endY = Math.min(by + bh, rby + rbh);
|
|
3032
|
+
const fPx = Math.floor(px);
|
|
3033
|
+
const fPy = Math.floor(py);
|
|
3034
|
+
for (let my = startY; my < endY; my++) {
|
|
3035
|
+
const dy = Math.abs(my - fPy + centerOffset);
|
|
3036
|
+
const maskRowOffset = (my - by) * bw;
|
|
3037
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
3038
|
+
const dx = Math.abs(mx - fPx + centerOffset);
|
|
3039
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
3040
|
+
if (dx <= halfW && dy <= halfH) {
|
|
3041
|
+
mask[maskIdx] = 1;
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
});
|
|
3046
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
3047
|
+
blendColorPixelOptions.alpha = alpha;
|
|
3048
|
+
blendColorPixelOptions.x = bx;
|
|
3049
|
+
blendColorPixelOptions.y = by;
|
|
3050
|
+
blendColorPixelOptions.w = bw;
|
|
3051
|
+
blendColorPixelOptions.h = bh;
|
|
3052
|
+
blendColorPixelDataBinaryMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
3053
|
+
}
|
|
3054
|
+
};
|
|
3055
|
+
});
|
|
3056
|
+
|
|
2072
3057
|
// src/PixelData/blendColorPixelData.ts
|
|
2073
3058
|
function blendColorPixelData(dst, color, opts = {}) {
|
|
2074
3059
|
const {
|
|
@@ -2077,22 +3062,13 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2077
3062
|
w: width = dst.width,
|
|
2078
3063
|
h: height = dst.height,
|
|
2079
3064
|
alpha: globalAlpha = 255,
|
|
2080
|
-
blendFn =
|
|
2081
|
-
mask,
|
|
2082
|
-
maskType = 0 /* ALPHA */,
|
|
2083
|
-
mw,
|
|
2084
|
-
mx = 0,
|
|
2085
|
-
my = 0,
|
|
2086
|
-
invertMask = false
|
|
3065
|
+
blendFn = sourceOverPerfect
|
|
2087
3066
|
} = opts;
|
|
2088
3067
|
if (globalAlpha === 0) return;
|
|
2089
3068
|
const baseSrcAlpha = color >>> 24;
|
|
2090
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
3069
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2091
3070
|
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2092
|
-
let x = targetX;
|
|
2093
|
-
let y = targetY;
|
|
2094
|
-
let w = width;
|
|
2095
|
-
let h = height;
|
|
3071
|
+
let x = targetX, y = targetY, w = width, h = height;
|
|
2096
3072
|
if (x < 0) {
|
|
2097
3073
|
w += x;
|
|
2098
3074
|
x = 0;
|
|
@@ -2104,76 +3080,33 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2104
3080
|
const actualW = Math.min(w, dst.width - x);
|
|
2105
3081
|
const actualH = Math.min(h, dst.height - y);
|
|
2106
3082
|
if (actualW <= 0 || actualH <= 0) return;
|
|
3083
|
+
let finalSrcColor = color;
|
|
3084
|
+
if (globalAlpha < 255) {
|
|
3085
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
3086
|
+
if (a === 0 && !isOverwrite) return;
|
|
3087
|
+
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
3088
|
+
}
|
|
2107
3089
|
const dst32 = dst.data32;
|
|
2108
3090
|
const dw = dst.width;
|
|
2109
|
-
|
|
2110
|
-
const
|
|
2111
|
-
const dx = x - targetX;
|
|
2112
|
-
const dy = y - targetY;
|
|
2113
|
-
let dIdx = y * dw + x;
|
|
2114
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2115
|
-
const dStride = dw - actualW;
|
|
2116
|
-
const mStride = mPitch - actualW;
|
|
3091
|
+
let dIdx = y * dw + x | 0;
|
|
3092
|
+
const dStride = dw - actualW | 0;
|
|
2117
3093
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2118
3094
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2119
|
-
|
|
2120
|
-
if (mask) {
|
|
2121
|
-
const mVal = mask[mIdx];
|
|
2122
|
-
if (isAlphaMask) {
|
|
2123
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2124
|
-
if (effectiveM === 0) {
|
|
2125
|
-
dIdx++;
|
|
2126
|
-
mIdx++;
|
|
2127
|
-
continue;
|
|
2128
|
-
}
|
|
2129
|
-
if (globalAlpha === 255) {
|
|
2130
|
-
weight = effectiveM;
|
|
2131
|
-
} else if (effectiveM === 255) {
|
|
2132
|
-
weight = globalAlpha;
|
|
2133
|
-
} else {
|
|
2134
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2135
|
-
}
|
|
2136
|
-
} else {
|
|
2137
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2138
|
-
if (!isHit) {
|
|
2139
|
-
dIdx++;
|
|
2140
|
-
mIdx++;
|
|
2141
|
-
continue;
|
|
2142
|
-
}
|
|
2143
|
-
weight = globalAlpha;
|
|
2144
|
-
}
|
|
2145
|
-
if (weight === 0) {
|
|
2146
|
-
dIdx++;
|
|
2147
|
-
mIdx++;
|
|
2148
|
-
continue;
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
let currentSrcColor = color;
|
|
2152
|
-
if (weight < 255) {
|
|
2153
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2154
|
-
if (baseSrcAlpha === 255) {
|
|
2155
|
-
currentSrcAlpha = weight;
|
|
2156
|
-
} else {
|
|
2157
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2158
|
-
}
|
|
2159
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2160
|
-
dIdx++;
|
|
2161
|
-
mIdx++;
|
|
2162
|
-
continue;
|
|
2163
|
-
}
|
|
2164
|
-
currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
2165
|
-
}
|
|
2166
|
-
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
3095
|
+
dst32[dIdx] = blendFn(finalSrcColor, dst32[dIdx]);
|
|
2167
3096
|
dIdx++;
|
|
2168
|
-
mIdx++;
|
|
2169
3097
|
}
|
|
2170
3098
|
dIdx += dStride;
|
|
2171
|
-
mIdx += mStride;
|
|
2172
3099
|
}
|
|
2173
3100
|
}
|
|
2174
3101
|
|
|
2175
3102
|
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2176
|
-
|
|
3103
|
+
var defaults10 = {
|
|
3104
|
+
blendColorPixelData
|
|
3105
|
+
};
|
|
3106
|
+
var mutatorBlendColor = ((writer, deps = defaults10) => {
|
|
3107
|
+
const {
|
|
3108
|
+
blendColorPixelData: blendColorPixelData2 = defaults10.blendColorPixelData
|
|
3109
|
+
} = deps;
|
|
2177
3110
|
return {
|
|
2178
3111
|
blendColor(color, opts = {}) {
|
|
2179
3112
|
const {
|
|
@@ -2183,10 +3116,10 @@ function mutatorBlendColor(writer) {
|
|
|
2183
3116
|
h = writer.target.height
|
|
2184
3117
|
} = opts;
|
|
2185
3118
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2186
|
-
|
|
3119
|
+
blendColorPixelData2(writer.target, color, opts);
|
|
2187
3120
|
}
|
|
2188
3121
|
};
|
|
2189
|
-
}
|
|
3122
|
+
});
|
|
2190
3123
|
|
|
2191
3124
|
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2192
3125
|
function mutatorBlendPixel(writer) {
|
|
@@ -2220,13 +3153,7 @@ function blendPixelData(dst, src, opts) {
|
|
|
2220
3153
|
w: width = src.width,
|
|
2221
3154
|
h: height = src.height,
|
|
2222
3155
|
alpha: globalAlpha = 255,
|
|
2223
|
-
blendFn =
|
|
2224
|
-
mask,
|
|
2225
|
-
maskType = 0 /* ALPHA */,
|
|
2226
|
-
mw,
|
|
2227
|
-
mx = 0,
|
|
2228
|
-
my = 0,
|
|
2229
|
-
invertMask = false
|
|
3156
|
+
blendFn = sourceOverPerfect
|
|
2230
3157
|
} = opts;
|
|
2231
3158
|
if (globalAlpha === 0) return;
|
|
2232
3159
|
let x = targetX;
|
|
@@ -2264,91 +3191,48 @@ function blendPixelData(dst, src, opts) {
|
|
|
2264
3191
|
const src32 = src.data32;
|
|
2265
3192
|
const dw = dst.width;
|
|
2266
3193
|
const sw = src.width;
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
const
|
|
2270
|
-
const
|
|
2271
|
-
|
|
2272
|
-
let sIdx = sy * sw + sx;
|
|
2273
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2274
|
-
const dStride = dw - actualW;
|
|
2275
|
-
const sStride = sw - actualW;
|
|
2276
|
-
const mStride = mPitch - actualW;
|
|
3194
|
+
let dIdx = y * dw + x | 0;
|
|
3195
|
+
let sIdx = sy * sw + sx | 0;
|
|
3196
|
+
const dStride = dw - actualW | 0;
|
|
3197
|
+
const sStride = sw - actualW | 0;
|
|
3198
|
+
const isOpaque = globalAlpha === 255;
|
|
2277
3199
|
const isOverwrite = blendFn.isOverwrite;
|
|
2278
3200
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2279
3201
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2280
|
-
const
|
|
2281
|
-
const
|
|
2282
|
-
if (
|
|
3202
|
+
const srcCol = src32[sIdx];
|
|
3203
|
+
const srcAlpha = srcCol >>> 24;
|
|
3204
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2283
3205
|
dIdx++;
|
|
2284
3206
|
sIdx++;
|
|
2285
|
-
mIdx++;
|
|
2286
3207
|
continue;
|
|
2287
3208
|
}
|
|
2288
|
-
let
|
|
2289
|
-
if (
|
|
2290
|
-
const
|
|
2291
|
-
if (
|
|
2292
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2293
|
-
if (effectiveM === 0) {
|
|
2294
|
-
dIdx++;
|
|
2295
|
-
sIdx++;
|
|
2296
|
-
mIdx++;
|
|
2297
|
-
continue;
|
|
2298
|
-
}
|
|
2299
|
-
if (globalAlpha === 255) {
|
|
2300
|
-
weight = effectiveM;
|
|
2301
|
-
} else if (effectiveM === 255) {
|
|
2302
|
-
weight = globalAlpha;
|
|
2303
|
-
} else {
|
|
2304
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2305
|
-
}
|
|
2306
|
-
} else {
|
|
2307
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2308
|
-
if (!isHit) {
|
|
2309
|
-
dIdx++;
|
|
2310
|
-
sIdx++;
|
|
2311
|
-
mIdx++;
|
|
2312
|
-
continue;
|
|
2313
|
-
}
|
|
2314
|
-
weight = globalAlpha;
|
|
2315
|
-
}
|
|
2316
|
-
if (weight === 0) {
|
|
2317
|
-
dIdx++;
|
|
2318
|
-
sIdx++;
|
|
2319
|
-
mIdx++;
|
|
2320
|
-
continue;
|
|
2321
|
-
}
|
|
2322
|
-
}
|
|
2323
|
-
let currentSrcColor = baseSrcColor;
|
|
2324
|
-
if (weight < 255) {
|
|
2325
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2326
|
-
if (baseSrcAlpha === 255) {
|
|
2327
|
-
currentSrcAlpha = weight;
|
|
2328
|
-
} else {
|
|
2329
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2330
|
-
}
|
|
2331
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
3209
|
+
let finalCol = srcCol;
|
|
3210
|
+
if (!isOpaque) {
|
|
3211
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
3212
|
+
if (a === 0 && !isOverwrite) {
|
|
2332
3213
|
dIdx++;
|
|
2333
3214
|
sIdx++;
|
|
2334
|
-
mIdx++;
|
|
2335
3215
|
continue;
|
|
2336
3216
|
}
|
|
2337
|
-
|
|
3217
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2338
3218
|
}
|
|
2339
|
-
dst32[dIdx] = blendFn(
|
|
3219
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
2340
3220
|
dIdx++;
|
|
2341
3221
|
sIdx++;
|
|
2342
|
-
mIdx++;
|
|
2343
3222
|
}
|
|
2344
3223
|
dIdx += dStride;
|
|
2345
3224
|
sIdx += sStride;
|
|
2346
|
-
mIdx += mStride;
|
|
2347
3225
|
}
|
|
2348
3226
|
}
|
|
2349
3227
|
|
|
2350
3228
|
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
2351
|
-
|
|
3229
|
+
var defaults11 = {
|
|
3230
|
+
blendPixelData
|
|
3231
|
+
};
|
|
3232
|
+
var mutatorBlendPixelData = ((writer, deps = defaults11) => {
|
|
3233
|
+
const {
|
|
3234
|
+
blendPixelData: blendPixelData2 = defaults11.blendPixelData
|
|
3235
|
+
} = deps;
|
|
2352
3236
|
return {
|
|
2353
3237
|
blendPixelData(src, opts) {
|
|
2354
3238
|
const {
|
|
@@ -2358,12 +3242,13 @@ function mutatorBlendPixelData(writer) {
|
|
|
2358
3242
|
h = src.height
|
|
2359
3243
|
} = opts;
|
|
2360
3244
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2361
|
-
|
|
3245
|
+
blendPixelData2(writer.target, src, opts);
|
|
2362
3246
|
}
|
|
2363
3247
|
};
|
|
2364
|
-
}
|
|
3248
|
+
});
|
|
2365
3249
|
|
|
2366
3250
|
// src/PixelData/fillPixelData.ts
|
|
3251
|
+
var SCRATCH_RECT = makeClippedRect();
|
|
2367
3252
|
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
2368
3253
|
let x;
|
|
2369
3254
|
let y;
|
|
@@ -2385,34 +3270,57 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
|
2385
3270
|
w = dst.width;
|
|
2386
3271
|
h = dst.height;
|
|
2387
3272
|
}
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
}
|
|
2396
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2397
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2398
|
-
if (actualW <= 0 || actualH <= 0) {
|
|
2399
|
-
return;
|
|
2400
|
-
}
|
|
3273
|
+
const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT);
|
|
3274
|
+
if (!clip.inBounds) return;
|
|
3275
|
+
const {
|
|
3276
|
+
x: finalX,
|
|
3277
|
+
y: finalY,
|
|
3278
|
+
w: actualW,
|
|
3279
|
+
h: actualH
|
|
3280
|
+
} = clip;
|
|
2401
3281
|
const dst32 = dst.data32;
|
|
2402
3282
|
const dw = dst.width;
|
|
2403
|
-
if (actualW === dw && actualH === dst.height &&
|
|
3283
|
+
if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
|
|
2404
3284
|
dst32.fill(color);
|
|
2405
3285
|
return;
|
|
2406
3286
|
}
|
|
2407
3287
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2408
|
-
const start = (
|
|
3288
|
+
const start = (finalY + iy) * dw + finalX;
|
|
2409
3289
|
const end = start + actualW;
|
|
2410
3290
|
dst32.fill(color, start, end);
|
|
2411
3291
|
}
|
|
2412
3292
|
}
|
|
2413
3293
|
|
|
2414
|
-
// src/History/PixelMutator/
|
|
2415
|
-
|
|
3294
|
+
// src/History/PixelMutator/mutatorClear.ts
|
|
3295
|
+
var defaults12 = {
|
|
3296
|
+
fillPixelData
|
|
3297
|
+
};
|
|
3298
|
+
var mutatorClear = ((writer, deps = defaults12) => {
|
|
3299
|
+
const {
|
|
3300
|
+
fillPixelData: fillPixelData2 = defaults12.fillPixelData
|
|
3301
|
+
} = deps;
|
|
3302
|
+
return {
|
|
3303
|
+
clear(rect = {}) {
|
|
3304
|
+
const {
|
|
3305
|
+
x = 0,
|
|
3306
|
+
y = 0,
|
|
3307
|
+
w = writer.target.width,
|
|
3308
|
+
h = writer.target.height
|
|
3309
|
+
} = rect;
|
|
3310
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3311
|
+
fillPixelData2(writer.target, 0, x, y, w, h);
|
|
3312
|
+
}
|
|
3313
|
+
};
|
|
3314
|
+
});
|
|
3315
|
+
|
|
3316
|
+
// src/History/PixelMutator/mutatorFill.ts
|
|
3317
|
+
var defaults13 = {
|
|
3318
|
+
fillPixelData
|
|
3319
|
+
};
|
|
3320
|
+
var mutatorFill = ((writer, deps = defaults13) => {
|
|
3321
|
+
const {
|
|
3322
|
+
fillPixelData: fillPixelData2 = defaults13.fillPixelData
|
|
3323
|
+
} = deps;
|
|
2416
3324
|
return {
|
|
2417
3325
|
fill(color, rect = {}) {
|
|
2418
3326
|
const {
|
|
@@ -2422,12 +3330,13 @@ function mutatorFill(writer) {
|
|
|
2422
3330
|
h = writer.target.height
|
|
2423
3331
|
} = rect;
|
|
2424
3332
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2425
|
-
|
|
3333
|
+
fillPixelData2(writer.target, color, x, y, w, h);
|
|
2426
3334
|
}
|
|
2427
3335
|
};
|
|
2428
|
-
}
|
|
3336
|
+
});
|
|
2429
3337
|
|
|
2430
3338
|
// src/PixelData/invertPixelData.ts
|
|
3339
|
+
var SCRATCH_RECT2 = makeClippedRect();
|
|
2431
3340
|
function invertPixelData(pixelData, opts = {}) {
|
|
2432
3341
|
const dst = pixelData;
|
|
2433
3342
|
const {
|
|
@@ -2441,21 +3350,14 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
2441
3350
|
my = 0,
|
|
2442
3351
|
invertMask = false
|
|
2443
3352
|
} = opts;
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
w
|
|
2450
|
-
|
|
2451
|
-
}
|
|
2452
|
-
if (y < 0) {
|
|
2453
|
-
h += y;
|
|
2454
|
-
y = 0;
|
|
2455
|
-
}
|
|
2456
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2457
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2458
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3353
|
+
const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT2);
|
|
3354
|
+
if (!clip.inBounds) return;
|
|
3355
|
+
const {
|
|
3356
|
+
x,
|
|
3357
|
+
y,
|
|
3358
|
+
w: actualW,
|
|
3359
|
+
h: actualH
|
|
3360
|
+
} = clip;
|
|
2459
3361
|
const dst32 = dst.data32;
|
|
2460
3362
|
const dw = dst.width;
|
|
2461
3363
|
const mPitch = mw ?? width;
|
|
@@ -2491,7 +3393,13 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
2491
3393
|
}
|
|
2492
3394
|
|
|
2493
3395
|
// src/History/PixelMutator/mutatorInvert.ts
|
|
2494
|
-
|
|
3396
|
+
var defaults14 = {
|
|
3397
|
+
invertPixelData
|
|
3398
|
+
};
|
|
3399
|
+
var mutatorInvert = ((writer, deps = defaults14) => {
|
|
3400
|
+
const {
|
|
3401
|
+
invertPixelData: invertPixelData2 = defaults14.invertPixelData
|
|
3402
|
+
} = deps;
|
|
2495
3403
|
return {
|
|
2496
3404
|
invert(opts = {}) {
|
|
2497
3405
|
const {
|
|
@@ -2501,44 +3409,121 @@ function mutatorInvert(writer) {
|
|
|
2501
3409
|
h = writer.target.height
|
|
2502
3410
|
} = opts;
|
|
2503
3411
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2504
|
-
|
|
3412
|
+
invertPixelData2(writer.target, opts);
|
|
2505
3413
|
}
|
|
2506
3414
|
};
|
|
2507
|
-
}
|
|
3415
|
+
});
|
|
2508
3416
|
|
|
2509
3417
|
// src/History/PixelMutator.ts
|
|
2510
3418
|
function makeFullPixelMutator(writer) {
|
|
2511
3419
|
return {
|
|
2512
|
-
...
|
|
3420
|
+
...mutatorApplyAlphaMask(writer),
|
|
3421
|
+
...mutatorApplyBinaryMask(writer),
|
|
2513
3422
|
...mutatorBlendPixelData(writer),
|
|
2514
3423
|
...mutatorBlendColor(writer),
|
|
2515
3424
|
...mutatorBlendPixel(writer),
|
|
2516
3425
|
...mutatorFill(writer),
|
|
2517
|
-
...mutatorInvert(writer)
|
|
3426
|
+
...mutatorInvert(writer),
|
|
3427
|
+
...mutatorApplyCircleBrush(writer),
|
|
3428
|
+
...mutatorApplyCircleBrushStroke(writer),
|
|
3429
|
+
...mutatorApplyCirclePencilStroke(writer),
|
|
3430
|
+
...mutatorApplyRectBrush(writer),
|
|
3431
|
+
...mutatorApplyRectBrushStroke(writer),
|
|
3432
|
+
...mutatorApplyRectPencil(writer),
|
|
3433
|
+
...mutatorApplyRectPencilStroke(writer),
|
|
3434
|
+
...mutatorClear(writer)
|
|
2518
3435
|
};
|
|
2519
3436
|
}
|
|
2520
3437
|
|
|
2521
|
-
// src/
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
3438
|
+
// src/History/PixelWriter.ts
|
|
3439
|
+
var PixelWriter = class {
|
|
3440
|
+
target;
|
|
3441
|
+
historyManager;
|
|
3442
|
+
accumulator;
|
|
3443
|
+
config;
|
|
3444
|
+
mutator;
|
|
3445
|
+
constructor(target, mutatorFactory, {
|
|
3446
|
+
tileSize = 256,
|
|
3447
|
+
maxHistorySteps = 50,
|
|
3448
|
+
historyManager = new HistoryManager(maxHistorySteps)
|
|
3449
|
+
} = {}) {
|
|
3450
|
+
this.target = target;
|
|
3451
|
+
this.config = new PixelEngineConfig(tileSize);
|
|
3452
|
+
this.historyManager = historyManager;
|
|
3453
|
+
this.accumulator = new PixelAccumulator(target, this.config);
|
|
3454
|
+
this.mutator = mutatorFactory(this);
|
|
3455
|
+
}
|
|
3456
|
+
withHistory(cb) {
|
|
3457
|
+
cb(this.mutator);
|
|
3458
|
+
this.captureHistory();
|
|
3459
|
+
}
|
|
3460
|
+
captureHistory() {
|
|
3461
|
+
const beforeTiles = this.accumulator.beforeTiles;
|
|
3462
|
+
if (beforeTiles.length === 0) return;
|
|
3463
|
+
const afterTiles = this.accumulator.extractAfterTiles();
|
|
3464
|
+
const patch = {
|
|
3465
|
+
beforeTiles,
|
|
3466
|
+
afterTiles
|
|
3467
|
+
};
|
|
3468
|
+
const target = this.target;
|
|
3469
|
+
const tileSize = this.config.tileSize;
|
|
3470
|
+
const accumulator = this.accumulator;
|
|
3471
|
+
const action = {
|
|
3472
|
+
undo: () => applyPatchTiles(target, patch.beforeTiles, tileSize),
|
|
3473
|
+
redo: () => applyPatchTiles(target, patch.afterTiles, tileSize),
|
|
3474
|
+
dispose: () => accumulator.recyclePatch(patch)
|
|
3475
|
+
};
|
|
3476
|
+
this.historyManager.commit(action);
|
|
3477
|
+
this.accumulator.reset();
|
|
3478
|
+
}
|
|
3479
|
+
};
|
|
3480
|
+
|
|
3481
|
+
// src/History/PixelMutator/mutatorApplyCirclePencil.ts
|
|
3482
|
+
var defaults15 = {
|
|
3483
|
+
applyCircleBrushToPixelData,
|
|
3484
|
+
getCircleBrushOrPencilBounds,
|
|
3485
|
+
fallOff: () => 1
|
|
3486
|
+
};
|
|
3487
|
+
var mutatorApplyCirclePencil = ((writer, deps = defaults15) => {
|
|
3488
|
+
const {
|
|
3489
|
+
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults15.applyCircleBrushToPixelData,
|
|
3490
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults15.getCircleBrushOrPencilBounds,
|
|
3491
|
+
fallOff = defaults15.fallOff
|
|
3492
|
+
} = deps;
|
|
3493
|
+
const boundsOut = {
|
|
3494
|
+
x: 0,
|
|
3495
|
+
y: 0,
|
|
3496
|
+
w: 0,
|
|
3497
|
+
h: 0
|
|
3498
|
+
};
|
|
3499
|
+
return {
|
|
3500
|
+
applyCirclePencil(color, centerX, centerY, brushSize, alpha = 255, blendFn) {
|
|
3501
|
+
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
|
|
3502
|
+
const {
|
|
3503
|
+
x,
|
|
3504
|
+
y,
|
|
3505
|
+
w,
|
|
3506
|
+
h
|
|
3507
|
+
} = bounds;
|
|
3508
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3509
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
|
|
2532
3510
|
}
|
|
2533
|
-
return imageData;
|
|
2534
3511
|
};
|
|
2535
|
-
}
|
|
3512
|
+
});
|
|
2536
3513
|
|
|
2537
3514
|
// src/ImageData/copyImageData.ts
|
|
2538
|
-
function copyImageData({
|
|
3515
|
+
function copyImageData({
|
|
3516
|
+
data,
|
|
3517
|
+
width,
|
|
3518
|
+
height
|
|
3519
|
+
}) {
|
|
2539
3520
|
return new ImageData(data.slice(), width, height);
|
|
2540
3521
|
}
|
|
2541
|
-
function copyImageDataLike({
|
|
3522
|
+
function copyImageDataLike({
|
|
3523
|
+
data,
|
|
3524
|
+
width,
|
|
3525
|
+
height
|
|
3526
|
+
}) {
|
|
2542
3527
|
return {
|
|
2543
3528
|
data: data.slice(),
|
|
2544
3529
|
width,
|
|
@@ -2546,20 +3531,15 @@ function copyImageDataLike({ data, width, height }) {
|
|
|
2546
3531
|
};
|
|
2547
3532
|
}
|
|
2548
3533
|
|
|
2549
|
-
// src/
|
|
2550
|
-
function
|
|
2551
|
-
const
|
|
2552
|
-
|
|
3534
|
+
// src/ImageData/ImageDataLike.ts
|
|
3535
|
+
function makeImageDataLike(width, height, data) {
|
|
3536
|
+
const size = width * height * 4;
|
|
3537
|
+
const buffer = data ? new Uint8ClampedArray(data.buffer, data.byteOffset, size) : new Uint8ClampedArray(size);
|
|
3538
|
+
return {
|
|
2553
3539
|
width,
|
|
2554
|
-
height
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
const mask = new Uint8Array(width * height);
|
|
2558
|
-
for (let i = 0; i < len; i++) {
|
|
2559
|
-
const val = data32[i];
|
|
2560
|
-
mask[i] = val >>> 24 & 255;
|
|
2561
|
-
}
|
|
2562
|
-
return mask;
|
|
3540
|
+
height,
|
|
3541
|
+
data: buffer
|
|
3542
|
+
};
|
|
2563
3543
|
}
|
|
2564
3544
|
|
|
2565
3545
|
// src/ImageData/imageDataToAlphaMask.ts
|
|
@@ -2569,11 +3549,7 @@ function imageDataToAlphaMask(imageData) {
|
|
|
2569
3549
|
height,
|
|
2570
3550
|
data
|
|
2571
3551
|
} = imageData;
|
|
2572
|
-
const data32 = new Uint32Array(
|
|
2573
|
-
data.buffer,
|
|
2574
|
-
data.byteOffset,
|
|
2575
|
-
data.byteLength >> 2
|
|
2576
|
-
);
|
|
3552
|
+
const data32 = new Uint32Array(data.buffer, data.byteOffset, data.byteLength >> 2);
|
|
2577
3553
|
const len = data32.length;
|
|
2578
3554
|
const mask = new Uint8Array(width * height);
|
|
2579
3555
|
for (let i = 0; i < len; i++) {
|
|
@@ -2586,7 +3562,10 @@ function imageDataToAlphaMask(imageData) {
|
|
|
2586
3562
|
// src/ImageData/imageDataToDataUrl.ts
|
|
2587
3563
|
var get = makeReusableCanvas();
|
|
2588
3564
|
function imageDataToDataUrl(imageData) {
|
|
2589
|
-
const {
|
|
3565
|
+
const {
|
|
3566
|
+
canvas,
|
|
3567
|
+
ctx
|
|
3568
|
+
} = get(imageData.width, imageData.height);
|
|
2590
3569
|
ctx.putImageData(imageData, 0, 0);
|
|
2591
3570
|
return canvas.toDataURL();
|
|
2592
3571
|
}
|
|
@@ -2644,7 +3623,11 @@ function resample32(srcData32, srcW, srcH, factor) {
|
|
|
2644
3623
|
// src/ImageData/resampleImageData.ts
|
|
2645
3624
|
function resampleImageData(source, factor) {
|
|
2646
3625
|
const src32 = new Uint32Array(source.data.buffer);
|
|
2647
|
-
const {
|
|
3626
|
+
const {
|
|
3627
|
+
data,
|
|
3628
|
+
width,
|
|
3629
|
+
height
|
|
3630
|
+
} = resample32(src32, source.width, source.height, factor);
|
|
2648
3631
|
const uint8ClampedArray = new Uint8ClampedArray(data.buffer);
|
|
2649
3632
|
return new ImageData(uint8ClampedArray, width, height);
|
|
2650
3633
|
}
|
|
@@ -2673,14 +3656,25 @@ function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0)
|
|
|
2673
3656
|
const srcX = x0 - offsetX;
|
|
2674
3657
|
const dstStart = (dstY * newWidth + x0) * 4;
|
|
2675
3658
|
const srcStart = (srcY * oldW + srcX) * 4;
|
|
2676
|
-
newData.set(
|
|
2677
|
-
oldData.subarray(srcStart, srcStart + rowLen),
|
|
2678
|
-
dstStart
|
|
2679
|
-
);
|
|
3659
|
+
newData.set(oldData.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
2680
3660
|
}
|
|
2681
3661
|
return result;
|
|
2682
3662
|
}
|
|
2683
3663
|
|
|
3664
|
+
// src/ImageData/ReusableImageData.ts
|
|
3665
|
+
function makeReusableImageData() {
|
|
3666
|
+
let imageData = null;
|
|
3667
|
+
return function getReusableImageData(width, height) {
|
|
3668
|
+
const hasInstance = !!imageData;
|
|
3669
|
+
const widthMatches = hasInstance && imageData.width === width;
|
|
3670
|
+
const heightMatches = hasInstance && imageData.height === height;
|
|
3671
|
+
if (!widthMatches || !heightMatches) {
|
|
3672
|
+
imageData = new ImageData(width, height);
|
|
3673
|
+
}
|
|
3674
|
+
return imageData;
|
|
3675
|
+
};
|
|
3676
|
+
}
|
|
3677
|
+
|
|
2684
3678
|
// src/ImageData/serialization.ts
|
|
2685
3679
|
function base64EncodeArrayBuffer(buffer) {
|
|
2686
3680
|
const uint8 = new Uint8Array(buffer);
|
|
@@ -2723,32 +3717,53 @@ function deserializeNullableImageData(serialized) {
|
|
|
2723
3717
|
return deserializeImageData(serialized);
|
|
2724
3718
|
}
|
|
2725
3719
|
|
|
3720
|
+
// src/ImageData/uInt32ArrayToImageData.ts
|
|
3721
|
+
function uInt32ArrayToImageData(data, width, height) {
|
|
3722
|
+
const buffer = data.buffer;
|
|
3723
|
+
const byteOffset = data.byteOffset;
|
|
3724
|
+
const byteLength = data.byteLength;
|
|
3725
|
+
const clampedArray = new Uint8ClampedArray(buffer, byteOffset, byteLength);
|
|
3726
|
+
return new ImageData(clampedArray, width, height);
|
|
3727
|
+
}
|
|
3728
|
+
function uInt32ArrayToImageDataLike(data, width, height) {
|
|
3729
|
+
const buffer = data.buffer;
|
|
3730
|
+
const byteOffset = data.byteOffset;
|
|
3731
|
+
const byteLength = data.byteLength;
|
|
3732
|
+
const clampedArray = new Uint8ClampedArray(buffer, byteOffset, byteLength);
|
|
3733
|
+
return {
|
|
3734
|
+
width,
|
|
3735
|
+
height,
|
|
3736
|
+
data: clampedArray
|
|
3737
|
+
};
|
|
3738
|
+
}
|
|
3739
|
+
|
|
2726
3740
|
// src/ImageData/writeImageData.ts
|
|
3741
|
+
var SCRATCH_BLIT2 = makeClippedBlit();
|
|
2727
3742
|
function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
|
|
2728
3743
|
const dstW = target.width;
|
|
2729
3744
|
const dstH = target.height;
|
|
2730
3745
|
const dstData = target.data;
|
|
2731
3746
|
const srcW = source.width;
|
|
2732
3747
|
const srcData = source.data;
|
|
2733
|
-
const
|
|
2734
|
-
|
|
2735
|
-
const
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
3748
|
+
const clip = resolveBlitClipping(x, y, sx, sy, sw, sh, dstW, dstH, srcW, source.height, SCRATCH_BLIT2);
|
|
3749
|
+
if (!clip.inBounds) return;
|
|
3750
|
+
const {
|
|
3751
|
+
x: dstX,
|
|
3752
|
+
y: dstY,
|
|
3753
|
+
sx: srcX,
|
|
3754
|
+
sy: srcY,
|
|
3755
|
+
w: copyW,
|
|
3756
|
+
h: copyH
|
|
3757
|
+
} = clip;
|
|
2740
3758
|
const useMask = !!mask;
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
const
|
|
2745
|
-
const
|
|
2746
|
-
const srcXBase = sx + (x0 - x);
|
|
2747
|
-
const dstStart = (dstY * dstW + x0) * 4;
|
|
2748
|
-
const srcStart = (srcY * srcW + srcXBase) * 4;
|
|
3759
|
+
for (let row = 0; row < copyH; row++) {
|
|
3760
|
+
const currentDstY = dstY + row;
|
|
3761
|
+
const currentSrcY = srcY + row;
|
|
3762
|
+
const dstStart = (currentDstY * dstW + dstX) * 4;
|
|
3763
|
+
const srcStart = (currentSrcY * srcW + srcX) * 4;
|
|
2749
3764
|
if (useMask && mask) {
|
|
2750
|
-
for (let ix = 0; ix <
|
|
2751
|
-
const mi =
|
|
3765
|
+
for (let ix = 0; ix < copyW; ix++) {
|
|
3766
|
+
const mi = currentSrcY * srcW + (srcX + ix);
|
|
2752
3767
|
const alpha = mask[mi];
|
|
2753
3768
|
if (alpha === 0) {
|
|
2754
3769
|
continue;
|
|
@@ -2770,7 +3785,7 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
|
|
|
2770
3785
|
}
|
|
2771
3786
|
}
|
|
2772
3787
|
} else {
|
|
2773
|
-
const byteLen =
|
|
3788
|
+
const byteLen = copyW * 4;
|
|
2774
3789
|
const sub = srcData.subarray(srcStart, srcStart + byteLen);
|
|
2775
3790
|
dstData.set(sub, dstStart);
|
|
2776
3791
|
}
|
|
@@ -2778,24 +3793,52 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
|
|
|
2778
3793
|
}
|
|
2779
3794
|
|
|
2780
3795
|
// src/ImageData/writeImageDataBuffer.ts
|
|
3796
|
+
var SCRATCH_BLIT3 = makeClippedBlit();
|
|
2781
3797
|
function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
|
|
2782
|
-
const {
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
3798
|
+
const {
|
|
3799
|
+
x,
|
|
3800
|
+
y,
|
|
3801
|
+
w,
|
|
3802
|
+
h
|
|
3803
|
+
} = typeof _x === "object" ? _x : {
|
|
3804
|
+
x: _x,
|
|
3805
|
+
y: _y,
|
|
3806
|
+
w: _w,
|
|
3807
|
+
h: _h
|
|
3808
|
+
};
|
|
3809
|
+
const {
|
|
3810
|
+
width: dstW,
|
|
3811
|
+
height: dstH,
|
|
3812
|
+
data: dst
|
|
3813
|
+
} = imageData;
|
|
3814
|
+
const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT3);
|
|
3815
|
+
if (!clip.inBounds) return;
|
|
3816
|
+
const {
|
|
3817
|
+
x: dstX,
|
|
3818
|
+
y: dstY,
|
|
3819
|
+
sx: srcX,
|
|
3820
|
+
sy: srcY,
|
|
3821
|
+
w: copyW,
|
|
3822
|
+
h: copyH
|
|
3823
|
+
} = clip;
|
|
3824
|
+
const rowLen = copyW * 4;
|
|
3825
|
+
for (let row = 0; row < copyH; row++) {
|
|
3826
|
+
const dstStart = ((dstY + row) * dstW + dstX) * 4;
|
|
3827
|
+
const srcStart = ((srcY + row) * w + srcX) * 4;
|
|
3828
|
+
dst.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
// src/IndexedImage/getIndexedImageColorCounts.ts
|
|
3833
|
+
function getIndexedImageColorCounts(indexedImage) {
|
|
3834
|
+
const data = indexedImage.data;
|
|
3835
|
+
const palette = indexedImage.palette;
|
|
3836
|
+
const frequencies = new Int32Array(palette.length);
|
|
3837
|
+
for (let i = 0; i < data.length; i++) {
|
|
3838
|
+
const colorIndex = data[i];
|
|
3839
|
+
frequencies[colorIndex]++;
|
|
2798
3840
|
}
|
|
3841
|
+
return frequencies;
|
|
2799
3842
|
}
|
|
2800
3843
|
|
|
2801
3844
|
// src/IndexedImage/IndexedImage.ts
|
|
@@ -2861,13 +3904,7 @@ var IndexedImage = class _IndexedImage {
|
|
|
2861
3904
|
indexedData[i] = id;
|
|
2862
3905
|
}
|
|
2863
3906
|
const palette = Uint32Array.from(colorMap.keys());
|
|
2864
|
-
return new _IndexedImage(
|
|
2865
|
-
width,
|
|
2866
|
-
height,
|
|
2867
|
-
indexedData,
|
|
2868
|
-
palette,
|
|
2869
|
-
transparentPalletIndex
|
|
2870
|
-
);
|
|
3907
|
+
return new _IndexedImage(width, height, indexedData, palette, transparentPalletIndex);
|
|
2871
3908
|
}
|
|
2872
3909
|
/**
|
|
2873
3910
|
* Retrieves the 32-bit packed color value at the given coordinates.
|
|
@@ -2882,21 +3919,13 @@ var IndexedImage = class _IndexedImage {
|
|
|
2882
3919
|
}
|
|
2883
3920
|
};
|
|
2884
3921
|
|
|
2885
|
-
// src/IndexedImage/getIndexedImageColorCounts.ts
|
|
2886
|
-
function getIndexedImageColorCounts(indexedImage) {
|
|
2887
|
-
const data = indexedImage.data;
|
|
2888
|
-
const palette = indexedImage.palette;
|
|
2889
|
-
const frequencies = new Int32Array(palette.length);
|
|
2890
|
-
for (let i = 0; i < data.length; i++) {
|
|
2891
|
-
const colorIndex = data[i];
|
|
2892
|
-
frequencies[colorIndex]++;
|
|
2893
|
-
}
|
|
2894
|
-
return frequencies;
|
|
2895
|
-
}
|
|
2896
|
-
|
|
2897
3922
|
// src/IndexedImage/indexedImageToAverageColor.ts
|
|
2898
3923
|
function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
|
|
2899
|
-
const {
|
|
3924
|
+
const {
|
|
3925
|
+
data,
|
|
3926
|
+
palette,
|
|
3927
|
+
transparentPalletIndex
|
|
3928
|
+
} = indexedImage;
|
|
2900
3929
|
const counts = new Uint32Array(palette.length);
|
|
2901
3930
|
for (let i = 0; i < data.length; i++) {
|
|
2902
3931
|
const id = data[i];
|
|
@@ -2936,26 +3965,14 @@ function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
|
|
|
2936
3965
|
return packColor(r, g, b, a);
|
|
2937
3966
|
}
|
|
2938
3967
|
|
|
2939
|
-
// src/IndexedImage/
|
|
2940
|
-
function
|
|
2941
|
-
const {
|
|
2942
|
-
source.data,
|
|
2943
|
-
source.width,
|
|
2944
|
-
source.height,
|
|
2945
|
-
factor
|
|
2946
|
-
);
|
|
2947
|
-
return new IndexedImage(
|
|
3968
|
+
// src/IndexedImage/indexedImageToImageData.ts
|
|
3969
|
+
function indexedImageToImageData(indexedImage) {
|
|
3970
|
+
const {
|
|
2948
3971
|
width,
|
|
2949
3972
|
height,
|
|
2950
3973
|
data,
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
);
|
|
2954
|
-
}
|
|
2955
|
-
|
|
2956
|
-
// src/IndexedImage/indexedImageToImageData.ts
|
|
2957
|
-
function indexedImageToImageData(indexedImage) {
|
|
2958
|
-
const { width, height, data, palette } = indexedImage;
|
|
3974
|
+
palette
|
|
3975
|
+
} = indexedImage;
|
|
2959
3976
|
const result = new ImageData(width, height);
|
|
2960
3977
|
const data32 = new Uint32Array(result.data.buffer);
|
|
2961
3978
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -2966,6 +3983,16 @@ function indexedImageToImageData(indexedImage) {
|
|
|
2966
3983
|
return result;
|
|
2967
3984
|
}
|
|
2968
3985
|
|
|
3986
|
+
// src/IndexedImage/resampleIndexedImage.ts
|
|
3987
|
+
function resampleIndexedImage(source, factor) {
|
|
3988
|
+
const {
|
|
3989
|
+
data,
|
|
3990
|
+
width,
|
|
3991
|
+
height
|
|
3992
|
+
} = resample32(source.data, source.width, source.height, factor);
|
|
3993
|
+
return new IndexedImage(width, height, data, source.palette, source.transparentPalletIndex);
|
|
3994
|
+
}
|
|
3995
|
+
|
|
2969
3996
|
// src/Input/fileInputChangeToImageData.ts
|
|
2970
3997
|
async function fileInputChangeToImageData(event) {
|
|
2971
3998
|
const target = event.target;
|
|
@@ -2989,23 +4016,11 @@ async function fileToImageData(file) {
|
|
|
2989
4016
|
let bitmap = null;
|
|
2990
4017
|
try {
|
|
2991
4018
|
bitmap = await createImageBitmap(file);
|
|
2992
|
-
const canvas = new OffscreenCanvas(
|
|
2993
|
-
bitmap.width,
|
|
2994
|
-
bitmap.height
|
|
2995
|
-
);
|
|
4019
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
2996
4020
|
const ctx = canvas.getContext("2d");
|
|
2997
4021
|
if (!ctx) throw new Error(OFFSCREEN_CANVAS_CTX_FAILED);
|
|
2998
|
-
ctx.drawImage(
|
|
2999
|
-
|
|
3000
|
-
0,
|
|
3001
|
-
0
|
|
3002
|
-
);
|
|
3003
|
-
return ctx.getImageData(
|
|
3004
|
-
0,
|
|
3005
|
-
0,
|
|
3006
|
-
bitmap.width,
|
|
3007
|
-
bitmap.height
|
|
3008
|
-
);
|
|
4022
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
4023
|
+
return ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
3009
4024
|
} finally {
|
|
3010
4025
|
bitmap?.close();
|
|
3011
4026
|
}
|
|
@@ -3013,32 +4028,23 @@ async function fileToImageData(file) {
|
|
|
3013
4028
|
|
|
3014
4029
|
// src/Input/getSupportedRasterFormats.ts
|
|
3015
4030
|
var formatsPromise = null;
|
|
3016
|
-
var defaultRasterMimes = [
|
|
3017
|
-
"image/png",
|
|
3018
|
-
"image/jpeg",
|
|
3019
|
-
"image/webp",
|
|
3020
|
-
"image/avif",
|
|
3021
|
-
"image/gif",
|
|
3022
|
-
"image/bmp"
|
|
3023
|
-
];
|
|
4031
|
+
var defaultRasterMimes = ["image/png", "image/jpeg", "image/webp", "image/avif", "image/gif", "image/bmp"];
|
|
3024
4032
|
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
3025
4033
|
if (formatsPromise) {
|
|
3026
4034
|
return formatsPromise;
|
|
3027
4035
|
}
|
|
3028
4036
|
const probeCanvas = async () => {
|
|
3029
4037
|
const canvas = new OffscreenCanvas(1, 1);
|
|
3030
|
-
const results = await Promise.all(
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
})
|
|
3041
|
-
);
|
|
4038
|
+
const results = await Promise.all(rasterMimes.map(async (mime) => {
|
|
4039
|
+
try {
|
|
4040
|
+
const blob = await canvas.convertToBlob({
|
|
4041
|
+
type: mime
|
|
4042
|
+
});
|
|
4043
|
+
return blob.type === mime ? mime : null;
|
|
4044
|
+
} catch {
|
|
4045
|
+
return null;
|
|
4046
|
+
}
|
|
4047
|
+
}));
|
|
3042
4048
|
return results.filter((type) => {
|
|
3043
4049
|
return type !== null;
|
|
3044
4050
|
});
|
|
@@ -3050,6 +4056,73 @@ async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
|
3050
4056
|
return formatsPromise;
|
|
3051
4057
|
}
|
|
3052
4058
|
|
|
4059
|
+
// src/Mask/applyBinaryMaskToAlphaMask.ts
|
|
4060
|
+
function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWidth, opts = {}) {
|
|
4061
|
+
const {
|
|
4062
|
+
x: targetX = 0,
|
|
4063
|
+
y: targetY = 0,
|
|
4064
|
+
w: reqWidth = 0,
|
|
4065
|
+
h: reqHeight = 0,
|
|
4066
|
+
mx = 0,
|
|
4067
|
+
my = 0,
|
|
4068
|
+
invertMask = false
|
|
4069
|
+
} = opts;
|
|
4070
|
+
if (dstWidth <= 0) return;
|
|
4071
|
+
if (binaryMaskSrc.length === 0) return;
|
|
4072
|
+
if (srcWidth <= 0) return;
|
|
4073
|
+
const dstHeight = alphaMaskDst.length / dstWidth | 0;
|
|
4074
|
+
const srcHeight = binaryMaskSrc.length / srcWidth | 0;
|
|
4075
|
+
if (dstHeight <= 0) return;
|
|
4076
|
+
if (srcHeight <= 0) return;
|
|
4077
|
+
const dstX0 = Math.max(0, targetX);
|
|
4078
|
+
const dstY0 = Math.max(0, targetY);
|
|
4079
|
+
const dstX1 = reqWidth > 0 ? Math.min(dstWidth, targetX + reqWidth) : dstWidth;
|
|
4080
|
+
const dstY1 = reqHeight > 0 ? Math.min(dstHeight, targetY + reqHeight) : dstHeight;
|
|
4081
|
+
if (dstX0 >= dstX1) return;
|
|
4082
|
+
if (dstY0 >= dstY1) return;
|
|
4083
|
+
const srcX0 = mx + (dstX0 - targetX);
|
|
4084
|
+
const srcY0 = my + (dstY0 - targetY);
|
|
4085
|
+
if (srcX0 >= srcWidth) return;
|
|
4086
|
+
if (srcY0 >= srcHeight) return;
|
|
4087
|
+
if (srcX0 + (dstX1 - dstX0) <= 0) return;
|
|
4088
|
+
if (srcY0 + (dstY1 - dstY0) <= 0) return;
|
|
4089
|
+
const iterW = Math.min(dstX1 - dstX0, srcWidth - srcX0);
|
|
4090
|
+
const iterH = Math.min(dstY1 - dstY0, srcHeight - srcY0);
|
|
4091
|
+
let dstIdx = dstY0 * dstWidth + dstX0;
|
|
4092
|
+
let srcIdx = srcY0 * srcWidth + srcX0;
|
|
4093
|
+
if (invertMask) {
|
|
4094
|
+
for (let row = 0; row < iterH; row++) {
|
|
4095
|
+
const dstEnd = dstIdx + iterW;
|
|
4096
|
+
let d = dstIdx;
|
|
4097
|
+
let s = srcIdx;
|
|
4098
|
+
while (d < dstEnd) {
|
|
4099
|
+
if (binaryMaskSrc[s] !== 0) {
|
|
4100
|
+
alphaMaskDst[d] = 0;
|
|
4101
|
+
}
|
|
4102
|
+
d++;
|
|
4103
|
+
s++;
|
|
4104
|
+
}
|
|
4105
|
+
dstIdx += dstWidth;
|
|
4106
|
+
srcIdx += srcWidth;
|
|
4107
|
+
}
|
|
4108
|
+
} else {
|
|
4109
|
+
for (let row = 0; row < iterH; row++) {
|
|
4110
|
+
const dstEnd = dstIdx + iterW;
|
|
4111
|
+
let d = dstIdx;
|
|
4112
|
+
let s = srcIdx;
|
|
4113
|
+
while (d < dstEnd) {
|
|
4114
|
+
if (binaryMaskSrc[s] === 0) {
|
|
4115
|
+
alphaMaskDst[d] = 0;
|
|
4116
|
+
}
|
|
4117
|
+
d++;
|
|
4118
|
+
s++;
|
|
4119
|
+
}
|
|
4120
|
+
dstIdx += dstWidth;
|
|
4121
|
+
srcIdx += srcWidth;
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
|
|
3053
4126
|
// src/Mask/copyMask.ts
|
|
3054
4127
|
function copyMask(src) {
|
|
3055
4128
|
return src.slice();
|
|
@@ -3069,69 +4142,124 @@ function invertAlphaMask(dst) {
|
|
|
3069
4142
|
}
|
|
3070
4143
|
}
|
|
3071
4144
|
|
|
3072
|
-
// src/Mask/
|
|
3073
|
-
function
|
|
4145
|
+
// src/Mask/mergeAlphaMasks.ts
|
|
4146
|
+
function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
3074
4147
|
const {
|
|
3075
4148
|
x: targetX = 0,
|
|
3076
4149
|
y: targetY = 0,
|
|
3077
4150
|
w: width = 0,
|
|
3078
4151
|
h: height = 0,
|
|
3079
4152
|
alpha: globalAlpha = 255,
|
|
3080
|
-
maskType = 0 /* ALPHA */,
|
|
3081
|
-
mw,
|
|
3082
4153
|
mx = 0,
|
|
3083
4154
|
my = 0,
|
|
3084
4155
|
invertMask = false
|
|
3085
4156
|
} = opts;
|
|
3086
|
-
|
|
3087
|
-
|
|
4157
|
+
const dstHeight = dst.length / dstWidth | 0;
|
|
4158
|
+
const srcHeight = src.length / srcWidth | 0;
|
|
4159
|
+
if (width <= 0) return;
|
|
4160
|
+
if (height <= 0) return;
|
|
4161
|
+
if (globalAlpha === 0) return;
|
|
4162
|
+
const startX = Math.max(0, -targetX, -mx);
|
|
4163
|
+
const startY = Math.max(0, -targetY, -my);
|
|
4164
|
+
const endX = Math.min(width, dstWidth - targetX, srcWidth - mx);
|
|
4165
|
+
const endY = Math.min(height, dstHeight - targetY, srcHeight - my);
|
|
4166
|
+
if (startX >= endX) return;
|
|
4167
|
+
if (startY >= endY) return;
|
|
4168
|
+
for (let iy = startY; iy < endY; iy++) {
|
|
4169
|
+
const dy = targetY + iy;
|
|
4170
|
+
const sy = my + iy;
|
|
4171
|
+
let dIdx = dy * dstWidth + targetX + startX;
|
|
4172
|
+
let sIdx = sy * srcWidth + mx + startX;
|
|
4173
|
+
for (let ix = startX; ix < endX; ix++) {
|
|
4174
|
+
const rawM = src[sIdx];
|
|
4175
|
+
const effectiveM = invertMask ? 255 - rawM : rawM;
|
|
4176
|
+
let weight = 0;
|
|
4177
|
+
if (effectiveM === 0) {
|
|
4178
|
+
weight = 0;
|
|
4179
|
+
} else if (effectiveM === 255) {
|
|
4180
|
+
weight = globalAlpha;
|
|
4181
|
+
} else if (globalAlpha === 255) {
|
|
4182
|
+
weight = effectiveM;
|
|
4183
|
+
} else {
|
|
4184
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
4185
|
+
}
|
|
4186
|
+
if (weight !== 255) {
|
|
4187
|
+
if (weight === 0) {
|
|
4188
|
+
dst[dIdx] = 0;
|
|
4189
|
+
} else {
|
|
4190
|
+
const da = dst[dIdx];
|
|
4191
|
+
if (da === 255) {
|
|
4192
|
+
dst[dIdx] = weight;
|
|
4193
|
+
} else if (da !== 0) {
|
|
4194
|
+
dst[dIdx] = da * weight + 128 >> 8;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
sIdx++;
|
|
4199
|
+
dIdx++;
|
|
4200
|
+
}
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
|
|
4204
|
+
// src/Mask/mergeBinaryMasks.ts
|
|
4205
|
+
function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
4206
|
+
const {
|
|
4207
|
+
x: targetX = 0,
|
|
4208
|
+
y: targetY = 0,
|
|
4209
|
+
w: width = 0,
|
|
4210
|
+
h: height = 0,
|
|
4211
|
+
mx = 0,
|
|
4212
|
+
my = 0,
|
|
4213
|
+
invertMask = false
|
|
4214
|
+
} = opts;
|
|
4215
|
+
if (dstWidth <= 0) return;
|
|
4216
|
+
if (srcWidth <= 0) return;
|
|
4217
|
+
const dstHeight = dst.length / dstWidth | 0;
|
|
4218
|
+
const srcHeight = src.length / srcWidth | 0;
|
|
4219
|
+
let x = targetX;
|
|
4220
|
+
let y = targetY;
|
|
4221
|
+
let w = width;
|
|
4222
|
+
let h = height;
|
|
4223
|
+
if (x < 0) {
|
|
4224
|
+
w += x;
|
|
4225
|
+
x = 0;
|
|
4226
|
+
}
|
|
4227
|
+
if (y < 0) {
|
|
4228
|
+
h += y;
|
|
4229
|
+
y = 0;
|
|
3088
4230
|
}
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
4231
|
+
w = Math.min(w, dstWidth - x);
|
|
4232
|
+
h = Math.min(h, dstHeight - y);
|
|
4233
|
+
if (w <= 0) return;
|
|
4234
|
+
if (h <= 0) return;
|
|
4235
|
+
const startX = mx + (x - targetX);
|
|
4236
|
+
const startY = my + (y - targetY);
|
|
4237
|
+
const sX0 = Math.max(0, startX);
|
|
4238
|
+
const sY0 = Math.max(0, startY);
|
|
4239
|
+
const sX1 = Math.min(srcWidth, startX + w);
|
|
4240
|
+
const sY1 = Math.min(srcHeight, startY + h);
|
|
4241
|
+
const finalW = sX1 - sX0;
|
|
4242
|
+
const finalH = sY1 - sY0;
|
|
4243
|
+
if (finalW <= 0) return;
|
|
4244
|
+
if (finalH <= 0) return;
|
|
4245
|
+
const xShift = sX0 - startX;
|
|
4246
|
+
const yShift = sY0 - startY;
|
|
4247
|
+
const dStride = dstWidth - finalW;
|
|
4248
|
+
const sStride = srcWidth - finalW;
|
|
4249
|
+
let dIdx = (y + yShift) * dstWidth + (x + xShift);
|
|
4250
|
+
let sIdx = sY0 * srcWidth + sX0;
|
|
4251
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
4252
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
3105
4253
|
const mVal = src[sIdx];
|
|
3106
|
-
|
|
3107
|
-
if (
|
|
3108
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
3109
|
-
if (effectiveM === 0) {
|
|
3110
|
-
dst[dIdx] = 0;
|
|
3111
|
-
continue;
|
|
3112
|
-
}
|
|
3113
|
-
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
3114
|
-
} else {
|
|
3115
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
3116
|
-
if (!isHit) {
|
|
3117
|
-
dst[dIdx] = 0;
|
|
3118
|
-
continue;
|
|
3119
|
-
}
|
|
3120
|
-
weight = globalAlpha;
|
|
3121
|
-
}
|
|
3122
|
-
if (weight === 0) {
|
|
4254
|
+
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
4255
|
+
if (isMaskedOut) {
|
|
3123
4256
|
dst[dIdx] = 0;
|
|
3124
|
-
continue;
|
|
3125
|
-
}
|
|
3126
|
-
const da = dst[dIdx];
|
|
3127
|
-
if (da === 0) {
|
|
3128
|
-
} else if (weight === 255) {
|
|
3129
|
-
} else if (da === 255) {
|
|
3130
|
-
dst[dIdx] = weight;
|
|
3131
|
-
} else {
|
|
3132
|
-
dst[dIdx] = da * weight + 128 >> 8;
|
|
3133
4257
|
}
|
|
4258
|
+
dIdx++;
|
|
4259
|
+
sIdx++;
|
|
3134
4260
|
}
|
|
4261
|
+
dIdx += dStride;
|
|
4262
|
+
sIdx += sStride;
|
|
3135
4263
|
}
|
|
3136
4264
|
}
|
|
3137
4265
|
|
|
@@ -3139,118 +4267,258 @@ function mergeMasks(dst, dstWidth, src, opts) {
|
|
|
3139
4267
|
var PixelData = class _PixelData {
|
|
3140
4268
|
data32;
|
|
3141
4269
|
imageData;
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
}
|
|
3145
|
-
get height() {
|
|
3146
|
-
return this.imageData.height;
|
|
3147
|
-
}
|
|
4270
|
+
width;
|
|
4271
|
+
height;
|
|
3148
4272
|
constructor(imageData) {
|
|
3149
4273
|
this.data32 = imageDataToUInt32Array(imageData);
|
|
3150
4274
|
this.imageData = imageData;
|
|
4275
|
+
this.width = imageData.width;
|
|
4276
|
+
this.height = imageData.height;
|
|
3151
4277
|
}
|
|
3152
4278
|
set(imageData) {
|
|
4279
|
+
;
|
|
3153
4280
|
this.imageData = imageData;
|
|
3154
4281
|
this.data32 = imageDataToUInt32Array(imageData);
|
|
4282
|
+
this.width = imageData.width;
|
|
4283
|
+
this.height = imageData.height;
|
|
3155
4284
|
}
|
|
3156
|
-
|
|
3157
|
-
* Creates a deep copy of the PixelData using the environment's ImageData constructor.
|
|
3158
|
-
*/
|
|
4285
|
+
// should only be used for debug and testing
|
|
3159
4286
|
copy() {
|
|
3160
|
-
const
|
|
3161
|
-
const
|
|
3162
|
-
const
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
4287
|
+
const data = this.imageData.data;
|
|
4288
|
+
const buffer = new Uint8ClampedArray(data);
|
|
4289
|
+
const Ctor = this.imageData.constructor;
|
|
4290
|
+
const isCtorValid = typeof Ctor === "function";
|
|
4291
|
+
let newImageData;
|
|
4292
|
+
if (isCtorValid && Ctor !== Object) {
|
|
4293
|
+
const ImageConstructor = Ctor;
|
|
4294
|
+
newImageData = new ImageConstructor(buffer, this.width, this.height);
|
|
4295
|
+
} else {
|
|
4296
|
+
newImageData = {
|
|
4297
|
+
width: this.width,
|
|
4298
|
+
height: this.height,
|
|
4299
|
+
data: buffer
|
|
4300
|
+
};
|
|
4301
|
+
}
|
|
3167
4302
|
return new _PixelData(newImageData);
|
|
3168
4303
|
}
|
|
3169
4304
|
};
|
|
3170
4305
|
|
|
3171
|
-
// src/PixelData/
|
|
3172
|
-
function
|
|
3173
|
-
const
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
4306
|
+
// src/PixelData/blendPixelDataAlphaMask.ts
|
|
4307
|
+
function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
4308
|
+
const {
|
|
4309
|
+
x: targetX = 0,
|
|
4310
|
+
y: targetY = 0,
|
|
4311
|
+
sx: sourceX = 0,
|
|
4312
|
+
sy: sourceY = 0,
|
|
4313
|
+
w: width = src.width,
|
|
4314
|
+
h: height = src.height,
|
|
4315
|
+
alpha: globalAlpha = 255,
|
|
4316
|
+
blendFn = sourceOverPerfect,
|
|
4317
|
+
mw = src.width,
|
|
4318
|
+
mx = 0,
|
|
4319
|
+
my = 0,
|
|
4320
|
+
invertMask = false
|
|
4321
|
+
} = opts;
|
|
4322
|
+
if (globalAlpha === 0) return;
|
|
4323
|
+
let x = targetX;
|
|
4324
|
+
let y = targetY;
|
|
4325
|
+
let sx = sourceX;
|
|
4326
|
+
let sy = sourceY;
|
|
4327
|
+
let w = width;
|
|
4328
|
+
let h = height;
|
|
4329
|
+
if (sx < 0) {
|
|
4330
|
+
x -= sx;
|
|
4331
|
+
w += sx;
|
|
4332
|
+
sx = 0;
|
|
4333
|
+
}
|
|
4334
|
+
if (sy < 0) {
|
|
4335
|
+
y -= sy;
|
|
4336
|
+
h += sy;
|
|
4337
|
+
sy = 0;
|
|
4338
|
+
}
|
|
4339
|
+
w = Math.min(w, src.width - sx);
|
|
4340
|
+
h = Math.min(h, src.height - sy);
|
|
4341
|
+
if (x < 0) {
|
|
4342
|
+
sx -= x;
|
|
4343
|
+
w += x;
|
|
4344
|
+
x = 0;
|
|
4345
|
+
}
|
|
4346
|
+
if (y < 0) {
|
|
4347
|
+
sy -= y;
|
|
4348
|
+
h += y;
|
|
4349
|
+
y = 0;
|
|
4350
|
+
}
|
|
4351
|
+
const actualW = Math.min(w, dst.width - x);
|
|
4352
|
+
const actualH = Math.min(h, dst.height - y);
|
|
4353
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
4354
|
+
const dw = dst.width;
|
|
4355
|
+
const sw = src.width;
|
|
4356
|
+
const mPitch = mw;
|
|
4357
|
+
const dx = x - targetX | 0;
|
|
4358
|
+
const dy = y - targetY | 0;
|
|
4359
|
+
const dst32 = dst.data32;
|
|
4360
|
+
const src32 = src.data32;
|
|
4361
|
+
let dIdx = y * dw + x | 0;
|
|
4362
|
+
let sIdx = sy * sw + sx | 0;
|
|
4363
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
4364
|
+
const dStride = dw - actualW | 0;
|
|
4365
|
+
const sStride = sw - actualW | 0;
|
|
4366
|
+
const mStride = mPitch - actualW | 0;
|
|
4367
|
+
const isOpaque = globalAlpha === 255;
|
|
4368
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
4369
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
4370
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
4371
|
+
const mVal = alphaMask[mIdx];
|
|
4372
|
+
const effM = invertMask ? 255 - mVal : mVal;
|
|
4373
|
+
if (effM === 0) {
|
|
4374
|
+
dIdx++;
|
|
4375
|
+
sIdx++;
|
|
4376
|
+
mIdx++;
|
|
4377
|
+
continue;
|
|
4378
|
+
}
|
|
4379
|
+
const srcCol = src32[sIdx];
|
|
4380
|
+
const srcAlpha = srcCol >>> 24;
|
|
4381
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
4382
|
+
dIdx++;
|
|
4383
|
+
sIdx++;
|
|
4384
|
+
mIdx++;
|
|
4385
|
+
continue;
|
|
4386
|
+
}
|
|
4387
|
+
let weight = globalAlpha;
|
|
4388
|
+
if (isOpaque) {
|
|
4389
|
+
weight = effM;
|
|
4390
|
+
} else if (effM !== 255) {
|
|
4391
|
+
weight = effM * globalAlpha + 128 >> 8;
|
|
4392
|
+
}
|
|
4393
|
+
if (weight === 0) {
|
|
4394
|
+
dIdx++;
|
|
4395
|
+
sIdx++;
|
|
4396
|
+
mIdx++;
|
|
4397
|
+
continue;
|
|
4398
|
+
}
|
|
4399
|
+
let finalCol = srcCol;
|
|
4400
|
+
if (weight < 255) {
|
|
4401
|
+
const a = srcAlpha * weight + 128 >> 8;
|
|
4402
|
+
if (a === 0 && !isOverwrite) {
|
|
4403
|
+
dIdx++;
|
|
4404
|
+
sIdx++;
|
|
4405
|
+
mIdx++;
|
|
4406
|
+
continue;
|
|
3201
4407
|
}
|
|
4408
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3202
4409
|
}
|
|
4410
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
4411
|
+
dIdx++;
|
|
4412
|
+
sIdx++;
|
|
4413
|
+
mIdx++;
|
|
3203
4414
|
}
|
|
4415
|
+
dIdx += dStride;
|
|
4416
|
+
sIdx += sStride;
|
|
4417
|
+
mIdx += mStride;
|
|
3204
4418
|
}
|
|
3205
4419
|
}
|
|
3206
4420
|
|
|
3207
|
-
// src/PixelData/
|
|
3208
|
-
function
|
|
3209
|
-
const
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
4421
|
+
// src/PixelData/blendPixelDataBinaryMask.ts
|
|
4422
|
+
function blendPixelDataBinaryMask(dst, src, binaryMask, opts) {
|
|
4423
|
+
const {
|
|
4424
|
+
x: targetX = 0,
|
|
4425
|
+
y: targetY = 0,
|
|
4426
|
+
sx: sourceX = 0,
|
|
4427
|
+
sy: sourceY = 0,
|
|
4428
|
+
w: width = src.width,
|
|
4429
|
+
h: height = src.height,
|
|
4430
|
+
alpha: globalAlpha = 255,
|
|
4431
|
+
blendFn = sourceOverPerfect,
|
|
4432
|
+
mw = src.width,
|
|
4433
|
+
mx = 0,
|
|
4434
|
+
my = 0,
|
|
4435
|
+
invertMask = false
|
|
4436
|
+
} = opts;
|
|
4437
|
+
if (globalAlpha === 0) return;
|
|
4438
|
+
let x = targetX;
|
|
4439
|
+
let y = targetY;
|
|
4440
|
+
let sx = sourceX;
|
|
4441
|
+
let sy = sourceY;
|
|
4442
|
+
let w = width;
|
|
4443
|
+
let h = height;
|
|
4444
|
+
if (sx < 0) {
|
|
4445
|
+
x -= sx;
|
|
4446
|
+
w += sx;
|
|
4447
|
+
sx = 0;
|
|
4448
|
+
}
|
|
4449
|
+
if (sy < 0) {
|
|
4450
|
+
y -= sy;
|
|
4451
|
+
h += sy;
|
|
4452
|
+
sy = 0;
|
|
4453
|
+
}
|
|
4454
|
+
w = Math.min(w, src.width - sx);
|
|
4455
|
+
h = Math.min(h, src.height - sy);
|
|
4456
|
+
if (x < 0) {
|
|
4457
|
+
sx -= x;
|
|
4458
|
+
w += x;
|
|
4459
|
+
x = 0;
|
|
4460
|
+
}
|
|
4461
|
+
if (y < 0) {
|
|
4462
|
+
sy -= y;
|
|
4463
|
+
h += y;
|
|
4464
|
+
y = 0;
|
|
4465
|
+
}
|
|
4466
|
+
const actualW = Math.min(w, dst.width - x);
|
|
4467
|
+
const actualH = Math.min(h, dst.height - y);
|
|
4468
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
4469
|
+
const dx = x - targetX | 0;
|
|
4470
|
+
const dy = y - targetY | 0;
|
|
4471
|
+
const dst32 = dst.data32;
|
|
4472
|
+
const src32 = src.data32;
|
|
4473
|
+
const dw = dst.width;
|
|
4474
|
+
const sw = src.width;
|
|
4475
|
+
const mPitch = mw;
|
|
4476
|
+
let dIdx = y * dw + x | 0;
|
|
4477
|
+
let sIdx = sy * sw + sx | 0;
|
|
4478
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
4479
|
+
const dStride = dw - actualW | 0;
|
|
4480
|
+
const sStride = sw - actualW | 0;
|
|
4481
|
+
const mStride = mPitch - actualW | 0;
|
|
4482
|
+
const skipVal = invertMask ? 1 : 0;
|
|
4483
|
+
const isOpaque = globalAlpha === 255;
|
|
4484
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
4485
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
4486
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
4487
|
+
if (binaryMask[mIdx] === skipVal) {
|
|
4488
|
+
dIdx++;
|
|
4489
|
+
sIdx++;
|
|
4490
|
+
mIdx++;
|
|
4491
|
+
continue;
|
|
4492
|
+
}
|
|
4493
|
+
const srcCol = src32[sIdx];
|
|
4494
|
+
const srcAlpha = srcCol >>> 24;
|
|
4495
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
4496
|
+
dIdx++;
|
|
4497
|
+
sIdx++;
|
|
4498
|
+
mIdx++;
|
|
4499
|
+
continue;
|
|
3234
4500
|
}
|
|
4501
|
+
let finalCol = srcCol;
|
|
4502
|
+
if (!isOpaque) {
|
|
4503
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
4504
|
+
if (a === 0 && !isOverwrite) {
|
|
4505
|
+
dIdx++;
|
|
4506
|
+
sIdx++;
|
|
4507
|
+
mIdx++;
|
|
4508
|
+
continue;
|
|
4509
|
+
}
|
|
4510
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
4511
|
+
}
|
|
4512
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
4513
|
+
dIdx++;
|
|
4514
|
+
sIdx++;
|
|
4515
|
+
mIdx++;
|
|
3235
4516
|
}
|
|
4517
|
+
dIdx += dStride;
|
|
4518
|
+
sIdx += sStride;
|
|
4519
|
+
mIdx += mStride;
|
|
3236
4520
|
}
|
|
3237
4521
|
}
|
|
3238
|
-
function getRectBrushBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight) {
|
|
3239
|
-
const rawStartX = Math.floor(centerX - brushWidth / 2);
|
|
3240
|
-
const rawStartY = Math.floor(centerY - brushHeight / 2);
|
|
3241
|
-
const rawEndX = rawStartX + brushWidth;
|
|
3242
|
-
const rawEndY = rawStartY + brushHeight;
|
|
3243
|
-
const startX = targetWidth !== void 0 ? Math.max(0, rawStartX) : rawStartX;
|
|
3244
|
-
const startY = targetHeight !== void 0 ? Math.max(0, rawStartY) : rawStartY;
|
|
3245
|
-
const endX = targetWidth !== void 0 ? Math.min(targetWidth, rawEndX) : rawEndX;
|
|
3246
|
-
const endY = targetHeight !== void 0 ? Math.min(targetHeight, rawEndY) : rawEndY;
|
|
3247
|
-
return {
|
|
3248
|
-
x: startX,
|
|
3249
|
-
y: startY,
|
|
3250
|
-
w: endX - startX,
|
|
3251
|
-
h: endY - startY
|
|
3252
|
-
};
|
|
3253
|
-
}
|
|
3254
4522
|
|
|
3255
4523
|
// src/PixelData/clearPixelData.ts
|
|
3256
4524
|
function clearPixelData(dst, rect) {
|
|
@@ -3258,32 +4526,40 @@ function clearPixelData(dst, rect) {
|
|
|
3258
4526
|
}
|
|
3259
4527
|
|
|
3260
4528
|
// src/PixelData/extractPixelDataBuffer.ts
|
|
4529
|
+
var SCRATCH_BLIT4 = makeClippedBlit();
|
|
3261
4530
|
function extractPixelDataBuffer(source, _x, _y, _w, _h) {
|
|
3262
|
-
const {
|
|
4531
|
+
const {
|
|
4532
|
+
x,
|
|
4533
|
+
y,
|
|
4534
|
+
w,
|
|
4535
|
+
h
|
|
4536
|
+
} = typeof _x === "object" ? _x : {
|
|
4537
|
+
x: _x,
|
|
4538
|
+
y: _y,
|
|
4539
|
+
w: _w,
|
|
4540
|
+
h: _h
|
|
4541
|
+
};
|
|
3263
4542
|
const srcW = source.width;
|
|
3264
4543
|
const srcH = source.height;
|
|
3265
4544
|
const srcData = source.data32;
|
|
3266
4545
|
if (w <= 0 || h <= 0) {
|
|
3267
4546
|
return new Uint32Array(0);
|
|
3268
4547
|
}
|
|
3269
|
-
const
|
|
3270
|
-
const
|
|
3271
|
-
|
|
3272
|
-
const
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
for (let row = 0; row <
|
|
3281
|
-
const
|
|
3282
|
-
const
|
|
3283
|
-
const
|
|
3284
|
-
const dstCol = x0 - x;
|
|
3285
|
-
const dstStart = dstRow * w + dstCol;
|
|
3286
|
-
const chunk = srcData.subarray(srcStart, srcStart + copyWidth);
|
|
4548
|
+
const dstData = new Uint32Array(w * h);
|
|
4549
|
+
const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT4);
|
|
4550
|
+
if (!clip.inBounds) return dstData;
|
|
4551
|
+
const {
|
|
4552
|
+
x: dstX,
|
|
4553
|
+
y: dstY,
|
|
4554
|
+
sx: srcX,
|
|
4555
|
+
sy: srcY,
|
|
4556
|
+
w: copyW,
|
|
4557
|
+
h: copyH
|
|
4558
|
+
} = clip;
|
|
4559
|
+
for (let row = 0; row < copyH; row++) {
|
|
4560
|
+
const srcStart = (srcY + row) * srcW + srcX;
|
|
4561
|
+
const dstStart = (dstY + row) * w + dstX;
|
|
4562
|
+
const chunk = srcData.subarray(srcStart, srcStart + copyW);
|
|
3287
4563
|
dstData.set(chunk, dstStart);
|
|
3288
4564
|
}
|
|
3289
4565
|
return dstData;
|
|
@@ -3291,13 +4567,59 @@ function extractPixelDataBuffer(source, _x, _y, _w, _h) {
|
|
|
3291
4567
|
|
|
3292
4568
|
// src/PixelData/extractPixelData.ts
|
|
3293
4569
|
function extractPixelData(source, _x, _y, _w, _h) {
|
|
3294
|
-
const {
|
|
4570
|
+
const {
|
|
4571
|
+
x,
|
|
4572
|
+
y,
|
|
4573
|
+
w,
|
|
4574
|
+
h
|
|
4575
|
+
} = typeof _x === "object" ? _x : {
|
|
4576
|
+
x: _x,
|
|
4577
|
+
y: _y,
|
|
4578
|
+
w: _w,
|
|
4579
|
+
h: _h
|
|
4580
|
+
};
|
|
3295
4581
|
const result = new PixelData(new ImageData(w, h));
|
|
3296
4582
|
const buffer = extractPixelDataBuffer(source, x, y, w, h);
|
|
3297
4583
|
result.data32.set(buffer);
|
|
3298
4584
|
return result;
|
|
3299
4585
|
}
|
|
3300
4586
|
|
|
4587
|
+
// src/PixelData/PixelBuffer32.ts
|
|
4588
|
+
var PixelBuffer32 = class _PixelBuffer32 {
|
|
4589
|
+
constructor(width, height, data32) {
|
|
4590
|
+
this.width = width;
|
|
4591
|
+
this.height = height;
|
|
4592
|
+
this.data32 = data32 ?? new Uint32Array(width * height);
|
|
4593
|
+
}
|
|
4594
|
+
data32;
|
|
4595
|
+
set(width, height, data32) {
|
|
4596
|
+
;
|
|
4597
|
+
this.data32 = data32 ?? new Uint32Array(width * height);
|
|
4598
|
+
this.width = width;
|
|
4599
|
+
this.height = height;
|
|
4600
|
+
}
|
|
4601
|
+
copy() {
|
|
4602
|
+
const newData32 = new Uint32Array(this.data32);
|
|
4603
|
+
return new _PixelBuffer32(this.width, this.height, newData32);
|
|
4604
|
+
}
|
|
4605
|
+
};
|
|
4606
|
+
|
|
4607
|
+
// src/PixelData/pixelDataToAlphaMask.ts
|
|
4608
|
+
function pixelDataToAlphaMask(pixelData) {
|
|
4609
|
+
const {
|
|
4610
|
+
data32,
|
|
4611
|
+
width,
|
|
4612
|
+
height
|
|
4613
|
+
} = pixelData;
|
|
4614
|
+
const len = data32.length;
|
|
4615
|
+
const mask = new Uint8Array(width * height);
|
|
4616
|
+
for (let i = 0; i < len; i++) {
|
|
4617
|
+
const val = data32[i];
|
|
4618
|
+
mask[i] = val >>> 24 & 255;
|
|
4619
|
+
}
|
|
4620
|
+
return mask;
|
|
4621
|
+
}
|
|
4622
|
+
|
|
3301
4623
|
// src/PixelData/reflectPixelData.ts
|
|
3302
4624
|
function reflectPixelDataHorizontal(pixelData) {
|
|
3303
4625
|
const width = pixelData.width;
|
|
@@ -3335,12 +4657,12 @@ function reflectPixelDataVertical(pixelData) {
|
|
|
3335
4657
|
|
|
3336
4658
|
// src/PixelData/resamplePixelData.ts
|
|
3337
4659
|
function resamplePixelData(pixelData, factor) {
|
|
3338
|
-
const {
|
|
3339
|
-
|
|
3340
|
-
new Uint8ClampedArray(data.buffer),
|
|
4660
|
+
const {
|
|
4661
|
+
data,
|
|
3341
4662
|
width,
|
|
3342
4663
|
height
|
|
3343
|
-
)
|
|
4664
|
+
} = resample32(pixelData.data32, pixelData.width, pixelData.height, factor);
|
|
4665
|
+
return new PixelData(new ImageData(new Uint8ClampedArray(data.buffer), width, height));
|
|
3344
4666
|
}
|
|
3345
4667
|
|
|
3346
4668
|
// src/PixelData/rotatePixelData.ts
|
|
@@ -3364,11 +4686,7 @@ function rotatePixelData(pixelData) {
|
|
|
3364
4686
|
newData32[newIdx] = data[oldIdx];
|
|
3365
4687
|
}
|
|
3366
4688
|
}
|
|
3367
|
-
const newImageData = new ImageData(
|
|
3368
|
-
new Uint8ClampedArray(newData32.buffer),
|
|
3369
|
-
newWidth,
|
|
3370
|
-
newHeight
|
|
3371
|
-
);
|
|
4689
|
+
const newImageData = new ImageData(new Uint8ClampedArray(newData32.buffer), newWidth, newHeight);
|
|
3372
4690
|
pixelData.set(newImageData);
|
|
3373
4691
|
}
|
|
3374
4692
|
function rotateSquareInPlace(pixelData) {
|
|
@@ -3390,8 +4708,14 @@ function rotateSquareInPlace(pixelData) {
|
|
|
3390
4708
|
}
|
|
3391
4709
|
|
|
3392
4710
|
// src/PixelData/writePixelDataBuffer.ts
|
|
4711
|
+
var SCRATCH_BLIT5 = makeClippedBlit();
|
|
3393
4712
|
function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
3394
|
-
const {
|
|
4713
|
+
const {
|
|
4714
|
+
x,
|
|
4715
|
+
y,
|
|
4716
|
+
w,
|
|
4717
|
+
h
|
|
4718
|
+
} = typeof _x === "object" ? _x : {
|
|
3395
4719
|
x: _x,
|
|
3396
4720
|
y: _y,
|
|
3397
4721
|
w: _w,
|
|
@@ -3400,22 +4724,20 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3400
4724
|
const dstW = target.width;
|
|
3401
4725
|
const dstH = target.height;
|
|
3402
4726
|
const dstData = target.data32;
|
|
3403
|
-
const
|
|
3404
|
-
|
|
3405
|
-
const
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
const
|
|
3416
|
-
|
|
3417
|
-
const srcStart = srcRow * w + srcCol;
|
|
3418
|
-
dstData.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
4727
|
+
const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT5);
|
|
4728
|
+
if (!clip.inBounds) return;
|
|
4729
|
+
const {
|
|
4730
|
+
x: dstX,
|
|
4731
|
+
y: dstY,
|
|
4732
|
+
sx: srcX,
|
|
4733
|
+
sy: srcY,
|
|
4734
|
+
w: copyW,
|
|
4735
|
+
h: copyH
|
|
4736
|
+
} = clip;
|
|
4737
|
+
for (let row = 0; row < copyH; row++) {
|
|
4738
|
+
const dstStart = (dstY + row) * dstW + dstX;
|
|
4739
|
+
const srcStart = (srcY + row) * w + srcX;
|
|
4740
|
+
dstData.set(data.subarray(srcStart, srcStart + copyW), dstStart);
|
|
3419
4741
|
}
|
|
3420
4742
|
}
|
|
3421
4743
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -3423,23 +4745,32 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3423
4745
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
3424
4746
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
3425
4747
|
BaseBlendMode,
|
|
4748
|
+
CANVAS_CTX_FAILED,
|
|
3426
4749
|
HistoryManager,
|
|
3427
4750
|
IndexedImage,
|
|
3428
4751
|
MaskType,
|
|
4752
|
+
OFFSCREEN_CANVAS_CTX_FAILED,
|
|
3429
4753
|
PixelAccumulator,
|
|
4754
|
+
PixelBuffer32,
|
|
3430
4755
|
PixelData,
|
|
3431
4756
|
PixelEngineConfig,
|
|
3432
4757
|
PixelTile,
|
|
3433
4758
|
PixelWriter,
|
|
3434
4759
|
UnsupportedFormatError,
|
|
4760
|
+
applyAlphaMaskToPixelData,
|
|
4761
|
+
applyBinaryMaskToAlphaMask,
|
|
4762
|
+
applyBinaryMaskToPixelData,
|
|
3435
4763
|
applyCircleBrushToPixelData,
|
|
3436
|
-
applyMaskToPixelData,
|
|
3437
4764
|
applyPatchTiles,
|
|
3438
4765
|
applyRectBrushToPixelData,
|
|
3439
4766
|
base64DecodeArrayBuffer,
|
|
3440
4767
|
base64EncodeArrayBuffer,
|
|
3441
4768
|
blendColorPixelData,
|
|
4769
|
+
blendColorPixelDataAlphaMask,
|
|
4770
|
+
blendColorPixelDataBinaryMask,
|
|
3442
4771
|
blendPixelData,
|
|
4772
|
+
blendPixelDataAlphaMask,
|
|
4773
|
+
blendPixelDataBinaryMask,
|
|
3443
4774
|
clearPixelData,
|
|
3444
4775
|
color32ToCssRGBA,
|
|
3445
4776
|
color32ToHex,
|
|
@@ -3472,9 +4803,13 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3472
4803
|
fileToImageData,
|
|
3473
4804
|
fillPixelData,
|
|
3474
4805
|
floodFillSelection,
|
|
4806
|
+
forEachLinePoint,
|
|
4807
|
+
getCircleBrushOrPencilBounds,
|
|
4808
|
+
getCircleBrushOrPencilStrokeBounds,
|
|
3475
4809
|
getImageDataFromClipboard,
|
|
3476
4810
|
getIndexedImageColorCounts,
|
|
3477
|
-
|
|
4811
|
+
getRectBrushOrPencilBounds,
|
|
4812
|
+
getRectBrushOrPencilStrokeBounds,
|
|
3478
4813
|
getSupportedPixelFormats,
|
|
3479
4814
|
hardLightFast,
|
|
3480
4815
|
hardLightPerfect,
|
|
@@ -3506,17 +4841,29 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3506
4841
|
makeBlendModeRegistry,
|
|
3507
4842
|
makeFastBlendModeRegistry,
|
|
3508
4843
|
makeFullPixelMutator,
|
|
4844
|
+
makeImageDataLike,
|
|
3509
4845
|
makePerfectBlendModeRegistry,
|
|
3510
4846
|
makePixelCanvas,
|
|
3511
4847
|
makeReusableCanvas,
|
|
3512
4848
|
makeReusableImageData,
|
|
3513
|
-
|
|
4849
|
+
mergeAlphaMasks,
|
|
4850
|
+
mergeBinaryMasks,
|
|
3514
4851
|
multiplyFast,
|
|
3515
4852
|
multiplyPerfect,
|
|
3516
|
-
|
|
4853
|
+
mutatorApplyAlphaMask,
|
|
4854
|
+
mutatorApplyBinaryMask,
|
|
4855
|
+
mutatorApplyCircleBrush,
|
|
4856
|
+
mutatorApplyCircleBrushStroke,
|
|
4857
|
+
mutatorApplyCirclePencil,
|
|
4858
|
+
mutatorApplyCirclePencilStroke,
|
|
4859
|
+
mutatorApplyRectBrush,
|
|
4860
|
+
mutatorApplyRectBrushStroke,
|
|
4861
|
+
mutatorApplyRectPencil,
|
|
4862
|
+
mutatorApplyRectPencilStroke,
|
|
3517
4863
|
mutatorBlendColor,
|
|
3518
4864
|
mutatorBlendPixel,
|
|
3519
4865
|
mutatorBlendPixelData,
|
|
4866
|
+
mutatorClear,
|
|
3520
4867
|
mutatorFill,
|
|
3521
4868
|
mutatorInvert,
|
|
3522
4869
|
overlayFast,
|
|
@@ -3546,7 +4893,10 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3546
4893
|
sourceOverPerfect,
|
|
3547
4894
|
subtractFast,
|
|
3548
4895
|
subtractPerfect,
|
|
4896
|
+
toBlendModeIndexAndName,
|
|
3549
4897
|
trimRectBounds,
|
|
4898
|
+
uInt32ArrayToImageData,
|
|
4899
|
+
uInt32ArrayToImageDataLike,
|
|
3550
4900
|
unpackAlpha,
|
|
3551
4901
|
unpackBlue,
|
|
3552
4902
|
unpackColor,
|