pixel-data-js 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/index.dev.cjs +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 +21 -6
- package/src/Algorithm/forEachLinePoint.ts +36 -0
- package/src/BlendModes/BlendModeRegistry.ts +2 -0
- package/src/BlendModes/blend-modes-fast.ts +2 -2
- package/src/BlendModes/blend-modes-perfect.ts +5 -4
- package/src/BlendModes/toBlendModeIndexAndName.ts +41 -0
- package/src/History/PixelAccumulator.ts +2 -2
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +30 -0
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +30 -0
- package/src/History/PixelMutator/mutatorApplyCircleBrush.ts +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.js
CHANGED
|
@@ -1,614 +1,235 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
// src/_types.ts
|
|
2
|
+
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
3
|
+
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
4
|
+
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
5
|
+
return MaskType2;
|
|
6
|
+
})(MaskType || {});
|
|
7
|
+
|
|
8
|
+
// src/color.ts
|
|
9
|
+
function packColor(r, g, b, a) {
|
|
10
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
11
|
+
}
|
|
12
|
+
function packRGBA({
|
|
13
|
+
r,
|
|
14
|
+
g,
|
|
15
|
+
b,
|
|
16
|
+
a
|
|
17
|
+
}) {
|
|
18
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
19
|
+
}
|
|
20
|
+
var unpackRed = (packed) => packed >>> 0 & 255;
|
|
21
|
+
var unpackGreen = (packed) => packed >>> 8 & 255;
|
|
22
|
+
var unpackBlue = (packed) => packed >>> 16 & 255;
|
|
23
|
+
var unpackAlpha = (packed) => packed >>> 24 & 255;
|
|
24
|
+
function unpackColor(packed) {
|
|
25
|
+
return {
|
|
26
|
+
r: packed >>> 0 & 255,
|
|
27
|
+
g: packed >>> 8 & 255,
|
|
28
|
+
b: packed >>> 16 & 255,
|
|
29
|
+
a: packed >>> 24 & 255
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
var SCRATCH_RGBA = {
|
|
33
|
+
r: 0,
|
|
34
|
+
g: 0,
|
|
35
|
+
b: 0,
|
|
36
|
+
a: 0
|
|
26
37
|
};
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
|
|
39
|
+
scratch.r = packed >>> 0 & 255;
|
|
40
|
+
scratch.g = packed >>> 8 & 255;
|
|
41
|
+
scratch.b = packed >>> 16 & 255;
|
|
42
|
+
scratch.a = packed >>> 24 & 255;
|
|
43
|
+
return scratch;
|
|
44
|
+
}
|
|
45
|
+
function colorDistance(a, b) {
|
|
46
|
+
const dr = (a & 255) - (b & 255);
|
|
47
|
+
const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
|
|
48
|
+
const db = (a >>> 16 & 255) - (b >>> 16 & 255);
|
|
49
|
+
const da = (a >>> 24 & 255) - (b >>> 24 & 255);
|
|
50
|
+
return dr * dr + dg * dg + db * db + da * da;
|
|
51
|
+
}
|
|
52
|
+
function lerpColor32(a, b, t) {
|
|
53
|
+
const r = (a & 255) + t * ((b & 255) - (a & 255));
|
|
54
|
+
const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
|
|
55
|
+
const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
|
|
56
|
+
const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
|
|
57
|
+
return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
|
|
58
|
+
}
|
|
59
|
+
function lerpColor32Fast(src, dst, w) {
|
|
60
|
+
const invA = 255 - w;
|
|
61
|
+
const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
|
|
62
|
+
const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
|
|
63
|
+
return (rb | ga << 8) >>> 0;
|
|
64
|
+
}
|
|
65
|
+
function color32ToHex(color) {
|
|
66
|
+
const r = (color & 255).toString(16).padStart(2, "0");
|
|
67
|
+
const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
|
|
68
|
+
const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
|
|
69
|
+
const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
|
|
70
|
+
return `#${r}${g}${b}${a}`;
|
|
71
|
+
}
|
|
72
|
+
function color32ToCssRGBA(color) {
|
|
73
|
+
const r = color & 255;
|
|
74
|
+
const g = color >>> 8 & 255;
|
|
75
|
+
const b = color >>> 16 & 255;
|
|
76
|
+
const a = color >>> 24 & 255;
|
|
77
|
+
const alpha = Number((a / 255).toFixed(3));
|
|
78
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
79
|
+
}
|
|
29
80
|
|
|
30
|
-
// src/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
81
|
+
// src/Internal/resolveClipping.ts
|
|
82
|
+
var makeClippedRect = () => ({
|
|
83
|
+
x: 0,
|
|
84
|
+
y: 0,
|
|
85
|
+
w: 0,
|
|
86
|
+
h: 0,
|
|
87
|
+
inBounds: false
|
|
88
|
+
});
|
|
89
|
+
var makeClippedBlit = () => ({
|
|
90
|
+
x: 0,
|
|
91
|
+
y: 0,
|
|
92
|
+
sx: 0,
|
|
93
|
+
sy: 0,
|
|
94
|
+
w: 0,
|
|
95
|
+
h: 0,
|
|
96
|
+
inBounds: false
|
|
97
|
+
});
|
|
98
|
+
function resolveRectClipping(x, y, w, h, boundaryW, boundaryH, out) {
|
|
99
|
+
if (x < 0) {
|
|
100
|
+
w += x;
|
|
101
|
+
x = 0;
|
|
102
|
+
}
|
|
103
|
+
if (y < 0) {
|
|
104
|
+
h += y;
|
|
105
|
+
y = 0;
|
|
106
|
+
}
|
|
107
|
+
const actualW = Math.min(w, boundaryW - x);
|
|
108
|
+
const actualH = Math.min(h, boundaryH - y);
|
|
109
|
+
if (actualW <= 0 || actualH <= 0) {
|
|
110
|
+
out.inBounds = false;
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
out.x = x;
|
|
114
|
+
out.y = y;
|
|
115
|
+
out.w = actualW;
|
|
116
|
+
out.h = actualH;
|
|
117
|
+
out.inBounds = true;
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
function resolveBlitClipping(x, y, sx, sy, w, h, dstW, dstH, srcW, srcH, out) {
|
|
121
|
+
if (sx < 0) {
|
|
122
|
+
x -= sx;
|
|
123
|
+
w += sx;
|
|
124
|
+
sx = 0;
|
|
125
|
+
}
|
|
126
|
+
if (sy < 0) {
|
|
127
|
+
y -= sy;
|
|
128
|
+
h += sy;
|
|
129
|
+
sy = 0;
|
|
130
|
+
}
|
|
131
|
+
w = Math.min(w, srcW - sx);
|
|
132
|
+
h = Math.min(h, srcH - sy);
|
|
133
|
+
if (x < 0) {
|
|
134
|
+
sx -= x;
|
|
135
|
+
w += x;
|
|
136
|
+
x = 0;
|
|
137
|
+
}
|
|
138
|
+
if (y < 0) {
|
|
139
|
+
sy -= y;
|
|
140
|
+
h += y;
|
|
141
|
+
y = 0;
|
|
142
|
+
}
|
|
143
|
+
const actualW = Math.min(w, dstW - x);
|
|
144
|
+
const actualH = Math.min(h, dstH - y);
|
|
145
|
+
if (actualW <= 0 || actualH <= 0) {
|
|
146
|
+
out.inBounds = false;
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
out.x = x;
|
|
150
|
+
out.y = y;
|
|
151
|
+
out.sx = sx;
|
|
152
|
+
out.sy = sy;
|
|
153
|
+
out.w = actualW;
|
|
154
|
+
out.h = actualH;
|
|
155
|
+
out.inBounds = true;
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/ImageData/extractImageDataBuffer.ts
|
|
160
|
+
var SCRATCH_BLIT = makeClippedBlit();
|
|
161
|
+
function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
|
|
162
|
+
const {
|
|
163
|
+
x,
|
|
164
|
+
y,
|
|
165
|
+
w,
|
|
166
|
+
h
|
|
167
|
+
} = typeof _x === "object" ? _x : {
|
|
168
|
+
x: _x,
|
|
169
|
+
y: _y,
|
|
170
|
+
w: _w,
|
|
171
|
+
h: _h
|
|
172
|
+
};
|
|
173
|
+
const {
|
|
174
|
+
width: srcW,
|
|
175
|
+
height: srcH,
|
|
176
|
+
data: src
|
|
177
|
+
} = imageData;
|
|
178
|
+
if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
|
|
179
|
+
const out = new Uint8ClampedArray(w * h * 4);
|
|
180
|
+
const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT);
|
|
181
|
+
if (!clip.inBounds) return out;
|
|
182
|
+
const {
|
|
183
|
+
x: dstX,
|
|
184
|
+
y: dstY,
|
|
185
|
+
sx: srcX,
|
|
186
|
+
sy: srcY,
|
|
187
|
+
w: copyW,
|
|
188
|
+
h: copyH
|
|
189
|
+
} = clip;
|
|
190
|
+
const rowLen = copyW * 4;
|
|
191
|
+
for (let row = 0; row < copyH; row++) {
|
|
192
|
+
const srcStart = ((srcY + row) * srcW + srcX) * 4;
|
|
193
|
+
const dstStart = ((dstY + row) * w + dstX) * 4;
|
|
194
|
+
out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/Mask/extractMask.ts
|
|
200
|
+
function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
201
|
+
let finalX;
|
|
202
|
+
let finalY;
|
|
203
|
+
let finalW;
|
|
204
|
+
let finalH;
|
|
205
|
+
if (typeof xOrRect === "object") {
|
|
206
|
+
finalX = xOrRect.x;
|
|
207
|
+
finalY = xOrRect.y;
|
|
208
|
+
finalW = xOrRect.w;
|
|
209
|
+
finalH = xOrRect.h;
|
|
210
|
+
} else {
|
|
211
|
+
finalX = xOrRect;
|
|
212
|
+
finalY = y;
|
|
213
|
+
finalW = w;
|
|
214
|
+
finalH = h;
|
|
215
|
+
}
|
|
216
|
+
const out = new Uint8Array(finalW * finalH);
|
|
217
|
+
const srcH = mask.length / maskWidth;
|
|
218
|
+
for (let row = 0; row < finalH; row++) {
|
|
219
|
+
const currentSrcY = finalY + row;
|
|
220
|
+
if (currentSrcY < 0 || currentSrcY >= srcH) {
|
|
221
|
+
continue;
|
|
41
222
|
}
|
|
42
|
-
|
|
43
|
-
|
|
223
|
+
const start = Math.max(0, finalX);
|
|
224
|
+
const end = Math.min(maskWidth, finalX + finalW);
|
|
225
|
+
if (start < end) {
|
|
226
|
+
const srcOffset = currentSrcY * maskWidth + start;
|
|
227
|
+
const dstOffset = row * finalW + (start - finalX);
|
|
228
|
+
const count = end - start;
|
|
229
|
+
out.set(mask.subarray(srcOffset, srcOffset + count), dstOffset);
|
|
44
230
|
}
|
|
45
|
-
indexToName[index] = name;
|
|
46
|
-
indexToBlend[index] = blendFn;
|
|
47
|
-
blendToIndex.set(blendFn, index);
|
|
48
|
-
blendToName.set(blendFn, name);
|
|
49
|
-
nameToBlend[name] = blendFn;
|
|
50
|
-
nameToIndex[name] = index;
|
|
51
|
-
};
|
|
52
|
-
for (const [name, index] of Object.entries(blendModes)) {
|
|
53
|
-
const blend = initialEntries[index];
|
|
54
|
-
add(name, index, blend);
|
|
55
231
|
}
|
|
56
|
-
return
|
|
57
|
-
nameToBlend,
|
|
58
|
-
nameToIndex,
|
|
59
|
-
blendToIndex,
|
|
60
|
-
blendToName,
|
|
61
|
-
indexToBlend,
|
|
62
|
-
indexToName,
|
|
63
|
-
indexType: null,
|
|
64
|
-
nameType: null
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/BlendModes/blend-modes-fast.ts
|
|
69
|
-
var overwriteFast = overwriteBase;
|
|
70
|
-
var sourceOverFast = (src, dst) => {
|
|
71
|
-
const sa = src >>> 24 & 255;
|
|
72
|
-
if (sa === 255) return src;
|
|
73
|
-
if (sa === 0) return dst;
|
|
74
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
75
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
76
|
-
const da = dst >>> 24 & 255;
|
|
77
|
-
const invA = 255 - sa;
|
|
78
|
-
const r = sr * sa + dr * invA >> 8;
|
|
79
|
-
const g = sg * sa + dg * invA >> 8;
|
|
80
|
-
const b = sb * sa + db * invA >> 8;
|
|
81
|
-
const a = 255 * sa + da * invA >> 8;
|
|
82
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
83
|
-
};
|
|
84
|
-
var darkenFast = (src, dst) => {
|
|
85
|
-
const sa = src >>> 24 & 255;
|
|
86
|
-
if (sa === 0) return dst;
|
|
87
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
88
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
89
|
-
const br = sr < dr ? sr : dr;
|
|
90
|
-
const bg = sg < dg ? sg : dg;
|
|
91
|
-
const bb = sb < db ? sb : db;
|
|
92
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
93
|
-
const invA = 255 - sa;
|
|
94
|
-
const r = br * sa + dr * invA >> 8;
|
|
95
|
-
const g = bg * sa + dg * invA >> 8;
|
|
96
|
-
const b = bb * sa + db * invA >> 8;
|
|
97
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
98
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
99
|
-
};
|
|
100
|
-
var multiplyFast = (src, dst) => {
|
|
101
|
-
const sa = src >>> 24 & 255;
|
|
102
|
-
if (sa === 0) return dst;
|
|
103
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
104
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
105
|
-
const br = sr * dr >> 8;
|
|
106
|
-
const bg = sg * dg >> 8;
|
|
107
|
-
const bb = sb * db >> 8;
|
|
108
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
109
|
-
const invA = 255 - sa;
|
|
110
|
-
const da = dst >>> 24 & 255;
|
|
111
|
-
const r = br * sa + dr * invA >> 8;
|
|
112
|
-
const g = bg * sa + dg * invA >> 8;
|
|
113
|
-
const b = bb * sa + db * invA >> 8;
|
|
114
|
-
const a = 255 * sa + da * invA >> 8;
|
|
115
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
116
|
-
};
|
|
117
|
-
var colorBurnFast = (src, dst) => {
|
|
118
|
-
const sa = src >>> 24 & 255;
|
|
119
|
-
if (sa === 0) return dst;
|
|
120
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
121
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
122
|
-
const br = dr === 255 ? 255 : sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / sr | 0);
|
|
123
|
-
const bg = dg === 255 ? 255 : sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / sg | 0);
|
|
124
|
-
const bb = db === 255 ? 255 : sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / sb | 0);
|
|
125
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
126
|
-
const invA = 255 - sa;
|
|
127
|
-
const da = dst >>> 24 & 255;
|
|
128
|
-
const r = br * sa + dr * invA >> 8;
|
|
129
|
-
const g = bg * sa + dg * invA >> 8;
|
|
130
|
-
const b = bb * sa + db * invA >> 8;
|
|
131
|
-
const a = 255 * sa + da * invA >> 8;
|
|
132
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
133
|
-
};
|
|
134
|
-
var linearBurnFast = (src, dst) => {
|
|
135
|
-
const sa = src >>> 24 & 255;
|
|
136
|
-
if (sa === 0) return dst;
|
|
137
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
138
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
139
|
-
const brU = dr + sr - 255;
|
|
140
|
-
const bgU = dg + sg - 255;
|
|
141
|
-
const bbU = db + sb - 255;
|
|
142
|
-
const br = brU < 0 ? 0 : brU;
|
|
143
|
-
const bg = bgU < 0 ? 0 : bgU;
|
|
144
|
-
const bb = bbU < 0 ? 0 : bbU;
|
|
145
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
146
|
-
const invA = 255 - sa;
|
|
147
|
-
const r = br * sa + dr * invA >> 8;
|
|
148
|
-
const g = bg * sa + dg * invA >> 8;
|
|
149
|
-
const b = bb * sa + db * invA >> 8;
|
|
150
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
151
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
152
|
-
};
|
|
153
|
-
var darkerFast = (src, dst) => {
|
|
154
|
-
const sa = src >>> 24 & 255;
|
|
155
|
-
if (sa === 0) return dst;
|
|
156
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
157
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
158
|
-
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
159
|
-
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
160
|
-
let br, bg, bb;
|
|
161
|
-
if (lumSrc < lumDst) {
|
|
162
|
-
br = sr;
|
|
163
|
-
bg = sg;
|
|
164
|
-
bb = sb;
|
|
165
|
-
} else {
|
|
166
|
-
br = dr;
|
|
167
|
-
bg = dg;
|
|
168
|
-
bb = db;
|
|
169
|
-
}
|
|
170
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
171
|
-
const invA = 255 - sa;
|
|
172
|
-
const r = br * sa + dr * invA >> 8;
|
|
173
|
-
const g = bg * sa + dg * invA >> 8;
|
|
174
|
-
const b = bb * sa + db * invA >> 8;
|
|
175
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
176
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
177
|
-
};
|
|
178
|
-
var lightenFast = (src, dst) => {
|
|
179
|
-
const sa = src >>> 24 & 255;
|
|
180
|
-
if (sa === 0) return dst;
|
|
181
|
-
const br = Math.max(src & 255, dst & 255);
|
|
182
|
-
const bg = Math.max(src >> 8 & 255, dst >> 8 & 255);
|
|
183
|
-
const bb = Math.max(src >> 16 & 255, dst >> 16 & 255);
|
|
184
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
185
|
-
const dr = dst & 255;
|
|
186
|
-
const dg = dst >> 8 & 255;
|
|
187
|
-
const db = dst >> 16 & 255;
|
|
188
|
-
const invA = 255 - sa;
|
|
189
|
-
const r = br * sa + dr * invA >> 8;
|
|
190
|
-
const g = bg * sa + dg * invA >> 8;
|
|
191
|
-
const b = bb * sa + db * invA >> 8;
|
|
192
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
193
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
194
|
-
};
|
|
195
|
-
var screenFast = (src, dst) => {
|
|
196
|
-
const sa = src >>> 24 & 255;
|
|
197
|
-
if (sa === 0) return dst;
|
|
198
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
199
|
-
const br = 255 - ((255 - (src & 255)) * (255 - dr) >> 8);
|
|
200
|
-
const bg = 255 - ((255 - (src >>> 8 & 255)) * (255 - dg) >> 8);
|
|
201
|
-
const bb = 255 - ((255 - (src >>> 16 & 255)) * (255 - db) >> 8);
|
|
202
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
203
|
-
const invA = 255 - sa;
|
|
204
|
-
const r = br * sa + dr * invA >> 8;
|
|
205
|
-
const g = bg * sa + dg * invA >> 8;
|
|
206
|
-
const b = bb * sa + db * invA >> 8;
|
|
207
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
208
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
209
|
-
};
|
|
210
|
-
var colorDodgeFast = (src, dst) => {
|
|
211
|
-
const sa = src >>> 24 & 255;
|
|
212
|
-
if (sa === 0) return dst;
|
|
213
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
214
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
215
|
-
const br = sr === 255 ? 255 : Math.min(255, (dr << 8) / (255 - sr) | 0);
|
|
216
|
-
const bg = sg === 255 ? 255 : Math.min(255, (dg << 8) / (255 - sg) | 0);
|
|
217
|
-
const bb = sb === 255 ? 255 : Math.min(255, (db << 8) / (255 - sb) | 0);
|
|
218
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
219
|
-
const invA = 255 - sa;
|
|
220
|
-
const r = br * sa + dr * invA >> 8;
|
|
221
|
-
const g = bg * sa + dg * invA >> 8;
|
|
222
|
-
const b = bb * sa + db * invA >> 8;
|
|
223
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
224
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
225
|
-
};
|
|
226
|
-
var linearDodgeFast = (src, dst) => {
|
|
227
|
-
const sa = src >>> 24 & 255;
|
|
228
|
-
if (sa === 0) return dst;
|
|
229
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
230
|
-
const brU = (src & 255) + dr;
|
|
231
|
-
const bgU = (src >>> 8 & 255) + dg;
|
|
232
|
-
const bbU = (src >>> 16 & 255) + db;
|
|
233
|
-
const br = brU > 255 ? 255 : brU;
|
|
234
|
-
const bg = bgU > 255 ? 255 : bgU;
|
|
235
|
-
const bb = bbU > 255 ? 255 : bbU;
|
|
236
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
237
|
-
const invA = 255 - sa;
|
|
238
|
-
const r = br * sa + dr * invA >> 8;
|
|
239
|
-
const g = bg * sa + dg * invA >> 8;
|
|
240
|
-
const b = bb * sa + db * invA >> 8;
|
|
241
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
242
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
243
|
-
};
|
|
244
|
-
var lighterFast = (src, dst) => {
|
|
245
|
-
const sa = src >>> 24 & 255;
|
|
246
|
-
if (sa === 0) return dst;
|
|
247
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
248
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
249
|
-
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
250
|
-
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
251
|
-
let br, bg, bb;
|
|
252
|
-
if (lumSrc > lumDst) {
|
|
253
|
-
br = sr;
|
|
254
|
-
bg = sg;
|
|
255
|
-
bb = sb;
|
|
256
|
-
} else {
|
|
257
|
-
br = dr;
|
|
258
|
-
bg = dg;
|
|
259
|
-
bb = db;
|
|
260
|
-
}
|
|
261
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
262
|
-
const invA = 255 - sa;
|
|
263
|
-
const r = br * sa + dr * invA >> 8;
|
|
264
|
-
const g = bg * sa + dg * invA >> 8;
|
|
265
|
-
const b = bb * sa + db * invA >> 8;
|
|
266
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
267
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
268
|
-
};
|
|
269
|
-
var overlayFast = (src, dst) => {
|
|
270
|
-
const sa = src >>> 24 & 255;
|
|
271
|
-
if (sa === 0) return dst;
|
|
272
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
273
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
274
|
-
const br = dr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
275
|
-
const bg = dg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
276
|
-
const bb = db < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
277
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
278
|
-
const invA = 255 - sa;
|
|
279
|
-
const r = br * sa + dr * invA >> 8;
|
|
280
|
-
const g = bg * sa + dg * invA >> 8;
|
|
281
|
-
const b = bb * sa + db * invA >> 8;
|
|
282
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
283
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
284
|
-
};
|
|
285
|
-
var softLightFast = (src, dst) => {
|
|
286
|
-
const sa = src >>> 24 & 255;
|
|
287
|
-
if (sa === 0) return dst;
|
|
288
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
289
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
290
|
-
const br = (255 - dr) * (sr * dr >> 8) + dr * (255 - ((255 - sr) * (255 - dr) >> 8)) >> 8;
|
|
291
|
-
const bg = (255 - dg) * (sg * dg >> 8) + dg * (255 - ((255 - sg) * (255 - dg) >> 8)) >> 8;
|
|
292
|
-
const bb = (255 - db) * (sb * db >> 8) + db * (255 - ((255 - sb) * (255 - db) >> 8)) >> 8;
|
|
293
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
294
|
-
const invA = 255 - sa;
|
|
295
|
-
const r = br * sa + dr * invA >> 8;
|
|
296
|
-
const g = bg * sa + dg * invA >> 8;
|
|
297
|
-
const b = bb * sa + db * invA >> 8;
|
|
298
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
299
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
300
|
-
};
|
|
301
|
-
var hardLightFast = (src, dst) => {
|
|
302
|
-
const sa = src >>> 24 & 255;
|
|
303
|
-
if (sa === 0) return dst;
|
|
304
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
305
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
306
|
-
const br = sr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
307
|
-
const bg = sg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
308
|
-
const bb = sb < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
309
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
310
|
-
const invA = 255 - sa;
|
|
311
|
-
const r = br * sa + dr * invA >> 8;
|
|
312
|
-
const g = bg * sa + dg * invA >> 8;
|
|
313
|
-
const b = bb * sa + db * invA >> 8;
|
|
314
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
315
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
316
|
-
};
|
|
317
|
-
var vividLightFast = (src, dst) => {
|
|
318
|
-
const sa = src >>> 24 & 255;
|
|
319
|
-
if (sa === 0) return dst;
|
|
320
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
321
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
322
|
-
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);
|
|
323
|
-
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);
|
|
324
|
-
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);
|
|
325
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
326
|
-
const invA = 255 - sa;
|
|
327
|
-
const r = br * sa + dr * invA >> 8;
|
|
328
|
-
const g = bg * sa + dg * invA >> 8;
|
|
329
|
-
const b = bb * sa + db * invA >> 8;
|
|
330
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
331
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
332
|
-
};
|
|
333
|
-
var linearLightFast = (src, dst) => {
|
|
334
|
-
const sa = src >>> 24 & 255;
|
|
335
|
-
if (sa === 0) return dst;
|
|
336
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
337
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
338
|
-
const brU = dr + 2 * sr - 255;
|
|
339
|
-
const bgU = dg + 2 * sg - 255;
|
|
340
|
-
const bbU = db + 2 * sb - 255;
|
|
341
|
-
const br = brU < 0 ? 0 : brU > 255 ? 255 : brU;
|
|
342
|
-
const bg = bgU < 0 ? 0 : bgU > 255 ? 255 : bgU;
|
|
343
|
-
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU;
|
|
344
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
345
|
-
const invA = 255 - sa;
|
|
346
|
-
const r = br * sa + dr * invA >> 8;
|
|
347
|
-
const g = bg * sa + dg * invA >> 8;
|
|
348
|
-
const b = bb * sa + db * invA >> 8;
|
|
349
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
350
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
351
|
-
};
|
|
352
|
-
var pinLightFast = (src, dst) => {
|
|
353
|
-
const sa = src >>> 24 & 255;
|
|
354
|
-
if (sa === 0) return dst;
|
|
355
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
356
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
357
|
-
const br = sr < 128 ? dr < 2 * sr ? dr : 2 * sr : dr > 2 * sr - 256 ? dr : 2 * sr - 256;
|
|
358
|
-
const bg = sg < 128 ? dg < 2 * sg ? dg : 2 * sg : dg > 2 * sg - 256 ? dg : 2 * sg - 256;
|
|
359
|
-
const bb = sb < 128 ? db < 2 * sb ? db : 2 * sb : db > 2 * sb - 256 ? db : 2 * sb - 256;
|
|
360
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
361
|
-
const invA = 255 - sa;
|
|
362
|
-
const r = br * sa + dr * invA >> 8;
|
|
363
|
-
const g = bg * sa + dg * invA >> 8;
|
|
364
|
-
const b = bb * sa + db * invA >> 8;
|
|
365
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
366
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
367
|
-
};
|
|
368
|
-
var hardMixFast = (src, dst) => {
|
|
369
|
-
const sa = src >>> 24 & 255;
|
|
370
|
-
if (sa === 0) return dst;
|
|
371
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
372
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
373
|
-
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;
|
|
374
|
-
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;
|
|
375
|
-
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;
|
|
376
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
377
|
-
const invA = 255 - sa;
|
|
378
|
-
const r = br * sa + dr * invA >> 8;
|
|
379
|
-
const g = bg * sa + dg * invA >> 8;
|
|
380
|
-
const b = bb * sa + db * invA >> 8;
|
|
381
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
382
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
383
|
-
};
|
|
384
|
-
var differenceFast = (src, dst) => {
|
|
385
|
-
const sa = src >>> 24 & 255;
|
|
386
|
-
if (sa === 0) return dst;
|
|
387
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
388
|
-
const brD = (src & 255) - dr;
|
|
389
|
-
const bgD = (src >>> 8 & 255) - dg;
|
|
390
|
-
const bbD = (src >>> 16 & 255) - db;
|
|
391
|
-
const br = brD < 0 ? -brD : brD;
|
|
392
|
-
const bg = bgD < 0 ? -bgD : bgD;
|
|
393
|
-
const bb = bbD < 0 ? -bbD : bbD;
|
|
394
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
395
|
-
const invA = 255 - sa;
|
|
396
|
-
const r = br * sa + dr * invA >> 8;
|
|
397
|
-
const g = bg * sa + dg * invA >> 8;
|
|
398
|
-
const b = bb * sa + db * invA >> 8;
|
|
399
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
400
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
401
|
-
};
|
|
402
|
-
var exclusionFast = (src, dst) => {
|
|
403
|
-
const sa = src >>> 24 & 255;
|
|
404
|
-
if (sa === 0) return dst;
|
|
405
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
406
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
407
|
-
const br = dr + sr - (dr * sr >> 7);
|
|
408
|
-
const bg = dg + sg - (dg * sg >> 7);
|
|
409
|
-
const bb = db + sb - (db * sb >> 7);
|
|
410
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
411
|
-
const invA = 255 - sa;
|
|
412
|
-
const r = br * sa + dr * invA >> 8;
|
|
413
|
-
const g = bg * sa + dg * invA >> 8;
|
|
414
|
-
const b = bb * sa + db * invA >> 8;
|
|
415
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
416
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
417
|
-
};
|
|
418
|
-
var subtractFast = (src, dst) => {
|
|
419
|
-
const sa = src >>> 24 & 255;
|
|
420
|
-
if (sa === 0) return dst;
|
|
421
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
422
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
423
|
-
const brU = dr - sr;
|
|
424
|
-
const bgU = dg - sg;
|
|
425
|
-
const bbU = db - sb;
|
|
426
|
-
const br = brU < 0 ? 0 : brU;
|
|
427
|
-
const bg = bgU < 0 ? 0 : bgU;
|
|
428
|
-
const bb = bbU < 0 ? 0 : bbU;
|
|
429
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
430
|
-
const invA = 255 - sa;
|
|
431
|
-
const r = br * sa + dr * invA >> 8;
|
|
432
|
-
const g = bg * sa + dg * invA >> 8;
|
|
433
|
-
const b = bb * sa + db * invA >> 8;
|
|
434
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
435
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
436
|
-
};
|
|
437
|
-
var divideFast = (src, dst) => {
|
|
438
|
-
const sa = src >>> 24 & 255;
|
|
439
|
-
if (sa === 0) return dst;
|
|
440
|
-
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
441
|
-
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
442
|
-
const br = sr === 0 ? 255 : Math.min(255, (dr << 8) / sr | 0);
|
|
443
|
-
const bg = sg === 0 ? 255 : Math.min(255, (dg << 8) / sg | 0);
|
|
444
|
-
const bb = sb === 0 ? 255 : Math.min(255, (db << 8) / sb | 0);
|
|
445
|
-
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
446
|
-
const invA = 255 - sa;
|
|
447
|
-
const r = br * sa + dr * invA >> 8;
|
|
448
|
-
const g = bg * sa + dg * invA >> 8;
|
|
449
|
-
const b = bb * sa + db * invA >> 8;
|
|
450
|
-
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
451
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
452
|
-
};
|
|
453
|
-
var BASE_FAST_BLEND_MODE_FUNCTIONS = {
|
|
454
|
-
[BaseBlendMode.overwrite]: overwriteFast,
|
|
455
|
-
[BaseBlendMode.sourceOver]: sourceOverFast,
|
|
456
|
-
[BaseBlendMode.darken]: darkenFast,
|
|
457
|
-
[BaseBlendMode.multiply]: multiplyFast,
|
|
458
|
-
[BaseBlendMode.colorBurn]: colorBurnFast,
|
|
459
|
-
[BaseBlendMode.linearBurn]: linearBurnFast,
|
|
460
|
-
[BaseBlendMode.darkerColor]: darkerFast,
|
|
461
|
-
[BaseBlendMode.lighten]: lightenFast,
|
|
462
|
-
[BaseBlendMode.screen]: screenFast,
|
|
463
|
-
[BaseBlendMode.colorDodge]: colorDodgeFast,
|
|
464
|
-
[BaseBlendMode.linearDodge]: linearDodgeFast,
|
|
465
|
-
[BaseBlendMode.lighterColor]: lighterFast,
|
|
466
|
-
[BaseBlendMode.overlay]: overlayFast,
|
|
467
|
-
[BaseBlendMode.softLight]: softLightFast,
|
|
468
|
-
[BaseBlendMode.hardLight]: hardLightFast,
|
|
469
|
-
[BaseBlendMode.vividLight]: vividLightFast,
|
|
470
|
-
[BaseBlendMode.linearLight]: linearLightFast,
|
|
471
|
-
[BaseBlendMode.pinLight]: pinLightFast,
|
|
472
|
-
[BaseBlendMode.hardMix]: hardMixFast,
|
|
473
|
-
[BaseBlendMode.difference]: differenceFast,
|
|
474
|
-
[BaseBlendMode.exclusion]: exclusionFast,
|
|
475
|
-
[BaseBlendMode.subtract]: subtractFast,
|
|
476
|
-
[BaseBlendMode.divide]: divideFast
|
|
477
|
-
};
|
|
478
|
-
function makeFastBlendModeRegistry() {
|
|
479
|
-
return makeBlendModeRegistry(BaseBlendMode, BASE_FAST_BLEND_MODE_FUNCTIONS);
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// src/_types.ts
|
|
483
|
-
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
484
|
-
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
485
|
-
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
486
|
-
return MaskType2;
|
|
487
|
-
})(MaskType || {});
|
|
488
|
-
|
|
489
|
-
// src/color.ts
|
|
490
|
-
function packColor(r, g, b, a) {
|
|
491
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
492
|
-
}
|
|
493
|
-
function packRGBA({ r, g, b, a }) {
|
|
494
|
-
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
495
|
-
}
|
|
496
|
-
var unpackRed = (packed) => packed >>> 0 & 255;
|
|
497
|
-
var unpackGreen = (packed) => packed >>> 8 & 255;
|
|
498
|
-
var unpackBlue = (packed) => packed >>> 16 & 255;
|
|
499
|
-
var unpackAlpha = (packed) => packed >>> 24 & 255;
|
|
500
|
-
function unpackColor(packed) {
|
|
501
|
-
return {
|
|
502
|
-
r: packed >>> 0 & 255,
|
|
503
|
-
g: packed >>> 8 & 255,
|
|
504
|
-
b: packed >>> 16 & 255,
|
|
505
|
-
a: packed >>> 24 & 255
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
var SCRATCH_RGBA = { r: 0, g: 0, b: 0, a: 0 };
|
|
509
|
-
function unpackColorTo(packed, scratch = SCRATCH_RGBA) {
|
|
510
|
-
scratch.r = packed >>> 0 & 255;
|
|
511
|
-
scratch.g = packed >>> 8 & 255;
|
|
512
|
-
scratch.b = packed >>> 16 & 255;
|
|
513
|
-
scratch.a = packed >>> 24 & 255;
|
|
514
|
-
return scratch;
|
|
515
|
-
}
|
|
516
|
-
function colorDistance(a, b) {
|
|
517
|
-
const dr = (a & 255) - (b & 255);
|
|
518
|
-
const dg = (a >>> 8 & 255) - (b >>> 8 & 255);
|
|
519
|
-
const db = (a >>> 16 & 255) - (b >>> 16 & 255);
|
|
520
|
-
const da = (a >>> 24 & 255) - (b >>> 24 & 255);
|
|
521
|
-
return dr * dr + dg * dg + db * db + da * da;
|
|
522
|
-
}
|
|
523
|
-
function lerpColor32(a, b, t) {
|
|
524
|
-
const r = (a & 255) + t * ((b & 255) - (a & 255));
|
|
525
|
-
const g = (a >>> 8 & 255) + t * ((b >>> 8 & 255) - (a >>> 8 & 255));
|
|
526
|
-
const b_ = (a >>> 16 & 255) + t * ((b >>> 16 & 255) - (a >>> 16 & 255));
|
|
527
|
-
const a_ = (a >>> 24 & 255) + t * ((b >>> 24 & 255) - (a >>> 24 & 255));
|
|
528
|
-
return (a_ << 24 | b_ << 16 | g << 8 | r) >>> 0;
|
|
529
|
-
}
|
|
530
|
-
function lerpColor32Fast(src, dst, w) {
|
|
531
|
-
const invA = 255 - w;
|
|
532
|
-
const rb = (src & 16711935) * w + (dst & 16711935) * invA >>> 8 & 16711935;
|
|
533
|
-
const ga = (src >>> 8 & 16711935) * w + (dst >>> 8 & 16711935) * invA >>> 8 & 16711935;
|
|
534
|
-
return (rb | ga << 8) >>> 0;
|
|
535
|
-
}
|
|
536
|
-
function color32ToHex(color) {
|
|
537
|
-
const r = (color & 255).toString(16).padStart(2, "0");
|
|
538
|
-
const g = (color >>> 8 & 255).toString(16).padStart(2, "0");
|
|
539
|
-
const b = (color >>> 16 & 255).toString(16).padStart(2, "0");
|
|
540
|
-
const a = (color >>> 24 & 255).toString(16).padStart(2, "0");
|
|
541
|
-
return `#${r}${g}${b}${a}`;
|
|
542
|
-
}
|
|
543
|
-
function color32ToCssRGBA(color) {
|
|
544
|
-
const r = color & 255;
|
|
545
|
-
const g = color >>> 8 & 255;
|
|
546
|
-
const b = color >>> 16 & 255;
|
|
547
|
-
const a = color >>> 24 & 255;
|
|
548
|
-
const alpha = Number((a / 255).toFixed(3));
|
|
549
|
-
return `rgba(${r},${g},${b},${alpha})`;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
// src/ImageData/extractImageDataBuffer.ts
|
|
553
|
-
function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
|
|
554
|
-
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
555
|
-
const { width: srcW, height: srcH, data: src } = imageData;
|
|
556
|
-
if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
|
|
557
|
-
const out = new Uint8ClampedArray(w * h * 4);
|
|
558
|
-
const x0 = Math.max(0, x);
|
|
559
|
-
const y0 = Math.max(0, y);
|
|
560
|
-
const x1 = Math.min(srcW, x + w);
|
|
561
|
-
const y1 = Math.min(srcH, y + h);
|
|
562
|
-
if (x1 <= x0 || y1 <= y0) return out;
|
|
563
|
-
for (let row = 0; row < y1 - y0; row++) {
|
|
564
|
-
const srcRow = y0 + row;
|
|
565
|
-
const srcStart = (srcRow * srcW + x0) * 4;
|
|
566
|
-
const rowLen = (x1 - x0) * 4;
|
|
567
|
-
const dstRow = y0 - y + row;
|
|
568
|
-
const dstCol = x0 - x;
|
|
569
|
-
const dstStart = (dstRow * w + dstCol) * 4;
|
|
570
|
-
out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
571
|
-
}
|
|
572
|
-
return out;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// src/Mask/extractMask.ts
|
|
576
|
-
function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
577
|
-
let finalX;
|
|
578
|
-
let finalY;
|
|
579
|
-
let finalW;
|
|
580
|
-
let finalH;
|
|
581
|
-
if (typeof xOrRect === "object") {
|
|
582
|
-
finalX = xOrRect.x;
|
|
583
|
-
finalY = xOrRect.y;
|
|
584
|
-
finalW = xOrRect.w;
|
|
585
|
-
finalH = xOrRect.h;
|
|
586
|
-
} else {
|
|
587
|
-
finalX = xOrRect;
|
|
588
|
-
finalY = y;
|
|
589
|
-
finalW = w;
|
|
590
|
-
finalH = h;
|
|
591
|
-
}
|
|
592
|
-
const out = new Uint8Array(finalW * finalH);
|
|
593
|
-
const srcH = mask.length / maskWidth;
|
|
594
|
-
for (let row = 0; row < finalH; row++) {
|
|
595
|
-
const currentSrcY = finalY + row;
|
|
596
|
-
if (currentSrcY < 0 || currentSrcY >= srcH) {
|
|
597
|
-
continue;
|
|
598
|
-
}
|
|
599
|
-
const start = Math.max(0, finalX);
|
|
600
|
-
const end = Math.min(maskWidth, finalX + finalW);
|
|
601
|
-
if (start < end) {
|
|
602
|
-
const srcOffset = currentSrcY * maskWidth + start;
|
|
603
|
-
const dstOffset = row * finalW + (start - finalX);
|
|
604
|
-
const count = end - start;
|
|
605
|
-
out.set(
|
|
606
|
-
mask.subarray(srcOffset, srcOffset + count),
|
|
607
|
-
dstOffset
|
|
608
|
-
);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
return out;
|
|
232
|
+
return out;
|
|
612
233
|
}
|
|
613
234
|
|
|
614
235
|
// src/Rect/trimRectBounds.ts
|
|
@@ -618,14 +239,8 @@ function trimRectBounds(target, bounds) {
|
|
|
618
239
|
const originalW = target.w;
|
|
619
240
|
const intersectedX = Math.max(target.x, bounds.x);
|
|
620
241
|
const intersectedY = Math.max(target.y, bounds.y);
|
|
621
|
-
const intersectedMaxX = Math.min(
|
|
622
|
-
|
|
623
|
-
bounds.x + bounds.w
|
|
624
|
-
);
|
|
625
|
-
const intersectedMaxY = Math.min(
|
|
626
|
-
target.y + target.h,
|
|
627
|
-
bounds.y + bounds.h
|
|
628
|
-
);
|
|
242
|
+
const intersectedMaxX = Math.min(target.x + target.w, bounds.x + bounds.w);
|
|
243
|
+
const intersectedMaxY = Math.min(target.y + target.h, bounds.y + bounds.h);
|
|
629
244
|
if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
|
|
630
245
|
target.w = 0;
|
|
631
246
|
target.h = 0;
|
|
@@ -643,14 +258,7 @@ function trimRectBounds(target, bounds) {
|
|
|
643
258
|
target.w = intersectedW;
|
|
644
259
|
target.h = intersectedH;
|
|
645
260
|
if ("mask" in target && target.mask) {
|
|
646
|
-
const currentMask = extractMask(
|
|
647
|
-
target.mask,
|
|
648
|
-
originalW,
|
|
649
|
-
offsetX,
|
|
650
|
-
offsetY,
|
|
651
|
-
intersectedW,
|
|
652
|
-
intersectedH
|
|
653
|
-
);
|
|
261
|
+
const currentMask = extractMask(target.mask, originalW, offsetX, offsetY, intersectedW, intersectedH);
|
|
654
262
|
let minX = intersectedW;
|
|
655
263
|
let maxX = -1;
|
|
656
264
|
let minY = intersectedH;
|
|
@@ -674,14 +282,7 @@ function trimRectBounds(target, bounds) {
|
|
|
674
282
|
const finalW = maxX - minX + 1;
|
|
675
283
|
const finalH = maxY - minY + 1;
|
|
676
284
|
if (finalW !== intersectedW || finalH !== intersectedH) {
|
|
677
|
-
target.mask = extractMask(
|
|
678
|
-
currentMask,
|
|
679
|
-
intersectedW,
|
|
680
|
-
minX,
|
|
681
|
-
minY,
|
|
682
|
-
finalW,
|
|
683
|
-
finalH
|
|
684
|
-
);
|
|
285
|
+
target.mask = extractMask(currentMask, intersectedW, minX, minY, finalW, finalH);
|
|
685
286
|
target.x += minX;
|
|
686
287
|
target.y += minY;
|
|
687
288
|
target.w = finalW;
|
|
@@ -704,11 +305,7 @@ function floodFillSelection(img, startX, startY, {
|
|
|
704
305
|
data32 = img.data32;
|
|
705
306
|
imageData = img.imageData;
|
|
706
307
|
} else {
|
|
707
|
-
data32 = new Uint32Array(
|
|
708
|
-
img.data.buffer,
|
|
709
|
-
img.data.byteOffset,
|
|
710
|
-
img.data.byteLength >> 2
|
|
711
|
-
);
|
|
308
|
+
data32 = new Uint32Array(img.data.buffer, img.data.byteOffset, img.data.byteLength >> 2);
|
|
712
309
|
imageData = img;
|
|
713
310
|
}
|
|
714
311
|
const {
|
|
@@ -819,35 +416,514 @@ function floodFillSelection(img, startX, startY, {
|
|
|
819
416
|
finalMask[my * sw + mx] = 1;
|
|
820
417
|
}
|
|
821
418
|
}
|
|
822
|
-
trimRectBounds(
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
419
|
+
trimRectBounds(selectionRect, {
|
|
420
|
+
x: 0,
|
|
421
|
+
y: 0,
|
|
422
|
+
w: width,
|
|
423
|
+
h: height
|
|
424
|
+
});
|
|
425
|
+
const extracted = extractImageDataBuffer(imageData, selectionRect.x, selectionRect.y, selectionRect.w, selectionRect.h);
|
|
426
|
+
return {
|
|
427
|
+
startX,
|
|
428
|
+
startY,
|
|
429
|
+
selectionRect,
|
|
430
|
+
pixels: extracted
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// src/BlendModes/blend-modes.ts
|
|
435
|
+
var BaseBlendMode = {
|
|
436
|
+
overwrite: 0,
|
|
437
|
+
sourceOver: 1,
|
|
438
|
+
darken: 2,
|
|
439
|
+
multiply: 3,
|
|
440
|
+
colorBurn: 4,
|
|
441
|
+
linearBurn: 5,
|
|
442
|
+
darkerColor: 6,
|
|
443
|
+
lighten: 7,
|
|
444
|
+
screen: 8,
|
|
445
|
+
colorDodge: 9,
|
|
446
|
+
linearDodge: 10,
|
|
447
|
+
lighterColor: 11,
|
|
448
|
+
overlay: 12,
|
|
449
|
+
softLight: 13,
|
|
450
|
+
hardLight: 14,
|
|
451
|
+
vividLight: 15,
|
|
452
|
+
linearLight: 16,
|
|
453
|
+
pinLight: 17,
|
|
454
|
+
hardMix: 18,
|
|
455
|
+
difference: 19,
|
|
456
|
+
exclusion: 20,
|
|
457
|
+
subtract: 21,
|
|
458
|
+
divide: 22
|
|
459
|
+
};
|
|
460
|
+
var overwriteBase = (src, _dst) => src;
|
|
461
|
+
overwriteBase.isOverwrite = true;
|
|
462
|
+
|
|
463
|
+
// src/BlendModes/BlendModeRegistry.ts
|
|
464
|
+
function makeBlendModeRegistry(blendModes, initialEntries, registryName = "anonymous") {
|
|
465
|
+
const blendToName = /* @__PURE__ */ new Map();
|
|
466
|
+
const blendToIndex = /* @__PURE__ */ new Map();
|
|
467
|
+
const indexToName = [];
|
|
468
|
+
const indexToBlend = [];
|
|
469
|
+
const nameToBlend = {};
|
|
470
|
+
const nameToIndex = {};
|
|
471
|
+
const add = (name, index, blendFn) => {
|
|
472
|
+
if (!Number.isFinite(index)) {
|
|
473
|
+
throw new Error(`Index "${index}" is not a number. Attempting to add name: "${name}", index: "${index}"`);
|
|
474
|
+
}
|
|
475
|
+
if (indexToBlend[index]) {
|
|
476
|
+
throw new Error(`Blend Mode index: ${index} is already used. Attempting to add name: "${name}", index: "${index}"`);
|
|
477
|
+
}
|
|
478
|
+
indexToName[index] = name;
|
|
479
|
+
indexToBlend[index] = blendFn;
|
|
480
|
+
blendToIndex.set(blendFn, index);
|
|
481
|
+
blendToName.set(blendFn, name);
|
|
482
|
+
nameToBlend[name] = blendFn;
|
|
483
|
+
nameToIndex[name] = index;
|
|
484
|
+
};
|
|
485
|
+
for (const [name, index] of Object.entries(blendModes)) {
|
|
486
|
+
const blend = initialEntries[index];
|
|
487
|
+
add(name, index, blend);
|
|
488
|
+
}
|
|
833
489
|
return {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
490
|
+
registryName,
|
|
491
|
+
nameToBlend,
|
|
492
|
+
nameToIndex,
|
|
493
|
+
blendToIndex,
|
|
494
|
+
blendToName,
|
|
495
|
+
indexToBlend,
|
|
496
|
+
indexToName,
|
|
497
|
+
indexType: null,
|
|
498
|
+
nameType: null
|
|
838
499
|
};
|
|
839
500
|
}
|
|
840
501
|
|
|
502
|
+
// src/BlendModes/blend-modes-fast.ts
|
|
503
|
+
var overwriteFast = overwriteBase;
|
|
504
|
+
var sourceOverFast = (src, dst) => {
|
|
505
|
+
const sa = src >>> 24 & 255;
|
|
506
|
+
if (sa === 255) return src;
|
|
507
|
+
if (sa === 0) return dst;
|
|
508
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
509
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
510
|
+
const da = dst >>> 24 & 255;
|
|
511
|
+
const invA = 255 - sa;
|
|
512
|
+
const r = sr * sa + dr * invA >> 8;
|
|
513
|
+
const g = sg * sa + dg * invA >> 8;
|
|
514
|
+
const b = sb * sa + db * invA >> 8;
|
|
515
|
+
const a = 255 * sa + da * invA >> 8;
|
|
516
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
517
|
+
};
|
|
518
|
+
var darkenFast = (src, dst) => {
|
|
519
|
+
const sa = src >>> 24 & 255;
|
|
520
|
+
if (sa === 0) return dst;
|
|
521
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
522
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
523
|
+
const br = sr < dr ? sr : dr;
|
|
524
|
+
const bg = sg < dg ? sg : dg;
|
|
525
|
+
const bb = sb < db ? sb : db;
|
|
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 multiplyFast = (src, dst) => {
|
|
535
|
+
const sa = src >>> 24 & 255;
|
|
536
|
+
if (sa === 0) return dst;
|
|
537
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
538
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
539
|
+
const br = sr * dr >> 8;
|
|
540
|
+
const bg = sg * dg >> 8;
|
|
541
|
+
const bb = sb * db >> 8;
|
|
542
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
543
|
+
const invA = 255 - sa;
|
|
544
|
+
const da = dst >>> 24 & 255;
|
|
545
|
+
const r = br * sa + dr * invA >> 8;
|
|
546
|
+
const g = bg * sa + dg * invA >> 8;
|
|
547
|
+
const b = bb * sa + db * invA >> 8;
|
|
548
|
+
const a = 255 * sa + da * invA >> 8;
|
|
549
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
550
|
+
};
|
|
551
|
+
var colorBurnFast = (src, dst) => {
|
|
552
|
+
const sa = src >>> 24 & 255;
|
|
553
|
+
if (sa === 0) return dst;
|
|
554
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
555
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
556
|
+
const br = dr === 255 ? 255 : sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / sr | 0);
|
|
557
|
+
const bg = dg === 255 ? 255 : sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / sg | 0);
|
|
558
|
+
const bb = db === 255 ? 255 : sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / sb | 0);
|
|
559
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
560
|
+
const invA = 255 - sa;
|
|
561
|
+
const da = dst >>> 24 & 255;
|
|
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 + da * invA >> 8;
|
|
566
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
567
|
+
};
|
|
568
|
+
var linearBurnFast = (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 brU = dr + sr - 255;
|
|
574
|
+
const bgU = dg + sg - 255;
|
|
575
|
+
const bbU = db + sb - 255;
|
|
576
|
+
const br = brU < 0 ? 0 : brU;
|
|
577
|
+
const bg = bgU < 0 ? 0 : bgU;
|
|
578
|
+
const bb = bbU < 0 ? 0 : bbU;
|
|
579
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
580
|
+
const invA = 255 - sa;
|
|
581
|
+
const r = br * sa + dr * invA >> 8;
|
|
582
|
+
const g = bg * sa + dg * invA >> 8;
|
|
583
|
+
const b = bb * sa + db * invA >> 8;
|
|
584
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
585
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
586
|
+
};
|
|
587
|
+
var darkerFast = (src, dst) => {
|
|
588
|
+
const sa = src >>> 24 & 255;
|
|
589
|
+
if (sa === 0) return dst;
|
|
590
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
591
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
592
|
+
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
593
|
+
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
594
|
+
let br, bg, bb;
|
|
595
|
+
if (lumSrc < lumDst) {
|
|
596
|
+
br = sr;
|
|
597
|
+
bg = sg;
|
|
598
|
+
bb = sb;
|
|
599
|
+
} else {
|
|
600
|
+
br = dr;
|
|
601
|
+
bg = dg;
|
|
602
|
+
bb = db;
|
|
603
|
+
}
|
|
604
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
605
|
+
const invA = 255 - sa;
|
|
606
|
+
const r = br * sa + dr * invA >> 8;
|
|
607
|
+
const g = bg * sa + dg * invA >> 8;
|
|
608
|
+
const b = bb * sa + db * invA >> 8;
|
|
609
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
610
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
611
|
+
};
|
|
612
|
+
var lightenFast = (src, dst) => {
|
|
613
|
+
const sa = src >>> 24 & 255;
|
|
614
|
+
if (sa === 0) return dst;
|
|
615
|
+
const br = Math.max(src & 255, dst & 255);
|
|
616
|
+
const bg = Math.max(src >> 8 & 255, dst >> 8 & 255);
|
|
617
|
+
const bb = Math.max(src >> 16 & 255, dst >> 16 & 255);
|
|
618
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
619
|
+
const dr = dst & 255;
|
|
620
|
+
const dg = dst >> 8 & 255;
|
|
621
|
+
const db = dst >> 16 & 255;
|
|
622
|
+
const invA = 255 - sa;
|
|
623
|
+
const r = br * sa + dr * invA >> 8;
|
|
624
|
+
const g = bg * sa + dg * invA >> 8;
|
|
625
|
+
const b = bb * sa + db * invA >> 8;
|
|
626
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
627
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
628
|
+
};
|
|
629
|
+
var screenFast = (src, dst) => {
|
|
630
|
+
const sa = src >>> 24 & 255;
|
|
631
|
+
if (sa === 0) return dst;
|
|
632
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
633
|
+
const br = 255 - ((255 - (src & 255)) * (255 - dr) >> 8);
|
|
634
|
+
const bg = 255 - ((255 - (src >>> 8 & 255)) * (255 - dg) >> 8);
|
|
635
|
+
const bb = 255 - ((255 - (src >>> 16 & 255)) * (255 - db) >> 8);
|
|
636
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
637
|
+
const invA = 255 - sa;
|
|
638
|
+
const r = br * sa + dr * invA >> 8;
|
|
639
|
+
const g = bg * sa + dg * invA >> 8;
|
|
640
|
+
const b = bb * sa + db * invA >> 8;
|
|
641
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
642
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
643
|
+
};
|
|
644
|
+
var colorDodgeFast = (src, dst) => {
|
|
645
|
+
const sa = src >>> 24 & 255;
|
|
646
|
+
if (sa === 0) return dst;
|
|
647
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
648
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
649
|
+
const br = sr === 255 ? 255 : Math.min(255, (dr << 8) / (255 - sr) | 0);
|
|
650
|
+
const bg = sg === 255 ? 255 : Math.min(255, (dg << 8) / (255 - sg) | 0);
|
|
651
|
+
const bb = sb === 255 ? 255 : Math.min(255, (db << 8) / (255 - sb) | 0);
|
|
652
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
653
|
+
const invA = 255 - sa;
|
|
654
|
+
const r = br * sa + dr * invA >> 8;
|
|
655
|
+
const g = bg * sa + dg * invA >> 8;
|
|
656
|
+
const b = bb * sa + db * invA >> 8;
|
|
657
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
658
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
659
|
+
};
|
|
660
|
+
var linearDodgeFast = (src, dst) => {
|
|
661
|
+
const sa = src >>> 24 & 255;
|
|
662
|
+
if (sa === 0) return dst;
|
|
663
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
664
|
+
const brU = (src & 255) + dr;
|
|
665
|
+
const bgU = (src >>> 8 & 255) + dg;
|
|
666
|
+
const bbU = (src >>> 16 & 255) + db;
|
|
667
|
+
const br = brU > 255 ? 255 : brU;
|
|
668
|
+
const bg = bgU > 255 ? 255 : bgU;
|
|
669
|
+
const bb = bbU > 255 ? 255 : bbU;
|
|
670
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
671
|
+
const invA = 255 - sa;
|
|
672
|
+
const r = br * sa + dr * invA >> 8;
|
|
673
|
+
const g = bg * sa + dg * invA >> 8;
|
|
674
|
+
const b = bb * sa + db * invA >> 8;
|
|
675
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
676
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
677
|
+
};
|
|
678
|
+
var lighterFast = (src, dst) => {
|
|
679
|
+
const sa = src >>> 24 & 255;
|
|
680
|
+
if (sa === 0) return dst;
|
|
681
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
682
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
683
|
+
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
684
|
+
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
685
|
+
let br, bg, bb;
|
|
686
|
+
if (lumSrc > lumDst) {
|
|
687
|
+
br = sr;
|
|
688
|
+
bg = sg;
|
|
689
|
+
bb = sb;
|
|
690
|
+
} else {
|
|
691
|
+
br = dr;
|
|
692
|
+
bg = dg;
|
|
693
|
+
bb = db;
|
|
694
|
+
}
|
|
695
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
696
|
+
const invA = 255 - sa;
|
|
697
|
+
const r = br * sa + dr * invA >> 8;
|
|
698
|
+
const g = bg * sa + dg * invA >> 8;
|
|
699
|
+
const b = bb * sa + db * invA >> 8;
|
|
700
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
701
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
702
|
+
};
|
|
703
|
+
var overlayFast = (src, dst) => {
|
|
704
|
+
const sa = src >>> 24 & 255;
|
|
705
|
+
if (sa === 0) return dst;
|
|
706
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
707
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
708
|
+
const br = dr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
709
|
+
const bg = dg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
710
|
+
const bb = db < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
711
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
712
|
+
const invA = 255 - sa;
|
|
713
|
+
const r = br * sa + dr * invA >> 8;
|
|
714
|
+
const g = bg * sa + dg * invA >> 8;
|
|
715
|
+
const b = bb * sa + db * invA >> 8;
|
|
716
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
717
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
718
|
+
};
|
|
719
|
+
var softLightFast = (src, dst) => {
|
|
720
|
+
const sa = src >>> 24 & 255;
|
|
721
|
+
if (sa === 0) return dst;
|
|
722
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
723
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
724
|
+
const br = (255 - dr) * (sr * dr >> 8) + dr * (255 - ((255 - sr) * (255 - dr) >> 8)) >> 8;
|
|
725
|
+
const bg = (255 - dg) * (sg * dg >> 8) + dg * (255 - ((255 - sg) * (255 - dg) >> 8)) >> 8;
|
|
726
|
+
const bb = (255 - db) * (sb * db >> 8) + db * (255 - ((255 - sb) * (255 - db) >> 8)) >> 8;
|
|
727
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
728
|
+
const invA = 255 - sa;
|
|
729
|
+
const r = br * sa + dr * invA >> 8;
|
|
730
|
+
const g = bg * sa + dg * invA >> 8;
|
|
731
|
+
const b = bb * sa + db * invA >> 8;
|
|
732
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
733
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
734
|
+
};
|
|
735
|
+
var hardLightFast = (src, dst) => {
|
|
736
|
+
const sa = src >>> 24 & 255;
|
|
737
|
+
if (sa === 0) return dst;
|
|
738
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
739
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
740
|
+
const br = sr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
741
|
+
const bg = sg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
742
|
+
const bb = sb < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
743
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
744
|
+
const invA = 255 - sa;
|
|
745
|
+
const r = br * sa + dr * invA >> 8;
|
|
746
|
+
const g = bg * sa + dg * invA >> 8;
|
|
747
|
+
const b = bb * sa + db * invA >> 8;
|
|
748
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
749
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
750
|
+
};
|
|
751
|
+
var vividLightFast = (src, dst) => {
|
|
752
|
+
const sa = src >>> 24 & 255;
|
|
753
|
+
if (sa === 0) return dst;
|
|
754
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
755
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
756
|
+
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);
|
|
757
|
+
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);
|
|
758
|
+
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);
|
|
759
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
760
|
+
const invA = 255 - sa;
|
|
761
|
+
const r = br * sa + dr * invA >> 8;
|
|
762
|
+
const g = bg * sa + dg * invA >> 8;
|
|
763
|
+
const b = bb * sa + db * invA >> 8;
|
|
764
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
765
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
766
|
+
};
|
|
767
|
+
var linearLightFast = (src, dst) => {
|
|
768
|
+
const sa = src >>> 24 & 255;
|
|
769
|
+
if (sa === 0) return dst;
|
|
770
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
771
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
772
|
+
const brU = dr + 2 * sr - 255;
|
|
773
|
+
const bgU = dg + 2 * sg - 255;
|
|
774
|
+
const bbU = db + 2 * sb - 255;
|
|
775
|
+
const br = brU < 0 ? 0 : brU > 255 ? 255 : brU;
|
|
776
|
+
const bg = bgU < 0 ? 0 : bgU > 255 ? 255 : bgU;
|
|
777
|
+
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU;
|
|
778
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
779
|
+
const invA = 255 - sa;
|
|
780
|
+
const r = br * sa + dr * invA >> 8;
|
|
781
|
+
const g = bg * sa + dg * invA >> 8;
|
|
782
|
+
const b = bb * sa + db * invA >> 8;
|
|
783
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
784
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
785
|
+
};
|
|
786
|
+
var pinLightFast = (src, dst) => {
|
|
787
|
+
const sa = src >>> 24 & 255;
|
|
788
|
+
if (sa === 0) return dst;
|
|
789
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
790
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
791
|
+
const br = sr < 128 ? dr < 2 * sr ? dr : 2 * sr : dr > 2 * sr - 256 ? dr : 2 * sr - 256;
|
|
792
|
+
const bg = sg < 128 ? dg < 2 * sg ? dg : 2 * sg : dg > 2 * sg - 256 ? dg : 2 * sg - 256;
|
|
793
|
+
const bb = sb < 128 ? db < 2 * sb ? db : 2 * sb : db > 2 * sb - 256 ? db : 2 * sb - 256;
|
|
794
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
795
|
+
const invA = 255 - sa;
|
|
796
|
+
const r = br * sa + dr * invA >> 8;
|
|
797
|
+
const g = bg * sa + dg * invA >> 8;
|
|
798
|
+
const b = bb * sa + db * invA >> 8;
|
|
799
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
800
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
801
|
+
};
|
|
802
|
+
var hardMixFast = (src, dst) => {
|
|
803
|
+
const sa = src >>> 24 & 255;
|
|
804
|
+
if (sa === 0) return dst;
|
|
805
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
806
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
807
|
+
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;
|
|
808
|
+
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;
|
|
809
|
+
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;
|
|
810
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
811
|
+
const invA = 255 - sa;
|
|
812
|
+
const r = br * sa + dr * invA >> 8;
|
|
813
|
+
const g = bg * sa + dg * invA >> 8;
|
|
814
|
+
const b = bb * sa + db * invA >> 8;
|
|
815
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
816
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
817
|
+
};
|
|
818
|
+
var differenceFast = (src, dst) => {
|
|
819
|
+
const sa = src >>> 24 & 255;
|
|
820
|
+
if (sa === 0) return dst;
|
|
821
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
822
|
+
const brD = (src & 255) - dr;
|
|
823
|
+
const bgD = (src >>> 8 & 255) - dg;
|
|
824
|
+
const bbD = (src >>> 16 & 255) - db;
|
|
825
|
+
const br = brD < 0 ? -brD : brD;
|
|
826
|
+
const bg = bgD < 0 ? -bgD : bgD;
|
|
827
|
+
const bb = bbD < 0 ? -bbD : bbD;
|
|
828
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
829
|
+
const invA = 255 - sa;
|
|
830
|
+
const r = br * sa + dr * invA >> 8;
|
|
831
|
+
const g = bg * sa + dg * invA >> 8;
|
|
832
|
+
const b = bb * sa + db * invA >> 8;
|
|
833
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
834
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
835
|
+
};
|
|
836
|
+
var exclusionFast = (src, dst) => {
|
|
837
|
+
const sa = src >>> 24 & 255;
|
|
838
|
+
if (sa === 0) return dst;
|
|
839
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
840
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
841
|
+
const br = dr + sr - (dr * sr >> 7);
|
|
842
|
+
const bg = dg + sg - (dg * sg >> 7);
|
|
843
|
+
const bb = db + sb - (db * sb >> 7);
|
|
844
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
845
|
+
const invA = 255 - sa;
|
|
846
|
+
const r = br * sa + dr * invA >> 8;
|
|
847
|
+
const g = bg * sa + dg * invA >> 8;
|
|
848
|
+
const b = bb * sa + db * invA >> 8;
|
|
849
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
850
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
851
|
+
};
|
|
852
|
+
var subtractFast = (src, dst) => {
|
|
853
|
+
const sa = src >>> 24 & 255;
|
|
854
|
+
if (sa === 0) return dst;
|
|
855
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
856
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
857
|
+
const brU = dr - sr;
|
|
858
|
+
const bgU = dg - sg;
|
|
859
|
+
const bbU = db - sb;
|
|
860
|
+
const br = brU < 0 ? 0 : brU;
|
|
861
|
+
const bg = bgU < 0 ? 0 : bgU;
|
|
862
|
+
const bb = bbU < 0 ? 0 : 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 divideFast = (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 br = sr === 0 ? 255 : Math.min(255, (dr << 8) / sr | 0);
|
|
877
|
+
const bg = sg === 0 ? 255 : Math.min(255, (dg << 8) / sg | 0);
|
|
878
|
+
const bb = sb === 0 ? 255 : Math.min(255, (db << 8) / sb | 0);
|
|
879
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
880
|
+
const invA = 255 - sa;
|
|
881
|
+
const r = br * sa + dr * invA >> 8;
|
|
882
|
+
const g = bg * sa + dg * invA >> 8;
|
|
883
|
+
const b = bb * sa + db * invA >> 8;
|
|
884
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
885
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
886
|
+
};
|
|
887
|
+
var BASE_FAST_BLEND_MODE_FUNCTIONS = {
|
|
888
|
+
[BaseBlendMode.overwrite]: overwriteFast,
|
|
889
|
+
[BaseBlendMode.sourceOver]: sourceOverFast,
|
|
890
|
+
[BaseBlendMode.darken]: darkenFast,
|
|
891
|
+
[BaseBlendMode.multiply]: multiplyFast,
|
|
892
|
+
[BaseBlendMode.colorBurn]: colorBurnFast,
|
|
893
|
+
[BaseBlendMode.linearBurn]: linearBurnFast,
|
|
894
|
+
[BaseBlendMode.darkerColor]: darkerFast,
|
|
895
|
+
[BaseBlendMode.lighten]: lightenFast,
|
|
896
|
+
[BaseBlendMode.screen]: screenFast,
|
|
897
|
+
[BaseBlendMode.colorDodge]: colorDodgeFast,
|
|
898
|
+
[BaseBlendMode.linearDodge]: linearDodgeFast,
|
|
899
|
+
[BaseBlendMode.lighterColor]: lighterFast,
|
|
900
|
+
[BaseBlendMode.overlay]: overlayFast,
|
|
901
|
+
[BaseBlendMode.softLight]: softLightFast,
|
|
902
|
+
[BaseBlendMode.hardLight]: hardLightFast,
|
|
903
|
+
[BaseBlendMode.vividLight]: vividLightFast,
|
|
904
|
+
[BaseBlendMode.linearLight]: linearLightFast,
|
|
905
|
+
[BaseBlendMode.pinLight]: pinLightFast,
|
|
906
|
+
[BaseBlendMode.hardMix]: hardMixFast,
|
|
907
|
+
[BaseBlendMode.difference]: differenceFast,
|
|
908
|
+
[BaseBlendMode.exclusion]: exclusionFast,
|
|
909
|
+
[BaseBlendMode.subtract]: subtractFast,
|
|
910
|
+
[BaseBlendMode.divide]: divideFast
|
|
911
|
+
};
|
|
912
|
+
function makeFastBlendModeRegistry(name = "fast") {
|
|
913
|
+
return makeBlendModeRegistry(BaseBlendMode, BASE_FAST_BLEND_MODE_FUNCTIONS, name);
|
|
914
|
+
}
|
|
915
|
+
|
|
841
916
|
// src/BlendModes/blend-modes-perfect.ts
|
|
842
917
|
var overwritePerfect = overwriteBase;
|
|
843
918
|
var sourceOverPerfect = (src, dst) => {
|
|
844
919
|
const sa = src >>> 24 & 255;
|
|
845
920
|
if (sa === 255) return src;
|
|
846
921
|
if (sa === 0) return dst;
|
|
847
|
-
const
|
|
922
|
+
const da = dst >>> 24 & 255;
|
|
923
|
+
if (da === 0) return src;
|
|
848
924
|
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
849
925
|
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
850
|
-
const
|
|
926
|
+
const invA = 255 - sa;
|
|
851
927
|
const tR = sr * sa + dr * invA;
|
|
852
928
|
const r = tR + 1 + (tR >> 8) >> 8;
|
|
853
929
|
const tG = sg * sa + dg * invA;
|
|
@@ -1389,9 +1465,53 @@ var BASE_PERFECT_BLEND_MODE_FUNCTIONS = {
|
|
|
1389
1465
|
[BaseBlendMode.subtract]: subtractPerfect,
|
|
1390
1466
|
[BaseBlendMode.divide]: dividePerfect
|
|
1391
1467
|
};
|
|
1392
|
-
function makePerfectBlendModeRegistry() {
|
|
1393
|
-
return makeBlendModeRegistry(BaseBlendMode, BASE_PERFECT_BLEND_MODE_FUNCTIONS);
|
|
1468
|
+
function makePerfectBlendModeRegistry(name = "perfect") {
|
|
1469
|
+
return makeBlendModeRegistry(BaseBlendMode, BASE_PERFECT_BLEND_MODE_FUNCTIONS, name);
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
// src/BlendModes/toBlendModeIndexAndName.ts
|
|
1473
|
+
function toBlendModeIndexAndName(input) {
|
|
1474
|
+
if (typeof input === "number") {
|
|
1475
|
+
const name = getKeyByValue(BaseBlendMode, input);
|
|
1476
|
+
if (name === void 0) throw new Error(`Invalid index: ${input}`);
|
|
1477
|
+
return {
|
|
1478
|
+
blendIndex: input,
|
|
1479
|
+
blendName: name
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
const trimmed = input.trim();
|
|
1483
|
+
const num = Number(trimmed);
|
|
1484
|
+
const isNumeric = trimmed !== "" && !Number.isNaN(num);
|
|
1485
|
+
if (isNumeric && Number.isInteger(num)) {
|
|
1486
|
+
console.log({
|
|
1487
|
+
trimmed,
|
|
1488
|
+
num,
|
|
1489
|
+
isNumeric,
|
|
1490
|
+
isInt: Number.isInteger(num)
|
|
1491
|
+
});
|
|
1492
|
+
const name = getKeyByValue(BaseBlendMode, num);
|
|
1493
|
+
console.log({
|
|
1494
|
+
name
|
|
1495
|
+
});
|
|
1496
|
+
if (name === void 0) throw new Error(`Invalid index: ${num}`);
|
|
1497
|
+
return {
|
|
1498
|
+
blendIndex: num,
|
|
1499
|
+
blendName: name
|
|
1500
|
+
};
|
|
1501
|
+
}
|
|
1502
|
+
if (trimmed in BaseBlendMode) {
|
|
1503
|
+
return {
|
|
1504
|
+
blendIndex: BaseBlendMode[trimmed],
|
|
1505
|
+
blendName: trimmed
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1508
|
+
throw new Error(`Invalid blend mode: ${JSON.stringify(input)}`);
|
|
1394
1509
|
}
|
|
1510
|
+
var getKeyByValue = (obj, value) => {
|
|
1511
|
+
for (const key in obj) {
|
|
1512
|
+
if (obj[key] === value) return key;
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1395
1515
|
|
|
1396
1516
|
// src/Canvas/_constants.ts
|
|
1397
1517
|
var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
|
|
@@ -1430,7 +1550,10 @@ function makeReusableCanvas() {
|
|
|
1430
1550
|
} else {
|
|
1431
1551
|
ctx.clearRect(0, 0, width, height);
|
|
1432
1552
|
}
|
|
1433
|
-
return {
|
|
1553
|
+
return {
|
|
1554
|
+
canvas,
|
|
1555
|
+
ctx
|
|
1556
|
+
};
|
|
1434
1557
|
}
|
|
1435
1558
|
get2.reset = () => {
|
|
1436
1559
|
canvas = null;
|
|
@@ -1444,21 +1567,13 @@ async function imgBlobToImageData(blob) {
|
|
|
1444
1567
|
let bitmap = null;
|
|
1445
1568
|
try {
|
|
1446
1569
|
bitmap = await createImageBitmap(blob);
|
|
1447
|
-
const canvas = new OffscreenCanvas(
|
|
1448
|
-
bitmap.width,
|
|
1449
|
-
bitmap.height
|
|
1450
|
-
);
|
|
1570
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
1451
1571
|
const ctx = canvas.getContext("2d");
|
|
1452
1572
|
if (!ctx) {
|
|
1453
1573
|
throw new Error("Failed to get 2D context");
|
|
1454
1574
|
}
|
|
1455
1575
|
ctx.drawImage(bitmap, 0, 0);
|
|
1456
|
-
return ctx.getImageData(
|
|
1457
|
-
0,
|
|
1458
|
-
0,
|
|
1459
|
-
bitmap.width,
|
|
1460
|
-
bitmap.height
|
|
1461
|
-
);
|
|
1576
|
+
return ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
1462
1577
|
} finally {
|
|
1463
1578
|
bitmap?.close();
|
|
1464
1579
|
}
|
|
@@ -1506,6 +1621,64 @@ async function writeImageDataToClipboard(imageData) {
|
|
|
1506
1621
|
return writeImgBlobToClipboard(blob);
|
|
1507
1622
|
}
|
|
1508
1623
|
|
|
1624
|
+
// src/History/HistoryManager.ts
|
|
1625
|
+
var HistoryManager = class {
|
|
1626
|
+
constructor(maxSteps = 50) {
|
|
1627
|
+
this.maxSteps = maxSteps;
|
|
1628
|
+
this.undoStack = [];
|
|
1629
|
+
this.redoStack = [];
|
|
1630
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
1631
|
+
}
|
|
1632
|
+
undoStack;
|
|
1633
|
+
redoStack;
|
|
1634
|
+
listeners;
|
|
1635
|
+
get canUndo() {
|
|
1636
|
+
return this.undoStack.length > 0;
|
|
1637
|
+
}
|
|
1638
|
+
get canRedo() {
|
|
1639
|
+
return this.redoStack.length > 0;
|
|
1640
|
+
}
|
|
1641
|
+
subscribe(fn) {
|
|
1642
|
+
this.listeners.add(fn);
|
|
1643
|
+
return () => this.listeners.delete(fn);
|
|
1644
|
+
}
|
|
1645
|
+
notify() {
|
|
1646
|
+
this.listeners.forEach((fn) => fn());
|
|
1647
|
+
}
|
|
1648
|
+
commit(action) {
|
|
1649
|
+
this.undoStack.push(action);
|
|
1650
|
+
this.clearRedoStack();
|
|
1651
|
+
if (this.undoStack.length > this.maxSteps) {
|
|
1652
|
+
this.undoStack.shift()?.dispose?.();
|
|
1653
|
+
}
|
|
1654
|
+
this.notify();
|
|
1655
|
+
}
|
|
1656
|
+
undo() {
|
|
1657
|
+
let action = this.undoStack.pop();
|
|
1658
|
+
if (!action) return;
|
|
1659
|
+
this.redoStack.push(action);
|
|
1660
|
+
action.undo();
|
|
1661
|
+
this.notify();
|
|
1662
|
+
}
|
|
1663
|
+
redo() {
|
|
1664
|
+
let action = this.redoStack.pop();
|
|
1665
|
+
if (!action) return;
|
|
1666
|
+
this.undoStack.push(action);
|
|
1667
|
+
action.redo();
|
|
1668
|
+
this.notify();
|
|
1669
|
+
}
|
|
1670
|
+
clearRedoStack() {
|
|
1671
|
+
let length = this.redoStack.length;
|
|
1672
|
+
for (let i = 0; i < length; i++) {
|
|
1673
|
+
let action = this.redoStack[i];
|
|
1674
|
+
if (action) {
|
|
1675
|
+
action.dispose?.();
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
this.redoStack.length = 0;
|
|
1679
|
+
}
|
|
1680
|
+
};
|
|
1681
|
+
|
|
1509
1682
|
// src/History/PixelPatchTiles.ts
|
|
1510
1683
|
var PixelTile = class {
|
|
1511
1684
|
constructor(id, tx, ty, tileArea) {
|
|
@@ -1559,12 +1732,7 @@ var PixelAccumulator = class {
|
|
|
1559
1732
|
tile.ty = ty;
|
|
1560
1733
|
return tile;
|
|
1561
1734
|
}
|
|
1562
|
-
return new PixelTile(
|
|
1563
|
-
id,
|
|
1564
|
-
tx,
|
|
1565
|
-
ty,
|
|
1566
|
-
this.config.tileArea
|
|
1567
|
-
);
|
|
1735
|
+
return new PixelTile(id, tx, ty, this.config.tileArea);
|
|
1568
1736
|
}
|
|
1569
1737
|
recyclePatch(patch) {
|
|
1570
1738
|
const before = patch.beforeTiles;
|
|
@@ -1595,11 +1763,7 @@ var PixelAccumulator = class {
|
|
|
1595
1763
|
let id = ty * columns + tx;
|
|
1596
1764
|
let tile = this.lookup[id];
|
|
1597
1765
|
if (!tile) {
|
|
1598
|
-
tile = this.getTile(
|
|
1599
|
-
id,
|
|
1600
|
-
tx,
|
|
1601
|
-
ty
|
|
1602
|
-
);
|
|
1766
|
+
tile = this.getTile(id, tx, ty);
|
|
1603
1767
|
this.extractState(tile);
|
|
1604
1768
|
this.lookup[id] = tile;
|
|
1605
1769
|
this.beforeTiles.push(tile);
|
|
@@ -1625,11 +1789,7 @@ var PixelAccumulator = class {
|
|
|
1625
1789
|
let id = ty * columns + tx;
|
|
1626
1790
|
let tile = this.lookup[id];
|
|
1627
1791
|
if (!tile) {
|
|
1628
|
-
tile = this.getTile(
|
|
1629
|
-
id,
|
|
1630
|
-
tx,
|
|
1631
|
-
ty
|
|
1632
|
-
);
|
|
1792
|
+
tile = this.getTile(id, tx, ty);
|
|
1633
1793
|
this.extractState(tile);
|
|
1634
1794
|
this.lookup[id] = tile;
|
|
1635
1795
|
this.beforeTiles.push(tile);
|
|
@@ -1668,11 +1828,7 @@ var PixelAccumulator = class {
|
|
|
1668
1828
|
for (let i = 0; i < length; i++) {
|
|
1669
1829
|
let beforeTile = this.beforeTiles[i];
|
|
1670
1830
|
if (beforeTile) {
|
|
1671
|
-
let afterTile = this.getTile(
|
|
1672
|
-
beforeTile.id,
|
|
1673
|
-
beforeTile.tx,
|
|
1674
|
-
beforeTile.ty
|
|
1675
|
-
);
|
|
1831
|
+
let afterTile = this.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
|
|
1676
1832
|
this.extractState(afterTile);
|
|
1677
1833
|
afterTiles.push(afterTile);
|
|
1678
1834
|
}
|
|
@@ -1685,64 +1841,6 @@ var PixelAccumulator = class {
|
|
|
1685
1841
|
}
|
|
1686
1842
|
};
|
|
1687
1843
|
|
|
1688
|
-
// src/History/HistoryManager.ts
|
|
1689
|
-
var HistoryManager = class {
|
|
1690
|
-
constructor(maxSteps = 50) {
|
|
1691
|
-
this.maxSteps = maxSteps;
|
|
1692
|
-
this.undoStack = [];
|
|
1693
|
-
this.redoStack = [];
|
|
1694
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
1695
|
-
}
|
|
1696
|
-
undoStack;
|
|
1697
|
-
redoStack;
|
|
1698
|
-
listeners;
|
|
1699
|
-
get canUndo() {
|
|
1700
|
-
return this.undoStack.length > 0;
|
|
1701
|
-
}
|
|
1702
|
-
get canRedo() {
|
|
1703
|
-
return this.redoStack.length > 0;
|
|
1704
|
-
}
|
|
1705
|
-
subscribe(fn) {
|
|
1706
|
-
this.listeners.add(fn);
|
|
1707
|
-
return () => this.listeners.delete(fn);
|
|
1708
|
-
}
|
|
1709
|
-
notify() {
|
|
1710
|
-
this.listeners.forEach((fn) => fn());
|
|
1711
|
-
}
|
|
1712
|
-
commit(action) {
|
|
1713
|
-
this.undoStack.push(action);
|
|
1714
|
-
this.clearRedoStack();
|
|
1715
|
-
if (this.undoStack.length > this.maxSteps) {
|
|
1716
|
-
this.undoStack.shift()?.dispose?.();
|
|
1717
|
-
}
|
|
1718
|
-
this.notify();
|
|
1719
|
-
}
|
|
1720
|
-
undo() {
|
|
1721
|
-
let action = this.undoStack.pop();
|
|
1722
|
-
if (!action) return;
|
|
1723
|
-
this.redoStack.push(action);
|
|
1724
|
-
action.undo();
|
|
1725
|
-
this.notify();
|
|
1726
|
-
}
|
|
1727
|
-
redo() {
|
|
1728
|
-
let action = this.redoStack.pop();
|
|
1729
|
-
if (!action) return;
|
|
1730
|
-
this.undoStack.push(action);
|
|
1731
|
-
action.redo();
|
|
1732
|
-
this.notify();
|
|
1733
|
-
}
|
|
1734
|
-
clearRedoStack() {
|
|
1735
|
-
let length = this.redoStack.length;
|
|
1736
|
-
for (let i = 0; i < length; i++) {
|
|
1737
|
-
let action = this.redoStack[i];
|
|
1738
|
-
if (action) {
|
|
1739
|
-
action.dispose?.();
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
this.redoStack.length = 0;
|
|
1743
|
-
}
|
|
1744
|
-
};
|
|
1745
|
-
|
|
1746
1844
|
// src/History/PixelEngineConfig.ts
|
|
1747
1845
|
var PixelEngineConfig = class {
|
|
1748
1846
|
tileSize;
|
|
@@ -1760,51 +1858,210 @@ var PixelEngineConfig = class {
|
|
|
1760
1858
|
}
|
|
1761
1859
|
};
|
|
1762
1860
|
|
|
1763
|
-
// src/PixelData/
|
|
1764
|
-
function
|
|
1765
|
-
const
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1861
|
+
// src/PixelData/applyAlphaMaskToPixelData.ts
|
|
1862
|
+
function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
1863
|
+
const {
|
|
1864
|
+
x: targetX = 0,
|
|
1865
|
+
y: targetY = 0,
|
|
1866
|
+
w: width = dst.width,
|
|
1867
|
+
h: height = dst.height,
|
|
1868
|
+
alpha: globalAlpha = 255,
|
|
1869
|
+
mw,
|
|
1870
|
+
mx = 0,
|
|
1871
|
+
my = 0,
|
|
1872
|
+
invertMask = false
|
|
1873
|
+
} = opts;
|
|
1874
|
+
if (globalAlpha === 0) return;
|
|
1875
|
+
let x = targetX;
|
|
1876
|
+
let y = targetY;
|
|
1877
|
+
let w = width;
|
|
1878
|
+
let h = height;
|
|
1879
|
+
if (x < 0) {
|
|
1880
|
+
w += x;
|
|
1881
|
+
x = 0;
|
|
1882
|
+
}
|
|
1883
|
+
if (y < 0) {
|
|
1884
|
+
h += y;
|
|
1885
|
+
y = 0;
|
|
1886
|
+
}
|
|
1887
|
+
w = Math.min(w, dst.width - x);
|
|
1888
|
+
h = Math.min(h, dst.height - y);
|
|
1889
|
+
if (w <= 0) return;
|
|
1890
|
+
if (h <= 0) return;
|
|
1891
|
+
const mPitch = mw ?? width;
|
|
1892
|
+
if (mPitch <= 0) return;
|
|
1893
|
+
const maskHeight = mask.length / mPitch | 0;
|
|
1894
|
+
const startX = mx + (x - targetX);
|
|
1895
|
+
const startY = my + (y - targetY);
|
|
1896
|
+
const sX0 = Math.max(0, startX);
|
|
1897
|
+
const sY0 = Math.max(0, startY);
|
|
1898
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
1899
|
+
const sY1 = Math.min(maskHeight, startY + h);
|
|
1900
|
+
const finalW = sX1 - sX0;
|
|
1901
|
+
const finalH = sY1 - sY0;
|
|
1902
|
+
if (finalW <= 0) return;
|
|
1903
|
+
if (finalH <= 0) return;
|
|
1904
|
+
const xShift = sX0 - startX;
|
|
1905
|
+
const yShift = sY0 - startY;
|
|
1906
|
+
const dst32 = dst.data32;
|
|
1907
|
+
const dw = dst.width;
|
|
1908
|
+
const dStride = dw - finalW;
|
|
1909
|
+
const mStride = mPitch - finalW;
|
|
1910
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
1911
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
1912
|
+
for (let iy = 0; iy < h; iy++) {
|
|
1913
|
+
for (let ix = 0; ix < w; ix++) {
|
|
1914
|
+
const mVal = mask[mIdx];
|
|
1915
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1916
|
+
let weight = 0;
|
|
1917
|
+
if (effectiveM === 0) {
|
|
1918
|
+
weight = 0;
|
|
1919
|
+
} else if (effectiveM === 255) {
|
|
1920
|
+
weight = globalAlpha;
|
|
1921
|
+
} else if (globalAlpha === 255) {
|
|
1922
|
+
weight = effectiveM;
|
|
1923
|
+
} else {
|
|
1924
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
1925
|
+
}
|
|
1926
|
+
if (weight === 0) {
|
|
1927
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1928
|
+
} else if (weight !== 255) {
|
|
1929
|
+
const d = dst32[dIdx];
|
|
1930
|
+
const da = d >>> 24;
|
|
1931
|
+
if (da !== 0) {
|
|
1932
|
+
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
1933
|
+
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
dIdx++;
|
|
1937
|
+
mIdx++;
|
|
1938
|
+
}
|
|
1939
|
+
dIdx += dStride;
|
|
1940
|
+
mIdx += mStride;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
// src/History/PixelMutator/mutatorApplyAlphaMask.ts
|
|
1945
|
+
var defaults = {
|
|
1946
|
+
applyAlphaMaskToPixelData
|
|
1947
|
+
};
|
|
1948
|
+
var mutatorApplyAlphaMask = ((writer, deps = defaults) => {
|
|
1949
|
+
const {
|
|
1950
|
+
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults.applyAlphaMaskToPixelData
|
|
1951
|
+
} = deps;
|
|
1952
|
+
return {
|
|
1953
|
+
applyAlphaMask: (mask, opts = {}) => {
|
|
1954
|
+
let target = writer.target;
|
|
1955
|
+
const {
|
|
1956
|
+
x = 0,
|
|
1957
|
+
y = 0,
|
|
1958
|
+
w = writer.target.width,
|
|
1959
|
+
h = writer.target.height
|
|
1960
|
+
} = opts;
|
|
1961
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
1962
|
+
applyAlphaMaskToPixelData2(target, mask, opts);
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
});
|
|
1966
|
+
|
|
1967
|
+
// src/PixelData/applyBinaryMaskToPixelData.ts
|
|
1968
|
+
function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
1969
|
+
const {
|
|
1970
|
+
x: targetX = 0,
|
|
1971
|
+
y: targetY = 0,
|
|
1972
|
+
w: width = dst.width,
|
|
1973
|
+
h: height = dst.height,
|
|
1974
|
+
alpha = 255,
|
|
1975
|
+
mw,
|
|
1976
|
+
mx = 0,
|
|
1977
|
+
my = 0,
|
|
1978
|
+
invertMask = false
|
|
1979
|
+
} = opts;
|
|
1980
|
+
if (alpha === 0) return;
|
|
1981
|
+
let x = targetX;
|
|
1982
|
+
let y = targetY;
|
|
1983
|
+
let w = width;
|
|
1984
|
+
let h = height;
|
|
1985
|
+
if (x < 0) {
|
|
1986
|
+
w += x;
|
|
1987
|
+
x = 0;
|
|
1988
|
+
}
|
|
1989
|
+
if (y < 0) {
|
|
1990
|
+
h += y;
|
|
1991
|
+
y = 0;
|
|
1992
|
+
}
|
|
1993
|
+
w = Math.min(w, dst.width - x);
|
|
1994
|
+
h = Math.min(h, dst.height - y);
|
|
1995
|
+
if (w <= 0) return;
|
|
1996
|
+
if (h <= 0) return;
|
|
1997
|
+
const mPitch = mw ?? width;
|
|
1998
|
+
if (mPitch <= 0) return;
|
|
1999
|
+
const maskHeight = mask.length / mPitch | 0;
|
|
2000
|
+
const startX = mx + (x - targetX);
|
|
2001
|
+
const startY = my + (y - targetY);
|
|
2002
|
+
const sX0 = Math.max(0, startX);
|
|
2003
|
+
const sY0 = Math.max(0, startY);
|
|
2004
|
+
const sX1 = Math.min(mPitch, startX + w);
|
|
2005
|
+
const sY1 = Math.min(maskHeight, startY + h);
|
|
2006
|
+
const finalW = sX1 - sX0;
|
|
2007
|
+
const finalH = sY1 - sY0;
|
|
2008
|
+
if (finalW <= 0) return;
|
|
2009
|
+
if (finalH <= 0) return;
|
|
2010
|
+
const xShift = sX0 - startX;
|
|
2011
|
+
const yShift = sY0 - startY;
|
|
2012
|
+
const dst32 = dst.data32;
|
|
2013
|
+
const dw = dst.width;
|
|
2014
|
+
const dStride = dw - finalW;
|
|
2015
|
+
const mStride = mPitch - finalW;
|
|
2016
|
+
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2017
|
+
let mIdx = sY0 * mPitch + sX0;
|
|
2018
|
+
for (let iy = 0; iy < h; iy++) {
|
|
2019
|
+
for (let ix = 0; ix < w; ix++) {
|
|
2020
|
+
const mVal = mask[mIdx];
|
|
2021
|
+
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
2022
|
+
if (isMaskedOut) {
|
|
2023
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2024
|
+
} else if (alpha !== 255) {
|
|
2025
|
+
const d = dst32[dIdx];
|
|
2026
|
+
const da = d >>> 24;
|
|
2027
|
+
if (da !== 0) {
|
|
2028
|
+
const finalAlpha = da === 255 ? alpha : da * alpha + 128 >> 8;
|
|
2029
|
+
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
1802
2030
|
}
|
|
1803
2031
|
}
|
|
2032
|
+
dIdx++;
|
|
2033
|
+
mIdx++;
|
|
1804
2034
|
}
|
|
2035
|
+
dIdx += dStride;
|
|
2036
|
+
mIdx += mStride;
|
|
1805
2037
|
}
|
|
1806
2038
|
}
|
|
1807
|
-
|
|
2039
|
+
|
|
2040
|
+
// src/History/PixelMutator/mutatorApplyBinaryMask.ts
|
|
2041
|
+
var defaults2 = {
|
|
2042
|
+
applyBinaryMaskToPixelData
|
|
2043
|
+
};
|
|
2044
|
+
var mutatorApplyBinaryMask = ((writer, deps = defaults2) => {
|
|
2045
|
+
const {
|
|
2046
|
+
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults2.applyBinaryMaskToPixelData
|
|
2047
|
+
} = deps;
|
|
2048
|
+
return {
|
|
2049
|
+
applyBinaryMask: (mask, opts = {}) => {
|
|
2050
|
+
let target = writer.target;
|
|
2051
|
+
const {
|
|
2052
|
+
x = 0,
|
|
2053
|
+
y = 0,
|
|
2054
|
+
w = writer.target.width,
|
|
2055
|
+
h = writer.target.height
|
|
2056
|
+
} = opts;
|
|
2057
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2058
|
+
applyBinaryMaskToPixelData2(target, mask, opts);
|
|
2059
|
+
}
|
|
2060
|
+
};
|
|
2061
|
+
});
|
|
2062
|
+
|
|
2063
|
+
// src/Rect/getCircleBrushOrPencilBounds.ts
|
|
2064
|
+
function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight, out) {
|
|
1808
2065
|
const r = brushSize / 2;
|
|
1809
2066
|
const minOffset = -Math.ceil(r - 0.5);
|
|
1810
2067
|
const maxOffset = Math.floor(r - 0.5);
|
|
@@ -1818,104 +2075,137 @@ function getCircleBrushBounds(centerX, centerY, brushSize, targetWidth, targetHe
|
|
|
1818
2075
|
w: 0,
|
|
1819
2076
|
h: 0
|
|
1820
2077
|
};
|
|
1821
|
-
const cStartX =
|
|
1822
|
-
const cStartY =
|
|
1823
|
-
const cEndX =
|
|
1824
|
-
const cEndY =
|
|
2078
|
+
const cStartX = Math.max(0, startX);
|
|
2079
|
+
const cStartY = Math.max(0, startY);
|
|
2080
|
+
const cEndX = Math.min(targetWidth, endX);
|
|
2081
|
+
const cEndY = Math.min(targetHeight, endY);
|
|
2082
|
+
const w = cEndX - cStartX;
|
|
2083
|
+
const h = cEndY - cStartY;
|
|
1825
2084
|
res.x = cStartX;
|
|
1826
2085
|
res.y = cStartY;
|
|
1827
|
-
res.w =
|
|
1828
|
-
res.h =
|
|
2086
|
+
res.w = w < 0 ? 0 : w;
|
|
2087
|
+
res.h = h < 0 ? 0 : h;
|
|
1829
2088
|
return res;
|
|
1830
2089
|
}
|
|
1831
2090
|
|
|
1832
|
-
// src/
|
|
1833
|
-
|
|
1834
|
-
target;
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
2091
|
+
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
2092
|
+
function applyCircleBrushToPixelData(target, color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2093
|
+
const targetWidth = target.width;
|
|
2094
|
+
const targetHeight = target.height;
|
|
2095
|
+
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight);
|
|
2096
|
+
if (b.w <= 0 || b.h <= 0) return;
|
|
2097
|
+
const data32 = target.data32;
|
|
2098
|
+
const r = brushSize / 2;
|
|
2099
|
+
const rSqr = r * r;
|
|
2100
|
+
const invR = 1 / r;
|
|
2101
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
2102
|
+
const endX = b.x + b.w;
|
|
2103
|
+
const endY = b.y + b.h;
|
|
2104
|
+
const fCenterX = Math.floor(centerX);
|
|
2105
|
+
const fCenterY = Math.floor(centerY);
|
|
2106
|
+
const baseSrcAlpha = color >>> 24;
|
|
2107
|
+
const colorRGB = color & 16777215;
|
|
2108
|
+
const isOpaque = alpha === 255;
|
|
2109
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2110
|
+
for (let cy = b.y; cy < endY; cy++) {
|
|
2111
|
+
const relY = cy - fCenterY + centerOffset;
|
|
2112
|
+
const dySqr = relY * relY;
|
|
2113
|
+
const rowOffset = cy * targetWidth;
|
|
2114
|
+
for (let cx = b.x; cx < endX; cx++) {
|
|
2115
|
+
const relX = cx - fCenterX + centerOffset;
|
|
2116
|
+
const dSqr = relX * relX + dySqr;
|
|
2117
|
+
if (dSqr <= rSqr) {
|
|
2118
|
+
const idx = rowOffset + cx;
|
|
2119
|
+
let weight = alpha;
|
|
2120
|
+
const strength = fallOff(1 - Math.sqrt(dSqr) * invR);
|
|
2121
|
+
const maskVal = strength * 255 | 0;
|
|
2122
|
+
if (maskVal === 0) continue;
|
|
2123
|
+
if (isOpaque) {
|
|
2124
|
+
weight = maskVal;
|
|
2125
|
+
} else if (maskVal !== 255) {
|
|
2126
|
+
weight = maskVal * alpha + 128 >> 8;
|
|
2127
|
+
}
|
|
2128
|
+
let finalCol = color;
|
|
2129
|
+
if (weight < 255) {
|
|
2130
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2131
|
+
if (a === 0 && !isOverwrite) continue;
|
|
2132
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
2133
|
+
}
|
|
2134
|
+
data32[idx] = blendFn(finalCol, data32[idx]);
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
1872
2137
|
}
|
|
1873
|
-
}
|
|
2138
|
+
}
|
|
1874
2139
|
|
|
1875
2140
|
// src/History/PixelMutator/mutatorApplyCircleBrush.ts
|
|
1876
|
-
var
|
|
1877
|
-
|
|
2141
|
+
var defaults3 = {
|
|
2142
|
+
applyCircleBrushToPixelData,
|
|
2143
|
+
getCircleBrushOrPencilBounds
|
|
2144
|
+
};
|
|
2145
|
+
var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
|
|
2146
|
+
const {
|
|
2147
|
+
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
|
|
2148
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
|
|
2149
|
+
} = deps;
|
|
2150
|
+
const boundsOut = {
|
|
2151
|
+
x: 0,
|
|
2152
|
+
y: 0,
|
|
2153
|
+
w: 0,
|
|
2154
|
+
h: 0
|
|
2155
|
+
};
|
|
1878
2156
|
return {
|
|
1879
2157
|
applyCircleBrush(color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn) {
|
|
1880
|
-
const
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
);
|
|
1888
|
-
const { x, y, w, h } = circleBounds;
|
|
2158
|
+
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
|
|
2159
|
+
const {
|
|
2160
|
+
x,
|
|
2161
|
+
y,
|
|
2162
|
+
w,
|
|
2163
|
+
h
|
|
2164
|
+
} = bounds;
|
|
1889
2165
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
1890
|
-
|
|
1891
|
-
writer.target,
|
|
1892
|
-
color,
|
|
1893
|
-
centerX,
|
|
1894
|
-
centerY,
|
|
1895
|
-
brushSize,
|
|
1896
|
-
alpha,
|
|
1897
|
-
fallOff,
|
|
1898
|
-
blendFn,
|
|
1899
|
-
circleBounds
|
|
1900
|
-
);
|
|
2166
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
|
|
1901
2167
|
}
|
|
1902
2168
|
};
|
|
2169
|
+
});
|
|
2170
|
+
|
|
2171
|
+
// src/Algorithm/forEachLinePoint.ts
|
|
2172
|
+
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
2173
|
+
const dx = x1 - x0;
|
|
2174
|
+
const dy = y1 - y0;
|
|
2175
|
+
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
2176
|
+
if (steps === 0) {
|
|
2177
|
+
callback(x0, y0);
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
const xInc = dx / steps;
|
|
2181
|
+
const yInc = dy / steps;
|
|
2182
|
+
let curX = x0;
|
|
2183
|
+
let curY = y0;
|
|
2184
|
+
for (let i = 0; i <= steps; i++) {
|
|
2185
|
+
callback(curX, curY);
|
|
2186
|
+
curX += xInc;
|
|
2187
|
+
curY += yInc;
|
|
2188
|
+
}
|
|
1903
2189
|
}
|
|
1904
2190
|
|
|
1905
|
-
// src/PixelData/
|
|
1906
|
-
function
|
|
2191
|
+
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
2192
|
+
function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
|
|
1907
2193
|
const {
|
|
1908
2194
|
x: targetX = 0,
|
|
1909
2195
|
y: targetY = 0,
|
|
1910
2196
|
w: width = dst.width,
|
|
1911
2197
|
h: height = dst.height,
|
|
1912
2198
|
alpha: globalAlpha = 255,
|
|
1913
|
-
|
|
1914
|
-
mw,
|
|
2199
|
+
blendFn = sourceOverPerfect,
|
|
2200
|
+
mw = width,
|
|
1915
2201
|
mx = 0,
|
|
1916
2202
|
my = 0,
|
|
1917
2203
|
invertMask = false
|
|
1918
2204
|
} = opts;
|
|
2205
|
+
if (globalAlpha === 0 || !mask) return;
|
|
2206
|
+
const baseSrcAlpha = color >>> 24;
|
|
2207
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2208
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
1919
2209
|
let x = targetX;
|
|
1920
2210
|
let y = targetY;
|
|
1921
2211
|
let w = width;
|
|
@@ -1930,57 +2220,49 @@ function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1930
2220
|
}
|
|
1931
2221
|
const actualW = Math.min(w, dst.width - x);
|
|
1932
2222
|
const actualH = Math.min(h, dst.height - y);
|
|
1933
|
-
if (actualW <= 0 || actualH <= 0
|
|
1934
|
-
|
|
1935
|
-
|
|
2223
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2224
|
+
const dx = x - targetX | 0;
|
|
2225
|
+
const dy = y - targetY | 0;
|
|
1936
2226
|
const dst32 = dst.data32;
|
|
1937
2227
|
const dw = dst.width;
|
|
1938
|
-
const mPitch = mw
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
const
|
|
1942
|
-
let
|
|
1943
|
-
|
|
1944
|
-
const
|
|
1945
|
-
const mStride = mPitch - actualW;
|
|
2228
|
+
const mPitch = mw;
|
|
2229
|
+
let dIdx = y * dw + x | 0;
|
|
2230
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2231
|
+
const dStride = dw - actualW | 0;
|
|
2232
|
+
let mStride = mPitch - actualW | 0;
|
|
2233
|
+
const isOpaque = globalAlpha === 255;
|
|
2234
|
+
const colorRGB = color & 16777215;
|
|
1946
2235
|
for (let iy = 0; iy < actualH; iy++) {
|
|
1947
2236
|
for (let ix = 0; ix < actualW; ix++) {
|
|
1948
2237
|
const mVal = mask[mIdx];
|
|
2238
|
+
const effM = invertMask ? 255 - mVal : mVal;
|
|
2239
|
+
if (effM === 0) {
|
|
2240
|
+
dIdx++;
|
|
2241
|
+
mIdx++;
|
|
2242
|
+
continue;
|
|
2243
|
+
}
|
|
1949
2244
|
let weight = globalAlpha;
|
|
1950
|
-
if (
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
}
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
2245
|
+
if (isOpaque) {
|
|
2246
|
+
weight = effM;
|
|
2247
|
+
} else if (effM !== 255) {
|
|
2248
|
+
weight = effM * globalAlpha + 128 >> 8;
|
|
2249
|
+
}
|
|
2250
|
+
if (weight === 0) {
|
|
2251
|
+
dIdx++;
|
|
2252
|
+
mIdx++;
|
|
2253
|
+
continue;
|
|
2254
|
+
}
|
|
2255
|
+
let finalCol = color;
|
|
2256
|
+
if (weight < 255) {
|
|
2257
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2258
|
+
if (a === 0 && !isOverwrite) {
|
|
1963
2259
|
dIdx++;
|
|
1964
2260
|
mIdx++;
|
|
1965
2261
|
continue;
|
|
1966
2262
|
}
|
|
1967
|
-
|
|
1968
|
-
}
|
|
1969
|
-
if (weight === 0) {
|
|
1970
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1971
|
-
} else {
|
|
1972
|
-
const d = dst32[dIdx];
|
|
1973
|
-
const da = d >>> 24;
|
|
1974
|
-
let finalAlpha = da;
|
|
1975
|
-
if (da === 0) {
|
|
1976
|
-
} else if (weight === 255) {
|
|
1977
|
-
} else if (da === 255) {
|
|
1978
|
-
finalAlpha = weight;
|
|
1979
|
-
} else {
|
|
1980
|
-
finalAlpha = da * weight + 128 >> 8;
|
|
1981
|
-
}
|
|
1982
|
-
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2263
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
1983
2264
|
}
|
|
2265
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
1984
2266
|
dIdx++;
|
|
1985
2267
|
mIdx++;
|
|
1986
2268
|
}
|
|
@@ -1989,159 +2271,595 @@ function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1989
2271
|
}
|
|
1990
2272
|
}
|
|
1991
2273
|
|
|
1992
|
-
// src/
|
|
1993
|
-
function
|
|
2274
|
+
// src/Rect/getCircleBrushOrPencilStrokeBounds.ts
|
|
2275
|
+
function getCircleBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushSize, result) {
|
|
2276
|
+
const r = Math.ceil(brushSize / 2);
|
|
2277
|
+
const minX = Math.min(x0, x1) - r;
|
|
2278
|
+
const minY = Math.min(y0, y1) - r;
|
|
2279
|
+
const maxX = Math.max(x0, x1) + r;
|
|
2280
|
+
const maxY = Math.max(x0, y1) + r;
|
|
2281
|
+
result.x = Math.floor(minX);
|
|
2282
|
+
result.y = Math.floor(minY);
|
|
2283
|
+
result.w = Math.ceil(maxX - minX);
|
|
2284
|
+
result.h = Math.ceil(maxY - minY);
|
|
2285
|
+
return result;
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
// src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts
|
|
2289
|
+
var defaults4 = {
|
|
2290
|
+
forEachLinePoint,
|
|
2291
|
+
blendColorPixelDataAlphaMask,
|
|
2292
|
+
getCircleBrushOrPencilBounds,
|
|
2293
|
+
getCircleBrushOrPencilStrokeBounds
|
|
2294
|
+
};
|
|
2295
|
+
var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
2296
|
+
const {
|
|
2297
|
+
forEachLinePoint: forEachLinePoint2 = defaults4.forEachLinePoint,
|
|
2298
|
+
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults4.blendColorPixelDataAlphaMask,
|
|
2299
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults4.getCircleBrushOrPencilBounds,
|
|
2300
|
+
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults4.getCircleBrushOrPencilStrokeBounds
|
|
2301
|
+
} = deps;
|
|
2302
|
+
const strokeBoundsOut = {
|
|
2303
|
+
x: 0,
|
|
2304
|
+
y: 0,
|
|
2305
|
+
w: 0,
|
|
2306
|
+
h: 0
|
|
2307
|
+
};
|
|
2308
|
+
const circleBrushBounds = {
|
|
2309
|
+
x: 0,
|
|
2310
|
+
y: 0,
|
|
2311
|
+
w: 0,
|
|
2312
|
+
h: 0
|
|
2313
|
+
};
|
|
2314
|
+
const blendColorPixelOptions = {
|
|
2315
|
+
alpha: 255,
|
|
2316
|
+
blendFn: sourceOverPerfect,
|
|
2317
|
+
x: 0,
|
|
2318
|
+
y: 0,
|
|
2319
|
+
w: 0,
|
|
2320
|
+
h: 0
|
|
2321
|
+
};
|
|
1994
2322
|
return {
|
|
1995
|
-
|
|
1996
|
-
let target = writer.target;
|
|
2323
|
+
applyCircleBrushStroke(color, x0, y0, x1, y1, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
1997
2324
|
const {
|
|
1998
|
-
x
|
|
1999
|
-
y
|
|
2000
|
-
w
|
|
2001
|
-
h
|
|
2002
|
-
} =
|
|
2003
|
-
|
|
2004
|
-
|
|
2325
|
+
x: bx,
|
|
2326
|
+
y: by,
|
|
2327
|
+
w: bw,
|
|
2328
|
+
h: bh
|
|
2329
|
+
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
|
|
2330
|
+
if (bw <= 0 || bh <= 0) return;
|
|
2331
|
+
const mask = new Uint8Array(bw * bh);
|
|
2332
|
+
const r = brushSize / 2;
|
|
2333
|
+
const rSqr = r * r;
|
|
2334
|
+
const invR = 1 / r;
|
|
2335
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
2336
|
+
const targetWidth = writer.target.width;
|
|
2337
|
+
const targetHeight = writer.target.height;
|
|
2338
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2339
|
+
const {
|
|
2340
|
+
x: cbx,
|
|
2341
|
+
y: cby,
|
|
2342
|
+
w: cbw,
|
|
2343
|
+
h: cbh
|
|
2344
|
+
} = getCircleBrushOrPencilBounds2(px, py, brushSize, targetWidth, targetHeight, circleBrushBounds);
|
|
2345
|
+
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2346
|
+
const startX = Math.max(bx, cbx);
|
|
2347
|
+
const startY = Math.max(by, cby);
|
|
2348
|
+
const endX = Math.min(bx + bw, cbx + cbw);
|
|
2349
|
+
const endY = Math.min(by + bh, cby + cbh);
|
|
2350
|
+
const fPx = Math.floor(px);
|
|
2351
|
+
const fPy = Math.floor(py);
|
|
2352
|
+
for (let my = startY; my < endY; my++) {
|
|
2353
|
+
const dy = my - fPy + centerOffset;
|
|
2354
|
+
const dySqr = dy * dy;
|
|
2355
|
+
const maskRowOffset = (my - by) * bw;
|
|
2356
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
2357
|
+
const dx = mx - fPx + centerOffset;
|
|
2358
|
+
const dSqr = dx * dx + dySqr;
|
|
2359
|
+
if (dSqr <= rSqr) {
|
|
2360
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
2361
|
+
const dist = Math.sqrt(dSqr) * invR;
|
|
2362
|
+
const intensity = fallOff(1 - dist) * 255 | 0;
|
|
2363
|
+
if (intensity > mask[maskIdx]) {
|
|
2364
|
+
mask[maskIdx] = intensity;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
});
|
|
2370
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
2371
|
+
blendColorPixelOptions.alpha = alpha;
|
|
2372
|
+
blendColorPixelOptions.x = bx;
|
|
2373
|
+
blendColorPixelOptions.y = by;
|
|
2374
|
+
blendColorPixelOptions.w = bw;
|
|
2375
|
+
blendColorPixelOptions.h = bh;
|
|
2376
|
+
blendColorPixelDataAlphaMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
2005
2377
|
}
|
|
2006
2378
|
};
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
// src/ImageData/imageDataToUInt32Array.ts
|
|
2010
|
-
function imageDataToUInt32Array(imageData) {
|
|
2011
|
-
return new Uint32Array(
|
|
2012
|
-
imageData.data.buffer,
|
|
2013
|
-
imageData.data.byteOffset,
|
|
2014
|
-
// Shift right by 2 is a fast bitwise division by 4.
|
|
2015
|
-
imageData.data.byteLength >> 2
|
|
2016
|
-
);
|
|
2017
|
-
}
|
|
2379
|
+
});
|
|
2018
2380
|
|
|
2019
|
-
// src/PixelData/
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2381
|
+
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
2382
|
+
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
2383
|
+
const {
|
|
2384
|
+
x: targetX = 0,
|
|
2385
|
+
y: targetY = 0,
|
|
2386
|
+
w: width = dst.width,
|
|
2387
|
+
h: height = dst.height,
|
|
2388
|
+
alpha: globalAlpha = 255,
|
|
2389
|
+
blendFn = sourceOverPerfect,
|
|
2390
|
+
mw = width,
|
|
2391
|
+
mx = 0,
|
|
2392
|
+
my = 0,
|
|
2393
|
+
invertMask = false
|
|
2394
|
+
} = opts;
|
|
2395
|
+
if (globalAlpha === 0 || !mask) return;
|
|
2396
|
+
const baseSrcAlpha = color >>> 24;
|
|
2397
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2398
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2399
|
+
let x = targetX;
|
|
2400
|
+
let y = targetY;
|
|
2401
|
+
let w = width;
|
|
2402
|
+
let h = height;
|
|
2403
|
+
if (x < 0) {
|
|
2404
|
+
w += x;
|
|
2405
|
+
x = 0;
|
|
2028
2406
|
}
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2407
|
+
if (y < 0) {
|
|
2408
|
+
h += y;
|
|
2409
|
+
y = 0;
|
|
2032
2410
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2411
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2412
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2413
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2414
|
+
let baseColorWithGlobalAlpha = color;
|
|
2415
|
+
if (globalAlpha < 255) {
|
|
2416
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2417
|
+
if (a === 0 && !isOverwrite) return;
|
|
2418
|
+
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2036
2419
|
}
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2420
|
+
const dx = x - targetX | 0;
|
|
2421
|
+
const dy = y - targetY | 0;
|
|
2422
|
+
const dst32 = dst.data32;
|
|
2423
|
+
const dw = dst.width;
|
|
2424
|
+
const mPitch = mw;
|
|
2425
|
+
let dIdx = y * dw + x | 0;
|
|
2426
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2427
|
+
const dStride = dw - actualW | 0;
|
|
2428
|
+
const mStride = mPitch - actualW | 0;
|
|
2429
|
+
const skipVal = invertMask ? 1 : 0;
|
|
2430
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2431
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2432
|
+
if (mask[mIdx] === skipVal) {
|
|
2433
|
+
dIdx++;
|
|
2434
|
+
mIdx++;
|
|
2435
|
+
continue;
|
|
2436
|
+
}
|
|
2437
|
+
dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
|
|
2438
|
+
dIdx++;
|
|
2439
|
+
mIdx++;
|
|
2440
|
+
}
|
|
2441
|
+
dIdx += dStride;
|
|
2442
|
+
mIdx += mStride;
|
|
2049
2443
|
}
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
// src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
|
|
2447
|
+
var defaults5 = {
|
|
2448
|
+
forEachLinePoint,
|
|
2449
|
+
blendColorPixelDataBinaryMask,
|
|
2450
|
+
getCircleBrushOrPencilBounds,
|
|
2451
|
+
getCircleBrushOrPencilStrokeBounds
|
|
2050
2452
|
};
|
|
2453
|
+
var mutatorApplyCirclePencilStroke = ((writer, deps = defaults5) => {
|
|
2454
|
+
const {
|
|
2455
|
+
forEachLinePoint: forEachLinePoint2 = defaults5.forEachLinePoint,
|
|
2456
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults5.blendColorPixelDataBinaryMask,
|
|
2457
|
+
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults5.getCircleBrushOrPencilStrokeBounds,
|
|
2458
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
|
|
2459
|
+
} = deps;
|
|
2460
|
+
const strokeBoundsOut = {
|
|
2461
|
+
x: 0,
|
|
2462
|
+
y: 0,
|
|
2463
|
+
w: 0,
|
|
2464
|
+
h: 0
|
|
2465
|
+
};
|
|
2466
|
+
const circlePencilBounds = {
|
|
2467
|
+
x: 0,
|
|
2468
|
+
y: 0,
|
|
2469
|
+
w: 0,
|
|
2470
|
+
h: 0
|
|
2471
|
+
};
|
|
2472
|
+
const blendColorPixelOptions = {
|
|
2473
|
+
alpha: 255,
|
|
2474
|
+
blendFn: sourceOverPerfect,
|
|
2475
|
+
x: 0,
|
|
2476
|
+
y: 0,
|
|
2477
|
+
w: 0,
|
|
2478
|
+
h: 0
|
|
2479
|
+
};
|
|
2480
|
+
return {
|
|
2481
|
+
applyCirclePencilStroke(color, x0, y0, x1, y1, brushSize, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2482
|
+
const {
|
|
2483
|
+
x: bx,
|
|
2484
|
+
y: by,
|
|
2485
|
+
w: bw,
|
|
2486
|
+
h: bh
|
|
2487
|
+
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
|
|
2488
|
+
if (bw <= 0 || bh <= 0) return;
|
|
2489
|
+
const mask = new Uint8Array(bw * bh);
|
|
2490
|
+
const r = brushSize / 2;
|
|
2491
|
+
const rSqr = r * r;
|
|
2492
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
2493
|
+
const targetWidth = writer.target.width;
|
|
2494
|
+
const targetHeight = writer.target.height;
|
|
2495
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2496
|
+
const {
|
|
2497
|
+
x: cbx,
|
|
2498
|
+
y: cby,
|
|
2499
|
+
w: cbw,
|
|
2500
|
+
h: cbh
|
|
2501
|
+
} = getCircleBrushOrPencilBounds2(px, py, brushSize, targetWidth, targetHeight, circlePencilBounds);
|
|
2502
|
+
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2503
|
+
const startX = Math.max(bx, cbx);
|
|
2504
|
+
const startY = Math.max(by, cby);
|
|
2505
|
+
const endX = Math.min(bx + bw, cbx + cbw);
|
|
2506
|
+
const endY = Math.min(by + bh, cby + cbh);
|
|
2507
|
+
const fPx = Math.floor(px);
|
|
2508
|
+
const fPy = Math.floor(py);
|
|
2509
|
+
for (let my = startY; my < endY; my++) {
|
|
2510
|
+
const dy = my - fPy + centerOffset;
|
|
2511
|
+
const dySqr = dy * dy;
|
|
2512
|
+
const maskRowOffset = (my - by) * bw;
|
|
2513
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
2514
|
+
const dx = mx - fPx + centerOffset;
|
|
2515
|
+
const dSqr = dx * dx + dySqr;
|
|
2516
|
+
if (dSqr <= rSqr) {
|
|
2517
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
2518
|
+
mask[maskIdx] = 1;
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
});
|
|
2523
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
2524
|
+
blendColorPixelOptions.alpha = alpha;
|
|
2525
|
+
blendColorPixelOptions.x = bx;
|
|
2526
|
+
blendColorPixelOptions.y = by;
|
|
2527
|
+
blendColorPixelOptions.w = bw;
|
|
2528
|
+
blendColorPixelOptions.h = bh;
|
|
2529
|
+
blendColorPixelDataBinaryMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
2530
|
+
}
|
|
2531
|
+
};
|
|
2532
|
+
});
|
|
2533
|
+
|
|
2534
|
+
// src/Rect/getRectBrushOrPencilBounds.ts
|
|
2535
|
+
function getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight, out) {
|
|
2536
|
+
const startX = Math.floor(centerX - brushWidth / 2);
|
|
2537
|
+
const startY = Math.floor(centerY - brushHeight / 2);
|
|
2538
|
+
const endX = startX + brushWidth;
|
|
2539
|
+
const endY = startY + brushHeight;
|
|
2540
|
+
const res = out ?? {
|
|
2541
|
+
x: 0,
|
|
2542
|
+
y: 0,
|
|
2543
|
+
w: 0,
|
|
2544
|
+
h: 0
|
|
2545
|
+
};
|
|
2546
|
+
const cStartX = Math.max(0, startX);
|
|
2547
|
+
const cStartY = Math.max(0, startY);
|
|
2548
|
+
const cEndX = Math.min(targetWidth, endX);
|
|
2549
|
+
const cEndY = Math.min(targetHeight, endY);
|
|
2550
|
+
const w = cEndX - cStartX;
|
|
2551
|
+
const h = cEndY - cStartY;
|
|
2552
|
+
res.x = cStartX;
|
|
2553
|
+
res.y = cStartY;
|
|
2554
|
+
res.w = w < 0 ? 0 : w;
|
|
2555
|
+
res.h = h < 0 ? 0 : h;
|
|
2556
|
+
return res;
|
|
2557
|
+
}
|
|
2051
2558
|
|
|
2052
2559
|
// src/PixelData/applyRectBrushToPixelData.ts
|
|
2053
2560
|
function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2054
2561
|
const targetWidth = target.width;
|
|
2055
2562
|
const targetHeight = target.height;
|
|
2056
|
-
const b = bounds ??
|
|
2057
|
-
centerX,
|
|
2058
|
-
centerY,
|
|
2059
|
-
brushWidth,
|
|
2060
|
-
brushHeight,
|
|
2061
|
-
targetWidth,
|
|
2062
|
-
targetHeight
|
|
2063
|
-
);
|
|
2563
|
+
const b = bounds ?? getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight);
|
|
2064
2564
|
if (b.w <= 0 || b.h <= 0) return;
|
|
2065
2565
|
const data32 = target.data32;
|
|
2066
2566
|
const baseColor = color & 16777215;
|
|
2067
|
-
const
|
|
2567
|
+
const baseSrcAlpha = color >>> 24;
|
|
2568
|
+
const isOpaque = alpha === 255;
|
|
2068
2569
|
const invHalfW = 1 / (brushWidth / 2);
|
|
2069
2570
|
const invHalfH = 1 / (brushHeight / 2);
|
|
2571
|
+
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2572
|
+
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2573
|
+
const fCenterX = Math.floor(centerX);
|
|
2574
|
+
const fCenterY = Math.floor(centerY);
|
|
2070
2575
|
const endX = b.x + b.w;
|
|
2071
2576
|
const endY = b.y + b.h;
|
|
2577
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2072
2578
|
for (let py = b.y; py < endY; py++) {
|
|
2073
2579
|
const rowOffset = py * targetWidth;
|
|
2074
|
-
const dy =
|
|
2580
|
+
const dy = Math.abs(py - fCenterY + centerOffsetY) * invHalfH;
|
|
2075
2581
|
for (let px = b.x; px < endX; px++) {
|
|
2076
2582
|
const idx = rowOffset + px;
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2583
|
+
const dx = Math.abs(px - fCenterX + centerOffsetX) * invHalfW;
|
|
2584
|
+
const dist = dx > dy ? dx : dy;
|
|
2585
|
+
const strength = fallOff(dist);
|
|
2586
|
+
const maskVal = strength * 255 | 0;
|
|
2587
|
+
if (maskVal <= 0) continue;
|
|
2588
|
+
let weight = alpha;
|
|
2589
|
+
if (isOpaque) {
|
|
2590
|
+
weight = maskVal;
|
|
2591
|
+
} else if (maskVal !== 255) {
|
|
2592
|
+
weight = maskVal * alpha + 128 >> 8;
|
|
2593
|
+
}
|
|
2594
|
+
let finalCol = color;
|
|
2595
|
+
if (weight < 255) {
|
|
2596
|
+
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2597
|
+
if (a === 0 && !isOverwrite) continue;
|
|
2598
|
+
finalCol = (a << 24 | baseColor) >>> 0;
|
|
2086
2599
|
}
|
|
2600
|
+
data32[idx] = blendFn(finalCol, data32[idx]);
|
|
2087
2601
|
}
|
|
2088
2602
|
}
|
|
2089
2603
|
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2604
|
+
|
|
2605
|
+
// src/History/PixelMutator/mutatorApplyRectBrush.ts
|
|
2606
|
+
var defaults6 = {
|
|
2607
|
+
applyRectBrushToPixelData,
|
|
2608
|
+
getRectBrushOrPencilBounds
|
|
2609
|
+
};
|
|
2610
|
+
var mutatorApplyRectBrush = ((writer, deps = defaults6) => {
|
|
2611
|
+
const {
|
|
2612
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults6.applyRectBrushToPixelData,
|
|
2613
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults6.getRectBrushOrPencilBounds
|
|
2614
|
+
} = deps;
|
|
2615
|
+
const boundsOut = {
|
|
2616
|
+
x: 0,
|
|
2617
|
+
y: 0,
|
|
2618
|
+
w: 0,
|
|
2619
|
+
h: 0
|
|
2620
|
+
};
|
|
2621
|
+
return {
|
|
2622
|
+
applyRectBrush(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn) {
|
|
2623
|
+
const bounds = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, writer.target.width, writer.target.height, boundsOut);
|
|
2624
|
+
const {
|
|
2625
|
+
x,
|
|
2626
|
+
y,
|
|
2627
|
+
w,
|
|
2628
|
+
h
|
|
2629
|
+
} = bounds;
|
|
2630
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2631
|
+
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2632
|
+
}
|
|
2633
|
+
};
|
|
2634
|
+
});
|
|
2635
|
+
|
|
2636
|
+
// src/Rect/getRectBrushOrPencilStrokeBounds.ts
|
|
2637
|
+
function getRectBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushWidth, brushHeight, result) {
|
|
2638
|
+
const halfW = brushWidth / 2;
|
|
2639
|
+
const halfH = brushHeight / 2;
|
|
2640
|
+
const minX = Math.min(x0, x1) - halfW;
|
|
2641
|
+
const minY = Math.min(y0, y1) - halfH;
|
|
2642
|
+
const maxX = Math.max(x0, x1) + halfW;
|
|
2643
|
+
const maxY = Math.max(y0, y1) + halfH;
|
|
2644
|
+
result.x = Math.floor(minX);
|
|
2645
|
+
result.y = Math.floor(minY);
|
|
2646
|
+
result.w = Math.ceil(maxX - minX);
|
|
2647
|
+
result.h = Math.ceil(maxY - minY);
|
|
2648
|
+
return result;
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
// src/History/PixelMutator/mutatorApplyRectBrushStroke.ts
|
|
2652
|
+
var defaults7 = {
|
|
2653
|
+
forEachLinePoint,
|
|
2654
|
+
blendColorPixelDataAlphaMask,
|
|
2655
|
+
getRectBrushOrPencilBounds,
|
|
2656
|
+
getRectBrushOrPencilStrokeBounds
|
|
2657
|
+
};
|
|
2658
|
+
var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
|
|
2659
|
+
const {
|
|
2660
|
+
forEachLinePoint: forEachLinePoint2 = defaults7.forEachLinePoint,
|
|
2661
|
+
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults7.blendColorPixelDataAlphaMask,
|
|
2662
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults7.getRectBrushOrPencilBounds,
|
|
2663
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults7.getRectBrushOrPencilStrokeBounds
|
|
2664
|
+
} = deps;
|
|
2665
|
+
const strokeBoundsOut = {
|
|
2666
|
+
x: 0,
|
|
2667
|
+
y: 0,
|
|
2668
|
+
w: 0,
|
|
2669
|
+
h: 0
|
|
2670
|
+
};
|
|
2671
|
+
const rectBrushBounds = {
|
|
2672
|
+
x: 0,
|
|
2673
|
+
y: 0,
|
|
2674
|
+
w: 0,
|
|
2675
|
+
h: 0
|
|
2676
|
+
};
|
|
2677
|
+
const blendColorPixelOptions = {
|
|
2678
|
+
alpha: 255,
|
|
2679
|
+
blendFn: sourceOverPerfect,
|
|
2096
2680
|
x: 0,
|
|
2097
2681
|
y: 0,
|
|
2098
2682
|
w: 0,
|
|
2099
2683
|
h: 0
|
|
2100
2684
|
};
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2685
|
+
return {
|
|
2686
|
+
applyRectBrushStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
2687
|
+
const {
|
|
2688
|
+
x: bx,
|
|
2689
|
+
y: by,
|
|
2690
|
+
w: bw,
|
|
2691
|
+
h: bh
|
|
2692
|
+
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
2693
|
+
if (bw <= 0 || bh <= 0) return;
|
|
2694
|
+
const mask = new Uint8Array(bw * bh);
|
|
2695
|
+
const halfW = brushWidth / 2;
|
|
2696
|
+
const halfH = brushHeight / 2;
|
|
2697
|
+
const invHalfW = 1 / halfW;
|
|
2698
|
+
const invHalfH = 1 / halfH;
|
|
2699
|
+
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2700
|
+
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2701
|
+
const targetWidth = writer.target.width;
|
|
2702
|
+
const targetHeight = writer.target.height;
|
|
2703
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2704
|
+
const {
|
|
2705
|
+
x: rbx,
|
|
2706
|
+
y: rby,
|
|
2707
|
+
w: rbw,
|
|
2708
|
+
h: rbh
|
|
2709
|
+
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectBrushBounds);
|
|
2710
|
+
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
2711
|
+
const startX = Math.max(bx, rbx);
|
|
2712
|
+
const startY = Math.max(by, rby);
|
|
2713
|
+
const endX = Math.min(bx + bw, rbx + rbw);
|
|
2714
|
+
const endY = Math.min(by + bh, rby + rbh);
|
|
2715
|
+
const fPx = Math.floor(px);
|
|
2716
|
+
const fPy = Math.floor(py);
|
|
2717
|
+
for (let my = startY; my < endY; my++) {
|
|
2718
|
+
const dy = Math.abs(my - fPy + centerOffsetY) * invHalfH;
|
|
2719
|
+
const maskRowOffset = (my - by) * bw;
|
|
2720
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
2721
|
+
const dx = Math.abs(mx - fPx + centerOffsetX) * invHalfW;
|
|
2722
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
2723
|
+
const dist = dx > dy ? dx : dy;
|
|
2724
|
+
const strength = fallOff(dist);
|
|
2725
|
+
if (strength > 0) {
|
|
2726
|
+
const intensity = strength * 255 | 0;
|
|
2727
|
+
if (intensity > mask[maskIdx]) {
|
|
2728
|
+
mask[maskIdx] = intensity;
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
});
|
|
2734
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
2735
|
+
blendColorPixelOptions.alpha = alpha;
|
|
2736
|
+
blendColorPixelOptions.x = bx;
|
|
2737
|
+
blendColorPixelOptions.y = by;
|
|
2738
|
+
blendColorPixelOptions.w = bw;
|
|
2739
|
+
blendColorPixelOptions.h = bh;
|
|
2740
|
+
blendColorPixelDataAlphaMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
2741
|
+
}
|
|
2742
|
+
};
|
|
2743
|
+
});
|
|
2113
2744
|
|
|
2114
|
-
// src/History/PixelMutator/
|
|
2115
|
-
var
|
|
2116
|
-
|
|
2745
|
+
// src/History/PixelMutator/mutatorApplyRectPencil.ts
|
|
2746
|
+
var defaults8 = {
|
|
2747
|
+
applyRectBrushToPixelData,
|
|
2748
|
+
getRectBrushOrPencilBounds,
|
|
2749
|
+
fallOff: () => 1
|
|
2750
|
+
};
|
|
2751
|
+
var mutatorApplyRectPencil = ((writer, deps = defaults8) => {
|
|
2752
|
+
const {
|
|
2753
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults8.applyRectBrushToPixelData,
|
|
2754
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds,
|
|
2755
|
+
fallOff = defaults8.fallOff
|
|
2756
|
+
} = deps;
|
|
2757
|
+
const boundsOut = {
|
|
2758
|
+
x: 0,
|
|
2759
|
+
y: 0,
|
|
2760
|
+
w: 0,
|
|
2761
|
+
h: 0
|
|
2762
|
+
};
|
|
2117
2763
|
return {
|
|
2118
|
-
|
|
2119
|
-
const bounds =
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
boundsOut2
|
|
2127
|
-
);
|
|
2128
|
-
const { x, y, w, h } = bounds;
|
|
2764
|
+
applyRectPencil(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, blendFn) {
|
|
2765
|
+
const bounds = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, writer.target.width, writer.target.height, boundsOut);
|
|
2766
|
+
const {
|
|
2767
|
+
x,
|
|
2768
|
+
y,
|
|
2769
|
+
w,
|
|
2770
|
+
h
|
|
2771
|
+
} = bounds;
|
|
2129
2772
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2130
|
-
|
|
2131
|
-
writer.target,
|
|
2132
|
-
color,
|
|
2133
|
-
centerX,
|
|
2134
|
-
centerY,
|
|
2135
|
-
brushWidth,
|
|
2136
|
-
brushHeight,
|
|
2137
|
-
alpha,
|
|
2138
|
-
fallOff,
|
|
2139
|
-
blendFn,
|
|
2140
|
-
bounds
|
|
2141
|
-
);
|
|
2773
|
+
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2142
2774
|
}
|
|
2143
2775
|
};
|
|
2144
|
-
}
|
|
2776
|
+
});
|
|
2777
|
+
|
|
2778
|
+
// src/History/PixelMutator/mutatorApplyRectPencilStroke.ts
|
|
2779
|
+
var defaults9 = {
|
|
2780
|
+
forEachLinePoint,
|
|
2781
|
+
getRectBrushOrPencilBounds,
|
|
2782
|
+
getRectBrushOrPencilStrokeBounds,
|
|
2783
|
+
blendColorPixelDataBinaryMask
|
|
2784
|
+
};
|
|
2785
|
+
var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
|
|
2786
|
+
const {
|
|
2787
|
+
forEachLinePoint: forEachLinePoint2 = defaults9.forEachLinePoint,
|
|
2788
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults9.blendColorPixelDataBinaryMask,
|
|
2789
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
|
|
2790
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults9.getRectBrushOrPencilStrokeBounds
|
|
2791
|
+
} = deps;
|
|
2792
|
+
const strokeBoundsOut = {
|
|
2793
|
+
x: 0,
|
|
2794
|
+
y: 0,
|
|
2795
|
+
w: 0,
|
|
2796
|
+
h: 0
|
|
2797
|
+
};
|
|
2798
|
+
const rectPencilBounds = {
|
|
2799
|
+
x: 0,
|
|
2800
|
+
y: 0,
|
|
2801
|
+
w: 0,
|
|
2802
|
+
h: 0
|
|
2803
|
+
};
|
|
2804
|
+
const blendColorPixelOptions = {
|
|
2805
|
+
alpha: 255,
|
|
2806
|
+
blendFn: sourceOverPerfect,
|
|
2807
|
+
x: 0,
|
|
2808
|
+
y: 0,
|
|
2809
|
+
w: 0,
|
|
2810
|
+
h: 0
|
|
2811
|
+
};
|
|
2812
|
+
return {
|
|
2813
|
+
applyRectPencilStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2814
|
+
const {
|
|
2815
|
+
x: bx,
|
|
2816
|
+
y: by,
|
|
2817
|
+
w: bw,
|
|
2818
|
+
h: bh
|
|
2819
|
+
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
2820
|
+
if (bw <= 0 || bh <= 0) return;
|
|
2821
|
+
const mask = new Uint8Array(bw * bh);
|
|
2822
|
+
const halfW = brushWidth / 2;
|
|
2823
|
+
const halfH = brushHeight / 2;
|
|
2824
|
+
const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2825
|
+
const targetWidth = writer.target.width;
|
|
2826
|
+
const targetHeight = writer.target.height;
|
|
2827
|
+
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2828
|
+
const {
|
|
2829
|
+
x: rbx,
|
|
2830
|
+
y: rby,
|
|
2831
|
+
w: rbw,
|
|
2832
|
+
h: rbh
|
|
2833
|
+
} = getRectBrushOrPencilBounds2(px, py, brushWidth, brushHeight, targetWidth, targetHeight, rectPencilBounds);
|
|
2834
|
+
writer.accumulator.storeRegionBeforeState(rbx, rby, rbw, rbh);
|
|
2835
|
+
const startX = Math.max(bx, rbx);
|
|
2836
|
+
const startY = Math.max(by, rby);
|
|
2837
|
+
const endX = Math.min(bx + bw, rbx + rbw);
|
|
2838
|
+
const endY = Math.min(by + bh, rby + rbh);
|
|
2839
|
+
const fPx = Math.floor(px);
|
|
2840
|
+
const fPy = Math.floor(py);
|
|
2841
|
+
for (let my = startY; my < endY; my++) {
|
|
2842
|
+
const dy = Math.abs(my - fPy + centerOffset);
|
|
2843
|
+
const maskRowOffset = (my - by) * bw;
|
|
2844
|
+
for (let mx = startX; mx < endX; mx++) {
|
|
2845
|
+
const dx = Math.abs(mx - fPx + centerOffset);
|
|
2846
|
+
const maskIdx = maskRowOffset + (mx - bx);
|
|
2847
|
+
if (dx <= halfW && dy <= halfH) {
|
|
2848
|
+
mask[maskIdx] = 1;
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
});
|
|
2853
|
+
blendColorPixelOptions.blendFn = blendFn;
|
|
2854
|
+
blendColorPixelOptions.alpha = alpha;
|
|
2855
|
+
blendColorPixelOptions.x = bx;
|
|
2856
|
+
blendColorPixelOptions.y = by;
|
|
2857
|
+
blendColorPixelOptions.w = bw;
|
|
2858
|
+
blendColorPixelOptions.h = bh;
|
|
2859
|
+
blendColorPixelDataBinaryMask2(writer.target, color, mask, blendColorPixelOptions);
|
|
2860
|
+
}
|
|
2861
|
+
};
|
|
2862
|
+
});
|
|
2145
2863
|
|
|
2146
2864
|
// src/PixelData/blendColorPixelData.ts
|
|
2147
2865
|
function blendColorPixelData(dst, color, opts = {}) {
|
|
@@ -2151,22 +2869,13 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2151
2869
|
w: width = dst.width,
|
|
2152
2870
|
h: height = dst.height,
|
|
2153
2871
|
alpha: globalAlpha = 255,
|
|
2154
|
-
blendFn =
|
|
2155
|
-
mask,
|
|
2156
|
-
maskType = 0 /* ALPHA */,
|
|
2157
|
-
mw,
|
|
2158
|
-
mx = 0,
|
|
2159
|
-
my = 0,
|
|
2160
|
-
invertMask = false
|
|
2872
|
+
blendFn = sourceOverPerfect
|
|
2161
2873
|
} = opts;
|
|
2162
2874
|
if (globalAlpha === 0) return;
|
|
2163
2875
|
const baseSrcAlpha = color >>> 24;
|
|
2164
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
2876
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2165
2877
|
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2166
|
-
let x = targetX;
|
|
2167
|
-
let y = targetY;
|
|
2168
|
-
let w = width;
|
|
2169
|
-
let h = height;
|
|
2878
|
+
let x = targetX, y = targetY, w = width, h = height;
|
|
2170
2879
|
if (x < 0) {
|
|
2171
2880
|
w += x;
|
|
2172
2881
|
x = 0;
|
|
@@ -2178,76 +2887,33 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2178
2887
|
const actualW = Math.min(w, dst.width - x);
|
|
2179
2888
|
const actualH = Math.min(h, dst.height - y);
|
|
2180
2889
|
if (actualW <= 0 || actualH <= 0) return;
|
|
2890
|
+
let finalSrcColor = color;
|
|
2891
|
+
if (globalAlpha < 255) {
|
|
2892
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2893
|
+
if (a === 0 && !isOverwrite) return;
|
|
2894
|
+
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
2895
|
+
}
|
|
2181
2896
|
const dst32 = dst.data32;
|
|
2182
2897
|
const dw = dst.width;
|
|
2183
|
-
|
|
2184
|
-
const
|
|
2185
|
-
const dx = x - targetX;
|
|
2186
|
-
const dy = y - targetY;
|
|
2187
|
-
let dIdx = y * dw + x;
|
|
2188
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2189
|
-
const dStride = dw - actualW;
|
|
2190
|
-
const mStride = mPitch - actualW;
|
|
2898
|
+
let dIdx = y * dw + x | 0;
|
|
2899
|
+
const dStride = dw - actualW | 0;
|
|
2191
2900
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2192
2901
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2193
|
-
|
|
2194
|
-
if (mask) {
|
|
2195
|
-
const mVal = mask[mIdx];
|
|
2196
|
-
if (isAlphaMask) {
|
|
2197
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2198
|
-
if (effectiveM === 0) {
|
|
2199
|
-
dIdx++;
|
|
2200
|
-
mIdx++;
|
|
2201
|
-
continue;
|
|
2202
|
-
}
|
|
2203
|
-
if (globalAlpha === 255) {
|
|
2204
|
-
weight = effectiveM;
|
|
2205
|
-
} else if (effectiveM === 255) {
|
|
2206
|
-
weight = globalAlpha;
|
|
2207
|
-
} else {
|
|
2208
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2209
|
-
}
|
|
2210
|
-
} else {
|
|
2211
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2212
|
-
if (!isHit) {
|
|
2213
|
-
dIdx++;
|
|
2214
|
-
mIdx++;
|
|
2215
|
-
continue;
|
|
2216
|
-
}
|
|
2217
|
-
weight = globalAlpha;
|
|
2218
|
-
}
|
|
2219
|
-
if (weight === 0) {
|
|
2220
|
-
dIdx++;
|
|
2221
|
-
mIdx++;
|
|
2222
|
-
continue;
|
|
2223
|
-
}
|
|
2224
|
-
}
|
|
2225
|
-
let currentSrcColor = color;
|
|
2226
|
-
if (weight < 255) {
|
|
2227
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2228
|
-
if (baseSrcAlpha === 255) {
|
|
2229
|
-
currentSrcAlpha = weight;
|
|
2230
|
-
} else {
|
|
2231
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2232
|
-
}
|
|
2233
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2234
|
-
dIdx++;
|
|
2235
|
-
mIdx++;
|
|
2236
|
-
continue;
|
|
2237
|
-
}
|
|
2238
|
-
currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
2239
|
-
}
|
|
2240
|
-
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2902
|
+
dst32[dIdx] = blendFn(finalSrcColor, dst32[dIdx]);
|
|
2241
2903
|
dIdx++;
|
|
2242
|
-
mIdx++;
|
|
2243
2904
|
}
|
|
2244
2905
|
dIdx += dStride;
|
|
2245
|
-
mIdx += mStride;
|
|
2246
2906
|
}
|
|
2247
2907
|
}
|
|
2248
2908
|
|
|
2249
2909
|
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2250
|
-
|
|
2910
|
+
var defaults10 = {
|
|
2911
|
+
blendColorPixelData
|
|
2912
|
+
};
|
|
2913
|
+
var mutatorBlendColor = ((writer, deps = defaults10) => {
|
|
2914
|
+
const {
|
|
2915
|
+
blendColorPixelData: blendColorPixelData2 = defaults10.blendColorPixelData
|
|
2916
|
+
} = deps;
|
|
2251
2917
|
return {
|
|
2252
2918
|
blendColor(color, opts = {}) {
|
|
2253
2919
|
const {
|
|
@@ -2257,10 +2923,10 @@ function mutatorBlendColor(writer) {
|
|
|
2257
2923
|
h = writer.target.height
|
|
2258
2924
|
} = opts;
|
|
2259
2925
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2260
|
-
|
|
2926
|
+
blendColorPixelData2(writer.target, color, opts);
|
|
2261
2927
|
}
|
|
2262
2928
|
};
|
|
2263
|
-
}
|
|
2929
|
+
});
|
|
2264
2930
|
|
|
2265
2931
|
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2266
2932
|
function mutatorBlendPixel(writer) {
|
|
@@ -2294,13 +2960,7 @@ function blendPixelData(dst, src, opts) {
|
|
|
2294
2960
|
w: width = src.width,
|
|
2295
2961
|
h: height = src.height,
|
|
2296
2962
|
alpha: globalAlpha = 255,
|
|
2297
|
-
blendFn =
|
|
2298
|
-
mask,
|
|
2299
|
-
maskType = 0 /* ALPHA */,
|
|
2300
|
-
mw,
|
|
2301
|
-
mx = 0,
|
|
2302
|
-
my = 0,
|
|
2303
|
-
invertMask = false
|
|
2963
|
+
blendFn = sourceOverPerfect
|
|
2304
2964
|
} = opts;
|
|
2305
2965
|
if (globalAlpha === 0) return;
|
|
2306
2966
|
let x = targetX;
|
|
@@ -2338,91 +2998,48 @@ function blendPixelData(dst, src, opts) {
|
|
|
2338
2998
|
const src32 = src.data32;
|
|
2339
2999
|
const dw = dst.width;
|
|
2340
3000
|
const sw = src.width;
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
const
|
|
2344
|
-
const
|
|
2345
|
-
|
|
2346
|
-
let sIdx = sy * sw + sx;
|
|
2347
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2348
|
-
const dStride = dw - actualW;
|
|
2349
|
-
const sStride = sw - actualW;
|
|
2350
|
-
const mStride = mPitch - actualW;
|
|
3001
|
+
let dIdx = y * dw + x | 0;
|
|
3002
|
+
let sIdx = sy * sw + sx | 0;
|
|
3003
|
+
const dStride = dw - actualW | 0;
|
|
3004
|
+
const sStride = sw - actualW | 0;
|
|
3005
|
+
const isOpaque = globalAlpha === 255;
|
|
2351
3006
|
const isOverwrite = blendFn.isOverwrite;
|
|
2352
3007
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2353
3008
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2354
|
-
const
|
|
2355
|
-
const
|
|
2356
|
-
if (
|
|
3009
|
+
const srcCol = src32[sIdx];
|
|
3010
|
+
const srcAlpha = srcCol >>> 24;
|
|
3011
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
2357
3012
|
dIdx++;
|
|
2358
3013
|
sIdx++;
|
|
2359
|
-
mIdx++;
|
|
2360
3014
|
continue;
|
|
2361
3015
|
}
|
|
2362
|
-
let
|
|
2363
|
-
if (
|
|
2364
|
-
const
|
|
2365
|
-
if (
|
|
2366
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2367
|
-
if (effectiveM === 0) {
|
|
2368
|
-
dIdx++;
|
|
2369
|
-
sIdx++;
|
|
2370
|
-
mIdx++;
|
|
2371
|
-
continue;
|
|
2372
|
-
}
|
|
2373
|
-
if (globalAlpha === 255) {
|
|
2374
|
-
weight = effectiveM;
|
|
2375
|
-
} else if (effectiveM === 255) {
|
|
2376
|
-
weight = globalAlpha;
|
|
2377
|
-
} else {
|
|
2378
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2379
|
-
}
|
|
2380
|
-
} else {
|
|
2381
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2382
|
-
if (!isHit) {
|
|
2383
|
-
dIdx++;
|
|
2384
|
-
sIdx++;
|
|
2385
|
-
mIdx++;
|
|
2386
|
-
continue;
|
|
2387
|
-
}
|
|
2388
|
-
weight = globalAlpha;
|
|
2389
|
-
}
|
|
2390
|
-
if (weight === 0) {
|
|
2391
|
-
dIdx++;
|
|
2392
|
-
sIdx++;
|
|
2393
|
-
mIdx++;
|
|
2394
|
-
continue;
|
|
2395
|
-
}
|
|
2396
|
-
}
|
|
2397
|
-
let currentSrcColor = baseSrcColor;
|
|
2398
|
-
if (weight < 255) {
|
|
2399
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2400
|
-
if (baseSrcAlpha === 255) {
|
|
2401
|
-
currentSrcAlpha = weight;
|
|
2402
|
-
} else {
|
|
2403
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2404
|
-
}
|
|
2405
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
3016
|
+
let finalCol = srcCol;
|
|
3017
|
+
if (!isOpaque) {
|
|
3018
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
3019
|
+
if (a === 0 && !isOverwrite) {
|
|
2406
3020
|
dIdx++;
|
|
2407
3021
|
sIdx++;
|
|
2408
|
-
mIdx++;
|
|
2409
3022
|
continue;
|
|
2410
3023
|
}
|
|
2411
|
-
|
|
3024
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
2412
3025
|
}
|
|
2413
|
-
dst32[dIdx] = blendFn(
|
|
3026
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
2414
3027
|
dIdx++;
|
|
2415
3028
|
sIdx++;
|
|
2416
|
-
mIdx++;
|
|
2417
3029
|
}
|
|
2418
3030
|
dIdx += dStride;
|
|
2419
3031
|
sIdx += sStride;
|
|
2420
|
-
mIdx += mStride;
|
|
2421
3032
|
}
|
|
2422
3033
|
}
|
|
2423
3034
|
|
|
2424
3035
|
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
2425
|
-
|
|
3036
|
+
var defaults11 = {
|
|
3037
|
+
blendPixelData
|
|
3038
|
+
};
|
|
3039
|
+
var mutatorBlendPixelData = ((writer, deps = defaults11) => {
|
|
3040
|
+
const {
|
|
3041
|
+
blendPixelData: blendPixelData2 = defaults11.blendPixelData
|
|
3042
|
+
} = deps;
|
|
2426
3043
|
return {
|
|
2427
3044
|
blendPixelData(src, opts) {
|
|
2428
3045
|
const {
|
|
@@ -2432,12 +3049,13 @@ function mutatorBlendPixelData(writer) {
|
|
|
2432
3049
|
h = src.height
|
|
2433
3050
|
} = opts;
|
|
2434
3051
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2435
|
-
|
|
3052
|
+
blendPixelData2(writer.target, src, opts);
|
|
2436
3053
|
}
|
|
2437
3054
|
};
|
|
2438
|
-
}
|
|
3055
|
+
});
|
|
2439
3056
|
|
|
2440
3057
|
// src/PixelData/fillPixelData.ts
|
|
3058
|
+
var SCRATCH_RECT = makeClippedRect();
|
|
2441
3059
|
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
2442
3060
|
let x;
|
|
2443
3061
|
let y;
|
|
@@ -2459,34 +3077,57 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
|
2459
3077
|
w = dst.width;
|
|
2460
3078
|
h = dst.height;
|
|
2461
3079
|
}
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
}
|
|
2470
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2471
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2472
|
-
if (actualW <= 0 || actualH <= 0) {
|
|
2473
|
-
return;
|
|
2474
|
-
}
|
|
3080
|
+
const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT);
|
|
3081
|
+
if (!clip.inBounds) return;
|
|
3082
|
+
const {
|
|
3083
|
+
x: finalX,
|
|
3084
|
+
y: finalY,
|
|
3085
|
+
w: actualW,
|
|
3086
|
+
h: actualH
|
|
3087
|
+
} = clip;
|
|
2475
3088
|
const dst32 = dst.data32;
|
|
2476
3089
|
const dw = dst.width;
|
|
2477
|
-
if (actualW === dw && actualH === dst.height &&
|
|
3090
|
+
if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
|
|
2478
3091
|
dst32.fill(color);
|
|
2479
3092
|
return;
|
|
2480
3093
|
}
|
|
2481
3094
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2482
|
-
const start = (
|
|
3095
|
+
const start = (finalY + iy) * dw + finalX;
|
|
2483
3096
|
const end = start + actualW;
|
|
2484
3097
|
dst32.fill(color, start, end);
|
|
2485
3098
|
}
|
|
2486
3099
|
}
|
|
2487
3100
|
|
|
2488
|
-
// src/History/PixelMutator/
|
|
2489
|
-
|
|
3101
|
+
// src/History/PixelMutator/mutatorClear.ts
|
|
3102
|
+
var defaults12 = {
|
|
3103
|
+
fillPixelData
|
|
3104
|
+
};
|
|
3105
|
+
var mutatorClear = ((writer, deps = defaults12) => {
|
|
3106
|
+
const {
|
|
3107
|
+
fillPixelData: fillPixelData2 = defaults12.fillPixelData
|
|
3108
|
+
} = deps;
|
|
3109
|
+
return {
|
|
3110
|
+
clear(rect = {}) {
|
|
3111
|
+
const {
|
|
3112
|
+
x = 0,
|
|
3113
|
+
y = 0,
|
|
3114
|
+
w = writer.target.width,
|
|
3115
|
+
h = writer.target.height
|
|
3116
|
+
} = rect;
|
|
3117
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3118
|
+
fillPixelData2(writer.target, 0, x, y, w, h);
|
|
3119
|
+
}
|
|
3120
|
+
};
|
|
3121
|
+
});
|
|
3122
|
+
|
|
3123
|
+
// src/History/PixelMutator/mutatorFill.ts
|
|
3124
|
+
var defaults13 = {
|
|
3125
|
+
fillPixelData
|
|
3126
|
+
};
|
|
3127
|
+
var mutatorFill = ((writer, deps = defaults13) => {
|
|
3128
|
+
const {
|
|
3129
|
+
fillPixelData: fillPixelData2 = defaults13.fillPixelData
|
|
3130
|
+
} = deps;
|
|
2490
3131
|
return {
|
|
2491
3132
|
fill(color, rect = {}) {
|
|
2492
3133
|
const {
|
|
@@ -2496,12 +3137,13 @@ function mutatorFill(writer) {
|
|
|
2496
3137
|
h = writer.target.height
|
|
2497
3138
|
} = rect;
|
|
2498
3139
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2499
|
-
|
|
3140
|
+
fillPixelData2(writer.target, color, x, y, w, h);
|
|
2500
3141
|
}
|
|
2501
3142
|
};
|
|
2502
|
-
}
|
|
3143
|
+
});
|
|
2503
3144
|
|
|
2504
3145
|
// src/PixelData/invertPixelData.ts
|
|
3146
|
+
var SCRATCH_RECT2 = makeClippedRect();
|
|
2505
3147
|
function invertPixelData(pixelData, opts = {}) {
|
|
2506
3148
|
const dst = pixelData;
|
|
2507
3149
|
const {
|
|
@@ -2515,21 +3157,14 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
2515
3157
|
my = 0,
|
|
2516
3158
|
invertMask = false
|
|
2517
3159
|
} = opts;
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
w
|
|
2524
|
-
|
|
2525
|
-
}
|
|
2526
|
-
if (y < 0) {
|
|
2527
|
-
h += y;
|
|
2528
|
-
y = 0;
|
|
2529
|
-
}
|
|
2530
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2531
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2532
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3160
|
+
const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT2);
|
|
3161
|
+
if (!clip.inBounds) return;
|
|
3162
|
+
const {
|
|
3163
|
+
x,
|
|
3164
|
+
y,
|
|
3165
|
+
w: actualW,
|
|
3166
|
+
h: actualH
|
|
3167
|
+
} = clip;
|
|
2533
3168
|
const dst32 = dst.data32;
|
|
2534
3169
|
const dw = dst.width;
|
|
2535
3170
|
const mPitch = mw ?? width;
|
|
@@ -2565,54 +3200,137 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
2565
3200
|
}
|
|
2566
3201
|
|
|
2567
3202
|
// src/History/PixelMutator/mutatorInvert.ts
|
|
2568
|
-
|
|
3203
|
+
var defaults14 = {
|
|
3204
|
+
invertPixelData
|
|
3205
|
+
};
|
|
3206
|
+
var mutatorInvert = ((writer, deps = defaults14) => {
|
|
3207
|
+
const {
|
|
3208
|
+
invertPixelData: invertPixelData2 = defaults14.invertPixelData
|
|
3209
|
+
} = deps;
|
|
3210
|
+
return {
|
|
3211
|
+
invert(opts = {}) {
|
|
3212
|
+
const {
|
|
3213
|
+
x = 0,
|
|
3214
|
+
y = 0,
|
|
3215
|
+
w = writer.target.width,
|
|
3216
|
+
h = writer.target.height
|
|
3217
|
+
} = opts;
|
|
3218
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3219
|
+
invertPixelData2(writer.target, opts);
|
|
3220
|
+
}
|
|
3221
|
+
};
|
|
3222
|
+
});
|
|
3223
|
+
|
|
3224
|
+
// src/History/PixelMutator.ts
|
|
3225
|
+
function makeFullPixelMutator(writer) {
|
|
3226
|
+
return {
|
|
3227
|
+
...mutatorApplyAlphaMask(writer),
|
|
3228
|
+
...mutatorApplyBinaryMask(writer),
|
|
3229
|
+
...mutatorBlendPixelData(writer),
|
|
3230
|
+
...mutatorBlendColor(writer),
|
|
3231
|
+
...mutatorBlendPixel(writer),
|
|
3232
|
+
...mutatorFill(writer),
|
|
3233
|
+
...mutatorInvert(writer),
|
|
3234
|
+
...mutatorApplyCircleBrush(writer),
|
|
3235
|
+
...mutatorApplyCircleBrushStroke(writer),
|
|
3236
|
+
...mutatorApplyCirclePencilStroke(writer),
|
|
3237
|
+
...mutatorApplyRectBrush(writer),
|
|
3238
|
+
...mutatorApplyRectBrushStroke(writer),
|
|
3239
|
+
...mutatorApplyRectPencil(writer),
|
|
3240
|
+
...mutatorApplyRectPencilStroke(writer),
|
|
3241
|
+
...mutatorClear(writer)
|
|
3242
|
+
};
|
|
3243
|
+
}
|
|
3244
|
+
|
|
3245
|
+
// src/History/PixelWriter.ts
|
|
3246
|
+
var PixelWriter = class {
|
|
3247
|
+
target;
|
|
3248
|
+
historyManager;
|
|
3249
|
+
accumulator;
|
|
3250
|
+
config;
|
|
3251
|
+
mutator;
|
|
3252
|
+
constructor(target, mutatorFactory, {
|
|
3253
|
+
tileSize = 256,
|
|
3254
|
+
maxHistorySteps = 50,
|
|
3255
|
+
historyManager = new HistoryManager(maxHistorySteps)
|
|
3256
|
+
} = {}) {
|
|
3257
|
+
this.target = target;
|
|
3258
|
+
this.config = new PixelEngineConfig(tileSize);
|
|
3259
|
+
this.historyManager = historyManager;
|
|
3260
|
+
this.accumulator = new PixelAccumulator(target, this.config);
|
|
3261
|
+
this.mutator = mutatorFactory(this);
|
|
3262
|
+
}
|
|
3263
|
+
withHistory(cb) {
|
|
3264
|
+
cb(this.mutator);
|
|
3265
|
+
this.captureHistory();
|
|
3266
|
+
}
|
|
3267
|
+
captureHistory() {
|
|
3268
|
+
const beforeTiles = this.accumulator.beforeTiles;
|
|
3269
|
+
if (beforeTiles.length === 0) return;
|
|
3270
|
+
const afterTiles = this.accumulator.extractAfterTiles();
|
|
3271
|
+
const patch = {
|
|
3272
|
+
beforeTiles,
|
|
3273
|
+
afterTiles
|
|
3274
|
+
};
|
|
3275
|
+
const target = this.target;
|
|
3276
|
+
const tileSize = this.config.tileSize;
|
|
3277
|
+
const accumulator = this.accumulator;
|
|
3278
|
+
const action = {
|
|
3279
|
+
undo: () => applyPatchTiles(target, patch.beforeTiles, tileSize),
|
|
3280
|
+
redo: () => applyPatchTiles(target, patch.afterTiles, tileSize),
|
|
3281
|
+
dispose: () => accumulator.recyclePatch(patch)
|
|
3282
|
+
};
|
|
3283
|
+
this.historyManager.commit(action);
|
|
3284
|
+
this.accumulator.reset();
|
|
3285
|
+
}
|
|
3286
|
+
};
|
|
3287
|
+
|
|
3288
|
+
// src/History/PixelMutator/mutatorApplyCirclePencil.ts
|
|
3289
|
+
var defaults15 = {
|
|
3290
|
+
applyCircleBrushToPixelData,
|
|
3291
|
+
getCircleBrushOrPencilBounds,
|
|
3292
|
+
fallOff: () => 1
|
|
3293
|
+
};
|
|
3294
|
+
var mutatorApplyCirclePencil = ((writer, deps = defaults15) => {
|
|
3295
|
+
const {
|
|
3296
|
+
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults15.applyCircleBrushToPixelData,
|
|
3297
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults15.getCircleBrushOrPencilBounds,
|
|
3298
|
+
fallOff = defaults15.fallOff
|
|
3299
|
+
} = deps;
|
|
3300
|
+
const boundsOut = {
|
|
3301
|
+
x: 0,
|
|
3302
|
+
y: 0,
|
|
3303
|
+
w: 0,
|
|
3304
|
+
h: 0
|
|
3305
|
+
};
|
|
2569
3306
|
return {
|
|
2570
|
-
|
|
3307
|
+
applyCirclePencil(color, centerX, centerY, brushSize, alpha = 255, blendFn) {
|
|
3308
|
+
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
|
|
2571
3309
|
const {
|
|
2572
|
-
x
|
|
2573
|
-
y
|
|
2574
|
-
w
|
|
2575
|
-
h
|
|
2576
|
-
} =
|
|
3310
|
+
x,
|
|
3311
|
+
y,
|
|
3312
|
+
w,
|
|
3313
|
+
h
|
|
3314
|
+
} = bounds;
|
|
2577
3315
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2578
|
-
|
|
2579
|
-
}
|
|
2580
|
-
};
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
|
-
// src/History/PixelMutator.ts
|
|
2584
|
-
function makeFullPixelMutator(writer) {
|
|
2585
|
-
return {
|
|
2586
|
-
...mutatorApplyMask(writer),
|
|
2587
|
-
...mutatorBlendPixelData(writer),
|
|
2588
|
-
...mutatorBlendColor(writer),
|
|
2589
|
-
...mutatorBlendPixel(writer),
|
|
2590
|
-
...mutatorFill(writer),
|
|
2591
|
-
...mutatorInvert(writer),
|
|
2592
|
-
...mutatorApplyCircleBrush(writer),
|
|
2593
|
-
...mutatorApplyRectBrush(writer)
|
|
2594
|
-
};
|
|
2595
|
-
}
|
|
2596
|
-
|
|
2597
|
-
// src/ImageData/ReusableImageData.ts
|
|
2598
|
-
function makeReusableImageData() {
|
|
2599
|
-
let imageData = null;
|
|
2600
|
-
return function getReusableImageData(width, height) {
|
|
2601
|
-
const hasInstance = !!imageData;
|
|
2602
|
-
const widthMatches = hasInstance && imageData.width === width;
|
|
2603
|
-
const heightMatches = hasInstance && imageData.height === height;
|
|
2604
|
-
if (!widthMatches || !heightMatches) {
|
|
2605
|
-
imageData = new ImageData(width, height);
|
|
3316
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
|
|
2606
3317
|
}
|
|
2607
|
-
return imageData;
|
|
2608
3318
|
};
|
|
2609
|
-
}
|
|
3319
|
+
});
|
|
2610
3320
|
|
|
2611
3321
|
// src/ImageData/copyImageData.ts
|
|
2612
|
-
function copyImageData({
|
|
3322
|
+
function copyImageData({
|
|
3323
|
+
data,
|
|
3324
|
+
width,
|
|
3325
|
+
height
|
|
3326
|
+
}) {
|
|
2613
3327
|
return new ImageData(data.slice(), width, height);
|
|
2614
3328
|
}
|
|
2615
|
-
function copyImageDataLike({
|
|
3329
|
+
function copyImageDataLike({
|
|
3330
|
+
data,
|
|
3331
|
+
width,
|
|
3332
|
+
height
|
|
3333
|
+
}) {
|
|
2616
3334
|
return {
|
|
2617
3335
|
data: data.slice(),
|
|
2618
3336
|
width,
|
|
@@ -2620,20 +3338,15 @@ function copyImageDataLike({ data, width, height }) {
|
|
|
2620
3338
|
};
|
|
2621
3339
|
}
|
|
2622
3340
|
|
|
2623
|
-
// src/
|
|
2624
|
-
function
|
|
2625
|
-
const
|
|
2626
|
-
|
|
3341
|
+
// src/ImageData/ImageDataLike.ts
|
|
3342
|
+
function makeImageDataLike(width, height, data) {
|
|
3343
|
+
const size = width * height * 4;
|
|
3344
|
+
const buffer = data ? new Uint8ClampedArray(data.buffer, data.byteOffset, size) : new Uint8ClampedArray(size);
|
|
3345
|
+
return {
|
|
2627
3346
|
width,
|
|
2628
|
-
height
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
const mask = new Uint8Array(width * height);
|
|
2632
|
-
for (let i = 0; i < len; i++) {
|
|
2633
|
-
const val = data32[i];
|
|
2634
|
-
mask[i] = val >>> 24 & 255;
|
|
2635
|
-
}
|
|
2636
|
-
return mask;
|
|
3347
|
+
height,
|
|
3348
|
+
data: buffer
|
|
3349
|
+
};
|
|
2637
3350
|
}
|
|
2638
3351
|
|
|
2639
3352
|
// src/ImageData/imageDataToAlphaMask.ts
|
|
@@ -2643,11 +3356,7 @@ function imageDataToAlphaMask(imageData) {
|
|
|
2643
3356
|
height,
|
|
2644
3357
|
data
|
|
2645
3358
|
} = imageData;
|
|
2646
|
-
const data32 = new Uint32Array(
|
|
2647
|
-
data.buffer,
|
|
2648
|
-
data.byteOffset,
|
|
2649
|
-
data.byteLength >> 2
|
|
2650
|
-
);
|
|
3359
|
+
const data32 = new Uint32Array(data.buffer, data.byteOffset, data.byteLength >> 2);
|
|
2651
3360
|
const len = data32.length;
|
|
2652
3361
|
const mask = new Uint8Array(width * height);
|
|
2653
3362
|
for (let i = 0; i < len; i++) {
|
|
@@ -2660,12 +3369,25 @@ function imageDataToAlphaMask(imageData) {
|
|
|
2660
3369
|
// src/ImageData/imageDataToDataUrl.ts
|
|
2661
3370
|
var get = makeReusableCanvas();
|
|
2662
3371
|
function imageDataToDataUrl(imageData) {
|
|
2663
|
-
const {
|
|
3372
|
+
const {
|
|
3373
|
+
canvas,
|
|
3374
|
+
ctx
|
|
3375
|
+
} = get(imageData.width, imageData.height);
|
|
2664
3376
|
ctx.putImageData(imageData, 0, 0);
|
|
2665
3377
|
return canvas.toDataURL();
|
|
2666
3378
|
}
|
|
2667
3379
|
imageDataToDataUrl.reset = get.reset;
|
|
2668
3380
|
|
|
3381
|
+
// src/ImageData/imageDataToUInt32Array.ts
|
|
3382
|
+
function imageDataToUInt32Array(imageData) {
|
|
3383
|
+
return new Uint32Array(
|
|
3384
|
+
imageData.data.buffer,
|
|
3385
|
+
imageData.data.byteOffset,
|
|
3386
|
+
// Shift right by 2 is a fast bitwise division by 4.
|
|
3387
|
+
imageData.data.byteLength >> 2
|
|
3388
|
+
);
|
|
3389
|
+
}
|
|
3390
|
+
|
|
2669
3391
|
// src/ImageData/invertImageData.ts
|
|
2670
3392
|
function invertImageData(imageData) {
|
|
2671
3393
|
const data = imageData.data;
|
|
@@ -2708,7 +3430,11 @@ function resample32(srcData32, srcW, srcH, factor) {
|
|
|
2708
3430
|
// src/ImageData/resampleImageData.ts
|
|
2709
3431
|
function resampleImageData(source, factor) {
|
|
2710
3432
|
const src32 = new Uint32Array(source.data.buffer);
|
|
2711
|
-
const {
|
|
3433
|
+
const {
|
|
3434
|
+
data,
|
|
3435
|
+
width,
|
|
3436
|
+
height
|
|
3437
|
+
} = resample32(src32, source.width, source.height, factor);
|
|
2712
3438
|
const uint8ClampedArray = new Uint8ClampedArray(data.buffer);
|
|
2713
3439
|
return new ImageData(uint8ClampedArray, width, height);
|
|
2714
3440
|
}
|
|
@@ -2737,14 +3463,25 @@ function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0)
|
|
|
2737
3463
|
const srcX = x0 - offsetX;
|
|
2738
3464
|
const dstStart = (dstY * newWidth + x0) * 4;
|
|
2739
3465
|
const srcStart = (srcY * oldW + srcX) * 4;
|
|
2740
|
-
newData.set(
|
|
2741
|
-
oldData.subarray(srcStart, srcStart + rowLen),
|
|
2742
|
-
dstStart
|
|
2743
|
-
);
|
|
3466
|
+
newData.set(oldData.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
2744
3467
|
}
|
|
2745
3468
|
return result;
|
|
2746
3469
|
}
|
|
2747
3470
|
|
|
3471
|
+
// src/ImageData/ReusableImageData.ts
|
|
3472
|
+
function makeReusableImageData() {
|
|
3473
|
+
let imageData = null;
|
|
3474
|
+
return function getReusableImageData(width, height) {
|
|
3475
|
+
const hasInstance = !!imageData;
|
|
3476
|
+
const widthMatches = hasInstance && imageData.width === width;
|
|
3477
|
+
const heightMatches = hasInstance && imageData.height === height;
|
|
3478
|
+
if (!widthMatches || !heightMatches) {
|
|
3479
|
+
imageData = new ImageData(width, height);
|
|
3480
|
+
}
|
|
3481
|
+
return imageData;
|
|
3482
|
+
};
|
|
3483
|
+
}
|
|
3484
|
+
|
|
2748
3485
|
// src/ImageData/serialization.ts
|
|
2749
3486
|
function base64EncodeArrayBuffer(buffer) {
|
|
2750
3487
|
const uint8 = new Uint8Array(buffer);
|
|
@@ -2787,32 +3524,53 @@ function deserializeNullableImageData(serialized) {
|
|
|
2787
3524
|
return deserializeImageData(serialized);
|
|
2788
3525
|
}
|
|
2789
3526
|
|
|
3527
|
+
// src/ImageData/uInt32ArrayToImageData.ts
|
|
3528
|
+
function uInt32ArrayToImageData(data, width, height) {
|
|
3529
|
+
const buffer = data.buffer;
|
|
3530
|
+
const byteOffset = data.byteOffset;
|
|
3531
|
+
const byteLength = data.byteLength;
|
|
3532
|
+
const clampedArray = new Uint8ClampedArray(buffer, byteOffset, byteLength);
|
|
3533
|
+
return new ImageData(clampedArray, width, height);
|
|
3534
|
+
}
|
|
3535
|
+
function uInt32ArrayToImageDataLike(data, width, height) {
|
|
3536
|
+
const buffer = data.buffer;
|
|
3537
|
+
const byteOffset = data.byteOffset;
|
|
3538
|
+
const byteLength = data.byteLength;
|
|
3539
|
+
const clampedArray = new Uint8ClampedArray(buffer, byteOffset, byteLength);
|
|
3540
|
+
return {
|
|
3541
|
+
width,
|
|
3542
|
+
height,
|
|
3543
|
+
data: clampedArray
|
|
3544
|
+
};
|
|
3545
|
+
}
|
|
3546
|
+
|
|
2790
3547
|
// src/ImageData/writeImageData.ts
|
|
3548
|
+
var SCRATCH_BLIT2 = makeClippedBlit();
|
|
2791
3549
|
function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
|
|
2792
3550
|
const dstW = target.width;
|
|
2793
3551
|
const dstH = target.height;
|
|
2794
3552
|
const dstData = target.data;
|
|
2795
3553
|
const srcW = source.width;
|
|
2796
3554
|
const srcData = source.data;
|
|
2797
|
-
const
|
|
2798
|
-
|
|
2799
|
-
const
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3555
|
+
const clip = resolveBlitClipping(x, y, sx, sy, sw, sh, dstW, dstH, srcW, source.height, SCRATCH_BLIT2);
|
|
3556
|
+
if (!clip.inBounds) return;
|
|
3557
|
+
const {
|
|
3558
|
+
x: dstX,
|
|
3559
|
+
y: dstY,
|
|
3560
|
+
sx: srcX,
|
|
3561
|
+
sy: srcY,
|
|
3562
|
+
w: copyW,
|
|
3563
|
+
h: copyH
|
|
3564
|
+
} = clip;
|
|
2804
3565
|
const useMask = !!mask;
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
const
|
|
2809
|
-
const
|
|
2810
|
-
const srcXBase = sx + (x0 - x);
|
|
2811
|
-
const dstStart = (dstY * dstW + x0) * 4;
|
|
2812
|
-
const srcStart = (srcY * srcW + srcXBase) * 4;
|
|
3566
|
+
for (let row = 0; row < copyH; row++) {
|
|
3567
|
+
const currentDstY = dstY + row;
|
|
3568
|
+
const currentSrcY = srcY + row;
|
|
3569
|
+
const dstStart = (currentDstY * dstW + dstX) * 4;
|
|
3570
|
+
const srcStart = (currentSrcY * srcW + srcX) * 4;
|
|
2813
3571
|
if (useMask && mask) {
|
|
2814
|
-
for (let ix = 0; ix <
|
|
2815
|
-
const mi =
|
|
3572
|
+
for (let ix = 0; ix < copyW; ix++) {
|
|
3573
|
+
const mi = currentSrcY * srcW + (srcX + ix);
|
|
2816
3574
|
const alpha = mask[mi];
|
|
2817
3575
|
if (alpha === 0) {
|
|
2818
3576
|
continue;
|
|
@@ -2834,7 +3592,7 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
|
|
|
2834
3592
|
}
|
|
2835
3593
|
}
|
|
2836
3594
|
} else {
|
|
2837
|
-
const byteLen =
|
|
3595
|
+
const byteLen = copyW * 4;
|
|
2838
3596
|
const sub = srcData.subarray(srcStart, srcStart + byteLen);
|
|
2839
3597
|
dstData.set(sub, dstStart);
|
|
2840
3598
|
}
|
|
@@ -2842,24 +3600,52 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
|
|
|
2842
3600
|
}
|
|
2843
3601
|
|
|
2844
3602
|
// src/ImageData/writeImageDataBuffer.ts
|
|
3603
|
+
var SCRATCH_BLIT3 = makeClippedBlit();
|
|
2845
3604
|
function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
|
|
2846
|
-
const {
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
3605
|
+
const {
|
|
3606
|
+
x,
|
|
3607
|
+
y,
|
|
3608
|
+
w,
|
|
3609
|
+
h
|
|
3610
|
+
} = typeof _x === "object" ? _x : {
|
|
3611
|
+
x: _x,
|
|
3612
|
+
y: _y,
|
|
3613
|
+
w: _w,
|
|
3614
|
+
h: _h
|
|
3615
|
+
};
|
|
3616
|
+
const {
|
|
3617
|
+
width: dstW,
|
|
3618
|
+
height: dstH,
|
|
3619
|
+
data: dst
|
|
3620
|
+
} = imageData;
|
|
3621
|
+
const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT3);
|
|
3622
|
+
if (!clip.inBounds) return;
|
|
3623
|
+
const {
|
|
3624
|
+
x: dstX,
|
|
3625
|
+
y: dstY,
|
|
3626
|
+
sx: srcX,
|
|
3627
|
+
sy: srcY,
|
|
3628
|
+
w: copyW,
|
|
3629
|
+
h: copyH
|
|
3630
|
+
} = clip;
|
|
3631
|
+
const rowLen = copyW * 4;
|
|
3632
|
+
for (let row = 0; row < copyH; row++) {
|
|
3633
|
+
const dstStart = ((dstY + row) * dstW + dstX) * 4;
|
|
3634
|
+
const srcStart = ((srcY + row) * w + srcX) * 4;
|
|
3635
|
+
dst.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
|
|
3639
|
+
// src/IndexedImage/getIndexedImageColorCounts.ts
|
|
3640
|
+
function getIndexedImageColorCounts(indexedImage) {
|
|
3641
|
+
const data = indexedImage.data;
|
|
3642
|
+
const palette = indexedImage.palette;
|
|
3643
|
+
const frequencies = new Int32Array(palette.length);
|
|
3644
|
+
for (let i = 0; i < data.length; i++) {
|
|
3645
|
+
const colorIndex = data[i];
|
|
3646
|
+
frequencies[colorIndex]++;
|
|
2862
3647
|
}
|
|
3648
|
+
return frequencies;
|
|
2863
3649
|
}
|
|
2864
3650
|
|
|
2865
3651
|
// src/IndexedImage/IndexedImage.ts
|
|
@@ -2925,13 +3711,7 @@ var IndexedImage = class _IndexedImage {
|
|
|
2925
3711
|
indexedData[i] = id;
|
|
2926
3712
|
}
|
|
2927
3713
|
const palette = Uint32Array.from(colorMap.keys());
|
|
2928
|
-
return new _IndexedImage(
|
|
2929
|
-
width,
|
|
2930
|
-
height,
|
|
2931
|
-
indexedData,
|
|
2932
|
-
palette,
|
|
2933
|
-
transparentPalletIndex
|
|
2934
|
-
);
|
|
3714
|
+
return new _IndexedImage(width, height, indexedData, palette, transparentPalletIndex);
|
|
2935
3715
|
}
|
|
2936
3716
|
/**
|
|
2937
3717
|
* Retrieves the 32-bit packed color value at the given coordinates.
|
|
@@ -2946,21 +3726,13 @@ var IndexedImage = class _IndexedImage {
|
|
|
2946
3726
|
}
|
|
2947
3727
|
};
|
|
2948
3728
|
|
|
2949
|
-
// src/IndexedImage/getIndexedImageColorCounts.ts
|
|
2950
|
-
function getIndexedImageColorCounts(indexedImage) {
|
|
2951
|
-
const data = indexedImage.data;
|
|
2952
|
-
const palette = indexedImage.palette;
|
|
2953
|
-
const frequencies = new Int32Array(palette.length);
|
|
2954
|
-
for (let i = 0; i < data.length; i++) {
|
|
2955
|
-
const colorIndex = data[i];
|
|
2956
|
-
frequencies[colorIndex]++;
|
|
2957
|
-
}
|
|
2958
|
-
return frequencies;
|
|
2959
|
-
}
|
|
2960
|
-
|
|
2961
3729
|
// src/IndexedImage/indexedImageToAverageColor.ts
|
|
2962
3730
|
function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
|
|
2963
|
-
const {
|
|
3731
|
+
const {
|
|
3732
|
+
data,
|
|
3733
|
+
palette,
|
|
3734
|
+
transparentPalletIndex
|
|
3735
|
+
} = indexedImage;
|
|
2964
3736
|
const counts = new Uint32Array(palette.length);
|
|
2965
3737
|
for (let i = 0; i < data.length; i++) {
|
|
2966
3738
|
const id = data[i];
|
|
@@ -3000,26 +3772,14 @@ function indexedImageToAverageColor(indexedImage, includeTransparent = false) {
|
|
|
3000
3772
|
return packColor(r, g, b, a);
|
|
3001
3773
|
}
|
|
3002
3774
|
|
|
3003
|
-
// src/IndexedImage/
|
|
3004
|
-
function
|
|
3005
|
-
const {
|
|
3006
|
-
source.data,
|
|
3007
|
-
source.width,
|
|
3008
|
-
source.height,
|
|
3009
|
-
factor
|
|
3010
|
-
);
|
|
3011
|
-
return new IndexedImage(
|
|
3775
|
+
// src/IndexedImage/indexedImageToImageData.ts
|
|
3776
|
+
function indexedImageToImageData(indexedImage) {
|
|
3777
|
+
const {
|
|
3012
3778
|
width,
|
|
3013
3779
|
height,
|
|
3014
3780
|
data,
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
);
|
|
3018
|
-
}
|
|
3019
|
-
|
|
3020
|
-
// src/IndexedImage/indexedImageToImageData.ts
|
|
3021
|
-
function indexedImageToImageData(indexedImage) {
|
|
3022
|
-
const { width, height, data, palette } = indexedImage;
|
|
3781
|
+
palette
|
|
3782
|
+
} = indexedImage;
|
|
3023
3783
|
const result = new ImageData(width, height);
|
|
3024
3784
|
const data32 = new Uint32Array(result.data.buffer);
|
|
3025
3785
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -3030,6 +3790,16 @@ function indexedImageToImageData(indexedImage) {
|
|
|
3030
3790
|
return result;
|
|
3031
3791
|
}
|
|
3032
3792
|
|
|
3793
|
+
// src/IndexedImage/resampleIndexedImage.ts
|
|
3794
|
+
function resampleIndexedImage(source, factor) {
|
|
3795
|
+
const {
|
|
3796
|
+
data,
|
|
3797
|
+
width,
|
|
3798
|
+
height
|
|
3799
|
+
} = resample32(source.data, source.width, source.height, factor);
|
|
3800
|
+
return new IndexedImage(width, height, data, source.palette, source.transparentPalletIndex);
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3033
3803
|
// src/Input/fileInputChangeToImageData.ts
|
|
3034
3804
|
async function fileInputChangeToImageData(event) {
|
|
3035
3805
|
const target = event.target;
|
|
@@ -3053,23 +3823,11 @@ async function fileToImageData(file) {
|
|
|
3053
3823
|
let bitmap = null;
|
|
3054
3824
|
try {
|
|
3055
3825
|
bitmap = await createImageBitmap(file);
|
|
3056
|
-
const canvas = new OffscreenCanvas(
|
|
3057
|
-
bitmap.width,
|
|
3058
|
-
bitmap.height
|
|
3059
|
-
);
|
|
3826
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
3060
3827
|
const ctx = canvas.getContext("2d");
|
|
3061
3828
|
if (!ctx) throw new Error(OFFSCREEN_CANVAS_CTX_FAILED);
|
|
3062
|
-
ctx.drawImage(
|
|
3063
|
-
|
|
3064
|
-
0,
|
|
3065
|
-
0
|
|
3066
|
-
);
|
|
3067
|
-
return ctx.getImageData(
|
|
3068
|
-
0,
|
|
3069
|
-
0,
|
|
3070
|
-
bitmap.width,
|
|
3071
|
-
bitmap.height
|
|
3072
|
-
);
|
|
3829
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
3830
|
+
return ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
3073
3831
|
} finally {
|
|
3074
3832
|
bitmap?.close();
|
|
3075
3833
|
}
|
|
@@ -3077,125 +3835,495 @@ async function fileToImageData(file) {
|
|
|
3077
3835
|
|
|
3078
3836
|
// src/Input/getSupportedRasterFormats.ts
|
|
3079
3837
|
var formatsPromise = null;
|
|
3080
|
-
var defaultRasterMimes = [
|
|
3081
|
-
"image/png",
|
|
3082
|
-
"image/jpeg",
|
|
3083
|
-
"image/webp",
|
|
3084
|
-
"image/avif",
|
|
3085
|
-
"image/gif",
|
|
3086
|
-
"image/bmp"
|
|
3087
|
-
];
|
|
3838
|
+
var defaultRasterMimes = ["image/png", "image/jpeg", "image/webp", "image/avif", "image/gif", "image/bmp"];
|
|
3088
3839
|
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
3089
3840
|
if (formatsPromise) {
|
|
3090
3841
|
return formatsPromise;
|
|
3091
3842
|
}
|
|
3092
|
-
const probeCanvas = async () => {
|
|
3093
|
-
const canvas = new OffscreenCanvas(1, 1);
|
|
3094
|
-
const results = await Promise.all(
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3843
|
+
const probeCanvas = async () => {
|
|
3844
|
+
const canvas = new OffscreenCanvas(1, 1);
|
|
3845
|
+
const results = await Promise.all(rasterMimes.map(async (mime) => {
|
|
3846
|
+
try {
|
|
3847
|
+
const blob = await canvas.convertToBlob({
|
|
3848
|
+
type: mime
|
|
3849
|
+
});
|
|
3850
|
+
return blob.type === mime ? mime : null;
|
|
3851
|
+
} catch {
|
|
3852
|
+
return null;
|
|
3853
|
+
}
|
|
3854
|
+
}));
|
|
3855
|
+
return results.filter((type) => {
|
|
3856
|
+
return type !== null;
|
|
3857
|
+
});
|
|
3858
|
+
};
|
|
3859
|
+
formatsPromise = probeCanvas().catch((error) => {
|
|
3860
|
+
formatsPromise = null;
|
|
3861
|
+
throw error;
|
|
3862
|
+
});
|
|
3863
|
+
return formatsPromise;
|
|
3864
|
+
}
|
|
3865
|
+
|
|
3866
|
+
// src/Mask/applyBinaryMaskToAlphaMask.ts
|
|
3867
|
+
function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWidth, opts = {}) {
|
|
3868
|
+
const {
|
|
3869
|
+
x: targetX = 0,
|
|
3870
|
+
y: targetY = 0,
|
|
3871
|
+
w: reqWidth = 0,
|
|
3872
|
+
h: reqHeight = 0,
|
|
3873
|
+
mx = 0,
|
|
3874
|
+
my = 0,
|
|
3875
|
+
invertMask = false
|
|
3876
|
+
} = opts;
|
|
3877
|
+
if (dstWidth <= 0) return;
|
|
3878
|
+
if (binaryMaskSrc.length === 0) return;
|
|
3879
|
+
if (srcWidth <= 0) return;
|
|
3880
|
+
const dstHeight = alphaMaskDst.length / dstWidth | 0;
|
|
3881
|
+
const srcHeight = binaryMaskSrc.length / srcWidth | 0;
|
|
3882
|
+
if (dstHeight <= 0) return;
|
|
3883
|
+
if (srcHeight <= 0) return;
|
|
3884
|
+
const dstX0 = Math.max(0, targetX);
|
|
3885
|
+
const dstY0 = Math.max(0, targetY);
|
|
3886
|
+
const dstX1 = reqWidth > 0 ? Math.min(dstWidth, targetX + reqWidth) : dstWidth;
|
|
3887
|
+
const dstY1 = reqHeight > 0 ? Math.min(dstHeight, targetY + reqHeight) : dstHeight;
|
|
3888
|
+
if (dstX0 >= dstX1) return;
|
|
3889
|
+
if (dstY0 >= dstY1) return;
|
|
3890
|
+
const srcX0 = mx + (dstX0 - targetX);
|
|
3891
|
+
const srcY0 = my + (dstY0 - targetY);
|
|
3892
|
+
if (srcX0 >= srcWidth) return;
|
|
3893
|
+
if (srcY0 >= srcHeight) return;
|
|
3894
|
+
if (srcX0 + (dstX1 - dstX0) <= 0) return;
|
|
3895
|
+
if (srcY0 + (dstY1 - dstY0) <= 0) return;
|
|
3896
|
+
const iterW = Math.min(dstX1 - dstX0, srcWidth - srcX0);
|
|
3897
|
+
const iterH = Math.min(dstY1 - dstY0, srcHeight - srcY0);
|
|
3898
|
+
let dstIdx = dstY0 * dstWidth + dstX0;
|
|
3899
|
+
let srcIdx = srcY0 * srcWidth + srcX0;
|
|
3900
|
+
if (invertMask) {
|
|
3901
|
+
for (let row = 0; row < iterH; row++) {
|
|
3902
|
+
const dstEnd = dstIdx + iterW;
|
|
3903
|
+
let d = dstIdx;
|
|
3904
|
+
let s = srcIdx;
|
|
3905
|
+
while (d < dstEnd) {
|
|
3906
|
+
if (binaryMaskSrc[s] !== 0) {
|
|
3907
|
+
alphaMaskDst[d] = 0;
|
|
3908
|
+
}
|
|
3909
|
+
d++;
|
|
3910
|
+
s++;
|
|
3911
|
+
}
|
|
3912
|
+
dstIdx += dstWidth;
|
|
3913
|
+
srcIdx += srcWidth;
|
|
3914
|
+
}
|
|
3915
|
+
} else {
|
|
3916
|
+
for (let row = 0; row < iterH; row++) {
|
|
3917
|
+
const dstEnd = dstIdx + iterW;
|
|
3918
|
+
let d = dstIdx;
|
|
3919
|
+
let s = srcIdx;
|
|
3920
|
+
while (d < dstEnd) {
|
|
3921
|
+
if (binaryMaskSrc[s] === 0) {
|
|
3922
|
+
alphaMaskDst[d] = 0;
|
|
3923
|
+
}
|
|
3924
|
+
d++;
|
|
3925
|
+
s++;
|
|
3926
|
+
}
|
|
3927
|
+
dstIdx += dstWidth;
|
|
3928
|
+
srcIdx += srcWidth;
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
|
|
3933
|
+
// src/Mask/copyMask.ts
|
|
3934
|
+
function copyMask(src) {
|
|
3935
|
+
return src.slice();
|
|
3936
|
+
}
|
|
3937
|
+
|
|
3938
|
+
// src/Mask/invertMask.ts
|
|
3939
|
+
function invertBinaryMask(dst) {
|
|
3940
|
+
const len = dst.length;
|
|
3941
|
+
for (let i = 0; i < len; i++) {
|
|
3942
|
+
dst[i] = dst[i] === 0 ? 1 : 0;
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3945
|
+
function invertAlphaMask(dst) {
|
|
3946
|
+
const len = dst.length;
|
|
3947
|
+
for (let i = 0; i < len; i++) {
|
|
3948
|
+
dst[i] = 255 - dst[i];
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
|
|
3952
|
+
// src/Mask/mergeAlphaMasks.ts
|
|
3953
|
+
function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
3954
|
+
const {
|
|
3955
|
+
x: targetX = 0,
|
|
3956
|
+
y: targetY = 0,
|
|
3957
|
+
w: width = 0,
|
|
3958
|
+
h: height = 0,
|
|
3959
|
+
alpha: globalAlpha = 255,
|
|
3960
|
+
mx = 0,
|
|
3961
|
+
my = 0,
|
|
3962
|
+
invertMask = false
|
|
3963
|
+
} = opts;
|
|
3964
|
+
const dstHeight = dst.length / dstWidth | 0;
|
|
3965
|
+
const srcHeight = src.length / srcWidth | 0;
|
|
3966
|
+
if (width <= 0) return;
|
|
3967
|
+
if (height <= 0) return;
|
|
3968
|
+
if (globalAlpha === 0) return;
|
|
3969
|
+
const startX = Math.max(0, -targetX, -mx);
|
|
3970
|
+
const startY = Math.max(0, -targetY, -my);
|
|
3971
|
+
const endX = Math.min(width, dstWidth - targetX, srcWidth - mx);
|
|
3972
|
+
const endY = Math.min(height, dstHeight - targetY, srcHeight - my);
|
|
3973
|
+
if (startX >= endX) return;
|
|
3974
|
+
if (startY >= endY) return;
|
|
3975
|
+
for (let iy = startY; iy < endY; iy++) {
|
|
3976
|
+
const dy = targetY + iy;
|
|
3977
|
+
const sy = my + iy;
|
|
3978
|
+
let dIdx = dy * dstWidth + targetX + startX;
|
|
3979
|
+
let sIdx = sy * srcWidth + mx + startX;
|
|
3980
|
+
for (let ix = startX; ix < endX; ix++) {
|
|
3981
|
+
const rawM = src[sIdx];
|
|
3982
|
+
const effectiveM = invertMask ? 255 - rawM : rawM;
|
|
3983
|
+
let weight = 0;
|
|
3984
|
+
if (effectiveM === 0) {
|
|
3985
|
+
weight = 0;
|
|
3986
|
+
} else if (effectiveM === 255) {
|
|
3987
|
+
weight = globalAlpha;
|
|
3988
|
+
} else if (globalAlpha === 255) {
|
|
3989
|
+
weight = effectiveM;
|
|
3990
|
+
} else {
|
|
3991
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
3992
|
+
}
|
|
3993
|
+
if (weight !== 255) {
|
|
3994
|
+
if (weight === 0) {
|
|
3995
|
+
dst[dIdx] = 0;
|
|
3996
|
+
} else {
|
|
3997
|
+
const da = dst[dIdx];
|
|
3998
|
+
if (da === 255) {
|
|
3999
|
+
dst[dIdx] = weight;
|
|
4000
|
+
} else if (da !== 0) {
|
|
4001
|
+
dst[dIdx] = da * weight + 128 >> 8;
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
sIdx++;
|
|
4006
|
+
dIdx++;
|
|
4007
|
+
}
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
|
|
4011
|
+
// src/Mask/mergeBinaryMasks.ts
|
|
4012
|
+
function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
4013
|
+
const {
|
|
4014
|
+
x: targetX = 0,
|
|
4015
|
+
y: targetY = 0,
|
|
4016
|
+
w: width = 0,
|
|
4017
|
+
h: height = 0,
|
|
4018
|
+
mx = 0,
|
|
4019
|
+
my = 0,
|
|
4020
|
+
invertMask = false
|
|
4021
|
+
} = opts;
|
|
4022
|
+
if (dstWidth <= 0) return;
|
|
4023
|
+
if (srcWidth <= 0) return;
|
|
4024
|
+
const dstHeight = dst.length / dstWidth | 0;
|
|
4025
|
+
const srcHeight = src.length / srcWidth | 0;
|
|
4026
|
+
let x = targetX;
|
|
4027
|
+
let y = targetY;
|
|
4028
|
+
let w = width;
|
|
4029
|
+
let h = height;
|
|
4030
|
+
if (x < 0) {
|
|
4031
|
+
w += x;
|
|
4032
|
+
x = 0;
|
|
4033
|
+
}
|
|
4034
|
+
if (y < 0) {
|
|
4035
|
+
h += y;
|
|
4036
|
+
y = 0;
|
|
4037
|
+
}
|
|
4038
|
+
w = Math.min(w, dstWidth - x);
|
|
4039
|
+
h = Math.min(h, dstHeight - y);
|
|
4040
|
+
if (w <= 0) return;
|
|
4041
|
+
if (h <= 0) return;
|
|
4042
|
+
const startX = mx + (x - targetX);
|
|
4043
|
+
const startY = my + (y - targetY);
|
|
4044
|
+
const sX0 = Math.max(0, startX);
|
|
4045
|
+
const sY0 = Math.max(0, startY);
|
|
4046
|
+
const sX1 = Math.min(srcWidth, startX + w);
|
|
4047
|
+
const sY1 = Math.min(srcHeight, startY + h);
|
|
4048
|
+
const finalW = sX1 - sX0;
|
|
4049
|
+
const finalH = sY1 - sY0;
|
|
4050
|
+
if (finalW <= 0) return;
|
|
4051
|
+
if (finalH <= 0) return;
|
|
4052
|
+
const xShift = sX0 - startX;
|
|
4053
|
+
const yShift = sY0 - startY;
|
|
4054
|
+
const dStride = dstWidth - finalW;
|
|
4055
|
+
const sStride = srcWidth - finalW;
|
|
4056
|
+
let dIdx = (y + yShift) * dstWidth + (x + xShift);
|
|
4057
|
+
let sIdx = sY0 * srcWidth + sX0;
|
|
4058
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
4059
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
4060
|
+
const mVal = src[sIdx];
|
|
4061
|
+
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
4062
|
+
if (isMaskedOut) {
|
|
4063
|
+
dst[dIdx] = 0;
|
|
4064
|
+
}
|
|
4065
|
+
dIdx++;
|
|
4066
|
+
sIdx++;
|
|
4067
|
+
}
|
|
4068
|
+
dIdx += dStride;
|
|
4069
|
+
sIdx += sStride;
|
|
4070
|
+
}
|
|
3120
4071
|
}
|
|
3121
4072
|
|
|
3122
|
-
// src/
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
4073
|
+
// src/PixelData/PixelData.ts
|
|
4074
|
+
var PixelData = class _PixelData {
|
|
4075
|
+
data32;
|
|
4076
|
+
imageData;
|
|
4077
|
+
width;
|
|
4078
|
+
height;
|
|
4079
|
+
constructor(imageData) {
|
|
4080
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
4081
|
+
this.imageData = imageData;
|
|
4082
|
+
this.width = imageData.width;
|
|
4083
|
+
this.height = imageData.height;
|
|
3127
4084
|
}
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
4085
|
+
set(imageData) {
|
|
4086
|
+
;
|
|
4087
|
+
this.imageData = imageData;
|
|
4088
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
4089
|
+
this.width = imageData.width;
|
|
4090
|
+
this.height = imageData.height;
|
|
3133
4091
|
}
|
|
3134
|
-
|
|
4092
|
+
// should only be used for debug and testing
|
|
4093
|
+
copy() {
|
|
4094
|
+
const data = this.imageData.data;
|
|
4095
|
+
const buffer = new Uint8ClampedArray(data);
|
|
4096
|
+
const Ctor = this.imageData.constructor;
|
|
4097
|
+
const isCtorValid = typeof Ctor === "function";
|
|
4098
|
+
let newImageData;
|
|
4099
|
+
if (isCtorValid && Ctor !== Object) {
|
|
4100
|
+
const ImageConstructor = Ctor;
|
|
4101
|
+
newImageData = new ImageConstructor(buffer, this.width, this.height);
|
|
4102
|
+
} else {
|
|
4103
|
+
newImageData = {
|
|
4104
|
+
width: this.width,
|
|
4105
|
+
height: this.height,
|
|
4106
|
+
data: buffer
|
|
4107
|
+
};
|
|
4108
|
+
}
|
|
4109
|
+
return new _PixelData(newImageData);
|
|
4110
|
+
}
|
|
4111
|
+
};
|
|
3135
4112
|
|
|
3136
|
-
// src/
|
|
3137
|
-
function
|
|
4113
|
+
// src/PixelData/blendPixelDataAlphaMask.ts
|
|
4114
|
+
function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
3138
4115
|
const {
|
|
3139
4116
|
x: targetX = 0,
|
|
3140
4117
|
y: targetY = 0,
|
|
3141
|
-
|
|
3142
|
-
|
|
4118
|
+
sx: sourceX = 0,
|
|
4119
|
+
sy: sourceY = 0,
|
|
4120
|
+
w: width = src.width,
|
|
4121
|
+
h: height = src.height,
|
|
3143
4122
|
alpha: globalAlpha = 255,
|
|
3144
|
-
|
|
3145
|
-
mw,
|
|
4123
|
+
blendFn = sourceOverPerfect,
|
|
4124
|
+
mw = src.width,
|
|
3146
4125
|
mx = 0,
|
|
3147
4126
|
my = 0,
|
|
3148
4127
|
invertMask = false
|
|
3149
4128
|
} = opts;
|
|
3150
|
-
if (
|
|
3151
|
-
|
|
4129
|
+
if (globalAlpha === 0) return;
|
|
4130
|
+
let x = targetX;
|
|
4131
|
+
let y = targetY;
|
|
4132
|
+
let sx = sourceX;
|
|
4133
|
+
let sy = sourceY;
|
|
4134
|
+
let w = width;
|
|
4135
|
+
let h = height;
|
|
4136
|
+
if (sx < 0) {
|
|
4137
|
+
x -= sx;
|
|
4138
|
+
w += sx;
|
|
4139
|
+
sx = 0;
|
|
3152
4140
|
}
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
4141
|
+
if (sy < 0) {
|
|
4142
|
+
y -= sy;
|
|
4143
|
+
h += sy;
|
|
4144
|
+
sy = 0;
|
|
4145
|
+
}
|
|
4146
|
+
w = Math.min(w, src.width - sx);
|
|
4147
|
+
h = Math.min(h, src.height - sy);
|
|
4148
|
+
if (x < 0) {
|
|
4149
|
+
sx -= x;
|
|
4150
|
+
w += x;
|
|
4151
|
+
x = 0;
|
|
4152
|
+
}
|
|
4153
|
+
if (y < 0) {
|
|
4154
|
+
sy -= y;
|
|
4155
|
+
h += y;
|
|
4156
|
+
y = 0;
|
|
4157
|
+
}
|
|
4158
|
+
const actualW = Math.min(w, dst.width - x);
|
|
4159
|
+
const actualH = Math.min(h, dst.height - y);
|
|
4160
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
4161
|
+
const dw = dst.width;
|
|
4162
|
+
const sw = src.width;
|
|
4163
|
+
const mPitch = mw;
|
|
4164
|
+
const dx = x - targetX | 0;
|
|
4165
|
+
const dy = y - targetY | 0;
|
|
4166
|
+
const dst32 = dst.data32;
|
|
4167
|
+
const src32 = src.data32;
|
|
4168
|
+
let dIdx = y * dw + x | 0;
|
|
4169
|
+
let sIdx = sy * sw + sx | 0;
|
|
4170
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
4171
|
+
const dStride = dw - actualW | 0;
|
|
4172
|
+
const sStride = sw - actualW | 0;
|
|
4173
|
+
const mStride = mPitch - actualW | 0;
|
|
4174
|
+
const isOpaque = globalAlpha === 255;
|
|
4175
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
4176
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
4177
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
4178
|
+
const mVal = alphaMask[mIdx];
|
|
4179
|
+
const effM = invertMask ? 255 - mVal : mVal;
|
|
4180
|
+
if (effM === 0) {
|
|
4181
|
+
dIdx++;
|
|
4182
|
+
sIdx++;
|
|
4183
|
+
mIdx++;
|
|
4184
|
+
continue;
|
|
4185
|
+
}
|
|
4186
|
+
const srcCol = src32[sIdx];
|
|
4187
|
+
const srcAlpha = srcCol >>> 24;
|
|
4188
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
4189
|
+
dIdx++;
|
|
4190
|
+
sIdx++;
|
|
4191
|
+
mIdx++;
|
|
3165
4192
|
continue;
|
|
3166
4193
|
}
|
|
3167
|
-
const dIdx = dy * dstWidth + dx;
|
|
3168
|
-
const sIdx = sy * sPitch + sx;
|
|
3169
|
-
const mVal = src[sIdx];
|
|
3170
4194
|
let weight = globalAlpha;
|
|
3171
|
-
if (
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
4195
|
+
if (isOpaque) {
|
|
4196
|
+
weight = effM;
|
|
4197
|
+
} else if (effM !== 255) {
|
|
4198
|
+
weight = effM * globalAlpha + 128 >> 8;
|
|
4199
|
+
}
|
|
4200
|
+
if (weight === 0) {
|
|
4201
|
+
dIdx++;
|
|
4202
|
+
sIdx++;
|
|
4203
|
+
mIdx++;
|
|
4204
|
+
continue;
|
|
4205
|
+
}
|
|
4206
|
+
let finalCol = srcCol;
|
|
4207
|
+
if (weight < 255) {
|
|
4208
|
+
const a = srcAlpha * weight + 128 >> 8;
|
|
4209
|
+
if (a === 0 && !isOverwrite) {
|
|
4210
|
+
dIdx++;
|
|
4211
|
+
sIdx++;
|
|
4212
|
+
mIdx++;
|
|
3182
4213
|
continue;
|
|
3183
4214
|
}
|
|
3184
|
-
|
|
4215
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3185
4216
|
}
|
|
3186
|
-
|
|
3187
|
-
|
|
4217
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
4218
|
+
dIdx++;
|
|
4219
|
+
sIdx++;
|
|
4220
|
+
mIdx++;
|
|
4221
|
+
}
|
|
4222
|
+
dIdx += dStride;
|
|
4223
|
+
sIdx += sStride;
|
|
4224
|
+
mIdx += mStride;
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
// src/PixelData/blendPixelDataBinaryMask.ts
|
|
4229
|
+
function blendPixelDataBinaryMask(dst, src, binaryMask, opts) {
|
|
4230
|
+
const {
|
|
4231
|
+
x: targetX = 0,
|
|
4232
|
+
y: targetY = 0,
|
|
4233
|
+
sx: sourceX = 0,
|
|
4234
|
+
sy: sourceY = 0,
|
|
4235
|
+
w: width = src.width,
|
|
4236
|
+
h: height = src.height,
|
|
4237
|
+
alpha: globalAlpha = 255,
|
|
4238
|
+
blendFn = sourceOverPerfect,
|
|
4239
|
+
mw = src.width,
|
|
4240
|
+
mx = 0,
|
|
4241
|
+
my = 0,
|
|
4242
|
+
invertMask = false
|
|
4243
|
+
} = opts;
|
|
4244
|
+
if (globalAlpha === 0) return;
|
|
4245
|
+
let x = targetX;
|
|
4246
|
+
let y = targetY;
|
|
4247
|
+
let sx = sourceX;
|
|
4248
|
+
let sy = sourceY;
|
|
4249
|
+
let w = width;
|
|
4250
|
+
let h = height;
|
|
4251
|
+
if (sx < 0) {
|
|
4252
|
+
x -= sx;
|
|
4253
|
+
w += sx;
|
|
4254
|
+
sx = 0;
|
|
4255
|
+
}
|
|
4256
|
+
if (sy < 0) {
|
|
4257
|
+
y -= sy;
|
|
4258
|
+
h += sy;
|
|
4259
|
+
sy = 0;
|
|
4260
|
+
}
|
|
4261
|
+
w = Math.min(w, src.width - sx);
|
|
4262
|
+
h = Math.min(h, src.height - sy);
|
|
4263
|
+
if (x < 0) {
|
|
4264
|
+
sx -= x;
|
|
4265
|
+
w += x;
|
|
4266
|
+
x = 0;
|
|
4267
|
+
}
|
|
4268
|
+
if (y < 0) {
|
|
4269
|
+
sy -= y;
|
|
4270
|
+
h += y;
|
|
4271
|
+
y = 0;
|
|
4272
|
+
}
|
|
4273
|
+
const actualW = Math.min(w, dst.width - x);
|
|
4274
|
+
const actualH = Math.min(h, dst.height - y);
|
|
4275
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
4276
|
+
const dx = x - targetX | 0;
|
|
4277
|
+
const dy = y - targetY | 0;
|
|
4278
|
+
const dst32 = dst.data32;
|
|
4279
|
+
const src32 = src.data32;
|
|
4280
|
+
const dw = dst.width;
|
|
4281
|
+
const sw = src.width;
|
|
4282
|
+
const mPitch = mw;
|
|
4283
|
+
let dIdx = y * dw + x | 0;
|
|
4284
|
+
let sIdx = sy * sw + sx | 0;
|
|
4285
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
4286
|
+
const dStride = dw - actualW | 0;
|
|
4287
|
+
const sStride = sw - actualW | 0;
|
|
4288
|
+
const mStride = mPitch - actualW | 0;
|
|
4289
|
+
const skipVal = invertMask ? 1 : 0;
|
|
4290
|
+
const isOpaque = globalAlpha === 255;
|
|
4291
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
4292
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
4293
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
4294
|
+
if (binaryMask[mIdx] === skipVal) {
|
|
4295
|
+
dIdx++;
|
|
4296
|
+
sIdx++;
|
|
4297
|
+
mIdx++;
|
|
3188
4298
|
continue;
|
|
3189
4299
|
}
|
|
3190
|
-
const
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
4300
|
+
const srcCol = src32[sIdx];
|
|
4301
|
+
const srcAlpha = srcCol >>> 24;
|
|
4302
|
+
if (srcAlpha === 0 && !isOverwrite) {
|
|
4303
|
+
dIdx++;
|
|
4304
|
+
sIdx++;
|
|
4305
|
+
mIdx++;
|
|
4306
|
+
continue;
|
|
4307
|
+
}
|
|
4308
|
+
let finalCol = srcCol;
|
|
4309
|
+
if (!isOpaque) {
|
|
4310
|
+
const a = srcAlpha * globalAlpha + 128 >> 8;
|
|
4311
|
+
if (a === 0 && !isOverwrite) {
|
|
4312
|
+
dIdx++;
|
|
4313
|
+
sIdx++;
|
|
4314
|
+
mIdx++;
|
|
4315
|
+
continue;
|
|
4316
|
+
}
|
|
4317
|
+
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3197
4318
|
}
|
|
4319
|
+
dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
|
|
4320
|
+
dIdx++;
|
|
4321
|
+
sIdx++;
|
|
4322
|
+
mIdx++;
|
|
3198
4323
|
}
|
|
4324
|
+
dIdx += dStride;
|
|
4325
|
+
sIdx += sStride;
|
|
4326
|
+
mIdx += mStride;
|
|
3199
4327
|
}
|
|
3200
4328
|
}
|
|
3201
4329
|
|
|
@@ -3205,32 +4333,40 @@ function clearPixelData(dst, rect) {
|
|
|
3205
4333
|
}
|
|
3206
4334
|
|
|
3207
4335
|
// src/PixelData/extractPixelDataBuffer.ts
|
|
4336
|
+
var SCRATCH_BLIT4 = makeClippedBlit();
|
|
3208
4337
|
function extractPixelDataBuffer(source, _x, _y, _w, _h) {
|
|
3209
|
-
const {
|
|
4338
|
+
const {
|
|
4339
|
+
x,
|
|
4340
|
+
y,
|
|
4341
|
+
w,
|
|
4342
|
+
h
|
|
4343
|
+
} = typeof _x === "object" ? _x : {
|
|
4344
|
+
x: _x,
|
|
4345
|
+
y: _y,
|
|
4346
|
+
w: _w,
|
|
4347
|
+
h: _h
|
|
4348
|
+
};
|
|
3210
4349
|
const srcW = source.width;
|
|
3211
4350
|
const srcH = source.height;
|
|
3212
4351
|
const srcData = source.data32;
|
|
3213
4352
|
if (w <= 0 || h <= 0) {
|
|
3214
4353
|
return new Uint32Array(0);
|
|
3215
4354
|
}
|
|
3216
|
-
const
|
|
3217
|
-
const
|
|
3218
|
-
|
|
3219
|
-
const
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
for (let row = 0; row <
|
|
3228
|
-
const
|
|
3229
|
-
const
|
|
3230
|
-
const
|
|
3231
|
-
const dstCol = x0 - x;
|
|
3232
|
-
const dstStart = dstRow * w + dstCol;
|
|
3233
|
-
const chunk = srcData.subarray(srcStart, srcStart + copyWidth);
|
|
4355
|
+
const dstData = new Uint32Array(w * h);
|
|
4356
|
+
const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT4);
|
|
4357
|
+
if (!clip.inBounds) return dstData;
|
|
4358
|
+
const {
|
|
4359
|
+
x: dstX,
|
|
4360
|
+
y: dstY,
|
|
4361
|
+
sx: srcX,
|
|
4362
|
+
sy: srcY,
|
|
4363
|
+
w: copyW,
|
|
4364
|
+
h: copyH
|
|
4365
|
+
} = clip;
|
|
4366
|
+
for (let row = 0; row < copyH; row++) {
|
|
4367
|
+
const srcStart = (srcY + row) * srcW + srcX;
|
|
4368
|
+
const dstStart = (dstY + row) * w + dstX;
|
|
4369
|
+
const chunk = srcData.subarray(srcStart, srcStart + copyW);
|
|
3234
4370
|
dstData.set(chunk, dstStart);
|
|
3235
4371
|
}
|
|
3236
4372
|
return dstData;
|
|
@@ -3238,13 +4374,59 @@ function extractPixelDataBuffer(source, _x, _y, _w, _h) {
|
|
|
3238
4374
|
|
|
3239
4375
|
// src/PixelData/extractPixelData.ts
|
|
3240
4376
|
function extractPixelData(source, _x, _y, _w, _h) {
|
|
3241
|
-
const {
|
|
4377
|
+
const {
|
|
4378
|
+
x,
|
|
4379
|
+
y,
|
|
4380
|
+
w,
|
|
4381
|
+
h
|
|
4382
|
+
} = typeof _x === "object" ? _x : {
|
|
4383
|
+
x: _x,
|
|
4384
|
+
y: _y,
|
|
4385
|
+
w: _w,
|
|
4386
|
+
h: _h
|
|
4387
|
+
};
|
|
3242
4388
|
const result = new PixelData(new ImageData(w, h));
|
|
3243
4389
|
const buffer = extractPixelDataBuffer(source, x, y, w, h);
|
|
3244
4390
|
result.data32.set(buffer);
|
|
3245
4391
|
return result;
|
|
3246
4392
|
}
|
|
3247
4393
|
|
|
4394
|
+
// src/PixelData/PixelBuffer32.ts
|
|
4395
|
+
var PixelBuffer32 = class _PixelBuffer32 {
|
|
4396
|
+
constructor(width, height, data32) {
|
|
4397
|
+
this.width = width;
|
|
4398
|
+
this.height = height;
|
|
4399
|
+
this.data32 = data32 ?? new Uint32Array(width * height);
|
|
4400
|
+
}
|
|
4401
|
+
data32;
|
|
4402
|
+
set(width, height, data32) {
|
|
4403
|
+
;
|
|
4404
|
+
this.data32 = data32 ?? new Uint32Array(width * height);
|
|
4405
|
+
this.width = width;
|
|
4406
|
+
this.height = height;
|
|
4407
|
+
}
|
|
4408
|
+
copy() {
|
|
4409
|
+
const newData32 = new Uint32Array(this.data32);
|
|
4410
|
+
return new _PixelBuffer32(this.width, this.height, newData32);
|
|
4411
|
+
}
|
|
4412
|
+
};
|
|
4413
|
+
|
|
4414
|
+
// src/PixelData/pixelDataToAlphaMask.ts
|
|
4415
|
+
function pixelDataToAlphaMask(pixelData) {
|
|
4416
|
+
const {
|
|
4417
|
+
data32,
|
|
4418
|
+
width,
|
|
4419
|
+
height
|
|
4420
|
+
} = pixelData;
|
|
4421
|
+
const len = data32.length;
|
|
4422
|
+
const mask = new Uint8Array(width * height);
|
|
4423
|
+
for (let i = 0; i < len; i++) {
|
|
4424
|
+
const val = data32[i];
|
|
4425
|
+
mask[i] = val >>> 24 & 255;
|
|
4426
|
+
}
|
|
4427
|
+
return mask;
|
|
4428
|
+
}
|
|
4429
|
+
|
|
3248
4430
|
// src/PixelData/reflectPixelData.ts
|
|
3249
4431
|
function reflectPixelDataHorizontal(pixelData) {
|
|
3250
4432
|
const width = pixelData.width;
|
|
@@ -3282,12 +4464,12 @@ function reflectPixelDataVertical(pixelData) {
|
|
|
3282
4464
|
|
|
3283
4465
|
// src/PixelData/resamplePixelData.ts
|
|
3284
4466
|
function resamplePixelData(pixelData, factor) {
|
|
3285
|
-
const {
|
|
3286
|
-
|
|
3287
|
-
new Uint8ClampedArray(data.buffer),
|
|
4467
|
+
const {
|
|
4468
|
+
data,
|
|
3288
4469
|
width,
|
|
3289
4470
|
height
|
|
3290
|
-
)
|
|
4471
|
+
} = resample32(pixelData.data32, pixelData.width, pixelData.height, factor);
|
|
4472
|
+
return new PixelData(new ImageData(new Uint8ClampedArray(data.buffer), width, height));
|
|
3291
4473
|
}
|
|
3292
4474
|
|
|
3293
4475
|
// src/PixelData/rotatePixelData.ts
|
|
@@ -3311,11 +4493,7 @@ function rotatePixelData(pixelData) {
|
|
|
3311
4493
|
newData32[newIdx] = data[oldIdx];
|
|
3312
4494
|
}
|
|
3313
4495
|
}
|
|
3314
|
-
const newImageData = new ImageData(
|
|
3315
|
-
new Uint8ClampedArray(newData32.buffer),
|
|
3316
|
-
newWidth,
|
|
3317
|
-
newHeight
|
|
3318
|
-
);
|
|
4496
|
+
const newImageData = new ImageData(new Uint8ClampedArray(newData32.buffer), newWidth, newHeight);
|
|
3319
4497
|
pixelData.set(newImageData);
|
|
3320
4498
|
}
|
|
3321
4499
|
function rotateSquareInPlace(pixelData) {
|
|
@@ -3337,8 +4515,14 @@ function rotateSquareInPlace(pixelData) {
|
|
|
3337
4515
|
}
|
|
3338
4516
|
|
|
3339
4517
|
// src/PixelData/writePixelDataBuffer.ts
|
|
4518
|
+
var SCRATCH_BLIT5 = makeClippedBlit();
|
|
3340
4519
|
function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
3341
|
-
const {
|
|
4520
|
+
const {
|
|
4521
|
+
x,
|
|
4522
|
+
y,
|
|
4523
|
+
w,
|
|
4524
|
+
h
|
|
4525
|
+
} = typeof _x === "object" ? _x : {
|
|
3342
4526
|
x: _x,
|
|
3343
4527
|
y: _y,
|
|
3344
4528
|
w: _w,
|
|
@@ -3347,45 +4531,52 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
3347
4531
|
const dstW = target.width;
|
|
3348
4532
|
const dstH = target.height;
|
|
3349
4533
|
const dstData = target.data32;
|
|
3350
|
-
const
|
|
3351
|
-
|
|
3352
|
-
const
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
const
|
|
3363
|
-
|
|
3364
|
-
const srcStart = srcRow * w + srcCol;
|
|
3365
|
-
dstData.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
4534
|
+
const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT5);
|
|
4535
|
+
if (!clip.inBounds) return;
|
|
4536
|
+
const {
|
|
4537
|
+
x: dstX,
|
|
4538
|
+
y: dstY,
|
|
4539
|
+
sx: srcX,
|
|
4540
|
+
sy: srcY,
|
|
4541
|
+
w: copyW,
|
|
4542
|
+
h: copyH
|
|
4543
|
+
} = clip;
|
|
4544
|
+
for (let row = 0; row < copyH; row++) {
|
|
4545
|
+
const dstStart = (dstY + row) * dstW + dstX;
|
|
4546
|
+
const srcStart = (srcY + row) * w + srcX;
|
|
4547
|
+
dstData.set(data.subarray(srcStart, srcStart + copyW), dstStart);
|
|
3366
4548
|
}
|
|
3367
4549
|
}
|
|
3368
4550
|
export {
|
|
3369
4551
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
3370
4552
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
3371
4553
|
BaseBlendMode,
|
|
4554
|
+
CANVAS_CTX_FAILED,
|
|
3372
4555
|
HistoryManager,
|
|
3373
4556
|
IndexedImage,
|
|
3374
4557
|
MaskType,
|
|
4558
|
+
OFFSCREEN_CANVAS_CTX_FAILED,
|
|
3375
4559
|
PixelAccumulator,
|
|
4560
|
+
PixelBuffer32,
|
|
3376
4561
|
PixelData,
|
|
3377
4562
|
PixelEngineConfig,
|
|
3378
4563
|
PixelTile,
|
|
3379
4564
|
PixelWriter,
|
|
3380
4565
|
UnsupportedFormatError,
|
|
4566
|
+
applyAlphaMaskToPixelData,
|
|
4567
|
+
applyBinaryMaskToAlphaMask,
|
|
4568
|
+
applyBinaryMaskToPixelData,
|
|
3381
4569
|
applyCircleBrushToPixelData,
|
|
3382
|
-
applyMaskToPixelData,
|
|
3383
4570
|
applyPatchTiles,
|
|
3384
4571
|
applyRectBrushToPixelData,
|
|
3385
4572
|
base64DecodeArrayBuffer,
|
|
3386
4573
|
base64EncodeArrayBuffer,
|
|
3387
4574
|
blendColorPixelData,
|
|
4575
|
+
blendColorPixelDataAlphaMask,
|
|
4576
|
+
blendColorPixelDataBinaryMask,
|
|
3388
4577
|
blendPixelData,
|
|
4578
|
+
blendPixelDataAlphaMask,
|
|
4579
|
+
blendPixelDataBinaryMask,
|
|
3389
4580
|
clearPixelData,
|
|
3390
4581
|
color32ToCssRGBA,
|
|
3391
4582
|
color32ToHex,
|
|
@@ -3418,10 +4609,13 @@ export {
|
|
|
3418
4609
|
fileToImageData,
|
|
3419
4610
|
fillPixelData,
|
|
3420
4611
|
floodFillSelection,
|
|
3421
|
-
|
|
4612
|
+
forEachLinePoint,
|
|
4613
|
+
getCircleBrushOrPencilBounds,
|
|
4614
|
+
getCircleBrushOrPencilStrokeBounds,
|
|
3422
4615
|
getImageDataFromClipboard,
|
|
3423
4616
|
getIndexedImageColorCounts,
|
|
3424
|
-
|
|
4617
|
+
getRectBrushOrPencilBounds,
|
|
4618
|
+
getRectBrushOrPencilStrokeBounds,
|
|
3425
4619
|
getSupportedPixelFormats,
|
|
3426
4620
|
hardLightFast,
|
|
3427
4621
|
hardLightPerfect,
|
|
@@ -3453,17 +4647,29 @@ export {
|
|
|
3453
4647
|
makeBlendModeRegistry,
|
|
3454
4648
|
makeFastBlendModeRegistry,
|
|
3455
4649
|
makeFullPixelMutator,
|
|
4650
|
+
makeImageDataLike,
|
|
3456
4651
|
makePerfectBlendModeRegistry,
|
|
3457
4652
|
makePixelCanvas,
|
|
3458
4653
|
makeReusableCanvas,
|
|
3459
4654
|
makeReusableImageData,
|
|
3460
|
-
|
|
4655
|
+
mergeAlphaMasks,
|
|
4656
|
+
mergeBinaryMasks,
|
|
3461
4657
|
multiplyFast,
|
|
3462
4658
|
multiplyPerfect,
|
|
3463
|
-
|
|
4659
|
+
mutatorApplyAlphaMask,
|
|
4660
|
+
mutatorApplyBinaryMask,
|
|
4661
|
+
mutatorApplyCircleBrush,
|
|
4662
|
+
mutatorApplyCircleBrushStroke,
|
|
4663
|
+
mutatorApplyCirclePencil,
|
|
4664
|
+
mutatorApplyCirclePencilStroke,
|
|
4665
|
+
mutatorApplyRectBrush,
|
|
4666
|
+
mutatorApplyRectBrushStroke,
|
|
4667
|
+
mutatorApplyRectPencil,
|
|
4668
|
+
mutatorApplyRectPencilStroke,
|
|
3464
4669
|
mutatorBlendColor,
|
|
3465
4670
|
mutatorBlendPixel,
|
|
3466
4671
|
mutatorBlendPixelData,
|
|
4672
|
+
mutatorClear,
|
|
3467
4673
|
mutatorFill,
|
|
3468
4674
|
mutatorInvert,
|
|
3469
4675
|
overlayFast,
|
|
@@ -3493,7 +4699,10 @@ export {
|
|
|
3493
4699
|
sourceOverPerfect,
|
|
3494
4700
|
subtractFast,
|
|
3495
4701
|
subtractPerfect,
|
|
4702
|
+
toBlendModeIndexAndName,
|
|
3496
4703
|
trimRectBounds,
|
|
4704
|
+
uInt32ArrayToImageData,
|
|
4705
|
+
uInt32ArrayToImageDataLike,
|
|
3497
4706
|
unpackAlpha,
|
|
3498
4707
|
unpackBlue,
|
|
3499
4708
|
unpackColor,
|