pixel-data-js 0.18.0 → 0.19.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.
Files changed (77) hide show
  1. package/README.md +6 -1
  2. package/dist/index.dev.cjs +2723 -1487
  3. package/dist/index.dev.cjs.map +1 -1
  4. package/dist/index.dev.js +2690 -1481
  5. package/dist/index.dev.js.map +1 -1
  6. package/dist/index.prod.cjs +2723 -1487
  7. package/dist/index.prod.cjs.map +1 -1
  8. package/dist/index.prod.d.ts +400 -246
  9. package/dist/index.prod.js +2690 -1481
  10. package/dist/index.prod.js.map +1 -1
  11. package/package.json +21 -6
  12. package/src/Algorithm/forEachLinePoint.ts +36 -0
  13. package/src/BlendModes/BlendModeRegistry.ts +2 -0
  14. package/src/BlendModes/blend-modes-fast.ts +2 -2
  15. package/src/BlendModes/blend-modes-perfect.ts +5 -4
  16. package/src/BlendModes/toBlendModeIndexAndName.ts +41 -0
  17. package/src/History/PixelAccumulator.ts +2 -2
  18. package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +30 -0
  19. package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +30 -0
  20. package/src/History/PixelMutator/mutatorApplyCircleBrush.ts +23 -9
  21. package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +138 -0
  22. package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +59 -0
  23. package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +131 -0
  24. package/src/History/PixelMutator/mutatorApplyRectBrush.ts +20 -7
  25. package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +169 -0
  26. package/src/History/PixelMutator/mutatorApplyRectPencil.ts +62 -0
  27. package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +149 -0
  28. package/src/History/PixelMutator/mutatorBlendColor.ts +9 -4
  29. package/src/History/PixelMutator/mutatorBlendPixelData.ts +10 -5
  30. package/src/History/PixelMutator/mutatorClear.ts +27 -0
  31. package/src/History/PixelMutator/{mutatorFillPixelData.ts → mutatorFill.ts} +9 -3
  32. package/src/History/PixelMutator/mutatorInvert.ts +10 -3
  33. package/src/History/PixelMutator.ts +23 -3
  34. package/src/History/PixelPatchTiles.ts +2 -2
  35. package/src/History/PixelWriter.ts +3 -3
  36. package/src/ImageData/ImageDataLike.ts +13 -0
  37. package/src/ImageData/extractImageDataBuffer.ts +22 -15
  38. package/src/ImageData/serialization.ts +4 -4
  39. package/src/ImageData/uInt32ArrayToImageData.ts +29 -0
  40. package/src/ImageData/writeImageData.ts +26 -18
  41. package/src/ImageData/writeImageDataBuffer.ts +30 -18
  42. package/src/IndexedImage/indexedImageToAverageColor.ts +1 -1
  43. package/src/Internal/resolveClipping.ts +140 -0
  44. package/src/Mask/applyBinaryMaskToAlphaMask.ts +89 -0
  45. package/src/Mask/copyMask.ts +1 -3
  46. package/src/Mask/mergeAlphaMasks.ts +81 -0
  47. package/src/Mask/mergeBinaryMasks.ts +89 -0
  48. package/src/PixelData/PixelBuffer32.ts +28 -0
  49. package/src/PixelData/PixelData.ts +38 -33
  50. package/src/PixelData/applyAlphaMaskToPixelData.ts +119 -0
  51. package/src/PixelData/applyBinaryMaskToPixelData.ts +111 -0
  52. package/src/PixelData/applyCircleBrushToPixelData.ts +31 -56
  53. package/src/PixelData/applyRectBrushToPixelData.ts +39 -71
  54. package/src/PixelData/blendColorPixelData.ts +18 -111
  55. package/src/PixelData/blendColorPixelDataAlphaMask.ts +111 -0
  56. package/src/PixelData/blendColorPixelDataBinaryMask.ts +89 -0
  57. package/src/PixelData/blendPixelData.ts +19 -107
  58. package/src/PixelData/blendPixelDataAlphaMask.ts +149 -0
  59. package/src/PixelData/blendPixelDataBinaryMask.ts +133 -0
  60. package/src/PixelData/clearPixelData.ts +2 -3
  61. package/src/PixelData/extractPixelData.ts +4 -4
  62. package/src/PixelData/extractPixelDataBuffer.ts +38 -26
  63. package/src/PixelData/fillPixelData.ts +18 -20
  64. package/src/PixelData/invertPixelData.ts +13 -21
  65. package/src/PixelData/pixelDataToAlphaMask.ts +2 -3
  66. package/src/PixelData/reflectPixelData.ts +3 -3
  67. package/src/PixelData/resamplePixelData.ts +2 -6
  68. package/src/PixelData/writePixelDataBuffer.ts +34 -20
  69. package/src/Rect/getCircleBrushOrPencilBounds.ts +43 -0
  70. package/src/Rect/getCircleBrushOrPencilStrokeBounds.ts +24 -0
  71. package/src/Rect/getRectBrushOrPencilBounds.ts +38 -0
  72. package/src/Rect/getRectBrushOrPencilStrokeBounds.ts +26 -0
  73. package/src/_types.ts +49 -33
  74. package/src/index.ts +47 -11
  75. package/src/History/PixelMutator/mutatorApplyMask.ts +0 -20
  76. package/src/Mask/mergeMasks.ts +0 -100
  77. package/src/PixelData/applyMaskToPixelData.ts +0 -129
package/src/_types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { sourceOverFast } from './BlendModes/blend-modes-fast'
1
+ import { PixelWriter, sourceOverPerfect } from './index'
2
2
 
3
3
  /** ALL values are 0-255 (including alpha which in CSS is 0-1) */
4
4
  export type RGBA = { r: number, g: number, b: number, a: number }
@@ -23,6 +23,14 @@ export type ImageDataLike = {
23
23
  data: Uint8ClampedArray<ArrayBufferLike>
24
24
  }
25
25
 
26
+ export type ImageDataLikeConstructor<T extends ImageDataLike = ImageDataLike> = {
27
+ new(
28
+ data: Uint8ClampedArray,
29
+ width: number,
30
+ height: number,
31
+ ): T
32
+ }
33
+
26
34
  export type SerializedImageData = {
27
35
  width: number
28
36
  height: number
@@ -66,7 +74,7 @@ export type AnyMask = BinaryMask | AlphaMask
66
74
  * Configuration for pixel manipulation operations.
67
75
  * Designed to be used by spreading a Rect object ({x, y, w, h}) directly.
68
76
  */
69
- export interface PixelRectOptions {
77
+ export interface PixelRect {
70
78
  /**
71
79
  * The starting X coordinate in the destination buffer.
72
80
  * @default 0
@@ -80,26 +88,19 @@ export interface PixelRectOptions {
80
88
  y?: number
81
89
 
82
90
  /**
83
- * The width of the region to process.
91
+ * The width of the region in the destination buffer.
84
92
  * @default Source width.
85
93
  */
86
94
  w?: number
87
95
 
88
96
  /**
89
- * The height of the region to process.
97
+ * The height of the region in the destination buffer.
90
98
  * @default Source height.
91
99
  */
92
100
  h?: number
93
101
  }
94
102
 
95
- export interface PixelMaskRectOptions {
96
-
97
- /**
98
- * Mask width.
99
- * @default value of `w`
100
- */
101
- mw?: number
102
-
103
+ export interface MaskOffset {
103
104
  /**
104
105
  * X offset into the mask buffer.
105
106
  * @default 0
@@ -113,7 +114,15 @@ export interface PixelMaskRectOptions {
113
114
  my?: number
114
115
  }
115
116
 
116
- export interface PixelMaskInvertOptions {
117
+ export interface MaskOffsetWidth {
118
+ /**
119
+ * Mask width.
120
+ * @default value of `w`
121
+ */
122
+ mw?: number
123
+ }
124
+
125
+ export interface InvertMask {
117
126
 
118
127
  /**
119
128
  * If true the inverse of the mask will be applied
@@ -122,27 +131,22 @@ export interface PixelMaskInvertOptions {
122
131
  invertMask?: boolean
123
132
  }
124
133
 
125
- /**
126
- * Configuration for pixel manipulation operations.
127
- * Designed to be used by spreading a Rect object ({x, y, w, h}) directly.
128
- */
129
- export interface PixelOptions extends PixelRectOptions, PixelMaskRectOptions, PixelMaskInvertOptions {
134
+ export interface Alpha {
130
135
  /**
131
136
  * Overall layer opacity 0-255.
132
137
  * @default 255
133
138
  */
134
139
  alpha?: number
140
+ }
141
+
142
+ export interface ApplyMaskToPixelDataOptions extends PixelRect, Alpha, MaskOffsetWidth, MaskOffset, InvertMask {
143
+ }
135
144
 
136
- /** An optional mask to restrict where pixels are written. */
137
- mask?: AnyMask | null
145
+ export interface MergeAlphaMasksOptions extends PixelRect, Alpha, MaskOffset, InvertMask {
138
146
 
139
- /** The interpretation logic for the provided mask.
140
- * @default {@link MaskType.ALPHA}
141
- */
142
- maskType?: MaskType
143
147
  }
144
148
 
145
- export interface PixelMutateOptions extends PixelRectOptions, PixelMaskRectOptions, PixelMaskInvertOptions {
149
+ export interface PixelMutateOptions extends PixelRect, MaskOffset, MaskOffsetWidth, InvertMask {
146
150
  /** An optional mask to restrict where pixels are mutated. */
147
151
  mask?: BinaryMask | null
148
152
  }
@@ -150,7 +154,8 @@ export interface PixelMutateOptions extends PixelRectOptions, PixelMaskRectOptio
150
154
  /**
151
155
  * Configuration for blitting (copying/blending) one image into another.
152
156
  */
153
- export interface PixelBlendOptions extends PixelOptions {
157
+
158
+ export interface BasePixelBlendOptions {
154
159
  /**
155
160
  * The source rectangle x-coordinate
156
161
  * @default 0
@@ -165,23 +170,31 @@ export interface PixelBlendOptions extends PixelOptions {
165
170
 
166
171
  /**
167
172
  * The blending algorithm to use for blending pixels.
168
- * @default {@link sourceOverFast}
173
+ * @default {@link sourceOverPerfect}
169
174
  */
170
175
  blendFn?: BlendColor32
171
176
  }
172
177
 
178
+ export interface PixelBlendOptions extends PixelRect, Alpha, BasePixelBlendOptions {
179
+
180
+ }
181
+
182
+ export interface PixelBlendMaskOptions extends PixelRect, Alpha, MaskOffsetWidth, MaskOffset, InvertMask, BasePixelBlendOptions {
183
+ }
184
+
173
185
  /**
174
186
  * Configuration for operations that require color blending.
175
187
  */
176
- export interface ColorBlendOptions extends PixelOptions {
188
+ export interface ColorBlendOptions extends PixelRect, Alpha {
177
189
  /**
178
190
  * The blending algorithm to use for blending pixels.
179
- * @default {@link sourceOverFast}
191
+ * @default {@link sourceOverPerfect}
180
192
  */
181
193
  blendFn?: BlendColor32
182
194
  }
183
195
 
184
- export type ApplyMaskOptions = Omit<PixelOptions, 'mask'>
196
+ export interface ColorBlendMaskOptions extends ColorBlendOptions, MaskOffset, MaskOffsetWidth, InvertMask {
197
+ }
185
198
 
186
199
  export type SelectionRect = Rect & ({
187
200
  mask: Uint8Array,
@@ -191,7 +204,10 @@ export type SelectionRect = Rect & ({
191
204
  maskType?: null,
192
205
  })
193
206
 
194
- export type Point = {
195
- x: number,
196
- y: number,
207
+ export type HistoryMutator<T extends {}, D extends {}> = (writer: PixelWriter<any>, deps?: Partial<D>) => T
208
+
209
+ export interface IPixelData {
210
+ readonly data32: Uint32Array
211
+ readonly width: number
212
+ readonly height: number
197
213
  }
package/src/index.ts CHANGED
@@ -1,13 +1,16 @@
1
+ // @sort-all
1
2
  export * from './_types'
2
3
  export * from './color'
3
4
 
4
5
  export * from './Algorithm/floodFillSelection'
5
6
 
6
- export * from './BlendModes/BlendModeRegistry'
7
- export * from './BlendModes/blend-modes'
8
7
  export * from './BlendModes/blend-modes-fast'
9
8
  export * from './BlendModes/blend-modes-perfect'
9
+ export * from './BlendModes/blend-modes'
10
+ export * from './BlendModes/BlendModeRegistry'
11
+ export * from './BlendModes/toBlendModeIndexAndName'
10
12
 
13
+ export * from './Canvas/_constants'
11
14
  export * from './Canvas/PixelCanvas'
12
15
  export * from './Canvas/ReusableCanvas'
13
16
 
@@ -15,23 +18,38 @@ export * from './Clipboard/getImageDataFromClipboard'
15
18
  export * from './Clipboard/writeImageDataToClipboard'
16
19
  export * from './Clipboard/writeImgBlobToClipboard'
17
20
 
18
- export * from './History/PixelAccumulator'
19
21
  export * from './History/HistoryManager'
22
+ export * from './History/PixelAccumulator'
20
23
  export * from './History/PixelEngineConfig'
21
24
  export * from './History/PixelMutator'
22
25
  export * from './History/PixelPatchTiles'
23
26
  export * from './History/PixelWriter'
24
27
 
25
- export * from './History/PixelMutator/mutatorApplyMask'
28
+ export * from './History/PixelMutator/mutatorApplyAlphaMask'
29
+ export * from './History/PixelMutator/mutatorApplyBinaryMask'
30
+
31
+ export * from './History/PixelMutator/mutatorApplyCircleBrush'
32
+ export * from './History/PixelMutator/mutatorApplyCircleBrushStroke'
33
+
34
+ export * from './History/PixelMutator/mutatorApplyCirclePencil'
35
+ export * from './History/PixelMutator/mutatorApplyCirclePencilStroke'
36
+
37
+ export * from './History/PixelMutator/mutatorApplyRectPencil'
38
+ export * from './History/PixelMutator/mutatorApplyRectPencilStroke'
39
+
40
+ export * from './History/PixelMutator/mutatorApplyRectBrush'
41
+ export * from './History/PixelMutator/mutatorApplyRectBrushStroke'
42
+
26
43
  export * from './History/PixelMutator/mutatorBlendColor'
27
44
  export * from './History/PixelMutator/mutatorBlendPixel'
28
45
  export * from './History/PixelMutator/mutatorBlendPixelData'
29
- export * from './History/PixelMutator/mutatorFillPixelData'
46
+ export * from './History/PixelMutator/mutatorClear'
47
+ export * from './History/PixelMutator/mutatorFill'
30
48
  export * from './History/PixelMutator/mutatorInvert'
31
49
 
32
- export * from './ImageData/ReusableImageData'
33
50
  export * from './ImageData/copyImageData'
34
51
  export * from './ImageData/extractImageDataBuffer'
52
+ export * from './ImageData/ImageDataLike'
35
53
  export * from './ImageData/imageDataToAlphaMask'
36
54
  export * from './ImageData/imageDataToDataUrl'
37
55
  export * from './ImageData/imageDataToImgBlob'
@@ -40,40 +58,58 @@ export * from './ImageData/imgBlobToImageData'
40
58
  export * from './ImageData/invertImageData'
41
59
  export * from './ImageData/resampleImageData'
42
60
  export * from './ImageData/resizeImageData'
61
+ export * from './ImageData/ReusableImageData'
43
62
  export * from './ImageData/serialization'
63
+ export * from './ImageData/uInt32ArrayToImageData'
44
64
  export * from './ImageData/writeImageData'
45
65
  export * from './ImageData/writeImageDataBuffer'
46
66
 
47
- export * from './IndexedImage/IndexedImage'
48
67
  export * from './IndexedImage/getIndexedImageColorCounts'
68
+ export * from './IndexedImage/IndexedImage'
49
69
  export * from './IndexedImage/indexedImageToAverageColor'
50
- export * from './IndexedImage/resampleIndexedImage'
51
70
  export * from './IndexedImage/indexedImageToImageData'
71
+ export * from './IndexedImage/resampleIndexedImage'
52
72
 
53
73
  export * from './Input/fileInputChangeToImageData'
54
74
  export * from './Input/fileToImageData'
55
75
  export * from './Input/getSupportedRasterFormats'
56
76
 
77
+ export * from './Mask/applyBinaryMaskToAlphaMask'
57
78
  export * from './Mask/copyMask'
58
79
  export * from './Mask/extractMask'
59
80
  export * from './Mask/invertMask'
60
- export * from './Mask/mergeMasks'
81
+ export * from './Mask/mergeAlphaMasks'
82
+ export * from './Mask/mergeBinaryMasks'
61
83
 
62
- export * from './PixelData/PixelData'
84
+ export * from './PixelData/applyAlphaMaskToPixelData'
85
+ export * from './PixelData/applyBinaryMaskToPixelData'
63
86
  export * from './PixelData/applyCircleBrushToPixelData'
64
- export * from './PixelData/applyMaskToPixelData'
87
+ export * from './PixelData/PixelData'
88
+
65
89
  export * from './PixelData/applyRectBrushToPixelData'
66
90
  export * from './PixelData/blendColorPixelData'
91
+ export * from './PixelData/blendColorPixelDataAlphaMask'
92
+ export * from './PixelData/blendColorPixelDataBinaryMask'
67
93
  export * from './PixelData/blendPixelData'
94
+ export * from './PixelData/blendPixelDataAlphaMask'
95
+ export * from './PixelData/blendPixelDataBinaryMask'
96
+
68
97
  export * from './PixelData/clearPixelData'
69
98
  export * from './PixelData/extractPixelData'
70
99
  export * from './PixelData/extractPixelDataBuffer'
71
100
  export * from './PixelData/fillPixelData'
72
101
  export * from './PixelData/invertPixelData'
102
+ export * from './PixelData/PixelBuffer32'
73
103
  export * from './PixelData/pixelDataToAlphaMask'
74
104
  export * from './PixelData/reflectPixelData'
75
105
  export * from './PixelData/resamplePixelData'
76
106
  export * from './PixelData/rotatePixelData'
77
107
  export * from './PixelData/writePixelDataBuffer'
78
108
 
109
+ export * from './Rect/getCircleBrushOrPencilBounds'
110
+ export * from './Rect/getCircleBrushOrPencilStrokeBounds'
111
+ export * from './Rect/getRectBrushOrPencilBounds'
112
+ export * from './Rect/getRectBrushOrPencilStrokeBounds'
79
113
  export * from './Rect/trimRectBounds'
114
+
115
+ export * from './Algorithm/forEachLinePoint'
@@ -1,20 +0,0 @@
1
- import { type AnyMask, type ApplyMaskOptions } from '../../_types'
2
- import { applyMaskToPixelData } from '../../PixelData/applyMaskToPixelData'
3
- import { PixelWriter } from '../PixelWriter'
4
-
5
- export function mutatorApplyMask(writer: PixelWriter<any>) {
6
- return {
7
- applyMask: (mask: AnyMask, opts: ApplyMaskOptions = {}) => {
8
- let target = writer.target
9
- const {
10
- x = 0,
11
- y = 0,
12
- w = writer.target.width,
13
- h = writer.target.height,
14
- } = opts
15
-
16
- writer.accumulator.storeRegionBeforeState(x, y, w, h)
17
- applyMaskToPixelData(target, mask, opts)
18
- },
19
- }
20
- }
@@ -1,100 +0,0 @@
1
- import { type AlphaMask, type AnyMask, type ApplyMaskOptions, MaskType } from '../_types'
2
-
3
- /**
4
- * Merges a source mask into a destination AlphaMask.
5
- */
6
- export function mergeMasks(
7
- dst: AlphaMask,
8
- dstWidth: number,
9
- src: AnyMask,
10
- opts: ApplyMaskOptions,
11
- ): void {
12
- const {
13
- x: targetX = 0,
14
- y: targetY = 0,
15
- w: width = 0,
16
- h: height = 0,
17
- alpha: globalAlpha = 255,
18
- maskType = MaskType.ALPHA,
19
- mw,
20
- mx = 0,
21
- my = 0,
22
- invertMask = false,
23
- } = opts
24
-
25
- if (width <= 0 || height <= 0 || globalAlpha === 0) {
26
- return
27
- }
28
-
29
- const sPitch = mw ?? width
30
- const isAlpha = maskType === MaskType.ALPHA
31
-
32
- for (let iy = 0; iy < height; iy++) {
33
- const dy = targetY + iy
34
- const sy = my + iy
35
-
36
- if (dy < 0 || sy < 0) {
37
- continue
38
- }
39
-
40
- for (let ix = 0; ix < width; ix++) {
41
- const dx = targetX + ix
42
- const sx = mx + ix
43
-
44
- if (dx < 0 || dx >= dstWidth || sx < 0 || sx >= sPitch) {
45
- continue
46
- }
47
-
48
- const dIdx = dy * dstWidth + dx
49
- const sIdx = sy * sPitch + sx
50
- const mVal = src[sIdx]
51
- let weight = globalAlpha
52
-
53
- if (isAlpha) {
54
- const effectiveM = invertMask
55
- ? 255 - mVal
56
- : mVal
57
-
58
- if (effectiveM === 0) {
59
- dst[dIdx] = 0
60
- continue
61
- }
62
-
63
- weight = globalAlpha === 255
64
- ? effectiveM
65
- : (effectiveM * globalAlpha + 128) >> 8
66
- } else {
67
- // Strict Binary 1/0 Logic
68
- const isHit = invertMask
69
- ? mVal === 0
70
- : mVal === 1
71
-
72
- if (!isHit) {
73
- dst[dIdx] = 0
74
- continue
75
- }
76
-
77
- // If binary hit, weight is just the global alpha
78
- weight = globalAlpha
79
- }
80
-
81
- if (weight === 0) {
82
- dst[dIdx] = 0
83
- continue
84
- }
85
-
86
- const da = dst[dIdx]
87
-
88
- if (da === 0) {
89
- // Already transparent
90
- } else if (weight === 255) {
91
- // Identity: keep da
92
- } else if (da === 255) {
93
- // Identity: result is weight
94
- dst[dIdx] = weight
95
- } else {
96
- dst[dIdx] = (da * weight + 128) >> 8
97
- }
98
- }
99
- }
100
- }
@@ -1,129 +0,0 @@
1
- import { type AnyMask, type ApplyMaskOptions, MaskType } from '../_types'
2
- import type { PixelData } from './PixelData'
3
-
4
- /**
5
- * Directly applies a mask to a region of PixelData,
6
- * modifying the destination's alpha channel in-place.
7
- */
8
- export function applyMaskToPixelData(
9
- dst: PixelData,
10
- mask: AnyMask,
11
- opts: ApplyMaskOptions = {},
12
- ): void {
13
- const {
14
- x: targetX = 0,
15
- y: targetY = 0,
16
- w: width = dst.width,
17
- h: height = dst.height,
18
- alpha: globalAlpha = 255,
19
- maskType = MaskType.ALPHA,
20
- mw,
21
- mx = 0,
22
- my = 0,
23
- invertMask = false,
24
- } = opts
25
-
26
- let x = targetX
27
- let y = targetY
28
- let w = width
29
- let h = height
30
-
31
- // Clipping Logic
32
- if (x < 0) {
33
- w += x
34
- x = 0
35
- }
36
-
37
- if (y < 0) {
38
- h += y
39
- y = 0
40
- }
41
-
42
- const actualW = Math.min(w, dst.width - x)
43
- const actualH = Math.min(h, dst.height - y)
44
-
45
- if (actualW <= 0 || actualH <= 0 || globalAlpha === 0) {
46
- return
47
- }
48
-
49
- const dst32 = dst.data32
50
- const dw = dst.width
51
- const mPitch = mw ?? width
52
- const isAlpha = maskType === MaskType.ALPHA
53
- const dx = x - targetX
54
- const dy = y - targetY
55
-
56
- let dIdx = y * dw + x
57
- let mIdx = (my + dy) * mPitch + (mx + dx)
58
-
59
- const dStride = dw - actualW
60
- const mStride = mPitch - actualW
61
-
62
- for (let iy = 0; iy < actualH; iy++) {
63
- for (let ix = 0; ix < actualW; ix++) {
64
- const mVal = mask[mIdx]
65
- let weight = globalAlpha
66
-
67
- if (isAlpha) {
68
- const effectiveM = invertMask
69
- ? 255 - mVal
70
- : mVal
71
-
72
- // Short-circuit: if source is 0, destination alpha becomes 0
73
- if (effectiveM === 0) {
74
- dst32[dIdx] = (dst32[dIdx] & 0x00ffffff) >>> 0
75
- dIdx++
76
- mIdx++
77
- continue
78
- }
79
-
80
- weight = globalAlpha === 255
81
- ? effectiveM
82
- : (effectiveM * globalAlpha + 128) >> 8
83
- } else {
84
- // Strict Binary 1/0 Logic
85
- const isHit = invertMask
86
- ? mVal === 0
87
- : mVal === 1
88
-
89
- if (!isHit) {
90
- dst32[dIdx] = (dst32[dIdx] & 0x00ffffff) >>> 0
91
- dIdx++
92
- mIdx++
93
- continue
94
- }
95
-
96
- weight = globalAlpha
97
- }
98
-
99
- // If calculated weight is 0, clear alpha
100
- if (weight === 0) {
101
- dst32[dIdx] = (dst32[dIdx] & 0x00ffffff) >>> 0
102
- } else {
103
- const d = dst32[dIdx]
104
- const da = (d >>> 24)
105
-
106
- let finalAlpha = da
107
-
108
- if (da === 0) {
109
- // Already transparent
110
- } else if (weight === 255) {
111
- // Identity: keep original da
112
- } else if (da === 255) {
113
- // Identity: result is just the weight
114
- finalAlpha = weight
115
- } else {
116
- finalAlpha = (da * weight + 128) >> 8
117
- }
118
-
119
- dst32[dIdx] = ((d & 0x00ffffff) | (finalAlpha << 24)) >>> 0
120
- }
121
-
122
- dIdx++
123
- mIdx++
124
- }
125
-
126
- dIdx += dStride
127
- mIdx += mStride
128
- }
129
- }