@pixerate/editor 0.258.0 → 0.260.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/agent/index.cjs +2 -2
- package/dist/agent/index.js +1 -1
- package/dist/animation-editor/index.cjs +61 -59
- package/dist/animation-editor/index.js +5 -3
- package/dist/brushes/contract.d.cts +24 -0
- package/dist/brushes/contract.d.ts +24 -0
- package/dist/brushes/index.cjs +146 -31
- package/dist/brushes/index.d.cts +1 -0
- package/dist/brushes/index.d.ts +1 -0
- package/dist/brushes/index.js +121 -6
- package/dist/{brushstrokeRender-JI4W6F2G.js → brushstrokeRender-25Q5BEY6.js} +17 -7
- package/dist/{brushstrokeRender-MQ6PSDM5.cjs → brushstrokeRender-N6UPZSQS.cjs} +31 -21
- package/dist/canvas/brushTypes.d.cts +5 -0
- package/dist/canvas/brushTypes.d.ts +5 -0
- package/dist/canvas/drawController.d.cts +15 -1
- package/dist/canvas/drawController.d.ts +15 -1
- package/dist/canvas/index.cjs +136 -102
- package/dist/canvas/index.js +35 -1
- package/dist/{chunk-3PPJRMIG.js → chunk-3O47TPGX.js} +197 -18
- package/dist/{chunk-5Q5MLXAD.cjs → chunk-3TQW5MPW.cjs} +23 -23
- package/dist/{chunk-JBBJE76O.cjs → chunk-3ZRNK3RO.cjs} +1138 -85
- package/dist/{chunk-YSGW7VV4.cjs → chunk-43NT242D.cjs} +1401 -228
- package/dist/{chunk-SMTUQWGY.js → chunk-5IW65VQ6.js} +1 -1
- package/dist/{chunk-YQ4PQTBB.js → chunk-6NZL24W4.js} +9 -1
- package/dist/{chunk-O3ZVZSNJ.cjs → chunk-7AUQ2UJ3.cjs} +137 -129
- package/dist/{chunk-4M4E3N6X.js → chunk-CQVTGBQI.js} +1 -1
- package/dist/{chunk-SSFMWJDK.js → chunk-D4TE5JNW.js} +1192 -19
- package/dist/{chunk-AORZ5M5C.js → chunk-EHALWBBD.js} +1 -1
- package/dist/{chunk-6WCQ35GI.cjs → chunk-NHA26O5X.cjs} +2 -2
- package/dist/{chunk-DPYAO5U6.cjs → chunk-PVJMTLPJ.cjs} +197 -18
- package/dist/{chunk-MQGQTKVW.cjs → chunk-PYTJBVW5.cjs} +29 -29
- package/dist/{chunk-IXQZHCOF.js → chunk-QAR2N7HZ.js} +1 -1
- package/dist/{chunk-5P4JEOIV.js → chunk-TMDDMJCR.js} +2 -2
- package/dist/{chunk-RSIKDWOP.cjs → chunk-TZOX7KWV.cjs} +15 -15
- package/dist/{chunk-IPUTIUGQ.cjs → chunk-UVZ7RQOE.cjs} +1 -1
- package/dist/{chunk-A7GJ6BXI.js → chunk-WJ4WQJCC.js} +1062 -9
- package/dist/{chunk-ICTPLVSR.js → chunk-X2EXYY4J.js} +1 -1
- package/dist/{chunk-WQCNC4DK.js → chunk-XC6DPRYI.js} +695 -4
- package/dist/{chunk-KBYB7OWB.cjs → chunk-YHDHFJUC.cjs} +776 -85
- package/dist/{chunk-P3PZ63M3.cjs → chunk-YLUIFXSL.cjs} +35 -35
- package/dist/commands/index.cjs +2 -2
- package/dist/commands/index.js +1 -1
- package/dist/image-editor/index.cjs +1385 -2484
- package/dist/image-editor/index.js +139 -1238
- package/dist/image-editor/selection-worker.cjs +3 -4
- package/dist/image-editor/selection-worker.js +1 -2
- package/dist/paint/index.cjs +3 -5
- package/dist/paint/index.js +40 -42
- package/dist/paint-editor/contract.d.cts +29 -0
- package/dist/paint-editor/contract.d.ts +29 -0
- package/dist/paint-editor/dab-stroke.d.cts +5 -0
- package/dist/paint-editor/dab-stroke.d.ts +5 -0
- package/dist/paint-editor/index.cjs +402 -258
- package/dist/paint-editor/index.d.cts +1 -0
- package/dist/paint-editor/index.d.ts +1 -0
- package/dist/paint-editor/index.js +197 -53
- package/dist/paint-editor/stamp-tip.d.cts +17 -0
- package/dist/paint-editor/stamp-tip.d.ts +17 -0
- package/dist/paint-editor/ui.d.cts +21 -1
- package/dist/paint-editor/ui.d.ts +21 -1
- package/dist/raster/index.cjs +2 -4
- package/dist/raster/index.js +6 -8
- package/dist/vector/brushstroke.d.cts +6 -0
- package/dist/vector/brushstroke.d.ts +6 -0
- package/dist/vector/controller.d.cts +11 -2
- package/dist/vector/controller.d.ts +11 -2
- package/dist/vector/index.cjs +990 -973
- package/dist/vector/index.js +28 -11
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +1 -1
- package/skills/pixerate-canvas/SKILL.md +3 -1
- package/skills/pixerate-vector/SKILL.md +2 -2
- package/dist/chunk-2VJAVXLI.js +0 -192
- package/dist/chunk-62Z5WLRA.js +0 -700
- package/dist/chunk-BOHDJJ2O.cjs +0 -192
- package/dist/chunk-NKGB64CW.cjs +0 -700
- package/dist/chunk-SS53NNZO.cjs +0 -1066
- package/dist/chunk-ZNA3IQZF.js +0 -1066
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
var _chunkBB6TR422cjs = require('./chunk-BB6TR422.cjs');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var _chunkFQPUF2W2cjs = require('./chunk-FQPUF2W2.cjs');
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
2
21
|
|
|
3
22
|
|
|
4
23
|
var _chunk2VX55NFMcjs = require('./chunk-2VX55NFM.cjs');
|
|
@@ -80,6 +99,648 @@ function createPigmentTools() {
|
|
|
80
99
|
return [mixColors];
|
|
81
100
|
}
|
|
82
101
|
|
|
102
|
+
// src/paint/retouch.ts
|
|
103
|
+
var TONE_RANGES = ["shadows", "midtones", "highlights"];
|
|
104
|
+
function luma(r, g, b) {
|
|
105
|
+
return 0.299 * r + 0.587 * g + 0.114 * b;
|
|
106
|
+
}
|
|
107
|
+
function dodgeBurnCurve(v, e, range, burn) {
|
|
108
|
+
const x = Math.max(0, v);
|
|
109
|
+
const k = Math.min(1, Math.max(0, e));
|
|
110
|
+
const c = Math.min(1, x);
|
|
111
|
+
if (range === "midtones") {
|
|
112
|
+
const w2 = Math.min(1, Math.max(0, 4 * x * (1 - x)));
|
|
113
|
+
return x + w2 * (Math.pow(c, burn ? 1 + k : 1 / (1 + k)) - x);
|
|
114
|
+
}
|
|
115
|
+
const w = range === "shadows" ? (1 - c) * (1 - c) : c * c;
|
|
116
|
+
return burn ? x - k * w * x : x + k * w * (1 - c);
|
|
117
|
+
}
|
|
118
|
+
function compressGamut(c, l) {
|
|
119
|
+
const L = Math.min(1, Math.max(0, l));
|
|
120
|
+
const lo = Math.min(c[0], c[1], c[2]);
|
|
121
|
+
const hi = Math.max(c[0], c[1], c[2]);
|
|
122
|
+
let t = 1;
|
|
123
|
+
if (hi > 1 && hi - L > 1e-9) t = Math.min(t, (1 - L) / (hi - L));
|
|
124
|
+
if (lo < 0 && L - lo > 1e-9) t = Math.min(t, L / (L - lo));
|
|
125
|
+
for (let i = 0; i < 3; i++) c[i] = L + (c[i] - L) * t;
|
|
126
|
+
}
|
|
127
|
+
function dodgeBurn(c, e, range, burn, protectTones) {
|
|
128
|
+
if (!(e > 0)) return c;
|
|
129
|
+
if (protectTones) {
|
|
130
|
+
const l = luma(c[0], c[1], c[2]);
|
|
131
|
+
const nl = dodgeBurnCurve(l, e, range, burn);
|
|
132
|
+
if (l > 1e-6) for (let i = 0; i < 3; i++) c[i] *= nl / l;
|
|
133
|
+
else c[0] = c[1] = c[2] = nl;
|
|
134
|
+
compressGamut(c, nl);
|
|
135
|
+
} else for (let i = 0; i < 3; i++) c[i] = dodgeBurnCurve(c[i], e, range, burn);
|
|
136
|
+
return c;
|
|
137
|
+
}
|
|
138
|
+
function saturationOf(r, g, b) {
|
|
139
|
+
const lo = Math.min(r, g, b);
|
|
140
|
+
const hi = Math.max(r, g, b);
|
|
141
|
+
return hi <= 1e-6 ? 0 : Math.min(1, Math.max(0, (hi - lo) / hi));
|
|
142
|
+
}
|
|
143
|
+
function sponge(c, amount, saturate, vibrance) {
|
|
144
|
+
let a = Math.min(1, Math.max(0, amount));
|
|
145
|
+
if (!(a > 0)) return c;
|
|
146
|
+
if (vibrance) {
|
|
147
|
+
const s = saturationOf(c[0], c[1], c[2]);
|
|
148
|
+
a *= saturate ? 1 - s : 0.25 + 0.75 * s;
|
|
149
|
+
}
|
|
150
|
+
const l = luma(c[0], c[1], c[2]);
|
|
151
|
+
const k = saturate ? 1 + a : 1 - a;
|
|
152
|
+
for (let i = 0; i < 3; i++) c[i] = l + (c[i] - l) * k;
|
|
153
|
+
compressGamut(c, l);
|
|
154
|
+
return c;
|
|
155
|
+
}
|
|
156
|
+
function perDabStrength(e, spacing) {
|
|
157
|
+
return 1 - Math.pow(1 - Math.min(1, Math.max(0, e)), Math.min(1, Math.max(0.01, spacing)));
|
|
158
|
+
}
|
|
159
|
+
var RETOUCH_SAMPLES = ["current", "current-below", "all"];
|
|
160
|
+
var SPOT_HEAL_TYPES = ["proximity-match", "content-aware", "smooth"];
|
|
161
|
+
var DEFAULT_RETOUCH = {
|
|
162
|
+
aligned: true,
|
|
163
|
+
sample: "current",
|
|
164
|
+
spotType: "proximity-match",
|
|
165
|
+
range: "midtones",
|
|
166
|
+
exposure: 0.5,
|
|
167
|
+
protectTones: true,
|
|
168
|
+
spongeMode: "desaturate",
|
|
169
|
+
vibrance: true,
|
|
170
|
+
strength: 0.5,
|
|
171
|
+
historySteps: 0
|
|
172
|
+
};
|
|
173
|
+
function normalizeRetouch(raw = {}, base = DEFAULT_RETOUCH) {
|
|
174
|
+
const unit2 = (v, d) => typeof v === "number" && Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : d;
|
|
175
|
+
const bool = (v, d) => typeof v === "boolean" ? v : d;
|
|
176
|
+
const pick = (v, all, d) => all.includes(v) ? v : d;
|
|
177
|
+
return {
|
|
178
|
+
aligned: bool(raw.aligned, base.aligned),
|
|
179
|
+
sample: pick(raw.sample, RETOUCH_SAMPLES, base.sample),
|
|
180
|
+
spotType: pick(raw.spotType, SPOT_HEAL_TYPES, base.spotType),
|
|
181
|
+
range: pick(raw.range, TONE_RANGES, base.range),
|
|
182
|
+
exposure: unit2(raw.exposure, base.exposure),
|
|
183
|
+
protectTones: bool(raw.protectTones, base.protectTones),
|
|
184
|
+
spongeMode: pick(raw.spongeMode, ["desaturate", "saturate"], base.spongeMode),
|
|
185
|
+
vibrance: bool(raw.vibrance, base.vibrance),
|
|
186
|
+
strength: unit2(raw.strength, base.strength),
|
|
187
|
+
historySteps: typeof raw.historySteps === "number" && Number.isFinite(raw.historySteps) ? Math.min(1e3, Math.max(0, Math.round(raw.historySteps))) : base.historySteps
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function boxBlurPixels(data, w, h, n, r) {
|
|
191
|
+
if (r < 1) return;
|
|
192
|
+
if (n === 4) for (let i = 0; i < data.length; i += 4) for (let c = 0; c < 3; c++) data[i + c] *= data[i + 3] / 255;
|
|
193
|
+
const tmp = new Float32Array(data.length);
|
|
194
|
+
const k = 1 / (2 * r + 1);
|
|
195
|
+
for (let y = 0; y < h; y++) {
|
|
196
|
+
for (let x = 0; x < w; x++) {
|
|
197
|
+
for (let c = 0; c < n; c++) {
|
|
198
|
+
let s = 0;
|
|
199
|
+
for (let d = -r; d <= r; d++) s += data[(y * w + Math.min(w - 1, Math.max(0, x + d))) * n + c];
|
|
200
|
+
tmp[(y * w + x) * n + c] = s * k;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (let y = 0; y < h; y++) {
|
|
205
|
+
for (let x = 0; x < w; x++) {
|
|
206
|
+
for (let c = 0; c < n; c++) {
|
|
207
|
+
let s = 0;
|
|
208
|
+
for (let d = -r; d <= r; d++) s += tmp[(Math.min(h - 1, Math.max(0, y + d)) * w + x) * n + c];
|
|
209
|
+
data[(y * w + x) * n + c] = s * k;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (n === 4) {
|
|
214
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
215
|
+
const a = data[i + 3] / 255;
|
|
216
|
+
for (let c = 0; c < 3; c++) data[i + c] = a > 0 ? data[i + c] / a : 0;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function retouchFilter(data, w, h, n, kind, radius = 2, amount = 1) {
|
|
221
|
+
if (kind === "blur") {
|
|
222
|
+
boxBlurPixels(data, w, h, n, radius);
|
|
223
|
+
boxBlurPixels(data, w, h, n, radius);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const soft = data.slice();
|
|
227
|
+
boxBlurPixels(soft, w, h, n, 1);
|
|
228
|
+
for (let i = 0; i < data.length; i++) {
|
|
229
|
+
if (n === 4 && (i & 3) === 3) continue;
|
|
230
|
+
const v = data[i] + amount * (data[i] - soft[i]);
|
|
231
|
+
data[i] = v > 0 ? v : 0;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
var IDENTITY_CLONE_TRANSFORM = { scaleX: 1, scaleY: 1, rotate: 0 };
|
|
235
|
+
function isIdentityCloneTransform(t) {
|
|
236
|
+
return t.scaleX === 1 && t.scaleY === 1 && (t.rotate % 360 + 360) % 360 === 0;
|
|
237
|
+
}
|
|
238
|
+
function cloneSamplePoint(t, source, anchor, x, y) {
|
|
239
|
+
const a = -t.rotate * Math.PI / 180;
|
|
240
|
+
const c = Math.cos(a);
|
|
241
|
+
const s = Math.sin(a);
|
|
242
|
+
const dx = x - anchor.x;
|
|
243
|
+
const dy = y - anchor.y;
|
|
244
|
+
return [source.x + (c * dx - s * dy) / t.scaleX, source.y + (s * dx + c * dy) / t.scaleY];
|
|
245
|
+
}
|
|
246
|
+
var TransformedPixelSource = (_class = class {
|
|
247
|
+
constructor(inner, map) {;_class.prototype.__init.call(this);
|
|
248
|
+
this.inner = inner;
|
|
249
|
+
this.map = map;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
__init() {this.px = [0, 0, 0, 0]}
|
|
254
|
+
sample(x, y, out) {
|
|
255
|
+
const [u, v] = this.map(x, y);
|
|
256
|
+
const x0 = Math.floor(u);
|
|
257
|
+
const y0 = Math.floor(v);
|
|
258
|
+
const fx = u - x0;
|
|
259
|
+
const fy = v - y0;
|
|
260
|
+
let r = 0;
|
|
261
|
+
let g = 0;
|
|
262
|
+
let b = 0;
|
|
263
|
+
let a = 0;
|
|
264
|
+
for (let k = 0; k < 4; k++) {
|
|
265
|
+
const w = (k & 1 ? fx : 1 - fx) * (k & 2 ? fy : 1 - fy);
|
|
266
|
+
if (w <= 0) continue;
|
|
267
|
+
if (!this.inner.sample(x0 + (k & 1), y0 + (k >> 1), this.px)) continue;
|
|
268
|
+
const pa = this.px[3] * w;
|
|
269
|
+
r += this.px[0] * pa;
|
|
270
|
+
g += this.px[1] * pa;
|
|
271
|
+
b += this.px[2] * pa;
|
|
272
|
+
a += pa;
|
|
273
|
+
}
|
|
274
|
+
if (!(a > 0)) {
|
|
275
|
+
out[0] = out[1] = out[2] = out[3] = 0;
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
out[0] = r / a;
|
|
279
|
+
out[1] = g / a;
|
|
280
|
+
out[2] = b / a;
|
|
281
|
+
out[3] = a;
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
}, _class);
|
|
285
|
+
var TilePixelSource = (_class2 = class {
|
|
286
|
+
constructor(readTile, channels, offset = { x: 0, y: 0 }) {;_class2.prototype.__init2.call(this);_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);
|
|
287
|
+
this.readTile = readTile;
|
|
288
|
+
this.channels = channels;
|
|
289
|
+
this.offset = offset;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
__init2() {this.cache = /* @__PURE__ */ new Map()}
|
|
295
|
+
__init3() {this.lastKey = NaN}
|
|
296
|
+
__init4() {this.last = null}
|
|
297
|
+
sample(x, y, out) {
|
|
298
|
+
const lx = x - this.offset.x;
|
|
299
|
+
const ly = y - this.offset.y;
|
|
300
|
+
const tx = Math.floor(lx / _chunk474IQG74cjs.TILE);
|
|
301
|
+
const ty = Math.floor(ly / _chunk474IQG74cjs.TILE);
|
|
302
|
+
const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
|
|
303
|
+
if (key !== this.lastKey) {
|
|
304
|
+
let t2 = this.cache.get(key);
|
|
305
|
+
if (t2 === void 0) {
|
|
306
|
+
t2 = this.readTile(tx, ty);
|
|
307
|
+
this.cache.set(key, t2);
|
|
308
|
+
}
|
|
309
|
+
this.last = t2;
|
|
310
|
+
this.lastKey = key;
|
|
311
|
+
}
|
|
312
|
+
const t = this.last;
|
|
313
|
+
if (!t) {
|
|
314
|
+
out[0] = out[1] = out[2] = out[3] = 0;
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
const p = (ly - ty * _chunk474IQG74cjs.TILE) * _chunk474IQG74cjs.TILE + (lx - tx * _chunk474IQG74cjs.TILE);
|
|
318
|
+
if (this.channels === 1) {
|
|
319
|
+
out[0] = out[1] = out[2] = t[p];
|
|
320
|
+
out[3] = 255;
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
const i = p * 4;
|
|
324
|
+
out[0] = t[i];
|
|
325
|
+
out[1] = t[i + 1];
|
|
326
|
+
out[2] = t[i + 2];
|
|
327
|
+
out[3] = t[i + 3];
|
|
328
|
+
return out[3] > 0;
|
|
329
|
+
}
|
|
330
|
+
}, _class2);
|
|
331
|
+
var RegionPixelSource = class {
|
|
332
|
+
constructor(rect, data) {
|
|
333
|
+
this.rect = rect;
|
|
334
|
+
this.data = data;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
sample(x, y, out) {
|
|
339
|
+
const r = this.rect;
|
|
340
|
+
const lx = x - r.x;
|
|
341
|
+
const ly = y - r.y;
|
|
342
|
+
if (lx < 0 || ly < 0 || lx >= r.width || ly >= r.height) {
|
|
343
|
+
out[0] = out[1] = out[2] = out[3] = 0;
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
const i = (ly * r.width + lx) * 4;
|
|
347
|
+
out[0] = this.data[i];
|
|
348
|
+
out[1] = this.data[i + 1];
|
|
349
|
+
out[2] = this.data[i + 2];
|
|
350
|
+
out[3] = this.data[i + 3];
|
|
351
|
+
return out[3] > 0;
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
function readSourceRegion(source, rect, dx = 0, dy = 0) {
|
|
355
|
+
const out = new Float32Array(rect.width * rect.height * 4);
|
|
356
|
+
const px = [0, 0, 0, 0];
|
|
357
|
+
for (let y = 0; y < rect.height; y++) {
|
|
358
|
+
for (let x = 0; x < rect.width; x++) {
|
|
359
|
+
source.sample(rect.x + x + dx, rect.y + y + dy, px);
|
|
360
|
+
const i = (y * rect.width + x) * 4;
|
|
361
|
+
out[i] = px[0];
|
|
362
|
+
out[i + 1] = px[1];
|
|
363
|
+
out[i + 2] = px[2];
|
|
364
|
+
out[i + 3] = px[3];
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return out;
|
|
368
|
+
}
|
|
369
|
+
function applyRetouchToTile(coverage, tileData, channels, tx, ty, paint, s, options = {}) {
|
|
370
|
+
const out = (_nullishCoalesce(options.into, () => ( tileData))).slice();
|
|
371
|
+
const ox = tx * _chunk474IQG74cjs.TILE + s.offset.x;
|
|
372
|
+
const oy = ty * _chunk474IQG74cjs.TILE + s.offset.y;
|
|
373
|
+
let x0 = 0;
|
|
374
|
+
let y0 = 0;
|
|
375
|
+
let x1 = _chunk474IQG74cjs.TILE;
|
|
376
|
+
let y1 = _chunk474IQG74cjs.TILE;
|
|
377
|
+
if (options.region) {
|
|
378
|
+
const r = options.region;
|
|
379
|
+
x0 = Math.max(0, Math.floor(r.x) - ox);
|
|
380
|
+
y0 = Math.max(0, Math.floor(r.y) - oy);
|
|
381
|
+
x1 = Math.min(_chunk474IQG74cjs.TILE, Math.ceil(r.x + r.width) - ox);
|
|
382
|
+
y1 = Math.min(_chunk474IQG74cjs.TILE, Math.ceil(r.y + r.height) - oy);
|
|
383
|
+
if (x1 <= x0 || y1 <= y0) return out;
|
|
384
|
+
if (options.into) {
|
|
385
|
+
for (let y = y0; y < y1; y++) out.set(tileData.subarray((y * _chunk474IQG74cjs.TILE + x0) * channels, (y * _chunk474IQG74cjs.TILE + x1) * channels), (y * _chunk474IQG74cjs.TILE + x0) * channels);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const sel = s.selection;
|
|
389
|
+
const blend = _nullishCoalesce(s.blend, () => ( "normal"));
|
|
390
|
+
const src = [0, 0, 0, 0];
|
|
391
|
+
const rgb = [0, 0, 0];
|
|
392
|
+
const cb = [0, 0, 0, 0];
|
|
393
|
+
const cs = [0, 0, 0, 0];
|
|
394
|
+
let covKey = NaN;
|
|
395
|
+
let covTile;
|
|
396
|
+
for (let y = y0; y < y1; y++) {
|
|
397
|
+
const dy = oy + y;
|
|
398
|
+
const cty = Math.floor(dy / _chunk474IQG74cjs.TILE);
|
|
399
|
+
for (let x = x0; x < x1; x++) {
|
|
400
|
+
const dx = ox + x;
|
|
401
|
+
const ctx = Math.floor(dx / _chunk474IQG74cjs.TILE);
|
|
402
|
+
const key = _chunk474IQG74cjs.tileKey.call(void 0, ctx, cty);
|
|
403
|
+
if (key !== covKey) {
|
|
404
|
+
covKey = key;
|
|
405
|
+
covTile = coverage.tiles.get(key);
|
|
406
|
+
}
|
|
407
|
+
if (!covTile) continue;
|
|
408
|
+
const c = covTile[(dy - cty * _chunk474IQG74cjs.TILE) * _chunk474IQG74cjs.TILE + (dx - ctx * _chunk474IQG74cjs.TILE)];
|
|
409
|
+
if (c <= 0) continue;
|
|
410
|
+
let k = c * s.opacity;
|
|
411
|
+
if (sel) {
|
|
412
|
+
if (dx < 0 || dy < 0 || dx >= sel.width || dy >= sel.height) continue;
|
|
413
|
+
k *= sel.data[dy * sel.width + dx] / 255;
|
|
414
|
+
}
|
|
415
|
+
if (k > 1) k = 1;
|
|
416
|
+
if (k <= 0) continue;
|
|
417
|
+
const p = y * _chunk474IQG74cjs.TILE + x;
|
|
418
|
+
if (channels === 1) {
|
|
419
|
+
const g = out[p];
|
|
420
|
+
let t;
|
|
421
|
+
if (paint.kind === "tone") {
|
|
422
|
+
rgb[0] = rgb[1] = rgb[2] = g / 255;
|
|
423
|
+
paint.tone(rgb);
|
|
424
|
+
t = luma(rgb[0], rgb[1], rgb[2]) * 255;
|
|
425
|
+
} else if (paint.kind === "color") t = paint.color[0];
|
|
426
|
+
else {
|
|
427
|
+
if (!paint.source.sample(dx + paint.dx, dy + paint.dy, src)) continue;
|
|
428
|
+
t = src[0];
|
|
429
|
+
k *= src[3] / 255;
|
|
430
|
+
}
|
|
431
|
+
out[p] = Math.round(g + (t - g) * k);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
const i = p * 4;
|
|
435
|
+
const a = out[i + 3];
|
|
436
|
+
if (paint.kind === "tone") {
|
|
437
|
+
if (a === 0) continue;
|
|
438
|
+
rgb[0] = out[i] / 255;
|
|
439
|
+
rgb[1] = out[i + 1] / 255;
|
|
440
|
+
rgb[2] = out[i + 2] / 255;
|
|
441
|
+
const r0 = rgb[0];
|
|
442
|
+
const g0 = rgb[1];
|
|
443
|
+
const b0 = rgb[2];
|
|
444
|
+
paint.tone(rgb);
|
|
445
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, out, i, r0 + (rgb[0] - r0) * k);
|
|
446
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, out, i + 1, g0 + (rgb[1] - g0) * k);
|
|
447
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, out, i + 2, b0 + (rgb[2] - b0) * k);
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
if (s.lockTransparency && a === 0) continue;
|
|
451
|
+
if (paint.kind === "color") {
|
|
452
|
+
src[0] = paint.color[0];
|
|
453
|
+
src[1] = paint.color[1];
|
|
454
|
+
src[2] = paint.color[2];
|
|
455
|
+
src[3] = paint.color[3];
|
|
456
|
+
} else if (!paint.source.sample(dx + paint.dx, dy + paint.dy, src)) continue;
|
|
457
|
+
for (let ch = 0; ch < 4; ch++) {
|
|
458
|
+
cb[ch] = out[i + ch] / 255;
|
|
459
|
+
cs[ch] = src[ch] / 255;
|
|
460
|
+
}
|
|
461
|
+
const o = _chunk2VX55NFMcjs.blendPixel.call(void 0, blend, cb, cs, k);
|
|
462
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, out, i, o[0]);
|
|
463
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, out, i + 1, o[1]);
|
|
464
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, out, i + 2, o[2]);
|
|
465
|
+
if (!s.lockTransparency) _chunkFQPUF2W2cjs.put255.call(void 0, out, i + 3, o[3]);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return out;
|
|
469
|
+
}
|
|
470
|
+
function applyToneToDeepTile(coverage, samples, tx, ty, tone, s, options = {}) {
|
|
471
|
+
const linear = samples instanceof Float32Array;
|
|
472
|
+
const out = (_nullishCoalesce(options.into, () => ( samples))).slice();
|
|
473
|
+
const ox = tx * _chunk474IQG74cjs.TILE + s.offset.x;
|
|
474
|
+
const oy = ty * _chunk474IQG74cjs.TILE + s.offset.y;
|
|
475
|
+
let x0 = 0;
|
|
476
|
+
let y0 = 0;
|
|
477
|
+
let x1 = _chunk474IQG74cjs.TILE;
|
|
478
|
+
let y1 = _chunk474IQG74cjs.TILE;
|
|
479
|
+
if (options.region) {
|
|
480
|
+
const r = options.region;
|
|
481
|
+
x0 = Math.max(0, Math.floor(r.x) - ox);
|
|
482
|
+
y0 = Math.max(0, Math.floor(r.y) - oy);
|
|
483
|
+
x1 = Math.min(_chunk474IQG74cjs.TILE, Math.ceil(r.x + r.width) - ox);
|
|
484
|
+
y1 = Math.min(_chunk474IQG74cjs.TILE, Math.ceil(r.y + r.height) - oy);
|
|
485
|
+
if (x1 <= x0 || y1 <= y0) return out;
|
|
486
|
+
if (options.into) for (let y = y0; y < y1; y++) out.set(samples.subarray((y * _chunk474IQG74cjs.TILE + x0) * 4, (y * _chunk474IQG74cjs.TILE + x1) * 4), (y * _chunk474IQG74cjs.TILE + x0) * 4);
|
|
487
|
+
}
|
|
488
|
+
const sel = s.selection;
|
|
489
|
+
const rgb = [0, 0, 0];
|
|
490
|
+
const before = [0, 0, 0];
|
|
491
|
+
const excess = [0, 0, 0];
|
|
492
|
+
let covKey = NaN;
|
|
493
|
+
let covTile;
|
|
494
|
+
for (let y = y0; y < y1; y++) {
|
|
495
|
+
const dy = oy + y;
|
|
496
|
+
const cty = Math.floor(dy / _chunk474IQG74cjs.TILE);
|
|
497
|
+
for (let x = x0; x < x1; x++) {
|
|
498
|
+
const dx = ox + x;
|
|
499
|
+
const ctx = Math.floor(dx / _chunk474IQG74cjs.TILE);
|
|
500
|
+
const key = _chunk474IQG74cjs.tileKey.call(void 0, ctx, cty);
|
|
501
|
+
if (key !== covKey) {
|
|
502
|
+
covKey = key;
|
|
503
|
+
covTile = coverage.tiles.get(key);
|
|
504
|
+
}
|
|
505
|
+
if (!covTile) continue;
|
|
506
|
+
const c = covTile[(dy - cty * _chunk474IQG74cjs.TILE) * _chunk474IQG74cjs.TILE + (dx - ctx * _chunk474IQG74cjs.TILE)];
|
|
507
|
+
if (c <= 0) continue;
|
|
508
|
+
let k = c * s.opacity;
|
|
509
|
+
if (sel) {
|
|
510
|
+
if (dx < 0 || dy < 0 || dx >= sel.width || dy >= sel.height) continue;
|
|
511
|
+
k *= sel.data[dy * sel.width + dx] / 255;
|
|
512
|
+
}
|
|
513
|
+
if (k > 1) k = 1;
|
|
514
|
+
if (k <= 0) continue;
|
|
515
|
+
const i = (y * _chunk474IQG74cjs.TILE + x) * 4;
|
|
516
|
+
if (out[i + 3] === 0) continue;
|
|
517
|
+
for (let ch = 0; ch < 3; ch++) {
|
|
518
|
+
const v = out[i + ch];
|
|
519
|
+
if (linear) {
|
|
520
|
+
excess[ch] = v > 1 ? v - 1 : 0;
|
|
521
|
+
rgb[ch] = _chunk2VX55NFMcjs.srgbEncode.call(void 0, v > 1 ? 1 : v < 0 ? 0 : v);
|
|
522
|
+
} else rgb[ch] = v / 65535;
|
|
523
|
+
before[ch] = rgb[ch];
|
|
524
|
+
}
|
|
525
|
+
tone(rgb);
|
|
526
|
+
for (let ch = 0; ch < 3; ch++) {
|
|
527
|
+
const e = before[ch] + (rgb[ch] - before[ch]) * k;
|
|
528
|
+
if (linear) out[i + ch] = _chunk2VX55NFMcjs.srgbDecode.call(void 0, e) + excess[ch];
|
|
529
|
+
else out[i + ch] = e <= 0 ? 0 : e >= 1 ? 65535 : Math.round(e * 65535);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return out;
|
|
534
|
+
}
|
|
535
|
+
function toneOf(tool, settings) {
|
|
536
|
+
const burn = tool === "burn";
|
|
537
|
+
return (rgb) => {
|
|
538
|
+
dodgeBurn(rgb, settings.exposure, settings.range, burn, settings.protectTones);
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
function healPixels(w, h, src, dst, mask) {
|
|
542
|
+
const out = new Float32Array(dst);
|
|
543
|
+
const bb = _chunkBB6TR422cjs.maskBounds.call(void 0, w, h, mask);
|
|
544
|
+
if (!bb) return out;
|
|
545
|
+
const x0 = Math.max(0, bb[0] - 1);
|
|
546
|
+
const y0 = Math.max(0, bb[1] - 1);
|
|
547
|
+
const x1 = Math.min(w, bb[2] + 1);
|
|
548
|
+
const y1 = Math.min(h, bb[3] + 1);
|
|
549
|
+
const rw = x1 - x0;
|
|
550
|
+
const rh = y1 - y0;
|
|
551
|
+
const s = new Float32Array(rw * rh * 4);
|
|
552
|
+
const d = new Float32Array(rw * rh * 4);
|
|
553
|
+
const m = new Uint8Array(rw * rh);
|
|
554
|
+
for (let y = 0; y < rh; y++) {
|
|
555
|
+
for (let x = 0; x < rw; x++) {
|
|
556
|
+
const gi = (y + y0) * w + x + x0;
|
|
557
|
+
const li = y * rw + x;
|
|
558
|
+
m[li] = mask[gi] ? 1 : 0;
|
|
559
|
+
for (let c = 0; c < 4; c++) {
|
|
560
|
+
s[li * 4 + c] = src[gi * 4 + c];
|
|
561
|
+
d[li * 4 + c] = dst[gi * 4 + c];
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const healed = _chunkBB6TR422cjs.seamlessClone.call(void 0, rw, rh, 4, s, d, m);
|
|
566
|
+
for (let y = 0; y < rh; y++) {
|
|
567
|
+
for (let x = 0; x < rw; x++) {
|
|
568
|
+
const gi = ((y + y0) * w + x + x0) * 4;
|
|
569
|
+
const li = (y * rw + x) * 4;
|
|
570
|
+
for (let c = 0; c < 4; c++) out[gi + c] = Math.min(255, Math.max(0, healed[li + c]));
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return out;
|
|
574
|
+
}
|
|
575
|
+
function spotHealPixels(w, h, img, hole, size, type, onOffset) {
|
|
576
|
+
const domain = _chunkBB6TR422cjs.dilateMask.call(void 0, w, h, hole, 2);
|
|
577
|
+
const healMask = _chunkBB6TR422cjs.dilateMask.call(void 0, w, h, hole, 1);
|
|
578
|
+
let filled = null;
|
|
579
|
+
let bestFound = null;
|
|
580
|
+
if (type === "proximity-match") {
|
|
581
|
+
const ring = Math.min(16, Math.max(3, Math.floor(size / 8)));
|
|
582
|
+
const off2 = _chunkBB6TR422cjs.bestOffset.call(void 0, w, h, 4, img, domain, ring, Math.floor(Math.max(w, h) / 2));
|
|
583
|
+
if (off2) {
|
|
584
|
+
bestFound = off2;
|
|
585
|
+
filled = new Float32Array(img);
|
|
586
|
+
const [ddx, ddy] = off2;
|
|
587
|
+
for (let i = 0; i < w * h; i++) {
|
|
588
|
+
if (!domain[i]) continue;
|
|
589
|
+
const x = i % w + ddx;
|
|
590
|
+
const y = Math.floor(i / w) + ddy;
|
|
591
|
+
const j = (y * w + x) * 4;
|
|
592
|
+
for (let c = 0; c < 4; c++) filled[i * 4 + c] = img[j + c];
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
_optionalChain([onOffset, 'optionalCall', _ => _(filled ? bestFound : null)]);
|
|
597
|
+
if (!filled && type === "content-aware") filled = _chunkBB6TR422cjs.contentAwareFill.call(void 0, w, h, 4, img, domain);
|
|
598
|
+
if (!filled) filled = _chunkBB6TR422cjs.membraneFill.call(void 0, w, h, 4, img, domain);
|
|
599
|
+
return healPixels(w, h, filled, img, healMask);
|
|
600
|
+
}
|
|
601
|
+
function spotHealWindow(bounds, canvas) {
|
|
602
|
+
const g = Math.max(8, Math.ceil(Math.max(bounds.width, bounds.height)));
|
|
603
|
+
const x0 = Math.max(0, bounds.x - g);
|
|
604
|
+
const y0 = Math.max(0, bounds.y - g);
|
|
605
|
+
const x1 = Math.min(canvas.width, bounds.x + bounds.width + g);
|
|
606
|
+
const y1 = Math.min(canvas.height, bounds.y + bounds.height + g);
|
|
607
|
+
return { x: x0, y: y0, width: Math.max(0, x1 - x0), height: Math.max(0, y1 - y0) };
|
|
608
|
+
}
|
|
609
|
+
var RetouchDabStroke = (_class3 = class {
|
|
610
|
+
constructor(brush, target, effect) {;_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);
|
|
611
|
+
this.brush = brush;
|
|
612
|
+
this.effect = effect;
|
|
613
|
+
this.walker = new (0, _chunkFQPUF2W2cjs.DabWalker)(brush);
|
|
614
|
+
this.medium = new (0, _chunkFQPUF2W2cjs.TileMedium)(target);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
__init5() {this.dabCount = 0}
|
|
619
|
+
__init6() {this.bounds = null}
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
__init7() {this.smoothPos = null}
|
|
623
|
+
__init8() {this.buf = new Float32Array(0)}
|
|
624
|
+
push(points) {
|
|
625
|
+
const dabs = [];
|
|
626
|
+
for (const p of points) this.walker.push(this.smooth(p), dabs);
|
|
627
|
+
return this.paint(dabs);
|
|
628
|
+
}
|
|
629
|
+
finish(last) {
|
|
630
|
+
const dabs = [];
|
|
631
|
+
if (last && this.smoothPos && (this.smoothPos.x !== last.x || this.smoothPos.y !== last.y)) this.walker.push(last, dabs);
|
|
632
|
+
this.walker.finish(dabs);
|
|
633
|
+
return this.paint(dabs);
|
|
634
|
+
}
|
|
635
|
+
smooth(p) {
|
|
636
|
+
const a = 1 - Math.min(0.95, Math.max(0, this.brush.smoothing));
|
|
637
|
+
const cur = this.smoothPos;
|
|
638
|
+
const n = cur && a < 1 ? { ...p, x: cur.x + (p.x - cur.x) * a, y: cur.y + (p.y - cur.y) * a } : p;
|
|
639
|
+
this.smoothPos = n;
|
|
640
|
+
return n;
|
|
641
|
+
}
|
|
642
|
+
paint(dabs) {
|
|
643
|
+
const rects = [];
|
|
644
|
+
for (const d of dabs) {
|
|
645
|
+
const rect = _chunkFQPUF2W2cjs.dabRect.call(void 0, d, this.brush.hardness);
|
|
646
|
+
const n = rect.width * rect.height;
|
|
647
|
+
if (this.buf.length < n) this.buf = new Float32Array(n);
|
|
648
|
+
const cov = this.buf.subarray(0, n);
|
|
649
|
+
_chunkFQPUF2W2cjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.hardness, rect, cov);
|
|
650
|
+
this.medium.reset();
|
|
651
|
+
this.effect(this.medium, d, rect, cov);
|
|
652
|
+
rects.push(rect);
|
|
653
|
+
this.bounds = unionRect(this.bounds, rect);
|
|
654
|
+
this.dabCount++;
|
|
655
|
+
}
|
|
656
|
+
return rects;
|
|
657
|
+
}
|
|
658
|
+
}, _class3);
|
|
659
|
+
function smudgeEffect(brush, strength, mixing = "rgb") {
|
|
660
|
+
const s = Math.min(1, Math.max(0, strength));
|
|
661
|
+
const tip = new (0, _chunkFQPUF2W2cjs.SmudgeTip)({ strength: s, length: s, mixing }, brush.size);
|
|
662
|
+
return (medium, d, rect, cov) => tip.dab(medium, { x: d.x, y: d.y, radius: d.radius, opacity: d.opacity * d.alpha }, rect, cov);
|
|
663
|
+
}
|
|
664
|
+
function spongeEffect(brush, saturate, vibrance) {
|
|
665
|
+
const rgb = [0, 0, 0];
|
|
666
|
+
return (medium, d, rect, cov) => {
|
|
667
|
+
const w = rect.width;
|
|
668
|
+
for (let yy = 0; yy < rect.height; yy++) {
|
|
669
|
+
for (let xx = 0; xx < w; xx++) {
|
|
670
|
+
const cv = cov[yy * w + xx];
|
|
671
|
+
if (cv <= 0) continue;
|
|
672
|
+
const dx = rect.x + xx;
|
|
673
|
+
const dy = rect.y + yy;
|
|
674
|
+
const k = perDabStrength(cv * d.alpha * d.opacity * 0.5, brush.spacing) * medium.selectionAt(dx, dy);
|
|
675
|
+
if (k <= 0) continue;
|
|
676
|
+
const ri = medium.locate(dx, dy, false);
|
|
677
|
+
if (ri < 0 || medium.pixels[ri + 3] === 0) continue;
|
|
678
|
+
const i = medium.locate(dx, dy, true);
|
|
679
|
+
const px = medium.pixels;
|
|
680
|
+
rgb[0] = px[i] / 255;
|
|
681
|
+
rgb[1] = px[i + 1] / 255;
|
|
682
|
+
rgb[2] = px[i + 2] / 255;
|
|
683
|
+
sponge(rgb, k, saturate, vibrance);
|
|
684
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, px, i, rgb[0]);
|
|
685
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, px, i + 1, rgb[1]);
|
|
686
|
+
_chunkFQPUF2W2cjs.put255.call(void 0, px, i + 2, rgb[2]);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function rgbaViewOfGrey(target) {
|
|
692
|
+
const views = /* @__PURE__ */ new Map();
|
|
693
|
+
const dirty = /* @__PURE__ */ new Map();
|
|
694
|
+
const expand = (g) => {
|
|
695
|
+
const out = new Uint8ClampedArray(g.length * 4);
|
|
696
|
+
for (let i = 0; i < g.length; i++) {
|
|
697
|
+
out[i * 4] = out[i * 4 + 1] = out[i * 4 + 2] = g[i];
|
|
698
|
+
out[i * 4 + 3] = 255;
|
|
699
|
+
}
|
|
700
|
+
return out;
|
|
701
|
+
};
|
|
702
|
+
const view = {
|
|
703
|
+
offset: target.offset,
|
|
704
|
+
lockTransparency: true,
|
|
705
|
+
selection: target.selection,
|
|
706
|
+
readTile: (tx, ty) => {
|
|
707
|
+
const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
|
|
708
|
+
let v = views.get(key);
|
|
709
|
+
if (!v) {
|
|
710
|
+
v = expand(_nullishCoalesce(target.readTile(tx, ty), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE))));
|
|
711
|
+
views.set(key, v);
|
|
712
|
+
}
|
|
713
|
+
return v;
|
|
714
|
+
},
|
|
715
|
+
writeTile: (tx, ty) => {
|
|
716
|
+
const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
|
|
717
|
+
let v = views.get(key);
|
|
718
|
+
if (!v) {
|
|
719
|
+
v = expand(_nullishCoalesce(target.readTile(tx, ty), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE))));
|
|
720
|
+
views.set(key, v);
|
|
721
|
+
}
|
|
722
|
+
dirty.set(key, { tx, ty, data: v });
|
|
723
|
+
return v;
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
return {
|
|
727
|
+
target: view,
|
|
728
|
+
flush: () => {
|
|
729
|
+
for (const { tx, ty, data } of dirty.values()) {
|
|
730
|
+
const g = target.writeTile(tx, ty);
|
|
731
|
+
for (let i = 0; i < g.length; i++) g[i] = data[i * 4];
|
|
732
|
+
}
|
|
733
|
+
dirty.clear();
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
function unionRect(a, b) {
|
|
738
|
+
if (!a) return { ...b };
|
|
739
|
+
const x = Math.min(a.x, b.x);
|
|
740
|
+
const y = Math.min(a.y, b.y);
|
|
741
|
+
return { x, y, width: Math.max(a.x + a.width, b.x + b.width) - x, height: Math.max(a.y + a.height, b.y + b.height) - y };
|
|
742
|
+
}
|
|
743
|
+
|
|
83
744
|
// src/paint/wet/model.ts
|
|
84
745
|
var WET_TILE = 256;
|
|
85
746
|
var SLOT_SIDE = 258;
|
|
@@ -776,7 +1437,7 @@ function wetSupport(simd = _nullishCoalesce(simdCache, () => ( typeof WebAssembl
|
|
|
776
1437
|
const g = globalThis;
|
|
777
1438
|
const sharedMemory = canShareMemory();
|
|
778
1439
|
const workers = typeof g.Worker === "function" && typeof Blob === "function" && typeof URL !== "undefined" && typeof URL.createObjectURL === "function";
|
|
779
|
-
const cores = Math.max(1, Math.floor(_nullishCoalesce(_optionalChain([g, 'access',
|
|
1440
|
+
const cores = Math.max(1, Math.floor(_nullishCoalesce(_optionalChain([g, 'access', _2 => _2.navigator, 'optionalAccess', _3 => _3.hardwareConcurrency]), () => ( 1))));
|
|
780
1441
|
let message = null;
|
|
781
1442
|
if (!simd) message = "This browser has no WebAssembly SIMD, so wet paint runs in plain JavaScript: it flows much more slowly (the results are the same).";
|
|
782
1443
|
else if (workers && !sharedMemory)
|
|
@@ -880,8 +1541,8 @@ var WetWorkerPool = class _WetWorkerPool {
|
|
|
880
1541
|
ready.push(
|
|
881
1542
|
new Promise((resolve, reject) => {
|
|
882
1543
|
w.onmessage = (e) => {
|
|
883
|
-
if (_optionalChain([e, 'access',
|
|
884
|
-
else if (_optionalChain([e, 'access',
|
|
1544
|
+
if (_optionalChain([e, 'access', _4 => _4.data, 'optionalAccess', _5 => _5.type]) === "ready") resolve();
|
|
1545
|
+
else if (_optionalChain([e, 'access', _6 => _6.data, 'optionalAccess', _7 => _7.type]) === "error") reject(new Error(e.data.message));
|
|
885
1546
|
};
|
|
886
1547
|
w.onerror = (e) => reject(new Error(e.message || "The wet-media worker failed to start."));
|
|
887
1548
|
})
|
|
@@ -903,8 +1564,8 @@ var WetWorkerPool = class _WetWorkerPool {
|
|
|
903
1564
|
this.workers.map(
|
|
904
1565
|
(w, i) => new Promise((resolve, reject) => {
|
|
905
1566
|
w.onmessage = (e) => {
|
|
906
|
-
if (_optionalChain([e, 'access',
|
|
907
|
-
else if (_optionalChain([e, 'access',
|
|
1567
|
+
if (_optionalChain([e, 'access', _8 => _8.data, 'optionalAccess', _9 => _9.type]) === "done") resolve();
|
|
1568
|
+
else if (_optionalChain([e, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.type]) === "error") reject(new Error(e.data.message));
|
|
908
1569
|
};
|
|
909
1570
|
w.postMessage({ type: "run", steps, workers: n, id: i });
|
|
910
1571
|
})
|
|
@@ -951,53 +1612,53 @@ function makeLayout(width, height) {
|
|
|
951
1612
|
function quantizeHeight(v) {
|
|
952
1613
|
return Math.round(Math.min(1, Math.max(0, v)) * 65536) / 65536;
|
|
953
1614
|
}
|
|
954
|
-
var WetWorld = (
|
|
1615
|
+
var WetWorld = (_class4 = class {
|
|
955
1616
|
|
|
956
1617
|
|
|
957
1618
|
|
|
958
1619
|
/** Steps simulated so far. */
|
|
959
|
-
|
|
1620
|
+
__init9() {this.clock = 0}
|
|
960
1621
|
/** Messages for the user (slots ran out, a backend failed). */
|
|
961
|
-
|
|
1622
|
+
__init10() {this.warnings = []}
|
|
962
1623
|
|
|
963
1624
|
|
|
964
1625
|
|
|
965
1626
|
|
|
966
1627
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1628
|
+
__init11() {this.slotCount = 0}
|
|
1629
|
+
__init12() {this.freeSlots = []}
|
|
1630
|
+
__init13() {this.active = []}
|
|
1631
|
+
__init14() {this.parity = 0}
|
|
1632
|
+
__init15() {this.lanes = new Array(MAX_WET_LANES).fill(null)}
|
|
1633
|
+
__init16() {this.tilt = { ...FLAT }}
|
|
973
1634
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1635
|
+
__init17() {this.paperBytes = new Uint8Array(3)}
|
|
1636
|
+
__init18() {this.kind = "typescript"}
|
|
1637
|
+
__init19() {this.wasm = null}
|
|
1638
|
+
__init20() {this.pool = null}
|
|
1639
|
+
__init21() {this.busyFlag = false}
|
|
1640
|
+
__init22() {this.destroyed = false}
|
|
980
1641
|
|
|
981
|
-
|
|
1642
|
+
__init23() {this.prm = new Float32Array(PARAM_FLOATS)}
|
|
982
1643
|
// Engine B: the GPU mirror (see `attachGpu`).
|
|
983
|
-
|
|
1644
|
+
__init24() {this.gpu = null}
|
|
984
1645
|
/** Live tiles at which the GPU takes over the display (default 16: a fully wet 1024² canvas). */
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1646
|
+
__init25() {this.gpuMinTiles = 16}
|
|
1647
|
+
__init26() {this.gpuLive = false}
|
|
1648
|
+
__init27() {this.gpuFailure = null}
|
|
988
1649
|
/** Slot → rows (1..256, inclusive) to upload; `[0, 257]` means the whole slot. */
|
|
989
|
-
|
|
990
|
-
|
|
1650
|
+
__init28() {this.gpuDirty = /* @__PURE__ */ new Map()}
|
|
1651
|
+
__init29() {this.gpuParamsDirty = true}
|
|
991
1652
|
/**
|
|
992
1653
|
* Lead mode (between strokes): a batch is not sent to the GPU all at once; `gpuLead` steps it
|
|
993
1654
|
* frame by frame while the CPU works through it, so the display moves on before the CPU is done.
|
|
994
1655
|
*/
|
|
995
|
-
|
|
1656
|
+
__init30() {this.gpuLeadMode = false}
|
|
996
1657
|
/** The batch the GPU is working through in lead mode. */
|
|
997
|
-
|
|
1658
|
+
__init31() {this.gpuPlan = null}
|
|
998
1659
|
/** Resolves when the fastest available kernel is running (it may stay `typescript`). */
|
|
999
1660
|
|
|
1000
|
-
constructor(width, height, paper, options = {}) {;
|
|
1661
|
+
constructor(width, height, paper, options = {}) {;_class4.prototype.__init9.call(this);_class4.prototype.__init10.call(this);_class4.prototype.__init11.call(this);_class4.prototype.__init12.call(this);_class4.prototype.__init13.call(this);_class4.prototype.__init14.call(this);_class4.prototype.__init15.call(this);_class4.prototype.__init16.call(this);_class4.prototype.__init17.call(this);_class4.prototype.__init18.call(this);_class4.prototype.__init19.call(this);_class4.prototype.__init20.call(this);_class4.prototype.__init21.call(this);_class4.prototype.__init22.call(this);_class4.prototype.__init23.call(this);_class4.prototype.__init24.call(this);_class4.prototype.__init25.call(this);_class4.prototype.__init26.call(this);_class4.prototype.__init27.call(this);_class4.prototype.__init28.call(this);_class4.prototype.__init29.call(this);_class4.prototype.__init30.call(this);_class4.prototype.__init31.call(this);
|
|
1001
1662
|
if (!(width >= 1 && height >= 1 && width <= 16384 && height <= 16384)) throw new WetWorldError(`A wet canvas must be 1..16384 pixels per side, not ${width}\xD7${height}.`);
|
|
1002
1663
|
this.width = Math.round(width);
|
|
1003
1664
|
this.height = Math.round(height);
|
|
@@ -1052,7 +1713,7 @@ var WetWorld = (_class = class {
|
|
|
1052
1713
|
}
|
|
1053
1714
|
/** The kernel in use and why it is not faster. */
|
|
1054
1715
|
backend() {
|
|
1055
|
-
const threads = _nullishCoalesce(_optionalChain([this, 'access',
|
|
1716
|
+
const threads = _nullishCoalesce(_optionalChain([this, 'access', _12 => _12.pool, 'optionalAccess', _13 => _13.size]), () => ( 1));
|
|
1056
1717
|
let message = this.support.message;
|
|
1057
1718
|
if (this.kind === "typescript" && !message) message = this.wasm ? null : "Wet paint runs in plain JavaScript until the WebAssembly kernel has loaded.";
|
|
1058
1719
|
if (this.kind === "wasm-threads") message = null;
|
|
@@ -1064,17 +1725,17 @@ var WetWorld = (_class = class {
|
|
|
1064
1725
|
}
|
|
1065
1726
|
destroy() {
|
|
1066
1727
|
this.destroyed = true;
|
|
1067
|
-
_optionalChain([this, 'access',
|
|
1728
|
+
_optionalChain([this, 'access', _14 => _14.pool, 'optionalAccess', _15 => _15.destroy, 'call', _16 => _16()]);
|
|
1068
1729
|
this.pool = null;
|
|
1069
1730
|
}
|
|
1070
1731
|
// --- Lanes ---------------------------------------------------------------------
|
|
1071
1732
|
laneOf(id) {
|
|
1072
|
-
const l = this.lanes.find((x) => _optionalChain([x, 'optionalAccess',
|
|
1733
|
+
const l = this.lanes.find((x) => _optionalChain([x, 'optionalAccess', _17 => _17.id]) === id);
|
|
1073
1734
|
if (!l) throw new WetWorldError(`There is no wet layer "${id}".`);
|
|
1074
1735
|
return l;
|
|
1075
1736
|
}
|
|
1076
1737
|
hasLane(id) {
|
|
1077
|
-
return this.lanes.some((x) => _optionalChain([x, 'optionalAccess',
|
|
1738
|
+
return this.lanes.some((x) => _optionalChain([x, 'optionalAccess', _18 => _18.id]) === id);
|
|
1078
1739
|
}
|
|
1079
1740
|
laneIds() {
|
|
1080
1741
|
return this.lanes.filter((l) => Boolean(l)).map((l) => l.id);
|
|
@@ -1082,7 +1743,7 @@ var WetWorld = (_class = class {
|
|
|
1082
1743
|
/** Adds a wet layer (or returns it). Throws when `MAX_WET_LANES` are in use. */
|
|
1083
1744
|
ensureLane(id, options = {}) {
|
|
1084
1745
|
this.requireIdle();
|
|
1085
|
-
const existing = this.lanes.find((x) => _optionalChain([x, 'optionalAccess',
|
|
1746
|
+
const existing = this.lanes.find((x) => _optionalChain([x, 'optionalAccess', _19 => _19.id]) === id);
|
|
1086
1747
|
if (existing) {
|
|
1087
1748
|
if (options.params) this.setParams(id, options.params);
|
|
1088
1749
|
if (options.base) this.setBase(id, options.base);
|
|
@@ -1776,7 +2437,7 @@ var WetWorld = (_class = class {
|
|
|
1776
2437
|
if (!(a > 0)) return;
|
|
1777
2438
|
const key = _chunk474IQG74cjs.tileKey.call(void 0, x >> 8, y >> 8);
|
|
1778
2439
|
const li = (y & 255) * _chunk474IQG74cjs.TILE + (x & 255);
|
|
1779
|
-
let lt = _optionalChain([lightTiles, 'optionalAccess',
|
|
2440
|
+
let lt = _optionalChain([lightTiles, 'optionalAccess', _20 => _20.get, 'call', _21 => _21(key)]);
|
|
1780
2441
|
if (lt && (_nullishCoalesce(lt.uniform, () => ( 1))) !== 0) {
|
|
1781
2442
|
if (!lightWritten.has(key)) {
|
|
1782
2443
|
const data = lt.data.length ? new Uint8ClampedArray(lt.data) : new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE).fill(_nullishCoalesce(lt.uniform, () => ( 0)));
|
|
@@ -1849,7 +2510,7 @@ var WetWorld = (_class = class {
|
|
|
1849
2510
|
if (x1 <= x0 || y1 <= y0) continue;
|
|
1850
2511
|
const whole = x0 === tr.x && y0 === tr.y && x1 >= Math.min(tr.x + WET_TILE, this.width) && y1 >= Math.min(tr.y + WET_TILE, this.height);
|
|
1851
2512
|
if (whole) {
|
|
1852
|
-
if (this.bakeKey(key, true)) bounds =
|
|
2513
|
+
if (this.bakeKey(key, true)) bounds = unionRect2(bounds, { x: tr.x, y: tr.y, width: Math.min(WET_TILE, this.width - tr.x), height: Math.min(WET_TILE, this.height - tr.y) });
|
|
1853
2514
|
this.free(key);
|
|
1854
2515
|
continue;
|
|
1855
2516
|
}
|
|
@@ -1869,7 +2530,7 @@ var WetWorld = (_class = class {
|
|
|
1869
2530
|
f[c + P_SW * PLANE] = 0;
|
|
1870
2531
|
}
|
|
1871
2532
|
}
|
|
1872
|
-
bounds =
|
|
2533
|
+
bounds = unionRect2(bounds, { x: x0, y: y0, width: x1 - x0, height: y1 - y0 });
|
|
1873
2534
|
this.markEdited(lane, x0, y0, x1, y1);
|
|
1874
2535
|
}
|
|
1875
2536
|
this.syncList();
|
|
@@ -1897,7 +2558,7 @@ var WetWorld = (_class = class {
|
|
|
1897
2558
|
lightChanged = true;
|
|
1898
2559
|
}
|
|
1899
2560
|
}
|
|
1900
|
-
const src = _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2561
|
+
const src = _nullishCoalesce(_optionalChain([lane, 'access', _22 => _22.base, 'access', _23 => _23.tiles, 'access', _24 => _24.get, 'call', _25 => _25(tk), 'optionalAccess', _26 => _26.data]), () => ( null));
|
|
1901
2562
|
const out = this.shadeSlot(key, src, all ? "bake-all" : "bake");
|
|
1902
2563
|
if (!out) return lightChanged;
|
|
1903
2564
|
const tiles = new Map(lane.base.tiles);
|
|
@@ -1960,7 +2621,7 @@ var WetWorld = (_class = class {
|
|
|
1960
2621
|
for (const key of this.active) {
|
|
1961
2622
|
if (this.laneIndexOf(key) !== lane.index) continue;
|
|
1962
2623
|
const tk = this.tileKeyOf(key);
|
|
1963
|
-
const out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2624
|
+
const out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access', _27 => _27.base, 'access', _28 => _28.tiles, 'access', _29 => _29.get, 'call', _30 => _30(tk), 'optionalAccess', _31 => _31.data]), () => ( null)), "bake-all");
|
|
1964
2625
|
if (!out) continue;
|
|
1965
2626
|
const t = _chunk474IQG74cjs.finishTile.call(void 0, out, 4, 0);
|
|
1966
2627
|
if (t) tiles.set(tk, t);
|
|
@@ -2083,14 +2744,14 @@ var WetWorld = (_class = class {
|
|
|
2083
2744
|
display(id, maxTiles = Infinity) {
|
|
2084
2745
|
const lane = this.laneOf(id);
|
|
2085
2746
|
const keys = this.active.filter((k) => this.laneIndexOf(k) === lane.index);
|
|
2086
|
-
const stale = keys.filter((k) => _optionalChain([lane, 'access',
|
|
2087
|
-
stale.sort((a, b) => Number(lane.urgent.has(this.tileKeyOf(b))) - Number(lane.urgent.has(this.tileKeyOf(a))) || (_nullishCoalesce(_optionalChain([lane, 'access',
|
|
2747
|
+
const stale = keys.filter((k) => _optionalChain([lane, 'access', _32 => _32.shaded, 'access', _33 => _33.get, 'call', _34 => _34(this.tileKeyOf(k)), 'optionalAccess', _35 => _35.stamp]) !== lane.stamp);
|
|
2748
|
+
stale.sort((a, b) => Number(lane.urgent.has(this.tileKeyOf(b))) - Number(lane.urgent.has(this.tileKeyOf(a))) || (_nullishCoalesce(_optionalChain([lane, 'access', _36 => _36.shaded, 'access', _37 => _37.get, 'call', _38 => _38(this.tileKeyOf(a)), 'optionalAccess', _39 => _39.stamp]), () => ( 0))) - (_nullishCoalesce(_optionalChain([lane, 'access', _40 => _40.shaded, 'access', _41 => _41.get, 'call', _42 => _42(this.tileKeyOf(b)), 'optionalAccess', _43 => _43.stamp]), () => ( 0))));
|
|
2088
2749
|
const changed = [];
|
|
2089
2750
|
let done = 0;
|
|
2090
2751
|
for (const key of stale) {
|
|
2091
2752
|
if (done >= maxTiles) break;
|
|
2092
2753
|
const tk = this.tileKeyOf(key);
|
|
2093
|
-
const src = _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2754
|
+
const src = _nullishCoalesce(_optionalChain([lane, 'access', _44 => _44.base, 'access', _45 => _45.tiles, 'access', _46 => _46.get, 'call', _47 => _47(tk), 'optionalAccess', _48 => _48.data]), () => ( null));
|
|
2094
2755
|
const out = this.shadeSlot(key, src, "display");
|
|
2095
2756
|
const tile = out ? _chunk474IQG74cjs.finishTile.call(void 0, out, 4, 0) : _nullishCoalesce(lane.base.tiles.get(tk), () => ( null));
|
|
2096
2757
|
lane.shaded.set(tk, { stamp: lane.stamp, tile: _nullishCoalesce(tile, () => ( { data: new Uint8ClampedArray(0), uniform: 0 })) });
|
|
@@ -2127,7 +2788,7 @@ var WetWorld = (_class = class {
|
|
|
2127
2788
|
for (const key2 of keys) {
|
|
2128
2789
|
const tk = this.tileKeyOf(key2);
|
|
2129
2790
|
live.add(tk);
|
|
2130
|
-
if (_optionalChain([lane, 'access',
|
|
2791
|
+
if (_optionalChain([lane, 'access', _49 => _49.lightShaded, 'access', _50 => _50.get, 'call', _51 => _51(tk), 'optionalAccess', _52 => _52.stamp]) === lane.stamp) continue;
|
|
2131
2792
|
const src = _nullishCoalesce(lane.light.tiles.get(tk), () => ( null));
|
|
2132
2793
|
const out = this.shadeLightSlot(key2, src, "display");
|
|
2133
2794
|
lane.lightShaded.set(tk, { stamp: lane.stamp, tile: out ? _chunk474IQG74cjs.finishTile.call(void 0, out, 1, 0) : src });
|
|
@@ -2325,7 +2986,7 @@ var WetWorld = (_class = class {
|
|
|
2325
2986
|
if (!this.gpu || this.busyFlag && !plan || !plan && !this.gpuDecide()) return { ...this.display(id, maxCpuTiles), gpu: false };
|
|
2326
2987
|
const lane = this.laneOf(id);
|
|
2327
2988
|
const keys = this.active.filter((k) => this.laneIndexOf(k) === lane.index);
|
|
2328
|
-
const stale = plan ? keys : keys.filter((k) => _optionalChain([lane, 'access',
|
|
2989
|
+
const stale = plan ? keys : keys.filter((k) => _optionalChain([lane, 'access', _53 => _53.shaded, 'access', _54 => _54.get, 'call', _55 => _55(this.tileKeyOf(k)), 'optionalAccess', _56 => _56.stamp]) !== lane.stamp);
|
|
2329
2990
|
if (!stale.length) return { ...this.display(id, 0), gpu: true };
|
|
2330
2991
|
let tiles;
|
|
2331
2992
|
const stamp = lane.stamp;
|
|
@@ -2333,7 +2994,7 @@ var WetWorld = (_class = class {
|
|
|
2333
2994
|
try {
|
|
2334
2995
|
if (!plan) this.gpuSync();
|
|
2335
2996
|
const parity = plan ? plan.parity + plan.done & 1 : this.parity;
|
|
2336
|
-
tiles = await this.gpu.shade(this.gpuJobs(stale), parity, stale.map((k) => _nullishCoalesce(_optionalChain([base, 'access',
|
|
2997
|
+
tiles = await this.gpu.shade(this.gpuJobs(stale), parity, stale.map((k) => _nullishCoalesce(_optionalChain([base, 'access', _57 => _57.tiles, 'access', _58 => _58.get, 'call', _59 => _59(this.tileKeyOf(k)), 'optionalAccess', _60 => _60.data]), () => ( null))), [this.paperBytes[0], this.paperBytes[1], this.paperBytes[2]]);
|
|
2337
2998
|
} catch (e) {
|
|
2338
2999
|
this.gpuStop(`Wet paint stopped using the GPU (${e.message}).`);
|
|
2339
3000
|
return { ...this.display(id, maxCpuTiles), gpu: false };
|
|
@@ -2415,7 +3076,7 @@ var WetWorld = (_class = class {
|
|
|
2415
3076
|
const slot = this.slotOf(lane.index * this.layout.perLane + ty * this.layout.tilesX + tx);
|
|
2416
3077
|
return slot < 0 ? -1 : this.slotBase(slot);
|
|
2417
3078
|
}
|
|
2418
|
-
},
|
|
3079
|
+
}, _class4);
|
|
2419
3080
|
function moveWetSnapshot(snap, from, to, dx, dy, lane = () => ({})) {
|
|
2420
3081
|
if (!Number.isInteger(dx / WET_TILE) || !Number.isInteger(dy / WET_TILE)) throw new WetWorldError(`Wet paint moves by whole ${WET_TILE} px tiles, not (${dx}, ${dy}).`);
|
|
2421
3082
|
const a = makeLayout(from.width, from.height);
|
|
@@ -2439,7 +3100,7 @@ function moveWetSnapshot(snap, from, to, dx, dy, lane = () => ({})) {
|
|
|
2439
3100
|
});
|
|
2440
3101
|
return { clock: snap.clock, tilt: { ...snap.tilt }, lanes, slots, bytes };
|
|
2441
3102
|
}
|
|
2442
|
-
function
|
|
3103
|
+
function unionRect2(a, b) {
|
|
2443
3104
|
if (!a) return { ...b };
|
|
2444
3105
|
const x = Math.min(a.x, b.x);
|
|
2445
3106
|
const y = Math.min(a.y, b.y);
|
|
@@ -2512,8 +3173,8 @@ function normalizeFlow(raw = {}, base = DEFAULT_FLOW) {
|
|
|
2512
3173
|
}
|
|
2513
3174
|
function flowField(spec, width, height) {
|
|
2514
3175
|
const k = FLOW_ACCEL;
|
|
2515
|
-
const cx = _nullishCoalesce(_optionalChain([spec, 'access',
|
|
2516
|
-
const cy = _nullishCoalesce(_optionalChain([spec, 'access',
|
|
3176
|
+
const cx = _nullishCoalesce(_optionalChain([spec, 'access', _61 => _61.center, 'optionalAccess', _62 => _62.x]), () => ( width / 2));
|
|
3177
|
+
const cy = _nullishCoalesce(_optionalChain([spec, 'access', _63 => _63.center, 'optionalAccess', _64 => _64.y]), () => ( height / 2));
|
|
2517
3178
|
const r0 = Math.max(width, height) / 2;
|
|
2518
3179
|
switch (spec.kind) {
|
|
2519
3180
|
case "none":
|
|
@@ -2545,8 +3206,8 @@ function flowField(spec, width, height) {
|
|
|
2545
3206
|
|
|
2546
3207
|
// src/paint/wet/medium.ts
|
|
2547
3208
|
var SAMPLE_K = 3;
|
|
2548
|
-
var WetMedium = (
|
|
2549
|
-
constructor(world, laneId, options) {;
|
|
3209
|
+
var WetMedium = (_class5 = class {
|
|
3210
|
+
constructor(world, laneId, options) {;_class5.prototype.__init32.call(this);
|
|
2550
3211
|
this.world = world;
|
|
2551
3212
|
this.laneId = laneId;
|
|
2552
3213
|
this.options = options;
|
|
@@ -2554,7 +3215,7 @@ var WetMedium = (_class2 = class {
|
|
|
2554
3215
|
|
|
2555
3216
|
|
|
2556
3217
|
|
|
2557
|
-
|
|
3218
|
+
__init32() {this.pig = new Float64Array(4)}
|
|
2558
3219
|
sample(rect, cov) {
|
|
2559
3220
|
const s = this.world.sample(this.laneId, rect, cov);
|
|
2560
3221
|
if (!(s.wet > 0) || !(s.weight > 0)) return null;
|
|
@@ -2587,7 +3248,7 @@ var WetMedium = (_class2 = class {
|
|
|
2587
3248
|
const pig = [0, 1, 2, 3].map((q) => this.pig[q] * mass * dep);
|
|
2588
3249
|
this.world.paint(this.laneId, rect, cov, water * dep, mass > 0 ? pig : null, null, light);
|
|
2589
3250
|
}
|
|
2590
|
-
},
|
|
3251
|
+
}, _class5);
|
|
2591
3252
|
|
|
2592
3253
|
// src/paint/wet/gpu-kernels.ts
|
|
2593
3254
|
var GPU_JOB_WORDS = 16;
|
|
@@ -2976,7 +3637,7 @@ var UNIFORM = 64;
|
|
|
2976
3637
|
var STORAGE = 128;
|
|
2977
3638
|
function findWebGpu() {
|
|
2978
3639
|
const nav = globalThis.navigator;
|
|
2979
|
-
return _nullishCoalesce(_optionalChain([nav, 'optionalAccess',
|
|
3640
|
+
return _nullishCoalesce(_optionalChain([nav, 'optionalAccess', _65 => _65.gpu]), () => ( null));
|
|
2980
3641
|
}
|
|
2981
3642
|
async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
2982
3643
|
const no = (reason, adapter2 = null) => ({ engine: null, support: { supported: false, reason, adapter: adapter2, maxSlots: 0 } });
|
|
@@ -2988,7 +3649,7 @@ async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
|
2988
3649
|
return no(`WebGPU gave no adapter (${e.message}); wet paint runs on the CPU.`);
|
|
2989
3650
|
}
|
|
2990
3651
|
if (!adapter) return no("WebGPU gave no adapter (the GPU may be blocklisted); wet paint runs on the CPU.");
|
|
2991
|
-
const name = [_optionalChain([adapter, 'access',
|
|
3652
|
+
const name = [_optionalChain([adapter, 'access', _66 => _66.info, 'optionalAccess', _67 => _67.vendor]), _optionalChain([adapter, 'access', _68 => _68.info, 'optionalAccess', _69 => _69.architecture])].filter(Boolean).join(" ") || null;
|
|
2992
3653
|
const binding = Math.min(_nullishCoalesce(adapter.limits.maxStorageBufferBindingSize, () => ( 0)), _nullishCoalesce(adapter.limits.maxBufferSize, () => ( 0)));
|
|
2993
3654
|
const maxSlots = Math.min(MAX_WET_SLOTS, Math.floor(binding / SLOT_BYTES));
|
|
2994
3655
|
if (maxSlots < 4) return no(`The GPU's storage buffers hold ${Math.max(0, maxSlots)} wet tiles; at least 4 are needed. Wet paint runs on the CPU.`, name);
|
|
@@ -3008,32 +3669,32 @@ async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
|
3008
3669
|
const engine = await WetGpuEngine.start(device, maxSlots, name);
|
|
3009
3670
|
return { engine, support: { supported: true, reason: null, adapter: name, maxSlots } };
|
|
3010
3671
|
} catch (e) {
|
|
3011
|
-
_optionalChain([device, 'access',
|
|
3672
|
+
_optionalChain([device, 'access', _70 => _70.destroy, 'optionalCall', _71 => _71()]);
|
|
3012
3673
|
return no(`The wet-media shaders did not compile on this GPU (${e.message}); wet paint runs on the CPU.`, name);
|
|
3013
3674
|
}
|
|
3014
3675
|
}
|
|
3015
3676
|
async function wetGpuSupport(gpu = findWebGpu()) {
|
|
3016
3677
|
const { engine, support } = await createWetGpuEngine(gpu);
|
|
3017
|
-
_optionalChain([engine, 'optionalAccess',
|
|
3678
|
+
_optionalChain([engine, 'optionalAccess', _72 => _72.destroy, 'call', _73 => _73()]);
|
|
3018
3679
|
return support;
|
|
3019
3680
|
}
|
|
3020
3681
|
async function pipeline(device, code, label) {
|
|
3021
|
-
_optionalChain([device, 'access',
|
|
3682
|
+
_optionalChain([device, 'access', _74 => _74.pushErrorScope, 'optionalCall', _75 => _75("validation")]);
|
|
3022
3683
|
const module = device.createShaderModule({ code, label });
|
|
3023
|
-
const info = await _optionalChain([module, 'access',
|
|
3024
|
-
const errors = _nullishCoalesce(_optionalChain([info, 'optionalAccess',
|
|
3684
|
+
const info = await _optionalChain([module, 'access', _76 => _76.getCompilationInfo, 'optionalCall', _77 => _77()]);
|
|
3685
|
+
const errors = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _78 => _78.messages, 'access', _79 => _79.filter, 'call', _80 => _80((m) => m.type === "error")]), () => ( []));
|
|
3025
3686
|
if (errors.length) {
|
|
3026
|
-
await _optionalChain([device, 'access',
|
|
3687
|
+
await _optionalChain([device, 'access', _81 => _81.popErrorScope, 'optionalCall', _82 => _82()]);
|
|
3027
3688
|
throw new Error(`${label}: ${errors.map((m) => `line ${m.lineNum}: ${m.message}`).join("; ")}`);
|
|
3028
3689
|
}
|
|
3029
3690
|
const desc = { layout: "auto", compute: { module, entryPoint: "main" }, label };
|
|
3030
3691
|
const p = device.createComputePipelineAsync ? await device.createComputePipelineAsync(desc) : device.createComputePipeline(desc);
|
|
3031
|
-
const err = await _optionalChain([device, 'access',
|
|
3692
|
+
const err = await _optionalChain([device, 'access', _83 => _83.popErrorScope, 'optionalCall', _84 => _84()]);
|
|
3032
3693
|
if (err) throw new Error(`${label}: ${err.message}`);
|
|
3033
3694
|
return p;
|
|
3034
3695
|
}
|
|
3035
|
-
var WetGpuEngine = (
|
|
3036
|
-
constructor(device, maxSlots, adapter, stepPipe, haloPipe, shadePipe) {;
|
|
3696
|
+
var WetGpuEngine = (_class6 = class _WetGpuEngine {
|
|
3697
|
+
constructor(device, maxSlots, adapter, stepPipe, haloPipe, shadePipe) {;_class6.prototype.__init33.call(this);_class6.prototype.__init34.call(this);_class6.prototype.__init35.call(this);_class6.prototype.__init36.call(this);_class6.prototype.__init37.call(this);_class6.prototype.__init38.call(this);_class6.prototype.__init39.call(this);_class6.prototype.__init40.call(this);_class6.prototype.__init41.call(this);
|
|
3037
3698
|
this.device = device;
|
|
3038
3699
|
this.maxSlots = maxSlots;
|
|
3039
3700
|
this.adapter = adapter;
|
|
@@ -3054,8 +3715,8 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3054
3715
|
return b;
|
|
3055
3716
|
});
|
|
3056
3717
|
this.shadeUni = d.createBuffer({ size: 16, usage: UNIFORM | COPY_DST, label: "wet shade" });
|
|
3057
|
-
void _optionalChain([device, 'access',
|
|
3058
|
-
this.lostReason = _optionalChain([info, 'optionalAccess',
|
|
3718
|
+
void _optionalChain([device, 'access', _85 => _85.lost, 'optionalAccess', _86 => _86.then, 'call', _87 => _87((info) => {
|
|
3719
|
+
this.lostReason = _optionalChain([info, 'optionalAccess', _88 => _88.message]) || _optionalChain([info, 'optionalAccess', _89 => _89.reason]) || "the GPU device was lost";
|
|
3059
3720
|
})]);
|
|
3060
3721
|
}
|
|
3061
3722
|
|
|
@@ -3065,23 +3726,23 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3065
3726
|
|
|
3066
3727
|
|
|
3067
3728
|
/** Steps run on the GPU so far (for stats). */
|
|
3068
|
-
|
|
3729
|
+
__init33() {this.steps = 0}
|
|
3069
3730
|
/** Set once the device is lost; the engine does nothing after that. */
|
|
3070
|
-
|
|
3731
|
+
__init34() {this.lostReason = null}
|
|
3071
3732
|
|
|
3072
|
-
|
|
3733
|
+
__init35() {this.slots = 0}
|
|
3073
3734
|
|
|
3074
3735
|
|
|
3075
|
-
|
|
3736
|
+
__init36() {this.jobCap = 0}
|
|
3076
3737
|
|
|
3077
3738
|
|
|
3078
3739
|
|
|
3079
3740
|
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3741
|
+
__init37() {this.srcTiles = null}
|
|
3742
|
+
__init38() {this.outTiles = null}
|
|
3743
|
+
__init39() {this.outRead = null}
|
|
3744
|
+
__init40() {this.tileCap = 0}
|
|
3745
|
+
__init41() {this.groups = null}
|
|
3085
3746
|
/** @internal Compiles the kernels; use `createWetGpuEngine`. */
|
|
3086
3747
|
static async start(device, maxSlots, adapter) {
|
|
3087
3748
|
const [step, halo, shade] = await Promise.all([pipeline(device, WGSL_STEP, "wet step"), pipeline(device, WGSL_HALO, "wet halo"), pipeline(device, WGSL_SHADE, "wet shade")]);
|
|
@@ -3089,7 +3750,7 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3089
3750
|
}
|
|
3090
3751
|
/** Bytes of GPU memory in use. */
|
|
3091
3752
|
memoryBytes() {
|
|
3092
|
-
return this.state.size + this.jobs.size + (_nullishCoalesce(_optionalChain([this, 'access',
|
|
3753
|
+
return this.state.size + this.jobs.size + (_nullishCoalesce(_optionalChain([this, 'access', _90 => _90.srcTiles, 'optionalAccess', _91 => _91.size]), () => ( 0))) + (_nullishCoalesce(_optionalChain([this, 'access', _92 => _92.outTiles, 'optionalAccess', _93 => _93.size]), () => ( 0))) * 2;
|
|
3093
3754
|
}
|
|
3094
3755
|
/** Slots the state buffer holds now. */
|
|
3095
3756
|
get capacity() {
|
|
@@ -3238,9 +3899,9 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3238
3899
|
const d = this.device;
|
|
3239
3900
|
const tileBytes = TILE_WORDS * 4;
|
|
3240
3901
|
if (n > this.tileCap || !this.outTiles || !this.outRead || !this.srcTiles) {
|
|
3241
|
-
_optionalChain([this, 'access',
|
|
3242
|
-
_optionalChain([this, 'access',
|
|
3243
|
-
_optionalChain([this, 'access',
|
|
3902
|
+
_optionalChain([this, 'access', _94 => _94.srcTiles, 'optionalAccess', _95 => _95.destroy, 'call', _96 => _96()]);
|
|
3903
|
+
_optionalChain([this, 'access', _97 => _97.outTiles, 'optionalAccess', _98 => _98.destroy, 'call', _99 => _99()]);
|
|
3904
|
+
_optionalChain([this, 'access', _100 => _100.outRead, 'optionalAccess', _101 => _101.destroy, 'call', _102 => _102()]);
|
|
3244
3905
|
this.tileCap = Math.max(n, this.tileCap * 2, 4);
|
|
3245
3906
|
this.srcTiles = d.createBuffer({ size: this.tileCap * tileBytes, usage: STORAGE | COPY_DST, label: "wet base tiles" });
|
|
3246
3907
|
this.outTiles = d.createBuffer({ size: this.tileCap * tileBytes, usage: STORAGE | COPY_SRC, label: "wet shaded tiles" });
|
|
@@ -3294,10 +3955,10 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3294
3955
|
return this.device.queue.onSubmittedWorkDone();
|
|
3295
3956
|
}
|
|
3296
3957
|
destroy() {
|
|
3297
|
-
for (const b of [this.state, this.params, this.jobs, this.flags, this.flagsRead, ...this.uni, this.shadeUni, this.srcTiles, this.outTiles, this.outRead]) _optionalChain([b, 'optionalAccess',
|
|
3958
|
+
for (const b of [this.state, this.params, this.jobs, this.flags, this.flagsRead, ...this.uni, this.shadeUni, this.srcTiles, this.outTiles, this.outRead]) _optionalChain([b, 'optionalAccess', _103 => _103.destroy, 'call', _104 => _104()]);
|
|
3298
3959
|
this.device.destroy();
|
|
3299
3960
|
}
|
|
3300
|
-
},
|
|
3961
|
+
}, _class6);
|
|
3301
3962
|
|
|
3302
3963
|
// src/paint/pointer.ts
|
|
3303
3964
|
function pointerPressure(e) {
|
|
@@ -3320,7 +3981,7 @@ function pointerStrokeSample(e, toPoint) {
|
|
|
3320
3981
|
return s;
|
|
3321
3982
|
}
|
|
3322
3983
|
function pointerStrokeSamples(e, toPoint) {
|
|
3323
|
-
const events = _nullishCoalesce(_optionalChain([e, 'access',
|
|
3984
|
+
const events = _nullishCoalesce(_optionalChain([e, 'access', _105 => _105.getCoalescedEvents, 'optionalCall', _106 => _106()]), () => ( []));
|
|
3324
3985
|
return (events.length ? events : [e]).map((ev) => pointerStrokeSample(ev, toPoint));
|
|
3325
3986
|
}
|
|
3326
3987
|
|
|
@@ -3419,4 +4080,34 @@ function pointerStrokeSamples(e, toPoint) {
|
|
|
3419
4080
|
|
|
3420
4081
|
|
|
3421
4082
|
|
|
3422
|
-
|
|
4083
|
+
|
|
4084
|
+
|
|
4085
|
+
|
|
4086
|
+
|
|
4087
|
+
|
|
4088
|
+
|
|
4089
|
+
|
|
4090
|
+
|
|
4091
|
+
|
|
4092
|
+
|
|
4093
|
+
|
|
4094
|
+
|
|
4095
|
+
|
|
4096
|
+
|
|
4097
|
+
|
|
4098
|
+
|
|
4099
|
+
|
|
4100
|
+
|
|
4101
|
+
|
|
4102
|
+
|
|
4103
|
+
|
|
4104
|
+
|
|
4105
|
+
|
|
4106
|
+
|
|
4107
|
+
|
|
4108
|
+
|
|
4109
|
+
|
|
4110
|
+
|
|
4111
|
+
|
|
4112
|
+
|
|
4113
|
+
exports.createPigmentTools = createPigmentTools; exports.TONE_RANGES = TONE_RANGES; exports.luma = luma; exports.dodgeBurnCurve = dodgeBurnCurve; exports.dodgeBurn = dodgeBurn; exports.saturationOf = saturationOf; exports.sponge = sponge; exports.perDabStrength = perDabStrength; exports.RETOUCH_SAMPLES = RETOUCH_SAMPLES; exports.SPOT_HEAL_TYPES = SPOT_HEAL_TYPES; exports.DEFAULT_RETOUCH = DEFAULT_RETOUCH; exports.normalizeRetouch = normalizeRetouch; exports.boxBlurPixels = boxBlurPixels; exports.retouchFilter = retouchFilter; exports.IDENTITY_CLONE_TRANSFORM = IDENTITY_CLONE_TRANSFORM; exports.isIdentityCloneTransform = isIdentityCloneTransform; exports.cloneSamplePoint = cloneSamplePoint; exports.TransformedPixelSource = TransformedPixelSource; exports.TilePixelSource = TilePixelSource; exports.RegionPixelSource = RegionPixelSource; exports.readSourceRegion = readSourceRegion; exports.applyRetouchToTile = applyRetouchToTile; exports.applyToneToDeepTile = applyToneToDeepTile; exports.toneOf = toneOf; exports.healPixels = healPixels; exports.spotHealPixels = spotHealPixels; exports.spotHealWindow = spotHealWindow; exports.RetouchDabStroke = RetouchDabStroke; exports.smudgeEffect = smudgeEffect; exports.spongeEffect = spongeEffect; exports.rgbaViewOfGrey = rgbaViewOfGrey; exports.WET_TILE = WET_TILE; exports.SLOT_SIDE = SLOT_SIDE; exports.PLANE = PLANE; exports.PLANE_BYTES = PLANE_BYTES; exports.SET_PLANES = SET_PLANES; exports.P_RHO = P_RHO; exports.P_UX = P_UX; exports.P_UY = P_UY; exports.P_SW = P_SW; exports.P_P0 = P_P0; exports.P_L = P_L; exports.P_EDGE = P_EDGE; exports.P_D0 = P_D0; exports.P_DL = P_DL; exports.P_H = P_H; exports.P_FX = P_FX; exports.P_FY = P_FY; exports.SLOT_PLANES = SLOT_PLANES; exports.SLOT_BYTES = SLOT_BYTES; exports.PIGMENT_CHANNELS = PIGMENT_CHANNELS; exports.MASS_CHANNELS = MASS_CHANNELS; exports.EX = EX; exports.EY = EY; exports.OPP = OPP; exports.W9 = W9; exports.DRY_EPS = DRY_EPS; exports.U_MAX = U_MAX; exports.STRIP = STRIP; exports.MAX_BATCH = MAX_BATCH; exports.FREE_INTERVAL = FREE_INTERVAL; exports.FLAG_ALIVE = FLAG_ALIVE; exports.FLAG_LEFT = FLAG_LEFT; exports.FLAG_RIGHT = FLAG_RIGHT; exports.FLAG_TOP = FLAG_TOP; exports.FLAG_BOTTOM = FLAG_BOTTOM; exports.FLAG_WET = FLAG_WET; exports.PARAM_FLOATS = PARAM_FLOATS; exports.PARAM = PARAM; exports.DEFAULT_WET_PARAMS = DEFAULT_WET_PARAMS; exports.WET_PARAM_KEYS = WET_PARAM_KEYS; exports.DEFAULT_WET_PAPER = DEFAULT_WET_PAPER; exports.FLAT = FLAT; exports.normalizeWetParams = normalizeWetParams; exports.normalizeTilt = normalizeTilt; exports.latticeViscosity = latticeViscosity; exports.PAPER_CAPACITY = PAPER_CAPACITY; exports.MAX_TILT_ACCEL = MAX_TILT_ACCEL; exports.packWetParams = packWetParams; exports.edgeBits = edgeBits; exports.PIGMENT_UNIT = PIGMENT_UNIT; exports.HIDE = HIDE; exports.BODY_SCATTER = BODY_SCATTER; exports.dexp = dexp; exports.dlog = dlog; exports.dpow = dpow; exports.SRGB_TO_LINEAR = SRGB_TO_LINEAR; exports.srgbByteToLinear = srgbByteToLinear; exports.linearToSrgb8 = linearToSrgb8; exports.pigmentOf = pigmentOf; exports.expNeg = expNeg; exports.filmReflectance = filmReflectance; exports.pigmentColor = pigmentColor; exports.filmPixel = filmPixel; exports.pixelPigment = pixelPigment; exports.shadeTile = shadeTile; exports.shadeLightTile = shadeLightTile; exports.stepSlotTs = stepSlotTs; exports.loadWetKernel = loadWetKernel; exports.canShareMemory = canShareMemory; exports.wetSimdSupported = wetSimdSupported; exports.wetSupport = wetSupport; exports.WetWorkerPool = WetWorkerPool; exports.MAX_WET_LANES = MAX_WET_LANES; exports.MAX_WET_SLOTS = MAX_WET_SLOTS; exports.WetWorldError = WetWorldError; exports.WetWorld = WetWorld; exports.moveWetSnapshot = moveWetSnapshot; exports.WET_FLOW_KINDS = WET_FLOW_KINDS; exports.DEFAULT_FLOW = DEFAULT_FLOW; exports.dsincos = dsincos; exports.normalizeFlow = normalizeFlow; exports.flowField = flowField; exports.WetMedium = WetMedium; exports.WGSL_STEP = WGSL_STEP; exports.WGSL_HALO = WGSL_HALO; exports.WGSL_SHADE = WGSL_SHADE; exports.findWebGpu = findWebGpu; exports.createWetGpuEngine = createWetGpuEngine; exports.wetGpuSupport = wetGpuSupport; exports.WetGpuEngine = WetGpuEngine; exports.pointerPressure = pointerPressure; exports.pointerStrokeSample = pointerStrokeSample; exports.pointerStrokeSamples = pointerStrokeSamples;
|