pixel-data-js 0.35.0 → 0.37.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.prod.cjs +521 -326
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +132 -78
- package/dist/index.prod.js +513 -324
- package/dist/index.prod.js.map +1 -1
- package/package.json +2 -2
- package/src/Algorithm/floodFillSelection.ts +3 -2
- package/src/BlendModes/blend-modes-fast.ts +2 -1
- package/src/BlendModes/blend-modes-perfect.ts +2 -1
- package/src/Canvas/ReusableCanvas.ts +0 -5
- package/src/Color/_color-types.ts +8 -0
- package/src/Color/colorDistance.ts +9 -0
- package/src/Color/convert-color.ts +43 -0
- package/src/Color/lerpColor32.ts +44 -0
- package/src/Color/pack-color.ts +38 -0
- package/src/History/HistoryAction.ts +2 -2
- package/src/History/PixelAccumulator.ts +32 -13
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +2 -0
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +5 -1
- package/src/History/PixelMutator/mutatorApplyMask.ts +1 -0
- package/src/History/PixelMutator/mutatorBlendAlphaMask.ts +1 -0
- package/src/History/PixelMutator/mutatorBlendBinaryMask.ts +1 -0
- package/src/History/PixelMutator/mutatorBlendColor.ts +4 -1
- package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +2 -1
- package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +2 -1
- package/src/History/PixelMutator/mutatorBlendColorPaintMask.ts +24 -8
- package/src/History/PixelMutator/mutatorBlendColorPaintRect.ts +4 -1
- package/src/History/PixelMutator/mutatorBlendMask.ts +1 -0
- package/src/History/PixelMutator/mutatorBlendPixel.ts +3 -1
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +1 -0
- package/src/History/PixelMutator/mutatorClear.ts +3 -2
- package/src/History/PixelMutator/mutatorFill.ts +54 -38
- package/src/History/PixelMutator/mutatorFillBinaryMask.ts +3 -2
- package/src/History/PixelMutator/mutatorInvert.ts +3 -2
- package/src/History/PixelMutator.ts +1 -2
- package/src/History/PixelWriter.ts +5 -5
- package/src/IndexedImage/IndexedImage.ts +1 -1
- package/src/IndexedImage/indexedImageToAverageColor.ts +3 -2
- package/src/Mask/_mask-types.ts +9 -0
- package/src/Paint/AlphaMaskPaintBuffer.ts +26 -26
- package/src/Paint/BinaryMaskPaintBuffer.ts +19 -19
- package/src/Paint/ColorPaintBuffer.ts +40 -42
- package/src/Paint/Commit/AlphaMaskPaintBufferCommitter.ts +1 -1
- package/src/Paint/Commit/AlphaMaskPaintBufferManager.ts +6 -7
- package/src/Paint/Commit/BinaryMaskPaintBufferCommitter.ts +1 -1
- package/src/Paint/Commit/BinaryMaskPaintBufferManager.ts +6 -7
- package/src/Paint/Commit/ColorPaintBufferManager.ts +6 -7
- package/src/Paint/Commit/commitColorPaintBuffer.ts +2 -6
- package/src/Paint/Commit/commitMaskPaintBuffer.ts +3 -7
- package/src/Paint/Render/AlphaMaskPaintBufferCanvasRenderer.ts +42 -25
- package/src/Paint/Render/BinaryMaskPaintBufferCanvasRenderer.ts +40 -24
- package/src/Paint/Render/ColorPaintBufferCanvasRenderer.ts +21 -21
- package/src/Paint/Render/PaintCursorRenderer.ts +12 -2
- package/src/Paint/eachTileInBounds.ts +9 -10
- package/src/PixelData/_pixelData-types.ts +7 -0
- package/src/PixelData/blendColorPixelData.ts +2 -1
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +2 -1
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +2 -1
- package/src/PixelData/blendColorPixelDataMask.ts +2 -1
- package/src/PixelData/blendColorPixelDataPaintAlphaMask.ts +1 -1
- package/src/PixelData/blendColorPixelDataPaintBinaryMask.ts +1 -1
- package/src/PixelData/blendColorPixelDataPaintMask.ts +19 -8
- package/src/PixelData/blendPixel.ts +2 -1
- package/src/PixelData/blendPixelData.ts +2 -1
- package/src/PixelData/blendPixelDataAlphaMask.ts +2 -1
- package/src/PixelData/blendPixelDataBinaryMask.ts +2 -1
- package/src/PixelData/blendPixelDataPaintBuffer.ts +2 -3
- package/src/PixelData/clearPixelDataFast.ts +1 -1
- package/src/PixelData/cropPixelData.ts +36 -0
- package/src/PixelData/fillPixelData.ts +7 -7
- package/src/PixelData/fillPixelDataBinaryMask.ts +1 -1
- package/src/PixelData/fillPixelDataFast.ts +1 -1
- package/src/PixelData/trimPixelData.ts +49 -0
- package/src/PixelData/writePaintBufferToPixelData.ts +1 -5
- package/src/Tile/MaskTile.ts +4 -0
- package/src/Tile/PixelTile.ts +2 -0
- package/src/Tile/TilePool.ts +9 -8
- package/src/Tile/TileTargetConfig.ts +27 -0
- package/src/Tile/_tile-types.ts +16 -0
- package/src/_types.ts +1 -6
- package/src/index.ts +9 -3
- package/src/History/PixelEngineConfig.ts +0 -28
- package/src/Internal/_constants.ts +0 -3
- package/src/color.ts +0 -112
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Color32 } from '../../_types'
|
|
2
1
|
import { sourceOverPerfect } from '../../BlendModes/blend-modes-perfect'
|
|
2
|
+
import type { Color32 } from '../../Color/_color-types'
|
|
3
3
|
import type { PixelAccumulator } from '../../History/PixelAccumulator'
|
|
4
4
|
import { blendColorPixelDataAlphaMask } from '../../PixelData/blendColorPixelDataAlphaMask'
|
|
5
5
|
import { blendColorPixelDataBinaryMask } from '../../PixelData/blendColorPixelDataBinaryMask'
|
|
@@ -42,7 +42,6 @@ export function commitMaskPaintBuffer(
|
|
|
42
42
|
blendColorPixelDataMaskFn: any,
|
|
43
43
|
) {
|
|
44
44
|
const config = accumulator.config
|
|
45
|
-
const tileShift = config.tileShift
|
|
46
45
|
const lookup = paintBuffer.lookup
|
|
47
46
|
|
|
48
47
|
SCRATCH_OPTS.alpha = alpha
|
|
@@ -54,11 +53,8 @@ export function commitMaskPaintBuffer(
|
|
|
54
53
|
if (tile) {
|
|
55
54
|
const didChange = accumulator.storeTileBeforeState(tile.id, tile.tx, tile.ty)
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
SCRATCH_OPTS.x = dx
|
|
61
|
-
SCRATCH_OPTS.y = dy
|
|
56
|
+
SCRATCH_OPTS.x = tile.x
|
|
57
|
+
SCRATCH_OPTS.y = tile.y
|
|
62
58
|
SCRATCH_OPTS.w = tile.w
|
|
63
59
|
SCRATCH_OPTS.h = tile.h
|
|
64
60
|
|
|
@@ -1,31 +1,46 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import type { ReusableCanvasFactory } from '../../Canvas/_canvas-types'
|
|
2
|
+
import { makeReusableOffscreenCanvas } from '../../Canvas/ReusableCanvas'
|
|
3
|
+
import type { Color32 } from '../../Color/_color-types'
|
|
4
|
+
import type { PixelData } from '../../PixelData/_pixelData-types'
|
|
5
|
+
import { makeReusablePixelData } from '../../PixelData/ReusablePixelData'
|
|
6
|
+
import type { AlphaMaskTile, TileTargetMeta } from '../../Tile/_tile-types'
|
|
6
7
|
import type { AlphaMaskPaintBuffer } from '../AlphaMaskPaintBuffer'
|
|
7
8
|
|
|
8
9
|
export type AlphaMaskPaintBufferCanvasRenderer = ReturnType<typeof makeAlphaMaskPaintBufferCanvasRenderer>
|
|
9
10
|
|
|
10
|
-
export function makeAlphaMaskPaintBufferCanvasRenderer(
|
|
11
|
+
export function makeAlphaMaskPaintBufferCanvasRenderer<T extends HTMLCanvasElement | OffscreenCanvas>(
|
|
11
12
|
paintBuffer: AlphaMaskPaintBuffer,
|
|
12
|
-
|
|
13
|
+
reusableCanvasFactory?: () => ReusableCanvasFactory<T>,
|
|
13
14
|
) {
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
const factory = (reusableCanvasFactory ?? makeReusableOffscreenCanvas) as unknown as () => ReusableCanvasFactory<T>
|
|
16
|
+
const getBuffer = factory()
|
|
17
|
+
const getBridge = makeReusablePixelData()
|
|
18
|
+
|
|
19
|
+
let config: TileTargetMeta
|
|
20
|
+
let tileSize: number
|
|
21
|
+
let tileArea: number
|
|
22
|
+
let lookup: (AlphaMaskTile | undefined)[]
|
|
23
|
+
let view32: Uint32Array
|
|
24
|
+
let bridge: PixelData
|
|
25
|
+
let canvas: HTMLCanvasElement | OffscreenCanvas
|
|
26
|
+
let ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D
|
|
27
|
+
|
|
28
|
+
setBuffer(paintBuffer)
|
|
29
|
+
|
|
30
|
+
function setBuffer(value: AlphaMaskPaintBuffer) {
|
|
31
|
+
paintBuffer = value
|
|
32
|
+
config = paintBuffer.config
|
|
33
|
+
tileSize = config.tileSize
|
|
34
|
+
tileArea = config.tileArea
|
|
35
|
+
lookup = paintBuffer.lookup
|
|
36
|
+
bridge = getBridge(tileSize, tileSize)
|
|
37
|
+
view32 = bridge.data
|
|
38
|
+
const buff = getBuffer(tileSize, tileSize)
|
|
39
|
+
canvas = buff.canvas
|
|
40
|
+
ctx = buff.ctx
|
|
41
|
+
}
|
|
27
42
|
|
|
28
|
-
|
|
43
|
+
function draw(
|
|
29
44
|
targetCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
30
45
|
color: Color32,
|
|
31
46
|
alpha = 255,
|
|
@@ -64,15 +79,17 @@ export function makeAlphaMaskPaintBufferCanvasRenderer(
|
|
|
64
79
|
}
|
|
65
80
|
}
|
|
66
81
|
|
|
67
|
-
const dx = tile.tx << tileShift
|
|
68
|
-
const dy = tile.ty << tileShift
|
|
69
|
-
|
|
70
82
|
ctx.putImageData(bridge.imageData, 0, 0)
|
|
71
|
-
targetCtx.drawImage(canvas,
|
|
83
|
+
targetCtx.drawImage(canvas, tile.x, tile.y)
|
|
72
84
|
}
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
targetCtx.globalAlpha = 1
|
|
76
88
|
targetCtx.globalCompositeOperation = 'source-over'
|
|
77
89
|
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
draw,
|
|
93
|
+
setBuffer,
|
|
94
|
+
}
|
|
78
95
|
}
|
|
@@ -1,31 +1,46 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import type { ReusableCanvasFactory } from '../../Canvas/_canvas-types'
|
|
2
|
+
import { makeReusableOffscreenCanvas } from '../../Canvas/ReusableCanvas'
|
|
3
|
+
import type { Color32 } from '../../Color/_color-types'
|
|
4
|
+
import type { PixelData } from '../../PixelData/_pixelData-types'
|
|
5
|
+
import { makeReusablePixelData } from '../../PixelData/ReusablePixelData'
|
|
6
|
+
import type { BinaryMaskTile, TileTargetMeta } from '../../Tile/_tile-types'
|
|
6
7
|
import type { BinaryMaskPaintBuffer } from '../BinaryMaskPaintBuffer'
|
|
7
8
|
|
|
8
9
|
export type BinaryMaskPaintBufferCanvasRenderer = ReturnType<typeof makeBinaryMaskPaintBufferCanvasRenderer>
|
|
9
10
|
|
|
10
|
-
export function makeBinaryMaskPaintBufferCanvasRenderer(
|
|
11
|
+
export function makeBinaryMaskPaintBufferCanvasRenderer<T extends HTMLCanvasElement | OffscreenCanvas>(
|
|
11
12
|
paintBuffer: BinaryMaskPaintBuffer,
|
|
12
|
-
|
|
13
|
+
reusableCanvasFactory?: () => ReusableCanvasFactory<T>,
|
|
13
14
|
) {
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const tileArea = config.tileArea
|
|
18
|
-
const lookup = paintBuffer.lookup
|
|
15
|
+
const factory = (reusableCanvasFactory ?? makeReusableOffscreenCanvas) as unknown as () => ReusableCanvasFactory<T>
|
|
16
|
+
const getBuffer = factory()
|
|
17
|
+
const getBridge = makeReusablePixelData()
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
let config: TileTargetMeta
|
|
20
|
+
let tileSize: number
|
|
21
|
+
let tileArea: number
|
|
22
|
+
let lookup: (BinaryMaskTile | undefined)[]
|
|
23
|
+
let view32: Uint32Array
|
|
24
|
+
let bridge: PixelData
|
|
25
|
+
let canvas: HTMLCanvasElement | OffscreenCanvas
|
|
26
|
+
let ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
const view32 = bridge.data
|
|
28
|
+
setBuffer(paintBuffer)
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
function setBuffer(value: BinaryMaskPaintBuffer) {
|
|
31
|
+
paintBuffer = value
|
|
32
|
+
config = paintBuffer.config
|
|
33
|
+
tileSize = config.tileSize
|
|
34
|
+
tileArea = config.tileArea
|
|
35
|
+
lookup = paintBuffer.lookup
|
|
36
|
+
bridge = getBridge(tileSize, tileSize)
|
|
37
|
+
view32 = bridge.data
|
|
38
|
+
const buff = getBuffer(tileSize, tileSize)
|
|
39
|
+
canvas = buff.canvas
|
|
40
|
+
ctx = buff.ctx
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function draw(
|
|
29
44
|
targetCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
30
45
|
color: Color32,
|
|
31
46
|
alpha = 255,
|
|
@@ -47,21 +62,22 @@ export function makeBinaryMaskPaintBufferCanvasRenderer(
|
|
|
47
62
|
view32.fill(0)
|
|
48
63
|
|
|
49
64
|
for (let p = 0; p < tileArea; p++) {
|
|
50
|
-
// If mask is solid, the final pixel is just the unmodified color
|
|
51
65
|
if (data8[p] === 1) {
|
|
52
66
|
view32[p] = color
|
|
53
67
|
}
|
|
54
68
|
}
|
|
55
69
|
|
|
56
|
-
const dx = tile.tx << tileShift
|
|
57
|
-
const dy = tile.ty << tileShift
|
|
58
|
-
|
|
59
70
|
ctx.putImageData(bridge.imageData, 0, 0)
|
|
60
|
-
targetCtx.drawImage(canvas,
|
|
71
|
+
targetCtx.drawImage(canvas, tile.x, tile.y)
|
|
61
72
|
}
|
|
62
73
|
}
|
|
63
74
|
|
|
64
75
|
targetCtx.globalAlpha = 1
|
|
65
76
|
targetCtx.globalCompositeOperation = 'source-over'
|
|
66
77
|
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
draw,
|
|
81
|
+
setBuffer,
|
|
82
|
+
}
|
|
67
83
|
}
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import { CANVAS_CTX_FAILED } from '../../Internal/_errors'
|
|
1
|
+
import type { ReusableCanvasFactory } from '../../Canvas/_canvas-types'
|
|
2
|
+
import { makeReusableOffscreenCanvas } from '../../Canvas/ReusableCanvas'
|
|
4
3
|
import type { ColorPaintBuffer } from '../ColorPaintBuffer'
|
|
5
4
|
|
|
6
5
|
export type ColorPaintBufferCanvasRenderer = ReturnType<typeof makeColorPaintBufferCanvasRenderer>
|
|
7
6
|
|
|
8
|
-
export function makeColorPaintBufferCanvasRenderer(
|
|
7
|
+
export function makeColorPaintBufferCanvasRenderer<T extends HTMLCanvasElement | OffscreenCanvas>(
|
|
9
8
|
paintBuffer: ColorPaintBuffer,
|
|
10
|
-
|
|
9
|
+
reusableCanvasFactory?: () => ReusableCanvasFactory<T>,
|
|
11
10
|
) {
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const tileShift = config.tileShift
|
|
15
|
-
const lookup = paintBuffer.lookup
|
|
11
|
+
const factory = (reusableCanvasFactory ?? makeReusableOffscreenCanvas) as unknown as () => ReusableCanvasFactory<T>
|
|
12
|
+
const getBuffer = factory()
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
const ctx = canvas.getContext('2d')
|
|
19
|
-
if (!ctx) throw new Error(CANVAS_CTX_FAILED)
|
|
20
|
-
ctx.imageSmoothingEnabled = false
|
|
21
|
-
|
|
22
|
-
return function drawPaintBuffer(
|
|
14
|
+
function draw(
|
|
23
15
|
targetCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
24
16
|
alpha = 255,
|
|
25
17
|
compOperation: GlobalCompositeOperation = 'source-over',
|
|
26
18
|
): void {
|
|
19
|
+
const buff = getBuffer(paintBuffer.config.tileSize, paintBuffer.config.tileSize)
|
|
20
|
+
const lookup = paintBuffer.lookup
|
|
21
|
+
const length = lookup.length
|
|
22
|
+
const ctx = buff.ctx
|
|
23
|
+
const canvas = buff.canvas
|
|
27
24
|
|
|
28
25
|
targetCtx.globalAlpha = alpha / 255
|
|
29
26
|
targetCtx.globalCompositeOperation = compOperation
|
|
30
27
|
|
|
31
|
-
for (let i = 0; i <
|
|
28
|
+
for (let i = 0; i < length; i++) {
|
|
32
29
|
const tile = lookup[i]
|
|
33
30
|
|
|
34
31
|
if (tile) {
|
|
35
|
-
const dx = tile.tx << tileShift
|
|
36
|
-
const dy = tile.ty << tileShift
|
|
37
|
-
|
|
38
32
|
ctx.putImageData(tile.imageData, 0, 0)
|
|
39
|
-
|
|
40
|
-
targetCtx.drawImage(canvas, dx, dy)
|
|
33
|
+
targetCtx.drawImage(canvas, tile.x, tile.y)
|
|
41
34
|
}
|
|
42
35
|
}
|
|
43
36
|
|
|
44
37
|
targetCtx.globalAlpha = 1
|
|
45
38
|
targetCtx.globalCompositeOperation = 'source-over'
|
|
46
39
|
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
draw,
|
|
43
|
+
setBuffer(value: ColorPaintBuffer) {
|
|
44
|
+
paintBuffer = value
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
47
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { type Color32 } from '../../_types'
|
|
2
1
|
import type { ReusableCanvasFactory } from '../../Canvas/_canvas-types'
|
|
3
2
|
import { makeReusableOffscreenCanvas } from '../../Canvas/ReusableCanvas'
|
|
4
|
-
import {
|
|
3
|
+
import type { Color32 } from '../../Color/_color-types'
|
|
4
|
+
|
|
5
|
+
import { packColor } from '../../Color/pack-color'
|
|
5
6
|
import { _macro_paintRectCenterOffset } from '../../Internal/macros'
|
|
6
7
|
import { type BinaryMask, MaskType } from '../../Mask/_mask-types'
|
|
7
8
|
import { makeBinaryMaskFromAlphaMask } from '../../Mask/BinaryMask/makeBinaryMaskFromAlphaMask'
|
|
@@ -103,6 +104,14 @@ export function makePaintCursorRenderer<T extends HTMLCanvasElement | OffscreenC
|
|
|
103
104
|
drawCtx.drawImage(canvas, Math.floor(dx), Math.floor(dy))
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
function drawRaw(
|
|
108
|
+
drawCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
|
|
109
|
+
x: number,
|
|
110
|
+
y: number,
|
|
111
|
+
) {
|
|
112
|
+
drawCtx.drawImage(canvas, Math.floor(x * _scale), Math.floor(y * _scale))
|
|
113
|
+
}
|
|
114
|
+
|
|
106
115
|
function getSettings() {
|
|
107
116
|
return {
|
|
108
117
|
color: _color,
|
|
@@ -116,6 +125,7 @@ export function makePaintCursorRenderer<T extends HTMLCanvasElement | OffscreenC
|
|
|
116
125
|
getBounds,
|
|
117
126
|
getBoundsScaled: getOutlineBoundsScaled,
|
|
118
127
|
draw,
|
|
128
|
+
drawRaw,
|
|
119
129
|
getSettings,
|
|
120
130
|
}
|
|
121
131
|
}
|
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
import type { PixelEngineConfig } from '../History/PixelEngineConfig'
|
|
2
1
|
import type { Rect } from '../Rect/_rect-types'
|
|
3
|
-
import type { Tile } from '../Tile/_tile-types'
|
|
2
|
+
import type { Tile, TileTargetMeta } from '../Tile/_tile-types'
|
|
4
3
|
import type { TilePool } from '../Tile/TilePool'
|
|
5
4
|
|
|
6
5
|
export function eachTileInBounds<T extends Tile>(
|
|
7
|
-
config:
|
|
6
|
+
config: TileTargetMeta,
|
|
8
7
|
lookup: (T | undefined)[],
|
|
9
8
|
tilePool: TilePool<T>,
|
|
10
9
|
bounds: Rect,
|
|
11
10
|
callback: (tile: T, bX: number, bY: number, bW: number, bH: number) => void,
|
|
12
11
|
): void {
|
|
13
|
-
const {
|
|
12
|
+
const { targetRows, targetColumns, tileSize } = config
|
|
14
13
|
|
|
15
|
-
const x1 = Math.max(0, bounds.x
|
|
16
|
-
const y1 = Math.max(0, bounds.y
|
|
17
|
-
const x2 = Math.min(targetColumns - 1, (bounds.x + bounds.w - 1)
|
|
18
|
-
const y2 = Math.min(targetRows - 1, (bounds.y + bounds.h - 1)
|
|
14
|
+
const x1 = Math.max(0, Math.floor(bounds.x / tileSize))
|
|
15
|
+
const y1 = Math.max(0, Math.floor(bounds.y / tileSize))
|
|
16
|
+
const x2 = Math.min(targetColumns - 1, Math.floor((bounds.x + bounds.w - 1) / tileSize))
|
|
17
|
+
const y2 = Math.min(targetRows - 1, Math.floor((bounds.y + bounds.h - 1) / tileSize))
|
|
19
18
|
|
|
20
19
|
if (x1 > x2 || y1 > y2) return
|
|
21
20
|
|
|
22
21
|
for (let ty = y1; ty <= y2; ty++) {
|
|
23
22
|
const rowOffset = ty * targetColumns
|
|
24
|
-
const tileTop = ty
|
|
23
|
+
const tileTop = ty * tileSize
|
|
25
24
|
|
|
26
25
|
for (let tx = x1; tx <= x2; tx++) {
|
|
27
26
|
const id = rowOffset + tx
|
|
28
27
|
const tile = lookup[id] ?? (lookup[id] = tilePool.getTile(id, tx, ty))
|
|
29
|
-
const tileLeft = tx
|
|
28
|
+
const tileLeft = tx * tileSize
|
|
30
29
|
|
|
31
30
|
const startX = bounds.x > tileLeft ? bounds.x : tileLeft
|
|
32
31
|
const startY = bounds.y > tileTop ? bounds.y : tileTop
|
|
@@ -15,3 +15,10 @@ export interface MutablePixelData32 {
|
|
|
15
15
|
export interface PixelData<T extends ImageDataLike = ImageData> extends PixelData32 {
|
|
16
16
|
readonly imageData: T
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
export interface MutablePixelData<T extends ImageDataLike = ImageData> extends PixelData32 {
|
|
20
|
+
imageData: T
|
|
21
|
+
data: Uint32Array
|
|
22
|
+
w: number
|
|
23
|
+
h: number
|
|
24
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ColorBlendOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
4
|
import type { PixelData32 } from './_pixelData-types'
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ColorBlendMaskOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
4
|
import type { AlphaMask } from '../Mask/_mask-types'
|
|
4
5
|
import type { PixelData32 } from './_pixelData-types'
|
|
5
6
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ColorBlendMaskOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
4
|
import type { BinaryMask } from '../Mask/_mask-types'
|
|
4
5
|
import type { PixelData32 } from './_pixelData-types'
|
|
5
6
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ColorBlendMaskOptions } from '../_types'
|
|
2
|
+
import type { Color32 } from '../Color/_color-types'
|
|
2
3
|
import { type Mask, MaskType } from '../Mask/_mask-types'
|
|
3
4
|
import type { PixelData32 } from './_pixelData-types'
|
|
4
5
|
import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Color32 } from '../_types'
|
|
2
1
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
2
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
3
|
import type { PaintAlphaMask } from '../Paint/_paint-types'
|
|
4
4
|
import type { PixelData32 } from './_pixelData-types'
|
|
5
5
|
import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Color32 } from '../_types'
|
|
2
1
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
2
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
3
|
import type { PaintBinaryMask } from '../Paint/_paint-types'
|
|
4
4
|
import type { PixelData32 } from './_pixelData-types'
|
|
5
5
|
import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { type Color32 } from '../_types'
|
|
2
1
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
2
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
3
|
import { MaskType } from '../Mask/_mask-types'
|
|
4
|
-
import type { PaintMask } from '../Paint/_paint-types'
|
|
4
|
+
import type { PaintMask, PaintRect } from '../Paint/_paint-types'
|
|
5
5
|
import type { PixelData32 } from './_pixelData-types'
|
|
6
|
+
import { blendColorPixelData } from './blendColorPixelData'
|
|
6
7
|
import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
|
|
7
8
|
import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
|
|
8
9
|
|
|
@@ -11,12 +12,14 @@ const SCRATCH_OPTS = {
|
|
|
11
12
|
y: 0,
|
|
12
13
|
alpha: 255,
|
|
13
14
|
blendFn: sourceOverPerfect,
|
|
15
|
+
w: undefined as number | undefined,
|
|
16
|
+
h: undefined as number | undefined,
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export function blendColorPixelDataPaintMask(
|
|
17
|
-
|
|
20
|
+
target: PixelData32,
|
|
18
21
|
color: Color32,
|
|
19
|
-
mask: PaintMask,
|
|
22
|
+
mask: PaintMask | PaintRect,
|
|
20
23
|
x: number,
|
|
21
24
|
y: number,
|
|
22
25
|
alpha = 255,
|
|
@@ -29,10 +32,18 @@ export function blendColorPixelDataPaintMask(
|
|
|
29
32
|
SCRATCH_OPTS.y = ty
|
|
30
33
|
SCRATCH_OPTS.alpha = alpha
|
|
31
34
|
SCRATCH_OPTS.blendFn = blendFn
|
|
35
|
+
SCRATCH_OPTS.w = undefined
|
|
36
|
+
SCRATCH_OPTS.h = undefined
|
|
32
37
|
|
|
33
|
-
if (mask.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
if (mask.data) {
|
|
39
|
+
if (mask.type === MaskType.BINARY) {
|
|
40
|
+
return blendColorPixelDataBinaryMask(target, color, mask, SCRATCH_OPTS)
|
|
41
|
+
} else {
|
|
42
|
+
return blendColorPixelDataAlphaMask(target, color, mask, SCRATCH_OPTS)
|
|
43
|
+
}
|
|
37
44
|
}
|
|
45
|
+
SCRATCH_OPTS.w = mask.w
|
|
46
|
+
SCRATCH_OPTS.h = mask.h
|
|
47
|
+
|
|
48
|
+
return blendColorPixelData(target, color, SCRATCH_OPTS)
|
|
38
49
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { BlendColor32
|
|
1
|
+
import type { BlendColor32 } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
4
|
import type { PixelData32 } from './_pixelData-types'
|
|
4
5
|
|
|
5
6
|
export function blendPixel(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PixelBlendOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
4
|
import type { PixelData32 } from './_pixelData-types'
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PixelBlendMaskOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
4
|
import type { AlphaMask } from '../Mask/_mask-types'
|
|
4
5
|
import type { PixelData32 } from './_pixelData-types'
|
|
5
6
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PixelBlendMaskOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { Color32 } from '../Color/_color-types'
|
|
3
4
|
import type { BinaryMask } from '../Mask/_mask-types'
|
|
4
5
|
import type { PixelData32 } from './_pixelData-types'
|
|
5
6
|
|
|
@@ -17,14 +17,13 @@ export function blendPixelDataPaintBuffer(
|
|
|
17
17
|
blendFn?: BlendColor32,
|
|
18
18
|
blendPixelDataFn = blendPixelData,
|
|
19
19
|
): void {
|
|
20
|
-
const tileShift = paintBuffer.config.tileShift
|
|
21
20
|
const lookup = paintBuffer.lookup
|
|
22
21
|
for (let i = 0; i < lookup.length; i++) {
|
|
23
22
|
const tile = lookup[i]
|
|
24
23
|
|
|
25
24
|
if (tile) {
|
|
26
|
-
const x = tile.
|
|
27
|
-
const y = tile.
|
|
25
|
+
const x = tile.x
|
|
26
|
+
const y = tile.y
|
|
28
27
|
|
|
29
28
|
SCRATCH_OPTS.x = x
|
|
30
29
|
SCRATCH_OPTS.y = y
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { MutablePixelData, PixelData, PixelData32 } from './_pixelData-types'
|
|
2
|
+
import { setPixelData } from './PixelData'
|
|
3
|
+
|
|
4
|
+
export function cropPixelData(src: PixelData32, x: number, y: number, w: number, h: number, out?: MutablePixelData): PixelData {
|
|
5
|
+
const cx = Math.max(x, 0)
|
|
6
|
+
const cy = Math.max(y, 0)
|
|
7
|
+
const cw = Math.min(x + w, src.w) - cx
|
|
8
|
+
const ch = Math.min(y + h, src.h) - cy
|
|
9
|
+
|
|
10
|
+
if (cw <= 0 || ch <= 0) {
|
|
11
|
+
throw new Error(`Crop [${x},${y} ${w}x${h}] does not overlap PixelData [${src.w}x${src.h}]`)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const cropped = new ImageData(cw, ch)
|
|
15
|
+
|
|
16
|
+
let dst32: Uint32Array
|
|
17
|
+
if (out) {
|
|
18
|
+
setPixelData(out, cropped)
|
|
19
|
+
dst32 = out.data
|
|
20
|
+
} else {
|
|
21
|
+
dst32 = new Uint32Array(cropped.data.buffer)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for (let row = 0; row < ch; row++) {
|
|
25
|
+
const srcOffset = ((cy + row) * src.w) + cx
|
|
26
|
+
const dstOffset = row * cw
|
|
27
|
+
dst32.set(src.data.subarray(srcOffset, srcOffset + cw), dstOffset)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return out ?? {
|
|
31
|
+
data: dst32,
|
|
32
|
+
imageData: cropped,
|
|
33
|
+
w: cw,
|
|
34
|
+
h: ch,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Color32 } from '../
|
|
1
|
+
import type { Color32 } from '../Color/_color-types'
|
|
2
2
|
import type { Rect } from '../Rect/_rect-types'
|
|
3
3
|
import type { PixelData32 } from './_pixelData-types'
|
|
4
4
|
|
|
@@ -47,16 +47,16 @@ export function fillPixelData(
|
|
|
47
47
|
let w: number
|
|
48
48
|
let h: number
|
|
49
49
|
|
|
50
|
-
if (typeof _x === '
|
|
51
|
-
x = _x.x ?? 0
|
|
52
|
-
y = _x.y ?? 0
|
|
53
|
-
w = _x.w ?? dstW
|
|
54
|
-
h = _x.h ?? dstH
|
|
55
|
-
} else if (typeof _x === 'number') {
|
|
50
|
+
if (typeof _x === 'number') {
|
|
56
51
|
x = _x
|
|
57
52
|
y = _y!
|
|
58
53
|
w = _w!
|
|
59
54
|
h = _h!
|
|
55
|
+
} else if (typeof _x === 'object') {
|
|
56
|
+
x = _x.x ?? 0
|
|
57
|
+
y = _x.y ?? 0
|
|
58
|
+
w = _x.w ?? dstW
|
|
59
|
+
h = _x.h ?? dstH
|
|
60
60
|
} else {
|
|
61
61
|
x = 0
|
|
62
62
|
y = 0
|