pixel-data-js 0.30.0 → 0.32.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.
@@ -86,86 +86,7 @@ function color32ToCssRGBA(color) {
86
86
  return `rgba(${r},${g},${b},${alpha})`;
87
87
  }
88
88
 
89
- // src/Rect/resolveClipping.ts
90
- var makeClippedRect = () => ({
91
- x: 0,
92
- y: 0,
93
- w: 0,
94
- h: 0,
95
- inBounds: false
96
- });
97
- var makeClippedBlit = () => ({
98
- x: 0,
99
- y: 0,
100
- sx: 0,
101
- sy: 0,
102
- w: 0,
103
- h: 0,
104
- inBounds: false
105
- });
106
- function resolveRectClipping(x, y, w, h, boundaryW, boundaryH, out) {
107
- if (x < 0) {
108
- w += x;
109
- x = 0;
110
- }
111
- if (y < 0) {
112
- h += y;
113
- y = 0;
114
- }
115
- const actualW = Math.min(w, boundaryW - x);
116
- const actualH = Math.min(h, boundaryH - y);
117
- if (actualW <= 0 || actualH <= 0) {
118
- out.inBounds = false;
119
- return out;
120
- }
121
- out.x = x;
122
- out.y = y;
123
- out.w = actualW;
124
- out.h = actualH;
125
- out.inBounds = true;
126
- return out;
127
- }
128
- function resolveBlitClipping(x, y, sx, sy, w, h, dstW, dstH, srcW, srcH, out) {
129
- if (sx < 0) {
130
- x -= sx;
131
- w += sx;
132
- sx = 0;
133
- }
134
- if (sy < 0) {
135
- y -= sy;
136
- h += sy;
137
- sy = 0;
138
- }
139
- w = Math.min(w, srcW - sx);
140
- h = Math.min(h, srcH - sy);
141
- if (x < 0) {
142
- sx -= x;
143
- w += x;
144
- x = 0;
145
- }
146
- if (y < 0) {
147
- sy -= y;
148
- h += y;
149
- y = 0;
150
- }
151
- const actualW = Math.min(w, dstW - x);
152
- const actualH = Math.min(h, dstH - y);
153
- if (actualW <= 0 || actualH <= 0) {
154
- out.inBounds = false;
155
- return out;
156
- }
157
- out.x = x;
158
- out.y = y;
159
- out.sx = sx;
160
- out.sy = sy;
161
- out.w = actualW;
162
- out.h = actualH;
163
- out.inBounds = true;
164
- return out;
165
- }
166
-
167
89
  // src/ImageData/extractImageDataBuffer.ts
168
- var SCRATCH_BLIT = makeClippedBlit();
169
90
  function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
170
91
  const {
171
92
  x,
@@ -178,28 +99,52 @@ function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
178
99
  w: _w,
179
100
  h: _h
180
101
  };
181
- const {
182
- width: srcW,
183
- height: srcH,
184
- data: src
185
- } = imageData;
186
- if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
187
- const out = new Uint8ClampedArray(w * h * 4);
188
- const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT);
189
- if (!clip.inBounds) return out;
190
- const {
191
- x: dstX,
192
- y: dstY,
193
- sx: srcX,
194
- sy: srcY,
195
- w: copyW,
196
- h: copyH
197
- } = clip;
198
- const rowLen = copyW * 4;
199
- for (let row = 0; row < copyH; row++) {
200
- const srcStart = ((srcY + row) * srcW + srcX) * 4;
201
- const dstStart = ((dstY + row) * w + dstX) * 4;
202
- out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
102
+ if (w <= 0) return new Uint8ClampedArray(0);
103
+ if (h <= 0) return new Uint8ClampedArray(0);
104
+ const srcW = imageData.width;
105
+ const srcH = imageData.height;
106
+ const src = imageData.data;
107
+ const outLen = w * h * 4;
108
+ const out = new Uint8ClampedArray(outLen);
109
+ let srcX = x;
110
+ let srcY = y;
111
+ let dstX = 0;
112
+ let dstY = 0;
113
+ let copyW = w;
114
+ let copyH = h;
115
+ if (srcX < 0) {
116
+ dstX = -srcX;
117
+ copyW += srcX;
118
+ srcX = 0;
119
+ }
120
+ if (srcY < 0) {
121
+ dstY = -srcY;
122
+ copyH += srcY;
123
+ srcY = 0;
124
+ }
125
+ copyW = Math.min(copyW, srcW - srcX);
126
+ copyH = Math.min(copyH, srcH - srcY);
127
+ if (copyW <= 0) return out;
128
+ if (copyH <= 0) return out;
129
+ const isAligned = src.byteOffset % 4 === 0;
130
+ if (isAligned) {
131
+ const srcLen32 = src.byteLength / 4;
132
+ const src32 = new Uint32Array(src.buffer, src.byteOffset, srcLen32);
133
+ const out32 = new Uint32Array(out.buffer);
134
+ for (let row = 0; row < copyH; row++) {
135
+ const srcStart = (srcY + row) * srcW + srcX;
136
+ const dstStart = (dstY + row) * w + dstX;
137
+ const chunk = src32.subarray(srcStart, srcStart + copyW);
138
+ out32.set(chunk, dstStart);
139
+ }
140
+ } else {
141
+ const rowLen = copyW * 4;
142
+ for (let row = 0; row < copyH; row++) {
143
+ const srcStart = ((srcY + row) * srcW + srcX) * 4;
144
+ const dstStart = ((dstY + row) * w + dstX) * 4;
145
+ const chunk = src.subarray(srcStart, srcStart + rowLen);
146
+ out.set(chunk, dstStart);
147
+ }
203
148
  }
204
149
  return out;
205
150
  }
@@ -2025,6 +1970,67 @@ async function writeImageDataToClipboard(imageData) {
2025
1970
  return writeImgBlobToClipboard(blob);
2026
1971
  }
2027
1972
 
1973
+ // src/Control/BatchedQueue.ts
1974
+ function makeBatchedQueue(processor, queue) {
1975
+ let activeSet = /* @__PURE__ */ new Set();
1976
+ let processingSet = /* @__PURE__ */ new Set();
1977
+ let scheduled = false;
1978
+ const flush = () => {
1979
+ const current = activeSet;
1980
+ activeSet = processingSet;
1981
+ processingSet = current;
1982
+ scheduled = false;
1983
+ try {
1984
+ processor(processingSet);
1985
+ } finally {
1986
+ processingSet.clear();
1987
+ }
1988
+ };
1989
+ function markDirty(item) {
1990
+ activeSet.add(item);
1991
+ if (!scheduled) {
1992
+ scheduled = true;
1993
+ queue(flush);
1994
+ }
1995
+ }
1996
+ function markMultipleDirty(items) {
1997
+ let len = items.length;
1998
+ if (len === 0) return;
1999
+ for (let i = 0; i < len; i++) {
2000
+ activeSet.add(items[i]);
2001
+ }
2002
+ if (!scheduled) {
2003
+ scheduled = true;
2004
+ queue(flush);
2005
+ }
2006
+ }
2007
+ return {
2008
+ markDirty,
2009
+ markMultipleDirty
2010
+ };
2011
+ }
2012
+
2013
+ // src/Control/RenderQueue.ts
2014
+ function makeRenderQueue(cb) {
2015
+ let needsRender = false;
2016
+ let frameId = 0;
2017
+ const trigger = () => {
2018
+ if (needsRender) return;
2019
+ needsRender = true;
2020
+ frameId = requestAnimationFrame(() => {
2021
+ needsRender = false;
2022
+ cb();
2023
+ });
2024
+ };
2025
+ trigger.cancel = () => {
2026
+ if (needsRender) {
2027
+ cancelAnimationFrame(frameId);
2028
+ needsRender = false;
2029
+ }
2030
+ };
2031
+ return trigger;
2032
+ }
2033
+
2028
2034
  // src/History/PixelPatchTiles.ts
2029
2035
  function applyPatchTiles(target, tiles, tileSize) {
2030
2036
  for (let i = 0; i < tiles.length; i++) {
@@ -2587,11 +2593,10 @@ var PixelWriter = class {
2587
2593
  * throw immediately to prevent silent data loss from a nested extractPatch.
2588
2594
  *
2589
2595
  * @param transaction Callback to be executed inside the transaction.
2590
- * @param after Called after both undo and redo — use for generic change notifications.
2591
- * @param afterUndo Called after undo only — use for dimension or state changes specific to undo.
2596
+ * @param afterUndo Called after undo only.
2592
2597
  * @param afterRedo Called after redo only.
2593
2598
  */
2594
- withHistory(transaction, after, afterUndo, afterRedo) {
2599
+ withHistory(transaction, afterUndo, afterRedo) {
2595
2600
  if (this._inProgress) {
2596
2601
  throw new Error("withHistory is not re-entrant \u2014 commit or rollback the current operation first");
2597
2602
  }
@@ -2606,10 +2611,10 @@ var PixelWriter = class {
2606
2611
  }
2607
2612
  if (this.accumulator.beforeTiles.length === 0) return;
2608
2613
  const patch = this.accumulator.extractPatch();
2609
- const action = this.historyActionFactory(this.config, this.accumulator, patch, after, afterUndo, afterRedo);
2614
+ const action = this.historyActionFactory(this.config, this.accumulator, patch, afterUndo, afterRedo);
2610
2615
  this.historyManager.commit(action);
2611
2616
  }
2612
- resize(newWidth, newHeight, offsetX = 0, offsetY = 0, after, afterUndo, afterRedo, resizeImageDataFn = resizeImageData) {
2617
+ resize(newWidth, newHeight, offsetX = 0, offsetY = 0, afterUndo, afterRedo, resizeImageDataFn = resizeImageData) {
2613
2618
  if (this._inProgress) {
2614
2619
  throw new Error("Cannot resize inside a withHistory callback");
2615
2620
  }
@@ -2625,12 +2630,10 @@ var PixelWriter = class {
2625
2630
  undo: () => {
2626
2631
  setPixelData(target, beforeImageData);
2627
2632
  afterUndo?.(beforeImageData);
2628
- after?.(beforeImageData);
2629
2633
  },
2630
2634
  redo: () => {
2631
2635
  setPixelData(target, afterImageData);
2632
2636
  afterRedo?.(afterImageData);
2633
- after?.(afterImageData);
2634
2637
  }
2635
2638
  });
2636
2639
  }
@@ -3582,8 +3585,9 @@ var mutatorBlendPixelData = ((writer, deps = defaults13) => {
3582
3585
  });
3583
3586
 
3584
3587
  // src/PixelData/fillPixelData.ts
3585
- var SCRATCH_RECT = makeClippedRect();
3586
3588
  function fillPixelData(dst, color, _x, _y, _w, _h) {
3589
+ const dstW = dst.w;
3590
+ const dstH = dst.h;
3587
3591
  let x;
3588
3592
  let y;
3589
3593
  let w;
@@ -3591,8 +3595,8 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3591
3595
  if (typeof _x === "object") {
3592
3596
  x = _x.x ?? 0;
3593
3597
  y = _x.y ?? 0;
3594
- w = _x.w ?? dst.w;
3595
- h = _x.h ?? dst.h;
3598
+ w = _x.w ?? dstW;
3599
+ h = _x.h ?? dstH;
3596
3600
  } else if (typeof _x === "number") {
3597
3601
  x = _x;
3598
3602
  y = _y;
@@ -3601,24 +3605,42 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3601
3605
  } else {
3602
3606
  x = 0;
3603
3607
  y = 0;
3604
- w = dst.w;
3605
- h = dst.h;
3606
- }
3607
- const clip = resolveRectClipping(x, y, w, h, dst.w, dst.h, SCRATCH_RECT);
3608
- if (!clip.inBounds) return false;
3609
- const {
3610
- x: finalX,
3611
- y: finalY,
3612
- w: actualW,
3613
- h: actualH
3614
- } = clip;
3608
+ w = dstW;
3609
+ h = dstH;
3610
+ }
3611
+ let dstX = x;
3612
+ let dstY = y;
3613
+ let fillW = w;
3614
+ let fillH = h;
3615
+ if (dstX < 0) {
3616
+ fillW += dstX;
3617
+ dstX = 0;
3618
+ }
3619
+ if (dstY < 0) {
3620
+ fillH += dstY;
3621
+ dstY = 0;
3622
+ }
3623
+ fillW = Math.min(fillW, dstW - dstX);
3624
+ fillH = Math.min(fillH, dstH - dstY);
3625
+ if (fillW <= 0) return false;
3626
+ if (fillH <= 0) return false;
3615
3627
  const dst32 = dst.data;
3616
- const dw = dst.w;
3617
3628
  let hasChanged = false;
3618
- for (let iy = 0; iy < actualH; iy++) {
3619
- const rowOffset = (finalY + iy) * dw;
3620
- const start = rowOffset + finalX;
3621
- const end = start + actualW;
3629
+ if (dstX === 0 && fillW === dstW) {
3630
+ const start = dstY * dstW;
3631
+ const end = start + fillW * fillH;
3632
+ for (let i = start; i < end; i++) {
3633
+ if (dst32[i] !== color) {
3634
+ dst32[i] = color;
3635
+ hasChanged = true;
3636
+ }
3637
+ }
3638
+ return hasChanged;
3639
+ }
3640
+ for (let iy = 0; iy < fillH; iy++) {
3641
+ const rowOffset = (dstY + iy) * dstW;
3642
+ const start = rowOffset + dstX;
3643
+ const end = start + fillW;
3622
3644
  for (let i = start; i < end; i++) {
3623
3645
  if (dst32[i] !== color) {
3624
3646
  dst32[i] = color;
@@ -3680,39 +3702,48 @@ var mutatorFillRect = ((writer, deps = defaults15) => {
3680
3702
  });
3681
3703
 
3682
3704
  // src/PixelData/fillPixelDataBinaryMask.ts
3683
- var SCRATCH_RECT2 = makeClippedRect();
3684
3705
  function fillPixelDataBinaryMask(target, color, mask, x = 0, y = 0) {
3706
+ const targetW = target.w;
3707
+ const targetH = target.h;
3685
3708
  const maskW = mask.w;
3686
3709
  const maskH = mask.h;
3687
- const clip = resolveRectClipping(x, y, maskW, maskH, target.w, target.h, SCRATCH_RECT2);
3688
- if (!clip.inBounds) return false;
3689
- const {
3690
- x: finalX,
3691
- y: finalY,
3692
- w: actualW,
3693
- h: actualH
3694
- } = clip;
3710
+ let dstX = x;
3711
+ let dstY = y;
3712
+ let actualW = maskW;
3713
+ let actualH = maskH;
3714
+ if (dstX < 0) {
3715
+ actualW += dstX;
3716
+ dstX = 0;
3717
+ }
3718
+ if (dstY < 0) {
3719
+ actualH += dstY;
3720
+ dstY = 0;
3721
+ }
3722
+ actualW = Math.min(actualW, targetW - dstX);
3723
+ actualH = Math.min(actualH, targetH - dstY);
3724
+ if (actualW <= 0 || actualH <= 0) return false;
3695
3725
  const maskData = mask.data;
3696
3726
  const dst32 = target.data;
3697
- const dw = target.w;
3727
+ const mx = dstX - x;
3728
+ const my = dstY - y;
3698
3729
  let hasChanged = false;
3730
+ let dIdx = dstY * targetW + dstX;
3731
+ let mIdx = my * maskW + mx;
3732
+ const dStride = targetW - actualW;
3733
+ const mStride = maskW - actualW;
3699
3734
  for (let iy = 0; iy < actualH; iy++) {
3700
- const currentY = finalY + iy;
3701
- const maskY = currentY - y;
3702
- const maskOffset = maskY * maskW;
3703
- const dstRowOffset = currentY * dw;
3704
3735
  for (let ix = 0; ix < actualW; ix++) {
3705
- const currentX = finalX + ix;
3706
- const maskX = currentX - x;
3707
- const maskIndex = maskOffset + maskX;
3708
- if (maskData[maskIndex]) {
3709
- const current = dst32[dstRowOffset + currentX];
3710
- if (current !== color) {
3711
- dst32[dstRowOffset + currentX] = color;
3736
+ if (maskData[mIdx]) {
3737
+ if (dst32[dIdx] !== color) {
3738
+ dst32[dIdx] = color;
3712
3739
  hasChanged = true;
3713
3740
  }
3714
3741
  }
3742
+ dIdx++;
3743
+ mIdx++;
3715
3744
  }
3745
+ dIdx += dStride;
3746
+ mIdx += mStride;
3716
3747
  }
3717
3748
  return hasChanged;
3718
3749
  }
@@ -3734,35 +3765,43 @@ var mutatorFillBinaryMask = ((writer, deps = defaults16) => {
3734
3765
  });
3735
3766
 
3736
3767
  // src/PixelData/invertPixelData.ts
3737
- var SCRATCH_RECT3 = makeClippedRect();
3738
3768
  function invertPixelData(target, opts) {
3769
+ const targetW = target.w;
3770
+ const targetH = target.h;
3739
3771
  const mask = opts?.mask;
3772
+ const invertMask = opts?.invertMask ?? false;
3740
3773
  const targetX = opts?.x ?? 0;
3741
3774
  const targetY = opts?.y ?? 0;
3742
3775
  const mx = opts?.mx ?? 0;
3743
3776
  const my = opts?.my ?? 0;
3744
- const width = opts?.w ?? target.w;
3745
- const height = opts?.h ?? target.h;
3746
- const invertMask = opts?.invertMask ?? false;
3747
- const clip = resolveRectClipping(targetX, targetY, width, height, target.w, target.h, SCRATCH_RECT3);
3748
- if (!clip.inBounds) return false;
3749
- const {
3750
- x,
3751
- y,
3752
- w: actualW,
3753
- h: actualH
3754
- } = clip;
3777
+ const w = opts?.w ?? targetW;
3778
+ const h = opts?.h ?? targetH;
3779
+ let x = targetX;
3780
+ let y = targetY;
3781
+ let actualW = w;
3782
+ let actualH = h;
3783
+ if (x < 0) {
3784
+ actualW += x;
3785
+ x = 0;
3786
+ }
3787
+ if (y < 0) {
3788
+ actualH += y;
3789
+ y = 0;
3790
+ }
3791
+ actualW = Math.min(actualW, targetW - x);
3792
+ actualH = Math.min(actualH, targetH - y);
3793
+ if (actualW <= 0 || actualH <= 0) return false;
3755
3794
  const dst32 = target.data;
3756
- const dw = target.w;
3757
- const mPitch = mask?.w ?? width;
3795
+ const dw = targetW;
3758
3796
  const dx = x - targetX;
3759
3797
  const dy = y - targetY;
3760
3798
  let dIdx = y * dw + x;
3761
- let mIdx = (my + dy) * mPitch + (mx + dx);
3762
3799
  const dStride = dw - actualW;
3763
- const mStride = mPitch - actualW;
3764
3800
  if (mask) {
3765
3801
  const maskData = mask.data;
3802
+ const mPitch = mask.w;
3803
+ let mIdx = (my + dy) * mPitch + (mx + dx);
3804
+ const mStride = mPitch - actualW;
3766
3805
  for (let iy = 0; iy < actualH; iy++) {
3767
3806
  for (let ix = 0; ix < actualW; ix++) {
3768
3807
  const mVal = maskData[mIdx];
@@ -3854,6 +3893,27 @@ function copyImageDataLike({
3854
3893
  };
3855
3894
  }
3856
3895
 
3896
+ // src/ImageData/extractImageData.ts
3897
+ function extractImageData(imageData, _x, _y, _w, _h) {
3898
+ const {
3899
+ x,
3900
+ y,
3901
+ w,
3902
+ h
3903
+ } = typeof _x === "object" ? _x : {
3904
+ x: _x,
3905
+ y: _y,
3906
+ w: _w,
3907
+ h: _h
3908
+ };
3909
+ if (w <= 0) return null;
3910
+ if (h <= 0) return null;
3911
+ const result = new ImageData(w, h);
3912
+ const buffer = extractImageDataBuffer(imageData, x, y, w, h);
3913
+ result.data.set(buffer);
3914
+ return result;
3915
+ }
3916
+
3857
3917
  // src/ImageData/ImageDataLike.ts
3858
3918
  function makeImageDataLike(width, height, data) {
3859
3919
  const size = width * height * 4;
@@ -4004,94 +4064,120 @@ function uInt32ArrayToImageDataLike(data, width, height) {
4004
4064
  }
4005
4065
 
4006
4066
  // src/ImageData/writeImageData.ts
4007
- var SCRATCH_BLIT2 = makeClippedBlit();
4008
- function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
4067
+ function writeImageData(target, source, x, y) {
4009
4068
  const dstW = target.width;
4010
4069
  const dstH = target.height;
4011
- const dstData = target.data;
4070
+ const dst = target.data;
4012
4071
  const srcW = source.width;
4013
- const srcData = source.data;
4014
- const clip = resolveBlitClipping(x, y, sx, sy, sw, sh, dstW, dstH, srcW, source.height, SCRATCH_BLIT2);
4015
- if (!clip.inBounds) return;
4016
- const {
4017
- x: dstX,
4018
- y: dstY,
4019
- sx: srcX,
4020
- sy: srcY,
4021
- w: copyW,
4022
- h: copyH
4023
- } = clip;
4024
- const useMask = !!mask;
4025
- for (let row = 0; row < copyH; row++) {
4026
- const currentDstY = dstY + row;
4027
- const currentSrcY = srcY + row;
4028
- const dstStart = (currentDstY * dstW + dstX) * 4;
4029
- const srcStart = (currentSrcY * srcW + srcX) * 4;
4030
- if (useMask && mask) {
4031
- for (let ix = 0; ix < copyW; ix++) {
4032
- const mi = currentSrcY * srcW + (srcX + ix);
4033
- const alpha = mask[mi];
4034
- if (alpha === 0) {
4035
- continue;
4036
- }
4037
- const di = dstStart + ix * 4;
4038
- const si = srcStart + ix * 4;
4039
- if (maskType === 1 /* BINARY */ || alpha === 255) {
4040
- dstData[di] = srcData[si];
4041
- dstData[di + 1] = srcData[si + 1];
4042
- dstData[di + 2] = srcData[si + 2];
4043
- dstData[di + 3] = srcData[si + 3];
4044
- } else {
4045
- const a = alpha / 255;
4046
- const invA = 1 - a;
4047
- dstData[di] = srcData[si] * a + dstData[di] * invA;
4048
- dstData[di + 1] = srcData[si + 1] * a + dstData[di + 1] * invA;
4049
- dstData[di + 2] = srcData[si + 2] * a + dstData[di + 2] * invA;
4050
- dstData[di + 3] = srcData[si + 3] * a + dstData[di + 3] * invA;
4051
- }
4052
- }
4053
- } else {
4054
- const byteLen = copyW * 4;
4055
- const sub = srcData.subarray(srcStart, srcStart + byteLen);
4056
- dstData.set(sub, dstStart);
4072
+ const srcH = source.height;
4073
+ const src = source.data;
4074
+ let dstX = x;
4075
+ let dstY = y;
4076
+ let srcX = 0;
4077
+ let srcY = 0;
4078
+ let copyW = srcW;
4079
+ let copyH = srcH;
4080
+ if (dstX < 0) {
4081
+ srcX = -dstX;
4082
+ copyW += dstX;
4083
+ dstX = 0;
4084
+ }
4085
+ if (dstY < 0) {
4086
+ srcY = -dstY;
4087
+ copyH += dstY;
4088
+ dstY = 0;
4089
+ }
4090
+ copyW = Math.min(copyW, dstW - dstX);
4091
+ copyH = Math.min(copyH, dstH - dstY);
4092
+ if (copyW <= 0) return;
4093
+ if (copyH <= 0) return;
4094
+ const isDstAligned = dst.byteOffset % 4 === 0;
4095
+ const isSrcAligned = src.byteOffset % 4 === 0;
4096
+ if (isDstAligned && isSrcAligned) {
4097
+ const dstLen32 = dst.byteLength / 4;
4098
+ const dst32 = new Uint32Array(dst.buffer, dst.byteOffset, dstLen32);
4099
+ const srcLen32 = src.byteLength / 4;
4100
+ const src32 = new Uint32Array(src.buffer, src.byteOffset, srcLen32);
4101
+ for (let row = 0; row < copyH; row++) {
4102
+ const dstStart = (dstY + row) * dstW + dstX;
4103
+ const srcStart = (srcY + row) * srcW + srcX;
4104
+ const chunk = src32.subarray(srcStart, srcStart + copyW);
4105
+ dst32.set(chunk, dstStart);
4106
+ }
4107
+ } else {
4108
+ const rowLen = copyW * 4;
4109
+ for (let row = 0; row < copyH; row++) {
4110
+ const dstStart = ((dstY + row) * dstW + dstX) * 4;
4111
+ const srcStart = ((srcY + row) * srcW + srcX) * 4;
4112
+ const chunk = src.subarray(srcStart, srcStart + rowLen);
4113
+ dst.set(chunk, dstStart);
4057
4114
  }
4058
4115
  }
4059
4116
  }
4060
4117
 
4061
4118
  // src/ImageData/writeImageDataBuffer.ts
4062
- var SCRATCH_BLIT3 = makeClippedBlit();
4063
4119
  function writeImageDataBuffer(target, data, _x, _y, _w, _h) {
4064
- const {
4065
- x,
4066
- y,
4067
- w,
4068
- h
4069
- } = typeof _x === "object" ? _x : {
4070
- x: _x,
4071
- y: _y,
4072
- w: _w,
4073
- h: _h
4074
- };
4075
- const {
4076
- width: dstW,
4077
- height: dstH,
4078
- data: dst
4079
- } = target;
4080
- const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT3);
4081
- if (!clip.inBounds) return;
4082
- const {
4083
- x: dstX,
4084
- y: dstY,
4085
- sx: srcX,
4086
- sy: srcY,
4087
- w: copyW,
4088
- h: copyH
4089
- } = clip;
4090
- const rowLen = copyW * 4;
4091
- for (let row = 0; row < copyH; row++) {
4092
- const dstStart = ((dstY + row) * dstW + dstX) * 4;
4093
- const srcStart = ((srcY + row) * w + srcX) * 4;
4094
- dst.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
4120
+ let x;
4121
+ let y;
4122
+ let w;
4123
+ let h;
4124
+ if (typeof _x === "object") {
4125
+ x = _x.x;
4126
+ y = _x.y;
4127
+ w = _x.w;
4128
+ h = _x.h;
4129
+ } else {
4130
+ x = _x;
4131
+ y = _y;
4132
+ w = _w;
4133
+ h = _h;
4134
+ }
4135
+ if (w <= 0) return;
4136
+ if (h <= 0) return;
4137
+ const dstW = target.width;
4138
+ const dstH = target.height;
4139
+ const dst = target.data;
4140
+ let dstX = x;
4141
+ let dstY = y;
4142
+ let srcX = 0;
4143
+ let srcY = 0;
4144
+ let copyW = w;
4145
+ let copyH = h;
4146
+ if (dstX < 0) {
4147
+ srcX = -dstX;
4148
+ copyW += dstX;
4149
+ dstX = 0;
4150
+ }
4151
+ if (dstY < 0) {
4152
+ srcY = -dstY;
4153
+ copyH += dstY;
4154
+ dstY = 0;
4155
+ }
4156
+ copyW = Math.min(copyW, dstW - dstX);
4157
+ copyH = Math.min(copyH, dstH - dstY);
4158
+ if (copyW <= 0) return;
4159
+ if (copyH <= 0) return;
4160
+ const isDstAligned = dst.byteOffset % 4 === 0;
4161
+ const isSrcAligned = data.byteOffset % 4 === 0;
4162
+ if (isDstAligned && isSrcAligned) {
4163
+ const dstLen32 = dst.byteLength / 4;
4164
+ const dst32 = new Uint32Array(dst.buffer, dst.byteOffset, dstLen32);
4165
+ const srcLen32 = data.byteLength / 4;
4166
+ const src32 = new Uint32Array(data.buffer, data.byteOffset, srcLen32);
4167
+ for (let row = 0; row < copyH; row++) {
4168
+ const dstStart = (dstY + row) * dstW + dstX;
4169
+ const srcStart = (srcY + row) * w + srcX;
4170
+ const chunk = src32.subarray(srcStart, srcStart + copyW);
4171
+ dst32.set(chunk, dstStart);
4172
+ }
4173
+ } else {
4174
+ const rowLen = copyW * 4;
4175
+ for (let row = 0; row < copyH; row++) {
4176
+ const dstStart = ((dstY + row) * dstW + dstX) * 4;
4177
+ const srcStart = ((srcY + row) * w + srcX) * 4;
4178
+ const chunk = data.subarray(srcStart, srcStart + rowLen);
4179
+ dst.set(chunk, dstStart);
4180
+ }
4095
4181
  }
4096
4182
  }
4097
4183
 
@@ -6024,8 +6110,9 @@ function blendPixelDataPaintBuffer(target, paintBuffer, alpha = 255, blendFn, bl
6024
6110
  }
6025
6111
 
6026
6112
  // src/PixelData/fillPixelDataFast.ts
6027
- var SCRATCH_RECT4 = makeClippedRect();
6028
6113
  function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
6114
+ const dstW = dst.w;
6115
+ const dstH = dst.h;
6029
6116
  let x;
6030
6117
  let y;
6031
6118
  let w;
@@ -6046,23 +6133,31 @@ function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
6046
6133
  w = dst.w;
6047
6134
  h = dst.h;
6048
6135
  }
6049
- const clip = resolveRectClipping(x, y, w, h, dst.w, dst.h, SCRATCH_RECT4);
6050
- if (!clip.inBounds) return;
6051
- const {
6052
- x: finalX,
6053
- y: finalY,
6054
- w: actualW,
6055
- h: actualH
6056
- } = clip;
6136
+ let dstX = x;
6137
+ let dstY = y;
6138
+ let fillW = w;
6139
+ let fillH = h;
6140
+ if (dstX < 0) {
6141
+ fillW += dstX;
6142
+ dstX = 0;
6143
+ }
6144
+ if (dstY < 0) {
6145
+ fillH += dstY;
6146
+ dstY = 0;
6147
+ }
6148
+ fillW = Math.min(fillW, dstW - dstX);
6149
+ fillH = Math.min(fillH, dstH - dstY);
6150
+ if (fillW <= 0) return;
6151
+ if (fillH <= 0) return;
6057
6152
  const dst32 = dst.data;
6058
6153
  const dw = dst.w;
6059
- if (actualW === dw && actualH === dst.h && finalX === 0 && finalY === 0) {
6154
+ if (fillW === dw && fillH === dst.h && dstX === 0 && dstY === 0) {
6060
6155
  dst32.fill(color);
6061
6156
  return;
6062
6157
  }
6063
- for (let iy = 0; iy < actualH; iy++) {
6064
- const start = (finalY + iy) * dw + finalX;
6065
- const end = start + actualW;
6158
+ for (let iy = 0; iy < fillH; iy++) {
6159
+ const start = (dstY + iy) * dw + dstX;
6160
+ const end = start + fillW;
6066
6161
  dst32.fill(color, start, end);
6067
6162
  }
6068
6163
  }
@@ -6080,36 +6175,48 @@ function copyPixelData(target) {
6080
6175
  }
6081
6176
 
6082
6177
  // src/PixelData/extractPixelDataBuffer.ts
6083
- var SCRATCH_BLIT4 = makeClippedBlit();
6084
6178
  function extractPixelDataBuffer(source, _x, _y, _w, _h) {
6085
- const {
6086
- x,
6087
- y,
6088
- w,
6089
- h
6090
- } = typeof _x === "object" ? _x : {
6091
- x: _x,
6092
- y: _y,
6093
- w: _w,
6094
- h: _h
6095
- };
6179
+ let x;
6180
+ let y;
6181
+ let w;
6182
+ let h;
6183
+ if (typeof _x === "object") {
6184
+ x = _x.x;
6185
+ y = _x.y;
6186
+ w = _x.w;
6187
+ h = _x.h;
6188
+ } else {
6189
+ x = _x;
6190
+ y = _y;
6191
+ w = _w;
6192
+ h = _h;
6193
+ }
6096
6194
  const srcW = source.w;
6097
6195
  const srcH = source.h;
6098
6196
  const srcData = source.data;
6099
- if (w <= 0 || h <= 0) {
6100
- return new Uint32Array(0);
6101
- }
6197
+ if (w <= 0) return new Uint32Array(0);
6198
+ if (h <= 0) return new Uint32Array(0);
6102
6199
  const dstData = new Uint32Array(w * h);
6103
- const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT4);
6104
- if (!clip.inBounds) return dstData;
6105
- const {
6106
- x: dstX,
6107
- y: dstY,
6108
- sx: srcX,
6109
- sy: srcY,
6110
- w: copyW,
6111
- h: copyH
6112
- } = clip;
6200
+ let srcX = x;
6201
+ let srcY = y;
6202
+ let dstX = 0;
6203
+ let dstY = 0;
6204
+ let copyW = w;
6205
+ let copyH = h;
6206
+ if (srcX < 0) {
6207
+ dstX = -srcX;
6208
+ copyW += srcX;
6209
+ srcX = 0;
6210
+ }
6211
+ if (srcY < 0) {
6212
+ dstY = -srcY;
6213
+ copyH += srcY;
6214
+ srcY = 0;
6215
+ }
6216
+ copyW = Math.min(copyW, srcW - srcX);
6217
+ copyH = Math.min(copyH, srcH - srcY);
6218
+ if (copyW <= 0) return dstData;
6219
+ if (copyH <= 0) return dstData;
6113
6220
  for (let row = 0; row < copyH; row++) {
6114
6221
  const srcStart = (srcY + row) * srcW + srcX;
6115
6222
  const dstStart = (dstY + row) * w + dstX;
@@ -6202,6 +6309,46 @@ function resamplePixelDataInPlace(pixelData, factor) {
6202
6309
  resampled.imageData = uInt32ArrayToImageData(resampled.data, resampled.w, resampled.h);
6203
6310
  }
6204
6311
 
6312
+ // src/PixelData/resizePixelData.ts
6313
+ function resizePixelData(target, newWidth, newHeight, offsetX = 0, offsetY = 0, out) {
6314
+ const newData = new Uint32Array(newWidth * newHeight);
6315
+ const {
6316
+ w: oldW,
6317
+ h: oldH,
6318
+ data: oldData
6319
+ } = target;
6320
+ const result = out ?? {};
6321
+ result.w = newWidth;
6322
+ result.h = newHeight;
6323
+ result.data = newData;
6324
+ const x0 = Math.max(0, offsetX);
6325
+ const y0 = Math.max(0, offsetY);
6326
+ const x1 = Math.min(newWidth, offsetX + oldW);
6327
+ const y1 = Math.min(newHeight, offsetY + oldH);
6328
+ if (x1 <= x0 || y1 <= y0) {
6329
+ return result;
6330
+ }
6331
+ const copyW = x1 - x0;
6332
+ const copyH = y1 - y0;
6333
+ if (copyW === oldW && copyW === newWidth && offsetX === 0) {
6334
+ const srcStart = (y0 - offsetY) * oldW;
6335
+ const dstStart = y0 * newWidth;
6336
+ const len = copyW * copyH;
6337
+ newData.set(oldData.subarray(srcStart, srcStart + len), dstStart);
6338
+ return result;
6339
+ }
6340
+ for (let row = 0; row < copyH; row++) {
6341
+ const dstY = y0 + row;
6342
+ const srcY = dstY - offsetY;
6343
+ const srcX = x0 - offsetX;
6344
+ const dstStart = dstY * newWidth + x0;
6345
+ const srcStart = srcY * oldW + srcX;
6346
+ const chunk = oldData.subarray(srcStart, srcStart + copyW);
6347
+ newData.set(chunk, dstStart);
6348
+ }
6349
+ return result;
6350
+ }
6351
+
6205
6352
  // src/PixelData/rotatePixelData.ts
6206
6353
  function rotatePixelData(pixelData) {
6207
6354
  const width = pixelData.w;
@@ -6255,36 +6402,50 @@ function uInt32ArrayToPixelData(data, width, height) {
6255
6402
  }
6256
6403
 
6257
6404
  // src/PixelData/writePixelDataBuffer.ts
6258
- var SCRATCH_BLIT5 = makeClippedBlit();
6259
6405
  function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
6260
- const {
6261
- x,
6262
- y,
6263
- w,
6264
- h
6265
- } = typeof _x === "object" ? _x : {
6266
- x: _x,
6267
- y: _y,
6268
- w: _w,
6269
- h: _h
6270
- };
6406
+ let x;
6407
+ let y;
6408
+ let w;
6409
+ let h;
6410
+ if (typeof _x === "object") {
6411
+ x = _x.x;
6412
+ y = _x.y;
6413
+ w = _x.w;
6414
+ h = _x.h;
6415
+ } else {
6416
+ x = _x;
6417
+ y = _y;
6418
+ w = _w;
6419
+ h = _h;
6420
+ }
6421
+ if (w <= 0 || h <= 0) return;
6271
6422
  const dstW = target.w;
6272
6423
  const dstH = target.h;
6273
6424
  const dstData = target.data;
6274
- const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT5);
6275
- if (!clip.inBounds) return;
6276
- const {
6277
- x: dstX,
6278
- y: dstY,
6279
- sx: srcX,
6280
- sy: srcY,
6281
- w: copyW,
6282
- h: copyH
6283
- } = clip;
6425
+ let dstX = x;
6426
+ let dstY = y;
6427
+ let srcX = 0;
6428
+ let srcY = 0;
6429
+ let copyW = w;
6430
+ let copyH = h;
6431
+ if (dstX < 0) {
6432
+ srcX = -dstX;
6433
+ copyW += dstX;
6434
+ dstX = 0;
6435
+ }
6436
+ if (dstY < 0) {
6437
+ srcY = -dstY;
6438
+ copyH += dstY;
6439
+ dstY = 0;
6440
+ }
6441
+ copyW = Math.min(copyW, dstW - dstX);
6442
+ copyH = Math.min(copyH, dstH - dstY);
6443
+ if (copyW <= 0 || copyH <= 0) return;
6284
6444
  for (let row = 0; row < copyH; row++) {
6285
6445
  const dstStart = (dstY + row) * dstW + dstX;
6286
6446
  const srcStart = (srcY + row) * w + srcX;
6287
- dstData.set(data.subarray(srcStart, srcStart + copyW), dstStart);
6447
+ const chunk = data.subarray(srcStart, srcStart + copyW);
6448
+ dstData.set(chunk, dstStart);
6288
6449
  }
6289
6450
  }
6290
6451
 
@@ -6375,6 +6536,7 @@ export {
6375
6536
  eachTileInBounds,
6376
6537
  exclusionFast,
6377
6538
  exclusionPerfect,
6539
+ extractImageData,
6378
6540
  extractImageDataBuffer,
6379
6541
  extractMask,
6380
6542
  extractMaskBuffer,
@@ -6424,6 +6586,7 @@ export {
6424
6586
  makeAlphaMaskPaintBufferCommitter,
6425
6587
  makeAlphaMaskPaintBufferManager,
6426
6588
  makeAlphaMaskTile,
6589
+ makeBatchedQueue,
6427
6590
  makeBinaryMask,
6428
6591
  makeBinaryMaskFromAlphaMask,
6429
6592
  makeBinaryMaskOutline,
@@ -6437,8 +6600,6 @@ export {
6437
6600
  makeCircleBinaryMaskOutline,
6438
6601
  makeCirclePaintAlphaMask,
6439
6602
  makeCirclePaintBinaryMask,
6440
- makeClippedBlit,
6441
- makeClippedRect,
6442
6603
  makeColorPaintBufferCanvasRenderer,
6443
6604
  makeColorPaintBufferCommitter,
6444
6605
  makeColorPaintBufferManager,
@@ -6458,6 +6619,7 @@ export {
6458
6619
  makePixelTile,
6459
6620
  makeRectBinaryMaskOutline,
6460
6621
  makeRectFalloffPaintAlphaMask,
6622
+ makeRenderQueue,
6461
6623
  makeReusableCanvas,
6462
6624
  makeReusableImageData,
6463
6625
  makeReusableOffscreenCanvas,
@@ -6504,8 +6666,7 @@ export {
6504
6666
  resamplePixelDataInPlace,
6505
6667
  resampleUint32Array,
6506
6668
  resizeImageData,
6507
- resolveBlitClipping,
6508
- resolveRectClipping,
6669
+ resizePixelData,
6509
6670
  rotatePixelData,
6510
6671
  screenFast,
6511
6672
  screenPerfect,