pixel-data-js 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.dev.cjs +1024 -596
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1010 -592
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1024 -596
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +280 -165
- package/dist/index.prod.js +1010 -592
- package/dist/index.prod.js.map +1 -1
- package/package.json +3 -2
- package/src/Canvas/CanvasFrameRenderer.ts +57 -0
- package/src/Canvas/ReusableCanvas.ts +60 -11
- package/src/History/HistoryAction.ts +38 -0
- package/src/History/HistoryManager.ts +4 -8
- package/src/History/PixelAccumulator.ts +95 -80
- package/src/History/PixelEngineConfig.ts +18 -6
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +6 -6
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +6 -6
- package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +6 -5
- package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +22 -22
- package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +6 -5
- package/src/History/PixelMutator/mutatorApplyRectBrush.ts +19 -19
- package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +6 -4
- package/src/History/PixelMutator/mutatorApplyRectPencil.ts +20 -20
- package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +6 -4
- package/src/History/PixelMutator/mutatorBlendColor.ts +8 -5
- package/src/History/PixelMutator/mutatorBlendColorCircleMask.ts +71 -0
- package/src/History/PixelMutator/mutatorBlendPixel.ts +22 -26
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +5 -3
- package/src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts +5 -3
- package/src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts +5 -3
- package/src/History/PixelMutator/mutatorClear.ts +7 -6
- package/src/History/PixelMutator/mutatorFill.ts +34 -9
- package/src/History/PixelMutator/mutatorFillBinaryMask.ts +4 -2
- package/src/History/PixelMutator/mutatorInvert.ts +8 -4
- package/src/History/PixelMutator.ts +4 -3
- package/src/History/PixelPatchTiles.ts +3 -15
- package/src/History/PixelWriter.ts +29 -33
- package/src/ImageData/ReusableImageData.ts +3 -5
- package/src/Mask/{CircleBrushAlphaMask.ts → CircleAlphaMask.ts} +2 -2
- package/src/Mask/{CircleBrushBinaryMask.ts → CircleBinaryMask.ts} +2 -2
- package/src/PixelData/PixelData.ts +1 -27
- package/src/PixelData/applyAlphaMaskToPixelData.ts +19 -9
- package/src/PixelData/applyBinaryMaskToPixelData.ts +24 -17
- package/src/PixelData/applyRectBrushToPixelData.ts +18 -5
- package/src/PixelData/blendColorPixelData.ts +31 -7
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +16 -6
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +16 -7
- package/src/PixelData/{applyCircleBrushToPixelData.ts → blendColorPixelDataCircleMask.ts} +11 -10
- package/src/PixelData/blendPixel.ts +47 -0
- package/src/PixelData/blendPixelData.ts +14 -4
- package/src/PixelData/blendPixelDataAlphaMask.ts +12 -4
- package/src/PixelData/blendPixelDataBinaryMask.ts +13 -4
- package/src/PixelData/blendPixelDataPaintBuffer.ts +37 -0
- package/src/PixelData/clearPixelData.ts +2 -2
- package/src/PixelData/fillPixelData.ts +26 -16
- package/src/PixelData/fillPixelDataBinaryMask.ts +12 -4
- package/src/PixelData/fillPixelDataFast.ts +94 -0
- package/src/PixelData/invertPixelData.ts +4 -2
- package/src/PixelTile/PaintBuffer.ts +122 -0
- package/src/PixelTile/PaintBufferRenderer.ts +40 -0
- package/src/PixelTile/PixelTile.ts +21 -0
- package/src/PixelTile/PixelTilePool.ts +63 -0
- package/src/_types.ts +9 -9
- package/src/index.ts +16 -6
- package/src/History/PixelMutator/mutatorApplyCircleBrush.ts +0 -78
package/dist/index.dev.js
CHANGED
|
@@ -436,6 +436,26 @@ function floodFillSelection(img, startX, startY, {
|
|
|
436
436
|
};
|
|
437
437
|
}
|
|
438
438
|
|
|
439
|
+
// src/Algorithm/forEachLinePoint.ts
|
|
440
|
+
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
441
|
+
const dx = x1 - x0;
|
|
442
|
+
const dy = y1 - y0;
|
|
443
|
+
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
444
|
+
if (steps === 0) {
|
|
445
|
+
callback(x0, y0);
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const xInc = dx / steps;
|
|
449
|
+
const yInc = dy / steps;
|
|
450
|
+
let curX = x0;
|
|
451
|
+
let curY = y0;
|
|
452
|
+
for (let i = 0; i <= steps; i++) {
|
|
453
|
+
callback(curX, curY);
|
|
454
|
+
curX += xInc;
|
|
455
|
+
curY += yInc;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
439
459
|
// src/BlendModes/blend-modes.ts
|
|
440
460
|
var BaseBlendMode = {
|
|
441
461
|
overwrite: 0,
|
|
@@ -1513,51 +1533,104 @@ var getKeyByValue = (obj, value) => {
|
|
|
1513
1533
|
var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
|
|
1514
1534
|
var CANVAS_CTX_FAILED = "Failed to create Canvas context";
|
|
1515
1535
|
|
|
1516
|
-
// src/Canvas/PixelCanvas.ts
|
|
1517
|
-
function makePixelCanvas(canvas) {
|
|
1518
|
-
const ctx = canvas.getContext("2d");
|
|
1519
|
-
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
1520
|
-
ctx.imageSmoothingEnabled = false;
|
|
1521
|
-
return {
|
|
1522
|
-
canvas,
|
|
1523
|
-
ctx,
|
|
1524
|
-
resize(w, h) {
|
|
1525
|
-
canvas.width = w;
|
|
1526
|
-
canvas.height = h;
|
|
1527
|
-
ctx.imageSmoothingEnabled = false;
|
|
1528
|
-
}
|
|
1529
|
-
};
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
1536
|
// src/Canvas/ReusableCanvas.ts
|
|
1533
1537
|
function makeReusableCanvas() {
|
|
1538
|
+
return makeReusableCanvasMeta((w, h) => {
|
|
1539
|
+
const canvas = document.createElement("canvas");
|
|
1540
|
+
canvas.width = w;
|
|
1541
|
+
canvas.height = h;
|
|
1542
|
+
return canvas;
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
function makeReusableOffscreenCanvas() {
|
|
1546
|
+
return makeReusableCanvasMeta((w, h) => new OffscreenCanvas(w, h));
|
|
1547
|
+
}
|
|
1548
|
+
function makeReusableCanvasMeta(factory) {
|
|
1534
1549
|
let canvas = null;
|
|
1535
1550
|
let ctx = null;
|
|
1551
|
+
const result = {
|
|
1552
|
+
canvas: null,
|
|
1553
|
+
ctx: null
|
|
1554
|
+
};
|
|
1536
1555
|
function get2(width, height) {
|
|
1537
1556
|
if (canvas === null) {
|
|
1538
|
-
canvas =
|
|
1557
|
+
canvas = factory(width, height);
|
|
1539
1558
|
ctx = canvas.getContext("2d");
|
|
1540
|
-
if (!ctx)
|
|
1559
|
+
if (!ctx) {
|
|
1560
|
+
throw new Error(CANVAS_CTX_FAILED);
|
|
1561
|
+
}
|
|
1562
|
+
ctx.imageSmoothingEnabled = false;
|
|
1563
|
+
result.canvas = canvas;
|
|
1564
|
+
result.ctx = ctx;
|
|
1565
|
+
return result;
|
|
1541
1566
|
}
|
|
1542
1567
|
if (canvas.width !== width || canvas.height !== height) {
|
|
1543
1568
|
canvas.width = width;
|
|
1544
1569
|
canvas.height = height;
|
|
1545
1570
|
ctx.imageSmoothingEnabled = false;
|
|
1546
1571
|
} else {
|
|
1572
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
1547
1573
|
ctx.clearRect(0, 0, width, height);
|
|
1548
1574
|
}
|
|
1549
|
-
return
|
|
1550
|
-
canvas,
|
|
1551
|
-
ctx
|
|
1552
|
-
};
|
|
1575
|
+
return result;
|
|
1553
1576
|
}
|
|
1554
1577
|
get2.reset = () => {
|
|
1555
1578
|
canvas = null;
|
|
1556
1579
|
ctx = null;
|
|
1580
|
+
result.canvas = null;
|
|
1581
|
+
result.ctx = null;
|
|
1557
1582
|
};
|
|
1558
1583
|
return get2;
|
|
1559
1584
|
}
|
|
1560
1585
|
|
|
1586
|
+
// src/Canvas/CanvasFrameRenderer.ts
|
|
1587
|
+
var defaults = {
|
|
1588
|
+
makeReusableCanvas
|
|
1589
|
+
};
|
|
1590
|
+
function makeCanvasFrameRenderer(deps = defaults) {
|
|
1591
|
+
const {
|
|
1592
|
+
makeReusableCanvas: makeReusableCanvas2 = defaults.makeReusableCanvas
|
|
1593
|
+
} = deps;
|
|
1594
|
+
const bufferCanvas = makeReusableCanvas2();
|
|
1595
|
+
return function renderCanvasFrame(pixelCanvas, scale, getImageData, drawPixelLayer, drawScreenLayer) {
|
|
1596
|
+
const {
|
|
1597
|
+
canvas,
|
|
1598
|
+
ctx
|
|
1599
|
+
} = pixelCanvas;
|
|
1600
|
+
const {
|
|
1601
|
+
ctx: pxCtx,
|
|
1602
|
+
canvas: pxCanvas
|
|
1603
|
+
} = bufferCanvas(canvas.width, canvas.height);
|
|
1604
|
+
const img = getImageData();
|
|
1605
|
+
if (img) {
|
|
1606
|
+
pxCtx.putImageData(img, 0, 0);
|
|
1607
|
+
}
|
|
1608
|
+
drawPixelLayer?.(pxCtx);
|
|
1609
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
1610
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1611
|
+
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
|
1612
|
+
ctx.drawImage(pxCanvas, 0, 0);
|
|
1613
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
1614
|
+
drawScreenLayer?.(ctx, scale);
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
// src/Canvas/PixelCanvas.ts
|
|
1619
|
+
function makePixelCanvas(canvas) {
|
|
1620
|
+
const ctx = canvas.getContext("2d");
|
|
1621
|
+
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
1622
|
+
ctx.imageSmoothingEnabled = false;
|
|
1623
|
+
return {
|
|
1624
|
+
canvas,
|
|
1625
|
+
ctx,
|
|
1626
|
+
resize(w, h) {
|
|
1627
|
+
canvas.width = w;
|
|
1628
|
+
canvas.height = h;
|
|
1629
|
+
ctx.imageSmoothingEnabled = false;
|
|
1630
|
+
}
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1561
1634
|
// src/ImageData/imgBlobToImageData.ts
|
|
1562
1635
|
async function imgBlobToImageData(blob) {
|
|
1563
1636
|
let bitmap = null;
|
|
@@ -1617,6 +1690,50 @@ async function writeImageDataToClipboard(imageData) {
|
|
|
1617
1690
|
return writeImgBlobToClipboard(blob);
|
|
1618
1691
|
}
|
|
1619
1692
|
|
|
1693
|
+
// src/History/PixelPatchTiles.ts
|
|
1694
|
+
function applyPatchTiles(target, tiles, tileSize) {
|
|
1695
|
+
for (let i = 0; i < tiles.length; i++) {
|
|
1696
|
+
const tile = tiles[i];
|
|
1697
|
+
if (!tile) continue;
|
|
1698
|
+
const dst = target.data32;
|
|
1699
|
+
const src = tile.data32;
|
|
1700
|
+
const dstWidth = target.width;
|
|
1701
|
+
const dstHeight = target.height;
|
|
1702
|
+
const startX = tile.tx * tileSize;
|
|
1703
|
+
const startY = tile.ty * tileSize;
|
|
1704
|
+
const copyWidth = Math.max(0, Math.min(tileSize, dstWidth - startX));
|
|
1705
|
+
if (copyWidth <= 0) continue;
|
|
1706
|
+
for (let ly = 0; ly < tileSize; ly++) {
|
|
1707
|
+
const globalY = startY + ly;
|
|
1708
|
+
if (globalY >= dstHeight) break;
|
|
1709
|
+
const dstIndex = globalY * dstWidth + startX;
|
|
1710
|
+
const srcIndex = ly * tileSize;
|
|
1711
|
+
const rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1712
|
+
dst.set(rowData, dstIndex);
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
// src/History/HistoryAction.ts
|
|
1718
|
+
function makeHistoryAction(writer, patch, after, afterUndo, afterRedo, applyPatchTilesFn = applyPatchTiles) {
|
|
1719
|
+
const target = writer.config.target;
|
|
1720
|
+
const tileSize = writer.config.tileSize;
|
|
1721
|
+
const accumulator = writer.accumulator;
|
|
1722
|
+
return {
|
|
1723
|
+
undo: () => {
|
|
1724
|
+
applyPatchTilesFn(target, patch.beforeTiles, tileSize);
|
|
1725
|
+
afterUndo?.();
|
|
1726
|
+
after?.();
|
|
1727
|
+
},
|
|
1728
|
+
redo: () => {
|
|
1729
|
+
applyPatchTilesFn(target, patch.afterTiles, tileSize);
|
|
1730
|
+
afterRedo?.();
|
|
1731
|
+
after?.();
|
|
1732
|
+
},
|
|
1733
|
+
dispose: () => accumulator.recyclePatch(patch)
|
|
1734
|
+
};
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1620
1737
|
// src/History/HistoryManager.ts
|
|
1621
1738
|
var HistoryManager = class {
|
|
1622
1739
|
constructor(maxSteps = 50) {
|
|
@@ -1675,126 +1792,91 @@ var HistoryManager = class {
|
|
|
1675
1792
|
}
|
|
1676
1793
|
};
|
|
1677
1794
|
|
|
1678
|
-
// src/History/PixelPatchTiles.ts
|
|
1679
|
-
var PixelTile = class {
|
|
1680
|
-
constructor(id, tx, ty, tileArea) {
|
|
1681
|
-
this.id = id;
|
|
1682
|
-
this.tx = tx;
|
|
1683
|
-
this.ty = ty;
|
|
1684
|
-
this.data32 = new Uint32Array(tileArea);
|
|
1685
|
-
}
|
|
1686
|
-
data32;
|
|
1687
|
-
};
|
|
1688
|
-
function applyPatchTiles(target, tiles, tileSize = 256) {
|
|
1689
|
-
for (let i = 0; i < tiles.length; i++) {
|
|
1690
|
-
const tile = tiles[i];
|
|
1691
|
-
if (!tile) continue;
|
|
1692
|
-
const dst = target.data32;
|
|
1693
|
-
const src = tile.data32;
|
|
1694
|
-
const dstWidth = target.width;
|
|
1695
|
-
const dstHeight = target.height;
|
|
1696
|
-
const startX = tile.tx * tileSize;
|
|
1697
|
-
const startY = tile.ty * tileSize;
|
|
1698
|
-
const copyWidth = Math.max(0, Math.min(tileSize, dstWidth - startX));
|
|
1699
|
-
if (copyWidth <= 0) return;
|
|
1700
|
-
for (let ly = 0; ly < tileSize; ly++) {
|
|
1701
|
-
const globalY = startY + ly;
|
|
1702
|
-
if (globalY >= dstHeight) break;
|
|
1703
|
-
const dstIndex = globalY * dstWidth + startX;
|
|
1704
|
-
const srcIndex = ly * tileSize;
|
|
1705
|
-
const rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1706
|
-
dst.set(rowData, dstIndex);
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
|
|
1711
1795
|
// src/History/PixelAccumulator.ts
|
|
1712
1796
|
var PixelAccumulator = class {
|
|
1713
|
-
constructor(
|
|
1714
|
-
this.target = target;
|
|
1797
|
+
constructor(config, tilePool) {
|
|
1715
1798
|
this.config = config;
|
|
1799
|
+
this.tilePool = tilePool;
|
|
1716
1800
|
this.lookup = [];
|
|
1717
1801
|
this.beforeTiles = [];
|
|
1718
|
-
this.pool = [];
|
|
1719
1802
|
}
|
|
1720
1803
|
lookup;
|
|
1721
1804
|
beforeTiles;
|
|
1722
|
-
pool;
|
|
1723
|
-
getTile(id, tx, ty) {
|
|
1724
|
-
let tile = this.pool.pop();
|
|
1725
|
-
if (tile) {
|
|
1726
|
-
tile.id = id;
|
|
1727
|
-
tile.tx = tx;
|
|
1728
|
-
tile.ty = ty;
|
|
1729
|
-
return tile;
|
|
1730
|
-
}
|
|
1731
|
-
return new PixelTile(id, tx, ty, this.config.tileArea);
|
|
1732
|
-
}
|
|
1733
1805
|
recyclePatch(patch) {
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
let tile = before[i];
|
|
1737
|
-
if (tile) {
|
|
1738
|
-
this.pool.push(tile);
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
const after = patch.afterTiles;
|
|
1742
|
-
for (let i = 0; i < after.length; i++) {
|
|
1743
|
-
let tile = after[i];
|
|
1744
|
-
if (tile) {
|
|
1745
|
-
this.pool.push(tile);
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1806
|
+
this.tilePool.releaseTiles(patch.beforeTiles);
|
|
1807
|
+
this.tilePool.releaseTiles(patch.afterTiles);
|
|
1748
1808
|
}
|
|
1749
1809
|
/**
|
|
1750
1810
|
* @param x pixel x coordinate
|
|
1751
1811
|
* @param y pixel y coordinate
|
|
1752
1812
|
*/
|
|
1753
|
-
|
|
1754
|
-
let target = this.target;
|
|
1813
|
+
storePixelBeforeState(x, y) {
|
|
1755
1814
|
let shift = this.config.tileShift;
|
|
1756
|
-
let columns =
|
|
1815
|
+
let columns = this.config.targetColumns;
|
|
1757
1816
|
let tx = x >> shift;
|
|
1758
1817
|
let ty = y >> shift;
|
|
1759
1818
|
let id = ty * columns + tx;
|
|
1760
1819
|
let tile = this.lookup[id];
|
|
1820
|
+
let added = false;
|
|
1761
1821
|
if (!tile) {
|
|
1762
|
-
tile = this.getTile(id, tx, ty);
|
|
1822
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
1763
1823
|
this.extractState(tile);
|
|
1764
1824
|
this.lookup[id] = tile;
|
|
1765
1825
|
this.beforeTiles.push(tile);
|
|
1826
|
+
added = true;
|
|
1766
1827
|
}
|
|
1828
|
+
return (didChange) => {
|
|
1829
|
+
if (!didChange && added) {
|
|
1830
|
+
this.beforeTiles.pop();
|
|
1831
|
+
this.lookup[id] = void 0;
|
|
1832
|
+
this.tilePool.releaseTile(tile);
|
|
1833
|
+
}
|
|
1834
|
+
return didChange;
|
|
1835
|
+
};
|
|
1767
1836
|
}
|
|
1768
1837
|
/**
|
|
1769
|
-
*
|
|
1770
1838
|
* @param x pixel x coordinate
|
|
1771
1839
|
* @param y pixel y coordinate
|
|
1772
1840
|
* @param w pixel width
|
|
1773
1841
|
* @param h pixel height
|
|
1774
1842
|
*/
|
|
1775
1843
|
storeRegionBeforeState(x, y, w, h) {
|
|
1776
|
-
let target = this.target;
|
|
1777
1844
|
let shift = this.config.tileShift;
|
|
1778
|
-
let columns =
|
|
1845
|
+
let columns = this.config.targetColumns;
|
|
1779
1846
|
let startX = x >> shift;
|
|
1780
1847
|
let startY = y >> shift;
|
|
1781
1848
|
let endX = x + w - 1 >> shift;
|
|
1782
1849
|
let endY = y + h - 1 >> shift;
|
|
1850
|
+
let startIndex = this.beforeTiles.length;
|
|
1783
1851
|
for (let ty = startY; ty <= endY; ty++) {
|
|
1784
1852
|
for (let tx = startX; tx <= endX; tx++) {
|
|
1785
1853
|
let id = ty * columns + tx;
|
|
1786
1854
|
let tile = this.lookup[id];
|
|
1787
1855
|
if (!tile) {
|
|
1788
|
-
tile = this.getTile(id, tx, ty);
|
|
1856
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
1789
1857
|
this.extractState(tile);
|
|
1790
1858
|
this.lookup[id] = tile;
|
|
1791
1859
|
this.beforeTiles.push(tile);
|
|
1792
1860
|
}
|
|
1793
1861
|
}
|
|
1794
1862
|
}
|
|
1863
|
+
return (didChange) => {
|
|
1864
|
+
if (!didChange) {
|
|
1865
|
+
let length = this.beforeTiles.length;
|
|
1866
|
+
for (let i = startIndex; i < length; i++) {
|
|
1867
|
+
let t = this.beforeTiles[i];
|
|
1868
|
+
if (t) {
|
|
1869
|
+
this.lookup[t.id] = void 0;
|
|
1870
|
+
this.tilePool.releaseTile(t);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
this.beforeTiles.length = startIndex;
|
|
1874
|
+
}
|
|
1875
|
+
return didChange;
|
|
1876
|
+
};
|
|
1795
1877
|
}
|
|
1796
1878
|
extractState(tile) {
|
|
1797
|
-
let target = this.target;
|
|
1879
|
+
let target = this.config.target;
|
|
1798
1880
|
let TILE_SIZE = this.config.tileSize;
|
|
1799
1881
|
let dst = tile.data32;
|
|
1800
1882
|
let src = target.data32;
|
|
@@ -1802,7 +1884,12 @@ var PixelAccumulator = class {
|
|
|
1802
1884
|
let startY = tile.ty * TILE_SIZE;
|
|
1803
1885
|
let targetWidth = target.width;
|
|
1804
1886
|
let targetHeight = target.height;
|
|
1805
|
-
|
|
1887
|
+
if (startX >= targetWidth || startX + TILE_SIZE <= 0 || startY >= targetHeight || startY + TILE_SIZE <= 0) {
|
|
1888
|
+
dst.fill(0);
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
let srcOffsetX = Math.max(0, -startX);
|
|
1892
|
+
let copyWidth = Math.max(0, Math.min(TILE_SIZE - srcOffsetX, targetWidth - Math.max(0, startX)));
|
|
1806
1893
|
for (let ly = 0; ly < TILE_SIZE; ly++) {
|
|
1807
1894
|
let globalY = startY + ly;
|
|
1808
1895
|
let dstIndex = ly * TILE_SIZE;
|
|
@@ -1810,47 +1897,77 @@ var PixelAccumulator = class {
|
|
|
1810
1897
|
dst.fill(0, dstIndex, dstIndex + TILE_SIZE);
|
|
1811
1898
|
continue;
|
|
1812
1899
|
}
|
|
1813
|
-
let srcIndex = globalY * targetWidth + startX;
|
|
1900
|
+
let srcIndex = globalY * targetWidth + Math.max(0, startX);
|
|
1814
1901
|
let rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1815
|
-
dst.set(rowData, dstIndex);
|
|
1816
|
-
if (
|
|
1817
|
-
dst.fill(0, dstIndex
|
|
1902
|
+
dst.set(rowData, dstIndex + srcOffsetX);
|
|
1903
|
+
if (srcOffsetX > 0) {
|
|
1904
|
+
dst.fill(0, dstIndex, dstIndex + srcOffsetX);
|
|
1905
|
+
}
|
|
1906
|
+
if (srcOffsetX + copyWidth < TILE_SIZE) {
|
|
1907
|
+
dst.fill(0, dstIndex + srcOffsetX + copyWidth, dstIndex + TILE_SIZE);
|
|
1818
1908
|
}
|
|
1819
1909
|
}
|
|
1820
1910
|
}
|
|
1821
|
-
|
|
1911
|
+
extractPatch() {
|
|
1822
1912
|
let afterTiles = [];
|
|
1823
1913
|
let length = this.beforeTiles.length;
|
|
1824
1914
|
for (let i = 0; i < length; i++) {
|
|
1825
1915
|
let beforeTile = this.beforeTiles[i];
|
|
1826
1916
|
if (beforeTile) {
|
|
1827
|
-
let afterTile = this.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
|
|
1917
|
+
let afterTile = this.tilePool.getTile(beforeTile.id, beforeTile.tx, beforeTile.ty);
|
|
1828
1918
|
this.extractState(afterTile);
|
|
1829
1919
|
afterTiles.push(afterTile);
|
|
1830
1920
|
}
|
|
1831
1921
|
}
|
|
1832
|
-
|
|
1833
|
-
}
|
|
1834
|
-
reset() {
|
|
1835
|
-
this.lookup = [];
|
|
1922
|
+
let beforeTiles = this.beforeTiles;
|
|
1836
1923
|
this.beforeTiles = [];
|
|
1924
|
+
this.lookup.length = 0;
|
|
1925
|
+
return {
|
|
1926
|
+
beforeTiles,
|
|
1927
|
+
afterTiles
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
rollback() {
|
|
1931
|
+
let target = this.config.target;
|
|
1932
|
+
let tileSize = this.config.tileSize;
|
|
1933
|
+
let length = this.beforeTiles.length;
|
|
1934
|
+
applyPatchTiles(target, this.beforeTiles, tileSize);
|
|
1935
|
+
for (let i = 0; i < length; i++) {
|
|
1936
|
+
let tile = this.beforeTiles[i];
|
|
1937
|
+
if (tile) {
|
|
1938
|
+
this.lookup[tile.id] = void 0;
|
|
1939
|
+
this.tilePool.releaseTile(tile);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
this.beforeTiles.length = 0;
|
|
1943
|
+
this.lookup.length = 0;
|
|
1837
1944
|
}
|
|
1838
1945
|
};
|
|
1839
1946
|
|
|
1840
1947
|
// src/History/PixelEngineConfig.ts
|
|
1841
1948
|
var PixelEngineConfig = class {
|
|
1842
1949
|
tileSize;
|
|
1950
|
+
// pixelX = tileX << tileShift
|
|
1951
|
+
// pixelY = tileY << tileShift
|
|
1843
1952
|
tileShift;
|
|
1844
1953
|
tileMask;
|
|
1845
1954
|
tileArea;
|
|
1846
|
-
|
|
1955
|
+
target;
|
|
1956
|
+
targetColumns = 0;
|
|
1957
|
+
constructor(tileSize, target) {
|
|
1847
1958
|
if ((tileSize & tileSize - 1) !== 0) {
|
|
1848
1959
|
throw new Error("tileSize must be a power of 2");
|
|
1849
1960
|
}
|
|
1850
1961
|
this.tileSize = tileSize;
|
|
1851
|
-
this.tileShift = Math.
|
|
1962
|
+
this.tileShift = 31 - Math.clz32(tileSize);
|
|
1852
1963
|
this.tileMask = tileSize - 1;
|
|
1853
1964
|
this.tileArea = tileSize * tileSize;
|
|
1965
|
+
this.setTarget(target);
|
|
1966
|
+
}
|
|
1967
|
+
setTarget(target) {
|
|
1968
|
+
;
|
|
1969
|
+
this.target = target;
|
|
1970
|
+
this.targetColumns = target.width + this.tileMask >> this.tileShift;
|
|
1854
1971
|
}
|
|
1855
1972
|
};
|
|
1856
1973
|
|
|
@@ -1866,7 +1983,7 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1866
1983
|
my = 0,
|
|
1867
1984
|
invertMask = false
|
|
1868
1985
|
} = opts;
|
|
1869
|
-
if (globalAlpha === 0) return;
|
|
1986
|
+
if (globalAlpha === 0) return false;
|
|
1870
1987
|
let x = targetX;
|
|
1871
1988
|
let y = targetY;
|
|
1872
1989
|
let w = width;
|
|
@@ -1881,10 +1998,10 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1881
1998
|
}
|
|
1882
1999
|
w = Math.min(w, dst.width - x);
|
|
1883
2000
|
h = Math.min(h, dst.height - y);
|
|
1884
|
-
if (w <= 0) return;
|
|
1885
|
-
if (h <= 0) return;
|
|
2001
|
+
if (w <= 0) return false;
|
|
2002
|
+
if (h <= 0) return false;
|
|
1886
2003
|
const mPitch = mask.w;
|
|
1887
|
-
if (mPitch <= 0) return;
|
|
2004
|
+
if (mPitch <= 0) return false;
|
|
1888
2005
|
const startX = mx + (x - targetX);
|
|
1889
2006
|
const startY = my + (y - targetY);
|
|
1890
2007
|
const sX0 = Math.max(0, startX);
|
|
@@ -1893,8 +2010,8 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1893
2010
|
const sY1 = Math.min(mask.h, startY + h);
|
|
1894
2011
|
const finalW = sX1 - sX0;
|
|
1895
2012
|
const finalH = sY1 - sY0;
|
|
1896
|
-
if (finalW <= 0) return;
|
|
1897
|
-
if (finalH <= 0) return;
|
|
2013
|
+
if (finalW <= 0) return false;
|
|
2014
|
+
if (finalH <= 0) return false;
|
|
1898
2015
|
const xShift = sX0 - startX;
|
|
1899
2016
|
const yShift = sY0 - startY;
|
|
1900
2017
|
const dst32 = dst.data32;
|
|
@@ -1904,6 +2021,7 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1904
2021
|
const maskData = mask.data;
|
|
1905
2022
|
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
1906
2023
|
let mIdx = sY0 * mPitch + sX0;
|
|
2024
|
+
let didChange = false;
|
|
1907
2025
|
for (let iy = 0; iy < h; iy++) {
|
|
1908
2026
|
for (let ix = 0; ix < w; ix++) {
|
|
1909
2027
|
const mVal = maskData[mIdx];
|
|
@@ -1920,12 +2038,18 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1920
2038
|
}
|
|
1921
2039
|
if (weight === 0) {
|
|
1922
2040
|
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2041
|
+
didChange = true;
|
|
1923
2042
|
} else if (weight !== 255) {
|
|
1924
2043
|
const d = dst32[dIdx];
|
|
1925
2044
|
const da = d >>> 24;
|
|
1926
2045
|
if (da !== 0) {
|
|
1927
2046
|
const finalAlpha = da === 255 ? weight : da * weight + 128 >> 8;
|
|
1928
|
-
dst32[dIdx]
|
|
2047
|
+
const current = dst32[dIdx];
|
|
2048
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2049
|
+
if (current !== next) {
|
|
2050
|
+
dst32[dIdx] = next;
|
|
2051
|
+
didChange = true;
|
|
2052
|
+
}
|
|
1929
2053
|
}
|
|
1930
2054
|
}
|
|
1931
2055
|
dIdx++;
|
|
@@ -1934,27 +2058,28 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1934
2058
|
dIdx += dStride;
|
|
1935
2059
|
mIdx += mStride;
|
|
1936
2060
|
}
|
|
2061
|
+
return didChange;
|
|
1937
2062
|
}
|
|
1938
2063
|
|
|
1939
2064
|
// src/History/PixelMutator/mutatorApplyAlphaMask.ts
|
|
1940
|
-
var
|
|
2065
|
+
var defaults2 = {
|
|
1941
2066
|
applyAlphaMaskToPixelData
|
|
1942
2067
|
};
|
|
1943
|
-
var mutatorApplyAlphaMask = ((writer, deps =
|
|
2068
|
+
var mutatorApplyAlphaMask = ((writer, deps = defaults2) => {
|
|
1944
2069
|
const {
|
|
1945
|
-
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 =
|
|
2070
|
+
applyAlphaMaskToPixelData: applyAlphaMaskToPixelData2 = defaults2.applyAlphaMaskToPixelData
|
|
1946
2071
|
} = deps;
|
|
1947
2072
|
return {
|
|
1948
|
-
applyAlphaMask
|
|
1949
|
-
let target = writer.target;
|
|
2073
|
+
applyAlphaMask(mask, opts = {}) {
|
|
2074
|
+
let target = writer.config.target;
|
|
1950
2075
|
const {
|
|
1951
2076
|
x = 0,
|
|
1952
2077
|
y = 0,
|
|
1953
|
-
w =
|
|
1954
|
-
h =
|
|
2078
|
+
w = target.width,
|
|
2079
|
+
h = target.height
|
|
1955
2080
|
} = opts;
|
|
1956
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
1957
|
-
applyAlphaMaskToPixelData2(target, mask, opts);
|
|
2081
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2082
|
+
return didChange(applyAlphaMaskToPixelData2(target, mask, opts));
|
|
1958
2083
|
}
|
|
1959
2084
|
};
|
|
1960
2085
|
});
|
|
@@ -1971,7 +2096,7 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1971
2096
|
my = 0,
|
|
1972
2097
|
invertMask = false
|
|
1973
2098
|
} = opts;
|
|
1974
|
-
if (globalAlpha === 0) return;
|
|
2099
|
+
if (globalAlpha === 0) return false;
|
|
1975
2100
|
let x = targetX;
|
|
1976
2101
|
let y = targetY;
|
|
1977
2102
|
let w = width;
|
|
@@ -1986,10 +2111,9 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1986
2111
|
}
|
|
1987
2112
|
w = Math.min(w, dst.width - x);
|
|
1988
2113
|
h = Math.min(h, dst.height - y);
|
|
1989
|
-
if (w <= 0) return;
|
|
1990
|
-
if (h <= 0) return;
|
|
2114
|
+
if (w <= 0 || h <= 0) return false;
|
|
1991
2115
|
const mPitch = mask.w;
|
|
1992
|
-
if (mPitch <= 0) return;
|
|
2116
|
+
if (mPitch <= 0) return false;
|
|
1993
2117
|
const startX = mx + (x - targetX);
|
|
1994
2118
|
const startY = my + (y - targetY);
|
|
1995
2119
|
const sX0 = Math.max(0, startX);
|
|
@@ -1998,8 +2122,9 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1998
2122
|
const sY1 = Math.min(mask.h, startY + h);
|
|
1999
2123
|
const finalW = sX1 - sX0;
|
|
2000
2124
|
const finalH = sY1 - sY0;
|
|
2001
|
-
if (finalW <= 0)
|
|
2002
|
-
|
|
2125
|
+
if (finalW <= 0 || finalH <= 0) {
|
|
2126
|
+
return false;
|
|
2127
|
+
}
|
|
2003
2128
|
const xShift = sX0 - startX;
|
|
2004
2129
|
const yShift = sY0 - startY;
|
|
2005
2130
|
const dst32 = dst.data32;
|
|
@@ -2009,18 +2134,28 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2009
2134
|
const maskData = mask.data;
|
|
2010
2135
|
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2011
2136
|
let mIdx = sY0 * mPitch + sX0;
|
|
2012
|
-
|
|
2013
|
-
|
|
2137
|
+
let didChange = false;
|
|
2138
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
2139
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
2014
2140
|
const mVal = maskData[mIdx];
|
|
2015
2141
|
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
2016
2142
|
if (isMaskedOut) {
|
|
2017
|
-
|
|
2143
|
+
const current = dst32[dIdx];
|
|
2144
|
+
const next = (current & 16777215) >>> 0;
|
|
2145
|
+
if (current !== next) {
|
|
2146
|
+
dst32[dIdx] = next;
|
|
2147
|
+
didChange = true;
|
|
2148
|
+
}
|
|
2018
2149
|
} else if (globalAlpha !== 255) {
|
|
2019
2150
|
const d = dst32[dIdx];
|
|
2020
2151
|
const da = d >>> 24;
|
|
2021
2152
|
if (da !== 0) {
|
|
2022
2153
|
const finalAlpha = da === 255 ? globalAlpha : da * globalAlpha + 128 >> 8;
|
|
2023
|
-
|
|
2154
|
+
const next = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2155
|
+
if (d !== next) {
|
|
2156
|
+
dst32[dIdx] = next;
|
|
2157
|
+
didChange = true;
|
|
2158
|
+
}
|
|
2024
2159
|
}
|
|
2025
2160
|
}
|
|
2026
2161
|
dIdx++;
|
|
@@ -2029,59 +2164,32 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2029
2164
|
dIdx += dStride;
|
|
2030
2165
|
mIdx += mStride;
|
|
2031
2166
|
}
|
|
2167
|
+
return didChange;
|
|
2032
2168
|
}
|
|
2033
2169
|
|
|
2034
2170
|
// src/History/PixelMutator/mutatorApplyBinaryMask.ts
|
|
2035
|
-
var
|
|
2171
|
+
var defaults3 = {
|
|
2036
2172
|
applyBinaryMaskToPixelData
|
|
2037
2173
|
};
|
|
2038
|
-
var mutatorApplyBinaryMask = ((writer, deps =
|
|
2174
|
+
var mutatorApplyBinaryMask = ((writer, deps = defaults3) => {
|
|
2039
2175
|
const {
|
|
2040
|
-
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 =
|
|
2176
|
+
applyBinaryMaskToPixelData: applyBinaryMaskToPixelData2 = defaults3.applyBinaryMaskToPixelData
|
|
2041
2177
|
} = deps;
|
|
2042
2178
|
return {
|
|
2043
|
-
applyBinaryMask
|
|
2044
|
-
let target = writer.target;
|
|
2179
|
+
applyBinaryMask(mask, opts = {}) {
|
|
2180
|
+
let target = writer.config.target;
|
|
2045
2181
|
const {
|
|
2046
2182
|
x = 0,
|
|
2047
2183
|
y = 0,
|
|
2048
|
-
w =
|
|
2049
|
-
h =
|
|
2184
|
+
w = target.width,
|
|
2185
|
+
h = target.height
|
|
2050
2186
|
} = opts;
|
|
2051
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2052
|
-
applyBinaryMaskToPixelData2(target, mask, opts);
|
|
2187
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2188
|
+
return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
|
|
2053
2189
|
}
|
|
2054
2190
|
};
|
|
2055
2191
|
});
|
|
2056
2192
|
|
|
2057
|
-
// src/Rect/getCircleBrushOrPencilBounds.ts
|
|
2058
|
-
function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight, out) {
|
|
2059
|
-
const r = brushSize / 2;
|
|
2060
|
-
const minOffset = -Math.ceil(r - 0.5);
|
|
2061
|
-
const maxOffset = Math.floor(r - 0.5);
|
|
2062
|
-
const startX = Math.floor(centerX + minOffset);
|
|
2063
|
-
const startY = Math.floor(centerY + minOffset);
|
|
2064
|
-
const endX = Math.floor(centerX + maxOffset) + 1;
|
|
2065
|
-
const endY = Math.floor(centerY + maxOffset) + 1;
|
|
2066
|
-
const res = out ?? {
|
|
2067
|
-
x: 0,
|
|
2068
|
-
y: 0,
|
|
2069
|
-
w: 0,
|
|
2070
|
-
h: 0
|
|
2071
|
-
};
|
|
2072
|
-
const cStartX = Math.max(0, startX);
|
|
2073
|
-
const cStartY = Math.max(0, startY);
|
|
2074
|
-
const cEndX = Math.min(targetWidth, endX);
|
|
2075
|
-
const cEndY = Math.min(targetHeight, endY);
|
|
2076
|
-
const w = cEndX - cStartX;
|
|
2077
|
-
const h = cEndY - cStartY;
|
|
2078
|
-
res.x = cStartX;
|
|
2079
|
-
res.y = cStartY;
|
|
2080
|
-
res.w = w < 0 ? 0 : w;
|
|
2081
|
-
res.h = h < 0 ? 0 : h;
|
|
2082
|
-
return res;
|
|
2083
|
-
}
|
|
2084
|
-
|
|
2085
2193
|
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
2086
2194
|
function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
2087
2195
|
const targetX = opts.x ?? 0;
|
|
@@ -2093,10 +2201,10 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2093
2201
|
const mx = opts.mx ?? 0;
|
|
2094
2202
|
const my = opts.my ?? 0;
|
|
2095
2203
|
const invertMask = opts.invertMask ?? false;
|
|
2096
|
-
if (globalAlpha === 0) return;
|
|
2204
|
+
if (globalAlpha === 0) return false;
|
|
2097
2205
|
const baseSrcAlpha = color >>> 24;
|
|
2098
2206
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
2099
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2207
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2100
2208
|
let x = targetX;
|
|
2101
2209
|
let y = targetY;
|
|
2102
2210
|
let actualW = w;
|
|
@@ -2111,7 +2219,7 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2111
2219
|
}
|
|
2112
2220
|
actualW = Math.min(actualW, dst.width - x);
|
|
2113
2221
|
actualH = Math.min(actualH, dst.height - y);
|
|
2114
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
2222
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2115
2223
|
const dx = x - targetX | 0;
|
|
2116
2224
|
const dy = y - targetY | 0;
|
|
2117
2225
|
const dst32 = dst.data32;
|
|
@@ -2121,9 +2229,10 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2121
2229
|
let dIdx = y * dw + x | 0;
|
|
2122
2230
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2123
2231
|
const dStride = dw - actualW | 0;
|
|
2124
|
-
|
|
2232
|
+
const mStride = mPitch - actualW | 0;
|
|
2125
2233
|
const isOpaque = globalAlpha === 255;
|
|
2126
2234
|
const colorRGB = color & 16777215;
|
|
2235
|
+
let didChange = false;
|
|
2127
2236
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2128
2237
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2129
2238
|
const mVal = maskData[mIdx];
|
|
@@ -2154,162 +2263,47 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
|
2154
2263
|
}
|
|
2155
2264
|
finalCol = (colorRGB | a << 24) >>> 0;
|
|
2156
2265
|
}
|
|
2157
|
-
|
|
2266
|
+
const current = dst32[dIdx];
|
|
2267
|
+
const next = blendFn(finalCol, current);
|
|
2268
|
+
if (current !== next) {
|
|
2269
|
+
dst32[dIdx] = next;
|
|
2270
|
+
didChange = true;
|
|
2271
|
+
}
|
|
2158
2272
|
dIdx++;
|
|
2159
2273
|
mIdx++;
|
|
2160
2274
|
}
|
|
2161
2275
|
dIdx += dStride;
|
|
2162
2276
|
mIdx += mStride;
|
|
2163
2277
|
}
|
|
2278
|
+
return didChange;
|
|
2164
2279
|
}
|
|
2165
2280
|
|
|
2166
|
-
// src/
|
|
2167
|
-
function
|
|
2168
|
-
const
|
|
2169
|
-
const
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
const
|
|
2173
|
-
const
|
|
2174
|
-
const
|
|
2175
|
-
const
|
|
2176
|
-
const invertMask = opts.invertMask ?? false;
|
|
2177
|
-
if (globalAlpha === 0) return;
|
|
2178
|
-
const baseSrcAlpha = color >>> 24;
|
|
2179
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
2180
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2181
|
-
let x = targetX;
|
|
2182
|
-
let y = targetY;
|
|
2183
|
-
if (x < 0) {
|
|
2184
|
-
w += x;
|
|
2185
|
-
x = 0;
|
|
2186
|
-
}
|
|
2187
|
-
if (y < 0) {
|
|
2188
|
-
h += y;
|
|
2189
|
-
y = 0;
|
|
2190
|
-
}
|
|
2191
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2192
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2193
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
2194
|
-
let baseColorWithGlobalAlpha = color;
|
|
2195
|
-
if (globalAlpha < 255) {
|
|
2196
|
-
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2197
|
-
if (a === 0 && !isOverwrite) return;
|
|
2198
|
-
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2199
|
-
}
|
|
2200
|
-
const dx = x - targetX | 0;
|
|
2201
|
-
const dy = y - targetY | 0;
|
|
2202
|
-
const dst32 = dst.data32;
|
|
2203
|
-
const dw = dst.width;
|
|
2204
|
-
const mPitch = mask.w;
|
|
2205
|
-
const maskData = mask.data;
|
|
2206
|
-
let dIdx = y * dw + x | 0;
|
|
2207
|
-
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2208
|
-
const dStride = dw - actualW | 0;
|
|
2209
|
-
const mStride = mPitch - actualW | 0;
|
|
2210
|
-
const skipVal = invertMask ? 1 : 0;
|
|
2211
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
2212
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2213
|
-
if (maskData[mIdx] === skipVal) {
|
|
2214
|
-
dIdx++;
|
|
2215
|
-
mIdx++;
|
|
2216
|
-
continue;
|
|
2217
|
-
}
|
|
2218
|
-
dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
|
|
2219
|
-
dIdx++;
|
|
2220
|
-
mIdx++;
|
|
2221
|
-
}
|
|
2222
|
-
dIdx += dStride;
|
|
2223
|
-
mIdx += mStride;
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
|
|
2227
|
-
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
2228
|
-
function applyCircleBrushToPixelData(target, color, centerX, centerY, brush, alpha = 255, blendFn = sourceOverPerfect, scratchOptions = {}, bounds) {
|
|
2229
|
-
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brush.size, target.width, target.height);
|
|
2230
|
-
if (b.w <= 0 || b.h <= 0) return;
|
|
2231
|
-
const unclippedStartX = Math.floor(centerX + brush.minOffset);
|
|
2232
|
-
const unclippedStartY = Math.floor(centerY + brush.minOffset);
|
|
2233
|
-
const ix = Math.max(unclippedStartX, b.x);
|
|
2234
|
-
const iy = Math.max(unclippedStartY, b.y);
|
|
2235
|
-
const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
|
|
2236
|
-
const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
|
|
2237
|
-
const iw = ir - ix;
|
|
2238
|
-
const ih = ib - iy;
|
|
2239
|
-
if (iw <= 0 || ih <= 0) return;
|
|
2240
|
-
scratchOptions.x = ix;
|
|
2241
|
-
scratchOptions.y = iy;
|
|
2242
|
-
scratchOptions.w = iw;
|
|
2243
|
-
scratchOptions.h = ih;
|
|
2244
|
-
scratchOptions.mx = ix - unclippedStartX;
|
|
2245
|
-
scratchOptions.my = iy - unclippedStartY;
|
|
2246
|
-
scratchOptions.alpha = alpha;
|
|
2247
|
-
scratchOptions.blendFn = blendFn;
|
|
2248
|
-
if (brush.type === 0 /* ALPHA */) {
|
|
2249
|
-
blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
|
|
2250
|
-
}
|
|
2251
|
-
if (brush.type === 1 /* BINARY */) {
|
|
2252
|
-
blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
|
|
2253
|
-
}
|
|
2254
|
-
}
|
|
2255
|
-
|
|
2256
|
-
// src/History/PixelMutator/mutatorApplyCircleBrush.ts
|
|
2257
|
-
var defaults3 = {
|
|
2258
|
-
applyCircleBrushToPixelData,
|
|
2259
|
-
getCircleBrushOrPencilBounds
|
|
2260
|
-
};
|
|
2261
|
-
var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
|
|
2262
|
-
const {
|
|
2263
|
-
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
|
|
2264
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
|
|
2265
|
-
} = deps;
|
|
2266
|
-
const boundsOut = {
|
|
2267
|
-
x: 0,
|
|
2268
|
-
y: 0,
|
|
2269
|
-
w: 0,
|
|
2270
|
-
h: 0
|
|
2271
|
-
};
|
|
2272
|
-
const blendColorPixelOptions = {
|
|
2273
|
-
alpha: 255,
|
|
2274
|
-
blendFn: sourceOverPerfect,
|
|
2281
|
+
// src/Rect/getCircleBrushOrPencilBounds.ts
|
|
2282
|
+
function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight, out) {
|
|
2283
|
+
const r = brushSize / 2;
|
|
2284
|
+
const minOffset = -Math.ceil(r - 0.5);
|
|
2285
|
+
const maxOffset = Math.floor(r - 0.5);
|
|
2286
|
+
const startX = Math.floor(centerX + minOffset);
|
|
2287
|
+
const startY = Math.floor(centerY + minOffset);
|
|
2288
|
+
const endX = Math.floor(centerX + maxOffset) + 1;
|
|
2289
|
+
const endY = Math.floor(centerY + maxOffset) + 1;
|
|
2290
|
+
const res = out ?? {
|
|
2275
2291
|
x: 0,
|
|
2276
2292
|
y: 0,
|
|
2277
2293
|
w: 0,
|
|
2278
2294
|
h: 0
|
|
2279
2295
|
};
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
}
|
|
2292
|
-
};
|
|
2293
|
-
});
|
|
2294
|
-
|
|
2295
|
-
// src/Algorithm/forEachLinePoint.ts
|
|
2296
|
-
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
2297
|
-
const dx = x1 - x0;
|
|
2298
|
-
const dy = y1 - y0;
|
|
2299
|
-
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
2300
|
-
if (steps === 0) {
|
|
2301
|
-
callback(x0, y0);
|
|
2302
|
-
return;
|
|
2303
|
-
}
|
|
2304
|
-
const xInc = dx / steps;
|
|
2305
|
-
const yInc = dy / steps;
|
|
2306
|
-
let curX = x0;
|
|
2307
|
-
let curY = y0;
|
|
2308
|
-
for (let i = 0; i <= steps; i++) {
|
|
2309
|
-
callback(curX, curY);
|
|
2310
|
-
curX += xInc;
|
|
2311
|
-
curY += yInc;
|
|
2312
|
-
}
|
|
2296
|
+
const cStartX = Math.max(0, startX);
|
|
2297
|
+
const cStartY = Math.max(0, startY);
|
|
2298
|
+
const cEndX = Math.min(targetWidth, endX);
|
|
2299
|
+
const cEndY = Math.min(targetHeight, endY);
|
|
2300
|
+
const w = cEndX - cStartX;
|
|
2301
|
+
const h = cEndY - cStartY;
|
|
2302
|
+
res.x = cStartX;
|
|
2303
|
+
res.y = cStartY;
|
|
2304
|
+
res.w = w < 0 ? 0 : w;
|
|
2305
|
+
res.h = h < 0 ? 0 : h;
|
|
2306
|
+
return res;
|
|
2313
2307
|
}
|
|
2314
2308
|
|
|
2315
2309
|
// src/Rect/getCircleBrushOrPencilStrokeBounds.ts
|
|
@@ -2382,8 +2376,9 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2382
2376
|
const maskData = mask.data;
|
|
2383
2377
|
const brushData = brush.data;
|
|
2384
2378
|
const minOffset = brush.minOffset;
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2379
|
+
const target = writer.config.target;
|
|
2380
|
+
const targetWidth = target.width;
|
|
2381
|
+
const targetHeight = target.height;
|
|
2387
2382
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2388
2383
|
const {
|
|
2389
2384
|
x: cbx,
|
|
@@ -2421,19 +2416,117 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2421
2416
|
blendColorPixelOptions.y = by;
|
|
2422
2417
|
blendColorPixelOptions.w = bw;
|
|
2423
2418
|
blendColorPixelOptions.h = bh;
|
|
2424
|
-
blendColorPixelDataAlphaMask2(
|
|
2419
|
+
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2425
2420
|
}
|
|
2426
2421
|
};
|
|
2427
2422
|
});
|
|
2428
2423
|
|
|
2429
|
-
// src/
|
|
2424
|
+
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
2425
|
+
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
2426
|
+
const targetX = opts.x ?? 0;
|
|
2427
|
+
const targetY = opts.y ?? 0;
|
|
2428
|
+
let w = opts.w ?? mask.w;
|
|
2429
|
+
let h = opts.h ?? mask.h;
|
|
2430
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
2431
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
2432
|
+
const mx = opts.mx ?? 0;
|
|
2433
|
+
const my = opts.my ?? 0;
|
|
2434
|
+
const invertMask = opts.invertMask ?? false;
|
|
2435
|
+
if (globalAlpha === 0) return false;
|
|
2436
|
+
const baseSrcAlpha = color >>> 24;
|
|
2437
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2438
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
2439
|
+
let x = targetX;
|
|
2440
|
+
let y = targetY;
|
|
2441
|
+
if (x < 0) {
|
|
2442
|
+
w += x;
|
|
2443
|
+
x = 0;
|
|
2444
|
+
}
|
|
2445
|
+
if (y < 0) {
|
|
2446
|
+
h += y;
|
|
2447
|
+
y = 0;
|
|
2448
|
+
}
|
|
2449
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2450
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2451
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2452
|
+
let baseColorWithGlobalAlpha = color;
|
|
2453
|
+
if (globalAlpha < 255) {
|
|
2454
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2455
|
+
if (a === 0 && !isOverwrite) return false;
|
|
2456
|
+
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2457
|
+
}
|
|
2458
|
+
const dx = x - targetX | 0;
|
|
2459
|
+
const dy = y - targetY | 0;
|
|
2460
|
+
const dst32 = dst.data32;
|
|
2461
|
+
const dw = dst.width;
|
|
2462
|
+
const mPitch = mask.w;
|
|
2463
|
+
const maskData = mask.data;
|
|
2464
|
+
let dIdx = y * dw + x | 0;
|
|
2465
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2466
|
+
const dStride = dw - actualW | 0;
|
|
2467
|
+
const mStride = mPitch - actualW | 0;
|
|
2468
|
+
const skipVal = invertMask ? 1 : 0;
|
|
2469
|
+
let didChange = false;
|
|
2470
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2471
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2472
|
+
if (maskData[mIdx] === skipVal) {
|
|
2473
|
+
dIdx++;
|
|
2474
|
+
mIdx++;
|
|
2475
|
+
continue;
|
|
2476
|
+
}
|
|
2477
|
+
const current = dst32[dIdx];
|
|
2478
|
+
const next = blendFn(baseColorWithGlobalAlpha, current);
|
|
2479
|
+
if (current !== next) {
|
|
2480
|
+
dst32[dIdx] = next;
|
|
2481
|
+
didChange = true;
|
|
2482
|
+
}
|
|
2483
|
+
dIdx++;
|
|
2484
|
+
mIdx++;
|
|
2485
|
+
}
|
|
2486
|
+
dIdx += dStride;
|
|
2487
|
+
mIdx += mStride;
|
|
2488
|
+
}
|
|
2489
|
+
return didChange;
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
// src/PixelData/blendColorPixelDataCircleMask.ts
|
|
2493
|
+
function blendColorPixelDataCircleMask(target, color, centerX, centerY, brush, alpha = 255, blendFn = sourceOverPerfect, scratchOptions = {}, bounds) {
|
|
2494
|
+
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brush.size, target.width, target.height);
|
|
2495
|
+
if (b.w <= 0 || b.h <= 0) return false;
|
|
2496
|
+
const unclippedStartX = Math.floor(centerX + brush.minOffset);
|
|
2497
|
+
const unclippedStartY = Math.floor(centerY + brush.minOffset);
|
|
2498
|
+
const ix = Math.max(unclippedStartX, b.x);
|
|
2499
|
+
const iy = Math.max(unclippedStartY, b.y);
|
|
2500
|
+
const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
|
|
2501
|
+
const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
|
|
2502
|
+
const iw = ir - ix;
|
|
2503
|
+
const ih = ib - iy;
|
|
2504
|
+
if (iw <= 0 || ih <= 0) return false;
|
|
2505
|
+
scratchOptions.x = ix;
|
|
2506
|
+
scratchOptions.y = iy;
|
|
2507
|
+
scratchOptions.w = iw;
|
|
2508
|
+
scratchOptions.h = ih;
|
|
2509
|
+
scratchOptions.mx = ix - unclippedStartX;
|
|
2510
|
+
scratchOptions.my = iy - unclippedStartY;
|
|
2511
|
+
scratchOptions.alpha = alpha;
|
|
2512
|
+
scratchOptions.blendFn = blendFn;
|
|
2513
|
+
if (brush.type === 0 /* ALPHA */) {
|
|
2514
|
+
return blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
|
|
2515
|
+
}
|
|
2516
|
+
if (brush.type === 1 /* BINARY */) {
|
|
2517
|
+
return blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
|
|
2518
|
+
}
|
|
2519
|
+
return false;
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
// src/History/PixelMutator/mutatorBlendColorCircleMask.ts
|
|
2430
2523
|
var defaults5 = {
|
|
2431
|
-
|
|
2524
|
+
blendColorPixelDataCircleMask,
|
|
2432
2525
|
getCircleBrushOrPencilBounds
|
|
2433
2526
|
};
|
|
2434
|
-
var
|
|
2527
|
+
var mutatorBlendColorCircleMask = ((writer, deps = defaults5) => {
|
|
2435
2528
|
const {
|
|
2436
|
-
|
|
2529
|
+
blendColorPixelDataCircleMask: blendColorPixelDataCircleMask2 = defaults5.blendColorPixelDataCircleMask,
|
|
2437
2530
|
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults5.getCircleBrushOrPencilBounds
|
|
2438
2531
|
} = deps;
|
|
2439
2532
|
const boundsOut = {
|
|
@@ -2442,34 +2535,63 @@ var mutatorApplyCirclePencil = ((writer, deps = defaults5) => {
|
|
|
2442
2535
|
w: 0,
|
|
2443
2536
|
h: 0
|
|
2444
2537
|
};
|
|
2538
|
+
const blendColorPixelOptions = {
|
|
2539
|
+
alpha: 255,
|
|
2540
|
+
blendFn: sourceOverPerfect,
|
|
2541
|
+
x: 0,
|
|
2542
|
+
y: 0,
|
|
2543
|
+
w: 0,
|
|
2544
|
+
h: 0
|
|
2545
|
+
};
|
|
2546
|
+
return {
|
|
2547
|
+
applyCircleMask(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
2548
|
+
const target = writer.config.target;
|
|
2549
|
+
const b = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, target.width, target.height, boundsOut);
|
|
2550
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2551
|
+
return didChange(blendColorPixelDataCircleMask2(target, color, centerX, centerY, brush, alpha, blendFn, blendColorPixelOptions, b));
|
|
2552
|
+
}
|
|
2553
|
+
};
|
|
2554
|
+
});
|
|
2555
|
+
|
|
2556
|
+
// src/History/PixelMutator/mutatorApplyCirclePencil.ts
|
|
2557
|
+
var defaults6 = {
|
|
2558
|
+
applyCircleMaskToPixelData: blendColorPixelDataCircleMask,
|
|
2559
|
+
getCircleBrushOrPencilBounds
|
|
2560
|
+
};
|
|
2561
|
+
var mutatorApplyCirclePencil = ((writer, deps = defaults6) => {
|
|
2562
|
+
const {
|
|
2563
|
+
applyCircleMaskToPixelData = defaults6.applyCircleMaskToPixelData,
|
|
2564
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults6.getCircleBrushOrPencilBounds
|
|
2565
|
+
} = deps;
|
|
2566
|
+
const boundsOut = {
|
|
2567
|
+
x: 0,
|
|
2568
|
+
y: 0,
|
|
2569
|
+
w: 0,
|
|
2570
|
+
h: 0
|
|
2571
|
+
};
|
|
2445
2572
|
return {
|
|
2446
2573
|
applyCirclePencil(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
2447
|
-
const
|
|
2448
|
-
const
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
w,
|
|
2452
|
-
h
|
|
2453
|
-
} = bounds;
|
|
2454
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2455
|
-
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brush, alpha, blendFn, bounds);
|
|
2574
|
+
const target = writer.config.target;
|
|
2575
|
+
const b = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, target.width, target.height, boundsOut);
|
|
2576
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2577
|
+
return didChange(applyCircleMaskToPixelData(target, color, centerX, centerY, brush, alpha, blendFn, b));
|
|
2456
2578
|
}
|
|
2457
2579
|
};
|
|
2458
2580
|
});
|
|
2459
2581
|
|
|
2460
2582
|
// src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
|
|
2461
|
-
var
|
|
2583
|
+
var defaults7 = {
|
|
2462
2584
|
forEachLinePoint,
|
|
2463
2585
|
blendColorPixelDataBinaryMask,
|
|
2464
2586
|
getCircleBrushOrPencilBounds,
|
|
2465
2587
|
getCircleBrushOrPencilStrokeBounds
|
|
2466
2588
|
};
|
|
2467
|
-
var mutatorApplyCirclePencilStroke = ((writer, deps =
|
|
2589
|
+
var mutatorApplyCirclePencilStroke = ((writer, deps = defaults7) => {
|
|
2468
2590
|
const {
|
|
2469
|
-
forEachLinePoint: forEachLinePoint2 =
|
|
2470
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 =
|
|
2471
|
-
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 =
|
|
2472
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 =
|
|
2591
|
+
forEachLinePoint: forEachLinePoint2 = defaults7.forEachLinePoint,
|
|
2592
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults7.blendColorPixelDataBinaryMask,
|
|
2593
|
+
getCircleBrushOrPencilStrokeBounds: getCircleBrushOrPencilStrokeBounds2 = defaults7.getCircleBrushOrPencilStrokeBounds,
|
|
2594
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults7.getCircleBrushOrPencilBounds
|
|
2473
2595
|
} = deps;
|
|
2474
2596
|
const strokeBoundsOut = {
|
|
2475
2597
|
x: 0,
|
|
@@ -2510,8 +2632,9 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults6) => {
|
|
|
2510
2632
|
mask.w = bw;
|
|
2511
2633
|
mask.h = bh;
|
|
2512
2634
|
const maskData = mask.data;
|
|
2513
|
-
const
|
|
2514
|
-
const
|
|
2635
|
+
const target = writer.config.target;
|
|
2636
|
+
const targetWidth = target.width;
|
|
2637
|
+
const targetHeight = target.height;
|
|
2515
2638
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2516
2639
|
const {
|
|
2517
2640
|
x: cbx,
|
|
@@ -2546,7 +2669,7 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults6) => {
|
|
|
2546
2669
|
blendColorPixelOptions.y = by;
|
|
2547
2670
|
blendColorPixelOptions.w = bw;
|
|
2548
2671
|
blendColorPixelOptions.h = bh;
|
|
2549
|
-
blendColorPixelDataBinaryMask2(
|
|
2672
|
+
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
2550
2673
|
}
|
|
2551
2674
|
};
|
|
2552
2675
|
});
|
|
@@ -2581,7 +2704,9 @@ function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth,
|
|
|
2581
2704
|
const targetWidth = target.width;
|
|
2582
2705
|
const targetHeight = target.height;
|
|
2583
2706
|
const b = bounds ?? getRectBrushOrPencilBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight);
|
|
2584
|
-
if (b.w <= 0 || b.h <= 0)
|
|
2707
|
+
if (b.w <= 0 || b.h <= 0) {
|
|
2708
|
+
return false;
|
|
2709
|
+
}
|
|
2585
2710
|
const data32 = target.data32;
|
|
2586
2711
|
const baseColor = color & 16777215;
|
|
2587
2712
|
const baseSrcAlpha = color >>> 24;
|
|
@@ -2595,6 +2720,7 @@ function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth,
|
|
|
2595
2720
|
const endX = b.x + b.w;
|
|
2596
2721
|
const endY = b.y + b.h;
|
|
2597
2722
|
const isOverwrite = blendFn.isOverwrite;
|
|
2723
|
+
let didChange = false;
|
|
2598
2724
|
for (let py = b.y; py < endY; py++) {
|
|
2599
2725
|
const rowOffset = py * targetWidth;
|
|
2600
2726
|
const dy = Math.abs(py - fCenterY + centerOffsetY) * invHalfH;
|
|
@@ -2617,20 +2743,26 @@ function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth,
|
|
|
2617
2743
|
if (a === 0 && !isOverwrite) continue;
|
|
2618
2744
|
finalCol = (a << 24 | baseColor) >>> 0;
|
|
2619
2745
|
}
|
|
2620
|
-
|
|
2746
|
+
const current = data32[idx];
|
|
2747
|
+
const next = blendFn(finalCol, current);
|
|
2748
|
+
if (current !== next) {
|
|
2749
|
+
data32[idx] = next;
|
|
2750
|
+
didChange = true;
|
|
2751
|
+
}
|
|
2621
2752
|
}
|
|
2622
2753
|
}
|
|
2754
|
+
return didChange;
|
|
2623
2755
|
}
|
|
2624
2756
|
|
|
2625
2757
|
// src/History/PixelMutator/mutatorApplyRectBrush.ts
|
|
2626
|
-
var
|
|
2758
|
+
var defaults8 = {
|
|
2627
2759
|
applyRectBrushToPixelData,
|
|
2628
2760
|
getRectBrushOrPencilBounds
|
|
2629
2761
|
};
|
|
2630
|
-
var mutatorApplyRectBrush = ((writer, deps =
|
|
2762
|
+
var mutatorApplyRectBrush = ((writer, deps = defaults8) => {
|
|
2631
2763
|
const {
|
|
2632
|
-
applyRectBrushToPixelData: applyRectBrushToPixelData2 =
|
|
2633
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
2764
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults8.applyRectBrushToPixelData,
|
|
2765
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults8.getRectBrushOrPencilBounds
|
|
2634
2766
|
} = deps;
|
|
2635
2767
|
const boundsOut = {
|
|
2636
2768
|
x: 0,
|
|
@@ -2640,15 +2772,10 @@ var mutatorApplyRectBrush = ((writer, deps = defaults7) => {
|
|
|
2640
2772
|
};
|
|
2641
2773
|
return {
|
|
2642
2774
|
applyRectBrush(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn) {
|
|
2643
|
-
const
|
|
2644
|
-
const
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
w,
|
|
2648
|
-
h
|
|
2649
|
-
} = bounds;
|
|
2650
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2651
|
-
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2775
|
+
const target = writer.config.target;
|
|
2776
|
+
const b = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, target.width, target.height, boundsOut);
|
|
2777
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2778
|
+
return didChange(applyRectBrushToPixelData2(target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, b));
|
|
2652
2779
|
}
|
|
2653
2780
|
};
|
|
2654
2781
|
});
|
|
@@ -2669,18 +2796,18 @@ function getRectBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushWidth, brushHeigh
|
|
|
2669
2796
|
}
|
|
2670
2797
|
|
|
2671
2798
|
// src/History/PixelMutator/mutatorApplyRectBrushStroke.ts
|
|
2672
|
-
var
|
|
2799
|
+
var defaults9 = {
|
|
2673
2800
|
forEachLinePoint,
|
|
2674
2801
|
blendColorPixelDataAlphaMask,
|
|
2675
2802
|
getRectBrushOrPencilBounds,
|
|
2676
2803
|
getRectBrushOrPencilStrokeBounds
|
|
2677
2804
|
};
|
|
2678
|
-
var mutatorApplyRectBrushStroke = ((writer, deps =
|
|
2805
|
+
var mutatorApplyRectBrushStroke = ((writer, deps = defaults9) => {
|
|
2679
2806
|
const {
|
|
2680
|
-
forEachLinePoint: forEachLinePoint2 =
|
|
2681
|
-
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 =
|
|
2682
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
2683
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 =
|
|
2807
|
+
forEachLinePoint: forEachLinePoint2 = defaults9.forEachLinePoint,
|
|
2808
|
+
blendColorPixelDataAlphaMask: blendColorPixelDataAlphaMask2 = defaults9.blendColorPixelDataAlphaMask,
|
|
2809
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults9.getRectBrushOrPencilBounds,
|
|
2810
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults9.getRectBrushOrPencilStrokeBounds
|
|
2684
2811
|
} = deps;
|
|
2685
2812
|
const strokeBoundsOut = {
|
|
2686
2813
|
x: 0,
|
|
@@ -2727,8 +2854,9 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults8) => {
|
|
|
2727
2854
|
const invHalfH = 1 / halfH;
|
|
2728
2855
|
const centerOffsetX = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2729
2856
|
const centerOffsetY = brushHeight % 2 === 0 ? 0.5 : 0;
|
|
2730
|
-
const
|
|
2731
|
-
const
|
|
2857
|
+
const target = writer.config.target;
|
|
2858
|
+
const targetWidth = target.width;
|
|
2859
|
+
const targetHeight = target.height;
|
|
2732
2860
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2733
2861
|
const {
|
|
2734
2862
|
x: rbx,
|
|
@@ -2766,22 +2894,22 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults8) => {
|
|
|
2766
2894
|
blendColorPixelOptions.y = by;
|
|
2767
2895
|
blendColorPixelOptions.w = bw;
|
|
2768
2896
|
blendColorPixelOptions.h = bh;
|
|
2769
|
-
blendColorPixelDataAlphaMask2(
|
|
2897
|
+
blendColorPixelDataAlphaMask2(target, color, mask, blendColorPixelOptions);
|
|
2770
2898
|
}
|
|
2771
2899
|
};
|
|
2772
2900
|
});
|
|
2773
2901
|
|
|
2774
2902
|
// src/History/PixelMutator/mutatorApplyRectPencil.ts
|
|
2775
|
-
var
|
|
2903
|
+
var defaults10 = {
|
|
2776
2904
|
applyRectBrushToPixelData,
|
|
2777
2905
|
getRectBrushOrPencilBounds,
|
|
2778
2906
|
fallOff: () => 1
|
|
2779
2907
|
};
|
|
2780
|
-
var mutatorApplyRectPencil = ((writer, deps =
|
|
2908
|
+
var mutatorApplyRectPencil = ((writer, deps = defaults10) => {
|
|
2781
2909
|
const {
|
|
2782
|
-
applyRectBrushToPixelData: applyRectBrushToPixelData2 =
|
|
2783
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
2784
|
-
fallOff =
|
|
2910
|
+
applyRectBrushToPixelData: applyRectBrushToPixelData2 = defaults10.applyRectBrushToPixelData,
|
|
2911
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults10.getRectBrushOrPencilBounds,
|
|
2912
|
+
fallOff = defaults10.fallOff
|
|
2785
2913
|
} = deps;
|
|
2786
2914
|
const boundsOut = {
|
|
2787
2915
|
x: 0,
|
|
@@ -2791,32 +2919,27 @@ var mutatorApplyRectPencil = ((writer, deps = defaults9) => {
|
|
|
2791
2919
|
};
|
|
2792
2920
|
return {
|
|
2793
2921
|
applyRectPencil(color, centerX, centerY, brushWidth, brushHeight, alpha = 255, blendFn) {
|
|
2794
|
-
const
|
|
2795
|
-
const
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
w,
|
|
2799
|
-
h
|
|
2800
|
-
} = bounds;
|
|
2801
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2802
|
-
applyRectBrushToPixelData2(writer.target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, bounds);
|
|
2922
|
+
const target = writer.config.target;
|
|
2923
|
+
const b = getRectBrushOrPencilBounds2(centerX, centerY, brushWidth, brushHeight, target.width, target.height, boundsOut);
|
|
2924
|
+
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h);
|
|
2925
|
+
return didChange(applyRectBrushToPixelData2(target, color, centerX, centerY, brushWidth, brushHeight, alpha, fallOff, blendFn, b));
|
|
2803
2926
|
}
|
|
2804
2927
|
};
|
|
2805
2928
|
});
|
|
2806
2929
|
|
|
2807
2930
|
// src/History/PixelMutator/mutatorApplyRectPencilStroke.ts
|
|
2808
|
-
var
|
|
2931
|
+
var defaults11 = {
|
|
2809
2932
|
forEachLinePoint,
|
|
2810
2933
|
getRectBrushOrPencilBounds,
|
|
2811
2934
|
getRectBrushOrPencilStrokeBounds,
|
|
2812
2935
|
blendColorPixelDataBinaryMask
|
|
2813
2936
|
};
|
|
2814
|
-
var mutatorApplyRectPencilStroke = ((writer, deps =
|
|
2937
|
+
var mutatorApplyRectPencilStroke = ((writer, deps = defaults11) => {
|
|
2815
2938
|
const {
|
|
2816
|
-
forEachLinePoint: forEachLinePoint2 =
|
|
2817
|
-
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 =
|
|
2818
|
-
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 =
|
|
2819
|
-
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 =
|
|
2939
|
+
forEachLinePoint: forEachLinePoint2 = defaults11.forEachLinePoint,
|
|
2940
|
+
blendColorPixelDataBinaryMask: blendColorPixelDataBinaryMask2 = defaults11.blendColorPixelDataBinaryMask,
|
|
2941
|
+
getRectBrushOrPencilBounds: getRectBrushOrPencilBounds2 = defaults11.getRectBrushOrPencilBounds,
|
|
2942
|
+
getRectBrushOrPencilStrokeBounds: getRectBrushOrPencilStrokeBounds2 = defaults11.getRectBrushOrPencilStrokeBounds
|
|
2820
2943
|
} = deps;
|
|
2821
2944
|
const strokeBoundsOut = {
|
|
2822
2945
|
x: 0,
|
|
@@ -2860,8 +2983,9 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults10) => {
|
|
|
2860
2983
|
const halfW = brushWidth / 2;
|
|
2861
2984
|
const halfH = brushHeight / 2;
|
|
2862
2985
|
const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
2863
|
-
const
|
|
2864
|
-
const
|
|
2986
|
+
const target = writer.config.target;
|
|
2987
|
+
const targetWidth = target.width;
|
|
2988
|
+
const targetHeight = target.height;
|
|
2865
2989
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
2866
2990
|
const {
|
|
2867
2991
|
x: rbx,
|
|
@@ -2894,7 +3018,7 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults10) => {
|
|
|
2894
3018
|
blendColorPixelOptions.y = by;
|
|
2895
3019
|
blendColorPixelOptions.w = bw;
|
|
2896
3020
|
blendColorPixelOptions.h = bh;
|
|
2897
|
-
blendColorPixelDataBinaryMask2(
|
|
3021
|
+
blendColorPixelDataBinaryMask2(target, color, mask, blendColorPixelOptions);
|
|
2898
3022
|
}
|
|
2899
3023
|
};
|
|
2900
3024
|
});
|
|
@@ -2909,11 +3033,14 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2909
3033
|
alpha: globalAlpha = 255,
|
|
2910
3034
|
blendFn = sourceOverPerfect
|
|
2911
3035
|
} = opts;
|
|
2912
|
-
if (globalAlpha === 0) return;
|
|
3036
|
+
if (globalAlpha === 0) return false;
|
|
2913
3037
|
const baseSrcAlpha = color >>> 24;
|
|
2914
3038
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
2915
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2916
|
-
let x = targetX
|
|
3039
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return false;
|
|
3040
|
+
let x = targetX;
|
|
3041
|
+
let y = targetY;
|
|
3042
|
+
let w = width;
|
|
3043
|
+
let h = height;
|
|
2917
3044
|
if (x < 0) {
|
|
2918
3045
|
w += x;
|
|
2919
3046
|
x = 0;
|
|
@@ -2924,69 +3051,97 @@ function blendColorPixelData(dst, color, opts = {}) {
|
|
|
2924
3051
|
}
|
|
2925
3052
|
const actualW = Math.min(w, dst.width - x);
|
|
2926
3053
|
const actualH = Math.min(h, dst.height - y);
|
|
2927
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3054
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
2928
3055
|
let finalSrcColor = color;
|
|
2929
3056
|
if (globalAlpha < 255) {
|
|
2930
3057
|
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2931
|
-
if (a === 0 && !isOverwrite) return;
|
|
3058
|
+
if (a === 0 && !isOverwrite) return false;
|
|
2932
3059
|
finalSrcColor = (color & 16777215 | a << 24) >>> 0;
|
|
2933
3060
|
}
|
|
2934
3061
|
const dst32 = dst.data32;
|
|
2935
3062
|
const dw = dst.width;
|
|
2936
3063
|
let dIdx = y * dw + x | 0;
|
|
2937
3064
|
const dStride = dw - actualW | 0;
|
|
3065
|
+
let didChange = false;
|
|
2938
3066
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2939
3067
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2940
|
-
|
|
3068
|
+
const current = dst32[dIdx];
|
|
3069
|
+
const next = blendFn(finalSrcColor, current);
|
|
3070
|
+
if (current !== next) {
|
|
3071
|
+
dst32[dIdx] = next;
|
|
3072
|
+
didChange = true;
|
|
3073
|
+
}
|
|
2941
3074
|
dIdx++;
|
|
2942
3075
|
}
|
|
2943
3076
|
dIdx += dStride;
|
|
2944
3077
|
}
|
|
3078
|
+
return didChange;
|
|
2945
3079
|
}
|
|
2946
3080
|
|
|
2947
3081
|
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2948
|
-
var
|
|
3082
|
+
var defaults12 = {
|
|
2949
3083
|
blendColorPixelData
|
|
2950
3084
|
};
|
|
2951
|
-
var mutatorBlendColor = ((writer, deps =
|
|
3085
|
+
var mutatorBlendColor = ((writer, deps = defaults12) => {
|
|
2952
3086
|
const {
|
|
2953
|
-
blendColorPixelData: blendColorPixelData2 =
|
|
3087
|
+
blendColorPixelData: blendColorPixelData2 = defaults12.blendColorPixelData
|
|
2954
3088
|
} = deps;
|
|
2955
3089
|
return {
|
|
2956
3090
|
blendColor(color, opts = {}) {
|
|
3091
|
+
const target = writer.config.target;
|
|
2957
3092
|
const {
|
|
2958
3093
|
x = 0,
|
|
2959
3094
|
y = 0,
|
|
2960
|
-
w =
|
|
2961
|
-
h =
|
|
3095
|
+
w = target.width,
|
|
3096
|
+
h = target.height
|
|
2962
3097
|
} = opts;
|
|
2963
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2964
|
-
blendColorPixelData2(
|
|
3098
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3099
|
+
return didChange(blendColorPixelData2(target, color, opts));
|
|
2965
3100
|
}
|
|
2966
3101
|
};
|
|
2967
3102
|
});
|
|
2968
3103
|
|
|
3104
|
+
// src/PixelData/blendPixel.ts
|
|
3105
|
+
function blendPixel(target, x, y, color, alpha = 255, blendFn = sourceOverPerfect) {
|
|
3106
|
+
if (alpha === 0) return false;
|
|
3107
|
+
let width = target.width;
|
|
3108
|
+
let height = target.height;
|
|
3109
|
+
if (x < 0 || x >= width || y < 0 || y >= height) return false;
|
|
3110
|
+
let srcAlpha = color >>> 24;
|
|
3111
|
+
let isOverwrite = blendFn.isOverwrite;
|
|
3112
|
+
if (srcAlpha === 0 && !isOverwrite) return false;
|
|
3113
|
+
let dst32 = target.data32;
|
|
3114
|
+
let index = y * width + x;
|
|
3115
|
+
let finalColor = color;
|
|
3116
|
+
if (alpha !== 255) {
|
|
3117
|
+
let finalAlpha = srcAlpha * alpha + 128 >> 8;
|
|
3118
|
+
if (finalAlpha === 0 && !isOverwrite) return false;
|
|
3119
|
+
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
3120
|
+
}
|
|
3121
|
+
let current = dst32[index];
|
|
3122
|
+
let next = blendFn(finalColor, current);
|
|
3123
|
+
if (current !== next) {
|
|
3124
|
+
dst32[index] = next;
|
|
3125
|
+
return true;
|
|
3126
|
+
}
|
|
3127
|
+
return false;
|
|
3128
|
+
}
|
|
3129
|
+
|
|
2969
3130
|
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2970
|
-
|
|
3131
|
+
var defaults13 = {
|
|
3132
|
+
blendPixel
|
|
3133
|
+
};
|
|
3134
|
+
var mutatorBlendPixel = ((writer, deps = defaults13) => {
|
|
3135
|
+
const {
|
|
3136
|
+
blendPixel: blendPixel2 = defaults13.blendPixel
|
|
3137
|
+
} = deps;
|
|
2971
3138
|
return {
|
|
2972
|
-
blendPixel(x, y, color, alpha
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
let height = target.height;
|
|
2976
|
-
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
2977
|
-
writer.accumulator.storeTileBeforeState(x, y);
|
|
2978
|
-
let index = y * width + x;
|
|
2979
|
-
let bg = target.data32[index];
|
|
2980
|
-
let finalColor = color;
|
|
2981
|
-
if (alpha < 255) {
|
|
2982
|
-
let baseSrcAlpha = color >>> 24;
|
|
2983
|
-
let finalAlpha = baseSrcAlpha * alpha + 128 >> 8;
|
|
2984
|
-
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
2985
|
-
}
|
|
2986
|
-
target.data32[index] = blendFn(finalColor, bg);
|
|
3139
|
+
blendPixel(x, y, color, alpha, blendFn) {
|
|
3140
|
+
const didChange = writer.accumulator.storePixelBeforeState(x, y);
|
|
3141
|
+
return didChange(blendPixel2(writer.config.target, x, y, color, alpha, blendFn));
|
|
2987
3142
|
}
|
|
2988
3143
|
};
|
|
2989
|
-
}
|
|
3144
|
+
});
|
|
2990
3145
|
|
|
2991
3146
|
// src/PixelData/blendPixelData.ts
|
|
2992
3147
|
function blendPixelData(dst, src, opts = {}) {
|
|
@@ -3000,7 +3155,7 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3000
3155
|
alpha: globalAlpha = 255,
|
|
3001
3156
|
blendFn = sourceOverPerfect
|
|
3002
3157
|
} = opts;
|
|
3003
|
-
if (globalAlpha === 0) return;
|
|
3158
|
+
if (globalAlpha === 0) return false;
|
|
3004
3159
|
let x = targetX;
|
|
3005
3160
|
let y = targetY;
|
|
3006
3161
|
let sx = sourceX;
|
|
@@ -3031,7 +3186,7 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3031
3186
|
}
|
|
3032
3187
|
const actualW = Math.min(w, dst.width - x);
|
|
3033
3188
|
const actualH = Math.min(h, dst.height - y);
|
|
3034
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3189
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3035
3190
|
const dst32 = dst.data32;
|
|
3036
3191
|
const src32 = src.data32;
|
|
3037
3192
|
const dw = dst.width;
|
|
@@ -3042,6 +3197,7 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3042
3197
|
const sStride = sw - actualW | 0;
|
|
3043
3198
|
const isOpaque = globalAlpha === 255;
|
|
3044
3199
|
const isOverwrite = blendFn.isOverwrite;
|
|
3200
|
+
let didChange = false;
|
|
3045
3201
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3046
3202
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3047
3203
|
const srcCol = src32[sIdx];
|
|
@@ -3061,22 +3217,28 @@ function blendPixelData(dst, src, opts = {}) {
|
|
|
3061
3217
|
}
|
|
3062
3218
|
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3063
3219
|
}
|
|
3064
|
-
|
|
3220
|
+
const current = dst32[dIdx];
|
|
3221
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3222
|
+
if (current !== next) {
|
|
3223
|
+
dst32[dIdx] = next;
|
|
3224
|
+
didChange = true;
|
|
3225
|
+
}
|
|
3065
3226
|
dIdx++;
|
|
3066
3227
|
sIdx++;
|
|
3067
3228
|
}
|
|
3068
3229
|
dIdx += dStride;
|
|
3069
3230
|
sIdx += sStride;
|
|
3070
3231
|
}
|
|
3232
|
+
return didChange;
|
|
3071
3233
|
}
|
|
3072
3234
|
|
|
3073
3235
|
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
3074
|
-
var
|
|
3236
|
+
var defaults14 = {
|
|
3075
3237
|
blendPixelData
|
|
3076
3238
|
};
|
|
3077
|
-
var mutatorBlendPixelData = ((writer, deps =
|
|
3239
|
+
var mutatorBlendPixelData = ((writer, deps = defaults14) => {
|
|
3078
3240
|
const {
|
|
3079
|
-
blendPixelData: blendPixelData2 =
|
|
3241
|
+
blendPixelData: blendPixelData2 = defaults14.blendPixelData
|
|
3080
3242
|
} = deps;
|
|
3081
3243
|
return {
|
|
3082
3244
|
blendPixelData(src, opts = {}) {
|
|
@@ -3086,8 +3248,8 @@ var mutatorBlendPixelData = ((writer, deps = defaults12) => {
|
|
|
3086
3248
|
w = src.width,
|
|
3087
3249
|
h = src.height
|
|
3088
3250
|
} = opts;
|
|
3089
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3090
|
-
blendPixelData2(writer.target, src, opts);
|
|
3251
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3252
|
+
return didChange(blendPixelData2(writer.config.target, src, opts));
|
|
3091
3253
|
}
|
|
3092
3254
|
};
|
|
3093
3255
|
});
|
|
@@ -3107,7 +3269,7 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3107
3269
|
my = 0,
|
|
3108
3270
|
invertMask = false
|
|
3109
3271
|
} = opts;
|
|
3110
|
-
if (globalAlpha === 0) return;
|
|
3272
|
+
if (globalAlpha === 0) return false;
|
|
3111
3273
|
let x = targetX;
|
|
3112
3274
|
let y = targetY;
|
|
3113
3275
|
let sx = sourceX;
|
|
@@ -3138,7 +3300,7 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3138
3300
|
}
|
|
3139
3301
|
const actualW = Math.min(w, dst.width - x);
|
|
3140
3302
|
const actualH = Math.min(h, dst.height - y);
|
|
3141
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3303
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3142
3304
|
const dw = dst.width;
|
|
3143
3305
|
const sw = src.width;
|
|
3144
3306
|
const mPitch = alphaMask.w;
|
|
@@ -3155,6 +3317,7 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3155
3317
|
const mStride = mPitch - actualW | 0;
|
|
3156
3318
|
const isOpaque = globalAlpha === 255;
|
|
3157
3319
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
3320
|
+
let didChange = false;
|
|
3158
3321
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3159
3322
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3160
3323
|
const mVal = maskData[mIdx];
|
|
@@ -3196,7 +3359,12 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3196
3359
|
}
|
|
3197
3360
|
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3198
3361
|
}
|
|
3199
|
-
|
|
3362
|
+
const current = dst32[dIdx];
|
|
3363
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3364
|
+
if (current !== next) {
|
|
3365
|
+
dst32[dIdx] = next;
|
|
3366
|
+
didChange = true;
|
|
3367
|
+
}
|
|
3200
3368
|
dIdx++;
|
|
3201
3369
|
sIdx++;
|
|
3202
3370
|
mIdx++;
|
|
@@ -3205,15 +3373,16 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
3205
3373
|
sIdx += sStride;
|
|
3206
3374
|
mIdx += mStride;
|
|
3207
3375
|
}
|
|
3376
|
+
return didChange;
|
|
3208
3377
|
}
|
|
3209
3378
|
|
|
3210
3379
|
// src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts
|
|
3211
|
-
var
|
|
3380
|
+
var defaults15 = {
|
|
3212
3381
|
blendPixelDataAlphaMask
|
|
3213
3382
|
};
|
|
3214
|
-
var mutatorBlendPixelDataAlphaMask = ((writer, deps =
|
|
3383
|
+
var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults15) => {
|
|
3215
3384
|
const {
|
|
3216
|
-
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 =
|
|
3385
|
+
blendPixelDataAlphaMask: blendPixelDataAlphaMask2 = defaults15.blendPixelDataAlphaMask
|
|
3217
3386
|
} = deps;
|
|
3218
3387
|
return {
|
|
3219
3388
|
blendPixelDataAlphaMask(src, mask, opts = {}) {
|
|
@@ -3221,8 +3390,8 @@ var mutatorBlendPixelDataAlphaMask = ((writer, deps = defaults13) => {
|
|
|
3221
3390
|
const y = opts.y ?? 0;
|
|
3222
3391
|
const w = opts.w ?? src.width;
|
|
3223
3392
|
const h = opts.h ?? src.height;
|
|
3224
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3225
|
-
blendPixelDataAlphaMask2(writer.target, src, mask, opts);
|
|
3393
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3394
|
+
return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
|
|
3226
3395
|
}
|
|
3227
3396
|
};
|
|
3228
3397
|
});
|
|
@@ -3242,7 +3411,7 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3242
3411
|
my = 0,
|
|
3243
3412
|
invertMask = false
|
|
3244
3413
|
} = opts;
|
|
3245
|
-
if (globalAlpha === 0) return;
|
|
3414
|
+
if (globalAlpha === 0) return false;
|
|
3246
3415
|
let x = targetX;
|
|
3247
3416
|
let y = targetY;
|
|
3248
3417
|
let sx = sourceX;
|
|
@@ -3273,7 +3442,7 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3273
3442
|
}
|
|
3274
3443
|
const actualW = Math.min(w, dst.width - x);
|
|
3275
3444
|
const actualH = Math.min(h, dst.height - y);
|
|
3276
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
3445
|
+
if (actualW <= 0 || actualH <= 0) return false;
|
|
3277
3446
|
const dx = x - targetX | 0;
|
|
3278
3447
|
const dy = y - targetY | 0;
|
|
3279
3448
|
const dst32 = dst.data32;
|
|
@@ -3291,6 +3460,7 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3291
3460
|
const skipVal = invertMask ? 1 : 0;
|
|
3292
3461
|
const isOpaque = globalAlpha === 255;
|
|
3293
3462
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
3463
|
+
let didChange = false;
|
|
3294
3464
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3295
3465
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3296
3466
|
if (maskData[mIdx] === skipVal) {
|
|
@@ -3318,7 +3488,12 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3318
3488
|
}
|
|
3319
3489
|
finalCol = (srcCol & 16777215 | a << 24) >>> 0;
|
|
3320
3490
|
}
|
|
3321
|
-
|
|
3491
|
+
const current = dst32[dIdx];
|
|
3492
|
+
const next = blendFn(finalCol, dst32[dIdx]);
|
|
3493
|
+
if (current !== next) {
|
|
3494
|
+
dst32[dIdx] = next;
|
|
3495
|
+
didChange = true;
|
|
3496
|
+
}
|
|
3322
3497
|
dIdx++;
|
|
3323
3498
|
sIdx++;
|
|
3324
3499
|
mIdx++;
|
|
@@ -3327,15 +3502,16 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts = {}) {
|
|
|
3327
3502
|
sIdx += sStride;
|
|
3328
3503
|
mIdx += mStride;
|
|
3329
3504
|
}
|
|
3505
|
+
return didChange;
|
|
3330
3506
|
}
|
|
3331
3507
|
|
|
3332
3508
|
// src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts
|
|
3333
|
-
var
|
|
3509
|
+
var defaults16 = {
|
|
3334
3510
|
blendPixelDataBinaryMask
|
|
3335
3511
|
};
|
|
3336
|
-
var mutatorBlendPixelDataBinaryMask = ((writer, deps =
|
|
3512
|
+
var mutatorBlendPixelDataBinaryMask = ((writer, deps = defaults16) => {
|
|
3337
3513
|
const {
|
|
3338
|
-
blendPixelDataBinaryMask: blendPixelDataBinaryMask2 =
|
|
3514
|
+
blendPixelDataBinaryMask: blendPixelDataBinaryMask2 = defaults16.blendPixelDataBinaryMask
|
|
3339
3515
|
} = deps;
|
|
3340
3516
|
return {
|
|
3341
3517
|
blendPixelDataBinaryMask(src, mask, opts = {}) {
|
|
@@ -3343,15 +3519,15 @@ var mutatorBlendPixelDataBinaryMask = ((writer, deps = defaults14) => {
|
|
|
3343
3519
|
const y = opts.y ?? 0;
|
|
3344
3520
|
const w = opts.w ?? src.width;
|
|
3345
3521
|
const h = opts.h ?? src.height;
|
|
3346
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3347
|
-
blendPixelDataBinaryMask2(writer.target, src, mask, opts);
|
|
3522
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3523
|
+
return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
|
|
3348
3524
|
}
|
|
3349
3525
|
};
|
|
3350
3526
|
});
|
|
3351
3527
|
|
|
3352
|
-
// src/PixelData/
|
|
3528
|
+
// src/PixelData/fillPixelDataFast.ts
|
|
3353
3529
|
var SCRATCH_RECT = makeClippedRect();
|
|
3354
|
-
function
|
|
3530
|
+
function fillPixelDataFast(dst, color, _x, _y, _w, _h) {
|
|
3355
3531
|
let x;
|
|
3356
3532
|
let y;
|
|
3357
3533
|
let w;
|
|
@@ -3394,55 +3570,111 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
|
3394
3570
|
}
|
|
3395
3571
|
|
|
3396
3572
|
// src/History/PixelMutator/mutatorClear.ts
|
|
3397
|
-
var
|
|
3398
|
-
fillPixelData
|
|
3573
|
+
var defaults17 = {
|
|
3574
|
+
fillPixelData: fillPixelDataFast
|
|
3399
3575
|
};
|
|
3400
|
-
var mutatorClear = ((writer, deps =
|
|
3576
|
+
var mutatorClear = ((writer, deps = defaults17) => {
|
|
3401
3577
|
const {
|
|
3402
|
-
fillPixelData: fillPixelData2 =
|
|
3578
|
+
fillPixelData: fillPixelData2 = defaults17.fillPixelData
|
|
3403
3579
|
} = deps;
|
|
3404
3580
|
return {
|
|
3405
3581
|
clear(rect = {}) {
|
|
3582
|
+
const target = writer.config.target;
|
|
3406
3583
|
const x = rect.x ?? 0;
|
|
3407
3584
|
const y = rect.y ?? 0;
|
|
3408
|
-
const w = rect.w ??
|
|
3409
|
-
const h = rect.h ??
|
|
3585
|
+
const w = rect.w ?? target.width;
|
|
3586
|
+
const h = rect.h ?? target.height;
|
|
3410
3587
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3411
|
-
fillPixelData2(
|
|
3588
|
+
fillPixelData2(target, 0, x, y, w, h);
|
|
3412
3589
|
}
|
|
3413
3590
|
};
|
|
3414
3591
|
});
|
|
3415
3592
|
|
|
3593
|
+
// src/PixelData/fillPixelData.ts
|
|
3594
|
+
var SCRATCH_RECT2 = makeClippedRect();
|
|
3595
|
+
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
3596
|
+
let x;
|
|
3597
|
+
let y;
|
|
3598
|
+
let w;
|
|
3599
|
+
let h;
|
|
3600
|
+
if (typeof _x === "object") {
|
|
3601
|
+
x = _x.x ?? 0;
|
|
3602
|
+
y = _x.y ?? 0;
|
|
3603
|
+
w = _x.w ?? dst.width;
|
|
3604
|
+
h = _x.h ?? dst.height;
|
|
3605
|
+
} else if (typeof _x === "number") {
|
|
3606
|
+
x = _x;
|
|
3607
|
+
y = _y;
|
|
3608
|
+
w = _w;
|
|
3609
|
+
h = _h;
|
|
3610
|
+
} else {
|
|
3611
|
+
x = 0;
|
|
3612
|
+
y = 0;
|
|
3613
|
+
w = dst.width;
|
|
3614
|
+
h = dst.height;
|
|
3615
|
+
}
|
|
3616
|
+
const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT2);
|
|
3617
|
+
if (!clip.inBounds) return false;
|
|
3618
|
+
const {
|
|
3619
|
+
x: finalX,
|
|
3620
|
+
y: finalY,
|
|
3621
|
+
w: actualW,
|
|
3622
|
+
h: actualH
|
|
3623
|
+
} = clip;
|
|
3624
|
+
const dst32 = dst.data32;
|
|
3625
|
+
const dw = dst.width;
|
|
3626
|
+
let hasChanged = false;
|
|
3627
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
3628
|
+
const rowOffset = (finalY + iy) * dw;
|
|
3629
|
+
const start = rowOffset + finalX;
|
|
3630
|
+
const end = start + actualW;
|
|
3631
|
+
for (let i = start; i < end; i++) {
|
|
3632
|
+
if (dst32[i] !== color) {
|
|
3633
|
+
dst32[i] = color;
|
|
3634
|
+
hasChanged = true;
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
return hasChanged;
|
|
3639
|
+
}
|
|
3640
|
+
|
|
3416
3641
|
// src/History/PixelMutator/mutatorFill.ts
|
|
3417
|
-
var
|
|
3642
|
+
var defaults18 = {
|
|
3418
3643
|
fillPixelData
|
|
3419
3644
|
};
|
|
3420
|
-
var mutatorFill = ((writer, deps =
|
|
3645
|
+
var mutatorFill = ((writer, deps = defaults18) => {
|
|
3421
3646
|
const {
|
|
3422
|
-
fillPixelData: fillPixelData2 =
|
|
3647
|
+
fillPixelData: fillPixelData2 = defaults18.fillPixelData
|
|
3423
3648
|
} = deps;
|
|
3424
3649
|
return {
|
|
3425
|
-
fill(color,
|
|
3426
|
-
const
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3650
|
+
fill(color, x = 0, y = 0, w = writer.config.target.width, h = writer.config.target.height) {
|
|
3651
|
+
const target = writer.config.target;
|
|
3652
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3653
|
+
return didChange(fillPixelData2(target, color, x, y, w, h));
|
|
3654
|
+
}
|
|
3655
|
+
};
|
|
3656
|
+
});
|
|
3657
|
+
var mutatorFillRect = ((writer, deps = defaults18) => {
|
|
3658
|
+
const {
|
|
3659
|
+
fillPixelData: fillPixelData2 = defaults18.fillPixelData
|
|
3660
|
+
} = deps;
|
|
3661
|
+
return {
|
|
3662
|
+
fillRect(color, rect) {
|
|
3663
|
+
const target = writer.config.target;
|
|
3664
|
+
const didChange = writer.accumulator.storeRegionBeforeState(rect.x, rect.y, rect.w, rect.h);
|
|
3665
|
+
return didChange(fillPixelData2(target, color, rect.x, rect.y, rect.w, rect.h));
|
|
3434
3666
|
}
|
|
3435
3667
|
};
|
|
3436
3668
|
});
|
|
3437
3669
|
|
|
3438
3670
|
// src/PixelData/fillPixelDataBinaryMask.ts
|
|
3439
|
-
var
|
|
3671
|
+
var SCRATCH_RECT3 = makeClippedRect();
|
|
3440
3672
|
function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
3441
|
-
if (alpha === 0) return;
|
|
3673
|
+
if (alpha === 0) return false;
|
|
3442
3674
|
const maskW = mask.w;
|
|
3443
3675
|
const maskH = mask.h;
|
|
3444
|
-
const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height,
|
|
3445
|
-
if (!clip.inBounds) return;
|
|
3676
|
+
const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height, SCRATCH_RECT3);
|
|
3677
|
+
if (!clip.inBounds) return false;
|
|
3446
3678
|
const {
|
|
3447
3679
|
x: finalX,
|
|
3448
3680
|
y: finalY,
|
|
@@ -3459,6 +3691,7 @@ function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
|
3459
3691
|
const a = baseSrcAlpha * alpha + 128 >> 8;
|
|
3460
3692
|
finalCol = (colorRGB | a << 24) >>> 0;
|
|
3461
3693
|
}
|
|
3694
|
+
let hasChanged = false;
|
|
3462
3695
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3463
3696
|
const currentY = finalY + iy;
|
|
3464
3697
|
const maskY = currentY - y;
|
|
@@ -3469,30 +3702,35 @@ function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
|
3469
3702
|
const maskX = currentX - x;
|
|
3470
3703
|
const maskIndex = maskOffset + maskX;
|
|
3471
3704
|
if (maskData[maskIndex]) {
|
|
3472
|
-
dst32[dstRowOffset + currentX]
|
|
3705
|
+
const current = dst32[dstRowOffset + currentX];
|
|
3706
|
+
if (current !== finalCol) {
|
|
3707
|
+
dst32[dstRowOffset + currentX] = finalCol;
|
|
3708
|
+
hasChanged = true;
|
|
3709
|
+
}
|
|
3473
3710
|
}
|
|
3474
3711
|
}
|
|
3475
3712
|
}
|
|
3713
|
+
return hasChanged;
|
|
3476
3714
|
}
|
|
3477
3715
|
|
|
3478
3716
|
// src/History/PixelMutator/mutatorFillBinaryMask.ts
|
|
3479
|
-
var
|
|
3717
|
+
var defaults19 = {
|
|
3480
3718
|
fillPixelDataBinaryMask
|
|
3481
3719
|
};
|
|
3482
|
-
var mutatorFillBinaryMask = ((writer, deps =
|
|
3720
|
+
var mutatorFillBinaryMask = ((writer, deps = defaults19) => {
|
|
3483
3721
|
const {
|
|
3484
|
-
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 =
|
|
3722
|
+
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults19.fillPixelDataBinaryMask
|
|
3485
3723
|
} = deps;
|
|
3486
3724
|
return {
|
|
3487
3725
|
fillBinaryMask(color, mask, alpha = 255, x = 0, y = 0) {
|
|
3488
|
-
writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
|
|
3489
|
-
fillPixelDataBinaryMask2(writer.target, color, mask, alpha, x, y);
|
|
3726
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
|
|
3727
|
+
return didChange(fillPixelDataBinaryMask2(writer.config.target, color, mask, alpha, x, y));
|
|
3490
3728
|
}
|
|
3491
3729
|
};
|
|
3492
3730
|
});
|
|
3493
3731
|
|
|
3494
3732
|
// src/PixelData/invertPixelData.ts
|
|
3495
|
-
var
|
|
3733
|
+
var SCRATCH_RECT4 = makeClippedRect();
|
|
3496
3734
|
function invertPixelData(pixelData, opts = {}) {
|
|
3497
3735
|
const dst = pixelData;
|
|
3498
3736
|
const {
|
|
@@ -3505,8 +3743,8 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3505
3743
|
my = 0,
|
|
3506
3744
|
invertMask = false
|
|
3507
3745
|
} = opts;
|
|
3508
|
-
const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height,
|
|
3509
|
-
if (!clip.inBounds) return;
|
|
3746
|
+
const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT4);
|
|
3747
|
+
if (!clip.inBounds) return false;
|
|
3510
3748
|
const {
|
|
3511
3749
|
x,
|
|
3512
3750
|
y,
|
|
@@ -3546,26 +3784,28 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3546
3784
|
dIdx += dStride;
|
|
3547
3785
|
}
|
|
3548
3786
|
}
|
|
3787
|
+
return true;
|
|
3549
3788
|
}
|
|
3550
3789
|
|
|
3551
3790
|
// src/History/PixelMutator/mutatorInvert.ts
|
|
3552
|
-
var
|
|
3791
|
+
var defaults20 = {
|
|
3553
3792
|
invertPixelData
|
|
3554
3793
|
};
|
|
3555
|
-
var mutatorInvert = ((writer, deps =
|
|
3794
|
+
var mutatorInvert = ((writer, deps = defaults20) => {
|
|
3556
3795
|
const {
|
|
3557
|
-
invertPixelData: invertPixelData2 =
|
|
3796
|
+
invertPixelData: invertPixelData2 = defaults20.invertPixelData
|
|
3558
3797
|
} = deps;
|
|
3559
3798
|
return {
|
|
3560
3799
|
invert(opts = {}) {
|
|
3800
|
+
const target = writer.config.target;
|
|
3561
3801
|
const {
|
|
3562
3802
|
x = 0,
|
|
3563
3803
|
y = 0,
|
|
3564
|
-
w =
|
|
3565
|
-
h =
|
|
3804
|
+
w = target.width,
|
|
3805
|
+
h = target.height
|
|
3566
3806
|
} = opts;
|
|
3567
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3568
|
-
invertPixelData2(
|
|
3807
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3808
|
+
return didChange(invertPixelData2(target, opts));
|
|
3569
3809
|
}
|
|
3570
3810
|
};
|
|
3571
3811
|
});
|
|
@@ -3576,7 +3816,6 @@ function makeFullPixelMutator(writer) {
|
|
|
3576
3816
|
// @sort
|
|
3577
3817
|
...mutatorApplyAlphaMask(writer),
|
|
3578
3818
|
...mutatorApplyBinaryMask(writer),
|
|
3579
|
-
...mutatorApplyCircleBrush(writer),
|
|
3580
3819
|
...mutatorApplyCircleBrushStroke(writer),
|
|
3581
3820
|
...mutatorApplyCirclePencil(writer),
|
|
3582
3821
|
...mutatorApplyCirclePencilStroke(writer),
|
|
@@ -3585,6 +3824,7 @@ function makeFullPixelMutator(writer) {
|
|
|
3585
3824
|
...mutatorApplyRectPencil(writer),
|
|
3586
3825
|
...mutatorApplyRectPencilStroke(writer),
|
|
3587
3826
|
...mutatorBlendColor(writer),
|
|
3827
|
+
...mutatorBlendColorCircleMask(writer),
|
|
3588
3828
|
...mutatorBlendPixel(writer),
|
|
3589
3829
|
...mutatorBlendPixelData(writer),
|
|
3590
3830
|
...mutatorBlendPixelDataAlphaMask(writer),
|
|
@@ -3592,50 +3832,96 @@ function makeFullPixelMutator(writer) {
|
|
|
3592
3832
|
...mutatorClear(writer),
|
|
3593
3833
|
...mutatorFill(writer),
|
|
3594
3834
|
...mutatorFillBinaryMask(writer),
|
|
3835
|
+
...mutatorFillRect(writer),
|
|
3595
3836
|
...mutatorInvert(writer)
|
|
3596
3837
|
};
|
|
3597
3838
|
}
|
|
3598
3839
|
|
|
3840
|
+
// src/PixelTile/PixelTile.ts
|
|
3841
|
+
var PixelTile = class {
|
|
3842
|
+
constructor(id, tx, ty, tileSize, tileArea) {
|
|
3843
|
+
this.id = id;
|
|
3844
|
+
this.tx = tx;
|
|
3845
|
+
this.ty = ty;
|
|
3846
|
+
this.width = this.height = tileSize;
|
|
3847
|
+
this.data32 = new Uint32Array(tileArea);
|
|
3848
|
+
const data8 = new Uint8ClampedArray(this.data32.buffer);
|
|
3849
|
+
this.imageData = new ImageData(data8, tileSize, tileSize);
|
|
3850
|
+
}
|
|
3851
|
+
data32;
|
|
3852
|
+
width;
|
|
3853
|
+
height;
|
|
3854
|
+
imageData;
|
|
3855
|
+
};
|
|
3856
|
+
|
|
3857
|
+
// src/PixelTile/PixelTilePool.ts
|
|
3858
|
+
var PixelTilePool = class {
|
|
3859
|
+
pool;
|
|
3860
|
+
tileSize;
|
|
3861
|
+
tileArea;
|
|
3862
|
+
constructor(config) {
|
|
3863
|
+
this.pool = [];
|
|
3864
|
+
this.tileSize = config.tileSize;
|
|
3865
|
+
this.tileArea = config.tileArea;
|
|
3866
|
+
}
|
|
3867
|
+
getTile(id, tx, ty) {
|
|
3868
|
+
let tile = this.pool.pop();
|
|
3869
|
+
if (tile) {
|
|
3870
|
+
tile.id = id;
|
|
3871
|
+
tile.tx = tx;
|
|
3872
|
+
tile.ty = ty;
|
|
3873
|
+
tile.data32.fill(0);
|
|
3874
|
+
return tile;
|
|
3875
|
+
}
|
|
3876
|
+
return new PixelTile(id, tx, ty, this.tileSize, this.tileArea);
|
|
3877
|
+
}
|
|
3878
|
+
releaseTile(tile) {
|
|
3879
|
+
this.pool.push(tile);
|
|
3880
|
+
}
|
|
3881
|
+
releaseTiles(tiles) {
|
|
3882
|
+
let length = tiles.length;
|
|
3883
|
+
for (let i = 0; i < length; i++) {
|
|
3884
|
+
let tile = tiles[i];
|
|
3885
|
+
if (tile) {
|
|
3886
|
+
this.pool.push(tile);
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
tiles.length = 0;
|
|
3890
|
+
}
|
|
3891
|
+
};
|
|
3892
|
+
|
|
3599
3893
|
// src/History/PixelWriter.ts
|
|
3600
3894
|
var PixelWriter = class {
|
|
3601
|
-
target;
|
|
3602
3895
|
historyManager;
|
|
3603
3896
|
accumulator;
|
|
3897
|
+
historyActionFactory;
|
|
3604
3898
|
config;
|
|
3605
3899
|
mutator;
|
|
3606
3900
|
constructor(target, mutatorFactory, {
|
|
3607
3901
|
tileSize = 256,
|
|
3608
3902
|
maxHistorySteps = 50,
|
|
3609
|
-
historyManager = new HistoryManager(maxHistorySteps)
|
|
3903
|
+
historyManager = new HistoryManager(maxHistorySteps),
|
|
3904
|
+
historyActionFactory = makeHistoryAction,
|
|
3905
|
+
pixelTilePool
|
|
3610
3906
|
} = {}) {
|
|
3611
|
-
this.
|
|
3612
|
-
this.config = new PixelEngineConfig(tileSize);
|
|
3907
|
+
this.config = new PixelEngineConfig(tileSize, target);
|
|
3613
3908
|
this.historyManager = historyManager;
|
|
3614
|
-
|
|
3909
|
+
pixelTilePool ??= new PixelTilePool(this.config);
|
|
3910
|
+
this.accumulator = new PixelAccumulator(this.config, pixelTilePool);
|
|
3911
|
+
this.historyActionFactory = historyActionFactory;
|
|
3615
3912
|
this.mutator = mutatorFactory(this);
|
|
3616
3913
|
}
|
|
3617
|
-
withHistory(cb) {
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
const patch =
|
|
3626
|
-
|
|
3627
|
-
afterTiles
|
|
3628
|
-
};
|
|
3629
|
-
const target = this.target;
|
|
3630
|
-
const tileSize = this.config.tileSize;
|
|
3631
|
-
const accumulator = this.accumulator;
|
|
3632
|
-
const action = {
|
|
3633
|
-
undo: () => applyPatchTiles(target, patch.beforeTiles, tileSize),
|
|
3634
|
-
redo: () => applyPatchTiles(target, patch.afterTiles, tileSize),
|
|
3635
|
-
dispose: () => accumulator.recyclePatch(patch)
|
|
3636
|
-
};
|
|
3914
|
+
withHistory(cb, after, afterUndo, afterRedo) {
|
|
3915
|
+
try {
|
|
3916
|
+
cb(this.mutator);
|
|
3917
|
+
} catch (e) {
|
|
3918
|
+
this.accumulator.rollback();
|
|
3919
|
+
throw e;
|
|
3920
|
+
}
|
|
3921
|
+
if (this.accumulator.beforeTiles.length === 0) return;
|
|
3922
|
+
const patch = this.accumulator.extractPatch();
|
|
3923
|
+
const action = this.historyActionFactory(this, patch, after, afterUndo, afterRedo);
|
|
3637
3924
|
this.historyManager.commit(action);
|
|
3638
|
-
this.accumulator.reset();
|
|
3639
3925
|
}
|
|
3640
3926
|
};
|
|
3641
3927
|
|
|
@@ -3793,11 +4079,10 @@ function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0)
|
|
|
3793
4079
|
function makeReusableImageData() {
|
|
3794
4080
|
let imageData = null;
|
|
3795
4081
|
return function getReusableImageData(width, height) {
|
|
3796
|
-
|
|
3797
|
-
const widthMatches = hasInstance && imageData.width === width;
|
|
3798
|
-
const heightMatches = hasInstance && imageData.height === height;
|
|
3799
|
-
if (!widthMatches || !heightMatches) {
|
|
4082
|
+
if (imageData === null || imageData.width !== width || imageData.height !== height) {
|
|
3800
4083
|
imageData = new ImageData(width, height);
|
|
4084
|
+
} else {
|
|
4085
|
+
imageData.data.fill(0);
|
|
3801
4086
|
}
|
|
3802
4087
|
return imageData;
|
|
3803
4088
|
};
|
|
@@ -4204,8 +4489,8 @@ function makeBinaryMask(w, h, data) {
|
|
|
4204
4489
|
};
|
|
4205
4490
|
}
|
|
4206
4491
|
|
|
4207
|
-
// src/Mask/
|
|
4208
|
-
function
|
|
4492
|
+
// src/Mask/CircleAlphaMask.ts
|
|
4493
|
+
function makeCircleAlphaMask(size, fallOff = () => 1) {
|
|
4209
4494
|
const area = size * size;
|
|
4210
4495
|
const data = new Uint8Array(area);
|
|
4211
4496
|
const radius = size / 2;
|
|
@@ -4233,8 +4518,8 @@ function makeCircleBrushAlphaMask(size, fallOff = () => 1) {
|
|
|
4233
4518
|
};
|
|
4234
4519
|
}
|
|
4235
4520
|
|
|
4236
|
-
// src/Mask/
|
|
4237
|
-
function
|
|
4521
|
+
// src/Mask/CircleBinaryMask.ts
|
|
4522
|
+
function makeCircleBinaryMask(size) {
|
|
4238
4523
|
const area = size * size;
|
|
4239
4524
|
const data = new Uint8Array(area);
|
|
4240
4525
|
const radius = size / 2;
|
|
@@ -4530,57 +4815,6 @@ function setMaskData(mask, width, height, data) {
|
|
|
4530
4815
|
mask.data = data;
|
|
4531
4816
|
}
|
|
4532
4817
|
|
|
4533
|
-
// src/MaskRect/subtractBinaryMaskRects.ts
|
|
4534
|
-
function subtractBinaryMaskRects(current, subtracting) {
|
|
4535
|
-
let result = [...current];
|
|
4536
|
-
for (const sub of subtracting) {
|
|
4537
|
-
const next = [];
|
|
4538
|
-
for (const r of result) {
|
|
4539
|
-
const ix = Math.max(r.x, sub.x);
|
|
4540
|
-
const iy = Math.max(r.y, sub.y);
|
|
4541
|
-
const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
|
|
4542
|
-
const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
|
|
4543
|
-
if (ix >= ix2 || iy >= iy2) {
|
|
4544
|
-
next.push(r);
|
|
4545
|
-
continue;
|
|
4546
|
-
}
|
|
4547
|
-
if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
|
|
4548
|
-
if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
|
|
4549
|
-
if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
|
|
4550
|
-
if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
|
|
4551
|
-
}
|
|
4552
|
-
result = next;
|
|
4553
|
-
}
|
|
4554
|
-
return result;
|
|
4555
|
-
}
|
|
4556
|
-
function pushPiece(dest, r, x, y, w, h) {
|
|
4557
|
-
if (r.data === null || r.data === void 0) {
|
|
4558
|
-
dest.push({
|
|
4559
|
-
x,
|
|
4560
|
-
y,
|
|
4561
|
-
w,
|
|
4562
|
-
h,
|
|
4563
|
-
data: null,
|
|
4564
|
-
type: null
|
|
4565
|
-
});
|
|
4566
|
-
return;
|
|
4567
|
-
}
|
|
4568
|
-
const lx = x - r.x;
|
|
4569
|
-
const ly = y - r.y;
|
|
4570
|
-
const data = new Uint8Array(w * h);
|
|
4571
|
-
for (let row = 0; row < h; row++) {
|
|
4572
|
-
data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
|
|
4573
|
-
}
|
|
4574
|
-
dest.push({
|
|
4575
|
-
x,
|
|
4576
|
-
y,
|
|
4577
|
-
w,
|
|
4578
|
-
h,
|
|
4579
|
-
data,
|
|
4580
|
-
type: 1 /* BINARY */
|
|
4581
|
-
});
|
|
4582
|
-
}
|
|
4583
|
-
|
|
4584
4818
|
// src/Rect/getRectsBounds.ts
|
|
4585
4819
|
function getRectsBounds(rects) {
|
|
4586
4820
|
if (rects.length === 1) return {
|
|
@@ -4693,8 +4927,59 @@ function mergeBinaryMaskRects(current, adding) {
|
|
|
4693
4927
|
return rects;
|
|
4694
4928
|
}
|
|
4695
4929
|
|
|
4930
|
+
// src/MaskRect/subtractBinaryMaskRects.ts
|
|
4931
|
+
function subtractBinaryMaskRects(current, subtracting) {
|
|
4932
|
+
let result = [...current];
|
|
4933
|
+
for (const sub of subtracting) {
|
|
4934
|
+
const next = [];
|
|
4935
|
+
for (const r of result) {
|
|
4936
|
+
const ix = Math.max(r.x, sub.x);
|
|
4937
|
+
const iy = Math.max(r.y, sub.y);
|
|
4938
|
+
const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
|
|
4939
|
+
const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
|
|
4940
|
+
if (ix >= ix2 || iy >= iy2) {
|
|
4941
|
+
next.push(r);
|
|
4942
|
+
continue;
|
|
4943
|
+
}
|
|
4944
|
+
if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
|
|
4945
|
+
if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
|
|
4946
|
+
if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
|
|
4947
|
+
if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
|
|
4948
|
+
}
|
|
4949
|
+
result = next;
|
|
4950
|
+
}
|
|
4951
|
+
return result;
|
|
4952
|
+
}
|
|
4953
|
+
function pushPiece(dest, r, x, y, w, h) {
|
|
4954
|
+
if (r.data === null || r.data === void 0) {
|
|
4955
|
+
dest.push({
|
|
4956
|
+
x,
|
|
4957
|
+
y,
|
|
4958
|
+
w,
|
|
4959
|
+
h,
|
|
4960
|
+
data: null,
|
|
4961
|
+
type: null
|
|
4962
|
+
});
|
|
4963
|
+
return;
|
|
4964
|
+
}
|
|
4965
|
+
const lx = x - r.x;
|
|
4966
|
+
const ly = y - r.y;
|
|
4967
|
+
const data = new Uint8Array(w * h);
|
|
4968
|
+
for (let row = 0; row < h; row++) {
|
|
4969
|
+
data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
|
|
4970
|
+
}
|
|
4971
|
+
dest.push({
|
|
4972
|
+
x,
|
|
4973
|
+
y,
|
|
4974
|
+
w,
|
|
4975
|
+
h,
|
|
4976
|
+
data,
|
|
4977
|
+
type: 1 /* BINARY */
|
|
4978
|
+
});
|
|
4979
|
+
}
|
|
4980
|
+
|
|
4696
4981
|
// src/PixelData/PixelData.ts
|
|
4697
|
-
var PixelData = class
|
|
4982
|
+
var PixelData = class {
|
|
4698
4983
|
data32;
|
|
4699
4984
|
imageData;
|
|
4700
4985
|
width;
|
|
@@ -4712,30 +4997,35 @@ var PixelData = class _PixelData {
|
|
|
4712
4997
|
this.width = imageData.width;
|
|
4713
4998
|
this.height = imageData.height;
|
|
4714
4999
|
}
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
5000
|
+
};
|
|
5001
|
+
|
|
5002
|
+
// src/PixelData/blendPixelDataPaintBuffer.ts
|
|
5003
|
+
var SCRATCH_OPTS = {
|
|
5004
|
+
x: 0,
|
|
5005
|
+
y: 0,
|
|
5006
|
+
alpha: 255,
|
|
5007
|
+
blendFn: void 0
|
|
5008
|
+
};
|
|
5009
|
+
function blendPixelDataPaintBuffer(paintBuffer, target, alpha = 255, blendFn, blendPixelDataFn = blendPixelData) {
|
|
5010
|
+
const tileShift = paintBuffer.config.tileShift;
|
|
5011
|
+
const lookup = paintBuffer.lookup;
|
|
5012
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
5013
|
+
const tile = lookup[i];
|
|
5014
|
+
if (tile) {
|
|
5015
|
+
const x = tile.tx << tileShift;
|
|
5016
|
+
const y = tile.ty << tileShift;
|
|
5017
|
+
SCRATCH_OPTS.x = x;
|
|
5018
|
+
SCRATCH_OPTS.y = y;
|
|
5019
|
+
SCRATCH_OPTS.alpha = alpha;
|
|
5020
|
+
SCRATCH_OPTS.blendFn = blendFn;
|
|
5021
|
+
blendPixelDataFn(target, tile, SCRATCH_OPTS);
|
|
4731
5022
|
}
|
|
4732
|
-
return new _PixelData(newImageData);
|
|
4733
5023
|
}
|
|
4734
|
-
}
|
|
5024
|
+
}
|
|
4735
5025
|
|
|
4736
5026
|
// src/PixelData/clearPixelData.ts
|
|
4737
5027
|
function clearPixelData(dst, rect) {
|
|
4738
|
-
|
|
5028
|
+
fillPixelDataFast(dst, 0, rect);
|
|
4739
5029
|
}
|
|
4740
5030
|
|
|
4741
5031
|
// src/PixelData/extractPixelDataBuffer.ts
|
|
@@ -4954,6 +5244,124 @@ function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
|
4954
5244
|
dstData.set(data.subarray(srcStart, srcStart + copyW), dstStart);
|
|
4955
5245
|
}
|
|
4956
5246
|
}
|
|
5247
|
+
|
|
5248
|
+
// src/PixelTile/PaintBuffer.ts
|
|
5249
|
+
var PaintBuffer = class {
|
|
5250
|
+
constructor(config, tilePool) {
|
|
5251
|
+
this.config = config;
|
|
5252
|
+
this.tilePool = tilePool;
|
|
5253
|
+
this.lookup = [];
|
|
5254
|
+
}
|
|
5255
|
+
lookup;
|
|
5256
|
+
processMaskTiles(mask, callback) {
|
|
5257
|
+
const {
|
|
5258
|
+
tileShift,
|
|
5259
|
+
targetColumns
|
|
5260
|
+
} = this.config;
|
|
5261
|
+
const x1 = mask.x >> tileShift;
|
|
5262
|
+
const y1 = mask.y >> tileShift;
|
|
5263
|
+
const x2 = mask.x + mask.w - 1 >> tileShift;
|
|
5264
|
+
const y2 = mask.y + mask.h - 1 >> tileShift;
|
|
5265
|
+
for (let ty = y1; ty <= y2; ty++) {
|
|
5266
|
+
const tileRowIndex = ty * targetColumns;
|
|
5267
|
+
const tileTop = ty << tileShift;
|
|
5268
|
+
for (let tx = x1; tx <= x2; tx++) {
|
|
5269
|
+
const id = tileRowIndex + tx;
|
|
5270
|
+
let tile = this.lookup[id];
|
|
5271
|
+
if (!tile) {
|
|
5272
|
+
tile = this.tilePool.getTile(id, tx, ty);
|
|
5273
|
+
this.lookup[id] = tile;
|
|
5274
|
+
}
|
|
5275
|
+
const tileLeft = tx << tileShift;
|
|
5276
|
+
const startX = Math.max(mask.x, tileLeft);
|
|
5277
|
+
const endX = Math.min(mask.x + mask.w, tileLeft + this.config.tileSize);
|
|
5278
|
+
const startY = Math.max(mask.y, tileTop);
|
|
5279
|
+
const endY = Math.min(mask.y + mask.h, tileTop + this.config.tileSize);
|
|
5280
|
+
callback(tile, startX, startY, endX - startX, endY - startY, startX - mask.x, startY - mask.y);
|
|
5281
|
+
}
|
|
5282
|
+
}
|
|
5283
|
+
}
|
|
5284
|
+
writeColorBinaryMaskRect(color, mask) {
|
|
5285
|
+
const {
|
|
5286
|
+
tileShift,
|
|
5287
|
+
tileMask
|
|
5288
|
+
} = this.config;
|
|
5289
|
+
const maskData = mask.data;
|
|
5290
|
+
const maskW = mask.w;
|
|
5291
|
+
this.processMaskTiles(mask, (tile, bX, bY, bW, bH, mX, mY) => {
|
|
5292
|
+
const data32 = tile.data32;
|
|
5293
|
+
const startTileX = bX & tileMask;
|
|
5294
|
+
for (let i = 0; i < bH; i++) {
|
|
5295
|
+
const tileY = bY + i & tileMask;
|
|
5296
|
+
const maskY = mY + i;
|
|
5297
|
+
const tileRowOffset = tileY << tileShift;
|
|
5298
|
+
const maskRowOffset = maskY * maskW;
|
|
5299
|
+
const destStart = tileRowOffset + startTileX;
|
|
5300
|
+
const maskStart = maskRowOffset + mX;
|
|
5301
|
+
for (let j = 0; j < bW; j++) {
|
|
5302
|
+
if (maskData[maskStart + j]) {
|
|
5303
|
+
data32[destStart + j] = color;
|
|
5304
|
+
}
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
});
|
|
5308
|
+
}
|
|
5309
|
+
writeColorAlphaMaskRect(color, mask) {
|
|
5310
|
+
const {
|
|
5311
|
+
tileShift,
|
|
5312
|
+
tileMask
|
|
5313
|
+
} = this.config;
|
|
5314
|
+
const maskData = mask.data;
|
|
5315
|
+
const maskW = mask.w;
|
|
5316
|
+
const colorRGB = color & 16777215;
|
|
5317
|
+
const colorA = color >>> 24;
|
|
5318
|
+
this.processMaskTiles(mask, (tile, bX, bY, bW, bH, mX, mY) => {
|
|
5319
|
+
const data32 = tile.data32;
|
|
5320
|
+
const startTileX = bX & tileMask;
|
|
5321
|
+
for (let i = 0; i < bH; i++) {
|
|
5322
|
+
const tileY = bY + i & tileMask;
|
|
5323
|
+
const maskY = mY + i;
|
|
5324
|
+
const tileRowOffset = tileY << tileShift;
|
|
5325
|
+
const maskRowOffset = maskY * maskW;
|
|
5326
|
+
const destStart = tileRowOffset + startTileX;
|
|
5327
|
+
const maskStart = maskRowOffset + mX;
|
|
5328
|
+
for (let j = 0; j < bW; j++) {
|
|
5329
|
+
const maskA = maskData[maskStart + j];
|
|
5330
|
+
if (maskA > 0) {
|
|
5331
|
+
const finalA = colorA * maskA + 128 >> 8;
|
|
5332
|
+
data32[destStart + j] = (colorRGB | finalA << 24) >>> 0;
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5335
|
+
}
|
|
5336
|
+
});
|
|
5337
|
+
}
|
|
5338
|
+
clear() {
|
|
5339
|
+
this.tilePool.releaseTiles(this.lookup);
|
|
5340
|
+
}
|
|
5341
|
+
};
|
|
5342
|
+
|
|
5343
|
+
// src/PixelTile/PaintBufferRenderer.ts
|
|
5344
|
+
function makePaintBufferRenderer(paintBuffer, offscreenCanvasClass = OffscreenCanvas) {
|
|
5345
|
+
const config = paintBuffer.config;
|
|
5346
|
+
const tileSize = config.tileSize;
|
|
5347
|
+
const tileShift = config.tileShift;
|
|
5348
|
+
const lookup = paintBuffer.lookup;
|
|
5349
|
+
const canvas = new offscreenCanvasClass(tileSize, tileSize);
|
|
5350
|
+
const ctx = canvas.getContext("2d");
|
|
5351
|
+
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
5352
|
+
ctx.imageSmoothingEnabled = false;
|
|
5353
|
+
return function drawPaintBuffer(target) {
|
|
5354
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
5355
|
+
const tile = lookup[i];
|
|
5356
|
+
if (tile) {
|
|
5357
|
+
const dx = tile.tx << tileShift;
|
|
5358
|
+
const dy = tile.ty << tileShift;
|
|
5359
|
+
ctx.putImageData(tile.imageData, 0, 0);
|
|
5360
|
+
target.drawImage(canvas, dx, dy);
|
|
5361
|
+
}
|
|
5362
|
+
}
|
|
5363
|
+
};
|
|
5364
|
+
}
|
|
4957
5365
|
export {
|
|
4958
5366
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
4959
5367
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
@@ -4963,17 +5371,18 @@ export {
|
|
|
4963
5371
|
IndexedImage,
|
|
4964
5372
|
MaskType,
|
|
4965
5373
|
OFFSCREEN_CANVAS_CTX_FAILED,
|
|
5374
|
+
PaintBuffer,
|
|
4966
5375
|
PixelAccumulator,
|
|
4967
5376
|
PixelBuffer32,
|
|
4968
5377
|
PixelData,
|
|
4969
5378
|
PixelEngineConfig,
|
|
4970
5379
|
PixelTile,
|
|
5380
|
+
PixelTilePool,
|
|
4971
5381
|
PixelWriter,
|
|
4972
5382
|
UnsupportedFormatError,
|
|
4973
5383
|
applyAlphaMaskToPixelData,
|
|
4974
5384
|
applyBinaryMaskToAlphaMask,
|
|
4975
5385
|
applyBinaryMaskToPixelData,
|
|
4976
|
-
applyCircleBrushToPixelData,
|
|
4977
5386
|
applyPatchTiles,
|
|
4978
5387
|
applyRectBrushToPixelData,
|
|
4979
5388
|
base64DecodeArrayBuffer,
|
|
@@ -4981,9 +5390,12 @@ export {
|
|
|
4981
5390
|
blendColorPixelData,
|
|
4982
5391
|
blendColorPixelDataAlphaMask,
|
|
4983
5392
|
blendColorPixelDataBinaryMask,
|
|
5393
|
+
blendColorPixelDataCircleMask,
|
|
5394
|
+
blendPixel,
|
|
4984
5395
|
blendPixelData,
|
|
4985
5396
|
blendPixelDataAlphaMask,
|
|
4986
5397
|
blendPixelDataBinaryMask,
|
|
5398
|
+
blendPixelDataPaintBuffer,
|
|
4987
5399
|
clearPixelData,
|
|
4988
5400
|
color32ToCssRGBA,
|
|
4989
5401
|
color32ToHex,
|
|
@@ -5017,6 +5429,7 @@ export {
|
|
|
5017
5429
|
fileToImageData,
|
|
5018
5430
|
fillPixelData,
|
|
5019
5431
|
fillPixelDataBinaryMask,
|
|
5432
|
+
fillPixelDataFast,
|
|
5020
5433
|
floodFillSelection,
|
|
5021
5434
|
forEachLinePoint,
|
|
5022
5435
|
getCircleBrushOrPencilBounds,
|
|
@@ -5057,15 +5470,19 @@ export {
|
|
|
5057
5470
|
makeAlphaMask,
|
|
5058
5471
|
makeBinaryMask,
|
|
5059
5472
|
makeBlendModeRegistry,
|
|
5060
|
-
|
|
5061
|
-
|
|
5473
|
+
makeCanvasFrameRenderer,
|
|
5474
|
+
makeCircleAlphaMask,
|
|
5475
|
+
makeCircleBinaryMask,
|
|
5062
5476
|
makeFastBlendModeRegistry,
|
|
5063
5477
|
makeFullPixelMutator,
|
|
5478
|
+
makeHistoryAction,
|
|
5064
5479
|
makeImageDataLike,
|
|
5480
|
+
makePaintBufferRenderer,
|
|
5065
5481
|
makePerfectBlendModeRegistry,
|
|
5066
5482
|
makePixelCanvas,
|
|
5067
5483
|
makeReusableCanvas,
|
|
5068
5484
|
makeReusableImageData,
|
|
5485
|
+
makeReusableOffscreenCanvas,
|
|
5069
5486
|
merge2BinaryMaskRects,
|
|
5070
5487
|
mergeAlphaMasks,
|
|
5071
5488
|
mergeBinaryMaskRects,
|
|
@@ -5074,7 +5491,6 @@ export {
|
|
|
5074
5491
|
multiplyPerfect,
|
|
5075
5492
|
mutatorApplyAlphaMask,
|
|
5076
5493
|
mutatorApplyBinaryMask,
|
|
5077
|
-
mutatorApplyCircleBrush,
|
|
5078
5494
|
mutatorApplyCircleBrushStroke,
|
|
5079
5495
|
mutatorApplyCirclePencil,
|
|
5080
5496
|
mutatorApplyCirclePencilStroke,
|
|
@@ -5083,6 +5499,7 @@ export {
|
|
|
5083
5499
|
mutatorApplyRectPencil,
|
|
5084
5500
|
mutatorApplyRectPencilStroke,
|
|
5085
5501
|
mutatorBlendColor,
|
|
5502
|
+
mutatorBlendColorCircleMask,
|
|
5086
5503
|
mutatorBlendPixel,
|
|
5087
5504
|
mutatorBlendPixelData,
|
|
5088
5505
|
mutatorBlendPixelDataAlphaMask,
|
|
@@ -5090,6 +5507,7 @@ export {
|
|
|
5090
5507
|
mutatorClear,
|
|
5091
5508
|
mutatorFill,
|
|
5092
5509
|
mutatorFillBinaryMask,
|
|
5510
|
+
mutatorFillRect,
|
|
5093
5511
|
mutatorInvert,
|
|
5094
5512
|
overlayFast,
|
|
5095
5513
|
overlayPerfect,
|