pixel-data-js 0.24.0 → 0.25.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 +1431 -1845
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1297 -1702
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1305 -1719
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +220 -328
- package/dist/index.prod.js +1423 -1828
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/Algorithm/floodFillSelection.ts +2 -2
- package/src/Canvas/canvas-blend-modes.ts +28 -0
- package/src/History/PixelAccumulator.ts +52 -29
- package/src/History/PixelEngineConfig.ts +7 -9
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts +2 -2
- package/src/History/PixelMutator.ts +0 -20
- package/src/History/PixelPatchTiles.ts +2 -2
- package/src/History/PixelWriter.ts +132 -9
- package/src/Internal/helpers.ts +2 -0
- package/src/Paint/PaintBuffer.ts +269 -0
- package/src/{PixelTile/PaintBufferRenderer.ts → Paint/PaintBufferCanvasRenderer.ts} +13 -5
- package/src/Paint/makeCirclePaintAlphaMask.ts +41 -0
- package/src/{Mask/CircleBinaryMask.ts → Paint/makeCirclePaintBinaryMask.ts} +5 -6
- package/src/Paint/makePaintMask.ts +28 -0
- package/src/Paint/makeRectFalloffPaintAlphaMask.ts +47 -0
- package/src/PixelData/PixelBuffer32.ts +2 -2
- package/src/PixelData/PixelData.ts +1 -1
- package/src/PixelData/applyAlphaMaskToPixelData.ts +2 -2
- package/src/PixelData/applyBinaryMaskToPixelData.ts +2 -2
- package/src/PixelData/blendColorPixelData.ts +2 -2
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +3 -3
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/blendPixel.ts +2 -2
- package/src/PixelData/blendPixelData.ts +3 -3
- package/src/PixelData/blendPixelDataAlphaMask.ts +3 -3
- package/src/PixelData/blendPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/blendPixelDataPaintBuffer.ts +3 -3
- package/src/PixelData/clearPixelData.ts +2 -2
- package/src/PixelData/extractPixelData.ts +4 -4
- package/src/PixelData/extractPixelDataBuffer.ts +4 -4
- package/src/PixelData/fillPixelData.ts +5 -5
- package/src/PixelData/fillPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/fillPixelDataFast.ts +5 -5
- package/src/PixelData/invertPixelData.ts +2 -2
- package/src/PixelData/pixelDataToAlphaMask.ts +2 -2
- package/src/PixelData/reflectPixelData.ts +3 -3
- package/src/PixelData/resamplePixelData.ts +2 -2
- package/src/PixelData/writePaintBufferToPixelData.ts +26 -0
- package/src/PixelData/writePixelDataBuffer.ts +5 -5
- package/src/Rect/trimMaskRectBounds.ts +121 -0
- package/src/Rect/trimRectBounds.ts +25 -116
- package/src/_types.ts +16 -15
- package/src/index.ts +9 -24
- package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +0 -182
- package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +0 -59
- package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +0 -172
- package/src/History/PixelMutator/mutatorApplyRectBrush.ts +0 -64
- package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +0 -184
- package/src/History/PixelMutator/mutatorApplyRectPencil.ts +0 -65
- package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +0 -166
- package/src/History/PixelMutator/mutatorBlendColorCircleMask.ts +0 -71
- package/src/Mask/CircleAlphaMask.ts +0 -32
- package/src/PixelData/applyRectBrushToPixelData.ts +0 -98
- package/src/PixelData/blendColorPixelDataCircleMask.ts +0 -92
- package/src/PixelTile/PaintBuffer.ts +0 -122
- package/src/Rect/getCircleBrushOrPencilBounds.ts +0 -43
- package/src/Rect/getCircleBrushOrPencilStrokeBounds.ts +0 -24
- package/src/Rect/getRectBrushOrPencilBounds.ts +0 -38
- package/src/Rect/getRectBrushOrPencilStrokeBounds.ts +0 -26
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AlphaMask,
|
|
3
|
-
type BlendColor32,
|
|
4
|
-
type CircleAlphaMask,
|
|
5
|
-
type Color32,
|
|
6
|
-
type ColorBlendMaskOptions,
|
|
7
|
-
type HistoryMutator,
|
|
8
|
-
MaskType,
|
|
9
|
-
type Rect,
|
|
10
|
-
} from '../../_types'
|
|
11
|
-
import { forEachLinePoint } from '../../Algorithm/forEachLinePoint'
|
|
12
|
-
import { sourceOverPerfect } from '../../BlendModes/blend-modes-perfect'
|
|
13
|
-
import { blendColorPixelDataAlphaMask } from '../../PixelData/blendColorPixelDataAlphaMask'
|
|
14
|
-
import { getCircleBrushOrPencilBounds } from '../../Rect/getCircleBrushOrPencilBounds'
|
|
15
|
-
import { getCircleBrushOrPencilStrokeBounds } from '../../Rect/getCircleBrushOrPencilStrokeBounds'
|
|
16
|
-
import { PixelWriter } from '../PixelWriter'
|
|
17
|
-
|
|
18
|
-
const defaults = {
|
|
19
|
-
forEachLinePoint,
|
|
20
|
-
blendColorPixelDataAlphaMask,
|
|
21
|
-
getCircleBrushOrPencilBounds,
|
|
22
|
-
getCircleBrushOrPencilStrokeBounds,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type Deps = Partial<typeof defaults>
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param deps - @hidden
|
|
29
|
-
*/
|
|
30
|
-
export const mutatorApplyCircleBrushStroke = ((writer: PixelWriter<any>, deps: Deps = defaults) => {
|
|
31
|
-
const {
|
|
32
|
-
forEachLinePoint = defaults.forEachLinePoint,
|
|
33
|
-
blendColorPixelDataAlphaMask = defaults.blendColorPixelDataAlphaMask,
|
|
34
|
-
getCircleBrushOrPencilBounds = defaults.getCircleBrushOrPencilBounds,
|
|
35
|
-
getCircleBrushOrPencilStrokeBounds = defaults.getCircleBrushOrPencilStrokeBounds,
|
|
36
|
-
} = deps
|
|
37
|
-
|
|
38
|
-
const strokeBoundsOut: Rect = {
|
|
39
|
-
x: 0,
|
|
40
|
-
y: 0,
|
|
41
|
-
w: 0,
|
|
42
|
-
h: 0,
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const circleBrushBounds: Rect = {
|
|
46
|
-
x: 0,
|
|
47
|
-
y: 0,
|
|
48
|
-
w: 0,
|
|
49
|
-
h: 0,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const blendColorPixelOptions: ColorBlendMaskOptions = {
|
|
53
|
-
alpha: 255,
|
|
54
|
-
blendFn: sourceOverPerfect,
|
|
55
|
-
x: 0,
|
|
56
|
-
y: 0,
|
|
57
|
-
w: 0,
|
|
58
|
-
h: 0,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const mask = {
|
|
62
|
-
type: MaskType.ALPHA,
|
|
63
|
-
data: null as unknown as Uint8Array,
|
|
64
|
-
w: 0,
|
|
65
|
-
h: 0,
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
applyCircleBrushStroke(
|
|
70
|
-
color: Color32,
|
|
71
|
-
x0: number,
|
|
72
|
-
y0: number,
|
|
73
|
-
x1: number,
|
|
74
|
-
y1: number,
|
|
75
|
-
brush: CircleAlphaMask,
|
|
76
|
-
alpha = 255,
|
|
77
|
-
blendFn: BlendColor32 = sourceOverPerfect,
|
|
78
|
-
) {
|
|
79
|
-
const brushSize = brush.size
|
|
80
|
-
|
|
81
|
-
const {
|
|
82
|
-
x: bx,
|
|
83
|
-
y: by,
|
|
84
|
-
w: bw,
|
|
85
|
-
h: bh,
|
|
86
|
-
} = getCircleBrushOrPencilStrokeBounds(
|
|
87
|
-
x0,
|
|
88
|
-
y0,
|
|
89
|
-
x1,
|
|
90
|
-
y1,
|
|
91
|
-
brushSize,
|
|
92
|
-
strokeBoundsOut,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
if (bw <= 0 || bh <= 0) return
|
|
96
|
-
|
|
97
|
-
mask.data = new Uint8Array(bw * bh)
|
|
98
|
-
mask.w = bw
|
|
99
|
-
mask.h = bh
|
|
100
|
-
|
|
101
|
-
const maskData = mask.data
|
|
102
|
-
const brushData = brush.data
|
|
103
|
-
const minOffset = brush.minOffset
|
|
104
|
-
|
|
105
|
-
const target = writer.config.target
|
|
106
|
-
const targetWidth = target.width
|
|
107
|
-
const targetHeight = target.height
|
|
108
|
-
|
|
109
|
-
forEachLinePoint(
|
|
110
|
-
x0,
|
|
111
|
-
y0,
|
|
112
|
-
x1,
|
|
113
|
-
y1,
|
|
114
|
-
(px, py) => {
|
|
115
|
-
const {
|
|
116
|
-
x: cbx,
|
|
117
|
-
y: cby,
|
|
118
|
-
w: cbw,
|
|
119
|
-
h: cbh,
|
|
120
|
-
} = getCircleBrushOrPencilBounds(
|
|
121
|
-
px,
|
|
122
|
-
py,
|
|
123
|
-
brushSize,
|
|
124
|
-
targetWidth,
|
|
125
|
-
targetHeight,
|
|
126
|
-
circleBrushBounds,
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
writer.accumulator.storeRegionBeforeState(
|
|
130
|
-
cbx,
|
|
131
|
-
cby,
|
|
132
|
-
cbw,
|
|
133
|
-
cbh,
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
const startX = Math.max(bx, cbx)
|
|
137
|
-
const startY = Math.max(by, cby)
|
|
138
|
-
const endX = Math.min(bx + bw, cbx + cbw)
|
|
139
|
-
const endY = Math.min(by + bh, cby + cbh)
|
|
140
|
-
|
|
141
|
-
const unclippedStartX = Math.floor(px + minOffset)
|
|
142
|
-
const unclippedStartY = Math.floor(py + minOffset)
|
|
143
|
-
|
|
144
|
-
for (let my = startY; my < endY; my++) {
|
|
145
|
-
const strokeMaskY = my - by
|
|
146
|
-
const strokeMaskRowOffset = strokeMaskY * bw
|
|
147
|
-
|
|
148
|
-
const brushY = my - unclippedStartY
|
|
149
|
-
const brushRowOffset = brushY * brushSize
|
|
150
|
-
|
|
151
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
152
|
-
const brushX = mx - unclippedStartX
|
|
153
|
-
const brushVal = brushData[brushRowOffset + brushX]
|
|
154
|
-
|
|
155
|
-
if (brushVal > 0) {
|
|
156
|
-
const strokeMaskIdx = strokeMaskRowOffset + (mx - bx)
|
|
157
|
-
|
|
158
|
-
if (brushVal > maskData[strokeMaskIdx]) {
|
|
159
|
-
maskData[strokeMaskIdx] = brushVal
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
blendColorPixelOptions.blendFn = blendFn
|
|
168
|
-
blendColorPixelOptions.alpha = alpha
|
|
169
|
-
blendColorPixelOptions.x = bx
|
|
170
|
-
blendColorPixelOptions.y = by
|
|
171
|
-
blendColorPixelOptions.w = bw
|
|
172
|
-
blendColorPixelOptions.h = bh
|
|
173
|
-
|
|
174
|
-
blendColorPixelDataAlphaMask(
|
|
175
|
-
target,
|
|
176
|
-
color,
|
|
177
|
-
mask as AlphaMask,
|
|
178
|
-
blendColorPixelOptions,
|
|
179
|
-
)
|
|
180
|
-
},
|
|
181
|
-
}
|
|
182
|
-
}) satisfies HistoryMutator<any, Deps>
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { BlendColor32, CircleMask, Color32, HistoryMutator, Rect } from '../../_types'
|
|
2
|
-
import { blendColorPixelDataCircleMask } from '../../PixelData/blendColorPixelDataCircleMask'
|
|
3
|
-
import { getCircleBrushOrPencilBounds } from '../../Rect/getCircleBrushOrPencilBounds'
|
|
4
|
-
import { PixelWriter } from '../PixelWriter'
|
|
5
|
-
|
|
6
|
-
const defaults = {
|
|
7
|
-
applyCircleMaskToPixelData: blendColorPixelDataCircleMask,
|
|
8
|
-
getCircleBrushOrPencilBounds,
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
type Deps = Partial<typeof defaults>
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @param deps - @hidden
|
|
15
|
-
**/
|
|
16
|
-
export const mutatorApplyCirclePencil = ((writer: PixelWriter<any>, deps: Deps = defaults) => {
|
|
17
|
-
const {
|
|
18
|
-
applyCircleMaskToPixelData = defaults.applyCircleMaskToPixelData,
|
|
19
|
-
getCircleBrushOrPencilBounds = defaults.getCircleBrushOrPencilBounds,
|
|
20
|
-
} = deps
|
|
21
|
-
|
|
22
|
-
const boundsOut: Rect = { x: 0, y: 0, w: 0, h: 0 }
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
applyCirclePencil(
|
|
26
|
-
color: Color32,
|
|
27
|
-
centerX: number,
|
|
28
|
-
centerY: number,
|
|
29
|
-
brush: CircleMask,
|
|
30
|
-
alpha = 255,
|
|
31
|
-
blendFn?: BlendColor32,
|
|
32
|
-
): boolean {
|
|
33
|
-
|
|
34
|
-
const target = writer.config.target
|
|
35
|
-
const b = getCircleBrushOrPencilBounds(
|
|
36
|
-
centerX,
|
|
37
|
-
centerY,
|
|
38
|
-
brush.size,
|
|
39
|
-
target.width,
|
|
40
|
-
target.height,
|
|
41
|
-
boundsOut,
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h)
|
|
45
|
-
return didChange(
|
|
46
|
-
applyCircleMaskToPixelData(
|
|
47
|
-
target,
|
|
48
|
-
color,
|
|
49
|
-
centerX,
|
|
50
|
-
centerY,
|
|
51
|
-
brush,
|
|
52
|
-
alpha,
|
|
53
|
-
blendFn,
|
|
54
|
-
b,
|
|
55
|
-
),
|
|
56
|
-
)
|
|
57
|
-
},
|
|
58
|
-
}
|
|
59
|
-
}) satisfies HistoryMutator<any, Deps>
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type BinaryMask,
|
|
3
|
-
type BlendColor32,
|
|
4
|
-
type CircleBinaryMask,
|
|
5
|
-
type Color32,
|
|
6
|
-
type ColorBlendMaskOptions,
|
|
7
|
-
type HistoryMutator,
|
|
8
|
-
MaskType,
|
|
9
|
-
type Rect,
|
|
10
|
-
} from '../../_types'
|
|
11
|
-
import { forEachLinePoint } from '../../Algorithm/forEachLinePoint'
|
|
12
|
-
import { sourceOverPerfect } from '../../BlendModes/blend-modes-perfect'
|
|
13
|
-
import { blendColorPixelDataBinaryMask } from '../../PixelData/blendColorPixelDataBinaryMask'
|
|
14
|
-
import { getCircleBrushOrPencilBounds } from '../../Rect/getCircleBrushOrPencilBounds'
|
|
15
|
-
import { getCircleBrushOrPencilStrokeBounds } from '../../Rect/getCircleBrushOrPencilStrokeBounds'
|
|
16
|
-
import { PixelWriter } from '../PixelWriter'
|
|
17
|
-
|
|
18
|
-
const defaults = {
|
|
19
|
-
forEachLinePoint,
|
|
20
|
-
blendColorPixelDataBinaryMask,
|
|
21
|
-
getCircleBrushOrPencilBounds,
|
|
22
|
-
getCircleBrushOrPencilStrokeBounds,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type Deps = Partial<typeof defaults>
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param deps - @hidden
|
|
29
|
-
*/
|
|
30
|
-
export const mutatorApplyCirclePencilStroke = ((writer: PixelWriter<any>, deps: Deps = defaults) => {
|
|
31
|
-
const {
|
|
32
|
-
forEachLinePoint = defaults.forEachLinePoint,
|
|
33
|
-
blendColorPixelDataBinaryMask = defaults.blendColorPixelDataBinaryMask,
|
|
34
|
-
getCircleBrushOrPencilStrokeBounds = defaults.getCircleBrushOrPencilStrokeBounds,
|
|
35
|
-
getCircleBrushOrPencilBounds = defaults.getCircleBrushOrPencilBounds,
|
|
36
|
-
} = deps
|
|
37
|
-
|
|
38
|
-
const strokeBoundsOut: Rect = {
|
|
39
|
-
x: 0,
|
|
40
|
-
y: 0,
|
|
41
|
-
w: 0,
|
|
42
|
-
h: 0,
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const circlePencilBounds: Rect = {
|
|
46
|
-
x: 0,
|
|
47
|
-
y: 0,
|
|
48
|
-
w: 0,
|
|
49
|
-
h: 0,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const blendColorPixelOptions: ColorBlendMaskOptions = {
|
|
53
|
-
alpha: 255,
|
|
54
|
-
blendFn: sourceOverPerfect,
|
|
55
|
-
x: 0,
|
|
56
|
-
y: 0,
|
|
57
|
-
w: 0,
|
|
58
|
-
h: 0,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const mask = {
|
|
62
|
-
type: MaskType.BINARY,
|
|
63
|
-
data: null as unknown as Uint8Array,
|
|
64
|
-
w: 0,
|
|
65
|
-
h: 0,
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
applyCirclePencilStroke(
|
|
70
|
-
color: Color32,
|
|
71
|
-
x0: number,
|
|
72
|
-
y0: number,
|
|
73
|
-
x1: number,
|
|
74
|
-
y1: number,
|
|
75
|
-
brush: CircleBinaryMask,
|
|
76
|
-
alpha = 255,
|
|
77
|
-
blendFn: BlendColor32 = sourceOverPerfect,
|
|
78
|
-
) {
|
|
79
|
-
const {
|
|
80
|
-
x: bx,
|
|
81
|
-
y: by,
|
|
82
|
-
w: bw,
|
|
83
|
-
h: bh,
|
|
84
|
-
} = getCircleBrushOrPencilStrokeBounds(
|
|
85
|
-
x0,
|
|
86
|
-
y0,
|
|
87
|
-
x1,
|
|
88
|
-
y1,
|
|
89
|
-
brush.size,
|
|
90
|
-
strokeBoundsOut,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
if (bw <= 0 || bh <= 0) return
|
|
94
|
-
|
|
95
|
-
mask.data = new Uint8Array(bw * bh)
|
|
96
|
-
mask.w = bw
|
|
97
|
-
mask.h = bh
|
|
98
|
-
|
|
99
|
-
const maskData = mask.data
|
|
100
|
-
const target = writer.config.target
|
|
101
|
-
const targetWidth = target.width
|
|
102
|
-
const targetHeight = target.height
|
|
103
|
-
|
|
104
|
-
forEachLinePoint(
|
|
105
|
-
x0,
|
|
106
|
-
y0,
|
|
107
|
-
x1,
|
|
108
|
-
y1,
|
|
109
|
-
(px, py) => {
|
|
110
|
-
const {
|
|
111
|
-
x: cbx,
|
|
112
|
-
y: cby,
|
|
113
|
-
w: cbw,
|
|
114
|
-
h: cbh,
|
|
115
|
-
} = getCircleBrushOrPencilBounds(
|
|
116
|
-
px,
|
|
117
|
-
py,
|
|
118
|
-
brush.size,
|
|
119
|
-
targetWidth,
|
|
120
|
-
targetHeight,
|
|
121
|
-
circlePencilBounds,
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
writer.accumulator.storeRegionBeforeState(
|
|
125
|
-
cbx,
|
|
126
|
-
cby,
|
|
127
|
-
cbw,
|
|
128
|
-
cbh,
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
const unclippedStartX = Math.floor(px + brush.minOffset)
|
|
132
|
-
const unclippedStartY = Math.floor(py + brush.minOffset)
|
|
133
|
-
|
|
134
|
-
const startX = Math.max(bx, unclippedStartX)
|
|
135
|
-
const startY = Math.max(by, unclippedStartY)
|
|
136
|
-
const endX = Math.min(bx + bw, unclippedStartX + brush.w)
|
|
137
|
-
const endY = Math.min(by + bh, unclippedStartY + brush.h)
|
|
138
|
-
|
|
139
|
-
for (let my = startY; my < endY; my++) {
|
|
140
|
-
const brushY = my - unclippedStartY
|
|
141
|
-
const maskRowOffset = (my - by) * bw
|
|
142
|
-
const brushRowOffset = brushY * brush.w
|
|
143
|
-
|
|
144
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
145
|
-
const brushX = mx - unclippedStartX
|
|
146
|
-
const brushAlpha = brush.data[brushRowOffset + brushX]
|
|
147
|
-
|
|
148
|
-
if (brushAlpha > 0) {
|
|
149
|
-
const maskIdx = maskRowOffset + (mx - bx)
|
|
150
|
-
maskData[maskIdx] = brushAlpha
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
blendColorPixelOptions.blendFn = blendFn
|
|
158
|
-
blendColorPixelOptions.alpha = alpha
|
|
159
|
-
blendColorPixelOptions.x = bx
|
|
160
|
-
blendColorPixelOptions.y = by
|
|
161
|
-
blendColorPixelOptions.w = bw
|
|
162
|
-
blendColorPixelOptions.h = bh
|
|
163
|
-
|
|
164
|
-
blendColorPixelDataBinaryMask(
|
|
165
|
-
target,
|
|
166
|
-
color,
|
|
167
|
-
mask as BinaryMask,
|
|
168
|
-
blendColorPixelOptions,
|
|
169
|
-
)
|
|
170
|
-
},
|
|
171
|
-
}
|
|
172
|
-
}) satisfies HistoryMutator<any, Deps>
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import type { BlendColor32, Color32, HistoryMutator, Rect } from '../../_types'
|
|
2
|
-
import { applyRectBrushToPixelData } from '../../PixelData/applyRectBrushToPixelData'
|
|
3
|
-
import { getRectBrushOrPencilBounds } from '../../Rect/getRectBrushOrPencilBounds'
|
|
4
|
-
import { PixelWriter } from '../PixelWriter'
|
|
5
|
-
|
|
6
|
-
const defaults = {
|
|
7
|
-
applyRectBrushToPixelData,
|
|
8
|
-
getRectBrushOrPencilBounds,
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
type Deps = Partial<typeof defaults>
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @param deps - @hidden
|
|
15
|
-
*/
|
|
16
|
-
export const mutatorApplyRectBrush = ((writer: PixelWriter<any>, deps: Deps = defaults) => {
|
|
17
|
-
const {
|
|
18
|
-
applyRectBrushToPixelData = defaults.applyRectBrushToPixelData,
|
|
19
|
-
getRectBrushOrPencilBounds = defaults.getRectBrushOrPencilBounds,
|
|
20
|
-
} = deps
|
|
21
|
-
|
|
22
|
-
const boundsOut: Rect = { x: 0, y: 0, w: 0, h: 0 }
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
applyRectBrush(
|
|
26
|
-
color: Color32,
|
|
27
|
-
centerX: number,
|
|
28
|
-
centerY: number,
|
|
29
|
-
brushWidth: number,
|
|
30
|
-
brushHeight: number,
|
|
31
|
-
alpha = 255,
|
|
32
|
-
fallOff: (dist: number) => number,
|
|
33
|
-
blendFn?: BlendColor32,
|
|
34
|
-
): boolean {
|
|
35
|
-
|
|
36
|
-
const target = writer.config.target
|
|
37
|
-
const b = getRectBrushOrPencilBounds(
|
|
38
|
-
centerX,
|
|
39
|
-
centerY,
|
|
40
|
-
brushWidth,
|
|
41
|
-
brushHeight,
|
|
42
|
-
target.width,
|
|
43
|
-
target.height,
|
|
44
|
-
boundsOut,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
const didChange = writer.accumulator.storeRegionBeforeState(b.x, b.y, b.w, b.h)
|
|
48
|
-
return didChange(
|
|
49
|
-
applyRectBrushToPixelData(
|
|
50
|
-
target,
|
|
51
|
-
color,
|
|
52
|
-
centerX,
|
|
53
|
-
centerY,
|
|
54
|
-
brushWidth,
|
|
55
|
-
brushHeight,
|
|
56
|
-
alpha,
|
|
57
|
-
fallOff,
|
|
58
|
-
blendFn,
|
|
59
|
-
b,
|
|
60
|
-
),
|
|
61
|
-
)
|
|
62
|
-
},
|
|
63
|
-
}
|
|
64
|
-
}) satisfies HistoryMutator<any, Deps>
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AlphaMask,
|
|
3
|
-
type BlendColor32,
|
|
4
|
-
type Color32,
|
|
5
|
-
type ColorBlendOptions,
|
|
6
|
-
type HistoryMutator,
|
|
7
|
-
MaskType,
|
|
8
|
-
type Rect,
|
|
9
|
-
} from '../../_types'
|
|
10
|
-
import { forEachLinePoint } from '../../Algorithm/forEachLinePoint'
|
|
11
|
-
import { sourceOverPerfect } from '../../BlendModes/blend-modes-perfect'
|
|
12
|
-
import { blendColorPixelDataAlphaMask } from '../../PixelData/blendColorPixelDataAlphaMask'
|
|
13
|
-
import { getRectBrushOrPencilBounds } from '../../Rect/getRectBrushOrPencilBounds'
|
|
14
|
-
import { getRectBrushOrPencilStrokeBounds } from '../../Rect/getRectBrushOrPencilStrokeBounds'
|
|
15
|
-
import { PixelWriter } from '../PixelWriter'
|
|
16
|
-
|
|
17
|
-
const defaults = {
|
|
18
|
-
forEachLinePoint,
|
|
19
|
-
blendColorPixelDataAlphaMask,
|
|
20
|
-
getRectBrushOrPencilBounds,
|
|
21
|
-
getRectBrushOrPencilStrokeBounds,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
type Deps = Partial<typeof defaults>
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param deps - @hidden
|
|
28
|
-
*/
|
|
29
|
-
export const mutatorApplyRectBrushStroke = ((writer: PixelWriter<any>, deps: Deps = defaults) => {
|
|
30
|
-
const {
|
|
31
|
-
forEachLinePoint = defaults.forEachLinePoint,
|
|
32
|
-
blendColorPixelDataAlphaMask = defaults.blendColorPixelDataAlphaMask,
|
|
33
|
-
getRectBrushOrPencilBounds = defaults.getRectBrushOrPencilBounds,
|
|
34
|
-
getRectBrushOrPencilStrokeBounds = defaults.getRectBrushOrPencilStrokeBounds,
|
|
35
|
-
} = deps
|
|
36
|
-
|
|
37
|
-
const strokeBoundsOut: Rect = {
|
|
38
|
-
x: 0,
|
|
39
|
-
y: 0,
|
|
40
|
-
w: 0,
|
|
41
|
-
h: 0,
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const rectBrushBounds: Rect = {
|
|
45
|
-
x: 0,
|
|
46
|
-
y: 0,
|
|
47
|
-
w: 0,
|
|
48
|
-
h: 0,
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const blendColorPixelOptions: ColorBlendOptions = {
|
|
52
|
-
alpha: 255,
|
|
53
|
-
blendFn: sourceOverPerfect,
|
|
54
|
-
x: 0,
|
|
55
|
-
y: 0,
|
|
56
|
-
w: 0,
|
|
57
|
-
h: 0,
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const mask = {
|
|
61
|
-
type: MaskType.ALPHA,
|
|
62
|
-
data: null as unknown as Uint8Array,
|
|
63
|
-
w: 0,
|
|
64
|
-
h: 0,
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
applyRectBrushStroke(
|
|
69
|
-
color: Color32,
|
|
70
|
-
x0: number,
|
|
71
|
-
y0: number,
|
|
72
|
-
x1: number,
|
|
73
|
-
y1: number,
|
|
74
|
-
brushWidth: number,
|
|
75
|
-
brushHeight: number,
|
|
76
|
-
alpha = 255,
|
|
77
|
-
fallOff: (dist: number) => number,
|
|
78
|
-
blendFn: BlendColor32 = sourceOverPerfect,
|
|
79
|
-
) {
|
|
80
|
-
const {
|
|
81
|
-
x: bx,
|
|
82
|
-
y: by,
|
|
83
|
-
w: bw,
|
|
84
|
-
h: bh,
|
|
85
|
-
} = getRectBrushOrPencilStrokeBounds(
|
|
86
|
-
x0,
|
|
87
|
-
y0,
|
|
88
|
-
x1,
|
|
89
|
-
y1,
|
|
90
|
-
brushWidth,
|
|
91
|
-
brushHeight,
|
|
92
|
-
strokeBoundsOut,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
if (bw <= 0 || bh <= 0) return
|
|
96
|
-
|
|
97
|
-
mask.data = new Uint8Array(bw * bh)
|
|
98
|
-
mask.w = bw
|
|
99
|
-
mask.h = bh
|
|
100
|
-
|
|
101
|
-
const maskData = mask.data
|
|
102
|
-
const halfW = brushWidth / 2
|
|
103
|
-
const halfH = brushHeight / 2
|
|
104
|
-
const invHalfW = 1 / halfW
|
|
105
|
-
const invHalfH = 1 / halfH
|
|
106
|
-
|
|
107
|
-
// Restore the pixel-art centering logic
|
|
108
|
-
const centerOffsetX = (brushWidth % 2 === 0) ? 0.5 : 0
|
|
109
|
-
const centerOffsetY = (brushHeight % 2 === 0) ? 0.5 : 0
|
|
110
|
-
|
|
111
|
-
const target = writer.config.target
|
|
112
|
-
const targetWidth = target.width
|
|
113
|
-
const targetHeight = target.height
|
|
114
|
-
|
|
115
|
-
forEachLinePoint(x0, y0, x1, y1, (px, py) => {
|
|
116
|
-
const {
|
|
117
|
-
x: rbx,
|
|
118
|
-
y: rby,
|
|
119
|
-
w: rbw,
|
|
120
|
-
h: rbh,
|
|
121
|
-
} = getRectBrushOrPencilBounds(
|
|
122
|
-
px,
|
|
123
|
-
py,
|
|
124
|
-
brushWidth,
|
|
125
|
-
brushHeight,
|
|
126
|
-
targetWidth,
|
|
127
|
-
targetHeight,
|
|
128
|
-
rectBrushBounds,
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
writer.accumulator.storeRegionBeforeState(
|
|
132
|
-
rbx,
|
|
133
|
-
rby,
|
|
134
|
-
rbw,
|
|
135
|
-
rbh,
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
const startX = Math.max(bx, rbx)
|
|
139
|
-
const startY = Math.max(by, rby)
|
|
140
|
-
const endX = Math.min(bx + bw, rbx + rbw)
|
|
141
|
-
const endY = Math.min(by + bh, rby + rbh)
|
|
142
|
-
|
|
143
|
-
// Snapped origin for this specific point on the line
|
|
144
|
-
const fPx = Math.floor(px)
|
|
145
|
-
const fPy = Math.floor(py)
|
|
146
|
-
|
|
147
|
-
for (let my = startY; my < endY; my++) {
|
|
148
|
-
const dy = Math.abs((my - fPy) + centerOffsetY) * invHalfH
|
|
149
|
-
const maskRowOffset = (my - by) * bw
|
|
150
|
-
|
|
151
|
-
for (let mx = startX; mx < endX; mx++) {
|
|
152
|
-
const dx = Math.abs((mx - fPx) + centerOffsetX) * invHalfW
|
|
153
|
-
const maskIdx = maskRowOffset + (mx - bx)
|
|
154
|
-
|
|
155
|
-
const dist = dx > dy ? dx : dy
|
|
156
|
-
const strength = fallOff!(dist)
|
|
157
|
-
|
|
158
|
-
if (strength > 0) {
|
|
159
|
-
const intensity = (strength * 255) | 0
|
|
160
|
-
|
|
161
|
-
if (intensity > maskData[maskIdx]) {
|
|
162
|
-
maskData[maskIdx] = intensity
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
blendColorPixelOptions.blendFn = blendFn
|
|
170
|
-
blendColorPixelOptions.alpha = alpha
|
|
171
|
-
blendColorPixelOptions.x = bx
|
|
172
|
-
blendColorPixelOptions.y = by
|
|
173
|
-
blendColorPixelOptions.w = bw
|
|
174
|
-
blendColorPixelOptions.h = bh
|
|
175
|
-
|
|
176
|
-
blendColorPixelDataAlphaMask(
|
|
177
|
-
target,
|
|
178
|
-
color,
|
|
179
|
-
mask as AlphaMask,
|
|
180
|
-
blendColorPixelOptions,
|
|
181
|
-
)
|
|
182
|
-
},
|
|
183
|
-
}
|
|
184
|
-
}) satisfies HistoryMutator<any, Deps>
|