pixel-data-js 0.21.0 → 0.23.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.
Files changed (68) hide show
  1. package/dist/index.dev.cjs +1129 -717
  2. package/dist/index.dev.cjs.map +1 -1
  3. package/dist/index.dev.js +1114 -716
  4. package/dist/index.dev.js.map +1 -1
  5. package/dist/index.prod.cjs +1129 -717
  6. package/dist/index.prod.cjs.map +1 -1
  7. package/dist/index.prod.d.ts +317 -136
  8. package/dist/index.prod.js +1114 -716
  9. package/dist/index.prod.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/Algorithm/floodFillSelection.ts +12 -14
  12. package/src/BlendModes/toBlendModeIndexAndName.ts +0 -7
  13. package/src/Clipboard/writeImgBlobToClipboard.ts +1 -1
  14. package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +3 -0
  15. package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +3 -0
  16. package/src/History/PixelMutator/mutatorApplyCircleBrush.ts +25 -6
  17. package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +89 -46
  18. package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +7 -7
  19. package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +81 -41
  20. package/src/History/PixelMutator/mutatorApplyRectBrush.ts +3 -0
  21. package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +18 -5
  22. package/src/History/PixelMutator/mutatorApplyRectPencil.ts +3 -0
  23. package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +19 -4
  24. package/src/History/PixelMutator/mutatorBlendColor.ts +4 -0
  25. package/src/History/PixelMutator/mutatorBlendPixelData.ts +5 -1
  26. package/src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts +33 -0
  27. package/src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts +33 -0
  28. package/src/History/PixelMutator/mutatorClear.ts +12 -10
  29. package/src/History/PixelMutator/mutatorFill.ts +7 -4
  30. package/src/History/PixelMutator/mutatorFillBinaryMask.ts +28 -0
  31. package/src/History/PixelMutator/mutatorInvert.ts +3 -0
  32. package/src/History/PixelMutator.ts +14 -11
  33. package/src/ImageData/extractImageDataBuffer.ts +3 -3
  34. package/src/ImageData/{imageDataToAlphaMask.ts → imageDataToAlphaMaskBuffer.ts} +3 -4
  35. package/src/ImageData/resizeImageData.ts +3 -5
  36. package/src/ImageData/writeImageDataBuffer.ts +7 -7
  37. package/src/Mask/AlphaMask.ts +16 -0
  38. package/src/Mask/BinaryMask.ts +16 -0
  39. package/src/Mask/CircleBrushAlphaMask.ts +32 -0
  40. package/src/Mask/CircleBrushBinaryMask.ts +30 -0
  41. package/src/Mask/applyBinaryMaskToAlphaMask.ts +12 -9
  42. package/src/Mask/copyMask.ts +9 -3
  43. package/src/Mask/extractMask.ts +33 -31
  44. package/src/Mask/extractMaskBuffer.ts +87 -0
  45. package/src/Mask/invertMask.ts +6 -4
  46. package/src/Mask/mergeAlphaMasks.ts +11 -10
  47. package/src/Mask/mergeBinaryMasks.ts +10 -9
  48. package/src/Mask/setMaskData.ts +7 -0
  49. package/src/MaskRect/merge2BinaryMaskRects.ts +81 -0
  50. package/src/MaskRect/mergeBinaryMaskRects.ts +39 -0
  51. package/src/MaskRect/subtractBinaryMaskRects.ts +80 -0
  52. package/src/PixelData/applyAlphaMaskToPixelData.ts +8 -5
  53. package/src/PixelData/applyBinaryMaskToPixelData.ts +8 -9
  54. package/src/PixelData/applyCircleBrushToPixelData.ts +54 -62
  55. package/src/PixelData/blendColorPixelDataAlphaMask.ts +35 -25
  56. package/src/PixelData/blendColorPixelDataBinaryMask.ts +26 -19
  57. package/src/PixelData/blendPixelData.ts +1 -1
  58. package/src/PixelData/blendPixelDataAlphaMask.ts +3 -3
  59. package/src/PixelData/blendPixelDataBinaryMask.ts +4 -4
  60. package/src/PixelData/fillPixelData.ts +15 -42
  61. package/src/PixelData/fillPixelDataBinaryMask.ts +79 -0
  62. package/src/PixelData/invertPixelData.ts +3 -3
  63. package/src/PixelData/pixelDataToAlphaMask.ts +4 -2
  64. package/src/PixelData/writePixelDataBuffer.ts +2 -3
  65. package/src/Rect/getRectsBounds.ts +22 -0
  66. package/src/Rect/trimRectBounds.ts +20 -17
  67. package/src/_types.ts +55 -29
  68. package/src/index.ts +18 -1
@@ -75,11 +75,13 @@ __export(src_exports, {
75
75
  exclusionPerfect: () => exclusionPerfect,
76
76
  extractImageDataBuffer: () => extractImageDataBuffer,
77
77
  extractMask: () => extractMask,
78
+ extractMaskBuffer: () => extractMaskBuffer,
78
79
  extractPixelData: () => extractPixelData,
79
80
  extractPixelDataBuffer: () => extractPixelDataBuffer,
80
81
  fileInputChangeToImageData: () => fileInputChangeToImageData,
81
82
  fileToImageData: () => fileToImageData,
82
83
  fillPixelData: () => fillPixelData,
84
+ fillPixelDataBinaryMask: () => fillPixelDataBinaryMask,
83
85
  floodFillSelection: () => floodFillSelection,
84
86
  forEachLinePoint: () => forEachLinePoint,
85
87
  getCircleBrushOrPencilBounds: () => getCircleBrushOrPencilBounds,
@@ -88,12 +90,13 @@ __export(src_exports, {
88
90
  getIndexedImageColorCounts: () => getIndexedImageColorCounts,
89
91
  getRectBrushOrPencilBounds: () => getRectBrushOrPencilBounds,
90
92
  getRectBrushOrPencilStrokeBounds: () => getRectBrushOrPencilStrokeBounds,
93
+ getRectsBounds: () => getRectsBounds,
91
94
  getSupportedPixelFormats: () => getSupportedPixelFormats,
92
95
  hardLightFast: () => hardLightFast,
93
96
  hardLightPerfect: () => hardLightPerfect,
94
97
  hardMixFast: () => hardMixFast,
95
98
  hardMixPerfect: () => hardMixPerfect,
96
- imageDataToAlphaMask: () => imageDataToAlphaMask,
99
+ imageDataToAlphaMaskBuffer: () => imageDataToAlphaMaskBuffer,
97
100
  imageDataToDataUrl: () => imageDataToDataUrl,
98
101
  imageDataToImgBlob: () => imageDataToImgBlob,
99
102
  imageDataToUInt32Array: () => imageDataToUInt32Array,
@@ -116,7 +119,11 @@ __export(src_exports, {
116
119
  linearDodgePerfect: () => linearDodgePerfect,
117
120
  linearLightFast: () => linearLightFast,
118
121
  linearLightPerfect: () => linearLightPerfect,
122
+ makeAlphaMask: () => makeAlphaMask,
123
+ makeBinaryMask: () => makeBinaryMask,
119
124
  makeBlendModeRegistry: () => makeBlendModeRegistry,
125
+ makeCircleBrushAlphaMask: () => makeCircleBrushAlphaMask,
126
+ makeCircleBrushBinaryMask: () => makeCircleBrushBinaryMask,
120
127
  makeFastBlendModeRegistry: () => makeFastBlendModeRegistry,
121
128
  makeFullPixelMutator: () => makeFullPixelMutator,
122
129
  makeImageDataLike: () => makeImageDataLike,
@@ -124,7 +131,9 @@ __export(src_exports, {
124
131
  makePixelCanvas: () => makePixelCanvas,
125
132
  makeReusableCanvas: () => makeReusableCanvas,
126
133
  makeReusableImageData: () => makeReusableImageData,
134
+ merge2BinaryMaskRects: () => merge2BinaryMaskRects,
127
135
  mergeAlphaMasks: () => mergeAlphaMasks,
136
+ mergeBinaryMaskRects: () => mergeBinaryMaskRects,
128
137
  mergeBinaryMasks: () => mergeBinaryMasks,
129
138
  multiplyFast: () => multiplyFast,
130
139
  multiplyPerfect: () => multiplyPerfect,
@@ -141,8 +150,11 @@ __export(src_exports, {
141
150
  mutatorBlendColor: () => mutatorBlendColor,
142
151
  mutatorBlendPixel: () => mutatorBlendPixel,
143
152
  mutatorBlendPixelData: () => mutatorBlendPixelData,
153
+ mutatorBlendPixelDataAlphaMask: () => mutatorBlendPixelDataAlphaMask,
154
+ mutatorBlendPixelDataBinaryMask: () => mutatorBlendPixelDataBinaryMask,
144
155
  mutatorClear: () => mutatorClear,
145
156
  mutatorFill: () => mutatorFill,
157
+ mutatorFillBinaryMask: () => mutatorFillBinaryMask,
146
158
  mutatorInvert: () => mutatorInvert,
147
159
  overlayFast: () => overlayFast,
148
160
  overlayPerfect: () => overlayPerfect,
@@ -165,10 +177,12 @@ __export(src_exports, {
165
177
  screenPerfect: () => screenPerfect,
166
178
  serializeImageData: () => serializeImageData,
167
179
  serializeNullableImageData: () => serializeNullableImageData,
180
+ setMaskData: () => setMaskData,
168
181
  softLightFast: () => softLightFast,
169
182
  softLightPerfect: () => softLightPerfect,
170
183
  sourceOverFast: () => sourceOverFast,
171
184
  sourceOverPerfect: () => sourceOverPerfect,
185
+ subtractBinaryMaskRects: () => subtractBinaryMaskRects,
172
186
  subtractFast: () => subtractFast,
173
187
  subtractPerfect: () => subtractPerfect,
174
188
  toBlendModeIndexAndName: () => toBlendModeIndexAndName,
@@ -389,8 +403,8 @@ function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
389
403
  return out;
390
404
  }
391
405
 
392
- // src/Mask/extractMask.ts
393
- function extractMask(mask, maskWidth, xOrRect, y, w, h) {
406
+ // src/Mask/extractMaskBuffer.ts
407
+ function extractMaskBuffer(maskBuffer, maskWidth, xOrRect, y, w, h) {
394
408
  let finalX;
395
409
  let finalY;
396
410
  let finalW;
@@ -407,7 +421,7 @@ function extractMask(mask, maskWidth, xOrRect, y, w, h) {
407
421
  finalH = h;
408
422
  }
409
423
  const out = new Uint8Array(finalW * finalH);
410
- const srcH = mask.length / maskWidth;
424
+ const srcH = maskBuffer.length / maskWidth;
411
425
  for (let row = 0; row < finalH; row++) {
412
426
  const currentSrcY = finalY + row;
413
427
  if (currentSrcY < 0 || currentSrcY >= srcH) {
@@ -419,7 +433,7 @@ function extractMask(mask, maskWidth, xOrRect, y, w, h) {
419
433
  const srcOffset = currentSrcY * maskWidth + start;
420
434
  const dstOffset = row * finalW + (start - finalX);
421
435
  const count = end - start;
422
- out.set(mask.subarray(srcOffset, srcOffset + count), dstOffset);
436
+ out.set(maskBuffer.subarray(srcOffset, srcOffset + count), dstOffset);
423
437
  }
424
438
  }
425
439
  return out;
@@ -437,8 +451,8 @@ function trimRectBounds(target, bounds) {
437
451
  if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
438
452
  target.w = 0;
439
453
  target.h = 0;
440
- if ("mask" in target && target.mask) {
441
- target.mask = new Uint8Array(0);
454
+ if ("data" in target && target.data) {
455
+ target.data = new Uint8Array(0);
442
456
  }
443
457
  return;
444
458
  }
@@ -450,15 +464,15 @@ function trimRectBounds(target, bounds) {
450
464
  target.y = intersectedY;
451
465
  target.w = intersectedW;
452
466
  target.h = intersectedH;
453
- if ("mask" in target && target.mask) {
454
- const currentMask = extractMask(target.mask, originalW, offsetX, offsetY, intersectedW, intersectedH);
467
+ if ("data" in target && target.data) {
468
+ const currentMaskBuffer = extractMaskBuffer(target.data, originalW, offsetX, offsetY, intersectedW, intersectedH);
455
469
  let minX = intersectedW;
456
470
  let maxX = -1;
457
471
  let minY = intersectedH;
458
472
  let maxY = -1;
459
473
  for (let y = 0; y < intersectedH; y++) {
460
474
  for (let x = 0; x < intersectedW; x++) {
461
- if (currentMask[y * intersectedW + x] !== 0) {
475
+ if (currentMaskBuffer[y * intersectedW + x] !== 0) {
462
476
  if (x < minX) minX = x;
463
477
  if (x > maxX) maxX = x;
464
478
  if (y < minY) minY = y;
@@ -469,19 +483,22 @@ function trimRectBounds(target, bounds) {
469
483
  if (maxX === -1) {
470
484
  target.w = 0;
471
485
  target.h = 0;
472
- target.mask = new Uint8Array(0);
486
+ target.data = new Uint8Array(0);
473
487
  return;
474
488
  }
475
489
  const finalW = maxX - minX + 1;
476
490
  const finalH = maxY - minY + 1;
477
491
  if (finalW !== intersectedW || finalH !== intersectedH) {
478
- target.mask = extractMask(currentMask, intersectedW, minX, minY, finalW, finalH);
492
+ const newMaskBuffer = extractMaskBuffer(currentMaskBuffer, intersectedW, minX, minY, finalW, finalH);
479
493
  target.x += minX;
480
494
  target.y += minY;
481
495
  target.w = finalW;
482
496
  target.h = finalH;
497
+ target.data = newMaskBuffer;
483
498
  } else {
484
- target.mask = currentMask;
499
+ target.w = finalW;
500
+ target.h = finalH;
501
+ target.data = currentMaskBuffer;
485
502
  }
486
503
  }
487
504
  }
@@ -591,17 +608,19 @@ function floodFillSelection(img, startX, startY, {
591
608
  if (matchCount === 0) {
592
609
  return null;
593
610
  }
611
+ const w = maxX - minX + 1;
612
+ const h = maxY - minY + 1;
594
613
  const selectionRect = {
595
614
  x: minX,
596
615
  y: minY,
597
- w: maxX - minX + 1,
598
- h: maxY - minY + 1,
599
- mask: new Uint8Array((maxX - minX + 1) * (maxY - minY + 1)),
600
- maskType: 1 /* BINARY */
616
+ w,
617
+ h,
618
+ data: new Uint8Array(w * h),
619
+ type: 1 /* BINARY */
601
620
  };
602
621
  const sw = selectionRect.w;
603
622
  const sh = selectionRect.h;
604
- const finalMask = selectionRect.mask;
623
+ const finalMask = selectionRect.data;
605
624
  for (let i = 0; i < matchCount; i++) {
606
625
  const mx = matchX[i] - selectionRect.x;
607
626
  const my = matchY[i] - selectionRect.y;
@@ -1676,16 +1695,7 @@ function toBlendModeIndexAndName(input) {
1676
1695
  const num = Number(trimmed);
1677
1696
  const isNumeric = trimmed !== "" && !Number.isNaN(num);
1678
1697
  if (isNumeric && Number.isInteger(num)) {
1679
- console.log({
1680
- trimmed,
1681
- num,
1682
- isNumeric,
1683
- isInt: Number.isInteger(num)
1684
- });
1685
1698
  const name = getKeyByValue(BaseBlendMode, num);
1686
- console.log({
1687
- name
1688
- });
1689
1699
  if (name === void 0) throw new Error(`Invalid index: ${num}`);
1690
1700
  return {
1691
1701
  blendIndex: num,
@@ -2059,7 +2069,6 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
2059
2069
  w: width = dst.width,
2060
2070
  h: height = dst.height,
2061
2071
  alpha: globalAlpha = 255,
2062
- mw,
2063
2072
  mx = 0,
2064
2073
  my = 0,
2065
2074
  invertMask = false
@@ -2081,15 +2090,14 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
2081
2090
  h = Math.min(h, dst.height - y);
2082
2091
  if (w <= 0) return;
2083
2092
  if (h <= 0) return;
2084
- const mPitch = mw ?? width;
2093
+ const mPitch = mask.w;
2085
2094
  if (mPitch <= 0) return;
2086
- const maskHeight = mask.length / mPitch | 0;
2087
2095
  const startX = mx + (x - targetX);
2088
2096
  const startY = my + (y - targetY);
2089
2097
  const sX0 = Math.max(0, startX);
2090
2098
  const sY0 = Math.max(0, startY);
2091
2099
  const sX1 = Math.min(mPitch, startX + w);
2092
- const sY1 = Math.min(maskHeight, startY + h);
2100
+ const sY1 = Math.min(mask.h, startY + h);
2093
2101
  const finalW = sX1 - sX0;
2094
2102
  const finalH = sY1 - sY0;
2095
2103
  if (finalW <= 0) return;
@@ -2100,11 +2108,12 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
2100
2108
  const dw = dst.width;
2101
2109
  const dStride = dw - finalW;
2102
2110
  const mStride = mPitch - finalW;
2111
+ const maskData = mask.data;
2103
2112
  let dIdx = (y + yShift) * dw + (x + xShift);
2104
2113
  let mIdx = sY0 * mPitch + sX0;
2105
2114
  for (let iy = 0; iy < h; iy++) {
2106
2115
  for (let ix = 0; ix < w; ix++) {
2107
- const mVal = mask[mIdx];
2116
+ const mVal = maskData[mIdx];
2108
2117
  const effectiveM = invertMask ? 255 - mVal : mVal;
2109
2118
  let weight = 0;
2110
2119
  if (effectiveM === 0) {
@@ -2164,13 +2173,12 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
2164
2173
  y: targetY = 0,
2165
2174
  w: width = dst.width,
2166
2175
  h: height = dst.height,
2167
- alpha = 255,
2168
- mw,
2176
+ alpha: globalAlpha = 255,
2169
2177
  mx = 0,
2170
2178
  my = 0,
2171
2179
  invertMask = false
2172
2180
  } = opts;
2173
- if (alpha === 0) return;
2181
+ if (globalAlpha === 0) return;
2174
2182
  let x = targetX;
2175
2183
  let y = targetY;
2176
2184
  let w = width;
@@ -2187,15 +2195,14 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
2187
2195
  h = Math.min(h, dst.height - y);
2188
2196
  if (w <= 0) return;
2189
2197
  if (h <= 0) return;
2190
- const mPitch = mw ?? width;
2198
+ const mPitch = mask.w;
2191
2199
  if (mPitch <= 0) return;
2192
- const maskHeight = mask.length / mPitch | 0;
2193
2200
  const startX = mx + (x - targetX);
2194
2201
  const startY = my + (y - targetY);
2195
2202
  const sX0 = Math.max(0, startX);
2196
2203
  const sY0 = Math.max(0, startY);
2197
2204
  const sX1 = Math.min(mPitch, startX + w);
2198
- const sY1 = Math.min(maskHeight, startY + h);
2205
+ const sY1 = Math.min(mask.h, startY + h);
2199
2206
  const finalW = sX1 - sX0;
2200
2207
  const finalH = sY1 - sY0;
2201
2208
  if (finalW <= 0) return;
@@ -2206,19 +2213,20 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
2206
2213
  const dw = dst.width;
2207
2214
  const dStride = dw - finalW;
2208
2215
  const mStride = mPitch - finalW;
2216
+ const maskData = mask.data;
2209
2217
  let dIdx = (y + yShift) * dw + (x + xShift);
2210
2218
  let mIdx = sY0 * mPitch + sX0;
2211
2219
  for (let iy = 0; iy < h; iy++) {
2212
2220
  for (let ix = 0; ix < w; ix++) {
2213
- const mVal = mask[mIdx];
2221
+ const mVal = maskData[mIdx];
2214
2222
  const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
2215
2223
  if (isMaskedOut) {
2216
2224
  dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
2217
- } else if (alpha !== 255) {
2225
+ } else if (globalAlpha !== 255) {
2218
2226
  const d = dst32[dIdx];
2219
2227
  const da = d >>> 24;
2220
2228
  if (da !== 0) {
2221
- const finalAlpha = da === 255 ? alpha : da * alpha + 128 >> 8;
2229
+ const finalAlpha = da === 255 ? globalAlpha : da * globalAlpha + 128 >> 8;
2222
2230
  dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
2223
2231
  }
2224
2232
  }
@@ -2281,144 +2289,42 @@ function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth,
2281
2289
  return res;
2282
2290
  }
2283
2291
 
2284
- // src/PixelData/applyCircleBrushToPixelData.ts
2285
- function applyCircleBrushToPixelData(target, color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
2286
- const targetWidth = target.width;
2287
- const targetHeight = target.height;
2288
- const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight);
2289
- if (b.w <= 0 || b.h <= 0) return;
2290
- const data32 = target.data32;
2291
- const r = brushSize / 2;
2292
- const rSqr = r * r;
2293
- const invR = 1 / r;
2294
- const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
2295
- const endX = b.x + b.w;
2296
- const endY = b.y + b.h;
2297
- const fCenterX = Math.floor(centerX);
2298
- const fCenterY = Math.floor(centerY);
2299
- const baseSrcAlpha = color >>> 24;
2300
- const colorRGB = color & 16777215;
2301
- const isOpaque = alpha === 255;
2302
- const isOverwrite = blendFn.isOverwrite;
2303
- for (let cy = b.y; cy < endY; cy++) {
2304
- const relY = cy - fCenterY + centerOffset;
2305
- const dySqr = relY * relY;
2306
- const rowOffset = cy * targetWidth;
2307
- for (let cx = b.x; cx < endX; cx++) {
2308
- const relX = cx - fCenterX + centerOffset;
2309
- const dSqr = relX * relX + dySqr;
2310
- if (dSqr <= rSqr) {
2311
- const idx = rowOffset + cx;
2312
- let weight = alpha;
2313
- const strength = fallOff(1 - Math.sqrt(dSqr) * invR);
2314
- const maskVal = strength * 255 | 0;
2315
- if (maskVal === 0) continue;
2316
- if (isOpaque) {
2317
- weight = maskVal;
2318
- } else if (maskVal !== 255) {
2319
- weight = maskVal * alpha + 128 >> 8;
2320
- }
2321
- let finalCol = color;
2322
- if (weight < 255) {
2323
- const a = baseSrcAlpha * weight + 128 >> 8;
2324
- if (a === 0 && !isOverwrite) continue;
2325
- finalCol = (colorRGB | a << 24) >>> 0;
2326
- }
2327
- data32[idx] = blendFn(finalCol, data32[idx]);
2328
- }
2329
- }
2330
- }
2331
- }
2332
-
2333
- // src/History/PixelMutator/mutatorApplyCircleBrush.ts
2334
- var defaults3 = {
2335
- applyCircleBrushToPixelData,
2336
- getCircleBrushOrPencilBounds
2337
- };
2338
- var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
2339
- const {
2340
- applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
2341
- getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
2342
- } = deps;
2343
- const boundsOut = {
2344
- x: 0,
2345
- y: 0,
2346
- w: 0,
2347
- h: 0
2348
- };
2349
- return {
2350
- applyCircleBrush(color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn) {
2351
- const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
2352
- const {
2353
- x,
2354
- y,
2355
- w,
2356
- h
2357
- } = bounds;
2358
- writer.accumulator.storeRegionBeforeState(x, y, w, h);
2359
- applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
2360
- }
2361
- };
2362
- });
2363
-
2364
- // src/Algorithm/forEachLinePoint.ts
2365
- function forEachLinePoint(x0, y0, x1, y1, callback) {
2366
- const dx = x1 - x0;
2367
- const dy = y1 - y0;
2368
- const steps = Math.max(Math.abs(dx), Math.abs(dy));
2369
- if (steps === 0) {
2370
- callback(x0, y0);
2371
- return;
2372
- }
2373
- const xInc = dx / steps;
2374
- const yInc = dy / steps;
2375
- let curX = x0;
2376
- let curY = y0;
2377
- for (let i = 0; i <= steps; i++) {
2378
- callback(curX, curY);
2379
- curX += xInc;
2380
- curY += yInc;
2381
- }
2382
- }
2383
-
2384
2292
  // src/PixelData/blendColorPixelDataAlphaMask.ts
2385
- function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
2386
- const {
2387
- x: targetX = 0,
2388
- y: targetY = 0,
2389
- w: width = dst.width,
2390
- h: height = dst.height,
2391
- alpha: globalAlpha = 255,
2392
- blendFn = sourceOverPerfect,
2393
- mw = width,
2394
- mx = 0,
2395
- my = 0,
2396
- invertMask = false
2397
- } = opts;
2398
- if (globalAlpha === 0 || !mask) return;
2293
+ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
2294
+ const targetX = opts.x ?? 0;
2295
+ const targetY = opts.y ?? 0;
2296
+ const w = opts.w ?? mask.w;
2297
+ const h = opts.h ?? mask.h;
2298
+ const globalAlpha = opts.alpha ?? 255;
2299
+ const blendFn = opts.blendFn ?? sourceOverPerfect;
2300
+ const mx = opts.mx ?? 0;
2301
+ const my = opts.my ?? 0;
2302
+ const invertMask = opts.invertMask ?? false;
2303
+ if (globalAlpha === 0) return;
2399
2304
  const baseSrcAlpha = color >>> 24;
2400
2305
  const isOverwrite = blendFn.isOverwrite || false;
2401
2306
  if (baseSrcAlpha === 0 && !isOverwrite) return;
2402
2307
  let x = targetX;
2403
2308
  let y = targetY;
2404
- let w = width;
2405
- let h = height;
2309
+ let actualW = w;
2310
+ let actualH = h;
2406
2311
  if (x < 0) {
2407
- w += x;
2312
+ actualW += x;
2408
2313
  x = 0;
2409
2314
  }
2410
2315
  if (y < 0) {
2411
- h += y;
2316
+ actualH += y;
2412
2317
  y = 0;
2413
2318
  }
2414
- const actualW = Math.min(w, dst.width - x);
2415
- const actualH = Math.min(h, dst.height - y);
2319
+ actualW = Math.min(actualW, dst.width - x);
2320
+ actualH = Math.min(actualH, dst.height - y);
2416
2321
  if (actualW <= 0 || actualH <= 0) return;
2417
2322
  const dx = x - targetX | 0;
2418
2323
  const dy = y - targetY | 0;
2419
2324
  const dst32 = dst.data32;
2420
2325
  const dw = dst.width;
2421
- const mPitch = mw;
2326
+ const mPitch = mask.w;
2327
+ const maskData = mask.data;
2422
2328
  let dIdx = y * dw + x | 0;
2423
2329
  let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
2424
2330
  const dStride = dw - actualW | 0;
@@ -2427,7 +2333,7 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
2427
2333
  const colorRGB = color & 16777215;
2428
2334
  for (let iy = 0; iy < actualH; iy++) {
2429
2335
  for (let ix = 0; ix < actualW; ix++) {
2430
- const mVal = mask[mIdx];
2336
+ const mVal = maskData[mIdx];
2431
2337
  const effM = invertMask ? 255 - mVal : mVal;
2432
2338
  if (effM === 0) {
2433
2339
  dIdx++;
@@ -2464,6 +2370,155 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
2464
2370
  }
2465
2371
  }
2466
2372
 
2373
+ // src/PixelData/blendColorPixelDataBinaryMask.ts
2374
+ function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
2375
+ const targetX = opts.x ?? 0;
2376
+ const targetY = opts.y ?? 0;
2377
+ let w = opts.w ?? mask.w;
2378
+ let h = opts.h ?? mask.h;
2379
+ const globalAlpha = opts.alpha ?? 255;
2380
+ const blendFn = opts.blendFn ?? sourceOverPerfect;
2381
+ const mx = opts.mx ?? 0;
2382
+ const my = opts.my ?? 0;
2383
+ const invertMask = opts.invertMask ?? false;
2384
+ if (globalAlpha === 0) return;
2385
+ const baseSrcAlpha = color >>> 24;
2386
+ const isOverwrite = blendFn.isOverwrite || false;
2387
+ if (baseSrcAlpha === 0 && !isOverwrite) return;
2388
+ let x = targetX;
2389
+ let y = targetY;
2390
+ if (x < 0) {
2391
+ w += x;
2392
+ x = 0;
2393
+ }
2394
+ if (y < 0) {
2395
+ h += y;
2396
+ y = 0;
2397
+ }
2398
+ const actualW = Math.min(w, dst.width - x);
2399
+ const actualH = Math.min(h, dst.height - y);
2400
+ if (actualW <= 0 || actualH <= 0) return;
2401
+ let baseColorWithGlobalAlpha = color;
2402
+ if (globalAlpha < 255) {
2403
+ const a = baseSrcAlpha * globalAlpha + 128 >> 8;
2404
+ if (a === 0 && !isOverwrite) return;
2405
+ baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
2406
+ }
2407
+ const dx = x - targetX | 0;
2408
+ const dy = y - targetY | 0;
2409
+ const dst32 = dst.data32;
2410
+ const dw = dst.width;
2411
+ const mPitch = mask.w;
2412
+ const maskData = mask.data;
2413
+ let dIdx = y * dw + x | 0;
2414
+ let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
2415
+ const dStride = dw - actualW | 0;
2416
+ const mStride = mPitch - actualW | 0;
2417
+ const skipVal = invertMask ? 1 : 0;
2418
+ for (let iy = 0; iy < actualH; iy++) {
2419
+ for (let ix = 0; ix < actualW; ix++) {
2420
+ if (maskData[mIdx] === skipVal) {
2421
+ dIdx++;
2422
+ mIdx++;
2423
+ continue;
2424
+ }
2425
+ dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
2426
+ dIdx++;
2427
+ mIdx++;
2428
+ }
2429
+ dIdx += dStride;
2430
+ mIdx += mStride;
2431
+ }
2432
+ }
2433
+
2434
+ // src/PixelData/applyCircleBrushToPixelData.ts
2435
+ function applyCircleBrushToPixelData(target, color, centerX, centerY, brush, alpha = 255, blendFn = sourceOverPerfect, scratchOptions = {}, bounds) {
2436
+ const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brush.size, target.width, target.height);
2437
+ if (b.w <= 0 || b.h <= 0) return;
2438
+ const unclippedStartX = Math.floor(centerX + brush.minOffset);
2439
+ const unclippedStartY = Math.floor(centerY + brush.minOffset);
2440
+ const ix = Math.max(unclippedStartX, b.x);
2441
+ const iy = Math.max(unclippedStartY, b.y);
2442
+ const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
2443
+ const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
2444
+ const iw = ir - ix;
2445
+ const ih = ib - iy;
2446
+ if (iw <= 0 || ih <= 0) return;
2447
+ scratchOptions.x = ix;
2448
+ scratchOptions.y = iy;
2449
+ scratchOptions.w = iw;
2450
+ scratchOptions.h = ih;
2451
+ scratchOptions.mx = ix - unclippedStartX;
2452
+ scratchOptions.my = iy - unclippedStartY;
2453
+ scratchOptions.alpha = alpha;
2454
+ scratchOptions.blendFn = blendFn;
2455
+ if (brush.type === 0 /* ALPHA */) {
2456
+ blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
2457
+ }
2458
+ if (brush.type === 1 /* BINARY */) {
2459
+ blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
2460
+ }
2461
+ }
2462
+
2463
+ // src/History/PixelMutator/mutatorApplyCircleBrush.ts
2464
+ var defaults3 = {
2465
+ applyCircleBrushToPixelData,
2466
+ getCircleBrushOrPencilBounds
2467
+ };
2468
+ var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
2469
+ const {
2470
+ applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
2471
+ getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
2472
+ } = deps;
2473
+ const boundsOut = {
2474
+ x: 0,
2475
+ y: 0,
2476
+ w: 0,
2477
+ h: 0
2478
+ };
2479
+ const blendColorPixelOptions = {
2480
+ alpha: 255,
2481
+ blendFn: sourceOverPerfect,
2482
+ x: 0,
2483
+ y: 0,
2484
+ w: 0,
2485
+ h: 0
2486
+ };
2487
+ return {
2488
+ applyCircleBrush(color, centerX, centerY, brush, alpha = 255, blendFn) {
2489
+ const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, writer.target.width, writer.target.height, boundsOut);
2490
+ const {
2491
+ x,
2492
+ y,
2493
+ w,
2494
+ h
2495
+ } = bounds;
2496
+ writer.accumulator.storeRegionBeforeState(x, y, w, h);
2497
+ applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brush, alpha, blendFn, blendColorPixelOptions, bounds);
2498
+ }
2499
+ };
2500
+ });
2501
+
2502
+ // src/Algorithm/forEachLinePoint.ts
2503
+ function forEachLinePoint(x0, y0, x1, y1, callback) {
2504
+ const dx = x1 - x0;
2505
+ const dy = y1 - y0;
2506
+ const steps = Math.max(Math.abs(dx), Math.abs(dy));
2507
+ if (steps === 0) {
2508
+ callback(x0, y0);
2509
+ return;
2510
+ }
2511
+ const xInc = dx / steps;
2512
+ const yInc = dy / steps;
2513
+ let curX = x0;
2514
+ let curY = y0;
2515
+ for (let i = 0; i <= steps; i++) {
2516
+ callback(curX, curY);
2517
+ curX += xInc;
2518
+ curY += yInc;
2519
+ }
2520
+ }
2521
+
2467
2522
  // src/Rect/getCircleBrushOrPencilStrokeBounds.ts
2468
2523
  function getCircleBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushSize, result) {
2469
2524
  const r = Math.ceil(brushSize / 2);
@@ -2512,8 +2567,15 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
2512
2567
  w: 0,
2513
2568
  h: 0
2514
2569
  };
2570
+ const mask = {
2571
+ type: 0 /* ALPHA */,
2572
+ data: null,
2573
+ w: 0,
2574
+ h: 0
2575
+ };
2515
2576
  return {
2516
- applyCircleBrushStroke(color, x0, y0, x1, y1, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
2577
+ applyCircleBrushStroke(color, x0, y0, x1, y1, brush, alpha = 255, blendFn = sourceOverPerfect) {
2578
+ const brushSize = brush.size;
2517
2579
  const {
2518
2580
  x: bx,
2519
2581
  y: by,
@@ -2521,11 +2583,12 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
2521
2583
  h: bh
2522
2584
  } = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
2523
2585
  if (bw <= 0 || bh <= 0) return;
2524
- const mask = new Uint8Array(bw * bh);
2525
- const r = brushSize / 2;
2526
- const rSqr = r * r;
2527
- const invR = 1 / r;
2528
- const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
2586
+ mask.data = new Uint8Array(bw * bh);
2587
+ mask.w = bw;
2588
+ mask.h = bh;
2589
+ const maskData = mask.data;
2590
+ const brushData = brush.data;
2591
+ const minOffset = brush.minOffset;
2529
2592
  const targetWidth = writer.target.width;
2530
2593
  const targetHeight = writer.target.height;
2531
2594
  forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
@@ -2540,21 +2603,20 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
2540
2603
  const startY = Math.max(by, cby);
2541
2604
  const endX = Math.min(bx + bw, cbx + cbw);
2542
2605
  const endY = Math.min(by + bh, cby + cbh);
2543
- const fPx = Math.floor(px);
2544
- const fPy = Math.floor(py);
2606
+ const unclippedStartX = Math.floor(px + minOffset);
2607
+ const unclippedStartY = Math.floor(py + minOffset);
2545
2608
  for (let my = startY; my < endY; my++) {
2546
- const dy = my - fPy + centerOffset;
2547
- const dySqr = dy * dy;
2548
- const maskRowOffset = (my - by) * bw;
2609
+ const strokeMaskY = my - by;
2610
+ const strokeMaskRowOffset = strokeMaskY * bw;
2611
+ const brushY = my - unclippedStartY;
2612
+ const brushRowOffset = brushY * brushSize;
2549
2613
  for (let mx = startX; mx < endX; mx++) {
2550
- const dx = mx - fPx + centerOffset;
2551
- const dSqr = dx * dx + dySqr;
2552
- if (dSqr <= rSqr) {
2553
- const maskIdx = maskRowOffset + (mx - bx);
2554
- const dist = Math.sqrt(dSqr) * invR;
2555
- const intensity = fallOff(1 - dist) * 255 | 0;
2556
- if (intensity > mask[maskIdx]) {
2557
- mask[maskIdx] = intensity;
2614
+ const brushX = mx - unclippedStartX;
2615
+ const brushVal = brushData[brushRowOffset + brushX];
2616
+ if (brushVal > 0) {
2617
+ const strokeMaskIdx = strokeMaskRowOffset + (mx - bx);
2618
+ if (brushVal > maskData[strokeMaskIdx]) {
2619
+ maskData[strokeMaskIdx] = brushVal;
2558
2620
  }
2559
2621
  }
2560
2622
  }
@@ -2571,84 +2633,50 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
2571
2633
  };
2572
2634
  });
2573
2635
 
2574
- // src/PixelData/blendColorPixelDataBinaryMask.ts
2575
- function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
2636
+ // src/History/PixelMutator/mutatorApplyCirclePencil.ts
2637
+ var defaults5 = {
2638
+ applyCircleBrushToPixelData,
2639
+ getCircleBrushOrPencilBounds
2640
+ };
2641
+ var mutatorApplyCirclePencil = ((writer, deps = defaults5) => {
2576
2642
  const {
2577
- x: targetX = 0,
2578
- y: targetY = 0,
2579
- w: width = dst.width,
2580
- h: height = dst.height,
2581
- alpha: globalAlpha = 255,
2582
- blendFn = sourceOverPerfect,
2583
- mw = width,
2584
- mx = 0,
2585
- my = 0,
2586
- invertMask = false
2587
- } = opts;
2588
- if (globalAlpha === 0 || !mask) return;
2589
- const baseSrcAlpha = color >>> 24;
2590
- const isOverwrite = blendFn.isOverwrite || false;
2591
- if (baseSrcAlpha === 0 && !isOverwrite) return;
2592
- let x = targetX;
2593
- let y = targetY;
2594
- let w = width;
2595
- let h = height;
2596
- if (x < 0) {
2597
- w += x;
2598
- x = 0;
2599
- }
2600
- if (y < 0) {
2601
- h += y;
2602
- y = 0;
2603
- }
2604
- const actualW = Math.min(w, dst.width - x);
2605
- const actualH = Math.min(h, dst.height - y);
2606
- if (actualW <= 0 || actualH <= 0) return;
2607
- let baseColorWithGlobalAlpha = color;
2608
- if (globalAlpha < 255) {
2609
- const a = baseSrcAlpha * globalAlpha + 128 >> 8;
2610
- if (a === 0 && !isOverwrite) return;
2611
- baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
2612
- }
2613
- const dx = x - targetX | 0;
2614
- const dy = y - targetY | 0;
2615
- const dst32 = dst.data32;
2616
- const dw = dst.width;
2617
- const mPitch = mw;
2618
- let dIdx = y * dw + x | 0;
2619
- let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
2620
- const dStride = dw - actualW | 0;
2621
- const mStride = mPitch - actualW | 0;
2622
- const skipVal = invertMask ? 1 : 0;
2623
- for (let iy = 0; iy < actualH; iy++) {
2624
- for (let ix = 0; ix < actualW; ix++) {
2625
- if (mask[mIdx] === skipVal) {
2626
- dIdx++;
2627
- mIdx++;
2628
- continue;
2629
- }
2630
- dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
2631
- dIdx++;
2632
- mIdx++;
2643
+ applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults5.applyCircleBrushToPixelData,
2644
+ getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
2645
+ } = deps;
2646
+ const boundsOut = {
2647
+ x: 0,
2648
+ y: 0,
2649
+ w: 0,
2650
+ h: 0
2651
+ };
2652
+ return {
2653
+ applyCirclePencil(color, centerX, centerY, brush, alpha = 255, blendFn) {
2654
+ const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, writer.target.width, writer.target.height, boundsOut);
2655
+ const {
2656
+ x,
2657
+ y,
2658
+ w,
2659
+ h
2660
+ } = bounds;
2661
+ writer.accumulator.storeRegionBeforeState(x, y, w, h);
2662
+ applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brush, alpha, blendFn, bounds);
2633
2663
  }
2634
- dIdx += dStride;
2635
- mIdx += mStride;
2636
- }
2637
- }
2664
+ };
2665
+ });
2638
2666
 
2639
2667
  // src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
2640
- var defaults5 = {
2668
+ var defaults6 = {
2641
2669
  forEachLinePoint,
2642
2670
  blendColorPixelDataBinaryMask,
2643
2671
  getCircleBrushOrPencilBounds,
2644
2672
  getCircleBrushOrPencilStrokeBounds
2645
2673
  };
2646
- var mutatorApplyCirclePencilStroke = ((writer, deps = defaults5) => {
2674
+ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults6) => {
2647
2675
  const {
2648
- forEachLinePoint: forEachLinePoint2 = defaults5.forEachLinePoint,
2649
- blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults5.blendColorPixelDataBinaryMask,
2650
- getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults5.getCircleBrushOrPencilStrokeBounds,
2651
- getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
2676
+ forEachLinePoint: forEachLinePoint2 = defaults6.forEachLinePoint,
2677
+ blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults6.blendColorPixelDataBinaryMask,
2678
+ getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults6.getCircleBrushOrPencilStrokeBounds,
2679
+ getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults6.getCircleBrushOrPencilBounds
2652
2680
  } = deps;
2653
2681
  const strokeBoundsOut = {
2654
2682
  x: 0,
@@ -2670,19 +2698,25 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults5) => {
2670
2698
  w: 0,
2671
2699
  h: 0
2672
2700
  };
2701
+ const mask = {
2702
+ type: 1 /* BINARY */,
2703
+ data: null,
2704
+ w: 0,
2705
+ h: 0
2706
+ };
2673
2707
  return {
2674
- applyCirclePencilStroke(color, x0, y0, x1, y1, brushSize, alpha = 255, blendFn = sourceOverPerfect) {
2708
+ applyCirclePencilStroke(color, x0, y0, x1, y1, brush, alpha = 255, blendFn = sourceOverPerfect) {
2675
2709
  const {
2676
2710
  x: bx,
2677
2711
  y: by,
2678
2712
  w: bw,
2679
2713
  h: bh
2680
- } = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
2714
+ } = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brush.size, strokeBoundsOut);
2681
2715
  if (bw <= 0 || bh <= 0) return;
2682
- const mask = new Uint8Array(bw * bh);
2683
- const r = brushSize / 2;
2684
- const rSqr = r * r;
2685
- const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
2716
+ mask.data = new Uint8Array(bw * bh);
2717
+ mask.w = bw;
2718
+ mask.h = bh;
2719
+ const maskData = mask.data;
2686
2720
  const targetWidth = writer.target.width;
2687
2721
  const targetHeight = writer.target.height;
2688
2722
  forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
@@ -2691,24 +2725,24 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults5) => {
2691
2725
  y: cby,
2692
2726
  w: cbw,
2693
2727
  h: cbh
2694
- } = getCircleBrushOrPencilBounds2(px, py, brushSize, targetWidth, targetHeight, circlePencilBounds);
2728
+ } = getCircleBrushOrPencilBounds2(px, py, brush.size, targetWidth, targetHeight, circlePencilBounds);
2695
2729
  writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
2696
- const startX = Math.max(bx, cbx);
2697
- const startY = Math.max(by, cby);
2698
- const endX = Math.min(bx + bw, cbx + cbw);
2699
- const endY = Math.min(by + bh, cby + cbh);
2700
- const fPx = Math.floor(px);
2701
- const fPy = Math.floor(py);
2730
+ const unclippedStartX = Math.floor(px + brush.minOffset);
2731
+ const unclippedStartY = Math.floor(py + brush.minOffset);
2732
+ const startX = Math.max(bx, unclippedStartX);
2733
+ const startY = Math.max(by, unclippedStartY);
2734
+ const endX = Math.min(bx + bw, unclippedStartX + brush.w);
2735
+ const endY = Math.min(by + bh, unclippedStartY + brush.h);
2702
2736
  for (let my = startY; my < endY; my++) {
2703
- const dy = my - fPy + centerOffset;
2704
- const dySqr = dy * dy;
2737
+ const brushY = my - unclippedStartY;
2705
2738
  const maskRowOffset = (my - by) * bw;
2739
+ const brushRowOffset = brushY * brush.w;
2706
2740
  for (let mx = startX; mx < endX; mx++) {
2707
- const dx = mx - fPx + centerOffset;
2708
- const dSqr = dx * dx + dySqr;
2709
- if (dSqr <= rSqr) {
2741
+ const brushX = mx - unclippedStartX;
2742
+ const brushAlpha = brush.data[brushRowOffset + brushX];
2743
+ if (brushAlpha > 0) {
2710
2744
  const maskIdx = maskRowOffset + (mx - bx);
2711
- mask[maskIdx] = 1;
2745
+ maskData[maskIdx] = brushAlpha;
2712
2746
  }
2713
2747
  }
2714
2748
  }
@@ -2796,14 +2830,14 @@ function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth,
2796
2830
  }
2797
2831
 
2798
2832
  // src/History/PixelMutator/mutatorApplyRectBrush.ts
2799
- var defaults6 = {
2833
+ var defaults7 = {
2800
2834
  applyRectBrushToPixelData,
2801
2835
  getRectBrushOrPencilBounds
2802
2836
  };
2803
- var mutatorApplyRectBrush = ((writer, deps = defaults6) => {
2837
+ var mutatorApplyRectBrush = ((writer, deps = defaults7) => {
2804
2838
  const {
2805
- applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults6.applyRectBrushToPixelData,
2806
- getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults6.getRectBrushOrPencilBounds
2839
+ applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults7.applyRectBrushToPixelData,
2840
+ getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults7.getRectBrushOrPencilBounds
2807
2841
  } = deps;
2808
2842
  const boundsOut = {
2809
2843
  x: 0,
@@ -2842,18 +2876,18 @@ function getRectBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushWidth, brushHeigh
2842
2876
  }
2843
2877
 
2844
2878
  // src/History/PixelMutator/mutatorApplyRectBrushStroke.ts
2845
- var defaults7 = {
2879
+ var defaults8 = {
2846
2880
  forEachLinePoint,
2847
2881
  blendColorPixelDataAlphaMask,
2848
2882
  getRectBrushOrPencilBounds,
2849
2883
  getRectBrushOrPencilStrokeBounds
2850
2884
  };
2851
- var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
2885
+ var mutatorApplyRectBrushStroke = ((writer, deps = defaults8) => {
2852
2886
  const {
2853
- forEachLinePoint: forEachLinePoint2 = defaults7.forEachLinePoint,
2854
- blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults7.blendColorPixelDataAlphaMask,
2855
- getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults7.getRectBrushOrPencilBounds,
2856
- getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults7.getRectBrushOrPencilStrokeBounds
2887
+ forEachLinePoint: forEachLinePoint2 = defaults8.forEachLinePoint,
2888
+ blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults8.blendColorPixelDataAlphaMask,
2889
+ getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds,
2890
+ getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults8.getRectBrushOrPencilStrokeBounds
2857
2891
  } = deps;
2858
2892
  const strokeBoundsOut = {
2859
2893
  x: 0,
@@ -2875,6 +2909,12 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
2875
2909
  w: 0,
2876
2910
  h: 0
2877
2911
  };
2912
+ const mask = {
2913
+ type: 0 /* ALPHA */,
2914
+ data: null,
2915
+ w: 0,
2916
+ h: 0
2917
+ };
2878
2918
  return {
2879
2919
  applyRectBrushStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
2880
2920
  const {
@@ -2884,7 +2924,10 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
2884
2924
  h: bh
2885
2925
  } = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
2886
2926
  if (bw <= 0 || bh <= 0) return;
2887
- const mask = new Uint8Array(bw * bh);
2927
+ mask.data = new Uint8Array(bw * bh);
2928
+ mask.w = bw;
2929
+ mask.h = bh;
2930
+ const maskData = mask.data;
2888
2931
  const halfW = brushWidth / 2;
2889
2932
  const halfH = brushHeight / 2;
2890
2933
  const invHalfW = 1 / halfW;
@@ -2917,8 +2960,8 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
2917
2960
  const strength = fallOff(dist);
2918
2961
  if (strength > 0) {
2919
2962
  const intensity = strength * 255 | 0;
2920
- if (intensity > mask[maskIdx]) {
2921
- mask[maskIdx] = intensity;
2963
+ if (intensity > maskData[maskIdx]) {
2964
+ maskData[maskIdx] = intensity;
2922
2965
  }
2923
2966
  }
2924
2967
  }
@@ -2936,16 +2979,16 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
2936
2979
  });
2937
2980
 
2938
2981
  // src/History/PixelMutator/mutatorApplyRectPencil.ts
2939
- var defaults8 = {
2982
+ var defaults9 = {
2940
2983
  applyRectBrushToPixelData,
2941
2984
  getRectBrushOrPencilBounds,
2942
2985
  fallOff: () => 1
2943
2986
  };
2944
- var mutatorApplyRectPencil = ((writer, deps = defaults8) => {
2987
+ var mutatorApplyRectPencil = ((writer, deps = defaults9) => {
2945
2988
  const {
2946
- applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults8.applyRectBrushToPixelData,
2947
- getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds,
2948
- fallOff = defaults8.fallOff
2989
+ applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults9.applyRectBrushToPixelData,
2990
+ getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
2991
+ fallOff = defaults9.fallOff
2949
2992
  } = deps;
2950
2993
  const boundsOut = {
2951
2994
  x: 0,
@@ -2969,18 +3012,18 @@ var mutatorApplyRectPencil = ((writer, deps = defaults8) => {
2969
3012
  });
2970
3013
 
2971
3014
  // src/History/PixelMutator/mutatorApplyRectPencilStroke.ts
2972
- var defaults9 = {
3015
+ var defaults10 = {
2973
3016
  forEachLinePoint,
2974
3017
  getRectBrushOrPencilBounds,
2975
3018
  getRectBrushOrPencilStrokeBounds,
2976
3019
  blendColorPixelDataBinaryMask
2977
3020
  };
2978
- var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
3021
+ var mutatorApplyRectPencilStroke = ((writer, deps = defaults10) => {
2979
3022
  const {
2980
- forEachLinePoint: forEachLinePoint2 = defaults9.forEachLinePoint,
2981
- blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults9.blendColorPixelDataBinaryMask,
2982
- getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
2983
- getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults9.getRectBrushOrPencilStrokeBounds
3023
+ forEachLinePoint: forEachLinePoint2 = defaults10.forEachLinePoint,
3024
+ blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults10.blendColorPixelDataBinaryMask,
3025
+ getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults10.getRectBrushOrPencilBounds,
3026
+ getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults10.getRectBrushOrPencilStrokeBounds
2984
3027
  } = deps;
2985
3028
  const strokeBoundsOut = {
2986
3029
  x: 0,
@@ -3002,6 +3045,12 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
3002
3045
  w: 0,
3003
3046
  h: 0
3004
3047
  };
3048
+ const mask = {
3049
+ type: 1 /* BINARY */,
3050
+ data: null,
3051
+ w: 0,
3052
+ h: 0
3053
+ };
3005
3054
  return {
3006
3055
  applyRectPencilStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, blendFn = sourceOverPerfect) {
3007
3056
  const {
@@ -3011,7 +3060,10 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
3011
3060
  h: bh
3012
3061
  } = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
3013
3062
  if (bw <= 0 || bh <= 0) return;
3014
- const mask = new Uint8Array(bw * bh);
3063
+ mask.data = new Uint8Array(bw * bh);
3064
+ mask.w = bw;
3065
+ mask.h = bh;
3066
+ const maskData = mask.data;
3015
3067
  const halfW = brushWidth / 2;
3016
3068
  const halfH = brushHeight / 2;
3017
3069
  const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
@@ -3038,7 +3090,7 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
3038
3090
  const dx = Math.abs(mx - fPx + centerOffset);
3039
3091
  const maskIdx = maskRowOffset + (mx - bx);
3040
3092
  if (dx <= halfW && dy <= halfH) {
3041
- mask[maskIdx] = 1;
3093
+ maskData[maskIdx] = 1;
3042
3094
  }
3043
3095
  }
3044
3096
  }
@@ -3100,12 +3152,12 @@ function blendColorPixelData(dst, color, opts = {}) {
3100
3152
  }
3101
3153
 
3102
3154
  // src/History/PixelMutator/mutatorBlendColor.ts
3103
- var defaults10 = {
3155
+ var defaults11 = {
3104
3156
  blendColorPixelData
3105
3157
  };
3106
- var mutatorBlendColor = ((writer, deps = defaults10) => {
3158
+ var mutatorBlendColor = ((writer, deps = defaults11) => {
3107
3159
  const {
3108
- blendColorPixelData: blendColorPixelData2 = defaults10.blendColorPixelData
3160
+ blendColorPixelData: blendColorPixelData2 = defaults11.blendColorPixelData
3109
3161
  } = deps;
3110
3162
  return {
3111
3163
  blendColor(color, opts = {}) {
@@ -3144,7 +3196,7 @@ function mutatorBlendPixel(writer) {
3144
3196
  }
3145
3197
 
3146
3198
  // src/PixelData/blendPixelData.ts
3147
- function blendPixelData(dst, src, opts) {
3199
+ function blendPixelData(dst, src, opts = {}) {
3148
3200
  const {
3149
3201
  x: targetX = 0,
3150
3202
  y: targetY = 0,
@@ -3226,15 +3278,15 @@ function blendPixelData(dst, src, opts) {
3226
3278
  }
3227
3279
 
3228
3280
  // src/History/PixelMutator/mutatorBlendPixelData.ts
3229
- var defaults11 = {
3281
+ var defaults12 = {
3230
3282
  blendPixelData
3231
3283
  };
3232
- var mutatorBlendPixelData = ((writer, deps = defaults11) => {
3284
+ var mutatorBlendPixelData = ((writer, deps = defaults12) => {
3233
3285
  const {
3234
- blendPixelData: blendPixelData2 = defaults11.blendPixelData
3286
+ blendPixelData: blendPixelData2 = defaults12.blendPixelData
3235
3287
  } = deps;
3236
3288
  return {
3237
- blendPixelData(src, opts) {
3289
+ blendPixelData(src, opts = {}) {
3238
3290
  const {
3239
3291
  x = 0,
3240
3292
  y = 0,
@@ -3247,143 +3299,430 @@ var mutatorBlendPixelData = ((writer, deps = defaults11) => {
3247
3299
  };
3248
3300
  });
3249
3301
 
3250
- // src/PixelData/fillPixelData.ts
3251
- var SCRATCH_RECT = makeClippedRect();
3252
- function fillPixelData(dst, color, _x, _y, _w, _h, _mask) {
3253
- let x;
3254
- let y;
3255
- let w;
3256
- let h;
3257
- let mask;
3258
- if (typeof _x === "object") {
3259
- x = _x.x ?? 0;
3260
- y = _x.y ?? 0;
3261
- w = _x.w ?? dst.width;
3262
- h = _x.h ?? dst.height;
3263
- mask = _x.mask;
3264
- } else if (typeof _x === "number") {
3265
- x = _x;
3266
- y = _y;
3267
- w = _w;
3268
- h = _h;
3269
- mask = _mask;
3270
- } else {
3302
+ // src/PixelData/blendPixelDataAlphaMask.ts
3303
+ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
3304
+ const {
3305
+ x: targetX = 0,
3306
+ y: targetY = 0,
3307
+ sx: sourceX = 0,
3308
+ sy: sourceY = 0,
3309
+ w: width = src.width,
3310
+ h: height = src.height,
3311
+ alpha: globalAlpha = 255,
3312
+ blendFn = sourceOverPerfect,
3313
+ mx = 0,
3314
+ my = 0,
3315
+ invertMask = false
3316
+ } = opts;
3317
+ if (globalAlpha === 0) return;
3318
+ let x = targetX;
3319
+ let y = targetY;
3320
+ let sx = sourceX;
3321
+ let sy = sourceY;
3322
+ let w = width;
3323
+ let h = height;
3324
+ if (sx < 0) {
3325
+ x -= sx;
3326
+ w += sx;
3327
+ sx = 0;
3328
+ }
3329
+ if (sy < 0) {
3330
+ y -= sy;
3331
+ h += sy;
3332
+ sy = 0;
3333
+ }
3334
+ w = Math.min(w, src.width - sx);
3335
+ h = Math.min(h, src.height - sy);
3336
+ if (x < 0) {
3337
+ sx -= x;
3338
+ w += x;
3271
3339
  x = 0;
3340
+ }
3341
+ if (y < 0) {
3342
+ sy -= y;
3343
+ h += y;
3272
3344
  y = 0;
3273
- w = dst.width;
3274
- h = dst.height;
3275
3345
  }
3276
- const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT);
3277
- if (!clip.inBounds) return;
3278
- const {
3279
- x: finalX,
3280
- y: finalY,
3281
- w: actualW,
3282
- h: actualH
3283
- } = clip;
3284
- const dst32 = dst.data32;
3346
+ const actualW = Math.min(w, dst.width - x);
3347
+ const actualH = Math.min(h, dst.height - y);
3348
+ if (actualW <= 0 || actualH <= 0) return;
3285
3349
  const dw = dst.width;
3286
- if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
3287
- dst32.fill(color);
3288
- return;
3289
- }
3290
- if (mask) {
3291
- for (let iy = 0; iy < actualH; iy++) {
3292
- const currentY = finalY + iy;
3293
- const maskY = currentY - y;
3294
- const maskOffset = maskY * w;
3295
- for (let ix = 0; ix < actualW; ix++) {
3296
- const currentX = finalX + ix;
3297
- const maskX = currentX - x;
3298
- const maskIndex = maskOffset + maskX;
3299
- const isMasked = mask[maskIndex];
3300
- if (isMasked) {
3301
- const dstIndex = currentY * dw + currentX;
3302
- dst32[dstIndex] = color;
3350
+ const sw = src.width;
3351
+ const mPitch = alphaMask.w;
3352
+ const maskData = alphaMask.data;
3353
+ const dx = x - targetX | 0;
3354
+ const dy = y - targetY | 0;
3355
+ const dst32 = dst.data32;
3356
+ const src32 = src.data32;
3357
+ let dIdx = y * dw + x | 0;
3358
+ let sIdx = sy * sw + sx | 0;
3359
+ let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
3360
+ const dStride = dw - actualW | 0;
3361
+ const sStride = sw - actualW | 0;
3362
+ const mStride = mPitch - actualW | 0;
3363
+ const isOpaque = globalAlpha === 255;
3364
+ const isOverwrite = blendFn.isOverwrite || false;
3365
+ for (let iy = 0; iy < actualH; iy++) {
3366
+ for (let ix = 0; ix < actualW; ix++) {
3367
+ const mVal = maskData[mIdx];
3368
+ const effM = invertMask ? 255 - mVal : mVal;
3369
+ if (effM === 0) {
3370
+ dIdx++;
3371
+ sIdx++;
3372
+ mIdx++;
3373
+ continue;
3374
+ }
3375
+ const srcCol = src32[sIdx];
3376
+ const srcAlpha = srcCol >>> 24;
3377
+ if (srcAlpha === 0 && !isOverwrite) {
3378
+ dIdx++;
3379
+ sIdx++;
3380
+ mIdx++;
3381
+ continue;
3382
+ }
3383
+ let weight = globalAlpha;
3384
+ if (isOpaque) {
3385
+ weight = effM;
3386
+ } else if (effM !== 255) {
3387
+ weight = effM * globalAlpha + 128 >> 8;
3388
+ }
3389
+ if (weight === 0) {
3390
+ dIdx++;
3391
+ sIdx++;
3392
+ mIdx++;
3393
+ continue;
3394
+ }
3395
+ let finalCol = srcCol;
3396
+ if (weight < 255) {
3397
+ const a = srcAlpha * weight + 128 >> 8;
3398
+ if (a === 0 && !isOverwrite) {
3399
+ dIdx++;
3400
+ sIdx++;
3401
+ mIdx++;
3402
+ continue;
3303
3403
  }
3404
+ finalCol = (srcCol & 16777215 | a << 24) >>> 0;
3304
3405
  }
3406
+ dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
3407
+ dIdx++;
3408
+ sIdx++;
3409
+ mIdx++;
3305
3410
  }
3306
- } else {
3307
- for (let iy = 0; iy < actualH; iy++) {
3308
- const start = (finalY + iy) * dw + finalX;
3309
- const end = start + actualW;
3310
- dst32.fill(color, start, end);
3311
- }
3411
+ dIdx += dStride;
3412
+ sIdx += sStride;
3413
+ mIdx += mStride;
3312
3414
  }
3313
3415
  }
3314
3416
 
3315
- // src/History/PixelMutator/mutatorClear.ts
3316
- var defaults12 = {
3317
- fillPixelData
3318
- };
3319
- var mutatorClear = ((writer, deps = defaults12) => {
3320
- const {
3321
- fillPixelData: fillPixelData2 = defaults12.fillPixelData
3322
- } = deps;
3323
- return {
3324
- clear(rect = {}) {
3325
- const {
3326
- x = 0,
3327
- y = 0,
3328
- w = writer.target.width,
3329
- h = writer.target.height,
3330
- mask = void 0
3331
- } = rect;
3332
- writer.accumulator.storeRegionBeforeState(x, y, w, h);
3333
- fillPixelData2(writer.target, 0, x, y, w, h, mask);
3334
- }
3335
- };
3336
- });
3337
-
3338
- // src/History/PixelMutator/mutatorFill.ts
3417
+ // src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts
3339
3418
  var defaults13 = {
3340
- fillPixelData
3419
+ blendPixelDataAlphaMask
3341
3420
  };
3342
- var mutatorFill = ((writer, deps = defaults13) => {
3421
+ var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults13) => {
3343
3422
  const {
3344
- fillPixelData: fillPixelData2 = defaults13.fillPixelData
3423
+ blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults13.blendPixelDataAlphaMask
3345
3424
  } = deps;
3346
3425
  return {
3347
- fill(color, rect = {}) {
3348
- const {
3349
- x = 0,
3350
- y = 0,
3351
- w = writer.target.width,
3352
- h = writer.target.height,
3353
- mask = void 0
3354
- } = rect;
3426
+ blendPixelDataAlphaMask(src, mask, opts = {}) {
3427
+ const x = opts.x ?? 0;
3428
+ const y = opts.y ?? 0;
3429
+ const w = opts.w ?? src.width;
3430
+ const h = opts.h ?? src.height;
3355
3431
  writer.accumulator.storeRegionBeforeState(x, y, w, h);
3356
- fillPixelData2(writer.target, color, x, y, w, h, mask);
3432
+ blendPixelDataAlphaMask2(writer.target, src, mask, opts);
3357
3433
  }
3358
3434
  };
3359
3435
  });
3360
3436
 
3361
- // src/PixelData/invertPixelData.ts
3362
- var SCRATCH_RECT2 = makeClippedRect();
3363
- function invertPixelData(pixelData, opts = {}) {
3364
- const dst = pixelData;
3437
+ // src/PixelData/blendPixelDataBinaryMask.ts
3438
+ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
3365
3439
  const {
3366
3440
  x: targetX = 0,
3367
3441
  y: targetY = 0,
3368
- w: width = pixelData.width,
3369
- h: height = pixelData.height,
3370
- mask,
3371
- mw,
3442
+ sx: sourceX = 0,
3443
+ sy: sourceY = 0,
3444
+ w: width = src.width,
3445
+ h: height = src.height,
3446
+ alpha: globalAlpha = 255,
3447
+ blendFn = sourceOverPerfect,
3372
3448
  mx = 0,
3373
3449
  my = 0,
3374
3450
  invertMask = false
3375
3451
  } = opts;
3376
- const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT2);
3377
- if (!clip.inBounds) return;
3378
- const {
3379
- x,
3452
+ if (globalAlpha === 0) return;
3453
+ let x = targetX;
3454
+ let y = targetY;
3455
+ let sx = sourceX;
3456
+ let sy = sourceY;
3457
+ let w = width;
3458
+ let h = height;
3459
+ if (sx < 0) {
3460
+ x -= sx;
3461
+ w += sx;
3462
+ sx = 0;
3463
+ }
3464
+ if (sy < 0) {
3465
+ y -= sy;
3466
+ h += sy;
3467
+ sy = 0;
3468
+ }
3469
+ w = Math.min(w, src.width - sx);
3470
+ h = Math.min(h, src.height - sy);
3471
+ if (x < 0) {
3472
+ sx -= x;
3473
+ w += x;
3474
+ x = 0;
3475
+ }
3476
+ if (y < 0) {
3477
+ sy -= y;
3478
+ h += y;
3479
+ y = 0;
3480
+ }
3481
+ const actualW = Math.min(w, dst.width - x);
3482
+ const actualH = Math.min(h, dst.height - y);
3483
+ if (actualW <= 0 || actualH <= 0) return;
3484
+ const dx = x - targetX | 0;
3485
+ const dy = y - targetY | 0;
3486
+ const dst32 = dst.data32;
3487
+ const src32 = src.data32;
3488
+ const dw = dst.width;
3489
+ const sw = src.width;
3490
+ const mPitch = binaryMask.w;
3491
+ const maskData = binaryMask.data;
3492
+ let dIdx = y * dw + x | 0;
3493
+ let sIdx = sy * sw + sx | 0;
3494
+ let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
3495
+ const dStride = dw - actualW | 0;
3496
+ const sStride = sw - actualW | 0;
3497
+ const mStride = mPitch - actualW | 0;
3498
+ const skipVal = invertMask ? 1 : 0;
3499
+ const isOpaque = globalAlpha === 255;
3500
+ const isOverwrite = blendFn.isOverwrite || false;
3501
+ for (let iy = 0; iy < actualH; iy++) {
3502
+ for (let ix = 0; ix < actualW; ix++) {
3503
+ if (maskData[mIdx] === skipVal) {
3504
+ dIdx++;
3505
+ sIdx++;
3506
+ mIdx++;
3507
+ continue;
3508
+ }
3509
+ const srcCol = src32[sIdx];
3510
+ const srcAlpha = srcCol >>> 24;
3511
+ if (srcAlpha === 0 && !isOverwrite) {
3512
+ dIdx++;
3513
+ sIdx++;
3514
+ mIdx++;
3515
+ continue;
3516
+ }
3517
+ let finalCol = srcCol;
3518
+ if (!isOpaque) {
3519
+ const a = srcAlpha * globalAlpha + 128 >> 8;
3520
+ if (a === 0 && !isOverwrite) {
3521
+ dIdx++;
3522
+ sIdx++;
3523
+ mIdx++;
3524
+ continue;
3525
+ }
3526
+ finalCol = (srcCol & 16777215 | a << 24) >>> 0;
3527
+ }
3528
+ dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
3529
+ dIdx++;
3530
+ sIdx++;
3531
+ mIdx++;
3532
+ }
3533
+ dIdx += dStride;
3534
+ sIdx += sStride;
3535
+ mIdx += mStride;
3536
+ }
3537
+ }
3538
+
3539
+ // src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts
3540
+ var defaults14 = {
3541
+ blendPixelDataBinaryMask
3542
+ };
3543
+ var mutatorBlendPixelDataBinaryMask = ((writer, deps = defaults14) => {
3544
+ const {
3545
+ blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults14.blendPixelDataBinaryMask
3546
+ } = deps;
3547
+ return {
3548
+ blendPixelDataBinaryMask(src, mask, opts = {}) {
3549
+ const x = opts.x ?? 0;
3550
+ const y = opts.y ?? 0;
3551
+ const w = opts.w ?? src.width;
3552
+ const h = opts.h ?? src.height;
3553
+ writer.accumulator.storeRegionBeforeState(x, y, w, h);
3554
+ blendPixelDataBinaryMask2(writer.target, src, mask, opts);
3555
+ }
3556
+ };
3557
+ });
3558
+
3559
+ // src/PixelData/fillPixelData.ts
3560
+ var SCRATCH_RECT = makeClippedRect();
3561
+ function fillPixelData(dst, color, _x, _y, _w, _h) {
3562
+ let x;
3563
+ let y;
3564
+ let w;
3565
+ let h;
3566
+ if (typeof _x === "object") {
3567
+ x = _x.x ?? 0;
3568
+ y = _x.y ?? 0;
3569
+ w = _x.w ?? dst.width;
3570
+ h = _x.h ?? dst.height;
3571
+ } else if (typeof _x === "number") {
3572
+ x = _x;
3573
+ y = _y;
3574
+ w = _w;
3575
+ h = _h;
3576
+ } else {
3577
+ x = 0;
3578
+ y = 0;
3579
+ w = dst.width;
3580
+ h = dst.height;
3581
+ }
3582
+ const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT);
3583
+ if (!clip.inBounds) return;
3584
+ const {
3585
+ x: finalX,
3586
+ y: finalY,
3587
+ w: actualW,
3588
+ h: actualH
3589
+ } = clip;
3590
+ const dst32 = dst.data32;
3591
+ const dw = dst.width;
3592
+ if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
3593
+ dst32.fill(color);
3594
+ return;
3595
+ }
3596
+ for (let iy = 0; iy < actualH; iy++) {
3597
+ const start = (finalY + iy) * dw + finalX;
3598
+ const end = start + actualW;
3599
+ dst32.fill(color, start, end);
3600
+ }
3601
+ }
3602
+
3603
+ // src/History/PixelMutator/mutatorClear.ts
3604
+ var defaults15 = {
3605
+ fillPixelData
3606
+ };
3607
+ var mutatorClear = ((writer, deps = defaults15) => {
3608
+ const {
3609
+ fillPixelData: fillPixelData2 = defaults15.fillPixelData
3610
+ } = deps;
3611
+ return {
3612
+ clear(rect = {}) {
3613
+ const x = rect.x ?? 0;
3614
+ const y = rect.y ?? 0;
3615
+ const w = rect.w ?? writer.target.width;
3616
+ const h = rect.h ?? writer.target.height;
3617
+ writer.accumulator.storeRegionBeforeState(x, y, w, h);
3618
+ fillPixelData2(writer.target, 0, x, y, w, h);
3619
+ }
3620
+ };
3621
+ });
3622
+
3623
+ // src/History/PixelMutator/mutatorFill.ts
3624
+ var defaults16 = {
3625
+ fillPixelData
3626
+ };
3627
+ var mutatorFill = ((writer, deps = defaults16) => {
3628
+ const {
3629
+ fillPixelData: fillPixelData2 = defaults16.fillPixelData
3630
+ } = deps;
3631
+ return {
3632
+ fill(color, rect = {}) {
3633
+ const {
3634
+ x = 0,
3635
+ y = 0,
3636
+ w = writer.target.width,
3637
+ h = writer.target.height
3638
+ } = rect;
3639
+ writer.accumulator.storeRegionBeforeState(x, y, w, h);
3640
+ fillPixelData2(writer.target, color, x, y, w, h);
3641
+ }
3642
+ };
3643
+ });
3644
+
3645
+ // src/PixelData/fillPixelDataBinaryMask.ts
3646
+ var SCRATCH_RECT2 = makeClippedRect();
3647
+ function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
3648
+ if (alpha === 0) return;
3649
+ const maskW = mask.w;
3650
+ const maskH = mask.h;
3651
+ const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height, SCRATCH_RECT2);
3652
+ if (!clip.inBounds) return;
3653
+ const {
3654
+ x: finalX,
3655
+ y: finalY,
3656
+ w: actualW,
3657
+ h: actualH
3658
+ } = clip;
3659
+ const maskData = mask.data;
3660
+ const dst32 = dst.data32;
3661
+ const dw = dst.width;
3662
+ let finalCol = color;
3663
+ if (alpha < 255) {
3664
+ const baseSrcAlpha = color >>> 24;
3665
+ const colorRGB = color & 16777215;
3666
+ const a = baseSrcAlpha * alpha + 128 >> 8;
3667
+ finalCol = (colorRGB | a << 24) >>> 0;
3668
+ }
3669
+ for (let iy = 0; iy < actualH; iy++) {
3670
+ const currentY = finalY + iy;
3671
+ const maskY = currentY - y;
3672
+ const maskOffset = maskY * maskW;
3673
+ const dstRowOffset = currentY * dw;
3674
+ for (let ix = 0; ix < actualW; ix++) {
3675
+ const currentX = finalX + ix;
3676
+ const maskX = currentX - x;
3677
+ const maskIndex = maskOffset + maskX;
3678
+ if (maskData[maskIndex]) {
3679
+ dst32[dstRowOffset + currentX] = finalCol;
3680
+ }
3681
+ }
3682
+ }
3683
+ }
3684
+
3685
+ // src/History/PixelMutator/mutatorFillBinaryMask.ts
3686
+ var defaults17 = {
3687
+ fillPixelDataBinaryMask
3688
+ };
3689
+ var mutatorFillBinaryMask = ((writer, deps = defaults17) => {
3690
+ const {
3691
+ fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults17.fillPixelDataBinaryMask
3692
+ } = deps;
3693
+ return {
3694
+ fillBinaryMask(color, mask, alpha = 255, x = 0, y = 0) {
3695
+ writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
3696
+ fillPixelDataBinaryMask2(writer.target, color, mask, alpha, x, y);
3697
+ }
3698
+ };
3699
+ });
3700
+
3701
+ // src/PixelData/invertPixelData.ts
3702
+ var SCRATCH_RECT3 = makeClippedRect();
3703
+ function invertPixelData(pixelData, opts = {}) {
3704
+ const dst = pixelData;
3705
+ const {
3706
+ x: targetX = 0,
3707
+ y: targetY = 0,
3708
+ w: width = pixelData.width,
3709
+ h: height = pixelData.height,
3710
+ mask,
3711
+ mx = 0,
3712
+ my = 0,
3713
+ invertMask = false
3714
+ } = opts;
3715
+ const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT3);
3716
+ if (!clip.inBounds) return;
3717
+ const {
3718
+ x,
3380
3719
  y,
3381
3720
  w: actualW,
3382
3721
  h: actualH
3383
3722
  } = clip;
3384
3723
  const dst32 = dst.data32;
3385
3724
  const dw = dst.width;
3386
- const mPitch = mw ?? width;
3725
+ const mPitch = mask?.w ?? width;
3387
3726
  const dx = x - targetX;
3388
3727
  const dy = y - targetY;
3389
3728
  let dIdx = y * dw + x;
@@ -3391,9 +3730,10 @@ function invertPixelData(pixelData, opts = {}) {
3391
3730
  const dStride = dw - actualW;
3392
3731
  const mStride = mPitch - actualW;
3393
3732
  if (mask) {
3733
+ const maskData = mask.data;
3394
3734
  for (let iy = 0; iy < actualH; iy++) {
3395
3735
  for (let ix = 0; ix < actualW; ix++) {
3396
- const mVal = mask[mIdx];
3736
+ const mVal = maskData[mIdx];
3397
3737
  const isHit = invertMask ? mVal === 0 : mVal === 1;
3398
3738
  if (isHit) {
3399
3739
  dst32[dIdx] = dst32[dIdx] ^ 16777215;
@@ -3416,12 +3756,12 @@ function invertPixelData(pixelData, opts = {}) {
3416
3756
  }
3417
3757
 
3418
3758
  // src/History/PixelMutator/mutatorInvert.ts
3419
- var defaults14 = {
3759
+ var defaults18 = {
3420
3760
  invertPixelData
3421
3761
  };
3422
- var mutatorInvert = ((writer, deps = defaults14) => {
3762
+ var mutatorInvert = ((writer, deps = defaults18) => {
3423
3763
  const {
3424
- invertPixelData: invertPixelData2 = defaults14.invertPixelData
3764
+ invertPixelData: invertPixelData2 = defaults18.invertPixelData
3425
3765
  } = deps;
3426
3766
  return {
3427
3767
  invert(opts = {}) {
@@ -3440,21 +3780,26 @@ var mutatorInvert = ((writer, deps = defaults14) => {
3440
3780
  // src/History/PixelMutator.ts
3441
3781
  function makeFullPixelMutator(writer) {
3442
3782
  return {
3783
+ // @sort
3443
3784
  ...mutatorApplyAlphaMask(writer),
3444
3785
  ...mutatorApplyBinaryMask(writer),
3445
- ...mutatorBlendPixelData(writer),
3446
- ...mutatorBlendColor(writer),
3447
- ...mutatorBlendPixel(writer),
3448
- ...mutatorFill(writer),
3449
- ...mutatorInvert(writer),
3450
3786
  ...mutatorApplyCircleBrush(writer),
3451
3787
  ...mutatorApplyCircleBrushStroke(writer),
3788
+ ...mutatorApplyCirclePencil(writer),
3452
3789
  ...mutatorApplyCirclePencilStroke(writer),
3453
3790
  ...mutatorApplyRectBrush(writer),
3454
3791
  ...mutatorApplyRectBrushStroke(writer),
3455
3792
  ...mutatorApplyRectPencil(writer),
3456
3793
  ...mutatorApplyRectPencilStroke(writer),
3457
- ...mutatorClear(writer)
3794
+ ...mutatorBlendColor(writer),
3795
+ ...mutatorBlendPixel(writer),
3796
+ ...mutatorBlendPixelData(writer),
3797
+ ...mutatorBlendPixelDataAlphaMask(writer),
3798
+ ...mutatorBlendPixelDataBinaryMask(writer),
3799
+ ...mutatorClear(writer),
3800
+ ...mutatorFill(writer),
3801
+ ...mutatorFillBinaryMask(writer),
3802
+ ...mutatorInvert(writer)
3458
3803
  };
3459
3804
  }
3460
3805
 
@@ -3501,39 +3846,6 @@ var PixelWriter = class {
3501
3846
  }
3502
3847
  };
3503
3848
 
3504
- // src/History/PixelMutator/mutatorApplyCirclePencil.ts
3505
- var defaults15 = {
3506
- applyCircleBrushToPixelData,
3507
- getCircleBrushOrPencilBounds,
3508
- fallOff: () => 1
3509
- };
3510
- var mutatorApplyCirclePencil = ((writer, deps = defaults15) => {
3511
- const {
3512
- applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults15.applyCircleBrushToPixelData,
3513
- getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults15.getCircleBrushOrPencilBounds,
3514
- fallOff = defaults15.fallOff
3515
- } = deps;
3516
- const boundsOut = {
3517
- x: 0,
3518
- y: 0,
3519
- w: 0,
3520
- h: 0
3521
- };
3522
- return {
3523
- applyCirclePencil(color, centerX, centerY, brushSize, alpha = 255, blendFn) {
3524
- const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
3525
- const {
3526
- x,
3527
- y,
3528
- w,
3529
- h
3530
- } = bounds;
3531
- writer.accumulator.storeRegionBeforeState(x, y, w, h);
3532
- applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
3533
- }
3534
- };
3535
- });
3536
-
3537
3849
  // src/ImageData/copyImageData.ts
3538
3850
  function copyImageData({
3539
3851
  data,
@@ -3565,8 +3877,8 @@ function makeImageDataLike(width, height, data) {
3565
3877
  };
3566
3878
  }
3567
3879
 
3568
- // src/ImageData/imageDataToAlphaMask.ts
3569
- function imageDataToAlphaMask(imageData) {
3880
+ // src/ImageData/imageDataToAlphaMaskBuffer.ts
3881
+ function imageDataToAlphaMaskBuffer(imageData) {
3570
3882
  const {
3571
3883
  width,
3572
3884
  height,
@@ -3656,13 +3968,13 @@ function resampleImageData(source, factor) {
3656
3968
  }
3657
3969
 
3658
3970
  // src/ImageData/resizeImageData.ts
3659
- function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0) {
3971
+ function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0) {
3660
3972
  const result = new ImageData(newWidth, newHeight);
3661
3973
  const {
3662
3974
  width: oldW,
3663
3975
  height: oldH,
3664
3976
  data: oldData
3665
- } = current;
3977
+ } = target;
3666
3978
  const newData = result.data;
3667
3979
  const x0 = Math.max(0, offsetX);
3668
3980
  const y0 = Math.max(0, offsetY);
@@ -3817,7 +4129,7 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
3817
4129
 
3818
4130
  // src/ImageData/writeImageDataBuffer.ts
3819
4131
  var SCRATCH_BLIT3 = makeClippedBlit();
3820
- function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
4132
+ function writeImageDataBuffer(target, data, _x, _y, _w, _h) {
3821
4133
  const {
3822
4134
  x,
3823
4135
  y,
@@ -3833,7 +4145,7 @@ function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
3833
4145
  width: dstW,
3834
4146
  height: dstH,
3835
4147
  data: dst
3836
- } = imageData;
4148
+ } = target;
3837
4149
  const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT3);
3838
4150
  if (!clip.inBounds) return;
3839
4151
  const {
@@ -4079,22 +4391,100 @@ async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
4079
4391
  return formatsPromise;
4080
4392
  }
4081
4393
 
4082
- // src/Mask/applyBinaryMaskToAlphaMask.ts
4083
- function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWidth, opts = {}) {
4084
- const {
4085
- x: targetX = 0,
4086
- y: targetY = 0,
4087
- w: reqWidth = 0,
4088
- h: reqHeight = 0,
4089
- mx = 0,
4090
- my = 0,
4091
- invertMask = false
4092
- } = opts;
4093
- if (dstWidth <= 0) return;
4094
- if (binaryMaskSrc.length === 0) return;
4095
- if (srcWidth <= 0) return;
4096
- const dstHeight = alphaMaskDst.length / dstWidth | 0;
4097
- const srcHeight = binaryMaskSrc.length / srcWidth | 0;
4394
+ // src/Mask/AlphaMask.ts
4395
+ function makeAlphaMask(w, h, data) {
4396
+ return {
4397
+ type: 0 /* ALPHA */,
4398
+ data: data ?? new Uint8Array(w * h),
4399
+ w,
4400
+ h
4401
+ };
4402
+ }
4403
+
4404
+ // src/Mask/BinaryMask.ts
4405
+ function makeBinaryMask(w, h, data) {
4406
+ return {
4407
+ type: 1 /* BINARY */,
4408
+ data: data ?? new Uint8Array(w * h),
4409
+ w,
4410
+ h
4411
+ };
4412
+ }
4413
+
4414
+ // src/Mask/CircleBrushAlphaMask.ts
4415
+ function makeCircleBrushAlphaMask(size, fallOff = () => 1) {
4416
+ const area = size * size;
4417
+ const data = new Uint8Array(area);
4418
+ const radius = size / 2;
4419
+ const invR = 1 / radius;
4420
+ const minOffset = -Math.ceil(radius - 0.5);
4421
+ for (let y = 0; y < size; y++) {
4422
+ for (let x = 0; x < size; x++) {
4423
+ const dx = x - radius + 0.5;
4424
+ const dy = y - radius + 0.5;
4425
+ const distSqr = dx * dx + dy * dy;
4426
+ if (distSqr <= radius * radius) {
4427
+ const dist = Math.sqrt(distSqr);
4428
+ data[y * size + x] = fallOff(1 - dist * invR) * 255 | 0;
4429
+ }
4430
+ }
4431
+ }
4432
+ return {
4433
+ type: 0 /* ALPHA */,
4434
+ data,
4435
+ w: size,
4436
+ h: size,
4437
+ radius,
4438
+ size,
4439
+ minOffset
4440
+ };
4441
+ }
4442
+
4443
+ // src/Mask/CircleBrushBinaryMask.ts
4444
+ function makeCircleBrushBinaryMask(size) {
4445
+ const area = size * size;
4446
+ const data = new Uint8Array(area);
4447
+ const radius = size / 2;
4448
+ const minOffset = -Math.ceil(radius - 0.5);
4449
+ for (let y = 0; y < size; y++) {
4450
+ for (let x = 0; x < size; x++) {
4451
+ const dx = x - radius + 0.5;
4452
+ const dy = y - radius + 0.5;
4453
+ const distSqr = dx * dx + dy * dy;
4454
+ if (distSqr <= radius * radius) {
4455
+ data[y * size + x] = 1;
4456
+ }
4457
+ }
4458
+ }
4459
+ return {
4460
+ type: 1 /* BINARY */,
4461
+ data,
4462
+ w: size,
4463
+ h: size,
4464
+ radius,
4465
+ size,
4466
+ minOffset
4467
+ };
4468
+ }
4469
+
4470
+ // src/Mask/applyBinaryMaskToAlphaMask.ts
4471
+ function applyBinaryMaskToAlphaMask(alphaMaskDst, binaryMaskSrc, opts = {}) {
4472
+ const {
4473
+ x: targetX = 0,
4474
+ y: targetY = 0,
4475
+ w: reqWidth = 0,
4476
+ h: reqHeight = 0,
4477
+ mx = 0,
4478
+ my = 0,
4479
+ invertMask = false
4480
+ } = opts;
4481
+ const dstWidth = alphaMaskDst.w;
4482
+ if (dstWidth <= 0) return;
4483
+ if (binaryMaskSrc.data.length === 0) return;
4484
+ const srcWidth = binaryMaskSrc.w;
4485
+ if (srcWidth <= 0) return;
4486
+ const dstHeight = alphaMaskDst.data.length / dstWidth | 0;
4487
+ const srcHeight = binaryMaskSrc.data.length / srcWidth | 0;
4098
4488
  if (dstHeight <= 0) return;
4099
4489
  if (srcHeight <= 0) return;
4100
4490
  const dstX0 = Math.max(0, targetX);
@@ -4111,6 +4501,8 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
4111
4501
  if (srcY0 + (dstY1 - dstY0) <= 0) return;
4112
4502
  const iterW = Math.min(dstX1 - dstX0, srcWidth - srcX0);
4113
4503
  const iterH = Math.min(dstY1 - dstY0, srcHeight - srcY0);
4504
+ const srcData = binaryMaskSrc.data;
4505
+ const dstData = alphaMaskDst.data;
4114
4506
  let dstIdx = dstY0 * dstWidth + dstX0;
4115
4507
  let srcIdx = srcY0 * srcWidth + srcX0;
4116
4508
  if (invertMask) {
@@ -4119,8 +4511,8 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
4119
4511
  let d = dstIdx;
4120
4512
  let s = srcIdx;
4121
4513
  while (d < dstEnd) {
4122
- if (binaryMaskSrc[s] !== 0) {
4123
- alphaMaskDst[d] = 0;
4514
+ if (srcData[s] !== 0) {
4515
+ dstData[d] = 0;
4124
4516
  }
4125
4517
  d++;
4126
4518
  s++;
@@ -4134,8 +4526,8 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
4134
4526
  let d = dstIdx;
4135
4527
  let s = srcIdx;
4136
4528
  while (d < dstEnd) {
4137
- if (binaryMaskSrc[s] === 0) {
4138
- alphaMaskDst[d] = 0;
4529
+ if (srcData[s] === 0) {
4530
+ dstData[d] = 0;
4139
4531
  }
4140
4532
  d++;
4141
4533
  s++;
@@ -4148,25 +4540,72 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
4148
4540
 
4149
4541
  // src/Mask/copyMask.ts
4150
4542
  function copyMask(src) {
4151
- return src.slice();
4543
+ return {
4544
+ type: src.type,
4545
+ data: src.data.slice(),
4546
+ w: src.w,
4547
+ h: src.h
4548
+ };
4549
+ }
4550
+
4551
+ // src/Mask/extractMask.ts
4552
+ function extractMask(mask, xOrRect, y, w, h) {
4553
+ let finalX;
4554
+ let finalY;
4555
+ let finalW;
4556
+ let finalH;
4557
+ if (typeof xOrRect === "object") {
4558
+ finalX = xOrRect.x;
4559
+ finalY = xOrRect.y;
4560
+ finalW = xOrRect.w;
4561
+ finalH = xOrRect.h;
4562
+ } else {
4563
+ finalX = xOrRect;
4564
+ finalY = y;
4565
+ finalW = w;
4566
+ finalH = h;
4567
+ }
4568
+ const out = {
4569
+ type: mask.type,
4570
+ w: finalW,
4571
+ h: finalH,
4572
+ data: new Uint8Array(finalW * finalH)
4573
+ };
4574
+ const srcH = mask.h;
4575
+ const stride = mask.w;
4576
+ for (let row = 0; row < finalH; row++) {
4577
+ const currentSrcY = finalY + row;
4578
+ if (currentSrcY < 0 || currentSrcY >= srcH) continue;
4579
+ const start = Math.max(0, finalX);
4580
+ const end = Math.min(stride, finalX + finalW);
4581
+ if (start < end) {
4582
+ const srcOffset = currentSrcY * stride + start;
4583
+ const dstOffset = row * finalW + (start - finalX);
4584
+ const count = end - start;
4585
+ out.data.set(mask.data.subarray(srcOffset, srcOffset + count), dstOffset);
4586
+ }
4587
+ }
4588
+ return out;
4152
4589
  }
4153
4590
 
4154
4591
  // src/Mask/invertMask.ts
4155
4592
  function invertBinaryMask(dst) {
4156
- const len = dst.length;
4593
+ const data = dst.data;
4594
+ const len = data.length;
4157
4595
  for (let i = 0; i < len; i++) {
4158
- dst[i] = dst[i] === 0 ? 1 : 0;
4596
+ data[i] = data[i] === 0 ? 1 : 0;
4159
4597
  }
4160
4598
  }
4161
4599
  function invertAlphaMask(dst) {
4162
- const len = dst.length;
4600
+ const data = dst.data;
4601
+ const len = data.length;
4163
4602
  for (let i = 0; i < len; i++) {
4164
- dst[i] = 255 - dst[i];
4603
+ data[i] = 255 - data[i];
4165
4604
  }
4166
4605
  }
4167
4606
 
4168
4607
  // src/Mask/mergeAlphaMasks.ts
4169
- function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
4608
+ function mergeAlphaMasks(dst, src, opts) {
4170
4609
  const {
4171
4610
  x: targetX = 0,
4172
4611
  y: targetY = 0,
@@ -4177,15 +4616,17 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
4177
4616
  my = 0,
4178
4617
  invertMask = false
4179
4618
  } = opts;
4180
- const dstHeight = dst.length / dstWidth | 0;
4181
- const srcHeight = src.length / srcWidth | 0;
4182
4619
  if (width <= 0) return;
4183
4620
  if (height <= 0) return;
4184
4621
  if (globalAlpha === 0) return;
4622
+ const dstData = dst.data;
4623
+ const srcData = src.data;
4624
+ const srcWidth = src.w;
4625
+ const dstWidth = dst.w;
4185
4626
  const startX = Math.max(0, -targetX, -mx);
4186
4627
  const startY = Math.max(0, -targetY, -my);
4187
4628
  const endX = Math.min(width, dstWidth - targetX, srcWidth - mx);
4188
- const endY = Math.min(height, dstHeight - targetY, srcHeight - my);
4629
+ const endY = Math.min(height, dst.h - targetY, src.h - my);
4189
4630
  if (startX >= endX) return;
4190
4631
  if (startY >= endY) return;
4191
4632
  for (let iy = startY; iy < endY; iy++) {
@@ -4194,7 +4635,7 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
4194
4635
  let dIdx = dy * dstWidth + targetX + startX;
4195
4636
  let sIdx = sy * srcWidth + mx + startX;
4196
4637
  for (let ix = startX; ix < endX; ix++) {
4197
- const rawM = src[sIdx];
4638
+ const rawM = srcData[sIdx];
4198
4639
  const effectiveM = invertMask ? 255 - rawM : rawM;
4199
4640
  let weight = 0;
4200
4641
  if (effectiveM === 0) {
@@ -4208,13 +4649,13 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
4208
4649
  }
4209
4650
  if (weight !== 255) {
4210
4651
  if (weight === 0) {
4211
- dst[dIdx] = 0;
4652
+ dstData[dIdx] = 0;
4212
4653
  } else {
4213
- const da = dst[dIdx];
4654
+ const da = dstData[dIdx];
4214
4655
  if (da === 255) {
4215
- dst[dIdx] = weight;
4656
+ dstData[dIdx] = weight;
4216
4657
  } else if (da !== 0) {
4217
- dst[dIdx] = da * weight + 128 >> 8;
4658
+ dstData[dIdx] = da * weight + 128 >> 8;
4218
4659
  }
4219
4660
  }
4220
4661
  }
@@ -4225,7 +4666,7 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
4225
4666
  }
4226
4667
 
4227
4668
  // src/Mask/mergeBinaryMasks.ts
4228
- function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
4669
+ function mergeBinaryMasks(dst, src, opts) {
4229
4670
  const {
4230
4671
  x: targetX = 0,
4231
4672
  y: targetY = 0,
@@ -4235,10 +4676,12 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
4235
4676
  my = 0,
4236
4677
  invertMask = false
4237
4678
  } = opts;
4679
+ const dstData = dst.data;
4680
+ const srcData = src.data;
4681
+ const srcWidth = src.w;
4682
+ const dstWidth = dst.w;
4238
4683
  if (dstWidth <= 0) return;
4239
4684
  if (srcWidth <= 0) return;
4240
- const dstHeight = dst.length / dstWidth | 0;
4241
- const srcHeight = src.length / srcWidth | 0;
4242
4685
  let x = targetX;
4243
4686
  let y = targetY;
4244
4687
  let w = width;
@@ -4252,7 +4695,7 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
4252
4695
  y = 0;
4253
4696
  }
4254
4697
  w = Math.min(w, dstWidth - x);
4255
- h = Math.min(h, dstHeight - y);
4698
+ h = Math.min(h, dst.h - y);
4256
4699
  if (w <= 0) return;
4257
4700
  if (h <= 0) return;
4258
4701
  const startX = mx + (x - targetX);
@@ -4260,7 +4703,7 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
4260
4703
  const sX0 = Math.max(0, startX);
4261
4704
  const sY0 = Math.max(0, startY);
4262
4705
  const sX1 = Math.min(srcWidth, startX + w);
4263
- const sY1 = Math.min(srcHeight, startY + h);
4706
+ const sY1 = Math.min(src.h, startY + h);
4264
4707
  const finalW = sX1 - sX0;
4265
4708
  const finalH = sY1 - sY0;
4266
4709
  if (finalW <= 0) return;
@@ -4273,10 +4716,10 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
4273
4716
  let sIdx = sY0 * srcWidth + sX0;
4274
4717
  for (let iy = 0; iy < finalH; iy++) {
4275
4718
  for (let ix = 0; ix < finalW; ix++) {
4276
- const mVal = src[sIdx];
4719
+ const mVal = srcData[sIdx];
4277
4720
  const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
4278
4721
  if (isMaskedOut) {
4279
- dst[dIdx] = 0;
4722
+ dstData[dIdx] = 0;
4280
4723
  }
4281
4724
  dIdx++;
4282
4725
  sIdx++;
@@ -4286,6 +4729,177 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
4286
4729
  }
4287
4730
  }
4288
4731
 
4732
+ // src/Mask/setMaskData.ts
4733
+ function setMaskData(mask, width, height, data) {
4734
+ ;
4735
+ mask.w = width;
4736
+ mask.h = height;
4737
+ mask.data = data;
4738
+ }
4739
+
4740
+ // src/MaskRect/subtractBinaryMaskRects.ts
4741
+ function subtractBinaryMaskRects(current, subtracting) {
4742
+ let result = [...current];
4743
+ for (const sub of subtracting) {
4744
+ const next = [];
4745
+ for (const r of result) {
4746
+ const ix = Math.max(r.x, sub.x);
4747
+ const iy = Math.max(r.y, sub.y);
4748
+ const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
4749
+ const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
4750
+ if (ix >= ix2 || iy >= iy2) {
4751
+ next.push(r);
4752
+ continue;
4753
+ }
4754
+ if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
4755
+ if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
4756
+ if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
4757
+ if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
4758
+ }
4759
+ result = next;
4760
+ }
4761
+ return result;
4762
+ }
4763
+ function pushPiece(dest, r, x, y, w, h) {
4764
+ if (r.data === null || r.data === void 0) {
4765
+ dest.push({
4766
+ x,
4767
+ y,
4768
+ w,
4769
+ h,
4770
+ data: null,
4771
+ type: null
4772
+ });
4773
+ return;
4774
+ }
4775
+ const lx = x - r.x;
4776
+ const ly = y - r.y;
4777
+ const data = new Uint8Array(w * h);
4778
+ for (let row = 0; row < h; row++) {
4779
+ data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
4780
+ }
4781
+ dest.push({
4782
+ x,
4783
+ y,
4784
+ w,
4785
+ h,
4786
+ data,
4787
+ type: 1 /* BINARY */
4788
+ });
4789
+ }
4790
+
4791
+ // src/Rect/getRectsBounds.ts
4792
+ function getRectsBounds(rects) {
4793
+ if (rects.length === 1) return {
4794
+ ...rects[0]
4795
+ };
4796
+ let minX = Infinity, minY = Infinity;
4797
+ let maxX = -Infinity, maxY = -Infinity;
4798
+ for (let i = 0; i < rects.length; i++) {
4799
+ const r = rects[i];
4800
+ const x1 = r.x;
4801
+ const y1 = r.y;
4802
+ const x2 = x1 + r.w;
4803
+ const y2 = y1 + r.h;
4804
+ if (x1 < minX) minX = x1;
4805
+ if (y1 < minY) minY = y1;
4806
+ if (x2 > maxX) maxX = x2;
4807
+ if (y2 > maxY) maxY = y2;
4808
+ }
4809
+ return {
4810
+ x: minX,
4811
+ y: minY,
4812
+ w: maxX - minX,
4813
+ h: maxY - minY
4814
+ };
4815
+ }
4816
+
4817
+ // src/MaskRect/merge2BinaryMaskRects.ts
4818
+ function merge2BinaryMaskRects(a, b) {
4819
+ const bounds = getRectsBounds([a, b]);
4820
+ if ((a.data === null || a.data === void 0) && (b.data === null || b.data === void 0)) {
4821
+ const ix = Math.max(a.x, b.x);
4822
+ const iy = Math.max(a.y, b.y);
4823
+ const ir = Math.min(a.x + a.w, b.x + b.w);
4824
+ const ib = Math.min(a.y + a.h, b.y + b.h);
4825
+ const iw = Math.max(0, ir - ix);
4826
+ const ih = Math.max(0, ib - iy);
4827
+ const intersectionArea = iw * ih;
4828
+ const areaA = a.w * a.h;
4829
+ const areaB = b.w * b.h;
4830
+ const boundsArea = bounds.w * bounds.h;
4831
+ if (boundsArea === areaA + areaB - intersectionArea) {
4832
+ return {
4833
+ ...bounds,
4834
+ data: null,
4835
+ type: null
4836
+ };
4837
+ }
4838
+ }
4839
+ const maskData = new Uint8Array(bounds.w * bounds.h);
4840
+ const aOffY = a.y - bounds.y;
4841
+ const aOffX = a.x - bounds.x;
4842
+ if (a.data === void 0 || a.data === null) {
4843
+ for (let ay = 0; ay < a.h; ay++) {
4844
+ const destRow = (aOffY + ay) * bounds.w + aOffX;
4845
+ maskData.fill(1, destRow, destRow + a.w);
4846
+ }
4847
+ } else {
4848
+ for (let ay = 0; ay < a.h; ay++) {
4849
+ const srcRow = ay * a.w;
4850
+ const destRow = (aOffY + ay) * bounds.w + aOffX;
4851
+ maskData.set(a.data.subarray(srcRow, srcRow + a.w), destRow);
4852
+ }
4853
+ }
4854
+ const bOffY = b.y - bounds.y;
4855
+ const bOffX = b.x - bounds.x;
4856
+ if (b.data === void 0 || b.data === null) {
4857
+ for (let by = 0; by < b.h; by++) {
4858
+ const destRow = (bOffY + by) * bounds.w + bOffX;
4859
+ maskData.fill(1, destRow, destRow + b.w);
4860
+ }
4861
+ } else {
4862
+ for (let by = 0; by < b.h; by++) {
4863
+ const srcRow = by * b.w;
4864
+ const destRow = (bOffY + by) * bounds.w + bOffX;
4865
+ for (let bx = 0; bx < b.w; bx++) {
4866
+ maskData[destRow + bx] |= b.data[srcRow + bx];
4867
+ }
4868
+ }
4869
+ }
4870
+ return {
4871
+ ...bounds,
4872
+ data: maskData,
4873
+ type: 1 /* BINARY */
4874
+ };
4875
+ }
4876
+
4877
+ // src/MaskRect/mergeBinaryMaskRects.ts
4878
+ function mergeBinaryMaskRects(current, adding) {
4879
+ const rects = [...current, ...adding];
4880
+ let changed = true;
4881
+ while (changed) {
4882
+ changed = false;
4883
+ const next = [];
4884
+ for (const r of rects) {
4885
+ let merged = false;
4886
+ for (let i = 0; i < next.length; i++) {
4887
+ const n = next[i];
4888
+ const overlap = r.x <= n.x + n.w && r.x + r.w >= n.x && r.y <= n.y + n.h && r.y + r.h >= n.y;
4889
+ if (overlap) {
4890
+ next[i] = merge2BinaryMaskRects(n, r);
4891
+ merged = true;
4892
+ changed = true;
4893
+ break;
4894
+ }
4895
+ }
4896
+ if (!merged) next.push(r);
4897
+ }
4898
+ rects.splice(0, rects.length, ...next);
4899
+ }
4900
+ return rects;
4901
+ }
4902
+
4289
4903
  // src/PixelData/PixelData.ts
4290
4904
  var PixelData = class _PixelData {
4291
4905
  data32;
@@ -4326,223 +4940,6 @@ var PixelData = class _PixelData {
4326
4940
  }
4327
4941
  };
4328
4942
 
4329
- // src/PixelData/blendPixelDataAlphaMask.ts
4330
- function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
4331
- const {
4332
- x: targetX = 0,
4333
- y: targetY = 0,
4334
- sx: sourceX = 0,
4335
- sy: sourceY = 0,
4336
- w: width = src.width,
4337
- h: height = src.height,
4338
- alpha: globalAlpha = 255,
4339
- blendFn = sourceOverPerfect,
4340
- mw = src.width,
4341
- mx = 0,
4342
- my = 0,
4343
- invertMask = false
4344
- } = opts;
4345
- if (globalAlpha === 0) return;
4346
- let x = targetX;
4347
- let y = targetY;
4348
- let sx = sourceX;
4349
- let sy = sourceY;
4350
- let w = width;
4351
- let h = height;
4352
- if (sx < 0) {
4353
- x -= sx;
4354
- w += sx;
4355
- sx = 0;
4356
- }
4357
- if (sy < 0) {
4358
- y -= sy;
4359
- h += sy;
4360
- sy = 0;
4361
- }
4362
- w = Math.min(w, src.width - sx);
4363
- h = Math.min(h, src.height - sy);
4364
- if (x < 0) {
4365
- sx -= x;
4366
- w += x;
4367
- x = 0;
4368
- }
4369
- if (y < 0) {
4370
- sy -= y;
4371
- h += y;
4372
- y = 0;
4373
- }
4374
- const actualW = Math.min(w, dst.width - x);
4375
- const actualH = Math.min(h, dst.height - y);
4376
- if (actualW <= 0 || actualH <= 0) return;
4377
- const dw = dst.width;
4378
- const sw = src.width;
4379
- const mPitch = mw;
4380
- const dx = x - targetX | 0;
4381
- const dy = y - targetY | 0;
4382
- const dst32 = dst.data32;
4383
- const src32 = src.data32;
4384
- let dIdx = y * dw + x | 0;
4385
- let sIdx = sy * sw + sx | 0;
4386
- let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
4387
- const dStride = dw - actualW | 0;
4388
- const sStride = sw - actualW | 0;
4389
- const mStride = mPitch - actualW | 0;
4390
- const isOpaque = globalAlpha === 255;
4391
- const isOverwrite = blendFn.isOverwrite || false;
4392
- for (let iy = 0; iy < actualH; iy++) {
4393
- for (let ix = 0; ix < actualW; ix++) {
4394
- const mVal = alphaMask[mIdx];
4395
- const effM = invertMask ? 255 - mVal : mVal;
4396
- if (effM === 0) {
4397
- dIdx++;
4398
- sIdx++;
4399
- mIdx++;
4400
- continue;
4401
- }
4402
- const srcCol = src32[sIdx];
4403
- const srcAlpha = srcCol >>> 24;
4404
- if (srcAlpha === 0 && !isOverwrite) {
4405
- dIdx++;
4406
- sIdx++;
4407
- mIdx++;
4408
- continue;
4409
- }
4410
- let weight = globalAlpha;
4411
- if (isOpaque) {
4412
- weight = effM;
4413
- } else if (effM !== 255) {
4414
- weight = effM * globalAlpha + 128 >> 8;
4415
- }
4416
- if (weight === 0) {
4417
- dIdx++;
4418
- sIdx++;
4419
- mIdx++;
4420
- continue;
4421
- }
4422
- let finalCol = srcCol;
4423
- if (weight < 255) {
4424
- const a = srcAlpha * weight + 128 >> 8;
4425
- if (a === 0 && !isOverwrite) {
4426
- dIdx++;
4427
- sIdx++;
4428
- mIdx++;
4429
- continue;
4430
- }
4431
- finalCol = (srcCol & 16777215 | a << 24) >>> 0;
4432
- }
4433
- dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
4434
- dIdx++;
4435
- sIdx++;
4436
- mIdx++;
4437
- }
4438
- dIdx += dStride;
4439
- sIdx += sStride;
4440
- mIdx += mStride;
4441
- }
4442
- }
4443
-
4444
- // src/PixelData/blendPixelDataBinaryMask.ts
4445
- function blendPixelDataBinaryMask(dst, src, binaryMask, opts) {
4446
- const {
4447
- x: targetX = 0,
4448
- y: targetY = 0,
4449
- sx: sourceX = 0,
4450
- sy: sourceY = 0,
4451
- w: width = src.width,
4452
- h: height = src.height,
4453
- alpha: globalAlpha = 255,
4454
- blendFn = sourceOverPerfect,
4455
- mw = src.width,
4456
- mx = 0,
4457
- my = 0,
4458
- invertMask = false
4459
- } = opts;
4460
- if (globalAlpha === 0) return;
4461
- let x = targetX;
4462
- let y = targetY;
4463
- let sx = sourceX;
4464
- let sy = sourceY;
4465
- let w = width;
4466
- let h = height;
4467
- if (sx < 0) {
4468
- x -= sx;
4469
- w += sx;
4470
- sx = 0;
4471
- }
4472
- if (sy < 0) {
4473
- y -= sy;
4474
- h += sy;
4475
- sy = 0;
4476
- }
4477
- w = Math.min(w, src.width - sx);
4478
- h = Math.min(h, src.height - sy);
4479
- if (x < 0) {
4480
- sx -= x;
4481
- w += x;
4482
- x = 0;
4483
- }
4484
- if (y < 0) {
4485
- sy -= y;
4486
- h += y;
4487
- y = 0;
4488
- }
4489
- const actualW = Math.min(w, dst.width - x);
4490
- const actualH = Math.min(h, dst.height - y);
4491
- if (actualW <= 0 || actualH <= 0) return;
4492
- const dx = x - targetX | 0;
4493
- const dy = y - targetY | 0;
4494
- const dst32 = dst.data32;
4495
- const src32 = src.data32;
4496
- const dw = dst.width;
4497
- const sw = src.width;
4498
- const mPitch = mw;
4499
- let dIdx = y * dw + x | 0;
4500
- let sIdx = sy * sw + sx | 0;
4501
- let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
4502
- const dStride = dw - actualW | 0;
4503
- const sStride = sw - actualW | 0;
4504
- const mStride = mPitch - actualW | 0;
4505
- const skipVal = invertMask ? 1 : 0;
4506
- const isOpaque = globalAlpha === 255;
4507
- const isOverwrite = blendFn.isOverwrite || false;
4508
- for (let iy = 0; iy < actualH; iy++) {
4509
- for (let ix = 0; ix < actualW; ix++) {
4510
- if (binaryMask[mIdx] === skipVal) {
4511
- dIdx++;
4512
- sIdx++;
4513
- mIdx++;
4514
- continue;
4515
- }
4516
- const srcCol = src32[sIdx];
4517
- const srcAlpha = srcCol >>> 24;
4518
- if (srcAlpha === 0 && !isOverwrite) {
4519
- dIdx++;
4520
- sIdx++;
4521
- mIdx++;
4522
- continue;
4523
- }
4524
- let finalCol = srcCol;
4525
- if (!isOpaque) {
4526
- const a = srcAlpha * globalAlpha + 128 >> 8;
4527
- if (a === 0 && !isOverwrite) {
4528
- dIdx++;
4529
- sIdx++;
4530
- mIdx++;
4531
- continue;
4532
- }
4533
- finalCol = (srcCol & 16777215 | a << 24) >>> 0;
4534
- }
4535
- dst32[dIdx] = blendFn(finalCol, dst32[dIdx]);
4536
- dIdx++;
4537
- sIdx++;
4538
- mIdx++;
4539
- }
4540
- dIdx += dStride;
4541
- sIdx += sStride;
4542
- mIdx += mStride;
4543
- }
4544
- }
4545
-
4546
4943
  // src/PixelData/clearPixelData.ts
4547
4944
  function clearPixelData(dst, rect) {
4548
4945
  fillPixelData(dst, 0, rect);
@@ -4635,10 +5032,11 @@ function pixelDataToAlphaMask(pixelData) {
4635
5032
  height
4636
5033
  } = pixelData;
4637
5034
  const len = data32.length;
4638
- const mask = new Uint8Array(width * height);
5035
+ const mask = makeAlphaMask(width, height);
5036
+ const maskData = mask.data;
4639
5037
  for (let i = 0; i < len; i++) {
4640
5038
  const val = data32[i];
4641
- mask[i] = val >>> 24 & 255;
5039
+ maskData[i] = val >>> 24 & 255;
4642
5040
  }
4643
5041
  return mask;
4644
5042
  }
@@ -4820,11 +5218,13 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
4820
5218
  exclusionPerfect,
4821
5219
  extractImageDataBuffer,
4822
5220
  extractMask,
5221
+ extractMaskBuffer,
4823
5222
  extractPixelData,
4824
5223
  extractPixelDataBuffer,
4825
5224
  fileInputChangeToImageData,
4826
5225
  fileToImageData,
4827
5226
  fillPixelData,
5227
+ fillPixelDataBinaryMask,
4828
5228
  floodFillSelection,
4829
5229
  forEachLinePoint,
4830
5230
  getCircleBrushOrPencilBounds,
@@ -4833,12 +5233,13 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
4833
5233
  getIndexedImageColorCounts,
4834
5234
  getRectBrushOrPencilBounds,
4835
5235
  getRectBrushOrPencilStrokeBounds,
5236
+ getRectsBounds,
4836
5237
  getSupportedPixelFormats,
4837
5238
  hardLightFast,
4838
5239
  hardLightPerfect,
4839
5240
  hardMixFast,
4840
5241
  hardMixPerfect,
4841
- imageDataToAlphaMask,
5242
+ imageDataToAlphaMaskBuffer,
4842
5243
  imageDataToDataUrl,
4843
5244
  imageDataToImgBlob,
4844
5245
  imageDataToUInt32Array,
@@ -4861,7 +5262,11 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
4861
5262
  linearDodgePerfect,
4862
5263
  linearLightFast,
4863
5264
  linearLightPerfect,
5265
+ makeAlphaMask,
5266
+ makeBinaryMask,
4864
5267
  makeBlendModeRegistry,
5268
+ makeCircleBrushAlphaMask,
5269
+ makeCircleBrushBinaryMask,
4865
5270
  makeFastBlendModeRegistry,
4866
5271
  makeFullPixelMutator,
4867
5272
  makeImageDataLike,
@@ -4869,7 +5274,9 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
4869
5274
  makePixelCanvas,
4870
5275
  makeReusableCanvas,
4871
5276
  makeReusableImageData,
5277
+ merge2BinaryMaskRects,
4872
5278
  mergeAlphaMasks,
5279
+ mergeBinaryMaskRects,
4873
5280
  mergeBinaryMasks,
4874
5281
  multiplyFast,
4875
5282
  multiplyPerfect,
@@ -4886,8 +5293,11 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
4886
5293
  mutatorBlendColor,
4887
5294
  mutatorBlendPixel,
4888
5295
  mutatorBlendPixelData,
5296
+ mutatorBlendPixelDataAlphaMask,
5297
+ mutatorBlendPixelDataBinaryMask,
4889
5298
  mutatorClear,
4890
5299
  mutatorFill,
5300
+ mutatorFillBinaryMask,
4891
5301
  mutatorInvert,
4892
5302
  overlayFast,
4893
5303
  overlayPerfect,
@@ -4910,10 +5320,12 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
4910
5320
  screenPerfect,
4911
5321
  serializeImageData,
4912
5322
  serializeNullableImageData,
5323
+ setMaskData,
4913
5324
  softLightFast,
4914
5325
  softLightPerfect,
4915
5326
  sourceOverFast,
4916
5327
  sourceOverPerfect,
5328
+ subtractBinaryMaskRects,
4917
5329
  subtractFast,
4918
5330
  subtractPerfect,
4919
5331
  toBlendModeIndexAndName,