@pixerate/editor 0.109.0 → 0.110.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/blending-DXl06NSx.d.ts +486 -0
- package/dist/blending-aOE6Y3UE.d.cts +486 -0
- package/dist/chunk-7VOHOPLW.cjs +1136 -0
- package/dist/chunk-7VOHOPLW.cjs.map +1 -0
- package/dist/{chunk-RE77QYUF.js → chunk-DMRSJBJF.js} +3 -3
- package/dist/chunk-FTBZPI77.cjs +1 -0
- package/dist/chunk-FTBZPI77.cjs.map +1 -0
- package/dist/{chunk-WMBIJCHA.js → chunk-HNS7UHCM.js} +5 -1
- package/dist/{chunk-WMBIJCHA.js.map → chunk-HNS7UHCM.js.map} +1 -1
- package/dist/{chunk-CFMWALBM.js → chunk-LQEEDHOP.js} +2 -2
- package/dist/{chunk-D37BX2ZA.cjs → chunk-MGL4U5WA.cjs} +199 -199
- package/dist/{chunk-D37BX2ZA.cjs.map → chunk-MGL4U5WA.cjs.map} +1 -1
- package/dist/{chunk-AZTZRLDI.cjs → chunk-POGBUYWE.cjs} +92 -92
- package/dist/{chunk-AZTZRLDI.cjs.map → chunk-POGBUYWE.cjs.map} +1 -1
- package/dist/chunk-VKK5VS2T.js +1 -0
- package/dist/{chunk-SZ6KMZNM.cjs → chunk-XIOMMGPD.cjs} +6 -2
- package/dist/chunk-XIOMMGPD.cjs.map +1 -0
- package/dist/{chunk-3PHA3UKI.js → chunk-Z4BC6M74.js} +523 -121
- package/dist/chunk-Z4BC6M74.js.map +1 -0
- package/dist/{export-BLPLaE6Z.d.ts → export-CO2ryu3I.d.ts} +3 -3
- package/dist/{export-DSUc4fQD.d.cts → export-DRiLzP_j.d.cts} +3 -3
- package/dist/image-editor/index.cjs +722 -696
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +9 -9
- package/dist/image-editor/index.d.ts +9 -9
- package/dist/image-editor/index.js +31 -5
- package/dist/image-editor/index.js.map +1 -1
- package/dist/paint/index.cjs +28 -4
- package/dist/paint/index.cjs.map +1 -1
- package/dist/paint/index.d.cts +3 -89
- package/dist/paint/index.d.ts +3 -89
- package/dist/paint/index.js +27 -3
- package/dist/paint-editor/index.cjs +1052 -286
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +301 -22
- package/dist/paint-editor/index.d.ts +301 -22
- package/dist/paint-editor/index.js +848 -82
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/raster/index.cjs +5 -3
- package/dist/raster/index.cjs.map +1 -1
- package/dist/raster/index.d.cts +2 -2
- package/dist/raster/index.d.ts +2 -2
- package/dist/raster/index.js +4 -2
- package/dist/{render-C-fO_mes.d.cts → render-BEriFuqK.d.cts} +1 -1
- package/dist/{render-OLIMk_v0.d.ts → render-tjzKaik-.d.ts} +1 -1
- package/dist/{surface-CkKOHGPm.d.cts → surface-C8RRg_Bh.d.cts} +109 -1
- package/dist/{surface-CkKOHGPm.d.ts → surface-C8RRg_Bh.d.ts} +109 -1
- package/package.json +1 -1
- package/skills/pixerate-paint-editor/SKILL.md +49 -13
- package/dist/chunk-3PHA3UKI.js.map +0 -1
- package/dist/chunk-6BU5WU4R.cjs +0 -1
- package/dist/chunk-6BU5WU4R.cjs.map +0 -1
- package/dist/chunk-HUFQD4CB.cjs +0 -734
- package/dist/chunk-HUFQD4CB.cjs.map +0 -1
- package/dist/chunk-SZ6KMZNM.cjs.map +0 -1
- package/dist/chunk-XYBJKUAU.js +0 -1
- package/dist/mixer-5ziHU8OS.d.cts +0 -282
- package/dist/mixer-DNqiYXYQ.d.ts +0 -282
- /package/dist/{chunk-RE77QYUF.js.map → chunk-DMRSJBJF.js.map} +0 -0
- /package/dist/{chunk-CFMWALBM.js.map → chunk-LQEEDHOP.js.map} +0 -0
- /package/dist/{chunk-XYBJKUAU.js.map → chunk-VKK5VS2T.js.map} +0 -0
package/dist/chunk-HUFQD4CB.cjs
DELETED
|
@@ -1,734 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); 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;
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var _chunkSZ6KMZNMcjs = require('./chunk-SZ6KMZNM.cjs');
|
|
12
|
-
|
|
13
|
-
// src/paint/brush.ts
|
|
14
|
-
var DEFAULT_BRUSH = {
|
|
15
|
-
size: 20,
|
|
16
|
-
hardness: 1,
|
|
17
|
-
spacing: 0.1,
|
|
18
|
-
angle: 0,
|
|
19
|
-
roundness: 1,
|
|
20
|
-
opacity: 1,
|
|
21
|
-
flow: 1,
|
|
22
|
-
smoothing: 0,
|
|
23
|
-
pressureSize: true,
|
|
24
|
-
pressureOpacity: false,
|
|
25
|
-
blend: "normal"
|
|
26
|
-
};
|
|
27
|
-
var MAX_BRUSH_SIZE = 2500;
|
|
28
|
-
function normalizeBrush(raw = {}) {
|
|
29
|
-
const num = (v, lo, hi, d) => typeof v === "number" && Number.isFinite(v) ? Math.min(hi, Math.max(lo, v)) : d;
|
|
30
|
-
return {
|
|
31
|
-
size: num(raw.size, 1, MAX_BRUSH_SIZE, DEFAULT_BRUSH.size),
|
|
32
|
-
hardness: num(raw.hardness, 0, 1, DEFAULT_BRUSH.hardness),
|
|
33
|
-
spacing: num(raw.spacing, 0.01, 10, DEFAULT_BRUSH.spacing),
|
|
34
|
-
angle: num(raw.angle, -360, 360, DEFAULT_BRUSH.angle),
|
|
35
|
-
roundness: num(raw.roundness, 0.01, 1, DEFAULT_BRUSH.roundness),
|
|
36
|
-
opacity: num(raw.opacity, 0, 1, DEFAULT_BRUSH.opacity),
|
|
37
|
-
flow: num(raw.flow, 0, 1, DEFAULT_BRUSH.flow),
|
|
38
|
-
smoothing: num(raw.smoothing, 0, 0.95, DEFAULT_BRUSH.smoothing),
|
|
39
|
-
pressureSize: typeof raw.pressureSize === "boolean" ? raw.pressureSize : DEFAULT_BRUSH.pressureSize,
|
|
40
|
-
pressureOpacity: typeof raw.pressureOpacity === "boolean" ? raw.pressureOpacity : DEFAULT_BRUSH.pressureOpacity,
|
|
41
|
-
blend: _nullishCoalesce(raw.blend, () => ( "normal"))
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
var TIP_SHAPE = [
|
|
45
|
-
[0, 0.664],
|
|
46
|
-
[0.14, 0.58],
|
|
47
|
-
[0.28, 0.5],
|
|
48
|
-
[0.4, 0.44],
|
|
49
|
-
[0.52, 0.36],
|
|
50
|
-
[0.63, 0.29],
|
|
51
|
-
[0.7, 0.24],
|
|
52
|
-
[0.78, 0.19],
|
|
53
|
-
[0.84, 0.15],
|
|
54
|
-
[0.89, 0.11],
|
|
55
|
-
[1, 0]
|
|
56
|
-
];
|
|
57
|
-
var TIP_EDGE_PX = 1.2;
|
|
58
|
-
var SMALL_TIP_RADIUS = 3;
|
|
59
|
-
var SUBPIXEL = [-0.375, -0.125, 0.125, 0.375];
|
|
60
|
-
function tipShape(radius, hardness) {
|
|
61
|
-
const h = (Number.isNaN(hardness) ? 0 : Math.min(1, Math.max(0, hardness))) * 10;
|
|
62
|
-
const i = Math.min(9, Math.floor(h));
|
|
63
|
-
const t = h - i;
|
|
64
|
-
const a = TIP_SHAPE[i];
|
|
65
|
-
const b = TIP_SHAPE[i + 1];
|
|
66
|
-
const r0 = a[0] + (b[0] - a[0]) * t;
|
|
67
|
-
const s = a[1] + (b[1] - a[1]) * t;
|
|
68
|
-
const r = Number.isFinite(radius) ? Math.max(0, radius) : 0;
|
|
69
|
-
const edge = Math.max(0.25, Math.min(TIP_EDGE_PX, 0.3 * r));
|
|
70
|
-
return [Math.max(0, Math.min(r0 * r, r - edge)), Math.max(1e-3, s * r, edge)];
|
|
71
|
-
}
|
|
72
|
-
function softExp(u) {
|
|
73
|
-
let g = Math.min(1, Math.max(0, 1 - u / 64));
|
|
74
|
-
for (let k = 0; k < 6; k++) g *= g;
|
|
75
|
-
return g;
|
|
76
|
-
}
|
|
77
|
-
function tipFalloff(d, radius, hardness) {
|
|
78
|
-
const [r0, s] = tipShape(radius, hardness);
|
|
79
|
-
if (d <= r0) return 1;
|
|
80
|
-
const x = (d - r0) / s;
|
|
81
|
-
return softExp(x * x);
|
|
82
|
-
}
|
|
83
|
-
function tipReach(radius, hardness) {
|
|
84
|
-
const [r0, s] = tipShape(radius, hardness);
|
|
85
|
-
return r0 + 2.6 * s;
|
|
86
|
-
}
|
|
87
|
-
function dabCoverage(d, radius, hardness) {
|
|
88
|
-
if (Number.isNaN(d) || d >= tipReach(radius, hardness) + 0.5) return 0;
|
|
89
|
-
return tipFalloff(d, radius, hardness);
|
|
90
|
-
}
|
|
91
|
-
function smoothPoints(points, amount) {
|
|
92
|
-
const a = 1 - Math.min(0.95, Math.max(0, amount));
|
|
93
|
-
if (a >= 1 || points.length < 3) return points.slice();
|
|
94
|
-
const out = [];
|
|
95
|
-
let cur = null;
|
|
96
|
-
for (const p of points) {
|
|
97
|
-
const n = cur ? { ...p, x: cur.x + (p.x - cur.x) * a, y: cur.y + (p.y - cur.y) * a } : p;
|
|
98
|
-
out.push(n);
|
|
99
|
-
cur = n;
|
|
100
|
-
}
|
|
101
|
-
out[out.length - 1] = points[points.length - 1];
|
|
102
|
-
return out;
|
|
103
|
-
}
|
|
104
|
-
var pressureOf = (p) => typeof p.pressure === "number" && Number.isFinite(p.pressure) ? Math.min(1, Math.max(0, p.pressure)) : 1;
|
|
105
|
-
var DabWalker = (_class = class {
|
|
106
|
-
constructor(brush) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
|
|
107
|
-
this.brush = brush;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
__init() {this.last = null}
|
|
111
|
-
__init2() {this.nextAt = 0}
|
|
112
|
-
__init3() {this.pendingFirst = null}
|
|
113
|
-
diameter(p) {
|
|
114
|
-
return this.brush.pressureSize ? this.brush.size * pressureOf(p) : this.brush.size;
|
|
115
|
-
}
|
|
116
|
-
stepLen(p) {
|
|
117
|
-
return Math.max(0.5, Math.max(1, this.diameter(p)) * Math.max(0.01, this.brush.spacing));
|
|
118
|
-
}
|
|
119
|
-
dab(p) {
|
|
120
|
-
const b = this.brush;
|
|
121
|
-
return {
|
|
122
|
-
x: p.x,
|
|
123
|
-
y: p.y,
|
|
124
|
-
radius: Math.max(0.5, this.diameter(p) / 2),
|
|
125
|
-
alpha: Math.min(1, Math.max(0, b.flow)),
|
|
126
|
-
opacity: b.pressureOpacity ? pressureOf(p) : 1,
|
|
127
|
-
angle: b.angle * Math.PI / 180,
|
|
128
|
-
roundness: Math.min(1, Math.max(0.01, b.roundness))
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
push(p, out) {
|
|
132
|
-
const a = this.last;
|
|
133
|
-
if (!a) {
|
|
134
|
-
this.last = p;
|
|
135
|
-
this.pendingFirst = p;
|
|
136
|
-
this.nextAt = this.stepLen(p);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (this.pendingFirst) {
|
|
140
|
-
out.push(this.dab(this.pendingFirst));
|
|
141
|
-
this.pendingFirst = null;
|
|
142
|
-
}
|
|
143
|
-
const dx = p.x - a.x;
|
|
144
|
-
const dy = p.y - a.y;
|
|
145
|
-
const len = Math.hypot(dx, dy);
|
|
146
|
-
if (len > 1e-9) {
|
|
147
|
-
while (this.nextAt <= len + 1e-9) {
|
|
148
|
-
const f = Math.min(1, this.nextAt / len);
|
|
149
|
-
const q = {
|
|
150
|
-
x: a.x + dx * f,
|
|
151
|
-
y: a.y + dy * f,
|
|
152
|
-
pressure: pressureOf(a) + (pressureOf(p) - pressureOf(a)) * f
|
|
153
|
-
};
|
|
154
|
-
out.push(this.dab(q));
|
|
155
|
-
this.nextAt += this.stepLen(q);
|
|
156
|
-
}
|
|
157
|
-
this.nextAt -= len;
|
|
158
|
-
}
|
|
159
|
-
this.last = p;
|
|
160
|
-
}
|
|
161
|
-
finish(out) {
|
|
162
|
-
if (this.pendingFirst) {
|
|
163
|
-
out.push(this.dab(this.pendingFirst));
|
|
164
|
-
this.pendingFirst = null;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}, _class);
|
|
168
|
-
function walkDabs(points, brush) {
|
|
169
|
-
const w = new DabWalker(brush);
|
|
170
|
-
const out = [];
|
|
171
|
-
for (const p of smoothPoints(points, brush.smoothing)) w.push(p, out);
|
|
172
|
-
w.finish(out);
|
|
173
|
-
return out;
|
|
174
|
-
}
|
|
175
|
-
function dabRect(d, hardness) {
|
|
176
|
-
const ro = Math.min(1, Math.max(0.5 / d.radius, d.roundness));
|
|
177
|
-
const rm = Math.max(0.5, d.radius * ro);
|
|
178
|
-
const r = Math.max(rm, tipReach(rm, hardness)) / ro + 1.5;
|
|
179
|
-
const x0 = Math.floor(d.x - r);
|
|
180
|
-
const y0 = Math.floor(d.y - r);
|
|
181
|
-
return { x: x0, y: y0, width: Math.ceil(d.x + r) - x0, height: Math.ceil(d.y + r) - y0 };
|
|
182
|
-
}
|
|
183
|
-
function rasterizeDab(d, hardness, rect, out) {
|
|
184
|
-
const w = rect.width;
|
|
185
|
-
const h = rect.height;
|
|
186
|
-
out.fill(0, 0, w * h);
|
|
187
|
-
const r = d.radius;
|
|
188
|
-
const ro = Math.min(1, Math.max(0.5 / r, d.roundness));
|
|
189
|
-
const rm = Math.max(0.5, r * ro);
|
|
190
|
-
const reach = Math.max(rm, tipReach(rm, hardness));
|
|
191
|
-
const sn = Math.sin(d.angle);
|
|
192
|
-
const cs = Math.cos(d.angle);
|
|
193
|
-
const toTip = (dx, dy) => {
|
|
194
|
-
const ux = dx;
|
|
195
|
-
const uy = -dy;
|
|
196
|
-
return [ux * cs + uy * sn, -ux * sn + uy * cs];
|
|
197
|
-
};
|
|
198
|
-
const small = rm < SMALL_TIP_RADIUS;
|
|
199
|
-
const reach2 = (reach + (small ? 0.75 : 0.5)) ** 2;
|
|
200
|
-
for (let yy = 0; yy < h; yy++) {
|
|
201
|
-
const dy = rect.y + yy + 0.5 - d.y;
|
|
202
|
-
for (let xx = 0; xx < w; xx++) {
|
|
203
|
-
const dx = rect.x + xx + 0.5 - d.x;
|
|
204
|
-
const [u, v] = toTip(dx, dy);
|
|
205
|
-
const d2 = (u * ro) ** 2 + v * v;
|
|
206
|
-
if (d2 >= reach2) continue;
|
|
207
|
-
let val;
|
|
208
|
-
if (small) {
|
|
209
|
-
let sum = 0;
|
|
210
|
-
for (const sy of SUBPIXEL) {
|
|
211
|
-
for (const sx of SUBPIXEL) {
|
|
212
|
-
const [su, sv] = toTip(dx + sx, dy + sy);
|
|
213
|
-
sum += tipFalloff(Math.sqrt((su * ro) ** 2 + sv * sv), rm, hardness);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
val = sum / 16;
|
|
217
|
-
} else {
|
|
218
|
-
val = dabCoverage(Math.sqrt(d2), rm, hardness);
|
|
219
|
-
}
|
|
220
|
-
if (val > 0) out[yy * w + xx] = val * d.alpha;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
var TILE_PIXELS = _chunkSZ6KMZNMcjs.TILE * _chunkSZ6KMZNMcjs.TILE;
|
|
225
|
-
var CoverageMap = (_class2 = class {constructor() { _class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this); }
|
|
226
|
-
__init4() {this.tiles = /* @__PURE__ */ new Map()}
|
|
227
|
-
__init5() {this.bounds = null}
|
|
228
|
-
__init6() {this.dirty = /* @__PURE__ */ new Set()}
|
|
229
|
-
get(x, y) {
|
|
230
|
-
const tx = Math.floor(x / _chunkSZ6KMZNMcjs.TILE);
|
|
231
|
-
const ty = Math.floor(y / _chunkSZ6KMZNMcjs.TILE);
|
|
232
|
-
const t = this.tiles.get(_chunkSZ6KMZNMcjs.tileKey.call(void 0, tx, ty));
|
|
233
|
-
return t ? t[(y - ty * _chunkSZ6KMZNMcjs.TILE) * _chunkSZ6KMZNMcjs.TILE + (x - tx * _chunkSZ6KMZNMcjs.TILE)] : 0;
|
|
234
|
-
}
|
|
235
|
-
/** Builds up `vals` (over `rect`) with flow towards `ceil`: `c ← c + v·(ceil − c)`. */
|
|
236
|
-
accumulate(rect, vals, ceil) {
|
|
237
|
-
if (rect.width <= 0 || rect.height <= 0) return;
|
|
238
|
-
const w = rect.width;
|
|
239
|
-
const tx0 = Math.floor(rect.x / _chunkSZ6KMZNMcjs.TILE);
|
|
240
|
-
const ty0 = Math.floor(rect.y / _chunkSZ6KMZNMcjs.TILE);
|
|
241
|
-
const tx1 = Math.floor((rect.x + rect.width - 1) / _chunkSZ6KMZNMcjs.TILE);
|
|
242
|
-
const ty1 = Math.floor((rect.y + rect.height - 1) / _chunkSZ6KMZNMcjs.TILE);
|
|
243
|
-
let touched = false;
|
|
244
|
-
for (let ty = ty0; ty <= ty1; ty++) {
|
|
245
|
-
for (let tx = tx0; tx <= tx1; tx++) {
|
|
246
|
-
const x0 = Math.max(rect.x, tx * _chunkSZ6KMZNMcjs.TILE);
|
|
247
|
-
const y0 = Math.max(rect.y, ty * _chunkSZ6KMZNMcjs.TILE);
|
|
248
|
-
const x1 = Math.min(rect.x + rect.width, tx * _chunkSZ6KMZNMcjs.TILE + _chunkSZ6KMZNMcjs.TILE);
|
|
249
|
-
const y1 = Math.min(rect.y + rect.height, ty * _chunkSZ6KMZNMcjs.TILE + _chunkSZ6KMZNMcjs.TILE);
|
|
250
|
-
let tile;
|
|
251
|
-
for (let y = y0; y < y1; y++) {
|
|
252
|
-
const row = (y - rect.y) * w;
|
|
253
|
-
const trow = (y - ty * _chunkSZ6KMZNMcjs.TILE) * _chunkSZ6KMZNMcjs.TILE;
|
|
254
|
-
for (let x = x0; x < x1; x++) {
|
|
255
|
-
const v = vals[row + (x - rect.x)];
|
|
256
|
-
if (v <= 0) continue;
|
|
257
|
-
if (!tile) {
|
|
258
|
-
const key = _chunkSZ6KMZNMcjs.tileKey.call(void 0, tx, ty);
|
|
259
|
-
tile = this.tiles.get(key);
|
|
260
|
-
if (!tile) {
|
|
261
|
-
tile = new Float32Array(TILE_PIXELS);
|
|
262
|
-
this.tiles.set(key, tile);
|
|
263
|
-
}
|
|
264
|
-
this.dirty.add(key);
|
|
265
|
-
touched = true;
|
|
266
|
-
}
|
|
267
|
-
const ti = trow + (x - tx * _chunkSZ6KMZNMcjs.TILE);
|
|
268
|
-
const c = tile[ti];
|
|
269
|
-
if (ceil > c) tile[ti] = c + v * (ceil - c);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (touched) this.bounds = unionRect(this.bounds, rect);
|
|
275
|
-
}
|
|
276
|
-
/** Tiles changed since the last call. */
|
|
277
|
-
takeDirty() {
|
|
278
|
-
const out = [...this.dirty];
|
|
279
|
-
this.dirty.clear();
|
|
280
|
-
return out;
|
|
281
|
-
}
|
|
282
|
-
}, _class2);
|
|
283
|
-
function unionRect(a, b) {
|
|
284
|
-
if (!a) return { ...b };
|
|
285
|
-
const x = Math.min(a.x, b.x);
|
|
286
|
-
const y = Math.min(a.y, b.y);
|
|
287
|
-
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 };
|
|
288
|
-
}
|
|
289
|
-
var StrokeCoverage = (_class3 = class {
|
|
290
|
-
constructor(brush) {;_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);
|
|
291
|
-
this.brush = brush;
|
|
292
|
-
this.walker = new DabWalker(brush);
|
|
293
|
-
this.smoothing = brush.smoothing;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
__init7() {this.coverage = new CoverageMap()}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
__init8() {this.smoothPos = null}
|
|
300
|
-
__init9() {this.buf = new Float32Array(0)}
|
|
301
|
-
__init10() {this.dabCount = 0}
|
|
302
|
-
/** Feeds input points; returns the document rectangles the new dabs touched. */
|
|
303
|
-
push(points) {
|
|
304
|
-
const dabs = [];
|
|
305
|
-
for (const p of points) this.walker.push(this.smooth(p), dabs);
|
|
306
|
-
return this.paint(dabs);
|
|
307
|
-
}
|
|
308
|
-
/** Ends the stroke (a single click still paints one dab). */
|
|
309
|
-
finish(last) {
|
|
310
|
-
const dabs = [];
|
|
311
|
-
if (last && this.smoothPos && (this.smoothPos.x !== last.x || this.smoothPos.y !== last.y)) this.walker.push(last, dabs);
|
|
312
|
-
this.walker.finish(dabs);
|
|
313
|
-
return this.paint(dabs);
|
|
314
|
-
}
|
|
315
|
-
smooth(p) {
|
|
316
|
-
const a = 1 - Math.min(0.95, Math.max(0, this.smoothing));
|
|
317
|
-
const cur = this.smoothPos;
|
|
318
|
-
const n = cur && a < 1 ? { ...p, x: cur.x + (p.x - cur.x) * a, y: cur.y + (p.y - cur.y) * a } : p;
|
|
319
|
-
this.smoothPos = n;
|
|
320
|
-
return n;
|
|
321
|
-
}
|
|
322
|
-
paint(dabs) {
|
|
323
|
-
const rects = [];
|
|
324
|
-
for (const d of dabs) {
|
|
325
|
-
const rect = dabRect(d, this.brush.hardness);
|
|
326
|
-
const n = rect.width * rect.height;
|
|
327
|
-
if (this.buf.length < n) this.buf = new Float32Array(n);
|
|
328
|
-
const vals = this.buf.subarray(0, n);
|
|
329
|
-
rasterizeDab(d, this.brush.hardness, rect, vals);
|
|
330
|
-
this.coverage.accumulate(rect, vals, d.opacity);
|
|
331
|
-
rects.push(rect);
|
|
332
|
-
this.dabCount++;
|
|
333
|
-
}
|
|
334
|
-
return rects;
|
|
335
|
-
}
|
|
336
|
-
}, _class3);
|
|
337
|
-
function applyStrokeToTile(coverage, tileData, channels, tx, ty, s, options = {}) {
|
|
338
|
-
const out = options.into ? new Uint8ClampedArray(options.into) : new Uint8ClampedArray(tileData);
|
|
339
|
-
const ox = tx * _chunkSZ6KMZNMcjs.TILE + s.offset.x;
|
|
340
|
-
const oy = ty * _chunkSZ6KMZNMcjs.TILE + s.offset.y;
|
|
341
|
-
let x0 = 0;
|
|
342
|
-
let y0 = 0;
|
|
343
|
-
let x1 = _chunkSZ6KMZNMcjs.TILE;
|
|
344
|
-
let y1 = _chunkSZ6KMZNMcjs.TILE;
|
|
345
|
-
if (options.region) {
|
|
346
|
-
const r = options.region;
|
|
347
|
-
x0 = Math.max(0, Math.floor(r.x) - ox);
|
|
348
|
-
y0 = Math.max(0, Math.floor(r.y) - oy);
|
|
349
|
-
x1 = Math.min(_chunkSZ6KMZNMcjs.TILE, Math.ceil(r.x + r.width) - ox);
|
|
350
|
-
y1 = Math.min(_chunkSZ6KMZNMcjs.TILE, Math.ceil(r.y + r.height) - oy);
|
|
351
|
-
if (x1 <= x0 || y1 <= y0) return out;
|
|
352
|
-
if (options.into) {
|
|
353
|
-
for (let y = y0; y < y1; y++) out.set(tileData.subarray((y * _chunkSZ6KMZNMcjs.TILE + x0) * channels, (y * _chunkSZ6KMZNMcjs.TILE + x1) * channels), (y * _chunkSZ6KMZNMcjs.TILE + x0) * channels);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
const sel = s.selection;
|
|
357
|
-
const cb = [0, 0, 0, 0];
|
|
358
|
-
const cs = [s.color[0] / 255, s.color[1] / 255, s.color[2] / 255, s.color[3] / 255];
|
|
359
|
-
const bg = [s.background[0] / 255, s.background[1] / 255, s.background[2] / 255, s.background[3] / 255];
|
|
360
|
-
const aligned = s.offset.x % _chunkSZ6KMZNMcjs.TILE === 0 && s.offset.y % _chunkSZ6KMZNMcjs.TILE === 0;
|
|
361
|
-
const covTile = aligned ? coverage.tiles.get(_chunkSZ6KMZNMcjs.tileKey.call(void 0, Math.floor(ox / _chunkSZ6KMZNMcjs.TILE), Math.floor(oy / _chunkSZ6KMZNMcjs.TILE))) : void 0;
|
|
362
|
-
if (aligned && !covTile) return out;
|
|
363
|
-
for (let y = y0; y < y1; y++) {
|
|
364
|
-
const dy = oy + y;
|
|
365
|
-
for (let x = x0; x < x1; x++) {
|
|
366
|
-
const dx = ox + x;
|
|
367
|
-
const c = covTile ? covTile[y * _chunkSZ6KMZNMcjs.TILE + x] : coverage.get(dx, dy);
|
|
368
|
-
if (c <= 0) continue;
|
|
369
|
-
let k = c * s.opacity;
|
|
370
|
-
if (sel) {
|
|
371
|
-
if (dx < 0 || dy < 0 || dx >= sel.width || dy >= sel.height) continue;
|
|
372
|
-
k *= sel.data[dy * sel.width + dx] / 255;
|
|
373
|
-
}
|
|
374
|
-
if (k > 1) k = 1;
|
|
375
|
-
if (k <= 0) continue;
|
|
376
|
-
const p = y * _chunkSZ6KMZNMcjs.TILE + x;
|
|
377
|
-
if (channels === 1) {
|
|
378
|
-
const target = s.mode === "erase" ? s.background[0] : s.color[0];
|
|
379
|
-
out[p] = Math.round(out[p] + (target - out[p]) * k);
|
|
380
|
-
continue;
|
|
381
|
-
}
|
|
382
|
-
const i = p * 4;
|
|
383
|
-
if (s.mode === "erase" && !s.lockTransparency) {
|
|
384
|
-
out[i + 3] = Math.round(out[i + 3] * (1 - k));
|
|
385
|
-
continue;
|
|
386
|
-
}
|
|
387
|
-
if (s.lockTransparency && out[i + 3] === 0) continue;
|
|
388
|
-
const src = s.mode === "erase" ? bg : cs;
|
|
389
|
-
if (s.blend === "pigment") {
|
|
390
|
-
const bytes = s.mode === "erase" ? s.background : s.color;
|
|
391
|
-
const as = src[3] * k;
|
|
392
|
-
if (!(as > 0)) continue;
|
|
393
|
-
const ao = as + out[i + 3] / 255 * (1 - as);
|
|
394
|
-
_chunkSZ6KMZNMcjs.mixPigment8.call(void 0, out[i], out[i + 1], out[i + 2], bytes[0], bytes[1], bytes[2], as / ao, cb);
|
|
395
|
-
out[i] = Math.round(cb[0] * 255);
|
|
396
|
-
out[i + 1] = Math.round(cb[1] * 255);
|
|
397
|
-
out[i + 2] = Math.round(cb[2] * 255);
|
|
398
|
-
if (!s.lockTransparency) out[i + 3] = Math.round(ao * 255);
|
|
399
|
-
continue;
|
|
400
|
-
}
|
|
401
|
-
for (let ch = 0; ch < 4; ch++) cb[ch] = out[i + ch] / 255;
|
|
402
|
-
const o = _chunkSZ6KMZNMcjs.blendPixel.call(void 0, s.blend, cb, src, k);
|
|
403
|
-
out[i] = Math.round(o[0] * 255);
|
|
404
|
-
out[i + 1] = Math.round(o[1] * 255);
|
|
405
|
-
out[i + 2] = Math.round(o[2] * 255);
|
|
406
|
-
if (!s.lockTransparency) out[i + 3] = Math.round(o[3] * 255);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
return out;
|
|
410
|
-
}
|
|
411
|
-
function coverageTileCoord(key) {
|
|
412
|
-
return _chunkSZ6KMZNMcjs.tileCoord.call(void 0, key);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// src/paint/mixer.ts
|
|
416
|
-
var MIXING_MODELS = ["rgb", "pigment"];
|
|
417
|
-
var DEFAULT_MIXER = {
|
|
418
|
-
wet: 0.5,
|
|
419
|
-
load: 0.5,
|
|
420
|
-
mix: 0.5,
|
|
421
|
-
loadEachStroke: true,
|
|
422
|
-
cleanEachStroke: true,
|
|
423
|
-
mixing: "rgb"
|
|
424
|
-
};
|
|
425
|
-
var MIXER_PICKUP_RATE = 0.25;
|
|
426
|
-
var MIXER_DRAIN = 0.08;
|
|
427
|
-
function normalizeMixer(raw = {}) {
|
|
428
|
-
const unit = (v, d) => typeof v === "number" && Number.isFinite(v) ? Math.min(1, Math.max(0, v)) : d;
|
|
429
|
-
const bool = (v, d) => typeof v === "boolean" ? v : d;
|
|
430
|
-
return {
|
|
431
|
-
wet: unit(raw.wet, DEFAULT_MIXER.wet),
|
|
432
|
-
load: unit(raw.load, DEFAULT_MIXER.load),
|
|
433
|
-
mix: unit(raw.mix, DEFAULT_MIXER.mix),
|
|
434
|
-
loadEachStroke: bool(raw.loadEachStroke, DEFAULT_MIXER.loadEachStroke),
|
|
435
|
-
cleanEachStroke: bool(raw.cleanEachStroke, DEFAULT_MIXER.cleanEachStroke),
|
|
436
|
-
mixing: raw.mixing === "pigment" ? "pigment" : "rgb"
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
var EMPTY_MIXER_LOAD = { reservoir: null, amount: 0, pickup: null };
|
|
440
|
-
function loadMixer(load, color) {
|
|
441
|
-
const c = (v) => Math.min(1, Math.max(0, Number.isFinite(v) ? v : 0));
|
|
442
|
-
return { reservoir: [c(color[0]), c(color[1]), c(color[2])], amount: 1, pickup: load.pickup };
|
|
443
|
-
}
|
|
444
|
-
function cleanMixer(load) {
|
|
445
|
-
return { reservoir: load.reservoir, amount: load.amount, pickup: null };
|
|
446
|
-
}
|
|
447
|
-
var MixerStroke = (_class4 = class {
|
|
448
|
-
constructor(brush, settings, load, target) {;_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);
|
|
449
|
-
this.brush = brush;
|
|
450
|
-
this.target = target;
|
|
451
|
-
this.settings = normalizeMixer(settings);
|
|
452
|
-
this.walker = new DabWalker(brush);
|
|
453
|
-
this.reservoir = load.reservoir ? [load.reservoir[0], load.reservoir[1], load.reservoir[2]] : null;
|
|
454
|
-
this.amount = this.reservoir ? Math.min(1, Math.max(0, load.amount)) : 0;
|
|
455
|
-
this.pickup = load.pickup ? [load.pickup[0], load.pickup[1], load.pickup[2]] : null;
|
|
456
|
-
this.pig = this.settings.mixing === "pigment" ? { res: _chunkSZ6KMZNMcjs.createPigment.call(void 0, _nullishCoalesce(this.reservoir, () => ( [0, 0, 0]))), pick: _chunkSZ6KMZNMcjs.createPigment.call(void 0, _nullishCoalesce(this.pickup, () => ( [0, 0, 0]))), paint: _chunkSZ6KMZNMcjs.createPigment.call(void 0, [0, 0, 0]), canvas: _chunkSZ6KMZNMcjs.createPigment.call(void 0, [0, 0, 0]) } : null;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
__init11() {this.dabCount = 0}
|
|
461
|
-
__init12() {this.bounds = null}
|
|
462
|
-
|
|
463
|
-
__init13() {this.smoothPos = null}
|
|
464
|
-
__init14() {this.buf = new Float32Array(0)}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
__init15() {this.out = [0, 0, 0]}
|
|
471
|
-
/** The brush load after the dabs so far. */
|
|
472
|
-
get load() {
|
|
473
|
-
return { reservoir: this.reservoir ? [...this.reservoir] : null, amount: this.amount, pickup: this.pickup ? [...this.pickup] : null };
|
|
474
|
-
}
|
|
475
|
-
push(points) {
|
|
476
|
-
const dabs = [];
|
|
477
|
-
for (const p of points) this.walker.push(this.smooth(p), dabs);
|
|
478
|
-
return this.paint(dabs);
|
|
479
|
-
}
|
|
480
|
-
finish(last) {
|
|
481
|
-
const dabs = [];
|
|
482
|
-
if (last && this.smoothPos && (this.smoothPos.x !== last.x || this.smoothPos.y !== last.y)) this.walker.push(last, dabs);
|
|
483
|
-
this.walker.finish(dabs);
|
|
484
|
-
return this.paint(dabs);
|
|
485
|
-
}
|
|
486
|
-
smooth(p) {
|
|
487
|
-
const a = 1 - Math.min(0.95, Math.max(0, this.brush.smoothing));
|
|
488
|
-
const cur = this.smoothPos;
|
|
489
|
-
const n = cur && a < 1 ? { ...p, x: cur.x + (p.x - cur.x) * a, y: cur.y + (p.y - cur.y) * a } : p;
|
|
490
|
-
this.smoothPos = n;
|
|
491
|
-
return n;
|
|
492
|
-
}
|
|
493
|
-
/** `a` mixed `t` of the way to `b` into `this.out`, by the mixing model. */
|
|
494
|
-
mix(a, pa, b, pb, t) {
|
|
495
|
-
const o = this.out;
|
|
496
|
-
if (pa && pb) _chunkSZ6KMZNMcjs.lerpPigmentInto.call(void 0, pa, pb, t, o, 0);
|
|
497
|
-
else for (let c = 0; c < 3; c++) o[c] = a[c] + (b[c] - a[c]) * t;
|
|
498
|
-
return o;
|
|
499
|
-
}
|
|
500
|
-
paint(dabs) {
|
|
501
|
-
const rects = [];
|
|
502
|
-
for (const d of dabs) {
|
|
503
|
-
const rect = dabRect(d, this.brush.hardness);
|
|
504
|
-
const n = rect.width * rect.height;
|
|
505
|
-
if (this.buf.length < n) this.buf = new Float32Array(n);
|
|
506
|
-
const cov = this.buf.subarray(0, n);
|
|
507
|
-
rasterizeDab({ ...d, alpha: 1 }, this.brush.hardness, rect, cov);
|
|
508
|
-
this.dab(d, rect, cov);
|
|
509
|
-
rects.push(rect);
|
|
510
|
-
this.bounds = union(this.bounds, rect);
|
|
511
|
-
this.dabCount++;
|
|
512
|
-
}
|
|
513
|
-
return rects;
|
|
514
|
-
}
|
|
515
|
-
// The tile last looked up by `locate` (and whether it came from `writeTile`).
|
|
516
|
-
__init16() {this.tx = NaN}
|
|
517
|
-
__init17() {this.ty = NaN}
|
|
518
|
-
__init18() {this.tile = null}
|
|
519
|
-
__init19() {this.writable = false}
|
|
520
|
-
/** Index of document pixel (dx, dy) in `this.tile`, or -1 when reading an empty tile. */
|
|
521
|
-
locate(dx, dy, write) {
|
|
522
|
-
const t = this.target;
|
|
523
|
-
const lx = dx - t.offset.x;
|
|
524
|
-
const ly = dy - t.offset.y;
|
|
525
|
-
const tx = Math.floor(lx / _chunkSZ6KMZNMcjs.TILE);
|
|
526
|
-
const ty = Math.floor(ly / _chunkSZ6KMZNMcjs.TILE);
|
|
527
|
-
if (tx !== this.tx || ty !== this.ty || write && !this.writable) {
|
|
528
|
-
this.tx = tx;
|
|
529
|
-
this.ty = ty;
|
|
530
|
-
this.tile = write ? t.writeTile(tx, ty) : t.readTile(tx, ty);
|
|
531
|
-
this.writable = write;
|
|
532
|
-
}
|
|
533
|
-
return this.tile ? ((ly - ty * _chunkSZ6KMZNMcjs.TILE) * _chunkSZ6KMZNMcjs.TILE + (lx - tx * _chunkSZ6KMZNMcjs.TILE)) * 4 : -1;
|
|
534
|
-
}
|
|
535
|
-
dab(d, rect, cov) {
|
|
536
|
-
const { wet, mix, load } = this.settings;
|
|
537
|
-
const pig = this.pig;
|
|
538
|
-
const w = rect.width;
|
|
539
|
-
this.tx = NaN;
|
|
540
|
-
let ar = 0;
|
|
541
|
-
let ag = 0;
|
|
542
|
-
let ab = 0;
|
|
543
|
-
let wsum = 0;
|
|
544
|
-
let asum = 0;
|
|
545
|
-
for (let yy = 0; yy < rect.height; yy++) {
|
|
546
|
-
for (let xx = 0; xx < w; xx++) {
|
|
547
|
-
const k = cov[yy * w + xx];
|
|
548
|
-
if (k <= 0) continue;
|
|
549
|
-
wsum += k;
|
|
550
|
-
const i = this.locate(rect.x + xx, rect.y + yy, false);
|
|
551
|
-
if (i < 0) continue;
|
|
552
|
-
const px = this.tile;
|
|
553
|
-
const al = px[i + 3] / 255;
|
|
554
|
-
if (al <= 0) continue;
|
|
555
|
-
const ka = k * al;
|
|
556
|
-
ar += px[i] / 255 * ka;
|
|
557
|
-
ag += px[i + 1] / 255 * ka;
|
|
558
|
-
ab += px[i + 2] / 255 * ka;
|
|
559
|
-
asum += ka;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
if (asum > 1e-6 && wet > 0) {
|
|
563
|
-
const canvas = [ar / asum, ag / asum, ab / asum];
|
|
564
|
-
if (!this.pickup) this.pickup = canvas;
|
|
565
|
-
else {
|
|
566
|
-
if (pig) _chunkSZ6KMZNMcjs.setPigmentColor.call(void 0, pig.canvas, canvas[0], canvas[1], canvas[2]);
|
|
567
|
-
const o = this.mix(this.pickup, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _ => _.pick]), () => ( null)), canvas, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _2 => _2.canvas]), () => ( null)), MIXER_PICKUP_RATE * wet * (asum / Math.max(1e-6, wsum)));
|
|
568
|
-
this.pickup = [o[0], o[1], o[2]];
|
|
569
|
-
}
|
|
570
|
-
if (pig) _chunkSZ6KMZNMcjs.setPigmentColor.call(void 0, pig.pick, this.pickup[0], this.pickup[1], this.pickup[2]);
|
|
571
|
-
}
|
|
572
|
-
const res = this.reservoir;
|
|
573
|
-
const wr = res ? this.amount * (1 - mix * wet) : 0;
|
|
574
|
-
const wp = this.pickup ? mix * wet : 0;
|
|
575
|
-
const total = wr + wp;
|
|
576
|
-
if (total > 1e-6) {
|
|
577
|
-
const paint = res && this.pickup ? [...this.mix(res, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _3 => _3.res]), () => ( null)), this.pickup, _nullishCoalesce(_optionalChain([pig, 'optionalAccess', _4 => _4.pick]), () => ( null)), wp / total)] : [..._nullishCoalesce(res, () => ( this.pickup))];
|
|
578
|
-
if (pig) _chunkSZ6KMZNMcjs.setPigmentColor.call(void 0, pig.paint, paint[0], paint[1], paint[2]);
|
|
579
|
-
const dep = Math.min(1, total) * this.brush.flow * this.brush.opacity * d.opacity;
|
|
580
|
-
if (dep > 0) this.deposit(rect, cov, paint, dep);
|
|
581
|
-
}
|
|
582
|
-
this.amount *= 1 - MIXER_DRAIN * (1 - load);
|
|
583
|
-
}
|
|
584
|
-
/** Lays `paint` over the pixels under the dab at `dep` × coverage (× selection). */
|
|
585
|
-
deposit(rect, cov, paint, dep) {
|
|
586
|
-
const t = this.target;
|
|
587
|
-
const sel = t.selection;
|
|
588
|
-
const pig = this.pig;
|
|
589
|
-
const w = rect.width;
|
|
590
|
-
const o = this.out;
|
|
591
|
-
let lastKey = -1;
|
|
592
|
-
for (let yy = 0; yy < rect.height; yy++) {
|
|
593
|
-
const dy = rect.y + yy;
|
|
594
|
-
for (let xx = 0; xx < w; xx++) {
|
|
595
|
-
let k = cov[yy * w + xx] * dep;
|
|
596
|
-
if (k <= 0) continue;
|
|
597
|
-
const dx = rect.x + xx;
|
|
598
|
-
if (sel) {
|
|
599
|
-
if (dx < 0 || dy < 0 || dx >= sel.width || dy >= sel.height) continue;
|
|
600
|
-
k *= sel.data[dy * sel.width + dx] / 255;
|
|
601
|
-
if (k <= 0) continue;
|
|
602
|
-
}
|
|
603
|
-
if (k > 1) k = 1;
|
|
604
|
-
if (t.lockTransparency) {
|
|
605
|
-
const ri = this.locate(dx, dy, false);
|
|
606
|
-
if (ri < 0 || this.tile[ri + 3] === 0) continue;
|
|
607
|
-
}
|
|
608
|
-
const i = this.locate(dx, dy, true);
|
|
609
|
-
const px = this.tile;
|
|
610
|
-
const a = px[i + 3] / 255;
|
|
611
|
-
const na = t.lockTransparency ? a : a + (1 - a) * k;
|
|
612
|
-
const share = t.lockTransparency ? k : na > 0 ? k / na : 1;
|
|
613
|
-
if (a <= 0 || share >= 1) {
|
|
614
|
-
o[0] = paint[0];
|
|
615
|
-
o[1] = paint[1];
|
|
616
|
-
o[2] = paint[2];
|
|
617
|
-
} else if (pig) {
|
|
618
|
-
const key = px[i] << 16 | px[i + 1] << 8 | px[i + 2];
|
|
619
|
-
if (key !== lastKey) {
|
|
620
|
-
_chunkSZ6KMZNMcjs.setPigmentColor.call(void 0, pig.canvas, px[i] / 255, px[i + 1] / 255, px[i + 2] / 255);
|
|
621
|
-
lastKey = key;
|
|
622
|
-
}
|
|
623
|
-
_chunkSZ6KMZNMcjs.lerpPigmentInto.call(void 0, pig.canvas, pig.paint, share, o, 0);
|
|
624
|
-
} else {
|
|
625
|
-
for (let c = 0; c < 3; c++) o[c] = px[i + c] / 255 + (paint[c] - px[i + c] / 255) * share;
|
|
626
|
-
}
|
|
627
|
-
px[i] = Math.round(o[0] * 255);
|
|
628
|
-
px[i + 1] = Math.round(o[1] * 255);
|
|
629
|
-
px[i + 2] = Math.round(o[2] * 255);
|
|
630
|
-
px[i + 3] = Math.round(na * 255);
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
}, _class4);
|
|
635
|
-
function union(a, b) {
|
|
636
|
-
if (!a) return { ...b };
|
|
637
|
-
const x = Math.min(a.x, b.x);
|
|
638
|
-
const y = Math.min(a.y, b.y);
|
|
639
|
-
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 };
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// src/paint/pigment-tools.ts
|
|
643
|
-
var HEX = /^#?([0-9a-f]{6})$/i;
|
|
644
|
-
function parseHex(value, index) {
|
|
645
|
-
const m = typeof value === "string" ? HEX.exec(value.trim()) : null;
|
|
646
|
-
if (!m) throw new Error(`colors[${index}].color is ${JSON.stringify(value)}; use #rrggbb, e.g. "#1e40af".`);
|
|
647
|
-
const n = parseInt(m[1], 16);
|
|
648
|
-
return [(n >> 16 & 255) / 255, (n >> 8 & 255) / 255, (n & 255) / 255];
|
|
649
|
-
}
|
|
650
|
-
function toHex(rgb) {
|
|
651
|
-
return "#" + rgb.map((v) => Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, "0")).join("");
|
|
652
|
-
}
|
|
653
|
-
function createPigmentTools() {
|
|
654
|
-
const mixColors = {
|
|
655
|
-
name: "mix_colors",
|
|
656
|
-
title: "Mix colours like paint",
|
|
657
|
-
description: "Mixes colours as paint would (Kubelka-Munk pigment mixing over reflectance spectra), so blue and yellow make green and white lightens a colour into a tint instead of greying it. Changes nothing. Returns the mixed colour as #rrggbb, the plain RGB average (rgbLerp) for comparison, and the normalised weights.",
|
|
658
|
-
inputSchema: {
|
|
659
|
-
type: "object",
|
|
660
|
-
properties: {
|
|
661
|
-
colors: {
|
|
662
|
-
type: "array",
|
|
663
|
-
minItems: 1,
|
|
664
|
-
maxItems: 16,
|
|
665
|
-
description: "The paints to mix (1 to 16).",
|
|
666
|
-
items: {
|
|
667
|
-
type: "object",
|
|
668
|
-
properties: {
|
|
669
|
-
color: { type: "string", description: "Paint colour #rrggbb." },
|
|
670
|
-
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." },
|
|
671
|
-
strength: {
|
|
672
|
-
type: "number",
|
|
673
|
-
exclusiveMinimum: 0,
|
|
674
|
-
maximum: 100,
|
|
675
|
-
description: "Tinting strength (default 1): each part counts as this many, so a strong dark paint (e.g. 4) tints a lot of white."
|
|
676
|
-
}
|
|
677
|
-
},
|
|
678
|
-
required: ["color", "weight"],
|
|
679
|
-
additionalProperties: false
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
},
|
|
683
|
-
required: ["colors"],
|
|
684
|
-
additionalProperties: false
|
|
685
|
-
},
|
|
686
|
-
annotations: { title: "Mix colours like paint", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
687
|
-
handler: (args) => {
|
|
688
|
-
const items = args.colors;
|
|
689
|
-
const rgbs = items.map((item, i) => parseHex(item.color, i));
|
|
690
|
-
const total = items.reduce((sum, item) => sum + item.weight, 0);
|
|
691
|
-
if (!(total > 0)) throw new Error("Every weight is 0; give at least one colour a weight above 0.");
|
|
692
|
-
const pigments = rgbs.map((rgb, i) => _chunkSZ6KMZNMcjs.createPigment.call(void 0, rgb, { strength: items[i].strength }));
|
|
693
|
-
const mixed = _chunkSZ6KMZNMcjs.mixPigments.call(void 0, pigments, items.map((item) => item.weight));
|
|
694
|
-
const lerp = [0, 1, 2].map((c) => rgbs.reduce((sum, rgb, i) => sum + rgb[c] * items[i].weight, 0) / total);
|
|
695
|
-
return {
|
|
696
|
-
mixed: toHex(mixed),
|
|
697
|
-
rgbLerp: toHex(lerp),
|
|
698
|
-
weights: items.map((item) => item.weight / total),
|
|
699
|
-
model: "kubelka-munk"
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
};
|
|
703
|
-
return [mixColors];
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
exports.DEFAULT_BRUSH = DEFAULT_BRUSH; exports.MAX_BRUSH_SIZE = MAX_BRUSH_SIZE; exports.normalizeBrush = normalizeBrush; exports.tipShape = tipShape; exports.tipFalloff = tipFalloff; exports.tipReach = tipReach; exports.dabCoverage = dabCoverage; exports.smoothPoints = smoothPoints; exports.DabWalker = DabWalker; exports.walkDabs = walkDabs; exports.dabRect = dabRect; exports.rasterizeDab = rasterizeDab; exports.CoverageMap = CoverageMap; exports.StrokeCoverage = StrokeCoverage; exports.applyStrokeToTile = applyStrokeToTile; exports.coverageTileCoord = coverageTileCoord; exports.MIXING_MODELS = MIXING_MODELS; exports.DEFAULT_MIXER = DEFAULT_MIXER; exports.MIXER_PICKUP_RATE = MIXER_PICKUP_RATE; exports.MIXER_DRAIN = MIXER_DRAIN; exports.normalizeMixer = normalizeMixer; exports.EMPTY_MIXER_LOAD = EMPTY_MIXER_LOAD; exports.loadMixer = loadMixer; exports.cleanMixer = cleanMixer; exports.MixerStroke = MixerStroke; exports.createPigmentTools = createPigmentTools;
|
|
734
|
-
//# sourceMappingURL=chunk-HUFQD4CB.cjs.map
|