@pixerate/editor 0.266.2 → 0.267.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/controller.d.cts +8 -0
- package/dist/animation-editor/controller.d.ts +8 -0
- package/dist/animation-editor/effect-tools.d.cts +1 -1
- package/dist/animation-editor/effect-tools.d.ts +1 -1
- package/dist/animation-editor/index.cjs +172 -105
- package/dist/animation-editor/index.js +91 -24
- package/dist/brushes/index.cjs +59 -59
- package/dist/brushes/index.js +5 -5
- package/dist/brushes/profiles.d.cts +6 -1
- package/dist/brushes/profiles.d.ts +6 -1
- package/dist/{brushstrokeRender-FSUWXUZY.cjs → brushstrokeRender-L7JYRR2R.cjs} +16 -16
- package/dist/{brushstrokeRender-KD453OBX.js → brushstrokeRender-NLFPEBGI.js} +4 -4
- package/dist/canvas/brushTypes.d.cts +12 -0
- package/dist/canvas/brushTypes.d.ts +12 -0
- package/dist/canvas/brushstroke.d.cts +1 -1
- package/dist/canvas/brushstroke.d.ts +1 -1
- package/dist/canvas/drawController.d.cts +19 -4
- package/dist/canvas/drawController.d.ts +19 -4
- package/dist/canvas/index.cjs +144 -105
- package/dist/canvas/index.js +46 -7
- package/dist/{chunk-XORJ7UZO.cjs → chunk-3VHH6V67.cjs} +13 -12
- package/dist/{chunk-T2LDTEXK.js → chunk-4IDUYB45.js} +2217 -56
- package/dist/chunk-7UKFXXWL.js +802 -0
- package/dist/chunk-ADMRNWR7.js +340 -0
- package/dist/{chunk-CIJBSUM5.js → chunk-AGNUD5BI.js} +2 -2
- package/dist/{chunk-WLUVZKVD.cjs → chunk-DT4YQUGT.cjs} +32 -32
- package/dist/{chunk-DXYHQ2VN.js → chunk-EF7LZAXQ.js} +1 -1
- package/dist/chunk-EXB2EGBE.cjs +802 -0
- package/dist/{chunk-4ODRXQRW.js → chunk-EYSHTYLG.js} +1 -1
- package/dist/{chunk-R44Y3EFS.js → chunk-FGJHJIMN.js} +8 -336
- package/dist/{chunk-AQZQWXEU.cjs → chunk-G7NHE2VD.cjs} +35 -35
- package/dist/{chunk-XC6DPRYI.js → chunk-GSTSZPSR.js} +154 -949
- package/dist/{chunk-VRK322ZC.cjs → chunk-HIO6E7LC.cjs} +2 -2
- package/dist/{chunk-TOID45I2.cjs → chunk-J2TNIZ55.cjs} +1 -1
- package/dist/{chunk-YHDHFJUC.cjs → chunk-J5VQYK7T.cjs} +217 -1012
- package/dist/{chunk-3C33YTNN.js → chunk-JGWVZPT6.js} +2 -2
- package/dist/{chunk-ACFSFUQH.js → chunk-JL6YH5WD.js} +4 -0
- package/dist/{chunk-3SBLVGOM.cjs → chunk-LA5Y4ETA.cjs} +23 -23
- package/dist/{chunk-MVUQSK5J.cjs → chunk-LHPEG5AU.cjs} +107 -435
- package/dist/{chunk-DOZ6F2K2.js → chunk-NSETJI74.js} +3 -2
- package/dist/{chunk-XRXFVRGY.cjs → chunk-OKHKA43L.cjs} +2364 -203
- package/dist/{chunk-LK4SXL3V.js → chunk-OSEXT7JL.js} +1 -1
- package/dist/{chunk-PE6YJMQT.cjs → chunk-PFHJS4HE.cjs} +20 -19
- package/dist/{chunk-7KNW3WXZ.cjs → chunk-QEVLRLUN.cjs} +63 -0
- package/dist/{chunk-OTN6VB5S.cjs → chunk-RDFHWAHL.cjs} +5 -1
- package/dist/{chunk-6JL2D5SG.js → chunk-VE6UKYQ2.js} +3 -2
- package/dist/{chunk-RFJZGTHA.cjs → chunk-XVOP3CGQ.cjs} +9 -9
- package/dist/{chunk-EZOJBP4D.js → chunk-YIC6MAJ2.js} +1 -1
- package/dist/chunk-YZWM6ZIP.cjs +340 -0
- package/dist/{chunk-472INMWH.js → chunk-ZA7L5YJB.js} +63 -0
- package/dist/commands/builtins.d.cts +12 -1
- package/dist/commands/builtins.d.ts +12 -1
- package/dist/commands/index.cjs +2 -2
- package/dist/commands/index.js +1 -1
- package/dist/image-editor/controller.d.cts +1 -1
- package/dist/image-editor/controller.d.ts +1 -1
- package/dist/image-editor/index.cjs +837 -833
- package/dist/image-editor/index.js +105 -101
- package/dist/paint/index.cjs +5 -3
- package/dist/paint/index.js +46 -44
- package/dist/paint-editor/controller.d.cts +5 -3
- package/dist/paint-editor/controller.d.ts +5 -3
- package/dist/paint-editor/index.cjs +832 -2295
- package/dist/paint-editor/index.js +285 -1748
- package/dist/paint-editor/path-samples.d.cts +2 -0
- package/dist/paint-editor/path-samples.d.ts +2 -0
- package/dist/paint-editor/presence.d.cts +20 -1
- package/dist/paint-editor/presence.d.ts +20 -1
- package/dist/stickers/helpers.d.cts +2 -0
- package/dist/stickers/helpers.d.ts +2 -0
- package/dist/stickers/index.cjs +41 -35
- package/dist/stickers/index.js +22 -16
- package/dist/stickers/types.d.cts +4 -2
- package/dist/stickers/types.d.ts +4 -2
- package/dist/vector/backdrop.d.cts +13 -0
- package/dist/vector/backdrop.d.ts +13 -0
- package/dist/vector/brushstroke.d.cts +54 -7
- package/dist/vector/brushstroke.d.ts +54 -7
- package/dist/vector/brushstrokeMedia.d.cts +96 -0
- package/dist/vector/brushstrokeMedia.d.ts +96 -0
- package/dist/vector/controller.d.cts +17 -3
- package/dist/vector/controller.d.ts +17 -3
- package/dist/vector/index.cjs +1846 -1386
- package/dist/vector/index.d.cts +2 -0
- package/dist/vector/index.d.ts +2 -0
- package/dist/vector/index.js +517 -57
- package/dist/vector/render.d.cts +6 -0
- package/dist/vector/render.d.ts +6 -0
- package/dist/vector/types.d.cts +14 -0
- package/dist/vector/types.d.ts +14 -0
- package/package.json +1 -1
- package/skills/pixerate-animation-editor/SKILL.md +1 -0
- package/skills/pixerate-brushes/SKILL.md +2 -2
- package/skills/pixerate-brushes-design/SKILL.md +7 -4
- package/skills/pixerate-brushes-design/evals/port-to-vector.json +8 -8
- package/skills/pixerate-canvas/SKILL.md +11 -1
- package/skills/pixerate-image-editor/SKILL.md +19 -64
- package/skills/pixerate-image-editor/references/color-management.md +2 -1
- package/skills/pixerate-image-editor/references/free-transform.md +12 -0
- package/skills/pixerate-image-editor/references/layer-effects.md +10 -0
- package/skills/pixerate-image-editor/references/painting.md +17 -0
- package/skills/pixerate-image-editor/references/photoshop-files.md +1 -1
- package/skills/pixerate-image-editor/references/shapes-and-type.md +14 -0
- package/skills/pixerate-image-editor/references/smart-objects.md +10 -0
- package/skills/pixerate-paint-editor/SKILL.md +8 -4
- package/skills/pixerate-paint-editor/references/wet-media.md +9 -0
- package/skills/pixerate-vector/SKILL.md +16 -6
- package/skills/pixerate-vector/references/best-practices.md +1 -0
- package/skills/pixerate-vector/references/commands.md +19 -0
|
@@ -1,879 +1,10 @@
|
|
|
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;
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
var _chunk2VX55NFMcjs = require('./chunk-2VX55NFM.cjs');
|
|
24
|
-
|
|
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;
|
|
25
2
|
|
|
26
3
|
|
|
27
4
|
|
|
28
5
|
|
|
29
6
|
var _chunk474IQG74cjs = require('./chunk-474IQG74.cjs');
|
|
30
7
|
|
|
31
|
-
// src/paint/pigment-tools.ts
|
|
32
|
-
var HEX = /^#?([0-9a-f]{6})$/i;
|
|
33
|
-
function parseHex(value, index) {
|
|
34
|
-
const m = typeof value === "string" ? HEX.exec(value.trim()) : null;
|
|
35
|
-
if (!m) throw new Error(`colors[${index}].color is ${JSON.stringify(value)}; use #rrggbb, e.g. "#1e40af".`);
|
|
36
|
-
const n = parseInt(m[1], 16);
|
|
37
|
-
return [(n >> 16 & 255) / 255, (n >> 8 & 255) / 255, (n & 255) / 255];
|
|
38
|
-
}
|
|
39
|
-
function toHex(rgb) {
|
|
40
|
-
return "#" + rgb.map((v) => Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, "0")).join("");
|
|
41
|
-
}
|
|
42
|
-
function createPigmentTools() {
|
|
43
|
-
const mixColors = {
|
|
44
|
-
name: "mix_colors",
|
|
45
|
-
title: "Mix colours like paint",
|
|
46
|
-
description: "Mixes colours as paint would (model pigment, the default: Kubelka-Munk mixing over reflectance spectra, so blue and yellow make green and white lightens a colour into a tint instead of greying it), or as light on screen (model rgb: the weighted RGB average). Changes nothing. Returns mixed (#rrggbb, by the chosen model), the other model's result for comparison (rgbLerp and pigment), the normalised weights and the model.",
|
|
47
|
-
inputSchema: {
|
|
48
|
-
type: "object",
|
|
49
|
-
properties: {
|
|
50
|
-
colors: {
|
|
51
|
-
type: "array",
|
|
52
|
-
minItems: 1,
|
|
53
|
-
maxItems: 16,
|
|
54
|
-
description: "The paints to mix (1 to 16).",
|
|
55
|
-
items: {
|
|
56
|
-
type: "object",
|
|
57
|
-
properties: {
|
|
58
|
-
color: { type: "string", description: "Paint colour #rrggbb." },
|
|
59
|
-
weight: { type: "number", minimum: 0, description: "Parts of this paint, any scale (e.g. 1 and 3 for a 1:3 mix). At least one weight must be above 0." },
|
|
60
|
-
strength: {
|
|
61
|
-
type: "number",
|
|
62
|
-
exclusiveMinimum: 0,
|
|
63
|
-
maximum: 100,
|
|
64
|
-
description: "Tinting strength (default 1): each part counts as this many, so a strong dark paint (e.g. 4) tints a lot of white."
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
required: ["color", "weight"],
|
|
68
|
-
additionalProperties: false
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
model: {
|
|
72
|
-
type: "string",
|
|
73
|
-
enum: ["pigment", "rgb"],
|
|
74
|
-
description: "pigment (default): mix like paint (Kubelka-Munk), as the pigment blend mode, Mixer Brush and mixing pad do; rgb: average the RGB values, as normal blending and rgb mixing brushes do (strength is ignored)."
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
required: ["colors"],
|
|
78
|
-
additionalProperties: false
|
|
79
|
-
},
|
|
80
|
-
annotations: { title: "Mix colours like paint", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
81
|
-
handler: (args) => {
|
|
82
|
-
const items = args.colors;
|
|
83
|
-
const rgbs = items.map((item, i) => parseHex(item.color, i));
|
|
84
|
-
const total = items.reduce((sum, item) => sum + item.weight, 0);
|
|
85
|
-
if (!(total > 0)) throw new Error("Every weight is 0; give at least one colour a weight above 0.");
|
|
86
|
-
const pigments = rgbs.map((rgb2, i) => _chunk2VX55NFMcjs.createPigment.call(void 0, rgb2, { strength: items[i].strength }));
|
|
87
|
-
const mixed = _chunk2VX55NFMcjs.mixPigments.call(void 0, pigments, items.map((item) => item.weight));
|
|
88
|
-
const lerp = [0, 1, 2].map((c) => rgbs.reduce((sum, rgb2, i) => sum + rgb2[c] * items[i].weight, 0) / total);
|
|
89
|
-
const rgb = args.model === "rgb";
|
|
90
|
-
return {
|
|
91
|
-
mixed: toHex(rgb ? lerp : mixed),
|
|
92
|
-
rgbLerp: toHex(lerp),
|
|
93
|
-
pigment: toHex(mixed),
|
|
94
|
-
weights: items.map((item) => item.weight / total),
|
|
95
|
-
model: rgb ? "rgb" : "kubelka-munk"
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
return [mixColors];
|
|
100
|
-
}
|
|
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
|
-
|
|
744
|
-
// src/paint/wet/model.ts
|
|
745
|
-
var WET_TILE = 256;
|
|
746
|
-
var SLOT_SIDE = 258;
|
|
747
|
-
var PLANE = SLOT_SIDE * SLOT_SIDE;
|
|
748
|
-
var PLANE_BYTES = PLANE * 4;
|
|
749
|
-
var SET_PLANES = 19;
|
|
750
|
-
var P_RHO = 9;
|
|
751
|
-
var P_UX = 10;
|
|
752
|
-
var P_UY = 11;
|
|
753
|
-
var P_SW = 12;
|
|
754
|
-
var P_P0 = 13;
|
|
755
|
-
var P_L = P_P0 + 4;
|
|
756
|
-
var P_EDGE = 18;
|
|
757
|
-
var P_D0 = 2 * SET_PLANES;
|
|
758
|
-
var P_DL = P_D0 + 4;
|
|
759
|
-
var P_H = P_D0 + 5;
|
|
760
|
-
var P_FX = P_H + 1;
|
|
761
|
-
var P_FY = P_H + 2;
|
|
762
|
-
var SLOT_PLANES = P_FY + 1;
|
|
763
|
-
var SLOT_BYTES = SLOT_PLANES * PLANE_BYTES;
|
|
764
|
-
var PIGMENT_CHANNELS = 4;
|
|
765
|
-
var MASS_CHANNELS = 5;
|
|
766
|
-
var EX = [0, 1, 0, -1, 0, 1, -1, -1, 1];
|
|
767
|
-
var EY = [0, 0, 1, 0, -1, 1, 1, -1, -1];
|
|
768
|
-
var OPP = [0, 3, 4, 1, 2, 7, 8, 5, 6];
|
|
769
|
-
var W9 = [4 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 36, 1 / 36, 1 / 36, 1 / 36];
|
|
770
|
-
var DRY_EPS = 1e-3;
|
|
771
|
-
var U_MAX = 0.25;
|
|
772
|
-
var STRIP = 64;
|
|
773
|
-
var MAX_BATCH = 32;
|
|
774
|
-
var FREE_INTERVAL = 32;
|
|
775
|
-
var FLAG_ALIVE = 1;
|
|
776
|
-
var FLAG_LEFT = 2;
|
|
777
|
-
var FLAG_RIGHT = 4;
|
|
778
|
-
var FLAG_TOP = 8;
|
|
779
|
-
var FLAG_BOTTOM = 16;
|
|
780
|
-
var FLAG_WET = 32;
|
|
781
|
-
var PARAM_FLOATS = 32;
|
|
782
|
-
var PARAM = {
|
|
783
|
-
omega: 0,
|
|
784
|
-
tau: 1,
|
|
785
|
-
evap: 2,
|
|
786
|
-
edgeEvap: 3,
|
|
787
|
-
// times the edge field
|
|
788
|
-
mobility: 4,
|
|
789
|
-
// half the pigment mobility (the face flux uses the sum of two velocities)
|
|
790
|
-
depRate: 5,
|
|
791
|
-
pickup: 6,
|
|
792
|
-
absorption: 7,
|
|
793
|
-
invCap: 8,
|
|
794
|
-
blockScale: 9,
|
|
795
|
-
rough: 10,
|
|
796
|
-
pinT: 11,
|
|
797
|
-
gx: 12,
|
|
798
|
-
gy: 13,
|
|
799
|
-
flowK: 14,
|
|
800
|
-
granulation: 15,
|
|
801
|
-
edgeDep: 16,
|
|
802
|
-
// times the edge field
|
|
803
|
-
bloom: 17,
|
|
804
|
-
paperEvap: 18,
|
|
805
|
-
hasFlow: 19,
|
|
806
|
-
bleed: 20
|
|
807
|
-
};
|
|
808
|
-
var DEFAULT_WET_PARAMS = {
|
|
809
|
-
viscosity: 0.3,
|
|
810
|
-
evaporation: 0.45,
|
|
811
|
-
edgeDarkening: 0.5,
|
|
812
|
-
pigmentWeight: 0.3,
|
|
813
|
-
granulation: 0.4,
|
|
814
|
-
pickup: 0.2,
|
|
815
|
-
fixture: 0.2,
|
|
816
|
-
bloom: 0.4,
|
|
817
|
-
bleed: 0.3
|
|
818
|
-
};
|
|
819
|
-
var WET_PARAM_KEYS = Object.keys(DEFAULT_WET_PARAMS);
|
|
820
|
-
var DEFAULT_WET_PAPER = { absorption: 0.7, permeability: 0.5, roughness: 0.6 };
|
|
821
|
-
var FLAT = { angle: 0, direction: 0 };
|
|
822
|
-
var unit = (v, d) => typeof v === "number" && Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : d;
|
|
823
|
-
function normalizeWetParams(raw = {}, base = DEFAULT_WET_PARAMS) {
|
|
824
|
-
const out = {};
|
|
825
|
-
for (const k of WET_PARAM_KEYS) out[k] = unit(raw[k], base[k]);
|
|
826
|
-
return out;
|
|
827
|
-
}
|
|
828
|
-
function normalizeTilt(raw = {}, base = FLAT) {
|
|
829
|
-
const angle = typeof raw.angle === "number" && Number.isFinite(raw.angle) ? Math.min(90, Math.max(0, raw.angle)) : base.angle;
|
|
830
|
-
let direction = typeof raw.direction === "number" && Number.isFinite(raw.direction) ? raw.direction : base.direction;
|
|
831
|
-
direction = (direction % 360 + 360) % 360;
|
|
832
|
-
return { angle, direction };
|
|
833
|
-
}
|
|
834
|
-
function latticeViscosity(v) {
|
|
835
|
-
return 0.02 * Math.pow(75, v);
|
|
836
|
-
}
|
|
837
|
-
var PAPER_CAPACITY = 0.08;
|
|
838
|
-
var MAX_TILT_ACCEL = 0.025;
|
|
839
|
-
function packWetParams(params, paper, tilt, flowStrength, out = new Float32Array(PARAM_FLOATS)) {
|
|
840
|
-
const nu = latticeViscosity(params.viscosity);
|
|
841
|
-
const tau = 3 * nu + 0.5;
|
|
842
|
-
const g = MAX_TILT_ACCEL * Math.sin(tilt.angle * Math.PI / 180);
|
|
843
|
-
const dir = tilt.direction * Math.PI / 180;
|
|
844
|
-
out.fill(0);
|
|
845
|
-
out[PARAM.omega] = 1 / tau;
|
|
846
|
-
out[PARAM.tau] = tau;
|
|
847
|
-
out[PARAM.evap] = 1e-3 * params.evaporation * params.evaporation;
|
|
848
|
-
out[PARAM.edgeEvap] = params.edgeDarkening * 12;
|
|
849
|
-
out[PARAM.mobility] = 0.5 * (1 - 0.5 * params.pigmentWeight);
|
|
850
|
-
out[PARAM.depRate] = 0.019 * params.fixture * (0.5 + params.pigmentWeight);
|
|
851
|
-
out[PARAM.pickup] = 0.01 * params.pickup;
|
|
852
|
-
out[PARAM.absorption] = 15e-4 * paper.absorption;
|
|
853
|
-
out[PARAM.invCap] = 1 / PAPER_CAPACITY;
|
|
854
|
-
out[PARAM.blockScale] = 0.05 * (1 - paper.permeability);
|
|
855
|
-
out[PARAM.rough] = 0.15 * paper.roughness;
|
|
856
|
-
out[PARAM.pinT] = 0.2;
|
|
857
|
-
out[PARAM.gx] = -g * Math.sin(dir);
|
|
858
|
-
out[PARAM.gy] = g * Math.cos(dir);
|
|
859
|
-
out[PARAM.flowK] = flowStrength;
|
|
860
|
-
out[PARAM.granulation] = 1.2 * params.granulation * paper.roughness;
|
|
861
|
-
out[PARAM.edgeDep] = params.edgeDarkening * 3;
|
|
862
|
-
out[PARAM.bloom] = 60 * params.bloom;
|
|
863
|
-
out[PARAM.paperEvap] = 5e-4 * params.evaporation * params.evaporation;
|
|
864
|
-
out[PARAM.hasFlow] = flowStrength !== 0 ? 1 : 0;
|
|
865
|
-
out[PARAM.bleed] = 0.05 * params.bleed;
|
|
866
|
-
return out;
|
|
867
|
-
}
|
|
868
|
-
function edgeBits(lx, ly) {
|
|
869
|
-
let b = 0;
|
|
870
|
-
if (lx < STRIP) b |= FLAG_LEFT;
|
|
871
|
-
if (lx >= WET_TILE - STRIP) b |= FLAG_RIGHT;
|
|
872
|
-
if (ly < STRIP) b |= FLAG_TOP;
|
|
873
|
-
if (ly >= WET_TILE - STRIP) b |= FLAG_BOTTOM;
|
|
874
|
-
return b;
|
|
875
|
-
}
|
|
876
|
-
|
|
877
8
|
// src/paint/wet/film.ts
|
|
878
9
|
var PIGMENT_UNIT = 0.25;
|
|
879
10
|
var HIDE = 1.5;
|
|
@@ -1200,6 +331,139 @@ function shadeLightTile(f, plane, side, d, p, dl, pl, src, out, w, h) {
|
|
|
1200
331
|
return any;
|
|
1201
332
|
}
|
|
1202
333
|
|
|
334
|
+
// src/paint/wet/model.ts
|
|
335
|
+
var WET_TILE = 256;
|
|
336
|
+
var SLOT_SIDE = 258;
|
|
337
|
+
var PLANE = SLOT_SIDE * SLOT_SIDE;
|
|
338
|
+
var PLANE_BYTES = PLANE * 4;
|
|
339
|
+
var SET_PLANES = 19;
|
|
340
|
+
var P_RHO = 9;
|
|
341
|
+
var P_UX = 10;
|
|
342
|
+
var P_UY = 11;
|
|
343
|
+
var P_SW = 12;
|
|
344
|
+
var P_P0 = 13;
|
|
345
|
+
var P_L = P_P0 + 4;
|
|
346
|
+
var P_EDGE = 18;
|
|
347
|
+
var P_D0 = 2 * SET_PLANES;
|
|
348
|
+
var P_DL = P_D0 + 4;
|
|
349
|
+
var P_H = P_D0 + 5;
|
|
350
|
+
var P_FX = P_H + 1;
|
|
351
|
+
var P_FY = P_H + 2;
|
|
352
|
+
var SLOT_PLANES = P_FY + 1;
|
|
353
|
+
var SLOT_BYTES = SLOT_PLANES * PLANE_BYTES;
|
|
354
|
+
var PIGMENT_CHANNELS = 4;
|
|
355
|
+
var MASS_CHANNELS = 5;
|
|
356
|
+
var EX = [0, 1, 0, -1, 0, 1, -1, -1, 1];
|
|
357
|
+
var EY = [0, 0, 1, 0, -1, 1, 1, -1, -1];
|
|
358
|
+
var OPP = [0, 3, 4, 1, 2, 7, 8, 5, 6];
|
|
359
|
+
var W9 = [4 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 36, 1 / 36, 1 / 36, 1 / 36];
|
|
360
|
+
var DRY_EPS = 1e-3;
|
|
361
|
+
var U_MAX = 0.25;
|
|
362
|
+
var STRIP = 64;
|
|
363
|
+
var MAX_BATCH = 32;
|
|
364
|
+
var FREE_INTERVAL = 32;
|
|
365
|
+
var FLAG_ALIVE = 1;
|
|
366
|
+
var FLAG_LEFT = 2;
|
|
367
|
+
var FLAG_RIGHT = 4;
|
|
368
|
+
var FLAG_TOP = 8;
|
|
369
|
+
var FLAG_BOTTOM = 16;
|
|
370
|
+
var FLAG_WET = 32;
|
|
371
|
+
var PARAM_FLOATS = 32;
|
|
372
|
+
var PARAM = {
|
|
373
|
+
omega: 0,
|
|
374
|
+
tau: 1,
|
|
375
|
+
evap: 2,
|
|
376
|
+
edgeEvap: 3,
|
|
377
|
+
// times the edge field
|
|
378
|
+
mobility: 4,
|
|
379
|
+
// half the pigment mobility (the face flux uses the sum of two velocities)
|
|
380
|
+
depRate: 5,
|
|
381
|
+
pickup: 6,
|
|
382
|
+
absorption: 7,
|
|
383
|
+
invCap: 8,
|
|
384
|
+
blockScale: 9,
|
|
385
|
+
rough: 10,
|
|
386
|
+
pinT: 11,
|
|
387
|
+
gx: 12,
|
|
388
|
+
gy: 13,
|
|
389
|
+
flowK: 14,
|
|
390
|
+
granulation: 15,
|
|
391
|
+
edgeDep: 16,
|
|
392
|
+
// times the edge field
|
|
393
|
+
bloom: 17,
|
|
394
|
+
paperEvap: 18,
|
|
395
|
+
hasFlow: 19,
|
|
396
|
+
bleed: 20
|
|
397
|
+
};
|
|
398
|
+
var DEFAULT_WET_PARAMS = {
|
|
399
|
+
viscosity: 0.3,
|
|
400
|
+
evaporation: 0.45,
|
|
401
|
+
edgeDarkening: 0.5,
|
|
402
|
+
pigmentWeight: 0.3,
|
|
403
|
+
granulation: 0.4,
|
|
404
|
+
pickup: 0.2,
|
|
405
|
+
fixture: 0.2,
|
|
406
|
+
bloom: 0.4,
|
|
407
|
+
bleed: 0.3
|
|
408
|
+
};
|
|
409
|
+
var WET_PARAM_KEYS = Object.keys(DEFAULT_WET_PARAMS);
|
|
410
|
+
var DEFAULT_WET_PAPER = { absorption: 0.7, permeability: 0.5, roughness: 0.6 };
|
|
411
|
+
var FLAT = { angle: 0, direction: 0 };
|
|
412
|
+
var unit = (v, d) => typeof v === "number" && Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : d;
|
|
413
|
+
function normalizeWetParams(raw = {}, base = DEFAULT_WET_PARAMS) {
|
|
414
|
+
const out = {};
|
|
415
|
+
for (const k of WET_PARAM_KEYS) out[k] = unit(raw[k], base[k]);
|
|
416
|
+
return out;
|
|
417
|
+
}
|
|
418
|
+
function normalizeTilt(raw = {}, base = FLAT) {
|
|
419
|
+
const angle = typeof raw.angle === "number" && Number.isFinite(raw.angle) ? Math.min(90, Math.max(0, raw.angle)) : base.angle;
|
|
420
|
+
let direction = typeof raw.direction === "number" && Number.isFinite(raw.direction) ? raw.direction : base.direction;
|
|
421
|
+
direction = (direction % 360 + 360) % 360;
|
|
422
|
+
return { angle, direction };
|
|
423
|
+
}
|
|
424
|
+
function latticeViscosity(v) {
|
|
425
|
+
return 0.02 * Math.pow(75, v);
|
|
426
|
+
}
|
|
427
|
+
var PAPER_CAPACITY = 0.08;
|
|
428
|
+
var MAX_TILT_ACCEL = 0.025;
|
|
429
|
+
function packWetParams(params, paper, tilt, flowStrength, out = new Float32Array(PARAM_FLOATS)) {
|
|
430
|
+
const nu = latticeViscosity(params.viscosity);
|
|
431
|
+
const tau = 3 * nu + 0.5;
|
|
432
|
+
const g = MAX_TILT_ACCEL * Math.sin(tilt.angle * Math.PI / 180);
|
|
433
|
+
const dir = tilt.direction * Math.PI / 180;
|
|
434
|
+
out.fill(0);
|
|
435
|
+
out[PARAM.omega] = 1 / tau;
|
|
436
|
+
out[PARAM.tau] = tau;
|
|
437
|
+
out[PARAM.evap] = 1e-3 * params.evaporation * params.evaporation;
|
|
438
|
+
out[PARAM.edgeEvap] = params.edgeDarkening * 12;
|
|
439
|
+
out[PARAM.mobility] = 0.5 * (1 - 0.5 * params.pigmentWeight);
|
|
440
|
+
out[PARAM.depRate] = 0.019 * params.fixture * (0.5 + params.pigmentWeight);
|
|
441
|
+
out[PARAM.pickup] = 0.01 * params.pickup;
|
|
442
|
+
out[PARAM.absorption] = 15e-4 * paper.absorption;
|
|
443
|
+
out[PARAM.invCap] = 1 / PAPER_CAPACITY;
|
|
444
|
+
out[PARAM.blockScale] = 0.05 * (1 - paper.permeability);
|
|
445
|
+
out[PARAM.rough] = 0.15 * paper.roughness;
|
|
446
|
+
out[PARAM.pinT] = 0.2;
|
|
447
|
+
out[PARAM.gx] = -g * Math.sin(dir);
|
|
448
|
+
out[PARAM.gy] = g * Math.cos(dir);
|
|
449
|
+
out[PARAM.flowK] = flowStrength;
|
|
450
|
+
out[PARAM.granulation] = 1.2 * params.granulation * paper.roughness;
|
|
451
|
+
out[PARAM.edgeDep] = params.edgeDarkening * 3;
|
|
452
|
+
out[PARAM.bloom] = 60 * params.bloom;
|
|
453
|
+
out[PARAM.paperEvap] = 5e-4 * params.evaporation * params.evaporation;
|
|
454
|
+
out[PARAM.hasFlow] = flowStrength !== 0 ? 1 : 0;
|
|
455
|
+
out[PARAM.bleed] = 0.05 * params.bleed;
|
|
456
|
+
return out;
|
|
457
|
+
}
|
|
458
|
+
function edgeBits(lx, ly) {
|
|
459
|
+
let b = 0;
|
|
460
|
+
if (lx < STRIP) b |= FLAG_LEFT;
|
|
461
|
+
if (lx >= WET_TILE - STRIP) b |= FLAG_RIGHT;
|
|
462
|
+
if (ly < STRIP) b |= FLAG_TOP;
|
|
463
|
+
if (ly >= WET_TILE - STRIP) b |= FLAG_BOTTOM;
|
|
464
|
+
return b;
|
|
465
|
+
}
|
|
466
|
+
|
|
1203
467
|
// src/paint/wet/kernel.ts
|
|
1204
468
|
var F = Math.fround;
|
|
1205
469
|
var S = SLOT_SIDE;
|
|
@@ -1437,7 +701,7 @@ function wetSupport(simd = _nullishCoalesce(simdCache, () => ( typeof WebAssembl
|
|
|
1437
701
|
const g = globalThis;
|
|
1438
702
|
const sharedMemory = canShareMemory();
|
|
1439
703
|
const workers = typeof g.Worker === "function" && typeof Blob === "function" && typeof URL !== "undefined" && typeof URL.createObjectURL === "function";
|
|
1440
|
-
const cores = Math.max(1, Math.floor(_nullishCoalesce(_optionalChain([g, 'access',
|
|
704
|
+
const cores = Math.max(1, Math.floor(_nullishCoalesce(_optionalChain([g, 'access', _ => _.navigator, 'optionalAccess', _2 => _2.hardwareConcurrency]), () => ( 1))));
|
|
1441
705
|
let message = null;
|
|
1442
706
|
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).";
|
|
1443
707
|
else if (workers && !sharedMemory)
|
|
@@ -1541,8 +805,8 @@ var WetWorkerPool = class _WetWorkerPool {
|
|
|
1541
805
|
ready.push(
|
|
1542
806
|
new Promise((resolve, reject) => {
|
|
1543
807
|
w.onmessage = (e) => {
|
|
1544
|
-
if (_optionalChain([e, 'access',
|
|
1545
|
-
else if (_optionalChain([e, 'access',
|
|
808
|
+
if (_optionalChain([e, 'access', _3 => _3.data, 'optionalAccess', _4 => _4.type]) === "ready") resolve();
|
|
809
|
+
else if (_optionalChain([e, 'access', _5 => _5.data, 'optionalAccess', _6 => _6.type]) === "error") reject(new Error(e.data.message));
|
|
1546
810
|
};
|
|
1547
811
|
w.onerror = (e) => reject(new Error(e.message || "The wet-media worker failed to start."));
|
|
1548
812
|
})
|
|
@@ -1564,8 +828,8 @@ var WetWorkerPool = class _WetWorkerPool {
|
|
|
1564
828
|
this.workers.map(
|
|
1565
829
|
(w, i) => new Promise((resolve, reject) => {
|
|
1566
830
|
w.onmessage = (e) => {
|
|
1567
|
-
if (_optionalChain([e, 'access',
|
|
1568
|
-
else if (_optionalChain([e, 'access',
|
|
831
|
+
if (_optionalChain([e, 'access', _7 => _7.data, 'optionalAccess', _8 => _8.type]) === "done") resolve();
|
|
832
|
+
else if (_optionalChain([e, 'access', _9 => _9.data, 'optionalAccess', _10 => _10.type]) === "error") reject(new Error(e.data.message));
|
|
1569
833
|
};
|
|
1570
834
|
w.postMessage({ type: "run", steps, workers: n, id: i });
|
|
1571
835
|
})
|
|
@@ -1612,53 +876,53 @@ function makeLayout(width, height) {
|
|
|
1612
876
|
function quantizeHeight(v) {
|
|
1613
877
|
return Math.round(Math.min(1, Math.max(0, v)) * 65536) / 65536;
|
|
1614
878
|
}
|
|
1615
|
-
var WetWorld = (
|
|
879
|
+
var WetWorld = (_class = class {
|
|
1616
880
|
|
|
1617
881
|
|
|
1618
882
|
|
|
1619
883
|
/** Steps simulated so far. */
|
|
1620
|
-
|
|
884
|
+
__init() {this.clock = 0}
|
|
1621
885
|
/** Messages for the user (slots ran out, a backend failed). */
|
|
1622
|
-
|
|
886
|
+
__init2() {this.warnings = []}
|
|
1623
887
|
|
|
1624
888
|
|
|
1625
889
|
|
|
1626
890
|
|
|
1627
891
|
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
892
|
+
__init3() {this.slotCount = 0}
|
|
893
|
+
__init4() {this.freeSlots = []}
|
|
894
|
+
__init5() {this.active = []}
|
|
895
|
+
__init6() {this.parity = 0}
|
|
896
|
+
__init7() {this.lanes = new Array(MAX_WET_LANES).fill(null)}
|
|
897
|
+
__init8() {this.tilt = { ...FLAT }}
|
|
1634
898
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
899
|
+
__init9() {this.paperBytes = new Uint8Array(3)}
|
|
900
|
+
__init10() {this.kind = "typescript"}
|
|
901
|
+
__init11() {this.wasm = null}
|
|
902
|
+
__init12() {this.pool = null}
|
|
903
|
+
__init13() {this.busyFlag = false}
|
|
904
|
+
__init14() {this.destroyed = false}
|
|
1641
905
|
|
|
1642
|
-
|
|
906
|
+
__init15() {this.prm = new Float32Array(PARAM_FLOATS)}
|
|
1643
907
|
// Engine B: the GPU mirror (see `attachGpu`).
|
|
1644
|
-
|
|
908
|
+
__init16() {this.gpu = null}
|
|
1645
909
|
/** Live tiles at which the GPU takes over the display (default 16: a fully wet 1024² canvas). */
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
910
|
+
__init17() {this.gpuMinTiles = 16}
|
|
911
|
+
__init18() {this.gpuLive = false}
|
|
912
|
+
__init19() {this.gpuFailure = null}
|
|
1649
913
|
/** Slot → rows (1..256, inclusive) to upload; `[0, 257]` means the whole slot. */
|
|
1650
|
-
|
|
1651
|
-
|
|
914
|
+
__init20() {this.gpuDirty = /* @__PURE__ */ new Map()}
|
|
915
|
+
__init21() {this.gpuParamsDirty = true}
|
|
1652
916
|
/**
|
|
1653
917
|
* Lead mode (between strokes): a batch is not sent to the GPU all at once; `gpuLead` steps it
|
|
1654
918
|
* frame by frame while the CPU works through it, so the display moves on before the CPU is done.
|
|
1655
919
|
*/
|
|
1656
|
-
|
|
920
|
+
__init22() {this.gpuLeadMode = false}
|
|
1657
921
|
/** The batch the GPU is working through in lead mode. */
|
|
1658
|
-
|
|
922
|
+
__init23() {this.gpuPlan = null}
|
|
1659
923
|
/** Resolves when the fastest available kernel is running (it may stay `typescript`). */
|
|
1660
924
|
|
|
1661
|
-
constructor(width, height, paper, options = {}) {;
|
|
925
|
+
constructor(width, height, paper, options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);_class.prototype.__init13.call(this);_class.prototype.__init14.call(this);_class.prototype.__init15.call(this);_class.prototype.__init16.call(this);_class.prototype.__init17.call(this);_class.prototype.__init18.call(this);_class.prototype.__init19.call(this);_class.prototype.__init20.call(this);_class.prototype.__init21.call(this);_class.prototype.__init22.call(this);_class.prototype.__init23.call(this);
|
|
1662
926
|
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}.`);
|
|
1663
927
|
this.width = Math.round(width);
|
|
1664
928
|
this.height = Math.round(height);
|
|
@@ -1713,7 +977,7 @@ var WetWorld = (_class4 = class {
|
|
|
1713
977
|
}
|
|
1714
978
|
/** The kernel in use and why it is not faster. */
|
|
1715
979
|
backend() {
|
|
1716
|
-
const threads = _nullishCoalesce(_optionalChain([this, 'access',
|
|
980
|
+
const threads = _nullishCoalesce(_optionalChain([this, 'access', _11 => _11.pool, 'optionalAccess', _12 => _12.size]), () => ( 1));
|
|
1717
981
|
let message = this.support.message;
|
|
1718
982
|
if (this.kind === "typescript" && !message) message = this.wasm ? null : "Wet paint runs in plain JavaScript until the WebAssembly kernel has loaded.";
|
|
1719
983
|
if (this.kind === "wasm-threads") message = null;
|
|
@@ -1725,17 +989,17 @@ var WetWorld = (_class4 = class {
|
|
|
1725
989
|
}
|
|
1726
990
|
destroy() {
|
|
1727
991
|
this.destroyed = true;
|
|
1728
|
-
_optionalChain([this, 'access',
|
|
992
|
+
_optionalChain([this, 'access', _13 => _13.pool, 'optionalAccess', _14 => _14.destroy, 'call', _15 => _15()]);
|
|
1729
993
|
this.pool = null;
|
|
1730
994
|
}
|
|
1731
995
|
// --- Lanes ---------------------------------------------------------------------
|
|
1732
996
|
laneOf(id) {
|
|
1733
|
-
const l = this.lanes.find((x) => _optionalChain([x, 'optionalAccess',
|
|
997
|
+
const l = this.lanes.find((x) => _optionalChain([x, 'optionalAccess', _16 => _16.id]) === id);
|
|
1734
998
|
if (!l) throw new WetWorldError(`There is no wet layer "${id}".`);
|
|
1735
999
|
return l;
|
|
1736
1000
|
}
|
|
1737
1001
|
hasLane(id) {
|
|
1738
|
-
return this.lanes.some((x) => _optionalChain([x, 'optionalAccess',
|
|
1002
|
+
return this.lanes.some((x) => _optionalChain([x, 'optionalAccess', _17 => _17.id]) === id);
|
|
1739
1003
|
}
|
|
1740
1004
|
laneIds() {
|
|
1741
1005
|
return this.lanes.filter((l) => Boolean(l)).map((l) => l.id);
|
|
@@ -1743,7 +1007,7 @@ var WetWorld = (_class4 = class {
|
|
|
1743
1007
|
/** Adds a wet layer (or returns it). Throws when `MAX_WET_LANES` are in use. */
|
|
1744
1008
|
ensureLane(id, options = {}) {
|
|
1745
1009
|
this.requireIdle();
|
|
1746
|
-
const existing = this.lanes.find((x) => _optionalChain([x, 'optionalAccess',
|
|
1010
|
+
const existing = this.lanes.find((x) => _optionalChain([x, 'optionalAccess', _18 => _18.id]) === id);
|
|
1747
1011
|
if (existing) {
|
|
1748
1012
|
if (options.params) this.setParams(id, options.params);
|
|
1749
1013
|
if (options.base) this.setBase(id, options.base);
|
|
@@ -2437,7 +1701,7 @@ var WetWorld = (_class4 = class {
|
|
|
2437
1701
|
if (!(a > 0)) return;
|
|
2438
1702
|
const key = _chunk474IQG74cjs.tileKey.call(void 0, x >> 8, y >> 8);
|
|
2439
1703
|
const li = (y & 255) * _chunk474IQG74cjs.TILE + (x & 255);
|
|
2440
|
-
let lt = _optionalChain([lightTiles, 'optionalAccess',
|
|
1704
|
+
let lt = _optionalChain([lightTiles, 'optionalAccess', _19 => _19.get, 'call', _20 => _20(key)]);
|
|
2441
1705
|
if (lt && (_nullishCoalesce(lt.uniform, () => ( 1))) !== 0) {
|
|
2442
1706
|
if (!lightWritten.has(key)) {
|
|
2443
1707
|
const data = lt.data.length ? new Uint8ClampedArray(lt.data) : new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE).fill(_nullishCoalesce(lt.uniform, () => ( 0)));
|
|
@@ -2510,7 +1774,7 @@ var WetWorld = (_class4 = class {
|
|
|
2510
1774
|
if (x1 <= x0 || y1 <= y0) continue;
|
|
2511
1775
|
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);
|
|
2512
1776
|
if (whole) {
|
|
2513
|
-
if (this.bakeKey(key, true)) bounds =
|
|
1777
|
+
if (this.bakeKey(key, true)) bounds = unionRect(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) });
|
|
2514
1778
|
this.free(key);
|
|
2515
1779
|
continue;
|
|
2516
1780
|
}
|
|
@@ -2530,7 +1794,7 @@ var WetWorld = (_class4 = class {
|
|
|
2530
1794
|
f[c + P_SW * PLANE] = 0;
|
|
2531
1795
|
}
|
|
2532
1796
|
}
|
|
2533
|
-
bounds =
|
|
1797
|
+
bounds = unionRect(bounds, { x: x0, y: y0, width: x1 - x0, height: y1 - y0 });
|
|
2534
1798
|
this.markEdited(lane, x0, y0, x1, y1);
|
|
2535
1799
|
}
|
|
2536
1800
|
this.syncList();
|
|
@@ -2558,7 +1822,7 @@ var WetWorld = (_class4 = class {
|
|
|
2558
1822
|
lightChanged = true;
|
|
2559
1823
|
}
|
|
2560
1824
|
}
|
|
2561
|
-
const src = _nullishCoalesce(_optionalChain([lane, 'access',
|
|
1825
|
+
const src = _nullishCoalesce(_optionalChain([lane, 'access', _21 => _21.base, 'access', _22 => _22.tiles, 'access', _23 => _23.get, 'call', _24 => _24(tk), 'optionalAccess', _25 => _25.data]), () => ( null));
|
|
2562
1826
|
const out = this.shadeSlot(key, src, all ? "bake-all" : "bake");
|
|
2563
1827
|
if (!out) return lightChanged;
|
|
2564
1828
|
const tiles = new Map(lane.base.tiles);
|
|
@@ -2621,7 +1885,7 @@ var WetWorld = (_class4 = class {
|
|
|
2621
1885
|
for (const key of this.active) {
|
|
2622
1886
|
if (this.laneIndexOf(key) !== lane.index) continue;
|
|
2623
1887
|
const tk = this.tileKeyOf(key);
|
|
2624
|
-
const out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access',
|
|
1888
|
+
const out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access', _26 => _26.base, 'access', _27 => _27.tiles, 'access', _28 => _28.get, 'call', _29 => _29(tk), 'optionalAccess', _30 => _30.data]), () => ( null)), "bake-all");
|
|
2625
1889
|
if (!out) continue;
|
|
2626
1890
|
const t = _chunk474IQG74cjs.finishTile.call(void 0, out, 4, 0);
|
|
2627
1891
|
if (t) tiles.set(tk, t);
|
|
@@ -2744,14 +2008,14 @@ var WetWorld = (_class4 = class {
|
|
|
2744
2008
|
display(id, maxTiles = Infinity) {
|
|
2745
2009
|
const lane = this.laneOf(id);
|
|
2746
2010
|
const keys = this.active.filter((k) => this.laneIndexOf(k) === lane.index);
|
|
2747
|
-
const stale = keys.filter((k) => _optionalChain([lane, 'access',
|
|
2748
|
-
stale.sort((a, b) => Number(lane.urgent.has(this.tileKeyOf(b))) - Number(lane.urgent.has(this.tileKeyOf(a))) || (_nullishCoalesce(_optionalChain([lane, 'access',
|
|
2011
|
+
const stale = keys.filter((k) => _optionalChain([lane, 'access', _31 => _31.shaded, 'access', _32 => _32.get, 'call', _33 => _33(this.tileKeyOf(k)), 'optionalAccess', _34 => _34.stamp]) !== lane.stamp);
|
|
2012
|
+
stale.sort((a, b) => Number(lane.urgent.has(this.tileKeyOf(b))) - Number(lane.urgent.has(this.tileKeyOf(a))) || (_nullishCoalesce(_optionalChain([lane, 'access', _35 => _35.shaded, 'access', _36 => _36.get, 'call', _37 => _37(this.tileKeyOf(a)), 'optionalAccess', _38 => _38.stamp]), () => ( 0))) - (_nullishCoalesce(_optionalChain([lane, 'access', _39 => _39.shaded, 'access', _40 => _40.get, 'call', _41 => _41(this.tileKeyOf(b)), 'optionalAccess', _42 => _42.stamp]), () => ( 0))));
|
|
2749
2013
|
const changed = [];
|
|
2750
2014
|
let done = 0;
|
|
2751
2015
|
for (const key of stale) {
|
|
2752
2016
|
if (done >= maxTiles) break;
|
|
2753
2017
|
const tk = this.tileKeyOf(key);
|
|
2754
|
-
const src = _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2018
|
+
const src = _nullishCoalesce(_optionalChain([lane, 'access', _43 => _43.base, 'access', _44 => _44.tiles, 'access', _45 => _45.get, 'call', _46 => _46(tk), 'optionalAccess', _47 => _47.data]), () => ( null));
|
|
2755
2019
|
const out = this.shadeSlot(key, src, "display");
|
|
2756
2020
|
const tile = out ? _chunk474IQG74cjs.finishTile.call(void 0, out, 4, 0) : _nullishCoalesce(lane.base.tiles.get(tk), () => ( null));
|
|
2757
2021
|
lane.shaded.set(tk, { stamp: lane.stamp, tile: _nullishCoalesce(tile, () => ( { data: new Uint8ClampedArray(0), uniform: 0 })) });
|
|
@@ -2788,7 +2052,7 @@ var WetWorld = (_class4 = class {
|
|
|
2788
2052
|
for (const key2 of keys) {
|
|
2789
2053
|
const tk = this.tileKeyOf(key2);
|
|
2790
2054
|
live.add(tk);
|
|
2791
|
-
if (_optionalChain([lane, 'access',
|
|
2055
|
+
if (_optionalChain([lane, 'access', _48 => _48.lightShaded, 'access', _49 => _49.get, 'call', _50 => _50(tk), 'optionalAccess', _51 => _51.stamp]) === lane.stamp) continue;
|
|
2792
2056
|
const src = _nullishCoalesce(lane.light.tiles.get(tk), () => ( null));
|
|
2793
2057
|
const out = this.shadeLightSlot(key2, src, "display");
|
|
2794
2058
|
lane.lightShaded.set(tk, { stamp: lane.stamp, tile: out ? _chunk474IQG74cjs.finishTile.call(void 0, out, 1, 0) : src });
|
|
@@ -2986,7 +2250,7 @@ var WetWorld = (_class4 = class {
|
|
|
2986
2250
|
if (!this.gpu || this.busyFlag && !plan || !plan && !this.gpuDecide()) return { ...this.display(id, maxCpuTiles), gpu: false };
|
|
2987
2251
|
const lane = this.laneOf(id);
|
|
2988
2252
|
const keys = this.active.filter((k) => this.laneIndexOf(k) === lane.index);
|
|
2989
|
-
const stale = plan ? keys : keys.filter((k) => _optionalChain([lane, 'access',
|
|
2253
|
+
const stale = plan ? keys : keys.filter((k) => _optionalChain([lane, 'access', _52 => _52.shaded, 'access', _53 => _53.get, 'call', _54 => _54(this.tileKeyOf(k)), 'optionalAccess', _55 => _55.stamp]) !== lane.stamp);
|
|
2990
2254
|
if (!stale.length) return { ...this.display(id, 0), gpu: true };
|
|
2991
2255
|
let tiles;
|
|
2992
2256
|
const stamp = lane.stamp;
|
|
@@ -2994,7 +2258,7 @@ var WetWorld = (_class4 = class {
|
|
|
2994
2258
|
try {
|
|
2995
2259
|
if (!plan) this.gpuSync();
|
|
2996
2260
|
const parity = plan ? plan.parity + plan.done & 1 : this.parity;
|
|
2997
|
-
tiles = await this.gpu.shade(this.gpuJobs(stale), parity, stale.map((k) => _nullishCoalesce(_optionalChain([base, 'access',
|
|
2261
|
+
tiles = await this.gpu.shade(this.gpuJobs(stale), parity, stale.map((k) => _nullishCoalesce(_optionalChain([base, 'access', _56 => _56.tiles, 'access', _57 => _57.get, 'call', _58 => _58(this.tileKeyOf(k)), 'optionalAccess', _59 => _59.data]), () => ( null))), [this.paperBytes[0], this.paperBytes[1], this.paperBytes[2]]);
|
|
2998
2262
|
} catch (e) {
|
|
2999
2263
|
this.gpuStop(`Wet paint stopped using the GPU (${e.message}).`);
|
|
3000
2264
|
return { ...this.display(id, maxCpuTiles), gpu: false };
|
|
@@ -3076,7 +2340,7 @@ var WetWorld = (_class4 = class {
|
|
|
3076
2340
|
const slot = this.slotOf(lane.index * this.layout.perLane + ty * this.layout.tilesX + tx);
|
|
3077
2341
|
return slot < 0 ? -1 : this.slotBase(slot);
|
|
3078
2342
|
}
|
|
3079
|
-
},
|
|
2343
|
+
}, _class);
|
|
3080
2344
|
function moveWetSnapshot(snap, from, to, dx, dy, lane = () => ({})) {
|
|
3081
2345
|
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}).`);
|
|
3082
2346
|
const a = makeLayout(from.width, from.height);
|
|
@@ -3100,7 +2364,7 @@ function moveWetSnapshot(snap, from, to, dx, dy, lane = () => ({})) {
|
|
|
3100
2364
|
});
|
|
3101
2365
|
return { clock: snap.clock, tilt: { ...snap.tilt }, lanes, slots, bytes };
|
|
3102
2366
|
}
|
|
3103
|
-
function
|
|
2367
|
+
function unionRect(a, b) {
|
|
3104
2368
|
if (!a) return { ...b };
|
|
3105
2369
|
const x = Math.min(a.x, b.x);
|
|
3106
2370
|
const y = Math.min(a.y, b.y);
|
|
@@ -3173,8 +2437,8 @@ function normalizeFlow(raw = {}, base = DEFAULT_FLOW) {
|
|
|
3173
2437
|
}
|
|
3174
2438
|
function flowField(spec, width, height) {
|
|
3175
2439
|
const k = FLOW_ACCEL;
|
|
3176
|
-
const cx = _nullishCoalesce(_optionalChain([spec, 'access',
|
|
3177
|
-
const cy = _nullishCoalesce(_optionalChain([spec, 'access',
|
|
2440
|
+
const cx = _nullishCoalesce(_optionalChain([spec, 'access', _60 => _60.center, 'optionalAccess', _61 => _61.x]), () => ( width / 2));
|
|
2441
|
+
const cy = _nullishCoalesce(_optionalChain([spec, 'access', _62 => _62.center, 'optionalAccess', _63 => _63.y]), () => ( height / 2));
|
|
3178
2442
|
const r0 = Math.max(width, height) / 2;
|
|
3179
2443
|
switch (spec.kind) {
|
|
3180
2444
|
case "none":
|
|
@@ -3206,8 +2470,8 @@ function flowField(spec, width, height) {
|
|
|
3206
2470
|
|
|
3207
2471
|
// src/paint/wet/medium.ts
|
|
3208
2472
|
var SAMPLE_K = 3;
|
|
3209
|
-
var WetMedium = (
|
|
3210
|
-
constructor(world, laneId, options) {;
|
|
2473
|
+
var WetMedium = (_class2 = class {
|
|
2474
|
+
constructor(world, laneId, options) {;_class2.prototype.__init24.call(this);
|
|
3211
2475
|
this.world = world;
|
|
3212
2476
|
this.laneId = laneId;
|
|
3213
2477
|
this.options = options;
|
|
@@ -3215,7 +2479,7 @@ var WetMedium = (_class5 = class {
|
|
|
3215
2479
|
|
|
3216
2480
|
|
|
3217
2481
|
|
|
3218
|
-
|
|
2482
|
+
__init24() {this.pig = new Float64Array(4)}
|
|
3219
2483
|
sample(rect, cov) {
|
|
3220
2484
|
const s = this.world.sample(this.laneId, rect, cov);
|
|
3221
2485
|
if (!(s.wet > 0) || !(s.weight > 0)) return null;
|
|
@@ -3248,7 +2512,7 @@ var WetMedium = (_class5 = class {
|
|
|
3248
2512
|
const pig = [0, 1, 2, 3].map((q) => this.pig[q] * mass * dep);
|
|
3249
2513
|
this.world.paint(this.laneId, rect, cov, water * dep, mass > 0 ? pig : null, null, light);
|
|
3250
2514
|
}
|
|
3251
|
-
},
|
|
2515
|
+
}, _class2);
|
|
3252
2516
|
|
|
3253
2517
|
// src/paint/wet/gpu-kernels.ts
|
|
3254
2518
|
var GPU_JOB_WORDS = 16;
|
|
@@ -3637,7 +2901,7 @@ var UNIFORM = 64;
|
|
|
3637
2901
|
var STORAGE = 128;
|
|
3638
2902
|
function findWebGpu() {
|
|
3639
2903
|
const nav = globalThis.navigator;
|
|
3640
|
-
return _nullishCoalesce(_optionalChain([nav, 'optionalAccess',
|
|
2904
|
+
return _nullishCoalesce(_optionalChain([nav, 'optionalAccess', _64 => _64.gpu]), () => ( null));
|
|
3641
2905
|
}
|
|
3642
2906
|
async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
3643
2907
|
const no = (reason, adapter2 = null) => ({ engine: null, support: { supported: false, reason, adapter: adapter2, maxSlots: 0 } });
|
|
@@ -3649,7 +2913,7 @@ async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
|
3649
2913
|
return no(`WebGPU gave no adapter (${e.message}); wet paint runs on the CPU.`);
|
|
3650
2914
|
}
|
|
3651
2915
|
if (!adapter) return no("WebGPU gave no adapter (the GPU may be blocklisted); wet paint runs on the CPU.");
|
|
3652
|
-
const name = [_optionalChain([adapter, 'access',
|
|
2916
|
+
const name = [_optionalChain([adapter, 'access', _65 => _65.info, 'optionalAccess', _66 => _66.vendor]), _optionalChain([adapter, 'access', _67 => _67.info, 'optionalAccess', _68 => _68.architecture])].filter(Boolean).join(" ") || null;
|
|
3653
2917
|
const binding = Math.min(_nullishCoalesce(adapter.limits.maxStorageBufferBindingSize, () => ( 0)), _nullishCoalesce(adapter.limits.maxBufferSize, () => ( 0)));
|
|
3654
2918
|
const maxSlots = Math.min(MAX_WET_SLOTS, Math.floor(binding / SLOT_BYTES));
|
|
3655
2919
|
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);
|
|
@@ -3669,32 +2933,32 @@ async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
|
3669
2933
|
const engine = await WetGpuEngine.start(device, maxSlots, name);
|
|
3670
2934
|
return { engine, support: { supported: true, reason: null, adapter: name, maxSlots } };
|
|
3671
2935
|
} catch (e) {
|
|
3672
|
-
_optionalChain([device, 'access',
|
|
2936
|
+
_optionalChain([device, 'access', _69 => _69.destroy, 'optionalCall', _70 => _70()]);
|
|
3673
2937
|
return no(`The wet-media shaders did not compile on this GPU (${e.message}); wet paint runs on the CPU.`, name);
|
|
3674
2938
|
}
|
|
3675
2939
|
}
|
|
3676
2940
|
async function wetGpuSupport(gpu = findWebGpu()) {
|
|
3677
2941
|
const { engine, support } = await createWetGpuEngine(gpu);
|
|
3678
|
-
_optionalChain([engine, 'optionalAccess',
|
|
2942
|
+
_optionalChain([engine, 'optionalAccess', _71 => _71.destroy, 'call', _72 => _72()]);
|
|
3679
2943
|
return support;
|
|
3680
2944
|
}
|
|
3681
2945
|
async function pipeline(device, code, label) {
|
|
3682
|
-
_optionalChain([device, 'access',
|
|
2946
|
+
_optionalChain([device, 'access', _73 => _73.pushErrorScope, 'optionalCall', _74 => _74("validation")]);
|
|
3683
2947
|
const module = device.createShaderModule({ code, label });
|
|
3684
|
-
const info = await _optionalChain([module, 'access',
|
|
3685
|
-
const errors = _nullishCoalesce(_optionalChain([info, 'optionalAccess',
|
|
2948
|
+
const info = await _optionalChain([module, 'access', _75 => _75.getCompilationInfo, 'optionalCall', _76 => _76()]);
|
|
2949
|
+
const errors = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _77 => _77.messages, 'access', _78 => _78.filter, 'call', _79 => _79((m) => m.type === "error")]), () => ( []));
|
|
3686
2950
|
if (errors.length) {
|
|
3687
|
-
await _optionalChain([device, 'access',
|
|
2951
|
+
await _optionalChain([device, 'access', _80 => _80.popErrorScope, 'optionalCall', _81 => _81()]);
|
|
3688
2952
|
throw new Error(`${label}: ${errors.map((m) => `line ${m.lineNum}: ${m.message}`).join("; ")}`);
|
|
3689
2953
|
}
|
|
3690
2954
|
const desc = { layout: "auto", compute: { module, entryPoint: "main" }, label };
|
|
3691
2955
|
const p = device.createComputePipelineAsync ? await device.createComputePipelineAsync(desc) : device.createComputePipeline(desc);
|
|
3692
|
-
const err = await _optionalChain([device, 'access',
|
|
2956
|
+
const err = await _optionalChain([device, 'access', _82 => _82.popErrorScope, 'optionalCall', _83 => _83()]);
|
|
3693
2957
|
if (err) throw new Error(`${label}: ${err.message}`);
|
|
3694
2958
|
return p;
|
|
3695
2959
|
}
|
|
3696
|
-
var WetGpuEngine = (
|
|
3697
|
-
constructor(device, maxSlots, adapter, stepPipe, haloPipe, shadePipe) {;
|
|
2960
|
+
var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
2961
|
+
constructor(device, maxSlots, adapter, stepPipe, haloPipe, shadePipe) {;_class3.prototype.__init25.call(this);_class3.prototype.__init26.call(this);_class3.prototype.__init27.call(this);_class3.prototype.__init28.call(this);_class3.prototype.__init29.call(this);_class3.prototype.__init30.call(this);_class3.prototype.__init31.call(this);_class3.prototype.__init32.call(this);_class3.prototype.__init33.call(this);
|
|
3698
2962
|
this.device = device;
|
|
3699
2963
|
this.maxSlots = maxSlots;
|
|
3700
2964
|
this.adapter = adapter;
|
|
@@ -3715,8 +2979,8 @@ var WetGpuEngine = (_class6 = class _WetGpuEngine {
|
|
|
3715
2979
|
return b;
|
|
3716
2980
|
});
|
|
3717
2981
|
this.shadeUni = d.createBuffer({ size: 16, usage: UNIFORM | COPY_DST, label: "wet shade" });
|
|
3718
|
-
void _optionalChain([device, 'access',
|
|
3719
|
-
this.lostReason = _optionalChain([info, 'optionalAccess',
|
|
2982
|
+
void _optionalChain([device, 'access', _84 => _84.lost, 'optionalAccess', _85 => _85.then, 'call', _86 => _86((info) => {
|
|
2983
|
+
this.lostReason = _optionalChain([info, 'optionalAccess', _87 => _87.message]) || _optionalChain([info, 'optionalAccess', _88 => _88.reason]) || "the GPU device was lost";
|
|
3720
2984
|
})]);
|
|
3721
2985
|
}
|
|
3722
2986
|
|
|
@@ -3726,23 +2990,23 @@ var WetGpuEngine = (_class6 = class _WetGpuEngine {
|
|
|
3726
2990
|
|
|
3727
2991
|
|
|
3728
2992
|
/** Steps run on the GPU so far (for stats). */
|
|
3729
|
-
|
|
2993
|
+
__init25() {this.steps = 0}
|
|
3730
2994
|
/** Set once the device is lost; the engine does nothing after that. */
|
|
3731
|
-
|
|
2995
|
+
__init26() {this.lostReason = null}
|
|
3732
2996
|
|
|
3733
|
-
|
|
2997
|
+
__init27() {this.slots = 0}
|
|
3734
2998
|
|
|
3735
2999
|
|
|
3736
|
-
|
|
3000
|
+
__init28() {this.jobCap = 0}
|
|
3737
3001
|
|
|
3738
3002
|
|
|
3739
3003
|
|
|
3740
3004
|
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3005
|
+
__init29() {this.srcTiles = null}
|
|
3006
|
+
__init30() {this.outTiles = null}
|
|
3007
|
+
__init31() {this.outRead = null}
|
|
3008
|
+
__init32() {this.tileCap = 0}
|
|
3009
|
+
__init33() {this.groups = null}
|
|
3746
3010
|
/** @internal Compiles the kernels; use `createWetGpuEngine`. */
|
|
3747
3011
|
static async start(device, maxSlots, adapter) {
|
|
3748
3012
|
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")]);
|
|
@@ -3750,7 +3014,7 @@ var WetGpuEngine = (_class6 = class _WetGpuEngine {
|
|
|
3750
3014
|
}
|
|
3751
3015
|
/** Bytes of GPU memory in use. */
|
|
3752
3016
|
memoryBytes() {
|
|
3753
|
-
return this.state.size + this.jobs.size + (_nullishCoalesce(_optionalChain([this, 'access',
|
|
3017
|
+
return this.state.size + this.jobs.size + (_nullishCoalesce(_optionalChain([this, 'access', _89 => _89.srcTiles, 'optionalAccess', _90 => _90.size]), () => ( 0))) + (_nullishCoalesce(_optionalChain([this, 'access', _91 => _91.outTiles, 'optionalAccess', _92 => _92.size]), () => ( 0))) * 2;
|
|
3754
3018
|
}
|
|
3755
3019
|
/** Slots the state buffer holds now. */
|
|
3756
3020
|
get capacity() {
|
|
@@ -3899,9 +3163,9 @@ var WetGpuEngine = (_class6 = class _WetGpuEngine {
|
|
|
3899
3163
|
const d = this.device;
|
|
3900
3164
|
const tileBytes = TILE_WORDS * 4;
|
|
3901
3165
|
if (n > this.tileCap || !this.outTiles || !this.outRead || !this.srcTiles) {
|
|
3902
|
-
_optionalChain([this, 'access',
|
|
3903
|
-
_optionalChain([this, 'access',
|
|
3904
|
-
_optionalChain([this, 'access',
|
|
3166
|
+
_optionalChain([this, 'access', _93 => _93.srcTiles, 'optionalAccess', _94 => _94.destroy, 'call', _95 => _95()]);
|
|
3167
|
+
_optionalChain([this, 'access', _96 => _96.outTiles, 'optionalAccess', _97 => _97.destroy, 'call', _98 => _98()]);
|
|
3168
|
+
_optionalChain([this, 'access', _99 => _99.outRead, 'optionalAccess', _100 => _100.destroy, 'call', _101 => _101()]);
|
|
3905
3169
|
this.tileCap = Math.max(n, this.tileCap * 2, 4);
|
|
3906
3170
|
this.srcTiles = d.createBuffer({ size: this.tileCap * tileBytes, usage: STORAGE | COPY_DST, label: "wet base tiles" });
|
|
3907
3171
|
this.outTiles = d.createBuffer({ size: this.tileCap * tileBytes, usage: STORAGE | COPY_SRC, label: "wet shaded tiles" });
|
|
@@ -3955,69 +3219,10 @@ var WetGpuEngine = (_class6 = class _WetGpuEngine {
|
|
|
3955
3219
|
return this.device.queue.onSubmittedWorkDone();
|
|
3956
3220
|
}
|
|
3957
3221
|
destroy() {
|
|
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',
|
|
3222
|
+
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', _102 => _102.destroy, 'call', _103 => _103()]);
|
|
3959
3223
|
this.device.destroy();
|
|
3960
3224
|
}
|
|
3961
|
-
},
|
|
3962
|
-
|
|
3963
|
-
// src/paint/pointer.ts
|
|
3964
|
-
function pointerPressure(e) {
|
|
3965
|
-
if (e.pointerType === "pen" && typeof e.pressure === "number" && e.pressure > 0) return Math.min(1, e.pressure);
|
|
3966
|
-
return 1;
|
|
3967
|
-
}
|
|
3968
|
-
function pointerStrokeSample(e, toPoint) {
|
|
3969
|
-
const p = toPoint(e.clientX, e.clientY);
|
|
3970
|
-
const s = { x: p.x, y: p.y, pressure: pointerPressure(e) };
|
|
3971
|
-
if (typeof e.timeStamp === "number" && Number.isFinite(e.timeStamp)) s.t = e.timeStamp;
|
|
3972
|
-
if (e.pointerType === "pen") {
|
|
3973
|
-
if (typeof e.altitudeAngle === "number" && e.altitudeAngle < Math.PI / 2 - 1e-6) {
|
|
3974
|
-
s.altitude = e.altitudeAngle;
|
|
3975
|
-
s.azimuth = _nullishCoalesce(e.azimuthAngle, () => ( 0));
|
|
3976
|
-
} else if (e.tiltX || e.tiltY) {
|
|
3977
|
-
s.tiltX = _nullishCoalesce(e.tiltX, () => ( 0));
|
|
3978
|
-
s.tiltY = _nullishCoalesce(e.tiltY, () => ( 0));
|
|
3979
|
-
}
|
|
3980
|
-
}
|
|
3981
|
-
return s;
|
|
3982
|
-
}
|
|
3983
|
-
function pointerStrokeSamples(e, toPoint) {
|
|
3984
|
-
const events = _nullishCoalesce(_optionalChain([e, 'access', _105 => _105.getCoalescedEvents, 'optionalCall', _106 => _106()]), () => ( []));
|
|
3985
|
-
return (events.length ? events : [e]).map((ev) => pointerStrokeSample(ev, toPoint));
|
|
3986
|
-
}
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
3225
|
+
}, _class3);
|
|
4021
3226
|
|
|
4022
3227
|
|
|
4023
3228
|
|
|
@@ -4110,4 +3315,4 @@ function pointerStrokeSamples(e, toPoint) {
|
|
|
4110
3315
|
|
|
4111
3316
|
|
|
4112
3317
|
|
|
4113
|
-
exports.
|
|
3318
|
+
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.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.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;
|