@pixerate/editor 0.266.1 → 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 +8 -4
- package/dist/agent/index.js +6 -2
- 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-ZQI3WUPP.js → chunk-QCLY5SFS.js} +12 -0
- 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/{chunk-YBC3RKT2.cjs → chunk-ZGXJ7BTR.cjs} +13 -1
- 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/tools/conformance.d.cts +8 -0
- package/dist/tools/conformance.d.ts +8 -0
- package/dist/tools/index.cjs +6 -2
- package/dist/tools/index.js +5 -1
- 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
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
// src/image-editor/layers/vector-raster.ts
|
|
2
|
+
var FLATNESS = 0.01;
|
|
3
|
+
function flattenPath(path, tolerance = FLATNESS) {
|
|
4
|
+
const out = [];
|
|
5
|
+
let pts = [];
|
|
6
|
+
let cx = 0;
|
|
7
|
+
let cy = 0;
|
|
8
|
+
let sx = 0;
|
|
9
|
+
let sy = 0;
|
|
10
|
+
const flush = () => {
|
|
11
|
+
if (pts.length >= 6) out.push(Float64Array.from(pts));
|
|
12
|
+
pts = [];
|
|
13
|
+
};
|
|
14
|
+
const steps = (dd, degree) => Math.max(1, Math.min(1024, Math.ceil(Math.sqrt(degree * (degree - 1) * dd / (8 * tolerance)))));
|
|
15
|
+
for (const c of path) {
|
|
16
|
+
switch (c.type) {
|
|
17
|
+
case "M":
|
|
18
|
+
flush();
|
|
19
|
+
cx = sx = c.x;
|
|
20
|
+
cy = sy = c.y;
|
|
21
|
+
pts.push(cx, cy);
|
|
22
|
+
break;
|
|
23
|
+
case "L":
|
|
24
|
+
if (!pts.length) pts.push(cx, cy);
|
|
25
|
+
cx = c.x;
|
|
26
|
+
cy = c.y;
|
|
27
|
+
pts.push(cx, cy);
|
|
28
|
+
break;
|
|
29
|
+
case "Q": {
|
|
30
|
+
if (!pts.length) pts.push(cx, cy);
|
|
31
|
+
const n = steps(Math.hypot(cx - 2 * c.x1 + c.x, cy - 2 * c.y1 + c.y), 2);
|
|
32
|
+
for (let k = 1; k <= n; k++) {
|
|
33
|
+
const t = k / n;
|
|
34
|
+
const u = 1 - t;
|
|
35
|
+
pts.push(u * u * cx + 2 * u * t * c.x1 + t * t * c.x, u * u * cy + 2 * u * t * c.y1 + t * t * c.y);
|
|
36
|
+
}
|
|
37
|
+
cx = c.x;
|
|
38
|
+
cy = c.y;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case "C": {
|
|
42
|
+
if (!pts.length) pts.push(cx, cy);
|
|
43
|
+
const dd = Math.max(Math.hypot(cx - 2 * c.x1 + c.x2, cy - 2 * c.y1 + c.y2), Math.hypot(c.x1 - 2 * c.x2 + c.x, c.y1 - 2 * c.y2 + c.y));
|
|
44
|
+
const n = steps(dd, 3);
|
|
45
|
+
for (let k = 1; k <= n; k++) {
|
|
46
|
+
const t = k / n;
|
|
47
|
+
const u = 1 - t;
|
|
48
|
+
const a = u * u * u;
|
|
49
|
+
const b = 3 * u * u * t;
|
|
50
|
+
const d = 3 * u * t * t;
|
|
51
|
+
const e = t * t * t;
|
|
52
|
+
pts.push(a * cx + b * c.x1 + d * c.x2 + e * c.x, a * cy + b * c.y1 + d * c.y2 + e * c.y);
|
|
53
|
+
}
|
|
54
|
+
cx = c.x;
|
|
55
|
+
cy = c.y;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case "Z":
|
|
59
|
+
flush();
|
|
60
|
+
cx = sx;
|
|
61
|
+
cy = sy;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
flush();
|
|
66
|
+
return out.filter((p) => p.every(Number.isFinite));
|
|
67
|
+
}
|
|
68
|
+
function flatBounds(flat) {
|
|
69
|
+
let x0 = Infinity;
|
|
70
|
+
let y0 = Infinity;
|
|
71
|
+
let x1 = -Infinity;
|
|
72
|
+
let y1 = -Infinity;
|
|
73
|
+
for (const p of flat) {
|
|
74
|
+
for (let i = 0; i < p.length; i += 2) {
|
|
75
|
+
if (p[i] < x0) x0 = p[i];
|
|
76
|
+
if (p[i] > x1) x1 = p[i];
|
|
77
|
+
if (p[i + 1] < y0) y0 = p[i + 1];
|
|
78
|
+
if (p[i + 1] > y1) y1 = p[i + 1];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (x0 === Infinity) return null;
|
|
82
|
+
const x = Math.floor(x0);
|
|
83
|
+
const y = Math.floor(y0);
|
|
84
|
+
return { x, y, width: Math.ceil(x1) - x, height: Math.ceil(y1) - y };
|
|
85
|
+
}
|
|
86
|
+
function drawLine(a, w, h, x0, y0, x1, y1) {
|
|
87
|
+
if (y0 === y1) return;
|
|
88
|
+
let dir = 1;
|
|
89
|
+
if (y0 > y1) {
|
|
90
|
+
dir = -1;
|
|
91
|
+
let t = x0;
|
|
92
|
+
x0 = x1;
|
|
93
|
+
x1 = t;
|
|
94
|
+
t = y0;
|
|
95
|
+
y0 = y1;
|
|
96
|
+
y1 = t;
|
|
97
|
+
}
|
|
98
|
+
if (y1 <= 0 || y0 >= h) return;
|
|
99
|
+
const dxdy = (x1 - x0) / (y1 - y0);
|
|
100
|
+
let x = x0;
|
|
101
|
+
if (y0 < 0) x -= y0 * dxdy;
|
|
102
|
+
const rowStart = Math.max(0, Math.floor(y0));
|
|
103
|
+
const rowEnd = Math.min(h, Math.ceil(y1));
|
|
104
|
+
for (let y = rowStart; y < rowEnd; y++) {
|
|
105
|
+
const line = y * w;
|
|
106
|
+
const dy = Math.min(y + 1, y1) - Math.max(y, y0);
|
|
107
|
+
const xnext = x + dxdy * dy;
|
|
108
|
+
const d = dy * dir;
|
|
109
|
+
const xa = x < xnext ? x : xnext;
|
|
110
|
+
const xb = x < xnext ? xnext : x;
|
|
111
|
+
const xaFloor = Math.floor(xa);
|
|
112
|
+
const xai = xaFloor;
|
|
113
|
+
const xbCeil = Math.ceil(xb);
|
|
114
|
+
const xbi = xbCeil;
|
|
115
|
+
if (xbi <= xai + 1) {
|
|
116
|
+
const xmf = 0.5 * (x + xnext) - xaFloor;
|
|
117
|
+
a[line + xai] += d - d * xmf;
|
|
118
|
+
a[line + xai + 1] += d * xmf;
|
|
119
|
+
} else {
|
|
120
|
+
const s = 1 / (xb - xa);
|
|
121
|
+
const xaf = xa - xaFloor;
|
|
122
|
+
const a0 = 0.5 * s * (1 - xaf) * (1 - xaf);
|
|
123
|
+
const xbf = xb - xbCeil + 1;
|
|
124
|
+
const am = 0.5 * s * xbf * xbf;
|
|
125
|
+
a[line + xai] += d * a0;
|
|
126
|
+
if (xbi === xai + 2) a[line + xai + 1] += d * (1 - a0 - am);
|
|
127
|
+
else {
|
|
128
|
+
const a1 = s * (1.5 - xaf);
|
|
129
|
+
a[line + xai + 1] += d * (a1 - a0);
|
|
130
|
+
for (let xi = xai + 2; xi < xbi - 1; xi++) a[line + xi] += d * s;
|
|
131
|
+
const a2 = a1 + (xbi - xai - 3) * s;
|
|
132
|
+
a[line + xbi - 1] += d * (1 - a2 - am);
|
|
133
|
+
}
|
|
134
|
+
a[line + xbi] += d * am;
|
|
135
|
+
}
|
|
136
|
+
x = xnext;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function drawClippedLine(a, w, h, x0, y0, x1, y1) {
|
|
140
|
+
if (y0 === y1) return;
|
|
141
|
+
if (y0 <= 0 && y1 <= 0 || y0 >= h && y1 >= h) return;
|
|
142
|
+
if (x0 >= 0 && x0 <= w && x1 >= 0 && x1 <= w) return drawLine(a, w, h, x0, y0, x1, y1);
|
|
143
|
+
const ts = [0, 1];
|
|
144
|
+
const dx = x1 - x0;
|
|
145
|
+
if (dx !== 0) {
|
|
146
|
+
for (const edge of [0, w]) {
|
|
147
|
+
const t = (edge - x0) / dx;
|
|
148
|
+
if (t > 0 && t < 1) ts.push(t);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
ts.sort((p, q) => p - q);
|
|
152
|
+
const clamp = (v) => v < 0 ? 0 : v > w ? w : v;
|
|
153
|
+
for (let i = 0; i + 1 < ts.length; i++) {
|
|
154
|
+
const ta = ts[i];
|
|
155
|
+
const tb = ts[i + 1];
|
|
156
|
+
drawLine(a, w, h, clamp(x0 + dx * ta), y0 + (y1 - y0) * ta, clamp(x0 + dx * tb), y0 + (y1 - y0) * tb);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function ruleCoverage(v, rule) {
|
|
160
|
+
const m = v < 0 ? -v : v;
|
|
161
|
+
if (rule === "nonzero") return m >= 1 ? 1 : m;
|
|
162
|
+
const f = m % 2;
|
|
163
|
+
return f > 1 ? 2 - f : f;
|
|
164
|
+
}
|
|
165
|
+
function rasterizeCoverage(flat, rect, rule = "nonzero") {
|
|
166
|
+
const w = rect.width;
|
|
167
|
+
const h = rect.height;
|
|
168
|
+
if (w <= 0 || h <= 0 || !flat.length) return null;
|
|
169
|
+
const a = new Float64Array(w * h + w + 4);
|
|
170
|
+
const ox = rect.x;
|
|
171
|
+
const oy = rect.y;
|
|
172
|
+
let touched = false;
|
|
173
|
+
for (const p of flat) {
|
|
174
|
+
const n = p.length;
|
|
175
|
+
for (let i = 0; i < n; i += 2) {
|
|
176
|
+
const j = i + 2 < n ? i + 2 : 0;
|
|
177
|
+
const ya = p[i + 1] - oy;
|
|
178
|
+
const yb = p[j + 1] - oy;
|
|
179
|
+
if (ya <= 0 && yb <= 0 || ya >= h && yb >= h || ya === yb) continue;
|
|
180
|
+
drawClippedLine(a, w, h, p[i] - ox, ya, p[j] - ox, yb);
|
|
181
|
+
touched = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (!touched) return null;
|
|
185
|
+
const out = new Float32Array(w * h);
|
|
186
|
+
let acc = 0;
|
|
187
|
+
let any = false;
|
|
188
|
+
for (let i = 0; i < out.length; i++) {
|
|
189
|
+
acc += a[i];
|
|
190
|
+
const c = ruleCoverage(acc, rule);
|
|
191
|
+
if (c > 1e-6) {
|
|
192
|
+
out[i] = c;
|
|
193
|
+
any = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return any ? out : null;
|
|
197
|
+
}
|
|
198
|
+
var SUB_ROWS = 16;
|
|
199
|
+
function rasterizeCoverageSampled(flat, rect, rule = "nonzero") {
|
|
200
|
+
const w = rect.width;
|
|
201
|
+
const h = rect.height;
|
|
202
|
+
if (w <= 0 || h <= 0 || !flat.length) return null;
|
|
203
|
+
let n = 0;
|
|
204
|
+
for (const p of flat) n += p.length >> 1;
|
|
205
|
+
const ey0 = new Float64Array(n);
|
|
206
|
+
const ey1 = new Float64Array(n);
|
|
207
|
+
const ex0 = new Float64Array(n);
|
|
208
|
+
const eslope = new Float64Array(n);
|
|
209
|
+
const edir = new Int8Array(n);
|
|
210
|
+
let count = 0;
|
|
211
|
+
for (const p of flat) {
|
|
212
|
+
const len = p.length;
|
|
213
|
+
for (let i = 0; i < len; i += 2) {
|
|
214
|
+
const j = i + 2 < len ? i + 2 : 0;
|
|
215
|
+
let xa = p[i] - rect.x;
|
|
216
|
+
let ya = p[i + 1] - rect.y;
|
|
217
|
+
let xb = p[j] - rect.x;
|
|
218
|
+
let yb = p[j + 1] - rect.y;
|
|
219
|
+
if (ya === yb) continue;
|
|
220
|
+
let dir = 1;
|
|
221
|
+
if (ya > yb) {
|
|
222
|
+
dir = -1;
|
|
223
|
+
let t = xa;
|
|
224
|
+
xa = xb;
|
|
225
|
+
xb = t;
|
|
226
|
+
t = ya;
|
|
227
|
+
ya = yb;
|
|
228
|
+
yb = t;
|
|
229
|
+
}
|
|
230
|
+
if (yb <= 0 || ya >= h) continue;
|
|
231
|
+
ey0[count] = ya;
|
|
232
|
+
ey1[count] = yb;
|
|
233
|
+
ex0[count] = xa;
|
|
234
|
+
eslope[count] = (xb - xa) / (yb - ya);
|
|
235
|
+
edir[count] = dir;
|
|
236
|
+
count++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (!count) return null;
|
|
240
|
+
const order = Array.from({ length: count }, (_, i) => i).sort((a, b) => ey0[a] - ey0[b]);
|
|
241
|
+
const out = new Float32Array(w * h);
|
|
242
|
+
const diff = new Float32Array(w + 1);
|
|
243
|
+
let active = [];
|
|
244
|
+
let next = 0;
|
|
245
|
+
const xs = [];
|
|
246
|
+
const ds = [];
|
|
247
|
+
const idx = [];
|
|
248
|
+
const f = 1 / SUB_ROWS;
|
|
249
|
+
let any = false;
|
|
250
|
+
const firstRow = Math.max(0, Math.floor(ey0[order[0]]));
|
|
251
|
+
for (let y = firstRow; y < h; y++) {
|
|
252
|
+
if (next >= count && !active.length) break;
|
|
253
|
+
const row = y * w;
|
|
254
|
+
let rowTouched = false;
|
|
255
|
+
for (let s = 0; s < SUB_ROWS; s++) {
|
|
256
|
+
const sy = y + (s + 0.5) * f;
|
|
257
|
+
while (next < count && ey0[order[next]] <= sy) active.push(order[next++]);
|
|
258
|
+
if (!active.length) continue;
|
|
259
|
+
active = active.filter((e) => ey1[e] > sy);
|
|
260
|
+
xs.length = 0;
|
|
261
|
+
ds.length = 0;
|
|
262
|
+
idx.length = 0;
|
|
263
|
+
for (const e of active) {
|
|
264
|
+
if (ey0[e] > sy) continue;
|
|
265
|
+
idx.push(xs.length);
|
|
266
|
+
xs.push(ex0[e] + (sy - ey0[e]) * eslope[e]);
|
|
267
|
+
ds.push(edir[e]);
|
|
268
|
+
}
|
|
269
|
+
if (xs.length < 2) continue;
|
|
270
|
+
idx.sort((a, b) => xs[a] - xs[b]);
|
|
271
|
+
let wind = 0;
|
|
272
|
+
for (let k = 0; k + 1 < idx.length; k++) {
|
|
273
|
+
wind += ds[idx[k]];
|
|
274
|
+
const inside = rule === "nonzero" ? wind !== 0 : (wind & 1) !== 0;
|
|
275
|
+
if (!inside) continue;
|
|
276
|
+
let xa = xs[idx[k]];
|
|
277
|
+
let xb = xs[idx[k + 1]];
|
|
278
|
+
if (xb <= 0 || xa >= w || xb <= xa) continue;
|
|
279
|
+
if (xa < 0) xa = 0;
|
|
280
|
+
if (xb > w) xb = w;
|
|
281
|
+
const ia = Math.floor(xa);
|
|
282
|
+
const ib = Math.floor(xb);
|
|
283
|
+
rowTouched = true;
|
|
284
|
+
if (ia === ib) {
|
|
285
|
+
out[row + ia] += (xb - xa) * f;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
out[row + ia] += (ia + 1 - xa) * f;
|
|
289
|
+
diff[ia + 1] += f;
|
|
290
|
+
diff[ib] -= f;
|
|
291
|
+
if (ib < w) out[row + ib] += (xb - ib) * f;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (!rowTouched) continue;
|
|
295
|
+
let run = 0;
|
|
296
|
+
for (let x = 0; x < w; x++) {
|
|
297
|
+
run += diff[x];
|
|
298
|
+
diff[x] = 0;
|
|
299
|
+
const v = out[row + x] + run;
|
|
300
|
+
out[row + x] = v > 1 ? 1 : v < 1e-6 ? 0 : v;
|
|
301
|
+
if (out[row + x] > 0) any = true;
|
|
302
|
+
}
|
|
303
|
+
diff[w] = 0;
|
|
304
|
+
}
|
|
305
|
+
return any ? out : null;
|
|
306
|
+
}
|
|
307
|
+
function combineCoverage(a, b, op, n) {
|
|
308
|
+
if (op === "combine") {
|
|
309
|
+
if (!a) return b;
|
|
310
|
+
if (!b) return a;
|
|
311
|
+
const out2 = new Float32Array(n);
|
|
312
|
+
for (let i = 0; i < n; i++) out2[i] = a[i] + b[i] - a[i] * b[i];
|
|
313
|
+
return out2;
|
|
314
|
+
}
|
|
315
|
+
if (op === "subtract") {
|
|
316
|
+
if (!a || !b) return a;
|
|
317
|
+
const out2 = new Float32Array(n);
|
|
318
|
+
for (let i = 0; i < n; i++) out2[i] = a[i] * (1 - b[i]);
|
|
319
|
+
return out2;
|
|
320
|
+
}
|
|
321
|
+
if (op === "intersect") {
|
|
322
|
+
if (!a || !b) return null;
|
|
323
|
+
const out2 = new Float32Array(n);
|
|
324
|
+
for (let i = 0; i < n; i++) out2[i] = a[i] * b[i];
|
|
325
|
+
return out2;
|
|
326
|
+
}
|
|
327
|
+
if (!a) return b;
|
|
328
|
+
if (!b) return a;
|
|
329
|
+
const out = new Float32Array(n);
|
|
330
|
+
for (let i = 0; i < n; i++) out[i] = a[i] + b[i] - 2 * a[i] * b[i];
|
|
331
|
+
return out;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export {
|
|
335
|
+
flattenPath,
|
|
336
|
+
flatBounds,
|
|
337
|
+
rasterizeCoverage,
|
|
338
|
+
rasterizeCoverageSampled,
|
|
339
|
+
combineCoverage
|
|
340
|
+
};
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
STAMP_KINDS,
|
|
3
3
|
editorStampOf,
|
|
4
4
|
normalizeStickerRef
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JL6YH5WD.js";
|
|
6
6
|
import {
|
|
7
7
|
validateJsonSchema
|
|
8
8
|
} from "./chunk-V2ZCJRDM.js";
|
|
@@ -1886,7 +1886,7 @@ var CANVAS_PROFILE = {
|
|
|
1886
1886
|
velocity: "ignored",
|
|
1887
1887
|
tilt: "full"
|
|
1888
1888
|
};
|
|
1889
|
-
var VECTOR_PROFILE = { ...CANVAS_PROFILE, id: "vector", name: "Vector editor", light: "ignored" };
|
|
1889
|
+
var VECTOR_PROFILE = { ...CANVAS_PROFILE, id: "vector", name: "Vector editor", kinds: ["mark", "tool"], tools: ["blender", "smudge"], surfaces: ["dry", "wet"], reservoir: "full", light: "ignored" };
|
|
1890
1890
|
var BRUSH_HOST_PROFILES = { paint: PAINT_PROFILE, image: IMAGE_PROFILE, canvas: CANVAS_PROFILE, vector: VECTOR_PROFILE };
|
|
1891
1891
|
function brushColourKind(paint) {
|
|
1892
1892
|
if (typeof paint === "string") return "solid";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkPFHJS4HEcjs = require('./chunk-PFHJS4HE.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -16,12 +16,12 @@ var _chunkPE6YJMQTcjs = require('./chunk-PE6YJMQT.cjs');
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
var
|
|
19
|
+
var _chunkXVOP3CGQcjs = require('./chunk-XVOP3CGQ.cjs');
|
|
20
20
|
|
|
21
21
|
// src/brushes/patch.ts
|
|
22
22
|
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
23
23
|
var copy = (v) => JSON.parse(JSON.stringify(v));
|
|
24
|
-
var FACETS =
|
|
24
|
+
var FACETS = _chunkXVOP3CGQcjs.BRUSH_JSON_SCHEMA.properties;
|
|
25
25
|
var BRUSH_PATCH_PROPERTIES = (() => {
|
|
26
26
|
const { id: _id, name: _name, ...rest } = FACETS;
|
|
27
27
|
const { required: _r, ...tip } = rest.tip;
|
|
@@ -53,17 +53,17 @@ function changedBrushPaths(a, b, path = "") {
|
|
|
53
53
|
// src/brushes/tools.ts
|
|
54
54
|
var READ = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
55
55
|
var WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
56
|
-
var FACETS2 =
|
|
56
|
+
var FACETS2 = _chunkXVOP3CGQcjs.BRUSH_JSON_SCHEMA.properties;
|
|
57
57
|
var ID = { type: "string", pattern: String(FACETS2.id.pattern), description: "Brush id from list_brush_presets (lowercase letters, digits and dashes)." };
|
|
58
58
|
var FACET_PROPS = BRUSH_PATCH_PROPERTIES;
|
|
59
|
-
var HOSTS = Object.keys(
|
|
59
|
+
var HOSTS = Object.keys(_chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES);
|
|
60
60
|
var copy2 = (v) => JSON.parse(JSON.stringify(v));
|
|
61
61
|
var merge = mergeBrushPatch;
|
|
62
62
|
var changedPaths = changedBrushPaths;
|
|
63
63
|
function summary(entry, profile, withCheck) {
|
|
64
64
|
const b = entry.brush;
|
|
65
|
-
const engine =
|
|
66
|
-
const check = withCheck ?
|
|
65
|
+
const engine = _chunkXVOP3CGQcjs.resolveEngine.call(void 0, b);
|
|
66
|
+
const check = withCheck ? _chunkXVOP3CGQcjs.checkBrush.call(void 0, b, profile) : null;
|
|
67
67
|
return {
|
|
68
68
|
id: b.id,
|
|
69
69
|
name: b.name,
|
|
@@ -72,7 +72,7 @@ function summary(entry, profile, withCheck) {
|
|
|
72
72
|
...b.medium ? { medium: b.medium } : {},
|
|
73
73
|
...b.variety ? { variety: b.variety } : {},
|
|
74
74
|
...b.tool ? { tool: b.tool } : {},
|
|
75
|
-
category:
|
|
75
|
+
category: _chunkXVOP3CGQcjs.resolveCategory.call(void 0, b, engine),
|
|
76
76
|
engine,
|
|
77
77
|
tip: b.tip.shape,
|
|
78
78
|
...b.tip.size !== void 0 ? { size: b.tip.size } : {},
|
|
@@ -86,28 +86,28 @@ function summary(entry, profile, withCheck) {
|
|
|
86
86
|
var refusal = (check, host) => `${host.name} can't use this brush: ${check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`).join(" ")} (check_brush lists every issue; nothing was saved.)`;
|
|
87
87
|
var warnings = (check) => check.issues.filter((i) => i.severity === "warning");
|
|
88
88
|
function createBrushLibraryTools(library, options = {}) {
|
|
89
|
-
const profile = _nullishCoalesce(options.profile, () => (
|
|
89
|
+
const profile = _nullishCoalesce(options.profile, () => ( _chunkXVOP3CGQcjs.PAINT_PROFILE));
|
|
90
90
|
const hostOf = (id) => {
|
|
91
91
|
if (id === void 0) return profile;
|
|
92
|
-
const p =
|
|
93
|
-
if (!p) throw new (0,
|
|
92
|
+
const p = _chunkXVOP3CGQcjs.BRUSH_HOST_PROFILES[id];
|
|
93
|
+
if (!p) throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("invalid", `No host "${id}"; use one of: ${HOSTS.join(", ")}.`);
|
|
94
94
|
return p;
|
|
95
95
|
};
|
|
96
96
|
const entry = async (id) => {
|
|
97
97
|
const found = await library.get(id);
|
|
98
98
|
if (found) return found;
|
|
99
99
|
const ids = (await library.list()).map((e) => e.brush.id);
|
|
100
|
-
throw new (0,
|
|
100
|
+
throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("unknown_brush", `No brush "${id}". ${_chunkXVOP3CGQcjs.closest.call(void 0, id, ids)}list_brush_presets lists them.`);
|
|
101
101
|
};
|
|
102
102
|
const checkFor = async (brush, p) => {
|
|
103
|
-
const check2 =
|
|
103
|
+
const check2 = _chunkXVOP3CGQcjs.checkBrush.call(void 0, brush, p);
|
|
104
104
|
const provider = _optionalChain([options, 'access', _9 => _9.stickers, 'optionalCall', _10 => _10()]);
|
|
105
105
|
if (!provider || brush.tip.shape !== "stamp") return check2;
|
|
106
106
|
const issues = [...check2.issues];
|
|
107
107
|
for (const ref of _nullishCoalesce(brush.tip.stamps, () => ( []))) {
|
|
108
108
|
if (ref.startsWith("editor:")) continue;
|
|
109
109
|
try {
|
|
110
|
-
await
|
|
110
|
+
await _chunkPFHJS4HEcjs.describeStickerRef.call(void 0, provider, ref);
|
|
111
111
|
} catch (e) {
|
|
112
112
|
issues.push({ facet: "tip.stamps", severity: "error", reason: `${p.name} can't load sticker "${ref}": ${e.message}`, fix: "Use a ref from find_stickers, or an editor stamp (editor:star, editor:dot\u2026)." });
|
|
113
113
|
}
|
|
@@ -118,12 +118,12 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
118
118
|
const problems = [];
|
|
119
119
|
let brush;
|
|
120
120
|
try {
|
|
121
|
-
brush =
|
|
121
|
+
brush = _chunkXVOP3CGQcjs.normalizeBrushSpec.call(void 0, raw, problems);
|
|
122
122
|
} catch (e) {
|
|
123
|
-
throw new (0,
|
|
123
|
+
throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("invalid", e.message);
|
|
124
124
|
}
|
|
125
|
-
const check2 =
|
|
126
|
-
if (!check2.ok) throw new (0,
|
|
125
|
+
const check2 = _chunkXVOP3CGQcjs.withKeptIssues.call(void 0, await checkFor(brush, profile), original ? await checkFor(original, profile) : null);
|
|
126
|
+
if (!check2.ok) throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("invalid", refusal(check2, profile));
|
|
127
127
|
const saved = await library.save(brush, { overwrite });
|
|
128
128
|
return { ...saved, problems, check: check2 };
|
|
129
129
|
};
|
|
@@ -134,10 +134,10 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
134
134
|
inputSchema: {
|
|
135
135
|
type: "object",
|
|
136
136
|
properties: {
|
|
137
|
-
kind: { type: "string", enum: [...
|
|
138
|
-
medium: { type: "string", enum: [...
|
|
137
|
+
kind: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_KINDS], description: "mark (lays a material) or tool (works on paint already down)." },
|
|
138
|
+
medium: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_MEDIA], description: "Marks laying this medium." },
|
|
139
139
|
variety: { type: "string", maxLength: 40, description: "This variety (oil, watercolor, pencil, highlighter\u2026)." },
|
|
140
|
-
tool: { type: "string", enum: [...
|
|
140
|
+
tool: { type: "string", enum: [..._chunkXVOP3CGQcjs.BRUSH_TOOLS], description: "Tools that do this." },
|
|
141
141
|
tag: { type: "string", maxLength: 40, description: "Brushes with this tag." },
|
|
142
142
|
text: { type: "string", maxLength: 200, description: "Words in the id, name, description, variety or tags (each word must match the start of one)." },
|
|
143
143
|
source: { type: "string", enum: ["all", "builtin", "user"], description: "all (default), builtin presets only, or user (saved) brushes only." },
|
|
@@ -164,8 +164,8 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
164
164
|
annotations: { title: "Describe a brush", ...READ },
|
|
165
165
|
handler: async ({ id }) => {
|
|
166
166
|
const e = await entry(id);
|
|
167
|
-
const engine =
|
|
168
|
-
return { brush: e.brush, builtin: e.builtin, engine, category:
|
|
167
|
+
const engine = _chunkXVOP3CGQcjs.resolveEngine.call(void 0, e.brush);
|
|
168
|
+
return { brush: e.brush, builtin: e.builtin, engine, category: _chunkXVOP3CGQcjs.resolveCategory.call(void 0, e.brush, engine), check: await checkFor(e.brush, profile) };
|
|
169
169
|
}
|
|
170
170
|
};
|
|
171
171
|
const check = {
|
|
@@ -183,20 +183,20 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
183
183
|
},
|
|
184
184
|
annotations: { title: "Check a brush for a host", ...READ },
|
|
185
185
|
handler: async ({ id, brush, host }) => {
|
|
186
|
-
if (id === void 0 === (brush === void 0)) throw new (0,
|
|
186
|
+
if (id === void 0 === (brush === void 0)) throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("invalid", "Give either id (a library brush) or brush (a spec), not both or neither.");
|
|
187
187
|
const p = hostOf(host);
|
|
188
188
|
let b;
|
|
189
189
|
const problems = [];
|
|
190
190
|
if (id !== void 0) b = (await entry(id)).brush;
|
|
191
191
|
else {
|
|
192
192
|
try {
|
|
193
|
-
b =
|
|
193
|
+
b = _chunkXVOP3CGQcjs.normalizeBrushSpec.call(void 0, brush, problems);
|
|
194
194
|
} catch (e) {
|
|
195
|
-
throw new (0,
|
|
195
|
+
throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("invalid", e.message);
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
const result = await checkFor(b, p);
|
|
199
|
-
return { host: p.id, ...result, ...problems.length ? { problems } : {}, ...!result.ok ? { degraded:
|
|
199
|
+
return { host: p.id, ...result, ...problems.length ? { problems } : {}, ...!result.ok ? { degraded: _chunkXVOP3CGQcjs.degrade.call(void 0, b, p) } : {} };
|
|
200
200
|
}
|
|
201
201
|
};
|
|
202
202
|
const exportTool = {
|
|
@@ -255,12 +255,12 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
255
255
|
},
|
|
256
256
|
annotations: { title: "Save a new brush", ...WRITE },
|
|
257
257
|
handler: async ({ basedOn, ...spec }) => {
|
|
258
|
-
if (library.isBuiltin(spec.id)) throw new (0,
|
|
259
|
-
if (await library.get(spec.id)) throw new (0,
|
|
258
|
+
if (library.isBuiltin(spec.id)) throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("builtin", `"${spec.id}" is a built-in brush id; pick another id (or basedOn "${spec.id}" with a new id).`);
|
|
259
|
+
if (await library.get(spec.id)) throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("exists", `A brush "${spec.id}" exists already; pick another id, or change it with update_brush.`);
|
|
260
260
|
const base = basedOn !== void 0 ? (await entry(basedOn)).brush : void 0;
|
|
261
261
|
const raw = base ? merge(base, spec) : spec;
|
|
262
262
|
const saved = await store(raw, false);
|
|
263
|
-
return { id: saved.brush.id, brush: saved.brush, engine:
|
|
263
|
+
return { id: saved.brush.id, brush: saved.brush, engine: _chunkXVOP3CGQcjs.resolveEngine.call(void 0, saved.brush), problems: saved.problems, warnings: warnings(saved.check) };
|
|
264
264
|
}
|
|
265
265
|
},
|
|
266
266
|
{
|
|
@@ -281,7 +281,7 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
281
281
|
annotations: { title: "Update a brush", ...WRITE, idempotentHint: true },
|
|
282
282
|
handler: async ({ id, unset, ...patch }) => {
|
|
283
283
|
const e = await entry(id);
|
|
284
|
-
if (e.builtin) throw new (0,
|
|
284
|
+
if (e.builtin) throw new (0, _chunkXVOP3CGQcjs.BrushLibraryError)("builtin", `"${id}" is a built-in brush and can't be changed; duplicate_brush makes a copy you can change.`);
|
|
285
285
|
const base = copy2(e.brush);
|
|
286
286
|
for (const k of _nullishCoalesce(unset, () => ( []))) delete base[k];
|
|
287
287
|
const saved = await store(merge(base, { ...patch, id }), true, e.brush);
|
|
@@ -340,7 +340,7 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
340
340
|
return tools;
|
|
341
341
|
}
|
|
342
342
|
function createBrushLibraryToolProvider(library, options = {}) {
|
|
343
|
-
const profile = _nullishCoalesce(options.profile, () => (
|
|
343
|
+
const profile = _nullishCoalesce(options.profile, () => ( _chunkXVOP3CGQcjs.PAINT_PROFILE));
|
|
344
344
|
const tools = createBrushLibraryTools(library, options);
|
|
345
345
|
return {
|
|
346
346
|
id: _nullishCoalesce(options.id, () => ( "brushes")),
|
|
@@ -74,7 +74,7 @@ function profileAlongPolyline(points, values, count = 32) {
|
|
|
74
74
|
var round3 = (v) => Math.round(v * 1e3) / 1e3;
|
|
75
75
|
var loading = null;
|
|
76
76
|
function loadCanvasBrushstrokeRenderer() {
|
|
77
|
-
loading ??= import("./brushstrokeRender-
|
|
77
|
+
loading ??= import("./brushstrokeRender-NLFPEBGI.js").catch((error) => {
|
|
78
78
|
loading = null;
|
|
79
79
|
throw error;
|
|
80
80
|
});
|