pixel-data-js 0.31.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.
@@ -93,6 +93,7 @@ __export(src_exports, {
93
93
  eachTileInBounds: () => eachTileInBounds,
94
94
  exclusionFast: () => exclusionFast,
95
95
  exclusionPerfect: () => exclusionPerfect,
96
+ extractImageData: () => extractImageData,
96
97
  extractImageDataBuffer: () => extractImageDataBuffer,
97
98
  extractMask: () => extractMask,
98
99
  extractMaskBuffer: () => extractMaskBuffer,
@@ -156,8 +157,6 @@ __export(src_exports, {
156
157
  makeCircleBinaryMaskOutline: () => makeCircleBinaryMaskOutline,
157
158
  makeCirclePaintAlphaMask: () => makeCirclePaintAlphaMask,
158
159
  makeCirclePaintBinaryMask: () => makeCirclePaintBinaryMask,
159
- makeClippedBlit: () => makeClippedBlit,
160
- makeClippedRect: () => makeClippedRect,
161
160
  makeColorPaintBufferCanvasRenderer: () => makeColorPaintBufferCanvasRenderer,
162
161
  makeColorPaintBufferCommitter: () => makeColorPaintBufferCommitter,
163
162
  makeColorPaintBufferManager: () => makeColorPaintBufferManager,
@@ -224,8 +223,7 @@ __export(src_exports, {
224
223
  resamplePixelDataInPlace: () => resamplePixelDataInPlace,
225
224
  resampleUint32Array: () => resampleUint32Array,
226
225
  resizeImageData: () => resizeImageData,
227
- resolveBlitClipping: () => resolveBlitClipping,
228
- resolveRectClipping: () => resolveRectClipping,
226
+ resizePixelData: () => resizePixelData,
229
227
  rotatePixelData: () => rotatePixelData,
230
228
  screenFast: () => screenFast,
231
229
  screenPerfect: () => screenPerfect,
@@ -353,86 +351,7 @@ function color32ToCssRGBA(color) {
353
351
  return `rgba(${r},${g},${b},${alpha})`;
354
352
  }
355
353
 
356
- // src/Rect/resolveClipping.ts
357
- var makeClippedRect = () => ({
358
- x: 0,
359
- y: 0,
360
- w: 0,
361
- h: 0,
362
- inBounds: false
363
- });
364
- var makeClippedBlit = () => ({
365
- x: 0,
366
- y: 0,
367
- sx: 0,
368
- sy: 0,
369
- w: 0,
370
- h: 0,
371
- inBounds: false
372
- });
373
- function resolveRectClipping(x, y, w, h, boundaryW, boundaryH, out) {
374
- if (x < 0) {
375
- w += x;
376
- x = 0;
377
- }
378
- if (y < 0) {
379
- h += y;
380
- y = 0;
381
- }
382
- const actualW = Math.min(w, boundaryW - x);
383
- const actualH = Math.min(h, boundaryH - y);
384
- if (actualW <= 0 || actualH <= 0) {
385
- out.inBounds = false;
386
- return out;
387
- }
388
- out.x = x;
389
- out.y = y;
390
- out.w = actualW;
391
- out.h = actualH;
392
- out.inBounds = true;
393
- return out;
394
- }
395
- function resolveBlitClipping(x, y, sx, sy, w, h, dstW, dstH, srcW, srcH, out) {
396
- if (sx < 0) {
397
- x -= sx;
398
- w += sx;
399
- sx = 0;
400
- }
401
- if (sy < 0) {
402
- y -= sy;
403
- h += sy;
404
- sy = 0;
405
- }
406
- w = Math.min(w, srcW - sx);
407
- h = Math.min(h, srcH - sy);
408
- if (x < 0) {
409
- sx -= x;
410
- w += x;
411
- x = 0;
412
- }
413
- if (y < 0) {
414
- sy -= y;
415
- h += y;
416
- y = 0;
417
- }
418
- const actualW = Math.min(w, dstW - x);
419
- const actualH = Math.min(h, dstH - y);
420
- if (actualW <= 0 || actualH <= 0) {
421
- out.inBounds = false;
422
- return out;
423
- }
424
- out.x = x;
425
- out.y = y;
426
- out.sx = sx;
427
- out.sy = sy;
428
- out.w = actualW;
429
- out.h = actualH;
430
- out.inBounds = true;
431
- return out;
432
- }
433
-
434
354
  // src/ImageData/extractImageDataBuffer.ts
435
- var SCRATCH_BLIT = makeClippedBlit();
436
355
  function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
437
356
  const {
438
357
  x,
@@ -445,28 +364,52 @@ function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
445
364
  w: _w,
446
365
  h: _h
447
366
  };
448
- const {
449
- width: srcW,
450
- height: srcH,
451
- data: src
452
- } = imageData;
453
- if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
454
- const out = new Uint8ClampedArray(w * h * 4);
455
- const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT);
456
- if (!clip.inBounds) return out;
457
- const {
458
- x: dstX,
459
- y: dstY,
460
- sx: srcX,
461
- sy: srcY,
462
- w: copyW,
463
- h: copyH
464
- } = clip;
465
- const rowLen = copyW * 4;
466
- for (let row = 0; row < copyH; row++) {
467
- const srcStart = ((srcY + row) * srcW + srcX) * 4;
468
- const dstStart = ((dstY + row) * w + dstX) * 4;
469
- out.set(src.subarray(srcStart, srcStart + rowLen), dstStart);
367
+ if (w <= 0) return new Uint8ClampedArray(0);
368
+ if (h <= 0) return new Uint8ClampedArray(0);
369
+ const srcW = imageData.width;
370
+ const srcH = imageData.height;
371
+ const src = imageData.data;
372
+ const outLen = w * h * 4;
373
+ const out = new Uint8ClampedArray(outLen);
374
+ let srcX = x;
375
+ let srcY = y;
376
+ let dstX = 0;
377
+ let dstY = 0;
378
+ let copyW = w;
379
+ let copyH = h;
380
+ if (srcX < 0) {
381
+ dstX = -srcX;
382
+ copyW += srcX;
383
+ srcX = 0;
384
+ }
385
+ if (srcY < 0) {
386
+ dstY = -srcY;
387
+ copyH += srcY;
388
+ srcY = 0;
389
+ }
390
+ copyW = Math.min(copyW, srcW - srcX);
391
+ copyH = Math.min(copyH, srcH - srcY);
392
+ if (copyW <= 0) return out;
393
+ if (copyH <= 0) return out;
394
+ const isAligned = src.byteOffset % 4 === 0;
395
+ if (isAligned) {
396
+ const srcLen32 = src.byteLength / 4;
397
+ const src32 = new Uint32Array(src.buffer, src.byteOffset, srcLen32);
398
+ const out32 = new Uint32Array(out.buffer);
399
+ for (let row = 0; row < copyH; row++) {
400
+ const srcStart = (srcY + row) * srcW + srcX;
401
+ const dstStart = (dstY + row) * w + dstX;
402
+ const chunk = src32.subarray(srcStart, srcStart + copyW);
403
+ out32.set(chunk, dstStart);
404
+ }
405
+ } else {
406
+ const rowLen = copyW * 4;
407
+ for (let row = 0; row < copyH; row++) {
408
+ const srcStart = ((srcY + row) * srcW + srcX) * 4;
409
+ const dstStart = ((dstY + row) * w + dstX) * 4;
410
+ const chunk = src.subarray(srcStart, srcStart + rowLen);
411
+ out.set(chunk, dstStart);
412
+ }
470
413
  }
471
414
  return out;
472
415
  }
@@ -3907,8 +3850,9 @@ var mutatorBlendPixelData = ((writer, deps = defaults13) => {
3907
3850
  });
3908
3851
 
3909
3852
  // src/PixelData/fillPixelData.ts
3910
- var SCRATCH_RECT = makeClippedRect();
3911
3853
  function fillPixelData(dst, color, _x, _y, _w, _h) {
3854
+ const dstW = dst.w;
3855
+ const dstH = dst.h;
3912
3856
  let x;
3913
3857
  let y;
3914
3858
  let w;
@@ -3916,8 +3860,8 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3916
3860
  if (typeof _x === "object") {
3917
3861
  x = _x.x ?? 0;
3918
3862
  y = _x.y ?? 0;
3919
- w = _x.w ?? dst.w;
3920
- h = _x.h ?? dst.h;
3863
+ w = _x.w ?? dstW;
3864
+ h = _x.h ?? dstH;
3921
3865
  } else if (typeof _x === "number") {
3922
3866
  x = _x;
3923
3867
  y = _y;
@@ -3926,24 +3870,42 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3926
3870
  } else {
3927
3871
  x = 0;
3928
3872
  y = 0;
3929
- w = dst.w;
3930
- h = dst.h;
3931
- }
3932
- const clip = resolveRectClipping(x, y, w, h, dst.w, dst.h, SCRATCH_RECT);
3933
- if (!clip.inBounds) return false;
3934
- const {
3935
- x: finalX,
3936
- y: finalY,
3937
- w: actualW,
3938
- h: actualH
3939
- } = clip;
3873
+ w = dstW;
3874
+ h = dstH;
3875
+ }
3876
+ let dstX = x;
3877
+ let dstY = y;
3878
+ let fillW = w;
3879
+ let fillH = h;
3880
+ if (dstX < 0) {
3881
+ fillW += dstX;
3882
+ dstX = 0;
3883
+ }
3884
+ if (dstY < 0) {
3885
+ fillH += dstY;
3886
+ dstY = 0;
3887
+ }
3888
+ fillW = Math.min(fillW, dstW - dstX);
3889
+ fillH = Math.min(fillH, dstH - dstY);
3890
+ if (fillW <= 0) return false;
3891
+ if (fillH <= 0) return false;
3940
3892
  const dst32 = dst.data;
3941
- const dw = dst.w;
3942
3893
  let hasChanged = false;
3943
- for (let iy = 0; iy < actualH; iy++) {
3944
- const rowOffset = (finalY + iy) * dw;
3945
- const start = rowOffset + finalX;
3946
- const end = start + actualW;
3894
+ if (dstX === 0 && fillW === dstW) {
3895
+ const start = dstY * dstW;
3896
+ const end = start + fillW * fillH;
3897
+ for (let i = start; i < end; i++) {
3898
+ if (dst32[i] !== color) {
3899
+ dst32[i] = color;
3900
+ hasChanged = true;
3901
+ }
3902
+ }
3903
+ return hasChanged;
3904
+ }
3905
+ for (let iy = 0; iy < fillH; iy++) {
3906
+ const rowOffset = (dstY + iy) * dstW;
3907
+ const start = rowOffset + dstX;
3908
+ const end = start + fillW;
3947
3909
  for (let i = start; i < end; i++) {
3948
3910
  if (dst32[i] !== color) {
3949
3911
  dst32[i] = color;
@@ -4005,39 +3967,48 @@ var mutatorFillRect = ((writer, deps = defaults15) => {
4005
3967
  });
4006
3968
 
4007
3969
  // src/PixelData/fillPixelDataBinaryMask.ts
4008
- var SCRATCH_RECT2 = makeClippedRect();
4009
3970
  function fillPixelDataBinaryMask(target, color, mask, x = 0, y = 0) {
3971
+ const targetW = target.w;
3972
+ const targetH = target.h;
4010
3973
  const maskW = mask.w;
4011
3974
  const maskH = mask.h;
4012
- const clip = resolveRectClipping(x, y, maskW, maskH, target.w, target.h, SCRATCH_RECT2);
4013
- if (!clip.inBounds) return false;
4014
- const {
4015
- x: finalX,
4016
- y: finalY,
4017
- w: actualW,
4018
- h: actualH
4019
- } = clip;
3975
+ let dstX = x;
3976
+ let dstY = y;
3977
+ let actualW = maskW;
3978
+ let actualH = maskH;
3979
+ if (dstX < 0) {
3980
+ actualW += dstX;
3981
+ dstX = 0;
3982
+ }
3983
+ if (dstY < 0) {
3984
+ actualH += dstY;
3985
+ dstY = 0;
3986
+ }
3987
+ actualW = Math.min(actualW, targetW - dstX);
3988
+ actualH = Math.min(actualH, targetH - dstY);
3989
+ if (actualW <= 0 || actualH <= 0) return false;
4020
3990
  const maskData = mask.data;
4021
3991
  const dst32 = target.data;
4022
- const dw = target.w;
3992
+ const mx = dstX - x;
3993
+ const my = dstY - y;
4023
3994
  let hasChanged = false;
3995
+ let dIdx = dstY * targetW + dstX;
3996
+ let mIdx = my * maskW + mx;
3997
+ const dStride = targetW - actualW;
3998
+ const mStride = maskW - actualW;
4024
3999
  for (let iy = 0; iy < actualH; iy++) {
4025
- const currentY = finalY + iy;
4026
- const maskY = currentY - y;
4027
- const maskOffset = maskY * maskW;
4028
- const dstRowOffset = currentY * dw;
4029
4000
  for (let ix = 0; ix < actualW; ix++) {
4030
- const currentX = finalX + ix;
4031
- const maskX = currentX - x;
4032
- const maskIndex = maskOffset + maskX;
4033
- if (maskData[maskIndex]) {
4034
- const current = dst32[dstRowOffset + currentX];
4035
- if (current !== color) {
4036
- dst32[dstRowOffset + currentX] = color;
4001
+ if (maskData[mIdx]) {
4002
+ if (dst32[dIdx] !== color) {
4003
+ dst32[dIdx] = color;
4037
4004
  hasChanged = true;
4038
4005
  }
4039
4006
  }
4007
+ dIdx++;
4008
+ mIdx++;
4040
4009
  }
4010
+ dIdx += dStride;
4011
+ mIdx += mStride;
4041
4012
  }
4042
4013
  return hasChanged;
4043
4014
  }
@@ -4059,35 +4030,43 @@ var mutatorFillBinaryMask = ((writer, deps = defaults16) => {
4059
4030
  });
4060
4031
 
4061
4032
  // src/PixelData/invertPixelData.ts
4062
- var SCRATCH_RECT3 = makeClippedRect();
4063
4033
  function invertPixelData(target, opts) {
4034
+ const targetW = target.w;
4035
+ const targetH = target.h;
4064
4036
  const mask = opts?.mask;
4037
+ const invertMask = opts?.invertMask ?? false;
4065
4038
  const targetX = opts?.x ?? 0;
4066
4039
  const targetY = opts?.y ?? 0;
4067
4040
  const mx = opts?.mx ?? 0;
4068
4041
  const my = opts?.my ?? 0;
4069
- const width = opts?.w ?? target.w;
4070
- const height = opts?.h ?? target.h;
4071
- const invertMask = opts?.invertMask ?? false;
4072
- const clip = resolveRectClipping(targetX, targetY, width, height, target.w, target.h, SCRATCH_RECT3);
4073
- if (!clip.inBounds) return false;
4074
- const {
4075
- x,
4076
- y,
4077
- w: actualW,
4078
- h: actualH
4079
- } = clip;
4042
+ const w = opts?.w ?? targetW;
4043
+ const h = opts?.h ?? targetH;
4044
+ let x = targetX;
4045
+ let y = targetY;
4046
+ let actualW = w;
4047
+ let actualH = h;
4048
+ if (x < 0) {
4049
+ actualW += x;
4050
+ x = 0;
4051
+ }
4052
+ if (y < 0) {
4053
+ actualH += y;
4054
+ y = 0;
4055
+ }
4056
+ actualW = Math.min(actualW, targetW - x);
4057
+ actualH = Math.min(actualH, targetH - y);
4058
+ if (actualW <= 0 || actualH <= 0) return false;
4080
4059
  const dst32 = target.data;
4081
- const dw = target.w;
4082
- const mPitch = mask?.w ?? width;
4060
+ const dw = targetW;
4083
4061
  const dx = x - targetX;
4084
4062
  const dy = y - targetY;
4085
4063
  let dIdx = y * dw + x;
4086
- let mIdx = (my + dy) * mPitch + (mx + dx);
4087
4064
  const dStride = dw - actualW;
4088
- const mStride = mPitch - actualW;
4089
4065
  if (mask) {
4090
4066
  const maskData = mask.data;
4067
+ const mPitch = mask.w;
4068
+ let mIdx = (my + dy) * mPitch + (mx + dx);
4069
+ const mStride = mPitch - actualW;
4091
4070
  for (let iy = 0; iy < actualH; iy++) {
4092
4071
  for (let ix = 0; ix < actualW; ix++) {
4093
4072
  const mVal = maskData[mIdx];
@@ -4179,6 +4158,27 @@ function copyImageDataLike({
4179
4158
  };
4180
4159
  }
4181
4160
 
4161
+ // src/ImageData/extractImageData.ts
4162
+ function extractImageData(imageData, _x, _y, _w, _h) {
4163
+ const {
4164
+ x,
4165
+ y,
4166
+ w,
4167
+ h
4168
+ } = typeof _x === "object" ? _x : {
4169
+ x: _x,
4170
+ y: _y,
4171
+ w: _w,
4172
+ h: _h
4173
+ };
4174
+ if (w <= 0) return null;
4175
+ if (h <= 0) return null;
4176
+ const result = new ImageData(w, h);
4177
+ const buffer = extractImageDataBuffer(imageData, x, y, w, h);
4178
+ result.data.set(buffer);
4179
+ return result;
4180
+ }
4181
+
4182
4182
  // src/ImageData/ImageDataLike.ts
4183
4183
  function makeImageDataLike(width, height, data) {
4184
4184
  const size = width * height * 4;
@@ -4329,94 +4329,120 @@ function uInt32ArrayToImageDataLike(data, width, height) {
4329
4329
  }
4330
4330
 
4331
4331
  // src/ImageData/writeImageData.ts
4332
- var SCRATCH_BLIT2 = makeClippedBlit();
4333
- function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
4332
+ function writeImageData(target, source, x, y) {
4334
4333
  const dstW = target.width;
4335
4334
  const dstH = target.height;
4336
- const dstData = target.data;
4335
+ const dst = target.data;
4337
4336
  const srcW = source.width;
4338
- const srcData = source.data;
4339
- const clip = resolveBlitClipping(x, y, sx, sy, sw, sh, dstW, dstH, srcW, source.height, SCRATCH_BLIT2);
4340
- if (!clip.inBounds) return;
4341
- const {
4342
- x: dstX,
4343
- y: dstY,
4344
- sx: srcX,
4345
- sy: srcY,
4346
- w: copyW,
4347
- h: copyH
4348
- } = clip;
4349
- const useMask = !!mask;
4350
- for (let row = 0; row < copyH; row++) {
4351
- const currentDstY = dstY + row;
4352
- const currentSrcY = srcY + row;
4353
- const dstStart = (currentDstY * dstW + dstX) * 4;
4354
- const srcStart = (currentSrcY * srcW + srcX) * 4;
4355
- if (useMask && mask) {
4356
- for (let ix = 0; ix < copyW; ix++) {
4357
- const mi = currentSrcY * srcW + (srcX + ix);
4358
- const alpha = mask[mi];
4359
- if (alpha === 0) {
4360
- continue;
4361
- }
4362
- const di = dstStart + ix * 4;
4363
- const si = srcStart + ix * 4;
4364
- if (maskType === 1 /* BINARY */ || alpha === 255) {
4365
- dstData[di] = srcData[si];
4366
- dstData[di + 1] = srcData[si + 1];
4367
- dstData[di + 2] = srcData[si + 2];
4368
- dstData[di + 3] = srcData[si + 3];
4369
- } else {
4370
- const a = alpha / 255;
4371
- const invA = 1 - a;
4372
- dstData[di] = srcData[si] * a + dstData[di] * invA;
4373
- dstData[di + 1] = srcData[si + 1] * a + dstData[di + 1] * invA;
4374
- dstData[di + 2] = srcData[si + 2] * a + dstData[di + 2] * invA;
4375
- dstData[di + 3] = srcData[si + 3] * a + dstData[di + 3] * invA;
4376
- }
4377
- }
4378
- } else {
4379
- const byteLen = copyW * 4;
4380
- const sub = srcData.subarray(srcStart, srcStart + byteLen);
4381
- dstData.set(sub, dstStart);
4337
+ const srcH = source.height;
4338
+ const src = source.data;
4339
+ let dstX = x;
4340
+ let dstY = y;
4341
+ let srcX = 0;
4342
+ let srcY = 0;
4343
+ let copyW = srcW;
4344
+ let copyH = srcH;
4345
+ if (dstX < 0) {
4346
+ srcX = -dstX;
4347
+ copyW += dstX;
4348
+ dstX = 0;
4349
+ }
4350
+ if (dstY < 0) {
4351
+ srcY = -dstY;
4352
+ copyH += dstY;
4353
+ dstY = 0;
4354
+ }
4355
+ copyW = Math.min(copyW, dstW - dstX);
4356
+ copyH = Math.min(copyH, dstH - dstY);
4357
+ if (copyW <= 0) return;
4358
+ if (copyH <= 0) return;
4359
+ const isDstAligned = dst.byteOffset % 4 === 0;
4360
+ const isSrcAligned = src.byteOffset % 4 === 0;
4361
+ if (isDstAligned && isSrcAligned) {
4362
+ const dstLen32 = dst.byteLength / 4;
4363
+ const dst32 = new Uint32Array(dst.buffer, dst.byteOffset, dstLen32);
4364
+ const srcLen32 = src.byteLength / 4;
4365
+ const src32 = new Uint32Array(src.buffer, src.byteOffset, srcLen32);
4366
+ for (let row = 0; row < copyH; row++) {
4367
+ const dstStart = (dstY + row) * dstW + dstX;
4368
+ const srcStart = (srcY + row) * srcW + srcX;
4369
+ const chunk = src32.subarray(srcStart, srcStart + copyW);
4370
+ dst32.set(chunk, dstStart);
4371
+ }
4372
+ } else {
4373
+ const rowLen = copyW * 4;
4374
+ for (let row = 0; row < copyH; row++) {
4375
+ const dstStart = ((dstY + row) * dstW + dstX) * 4;
4376
+ const srcStart = ((srcY + row) * srcW + srcX) * 4;
4377
+ const chunk = src.subarray(srcStart, srcStart + rowLen);
4378
+ dst.set(chunk, dstStart);
4382
4379
  }
4383
4380
  }
4384
4381
  }
4385
4382
 
4386
4383
  // src/ImageData/writeImageDataBuffer.ts
4387
- var SCRATCH_BLIT3 = makeClippedBlit();
4388
4384
  function writeImageDataBuffer(target, data, _x, _y, _w, _h) {
4389
- const {
4390
- x,
4391
- y,
4392
- w,
4393
- h
4394
- } = typeof _x === "object" ? _x : {
4395
- x: _x,
4396
- y: _y,
4397
- w: _w,
4398
- h: _h
4399
- };
4400
- const {
4401
- width: dstW,
4402
- height: dstH,
4403
- data: dst
4404
- } = target;
4405
- const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT3);
4406
- if (!clip.inBounds) return;
4407
- const {
4408
- x: dstX,
4409
- y: dstY,
4410
- sx: srcX,
4411
- sy: srcY,
4412
- w: copyW,
4413
- h: copyH
4414
- } = clip;
4415
- const rowLen = copyW * 4;
4416
- for (let row = 0; row < copyH; row++) {
4417
- const dstStart = ((dstY + row) * dstW + dstX) * 4;
4418
- const srcStart = ((srcY + row) * w + srcX) * 4;
4419
- dst.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
4385
+ let x;
4386
+ let y;
4387
+ let w;
4388
+ let h;
4389
+ if (typeof _x === "object") {
4390
+ x = _x.x;
4391
+ y = _x.y;
4392
+ w = _x.w;
4393
+ h = _x.h;
4394
+ } else {
4395
+ x = _x;
4396
+ y = _y;
4397
+ w = _w;
4398
+ h = _h;
4399
+ }
4400
+ if (w <= 0) return;
4401
+ if (h <= 0) return;
4402
+ const dstW = target.width;
4403
+ const dstH = target.height;
4404
+ const dst = target.data;
4405
+ let dstX = x;
4406
+ let dstY = y;
4407
+ let srcX = 0;
4408
+ let srcY = 0;
4409
+ let copyW = w;
4410
+ let copyH = h;
4411
+ if (dstX < 0) {
4412
+ srcX = -dstX;
4413
+ copyW += dstX;
4414
+ dstX = 0;
4415
+ }
4416
+ if (dstY < 0) {
4417
+ srcY = -dstY;
4418
+ copyH += dstY;
4419
+ dstY = 0;
4420
+ }
4421
+ copyW = Math.min(copyW, dstW - dstX);
4422
+ copyH = Math.min(copyH, dstH - dstY);
4423
+ if (copyW <= 0) return;
4424
+ if (copyH <= 0) return;
4425
+ const isDstAligned = dst.byteOffset % 4 === 0;
4426
+ const isSrcAligned = data.byteOffset % 4 === 0;
4427
+ if (isDstAligned && isSrcAligned) {
4428
+ const dstLen32 = dst.byteLength / 4;
4429
+ const dst32 = new Uint32Array(dst.buffer, dst.byteOffset, dstLen32);
4430
+ const srcLen32 = data.byteLength / 4;
4431
+ const src32 = new Uint32Array(data.buffer, data.byteOffset, srcLen32);
4432
+ for (let row = 0; row < copyH; row++) {
4433
+ const dstStart = (dstY + row) * dstW + dstX;
4434
+ const srcStart = (srcY + row) * w + srcX;
4435
+ const chunk = src32.subarray(srcStart, srcStart + copyW);
4436
+ dst32.set(chunk, dstStart);
4437
+ }
4438
+ } else {
4439
+ const rowLen = copyW * 4;
4440
+ for (let row = 0; row < copyH; row++) {
4441
+ const dstStart = ((dstY + row) * dstW + dstX) * 4;
4442
+ const srcStart = ((srcY + row) * w + srcX) * 4;
4443
+ const chunk = data.subarray(srcStart, srcStart + rowLen);
4444
+ dst.set(chunk, dstStart);
4445
+ }
4420
4446
  }
4421
4447
  }
4422
4448
 
@@ -6349,8 +6375,9 @@ function blendPixelDataPaintBuffer(target, paintBuffer, alpha = 255, blendFn, bl
6349
6375
  }
6350
6376
 
6351
6377
  // src/PixelData/fillPixelDataFast.ts
6352
- var SCRATCH_RECT4 = makeClippedRect();
6353
6378
  function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
6379
+ const dstW = dst.w;
6380
+ const dstH = dst.h;
6354
6381
  let x;
6355
6382
  let y;
6356
6383
  let w;
@@ -6371,23 +6398,31 @@ function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
6371
6398
  w = dst.w;
6372
6399
  h = dst.h;
6373
6400
  }
6374
- const clip = resolveRectClipping(x, y, w, h, dst.w, dst.h, SCRATCH_RECT4);
6375
- if (!clip.inBounds) return;
6376
- const {
6377
- x: finalX,
6378
- y: finalY,
6379
- w: actualW,
6380
- h: actualH
6381
- } = clip;
6401
+ let dstX = x;
6402
+ let dstY = y;
6403
+ let fillW = w;
6404
+ let fillH = h;
6405
+ if (dstX < 0) {
6406
+ fillW += dstX;
6407
+ dstX = 0;
6408
+ }
6409
+ if (dstY < 0) {
6410
+ fillH += dstY;
6411
+ dstY = 0;
6412
+ }
6413
+ fillW = Math.min(fillW, dstW - dstX);
6414
+ fillH = Math.min(fillH, dstH - dstY);
6415
+ if (fillW <= 0) return;
6416
+ if (fillH <= 0) return;
6382
6417
  const dst32 = dst.data;
6383
6418
  const dw = dst.w;
6384
- if (actualW === dw && actualH === dst.h && finalX === 0 && finalY === 0) {
6419
+ if (fillW === dw && fillH === dst.h && dstX === 0 && dstY === 0) {
6385
6420
  dst32.fill(color);
6386
6421
  return;
6387
6422
  }
6388
- for (let iy = 0; iy < actualH; iy++) {
6389
- const start = (finalY + iy) * dw + finalX;
6390
- const end = start + actualW;
6423
+ for (let iy = 0; iy < fillH; iy++) {
6424
+ const start = (dstY + iy) * dw + dstX;
6425
+ const end = start + fillW;
6391
6426
  dst32.fill(color, start, end);
6392
6427
  }
6393
6428
  }
@@ -6405,36 +6440,48 @@ function copyPixelData(target) {
6405
6440
  }
6406
6441
 
6407
6442
  // src/PixelData/extractPixelDataBuffer.ts
6408
- var SCRATCH_BLIT4 = makeClippedBlit();
6409
6443
  function extractPixelDataBuffer(source, _x, _y, _w, _h) {
6410
- const {
6411
- x,
6412
- y,
6413
- w,
6414
- h
6415
- } = typeof _x === "object" ? _x : {
6416
- x: _x,
6417
- y: _y,
6418
- w: _w,
6419
- h: _h
6420
- };
6444
+ let x;
6445
+ let y;
6446
+ let w;
6447
+ let h;
6448
+ if (typeof _x === "object") {
6449
+ x = _x.x;
6450
+ y = _x.y;
6451
+ w = _x.w;
6452
+ h = _x.h;
6453
+ } else {
6454
+ x = _x;
6455
+ y = _y;
6456
+ w = _w;
6457
+ h = _h;
6458
+ }
6421
6459
  const srcW = source.w;
6422
6460
  const srcH = source.h;
6423
6461
  const srcData = source.data;
6424
- if (w <= 0 || h <= 0) {
6425
- return new Uint32Array(0);
6426
- }
6462
+ if (w <= 0) return new Uint32Array(0);
6463
+ if (h <= 0) return new Uint32Array(0);
6427
6464
  const dstData = new Uint32Array(w * h);
6428
- const clip = resolveBlitClipping(0, 0, x, y, w, h, w, h, srcW, srcH, SCRATCH_BLIT4);
6429
- if (!clip.inBounds) return dstData;
6430
- const {
6431
- x: dstX,
6432
- y: dstY,
6433
- sx: srcX,
6434
- sy: srcY,
6435
- w: copyW,
6436
- h: copyH
6437
- } = clip;
6465
+ let srcX = x;
6466
+ let srcY = y;
6467
+ let dstX = 0;
6468
+ let dstY = 0;
6469
+ let copyW = w;
6470
+ let copyH = h;
6471
+ if (srcX < 0) {
6472
+ dstX = -srcX;
6473
+ copyW += srcX;
6474
+ srcX = 0;
6475
+ }
6476
+ if (srcY < 0) {
6477
+ dstY = -srcY;
6478
+ copyH += srcY;
6479
+ srcY = 0;
6480
+ }
6481
+ copyW = Math.min(copyW, srcW - srcX);
6482
+ copyH = Math.min(copyH, srcH - srcY);
6483
+ if (copyW <= 0) return dstData;
6484
+ if (copyH <= 0) return dstData;
6438
6485
  for (let row = 0; row < copyH; row++) {
6439
6486
  const srcStart = (srcY + row) * srcW + srcX;
6440
6487
  const dstStart = (dstY + row) * w + dstX;
@@ -6527,6 +6574,46 @@ function resamplePixelDataInPlace(pixelData, factor) {
6527
6574
  resampled.imageData = uInt32ArrayToImageData(resampled.data, resampled.w, resampled.h);
6528
6575
  }
6529
6576
 
6577
+ // src/PixelData/resizePixelData.ts
6578
+ function resizePixelData(target, newWidth, newHeight, offsetX = 0, offsetY = 0, out) {
6579
+ const newData = new Uint32Array(newWidth * newHeight);
6580
+ const {
6581
+ w: oldW,
6582
+ h: oldH,
6583
+ data: oldData
6584
+ } = target;
6585
+ const result = out ?? {};
6586
+ result.w = newWidth;
6587
+ result.h = newHeight;
6588
+ result.data = newData;
6589
+ const x0 = Math.max(0, offsetX);
6590
+ const y0 = Math.max(0, offsetY);
6591
+ const x1 = Math.min(newWidth, offsetX + oldW);
6592
+ const y1 = Math.min(newHeight, offsetY + oldH);
6593
+ if (x1 <= x0 || y1 <= y0) {
6594
+ return result;
6595
+ }
6596
+ const copyW = x1 - x0;
6597
+ const copyH = y1 - y0;
6598
+ if (copyW === oldW && copyW === newWidth && offsetX === 0) {
6599
+ const srcStart = (y0 - offsetY) * oldW;
6600
+ const dstStart = y0 * newWidth;
6601
+ const len = copyW * copyH;
6602
+ newData.set(oldData.subarray(srcStart, srcStart + len), dstStart);
6603
+ return result;
6604
+ }
6605
+ for (let row = 0; row < copyH; row++) {
6606
+ const dstY = y0 + row;
6607
+ const srcY = dstY - offsetY;
6608
+ const srcX = x0 - offsetX;
6609
+ const dstStart = dstY * newWidth + x0;
6610
+ const srcStart = srcY * oldW + srcX;
6611
+ const chunk = oldData.subarray(srcStart, srcStart + copyW);
6612
+ newData.set(chunk, dstStart);
6613
+ }
6614
+ return result;
6615
+ }
6616
+
6530
6617
  // src/PixelData/rotatePixelData.ts
6531
6618
  function rotatePixelData(pixelData) {
6532
6619
  const width = pixelData.w;
@@ -6580,36 +6667,50 @@ function uInt32ArrayToPixelData(data, width, height) {
6580
6667
  }
6581
6668
 
6582
6669
  // src/PixelData/writePixelDataBuffer.ts
6583
- var SCRATCH_BLIT5 = makeClippedBlit();
6584
6670
  function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
6585
- const {
6586
- x,
6587
- y,
6588
- w,
6589
- h
6590
- } = typeof _x === "object" ? _x : {
6591
- x: _x,
6592
- y: _y,
6593
- w: _w,
6594
- h: _h
6595
- };
6671
+ let x;
6672
+ let y;
6673
+ let w;
6674
+ let h;
6675
+ if (typeof _x === "object") {
6676
+ x = _x.x;
6677
+ y = _x.y;
6678
+ w = _x.w;
6679
+ h = _x.h;
6680
+ } else {
6681
+ x = _x;
6682
+ y = _y;
6683
+ w = _w;
6684
+ h = _h;
6685
+ }
6686
+ if (w <= 0 || h <= 0) return;
6596
6687
  const dstW = target.w;
6597
6688
  const dstH = target.h;
6598
6689
  const dstData = target.data;
6599
- const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT5);
6600
- if (!clip.inBounds) return;
6601
- const {
6602
- x: dstX,
6603
- y: dstY,
6604
- sx: srcX,
6605
- sy: srcY,
6606
- w: copyW,
6607
- h: copyH
6608
- } = clip;
6690
+ let dstX = x;
6691
+ let dstY = y;
6692
+ let srcX = 0;
6693
+ let srcY = 0;
6694
+ let copyW = w;
6695
+ let copyH = h;
6696
+ if (dstX < 0) {
6697
+ srcX = -dstX;
6698
+ copyW += dstX;
6699
+ dstX = 0;
6700
+ }
6701
+ if (dstY < 0) {
6702
+ srcY = -dstY;
6703
+ copyH += dstY;
6704
+ dstY = 0;
6705
+ }
6706
+ copyW = Math.min(copyW, dstW - dstX);
6707
+ copyH = Math.min(copyH, dstH - dstY);
6708
+ if (copyW <= 0 || copyH <= 0) return;
6609
6709
  for (let row = 0; row < copyH; row++) {
6610
6710
  const dstStart = (dstY + row) * dstW + dstX;
6611
6711
  const srcStart = (srcY + row) * w + srcX;
6612
- dstData.set(data.subarray(srcStart, srcStart + copyW), dstStart);
6712
+ const chunk = data.subarray(srcStart, srcStart + copyW);
6713
+ dstData.set(chunk, dstStart);
6613
6714
  }
6614
6715
  }
6615
6716
 
@@ -6701,6 +6802,7 @@ function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn
6701
6802
  eachTileInBounds,
6702
6803
  exclusionFast,
6703
6804
  exclusionPerfect,
6805
+ extractImageData,
6704
6806
  extractImageDataBuffer,
6705
6807
  extractMask,
6706
6808
  extractMaskBuffer,
@@ -6764,8 +6866,6 @@ function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn
6764
6866
  makeCircleBinaryMaskOutline,
6765
6867
  makeCirclePaintAlphaMask,
6766
6868
  makeCirclePaintBinaryMask,
6767
- makeClippedBlit,
6768
- makeClippedRect,
6769
6869
  makeColorPaintBufferCanvasRenderer,
6770
6870
  makeColorPaintBufferCommitter,
6771
6871
  makeColorPaintBufferManager,
@@ -6832,8 +6932,7 @@ function writePaintBufferToPixelData(target, paintBuffer, writePixelDataBufferFn
6832
6932
  resamplePixelDataInPlace,
6833
6933
  resampleUint32Array,
6834
6934
  resizeImageData,
6835
- resolveBlitClipping,
6836
- resolveRectClipping,
6935
+ resizePixelData,
6837
6936
  rotatePixelData,
6838
6937
  screenFast,
6839
6938
  screenPerfect,