pixel-data-js 0.18.0 → 0.19.1
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 +2723 -1487
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +2690 -1481
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +2723 -1487
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +400 -246
- package/dist/index.prod.js +2690 -1481
- package/dist/index.prod.js.map +1 -1
- package/package.json +22 -7
- 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 +23 -9
- 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 +20 -7
- 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 +23 -3
- package/src/History/PixelPatchTiles.ts +2 -2
- package/src/History/PixelWriter.ts +3 -3
- package/src/ImageData/ImageDataLike.ts +13 -0
- 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 +31 -56
- package/src/PixelData/applyRectBrushToPixelData.ts +39 -71
- 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,10 +81,13 @@ __export(src_exports, {
|
|
|
72
81
|
fileToImageData: () => fileToImageData,
|
|
73
82
|
fillPixelData: () => fillPixelData,
|
|
74
83
|
floodFillSelection: () => floodFillSelection,
|
|
75
|
-
|
|
84
|
+
forEachLinePoint: () => forEachLinePoint,
|
|
85
|
+
getCircleBrushOrPencilBounds: () => getCircleBrushOrPencilBounds,
|
|
86
|
+
getCircleBrushOrPencilStrokeBounds: () => getCircleBrushOrPencilStrokeBounds,
|
|
76
87
|
getImageDataFromClipboard: () => getImageDataFromClipboard,
|
|
77
88
|
getIndexedImageColorCounts: () => getIndexedImageColorCounts,
|
|
78
|
-
|
|
89
|
+
getRectBrushOrPencilBounds: () => getRectBrushOrPencilBounds,
|
|
90
|
+
getRectBrushOrPencilStrokeBounds: () => getRectBrushOrPencilStrokeBounds,
|
|
79
91
|
getSupportedPixelFormats: () => getSupportedPixelFormats,
|
|
80
92
|
hardLightFast: () => hardLightFast,
|
|
81
93
|
hardLightPerfect: () => hardLightPerfect,
|
|
@@ -107,17 +119,29 @@ __export(src_exports, {
|
|
|
107
119
|
makeBlendModeRegistry: () => makeBlendModeRegistry,
|
|
108
120
|
makeFastBlendModeRegistry: () => makeFastBlendModeRegistry,
|
|
109
121
|
makeFullPixelMutator: () => makeFullPixelMutator,
|
|
122
|
+
makeImageDataLike: () => makeImageDataLike,
|
|
110
123
|
makePerfectBlendModeRegistry: () => makePerfectBlendModeRegistry,
|
|
111
124
|
makePixelCanvas: () => makePixelCanvas,
|
|
112
125
|
makeReusableCanvas: () => makeReusableCanvas,
|
|
113
126
|
makeReusableImageData: () => makeReusableImageData,
|
|
114
|
-
|
|
127
|
+
mergeAlphaMasks: () => mergeAlphaMasks,
|
|
128
|
+
mergeBinaryMasks: () => mergeBinaryMasks,
|
|
115
129
|
multiplyFast: () => multiplyFast,
|
|
116
130
|
multiplyPerfect: () => multiplyPerfect,
|
|
117
|
-
|
|
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,
|
|
118
141
|
mutatorBlendColor: () => mutatorBlendColor,
|
|
119
142
|
mutatorBlendPixel: () => mutatorBlendPixel,
|
|
120
143
|
mutatorBlendPixelData: () => mutatorBlendPixelData,
|
|
144
|
+
mutatorClear: () => mutatorClear,
|
|
121
145
|
mutatorFill: () => mutatorFill,
|
|
122
146
|
mutatorInvert: () => mutatorInvert,
|
|
123
147
|
overlayFast: () => overlayFast,
|
|
@@ -147,7 +171,10 @@ __export(src_exports, {
|
|
|
147
171
|
sourceOverPerfect: () => sourceOverPerfect,
|
|
148
172
|
subtractFast: () => subtractFast,
|
|
149
173
|
subtractPerfect: () => subtractPerfect,
|
|
174
|
+
toBlendModeIndexAndName: () => toBlendModeIndexAndName,
|
|
150
175
|
trimRectBounds: () => trimRectBounds,
|
|
176
|
+
uInt32ArrayToImageData: () => uInt32ArrayToImageData,
|
|
177
|
+
uInt32ArrayToImageDataLike: () => uInt32ArrayToImageDataLike,
|
|
151
178
|
unpackAlpha: () => unpackAlpha,
|
|
152
179
|
unpackBlue: () => unpackBlue,
|
|
153
180
|
unpackColor: () => unpackColor,
|
|
@@ -164,617 +191,238 @@ __export(src_exports, {
|
|
|
164
191
|
});
|
|
165
192
|
module.exports = __toCommonJS(src_exports);
|
|
166
193
|
|
|
167
|
-
// src/
|
|
168
|
-
var
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
|
192
230
|
};
|
|
193
|
-
|
|
194
|
-
|
|
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
|
+
}
|
|
195
273
|
|
|
196
|
-
// src/
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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;
|
|
207
415
|
}
|
|
208
|
-
|
|
209
|
-
|
|
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);
|
|
210
423
|
}
|
|
211
|
-
indexToName[index] = name;
|
|
212
|
-
indexToBlend[index] = blendFn;
|
|
213
|
-
blendToIndex.set(blendFn, index);
|
|
214
|
-
blendToName.set(blendFn, name);
|
|
215
|
-
nameToBlend[name] = blendFn;
|
|
216
|
-
nameToIndex[name] = index;
|
|
217
|
-
};
|
|
218
|
-
for (const [name, index] of Object.entries(blendModes)) {
|
|
219
|
-
const blend = initialEntries[index];
|
|
220
|
-
add(name, index, blend);
|
|
221
424
|
}
|
|
222
|
-
return
|
|
223
|
-
nameToBlend,
|
|
224
|
-
nameToIndex,
|
|
225
|
-
blendToIndex,
|
|
226
|
-
blendToName,
|
|
227
|
-
indexToBlend,
|
|
228
|
-
indexToName,
|
|
229
|
-
indexType: null,
|
|
230
|
-
nameType: null
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// src/BlendModes/blend-modes-fast.ts
|
|
235
|
-
var overwriteFast = overwriteBase;
|
|
236
|
-
var sourceOverFast = (src, dst) => {
|
|
237
|
-
const sa = src >>> 24 & 255;
|
|
238
|
-
if (sa === 255) return src;
|
|
239
|
-
if (sa === 0) return dst;
|
|
240
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
241
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
242
|
-
const da = dst >>> 24 & 255;
|
|
243
|
-
const invA = 255 - sa;
|
|
244
|
-
const r = sr * sa + dr * invA >> 8;
|
|
245
|
-
const g = sg * sa + dg * invA >> 8;
|
|
246
|
-
const b = sb * sa + db * invA >> 8;
|
|
247
|
-
const a = 255 * sa + da * invA >> 8;
|
|
248
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
249
|
-
};
|
|
250
|
-
var darkenFast = (src, dst) => {
|
|
251
|
-
const sa = src >>> 24 & 255;
|
|
252
|
-
if (sa === 0) return dst;
|
|
253
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
254
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
255
|
-
const br = sr < dr ? sr : dr;
|
|
256
|
-
const bg = sg < dg ? sg : dg;
|
|
257
|
-
const bb = sb < db ? sb : db;
|
|
258
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
259
|
-
const invA = 255 - sa;
|
|
260
|
-
const r = br * sa + dr * invA >> 8;
|
|
261
|
-
const g = bg * sa + dg * invA >> 8;
|
|
262
|
-
const b = bb * sa + db * invA >> 8;
|
|
263
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
264
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
265
|
-
};
|
|
266
|
-
var multiplyFast = (src, dst) => {
|
|
267
|
-
const sa = src >>> 24 & 255;
|
|
268
|
-
if (sa === 0) return dst;
|
|
269
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
270
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
271
|
-
const br = sr * dr >> 8;
|
|
272
|
-
const bg = sg * dg >> 8;
|
|
273
|
-
const bb = sb * db >> 8;
|
|
274
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
275
|
-
const invA = 255 - sa;
|
|
276
|
-
const da = dst >>> 24 & 255;
|
|
277
|
-
const r = br * sa + dr * invA >> 8;
|
|
278
|
-
const g = bg * sa + dg * invA >> 8;
|
|
279
|
-
const b = bb * sa + db * invA >> 8;
|
|
280
|
-
const a = 255 * sa + da * invA >> 8;
|
|
281
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
282
|
-
};
|
|
283
|
-
var colorBurnFast = (src, dst) => {
|
|
284
|
-
const sa = src >>> 24 & 255;
|
|
285
|
-
if (sa === 0) return dst;
|
|
286
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
287
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
288
|
-
const br = dr === 255 ? 255 : sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / sr | 0);
|
|
289
|
-
const bg = dg === 255 ? 255 : sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / sg | 0);
|
|
290
|
-
const bb = db === 255 ? 255 : sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / sb | 0);
|
|
291
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
292
|
-
const invA = 255 - sa;
|
|
293
|
-
const da = dst >>> 24 & 255;
|
|
294
|
-
const r = br * sa + dr * invA >> 8;
|
|
295
|
-
const g = bg * sa + dg * invA >> 8;
|
|
296
|
-
const b = bb * sa + db * invA >> 8;
|
|
297
|
-
const a = 255 * sa + da * invA >> 8;
|
|
298
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
299
|
-
};
|
|
300
|
-
var linearBurnFast = (src, dst) => {
|
|
301
|
-
const sa = src >>> 24 & 255;
|
|
302
|
-
if (sa === 0) return dst;
|
|
303
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
304
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
305
|
-
const brU = dr + sr - 255;
|
|
306
|
-
const bgU = dg + sg - 255;
|
|
307
|
-
const bbU = db + sb - 255;
|
|
308
|
-
const br = brU < 0 ? 0 : brU;
|
|
309
|
-
const bg = bgU < 0 ? 0 : bgU;
|
|
310
|
-
const bb = bbU < 0 ? 0 : bbU;
|
|
311
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
312
|
-
const invA = 255 - sa;
|
|
313
|
-
const r = br * sa + dr * invA >> 8;
|
|
314
|
-
const g = bg * sa + dg * invA >> 8;
|
|
315
|
-
const b = bb * sa + db * invA >> 8;
|
|
316
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
317
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
318
|
-
};
|
|
319
|
-
var darkerFast = (src, dst) => {
|
|
320
|
-
const sa = src >>> 24 & 255;
|
|
321
|
-
if (sa === 0) return dst;
|
|
322
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
323
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
324
|
-
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
325
|
-
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
326
|
-
let br, bg, bb;
|
|
327
|
-
if (lumSrc < lumDst) {
|
|
328
|
-
br = sr;
|
|
329
|
-
bg = sg;
|
|
330
|
-
bb = sb;
|
|
331
|
-
} else {
|
|
332
|
-
br = dr;
|
|
333
|
-
bg = dg;
|
|
334
|
-
bb = db;
|
|
335
|
-
}
|
|
336
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
337
|
-
const invA = 255 - sa;
|
|
338
|
-
const r = br * sa + dr * invA >> 8;
|
|
339
|
-
const g = bg * sa + dg * invA >> 8;
|
|
340
|
-
const b = bb * sa + db * invA >> 8;
|
|
341
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
342
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
343
|
-
};
|
|
344
|
-
var lightenFast = (src, dst) => {
|
|
345
|
-
const sa = src >>> 24 & 255;
|
|
346
|
-
if (sa === 0) return dst;
|
|
347
|
-
const br = Math.max(src & 255, dst & 255);
|
|
348
|
-
const bg = Math.max(src >> 8 & 255, dst >> 8 & 255);
|
|
349
|
-
const bb = Math.max(src >> 16 & 255, dst >> 16 & 255);
|
|
350
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
351
|
-
const dr = dst & 255;
|
|
352
|
-
const dg = dst >> 8 & 255;
|
|
353
|
-
const db = dst >> 16 & 255;
|
|
354
|
-
const invA = 255 - sa;
|
|
355
|
-
const r = br * sa + dr * invA >> 8;
|
|
356
|
-
const g = bg * sa + dg * invA >> 8;
|
|
357
|
-
const b = bb * sa + db * invA >> 8;
|
|
358
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
359
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
360
|
-
};
|
|
361
|
-
var screenFast = (src, dst) => {
|
|
362
|
-
const sa = src >>> 24 & 255;
|
|
363
|
-
if (sa === 0) return dst;
|
|
364
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
365
|
-
const br = 255 - ((255 - (src & 255)) * (255 - dr) >> 8);
|
|
366
|
-
const bg = 255 - ((255 - (src >>> 8 & 255)) * (255 - dg) >> 8);
|
|
367
|
-
const bb = 255 - ((255 - (src >>> 16 & 255)) * (255 - db) >> 8);
|
|
368
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
369
|
-
const invA = 255 - sa;
|
|
370
|
-
const r = br * sa + dr * invA >> 8;
|
|
371
|
-
const g = bg * sa + dg * invA >> 8;
|
|
372
|
-
const b = bb * sa + db * invA >> 8;
|
|
373
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
374
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
375
|
-
};
|
|
376
|
-
var colorDodgeFast = (src, dst) => {
|
|
377
|
-
const sa = src >>> 24 & 255;
|
|
378
|
-
if (sa === 0) return dst;
|
|
379
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
380
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
381
|
-
const br = sr === 255 ? 255 : Math.min(255, (dr << 8) / (255 - sr) | 0);
|
|
382
|
-
const bg = sg === 255 ? 255 : Math.min(255, (dg << 8) / (255 - sg) | 0);
|
|
383
|
-
const bb = sb === 255 ? 255 : Math.min(255, (db << 8) / (255 - sb) | 0);
|
|
384
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
385
|
-
const invA = 255 - sa;
|
|
386
|
-
const r = br * sa + dr * invA >> 8;
|
|
387
|
-
const g = bg * sa + dg * invA >> 8;
|
|
388
|
-
const b = bb * sa + db * invA >> 8;
|
|
389
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
390
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
391
|
-
};
|
|
392
|
-
var linearDodgeFast = (src, dst) => {
|
|
393
|
-
const sa = src >>> 24 & 255;
|
|
394
|
-
if (sa === 0) return dst;
|
|
395
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
396
|
-
const brU = (src & 255) + dr;
|
|
397
|
-
const bgU = (src >>> 8 & 255) + dg;
|
|
398
|
-
const bbU = (src >>> 16 & 255) + db;
|
|
399
|
-
const br = brU > 255 ? 255 : brU;
|
|
400
|
-
const bg = bgU > 255 ? 255 : bgU;
|
|
401
|
-
const bb = bbU > 255 ? 255 : bbU;
|
|
402
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
403
|
-
const invA = 255 - sa;
|
|
404
|
-
const r = br * sa + dr * invA >> 8;
|
|
405
|
-
const g = bg * sa + dg * invA >> 8;
|
|
406
|
-
const b = bb * sa + db * invA >> 8;
|
|
407
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
408
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
409
|
-
};
|
|
410
|
-
var lighterFast = (src, dst) => {
|
|
411
|
-
const sa = src >>> 24 & 255;
|
|
412
|
-
if (sa === 0) return dst;
|
|
413
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
414
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
415
|
-
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
416
|
-
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
417
|
-
let br, bg, bb;
|
|
418
|
-
if (lumSrc > lumDst) {
|
|
419
|
-
br = sr;
|
|
420
|
-
bg = sg;
|
|
421
|
-
bb = sb;
|
|
422
|
-
} else {
|
|
423
|
-
br = dr;
|
|
424
|
-
bg = dg;
|
|
425
|
-
bb = db;
|
|
426
|
-
}
|
|
427
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
428
|
-
const invA = 255 - sa;
|
|
429
|
-
const r = br * sa + dr * invA >> 8;
|
|
430
|
-
const g = bg * sa + dg * invA >> 8;
|
|
431
|
-
const b = bb * sa + db * invA >> 8;
|
|
432
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
433
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
434
|
-
};
|
|
435
|
-
var overlayFast = (src, dst) => {
|
|
436
|
-
const sa = src >>> 24 & 255;
|
|
437
|
-
if (sa === 0) return dst;
|
|
438
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
439
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
440
|
-
const br = dr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
441
|
-
const bg = dg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
442
|
-
const bb = db < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
443
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
444
|
-
const invA = 255 - sa;
|
|
445
|
-
const r = br * sa + dr * invA >> 8;
|
|
446
|
-
const g = bg * sa + dg * invA >> 8;
|
|
447
|
-
const b = bb * sa + db * invA >> 8;
|
|
448
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
449
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
450
|
-
};
|
|
451
|
-
var softLightFast = (src, dst) => {
|
|
452
|
-
const sa = src >>> 24 & 255;
|
|
453
|
-
if (sa === 0) return dst;
|
|
454
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
455
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
456
|
-
const br = (255 - dr) * (sr * dr >> 8) + dr * (255 - ((255 - sr) * (255 - dr) >> 8)) >> 8;
|
|
457
|
-
const bg = (255 - dg) * (sg * dg >> 8) + dg * (255 - ((255 - sg) * (255 - dg) >> 8)) >> 8;
|
|
458
|
-
const bb = (255 - db) * (sb * db >> 8) + db * (255 - ((255 - sb) * (255 - db) >> 8)) >> 8;
|
|
459
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
460
|
-
const invA = 255 - sa;
|
|
461
|
-
const r = br * sa + dr * invA >> 8;
|
|
462
|
-
const g = bg * sa + dg * invA >> 8;
|
|
463
|
-
const b = bb * sa + db * invA >> 8;
|
|
464
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
465
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
466
|
-
};
|
|
467
|
-
var hardLightFast = (src, dst) => {
|
|
468
|
-
const sa = src >>> 24 & 255;
|
|
469
|
-
if (sa === 0) return dst;
|
|
470
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
471
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
472
|
-
const br = sr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
473
|
-
const bg = sg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
474
|
-
const bb = sb < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
475
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
476
|
-
const invA = 255 - sa;
|
|
477
|
-
const r = br * sa + dr * invA >> 8;
|
|
478
|
-
const g = bg * sa + dg * invA >> 8;
|
|
479
|
-
const b = bb * sa + db * invA >> 8;
|
|
480
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
481
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
482
|
-
};
|
|
483
|
-
var vividLightFast = (src, dst) => {
|
|
484
|
-
const sa = src >>> 24 & 255;
|
|
485
|
-
if (sa === 0) return dst;
|
|
486
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
487
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
488
|
-
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);
|
|
489
|
-
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);
|
|
490
|
-
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);
|
|
491
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
492
|
-
const invA = 255 - sa;
|
|
493
|
-
const r = br * sa + dr * invA >> 8;
|
|
494
|
-
const g = bg * sa + dg * invA >> 8;
|
|
495
|
-
const b = bb * sa + db * invA >> 8;
|
|
496
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
497
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
498
|
-
};
|
|
499
|
-
var linearLightFast = (src, dst) => {
|
|
500
|
-
const sa = src >>> 24 & 255;
|
|
501
|
-
if (sa === 0) return dst;
|
|
502
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
503
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
504
|
-
const brU = dr + 2 * sr - 255;
|
|
505
|
-
const bgU = dg + 2 * sg - 255;
|
|
506
|
-
const bbU = db + 2 * sb - 255;
|
|
507
|
-
const br = brU < 0 ? 0 : brU > 255 ? 255 : brU;
|
|
508
|
-
const bg = bgU < 0 ? 0 : bgU > 255 ? 255 : bgU;
|
|
509
|
-
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU;
|
|
510
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
511
|
-
const invA = 255 - sa;
|
|
512
|
-
const r = br * sa + dr * invA >> 8;
|
|
513
|
-
const g = bg * sa + dg * invA >> 8;
|
|
514
|
-
const b = bb * sa + db * invA >> 8;
|
|
515
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
516
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
517
|
-
};
|
|
518
|
-
var pinLightFast = (src, dst) => {
|
|
519
|
-
const sa = src >>> 24 & 255;
|
|
520
|
-
if (sa === 0) return dst;
|
|
521
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
522
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
523
|
-
const br = sr < 128 ? dr < 2 * sr ? dr : 2 * sr : dr > 2 * sr - 256 ? dr : 2 * sr - 256;
|
|
524
|
-
const bg = sg < 128 ? dg < 2 * sg ? dg : 2 * sg : dg > 2 * sg - 256 ? dg : 2 * sg - 256;
|
|
525
|
-
const bb = sb < 128 ? db < 2 * sb ? db : 2 * sb : db > 2 * sb - 256 ? db : 2 * sb - 256;
|
|
526
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
527
|
-
const invA = 255 - sa;
|
|
528
|
-
const r = br * sa + dr * invA >> 8;
|
|
529
|
-
const g = bg * sa + dg * invA >> 8;
|
|
530
|
-
const b = bb * sa + db * invA >> 8;
|
|
531
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
532
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
533
|
-
};
|
|
534
|
-
var hardMixFast = (src, dst) => {
|
|
535
|
-
const sa = src >>> 24 & 255;
|
|
536
|
-
if (sa === 0) return dst;
|
|
537
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
538
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
539
|
-
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;
|
|
540
|
-
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;
|
|
541
|
-
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;
|
|
542
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
543
|
-
const invA = 255 - sa;
|
|
544
|
-
const r = br * sa + dr * invA >> 8;
|
|
545
|
-
const g = bg * sa + dg * invA >> 8;
|
|
546
|
-
const b = bb * sa + db * invA >> 8;
|
|
547
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
548
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
549
|
-
};
|
|
550
|
-
var differenceFast = (src, dst) => {
|
|
551
|
-
const sa = src >>> 24 & 255;
|
|
552
|
-
if (sa === 0) return dst;
|
|
553
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
554
|
-
const brD = (src & 255) - dr;
|
|
555
|
-
const bgD = (src >>> 8 & 255) - dg;
|
|
556
|
-
const bbD = (src >>> 16 & 255) - db;
|
|
557
|
-
const br = brD < 0 ? -brD : brD;
|
|
558
|
-
const bg = bgD < 0 ? -bgD : bgD;
|
|
559
|
-
const bb = bbD < 0 ? -bbD : bbD;
|
|
560
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
561
|
-
const invA = 255 - sa;
|
|
562
|
-
const r = br * sa + dr * invA >> 8;
|
|
563
|
-
const g = bg * sa + dg * invA >> 8;
|
|
564
|
-
const b = bb * sa + db * invA >> 8;
|
|
565
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
566
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
567
|
-
};
|
|
568
|
-
var exclusionFast = (src, dst) => {
|
|
569
|
-
const sa = src >>> 24 & 255;
|
|
570
|
-
if (sa === 0) return dst;
|
|
571
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
572
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
573
|
-
const br = dr + sr - (dr * sr >> 7);
|
|
574
|
-
const bg = dg + sg - (dg * sg >> 7);
|
|
575
|
-
const bb = db + sb - (db * sb >> 7);
|
|
576
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
577
|
-
const invA = 255 - sa;
|
|
578
|
-
const r = br * sa + dr * invA >> 8;
|
|
579
|
-
const g = bg * sa + dg * invA >> 8;
|
|
580
|
-
const b = bb * sa + db * invA >> 8;
|
|
581
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
582
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
583
|
-
};
|
|
584
|
-
var subtractFast = (src, dst) => {
|
|
585
|
-
const sa = src >>> 24 & 255;
|
|
586
|
-
if (sa === 0) return dst;
|
|
587
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
588
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
589
|
-
const brU = dr - sr;
|
|
590
|
-
const bgU = dg - sg;
|
|
591
|
-
const bbU = db - sb;
|
|
592
|
-
const br = brU < 0 ? 0 : brU;
|
|
593
|
-
const bg = bgU < 0 ? 0 : bgU;
|
|
594
|
-
const bb = bbU < 0 ? 0 : bbU;
|
|
595
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
596
|
-
const invA = 255 - sa;
|
|
597
|
-
const r = br * sa + dr * invA >> 8;
|
|
598
|
-
const g = bg * sa + dg * invA >> 8;
|
|
599
|
-
const b = bb * sa + db * invA >> 8;
|
|
600
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
601
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
602
|
-
};
|
|
603
|
-
var divideFast = (src, dst) => {
|
|
604
|
-
const sa = src >>> 24 & 255;
|
|
605
|
-
if (sa === 0) return dst;
|
|
606
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
607
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
608
|
-
const br = sr === 0 ? 255 : Math.min(255, (dr << 8) / sr | 0);
|
|
609
|
-
const bg = sg === 0 ? 255 : Math.min(255, (dg << 8) / sg | 0);
|
|
610
|
-
const bb = sb === 0 ? 255 : Math.min(255, (db << 8) / sb | 0);
|
|
611
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
612
|
-
const invA = 255 - sa;
|
|
613
|
-
const r = br * sa + dr * invA >> 8;
|
|
614
|
-
const g = bg * sa + dg * invA >> 8;
|
|
615
|
-
const b = bb * sa + db * invA >> 8;
|
|
616
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
617
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
618
|
-
};
|
|
619
|
-
var BASE_FAST_BLEND_MODE_FUNCTIONS = {
|
|
620
|
-
[BaseBlendMode.overwrite]: overwriteFast,
|
|
621
|
-
[BaseBlendMode.sourceOver]: sourceOverFast,
|
|
622
|
-
[BaseBlendMode.darken]: darkenFast,
|
|
623
|
-
[BaseBlendMode.multiply]: multiplyFast,
|
|
624
|
-
[BaseBlendMode.colorBurn]: colorBurnFast,
|
|
625
|
-
[BaseBlendMode.linearBurn]: linearBurnFast,
|
|
626
|
-
[BaseBlendMode.darkerColor]: darkerFast,
|
|
627
|
-
[BaseBlendMode.lighten]: lightenFast,
|
|
628
|
-
[BaseBlendMode.screen]: screenFast,
|
|
629
|
-
[BaseBlendMode.colorDodge]: colorDodgeFast,
|
|
630
|
-
[BaseBlendMode.linearDodge]: linearDodgeFast,
|
|
631
|
-
[BaseBlendMode.lighterColor]: lighterFast,
|
|
632
|
-
[BaseBlendMode.overlay]: overlayFast,
|
|
633
|
-
[BaseBlendMode.softLight]: softLightFast,
|
|
634
|
-
[BaseBlendMode.hardLight]: hardLightFast,
|
|
635
|
-
[BaseBlendMode.vividLight]: vividLightFast,
|
|
636
|
-
[BaseBlendMode.linearLight]: linearLightFast,
|
|
637
|
-
[BaseBlendMode.pinLight]: pinLightFast,
|
|
638
|
-
[BaseBlendMode.hardMix]: hardMixFast,
|
|
639
|
-
[BaseBlendMode.difference]: differenceFast,
|
|
640
|
-
[BaseBlendMode.exclusion]: exclusionFast,
|
|
641
|
-
[BaseBlendMode.subtract]: subtractFast,
|
|
642
|
-
[BaseBlendMode.divide]: divideFast
|
|
643
|
-
};
|
|
644
|
-
function makeFastBlendModeRegistry() {
|
|
645
|
-
return makeBlendModeRegistry(BaseBlendMode, BASE_FAST_BLEND_MODE_FUNCTIONS);
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// src/_types.ts
|
|
649
|
-
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
650
|
-
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
651
|
-
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
652
|
-
return MaskType2;
|
|
653
|
-
})(MaskType || {});
|
|
654
|
-
|
|
655
|
-
// src/color.ts
|
|
656
|
-
function packColor(r, g, b, a) {
|
|
657
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
658
|
-
}
|
|
659
|
-
function packRGBA({ r, g, b, a }) {
|
|
660
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
661
|
-
}
|
|
662
|
-
var unpackRed = (packed) => packed >>> 0 & 255;
|
|
663
|
-
var unpackGreen = (packed) => packed >>> 8 & 255;
|
|
664
|
-
var unpackBlue = (packed) => packed >>> 16 & 255;
|
|
665
|
-
var unpackAlpha = (packed) => packed >>> 24 & 255;
|
|
666
|
-
function unpackColor(packed) {
|
|
667
|
-
return {
|
|
668
|
-
r: packed >>> 0 & 255,
|
|
669
|
-
g: packed >>> 8 & 255,
|
|
670
|
-
b: packed >>> 16 & 255,
|
|
671
|
-
a: packed >>> 24 & 255
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
|
|
675
|
-
function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
|
|
676
|
-
scratch.r = packed >>> 0 & 255;
|
|
677
|
-
scratch.g = packed >>> 8 & 255;
|
|
678
|
-
scratch.b = packed >>> 16 & 255;
|
|
679
|
-
scratch.a = packed >>> 24 & 255;
|
|
680
|
-
return scratch;
|
|
681
|
-
}
|
|
682
|
-
function colorDistance(a, b) {
|
|
683
|
-
const dr = (a & 255) - (b & 255);
|
|
684
|
-
const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
|
|
685
|
-
const db = (a >>> 16 & 255) - (b >>> 16 & 255);
|
|
686
|
-
const da = (a >>> 24 & 255) - (b >>> 24 & 255);
|
|
687
|
-
return dr * dr + dg * dg + db * db + da * da;
|
|
688
|
-
}
|
|
689
|
-
function lerpColor32(a, b, t) {
|
|
690
|
-
const r = (a & 255) + t * ((b & 255) - (a & 255));
|
|
691
|
-
const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
|
|
692
|
-
const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
|
|
693
|
-
const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
|
|
694
|
-
return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
|
|
695
|
-
}
|
|
696
|
-
function lerpColor32Fast(src, dst, w) {
|
|
697
|
-
const invA = 255 - w;
|
|
698
|
-
const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
|
|
699
|
-
const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
|
|
700
|
-
return (rb | ga << 8) >>> 0;
|
|
701
|
-
}
|
|
702
|
-
function color32ToHex(color) {
|
|
703
|
-
const r = (color & 255).toString(16).padStart(2, "0");
|
|
704
|
-
const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
|
|
705
|
-
const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
|
|
706
|
-
const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
|
|
707
|
-
return `#${r}${g}${b}${a}`;
|
|
708
|
-
}
|
|
709
|
-
function color32ToCssRGBA(color) {
|
|
710
|
-
const r = color & 255;
|
|
711
|
-
const g = color >>> 8 & 255;
|
|
712
|
-
const b = color >>> 16 & 255;
|
|
713
|
-
const a = color >>> 24 & 255;
|
|
714
|
-
const alpha = Number((a / 255).toFixed(3));
|
|
715
|
-
return `rgba(${r},${g},${b},${alpha})`;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// src/ImageData/extractImageDataBuffer.ts
|
|
719
|
-
function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
|
|
720
|
-
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
721
|
-
const { width: srcW, height: srcH, data: src } = imageData;
|
|
722
|
-
if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
|
|
723
|
-
const out = new Uint8ClampedArray(w * h * 4);
|
|
724
|
-
const x0 = Math.max(0, x);
|
|
725
|
-
const y0 = Math.max(0, y);
|
|
726
|
-
const x1 = Math.min(srcW, x + w);
|
|
727
|
-
const y1 = Math.min(srcH, y + h);
|
|
728
|
-
if (x1 <= x0 || y1 <= y0) return out;
|
|
729
|
-
for (let row = 0; row < y1 - y0; row++) {
|
|
730
|
-
const srcRow = y0 + row;
|
|
731
|
-
const srcStart = (srcRow * srcW + x0) * 4;
|
|
732
|
-
const rowLen = (x1 - x0) * 4;
|
|
733
|
-
const dstRow = y0 - y + row;
|
|
734
|
-
const dstCol = x0 - x;
|
|
735
|
-
const dstStart = (dstRow * w + dstCol) * 4;
|
|
736
|
-
out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
737
|
-
}
|
|
738
|
-
return out;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
// src/Mask/extractMask.ts
|
|
742
|
-
function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
743
|
-
let finalX;
|
|
744
|
-
let finalY;
|
|
745
|
-
let finalW;
|
|
746
|
-
let finalH;
|
|
747
|
-
if (typeof xOrRect === "object") {
|
|
748
|
-
finalX = xOrRect.x;
|
|
749
|
-
finalY = xOrRect.y;
|
|
750
|
-
finalW = xOrRect.w;
|
|
751
|
-
finalH = xOrRect.h;
|
|
752
|
-
} else {
|
|
753
|
-
finalX = xOrRect;
|
|
754
|
-
finalY = y;
|
|
755
|
-
finalW = w;
|
|
756
|
-
finalH = h;
|
|
757
|
-
}
|
|
758
|
-
const out = new Uint8Array(finalW * finalH);
|
|
759
|
-
const srcH = mask.length / maskWidth;
|
|
760
|
-
for (let row = 0; row < finalH; row++) {
|
|
761
|
-
const currentSrcY = finalY + row;
|
|
762
|
-
if (currentSrcY < 0 || currentSrcY >= srcH) {
|
|
763
|
-
continue;
|
|
764
|
-
}
|
|
765
|
-
const start = Math.max(0, finalX);
|
|
766
|
-
const end = Math.min(maskWidth, finalX + finalW);
|
|
767
|
-
if (start < end) {
|
|
768
|
-
const srcOffset = currentSrcY * maskWidth + start;
|
|
769
|
-
const dstOffset = row * finalW + (start - finalX);
|
|
770
|
-
const count = end - start;
|
|
771
|
-
out.set(
|
|
772
|
-
mask.subarray(srcOffset, srcOffset + count),
|
|
773
|
-
dstOffset
|
|
774
|
-
);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
return out;
|
|
425
|
+
return out;
|
|
778
426
|
}
|
|
779
427
|
|
|
780
428
|
// src/Rect/trimRectBounds.ts
|
|
@@ -784,14 +432,8 @@ function trimRectBounds(target, bounds) {
|
|
|
784
432
|
const originalW = target.w;
|
|
785
433
|
const intersectedX = Math.max(target.x, bounds.x);
|
|
786
434
|
const intersectedY = Math.max(target.y, bounds.y);
|
|
787
|
-
const intersectedMaxX = Math.min(
|
|
788
|
-
|
|
789
|
-
bounds.x + bounds.w
|
|
790
|
-
);
|
|
791
|
-
const intersectedMaxY = Math.min(
|
|
792
|
-
target.y + target.h,
|
|
793
|
-
bounds.y + bounds.h
|
|
794
|
-
);
|
|
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);
|
|
795
437
|
if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
|
|
796
438
|
target.w = 0;
|
|
797
439
|
target.h = 0;
|
|
@@ -809,14 +451,7 @@ function trimRectBounds(target, bounds) {
|
|
|
809
451
|
target.w = intersectedW;
|
|
810
452
|
target.h = intersectedH;
|
|
811
453
|
if ("mask" in target && target.mask) {
|
|
812
|
-
const currentMask = extractMask(
|
|
813
|
-
target.mask,
|
|
814
|
-
originalW,
|
|
815
|
-
offsetX,
|
|
816
|
-
offsetY,
|
|
817
|
-
intersectedW,
|
|
818
|
-
intersectedH
|
|
819
|
-
);
|
|
454
|
+
const currentMask = extractMask(target.mask, originalW, offsetX, offsetY, intersectedW, intersectedH);
|
|
820
455
|
let minX = intersectedW;
|
|
821
456
|
let maxX = -1;
|
|
822
457
|
let minY = intersectedH;
|
|
@@ -840,14 +475,7 @@ function trimRectBounds(target, bounds) {
|
|
|
840
475
|
const finalW = maxX - minX + 1;
|
|
841
476
|
const finalH = maxY - minY + 1;
|
|
842
477
|
if (finalW !== intersectedW || finalH !== intersectedH) {
|
|
843
|
-
target.mask = extractMask(
|
|
844
|
-
currentMask,
|
|
845
|
-
intersectedW,
|
|
846
|
-
minX,
|
|
847
|
-
minY,
|
|
848
|
-
finalW,
|
|
849
|
-
finalH
|
|
850
|
-
);
|
|
478
|
+
target.mask = extractMask(currentMask, intersectedW, minX, minY, finalW, finalH);
|
|
851
479
|
target.x += minX;
|
|
852
480
|
target.y += minY;
|
|
853
481
|
target.w = finalW;
|
|
@@ -870,11 +498,7 @@ function floodFillSelection(img, startX, startY, {
|
|
|
870
498
|
data32 = img.data32;
|
|
871
499
|
imageData = img.imageData;
|
|
872
500
|
} else {
|
|
873
|
-
data32 = new Uint32Array(
|
|
874
|
-
img.data.buffer,
|
|
875
|
-
img.data.byteOffset,
|
|
876
|
-
img.data.byteLength >> 2
|
|
877
|
-
);
|
|
501
|
+
data32 = new Uint32Array(img.data.buffer, img.data.byteOffset, img.data.byteLength >> 2);
|
|
878
502
|
imageData = img;
|
|
879
503
|
}
|
|
880
504
|
const {
|
|
@@ -985,35 +609,514 @@ function floodFillSelection(img, startX, startY, {
|
|
|
985
609
|
finalMask[my * sw + mx] = 1;
|
|
986
610
|
}
|
|
987
611
|
}
|
|
988
|
-
trimRectBounds(
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
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
|
+
}
|
|
999
682
|
return {
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
683
|
+
registryName,
|
|
684
|
+
nameToBlend,
|
|
685
|
+
nameToIndex,
|
|
686
|
+
blendToIndex,
|
|
687
|
+
blendToName,
|
|
688
|
+
indexToBlend,
|
|
689
|
+
indexToName,
|
|
690
|
+
indexType: null,
|
|
691
|
+
nameType: null
|
|
1004
692
|
};
|
|
1005
693
|
}
|
|
1006
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;
|
|
796
|
+
}
|
|
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;
|
|
887
|
+
}
|
|
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);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1007
1109
|
// src/BlendModes/blend-modes-perfect.ts
|
|
1008
1110
|
var overwritePerfect = overwriteBase;
|
|
1009
1111
|
var sourceOverPerfect = (src, dst) => {
|
|
1010
1112
|
const sa = src >>> 24 & 255;
|
|
1011
1113
|
if (sa === 255) return src;
|
|
1012
1114
|
if (sa === 0) return dst;
|
|
1013
|
-
const
|
|
1115
|
+
const da = dst >>> 24 & 255;
|
|
1116
|
+
if (da === 0) return src;
|
|
1014
1117
|
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1015
1118
|
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1016
|
-
const
|
|
1119
|
+
const invA = 255 - sa;
|
|
1017
1120
|
const tR = sr * sa + dr * invA;
|
|
1018
1121
|
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1019
1122
|
const tG = sg * sa + dg * invA;
|
|
@@ -1555,9 +1658,53 @@ var BASE_PERFECT_BLEND_MODE_FUNCTIONS = {
|
|
|
1555
1658
|
[BaseBlendMode.subtract]: subtractPerfect,
|
|
1556
1659
|
[BaseBlendMode.divide]: dividePerfect
|
|
1557
1660
|
};
|
|
1558
|
-
function makePerfectBlendModeRegistry() {
|
|
1559
|
-
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)}`);
|
|
1560
1702
|
}
|
|
1703
|
+
var getKeyByValue = (obj, value) => {
|
|
1704
|
+
for (const key in obj) {
|
|
1705
|
+
if (obj[key] === value) return key;
|
|
1706
|
+
}
|
|
1707
|
+
};
|
|
1561
1708
|
|
|
1562
1709
|
// src/Canvas/_constants.ts
|
|
1563
1710
|
var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
|
|
@@ -1596,7 +1743,10 @@ function makeReusableCanvas() {
|
|
|
1596
1743
|
} else {
|
|
1597
1744
|
ctx.clearRect(0, 0, width, height);
|
|
1598
1745
|
}
|
|
1599
|
-
return {
|
|
1746
|
+
return {
|
|
1747
|
+
canvas,
|
|
1748
|
+
ctx
|
|
1749
|
+
};
|
|
1600
1750
|
}
|
|
1601
1751
|
get2.reset = () => {
|
|
1602
1752
|
canvas = null;
|
|
@@ -1610,21 +1760,13 @@ async function imgBlobToImageData(blob) {
|
|
|
1610
1760
|
let bitmap = null;
|
|
1611
1761
|
try {
|
|
1612
1762
|
bitmap = await createImageBitmap(blob);
|
|
1613
|
-
const canvas = new OffscreenCanvas(
|
|
1614
|
-
bitmap.width,
|
|
1615
|
-
bitmap.height
|
|
1616
|
-
);
|
|
1763
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
1617
1764
|
const ctx = canvas.getContext("2d");
|
|
1618
1765
|
if (!ctx) {
|
|
1619
1766
|
throw new Error("Failed to get 2D context");
|
|
1620
1767
|
}
|
|
1621
1768
|
ctx.drawImage(bitmap, 0, 0);
|
|
1622
|
-
return ctx.getImageData(
|
|
1623
|
-
0,
|
|
1624
|
-
0,
|
|
1625
|
-
bitmap.width,
|
|
1626
|
-
bitmap.height
|
|
1627
|
-
);
|
|
1769
|
+
return ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
1628
1770
|
} finally {
|
|
1629
1771
|
bitmap?.close();
|
|
1630
1772
|
}
|
|
@@ -1672,6 +1814,64 @@ async function writeImageDataToClipboard(imageData) {
|
|
|
1672
1814
|
return writeImgBlobToClipboard(blob);
|
|
1673
1815
|
}
|
|
1674
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
|
+
|
|
1675
1875
|
// src/History/PixelPatchTiles.ts
|
|
1676
1876
|
var PixelTile = class {
|
|
1677
1877
|
constructor(id, tx, ty, tileArea) {
|
|
@@ -1725,12 +1925,7 @@ var PixelAccumulator = class {
|
|
|
1725
1925
|
tile.ty = ty;
|
|
1726
1926
|
return tile;
|
|
1727
1927
|
}
|
|
1728
|
-
return new PixelTile(
|
|
1729
|
-
id,
|
|
1730
|
-
tx,
|
|
1731
|
-
ty,
|
|
1732
|
-
this.config.tileArea
|
|
1733
|
-
);
|
|
1928
|
+
return new PixelTile(id, tx, ty, this.config.tileArea);
|
|
1734
1929
|
}
|
|
1735
1930
|
recyclePatch(patch) {
|
|
1736
1931
|
const before = patch.beforeTiles;
|
|
@@ -1761,11 +1956,7 @@ var PixelAccumulator = class {
|
|
|
1761
1956
|
let id = ty * columns + tx;
|
|
1762
1957
|
let tile = this.lookup[id];
|
|
1763
1958
|
if (!tile) {
|
|
1764
|
-
tile = this.getTile(
|
|
1765
|
-
id,
|
|
1766
|
-
tx,
|
|
1767
|
-
ty
|
|
1768
|
-
);
|
|
1959
|
+
tile = this.getTile(id, tx, ty);
|
|
1769
1960
|
this.extractState(tile);
|
|
1770
1961
|
this.lookup[id] = tile;
|
|
1771
1962
|
this.beforeTiles.push(tile);
|
|
@@ -1791,11 +1982,7 @@ var PixelAccumulator = class {
|
|
|
1791
1982
|
let id = ty * columns + tx;
|
|
1792
1983
|
let tile = this.lookup[id];
|
|
1793
1984
|
if (!tile) {
|
|
1794
|
-
tile = this.getTile(
|
|
1795
|
-
id,
|
|
1796
|
-
tx,
|
|
1797
|
-
ty
|
|
1798
|
-
);
|
|
1985
|
+
tile = this.getTile(id, tx, ty);
|
|
1799
1986
|
this.extractState(tile);
|
|
1800
1987
|
this.lookup[id] = tile;
|
|
1801
1988
|
this.beforeTiles.push(tile);
|
|
@@ -1834,11 +2021,7 @@ var PixelAccumulator = class {
|
|
|
1834
2021
|
for (let i = 0; i < length; i++) {
|
|
1835
2022
|
let beforeTile = this.beforeTiles[i];
|
|
1836
2023
|
if (beforeTile) {
|
|
1837
|
-
let afterTile = this.getTile(
|
|
1838
|
-
beforeTile.id,
|
|
1839
|
-
beforeTile.tx,
|
|
1840
|
-
beforeTile.ty
|
|
1841
|
-
);
|
|
2024
|
+
let afterTile = this.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
|
|
1842
2025
|
this.extractState(afterTile);
|
|
1843
2026
|
afterTiles.push(afterTile);
|
|
1844
2027
|
}
|
|
@@ -1851,64 +2034,6 @@ var PixelAccumulator = class {
|
|
|
1851
2034
|
}
|
|
1852
2035
|
};
|
|
1853
2036
|
|
|
1854
|
-
// src/History/HistoryManager.ts
|
|
1855
|
-
var HistoryManager = class {
|
|
1856
|
-
constructor(maxSteps = 50) {
|
|
1857
|
-
this.maxSteps = maxSteps;
|
|
1858
|
-
this.undoStack = [];
|
|
1859
|
-
this.redoStack = [];
|
|
1860
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
1861
|
-
}
|
|
1862
|
-
undoStack;
|
|
1863
|
-
redoStack;
|
|
1864
|
-
listeners;
|
|
1865
|
-
get canUndo() {
|
|
1866
|
-
return this.undoStack.length > 0;
|
|
1867
|
-
}
|
|
1868
|
-
get canRedo() {
|
|
1869
|
-
return this.redoStack.length > 0;
|
|
1870
|
-
}
|
|
1871
|
-
subscribe(fn) {
|
|
1872
|
-
this.listeners.add(fn);
|
|
1873
|
-
return () => this.listeners.delete(fn);
|
|
1874
|
-
}
|
|
1875
|
-
notify() {
|
|
1876
|
-
this.listeners.forEach((fn) => fn());
|
|
1877
|
-
}
|
|
1878
|
-
commit(action) {
|
|
1879
|
-
this.undoStack.push(action);
|
|
1880
|
-
this.clearRedoStack();
|
|
1881
|
-
if (this.undoStack.length > this.maxSteps) {
|
|
1882
|
-
this.undoStack.shift()?.dispose?.();
|
|
1883
|
-
}
|
|
1884
|
-
this.notify();
|
|
1885
|
-
}
|
|
1886
|
-
undo() {
|
|
1887
|
-
let action = this.undoStack.pop();
|
|
1888
|
-
if (!action) return;
|
|
1889
|
-
this.redoStack.push(action);
|
|
1890
|
-
action.undo();
|
|
1891
|
-
this.notify();
|
|
1892
|
-
}
|
|
1893
|
-
redo() {
|
|
1894
|
-
let action = this.redoStack.pop();
|
|
1895
|
-
if (!action) return;
|
|
1896
|
-
this.undoStack.push(action);
|
|
1897
|
-
action.redo();
|
|
1898
|
-
this.notify();
|
|
1899
|
-
}
|
|
1900
|
-
clearRedoStack() {
|
|
1901
|
-
let length = this.redoStack.length;
|
|
1902
|
-
for (let i = 0; i < length; i++) {
|
|
1903
|
-
let action = this.redoStack[i];
|
|
1904
|
-
if (action) {
|
|
1905
|
-
action.dispose?.();
|
|
1906
|
-
}
|
|
1907
|
-
}
|
|
1908
|
-
this.redoStack.length = 0;
|
|
1909
|
-
}
|
|
1910
|
-
};
|
|
1911
|
-
|
|
1912
2037
|
// src/History/PixelEngineConfig.ts
|
|
1913
2038
|
var PixelEngineConfig = class {
|
|
1914
2039
|
tileSize;
|
|
@@ -1926,51 +2051,210 @@ var PixelEngineConfig = class {
|
|
|
1926
2051
|
}
|
|
1927
2052
|
};
|
|
1928
2053
|
|
|
1929
|
-
// src/PixelData/
|
|
1930
|
-
function
|
|
1931
|
-
const
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
2054
|
+
// src/PixelData/applyAlphaMaskToPixelData.ts
|
|
2055
|
+
function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
2056
|
+
const {
|
|
2057
|
+
x: targetX = 0,
|
|
2058
|
+
y: targetY = 0,
|
|
2059
|
+
w: width = dst.width,
|
|
2060
|
+
h: height = dst.height,
|
|
2061
|
+
alpha: globalAlpha = 255,
|
|
2062
|
+
mw,
|
|
2063
|
+
mx = 0,
|
|
2064
|
+
my = 0,
|
|
2065
|
+
invertMask = false
|
|
2066
|
+
} = opts;
|
|
2067
|
+
if (globalAlpha === 0) return;
|
|
2068
|
+
let x = targetX;
|
|
2069
|
+
let y = targetY;
|
|
2070
|
+
let w = width;
|
|
2071
|
+
let h = height;
|
|
2072
|
+
if (x < 0) {
|
|
2073
|
+
w += x;
|
|
2074
|
+
x = 0;
|
|
2075
|
+
}
|
|
2076
|
+
if (y < 0) {
|
|
2077
|
+
h += y;
|
|
2078
|
+
y = 0;
|
|
2079
|
+
}
|
|
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;
|
|
1968
2223
|
}
|
|
1969
2224
|
}
|
|
2225
|
+
dIdx++;
|
|
2226
|
+
mIdx++;
|
|
1970
2227
|
}
|
|
2228
|
+
dIdx += dStride;
|
|
2229
|
+
mIdx += mStride;
|
|
1971
2230
|
}
|
|
1972
2231
|
}
|
|
1973
|
-
|
|
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) {
|
|
1974
2258
|
const r = brushSize / 2;
|
|
1975
2259
|
const minOffset = -Math.ceil(r - 0.5);
|
|
1976
2260
|
const maxOffset = Math.floor(r - 0.5);
|
|
@@ -1984,104 +2268,137 @@ function getCircleBrushBounds(centerX, centerY, brushSize, targetWidth, targetHe
|
|
|
1984
2268
|
w: 0,
|
|
1985
2269
|
h: 0
|
|
1986
2270
|
};
|
|
1987
|
-
const cStartX =
|
|
1988
|
-
const cStartY =
|
|
1989
|
-
const cEndX =
|
|
1990
|
-
const cEndY =
|
|
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;
|
|
1991
2277
|
res.x = cStartX;
|
|
1992
2278
|
res.y = cStartY;
|
|
1993
|
-
res.w =
|
|
1994
|
-
res.h =
|
|
2279
|
+
res.w = w < 0 ? 0 : w;
|
|
2280
|
+
res.h = h < 0 ? 0 : h;
|
|
1995
2281
|
return res;
|
|
1996
2282
|
}
|
|
1997
2283
|
|
|
1998
|
-
// src/
|
|
1999
|
-
|
|
2000
|
-
target;
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
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
|
+
}
|
|
2038
2330
|
}
|
|
2039
|
-
}
|
|
2331
|
+
}
|
|
2040
2332
|
|
|
2041
2333
|
// src/History/PixelMutator/mutatorApplyCircleBrush.ts
|
|
2042
|
-
var
|
|
2043
|
-
|
|
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
|
+
};
|
|
2044
2349
|
return {
|
|
2045
2350
|
applyCircleBrush(color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn) {
|
|
2046
|
-
const
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
);
|
|
2054
|
-
const { x, y, w, h } = circleBounds;
|
|
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;
|
|
2055
2358
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2056
|
-
|
|
2057
|
-
writer.target,
|
|
2058
|
-
color,
|
|
2059
|
-
centerX,
|
|
2060
|
-
centerY,
|
|
2061
|
-
brushSize,
|
|
2062
|
-
alpha,
|
|
2063
|
-
fallOff,
|
|
2064
|
-
blendFn,
|
|
2065
|
-
circleBounds
|
|
2066
|
-
);
|
|
2359
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
|
|
2067
2360
|
}
|
|
2068
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);
|
|
2371
|
+
return;
|
|
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
|
+
}
|
|
2069
2382
|
}
|
|
2070
2383
|
|
|
2071
|
-
// src/PixelData/
|
|
2072
|
-
function
|
|
2384
|
+
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
2385
|
+
function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
|
|
2073
2386
|
const {
|
|
2074
2387
|
x: targetX = 0,
|
|
2075
2388
|
y: targetY = 0,
|
|
2076
2389
|
w: width = dst.width,
|
|
2077
2390
|
h: height = dst.height,
|
|
2078
2391
|
alpha: globalAlpha = 255,
|
|
2079
|
-
|
|
2080
|
-
mw,
|
|
2392
|
+
blendFn = sourceOverPerfect,
|
|
2393
|
+
mw = width,
|
|
2081
2394
|
mx = 0,
|
|
2082
2395
|
my = 0,
|
|
2083
2396
|
invertMask = false
|
|
2084
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;
|
|
2085
2402
|
let x = targetX;
|
|
2086
2403
|
let y = targetY;
|
|
2087
2404
|
let w = width;
|
|
@@ -2096,57 +2413,49 @@ function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2096
2413
|
}
|
|
2097
2414
|
const actualW = Math.min(w, dst.width - x);
|
|
2098
2415
|
const actualH = Math.min(h, dst.height - y);
|
|
2099
|
-
if (actualW <= 0 || actualH <= 0
|
|
2100
|
-
|
|
2101
|
-
|
|
2416
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2417
|
+
const dx = x - targetX | 0;
|
|
2418
|
+
const dy = y - targetY | 0;
|
|
2102
2419
|
const dst32 = dst.data32;
|
|
2103
2420
|
const dw = dst.width;
|
|
2104
|
-
const mPitch = mw
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
const
|
|
2108
|
-
let
|
|
2109
|
-
|
|
2110
|
-
const
|
|
2111
|
-
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;
|
|
2112
2428
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2113
2429
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2114
2430
|
const mVal = mask[mIdx];
|
|
2431
|
+
const effM = invertMask ? 255 - mVal : mVal;
|
|
2432
|
+
if (effM === 0) {
|
|
2433
|
+
dIdx++;
|
|
2434
|
+
mIdx++;
|
|
2435
|
+
continue;
|
|
2436
|
+
}
|
|
2115
2437
|
let weight = globalAlpha;
|
|
2116
|
-
if (
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
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) {
|
|
2129
2452
|
dIdx++;
|
|
2130
2453
|
mIdx++;
|
|
2131
2454
|
continue;
|
|
2132
2455
|
}
|
|
2133
|
-
|
|
2134
|
-
}
|
|
2135
|
-
if (weight === 0) {
|
|
2136
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2137
|
-
} else {
|
|
2138
|
-
const d = dst32[dIdx];
|
|
2139
|
-
const da = d >>> 24;
|
|
2140
|
-
let finalAlpha = da;
|
|
2141
|
-
if (da === 0) {
|
|
2142
|
-
} else if (weight === 255) {
|
|
2143
|
-
} else if (da === 255) {
|
|
2144
|
-
finalAlpha = weight;
|
|
2145
|
-
} else {
|
|
2146
|
-
finalAlpha = da * weight + 128 >> 8;
|
|
2147
|
-
}
|
|
2148
|
-
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2456
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
2149
2457
|
}
|
|
2458
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
2150
2459
|
dIdx++;
|
|
2151
2460
|
mIdx++;
|
|
2152
2461
|
}
|
|
@@ -2155,159 +2464,595 @@ function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2155
2464
|
}
|
|
2156
2465
|
}
|
|
2157
2466
|
|
|
2158
|
-
// src/
|
|
2159
|
-
function
|
|
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
|
+
};
|
|
2160
2515
|
return {
|
|
2161
|
-
|
|
2162
|
-
let target = writer.target;
|
|
2516
|
+
applyCircleBrushStroke(color, x0, y0, x1, y1, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
2163
2517
|
const {
|
|
2164
|
-
x
|
|
2165
|
-
y
|
|
2166
|
-
w
|
|
2167
|
-
h
|
|
2168
|
-
} =
|
|
2169
|
-
|
|
2170
|
-
|
|
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
|
+
}
|
|
2561
|
+
}
|
|
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);
|
|
2171
2570
|
}
|
|
2172
2571
|
};
|
|
2173
|
-
}
|
|
2174
|
-
|
|
2175
|
-
// src/ImageData/imageDataToUInt32Array.ts
|
|
2176
|
-
function imageDataToUInt32Array(imageData) {
|
|
2177
|
-
return new Uint32Array(
|
|
2178
|
-
imageData.data.buffer,
|
|
2179
|
-
imageData.data.byteOffset,
|
|
2180
|
-
// Shift right by 2 is a fast bitwise division by 4.
|
|
2181
|
-
imageData.data.byteLength >> 2
|
|
2182
|
-
);
|
|
2183
|
-
}
|
|
2572
|
+
});
|
|
2184
2573
|
|
|
2185
|
-
// src/PixelData/
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
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;
|
|
2194
2599
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2600
|
+
if (y < 0) {
|
|
2601
|
+
h += y;
|
|
2602
|
+
y = 0;
|
|
2198
2603
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
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;
|
|
2202
2612
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
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;
|
|
2629
|
+
}
|
|
2630
|
+
dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
|
|
2631
|
+
dIdx++;
|
|
2632
|
+
mIdx++;
|
|
2633
|
+
}
|
|
2634
|
+
dIdx += dStride;
|
|
2635
|
+
mIdx += mStride;
|
|
2215
2636
|
}
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
// src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
|
|
2640
|
+
var defaults5 = {
|
|
2641
|
+
forEachLinePoint,
|
|
2642
|
+
blendColorPixelDataBinaryMask,
|
|
2643
|
+
getCircleBrushOrPencilBounds,
|
|
2644
|
+
getCircleBrushOrPencilStrokeBounds
|
|
2216
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
|
+
});
|
|
2726
|
+
|
|
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
|
+
}
|
|
2217
2751
|
|
|
2218
2752
|
// src/PixelData/applyRectBrushToPixelData.ts
|
|
2219
2753
|
function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2220
2754
|
const targetWidth = target.width;
|
|
2221
2755
|
const targetHeight = target.height;
|
|
2222
|
-
const b = bounds ??
|
|
2223
|
-
centerX,
|
|
2224
|
-
centerY,
|
|
2225
|
-
brushWidth,
|
|
2226
|
-
brushHeight,
|
|
2227
|
-
targetWidth,
|
|
2228
|
-
targetHeight
|
|
2229
|
-
);
|
|
2756
|
+
const b = bounds ?? getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight);
|
|
2230
2757
|
if (b.w <= 0 || b.h <= 0) return;
|
|
2231
2758
|
const data32 = target.data32;
|
|
2232
2759
|
const baseColor = color & 16777215;
|
|
2233
|
-
const
|
|
2760
|
+
const baseSrcAlpha = color >>> 24;
|
|
2761
|
+
const isOpaque = alpha === 255;
|
|
2234
2762
|
const invHalfW = 1 / (brushWidth / 2);
|
|
2235
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);
|
|
2236
2768
|
const endX = b.x + b.w;
|
|
2237
2769
|
const endY = b.y + b.h;
|
|
2770
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2238
2771
|
for (let py = b.y; py < endY; py++) {
|
|
2239
2772
|
const rowOffset = py * targetWidth;
|
|
2240
|
-
const dy =
|
|
2773
|
+
const dy = Math.abs(py - fCenterY + centerOffsetY) * invHalfH;
|
|
2241
2774
|
for (let px = b.x; px < endX; px++) {
|
|
2242
2775
|
const idx = rowOffset + px;
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
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;
|
|
2252
2792
|
}
|
|
2793
|
+
data32[idx] = blendFn(finalCol, data32[idx]);
|
|
2253
2794
|
}
|
|
2254
2795
|
}
|
|
2255
2796
|
}
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
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
|
+
};
|
|
2814
|
+
return {
|
|
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);
|
|
2817
|
+
const {
|
|
2818
|
+
x,
|
|
2819
|
+
y,
|
|
2820
|
+
w,
|
|
2821
|
+
h
|
|
2822
|
+
} = bounds;
|
|
2823
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2824
|
+
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2825
|
+
}
|
|
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;
|
|
2842
|
+
}
|
|
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 = {
|
|
2262
2951
|
x: 0,
|
|
2263
2952
|
y: 0,
|
|
2264
2953
|
w: 0,
|
|
2265
2954
|
h: 0
|
|
2266
2955
|
};
|
|
2267
|
-
const cStartX = targetWidth !== void 0 ? Math.max(0, startX) : startX;
|
|
2268
|
-
const cStartY = targetHeight !== void 0 ? Math.max(0, startY) : startY;
|
|
2269
|
-
const cEndX = targetWidth !== void 0 ? Math.min(targetWidth, endX) : endX;
|
|
2270
|
-
const cEndY = targetHeight !== void 0 ? Math.min(targetHeight, endY) : endY;
|
|
2271
|
-
const w = cEndX - cStartX;
|
|
2272
|
-
const h = cEndY - cStartY;
|
|
2273
|
-
res.x = cStartX;
|
|
2274
|
-
res.y = cStartY;
|
|
2275
|
-
res.w = w < 0 ? 0 : w;
|
|
2276
|
-
res.h = h < 0 ? 0 : h;
|
|
2277
|
-
return res;
|
|
2278
|
-
}
|
|
2279
|
-
|
|
2280
|
-
// src/History/PixelMutator/mutatorApplyRectBrush.ts
|
|
2281
|
-
var boundsOut2 = { x: 0, y: 0, w: 0, h: 0 };
|
|
2282
|
-
function mutatorApplyRectBrush(writer) {
|
|
2283
2956
|
return {
|
|
2284
|
-
|
|
2285
|
-
const bounds =
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
boundsOut2
|
|
2293
|
-
);
|
|
2294
|
-
const { x, y, w, h } = bounds;
|
|
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;
|
|
2295
2965
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2296
|
-
|
|
2297
|
-
writer.target,
|
|
2298
|
-
color,
|
|
2299
|
-
centerX,
|
|
2300
|
-
centerY,
|
|
2301
|
-
brushWidth,
|
|
2302
|
-
brushHeight,
|
|
2303
|
-
alpha,
|
|
2304
|
-
fallOff,
|
|
2305
|
-
blendFn,
|
|
2306
|
-
bounds
|
|
2307
|
-
);
|
|
2966
|
+
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2308
2967
|
}
|
|
2309
2968
|
};
|
|
2310
|
-
}
|
|
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
|
+
});
|
|
2311
3056
|
|
|
2312
3057
|
// src/PixelData/blendColorPixelData.ts
|
|
2313
3058
|
function blendColorPixelData(dst, color, opts = {}) {
|
|
@@ -2317,22 +3062,13 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2317
3062
|
w: width = dst.width,
|
|
2318
3063
|
h: height = dst.height,
|
|
2319
3064
|
alpha: globalAlpha = 255,
|
|
2320
|
-
blendFn =
|
|
2321
|
-
mask,
|
|
2322
|
-
maskType = 0 /* ALPHA */,
|
|
2323
|
-
mw,
|
|
2324
|
-
mx = 0,
|
|
2325
|
-
my = 0,
|
|
2326
|
-
invertMask = false
|
|
3065
|
+
blendFn = sourceOverPerfect
|
|
2327
3066
|
} = opts;
|
|
2328
3067
|
if (globalAlpha === 0) return;
|
|
2329
3068
|
const baseSrcAlpha = color >>> 24;
|
|
2330
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
3069
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2331
3070
|
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2332
|
-
let x = targetX;
|
|
2333
|
-
let y = targetY;
|
|
2334
|
-
let w = width;
|
|
2335
|
-
let h = height;
|
|
3071
|
+
let x = targetX, y = targetY, w = width, h = height;
|
|
2336
3072
|
if (x < 0) {
|
|
2337
3073
|
w += x;
|
|
2338
3074
|
x = 0;
|
|
@@ -2344,76 +3080,33 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2344
3080
|
const actualW = Math.min(w, dst.width - x);
|
|
2345
3081
|
const actualH = Math.min(h, dst.height - y);
|
|
2346
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
|
+
}
|
|
2347
3089
|
const dst32 = dst.data32;
|
|
2348
3090
|
const dw = dst.width;
|
|
2349
|
-
|
|
2350
|
-
const
|
|
2351
|
-
const dx = x - targetX;
|
|
2352
|
-
const dy = y - targetY;
|
|
2353
|
-
let dIdx = y * dw + x;
|
|
2354
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2355
|
-
const dStride = dw - actualW;
|
|
2356
|
-
const mStride = mPitch - actualW;
|
|
3091
|
+
let dIdx = y * dw + x | 0;
|
|
3092
|
+
const dStride = dw - actualW | 0;
|
|
2357
3093
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2358
3094
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2359
|
-
|
|
2360
|
-
if (mask) {
|
|
2361
|
-
const mVal = mask[mIdx];
|
|
2362
|
-
if (isAlphaMask) {
|
|
2363
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2364
|
-
if (effectiveM === 0) {
|
|
2365
|
-
dIdx++;
|
|
2366
|
-
mIdx++;
|
|
2367
|
-
continue;
|
|
2368
|
-
}
|
|
2369
|
-
if (globalAlpha === 255) {
|
|
2370
|
-
weight = effectiveM;
|
|
2371
|
-
} else if (effectiveM === 255) {
|
|
2372
|
-
weight = globalAlpha;
|
|
2373
|
-
} else {
|
|
2374
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2375
|
-
}
|
|
2376
|
-
} else {
|
|
2377
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2378
|
-
if (!isHit) {
|
|
2379
|
-
dIdx++;
|
|
2380
|
-
mIdx++;
|
|
2381
|
-
continue;
|
|
2382
|
-
}
|
|
2383
|
-
weight = globalAlpha;
|
|
2384
|
-
}
|
|
2385
|
-
if (weight === 0) {
|
|
2386
|
-
dIdx++;
|
|
2387
|
-
mIdx++;
|
|
2388
|
-
continue;
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
let currentSrcColor = color;
|
|
2392
|
-
if (weight < 255) {
|
|
2393
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2394
|
-
if (baseSrcAlpha === 255) {
|
|
2395
|
-
currentSrcAlpha = weight;
|
|
2396
|
-
} else {
|
|
2397
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2398
|
-
}
|
|
2399
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2400
|
-
dIdx++;
|
|
2401
|
-
mIdx++;
|
|
2402
|
-
continue;
|
|
2403
|
-
}
|
|
2404
|
-
currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
2405
|
-
}
|
|
2406
|
-
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
3095
|
+
dst32[dIdx] = blendFn(finalSrcColor, dst32[dIdx]);
|
|
2407
3096
|
dIdx++;
|
|
2408
|
-
mIdx++;
|
|
2409
3097
|
}
|
|
2410
3098
|
dIdx += dStride;
|
|
2411
|
-
mIdx += mStride;
|
|
2412
3099
|
}
|
|
2413
3100
|
}
|
|
2414
3101
|
|
|
2415
3102
|
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2416
|
-
|
|
3103
|
+
var defaults10 = {
|
|
3104
|
+
blendColorPixelData
|
|
3105
|
+
};
|
|
3106
|
+
var mutatorBlendColor = ((writer, deps = defaults10) => {
|
|
3107
|
+
const {
|
|
3108
|
+
blendColorPixelData: blendColorPixelData2 = defaults10.blendColorPixelData
|
|
3109
|
+
} = deps;
|
|
2417
3110
|
return {
|
|
2418
3111
|
blendColor(color, opts = {}) {
|
|
2419
3112
|
const {
|
|
@@ -2423,10 +3116,10 @@ function mutatorBlendColor(writer) {
|
|
|
2423
3116
|
h = writer.target.height
|
|
2424
3117
|
} = opts;
|
|
2425
3118
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2426
|
-
|
|
3119
|
+
blendColorPixelData2(writer.target, color, opts);
|
|
2427
3120
|
}
|
|
2428
3121
|
};
|
|
2429
|
-
}
|
|
3122
|
+
});
|
|
2430
3123
|
|
|
2431
3124
|
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2432
3125
|
function mutatorBlendPixel(writer) {
|
|
@@ -2460,13 +3153,7 @@ function blendPixelData(dst, src, opts) {
|
|
|
2460
3153
|
w: width = src.width,
|
|
2461
3154
|
h: height = src.height,
|
|
2462
3155
|
alpha: globalAlpha = 255,
|
|
2463
|
-
blendFn =
|
|
2464
|
-
mask,
|
|
2465
|
-
maskType = 0 /* ALPHA */,
|
|
2466
|
-
mw,
|
|
2467
|
-
mx = 0,
|
|
2468
|
-
my = 0,
|
|
2469
|
-
invertMask = false
|
|
3156
|
+
blendFn = sourceOverPerfect
|
|
2470
3157
|
} = opts;
|
|
2471
3158
|
if (globalAlpha === 0) return;
|
|
2472
3159
|
let x = targetX;
|
|
@@ -2504,91 +3191,48 @@ function blendPixelData(dst, src, opts) {
|
|
|
2504
3191
|
const src32 = src.data32;
|
|
2505
3192
|
const dw = dst.width;
|
|
2506
3193
|
const sw = src.width;
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
const
|
|
2510
|
-
const
|
|
2511
|
-
|
|
2512
|
-
let sIdx = sy * sw + sx;
|
|
2513
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2514
|
-
const dStride = dw - actualW;
|
|
2515
|
-
const sStride = sw - actualW;
|
|
2516
|
-
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;
|
|
2517
3199
|
const isOverwrite = blendFn.isOverwrite;
|
|
2518
3200
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2519
3201
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2520
|
-
const
|
|
2521
|
-
const
|
|
2522
|
-
if (
|
|
3202
|
+
const srcCol = src32[sIdx];
|
|
3203
|
+
const srcAlpha = srcCol >>> 24;
|
|
3204
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2523
3205
|
dIdx++;
|
|
2524
3206
|
sIdx++;
|
|
2525
|
-
mIdx++;
|
|
2526
3207
|
continue;
|
|
2527
3208
|
}
|
|
2528
|
-
let
|
|
2529
|
-
if (
|
|
2530
|
-
const
|
|
2531
|
-
if (
|
|
2532
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2533
|
-
if (effectiveM === 0) {
|
|
2534
|
-
dIdx++;
|
|
2535
|
-
sIdx++;
|
|
2536
|
-
mIdx++;
|
|
2537
|
-
continue;
|
|
2538
|
-
}
|
|
2539
|
-
if (globalAlpha === 255) {
|
|
2540
|
-
weight = effectiveM;
|
|
2541
|
-
} else if (effectiveM === 255) {
|
|
2542
|
-
weight = globalAlpha;
|
|
2543
|
-
} else {
|
|
2544
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2545
|
-
}
|
|
2546
|
-
} else {
|
|
2547
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2548
|
-
if (!isHit) {
|
|
2549
|
-
dIdx++;
|
|
2550
|
-
sIdx++;
|
|
2551
|
-
mIdx++;
|
|
2552
|
-
continue;
|
|
2553
|
-
}
|
|
2554
|
-
weight = globalAlpha;
|
|
2555
|
-
}
|
|
2556
|
-
if (weight === 0) {
|
|
2557
|
-
dIdx++;
|
|
2558
|
-
sIdx++;
|
|
2559
|
-
mIdx++;
|
|
2560
|
-
continue;
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
let currentSrcColor = baseSrcColor;
|
|
2564
|
-
if (weight < 255) {
|
|
2565
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2566
|
-
if (baseSrcAlpha === 255) {
|
|
2567
|
-
currentSrcAlpha = weight;
|
|
2568
|
-
} else {
|
|
2569
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2570
|
-
}
|
|
2571
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
3209
|
+
let finalCol = srcCol;
|
|
3210
|
+
if (!isOpaque) {
|
|
3211
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
3212
|
+
if (a === 0 && !isOverwrite) {
|
|
2572
3213
|
dIdx++;
|
|
2573
3214
|
sIdx++;
|
|
2574
|
-
mIdx++;
|
|
2575
3215
|
continue;
|
|
2576
3216
|
}
|
|
2577
|
-
|
|
3217
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2578
3218
|
}
|
|
2579
|
-
dst32[dIdx] = blendFn(
|
|
3219
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
2580
3220
|
dIdx++;
|
|
2581
3221
|
sIdx++;
|
|
2582
|
-
mIdx++;
|
|
2583
3222
|
}
|
|
2584
3223
|
dIdx += dStride;
|
|
2585
3224
|
sIdx += sStride;
|
|
2586
|
-
mIdx += mStride;
|
|
2587
3225
|
}
|
|
2588
3226
|
}
|
|
2589
3227
|
|
|
2590
3228
|
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
2591
|
-
|
|
3229
|
+
var defaults11 = {
|
|
3230
|
+
blendPixelData
|
|
3231
|
+
};
|
|
3232
|
+
var mutatorBlendPixelData = ((writer, deps = defaults11) => {
|
|
3233
|
+
const {
|
|
3234
|
+
blendPixelData: blendPixelData2 = defaults11.blendPixelData
|
|
3235
|
+
} = deps;
|
|
2592
3236
|
return {
|
|
2593
3237
|
blendPixelData(src, opts) {
|
|
2594
3238
|
const {
|
|
@@ -2598,12 +3242,13 @@ function mutatorBlendPixelData(writer) {
|
|
|
2598
3242
|
h = src.height
|
|
2599
3243
|
} = opts;
|
|
2600
3244
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2601
|
-
|
|
3245
|
+
blendPixelData2(writer.target, src, opts);
|
|
2602
3246
|
}
|
|
2603
3247
|
};
|
|
2604
|
-
}
|
|
3248
|
+
});
|
|
2605
3249
|
|
|
2606
3250
|
// src/PixelData/fillPixelData.ts
|
|
3251
|
+
var SCRATCH_RECT = makeClippedRect();
|
|
2607
3252
|
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
2608
3253
|
let x;
|
|
2609
3254
|
let y;
|
|
@@ -2625,34 +3270,57 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
|
2625
3270
|
w = dst.width;
|
|
2626
3271
|
h = dst.height;
|
|
2627
3272
|
}
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
}
|
|
2636
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2637
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2638
|
-
if (actualW <= 0 || actualH <= 0) {
|
|
2639
|
-
return;
|
|
2640
|
-
}
|
|
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;
|
|
2641
3281
|
const dst32 = dst.data32;
|
|
2642
3282
|
const dw = dst.width;
|
|
2643
|
-
if (actualW === dw && actualH === dst.height &&
|
|
3283
|
+
if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
|
|
2644
3284
|
dst32.fill(color);
|
|
2645
3285
|
return;
|
|
2646
3286
|
}
|
|
2647
3287
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2648
|
-
const start = (
|
|
3288
|
+
const start = (finalY + iy) * dw + finalX;
|
|
2649
3289
|
const end = start + actualW;
|
|
2650
3290
|
dst32.fill(color, start, end);
|
|
2651
3291
|
}
|
|
2652
3292
|
}
|
|
2653
3293
|
|
|
2654
|
-
// src/History/PixelMutator/
|
|
2655
|
-
|
|
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;
|
|
2656
3324
|
return {
|
|
2657
3325
|
fill(color, rect = {}) {
|
|
2658
3326
|
const {
|
|
@@ -2662,12 +3330,13 @@ function mutatorFill(writer) {
|
|
|
2662
3330
|
h = writer.target.height
|
|
2663
3331
|
} = rect;
|
|
2664
3332
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2665
|
-
|
|
3333
|
+
fillPixelData2(writer.target, color, x, y, w, h);
|
|
2666
3334
|
}
|
|
2667
3335
|
};
|
|
2668
|
-
}
|
|
3336
|
+
});
|
|
2669
3337
|
|
|
2670
3338
|
// src/PixelData/invertPixelData.ts
|
|
3339
|
+
var SCRATCH_RECT2 = makeClippedRect();
|
|
2671
3340
|
function invertPixelData(pixelData, opts = {}) {
|
|
2672
3341
|
const dst = pixelData;
|
|
2673
3342
|
const {
|
|
@@ -2681,21 +3350,14 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
2681
3350
|
my = 0,
|
|
2682
3351
|
invertMask = false
|
|
2683
3352
|
} = opts;
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
w
|
|
2690
|
-
|
|
2691
|
-
}
|
|
2692
|
-
if (y < 0) {
|
|
2693
|
-
h += y;
|
|
2694
|
-
y = 0;
|
|
2695
|
-
}
|
|
2696
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2697
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2698
|
-
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;
|
|
2699
3361
|
const dst32 = dst.data32;
|
|
2700
3362
|
const dw = dst.width;
|
|
2701
3363
|
const mPitch = mw ?? width;
|
|
@@ -2731,54 +3393,137 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
2731
3393
|
}
|
|
2732
3394
|
|
|
2733
3395
|
// src/History/PixelMutator/mutatorInvert.ts
|
|
2734
|
-
|
|
3396
|
+
var defaults14 = {
|
|
3397
|
+
invertPixelData
|
|
3398
|
+
};
|
|
3399
|
+
var mutatorInvert = ((writer, deps = defaults14) => {
|
|
3400
|
+
const {
|
|
3401
|
+
invertPixelData: invertPixelData2 = defaults14.invertPixelData
|
|
3402
|
+
} = deps;
|
|
3403
|
+
return {
|
|
3404
|
+
invert(opts = {}) {
|
|
3405
|
+
const {
|
|
3406
|
+
x = 0,
|
|
3407
|
+
y = 0,
|
|
3408
|
+
w = writer.target.width,
|
|
3409
|
+
h = writer.target.height
|
|
3410
|
+
} = opts;
|
|
3411
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3412
|
+
invertPixelData2(writer.target, opts);
|
|
3413
|
+
}
|
|
3414
|
+
};
|
|
3415
|
+
});
|
|
3416
|
+
|
|
3417
|
+
// src/History/PixelMutator.ts
|
|
3418
|
+
function makeFullPixelMutator(writer) {
|
|
3419
|
+
return {
|
|
3420
|
+
...mutatorApplyAlphaMask(writer),
|
|
3421
|
+
...mutatorApplyBinaryMask(writer),
|
|
3422
|
+
...mutatorBlendPixelData(writer),
|
|
3423
|
+
...mutatorBlendColor(writer),
|
|
3424
|
+
...mutatorBlendPixel(writer),
|
|
3425
|
+
...mutatorFill(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)
|
|
3435
|
+
};
|
|
3436
|
+
}
|
|
3437
|
+
|
|
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
|
+
};
|
|
2735
3499
|
return {
|
|
2736
|
-
|
|
3500
|
+
applyCirclePencil(color, centerX, centerY, brushSize, alpha = 255, blendFn) {
|
|
3501
|
+
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
|
|
2737
3502
|
const {
|
|
2738
|
-
x
|
|
2739
|
-
y
|
|
2740
|
-
w
|
|
2741
|
-
h
|
|
2742
|
-
} =
|
|
3503
|
+
x,
|
|
3504
|
+
y,
|
|
3505
|
+
w,
|
|
3506
|
+
h
|
|
3507
|
+
} = bounds;
|
|
2743
3508
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2744
|
-
|
|
2745
|
-
}
|
|
2746
|
-
};
|
|
2747
|
-
}
|
|
2748
|
-
|
|
2749
|
-
// src/History/PixelMutator.ts
|
|
2750
|
-
function makeFullPixelMutator(writer) {
|
|
2751
|
-
return {
|
|
2752
|
-
...mutatorApplyMask(writer),
|
|
2753
|
-
...mutatorBlendPixelData(writer),
|
|
2754
|
-
...mutatorBlendColor(writer),
|
|
2755
|
-
...mutatorBlendPixel(writer),
|
|
2756
|
-
...mutatorFill(writer),
|
|
2757
|
-
...mutatorInvert(writer),
|
|
2758
|
-
...mutatorApplyCircleBrush(writer),
|
|
2759
|
-
...mutatorApplyRectBrush(writer)
|
|
2760
|
-
};
|
|
2761
|
-
}
|
|
2762
|
-
|
|
2763
|
-
// src/ImageData/ReusableImageData.ts
|
|
2764
|
-
function makeReusableImageData() {
|
|
2765
|
-
let imageData = null;
|
|
2766
|
-
return function getReusableImageData(width, height) {
|
|
2767
|
-
const hasInstance = !!imageData;
|
|
2768
|
-
const widthMatches = hasInstance && imageData.width === width;
|
|
2769
|
-
const heightMatches = hasInstance && imageData.height === height;
|
|
2770
|
-
if (!widthMatches || !heightMatches) {
|
|
2771
|
-
imageData = new ImageData(width, height);
|
|
3509
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
|
|
2772
3510
|
}
|
|
2773
|
-
return imageData;
|
|
2774
3511
|
};
|
|
2775
|
-
}
|
|
3512
|
+
});
|
|
2776
3513
|
|
|
2777
3514
|
// src/ImageData/copyImageData.ts
|
|
2778
|
-
function copyImageData({
|
|
3515
|
+
function copyImageData({
|
|
3516
|
+
data,
|
|
3517
|
+
width,
|
|
3518
|
+
height
|
|
3519
|
+
}) {
|
|
2779
3520
|
return new ImageData(data.slice(), width, height);
|
|
2780
3521
|
}
|
|
2781
|
-
function copyImageDataLike({
|
|
3522
|
+
function copyImageDataLike({
|
|
3523
|
+
data,
|
|
3524
|
+
width,
|
|
3525
|
+
height
|
|
3526
|
+
}) {
|
|
2782
3527
|
return {
|
|
2783
3528
|
data: data.slice(),
|
|
2784
3529
|
width,
|
|
@@ -2786,20 +3531,15 @@ function copyImageDataLike({ data, width, height }) {
|
|
|
2786
3531
|
};
|
|
2787
3532
|
}
|
|
2788
3533
|
|
|
2789
|
-
// src/
|
|
2790
|
-
function
|
|
2791
|
-
const
|
|
2792
|
-
|
|
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 {
|
|
2793
3539
|
width,
|
|
2794
|
-
height
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
const mask = new Uint8Array(width * height);
|
|
2798
|
-
for (let i = 0; i < len; i++) {
|
|
2799
|
-
const val = data32[i];
|
|
2800
|
-
mask[i] = val >>> 24 & 255;
|
|
2801
|
-
}
|
|
2802
|
-
return mask;
|
|
3540
|
+
height,
|
|
3541
|
+
data: buffer
|
|
3542
|
+
};
|
|
2803
3543
|
}
|
|
2804
3544
|
|
|
2805
3545
|
// src/ImageData/imageDataToAlphaMask.ts
|
|
@@ -2809,11 +3549,7 @@ function imageDataToAlphaMask(imageData) {
|
|
|
2809
3549
|
height,
|
|
2810
3550
|
data
|
|
2811
3551
|
} = imageData;
|
|
2812
|
-
const data32 = new Uint32Array(
|
|
2813
|
-
data.buffer,
|
|
2814
|
-
data.byteOffset,
|
|
2815
|
-
data.byteLength >> 2
|
|
2816
|
-
);
|
|
3552
|
+
const data32 = new Uint32Array(data.buffer, data.byteOffset, data.byteLength >> 2);
|
|
2817
3553
|
const len = data32.length;
|
|
2818
3554
|
const mask = new Uint8Array(width * height);
|
|
2819
3555
|
for (let i = 0; i < len; i++) {
|
|
@@ -2826,12 +3562,25 @@ function imageDataToAlphaMask(imageData) {
|
|
|
2826
3562
|
// src/ImageData/imageDataToDataUrl.ts
|
|
2827
3563
|
var get = makeReusableCanvas();
|
|
2828
3564
|
function imageDataToDataUrl(imageData) {
|
|
2829
|
-
const {
|
|
3565
|
+
const {
|
|
3566
|
+
canvas,
|
|
3567
|
+
ctx
|
|
3568
|
+
} = get(imageData.width, imageData.height);
|
|
2830
3569
|
ctx.putImageData(imageData, 0, 0);
|
|
2831
3570
|
return canvas.toDataURL();
|
|
2832
3571
|
}
|
|
2833
3572
|
imageDataToDataUrl.reset = get.reset;
|
|
2834
3573
|
|
|
3574
|
+
// src/ImageData/imageDataToUInt32Array.ts
|
|
3575
|
+
function imageDataToUInt32Array(imageData) {
|
|
3576
|
+
return new Uint32Array(
|
|
3577
|
+
imageData.data.buffer,
|
|
3578
|
+
imageData.data.byteOffset,
|
|
3579
|
+
// Shift right by 2 is a fast bitwise division by 4.
|
|
3580
|
+
imageData.data.byteLength >> 2
|
|
3581
|
+
);
|
|
3582
|
+
}
|
|
3583
|
+
|
|
2835
3584
|
// src/ImageData/invertImageData.ts
|
|
2836
3585
|
function invertImageData(imageData) {
|
|
2837
3586
|
const data = imageData.data;
|
|
@@ -2874,7 +3623,11 @@ function resample32(srcData32, srcW, srcH, factor) {
|
|
|
2874
3623
|
// src/ImageData/resampleImageData.ts
|
|
2875
3624
|
function resampleImageData(source, factor) {
|
|
2876
3625
|
const src32 = new Uint32Array(source.data.buffer);
|
|
2877
|
-
const {
|
|
3626
|
+
const {
|
|
3627
|
+
data,
|
|
3628
|
+
width,
|
|
3629
|
+
height
|
|
3630
|
+
} = resample32(src32, source.width, source.height, factor);
|
|
2878
3631
|
const uint8ClampedArray = new Uint8ClampedArray(data.buffer);
|
|
2879
3632
|
return new ImageData(uint8ClampedArray, width, height);
|
|
2880
3633
|
}
|
|
@@ -2903,14 +3656,25 @@ function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0)
|
|
|
2903
3656
|
const srcX = x0 - offsetX;
|
|
2904
3657
|
const dstStart = (dstY * newWidth + x0) * 4;
|
|
2905
3658
|
const srcStart = (srcY * oldW + srcX) * 4;
|
|
2906
|
-
newData.set(
|
|
2907
|
-
oldData.subarray(srcStart, srcStart + rowLen),
|
|
2908
|
-
dstStart
|
|
2909
|
-
);
|
|
3659
|
+
newData.set(oldData.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
2910
3660
|
}
|
|
2911
3661
|
return result;
|
|
2912
3662
|
}
|
|
2913
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
|
+
|
|
2914
3678
|
// src/ImageData/serialization.ts
|
|
2915
3679
|
function base64EncodeArrayBuffer(buffer) {
|
|
2916
3680
|
const uint8 = new Uint8Array(buffer);
|
|
@@ -2953,32 +3717,53 @@ function deserializeNullableImageData(serialized) {
|
|
|
2953
3717
|
return deserializeImageData(serialized);
|
|
2954
3718
|
}
|
|
2955
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
|
+
|
|
2956
3740
|
// src/ImageData/writeImageData.ts
|
|
3741
|
+
var SCRATCH_BLIT2 = makeClippedBlit();
|
|
2957
3742
|
function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
|
|
2958
3743
|
const dstW = target.width;
|
|
2959
3744
|
const dstH = target.height;
|
|
2960
3745
|
const dstData = target.data;
|
|
2961
3746
|
const srcW = source.width;
|
|
2962
3747
|
const srcData = source.data;
|
|
2963
|
-
const
|
|
2964
|
-
|
|
2965
|
-
const
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
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;
|
|
2970
3758
|
const useMask = !!mask;
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
const
|
|
2975
|
-
const
|
|
2976
|
-
const srcXBase = sx + (x0 - x);
|
|
2977
|
-
const dstStart = (dstY * dstW + x0) * 4;
|
|
2978
|
-
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;
|
|
2979
3764
|
if (useMask && mask) {
|
|
2980
|
-
for (let ix = 0; ix <
|
|
2981
|
-
const mi =
|
|
3765
|
+
for (let ix = 0; ix < copyW; ix++) {
|
|
3766
|
+
const mi = currentSrcY * srcW + (srcX + ix);
|
|
2982
3767
|
const alpha = mask[mi];
|
|
2983
3768
|
if (alpha === 0) {
|
|
2984
3769
|
continue;
|
|
@@ -3000,7 +3785,7 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
|
|
|
3000
3785
|
}
|
|
3001
3786
|
}
|
|
3002
3787
|
} else {
|
|
3003
|
-
const byteLen =
|
|
3788
|
+
const byteLen = copyW * 4;
|
|
3004
3789
|
const sub = srcData.subarray(srcStart, srcStart + byteLen);
|
|
3005
3790
|
dstData.set(sub, dstStart);
|
|
3006
3791
|
}
|
|
@@ -3008,24 +3793,52 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
|
|
|
3008
3793
|
}
|
|
3009
3794
|
|
|
3010
3795
|
// src/ImageData/writeImageDataBuffer.ts
|
|
3796
|
+
var SCRATCH_BLIT3 = makeClippedBlit();
|
|
3011
3797
|
function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
|
|
3012
|
-
const {
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
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]++;
|
|
3028
3840
|
}
|
|
3841
|
+
return frequencies;
|
|
3029
3842
|
}
|
|
3030
3843
|
|
|
3031
3844
|
// src/IndexedImage/IndexedImage.ts
|
|
@@ -3091,13 +3904,7 @@ var IndexedImage = class _IndexedImage {
|
|
|
3091
3904
|
indexedData[i] = id;
|
|
3092
3905
|
}
|
|
3093
3906
|
const palette = Uint32Array.from(colorMap.keys());
|
|
3094
|
-
return new _IndexedImage(
|
|
3095
|
-
width,
|
|
3096
|
-
height,
|
|
3097
|
-
indexedData,
|
|
3098
|
-
palette,
|
|
3099
|
-
transparentPalletIndex
|
|
3100
|
-
);
|
|
3907
|
+
return new _IndexedImage(width, height, indexedData, palette, transparentPalletIndex);
|
|
3101
3908
|
}
|
|
3102
3909
|
/**
|
|
3103
3910
|
* Retrieves the 32-bit packed color value at the given coordinates.
|
|
@@ -3112,21 +3919,13 @@ var IndexedImage = class _IndexedImage {
|
|
|
3112
3919
|
}
|
|
3113
3920
|
};
|
|
3114
3921
|
|
|
3115
|
-
// src/IndexedImage/getIndexedImageColorCounts.ts
|
|
3116
|
-
function getIndexedImageColorCounts(indexedImage) {
|
|
3117
|
-
const data = indexedImage.data;
|
|
3118
|
-
const palette = indexedImage.palette;
|
|
3119
|
-
const frequencies = new Int32Array(palette.length);
|
|
3120
|
-
for (let i = 0; i < data.length; i++) {
|
|
3121
|
-
const colorIndex = data[i];
|
|
3122
|
-
frequencies[colorIndex]++;
|
|
3123
|
-
}
|
|
3124
|
-
return frequencies;
|
|
3125
|
-
}
|
|
3126
|
-
|
|
3127
3922
|
// src/IndexedImage/indexedImageToAverageColor.ts
|
|
3128
3923
|
function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
|
|
3129
|
-
const {
|
|
3924
|
+
const {
|
|
3925
|
+
data,
|
|
3926
|
+
palette,
|
|
3927
|
+
transparentPalletIndex
|
|
3928
|
+
} = indexedImage;
|
|
3130
3929
|
const counts = new Uint32Array(palette.length);
|
|
3131
3930
|
for (let i = 0; i < data.length; i++) {
|
|
3132
3931
|
const id = data[i];
|
|
@@ -3166,26 +3965,14 @@ function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
|
|
|
3166
3965
|
return packColor(r, g, b, a);
|
|
3167
3966
|
}
|
|
3168
3967
|
|
|
3169
|
-
// src/IndexedImage/
|
|
3170
|
-
function
|
|
3171
|
-
const {
|
|
3172
|
-
source.data,
|
|
3173
|
-
source.width,
|
|
3174
|
-
source.height,
|
|
3175
|
-
factor
|
|
3176
|
-
);
|
|
3177
|
-
return new IndexedImage(
|
|
3968
|
+
// src/IndexedImage/indexedImageToImageData.ts
|
|
3969
|
+
function indexedImageToImageData(indexedImage) {
|
|
3970
|
+
const {
|
|
3178
3971
|
width,
|
|
3179
3972
|
height,
|
|
3180
3973
|
data,
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
);
|
|
3184
|
-
}
|
|
3185
|
-
|
|
3186
|
-
// src/IndexedImage/indexedImageToImageData.ts
|
|
3187
|
-
function indexedImageToImageData(indexedImage) {
|
|
3188
|
-
const { width, height, data, palette } = indexedImage;
|
|
3974
|
+
palette
|
|
3975
|
+
} = indexedImage;
|
|
3189
3976
|
const result = new ImageData(width, height);
|
|
3190
3977
|
const data32 = new Uint32Array(result.data.buffer);
|
|
3191
3978
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -3196,6 +3983,16 @@ function indexedImageToImageData(indexedImage) {
|
|
|
3196
3983
|
return result;
|
|
3197
3984
|
}
|
|
3198
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
|
+
|
|
3199
3996
|
// src/Input/fileInputChangeToImageData.ts
|
|
3200
3997
|
async function fileInputChangeToImageData(event) {
|
|
3201
3998
|
const target = event.target;
|
|
@@ -3219,23 +4016,11 @@ async function fileToImageData(file) {
|
|
|
3219
4016
|
let bitmap = null;
|
|
3220
4017
|
try {
|
|
3221
4018
|
bitmap = await createImageBitmap(file);
|
|
3222
|
-
const canvas = new OffscreenCanvas(
|
|
3223
|
-
bitmap.width,
|
|
3224
|
-
bitmap.height
|
|
3225
|
-
);
|
|
4019
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
3226
4020
|
const ctx = canvas.getContext("2d");
|
|
3227
4021
|
if (!ctx) throw new Error(OFFSCREEN_CANVAS_CTX_FAILED);
|
|
3228
|
-
ctx.drawImage(
|
|
3229
|
-
|
|
3230
|
-
0,
|
|
3231
|
-
0
|
|
3232
|
-
);
|
|
3233
|
-
return ctx.getImageData(
|
|
3234
|
-
0,
|
|
3235
|
-
0,
|
|
3236
|
-
bitmap.width,
|
|
3237
|
-
bitmap.height
|
|
3238
|
-
);
|
|
4022
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
4023
|
+
return ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
3239
4024
|
} finally {
|
|
3240
4025
|
bitmap?.close();
|
|
3241
4026
|
}
|
|
@@ -3243,125 +4028,495 @@ async function fileToImageData(file) {
|
|
|
3243
4028
|
|
|
3244
4029
|
// src/Input/getSupportedRasterFormats.ts
|
|
3245
4030
|
var formatsPromise = null;
|
|
3246
|
-
var defaultRasterMimes = [
|
|
3247
|
-
"image/png",
|
|
3248
|
-
"image/jpeg",
|
|
3249
|
-
"image/webp",
|
|
3250
|
-
"image/avif",
|
|
3251
|
-
"image/gif",
|
|
3252
|
-
"image/bmp"
|
|
3253
|
-
];
|
|
4031
|
+
var defaultRasterMimes = ["image/png", "image/jpeg", "image/webp", "image/avif", "image/gif", "image/bmp"];
|
|
3254
4032
|
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
3255
4033
|
if (formatsPromise) {
|
|
3256
4034
|
return formatsPromise;
|
|
3257
4035
|
}
|
|
3258
|
-
const probeCanvas = async () => {
|
|
3259
|
-
const canvas = new OffscreenCanvas(1, 1);
|
|
3260
|
-
const results = await Promise.all(
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
4036
|
+
const probeCanvas = async () => {
|
|
4037
|
+
const canvas = new OffscreenCanvas(1, 1);
|
|
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
|
+
}));
|
|
4048
|
+
return results.filter((type) => {
|
|
4049
|
+
return type !== null;
|
|
4050
|
+
});
|
|
4051
|
+
};
|
|
4052
|
+
formatsPromise = probeCanvas().catch((error) => {
|
|
4053
|
+
formatsPromise = null;
|
|
4054
|
+
throw error;
|
|
4055
|
+
});
|
|
4056
|
+
return formatsPromise;
|
|
4057
|
+
}
|
|
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
|
+
|
|
4126
|
+
// src/Mask/copyMask.ts
|
|
4127
|
+
function copyMask(src) {
|
|
4128
|
+
return src.slice();
|
|
4129
|
+
}
|
|
4130
|
+
|
|
4131
|
+
// src/Mask/invertMask.ts
|
|
4132
|
+
function invertBinaryMask(dst) {
|
|
4133
|
+
const len = dst.length;
|
|
4134
|
+
for (let i = 0; i < len; i++) {
|
|
4135
|
+
dst[i] = dst[i] === 0 ? 1 : 0;
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4138
|
+
function invertAlphaMask(dst) {
|
|
4139
|
+
const len = dst.length;
|
|
4140
|
+
for (let i = 0; i < len; i++) {
|
|
4141
|
+
dst[i] = 255 - dst[i];
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
// src/Mask/mergeAlphaMasks.ts
|
|
4146
|
+
function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
4147
|
+
const {
|
|
4148
|
+
x: targetX = 0,
|
|
4149
|
+
y: targetY = 0,
|
|
4150
|
+
w: width = 0,
|
|
4151
|
+
h: height = 0,
|
|
4152
|
+
alpha: globalAlpha = 255,
|
|
4153
|
+
mx = 0,
|
|
4154
|
+
my = 0,
|
|
4155
|
+
invertMask = false
|
|
4156
|
+
} = opts;
|
|
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;
|
|
4230
|
+
}
|
|
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++) {
|
|
4253
|
+
const mVal = src[sIdx];
|
|
4254
|
+
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
4255
|
+
if (isMaskedOut) {
|
|
4256
|
+
dst[dIdx] = 0;
|
|
4257
|
+
}
|
|
4258
|
+
dIdx++;
|
|
4259
|
+
sIdx++;
|
|
4260
|
+
}
|
|
4261
|
+
dIdx += dStride;
|
|
4262
|
+
sIdx += sStride;
|
|
4263
|
+
}
|
|
3286
4264
|
}
|
|
3287
4265
|
|
|
3288
|
-
// src/
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
4266
|
+
// src/PixelData/PixelData.ts
|
|
4267
|
+
var PixelData = class _PixelData {
|
|
4268
|
+
data32;
|
|
4269
|
+
imageData;
|
|
4270
|
+
width;
|
|
4271
|
+
height;
|
|
4272
|
+
constructor(imageData) {
|
|
4273
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
4274
|
+
this.imageData = imageData;
|
|
4275
|
+
this.width = imageData.width;
|
|
4276
|
+
this.height = imageData.height;
|
|
3293
4277
|
}
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
4278
|
+
set(imageData) {
|
|
4279
|
+
;
|
|
4280
|
+
this.imageData = imageData;
|
|
4281
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
4282
|
+
this.width = imageData.width;
|
|
4283
|
+
this.height = imageData.height;
|
|
3299
4284
|
}
|
|
3300
|
-
|
|
4285
|
+
// should only be used for debug and testing
|
|
4286
|
+
copy() {
|
|
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
|
+
}
|
|
4302
|
+
return new _PixelData(newImageData);
|
|
4303
|
+
}
|
|
4304
|
+
};
|
|
3301
4305
|
|
|
3302
|
-
// src/
|
|
3303
|
-
function
|
|
4306
|
+
// src/PixelData/blendPixelDataAlphaMask.ts
|
|
4307
|
+
function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
3304
4308
|
const {
|
|
3305
4309
|
x: targetX = 0,
|
|
3306
4310
|
y: targetY = 0,
|
|
3307
|
-
|
|
3308
|
-
|
|
4311
|
+
sx: sourceX = 0,
|
|
4312
|
+
sy: sourceY = 0,
|
|
4313
|
+
w: width = src.width,
|
|
4314
|
+
h: height = src.height,
|
|
3309
4315
|
alpha: globalAlpha = 255,
|
|
3310
|
-
|
|
3311
|
-
mw,
|
|
4316
|
+
blendFn = sourceOverPerfect,
|
|
4317
|
+
mw = src.width,
|
|
3312
4318
|
mx = 0,
|
|
3313
4319
|
my = 0,
|
|
3314
4320
|
invertMask = false
|
|
3315
4321
|
} = opts;
|
|
3316
|
-
if (
|
|
3317
|
-
|
|
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;
|
|
3318
4333
|
}
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
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++;
|
|
3331
4385
|
continue;
|
|
3332
4386
|
}
|
|
3333
|
-
const dIdx = dy * dstWidth + dx;
|
|
3334
|
-
const sIdx = sy * sPitch + sx;
|
|
3335
|
-
const mVal = src[sIdx];
|
|
3336
4387
|
let weight = globalAlpha;
|
|
3337
|
-
if (
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
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++;
|
|
3348
4406
|
continue;
|
|
3349
4407
|
}
|
|
3350
|
-
|
|
4408
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3351
4409
|
}
|
|
3352
|
-
|
|
3353
|
-
|
|
4410
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
4411
|
+
dIdx++;
|
|
4412
|
+
sIdx++;
|
|
4413
|
+
mIdx++;
|
|
4414
|
+
}
|
|
4415
|
+
dIdx += dStride;
|
|
4416
|
+
sIdx += sStride;
|
|
4417
|
+
mIdx += mStride;
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
|
|
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++;
|
|
3354
4491
|
continue;
|
|
3355
4492
|
}
|
|
3356
|
-
const
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
4493
|
+
const srcCol = src32[sIdx];
|
|
4494
|
+
const srcAlpha = srcCol >>> 24;
|
|
4495
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
4496
|
+
dIdx++;
|
|
4497
|
+
sIdx++;
|
|
4498
|
+
mIdx++;
|
|
4499
|
+
continue;
|
|
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;
|
|
3363
4511
|
}
|
|
4512
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
4513
|
+
dIdx++;
|
|
4514
|
+
sIdx++;
|
|
4515
|
+
mIdx++;
|
|
3364
4516
|
}
|
|
4517
|
+
dIdx += dStride;
|
|
4518
|
+
sIdx += sStride;
|
|
4519
|
+
mIdx += mStride;
|
|
3365
4520
|
}
|
|
3366
4521
|
}
|
|
3367
4522
|
|
|
@@ -3371,32 +4526,40 @@ function clearPixelData(dst, rect) {
|
|
|
3371
4526
|
}
|
|
3372
4527
|
|
|
3373
4528
|
// src/PixelData/extractPixelDataBuffer.ts
|
|
4529
|
+
var SCRATCH_BLIT4 = makeClippedBlit();
|
|
3374
4530
|
function extractPixelDataBuffer(source, _x, _y, _w, _h) {
|
|
3375
|
-
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
|
+
};
|
|
3376
4542
|
const srcW = source.width;
|
|
3377
4543
|
const srcH = source.height;
|
|
3378
4544
|
const srcData = source.data32;
|
|
3379
4545
|
if (w <= 0 || h <= 0) {
|
|
3380
4546
|
return new Uint32Array(0);
|
|
3381
4547
|
}
|
|
3382
|
-
const
|
|
3383
|
-
const
|
|
3384
|
-
|
|
3385
|
-
const
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
for (let row = 0; row <
|
|
3394
|
-
const
|
|
3395
|
-
const
|
|
3396
|
-
const
|
|
3397
|
-
const dstCol = x0 - x;
|
|
3398
|
-
const dstStart = dstRow * w + dstCol;
|
|
3399
|
-
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);
|
|
3400
4563
|
dstData.set(chunk, dstStart);
|
|
3401
4564
|
}
|
|
3402
4565
|
return dstData;
|
|
@@ -3404,13 +4567,59 @@ function extractPixelDataBuffer(source, _x, _y, _w, _h) {
|
|
|
3404
4567
|
|
|
3405
4568
|
// src/PixelData/extractPixelData.ts
|
|
3406
4569
|
function extractPixelData(source, _x, _y, _w, _h) {
|
|
3407
|
-
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
|
+
};
|
|
3408
4581
|
const result = new PixelData(new ImageData(w, h));
|
|
3409
4582
|
const buffer = extractPixelDataBuffer(source, x, y, w, h);
|
|
3410
4583
|
result.data32.set(buffer);
|
|
3411
4584
|
return result;
|
|
3412
4585
|
}
|
|
3413
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
|
+
|
|
3414
4623
|
// src/PixelData/reflectPixelData.ts
|
|
3415
4624
|
function reflectPixelDataHorizontal(pixelData) {
|
|
3416
4625
|
const width = pixelData.width;
|
|
@@ -3448,12 +4657,12 @@ function reflectPixelDataVertical(pixelData) {
|
|
|
3448
4657
|
|
|
3449
4658
|
// src/PixelData/resamplePixelData.ts
|
|
3450
4659
|
function resamplePixelData(pixelData, factor) {
|
|
3451
|
-
const {
|
|
3452
|
-
|
|
3453
|
-
new Uint8ClampedArray(data.buffer),
|
|
4660
|
+
const {
|
|
4661
|
+
data,
|
|
3454
4662
|
width,
|
|
3455
4663
|
height
|
|
3456
|
-
)
|
|
4664
|
+
} = resample32(pixelData.data32, pixelData.width, pixelData.height, factor);
|
|
4665
|
+
return new PixelData(new ImageData(new Uint8ClampedArray(data.buffer), width, height));
|
|
3457
4666
|
}
|
|
3458
4667
|
|
|
3459
4668
|
// src/PixelData/rotatePixelData.ts
|
|
@@ -3477,11 +4686,7 @@ function rotatePixelData(pixelData) {
|
|
|
3477
4686
|
newData32[newIdx] = data[oldIdx];
|
|
3478
4687
|
}
|
|
3479
4688
|
}
|
|
3480
|
-
const newImageData = new ImageData(
|
|
3481
|
-
new Uint8ClampedArray(newData32.buffer),
|
|
3482
|
-
newWidth,
|
|
3483
|
-
newHeight
|
|
3484
|
-
);
|
|
4689
|
+
const newImageData = new ImageData(new Uint8ClampedArray(newData32.buffer), newWidth, newHeight);
|
|
3485
4690
|
pixelData.set(newImageData);
|
|
3486
4691
|
}
|
|
3487
4692
|
function rotateSquareInPlace(pixelData) {
|
|
@@ -3503,8 +4708,14 @@ function rotateSquareInPlace(pixelData) {
|
|
|
3503
4708
|
}
|
|
3504
4709
|
|
|
3505
4710
|
// src/PixelData/writePixelDataBuffer.ts
|
|
4711
|
+
var SCRATCH_BLIT5 = makeClippedBlit();
|
|
3506
4712
|
function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
3507
|
-
const {
|
|
4713
|
+
const {
|
|
4714
|
+
x,
|
|
4715
|
+
y,
|
|
4716
|
+
w,
|
|
4717
|
+
h
|
|
4718
|
+
} = typeof _x === "object" ? _x : {
|
|
3508
4719
|
x: _x,
|
|
3509
4720
|
y: _y,
|
|
3510
4721
|
w: _w,
|
|
@@ -3513,22 +4724,20 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3513
4724
|
const dstW = target.width;
|
|
3514
4725
|
const dstH = target.height;
|
|
3515
4726
|
const dstData = target.data32;
|
|
3516
|
-
const
|
|
3517
|
-
|
|
3518
|
-
const
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
const
|
|
3529
|
-
|
|
3530
|
-
const srcStart = srcRow * w + srcCol;
|
|
3531
|
-
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);
|
|
3532
4741
|
}
|
|
3533
4742
|
}
|
|
3534
4743
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -3536,23 +4745,32 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3536
4745
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
3537
4746
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
3538
4747
|
BaseBlendMode,
|
|
4748
|
+
CANVAS_CTX_FAILED,
|
|
3539
4749
|
HistoryManager,
|
|
3540
4750
|
IndexedImage,
|
|
3541
4751
|
MaskType,
|
|
4752
|
+
OFFSCREEN_CANVAS_CTX_FAILED,
|
|
3542
4753
|
PixelAccumulator,
|
|
4754
|
+
PixelBuffer32,
|
|
3543
4755
|
PixelData,
|
|
3544
4756
|
PixelEngineConfig,
|
|
3545
4757
|
PixelTile,
|
|
3546
4758
|
PixelWriter,
|
|
3547
4759
|
UnsupportedFormatError,
|
|
4760
|
+
applyAlphaMaskToPixelData,
|
|
4761
|
+
applyBinaryMaskToAlphaMask,
|
|
4762
|
+
applyBinaryMaskToPixelData,
|
|
3548
4763
|
applyCircleBrushToPixelData,
|
|
3549
|
-
applyMaskToPixelData,
|
|
3550
4764
|
applyPatchTiles,
|
|
3551
4765
|
applyRectBrushToPixelData,
|
|
3552
4766
|
base64DecodeArrayBuffer,
|
|
3553
4767
|
base64EncodeArrayBuffer,
|
|
3554
4768
|
blendColorPixelData,
|
|
4769
|
+
blendColorPixelDataAlphaMask,
|
|
4770
|
+
blendColorPixelDataBinaryMask,
|
|
3555
4771
|
blendPixelData,
|
|
4772
|
+
blendPixelDataAlphaMask,
|
|
4773
|
+
blendPixelDataBinaryMask,
|
|
3556
4774
|
clearPixelData,
|
|
3557
4775
|
color32ToCssRGBA,
|
|
3558
4776
|
color32ToHex,
|
|
@@ -3585,10 +4803,13 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3585
4803
|
fileToImageData,
|
|
3586
4804
|
fillPixelData,
|
|
3587
4805
|
floodFillSelection,
|
|
3588
|
-
|
|
4806
|
+
forEachLinePoint,
|
|
4807
|
+
getCircleBrushOrPencilBounds,
|
|
4808
|
+
getCircleBrushOrPencilStrokeBounds,
|
|
3589
4809
|
getImageDataFromClipboard,
|
|
3590
4810
|
getIndexedImageColorCounts,
|
|
3591
|
-
|
|
4811
|
+
getRectBrushOrPencilBounds,
|
|
4812
|
+
getRectBrushOrPencilStrokeBounds,
|
|
3592
4813
|
getSupportedPixelFormats,
|
|
3593
4814
|
hardLightFast,
|
|
3594
4815
|
hardLightPerfect,
|
|
@@ -3620,17 +4841,29 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3620
4841
|
makeBlendModeRegistry,
|
|
3621
4842
|
makeFastBlendModeRegistry,
|
|
3622
4843
|
makeFullPixelMutator,
|
|
4844
|
+
makeImageDataLike,
|
|
3623
4845
|
makePerfectBlendModeRegistry,
|
|
3624
4846
|
makePixelCanvas,
|
|
3625
4847
|
makeReusableCanvas,
|
|
3626
4848
|
makeReusableImageData,
|
|
3627
|
-
|
|
4849
|
+
mergeAlphaMasks,
|
|
4850
|
+
mergeBinaryMasks,
|
|
3628
4851
|
multiplyFast,
|
|
3629
4852
|
multiplyPerfect,
|
|
3630
|
-
|
|
4853
|
+
mutatorApplyAlphaMask,
|
|
4854
|
+
mutatorApplyBinaryMask,
|
|
4855
|
+
mutatorApplyCircleBrush,
|
|
4856
|
+
mutatorApplyCircleBrushStroke,
|
|
4857
|
+
mutatorApplyCirclePencil,
|
|
4858
|
+
mutatorApplyCirclePencilStroke,
|
|
4859
|
+
mutatorApplyRectBrush,
|
|
4860
|
+
mutatorApplyRectBrushStroke,
|
|
4861
|
+
mutatorApplyRectPencil,
|
|
4862
|
+
mutatorApplyRectPencilStroke,
|
|
3631
4863
|
mutatorBlendColor,
|
|
3632
4864
|
mutatorBlendPixel,
|
|
3633
4865
|
mutatorBlendPixelData,
|
|
4866
|
+
mutatorClear,
|
|
3634
4867
|
mutatorFill,
|
|
3635
4868
|
mutatorInvert,
|
|
3636
4869
|
overlayFast,
|
|
@@ -3660,7 +4893,10 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3660
4893
|
sourceOverPerfect,
|
|
3661
4894
|
subtractFast,
|
|
3662
4895
|
subtractPerfect,
|
|
4896
|
+
toBlendModeIndexAndName,
|
|
3663
4897
|
trimRectBounds,
|
|
4898
|
+
uInt32ArrayToImageData,
|
|
4899
|
+
uInt32ArrayToImageDataLike,
|
|
3664
4900
|
unpackAlpha,
|
|
3665
4901
|
unpackBlue,
|
|
3666
4902
|
unpackColor,
|